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>2022-10-20 12:40:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-10-20 12:40:42 +0300
commitee664acb356f8123f4f6b00b73c1e1cf0866c7fb (patch)
treef8479f94a28f66654c6a4f6fb99bad6b4e86a40e
parent62f7d5c5b69180e82ae8196b7b429eeffc8e7b4f (diff)
Add latest changes from gitlab-org/gitlab@15-5-stable-eev15.5.0-rc42
-rw-r--r--.gitattributes1
-rw-r--r--.gitlab-ci.yml23
-rw-r--r--.gitlab/CODEOWNERS284
-rw-r--r--.gitlab/ci/_skip.yml2
-rw-r--r--.gitlab/ci/build-images.gitlab-ci.yml22
-rw-r--r--.gitlab/ci/caching.gitlab-ci.yml65
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml65
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml41
-rw-r--r--.gitlab/ci/notify.gitlab-ci.yml29
-rw-r--r--.gitlab/ci/package-and-test/main.gitlab-ci.yml105
-rw-r--r--.gitlab/ci/package-and-test/rules.gitlab-ci.yml32
-rw-r--r--.gitlab/ci/package-and-test/variables.gitlab-ci.yml3
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml229
-rw-r--r--.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb50
-rw-r--r--.gitlab/ci/rails/shared.gitlab-ci.yml172
-rw-r--r--.gitlab/ci/releases.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review-apps/dast-api.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml18
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml27
-rw-r--r--.gitlab/ci/review-apps/rules.gitlab-ci.yml41
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml18
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml148
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml13
-rw-r--r--.gitlab/ci/static-analysis.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/vendored-gems.gitlab-ci.yml16
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml6
-rw-r--r--.gitlab/issue_templates/Actionable Insight - Exploration needed.md2
-rw-r--r--.gitlab/issue_templates/Actionable Insight - Product change.md2
-rw-r--r--.gitlab/issue_templates/Bug.md5
-rw-r--r--.gitlab/issue_templates/Deprecations.md5
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md10
-rw-r--r--.gitlab/issue_templates/Feature proposal - detailed.md2
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md62
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md71
-rw-r--r--.gitlab/issue_templates/QA Failure.md3
-rw-r--r--.gitlab/issue_templates/Solution Validation.md2
-rw-r--r--.gitlab/issue_templates/UX Theme.md6
-rw-r--r--.gitlab/merge_request_templates/Deprecations.md2
-rw-r--r--.gitlab/merge_request_templates/Documentation.md6
-rw-r--r--.gitlab/merge_request_templates/Removals.md2
-rw-r--r--.gitpod.yml16
-rw-r--r--.haml-lint.yml1
-rw-r--r--.haml-lint_todo.yml14
-rw-r--r--.projections.json.example95
-rw-r--r--.rubocop.yml66
-rw-r--r--.rubocop_todo/capybara/visibility_matcher.yml79
-rw-r--r--.rubocop_todo/cop/static_translation_definition.yml14
-rw-r--r--.rubocop_todo/gitlab/no_code_coverage_comment.yml19
-rw-r--r--.rubocop_todo/gitlab/service_response.yml84
-rw-r--r--.rubocop_todo/layout/argument_alignment.yml1
-rw-r--r--.rubocop_todo/layout/closing_parenthesis_indentation.yml6
-rw-r--r--.rubocop_todo/layout/empty_line_between_defs.yml8
-rw-r--r--.rubocop_todo/layout/first_array_element_indentation.yml191
-rw-r--r--.rubocop_todo/layout/first_hash_element_indentation.yml3
-rw-r--r--.rubocop_todo/layout/leading_comment_space.yml6
-rw-r--r--.rubocop_todo/layout/line_length.yml363
-rw-r--r--.rubocop_todo/layout/space_around_operators.yml5
-rw-r--r--.rubocop_todo/layout/space_before_block_braces.yml5
-rw-r--r--.rubocop_todo/layout/space_inside_block_braces.yml5
-rw-r--r--.rubocop_todo/layout/space_inside_parens.yml1
-rw-r--r--.rubocop_todo/layout/trailing_whitespace.yml16
-rw-r--r--.rubocop_todo/lint/binary_operator_with_identical_operands.yml15
-rw-r--r--.rubocop_todo/lint/duplicate_case_condition.yml4
-rw-r--r--.rubocop_todo/lint/redundant_cop_disable_directive.yml115
-rw-r--r--.rubocop_todo/metrics/abc_size.yml1
-rw-r--r--.rubocop_todo/metrics/parameter_lists.yml9
-rw-r--r--.rubocop_todo/performance/bind_call.yml10
-rw-r--r--.rubocop_todo/performance/redundant_block_call.yml12
-rw-r--r--.rubocop_todo/rails/active_record_callbacks_order.yml5
-rw-r--r--.rubocop_todo/rails/file_path.yml17
-rw-r--r--.rubocop_todo/rails/helper_instance_variable.yml11
-rw-r--r--.rubocop_todo/rails/http_status.yml9
-rw-r--r--.rubocop_todo/rails/index_with.yml11
-rw-r--r--.rubocop_todo/rails/inverse_of.yml17
-rw-r--r--.rubocop_todo/rails/redundant_foreign_key.yml12
-rw-r--r--.rubocop_todo/rails/skips_model_validations.yml1
-rw-r--r--.rubocop_todo/rails/time_zone.yml1
-rw-r--r--.rubocop_todo/rspec/any_instance_of.yml1
-rw-r--r--.rubocop_todo/rspec/capybara/visibility_matcher.yml79
-rw-r--r--.rubocop_todo/rspec/context_wording.yml3
-rw-r--r--.rubocop_todo/rspec/described_class.yml1
-rw-r--r--.rubocop_todo/rspec/expect_change.yml265
-rw-r--r--.rubocop_todo/rspec/expect_in_hook.yml2
-rw-r--r--.rubocop_todo/rspec/factory_bot/avoid_create.yml211
-rw-r--r--.rubocop_todo/rspec/file_path.yml67
-rw-r--r--.rubocop_todo/rspec/instance_variable.yml1
-rw-r--r--.rubocop_todo/rspec/let_before_examples.yml17
-rw-r--r--.rubocop_todo/rspec/multiple_memoized_helpers.yml42
-rw-r--r--.rubocop_todo/rspec/overwriting_setup.yml17
-rw-r--r--.rubocop_todo/rspec/predicate_matcher.yml4
-rw-r--r--.rubocop_todo/rspec/scattered_let.yml218
-rw-r--r--.rubocop_todo/rspec/variable_definition.yml6
-rw-r--r--.rubocop_todo/rspec/variable_name.yml4
-rw-r--r--.rubocop_todo/rspec/verified_doubles.yml1
-rw-r--r--.rubocop_todo/style/accessor_grouping.yml7
-rw-r--r--.rubocop_todo/style/case_like_if.yml12
-rw-r--r--.rubocop_todo/style/class_and_module_children.yml1
-rw-r--r--.rubocop_todo/style/conditional_assignment.yml5
-rw-r--r--.rubocop_todo/style/each_for_simple_loop.yml6
-rw-r--r--.rubocop_todo/style/empty_method.yml30
-rw-r--r--.rubocop_todo/style/explicit_block_argument.yml17
-rw-r--r--.rubocop_todo/style/format_string.yml2
-rw-r--r--.rubocop_todo/style/guard_clause.yml1
-rw-r--r--.rubocop_todo/style/if_unless_modifier.yml42
-rw-r--r--.rubocop_todo/style/keyword_parameters_order.yml15
-rw-r--r--.rubocop_todo/style/numeric_literal_prefix.yml20
-rw-r--r--.rubocop_todo/style/percent_literal_delimiters.yml3
-rw-r--r--.rubocop_todo/style/redundant_begin.yml57
-rw-r--r--.rubocop_todo/style/redundant_condition.yml6
-rw-r--r--.rubocop_todo/style/redundant_parentheses.yml6
-rw-r--r--.rubocop_todo/style/single_argument_dig.yml12
-rw-r--r--.rubocop_todo/style/sole_nested_conditional.yml13
-rw-r--r--.rubocop_todo/style/special_global_vars.yml4
-rw-r--r--.rubocop_todo/style/string_concatenation.yml2
-rw-r--r--.rubocop_todo/style/string_literals_in_interpolation.yml15
-rw-r--r--.rubocop_todo/style/symbol_proc.yml12
-rw-r--r--CHANGELOG.md50
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile84
-rw-r--r--Gemfile.checksum137
-rw-r--r--Gemfile.lock277
-rw-r--r--PROCESS.md222
-rw-r--r--app/assets/javascripts/access_tokens/components/access_token_table_app.vue26
-rw-r--r--app/assets/javascripts/access_tokens/components/new_access_token_app.vue14
-rw-r--r--app/assets/javascripts/access_tokens/components/tokens_app.vue2
-rw-r--r--app/assets/javascripts/access_tokens/index.js11
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue4
-rw-r--r--app/assets/javascripts/add_context_commits_modal/store/actions.js6
-rw-r--r--app/assets/javascripts/admin/background_migrations/components/database_listbox.vue2
-rw-r--r--app/assets/javascripts/admin/broadcast_messages/components/base.vue112
-rw-r--r--app/assets/javascripts/admin/broadcast_messages/components/messages_table.vue113
-rw-r--r--app/assets/javascripts/admin/broadcast_messages/index.js21
-rw-r--r--app/assets/javascripts/admin/deploy_keys/components/table.vue4
-rw-r--r--app/assets/javascripts/admin/statistics_panel/store/actions.js4
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue4
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue7
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue42
-rw-r--r--app/assets/javascripts/alerts_settings/utils/cache_updates.js4
-rw-r--r--app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue4
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue4
-rw-r--r--app/assets/javascripts/api/projects_api.js8
-rw-r--r--app/assets/javascripts/api/user_api.js4
-rw-r--r--app/assets/javascripts/awards_handler.js4
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue14
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue8
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js12
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js19
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js4
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/keybindings.js14
-rw-r--r--app/assets/javascripts/blame/blame_redirect.js23
-rw-r--r--app/assets/javascripts/blob/3d_viewer/index.js2
-rw-r--r--app/assets/javascripts/blob/3d_viewer/mesh_object.js2
-rw-r--r--app/assets/javascripts/blob/blob_line_permalink_updater.js1
-rw-r--r--app/assets/javascripts/blob/components/table_contents.vue14
-rw-r--r--app/assets/javascripts/blob/file_template_mediator.js4
-rw-r--r--app/assets/javascripts/blob/openapi/index.js4
-rw-r--r--app/assets/javascripts/blob/viewer/index.js6
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js4
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js6
-rw-r--r--app/assets/javascripts/boards/components/board_blocked_icon.vue207
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue10
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue14
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue7
-rw-r--r--app/assets/javascripts/boards/constants.js11
-rw-r--r--app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql17
-rw-r--r--app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql14
-rw-r--r--app/assets/javascripts/boards/index.js1
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js4
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue29
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue58
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue55
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue62
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue3
-rw-r--r--app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_settings.vue4
-rw-r--r--app/assets/javascripts/ci_variable_list/constants.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql8
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql8
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql8
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/resolvers.js165
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/settings.js256
-rw-r--r--app/assets/javascripts/ci_variable_list/index.js8
-rw-r--r--app/assets/javascripts/ci_variable_list/store/actions.js12
-rw-r--r--app/assets/javascripts/ci_variable_list/utils.js10
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_events_list.vue6
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_history_item.vue10
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js4
-rw-r--r--app/assets/javascripts/clusters_list/store/actions.js4
-rw-r--r--app/assets/javascripts/code_navigation/utils/dom_utils.js14
-rw-r--r--app/assets/javascripts/code_navigation/utils/index.js8
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue11
-rw-r--r--app/assets/javascripts/commit_merge_requests.js4
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/project_form_group.vue4
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue20
-rw-r--r--app/assets/javascripts/content_editor/components/editor_state_observer.vue4
-rw-r--r--app/assets/javascripts/content_editor/components/suggestions_dropdown.vue264
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/label.vue34
-rw-r--r--app/assets/javascripts/content_editor/constants/index.js6
-rw-r--r--app/assets/javascripts/content_editor/extensions/diagram.js5
-rw-r--r--app/assets/javascripts/content_editor/extensions/external_keydown_handler.js38
-rw-r--r--app/assets/javascripts/content_editor/extensions/heading.js16
-rw-r--r--app/assets/javascripts/content_editor/extensions/reference.js14
-rw-r--r--app/assets/javascripts/content_editor/extensions/reference_label.js35
-rw-r--r--app/assets/javascripts/content_editor/extensions/suggestions.js227
-rw-r--r--app/assets/javascripts/content_editor/services/create_content_editor.js6
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js7
-rw-r--r--app/assets/javascripts/content_editor/services/serialization_helpers.js5
-rw-r--r--app/assets/javascripts/contributors/components/contributors.vue2
-rw-r--r--app/assets/javascripts/contributors/stores/actions.js4
-rw-r--r--app/assets/javascripts/crm/contacts/components/contacts_root.vue11
-rw-r--r--app/assets/javascripts/crm/organizations/components/organizations_root.vue9
-rw-r--r--app/assets/javascripts/cycle_analytics/store/actions.js6
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue2
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js8
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutations.js4
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue8
-rw-r--r--app/assets/javascripts/deploy_tokens/components/new_deploy_token.vue332
-rw-r--r--app/assets/javascripts/deploy_tokens/index.js33
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue71
-rw-r--r--app/assets/javascripts/design_management/mixins/all_designs.js8
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue4
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue10
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js6
-rw-r--r--app/assets/javascripts/diff.js4
-rw-r--r--app/assets/javascripts/diffs/components/app.vue10
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue4
-rw-r--r--app/assets/javascripts/diffs/components/commit_widget.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue7
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_row_utils.js6
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue18
-rw-r--r--app/assets/javascripts/diffs/mixins/draft_comments.js2
-rw-r--r--app/assets/javascripts/diffs/store/actions.js11
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js4
-rw-r--r--app/assets/javascripts/editor/schema/ci.json624
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue6
-rw-r--r--app/assets/javascripts/environments/components/deployment.vue4
-rw-r--r--app/assets/javascripts/environments/components/edit_environment.vue4
-rw-r--r--app/assets/javascripts/environments/components/empty_state.vue45
-rw-r--r--app/assets/javascripts/environments/components/enable_review_app_modal.vue160
-rw-r--r--app/assets/javascripts/environments/components/environment_external_url.vue16
-rw-r--r--app/assets/javascripts/environments/components/environment_folder.vue10
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue60
-rw-r--r--app/assets/javascripts/environments/components/environments_detail_header.vue37
-rw-r--r--app/assets/javascripts/environments/components/new_environment.vue4
-rw-r--r--app/assets/javascripts/environments/constants.js31
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql4
-rw-r--r--app/assets/javascripts/environments/graphql/queries/folder.query.graphql4
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers.js8
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js8
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue8
-rw-r--r--app/assets/javascripts/error_tracking/store/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking/store/list/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/app.vue2
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/actions.js4
-rw-r--r--app/assets/javascripts/feature_flags/components/environments_dropdown.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue4
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/actions.js4
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_helper.js4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js4
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js4
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js6
-rw-r--r--app/assets/javascripts/flash.js2
-rw-r--r--app/assets/javascripts/gpg_badges.js4
-rw-r--r--app/assets/javascripts/grafana_integration/store/actions.js4
-rw-r--r--app/assets/javascripts/graphql_shared/issuable_client.js52
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json2
-rw-r--r--app/assets/javascripts/graphql_shared/queries/users_search.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/users_search_with_mr_permissions.graphql6
-rw-r--r--app/assets/javascripts/group.js6
-rw-r--r--app/assets/javascripts/groups/components/app.vue28
-rw-r--r--app/assets/javascripts/groups/components/groups.vue20
-rw-r--r--app/assets/javascripts/groups/components/new_top_level_group_alert.vue40
-rw-r--r--app/assets/javascripts/groups/components/overview_tabs.vue177
-rw-r--r--app/assets/javascripts/groups/components/transfer_group_form.vue2
-rw-r--r--app/assets/javascripts/groups/constants.js25
-rw-r--r--app/assets/javascripts/groups/init_overview_tabs.js2
-rw-r--r--app/assets/javascripts/groups/settings/components/access_dropdown.vue4
-rw-r--r--app/assets/javascripts/groups_select.js12
-rw-r--r--app/assets/javascripts/header_search/components/app.vue19
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/description.vue7
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue23
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue6
-rw-r--r--app/assets/javascripts/ide/index.js4
-rw-r--r--app/assets/javascripts/ide/init_gitlab_web_ide.js3
-rw-r--r--app/assets/javascripts/ide/stores/actions.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js4
-rw-r--r--app/assets/javascripts/ide/utils.js22
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue28
-rw-r--r--app/assets/javascripts/import_entities/import_groups/services/status_poller.js4
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/advanced_settings.vue51
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue30
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue6
-rw-r--r--app/assets/javascripts/import_entities/import_projects/index.js1
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/actions.js29
-rw-r--r--app/assets/javascripts/integrations/constants.js2
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue87
-rw-r--r--app/assets/javascripts/issuable/auto_width_dropdown_select.js56
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue57
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/components/status_select.vue58
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue51
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/constants.js22
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/index.js25
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js2
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js28
-rw-r--r--app/assets/javascripts/issuable/issuable_context.js19
-rw-r--r--app/assets/javascripts/issuable/issuable_form.js52
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue7
-rw-r--r--app/assets/javascripts/issues/list/constants.js10
-rw-r--r--app/assets/javascripts/issues/show/components/edited.vue33
-rw-r--r--app/assets/javascripts/issues/show/components/fields/description.vue31
-rw-r--r--app/assets/javascripts/issues/show/components/form.vue79
-rw-r--r--app/assets/javascripts/issues/show/components/header_actions.vue2
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue5
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue7
-rw-r--r--app/assets/javascripts/issues/show/index.js1
-rw-r--r--app/assets/javascripts/jobs/components/table/constants.js19
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_app.vue4
-rw-r--r--app/assets/javascripts/jobs/store/actions.js12
-rw-r--r--app/assets/javascripts/labels/components/promote_label_modal.vue4
-rw-r--r--app/assets/javascripts/labels/group_label_subscription.js6
-rw-r--r--app/assets/javascripts/labels/label_manager.js6
-rw-r--r--app/assets/javascripts/labels/labels_select.js6
-rw-r--r--app/assets/javascripts/labels/project_label_subscription.js4
-rw-r--r--app/assets/javascripts/lib/dompurify.js13
-rw-r--r--app/assets/javascripts/lib/utils/autosave.js40
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js51
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js18
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_format_utility.js26
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js61
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js14
-rw-r--r--app/assets/javascripts/listbox/index.js48
-rw-r--r--app/assets/javascripts/logo.js2
-rw-r--r--app/assets/javascripts/main.js7
-rw-r--r--app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue6
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue5
-rw-r--r--app/assets/javascripts/members/utils.js5
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue4
-rw-r--r--app/assets/javascripts/merge_conflicts/store/actions.js4
-rw-r--r--app/assets/javascripts/merge_request.js6
-rw-r--r--app/assets/javascripts/merge_request_tabs.js6
-rw-r--r--app/assets/javascripts/merge_requests/components/sticky_header.vue1
-rw-r--r--app/assets/javascripts/milestones/components/promote_milestone_modal.vue4
-rw-r--r--app/assets/javascripts/milestones/milestone.js4
-rw-r--r--app/assets/javascripts/milestones/milestone_select.js2
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js4
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js4
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue8
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js30
-rw-r--r--app/assets/javascripts/mr_notes/index.js3
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js13
-rw-r--r--app/assets/javascripts/namespaces/leave_by_url.js4
-rw-r--r--app/assets/javascripts/nav/components/top_nav_app.vue10
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue2
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue9
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue19
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue7
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue5
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue4
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue67
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue4
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue19
-rw-r--r--app/assets/javascripts/notes/components/notes_activity_header.vue38
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue24
-rw-r--r--app/assets/javascripts/notes/components/timeline_toggle.vue1
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue4
-rw-r--r--app/assets/javascripts/notes/discussion_filters.js34
-rw-r--r--app/assets/javascripts/notes/i18n.js2
-rw-r--r--app/assets/javascripts/notes/index.js13
-rw-r--r--app/assets/javascripts/notes/mixins/diff_line_note_form.js6
-rw-r--r--app/assets/javascripts/notes/mixins/discussion_navigation.js156
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js4
-rw-r--r--app/assets/javascripts/notes/timeline.js16
-rw-r--r--app/assets/javascripts/notes/utils/get_notes_filter_data.js21
-rw-r--r--app/assets/javascripts/operation_settings/store/actions.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js10
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list.vue11
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js12
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue18
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue11
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js11
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue60
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/cleanup_image_tags.vue7
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue2
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_downloader.js4
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_previewer.js4
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js4
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/index.js9
-rw-r--r--app/assets/javascripts/pages/admin/dashboard/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/groups/show/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue4
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js6
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js8
-rw-r--r--app/assets/javascripts/pages/groups/new/group_path_validator.js4
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js9
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/settings/index.js2
-rw-r--r--app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue4
-rw-r--r--app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue95
-rw-r--r--app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js20
-rw-r--r--app/assets/javascripts/pages/import/history/components/import_history_app.vue4
-rw-r--r--app/assets/javascripts/pages/profiles/index.js2
-rw-r--r--app/assets/javascripts/pages/profiles/init_timezone_dropdown.js34
-rw-r--r--app/assets/javascripts/pages/projects/blame/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue4
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue4
-rw-r--r--app/assets/javascripts/pages/projects/hooks/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js4
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js15
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js3
-rw-r--r--app/assets/javascripts/pages/projects/project.js4
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue30
-rw-r--r--app/assets/javascripts/pages/sessions/new/username_validator.js4
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue4
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue221
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js6
-rw-r--r--app/assets/javascripts/pdf/index.vue17
-rw-r--r--app/assets/javascripts/persistent_user_callout.js6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue48
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js3
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue4
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue2
-rw-r--r--app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue2
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue254
-rw-r--r--app/assets/javascripts/pipeline_new/graphql/mutations/create_pipeline.mutation.graphql9
-rw-r--r--app/assets/javascripts/pipeline_new/graphql/queries/ci_config_variables.graphql11
-rw-r--r--app/assets/javascripts/pipeline_new/graphql/resolvers.js29
-rw-r--r--app/assets/javascripts/pipeline_new/index.js14
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/pipeline_schedules.vue134
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_form.vue18
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_actions.vue66
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline.vue32
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_next_run.vue32
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_owner.vue29
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_target.vue36
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/table/pipeline_schedules_table.vue95
-rw-r--r--app/assets/javascripts/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql6
-rw-r--r--app/assets/javascripts/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql40
-rw-r--r--app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_app.js32
-rw-r--r--app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_form_app.js32
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/widgets/list.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/failed_jobs_app.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/failed_jobs_table.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/jobs_app.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_tabs.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue4
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js16
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/actions.js4
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/mutations.js4
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue6
-rw-r--r--app/assets/javascripts/profile/gl_crop.js1
-rw-r--r--app/assets/javascripts/profile/preferences/components/profile_preferences.vue16
-rw-r--r--app/assets/javascripts/profile/profile.js14
-rw-r--r--app/assets/javascripts/project_select.js4
-rw-r--r--app/assets/javascripts/projects/commit/store/actions.js4
-rw-r--r--app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue8
-rw-r--r--app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue4
-rw-r--r--app/assets/javascripts/projects/commits/store/actions.js4
-rw-r--r--app/assets/javascripts/projects/compare/components/app.vue46
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown.vue6
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue4
-rw-r--r--app/assets/javascripts/projects/compare/index.js3
-rw-r--r--app/assets/javascripts/projects/project_find_file.js4
-rw-r--r--app/assets/javascripts/projects/settings/access_dropdown.js6
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue137
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue137
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/index.vue (renamed from app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue)0
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/index.vue (renamed from app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue)0
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/merge_protections.vue (renamed from app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue)0
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue (renamed from app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue)0
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js42
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue207
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/protection.vue99
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue110
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js11
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql50
-rw-r--r--app/assets/javascripts/projects/settings/components/access_dropdown.vue6
-rw-r--r--app/assets/javascripts/projects/settings/components/default_branch_selector.vue38
-rw-r--r--app/assets/javascripts/projects/settings/components/transfer_project_form.vue170
-rw-r--r--app/assets/javascripts/projects/settings/graphql/queries/current_user_namespace.query.graphql9
-rw-r--r--app/assets/javascripts/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql24
-rw-r--r--app/assets/javascripts/projects/settings/init_transfer_project_form.js2
-rw-r--r--app/assets/javascripts/projects/settings/mount_default_branch_selector.js22
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/app.vue9
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue37
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js12
-rw-r--r--app/assets/javascripts/projects/star.js6
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue4
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js6
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js6
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_edit.js4
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue174
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue4
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue12
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue4
-rw-r--r--app/assets/javascripts/releases/components/app_show.vue4
-rw-r--r--app/assets/javascripts/releases/components/tag_field_new.vue92
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/actions.js17
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/getters.js1
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js1
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/mutations.js4
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/state.js2
-rw-r--r--app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue61
-rw-r--r--app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue65
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/actions.js76
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/getters.js45
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/index.js17
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutations.js20
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/state.js28
-rw-r--r--app/assets/javascripts/reports/components/issue_body.js3
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue35
-rw-r--r--app/assets/javascripts/repository/commits_service.js4
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue4
-rw-r--r--app/assets/javascripts/repository/components/blob_controls.vue34
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue4
-rw-r--r--app/assets/javascripts/repository/components/new_directory_modal.vue4
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue6
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue4
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue4
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue38
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_actions_cell.vue7
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_owner_cell.vue63
-rw-r--r--app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue16
-rw-r--r--app/assets/javascripts/runner/components/runner_delete_button.vue32
-rw-r--r--app/assets/javascripts/runner/components/runner_details.vue7
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue1
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue44
-rw-r--r--app/assets/javascripts/runner/components/runner_list_empty_state.vue9
-rw-r--r--app/assets/javascripts/runner/components/runner_membership_toggle.vue42
-rw-r--r--app/assets/javascripts/runner/components/search_tokens/tag_token.vue18
-rw-r--r--app/assets/javascripts/runner/constants.js19
-rw-r--r--app/assets/javascripts/runner/graphql/list/group_runners.query.graphql5
-rw-r--r--app/assets/javascripts/runner/graphql/list/group_runners_count.query.graphql3
-rw-r--r--app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql14
-rw-r--r--app/assets/javascripts/runner/graphql/list/local_state.js22
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue50
-rw-r--r--app/assets/javascripts/runner/group_runners/index.js6
-rw-r--r--app/assets/javascripts/runner/runner_search_utils.js18
-rw-r--r--app/assets/javascripts/search/index.js10
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue25
-rw-r--r--app/assets/javascripts/search/sidebar/index.js9
-rw-r--r--app/assets/javascripts/search/store/actions.js10
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue47
-rw-r--r--app/assets/javascripts/search_settings/components/search_settings.vue41
-rw-r--r--app/assets/javascripts/search_settings/mount.js1
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue11
-rw-r--r--app/assets/javascripts/security_configuration/components/upgrade_banner.vue2
-rw-r--r--app/assets/javascripts/service_ping_consent.js4
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_form.vue10
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue16
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue15
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/report.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue8
-rw-r--r--app/assets/javascripts/sidebar/constants.js7
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js6
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_participants.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebar_details.query.graphql9
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebar_details_mr.query.graphql9
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js33
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js8
-rw-r--r--app/assets/javascripts/single_file_diff.js4
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_view.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue8
-rw-r--r--app/assets/javascripts/task_list.js4
-rw-r--r--app/assets/javascripts/token_access/components/token_access.vue32
-rw-r--r--app/assets/javascripts/users_select/index.js31
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue44
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/state_container.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue314
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue137
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue119
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue98
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue67
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue49
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue68
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_section.vue35
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue40
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/color_select_dropdown/color_select_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/confidentiality_badge.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/gitlab_version_check.vue27
-rw-r--r--app/assets/javascripts/vue_shared/components/group_select/utils.js15
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql17
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql14
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue214
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue47
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue216
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/metric_images/store/actions.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue208
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select_deprecated.vue212
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue24
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/constants.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/history_item.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/registry_search.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql4
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql4
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue34
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/constants.js11
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js13
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_bidi_chars.js30
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js45
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js41
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight_utils.js15
-rw-r--r--app/assets/javascripts/vue_shared/components/timezone_dropdown.vue88
-rw-r--r--app/assets/javascripts/vue_shared/components/timezone_dropdown/timezone_dropdown.vue119
-rw-r--r--app/assets/javascripts/vue_shared/components/url_sync.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue71
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue117
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_old.vue114
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue70
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_new.vue122
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_old.vue117
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/user_select/user_select.vue1
-rw-r--r--app/assets/javascripts/vue_shared/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/directives/safe_html.js25
-rw-r--r--app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue11
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue4
-rw-r--r--app/assets/javascripts/webhooks/components/form_url_app.vue134
-rw-r--r--app/assets/javascripts/webhooks/components/form_url_mask_item.vue90
-rw-r--r--app/assets/javascripts/webhooks/index.js25
-rw-r--r--app/assets/javascripts/work_items/components/work_item_assignees.vue12
-rw-r--r--app/assets/javascripts/work_items/components/work_item_description.vue19
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue151
-rw-r--r--app/assets/javascripts/work_items/components/work_item_due_date.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_labels.vue118
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/index.js10
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue12
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue32
-rw-r--r--app/assets/javascripts/work_items/components/work_item_milestone.vue248
-rw-r--r--app/assets/javascripts/work_items/components/work_item_type_icon.vue2
-rw-r--r--app/assets/javascripts/work_items/constants.js15
-rw-r--r--app/assets/javascripts/work_items/graphql/get_issue_details.query.graphql9
-rw-r--r--app/assets/javascripts/work_items/graphql/typedefs.graphql16
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.fragment.graphql1
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.query.graphql9
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_assignees.subscription.graphql21
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_dates.subscription.graphql1
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_labels.subscription.graphql19
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql16
-rw-r--r--app/assets/javascripts/work_items/index.js10
-rw-r--r--app/assets/javascripts/work_items/pages/create_work_item.vue43
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss7
-rw-r--r--app/assets/stylesheets/bootstrap_migration_reset.scss4
-rw-r--r--app/assets/stylesheets/components/batch_comments/review_bar.scss71
-rw-r--r--app/assets/stylesheets/components/dashboard_skeleton.scss78
-rw-r--r--app/assets/stylesheets/components/date_time_picker.scss5
-rw-r--r--app/assets/stylesheets/components/design_management/design.scss193
-rw-r--r--app/assets/stylesheets/components/design_management/design_list_item.scss19
-rw-r--r--app/assets/stylesheets/components/feature_highlight.scss5
-rw-r--r--app/assets/stylesheets/components/milestone_combobox.scss5
-rw-r--r--app/assets/stylesheets/components/related_items_list.scss41
-rw-r--r--app/assets/stylesheets/components/release_block.scss3
-rw-r--r--app/assets/stylesheets/components/release_block_milestone_info.scss6
-rw-r--r--app/assets/stylesheets/components/shortcuts_help.scss29
-rw-r--r--app/assets/stylesheets/framework.scss4
-rw-r--r--app/assets/stylesheets/framework/blocks.scss1
-rw-r--r--app/assets/stylesheets/framework/calendar.scss8
-rw-r--r--app/assets/stylesheets/framework/ci_variable_list.scss77
-rw-r--r--app/assets/stylesheets/framework/diffs.scss247
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss1
-rw-r--r--app/assets/stylesheets/framework/flash.scss27
-rw-r--r--app/assets/stylesheets/framework/flex_grid.scss52
-rw-r--r--app/assets/stylesheets/framework/gfm.scss6
-rw-r--r--app/assets/stylesheets/framework/lists.scss7
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss29
-rw-r--r--app/assets/stylesheets/framework/memory_graph.scss4
-rw-r--r--app/assets/stylesheets/framework/tables.scss16
-rw-r--r--app/assets/stylesheets/framework/timeline.scss26
-rw-r--r--app/assets/stylesheets/framework/toggle.scss131
-rw-r--r--app/assets/stylesheets/framework/typography.scss12
-rw-r--r--app/assets/stylesheets/framework/variables.scss21
-rw-r--r--app/assets/stylesheets/framework/wells.scss9
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss4
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss2
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss4
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss2
-rw-r--r--app/assets/stylesheets/lazy_bundles/gridstack.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/admin/geo_nodes.scss45
-rw-r--r--app/assets/stylesheets/page_bundles/admin/geo_replicable.scss18
-rw-r--r--app/assets/stylesheets/page_bundles/cluster_agents.scss13
-rw-r--r--app/assets/stylesheets/page_bundles/clusters.scss22
-rw-r--r--app/assets/stylesheets/page_bundles/graph_charts.scss27
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss7
-rw-r--r--app/assets/stylesheets/page_bundles/incidents.scss73
-rw-r--r--app/assets/stylesheets/page_bundles/issues_show.scss214
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss323
-rw-r--r--app/assets/stylesheets/page_bundles/milestone.scss35
-rw-r--r--app/assets/stylesheets/page_bundles/operations.scss80
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline_schedules.scss96
-rw-r--r--app/assets/stylesheets/page_bundles/profile.scss58
-rw-r--r--app/assets/stylesheets/page_bundles/project.scss8
-rw-r--r--app/assets/stylesheets/page_bundles/prometheus.scss113
-rw-r--r--app/assets/stylesheets/page_bundles/releases.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/tree.scss207
-rw-r--r--app/assets/stylesheets/page_bundles/work_items.scss19
-rw-r--r--app/assets/stylesheets/pages/clusters.scss32
-rw-r--r--app/assets/stylesheets/pages/deploy_keys.scss4
-rw-r--r--app/assets/stylesheets/pages/environment_logs.scss54
-rw-r--r--app/assets/stylesheets/pages/events.scss4
-rw-r--r--app/assets/stylesheets/pages/help.scss40
-rw-r--r--app/assets/stylesheets/pages/issuable.scss126
-rw-r--r--app/assets/stylesheets/pages/issues.scss5
-rw-r--r--app/assets/stylesheets/pages/notes.scss336
-rw-r--r--app/assets/stylesheets/pages/profile.scss105
-rw-r--r--app/assets/stylesheets/pages/projects.scss63
-rw-r--r--app/assets/stylesheets/pages/prometheus.scss114
-rw-r--r--app/assets/stylesheets/pages/search.scss19
-rw-r--r--app/assets/stylesheets/pages/service_desk.scss7
-rw-r--r--app/assets/stylesheets/pages/settings.scss25
-rw-r--r--app/assets/stylesheets/pages/tree.scss246
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss27
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss22
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss9
-rw-r--r--app/assets/stylesheets/themes/_dark.scss10
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss5
-rw-r--r--app/assets/stylesheets/utilities.scss131
-rw-r--r--app/components/pajamas/alert_component.rb8
-rw-r--r--app/components/pajamas/progress_component.html.haml2
-rw-r--r--app/components/pajamas/progress_component.rb12
-rw-r--r--app/controllers/admin/broadcast_messages_controller.rb3
-rw-r--r--app/controllers/admin/groups_controller.rb11
-rw-r--r--app/controllers/admin/impersonation_tokens_controller.rb19
-rw-r--r--app/controllers/admin/runners_controller.rb7
-rw-r--r--app/controllers/application_controller.rb1
-rw-r--r--app/controllers/autocomplete_controller.rb20
-rw-r--r--app/controllers/boards/application_controller.rb23
-rw-r--r--app/controllers/boards/issues_controller.rb162
-rw-r--r--app/controllers/boards/lists_controller.rb103
-rw-r--r--app/controllers/concerns/access_tokens_actions.rb16
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb5
-rw-r--r--app/controllers/concerns/boards_actions.rb59
-rw-r--r--app/controllers/concerns/boards_responses.rb94
-rw-r--r--app/controllers/concerns/import/github_oauth.rb100
-rw-r--r--app/controllers/concerns/issuable_collections_action.rb5
-rw-r--r--app/controllers/concerns/multiple_boards_actions.rb93
-rw-r--r--app/controllers/concerns/preview_markdown.rb16
-rw-r--r--app/controllers/concerns/product_analytics_tracking.rb9
-rw-r--r--app/controllers/concerns/registrations_tracking.rb15
-rw-r--r--app/controllers/concerns/sends_blob.rb22
-rw-r--r--app/controllers/concerns/wiki_actions.rb6
-rw-r--r--app/controllers/groups/application_controller.rb4
-rw-r--r--app/controllers/groups/boards_controller.rb15
-rw-r--r--app/controllers/groups/runners_controller.rb16
-rw-r--r--app/controllers/groups/settings/access_tokens_controller.rb6
-rw-r--r--app/controllers/groups_controller.rb6
-rw-r--r--app/controllers/ide_controller.rb5
-rw-r--r--app/controllers/import/bulk_imports_controller.rb8
-rw-r--r--app/controllers/import/github_controller.rb89
-rw-r--r--app/controllers/import/github_groups_controller.rb57
-rw-r--r--app/controllers/jira_connect/public_keys_controller.rb24
-rw-r--r--app/controllers/oauth/applications_controller.rb1
-rw-r--r--app/controllers/oauth/authorizations_controller.rb1
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb11
-rw-r--r--app/controllers/profiles/personal_access_tokens_controller.rb6
-rw-r--r--app/controllers/profiles/preferences_controller.rb4
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb60
-rw-r--r--app/controllers/projects/application_controller.rb4
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb7
-rw-r--r--app/controllers/projects/blame_controller.rb3
-rw-r--r--app/controllers/projects/boards_controller.rb18
-rw-r--r--app/controllers/projects/compare_controller.rb11
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb6
-rw-r--r--app/controllers/projects/google_cloud/databases_controller.rb25
-rw-r--r--app/controllers/projects/incident_management/timeline_events_controller.rb16
-rw-r--r--app/controllers/projects/incidents_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb47
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb1
-rw-r--r--app/controllers/projects/merge_requests_controller.rb9
-rw-r--r--app/controllers/projects/milestones_controller.rb14
-rw-r--r--app/controllers/projects/pages_domains_controller.rb19
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb5
-rw-r--r--app/controllers/projects/product_analytics_controller.rb4
-rw-r--r--app/controllers/projects/protected_refs_controller.rb1
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb6
-rw-r--r--app/controllers/projects/snippets_controller.rb2
-rw-r--r--app/controllers/projects/web_ide_terminals_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb10
-rw-r--r--app/controllers/registrations/welcome_controller.rb7
-rw-r--r--app/controllers/registrations_controller.rb12
-rw-r--r--app/controllers/search_controller.rb4
-rw-r--r--app/controllers/sessions_controller.rb4
-rw-r--r--app/controllers/users/namespace_callouts_controller.rb17
-rw-r--r--app/controllers/users_controller.rb5
-rw-r--r--app/events/pages_domains/pages_domain_created_event.rb18
-rw-r--r--app/events/pages_domains/pages_domain_deleted_event.rb18
-rw-r--r--app/events/pages_domains/pages_domain_updated_event.rb18
-rw-r--r--app/events/projects/project_attributes_changed_event.rb29
-rw-r--r--app/events/projects/project_features_changed_event.rb22
-rw-r--r--app/finders/ci/runners_finder.rb6
-rw-r--r--app/finders/clusters/agent_authorizations_finder.rb36
-rw-r--r--app/finders/groups/accepting_group_transfers_finder.rb7
-rw-r--r--app/finders/labels_finder.rb2
-rw-r--r--app/finders/packages/group_packages_finder.rb2
-rw-r--r--app/finders/packages/helm/packages_finder.rb2
-rw-r--r--app/finders/packages/nuget/package_finder.rb2
-rw-r--r--app/finders/packages/package_finder.rb2
-rw-r--r--app/finders/packages/packages_finder.rb2
-rw-r--r--app/finders/personal_access_tokens_finder.rb42
-rw-r--r--app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb21
-rw-r--r--app/graphql/gitlab_schema.rb13
-rw-r--r--app/graphql/graphql_triggers.rb20
-rw-r--r--app/graphql/mutations/alert_management/create_alert_issue.rb4
-rw-r--r--app/graphql/mutations/ci/job/artifacts_destroy.rb21
-rw-r--r--app/graphql/mutations/ci/pipeline_schedule/base.rb21
-rw-r--r--app/graphql/mutations/ci/pipeline_schedule/delete.rb27
-rw-r--r--app/graphql/mutations/ci/project_ci_cd_settings_update.rb11
-rw-r--r--app/graphql/mutations/ci/runner/update.rb2
-rw-r--r--app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb3
-rw-r--r--app/graphql/mutations/issues/create.rb8
-rw-r--r--app/graphql/mutations/namespace/package_settings/update.rb30
-rw-r--r--app/graphql/mutations/packages/bulk_destroy.rb43
-rw-r--r--app/graphql/mutations/packages/destroy_files.rb4
-rw-r--r--app/graphql/mutations/work_items/update_widgets.rb60
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb2
-rw-r--r--app/graphql/resolvers/bulk_labels_resolver.rb27
-rw-r--r--app/graphql/resolvers/ci/all_jobs_resolver.rb17
-rw-r--r--app/graphql/resolvers/ci/runner_projects_resolver.rb4
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb27
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb4
-rw-r--r--app/graphql/resolvers/down_votes_count_resolver.rb15
-rw-r--r--app/graphql/resolvers/project_pipeline_schedules_resolver.rb17
-rw-r--r--app/graphql/resolvers/projects/branch_rules_resolver.rb8
-rw-r--r--app/graphql/resolvers/projects_resolver.rb4
-rw-r--r--app/graphql/resolvers/up_votes_count_resolver.rb15
-rw-r--r--app/graphql/resolvers/work_items_resolver.rb26
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb11
-rw-r--r--app/graphql/types/ci/config_variable_type.rb4
-rw-r--r--app/graphql/types/ci/job_type.rb18
-rw-r--r--app/graphql/types/ci/pipeline_schedule_status_enum.rb12
-rw-r--r--app/graphql/types/ci/pipeline_schedule_type.rb45
-rw-r--r--app/graphql/types/ci/runner_membership_filter_enum.rb7
-rw-r--r--app/graphql/types/environment_type.rb4
-rw-r--r--app/graphql/types/issue_type.rb19
-rw-r--r--app/graphql/types/merge_request_type.rb23
-rw-r--r--app/graphql/types/merge_requests/detailed_merge_status_enum.rb3
-rw-r--r--app/graphql/types/mutation_type.rb4
-rw-r--r--app/graphql/types/namespace/package_settings_type.rb49
-rw-r--r--app/graphql/types/notes/note_type.rb2
-rw-r--r--app/graphql/types/permission_types/ci/pipeline_schedules.rb17
-rw-r--r--app/graphql/types/project_type.rb6
-rw-r--r--app/graphql/types/projects/branch_rule_type.rb9
-rw-r--r--app/graphql/types/query_type.rb6
-rw-r--r--app/graphql/types/subscription_type.rb8
-rw-r--r--app/graphql/types/work_items/widget_interface.rb3
-rw-r--r--app/graphql/types/work_items/widgets/labels_update_input_type.rb20
-rw-r--r--app/helpers/application_helper.rb7
-rw-r--r--app/helpers/application_settings_helper.rb3
-rw-r--r--app/helpers/boards_helper.rb25
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb12
-rw-r--r--app/helpers/ci/pipelines_helper.rb3
-rw-r--r--app/helpers/compare_helper.rb3
-rw-r--r--app/helpers/events_helper.rb48
-rw-r--r--app/helpers/form_helper.rb23
-rw-r--r--app/helpers/groups_helper.rb7
-rw-r--r--app/helpers/hooks_helper.rb7
-rw-r--r--app/helpers/ide_helper.rb32
-rw-r--r--app/helpers/issuables_helper.rb4
-rw-r--r--app/helpers/issues_helper.rb9
-rw-r--r--app/helpers/markup_helper.rb77
-rw-r--r--app/helpers/milestones_helper.rb26
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/helpers/projects_helper.rb16
-rw-r--r--app/helpers/recaptcha_helper.rb18
-rw-r--r--app/helpers/releases_helper.rb2
-rw-r--r--app/helpers/search_helper.rb34
-rw-r--r--app/helpers/selects_helper.rb5
-rw-r--r--app/helpers/sessions_helper.rb2
-rw-r--r--app/helpers/time_helper.rb6
-rw-r--r--app/helpers/timeboxes_helper.rb12
-rw-r--r--app/helpers/todos_helper.rb26
-rw-r--r--app/helpers/users/callouts_helper.rb4
-rw-r--r--app/helpers/users_helper.rb15
-rw-r--r--app/helpers/wiki_helper.rb10
-rw-r--r--app/mailers/emails/profile.rb24
-rw-r--r--app/mailers/previews/notify_preview.rb16
-rw-r--r--app/models/application_setting.rb46
-rw-r--r--app/models/application_setting_implementation.rb3
-rw-r--r--app/models/award_emoji.rb4
-rw-r--r--app/models/bulk_imports/entity.rb23
-rw-r--r--app/models/bulk_imports/export_status.rb14
-rw-r--r--app/models/bulk_imports/failure.rb20
-rw-r--r--app/models/bulk_imports/tracker.rb2
-rw-r--r--app/models/ci/build.rb49
-rw-r--r--app/models/ci/build_metadata.rb5
-rw-r--r--app/models/ci/job_token/project_scope_link.rb5
-rw-r--r--app/models/ci/job_token/scope.rb2
-rw-r--r--app/models/ci/pipeline.rb54
-rw-r--r--app/models/ci/pipeline_metadata.rb14
-rw-r--r--app/models/ci/runner.rb38
-rw-r--r--app/models/ci/secure_file.rb39
-rw-r--r--app/models/clusters/agents/implicit_authorization.rb2
-rw-r--r--app/models/concerns/approvable.rb4
-rw-r--r--app/models/concerns/atomic_internal_id.rb17
-rw-r--r--app/models/concerns/boards/listable.rb2
-rw-r--r--app/models/concerns/cache_markdown_field.rb2
-rw-r--r--app/models/concerns/ci/metadatable.rb2
-rw-r--r--app/models/concerns/ci/partitionable.rb27
-rw-r--r--app/models/concerns/counter_attribute.rb63
-rw-r--r--app/models/concerns/has_wiki.rb2
-rw-r--r--app/models/concerns/integrations/base_data_fields.rb2
-rw-r--r--app/models/concerns/integrations/has_web_hook.rb2
-rw-r--r--app/models/concerns/issuable.rb44
-rw-r--r--app/models/concerns/participable.rb12
-rw-r--r--app/models/concerns/routable.rb3
-rw-r--r--app/models/concerns/timebox.rb92
-rw-r--r--app/models/deploy_key.rb1
-rw-r--r--app/models/deployment.rb21
-rw-r--r--app/models/diff_viewer/server_side.rb3
-rw-r--r--app/models/environment.rb18
-rw-r--r--app/models/event.rb10
-rw-r--r--app/models/group.rb6
-rw-r--r--app/models/group_group_link.rb2
-rw-r--r--app/models/group_label.rb1
-rw-r--r--app/models/hooks/project_hook.rb7
-rw-r--r--app/models/hooks/service_hook.rb2
-rw-r--r--app/models/hooks/web_hook.rb23
-rw-r--r--app/models/incident_management/timeline_event.rb8
-rw-r--r--app/models/incident_management/timeline_event_tag.rb20
-rw-r--r--app/models/incident_management/timeline_event_tag_link.rb11
-rw-r--r--app/models/integration.rb4
-rw-r--r--app/models/integrations/datadog.rb153
-rw-r--r--app/models/integrations/harbor.rb71
-rw-r--r--app/models/issue.rb18
-rw-r--r--app/models/iteration.rb6
-rw-r--r--app/models/jira_connect/public_key.rb48
-rw-r--r--app/models/jira_connect_installation.rb19
-rw-r--r--app/models/jira_import_state.rb2
-rw-r--r--app/models/label.rb8
-rw-r--r--app/models/member.rb3
-rw-r--r--app/models/members/member_role.rb11
-rw-r--r--app/models/merge_request.rb32
-rw-r--r--app/models/merge_request_diff_file.rb16
-rw-r--r--app/models/milestone.rb91
-rw-r--r--app/models/ml/candidate_param.rb1
-rw-r--r--app/models/ml/experiment.rb8
-rw-r--r--app/models/namespace.rb4
-rw-r--r--app/models/namespace/aggregation_schedule.rb13
-rw-r--r--app/models/namespace/detail.rb4
-rw-r--r--app/models/namespace/package_setting.rb6
-rw-r--r--app/models/note.rb9
-rw-r--r--app/models/notification_recipient.rb2
-rw-r--r--app/models/packages/package.rb7
-rw-r--r--app/models/packages/rpm/repository_file.rb25
-rw-r--r--app/models/pages/lookup_path.rb4
-rw-r--r--app/models/personal_access_token.rb9
-rw-r--r--app/models/preloaders/labels_preloader.rb2
-rw-r--r--app/models/preloaders/project_root_ancestor_preloader.rb3
-rw-r--r--app/models/project.rb57
-rw-r--r--app/models/project_authorization.rb39
-rw-r--r--app/models/project_ci_cd_setting.rb4
-rw-r--r--app/models/project_group_link.rb2
-rw-r--r--app/models/project_label.rb1
-rw-r--r--app/models/project_setting.rb1
-rw-r--r--app/models/project_statistics.rb73
-rw-r--r--app/models/projects/build_artifacts_size_refresh.rb4
-rw-r--r--app/models/protected_branch.rb4
-rw-r--r--app/models/protected_branch/merge_access_level.rb2
-rw-r--r--app/models/protected_branch/push_access_level.rb2
-rw-r--r--app/models/repository.rb40
-rw-r--r--app/models/resource_label_event.rb2
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/models/tree.rb5
-rw-r--r--app/models/user.rb91
-rw-r--r--app/models/user_detail.rb43
-rw-r--r--app/models/user_preference.rb2
-rw-r--r--app/models/users/banned_user.rb2
-rw-r--r--app/models/users/callout.rb3
-rw-r--r--app/models/users/namespace_callout.rb33
-rw-r--r--app/models/users/phone_number_validation.rb41
-rw-r--r--app/models/users/project_callout.rb6
-rw-r--r--app/models/users/user_follow_user.rb15
-rw-r--r--app/models/wiki.rb172
-rw-r--r--app/models/wiki_page.rb17
-rw-r--r--app/policies/ci/runner_policy.rb11
-rw-r--r--app/policies/group_label_policy.rb2
-rw-r--r--app/policies/group_policy.rb20
-rw-r--r--app/policies/issuable_policy.rb12
-rw-r--r--app/policies/issue_policy.rb4
-rw-r--r--app/policies/namespaces/user_namespace_policy.rb2
-rw-r--r--app/policies/note_policy.rb3
-rw-r--r--app/policies/project_label_policy.rb2
-rw-r--r--app/policies/project_policy.rb7
-rw-r--r--app/policies/todo_policy.rb2
-rw-r--r--app/presenters/ci/build_runner_presenter.rb4
-rw-r--r--app/presenters/ci/pipeline_presenter.rb2
-rw-r--r--app/presenters/deploy_key_presenter.rb9
-rw-r--r--app/presenters/event_presenter.rb2
-rw-r--r--app/presenters/key_presenter.rb22
-rw-r--r--app/serializers/board_serializer.rb5
-rw-r--r--app/serializers/board_simple_entity.rb8
-rw-r--r--app/serializers/current_board_entity.rb10
-rw-r--r--app/serializers/current_board_serializer.rb5
-rw-r--r--app/serializers/group_access_token_entity.rb2
-rw-r--r--app/serializers/import/github_org_entity.rb8
-rw-r--r--app/serializers/import/github_org_serializer.rb7
-rw-r--r--app/serializers/issue_entity.rb4
-rw-r--r--app/serializers/merge_request_noteable_entity.rb2
-rw-r--r--app/serializers/merge_request_user_entity.rb4
-rw-r--r--app/serializers/project_access_token_entity.rb2
-rw-r--r--app/serializers/user_serializer.rb2
-rw-r--r--app/services/admin/set_feature_flag_service.rb85
-rw-r--r--app/services/alert_management/create_alert_issue_service.rb2
-rw-r--r--app/services/authorized_project_update/project_recalculate_service.rb7
-rw-r--r--app/services/boards/issues/list_service.rb2
-rw-r--r--app/services/boards/lists/generate_service.rb39
-rw-r--r--app/services/boards/lists/list_service.rb20
-rw-r--r--app/services/bulk_imports/create_pipeline_trackers_service.rb6
-rw-r--r--app/services/bulk_imports/create_service.rb2
-rw-r--r--app/services/bulk_imports/repository_bundle_export_service.rb8
-rw-r--r--app/services/bulk_imports/uploads_export_service.rb5
-rw-r--r--app/services/ci/after_requeue_job_service.rb2
-rw-r--r--app/services/ci/create_pipeline_service.rb4
-rw-r--r--app/services/ci/generate_kubeconfig_service.rb12
-rw-r--r--app/services/ci/job_artifacts/delete_service.rb18
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb2
-rw-r--r--app/services/ci/pipeline_artifacts/coverage_report_service.rb11
-rw-r--r--app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb11
-rw-r--r--app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb32
-rw-r--r--app/services/ci/process_build_service.rb2
-rw-r--r--app/services/ci/runners/register_runner_service.rb2
-rw-r--r--app/services/ci/unlock_artifacts_service.rb6
-rw-r--r--app/services/clusters/applications/destroy_service.rb23
-rw-r--r--app/services/clusters/applications/uninstall_service.rb29
-rw-r--r--app/services/concerns/users/participable_service.rb2
-rw-r--r--app/services/concerns/work_items/widgetable_service.rb12
-rw-r--r--app/services/google_cloud/enable_cloudsql_service.rb6
-rw-r--r--app/services/groups/import_export/import_service.rb2
-rw-r--r--app/services/import/github/cancel_project_import_service.rb36
-rw-r--r--app/services/import/github_service.rb28
-rw-r--r--app/services/incident_management/incidents/create_service.rb12
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/create_service.rb1
-rw-r--r--app/services/incident_management/timeline_events/destroy_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/update_service.rb2
-rw-r--r--app/services/issuable/import_csv/base_service.rb2
-rw-r--r--app/services/issuable/process_assignees.rb10
-rw-r--r--app/services/issuable_base_service.rb47
-rw-r--r--app/services/issues/base_service.rb13
-rw-r--r--app/services/issues/clone_service.rb11
-rw-r--r--app/services/issues/create_service.rb23
-rw-r--r--app/services/issues/import_csv_service.rb4
-rw-r--r--app/services/issues/move_service.rb11
-rw-r--r--app/services/issues/update_service.rb10
-rw-r--r--app/services/jira_connect/create_asymmetric_jwt_service.rb51
-rw-r--r--app/services/labels/promote_service.rb4
-rw-r--r--app/services/members/create_service.rb4
-rw-r--r--app/services/members/destroy_service.rb25
-rw-r--r--app/services/merge_requests/approval_service.rb6
-rw-r--r--app/services/merge_requests/base_service.rb5
-rw-r--r--app/services/merge_requests/close_service.rb5
-rw-r--r--app/services/merge_requests/mark_reviewer_reviewed_service.rb2
-rw-r--r--app/services/merge_requests/merge_base_service.rb4
-rw-r--r--app/services/merge_requests/merge_service.rb24
-rw-r--r--app/services/merge_requests/mergeability/logger.rb16
-rw-r--r--app/services/merge_requests/push_options_handler_service.rb14
-rw-r--r--app/services/merge_requests/request_review_service.rb1
-rw-r--r--app/services/merge_requests/update_assignees_service.rb12
-rw-r--r--app/services/merge_requests/update_service.rb17
-rw-r--r--app/services/ml/experiment_tracking/candidate_repository.rb85
-rw-r--r--app/services/ml/experiment_tracking/experiment_repository.rb30
-rw-r--r--app/services/namespaces/package_settings/update_service.rb8
-rw-r--r--app/services/notes/create_service.rb38
-rw-r--r--app/services/notification_service.rb15
-rw-r--r--app/services/onboarding/progress_service.rb2
-rw-r--r--app/services/packages/debian/create_package_file_service.rb14
-rw-r--r--app/services/packages/mark_packages_for_destruction_service.rb79
-rw-r--r--app/services/packages/rpm/parse_package_service.rb84
-rw-r--r--app/services/packages/rpm/repository_metadata/base_builder.rb30
-rw-r--r--app/services/packages/rpm/repository_metadata/build_primary_xml.rb73
-rw-r--r--app/services/packages/rpm/repository_metadata/build_repomd_xml.rb5
-rw-r--r--app/services/pages_domains/create_acme_order_service.rb10
-rw-r--r--app/services/pages_domains/create_service.rb34
-rw-r--r--app/services/pages_domains/delete_service.rb32
-rw-r--r--app/services/pages_domains/update_service.rb34
-rw-r--r--app/services/personal_access_tokens/revoke_service.rb3
-rw-r--r--app/services/projects/autocomplete_service.rb20
-rw-r--r--app/services/projects/blame_service.rb8
-rw-r--r--app/services/projects/container_repository/cleanup_tags_base_service.rb17
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb110
-rw-r--r--app/services/projects/container_repository/gitlab/cleanup_tags_service.rb3
-rw-r--r--app/services/projects/container_repository/third_party/cleanup_tags_service.rb106
-rw-r--r--app/services/projects/destroy_service.rb2
-rw-r--r--app/services/projects/import_service.rb6
-rw-r--r--app/services/projects/update_service.rb40
-rw-r--r--app/services/releases/create_service.rb8
-rw-r--r--app/services/releases/destroy_service.rb4
-rw-r--r--app/services/releases/update_service.rb10
-rw-r--r--app/services/resource_access_tokens/create_service.rb13
-rw-r--r--app/services/search_service.rb10
-rw-r--r--app/services/users/build_service.rb2
-rw-r--r--app/services/users/dismiss_namespace_callout_service.rb11
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb4
-rw-r--r--app/services/web_hook_service.rb3
-rw-r--r--app/services/web_hooks/log_execution_service.rb2
-rw-r--r--app/services/work_items/create_service.rb12
-rw-r--r--app/services/work_items/update_service.rb21
-rw-r--r--app/services/work_items/widgets/base_service.rb5
-rw-r--r--app/services/work_items/widgets/labels_service/update_service.rb15
-rw-r--r--app/uploaders/job_artifact_uploader.rb1
-rw-r--r--app/uploaders/object_storage/cdn.rb10
-rw-r--r--app/uploaders/object_storage/cdn/google_cdn.rb4
-rw-r--r--app/uploaders/packages/rpm/repository_file_uploader.rb33
-rw-r--r--app/validators/json_schemas/build_metadata_secrets.json3
-rw-r--r--app/validators/json_schemas/ci_secure_file_metadata.json22
-rw-r--r--app/validators/json_schemas/merge_request_predictions_suggested_reviewers.json2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml14
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml3
-rw-r--r--app/views/admin/application_settings/_eks.html.haml2
-rw-r--r--app/views/admin/application_settings/_email.html.haml2
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_floc.html.haml2
-rw-r--r--app/views/admin/application_settings/_gitaly.html.haml4
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml2
-rw-r--r--app/views/admin/application_settings/_help_page.html.haml2
-rw-r--r--app/views/admin/application_settings/_import_export_limits.html.haml4
-rw-r--r--app/views/admin/application_settings/_ip_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_issue_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_jira_connect_application_key.html.haml2
-rw-r--r--app/views/admin/application_settings/_localization.html.haml2
-rw-r--r--app/views/admin/application_settings/_network_rate_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_note_limits.html.haml4
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml2
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml8
-rw-r--r--app/views/admin/application_settings/_pages.html.haml2
-rw-r--r--app/views/admin/application_settings/_performance.html.haml2
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml2
-rw-r--r--app/views/admin/application_settings/_pipeline_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_prometheus.html.haml2
-rw-r--r--app/views/admin/application_settings/_protected_paths.html.haml2
-rw-r--r--app/views/admin/application_settings/_registry.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_mirrors_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml2
-rw-r--r--app/views/admin/application_settings/_sentry.html.haml2
-rw-r--r--app/views/admin/application_settings/_sidekiq_job_limits.html.haml4
-rw-r--r--app/views/admin/application_settings/_signin.html.haml2
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml2
-rw-r--r--app/views/admin/application_settings/_sourcegraph.html.haml2
-rw-r--r--app/views/admin/application_settings/_terms.html.haml2
-rw-r--r--app/views/admin/application_settings/_third_party_offers.html.haml2
-rw-r--r--app/views/admin/application_settings/_usage.html.haml2
-rw-r--r--app/views/admin/application_settings/_user_restrictions.html.haml6
-rw-r--r--app/views/admin/application_settings/_users_api_limits.html.haml4
-rw-r--r--app/views/admin/application_settings/_whats_new.html.haml2
-rw-r--r--app/views/admin/application_settings/appearances/preview_sign_in.html.haml4
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml19
-rw-r--r--app/views/admin/application_settings/general.html.haml4
-rw-r--r--app/views/admin/application_settings/service_usage_data.html.haml39
-rw-r--r--app/views/admin/applications/_form.html.haml2
-rw-r--r--app/views/admin/background_jobs/show.html.haml3
-rw-r--r--app/views/admin/broadcast_messages/_table.html.haml38
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml63
-rw-r--r--app/views/admin/dashboard/index.html.haml4
-rw-r--r--app/views/admin/deploy_keys/edit.html.haml4
-rw-r--r--app/views/admin/deploy_keys/new.html.haml7
-rw-r--r--app/views/admin/groups/_form.html.haml4
-rw-r--r--app/views/admin/groups/_group.html.haml3
-rw-r--r--app/views/admin/groups/show.html.haml177
-rw-r--r--app/views/admin/hooks/edit.html.haml2
-rw-r--r--app/views/admin/hooks/index.html.haml2
-rw-r--r--app/views/admin/impersonation_tokens/index.html.haml13
-rw-r--r--app/views/admin/projects/_projects.html.haml45
-rw-r--r--app/views/admin/projects/show.html.haml1
-rw-r--r--app/views/admin/users/_projects.html.haml24
-rw-r--r--app/views/admin/users/_user_detail_note.html.haml6
-rw-r--r--app/views/admin/users/projects.html.haml68
-rw-r--r--app/views/admin/users/show.html.haml220
-rw-r--r--app/views/award_emoji/_awards_block.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml8
-rw-r--r--app/views/ci/variables/_url_query_variable_row.html.haml4
-rw-r--r--app/views/ci/variables/_variable_row.html.haml6
-rw-r--r--app/views/clusters/clusters/_health.html.haml4
-rw-r--r--app/views/clusters/clusters/index.html.haml1
-rw-r--r--app/views/clusters/clusters/user/_form.html.haml2
-rw-r--r--app/views/devise/registrations/new.html.haml2
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml8
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml8
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml2
-rw-r--r--app/views/discussions/_discussion.html.haml22
-rw-r--r--app/views/events/event/_common.html.haml2
-rw-r--r--app/views/groups/_import_group_from_another_instance_panel.html.haml6
-rw-r--r--app/views/groups/_import_group_from_file_panel.html.haml4
-rw-r--r--app/views/groups/_personalize.html.haml2
-rw-r--r--app/views/groups/boards/index.html.haml2
-rw-r--r--app/views/groups/merge_requests.html.haml30
-rw-r--r--app/views/groups/milestones/_form.html.haml4
-rw-r--r--app/views/groups/new.html.haml2
-rw-r--r--app/views/groups/projects.html.haml71
-rw-r--r--app/views/groups/settings/_pages_settings.html.haml4
-rw-r--r--app/views/groups/settings/access_tokens/index.html.haml18
-rw-r--r--app/views/groups/settings/ci_cd/_form.html.haml4
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/groups/settings/integrations/index.html.haml9
-rw-r--r--app/views/groups/show.html.haml3
-rw-r--r--app/views/help/index.html.haml8
-rw-r--r--app/views/help/instance_configuration.html.haml2
-rw-r--r--app/views/help/show.html.haml2
-rw-r--r--app/views/import/_githubish_status.html.haml4
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml30
-rw-r--r--app/views/import/github/status.html.haml5
-rw-r--r--app/views/layouts/_flash.html.haml18
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/fullscreen.html.haml11
-rw-r--r--app/views/layouts/header/_default.html.haml2
-rw-r--r--app/views/layouts/header/_gitlab_version.html.haml2
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml3
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml32
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml26
-rw-r--r--app/views/layouts/notify.html.haml2
-rw-r--r--app/views/layouts/terms.html.haml2
-rw-r--r--app/views/notify/access_token_revoked_email.html.haml7
-rw-r--r--app/views/notify/access_token_revoked_email.text.erb5
-rw-r--r--app/views/notify/project_was_exported_email.html.haml10
-rw-r--r--app/views/notify/project_was_moved_email.html.haml20
-rw-r--r--app/views/notify/project_was_not_exported_email.html.haml4
-rw-r--r--app/views/notify/repository_push_email.text.haml2
-rw-r--r--app/views/notify/request_review_merge_request_email.html.haml2
-rw-r--r--app/views/notify/send_unsubscribed_notification.html.haml2
-rw-r--r--app/views/notify/two_factor_otp_attempt_failed_email.html.haml51
-rw-r--r--app/views/notify/two_factor_otp_attempt_failed_email.text.haml7
-rw-r--r--app/views/notify/unknown_sign_in_email.html.haml2
-rw-r--r--app/views/notify/unknown_sign_in_email.text.haml2
-rw-r--r--app/views/profiles/active_sessions/index.html.haml2
-rw-r--r--app/views/profiles/audit_log.html.haml2
-rw-r--r--app/views/profiles/chat_names/index.html.haml2
-rw-r--r--app/views/profiles/emails/index.html.haml6
-rw-r--r--app/views/profiles/gpg_keys/_form.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml3
-rw-r--r--app/views/profiles/keys/_form.html.haml4
-rw-r--r--app/views/profiles/keys/_key_details.html.haml51
-rw-r--r--app/views/profiles/keys/index.html.haml3
-rw-r--r--app/views/profiles/notifications/show.html.haml2
-rw-r--r--app/views/profiles/passwords/edit.html.haml9
-rw-r--r--app/views/profiles/passwords/new.html.haml4
-rw-r--r--app/views/profiles/preferences/show.html.haml4
-rw-r--r--app/views/profiles/show.html.haml51
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml8
-rw-r--r--app/views/projects/_fork_suggestion.html.haml5
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml2
-rw-r--r--app/views/projects/_transfer.html.haml2
-rw-r--r--app/views/projects/artifacts/browse.html.haml1
-rw-r--r--app/views/projects/artifacts/file.html.haml1
-rw-r--r--app/views/projects/blame/show.html.haml3
-rw-r--r--app/views/projects/blob/_blob.html.haml2
-rw-r--r--app/views/projects/blob/_editor.html.haml16
-rw-r--r--app/views/projects/blob/_pipeline_tour_success.html.haml2
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml12
-rw-r--r--app/views/projects/blob/preview.html.haml2
-rw-r--r--app/views/projects/blob/show.html.haml1
-rw-r--r--app/views/projects/boards/index.html.haml2
-rw-r--r--app/views/projects/branch_rules/_show.html.haml2
-rw-r--r--app/views/projects/buttons/_clone.html.haml8
-rw-r--r--app/views/projects/buttons/_download_links.html.haml2
-rw-r--r--app/views/projects/buttons/_fork.html.haml2
-rw-r--r--app/views/projects/buttons/_star.html.haml14
-rw-r--r--app/views/projects/cleanup/_show.html.haml4
-rw-r--r--app/views/projects/cluster_agents/show.html.haml1
-rw-r--r--app/views/projects/commit/_signature.html.haml2
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml4
-rw-r--r--app/views/projects/commits/show.html.haml2
-rw-r--r--app/views/projects/compare/show.html.haml2
-rw-r--r--app/views/projects/default_branch/_show.html.haml4
-rw-r--r--app/views/projects/deploy_keys/edit.html.haml2
-rw-r--r--app/views/projects/deployments/_deployment.html.haml2
-rw-r--r--app/views/projects/deployments/_rollback.haml7
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/environments/metrics.html.haml2
-rw-r--r--app/views/projects/find_file/show.html.haml1
-rw-r--r--app/views/projects/graphs/charts.html.haml1
-rw-r--r--app/views/projects/hooks/edit.html.haml2
-rw-r--r--app/views/projects/hooks/index.html.haml4
-rw-r--r--app/views/projects/incidents/show.html.haml1
-rw-r--r--app/views/projects/issues/_discussion.html.haml3
-rw-r--r--app/views/projects/issues/_issue.html.haml5
-rw-r--r--app/views/projects/issues/_work_item_links.html.haml2
-rw-r--r--app/views/projects/issues/service_desk/_service_desk_info_content.html.haml2
-rw-r--r--app/views/projects/issues/show.html.haml1
-rw-r--r--app/views/projects/jobs/_user.html.haml2
-rw-r--r--app/views/projects/merge_requests/_awards_block.html.haml5
-rw-r--r--app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml5
-rw-r--r--app/views/projects/merge_requests/_discussion_filter.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml11
-rw-r--r--app/views/projects/merge_requests/_nav_btns.html.haml7
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml1
-rw-r--r--app/views/projects/merge_requests/show.html.haml6
-rw-r--r--app/views/projects/milestones/_form.html.haml2
-rw-r--r--app/views/projects/mirrors/_authentication_method.html.haml10
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml2
-rw-r--r--app/views/projects/network/_head.html.haml2
-rw-r--r--app/views/projects/pages/_destroy.haml18
-rw-r--r--app/views/projects/pages/new.html.haml11
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml6
-rw-r--r--app/views/projects/pipeline_schedules/edit.html.haml5
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml34
-rw-r--r--app/views/projects/pipeline_schedules/new.html.haml5
-rw-r--r--app/views/projects/pipelines/_info.html.haml13
-rw-r--r--app/views/projects/pipelines/new.html.haml1
-rw-r--r--app/views/projects/project_templates/_project_fields_form.html.haml2
-rw-r--r--app/views/projects/protected_branches/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/shared/_dropdown.html.haml8
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml8
-rw-r--r--app/views/projects/releases/index.html.haml1
-rw-r--r--app/views/projects/releases/show.html.haml1
-rw-r--r--app/views/projects/repositories/_feed.html.haml18
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml2
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml18
-rw-r--r--app/views/projects/settings/branch_rules/index.html.haml6
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_badge.html.haml18
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml3
-rw-r--r--app/views/projects/settings/integrations/index.html.haml11
-rw-r--r--app/views/projects/settings/merge_requests/show.html.haml5
-rw-r--r--app/views/projects/show.html.haml1
-rw-r--r--app/views/projects/snippets/show.html.haml2
-rw-r--r--app/views/projects/starrers/_starrer.html.haml4
-rw-r--r--app/views/projects/tags/new.html.haml20
-rw-r--r--app/views/projects/tree/show.html.haml1
-rw-r--r--app/views/projects/triggers/_index.html.haml18
-rw-r--r--app/views/projects/work_items/index.html.haml2
-rw-r--r--app/views/registrations/welcome/show.html.haml6
-rw-r--r--app/views/search/_results.html.haml37
-rw-r--r--app/views/search/_results_list.html.haml18
-rw-r--r--app/views/search/_results_status.html.haml26
-rw-r--r--app/views/search/_results_status_horiz_nav.html.haml22
-rw-r--r--app/views/search/_results_status_vert_nav.html.haml23
-rw-r--r--app/views/search/results/_snippet_title.html.haml2
-rw-r--r--app/views/search/results/_wiki_blob.html.haml2
-rw-r--r--app/views/search/show.html.haml3
-rw-r--r--app/views/shared/_clone_panel.html.haml4
-rw-r--r--app/views/shared/_commit_well.html.haml4
-rw-r--r--app/views/shared/_custom_attributes.html.haml19
-rw-r--r--app/views/shared/_file_highlight.html.haml3
-rw-r--r--app/views/shared/access_tokens/_form.html.haml5
-rw-r--r--app/views/shared/blob/_markdown_buttons.html.haml20
-rw-r--r--app/views/shared/deploy_keys/_project_group_form.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_index.html.haml20
-rw-r--r--app/views/shared/doorkeeper/applications/_index.html.haml2
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml12
-rw-r--r--app/views/shared/issuable/_feed_buttons.html.haml8
-rw-r--r--app/views/shared/issuable/_form.html.haml4
-rw-r--r--app/views/shared/issuable/_label_page_create.html.haml4
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml9
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml4
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar_reviewers.html.haml5
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml6
-rw-r--r--app/views/shared/issue_type/_details_header.html.haml7
-rw-r--r--app/views/shared/issue_type/_emoji_block.html.haml4
-rw-r--r--app/views/shared/labels/_form.html.haml6
-rw-r--r--app/views/shared/members/_member.html.haml2
-rw-r--r--app/views/shared/members/_requests.html.haml2
-rw-r--r--app/views/shared/milestones/_issuables.html.haml28
-rw-r--r--app/views/shared/milestones/_participants_tab.html.haml8
-rw-r--r--app/views/shared/notes/_note.html.haml15
-rw-r--r--app/views/shared/projects/_project.html.haml12
-rw-r--r--app/views/shared/projects/_search_form.html.haml2
-rw-r--r--app/views/shared/runners/_runner_description.html.haml12
-rw-r--r--app/views/shared/runners/_shared_runners_description.html.haml7
-rw-r--r--app/views/shared/snippets/_snippet.html.haml25
-rw-r--r--app/views/shared/tokens/_scopes_form.html.haml3
-rw-r--r--app/views/shared/users/_user.html.haml2
-rw-r--r--app/views/shared/web_hooks/_form.html.haml13
-rw-r--r--app/views/shared/web_hooks/_hook_errors.html.haml12
-rw-r--r--app/views/shared/web_hooks/_index.html.haml25
-rw-r--r--app/views/shared/wikis/pages.html.haml4
-rw-r--r--app/views/snippets/show.html.haml2
-rw-r--r--app/workers/all_queues.yml126
-rw-r--r--app/workers/bulk_import_worker.rb5
-rw-r--r--app/workers/bulk_imports/entity_worker.rb26
-rw-r--r--app/workers/bulk_imports/export_request_worker.rb89
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb54
-rw-r--r--app/workers/ci/cancel_pipeline_worker.rb1
-rw-r--r--app/workers/ci/parse_secure_file_metadata_worker.rb15
-rw-r--r--app/workers/ci/pipeline_success_unlock_artifacts_worker.rb4
-rw-r--r--app/workers/clusters/applications/uninstall_worker.rb6
-rw-r--r--app/workers/concerns/application_worker.rb10
-rw-r--r--app/workers/concerns/gitlab/github_import/object_importer.rb34
-rw-r--r--app/workers/concerns/gitlab/github_import/stage_methods.rb4
-rw-r--r--app/workers/experiments/record_conversion_event_worker.rb22
-rw-r--r--app/workers/gitlab/github_import/attachments/import_issue_worker.rb23
-rw-r--r--app/workers/gitlab/github_import/attachments/import_merge_request_worker.rb23
-rw-r--r--app/workers/gitlab/github_import/attachments/import_note_worker.rb23
-rw-r--r--app/workers/gitlab/github_import/attachments/import_release_worker.rb23
-rw-r--r--app/workers/gitlab/github_import/import_issue_worker.rb4
-rw-r--r--app/workers/gitlab/github_import/import_release_attachments_worker.rb6
-rw-r--r--app/workers/gitlab/github_import/stage/import_attachments_worker.rb9
-rw-r--r--app/workers/gitlab/github_import/stage/import_issue_events_worker.rb14
-rw-r--r--app/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker.rb2
-rw-r--r--app/workers/gitlab/github_import/stage/import_notes_worker.rb2
-rw-r--r--app/workers/gitlab/github_import/stage/import_repository_worker.rb18
-rw-r--r--app/workers/incident_management/pager_duty/process_incident_worker.rb2
-rw-r--r--app/workers/incident_management/process_alert_worker_v2.rb4
-rw-r--r--app/workers/merge_requests/delete_source_branch_worker.rb6
-rw-r--r--app/workers/namespaces/onboarding_issue_created_worker.rb24
-rw-r--r--app/workers/namespaces/onboarding_pipeline_created_worker.rb24
-rw-r--r--app/workers/namespaces/onboarding_progress_worker.rb25
-rw-r--r--app/workers/namespaces/onboarding_user_added_worker.rb21
-rw-r--r--app/workers/onboarding/issue_created_worker.rb27
-rw-r--r--app/workers/onboarding/pipeline_created_worker.rb27
-rw-r--r--app/workers/onboarding/progress_worker.rb28
-rw-r--r--app/workers/onboarding/user_added_worker.rb24
-rw-r--r--app/workers/process_commit_worker.rb24
-rwxr-xr-xbin/diagnostic-reports-uploader29
-rwxr-xr-xbin/profile-url22
-rwxr-xr-xbin/rubocop-profile39
-rw-r--r--config/application.rb14
-rw-r--r--config/dependency_decisions.yml7
-rw-r--r--config/esbuild.config.js59
-rw-r--r--config/feature_categories.yml3
-rw-r--r--config/feature_flags/development/about_your_company_registration_flow.yml8
-rw-r--r--config/feature_flags/development/add_timing_to_certain_cache_actions.yml8
-rw-r--r--config/feature_flags/development/admin_runners_bulk_delete.yml8
-rw-r--r--config/feature_flags/development/agent_authorization_include_descendants.yml8
-rw-r--r--config/feature_flags/development/allow_non_blocking_member_refresh.yml8
-rw-r--r--config/feature_flags/development/approval_rules_eligible_filter.yml8
-rw-r--r--config/feature_flags/development/audit_invalid_approver_rules.yml8
-rw-r--r--config/feature_flags/development/block_emails_with_failures.yml8
-rw-r--r--config/feature_flags/development/bypass_batch_pop_queueing_for_merge_trains.yml8
-rw-r--r--config/feature_flags/development/cache_issue_sums.yml8
-rw-r--r--config/feature_flags/development/cascade_package_forwarding_settings.yml8
-rw-r--r--config/feature_flags/development/ci_inbound_job_token_scope.yml8
-rw-r--r--config/feature_flags/development/ci_increase_includes_to_250.yml8
-rw-r--r--config/feature_flags/development/ci_job_artifacts_cdn.yml8
-rw-r--r--config/feature_flags/development/ci_limit_active_jobs_early.yml8
-rw-r--r--config/feature_flags/development/ci_limit_complete_hierarchy_size.yml2
-rw-r--r--config/feature_flags/development/ci_project_pipeline_config_refactoring.yml8
-rw-r--r--config/feature_flags/development/ci_requeue_with_dag_object_hierarchy.yml2
-rw-r--r--config/feature_flags/development/ci_rules_changes_compare.yml8
-rw-r--r--config/feature_flags/development/ci_skip_auto_cancelation_on_child_pipelines.yml8
-rw-r--r--config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml8
-rw-r--r--config/feature_flags/development/ci_variables_refactoring_to_variable.yml8
-rw-r--r--config/feature_flags/development/content_editor_on_issues.yml8
-rw-r--r--config/feature_flags/development/contribution_analytics_optimized_base_query.yml8
-rw-r--r--config/feature_flags/development/counter_attribute_db_lease_for_update.yml8
-rw-r--r--config/feature_flags/development/disable_load_entire_blob_for_diff_viewer.yml8
-rw-r--r--config/feature_flags/development/enable_minor_delay_during_project_authorizations_refresh.yml8
-rw-r--r--config/feature_flags/development/enforce_runner_token_expires_at.yml8
-rw-r--r--config/feature_flags/development/escape_gitaly_refs.yml8
-rw-r--r--config/feature_flags/development/extract_mr_diff_deletions.yml8
-rw-r--r--config/feature_flags/development/forward_deployment_enabled.yml8
-rw-r--r--config/feature_flags/development/geo_container_repository_replication.yml8
-rw-r--r--config/feature_flags/development/gitlab_shell_jwt_token.yml8
-rw-r--r--config/feature_flags/development/gl_avatar_for_all_user_avatars.yml8
-rw-r--r--config/feature_flags/development/global_search_custom_slis.yml8
-rw-r--r--config/feature_flags/development/graphql_keyset_pagination_without_next_page_query.yml2
-rw-r--r--config/feature_flags/development/group_analytics_dashboards_page.yml8
-rw-r--r--config/feature_flags/development/hash_oauth_tokens.yml2
-rw-r--r--config/feature_flags/development/highlight_diffs_renewable_expiration.yml8
-rw-r--r--config/feature_flags/development/highlight_diffs_short_renewable_expiration.yml8
-rw-r--r--config/feature_flags/development/import_export_web_upload_stream.yml8
-rw-r--r--config/feature_flags/development/improve_blobs_cache_headers.yml8
-rw-r--r--config/feature_flags/development/incident_timeline.yml8
-rw-r--r--config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml8
-rw-r--r--config/feature_flags/development/incubation_5mp_google_cloud.yml2
-rw-r--r--config/feature_flags/development/indifferent_wal_location_keys.yml8
-rw-r--r--config/feature_flags/development/integration_slack_app_notifications.yml8
-rw-r--r--config/feature_flags/development/license_from_gitaly.yml8
-rw-r--r--config/feature_flags/development/limit_assignees_per_issuable.yml8
-rw-r--r--config/feature_flags/development/mergeability_checks_logger.yml8
-rw-r--r--config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml8
-rw-r--r--config/feature_flags/development/operational_vulnerabilities_filters.yml2
-rw-r--r--config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml8
-rw-r--r--config/feature_flags/development/pages_lets_encrypt_ecdsa.yml8
-rw-r--r--config/feature_flags/development/pipeline_name.yml8
-rw-r--r--config/feature_flags/development/pipeline_schedules_vue.yml8
-rw-r--r--config/feature_flags/development/present_groups_select_all.yml8
-rw-r--r--config/feature_flags/development/process_issue_closure_in_background.yml8
-rw-r--r--config/feature_flags/development/read_package_policy_rule.yml8
-rw-r--r--config/feature_flags/development/realtime_labels.yml2
-rw-r--r--config/feature_flags/development/refactor_mr_widgets_extensions.yml8
-rw-r--r--config/feature_flags/development/refactor_mr_widgets_extensions_user.yml8
-rw-r--r--config/feature_flags/development/remove_namespace_aggregator_delay.yml8
-rw-r--r--config/feature_flags/development/remove_user_attributes_groups.yml8
-rw-r--r--config/feature_flags/development/remove_user_attributes_projects.yml8
-rw-r--r--config/feature_flags/development/runner_registration_control.yml8
-rw-r--r--config/feature_flags/development/scan_execution_rule_mode.yml2
-rw-r--r--config/feature_flags/development/search_page_vertical_nav.yml8
-rw-r--r--config/feature_flags/development/secure_files_metadata_parsers.yml8
-rw-r--r--config/feature_flags/development/set_feature_flag_service.yml8
-rw-r--r--config/feature_flags/development/skip_checking_namespace_in_query.yml8
-rw-r--r--config/feature_flags/development/skip_scheduling_mirrors_for_free.yml8
-rw-r--r--config/feature_flags/development/track_delete_source_errors.yml8
-rw-r--r--config/feature_flags/development/trigger_mr_subscription_on_merge_status_change.yml8
-rw-r--r--config/feature_flags/development/usage_data_ci_i_testing_test_report_uploaded.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml8
-rw-r--r--config/feature_flags/development/use_gitaly_pagination_for_refs.yml8
-rw-r--r--config/feature_flags/development/vue_broadcast_messages.yml8
-rw-r--r--config/feature_flags/development/webhook_form_mask_url.yml8
-rw-r--r--config/feature_flags/development/wiki_find_page_with_normal_repository_rpcs.yml8
-rw-r--r--config/feature_flags/ops/github_importer_attachments_import.yml8
-rw-r--r--config/feature_flags/ops/github_importer_issue_events_import.yml8
-rw-r--r--config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml8
-rw-r--r--config/feature_flags/ops/github_importer_single_endpoint_notes_import.yml8
-rw-r--r--config/feature_flags/ops/increase_branch_cache_expiry.yml8
-rw-r--r--config/feature_flags/ops/jira_raise_timeouts.yml2
-rw-r--r--config/feature_flags/ops/sidekiq_memory_killer_read_only_mode.yml7
-rw-r--r--config/feature_flags/undefined/gitaly_simplify_find_local_branches_response.yml8
-rw-r--r--config/gitlab.yml.example5
-rw-r--r--config/gitlab_loose_foreign_keys.yml4
-rw-r--r--config/initializers/1_settings.rb11
-rw-r--r--config/initializers/7_redis.rb6
-rw-r--r--config/initializers/attr_encrypted_no_db_connection.rb44
-rw-r--r--config/initializers/attr_encrypted_thread_safe.rb17
-rw-r--r--config/initializers/countries.rb7
-rw-r--r--config/initializers/diagnostic_reports.rb4
-rw-r--r--config/initializers/licensee_license_patch.rb14
-rw-r--r--config/initializers/load_balancing.rb16
-rw-r--r--config/initializers/memory_watchdog.rb38
-rw-r--r--config/initializers/multi_json.rb7
-rw-r--r--config/initializers/omniauth.rb13
-rw-r--r--config/initializers/sawyer_patch.rb10
-rw-r--r--config/initializers/sidekiq.rb42
-rw-r--r--config/locales/doorkeeper.en.yml12
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/metrics/aggregates/code_review.yml246
-rw-r--r--config/metrics/aggregates/common.yml71
-rw-r--r--config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml10
-rw-r--r--config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml17
-rw-r--r--config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml24
-rw-r--r--config/metrics/counts_28d/20210216181939_releases.yml1
-rw-r--r--config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml5
-rwxr-xr-xconfig/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml10
-rw-r--r--config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml7
-rw-r--r--config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml127
-rw-r--r--config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml9
-rw-r--r--config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml120
-rw-r--r--config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210901223532_p_ci_templates_implicit_jobs_load_performance_testing_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223702_p_ci_templates_implicit_jobs_browser_performance_testing_latest_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223711_p_ci_templates_implicit_jobs_cf_provision_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223721_p_ci_templates_implicit_jobs_build_latest_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223730_p_ci_templates_implicit_security_dast_runner_validation_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223739_p_ci_templates_implicit_security_dast_on_demand_scan_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223758_p_ci_templates_implicit_security_coverage_fuzzing_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223806_p_ci_templates_implicit_security_api_fuzzing_latest_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223815_p_ci_templates_implicit_security_secure_binaries_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223824_p_ci_templates_implicit_security_dast_api_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223841_p_ci_templates_implicit_security_dast_latest_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210901223858_p_ci_templates_implicit_security_api_fuzzing_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20220222215951_xmau_plan.yml11
-rw-r--r--config/metrics/counts_28d/20220222215952_xmau_project_management.yml11
-rw-r--r--config/metrics/counts_28d/20220222215955_users_work_items.yml11
-rw-r--r--config/metrics/counts_28d/20220310213320_p_ci_templates_implicit_jobs_secret_detection_latest_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220310213749_p_ci_templates_implicit_jobs_sast_latest_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20220315223227_error_tracking_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20220906065651_incident_management_timeline_event_created_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20220906070355_incident_management_timeline_event_edited_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20220906070634_incident_management_timeline_event_deleted_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20220907032044_i_quickactions_ready_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220907084347_p_ci_templates_implicit_security_sast_iac_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220907102714_p_ci_templates_implicit_jobs_sast_iac_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml11
-rw-r--r--config/metrics/counts_28d/20220913225020_p_ci_templates_security_coverage_fuzzing_latest_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220913225303_p_ci_templates_implicit_security_coverage_fuzzing_latest_monthly.yml27
-rw-r--r--config/metrics/counts_28d/20220922042106_users_updating_work_item_iteration_monthly.yml24
-rw-r--r--config/metrics/counts_28d/20221006065524_i_quickactions_link_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20221007011350_users_updating_work_item_labels_monthly.yml25
-rw-r--r--config/metrics/counts_7d/20210216174908_analytics_unique_visits_for_any_target.yml5
-rw-r--r--config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml10
-rw-r--r--config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml17
-rw-r--r--config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml24
-rw-r--r--config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml5
-rwxr-xr-xconfig/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml6
-rw-r--r--config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml8
-rw-r--r--config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml120
-rw-r--r--config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml117
-rw-r--r--config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml9
-rw-r--r--config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210901223528_p_ci_templates_implicit_jobs_load_performance_testing_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223658_p_ci_templates_implicit_jobs_browser_performance_testing_latest_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223707_p_ci_templates_implicit_jobs_cf_provision_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223716_p_ci_templates_implicit_jobs_build_latest_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223725_p_ci_templates_implicit_security_dast_runner_validation_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223735_p_ci_templates_implicit_security_dast_on_demand_scan_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223753_p_ci_templates_implicit_security_coverage_fuzzing_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223802_p_ci_templates_implicit_security_api_fuzzing_latest_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223811_p_ci_templates_implicit_security_secure_binaries_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223819_p_ci_templates_implicit_security_dast_api_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223837_p_ci_templates_implicit_security_dast_latest_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210901223854_p_ci_templates_implicit_security_api_fuzzing_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210929102731_p_ci_templates_implicit_jobs_deploy_latest_weekly.yml8
-rw-r--r--config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml8
-rw-r--r--config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml8
-rw-r--r--config/metrics/counts_7d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20220222215851_xmau_plan.yml13
-rw-r--r--config/metrics/counts_7d/20220222215852_xmau_project_management.yml11
-rw-r--r--config/metrics/counts_7d/20220222215855_users_work_items.yml11
-rw-r--r--config/metrics/counts_7d/20220310213315_p_ci_templates_implicit_jobs_secret_detection_latest_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220310213743_p_ci_templates_implicit_jobs_sast_latest_weekly.yml8
-rw-r--r--config/metrics/counts_7d/20220315223220_error_tracking_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml6
-rw-r--r--config/metrics/counts_7d/20220906065645_incident_management_timeline_event_created_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20220906070351_incident_management_timeline_event_edited_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20220906070629_incident_management_timeline_event_deleted_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20220907032041_i_quickactions_ready_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220907084343_p_ci_templates_implicit_security_sast_iac_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220907102710_p_ci_templates_implicit_jobs_sast_iac_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml11
-rw-r--r--config/metrics/counts_7d/20220913225013_p_ci_templates_security_coverage_fuzzing_latest_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220913225257_p_ci_templates_implicit_security_coverage_fuzzing_latest_weekly.yml27
-rw-r--r--config/metrics/counts_7d/20220922042528_users_updating_work_item_iteration_weekly.yml24
-rw-r--r--config/metrics/counts_7d/20221006065521_i_quickactions_link_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20221007010950_users_updating_work_item_labels_weekly.yml25
-rw-r--r--config/metrics/counts_all/20210216174832_cycle_analytics_views.yml4
-rw-r--r--config/metrics/counts_all/20210216175041_merge_request_comment.yml4
-rw-r--r--config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml6
-rw-r--r--config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml6
-rw-r--r--config/metrics/counts_all/20210216175446_network_policy_forwards.yml6
-rw-r--r--config/metrics/counts_all/20210216175448_network_policy_drops.yml6
-rw-r--r--config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml6
-rw-r--r--config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml6
-rw-r--r--config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml6
-rw-r--r--config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml6
-rw-r--r--config/metrics/counts_all/20210216180253_snippet_comment.yml4
-rw-r--r--config/metrics/counts_all/20210216180255_snippet_create.yml4
-rw-r--r--config/metrics/counts_all/20210216180257_snippet_update.yml4
-rw-r--r--config/metrics/counts_all/20210216180413_all_searches.yml5
-rw-r--r--config/metrics/counts_all/20210216180414_navbar_searches.yml5
-rw-r--r--config/metrics/counts_all/20210216180734_wiki_pages_create.yml4
-rw-r--r--config/metrics/counts_all/20210216180736_wiki_pages_update.yml4
-rw-r--r--config/metrics/counts_all/20210216180738_wiki_pages_delete.yml4
-rw-r--r--config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml1
-rw-r--r--config/metrics/counts_all/20210216182004_commit_comment.yml4
-rw-r--r--config/metrics/counts_all/20210216183023_wiki_pages_view.yml4
-rw-r--r--config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml4
-rw-r--r--config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml5
-rw-r--r--config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml5
-rw-r--r--config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml5
-rw-r--r--config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml5
-rw-r--r--config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml5
-rw-r--r--config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml5
-rw-r--r--config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml5
-rw-r--r--config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml5
-rw-r--r--config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml5
-rw-r--r--config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml5
-rw-r--r--config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml5
-rw-r--r--config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml5
-rw-r--r--config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml5
-rw-r--r--config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml5
-rw-r--r--config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml5
-rw-r--r--config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml5
-rw-r--r--config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml5
-rw-r--r--config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml5
-rw-r--r--config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml5
-rw-r--r--config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml5
-rw-r--r--config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml5
-rw-r--r--config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml5
-rw-r--r--config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml5
-rw-r--r--config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml5
-rw-r--r--config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml5
-rw-r--r--config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml5
-rw-r--r--config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml5
-rw-r--r--config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml5
-rw-r--r--config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml5
-rw-r--r--config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml5
-rw-r--r--config/metrics/counts_all/20220912145754_gitlab_for_jira_app_direct_installations.yml23
-rw-r--r--config/metrics/counts_all/20220913083454_gitlab_for_jira_app_proxy_installations.yml23
-rw-r--r--config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml6
-rw-r--r--config/metrics/settings/20211201012652_flavor.yml2
-rw-r--r--config/object_store_settings.rb2
-rw-r--r--config/open_api.yml18
-rw-r--r--config/plugins/monaco_webpack.js17
-rw-r--r--config/routes.rb27
-rw-r--r--config/routes/import.rb5
-rw-r--r--config/routes/jira_connect.rb1
-rw-r--r--config/routes/project.rb14
-rw-r--r--config/routes/user.rb1
-rw-r--r--config/sidekiq_queues.yml34
-rw-r--r--config/webpack.config.js92
-rw-r--r--config/webpack.vendor.config.js4
-rw-r--r--danger/documentation/Dangerfile2
-rw-r--r--danger/roulette/Dangerfile4
-rw-r--r--danger/specs/Dangerfile1
-rw-r--r--data/deprecations/14-5-runner-api-status-does-contain-paused.yml5
-rw-r--r--data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml21
-rw-r--r--data/deprecations/14-8-runner-api-project_type-breaking-change.yml15
-rw-r--r--data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml11
-rw-r--r--data/deprecations/15-5-confidential-field-on-notes.yml12
-rw-r--r--data/deprecations/15-5-vulnerabilityFindingDismiss-mutation.yml13
-rw-r--r--data/deprecations/templates/_deprecation_template.md.erb2
-rw-r--r--data/removals/templates/_removal_template.md.erb2
-rw-r--r--db/docs/ci_pipeline_metadata.yml9
-rw-r--r--db/docs/incident_management_timeline_event_tag_links.yml9
-rw-r--r--db/docs/incident_management_timeline_event_tags.yml9
-rw-r--r--db/docs/packages_rpm_repository_files.yml9
-rw-r--r--db/docs/project_wiki_repository_states.yml9
-rw-r--r--db/docs/push_rules.yml2
-rw-r--r--db/docs/sbom_component_versions.yml4
-rw-r--r--db/docs/sbom_components.yml4
-rw-r--r--db/docs/sbom_occurrences.yml4
-rw-r--r--db/docs/sbom_sources.yml4
-rw-r--r--db/docs/sbom_vulnerable_component_versions.yml4
-rw-r--r--db/docs/user_phone_number_validations.yml9
-rw-r--r--db/migrate/20220126191624_add_scan_file_path_to_dast_site_profile.rb14
-rw-r--r--db/migrate/20220615172230_add_user_preference_to_turn_off_automatic_lists.rb13
-rw-r--r--db/migrate/20220802200719_add_user_details_profile_fields.rb17
-rw-r--r--db/migrate/20220802202505_add_user_details_field_limits.rb25
-rw-r--r--db/migrate/20220805180311_add_unique_index_on_sbom_component_type_and_name.rb15
-rw-r--r--db/migrate/20220805183952_add_unique_index_to_sbom_component_versions_on_component_id_and_version.rb15
-rw-r--r--db/migrate/20220805193117_add_unique_index_to_sbom_sources_on_source_type_and_source.rb15
-rw-r--r--db/migrate/20220818125332_add_jitsu_tracking_columns_to_application_settings.rb15
-rw-r--r--db/migrate/20220818125703_add_jitsu_tracking_columns_to_application_settings_text_limits.rb19
-rw-r--r--db/migrate/20220818140553_add_unique_index_to_sbom_occurrences_on_ingestion_attributes.rb22
-rw-r--r--db/migrate/20220819184945_add_dashboard_limit_to_application_settings.rb11
-rw-r--r--db/migrate/20220901090004_add_can_create_group_to_application_settings.rb7
-rw-r--r--db/migrate/20220901092853_update_can_create_group_application_setting.rb26
-rw-r--r--db/migrate/20220901114501_only_allow_merge_if_all_status_checks_passed.rb7
-rw-r--r--db/migrate/20220907115806_add_security_orchestration_policy_configuration_id.rb58
-rw-r--r--db/migrate/20220912153839_create_packages_rpm_repository_file.rb25
-rw-r--r--db/migrate/20220913043728_create_user_phone_number_validations.rb29
-rw-r--r--db/migrate/20220913082824_finalize_invalid_group_member_cleanup.rb19
-rw-r--r--db/migrate/20220913084123_add_timestamp_to_ml_candidate_metrics.rb7
-rw-r--r--db/migrate/20220914070927_finalize_invalid_project_member_cleanup.rb19
-rw-r--r--db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb15
-rw-r--r--db/migrate/20220914112457_add_reject_non_dco_commits_to_push_rules.rb7
-rw-r--r--db/migrate/20220914130800_add_jitsu_key_to_projects.rb20
-rw-r--r--db/migrate/20220914131449_add_text_limit_to_projects_jitsu_key.rb13
-rw-r--r--db/migrate/20220914174705_remove_not_null_constraint_from_sbom_source_fingerprint.rb9
-rw-r--r--db/migrate/20220916094641_add_source_id_to_bulk_import_entities.rb7
-rw-r--r--db/migrate/20220916103311_add_index_on_jira_connect_installations_instance_url.rb15
-rw-r--r--db/migrate/20220918124223_add_suggested_reviewers_enabled_to_project_settings.rb9
-rw-r--r--db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb21
-rw-r--r--db/migrate/20220920022404_remove_temp_index_null_project_namespace_id.rb15
-rw-r--r--db/migrate/20220921174815_add_secure_files_metadata.rb8
-rw-r--r--db/migrate/20220921201347_add_maven_package_requests_forwarding_to_namespace_package_settings.rb28
-rw-r--r--db/migrate/20220922143612_add_inbound_ci_job_token_project_scope_links.rb13
-rw-r--r--db/migrate/20220923103006_add_ci_pipeline_metadata_title.rb27
-rw-r--r--db/migrate/20220927155407_add_column_inbound_job_token_scope_enabled_to_ci_cd_setting.rb13
-rw-r--r--db/migrate/20220928201920_create_project_wiki_repository_states.rb44
-rw-r--r--db/migrate/20220929171925_add_pypi_package_requests_forwarding_to_namespace_package_settings.rb28
-rw-r--r--db/migrate/20220929172356_add_npm_package_requests_forwarding_to_namespace_package_settings.rb28
-rw-r--r--db/migrate/20220930125609_add_migrated_to_state_transition_to_vulnerability_feedback.rb7
-rw-r--r--db/migrate/20221005072353_create_incident_management_timeline_event_tags.rb19
-rw-r--r--db/migrate/20221005094926_create_incident_management_timeline_event_tag_links.rb33
-rw-r--r--db/migrate/20221005103010_add_index_project_id_on_scan_finding_approval_project_rules.rb22
-rw-r--r--db/migrate/20221006131506_add_free_user_cap_over_limit_notified_at_to_namespace_details.rb20
-rw-r--r--db/migrate/20221006141145_add_targets_to_elastic_reindexing_tasks.rb7
-rw-r--r--db/migrate/20221008032350_add_password_expiration_migration.rb12
-rw-r--r--db/migrate/20221009085130_add_mr_checks_columns_to_namespace_settings.rb10
-rw-r--r--db/migrate/20221011162637_add_partial_index_project_incident_management_settings_on_project_id_and_sla_timer.rb17
-rw-r--r--db/migrate/20221011210455_add_use_legacy_web_ide_to_user_preferences.rb9
-rw-r--r--db/migrate/20221012033107_add_password_last_changed_at_to_user_details.rb9
-rw-r--r--db/migrate/20221012135524_add_scan_file_path_limit_for_dast_site_profile.rb13
-rw-r--r--db/migrate/20221014031033_add_temp_index_to_project_features_where_releases_access_level_gt_repository.rb19
-rw-r--r--db/migrate/20221014034338_populate_releases_access_level_from_repository.rb21
-rw-r--r--db/migrate/20221014190040_drop_notes_note_trigram_index.rb17
-rw-r--r--db/migrate/20221018081416_members_remove_member_namespace_id_not_null_constraint.rb15
-rw-r--r--db/post_migrate/20220809002011_schedule_destroy_invalid_group_members.rb14
-rw-r--r--db/post_migrate/20220831090454_cleanup_web_hooks_service_id.rb13
-rw-r--r--db/post_migrate/20220901035725_schedule_destroy_invalid_project_members.rb14
-rw-r--r--db/post_migrate/20220905120848_backfill_epic_cache_counts.rb29
-rw-r--r--db/post_migrate/20220907122648_populate_security_orchestration_policy_configuration_id.rb38
-rw-r--r--db/post_migrate/20220915192521_prepare_async_trigram_index_for_vulnerability_reads_container_images.rb19
-rw-r--r--db/post_migrate/20220916054103_remove_experience_level_column.rb13
-rw-r--r--db/post_migrate/20220916065418_add_index_id_partition_id_to_ci_builds_metadata.rb16
-rw-r--r--db/post_migrate/20220916070101_add_index_build_id_partition_id_to_ci_build_metadata.rb16
-rw-r--r--db/post_migrate/20220919023208_drop_unused_fields_from_merge_request_assignees.rb40
-rw-r--r--db/post_migrate/20220919041604_drop_unused_fields_from_merge_request_reviewers.rb26
-rw-r--r--db/post_migrate/20220919050555_drop_tmp_index_user_callouts_on_attention_request_feature_names.rb18
-rw-r--r--db/post_migrate/20220920081631_prepare_ci_builds_metadata_for_partitioning_primary_key.rb36
-rw-r--r--db/post_migrate/20220920122121_schedule_index_removal_for_ci_builds_metadata.rb16
-rw-r--r--db/post_migrate/20220920124709_backfill_internal_on_notes.rb26
-rw-r--r--db/post_migrate/20220920135356_tiebreak_user_type_index.rb18
-rw-r--r--db/post_migrate/20220920141001_add_index_on_internal_notes.rb15
-rw-r--r--db/post_migrate/20220920213504_finalize_task_system_note_renaming.rb11
-rw-r--r--db/post_migrate/20220920214524_remove_task_system_note_rename_temp_index.rb11
-rw-r--r--db/post_migrate/20220921093355_schedule_backfill_namespace_details.rb29
-rw-r--r--db/post_migrate/20220921111823_remove_and_add_ci_pipeline_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921111831_remove_and_add_ci_group_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921111840_remove_and_add_ci_instance_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921111849_remove_and_add_ci_job_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921111857_remove_and_add_ci_pipeline_schedule_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921111907_remove_and_add_ci_variables_raw_with_new_default.rb10
-rw-r--r--db/post_migrate/20220921144258_remove_orphan_group_token_users.rb40
-rw-r--r--db/post_migrate/20220922090236_remove_trace_column_from_ci_builds.rb9
-rw-r--r--db/post_migrate/20220922143143_schedule_reset_duplicate_ci_runners_token_values.rb28
-rw-r--r--db/post_migrate/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values.rb28
-rw-r--r--db/post_migrate/20220922204106_remove_index_for_requested_non_invited_awaiting_members.rb17
-rw-r--r--db/post_migrate/20220923052531_remove_tmp_index_merge_request_reviewers_on_attention_requested_state.rb18
-rw-r--r--db/post_migrate/20220923060226_remove_tmp_index_system_note_metadata_on_attention_request_actions.rb17
-rw-r--r--db/post_migrate/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status.rb27
-rw-r--r--db/post_migrate/20220929081645_tmp_idx_null_member_namespace_id.rb17
-rw-r--r--db/post_migrate/20220929091500_add_tmp_index_vulns_on_report_type.rb22
-rw-r--r--db/post_migrate/20220929101947_delete_remove_invalid_member_migration.rb19
-rw-r--r--db/post_migrate/20220929194453_add_index_releases_project_id_id.rb15
-rw-r--r--db/post_migrate/20220929213730_schedule_delete_orphaned_operational_vulnerabilities.rb25
-rw-r--r--db/post_migrate/20220930110127_remove_unique_index_build_id_to_ci_builds_metadata.rb16
-rw-r--r--db/post_migrate/20221003192827_add_index_resolved_on_default_branch_to_vulnerabilities_read.rb18
-rw-r--r--db/post_migrate/20221004092038_tmp_index_members_on_id_where_namespace_id_null.rb17
-rw-r--r--db/post_migrate/20221004094814_schedule_destroy_invalid_members.rb27
-rw-r--r--db/post_migrate/20221005103000_add_index_merge_request_id_on_scan_finding_approval_merge_request_rules.rb17
-rw-r--r--db/post_migrate/20221006083240_prepare_partial_trigram_indexes_for_issues_attempt_2.rb25
-rw-r--r--db/post_migrate/20221006172302_adjust_task_note_rename_background_migration_values.rb72
-rw-r--r--db/post_migrate/20221010074914_migrate_security_findings_delete_queues.rb16
-rw-r--r--db/post_migrate/20221010121510_prepare_async_index_author_id_target_project_id_on_merge_requests.rb15
-rw-r--r--db/post_migrate/20221010121807_add_compliance_framework_id_to_namespace_settings.rb7
-rw-r--r--db/post_migrate/20221010122138_add_async_index_author_id_target_project_id_on_merge_requests.rb15
-rw-r--r--db/post_migrate/20221010122352_add_index_to_namespace_settings_on_default_compliance_framework_id.rb15
-rw-r--r--db/post_migrate/20221010123040_add_compliance_framework_fk_to_namespace_settings.rb16
-rw-r--r--db/post_migrate/20221011113928_redo_remove_and_add_ci_job_variables_raw_with_new_default.rb12
-rw-r--r--db/post_migrate/20221012182701_remove_namespace_settings_cohort_free_user_cap_columns.rb15
-rw-r--r--db/post_migrate/20221013154159_update_invalid_dormant_user_setting.rb17
-rw-r--r--db/schema.rb5
-rw-r--r--db/schema_migrations/202201261916241
-rw-r--r--db/schema_migrations/202206151722301
-rw-r--r--db/schema_migrations/202208022007191
-rw-r--r--db/schema_migrations/202208022025051
-rw-r--r--db/schema_migrations/202208051803111
-rw-r--r--db/schema_migrations/202208051839521
-rw-r--r--db/schema_migrations/202208051931171
-rw-r--r--db/schema_migrations/202208181253321
-rw-r--r--db/schema_migrations/202208181257031
-rw-r--r--db/schema_migrations/202208181405531
-rw-r--r--db/schema_migrations/202208191849451
-rw-r--r--db/schema_migrations/202208310904541
-rw-r--r--db/schema_migrations/202209010900041
-rw-r--r--db/schema_migrations/202209010928531
-rw-r--r--db/schema_migrations/202209011145011
-rw-r--r--db/schema_migrations/202209051208481
-rw-r--r--db/schema_migrations/202209071158061
-rw-r--r--db/schema_migrations/202209071226481
-rw-r--r--db/schema_migrations/202209121538391
-rw-r--r--db/schema_migrations/202209130437281
-rw-r--r--db/schema_migrations/202209130828241
-rw-r--r--db/schema_migrations/202209130841231
-rw-r--r--db/schema_migrations/202209140709271
-rw-r--r--db/schema_migrations/202209140807161
-rw-r--r--db/schema_migrations/202209141124571
-rw-r--r--db/schema_migrations/202209141308001
-rw-r--r--db/schema_migrations/202209141314491
-rw-r--r--db/schema_migrations/202209141747051
-rw-r--r--db/schema_migrations/202209151925211
-rw-r--r--db/schema_migrations/202209160541031
-rw-r--r--db/schema_migrations/202209160654181
-rw-r--r--db/schema_migrations/202209160701011
-rw-r--r--db/schema_migrations/202209160946411
-rw-r--r--db/schema_migrations/202209161033111
-rw-r--r--db/schema_migrations/202209181242231
-rw-r--r--db/schema_migrations/202209190232081
-rw-r--r--db/schema_migrations/202209190416041
-rw-r--r--db/schema_migrations/202209190505551
-rw-r--r--db/schema_migrations/202209192256311
-rw-r--r--db/schema_migrations/202209200224041
-rw-r--r--db/schema_migrations/202209200816311
-rw-r--r--db/schema_migrations/202209201221211
-rw-r--r--db/schema_migrations/202209201247091
-rw-r--r--db/schema_migrations/202209201353561
-rw-r--r--db/schema_migrations/202209201410011
-rw-r--r--db/schema_migrations/202209202135041
-rw-r--r--db/schema_migrations/202209202145241
-rw-r--r--db/schema_migrations/202209210933551
-rw-r--r--db/schema_migrations/202209211118231
-rw-r--r--db/schema_migrations/202209211118311
-rw-r--r--db/schema_migrations/202209211118401
-rw-r--r--db/schema_migrations/202209211118491
-rw-r--r--db/schema_migrations/202209211118571
-rw-r--r--db/schema_migrations/202209211119071
-rw-r--r--db/schema_migrations/202209211442581
-rw-r--r--db/schema_migrations/202209211748151
-rw-r--r--db/schema_migrations/202209212013471
-rw-r--r--db/schema_migrations/202209220902361
-rw-r--r--db/schema_migrations/202209221431431
-rw-r--r--db/schema_migrations/202209221436121
-rw-r--r--db/schema_migrations/202209221436341
-rw-r--r--db/schema_migrations/202209222041061
-rw-r--r--db/schema_migrations/202209230525311
-rw-r--r--db/schema_migrations/202209230602261
-rw-r--r--db/schema_migrations/202209231030061
-rw-r--r--db/schema_migrations/202209271554071
-rw-r--r--db/schema_migrations/202209282019201
-rw-r--r--db/schema_migrations/202209282257111
-rw-r--r--db/schema_migrations/202209290816451
-rw-r--r--db/schema_migrations/202209290915001
-rw-r--r--db/schema_migrations/202209291019471
-rw-r--r--db/schema_migrations/202209291719251
-rw-r--r--db/schema_migrations/202209291723561
-rw-r--r--db/schema_migrations/202209291944531
-rw-r--r--db/schema_migrations/202209292137301
-rw-r--r--db/schema_migrations/202209301101271
-rw-r--r--db/schema_migrations/202209301256091
-rw-r--r--db/schema_migrations/202210031928271
-rw-r--r--db/schema_migrations/202210040920381
-rw-r--r--db/schema_migrations/202210040948141
-rw-r--r--db/schema_migrations/202210050723531
-rw-r--r--db/schema_migrations/202210050949261
-rw-r--r--db/schema_migrations/202210051030001
-rw-r--r--db/schema_migrations/202210051030101
-rw-r--r--db/schema_migrations/202210060832401
-rw-r--r--db/schema_migrations/202210061315061
-rw-r--r--db/schema_migrations/202210061411451
-rw-r--r--db/schema_migrations/202210061723021
-rw-r--r--db/schema_migrations/202210080323501
-rw-r--r--db/schema_migrations/202210090851301
-rw-r--r--db/schema_migrations/202210100749141
-rw-r--r--db/schema_migrations/202210101215101
-rw-r--r--db/schema_migrations/202210101218071
-rw-r--r--db/schema_migrations/202210101221381
-rw-r--r--db/schema_migrations/202210101223521
-rw-r--r--db/schema_migrations/202210101230401
-rw-r--r--db/schema_migrations/202210111139281
-rw-r--r--db/schema_migrations/202210111626371
-rw-r--r--db/schema_migrations/202210112104551
-rw-r--r--db/schema_migrations/202210120331071
-rw-r--r--db/schema_migrations/202210121355241
-rw-r--r--db/schema_migrations/202210121827011
-rw-r--r--db/schema_migrations/202210131541591
-rw-r--r--db/schema_migrations/202210140310331
-rw-r--r--db/schema_migrations/202210140343381
-rw-r--r--db/schema_migrations/202210141900401
-rw-r--r--db/schema_migrations/202210180814161
-rw-r--r--db/structure.sql406
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt4
-rw-r--r--doc/administration/application_settings_cache.md2
-rw-r--r--doc/administration/audit_event_streaming.md48
-rw-r--r--doc/administration/audit_events.md2
-rw-r--r--doc/administration/audit_reports.md2
-rw-r--r--doc/administration/auditor_users.md2
-rw-r--r--doc/administration/auth/atlassian.md14
-rw-r--r--doc/administration/auth/authentiq.md26
-rw-r--r--doc/administration/auth/cognito.md53
-rw-r--r--doc/administration/auth/crowd.md2
-rw-r--r--doc/administration/auth/index.md2
-rw-r--r--doc/administration/auth/jwt.md2
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md8
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md35
-rw-r--r--doc/administration/auth/ldap/ldap_synchronization.md2
-rw-r--r--doc/administration/auth/oidc.md283
-rw-r--r--doc/administration/auth/smartcard.md6
-rw-r--r--doc/administration/cicd.md5
-rw-r--r--doc/administration/clusters/kas.md37
-rw-r--r--doc/administration/compliance.md6
-rw-r--r--doc/administration/configure.md2
-rw-r--r--doc/administration/consul.md2
-rw-r--r--doc/administration/docs_self_host.md4
-rw-r--r--doc/administration/encrypted_configuration.md8
-rw-r--r--doc/administration/environment_variables.md2
-rw-r--r--doc/administration/external_pipeline_validation.md2
-rw-r--r--doc/administration/feature_flags.md7
-rw-r--r--doc/administration/file_hooks.md2
-rw-r--r--doc/administration/geo/disaster_recovery/background_verification.md2
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md2
-rw-r--r--doc/administration/geo/disaster_recovery/index.md12
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md4
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md4
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md4
-rw-r--r--doc/administration/geo/glossary.md2
-rw-r--r--doc/administration/geo/index.md3
-rw-r--r--doc/administration/geo/replication/configuration.md2
-rw-r--r--doc/administration/geo/replication/container_registry.md2
-rw-r--r--doc/administration/geo/replication/datatypes.md19
-rw-r--r--doc/administration/geo/replication/disable_geo.md4
-rw-r--r--doc/administration/geo/replication/faq.md4
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md2
-rw-r--r--doc/administration/geo/replication/location_aware_git_url.md2
-rw-r--r--doc/administration/geo/replication/multiple_servers.md4
-rw-r--r--doc/administration/geo/replication/object_storage.md2
-rw-r--r--doc/administration/geo/replication/remove_geo_site.md2
-rw-r--r--doc/administration/geo/replication/security_review.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md163
-rw-r--r--doc/administration/geo/replication/tuning.md2
-rw-r--r--doc/administration/geo/replication/upgrading_the_geo_sites.md2
-rw-r--r--doc/administration/geo/replication/usage.md2
-rw-r--r--doc/administration/geo/replication/version_specific_upgrades.md16
-rw-r--r--doc/administration/geo/secondary_proxy/index.md9
-rw-r--r--doc/administration/geo/secondary_proxy/location_aware_external_url.md2
-rw-r--r--doc/administration/geo/setup/database.md2
-rw-r--r--doc/administration/geo/setup/external_database.md9
-rw-r--r--doc/administration/geo/setup/index.md6
-rw-r--r--doc/administration/get_started.md4
-rw-r--r--doc/administration/git_protocol.md4
-rw-r--r--doc/administration/gitaly/configure_gitaly.md7
-rw-r--r--doc/administration/gitaly/faq.md6
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/administration/gitaly/monitoring.md2
-rw-r--r--doc/administration/gitaly/praefect.md4
-rw-r--r--doc/administration/gitaly/recovery.md73
-rw-r--r--doc/administration/gitaly/reference.md2
-rw-r--r--doc/administration/gitaly/troubleshooting.md22
-rw-r--r--doc/administration/housekeeping.md2
-rw-r--r--doc/administration/inactive_project_deletion.md2
-rw-r--r--doc/administration/incoming_email.md8
-rw-r--r--doc/administration/index.md4
-rw-r--r--doc/administration/instance_limits.md27
-rw-r--r--doc/administration/instance_review.md2
-rw-r--r--doc/administration/integration/kroki.md4
-rw-r--r--doc/administration/integration/mailgun.md4
-rw-r--r--doc/administration/integration/plantuml.md2
-rw-r--r--doc/administration/integration/terminal.md2
-rw-r--r--doc/administration/invalidate_markdown_cache.md2
-rw-r--r--doc/administration/issue_closing_pattern.md2
-rw-r--r--doc/administration/job_artifacts.md4
-rw-r--r--doc/administration/job_logs.md2
-rw-r--r--doc/administration/lfs/index.md3
-rw-r--r--doc/administration/libravatar.md2
-rw-r--r--doc/administration/load_balancer.md2
-rw-r--r--doc/administration/logs/index.md2
-rw-r--r--doc/administration/logs/log_parsing.md2
-rw-r--r--doc/administration/logs/tracing_correlation_id.md6
-rw-r--r--doc/administration/maintenance_mode/index.md10
-rw-r--r--doc/administration/merge_request_diffs.md10
-rw-r--r--doc/administration/monitoring/github_imports.md2
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md2
-rw-r--r--doc/administration/monitoring/index.md4
-rw-r--r--doc/administration/monitoring/ip_allowlist.md8
-rw-r--r--doc/administration/monitoring/ip_whitelist.md11
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md4
-rw-r--r--doc/administration/monitoring/performance/index.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md2
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md12
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md10
-rw-r--r--doc/administration/monitoring/prometheus/index.md8
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/puma_exporter.md11
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/registry_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/web_exporter.md2
-rw-r--r--doc/administration/nfs.md2
-rw-r--r--doc/administration/object_storage.md18
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md4
-rw-r--r--doc/administration/operations/filesystem_benchmarking.md2
-rw-r--r--doc/administration/operations/index.md2
-rw-r--r--doc/administration/operations/moving_repositories.md2
-rw-r--r--doc/administration/operations/puma.md4
-rw-r--r--doc/administration/operations/rails_console.md38
-rw-r--r--doc/administration/operations/ssh_certificates.md8
-rw-r--r--doc/administration/package_information/defaults.md2
-rw-r--r--doc/administration/package_information/deprecation_policy.md2
-rw-r--r--doc/administration/package_information/index.md6
-rw-r--r--doc/administration/package_information/licensing.md2
-rw-r--r--doc/administration/package_information/omnibus_packages.md2
-rw-r--r--doc/administration/package_information/postgresql_versions.md2
-rw-r--r--doc/administration/package_information/signed_packages.md2
-rw-r--r--doc/administration/package_information/supported_os.md3
-rw-r--r--doc/administration/packages/container_registry.md49
-rw-r--r--doc/administration/packages/dependency_proxy.md2
-rw-r--r--doc/administration/packages/index.md2
-rw-r--r--doc/administration/pages/index.md21
-rw-r--r--doc/administration/pages/source.md2
-rw-r--r--doc/administration/polling.md2
-rw-r--r--doc/administration/postgresql/database_load_balancing.md2
-rw-r--r--doc/administration/postgresql/external.md4
-rw-r--r--doc/administration/postgresql/index.md2
-rw-r--r--doc/administration/postgresql/moving.md2
-rw-r--r--doc/administration/postgresql/pgbouncer.md2
-rw-r--r--doc/administration/postgresql/replication_and_failover.md4
-rw-r--r--doc/administration/postgresql/standalone.md2
-rw-r--r--doc/administration/pseudonymizer.md14
-rw-r--r--doc/administration/raketasks/check.md2
-rw-r--r--doc/administration/raketasks/geo.md2
-rw-r--r--doc/administration/raketasks/github_import.md2
-rw-r--r--doc/administration/raketasks/ldap.md2
-rw-r--r--doc/administration/raketasks/maintenance.md8
-rw-r--r--doc/administration/raketasks/praefect.md2
-rw-r--r--doc/administration/raketasks/project_import_export.md2
-rw-r--r--doc/administration/raketasks/smtp.md2
-rw-r--r--doc/administration/raketasks/storage.md7
-rw-r--r--doc/administration/raketasks/uploads/migrate.md35
-rw-r--r--doc/administration/raketasks/uploads/sanitize.md2
-rw-r--r--doc/administration/read_only_gitlab.md2
-rw-r--r--doc/administration/redis/index.md2
-rw-r--r--doc/administration/redis/replication_and_failover.md2
-rw-r--r--doc/administration/redis/replication_and_failover_external.md2
-rw-r--r--doc/administration/redis/standalone.md2
-rw-r--r--doc/administration/redis/troubleshooting.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md127
-rw-r--r--doc/administration/reference_architectures/1k_users.md11
-rw-r--r--doc/administration/reference_architectures/25k_users.md126
-rw-r--r--doc/administration/reference_architectures/2k_users.md64
-rw-r--r--doc/administration/reference_architectures/3k_users.md120
-rw-r--r--doc/administration/reference_architectures/50k_users.md126
-rw-r--r--doc/administration/reference_architectures/5k_users.md112
-rw-r--r--doc/administration/reference_architectures/img/reference-architectures.pngbin12585 -> 0 bytes
-rw-r--r--doc/administration/reference_architectures/index.md388
-rw-r--r--doc/administration/reply_by_email.md4
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md2
-rw-r--r--doc/administration/repository_checks.md2
-rw-r--r--doc/administration/repository_storage_paths.md2
-rw-r--r--doc/administration/repository_storage_types.md6
-rw-r--r--doc/administration/restart_gitlab.md4
-rw-r--r--doc/administration/server_hooks.md2
-rw-r--r--doc/administration/sidekiq/extra_sidekiq_processes.md5
-rw-r--r--doc/administration/sidekiq/extra_sidekiq_routing.md19
-rw-r--r--doc/administration/sidekiq/index.md6
-rw-r--r--doc/administration/sidekiq/sidekiq_health_check.md2
-rw-r--r--doc/administration/sidekiq/sidekiq_job_migration.md2
-rw-r--r--doc/administration/sidekiq/sidekiq_memory_killer.md24
-rw-r--r--doc/administration/sidekiq/sidekiq_troubleshooting.md4
-rw-r--r--doc/administration/smime_signing_email.md2
-rw-r--r--doc/administration/snippets/index.md2
-rw-r--r--doc/administration/static_objects_external_storage.md2
-rw-r--r--doc/administration/system_hooks.md4
-rw-r--r--doc/administration/terraform_state.md2
-rw-r--r--doc/administration/timezone.md4
-rw-r--r--doc/administration/troubleshooting/diagnostics_tools.md4
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md709
-rw-r--r--doc/administration/troubleshooting/index.md2
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md2
-rw-r--r--doc/administration/troubleshooting/postgresql.md4
-rw-r--r--doc/administration/troubleshooting/ssl.md4
-rw-r--r--doc/administration/troubleshooting/test_environments.md2
-rw-r--r--doc/administration/uploads.md2
-rw-r--r--doc/administration/user_settings.md13
-rw-r--r--doc/administration/whats-new.md2
-rw-r--r--doc/administration/wikis/index.md2
-rw-r--r--doc/api/access_requests.md2
-rw-r--r--doc/api/admin_sidekiq_queues.md2
-rw-r--r--doc/api/alert_management_alerts.md4
-rw-r--r--doc/api/api_resources.md6
-rw-r--r--doc/api/appearance.md2
-rw-r--r--doc/api/applications.md2
-rw-r--r--doc/api/audit_events.md2
-rw-r--r--doc/api/avatar.md2
-rw-r--r--doc/api/award_emoji.md2
-rw-r--r--doc/api/boards.md2
-rw-r--r--doc/api/branches.md4
-rw-r--r--doc/api/broadcast_messages.md2
-rw-r--r--doc/api/bulk_imports.md11
-rw-r--r--doc/api/cluster_agents.md2
-rw-r--r--doc/api/commits.md2
-rw-r--r--doc/api/container_registry.md2
-rw-r--r--doc/api/custom_attributes.md2
-rw-r--r--doc/api/dependencies.md38
-rw-r--r--doc/api/dependency_proxy.md2
-rw-r--r--doc/api/deploy_keys.md2
-rw-r--r--doc/api/deploy_tokens.md2
-rw-r--r--doc/api/deployments.md2
-rw-r--r--doc/api/discussions.md2
-rw-r--r--doc/api/dora/metrics.md4
-rw-r--r--doc/api/environments.md3
-rw-r--r--doc/api/epic_issues.md2
-rw-r--r--doc/api/epic_links.md2
-rw-r--r--doc/api/epics.md2
-rw-r--r--doc/api/error_tracking.md2
-rw-r--r--doc/api/events.md2
-rw-r--r--doc/api/experiments.md2
-rw-r--r--doc/api/feature_flag_specs.md2
-rw-r--r--doc/api/feature_flag_user_lists.md2
-rw-r--r--doc/api/feature_flags.md12
-rw-r--r--doc/api/features.md2
-rw-r--r--doc/api/freeze_periods.md2
-rw-r--r--doc/api/geo_nodes.md34
-rw-r--r--doc/api/graphql/audit_report.md2
-rw-r--r--doc/api/graphql/custom_emoji.md2
-rw-r--r--doc/api/graphql/getting_started.md4
-rw-r--r--doc/api/graphql/index.md4
-rw-r--r--doc/api/graphql/reference/index.md539
-rw-r--r--doc/api/graphql/removed_items.md4
-rw-r--r--doc/api/graphql/sample_issue_boards.md2
-rw-r--r--doc/api/graphql/users_example.md2
-rw-r--r--doc/api/group_access_tokens.md2
-rw-r--r--doc/api/group_activity_analytics.md4
-rw-r--r--doc/api/group_badges.md2
-rw-r--r--doc/api/group_boards.md2
-rw-r--r--doc/api/group_clusters.md2
-rw-r--r--doc/api/group_import_export.md2
-rw-r--r--doc/api/group_iterations.md2
-rw-r--r--doc/api/group_labels.md2
-rw-r--r--doc/api/group_level_variables.md2
-rw-r--r--doc/api/group_milestones.md2
-rw-r--r--doc/api/group_protected_environments.md6
-rw-r--r--doc/api/group_relations_export.md2
-rw-r--r--doc/api/group_releases.md2
-rw-r--r--doc/api/group_repository_storage_moves.md2
-rw-r--r--doc/api/group_wikis.md2
-rw-r--r--doc/api/groups.md15
-rw-r--r--doc/api/import.md77
-rw-r--r--doc/api/index.md6
-rw-r--r--doc/api/instance_clusters.md2
-rw-r--r--doc/api/instance_level_ci_variables.md2
-rw-r--r--doc/api/integrations.md6
-rw-r--r--doc/api/invitations.md2
-rw-r--r--doc/api/issue_links.md2
-rw-r--r--doc/api/issues.md65
-rw-r--r--doc/api/issues_statistics.md2
-rw-r--r--doc/api/iterations.md2
-rw-r--r--doc/api/job_artifacts.md2
-rw-r--r--doc/api/jobs.md14
-rw-r--r--doc/api/keys.md2
-rw-r--r--doc/api/labels.md2
-rw-r--r--doc/api/license.md2
-rw-r--r--doc/api/linked_epics.md2
-rw-r--r--doc/api/lint.md2
-rw-r--r--doc/api/managed_licenses.md2
-rw-r--r--doc/api/markdown.md2
-rw-r--r--doc/api/members.md11
-rw-r--r--doc/api/merge_request_approvals.md2
-rw-r--r--doc/api/merge_request_context_commits.md2
-rw-r--r--doc/api/merge_requests.md2
-rw-r--r--doc/api/merge_trains.md2
-rw-r--r--doc/api/metadata.md2
-rw-r--r--doc/api/metrics_dashboard_annotations.md2
-rw-r--r--doc/api/metrics_user_starred_dashboards.md2
-rw-r--r--doc/api/milestones.md2
-rw-r--r--doc/api/namespaces.md2
-rw-r--r--doc/api/notes.md2
-rw-r--r--doc/api/notification_settings.md2
-rw-r--r--doc/api/oauth2.md16
-rw-r--r--doc/api/openapi/openapi_interactive.md4
-rw-r--r--doc/api/openapi/openapi_v2.yaml90
-rw-r--r--doc/api/packages.md2
-rw-r--r--doc/api/packages/composer.md2
-rw-r--r--doc/api/packages/conan.md2
-rw-r--r--doc/api/packages/debian.md2
-rw-r--r--doc/api/packages/debian_group_distributions.md2
-rw-r--r--doc/api/packages/debian_project_distributions.md2
-rw-r--r--doc/api/packages/go_proxy.md2
-rw-r--r--doc/api/packages/helm.md2
-rw-r--r--doc/api/packages/maven.md2
-rw-r--r--doc/api/packages/npm.md2
-rw-r--r--doc/api/packages/nuget.md2
-rw-r--r--doc/api/packages/pypi.md2
-rw-r--r--doc/api/packages/rubygems.md2
-rw-r--r--doc/api/packages/terraform-modules.md18
-rw-r--r--doc/api/pages.md2
-rw-r--r--doc/api/pages_domains.md2
-rw-r--r--doc/api/personal_access_tokens.md129
-rw-r--r--doc/api/pipeline_schedules.md2
-rw-r--r--doc/api/pipeline_triggers.md6
-rw-r--r--doc/api/pipelines.md2
-rw-r--r--doc/api/plan_limits.md2
-rw-r--r--doc/api/product_analytics.md7
-rw-r--r--doc/api/project_access_tokens.md2
-rw-r--r--doc/api/project_aliases.md12
-rw-r--r--doc/api/project_badges.md2
-rw-r--r--doc/api/project_clusters.md2
-rw-r--r--doc/api/project_import_export.md2
-rw-r--r--doc/api/project_level_variables.md2
-rw-r--r--doc/api/project_relations_export.md2
-rw-r--r--doc/api/project_repository_storage_moves.md2
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/api/project_statistics.md2
-rw-r--r--doc/api/project_templates.md2
-rw-r--r--doc/api/project_vulnerabilities.md2
-rw-r--r--doc/api/projects.md29
-rw-r--r--doc/api/protected_branches.md2
-rw-r--r--doc/api/protected_environments.md2
-rw-r--r--doc/api/protected_tags.md2
-rw-r--r--doc/api/releases/index.md2
-rw-r--r--doc/api/releases/links.md2
-rw-r--r--doc/api/remote_mirrors.md2
-rw-r--r--doc/api/repositories.md143
-rw-r--r--doc/api/repository_files.md2
-rw-r--r--doc/api/repository_submodules.md2
-rw-r--r--doc/api/resource_groups.md97
-rw-r--r--doc/api/resource_iteration_events.md2
-rw-r--r--doc/api/resource_label_events.md2
-rw-r--r--doc/api/resource_milestone_events.md2
-rw-r--r--doc/api/resource_state_events.md2
-rw-r--r--doc/api/resource_weight_events.md2
-rw-r--r--doc/api/runners.md2
-rw-r--r--doc/api/saml.md78
-rw-r--r--doc/api/scim.md243
-rw-r--r--doc/api/search.md94
-rw-r--r--doc/api/secure_files.md4
-rw-r--r--doc/api/settings.md8
-rw-r--r--doc/api/sidekiq_metrics.md2
-rw-r--r--doc/api/snippet_repository_storage_moves.md2
-rw-r--r--doc/api/snippets.md2
-rw-r--r--doc/api/statistics.md4
-rw-r--r--doc/api/status_checks.md2
-rw-r--r--doc/api/suggestions.md2
-rw-r--r--doc/api/system_hooks.md4
-rw-r--r--doc/api/tags.md2
-rw-r--r--doc/api/templates/dockerfiles.md2
-rw-r--r--doc/api/templates/gitignores.md2
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md2
-rw-r--r--doc/api/templates/licenses.md2
-rw-r--r--doc/api/todos.md2
-rw-r--r--doc/api/topics.md2
-rw-r--r--doc/api/usage_data.md2
-rw-r--r--doc/api/users.md37
-rw-r--r--doc/api/version.md13
-rw-r--r--doc/api/visual_review_discussions.md2
-rw-r--r--doc/api/vulnerabilities.md2
-rw-r--r--doc/api/vulnerability_exports.md2
-rw-r--r--doc/api/vulnerability_findings.md2
-rw-r--r--doc/api/wikis.md2
-rw-r--r--doc/architecture/blueprints/_template.md8
-rw-r--r--doc/architecture/blueprints/ci_data_decay/index.md20
-rw-r--r--doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md94
-rw-r--r--doc/architecture/blueprints/ci_pipeline_components/index.md17
-rw-r--r--doc/architecture/blueprints/ci_scale/index.md149
-rw-r--r--doc/architecture/blueprints/cloud_native_build_logs/index.md2
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md4
-rw-r--r--doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md8
-rw-r--r--doc/architecture/blueprints/consolidating_groups_and_projects/index.md2
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md2
-rw-r--r--doc/architecture/blueprints/database/scalability/patterns/index.md2
-rw-r--r--doc/architecture/blueprints/database/scalability/patterns/read_mostly.md2
-rw-r--r--doc/architecture/blueprints/database/scalability/patterns/time_decay.md6
-rw-r--r--doc/architecture/blueprints/database_testing/index.md4
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md4
-rw-r--r--doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md2
-rw-r--r--doc/architecture/blueprints/image_resizing/index.md2
-rw-r--r--doc/architecture/blueprints/pods/index.md170
-rw-r--r--doc/architecture/blueprints/pods/iteration0-organizations-introduction.pngbin0 -> 326285 bytes
-rw-r--r--doc/architecture/blueprints/pods/term-cluster.pngbin0 -> 271291 bytes
-rw-r--r--doc/architecture/blueprints/pods/term-organization.pngbin0 -> 22575 bytes
-rw-r--r--doc/architecture/blueprints/pods/term-pod.pngbin0 -> 16104 bytes
-rw-r--r--doc/architecture/blueprints/pods/term-top-level-namespace.pngbin0 -> 11451 bytes
-rw-r--r--doc/architecture/blueprints/rate_limiting/index.md6
-rw-r--r--doc/architecture/blueprints/runner_scaling/index.md280
-rw-r--r--doc/architecture/blueprints/work_items/index.md130
-rw-r--r--doc/architecture/index.md2
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/ci/chatops/index.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md2
-rw-r--r--doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md2
-rw-r--r--doc/ci/cloud_deployment/ecs/quick_start_guide.md11
-rw-r--r--doc/ci/cloud_deployment/heroku.md2
-rw-r--r--doc/ci/cloud_deployment/index.md4
-rw-r--r--doc/ci/cloud_services/aws/index.md2
-rw-r--r--doc/ci/cloud_services/azure/index.md22
-rw-r--r--doc/ci/cloud_services/google_cloud/index.md2
-rw-r--r--doc/ci/cloud_services/index.md2
-rw-r--r--doc/ci/directed_acyclic_graph/index.md2
-rw-r--r--doc/ci/docker/index.md2
-rw-r--r--doc/ci/docker/using_docker_build.md4
-rw-r--r--doc/ci/docker/using_docker_images.md8
-rw-r--r--doc/ci/docker/using_kaniko.md2
-rw-r--r--doc/ci/enable_or_disable_ci.md2
-rw-r--r--doc/ci/environments/deployment_approvals.md5
-rw-r--r--doc/ci/environments/deployment_safety.md2
-rw-r--r--doc/ci/environments/environments_dashboard.md2
-rw-r--r--doc/ci/environments/incremental_rollouts.md2
-rw-r--r--doc/ci/environments/index.md14
-rw-r--r--doc/ci/environments/protected_environments.md28
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md2
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md2
-rw-r--r--doc/ci/examples/deployment/index.md4
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md4
-rw-r--r--doc/ci/examples/index.md2
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md2
-rw-r--r--doc/ci/examples/php.md6
-rw-r--r--doc/ci/examples/semantic-release.md2
-rw-r--r--doc/ci/git_submodules.md10
-rw-r--r--doc/ci/index.md2
-rw-r--r--doc/ci/interactive_web_terminal/index.md2
-rw-r--r--doc/ci/introduction/index.md2
-rw-r--r--doc/ci/jobs/ci_job_token.md29
-rw-r--r--doc/ci/jobs/index.md2
-rw-r--r--doc/ci/jobs/job_control.md7
-rw-r--r--doc/ci/large_repositories/index.md7
-rw-r--r--doc/ci/lint.md2
-rw-r--r--doc/ci/metrics_reports.md11
-rw-r--r--doc/ci/migration/circleci.md2
-rw-r--r--doc/ci/migration/jenkins.md7
-rw-r--r--doc/ci/mobile_devops.md2
-rw-r--r--doc/ci/pipeline_editor/index.md2
-rw-r--r--doc/ci/pipelines/cicd_minutes.md9
-rw-r--r--doc/ci/pipelines/downstream_pipelines.md478
-rw-r--r--doc/ci/pipelines/index.md38
-rw-r--r--doc/ci/pipelines/job_artifacts.md2
-rw-r--r--doc/ci/pipelines/merge_request_pipelines.md2
-rw-r--r--doc/ci/pipelines/merge_trains.md4
-rw-r--r--doc/ci/pipelines/merged_results_pipelines.md4
-rw-r--r--doc/ci/pipelines/multi_project_pipelines.md4
-rw-r--r--doc/ci/pipelines/pipeline_architectures.md43
-rw-r--r--doc/ci/pipelines/pipeline_artifacts.md2
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md2
-rw-r--r--doc/ci/pipelines/schedules.md5
-rw-r--r--doc/ci/pipelines/settings.md12
-rw-r--r--doc/ci/quick_start/index.md2
-rw-r--r--doc/ci/resource_groups/index.md2
-rw-r--r--doc/ci/review_apps/index.md13
-rw-r--r--doc/ci/runners/configure_runners.md39
-rw-r--r--doc/ci/runners/index.md2
-rw-r--r--doc/ci/runners/runners_scope.md27
-rw-r--r--doc/ci/runners/saas/linux_saas_runner.md2
-rw-r--r--doc/ci/runners/saas/macos/codesigning.md2
-rw-r--r--doc/ci/runners/saas/macos/environment.md5
-rw-r--r--doc/ci/runners/saas/macos_saas_runner.md6
-rw-r--r--doc/ci/runners/saas/windows_saas_runner.md2
-rw-r--r--doc/ci/secrets/index.md4
-rw-r--r--doc/ci/secure_files/index.md10
-rw-r--r--doc/ci/services/gitlab.md2
-rw-r--r--doc/ci/services/index.md9
-rw-r--r--doc/ci/services/mysql.md2
-rw-r--r--doc/ci/services/postgres.md2
-rw-r--r--doc/ci/services/redis.md4
-rw-r--r--doc/ci/ssh_keys/index.md18
-rw-r--r--doc/ci/test_cases/index.md7
-rw-r--r--doc/ci/testing/accessibility_testing.md2
-rw-r--r--doc/ci/testing/browser_performance_testing.md2
-rw-r--r--doc/ci/testing/code_quality.md48
-rw-r--r--doc/ci/testing/fail_fast_testing.md2
-rw-r--r--doc/ci/testing/index.md2
-rw-r--r--doc/ci/testing/load_performance_testing.md2
-rw-r--r--doc/ci/testing/metrics_reports.md2
-rw-r--r--doc/ci/testing/test_coverage_visualization.md2
-rw-r--r--doc/ci/testing/unit_test_report_examples.md9
-rw-r--r--doc/ci/testing/unit_test_reports.md2
-rw-r--r--doc/ci/triggers/index.md2
-rw-r--r--doc/ci/troubleshooting.md2
-rw-r--r--doc/ci/unit_test_reports.md11
-rw-r--r--doc/ci/variables/index.md11
-rw-r--r--doc/ci/variables/predefined_variables.md9
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md2
-rw-r--r--doc/ci/yaml/artifacts_reports.md2
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/includes.md2
-rw-r--r--doc/ci/yaml/index.md73
-rw-r--r--doc/ci/yaml/script.md2
-rw-r--r--doc/ci/yaml/workflow.md2
-rw-r--r--doc/ci/yaml/yaml_optimization.md4
-rw-r--r--doc/cloud_seed/index.md10
-rw-r--r--doc/development/adding_service_component.md2
-rw-r--r--doc/development/api_graphql_styleguide.md4
-rw-r--r--doc/development/api_styleguide.md2
-rw-r--r--doc/development/application_limits.md2
-rw-r--r--doc/development/application_secrets.md2
-rw-r--r--doc/development/application_slis/index.md4
-rw-r--r--doc/development/application_slis/rails_request_apdex.md2
-rw-r--r--doc/development/approval_rules.md2
-rw-r--r--doc/development/appsec/index.md11
-rw-r--r--doc/development/architecture.md2
-rw-r--r--doc/development/audit_event_guide/index.md4
-rw-r--r--doc/development/auto_devops.md2
-rw-r--r--doc/development/avoiding_downtime_in_migrations.md11
-rw-r--r--doc/development/backend/create_source_code_be/gitaly_touch_points.md2
-rw-r--r--doc/development/backend/create_source_code_be/index.md2
-rw-r--r--doc/development/backend/create_source_code_be/rest_endpoints.md2
-rw-r--r--doc/development/backend/ruby_style_guide.md2
-rw-r--r--doc/development/background_migrations.md11
-rw-r--r--doc/development/batched_background_migrations.md11
-rw-r--r--doc/development/build_test_package.md2
-rw-r--r--doc/development/bulk_import.md2
-rw-r--r--doc/development/cached_queries.md2
-rw-r--r--doc/development/caching.md2
-rw-r--r--doc/development/cascading_settings.md2
-rw-r--r--doc/development/changelog.md8
-rw-r--r--doc/development/chaos_endpoints.md6
-rw-r--r--doc/development/chatops_on_gitlabcom.md2
-rw-r--r--doc/development/cicd/cicd_reference_documentation_guide.md2
-rw-r--r--doc/development/cicd/index.md5
-rw-r--r--doc/development/cicd/pipeline_wizard.md2
-rw-r--r--doc/development/cicd/schema.md2
-rw-r--r--doc/development/cicd/templates.md6
-rw-r--r--doc/development/code_comments.md2
-rw-r--r--doc/development/code_intelligence/index.md2
-rw-r--r--doc/development/code_review.md24
-rw-r--r--doc/development/contributing/community_roles.md6
-rw-r--r--doc/development/contributing/design.md12
-rw-r--r--doc/development/contributing/index.md7
-rw-r--r--doc/development/contributing/issue_workflow.md6
-rw-r--r--doc/development/contributing/merge_request_workflow.md4
-rw-r--r--doc/development/contributing/style_guides.md36
-rw-r--r--doc/development/contributing/verify/index.md4
-rw-r--r--doc/development/dangerbot.md4
-rw-r--r--doc/development/database/add_foreign_key_to_existing_column.md4
-rw-r--r--doc/development/database/adding_database_indexes.md2
-rw-r--r--doc/development/database/avoiding_downtime_in_migrations.md4
-rw-r--r--doc/development/database/background_migrations.md8
-rw-r--r--doc/development/database/batched_background_migrations.md122
-rw-r--r--doc/development/database/ci_mirrored_tables.md2
-rw-r--r--doc/development/database/client_side_connection_pool.md2
-rw-r--r--doc/development/database/constraint_naming_convention.md2
-rw-r--r--doc/development/database/creating_enums.md4
-rw-r--r--doc/development/database/database_debugging.md2
-rw-r--r--doc/development/database/database_dictionary.md2
-rw-r--r--doc/development/database/database_lab.md2
-rw-r--r--doc/development/database/database_migration_pipeline.md2
-rw-r--r--doc/development/database/database_query_comments.md2
-rw-r--r--doc/development/database/database_reviewer_guidelines.md2
-rw-r--r--doc/development/database/db_dump.md2
-rw-r--r--doc/development/database/dbcheck-migrations-job.md2
-rw-r--r--doc/development/database/deleting_migrations.md2
-rw-r--r--doc/development/database/efficient_in_operator_queries.md62
-rw-r--r--doc/development/database/filtering_by_label.md2
-rw-r--r--doc/development/database/foreign_keys.md100
-rw-r--r--doc/development/database/hash_indexes.md2
-rw-r--r--doc/development/database/img/list_v15_4.pngbin0 -> 63309 bytes
-rw-r--r--doc/development/database/img/pause_v15_4.pngbin0 -> 33525 bytes
-rw-r--r--doc/development/database/img/resume_v15_4.pngbin0 -> 33578 bytes
-rw-r--r--doc/development/database/img/status_v15_4.pngbin0 -> 34511 bytes
-rw-r--r--doc/development/database/index.md5
-rw-r--r--doc/development/database/insert_into_tables_in_batches.md4
-rw-r--r--doc/development/database/iterating_tables_in_batches.md6
-rw-r--r--doc/development/database/keyset_pagination.md2
-rw-r--r--doc/development/database/layout_and_access_patterns.md2
-rw-r--r--doc/development/database/loose_foreign_keys.md4
-rw-r--r--doc/development/database/maintenance_operations.md2
-rw-r--r--doc/development/database/migrations_for_multiple_databases.md2
-rw-r--r--doc/development/database/multiple_databases.md2
-rw-r--r--doc/development/database/namespaces_storage_statistics.md2
-rw-r--r--doc/development/database/not_null_constraints.md6
-rw-r--r--doc/development/database/ordering_table_columns.md2
-rw-r--r--doc/development/database/pagination_guidelines.md10
-rw-r--r--doc/development/database/pagination_performance_guidelines.md2
-rw-r--r--doc/development/database/polymorphic_associations.md2
-rw-r--r--doc/development/database/post_deployment_migrations.md2
-rw-r--r--doc/development/database/query_count_limits.md2
-rw-r--r--doc/development/database/query_performance.md2
-rw-r--r--doc/development/database/query_recorder.md2
-rw-r--r--doc/development/database/rename_database_tables.md2
-rw-r--r--doc/development/database/serializing_data.md2
-rw-r--r--doc/development/database/setting_multiple_values.md2
-rw-r--r--doc/development/database/sha1_as_binary.md2
-rw-r--r--doc/development/database/single_table_inheritance.md2
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md41
-rw-r--r--doc/development/database/swapping_tables.md2
-rw-r--r--doc/development/database/table_partitioning.md218
-rw-r--r--doc/development/database/transaction_guidelines.md6
-rw-r--r--doc/development/database/understanding_explain_plans.md6
-rw-r--r--doc/development/database/verifying_database_capabilities.md2
-rw-r--r--doc/development/database_review.md8
-rw-r--r--doc/development/deleting_migrations.md11
-rw-r--r--doc/development/dependencies.md2
-rw-r--r--doc/development/deprecation_guidelines/index.md2
-rw-r--r--doc/development/developing_with_solargraph.md2
-rw-r--r--doc/development/development_processes.md16
-rw-r--r--doc/development/diffs.md6
-rw-r--r--doc/development/directory_structure.md2
-rw-r--r--doc/development/distributed_tracing.md2
-rw-r--r--doc/development/documentation/feature_flags.md6
-rw-r--r--doc/development/documentation/graphql_styleguide.md2
-rw-r--r--doc/development/documentation/index.md10
-rw-r--r--doc/development/documentation/redirects.md2
-rw-r--r--doc/development/documentation/restful_api_styleguide.md2
-rw-r--r--doc/development/documentation/review_apps.md2
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md2
-rw-r--r--doc/development/documentation/site_architecture/folder_structure.md2
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md2
-rw-r--r--doc/development/documentation/site_architecture/index.md2
-rw-r--r--doc/development/documentation/styleguide/index.md243
-rw-r--r--doc/development/documentation/styleguide/word_list.md62
-rw-r--r--doc/development/documentation/testing.md2
-rw-r--r--doc/development/documentation/topic_types/concept.md2
-rw-r--r--doc/development/documentation/topic_types/index.md2
-rw-r--r--doc/development/documentation/topic_types/reference.md2
-rw-r--r--doc/development/documentation/topic_types/task.md2
-rw-r--r--doc/development/documentation/topic_types/troubleshooting.md2
-rw-r--r--doc/development/documentation/versions.md8
-rw-r--r--doc/development/documentation/workflow.md10
-rw-r--r--doc/development/ee_features.md28
-rw-r--r--doc/development/elasticsearch.md10
-rw-r--r--doc/development/emails.md4
-rw-r--r--doc/development/event_store.md2
-rw-r--r--doc/development/experiment_guide/experiment_code_reviews.md2
-rw-r--r--doc/development/experiment_guide/experiment_rollout.md2
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md11
-rw-r--r--doc/development/experiment_guide/implementing_experiments.md6
-rw-r--r--doc/development/experiment_guide/index.md2
-rw-r--r--doc/development/experiment_guide/testing_experiments.md2
-rw-r--r--doc/development/export_csv.md2
-rw-r--r--doc/development/fe_guide/accessibility.md82
-rw-r--r--doc/development/fe_guide/architecture.md2
-rw-r--r--doc/development/fe_guide/axios.md2
-rw-r--r--doc/development/fe_guide/content_editor.md2
-rw-r--r--doc/development/fe_guide/customizable_dashboards.md99
-rw-r--r--doc/development/fe_guide/dark_mode.md2
-rw-r--r--doc/development/fe_guide/dependencies.md2
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md4
-rw-r--r--doc/development/fe_guide/design_patterns.md2
-rw-r--r--doc/development/fe_guide/development_process.md4
-rw-r--r--doc/development/fe_guide/emojis.md2
-rw-r--r--doc/development/fe_guide/frontend_faq.md2
-rw-r--r--doc/development/fe_guide/graphql.md10
-rw-r--r--doc/development/fe_guide/haml.md2
-rw-r--r--doc/development/fe_guide/icons.md2
-rw-r--r--doc/development/fe_guide/index.md2
-rw-r--r--doc/development/fe_guide/keyboard_shortcuts.md2
-rw-r--r--doc/development/fe_guide/logging.md2
-rw-r--r--doc/development/fe_guide/merge_request_widget_extensions.md2
-rw-r--r--doc/development/fe_guide/performance.md2
-rw-r--r--doc/development/fe_guide/principles.md2
-rw-r--r--doc/development/fe_guide/registry_architecture.md2
-rw-r--r--doc/development/fe_guide/security.md2
-rw-r--r--doc/development/fe_guide/source_editor.md2
-rw-r--r--doc/development/fe_guide/storybook.md2
-rw-r--r--doc/development/fe_guide/style/html.md2
-rw-r--r--doc/development/fe_guide/style/index.md2
-rw-r--r--doc/development/fe_guide/style/javascript.md2
-rw-r--r--doc/development/fe_guide/style/scss.md2
-rw-r--r--doc/development/fe_guide/style/vue.md2
-rw-r--r--doc/development/fe_guide/tooling.md2
-rw-r--r--doc/development/fe_guide/troubleshooting.md2
-rw-r--r--doc/development/fe_guide/view_component.md4
-rw-r--r--doc/development/fe_guide/vue.md6
-rw-r--r--doc/development/fe_guide/vue3_migration.md2
-rw-r--r--doc/development/fe_guide/vuex.md2
-rw-r--r--doc/development/fe_guide/widgets.md2
-rw-r--r--doc/development/feature_categorization/index.md2
-rw-r--r--doc/development/feature_development.md9
-rw-r--r--doc/development/feature_flags/controls.md19
-rw-r--r--doc/development/feature_flags/index.md16
-rw-r--r--doc/development/features_inside_dot_gitlab.md4
-rw-r--r--doc/development/file_storage.md2
-rw-r--r--doc/development/fips_compliance.md6
-rw-r--r--doc/development/gemfile.md51
-rw-r--r--doc/development/geo.md6
-rw-r--r--doc/development/geo/framework.md2
-rw-r--r--doc/development/geo/proxying.md2
-rw-r--r--doc/development/git_object_deduplication.md2
-rw-r--r--doc/development/gitaly.md4
-rw-r--r--doc/development/github_importer.md22
-rw-r--r--doc/development/gitlab_flavored_markdown/index.md2
-rw-r--r--doc/development/gitlab_flavored_markdown/specification_guide/index.md417
-rw-r--r--doc/development/go_guide/dependencies.md2
-rw-r--r--doc/development/go_guide/go_upgrade.md4
-rw-r--r--doc/development/go_guide/index.md23
-rw-r--r--doc/development/gotchas.md2
-rw-r--r--doc/development/graphql_guide/authorization.md2
-rw-r--r--doc/development/graphql_guide/batchloader.md6
-rw-r--r--doc/development/graphql_guide/graphql_pro.md6
-rw-r--r--doc/development/graphql_guide/index.md4
-rw-r--r--doc/development/graphql_guide/monitoring.md4
-rw-r--r--doc/development/graphql_guide/pagination.md4
-rw-r--r--doc/development/i18n/externalization.md2
-rw-r--r--doc/development/i18n/index.md2
-rw-r--r--doc/development/i18n/merging_translations.md4
-rw-r--r--doc/development/i18n/proofreader.md3
-rw-r--r--doc/development/i18n/translation.md2
-rw-r--r--doc/development/image_scaling.md6
-rw-r--r--doc/development/import_export.md2
-rw-r--r--doc/development/import_project.md8
-rw-r--r--doc/development/index.md2
-rw-r--r--doc/development/integrations/codesandbox.md2
-rw-r--r--doc/development/integrations/index.md4
-rw-r--r--doc/development/integrations/jenkins.md4
-rw-r--r--doc/development/integrations/jira_connect.md4
-rw-r--r--doc/development/integrations/secure.md33
-rw-r--r--doc/development/integrations/secure_partner_integration.md2
-rw-r--r--doc/development/interacting_components.md2
-rw-r--r--doc/development/internal_api/index.md259
-rw-r--r--doc/development/internal_api/internal_api_allowed.md2
-rw-r--r--doc/development/internal_users.md2
-rw-r--r--doc/development/issuable-like-models.md2
-rw-r--r--doc/development/issue_types.md4
-rw-r--r--doc/development/json.md46
-rw-r--r--doc/development/kubernetes.md2
-rw-r--r--doc/development/lfs.md2
-rw-r--r--doc/development/licensing.md4
-rw-r--r--doc/development/logging.md2
-rw-r--r--doc/development/maintenance_mode.md2
-rw-r--r--doc/development/mass_insert.md2
-rw-r--r--doc/development/merge_request_application_and_rate_limit_guidelines.md2
-rw-r--r--doc/development/merge_request_concepts/index.md2
-rw-r--r--doc/development/merge_request_performance_guidelines.md8
-rw-r--r--doc/development/migration_style_guide.md55
-rw-r--r--doc/development/module_with_instance_variables.md2
-rw-r--r--doc/development/multi_version_compatibility.md2
-rw-r--r--doc/development/omnibus.md2
-rw-r--r--doc/development/packages.md11
-rw-r--r--doc/development/packages/debian_repository.md2
-rw-r--r--doc/development/packages/dependency_proxy.md197
-rw-r--r--doc/development/packages/index.md4
-rw-r--r--doc/development/packages/new_format_development.md2
-rw-r--r--doc/development/packages/settings.md2
-rw-r--r--doc/development/packages/structure.md2
-rw-r--r--doc/development/pages/index.md2
-rw-r--r--doc/development/performance.md8
-rw-r--r--doc/development/permissions.md4
-rw-r--r--doc/development/pipelines.md130
-rw-r--r--doc/development/policies.md2
-rw-r--r--doc/development/polling.md4
-rw-r--r--doc/development/post_deployment_migrations.md11
-rw-r--r--doc/development/product_qualified_lead_guide/index.md2
-rw-r--r--doc/development/profiling.md63
-rw-r--r--doc/development/project_templates.md4
-rw-r--r--doc/development/projections.md2
-rw-r--r--doc/development/prometheus_metrics.md2
-rw-r--r--doc/development/pry_debugging.md2
-rw-r--r--doc/development/python_guide/index.md2
-rw-r--r--doc/development/rails_initializers.md2
-rw-r--r--doc/development/rails_update.md2
-rw-r--r--doc/development/rake_tasks.md2
-rw-r--r--doc/development/reactive_caching.md2
-rw-r--r--doc/development/real_time.md4
-rw-r--r--doc/development/redis.md2
-rw-r--r--doc/development/redis/new_redis_instance.md2
-rw-r--r--doc/development/refactoring_guide/index.md8
-rw-r--r--doc/development/reference_processing.md2
-rw-r--r--doc/development/renaming_features.md2
-rw-r--r--doc/development/repository_mirroring.md2
-rw-r--r--doc/development/reusing_abstractions.md108
-rw-r--r--doc/development/routing.md2
-rw-r--r--doc/development/ruby3_gotchas.md2
-rw-r--r--doc/development/ruby_upgrade.md2
-rw-r--r--doc/development/scalability.md4
-rw-r--r--doc/development/sec/analyzer_development_guide.md185
-rw-r--r--doc/development/sec/index.md7
-rw-r--r--doc/development/secure_coding_guidelines.md8
-rw-r--r--doc/development/service_measurement.md6
-rw-r--r--doc/development/service_ping/implement.md30
-rw-r--r--doc/development/service_ping/index.md2
-rw-r--r--doc/development/service_ping/metrics_dictionary.md5
-rw-r--r--doc/development/service_ping/metrics_instrumentation.md82
-rw-r--r--doc/development/service_ping/metrics_lifecycle.md4
-rw-r--r--doc/development/service_ping/performance_indicator_metrics.md2
-rw-r--r--doc/development/service_ping/review_guidelines.md2
-rw-r--r--doc/development/service_ping/troubleshooting.md2
-rw-r--r--doc/development/service_ping/usage_data.md2
-rw-r--r--doc/development/session.md2
-rw-r--r--doc/development/shared_files.md2
-rw-r--r--doc/development/shell_commands.md2
-rw-r--r--doc/development/shell_scripting_guide/index.md2
-rw-r--r--doc/development/sidekiq/compatibility_across_updates.md2
-rw-r--r--doc/development/sidekiq/idempotent_jobs.md2
-rw-r--r--doc/development/sidekiq/index.md8
-rw-r--r--doc/development/sidekiq/limited_capacity_worker.md2
-rw-r--r--doc/development/sidekiq/logging.md2
-rw-r--r--doc/development/sidekiq/worker_attributes.md6
-rw-r--r--doc/development/snowplow/event_dictionary_guide.md2
-rw-r--r--doc/development/snowplow/implementation.md2
-rw-r--r--doc/development/snowplow/index.md4
-rw-r--r--doc/development/snowplow/infrastructure.md2
-rw-r--r--doc/development/snowplow/review_guidelines.md2
-rw-r--r--doc/development/snowplow/schemas.md2
-rw-r--r--doc/development/snowplow/troubleshooting.md8
-rw-r--r--doc/development/spam_protection_and_captcha/exploratory_testing.md2
-rw-r--r--doc/development/spam_protection_and_captcha/graphql_api.md2
-rw-r--r--doc/development/spam_protection_and_captcha/index.md2
-rw-r--r--doc/development/spam_protection_and_captcha/model_and_services.md2
-rw-r--r--doc/development/spam_protection_and_captcha/rest_api.md2
-rw-r--r--doc/development/spam_protection_and_captcha/web_ui.md2
-rw-r--r--doc/development/sql.md2
-rw-r--r--doc/development/stage_group_observability/dashboards/error_budget_detail.md2
-rw-r--r--doc/development/stage_group_observability/dashboards/index.md2
-rw-r--r--doc/development/stage_group_observability/dashboards/stage_group_dashboard.md6
-rw-r--r--doc/development/stage_group_observability/index.md2
-rw-r--r--doc/development/testing_guide/best_practices.md2
-rw-r--r--doc/development/testing_guide/contract/consumer_tests.md2
-rw-r--r--doc/development/testing_guide/contract/index.md4
-rw-r--r--doc/development/testing_guide/contract/provider_tests.md2
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md32
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md8
-rw-r--r--doc/development/testing_guide/end_to_end/capybara_to_chemlab_migration_guide.md2
-rw-r--r--doc/development/testing_guide/end_to_end/dynamic_element_validation.md4
-rw-r--r--doc/development/testing_guide/end_to_end/execution_context_selection.md2
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md2
-rw-r--r--doc/development/testing_guide/end_to_end/flows.md2
-rw-r--r--doc/development/testing_guide/end_to_end/index.md4
-rw-r--r--doc/development/testing_guide/end_to_end/page_objects.md4
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md2
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md2
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md2
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md2
-rw-r--r--doc/development/testing_guide/end_to_end/troubleshooting.md2
-rw-r--r--doc/development/testing_guide/flaky_tests.md20
-rw-r--r--doc/development/testing_guide/frontend_testing.md5
-rw-r--r--doc/development/testing_guide/index.md2
-rw-r--r--doc/development/testing_guide/review_apps.md6
-rw-r--r--doc/development/testing_guide/smoke.md2
-rw-r--r--doc/development/testing_guide/testing_levels.md2
-rw-r--r--doc/development/testing_guide/testing_migrations_guide.md5
-rw-r--r--doc/development/testing_guide/testing_rake_tasks.md2
-rw-r--r--doc/development/transient/prevention-patterns.md2
-rw-r--r--doc/development/uploads/background.md11
-rw-r--r--doc/development/uploads/implementation.md11
-rw-r--r--doc/development/uploads/index.md2
-rw-r--r--doc/development/uploads/working_with_uploads.md2
-rw-r--r--doc/development/utilities.md2
-rw-r--r--doc/development/value_stream_analytics.md26
-rw-r--r--doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md10
-rw-r--r--doc/development/wikis.md2
-rw-r--r--doc/development/windows.md4
-rw-r--r--doc/development/work_items.md27
-rw-r--r--doc/development/work_items_widgets.md12
-rw-r--r--doc/development/workhorse/channel.md2
-rw-r--r--doc/development/workhorse/configuration.md2
-rw-r--r--doc/development/workhorse/gitlab_features.md2
-rw-r--r--doc/development/workhorse/index.md2
-rw-r--r--doc/development/workhorse/new_features.md2
-rw-r--r--doc/development/workspace/index.md2
-rw-r--r--doc/downgrade_ee_to_ce/index.md2
-rw-r--r--doc/drawers/advanced_search_syntax.md2
-rw-r--r--doc/gitlab-basics/add-file.md2
-rw-r--r--doc/gitlab-basics/command-line-commands.md2
-rw-r--r--doc/gitlab-basics/feature_branch_workflow.md2
-rw-r--r--doc/gitlab-basics/index.md11
-rw-r--r--doc/gitlab-basics/start-using-git.md16
-rw-r--r--doc/index.md2
-rw-r--r--doc/install/aws/eks_clusters_aws.md2
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md2
-rw-r--r--doc/install/aws/gitlab_sre_for_aws.md2
-rw-r--r--doc/install/aws/index.md4
-rw-r--r--doc/install/aws/manual_install_aws.md10
-rw-r--r--doc/install/azure/index.md12
-rw-r--r--doc/install/digitaloceandocker.md11
-rw-r--r--doc/install/docker.md9
-rw-r--r--doc/install/google_cloud_platform/index.md6
-rw-r--r--doc/install/index.md2
-rw-r--r--doc/install/install_methods.md2
-rw-r--r--doc/install/installation.md8
-rw-r--r--doc/install/migrate/compare_sm_to_saas.md2
-rw-r--r--doc/install/next_steps.md2
-rw-r--r--doc/install/openshift_and_gitlab/index.md2
-rw-r--r--doc/install/postgresql_extensions.md2
-rw-r--r--doc/install/relative_url.md2
-rw-r--r--doc/install/requirements.md2
-rw-r--r--doc/integration/advanced_search/elasticsearch.md4
-rw-r--r--doc/integration/advanced_search/elasticsearch_troubleshooting.md2
-rw-r--r--doc/integration/akismet.md2
-rw-r--r--doc/integration/alicloud.md2
-rw-r--r--doc/integration/arkose.md4
-rw-r--r--doc/integration/auth0.md48
-rw-r--r--doc/integration/azure.md60
-rw-r--r--doc/integration/bitbucket.md27
-rw-r--r--doc/integration/cas.md2
-rw-r--r--doc/integration/datadog.md4
-rw-r--r--doc/integration/ding_talk.md24
-rw-r--r--doc/integration/elasticsearch.md11
-rw-r--r--doc/integration/external-issue-tracker.md4
-rw-r--r--doc/integration/facebook.md2
-rw-r--r--doc/integration/github.md2
-rw-r--r--doc/integration/gitlab.md2
-rw-r--r--doc/integration/gitpod.md2
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md4
-rw-r--r--doc/integration/google.md2
-rw-r--r--doc/integration/index.md12
-rw-r--r--doc/integration/jenkins.md14
-rw-r--r--doc/integration/jenkins_deprecated.md4
-rw-r--r--doc/integration/jira/configure.md4
-rw-r--r--doc/integration/jira/connect-app.md4
-rw-r--r--doc/integration/jira/development_panel.md6
-rw-r--r--doc/integration/jira/dvcs.md4
-rw-r--r--doc/integration/jira/index.md60
-rw-r--r--doc/integration/jira/issues.md4
-rw-r--r--doc/integration/jira/jira_cloud_configuration.md4
-rw-r--r--doc/integration/jira/jira_server_configuration.md4
-rw-r--r--doc/integration/kerberos.md4
-rw-r--r--doc/integration/mattermost/index.md4
-rw-r--r--doc/integration/oauth2_generic.md55
-rw-r--r--doc/integration/oauth_provider.md18
-rw-r--r--doc/integration/omniauth.md7
-rw-r--r--doc/integration/openid_connect_provider.md2
-rw-r--r--doc/integration/recaptcha.md2
-rw-r--r--doc/integration/salesforce.md4
-rw-r--r--doc/integration/saml.md4
-rw-r--r--doc/integration/security_partners/index.md2
-rw-r--r--doc/integration/slash_commands.md4
-rw-r--r--doc/integration/sourcegraph.md2
-rw-r--r--doc/integration/trello_power_up.md4
-rw-r--r--doc/integration/twitter.md58
-rw-r--r--doc/integration/vault.md190
-rw-r--r--doc/legal/corporate_contributor_license_agreement.md2
-rw-r--r--doc/legal/developer_certificate_of_origin.md2
-rw-r--r--doc/legal/index.md2
-rw-r--r--doc/legal/individual_contributor_license_agreement.md2
-rw-r--r--doc/operations/error_tracking.md8
-rw-r--r--doc/operations/feature_flags.md34
-rw-r--r--doc/operations/incident_management/alerts.md4
-rw-r--r--doc/operations/incident_management/escalation_policies.md2
-rw-r--r--doc/operations/incident_management/incident_timeline_events.md10
-rw-r--r--doc/operations/incident_management/incidents.md24
-rw-r--r--doc/operations/incident_management/index.md2
-rw-r--r--doc/operations/incident_management/integrations.md2
-rw-r--r--doc/operations/incident_management/linked_resources.md22
-rw-r--r--doc/operations/incident_management/oncall_schedules.md2
-rw-r--r--doc/operations/incident_management/paging.md2
-rw-r--r--doc/operations/incident_management/status_page.md6
-rw-r--r--doc/operations/index.md2
-rw-r--r--doc/operations/metrics/alerts.md2
-rw-r--r--doc/operations/metrics/dashboards/default.md2
-rw-r--r--doc/operations/metrics/dashboards/develop.md2
-rw-r--r--doc/operations/metrics/dashboards/index.md4
-rw-r--r--doc/operations/metrics/dashboards/panel_types.md2
-rw-r--r--doc/operations/metrics/dashboards/settings.md2
-rw-r--r--doc/operations/metrics/dashboards/templating_variables.md2
-rw-r--r--doc/operations/metrics/dashboards/variables.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml_number_format.md2
-rw-r--r--doc/operations/metrics/embed.md2
-rw-r--r--doc/operations/metrics/embed_grafana.md2
-rw-r--r--doc/operations/metrics/index.md6
-rw-r--r--doc/operations/product_analytics.md2
-rw-r--r--doc/operations/tracing.md2
-rw-r--r--doc/policy/alpha-beta-support.md2
-rw-r--r--doc/policy/maintenance.md5
-rw-r--r--doc/raketasks/backup_gitlab.md4
-rw-r--r--doc/raketasks/backup_restore.md2
-rw-r--r--doc/raketasks/cleanup.md2
-rw-r--r--doc/raketasks/generate_sample_prometheus_data.md2
-rw-r--r--doc/raketasks/import.md14
-rw-r--r--doc/raketasks/index.md2
-rw-r--r--doc/raketasks/list_repos.md2
-rw-r--r--doc/raketasks/migrate_snippets.md2
-rw-r--r--doc/raketasks/restore_gitlab.md4
-rw-r--r--doc/raketasks/spdx.md2
-rw-r--r--doc/raketasks/user_management.md4
-rw-r--r--doc/raketasks/web_hooks.md2
-rw-r--r--doc/raketasks/x509_signatures.md2
-rw-r--r--doc/security/asset_proxy.md4
-rw-r--r--doc/security/crime_vulnerability.md2
-rw-r--r--doc/security/index.md4
-rw-r--r--doc/security/information_exclusivity.md2
-rw-r--r--doc/security/password_length_limits.md2
-rw-r--r--doc/security/password_storage.md22
-rw-r--r--doc/security/passwords_for_integrated_authentication_methods.md2
-rw-r--r--doc/security/project_import_decompressed_archive_size_limits.md2
-rw-r--r--doc/security/rate_limits.md2
-rw-r--r--doc/security/reset_user_password.md15
-rw-r--r--doc/security/responding_to_security_incidents.md2
-rw-r--r--doc/security/ssh_keys_restrictions.md2
-rw-r--r--doc/security/token_overview.md4
-rw-r--r--doc/security/two_factor_authentication.md2
-rw-r--r--doc/security/unlock_user.md4
-rw-r--r--doc/security/user_email_confirmation.md2
-rw-r--r--doc/security/user_file_uploads.md2
-rw-r--r--doc/security/webhooks.md2
-rw-r--r--doc/subscriptions/bronze_starter.md5
-rw-r--r--doc/subscriptions/gitlab_com/index.md8
-rw-r--r--doc/subscriptions/gitlab_dedicated/index.md61
-rw-r--r--doc/subscriptions/img/support_diagram_c.pngbin55374 -> 0 bytes
-rw-r--r--doc/subscriptions/index.md79
-rw-r--r--doc/subscriptions/quarterly_reconciliation.md2
-rw-r--r--doc/subscriptions/self_managed/index.md6
-rw-r--r--doc/topics/authentication/index.md2
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_ec2.md2
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_ecs.md2
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md2
-rw-r--r--doc/topics/autodevops/customize.md4
-rw-r--r--doc/topics/autodevops/index.md136
-rw-r--r--doc/topics/autodevops/multiple_clusters_auto_devops.md65
-rw-r--r--doc/topics/autodevops/prepare_deployment.md2
-rw-r--r--doc/topics/autodevops/quick_start_guide.md11
-rw-r--r--doc/topics/autodevops/requirements.md2
-rw-r--r--doc/topics/autodevops/stages.md2
-rw-r--r--doc/topics/autodevops/troubleshooting.md2
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md2
-rw-r--r--doc/topics/autodevops/upgrading_postgresql.md2
-rw-r--r--doc/topics/awesome_co.md143
-rw-r--r--doc/topics/build_your_application.md2
-rw-r--r--doc/topics/cron/index.md2
-rw-r--r--doc/topics/git/bisect.md2
-rw-r--r--doc/topics/git/cherry_picking.md2
-rw-r--r--doc/topics/git/feature_branch_development.md2
-rw-r--r--doc/topics/git/feature_branching.md2
-rw-r--r--doc/topics/git/getting_started.md2
-rw-r--r--doc/topics/git/git_add.md2
-rw-r--r--doc/topics/git/git_log.md2
-rw-r--r--doc/topics/git/git_rebase.md2
-rw-r--r--doc/topics/git/how_to_install_git/index.md2
-rw-r--r--doc/topics/git/index.md2
-rw-r--r--doc/topics/git/lfs/index.md2
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md4
-rw-r--r--doc/topics/git/merge_conflicts.md2
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md2
-rw-r--r--doc/topics/git/partial_clone.md2
-rw-r--r--doc/topics/git/rollback_commits.md2
-rw-r--r--doc/topics/git/stash.md2
-rw-r--r--doc/topics/git/subtree.md2
-rw-r--r--doc/topics/git/tags.md2
-rw-r--r--doc/topics/git/terminology.md2
-rw-r--r--doc/topics/git/troubleshooting_git.md2
-rw-r--r--doc/topics/git/unstage.md2
-rw-r--r--doc/topics/git/useful_git_commands.md2
-rw-r--r--doc/topics/gitlab_flow.md2
-rw-r--r--doc/topics/offline/index.md2
-rw-r--r--doc/topics/offline/quick_start_guide.md2
-rw-r--r--doc/topics/plan_and_track.md2
-rw-r--r--doc/topics/release_your_application.md2
-rw-r--r--doc/topics/set_up_organization.md2
-rw-r--r--doc/tutorials/index.md8
-rw-r--r--doc/tutorials/make_your_first_git_commit.md2
-rw-r--r--doc/tutorials/move_personal_project_to_a_group.md2
-rw-r--r--doc/update/deprecations.md150
-rw-r--r--doc/update/index.md14
-rw-r--r--doc/update/mysql_to_postgresql.md2
-rw-r--r--doc/update/package/convert_to_ee.md2
-rw-r--r--doc/update/package/downgrade.md2
-rw-r--r--doc/update/package/index.md2
-rw-r--r--doc/update/patch_versions.md2
-rw-r--r--doc/update/plan_your_upgrade.md6
-rw-r--r--doc/update/removals.md2
-rw-r--r--doc/update/restore_after_failure.md2
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md2
-rw-r--r--doc/update/upgrading_from_source.md2
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md2
-rw-r--r--doc/update/with_downtime.md2
-rw-r--r--doc/update/zero_downtime.md6
-rw-r--r--doc/user/admin_area/analytics/dev_ops_reports.md4
-rw-r--r--doc/user/admin_area/analytics/index.md22
-rw-r--r--doc/user/admin_area/analytics/usage_trends.md4
-rw-r--r--doc/user/admin_area/appearance.md13
-rw-r--r--doc/user/admin_area/broadcast_messages.md2
-rw-r--r--doc/user/admin_area/credentials_inventory.md2
-rw-r--r--doc/user/admin_area/custom_project_templates.md2
-rw-r--r--doc/user/admin_area/diff_limits.md2
-rw-r--r--doc/user/admin_area/email_from_gitlab.md2
-rw-r--r--doc/user/admin_area/geo_sites.md2
-rw-r--r--doc/user/admin_area/index.md18
-rw-r--r--doc/user/admin_area/labels.md2
-rw-r--r--doc/user/admin_area/license.md2
-rw-r--r--doc/user/admin_area/license_file.md13
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md2
-rw-r--r--doc/user/admin_area/moderate_users.md11
-rw-r--r--doc/user/admin_area/monitoring/background_migrations.md2
-rw-r--r--doc/user/admin_area/monitoring/health_check.md4
-rw-r--r--doc/user/admin_area/reporting/git_abuse_rate_limit.md2
-rw-r--r--doc/user/admin_area/reporting/spamcheck.md4
-rw-r--r--doc/user/admin_area/review_abuse_reports.md4
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md17
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md14
-rw-r--r--doc/user/admin_area/settings/deprecated_api_rate_limits.md4
-rw-r--r--doc/user/admin_area/settings/email.md2
-rw-r--r--doc/user/admin_area/settings/external_authorization.md2
-rw-r--r--doc/user/admin_area/settings/files_api_rate_limits.md4
-rw-r--r--doc/user/admin_area/settings/floc.md2
-rw-r--r--doc/user/admin_area/settings/git_lfs_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/gitaly_timeouts.md2
-rw-r--r--doc/user/admin_area/settings/help_page.md2
-rw-r--r--doc/user/admin_area/settings/import_export_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/incident_management_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/index.md2
-rw-r--r--doc/user/admin_area/settings/instance_template_repository.md2
-rw-r--r--doc/user/admin_area/settings/package_registry_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md8
-rw-r--r--doc/user/admin_area/settings/protected_paths.md2
-rw-r--r--doc/user/admin_area/settings/push_event_activities_limit.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_issues_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_notes_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_users_api.md2
-rw-r--r--doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md2
-rw-r--r--doc/user/admin_area/settings/sidekiq_job_limits.md2
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/terms.md2
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md2
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md2
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md4
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md2
-rw-r--r--doc/user/admin_area/user_cohorts.md2
-rw-r--r--doc/user/analytics/ci_cd_analytics.md2
-rw-r--r--doc/user/analytics/code_review_analytics.md4
-rw-r--r--doc/user/analytics/index.md16
-rw-r--r--doc/user/analytics/issue_analytics.md4
-rw-r--r--doc/user/analytics/merge_request_analytics.md4
-rw-r--r--doc/user/analytics/productivity_analytics.md4
-rw-r--r--doc/user/analytics/repository_analytics.md4
-rw-r--r--doc/user/analytics/value_stream_analytics.md4
-rw-r--r--doc/user/application_security/api_fuzzing/create_har_files.md2
-rw-r--r--doc/user/application_security/api_fuzzing/index.md43
-rw-r--r--doc/user/application_security/cluster_image_scanning/index.md11
-rw-r--r--doc/user/application_security/configuration/index.md23
-rw-r--r--doc/user/application_security/container_scanning/index.md4
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md6
-rw-r--r--doc/user/application_security/cve_id_request.md2
-rw-r--r--doc/user/application_security/dast/browser_based.md17
-rw-r--r--doc/user/application_security/dast/checks/1004.1.md2
-rw-r--r--doc/user/application_security/dast/checks/16.1.md2
-rw-r--r--doc/user/application_security/dast/checks/16.10.md2
-rw-r--r--doc/user/application_security/dast/checks/16.2.md4
-rw-r--r--doc/user/application_security/dast/checks/16.3.md2
-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.md4
-rw-r--r--doc/user/application_security/dast/checks/16.7.md2
-rw-r--r--doc/user/application_security/dast/checks/16.8.md2
-rw-r--r--doc/user/application_security/dast/checks/16.9.md2
-rw-r--r--doc/user/application_security/dast/checks/200.1.md2
-rw-r--r--doc/user/application_security/dast/checks/209.1.md2
-rw-r--r--doc/user/application_security/dast/checks/209.2.md2
-rw-r--r--doc/user/application_security/dast/checks/287.1.md2
-rw-r--r--doc/user/application_security/dast/checks/287.2.md2
-rw-r--r--doc/user/application_security/dast/checks/319.1.md2
-rw-r--r--doc/user/application_security/dast/checks/352.1.md2
-rw-r--r--doc/user/application_security/dast/checks/359.1.md2
-rw-r--r--doc/user/application_security/dast/checks/359.2.md2
-rw-r--r--doc/user/application_security/dast/checks/548.1.md4
-rw-r--r--doc/user/application_security/dast/checks/598.1.md2
-rw-r--r--doc/user/application_security/dast/checks/598.2.md2
-rw-r--r--doc/user/application_security/dast/checks/598.3.md2
-rw-r--r--doc/user/application_security/dast/checks/601.1.md2
-rw-r--r--doc/user/application_security/dast/checks/614.1.md2
-rw-r--r--doc/user/application_security/dast/checks/693.1.md2
-rw-r--r--doc/user/application_security/dast/checks/798.1.md2
-rw-r--r--doc/user/application_security/dast/checks/798.10.md2
-rw-r--r--doc/user/application_security/dast/checks/798.100.md2
-rw-r--r--doc/user/application_security/dast/checks/798.101.md2
-rw-r--r--doc/user/application_security/dast/checks/798.102.md2
-rw-r--r--doc/user/application_security/dast/checks/798.103.md2
-rw-r--r--doc/user/application_security/dast/checks/798.104.md2
-rw-r--r--doc/user/application_security/dast/checks/798.105.md2
-rw-r--r--doc/user/application_security/dast/checks/798.106.md2
-rw-r--r--doc/user/application_security/dast/checks/798.107.md2
-rw-r--r--doc/user/application_security/dast/checks/798.108.md2
-rw-r--r--doc/user/application_security/dast/checks/798.109.md2
-rw-r--r--doc/user/application_security/dast/checks/798.11.md2
-rw-r--r--doc/user/application_security/dast/checks/798.110.md2
-rw-r--r--doc/user/application_security/dast/checks/798.111.md2
-rw-r--r--doc/user/application_security/dast/checks/798.112.md2
-rw-r--r--doc/user/application_security/dast/checks/798.113.md2
-rw-r--r--doc/user/application_security/dast/checks/798.114.md2
-rw-r--r--doc/user/application_security/dast/checks/798.115.md2
-rw-r--r--doc/user/application_security/dast/checks/798.116.md2
-rw-r--r--doc/user/application_security/dast/checks/798.117.md2
-rw-r--r--doc/user/application_security/dast/checks/798.118.md2
-rw-r--r--doc/user/application_security/dast/checks/798.119.md2
-rw-r--r--doc/user/application_security/dast/checks/798.12.md2
-rw-r--r--doc/user/application_security/dast/checks/798.120.md2
-rw-r--r--doc/user/application_security/dast/checks/798.121.md2
-rw-r--r--doc/user/application_security/dast/checks/798.122.md2
-rw-r--r--doc/user/application_security/dast/checks/798.123.md2
-rw-r--r--doc/user/application_security/dast/checks/798.124.md2
-rw-r--r--doc/user/application_security/dast/checks/798.125.md2
-rw-r--r--doc/user/application_security/dast/checks/798.126.md2
-rw-r--r--doc/user/application_security/dast/checks/798.127.md2
-rw-r--r--doc/user/application_security/dast/checks/798.128.md2
-rw-r--r--doc/user/application_security/dast/checks/798.13.md2
-rw-r--r--doc/user/application_security/dast/checks/798.14.md2
-rw-r--r--doc/user/application_security/dast/checks/798.15.md2
-rw-r--r--doc/user/application_security/dast/checks/798.16.md2
-rw-r--r--doc/user/application_security/dast/checks/798.17.md2
-rw-r--r--doc/user/application_security/dast/checks/798.18.md2
-rw-r--r--doc/user/application_security/dast/checks/798.19.md2
-rw-r--r--doc/user/application_security/dast/checks/798.2.md2
-rw-r--r--doc/user/application_security/dast/checks/798.20.md2
-rw-r--r--doc/user/application_security/dast/checks/798.21.md2
-rw-r--r--doc/user/application_security/dast/checks/798.22.md2
-rw-r--r--doc/user/application_security/dast/checks/798.23.md2
-rw-r--r--doc/user/application_security/dast/checks/798.24.md2
-rw-r--r--doc/user/application_security/dast/checks/798.25.md2
-rw-r--r--doc/user/application_security/dast/checks/798.26.md2
-rw-r--r--doc/user/application_security/dast/checks/798.27.md2
-rw-r--r--doc/user/application_security/dast/checks/798.28.md2
-rw-r--r--doc/user/application_security/dast/checks/798.29.md2
-rw-r--r--doc/user/application_security/dast/checks/798.3.md2
-rw-r--r--doc/user/application_security/dast/checks/798.30.md2
-rw-r--r--doc/user/application_security/dast/checks/798.31.md2
-rw-r--r--doc/user/application_security/dast/checks/798.32.md2
-rw-r--r--doc/user/application_security/dast/checks/798.33.md2
-rw-r--r--doc/user/application_security/dast/checks/798.34.md2
-rw-r--r--doc/user/application_security/dast/checks/798.35.md2
-rw-r--r--doc/user/application_security/dast/checks/798.36.md2
-rw-r--r--doc/user/application_security/dast/checks/798.37.md2
-rw-r--r--doc/user/application_security/dast/checks/798.38.md2
-rw-r--r--doc/user/application_security/dast/checks/798.39.md2
-rw-r--r--doc/user/application_security/dast/checks/798.4.md2
-rw-r--r--doc/user/application_security/dast/checks/798.40.md2
-rw-r--r--doc/user/application_security/dast/checks/798.41.md2
-rw-r--r--doc/user/application_security/dast/checks/798.42.md2
-rw-r--r--doc/user/application_security/dast/checks/798.43.md2
-rw-r--r--doc/user/application_security/dast/checks/798.44.md2
-rw-r--r--doc/user/application_security/dast/checks/798.46.md2
-rw-r--r--doc/user/application_security/dast/checks/798.47.md2
-rw-r--r--doc/user/application_security/dast/checks/798.48.md2
-rw-r--r--doc/user/application_security/dast/checks/798.49.md2
-rw-r--r--doc/user/application_security/dast/checks/798.5.md2
-rw-r--r--doc/user/application_security/dast/checks/798.50.md2
-rw-r--r--doc/user/application_security/dast/checks/798.52.md2
-rw-r--r--doc/user/application_security/dast/checks/798.53.md2
-rw-r--r--doc/user/application_security/dast/checks/798.54.md2
-rw-r--r--doc/user/application_security/dast/checks/798.55.md2
-rw-r--r--doc/user/application_security/dast/checks/798.56.md2
-rw-r--r--doc/user/application_security/dast/checks/798.57.md2
-rw-r--r--doc/user/application_security/dast/checks/798.58.md2
-rw-r--r--doc/user/application_security/dast/checks/798.59.md2
-rw-r--r--doc/user/application_security/dast/checks/798.6.md2
-rw-r--r--doc/user/application_security/dast/checks/798.60.md2
-rw-r--r--doc/user/application_security/dast/checks/798.61.md2
-rw-r--r--doc/user/application_security/dast/checks/798.62.md2
-rw-r--r--doc/user/application_security/dast/checks/798.63.md2
-rw-r--r--doc/user/application_security/dast/checks/798.64.md2
-rw-r--r--doc/user/application_security/dast/checks/798.65.md2
-rw-r--r--doc/user/application_security/dast/checks/798.66.md2
-rw-r--r--doc/user/application_security/dast/checks/798.67.md2
-rw-r--r--doc/user/application_security/dast/checks/798.68.md2
-rw-r--r--doc/user/application_security/dast/checks/798.69.md2
-rw-r--r--doc/user/application_security/dast/checks/798.7.md2
-rw-r--r--doc/user/application_security/dast/checks/798.70.md2
-rw-r--r--doc/user/application_security/dast/checks/798.72.md2
-rw-r--r--doc/user/application_security/dast/checks/798.74.md2
-rw-r--r--doc/user/application_security/dast/checks/798.75.md2
-rw-r--r--doc/user/application_security/dast/checks/798.77.md2
-rw-r--r--doc/user/application_security/dast/checks/798.78.md2
-rw-r--r--doc/user/application_security/dast/checks/798.8.md2
-rw-r--r--doc/user/application_security/dast/checks/798.80.md2
-rw-r--r--doc/user/application_security/dast/checks/798.81.md2
-rw-r--r--doc/user/application_security/dast/checks/798.82.md2
-rw-r--r--doc/user/application_security/dast/checks/798.83.md2
-rw-r--r--doc/user/application_security/dast/checks/798.84.md2
-rw-r--r--doc/user/application_security/dast/checks/798.86.md2
-rw-r--r--doc/user/application_security/dast/checks/798.87.md2
-rw-r--r--doc/user/application_security/dast/checks/798.88.md2
-rw-r--r--doc/user/application_security/dast/checks/798.89.md2
-rw-r--r--doc/user/application_security/dast/checks/798.9.md2
-rw-r--r--doc/user/application_security/dast/checks/798.90.md2
-rw-r--r--doc/user/application_security/dast/checks/798.91.md2
-rw-r--r--doc/user/application_security/dast/checks/798.92.md2
-rw-r--r--doc/user/application_security/dast/checks/798.93.md2
-rw-r--r--doc/user/application_security/dast/checks/798.94.md2
-rw-r--r--doc/user/application_security/dast/checks/798.95.md2
-rw-r--r--doc/user/application_security/dast/checks/798.96.md2
-rw-r--r--doc/user/application_security/dast/checks/798.97.md2
-rw-r--r--doc/user/application_security/dast/checks/798.98.md2
-rw-r--r--doc/user/application_security/dast/checks/798.99.md2
-rw-r--r--doc/user/application_security/dast/checks/829.1.md2
-rw-r--r--doc/user/application_security/dast/checks/829.2.md2
-rw-r--r--doc/user/application_security/dast/checks/index.md2
-rw-r--r--doc/user/application_security/dast/dast_troubleshooting.md2
-rw-r--r--doc/user/application_security/dast/index.md37
-rw-r--r--doc/user/application_security/dast/run_dast_offline.md2
-rw-r--r--doc/user/application_security/dast_api/index.md54
-rw-r--r--doc/user/application_security/dependency_list/index.md4
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md2
-rw-r--r--doc/user/application_security/dependency_scanning/index.md118
-rw-r--r--doc/user/application_security/generate_test_vulnerabilities/index.md18
-rw-r--r--doc/user/application_security/get-started-security.md6
-rw-r--r--doc/user/application_security/iac_scanning/index.md4
-rw-r--r--doc/user/application_security/img/secure_tools_and_cicd_stages.pngbin0 -> 42240 bytes
-rw-r--r--doc/user/application_security/index.md50
-rw-r--r--doc/user/application_security/offline_deployments/index.md4
-rw-r--r--doc/user/application_security/policies/img/scan_execution_policy_rule_mode_v15_5.pngbin0 -> 23688 bytes
-rw-r--r--doc/user/application_security/policies/img/scan_execution_policy_yaml_mode_v14_7.pngbin25442 -> 0 bytes
-rw-r--r--doc/user/application_security/policies/index.md4
-rw-r--r--doc/user/application_security/policies/scan-execution-policies.md53
-rw-r--r--doc/user/application_security/policies/scan-result-policies.md2
-rw-r--r--doc/user/application_security/sast/analyzers.md2
-rw-r--r--doc/user/application_security/sast/customize_rulesets.md10
-rw-r--r--doc/user/application_security/sast/index.md10
-rw-r--r--doc/user/application_security/secret_detection/index.md25
-rw-r--r--doc/user/application_security/secret_detection/post_processing.md2
-rw-r--r--doc/user/application_security/security_dashboard/index.md2
-rw-r--r--doc/user/application_security/terminology/index.md89
-rw-r--r--doc/user/application_security/vulnerabilities/index.md4
-rw-r--r--doc/user/application_security/vulnerabilities/severities.md6
-rw-r--r--doc/user/application_security/vulnerability_report/index.md10
-rw-r--r--doc/user/application_security/vulnerability_report/pipeline.md2
-rw-r--r--doc/user/asciidoc.md2
-rw-r--r--doc/user/award_emojis.md2
-rw-r--r--doc/user/clusters/agent/ci_cd_tunnel.md11
-rw-r--r--doc/user/clusters/agent/ci_cd_workflow.md28
-rw-r--r--doc/user/clusters/agent/gitops.md2
-rw-r--r--doc/user/clusters/agent/gitops/helm.md7
-rw-r--r--doc/user/clusters/agent/gitops/secrets_management.md2
-rw-r--r--doc/user/clusters/agent/index.md4
-rw-r--r--doc/user/clusters/agent/install/index.md7
-rw-r--r--doc/user/clusters/agent/repository.md11
-rw-r--r--doc/user/clusters/agent/troubleshooting.md2
-rw-r--r--doc/user/clusters/agent/vulnerabilities.md2
-rw-r--r--doc/user/clusters/agent/work_with_agent.md6
-rw-r--r--doc/user/clusters/applications.md13
-rw-r--r--doc/user/clusters/cost_management.md2
-rw-r--r--doc/user/clusters/create/index.md2
-rw-r--r--doc/user/clusters/crossplane.md13
-rw-r--r--doc/user/clusters/environments.md2
-rw-r--r--doc/user/clusters/integrations.md8
-rw-r--r--doc/user/clusters/management_project.md2
-rw-r--r--doc/user/clusters/management_project_template.md2
-rw-r--r--doc/user/clusters/migrating_from_gma_to_project_template.md2
-rw-r--r--doc/user/compliance/compliance_report/index.md4
-rw-r--r--doc/user/compliance/index.md2
-rw-r--r--doc/user/compliance/license_compliance/index.md65
-rw-r--r--doc/user/crm/index.md4
-rw-r--r--doc/user/discussions/index.md6
-rw-r--r--doc/user/feature_flags.md2
-rw-r--r--doc/user/free_user_limit.md25
-rw-r--r--doc/user/gitlab_com/index.md43
-rw-r--r--doc/user/group/access_and_permissions.md8
-rw-r--r--doc/user/group/clusters/index.md2
-rw-r--r--doc/user/group/contribution_analytics/index.md4
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/devops_adoption/index.md4
-rw-r--r--doc/user/group/epics/epic_boards.md2
-rw-r--r--doc/user/group/epics/index.md28
-rw-r--r--doc/user/group/epics/linked_epics.md2
-rw-r--r--doc/user/group/epics/manage_epics.md25
-rw-r--r--doc/user/group/import/index.md42
-rw-r--r--doc/user/group/index.md2
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.pngbin29784 -> 0 bytes
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart_v15_4.pngbin0 -> 75321 bytes
-rw-r--r--doc/user/group/insights/index.md50
-rw-r--r--doc/user/group/issues_analytics/index.md2
-rw-r--r--doc/user/group/iterations/index.md278
-rw-r--r--doc/user/group/manage.md265
-rw-r--r--doc/user/group/planning_hierarchy/index.md2
-rw-r--r--doc/user/group/repositories_analytics/index.md2
-rw-r--r--doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.pngbin0 -> 25453 bytes
-rw-r--r--doc/user/group/roadmap/index.md12
-rw-r--r--doc/user/group/saml_sso/example_saml_config.md4
-rw-r--r--doc/user/group/saml_sso/group_sync.md2
-rw-r--r--doc/user/group/saml_sso/index.md44
-rw-r--r--doc/user/group/saml_sso/scim_setup.md188
-rw-r--r--doc/user/group/saml_sso/troubleshooting.md23
-rw-r--r--doc/user/group/saml_sso/troubleshooting_scim.md129
-rw-r--r--doc/user/group/settings/group_access_tokens.md15
-rw-r--r--doc/user/group/settings/import_export.md15
-rw-r--r--doc/user/group/subgroups/index.md4
-rw-r--r--doc/user/group/value_stream_analytics/index.md12
-rw-r--r--doc/user/index.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/index.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/new_civo_cluster.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/new_eks_cluster.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/new_gke_cluster.md2
-rw-r--r--doc/user/infrastructure/clusters/deploy/inventory_object.md2
-rw-r--r--doc/user/infrastructure/clusters/index.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/clusters_health.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md12
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/runner.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/vault.md4
-rw-r--r--doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md4
-rw-r--r--doc/user/infrastructure/iac/index.md6
-rw-r--r--doc/user/infrastructure/iac/mr_integration.md4
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md2
-rw-r--r--doc/user/infrastructure/iac/troubleshooting.md2
-rw-r--r--doc/user/infrastructure/index.md2
-rw-r--r--doc/user/instance/clusters/index.md2
-rw-r--r--doc/user/markdown.md3
-rw-r--r--doc/user/namespace/index.md2
-rw-r--r--doc/user/operations_dashboard/index.md7
-rw-r--r--doc/user/packages/composer_repository/index.md2
-rw-r--r--doc/user/packages/conan_repository/index.md2
-rw-r--r--doc/user/packages/container_registry/index.md20
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_data_transfer.md2
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md61
-rw-r--r--doc/user/packages/debian_repository/index.md2
-rw-r--r--doc/user/packages/dependency_proxy/index.md8
-rw-r--r--doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md2
-rw-r--r--doc/user/packages/generic_packages/index.md2
-rw-r--r--doc/user/packages/go_proxy/index.md2
-rw-r--r--doc/user/packages/harbor_container_registry/index.md10
-rw-r--r--doc/user/packages/helm_repository/index.md4
-rw-r--r--doc/user/packages/index.md2
-rw-r--r--doc/user/packages/infrastructure_registry/index.md2
-rw-r--r--doc/user/packages/maven_repository/index.md145
-rw-r--r--doc/user/packages/npm_registry/index.md2
-rw-r--r--doc/user/packages/nuget_repository/index.md10
-rw-r--r--doc/user/packages/package_registry/index.md4
-rw-r--r--doc/user/packages/package_registry/reduce_package_registry_storage.md6
-rw-r--r--doc/user/packages/pypi_repository/index.md4
-rw-r--r--doc/user/packages/rubygems_registry/index.md4
-rw-r--r--doc/user/packages/terraform_module_registry/index.md2
-rw-r--r--doc/user/packages/workflows/project_registry.md2
-rw-r--r--doc/user/packages/workflows/working_with_monorepos.md4
-rw-r--r--doc/user/permissions.md8
-rw-r--r--doc/user/profile/account/create_accounts.md2
-rw-r--r--doc/user/profile/account/delete_account.md2
-rw-r--r--doc/user/profile/account/two_factor_authentication.md11
-rw-r--r--doc/user/profile/active_sessions.md2
-rw-r--r--doc/user/profile/img/unknown_sign_in_email_v14_0.pngbin21301 -> 0 bytes
-rw-r--r--doc/user/profile/index.md27
-rw-r--r--doc/user/profile/notifications.md32
-rw-r--r--doc/user/profile/personal_access_tokens.md21
-rw-r--r--doc/user/profile/preferences.md6
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md35
-rw-r--r--doc/user/profile/user_passwords.md76
-rw-r--r--doc/user/project/autocomplete_characters.md2
-rw-r--r--doc/user/project/badges.md2
-rw-r--r--doc/user/project/canary_deployments.md2
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md2
-rw-r--r--doc/user/project/clusters/add_existing_cluster.md6
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md4
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md2
-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/kubernetes_pod_logs.md4
-rw-r--r--doc/user/project/clusters/multiple_kubernetes_clusters.md2
-rw-r--r--doc/user/project/clusters/runbooks/index.md4
-rw-r--r--doc/user/project/clusters/serverless/aws.md11
-rw-r--r--doc/user/project/clusters/serverless/index.md11
-rw-r--r--doc/user/project/code_intelligence.md2
-rw-r--r--doc/user/project/code_owners.md12
-rw-r--r--doc/user/project/deploy_boards.md6
-rw-r--r--doc/user/project/deploy_keys/index.md37
-rw-r--r--doc/user/project/deploy_tokens/img/deploy_tokens_ui.pngbin35336 -> 0 bytes
-rw-r--r--doc/user/project/deploy_tokens/index.md277
-rw-r--r--doc/user/project/description_templates.md6
-rw-r--r--doc/user/project/file_lock.md2
-rw-r--r--doc/user/project/git_attributes.md2
-rw-r--r--doc/user/project/highlighting.md2
-rw-r--r--doc/user/project/import/bitbucket.md2
-rw-r--r--doc/user/project/import/bitbucket_server.md2
-rw-r--r--doc/user/project/import/clearcase.md2
-rw-r--r--doc/user/project/import/cvs.md2
-rw-r--r--doc/user/project/import/fogbugz.md2
-rw-r--r--doc/user/project/import/gitea.md2
-rw-r--r--doc/user/project/import/github.md57
-rw-r--r--doc/user/project/import/gitlab_com.md2
-rw-r--r--doc/user/project/import/index.md2
-rw-r--r--doc/user/project/import/jira.md2
-rw-r--r--doc/user/project/import/manifest.md4
-rw-r--r--doc/user/project/import/perforce.md2
-rw-r--r--doc/user/project/import/phabricator.md2
-rw-r--r--doc/user/project/import/repo_by_url.md2
-rw-r--r--doc/user/project/import/svn.md2
-rw-r--r--doc/user/project/import/tfvc.md6
-rw-r--r--doc/user/project/index.md2
-rw-r--r--doc/user/project/insights/img/project_insights.pngbin26534 -> 0 bytes
-rw-r--r--doc/user/project/insights/index.md253
-rw-r--r--doc/user/project/integrations/asana.md4
-rw-r--r--doc/user/project/integrations/bamboo.md4
-rw-r--r--doc/user/project/integrations/bugzilla.md4
-rw-r--r--doc/user/project/integrations/custom_issue_tracker.md4
-rw-r--r--doc/user/project/integrations/discord_notifications.md4
-rw-r--r--doc/user/project/integrations/emails_on_push.md4
-rw-r--r--doc/user/project/integrations/ewm.md4
-rw-r--r--doc/user/project/integrations/github.md4
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md20
-rw-r--r--doc/user/project/integrations/hangouts_chat.md4
-rw-r--r--doc/user/project/integrations/harbor.md6
-rw-r--r--doc/user/project/integrations/index.md4
-rw-r--r--doc/user/project/integrations/irker.md4
-rw-r--r--doc/user/project/integrations/mattermost.md4
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md4
-rw-r--r--doc/user/project/integrations/microsoft_teams.md6
-rw-r--r--doc/user/project/integrations/mock_ci.md4
-rw-r--r--doc/user/project/integrations/overview.md11
-rw-r--r--doc/user/project/integrations/pipeline_status_emails.md4
-rw-r--r--doc/user/project/integrations/pivotal_tracker.md4
-rw-r--r--doc/user/project/integrations/prometheus.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/cloudwatch.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/haproxy.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md4
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md2
-rw-r--r--doc/user/project/integrations/pumble.md4
-rw-r--r--doc/user/project/integrations/redmine.md4
-rw-r--r--doc/user/project/integrations/servicenow.md4
-rw-r--r--doc/user/project/integrations/shimo.md4
-rw-r--r--doc/user/project/integrations/slack.md22
-rw-r--r--doc/user/project/integrations/slack_slash_commands.md4
-rw-r--r--doc/user/project/integrations/unify_circuit.md4
-rw-r--r--doc/user/project/integrations/webex_teams.md6
-rw-r--r--doc/user/project/integrations/webhook_events.md5
-rw-r--r--doc/user/project/integrations/webhooks.md106
-rw-r--r--doc/user/project/integrations/youtrack.md4
-rw-r--r--doc/user/project/integrations/zentao.md4
-rw-r--r--doc/user/project/issue_board.md14
-rw-r--r--doc/user/project/issues/associate_zoom_meeting.md2
-rw-r--r--doc/user/project/issues/confidential_issues.md2
-rw-r--r--doc/user/project/issues/crosslinking_issues.md2
-rw-r--r--doc/user/project/issues/csv_export.md4
-rw-r--r--doc/user/project/issues/csv_import.md2
-rw-r--r--doc/user/project/issues/design_management.md2
-rw-r--r--doc/user/project/issues/due_dates.md2
-rw-r--r--doc/user/project/issues/index.md2
-rw-r--r--doc/user/project/issues/issue_weight.md2
-rw-r--r--doc/user/project/issues/managing_issues.md5
-rw-r--r--doc/user/project/issues/multiple_assignees_for_issues.md2
-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.md6
-rw-r--r--doc/user/project/members/index.md6
-rw-r--r--doc/user/project/members/share_project_with_groups.md2
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md11
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md2
-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.md4
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md2
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md11
-rw-r--r--doc/user/project/merge_requests/changes.md2
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md2
-rw-r--r--doc/user/project/merge_requests/code_quality.md11
-rw-r--r--doc/user/project/merge_requests/commit_templates.md2
-rw-r--r--doc/user/project/merge_requests/commits.md2
-rw-r--r--doc/user/project/merge_requests/confidential.md2
-rw-r--r--doc/user/project/merge_requests/conflicts.md2
-rw-r--r--doc/user/project/merge_requests/creating_merge_requests.md9
-rw-r--r--doc/user/project/merge_requests/csv_export.md2
-rw-r--r--doc/user/project/merge_requests/dependencies.md2
-rw-r--r--doc/user/project/merge_requests/drafts.md2
-rw-r--r--doc/user/project/merge_requests/fail_fast_testing.md11
-rw-r--r--doc/user/project/merge_requests/fast_forward_merge.md11
-rw-r--r--doc/user/project/merge_requests/getting_started.md2
-rw-r--r--doc/user/project/merge_requests/img/dependencies_edit_inaccessible_v12_4.pngbin19518 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/dependencies_view_v12_2.pngbin13579 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/index.md6
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md11
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md2
-rw-r--r--doc/user/project/merge_requests/methods/index.md2
-rw-r--r--doc/user/project/merge_requests/revert_changes.md2
-rw-r--r--doc/user/project/merge_requests/reviews/data_usage.md18
-rw-r--r--doc/user/project/merge_requests/reviews/index.md14
-rw-r--r--doc/user/project/merge_requests/reviews/suggestions.md2
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md2
-rw-r--r--doc/user/project/merge_requests/status_checks.md16
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md11
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md11
-rw-r--r--doc/user/project/merge_requests/versions.md2
-rw-r--r--doc/user/project/merge_requests/widgets.md4
-rw-r--r--doc/user/project/milestones/burndown_and_burnup_charts.md2
-rw-r--r--doc/user/project/milestones/index.md5
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md4
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md4
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md2
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md4
-rw-r--r--doc/user/project/pages/getting_started/pages_ci_cd_template.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_forked_sample_project.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_new_project_template.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_ui.md2
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--doc/user/project/pages/index.md2
-rw-r--r--doc/user/project/pages/introduction.md9
-rw-r--r--doc/user/project/pages/pages_access_control.md2
-rw-r--r--doc/user/project/pages/public_folder.md12
-rw-r--r--doc/user/project/pages/redirects.md2
-rw-r--r--doc/user/project/protected_branches.md2
-rw-r--r--doc/user/project/protected_tags.md2
-rw-r--r--doc/user/project/push_options.md16
-rw-r--r--doc/user/project/quick_actions.md11
-rw-r--r--doc/user/project/releases/index.md36
-rw-r--r--doc/user/project/releases/release_cicd_examples.md2
-rw-r--r--doc/user/project/releases/release_cli.md2
-rw-r--r--doc/user/project/releases/release_fields.md2
-rw-r--r--doc/user/project/remote_development/index.md139
-rw-r--r--doc/user/project/repository/branches/default.md2
-rw-r--r--doc/user/project/repository/branches/index.md23
-rw-r--r--doc/user/project/repository/csv.md2
-rw-r--r--doc/user/project/repository/file_finder.md2
-rw-r--r--doc/user/project/repository/forking_workflow.md2
-rw-r--r--doc/user/project/repository/git_blame.md2
-rw-r--r--doc/user/project/repository/git_history.md2
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md2
-rw-r--r--doc/user/project/repository/index.md32
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md2
-rw-r--r--doc/user/project/repository/managing_large_repositories.md8
-rw-r--r--doc/user/project/repository/mirror/bidirectional.md2
-rw-r--r--doc/user/project/repository/mirror/index.md37
-rw-r--r--doc/user/project/repository/mirror/pull.md2
-rw-r--r--doc/user/project/repository/mirror/push.md2
-rw-r--r--doc/user/project/repository/push_rules.md36
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md28
-rw-r--r--doc/user/project/repository/vscode.md2
-rw-r--r--doc/user/project/repository/web_editor.md9
-rw-r--r--doc/user/project/repository/x509_signed_commits/index.md4
-rw-r--r--doc/user/project/requirements/index.md2
-rw-r--r--doc/user/project/service_desk.md4
-rw-r--r--doc/user/project/settings/import_export.md21
-rw-r--r--doc/user/project/settings/index.md228
-rw-r--r--doc/user/project/settings/project_access_tokens.md13
-rw-r--r--doc/user/project/static_site_editor/index.md50
-rw-r--r--doc/user/project/time_tracking.md2
-rw-r--r--doc/user/project/web_ide/index.md18
-rw-r--r--doc/user/project/wiki/group.md2
-rw-r--r--doc/user/project/wiki/index.md9
-rw-r--r--doc/user/project/working_with_projects.md109
-rw-r--r--doc/user/public_access.md2
-rw-r--r--doc/user/report_abuse.md2
-rw-r--r--doc/user/reserved_names.md2
-rw-r--r--doc/user/search/advanced_search.md41
-rw-r--r--doc/user/search/global_search/advanced_search_syntax.md3
-rw-r--r--doc/user/search/index.md55
-rw-r--r--doc/user/shortcuts.md4
-rw-r--r--doc/user/snippets.md2
-rw-r--r--doc/user/ssh.md8
-rw-r--r--doc/user/tasks.md41
-rw-r--r--doc/user/todos.md2
-rw-r--r--doc/user/upgrade_email_bypass.md2
-rw-r--r--doc/user/usage_quotas.md45
-rw-r--r--doc/user/workspace/index.md4
-rw-r--r--glfm_specification/example_snapshots/examples_index.yml48
-rw-r--r--glfm_specification/example_snapshots/html.yml116
-rw-r--r--glfm_specification/example_snapshots/markdown.yml64
-rw-r--r--glfm_specification/example_snapshots/prosemirror_json.yml250
-rw-r--r--glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md10226
-rw-r--r--glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt10227
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt389
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml12
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml1
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml16
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md111
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md (renamed from glfm_specification/input/gitlab_flavored_markdown/glfm_intro.txt)0
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md277
-rw-r--r--glfm_specification/output/spec.html9220
-rw-r--r--glfm_specification/output/spec.txt109
-rw-r--r--jest.config.base.js4
-rw-r--r--lefthook.yml5
-rw-r--r--lib/api/access_requests.rb6
-rw-r--r--lib/api/admin/batched_background_migrations.rb10
-rw-r--r--lib/api/alert_management_alerts.rb3
-rw-r--r--lib/api/api.rb12
-rw-r--r--lib/api/applications.rb3
-rw-r--r--lib/api/badges.rb1
-rw-r--r--lib/api/branches.rb8
-rw-r--r--lib/api/bulk_imports.rb12
-rw-r--r--lib/api/ci/job_artifacts.rb4
-rw-r--r--lib/api/ci/resource_groups.rb19
-rw-r--r--lib/api/ci/runner.rb2
-rw-r--r--lib/api/ci/secure_files.rb4
-rw-r--r--lib/api/ci/variables.rb11
-rw-r--r--lib/api/commit_statuses.rb4
-rw-r--r--lib/api/concerns/packages/npm_endpoints.rb7
-rw-r--r--lib/api/debian_project_packages.rb6
-rw-r--r--lib/api/deploy_keys.rb4
-rw-r--r--lib/api/entities/bulk_imports/entity_failure.rb9
-rw-r--r--lib/api/entities/ci/job_basic.rb2
-rw-r--r--lib/api/entities/ci/runner.rb4
-rw-r--r--lib/api/entities/license.rb1
-rw-r--r--lib/api/entities/license_basic.rb8
-rw-r--r--lib/api/entities/merge_request_approvals.rb2
-rw-r--r--lib/api/entities/metadata.rb15
-rw-r--r--lib/api/entities/ml/mlflow/experiment.rb20
-rw-r--r--lib/api/entities/ml/mlflow/get_experiment.rb13
-rw-r--r--lib/api/entities/ml/mlflow/list_experiment.rb13
-rw-r--r--lib/api/entities/ml/mlflow/metric.rb16
-rw-r--r--lib/api/entities/ml/mlflow/run.rb5
-rw-r--r--lib/api/entities/ml/mlflow/run_param.rb14
-rw-r--r--lib/api/entities/ml/mlflow/update_run.rb2
-rw-r--r--lib/api/entities/project.rb3
-rw-r--r--lib/api/entities/user_with_admin.rb1
-rw-r--r--lib/api/environments.rb4
-rw-r--r--lib/api/features.rb62
-rw-r--r--lib/api/generic_packages.rb12
-rw-r--r--lib/api/group_import.rb2
-rw-r--r--lib/api/groups.rb6
-rw-r--r--lib/api/helm_packages.rb14
-rw-r--r--lib/api/helpers.rb54
-rw-r--r--lib/api/helpers/groups_helpers.rb2
-rw-r--r--lib/api/helpers/open_api.rb19
-rw-r--r--lib/api/helpers/packages/basic_auth_helpers.rb22
-rw-r--r--lib/api/helpers/packages/dependency_proxy_helpers.rb18
-rw-r--r--lib/api/helpers/personal_access_tokens_helpers.rb13
-rw-r--r--lib/api/helpers/projects_helpers.rb6
-rw-r--r--lib/api/import_github.rb16
-rw-r--r--lib/api/internal/pages.rb3
-rw-r--r--lib/api/issues.rb18
-rw-r--r--lib/api/maven_packages.rb8
-rw-r--r--lib/api/merge_requests.rb3
-rw-r--r--lib/api/metadata.rb73
-rw-r--r--lib/api/ml/mlflow.rb191
-rw-r--r--lib/api/notes.rb2
-rw-r--r--lib/api/pages_domains.rb12
-rw-r--r--lib/api/personal_access_tokens.rb10
-rw-r--r--lib/api/personal_access_tokens/self_information.rb30
-rw-r--r--lib/api/personal_access_tokens/self_revocation.rb26
-rw-r--r--lib/api/project_export.rb3
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/api/pypi_packages.rb7
-rw-r--r--lib/api/search.rb10
-rw-r--r--lib/api/settings.rb2
-rw-r--r--lib/api/snippets.rb5
-rw-r--r--lib/api/support/git_access_actor.rb2
-rw-r--r--lib/api/templates.rb24
-rw-r--r--lib/api/todos.rb26
-rw-r--r--lib/api/users.rb11
-rw-r--r--lib/api/version.rb34
-rw-r--r--lib/api/wikis.rb2
-rw-r--r--lib/banzai/filter/markdown_engines/common_mark.rb2
-rw-r--r--lib/banzai/filter/pathological_markdown_filter.rb27
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb4
-rw-r--r--lib/banzai/filter/truncate_visible_filter.rb69
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb11
-rw-r--r--lib/banzai/pipeline/ascii_doc_pipeline.rb1
-rw-r--r--lib/banzai/pipeline/plain_markdown_pipeline.rb1
-rw-r--r--lib/banzai/pipeline/post_process_pipeline.rb1
-rw-r--r--lib/bitbucket/client.rb5
-rw-r--r--lib/bulk_imports/common/pipelines/entity_finisher.rb5
-rw-r--r--lib/bulk_imports/common/pipelines/wiki_pipeline.rb5
-rw-r--r--lib/bulk_imports/common/rest/get_badges_query.rb5
-rw-r--r--lib/bulk_imports/features.rb19
-rw-r--r--lib/bulk_imports/groups/extractors/subgroups_extractor.rb4
-rw-r--r--lib/bulk_imports/groups/graphql/get_group_query.rb2
-rw-r--r--lib/bulk_imports/groups/graphql/get_projects_query.rb1
-rw-r--r--lib/bulk_imports/groups/pipelines/project_entities_pipeline.rb3
-rw-r--r--lib/bulk_imports/groups/stage.rb8
-rw-r--r--lib/bulk_imports/groups/transformers/group_attributes_transformer.rb97
-rw-r--r--lib/bulk_imports/network_error.rb34
-rw-r--r--lib/bulk_imports/pipeline.rb6
-rw-r--r--lib/bulk_imports/pipeline/context.rb4
-rw-r--r--lib/bulk_imports/pipeline/runner.rb13
-rw-r--r--lib/bulk_imports/projects/graphql/get_project_query.rb1
-rw-r--r--lib/container_registry/client.rb9
-rw-r--r--lib/container_registry/gitlab_api_client.rb16
-rw-r--r--lib/feature/shared.rb2
-rw-r--r--lib/gitlab/application_context.rb3
-rw-r--r--lib/gitlab/auth.rb2
-rw-r--r--lib/gitlab/auth/o_auth/user.rb15
-rw-r--r--lib/gitlab/auth_logger.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_epic_cache_counts.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_internal_on_notes.rb16
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_details.rb27
-rw-r--r--lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities.rb33
-rw-r--r--lib/gitlab/background_migration/destroy_invalid_members.rb23
-rw-r--r--lib/gitlab/background_migration/populate_approval_merge_request_rules_with_security_orchestration.rb15
-rw-r--r--lib/gitlab/background_migration/populate_approval_project_rules_with_security_orchestration.rb15
-rw-r--r--lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values.rb31
-rw-r--r--lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values.rb29
-rw-r--r--lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status.rb24
-rw-r--r--lib/gitlab/batch_pop_queueing.rb113
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb12
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb2
-rw-r--r--lib/gitlab/cache/helpers.rb13
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/changes.rb1
-rw-r--r--lib/gitlab/ci/config.rb4
-rw-r--r--lib/gitlab/ci/config/entry/current_variables.rb49
-rw-r--r--lib/gitlab/ci/config/entry/legacy_variables.rb46
-rw-r--r--lib/gitlab/ci/config/entry/root.rb3
-rw-r--r--lib/gitlab/ci/config/entry/timeout.rb2
-rw-r--r--lib/gitlab/ci/config/entry/variable.rb31
-rw-r--r--lib/gitlab/ci/config/entry/variables.rb36
-rw-r--r--lib/gitlab/ci/config/entry/workflow.rb7
-rw-r--r--lib/gitlab/ci/config/external/context.rb3
-rw-r--r--lib/gitlab/ci/jwt.rb2
-rw-r--r--lib/gitlab/ci/jwt_v2.rb16
-rw-r--r--lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb7
-rw-r--r--lib/gitlab/ci/parsers/security/common.rb45
-rw-r--r--lib/gitlab/ci/parsers/security/concerns/deprecated_syntax.rb36
-rw-r--r--lib/gitlab/ci/parsers/security/sast.rb4
-rw-r--r--lib/gitlab/ci/parsers/security/secret_detection.rb4
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schema_validator.rb16
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/cluster-image-scanning-report-format.json980
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/container-scanning-report-format.json914
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/coverage-fuzzing-report-format.json870
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dast-report-format.json1275
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dependency-scanning-report-format.json978
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/sast-report-format.json865
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/secret-detection-report-format.json888
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/cluster-image-scanning-report-format.json980
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/container-scanning-report-format.json912
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/coverage-fuzzing-report-format.json870
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dast-report-format.json1275
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dependency-scanning-report-format.json978
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/sast-report-format.json865
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/secret-detection-report-format.json888
-rw-r--r--lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb24
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb6
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content.rb26
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb34
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/bridge.rb25
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/external_project.rb51
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/parameter.rb29
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/remote.rb27
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/repository.rb38
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/source.rb49
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/active_jobs.rb63
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/job_activity.rb23
-rw-r--r--lib/gitlab/ci/pipeline/chain/populate.rb11
-rw-r--r--lib/gitlab/ci/pipeline/duration.rb2
-rw-r--r--lib/gitlab/ci/pipeline/logger.rb1
-rw-r--r--lib/gitlab/ci/processable_object_hierarchy.rb4
-rw-r--r--lib/gitlab/ci/reports/sbom/source.rb5
-rw-r--r--lib/gitlab/ci/reports/security/report.rb4
-rw-r--r--lib/gitlab/ci/reports/security/scanner.rb5
-rw-r--r--lib/gitlab/ci/secure_files/cer.rb56
-rw-r--r--lib/gitlab/ci/secure_files/mobile_provision.rb85
-rw-r--r--lib/gitlab/ci/secure_files/p12.rb56
-rw-r--r--lib/gitlab/ci/secure_files/x509_name.rb15
-rw-r--r--lib/gitlab/ci/templates/C++.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Clojure.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Crystal.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Django.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Elixir.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Flutter.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Go.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Gradle.gitlab-ci.yml7
-rw-r--r--lib/gitlab/ci/templates/Grails.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml9
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Julia.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Laravel.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Maven.gitlab-ci.yml45
-rw-r--r--lib/gitlab/ci/templates/Mono.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/PHP.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Python.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Rust.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Scala.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml15
-rw-r--r--lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Security/Coverage-Fuzzing.latest.gitlab-ci.yml64
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml13
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml13
-rw-r--r--lib/gitlab/ci/templates/Swift.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/trace.rb2
-rw-r--r--lib/gitlab/ci/variables/builder.rb20
-rw-r--r--lib/gitlab/ci/variables/builder/release.rb36
-rw-r--r--lib/gitlab/ci/variables/collection.rb17
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb74
-rw-r--r--lib/gitlab/config/entry/legacy_validation_helpers.rb14
-rw-r--r--lib/gitlab/config/entry/validators.rb11
-rw-r--r--lib/gitlab/config_checker/external_database_checker.rb23
-rw-r--r--lib/gitlab/data_builder/pipeline.rb1
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb4
-rw-r--r--lib/gitlab/database/gitlab_schemas.yml6
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb27
-rw-r--r--lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb8
-rw-r--r--lib/gitlab/database/migration_helpers.rb35
-rw-r--r--lib/gitlab/database/migrations/base_background_runner.rb7
-rw-r--r--lib/gitlab/database/migrations/runner.rb77
-rw-r--r--lib/gitlab/database/migrations/test_background_runner.rb2
-rw-r--r--lib/gitlab/database/migrations/test_batched_background_runner.rb102
-rw-r--r--lib/gitlab/database/partitioning/convert_table_to_first_list_partition.rb33
-rw-r--r--lib/gitlab/database/query_analyzers/base.rb16
-rw-r--r--lib/gitlab/database/reflection.rb6
-rw-r--r--lib/gitlab/database/schema_helpers.rb13
-rw-r--r--lib/gitlab/diff/highlight_cache.rb18
-rw-r--r--lib/gitlab/email/handler/create_issue_handler.rb8
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb6
-rw-r--r--lib/gitlab/email/message/in_product_marketing/trial.rb10
-rw-r--r--lib/gitlab/email/message/in_product_marketing/verify.rb8
-rw-r--r--lib/gitlab/encoding_helper.rb2
-rw-r--r--lib/gitlab/environment.rb4
-rw-r--r--lib/gitlab/event_store.rb9
-rw-r--r--lib/gitlab/exclusive_lease.rb2
-rw-r--r--lib/gitlab/experimentation.rb110
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb156
-rw-r--r--lib/gitlab/experimentation/experiment.rb45
-rw-r--r--lib/gitlab/experimentation_logger.rb9
-rw-r--r--lib/gitlab/git/declared_license.rb38
-rw-r--r--lib/gitlab/git/repository.rb29
-rw-r--r--lib/gitlab/git/wiki.rb131
-rw-r--r--lib/gitlab/git/wiki_page.rb21
-rw-r--r--lib/gitlab/git_access.rb5
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb8
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb6
-rw-r--r--lib/gitlab/gitaly_client/wiki_service.rb169
-rw-r--r--lib/gitlab/github_import/client.rb14
-rw-r--r--lib/gitlab/github_import/exceptions.rb11
-rw-r--r--lib/gitlab/github_import/importer/attachments/base_importer.rb55
-rw-r--r--lib/gitlab/github_import/importer/attachments/issues_importer.rb37
-rw-r--r--lib/gitlab/github_import/importer/attachments/merge_requests_importer.rb37
-rw-r--r--lib/gitlab/github_import/importer/attachments/notes_importer.rb35
-rw-r--r--lib/gitlab/github_import/importer/attachments/releases_importer.rb33
-rw-r--r--lib/gitlab/github_import/importer/diff_notes_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/issue_events_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/issues_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/labels_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/milestones_importer.rb16
-rw-r--r--lib/gitlab/github_import/importer/note_attachments_importer.rb57
-rw-r--r--lib/gitlab/github_import/importer/note_importer.rb3
-rw-r--r--lib/gitlab/github_import/importer/notes_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/protected_branch_importer.rb99
-rw-r--r--lib/gitlab/github_import/importer/protected_branches_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/release_attachments_importer.rb58
-rw-r--r--lib/gitlab/github_import/importer/releases_attachments_importer.rb59
-rw-r--r--lib/gitlab/github_import/importer/releases_importer.rb19
-rw-r--r--lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb10
-rw-r--r--lib/gitlab/github_import/issuable_finder.rb6
-rw-r--r--lib/gitlab/github_import/markdown/attachment.rb86
-rw-r--r--lib/gitlab/github_import/markdown_text.rb50
-rw-r--r--lib/gitlab/github_import/parallel_scheduling.rb10
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb32
-rw-r--r--lib/gitlab/github_import/representation/issue.rb26
-rw-r--r--lib/gitlab/github_import/representation/issue_event.rb30
-rw-r--r--lib/gitlab/github_import/representation/note.rb16
-rw-r--r--lib/gitlab/github_import/representation/note_text.rb61
-rw-r--r--lib/gitlab/github_import/representation/protected_branch.rb12
-rw-r--r--lib/gitlab/github_import/representation/pull_request.rb38
-rw-r--r--lib/gitlab/github_import/representation/pull_request_review.rb15
-rw-r--r--lib/gitlab/github_import/representation/release_attachments.rb44
-rw-r--r--lib/gitlab/github_import/representation/user.rb6
-rw-r--r--lib/gitlab/github_import/settings.rb72
-rw-r--r--lib/gitlab/github_import/single_endpoint_notes_importing.rb8
-rw-r--r--lib/gitlab/github_import/user_finder.rb19
-rw-r--r--lib/gitlab/gon_helper.rb4
-rw-r--r--lib/gitlab/graphql/pagination/keyset/connection.rb2
-rw-r--r--lib/gitlab/i18n.rb22
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb6
-rw-r--r--lib/gitlab/import_export/base/relation_factory.rb26
-rw-r--r--lib/gitlab/import_export/json/streaming_serializer.rb31
-rw-r--r--lib/gitlab/import_export/project/import_export.yml6
-rw-r--r--lib/gitlab/import_export/project/import_task.rb2
-rw-r--r--lib/gitlab/import_export/project/relation_factory.rb1
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb5
-rw-r--r--lib/gitlab/jira_import/handle_labels_service.rb2
-rw-r--r--lib/gitlab/jira_import/issues_importer.rb33
-rw-r--r--lib/gitlab/json.rb3
-rw-r--r--lib/gitlab/kroki.rb14
-rw-r--r--lib/gitlab/legacy_github_import/base_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/branch_formatter.rb14
-rw-r--r--lib/gitlab/legacy_github_import/comment_formatter.rb14
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb24
-rw-r--r--lib/gitlab/legacy_github_import/issuable_formatter.rb18
-rw-r--r--lib/gitlab/legacy_github_import/issue_formatter.rb10
-rw-r--r--lib/gitlab/legacy_github_import/label_formatter.rb4
-rw-r--r--lib/gitlab/legacy_github_import/milestone_formatter.rb16
-rw-r--r--lib/gitlab/legacy_github_import/pull_request_formatter.rb14
-rw-r--r--lib/gitlab/legacy_github_import/release_formatter.rb16
-rw-r--r--lib/gitlab/legacy_github_import/user_formatter.rb12
-rw-r--r--lib/gitlab/memory/diagnostic_reports_logger.rb19
-rw-r--r--lib/gitlab/memory/reports_daemon.rb2
-rw-r--r--lib/gitlab/memory/reports_uploader.rb52
-rw-r--r--lib/gitlab/memory/upload_and_cleanup_reports.rb72
-rw-r--r--lib/gitlab/memory/watchdog.rb181
-rw-r--r--lib/gitlab/memory/watchdog/configuration.rb64
-rw-r--r--lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb51
-rw-r--r--lib/gitlab/memory/watchdog/monitor/unique_memory_growth.rb47
-rw-r--r--lib/gitlab/memory/watchdog/monitor_state.rb85
-rw-r--r--lib/gitlab/metrics/global_search_slis.rb6
-rw-r--r--lib/gitlab/metrics/system.rb6
-rw-r--r--lib/gitlab/object_hierarchy.rb6
-rw-r--r--lib/gitlab/pages/cache_control.rb33
-rw-r--r--lib/gitlab/pagination/keyset/simple_order_builder.rb35
-rw-r--r--lib/gitlab/patch/sidekiq_cron_poller.rb21
-rw-r--r--lib/gitlab/profiler.rb31
-rw-r--r--lib/gitlab/project_authorizations.rb12
-rw-r--r--lib/gitlab/query_limiting/transaction.rb19
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb4
-rw-r--r--lib/gitlab/redis/duplicate_jobs.rb2
-rw-r--r--lib/gitlab/redis/sidekiq_status.rb2
-rw-r--r--lib/gitlab/regex.rb4
-rw-r--r--lib/gitlab/repository_set_cache.rb4
-rw-r--r--lib/gitlab/request_endpoints.rb1
-rw-r--r--lib/gitlab/runtime.rb4
-rw-r--r--lib/gitlab/search/query.rb23
-rw-r--r--lib/gitlab/set_cache.rb4
-rw-r--r--lib/gitlab/sidekiq_config.rb27
-rw-r--r--lib/gitlab/sidekiq_daemon/memory_killer.rb23
-rw-r--r--lib/gitlab/sidekiq_daemon/monitor.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/memory_killer.rb91
-rw-r--r--lib/gitlab/sidekiq_status.rb2
-rw-r--r--lib/gitlab/slash_commands/issue_new.rb12
-rw-r--r--lib/gitlab/tracking/service_ping_context.rb25
-rw-r--r--lib/gitlab/usage/metric.rb5
-rw-r--r--lib/gitlab/usage/metric_definition.rb2
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb93
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb71
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/base_metric.rb6
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb20
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/generic_metric.rb5
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb43
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_metric.rb16
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb13
-rw-r--r--lib/gitlab/usage_data.rb25
-rw-r--r--lib/gitlab/usage_data_counters.rb35
-rw-r--r--lib/gitlab/usage_data_counters/ci_template_unique_counter.rb15
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb10
-rw-r--r--lib/gitlab/usage_data_counters/known_events/analytics.yml56
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml134
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml58
-rw-r--r--lib/gitlab/usage_data_counters/known_events/epic_events.yml227
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml70
-rw-r--r--lib/gitlab/usage_data_counters/known_events/work_items.yml13
-rw-r--r--lib/gitlab/usage_data_counters/work_item_activity_unique_counter.rb5
-rw-r--r--lib/gitlab/usage_data_queries.rb4
-rw-r--r--lib/gitlab/utils/execution_tracker.rb2
-rw-r--r--lib/gitlab/utils/usage_data.rb8
-rw-r--r--lib/gitlab/web_hooks.rb1
-rw-r--r--lib/gitlab/x509/signature.rb2
-rw-r--r--lib/prometheus/pid_provider.rb2
-rw-r--r--lib/quality/seeders/issues.rb4
-rw-r--r--lib/sidebars/groups/menus/packages_registries_menu.rb8
-rw-r--r--lib/sidebars/projects/menus/infrastructure_menu.rb12
-rw-r--r--lib/sidebars/projects/menus/packages_registries_menu.rb8
-rw-r--r--lib/sidebars/projects/menus/repository_menu.rb2
-rw-r--r--lib/system_check/app/authorized_keys_permission_check.rb11
-rw-r--r--lib/tasks/gitlab/assets.rake103
-rw-r--r--lib/tasks/gitlab/backup.rake128
-rw-r--r--lib/tasks/gitlab/db.rake44
-rw-r--r--lib/tasks/gitlab/db/lock_writes.rake3
-rw-r--r--lib/tasks/gitlab/openapi.rake23
-rw-r--r--lib/tasks/gitlab/seed.rake35
-rw-r--r--lib/tasks/gitlab/snippets.rake2
-rw-r--r--lib/tasks/gitlab/tw/codeowners.rake19
-rw-r--r--lib/tasks/gitlab/usage_data.rake45
-rw-r--r--lib/version_check.rb30
-rw-r--r--locale/am_ET/gitlab.po1259
-rw-r--r--locale/ar_SA/gitlab.po1287
-rw-r--r--locale/as_IN/gitlab.po1259
-rw-r--r--locale/az_AZ/gitlab.po1259
-rw-r--r--locale/ba_RU/gitlab.po1252
-rw-r--r--locale/bg/gitlab.po1259
-rw-r--r--locale/bn_BD/gitlab.po1259
-rw-r--r--locale/bn_IN/gitlab.po1259
-rw-r--r--locale/br_FR/gitlab.po1280
-rw-r--r--locale/bs_BA/gitlab.po1266
-rw-r--r--locale/ca_ES/gitlab.po1259
-rw-r--r--locale/cs_CZ/gitlab.po1273
-rw-r--r--locale/cy_GB/gitlab.po1287
-rw-r--r--locale/da_DK/gitlab.po1285
-rw-r--r--locale/de/gitlab.po1359
-rw-r--r--locale/el_GR/gitlab.po1259
-rw-r--r--locale/en_GB/gitlab.po1269
-rw-r--r--locale/eo/gitlab.po1259
-rw-r--r--locale/es/gitlab.po1295
-rw-r--r--locale/et_EE/gitlab.po1259
-rw-r--r--locale/fa_IR/gitlab.po1259
-rw-r--r--locale/fi_FI/gitlab.po1259
-rw-r--r--locale/fil_PH/gitlab.po1259
-rw-r--r--locale/fr/gitlab.po18489
-rw-r--r--locale/gitlab.pot1256
-rw-r--r--locale/gl_ES/gitlab.po1259
-rw-r--r--locale/he_IL/gitlab.po1273
-rw-r--r--locale/hi_IN/gitlab.po1259
-rw-r--r--locale/hr_HR/gitlab.po1266
-rw-r--r--locale/hu_HU/gitlab.po1259
-rw-r--r--locale/hy_AM/gitlab.po1259
-rw-r--r--locale/id_ID/gitlab.po1252
-rw-r--r--locale/ig_NG/gitlab.po1252
-rw-r--r--locale/is_IS/gitlab.po1259
-rw-r--r--locale/it/gitlab.po1259
-rw-r--r--locale/ja/gitlab.po1270
-rw-r--r--locale/ka_GE/gitlab.po1259
-rw-r--r--locale/kab/gitlab.po1259
-rw-r--r--locale/ko/gitlab.po1928
-rw-r--r--locale/ku_TR/gitlab.po1259
-rw-r--r--locale/ky_KG/gitlab.po1259
-rw-r--r--locale/lt_LT/gitlab.po1273
-rw-r--r--locale/mk_MK/gitlab.po1259
-rw-r--r--locale/ml_IN/gitlab.po1259
-rw-r--r--locale/mn_MN/gitlab.po1259
-rw-r--r--locale/nb_NO/gitlab.po1283
-rw-r--r--locale/nl_NL/gitlab.po1259
-rw-r--r--locale/or_IN/gitlab.po1259
-rw-r--r--locale/pa_IN/gitlab.po1259
-rw-r--r--locale/pa_PK/gitlab.po48837
-rw-r--r--locale/pl_PL/gitlab.po1273
-rw-r--r--locale/pt_BR/gitlab.po1821
-rw-r--r--locale/pt_PT/gitlab.po1259
-rw-r--r--locale/ro_RO/gitlab.po1546
-rw-r--r--locale/ru/gitlab.po1281
-rw-r--r--locale/si_LK/gitlab.po1805
-rw-r--r--locale/sk_SK/gitlab.po1273
-rw-r--r--locale/sl_SI/gitlab.po1273
-rw-r--r--locale/sq_AL/gitlab.po1259
-rw-r--r--locale/sr_CS/gitlab.po1266
-rw-r--r--locale/sr_SP/gitlab.po1266
-rw-r--r--locale/sv_SE/gitlab.po1259
-rw-r--r--locale/sw_KE/gitlab.po1259
-rw-r--r--locale/ta_IN/gitlab.po1259
-rw-r--r--locale/th_TH/gitlab.po1252
-rw-r--r--locale/tr_TR/gitlab.po1265
-rw-r--r--locale/uk/gitlab.po1523
-rw-r--r--locale/ur_PK/gitlab.po1259
-rw-r--r--locale/uz_UZ/gitlab.po1259
-rw-r--r--locale/vi_VN/gitlab.po1252
-rw-r--r--locale/zh_CN/gitlab.po1792
-rw-r--r--locale/zh_HK/gitlab.po1252
-rw-r--r--locale/zh_TW/gitlab.po1766
-rw-r--r--package.json28
-rw-r--r--qa/Gemfile46
-rw-r--r--qa/Gemfile.lock250
-rw-r--r--qa/Rakefile4
-rw-r--r--qa/chemlab-library-gitlab.gemspec2
-rw-r--r--qa/lib/gitlab/page/admin/subscription.rb2
-rw-r--r--qa/lib/gitlab/page/group/settings/usage_quota.stub.rb404
-rw-r--r--qa/lib/gitlab/page/group/settings/usage_quotas.rb33
-rw-r--r--qa/qa.rb17
-rw-r--r--qa/qa/fixtures/package_managers/maven/client_pom.xml.erb19
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb (renamed from qa/qa/fixtures/package_managers/maven/build_install.gradle.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb (renamed from qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb (renamed from qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb (renamed from qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/consumer/gitlab_ci.yaml.erb (renamed from qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/consumer/pom.xml.erb19
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/consumer/settings.xml.erb16
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/producer/gitlab_ci.yaml.erb (renamed from qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/producer/pom.xml.erb (renamed from qa/qa/fixtures/package_managers/maven/package_pom.xml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/producer/settings.xml.erb (renamed from qa/qa/fixtures/package_managers/maven/settings.xml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/settings_with_pat.xml.erb (renamed from qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb)0
-rw-r--r--qa/qa/fixtures/package_managers/maven/project/gitlab_ci.yaml.erb9
-rw-r--r--qa/qa/fixtures/package_managers/maven/project/pom.xml.erb22
-rw-r--r--qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb23
-rw-r--r--qa/qa/fixtures/package_managers/maven/project/settings.xml.erb16
-rw-r--r--qa/qa/fixtures/software_licenses/other7
-rw-r--r--qa/qa/flow/purchase.rb7
-rw-r--r--qa/qa/mobile/page/main/menu.rb4
-rw-r--r--qa/qa/page/admin/menu.rb69
-rw-r--r--qa/qa/page/base.rb5
-rw-r--r--qa/qa/page/component/clone_panel.rb12
-rw-r--r--qa/qa/page/component/content_editor.rb6
-rw-r--r--qa/qa/page/component/groups_filter.rb2
-rw-r--r--qa/qa/page/component/invite_members_modal.rb10
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb9
-rw-r--r--qa/qa/page/component/legacy_clone_panel.rb8
-rw-r--r--qa/qa/page/component/namespace_select.rb6
-rw-r--r--qa/qa/page/component/wiki_page_form.rb7
-rw-r--r--qa/qa/page/group/show.rb4
-rw-r--r--qa/qa/page/main/menu.rb8
-rw-r--r--qa/qa/page/main/terms.rb2
-rw-r--r--qa/qa/page/merge_request/new.rb1
-rw-r--r--qa/qa/page/merge_request/show.rb5
-rw-r--r--qa/qa/page/project/secure/configuration_form.rb26
-rw-r--r--qa/qa/page/project/settings/default_branch.rb14
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb2
-rw-r--r--qa/qa/page/project/settings/services/jira.rb14
-rw-r--r--qa/qa/page/project/tag/new.rb12
-rw-r--r--qa/qa/resource/issuable.rb79
-rw-r--r--qa/qa/resource/issue.rb27
-rw-r--r--qa/qa/resource/merge_request.rb26
-rw-r--r--qa/qa/resource/project.rb20
-rw-r--r--qa/qa/resource/project_imported_from_github.rb9
-rw-r--r--qa/qa/resource/protected_branch.rb4
-rw-r--r--qa/qa/resource/user.rb2
-rw-r--r--qa/qa/resource/wiki/group_page.rb1
-rw-r--r--qa/qa/runtime/env.rb9
-rw-r--r--qa/qa/scenario/test/instance.rb36
-rw-r--r--qa/qa/scenario/test/integration/github.rb20
-rw-r--r--qa/qa/specs/features/api/1_manage/group_access_token_spec.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb166
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb620
-rw-r--r--qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb148
-rw-r--r--qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb495
-rw-r--r--qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb130
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb8
-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.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb10
-rw-r--r--qa/qa/specs/features/api/1_manage/users_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb129
-rw-r--r--qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb147
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb105
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb72
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb134
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb20
-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_badge_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_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/parent_group_access_termination_spec.rb64
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb63
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb72
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb145
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb102
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb95
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb51
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb34
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb44
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb75
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb45
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/license_detecton_spec.rb45
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb43
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb93
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb51
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb33
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb73
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb26
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_status_emails_spec.rb134
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb200
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb214
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb36
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb20
-rw-r--r--qa/qa/specs/features/sanity/framework_spec.rb2
-rw-r--r--qa/qa/specs/qa_deprecation_toolkit_env.rb30
-rw-r--r--qa/qa/specs/spec_helper.rb3
-rw-r--r--qa/qa/support/api.rb25
-rw-r--r--qa/qa/support/formatters/test_stats_formatter.rb1
-rw-r--r--qa/qa/support/repeater.rb3
-rw-r--r--qa/qa/tools/ci/non_empty_suites.rb81
-rw-r--r--qa/qa/tools/ci/qa_changes.rb51
-rw-r--r--qa/qa/tools/delete_test_ssh_keys.rb2
-rw-r--r--qa/qa/tools/initialize_gitlab_auth.rb2
-rw-r--r--qa/qa/tools/test_resources_handler.rb105
-rw-r--r--qa/qa/vendor/jira/jira_issue_page.rb47
-rw-r--r--qa/spec/resource/user_spec.rb4
-rw-r--r--qa/spec/runtime/env_spec.rb31
-rw-r--r--qa/spec/scenario/test/integration/github_spec.rb21
-rw-r--r--qa/spec/support/formatters/test_stats_formatter_spec.rb5
-rw-r--r--qa/spec/tools/ci/non_empty_suites_spec.rb4
-rw-r--r--qa/spec/tools/ci/qa_changes_spec.rb52
-rw-r--r--qa/spec/tools/reliable_report_spec.rb3
-rw-r--r--qa/tasks/ci.rake4
-rw-r--r--rubocop/check_graceful_task.rb8
-rw-r--r--rubocop/cop/gitlab/duplicate_spec_location.rb13
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb28
-rw-r--r--rubocop/cop/gitlab/no_code_coverage_comment.rb67
-rw-r--r--rubocop/cop/gitlab/service_response.rb43
-rw-r--r--rubocop/cop/migration/background_migration_missing_active_concern.rb58
-rw-r--r--rubocop/cop/redis_queue_usage.rb38
-rw-r--r--rubocop/cop/rspec/any_instance_of.rb2
-rw-r--r--rubocop/cop/rspec/be_success_matcher.rb2
-rw-r--r--rubocop/cop/rspec/env_assignment.rb2
-rw-r--r--rubocop/cop/rspec/expect_gitlab_tracking.rb2
-rw-r--r--rubocop/cop/rspec/factories_in_migration_specs.rb2
-rw-r--r--rubocop/cop/rspec/factory_bot/avoid_create.rb46
-rw-r--r--rubocop/cop/rspec/factory_bot/inline_association.rb2
-rw-r--r--rubocop/cop/rspec/have_gitlab_http_status.rb1
-rw-r--r--rubocop/cop/rspec/httparty_basic_auth.rb2
-rw-r--r--rubocop/cop/rspec/modify_sidekiq_middleware.rb2
-rw-r--r--rubocop/cop/rspec/timecop_freeze.rb2
-rw-r--r--rubocop/cop/rspec/timecop_travel.rb2
-rw-r--r--rubocop/cop/rspec/top_level_describe_path.rb19
-rw-r--r--rubocop/cop/rspec/web_mock_enable.rb2
-rw-r--r--rubocop/cop/sidekiq_api_usage.rb31
-rw-r--r--rubocop/cop/sidekiq_redis_call.rb18
-rw-r--r--rubocop/cop/static_translation_definition.rb2
-rw-r--r--rubocop/cop_todo.rb14
-rw-r--r--rubocop/ext/path_util.rb26
-rw-r--r--rubocop/ext/variable_force.rb17
-rw-r--r--rubocop/formatter/todo_formatter.rb26
-rw-r--r--rubocop/migration_helpers.rb6
-rw-r--r--rubocop/rubocop-ruby30.yml16
-rw-r--r--rubocop/rubocop-usage-data.yml1
-rw-r--r--rubocop/rubocop.rb5
-rwxr-xr-xscripts/api/cancel_pipeline.rb2
-rwxr-xr-xscripts/api/download_job_artifact.rb2
-rwxr-xr-xscripts/api/get_job_id.rb2
-rw-r--r--scripts/api/pipeline_failed_jobs.rb47
-rwxr-xr-xscripts/build_qa_image32
-rwxr-xr-xscripts/changed-feature-flags2
-rwxr-xr-xscripts/clean-old-cached-assets8
-rwxr-xr-xscripts/failed_tests.rb2
-rwxr-xr-xscripts/generate-e2e-pipeline3
-rwxr-xr-xscripts/generate-failed-pipeline-slack-message.rb112
-rwxr-xr-xscripts/generate-rspec-foss-impact-pipeline66
-rw-r--r--scripts/gitlab_component_helpers.sh151
-rw-r--r--scripts/gitlab_workhorse_component_helpers.sh74
-rwxr-xr-xscripts/glfm/verify-all-generated-files-are-up-to-date.rb5
-rw-r--r--scripts/lib/glfm/constants.rb24
-rw-r--r--scripts/lib/glfm/render_static_html.rb16
-rw-r--r--scripts/lib/glfm/update_example_snapshots.rb57
-rw-r--r--scripts/lib/glfm/update_specification.rb140
-rw-r--r--scripts/lib/glfm/verify_all_generated_files_are_up_to_date.rb48
-rwxr-xr-xscripts/lint-json.sh8
-rw-r--r--scripts/migration_schema_validator.rb117
-rwxr-xr-xscripts/packages/automated_cleanup.rb126
-rwxr-xr-xscripts/perf/query_limiting_report.rb2
-rwxr-xr-xscripts/pipeline_test_report_builder.rb2
-rwxr-xr-xscripts/post_deployment_migrations_validator31
-rwxr-xr-xscripts/review_apps/automated_cleanup.rb418
-rwxr-xr-xscripts/review_apps/review-apps.sh27
-rw-r--r--scripts/rspec_helpers.sh54
-rwxr-xr-xscripts/rubocop-max-files-in-cache-check5
-rwxr-xr-xscripts/rubocop-parse77
-rwxr-xr-xscripts/setup/find-jh-branch.rb2
-rwxr-xr-xscripts/slack2
-rwxr-xr-xscripts/static-analysis2
-rwxr-xr-xscripts/trigger-build.rb2
-rw-r--r--scripts/utils.sh22
-rwxr-xr-xscripts/validate_migration_schema116
-rw-r--r--spec/bin/diagnostic_reports_uploader_spec.rb86
-rw-r--r--spec/commands/diagnostic_reports/uploader_smoke_spec.rb83
-rw-r--r--spec/components/pajamas/alert_component_spec.rb49
-rw-r--r--spec/components/pajamas/progress_component_spec.rb36
-rw-r--r--spec/components/previews/pajamas/alert_component_preview.rb5
-rw-r--r--spec/components/previews/pajamas/progress_component_preview.rb16
-rw-r--r--spec/config/object_store_settings_spec.rb21
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb7
-rw-r--r--spec/controllers/admin/cohorts_controller_spec.rb2
-rw-r--r--spec/controllers/admin/dev_ops_report_controller_spec.rb2
-rw-r--r--spec/controllers/admin/groups_controller_spec.rb60
-rw-r--r--spec/controllers/admin/usage_trends_controller_spec.rb2
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb2
-rw-r--r--spec/controllers/boards/issues_controller_spec.rb596
-rw-r--r--spec/controllers/boards/lists_controller_spec.rb333
-rw-r--r--spec/controllers/concerns/boards_responses_spec.rb23
-rw-r--r--spec/controllers/concerns/product_analytics_tracking_spec.rb44
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb7
-rw-r--r--spec/controllers/dashboard_controller_spec.rb31
-rw-r--r--spec/controllers/groups/boards_controller_spec.rb84
-rw-r--r--spec/controllers/groups/runners_controller_spec.rb71
-rw-r--r--spec/controllers/groups_controller_spec.rb22
-rw-r--r--spec/controllers/health_check_controller_spec.rb13
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb23
-rw-r--r--spec/controllers/import/github_controller_spec.rb103
-rw-r--r--spec/controllers/profiles/personal_access_tokens_controller_spec.rb20
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb3
-rw-r--r--spec/controllers/profiles/two_factor_auths_controller_spec.rb28
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/autocomplete_sources_controller_spec.rb136
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb150
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb94
-rw-r--r--spec/controllers/projects/cycle_analytics_controller_spec.rb2
-rw-r--r--spec/controllers/projects/deploy_keys_controller_spec.rb31
-rw-r--r--spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb2
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb56
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb23
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb20
-rw-r--r--spec/controllers/projects/pages_domains_controller_spec.rb56
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb2
-rw-r--r--spec/controllers/projects/prometheus/metrics_controller_spec.rb2
-rw-r--r--spec/controllers/projects/protected_branches_controller_spec.rb46
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb25
-rw-r--r--spec/controllers/projects_controller_spec.rb30
-rw-r--r--spec/controllers/registrations/welcome_controller_spec.rb5
-rw-r--r--spec/controllers/search_controller_spec.rb2
-rw-r--r--spec/controllers/sessions_controller_spec.rb18
-rw-r--r--spec/controllers/uploads_controller_spec.rb2
-rw-r--r--spec/factories/bulk_import/entities.rb1
-rw-r--r--spec/factories/ci/build_metadata.rb4
-rw-r--r--spec/factories/ci/builds.rb26
-rw-r--r--spec/factories/ci/job_artifacts.rb22
-rw-r--r--spec/factories/ci/pipeline_artifacts.rb5
-rw-r--r--spec/factories/ci/pipeline_metadata.rb10
-rw-r--r--spec/factories/ci/pipelines.rb8
-rw-r--r--spec/factories/ci/reports/sbom/components.rb2
-rw-r--r--spec/factories/ci/reports/sbom/reports.rb18
-rw-r--r--spec/factories/ci/reports/sbom/sources.rb5
-rw-r--r--spec/factories/customer_relations/contacts.rb4
-rw-r--r--spec/factories/events.rb14
-rw-r--r--spec/factories/git_wiki_commit_details.rb15
-rw-r--r--spec/factories/go_module_commits.rb4
-rw-r--r--spec/factories/incident_management/timeline_event_tag_links.rb8
-rw-r--r--spec/factories/incident_management/timeline_event_tags.rb8
-rw-r--r--spec/factories/ml/candidate_metrics.rb12
-rw-r--r--spec/factories/ml/candidate_params.rb10
-rw-r--r--spec/factories/ml/candidates.rb7
-rw-r--r--spec/factories/ml/experiments.rb5
-rw-r--r--spec/factories/notes.rb2
-rw-r--r--spec/factories/packages/packages.rb2
-rw-r--r--spec/factories/packages/rpm/rpm_repository_files.rb33
-rw-r--r--spec/factories/projects.rb67
-rw-r--r--spec/factories/users/namespace_user_callouts.rb10
-rw-r--r--spec/factories/users/phone_number_validations.rb10
-rw-r--r--spec/fast_spec_helper.rb2
-rw-r--r--spec/features/admin/admin_broadcast_messages_spec.rb1
-rw-r--r--spec/features/admin/admin_groups_spec.rb25
-rw-r--r--spec/features/admin/admin_runners_spec.rb64
-rw-r--r--spec/features/admin/admin_settings_spec.rb44
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb14
-rw-r--r--spec/features/admin/users/users_spec.rb8
-rw-r--r--spec/features/boards/boards_spec.rb1
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb4
-rw-r--r--spec/features/dashboard/issues_filter_spec.rb2
-rw-r--r--spec/features/dashboard/projects_spec.rb3
-rw-r--r--spec/features/dashboard/user_filters_projects_spec.rb7
-rw-r--r--spec/features/discussion_comments/issue_spec.rb1
-rw-r--r--spec/features/discussion_comments/merge_request_spec.rb1
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb5
-rw-r--r--spec/features/global_search_spec.rb1
-rw-r--r--spec/features/groups/empty_states_spec.rb4
-rw-r--r--spec/features/groups/group_runners_spec.rb46
-rw-r--r--spec/features/groups/labels/sort_labels_spec.rb4
-rw-r--r--spec/features/groups/merge_requests_spec.rb10
-rw-r--r--spec/features/groups/milestones_sorting_spec.rb4
-rw-r--r--spec/features/groups/new_group_page_spec.rb32
-rw-r--r--spec/features/groups/settings/repository_spec.rb34
-rw-r--r--spec/features/help_dropdown_spec.rb4
-rw-r--r--spec/features/ide/user_commits_changes_spec.rb35
-rw-r--r--spec/features/incidents/incident_timeline_events_spec.rb1
-rw-r--r--spec/features/issuables/markdown_references/jira_spec.rb6
-rw-r--r--spec/features/issues/incident_issue_spec.rb28
-rw-r--r--spec/features/issues/related_issues_spec.rb116
-rw-r--r--spec/features/issues/resource_label_events_spec.rb9
-rw-r--r--spec/features/issues/service_desk_spec.rb1
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb2
-rw-r--r--spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb1
-rw-r--r--spec/features/markdown/gitlab_flavored_markdown_spec.rb9
-rw-r--r--spec/features/markdown/metrics_spec.rb2
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb18
-rw-r--r--spec/features/merge_request/close_reopen_report_toggle_spec.rb10
-rw-r--r--spec/features/merge_request/merge_request_discussion_lock_spec.rb4
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb1
-rw-r--r--spec/features/merge_request/user_comments_on_merge_request_spec.rb1
-rw-r--r--spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb4
-rw-r--r--spec/features/merge_request/user_jumps_to_discussion_spec.rb29
-rw-r--r--spec/features/merge_request/user_manages_subscription_spec.rb6
-rw-r--r--spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb4
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb15
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb32
-rw-r--r--spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb34
-rw-r--r--spec/features/milestone_spec.rb12
-rw-r--r--spec/features/milestones/user_creates_milestone_spec.rb99
-rw-r--r--spec/features/oauth_registration_spec.rb175
-rw-r--r--spec/features/profiles/password_spec.rb23
-rw-r--r--spec/features/profiles/two_factor_auths_spec.rb8
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb50
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb2
-rw-r--r--spec/features/projects/blobs/edit_spec.rb39
-rw-r--r--spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb63
-rw-r--r--spec/features/projects/branches_spec.rb8
-rw-r--r--spec/features/projects/ci/editor_spec.rb13
-rw-r--r--spec/features/projects/ci/lint_spec.rb9
-rw-r--r--spec/features/projects/environments/environment_metrics_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb4
-rw-r--r--spec/features/projects/fork_spec.rb53
-rw-r--r--spec/features/projects/infrastructure_registry_spec.rb2
-rw-r--r--spec/features/projects/labels/sort_labels_spec.rb4
-rw-r--r--spec/features/projects/milestones/milestones_sorting_spec.rb4
-rw-r--r--spec/features/projects/packages_spec.rb2
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb4
-rw-r--r--spec/features/projects/pipelines/legacy_pipeline_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb4
-rw-r--r--spec/features/projects/releases/user_creates_release_spec.rb3
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/user_changes_default_branch_spec.rb13
-rw-r--r--spec/features/projects/settings/user_transfers_a_project_spec.rb2
-rw-r--r--spec/features/projects/settings/webhooks_settings_spec.rb8
-rw-r--r--spec/features/projects/show/user_interacts_with_stars_spec.rb12
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb6
-rw-r--r--spec/features/projects/user_sorts_projects_spec.rb20
-rw-r--r--spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb33
-rw-r--r--spec/features/protected_branches_spec.rb2
-rw-r--r--spec/features/runners_spec.rb10
-rw-r--r--spec/features/search/user_searches_for_code_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_comments_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb10
-rw-r--r--spec/features/search/user_searches_for_issues_spec.rb3
-rw-r--r--spec/features/search/user_searches_for_merge_requests_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_milestones_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_projects_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_users_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb5
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb1
-rw-r--r--spec/features/snippets/search_snippets_spec.rb4
-rw-r--r--spec/features/tags/developer_creates_tag_spec.rb25
-rw-r--r--spec/features/unsubscribe_links_spec.rb13
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_profile_spec.rb2
-rw-r--r--spec/features/user_opens_link_to_comment_spec.rb2
-rw-r--r--spec/features/users/signup_spec.rb1
-rw-r--r--spec/features/work_items/work_item_spec.rb33
-rw-r--r--spec/finders/ci/runners_finder_spec.rb37
-rw-r--r--spec/finders/clusters/agent_authorizations_finder_spec.rb32
-rw-r--r--spec/finders/groups/accepting_group_transfers_finder_spec.rb13
-rw-r--r--spec/finders/merge_requests_finder_spec.rb53
-rw-r--r--spec/finders/packages/nuget/package_finder_spec.rb10
-rw-r--r--spec/finders/personal_access_tokens_finder_spec.rb44
-rw-r--r--spec/fixtures/api/schemas/board.json10
-rw-r--r--spec/fixtures/api/schemas/boards.json4
-rw-r--r--spec/fixtures/api/schemas/current-board.json16
-rw-r--r--spec/fixtures/api/schemas/ml/get_experiment.json27
-rw-r--r--spec/fixtures/api/schemas/ml/list_experiments.json39
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/user/admin.json2
-rw-r--r--spec/fixtures/ci_secure_files/sample.cerbin0 -> 1479 bytes
-rw-r--r--spec/fixtures/ci_secure_files/sample.mobileprovisionbin0 -> 12278 bytes
-rw-r--r--spec/fixtures/ci_secure_files/sample.p12bin0 -> 3352 bytes
-rw-r--r--spec/fixtures/git-cheat-sheet.pdf3
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json6
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/tree/project/ci_pipelines.ndjson2
-rw-r--r--spec/fixtures/markdown/markdown_golden_master_examples.yml16
-rw-r--r--spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.src.rpmbin0 -> 6435 bytes
-rw-r--r--spec/fixtures/packages/rpm/payload.json47
-rw-r--r--spec/fixtures/packages/rpm/repodata/repomd.xml27
-rw-r--r--spec/fixtures/packages/rubygems/package.gemspec2
-rw-r--r--spec/fixtures/sample.pdf13
-rw-r--r--spec/fixtures/security_reports/deprecated/gl-sast-report.json964
-rw-r--r--spec/fixtures/security_reports/feature-branch/gl-sast-report.json4
-rw-r--r--spec/fixtures/security_reports/master/gl-common-scanning-report-names.json59
-rw-r--r--spec/fixtures/security_reports/master/gl-common-scanning-report.json170
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report-minimal.json4
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json7
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-multiple-findings.json134
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report.json4
-rw-r--r--spec/fixtures/security_reports/master/gl-secret-detection-report.json3
-rw-r--r--spec/frontend/__helpers__/class_spec_helper.js10
-rw-r--r--spec/frontend/__helpers__/class_spec_helper_spec.js26
-rw-r--r--spec/frontend/__helpers__/dom_shims/index.js1
-rw-r--r--spec/frontend/__helpers__/dom_shims/text_encoder.js4
-rw-r--r--spec/frontend/__helpers__/graphql_transformer.js8
-rw-r--r--spec/frontend/__helpers__/shared_test_setup.js15
-rw-r--r--spec/frontend/__helpers__/stub_component.js2
-rw-r--r--spec/frontend/__helpers__/vue_mount_component_helper.js34
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js3
-rw-r--r--spec/frontend/__mocks__/monaco-editor/index.js2
-rw-r--r--spec/frontend/__mocks__/monaco-yaml/index.js4
-rw-r--r--spec/frontend/access_tokens/components/access_token_table_app_spec.js147
-rw-r--r--spec/frontend/access_tokens/components/new_access_token_app_spec.js19
-rw-r--r--spec/frontend/access_tokens/index_spec.js73
-rw-r--r--spec/frontend/admin/broadcast_messages/components/base_spec.js112
-rw-r--r--spec/frontend/admin/broadcast_messages/components/messages_table_spec.js51
-rw-r--r--spec/frontend/admin/broadcast_messages/mock_data.js17
-rw-r--r--spec/frontend/admin/deploy_keys/components/table_spec.js4
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js4
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js13
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_form_spec.js59
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js26
-rw-r--r--spec/frontend/api/projects_api_spec.js23
-rw-r--r--spec/frontend/awards_handler_spec.js4
-rw-r--r--spec/frontend/badges/components/badge_form_spec.js194
-rw-r--r--spec/frontend/badges/components/badge_list_row_spec.js137
-rw-r--r--spec/frontend/badges/components/badge_list_spec.js125
-rw-r--r--spec/frontend/badges/components/badge_spec.js150
-rw-r--r--spec/frontend/batch_comments/components/drafts_count_spec.js30
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js36
-rw-r--r--spec/frontend/batch_comments/components/publish_button_spec.js30
-rw-r--r--spec/frontend/behaviors/bind_in_out_spec.js9
-rw-r--r--spec/frontend/blame/blame_redirect_spec.js70
-rw-r--r--spec/frontend/blob/3d_viewer/mesh_object_spec.js2
-rw-r--r--spec/frontend/blob/blob_blame_link_spec.js6
-rw-r--r--spec/frontend/blob/components/blob_content_spec.js4
-rw-r--r--spec/frontend/blob/components/table_contents_spec.js5
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js13
-rw-r--r--spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap30
-rw-r--r--spec/frontend/boards/components/board_blocked_icon_spec.js264
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js8
-rw-r--r--spec/frontend/boards/stores/actions_spec.js254
-rw-r--r--spec/frontend/captcha/init_recaptcha_script_spec.js3
-rw-r--r--spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js16
-rw-r--r--spec/frontend/ci_variable_list/components/ci_group_variables_spec.js16
-rw-r--r--spec/frontend/ci_variable_list/components/ci_project_variables_spec.js20
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js14
-rw-r--r--spec/frontend/ci_variable_list/mocks.js6
-rw-r--r--spec/frontend/ci_variable_list/store/actions_spec.js12
-rw-r--r--spec/frontend/clusters_list/store/actions_spec.js4
-rw-r--r--spec/frontend/code_navigation/utils/index_spec.js8
-rw-r--r--spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js6
-rw-r--r--spec/frontend/commit/commit_pipeline_status_component_spec.js4
-rw-r--r--spec/frontend/commit/components/commit_box_pipeline_status_spec.js8
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js31
-rw-r--r--spec/frontend/content_editor/components/editor_state_observer_spec.js11
-rw-r--r--spec/frontend/content_editor/components/suggestions_dropdown_spec.js286
-rw-r--r--spec/frontend/content_editor/components/wrappers/label_spec.js36
-rw-r--r--spec/frontend/content_editor/extensions/heading_spec.js54
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec_helper.js12
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js18
-rw-r--r--spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js2
-rw-r--r--spec/frontend/contributors/component/contributors_spec.js5
-rw-r--r--spec/frontend/contributors/store/actions_spec.js4
-rw-r--r--spec/frontend/crm/contacts_root_spec.js14
-rw-r--r--spec/frontend/crm/organizations_root_spec.js2
-rw-r--r--spec/frontend/cycle_analytics/value_stream_metrics_spec.js4
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js11
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js3
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js102
-rw-r--r--spec/frontend/deploy_freeze/helpers.js9
-rw-r--r--spec/frontend/deploy_freeze/store/actions_spec.js3
-rw-r--r--spec/frontend/deploy_freeze/store/mutations_spec.js13
-rw-r--r--spec/frontend/deploy_tokens/components/new_deploy_token_spec.js103
-rw-r--r--spec/frontend/design_management/components/delete_button_spec.js6
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js69
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js8
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js10
-rw-r--r--spec/frontend/design_management/pages/index_spec.js4
-rw-r--r--spec/frontend/design_management/utils/cache_update_spec.js8
-rw-r--r--spec/frontend/diffs/components/app_spec.js24
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_row_utils_spec.js6
-rw-r--r--spec/frontend/diffs/components/diff_view_spec.js16
-rw-r--r--spec/frontend/diffs/components/file_row_stats_spec.js20
-rw-r--r--spec/frontend/diffs/mock_data/diff_code_quality.js6
-rw-r--r--spec/frontend/diffs/store/actions_spec.js37
-rw-r--r--spec/frontend/editor/schema/ci/ci_schema_spec.js47
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/empty.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/invalid_variable.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/leading_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/no_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/tailing_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/empty.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/invalid_variable.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/leading_slash.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/no_slash.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/tailing_slash.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/empty.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/invalid_variable.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/leading_slash.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/no_slash.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/tailing_slash.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/empty.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/invalid_variable.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/leading_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/no_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/tailing_slash.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml5
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/project_path.yml101
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml2
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml8
-rw-r--r--spec/frontend/editor/source_editor_ci_schema_ext_spec.js12
-rw-r--r--spec/frontend/editor/source_editor_instance_spec.js2
-rw-r--r--spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js4
-rw-r--r--spec/frontend/environments/delete_environment_modal_spec.js6
-rw-r--r--spec/frontend/environments/edit_environment_spec.js4
-rw-r--r--spec/frontend/environments/empty_state_spec.js52
-rw-r--r--spec/frontend/environments/enable_review_app_modal_spec.js23
-rw-r--r--spec/frontend/environments/environment_external_url_spec.js31
-rw-r--r--spec/frontend/environments/environment_folder_spec.js22
-rw-r--r--spec/frontend/environments/environments_app_spec.js53
-rw-r--r--spec/frontend/environments/environments_detail_header_spec.js21
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js26
-rw-r--r--spec/frontend/environments/new_environment_spec.js4
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js8
-rw-r--r--spec/frontend/error_tracking/store/actions_spec.js6
-rw-r--r--spec/frontend/error_tracking/store/details/actions_spec.js6
-rw-r--r--spec/frontend/error_tracking/store/list/actions_spec.js4
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_helper_spec.js4
-rw-r--r--spec/frontend/fixtures/namespaces.rb47
-rw-r--r--spec/frontend/fixtures/pipeline_schedules.rb72
-rw-r--r--spec/frontend/flash_spec.js7
-rw-r--r--spec/frontend/grafana_integration/components/grafana_integration_spec.js6
-rw-r--r--spec/frontend/groups/components/app_spec.js88
-rw-r--r--spec/frontend/groups/components/group_item_spec.js11
-rw-r--r--spec/frontend/groups/components/groups_spec.js9
-rw-r--r--spec/frontend/groups/components/new_top_level_group_alert_spec.js75
-rw-r--r--spec/frontend/groups/components/overview_tabs_spec.js162
-rw-r--r--spec/frontend/groups/components/transfer_group_form_spec.js2
-rw-r--r--spec/frontend/groups/store/groups_store_spec.js10
-rw-r--r--spec/frontend/header_search/components/app_spec.js26
-rw-r--r--spec/frontend/ide/components/commit_sidebar/actions_spec.js65
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_item_spec.js125
-rw-r--r--spec/frontend/ide/components/commit_sidebar/message_field_spec.js128
-rw-r--r--spec/frontend/ide/components/commit_sidebar/radio_group_spec.js135
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js140
-rw-r--r--spec/frontend/ide/components/file_templates/bar_spec.js71
-rw-r--r--spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap60
-rw-r--r--spec/frontend/ide/components/jobs/detail/description_spec.js35
-rw-r--r--spec/frontend/ide/components/jobs/detail_spec.js162
-rw-r--r--spec/frontend/ide/components/jobs/item_spec.js30
-rw-r--r--spec/frontend/ide/components/jobs/stage_spec.js9
-rw-r--r--spec/frontend/ide/components/new_dropdown/button_spec.js65
-rw-r--r--spec/frontend/ide/components/new_dropdown/modal_spec.js10
-rw-r--r--spec/frontend/ide/components/new_dropdown/upload_spec.js71
-rw-r--r--spec/frontend/ide/components/shared/tokened_input_spec.js135
-rw-r--r--spec/frontend/ide/components/terminal/terminal_spec.js2
-rw-r--r--spec/frontend/ide/init_gitlab_web_ide_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js8
-rw-r--r--spec/frontend/ide/stores/actions/project_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions_spec.js16
-rw-r--r--spec/frontend/ide/stores/modules/commit/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js6
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js4
-rw-r--r--spec/frontend/ide/stores/mutations/tree_spec.js4
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js8
-rw-r--r--spec/frontend/ide/utils_spec.js4
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js16
-rw-r--r--spec/frontend/import_entities/import_groups/services/status_poller_spec.js4
-rw-r--r--spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js60
-rw-r--r--spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js22
-rw-r--r--spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js22
-rw-r--r--spec/frontend/import_entities/import_projects/store/actions_spec.js30
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js45
-rw-r--r--spec/frontend/issuable/bulk_update_sidebar/components/status_dropdown_spec.js75
-rw-r--r--spec/frontend/issuable/bulk_update_sidebar/components/status_select_spec.js77
-rw-r--r--spec/frontend/issuable/bulk_update_sidebar/components/subscriptions_dropdown_spec.js76
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js8
-rw-r--r--spec/frontend/issues/show/components/edited_spec.js16
-rw-r--r--spec/frontend/issues/show/components/fields/description_spec.js59
-rw-r--r--spec/frontend/issues/show/components/form_spec.js76
-rw-r--r--spec/frontend/issues/show/components/incidents/incident_tabs_spec.js19
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js24
-rw-r--r--spec/frontend/jira_connect/branches/components/new_branch_form_spec.js2
-rw-r--r--spec/frontend/jira_connect/subscriptions/pkce_spec.js4
-rw-r--r--spec/frontend/jobs/components/table/job_table_app_spec.js4
-rw-r--r--spec/frontend/labels/components/promote_label_modal_spec.js116
-rw-r--r--spec/frontend/lib/dompurify_spec.js4
-rw-r--r--spec/frontend/lib/utils/autosave_spec.js57
-rw-r--r--spec/frontend/lib/utils/datetime/date_format_utility_spec.js19
-rw-r--r--spec/frontend/lib/utils/text_markdown_spec.js51
-rw-r--r--spec/frontend/lib/utils/text_utility_spec.js12
-rw-r--r--spec/frontend/listbox/index_spec.js30
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js2
-rw-r--r--spec/frontend/members/components/table/member_action_buttons_spec.js2
-rw-r--r--spec/frontend/members/components/table/member_avatar_spec.js2
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js2
-rw-r--r--spec/frontend/members/utils_spec.js12
-rw-r--r--spec/frontend/merge_conflicts/store/actions_spec.js4
-rw-r--r--spec/frontend/merge_request_spec.js10
-rw-r--r--spec/frontend/milestones/components/promote_milestone_modal_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js8
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js4
-rw-r--r--spec/frontend/monitoring/requests/index_spec.js2
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js20
-rw-r--r--spec/frontend/monitoring/utils_spec.js14
-rw-r--r--spec/frontend/nav/components/top_nav_app_spec.js28
-rw-r--r--spec/frontend/notebook/cells/output/index_spec.js1
-rw-r--r--spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap8
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js29
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js2
-rw-r--r--spec/frontend/notes/components/note_header_spec.js99
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js2
-rw-r--r--spec/frontend/notes/components/notes_activity_header_spec.js67
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js31
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js141
-rw-r--r--spec/frontend/notes/mock_data.js17
-rw-r--r--spec/frontend/notes/utils/get_notes_filter_data_spec.js44
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js18
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap24
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js22
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js18
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js1
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/details_spec.js42
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js32
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js37
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/mock_data.js9
-rw-r--r--spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js38
-rw-r--r--spec/frontend/pages/import/fogbugz/new_user_map/components/user_select_spec.js81
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_form_spec.js4
-rw-r--r--spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js4
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js3
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js291
-rw-r--r--spec/frontend/pdf/page_spec.js27
-rw-r--r--spec/frontend/performance_bar/components/request_warning_spec.js29
-rw-r--r--spec/frontend/persistent_user_callout_spec.js6
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js30
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js21
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_home_spec.js10
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js242
-rw-r--r--spec/frontend/pipeline_new/mock_data.js59
-rw-r--r--spec/frontend/pipeline_schedules/components/pipeline_schedules_form_spec.js25
-rw-r--r--spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js161
-rw-r--r--spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_actions_spec.js49
-rw-r--r--spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline_spec.js42
-rw-r--r--spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_next_run_spec.js43
-rw-r--r--spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_owner_spec.js40
-rw-r--r--spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_target_spec.js41
-rw-r--r--spec/frontend/pipeline_schedules/components/table/pipeline_schedules_table_spec.js39
-rw-r--r--spec/frontend/pipeline_schedules/mock_data.js35
-rw-r--r--spec/frontend/pipeline_wizard/components/commit_spec.js4
-rw-r--r--spec/frontend/pipeline_wizard/components/editor_spec.js20
-rw-r--r--spec/frontend/pipeline_wizard/components/widgets/list_spec.js21
-rw-r--r--spec/frontend/pipeline_wizard/components/wrapper_spec.js29
-rw-r--r--spec/frontend/pipeline_wizard/mock/yaml.js3
-rw-r--r--spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js6
-rw-r--r--spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js4
-rw-r--r--spec/frontend/pipelines/components/jobs/jobs_app_spec.js6
-rw-r--r--spec/frontend/pipelines/pipeline_multi_actions_spec.js19
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js4
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js16
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js4
-rw-r--r--spec/frontend/pipelines/test_reports/stores/mutations_spec.js4
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js6
-rw-r--r--spec/frontend/profile/preferences/components/profile_preferences_spec.js16
-rw-r--r--spec/frontend/projects/commit/store/actions_spec.js4
-rw-r--r--spec/frontend/projects/commits/store/actions_spec.js6
-rw-r--r--spec/frontend/projects/compare/components/app_spec.js34
-rw-r--r--spec/frontend/projects/compare/components/mock_data.js1
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js4
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js6
-rw-r--r--spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js110
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js110
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js108
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js57
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js53
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js50
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/protections/index_spec.js57
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/protections/merge_protections_spec.js53
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/protections/push_protections_spec.js50
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/view/index_spec.js113
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/view/mock_data.js141
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js71
-rw-r--r--spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js68
-rw-r--r--spec/frontend/projects/settings/branch_rules/rule_edit_spec.js108
-rw-r--r--spec/frontend/projects/settings/components/default_branch_selector_spec.js46
-rw-r--r--spec/frontend/projects/settings/components/transfer_project_form_spec.js273
-rw-r--r--spec/frontend/projects/settings/repository/branch_rules/app_spec.js18
-rw-r--r--spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js30
-rw-r--r--spec/frontend/projects/settings/repository/branch_rules/mock_data.js13
-rw-r--r--spec/frontend/protected_branches/protected_branch_edit_spec.js6
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js28
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap12
-rw-r--r--spec/frontend/releases/components/app_index_spec.js6
-rw-r--r--spec/frontend/releases/components/app_show_spec.js6
-rw-r--r--spec/frontend/releases/components/evidence_block_spec.js6
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js46
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js43
-rw-r--r--spec/frontend/releases/stores/modules/detail/getters_spec.js4
-rw-r--r--spec/frontend/releases/stores/modules/detail/mutations_spec.js11
-rw-r--r--spec/frontend/releases/util_spec.js16
-rw-r--r--spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js112
-rw-r--r--spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js125
-rw-r--r--spec/frontend/reports/accessibility_report/mock_data.js53
-rw-r--r--spec/frontend/reports/accessibility_report/store/actions_spec.js115
-rw-r--r--spec/frontend/reports/accessibility_report/store/getters_spec.js149
-rw-r--r--spec/frontend/reports/accessibility_report/store/mutations_spec.js64
-rw-r--r--spec/frontend/reports/components/report_section_spec.js22
-rw-r--r--spec/frontend/repository/commits_service_spec.js6
-rw-r--r--spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap2
-rw-r--r--spec/frontend/repository/components/blob_controls_spec.js12
-rw-r--r--spec/frontend/repository/components/last_commit_spec.js2
-rw-r--r--spec/frontend/repository/components/new_directory_modal_spec.js4
-rw-r--r--spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap18
-rw-r--r--spec/frontend/repository/components/table/index_spec.js2
-rw-r--r--spec/frontend/repository/components/table/parent_row_spec.js4
-rw-r--r--spec/frontend/repository/components/table/row_spec.js16
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js4
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js16
-rw-r--r--spec/frontend/repository/pages/blob_spec.js2
-rw-r--r--spec/frontend/repository/pages/index_spec.js2
-rw-r--r--spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js4
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js75
-rw-r--r--spec/frontend/runner/components/cells/link_cell_spec.js2
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js4
-rw-r--r--spec/frontend/runner/components/cells/runner_owner_cell_spec.js111
-rw-r--r--spec/frontend/runner/components/cells/runner_stacked_summary_cell_spec.js6
-rw-r--r--spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js99
-rw-r--r--spec/frontend/runner/components/runner_delete_button_spec.js31
-rw-r--r--spec/frontend/runner/components/runner_details_spec.js28
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js33
-rw-r--r--spec/frontend/runner/components/runner_list_empty_state_spec.js57
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js56
-rw-r--r--spec/frontend/runner/components/runner_membership_toggle_spec.js57
-rw-r--r--spec/frontend/runner/components/runner_stacked_layout_banner_spec.js2
-rw-r--r--spec/frontend/runner/components/runner_type_tabs_spec.js20
-rw-r--r--spec/frontend/runner/components/runner_update_form_spec.js2
-rw-r--r--spec/frontend/runner/components/search_tokens/tag_token_spec.js43
-rw-r--r--spec/frontend/runner/graphql/local_state_spec.js51
-rw-r--r--spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js5
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js69
-rw-r--r--spec/frontend/runner/mock_data.js96
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js41
-rw-r--r--spec/frontend/search/sidebar/components/confidentiality_filter_spec.js2
-rw-r--r--spec/frontend/search/sidebar/components/radio_filter_spec.js2
-rw-r--r--spec/frontend/search/sidebar/components/status_filter_spec.js2
-rw-r--r--spec/frontend/search/sort/components/app_spec.js6
-rw-r--r--spec/frontend/search/store/actions_spec.js6
-rw-r--r--spec/frontend/search/topbar/components/app_spec.js6
-rw-r--r--spec/frontend/search/topbar/components/group_filter_spec.js2
-rw-r--r--spec/frontend/search/topbar/components/project_filter_spec.js2
-rw-r--r--spec/frontend/search_settings/components/search_settings_spec.js46
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js2
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js4
-rw-r--r--spec/frontend/security_configuration/components/upgrade_banner_spec.js2
-rw-r--r--spec/frontend/self_monitor/components/self_monitor_form_spec.js4
-rw-r--r--spec/frontend/set_status_modal/set_status_form_spec.js2
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js8
-rw-r--r--spec/frontend/sidebar/assignee_title_spec.js4
-rw-r--r--spec/frontend/sidebar/assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js36
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js2
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js6
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js4
-rw-r--r--spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js2
-rw-r--r--spec/frontend/sidebar/components/crm_contacts_spec.js4
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js10
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_formatted_date_spec.js2
-rw-r--r--spec/frontend/sidebar/components/severity/severity_spec.js2
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js6
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js14
-rw-r--r--spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js4
-rw-r--r--spec/frontend/sidebar/components/time_tracking/report_spec.js10
-rw-r--r--spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js16
-rw-r--r--spec/frontend/sidebar/issuable_assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/lock/edit_form_buttons_spec.js6
-rw-r--r--spec/frontend/sidebar/lock/issuable_lock_form_spec.js2
-rw-r--r--spec/frontend/sidebar/mock_data.js1
-rw-r--r--spec/frontend/sidebar/participants_spec.js6
-rw-r--r--spec/frontend/sidebar/reviewer_title_spec.js4
-rw-r--r--spec/frontend/sidebar/reviewers_spec.js2
-rw-r--r--spec/frontend/sidebar/sidebar_assignees_spec.js8
-rw-r--r--spec/frontend/sidebar/sidebar_mediator_spec.js18
-rw-r--r--spec/frontend/sidebar/sidebar_move_issue_spec.js4
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js2
-rw-r--r--spec/frontend/sidebar/todo_spec.js10
-rw-r--r--spec/frontend/smart_interval_spec.js16
-rw-r--r--spec/frontend/snippet/collapsible_input_spec.js4
-rw-r--r--spec/frontend/snippets/components/edit_spec.js14
-rw-r--r--spec/frontend/snippets/components/embed_dropdown_spec.js2
-rw-r--r--spec/frontend/snippets/components/snippet_blob_edit_spec.js10
-rw-r--r--spec/frontend/snippets/components/snippet_blob_view_spec.js89
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js14
-rw-r--r--spec/frontend/snippets/components/snippet_title_spec.js8
-rw-r--r--spec/frontend/snippets/components/snippet_visibility_edit_spec.js8
-rw-r--r--spec/frontend/terms/components/app_spec.js2
-rw-r--r--spec/frontend/terraform/components/states_table_spec.js6
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js14
-rw-r--r--spec/frontend/toggles/index_spec.js4
-rw-r--r--spec/frontend/token_access/token_access_spec.js16
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js18
-rw-r--r--spec/frontend/user_lists/components/edit_user_list_spec.js8
-rw-r--r--spec/frontend/user_lists/components/new_user_list_spec.js2
-rw-r--r--spec/frontend/user_lists/components/user_list_spec.js6
-rw-r--r--spec/frontend/user_lists/components/user_lists_table_spec.js4
-rw-r--r--spec/frontend/user_popovers_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js14
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js6
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js12
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap10
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js6
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js4
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js222
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js21
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js77
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js175
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js93
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/__snapshots__/dynamic_content_spec.js.snap35
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/dynamic_content_spec.js52
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/widget_content_row_spec.js65
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/widget_content_section_spec.js39
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js7
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js20
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js20
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js16
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js94
-rw-r--r--spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js96
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js17
-rw-r--r--spec/frontend/vue_shared/components/ci_badge_link_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js51
-rw-r--r--spec/frontend/vue_shared/components/file_finder/item_spec.js118
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/gitlab_version_check_spec.js33
-rw-r--r--spec/frontend/vue_shared/components/gl_countdown_spec.js36
-rw-r--r--spec/frontend/vue_shared/components/group_select/utils_spec.js24
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js289
-rw-r--r--spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/metric_images/store/actions_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/modal_copy_button_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_deprecated_spec.js236
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js226
-rw-r--r--spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap23
-rw-r--r--spec/frontend/vue_shared/components/notes/placeholder_note_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/panel_resizer_spec.js81
-rw-r--r--spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap8
-rw-r--r--spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/highlight_util_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/index_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/wrap_bidi_chars_spec.js17
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/wrap_comments_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js21
-rw-r--r--spec/frontend/vue_shared/components/stacked_progress_bar_spec.js124
-rw-r--r--spec/frontend/vue_shared/components/timezone_dropdown/helpers.js6
-rw-r--r--spec/frontend/vue_shared/components/timezone_dropdown/timezone_dropdown_spec.js111
-rw-r--r--spec/frontend/vue_shared/components/url_sync_spec.js62
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_new_spec.js134
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_old_spec.js127
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js143
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_new_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_old_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js119
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js25
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js70
-rw-r--r--spec/frontend/vue_shared/directives/safe_html_spec.js116
-rw-r--r--spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap30
-rw-r--r--spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js265
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js8
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js6
-rw-r--r--spec/frontend/webhooks/components/form_url_app_spec.js142
-rw-r--r--spec/frontend/webhooks/components/form_url_mask_item_spec.js100
-rw-r--r--spec/frontend/whats_new/components/app_spec.js6
-rw-r--r--spec/frontend/work_items/components/work_item_assignees_spec.js8
-rw-r--r--spec/frontend/work_items/components/work_item_description_spec.js31
-rw-r--r--spec/frontend/work_items/components/work_item_detail_spec.js100
-rw-r--r--spec/frontend/work_items/components/work_item_due_date_spec.js4
-rw-r--r--spec/frontend/work_items/components/work_item_labels_spec.js98
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js2
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js4
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_spec.js31
-rw-r--r--spec/frontend/work_items/components/work_item_milestone_spec.js247
-rw-r--r--spec/frontend/work_items/components/work_item_type_icon_spec.js2
-rw-r--r--spec/frontend/work_items/mock_data.js273
-rw-r--r--spec/frontend/work_items/router_spec.js10
-rw-r--r--spec/frontend/work_items_hierarchy/components/app_spec.js4
-rw-r--r--spec/frontend/work_items_hierarchy/components/hierarchy_spec.js2
-rw-r--r--spec/frontend_integration/content_editor/content_editor_integration_spec.js21
-rw-r--r--spec/frontend_integration/diffs/diffs_interopability_spec.js1
-rw-r--r--spec/graphql/gitlab_schema_spec.rb103
-rw-r--r--spec/graphql/graphql_triggers_spec.rb42
-rw-r--r--spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb2
-rw-r--r--spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb2
-rw-r--r--spec/graphql/mutations/ci/runner/update_spec.rb10
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/create_spec.rb2
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/update_spec.rb2
-rw-r--r--spec/graphql/mutations/namespace/package_settings/update_spec.rb37
-rw-r--r--spec/graphql/mutations/work_items/update_widgets_spec.rb58
-rw-r--r--spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb52
-rw-r--r--spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/project_pipeline_schedules_resolver_spec.rb40
-rw-r--r--spec/graphql/resolvers/users/participants_resolver_spec.rb83
-rw-r--r--spec/graphql/types/branch_rule_type_spec.rb22
-rw-r--r--spec/graphql/types/ci/job_token_scope_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb13
-rw-r--r--spec/graphql/types/ci/pipeline_schedule_status_enum_spec.rb11
-rw-r--r--spec/graphql/types/ci/pipeline_schedule_type_spec.rb30
-rw-r--r--spec/graphql/types/environment_type_spec.rb4
-rw-r--r--spec/graphql/types/namespace/package_settings_type_spec.rb20
-rw-r--r--spec/graphql/types/packages/tag_type_spec.rb2
-rw-r--r--spec/graphql/types/permission_types/ci/pipeline_schedule_type_spec.rb7
-rw-r--r--spec/graphql/types/project_type_spec.rb16
-rw-r--r--spec/graphql/types/projects/branch_rule_type_spec.rb23
-rw-r--r--spec/graphql/types/subscription_type_spec.rb2
-rw-r--r--spec/graphql/types/work_items/widgets/labels_update_input_type_spec.rb9
-rw-r--r--spec/helpers/application_helper_spec.rb19
-rw-r--r--spec/helpers/application_settings_helper_spec.rb48
-rw-r--r--spec/helpers/boards_helper_spec.rb14
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb105
-rw-r--r--spec/helpers/commits_helper_spec.rb9
-rw-r--r--spec/helpers/events_helper_spec.rb39
-rw-r--r--spec/helpers/form_helper_spec.rb68
-rw-r--r--spec/helpers/groups_helper_spec.rb31
-rw-r--r--spec/helpers/hooks_helper_spec.rb7
-rw-r--r--spec/helpers/ide_helper_spec.rb130
-rw-r--r--spec/helpers/invite_members_helper_spec.rb4
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb12
-rw-r--r--spec/helpers/issues_helper_spec.rb4
-rw-r--r--spec/helpers/listbox_helper_spec.rb32
-rw-r--r--spec/helpers/markup_helper_spec.rb66
-rw-r--r--spec/helpers/milestones_helper_spec.rb41
-rw-r--r--spec/helpers/nav_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb22
-rw-r--r--spec/helpers/recaptcha_helper_spec.rb69
-rw-r--r--spec/helpers/releases_helper_spec.rb6
-rw-r--r--spec/helpers/search_helper_spec.rb293
-rw-r--r--spec/helpers/sessions_helper_spec.rb6
-rw-r--r--spec/helpers/todos_helper_spec.rb18
-rw-r--r--spec/helpers/users_helper_spec.rb11
-rw-r--r--spec/helpers/wiki_helper_spec.rb23
-rw-r--r--spec/initializers/100_patch_omniauth_oauth2_spec.rb2
-rw-r--r--spec/initializers/attr_encrypted_no_db_connection_spec.rb40
-rw-r--r--spec/initializers/attr_encrypted_thread_safe_spec.rb28
-rw-r--r--spec/initializers/diagnostic_reports_spec.rb28
-rw-r--r--spec/initializers/memory_watchdog_spec.rb76
-rw-r--r--spec/initializers/sawyer_patch_spec.rb24
-rw-r--r--spec/initializers/sidekiq_spec.rb57
-rw-r--r--spec/lib/api/entities/bulk_imports/entity_failure_spec.rb19
-rw-r--r--spec/lib/api/entities/ml/mlflow/run_spec.rb50
-rw-r--r--spec/lib/api/helpers/merge_requests_helpers_spec.rb4
-rw-r--r--spec/lib/api/helpers/open_api_spec.rb21
-rw-r--r--spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb66
-rw-r--r--spec/lib/api/helpers/packages_helpers_spec.rb20
-rw-r--r--spec/lib/api/helpers_spec.rb110
-rw-r--r--spec/lib/banzai/filter/pathological_markdown_filter_spec.rb27
-rw-r--r--spec/lib/banzai/filter/references/label_reference_filter_spec.rb22
-rw-r--r--spec/lib/banzai/filter/truncate_visible_filter_spec.rb128
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb8
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb16
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb2
-rw-r--r--spec/lib/bitbucket/connection_spec.rb10
-rw-r--r--spec/lib/bulk_imports/common/pipelines/entity_finisher_spec.rb5
-rw-r--r--spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb4
-rw-r--r--spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb31
-rw-r--r--spec/lib/bulk_imports/features_spec.rb43
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb78
-rw-r--r--spec/lib/bulk_imports/network_error_spec.rb16
-rw-r--r--spec/lib/bulk_imports/pipeline/runner_spec.rb10
-rw-r--r--spec/lib/bulk_imports/pipeline_spec.rb33
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb5
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb5
-rw-r--r--spec/lib/container_registry/client_spec.rb32
-rw-r--r--spec/lib/container_registry/gitlab_api_client_spec.rb11
-rw-r--r--spec/lib/csv_builders/stream_spec.rb20
-rw-r--r--spec/lib/expand_variables_spec.rb4
-rw-r--r--spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb18
-rw-r--r--spec/lib/gitlab/anonymous_session_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb44
-rw-r--r--spec/lib/gitlab/auth_spec.rb6
-rw-r--r--spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb30
-rw-r--r--spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb30
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb55
-rw-r--r--spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb25
-rw-r--r--spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb111
-rw-r--r--spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb141
-rw-r--r--spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb9
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb15
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb70
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb70
-rw-r--r--spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb62
-rw-r--r--spec/lib/gitlab/bare_repository_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/bare_repository_import/repository_spec.rb2
-rw-r--r--spec/lib/gitlab/batch_pop_queueing_spec.rb147
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb59
-rw-r--r--spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/ansi2json_spec.rb389
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb36
-rw-r--r--spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb173
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb9
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config/entry/variable_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/config/entry/variables_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/config/entry/workflow_spec.rb48
-rw-r--r--spec/lib/gitlab/ci/config/external/file/artifact_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/jwt_v2_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb106
-rw-r--r--spec/lib/gitlab/ci/parsers/security/sast_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb51
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb97
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/pipeline/duration_spec.rb224
-rw-r--r--spec/lib/gitlab/ci/pipeline/logger_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb33
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/source_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/reports/security/report_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/secure_files/cer_spec.rb69
-rw-r--r--spec/lib/gitlab/ci/secure_files/mobile_provision_spec.rb149
-rw-r--r--spec/lib/gitlab/ci/secure_files/p12_spec.rb81
-rw-r--r--spec/lib/gitlab/ci/secure_files/x509_name_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/builder/group_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/variables/builder/project_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/variables/builder/release_spec.rb69
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb44
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sort_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb9
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb330
-rw-r--r--spec/lib/gitlab/config/entry/validators_spec.rb2
-rw-r--r--spec/lib/gitlab/config_checker/external_database_checker_spec.rb99
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb27
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb1
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb44
-rw-r--r--spec/lib/gitlab/database/each_database_spec.rb53
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb30
-rw-r--r--spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb19
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb42
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb10
-rw-r--r--spec/lib/gitlab/database/load_balancing/transaction_leaking_spec.rb67
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb184
-rw-r--r--spec/lib/gitlab/database/migrations/base_background_runner_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/runner_spec.rb195
-rw-r--r--spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb202
-rw-r--r--spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb19
-rw-r--r--spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb15
-rw-r--r--spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb9
-rw-r--r--spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb17
-rw-r--r--spec/lib/gitlab/database/partitioning/time_partition_spec.rb13
-rw-r--r--spec/lib/gitlab/database/partitioning_spec.rb14
-rw-r--r--spec/lib/gitlab/database/reflection_spec.rb6
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb20
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb8
-rw-r--r--spec/lib/gitlab/database/similarity_score_spec.rb18
-rw-r--r--spec/lib/gitlab/database_spec.rb15
-rw-r--r--spec/lib/gitlab/diff/char_diff_spec.rb22
-rw-r--r--spec/lib/gitlab/diff/file_collection_sorter_spec.rb43
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb13
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb64
-rw-r--r--spec/lib/gitlab/encoding_helper_spec.rb12
-rw-r--r--spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb6
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb675
-rw-r--r--spec/lib/gitlab/experimentation/experiment_spec.rb58
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb161
-rw-r--r--spec/lib/gitlab/git/keep_around_spec.rb13
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb77
-rw-r--r--spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb3
-rw-r--r--spec/lib/gitlab/git/wiki_spec.rb134
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb1
-rw-r--r--spec/lib/gitlab/git_access_spec.rb53
-rw-r--r--spec/lib/gitlab/gitaly_client/blob_service_spec.rb28
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb32
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb16
-rw-r--r--spec/lib/gitlab/gitaly_client/wiki_service_spec.rb118
-rw-r--r--spec/lib/gitlab/github_import/client_spec.rb30
-rw-r--r--spec/lib/gitlab/github_import/importer/attachments/base_importer_spec.rb28
-rw-r--r--spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb61
-rw-r--r--spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb61
-rw-r--r--spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb58
-rw-r--r--spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb57
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/issues_importer_spec.rb33
-rw-r--r--spec/lib/gitlab/github_import/importer/labels_importer_spec.rb6
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb7
-rw-r--r--spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb10
-rw-r--r--spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb85
-rw-r--r--spec/lib/gitlab/github_import/importer/note_importer_spec.rb7
-rw-r--r--spec/lib/gitlab/github_import/importer/notes_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/protected_branch_importer_spec.rb218
-rw-r--r--spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb6
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb15
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb50
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb10
-rw-r--r--spec/lib/gitlab/github_import/importer/release_attachments_importer_spec.rb57
-rw-r--r--spec/lib/gitlab/github_import/importer/releases_attachments_importer_spec.rb74
-rw-r--r--spec/lib/gitlab/github_import/importer/releases_importer_spec.rb27
-rw-r--r--spec/lib/gitlab/github_import/importer/single_endpoint_diff_notes_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb32
-rw-r--r--spec/lib/gitlab/github_import/importer/single_endpoint_issue_notes_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/importer/single_endpoint_merge_request_notes_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/issuable_finder_spec.rb67
-rw-r--r--spec/lib/gitlab/github_import/markdown/attachment_spec.rb93
-rw-r--r--spec/lib/gitlab/github_import/markdown_text_spec.rb37
-rw-r--r--spec/lib/gitlab/github_import/parallel_scheduling_spec.rb32
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_note_spec.rb9
-rw-r--r--spec/lib/gitlab/github_import/representation/issue_event_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/representation/issue_spec.rb17
-rw-r--r--spec/lib/gitlab/github_import/representation/note_spec.rb11
-rw-r--r--spec/lib/gitlab/github_import/representation/note_text_spec.rb80
-rw-r--r--spec/lib/gitlab/github_import/representation/protected_branch_spec.rb38
-rw-r--r--spec/lib/gitlab/github_import/representation/pull_request_review_spec.rb11
-rw-r--r--spec/lib/gitlab/github_import/representation/pull_request_spec.rb33
-rw-r--r--spec/lib/gitlab/github_import/representation/release_attachments_spec.rb49
-rw-r--r--spec/lib/gitlab/github_import/representation/user_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/settings_spec.rb82
-rw-r--r--spec/lib/gitlab/github_import/user_finder_spec.rb34
-rw-r--r--spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb11
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb1
-rw-r--r--spec/lib/gitlab/health_checks/master_check_spec.rb50
-rw-r--r--spec/lib/gitlab/hook_data/release_builder_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb130
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml11
-rw-r--r--spec/lib/gitlab/import_export/group/tree_restorer_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/group/tree_saver_spec.rb11
-rw-r--r--spec/lib/gitlab/import_export/project/relation_factory_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb23
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml6
-rw-r--r--spec/lib/gitlab/import_export/uploads_manager_spec.rb26
-rw-r--r--spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/jira_import/issues_importer_spec.rb50
-rw-r--r--spec/lib/gitlab/json_spec.rb10
-rw-r--r--spec/lib/gitlab/kubernetes/rollout_instances_spec.rb45
-rw-r--r--spec/lib/gitlab/legacy_github_import/branch_formatter_spec.rb18
-rw-r--r--spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb16
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb52
-rw-r--r--spec/lib/gitlab/legacy_github_import/issuable_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb36
-rw-r--r--spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb6
-rw-r--r--spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb8
-rw-r--r--spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb78
-rw-r--r--spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb12
-rw-r--r--spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb12
-rw-r--r--spec/lib/gitlab/memory/diagnostic_reports_logger_spec.rb22
-rw-r--r--spec/lib/gitlab/memory/reports_daemon_spec.rb39
-rw-r--r--spec/lib/gitlab/memory/reports_uploader_spec.rb80
-rw-r--r--spec/lib/gitlab/memory/upload_and_cleanup_reports_spec.rb109
-rw-r--r--spec/lib/gitlab/memory/watchdog/configuration_spec.rb121
-rw-r--r--spec/lib/gitlab/memory/watchdog/monitor/heap_fragmentation_spec.rb60
-rw-r--r--spec/lib/gitlab/memory/watchdog/monitor/unique_memory_growth_spec.rb62
-rw-r--r--spec/lib/gitlab/memory/watchdog/monitor_state_spec.rb72
-rw-r--r--spec/lib/gitlab/memory/watchdog_spec.rb396
-rw-r--r--spec/lib/gitlab/metrics/global_search_slis_spec.rb129
-rw-r--r--spec/lib/gitlab/metrics/system_spec.rb67
-rw-r--r--spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb22
-rw-r--r--spec/lib/gitlab/pages/cache_control_spec.rb47
-rw-r--r--spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb9
-rw-r--r--spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb202
-rw-r--r--spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb37
-rw-r--r--spec/lib/gitlab/pagination/keyset/iterator_spec.rb31
-rw-r--r--spec/lib/gitlab/pagination/keyset/order_spec.rb381
-rw-r--r--spec/lib/gitlab/profiler_spec.rb84
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb5
-rw-r--r--spec/lib/gitlab/project_transfer_spec.rb9
-rw-r--r--spec/lib/gitlab/prometheus_client_spec.rb13
-rw-r--r--spec/lib/gitlab/push_options_spec.rb25
-rw-r--r--spec/lib/gitlab/query_limiting/transaction_spec.rb12
-rw-r--r--spec/lib/gitlab/rack_attack/request_spec.rb9
-rw-r--r--spec/lib/gitlab/reference_extractor_spec.rb2
-rw-r--r--spec/lib/gitlab/regex_requires_app_spec.rb6
-rw-r--r--spec/lib/gitlab/regex_spec.rb10
-rw-r--r--spec/lib/gitlab/search/abuse_detection_spec.rb20
-rw-r--r--spec/lib/gitlab/search/query_spec.rb34
-rw-r--r--spec/lib/gitlab/serializer/ci/variables_spec.rb9
-rw-r--r--spec/lib/gitlab/sidekiq_config_spec.rb4
-rw-r--r--spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb128
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb83
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb3
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb10
-rw-r--r--spec/lib/gitlab/sidekiq_status_spec.rb8
-rw-r--r--spec/lib/gitlab/slash_commands/issue_new_spec.rb15
-rw-r--r--spec/lib/gitlab/ssh_public_key_spec.rb24
-rw-r--r--spec/lib/gitlab/tracking/service_ping_context_spec.rb19
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb150
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/aggregated_metric_spec.rb72
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb19
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb18
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb19
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb25
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb30
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric_spec.rb60
-rw-r--r--spec/lib/gitlab/usage_data/topology_spec.rb278
-rw-r--r--spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb16
-rw-r--r--spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb19
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb8
-rw-r--r--spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb8
-rw-r--r--spec/lib/gitlab/usage_data_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb21
-rw-r--r--spec/lib/gitlab/user_access_snippet_spec.rb2
-rw-r--r--spec/lib/gitlab/utils_spec.rb11
-rw-r--r--spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb23
-rw-r--r--spec/lib/gitlab/webpack/manifest_spec.rb9
-rw-r--r--spec/lib/gitlab/x509/signature_spec.rb14
-rw-r--r--spec/lib/gitlab/x509/tag_spec.rb4
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb18
-rw-r--r--spec/lib/object_storage/config_spec.rb1
-rw-r--r--spec/lib/peek/views/bullet_detailed_spec.rb9
-rw-r--r--spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb10
-rw-r--r--spec/lib/sidebars/projects/menus/analytics_menu_spec.rb30
-rw-r--r--spec/lib/sidebars/projects/menus/deployments_menu_spec.rb34
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb25
-rw-r--r--spec/lib/sidebars/projects/menus/repository_menu_spec.rb24
-rw-r--r--spec/lib/system_check/incoming_email_check_spec.rb20
-rw-r--r--spec/lib/unnested_in_filters/rewriter_spec.rb34
-rw-r--r--spec/lib/version_check_spec.rb14
-rw-r--r--spec/mailers/emails/profile_spec.rb64
-rw-r--r--spec/migrations/20220809002011_schedule_destroy_invalid_group_members_spec.rb31
-rw-r--r--spec/migrations/20220901035725_schedule_destroy_invalid_project_members_spec.rb31
-rw-r--r--spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb31
-rw-r--r--spec/migrations/20220921093355_schedule_backfill_namespace_details_spec.rb37
-rw-r--r--spec/migrations/20220921144258_remove_orphan_group_token_users_spec.rb74
-rw-r--r--spec/migrations/20220922143143_schedule_reset_duplicate_ci_runners_token_values_spec.rb35
-rw-r--r--spec/migrations/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values_spec.rb35
-rw-r--r--spec/migrations/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status_spec.rb31
-rw-r--r--spec/migrations/20220929213730_schedule_delete_orphaned_operational_vulnerabilities_spec.rb32
-rw-r--r--spec/migrations/20221004094814_schedule_destroy_invalid_members_spec.rb31
-rw-r--r--spec/migrations/20221008032350_add_password_expiration_migration_spec.rb19
-rw-r--r--spec/migrations/20221012033107_add_password_last_changed_at_to_user_details_spec.rb33
-rw-r--r--spec/migrations/20221013154159_update_invalid_dormant_user_setting_spec.rb40
-rw-r--r--spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb14
-rw-r--r--spec/migrations/adjust_task_note_rename_background_migration_values_spec.rb143
-rw-r--r--spec/migrations/backfill_epic_cache_counts_spec.rb32
-rw-r--r--spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb59
-rw-r--r--spec/migrations/populate_releases_access_level_from_repository_spec.rb39
-rw-r--r--spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb13
-rw-r--r--spec/models/analytics/cycle_analytics/project_stage_spec.rb9
-rw-r--r--spec/models/application_setting_spec.rb39
-rw-r--r--spec/models/award_emoji_spec.rb9
-rw-r--r--spec/models/bulk_imports/entity_spec.rb51
-rw-r--r--spec/models/bulk_imports/export_status_spec.rb30
-rw-r--r--spec/models/bulk_imports/failure_spec.rb36
-rw-r--r--spec/models/ci/bridge_spec.rb6
-rw-r--r--spec/models/ci/build_metadata_spec.rb57
-rw-r--r--spec/models/ci/build_spec.rb152
-rw-r--r--spec/models/ci/build_trace_chunks/redis_spec.rb8
-rw-r--r--spec/models/ci/build_trace_spec.rb7
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb37
-rw-r--r--spec/models/ci/job_token/project_scope_link_spec.rb11
-rw-r--r--spec/models/ci/job_token/scope_spec.rb4
-rw-r--r--spec/models/ci/pipeline_metadata_spec.rb14
-rw-r--r--spec/models/ci/pipeline_spec.rb113
-rw-r--r--spec/models/ci/processable_spec.rb2
-rw-r--r--spec/models/ci/resource_group_spec.rb6
-rw-r--r--spec/models/ci/runner_spec.rb184
-rw-r--r--spec/models/ci/secure_file_spec.rb66
-rw-r--r--spec/models/ci/unit_test_spec.rb40
-rw-r--r--spec/models/ci/variable_spec.rb2
-rw-r--r--spec/models/clusters/agents/implicit_authorization_spec.rb2
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb52
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb67
-rw-r--r--spec/models/commit_collection_spec.rb5
-rw-r--r--spec/models/compare_spec.rb15
-rw-r--r--spec/models/concerns/approvable_spec.rb8
-rw-r--r--spec/models/concerns/atomic_internal_id_spec.rb13
-rw-r--r--spec/models/concerns/cascading_namespace_setting_attribute_spec.rb347
-rw-r--r--spec/models/concerns/ci/partitionable_spec.rb26
-rw-r--r--spec/models/concerns/counter_attribute_spec.rb4
-rw-r--r--spec/models/concerns/id_in_ordered_spec.rb7
-rw-r--r--spec/models/concerns/issuable_spec.rb18
-rw-r--r--spec/models/concerns/mentionable_spec.rb2
-rw-r--r--spec/models/concerns/noteable_spec.rb100
-rw-r--r--spec/models/concerns/participable_spec.rb3
-rw-r--r--spec/models/concerns/prometheus_adapter_spec.rb2
-rw-r--r--spec/models/concerns/routable_spec.rb6
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb100
-rw-r--r--spec/models/container_repository_spec.rb2
-rw-r--r--spec/models/deployment_spec.rb15
-rw-r--r--spec/models/diff_note_spec.rb28
-rw-r--r--spec/models/diff_viewer/server_side_spec.rb26
-rw-r--r--spec/models/discussion_spec.rb9
-rw-r--r--spec/models/environment_spec.rb59
-rw-r--r--spec/models/factories_spec.rb2
-rw-r--r--spec/models/group_spec.rb19
-rw-r--r--spec/models/hooks/web_hook_spec.rb120
-rw-r--r--spec/models/incident_management/timeline_event_spec.rb7
-rw-r--r--spec/models/incident_management/timeline_event_tag_link_spec.rb10
-rw-r--r--spec/models/incident_management/timeline_event_tag_spec.rb28
-rw-r--r--spec/models/integration_spec.rb11
-rw-r--r--spec/models/integrations/chat_message/issue_message_spec.rb17
-rw-r--r--spec/models/integrations/chat_message/wiki_page_message_spec.rb26
-rw-r--r--spec/models/integrations/datadog_spec.rb4
-rw-r--r--spec/models/integrations/harbor_spec.rb70
-rw-r--r--spec/models/integrations/jira_spec.rb9
-rw-r--r--spec/models/integrations/microsoft_teams_spec.rb6
-rw-r--r--spec/models/integrations/prometheus_spec.rb4
-rw-r--r--spec/models/jira_connect/public_key_spec.rb90
-rw-r--r--spec/models/jira_connect_installation_spec.rb98
-rw-r--r--spec/models/label_note_spec.rb14
-rw-r--r--spec/models/member_spec.rb24
-rw-r--r--spec/models/members/member_role_spec.rb34
-rw-r--r--spec/models/merge_request/cleanup_schedule_spec.rb13
-rw-r--r--spec/models/merge_request_diff_file_spec.rb20
-rw-r--r--spec/models/merge_request_diff_spec.rb119
-rw-r--r--spec/models/merge_request_spec.rb311
-rw-r--r--spec/models/milestone_spec.rb128
-rw-r--r--spec/models/ml/candidate_spec.rb10
-rw-r--r--spec/models/ml/experiment_spec.rb33
-rw-r--r--spec/models/namespace/aggregation_schedule_spec.rb26
-rw-r--r--spec/models/namespace/package_setting_spec.rb9
-rw-r--r--spec/models/namespace_setting_spec.rb4
-rw-r--r--spec/models/namespace_spec.rb21
-rw-r--r--spec/models/note_spec.rb10
-rw-r--r--spec/models/notification_recipient_spec.rb20
-rw-r--r--spec/models/operations/feature_flags/strategy_spec.rb26
-rw-r--r--spec/models/packages/package_spec.rb8
-rw-r--r--spec/models/packages/rpm/repository_file_spec.rb44
-rw-r--r--spec/models/pages_domain_spec.rb2
-rw-r--r--spec/models/personal_access_token_spec.rb25
-rw-r--r--spec/models/pool_repository_spec.rb13
-rw-r--r--spec/models/preloaders/project_root_ancestor_preloader_spec.rb48
-rw-r--r--spec/models/project_authorization_spec.rb186
-rw-r--r--spec/models/project_group_link_spec.rb6
-rw-r--r--spec/models/project_setting_spec.rb4
-rw-r--r--spec/models/project_spec.rb106
-rw-r--r--spec/models/project_statistics_spec.rb48
-rw-r--r--spec/models/protected_branch_spec.rb24
-rw-r--r--spec/models/repository_spec.rb191
-rw-r--r--spec/models/resource_label_event_spec.rb10
-rw-r--r--spec/models/user_detail_spec.rb135
-rw-r--r--spec/models/user_preference_spec.rb51
-rw-r--r--spec/models/user_spec.rb263
-rw-r--r--spec/models/users/namespace_callout_spec.rb39
-rw-r--r--spec/models/users/phone_number_validation_spec.rb81
-rw-r--r--spec/models/wiki_directory_spec.rb49
-rw-r--r--spec/models/wiki_page_spec.rb148
-rw-r--r--spec/policies/blob_policy_spec.rb1
-rw-r--r--spec/policies/ci/runner_policy_spec.rb147
-rw-r--r--spec/policies/concerns/crud_policy_helpers_spec.rb39
-rw-r--r--spec/policies/group_policy_spec.rb98
-rw-r--r--spec/policies/issuable_policy_spec.rb24
-rw-r--r--spec/policies/issue_policy_spec.rb7
-rw-r--r--spec/policies/namespaces/user_namespace_policy_spec.rb2
-rw-r--r--spec/policies/project_policy_spec.rb127
-rw-r--r--spec/policies/project_snippet_policy_spec.rb328
-rw-r--r--spec/policies/wiki_page_policy_spec.rb45
-rw-r--r--spec/presenters/blobs/unfold_presenter_spec.rb20
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb17
-rw-r--r--spec/presenters/commit_presenter_spec.rb5
-rw-r--r--spec/presenters/deploy_key_presenter_spec.rb24
-rw-r--r--spec/presenters/event_presenter_spec.rb8
-rw-r--r--spec/presenters/key_presenter_spec.rb32
-rw-r--r--spec/presenters/project_presenter_spec.rb8
-rw-r--r--spec/presenters/projects/security/configuration_presenter_spec.rb31
-rw-r--r--spec/requests/admin/impersonation_tokens_controller_spec.rb18
-rw-r--r--spec/requests/api/admin/batched_background_migrations_spec.rb88
-rw-r--r--spec/requests/api/branches_spec.rb48
-rw-r--r--spec/requests/api/bulk_imports_spec.rb12
-rw-r--r--spec/requests/api/ci/job_artifacts_spec.rb43
-rw-r--r--spec/requests/api/ci/jobs_spec.rb25
-rw-r--r--spec/requests/api/ci/resource_groups_spec.rb42
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb52
-rw-r--r--spec/requests/api/ci/runner/runners_reset_spec.rb1
-rw-r--r--spec/requests/api/ci/runners_spec.rb40
-rw-r--r--spec/requests/api/deploy_tokens_spec.rb37
-rw-r--r--spec/requests/api/features_spec.rb772
-rw-r--r--spec/requests/api/generic_packages_spec.rb15
-rw-r--r--spec/requests/api/graphql/ci/ci_cd_setting_spec.rb2
-rw-r--r--spec/requests/api/graphql/ci/config_spec.rb64
-rw-r--r--spec/requests/api/graphql/ci/config_variables_spec.rb9
-rw-r--r--spec/requests/api/graphql/ci/jobs_spec.rb11
-rw-r--r--spec/requests/api/graphql/ci/pipeline_schedules_spec.rb88
-rw-r--r--spec/requests/api/graphql/jobs_query_spec.rb55
-rw-r--r--spec/requests/api/graphql/milestone_spec.rb199
-rw-r--r--spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb85
-rw-r--r--spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb82
-rw-r--r--spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb51
-rw-r--r--spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb45
-rw-r--r--spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb128
-rw-r--r--spec/requests/api/graphql/mutations/uploads/delete_spec.rb9
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb72
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb61
-rw-r--r--spec/requests/api/graphql/project/branch_rules_spec.rb68
-rw-r--r--spec/requests/api/graphql/project/cluster_agents_spec.rb11
-rw-r--r--spec/requests/api/graphql/project/issue/designs/designs_spec.rb33
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb50
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb53
-rw-r--r--spec/requests/api/graphql/project/milestones_spec.rb7
-rw-r--r--spec/requests/api/graphql/project/work_items_spec.rb113
-rw-r--r--spec/requests/api/graphql/todo_query_spec.rb9
-rw-r--r--spec/requests/api/graphql/usage_trends_measurements_spec.rb22
-rw-r--r--spec/requests/api/graphql/work_item_spec.rb16
-rw-r--r--spec/requests/api/groups_spec.rb34
-rw-r--r--spec/requests/api/helm_packages_spec.rb11
-rw-r--r--spec/requests/api/import_github_spec.rb41
-rw-r--r--spec/requests/api/internal/base_spec.rb20
-rw-r--r--spec/requests/api/issues/issues_spec.rb15
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb4
-rw-r--r--spec/requests/api/issues/put_projects_issues_spec.rb4
-rw-r--r--spec/requests/api/maven_packages_spec.rb52
-rw-r--r--spec/requests/api/merge_requests_spec.rb87
-rw-r--r--spec/requests/api/metadata_spec.rb26
-rw-r--r--spec/requests/api/ml/mlflow_spec.rb330
-rw-r--r--spec/requests/api/pages_domains_spec.rb60
-rw-r--r--spec/requests/api/personal_access_tokens/self_information_spec.rb102
-rw-r--r--spec/requests/api/personal_access_tokens/self_revocation_spec.rb69
-rw-r--r--spec/requests/api/personal_access_tokens_spec.rb367
-rw-r--r--spec/requests/api/project_attributes.yml7
-rw-r--r--spec/requests/api/projects_spec.rb26
-rw-r--r--spec/requests/api/settings_spec.rb5
-rw-r--r--spec/requests/api/tags_spec.rb8
-rw-r--r--spec/requests/api/users_spec.rb33
-rw-r--r--spec/requests/api/version_spec.rb93
-rw-r--r--spec/requests/boards/lists_controller_spec.rb25
-rw-r--r--spec/requests/git_http_spec.rb54
-rw-r--r--spec/requests/groups/settings/access_tokens_controller_spec.rb15
-rw-r--r--spec/requests/ide_controller_spec.rb31
-rw-r--r--spec/requests/import/github_groups_controller_spec.rb69
-rw-r--r--spec/requests/jira_connect/public_keys_controller_spec.rb55
-rw-r--r--spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb9
-rw-r--r--spec/requests/projects/incident_management/timeline_events_spec.rb60
-rw-r--r--spec/requests/projects/issues_controller_spec.rb15
-rw-r--r--spec/requests/projects/merge_requests_controller_spec.rb15
-rw-r--r--spec/requests/projects/settings/access_tokens_controller_spec.rb15
-rw-r--r--spec/requests/users/namespace_callouts_spec.rb57
-rw-r--r--spec/requests/users_controller_spec.rb20
-rw-r--r--spec/routing/import_routing_spec.rb7
-rw-r--r--spec/rubocop/check_graceful_task_spec.rb18
-rw-r--r--spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb51
-rw-r--r--spec/rubocop/cop/gitlab/no_code_coverage_comment_spec.rb60
-rw-r--r--spec/rubocop/cop/gitlab/service_response_spec.rb41
-rw-r--r--spec/rubocop/cop/migration/background_migration_missing_active_concern_spec.rb86
-rw-r--r--spec/rubocop/cop/redis_queue_usage_spec.rb99
-rw-r--r--spec/rubocop/cop/rspec/factory_bot/avoid_create_spec.rb25
-rw-r--r--spec/rubocop/cop/rspec/top_level_describe_path_spec.rb13
-rw-r--r--spec/rubocop/cop/sidekiq_api_usage_spec.rb60
-rw-r--r--spec/rubocop/cop/sidekiq_redis_call_spec.rb30
-rw-r--r--spec/rubocop/cop/static_translation_definition_spec.rb12
-rw-r--r--spec/rubocop/cop_todo_spec.rb35
-rw-r--r--spec/rubocop/formatter/graceful_formatter_spec.rb9
-rw-r--r--spec/rubocop/formatter/todo_formatter_spec.rb70
-rw-r--r--spec/rubocop_spec_helper.rb18
-rw-r--r--spec/scripts/lib/glfm/update_example_snapshots_spec.rb759
-rw-r--r--spec/scripts/lib/glfm/update_specification_spec.rb169
-rw-r--r--spec/scripts/lib/glfm/verify_all_generated_files_are_up_to_date_spec.rb62
-rw-r--r--spec/scripts/trigger-build_spec.rb2
-rw-r--r--spec/serializers/board_serializer_spec.rb20
-rw-r--r--spec/serializers/board_simple_entity_spec.rb16
-rw-r--r--spec/serializers/build_trace_entity_spec.rb7
-rw-r--r--spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb33
-rw-r--r--spec/serializers/deployment_entity_spec.rb72
-rw-r--r--spec/serializers/environment_status_entity_spec.rb35
-rw-r--r--spec/serializers/group_access_token_entity_spec.rb4
-rw-r--r--spec/serializers/import/github_org_entity_spec.rb25
-rw-r--r--spec/serializers/import/github_org_serializer_spec.rb47
-rw-r--r--spec/serializers/issue_entity_spec.rb2
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb18
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb74
-rw-r--r--spec/serializers/project_access_token_entity_spec.rb4
-rw-r--r--spec/services/admin/set_feature_flag_service_spec.rb300
-rw-r--r--spec/services/alert_management/create_alert_issue_service_spec.rb6
-rw-r--r--spec/services/award_emojis/copy_service_spec.rb10
-rw-r--r--spec/services/boards/issues/create_service_spec.rb5
-rw-r--r--spec/services/boards/lists/generate_service_spec.rb45
-rw-r--r--spec/services/boards/lists/list_service_spec.rb34
-rw-r--r--spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb8
-rw-r--r--spec/services/bulk_imports/create_service_spec.rb5
-rw-r--r--spec/services/bulk_imports/repository_bundle_export_service_spec.rb10
-rw-r--r--spec/services/bulk_imports/uploads_export_service_spec.rb62
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb4
-rw-r--r--spec/services/ci/compare_test_reports_service_spec.rb9
-rw-r--r--spec/services/ci/create_pipeline_service/include_spec.rb46
-rw-r--r--spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb53
-rw-r--r--spec/services/ci/create_pipeline_service/logger_spec.rb1
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb48
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb6
-rw-r--r--spec/services/ci/find_exposed_artifacts_service_spec.rb58
-rw-r--r--spec/services/ci/generate_kubeconfig_service_spec.rb6
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb3
-rw-r--r--spec/services/ci/job_artifacts/delete_service_spec.rb27
-rw-r--r--spec/services/ci/job_token_scope/add_project_service_spec.rb2
-rw-r--r--spec/services/ci/job_token_scope/remove_project_service_spec.rb2
-rw-r--r--spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb25
-rw-r--r--spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb24
-rw-r--r--spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb32
-rw-r--r--spec/services/ci/runners/register_runner_service_spec.rb43
-rw-r--r--spec/services/ci/runners/set_runner_associated_projects_service_spec.rb12
-rw-r--r--spec/services/ci/unlock_artifacts_service_spec.rb21
-rw-r--r--spec/services/clusters/applications/destroy_service_spec.rb63
-rw-r--r--spec/services/clusters/applications/uninstall_service_spec.rb77
-rw-r--r--spec/services/design_management/move_designs_service_spec.rb35
-rw-r--r--spec/services/git/tag_hooks_service_spec.rb12
-rw-r--r--spec/services/google_cloud/enable_cloudsql_service_spec.rb30
-rw-r--r--spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb18
-rw-r--r--spec/services/groups/destroy_service_spec.rb6
-rw-r--r--spec/services/groups/import_export/import_service_spec.rb72
-rw-r--r--spec/services/import/github/cancel_project_import_service_spec.rb56
-rw-r--r--spec/services/import/github_service_spec.rb40
-rw-r--r--spec/services/import/gitlab_projects/create_project_service_spec.rb9
-rw-r--r--spec/services/incident_management/incidents/create_service_spec.rb4
-rw-r--r--spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb15
-rw-r--r--spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb2
-rw-r--r--spec/services/incident_management/timeline_events/create_service_spec.rb84
-rw-r--r--spec/services/incident_management/timeline_events/destroy_service_spec.rb22
-rw-r--r--spec/services/incident_management/timeline_events/update_service_spec.rb16
-rw-r--r--spec/services/issuable/process_assignees_spec.rb23
-rw-r--r--spec/services/issues/clone_service_spec.rb15
-rw-r--r--spec/services/issues/create_service_spec.rb128
-rw-r--r--spec/services/issues/move_service_spec.rb17
-rw-r--r--spec/services/issues/update_service_spec.rb32
-rw-r--r--spec/services/jira_connect/create_asymmetric_jwt_service_spec.rb46
-rw-r--r--spec/services/jira_connect/sync_service_spec.rb9
-rw-r--r--spec/services/members/create_service_spec.rb49
-rw-r--r--spec/services/members/destroy_service_spec.rb31
-rw-r--r--spec/services/merge_requests/close_service_spec.rb37
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb24
-rw-r--r--spec/services/merge_requests/create_service_spec.rb2
-rw-r--r--spec/services/merge_requests/ff_merge_service_spec.rb6
-rw-r--r--spec/services/merge_requests/link_lfs_objects_service_spec.rb9
-rw-r--r--spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb22
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb76
-rw-r--r--spec/services/merge_requests/mergeability/logger_spec.rb19
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb16
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb53
-rw-r--r--spec/services/merge_requests/request_review_service_spec.rb22
-rw-r--r--spec/services/merge_requests/update_assignees_service_spec.rb26
-rw-r--r--spec/services/merge_requests/update_reviewers_service_spec.rb12
-rw-r--r--spec/services/merge_requests/update_service_spec.rb48
-rw-r--r--spec/services/ml/experiment_tracking/candidate_repository_spec.rb199
-rw-r--r--spec/services/ml/experiment_tracking/experiment_repository_spec.rb85
-rw-r--r--spec/services/namespaces/package_settings/update_service_spec.rb37
-rw-r--r--spec/services/notification_service_spec.rb21
-rw-r--r--spec/services/onboarding/progress_service_spec.rb6
-rw-r--r--spec/services/packages/debian/create_package_file_service_spec.rb53
-rw-r--r--spec/services/packages/mark_packages_for_destruction_service_spec.rb107
-rw-r--r--spec/services/packages/rpm/parse_package_service_spec.rb60
-rw-r--r--spec/services/packages/rpm/repository_metadata/base_builder_spec.rb13
-rw-r--r--spec/services/packages/rpm/repository_metadata/build_primary_xml_spec.rb34
-rw-r--r--spec/services/packages/rpm/repository_metadata/build_repomd_xml_spec.rb20
-rw-r--r--spec/services/pages_domains/create_acme_order_service_spec.rb10
-rw-r--r--spec/services/pages_domains/create_service_spec.rb61
-rw-r--r--spec/services/pages_domains/delete_service_spec.rb47
-rw-r--r--spec/services/pages_domains/update_service_spec.rb61
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb34
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb394
-rw-r--r--spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb4
-rw-r--r--spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb370
-rw-r--r--spec/services/projects/destroy_service_spec.rb14
-rw-r--r--spec/services/projects/import_service_spec.rb9
-rw-r--r--spec/services/projects/update_repository_storage_service_spec.rb5
-rw-r--r--spec/services/projects/update_service_spec.rb53
-rw-r--r--spec/services/repositories/changelog_service_spec.rb18
-rw-r--r--spec/services/resource_events/merge_into_notes_service_spec.rb4
-rw-r--r--spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb9
-rw-r--r--spec/services/snippets/update_repository_storage_service_spec.rb7
-rw-r--r--spec/services/users/destroy_service_spec.rb75
-rw-r--r--spec/services/users/dismiss_namespace_callout_service_spec.rb24
-rw-r--r--spec/services/users/refresh_authorized_projects_service_spec.rb4
-rw-r--r--spec/services/web_hook_service_spec.rb21
-rw-r--r--spec/services/web_hooks/log_execution_service_spec.rb43
-rw-r--r--spec/services/work_items/update_service_spec.rb80
-rw-r--r--spec/spec_helper.rb15
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/capybara_slow_finder.rb32
-rw-r--r--spec/support/cross_database_modification.rb9
-rw-r--r--spec/support/database/multiple_databases.rb48
-rw-r--r--spec/support/database/prevent_cross_database_modification.rb10
-rw-r--r--spec/support/database_cleaner.rb23
-rw-r--r--spec/support/db_cleaner.rb38
-rw-r--r--spec/support/finder_collection_allowlist.yml1
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci.yml5
-rw-r--r--spec/support/helpers/exclusive_lease_helpers.rb19
-rw-r--r--spec/support/helpers/features/web_ide_spec_helpers.rb24
-rw-r--r--spec/support/helpers/git_helpers.rb4
-rw-r--r--spec/support/helpers/graphql_helpers.rb5
-rw-r--r--spec/support/helpers/html_escaped_helpers.rb31
-rw-r--r--spec/support/helpers/ldap_helpers.rb26
-rw-r--r--spec/support/helpers/login_helpers.rb10
-rw-r--r--spec/support/helpers/migrations_helpers/vulnerabilities_helper.rb40
-rw-r--r--spec/support/helpers/project_helpers.rb16
-rw-r--r--spec/support/helpers/seed_helper.rb67
-rw-r--r--spec/support/helpers/stub_configuration.rb2
-rw-r--r--spec/support/helpers/stub_experiments.rb37
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb6
-rw-r--r--spec/support/helpers/stub_object_storage.rb17
-rw-r--r--spec/support/helpers/test_env.rb24
-rw-r--r--spec/support/helpers/usage_data_helpers.rb18
-rw-r--r--spec/support/helpers/user_helpers.rb33
-rw-r--r--spec/support/matchers/event_store.rb61
-rw-r--r--spec/support/migration.rb4
-rw-r--r--spec/support/models/partitionable_check.rb46
-rw-r--r--spec/support/rspec_order_todo.yml10
-rw-r--r--spec/support/services/issuable_update_service_shared_examples.rb6
-rw-r--r--spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb13
-rw-r--r--spec/support/shared_contexts/html_safe_shared_context.rb23
-rw-r--r--spec/support/shared_contexts/lib/api/helpers/packages/dependency_proxy_helpers_shared_context.rb5
-rw-r--r--spec/support/shared_contexts/markdown_golden_master_shared_examples.rb2
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/rubocop_default_rspec_language_config_context.rb32
-rw-r--r--spec/support/shared_contexts/services/packages/rpm/xml_shared_context.rb7
-rw-r--r--spec/support/shared_contexts/views/html_safe_render_shared_context.rb39
-rw-r--r--spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb48
-rw-r--r--spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb12
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/features/access_tokens_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/content_editor_shared_examples.rb125
-rw-r--r--spec/support/shared_examples/features/deploy_token_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb4
-rw-r--r--spec/support/shared_examples/features/project_upload_files_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/runners_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/features/search/search_timeouts_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb33
-rw-r--r--spec/support/shared_examples/graphql/n_plus_one_query_examples.rb16
-rw-r--r--spec/support/shared_examples/lib/cache_helpers_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/lib/gitlab/regex_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/models/boards/listable_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/chat_integration_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb355
-rw-r--r--spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb104
-rw-r--r--spec/support/shared_examples/models/concerns/has_wiki_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/concerns/participable_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/models/concerns/timebox_shared_examples.rb118
-rw-r--r--spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/project_ci_cd_settings_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb298
-rw-r--r--spec/support/shared_examples/policies/wiki_policies_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb62
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/max_issuable_examples.rb85
-rw-r--r--spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb40
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/requests/api/hooks_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/requests/api/issuable_update_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/projects/google_cloud/google_oauth2_token_examples.rb1
-rw-r--r--spec/support/shared_examples/serializers/issuable_current_user_properties_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/services/base_rpm_service_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/services/merge_request_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/services/reviewers_change_trigger_shared_examples.rb17
-rw-r--r--spec/support/view_component.rb7
-rw-r--r--spec/support_specs/capybara_slow_finder_spec.rb78
-rw-r--r--spec/support_specs/database/multiple_databases_spec.rb22
-rw-r--r--spec/support_specs/helpers/graphql_helpers_spec.rb35
-rw-r--r--spec/support_specs/helpers/html_escaped_helpers_spec.rb29
-rw-r--r--spec/support_specs/helpers/stub_method_calls_spec.rb4
-rw-r--r--spec/support_specs/matchers/event_store_spec.rb126
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb302
-rw-r--r--spec/tasks/gitlab/db/lock_writes_rake_spec.rb20
-rw-r--r--spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb8
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb74
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb9
-rw-r--r--spec/tooling/danger/config_files_spec.rb2
-rw-r--r--spec/tooling/danger/project_helper_spec.rb9
-rw-r--r--spec/tooling/danger/specs_spec.rb166
-rw-r--r--spec/tooling/quality/test_level_spec.rb2
-rw-r--r--spec/uploaders/job_artifact_uploader_spec.rb8
-rw-r--r--spec/uploaders/object_storage/cdn/google_cdn_spec.rb22
-rw-r--r--spec/uploaders/object_storage/cdn_spec.rb44
-rw-r--r--spec/uploaders/packages/rpm/repository_file_uploader_spec.rb45
-rw-r--r--spec/views/admin/application_settings/_package_registry.html.haml_spec.rb2
-rw-r--r--spec/views/admin/application_settings/ci_cd.html.haml_spec.rb39
-rw-r--r--spec/views/admin/broadcast_messages/index.html.haml_spec.rb36
-rw-r--r--spec/views/events/event/_common.html.haml_spec.rb26
-rw-r--r--spec/views/groups/new.html.haml_spec.rb7
-rw-r--r--spec/views/layouts/_flash.html.haml_spec.rb25
-rw-r--r--spec/views/layouts/fullscreen.html.haml_spec.rb29
-rw-r--r--spec/views/layouts/header/_gitlab_version.html.haml_spec.rb6
-rw-r--r--spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb16
-rw-r--r--spec/views/projects/hooks/edit.html.haml_spec.rb2
-rw-r--r--spec/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml_spec.rb34
-rw-r--r--spec/views/registrations/welcome/show.html.haml_spec.rb1
-rw-r--r--spec/views/search/_results.html.haml_spec.rb9
-rw-r--r--spec/views/search/show.html.haml_spec.rb135
-rw-r--r--spec/views/shared/projects/_project.html.haml_spec.rb4
-rw-r--r--spec/workers/bulk_import_worker_spec.rb3
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb37
-rw-r--r--spec/workers/bulk_imports/export_request_worker_spec.rb130
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb53
-rw-r--r--spec/workers/ci/parse_secure_file_metadata_worker_spec.rb31
-rw-r--r--spec/workers/ci/pipeline_success_unlock_artifacts_worker_spec.rb21
-rw-r--r--spec/workers/concerns/gitlab/github_import/object_importer_spec.rb14
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb13
-rw-r--r--spec/workers/experiments/record_conversion_event_worker_spec.rb35
-rw-r--r--spec/workers/gitlab/github_import/attachments/import_issue_worker_spec.rb34
-rw-r--r--spec/workers/gitlab/github_import/attachments/import_merge_request_worker_spec.rb34
-rw-r--r--spec/workers/gitlab/github_import/attachments/import_note_worker_spec.rb49
-rw-r--r--spec/workers/gitlab/github_import/attachments/import_release_worker_spec.rb49
-rw-r--r--spec/workers/gitlab/github_import/import_issue_worker_spec.rb11
-rw-r--r--spec/workers/gitlab/github_import/import_release_attachments_worker_spec.rb6
-rw-r--r--spec/workers/gitlab/github_import/stage/import_attachments_worker_spec.rb60
-rw-r--r--spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb46
-rw-r--r--spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb44
-rw-r--r--spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb45
-rw-r--r--spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb71
-rw-r--r--spec/workers/integrations/create_external_cross_reference_worker_spec.rb2
-rw-r--r--spec/workers/merge_requests/delete_source_branch_worker_spec.rb42
-rw-r--r--spec/workers/namespaces/onboarding_issue_created_worker_spec.rb29
-rw-r--r--spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb17
-rw-r--r--spec/workers/namespaces/onboarding_progress_worker_spec.rb22
-rw-r--r--spec/workers/namespaces/onboarding_user_added_worker_spec.rb11
-rw-r--r--spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb2
-rw-r--r--spec/workers/onboarding/issue_created_worker_spec.rb29
-rw-r--r--spec/workers/onboarding/pipeline_created_worker_spec.rb17
-rw-r--r--spec/workers/onboarding/progress_worker_spec.rb22
-rw-r--r--spec/workers/onboarding/user_added_worker_spec.rb11
-rw-r--r--spec/workers/pages/invalidate_domain_cache_worker_spec.rb101
-rw-r--r--spec/workers/process_commit_worker_spec.rb28
-rw-r--r--spec/workers/project_cache_worker_spec.rb6
-rw-r--r--spec/workers/project_destroy_worker_spec.rb8
-rw-r--r--spec/workers/repository_check/single_repository_worker_spec.rb6
-rw-r--r--spec/workers/repository_fork_worker_spec.rb2
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb3
-rw-r--r--tooling/config/CODEOWNERS.yml1
-rw-r--r--tooling/danger/project_helper.rb2
-rw-r--r--tooling/danger/specs.rb80
-rw-r--r--tooling/graphql/docs/helper.rb4
-rw-r--r--vendor/gems/attr_encrypted/.gitignore5
-rw-r--r--vendor/gems/attr_encrypted/.gitlab-ci.yml26
-rw-r--r--vendor/gems/attr_encrypted/CHANGELOG.md98
-rw-r--r--vendor/gems/attr_encrypted/Gemfile3
-rw-r--r--vendor/gems/attr_encrypted/Gemfile.lock155
-rw-r--r--vendor/gems/attr_encrypted/MIT-LICENSE20
-rw-r--r--vendor/gems/attr_encrypted/README.md466
-rw-r--r--vendor/gems/attr_encrypted/Rakefile25
-rw-r--r--vendor/gems/attr_encrypted/attr_encrypted.gemspec52
-rw-r--r--vendor/gems/attr_encrypted/lib/attr_encrypted.rb473
-rw-r--r--vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb146
-rw-r--r--vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/data_mapper.rb24
-rw-r--r--vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/sequel.rb16
-rw-r--r--vendor/gems/attr_encrypted/lib/attr_encrypted/version.rb19
-rw-r--r--vendor/gems/attr_encrypted/test/active_record_test.rb368
-rw-r--r--vendor/gems/attr_encrypted/test/attr_encrypted_test.rb490
-rw-r--r--vendor/gems/attr_encrypted/test/compatibility_test.rb109
-rw-r--r--vendor/gems/attr_encrypted/test/data_mapper_test.rb59
-rw-r--r--vendor/gems/attr_encrypted/test/legacy_active_record_test.rb120
-rw-r--r--vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb300
-rw-r--r--vendor/gems/attr_encrypted/test/legacy_compatibility_test.rb95
-rw-r--r--vendor/gems/attr_encrypted/test/legacy_data_mapper_test.rb57
-rw-r--r--vendor/gems/attr_encrypted/test/legacy_sequel_test.rb54
-rwxr-xr-xvendor/gems/attr_encrypted/test/run.sh12
-rw-r--r--vendor/gems/attr_encrypted/test/sequel_test.rb55
-rw-r--r--vendor/gems/attr_encrypted/test/test_helper.rb63
-rw-r--r--vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum1
-rw-r--r--vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock11
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/Gemfile.lock11
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/devise-pbkdf2-encryptable.gemspec1
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/lib/devise-pbkdf2-encryptable.rb1
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/lib/devise/models/two_factor_backupable_pbkdf2.rb58
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/spec/lib/models/two_factor_backupable_pbkdf2_spec.rb100
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/spec/spec_helper.rb2
-rw-r--r--vendor/gems/microsoft_graph_mailer/README.md4
-rw-r--r--vendor/gems/omniauth-gitlab/Gemfile.lock6
-rw-r--r--vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec2
-rw-r--r--vendor/gems/omniauth-google-oauth2/.gitlab-ci.yml28
-rw-r--r--vendor/gems/omniauth-google-oauth2/CHANGELOG.md354
-rw-r--r--vendor/gems/omniauth-google-oauth2/Gemfile5
-rw-r--r--vendor/gems/omniauth-google-oauth2/Gemfile.lock87
-rw-r--r--vendor/gems/omniauth-google-oauth2/README.md368
-rw-r--r--vendor/gems/omniauth-google-oauth2/Rakefile8
-rw-r--r--vendor/gems/omniauth-google-oauth2/examples/Gemfile8
-rw-r--r--vendor/gems/omniauth-google-oauth2/examples/Gemfile.lock72
-rw-r--r--vendor/gems/omniauth-google-oauth2/examples/config.ru120
-rw-r--r--vendor/gems/omniauth-google-oauth2/examples/omni_auth.rb37
-rw-r--r--vendor/gems/omniauth-google-oauth2/lib/omniauth-google-oauth2.rb3
-rw-r--r--vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2.rb3
-rw-r--r--vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2/version.rb7
-rw-r--r--vendor/gems/omniauth-google-oauth2/lib/omniauth/strategies/google_oauth2.rb254
-rw-r--r--vendor/gems/omniauth-google-oauth2/omniauth-google-oauth2.gemspec31
-rw-r--r--vendor/gems/omniauth-google-oauth2/spec/omniauth/strategies/google_oauth2_spec.rb850
-rw-r--r--vendor/gems/omniauth-google-oauth2/spec/spec_helper.rb4
-rw-r--r--workhorse/.tool-versions2
-rw-r--r--workhorse/README.md2
-rw-r--r--workhorse/doc/architecture/channel.md16
-rw-r--r--workhorse/doc/architecture/gitlab_features.md14
-rw-r--r--workhorse/doc/channel.md14
-rw-r--r--workhorse/doc/development/new_features.md14
-rw-r--r--workhorse/doc/development/tests.md14
-rw-r--r--workhorse/doc/operations/configuration.md14
-rw-r--r--workhorse/doc/operations/install.md14
-rw-r--r--workhorse/go.mod12
-rw-r--r--workhorse/go.sum33
-rw-r--r--workhorse/internal/api/api.go1
-rw-r--r--workhorse/internal/dependencyproxy/dependencyproxy.go4
-rw-r--r--workhorse/internal/helper/httptransport/http_transport.go37
-rw-r--r--workhorse/internal/imageresizer/image_resizer.go4
-rw-r--r--workhorse/internal/queueing/queue.go23
-rw-r--r--workhorse/internal/queueing/queue_test.go8
-rw-r--r--workhorse/internal/queueing/requests.go6
-rw-r--r--workhorse/internal/queueing/requests_test.go6
-rw-r--r--workhorse/internal/redis/redis.go19
-rw-r--r--workhorse/internal/sendurl/sendurl.go4
-rw-r--r--workhorse/internal/transport/transport.go58
-rw-r--r--workhorse/internal/upload/destination/objectstore/object.go4
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_session.go13
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_session_test.go16
-rw-r--r--workhorse/internal/upstream/routes.go3
-rw-r--r--workhorse/internal/version/version.go20
-rw-r--r--workhorse/internal/version/version_test.go19
-rw-r--r--workhorse/internal/zipartifacts/open_archive.go6
-rw-r--r--workhorse/main.go5
-rw-r--r--yarn.lock797
6119 files changed, 259473 insertions, 89169 deletions
diff --git a/.gitattributes b/.gitattributes
index 720e5f62549..1f5d554ef25 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,4 @@
VERSION merge=ours
Dangerfile gitlab-language=ruby
-*.pdf filter=lfs diff=lfs merge=lfs -text
*.rb diff=ruby
workhorse/testdata/*.pdf -filter -diff -merge
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9c6b84d3931..689c05f4874 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -49,8 +49,23 @@ workflow:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "maintenance"'
variables:
CRYSTALBALL: "true"
+ NOTIFY_PIPELINE_FAILURE_CHANNEL: "master-broken"
+ # Run pipelines for ruby3 branch
+ - if: '$CI_COMMIT_BRANCH == "ruby3"'
+ variables:
+ RUBY_VERSION: "3.0"
+ NOTIFY_PIPELINE_FAILURE_CHANNEL: "f_ruby3"
+ OMNIBUS_GITLAB_RUBY3_BUILD: "true"
+ OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB_RUBY3"
+ # This work around https://gitlab.com/gitlab-org/gitlab/-/issues/332411 whichs prevents usage of dependency proxy
+ # when pipeline is triggered by a project access token.
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/'
+ variables:
+ GITLAB_DEPENDENCY_PROXY_ADDRESS: ""
# For `$CI_DEFAULT_BRANCH` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+ variables:
+ NOTIFY_PIPELINE_FAILURE_CHANNEL: "master-broken"
# For tags, create a pipeline.
- if: '$CI_COMMIT_TAG'
# If `$GITLAB_INTERNAL` isn't set, don't create a pipeline.
@@ -63,7 +78,10 @@ workflow:
variables:
PG_VERSION: "12"
- DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}.patched-golang-1.17-node-16.14-postgresql-${PG_VERSION}:rubygems-3.2-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-yarn-1.22-graphicsmagick-1.3.36"
+ DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}.patched-golang-${GO_VERSION}-node-16.14-postgresql-${PG_VERSION}:rubygems-3.2-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-yarn-1.22-graphicsmagick-1.3.36"
+ # We set $GITLAB_DEPENDENCY_PROXY to another variable (since it's set at the group level and has higher precedence than .gitlab-ci.yml)
+ # so that we can override $GITLAB_DEPENDENCY_PROXY_ADDRESS in workflow rules.
+ GITLAB_DEPENDENCY_PROXY_ADDRESS: "${GITLAB_DEPENDENCY_PROXY}"
RAILS_ENV: "test"
NODE_ENV: "test"
BUNDLE_WITHOUT: "production:development"
@@ -80,6 +98,7 @@ variables:
CHROME_VERSION: "103"
DOCKER_VERSION: "20.10.14"
RUBY_VERSION: "2.7"
+ GO_VERSION: "1.18"
TMP_TEST_FOLDER: "${CI_PROJECT_DIR}/tmp/tests"
GITLAB_WORKHORSE_FOLDER: "gitlab-workhorse"
@@ -92,7 +111,9 @@ variables:
FRONTEND_FIXTURES_MAPPING_PATH: crystalball/frontend_fixtures_mapping.json
RSPEC_CHANGED_FILES_PATH: rspec/changed_files.txt
RSPEC_MATCHING_TESTS_PATH: rspec/matching_tests.txt
+ RSPEC_MATCHING_TESTS_FOSS_PATH: rspec/matching_tests-foss.txt
RSPEC_LAST_RUN_RESULTS_FILE: rspec/rspec_last_run_results.txt
+ RSPEC_FOSS_IMPACT_PIPELINE_YML: rspec-foss-impact-pipeline.yml
JUNIT_RESULT_FILE: rspec/junit_rspec.xml
JUNIT_RETRY_FILE: rspec/junit_rspec-retry.xml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 03fcfc4dd53..1ea65fe4de5 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -2,11 +2,11 @@
# project here: https://gitlab.com/gitlab-org/gitlab/-/project_members
# As described in https://docs.gitlab.com/ee/user/project/code_owners.html
-* @gitlab-org/maintainers/rails-backend @gitlab-org/maintainers/frontend @gitlab-org/maintainers/database @gl-quality/qe-maintainers @gitlab-org/delivery @gitlab-org/maintainers/cicd-templates @kwiebers @nolith @jacobvosmaer-gitlab
+* @gitlab-org/maintainers/rails-backend @gitlab-org/maintainers/frontend @gitlab-org/maintainers/database @gl-quality/qe-maintainers @gitlab-org/delivery @gitlab-org/maintainers/cicd-templates @kwiebers @nolith @jacobvosmaer-gitlab @gitlab-org/tw-leadership
-CODEOWNERS @clefelhocz1 @timzallmann @cdu1 @wayne @dsatcher @sgoldstein @jeromezng @stanhu @susantacker @dianalogan @kpaizee @sselhorn
-docs/CODEOWNERS @clefelhocz1 @timzallmann @cdu1 @wayne @dsatcher @sgoldstein @jeromezng @stanhu @susantacker @dianalogan @kpaizee @sselhorn
-.gitlab/CODEOWNERS @clefelhocz1 @timzallmann @cdu1 @wayne @dsatcher @sgoldstein @jeromezng @stanhu @susantacker @dianalogan @kpaizee @sselhorn
+CODEOWNERS @gitlab-org/development-leaders @gitlab-org/tw-leadership
+docs/CODEOWNERS @gitlab-org/development-leaders @gitlab-org/tw-leadership
+.gitlab/CODEOWNERS @gitlab-org/development-leaders @gitlab-org/tw-leadership
## Allows release tooling to update the Gitaly Version
GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend @gitlab-org/delivery
@@ -20,6 +20,14 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
/data/deprecations/*.yml
/data/removals/*.yml
+## Technical writing files that do need approval
+/data/deprecations/templates/ @marcel.amirault @gitlab-org/tw-leadership @sarahgerman
+/data/removals/templates/ @marcel.amirault @gitlab-org/tw-leadership @sarahgerman
+.markdownlint.yml @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/doc/.markdownlint/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/doc/.vale/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/lib/tasks/gitlab/tw/codeowners.rake @aqualls @gitlab-org/tw-leadership
+
^[Backend]
*.rb @gitlab-org/maintainers/rails-backend
*.rake @gitlab-org/maintainers/rails-backend
@@ -140,17 +148,18 @@ Dangerfile @gl-quality/eng-prod
/ee/app/workers/clear_shared_runners_minutes_worker.rb @gitlab-org/maintainers/cicd-verify
/ee/lib/**/ci/ @gitlab-org/maintainers/cicd-verify
/ee/lib/ee/api/entities/merge_train.rb @gitlab-org/maintainers/cicd-verify
-/**/javascripts/jobs/ @pburdette @jivanvl
-/**/javascripts/pipelines/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
-/app/assets/javascripts/pipeline_new/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
-/app/assets/javascripts/ci_lint/ @f_caplette @bsandlin @mgandres
-/app/assets/javascripts/ci_variable_list/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
-/app/assets/javascripts/pipeline_schedules/ @pburdette @jivanvl
-/app/assets/javascripts/pipeline_editor/ @f_caplette @bsandlin @mgandres
-/ee/app/assets/javascripts/ci_minutes_usage/ @pburdette @jivanvl
-/ee/app/assets/javascripts/usage_quotas/ci_minutes_usage/ @pburdette @jivanvl
-/ee/app/assets/javascripts/usage_quotas/pipelines/ @pburdette @jivanvl
-/ee/app/assets/javascripts/reports/ @mfluharty
+/**/javascripts/jobs/ @gitlab-org/ci-cd/verify/frontend
+/**/javascripts/pipelines/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/pipeline_new/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/ci_lint/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/ci_variable_list/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/pipeline_schedules/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/pipeline_editor/ @gitlab-org/ci-cd/verify/frontend
+/app/assets/javascripts/runner/ @gitlab-org/ci-cd/verify/frontend
+/ee/app/assets/javascripts/ci_minutes_usage/ @gitlab-org/ci-cd/verify/frontend
+/ee/app/assets/javascripts/usage_quotas/ci_minutes_usage/ @gitlab-org/ci-cd/verify/frontend
+/ee/app/assets/javascripts/usage_quotas/pipelines/ @gitlab-org/ci-cd/verify/frontend
+/ee/app/assets/javascripts/reports/ @gitlab-org/ci-cd/verify/frontend
^[Templates]
/lib/gitlab/ci/templates/ @gitlab-org/maintainers/cicd-templates
@@ -333,19 +342,18 @@ ee/lib/ee/gitlab/checks/** @proglottis @toon @zj-gitlab
lib/gitlab/checks/** @proglottis @toon @zj-gitlab
^[Documentation Directories]
-.markdownlint.yml @marcel.amirault @eread @aqualls @dianalogan @kpaizee
/doc/ @gl-docsteam
-/doc/.markdownlint/ @marcel.amirault @eread @aqualls @dianalogan @kpaizee
-/doc/.vale/ @marcel.amirault @eread @aqualls @dianalogan @kpaizee
+/data/deprecations/ @gl-docsteam
+/data/removals/ @gl-docsteam
^[Documentation Pages]
/doc/administration/application_settings_cache.md @sselhorn
/doc/administration/audit_event_streaming.md @eread
/doc/administration/audit_events.md @eread
/doc/administration/audit_reports.md @eread
-/doc/administration/auditor_users.md @eread
-/doc/administration/auth/ @eread
-/doc/administration/auth/ldap/ @eread
+/doc/administration/auditor_users.md @jglassman1
+/doc/administration/auth/ @jglassman1
+/doc/administration/auth/ldap/ @jglassman1
/doc/administration/cicd.md @marcel.amirault
/doc/administration/clusters/ @phillipwells
/doc/administration/compliance.md @eread
@@ -374,7 +382,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/integration/kroki.md @msedlakjakubowski
/doc/administration/integration/mailgun.md @msedlakjakubowski
/doc/administration/integration/plantuml.md @aqualls
-/doc/administration/integration/terminal.md @ashrafkhamis
+/doc/administration/integration/terminal.md @phillipwells
/doc/administration/invalidate_markdown_cache.md @msedlakjakubowski
/doc/administration/issue_closing_pattern.md @aqualls
/doc/administration/job_artifacts.md @marcel.amirault
@@ -382,11 +390,10 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/lfs/ @aqualls
/doc/administration/libravatar.md @axil
/doc/administration/load_balancer.md @axil
+/doc/administration/logs/ @axil
/doc/administration/logs/index.md @msedlakjakubowski
-/doc/administration/logs/log_parsing.md @axil
-/doc/administration/logs/tracing_correlation_id.md @axil
/doc/administration/maintenance_mode/ @axil
-/doc/administration/merge_request_diffs.md @aqualls
+/doc/administration/merge_request_diffs.md @ashrafkhamis
/doc/administration/monitoring/ @msedlakjakubowski
/doc/administration/monitoring/gitlab_self_monitoring_project/ @msedlakjakubowski
/doc/administration/monitoring/ip_allowlist.md @sselhorn
@@ -401,12 +408,13 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/operations/moving_repositories.md @eread
/doc/administration/package_information/ @axil
/doc/administration/packages/ @claytoncornell
-/doc/administration/pages/ @aqualls
+/doc/administration/pages/ @ashrafkhamis
/doc/administration/polling.md @axil
/doc/administration/postgresql/ @aqualls
/doc/administration/raketasks/ @axil
-/doc/administration/raketasks/ldap.md @eread
+/doc/administration/raketasks/ldap.md @jglassman1
/doc/administration/raketasks/praefect.md @eread
+/doc/administration/raketasks/uploads/ @axil
/doc/administration/read_only_gitlab.md @axil
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
@@ -418,25 +426,26 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/restart_gitlab.md @axil
/doc/administration/server_hooks.md @eread
/doc/administration/sidekiq/ @axil
+/doc/administration/sidekiq/sidekiq_memory_killer.md @sselhorn
/doc/administration/smime_signing_email.md @axil
-/doc/administration/snippets/ @aqualls
-/doc/administration/static_objects_external_storage.md @aqualls
+/doc/administration/snippets/ @ashrafkhamis
+/doc/administration/static_objects_external_storage.md @ashrafkhamis
/doc/administration/system_hooks.md @ashrafkhamis
/doc/administration/terraform_state.md @phillipwells
/doc/administration/timezone.md @axil
/doc/administration/troubleshooting/ @axil
/doc/administration/troubleshooting/postgresql.md @aqualls
/doc/administration/uploads.md @axil
-/doc/administration/user_settings.md @eread
-/doc/administration/wikis/ @aqualls
-/doc/api/access_requests.md @eread
+/doc/administration/user_settings.md @jglassman1
+/doc/administration/wikis/ @ashrafkhamis
+/doc/api/access_requests.md @jglassman1
/doc/api/admin_sidekiq_queues.md @axil
/doc/api/alert_management_alerts.md @msedlakjakubowski
/doc/api/api_resources.md @ashrafkhamis
-/doc/api/appearance.md @eread
-/doc/api/applications.md @eread
+/doc/api/appearance.md @jglassman1
+/doc/api/applications.md @jglassman1
/doc/api/audit_events.md @eread
-/doc/api/avatar.md @eread
+/doc/api/avatar.md @jglassman1
/doc/api/award_emoji.md @msedlakjakubowski
/doc/api/boards.md @msedlakjakubowski
/doc/api/branches.md @aqualls
@@ -445,7 +454,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/cluster_agents.md @phillipwells
/doc/api/commits.md @aqualls
/doc/api/container_registry.md @claytoncornell
-/doc/api/custom_attributes.md @ashrafkhamis
+/doc/api/custom_attributes.md @msedlakjakubowski
/doc/api/dependencies.md @rdickenson
/doc/api/dependency_proxy.md @claytoncornell
/doc/api/deploy_keys.md @rdickenson
@@ -466,10 +475,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/features.md @rdickenson
/doc/api/freeze_periods.md @rdickenson
/doc/api/geo_nodes.md @axil
-/doc/api/graphql/ @ashrafkhamis
+/doc/api/graphql/audit_report.md @eread
/doc/api/graphql/custom_emoji.md @msedlakjakubowski
+/doc/api/graphql/getting_started.md @ashrafkhamis
+/doc/api/graphql/index.md @ashrafkhamis
+/doc/api/graphql/reference/ @ashrafkhamis
+/doc/api/graphql/removed_items.md @ashrafkhamis
/doc/api/graphql/sample_issue_boards.md @msedlakjakubowski
-/doc/api/group_access_tokens.md @eread
+/doc/api/graphql/users_example.md @jglassman1
+/doc/api/group_access_tokens.md @jglassman1
/doc/api/group_activity_analytics.md @fneill
/doc/api/group_badges.md @fneill
/doc/api/group_boards.md @msedlakjakubowski
@@ -482,8 +496,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/group_protected_environments.md @rdickenson
/doc/api/group_relations_export.md @eread
/doc/api/group_releases.md @rdickenson
-/doc/api/group_repository_storage_moves.md @aqualls
-/doc/api/group_wikis.md @aqualls
+/doc/api/group_repository_storage_moves.md @ashrafkhamis
+/doc/api/group_wikis.md @ashrafkhamis
/doc/api/groups.md @fneill
/doc/api/import.md @eread
/doc/api/index.md @ashrafkhamis
@@ -504,30 +518,31 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/lint.md @marcel.amirault
/doc/api/managed_licenses.md @fneill
/doc/api/markdown.md @msedlakjakubowski
-/doc/api/members.md @eread
+/doc/api/members.md @jglassman1
/doc/api/merge_request_approvals.md @aqualls
/doc/api/merge_request_context_commits.md @aqualls
/doc/api/merge_requests.md @aqualls
/doc/api/merge_trains.md @marcel.amirault
-/doc/api/metadata.md @ashrafkhamis
+/doc/api/metadata.md @phillipwells
/doc/api/metrics_dashboard_annotations.md @msedlakjakubowski
/doc/api/metrics_user_starred_dashboards.md @msedlakjakubowski
/doc/api/milestones.md @msedlakjakubowski
-/doc/api/namespaces.md @eread
+/doc/api/namespaces.md @jglassman1
/doc/api/notes.md @msedlakjakubowski
/doc/api/notification_settings.md @msedlakjakubowski
-/doc/api/oauth2.md @eread
+/doc/api/oauth2.md @jglassman1
/doc/api/openapi/ @ashrafkhamis
/doc/api/packages.md @claytoncornell
/doc/api/packages/ @claytoncornell
-/doc/api/pages.md @aqualls
-/doc/api/pages_domains.md @aqualls
+/doc/api/pages.md @ashrafkhamis
+/doc/api/pages_domains.md @ashrafkhamis
/doc/api/personal_access_tokens.md @eread
/doc/api/pipeline_schedules.md @marcel.amirault
/doc/api/pipeline_triggers.md @marcel.amirault
/doc/api/pipelines.md @marcel.amirault
-/doc/api/plan_limits.md @eread
-/doc/api/project_access_tokens.md @eread
+/doc/api/plan_limits.md @jglassman1
+/doc/api/product_analytics.md @lciutacu
+/doc/api/project_access_tokens.md @jglassman1
/doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls
/doc/api/project_clusters.md @phillipwells
@@ -535,7 +550,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/project_level_variables.md @marcel.amirault
/doc/api/project_relations_export.md @eread
/doc/api/project_repository_storage_moves.md @eread
-/doc/api/project_snippets.md @aqualls
+/doc/api/project_snippets.md @ashrafkhamis
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
@@ -555,14 +570,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/resource_state_events.md @msedlakjakubowski
/doc/api/resource_weight_events.md @msedlakjakubowski
/doc/api/runners.md @sselhorn
-/doc/api/scim.md @eread
-/doc/api/search.md @aqualls
+/doc/api/saml.md @jglassman1
+/doc/api/scim.md @jglassman1
+/doc/api/search.md @ashrafkhamis
/doc/api/secure_files.md @marcel.amirault
-/doc/api/settings.md @eread
+/doc/api/settings.md @jglassman1
/doc/api/sidekiq_metrics.md @axil
-/doc/api/snippet_repository_storage_moves.md @aqualls
-/doc/api/snippets.md @aqualls
-/doc/api/statistics.md @eread
+/doc/api/snippet_repository_storage_moves.md @ashrafkhamis
+/doc/api/snippets.md @ashrafkhamis
+/doc/api/statistics.md @jglassman1
/doc/api/status_checks.md @eread
/doc/api/suggestions.md @aqualls
/doc/api/system_hooks.md @ashrafkhamis
@@ -574,17 +590,19 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/todos.md @msedlakjakubowski
/doc/api/topics.md @fneill
/doc/api/usage_data.md @claytoncornell
-/doc/api/users.md @eread
-/doc/api/version.md @ashrafkhamis
+/doc/api/users.md @jglassman1
+/doc/api/version.md @phillipwells
/doc/api/visual_review_discussions.md @marcel.amirault
/doc/api/vulnerabilities.md @claytoncornell
/doc/api/vulnerability_exports.md @claytoncornell
/doc/api/vulnerability_findings.md @claytoncornell
-/doc/api/wikis.md @aqualls
+/doc/api/wikis.md @ashrafkhamis
+/doc/architecture/blueprints/ci_pipeline_components/ @marcel.amirault
/doc/architecture/blueprints/container_registry_metadata_database/ @claytoncornell
/doc/architecture/blueprints/database/scalability/patterns/ @aqualls
/doc/architecture/blueprints/database_scaling/ @aqualls
/doc/architecture/blueprints/gitlab_to_kubernetes_communication/ @phillipwells
+/doc/architecture/blueprints/work_items/ @msedlakjakubowski
/doc/ci/ @marcel.amirault
/doc/ci/caching/ @marcel.amirault
/doc/ci/chatops/ @phillipwells
@@ -596,17 +614,14 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/ci/cloud_services/azure/ @marcel.amirault
/doc/ci/cloud_services/google_cloud/ @marcel.amirault
/doc/ci/directed_acyclic_graph/ @marcel.amirault
-/doc/ci/docker/index.md @marcel.amirault
-/doc/ci/docker/using_docker_build.md @marcel.amirault
+/doc/ci/docker/ @marcel.amirault
/doc/ci/docker/using_docker_images.md @sselhorn
-/doc/ci/docker/using_kaniko.md @marcel.amirault
/doc/ci/environments/ @rdickenson
+/doc/ci/examples/ @marcel.amirault
/doc/ci/examples/authenticating-with-hashicorp-vault/ @marcel.amirault
/doc/ci/examples/deployment/ @rdickenson
/doc/ci/examples/end_to_end_testing_webdriverio/ @marcel.amirault
-/doc/ci/examples/index.md @marcel.amirault
/doc/ci/examples/laravel_with_gitlab_and_envoy/ @marcel.amirault
-/doc/ci/examples/php.md @marcel.amirault
/doc/ci/examples/semantic-release.md @claytoncornell
/doc/ci/interactive_web_terminal/ @sselhorn
/doc/ci/introduction/ @marcel.amirault
@@ -640,7 +655,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/build_test_package.md @axil
/doc/development/bulk_import.md @eread
/doc/development/cached_queries.md @sselhorn
-/doc/development/cascading_settings.md @eread
+/doc/development/cascading_settings.md @jglassman1
/doc/development/chatops_on_gitlabcom.md @phillipwells
/doc/development/cicd/ @marcel.amirault
/doc/development/code_intelligence/ @aqualls
@@ -659,11 +674,12 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/elasticsearch.md @ashrafkhamis
/doc/development/experiment_guide/ @phillipwells
/doc/development/export_csv.md @eread
-/doc/development/fe_guide/content_editor.md @aqualls
+/doc/development/fe_guide/content_editor.md @ashrafkhamis
+/doc/development/fe_guide/customizable_dashboards.md @lciutacu
/doc/development/fe_guide/dark_mode.md @sselhorn
/doc/development/fe_guide/graphql.md @sselhorn
/doc/development/fe_guide/merge_request_widget_extensions.md @aqualls
-/doc/development/fe_guide/source_editor.md @aqualls
+/doc/development/fe_guide/source_editor.md @ashrafkhamis
/doc/development/fe_guide/view_component.md @rdickenson
/doc/development/feature_categorization/ @sselhorn
/doc/development/feature_development.md @sselhorn
@@ -673,19 +689,19 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/geo/ @axil
/doc/development/git_object_deduplication.md @eread
/doc/development/gitaly.md @eread
-/doc/development/gitlab_flavored_markdown/ @aqualls
-/doc/development/gitlab_flavored_markdown/specification_guide/ @aqualls
+/doc/development/gitlab_flavored_markdown/ @ashrafkhamis
+/doc/development/gitlab_flavored_markdown/specification_guide/ @ashrafkhamis
+/doc/development/graphql_guide/ @ashrafkhamis
/doc/development/graphql_guide/batchloader.md @aqualls
-/doc/development/graphql_guide/graphql_pro.md @ashrafkhamis
-/doc/development/graphql_guide/index.md @ashrafkhamis
-/doc/development/graphql_guide/monitoring.md @ashrafkhamis
-/doc/development/graphql_guide/pagination.md @ashrafkhamis
/doc/development/i18n/ @eread
/doc/development/image_scaling.md @sselhorn
/doc/development/import_export.md @eread
/doc/development/index.md @sselhorn
-/doc/development/integrations/ @ashrafkhamis
-/doc/development/integrations/secure.md @claytoncornell
+/doc/development/integrations/codesandbox.md @sselhorn
+/doc/development/integrations/index.md @ashrafkhamis
+/doc/development/integrations/jenkins.md @ashrafkhamis
+/doc/development/integrations/jira_connect.md @ashrafkhamis
+/doc/development/integrations/secure.md @rdickenson
/doc/development/integrations/secure_partner_integration.md @rdickenson
/doc/development/internal_api/ @aqualls
/doc/development/internal_users.md @sselhorn
@@ -698,9 +714,9 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/merge_request_concepts/ @aqualls
/doc/development/omnibus.md @axil
/doc/development/packages/ @claytoncornell
-/doc/development/pages/ @aqualls
-/doc/development/permissions.md @eread
-/doc/development/policies.md @eread
+/doc/development/pages/ @ashrafkhamis
+/doc/development/permissions.md @jglassman1
+/doc/development/policies.md @jglassman1
/doc/development/product_qualified_lead_guide/ @phillipwells
/doc/development/project_templates.md @fneill
/doc/development/prometheus_metrics.md @msedlakjakubowski
@@ -709,14 +725,14 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/secure_coding_guidelines.md @sselhorn
/doc/development/service_ping/ @claytoncornell
/doc/development/snowplow/ @claytoncornell
-/doc/development/spam_protection_and_captcha/ @eread
+/doc/development/spam_protection_and_captcha/ @jglassman1
/doc/development/sql.md @aqualls
/doc/development/testing_guide/ @sselhorn
/doc/development/testing_guide/contract/ @sselhorn
/doc/development/testing_guide/end_to_end/ @sselhorn
/doc/development/value_stream_analytics.md @fneill
/doc/development/value_stream_analytics/ @fneill
-/doc/development/wikis.md @aqualls
+/doc/development/wikis.md @ashrafkhamis
/doc/development/work_items.md @msedlakjakubowski
/doc/development/work_items_widgets.md @msedlakjakubowski
/doc/development/workhorse/ @aqualls
@@ -727,43 +743,25 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/install/ @axil
/doc/install/aws/ @axil
/doc/install/azure/ @axil
-/doc/install/cloud_native/ @axil
/doc/install/google_cloud_platform/ @axil
+/doc/install/migrate/ @axil
/doc/install/openshift_and_gitlab/ @axil
+/doc/integration/ @jglassman1
/doc/integration/advanced_search/ @ashrafkhamis
-/doc/integration/akismet.md @ashrafkhamis
-/doc/integration/alicloud.md @eread
+/doc/integration/akismet.md @phillipwells
/doc/integration/arkose.md @phillipwells
-/doc/integration/auth0.md @eread
-/doc/integration/azure.md @eread
-/doc/integration/bitbucket.md @eread
-/doc/integration/cas.md @eread
/doc/integration/datadog.md @ashrafkhamis
-/doc/integration/ding_talk.md @eread
/doc/integration/external-issue-tracker.md @ashrafkhamis
-/doc/integration/facebook.md @eread
-/doc/integration/github.md @eread
-/doc/integration/gitlab.md @eread
-/doc/integration/gitpod.md @aqualls
+/doc/integration/gitpod.md @ashrafkhamis
/doc/integration/gmail_action_buttons_for_gitlab.md @ashrafkhamis
-/doc/integration/google.md @eread
/doc/integration/index.md @ashrafkhamis
/doc/integration/jenkins.md @ashrafkhamis
/doc/integration/jira/ @ashrafkhamis
-/doc/integration/kerberos.md @eread
/doc/integration/mattermost/ @axil
-/doc/integration/oauth2_generic.md @eread
-/doc/integration/oauth_provider.md @eread
-/doc/integration/omniauth.md @eread
-/doc/integration/openid_connect_provider.md @eread
-/doc/integration/recaptcha.md @ashrafkhamis
-/doc/integration/salesforce.md @eread
-/doc/integration/saml.md @eread
/doc/integration/security_partners/ @rdickenson
/doc/integration/slash_commands.md @ashrafkhamis
/doc/integration/sourcegraph.md @aqualls
/doc/integration/trello_power_up.md @ashrafkhamis
-/doc/integration/twitter.md @eread
/doc/integration/vault.md @phillipwells
/doc/operations/error_tracking.md msedlakjakubowski
/doc/operations/feature_flags.md @rdickenson
@@ -771,22 +769,23 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/operations/index.md @msedlakjakubowski
/doc/operations/metrics/ @msedlakjakubowski
/doc/operations/metrics/dashboards/ @msedlakjakubowski
-/doc/operations/product_analytics.md @claytoncornell
+/doc/operations/product_analytics.md @lciutacu
/doc/operations/tracing.md @msedlakjakubowski
/doc/policy/ @axil
/doc/raketasks/ @axil
/doc/raketasks/generate_sample_prometheus_data.md @msedlakjakubowski
-/doc/raketasks/migrate_snippets.md @aqualls
+/doc/raketasks/migrate_snippets.md @ashrafkhamis
/doc/raketasks/spdx.md @rdickenson
/doc/raketasks/x509_signatures.md @aqualls
-/doc/security/ @eread
+/doc/security/ @jglassman1
/doc/subscriptions/ @fneill
/doc/subscriptions/gitlab_com/ @fneill
/doc/subscriptions/gitlab_dedicated/ @axil
/doc/subscriptions/self_managed/ @fneill
-/doc/topics/authentication/ @eread
+/doc/topics/authentication/ @jglassman1
/doc/topics/autodevops/ @phillipwells
/doc/topics/autodevops/cloud_deployments/ @phillipwells
+/doc/topics/awesome_co.md @rdickenson
/doc/topics/git/ @aqualls
/doc/topics/git/how_to_install_git/ @aqualls
/doc/topics/git/lfs/ @aqualls
@@ -801,7 +800,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/update/upgrading_postgresql_using_slony.md @aqualls
/doc/user/admin_area/analytics/ @fneill
/doc/user/admin_area/broadcast_messages.md @phillipwells
-/doc/user/admin_area/credentials_inventory.md @eread
+/doc/user/admin_area/credentials_inventory.md @jglassman1
/doc/user/admin_area/custom_project_templates.md @eread
/doc/user/admin_area/diff_limits.md @aqualls
/doc/user/admin_area/geo_sites.md @axil
@@ -809,17 +808,17 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/admin_area/license.md @fneill
/doc/user/admin_area/license_file.md @fneill
/doc/user/admin_area/merge_requests_approvals.md @aqualls
-/doc/user/admin_area/moderate_users.md @eread
+/doc/user/admin_area/moderate_users.md @jglassman1
/doc/user/admin_area/monitoring/background_migrations.md @aqualls
/doc/user/admin_area/monitoring/health_check.md @msedlakjakubowski
/doc/user/admin_area/reporting/git_abuse_rate_limit.md @phillipwells
/doc/user/admin_area/reporting/spamcheck.md @axil
-/doc/user/admin_area/review_abuse_reports.md @eread
+/doc/user/admin_area/review_abuse_reports.md @jglassman1
/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
/doc/user/admin_area/settings/continuous_integration.md @marcel.amirault
/doc/user/admin_area/settings/deprecated_api_rate_limits.md @aqualls
/doc/user/admin_area/settings/email.md @msedlakjakubowski
-/doc/user/admin_area/settings/external_authorization.md @eread
+/doc/user/admin_area/settings/external_authorization.md @jglassman1
/doc/user/admin_area/settings/files_api_rate_limits.md @aqualls
/doc/user/admin_area/settings/git_lfs_rate_limits.md @aqualls
/doc/user/admin_area/settings/gitaly_timeouts.md @eread
@@ -833,15 +832,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @msedlakjakubowski
/doc/user/admin_area/settings/rate_limit_on_notes_creation.md @msedlakjakubowski
/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md @marcel.amirault
-/doc/user/admin_area/settings/rate_limit_on_users_api.md @eread
+/doc/user/admin_area/settings/rate_limit_on_users_api.md @jglassman1
/doc/user/admin_area/settings/third_party_offers.md @fneill
/doc/user/admin_area/settings/usage_statistics.md @claytoncornell
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
-/doc/user/analytics/ci_cd_analytics.md @rdickenson
/doc/user/analytics/ @fneill
+/doc/user/analytics/ci_cd_analytics.md @rdickenson
/doc/user/application_security/api_fuzzing/ @rdickenson
/doc/user/application_security/configuration/ @rdickenson
-/doc/user/application_security/container_scanning/ @claytoncornell
+/doc/user/application_security/container_scanning/ @rdickenson
/doc/user/application_security/coverage_fuzzing/ @rdickenson
/doc/user/application_security/cve_id_request.md @claytoncornell
/doc/user/application_security/dast/ @rdickenson
@@ -874,23 +873,22 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/discussions/ @aqualls
/doc/user/feature_flags.md @sselhorn
/doc/user/free_user_limit.md @phillipwells
-/doc/user/group/access_and_permissions.md @fneill
+/doc/user/group/ @fneill
/doc/user/group/clusters/ @phillipwells
/doc/user/group/contribution_analytics/ @fneill
/doc/user/group/custom_project_templates.md @eread
/doc/user/group/devops_adoption/ @fneill
/doc/user/group/epics/ @msedlakjakubowski
/doc/user/group/import/ @eread
-/doc/user/group/index.md @fneill
/doc/user/group/insights/ @fneill
/doc/user/group/issues_analytics/ @msedlakjakubowski
/doc/user/group/iterations/ @msedlakjakubowski
-/doc/user/group/manage.md @fneill
/doc/user/group/planning_hierarchy/ @msedlakjakubowski
/doc/user/group/repositories_analytics/ @marcel.amirault
/doc/user/group/roadmap/ @msedlakjakubowski
-/doc/user/group/saml_sso/ @eread
-/doc/user/group/settings/ @eread
+/doc/user/group/saml_sso/ @jglassman1
+/doc/user/group/settings/group_access_tokens.md @jglassman1
+/doc/user/group/settings/import_export.md @eread
/doc/user/group/subgroups/ @fneill
/doc/user/group/value_stream_analytics/ @fneill
/doc/user/infrastructure/ @phillipwells
@@ -898,10 +896,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/infrastructure/clusters/connect/ @phillipwells
/doc/user/infrastructure/clusters/deploy/ @phillipwells
/doc/user/infrastructure/clusters/manage/ @phillipwells
-/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md @phillipwells
-/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md @phillipwells
+/doc/user/infrastructure/clusters/manage/management_project_applications/ @phillipwells
/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md @sselhorn
-/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md @phillipwells
/doc/user/infrastructure/iac/ @phillipwells
/doc/user/markdown.md @aqualls
/doc/user/namespace/ @fneill
@@ -913,6 +909,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/packages/dependency_proxy/ @claytoncornell
/doc/user/packages/generic_packages/ @claytoncornell
/doc/user/packages/go_proxy/ @claytoncornell
+/doc/user/packages/harbor_container_registry/ @claytoncornell
/doc/user/packages/helm_repository/ @claytoncornell
/doc/user/packages/infrastructure_registry/ @phillipwells
/doc/user/packages/maven_repository/ @claytoncornell
@@ -923,68 +920,67 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/packages/rubygems_registry/ @claytoncornell
/doc/user/packages/terraform_module_registry/ @phillipwells
/doc/user/packages/workflows/ @claytoncornell
-/doc/user/permissions.md @eread
-/doc/user/profile/account/ @eread
-/doc/user/profile/index.md @eread
+/doc/user/permissions.md @jglassman1
+/doc/user/profile/ @jglassman1
+/doc/user/profile/account/ @jglassman1
/doc/user/profile/notifications.md @msedlakjakubowski
-/doc/user/profile/personal_access_tokens.md @eread
-/doc/user/profile/unknown_sign_in_notification.md @eread
-/doc/user/project/autocomplete_characters.md @aqualls
-/doc/user/project/badges.md @aqualls
+/doc/user/project/ @aqualls
/doc/user/project/clusters/ @phillipwells
/doc/user/project/clusters/runbooks/ @phillipwells
-/doc/user/project/code_intelligence.md @aqualls
-/doc/user/project/code_owners.md @aqualls
/doc/user/project/deploy_boards.md @rdickenson
/doc/user/project/deploy_keys/ @rdickenson
/doc/user/project/deploy_tokens/ @rdickenson
/doc/user/project/description_templates.md @msedlakjakubowski
-/doc/user/project/file_lock.md @aqualls
-/doc/user/project/git_attributes.md @aqualls
-/doc/user/project/highlighting.md @aqualls
/doc/user/project/import/ @eread
/doc/user/project/import/jira.md @msedlakjakubowski
/doc/user/project/index.md @fneill
+/doc/user/project/insights/ @fneill
/doc/user/project/integrations/ @ashrafkhamis
/doc/user/project/integrations/prometheus.md @msedlakjakubowski
/doc/user/project/integrations/prometheus_library/ @msedlakjakubowski
/doc/user/project/issue_board.md @msedlakjakubowski
/doc/user/project/issues/ @msedlakjakubowski
/doc/user/project/issues/csv_import.md @eread
+/doc/user/project/labels.md @msedlakjakubowski
/doc/user/project/members/ @fneill
/doc/user/project/merge_requests/ @aqualls
/doc/user/project/merge_requests/approvals/ @aqualls
/doc/user/project/merge_requests/csv_export.md @eread
+/doc/user/project/merge_requests/methods/ @aqualls
+/doc/user/project/merge_requests/reviews/ @aqualls
/doc/user/project/merge_requests/status_checks.md @eread
/doc/user/project/milestones/ @msedlakjakubowski
-/doc/user/project/pages/ @aqualls
-/doc/user/project/pages/custom_domains_ssl_tls_certification/ @aqualls
-/doc/user/project/pages/getting_started/ @aqualls
-/doc/user/project/protected_branches.md @aqualls
-/doc/user/project/protected_tags.md @aqualls
-/doc/user/project/push_options.md @aqualls
+/doc/user/project/pages/ @ashrafkhamis
+/doc/user/project/pages/custom_domains_ssl_tls_certification/ @ashrafkhamis
+/doc/user/project/pages/getting_started/ @ashrafkhamis
/doc/user/project/quick_actions.md @msedlakjakubowski
/doc/user/project/releases/ @rdickenson
/doc/user/project/repository/ @aqualls
/doc/user/project/repository/branches/ @aqualls
+/doc/user/project/repository/file_finder.md @ashrafkhamis
+/doc/user/project/repository/gpg_signed_commits/ @aqualls
+/doc/user/project/repository/jupyter_notebooks/ @aqualls
/doc/user/project/repository/managing_large_repositories.md @axil
+/doc/user/project/repository/mirror/ @aqualls
/doc/user/project/repository/reducing_the_repo_size_using_git.md @eread
+/doc/user/project/repository/web_editor.md @ashrafkhamis
+/doc/user/project/repository/x509_signed_commits/ @aqualls
/doc/user/project/requirements/ @msedlakjakubowski
/doc/user/project/service_desk.md @msedlakjakubowski
/doc/user/project/settings/import_export.md @eread
/doc/user/project/settings/index.md @fneill
-/doc/user/project/settings/project_access_tokens.md @eread
+/doc/user/project/settings/project_access_tokens.md @jglassman1
/doc/user/project/time_tracking.md @msedlakjakubowski
-/doc/user/project/web_ide/ @aqualls
-/doc/user/project/wiki/ @aqualls
+/doc/user/project/web_ide/ @ashrafkhamis
+/doc/user/project/wiki/ @ashrafkhamis
/doc/user/project/working_with_projects.md @fneill
/doc/user/public_access.md @fneill
/doc/user/reserved_names.md @fneill
/doc/user/search/ @ashrafkhamis
/doc/user/search/global_search/ @ashrafkhamis
-/doc/user/shortcuts.md @aqualls
-/doc/user/snippets.md @aqualls
-/doc/user/ssh.md @eread
+/doc/user/shortcuts.md @ashrafkhamis
+/doc/user/snippets.md @ashrafkhamis
+/doc/user/ssh.md @jglassman1
/doc/user/tasks.md @msedlakjakubowski
/doc/user/todos.md @msedlakjakubowski
/doc/user/usage_quotas.md @fneill
diff --git a/.gitlab/ci/_skip.yml b/.gitlab/ci/_skip.yml
index 27a3ff5b836..9d3745cf2f1 100644
--- a/.gitlab/ci/_skip.yml
+++ b/.gitlab/ci/_skip.yml
@@ -1,7 +1,7 @@
# no-op pipeline template for skipping whole child pipeline execution
no-op:
- image: ${GITLAB_DEPENDENCY_PROXY}alpine:latest
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:latest
stage: test
variables:
GIT_STRATEGY: none
diff --git a/.gitlab/ci/build-images.gitlab-ci.yml b/.gitlab/ci/build-images.gitlab-ci.yml
index 1b041c9af38..3c7056a92c1 100644
--- a/.gitlab/ci/build-images.gitlab-ci.yml
+++ b/.gitlab/ci/build-images.gitlab-ci.yml
@@ -15,27 +15,7 @@ build-qa-image:
stage: build-images
needs: []
script:
- # Tag with commit SHA by default
- - export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA}"
- # For branches, tag with slugified branch name. For tags, use the tag directly
- - export QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"
- # Auto-deploy tag format uses first 12 letters of commit SHA. Tag with that
- # reference also
- - export QA_IMAGE_FOR_AUTO_DEPLOY="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA:0:11}"
- - echo $QA_IMAGE
- - echo $QA_IMAGE_BRANCH
- - echo $QA_IMAGE_FOR_AUTO_DEPLOY
- - |
- /kaniko/executor \
- --context=${CI_PROJECT_DIR} \
- --dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile \
- --destination=${QA_IMAGE} \
- --destination=${QA_IMAGE_BRANCH} \
- --destination=${QA_IMAGE_FOR_AUTO_DEPLOY} \
- --build-arg=CHROME_VERSION=${CHROME_VERSION} \
- --build-arg=DOCKER_VERSION=${DOCKER_VERSION} \
- --build-arg=QA_BUILD_TARGET=${QA_BUILD_TARGET:-qa} \
- --cache=true
+ - ./scripts/build_qa_image
# This image is used by:
# - The `CNG` pipelines (via the `review-build-cng` job): https://gitlab.com/gitlab-org/build/CNG/-/blob/cfc67136d711e1c8c409bf8e57427a644393da2f/.gitlab-ci.yml#L335
diff --git a/.gitlab/ci/caching.gitlab-ci.yml b/.gitlab/ci/caching.gitlab-ci.yml
new file mode 100644
index 00000000000..6a13fc3c56f
--- /dev/null
+++ b/.gitlab/ci/caching.gitlab-ci.yml
@@ -0,0 +1,65 @@
+cache-workhorse:
+ extends:
+ - .default-retry
+ - .default-before_script
+ - .rails-cache
+ - .setup-test-env-cache
+ - .caching:rules:cache-workhorse
+ stage: prepare
+ variables:
+ SETUP_DB: "false"
+ script:
+ - source scripts/gitlab_component_helpers.sh
+ - 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
+ - run_timed_command "scripts/setup-test-env"
+ - run_timed_command "select_gitlab_workhorse_essentials"
+ - run_timed_command "create_gitlab_workhorse_package"
+ - run_timed_command "upload_gitlab_workhorse_package"
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
+
+.cache-assets-base:
+ extends:
+ - .compile-assets-base
+ - .assets-compile-cache
+ - .caching:rules:cache-assets
+ stage: prepare
+ variables:
+ WEBPACK_REPORT: "false"
+ script:
+ - yarn_install_script
+ - export GITLAB_ASSETS_HASH=$(bundle exec rake gitlab:assets:hash_sum)
+ - source scripts/gitlab_component_helpers.sh
+ - 'gitlab_assets_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
+ - assets_compile_script
+ - echo -n "${GITLAB_ASSETS_HASH}" > "cached-assets-hash.txt"
+ - run_timed_command "create_gitlab_assets_package"
+ - run_timed_command "upload_gitlab_assets_package"
+
+cache-assets:test:
+ extends: .cache-assets-base
+
+cache-assets:test as-if-foss:
+ extends:
+ - .cache-assets-base
+ - .as-if-foss
+
+cache-assets:production:
+ extends: .cache-assets-base
+ variables:
+ NODE_ENV: "production"
+ RAILS_ENV: "production"
+
+packages-cleanup:
+ extends:
+ - .default-retry
+ - .caching:rules:packages-cleanup
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}
+ stage: prepare
+ before_script:
+ - source scripts/utils.sh
+ - install_gitlab_gem
+ script:
+ - scripts/packages/automated_cleanup.rb
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 7e157171183..022f1c17a93 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -2,7 +2,7 @@
extends:
- .default-retry
- .docs:rules:review-docs
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-alpine
stage: review
needs: []
variables:
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 3bd65b565e4..085c0aa890d 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -1,11 +1,3 @@
-.yarn-install: &yarn-install
- - source scripts/utils.sh
- - run_timed_command "retry yarn install --frozen-lockfile"
-
-.storybook-yarn-install: &storybook-yarn-install
- - source scripts/utils.sh
- - run_timed_command "retry yarn run storybook:install --frozen-lockfile"
-
.compile-assets-base:
extends:
- .default-retry
@@ -21,9 +13,16 @@
WEBPACK_COMPILE_LOG_PATH: "tmp/webpack-output.log"
stage: prepare
script:
- - *yarn-install
- - run_timed_command "bin/rake gitlab:assets:compile"
- - run_timed_command "scripts/clean-old-cached-assets"
+ - yarn_install_script
+ - export GITLAB_ASSETS_HASH=$(bin/rake gitlab:assets:hash_sum)
+ - 'echo "CACHE_ASSETS_AS_PACKAGE: ${CACHE_ASSETS_AS_PACKAGE}"'
+ # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
+ - |
+ if [[ "${CACHE_ASSETS_AS_PACKAGE}" == "true" ]]; then
+ source scripts/gitlab_component_helpers.sh
+ gitlab_assets_archive_doesnt_exist || run_timed_command "download_and_extract_gitlab_assets"
+ fi
+ - assets_compile_script
compile-production-assets:
extends:
@@ -42,8 +41,6 @@ compile-production-assets:
- public/assets/
- "${WEBPACK_COMPILE_LOG_PATH}"
when: always
- before_script:
- - !reference [.default-before_script, before_script]
after_script:
- rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
@@ -71,6 +68,9 @@ update-assets-compile-production-cache:
- .assets-compile-cache-push
- .shared:rules:update-cache
stage: prepare
+ script:
+ - !reference [compile-production-assets, script]
+ - echo -n "${GITLAB_ASSETS_HASH}" > "cached-assets-hash.txt"
artifacts: {} # This job's purpose is only to update the cache.
update-assets-compile-test-cache:
@@ -79,25 +79,31 @@ update-assets-compile-test-cache:
- .assets-compile-cache-push
- .shared:rules:update-cache
stage: prepare
+ script:
+ - !reference [compile-test-assets, script]
+ - echo -n "${GITLAB_ASSETS_HASH}" > "cached-assets-hash.txt"
artifacts: {} # This job's purpose is only to update the cache.
+# TODO: Remove this as it's duplicating update-assets-compile-*-cache
update-yarn-cache:
extends:
- .default-retry
+ - .default-utils-before_script
- .yarn-cache-push
- .shared:rules:update-cache
stage: prepare
script:
- - *yarn-install
+ - yarn_install_script
update-storybook-yarn-cache:
extends:
- .default-retry
+ - .default-utils-before_script
- .storybook-yarn-cache-push
- .shared:rules:update-cache
stage: prepare
script:
- - *storybook-yarn-install
+ - yarn_install_script
.frontend-fixtures-base:
extends:
@@ -180,7 +186,7 @@ graphql-schema-dump as-if-foss:
SETUP_DB: "false"
before_script:
- !reference [.default-before_script, before_script]
- - *yarn-install
+ - yarn_install_script
stage: test
.jest-base:
@@ -247,6 +253,7 @@ jest-integration:
coverage-frontend:
extends:
- .default-retry
+ - .default-utils-before_script
- .yarn-cache
- .frontend:rules:coverage-frontend
needs:
@@ -255,9 +262,8 @@ coverage-frontend:
- job: "jest minimal"
optional: true
stage: post-test
- before_script:
- - *yarn-install
script:
+ - yarn_install_script
- run_timed_command "yarn node scripts/frontend/merge_coverage_frontend.js"
# Removing the individual coverage results, as we just merged them.
- if ls coverage-frontend/jest-* > /dev/null 2>&1; then
@@ -277,31 +283,33 @@ coverage-frontend:
.qa-frontend-node:
extends:
- .default-retry
- - .yarn-cache
+ - .default-utils-before_script
+ - .qa-frontend-node-cache
- .frontend:rules:qa-frontend-node
stage: test
- dependencies: []
+ needs: []
script:
- - *yarn-install
+ - yarn_install_script
- run_timed_command "retry yarn run webpack-prod"
qa-frontend-node:14:
extends: .qa-frontend-node
- image: ${GITLAB_DEPENDENCY_PROXY}node:14
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}node:14
qa-frontend-node:16:
extends: .qa-frontend-node
- image: ${GITLAB_DEPENDENCY_PROXY}node:16
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}node:16
qa-frontend-node:latest:
extends:
- .qa-frontend-node
- .frontend:rules:qa-frontend-node-latest
- image: ${GITLAB_DEPENDENCY_PROXY}node:latest
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}node:latest
webpack-dev-server:
extends:
- .default-retry
+ - .default-utils-before_script
- .yarn-cache
- .frontend:rules:default-frontend-jobs
stage: test
@@ -310,7 +318,7 @@ webpack-dev-server:
WEBPACK_MEMORY_TEST: "true"
WEBPACK_VENDOR_DLL: "true"
script:
- - *yarn-install
+ - yarn_install_script
- run_timed_command "retry yarn webpack-vendor"
- run_timed_command "node --expose-gc node_modules/.bin/webpack-dev-server --config config/webpack.config.js"
artifacts:
@@ -322,13 +330,14 @@ webpack-dev-server:
bundle-size-review:
extends:
- .default-retry
+ - .default-utils-before_script
- .assets-compile-cache
- .frontend:rules:bundle-size-review
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:danger
stage: test
needs: []
script:
- - *yarn-install
+ - yarn_install_script
- scripts/bundle_size_review
artifacts:
when: always
@@ -366,8 +375,8 @@ startup-css-check as-if-foss:
- .frontend-test-base
- .storybook-yarn-cache
script:
- - *storybook-yarn-install
- - yarn run storybook:build
+ - run_timed_command "retry yarn run storybook:install --frozen-lockfile"
+ - run_timed_command "yarn run storybook:build"
needs: ["graphql-schema-dump"]
compile-storybook:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 7bdca62b68e..ed59a0dd8fe 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -8,13 +8,17 @@
- job_execution_timeout
- stuck_or_timeout_failure
-.default-before_script:
+.default-utils-before_script:
before_script:
- echo $FOSS_ONLY
- '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'
- export GOPATH=$CI_PROJECT_DIR/.go
- mkdir -p $GOPATH
- source scripts/utils.sh
+
+.default-before_script:
+ before_script:
+ - !reference [.default-utils-before_script, before_script]
- source scripts/prepare_build.sh
.ruby-gems-cache: &ruby-gems-cache
@@ -79,19 +83,30 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.assets-cache: &assets-cache
- key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v2"
+ key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v5"
+ # This list should match GITLAB_ASSETS_PATHS_LIST from scripts/gitlab_component_helpers.sh
paths:
- - assets-hash.txt
- - public/assets/webpack/
- - tmp/cache/assets/sprockets/
- - tmp/cache/babel-loader/
- - tmp/cache/vue-loader/
+ - cached-assets-hash.txt
+ - app/assets/javascripts/locale/**/app.js
+ - public/assets/
policy: pull
.assets-cache-push: &assets-cache-push
<<: *assets-cache
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
+.assets-tmp-cache: &assets-tmp-cache
+ key: "assets-tmp-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v1"
+ paths:
+ - tmp/cache/assets/sprockets/
+ - tmp/cache/babel-loader/
+ - tmp/cache/vue-loader/
+ policy: pull
+
+.assets-tmp-cache-push: &assets-tmp-cache-push
+ <<: *assets-tmp-cache
+ policy: push # We want to rebuild the cache from scratch to ensure we don't pile up outdated cache files.
+
.storybook-node-modules-cache: &storybook-node-modules-cache
key: "storybook-node-modules-${DEBIAN_VERSION}-${NODE_ENV}"
paths:
@@ -174,7 +189,7 @@
cache:
- *ruby-gems-cache
-.danger-review-cache:
+.ruby-node-cache:
cache:
- *ruby-gems-cache
- *node-modules-cache
@@ -199,6 +214,12 @@
cache:
- *node-modules-cache
+.qa-frontend-node-cache:
+ cache:
+ - *node-modules-cache
+ - *assets-tmp-cache
+
+# TODO: Remove this as it's duplicating .assets-compile-cache-push
.yarn-cache-push:
cache:
- *node-modules-cache-push
@@ -208,12 +229,14 @@
- *ruby-gems-cache
- *node-modules-cache
- *assets-cache
+ - *assets-tmp-cache
.assets-compile-cache-push:
cache:
- *ruby-gems-cache # We don't push this cache as it's already rebuilt by `update-setup-test-env-cache`
- *node-modules-cache-push
- *assets-cache-push
+ - *assets-tmp-cache-push
.storybook-yarn-cache:
cache:
@@ -323,7 +346,7 @@
FOSS_ONLY: '1'
.use-docker-in-docker:
- image: ${GITLAB_DEPENDENCY_PROXY}docker:${DOCKER_VERSION}
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}docker:${DOCKER_VERSION}
services:
- docker:${DOCKER_VERSION}-dind
variables:
diff --git a/.gitlab/ci/notify.gitlab-ci.yml b/.gitlab/ci/notify.gitlab-ci.yml
index 95318d5ce08..51b0f4071eb 100644
--- a/.gitlab/ci/notify.gitlab-ci.yml
+++ b/.gitlab/ci/notify.gitlab-ci.yml
@@ -1,12 +1,12 @@
.notify-slack:
- image: ${GITLAB_DEPENDENCY_PROXY}alpine
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine/curl
stage: notify
dependencies: []
cache: {}
variables:
MERGE_REQUEST_URL: ${CI_MERGE_REQUEST_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}
before_script:
- - apk update && apk add git curl bash
+ - apk update && apk add git bash
- echo "NOTIFY_CHANNEL is ${NOTIFY_CHANNEL}"
- echo "CI_PIPELINE_URL is ${CI_PIPELINE_URL}"
@@ -34,13 +34,28 @@ notify-security-pipeline:
- scripts/slack ${NOTIFY_CHANNEL} "<!subteam^S0127FU8PDE> â˜ ï¸ Pipeline for merged result failed! â˜ ï¸ See ${CI_PIPELINE_URL} (triggered from ${MERGE_REQUEST_URL})" ci_failing "GitLab Release Tools Bot"
notify-pipeline-failure:
- extends:
- - .notify-slack
+ extends: .notify-slack
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
rules:
- - if: '$NOTIFY_PIPELINE_FAILURE_CHANNEL'
+ # Don't report child pipeline failures
+ - if: '$CI_PIPELINE_SOURCE == "parent_pipeline"'
+ when: never
+ - if: '$CI_SLACK_WEBHOOK_URL && $NOTIFY_PIPELINE_FAILURE_CHANNEL'
when: on_failure
allow_failure: true
variables:
- NOTIFY_CHANNEL: "${NOTIFY_PIPELINE_FAILURE_CHANNEL}"
+ SLACK_CHANNEL: "${NOTIFY_PIPELINE_FAILURE_CHANNEL}"
+ FAILED_PIPELINE_REPORT_FILE: "failed_pipeline_report.json"
+ before_script:
+ - source scripts/utils.sh
+ - apt-get update && apt-get install -y jq
+ - install_gitlab_gem
script:
- - scripts/slack ${NOTIFY_CHANNEL} "⌠\`${CI_COMMIT_REF_NAME}\` pipeline failed! See ${CI_PIPELINE_URL}" ci_failing "notify-pipeline-failure"
+ - scripts/generate-failed-pipeline-slack-message.rb
+ - |
+ curl -X POST -H 'Content-Type: application/json' --data @${FAILED_PIPELINE_REPORT_FILE} "$CI_SLACK_WEBHOOK_URL"
+ artifacts:
+ paths:
+ - ${FAILED_PIPELINE_REPORT_FILE}
+ when: always
+ expire_in: 2 days
diff --git a/.gitlab/ci/package-and-test/main.gitlab-ci.yml b/.gitlab/ci/package-and-test/main.gitlab-ci.yml
index d96da7744ab..1a1c67bf572 100644
--- a/.gitlab/ci/package-and-test/main.gitlab-ci.yml
+++ b/.gitlab/ci/package-and-test/main.gitlab-ci.yml
@@ -1,11 +1,13 @@
# E2E tests pipeline loaded dynamically by script: scripts/generate-e2e-pipeline
+default:
+ interruptible: true
+
include:
- - local: .gitlab/ci/global.gitlab-ci.yml
- local: .gitlab/ci/package-and-test/rules.gitlab-ci.yml
- local: .gitlab/ci/package-and-test/variables.gitlab-ci.yml
- project: gitlab-org/quality/pipeline-common
- ref: 1.2.1
+ ref: 1.3.0
file:
- /ci/base.gitlab-ci.yml
- /ci/allure-report.yml
@@ -27,13 +29,12 @@ stages:
.ruby-image:
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3
-.bundle-install:
+.qa-install:
+ variables:
+ BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES: "true"
+ BUNDLE_SILENCE_ROOT_WARNING: "true"
extends:
- .gitlab-qa-install
- - .qa-cache
- variables:
- RUN_WITH_BUNDLE: "true" # installs and runs gitlab-qa via bundler
- QA_PATH: qa
.omnibus-env:
variables:
@@ -44,6 +45,8 @@ stages:
echo "SECURITY_SOURCES=${SECURITY_SOURCES:-false}" > $BUILD_ENV
echo "OMNIBUS_GITLAB_CACHE_UPDATE=${OMNIBUS_GITLAB_CACHE_UPDATE:-false}" >> $BUILD_ENV
for version_file in *_VERSION; do echo "$version_file=$(cat $version_file)" >> $BUILD_ENV; done
+ echo "OMNIBUS_GITLAB_RUBY3_BUILD=${OMNIBUS_GITLAB_RUBY3_BUILD:-false}" >> $BUILD_ENV
+ echo "OMNIBUS_GITLAB_CACHE_EDITION=${OMNIBUS_GITLAB_CACHE_EDITION:-GITLAB}" >> $BUILD_ENV
echo "Built environment file for omnibus build:"
cat $BUILD_ENV
artifacts:
@@ -59,14 +62,16 @@ stages:
.qa:
extends:
- .qa-base
- - .bundle-install
+ - .qa-install
- .gitlab-qa-report
stage: test
tags:
- e2e
needs:
- - trigger-omnibus
- - download-knapsack-report
+ - job: trigger-omnibus
+ optional: true
+ - job: download-knapsack-report
+ artifacts: true
variables:
QA_GENERATE_ALLURE_REPORT: "true"
QA_CAN_TEST_PRAEFECT: "false"
@@ -80,14 +85,33 @@ stages:
# ==========================================
# Prepare stage
# ==========================================
+check-release-set:
+ extends: .rules:prepare
+ stage: .pre
+ script:
+ - |
+ if [ -z "$RELEASE" ]; then
+ echo "E2E test pipeline requires omnibus installation docker image to be set via $RELEASE environment variable"
+ exit 1
+ else
+ echo "Omnibus installation image is set to '$RELEASE'"
+ fi
+
+dont-interrupt-me:
+ extends: .rules:dont-interrupt
+ stage: .pre
+ interruptible: false
+ script:
+ - echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible."
+
trigger-omnibus-env:
extends:
- .omnibus-env
- - .rules:prepare
+ - .rules:omnibus-build
stage: .pre
trigger-omnibus:
- extends: .rules:prepare
+ extends: .rules:omnibus-build
stage: .pre
needs:
- trigger-omnibus-env
@@ -106,6 +130,8 @@ trigger-omnibus:
TOP_UPSTREAM_SOURCE_PROJECT: $CI_PROJECT_PATH
SECURITY_SOURCES: $SECURITY_SOURCES
CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
+ RUBY3_BUILD: $OMNIBUS_GITLAB_RUBY3_BUILD
+ CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION
SKIP_QA_DOCKER: "true"
SKIP_QA_TEST: "true"
ee: "true"
@@ -115,30 +141,34 @@ trigger-omnibus:
download-knapsack-report:
extends:
- - .bundle-install
- - .ruby-image
+ - .gitlab-qa-image
- .rules:prepare
stage: .pre
+ variables:
+ KNAPSACK_DIR: ${CI_PROJECT_DIR}/qa/knapsack
+ GIT_STRATEGY: none
script:
+ # when using qa-image, code runs in /home/gitlab/qa folder
- bundle exec rake "knapsack:download[test]"
+ - mkdir -p "$KNAPSACK_DIR" && cp knapsack/*.json "${KNAPSACK_DIR}/"
allow_failure: true
artifacts:
paths:
- - qa/knapsack/ee-*.json
+ - qa/knapsack/*.json
expire_in: 1 day
-# e2e test jobs run on separate runner which has separate cache setup
cache-gems:
extends:
- - .bundle-install
+ - .qa-install
- .ruby-image
- - .qa-cache-push
- .rules:prepare
stage: .pre
tags:
- e2e
script:
- echo "Populated qa cache"
+ cache:
+ policy: pull-push
# ==========================================
# Test stage
@@ -154,11 +184,11 @@ cache-gems:
_ee:quarantine:
extends:
- .qa
- - .rules:test:quarantine
+ - .rules:test:manual
needs:
- - trigger-omnibus
+ - job: trigger-omnibus
+ optional: true
stage: test
- allow_failure: true
variables:
QA_RSPEC_TAGS: --tag quarantine
@@ -332,8 +362,9 @@ ee:update-minor:
UPDATE_TYPE: minor
QA_RSPEC_TAGS: --tag smoke
rules:
- - !reference [.rules:test:qa, rules]
+ - !reference [.rules:test:update, rules]
- if: $QA_SUITES =~ /Test::Instance::Smoke/
+ - !reference [.rules:test:manual, rules]
ee:update-major:
extends:
@@ -343,8 +374,9 @@ ee:update-major:
UPDATE_TYPE: major
QA_RSPEC_TAGS: --tag smoke
rules:
- - !reference [.rules:test:qa, rules]
+ - !reference [.rules:test:update, rules]
- if: $QA_SUITES =~ /Test::Instance::Smoke/
+ - !reference [.rules:test:manual, rules]
ee:gitaly-cluster:
extends: .qa
@@ -353,6 +385,7 @@ ee:gitaly-cluster:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::GitalyCluster/
+ - !reference [.rules:test:manual, rules]
ee:group-saml:
extends: .qa
@@ -361,6 +394,7 @@ ee:group-saml:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::GroupSAML/
+ - !reference [.rules:test:manual, rules]
ee:instance-saml:
extends: .qa
@@ -369,6 +403,7 @@ ee:instance-saml:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::InstanceSAML/
+ - !reference [.rules:test:manual, rules]
ee:jira:
extends: .qa
@@ -379,6 +414,7 @@ ee:jira:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::Jira/
+ - !reference [.rules:test:manual, rules]
ee:ldap-no-server:
extends: .qa
@@ -387,6 +423,7 @@ ee:ldap-no-server:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::LDAPNoServer/
+ - !reference [.rules:test:manual, rules]
ee:ldap-tls:
extends: .qa
@@ -395,6 +432,7 @@ ee:ldap-tls:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::LDAPTLS/
+ - !reference [.rules:test:manual, rules]
ee:ldap-no-tls:
extends: .qa
@@ -403,6 +441,7 @@ ee:ldap-no-tls:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::LDAPNoTLS/
+ - !reference [.rules:test:manual, rules]
ee:mtls:
extends: .qa
@@ -411,6 +450,7 @@ ee:mtls:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::MTLS/
+ - !reference [.rules:test:manual, rules]
ee:mattermost:
extends: .qa
@@ -419,6 +459,7 @@ ee:mattermost:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::Mattermost/
+ - !reference [.rules:test:manual, rules]
ee:registry:
extends: .qa
@@ -427,6 +468,7 @@ ee:registry:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::Registry/
+ - !reference [.rules:test:manual, rules]
ee:registry-with-cdn:
extends: .qa
@@ -443,6 +485,7 @@ ee:registry-with-cdn:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::RegistryWithCDN/
+ - !reference [.rules:test:manual, rules]
ee:repository-storage:
extends: .qa
@@ -451,6 +494,7 @@ ee:repository-storage:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Instance::RepositoryStorage/
+ - !reference [.rules:test:manual, rules]
ee:service-ping-disabled:
extends: .qa
@@ -459,6 +503,7 @@ ee:service-ping-disabled:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::ServicePingDisabled/
+ - !reference [.rules:test:manual, rules]
ee:smtp:
extends: .qa
@@ -467,6 +512,7 @@ ee:smtp:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::SMTP/
+ - !reference [.rules:test:manual, rules]
ee:cloud-activation:
extends: .qa
@@ -476,6 +522,7 @@ ee:cloud-activation:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::CloudActivation/
+ - !reference [.rules:test:manual, rules]
ee:large-setup:
extends: .qa
@@ -485,6 +532,7 @@ ee:large-setup:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Instance::LargeSetup/
+ - !reference [.rules:test:manual, rules]
ee:metrics:
extends: .qa
@@ -493,6 +541,7 @@ ee:metrics:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Instance::Metrics/
+ - !reference [.rules:test:manual, rules]
ee:elasticsearch:
extends: .qa
@@ -504,6 +553,7 @@ ee:elasticsearch:
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::Elasticsearch/
+ - !reference [.rules:test:manual, rules]
ee:registry-object-storage-tls:
extends: ee:object-storage-aws
@@ -536,7 +586,7 @@ e2e-test-report:
upload-knapsack-report:
extends:
- .generate-knapsack-report-base
- - .bundle-install
+ - .qa-install
- .ruby-image
- .rules:report:process-results
stage: report
@@ -544,7 +594,7 @@ upload-knapsack-report:
relate-test-failures:
extends:
- - .bundle-install
+ - .qa-install
- .ruby-image
- .rules:report:process-results
stage: report
@@ -562,7 +612,7 @@ relate-test-failures:
generate-test-session:
extends:
- - .bundle-install
+ - .qa-install
- .ruby-image
- .rules:report:process-results
stage: report
@@ -585,7 +635,7 @@ generate-test-session:
notify-slack:
extends:
- .notify-slack-qa
- - .bundle-install
+ - .qa-install
- .ruby-image
- .rules:report:process-results
stage: notify
@@ -594,6 +644,7 @@ notify-slack:
SLACK_ICON_EMOJI: ci_failing
STATUS_SYM: ☠ï¸
STATUS: failed
+ TYPE: "(package-and-test) "
when: on_failure
script:
- bundle exec gitlab-qa-report --prepare-stage-reports "$CI_PROJECT_DIR/gitlab-qa-run-*/**/rspec-*.xml" # generate summary
diff --git a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml
index d866dec1cd0..47625340a3a 100644
--- a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml
+++ b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml
@@ -41,12 +41,27 @@
rules:
- when: always
+.rules:dont-interrupt:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ allow_failure: true
+ - if: $CI_MERGE_REQUEST_IID
+ when: manual
+ allow_failure: true
+
+.rules:omnibus-build:
+ rules:
+ - if: $SKIP_OMNIBUS_TRIGGER == "true"
+ when: never
+ - when: always
+
# ------------------------------------------
# Test
# ------------------------------------------
-.rules:test:quarantine:
+.rules:test:manual:
rules:
- when: manual
+ allow_failure: true
variables:
QA_TESTS: ""
@@ -78,7 +93,10 @@
rules:
- *qa-framework-changes
- <<: *specific-specs
- when: never
+ when: manual
+ allow_failure: true
+ variables:
+ QA_TESTS: ""
- *feature-flags-set-manual
# general qa job rule for jobs without the need to run in parallel
@@ -87,11 +105,21 @@
- *qa-framework-changes
- *feature-flags-set-manual
+.rules:test:update:
+ rules:
+ # skip upgrade jobs if gitlab version is not provided
+ # these jobs need gitlab version because we can't reliably detect it from just the image
+ - if: $GITLAB_VERSION == null
+ when: never
+ - !reference [.rules:test:qa, rules]
+
# ------------------------------------------
# Report
# ------------------------------------------
.rules:report:allure-report:
rules:
+ - if: $SKIP_ALLURE_REPORT == "true"
+ when: never
- when: always
.rules:report:process-results:
diff --git a/.gitlab/ci/package-and-test/variables.gitlab-ci.yml b/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
index 324092c80f4..cd22fa0e6e4 100644
--- a/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
+++ b/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
@@ -1,9 +1,10 @@
# Default variables for package-and-test
variables:
- RELEASE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/build/omnibus-gitlab-mirror/gitlab-ee:${CI_COMMIT_SHA}"
SKIP_REPORT_IN_ISSUES: "true"
OMNIBUS_GITLAB_CACHE_UPDATE: "false"
+ OMNIBUS_GITLAB_RUBY3_BUILD: "false"
+ OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB"
QA_LOG_LEVEL: "info"
QA_TESTS: ""
QA_FEATURE_FLAGS: ""
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index c5a182b055a..bd587cb4418 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -76,8 +76,15 @@ e2e:package-and-test:
- e2e-test-pipeline-generate
variables:
SKIP_MESSAGE: Skipping package-and-test due to mr containing only quarantine changes!
+ RELEASE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/build/omnibus-gitlab-mirror/gitlab-ee:${CI_COMMIT_SHA}"
+ GITLAB_QA_IMAGE: "${CI_REGISTRY_IMAGE}/gitlab-ee-qa:${CI_COMMIT_SHA}"
+ RUN_WITH_BUNDLE: "true" # instructs pipeline to install and run gitlab-qa gem via bundler
+ QA_PATH: qa # sets the optional path for bundler to run from
trigger:
strategy: depend
+ forward:
+ yaml_variables: true
+ pipeline_variables: true
include:
- artifact: package-and-test-pipeline.yml
job: e2e-test-pipeline-generate
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 0f524f03188..c60f85634b6 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -1,160 +1,5 @@
-#######################
-# rspec job base specs
-.rails-job-base:
- extends:
- - .default-retry
- - .default-before_script
- - .rails-cache
-
-.base-script:
- script:
- - source ./scripts/rspec_helpers.sh
- # Only install knapsack after bundle install! Otherwise oddly some native
- # gems could not be found under some circumstance. No idea why, hours wasted.
- - run_timed_command "gem install knapsack --no-document"
- - echo -e "\e[0Ksection_start:`date +%s`:gitaly-test-spawn[collapsed=true]\r\e[0KStarting Gitaly"
- - run_timed_command "scripts/gitaly-test-spawn" # Do not use 'bundle exec' here
- - echo -e "\e[0Ksection_end:`date +%s`:gitaly-test-spawn\r\e[0K"
-
-.minimal-rspec-tests:
- variables:
- RSPEC_TESTS_MAPPING_ENABLED: "true"
-
-.single-db:
- variables:
- DECOMPOSED_DB: "false"
-
-.single-db-rspec:
- extends: .single-db
-
-.praefect-with-db:
- variables:
- GITALY_PRAEFECT_WITH_DB: '1'
-
-.rspec-base:
- extends:
- - .rails-job-base
- - .base-artifacts
- stage: test
- variables:
- 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]
- - rspec_paralellized_job "--tag ~quarantine --tag ~level:migration"
-
-.base-artifacts:
- artifacts:
- expire_in: 31d
- when: always
- paths:
- - coverage/
- - crystalball/
- - deprecations/
- - knapsack/
- - rspec/
- - tmp/capybara/
- - log/*.log
- reports:
- junit: ${JUNIT_RESULT_FILE}
-
-.rspec-base-migration:
- extends:
- - .base-artifacts
- - .rails:rules:ee-and-foss-migration
- script:
- - !reference [.base-script, script]
- - rspec_paralellized_job "--tag ~quarantine --tag level:migration"
-
-.rspec-base-pg11:
- extends:
- - .rspec-base
- - .use-pg11
-
-.rspec-base-pg12:
- extends:
- - .rspec-base
- - .use-pg12
-
-.rspec-base-pg12-as-if-foss:
- extends:
- - .rspec-base
- - .as-if-foss
- - .use-pg12
- needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"]
-
-.rspec-base-pg13:
- extends:
- - .rspec-base
- - .use-pg13
-
-.rspec-ee-base-pg11:
- extends:
- - .rspec-base
- - .use-pg11-ee
-
-.rspec-ee-base-pg12:
- extends:
- - .rspec-base
- - .use-pg12-ee
-
-.rspec-ee-base-pg12-es8:
- extends:
- - .rspec-base
- - .use-pg12-es8-ee
- - .rails:rules:run-search-tests
-
-.rspec-ee-base-pg12-opensearch1:
- extends:
- - .rspec-base
- - .use-pg12-opensearch1-ee
- - .rails:rules:run-search-tests
-
-.rspec-ee-base-pg13:
- extends:
- - .rspec-base
- - .use-pg13-ee
-
-.db-job-base:
- extends:
- - .rails-job-base
- - .rails:rules:ee-and-foss-migration
- - .use-pg12
- stage: test
- needs: ["setup-test-env"]
-# rspec job base specs
-######################
-
-############################
-# rspec job parallel configs
-.rspec-migration-parallel:
- parallel: 12
-
-.rspec-ee-migration-parallel:
- parallel: 4
-
-.rspec-unit-parallel:
- parallel: 28
-
-.rspec-ee-unit-parallel:
- parallel: 18
-
-.rspec-integration-parallel:
- parallel: 12
-
-.rspec-ee-integration-parallel:
- parallel: 6
-
-.rspec-system-parallel:
- parallel: 28
-
-.rspec-ee-system-parallel:
- parallel: 10
-# rspec job parallel configs
-############################
+include:
+ - local: .gitlab/ci/rails/shared.gitlab-ci.yml
###############################################################
# EE/FOSS: default refs (MRs, default branch, schedules) jobs #
@@ -168,7 +13,7 @@ setup-test-env:
SETUP_DB: "false"
script:
- echo $CI_MERGE_REQUEST_APPROVED
- - source scripts/gitlab_workhorse_component_helpers.sh
+ - source scripts/gitlab_component_helpers.sh
- run_timed_command "download_and_extract_gitlab_workhorse_package" || true
- run_timed_command "scripts/setup-test-env"
- run_timed_command "select_gitlab_workhorse_essentials"
@@ -197,22 +42,6 @@ setup-test-env:
- ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
when: always
-build-components:
- extends:
- - setup-test-env
- - .rails:rules:build-components
- script:
- - source scripts/gitlab_workhorse_component_helpers.sh
- - 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
- - run_timed_command "scripts/setup-test-env"
- - run_timed_command "select_gitlab_workhorse_essentials"
- - run_timed_command "create_gitlab_workhorse_package"
- - run_timed_command "upload_gitlab_workhorse_package"
- artifacts:
- expire_in: 7d
- paths:
- - ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
-
update-setup-test-env-cache:
extends:
- setup-test-env
@@ -407,6 +236,21 @@ db:check-migrations-single-db:
- .single-db
- .rails:rules:single-db
+db:post_deployment_migrations_validator:
+ extends:
+ - .db-job-base
+ - .rails:rules:ee-and-foss-mr-with-migration
+ script:
+ - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --depth 20
+ - scripts/post_deployment_migrations_validator
+ allow_failure: true
+
+db:post_deployment_migrations_validator-single-db:
+ extends:
+ - db:post_deployment_migrations_validator
+ - .single-db
+ - .rails:rules:single-db
+
db:migrate-non-superuser:
extends:
- .db-job-base
@@ -943,18 +787,41 @@ rspec fail-fast:
paths:
- tmp/capybara/
-rspec foss-impact:
+rspec-foss-impact:pipeline-generate:
extends:
- - .rspec-base-pg12-as-if-foss
- .rails:rules:rspec-foss-impact
- needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"]
+ stage: prepare
+ needs: ["detect-tests"]
script:
- - !reference [.base-script, script]
- - rspec_matched_foss_tests "${RSPEC_MATCHING_TESTS_PATH}" "--tag ~quarantine"
+ - scripts/generate-rspec-foss-impact-pipeline "${RSPEC_MATCHING_TESTS_FOSS_PATH}" "${RSPEC_FOSS_IMPACT_PIPELINE_YML}"
artifacts:
- expire_in: 7d
+ expire_in: 1 day
paths:
- - tmp/capybara/
+ - $RSPEC_FOSS_IMPACT_PIPELINE_YML
+
+rspec-foss-impact:trigger:
+ extends:
+ - .rails:rules:rspec-foss-impact
+ stage: test
+ needs:
+ - job: "setup-test-env"
+ artifacts: false
+ - job: "retrieve-tests-metadata"
+ artifacts: false
+ - job: "compile-test-assets as-if-foss"
+ artifacts: false
+ - job: "rspec-foss-impact:pipeline-generate"
+ artifacts: true
+ variables:
+ PARENT_PIPELINE_ID: $CI_PIPELINE_ID
+ trigger:
+ strategy: depend
+ forward:
+ yaml_variables: true
+ pipeline_variables: true
+ include:
+ - artifact: $RSPEC_FOSS_IMPACT_PIPELINE_YML
+ job: rspec-foss-impact:pipeline-generate
fail-pipeline-early:
extends:
diff --git a/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb b/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
new file mode 100644
index 00000000000..4ae4cb75a25
--- /dev/null
+++ b/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
@@ -0,0 +1,50 @@
+# RSpec FOSS impact pipeline loaded dynamically by script: scripts/generate-rspec-foss-impact-pipeline
+
+include:
+ - local: .gitlab/ci/rails/shared.gitlab-ci.yml
+
+default:
+ image: $DEFAULT_CI_IMAGE
+ tags:
+ - gitlab-org
+ # Default job timeout set to 90m https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10520
+ timeout: 90m
+ interruptible: true
+
+stages:
+ - test
+
+dont-interrupt-me:
+ extends: .rules:dont-interrupt
+ stage: .pre
+ interruptible: false
+ script:
+ - echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible."
+
+rspec foss-impact:
+ extends: .rspec-base-pg12-as-if-foss
+ needs:
+ - pipeline: $PARENT_PIPELINE_ID
+ job: detect-tests
+ - pipeline: $PARENT_PIPELINE_ID
+ job: setup-test-env
+ - pipeline: $PARENT_PIPELINE_ID
+ job: retrieve-tests-metadata
+ - pipeline: $PARENT_PIPELINE_ID
+ job: compile-test-assets as-if-foss
+ rules:
+ - when: always
+ variables:
+ RSPEC_TESTS_FILTER_FILE: "${RSPEC_MATCHING_TESTS_FOSS_PATH}"
+ RSPEC_TESTS_MAPPING_ENABLED: "true"
+<% if Integer(parallel_value) > 1 %>
+ parallel: <%= parallel_value %>
+<% end %>
+ script:
+ - !reference [.base-script, script]
+ - rspec_paralellized_job "--tag ~quarantine --tag ~level:migration"
+ artifacts:
+ expire_in: 7d
+ paths:
+ - "${RSPEC_MATCHING_TESTS_FOSS_PATH}"
+ - tmp/capybara/
diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml
new file mode 100644
index 00000000000..60c9826abfe
--- /dev/null
+++ b/.gitlab/ci/rails/shared.gitlab-ci.yml
@@ -0,0 +1,172 @@
+include:
+ - local: .gitlab/ci/global.gitlab-ci.yml
+ - local: .gitlab/ci/rules.gitlab-ci.yml
+
+.rules:dont-interrupt:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ allow_failure: true
+ - if: $CI_MERGE_REQUEST_IID
+ when: manual
+ allow_failure: true
+
+#######################
+# rspec job base specs
+.rails-job-base:
+ extends:
+ - .default-retry
+ - .default-before_script
+ - .rails-cache
+
+.base-script:
+ script:
+ - source ./scripts/rspec_helpers.sh
+ # Only install knapsack after bundle install! Otherwise oddly some native
+ # gems could not be found under some circumstance. No idea why, hours wasted.
+ - run_timed_command "gem install knapsack --no-document"
+ - echo -e "\e[0Ksection_start:`date +%s`:gitaly-test-spawn[collapsed=true]\r\e[0KStarting Gitaly"
+ - run_timed_command "scripts/gitaly-test-spawn" # Do not use 'bundle exec' here
+ - echo -e "\e[0Ksection_end:`date +%s`:gitaly-test-spawn\r\e[0K"
+
+.minimal-rspec-tests:
+ variables:
+ RSPEC_TESTS_MAPPING_ENABLED: "true"
+
+.single-db:
+ variables:
+ DECOMPOSED_DB: "false"
+
+.single-db-rspec:
+ extends: .single-db
+
+.praefect-with-db:
+ variables:
+ GITALY_PRAEFECT_WITH_DB: '1'
+
+.rspec-base:
+ extends:
+ - .rails-job-base
+ - .base-artifacts
+ stage: test
+ variables:
+ RUBY_GC_MALLOC_LIMIT: 67108864
+ RUBY_GC_MALLOC_LIMIT_MAX: 134217728
+ RECORD_DEPRECATIONS: "true"
+ GEO_SECONDARY_PROXY: 0
+ RSPEC_TESTS_FILTER_FILE: "${RSPEC_MATCHING_TESTS_PATH}"
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets", "detect-tests"]
+ script:
+ - !reference [.base-script, script]
+ - rspec_paralellized_job "--tag ~quarantine --tag ~level:migration"
+
+.base-artifacts:
+ artifacts:
+ expire_in: 31d
+ when: always
+ paths:
+ - coverage/
+ - crystalball/
+ - deprecations/
+ - knapsack/
+ - rspec/
+ - tmp/capybara/
+ - log/*.log
+ reports:
+ junit: ${JUNIT_RESULT_FILE}
+
+.rspec-base-migration:
+ extends:
+ - .base-artifacts
+ - .rails:rules:ee-and-foss-migration
+ variables:
+ RSPEC_TESTS_FILTER_FILE: "${RSPEC_MATCHING_TESTS_PATH}"
+ script:
+ - !reference [.base-script, script]
+ - rspec_paralellized_job "--tag ~quarantine --tag level:migration"
+
+.rspec-base-pg11:
+ extends:
+ - .rspec-base
+ - .use-pg11
+
+.rspec-base-pg12:
+ extends:
+ - .rspec-base
+ - .use-pg12
+
+.rspec-base-pg12-as-if-foss:
+ extends:
+ - .rspec-base
+ - .as-if-foss
+ - .use-pg12
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"]
+
+.rspec-base-pg13:
+ extends:
+ - .rspec-base
+ - .use-pg13
+
+.rspec-ee-base-pg11:
+ extends:
+ - .rspec-base
+ - .use-pg11-ee
+
+.rspec-ee-base-pg12:
+ extends:
+ - .rspec-base
+ - .use-pg12-ee
+
+.rspec-ee-base-pg12-es8:
+ extends:
+ - .rspec-base
+ - .use-pg12-es8-ee
+ - .rails:rules:run-search-tests
+
+.rspec-ee-base-pg12-opensearch1:
+ extends:
+ - .rspec-base
+ - .use-pg12-opensearch1-ee
+ - .rails:rules:run-search-tests
+
+.rspec-ee-base-pg13:
+ extends:
+ - .rspec-base
+ - .use-pg13-ee
+
+.db-job-base:
+ extends:
+ - .rails-job-base
+ - .rails:rules:ee-and-foss-migration
+ - .use-pg12
+ stage: test
+ needs: ["setup-test-env"]
+# rspec job base specs
+######################
+
+############################
+# rspec job parallel configs
+.rspec-migration-parallel:
+ parallel: 12
+
+.rspec-ee-migration-parallel:
+ parallel: 4
+
+.rspec-unit-parallel:
+ parallel: 28
+
+.rspec-ee-unit-parallel:
+ parallel: 18
+
+.rspec-integration-parallel:
+ parallel: 12
+
+.rspec-ee-integration-parallel:
+ parallel: 6
+
+.rspec-system-parallel:
+ parallel: 28
+
+.rspec-ee-system-parallel:
+ parallel: 10
+# rspec job parallel configs
+############################
diff --git a/.gitlab/ci/releases.gitlab-ci.yml b/.gitlab/ci/releases.gitlab-ci.yml
index 77f23814f3c..df7b07f5545 100644
--- a/.gitlab/ci/releases.gitlab-ci.yml
+++ b/.gitlab/ci/releases.gitlab-ci.yml
@@ -4,7 +4,7 @@
.merge-train-sync:
# We don't need/want any global before/after commands, so we overwrite these
# settings.
- image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge
stage: sync
before_script:
- apk add --no-cache --update curl bash jq
diff --git a/.gitlab/ci/review-apps/dast-api.gitlab-ci.yml b/.gitlab/ci/review-apps/dast-api.gitlab-ci.yml
new file mode 100644
index 00000000000..e2f32f120af
--- /dev/null
+++ b/.gitlab/ci/review-apps/dast-api.gitlab-ci.yml
@@ -0,0 +1,14 @@
+include:
+ - template: DAST-API.gitlab-ci.yml
+
+dast_api:
+ variables:
+ DAST_API_PROFILE: Passive
+ DAST_API_GRAPHQL: /api/graphql
+ DAST_API_TARGET_URL: ${CI_ENVIRONMENT_URL}
+ DAST_API_OVERRIDES_ENV: "{\"headers\":{\"Authorization\":\"Bearer $REVIEW_APPS_ROOT_TOKEN\"}}"
+ needs: ["review-deploy"]
+ # Uncomment resource_group if DAST_API_PROFILE is changed to an active scan
+ # resource_group: dast_api_scan
+ rules:
+ - !reference [".reports:rules:schedule-dast", rules]
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index e28ffc82811..d3f5d014464 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -1,3 +1,6 @@
+default:
+ interruptible: true
+
stages:
- prepare
- deploy
@@ -11,17 +14,25 @@ include:
- local: .gitlab/ci/review-apps/rules.gitlab-ci.yml
- local: .gitlab/ci/review-apps/qa.gitlab-ci.yml
- local: .gitlab/ci/review-apps/dast.gitlab-ci.yml
+ - local: .gitlab/ci/review-apps/dast-api.gitlab-ci.yml
.base-before_script: &base-before_script
- source ./scripts/utils.sh
- source ./scripts/review_apps/review-apps.sh
- apt-get update && apt-get install -y jq
+dont-interrupt-me:
+ extends: .rules:dont-interrupt
+ stage: prepare
+ interruptible: false
+ script:
+ - echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible."
+
review-build-cng-env:
extends:
- .default-retry
- .review:rules:review-build-cng
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:3.0-alpine3.13
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:3.0-alpine3.13
stage: prepare
needs: []
before_script:
@@ -90,6 +101,10 @@ review-deploy:
- .review:rules:review-deploy
stage: deploy
needs: ["review-build-cng"]
+ cache:
+ key: "review-deploy-dependencies-charts-${GITLAB_HELM_CHART_REF}-v1"
+ paths:
+ - "gitlab-${GITLAB_HELM_CHART_REF}"
before_script:
- export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
@@ -100,7 +115,6 @@ review-deploy:
script:
- check_kube_domain
- download_chart
- - date
- deploy || (display_deployment_debug && exit 1)
- verify_deploy || exit 1
- disable_sign_ups || (delete_release && exit 1)
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index 21e6a8e42fb..0214f5ef3f2 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -1,7 +1,8 @@
include:
- project: gitlab-org/quality/pipeline-common
- ref: 1.2.2
+ ref: 1.3.0
file:
+ - /ci/base.gitlab-ci.yml
- /ci/allure-report.yml
- /ci/knapsack-report.yml
@@ -58,7 +59,7 @@ include:
download-knapsack-report:
extends:
- .bundle-base
- - .rules:app-or-qa-framework-changes-or-review-scenarios
+ - .rules:prepare-report
stage: prepare
script:
- bundle exec rake "knapsack:download[qa]"
@@ -134,7 +135,7 @@ review-performance:
e2e-test-report:
extends:
- .generate-allure-report-base
- - .rules:app-or-qa-framework-changes-or-review-scenarios
+ - .rules:prepare-report
stage: post-qa
variables:
ALLURE_JOB_NAME: e2e-review-qa
@@ -162,7 +163,7 @@ upload-knapsack-report:
delete-test-resources:
extends:
- .bundle-base
- - .rules:app-or-qa-framework-changes-or-review-scenarios
+ - .rules:prepare-report
stage: post-qa
variables:
QA_TEST_RESOURCES_FILE_PATTERN: $CI_PROJECT_DIR/qa/tmp/test-resources-*.json
@@ -172,3 +173,21 @@ delete-test-resources:
- bundle exec rake "test_resources:delete[$QA_TEST_RESOURCES_FILE_PATTERN]"
allow_failure: true
when: always
+
+notify-slack:
+ extends:
+ - .notify-slack-qa
+ - .qa-cache
+ - .rules:notify-slack
+ stage: post-qa
+ variables:
+ RUN_WITH_BUNDLE: "true"
+ QA_PATH: qa
+ ALLURE_JOB_NAME: e2e-review-qa
+ SLACK_ICON_EMOJI: ci_failing
+ STATUS_SYM: ☠ï¸
+ STATUS: failed
+ TYPE: "(review-app) "
+ script:
+ - bundle exec gitlab-qa-report --prepare-stage-reports "$CI_PROJECT_DIR/qa/tmp/rspec-*.xml" # generate summary
+ - !reference [.notify-slack-qa, script]
diff --git a/.gitlab/ci/review-apps/rules.gitlab-ci.yml b/.gitlab/ci/review-apps/rules.gitlab-ci.yml
index 56d3731bb56..4e07f381bc9 100644
--- a/.gitlab/ci/review-apps/rules.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/rules.gitlab-ci.yml
@@ -19,6 +19,15 @@
.qa-framework-changes: &qa-framework-changes
if: $QA_FRAMEWORK_CHANGES == "true"
+.default-branch: &default-branch
+ if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+
+.qa-manual: &qa-manual
+ when: manual
+ allow_failure: true
+ variables:
+ QA_TESTS: ""
+
.never-when-qa-framework-changes-or-no-specific-specs:
- <<: *qa-framework-changes
when: never
@@ -27,10 +36,24 @@
.never-when-specific-specs-always-when-qa-framework-changes:
- <<: *specific-specs
- when: never
+ when: manual
+ allow_failure: true
+ variables:
+ QA_TESTS: ""
- *qa-framework-changes
# ------------------------------------------
+# Prepare
+# ------------------------------------------
+.rules:dont-interrupt:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ allow_failure: true
+ - if: $CI_MERGE_REQUEST_IID
+ when: manual
+ allow_failure: true
+
+# ------------------------------------------
# Test
# ------------------------------------------
.rules:qa-smoke:
@@ -41,6 +64,7 @@
QA_TESTS: "" # unset QA_TESTS even if specific tests were inferred from stage label
- *qa-framework-changes
- if: $QA_SUITES =~ /Test::Instance::Smoke/
+ - *qa-manual
.rules:qa-blocking:
rules:
@@ -70,12 +94,11 @@
# ------------------------------------------
# Prepare/Report
# ------------------------------------------
-# if no rules for test execution are matched, pipeline will not have e2e test jobs
-# so we need to skip knapsack, allure and test resource deletion jobs as well
-.rules:app-or-qa-framework-changes-or-review-scenarios:
+.rules:prepare-report:
rules:
- - *app-changes
- - *qa-framework-changes
- - if: $QA_SUITES =~ /Test::Instance::Smoke/
- - if: $QA_SUITES =~ /Test::Instance::ReviewBlocking/
- - if: $QA_SUITES =~ /Test::Instance::ReviewNonBlocking/
+ - when: always
+
+.rules:notify-slack:
+ rules:
+ - <<: *default-branch
+ when: on_failure
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 46e62829394..aefa96da159 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -1,6 +1,3 @@
-include:
- - remote: 'https://gitlab.com/gitlab-org/modelops/applied-ml/review-recommender/ci-templates/-/raw/v0.2.1/recommender/Reviewers.gitlab-ci.yml'
-
review-cleanup:
extends:
- .default-retry
@@ -20,7 +17,7 @@ review-cleanup:
script:
- delete_release
- delete_namespace
- - ruby -rrubygems scripts/review_apps/automated_cleanup.rb
+ - scripts/review_apps/automated_cleanup.rb
- gcp_cleanup
start-review-app-pipeline:
@@ -72,14 +69,14 @@ review-app-test-results:
danger-review:
extends:
- .default-retry
- - .danger-review-cache
+ - .ruby-node-cache
- .review:rules:danger
stage: test
needs: []
before_script:
- source scripts/utils.sh
- bundle_install_script "--with danger"
- - run_timed_command "retry yarn install --frozen-lockfile"
+ - yarn_install_script
script:
# ${DANGER_DANGERFILE} is used by Jihulab for customizing danger support: https://jihulab.com/gitlab-cn/gitlab/-/blob/main-jh/jh/.gitlab-ci.yml
- >
@@ -96,12 +93,3 @@ danger-review-local:
- .review:rules:danger-local
script:
- run_timed_command danger_as_local
-
-reviewers-recommender:
- extends:
- - .default-retry
- # extends generated values cannot overwrite values from included files
- # Use !reference as a workaround here
- rules: !reference [".review:rules:reviewers-recommender", rules]
- stage: test
- needs: []
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 9dc2f5eff23..afe900f39a6 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -31,11 +31,14 @@
.if-merge-request: &if-merge-request
if: '$CI_MERGE_REQUEST_IID'
+# Once https://gitlab.com/gitlab-org/gitlab/-/issues/373904 is implemented, we should be able to change this back to
+# if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_APPROVALS_COUNT > 0'
+# or any similar condition to check that the MR has *any* approval (not just required approval).
.if-merge-request-approved: &if-merge-request-approved
- if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_APPROVED'
+ if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-full-rspec/'
.if-merge-request-not-approved: &if-merge-request-not-approved
- if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_APPROVED != "true"'
+ if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-full-rspec/'
.if-automated-merge-request: &if-automated-merge-request
if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "release-tools/update-gitaly" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /stable-ee$/'
@@ -70,9 +73,6 @@
.if-merge-request-labels-skip-undercoverage: &if-merge-request-labels-skip-undercoverage
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:skip-undercoverage/'
-.if-merge-request-labels-community-contribution: &if-merge-request-labels-community-contribution
- if: '$CI_MERGE_REQUEST_LABELS =~ /Community contribution/'
-
.if-merge-request-labels-jh-contribution: &if-merge-request-labels-jh-contribution
if: '$CI_MERGE_REQUEST_LABELS =~ /JiHu contribution/'
@@ -130,6 +130,9 @@
.if-dot-com-gitlab-org-and-security-tag: &if-dot-com-gitlab-org-and-security-tag
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG'
+.if-ruby3-branch: &if-ruby3-branch
+ if: '$CI_COMMIT_BRANCH == "ruby3"'
+
# For Security merge requests, the gitlab-release-tools-bot triggers a new
# pipeline for the "Pipelines for merged results" feature. If the pipeline
# fails, we notify release managers.
@@ -179,6 +182,7 @@
- "GITLAB_WORKHORSE_VERSION"
- "workhorse/**/*"
- ".gitlab/ci/workhorse.gitlab-ci.yml"
+ - "spec/support/gitlab-git-test.git/**/*"
.yaml-lint-patterns: &yaml-lint-patterns
- "*.yml"
@@ -246,8 +250,21 @@
- "babel.config.js"
- "config/webpack.config.js"
- "config/**/*.js"
+ - "{,ee/,jh/}app/assets/**/*"
- "vendor/assets/**/*"
+
+# This list should match the list in Tasks::Gitlab::Assets.assets_impacting_compilation
+.assets-compilation-patterns: &assets-compilation-patterns
+ - "{package.json,yarn.lock}"
+ - ".browserslistrc"
+ - "babel.config.js"
+ - "config/webpack.config.js"
+ - "*.js"
+ - "config/**/*.js"
+ - "locale/**/gitlab.po"
- "{,ee/,jh/}app/assets/**/*"
+ - "fixtures/emojis/**/*"
+ - "vendor/assets/**/*"
.frontend-patterns-for-as-if-foss: &frontend-patterns-for-as-if-foss
- "{package.json,yarn.lock}"
@@ -516,7 +533,7 @@
- "vendor/assets/javascripts/**/*"
.feature-flag-development-config-patterns: &feature-flag-development-config-patterns
- - "{,ee/}config/feature_flags/{development,ops}/*.yml"
+ - "{,ee/,jh/}config/feature_flags/{development,ops}/*.yml"
##################
# Conditions set #
@@ -532,9 +549,6 @@
rules:
- <<: *if-merge-request-approved
when: never
- # Temporarily disabled minimal rspec jobs before and after approval because of https://gitlab.com/gitlab-org/gitlab/-/issues/373064.
- - <<: *if-merge-request-not-approved
- when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-security-merge-request
@@ -550,12 +564,12 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
- <<: *if-security-merge-request
changes: *backend-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
.rails:rules:as-if-foss-migration-unit-integration:minimal-default-rules:
rules:
@@ -579,12 +593,12 @@
changes: *core-backend-patterns
- <<: *if-merge-request
changes: *workhorse-patterns
- - <<: *if-merge-request
- 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
.rails:rules:system:minimal-default-rules:
rules:
@@ -629,8 +643,6 @@
######################
.build-images:rules:build-qa-image:
rules:
- - <<: *if-not-ee
- when: never
- <<: *if-not-canonical-namespace
when: never
- <<: *if-merge-request-targeting-stable-branch
@@ -643,6 +655,7 @@
- <<: *if-default-branch-or-tag
- <<: *if-dot-com-gitlab-org-schedule
- <<: *if-force-ci
+ - <<: *if-ruby3-branch
.build-images:rules:build-assets-image:
rules:
@@ -651,9 +664,60 @@
- <<: *if-merge-request-targeting-stable-branch
- <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
+ - <<: *if-ruby3-branch
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
+#################
+# Caching rules #
+#################
+.caching:rules:cache-workhorse:
+ rules:
+ # That would run for any project that has a "maintenance" pipeline schedule
+ # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
+ - <<: *if-default-branch-schedule-maintenance
+ - <<: *if-dot-com-gitlab-org-default-branch
+ changes: ["workhorse/**/*"]
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes:
+ - ".gitlab/ci/caching.gitlab-ci.yml"
+ - "scripts/gitlab_component_helpers.sh"
+ when: manual
+ allow_failure: true
+
+.caching:rules:cache-assets:
+ rules:
+ # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
+ - if: '$CACHE_ASSETS_AS_PACKAGE != "true"'
+ when: never
+ # That would run for any project that has a "maintenance" pipeline schedule
+ # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
+ - <<: *if-default-branch-schedule-maintenance
+ - <<: *if-dot-com-gitlab-org-default-branch
+ changes: *assets-compilation-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes:
+ - ".gitlab/ci/caching.gitlab-ci.yml"
+ - "scripts/gitlab_component_helpers.sh"
+ - "lib/tasks/gitlab/assets.rake"
+ when: manual
+ allow_failure: true
+
+.caching:rules:packages-cleanup:
+ rules:
+ # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
+ - if: '$CACHE_ASSETS_AS_PACKAGE != "true"'
+ when: never
+ # That would run for any project that has a "maintenance" pipeline schedule
+ # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
+ - <<: *if-default-branch-schedule-maintenance
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes:
+ - ".gitlab/ci/caching.gitlab-ci.yml"
+ - "scripts/packages/automated_cleanup.rb"
+ when: manual
+ allow_failure: true
+
######################
# CI Templates Rules #
######################
@@ -768,8 +832,6 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *startup-css-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
.frontend:rules:frontend_fixture-as-if-foss:
rules:
@@ -906,8 +968,6 @@
changes: *code-qa-patterns
- <<: *if-merge-request-labels-as-if-foss
- <<: *if-merge-request-labels-run-all-rspec
- - <<: *if-merge-request
- changes: *ci-patterns
.qa:rules:internal-as-if-foss:
rules:
@@ -928,6 +988,7 @@
allow_failure: true
- <<: *if-force-ci
allow_failure: true
+ - <<: *if-ruby3-branch
.qa:rules:package-and-test:
rules:
@@ -939,6 +1000,8 @@
when: never
- <<: *if-merge-request-targeting-stable-branch
allow_failure: true
+ - <<: *if-ruby3-branch
+ allow_failure: true
- <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
changes: *feature-flag-development-config-patterns
when: manual
@@ -975,16 +1038,6 @@
###############
# Rails rules #
###############
-.rails:rules:build-components:
- rules:
- - <<: *if-dot-com-ee-schedule
- - <<: *if-dot-com-gitlab-org-default-branch
- changes:
- - "workhorse/**/*"
- - <<: *if-dot-com-gitlab-org-merge-request
- when: manual
- allow_failure: true
-
.rails:rules:setup-test-env:
rules:
- changes: *setup-test-env-patterns
@@ -1009,8 +1062,6 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
# When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
@@ -1019,6 +1070,8 @@
changes: *db-patterns
- <<: *if-security-merge-request
changes: *db-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
- changes: *db-patterns
.rails:rules:ee-and-foss-migration:minimal:
@@ -1112,8 +1165,6 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
# When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request
@@ -1122,6 +1173,8 @@
changes: *db-patterns
- <<: *if-security-merge-request
changes: *db-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
- changes: *db-patterns
.rails:rules:ee-only-migration:minimal:
@@ -1201,8 +1254,6 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *core-backend-patterns
- - <<: *if-merge-request
- changes: *ci-patterns
# When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
- <<: *if-merge-request-labels-as-if-foss
@@ -1211,6 +1262,8 @@
changes: *db-patterns
- <<: *if-security-merge-request
changes: *db-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
.rails:rules:as-if-foss-migration:minimal:
rules:
@@ -1416,9 +1469,6 @@
- if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true" || $RETRY_FAILED_TESTS_IN_NEW_PROCESS == "true"'
changes: *code-backstage-patterns
when: always
- - if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true" || $RETRY_FAILED_TESTS_IN_NEW_PROCESS == "true"'
- changes: *ci-patterns
- when: always
#########################
# Static analysis rules #
@@ -1482,6 +1532,12 @@
changes: ["vendor/gems/mail-smtp_pool/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
+.vendor:rules:attr_encrypted:
+ rules:
+ - <<: *if-merge-request
+ changes: ["vendor/gems/attr_encrypted/**/*"]
+ - <<: *if-merge-request-labels-run-all-rspec
+
.vendor:rules:microsoft_graph_mailer:
rules:
- <<: *if-merge-request
@@ -1518,12 +1574,6 @@
changes: ["vendor/gems/omniauth-gitlab/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
-.vendor:rules:omniauth-google-oauth2:
- rules:
- - <<: *if-merge-request
- changes: ["vendor/gems/omniauth-google-oauth2/**/*"]
- - <<: *if-merge-request-labels-run-all-rspec
-
.vendor:rules:omniauth-salesforce:
rules:
- <<: *if-merge-request
@@ -1660,7 +1710,7 @@
rules:
- if: '$LICENSE_MANAGEMENT_DISABLED || $GITLAB_FEATURES !~ /\blicense_scanning\b/'
when: never
- - changes: *code-backstage-qa-patterns
+ - changes: *dependency-patterns
################
# Review rules #
@@ -1783,14 +1833,6 @@
- <<: *if-merge-request
changes: *danger-patterns
-.review:rules:reviewers-recommender:
- rules:
- - <<: *if-not-canonical-namespace
- when: never
- - <<: *if-merge-request-labels-community-contribution
- when: never
- - <<: *if-merge-request
-
###############
# Setup rules #
###############
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 4f3111de2bf..e417b054cd6 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -30,7 +30,7 @@ cache gems:
.absolutely-minimal-job:
extends:
- .minimal-job
- image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge
variables:
GIT_STRATEGY: none
@@ -79,7 +79,7 @@ verify-ruby-2.7:
verify-tests-yml:
extends:
- .setup:rules:verify-tests-yml
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}-alpine3.13
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-alpine3.13
stage: test
needs: []
script:
@@ -116,7 +116,7 @@ generate-frontend-fixtures-mapping:
detect-tests:
extends: .rails:rules:detect-tests
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
needs: []
stage: prepare
variables:
@@ -134,14 +134,17 @@ detect-tests:
tooling/bin/find_changes ${RSPEC_CHANGED_FILES_PATH};
tooling/bin/find_tests ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_MATCHING_TESTS_PATH};
tooling/bin/find_changes ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_MATCHING_TESTS_PATH} ${FRONTEND_FIXTURES_MAPPING_PATH};
- echo "Changed files: $(cat $RSPEC_CHANGED_FILES_PATH)";
- echo "Related rspec tests: $(cat $RSPEC_MATCHING_TESTS_PATH)";
+ filter_rspec_matched_foss_tests ${RSPEC_MATCHING_TESTS_PATH} ${RSPEC_MATCHING_TESTS_FOSS_PATH};
+ echoinfo "Changed files: $(cat $RSPEC_CHANGED_FILES_PATH)";
+ echoinfo "Related RSpec tests: $(cat $RSPEC_MATCHING_TESTS_PATH)";
+ echoinfo "Related FOSS RSpec tests: $(cat $RSPEC_MATCHING_TESTS_FOSS_PATH)";
fi
artifacts:
expire_in: 7d
paths:
- ${RSPEC_CHANGED_FILES_PATH}
- ${RSPEC_MATCHING_TESTS_PATH}
+ - ${RSPEC_MATCHING_TESTS_FOSS_PATH}
- ${FRONTEND_FIXTURES_MAPPING_PATH}
detect-previous-failed-tests:
diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml
index e845e7eb88b..59ea665ae07 100644
--- a/.gitlab/ci/static-analysis.gitlab-ci.yml
+++ b/.gitlab/ci/static-analysis.gitlab-ci.yml
@@ -31,7 +31,7 @@ static-analysis:
- .static-analysis:rules:static-analysis
parallel: 2
script:
- - run_timed_command "retry yarn install --frozen-lockfile"
+ - yarn_install_script
- scripts/static-analysis
static-analysis as-if-foss:
@@ -84,7 +84,7 @@ eslint:
variables:
USE_BUNDLE_INSTALL: "false"
script:
- - run_timed_command "retry yarn install --frozen-lockfile"
+ - yarn_install_script
- run_timed_command "yarn run lint:eslint:all"
eslint as-if-foss:
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index f4fa39300b6..e147305e25a 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -1,5 +1,5 @@
.tests-metadata-state:
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}
before_script:
- source scripts/utils.sh
artifacts:
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index 577bd37ca9e..a22ac5337f6 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -6,6 +6,14 @@ vendor mail-smtp_pool:
include: vendor/gems/mail-smtp_pool/.gitlab-ci.yml
strategy: depend
+vendor attr_encrypted:
+ extends:
+ - .vendor:rules:attr_encrypted
+ needs: []
+ trigger:
+ include: vendor/gems/attr_encrypted/.gitlab-ci.yml
+ strategy: depend
+
vendor microsoft_graph_mailer:
extends:
- .vendor:rules:microsoft_graph_mailer
@@ -54,14 +62,6 @@ vendor omniauth-gitlab:
include: vendor/gems/omniauth-gitlab/.gitlab-ci.yml
strategy: depend
-vendor omniauth-google-oauth2:
- extends:
- - .vendor:rules:omniauth-google-oauth2
- needs: []
- trigger:
- include: vendor/gems/omniauth-google-oauth2/.gitlab-ci.yml
- strategy: depend
-
vendor omniauth-salesforce:
extends:
- .vendor:rules:omniauth-salesforce
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index efd37b2247b..a11d5f000cf 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -1,9 +1,10 @@
workhorse:verify:
extends: .workhorse:rules:workhorse
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.17
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}golang:${GO_VERSION}
stage: test
needs: []
script:
+ - go version
- make -C workhorse # test build
- make -C workhorse verify
@@ -12,7 +13,6 @@ workhorse:verify:
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}:git-2.36
variables:
GITALY_ADDRESS: "tcp://127.0.0.1:8075"
- GO_VERSION: "1.17"
stage: test
needs:
- setup-test-env
@@ -27,7 +27,7 @@ workhorse:test go:
extends: .workhorse:test
parallel:
matrix:
- - GO_VERSION: ["1.17", "1.18"]
+ - GO_VERSION: ["1.17", "1.18", "1.19"]
script:
- make -C workhorse test-coverage
coverage: '/\d+.\d+%/'
diff --git a/.gitlab/issue_templates/Actionable Insight - Exploration needed.md b/.gitlab/issue_templates/Actionable Insight - Exploration needed.md
index 76316fc626d..e410715909c 100644
--- a/.gitlab/issue_templates/Actionable Insight - Exploration needed.md
+++ b/.gitlab/issue_templates/Actionable Insight - Exploration needed.md
@@ -1,4 +1,4 @@
-<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights
+<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/product/ux/ux-research-training/research-insights/#actionable-insights
This issue template is for an actionable insight that requires further exploration.-->
diff --git a/.gitlab/issue_templates/Actionable Insight - Product change.md b/.gitlab/issue_templates/Actionable Insight - Product change.md
index 6c030220636..fba467afd0e 100644
--- a/.gitlab/issue_templates/Actionable Insight - Product change.md
+++ b/.gitlab/issue_templates/Actionable Insight - Product change.md
@@ -1,4 +1,4 @@
-<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights
+<!-- Actionable insights must recommend an action that needs to take place. An actionable insight both defines the insight and clearly calls out action or next step required to improve based on the result of the research observation or data. Actionable insights are tracked over time and will include follow-up. Please follow the tasks outlined in this issue for best results. Learn more in the handbook here: https://about.gitlab.com/handbook/product/ux/ux-research-training/research-insights/#actionable-insights
This issue template is for an actionable insight that requires a change in the product.-->
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index b9fed3745d1..1266ee7efe7 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -39,7 +39,10 @@ will also determine whether the bug is fixed in a more recent version. -->
### Output of checks
-<!-- If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com -->
+<!-- If you are reporting a bug on GitLab.com, uncomment below -->
+
+<!-- This bug happens on GitLab.com -->
+<!-- /label ~"reproduced on GitLab.com" -->
#### Results of GitLab environment info
diff --git a/.gitlab/issue_templates/Deprecations.md b/.gitlab/issue_templates/Deprecations.md
index 76c66a3a891..ef6764c3621 100644
--- a/.gitlab/issue_templates/Deprecations.md
+++ b/.gitlab/issue_templates/Deprecations.md
@@ -1,4 +1,4 @@
-For guidance on the overall deprecations, removals and breaking changes workflow, please visit https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features
+For guidance on the overall deprecations, removals and breaking changes workflow, please visit [Breaking changes, deprecations, and removing features](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features)
<!-- Use this template as a starting point for deprecations. -->
@@ -10,6 +10,9 @@ This should contain a brief description of the feature or functionality that is
It is recommended that you link to the documentation.
The description of the deprecation should state what actions the user should take to rectify the behavior. If the deprecation is scheduled for an upcoming release, the content should remain in the deprecations documentation page until it has been completed. For example, if a deprecation is announced in 14.9 and scheduled to be completed in 15.0, the same content would be included in the documentation for 14.9, 14.10, and 15.0.
+
+**If this issue proposes a breaking change outside a major release XX.0, you need to get approval from your manager and request collaboration from Product Operations on communication. Be sure to follow the guidance [here](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features.)**
+
-->
### Breaking Change
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index f3830a5cc10..a9f96a61d29 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -82,6 +82,7 @@ _Consider adding links to check for Sentry errors, Production logs for 5xx, 302s
### Preparation before global rollout
+- [ ] Set a milestone to the rollout issue to signal for enabling and removing the feature flag when it is stable.
- [ ] Check if the feature flag change needs to be accompanied with a
[change management issue](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#feature-flags-and-the-change-management-process).
Cross link the issue here if it does.
@@ -167,4 +168,11 @@ You can either [create a follow-up issue for Feature Flag Cleanup](https://gitla
/chatops run feature set <feature-flag-name> false
```
-/label ~"feature flag" ~"type::feature" ~"feature::addition"
+<!-- A feature flag can also be used for rolling out a bug fix or a maintenance work.
+In this scenario, labels must be related to it, for example; ~"type::feature", ~"type::bug" or ~"type::maintenance".
+Please use /copy_metadata to copy the labels from the issue you're rolling out. -->
+
+/label ~group::
+/label ~"feature flag"
+/assign me
+/due in 1 month
diff --git a/.gitlab/issue_templates/Feature proposal - detailed.md b/.gitlab/issue_templates/Feature proposal - detailed.md
index 48052ed49ea..9eac2ca27c5 100644
--- a/.gitlab/issue_templates/Feature proposal - detailed.md
+++ b/.gitlab/issue_templates/Feature proposal - detailed.md
@@ -37,7 +37,7 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
<!-- What is the single user experience workflow this problem addresses?
For example, "The user should be able to use the UI/API/.gitlab-ci.yml with GitLab to <perform a specific task>"
-https://about.gitlab.com/handbook/engineering/ux/ux-research-training/user-story-mapping/ -->
+https://about.gitlab.com/handbook/product/ux/ux-research-training/user-story-mapping/ -->
### Proposal
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 7ef5287aba8..6c9b8bb6d78 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
@@ -51,20 +51,16 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
bin/rails generate migration CreateCoolWidgetRegistry --database geo
```
-Geo should continue using `Gitlab::Database::Migration[1.0]` until the `gitlab_geo` schema is supported, and is for the time being exempt from being validated by `Gitlab::Database::Migration[2.0]`. This requires a developer to manually amend the migration file to change from `[2.0]` to `[1.0]` due to the migration defaults being 2.0.
-
-For more information, see the [Enable Geo migrations to use Migration[2.0]](https://gitlab.com/gitlab-org/gitlab/-/issues/363491) issue.
-
- [ ] Replace the contents of the migration file with the following. Note that we cannot add a foreign key constraint on `cool_widget_id` because the `cool_widgets` table is in a different database. The application code must handle logic such as propagating deletions.
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetRegistry < Gitlab::Database::Migration[1.0]
+ class CreateCoolWidgetRegistry < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
- ApplicationRecord.transaction do
+ Geo::TrackingBase.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
@@ -105,6 +101,13 @@ For more information, see the [Enable Geo migrations to use Migration[2.0]](http
```
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+
+- [ ] Add the new table to the GitLab Schema defined in [`ee/lib/ee/gitlab/database/gitlab_schemas.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/database/gitlab_schemas.yml).
+
+ ```yaml
+ cool_widget_registry: :gitlab_geo
+ ```
+
- [ ] Run Geo tracking database migrations:
```shell
@@ -141,7 +144,7 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.datetime_with_timezone :verified_at
- t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.references :cool_widget, primary_key: true, default: nil, index: 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'
@@ -162,6 +165,12 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Add the new table to the GitLab Schema defined in [`lib/gitlab/database/gitlab_schemas.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/gitlab_schemas.yml) with the databases they need to be added to.
+
+ ```yaml
+ cool_widget_states: :gitlab_main
+ ```
+
- [ ] Run database migrations:
```shell
@@ -260,7 +269,6 @@ That's all of the required database changes.
def pool_repository
nil
end
- ...
def cool_widget_state
super || build_cool_widget_state
@@ -380,14 +388,16 @@ That's all of the required database changes.
```ruby
# frozen_string_literal: true
- class Geo::CoolWidgetRegistry < Geo::BaseRegistry
- include ::Geo::ReplicableRegistry
- include ::Geo::VerifiableRegistry
+ module Geo
+ class CoolWidgetRegistry < Geo::BaseRegistry
+ include ::Geo::ReplicableRegistry
+ include ::Geo::VerifiableRegistry
- MODEL_CLASS = ::CoolWidget
- MODEL_FOREIGN_KEY = :cool_widget_id
+ MODEL_CLASS = ::CoolWidget
+ MODEL_FOREIGN_KEY = :cool_widget_id
- belongs_to :cool_widget, class_name: 'CoolWidget'
+ belongs_to :cool_widget, class_name: 'CoolWidget'
+ end
end
```
@@ -454,13 +464,13 @@ That's all of the required database changes.
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
- trait(:verification_succeeded) do
+ trait :verification_succeeded do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
- trait(:verification_failed) do
+ trait :verification_failed do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
@@ -498,11 +508,11 @@ That's all of the required database changes.
factory :geo_cool_widget_state, class: 'Geo::CoolWidgetState' do
cool_widget
- trait(:checksummed) do
+ trait :checksummed do
verification_checksum { 'abc' }
end
- trait(:checksum_failure) do
+ trait :checksum_failure do
verification_failure { 'Could not calculate the checksum' }
end
end
@@ -552,8 +562,9 @@ The GraphQL API is used by `Admin > Geo > Replication Details` views, and is dir
field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
- description: 'Find Cool Widget registries on this Geo node',
- feature_flag: :geo_cool_widget_replication
+ description: 'Find Cool Widget registries on this Geo node. '\
+ 'Ignored if `geo_cool_widget_replication` feature flag is disabled.',
+ alpha: { milestone: '15.5' } # Update the milestone
```
- [ ] Add the new `cool_widget_registries` field name to the `expected_fields` array in `ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
@@ -618,13 +629,15 @@ The GraphQL API is used by `Admin > Geo > Replication Details` views, and is dir
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class CoolWidgetRegistryType < BaseObject
+ graphql_name 'CoolWidgetRegistry'
+
include ::Types::Geo::RegistryType
- graphql_name 'CoolWidgetRegistry'
description 'Represents the Geo replication and verification state of a cool_widget'
field :cool_widget_id, GraphQL::Types::ID, null: false, description: 'ID of the Cool Widget.'
end
+ # rubocop:enable Graphql/AuthorizeTypes
end
end
```
@@ -708,14 +721,15 @@ As illustrated by the above two examples, batch destroy logic cannot be handled
- [ ] Add a step to `Test replication and verification of Cool Widgets on a non-GDK-deployment. For example, using GitLab Environment Toolkit`.
- [ ] Add a step to `Ping the Geo PM and EM to coordinate testing`. For example, you might add steps to generate Cool Widgets, and then a Geo engineer may take it from there.
- [ ] In `ee/config/feature_flags/development/geo_cool_widget_replication.yml`, set `default_enabled: true`
-- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
+- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `alpha` option for the released type:
```ruby
field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
- description: 'Find Cool Widget registries on this Geo node',
- feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
+ description: 'Find Cool Widget registries on this Geo node. '\
+ 'Ignored if `geo_cool_widget_replication` feature flag is disabled.',
+ alpha: { milestone: '15.5' } # Update the milestone
```
- [ ] Run `bundle exec rake gitlab:graphql:compile_docs` after the step above to regenerate the GraphQL docs.
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 17a4dd4bc3e..76fe1772921 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -53,20 +53,16 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
bin/rails generate migration CreateCoolWidgetRegistry --database geo
```
-Geo should continue using `Gitlab::Database::Migration[1.0]` until the `gitlab_geo` schema is supported, and is for the time being exempt from being validated by `Gitlab::Database::Migration[2.0]`. This requires a developer to manually amend the migration file to change from `[2.0]` to `[1.0]` due to the migration defaults being 2.0.
-
-For more information, see the [Enable Geo migrations to use Migration[2.0]](https://gitlab.com/gitlab-org/gitlab/-/issues/363491) issue.
-
- [ ] Replace the contents of the migration file with the following. Note that we cannot add a foreign key constraint on `cool_widget_id` because the `cool_widgets` table is in a different database. The application code must handle logic such as propagating deletions.
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetRegistry < Gitlab::Database::Migration[1.0]
+ class CreateCoolWidgetRegistry < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
- ApplicationRecord.transaction do
+ Geo::TrackingBase.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
@@ -105,6 +101,13 @@ For more information, see the [Enable Geo migrations to use Migration[2.0]](http
```
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+
+- [ ] Add the new table to the GitLab Schema defined in [`ee/lib/ee/gitlab/database/gitlab_schemas.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/database/gitlab_schemas.yml).
+
+ ```yaml
+ cool_widget_registry: :gitlab_geo
+ ```
+
- [ ] Run Geo tracking database migrations:
```shell
@@ -143,7 +146,7 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.datetime_with_timezone :verified_at
- t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.references :cool_widget, primary_key: true, default: nil, index: 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'
@@ -164,6 +167,12 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Add the new table to the GitLab Schema defined in [`lib/gitlab/database/gitlab_schemas.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/gitlab_schemas.yml) with the databases they need to be added to.
+
+ ```yaml
+ cool_widget_states: :gitlab_main
+ ```
+
- [ ] Run database migrations:
```shell
@@ -238,7 +247,8 @@ That's all of the required database changes.
# we want to know which records to replicate. This is not easy to automate
# because for example:
#
- # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
+ # * The "selective sync" feature allows admins to choose which namespaces
+ # to replicate, per secondary site. Most Models are scoped to a
# namespace, but the nature of the relationship to a namespace varies
# between Models.
# * The "selective sync" feature allows admins to choose which shards to
@@ -256,7 +266,6 @@ That's all of the required database changes.
CoolWidgetState
end
end
- ...
def cool_widget_state
super || build_cool_widget_state
@@ -308,7 +317,7 @@ That's all of the required database changes.
end
```
-- [ ] Generate the feature flag definition fileы by running the feature flag commands 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'
@@ -346,14 +355,16 @@ That's all of the required database changes.
```ruby
# frozen_string_literal: true
- class Geo::CoolWidgetRegistry < Geo::BaseRegistry
- include ::Geo::ReplicableRegistry
- include ::Geo::VerifiableRegistry
+ module Geo
+ class CoolWidgetRegistry < Geo::BaseRegistry
+ include ::Geo::ReplicableRegistry
+ include ::Geo::VerifiableRegistry
- MODEL_CLASS = ::CoolWidget
- MODEL_FOREIGN_KEY = :cool_widget_id
+ MODEL_CLASS = ::CoolWidget
+ MODEL_FOREIGN_KEY = :cool_widget_id
- belongs_to :cool_widget, class_name: 'CoolWidget'
+ belongs_to :cool_widget, class_name: 'CoolWidget'
+ end
end
```
@@ -420,13 +431,13 @@ That's all of the required database changes.
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
- trait(:verification_succeeded) do
+ trait :verification_succeeded do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
- trait(:verification_failed) do
+ trait :verification_failed do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
@@ -438,6 +449,8 @@ That's all of the required database changes.
- [ ] Following [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309) add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
``` ruby
+ # frozen_string_literal: true
+
module Geo
class CoolWidgetState < ApplicationRecord
include EachBatch
@@ -462,11 +475,11 @@ That's all of the required database changes.
factory :geo_cool_widget_state, class: 'Geo::CoolWidgetState' do
cool_widget
- trait(:checksummed) do
+ trait :checksummed do
verification_checksum { 'abc' }
end
- trait(:checksum_failure) do
+ trait :checksum_failure do
verification_failure { 'Could not calculate the checksum' }
end
end
@@ -516,8 +529,9 @@ The GraphQL API is used by `Admin > Geo > Replication Details` views, and is dir
field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
- description: 'Find Cool Widget registries on this Geo node',
- feature_flag: :geo_cool_widget_replication
+ description: 'Find Cool Widget registries on this Geo node. '\
+ 'Ignored if `geo_cool_widget_replication` feature flag is disabled.',
+ alpha: { milestone: '15.5' } # Update the milestone
```
- [ ] Add the new `cool_widget_registries` field name to the `expected_fields` array in `ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
@@ -582,13 +596,15 @@ The GraphQL API is used by `Admin > Geo > Replication Details` views, and is dir
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class CoolWidgetRegistryType < BaseObject
+ graphql_name 'CoolWidgetRegistry'
+
include ::Types::Geo::RegistryType
- graphql_name 'CoolWidgetRegistry'
description 'Represents the Geo replication and verification state of a cool_widget'
- field :cool_widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Cool Widget'
+ field :cool_widget_id, GraphQL::Types::ID, null: false, description: 'ID of the Cool Widget.'
end
+ # rubocop:enable Graphql/AuthorizeTypes
end
end
```
@@ -673,14 +689,15 @@ As illustrated by the above two examples, batch destroy logic cannot be handled
- [ ] Add a step to `Test replication and verification of Cool Widgets on a non-GDK-deployment. For example, using GitLab Environment Toolkit`.
- [ ] Add a step to `Ping the Geo PM and EM to coordinate testing`. For example, you might add steps to generate Cool Widgets, and then a Geo engineer may take it from there.
- [ ] In `ee/config/feature_flags/development/geo_cool_widget_replication.yml`, set `default_enabled: true`
-- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
+- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `alpha` option for the released type:
```ruby
field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
- description: 'Find Cool Widget registries on this Geo node',
- feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
+ description: 'Find Cool Widget registries on this Geo node. '\
+ 'Ignored if `geo_cool_widget_replication` feature flag is disabled.',
+ alpha: { milestone: '15.5' } # Update the milestone
```
- [ ] Run `bundle exec rake gitlab:graphql:compile_docs` after the step above to regenerate the GraphQL docs.
diff --git a/.gitlab/issue_templates/QA Failure.md b/.gitlab/issue_templates/QA Failure.md
index 3171923d8c5..bcfe7c42e90 100644
--- a/.gitlab/issue_templates/QA Failure.md
+++ b/.gitlab/issue_templates/QA Failure.md
@@ -56,6 +56,9 @@ If you include multiple screenshots it can be helpful to hide all but the first
<!-- Base labels. -->
/label ~Quality ~QA ~test
+<!-- Work classification type label, please apply ignore type label until the investigation is complete and an [issue type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) is determined.-->
+/label ~"type::ignore"
+
<!-- Test failure type label, please use just one.-->
/label ~"failure::broken-test" ~"failure::flaky-test" ~"failure::stale-test" ~"failure::test-environment" ~"failure::investigating" ~"failure::new"
diff --git a/.gitlab/issue_templates/Solution Validation.md b/.gitlab/issue_templates/Solution Validation.md
index 27f97d8dd12..e7ab7fe820f 100644
--- a/.gitlab/issue_templates/Solution Validation.md
+++ b/.gitlab/issue_templates/Solution Validation.md
@@ -26,7 +26,7 @@
<!-- #### TODO Checklist
Consider adding a checklist in order to keep track of what stage the research is up to. Some possible checklist templates are here:
- https://about.gitlab.com/handbook/engineering/ux/ux-research-training/templates-resources-for-research-studies/#checklists
+ https://about.gitlab.com/handbook/product/ux/ux-research-training/templates-resources-for-research-studies/#checklists
-->
/label ~"workflow::solution validation" \ No newline at end of file
diff --git a/.gitlab/issue_templates/UX Theme.md b/.gitlab/issue_templates/UX Theme.md
index 043cb705352..2ba60523e20 100644
--- a/.gitlab/issue_templates/UX Theme.md
+++ b/.gitlab/issue_templates/UX Theme.md
@@ -1,6 +1,6 @@
<!-- A majority of the work designers do will be on themes in the (Now) Next 1-3 milestone column. These themes are comprised of high-confidence outcomes and validated needs. The UX theme issue is where collaboration should occur, including plans and discussion on subthemes, research, and design feedback. Related issues for design exploration and solution validation should stem from the theme issue.
-One of the advantages of working with UX themes is that it allows us to think and design holistically by designing the theme as a whole as opposed to a single issue at a time trying to piece them together as you go. For more details please refer to this section of the handbook when creating UX Themes: https://about.gitlab.com/handbook/engineering/ux/product-design/ux-roadmaps/#theme-structure -->
+One of the advantages of working with UX themes is that it allows us to think and design holistically by designing the theme as a whole as opposed to a single issue at a time trying to piece them together as you go. For more details please refer to this section of the handbook when creating UX Themes: https://about.gitlab.com/handbook/product/ux/product-design/ux-roadmaps/#theme-structure -->
### UX Theme
<!-- A theme is written as a statement that combines the beneficiary, their need, and the expected outcome when the work is delivered. Well-defined statements are concise without sacrificing the substance of the theme so that anyone can understand it at a glance. (For instance; Reduce the effort for security teams to identify and escalate business-critical risks)
@@ -37,7 +37,7 @@ One of the advantages of working with UX themes is that it allows us to think an
#### Confidence
-<!-- How well do we understand the user's problem and their need? Refer to https://about.gitlab.com/handbook/engineering/ux/product-design/ux-roadmaps/#confidence to assess confidence -->
+<!-- How well do we understand the user's problem and their need? Refer to https://about.gitlab.com/handbook/product/ux/product-design/ux-roadmaps/#confidence to assess confidence -->
| Confidence | Research |
@@ -55,7 +55,7 @@ Note: This is not a backlog. If the subthemes can not be delivered in the theme
Note: if feature issues already exist then you can add them to this table. Keep in mind that subthemes require validation if they are assumptive
-Refer to https://about.gitlab.com/handbook/engineering/ux/product-designer/#ux-issue-weights for calculating UX weights.
+Refer to https://about.gitlab.com/handbook/product/ux/product-designer/#ux-issue-weights for calculating UX weights.
-->
| Issue | UX Weight |
diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md
index dcd5d79e0d0..6a5ee6e74e7 100644
--- a/.gitlab/merge_request_templates/Deprecations.md
+++ b/.gitlab/merge_request_templates/Deprecations.md
@@ -56,7 +56,7 @@ feature for all reviews. Reviewers will then `approve` the MR and remove themsel
- [ ] (Recommended) PMM
- [ ] (Optional) Product Designer
- [ ] (Optional) Group Manager or Director
-- [ ] Required review and approval: [Technical Writer designated to the corresponding DevOps stage/group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+- [ ] Required review and approval: [Technical Writer designated to the corresponding DevOps stage/group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
### Tech writer review
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 4932fbd7f26..2096b06d73b 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -8,7 +8,7 @@
## Author's checklist
-- [ ] Optional. Consider taking [the GitLab Technical Writing Fundamentals course](https://about.gitlab.com/handbook/engineering/ux/technical-writing/fundamentals/).
+- [ ] Optional. Consider taking [the GitLab Technical Writing Fundamentals course](https://about.gitlab.com/handbook/product/ux/technical-writing/fundamentals/).
- [ ] Follow the:
- [Documentation process](https://docs.gitlab.com/ee/development/documentation/workflow.html).
- [Documentation guidelines](https://docs.gitlab.com/ee/development/documentation/).
@@ -16,7 +16,7 @@
- [ ] If you're adding or changing the main heading of the page (H1), ensure that the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#product-tier-badges) is added.
- [ ] If you are a GitLab team member, [request a review](https://docs.gitlab.com/ee/development/code_review.html#dogfooding-the-attention-request-feature) based on:
- The documentation page's [metadata](https://docs.gitlab.com/ee/development/documentation/#metadata).
- - The [associated Technical Writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+ - The [associated Technical Writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
If you are a GitLab team member and only adding documentation, do not add any of the following labels:
@@ -34,7 +34,7 @@ Documentation-related MRs should be reviewed by a Technical Writer for a non-blo
- [ ] If the content requires it, ensure the information is reviewed by a subject matter expert.
- Technical writer review items:
- [ ] Ensure docs metadata is present and up-to-date.
- - [ ] Ensure the appropriate [labels](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#labels) are added to this MR.
+ - [ ] Ensure the appropriate [labels](https://about.gitlab.com/handbook/product/ux/technical-writing/workflow/#labels) are added to this MR.
- [ ] Ensure a release milestone is set.
- If relevant to this MR, ensure [content topic type](https://docs.gitlab.com/ee/development/documentation/structure.html) principles are in use, including:
- [ ] The headings should be something you'd do a Google search for. Instead of `Default behavior`, say something like `Default behavior when you close an issue`.
diff --git a/.gitlab/merge_request_templates/Removals.md b/.gitlab/merge_request_templates/Removals.md
index 4801af2a123..afe95f853bc 100644
--- a/.gitlab/merge_request_templates/Removals.md
+++ b/.gitlab/merge_request_templates/Removals.md
@@ -61,7 +61,7 @@ feature for all reviews. Reviewers will `approve` the MR and remove themselves f
- [ ] (Recommended) PMM
- [ ] (Optional) Product Designer
- [ ] (Optional) Group Manager or Director
-- [ ] Required review and approval: [Technical Writer designated to the corresponding DevOps stage/group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+- [ ] Required review and approval: [Technical Writer designated to the corresponding DevOps stage/group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
### Tech writer review
diff --git a/.gitpod.yml b/.gitpod.yml
index 3fb623b9fb6..535c60b42c8 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -86,7 +86,7 @@ tasks:
printf "$(date) – GitLab is up (took ~%.1f minutes)\n" "$((10*$SECONDS/60))e-1" | tee -a /workspace/startup.log
gp preview $(gp url 3000) || true
PREBUILD_LOG=(/workspace/.gitpod/prebuild-log-*)
- [[ -f /workspace/gitpod_start_time.sh ]] && printf "Took %.1f minutes from https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml being executed through to completion %s\n" "$((10*(($(date +%s)-${START_TIME_IN_SECONDS}))/60))e-1" "$([[ -f "$PREBUILD_LOG" ]] && echo "With Prebuilds")"
+ [[ -f /workspace/gitpod_start_time.sh ]] && printf "Took %.1f minutes from https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml being executed through to completion %s\n" "$((10*(($(date +%s)-${START_TIME_IN_SECONDS}))/60))e-1" "$([[ -f "$PREBUILD_LOG" ]] && echo "With Prebuilds")"
)
ports:
@@ -111,10 +111,10 @@ ports:
vscode:
extensions:
- - rebornix.ruby@0.28.0
- - wingrunr21.vscode-ruby@0.27.0
- - karunamurti.haml@1.3.1
- - octref.vetur@0.34.1
- - dbaeumer.vscode-eslint@2.1.8
- - gitlab.gitlab-workflow@3.24.0
- - DavidAnson.vscode-markdownlint@0.44.4
+ - rebornix.ruby@0.28.1
+ - wingrunr21.vscode-ruby@0.28.0
+ - karunamurti.haml@1.4.1
+ - octref.vetur@0.36.0
+ - dbaeumer.vscode-eslint@2.2.6
+ - GitLab.gitlab-workflow@3.48.1
+ - DavidAnson.vscode-markdownlint@0.47.0
diff --git a/.haml-lint.yml b/.haml-lint.yml
index 7d772831b2c..60f86eb4158 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -101,6 +101,7 @@ linters:
- Style/IfUnlessModifier
- Style/IndentationWidth
- Style/Next
+ - Style/SoleNestedConditional
- Style/TrailingWhitespace
- Style/WhileUntilModifier
- Cop/StaticTranslationDefinition
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index 9f201dcc289..ce4f697300f 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -1,7 +1,19 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
-# on 2021-04-01 00:00:00 +0000 using Haml-Lint version 0.36.0.
+# on 2022-09-15 12:13:31 +0000 using Haml-Lint version 0.40.1.
# The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again.
+
+linters:
+
+ # Offense count: 11
+ RuboCop:
+ exclude:
+ - "app/views/layouts/_page.html.haml"
+ - "app/views/layouts/header/_default.html.haml"
+ - "app/views/projects/merge_requests/dropdowns/_branch.html.haml"
+ - "app/views/projects/merge_requests/dropdowns/_project.html.haml"
+ - "app/views/shared/_flash_user_callout.html.haml"
+ - "app/views/shared/_label.html.haml" \ No newline at end of file
diff --git a/.projections.json.example b/.projections.json.example
index dc1b42b917a..5a5c87704c1 100644
--- a/.projections.json.example
+++ b/.projections.json.example
@@ -1,5 +1,7 @@
{
"ee/*": { "type": "ee" },
+ "app/*": { "type": "ce" },
+ "lib/*": { "type": "ce" },
"config/initializers/*.rb": {
"alternate": "spec/initializers/{}_spec.rb",
"type": "source"
@@ -57,37 +59,40 @@
"type": "source"
},
"app/presenters/*.rb": {
+ "alternate": "spec/app/presenters/{}_spec.rb",
"related": "ee/app/presenters/ee/{}.rb",
"type": "source"
},
"app/serializers/*.rb": {
+ "alternate": "spec/app/serializers/{}_spec.rb",
"related": "ee/app/serializers/ee/{}.rb",
"type": "source"
},
"app/services/*.rb": {
+ "alternate": "spec/app/services/{}_spec.rb",
"related": "ee/app/services/ee/{}.rb",
"type": "source"
},
"app/uploaders/*.rb": {
+ "alternate": "spec/app/uploaders/{}_spec.rb",
"related": "ee/app/uploaders/ee/{}.rb",
"type": "source"
},
"app/validators/*.rb": {
+ "alternate": "spec/app/validators/{}_spec.rb",
"related": "ee/app/validators/ee/{}.rb",
"type": "source"
},
"app/views/*.rb": {
+ "alternate": "spec/app/views/{}_spec.rb",
"related": "ee/app/views/ee/{}.rb",
"type": "source"
},
"app/workers/*.rb": {
+ "alternate": "spec/app/workers/{}_spec.rb",
"related": "ee/app/workers/ee/{}.rb",
"type": "source"
},
- "app/*.rb": {
- "alternate": "spec/{}_spec.rb",
- "type": "source"
- },
"spec/*_spec.rb": {
"alternate": "app/{}.rb",
"type": "test"
@@ -124,8 +129,79 @@
"alternate": "ee/lib/api/{}.rb",
"type": "test"
},
+ "ee/app/controllers/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/controllers/{}.rb",
+ "type": "source"
+ },
+ "ee/app/finders/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/finders/{}.rb",
+ "type": "source"
+ },
+ "ee/app/graphql/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/graphql/{}.rb",
+ "type": "source"
+ },
+ "ee/app/helpers/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/helpers/{}.rb",
+ "type": "source"
+ },
+ "ee/app/mailers/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/mailers/{}.rb",
+ "type": "source"
+ },
+ "ee/app/models/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/models/{}.rb",
+ "type": "source"
+ },
+ "ee/app/policies/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/policies/{}.rb",
+ "type": "source"
+ },
+ "ee/app/presenters/ee/*.rb": {
+ "alternate": "ee/spec/{}_spec.rb",
+ "related": "app/presenters/{}.rb",
+ "type": "source"
+ },
+ "ee/app/serializers/ee/*.rb": {
+ "alternate": "spec/app/serializers/{}_spec.rb",
+ "related": "app/serializers/{}.rb",
+ "type": "source"
+ },
+ "ee/app/services/ee/*.rb": {
+ "alternate": "spec/app/services/{}_spec.rb",
+ "related": "app/services/{}.rb",
+ "type": "source"
+ },
+ "ee/app/uploaders/ee/*.rb": {
+ "alternate": "spec/app/uploaders/{}_spec.rb",
+ "related": "app/uploaders/{}.rb",
+ "type": "source"
+ },
+ "ee/app/validators/ee/*.rb": {
+ "alternate": "spec/app/validators/{}_spec.rb",
+ "related": "app/validators/{}.rb",
+ "type": "source"
+ },
+ "ee/app/views/ee/*.rb": {
+ "alternate": "spec/app/views/{}_spec.rb",
+ "related": "app/views/{}.rb",
+ "type": "source"
+ },
+ "ee/app/workers/ee/*.rb": {
+ "alternate": "spec/app/workers/{}_spec.rb",
+ "related": "app/workers/{}.rb",
+ "type": "source"
+ },
"ee/app/*.rb": {
"alternate": "ee/spec/{}_spec.rb",
+ "related": "app/{}.rb",
"type": "source"
},
"ee/spec/*_spec.rb": {
@@ -136,6 +212,11 @@
"alternate": "ee/spec/lib/{}_spec.rb",
"type": "source"
},
+ "ee/lib/ee/*.rb": {
+ "alternate": "ee/spec/lib/{}_spec.rb",
+ "related": "lib/{}.rb",
+ "type": "source"
+ },
"ee/spec/lib/*_spec.rb": {
"alternate": "ee/lib/{}.rb",
"type": "test"
@@ -154,16 +235,18 @@
},
"ee/app/assets/javascripts/*.js": {
"alternate": "ee/spec/frontend/{}_spec.js",
+ "related": "app/assets/javascripts/{}.js",
"type": "source"
},
"ee/app/assets/javascripts/*.vue": {
"alternate": "ee/spec/frontend/{}_spec.js",
+ "related": "app/assets/javascripts/{}.vue",
"type": "source"
},
"ee/spec/frontend/*_spec.js": {
"alternate": ["ee/app/assets/javascripts/{}.vue", "ee/app/assets/javascripts/{}.js"],
"type": "test"
},
- "*.rb": {"dispatch": "bundle exec rubocop {file}"},
- "*_spec.rb": {"dispatch": "bundle exec rspec {file}"}
+ "*.rb": { "dispatch": "bundle exec rubocop {file}" },
+ "*_spec.rb": { "dispatch": "bundle exec rspec {file}" }
}
diff --git a/.rubocop.yml b/.rubocop.yml
index 7fe3fc35b66..b84effd5b16 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -13,6 +13,9 @@ inherit_from:
<% end %>
- '.rubocop_todo.yml'
<% end %>
+ <% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.0' %>
+ - ./rubocop/rubocop-ruby30.yml
+ <% end %>
- ./rubocop/rubocop-migrations.yml
- ./rubocop/rubocop-usage-data.yml
- ./rubocop/rubocop-code_reuse.yml
@@ -26,7 +29,8 @@ inherit_mode:
- Exclude
AllCops:
- TargetRubyVersion: 2.7
+ # Target the current Ruby version. For example, "2.7" or "3.0".
+ TargetRubyVersion: <%= RUBY_VERSION[/^\d+\.\d+/, 0] %>
TargetRailsVersion: 6.0
Exclude:
- 'vendor/**/*'
@@ -40,11 +44,23 @@ AllCops:
- 'plugins/**/*'
- 'file_hooks/**/*'
- 'workhorse/**/*'
+ - 'shared/packages/**/*'
- 'spec/support/*.git/**/*' # e.g. spec/support/gitlab-git-test.git
- 'db/ci_migrate/*.rb' # since the `db/ci_migrate` is a symlinked to `db/migrate`
# Use absolute path to avoid orphan directories with changed workspace root.
CacheRootDirectory: <%= Dir.getwd %>/tmp
MaxFilesInCache: 35000
+ NewCops: disable
+ SuggestExtensions: false
+
+RSpec:
+ Language:
+ Includes:
+ Examples:
+ - run_permission_checks
+ - run_group_permission_checks
+ - it_should_email!
+ - it_should_not_email!
Metrics/ParameterLists:
Exclude:
@@ -80,7 +96,6 @@ Lint/EmptyFile:
# This cop checks whether some constant value isn't a
# mutable literal (e.g. array or hash).
Style/MutableConstant:
- Enabled: true
Exclude:
- 'db/migrate/**/*'
- 'db/post_migrate/**/*'
@@ -101,8 +116,7 @@ Style/FrozenStringLiteralComment:
EnforcedStyle: always_true
Style/SpecialGlobalVars:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/358427
- EnforcedStyle: use_perl_names
+ EnforcedStyle: use_builtin_english_names
RSpec/FilePath:
Exclude:
@@ -448,6 +462,12 @@ RSpec/FactoriesInMigrationSpecs:
- 'spec/lib/ee/gitlab/background_migration/**/*.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb'
+RSpec/FactoryBot/AvoidCreate:
+ Enabled: true
+ Include:
+ - 'spec/serializers/**/*.rb'
+ - 'ee/spec/serializers/**/*.rb'
+
Cop/IncludeSidekiqWorker:
Enabled: true
Exclude:
@@ -690,7 +710,7 @@ Gitlab/RailsLogger:
- 'ee/spec/**/*.rb'
# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/267606
-FactoryBot/InlineAssociation:
+RSpec/FactoryBot/InlineAssociation:
Include:
- 'spec/factories/**/*.rb'
- 'ee/spec/factories/**/*.rb'
@@ -775,3 +795,39 @@ Fips/OpenSSL:
Gemspec/AvoidExecutingGit:
Enabled: false
+
+Lint/BinaryOperatorWithIdenticalOperands:
+ Exclude:
+ - '{,ee/,qa/}spec/**/*_{spec,shared_examples,shared_context}.rb'
+
+Cop/SidekiqRedisCall:
+ Enabled: true
+ Exclude:
+ - '{,ee/,jh/}spec/**/*'
+ - 'lib/gitlab/database/migration_helpers.rb'
+ - 'lib/gitlab/sidekiq_migrate_jobs.rb'
+ - 'lib/gitlab/sidekiq_versioning.rb'
+
+Cop/RedisQueueUsage:
+ Enabled: true
+ Exclude:
+ - '{,ee/,jh/}spec/**/*'
+ - 'config/initializers/sidekiq.rb'
+ - 'lib/gitlab/instrumentation/redis.rb'
+ - 'lib/gitlab/redis.rb'
+ - 'lib/system_check/app/redis_version_check.rb'
+ - 'lib/gitlab/mail_room.rb'
+
+Cop/SidekiqApiUsage:
+ Enabled: true
+ Exclude:
+ - '{,ee/,jh/}spec/**/*'
+ - 'db/post_migrate/**/*'
+ - 'lib/gitlab/sidekiq_middleware/**/*'
+ - 'lib/gitlab/background_migration/**/*'
+ - 'lib/gitlab/hashed_storage/migrator.rb'
+ - 'lib/api/sidekiq_metrics.rb'
+ - 'lib/gitlab/sidekiq_config.rb'
+ - 'lib/gitlab/sidekiq_queue.rb'
+ - 'config/initializers/sidekiq.rb'
+ - 'config/initializers/forbid_sidekiq_in_transactions.rb'
diff --git a/.rubocop_todo/capybara/visibility_matcher.yml b/.rubocop_todo/capybara/visibility_matcher.yml
deleted file mode 100644
index e236be2593e..00000000000
--- a/.rubocop_todo/capybara/visibility_matcher.yml
+++ /dev/null
@@ -1,79 +0,0 @@
----
-Capybara/VisibilityMatcher:
- Exclude:
- - 'ee/spec/features/boards/sidebar_spec.rb'
- - 'ee/spec/features/epics/epic_show_spec.rb'
- - 'ee/spec/features/epics/todo_spec.rb'
- - 'ee/spec/features/epics/update_epic_spec.rb'
- - 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
- - 'ee/spec/features/groups/issues_spec.rb'
- - 'ee/spec/features/groups/saml_enforcement_spec.rb'
- - 'ee/spec/features/groups/settings/protected_environments_spec.rb'
- - 'ee/spec/features/issues/related_issues_spec.rb'
- - 'ee/spec/features/projects/integrations/user_activates_jira_spec.rb'
- - 'ee/spec/features/projects/quality/test_case_show_spec.rb'
- - 'ee/spec/features/projects/requirements_management/requirements_list_spec.rb'
- - 'ee/spec/features/projects/settings/ee/repository_mirrors_settings_spec.rb'
- - 'ee/spec/features/promotion_spec.rb'
- - 'ee/spec/features/registrations/welcome_spec.rb'
- - 'ee/spec/support/helpers/billing_plans_helpers.rb'
- - 'ee/spec/support/shared_examples/features/password_complexity_shared_examples.rb'
- - 'ee/spec/support/shared_examples/views/issuable_bulk_dropdown_shared_examples.rb'
- - 'ee/spec/views/layouts/_search.html.haml_spec.rb'
- - 'ee/spec/views/registrations/welcome/show.html.haml_spec.rb'
- - 'spec/features/admin/admin_mode_spec.rb'
- - 'spec/features/dashboard/merge_requests_spec.rb'
- - 'spec/features/dashboard/todos/todos_spec.rb'
- - 'spec/features/groups/group_settings_spec.rb'
- - 'spec/features/issues/service_desk_spec.rb'
- - 'spec/features/issues/todo_spec.rb'
- - 'spec/features/issues/user_creates_branch_and_merge_request_spec.rb'
- - 'spec/features/issues/user_creates_issue_spec.rb'
- - 'spec/features/merge_request/user_posts_notes_spec.rb'
- - 'spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb'
- - 'spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb'
- - 'spec/features/merge_request/user_sees_diff_spec.rb'
- - 'spec/features/merge_request/user_sees_merge_widget_spec.rb'
- - 'spec/features/merge_request/user_views_diffs_commit_spec.rb'
- - 'spec/features/merge_request/user_views_diffs_spec.rb'
- - 'spec/features/projects/blobs/blob_show_spec.rb'
- - 'spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb'
- - 'spec/features/projects/ci/lint_spec.rb'
- - 'spec/features/projects/commit/comments/user_adds_comment_spec.rb'
- - 'spec/features/projects/commits/multi_view_diff_spec.rb'
- - 'spec/features/projects/commits/user_browses_commits_spec.rb'
- - 'spec/features/projects/integrations/user_activates_jira_spec.rb'
- - 'spec/features/projects/issues/design_management/user_views_designs_with_svg_xss_spec.rb'
- - 'spec/features/projects/jobs_spec.rb'
- - 'spec/features/projects/network_graph_spec.rb'
- - 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
- - 'spec/features/projects/pipelines/pipeline_spec.rb'
- - 'spec/features/projects/settings/lfs_settings_spec.rb'
- - 'spec/features/projects/settings/packages_settings_spec.rb'
- - 'spec/features/projects/settings/repository_settings_spec.rb'
- - 'spec/features/projects/settings/visibility_settings_spec.rb'
- - 'spec/features/projects/show/user_manages_notifications_spec.rb'
- - 'spec/features/projects/user_changes_project_visibility_spec.rb'
- - 'spec/features/projects/user_sees_user_popover_spec.rb'
- - 'spec/features/search/user_searches_for_commits_spec.rb'
- - 'spec/features/snippets/notes_on_personal_snippets_spec.rb'
- - 'spec/features/task_lists_spec.rb'
- - 'spec/features/u2f_spec.rb'
- - 'spec/features/uploads/user_uploads_file_to_note_spec.rb'
- - 'spec/features/users/email_verification_on_login_spec.rb'
- - 'spec/features/users/overview_spec.rb'
- - 'spec/features/users/user_browses_projects_on_user_page_spec.rb'
- - 'spec/features/webauthn_spec.rb'
- - 'spec/features/whats_new_spec.rb'
- - 'spec/support/helpers/features/canonical_link_helpers.rb'
- - 'spec/support/shared_examples/features/discussion_comments_shared_example.rb'
- - 'spec/support/shared_examples/features/page_description_shared_examples.rb'
- - 'spec/support/shared_examples/features/rss_shared_examples.rb'
- - 'spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb'
- - 'spec/views/import/gitlab_projects/new.html.haml_spec.rb'
- - 'spec/views/layouts/_header_search.html.haml_spec.rb'
- - 'spec/views/layouts/_search.html.haml_spec.rb'
- - 'spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb'
- - 'spec/views/profiles/preferences/show.html.haml_spec.rb'
- - 'spec/views/projects/merge_requests/edit.html.haml_spec.rb'
- - 'spec/views/projects/merge_requests/show.html.haml_spec.rb'
diff --git a/.rubocop_todo/cop/static_translation_definition.yml b/.rubocop_todo/cop/static_translation_definition.yml
index 22f5070d07c..ecbee866a6c 100644
--- a/.rubocop_todo/cop/static_translation_definition.yml
+++ b/.rubocop_todo/cop/static_translation_definition.yml
@@ -1,20 +1,6 @@
---
Cop/StaticTranslationDefinition:
Exclude:
- - 'app/models/application_setting.rb'
- 'app/models/diff_viewer/image.rb'
- 'app/models/diff_viewer/rich.rb'
- 'app/models/diff_viewer/simple.rb'
- - 'app/models/group_group_link.rb'
- - 'app/models/jira_import_state.rb'
- - 'app/models/member.rb'
- - 'app/models/project.rb'
- - 'app/models/project_group_link.rb'
- - 'app/models/user.rb'
- - 'app/models/users/banned_user.rb'
- - 'ee/app/models/allowed_email_domain.rb'
- - 'ee/app/models/dast/site_profile_secret_variable.rb'
- - 'ee/app/models/group_merge_request_approval_setting.rb'
- - 'ee/app/models/incident_management/escalation_policy.rb'
- - 'ee/app/models/incident_management/escalation_rule.rb'
- - 'ee/app/models/vulnerabilities/read.rb'
diff --git a/.rubocop_todo/gitlab/no_code_coverage_comment.yml b/.rubocop_todo/gitlab/no_code_coverage_comment.yml
new file mode 100644
index 00000000000..0dcee5f32ee
--- /dev/null
+++ b/.rubocop_todo/gitlab/no_code_coverage_comment.yml
@@ -0,0 +1,19 @@
+---
+Gitlab/NoCodeCoverageComment:
+ Details: grace period
+ Exclude:
+ - 'app/models/integration.rb'
+ - 'app/services/ci/job_artifacts/destroy_batch_service.rb'
+ - 'app/workers/database/batched_background_migration/single_database_worker.rb'
+ - 'config/initializers/net_http_response_patch.rb'
+ - 'ee/app/models/concerns/geo/replicable_model.rb'
+ - 'ee/lib/gitlab/geo/replicator.rb'
+ - 'lib/gitlab/auth/o_auth/session.rb'
+ - 'lib/gitlab/cleanup/personal_access_tokens.rb'
+ - 'lib/gitlab/cycle_analytics/summary/defaults.rb'
+ - 'lib/gitlab/database/background_migration/health_status/signals.rb'
+ - 'lib/gitlab/seeder.rb'
+ - 'lib/gitlab/webpack/dev_server_middleware.rb'
+ - 'lib/tasks/dev.rake'
+ - 'lib/tasks/gems.rake'
+ - 'lib/tasks/gitlab/db.rake'
diff --git a/.rubocop_todo/gitlab/service_response.yml b/.rubocop_todo/gitlab/service_response.yml
new file mode 100644
index 00000000000..ccf934e09b3
--- /dev/null
+++ b/.rubocop_todo/gitlab/service_response.yml
@@ -0,0 +1,84 @@
+---
+Gitlab/ServiceResponse:
+ Details: grace period
+ Exclude:
+ - 'app/services/alert_management/metric_images/upload_service.rb'
+ - 'app/services/analytics/cycle_analytics/stages/base_service.rb'
+ - 'app/services/boards/lists/base_update_service.rb'
+ - 'app/services/branches/delete_service.rb'
+ - 'app/services/bulk_imports/create_service.rb'
+ - 'app/services/bulk_imports/export_service.rb'
+ - 'app/services/ci/build_cancel_service.rb'
+ - 'app/services/ci/build_erase_service.rb'
+ - 'app/services/ci/build_unschedule_service.rb'
+ - 'app/services/ci/prometheus_metrics/observe_histograms_service.rb'
+ - 'app/services/ci/retry_pipeline_service.rb'
+ - 'app/services/ci/runners/assign_runner_service.rb'
+ - 'app/services/ci/runners/register_runner_service.rb'
+ - 'app/services/ci/runners/set_runner_associated_projects_service.rb'
+ - 'app/services/concerns/alert_management/responses.rb'
+ - 'app/services/concerns/services/return_service_responses.rb'
+ - 'app/services/container_expiration_policies/update_service.rb'
+ - 'app/services/dependency_proxy/group_settings/update_service.rb'
+ - 'app/services/dependency_proxy/image_ttl_group_policies/update_service.rb'
+ - 'app/services/groups/update_statistics_service.rb'
+ - 'app/services/incident_management/pager_duty/create_incident_issue_service.rb'
+ - 'app/services/incident_management/pager_duty/process_webhook_service.rb'
+ - 'app/services/issuable/bulk_update_service.rb'
+ - 'app/services/jira_import/start_import_service.rb'
+ - 'app/services/namespaces/package_settings/update_service.rb'
+ - 'app/services/packages/debian/create_distribution_service.rb'
+ - 'app/services/packages/mark_package_for_destruction_service.rb'
+ - 'app/services/packages/rubygems/dependency_resolver_service.rb'
+ - 'app/services/snippets/base_service.rb'
+ - 'app/services/snippets/bulk_destroy_service.rb'
+ - 'app/services/snippets/destroy_service.rb'
+ - 'app/services/snippets/repository_validation_service.rb'
+ - 'app/services/snippets/update_statistics_service.rb'
+ - 'app/services/timelogs/base_service.rb'
+ - 'app/services/work_items/create_and_link_service.rb'
+ - 'app/services/work_items/create_from_task_service.rb'
+ - 'app/services/work_items/delete_task_service.rb'
+ - 'ee/app/services/analytics/cycle_analytics/value_streams/create_service.rb'
+ - 'ee/app/services/app_sec/dast/profiles/destroy_service.rb'
+ - 'ee/app/services/app_sec/dast/scanner_profiles/destroy_service.rb'
+ - 'ee/app/services/app_sec/dast/scanner_profiles/update_service.rb'
+ - 'ee/app/services/app_sec/dast/site_profiles/destroy_service.rb'
+ - 'ee/app/services/ee/analytics/cycle_analytics/stages/base_service.rb'
+ - 'ee/app/services/ee/ci/retry_pipeline_service.rb'
+ - 'ee/app/services/external_status_checks/create_service.rb'
+ - 'ee/app/services/external_status_checks/destroy_service.rb'
+ - 'ee/app/services/external_status_checks/dispatch_service.rb'
+ - 'ee/app/services/external_status_checks/update_service.rb'
+ - 'ee/app/services/gitlab_subscriptions/create_trial_or_lead_service.rb'
+ - 'ee/app/services/group_saml/saml_group_links/create_service.rb'
+ - 'ee/app/services/iterations/cadences/create_iterations_in_advance_service.rb'
+ - 'ee/app/services/iterations/cadences/create_service.rb'
+ - 'ee/app/services/iterations/cadences/destroy_service.rb'
+ - 'ee/app/services/iterations/cadences/update_service.rb'
+ - 'ee/app/services/iterations/create_service.rb'
+ - 'ee/app/services/iterations/delete_service.rb'
+ - 'ee/app/services/iterations/roll_over_issues_service.rb'
+ - 'ee/app/services/iterations/update_service.rb'
+ - 'ee/app/services/security/findings/dismiss_service.rb'
+ - 'ee/app/services/vulnerabilities/finding_dismiss_service.rb'
+ - 'ee/app/services/vulnerability_issue_links/create_service.rb'
+ - 'ee/app/services/vulnerability_issue_links/delete_service.rb'
+ - 'ee/spec/graphql/mutations/security/finding/dismiss_spec.rb'
+ - 'spec/controllers/boards/issues_controller_spec.rb'
+ - 'spec/controllers/import/bulk_imports_controller_spec.rb'
+ - 'spec/controllers/import/fogbugz_controller_spec.rb'
+ - 'spec/controllers/projects/alerting/notifications_controller_spec.rb'
+ - 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/controllers/projects/pipelines_controller_spec.rb'
+ - 'spec/controllers/projects/prometheus/alerts_controller_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
+ - 'spec/requests/api/ci/pipelines_spec.rb'
+ - 'spec/requests/api/ci/runner/runners_post_spec.rb'
+ - 'spec/requests/api/group_export_spec.rb'
+ - 'spec/requests/api/issues/issues_spec.rb'
+ - 'spec/requests/api/project_export_spec.rb'
+ - 'spec/requests/api/project_import_spec.rb'
+ - 'spec/requests/projects/incident_management/pagerduty_incidents_spec.rb'
+ - 'spec/services/bulk_imports/export_service_spec.rb'
+ - 'spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb'
diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml
index bd4cd386153..195f3fee98e 100644
--- a/.rubocop_todo/layout/argument_alignment.yml
+++ b/.rubocop_todo/layout/argument_alignment.yml
@@ -854,7 +854,6 @@ Layout/ArgumentAlignment:
- 'spec/rubocop/cop/rspec/be_success_matcher_spec.rb'
- 'spec/serializers/feature_flag_entity_spec.rb'
- 'spec/serializers/feature_flag_serializer_spec.rb'
- - 'spec/serializers/pipeline_serializer_spec.rb'
- 'spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
- 'spec/services/award_emojis/destroy_service_spec.rb'
- 'spec/services/bulk_update_integration_service_spec.rb'
diff --git a/.rubocop_todo/layout/closing_parenthesis_indentation.yml b/.rubocop_todo/layout/closing_parenthesis_indentation.yml
new file mode 100644
index 00000000000..79397e92312
--- /dev/null
+++ b/.rubocop_todo/layout/closing_parenthesis_indentation.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+Layout/ClosingParenthesisIndentation:
+ Exclude:
+ - 'app/presenters/project_presenter.rb'
+ - 'spec/requests/api/internal/base_spec.rb'
diff --git a/.rubocop_todo/layout/empty_line_between_defs.yml b/.rubocop_todo/layout/empty_line_between_defs.yml
new file mode 100644
index 00000000000..ba69fc4c51b
--- /dev/null
+++ b/.rubocop_todo/layout/empty_line_between_defs.yml
@@ -0,0 +1,8 @@
+---
+# Cop supports --auto-correct.
+Layout/EmptyLineBetweenDefs:
+ Exclude:
+ - 'db/post_migrate/20220202105733_delete_service_template_records.rb'
+ - 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
+ - 'lib/gitlab/import_export/remote_stream_upload.rb'
+ - 'lib/gitlab/redis/multi_store.rb'
diff --git a/.rubocop_todo/layout/first_array_element_indentation.yml b/.rubocop_todo/layout/first_array_element_indentation.yml
index 5207d493044..cbe806fc16f 100644
--- a/.rubocop_todo/layout/first_array_element_indentation.yml
+++ b/.rubocop_todo/layout/first_array_element_indentation.yml
@@ -1,203 +1,14 @@
---
# Cop supports --auto-correct.
Layout/FirstArrayElementIndentation:
+ Details: grace period
Exclude:
- - 'lib/gitlab/email/message/in_product_marketing/trial.rb'
- - 'lib/gitlab/email/message/in_product_marketing/verify.rb'
- - 'lib/gitlab/import_export/base/relation_factory.rb'
- - 'lib/gitlab/import_export/json/streaming_serializer.rb'
- - 'lib/gitlab/kroki.rb'
- - 'lib/gitlab/object_hierarchy.rb'
- - 'lib/gitlab/pagination/keyset/simple_order_builder.rb'
- - 'lib/gitlab/project_authorizations.rb'
- - 'lib/gitlab/usage_data.rb'
- - 'lib/system_check/app/authorized_keys_permission_check.rb'
- - 'qa/qa/resource/protected_branch.rb'
- - 'qa/qa/specs/features/api/1_manage/group_access_token_spec.rb'
- - 'qa/qa/specs/features/api/1_manage/project_access_token_spec.rb'
- - 'qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb'
- - 'qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb'
- - 'qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb'
- - 'qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb'
- - 'qa/qa/specs/features/ee/api/1_manage/user/minimal_access_user_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/advanced_global_advanced_syntax_search_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/elasticsearch_api_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/main_index/blob_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/nightly_elasticsearch_test_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/code_owners_with_protected_branch_and_squashed_commits_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/4_verify/new_discussion_not_dropping_merge_trains_mr_spec.rb'
- - 'spec/controllers/concerns/send_file_upload_spec.rb'
- - 'spec/graphql/types/packages/tag_type_spec.rb'
- - 'spec/helpers/application_settings_helper_spec.rb'
- - 'spec/helpers/commits_helper_spec.rb'
- - 'spec/helpers/issuables_description_templates_helper_spec.rb'
- - 'spec/helpers/listbox_helper_spec.rb'
- - 'spec/helpers/users_helper_spec.rb'
- - 'spec/lib/api/helpers/merge_requests_helpers_spec.rb'
- - 'spec/lib/banzai/filter/references/label_reference_filter_spec.rb'
- - 'spec/lib/csv_builders/stream_spec.rb'
- - 'spec/lib/expand_variables_spec.rb'
- - 'spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb'
- - 'spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb'
- - 'spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb'
- - 'spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb'
- - 'spec/lib/gitlab/ci/ansi2json_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/artifact_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/project_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/mapper_spec.rb'
- - 'spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb'
- - 'spec/lib/gitlab/ci/parsers/security/common_spec.rb'
- - 'spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb'
- - 'spec/lib/gitlab/ci/reports/codequality_reports_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder/group_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder/project_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder_spec.rb'
- - 'spec/lib/gitlab/ci/variables/collection/sort_spec.rb'
- - 'spec/lib/gitlab/ci/yaml_processor/result_spec.rb'
- - 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- - 'spec/lib/gitlab/conflict/file_spec.rb'
- - 'spec/lib/gitlab/database/each_database_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/sticking_spec.rb'
- - 'spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb'
- - 'spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb'
- - 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
- - 'spec/lib/gitlab/database/partitioning/time_partition_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_spec.rb'
- - 'spec/lib/gitlab/database/similarity_score_spec.rb'
- - 'spec/lib/gitlab/diff/char_diff_spec.rb'
- - 'spec/lib/gitlab/diff/file_collection_sorter_spec.rb'
- - 'spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/blob_service_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb'
- 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/notes_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/parallel_scheduling_spec.rb'
- - 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
- - 'spec/lib/gitlab/hook_data/release_builder_spec.rb'
- - 'spec/lib/gitlab/import_export/group/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/kubernetes/rollout_instances_spec.rb'
- - 'spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/iterator_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
- - 'spec/lib/gitlab/project_transfer_spec.rb'
- - 'spec/lib/gitlab/prometheus_client_spec.rb'
- - 'spec/lib/gitlab/push_options_spec.rb'
- - 'spec/lib/gitlab/rack_attack/request_spec.rb'
- - 'spec/lib/gitlab/search/abuse_detection_spec.rb'
- 'spec/lib/gitlab/search/found_blob_spec.rb'
- - 'spec/lib/gitlab/serializer/ci/variables_spec.rb'
- - 'spec/lib/gitlab/sidekiq_config_spec.rb'
- - 'spec/lib/gitlab/ssh_public_key_spec.rb'
- - 'spec/lib/gitlab/usage_data/topology_spec.rb'
- - 'spec/lib/gitlab/usage_data_spec.rb'
- - 'spec/lib/gitlab/utils_spec.rb'
- - 'spec/lib/gitlab/webpack/manifest_spec.rb'
- - 'spec/lib/google_api/cloud_platform/client_spec.rb'
- - 'spec/lib/peek/views/bullet_detailed_spec.rb'
- - 'spec/lib/system_check/incoming_email_check_spec.rb'
- - 'spec/lib/unnested_in_filters/rewriter_spec.rb'
- - 'spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb'
- - 'spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb'
- - 'spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb'
- - 'spec/models/analytics/cycle_analytics/project_stage_spec.rb'
- - 'spec/models/application_setting_spec.rb'
- - 'spec/models/ci/build_spec.rb'
- - 'spec/models/ci/build_trace_spec.rb'
- - 'spec/models/ci/daily_build_group_report_result_spec.rb'
- - 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/ci/runner_version_spec.rb'
- - 'spec/models/ci/unit_test_spec.rb'
- - 'spec/models/clusters/applications/cert_manager_spec.rb'
- - 'spec/models/clusters/platforms/kubernetes_spec.rb'
- - 'spec/models/commit_collection_spec.rb'
- - 'spec/models/compare_spec.rb'
- - 'spec/models/concerns/id_in_ordered_spec.rb'
- - 'spec/models/concerns/noteable_spec.rb'
- - 'spec/models/diff_note_spec.rb'
- - 'spec/models/discussion_spec.rb'
- - 'spec/models/group_group_link_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/integration_spec.rb'
- - 'spec/models/integrations/chat_message/issue_message_spec.rb'
- - 'spec/models/integrations/chat_message/wiki_page_message_spec.rb'
- - 'spec/models/integrations/jira_spec.rb'
- - 'spec/models/label_note_spec.rb'
- - 'spec/models/merge_request/cleanup_schedule_spec.rb'
- - 'spec/models/merge_request_diff_spec.rb'
- - 'spec/models/merge_request_spec.rb'
- - 'spec/models/operations/feature_flags/strategy_spec.rb'
- - 'spec/models/project_group_link_spec.rb'
- 'spec/models/repository_spec.rb'
- - 'spec/models/user_preference_spec.rb'
- - 'spec/models/user_spec.rb'
- - 'spec/models/wiki_directory_spec.rb'
- - 'spec/policies/concerns/crud_policy_helpers_spec.rb'
- - 'spec/presenters/ci/build_runner_presenter_spec.rb'
- - 'spec/requests/api/ci/jobs_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
- - 'spec/requests/api/ci/runners_spec.rb'
- - 'spec/requests/api/deploy_tokens_spec.rb'
- - 'spec/requests/api/graphql/ci/config_spec.rb'
- - 'spec/requests/api/graphql/ci/jobs_spec.rb'
- - 'spec/requests/api/graphql/mutations/uploads/delete_spec.rb'
- - 'spec/requests/api/graphql/project/cluster_agents_spec.rb'
- - 'spec/requests/api/graphql/project/issue/designs/designs_spec.rb'
- - 'spec/requests/api/graphql/project/milestones_spec.rb'
- - 'spec/requests/api/graphql/usage_trends_measurements_spec.rb'
- - 'spec/requests/api/graphql/work_item_spec.rb'
- - 'spec/requests/api/issues/post_projects_issues_spec.rb'
- - 'spec/requests/api/issues/put_projects_issues_spec.rb'
- - 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/task_completion_status_spec.rb'
- - 'spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb'
- - 'spec/requests/projects/issues_controller_spec.rb'
- - 'spec/requests/projects/merge_requests_controller_spec.rb'
- - 'spec/serializers/build_trace_entity_spec.rb'
- - 'spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb'
- - 'spec/serializers/merge_request_poll_widget_entity_spec.rb'
- - 'spec/services/award_emojis/copy_service_spec.rb'
- - 'spec/services/bulk_update_integration_service_spec.rb'
- - 'spec/services/ci/compare_test_reports_service_spec.rb'
- - 'spec/services/ci/create_pipeline_service/rules_spec.rb'
- - 'spec/services/ci/find_exposed_artifacts_service_spec.rb'
- - 'spec/services/design_management/move_designs_service_spec.rb'
- - 'spec/services/git/tag_hooks_service_spec.rb'
- - 'spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb'
- - 'spec/services/import/gitlab_projects/create_project_service_spec.rb'
- - 'spec/services/jira_connect/sync_service_spec.rb'
- - 'spec/services/merge_requests/link_lfs_objects_service_spec.rb'
- - 'spec/services/merge_requests/refresh_service_spec.rb'
- - 'spec/services/repositories/changelog_service_spec.rb'
- - 'spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb'
- 'spec/services/security/merge_reports_service_spec.rb'
- - 'spec/services/users/destroy_service_spec.rb'
- 'spec/simplecov_env.rb'
- 'spec/support/atlassian/jira_connect/schemata.rb'
- 'spec/support/capybara.rb'
diff --git a/.rubocop_todo/layout/first_hash_element_indentation.yml b/.rubocop_todo/layout/first_hash_element_indentation.yml
index 94ad3fde252..50cd90019b6 100644
--- a/.rubocop_todo/layout/first_hash_element_indentation.yml
+++ b/.rubocop_todo/layout/first_hash_element_indentation.yml
@@ -308,7 +308,6 @@ Layout/FirstHashElementIndentation:
- 'lib/gitlab/asciidoc/include_processor.rb'
- 'lib/gitlab/auth/otp/strategies/forti_token_cloud.rb'
- 'lib/gitlab/ci/config/entry/processable.rb'
- - 'lib/gitlab/config_checker/external_database_checker.rb'
- 'lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb'
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
- 'lib/gitlab/github_import/importer/diff_note_importer.rb'
@@ -471,7 +470,6 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/gitlab/ci/reports/security/scanner_spec.rb'
- 'spec/lib/gitlab/ci/reports/terraform_reports_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- - 'spec/lib/gitlab/config_checker/external_database_checker_spec.rb'
- 'spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb'
- 'spec/lib/gitlab/data_builder/build_spec.rb'
- 'spec/lib/gitlab/data_builder/issuable_spec.rb'
@@ -633,7 +631,6 @@ Layout/FirstHashElementIndentation:
- 'spec/support_specs/graphql/arguments_spec.rb'
- 'spec/support_specs/graphql/field_selection_spec.rb'
- 'spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tooling/danger/datateam_spec.rb'
- 'spec/tooling/lib/tooling/kubernetes_client_spec.rb'
- 'spec/views/projects/issues/_issue.html.haml_spec.rb'
diff --git a/.rubocop_todo/layout/leading_comment_space.yml b/.rubocop_todo/layout/leading_comment_space.yml
new file mode 100644
index 00000000000..fda1d4ff30b
--- /dev/null
+++ b/.rubocop_todo/layout/leading_comment_space.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+Layout/LeadingCommentSpace:
+ Exclude:
+ - 'config/initializers/kaminari_active_record_relation_methods_with_limit.rb'
+ - 'lib/uploaded_file.rb'
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 01c83d7ac5d..fe9c0593f7d 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -9,13 +9,11 @@ Layout/LineLength:
- 'app/controllers/admin/impersonation_tokens_controller.rb'
- 'app/controllers/admin/keys_controller.rb'
- 'app/controllers/admin/projects_controller.rb'
- - 'app/controllers/admin/runners_controller.rb'
- 'app/controllers/admin/sessions_controller.rb'
- 'app/controllers/admin/topics_controller.rb'
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/controllers/boards/lists_controller.rb'
- - 'app/controllers/clusters/clusters_controller.rb'
- 'app/controllers/concerns/access_tokens_actions.rb'
- 'app/controllers/concerns/analytics/cycle_analytics/stage_actions.rb'
- 'app/controllers/concerns/clientside_preview_csp.rb'
@@ -27,7 +25,6 @@ Layout/LineLength:
- 'app/controllers/concerns/membership_actions.rb'
- 'app/controllers/concerns/metrics_dashboard.rb'
- 'app/controllers/concerns/notes_actions.rb'
- - 'app/controllers/concerns/one_trust_csp.rb'
- 'app/controllers/concerns/product_analytics_tracking.rb'
- 'app/controllers/concerns/routable_actions.rb'
- 'app/controllers/concerns/send_file_upload.rb'
@@ -42,7 +39,6 @@ Layout/LineLength:
- 'app/controllers/groups/dependency_proxy_for_containers_controller.rb'
- 'app/controllers/groups/email_campaigns_controller.rb'
- 'app/controllers/groups/group_members_controller.rb'
- - 'app/controllers/groups/runners_controller.rb'
- 'app/controllers/groups/settings/applications_controller.rb'
- 'app/controllers/groups/settings/ci_cd_controller.rb'
- 'app/controllers/groups/settings/integrations_controller.rb'
@@ -59,7 +55,6 @@ Layout/LineLength:
- 'app/controllers/import/gitlab_groups_controller.rb'
- 'app/controllers/import/gitlab_projects_controller.rb'
- 'app/controllers/invites_controller.rb'
- - 'app/controllers/jira_connect/application_controller.rb'
- 'app/controllers/jira_connect/events_controller.rb'
- 'app/controllers/jira_connect/subscriptions_controller.rb'
- 'app/controllers/jwt_controller.rb'
@@ -84,7 +79,6 @@ Layout/LineLength:
- 'app/controllers/projects/forks_controller.rb'
- 'app/controllers/projects/google_cloud/gcp_regions_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- - 'app/controllers/projects/integrations/shimos_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/jobs_controller.rb'
- 'app/controllers/projects/labels_controller.rb'
@@ -97,12 +91,10 @@ Layout/LineLength:
- 'app/controllers/projects/notes_controller.rb'
- 'app/controllers/projects/performance_monitoring/dashboards_controller.rb'
- 'app/controllers/projects/pipeline_schedules_controller.rb'
- - 'app/controllers/projects/pipelines/tests_controller.rb'
- 'app/controllers/projects/pipelines_controller.rb'
- 'app/controllers/projects/prometheus/metrics_controller.rb'
- 'app/controllers/projects/raw_controller.rb'
- 'app/controllers/projects/settings/ci_cd_controller.rb'
- - 'app/controllers/projects/settings/operations_controller.rb'
- 'app/controllers/projects/settings/repository_controller.rb'
- 'app/controllers/projects/templates_controller.rb'
- 'app/controllers/projects/tree_controller.rb'
@@ -139,7 +131,6 @@ Layout/LineLength:
- 'app/finders/security/security_jobs_finder.rb'
- 'app/finders/todos_finder.rb'
- 'app/finders/user_group_notification_settings_finder.rb'
- - 'app/finders/user_recent_events_finder.rb'
- 'app/graphql/batch_loaders/merge_request_diff_summary_batch_loader.rb'
- 'app/graphql/mutations/alert_management/http_integration/create.rb'
- 'app/graphql/mutations/alert_management/http_integration/http_integration_base.rb'
@@ -162,7 +153,6 @@ Layout/LineLength:
- 'app/graphql/mutations/merge_requests/set_labels.rb'
- 'app/graphql/mutations/merge_requests/set_locked.rb'
- 'app/graphql/mutations/merge_requests/set_milestone.rb'
- - 'app/graphql/mutations/merge_requests/toggle_attention_requested.rb'
- 'app/graphql/mutations/metrics/dashboard/annotations/create.rb'
- 'app/graphql/mutations/namespace/package_settings/update.rb'
- 'app/graphql/mutations/notes/create/note.rb'
@@ -175,32 +165,20 @@ Layout/LineLength:
- 'app/graphql/mutations/snippets/update.rb'
- 'app/graphql/mutations/todos/create.rb'
- 'app/graphql/mutations/todos/mark_all_done.rb'
- - 'app/graphql/mutations/work_items/create.rb'
- - 'app/graphql/mutations/work_items/create_from_task.rb'
- - 'app/graphql/mutations/work_items/delete.rb'
- - 'app/graphql/mutations/work_items/update.rb'
- - 'app/graphql/resolvers/ci/job_token_scope_resolver.rb'
- - 'app/graphql/resolvers/ci/runner_jobs_resolver.rb'
- - 'app/graphql/resolvers/ci/runner_status_resolver.rb'
- 'app/graphql/resolvers/concerns/issue_resolver_arguments.rb'
- 'app/graphql/resolvers/concerns/time_frame_arguments.rb'
- 'app/graphql/resolvers/container_repository_tags_resolver.rb'
- - 'app/graphql/resolvers/group_packages_resolver.rb'
- - 'app/graphql/resolvers/package_details_resolver.rb'
- - 'app/graphql/resolvers/project_jobs_resolver.rb'
- 'app/graphql/resolvers/project_merge_requests_resolver.rb'
- 'app/graphql/resolvers/projects_resolver.rb'
- 'app/graphql/resolvers/user_discussions_count_resolver.rb'
- 'app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb'
- 'app/graphql/types/alert_management/prometheus_integration_type.rb'
- 'app/graphql/types/alert_management/status_enum.rb'
- - 'app/graphql/types/base_field.rb'
- 'app/graphql/types/boards/board_issuable_input_base_type.rb'
- 'app/graphql/types/ci/job_artifact_file_type_enum.rb'
- 'app/graphql/types/ci/job_type.rb'
- 'app/graphql/types/ci/pipeline_config_source_enum.rb'
- 'app/graphql/types/ci/pipeline_type.rb'
- - 'app/graphql/types/ci/runner_membership_filter_enum.rb'
- 'app/graphql/types/ci/runner_setup_type.rb'
- 'app/graphql/types/ci/runner_status_enum.rb'
- 'app/graphql/types/ci/runner_type.rb'
@@ -234,7 +212,6 @@ Layout/LineLength:
- 'app/graphql/types/packages/nuget/dependency_link_metadatum_type.rb'
- 'app/graphql/types/packages/package_dependency_link_type.rb'
- 'app/graphql/types/packages/package_details_type.rb'
- - 'app/graphql/types/packages/package_type.rb'
- 'app/graphql/types/packages/package_type_enum.rb'
- 'app/graphql/types/packages/pypi/metadatum_type.rb'
- 'app/graphql/types/project_type.rb'
@@ -272,7 +249,6 @@ Layout/LineLength:
- 'app/helpers/ide_helper.rb'
- 'app/helpers/import_helper.rb'
- 'app/helpers/in_product_marketing_helper.rb'
- - 'app/helpers/integrations_helper.rb'
- 'app/helpers/invite_members_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/jira_connect_helper.rb'
@@ -305,7 +281,6 @@ Layout/LineLength:
- 'app/helpers/tags_helper.rb'
- 'app/helpers/timeboxes_helper.rb'
- 'app/helpers/tree_helper.rb'
- - 'app/helpers/users/callouts_helper.rb'
- 'app/helpers/users_helper.rb'
- 'app/helpers/version_check_helper.rb'
- 'app/helpers/visibility_level_helper.rb'
@@ -328,15 +303,12 @@ Layout/LineLength:
- 'app/models/application_setting_implementation.rb'
- 'app/models/award_emoji.rb'
- 'app/models/blob_viewer/base.rb'
- - 'app/models/broadcast_message.rb'
- 'app/models/bulk_imports/entity.rb'
- 'app/models/ci/build.rb'
- 'app/models/ci/job_artifact.rb'
- - 'app/models/ci/namespace_mirror.rb'
- 'app/models/ci/pipeline.rb'
- 'app/models/ci/pipeline_artifact.rb'
- 'app/models/ci/runner.rb'
- - 'app/models/ci/secure_file.rb'
- 'app/models/ci/unit_test.rb'
- 'app/models/clusters/agent.rb'
- 'app/models/clusters/applications/cert_manager.rb'
@@ -365,9 +337,7 @@ Layout/LineLength:
- 'app/models/concerns/ignorable_columns.rb'
- 'app/models/concerns/iid_routes.rb'
- 'app/models/concerns/integrations/has_data_fields.rb'
- - 'app/models/concerns/integrations/has_issue_tracker_fields.rb'
- 'app/models/concerns/issuable.rb'
- - 'app/models/concerns/limitable.rb'
- 'app/models/concerns/mentionable/reference_regexes.rb'
- 'app/models/concerns/milestoneable.rb'
- 'app/models/concerns/noteable.rb'
@@ -433,7 +403,6 @@ Layout/LineLength:
- 'app/models/integrations/jira.rb'
- 'app/models/integrations/mattermost.rb'
- 'app/models/integrations/microsoft_teams.rb'
- - 'app/models/integrations/mock_ci.rb'
- 'app/models/integrations/pipelines_email.rb'
- 'app/models/integrations/pivotaltracker.rb'
- 'app/models/integrations/prometheus.rb'
@@ -459,7 +428,6 @@ Layout/LineLength:
- 'app/models/merge_request.rb'
- 'app/models/merge_request_assignee.rb'
- 'app/models/merge_request_diff.rb'
- - 'app/models/merge_request_reviewer.rb'
- 'app/models/merge_requests_closing_issues.rb'
- 'app/models/metrics/dashboard/annotation.rb'
- 'app/models/milestone.rb'
@@ -495,9 +463,7 @@ Layout/LineLength:
- 'app/models/repository.rb'
- 'app/models/serverless/domain.rb'
- 'app/models/service_desk_setting.rb'
- - 'app/models/snippet.rb'
- 'app/models/suggestion.rb'
- - 'app/models/terraform/state.rb'
- 'app/models/todo.rb'
- 'app/models/upload.rb'
- 'app/models/user.rb'
@@ -519,7 +485,6 @@ Layout/LineLength:
- 'app/presenters/merge_request_presenter.rb'
- 'app/presenters/packages/composer/packages_presenter.rb'
- 'app/presenters/packages/conan/package_presenter.rb'
- - 'app/presenters/pages_domain_presenter.rb'
- 'app/presenters/project_clusterable_presenter.rb'
- 'app/presenters/project_presenter.rb'
- 'app/presenters/snippet_blob_presenter.rb'
@@ -536,25 +501,18 @@ Layout/LineLength:
- 'app/serializers/merge_request_poll_cached_widget_entity.rb'
- 'app/serializers/merge_request_poll_widget_entity.rb'
- 'app/serializers/merge_request_sidebar_extras_entity.rb'
- - 'app/serializers/merge_request_user_entity.rb'
- 'app/serializers/merge_request_widget_entity.rb'
- 'app/serializers/note_entity.rb'
- 'app/serializers/project_note_entity.rb'
- - 'app/serializers/prometheus_alert_entity.rb'
- 'app/services/application_settings/update_service.rb'
- 'app/services/auth/container_registry_authentication_service.rb'
- - 'app/services/auto_merge/base_service.rb'
- 'app/services/auto_merge/merge_when_pipeline_succeeds_service.rb'
- 'app/services/boards/base_items_list_service.rb'
- - 'app/services/boards/destroy_service.rb'
- 'app/services/boards/issues/create_service.rb'
- 'app/services/boards/issues/move_service.rb'
- 'app/services/boards/lists/base_create_service.rb'
- 'app/services/branches/delete_service.rb'
- - 'app/services/bulk_create_integration_service.rb'
- - 'app/services/bulk_imports/file_decompression_service.rb'
- 'app/services/bulk_imports/uploads_export_service.rb'
- - 'app/services/bulk_update_integration_service.rb'
- 'app/services/ci/create_pipeline_service.rb'
- 'app/services/ci/drop_pipeline_service.rb'
- 'app/services/ci/generate_coverage_reports_service.rb'
@@ -606,11 +564,8 @@ Layout/LineLength:
- 'app/services/git/process_ref_changes_service.rb'
- 'app/services/google_cloud/create_service_accounts_service.rb'
- 'app/services/google_cloud/generate_pipeline_service.rb'
- - 'app/services/google_cloud/service_accounts_service.rb'
- 'app/services/groups/create_service.rb'
- 'app/services/groups/destroy_service.rb'
- - 'app/services/groups/import_export/import_service.rb'
- - 'app/services/groups/open_issues_count_service.rb'
- 'app/services/groups/transfer_service.rb'
- 'app/services/groups/update_service.rb'
- 'app/services/import/bitbucket_server_service.rb'
@@ -640,7 +595,6 @@ Layout/LineLength:
- 'app/services/lfs/unlock_file_service.rb'
- 'app/services/loose_foreign_keys/batch_cleaner_service.rb'
- 'app/services/loose_foreign_keys/cleaner_service.rb'
- - 'app/services/members/approve_access_request_service.rb'
- 'app/services/members/destroy_service.rb'
- 'app/services/members/invitation_reminder_email_service.rb'
- 'app/services/members/update_service.rb'
@@ -649,10 +603,8 @@ Layout/LineLength:
- 'app/services/merge_requests/base_service.rb'
- 'app/services/merge_requests/build_service.rb'
- 'app/services/merge_requests/create_from_issue_service.rb'
- - 'app/services/merge_requests/create_pipeline_service.rb'
- 'app/services/merge_requests/merge_base_service.rb'
- 'app/services/merge_requests/merge_service.rb'
- - 'app/services/merge_requests/mergeability/run_checks_service.rb'
- 'app/services/merge_requests/mergeability_check_service.rb'
- 'app/services/merge_requests/push_options_handler_service.rb'
- 'app/services/merge_requests/refresh_service.rb'
@@ -665,7 +617,6 @@ Layout/LineLength:
- 'app/services/milestones/destroy_service.rb'
- 'app/services/namespace_settings/update_service.rb'
- 'app/services/notes/build_service.rb'
- - 'app/services/notes/copy_service.rb'
- 'app/services/notes/quick_actions_service.rb'
- 'app/services/notes/resolve_service.rb'
- 'app/services/notification_recipients/builder/default.rb'
@@ -687,7 +638,6 @@ Layout/LineLength:
- 'app/services/packages/npm/create_package_service.rb'
- 'app/services/packages/nuget/search_service.rb'
- 'app/services/packages/nuget/update_package_from_metadata_service.rb'
- - 'app/services/packages/rubygems/dependency_resolver_service.rb'
- 'app/services/pages/migrate_from_legacy_storage_service.rb'
- 'app/services/pages/migrate_legacy_storage_to_deployment_service.rb'
- 'app/services/personal_access_tokens/create_service.rb'
@@ -718,7 +668,6 @@ Layout/LineLength:
- 'app/services/repository_archive_clean_up_service.rb'
- 'app/services/resource_access_tokens/create_service.rb'
- 'app/services/resource_access_tokens/revoke_service.rb'
- - 'app/services/resource_events/change_labels_service.rb'
- 'app/services/search/global_service.rb'
- 'app/services/search_service.rb'
- 'app/services/security/ci_configuration/container_scanning_create_service.rb'
@@ -727,7 +676,6 @@ Layout/LineLength:
- 'app/services/security/ci_configuration/sast_iac_create_service.rb'
- 'app/services/security/ci_configuration/sast_parser_service.rb'
- 'app/services/security/ci_configuration/secret_detection_create_service.rb'
- - 'app/services/service_ping/submit_service.rb'
- 'app/services/snippets/count_service.rb'
- 'app/services/snippets/create_service.rb'
- 'app/services/spam/spam_action_service.rb'
@@ -790,7 +738,6 @@ Layout/LineLength:
- 'config/application.rb'
- 'config/initializers/00_rails_disable_joins.rb'
- 'config/initializers/01_secret_token.rb'
- - 'config/initializers/0_marginalia.rb'
- 'config/initializers/1_settings.rb'
- 'config/initializers/5_backend.rb'
- 'config/initializers/7_prometheus_metrics.rb'
@@ -798,9 +745,7 @@ Layout/LineLength:
- 'config/initializers/active_record_force_reconnects.rb'
- 'config/initializers/active_record_keyset_pagination.rb'
- 'config/initializers/active_record_schema_versions.rb'
- - 'config/initializers/active_record_transaction_observer.rb'
- 'config/initializers/carrierwave_patch.rb'
- - 'config/initializers/content_security_policy.rb'
- 'config/initializers/deprecations.rb'
- 'config/initializers/devise_dynamic_password_length_validation.rb'
- 'config/initializers/direct_upload_support.rb'
@@ -812,10 +757,8 @@ Layout/LineLength:
- 'config/initializers/pages_storage_check.rb'
- 'config/initializers/rails_host_authorization.rb'
- 'config/initializers/session_store.rb'
- - 'config/initializers/sidekiq.rb'
- 'config/initializers/validate_database_config.rb'
- 'config/initializers/validate_puma.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
- 'config/initializers/zz_metrics.rb'
- 'config/object_store_settings.rb'
- 'config/routes.rb'
@@ -828,7 +771,6 @@ Layout/LineLength:
- 'config/routes/uploads.rb'
- 'config/routes/user.rb'
- 'config/settings.rb'
- - 'danger/ce_ee_vue_templates/Dangerfile'
- 'danger/ci_config/Dangerfile'
- 'danger/documentation/Dangerfile'
- 'danger/feature_flag/Dangerfile'
@@ -1122,35 +1064,28 @@ Layout/LineLength:
- 'ee/app/controllers/concerns/credentials_inventory_actions.rb'
- 'ee/app/controllers/concerns/ee/issuable_collections.rb'
- 'ee/app/controllers/concerns/group_invite_members.rb'
- - 'ee/app/controllers/concerns/insights_actions.rb'
- - 'ee/app/controllers/ee/admin/dev_ops_report_controller.rb'
- 'ee/app/controllers/ee/admin/users_controller.rb'
- 'ee/app/controllers/ee/application_controller.rb'
- 'ee/app/controllers/ee/groups/group_members_controller.rb'
- 'ee/app/controllers/ee/groups_controller.rb'
- 'ee/app/controllers/ee/projects/deploy_tokens_controller.rb'
- - 'ee/app/controllers/ee/projects/pipelines_controller.rb'
- 'ee/app/controllers/ee/projects/settings/operations_controller.rb'
- 'ee/app/controllers/ee/projects/settings/repository_controller.rb'
- 'ee/app/controllers/ee/projects_controller.rb'
- 'ee/app/controllers/ee/repositories/git_http_client_controller.rb'
- 'ee/app/controllers/ee/repositories/git_http_controller.rb'
- 'ee/app/controllers/ee/repositories/lfs_api_controller.rb'
- - 'ee/app/controllers/ee/sessions_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics/stages_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics/summary_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics/value_streams_controller.rb'
- - 'ee/app/controllers/groups/analytics/cycle_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/productivity_analytics_controller.rb'
- 'ee/app/controllers/groups/hooks_controller.rb'
- 'ee/app/controllers/groups/ldap_settings_controller.rb'
- 'ee/app/controllers/groups/omniauth_callbacks_controller.rb'
- 'ee/app/controllers/groups/saml_group_links_controller.rb'
- 'ee/app/controllers/groups/sso_controller.rb'
- - 'ee/app/controllers/groups/usage_quotas_controller.rb'
- 'ee/app/controllers/oauth/geo_auth_controller.rb'
- 'ee/app/controllers/operations_controller.rb'
- - 'ee/app/controllers/profiles/usage_quotas_controller.rb'
- 'ee/app/controllers/projects/audit_events_controller.rb'
- 'ee/app/controllers/projects/insights_controller.rb'
- 'ee/app/controllers/projects/integrations/zentao/issues_controller.rb'
@@ -1160,7 +1095,6 @@ Layout/LineLength:
- 'ee/app/controllers/projects/security/policies_controller.rb'
- 'ee/app/controllers/projects/security/vulnerabilities/notes_controller.rb'
- 'ee/app/controllers/subscriptions_controller.rb'
- - 'ee/app/controllers/trial_registrations_controller.rb'
- 'ee/app/controllers/trials_controller.rb'
- 'ee/app/enums/vulnerabilities/dismissal_reason_enum.rb'
- 'ee/app/finders/compliance_management/merge_requests/compliance_violations_finder.rb'
@@ -1169,12 +1103,10 @@ Layout/LineLength:
- 'ee/app/finders/merge_requests/by_approvers_finder.rb'
- 'ee/app/finders/projects/integrations/jira/by_ids_finder.rb'
- 'ee/app/finders/projects/integrations/jira/issues_finder.rb'
- - 'ee/app/finders/security/findings_finder.rb'
- 'ee/app/finders/security/pipeline_vulnerabilities_finder.rb'
- 'ee/app/finders/security/vulnerabilities_finder.rb'
- 'ee/app/graphql/ee/mutations/boards/lists/create.rb'
- 'ee/app/graphql/ee/mutations/ci/runner/update.rb'
- - 'ee/app/graphql/ee/mutations/issues/create.rb'
- 'ee/app/graphql/ee/resolvers/base_issues_resolver.rb'
- 'ee/app/graphql/mutations/analytics/devops_adoption/enabled_namespaces/bulk_enable.rb'
- 'ee/app/graphql/mutations/audit_events/external_audit_event_destinations/create.rb'
@@ -1194,7 +1126,6 @@ Layout/LineLength:
- 'ee/app/graphql/mutations/incident_management/oncall_rotation/create.rb'
- 'ee/app/graphql/mutations/incident_management/oncall_rotation/update.rb'
- 'ee/app/graphql/mutations/instance_security_dashboard/remove_project.rb'
- - 'ee/app/graphql/mutations/iterations/create.rb'
- 'ee/app/graphql/mutations/iterations/update.rb'
- 'ee/app/graphql/mutations/security/training_provider_update.rb'
- 'ee/app/graphql/mutations/security_policy/assign_security_policy_project.rb'
@@ -1209,13 +1140,11 @@ Layout/LineLength:
- 'ee/app/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver.rb'
- 'ee/app/graphql/resolvers/concerns/resolves_orchestration_policy.rb'
- 'ee/app/graphql/resolvers/dora_metrics_resolver.rb'
- - 'ee/app/graphql/resolvers/epics_resolver.rb'
- 'ee/app/graphql/resolvers/external_issue_resolver.rb'
- 'ee/app/graphql/resolvers/incident_management/oncall_rotations_resolver.rb'
- 'ee/app/graphql/resolvers/incident_management/oncall_schedule_resolver.rb'
- 'ee/app/graphql/resolvers/iterations/cadences_resolver.rb'
- 'ee/app/graphql/resolvers/iterations_resolver.rb'
- - 'ee/app/graphql/resolvers/network_policy_resolver.rb'
- 'ee/app/graphql/resolvers/security_orchestration/scan_execution_policy_resolver.rb'
- 'ee/app/graphql/resolvers/security_report_summary_resolver.rb'
- 'ee/app/graphql/resolvers/timebox_report_resolver.rb'
@@ -1246,8 +1175,6 @@ Layout/LineLength:
- 'ee/app/graphql/types/instance_security_dashboard_type.rb'
- 'ee/app/graphql/types/iteration_sort_enum.rb'
- 'ee/app/graphql/types/iteration_type.rb'
- - 'ee/app/graphql/types/merge_requests/approval_state_type.rb'
- - 'ee/app/graphql/types/network_policy_type.rb'
- 'ee/app/graphql/types/scanned_resource_type.rb'
- 'ee/app/graphql/types/security/training_url_request_status_enum.rb'
- 'ee/app/graphql/types/security_orchestration/orchestration_policy_type.rb'
@@ -1256,7 +1183,6 @@ Layout/LineLength:
- 'ee/app/graphql/types/vulnerability/external_issue_link_external_tracker_enum.rb'
- 'ee/app/graphql/types/vulnerability_confidence_enum.rb'
- 'ee/app/graphql/types/vulnerability_detail_type.rb'
- - 'ee/app/graphql/types/vulnerability_request_type.rb'
- 'ee/app/graphql/types/vulnerability_type.rb'
- 'ee/app/helpers/admin/emails_helper.rb'
- 'ee/app/helpers/admin/ip_restriction_helper.rb'
@@ -1264,7 +1190,6 @@ Layout/LineLength:
- 'ee/app/helpers/analytics/code_review_helper.rb'
- 'ee/app/helpers/billing_plans_helper.rb'
- 'ee/app/helpers/ee/application_helper.rb'
- - 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/button_helper.rb'
- 'ee/app/helpers/ee/environments_helper.rb'
- 'ee/app/helpers/ee/feature_flags_helper.rb'
@@ -1279,7 +1204,6 @@ Layout/LineLength:
- 'ee/app/helpers/ee/lock_helper.rb'
- 'ee/app/helpers/ee/merge_requests_helper.rb'
- 'ee/app/helpers/ee/mirror_helper.rb'
- - 'ee/app/helpers/ee/nav/top_nav_helper.rb'
- 'ee/app/helpers/ee/notes_helper.rb'
- 'ee/app/helpers/ee/personal_access_tokens_helper.rb'
- 'ee/app/helpers/ee/profiles_helper.rb'
@@ -1300,11 +1224,9 @@ Layout/LineLength:
- 'ee/app/helpers/projects/security/dast_profiles_helper.rb'
- 'ee/app/helpers/projects/security/discover_helper.rb'
- 'ee/app/helpers/push_rules_helper.rb'
- - 'ee/app/helpers/security_helper.rb'
- 'ee/app/helpers/trial_status_widget_helper.rb'
- 'ee/app/helpers/vulnerabilities_helper.rb'
- 'ee/app/mailers/ee/emails/profile.rb'
- - 'ee/app/mailers/ee/emails/projects.rb'
- 'ee/app/mailers/ee/preview/notify_preview.rb'
- 'ee/app/mailers/emails/namespace_storage_usage_mailer.rb'
- 'ee/app/models/analytics/cycle_analytics/group_stage.rb'
@@ -1346,7 +1268,6 @@ Layout/LineLength:
- 'ee/app/models/ee/key.rb'
- 'ee/app/models/ee/lfs_object.rb'
- 'ee/app/models/ee/list.rb'
- - 'ee/app/models/ee/member.rb'
- 'ee/app/models/ee/merge_request/metrics.rb'
- 'ee/app/models/ee/merge_request_diff.rb'
- 'ee/app/models/ee/milestone_release.rb'
@@ -1455,7 +1376,6 @@ Layout/LineLength:
- 'ee/app/services/ee/auth/container_registry_authentication_service.rb'
- 'ee/app/services/ee/boards/base_service.rb'
- 'ee/app/services/ee/ci/job_artifacts/destroy_batch_service.rb'
- - 'ee/app/services/ee/ci/queue/build_queue_service.rb'
- 'ee/app/services/ee/ci/register_job_service.rb'
- 'ee/app/services/ee/ci/retry_pipeline_service.rb'
- 'ee/app/services/ee/groups/autocomplete_service.rb'
@@ -1469,11 +1389,8 @@ Layout/LineLength:
- 'ee/app/services/ee/issuable/common_system_notes_service.rb'
- 'ee/app/services/ee/issues/base_service.rb'
- 'ee/app/services/ee/issues/clone_service.rb'
- - 'ee/app/services/ee/issues/move_service.rb'
- - 'ee/app/services/ee/merge_requests/base_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/notification_service.rb'
- 'ee/app/services/ee/personal_access_tokens/create_service.rb'
- 'ee/app/services/ee/personal_access_tokens/revoke_service.rb'
- 'ee/app/services/ee/projects/create_from_template_service.rb'
@@ -1482,13 +1399,11 @@ Layout/LineLength:
- 'ee/app/services/ee/projects/deploy_tokens/destroy_service.rb'
- 'ee/app/services/ee/projects/gitlab_projects_import_service.rb'
- 'ee/app/services/ee/projects/group_links/create_service.rb'
- - 'ee/app/services/ee/projects/transfer_service.rb'
- 'ee/app/services/ee/projects/update_service.rb'
- 'ee/app/services/ee/protected_branches/api_service.rb'
- 'ee/app/services/ee/protected_branches/create_service.rb'
- 'ee/app/services/ee/protected_branches/update_service.rb'
- 'ee/app/services/ee/resource_access_tokens/create_service.rb'
- - 'ee/app/services/ee/resource_events/change_labels_service.rb'
- 'ee/app/services/ee/system_note_service.rb'
- 'ee/app/services/ee/users/update_service.rb'
- 'ee/app/services/elastic/cluster_reindexing_service.rb'
@@ -1496,7 +1411,6 @@ Layout/LineLength:
- 'ee/app/services/epics/issue_promote_service.rb'
- 'ee/app/services/epics/update_service.rb'
- 'ee/app/services/external_status_checks/create_service.rb'
- - 'ee/app/services/external_status_checks/dispatch_service.rb'
- 'ee/app/services/geo/blob_upload_service.rb'
- 'ee/app/services/geo/event_service.rb'
- 'ee/app/services/geo/file_registry_removal_service.rb'
@@ -1536,7 +1450,6 @@ Layout/LineLength:
- 'ee/app/services/projects/licenses/create_policy_service.rb'
- 'ee/app/services/projects/mark_for_deletion_service.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
- - 'ee/app/services/requirements_management/update_requirement_service.rb'
- 'ee/app/services/resource_events/change_weight_service.rb'
- 'ee/app/services/security/auto_fix_service.rb'
- 'ee/app/services/security/dependency_list_service.rb'
@@ -1554,7 +1467,6 @@ Layout/LineLength:
- 'ee/app/services/security/security_orchestration_policies/policy_configuration_validation_service.rb'
- 'ee/app/services/security/security_orchestration_policies/process_policy_service.rb'
- 'ee/app/services/security/security_orchestration_policies/project_create_service.rb'
- - 'ee/app/services/security/security_orchestration_policies/rule_schedule_service.rb'
- 'ee/app/services/security/security_orchestration_policies/validate_policy_service.rb'
- 'ee/app/services/security/store_scan_service.rb'
- 'ee/app/services/security/track_scan_service.rb'
@@ -1563,7 +1475,6 @@ Layout/LineLength:
- 'ee/app/services/system_notes/escalations_service.rb'
- 'ee/app/services/timebox_report_service.rb'
- 'ee/app/services/vulnerabilities/base_service.rb'
- - 'ee/app/services/vulnerabilities/confirm_service.rb'
- 'ee/app/services/vulnerabilities/dismiss_service.rb'
- 'ee/app/services/vulnerabilities/historical_statistics/adjustment_service.rb'
- 'ee/app/services/vulnerabilities/resolve_service.rb'
@@ -1626,11 +1537,6 @@ Layout/LineLength:
- 'ee/db/geo/migrate/20211124000002_add_indexes_to_lfs_object_registry.rb'
- 'ee/db/geo/migrate/20211207162157_add_indexes_to_pages_deployment_registry.rb'
- 'ee/db/geo/post_migrate/20220202101354_migrate_job_artifact_registry.rb'
- - 'ee/elastic/migrate/20210302104500_migrate_notes_to_separate_index.rb'
- - 'ee/elastic/migrate/20210421140400_add_new_data_to_merge_requests_documents.rb'
- - 'ee/elastic/migrate/20210429154500_migrate_merge_requests_to_separate_index.rb'
- - 'ee/elastic/migrate/20210510113500_delete_merge_requests_from_original_index.rb'
- - 'ee/elastic/migrate/20210510143200_delete_notes_from_original_index.rb'
- 'ee/lib/analytics/devops_adoption/snapshot_calculator.rb'
- 'ee/lib/analytics/productivity_analytics_request_params.rb'
- 'ee/lib/api/analytics/code_review_analytics.rb'
@@ -1645,9 +1551,7 @@ Layout/LineLength:
- 'ee/lib/api/group_push_rule.rb'
- 'ee/lib/api/group_repository_storage_moves.rb'
- 'ee/lib/api/helpers/project_approval_rules_helpers.rb'
- - 'ee/lib/api/iterations.rb'
- 'ee/lib/api/license.rb'
- - 'ee/lib/api/managed_licenses.rb'
- 'ee/lib/api/merge_request_approval_rules.rb'
- 'ee/lib/api/merge_request_approval_settings.rb'
- 'ee/lib/api/project_approval_rules.rb'
@@ -1688,7 +1592,6 @@ Layout/LineLength:
- 'ee/lib/ee/api/namespaces.rb'
- 'ee/lib/ee/api/protected_branches.rb'
- 'ee/lib/ee/audit/project_changes_auditor.rb'
- - 'ee/lib/ee/audit/protected_branches_changes_auditor.rb'
- 'ee/lib/ee/banzai/filter/references/iteration_reference_filter.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/data_collector.rb'
@@ -1703,13 +1606,10 @@ Layout/LineLength:
- 'ee/lib/ee/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids.rb'
- - 'ee/lib/ee/gitlab/background_migration/populate_namespace_statistics.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
- - 'ee/lib/ee/gitlab/background_migration/populate_status_column_of_security_scans.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings.rb'
- 'ee/lib/ee/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb'
- 'ee/lib/ee/gitlab/background_migration/update_vulnerability_occurrences_location.rb'
- - 'ee/lib/ee/gitlab/checks/diff_check.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/commit_check.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/file_size_check.rb'
- 'ee/lib/ee/gitlab/ci/config_ee.rb'
@@ -1719,7 +1619,6 @@ Layout/LineLength:
- 'ee/lib/ee/gitlab/ci/reports/security/reports.rb'
- 'ee/lib/ee/gitlab/ci/status/build/manual.rb'
- 'ee/lib/ee/gitlab/git_access.rb'
- - 'ee/lib/ee/gitlab/graphql/pagination/keyset/order_info.rb'
- 'ee/lib/ee/gitlab/import_export/after_export_strategies/custom_template_export_import_strategy.rb'
- 'ee/lib/ee/gitlab/middleware/read_only/controller.rb'
- 'ee/lib/ee/gitlab/project_template.rb'
@@ -1741,7 +1640,6 @@ Layout/LineLength:
- 'ee/lib/elastic/latest/git_instance_proxy.rb'
- 'ee/lib/elastic/latest/issue_class_proxy.rb'
- 'ee/lib/elastic/latest/issue_instance_proxy.rb'
- - 'ee/lib/elastic/latest/merge_request_class_proxy.rb'
- 'ee/lib/elastic/latest/note_class_proxy.rb'
- 'ee/lib/elastic/latest/project_class_proxy.rb'
- 'ee/lib/elastic/latest/repository_class_proxy.rb'
@@ -1758,7 +1656,6 @@ Layout/LineLength:
- 'ee/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_label_removed.rb'
- 'ee/lib/gitlab/analytics/cycle_analytics/summary/base_time.rb'
- 'ee/lib/gitlab/analytics/cycle_analytics/summary/group/deployment_frequency.rb'
- - 'ee/lib/gitlab/analytics/cycle_analytics/summary/lead_time.rb'
- 'ee/lib/gitlab/auth/group_saml/response_check.rb'
- 'ee/lib/gitlab/auth/group_saml/session_enforcer.rb'
- 'ee/lib/gitlab/auth/group_saml/user.rb'
@@ -1843,7 +1740,6 @@ Layout/LineLength:
- 'ee/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb'
- 'ee/spec/controllers/projects/audit_events_controller_spec.rb'
- 'ee/spec/controllers/projects/dependencies_controller_spec.rb'
- - 'ee/spec/controllers/projects/insights_controller_spec.rb'
- 'ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb'
- 'ee/spec/controllers/projects/integrations/zentao/issues_controller_spec.rb'
- 'ee/spec/controllers/projects/issues_controller_spec.rb'
@@ -1862,12 +1758,6 @@ Layout/LineLength:
- 'ee/spec/controllers/registrations/welcome_controller_spec.rb'
- 'ee/spec/controllers/subscriptions/groups_controller_spec.rb'
- 'ee/spec/controllers/subscriptions_controller_spec.rb'
- - 'ee/spec/controllers/trials_controller_spec.rb'
- - 'ee/spec/elastic/migrate/20210201104800_migrate_notes_to_separate_index_spec.rb'
- - 'ee/spec/elastic/migrate/20210421140400_add_new_data_to_merge_requests_documents_spec.rb'
- - 'ee/spec/elastic/migrate/20210429154500_migrate_merge_requests_to_separate_index_spec.rb'
- - 'ee/spec/elastic/migrate/20210510113500_delete_merge_requests_from_original_index_spec.rb'
- - 'ee/spec/elastic/migrate/20210510143200_delete_notes_from_original_index_spec.rb'
- 'ee/spec/elastic/migrate/migration_shared_examples.rb'
- 'ee/spec/factories/ci/builds.rb'
- 'ee/spec/factories/ci/job_artifacts.rb'
@@ -1879,7 +1769,6 @@ Layout/LineLength:
- 'ee/spec/factories/geo/container_repository_registry.rb'
- 'ee/spec/factories/iterations.rb'
- 'ee/spec/factories/namespaces.rb'
- - 'ee/spec/factories/requirements_management/requirements.rb'
- 'ee/spec/factories/vulnerabilities/exports.rb'
- 'ee/spec/factories/vulnerabilities/findings.rb'
- 'ee/spec/features/admin/admin_audit_logs_spec.rb'
@@ -1898,7 +1787,6 @@ Layout/LineLength:
- 'ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb'
- 'ee/spec/features/boards/user_visits_board_spec.rb'
- 'ee/spec/features/burnup_charts_spec.rb'
- - 'ee/spec/features/ci_shared_runner_warnings_spec.rb'
- 'ee/spec/features/dashboards/operations_spec.rb'
- 'ee/spec/features/epic_boards/epic_boards_spec.rb'
- 'ee/spec/features/epics/epic_issues_spec.rb'
@@ -1935,7 +1823,6 @@ Layout/LineLength:
- 'ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb'
- 'ee/spec/features/issues/form_spec.rb'
- 'ee/spec/features/issues/issue_sidebar_spec.rb'
- - 'ee/spec/features/issues/user_sees_empty_state_spec.rb'
- 'ee/spec/features/labels_hierarchy_spec.rb'
- 'ee/spec/features/merge_request/user_approves_spec.rb'
- 'ee/spec/features/merge_request/user_approves_with_password_spec.rb'
@@ -1950,7 +1837,6 @@ Layout/LineLength:
- 'ee/spec/features/merge_trains/user_adds_to_merge_train_when_pipeline_succeeds_spec.rb'
- 'ee/spec/features/pending_group_memberships_spec.rb'
- 'ee/spec/features/projects/audit_events_spec.rb'
- - 'ee/spec/features/projects/custom_projects_template_spec.rb'
- 'ee/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb'
- 'ee/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb'
- 'ee/spec/features/projects/integrations/prometheus_custom_metrics_spec.rb'
@@ -1983,7 +1869,6 @@ Layout/LineLength:
- 'ee/spec/finders/analytics/devops_adoption/enabled_namespaces_finder_spec.rb'
- 'ee/spec/finders/analytics/devops_adoption/snapshots_finder_spec.rb'
- 'ee/spec/finders/audit_event_finder_spec.rb'
- - 'ee/spec/finders/billed_users_finder_spec.rb'
- 'ee/spec/finders/boards/users_finder_spec.rb'
- 'ee/spec/finders/compliance_management/merge_requests/compliance_violations_finder_spec.rb'
- 'ee/spec/finders/custom_project_templates_finder_spec.rb'
@@ -1992,7 +1877,7 @@ Layout/LineLength:
- 'ee/spec/finders/ee/group_members_finder_spec.rb'
- 'ee/spec/finders/ee/projects_finder_spec.rb'
- 'ee/spec/finders/epics_finder_spec.rb'
- - 'ee/spec/finders/geo/container_repository_registry_finder_spec.rb'
+ - 'ee/spec/finders/geo/container_repository_legacy_registry_finder_spec.rb'
- 'ee/spec/finders/geo/project_registry_finder_spec.rb'
- 'ee/spec/finders/geo/project_registry_status_finder_spec.rb'
- 'ee/spec/finders/group_projects_finder_spec.rb'
@@ -2034,14 +1919,12 @@ Layout/LineLength:
- 'ee/spec/graphql/ee/types/board_type_spec.rb'
- 'ee/spec/graphql/ee/types/issue_sort_enum_spec.rb'
- 'ee/spec/graphql/ee/types/merge_request_type_spec.rb'
- - 'ee/spec/graphql/ee/types/mutation_type_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/create_spec.rb'
- 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
- 'ee/spec/graphql/mutations/boards/lists/update_limit_metrics_spec.rb'
- 'ee/spec/graphql/mutations/compliance_management/frameworks/update_spec.rb'
- 'ee/spec/graphql/mutations/dast/profiles/run_spec.rb'
- 'ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb'
- - 'ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb'
- 'ee/spec/graphql/mutations/dast_scanner_profiles/update_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_profiles/create_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_profiles/update_spec.rb'
@@ -2079,7 +1962,6 @@ Layout/LineLength:
- 'ee/spec/graphql/resolvers/iterations/cadences_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/iterations_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/network_policy_resolver_spec.rb'
- - 'ee/spec/graphql/resolvers/path_locks_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/pipeline_security_report_findings_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/requirements_management/requirements_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/requirements_management/test_reports_resolver_spec.rb'
@@ -2092,7 +1974,6 @@ Layout/LineLength:
- 'ee/spec/graphql/resolvers/vulnerabilities_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/vulnerability_severities_count_resolver_spec.rb'
- 'ee/spec/graphql/types/alert_management/payload_alert_field_name_enum_spec.rb'
- - 'ee/spec/graphql/types/asset_type_spec.rb'
- 'ee/spec/graphql/types/ci/minutes/namespace_monthly_usage_type_spec.rb'
- 'ee/spec/graphql/types/dast/profile_schedule_type_spec.rb'
- 'ee/spec/graphql/types/dast_scanner_profile_type_spec.rb'
@@ -2100,20 +1981,14 @@ Layout/LineLength:
- 'ee/spec/graphql/types/epic_sort_enum_spec.rb'
- 'ee/spec/graphql/types/incident_management/escalation_rule_input_type_spec.rb'
- 'ee/spec/graphql/types/issue_type_spec.rb'
- - 'ee/spec/graphql/types/network_policy_type_spec.rb'
- 'ee/spec/graphql/types/permission_types/vulnerability_spec.rb'
- 'ee/spec/graphql/types/pipeline_security_report_finding_type_spec.rb'
- 'ee/spec/graphql/types/project_type_spec.rb'
- 'ee/spec/graphql/types/security_scanner_type_enum_spec.rb'
- 'ee/spec/graphql/types/vulnerability_details/file_location_type_spec.rb'
- - 'ee/spec/graphql/types/vulnerability_evidence_source_type_spec.rb'
- - 'ee/spec/graphql/types/vulnerability_evidence_supporting_message_type_spec.rb'
- 'ee/spec/graphql/types/vulnerability_evidence_type_spec.rb'
- 'ee/spec/graphql/types/vulnerability_report_type_enum_spec.rb'
- - 'ee/spec/graphql/types/vulnerability_request_response_header_type_spec.rb'
- - 'ee/spec/graphql/types/vulnerability_request_type_spec.rb'
- 'ee/spec/graphql/types/vulnerability_response_type_spec.rb'
- - 'ee/spec/graphql/types/vulnerability_sort_enum_spec.rb'
- 'ee/spec/graphql/types/vulnerability_type_spec.rb'
- 'ee/spec/helpers/admin/emails_helper_spec.rb'
- 'ee/spec/helpers/analytics/code_review_helper_spec.rb'
@@ -2128,7 +2003,6 @@ Layout/LineLength:
- 'ee/spec/helpers/ee/feature_flags_helper_spec.rb'
- 'ee/spec/helpers/ee/gitlab_routing_helper_spec.rb'
- 'ee/spec/helpers/ee/groups/group_members_helper_spec.rb'
- - 'ee/spec/helpers/ee/groups/settings_helper_spec.rb'
- 'ee/spec/helpers/ee/groups_helper_spec.rb'
- 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- 'ee/spec/helpers/ee/issuables_helper_spec.rb'
@@ -2139,7 +2013,6 @@ Layout/LineLength:
- 'ee/spec/helpers/ee/projects/pipeline_helper_spec.rb'
- 'ee/spec/helpers/ee/projects/security/api_fuzzing_configuration_helper_spec.rb'
- 'ee/spec/helpers/ee/projects/security/dast_configuration_helper_spec.rb'
- - 'ee/spec/helpers/ee/registrations_helper_spec.rb'
- 'ee/spec/helpers/ee/subscribable_banner_helper_spec.rb'
- 'ee/spec/helpers/ee/users/callouts_helper_spec.rb'
- 'ee/spec/helpers/ee/version_check_helper_spec.rb'
@@ -2157,9 +2030,7 @@ Layout/LineLength:
- 'ee/spec/helpers/projects/security/dast_profiles_helper_spec.rb'
- 'ee/spec/helpers/projects_helper_spec.rb'
- 'ee/spec/helpers/push_rules_helper_spec.rb'
- - 'ee/spec/helpers/routing/pseudonymization_helper_spec.rb'
- 'ee/spec/helpers/search_helper_spec.rb'
- - 'ee/spec/helpers/security_helper_spec.rb'
- 'ee/spec/helpers/subscriptions_helper_spec.rb'
- 'ee/spec/helpers/timeboxes_helper_spec.rb'
- 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
@@ -2177,7 +2048,6 @@ Layout/LineLength:
- 'ee/spec/lib/bulk_imports/projects/pipelines/push_rule_pipeline_spec.rb'
- 'ee/spec/lib/compliance_management/merge_request_approval_settings/resolver_spec.rb'
- 'ee/spec/lib/container_registry/client_spec.rb'
- - 'ee/spec/lib/ee/api/entities/billable_member_spec.rb'
- 'ee/spec/lib/ee/api/entities/deployment_extended_spec.rb'
- 'ee/spec/lib/ee/api/entities/vulnerability_export_spec.rb'
- 'ee/spec/lib/ee/api/helpers_spec.rb'
@@ -2232,7 +2102,6 @@ Layout/LineLength:
- 'ee/spec/lib/ee/sidebars/projects/menus/security_compliance_menu_spec.rb'
- 'ee/spec/lib/elastic/latest/config_shared_examples.rb'
- 'ee/spec/lib/elastic/latest/custom_language_analyzers_spec.rb'
- - 'ee/spec/lib/elastic/latest/git_class_proxy_spec.rb'
- 'ee/spec/lib/elastic/multi_version_class_proxy_spec.rb'
- 'ee/spec/lib/elastic/multi_version_instance_proxy_spec.rb'
- 'ee/spec/lib/gem_extensions/elasticsearch/model/adapter/active_record/records_spec.rb'
@@ -2290,7 +2159,6 @@ Layout/LineLength:
- 'ee/spec/lib/gitlab/custom_file_templates_spec.rb'
- 'ee/spec/lib/gitlab/data_builder/vulnerability_spec.rb'
- 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/client_spec.rb'
- 'ee/spec/lib/gitlab/elastic/group_search_results_spec.rb'
- 'ee/spec/lib/gitlab/elastic/indexer_spec.rb'
- 'ee/spec/lib/gitlab/elastic/project_search_results_spec.rb'
@@ -2299,7 +2167,6 @@ Layout/LineLength:
- 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'ee/spec/lib/gitlab/email/message/account_validation_spec.rb'
- 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- - 'ee/spec/lib/gitlab/geo/cron_manager_spec.rb'
- 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- 'ee/spec/lib/gitlab/geo/geo_tasks_spec.rb'
- 'ee/spec/lib/gitlab/geo/git_ssh_proxy_spec.rb'
@@ -2320,7 +2187,6 @@ Layout/LineLength:
- 'ee/spec/lib/gitlab/graphql/aggregations/vulnerabilities/lazy_user_notes_count_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/graphql/loaders/bulk_epic_aggregate_loader_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb'
- 'ee/spec/lib/gitlab/import_export/attributes_permitter_spec.rb'
- 'ee/spec/lib/gitlab/import_export/group/group_and_descendants_repo_restorer_spec.rb'
- 'ee/spec/lib/gitlab/insights/finders/issuable_finder_spec.rb'
@@ -2396,7 +2262,6 @@ Layout/LineLength:
- 'ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb'
- 'ee/spec/models/ci/minutes/project_monthly_usage_spec.rb'
- 'ee/spec/models/ci/pipeline_spec.rb'
- - 'ee/spec/models/ci/subscriptions/project_spec.rb'
- 'ee/spec/models/concerns/ee/clusters/agents/authorization_config_scopes_spec.rb'
- 'ee/spec/models/concerns/ee/issuable_spec.rb'
- 'ee/spec/models/concerns/ee/noteable_spec.rb'
@@ -2428,7 +2293,6 @@ Layout/LineLength:
- 'ee/spec/models/ee/audit_event_spec.rb'
- 'ee/spec/models/ee/ci/job_artifact_spec.rb'
- 'ee/spec/models/ee/ci/pipeline_artifact_spec.rb'
- - 'ee/spec/models/ee/ci/runner_spec.rb'
- 'ee/spec/models/ee/group_spec.rb'
- 'ee/spec/models/ee/incident_management/project_incident_management_setting_spec.rb'
- 'ee/spec/models/ee/integrations/jira_spec.rb'
@@ -2453,7 +2317,6 @@ Layout/LineLength:
- 'ee/spec/models/epic_spec.rb'
- 'ee/spec/models/geo/container_repository_registry_spec.rb'
- 'ee/spec/models/geo/event_log_spec.rb'
- - 'ee/spec/models/geo/job_artifact_registry_spec.rb'
- 'ee/spec/models/geo/package_file_registry_spec.rb'
- 'ee/spec/models/geo/project_registry_spec.rb'
- 'ee/spec/models/geo/secondary_usage_data_spec.rb'
@@ -2470,7 +2333,6 @@ Layout/LineLength:
- 'ee/spec/models/incident_management/oncall_shift_spec.rb'
- 'ee/spec/models/instance_security_dashboard_spec.rb'
- 'ee/spec/models/integrations/chat_message/vulnerability_message_spec.rb'
- - 'ee/spec/models/integrations/github_spec.rb'
- 'ee/spec/models/issuable_sla_spec.rb'
- 'ee/spec/models/issue_spec.rb'
- 'ee/spec/models/license_spec.rb'
@@ -2523,15 +2385,12 @@ Layout/LineLength:
- 'ee/spec/presenters/audit_event_presenter_spec.rb'
- 'ee/spec/presenters/ci/build_runner_presenter_spec.rb'
- 'ee/spec/presenters/ci/pipeline_presenter_spec.rb'
- - 'ee/spec/presenters/ee/issue_presenter_spec.rb'
- 'ee/spec/presenters/epic_issue_presenter_spec.rb'
- 'ee/spec/presenters/epic_presenter_spec.rb'
- 'ee/spec/presenters/group_member_presenter_spec.rb'
- 'ee/spec/presenters/merge_request_presenter_spec.rb'
- 'ee/spec/presenters/security/scan_presenter_spec.rb'
- - 'ee/spec/presenters/vulnerabilities/finding_presenter_spec.rb'
- 'ee/spec/presenters/vulnerability_presenter_spec.rb'
- - 'ee/spec/replicators/geo/upload_replicator_spec.rb'
- 'ee/spec/requests/admin/credentials_controller_spec.rb'
- 'ee/spec/requests/admin/geo/replicables_controller_spec.rb'
- 'ee/spec/requests/admin/user_permission_exports_controller_spec.rb'
@@ -2587,7 +2446,6 @@ Layout/LineLength:
- 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/epics/add_issue_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/issues/create_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/issues/set_weight_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/iterations/cadences/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/iterations/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/iterations/update_spec.rb'
@@ -2687,8 +2545,6 @@ Layout/LineLength:
- 'ee/spec/serializers/environment_entity_spec.rb'
- 'ee/spec/serializers/epic_entity_spec.rb'
- 'ee/spec/serializers/fork_namespace_entity_spec.rb'
- - 'ee/spec/serializers/integrations/jira_serializers/issue_detail_entity_spec.rb'
- - 'ee/spec/serializers/integrations/jira_serializers/issue_entity_spec.rb'
- 'ee/spec/serializers/member_entity_spec.rb'
- 'ee/spec/serializers/project_mirror_entity_spec.rb'
- 'ee/spec/serializers/security/license_policy_entity_spec.rb'
@@ -2729,7 +2585,6 @@ Layout/LineLength:
- 'ee/spec/services/approval_rules/create_service_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/params_filtering_service_spec.rb'
- - 'ee/spec/services/arkose/user_verification_service_spec.rb'
- 'ee/spec/services/audit_events/protected_branch_audit_event_service_spec.rb'
- 'ee/spec/services/audit_events/register_runner_audit_event_service_spec.rb'
- 'ee/spec/services/audit_events/release_associate_milestone_audit_event_service_spec.rb'
@@ -2768,7 +2623,6 @@ Layout/LineLength:
- 'ee/spec/services/ee/groups/import_export/export_service_spec.rb'
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
- 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
- - 'ee/spec/services/ee/issuable/destroy_service_spec.rb'
- 'ee/spec/services/ee/issue_links/create_service_spec.rb'
- 'ee/spec/services/ee/issues/clone_service_spec.rb'
- 'ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb'
@@ -2861,7 +2715,6 @@ Layout/LineLength:
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
- 'ee/spec/services/projects/cleanup_service_spec.rb'
- 'ee/spec/services/projects/gitlab_projects_import_service_spec.rb'
- - 'ee/spec/services/projects/group_links/create_service_spec.rb'
- 'ee/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb'
- 'ee/spec/services/projects/import_export/export_service_spec.rb'
- 'ee/spec/services/projects/mark_for_deletion_service_spec.rb'
@@ -2870,7 +2723,6 @@ Layout/LineLength:
- 'ee/spec/services/projects/update_service_spec.rb'
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- 'ee/spec/services/requirements_management/export_csv_service_spec.rb'
- - 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
- 'ee/spec/services/resource_events/change_weight_service_spec.rb'
- 'ee/spec/services/search/global_service_spec.rb'
- 'ee/spec/services/search/group_service_spec.rb'
@@ -2887,7 +2739,6 @@ Layout/LineLength:
- 'ee/spec/services/security/ingestion/tasks/ingest_findings_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_identifiers_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_remediations_spec.rb'
- - 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_vulnerability_flags_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_vulnerability_statistics_spec.rb'
- 'ee/spec/services/security/merge_reports_service_spec.rb'
@@ -2917,13 +2768,11 @@ Layout/LineLength:
- 'ee/spec/services/timebox_report_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
- 'ee/spec/services/user_permissions/export_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/destroy_dismissal_feedback_service_spec.rb'
- 'ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
- 'ee/spec/services/vulnerabilities/finding_dismiss_service_spec.rb'
- 'ee/spec/services/vulnerabilities/historical_statistics/adjustment_service_spec.rb'
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
- 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/starboard_vulnerability_resolve_service_spec.rb'
- 'ee/spec/services/vulnerabilities/statistics/adjustment_service_spec.rb'
- 'ee/spec/services/vulnerabilities/update_service_spec.rb'
- 'ee/spec/services/vulnerability_exports/create_service_spec.rb'
@@ -2954,7 +2803,6 @@ Layout/LineLength:
- 'ee/spec/support/shared_examples/controllers/concerns/description_diff_actions_shared_examples.rb'
- 'ee/spec/support/shared_examples/controllers/projects/license_scanning_report_comparison_shared_examples.rb'
- 'ee/spec/support/shared_examples/features/epics_filtered_search_shared_examples.rb'
- - 'ee/spec/support/shared_examples/features/over_free_user_limit_shared_examples.rb'
- 'ee/spec/support/shared_examples/features/protected_branches_access_control_shared_examples.rb'
- 'ee/spec/support/shared_examples/features/sidebar_shared_examples.rb'
- 'ee/spec/support/shared_examples/finders/geo/file_registry_finder_shared_examples.rb'
@@ -2978,8 +2826,6 @@ Layout/LineLength:
- 'ee/spec/support/shared_examples/quick_actions/merge_request/unassign_reviewer_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/api/graphql/geo/registries_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/boards/base_service_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/build_execute_shared_examples.rb'
@@ -2987,10 +2833,8 @@ Layout/LineLength:
- 'ee/spec/support/shared_examples/services/dast_on_demand_scans_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/geo/geo_request_service_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/group_saml/saml_provider/base_service_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/issue_epic_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/scoped_label_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/search_notes_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/sync_issue_and_requirement_state_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/vulnerabilities/calls_vulnerability_statistics_utility_services_in_order.rb'
- 'ee/spec/support/shared_examples/views/subscription_shared_examples.rb'
- 'ee/spec/tasks/geo/git_rake_spec.rb'
@@ -3017,13 +2861,10 @@ Layout/LineLength:
- 'ee/spec/views/shared/credentials_inventory/personal_access_tokens/_personal_access_token.html.haml_spec.rb'
- 'ee/spec/views/shared/credentials_inventory/project_access_tokens/_project_access_token.html.haml_spec.rb'
- 'ee/spec/views/shared/promotions/_promotion_link_project.html.haml_spec.rb'
- - 'ee/spec/views/subscriptions/groups/edit.html.haml_spec.rb'
- - 'ee/spec/views/trial_registrations/new.html.haml_spec.rb'
- 'ee/spec/workers/active_user_count_threshold_worker_spec.rb'
- 'ee/spec/workers/adjourned_group_deletion_worker_spec.rb'
- 'ee/spec/workers/adjourned_projects_deletion_cron_worker_spec.rb'
- 'ee/spec/workers/analytics/cycle_analytics/consistency_worker_spec.rb'
- - 'ee/spec/workers/analytics/cycle_analytics/incremental_worker_spec.rb'
- 'ee/spec/workers/analytics/devops_adoption/create_all_snapshots_worker_spec.rb'
- 'ee/spec/workers/analytics/devops_adoption/create_snapshot_worker_spec.rb'
- 'ee/spec/workers/app_sec/dast/profile_schedule_worker_spec.rb'
@@ -3062,8 +2903,6 @@ Layout/LineLength:
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/refresh_license_compliance_checks_worker_spec.rb'
- 'ee/spec/workers/repository_import_worker_spec.rb'
- - 'ee/spec/workers/scan_security_report_secrets_worker_spec.rb'
- - 'ee/spec/workers/security/create_orchestration_policy_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_namespace_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb'
- 'ee/spec/workers/store_security_reports_worker_spec.rb'
@@ -3117,7 +2956,6 @@ Layout/LineLength:
- 'lib/api/generic_packages.rb'
- 'lib/api/go_proxy.rb'
- 'lib/api/group_clusters.rb'
- - 'lib/api/group_container_repositories.rb'
- 'lib/api/group_import.rb'
- 'lib/api/group_labels.rb'
- 'lib/api/group_packages.rb'
@@ -3132,7 +2970,6 @@ Layout/LineLength:
- 'lib/api/helpers/file_upload_helpers.rb'
- 'lib/api/helpers/groups_helpers.rb'
- 'lib/api/helpers/integrations_helpers.rb'
- - 'lib/api/helpers/internal_helpers.rb'
- 'lib/api/helpers/label_helpers.rb'
- 'lib/api/helpers/members_helpers.rb'
- 'lib/api/helpers/merge_requests_helpers.rb'
@@ -3229,7 +3066,6 @@ Layout/LineLength:
- 'lib/container_registry/base_client.rb'
- 'lib/declarative_enum.rb'
- 'lib/error_tracking/collector/payload_validator.rb'
- - 'lib/error_tracking/sentry_client/issue.rb'
- 'lib/feature.rb'
- 'lib/feature/definition.rb'
- 'lib/file_size_validator.rb'
@@ -3266,7 +3102,6 @@ Layout/LineLength:
- 'lib/gitlab/background_migration/backfill_snippet_repositories.rb'
- 'lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb'
- 'lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb'
- - 'lib/gitlab/background_migration/copy_column_using_background_migration_job.rb'
- 'lib/gitlab/background_migration/create_security_setting.rb'
- 'lib/gitlab/background_migration/drop_invalid_remediations.rb'
- 'lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
@@ -3286,7 +3121,6 @@ Layout/LineLength:
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- 'lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb'
- 'lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects.rb'
- - 'lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects.rb'
- 'lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb'
- 'lib/gitlab/batch_pop_queueing.rb'
- 'lib/gitlab/bitbucket_import/importer.rb'
@@ -3342,8 +3176,6 @@ Layout/LineLength:
- 'lib/gitlab/composer/version_index.rb'
- 'lib/gitlab/config/entry/configurable.rb'
- 'lib/gitlab/config/entry/validators.rb'
- - 'lib/gitlab/config_checker/external_database_checker.rb'
- - 'lib/gitlab/config_checker/puma_rugged_checker.rb'
- 'lib/gitlab/conflict/file.rb'
- 'lib/gitlab/conflict/file_collection.rb'
- 'lib/gitlab/content_security_policy/config_loader.rb'
@@ -3351,7 +3183,6 @@ Layout/LineLength:
- 'lib/gitlab/current_settings.rb'
- 'lib/gitlab/cycle_analytics/summary/deploy.rb'
- 'lib/gitlab/cycle_analytics/summary/deployment_frequency.rb'
- - 'lib/gitlab/data_builder/push.rb'
- 'lib/gitlab/database.rb'
- 'lib/gitlab/database/as_with_materialized.rb'
- 'lib/gitlab/database/async_indexes/migration_helpers.rb'
@@ -3362,7 +3193,6 @@ Layout/LineLength:
- 'lib/gitlab/database/batch_counter.rb'
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/database/gitlab_schema.rb'
- - 'lib/gitlab/database/load_balancing/configuration.rb'
- 'lib/gitlab/database/load_balancing/host.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb'
@@ -3370,11 +3200,9 @@ Layout/LineLength:
- 'lib/gitlab/database/migrations/background_migration_helpers.rb'
- 'lib/gitlab/database/migrations/batched_background_migration_helpers.rb'
- 'lib/gitlab/database/migrations/runner.rb'
- - 'lib/gitlab/database/migrations/test_background_runner.rb'
- 'lib/gitlab/database/partitioning/detached_partition_dropper.rb'
- 'lib/gitlab/database/partitioning/partition_monitoring.rb'
- 'lib/gitlab/database/partitioning/replace_table.rb'
- - 'lib/gitlab/database/partitioning/single_numeric_list_partition.rb'
- 'lib/gitlab/database/partitioning/time_partition.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb'
@@ -3385,7 +3213,6 @@ Layout/LineLength:
- 'lib/gitlab/database/postgres_partition.rb'
- 'lib/gitlab/database/postgres_partitioned_table.rb'
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
- - 'lib/gitlab/database/query_analyzers/restrict_allowed_schemas.rb'
- 'lib/gitlab/database/reflection.rb'
- 'lib/gitlab/database/reindexing.rb'
- 'lib/gitlab/database/reindexing/coordinator.rb'
@@ -3406,13 +3233,11 @@ Layout/LineLength:
- 'lib/gitlab/diff/formatters/base_formatter.rb'
- 'lib/gitlab/diff/highlight_cache.rb'
- 'lib/gitlab/diff/parser.rb'
- - 'lib/gitlab/diff/rendered/notebook/diff_file.rb'
- 'lib/gitlab/email/failure_handler.rb'
- 'lib/gitlab/email/handler/create_issue_handler.rb'
- 'lib/gitlab/email/handler/create_merge_request_handler.rb'
- 'lib/gitlab/email/message/in_product_marketing/base.rb'
- 'lib/gitlab/email/message/in_product_marketing/create.rb'
- - 'lib/gitlab/email/message/in_product_marketing/experience.rb'
- 'lib/gitlab/email/message/in_product_marketing/helper.rb'
- 'lib/gitlab/email/message/in_product_marketing/team.rb'
- 'lib/gitlab/email/message/in_product_marketing/trial.rb'
@@ -3444,7 +3269,6 @@ Layout/LineLength:
- 'lib/gitlab/git_access.rb'
- 'lib/gitlab/git_access_project.rb'
- 'lib/gitlab/git_access_snippet.rb'
- - 'lib/gitlab/git_access_wiki.rb'
- 'lib/gitlab/gitaly_client.rb'
- 'lib/gitlab/gitaly_client/blob_service.rb'
- 'lib/gitlab/gitaly_client/call.rb'
@@ -3469,8 +3293,6 @@ Layout/LineLength:
- 'lib/gitlab/gpg/invalid_gpg_signature_updater.rb'
- 'lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb'
- 'lib/gitlab/grape_logging/loggers/client_env_logger.rb'
- - 'lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb'
- - 'lib/gitlab/graphql/pagination/keyset/query_builder.rb'
- 'lib/gitlab/graphql/timeout.rb'
- 'lib/gitlab/group_search_results.rb'
- 'lib/gitlab/hashed_storage/migrator.rb'
@@ -3518,10 +3340,8 @@ Layout/LineLength:
- 'lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb'
- 'lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb'
- 'lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb'
- - 'lib/gitlab/metrics/dashboard/url.rb'
- 'lib/gitlab/metrics/dashboard/validator.rb'
- 'lib/gitlab/metrics/dashboard/validator/errors.rb'
- - 'lib/gitlab/metrics/rails_slis.rb'
- 'lib/gitlab/metrics/samplers/action_cable_sampler.rb'
- 'lib/gitlab/metrics/samplers/puma_sampler.rb'
- 'lib/gitlab/metrics/samplers/ruby_sampler.rb'
@@ -3574,7 +3394,6 @@ Layout/LineLength:
- 'lib/gitlab/sidekiq_daemon/monitor.rb'
- 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
- 'lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb'
- - 'lib/gitlab/sidekiq_middleware/memory_killer.rb'
- 'lib/gitlab/sidekiq_middleware/server_metrics.rb'
- 'lib/gitlab/sidekiq_middleware/size_limiter/compressor.rb'
- 'lib/gitlab/sidekiq_versioning.rb'
@@ -3590,7 +3409,6 @@ Layout/LineLength:
- 'lib/gitlab/usage/metrics/aggregates/aggregate.rb'
- 'lib/gitlab/usage/metrics/aggregates/sources/calculations/intersection.rb'
- 'lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb'
- - 'lib/gitlab/usage/metrics/instrumentations/database_metric.rb'
- 'lib/gitlab/usage/metrics/name_suggestion.rb'
- 'lib/gitlab/usage/metrics/names_suggestions/generator.rb'
- 'lib/gitlab/usage/service_ping_report.rb'
@@ -3618,12 +3436,8 @@ Layout/LineLength:
- 'lib/security/ci_configuration/base_build_action.rb'
- 'lib/security/ci_configuration/sast_build_action.rb'
- 'lib/sidebars/groups/menus/packages_registries_menu.rb'
- - 'lib/sidebars/groups/menus/settings_menu.rb'
- 'lib/sidebars/menu_item.rb'
- - 'lib/sidebars/projects/menus/infrastructure_menu.rb'
- - 'lib/sidebars/projects/menus/packages_registries_menu.rb'
- 'lib/sidebars/projects/menus/repository_menu.rb'
- - 'lib/sidebars/projects/panel.rb'
- 'lib/system_check/app/orphaned_group_members_check.rb'
- 'lib/system_check/app/redis_version_check.rb'
- 'lib/system_check/incoming_email/mail_room_enabled_check.rb'
@@ -3640,7 +3454,6 @@ Layout/LineLength:
- 'lib/tasks/gitlab/info.rake'
- 'lib/tasks/gitlab/packages/events.rake'
- 'lib/tasks/gitlab/packages/migrate.rake'
- - 'lib/tasks/gitlab/pages.rake'
- 'lib/tasks/gitlab/seed/group_seed.rake'
- 'lib/tasks/gitlab/shell.rake'
- 'lib/tasks/gitlab/sidekiq.rake'
@@ -3669,8 +3482,6 @@ Layout/LineLength:
- 'qa/qa/git/repository.rb'
- 'qa/qa/page/base.rb'
- 'qa/qa/page/component/ci_badge_link.rb'
- - 'qa/qa/page/component/design_management.rb'
- - 'qa/qa/page/component/invite_members_modal.rb'
- 'qa/qa/page/component/issuable/sidebar.rb'
- 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/dashboard/snippet/index.rb'
@@ -3679,14 +3490,12 @@ Layout/LineLength:
- 'qa/qa/page/group/settings/package_registries.rb'
- 'qa/qa/page/merge_request/new.rb'
- 'qa/qa/page/project/import/repo_by_url.rb'
- - 'qa/qa/page/project/issue/index.rb'
- 'qa/qa/page/project/registry/show.rb'
- 'qa/qa/page/project/settings/protected_branches.rb'
- 'qa/qa/page/project/web_ide/edit.rb'
- 'qa/qa/resource/api_fabricator.rb'
- 'qa/qa/resource/file.rb'
- 'qa/qa/resource/members.rb'
- - 'qa/qa/resource/project.rb'
- 'qa/qa/resource/protected_branch.rb'
- 'qa/qa/resource/registry_repository.rb'
- 'qa/qa/resource/repository/push.rb'
@@ -3699,28 +3508,19 @@ Layout/LineLength:
- 'qa/qa/resource/wiki/group_page.rb'
- 'qa/qa/runtime/api/repository_storage_moves.rb'
- 'qa/qa/runtime/application_settings.rb'
- - 'qa/qa/runtime/browser.rb'
- 'qa/qa/runtime/env.rb'
- 'qa/qa/runtime/feature.rb'
- 'qa/qa/runtime/fixtures.rb'
- 'qa/qa/runtime/ip_address.rb'
- 'qa/qa/runtime/search.rb'
- 'qa/qa/scenario/bootable.rb'
- - 'qa/qa/scenario/template.rb'
- 'qa/qa/service/cluster_provider/gcloud.rb'
- 'qa/qa/service/cluster_provider/k3s.rb'
- - 'qa/qa/service/kubernetes_cluster.rb'
- 'qa/qa/service/praefect_manager.rb'
- 'qa/qa/specs/features/api/1_manage/project_access_token_spec.rb'
- 'qa/qa/specs/features/api/1_manage/rate_limits_spec.rb'
- 'qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb'
- 'qa/qa/specs/features/api/1_manage/users_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/praefect_connectivity_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/praefect_dataloss_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb'
- 'qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb'
- 'qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb'
- 'qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb'
@@ -3732,7 +3532,6 @@ Layout/LineLength:
- 'qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb'
- 'qa/qa/specs/features/api/5_package/container_registry_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb'
@@ -3741,15 +3540,12 @@ Layout/LineLength:
- 'qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb'
- - 'qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb'
@@ -3758,8 +3554,6 @@ Layout/LineLength:
- 'qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb'
@@ -3783,7 +3577,6 @@ Layout/LineLength:
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_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_over_http_file_size_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb'
@@ -3817,7 +3610,6 @@ Layout/LineLength:
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb'
- - 'qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/update_ci_file_with_pipeline_editor_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb'
@@ -3836,20 +3628,10 @@ Layout/LineLength:
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb'
- - 'qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb'
- - 'qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb'
- - 'qa/qa/specs/features/ee/api/12_geo/geo_nodes_spec.rb'
- 'qa/qa/specs/features/ee/api/1_manage/user/minimal_access_user_spec.rb'
- 'qa/qa/specs/features/ee/api/2_plan/epics_milestone_dates_spec.rb'
- 'qa/qa/specs/features/ee/api/3_create/wiki/group_wiki_repository_storage_move_spec.rb'
- 'qa/qa/specs/features/ee/api/7_configure/kubernetes/kubernetes_agent_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/advanced_global_advanced_syntax_search_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/elasticsearch_api_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/issues_index/issue_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/main_index/blob_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/merge_request_index/merge_request_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/notes_index/note_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/nightly_elasticsearch_test_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/10_protect/policies_list_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/license/cloud_activation_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/license/license_spec.rb'
@@ -3858,24 +3640,9 @@ Layout/LineLength:
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/purchase_storage_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/upgrade_group_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/user_registration_billing_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/attachment_replication_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/database_delete_replication_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_ci_job_log_artifacts_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_maven_package_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_npm_registry_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_project_snippets_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/http_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/http_push_to_secondary_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/ssh_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/ssh_push_to_secondary_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_http_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_http_push_to_secondary_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_ssh_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_ssh_push_to_secondary_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/create_merge_request_with_secure_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/enable_scanning_from_configuration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/license_compliance_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/13_secure/merge_request_license_widget_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/security_reports_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/vulnerability_management_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
@@ -3884,12 +3651,10 @@ Layout/LineLength:
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_saml_enforced_sso_new_account_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_saml_non_enforced_sso_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/prevent_forking_outside_group_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/group/restrict_by_ip_address_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/share_group_with_group_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/instance/instance_audit_logs_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/ldap/admin_ldap_sync_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_templates_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/user/minimal_access_user_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/burndown_chart/burndown_chart_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/custom_email/custom_email_spec.rb'
@@ -3903,7 +3668,6 @@ Layout/LineLength:
- 'qa/qa/specs/features/ee/browser_ui/2_plan/issue_boards/sum_of_issues_weights_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/issues_analytics/issues_analytics_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/issues_weight/issue_weight_visualization_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/2_plan/iterations/assign_group_iteration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/iterations/create_group_iteration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/four_assignees_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/more_than_four_assignees_spec.rb'
@@ -3924,32 +3688,21 @@ Layout/LineLength:
- 'qa/qa/specs/features/ee/browser_ui/4_verify/pipeline_subscription_with_group_owned_project_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/transient/merge_trains_transient_bug_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/5_package/dependency_proxy_sso_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/9_enablement/elasticsearch/elasticsearch_reindexing_spec.rb'
- 'qa/qa/specs/helpers/context_selector.rb'
- 'qa/qa/specs/parallel_runner.rb'
- - 'qa/qa/specs/runner.rb'
- 'qa/qa/support/loglinking.rb'
- - 'qa/qa/support/page_error_checker.rb'
- 'qa/qa/support/run.rb'
- 'qa/qa/support/ssh.rb'
- - 'qa/qa/support/wait_for_requests.rb'
- 'qa/qa/tools/delete_projects.rb'
- 'qa/qa/tools/delete_subgroups.rb'
- 'qa/qa/tools/delete_test_ssh_keys.rb'
- 'qa/qa/tools/delete_test_users.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- 'qa/qa/tools/initialize_gitlab_auth.rb'
- - 'qa/qa/tools/revoke_all_personal_access_tokens.rb'
- - 'qa/qa/tools/test_resources_handler.rb'
- - 'qa/qa/vendor/jenkins/page/configure_job.rb'
- - 'qa/qa/vendor/jenkins/page/login.rb'
- 'qa/spec/git/repository_spec.rb'
- - 'qa/spec/page/logging_spec.rb'
- 'qa/spec/resource/api_fabricator_spec.rb'
- 'qa/spec/runtime/env_spec.rb'
- 'qa/spec/runtime/feature_spec.rb'
- - 'qa/spec/scenario/template_spec.rb'
- - 'qa/spec/spec_helper.rb'
- 'qa/spec/specs/helpers/context_selector_spec.rb'
- 'qa/spec/specs/helpers/quarantine_spec.rb'
- 'qa/spec/specs/runner_spec.rb'
@@ -3970,10 +3723,8 @@ Layout/LineLength:
- 'rubocop/cop/migration/safer_boolean_column.rb'
- 'rubocop/cop/migration/versioned_migration_class.rb'
- 'rubocop/cop/migration/with_lock_retries_disallowed_method.rb'
- - 'rubocop/cop/performance/ar_exists_and_present_blank.rb'
- 'rubocop/cop/qa/selector_usage.rb'
- 'rubocop/cop/rspec/top_level_describe_path.rb'
- - 'rubocop/cop/static_translation_definition.rb'
- 'rubocop/cop/usage_data/large_table.rb'
- 'scripts/api/cancel_pipeline.rb'
- 'scripts/api/download_job_artifact.rb'
@@ -3995,9 +3746,7 @@ Layout/LineLength:
- 'sidekiq_cluster/cli.rb'
- 'sidekiq_cluster/sidekiq_cluster.rb'
- 'spec/benchmarks/banzai_benchmark.rb'
- - 'spec/commands/metrics_server/metrics_server_spec.rb'
- 'spec/commands/sidekiq_cluster/cli_spec.rb'
- - 'spec/components/pajamas/alert_component_spec.rb'
- 'spec/config/metrics/aggregates/aggregated_metrics_spec.rb'
- 'spec/config/settings_spec.rb'
- 'spec/controllers/admin/application_settings_controller_spec.rb'
@@ -4027,7 +3776,6 @@ Layout/LineLength:
- 'spec/controllers/groups/milestones_controller_spec.rb'
- 'spec/controllers/groups/releases_controller_spec.rb'
- 'spec/controllers/groups/settings/applications_controller_spec.rb'
- - 'spec/controllers/groups/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/groups/settings/integrations_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/import/available_namespaces_controller_spec.rb'
@@ -4037,12 +3785,9 @@ Layout/LineLength:
- 'spec/controllers/import/fogbugz_controller_spec.rb'
- 'spec/controllers/import/gitea_controller_spec.rb'
- 'spec/controllers/import/github_controller_spec.rb'
- - 'spec/controllers/import/gitlab_controller_spec.rb'
- 'spec/controllers/invites_controller_spec.rb'
- - 'spec/controllers/jira_connect/app_descriptor_controller_spec.rb'
- 'spec/controllers/jira_connect/events_controller_spec.rb'
- 'spec/controllers/jira_connect/subscriptions_controller_spec.rb'
- - 'spec/controllers/metrics_controller_spec.rb'
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- 'spec/controllers/passwords_controller_spec.rb'
- 'spec/controllers/profiles/accounts_controller_spec.rb'
@@ -4106,7 +3851,6 @@ Layout/LineLength:
- 'spec/controllers/uploads_controller_spec.rb'
- 'spec/db/schema_spec.rb'
- 'spec/deprecation_toolkit_env.rb'
- - 'spec/experiments/application_experiment_spec.rb'
- 'spec/experiments/concerns/project_commit_count_spec.rb'
- 'spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb'
- 'spec/factories/ci/builds.rb'
@@ -4135,7 +3879,6 @@ Layout/LineLength:
- 'spec/features/admin/admin_sees_project_statistics_spec.rb'
- 'spec/features/admin/admin_settings_spec.rb'
- 'spec/features/admin/admin_users_spec.rb'
- - 'spec/features/admin/users/user_spec.rb'
- 'spec/features/alert_management/user_filters_alerts_by_status_spec.rb'
- 'spec/features/alert_management/user_updates_alert_status_spec.rb'
- 'spec/features/alert_management_spec.rb'
@@ -4150,7 +3893,6 @@ Layout/LineLength:
- 'spec/features/boards/user_visits_board_spec.rb'
- 'spec/features/calendar_spec.rb'
- 'spec/features/callouts/registration_enabled_spec.rb'
- - 'spec/features/clusters/cluster_detail_page_spec.rb'
- 'spec/features/commits_spec.rb'
- 'spec/features/contextual_sidebar_spec.rb'
- 'spec/features/cycle_analytics_spec.rb'
@@ -4176,7 +3918,6 @@ Layout/LineLength:
- 'spec/features/groups/milestones_sorting_spec.rb'
- 'spec/features/groups/packages_spec.rb'
- 'spec/features/groups/settings/access_tokens_spec.rb'
- - 'spec/features/groups/settings/group_badges_spec.rb'
- 'spec/features/groups/settings/repository_spec.rb'
- 'spec/features/groups_spec.rb'
- 'spec/features/ide/static_object_external_storage_csp_spec.rb'
@@ -4191,7 +3932,6 @@ Layout/LineLength:
- 'spec/features/issues/csv_spec.rb'
- 'spec/features/issues/filtered_search/filter_issues_spec.rb'
- 'spec/features/issues/filtered_search/recent_searches_spec.rb'
- - 'spec/features/issues/filtered_search/visual_tokens_spec.rb'
- 'spec/features/issues/form_spec.rb'
- 'spec/features/issues/gfm_autocomplete_spec.rb'
- 'spec/features/issues/issue_detail_spec.rb'
@@ -4206,7 +3946,6 @@ Layout/LineLength:
- 'spec/features/issues/user_sees_empty_state_spec.rb'
- 'spec/features/issues/user_sees_live_update_spec.rb'
- 'spec/features/issues/user_views_issue_spec.rb'
- - 'spec/features/jira_connect/subscriptions_spec.rb'
- 'spec/features/labels_hierarchy_spec.rb'
- 'spec/features/markdown/copy_as_gfm_spec.rb'
- 'spec/features/markdown/gitlab_flavored_markdown_spec.rb'
@@ -4247,7 +3986,6 @@ Layout/LineLength:
- 'spec/features/merge_request/user_squashes_merge_request_spec.rb'
- 'spec/features/merge_request/user_suggests_changes_on_diff_spec.rb'
- 'spec/features/merge_request/user_toggles_whitespace_changes_spec.rb'
- - 'spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb'
- 'spec/features/merge_requests/filters_generic_behavior_spec.rb'
- 'spec/features/merge_requests/user_exports_as_csv_spec.rb'
- 'spec/features/merge_requests/user_filters_by_approvals_spec.rb'
@@ -4314,7 +4052,6 @@ Layout/LineLength:
- 'spec/features/projects/releases/user_views_edit_release_spec.rb'
- 'spec/features/projects/releases/user_views_releases_spec.rb'
- 'spec/features/projects/settings/access_tokens_spec.rb'
- - 'spec/features/projects/settings/project_badges_spec.rb'
- 'spec/features/projects/settings/project_settings_spec.rb'
- 'spec/features/projects/settings/registry_settings_spec.rb'
- 'spec/features/projects/settings/service_desk_setting_spec.rb'
@@ -4325,12 +4062,9 @@ Layout/LineLength:
- 'spec/features/projects/show/schema_markup_spec.rb'
- 'spec/features/projects/show/user_sees_deletion_failure_message_spec.rb'
- 'spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb'
- - 'spec/features/projects/tags/user_edits_tags_spec.rb'
- 'spec/features/projects/terraform_spec.rb'
- 'spec/features/projects/tree/upload_file_spec.rb'
- - 'spec/features/projects/view_on_env_spec.rb'
- 'spec/features/projects_spec.rb'
- - 'spec/features/runners_spec.rb'
- 'spec/features/search/user_searches_for_comments_spec.rb'
- 'spec/features/search/user_searches_for_merge_requests_spec.rb'
- 'spec/features/search/user_searches_for_projects_spec.rb'
@@ -4344,19 +4078,16 @@ Layout/LineLength:
- 'spec/features/snippets/spam_snippets_spec.rb'
- 'spec/features/snippets/user_edits_snippet_spec.rb'
- 'spec/features/task_lists_spec.rb'
- - 'spec/features/topic_show_spec.rb'
- 'spec/features/unsubscribe_links_spec.rb'
- 'spec/features/user_sorts_things_spec.rb'
- 'spec/features/users/login_spec.rb'
- 'spec/features/users/overview_spec.rb'
- - 'spec/features/users/show_spec.rb'
- 'spec/features/users/signup_spec.rb'
- 'spec/features/users/user_browses_projects_on_user_page_spec.rb'
- 'spec/features/webauthn_spec.rb'
- 'spec/finders/access_requests_finder_spec.rb'
- 'spec/finders/admin/projects_finder_spec.rb'
- 'spec/finders/alert_management/alerts_finder_spec.rb'
- - 'spec/finders/applications_finder_spec.rb'
- 'spec/finders/autocomplete/users_finder_spec.rb'
- 'spec/finders/award_emojis_finder_spec.rb'
- 'spec/finders/branches_finder_spec.rb'
@@ -4377,8 +4108,6 @@ Layout/LineLength:
- 'spec/finders/group_projects_finder_spec.rb'
- 'spec/finders/groups/user_groups_finder_spec.rb'
- 'spec/finders/groups_finder_spec.rb'
- - 'spec/finders/issues_finder_spec.rb'
- - 'spec/finders/keys_finder_spec.rb'
- 'spec/finders/labels_finder_spec.rb'
- 'spec/finders/members_finder_spec.rb'
- 'spec/finders/merge_requests/by_approvals_finder_spec.rb'
@@ -4388,7 +4117,6 @@ Layout/LineLength:
- 'spec/finders/milestones_finder_spec.rb'
- 'spec/finders/namespaces/projects_finder_spec.rb'
- 'spec/finders/notes_finder_spec.rb'
- - 'spec/finders/packages/build_infos_finder_spec.rb'
- 'spec/finders/packages/go/version_finder_spec.rb'
- 'spec/finders/packages/group_packages_finder_spec.rb'
- 'spec/finders/packages/maven/package_finder_spec.rb'
@@ -4411,8 +4139,6 @@ Layout/LineLength:
- 'spec/finders/user_recent_events_finder_spec.rb'
- 'spec/finders/users_finder_spec.rb'
- 'spec/frontend/fixtures/api_deploy_keys.rb'
- - 'spec/frontend/fixtures/blob.rb'
- - 'spec/frontend/fixtures/deploy_keys.rb'
- 'spec/frontend/fixtures/freeze_period.rb'
- 'spec/frontend/fixtures/issues.rb'
- 'spec/frontend/fixtures/jobs.rb'
@@ -4421,7 +4147,6 @@ Layout/LineLength:
- 'spec/frontend/fixtures/pipeline_schedules.rb'
- 'spec/frontend/fixtures/projects.rb'
- 'spec/frontend/fixtures/snippet.rb'
- - 'spec/graphql/features/feature_flag_spec.rb'
- 'spec/graphql/gitlab_schema_spec.rb'
- 'spec/graphql/mutations/boards/issues/issue_move_list_spec.rb'
- 'spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb'
@@ -4430,10 +4155,7 @@ Layout/LineLength:
- 'spec/graphql/mutations/clusters/agents/create_spec.rb'
- 'spec/graphql/mutations/commits/create_spec.rb'
- 'spec/graphql/mutations/container_expiration_policies/update_spec.rb'
- - 'spec/graphql/mutations/custom_emoji/create_spec.rb'
- 'spec/graphql/mutations/customer_relations/contacts/create_spec.rb'
- - 'spec/graphql/mutations/customer_relations/contacts/update_spec.rb'
- - 'spec/graphql/mutations/customer_relations/organizations/create_spec.rb'
- 'spec/graphql/mutations/customer_relations/organizations/update_spec.rb'
- 'spec/graphql/mutations/discussions/toggle_resolve_spec.rb'
- 'spec/graphql/mutations/groups/update_spec.rb'
@@ -4448,7 +4170,6 @@ Layout/LineLength:
- 'spec/graphql/mutations/releases/update_spec.rb'
- 'spec/graphql/mutations/saved_replies/create_spec.rb'
- 'spec/graphql/mutations/saved_replies/update_spec.rb'
- - 'spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb'
- 'spec/graphql/mutations/security/ci_configuration/configure_sast_spec.rb'
- 'spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb'
- 'spec/graphql/resolvers/alert_management/alert_resolver_spec.rb'
@@ -4487,15 +4208,12 @@ Layout/LineLength:
- 'spec/graphql/types/base_field_spec.rb'
- 'spec/graphql/types/commit_type_spec.rb'
- 'spec/graphql/types/container_expiration_policy_type_spec.rb'
- - 'spec/graphql/types/container_repository_details_type_spec.rb'
- - 'spec/graphql/types/container_repository_type_spec.rb'
- 'spec/graphql/types/environment_type_spec.rb'
- 'spec/graphql/types/global_id_type_spec.rb'
- 'spec/graphql/types/group_type_spec.rb'
- 'spec/graphql/types/issue_sort_enum_spec.rb'
- 'spec/graphql/types/issue_type_spec.rb'
- 'spec/graphql/types/merge_request_type_spec.rb'
- - 'spec/graphql/types/mutation_type_spec.rb'
- 'spec/graphql/types/packages/helm/metadata_type_spec.rb'
- 'spec/graphql/types/packages/package_dependency_type_enum_spec.rb'
- 'spec/graphql/types/packages/package_group_sort_enum_spec.rb'
@@ -4554,7 +4272,6 @@ Layout/LineLength:
- 'spec/helpers/projects/security/configuration_helper_spec.rb'
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/helpers/registrations_helper_spec.rb'
- - 'spec/helpers/routing/pseudonymization_helper_spec.rb'
- 'spec/helpers/search_helper_spec.rb'
- 'spec/helpers/sidebars_helper_spec.rb'
- 'spec/helpers/sidekiq_helper_spec.rb'
@@ -4574,7 +4291,6 @@ Layout/LineLength:
- 'spec/helpers/wiki_page_version_helper_spec.rb'
- 'spec/initializers/00_rails_disable_joins_spec.rb'
- 'spec/initializers/6_validations_spec.rb'
- - 'spec/initializers/carrierwave_patch_spec.rb'
- 'spec/initializers/direct_upload_support_spec.rb'
- 'spec/initializers/global_id_spec.rb'
- 'spec/initializers/lograge_spec.rb'
@@ -4583,7 +4299,6 @@ Layout/LineLength:
- 'spec/initializers/secret_token_spec.rb'
- 'spec/initializers/session_store_spec.rb'
- 'spec/initializers/settings_spec.rb'
- - 'spec/initializers/trusted_proxies_spec.rb'
- 'spec/lib/api/entities/ci/pipeline_spec.rb'
- 'spec/lib/api/entities/project_import_status_spec.rb'
- 'spec/lib/api/entities/projects/repository_storage_move_spec.rb'
@@ -4599,7 +4314,6 @@ Layout/LineLength:
- 'spec/lib/api/helpers/rate_limiter_spec.rb'
- 'spec/lib/api/helpers_spec.rb'
- 'spec/lib/atlassian/jira_connect/client_spec.rb'
- - 'spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb'
- 'spec/lib/atlassian/jira_issue_key_extractor_spec.rb'
- 'spec/lib/backup/files_spec.rb'
- 'spec/lib/backup/gitaly_backup_spec.rb'
@@ -4609,7 +4323,6 @@ Layout/LineLength:
- 'spec/lib/banzai/filter/ascii_doc_post_processing_filter_spec.rb'
- 'spec/lib/banzai/filter/ascii_doc_sanitization_filter_spec.rb'
- 'spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb'
- - 'spec/lib/banzai/filter/custom_emoji_filter_spec.rb'
- 'spec/lib/banzai/filter/external_link_filter_spec.rb'
- 'spec/lib/banzai/filter/gollum_tags_filter_spec.rb'
- 'spec/lib/banzai/filter/image_link_filter_spec.rb'
@@ -4658,7 +4371,6 @@ Layout/LineLength:
- 'spec/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb'
- - 'spec/lib/bulk_imports/projects/pipelines/project_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb'
- 'spec/lib/bulk_imports/users_mapper_spec.rb'
@@ -4668,7 +4380,6 @@ Layout/LineLength:
- 'spec/lib/csv_builder_spec.rb'
- 'spec/lib/declarative_enum_spec.rb'
- 'spec/lib/error_tracking/sentry_client/issue_link_spec.rb'
- - 'spec/lib/error_tracking/sentry_client/issue_spec.rb'
- 'spec/lib/error_tracking/sentry_client/pagination_parser_spec.rb'
- 'spec/lib/error_tracking/sentry_client/projects_spec.rb'
- 'spec/lib/event_filter_spec.rb'
@@ -4709,7 +4420,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/background_migration/backfill_member_namespace_for_group_members_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb'
- 'spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb'
- 'spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb'
- 'spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb'
@@ -4746,7 +4456,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb'
- 'spec/lib/gitlab/chat/output_spec.rb'
- 'spec/lib/gitlab/checks/branch_check_spec.rb'
- - 'spec/lib/gitlab/checks/changes_access_spec.rb'
- 'spec/lib/gitlab/checks/diff_check_spec.rb'
- 'spec/lib/gitlab/checks/push_check_spec.rb'
- 'spec/lib/gitlab/checks/snippet_check_spec.rb'
@@ -4792,11 +4501,9 @@ Layout/LineLength:
- 'spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb'
- 'spec/lib/gitlab/ci/reports/codequality_mr_diff_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/flag_spec.rb'
- - 'spec/lib/gitlab/ci/reports/security/link_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/reports_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/scanner_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb'
- - 'spec/lib/gitlab/ci/runner_releases_spec.rb'
- 'spec/lib/gitlab/ci/runner_upgrade_check_spec.rb'
- 'spec/lib/gitlab/ci/status/bridge/factory_spec.rb'
- 'spec/lib/gitlab/ci/status/build/manual_spec.rb'
@@ -4815,7 +4522,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/code_navigation_path_spec.rb'
- 'spec/lib/gitlab/composer/cache_spec.rb'
- 'spec/lib/gitlab/composer/version_index_spec.rb'
- - 'spec/lib/gitlab/config_checker/external_database_checker_spec.rb'
- 'spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb'
- 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/consul/internal_spec.rb'
@@ -4835,7 +4541,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/database/load_balancing/configuration_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/host_list_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/setup_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb'
@@ -4885,7 +4590,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/diff/highlight_cache_spec.rb'
- 'spec/lib/gitlab/diff/highlight_spec.rb'
- 'spec/lib/gitlab/diff/inline_diff_marker_spec.rb'
- - 'spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb'
- 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
@@ -4941,20 +4645,13 @@ Layout/LineLength:
- 'spec/lib/gitlab/github_import/importer/lfs_object_importer_spec.rb'
- 'spec/lib/gitlab/github_import/object_counter_spec.rb'
- 'spec/lib/gitlab/github_import/user_finder_spec.rb'
- - 'spec/lib/gitlab/github_import_spec.rb'
- 'spec/lib/gitlab/gl_repository/repo_type_spec.rb'
- - 'spec/lib/gitlab/global_id/deprecations_spec.rb'
- 'spec/lib/gitlab/gpg/commit_spec.rb'
- 'spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb'
- 'spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb'
- 'spec/lib/gitlab/graphql/markdown_field_spec.rb'
- 'spec/lib/gitlab/graphql/pagination/connections_spec.rb'
- - 'spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb'
- - 'spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_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/graphql/pagination/keyset/order_info_spec.rb'
- - 'spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb'
- 'spec/lib/gitlab/graphql/present/field_extension_spec.rb'
- 'spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb'
- 'spec/lib/gitlab/graphs/commits_spec.rb'
@@ -4998,7 +4695,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/import_sources_spec.rb'
- 'spec/lib/gitlab/incoming_email_spec.rb'
- 'spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb'
- - 'spec/lib/gitlab/internal_post_receive/response_spec.rb'
- 'spec/lib/gitlab/issuable_metadata_spec.rb'
- 'spec/lib/gitlab/issues/rebalancing/state_spec.rb'
- 'spec/lib/gitlab/jira/dvcs_spec.rb'
@@ -5057,7 +4753,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/pagination/keyset/iterator_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/paginator_spec.rb'
- - 'spec/lib/gitlab/pagination/offset_header_builder_spec.rb'
- 'spec/lib/gitlab/pagination/offset_pagination_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
- 'spec/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled_spec.rb'
@@ -5065,7 +4760,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/phabricator_import/conduit/user_spec.rb'
- 'spec/lib/gitlab/phabricator_import/user_finder_spec.rb'
- 'spec/lib/gitlab/project_search_results_spec.rb'
- - 'spec/lib/gitlab/project_template_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb'
@@ -5120,7 +4814,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb'
- 'spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb'
- 'spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb'
- 'spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb'
- 'spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb'
- 'spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/constraints_spec.rb'
@@ -5182,7 +4875,6 @@ Layout/LineLength:
- 'spec/mailers/emails/releases_spec.rb'
- 'spec/mailers/emails/service_desk_spec.rb'
- 'spec/mailers/notify_spec.rb'
- - 'spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
- 'spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb'
- 'spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb'
- 'spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb'
@@ -5196,7 +4888,6 @@ Layout/LineLength:
- 'spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb'
- 'spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb'
- 'spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb'
- - 'spec/migrations/20210918201050_remove_old_pending_jobs_for_recalculate_vulnerabilities_occurrences_uuid_spec.rb'
- 'spec/migrations/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3_spec.rb'
- 'spec/migrations/20211110143306_add_not_null_constraint_to_security_findings_uuid_spec.rb'
- 'spec/migrations/20211110151350_schedule_drop_invalid_security_findings_spec.rb'
@@ -5216,7 +4907,6 @@ Layout/LineLength:
- 'spec/migrations/20220309084954_remove_leftover_external_pull_request_deletions_spec.rb'
- 'spec/migrations/active_record/schema_spec.rb'
- 'spec/migrations/add_upvotes_count_index_to_issues_spec.rb'
- - 'spec/migrations/associate_existing_dast_builds_with_variables_spec.rb'
- 'spec/migrations/backfill_all_project_namespaces_spec.rb'
- 'spec/migrations/backfill_cadence_id_for_boards_scoped_to_iteration_spec.rb'
- 'spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb'
@@ -5228,24 +4918,19 @@ Layout/LineLength:
- 'spec/migrations/cleanup_move_container_registry_enabled_to_project_feature_spec.rb'
- 'spec/migrations/confirm_support_bot_user_spec.rb'
- 'spec/migrations/delete_security_findings_without_uuid_spec.rb'
- - 'spec/migrations/disable_job_token_scope_when_unused_spec.rb'
- 'spec/migrations/finalize_project_namespaces_backfill_spec.rb'
- 'spec/migrations/fix_and_backfill_project_namespaces_for_projects_with_duplicate_name_spec.rb'
- 'spec/migrations/fix_batched_migrations_old_format_job_arguments_spec.rb'
- - 'spec/migrations/populate_audit_event_streaming_verification_token_spec.rb'
- 'spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb'
- 'spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb'
- 'spec/migrations/recreate_index_security_ci_builds_on_name_and_id_parser_features_spec.rb'
- 'spec/migrations/recreate_index_security_ci_builds_on_name_and_id_parser_with_new_features_spec.rb'
- 'spec/migrations/remove_duplicate_dast_site_tokens_spec.rb'
- - 'spec/migrations/remove_duplicate_dast_site_tokens_with_same_token_spec.rb'
- 'spec/migrations/remove_not_null_contraint_on_title_from_sprints_spec.rb'
- 'spec/migrations/rename_services_to_integrations_spec.rb'
- 'spec/migrations/replace_external_wiki_triggers_spec.rb'
- 'spec/migrations/reset_severity_levels_to_new_default_spec.rb'
- 'spec/migrations/schedule_add_primary_email_to_emails_if_user_confirmed_spec.rb'
- - 'spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb'
- - 'spec/migrations/schedule_populate_status_column_of_security_scans_spec.rb'
- 'spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb'
- 'spec/migrations/schedule_update_timelogs_null_spent_at_spec.rb'
- 'spec/migrations/schedule_update_timelogs_project_id_spec.rb'
@@ -5262,15 +4947,12 @@ Layout/LineLength:
- 'spec/models/audit_event_spec.rb'
- 'spec/models/authentication_event_spec.rb'
- 'spec/models/award_emoji_spec.rb'
- - 'spec/models/badge_spec.rb'
- - 'spec/models/badges/project_badge_spec.rb'
- 'spec/models/blob_viewer/go_mod_spec.rb'
- 'spec/models/blob_viewer/metrics_dashboard_yml_spec.rb'
- 'spec/models/broadcast_message_spec.rb'
- 'spec/models/bulk_import_spec.rb'
- 'spec/models/bulk_imports/entity_spec.rb'
- 'spec/models/bulk_imports/file_transfer/project_config_spec.rb'
- - 'spec/models/ci/artifact_blob_spec.rb'
- 'spec/models/ci/build_runner_session_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/models/ci/build_trace_chunk_spec.rb'
@@ -5324,7 +5006,6 @@ Layout/LineLength:
- 'spec/models/concerns/token_authenticatable_spec.rb'
- 'spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb'
- 'spec/models/concerns/x509_serial_number_attribute_spec.rb'
- - 'spec/models/container_registry/event_spec.rb'
- 'spec/models/container_repository_spec.rb'
- 'spec/models/context_commits_diff_spec.rb'
- 'spec/models/customer_relations/issue_contact_spec.rb'
@@ -5361,9 +5042,7 @@ Layout/LineLength:
- 'spec/models/integrations/discord_spec.rb'
- 'spec/models/integrations/drone_ci_spec.rb'
- 'spec/models/integrations/emails_on_push_spec.rb'
- - 'spec/models/integrations/jenkins_spec.rb'
- 'spec/models/integrations/jira_spec.rb'
- - 'spec/models/integrations/jira_tracker_data_spec.rb'
- 'spec/models/integrations/packagist_spec.rb'
- 'spec/models/integrations/prometheus_spec.rb'
- 'spec/models/integrations/slack_spec.rb'
@@ -5444,7 +5123,6 @@ Layout/LineLength:
- 'spec/models/snippet_spec.rb'
- 'spec/models/state_note_spec.rb'
- 'spec/models/suggestion_spec.rb'
- - 'spec/models/terraform/state_spec.rb'
- 'spec/models/timelog_spec.rb'
- 'spec/models/todo_spec.rb'
- 'spec/models/upload_spec.rb'
@@ -5469,7 +5147,6 @@ Layout/LineLength:
- 'spec/presenters/clusters/cluster_presenter_spec.rb'
- 'spec/presenters/commit_status_presenter_spec.rb'
- 'spec/presenters/gitlab/blame_presenter_spec.rb'
- - 'spec/presenters/issue_presenter_spec.rb'
- 'spec/presenters/merge_request_presenter_spec.rb'
- 'spec/presenters/packages/composer/packages_presenter_spec.rb'
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
@@ -5483,7 +5160,6 @@ Layout/LineLength:
- 'spec/presenters/prometheus_alert_presenter_spec.rb'
- 'spec/presenters/service_hook_presenter_spec.rb'
- 'spec/presenters/snippet_blob_presenter_spec.rb'
- - 'spec/presenters/tree_entry_presenter_spec.rb'
- 'spec/rack_servers/puma_spec.rb'
- 'spec/requests/admin/background_migrations_controller_spec.rb'
- 'spec/requests/api/access_requests_spec.rb'
@@ -5580,7 +5256,6 @@ Layout/LineLength:
- 'spec/requests/api/graphql/project/jobs_spec.rb'
- 'spec/requests/api/graphql/project/milestones_spec.rb'
- 'spec/requests/api/graphql/project/pipeline_spec.rb'
- - 'spec/requests/api/graphql/project/project_members_spec.rb'
- 'spec/requests/api/graphql/project/project_statistics_spec.rb'
- 'spec/requests/api/graphql/project/release_spec.rb'
- 'spec/requests/api/graphql/usage_trends_measurements_spec.rb'
@@ -5613,7 +5288,6 @@ Layout/LineLength:
- 'spec/requests/api/keys_spec.rb'
- 'spec/requests/api/labels_spec.rb'
- 'spec/requests/api/lint_spec.rb'
- - 'spec/requests/api/markdown_spec.rb'
- 'spec/requests/api/maven_packages_spec.rb'
- 'spec/requests/api/members_spec.rb'
- 'spec/requests/api/merge_request_diffs_spec.rb'
@@ -5635,7 +5309,6 @@ Layout/LineLength:
- 'spec/requests/api/project_debian_distributions_spec.rb'
- 'spec/requests/api/project_events_spec.rb'
- 'spec/requests/api/project_export_spec.rb'
- - 'spec/requests/api/project_hooks_spec.rb'
- 'spec/requests/api/project_import_spec.rb'
- 'spec/requests/api/project_milestones_spec.rb'
- 'spec/requests/api/project_packages_spec.rb'
@@ -5647,7 +5320,6 @@ Layout/LineLength:
- 'spec/requests/api/release/links_spec.rb'
- 'spec/requests/api/releases_spec.rb'
- 'spec/requests/api/repositories_spec.rb'
- - 'spec/requests/api/resource_state_events_spec.rb'
- 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/api/search_spec.rb'
- 'spec/requests/api/settings_spec.rb'
@@ -5666,8 +5338,6 @@ Layout/LineLength:
- 'spec/requests/groups/settings/access_tokens_controller_spec.rb'
- 'spec/requests/groups_controller_spec.rb'
- 'spec/requests/ide_controller_spec.rb'
- - 'spec/requests/jira_connect/installations_controller_spec.rb'
- - 'spec/requests/jira_connect/users_controller_spec.rb'
- 'spec/requests/jwt_controller_spec.rb'
- 'spec/requests/lfs_http_spec.rb'
- 'spec/requests/oauth/tokens_controller_spec.rb'
@@ -5688,7 +5358,6 @@ Layout/LineLength:
- 'spec/requests/projects/merge_requests_spec.rb'
- 'spec/requests/projects/metrics/dashboards/builder_spec.rb'
- 'spec/requests/projects/noteable_notes_spec.rb'
- - 'spec/requests/projects/releases_controller_spec.rb'
- 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
- 'spec/requests/projects/tags_controller_spec.rb'
- 'spec/requests/projects_controller_spec.rb'
@@ -5702,7 +5371,6 @@ Layout/LineLength:
- 'spec/routing/project_routing_spec.rb'
- 'spec/routing/projects/security/configuration_controller_routing_spec.rb'
- 'spec/routing/routing_spec.rb'
- - 'spec/routing/uploads_routing_spec.rb'
- 'spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb'
- 'spec/rubocop/cop/lint/last_keyword_argument_spec.rb'
- 'spec/rubocop/cop/migration/safer_boolean_column_spec.rb'
@@ -5710,10 +5378,7 @@ Layout/LineLength:
- 'spec/rubocop/cop/performance/readlines_each_spec.rb'
- 'spec/rubocop/cop/rspec/env_assignment_spec.rb'
- 'spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb'
- - 'spec/rubocop/cop/scalability/file_uploads_spec.rb'
- - 'spec/scripts/changed-feature-flags_spec.rb'
- 'spec/scripts/failed_tests_spec.rb'
- - 'spec/scripts/pipeline_test_report_builder_spec.rb'
- 'spec/serializers/accessibility_error_entity_spec.rb'
- 'spec/serializers/accessibility_reports_comparer_entity_spec.rb'
- 'spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb'
@@ -5779,7 +5444,6 @@ Layout/LineLength:
- 'spec/services/ci/pipeline_processing/atomic_processing_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_job_service_spec.rb'
- 'spec/services/ci/runners/register_runner_service_spec.rb'
- 'spec/services/ci/test_failure_history_service_spec.rb'
- 'spec/services/ci/unlock_artifacts_service_spec.rb'
@@ -5804,7 +5468,6 @@ Layout/LineLength:
- 'spec/services/container_expiration_policies/cleanup_service_spec.rb'
- 'spec/services/container_expiration_policies/update_service_spec.rb'
- 'spec/services/customer_relations/contacts/create_service_spec.rb'
- - 'spec/services/customer_relations/contacts/update_service_spec.rb'
- 'spec/services/customer_relations/organizations/create_service_spec.rb'
- 'spec/services/dependency_proxy/find_cached_manifest_service_spec.rb'
- 'spec/services/deployments/link_merge_requests_service_spec.rb'
@@ -5812,7 +5475,6 @@ Layout/LineLength:
- 'spec/services/design_management/copy_design_collection/copy_service_spec.rb'
- 'spec/services/design_management/delete_designs_service_spec.rb'
- 'spec/services/design_management/design_user_notes_count_service_spec.rb'
- - 'spec/services/design_management/save_designs_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
- 'spec/services/discussions/resolve_service_spec.rb'
- 'spec/services/draft_notes/publish_service_spec.rb'
@@ -5833,7 +5495,6 @@ Layout/LineLength:
- 'spec/services/groups/autocomplete_service_spec.rb'
- 'spec/services/groups/create_service_spec.rb'
- 'spec/services/groups/group_links/destroy_service_spec.rb'
- - 'spec/services/groups/open_issues_count_service_spec.rb'
- 'spec/services/groups/transfer_service_spec.rb'
- 'spec/services/groups/update_service_spec.rb'
- 'spec/services/groups/update_shared_runners_service_spec.rb'
@@ -5871,7 +5532,6 @@ Layout/LineLength:
- 'spec/services/jira_import/cloud_users_mapper_service_spec.rb'
- 'spec/services/jira_import/server_users_mapper_service_spec.rb'
- 'spec/services/jira_import/start_import_service_spec.rb'
- - 'spec/services/jira_import/users_importer_spec.rb'
- 'spec/services/labels/available_labels_service_spec.rb'
- 'spec/services/labels/promote_service_spec.rb'
- 'spec/services/labels/transfer_service_spec.rb'
@@ -5889,7 +5549,6 @@ Layout/LineLength:
- 'spec/services/merge_requests/assign_issues_service_spec.rb'
- 'spec/services/merge_requests/base_service_spec.rb'
- 'spec/services/merge_requests/build_service_spec.rb'
- - 'spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb'
- 'spec/services/merge_requests/cleanup_refs_service_spec.rb'
- 'spec/services/merge_requests/conflicts/list_service_spec.rb'
- 'spec/services/merge_requests/create_from_issue_service_spec.rb'
@@ -5901,8 +5560,6 @@ Layout/LineLength:
- 'spec/services/merge_requests/link_lfs_objects_service_spec.rb'
- 'spec/services/merge_requests/merge_service_spec.rb'
- 'spec/services/merge_requests/merge_to_ref_service_spec.rb'
- - 'spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb'
- - 'spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb'
- 'spec/services/merge_requests/mergeability/run_checks_service_spec.rb'
- 'spec/services/merge_requests/mergeability_check_service_spec.rb'
- 'spec/services/merge_requests/push_options_handler_service_spec.rb'
@@ -5910,7 +5567,6 @@ Layout/LineLength:
- 'spec/services/merge_requests/refresh_service_spec.rb'
- 'spec/services/merge_requests/request_review_service_spec.rb'
- 'spec/services/merge_requests/squash_service_spec.rb'
- - 'spec/services/merge_requests/toggle_attention_requested_service_spec.rb'
- 'spec/services/merge_requests/update_service_spec.rb'
- 'spec/services/metrics/dashboard/annotations/create_service_spec.rb'
- 'spec/services/metrics/dashboard/clone_dashboard_service_spec.rb'
@@ -5984,7 +5640,6 @@ Layout/LineLength:
- 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
- 'spec/services/projects/lfs_pointers/lfs_import_service_spec.rb'
- 'spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb'
- - 'spec/services/projects/open_issues_count_service_spec.rb'
- 'spec/services/projects/operations/update_service_spec.rb'
- 'spec/services/projects/overwrite_project_service_spec.rb'
- 'spec/services/projects/transfer_service_spec.rb'
@@ -5994,7 +5649,6 @@ Layout/LineLength:
- 'spec/services/projects/update_service_spec.rb'
- 'spec/services/protected_branches/create_service_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb'
- - 'spec/services/repositories/destroy_service_spec.rb'
- 'spec/services/repository_archive_clean_up_service_spec.rb'
- 'spec/services/resource_access_tokens/create_service_spec.rb'
- 'spec/services/resource_access_tokens/revoke_service_spec.rb'
@@ -6006,7 +5660,6 @@ Layout/LineLength:
- 'spec/services/search_service_spec.rb'
- 'spec/services/security/ci_configuration/sast_create_service_spec.rb'
- 'spec/services/security/merge_reports_service_spec.rb'
- - 'spec/services/service_ping/submit_service_ping_service_spec.rb'
- 'spec/services/snippets/create_service_spec.rb'
- 'spec/services/snippets/update_repository_storage_service_spec.rb'
- 'spec/services/snippets/update_service_spec.rb'
@@ -6034,7 +5687,6 @@ Layout/LineLength:
- 'spec/services/web_hooks/log_execution_service_spec.rb'
- 'spec/services/work_items/create_and_link_service_spec.rb'
- 'spec/services/work_items/create_from_task_service_spec.rb'
- - 'spec/services/work_items/create_service_spec.rb'
- 'spec/services/work_items/task_list_reference_replacement_service_spec.rb'
- 'spec/services/work_items/update_service_spec.rb'
- 'spec/services/x509_certificate_revoke_service_spec.rb'
@@ -6058,7 +5710,6 @@ Layout/LineLength:
- 'spec/support/helpers/feature_flag_helpers.rb'
- 'spec/support/helpers/filtered_search_helpers.rb'
- 'spec/support/helpers/git_http_helpers.rb'
- - 'spec/support/helpers/global_id_deprecation_helpers.rb'
- 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/helpers/javascript_fixtures_helpers.rb'
- 'spec/support/helpers/kubernetes_helpers.rb'
@@ -6111,7 +5762,6 @@ Layout/LineLength:
- 'spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb'
- 'spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb'
- 'spec/support/shared_examples/features/2fa_shared_examples.rb'
- - 'spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb'
- 'spec/support/shared_examples/features/container_registry_shared_examples.rb'
- 'spec/support/shared_examples/features/discussion_comments_shared_example.rb'
- 'spec/support/shared_examples/features/editable_merge_request_shared_examples.rb'
@@ -6235,7 +5885,6 @@ Layout/LineLength:
- 'spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb'
- 'spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb'
- 'spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb'
- - 'spec/support/shared_examples/snippet_blob_shared_examples.rb'
- 'spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb'
- 'spec/support/shared_examples/uploaders/upload_type_shared_examples.rb'
- 'spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb'
@@ -6251,7 +5900,6 @@ Layout/LineLength:
- 'spec/tasks/dev_rake_spec.rb'
- 'spec/tasks/gitlab/artifacts/check_rake_spec.rb'
- 'spec/tasks/gitlab/background_migrations_rake_spec.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/db/validate_config_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/tasks/gitlab/external_diffs_rake_spec.rb'
@@ -6267,7 +5915,6 @@ Layout/LineLength:
- 'spec/tasks/gitlab/storage_rake_spec.rb'
- 'spec/tasks/gitlab/task_helpers_spec.rb'
- 'spec/tasks/gitlab/terraform/migrate_rake_spec.rb'
- - 'spec/tasks/gitlab/update_templates_rake_spec.rb'
- 'spec/tasks/gitlab/uploads/check_rake_spec.rb'
- 'spec/tasks/gitlab/workhorse_rake_spec.rb'
- 'spec/tasks/migrate/schema_check_rake_spec.rb'
@@ -6306,13 +5953,10 @@ Layout/LineLength:
- 'spec/views/layouts/_head.html.haml_spec.rb'
- 'spec/views/layouts/application.html.haml_spec.rb'
- 'spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb'
- - 'spec/views/notify/change_in_merge_request_draft_status_email.html.haml_spec.rb'
- - 'spec/views/notify/change_in_merge_request_draft_status_email.text.erb_spec.rb'
- 'spec/views/notify/push_to_merge_request_email.text.haml_spec.rb'
- 'spec/views/profiles/keys/_form.html.haml_spec.rb'
- 'spec/views/projects/artifacts/_artifact.html.haml_spec.rb'
- 'spec/views/projects/commits/_commit.html.haml_spec.rb'
- - 'spec/views/projects/edit.html.haml_spec.rb'
- 'spec/views/projects/imports/new.html.haml_spec.rb'
- 'spec/views/projects/jobs/_build.html.haml_spec.rb'
- 'spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb'
@@ -6356,8 +6000,6 @@ Layout/LineLength:
- 'spec/workers/container_registry/migration/guard_worker_spec.rb'
- 'spec/workers/container_registry/migration/observer_worker_spec.rb'
- 'spec/workers/create_pipeline_worker_spec.rb'
- - 'spec/workers/database/batched_background_migration/ci_database_worker_spec.rb'
- - 'spec/workers/database/batched_background_migration_worker_spec.rb'
- 'spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb'
- 'spec/workers/deployments/hooks_worker_spec.rb'
- 'spec/workers/deployments/update_environment_worker_spec.rb'
@@ -6380,8 +6022,6 @@ Layout/LineLength:
- 'spec/workers/jira_connect/sync_project_worker_spec.rb'
- 'spec/workers/loose_foreign_keys/cleanup_worker_spec.rb'
- 'spec/workers/members_destroyer/unassign_issuables_worker_spec.rb'
- - 'spec/workers/merge_requests/create_pipeline_worker_spec.rb'
- - 'spec/workers/merge_requests/update_head_pipeline_worker_spec.rb'
- 'spec/workers/new_issue_worker_spec.rb'
- 'spec/workers/new_merge_request_worker_spec.rb'
- 'spec/workers/packages/cleanup_package_file_worker_spec.rb'
@@ -6394,7 +6034,6 @@ Layout/LineLength:
- 'spec/workers/personal_access_tokens/expiring_worker_spec.rb'
- 'spec/workers/post_receive_spec.rb'
- 'spec/workers/projects/post_creation_worker_spec.rb'
- - 'spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb'
- 'spec/workers/propagate_integration_inherit_descendant_worker_spec.rb'
- 'spec/workers/remove_expired_members_worker_spec.rb'
- 'spec/workers/repository_check/dispatch_worker_spec.rb'
diff --git a/.rubocop_todo/layout/space_around_operators.yml b/.rubocop_todo/layout/space_around_operators.yml
new file mode 100644
index 00000000000..9f6c0145723
--- /dev/null
+++ b/.rubocop_todo/layout/space_around_operators.yml
@@ -0,0 +1,5 @@
+---
+# Cop supports --auto-correct.
+Layout/SpaceAroundOperators:
+ Exclude:
+ - 'lib/gitlab/utils/strong_memoize.rb'
diff --git a/.rubocop_todo/layout/space_before_block_braces.yml b/.rubocop_todo/layout/space_before_block_braces.yml
new file mode 100644
index 00000000000..3be90947fee
--- /dev/null
+++ b/.rubocop_todo/layout/space_before_block_braces.yml
@@ -0,0 +1,5 @@
+---
+# Cop supports --auto-correct.
+Layout/SpaceBeforeBlockBraces:
+ Exclude:
+ - 'app/helpers/colors_helper.rb'
diff --git a/.rubocop_todo/layout/space_inside_block_braces.yml b/.rubocop_todo/layout/space_inside_block_braces.yml
new file mode 100644
index 00000000000..c775ad94e46
--- /dev/null
+++ b/.rubocop_todo/layout/space_inside_block_braces.yml
@@ -0,0 +1,5 @@
+---
+# Cop supports --auto-correct.
+Layout/SpaceInsideBlockBraces:
+ Exclude:
+ - 'spec/requests/api/groups_spec.rb'
diff --git a/.rubocop_todo/layout/space_inside_parens.yml b/.rubocop_todo/layout/space_inside_parens.yml
index 301568f0ec4..805a9791409 100644
--- a/.rubocop_todo/layout/space_inside_parens.yml
+++ b/.rubocop_todo/layout/space_inside_parens.yml
@@ -418,7 +418,6 @@ Layout/SpaceInsideParens:
- 'spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/releases_shared_examples.rb'
- 'spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/validators/devise_email_validator_spec.rb'
- 'spec/views/shared/runners/_runner_details.html.haml_spec.rb'
diff --git a/.rubocop_todo/layout/trailing_whitespace.yml b/.rubocop_todo/layout/trailing_whitespace.yml
new file mode 100644
index 00000000000..d9c88c989e0
--- /dev/null
+++ b/.rubocop_todo/layout/trailing_whitespace.yml
@@ -0,0 +1,16 @@
+---
+# Cop supports --auto-correct.
+Layout/TrailingWhitespace:
+ Details: grace period
+ Exclude:
+ - 'app/models/concerns/analytics/cycle_analytics/stage_event_model.rb'
+ - 'db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb'
+ - 'db/migrate/20220913082728_drop_index_cadence_create_iterations_automation.rb'
+ - 'db/post_migrate/20220816163444_update_start_date_for_iterations_cadences.rb'
+ - 'lib/gitlab/background_migration/fix_duplicate_project_name_and_path.rb'
+ - 'lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb'
+ - 'lib/gitlab/pagination/keyset/sql_type_missing_error.rb'
+ - 'qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb'
+ - 'spec/lib/banzai/filter/front_matter_filter_spec.rb'
+ - 'spec/services/suggestions/apply_service_spec.rb'
+ - 'spec/support/helpers/x509_helpers.rb'
diff --git a/.rubocop_todo/lint/binary_operator_with_identical_operands.yml b/.rubocop_todo/lint/binary_operator_with_identical_operands.yml
deleted file mode 100644
index 90c3a76d3b1..00000000000
--- a/.rubocop_todo/lint/binary_operator_with_identical_operands.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-Lint/BinaryOperatorWithIdenticalOperands:
- Exclude:
- - 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- - 'spec/helpers/visibility_level_helper_spec.rb'
- - 'spec/lib/gitlab/conan_token_spec.rb'
- - 'spec/lib/gitlab/git/conflict/parser_spec.rb'
- - 'spec/lib/gitlab/graphql/lazy_spec.rb'
- - 'spec/models/ci/build_trace_chunk_spec.rb'
- - 'spec/models/clusters/platforms/kubernetes_spec.rb'
- - 'spec/models/concerns/where_composite_spec.rb'
- - 'spec/models/metrics/dashboard/annotation_spec.rb'
- - 'spec/models/repository_spec.rb'
- - 'spec/models/ssh_host_key_spec.rb'
- - 'spec/tooling/danger/sidekiq_queues_spec.rb'
diff --git a/.rubocop_todo/lint/duplicate_case_condition.yml b/.rubocop_todo/lint/duplicate_case_condition.yml
new file mode 100644
index 00000000000..d7e1eac2e03
--- /dev/null
+++ b/.rubocop_todo/lint/duplicate_case_condition.yml
@@ -0,0 +1,4 @@
+---
+Lint/DuplicateCaseCondition:
+ Exclude:
+ - 'app/helpers/icons_helper.rb'
diff --git a/.rubocop_todo/lint/redundant_cop_disable_directive.yml b/.rubocop_todo/lint/redundant_cop_disable_directive.yml
index e4925aa2cfd..b0b5697536e 100644
--- a/.rubocop_todo/lint/redundant_cop_disable_directive.yml
+++ b/.rubocop_todo/lint/redundant_cop_disable_directive.yml
@@ -1,18 +1,25 @@
---
# Cop supports --auto-correct.
Lint/RedundantCopDisableDirective:
- # This cop can only be enabled after enabling all cops which are currently
- # disabled. Otherwise we'll see RuboCop complaining depending on
- # REVEAL_RUBOCOP_TODO environment variable.
+ # Used to be enabled in "grace period" and is now disabled due to too many
+ # silenced offenses.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/376133
Enabled: false
Exclude:
+ - 'app/controllers/concerns/enforces_two_factor_authentication.rb'
+ - 'app/controllers/concerns/web_hooks/hook_log_actions.rb'
+ - 'app/controllers/groups/autocomplete_sources_controller.rb'
+ - 'app/controllers/groups/labels_controller.rb'
+ - 'app/controllers/projects/merge_requests/diffs_controller.rb'
- 'app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb'
- 'app/finders/autocomplete/move_to_project_finder.rb'
- 'app/finders/autocomplete/routes_finder.rb'
- 'app/finders/autocomplete/users_finder.rb'
- 'app/finders/ci/daily_build_group_report_results_finder.rb'
+ - 'app/finders/ci/runner_jobs_finder.rb'
- 'app/finders/groups_finder.rb'
- 'app/finders/users_finder.rb'
+ - 'app/graphql/gitlab_schema.rb'
- 'app/graphql/resolvers/concerns/caching_array_resolver.rb'
- 'app/graphql/resolvers/project_milestones_resolver.rb'
- 'app/graphql/types/base_enum.rb'
@@ -20,13 +27,17 @@ Lint/RedundantCopDisableDirective:
- 'app/graphql/types/packages/helm/dependency_type.rb'
- 'app/graphql/types/projects/service_type_enum.rb'
- 'app/helpers/diff_helper.rb'
+ - 'app/helpers/lazy_image_tag_helper.rb'
- 'app/helpers/search_helper.rb'
+ - 'app/models/clusters/cluster.rb'
- 'app/models/concerns/cascading_namespace_setting_attribute.rb'
- 'app/models/concerns/from_except.rb'
- 'app/models/concerns/from_intersect.rb'
- 'app/models/concerns/from_union.rb'
+ - 'app/models/project_statistics.rb'
- 'app/models/user.rb'
- 'app/presenters/dev_ops_report/metric_presenter.rb'
+ - 'app/presenters/packages/nuget/search_results_presenter.rb'
- 'app/serializers/diffs_entity.rb'
- 'app/serializers/fork_namespace_entity.rb'
- 'app/services/ci/job_artifacts/destroy_batch_service.rb'
@@ -35,25 +46,35 @@ Lint/RedundantCopDisableDirective:
- 'app/services/database/consistency_check_service.rb'
- 'app/services/issues/export_csv_service.rb'
- 'app/services/labels/transfer_service.rb'
+ - 'app/services/members/create_service.rb'
+ - 'app/services/members/creator_service.rb'
+ - 'app/services/members/projects/creator_service.rb'
+ - 'app/services/members/standard_member_builder.rb'
- 'app/services/projects/auto_devops/disable_service.rb'
- 'app/services/projects/open_issues_count_service.rb'
- 'app/services/spam/spam_action_service.rb'
- 'app/services/users/migrate_to_ghost_user_service.rb'
- - 'app/services/web_hooks/destroy_service.rb'
+ - 'app/services/web_hook_service.rb'
+ - 'app/uploaders/object_storage/cdn/google_ip_cache.rb'
- 'app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb'
+ - 'app/workers/build_hooks_worker.rb'
- 'app/workers/bulk_imports/entity_worker.rb'
- - 'app/workers/container_expiration_policy_worker.rb'
+ - 'app/workers/ci/track_failed_build_worker.rb'
+ - 'app/workers/container_registry/migration/enqueuer_worker.rb'
- 'app/workers/create_note_diff_file_worker.rb'
- 'app/workers/import_issues_csv_worker.rb'
- 'app/workers/incident_management/process_alert_worker_v2.rb'
- 'app/workers/merge_worker.rb'
- 'app/workers/remove_unaccepted_member_invites_worker.rb'
- 'config/initializers/warden.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
+ - 'config/initializers/wikicloth_ruby_3_patch.rb'
- 'config/routes/api.rb'
- 'db/migrate/20210303193544_add_concurrent_fields_to_bulk_imports_trackers.rb'
- 'db/migrate/20210917134321_remove_temporary_index_for_project_topics_on_taggings.rb'
- 'db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb'
+ - 'db/migrate/20220316022505_create_namespace_details.rb'
+ - 'db/migrate/20220421141342_add_allowed_plans_to_ci_runners.rb'
+ - 'db/migrate/20220531024905_add_operations_access_levels_to_project_feature.rb'
- 'db/post_migrate/20210610042700_remove_clusters_applications_fluentd_table.rb'
- 'db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb'
- 'db/post_migrate/20210730104800_schedule_extract_project_topics_into_separate_table.rb'
@@ -62,8 +83,12 @@ Lint/RedundantCopDisableDirective:
- 'db/post_migrate/20211028100303_tmp_index_for_delete_issue_merge_request_taggings_records.rb'
- 'db/post_migrate/20220328100456_schedule20220328_reset_duplicate_ci_runners_token_encrypted_values_on_projects.rb'
- 'db/post_migrate/20220328100457_schedule20220328_reset_duplicate_ci_runners_token_values_on_projects.rb'
+ - 'db/post_migrate/20220720090354_remove_pending_builds_covering_index_from_ci_builds.rb'
+ - 'db/post_migrate/20220902204048_move_security_findings_table_to_gitlab_partitions_dynamic_schema.rb'
- 'ee/app/controllers/ee/groups/group_members_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/ci_cd_controller.rb'
- 'ee/app/controllers/groups/todos_controller.rb'
+ - 'ee/app/experiments/cart_abandonment_modal_experiment.rb'
- 'ee/app/finders/geo/file_registry_finder.rb'
- 'ee/app/finders/geo/project_registry_finder.rb'
- 'ee/app/finders/geo/registry_finder.rb'
@@ -72,13 +97,16 @@ Lint/RedundantCopDisableDirective:
- 'ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb'
- 'ee/app/graphql/types/incident_management/oncall_rotation_active_period_input_type.rb'
- 'ee/app/graphql/types/scan_type.rb'
+ - 'ee/app/graphql/types/vulnerability_request_type.rb'
- 'ee/app/helpers/ee/boards_helper.rb'
- - 'ee/app/helpers/ee/namespaces_helper.rb'
- 'ee/app/helpers/projects/on_demand_scans_helper.rb'
+ - 'ee/app/models/dast/branch.rb'
- 'ee/app/models/ee/vulnerability.rb'
- 'ee/app/models/geo/event_log.rb'
+ - 'ee/app/services/analytics/cycle_analytics/consistency_check_service.rb'
- 'ee/app/services/analytics/cycle_analytics/data_loader_service.rb'
- 'ee/app/services/ee/boards/issues/list_service.rb'
+ - 'ee/app/services/ee/ci/queue/build_queue_service.rb'
- 'ee/app/services/ee/search_service.rb'
- 'ee/app/services/ee/users/migrate_to_ghost_user_service.rb'
- 'ee/app/services/geo/repository_base_sync_service.rb'
@@ -92,20 +120,30 @@ Lint/RedundantCopDisableDirective:
- 'ee/db/geo/migrate/20210504143244_add_verification_to_merge_request_diff_registry.rb'
- 'ee/lib/analytics/merge_request_metrics_calculator.rb'
- 'ee/lib/api/audit_events.rb'
+ - 'ee/lib/api/scim.rb'
- 'ee/lib/ee/api/entities/analytics/code_review/merge_request.rb'
- - 'ee/lib/ee/api/settings.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_epic_cache_counts.rb'
+ - 'ee/lib/ee/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb'
+ - 'ee/lib/ee/gitlab/background_migration/purge_stale_security_scans.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
+ - 'ee/lib/elastic/latest/git_class_proxy.rb'
- 'ee/lib/gitlab/analytics/type_of_work/tasks_by_type.rb'
+ - 'ee/lib/gitlab/elastic/bool_expr.rb'
+ - 'ee/lib/gitlab/spdx/license.rb'
+ - 'ee/lib/gitlab/status_page/storage/object.rb'
+ - 'ee/spec/features/boards/user_visits_board_spec.rb'
+ - 'ee/spec/features/groups/settings/domain_verification_spec.rb'
- 'ee/spec/helpers/ee/releases_helper_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size_spec.rb'
- 'ee/spec/lib/ee/gitlab/issuable_metadata_spec.rb'
- 'ee/spec/lib/elastic/latest/project_instance_proxy_spec.rb'
+ - 'ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environment_approval_rules_required_approvals_average_metric_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
- 'ee/spec/services/security/merge_reports_service_spec.rb'
- 'ee/spec/support/shared_examples/models/elasticsearch_indexed_container_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/geo_verifiable_registry_shared_examples.rb'
- 'lib/api/api.rb'
- 'lib/api/ci/variables.rb'
- - 'lib/api/entities/environment.rb'
- 'lib/api/entities/issuable_time_stats.rb'
- 'lib/api/helpers.rb'
- 'lib/bulk_imports/common/transformers/user_reference_transformer.rb'
@@ -115,24 +153,32 @@ Lint/RedundantCopDisableDirective:
- 'lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb'
- 'lib/gitlab/analytics/cycle_analytics/base_query_builder.rb'
- 'lib/gitlab/analytics/cycle_analytics/records_fetcher.rb'
+ - 'lib/gitlab/application_context.rb'
- 'lib/gitlab/background_migration/backfill_issue_search_data.rb'
+ - 'lib/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
+ - 'lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb'
- 'lib/gitlab/background_migration/drop_invalid_vulnerabilities.rb'
- - 'lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb'
- 'lib/gitlab/background_migration/migrate_personal_namespace_project_maintainer_to_owner.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
+ - 'lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb'
+ - 'lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/bitbucket_import/importer.rb'
+ - 'lib/gitlab/buffered_io.rb'
- 'lib/gitlab/cache/request_cache.rb'
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
+ - 'lib/gitlab/ci/pipeline/chain/command.rb'
- 'lib/gitlab/ci/pipeline/duration.rb'
- 'lib/gitlab/ci/reports/accessibility_reports.rb'
- - 'lib/gitlab/ci/reports/test_reports.rb'
+ - 'lib/gitlab/ci/reports/test_report.rb'
- 'lib/gitlab/ci/reports/test_reports_comparer.rb'
- 'lib/gitlab/ci/reports/test_suite.rb'
- 'lib/gitlab/ci/reports/test_suite_summary.rb'
+ - 'lib/gitlab/cleanup/personal_access_tokens.rb'
- 'lib/gitlab/composer/cache.rb'
- 'lib/gitlab/database/consistency_checker.rb'
- 'lib/gitlab/database/migration.rb'
+ - 'lib/gitlab/database/migrations/observation.rb'
- 'lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb'
- 'lib/gitlab/diff/file.rb'
- 'lib/gitlab/diff/file_collection/merge_request_diff_batch.rb'
@@ -140,52 +186,95 @@ Lint/RedundantCopDisableDirective:
- 'lib/gitlab/diff/parser.rb'
- 'lib/gitlab/encrypted_ldap_command.rb'
- 'lib/gitlab/encrypted_smtp_command.rb'
+ - 'lib/gitlab/git/commit.rb'
- 'lib/gitlab/git/patches/collection.rb'
- 'lib/gitlab/github_import/user_finder.rb'
- 'lib/gitlab/gitlab_import/importer.rb'
- 'lib/gitlab/graphql/pagination/keyset/connection.rb'
+ - 'lib/gitlab/health_checks/metric.rb'
+ - 'lib/gitlab/health_checks/probes/status.rb'
+ - 'lib/gitlab/health_checks/result.rb'
- 'lib/gitlab/legacy_github_import/user_formatter.rb'
+ - 'lib/gitlab/middleware/release_env.rb'
- 'lib/gitlab/object_hierarchy.rb'
- 'lib/gitlab/pagination/keyset/pager.rb'
- 'lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb'
- 'lib/gitlab/profiler.rb'
- 'lib/gitlab/project_search_results.rb'
- 'lib/gitlab/redis/hll.rb'
+ - 'lib/gitlab/search/sort_options.rb'
- 'lib/gitlab/slash_commands/issue_search.rb'
+ - 'lib/gitlab/slash_commands/result.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb'
- 'lib/gitlab/usage_data.rb'
- 'lib/gitlab/usage_data_queries.rb'
- 'lib/gitlab/utils/usage_data.rb'
+ - 'lib/gitlab/x509/signature.rb'
- 'lib/tasks/gitlab/cleanup.rake'
+ - 'qa/tasks/ci.rake'
+ - 'scripts/lib/glfm/render_static_html.rb'
- 'scripts/security-harness'
- 'sidekiq_cluster/cli.rb'
- 'sidekiq_cluster/sidekiq_cluster.rb'
+ - 'spec/components/previews/pajamas/banner_component_preview.rb'
+ - 'spec/fixtures/packages/rubygems/package.gemspec'
- 'spec/frontend/fixtures/merge_requests.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/resolvers/base_resolver_spec.rb'
- 'spec/helpers/releases_helper_spec.rb'
+ - 'spec/initializers/memory_watchdog_spec.rb'
- 'spec/lib/gitlab/avatar_cache_spec.rb'
- - 'spec/lib/gitlab/background_migration/batching_strategies/backfill_issue_work_item_type_batching_strategy_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb'
+ - 'spec/lib/gitlab/background_migration/batching_strategies/backfill_project_statistics_with_container_registry_size_batching_strategy_spec.rb'
+ - 'spec/lib/gitlab/background_migration/batching_strategies/remove_backfilled_job_artifacts_expire_at_batching_strategy_spec.rb'
- 'spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb'
- 'spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb'
- 'spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb'
+ - 'spec/lib/gitlab/ci/reports/security/scanner_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb'
+ - 'spec/lib/gitlab/doorkeeper_secret_storing/secret/pbkdf2_sha512_spec.rb'
+ - 'spec/lib/gitlab/doorkeeper_secret_storing/token/pbkdf2_sha512_spec.rb'
- 'spec/lib/gitlab/git/tree_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/relation_saver_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/iterator_spec.rb'
+ - 'spec/lib/gitlab/rack_attack/request_spec.rb'
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb'
+ - 'spec/lib/initializer_connections_spec.rb'
- 'spec/metrics_server/metrics_server_spec.rb'
+ - 'spec/migrations/20220725150127_update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
+ - 'spec/migrations/reschedule_backfill_imported_issue_search_data_spec.rb'
- 'spec/models/ci/build_trace_chunk_spec.rb'
+ - 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/namespace/package_setting_spec.rb'
- 'spec/models/namespace_spec.rb'
+ - 'spec/models/project_feature_spec.rb'
+ - 'spec/models/project_spec.rb'
+ - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
+ - 'spec/presenters/packages/pypi/simple_index_presenter_spec.rb'
+ - 'spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb'
- 'spec/requests/api/alert_management_alerts_spec.rb'
+ - 'spec/requests/api/graphql/ci/config_spec.rb'
- 'spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb'
- 'spec/services/alert_management/metric_images/upload_service_spec.rb'
- - 'spec/services/suggestions/apply_service_spec.rb'
+ - 'spec/services/projects/update_statistics_service_spec.rb'
+ - 'spec/services/spam/spam_verdict_service_spec.rb'
+ - 'spec/services/topics/merge_service_spec.rb'
+ - 'spec/support/forgery_protection.rb'
- 'spec/support/helpers/snowplow_helpers.rb'
- 'spec/support/helpers/wait_for_requests.rb'
+ - 'spec/support/shared_examples/lib/gitlab/local_and_remote_storage_migration_shared_examples.rb'
- 'spec/support/shared_examples/models/boards/listable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb'
- 'spec/support/shared_examples/models/packages/debian/distribution_key_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb'
+ - 'spec/tasks/gitlab/db/validate_config_rake_spec.rb'
- 'spec/uploaders/packages/composer/cache_uploader_spec.rb'
- 'tooling/danger/product_intelligence.rb'
- 'tooling/lib/tooling/helm3_client.rb'
diff --git a/.rubocop_todo/metrics/abc_size.yml b/.rubocop_todo/metrics/abc_size.yml
index 747ef3823f5..f5646151592 100644
--- a/.rubocop_todo/metrics/abc_size.yml
+++ b/.rubocop_todo/metrics/abc_size.yml
@@ -12,3 +12,4 @@ Metrics/AbcSize:
- 'lib/gitlab/analytics/cycle_analytics/request_params.rb'
- 'lib/gitlab/sidekiq_middleware/server_metrics.rb'
- 'qa/qa/resource/repository/push.rb'
+ - 'ee/db/seeds/awesome_co/**/*.rb'
diff --git a/.rubocop_todo/metrics/parameter_lists.yml b/.rubocop_todo/metrics/parameter_lists.yml
new file mode 100644
index 00000000000..14cd46d31fb
--- /dev/null
+++ b/.rubocop_todo/metrics/parameter_lists.yml
@@ -0,0 +1,9 @@
+---
+Metrics/ParameterLists:
+ Exclude:
+ - 'app/helpers/avatars_helper.rb'
+ - 'app/helpers/blob_helper.rb'
+ - 'app/models/packages/sem_ver.rb'
+ - 'app/models/repository.rb'
+ - 'lib/gitlab/git/tree.rb'
+ - 'lib/gitlab/version_info.rb'
diff --git a/.rubocop_todo/performance/bind_call.yml b/.rubocop_todo/performance/bind_call.yml
new file mode 100644
index 00000000000..5adb519793d
--- /dev/null
+++ b/.rubocop_todo/performance/bind_call.yml
@@ -0,0 +1,10 @@
+---
+# Cop supports --auto-correct.
+Performance/BindCall:
+ Exclude:
+ - 'app/services/metrics/dashboard/grafana_metric_embed_service.rb'
+ - 'ee/spec/features/issues/form_spec.rb'
+ - 'lib/gitlab/patch/prependable.rb'
+ - 'spec/features/issues/form_spec.rb'
+ - 'spec/mailers/notify_spec.rb'
+ - 'spec/support/patches/rspec_mocks_prepended_methods.rb'
diff --git a/.rubocop_todo/performance/redundant_block_call.yml b/.rubocop_todo/performance/redundant_block_call.yml
new file mode 100644
index 00000000000..89a67e3fd30
--- /dev/null
+++ b/.rubocop_todo/performance/redundant_block_call.yml
@@ -0,0 +1,12 @@
+---
+# Cop supports --auto-correct.
+Performance/RedundantBlockCall:
+ Exclude:
+ - 'ee/app/models/gitlab_subscription.rb'
+ - 'ee/lib/ee/gitlab/auth/ldap/sync/proxy.rb'
+ - 'lib/gitlab/auth/ldap/access.rb'
+ - 'lib/gitlab/auth/ldap/adapter.rb'
+ - 'lib/gitlab/database/bulk_update.rb'
+ - 'lib/gitlab/http.rb'
+ - 'lib/gitlab/safe_request_store.rb'
+ - 'lib/gitlab/timeless.rb'
diff --git a/.rubocop_todo/rails/active_record_callbacks_order.yml b/.rubocop_todo/rails/active_record_callbacks_order.yml
index 9585a720c6a..11ffff36e8d 100644
--- a/.rubocop_todo/rails/active_record_callbacks_order.yml
+++ b/.rubocop_todo/rails/active_record_callbacks_order.yml
@@ -1,12 +1,9 @@
---
# Cop supports --auto-correct.
Rails/ActiveRecordCallbacksOrder:
- # Offense count: 30
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/models/award_emoji.rb'
- - 'app/models/ci/job_artifact.rb'
- 'app/models/gpg_key.rb'
- 'app/models/group.rb'
- 'app/models/issue.rb'
diff --git a/.rubocop_todo/rails/file_path.yml b/.rubocop_todo/rails/file_path.yml
index 467073eb2db..24a08fa5ee2 100644
--- a/.rubocop_todo/rails/file_path.yml
+++ b/.rubocop_todo/rails/file_path.yml
@@ -1,10 +1,7 @@
---
Rails/FilePath:
- # Offense count: 212
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- - 'app/controllers/clusters/clusters_controller.rb'
- 'app/controllers/help_controller.rb'
- 'app/helpers/startupjs_helper.rb'
- 'app/models/clusters/applications/cert_manager.rb'
@@ -29,6 +26,7 @@ Rails/FilePath:
- 'ee/db/fixtures/development/21_dast_profiles.rb'
- 'ee/db/fixtures/development/32_compliance_report_violations.rb'
- 'ee/lib/ee/feature/definition.rb'
+ - 'ee/lib/ee/gitlab/audit/type/definition.rb'
- 'ee/lib/ee/gitlab/usage/metric_definition.rb'
- 'ee/lib/gitlab/geo/health_check.rb'
- 'ee/lib/tasks/gitlab/seed/metrics.rake'
@@ -48,6 +46,8 @@ Rails/FilePath:
- 'lib/api/api.rb'
- 'lib/error_tracking/collector/payload_validator.rb'
- 'lib/feature/definition.rb'
+ - 'lib/gitlab/audit/type/definition.rb'
+ - 'lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator.rb'
- 'lib/gitlab/ci/reports/codequality_reports.rb'
- 'lib/gitlab/database/migrations/runner.rb'
- 'lib/gitlab/favicon.rb'
@@ -69,14 +69,17 @@ Rails/FilePath:
- 'lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb'
- 'lib/system_check/app/uploads_directory_exists_check.rb'
- 'lib/system_check/incoming_email/imap_authentication_check.rb'
+ - 'lib/tasks/gitlab/db.rake'
- 'lib/tasks/gitlab/metrics_exporter.rake'
+ - 'lib/tasks/gitlab/usage_data.rake'
- 'lib/tasks/tanuki_emoji.rake'
- 'metrics_server/metrics_server.rb'
- 'spec/commands/metrics_server/metrics_server_spec.rb'
- 'spec/config/object_store_settings_spec.rb'
- - 'spec/controllers/help_controller_spec.rb'
+ - 'spec/db/development/add_security_training_providers_spec.rb'
- 'spec/db/development/create_base_work_item_types_spec.rb'
- 'spec/db/development/import_common_metrics_spec.rb'
+ - 'spec/db/production/add_security_training_providers_spec.rb'
- 'spec/db/production/create_base_work_item_types_spec.rb'
- 'spec/db/production/import_common_metrics_spec.rb'
- 'spec/db/schema_spec.rb'
@@ -100,7 +103,6 @@ Rails/FilePath:
- 'spec/features/projects/settings/repository_settings_spec.rb'
- 'spec/features/projects/settings/user_changes_avatar_spec.rb'
- 'spec/features/projects/snippets/create_snippet_spec.rb'
- - 'spec/features/projects/tags/user_edits_tags_spec.rb'
- 'spec/features/projects/tree/upload_file_spec.rb'
- 'spec/features/snippets/user_creates_snippet_spec.rb'
- 'spec/features/snippets/user_edits_snippet_spec.rb'
@@ -127,10 +129,12 @@ Rails/FilePath:
- 'spec/models/clusters/applications/cert_manager_spec.rb'
- 'spec/models/release_highlight_spec.rb'
- 'spec/requests/api/internal/mail_room_spec.rb'
+ - 'spec/requests/api/usage_data_queries_spec.rb'
- 'spec/serializers/review_app_setup_entity_spec.rb'
- 'spec/services/clusters/aws/fetch_credentials_service_spec.rb'
- 'spec/services/clusters/aws/provision_service_spec.rb'
- 'spec/services/metrics/sample_metrics_service_spec.rb'
+ - 'spec/support/helpers/doc_url_helper.rb'
- 'spec/support/helpers/test_env.rb'
- 'spec/support/helpers/upload_helpers.rb'
- 'spec/support/shared_examples/features/project_upload_files_shared_examples.rb'
@@ -139,3 +143,4 @@ Rails/FilePath:
- 'spec/support/shared_examples/models/wiki_shared_examples.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb'
+ - 'spec/tasks/gitlab/usage_data_rake_spec.rb'
diff --git a/.rubocop_todo/rails/helper_instance_variable.yml b/.rubocop_todo/rails/helper_instance_variable.yml
index f43ca39f47c..8f9197c9223 100644
--- a/.rubocop_todo/rails/helper_instance_variable.yml
+++ b/.rubocop_todo/rails/helper_instance_variable.yml
@@ -1,8 +1,6 @@
---
Rails/HelperInstanceVariable:
- # Offense count: 671
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/helpers/admin/user_actions_helper.rb'
- 'app/helpers/application_helper.rb'
@@ -29,7 +27,6 @@ Rails/HelperInstanceVariable:
- 'app/helpers/icons_helper.rb'
- 'app/helpers/ide_helper.rb'
- 'app/helpers/import_helper.rb'
- - 'app/helpers/integrations_helper.rb'
- 'app/helpers/issuables_description_templates_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/issues_helper.rb'
@@ -40,6 +37,7 @@ Rails/HelperInstanceVariable:
- 'app/helpers/nav_helper.rb'
- 'app/helpers/notes_helper.rb'
- 'app/helpers/operations_helper.rb'
+ - 'app/helpers/packages_helper.rb'
- 'app/helpers/page_layout_helper.rb'
- 'app/helpers/projects_helper.rb'
- 'app/helpers/releases_helper.rb'
@@ -59,11 +57,13 @@ Rails/HelperInstanceVariable:
- 'app/helpers/webpack_helper.rb'
- 'app/helpers/wiki_helper.rb'
- 'ee/app/helpers/ee/application_helper.rb'
+ - 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/boards_helper.rb'
- 'ee/app/helpers/ee/feature_flags_helper.rb'
- 'ee/app/helpers/ee/form_helper.rb'
- 'ee/app/helpers/ee/graph_helper.rb'
- 'ee/app/helpers/ee/groups/group_members_helper.rb'
+ - 'ee/app/helpers/ee/groups/settings_helper.rb'
- 'ee/app/helpers/ee/groups_helper.rb'
- 'ee/app/helpers/ee/integrations_helper.rb'
- 'ee/app/helpers/ee/kerberos_helper.rb'
@@ -77,7 +77,8 @@ Rails/HelperInstanceVariable:
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/helpers/ee/search_helper.rb'
- 'ee/app/helpers/ee/selects_helper.rb'
+ - 'ee/app/helpers/ee/sorting_helper.rb'
- 'ee/app/helpers/ee/subscribable_banner_helper.rb'
- 'ee/app/helpers/ee/wiki_helper.rb'
- 'ee/app/helpers/path_locks_helper.rb'
- - 'ee/app/helpers/projects/security/discover_helper.rb'
+ - 'ee/app/helpers/seat_count_alert_helper.rb'
diff --git a/.rubocop_todo/rails/http_status.yml b/.rubocop_todo/rails/http_status.yml
new file mode 100644
index 00000000000..1a8ece49304
--- /dev/null
+++ b/.rubocop_todo/rails/http_status.yml
@@ -0,0 +1,9 @@
+---
+# Cop supports --auto-correct.
+Rails/HttpStatus:
+ Exclude:
+ - 'app/controllers/concerns/invisible_captcha_on_signup.rb'
+ - 'app/controllers/projects/runner_projects_controller.rb'
+ - 'app/controllers/projects/service_ping_controller.rb'
+ - 'app/controllers/repositories/lfs_storage_controller.rb'
+ - 'ee/app/controllers/trials_controller.rb'
diff --git a/.rubocop_todo/rails/index_with.yml b/.rubocop_todo/rails/index_with.yml
index d8ccbd97f7c..91a75e198f5 100644
--- a/.rubocop_todo/rails/index_with.yml
+++ b/.rubocop_todo/rails/index_with.yml
@@ -1,29 +1,30 @@
---
# Cop supports --auto-correct.
Rails/IndexWith:
- # Offense count: 54
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/helpers/ci/jobs_helper.rb'
- 'app/models/ci/build_trace_chunk.rb'
- 'app/models/ci/processable.rb'
- 'app/models/concerns/cached_commit.rb'
+ - 'app/models/customer_relations/organization.rb'
- 'app/models/environment.rb'
- 'app/services/concerns/rate_limited_service.rb'
+ - 'app/services/packages/rpm/parse_package_service.rb'
- 'db/post_migrate/20210731132939_backfill_stage_event_hash.rb'
+ - 'ee/app/models/concerns/identity_verifiable.rb'
- 'ee/app/models/vulnerabilities/projects_grade.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
- 'ee/lib/gitlab/auth/group_saml/auth_hash.rb'
- 'ee/lib/gitlab/custom_file_templates.rb'
- 'ee/lib/gitlab/insights/reducers/count_per_label_reducer.rb'
- 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- - 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/sca/license_compliance_spec.rb'
- 'ee/spec/views/admin/dashboard/index.html.haml_spec.rb'
- 'lib/api/entities/project_integration.rb'
- 'lib/api/helpers/packages/conan/api_helpers.rb'
- 'lib/banzai/filter/repository_link_filter.rb'
+ - 'lib/gitlab/background_migration/backfill_note_discussion_id.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ci/reports/security/finding.rb'
@@ -32,10 +33,12 @@ Rails/IndexWith:
- 'lib/gitlab/database/count/exact_count_strategy.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/gitlab/database/obsolete_ignored_columns.rb'
+ - 'lib/gitlab/database/tables_sorted_by_foreign_keys.rb'
- 'lib/gitlab/issuable_metadata.rb'
- 'lib/gitlab/template/base_template.rb'
- 'lib/gitlab/usage_data.rb'
- 'lib/google_api/cloud_platform/client.rb'
+ - 'lib/tasks/gitlab/db.rake'
- 'qa/qa/resource/reusable.rb'
- 'scripts/trigger-build.rb'
- 'spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb'
diff --git a/.rubocop_todo/rails/inverse_of.yml b/.rubocop_todo/rails/inverse_of.yml
index 98d116c3319..262804739bd 100644
--- a/.rubocop_todo/rails/inverse_of.yml
+++ b/.rubocop_todo/rails/inverse_of.yml
@@ -1,8 +1,6 @@
---
Rails/InverseOf:
- # Offense count: 210
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/models/alert_management/alert.rb'
- 'app/models/alert_management/alert_assignee.rb'
@@ -12,7 +10,6 @@ Rails/InverseOf:
- 'app/models/board.rb'
- 'app/models/bulk_imports/entity.rb'
- 'app/models/bulk_imports/tracker.rb'
- - 'app/models/chat_name.rb'
- 'app/models/ci/bridge.rb'
- 'app/models/ci/build.rb'
- 'app/models/ci/build_pending_state.rb'
@@ -25,7 +22,6 @@ Rails/InverseOf:
- 'app/models/ci/runner.rb'
- 'app/models/ci/runner_namespace.rb'
- 'app/models/ci/sources/pipeline.rb'
- - 'app/models/ci/stage.rb'
- 'app/models/ci/trigger_request.rb'
- 'app/models/ci/unit_test_failure.rb'
- 'app/models/clusters/applications/runner.rb'
@@ -38,7 +34,6 @@ Rails/InverseOf:
- 'app/models/concerns/analytics/cycle_analytics/stage.rb'
- 'app/models/concerns/awardable.rb'
- 'app/models/concerns/commit_signature.rb'
- - 'app/models/concerns/merge_request_reviewer_state.rb'
- 'app/models/concerns/with_uploads.rb'
- 'app/models/custom_emoji.rb'
- 'app/models/customer_relations/contact.rb'
@@ -51,7 +46,7 @@ Rails/InverseOf:
- 'app/models/group.rb'
- 'app/models/group/crm_settings.rb'
- 'app/models/group_group_link.rb'
- - 'app/models/hooks/service_hook.rb'
+ - 'app/models/group_label.rb'
- 'app/models/incident_management/timeline_event.rb'
- 'app/models/integrations/base_slash_commands.rb'
- 'app/models/issue.rb'
@@ -66,11 +61,15 @@ Rails/InverseOf:
- 'app/models/packages/composer/cache_file.rb'
- 'app/models/packages/maven/metadatum.rb'
- 'app/models/project.rb'
+ - 'app/models/project_label.rb'
- 'app/models/resource_state_event.rb'
- 'app/models/serverless/domain_cluster.rb'
- 'app/models/terraform/state_version.rb'
+ - 'app/models/time_tracking/timelog_category.rb'
- 'app/models/todo.rb'
- 'app/models/user.rb'
+ - 'app/models/users/phone_number_validation.rb'
+ - 'app/models/work_item.rb'
- 'app/models/x509_certificate.rb'
- 'ee/app/models/allowed_email_domain.rb'
- 'ee/app/models/analytics/cycle_analytics/group_stage.rb'
@@ -78,12 +77,14 @@ Rails/InverseOf:
- 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
- 'ee/app/models/analytics/devops_adoption/snapshot.rb'
- 'ee/app/models/audit_events/external_audit_event_destination.rb'
+ - 'ee/app/models/audit_events/streaming/header.rb'
- 'ee/app/models/ci/sources/project.rb'
- 'ee/app/models/compliance_management/compliance_framework/project_settings.rb'
- 'ee/app/models/concerns/incident_management/base_pending_escalation.rb'
- 'ee/app/models/dast/profile_schedule.rb'
- 'ee/app/models/ee/ci/build.rb'
- 'ee/app/models/ee/ci/pipeline.rb'
+ - 'ee/app/models/ee/clusters/agent.rb'
- 'ee/app/models/ee/epic.rb'
- 'ee/app/models/ee/group.rb'
- 'ee/app/models/ee/iteration.rb'
@@ -105,9 +106,9 @@ Rails/InverseOf:
- 'ee/app/models/integrations/gitlab_slack_application.rb'
- 'ee/app/models/requirements_management/requirement.rb'
- 'ee/app/models/requirements_management/test_report.rb'
+ - 'ee/app/models/sbom/vulnerable_component_version.rb'
- 'ee/app/models/security/orchestration_policy_configuration.rb'
- 'ee/app/models/security/orchestration_policy_rule_schedule.rb'
- - 'ee/app/models/slack_integration.rb'
- 'ee/app/models/software_license_policy.rb'
- 'ee/app/models/user_permission_export_upload.rb'
- 'ee/app/models/vulnerabilities/feedback.rb'
diff --git a/.rubocop_todo/rails/redundant_foreign_key.yml b/.rubocop_todo/rails/redundant_foreign_key.yml
index 7e394849670..22af6131b33 100644
--- a/.rubocop_todo/rails/redundant_foreign_key.yml
+++ b/.rubocop_todo/rails/redundant_foreign_key.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Rails/RedundantForeignKey:
- # Offense count: 90
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/models/alert_management/metric_image.rb'
- 'app/models/ci/build.rb'
@@ -23,9 +21,11 @@ Rails/RedundantForeignKey:
- 'app/models/commit_signatures/x509_commit_signature.rb'
- 'app/models/concerns/analytics/cycle_analytics/stage.rb'
- 'app/models/concerns/commit_signature.rb'
+ - 'app/models/concerns/integrations/base_data_fields.rb'
- 'app/models/group.rb'
- 'app/models/group_group_link.rb'
- - 'app/models/integrations/zentao_tracker_data.rb'
+ - 'app/models/incident_management/timeline_event.rb'
+ - 'app/models/issue.rb'
- 'app/models/member.rb'
- 'app/models/merge_request.rb'
- 'app/models/merge_request/metrics.rb'
@@ -35,9 +35,13 @@ Rails/RedundantForeignKey:
- 'app/models/project.rb'
- 'app/models/resource_state_event.rb'
- 'app/models/review.rb'
+ - 'app/models/time_tracking/timelog_category.rb'
- 'app/models/user.rb'
+ - 'app/models/users/phone_number_validation.rb'
+ - 'app/models/work_item.rb'
- 'app/models/x509_certificate.rb'
- 'ee/app/models/allowed_email_domain.rb'
+ - 'ee/app/models/audit_events/streaming/header.rb'
- 'ee/app/models/boards/epic_board.rb'
- 'ee/app/models/boards/epic_list_user_preference.rb'
- 'ee/app/models/ci/sources/project.rb'
diff --git a/.rubocop_todo/rails/skips_model_validations.yml b/.rubocop_todo/rails/skips_model_validations.yml
index 8ef895ed562..f5aa7411c89 100644
--- a/.rubocop_todo/rails/skips_model_validations.yml
+++ b/.rubocop_todo/rails/skips_model_validations.yml
@@ -252,7 +252,6 @@ Rails/SkipsModelValidations:
- 'ee/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb'
- 'ee/spec/controllers/groups/ldaps_controller_spec.rb'
- 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'ee/spec/controllers/trials_controller_spec.rb'
- 'ee/spec/factories/import_states.rb'
- 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb'
diff --git a/.rubocop_todo/rails/time_zone.yml b/.rubocop_todo/rails/time_zone.yml
index 8931b337ce1..f1e7d519a8f 100644
--- a/.rubocop_todo/rails/time_zone.yml
+++ b/.rubocop_todo/rails/time_zone.yml
@@ -19,7 +19,6 @@ Rails/TimeZone:
- 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/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
diff --git a/.rubocop_todo/rspec/any_instance_of.yml b/.rubocop_todo/rspec/any_instance_of.yml
index e7855e84b28..5ee00cb0e24 100644
--- a/.rubocop_todo/rspec/any_instance_of.yml
+++ b/.rubocop_todo/rspec/any_instance_of.yml
@@ -13,7 +13,6 @@ RSpec/AnyInstanceOf:
- 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
diff --git a/.rubocop_todo/rspec/capybara/visibility_matcher.yml b/.rubocop_todo/rspec/capybara/visibility_matcher.yml
new file mode 100644
index 00000000000..f9e8c982903
--- /dev/null
+++ b/.rubocop_todo/rspec/capybara/visibility_matcher.yml
@@ -0,0 +1,79 @@
+---
+RSpec/Capybara/VisibilityMatcher:
+ Exclude:
+ - 'ee/spec/features/boards/sidebar_spec.rb'
+ - 'ee/spec/features/epics/epic_show_spec.rb'
+ - 'ee/spec/features/epics/todo_spec.rb'
+ - 'ee/spec/features/epics/update_epic_spec.rb'
+ - 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
+ - 'ee/spec/features/groups/issues_spec.rb'
+ - 'ee/spec/features/groups/saml_enforcement_spec.rb'
+ - 'ee/spec/features/groups/settings/protected_environments_spec.rb'
+ - 'ee/spec/features/issues/related_issues_spec.rb'
+ - 'ee/spec/features/projects/integrations/user_activates_jira_spec.rb'
+ - 'ee/spec/features/projects/quality/test_case_show_spec.rb'
+ - 'ee/spec/features/projects/requirements_management/requirements_list_spec.rb'
+ - 'ee/spec/features/projects/settings/ee/repository_mirrors_settings_spec.rb'
+ - 'ee/spec/features/promotion_spec.rb'
+ - 'ee/spec/features/registrations/welcome_spec.rb'
+ - 'ee/spec/support/helpers/billing_plans_helpers.rb'
+ - 'ee/spec/support/shared_examples/features/password_complexity_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/views/issuable_bulk_dropdown_shared_examples.rb'
+ - 'ee/spec/views/layouts/_search.html.haml_spec.rb'
+ - 'ee/spec/views/registrations/welcome/show.html.haml_spec.rb'
+ - 'spec/features/admin/admin_mode_spec.rb'
+ - 'spec/features/dashboard/merge_requests_spec.rb'
+ - 'spec/features/dashboard/todos/todos_spec.rb'
+ - 'spec/features/groups/group_settings_spec.rb'
+ - 'spec/features/issues/service_desk_spec.rb'
+ - 'spec/features/issues/todo_spec.rb'
+ - 'spec/features/issues/user_creates_branch_and_merge_request_spec.rb'
+ - 'spec/features/issues/user_creates_issue_spec.rb'
+ - 'spec/features/merge_request/user_posts_notes_spec.rb'
+ - 'spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb'
+ - 'spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb'
+ - 'spec/features/merge_request/user_sees_diff_spec.rb'
+ - 'spec/features/merge_request/user_sees_merge_widget_spec.rb'
+ - 'spec/features/merge_request/user_views_diffs_commit_spec.rb'
+ - 'spec/features/merge_request/user_views_diffs_spec.rb'
+ - 'spec/features/projects/blobs/blob_show_spec.rb'
+ - 'spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb'
+ - 'spec/features/projects/ci/lint_spec.rb'
+ - 'spec/features/projects/commit/comments/user_adds_comment_spec.rb'
+ - 'spec/features/projects/commits/multi_view_diff_spec.rb'
+ - 'spec/features/projects/commits/user_browses_commits_spec.rb'
+ - 'spec/features/projects/integrations/user_activates_jira_spec.rb'
+ - 'spec/features/projects/issues/design_management/user_views_designs_with_svg_xss_spec.rb'
+ - 'spec/features/projects/jobs_spec.rb'
+ - 'spec/features/projects/network_graph_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
+ - 'spec/features/projects/pipelines/pipeline_spec.rb'
+ - 'spec/features/projects/settings/lfs_settings_spec.rb'
+ - 'spec/features/projects/settings/packages_settings_spec.rb'
+ - 'spec/features/projects/settings/repository_settings_spec.rb'
+ - 'spec/features/projects/settings/visibility_settings_spec.rb'
+ - 'spec/features/projects/show/user_manages_notifications_spec.rb'
+ - 'spec/features/projects/user_changes_project_visibility_spec.rb'
+ - 'spec/features/projects/user_sees_user_popover_spec.rb'
+ - 'spec/features/search/user_searches_for_commits_spec.rb'
+ - 'spec/features/snippets/notes_on_personal_snippets_spec.rb'
+ - 'spec/features/task_lists_spec.rb'
+ - 'spec/features/u2f_spec.rb'
+ - 'spec/features/uploads/user_uploads_file_to_note_spec.rb'
+ - 'spec/features/users/email_verification_on_login_spec.rb'
+ - 'spec/features/users/overview_spec.rb'
+ - 'spec/features/users/user_browses_projects_on_user_page_spec.rb'
+ - 'spec/features/webauthn_spec.rb'
+ - 'spec/features/whats_new_spec.rb'
+ - 'spec/support/helpers/features/canonical_link_helpers.rb'
+ - 'spec/support/shared_examples/features/discussion_comments_shared_example.rb'
+ - 'spec/support/shared_examples/features/page_description_shared_examples.rb'
+ - 'spec/support/shared_examples/features/rss_shared_examples.rb'
+ - 'spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb'
+ - 'spec/views/import/gitlab_projects/new.html.haml_spec.rb'
+ - 'spec/views/layouts/_header_search.html.haml_spec.rb'
+ - 'spec/views/layouts/_search.html.haml_spec.rb'
+ - 'spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb'
+ - 'spec/views/profiles/preferences/show.html.haml_spec.rb'
+ - 'spec/views/projects/merge_requests/edit.html.haml_spec.rb'
+ - 'spec/views/projects/merge_requests/show.html.haml_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 97480a0e0ba..79dfd85281c 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -70,7 +70,6 @@ RSpec/ContextWording:
- 'ee/spec/controllers/security/vulnerabilities_controller_spec.rb'
- 'ee/spec/controllers/subscriptions_controller_spec.rb'
- 'ee/spec/controllers/trial_registrations_controller_spec.rb'
- - 'ee/spec/controllers/trials_controller_spec.rb'
- 'ee/spec/controllers/users_controller_spec.rb'
- 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
- 'ee/spec/elastic/migrate/20220512150000_pause_indexing_for_unsupported_es_versions_spec.rb'
@@ -2542,7 +2541,6 @@ RSpec/ContextWording:
- 'spec/policies/terraform/state_version_policy_spec.rb'
- 'spec/policies/user_policy_spec.rb'
- 'spec/presenters/blob_presenter_spec.rb'
- - 'spec/presenters/blobs/unfold_presenter_spec.rb'
- 'spec/presenters/ci/build_presenter_spec.rb'
- 'spec/presenters/ci/pipeline_presenter_spec.rb'
- 'spec/presenters/clusters/cluster_presenter_spec.rb'
@@ -3372,7 +3370,6 @@ RSpec/ContextWording:
- 'spec/tasks/cache/clear/redis_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- 'spec/tasks/gettext_rake_spec.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- 'spec/tasks/gitlab/db/lock_writes_rake_spec.rb'
- 'spec/tasks/gitlab/db/validate_config_rake_spec.rb'
diff --git a/.rubocop_todo/rspec/described_class.yml b/.rubocop_todo/rspec/described_class.yml
index 8304704985b..516eda12675 100644
--- a/.rubocop_todo/rspec/described_class.yml
+++ b/.rubocop_todo/rspec/described_class.yml
@@ -69,7 +69,6 @@ RSpec/DescribedClass:
- 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb'
- 'ee/spec/services/users/captcha_challenge_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb'
- 'ee/spec/workers/concerns/elastic/indexing_control_spec.rb'
- 'ee/spec/workers/elastic/migration_worker_spec.rb'
- 'ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/expect_change.yml b/.rubocop_todo/rspec/expect_change.yml
index f8962515874..626ed1390ce 100644
--- a/.rubocop_todo/rspec/expect_change.yml
+++ b/.rubocop_todo/rspec/expect_change.yml
@@ -1,11 +1,13 @@
---
# Cop supports --auto-correct.
RSpec/ExpectChange:
+ Details: grace period
Exclude:
- 'ee/spec/controllers/admin/applications_controller_spec.rb'
- 'ee/spec/controllers/ee/groups_controller_spec.rb'
- 'ee/spec/controllers/ee/omniauth_callbacks_controller_spec.rb'
- 'ee/spec/controllers/ee/registrations_controller_spec.rb'
+ - 'ee/spec/controllers/groups/analytics/cycle_analytics/value_streams_controller_spec.rb'
- 'ee/spec/controllers/groups/epic_issues_controller_spec.rb'
- 'ee/spec/controllers/groups/epics/notes_controller_spec.rb'
- 'ee/spec/controllers/groups/epics_controller_spec.rb'
@@ -21,19 +23,25 @@ RSpec/ExpectChange:
- 'ee/spec/controllers/projects/protected_environments_controller_spec.rb'
- 'ee/spec/controllers/projects/repositories_controller_spec.rb'
- 'ee/spec/controllers/projects/security/vulnerabilities/notes_controller_spec.rb'
+ - 'ee/spec/controllers/projects/vulnerability_feedback_controller_spec.rb'
- 'ee/spec/controllers/projects_controller_spec.rb'
- 'ee/spec/controllers/trials_controller_spec.rb'
- 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
+ - 'ee/spec/elastic/migrate/20220512150000_pause_indexing_for_unsupported_es_versions_spec.rb'
- 'ee/spec/features/groups/group_settings_spec.rb'
- 'ee/spec/features/projects_spec.rb'
- 'ee/spec/features/signup_spec.rb'
- 'ee/spec/features/users/login_spec.rb'
- 'ee/spec/graphql/ee/mutations/ci/runner/update_spec.rb'
- 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
+ - 'ee/spec/graphql/mutations/compliance_management/frameworks/destroy_spec.rb'
- 'ee/spec/graphql/mutations/compliance_management/frameworks/update_spec.rb'
+ - 'ee/spec/graphql/mutations/dast/profiles/delete_spec.rb'
- 'ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_profiles/delete_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_validations/revoke_spec.rb'
+ - 'ee/spec/graphql/types/dast_scanner_profile_type_spec.rb'
+ - 'ee/spec/graphql/types/dast_site_profile_type_spec.rb'
- 'ee/spec/helpers/paid_feature_callout_helper_spec.rb'
- 'ee/spec/lib/audit/changes_spec.rb'
- 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb'
@@ -53,12 +61,14 @@ RSpec/ExpectChange:
- 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/cleanup/orphan_job_artifact_files_batch_spec.rb'
- 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/project/tree_restorer_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/repo_restorer_spec.rb'
- 'ee/spec/lib/ee/gitlab/issuable/clone/copy_resource_events_service_spec.rb'
- 'ee/spec/lib/ee/gitlab/scim/deprovision_service_spec.rb'
- 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/distinct_stage_loader_spec.rb'
- 'ee/spec/lib/gitlab/audit/auditor_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/user_spec.rb'
@@ -66,13 +76,17 @@ RSpec/ExpectChange:
- 'ee/spec/lib/gitlab/auth/smartcard/certificate_spec.rb'
- 'ee/spec/lib/gitlab/auth/smartcard/ldap_certificate_spec.rb'
- 'ee/spec/lib/gitlab/background_migration/migrate_requirements_to_work_items_spec.rb'
+ - 'ee/spec/lib/gitlab/cache_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/replicator_spec.rb'
- 'ee/spec/lib/gitlab/mirror_spec.rb'
- 'ee/spec/migrations/20220411173544_cleanup_orphans_approval_project_rules_spec.rb'
- 'ee/spec/models/ci/bridge_spec.rb'
- 'ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb'
- 'ee/spec/models/ci/minutes/project_monthly_usage_spec.rb'
+ - 'ee/spec/models/concerns/geo/eventable_spec.rb'
- 'ee/spec/models/concerns/geo/replicable_model_spec.rb'
- 'ee/spec/models/concerns/geo/verification_state_spec.rb'
+ - 'ee/spec/models/container_registry/event_spec.rb'
- 'ee/spec/models/dast/profile_schedule_spec.rb'
- 'ee/spec/models/dast_site_spec.rb'
- 'ee/spec/models/ee/ci/job_artifact_spec.rb'
@@ -85,15 +99,20 @@ RSpec/ExpectChange:
- 'ee/spec/models/epic_spec.rb'
- 'ee/spec/models/geo/project_registry_spec.rb'
- 'ee/spec/models/geo/secondary_usage_data_spec.rb'
- - 'ee/spec/models/gitlab_subscription_spec.rb'
- 'ee/spec/models/issue_spec.rb'
- 'ee/spec/models/project_import_state_spec.rb'
+ - 'ee/spec/models/project_member_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/repository_spec.rb'
+ - 'ee/spec/models/requirements_management/requirement_spec.rb'
+ - 'ee/spec/models/requirements_management/test_report_spec.rb'
- 'ee/spec/models/status_page/published_incident_spec.rb'
- 'ee/spec/models/vulnerabilities/export_spec.rb'
+ - 'ee/spec/models/vulnerabilities/read_spec.rb'
- 'ee/spec/models/vulnerabilities/statistic_spec.rb'
+ - 'ee/spec/replicators/geo/pipeline_replicator_spec.rb'
- 'ee/spec/requests/api/ci/pipelines_spec.rb'
+ - 'ee/spec/requests/api/deployments_spec.rb'
- 'ee/spec/requests/api/epic_issues_spec.rb'
- 'ee/spec/requests/api/epics_spec.rb'
- 'ee/spec/requests/api/geo_spec.rb'
@@ -101,8 +120,12 @@ RSpec/ExpectChange:
- 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/destroy_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/update_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/boards/epic_boards/destroy_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/boards/epics/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/compliance_management/frameworks/destroy_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/compliance_management/frameworks/update_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast/profiles/delete_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/delete_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/dast_site_profiles/delete_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb'
@@ -110,6 +133,8 @@ RSpec/ExpectChange:
- 'ee/spec/requests/api/graphql/mutations/dast_site_validations/revoke_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/quality_management/test_cases/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/requirements_management/update_requirement_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/work_items/update_spec.rb'
- 'ee/spec/requests/api/group_push_rule_spec.rb'
- 'ee/spec/requests/api/groups_spec.rb'
@@ -121,19 +146,30 @@ RSpec/ExpectChange:
- 'ee/spec/requests/api/projects_spec.rb'
- 'ee/spec/requests/api/releases_spec.rb'
- 'ee/spec/requests/api/repositories_spec.rb'
+ - 'ee/spec/requests/api/status_checks_spec.rb'
- 'ee/spec/requests/api/todos_spec.rb'
- 'ee/spec/requests/api/users_spec.rb'
- 'ee/spec/requests/ee/projects/deploy_tokens_controller_spec.rb'
+ - 'ee/spec/requests/groups/epics/related_epic_links_controller_spec.rb'
- 'ee/spec/requests/groups/protected_environments_controller_spec.rb'
- 'ee/spec/requests/groups_controller_spec.rb'
- 'ee/spec/requests/smartcard_controller_spec.rb'
+ - 'ee/spec/services/analytics/cycle_analytics/stages/list_service_spec.rb'
+ - 'ee/spec/services/analytics/devops_adoption/enabled_namespaces/bulk_find_or_create_service_spec.rb'
+ - 'ee/spec/services/analytics/devops_adoption/enabled_namespaces/find_or_create_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/profiles/create_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/profiles/destroy_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/profiles/update_service_spec.rb'
- 'ee/spec/services/app_sec/dast/scanner_profiles/destroy_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_profile_secret_variables/create_or_update_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_profile_secret_variables/destroy_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_profiles/audit/update_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_profiles/destroy_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_tokens/find_or_create_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_validations/find_or_create_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_validations/revoke_service_spec.rb'
- 'ee/spec/services/app_sec/dast/site_validations/runner_service_spec.rb'
+ - 'ee/spec/services/app_sec/fuzzing/coverage/corpuses/create_service_spec.rb'
- 'ee/spec/services/application_settings/update_service_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/project_rule_destroy_service_spec.rb'
@@ -144,18 +180,27 @@ RSpec/ExpectChange:
- 'ee/spec/services/audit_events/streaming/headers/update_service_spec.rb'
- 'ee/spec/services/audit_events/user_impersonation_group_audit_event_service_spec.rb'
- 'ee/spec/services/auto_merge/merge_train_service_spec.rb'
+ - 'ee/spec/services/boards/epic_user_preferences/update_service_spec.rb'
- 'ee/spec/services/boards/epics/create_service_spec.rb'
- 'ee/spec/services/boards/epics/move_service_spec.rb'
+ - 'ee/spec/services/boards/epics/position_create_service_spec.rb'
- 'ee/spec/services/ci/destroy_pipeline_service_spec.rb'
- 'ee/spec/services/ci/external_pull_requests/process_github_event_service_spec.rb'
+ - 'ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb'
+ - 'ee/spec/services/ci/pipeline_trigger_service_spec.rb'
- 'ee/spec/services/ci/process_build_service_spec.rb'
+ - 'ee/spec/services/ci/retry_job_service_spec.rb'
+ - 'ee/spec/services/ci/runners/stale_group_runners_prune_service_spec.rb'
- 'ee/spec/services/ci/subscribe_bridge_service_spec.rb'
+ - 'ee/spec/services/ci/trigger_downstream_subscription_service_spec.rb'
- 'ee/spec/services/compliance_management/frameworks/create_service_spec.rb'
- 'ee/spec/services/compliance_management/frameworks/destroy_service_spec.rb'
- 'ee/spec/services/compliance_management/frameworks/update_service_spec.rb'
- 'ee/spec/services/deploy_keys/create_service_spec.rb'
- 'ee/spec/services/deployments/approval_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/ci/job_artifacts/destroy_batch_service_spec.rb'
- 'ee/spec/services/ee/gpg_keys/destroy_service_spec.rb'
- 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'
- 'ee/spec/services/ee/groups/deploy_tokens/destroy_service_spec.rb'
@@ -168,6 +213,7 @@ RSpec/ExpectChange:
- 'ee/spec/services/ee/members/destroy_service_spec.rb'
- 'ee/spec/services/ee/members/invite_service_spec.rb'
- 'ee/spec/services/ee/members/update_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/create_pipeline_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/projects/deploy_tokens/create_service_spec.rb'
@@ -179,6 +225,7 @@ RSpec/ExpectChange:
- 'ee/spec/services/ee/users/reject_service_spec.rb'
- 'ee/spec/services/ee/users/update_service_spec.rb'
- 'ee/spec/services/elastic/indexing_control_service_spec.rb'
+ - 'ee/spec/services/elastic/process_initial_bookkeeping_service_spec.rb'
- 'ee/spec/services/emails/create_service_spec.rb'
- 'ee/spec/services/emails/destroy_service_spec.rb'
- 'ee/spec/services/epic_issues/create_service_spec.rb'
@@ -193,16 +240,21 @@ RSpec/ExpectChange:
- 'ee/spec/services/geo/blob_download_service_spec.rb'
- 'ee/spec/services/geo/metrics_update_service_spec.rb'
- 'ee/spec/services/geo/project_housekeeping_service_spec.rb'
+ - 'ee/spec/services/geo/prune_event_log_service_spec.rb'
- 'ee/spec/services/geo/registry_consistency_service_spec.rb'
+ - 'ee/spec/services/geo/repository_registry_removal_service_spec.rb'
- 'ee/spec/services/geo/repository_sync_service_spec.rb'
- 'ee/spec/services/group_saml/group_managed_accounts/transfer_membership_service_spec.rb'
- 'ee/spec/services/group_saml/identity/destroy_service_spec.rb'
- 'ee/spec/services/group_saml/sign_up_service_spec.rb'
+ - 'ee/spec/services/groups/destroy_service_spec.rb'
- 'ee/spec/services/groups/mark_for_deletion_service_spec.rb'
- 'ee/spec/services/groups/restore_service_spec.rb'
- 'ee/spec/services/groups/sync_service_spec.rb'
+ - 'ee/spec/services/incident_management/issuable_resource_links/create_service_spec.rb'
- 'ee/spec/services/incident_management/oncall_rotations/edit_service_spec.rb'
- 'ee/spec/services/incident_management/pending_escalations/create_service_spec.rb'
+ - 'ee/spec/services/iterations/cadences/create_service_spec.rb'
- 'ee/spec/services/iterations/update_service_spec.rb'
- 'ee/spec/services/keys/create_service_spec.rb'
- 'ee/spec/services/lfs/lock_file_service_spec.rb'
@@ -210,56 +262,101 @@ RSpec/ExpectChange:
- 'ee/spec/services/members/activate_service_spec.rb'
- 'ee/spec/services/merge_request_approval_settings/update_service_spec.rb'
- 'ee/spec/services/merge_requests/update_blocks_service_spec.rb'
- - 'ee/spec/services/namespaces/free_user_cap/update_prevent_sharing_outside_hierarchy_service_spec.rb'
+ - 'ee/spec/services/projects/destroy_service_spec.rb'
- 'ee/spec/services/projects/disable_deploy_key_service_spec.rb'
- 'ee/spec/services/projects/enable_deploy_key_service_spec.rb'
+ - 'ee/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb'
+ - 'ee/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb'
- 'ee/spec/services/projects/import_service_spec.rb'
- 'ee/spec/services/projects/mark_for_deletion_service_spec.rb'
- 'ee/spec/services/projects/restore_service_spec.rb'
- 'ee/spec/services/projects/transfer_service_spec.rb'
- 'ee/spec/services/projects/update_service_spec.rb'
- 'ee/spec/services/protected_environments/destroy_service_spec.rb'
+ - 'ee/spec/services/protected_environments/update_service_spec.rb'
- 'ee/spec/services/push_rules/create_or_update_service_spec.rb'
- - 'ee/spec/services/requirements_management/create_requirement_service_spec.rb'
+ - 'ee/spec/services/requirements_management/process_test_reports_service_spec.rb'
- 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
- 'ee/spec/services/resource_access_tokens/revoke_service_spec.rb'
- 'ee/spec/services/resource_events/change_weight_service_spec.rb'
- 'ee/spec/services/security/ingestion/finding_map_spec.rb'
- 'ee/spec/services/security/ingestion/ingest_report_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_finding_evidence_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_finding_identifiers_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_finding_links_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_finding_signatures_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_findings_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_identifiers_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_remediations_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities/mark_resolved_as_detected_spec.rb'
- 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities_spec.rb'
- 'ee/spec/services/security/orchestration/assign_service_spec.rb'
- 'ee/spec/services/security/override_uuids_service_spec.rb'
- 'ee/spec/services/security/security_orchestration_policies/sync_opened_merge_requests_service_spec.rb'
+ - 'ee/spec/services/security/store_findings_metadata_service_spec.rb'
- 'ee/spec/services/security/store_scan_service_spec.rb'
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
+ - 'ee/spec/services/status_page/mark_for_publication_service_spec.rb'
- 'ee/spec/services/system_notes/epics_service_spec.rb'
- 'ee/spec/services/system_notes/merge_train_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
- 'ee/spec/services/todos/destroy/confidential_epic_service_spec.rb'
+ - 'ee/spec/services/upcoming_reconciliations/update_service_spec.rb'
- 'ee/spec/services/users_ops_dashboard_projects/destroy_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/confirm_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/destroy_dismissal_feedback_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/historical_statistics/adjustment_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/historical_statistics/deletion_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/resolve_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/security_finding/create_issue_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/starboard_vulnerability_create_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/statistics/adjustment_service_spec.rb'
- 'ee/spec/services/vulnerabilities/statistics/update_service_spec.rb'
+ - 'ee/spec/services/vulnerability_exports/create_service_spec.rb'
- 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
+ - 'ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb'
+ - 'ee/spec/services/vulnerability_external_issue_links/destroy_service_spec.rb'
- 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
- 'ee/spec/services/vulnerability_feedback/destroy_service_spec.rb'
+ - 'ee/spec/services/vulnerability_issue_links/create_service_spec.rb'
+ - 'ee/spec/services/vulnerability_issue_links/delete_service_spec.rb'
- 'ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb'
- 'ee/spec/support/shared_examples/graphql/mutations/update_health_status_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/models/concerns/blob_replicator_strategy_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/concerns/replicable_model_with_separate_table_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/models/concerns/repository_replicator_strategy_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/geo_verifiable_registry_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/group_saml/saml_provider/base_service_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/update_issuable_health_status_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/services/vulnerabilities/removes_dismissal_feedback_from_associated_findings_shared_example.rb'
- 'ee/spec/tasks/geo/git_rake_spec.rb'
- 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
+ - 'ee/spec/workers/app_sec/dast/scanner_profiles_builds/consistency_worker_spec.rb'
+ - 'ee/spec/workers/app_sec/dast/scans/consistency_worker_spec.rb'
+ - 'ee/spec/workers/app_sec/dast/site_profiles_builds/consistency_worker_spec.rb'
+ - 'ee/spec/workers/ci/runners/stale_group_runners_prune_cron_worker_spec.rb'
+ - 'ee/spec/workers/ci/upstream_projects_subscriptions_cleanup_worker_spec.rb'
- 'ee/spec/workers/ee/projects/inactive_projects_deletion_cron_worker_spec.rb'
- 'ee/spec/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker_spec.rb'
+ - 'ee/spec/workers/geo/create_repository_updated_event_worker_spec.rb'
+ - 'ee/spec/workers/geo/prune_event_log_worker_spec.rb'
- 'ee/spec/workers/geo/verification_state_backfill_service_spec.rb'
+ - 'ee/spec/workers/incident_management/oncall_rotations/persist_shifts_job_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/store_security_reports_worker_spec.rb'
+ - 'ee/spec/workers/vulnerability_exports/export_deletion_worker_spec.rb'
+ - 'spec/controllers/admin/applications_controller_spec.rb'
+ - 'spec/controllers/admin/clusters_controller_spec.rb'
- 'spec/controllers/admin/groups_controller_spec.rb'
- 'spec/controllers/admin/runners_controller_spec.rb'
- 'spec/controllers/admin/spam_logs_controller_spec.rb'
+ - 'spec/controllers/admin/topics_controller_spec.rb'
- 'spec/controllers/admin/users_controller_spec.rb'
+ - 'spec/controllers/groups/clusters_controller_spec.rb'
- 'spec/controllers/groups/runners_controller_spec.rb'
+ - 'spec/controllers/groups/settings/applications_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/import/bitbucket_controller_spec.rb'
- 'spec/controllers/import/gitlab_controller_spec.rb'
@@ -268,38 +365,71 @@ RSpec/ExpectChange:
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- 'spec/controllers/profiles/gpg_keys_controller_spec.rb'
- 'spec/controllers/profiles/keys_controller_spec.rb'
+ - 'spec/controllers/projects/artifacts_controller_spec.rb'
+ - 'spec/controllers/projects/clusters_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
+ - 'spec/controllers/projects/feature_flags_controller_spec.rb'
- 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/controllers/projects/jobs_controller_spec.rb'
- 'spec/controllers/projects/merge_requests/creations_controller_spec.rb'
- 'spec/controllers/projects/merge_requests/drafts_controller_spec.rb'
- 'spec/controllers/projects/merge_requests_controller_spec.rb'
- 'spec/controllers/projects/mirrors_controller_spec.rb'
- 'spec/controllers/projects/notes_controller_spec.rb'
- 'spec/controllers/projects/pages_domains_controller_spec.rb'
+ - 'spec/controllers/projects/pipeline_schedules_controller_spec.rb'
+ - 'spec/controllers/projects/pipelines_controller_spec.rb'
+ - 'spec/controllers/projects/raw_controller_spec.rb'
- 'spec/controllers/projects/runners_controller_spec.rb'
+ - 'spec/controllers/projects/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/projects_controller_spec.rb'
- 'spec/controllers/repositories/lfs_storage_controller_spec.rb'
- 'spec/controllers/sessions_controller_spec.rb'
- 'spec/controllers/snippets/notes_controller_spec.rb'
- 'spec/controllers/uploads_controller_spec.rb'
+ - 'spec/controllers/users/callouts_controller_spec.rb'
- 'spec/features/admin/users/users_spec.rb'
- 'spec/features/file_uploads/attachment_spec.rb'
+ - 'spec/features/file_uploads/ci_artifact_spec.rb'
- 'spec/features/file_uploads/git_lfs_spec.rb'
+ - 'spec/features/file_uploads/graphql_add_design_spec.rb'
- 'spec/features/file_uploads/group_import_spec.rb'
+ - 'spec/features/file_uploads/maven_package_spec.rb'
+ - 'spec/features/file_uploads/nuget_package_spec.rb'
- 'spec/features/file_uploads/project_import_spec.rb'
+ - 'spec/features/file_uploads/rubygem_package_spec.rb'
- 'spec/features/groups/import_export/import_file_spec.rb'
- 'spec/features/groups_spec.rb'
- 'spec/features/invites_spec.rb'
+ - 'spec/features/projects/environments/environment_spec.rb'
+ - 'spec/features/projects/environments/environments_spec.rb'
- 'spec/features/projects/import_export/import_file_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipelines_spec.rb'
+ - 'spec/features/projects/pipelines/pipelines_spec.rb'
- 'spec/features/projects_spec.rb'
- 'spec/features/users/signup_spec.rb'
+ - 'spec/finders/environments/environments_by_deployments_finder_spec.rb'
+ - 'spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb'
+ - 'spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb'
+ - 'spec/graphql/mutations/ci/runner/bulk_delete_spec.rb'
+ - 'spec/graphql/mutations/ci/runner/delete_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/container_repositories/destroy_spec.rb'
+ - 'spec/graphql/mutations/container_repositories/destroy_tags_spec.rb'
+ - 'spec/graphql/mutations/dependency_proxy/image_ttl_group_policy/update_spec.rb'
- 'spec/graphql/mutations/issues/set_severity_spec.rb'
- 'spec/graphql/mutations/releases/delete_spec.rb'
- 'spec/graphql/mutations/timelogs/delete_spec.rb'
+ - 'spec/helpers/markup_helper_spec.rb'
+ - 'spec/helpers/projects_helper_spec.rb'
- 'spec/initializers/active_record_locking_spec.rb'
- 'spec/lib/api/helpers_spec.rb'
+ - 'spec/lib/banzai/filter/repository_link_filter_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/project_pipeline_spec.rb'
- 'spec/lib/declarative_enum_spec.rb'
+ - 'spec/lib/gitaly/server_spec.rb'
- 'spec/lib/gitlab/auth/ldap/access_spec.rb'
- 'spec/lib/gitlab/auth/ldap/user_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb'
@@ -315,16 +445,21 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/background_task_spec.rb'
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
+ - 'spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb'
- 'spec/lib/gitlab/checks/matching_merge_request_spec.rb'
- 'spec/lib/gitlab/ci/ansi2json/line_spec.rb'
- 'spec/lib/gitlab/ci/config/external/context_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/common_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/report_spec.rb'
- 'spec/lib/gitlab/ci/status/factory_spec.rb'
+ - 'spec/lib/gitlab/ci/trace/archive_spec.rb'
- 'spec/lib/gitlab/ci/trace/chunked_io_spec.rb'
+ - 'spec/lib/gitlab/composer/cache_spec.rb'
- 'spec/lib/gitlab/config/entry/validatable_spec.rb'
- 'spec/lib/gitlab/daemon_spec.rb'
- 'spec/lib/gitlab/database/async_indexes/index_creator_spec.rb'
@@ -333,12 +468,20 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb'
+ - 'spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/observers/query_log_spec.rb'
- 'spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb'
- 'spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb'
+ - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/partitioning_spec.rb'
- 'spec/lib/gitlab/database/reindexing/reindex_action_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
+ - 'spec/lib/gitlab/git/commit_spec.rb'
+ - 'spec/lib/gitlab/git/tag_spec.rb'
- 'spec/lib/gitlab/git_access_project_spec.rb'
- 'spec/lib/gitlab/github_import/importer/events/changed_assignee_spec.rb'
- 'spec/lib/gitlab/github_import/importer/events/renamed_spec.rb'
@@ -360,6 +503,7 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/process_supervisor_spec.rb'
- 'spec/lib/gitlab/query_limiting_spec.rb'
- 'spec/lib/gitlab/reference_counter_spec.rb'
+ - 'spec/lib/gitlab/seeders/ci/daily_build_group_report_result_spec.rb'
- 'spec/lib/gitlab/slash_commands/issue_move_spec.rb'
- 'spec/lib/gitlab/word_diff/positions_counter_spec.rb'
- 'spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb'
@@ -371,11 +515,14 @@ RSpec/ExpectChange:
- 'spec/migrations/20220202105733_delete_service_template_records_spec.rb'
- 'spec/migrations/20220222192525_remove_null_releases_spec.rb'
- 'spec/migrations/20220629184402_unset_escalation_policies_for_alert_incidents_spec.rb'
+ - 'spec/migrations/add_new_trail_plans_spec.rb'
+ - 'spec/migrations/add_open_source_plan_spec.rb'
- 'spec/migrations/backfill_cycle_analytics_aggregations_spec.rb'
- 'spec/migrations/bulk_insert_cluster_enabled_grants_spec.rb'
- 'spec/migrations/cleanup_after_add_primary_email_to_emails_if_user_confirmed_spec.rb'
- 'spec/migrations/cleanup_after_fixing_issue_when_admin_changed_primary_email_spec.rb'
- 'spec/migrations/cleanup_after_fixing_regression_with_new_users_emails_spec.rb'
+ - 'spec/migrations/delete_security_findings_without_uuid_spec.rb'
- 'spec/migrations/populate_audit_event_streaming_verification_token_spec.rb'
- 'spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb'
- 'spec/migrations/remove_wiki_notes_spec.rb'
@@ -389,11 +536,14 @@ RSpec/ExpectChange:
- 'spec/models/ci/build_spec.rb'
- 'spec/models/ci/deleted_object_spec.rb'
- 'spec/models/ci/namespace_mirror_spec.rb'
+ - 'spec/models/ci/pipeline_artifact_spec.rb'
- 'spec/models/ci/pipeline_schedule_spec.rb'
+ - 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/ci/processable_spec.rb'
- 'spec/models/ci/project_mirror_spec.rb'
- 'spec/models/ci/ref_spec.rb'
- 'spec/models/ci/runner_spec.rb'
+ - 'spec/models/clusters/applications/runner_spec.rb'
- 'spec/models/clusters/cluster_spec.rb'
- 'spec/models/commit_status_spec.rb'
- 'spec/models/concerns/atomic_internal_id_spec.rb'
@@ -410,6 +560,7 @@ RSpec/ExpectChange:
- 'spec/models/container_repository_spec.rb'
- 'spec/models/customer_relations/issue_contact_spec.rb'
- 'spec/models/design_management/version_spec.rb'
+ - 'spec/models/error_tracking/project_error_tracking_setting_spec.rb'
- 'spec/models/event_spec.rb'
- 'spec/models/experiment_spec.rb'
- 'spec/models/group_spec.rb'
@@ -423,6 +574,7 @@ RSpec/ExpectChange:
- 'spec/models/member_spec.rb'
- 'spec/models/merge_request_spec.rb'
- 'spec/models/packages/package_file_spec.rb'
+ - 'spec/models/packages/package_spec.rb'
- 'spec/models/pages_domain_spec.rb'
- 'spec/models/plan_spec.rb'
- 'spec/models/project_auto_devops_spec.rb'
@@ -437,6 +589,7 @@ RSpec/ExpectChange:
- 'spec/models/route_spec.rb'
- 'spec/models/sent_notification_spec.rb'
- 'spec/models/snippet_spec.rb'
+ - 'spec/models/terraform/state_spec.rb'
- 'spec/models/upload_spec.rb'
- 'spec/models/user_interacted_project_spec.rb'
- 'spec/models/user_spec.rb'
@@ -444,18 +597,33 @@ RSpec/ExpectChange:
- 'spec/models/x509_certificate_spec.rb'
- 'spec/models/x509_issuer_spec.rb'
- 'spec/requests/abuse_reports_controller_spec.rb'
+ - 'spec/requests/api/admin/ci/variables_spec.rb'
+ - 'spec/requests/api/applications_spec.rb'
- 'spec/requests/api/broadcast_messages_spec.rb'
+ - 'spec/requests/api/ci/pipeline_schedules_spec.rb'
- 'spec/requests/api/ci/pipelines_spec.rb'
- 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb'
- 'spec/requests/api/deploy_keys_spec.rb'
- 'spec/requests/api/deploy_tokens_spec.rb'
+ - 'spec/requests/api/error_tracking/collector_spec.rb'
+ - 'spec/requests/api/feature_flags_spec.rb'
+ - 'spec/requests/api/freeze_periods_spec.rb'
+ - 'spec/requests/api/generic_packages_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/add_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb'
- 'spec/requests/api/graphql/mutations/boards/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/clusters/agent_tokens/agent_tokens/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/clusters/agents/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/clusters/agents/delete_spec.rb'
+ - 'spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb'
- 'spec/requests/api/graphql/mutations/labels/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb'
- 'spec/requests/api/graphql/mutations/notes/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb'
- 'spec/requests/api/graphql/mutations/releases/delete_spec.rb'
- 'spec/requests/api/graphql/mutations/snippets/create_spec.rb'
- 'spec/requests/api/graphql/mutations/snippets/destroy_spec.rb'
@@ -463,21 +631,35 @@ RSpec/ExpectChange:
- 'spec/requests/api/group_import_spec.rb'
- 'spec/requests/api/groups_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/notes_spec.rb'
+ - 'spec/requests/api/npm_project_packages_spec.rb'
- 'spec/requests/api/project_snippets_spec.rb'
- 'spec/requests/api/projects_spec.rb'
+ - 'spec/requests/api/pypi_packages_spec.rb'
+ - 'spec/requests/api/release/links_spec.rb'
- 'spec/requests/api/releases_spec.rb'
+ - 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/api/snippets_spec.rb'
+ - 'spec/requests/api/terraform/modules/v1/packages_spec.rb'
+ - 'spec/requests/api/terraform/state_spec.rb'
+ - 'spec/requests/api/terraform/state_version_spec.rb'
- 'spec/requests/api/users_spec.rb'
- 'spec/requests/groups/settings/access_tokens_controller_spec.rb'
- 'spec/requests/import/gitlab_groups_controller_spec.rb'
+ - 'spec/requests/oauth_tokens_spec.rb'
- 'spec/requests/product_analytics/collector_app_spec.rb'
- 'spec/requests/projects/issue_links_controller_spec.rb'
+ - 'spec/requests/projects/merge_requests_discussions_spec.rb'
- 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
+ - 'spec/requests/users/group_callouts_spec.rb'
+ - 'spec/requests/users/namespace_callouts_spec.rb'
+ - 'spec/requests/users/project_callouts_spec.rb'
- 'spec/services/alert_management/alerts/todo/create_service_spec.rb'
- 'spec/services/alert_management/alerts/update_service_spec.rb'
- 'spec/services/application_settings/update_service_spec.rb'
+ - 'spec/services/applications/create_service_spec.rb'
- 'spec/services/authorized_project_update/project_recalculate_per_user_service_spec.rb'
- 'spec/services/authorized_project_update/project_recalculate_service_spec.rb'
- 'spec/services/award_emojis/add_service_spec.rb'
@@ -486,18 +668,39 @@ RSpec/ExpectChange:
- 'spec/services/award_emojis/toggle_service_spec.rb'
- 'spec/services/bulk_imports/create_service_spec.rb'
- 'spec/services/bulk_imports/relation_export_service_spec.rb'
+ - 'spec/services/ci/build_report_result_service_spec.rb'
- 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
+ - 'spec/services/ci/daily_build_group_report_result_service_spec.rb'
+ - 'spec/services/ci/delete_objects_service_spec.rb'
- 'spec/services/ci/destroy_pipeline_service_spec.rb'
+ - 'spec/services/ci/ensure_stage_service_spec.rb'
+ - 'spec/services/ci/job_artifacts/create_service_spec.rb'
- 'spec/services/ci/job_artifacts/delete_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/job_artifacts/destroy_batch_service_spec.rb'
- 'spec/services/ci/job_artifacts/update_unknown_locked_status_service_spec.rb'
+ - 'spec/services/ci/job_token_scope/add_project_service_spec.rb'
+ - 'spec/services/ci/job_token_scope/remove_project_service_spec.rb'
+ - 'spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb'
+ - 'spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb'
+ - 'spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb'
+ - 'spec/services/ci/pipeline_trigger_service_spec.rb'
- 'spec/services/ci/play_build_service_spec.rb'
- 'spec/services/ci/process_build_service_spec.rb'
- 'spec/services/ci/retry_job_service_spec.rb'
- 'spec/services/ci/retry_pipeline_service_spec.rb'
- 'spec/services/ci/run_scheduled_build_service_spec.rb'
+ - 'spec/services/ci/runners/bulk_delete_runners_service_spec.rb'
+ - 'spec/services/ci/runners/unregister_runner_service_spec.rb'
- 'spec/services/ci/update_build_queue_service_spec.rb'
- 'spec/services/ci/update_build_state_service_spec.rb'
+ - 'spec/services/ci/update_instance_variables_service_spec.rb'
+ - 'spec/services/clusters/agent_tokens/create_service_spec.rb'
+ - 'spec/services/clusters/agents/create_service_spec.rb'
+ - 'spec/services/clusters/agents/delete_service_spec.rb'
+ - 'spec/services/clusters/create_service_spec.rb'
- 'spec/services/clusters/destroy_service_spec.rb'
- 'spec/services/container_expiration_policies/cleanup_service_spec.rb'
- 'spec/services/deployments/create_for_build_service_spec.rb'
@@ -509,17 +712,21 @@ RSpec/ExpectChange:
- 'spec/services/draft_notes/destroy_service_spec.rb'
- 'spec/services/draft_notes/publish_service_spec.rb'
- 'spec/services/emails/create_service_spec.rb'
+ - 'spec/services/error_tracking/collect_error_service_spec.rb'
- 'spec/services/error_tracking/list_projects_service_spec.rb'
- 'spec/services/event_create_service_spec.rb'
- 'spec/services/feature_flags/create_service_spec.rb'
- 'spec/services/feature_flags/destroy_service_spec.rb'
- 'spec/services/feature_flags/update_service_spec.rb'
+ - 'spec/services/git/branch_push_service_spec.rb'
- 'spec/services/git/process_ref_changes_service_spec.rb'
+ - 'spec/services/git/tag_hooks_service_spec.rb'
- 'spec/services/groups/create_service_spec.rb'
- 'spec/services/groups/import_export/import_service_spec.rb'
- 'spec/services/groups/transfer_service_spec.rb'
- 'spec/services/groups/update_service_spec.rb'
- 'spec/services/groups/update_statistics_service_spec.rb'
+ - 'spec/services/incident_management/timeline_events/create_service_spec.rb'
- 'spec/services/incident_management/timeline_events/update_service_spec.rb'
- 'spec/services/issuable/common_system_notes_service_spec.rb'
- 'spec/services/issues/close_service_spec.rb'
@@ -533,6 +740,7 @@ RSpec/ExpectChange:
- 'spec/services/lfs/lock_file_service_spec.rb'
- 'spec/services/merge_requests/add_spent_time_service_spec.rb'
- 'spec/services/merge_requests/close_service_spec.rb'
+ - 'spec/services/merge_requests/create_pipeline_service_spec.rb'
- 'spec/services/merge_requests/create_service_spec.rb'
- 'spec/services/merge_requests/ff_merge_service_spec.rb'
- 'spec/services/merge_requests/merge_service_spec.rb'
@@ -544,24 +752,48 @@ RSpec/ExpectChange:
- 'spec/services/merge_requests/update_service_spec.rb'
- 'spec/services/milestones/destroy_service_spec.rb'
- 'spec/services/namespace_settings/update_service_spec.rb'
+ - 'spec/services/namespaces/in_product_marketing_emails_service_spec.rb'
- 'spec/services/notes/create_service_spec.rb'
- 'spec/services/notes/destroy_service_spec.rb'
- 'spec/services/notes/quick_actions_service_spec.rb'
- 'spec/services/packages/cleanup/update_policy_service_spec.rb'
+ - 'spec/services/packages/composer/create_package_service_spec.rb'
+ - 'spec/services/packages/create_dependency_service_spec.rb'
+ - 'spec/services/packages/create_event_service_spec.rb'
+ - 'spec/services/packages/create_temporary_package_service_spec.rb'
+ - 'spec/services/packages/debian/find_or_create_package_service_spec.rb'
+ - 'spec/services/packages/debian/process_changes_service_spec.rb'
+ - 'spec/services/packages/generic/create_package_file_service_spec.rb'
+ - 'spec/services/packages/go/create_package_service_spec.rb'
- 'spec/services/packages/helm/process_file_service_spec.rb'
- 'spec/services/packages/mark_package_for_destruction_service_spec.rb'
+ - 'spec/services/packages/maven/find_or_create_package_service_spec.rb'
+ - 'spec/services/packages/npm/create_package_service_spec.rb'
+ - 'spec/services/packages/npm/create_tag_service_spec.rb'
+ - 'spec/services/packages/nuget/create_dependency_service_spec.rb'
+ - 'spec/services/packages/nuget/sync_metadatum_service_spec.rb'
+ - 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
+ - 'spec/services/packages/pypi/create_package_service_spec.rb'
+ - 'spec/services/packages/remove_tag_service_spec.rb'
+ - 'spec/services/packages/rubygems/create_dependencies_service_spec.rb'
+ - 'spec/services/packages/rubygems/metadata_extraction_service_spec.rb'
+ - 'spec/services/packages/terraform_module/create_package_service_spec.rb'
- 'spec/services/packages/update_package_file_service_spec.rb'
+ - 'spec/services/packages/update_tags_service_spec.rb'
- 'spec/services/pages/delete_service_spec.rb'
- 'spec/services/pages/destroy_deployments_service_spec.rb'
- 'spec/services/pages_domains/retry_acme_order_service_spec.rb'
- 'spec/services/personal_access_tokens/last_used_service_spec.rb'
- 'spec/services/projects/auto_devops/disable_service_spec.rb'
+ - 'spec/services/projects/destroy_service_spec.rb'
- 'spec/services/projects/fetch_statistics_increment_service_spec.rb'
- 'spec/services/projects/hashed_storage/migration_service_spec.rb'
- 'spec/services/projects/hashed_storage/rollback_repository_service_spec.rb'
- 'spec/services/projects/hashed_storage/rollback_service_spec.rb'
+ - 'spec/services/projects/in_product_marketing_campaign_emails_service_spec.rb'
- 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
- 'spec/services/projects/record_target_platforms_service_spec.rb'
+ - 'spec/services/projects/transfer_service_spec.rb'
- 'spec/services/projects/update_pages_service_spec.rb'
- 'spec/services/projects/update_service_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb'
@@ -594,14 +826,17 @@ RSpec/ExpectChange:
- 'spec/services/users/update_service_spec.rb'
- 'spec/services/verify_pages_domain_service_spec.rb'
- 'spec/services/work_items/parent_links/create_service_spec.rb'
+ - 'spec/support/services/clusters/create_service_shared.rb'
- 'spec/support/services/deploy_token_shared_examples.rb'
- 'spec/support/services/issuable_import_csv_service_shared_examples.rb'
- 'spec/support/shared_contexts/email_shared_context.rb'
+ - 'spec/support/shared_examples/controllers/clusters_controller_shared_examples.rb'
- 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
- 'spec/support/shared_examples/controllers/variables_shared_examples.rb'
- 'spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb'
- 'spec/support/shared_examples/graphql/notes_creation_shared_examples.rb'
- 'spec/support/shared_examples/incident_management/issuable_escalation_statuses/build_examples.rb'
+ - 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- 'spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb'
- 'spec/support/shared_examples/models/commit_signature_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb'
@@ -610,17 +845,29 @@ RSpec/ExpectChange:
- 'spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/limitable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb'
+ - 'spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb'
- 'spec/support/shared_examples/models/member_shared_examples.rb'
- 'spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb'
- 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
- 'spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb'
- 'spec/support/shared_examples/services/common_system_notes_shared_examples.rb'
- 'spec/support/shared_examples/services/container_expiration_policy_shared_examples.rb'
- 'spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/dependency_proxy_ttl_policies_shared_examples.rb'
- 'spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb'
- 'spec/support/shared_examples/services/merge_request_shared_examples.rb'
+ - 'spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb'
+ - 'spec/support/shared_examples/services/packages_shared_examples.rb'
- 'spec/support/shared_examples/services/rate_limited_service_shared_examples.rb'
- 'spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb'
- 'spec/support/shared_examples/services/updating_mentions_shared_examples.rb'
@@ -633,14 +880,26 @@ RSpec/ExpectChange:
- 'spec/tooling/rspec_flaky/listener_spec.rb'
- 'spec/uploaders/file_uploader_spec.rb'
- 'spec/uploaders/records_uploads_spec.rb'
+ - 'spec/workers/analytics/usage_trends/counter_job_worker_spec.rb'
- 'spec/workers/destroy_pages_deployments_worker_spec.rb'
- 'spec/workers/environments/auto_delete_cron_worker_spec.rb'
- 'spec/workers/gitlab/phabricator_import/base_worker_spec.rb'
- 'spec/workers/gitlab_service_ping_worker_spec.rb'
- 'spec/workers/group_import_worker_spec.rb'
- 'spec/workers/incident_management/process_alert_worker_v2_spec.rb'
+ - 'spec/workers/namespaces/root_statistics_worker_spec.rb'
+ - 'spec/workers/namespaces/schedule_aggregation_worker_spec.rb'
- 'spec/workers/new_issue_worker_spec.rb'
- 'spec/workers/new_merge_request_worker_spec.rb'
+ - 'spec/workers/packages/cleanup_package_file_worker_spec.rb'
+ - 'spec/workers/packages/composer/cache_cleanup_worker_spec.rb'
+ - 'spec/workers/packages/composer/cache_update_worker_spec.rb'
+ - 'spec/workers/packages/debian/process_changes_worker_spec.rb'
+ - 'spec/workers/packages/go/sync_packages_worker_spec.rb'
+ - 'spec/workers/packages/helm/extraction_worker_spec.rb'
+ - 'spec/workers/packages/maven/metadata/sync_worker_spec.rb'
+ - 'spec/workers/packages/nuget/extraction_worker_spec.rb'
+ - 'spec/workers/packages/rubygems/extraction_worker_spec.rb'
- 'spec/workers/pages_domain_removal_cron_worker_spec.rb'
- 'spec/workers/projects/post_creation_worker_spec.rb'
- 'spec/workers/prune_old_events_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/expect_in_hook.yml b/.rubocop_todo/rspec/expect_in_hook.yml
index 1551f2dc637..70b4105fc89 100644
--- a/.rubocop_todo/rspec/expect_in_hook.yml
+++ b/.rubocop_todo/rspec/expect_in_hook.yml
@@ -7,7 +7,6 @@ RSpec/ExpectInHook:
- 'ee/spec/controllers/projects/boards_controller_spec.rb'
- 'ee/spec/controllers/projects/settings/slacks_controller_spec.rb'
- 'ee/spec/controllers/subscriptions_controller_spec.rb'
- - 'ee/spec/controllers/trials_controller_spec.rb'
- 'ee/spec/elastic/migrate/20220118150500_delete_orphaned_commits_spec.rb'
- 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
- 'ee/spec/features/billings/billing_plans_spec.rb'
@@ -19,7 +18,6 @@ RSpec/ExpectInHook:
- 'ee/spec/features/registrations/trial_during_signup_flow_spec.rb'
- 'ee/spec/features/signup_spec.rb'
- 'ee/spec/features/trial_registrations/company_information_spec.rb'
- - 'ee/spec/features/trials/capture_lead_spec.rb'
- 'ee/spec/features/trials/select_namespace_spec.rb'
- 'ee/spec/finders/license_template_finder_spec.rb'
- 'ee/spec/finders/projects/integrations/jira/issues_finder_spec.rb'
diff --git a/.rubocop_todo/rspec/factory_bot/avoid_create.yml b/.rubocop_todo/rspec/factory_bot/avoid_create.yml
new file mode 100644
index 00000000000..2da0040f8ed
--- /dev/null
+++ b/.rubocop_todo/rspec/factory_bot/avoid_create.yml
@@ -0,0 +1,211 @@
+---
+RSpec/FactoryBot/AvoidCreate:
+ Details: grace period
+ Exclude:
+ - 'ee/spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb'
+ - 'ee/spec/serializers/analytics/cycle_analytics/value_stream_errors_serializer_spec.rb'
+ - 'ee/spec/serializers/audit_event_entity_spec.rb'
+ - 'ee/spec/serializers/audit_event_serializer_spec.rb'
+ - 'ee/spec/serializers/blocking_merge_request_entity_spec.rb'
+ - 'ee/spec/serializers/clusters/deployment_entity_spec.rb'
+ - 'ee/spec/serializers/clusters/environment_entity_spec.rb'
+ - 'ee/spec/serializers/clusters/environment_serializer_spec.rb'
+ - 'ee/spec/serializers/dashboard_environment_entity_spec.rb'
+ - 'ee/spec/serializers/dashboard_environments_project_entity_spec.rb'
+ - 'ee/spec/serializers/dashboard_environments_serializer_spec.rb'
+ - 'ee/spec/serializers/dashboard_operations_project_entity_spec.rb'
+ - 'ee/spec/serializers/dependency_entity_spec.rb'
+ - 'ee/spec/serializers/dependency_list_serializer_spec.rb'
+ - 'ee/spec/serializers/ee/blob_entity_spec.rb'
+ - 'ee/spec/serializers/ee/build_details_entity_spec.rb'
+ - 'ee/spec/serializers/ee/ci/job_entity_spec.rb'
+ - 'ee/spec/serializers/ee/deployment_entity_spec.rb'
+ - 'ee/spec/serializers/ee/environment_serializer_spec.rb'
+ - 'ee/spec/serializers/ee/group_child_entity_spec.rb'
+ - 'ee/spec/serializers/ee/issue_board_entity_spec.rb'
+ - 'ee/spec/serializers/ee/issue_entity_spec.rb'
+ - 'ee/spec/serializers/ee/issue_sidebar_basic_entity_spec.rb'
+ - 'ee/spec/serializers/ee/issue_sidebar_extras_entity_spec.rb'
+ - 'ee/spec/serializers/ee/merge_request_poll_cached_widget_entity_spec.rb'
+ - 'ee/spec/serializers/ee/note_entity_spec.rb'
+ - 'ee/spec/serializers/ee/user_serializer_spec.rb'
+ - 'ee/spec/serializers/environment_entity_spec.rb'
+ - 'ee/spec/serializers/epic_entity_spec.rb'
+ - 'ee/spec/serializers/epic_note_entity_spec.rb'
+ - 'ee/spec/serializers/epics/related_epic_entity_spec.rb'
+ - 'ee/spec/serializers/fork_namespace_entity_spec.rb'
+ - 'ee/spec/serializers/geo_project_registry_entity_spec.rb'
+ - 'ee/spec/serializers/incident_management/escalation_policy_entity_spec.rb'
+ - 'ee/spec/serializers/incident_management/oncall_schedule_entity_spec.rb'
+ - 'ee/spec/serializers/integrations/field_entity_spec.rb'
+ - 'ee/spec/serializers/integrations/jira_serializers/issue_detail_entity_spec.rb'
+ - 'ee/spec/serializers/integrations/jira_serializers/issue_entity_spec.rb'
+ - 'ee/spec/serializers/integrations/jira_serializers/issue_serializer_spec.rb'
+ - 'ee/spec/serializers/integrations/zentao_serializers/issue_entity_spec.rb'
+ - 'ee/spec/serializers/issuable_sidebar_extras_entity_spec.rb'
+ - 'ee/spec/serializers/issue_serializer_spec.rb'
+ - 'ee/spec/serializers/issues/linked_issue_feature_flag_entity_spec.rb'
+ - 'ee/spec/serializers/license_compliance/collapsed_comparer_entity_spec.rb'
+ - 'ee/spec/serializers/license_compliance/comparer_entity_spec.rb'
+ - 'ee/spec/serializers/licenses_list_entity_spec.rb'
+ - 'ee/spec/serializers/licenses_list_serializer_spec.rb'
+ - 'ee/spec/serializers/linked_feature_flag_issue_entity_spec.rb'
+ - 'ee/spec/serializers/member_entity_spec.rb'
+ - 'ee/spec/serializers/member_user_entity_spec.rb'
+ - 'ee/spec/serializers/merge_request_poll_widget_entity_spec.rb'
+ - 'ee/spec/serializers/merge_request_sidebar_basic_entity_spec.rb'
+ - 'ee/spec/serializers/merge_request_widget_entity_spec.rb'
+ - 'ee/spec/serializers/pipeline_serializer_spec.rb'
+ - 'ee/spec/serializers/productivity_analytics_merge_request_entity_spec.rb'
+ - 'ee/spec/serializers/project_mirror_entity_spec.rb'
+ - 'ee/spec/serializers/scim_oauth_access_token_entity_spec.rb'
+ - 'ee/spec/serializers/security/vulnerability_report_data_entity_spec.rb'
+ - 'ee/spec/serializers/status_page/incident_comment_entity_spec.rb'
+ - 'ee/spec/serializers/status_page/incident_entity_spec.rb'
+ - 'ee/spec/serializers/status_page/incident_serializer_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/feedback_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/finding_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/finding_reports_comparer_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/finding_serializer_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/identifier_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/request_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/response_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerabilities/scanner_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerability_entity_spec.rb'
+ - 'ee/spec/serializers/vulnerability_note_entity_spec.rb'
+ - 'spec/serializers/access_token_entity_base_spec.rb'
+ - 'spec/serializers/analytics_build_entity_spec.rb'
+ - 'spec/serializers/analytics_build_serializer_spec.rb'
+ - 'spec/serializers/analytics_issue_entity_spec.rb'
+ - 'spec/serializers/analytics_issue_serializer_spec.rb'
+ - 'spec/serializers/analytics_merge_request_serializer_spec.rb'
+ - 'spec/serializers/analytics_summary_serializer_spec.rb'
+ - 'spec/serializers/base_discussion_entity_spec.rb'
+ - 'spec/serializers/blob_entity_spec.rb'
+ - 'spec/serializers/build_action_entity_spec.rb'
+ - 'spec/serializers/build_artifact_entity_spec.rb'
+ - 'spec/serializers/build_details_entity_spec.rb'
+ - 'spec/serializers/ci/dag_job_entity_spec.rb'
+ - 'spec/serializers/ci/dag_job_group_entity_spec.rb'
+ - 'spec/serializers/ci/dag_pipeline_entity_spec.rb'
+ - 'spec/serializers/ci/dag_pipeline_serializer_spec.rb'
+ - 'spec/serializers/ci/dag_stage_entity_spec.rb'
+ - 'spec/serializers/ci/downloadable_artifact_entity_spec.rb'
+ - 'spec/serializers/ci/downloadable_artifact_serializer_spec.rb'
+ - 'spec/serializers/ci/group_variable_entity_spec.rb'
+ - 'spec/serializers/ci/job_entity_spec.rb'
+ - 'spec/serializers/ci/job_serializer_spec.rb'
+ - 'spec/serializers/ci/lint/result_serializer_spec.rb'
+ - 'spec/serializers/ci/pipeline_entity_spec.rb'
+ - 'spec/serializers/ci/trigger_entity_spec.rb'
+ - 'spec/serializers/ci/variable_entity_spec.rb'
+ - 'spec/serializers/cluster_application_entity_spec.rb'
+ - 'spec/serializers/cluster_entity_spec.rb'
+ - 'spec/serializers/cluster_serializer_spec.rb'
+ - 'spec/serializers/clusters/kubernetes_error_entity_spec.rb'
+ - 'spec/serializers/commit_entity_spec.rb'
+ - 'spec/serializers/container_repositories_serializer_spec.rb'
+ - 'spec/serializers/container_repository_entity_spec.rb'
+ - 'spec/serializers/container_tag_entity_spec.rb'
+ - 'spec/serializers/context_commits_diff_entity_spec.rb'
+ - 'spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb'
+ - 'spec/serializers/deploy_keys/deploy_key_entity_spec.rb'
+ - 'spec/serializers/deployment_cluster_entity_spec.rb'
+ - 'spec/serializers/deployment_entity_spec.rb'
+ - 'spec/serializers/deployment_serializer_spec.rb'
+ - 'spec/serializers/diff_file_base_entity_spec.rb'
+ - 'spec/serializers/diff_file_entity_spec.rb'
+ - 'spec/serializers/diff_file_metadata_entity_spec.rb'
+ - 'spec/serializers/diff_viewer_entity_spec.rb'
+ - 'spec/serializers/diffs_entity_spec.rb'
+ - 'spec/serializers/diffs_metadata_entity_spec.rb'
+ - 'spec/serializers/discussion_diff_file_entity_spec.rb'
+ - 'spec/serializers/discussion_entity_spec.rb'
+ - 'spec/serializers/environment_entity_spec.rb'
+ - 'spec/serializers/environment_serializer_spec.rb'
+ - 'spec/serializers/environment_status_entity_spec.rb'
+ - 'spec/serializers/evidences/evidence_entity_spec.rb'
+ - 'spec/serializers/evidences/release_entity_spec.rb'
+ - 'spec/serializers/feature_flag_entity_spec.rb'
+ - 'spec/serializers/feature_flag_serializer_spec.rb'
+ - 'spec/serializers/feature_flag_summary_entity_spec.rb'
+ - 'spec/serializers/feature_flag_summary_serializer_spec.rb'
+ - 'spec/serializers/feature_flags_client_serializer_spec.rb'
+ - 'spec/serializers/fork_namespace_entity_spec.rb'
+ - 'spec/serializers/group_access_token_entity_spec.rb'
+ - 'spec/serializers/group_access_token_serializer_spec.rb'
+ - 'spec/serializers/group_child_entity_spec.rb'
+ - 'spec/serializers/group_child_serializer_spec.rb'
+ - 'spec/serializers/group_deploy_key_entity_spec.rb'
+ - 'spec/serializers/group_link/group_group_link_entity_spec.rb'
+ - 'spec/serializers/group_link/project_group_link_entity_spec.rb'
+ - 'spec/serializers/group_link/project_group_link_serializer_spec.rb'
+ - 'spec/serializers/impersonation_access_token_entity_spec.rb'
+ - 'spec/serializers/impersonation_access_token_serializer_spec.rb'
+ - 'spec/serializers/import/manifest_provider_repo_entity_spec.rb'
+ - 'spec/serializers/integrations/event_entity_spec.rb'
+ - 'spec/serializers/integrations/field_entity_spec.rb'
+ - 'spec/serializers/integrations/harbor_serializers/artifact_entity_spec.rb'
+ - 'spec/serializers/integrations/harbor_serializers/repository_entity_spec.rb'
+ - 'spec/serializers/integrations/harbor_serializers/tag_entity_spec.rb'
+ - 'spec/serializers/integrations/project_entity_spec.rb'
+ - 'spec/serializers/issuable_sidebar_extras_entity_spec.rb'
+ - 'spec/serializers/issue_board_entity_spec.rb'
+ - 'spec/serializers/issue_entity_spec.rb'
+ - 'spec/serializers/issue_serializer_spec.rb'
+ - 'spec/serializers/issue_sidebar_basic_entity_spec.rb'
+ - 'spec/serializers/jira_connect/app_data_serializer_spec.rb'
+ - 'spec/serializers/jira_connect/group_entity_spec.rb'
+ - 'spec/serializers/jira_connect/subscription_entity_spec.rb'
+ - 'spec/serializers/job_artifact_report_entity_spec.rb'
+ - 'spec/serializers/label_serializer_spec.rb'
+ - 'spec/serializers/lfs_file_lock_entity_spec.rb'
+ - 'spec/serializers/linked_project_issue_entity_spec.rb'
+ - 'spec/serializers/member_entity_spec.rb'
+ - 'spec/serializers/member_serializer_spec.rb'
+ - 'spec/serializers/member_user_entity_spec.rb'
+ - 'spec/serializers/merge_request_current_user_entity_spec.rb'
+ - 'spec/serializers/merge_request_diff_entity_spec.rb'
+ - 'spec/serializers/merge_request_for_pipeline_entity_spec.rb'
+ - 'spec/serializers/merge_request_metrics_helper_spec.rb'
+ - 'spec/serializers/merge_request_poll_cached_widget_entity_spec.rb'
+ - 'spec/serializers/merge_request_poll_widget_entity_spec.rb'
+ - 'spec/serializers/merge_request_serializer_spec.rb'
+ - 'spec/serializers/merge_request_sidebar_basic_entity_spec.rb'
+ - 'spec/serializers/merge_request_sidebar_extras_entity_spec.rb'
+ - 'spec/serializers/merge_request_user_entity_spec.rb'
+ - 'spec/serializers/merge_request_widget_commit_entity_spec.rb'
+ - 'spec/serializers/merge_request_widget_entity_spec.rb'
+ - 'spec/serializers/merge_requests/pipeline_entity_spec.rb'
+ - 'spec/serializers/namespace_basic_entity_spec.rb'
+ - 'spec/serializers/note_entity_spec.rb'
+ - 'spec/serializers/paginated_diff_entity_spec.rb'
+ - 'spec/serializers/personal_access_token_entity_spec.rb'
+ - 'spec/serializers/personal_access_token_serializer_spec.rb'
+ - 'spec/serializers/pipeline_details_entity_spec.rb'
+ - 'spec/serializers/pipeline_serializer_spec.rb'
+ - 'spec/serializers/project_access_token_entity_spec.rb'
+ - 'spec/serializers/project_access_token_serializer_spec.rb'
+ - 'spec/serializers/project_import_entity_spec.rb'
+ - 'spec/serializers/project_mirror_entity_spec.rb'
+ - 'spec/serializers/project_note_entity_spec.rb'
+ - 'spec/serializers/project_serializer_spec.rb'
+ - 'spec/serializers/prometheus_alert_entity_spec.rb'
+ - 'spec/serializers/release_serializer_spec.rb'
+ - 'spec/serializers/remote_mirror_entity_spec.rb'
+ - 'spec/serializers/review_app_setup_entity_spec.rb'
+ - 'spec/serializers/runner_entity_spec.rb'
+ - 'spec/serializers/serverless/domain_entity_spec.rb'
+ - 'spec/serializers/stage_entity_spec.rb'
+ - 'spec/serializers/stage_serializer_spec.rb'
+ - 'spec/serializers/suggestion_entity_spec.rb'
+ - 'spec/serializers/test_case_entity_spec.rb'
+ - 'spec/serializers/test_report_entity_spec.rb'
+ - 'spec/serializers/test_report_summary_entity_spec.rb'
+ - 'spec/serializers/test_suite_entity_spec.rb'
+ - 'spec/serializers/test_suite_summary_entity_spec.rb'
+ - 'spec/serializers/trigger_variable_entity_spec.rb'
+ - 'spec/serializers/user_entity_spec.rb'
+ - 'spec/serializers/user_serializer_spec.rb'
+ - 'spec/serializers/web_ide_terminal_entity_spec.rb'
+ - 'spec/serializers/web_ide_terminal_serializer_spec.rb'
diff --git a/.rubocop_todo/rspec/file_path.yml b/.rubocop_todo/rspec/file_path.yml
new file mode 100644
index 00000000000..3cf0e969c34
--- /dev/null
+++ b/.rubocop_todo/rspec/file_path.yml
@@ -0,0 +1,67 @@
+---
+RSpec/FilePath:
+ Details: grace period
+ Exclude:
+ - 'ee/spec/frontend/fixtures/analytics/charts.rb'
+ - 'ee/spec/frontend/fixtures/analytics/devops_reports/devops_adoption/enabled_namespaces.rb'
+ - 'ee/spec/frontend/fixtures/analytics/metrics.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_code_stage.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_issue_stage.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_plan_stage.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_review_stage.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_staging_stage.rb'
+ - 'ee/spec/frontend/fixtures/analytics/value_streams_test_stage.rb'
+ - 'ee/spec/frontend/fixtures/dora/metrics.rb'
+ - 'ee/spec/models/merge_request/blocking_spec.rb'
+ - 'ee/spec/requests/api/ci/runner/jobs_put_spec.rb'
+ - 'ee/spec/requests/api/ci/runner/jobs_trace_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/compliance_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/cross_needs_artifacts_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/needs_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/runnable_builds_spec.rb'
+ - 'spec/benchmarks/banzai_benchmark.rb'
+ - 'spec/docs_screenshots/container_registry_docs.rb'
+ - 'spec/docs_screenshots/wiki_docs.rb'
+ - 'spec/lib/error_tracking/sentry_client/event_spec.rb'
+ - 'spec/lib/gitlab/import_export/import_export_equivalence_spec.rb'
+ - 'spec/lib/gitlab/import_export/import_export_spec.rb'
+ - 'spec/lib/gitlab/mail_room/mail_room_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_reset_spec.rb'
+ - 'spec/requests/api/ci/runner/runners_verify_post_spec.rb'
+ - 'spec/requests/api/issues/get_group_issues_spec.rb'
+ - 'spec/requests/api/issues/get_project_issues_spec.rb'
+ - 'spec/requests/api/issues/issues_spec.rb'
+ - 'spec/requests/api/issues/post_projects_issues_spec.rb'
+ - 'spec/requests/api/issues/put_projects_issues_spec.rb'
+ - 'spec/requests/api/pages/pages_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/artifacts_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/cache_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/custom_config_content_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/dry_run_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/environment_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/include_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/logger_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/merge_requests_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/needs_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/parallel_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/parameter_content_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/partitioning_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/pre_post_stages_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/rate_limit_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/rules_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/tags_spec.rb'
diff --git a/.rubocop_todo/rspec/instance_variable.yml b/.rubocop_todo/rspec/instance_variable.yml
index df62a8b0f87..2cc146a0625 100644
--- a/.rubocop_todo/rspec/instance_variable.yml
+++ b/.rubocop_todo/rspec/instance_variable.yml
@@ -171,7 +171,6 @@ RSpec/InstanceVariable:
- spec/requests/openid_connect_spec.rb
- spec/requests/projects/issues/discussions_spec.rb
- spec/rubocop/cop/migration/update_column_in_batches_spec.rb
- - spec/serializers/pipeline_serializer_spec.rb
- spec/services/ci/create_pipeline_service/logger_spec.rb
- spec/services/ci/process_sync_events_service_spec.rb
- spec/services/labels/update_service_spec.rb
diff --git a/.rubocop_todo/rspec/let_before_examples.yml b/.rubocop_todo/rspec/let_before_examples.yml
new file mode 100644
index 00000000000..f84df4bdb5f
--- /dev/null
+++ b/.rubocop_todo/rspec/let_before_examples.yml
@@ -0,0 +1,17 @@
+---
+# Cop supports --auto-correct.
+RSpec/LetBeforeExamples:
+ Exclude:
+ - 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
+ - 'ee/spec/models/resource_weight_event_spec.rb'
+ - 'ee/spec/models/vulnerabilities/feedback_spec.rb'
+ - 'ee/spec/requests/api/internal/kubernetes_spec.rb'
+ - 'ee/spec/requests/api/scim_spec.rb'
+ - 'spec/graphql/types/ci/detailed_status_type_spec.rb'
+ - 'spec/graphql/types/merge_request_type_spec.rb'
+ - 'spec/graphql/types/snippets/blob_type_spec.rb'
+ - 'spec/models/ci/job_token/project_scope_link_spec.rb'
+ - 'spec/models/ci/runner_version_spec.rb'
+ - 'spec/models/group_deploy_key_spec.rb'
+ - 'spec/models/snippet_repository_spec.rb'
+ - 'spec/requests/api/issue_links_spec.rb'
diff --git a/.rubocop_todo/rspec/multiple_memoized_helpers.yml b/.rubocop_todo/rspec/multiple_memoized_helpers.yml
index 8330d768794..218ec3bb478 100644
--- a/.rubocop_todo/rspec/multiple_memoized_helpers.yml
+++ b/.rubocop_todo/rspec/multiple_memoized_helpers.yml
@@ -1,9 +1,39 @@
---
RSpec/MultipleMemoizedHelpers:
+ Details: grace period
Exclude:
- - spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
- - spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
- - spec/requests/api/ci/runner/jobs_artifacts_spec.rb
- - ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb
- - ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb
- - ee/spec/services/ee/boards/issues/move_service_spec.rb
+ - 'ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb'
+ - 'ee/spec/finders/epics_finder_spec.rb'
+ - 'ee/spec/finders/incident_management/oncall_users_finder_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb'
+ - 'ee/spec/lib/gitlab/graphql/loaders/bulk_epic_aggregate_loader_spec.rb'
+ - 'ee/spec/requests/api/analytics/project_deployment_frequency_spec.rb'
+ - 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
+ - 'ee/spec/services/ee/boards/issues/move_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb'
+ - 'spec/features/boards/boards_spec.rb'
+ - 'spec/finders/ci/runners_finder_spec.rb'
+ - 'spec/finders/labels_finder_spec.rb'
+ - 'spec/finders/user_recent_events_finder_spec.rb'
+ - 'spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb'
+ - 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
+ - 'spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb'
+ - 'spec/models/event_spec.rb'
+ - 'spec/models/milestone_spec.rb'
+ - 'spec/models/packages/package_file_spec.rb'
+ - 'spec/requests/api/ci/runner/jobs_artifacts_spec.rb'
+ - 'spec/requests/api/issues/get_group_issues_spec.rb'
+ - 'spec/requests/api/issues/get_project_issues_spec.rb'
+ - 'spec/requests/api/issues/issues_spec.rb'
+ - 'spec/requests/api/issues/put_projects_issues_spec.rb'
+ - 'spec/requests/api/maven_packages_spec.rb'
+ - 'spec/services/boards/issues/list_service_spec.rb'
+ - 'spec/services/labels/promote_service_spec.rb'
+ - 'spec/services/merge_requests/push_options_handler_service_spec.rb'
+ - 'spec/services/packages/cleanup/execute_policy_service_spec.rb'
+ - 'spec/services/todo_service_spec.rb'
+ - 'spec/services/todos/allowed_target_filter_service_spec.rb'
+ - 'spec/services/todos/destroy/entity_leave_service_spec.rb'
+ - 'spec/support/shared_contexts/policies/project_policy_shared_context.rb'
+ - 'spec/support/shared_contexts/requests/api/debian_repository_shared_context.rb'
diff --git a/.rubocop_todo/rspec/overwriting_setup.yml b/.rubocop_todo/rspec/overwriting_setup.yml
new file mode 100644
index 00000000000..630f08eb72f
--- /dev/null
+++ b/.rubocop_todo/rspec/overwriting_setup.yml
@@ -0,0 +1,17 @@
+---
+RSpec/OverwritingSetup:
+ Exclude:
+ - 'ee/spec/features/groups/analytics/ci_cd_analytics_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
+ - 'ee/spec/models/ee/iteration_spec.rb'
+ - 'ee/spec/requests/api/namespaces_spec.rb'
+ - 'ee/spec/services/epics/descendant_count_service_spec.rb'
+ - 'spec/finders/packages/helm/packages_finder_spec.rb'
+ - 'spec/finders/packages/npm/package_finder_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
+ - 'spec/models/packages/package_file_spec.rb'
+ - 'spec/models/todo_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/policies/ci/build_policy_spec.rb'
+ - 'spec/services/packages/nuget/search_service_spec.rb'
+ - 'spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb'
diff --git a/.rubocop_todo/rspec/predicate_matcher.yml b/.rubocop_todo/rspec/predicate_matcher.yml
index f3cfe93191d..5847080dcde 100644
--- a/.rubocop_todo/rspec/predicate_matcher.yml
+++ b/.rubocop_todo/rspec/predicate_matcher.yml
@@ -99,8 +99,6 @@ RSpec/PredicateMatcher:
- 'ee/spec/services/jira/requests/issues/list_service_spec.rb'
- 'ee/spec/services/milestones/promote_service_spec.rb'
- 'ee/spec/services/protected_environments/create_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/findings/create_from_security_finding_service_spec.rb'
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
- 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
- 'ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scans_shared_examples.rb'
@@ -414,7 +412,6 @@ RSpec/PredicateMatcher:
- 'spec/requests/api/users_spec.rb'
- 'spec/requests/git_http_spec.rb'
- 'spec/requests/lfs_http_spec.rb'
- - 'spec/serializers/pipeline_serializer_spec.rb'
- 'spec/services/branches/create_service_spec.rb'
- 'spec/services/ci/create_pipeline_service/needs_spec.rb'
- 'spec/services/ci/create_pipeline_service/rate_limit_spec.rb'
@@ -499,7 +496,6 @@ RSpec/PredicateMatcher:
- 'spec/support/shared_examples/requests/api/hooks_shared_examples.rb'
- 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
- 'spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- 'spec/uploaders/object_storage_spec.rb'
- 'spec/validators/any_field_validator_spec.rb'
diff --git a/.rubocop_todo/rspec/scattered_let.yml b/.rubocop_todo/rspec/scattered_let.yml
index 93f373b0a9e..61f1a09589f 100644
--- a/.rubocop_todo/rspec/scattered_let.yml
+++ b/.rubocop_todo/rspec/scattered_let.yml
@@ -1,123 +1,144 @@
---
# Cop supports --auto-correct.
RSpec/ScatteredLet:
+ Details: grace period
Exclude:
+ - 'ee/spec/features/boards/user_visits_board_spec.rb'
- 'ee/spec/features/groups/group_roadmap_spec.rb'
- - 'ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb'
+ - 'ee/spec/features/milestones/user_views_milestone_spec.rb'
+ - 'ee/spec/finders/analytics/devops_adoption/enabled_namespaces_finder_spec.rb'
+ - 'ee/spec/finders/ee/alert_management/http_integrations_finder_spec.rb'
+ - 'ee/spec/finders/issues_finder_spec.rb'
- 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb'
- - 'ee/spec/finders/security/vulnerability_reads_finder_spec.rb'
- - 'ee/spec/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
+ - 'ee/spec/frontend/fixtures/runner.rb'
+ - 'ee/spec/graphql/ee/types/clusters/agent_type_spec.rb'
- 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
- - 'ee/spec/graphql/mutations/dast_site_profiles/create_spec.rb'
- 'ee/spec/graphql/mutations/merge_requests/accept_spec.rb'
- 'ee/spec/graphql/mutations/releases/update_spec.rb'
+ - 'ee/spec/graphql/resolvers/analytics/devops_adoption/enabled_namespaces_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/clusters/agents_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/security_orchestration/scan_execution_policy_resolver_spec.rb'
+ - 'ee/spec/graphql/types/asset_type_spec.rb'
- 'ee/spec/graphql/types/boards/board_epic_type_spec.rb'
- 'ee/spec/graphql/types/instance_security_dashboard_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_evidence_source_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_evidence_supporting_message_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_evidence_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_request_response_header_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_request_type_spec.rb'
+ - 'ee/spec/graphql/types/vulnerability_response_type_spec.rb'
+ - 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- 'ee/spec/helpers/ee/subscribable_banner_helper_spec.rb'
- - 'ee/spec/helpers/trial_status_widget_helper_spec.rb'
+ - 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/api/helpers/members_helpers_spec.rb'
- 'ee/spec/lib/ee/audit/compliance_framework_changes_auditor_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/config_spec.rb'
- - 'ee/spec/lib/ee/gitlab/email/handler/service_desk_handler_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
- 'ee/spec/lib/gitlab/background_migration/migrate_requirements_to_work_items_spec.rb'
- 'ee/spec/lib/gitlab/ci/parsers/security/dast_spec.rb'
- - 'ee/spec/lib/gitlab/ci/parsers/security/formatters/dependency_list_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb'
+ - 'ee/spec/lib/gitlab/code_owners/loader_spec.rb'
- 'ee/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/security_orchestration_policies/lazy_dast_profile_aggregate_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/insights/reducers/count_per_label_reducer_spec.rb'
- 'ee/spec/lib/gitlab/insights/reducers/label_count_per_period_reducer_spec.rb'
+ - 'ee/spec/lib/gitlab/usage/metrics/instrumentations/approval_project_rules_with_user_metric_spec.rb'
- 'ee/spec/lib/gitlab/usage_data_metrics_spec.rb'
- - 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
- 'ee/spec/models/approval_wrapped_any_approver_rule_spec.rb'
- - 'ee/spec/models/approvals/scan_finding_wrapped_rule_set_spec.rb'
- - 'ee/spec/models/ci/minutes/notification_spec.rb'
- - 'ee/spec/models/ci/pipeline_spec.rb'
+ - 'ee/spec/models/dast_site_validation_spec.rb'
- 'ee/spec/models/ee/ci/build_dependencies_spec.rb'
- - 'ee/spec/models/label_note_spec.rb'
- - 'ee/spec/models/sca/license_compliance_spec.rb'
- - 'ee/spec/policies/merge_request_policy_spec.rb'
+ - 'ee/spec/models/ee/iteration_spec.rb'
+ - 'ee/spec/models/ee/user_spec.rb'
+ - 'ee/spec/models/epic_spec.rb'
+ - 'ee/spec/models/preloaders/environments/protected_environment_preloader_spec.rb'
+ - 'ee/spec/models/vulnerabilities/historical_statistic_spec.rb'
+ - 'ee/spec/requests/api/analytics/project_deployment_frequency_spec.rb'
- 'ee/spec/requests/api/graphql/compliance_management/merge_requests/compliance_violations_spec.rb'
- 'ee/spec/requests/api/graphql/group/ci_cd_settings_spec.rb'
- 'ee/spec/requests/api/graphql/group/epic/notes_spec.rb'
- - 'ee/spec/requests/api/graphql/group_query_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
+ - 'ee/spec/requests/api/graphql/instance_security_dashboard_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/update_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/issues/promote_to_epic_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/security_policy/commit_scan_execution_policy_spec.rb'
- - 'ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/projects/set_compliance_framework_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/security/finding/create_issue_spec.rb'
- 'ee/spec/requests/api/graphql/project/dast_profile_schedule_spec.rb'
+ - 'ee/spec/requests/api/graphql/project/environments_spec.rb'
- 'ee/spec/requests/api/graphql/project/pipeline/dast_profile_spec.rb'
+ - 'ee/spec/requests/api/graphql/project/pipeline/security_report_finding_spec.rb'
+ - 'ee/spec/requests/api/graphql/project/pipeline/security_report_summary_spec.rb'
- 'ee/spec/requests/api/graphql/project/pipelines/dast_profile_spec.rb'
- - 'ee/spec/requests/api/internal/base_spec.rb'
- - 'ee/spec/requests/api/projects_spec.rb'
+ - 'ee/spec/requests/api/graphql/project/requirements_management/requirements_spec.rb'
+ - 'ee/spec/requests/api/graphql/project/requirements_management/test_reports_spec.rb'
+ - 'ee/spec/requests/api/graphql/vulnerabilities/details_spec.rb'
+ - 'ee/spec/requests/api/group_boards_spec.rb'
+ - 'ee/spec/requests/api/project_push_rule_spec.rb'
- 'ee/spec/requests/api/settings_spec.rb'
- 'ee/spec/requests/api/vulnerability_findings_spec.rb'
- - 'ee/spec/requests/git_http_geo_spec.rb'
- - 'ee/spec/serializers/license_compliance/collapsed_comparer_entity_spec.rb'
- - 'ee/spec/serializers/status_page/incident_serializer_spec.rb'
+ - 'ee/spec/services/analytics/devops_adoption/snapshots/calculate_and_save_service_spec.rb'
- 'ee/spec/services/app_sec/dast/scan_configs/fetch_service_spec.rb'
- - 'ee/spec/services/app_sec/dast/scanner_profiles/update_service_spec.rb'
- 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
- - 'ee/spec/services/arkose/user_verification_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
- - 'ee/spec/services/audit_events/protected_branch_audit_event_service_spec.rb'
+ - 'ee/spec/services/boards/epics/move_service_spec.rb'
+ - 'ee/spec/services/compliance_management/frameworks/create_service_spec.rb'
+ - 'ee/spec/services/compliance_management/frameworks/update_service_spec.rb'
+ - 'ee/spec/services/concerns/epics/related_epic_links/usage_data_helper_spec.rb'
- 'ee/spec/services/ee/issue_links/create_service_spec.rb'
+ - 'ee/spec/services/ee/issues/create_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/base_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/update_assignees_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/update_reviewers_service_spec.rb'
- 'ee/spec/services/epic_issues/create_service_spec.rb'
- 'ee/spec/services/epics/issue_promote_service_spec.rb'
- - 'ee/spec/services/gitlab_subscriptions/activate_service_spec.rb'
+ - 'ee/spec/services/geo/metrics_update_service_spec.rb'
- 'ee/spec/services/group_saml/saml_provider/create_service_spec.rb'
- 'ee/spec/services/group_saml/saml_provider/update_service_spec.rb'
- 'ee/spec/services/groups/memberships/export_service_spec.rb'
- 'ee/spec/services/incident_management/escalation_policies/create_service_spec.rb'
- 'ee/spec/services/incident_management/oncall_rotations/remove_participant_service_spec.rb'
- - 'ee/spec/services/merge_request_approval_settings/update_service_spec.rb'
- - 'ee/spec/services/merge_trains/refresh_service_spec.rb'
- - 'ee/spec/services/projects/destroy_service_spec.rb'
- - 'ee/spec/services/projects/prometheus/alerts/notify_service_spec.rb'
- - 'ee/spec/services/quality_management/test_cases/create_service_spec.rb'
- - 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- - 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
- - 'ee/spec/services/search/group_service_spec.rb'
- - 'ee/spec/services/search/project_service_spec.rb'
- - 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb'
- - 'ee/spec/services/todo_service_spec.rb'
- - 'ee/spec/views/shared/_mirror_update_button.html.haml_spec.rb'
+ - 'ee/spec/services/members/activate_service_spec.rb'
+ - 'ee/spec/services/personal_access_tokens/groups/update_lifetime_service_spec.rb'
+ - 'ee/spec/services/sbom/ingestion/occurrence_map_spec.rb'
+ - 'ee/spec/services/security/report_summary_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/security_finding/create_issue_service_spec.rb'
- 'ee/spec/views/subscriptions/groups/edit.html.haml_spec.rb'
- - 'ee/spec/workers/compliance_management/merge_requests/compliance_violations_worker_spec.rb'
- 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
- - 'spec/controllers/projects/artifacts_controller_spec.rb'
+ - 'spec/controllers/concerns/metrics_dashboard_spec.rb'
+ - 'spec/controllers/import/bitbucket_server_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
- 'spec/controllers/projects/environments_controller_spec.rb'
- 'spec/controllers/projects/issues_controller_spec.rb'
- - 'spec/controllers/projects/releases/evidences_controller_spec.rb'
- - 'spec/controllers/projects/releases_controller_spec.rb'
- - 'spec/finders/ci/daily_build_group_report_results_finder_spec.rb'
+ - 'spec/controllers/projects/jobs_controller_spec.rb'
+ - 'spec/features/boards/user_visits_board_spec.rb'
+ - 'spec/features/groups/dependency_proxy_for_containers_spec.rb'
+ - 'spec/features/issues/user_filters_issues_spec.rb'
- 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
- - 'spec/finders/concerns/finder_with_group_hierarchy_spec.rb'
- - 'spec/finders/events_finder_spec.rb'
- 'spec/finders/group_projects_finder_spec.rb'
+ - 'spec/finders/groups/user_groups_finder_spec.rb'
- 'spec/finders/license_template_finder_spec.rb'
- - 'spec/frontend/fixtures/pipelines.rb'
- - 'spec/graphql/resolvers/commit_pipelines_resolver_spec.rb'
+ - 'spec/finders/projects/groups_finder_spec.rb'
+ - 'spec/frontend/fixtures/jobs.rb'
+ - 'spec/graphql/resolvers/clusters/agents_resolver_spec.rb'
+ - 'spec/graphql/resolvers/concerns/looks_ahead_spec.rb'
+ - 'spec/graphql/resolvers/concerns/resolves_project_spec.rb'
- 'spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb'
- - 'spec/graphql/resolvers/design_management/versions_resolver_spec.rb'
+ - 'spec/graphql/resolvers/group_milestones_resolver_spec.rb'
+ - 'spec/graphql/resolvers/users/groups_resolver_spec.rb'
+ - 'spec/graphql/types/base_object_spec.rb'
- 'spec/graphql/types/ci/job_token_scope_type_spec.rb'
+ - 'spec/graphql/types/environment_type_spec.rb'
+ - 'spec/graphql/types/merge_request_type_spec.rb'
+ - 'spec/graphql/types/project_type_spec.rb'
+ - 'spec/graphql/types/terraform/state_version_type_spec.rb'
+ - 'spec/graphql/types/user_type_spec.rb'
+ - 'spec/helpers/blob_helper_spec.rb'
- 'spec/helpers/merge_requests_helper_spec.rb'
+ - 'spec/lib/atlassian/jira_connect/jwt/asymmetric_spec.rb'
- 'spec/lib/banzai/filter/references/project_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/user_reference_filter_spec.rb'
- - 'spec/lib/banzai/filter/upload_link_filter_spec.rb'
- 'spec/lib/banzai/reference_parser/alert_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_range_parser_spec.rb'
+ - 'spec/lib/banzai/reference_parser/design_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/label_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/merge_request_parser_spec.rb'
@@ -125,32 +146,29 @@ RSpec/ScatteredLet:
- 'spec/lib/banzai/reference_parser/project_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/snippet_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/user_parser_spec.rb'
+ - 'spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb'
- 'spec/lib/bulk_imports/pipeline/runner_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb'
- 'spec/lib/gitlab/asciidoc/include_processor_spec.rb'
- 'spec/lib/gitlab/auth/ldap/person_spec.rb'
- 'spec/lib/gitlab/auth/saml/auth_hash_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb'
- - 'spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb'
- 'spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_inactive_public_projects_spec.rb'
- 'spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb'
- 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
- 'spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb'
- 'spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb'
- - 'spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb'
- 'spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
+ - 'spec/lib/gitlab/checks/matching_merge_request_spec.rb'
- 'spec/lib/gitlab/ci/config/external/file/artifact_spec.rb'
+ - 'spec/lib/gitlab/ci/config_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb'
- - 'spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb'
- 'spec/lib/gitlab/ci/status/stage/factory_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder/group_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder/project_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- - 'spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
- 'spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb'
- 'spec/lib/gitlab/database/partitioning/partition_manager_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/database/postgresql_adapter/empty_query_ping_spec.rb'
- 'spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb'
- 'spec/lib/gitlab/diff/file_collection/merge_request_diff_batch_spec.rb'
@@ -160,41 +178,43 @@ RSpec/ScatteredLet:
- 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_diff_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
- - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb'
- - 'spec/lib/gitlab/error_tracking_spec.rb'
- 'spec/lib/gitlab/git/blame_spec.rb'
- 'spec/lib/gitlab/git/diff_collection_spec.rb'
- 'spec/lib/gitlab/git_access_spec.rb'
- 'spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/parallel_scheduling_spec.rb'
- 'spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/project/export_task_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb'
- 'spec/lib/gitlab/jira_import/issue_serializer_spec.rb'
- 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/external_http_spec.rb'
- 'spec/lib/gitlab/middleware/memory_report_spec.rb'
- - 'spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/page_spec.rb'
- 'spec/lib/gitlab/pagination/offset_pagination_spec.rb'
- 'spec/lib/gitlab/patch/database_config_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb'
+ - 'spec/lib/gitlab/redis/multi_store_spec.rb'
+ - 'spec/lib/gitlab/relative_positioning/item_context_spec.rb'
+ - 'spec/lib/gitlab/relative_positioning/mover_spec.rb'
- 'spec/lib/gitlab/serializer/pagination_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/extra_done_log_metadata_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb'
- - 'spec/lib/gitlab/spamcheck/client_spec.rb'
- 'spec/lib/gitlab/template/finders/global_template_finder_spec.rb'
- 'spec/lib/gitlab/tree_summary_spec.rb'
+ - 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb'
- 'spec/lib/gitlab/usage_data_metrics_spec.rb'
+ - 'spec/lib/gitlab/usage_data_spec.rb'
- 'spec/lib/gitlab/utils/measuring_spec.rb'
- 'spec/lib/gitlab/zentao/client_spec.rb'
- 'spec/lib/peek/views/external_http_spec.rb'
- 'spec/mailers/emails/in_product_marketing_spec.rb'
- - 'spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
+ - 'spec/mailers/notify_spec.rb'
+ - 'spec/mailers/previews_spec.rb'
- 'spec/migrations/20220329175119_remove_leftover_ci_job_artifact_deletions_spec.rb'
- - 'spec/models/application_record_spec.rb'
+ - 'spec/models/ci/bridge_spec.rb'
- 'spec/models/ci/build_dependencies_spec.rb'
- 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/concerns/issuable_spec.rb'
@@ -203,68 +223,61 @@ RSpec/ScatteredLet:
- 'spec/models/deploy_keys_project_spec.rb'
- 'spec/models/design_management/design_at_version_spec.rb'
- 'spec/models/diff_note_spec.rb'
- - 'spec/models/environment_spec.rb'
- 'spec/models/integration_spec.rb'
- - 'spec/models/merge_request_diff_spec.rb'
- 'spec/models/merge_request_spec.rb'
- - 'spec/models/milestone_spec.rb'
- 'spec/models/push_event_spec.rb'
+ - 'spec/models/snippet_repository_spec.rb'
- 'spec/models/ssh_host_key_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/models/users/credit_card_validation_spec.rb'
- 'spec/models/wiki_page_spec.rb'
- - 'spec/policies/ci/build_policy_spec.rb'
- - 'spec/policies/design_management/design_policy_spec.rb'
- 'spec/policies/group_member_policy_spec.rb'
- 'spec/requests/admin/background_migrations_controller_spec.rb'
+ - 'spec/requests/api/ci/jobs_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/graphql/ci/groups_spec.rb'
- - 'spec/requests/api/graphql/ci/pipelines_spec.rb'
+ - 'spec/requests/api/graphql/ci/runners_spec.rb'
+ - 'spec/requests/api/graphql/group/work_item_types_spec.rb'
+ - 'spec/requests/api/graphql/milestone_spec.rb'
- 'spec/requests/api/graphql/mutations/boards/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb'
- 'spec/requests/api/graphql/namespace/projects_spec.rb'
+ - 'spec/requests/api/graphql/project/deployment_spec.rb'
+ - 'spec/requests/api/graphql/project/environments_spec.rb'
- 'spec/requests/api/graphql/project/issue/design_collection/version_spec.rb'
- 'spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb'
- 'spec/requests/api/graphql/project/issue_spec.rb'
+ - 'spec/requests/api/graphql/project/jira_projects_spec.rb'
+ - 'spec/requests/api/graphql/project/merge_request/diff_notes_spec.rb'
- 'spec/requests/api/graphql/project/milestones_spec.rb'
- - 'spec/requests/api/graphql/project/pipeline_spec.rb'
- - 'spec/requests/api/graphql/project/release_spec.rb'
- - 'spec/requests/api/graphql/user/starred_projects_query_spec.rb'
+ - 'spec/requests/api/graphql/project/work_item_types_spec.rb'
+ - 'spec/requests/api/graphql/todo_query_spec.rb'
+ - 'spec/requests/api/group_boards_spec.rb'
- 'spec/requests/api/issues/get_group_issues_spec.rb'
- - 'spec/requests/api/issues/get_project_issues_spec.rb'
- - 'spec/requests/api/issues/post_projects_issues_spec.rb'
- - 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/notes_spec.rb'
- 'spec/requests/api/project_clusters_spec.rb'
- - 'spec/requests/api/project_export_spec.rb'
- - 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/jira_routing_spec.rb'
- - 'spec/requests/projects/releases_controller_spec.rb'
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/scripts/pipeline_test_report_builder_spec.rb'
- 'spec/serializers/build_details_entity_spec.rb'
- 'spec/serializers/ci/job_entity_spec.rb'
- 'spec/serializers/merge_requests/pipeline_entity_spec.rb'
- - 'spec/services/ci/change_variable_service_spec.rb'
- - 'spec/services/ci/change_variables_service_spec.rb'
- 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/include_spec.rb'
- 'spec/services/ci/create_pipeline_service/logger_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/rules_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
- 'spec/services/ci/destroy_pipeline_service_spec.rb'
- - 'spec/services/ci/find_exposed_artifacts_service_spec.rb'
- - 'spec/services/ci/pipeline_bridge_status_service_spec.rb'
- - 'spec/services/commits/cherry_pick_service_spec.rb'
- 'spec/services/design_management/delete_designs_service_spec.rb'
- 'spec/services/design_management/save_designs_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
- 'spec/services/events/destroy_service_spec.rb'
- 'spec/services/git/base_hooks_service_spec.rb'
- - 'spec/services/groups/group_links/update_service_spec.rb'
- - 'spec/services/jira_import/cloud_users_mapper_service_spec.rb'
- - 'spec/services/jira_import/server_users_mapper_service_spec.rb'
- - 'spec/services/lfs/push_service_spec.rb'
+ - 'spec/services/issues/create_service_spec.rb'
+ - 'spec/services/merge_requests/mergeability/logger_spec.rb'
+ - 'spec/services/merge_requests/update_assignees_service_spec.rb'
+ - 'spec/services/merge_requests/update_reviewers_service_spec.rb'
- 'spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb'
- 'spec/services/metrics/dashboard/dynamic_embed_service_spec.rb'
- 'spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb'
@@ -272,19 +285,18 @@ RSpec/ScatteredLet:
- 'spec/services/notification_service_spec.rb'
- 'spec/services/packages/composer/create_package_service_spec.rb'
- 'spec/services/packages/conan/create_package_file_service_spec.rb'
+ - 'spec/services/packages/debian/create_distribution_service_spec.rb'
- 'spec/services/packages/debian/create_package_file_service_spec.rb'
- 'spec/services/packages/debian/generate_distribution_key_service_spec.rb'
- 'spec/services/packages/debian/update_distribution_service_spec.rb'
- 'spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb'
- 'spec/services/snippets/create_service_spec.rb'
- - 'spec/services/spam/spam_verdict_service_spec.rb'
- 'spec/services/suggestions/create_service_spec.rb'
- 'spec/services/system_notes/design_management_service_spec.rb'
- 'spec/services/system_notes/merge_requests_service_spec.rb'
+ - 'spec/services/system_notes/time_tracking_service_spec.rb'
- 'spec/services/todo_service_spec.rb'
- - 'spec/services/web_hook_service_spec.rb'
- - 'spec/services/work_items/update_service_spec.rb'
- 'spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb'
- 'spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- - 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
+ - 'spec/workers/environments/auto_stop_worker_spec.rb'
- 'spec/workers/packages/debian/generate_distribution_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/variable_definition.yml b/.rubocop_todo/rspec/variable_definition.yml
new file mode 100644
index 00000000000..797fa763ba1
--- /dev/null
+++ b/.rubocop_todo/rspec/variable_definition.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+RSpec/VariableDefinition:
+ Exclude:
+ - 'spec/lib/gitlab/usage_data_spec.rb'
+ - 'spec/presenters/packages/npm/package_presenter_spec.rb'
diff --git a/.rubocop_todo/rspec/variable_name.yml b/.rubocop_todo/rspec/variable_name.yml
new file mode 100644
index 00000000000..8858fbd9eb7
--- /dev/null
+++ b/.rubocop_todo/rspec/variable_name.yml
@@ -0,0 +1,4 @@
+---
+RSpec/VariableName:
+ Exclude:
+ - 'spec/models/user_spec.rb'
diff --git a/.rubocop_todo/rspec/verified_doubles.yml b/.rubocop_todo/rspec/verified_doubles.yml
index a225dbf21ae..c9f405a8283 100644
--- a/.rubocop_todo/rspec/verified_doubles.yml
+++ b/.rubocop_todo/rspec/verified_doubles.yml
@@ -67,7 +67,6 @@ RSpec/VerifiedDoubles:
- ee/spec/lib/gitlab/authority_analyzer_spec.rb
- ee/spec/lib/gitlab/cache_spec.rb
- ee/spec/lib/gitlab/ci/pipeline/chain/limit/activity_spec.rb
- - ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb
- ee/spec/lib/gitlab/ci/pipeline/chain/limit/size_spec.rb
- ee/spec/lib/gitlab/code_owners/groups_loader_spec.rb
- ee/spec/lib/gitlab/code_owners/users_loader_spec.rb
diff --git a/.rubocop_todo/style/accessor_grouping.yml b/.rubocop_todo/style/accessor_grouping.yml
index 821e3398301..a2ba217dbcc 100644
--- a/.rubocop_todo/style/accessor_grouping.yml
+++ b/.rubocop_todo/style/accessor_grouping.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/AccessorGrouping:
- # Offense count: 254
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/finders/template_finder.rb'
- 'app/models/commit.rb'
@@ -23,7 +21,6 @@ Style/AccessorGrouping:
- 'app/models/project.rb'
- 'app/services/deployments/update_environment_service.rb'
- 'app/services/issues/clone_service.rb'
- - 'app/services/merge_requests/bulk_remove_attention_requested_service.rb'
- 'app/services/note_summary.rb'
- 'app/services/notification_recipients/builder/default.rb'
- 'app/services/task_list_toggle_service.rb'
@@ -38,6 +35,7 @@ Style/AccessorGrouping:
- 'ee/lib/gitlab/ci/reports/security/locations/dast.rb'
- 'ee/lib/gitlab/ci/reports/security/locations/dependency_scanning.rb'
- 'lib/feature/definition.rb'
+ - 'lib/gitlab/audit/type/definition.rb'
- 'lib/gitlab/bitbucket_server_import/importer.rb'
- 'lib/gitlab/ci/config/external/context.rb'
- 'lib/gitlab/ci/reports/security/finding.rb'
@@ -65,7 +63,6 @@ Style/AccessorGrouping:
- 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
- 'lib/gitlab/suggestions/file_suggestion.rb'
- 'lib/gitlab/tracking/event_definition.rb'
- - 'lib/gitlab/tree_summary.rb'
- 'lib/gitlab/usage/metric_definition.rb'
- 'lib/gitlab/usage/metrics/instrumentations/base_metric.rb'
- 'lib/gitlab/usage/service_ping/instrumented_payload.rb'
diff --git a/.rubocop_todo/style/case_like_if.yml b/.rubocop_todo/style/case_like_if.yml
index 119ca3d800f..61f2e6bc238 100644
--- a/.rubocop_todo/style/case_like_if.yml
+++ b/.rubocop_todo/style/case_like_if.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/CaseLikeIf:
- # Offense count: 60
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/controllers/concerns/issuable_actions.rb'
- 'app/controllers/groups/dependency_proxy/application_controller.rb'
@@ -13,6 +11,7 @@ Style/CaseLikeIf:
- 'app/helpers/broadcast_messages_helper.rb'
- 'app/helpers/issues_helper.rb'
- 'app/helpers/routing/pseudonymization_helper.rb'
+ - 'app/helpers/todos_helper.rb'
- 'app/models/integrations/jira.rb'
- 'app/models/members/member_task.rb'
- 'app/models/namespace.rb'
@@ -21,8 +20,11 @@ Style/CaseLikeIf:
- 'app/services/google_cloud/generate_pipeline_service.rb'
- 'app/services/issuable/bulk_update_service.rb'
- 'app/services/todo_service.rb'
+ - 'app/services/user_project_access_changed_service.rb'
- 'ee/app/controllers/concerns/credentials_inventory_actions.rb'
- 'ee/app/finders/ee/notes_finder.rb'
+ - 'ee/app/finders/security/scan_execution_policies_finder.rb'
+ - 'ee/app/finders/security/training_providers/secure_code_warrior_url_finder.rb'
- 'ee/app/helpers/ee/branches_helper.rb'
- 'ee/app/services/epics/tree_reorder_service.rb'
- 'ee/app/services/merge_request_approval_settings/update_service.rb'
@@ -43,18 +45,18 @@ Style/CaseLikeIf:
- 'lib/gitlab/utils/strong_memoize.rb'
- 'qa/qa/git/repository.rb'
- 'qa/qa/scenario/bootable.rb'
- - 'rubocop/cop/gitlab/keys_first_and_values_first.rb'
- 'spec/features/boards/user_adds_lists_to_board_spec.rb'
- 'spec/lib/gitlab/auth/auth_finders_spec.rb'
- 'spec/lib/gitlab/database/load_balancing_spec.rb'
- 'spec/lib/omni_auth/strategies/jwt_spec.rb'
- 'spec/models/concerns/sha_attribute_spec.rb'
- 'spec/models/preloaders/labels_preloader_spec.rb'
+ - 'spec/requests/api/personal_access_tokens_spec.rb'
- 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/api/terraform/modules/v1/packages_spec.rb'
+ - 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb'
- 'spec/services/resource_events/change_state_service_spec.rb'
- 'spec/support/helpers/filter_spec_helper.rb'
- - 'spec/support/matchers/abort_matcher.rb'
- 'spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/notes_shared_examples.rb'
- 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
diff --git a/.rubocop_todo/style/class_and_module_children.yml b/.rubocop_todo/style/class_and_module_children.yml
index 2674902c7ee..bff827ba5d3 100644
--- a/.rubocop_todo/style/class_and_module_children.yml
+++ b/.rubocop_todo/style/class_and_module_children.yml
@@ -521,6 +521,7 @@ Style/ClassAndModuleChildren:
- 'ee/db/fixtures/development/21_dast_profiles.rb'
- 'ee/db/fixtures/development/30_customizable_cycle_analytics.rb'
- 'ee/db/fixtures/development/32_compliance_report_violations.rb'
+ - 'ee/db/fixtures/development/35_merge_request_predictions.rb'
- 'ee/db/fixtures/development/90_productivity_analytics.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/base_query_builder.rb'
diff --git a/.rubocop_todo/style/conditional_assignment.yml b/.rubocop_todo/style/conditional_assignment.yml
new file mode 100644
index 00000000000..c9bbaaeb175
--- /dev/null
+++ b/.rubocop_todo/style/conditional_assignment.yml
@@ -0,0 +1,5 @@
+---
+# Cop supports --auto-correct.
+Style/ConditionalAssignment:
+ Exclude:
+ - 'app/helpers/icons_helper.rb'
diff --git a/.rubocop_todo/style/each_for_simple_loop.yml b/.rubocop_todo/style/each_for_simple_loop.yml
new file mode 100644
index 00000000000..5d495f890d2
--- /dev/null
+++ b/.rubocop_todo/style/each_for_simple_loop.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+Style/EachForSimpleLoop:
+ Exclude:
+ - 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
+ - 'spec/services/members/invitation_reminder_email_service_spec.rb'
diff --git a/.rubocop_todo/style/empty_method.yml b/.rubocop_todo/style/empty_method.yml
index 3e6a1efec70..7fbec98ead5 100644
--- a/.rubocop_todo/style/empty_method.yml
+++ b/.rubocop_todo/style/empty_method.yml
@@ -1,16 +1,12 @@
---
# Cop supports --auto-correct.
Style/EmptyMethod:
- # Offense count: 240
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/controllers/admin/application_settings/appearances_controller.rb'
- 'app/controllers/admin/applications_controller.rb'
- 'app/controllers/admin/broadcast_messages_controller.rb'
- 'app/controllers/admin/deploy_keys_controller.rb'
- - 'app/controllers/admin/hook_logs_controller.rb'
- - 'app/controllers/admin/hooks_controller.rb'
- 'app/controllers/admin/identities_controller.rb'
- 'app/controllers/admin/labels_controller.rb'
- 'app/controllers/admin/runners_controller.rb'
@@ -35,13 +31,11 @@ Style/EmptyMethod:
- 'app/controllers/projects/alert_management_controller.rb'
- 'app/controllers/projects/ci/lints_controller.rb'
- 'app/controllers/projects/ci/pipeline_editor_controller.rb'
- - 'app/controllers/projects/ci/secure_files_controller.rb'
- 'app/controllers/projects/confluences_controller.rb'
- 'app/controllers/projects/deploy_keys_controller.rb'
- 'app/controllers/projects/environments_controller.rb'
- 'app/controllers/projects/feature_flags_controller.rb'
- 'app/controllers/projects/feature_flags_user_lists_controller.rb'
- - 'app/controllers/projects/hook_logs_controller.rb'
- 'app/controllers/projects/import/jira_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- 'app/controllers/projects/incidents_controller.rb'
@@ -55,30 +49,32 @@ Style/EmptyMethod:
- 'app/controllers/projects/runners_controller.rb'
- 'app/controllers/projects/settings/integrations_controller.rb'
- 'app/controllers/projects/settings/packages_and_registries_controller.rb'
- - 'app/controllers/projects/tags/releases_controller.rb'
- 'app/controllers/projects/terraform_controller.rb'
- 'app/controllers/projects/triggers_controller.rb'
+ - 'app/controllers/pwa_controller.rb'
- 'app/controllers/registrations/welcome_controller.rb'
- 'app/controllers/search_controller.rb'
+ - 'app/experiments/security_actions_continuous_onboarding_experiment.rb'
- 'app/graphql/resolvers/concerns/caching_array_resolver.rb'
- 'app/helpers/subscribable_banner_helper.rb'
- 'app/helpers/users/callouts_helper.rb'
- 'app/models/ci/bridge.rb'
+ - 'app/models/ci/job_artifact.rb'
- 'app/models/concerns/cross_database_modification.rb'
- 'app/models/concerns/reactive_caching.rb'
- 'app/models/concerns/relative_positioning.rb'
- 'app/models/hooks/web_hook.rb'
- 'app/models/integrations/hangouts_chat.rb'
- 'app/models/integrations/microsoft_teams.rb'
+ - 'app/models/integrations/pumble.rb'
- 'app/models/integrations/unify_circuit.rb'
- 'app/models/integrations/webex_teams.rb'
- 'app/models/wiki.rb'
- 'app/services/auto_merge/base_service.rb'
- 'app/services/award_emojis/destroy_service.rb'
+ - 'app/services/groups/transfer_service.rb'
- 'app/services/issuable_base_service.rb'
- - 'app/services/issues/reopen_service.rb'
- 'app/services/projects/transfer_service.rb'
- - 'app/workers/authorized_projects_worker.rb'
- 'app/workers/namespaces/root_statistics_worker.rb'
- 'db/migrate/20210420012444_change_web_hook_events_default.rb'
- 'db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb'
@@ -92,6 +88,7 @@ Style/EmptyMethod:
- 'db/post_migrate/20220324032250_migrate_shimo_confluence_service_category.rb'
- 'db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb'
- 'db/post_migrate/20220425121435_backfill_integrations_enable_ssl_verification.rb'
+ - 'db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb'
- 'ee/app/controllers/admin/emails_controller.rb'
- 'ee/app/controllers/admin/geo/designs_controller.rb'
- 'ee/app/controllers/admin/geo/settings_controller.rb'
@@ -101,9 +98,8 @@ Style/EmptyMethod:
- 'ee/app/controllers/groups/analytics/devops_adoption_controller.rb'
- 'ee/app/controllers/groups/compliance_frameworks_controller.rb'
- 'ee/app/controllers/groups/feature_discovery_moments_controller.rb'
- - 'ee/app/controllers/groups/hooks_controller.rb'
- 'ee/app/controllers/groups/ldap_group_links_controller.rb'
- - 'ee/app/controllers/groups/push_rules_controller.rb'
+ - 'ee/app/controllers/groups/settings/reporting_controller.rb'
- 'ee/app/controllers/projects/analytics/code_reviews_controller.rb'
- 'ee/app/controllers/projects/analytics/merge_request_analytics_controller.rb'
- 'ee/app/controllers/projects/incident_management/escalation_policies_controller.rb'
@@ -122,8 +118,10 @@ Style/EmptyMethod:
- 'ee/app/controllers/subscriptions/groups_controller.rb'
- 'ee/app/controllers/trial_registrations_controller.rb'
- 'ee/app/controllers/trials_controller.rb'
+ - 'ee/app/controllers/users/identity_verification_controller.rb'
- 'ee/app/experiments/cart_abandonment_modal_experiment.rb'
- 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/geo/group_wiki_repository_registry.rb'
- 'ee/app/services/feature_flag_issues/destroy_service.rb'
- 'ee/db/geo/migrate/20170906174622_remove_duplicates_from_project_registry.rb'
- 'lib/api/helpers/packages/conan/api_helpers.rb'
@@ -135,6 +133,8 @@ Style/EmptyMethod:
- 'lib/gitlab/alert_management/payload/base.rb'
- 'lib/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'
- 'lib/gitlab/background_migration/create_security_setting.rb'
+ - 'lib/gitlab/background_migration/delete_approval_rules_with_vulnerability.rb'
+ - 'lib/gitlab/background_migration/delete_invalid_epic_issues.rb'
- 'lib/gitlab/background_migration/drop_invalid_remediations.rb'
- 'lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
@@ -142,6 +142,7 @@ Style/EmptyMethod:
- 'lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb'
- 'lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb'
- 'lib/gitlab/background_migration/migrate_requirements_to_work_items.rb'
+ - 'lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb'
- 'lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb'
- 'lib/gitlab/ci/config/entry/need.rb'
@@ -150,10 +151,10 @@ Style/EmptyMethod:
- 'lib/gitlab/ci/pipeline/chain/validate/after_config.rb'
- 'lib/gitlab/config/entry/node.rb'
- 'lib/gitlab/config/entry/simplifiable.rb'
- - 'lib/gitlab/email/message/in_product_marketing/experience.rb'
- 'lib/gitlab/empty_search_results.rb'
- 'lib/gitlab/git_access.rb'
- 'lib/gitlab/import_export/json/ndjson_writer.rb'
+ - 'lib/gitlab/mailgun/webhook_processors/base.rb'
- 'lib/gitlab/null_request_store.rb'
- 'lib/gitlab/usage_data_non_sql_metrics.rb'
- 'lib/mattermost/session.rb'
@@ -162,7 +163,6 @@ Style/EmptyMethod:
- 'qa/qa/resource/job.rb'
- 'qa/qa/resource/package.rb'
- 'qa/qa/resource/registry_repository.rb'
- - 'qa/qa/resource/runner.rb'
- 'qa/qa/service/cluster_provider/k3d.rb'
- 'qa/qa/service/cluster_provider/k3s.rb'
- 'qa/qa/service/cluster_provider/minikube.rb'
@@ -173,7 +173,6 @@ Style/EmptyMethod:
- 'spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb'
- - 'spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb'
- 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
- 'spec/lib/gitlab/database/postgresql_adapter/dump_schema_versions_mixin_spec.rb'
- 'spec/lib/gitlab/database/postgresql_database_tasks/load_schema_versions_mixin_spec.rb'
@@ -192,4 +191,5 @@ Style/EmptyMethod:
- 'spec/lib/gitlab/utils/delegator_override/validator_spec.rb'
- 'spec/lib/gitlab/utils/delegator_override_spec.rb'
- 'spec/lib/gitlab/utils/override_spec.rb'
+ - 'spec/lib/gitlab/utils/strong_memoize_spec.rb'
- 'spec/workers/concerns/waitable_worker_spec.rb'
diff --git a/.rubocop_todo/style/explicit_block_argument.yml b/.rubocop_todo/style/explicit_block_argument.yml
index 63b7b5d387d..346be201322 100644
--- a/.rubocop_todo/style/explicit_block_argument.yml
+++ b/.rubocop_todo/style/explicit_block_argument.yml
@@ -1,11 +1,10 @@
---
# Cop supports --auto-correct.
Style/ExplicitBlockArgument:
- # Offense count: 143
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/controllers/admin/background_migrations_controller.rb'
+ - 'app/controllers/admin/batched_jobs_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/models/application_record.rb'
- 'app/models/broadcast_message.rb'
@@ -14,13 +13,14 @@ Style/ExplicitBlockArgument:
- 'app/models/ci/build_trace_chunks/redis_trace_chunks.rb'
- 'app/models/concerns/counter_attribute.rb'
- 'app/models/merge_request.rb'
+ - 'app/models/merge_request_diff.rb'
- 'app/models/snippet_repository.rb'
- 'app/services/import_export_clean_up_service.rb'
- 'app/services/packages/debian/generate_distribution_key_service.rb'
- 'app/workers/concerns/each_shard_worker.rb'
- - 'db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb'
- 'ee/app/services/gitlab_subscriptions/fetch_subscription_plans_service.rb'
- 'ee/app/services/group_saml/identity/destroy_service.rb'
+ - 'ee/app/services/security/security_orchestration_policies/base_merge_requests_service.rb'
- 'ee/lib/ee/backup/repositories.rb'
- 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
- 'ee/lib/gitlab/audit/events/preloader.rb'
@@ -44,6 +44,7 @@ Style/ExplicitBlockArgument:
- 'lib/gitlab/ci/variables/collection.rb'
- 'lib/gitlab/cleanup/remote_uploads.rb'
- 'lib/gitlab/database/dynamic_model_helpers.rb'
+ - 'lib/gitlab/database/lock_writes_manager.rb'
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- 'lib/gitlab/git/changes.rb'
- 'lib/gitlab/gitaly_client/list_blobs_adapter.rb'
@@ -58,16 +59,20 @@ Style/ExplicitBlockArgument:
- 'lib/gitlab/import_export/project/base_task.rb'
- 'lib/gitlab/import_export/project/export_task.rb'
- 'lib/gitlab/import_export/project/import_task.rb'
+ - 'lib/gitlab/import_export/remote_stream_upload.rb'
+ - 'lib/gitlab/issuable/clone/copy_resource_events_service.rb'
- 'lib/gitlab/metrics/dashboard/cache.rb'
- 'lib/gitlab/metrics/dashboard/stages/base_stage.rb'
- 'lib/gitlab/profiler.rb'
- 'lib/gitlab/redis/wrapper.rb'
- 'lib/gitlab/reference_counter.rb'
- 'lib/gitlab/seeder.rb'
+ - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
- 'lib/gitlab/sidekiq_middleware/monitor.rb'
- 'lib/gitlab/sidekiq_middleware/query_analyzer.rb'
- 'lib/gitlab/sidekiq_middleware/request_store_middleware.rb'
- 'lib/gitlab/sidekiq_middleware/server_metrics.rb'
+ - 'lib/gitlab/sidekiq_status.rb'
- 'lib/gitlab/utils/measuring.rb'
- 'lib/tasks/config_lint.rake'
- 'qa/qa/ee/page/insights/show.rb'
@@ -87,7 +92,6 @@ Style/ExplicitBlockArgument:
- 'qa/qa/resource/events/base.rb'
- 'qa/qa/runtime/api/repository_storage_moves.rb'
- 'qa/qa/runtime/search.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb'
- 'rubocop/code_reuse_helpers.rb'
- 'spec/features/merge_request/user_sees_wip_help_message_spec.rb'
- 'spec/features/projects/features_visibility_spec.rb'
@@ -99,9 +103,10 @@ Style/ExplicitBlockArgument:
- 'spec/models/repository_spec.rb'
- 'spec/services/pages/zip_directory_service_spec.rb'
- 'spec/services/todo_service_spec.rb'
+ - 'spec/support/database/gitlab_schemas_validate_connection.rb'
- 'spec/support/helpers/feature_flag_helpers.rb'
+ - 'spec/support/helpers/features/runners_helpers.rb'
- 'spec/support/helpers/features/top_nav_spec_helpers.rb'
- - 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/helpers/modal_helpers.rb'
- 'spec/support/helpers/next_found_instance_of.rb'
- 'spec/support/helpers/usage_data_helpers.rb'
diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml
index 66c368a7a52..4da3c32416c 100644
--- a/.rubocop_todo/style/format_string.yml
+++ b/.rubocop_todo/style/format_string.yml
@@ -142,6 +142,7 @@ Style/FormatString:
- 'app/presenters/ci/pipeline_presenter.rb'
- 'app/presenters/merge_request_presenter.rb'
- 'app/presenters/project_presenter.rb'
+ - 'app/presenters/key_presenter.rb'
- 'app/serializers/build_details_entity.rb'
- 'app/services/alert_management/alerts/update_service.rb'
- 'app/services/boards/lists/base_create_service.rb'
@@ -265,7 +266,6 @@ Style/FormatString:
- 'ee/app/services/vulnerabilities/destroy_dismissal_feedback_service.rb'
- 'ee/app/services/vulnerabilities/dismiss_service.rb'
- 'ee/app/services/vulnerabilities/finding_dismiss_service.rb'
- - 'ee/app/services/vulnerabilities/findings/create_from_security_finding_service.rb'
- 'ee/app/services/vulnerabilities/historical_statistics/adjustment_service.rb'
- 'ee/app/services/vulnerabilities/statistics/adjustment_service.rb'
- 'ee/app/services/vulnerability_external_issue_links/create_service.rb'
diff --git a/.rubocop_todo/style/guard_clause.yml b/.rubocop_todo/style/guard_clause.yml
index b07c29ca1df..a4ae491b902 100644
--- a/.rubocop_todo/style/guard_clause.yml
+++ b/.rubocop_todo/style/guard_clause.yml
@@ -378,6 +378,7 @@ Style/GuardClause:
- 'ee/app/models/namespace_limit.rb'
- 'ee/app/models/preloaders/environments/protected_environment_preloader.rb'
- 'ee/app/models/protected_environment.rb'
+ - 'ee/app/models/protected_environments/deploy_access_level.rb'
- 'ee/app/models/sbom/occurrence.rb'
- 'ee/app/models/users_security_dashboard_project.rb'
- 'ee/app/models/vulnerabilities/feedback.rb'
diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml
index cc21860d462..8e295c68623 100644
--- a/.rubocop_todo/style/if_unless_modifier.yml
+++ b/.rubocop_todo/style/if_unless_modifier.yml
@@ -34,7 +34,6 @@ Style/IfUnlessModifier:
- 'app/controllers/import/github_controller.rb'
- 'app/controllers/import/gitlab_controller.rb'
- 'app/controllers/import/manifest_controller.rb'
- - 'app/controllers/jwt_controller.rb'
- 'app/controllers/omniauth_callbacks_controller.rb'
- 'app/controllers/profiles/emails_controller.rb'
- 'app/controllers/profiles/two_factor_auths_controller.rb'
@@ -47,7 +46,6 @@ Style/IfUnlessModifier:
- 'app/controllers/projects/deploy_keys_controller.rb'
- 'app/controllers/projects/design_management/designs_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- - 'app/controllers/projects/integrations/shimos_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/merge_requests/diffs_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
@@ -94,13 +92,9 @@ Style/IfUnlessModifier:
- 'app/graphql/mutations/release_asset_links/update.rb'
- 'app/graphql/mutations/todos/mark_all_done.rb'
- 'app/graphql/resolvers/blobs_resolver.rb'
- - 'app/graphql/resolvers/ci/runner_jobs_resolver.rb'
- 'app/graphql/resolvers/concerns/board_item_filterable.rb'
- 'app/graphql/resolvers/concerns/issue_resolver_arguments.rb'
- 'app/graphql/resolvers/concerns/time_frame_arguments.rb'
- - 'app/graphql/resolvers/group_packages_resolver.rb'
- - 'app/graphql/resolvers/package_details_resolver.rb'
- - 'app/graphql/resolvers/project_jobs_resolver.rb'
- 'app/graphql/resolvers/project_pipeline_resolver.rb'
- 'app/graphql/resolvers/timelog_resolver.rb'
- 'app/graphql/types/ci/job_type.rb'
@@ -133,7 +127,6 @@ Style/IfUnlessModifier:
- 'app/helpers/selects_helper.rb'
- 'app/helpers/snippets_helper.rb'
- 'app/helpers/sorting_helper.rb'
- - 'app/helpers/storage_helper.rb'
- 'app/helpers/submodule_helper.rb'
- 'app/helpers/tab_helper.rb'
- 'app/helpers/timeboxes_helper.rb'
@@ -168,7 +161,6 @@ Style/IfUnlessModifier:
- 'app/models/concerns/bulk_users_by_email_load.rb'
- 'app/models/concerns/cache_markdown_field.rb'
- 'app/models/concerns/ci/artifactable.rb'
- - 'app/models/concerns/counter_attribute.rb'
- 'app/models/concerns/deprecated_assignee.rb'
- 'app/models/concerns/group_descendant.rb'
- 'app/models/concerns/has_wiki_page_meta_attributes.rb'
@@ -272,7 +264,6 @@ Style/IfUnlessModifier:
- 'app/services/ci/job_token_scope/remove_project_service.rb'
- 'app/services/ci/parse_dotenv_artifact_service.rb'
- 'app/services/ci/pipeline_processing/atomic_processing_service.rb'
- - 'app/services/ci/pipelines/add_job_service.rb'
- 'app/services/ci/register_job_service.rb'
- 'app/services/ci/retry_job_service.rb'
- 'app/services/ci/run_scheduled_build_service.rb'
@@ -322,14 +313,11 @@ Style/IfUnlessModifier:
- 'app/services/merge_requests/add_context_service.rb'
- 'app/services/merge_requests/base_service.rb'
- 'app/services/merge_requests/build_service.rb'
- - 'app/services/merge_requests/handle_assignees_change_service.rb'
- 'app/services/merge_requests/merge_base_service.rb'
- 'app/services/merge_requests/mergeability_check_service.rb'
- 'app/services/merge_requests/push_options_handler_service.rb'
- 'app/services/merge_requests/refresh_service.rb'
- - 'app/services/merge_requests/request_attention_service.rb'
- 'app/services/merge_requests/squash_service.rb'
- - 'app/services/merge_requests/toggle_attention_requested_service.rb'
- 'app/services/merge_requests/update_service.rb'
- 'app/services/metrics/dashboard/clone_dashboard_service.rb'
- 'app/services/metrics/dashboard/update_dashboard_service.rb'
@@ -354,7 +342,6 @@ Style/IfUnlessModifier:
- 'app/services/packages/maven/find_or_create_package_service.rb'
- 'app/services/packages/nuget/update_package_from_metadata_service.rb'
- 'app/services/packages/pypi/create_package_service.rb'
- - 'app/services/packages/rubygems/dependency_resolver_service.rb'
- 'app/services/pages/migrate_legacy_storage_to_deployment_service.rb'
- 'app/services/post_receive_service.rb'
- 'app/services/projects/container_repository/gitlab/delete_tags_service.rb'
@@ -375,7 +362,6 @@ Style/IfUnlessModifier:
- 'app/services/projects/update_repository_storage_service.rb'
- 'app/services/protected_branches/cache_service.rb'
- 'app/services/resource_access_tokens/create_service.rb'
- - 'app/services/resource_events/change_labels_service.rb'
- 'app/services/snippets/create_service.rb'
- 'app/services/snippets/destroy_service.rb'
- 'app/services/snippets/repository_validation_service.rb'
@@ -422,8 +408,6 @@ Style/IfUnlessModifier:
- 'app/workers/google_cloud/create_cloudsql_instance_worker.rb'
- 'app/workers/issues/rebalancing_worker.rb'
- 'app/workers/merge_request_mergeability_check_worker.rb'
- - 'app/workers/object_storage/migrate_uploads_worker.rb'
- - 'app/workers/process_commit_worker.rb'
- 'app/workers/projects/import_export/relation_export_worker.rb'
- 'app/workers/remove_expired_members_worker.rb'
- 'app/workers/repository_fork_worker.rb'
@@ -450,8 +434,6 @@ Style/IfUnlessModifier:
- 'config/initializers/sidekiq.rb'
- 'config/initializers/stackprof.rb'
- 'config/initializers/validate_database_config.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
- - 'config/initializers/zz_metrics.rb'
- 'config/initializers_before_autoloader/002_sidekiq.rb'
- 'config/routes.rb'
- 'danger/database/Dangerfile'
@@ -603,6 +585,7 @@ Style/IfUnlessModifier:
- 'ee/app/services/ee/protected_branches/create_service.rb'
- 'ee/app/services/ee/todo_service.rb'
- 'ee/app/services/ee/users/update_service.rb'
+ - 'ee/app/services/elastic/cluster_reindexing_service.rb'
- 'ee/app/services/elastic/indexing_control_service.rb'
- 'ee/app/services/elastic/process_bookkeeping_service.rb'
- 'ee/app/services/epics/base_service.rb'
@@ -652,7 +635,6 @@ Style/IfUnlessModifier:
- 'ee/app/services/vulnerability_feedback/create_service.rb'
- 'ee/app/services/vulnerability_feedback/destroy_service.rb'
- 'ee/app/services/vulnerability_feedback_module/update_service.rb'
- - 'ee/app/services/elastic/cluster_reindexing_service.rb'
- 'ee/app/validators/host_validator.rb'
- 'ee/app/validators/password/complexity_validator.rb'
- 'ee/app/workers/app_sec/dast/profile_schedule_worker.rb'
@@ -889,7 +871,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/ci/config/normalizer.rb'
- 'lib/gitlab/ci/parsers/coverage/sax_document.rb'
- 'lib/gitlab/ci/parsers/security/common.rb'
- - 'lib/gitlab/ci/parsers/security/validators/schema_validator.rb'
- 'lib/gitlab/ci/pipeline/chain/populate.rb'
- 'lib/gitlab/ci/pipeline/chain/seed.rb'
- 'lib/gitlab/ci/pipeline/chain/validate/abilities.rb'
@@ -991,7 +972,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/import_export/project/relation_factory.rb'
- 'lib/gitlab/import_export/project/tree_restorer.rb'
- 'lib/gitlab/instrumentation/rate_limiting_gates.rb'
- - 'lib/gitlab/instrumentation/redis_interceptor.rb'
- 'lib/gitlab/jira_import.rb'
- 'lib/gitlab/jira_import/base_importer.rb'
- 'lib/gitlab/legacy_github_import/client.rb'
@@ -1034,7 +1014,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/search/params.rb'
- 'lib/gitlab/search_context.rb'
- 'lib/gitlab/search_results.rb'
- - 'lib/gitlab/shell.rb'
- 'lib/gitlab/sidekiq_config.rb'
- 'lib/gitlab/sidekiq_config/cli_methods.rb'
- 'lib/gitlab/sidekiq_config/worker_router.rb'
@@ -1063,7 +1042,6 @@ Style/IfUnlessModifier:
- 'lib/sidebars/projects/menus/packages_registries_menu.rb'
- 'lib/sidebars/projects/menus/security_compliance_menu.rb'
- 'lib/sidebars/projects/menus/settings_menu.rb'
- - 'lib/sidebars/projects/panel.rb'
- 'lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb'
- 'lib/system_check/init_helpers.rb'
- 'lib/tasks/cleanup.rake'
@@ -1078,7 +1056,6 @@ Style/IfUnlessModifier:
- 'lib/tasks/gitlab/snippets.rake'
- 'lib/tasks/gitlab/storage.rake'
- 'lib/tasks/gitlab/update_templates.rake'
- - 'qa/qa/ee/page/merge_request/show.rb'
- 'qa/qa/ee/resource/settings/elasticsearch.rb'
- 'qa/qa/flow/sign_up.rb'
- 'qa/qa/page/component/select2.rb'
@@ -1099,21 +1076,10 @@ Style/IfUnlessModifier:
- 'qa/qa/runtime/ip_address.rb'
- 'qa/qa/scenario/bootable.rb'
- 'qa/qa/service/praefect_manager.rb'
- - 'qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/advanced_global_advanced_syntax_search_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/elasticsearch_api_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/commit_index/commit_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/issues_index/issue_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/main_index/blob_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/merge_request_index/merge_request_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/notes_index/note_index_spec.rb'
- - 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/nightly_elasticsearch_test_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_maven_package_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_ldap_sync_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/9_enablement/elasticsearch/elasticsearch_reindexing_spec.rb'
- 'qa/qa/specs/helpers/context_selector.rb'
- 'qa/qa/specs/parallel_runner.rb'
- 'qa/qa/support/loglinking.rb'
@@ -1123,7 +1089,6 @@ Style/IfUnlessModifier:
- 'rubocop/cop/api/grape_array_missing_coerce.rb'
- 'rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb'
- 'rubocop/cop/gitlab/event_store_subscriber.rb'
- - 'rubocop/cop/gitlab/keys_first_and_values_first.rb'
- 'rubocop/cop/gitlab/mark_used_feature_flags.rb'
- 'rubocop/cop/gitlab/policy_rule_boolean.rb'
- 'rubocop/cop/ignored_columns.rb'
@@ -1131,8 +1096,6 @@ Style/IfUnlessModifier:
- 'rubocop/cop/migration/add_reference.rb'
- 'rubocop/cop/migration/remove_column.rb'
- 'rubocop/cop/migration/sidekiq_queue_migrate.rb'
- - 'rubocop/cop/performance/ar_exists_and_present_blank.rb'
- - 'rubocop/cop/rspec/web_mock_enable.rb'
- 'rubocop/routes_under_scope.rb'
- 'scripts/pipeline_test_report_builder.rb'
- 'scripts/review_apps/automated_cleanup.rb'
@@ -1187,6 +1150,7 @@ Style/IfUnlessModifier:
- 'spec/requests/api/integrations_spec.rb'
- 'spec/requests/users_controller_spec.rb'
- 'spec/routing/import_routing_spec.rb'
+ - 'spec/rubocop_spec_helper.rb'
- 'spec/serializers/issue_sidebar_basic_entity_spec.rb'
- 'spec/services/application_settings/update_service_spec.rb'
- 'spec/services/clusters/applications/create_service_spec.rb'
@@ -1197,7 +1161,6 @@ Style/IfUnlessModifier:
- 'spec/services/packages/maven/find_or_create_package_service_spec.rb'
- 'spec/services/packages/maven/metadata/append_package_file_service_spec.rb'
- 'spec/services/packages/maven/metadata/sync_service_spec.rb'
- - 'spec/services/projects/container_repository/cleanup_tags_service_spec.rb'
- 'spec/services/projects/create_service_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support/capybara.rb'
@@ -1213,7 +1176,6 @@ Style/IfUnlessModifier:
- 'spec/support/helpers/lets_encrypt_helpers.rb'
- 'spec/support/helpers/live_debugger.rb'
- 'spec/support/helpers/modal_helpers.rb'
- - 'spec/support/helpers/seed_helper.rb'
- 'spec/support/helpers/stub_gitlab_calls.rb'
- 'spec/support/helpers/stubbed_feature.rb'
- 'spec/support/helpers/test_env.rb'
diff --git a/.rubocop_todo/style/keyword_parameters_order.yml b/.rubocop_todo/style/keyword_parameters_order.yml
index 0bb499cebb0..3521f295cc1 100644
--- a/.rubocop_todo/style/keyword_parameters_order.yml
+++ b/.rubocop_todo/style/keyword_parameters_order.yml
@@ -1,10 +1,9 @@
---
# Cop supports --auto-correct.
Style/KeywordParametersOrder:
- # Offense count: 110
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
+ - 'app/controllers/concerns/product_analytics_tracking.rb'
- 'app/finders/group_descendants_finder.rb'
- 'app/finders/merge_request_target_project_finder.rb'
- 'app/graphql/resolvers/package_pipelines_resolver.rb'
@@ -30,20 +29,23 @@ Style/KeywordParametersOrder:
- 'ee/app/services/analytics/devops_adoption/enabled_namespaces/create_service.rb'
- 'ee/app/services/analytics/devops_adoption/enabled_namespaces/find_or_create_service.rb'
- 'ee/app/services/audit_events/user_impersonation_group_audit_event_service.rb'
- - 'ee/app/services/members/activate_service.rb'
- 'ee/lib/gitlab/elastic/helper.rb'
+ - 'ee/lib/gitlab/insights/executors/dora_executor.rb'
+ - 'ee/lib/gitlab/insights/executors/issuable_executor.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
- 'ee/spec/requests/api/deployments_spec.rb'
+ - 'lib/gitlab/background_migration/batched_migration_job.rb'
- 'lib/gitlab/checks/timed_logger.rb'
- 'lib/gitlab/ci/reports/security/finding.rb'
+ - 'lib/gitlab/cleanup/personal_access_tokens.rb'
- 'lib/gitlab/database/partitioning/monthly_strategy.rb'
- 'lib/gitlab/database/with_lock_retries.rb'
- 'lib/gitlab/diff/diff_refs.rb'
- 'lib/gitlab/email/smime/signer.rb'
- - 'lib/gitlab/error_tracking.rb'
- 'lib/gitlab/exclusive_lease.rb'
- 'lib/gitlab/import_export/import_failure_service.rb'
- 'lib/gitlab/merge_requests/mergeability/results_store.rb'
+ - 'lib/gitlab/usage_data_counters/editor_unique_counter.rb'
- 'lib/microsoft_teams/notifier.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
@@ -64,9 +66,12 @@ Style/KeywordParametersOrder:
- 'spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb'
- 'spec/migrations/confirm_support_bot_user_spec.rb'
- 'spec/services/service_ping/submit_service_ping_service_spec.rb'
+ - 'spec/support/helpers/doc_url_helper.rb'
- 'spec/support/helpers/smime_helper.rb'
- 'spec/support/helpers/workhorse_helpers.rb'
+ - 'spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb'
- 'spec/support/shared_examples/services/container_expiration_policy_shared_examples.rb'
- 'spec/support/shared_examples/services/dependency_proxy_ttl_policies_shared_examples.rb'
- 'spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb'
+ - 'spec/tasks/gitlab/usage_data_rake_spec.rb'
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'
diff --git a/.rubocop_todo/style/numeric_literal_prefix.yml b/.rubocop_todo/style/numeric_literal_prefix.yml
index ea0b028d11c..5de15180438 100644
--- a/.rubocop_todo/style/numeric_literal_prefix.yml
+++ b/.rubocop_todo/style/numeric_literal_prefix.yml
@@ -1,21 +1,22 @@
---
# Cop supports --auto-correct.
Style/NumericLiteralPrefix:
- # Offense count: 148
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/models/container_repository.rb'
- 'app/services/packages/debian/generate_distribution_key_service.rb'
- 'config/initializers/01_secret_token.rb'
- 'config/initializers/1_settings.rb'
- 'db/post_migrate/20220131000001_schedule_trace_expiry_removal.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
- 'ee/lib/gitlab/geo/replication/blob_downloader.rb'
- 'ee/spec/lib/bulk_imports/groups/pipelines/iterations_pipeline_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size_spec.rb'
- 'ee/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb'
- 'ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb'
- 'ee/spec/migrations/schedule_trace_expiry_removal_spec.rb'
- 'ee/spec/models/analytics/devops_adoption/snapshot_spec.rb'
+ - 'ee/spec/models/ci/minutes/usage_spec.rb'
- 'ee/spec/models/ee/group_spec.rb'
- 'ee/spec/models/gitlab/seat_link_data_spec.rb'
- 'ee/spec/services/incident_management/oncall_schedules/update_service_spec.rb'
@@ -27,18 +28,17 @@ Style/NumericLiteralPrefix:
- 'lib/gitlab/jwt_authenticatable.rb'
- 'lib/system_check/app/uploads_path_permission_check.rb'
- 'lib/system_check/app/uploads_path_tmp_permission_check.rb'
+ - 'lib/tasks/gitlab/backup.rake'
- 'lib/tasks/tanuki_emoji.rake'
- 'metrics_server/metrics_server.rb'
- 'qa/qa/support/ssh.rb'
- 'qa/spec/support/ssh_spec.rb'
- 'scripts/security-harness'
+ - 'spec/finders/personal_access_tokens_finder_spec.rb'
- 'spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_job_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- - 'spec/lib/gitlab/encoding_helper_spec.rb'
- 'spec/lib/gitlab/git/diff_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb'
- 'spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb'
- 'spec/lib/gitlab/gitaly_client/diff_spec.rb'
@@ -65,11 +65,11 @@ Style/NumericLiteralPrefix:
- 'spec/lib/gitlab/puma_logging/json_formatter_spec.rb'
- 'spec/lib/gitlab/relative_positioning/range_spec.rb'
- 'spec/metrics_server/metrics_server_spec.rb'
+ - 'spec/migrations/20220506154054_create_sync_namespace_details_trigger_spec.rb'
+ - 'spec/migrations/20220524184149_create_sync_project_namespace_details_trigger_spec.rb'
- 'spec/models/issue_spec.rb'
- - 'spec/models/repository_spec.rb'
- - 'spec/support/helpers/repo_helpers.rb'
- - 'spec/support/helpers/test_env.rb'
+ - 'spec/models/personal_access_token_spec.rb'
+ - 'spec/requests/api/personal_access_tokens_spec.rb'
- 'spec/support/import_export/export_file_helper.rb'
- 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
- 'spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml
index 9989ae3f8b3..472a722ed22 100644
--- a/.rubocop_todo/style/percent_literal_delimiters.yml
+++ b/.rubocop_todo/style/percent_literal_delimiters.yml
@@ -592,7 +592,6 @@ Style/PercentLiteralDelimiters:
- 'lib/gitlab/search/abuse_detection.rb'
- 'lib/gitlab/search_context.rb'
- 'lib/gitlab/sidekiq_daemon/memory_killer.rb'
- - 'lib/gitlab/sidekiq_middleware/memory_killer.rb'
- 'lib/gitlab/slash_commands/presenters/base.rb'
- 'lib/gitlab/ssh_public_key.rb'
- 'lib/gitlab/task_helpers.rb'
@@ -1155,7 +1154,6 @@ Style/PercentLiteralDelimiters:
- 'spec/support/helpers/login_helpers.rb'
- 'spec/support/helpers/prometheus_helpers.rb'
- 'spec/support/helpers/repo_helpers.rb'
- - 'spec/support/helpers/seed_helper.rb'
- 'spec/support/helpers/seed_repo.rb'
- 'spec/support/helpers/test_env.rb'
- 'spec/support/helpers/usage_data_helpers.rb'
@@ -1192,7 +1190,6 @@ Style/PercentLiteralDelimiters:
- 'spec/support_specs/graphql/arguments_spec.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
- 'spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/tasks/gitlab/task_helpers_spec.rb'
- 'spec/tasks/gitlab/uploads/migrate_rake_spec.rb'
diff --git a/.rubocop_todo/style/redundant_begin.yml b/.rubocop_todo/style/redundant_begin.yml
new file mode 100644
index 00000000000..e96cdb26b08
--- /dev/null
+++ b/.rubocop_todo/style/redundant_begin.yml
@@ -0,0 +1,57 @@
+---
+# Cop supports --auto-correct.
+Style/RedundantBegin:
+ Details: grace period
+ Exclude:
+ - 'app/controllers/concerns/membership_actions.rb'
+ - 'app/controllers/concerns/metrics_dashboard.rb'
+ - 'app/controllers/concerns/renders_ldap_servers.rb'
+ - 'app/helpers/auth_helper.rb'
+ - 'app/models/event.rb'
+ - 'app/models/integrations/asana.rb'
+ - 'app/models/integrations/jira.rb'
+ - 'app/models/user.rb'
+ - 'app/services/ci/register_job_service.rb'
+ - 'app/services/design_management/generate_image_versions_service.rb'
+ - 'app/services/error_tracking/list_projects_service.rb'
+ - 'app/services/issue_links/create_service.rb'
+ - 'app/services/merge_requests/assign_issues_service.rb'
+ - 'app/services/projects/batch_forks_count_service.rb'
+ - 'app/services/projects/batch_open_issues_count_service.rb'
+ - 'app/services/projects/lfs_pointers/lfs_object_download_list_service.rb'
+ - 'app/services/users/update_highest_member_role_service.rb'
+ - 'ee/app/controllers/groups/sso_controller.rb'
+ - 'ee/app/finders/security/findings_finder.rb'
+ - 'ee/app/services/epics/epic_links/create_service.rb'
+ - 'ee/app/services/epics/related_epic_links/create_service.rb'
+ - 'ee/app/services/geo/container_repository_sync_service.rb'
+ - 'ee/app/validators/ee/json_schema_validator.rb'
+ - 'ee/lib/ee/api/helpers/award_emoji.rb'
+ - 'ee/lib/gem_extensions/elasticsearch/model/adapter/multiple/records.rb'
+ - 'ee/lib/gitlab/ci/parsers/security/dast.rb'
+ - 'ee/lib/omni_auth/strategies/group_saml.rb'
+ - 'ee/lib/system_check/geo/authorized_keys_check.rb'
+ - 'lib/api/helpers/award_emoji.rb'
+ - 'lib/api/time_tracking_endpoints.rb'
+ - 'lib/atlassian/jira_connect/serializers/build_entity.rb'
+ - 'lib/backup/manager.rb'
+ - 'lib/banzai/pipeline/wiki_pipeline.rb'
+ - 'lib/gem_extensions/active_record/association.rb'
+ - 'lib/gitlab.rb'
+ - 'lib/gitlab/changes_list.rb'
+ - 'lib/gitlab/color.rb'
+ - 'lib/gitlab/database/migration_helpers.rb'
+ - 'lib/gitlab/database/schema_cache_with_renamed_table.rb'
+ - 'lib/gitlab/favicon.rb'
+ - 'lib/gitlab/import_export/base/relation_factory.rb'
+ - 'lib/gitlab/import_export/members_mapper.rb'
+ - 'lib/gitlab/import_export/project/tree_saver.rb'
+ - 'lib/gitlab/instrumentation/redis_interceptor.rb'
+ - 'lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb'
+ - 'lib/gitlab/phabricator_import/project_creator.rb'
+ - 'lib/gitlab/project_search_results.rb'
+ - 'lib/gitlab/shell.rb'
+ - 'lib/gitlab/usage/metrics/aggregates/sources/calculations/intersection.rb'
+ - 'lib/sidebars/menu.rb'
+ - 'qa/qa/resource/api_fabricator.rb'
+ - 'qa/qa/runtime/api/client.rb'
diff --git a/.rubocop_todo/style/redundant_condition.yml b/.rubocop_todo/style/redundant_condition.yml
new file mode 100644
index 00000000000..86be40f7ffa
--- /dev/null
+++ b/.rubocop_todo/style/redundant_condition.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+Style/RedundantCondition:
+ Exclude:
+ - 'ee/app/models/license.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
diff --git a/.rubocop_todo/style/redundant_parentheses.yml b/.rubocop_todo/style/redundant_parentheses.yml
new file mode 100644
index 00000000000..1ca658776b8
--- /dev/null
+++ b/.rubocop_todo/style/redundant_parentheses.yml
@@ -0,0 +1,6 @@
+---
+# Cop supports --auto-correct.
+Style/RedundantParentheses:
+ Exclude:
+ - 'lib/gitlab/database/tables_truncate.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/utilization/billing_seats_usage_data_spec.rb'
diff --git a/.rubocop_todo/style/single_argument_dig.yml b/.rubocop_todo/style/single_argument_dig.yml
index 860183426e9..3ffd27d26ae 100644
--- a/.rubocop_todo/style/single_argument_dig.yml
+++ b/.rubocop_todo/style/single_argument_dig.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/SingleArgumentDig:
- # Offense count: 150
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/graphql/resolvers/namespace_projects_resolver.rb'
- 'app/models/ci/build.rb'
@@ -22,6 +20,7 @@ Style/SingleArgumentDig:
- 'ee/app/workers/concerns/elastic/migration_helper.rb'
- 'ee/lib/gitlab/ci/parsers/security/dependency_list.rb'
- 'ee/lib/gitlab/subscription_portal/clients/graphql.rb'
+ - 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
- 'ee/spec/graphql/mutations/vulnerabilities/create_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/parsers/security/common_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/chain/validate/external_spec.rb'
@@ -35,10 +34,11 @@ Style/SingleArgumentDig:
- 'ee/spec/requests/api/graphql/project/dast_site_profiles_spec.rb'
- 'ee/spec/requests/api/graphql/project/requirements_management/requirements_spec.rb'
- 'ee/spec/requests/api/internal/upcoming_reconciliations_spec.rb'
+ - 'ee/spec/services/vulnerabilities/findings/find_or_create_from_security_finding_service_spec.rb'
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
+ - 'lib/gitlab/auth/o_auth/auth_hash.rb'
- 'lib/gitlab/ci/badge/coverage/template.rb'
- - 'lib/gitlab/ci/badge/pipeline/template.rb'
- - 'lib/gitlab/ci/badge/release/template.rb'
+ - 'lib/gitlab/ci/badge/template.rb'
- 'lib/gitlab/ci/lint.rb'
- 'lib/gitlab/ci/parsers/accessibility/pa11y.rb'
- 'lib/gitlab/ci/parsers/security/common.rb'
@@ -51,11 +51,13 @@ Style/SingleArgumentDig:
- 'lib/gitlab/database/transaction/observer.rb'
- 'lib/gitlab/serverless/service.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb'
+ - 'qa/qa/vendor/mail_hog/api.rb'
- 'spec/controllers/graphql_controller_spec.rb'
- 'spec/graphql/types/release_links_type_spec.rb'
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
+ - 'spec/requests/api/graphql/ci/instance_variables_spec.rb'
- 'spec/requests/api/graphql/container_repository/container_repository_details_spec.rb'
- 'spec/requests/api/graphql/project/container_repositories_spec.rb'
- 'spec/requests/api/graphql/project/jira_import_spec.rb'
diff --git a/.rubocop_todo/style/sole_nested_conditional.yml b/.rubocop_todo/style/sole_nested_conditional.yml
index 620d66a272c..535b8d20765 100644
--- a/.rubocop_todo/style/sole_nested_conditional.yml
+++ b/.rubocop_todo/style/sole_nested_conditional.yml
@@ -1,8 +1,7 @@
---
+# Cop supports --auto-correct.
Style/SoleNestedConditional:
- # Offense count: 64
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/controllers/admin/application_settings_controller.rb'
- 'app/controllers/ldap/omniauth_callbacks_controller.rb'
@@ -17,7 +16,6 @@ Style/SoleNestedConditional:
- 'app/models/network/graph.rb'
- 'app/models/packages/package.rb'
- 'app/models/protected_branch.rb'
- - 'app/services/ci/register_job_service.rb'
- 'app/services/concerns/update_visibility_level.rb'
- 'app/services/incident_management/incidents/create_service.rb'
- 'app/services/merge_requests/update_service.rb'
@@ -27,9 +25,11 @@ Style/SoleNestedConditional:
- 'app/services/projects/create_service.rb'
- 'app/services/projects/hashed_storage/migration_service.rb'
- 'app/services/projects/hashed_storage/rollback_service.rb'
+ - 'app/workers/merge_requests/delete_source_branch_worker.rb'
- 'ee/app/finders/ee/snippets_finder.rb'
- 'ee/app/services/ee/issue_links/create_service.rb'
- 'ee/app/services/ee/lfs/unlock_file_service.rb'
+ - 'ee/app/services/ee/merge_requests/create_pipeline_service.rb'
- 'ee/app/services/epics/tree_reorder_service.rb'
- 'ee/app/services/geo/framework_repository_sync_service.rb'
- 'ee/app/services/geo/repository_base_sync_service.rb'
@@ -43,6 +43,7 @@ Style/SoleNestedConditional:
- 'lib/api/ci/helpers/runner.rb'
- 'lib/api/deploy_keys.rb'
- 'lib/api/helpers/label_helpers.rb'
+ - 'lib/api/maven_packages.rb'
- 'lib/api/users.rb'
- 'lib/banzai/filter/ascii_doc_sanitization_filter.rb'
- 'lib/banzai/filter/base_sanitization_filter.rb'
@@ -52,7 +53,9 @@ Style/SoleNestedConditional:
- 'lib/gitlab/config/entry/configurable.rb'
- 'lib/gitlab/config/entry/validators.rb'
- 'lib/gitlab/database/each_database.rb'
+ - 'lib/gitlab/database/load_balancing/load_balancer.rb'
- 'lib/gitlab/email/handler/reply_processing.rb'
+ - 'lib/gitlab/patch/database_config.rb'
- 'lib/gitlab/user_access.rb'
- 'lib/gitlab/utils.rb'
- 'lib/gitlab/x509/signature.rb'
@@ -60,5 +63,5 @@ Style/SoleNestedConditional:
- 'lib/mattermost/session.rb'
- 'lib/object_storage/direct_upload.rb'
- 'qa/qa/flow/login.rb'
- - 'qa/qa/support/page_error_checker.rb'
+ - 'qa/qa/page/project/web_ide/edit.rb'
- 'spec/spec_helper.rb'
diff --git a/.rubocop_todo/style/special_global_vars.yml b/.rubocop_todo/style/special_global_vars.yml
new file mode 100644
index 00000000000..df688872d71
--- /dev/null
+++ b/.rubocop_todo/style/special_global_vars.yml
@@ -0,0 +1,4 @@
+---
+# Cop supports --auto-correct.
+Style/SpecialGlobalVars:
+ Details: grace period
diff --git a/.rubocop_todo/style/string_concatenation.yml b/.rubocop_todo/style/string_concatenation.yml
index 315ce3701a8..ec15edbc206 100644
--- a/.rubocop_todo/style/string_concatenation.yml
+++ b/.rubocop_todo/style/string_concatenation.yml
@@ -263,9 +263,9 @@ Style/StringConcatenation:
- 'spec/models/custom_emoji_spec.rb'
- 'spec/models/grafana_integration_spec.rb'
- 'spec/models/integrations/campfire_spec.rb'
+ - 'spec/models/integrations/datadog_spec.rb'
- 'spec/models/integrations/chat_message/pipeline_message_spec.rb'
- 'spec/models/integrations/chat_message/push_message_spec.rb'
- - 'spec/models/integrations/datadog_spec.rb'
- 'spec/models/integrations/jenkins_spec.rb'
- 'spec/models/merge_request_diff_spec.rb'
- 'spec/models/merge_request_spec.rb'
diff --git a/.rubocop_todo/style/string_literals_in_interpolation.yml b/.rubocop_todo/style/string_literals_in_interpolation.yml
index cded81afa7f..fc90e1ce6a6 100644
--- a/.rubocop_todo/style/string_literals_in_interpolation.yml
+++ b/.rubocop_todo/style/string_literals_in_interpolation.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/StringLiteralsInInterpolation:
- # Offense count: 119
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/graphql/mutations/base_mutation.rb'
- 'app/helpers/colors_helper.rb'
@@ -23,11 +21,16 @@ Style/StringLiteralsInInterpolation:
- 'ee/app/helpers/ee/merge_requests_helper.rb'
- 'ee/app/models/license.rb'
- 'ee/app/services/epics/tree_reorder_service.rb'
+ - 'ee/lib/ee/api/helpers/issues_helpers.rb'
- 'ee/lib/gitlab/elastic/helper.rb'
+ - 'ee/lib/tasks/gitlab/elastic.rake'
- 'ee/spec/features/admin/admin_settings_spec.rb'
+ - 'ee/spec/features/subscriptions/expiring_subscription_message_spec.rb'
+ - 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- 'lib/api/helpers/snippets_helpers.rb'
- 'lib/api/validations/validators/check_assignees_count.rb'
- 'lib/banzai/filter/references/abstract_reference_filter.rb'
+ - 'lib/banzai/filter/syntax_highlight_filter.rb'
- 'lib/generators/gitlab/usage_metric_definition_generator.rb'
- 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb'
- 'lib/gitlab/ci/config/entry/job.rb'
@@ -36,6 +39,7 @@ Style/StringLiteralsInInterpolation:
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
- 'lib/gitlab/doctor/secrets.rb'
- 'lib/gitlab/endpoint_attributes/config.rb'
+ - 'lib/gitlab/gitaly_client/ref_service.rb'
- 'lib/gitlab/graphql/queries.rb'
- 'lib/gitlab/quick_actions/extractor.rb'
- 'lib/gitlab/sanitizers/exif.rb'
@@ -43,13 +47,11 @@ Style/StringLiteralsInInterpolation:
- 'lib/gitlab/tracking/destinations/snowplow.rb'
- 'lib/tasks/gitlab/info.rake'
- 'lib/tasks/gitlab/sidekiq.rake'
- - 'lib/tasks/gitlab/tw/codeowners.rake'
- 'qa/qa/ee/page/component/secure_report.rb'
- 'qa/qa/ee/page/group/secure/show.rb'
- 'qa/qa/resource/events/base.rb'
- 'qa/qa/service/cluster_provider/base.rb'
- 'qa/qa/service/cluster_provider/gcloud.rb'
- - 'qa/qa/service/docker_run/gitlab_runner.rb'
- 'qa/qa/specs/helpers/context_selector.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- 'rubocop/cop/migration/prevent_index_creation.rb'
@@ -59,9 +61,12 @@ Style/StringLiteralsInInterpolation:
- 'spec/finders/serverless_domain_finder_spec.rb'
- 'spec/lib/banzai/filter/references/commit_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/issue_reference_filter_spec.rb'
+ - 'spec/lib/gitlab/background_migration/batched_migration_job_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/ref_service_spec.rb'
- 'spec/lib/object_storage/direct_upload_spec.rb'
- 'spec/models/serverless/domain_spec.rb'
- 'spec/requests/api/keys_spec.rb'
- 'spec/support/database/prevent_cross_joins.rb'
+ - 'spec/views/notify/import_issues_csv_email.html.haml_spec.rb'
diff --git a/.rubocop_todo/style/symbol_proc.yml b/.rubocop_todo/style/symbol_proc.yml
index bfb3867b127..d373788dbc6 100644
--- a/.rubocop_todo/style/symbol_proc.yml
+++ b/.rubocop_todo/style/symbol_proc.yml
@@ -70,8 +70,6 @@ Style/SymbolProc:
- 'app/services/clusters/agents/delete_expired_events_service.rb'
- 'app/services/feature_flags/update_service.rb'
- 'app/services/merge_requests/base_service.rb'
- - 'app/services/merge_requests/bulk_remove_attention_requested_service.rb'
- - 'app/services/merge_requests/reopen_service.rb'
- 'app/services/notes/destroy_service.rb'
- 'app/services/packages/debian/generate_distribution_service.rb'
- 'app/services/resource_events/synthetic_label_notes_builder_service.rb'
@@ -87,7 +85,6 @@ Style/SymbolProc:
- 'config/initializers/01_active_record_database_tasks_configuration_flag.rb'
- 'config/initializers/doorkeeper_openid_connect.rb'
- 'config/initializers/mail_encoding_patch.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
- 'config/settings.rb'
- 'db/migrate/20210318134427_delete_security_findings_without_uuid.rb'
- 'db/migrate/20210503105845_add_project_value_stream_id_to_project_stages.rb'
@@ -136,7 +133,6 @@ Style/SymbolProc:
- 'ee/spec/helpers/ee/registrations_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/search_results_spec.rb'
- 'ee/spec/lib/gitlab/elastic/document_reference_spec.rb'
- - 'ee/spec/models/ee/iterations/cadence_spec.rb'
- 'ee/spec/services/groups/participants_service_spec.rb'
- 'ee/spec/support/helpers/subscription_portal_helpers.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/graphql/issuables_lazy_links_aggregate_shared_examples.rb'
@@ -205,17 +201,13 @@ Style/SymbolProc:
- 'qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/attachment_replication_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/http_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/rename_replication_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/ssh_push_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_http_push_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/13_secure/enable_scanning_from_configuration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/merge_request/approval_rules_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/pipeline_status_on_operation_dashboard_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/pipeline_subscription_with_group_owned_project_spec.rb'
- 'rubocop/cop/gitlab/mark_used_feature_flags.rb'
+ - 'rubocop/cop/gitlab/namespaced_class.rb'
- 'scripts/qa/testcases-check'
- 'scripts/static-analysis'
- 'spec/controllers/concerns/product_analytics_tracking_spec.rb'
@@ -245,7 +237,6 @@ Style/SymbolProc:
- 'spec/lib/gitlab/database/loose_foreign_keys_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb'
- 'spec/lib/gitlab/git/commit_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- 'spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb'
- 'spec/lib/gitlab/graphql/lazy_spec.rb'
- 'spec/lib/gitlab/graphql/markdown_field_spec.rb'
@@ -272,7 +263,6 @@ Style/SymbolProc:
- 'spec/services/merge_requests/conflicts/list_service_spec.rb'
- 'spec/services/notification_recipients/builder/default_spec.rb'
- 'spec/services/packages/go/create_package_service_spec.rb'
- - 'spec/services/suggestions/apply_service_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support/generate-seed-repo-rb'
- 'spec/support/helpers/filter_spec_helper.rb'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29fcd1e0ca4..dd62854c530 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,15 +2,6 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
-## 15.4.3 (2022-10-19)
-
-### Fixed (4 changes)
-
-- [Sign in: use custom logo again](gitlab-org/gitlab@5822562c4c3508927e3b217749867736e91316f3) ([merge request](gitlab-org/gitlab!101235))
-- [Fix closing of external issues](gitlab-org/gitlab@1302f992e3706b698c983961f596fcab03704c3f) ([merge request](gitlab-org/gitlab!101235))
-- [Sign in: use custom logo again](gitlab-org/gitlab@d760473a022ef485be7e258ab5fc406f05a127a4) ([merge request](gitlab-org/gitlab!101235))
-- [Fix REST/GRAPHQL APIs handling TODOs WorkItem target](gitlab-org/gitlab@f4157b08596040bbc504292c4a75fe2100aa570c) ([merge request](gitlab-org/gitlab!100081))
-
## 15.4.2 (2022-10-04)
### Fixed (1 change)
@@ -669,6 +660,26 @@ entry.
- [Improve specs with shared examples](gitlab-org/gitlab@dd3f2ecd882e89511eaa927102fc4101f684a38f) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95539)) **GitLab Enterprise Edition**
- [Fix Style/Next offenses](gitlab-org/gitlab@bdf877063ba1d8d4df1216f7875905343d9e5e33) ([merge request](gitlab-org/gitlab!93329))
+## 15.3.4 (2022-09-29)
+
+### Security (15 changes)
+
+- [Redact user's private email in group member event webhook](gitlab-org/security/gitlab@172b8a57bd4acca14d65a4b7a5fd021babacb146) ([merge request](gitlab-org/security/gitlab!2794))
+- [Redact secrets from WebHookLogs](gitlab-org/security/gitlab@7394ab9b32a7bd83b98f93e904312e469f34cd9c) ([merge request](gitlab-org/security/gitlab!2737))
+- [Forbid creating a tag using default branch name](gitlab-org/security/gitlab@1b556c33aa11c32994be562cfea0ff2e5e13a54e) ([merge request](gitlab-org/security/gitlab!2799))
+- [Sanitize Url and check for valid numerical errorId in error tracking](gitlab-org/security/gitlab@2a5a51b5b2839963fe7084261c8a7fcc6f09f19c) ([merge request](gitlab-org/security/gitlab!2785))
+- [Add security protection for Github](gitlab-org/security/gitlab@bc23f46dba26bcdf0c773c24081e4ae3597bf751) ([merge request](gitlab-org/security/gitlab!2802))
+- [Fix leaking emails in WebHookLogs](gitlab-org/security/gitlab@a31a652c331877e0f97269310ec5f1bc6266398f) ([merge request](gitlab-org/security/gitlab!2807))
+- [Restrict max duration to 1 year for trace display](gitlab-org/security/gitlab@b62fd774b6f311988c7e10f3544f2aeabeab85d1) ([merge request](gitlab-org/security/gitlab!2815))
+- [Use UntrustedRegexp for upload rewriter](gitlab-org/security/gitlab@2eea36acbc5687aa9806946861e73f2fb11a9654) ([merge request](gitlab-org/security/gitlab!2791))
+- [Validate httpUrlToRepo to be http or https only](gitlab-org/security/gitlab@0b340ef6d6e54804445916f5b1fa53185de4b1f7) ([merge request](gitlab-org/security/gitlab!2760))
+- [Respect instance level rule for editing approval rules](gitlab-org/security/gitlab@2d2a7b8652dbd1085fe1bfc0b69138aecdeaf9c8) ([merge request](gitlab-org/security/gitlab!2782))
+- [Prevent users creating issues in ay project via board/issues controller](gitlab-org/security/gitlab@559b23e6942a650cafa358ea96b7ee549f76fbd6) ([merge request](gitlab-org/security/gitlab!2780))
+- [Prevent serialization of sensible attributes from JsonCache](gitlab-org/security/gitlab@f712d58af3aeb3f0fe1c56a290188e19fce72ad6) ([merge request](gitlab-org/security/gitlab!2771))
+- [Update TodoPolicy to handle confidential notes](gitlab-org/security/gitlab@6bd37cd0595bbf4c744a5b212fc41181c9dc88ef) ([merge request](gitlab-org/security/gitlab!2748))
+- [Enforce group IP restriction on Dependency Proxy](gitlab-org/security/gitlab@cc42b5e91e04e77ade63f1fdb91e88b998c156f7) ([merge request](gitlab-org/security/gitlab!2764))
+- [Fixes XSS in widget extensions](gitlab-org/security/gitlab@1d10849c7eee6207435bfd223e1f8639b2816c1e) ([merge request](gitlab-org/security/gitlab!2759))
+
## 15.3.3 (2022-09-01)
### Fixed (5 changes)
@@ -1312,6 +1323,27 @@ entry.
- [Remove FF import_release_authors_from_github](gitlab-org/gitlab@c4d6871e4438a1626d688856903778623138f671) ([merge request](gitlab-org/gitlab!92686))
- [Remove unused feature](gitlab-org/gitlab@0ef95d341e4a15150d6ccb3d104ebbe064aa062a) ([merge request](gitlab-org/gitlab!92753))
+## 15.2.5 (2022-09-29)
+
+### Security (16 changes)
+
+- [Geo: Do not delete object stored files when not GitLab managed](gitlab-org/security/gitlab@340554d933823b0424e16318673ccd6a82e87d35) ([merge request](gitlab-org/security/gitlab!2775))
+- [Redact user's private email in group member event webhook](gitlab-org/security/gitlab@dcc5fd6bcef40109c92e0faa34bf52b568465e80) ([merge request](gitlab-org/security/gitlab!2795))
+- [Redact secrets from WebHookLogs](gitlab-org/security/gitlab@e53429f776d06b9881f20a000d1a2b40e2f13a2c) ([merge request](gitlab-org/security/gitlab!2657))
+- [Forbid creating a tag using default branch name](gitlab-org/security/gitlab@ff172ca5d5550d3ff263efaef9ce18b6b78cbfbb) ([merge request](gitlab-org/security/gitlab!2800))
+- [Sanitize Url and check for valid numerical errorId in error tracking](gitlab-org/security/gitlab@2d983dc2b99f387c1e30312cb452cf21a4aa6f27) ([merge request](gitlab-org/security/gitlab!2786))
+- [Add security protection for Github](gitlab-org/security/gitlab@9f6d284039431f1376c4be03f5d364e12090fbc7) ([merge request](gitlab-org/security/gitlab!2804))
+- [Fix leaking emails in WebHookLogs](gitlab-org/security/gitlab@7e0e629f7559ad1ad7375a4ab94748febe5fd1ef) ([merge request](gitlab-org/security/gitlab!2808))
+- [Restrict max duration to 1 year for trace display](gitlab-org/security/gitlab@2df0b5b9978b09bbc95efbea5f227e3afaa220c7) ([merge request](gitlab-org/security/gitlab!2816))
+- [Use UntrustedRegexp for upload rewriter](gitlab-org/security/gitlab@c0bd5867a091ed7d04e19a6598c2e112daca4861) ([merge request](gitlab-org/security/gitlab!2792))
+- [Validate httpUrlToRepo to be http or https only](gitlab-org/security/gitlab@98ee48505898f3b5535587c0081292d82b94009e) ([merge request](gitlab-org/security/gitlab!2761))
+- [Respect instance level rule for editing approval rules](gitlab-org/security/gitlab@7157ddbaf6be664a708b24f59be541d7e16fbbd6) ([merge request](gitlab-org/security/gitlab!2783))
+- [Prevent users creating issues in ay project via board/issues controller](gitlab-org/security/gitlab@55b2ba96fa53b2aa3e8de889bc05671339f7aa76) ([merge request](gitlab-org/security/gitlab!2779))
+- [Prevent serialization of sensible attributes from JsonCache](gitlab-org/security/gitlab@809aff4805a2916425f7ec0cd995101140f663f8) ([merge request](gitlab-org/security/gitlab!2772))
+- [Update TodoPolicy to handle confidential notes](gitlab-org/security/gitlab@b95b1bc4ea7b5d69ff02283789c68f821ec54cee) ([merge request](gitlab-org/security/gitlab!2749))
+- [Enforce group IP restriction on Dependency Proxy](gitlab-org/security/gitlab@4342542081be434e013110f9dd456b5caf286464) ([merge request](gitlab-org/security/gitlab!2765))
+- [Fixes XSS in widget extensions](gitlab-org/security/gitlab@e3d4d46967e72f12645d08ef1879223a1ec2d398) ([merge request](gitlab-org/security/gitlab!2675))
+
## 15.2.4 (2022-08-30)
### Security (18 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 52e5165c62b..fe81f057738 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-15.4.3 \ No newline at end of file
+334a620a54df6bbb1563c440514e06d7068255e7
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
index b5021469305..75a22a26ac4 100644
--- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -1 +1 @@
-3.0.2
+3.0.3
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index c915b5db730..2e0b428c416 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-15.4.0
+15.5.1
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 6242bb49da0..27fbdebd13c 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-14.10.0
+14.12.0
diff --git a/Gemfile b/Gemfile
index 6631a889375..8a8c0a444a9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,12 +2,30 @@
source 'https://rubygems.org'
+if ENV['BUNDLER_CHECKSUM_VERIFICATION_OPT_IN'] # this verification is still experimental
+ $LOAD_PATH.unshift(File.expand_path("vendor/gems/bundler-checksum/lib", __dir__))
+ require 'bundler-checksum'
+ Bundler::Checksum.patch!
+end
+
gem 'bundler-checksum', '~> 0.1.0', path: 'vendor/gems/bundler-checksum', require: false
+# NOTE: When incrementing the major or minor version here, also increment activerecord_version
+# in vendor/gems/attr_encrypted/attr_encrypted.gemspec until we resolve
+# https://gitlab.com/gitlab-org/gitlab/-/issues/375713
gem 'rails', '~> 6.1.6.1'
gem 'bootsnap', '~> 1.13.0', require: false
+# Pin openssl to match the version bundled with our supported Rubies.
+# See https://stdgems.org/openssl/#gem-version.
+gem 'openssl', '2.2.1'
+# This gem was originally bundled with Ruby 2.7, but is unbundled as of Ruby 3.
+# Since the latest version caused problems with GitLab, we pin this to an older
+# version for now.
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/376417
+gem 'ipaddr', '1.2.2'
+
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'
@@ -19,13 +37,13 @@ gem 'view_component', '~> 2.71.0'
gem 'default_value_for', '~> 3.4.0'
# Supported DBs
-gem 'pg', '~> 1.4.0'
+gem 'pg', '~> 1.4.3'
gem 'rugged', '~> 1.2'
gem 'grape-path-helpers', '~> 1.7.1'
gem 'faraday', '~> 1.0'
-gem 'marginalia', '~> 1.10.0'
+gem 'marginalia', '~> 1.11.1'
# Authorization
gem 'declarative_policy', '~> 1.1.0'
@@ -38,18 +56,17 @@ gem 'doorkeeper', '~> 5.5.0.rc2'
gem 'doorkeeper-openid_connect', '~> 1.7.5'
gem 'rexml', '~> 3.2.5'
gem 'ruby-saml', '~> 1.13.0'
-gem 'omniauth-rails_csrf_protection'
gem 'omniauth', '~> 2.1.0'
gem 'omniauth-auth0', '~> 2.0.0'
-gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
+gem 'omniauth-azure-activedirectory-v2', '~> 2.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9', path: 'vendor/gems/omniauth-azure-oauth2' # See gem README.md
gem 'omniauth-cas3', '~> 1.1.4', path: 'vendor/gems/omniauth-cas3' # See vendor/gems/omniauth-cas3/README.md
gem 'omniauth-dingtalk-oauth2', '~> 1.0'
-gem 'omniauth-alicloud', '~> 1.0.1'
+gem 'omniauth-alicloud', '~> 2.0.0'
gem 'omniauth-facebook', '~> 4.0.0'
-gem 'omniauth-github', '2.0.0'
+gem 'omniauth-github', '2.0.1'
gem 'omniauth-gitlab', '~> 4.0.0', path: 'vendor/gems/omniauth-gitlab' # See vendor/gems/omniauth-gitlab/README.md
-gem 'omniauth-google-oauth2', '~> 1.0.1', path: 'vendor/gems/omniauth-google-oauth2' # See gem README.md
+gem 'omniauth-google-oauth2', '~> 1.1'
gem 'omniauth-oauth2-generic', '~> 0.2.2'
gem 'omniauth-saml', '~> 2.0.0'
gem 'omniauth-shibboleth', '~> 1.3.0'
@@ -59,7 +76,7 @@ gem 'omniauth-authentiq', '~> 0.3.3'
gem 'gitlab-omniauth-openid-connect', '~> 0.10.0', require: 'omniauth_openid_connect'
gem 'omniauth-salesforce', '~> 1.0.5', path: 'vendor/gems/omniauth-salesforce' # See gem README.md
gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
-gem 'rack-oauth2', '~> 1.21.2'
+gem 'rack-oauth2', '~> 1.21.3'
gem 'jwt', '~> 2.1.0'
# Kerberos authentication. EE-only
@@ -74,7 +91,7 @@ gem 'invisible_captcha', '~> 1.1.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 4.0.2'
gem 'rqrcode-rails3', '~> 0.1.7'
-gem 'attr_encrypted', '~> 3.1.0'
+gem 'attr_encrypted', '~> 3.2.4', path: 'vendor/gems/attr_encrypted'
gem 'u2f', '~> 0.2.1'
# GitLab Pages
@@ -101,7 +118,9 @@ gem 'net-ldap', '~> 0.16.3'
# API
gem 'grape', '~> 1.5.2'
gem 'grape-entity', '~> 0.10.0'
-gem 'rack-cors', '~> 1.1.0', require: 'rack/cors'
+gem 'rack-cors', '~> 1.1.1', require: 'rack/cors'
+gem 'grape-swagger', '~>1.5.0', group: [:development, :test]
+gem 'grape-swagger-entity', '~> 0.5.1', group: [:development, :test]
# GraphQL API
gem 'graphql', '~> 1.13.12'
@@ -149,7 +168,7 @@ gem 'seed-fu', '~> 2.3.7'
gem 'elasticsearch-model', '~> 7.2'
gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation'
gem 'elasticsearch-api', '7.13.3'
-gem 'aws-sdk-core', '~> 3.131.0'
+gem 'aws-sdk-core', '~> 3.159.0'
gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1.114.0'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
@@ -160,7 +179,7 @@ gem 'html-pipeline', '~> 2.13.2'
gem 'deckar01-task_list', '2.3.1'
gem 'gitlab-markup', '~> 1.8.0'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
-gem 'commonmarker', '~> 0.23.4'
+gem 'commonmarker', '~> 0.23.6'
gem 'kramdown', '~> 2.3.1'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.3.2'
@@ -175,7 +194,6 @@ gem 'rouge', '~> 3.30.0'
gem 'truncato', '~> 0.7.12'
gem 'bootstrap_form', '~> 4.2.0'
gem 'nokogiri', '~> 1.13.8'
-gem 'escape_utils', '~> 1.1'
# Calendar rendering
gem 'icalendar'
@@ -187,7 +205,7 @@ gem 'diff_match_patch', '~> 0.1.0'
# Application server
gem 'rack', '~> 2.2.4'
# https://github.com/zombocom/rack-timeout/blob/master/README.md#rails-apps-manually
-gem 'rack-timeout', '~> 0.6.0', require: 'rack/timeout/base'
+gem 'rack-timeout', '~> 0.6.3', require: 'rack/timeout/base'
group :puma do
gem 'puma', '~> 5.6.5', require: false
@@ -203,8 +221,8 @@ gem 'acts-as-taggable-on', '~> 9.0'
# Background jobs
gem 'sidekiq', '~> 6.4.0'
-gem 'sidekiq-cron', '~> 1.4.0'
-gem 'redis-namespace', '~> 1.8.1'
+gem 'sidekiq-cron', '~> 1.8.0'
+gem 'redis-namespace', '~> 1.9.0'
gem 'gitlab-sidekiq-fetcher', '0.8.0', require: 'sidekiq-reliable-fetch'
# Cron Parser
@@ -223,7 +241,7 @@ gem 'ruby-progressbar', '~> 1.10'
gem 'settingslogic', '~> 2.0.9'
# Linear-time regex library for untrusted regular expressions
-gem 're2', '~> 1.4.0'
+gem 're2', '~> 1.5.0'
# Misc
@@ -272,7 +290,7 @@ gem 'sanitize', '~> 6.0'
gem 'babosa', '~> 1.0.4'
# Sanitizes SVG input
-gem 'loofah', '~> 2.18.0'
+gem 'loofah', '~> 2.19.0'
# Working with license
# Detects the open source license the repository includes
@@ -292,7 +310,7 @@ gem 'fast_blank'
gem 'gitlab-chronic', '~> 0.10.5'
gem 'gitlab_chronic_duration', '~> 0.10.6.2'
-gem 'rack-proxy', '~> 0.7.2'
+gem 'rack-proxy', '~> 0.7.4'
gem 'sassc-rails', '~> 2.1.0'
gem 'autoprefixer-rails', '10.2.5.1'
@@ -307,7 +325,7 @@ gem 'base32', '~> 0.3.0'
gem 'gitlab-license', '~> 2.2.1'
# Protect against bruteforcing
-gem 'rack-attack', '~> 6.6.0'
+gem 'rack-attack', '~> 6.6.1'
# Sentry integration
gem 'sentry-raven', '~> 3.1'
@@ -317,7 +335,7 @@ gem 'sentry-sidekiq', '~> 5.1.1'
# PostgreSQL query parsing
#
-gem 'pg_query', '~> 2.1.0'
+gem 'pg_query', '~> 2.1.4'
gem 'premailer-rails', '~> 1.10.3'
@@ -347,12 +365,12 @@ gem 'prometheus-client-mmap', '~> 0.16', require: 'prometheus/client'
gem 'warning', '~> 1.3.0'
group :development do
- gem 'lefthook', '~> 1.1.1', require: false
+ gem 'lefthook', '~> 1.1.3', require: false
gem 'rubocop'
- gem 'solargraph', '~> 0.46.0', require: false
+ gem 'solargraph', '~> 0.47.2', require: false
gem 'letter_opener_web', '~> 2.0.0'
- gem 'lookbook', '~> 1.0'
+ gem 'lookbook', '~> 1.0', '>= 1.0.8'
# Better errors handler
gem 'better_errors', '~> 2.9.1'
@@ -382,7 +400,7 @@ group :development, :test do
gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 8.0.0', require: false
+ gem 'gitlab-styles', '~> 9.0.0', require: false
gem 'haml_lint', '~> 0.40.0', require: false
gem 'bundler-audit', '~> 0.7.0.1', require: false
@@ -406,7 +424,7 @@ group :development, :test do
gem 'sigdump', '~> 0.2.4', require: 'sigdump/setup'
- gem 'pact', '~> 1.12'
+ gem 'pact', '~> 1.63'
end
group :development, :test, :danger do
@@ -460,7 +478,6 @@ gem 'gitlab-mail_room', '~> 0.0.9', require: 'mail_room'
gem 'email_reply_trimmer', '~> 0.1'
gem 'html2text'
-gem 'ruby-prof', '~> 1.3.0'
gem 'stackprof', '~> 0.2.21', require: false
gem 'rbtrace', '~> 0.4', require: false
gem 'memory_profiler', '~> 0.9', require: false
@@ -495,7 +512,7 @@ gem 'grpc', '~> 1.42.0'
gem 'google-protobuf', '~> 3.21'
-gem 'toml-rb', '~> 2.0'
+gem 'toml-rb', '~> 2.2.0'
# Feature toggles
gem 'flipper', '~> 0.25.0'
@@ -519,8 +536,6 @@ gem 'retriable', '~> 3.1.2'
# LRU cache
gem 'lru_redux'
-gem 'erubi', '~> 1.9.0'
-
# Locked as long as quoted-printable encoding issues are not resolved
# Monkey-patched in `config/initializers/mail_encoding_patch.rb`
# See https://gitlab.com/gitlab-org/gitlab/issues/197386
@@ -556,3 +571,12 @@ gem 'ed25519', '~> 1.3.0'
# Error Tracking OpenAPI client
# See https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/rake_tasks.md#update-openapi-client-for-error-tracking-feature
gem 'error_tracking_open_api', path: 'vendor/gems/error_tracking_open_api'
+
+# Vulnerability advisories
+gem 'cvss-suite', '~> 3.0.1', require: 'cvss_suite'
+
+# Work with RPM packages
+gem 'arr-pm', '~> 0.0.12'
+
+# Apple plist parsing
+gem 'CFPropertyList'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 542a8d25fb6..afcbc5a6a65 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -1,4 +1,5 @@
[
+{"name":"CFPropertyList","version":"3.0.5","platform":"ruby","checksum":"a78551cd4768d78ebca98488c27e33652ef818be64697a54676d34e6434674a4"},
{"name":"RedCloth","version":"4.3.2","platform":"ruby","checksum":"1ee7bc55c8dcec92cf7741a2132a9a6cd19e4b884fbc1b3aca23e1a4fcd92d55"},
{"name":"acme-client","version":"2.0.11","platform":"ruby","checksum":"edf6da9f3c5dbe3ab0c6738eb3b97978b7a60e3500445480d2a72fcc610089de"},
{"name":"actioncable","version":"6.1.6.1","platform":"ruby","checksum":"11f079141cf032026881e4a79ae0cc93753351089c1b6ca1ed30a8a6a21f961b"},
@@ -14,11 +15,12 @@
{"name":"activestorage","version":"6.1.6.1","platform":"ruby","checksum":"3fbf4c355a69a46e14676004ad8e06245bdce7f96858e72782715218326aafc5"},
{"name":"activesupport","version":"6.1.6.1","platform":"ruby","checksum":"5fc9fd6fe6f755e7523bb3aaf4370fb91a8416b39e3202939fd8bded4fec606d"},
{"name":"acts-as-taggable-on","version":"9.0.0","platform":"ruby","checksum":"5a409be0eae125b7b02c1a7316264b40d4a583584a13d4ea4a6d82acdb351b86"},
-{"name":"addressable","version":"2.8.0","platform":"ruby","checksum":"f76d29d2d1f54b6c6a49aec58f9583b08d97e088c227a3fcba92f6c6531d5908"},
+{"name":"addressable","version":"2.8.1","platform":"ruby","checksum":"bc724a176ef02118c8a3ed6b5c04c39cf59209607ffcce77b91d0261dbadedfa"},
{"name":"aes_key_wrap","version":"1.1.0","platform":"ruby","checksum":"b935f4756b37375895db45669e79dfcdc0f7901e12d4e08974d5540c8e0776a5"},
{"name":"akismet","version":"3.0.0","platform":"ruby","checksum":"74991b8e3d3257eeea996b47069abb8da2006c84a144255123e8dffd1c86b230"},
{"name":"android_key_attestation","version":"0.3.0","platform":"ruby","checksum":"467eb01a99d2bb48ef9cf24cc13712669d7056cba5a52d009554ff037560570b"},
{"name":"apollo_upload_server","version":"2.1.0","platform":"ruby","checksum":"e5f3c9dda0c2ca775d007072742b98d517dfd91a667111fedbcdc94dfabd904e"},
+{"name":"arr-pm","version":"0.0.12","platform":"ruby","checksum":"fdff482f75239239201f4d667d93424412639aad0b3b0ad4d827e7c637e0ad39"},
{"name":"asana","version":"0.10.13","platform":"ruby","checksum":"36d0d37f8dd6118a54580f1b80224875d7b6a9027598938e1722a508bfc2d7ac"},
{"name":"asciidoctor","version":"2.0.17","platform":"ruby","checksum":"ed5b5e399e8d64994cc16f0983f993d6e33990909a8415b6fc8b786cdeb00f3d"},
{"name":"asciidoctor-include-ext","version":"0.4.0","platform":"ruby","checksum":"406adb9d2fbfc25536609ca13b787ed704dc06a4e49d6709b83f3bad578f7878"},
@@ -26,18 +28,17 @@
{"name":"asciidoctor-plantuml","version":"0.0.16","platform":"ruby","checksum":"407e47cd1186ded5ccc75f0c812e5524c26c571d542247c5132abb8f47bd1793"},
{"name":"ast","version":"2.4.2","platform":"ruby","checksum":"1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12"},
{"name":"atlassian-jwt","version":"0.2.0","platform":"ruby","checksum":"52e653e9d6062d7a740c3675b0e79fa08367927c6fc17f5476d1b6b3798c6eb2"},
-{"name":"attr_encrypted","version":"3.1.0","platform":"ruby","checksum":"4f0682604714ed4599cf00771ad27e82f0b51b0ed8644af51a43d21fbe129b59"},
{"name":"attr_required","version":"1.0.1","platform":"ruby","checksum":"024e10393bd30901e1adf6769bd756b873a5ef7da60f86f8f11066116b5742bc"},
{"name":"autoprefixer-rails","version":"10.2.5.1","platform":"ruby","checksum":"3711d67f1112361c7628847ac192d8aa6f3b8abe47527aee8a69dc8985e798ee"},
{"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"},
{"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"},
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
-{"name":"aws-partitions","version":"1.600.0","platform":"ruby","checksum":"23592386dd0bb34c38fae2714eb1ab5c18fbef714f22b042815a92fdd51fa733"},
+{"name":"aws-partitions","version":"1.644.0","platform":"ruby","checksum":"63791750839afff110c5b5a8805018c4275720d7a5c7ec79319d4d520c7da874"},
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
-{"name":"aws-sdk-core","version":"3.131.1","platform":"ruby","checksum":"481c602d682b61abccb4e9f5b64750907bb49758f6f31b3bec599819951a3f7a"},
+{"name":"aws-sdk-core","version":"3.159.0","platform":"ruby","checksum":"8863e2cdfd6816a0532ad9eb82a07b81b3d12667da747e9e82554e4dd7adb231"},
{"name":"aws-sdk-kms","version":"1.57.0","platform":"ruby","checksum":"ffd7dbb9b4251f29d4f508af761d0addd7035a346a88e3481cdb4dc548e51bd5"},
{"name":"aws-sdk-s3","version":"1.114.0","platform":"ruby","checksum":"ce0f71df1a7b0fb1f88d40a70636ef1a9b08e69fb560694c5dab3f4ac7efcde4"},
-{"name":"aws-sigv4","version":"1.5.0","platform":"ruby","checksum":"3f81c08bacabec6cbc77ebbbac755ca6132a74a4a3279afbde64db83796ce776"},
+{"name":"aws-sigv4","version":"1.5.1","platform":"ruby","checksum":"d68c87fff4ee843b4b92b23c7f31f957f254ec6eb064181f7119124aab8b8bb4"},
{"name":"azure-storage-blob","version":"2.0.3","platform":"ruby","checksum":"61b76118843c91776bd24bee22c74adafeb7c4bb3a858a325047dae3b59d0363"},
{"name":"azure-storage-common","version":"2.0.4","platform":"ruby","checksum":"608f4daab0e06b583b73dcffd3246ea39e78056de31630286b0cf97af7d6956b"},
{"name":"babosa","version":"1.0.4","platform":"ruby","checksum":"18dea450f595462ed7cb80595abd76b2e535db8c91b350f6c4b3d73986c5bc99"},
@@ -53,7 +54,7 @@
{"name":"benchmark-perf","version":"0.6.0","platform":"ruby","checksum":"fe2b01959f3de0f9dd34820d54ef881eb4f3589fccb7d17b63068ac92d7f9621"},
{"name":"benchmark-trend","version":"0.4.0","platform":"ruby","checksum":"de5a02a9f443babefbbd97784759820decee8554a0c273d859c02a0990845d81"},
{"name":"better_errors","version":"2.9.1","platform":"ruby","checksum":"39efc116ab04d6c4200052c5782936e4bd99906978d098992bce6bf81d054284"},
-{"name":"bindata","version":"2.4.10","platform":"ruby","checksum":"798b5e3ec00e9d562243076b819c16b1e226eb176d5b7b5cd21417bc3589981a"},
+{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_ninja","version":"0.2.3","platform":"java","checksum":"bbcf70b211d6e397493bf57c249bbec6aaf28fa7dafeb78e447b1b2f0610484f"},
{"name":"binding_ninja","version":"0.2.3","platform":"ruby","checksum":"4a85550a0066ee4721506b4e150857486808e50c9ddfeed04bdc896bb61eca9d"},
{"name":"bootsnap","version":"1.13.0","platform":"ruby","checksum":"c673282ec0f48506f093ca9acefe0f666d1ab9fda716e49fb95c9fe677653e78"},
@@ -79,9 +80,9 @@
{"name":"claide-plugins","version":"0.9.2","platform":"ruby","checksum":"c7ea78bc067ab23bce8515497cdcdcb8f01c86dadfbe13c44644e382922c1c2e"},
{"name":"coderay","version":"1.1.3","platform":"ruby","checksum":"dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b"},
{"name":"colored2","version":"3.1.2","platform":"ruby","checksum":"b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a"},
-{"name":"commonmarker","version":"0.23.4","platform":"ruby","checksum":"95d9cb050576376374a66d71a4feab3562e0955aab9d80a3e8606a5cf5e9c7ce"},
+{"name":"commonmarker","version":"0.23.6","platform":"ruby","checksum":"c8aeaaaff4ba497bf180f762db63a0069794fafb6eff221224c9c8199d337b38"},
{"name":"concurrent-ruby","version":"1.1.10","platform":"ruby","checksum":"244cb1ca0d91ec2c15ca2209507c39fb163336994428e16fbd3f465c87bd8e68"},
-{"name":"connection_pool","version":"2.2.5","platform":"ruby","checksum":"13a8fc3921ce4df8e04fb65f1037251decb08d74757b41163688bd1c1feccd39"},
+{"name":"connection_pool","version":"2.3.0","platform":"ruby","checksum":"677985be912f33c90f98f229aaa0c0ddb2ef8776f21929a36eeeb25251c944da"},
{"name":"contracts","version":"0.11.0","platform":"ruby","checksum":"df6e438efa89c31dd3095851c3f7a25dfdae36b35ff1d4547f1d92941b3c7286"},
{"name":"cork","version":"0.3.0","platform":"ruby","checksum":"a0a0ac50e262f8514d1abe0a14e95e71c98b24e3378690e5d044daf0013ad4bc"},
{"name":"cose","version":"1.0.0","platform":"ruby","checksum":"520ebaad97b56d2873de02ff4e2c973f5e77ce2f8edbda454af9ee3073643bc0"},
@@ -90,7 +91,8 @@
{"name":"crass","version":"1.0.6","platform":"ruby","checksum":"dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d"},
{"name":"creole","version":"0.5.0","platform":"ruby","checksum":"951701e2d80760f156b1cb2a93471ca97c076289becc067a33b745133ed32c03"},
{"name":"crystalball","version":"0.7.0","platform":"ruby","checksum":"6e729f372a5071daec877adb40c5df4cb25fe21f350635e2a9624373fc151ef2"},
-{"name":"css_parser","version":"1.11.0","platform":"ruby","checksum":"568926c3193579446ad3e3f9d761c73e2918ee5b3b7757a1a49ec166c67d6de1"},
+{"name":"css_parser","version":"1.12.0","platform":"ruby","checksum":"8b7c04bca32257da0c65bd7b1fa585df5a0fd9f5197ccd78498d5598dd900784"},
+{"name":"cvss-suite","version":"3.0.1","platform":"ruby","checksum":"b5ca9e9e94032a42fd0dc28c1e305378b62c949e35ed7111fc4a1d76f68ad3f9"},
{"name":"danger","version":"8.6.1","platform":"ruby","checksum":"d95eb58b41f68d3aaa9bbef697916b6b4d161a38819517c98562531be75cdfd8"},
{"name":"danger-gitlab","version":"8.0.0","platform":"ruby","checksum":"497dd7d0f6513913de651019223d8058cf494df10acbd17de92b175dfa04a3a8"},
{"name":"database_cleaner","version":"1.7.0","platform":"ruby","checksum":"bdf833c197afac7054015bcde2567c3834c366bbfe6a377c30151ca984b32016"},
@@ -133,12 +135,13 @@
{"name":"email_reply_trimmer","version":"0.1.6","platform":"ruby","checksum":"9fede222ce660993e4e2e3dad282535ceb7914e246eb8302c19aa9e021f7326e"},
{"name":"email_spec","version":"2.2.0","platform":"ruby","checksum":"60b7980580a835e7f676db60667f17a2d60e8e0e39c26d81cfc231805c544d79"},
{"name":"encryptor","version":"3.0.0","platform":"ruby","checksum":"abf23f94ab4d864b8cea85b43f3432044a60001982cda7c33c1cd90da8db1969"},
-{"name":"erubi","version":"1.9.0","platform":"ruby","checksum":"7d84d6037396418c4ba30bc40ed7a0aec9beb567ce55bcecb12e8c0cb1ed9fdb"},
+{"name":"erubi","version":"1.11.0","platform":"ruby","checksum":"fda72d577feaf3bdcd646d33fa630be5f92f48e179a9278e4175a9cec20e7f85"},
{"name":"escape_utils","version":"1.2.1","platform":"ruby","checksum":"e5292fe8d7e12a9bcb4502d99e28fb602e4e1514690d98a1c4957f6f77b4b162"},
{"name":"et-orbi","version":"1.2.7","platform":"ruby","checksum":"3b693d47f94a4060ccc07e60adda488759b1e8b9228a633ebbad842dfc245fb4"},
{"name":"ethon","version":"0.15.0","platform":"ruby","checksum":"0809805a035bc10f54162ca99f15ded49e428e0488bcfe1c08c821e18261a74d"},
{"name":"excon","version":"0.90.0","platform":"ruby","checksum":"01beac0f20652b12de95aef931f72bcb82ffb009e1c34c42a5cf5df93f4070ae"},
{"name":"execjs","version":"2.8.1","platform":"ruby","checksum":"6d939919cfd81bcc4d6556f322c3995a70cfe4289ea0bd3b1f999b489c323088"},
+{"name":"expgen","version":"0.1.1","platform":"ruby","checksum":"4e6a0f65b210a201d6045debb3e62a24e33251a49f81a11b067d303a60d3a239"},
{"name":"expression_parser","version":"0.9.0","platform":"ruby","checksum":"2b56db3cffc48c3337f4f29f5bc2374c86e7ba29acb40269c74bb55af9f868a4"},
{"name":"extended-markdown-filter","version":"0.6.0","platform":"ruby","checksum":"46844b5740b1703a0e0674e31a17c83d1244a3198abb3aae51cad1eb152eb19e"},
{"name":"factory_bot","version":"6.2.0","platform":"ruby","checksum":"d181902cdda531cf6cef036001b3a700a7b5e04bac63976864530120b2ac7d13"},
@@ -205,31 +208,33 @@
{"name":"gitlab-labkit","version":"0.24.0","platform":"ruby","checksum":"8f16e5aa4e0a05be58958fe880bdd53c84b659a081ea9981d2b510922a4a0548"},
{"name":"gitlab-license","version":"2.2.1","platform":"ruby","checksum":"39fcf6be8b2887df8afe01b5dcbae8d08b7c5d937ff56b0fb40484a8c4f02d30"},
{"name":"gitlab-mail_room","version":"0.0.9","platform":"ruby","checksum":"6700374b5c0aa9d9ad4e711aeb677f0b7d415a6d01d3baa699efab25349d851c"},
-{"name":"gitlab-markup","version":"1.8.0","platform":"ruby","checksum":"fb629369dca5dd343e47ebf5fa2e0a0fc146012fc49c35eff5ca826ae4186c86"},
+{"name":"gitlab-markup","version":"1.8.1","platform":"ruby","checksum":"ab1f9fd016977497c2af25b76341dea670533014f406861834a0bd99f646707b"},
{"name":"gitlab-net-dns","version":"0.9.1","platform":"ruby","checksum":"bcd1a08dcb31b731e8ff602d828de619d2d9f53f5812f6abacf11c720873d4cb"},
{"name":"gitlab-omniauth-openid-connect","version":"0.10.0","platform":"ruby","checksum":"ea44a23ea93457057bba6a9912e883f5aefab36a941c6c58512c8a7095fb1153"},
{"name":"gitlab-sidekiq-fetcher","version":"0.8.0","platform":"ruby","checksum":"9c564caa2a958d44a8d78672dc23b2a206102d0223b41b77b58626a945e37362"},
-{"name":"gitlab-styles","version":"8.0.0","platform":"ruby","checksum":"ff77d8543b7093e387430ebdaa2adce9dc3caaa8b10ce9bf9b40242d5f7b66da"},
+{"name":"gitlab-styles","version":"9.0.0","platform":"ruby","checksum":"ef0edfab8f807a5be2309ba24dfc44fec5ba52ed68b87167c051e9ffdadb3bad"},
{"name":"gitlab_chronic_duration","version":"0.10.6.2","platform":"ruby","checksum":"6dda4cfe7dca9b958f163ac8835c3d9cc70cf8df8cbb89bb2fbf9ba4375105fb"},
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
{"name":"globalid","version":"1.0.0","platform":"ruby","checksum":"1253641b1dc3392721c964351773755d75135d3d3c5cc65d88b0a3880a60bed8"},
{"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"},
{"name":"google-api-client","version":"0.50.0","platform":"ruby","checksum":"3ae45e972f293f3a66e53950ecc0fd350d85d6347c06a430bb971bd1ae5ad617"},
{"name":"google-cloud-env","version":"1.6.0","platform":"ruby","checksum":"6179acb946975892c7908748df5722a4ebadfc8cf5bb7b0d8d933ca67183fa15"},
-{"name":"google-protobuf","version":"3.21.5","platform":"java","checksum":"f63a511439c6350823790d1c8d903a7b536549bbc3eec21160aff3ee5594dcc3"},
-{"name":"google-protobuf","version":"3.21.5","platform":"ruby","checksum":"c94bee502390041d0f5c6fd4b776118656c5b54521c2a5c7957686de6ba95bfb"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x64-mingw-ucrt","checksum":"cf17273c5d5d33fc4c4879ba8aa5973aa9e34f879d728c461facf5da24db7745"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x64-mingw32","checksum":"677a4c0770446e0b08828da6b8c021469551639cfb2b489f3d3f32da435bd6e8"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x86-linux","checksum":"cdaa147bbb7e5fd59adc2aba167b7965221013a39830494f616974e97db02a42"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x86-mingw32","checksum":"eda2bd51324e855a1593aa0c805d1c99a95dcc5161bc61eb6e8afb5d4e7bcb75"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x86_64-darwin","checksum":"4e2c937e5dc991a5675e4b78d6132e818862f19479013c2edc2455c76b54be53"},
-{"name":"google-protobuf","version":"3.21.5","platform":"x86_64-linux","checksum":"ec2dabea012d31dd99f450174be461f9323b4e97460af13cc3a4f9426c2b0fc0"},
+{"name":"google-protobuf","version":"3.21.7","platform":"java","checksum":"e8a0d10014d18f741afc4882035badbd08558e6f46e09cd937b6ea254881314a"},
+{"name":"google-protobuf","version":"3.21.7","platform":"ruby","checksum":"8d501659c77d159fde20f983f7272ce4c28339f6412c480e4eb98c1ccb52cc62"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x64-mingw-ucrt","checksum":"35dc328caf1c843ae25ec1a4825ded8a71b8f4750449bd8d8e1664ae0dcdc240"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x64-mingw32","checksum":"c9ea241dc186823ceba2abf9952a609668d38a729dd92f0ec744ff67fb60ab30"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x86-linux","checksum":"02a1212e6e62e5927649124bdc6315dd54256059b3a7aed119811ceaef85c310"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x86-mingw32","checksum":"509529f9231a6b61c97c26e12938054007be8a1dacb83dcd3b3a385107ce60cc"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x86_64-darwin","checksum":"93754c1366a3ecbd69bec241ab531a01aa05640577a2c0e52e671bdcb194f19f"},
+{"name":"google-protobuf","version":"3.21.7","platform":"x86_64-linux","checksum":"9c7a49bb1cdbb17c039297d9aff8515245868f3ad86ebf274e4c0fd6fd9263be"},
{"name":"googleapis-common-protos-types","version":"1.3.0","platform":"ruby","checksum":"c5411f3197cc3e02547ded1858303b1f830b4dc89c588c142ad6c8a231050671"},
{"name":"googleauth","version":"0.14.0","platform":"ruby","checksum":"4659b563d5b2727e775ba9231e75485c1b55ac8fc319e0bf1bc87d5e9705a632"},
{"name":"gpgme","version":"2.0.20","platform":"ruby","checksum":"fc194689cff40cd4ccafb3086031e930650b3efc15348bbfdf7a2f8b5a826f75"},
{"name":"grape","version":"1.5.2","platform":"ruby","checksum":"1df3b734c3862e235174232bc629587eddda9ef3df648230827575186700ae29"},
{"name":"grape-entity","version":"0.10.0","platform":"ruby","checksum":"9aed1e7cbbc96d9e73f72e5f32c776d4ba8a5baf54c3acda2682008dba2b2cfe"},
{"name":"grape-path-helpers","version":"1.7.1","platform":"ruby","checksum":"2e27271a20d4073e3a3b2b955425c7f803e198be3ba8f6e59e3d59643c5381e2"},
+{"name":"grape-swagger","version":"1.5.0","platform":"ruby","checksum":"9c885b326ab0644abecf7df4ce866abc2411f359cfd59cbcca545b9b3b25c8ff"},
+{"name":"grape-swagger-entity","version":"0.5.1","platform":"ruby","checksum":"f51e372d00ac96cf90d948f87b3f4eb287ab053976ca57ad503d442ad8605523"},
{"name":"grape_logging","version":"1.8.4","platform":"ruby","checksum":"efcc3e322dbd5d620a68f078733b7db043cf12680144cd03c982f14115c792d1"},
{"name":"graphiql-rails","version":"1.8.0","platform":"ruby","checksum":"02e2c5098be2c6c29219a0e9b2910a2cd3c494301587a3199a7c4484d8038ed1"},
{"name":"graphlient","version":"0.5.0","platform":"ruby","checksum":"0f2c9416142e50b6bd4edcd86fe6810f792951732c487f9061aee6d420e0f292"},
@@ -256,7 +261,7 @@
{"name":"hashdiff","version":"1.0.1","platform":"ruby","checksum":"2cd4d04f5080314ecc8403c4e2e00dbaa282dff395e2d031bc16c8d501bdd6db"},
{"name":"hashie","version":"4.1.0","platform":"ruby","checksum":"7890dcb9ec18a4b66acec797018c73824b89cef5eb8cda36e8e8501845e87a09"},
{"name":"hashie-forbidden_attributes","version":"0.1.1","platform":"ruby","checksum":"3a6ed37f3a314e4fb1dd1e2df6eb7721bcadd023a30bc0b951b2b5285a790fb2"},
-{"name":"health_check","version":"3.0.0","platform":"ruby","checksum":"1b336c5c49036a993153e75c8d14e9742377fb9b7361c0a6af2e5fedb45b991f"},
+{"name":"health_check","version":"3.1.0","platform":"ruby","checksum":"10146508237dc54ed7e24c292d8ba7fb8f9590cf26c66e325b947438c4103b57"},
{"name":"heapy","version":"0.2.0","platform":"ruby","checksum":"74141e845d61ffc7c1e8bf8b127c8cf94544ec7a1181aec613288682543585ea"},
{"name":"html-pipeline","version":"2.13.2","platform":"ruby","checksum":"a1de83f7bd2d3464f3a068e391b661983fc6099d194c8d9ceb91ace02dadb803"},
{"name":"html2text","version":"0.2.0","platform":"ruby","checksum":"31c2f0be9ab7aa4fc780b07d5f84882ebc22a9024c29a45f4f5adfe42e92ad4f"},
@@ -274,6 +279,7 @@
{"name":"icalendar","version":"2.4.1","platform":"ruby","checksum":"ade7384b3a78d302e01c0b93f66816b734c9abd85d1511b90200de2eee6d5ef7"},
{"name":"imagen","version":"0.1.8","platform":"ruby","checksum":"fde7b727d4fe79c6bb5ac46c1f7184bf87a6d54df54d712ad2be039d2f93a162"},
{"name":"invisible_captcha","version":"1.1.0","platform":"ruby","checksum":"3670294a998ab1430ff07cd1697d25c70e6367bdb0dff534df24a14fdee8b4d2"},
+{"name":"ipaddr","version":"1.2.2","platform":"ruby","checksum":"27916ee6367d549850d3675bc020f1f1ddafbbe1cfc58635f17dfa56c42f9f79"},
{"name":"ipaddress","version":"0.8.3","platform":"ruby","checksum":"85640c4f9194c26937afc8c78e3074a8e7c97d5d1210358d1440f01034d006f5"},
{"name":"jaeger-client","version":"1.1.0","platform":"ruby","checksum":"cb5e9b9bbee6ee8d6a82d03d947a5b04543d8c0a949c22e484254f18d8a458a8"},
{"name":"jaro_winkler","version":"1.5.4","platform":"java","checksum":"0454333a50b44a09745878bfe57859893631ff7dfe48c029827894944514fe7c"},
@@ -283,7 +289,7 @@
{"name":"js_regex","version":"3.7.0","platform":"ruby","checksum":"b13fac68c4416d1a5f21c3bab8a71b4530f424b7c4ff9f46d8e62b895dc05975"},
{"name":"json","version":"2.5.1","platform":"java","checksum":"be284a0c4a9d0373e81b0d5dfe71ed5b18d0479f05970e60a77be89a2978ce6c"},
{"name":"json","version":"2.5.1","platform":"ruby","checksum":"918d8c41dacb7cfdbe0c7bbd6014a5372f0cf1c454ca150e9f4010fe80cc3153"},
-{"name":"json-jwt","version":"1.13.0","platform":"ruby","checksum":"b9bded80ba687e59d199db365731494ee68214f27d0d7be5b635b9956b98eb5b"},
+{"name":"json-jwt","version":"1.15.3","platform":"ruby","checksum":"66db4f14e538a774c15502a5b5b26b1f3e7585481bbb96df490aa74b5c2d6110"},
{"name":"json_schemer","version":"0.2.18","platform":"ruby","checksum":"3362c21efbefdd12ce994e541a1e7fdb86fd267a6541dd8715e8a580fe3b6be6"},
{"name":"jsonpath","version":"1.1.2","platform":"ruby","checksum":"6804124c244d04418218acb85b15c7caa79c592d7d6970195300428458946d3a"},
{"name":"jwt","version":"2.1.0","platform":"ruby","checksum":"7e7e7ffc1a5ebce628ac7da428341c50615a3a10ac47bb74c22c1cba325613f0"},
@@ -297,7 +303,7 @@
{"name":"kramdown-parser-gfm","version":"1.1.0","platform":"ruby","checksum":"fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729"},
{"name":"kubeclient","version":"4.9.3","platform":"ruby","checksum":"d5d38e719fbac44f396851aa57cd1b9f4f7dab4410ab680ccd21c9b741230046"},
{"name":"launchy","version":"2.5.0","platform":"ruby","checksum":"954243c4255920982ce682f89a42e76372dba94770bf09c23a523e204bdebef5"},
-{"name":"lefthook","version":"1.1.1","platform":"ruby","checksum":"fa7dcd2c55dc14f6f164f96cf1404e712be84a2ac256e75947213093e080d05b"},
+{"name":"lefthook","version":"1.1.3","platform":"ruby","checksum":"3f8337b2176f49e6d4ab8f0f4494c8d1be0548d79bca898fbf2184d717092b75"},
{"name":"letter_opener","version":"1.7.0","platform":"ruby","checksum":"095bc0d58e006e5b43ea7d219e64ecf2de8d1f7d9dafc432040a845cf59b4725"},
{"name":"letter_opener_web","version":"2.0.0","platform":"ruby","checksum":"33860ad41e1785d75456500e8ca8bba8ed71ee6eaf08a98d06bbab67c5577b6f"},
{"name":"libyajl2","version":"1.2.0","platform":"ruby","checksum":"1117cd1e48db013b626e36269bbf1cef210538ca6d2e62d3fa3db9ded005b258"},
@@ -307,13 +313,13 @@
{"name":"locale","version":"2.1.3","platform":"ruby","checksum":"b6ddee011e157817cb98e521b3ce7cb626424d5882f1e844aafdee3e8b212725"},
{"name":"lockbox","version":"0.6.2","platform":"ruby","checksum":"0136677875c3d6e27cef87cd7bd66610404e2b3cd7f07f1ac8ed34e48f18dc3c"},
{"name":"lograge","version":"0.11.2","platform":"ruby","checksum":"4cbd1554b86f545d795eff15a0c24fd25057d2ac4e1caa5fc186168b3da932ef"},
-{"name":"loofah","version":"2.18.0","platform":"ruby","checksum":"61975a247a6aeb8f09ac5a3430305451efc4525c0b9b79c05feaec35a8b9d5a3"},
-{"name":"lookbook","version":"1.0.3","platform":"ruby","checksum":"c53e130a37588e32f66be3b9418b1efcb51bef69946b276edd3b4348a71cbcd6"},
+{"name":"loofah","version":"2.19.0","platform":"ruby","checksum":"302791371f473611e342f9e469e7f2fbf1155bb1b3a978a83ac7df625298feba"},
+{"name":"lookbook","version":"1.0.8","platform":"ruby","checksum":"e4b8789c5ff25c6443394da1d6b62966642c324e19c42d7f4cf3b5da2fe75f77"},
{"name":"lru_redux","version":"1.1.0","platform":"ruby","checksum":"ee71d0ccab164c51de146c27b480a68b3631d5b4297b8ffe8eda1c72de87affb"},
{"name":"lumberjack","version":"1.2.7","platform":"ruby","checksum":"a5c6aae6b4234f1420dbcd80b23e3bca0817bd239440dde097ebe3fa63c63b1f"},
{"name":"mail","version":"2.7.1","platform":"ruby","checksum":"ec2a3d489f7510b90d8eaa3f6abaad7038cf1d663cdf8ee66d0214a0bdf99c03"},
{"name":"marcel","version":"1.0.2","platform":"ruby","checksum":"a013b677ef46cbcb49fd5c59b3d35803d2ee04dd75d8bfdc43533fc5a31f7e4e"},
-{"name":"marginalia","version":"1.10.0","platform":"ruby","checksum":"68289091ee493e1a8f22369c245f250652a6538e497fdeef68cb2a2490830380"},
+{"name":"marginalia","version":"1.11.1","platform":"ruby","checksum":"cb63212ab63e42746e27595e912cb20408a1a28bcd0edde55d15b7c45fa289cf"},
{"name":"memoist","version":"0.16.2","platform":"ruby","checksum":"a52c53a3f25b5875151670b2f3fd44388633486dc0f09f9a7150ead1e3bf3c45"},
{"name":"memory_profiler","version":"0.9.14","platform":"ruby","checksum":"de558cf6525d8d56d2c0ea465b1664517fbe45560f892dc7a898d3b8c2863b12"},
{"name":"method_source","version":"1.0.0","platform":"ruby","checksum":"d779455a2b5666a079ce58577bfad8534f571af7cec8107f4dce328f0981dede"},
@@ -364,48 +370,48 @@
{"name":"notiffany","version":"0.1.3","platform":"ruby","checksum":"d37669605b7f8dcb04e004e6373e2a780b98c776f8eb503ac9578557d7808738"},
{"name":"numerizer","version":"0.2.0","platform":"ruby","checksum":"e58076d5ee5370417b7e52d9cb25836d62acd1b8d9a194c308707986c1705d7b"},
{"name":"oauth","version":"0.5.6","platform":"ruby","checksum":"4085fe28e0c5e2434135e00a6555294fd2a4ff96a98d1bdecdcd619fc6368dff"},
-{"name":"oauth2","version":"2.0.3","platform":"ruby","checksum":"b343d8665a936b4223b335b38f8640134ce14e07c540b8d17e8bbac0b4e5c41b"},
+{"name":"oauth2","version":"2.0.9","platform":"ruby","checksum":"b21f9defcf52dc1610e0dfab4c868342173dcd707fd15c777d9f4f04e153f7fb"},
{"name":"octokit","version":"4.25.1","platform":"ruby","checksum":"c02092ee82dcdfe84db0e0ea630a70d32becc54245a4f0bacfd21c010df09b96"},
{"name":"ohai","version":"16.10.6","platform":"ruby","checksum":"b835806e585faea4ac8346b68c722fb5fc29a29f73fd7e3a022f9073132dec22"},
{"name":"oj","version":"3.13.21","platform":"ruby","checksum":"aef31a8dcc6f0b9b4bb5cc7ac6cc5272b2d851deb11a1804c2ed6b5501b50e46"},
{"name":"omniauth","version":"2.1.0","platform":"ruby","checksum":"bff7234f5ec9323622b217c7f26d52f850de0b0e2b8c807c3358fc79fe572300"},
-{"name":"omniauth-alicloud","version":"1.0.1","platform":"ruby","checksum":"2f81ec0b8f98d2ab5e5d64555c75ace46582cf27c4ef4207aa59f15331dd697a"},
+{"name":"omniauth-alicloud","version":"2.0.0","platform":"ruby","checksum":"8ecf369d51cd5317c1e7c6b80276891f76cff210a534ec654326af5c62265de3"},
{"name":"omniauth-atlassian-oauth2","version":"0.2.0","platform":"ruby","checksum":"eb07574a188ab8a03376ce288bce86bc2dd4a1382ffa5781cb5e2b7bc15d76c9"},
{"name":"omniauth-auth0","version":"2.0.0","platform":"ruby","checksum":"823769be7883b45b2fa94367c2f6a17f7b3b1333986016089c016d45827da545"},
{"name":"omniauth-authentiq","version":"0.3.3","platform":"ruby","checksum":"11b3791085a130782bf14b0088653beeb085638a9548d7110a57d3cbbb54fb4c"},
-{"name":"omniauth-azure-activedirectory-v2","version":"1.0.0","platform":"ruby","checksum":"edcdd77ace89ae3a0ed4b3d350b64a0c81b5a2435dff6f8eda8cbce15cbf69df"},
+{"name":"omniauth-azure-activedirectory-v2","version":"2.0.0","platform":"ruby","checksum":"c484cedd52cd233e3c216c4b3ed667ec07d20e51c550a613b65a0f90fe8ad072"},
{"name":"omniauth-dingtalk-oauth2","version":"1.0.1","platform":"ruby","checksum":"6545670f1c38344eaf960df9750c550a9534f790f888af088761a9e04269139b"},
{"name":"omniauth-facebook","version":"4.0.0","platform":"ruby","checksum":"05ae3565c8fdb38df8dab04eb8ca854ea6c18e81591d3e6598ce101293a2f20f"},
-{"name":"omniauth-github","version":"2.0.0","platform":"ruby","checksum":"1ca26576125a97e27d3f8dc39cd98853d7382dd0fc04a40d3b9ec345ee378649"},
+{"name":"omniauth-github","version":"2.0.1","platform":"ruby","checksum":"8ff8e70ac6d6db9d52485eef52cfa894938c941496e66b52b5e2773ade3ccad4"},
+{"name":"omniauth-google-oauth2","version":"1.1.1","platform":"ruby","checksum":"4496f126e84eaf760f9c6a5c69e5e7511f98092d7f25ad79fd2c0ae5e09b5039"},
{"name":"omniauth-oauth","version":"1.2.0","platform":"ruby","checksum":"e7a78658498dc83aa3f3be1a776425c0f06a60d45d9236dbe5e98e61fadf827b"},
-{"name":"omniauth-oauth2","version":"1.7.3","platform":"ruby","checksum":"3f5a8f99fa72e0f91d2abd7475ceb972a4ae67ed59e049f314c0c1bad81f4745"},
-{"name":"omniauth-oauth2-generic","version":"0.2.2","platform":"ruby","checksum":"e30814f6c472e04f3d9e4a3ddc03bc9a46f53f9333f8d443bf3ad43c6ebcdbd4"},
-{"name":"omniauth-rails_csrf_protection","version":"1.0.1","platform":"ruby","checksum":"fc546aeb7d43b7b9d7737051c380156e61c8f080b898cd4934d523eaa7e59acf"},
+{"name":"omniauth-oauth2","version":"1.8.0","platform":"ruby","checksum":"b2f8e9559cc7e2d4efba57607691d6d2b634b879fc5b5b6ccfefa3da85089e78"},
+{"name":"omniauth-oauth2-generic","version":"0.2.8","platform":"ruby","checksum":"ce6e8539019d5ebf2f48867072b9f248f148bb4cbe7166dee655865abfae7613"},
{"name":"omniauth-saml","version":"2.0.0","platform":"ruby","checksum":"02594fd6630de26a9e65a2e64223e9ad32324fa97a6c7f1f22a1553ea3dd44c7"},
{"name":"omniauth-shibboleth","version":"1.3.0","platform":"ruby","checksum":"b0bb725ced5cb76fbfc187ddbb8ad6864d0cd5df714cab36a528df8ee4b1d113"},
{"name":"omniauth-twitter","version":"1.4.0","platform":"ruby","checksum":"c5cc6c77cd767745ffa9ebbd5fbd694a3fa99d1d2d82a4d7def0bf3b6131b264"},
{"name":"open4","version":"1.3.4","platform":"ruby","checksum":"a1df037310624ecc1ea1d81264b11c83e96d0c3c1c6043108d37d396dcd0f4b1"},
{"name":"openid_connect","version":"1.3.0","platform":"ruby","checksum":"a796855096850cc01140e37ea6ae9fd14f2be818b9b5bc698418063dfe228770"},
-{"name":"openssl","version":"2.2.0","platform":"ruby","checksum":"1cdcbd35c7977647d7583def720aed15111cd29b326b737aa0c72b38bff58b0f"},
+{"name":"openssl","version":"2.2.1","platform":"ruby","checksum":"f6afbf4b66f3fcd3c08dc1da1ddd2245b76c19d0ea2dd7e2c8b55794ca1a7d72"},
{"name":"openssl-signature_algorithm","version":"0.4.0","platform":"ruby","checksum":"e53a225b773784935249cf4c61238c6cf0e1e464e78ae2f8ddaf995fb22ca991"},
{"name":"opentracing","version":"0.5.0","platform":"ruby","checksum":"deb5d7abe6b0e7631d866d8cb5ee7bb9352650a504a32f61591302bc510b9286"},
{"name":"optimist","version":"3.0.1","platform":"ruby","checksum":"336b753676d6117cad9301fac7e91dab4228f747d4e7179891ad3a163c64e2ed"},
{"name":"org-ruby","version":"0.9.12","platform":"ruby","checksum":"93cbec3a4470cb9dca6a4a98dc276a6434ea9d9e7bc2d42ea33c3aedd5d1c974"},
{"name":"orm_adapter","version":"0.5.0","platform":"ruby","checksum":"aa5d0be5d540cbb46d3a93e88061f4ece6a25f6e97d6a47122beb84fe595e9b9"},
{"name":"os","version":"1.1.1","platform":"ruby","checksum":"3db1fbc14ab8ea99b69ed8e353c894613e1b35e665fffb90414996cf8989d489"},
-{"name":"pact","version":"1.59.0","platform":"ruby","checksum":"6272cea35e4ee809493fadcba9800d4a24c262ef0778a0d1ba5d9a9b3f61fc59"},
-{"name":"pact-mock_service","version":"3.6.2","platform":"ruby","checksum":"cc91229484ae428b6eb3a6673c178046cbf6610ee6536ca6cbac060b6071f547"},
-{"name":"pact-support","version":"1.15.1","platform":"ruby","checksum":"c364596fe9fe78c4f93028013262d5d97867a680fa6acc35dda946447cdf1d1f"},
+{"name":"pact","version":"1.63.0","platform":"ruby","checksum":"cc2991ed242bf182c6a4abadfd492b2923d09a9b3ed24578126cc056921cb151"},
+{"name":"pact-mock_service","version":"3.10.0","platform":"ruby","checksum":"898ec3b8d96f1934d15941c701ca7d5fef5ccff32022d9a196fb82073cd95e27"},
+{"name":"pact-support","version":"1.18.1","platform":"ruby","checksum":"4a25961c8b1c4132e433a8eaa838b1e6914c6d3aae48eee705b9860a5e8b0476"},
{"name":"parallel","version":"1.22.1","platform":"ruby","checksum":"ebdf1f0c51f182df38522f70ba770214940bef998cdb6e00f36492b29699761f"},
{"name":"parser","version":"3.1.2.1","platform":"ruby","checksum":"57e49821b52d5fe7baffaca44ed77e9754688c9bbc68443b5293a722fdb161e0"},
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},
-{"name":"pg","version":"1.4.1","platform":"ruby","checksum":"386bbffad223cce1dda903dad2c59268e41f3d183792506671ae526011ff0487"},
-{"name":"pg","version":"1.4.1","platform":"x64-mingw-ucrt","checksum":"de35769d4e7c25daa035f2dc33447e74711ab0dc8b73f685a846987e0080d030"},
-{"name":"pg","version":"1.4.1","platform":"x64-mingw32","checksum":"3457bf6bfdda7144097ef23d490a83980ba4572c78c58689aadaf58940a1989d"},
-{"name":"pg","version":"1.4.1","platform":"x86-mingw32","checksum":"323d09138b7bbfc6ae8eb427774d3639fc0e995983e65bb729527bf8e859fc29"},
-{"name":"pg_query","version":"2.1.3","platform":"ruby","checksum":"f3dd4b4c88c638eab48e9274f0dd88c584b60f8da58e3008b873192fe1e47001"},
+{"name":"pg","version":"1.4.3","platform":"ruby","checksum":"ab0219cdd9e5750abb04b8bca5a5a490f60abdf37503027fd2f90d0c2d31f2fa"},
+{"name":"pg","version":"1.4.3","platform":"x64-mingw-ucrt","checksum":"9f4d1d39af5ae5eea9f3c6b1e3092cbd5d26b716ff0e1283cf71c0690c69b36c"},
+{"name":"pg","version":"1.4.3","platform":"x64-mingw32","checksum":"3265afd0e00331c7c70e50d4a13eea9083e5b683ebcd808bd671af70d92b189e"},
+{"name":"pg","version":"1.4.3","platform":"x86-mingw32","checksum":"08a6ef4c702e313c1a04ad6b088b1843361ca8606843c7cd607e181e0d4e5508"},
+{"name":"pg_query","version":"2.1.4","platform":"ruby","checksum":"48f1363f88cf9d86fa11d76d1b0f839ca3723b8bd397b7cbc4b578e1ca82d0bb"},
{"name":"plist","version":"3.6.0","platform":"ruby","checksum":"f468bcf6b72ec6d1585ed6744eb4817c1932a5bf91895ed056e69b7f12ca10f2"},
{"name":"png_quantizator","version":"0.2.1","platform":"ruby","checksum":"6023d4d064125c3a7e02929c95b7320ed6ac0d7341f9e8de0c9ea6576ef3106b"},
{"name":"po_to_json","version":"1.0.1","platform":"ruby","checksum":"6a7188aa6c42a22c9718f9b39062862ef7f3d8f6a7b4177cae058c3308b56af7"},
@@ -418,7 +424,7 @@
{"name":"pry-byebug","version":"3.9.0","platform":"ruby","checksum":"3bba08f97fea15b89cc299f3b5136e3b85763cd18cf84960eac4fbfbeb2ede24"},
{"name":"pry-rails","version":"0.3.9","platform":"ruby","checksum":"468662575abb6b67f4a9831219f99290d5eae7bf186e64dd810d0a3e4a8cc4b1"},
{"name":"pry-shell","version":"0.5.1","platform":"ruby","checksum":"2b9000e30677acf5d66f55fa53d31934b7c069d9e0f738a0b84eed03a4ab677d"},
-{"name":"public_suffix","version":"4.0.7","platform":"ruby","checksum":"8be161e2421f8d45b0098c042c06486789731ea93dc3a896d30554ee38b573b8"},
+{"name":"public_suffix","version":"5.0.0","platform":"ruby","checksum":"26ee4fbce33ada25eb117ac71f2c24bf4d8b3414ab6b34f05b4708a3e90f1c6b"},
{"name":"puma","version":"5.6.5","platform":"java","checksum":"29d78fc2bc070b9db285a3334a890c3e0ece9bb369388065f0f340ccb1e57faf"},
{"name":"puma","version":"5.6.5","platform":"ruby","checksum":"661029d15a115e9f6c0641a69c830ffd9f1b9ac63fcd0791d94ccd900e03f863"},
{"name":"puma_worker_killer","version":"0.3.1","platform":"ruby","checksum":"9c5534d296b5e92d1ad4a578f2daf2aa71563003c84f7263f0a8dfd22b5c614a"},
@@ -430,11 +436,11 @@
{"name":"rack-accept","version":"0.4.5","platform":"ruby","checksum":"66247b5449db64ebb93ae2ec4af4764b87d1ae8a7463c7c68893ac13fa8d4da2"},
{"name":"rack-attack","version":"6.6.1","platform":"ruby","checksum":"187e5d248c6a162ed8cafa8241a7b5947d9b9cf122a4870eb1cdd0db861f3a11"},
{"name":"rack-cors","version":"1.1.1","platform":"ruby","checksum":"4702644ac6d63ebbddff372a3cd4cd573513287e3524b5a5415f678970057a4b"},
-{"name":"rack-oauth2","version":"1.21.2","platform":"ruby","checksum":"06fc157cad243ac11d8681c18139c4556a3f86b518f0fcb419e29512181a3ff2"},
+{"name":"rack-oauth2","version":"1.21.3","platform":"ruby","checksum":"4e72a79dd6a866692e84422a552b27c38a5a1918ded06661e04910f2bbe676ba"},
{"name":"rack-protection","version":"2.2.2","platform":"ruby","checksum":"fd41414dbabbec274af0bdb1f72a48504449de4d979782c9af38cbb5dfff3299"},
-{"name":"rack-proxy","version":"0.7.2","platform":"ruby","checksum":"89c74fd6d3e5a4db0ed7e0d8b9915dbc85360fd6f98f6c1f9a66479fe236f4b6"},
-{"name":"rack-test","version":"1.1.0","platform":"ruby","checksum":"154161f40f162b1c009a655b7b0c5de3a3102cc6d7d2e94b64e1f46ace800866"},
-{"name":"rack-timeout","version":"0.6.0","platform":"ruby","checksum":"6038d1cc31936394bd2c57bb16c17b31d2fd1d33ce928537cf0ef6f1f1905099"},
+{"name":"rack-proxy","version":"0.7.4","platform":"ruby","checksum":"a8bb373583d8a3165d8caf5af5fd7c32c9e8a91b983fbc531efa0e3d6617d2d4"},
+{"name":"rack-test","version":"2.0.2","platform":"ruby","checksum":"adadd0e957f63a34199a9fdf905a920a0b0a50795735095b4ac4bd3c13385466"},
+{"name":"rack-timeout","version":"0.6.3","platform":"ruby","checksum":"1754892eacc124d405e7f1145731ec9b7421ebd1bee5d51ddc18b72c204d0ab3"},
{"name":"rails","version":"6.1.6.1","platform":"ruby","checksum":"17024921a3913fb341f584542b06adf6bb12977a8b92d5fce093c3996c963686"},
{"name":"rails-controller-testing","version":"1.0.5","platform":"ruby","checksum":"741448db59366073e86fc965ba403f881c636b79a2c39a48d0486f2607182e94"},
{"name":"rails-dom-testing","version":"2.0.3","platform":"ruby","checksum":"b140c4f39f6e609c8113137b9a60dfc2ecb89864e496f87f23a68b3b8f12d8d1"},
@@ -443,24 +449,22 @@
{"name":"railties","version":"6.1.6.1","platform":"ruby","checksum":"bafecdf2dcbe4ea44e1ab7081fd797aa87ae9bbcd0f3a4372b662a1b93949733"},
{"name":"rainbow","version":"3.1.1","platform":"ruby","checksum":"039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a"},
{"name":"rake","version":"13.0.6","platform":"ruby","checksum":"5ce4bf5037b4196c24ac62834d8db1ce175470391026bd9e557d669beeb19097"},
-{"name":"randexp","version":"0.1.7","platform":"ruby","checksum":"3026510ecf6a8e8642b9b96fa44bb41af6d24058023b7df77cf280f08e14e4c8"},
-{"name":"rash_alt","version":"0.4.12","platform":"ruby","checksum":"1d4a6dd5b8fdcecc6b777c0b924dbf31c125ddd8d805e72dc9359db8324e1607"},
{"name":"rb-fsevent","version":"0.11.2","platform":"ruby","checksum":"43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe"},
{"name":"rb-inotify","version":"0.10.1","platform":"ruby","checksum":"050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca"},
{"name":"rbtrace","version":"0.4.14","platform":"ruby","checksum":"162bbf89cecabfc4f09c869b655f6f3a679c4870ebb7cbdcadf7393a81cc1769"},
{"name":"rbtree","version":"0.4.4","platform":"ruby","checksum":"c1277a502a96fe8fd8656cb619db1ac87145df809ea4db35f7242b50bb161d5c"},
{"name":"rchardet","version":"1.8.0","platform":"ruby","checksum":"693acd5253d5ade81a51940697955f6dd4bb2f0d245bda76a8e23deec70a52c7"},
{"name":"rdoc","version":"6.3.2","platform":"ruby","checksum":"def4a720235c27d56c176ae73555e647eb04ea58a8bbaa927f8f9f79de7805a6"},
-{"name":"re2","version":"1.4.0","platform":"ruby","checksum":"5c07d2351be1159530e2b815aae499b6524942e79bf21d560fcff5b2fa20ea8f"},
+{"name":"re2","version":"1.5.0","platform":"ruby","checksum":"35fe8b408de9f1ef609b1e54e01ea1e55413ca3e9daf1e4b20756d9a02f630cc"},
{"name":"recaptcha","version":"4.13.1","platform":"ruby","checksum":"dc6c2cb78afa87034358b7ba1c6f7175972b5709fdf7500e2550623e119e3788"},
{"name":"recursive-open-struct","version":"1.1.3","platform":"ruby","checksum":"a3538a72552fcebcd0ada657bdff313641a4a5fbc482c08cfb9a65acb1c9de5a"},
{"name":"redcarpet","version":"3.5.1","platform":"ruby","checksum":"717f64cb6ec11c8d9ec9b521ed26ca2eeda68b4fe1fc3388a641176dbd47732f"},
{"name":"redis","version":"4.7.1","platform":"ruby","checksum":"ecb256d4e53ead3eca05bf394dd100e6a162c136f461fe752ddf5d35b64a2df6"},
{"name":"redis-actionpack","version":"5.3.0","platform":"ruby","checksum":"3fb1ad0a8fd9d26a289c9399bb609dcaef38bf37711e6f677a53ca728fc19140"},
-{"name":"redis-namespace","version":"1.8.1","platform":"ruby","checksum":"c81707d693e5e754c690b4e1fa68ecfa8bd1028fbf306e533b3832e44e76c54c"},
+{"name":"redis-namespace","version":"1.9.0","platform":"ruby","checksum":"0923961f38cf15b86cb57d92507e0a3b32480729eb5033249f5de8b12e0d8612"},
{"name":"redis-rack","version":"2.1.4","platform":"ruby","checksum":"0872eecb303e483c3863d6bd0d47323d230640d41c1a4ac4a2c7596ec0b1774c"},
{"name":"redis-store","version":"1.9.1","platform":"ruby","checksum":"7b4c7438d46f7b7ce8f67fc0eda3a04fc67d32d28cf606cc98a5df4d2b77071d"},
-{"name":"regexp_parser","version":"2.5.0","platform":"ruby","checksum":"a076d2d35ab8d11feab5fecf8aa09ec6df68c2429810748cba079f7b021ecde5"},
+{"name":"regexp_parser","version":"2.6.0","platform":"ruby","checksum":"f163ba463a45ca2f2730e0902f2475bb0eefcd536dfc2f900a86d1e5a7d7a556"},
{"name":"regexp_property_values","version":"1.0.0","platform":"java","checksum":"5e26782b01241616855c4ee7bb8a62fce9387e484f2d3eaf04f2a0633708222e"},
{"name":"regexp_property_values","version":"1.0.0","platform":"ruby","checksum":"162499dc0bba1e66d334273a059f207a61981cc8cc69d2ca743594e7886d080f"},
{"name":"representable","version":"3.0.4","platform":"ruby","checksum":"07d43917dea4712ecebd19c1909e769deed863ad444d23ceb6461519e2cba962"},
@@ -480,26 +484,24 @@
{"name":"rqrcode-rails3","version":"0.1.7","platform":"ruby","checksum":"6f0582f26485123e5ed6f2a8a2871f00d86d353e0f58c8429a5a13212bcf48c4"},
{"name":"rspec","version":"3.10.0","platform":"ruby","checksum":"b870b43d49ae4a4e063b94976d2742b0854ec10458c425d569b5556ee5898ab7"},
{"name":"rspec-benchmark","version":"0.6.0","platform":"ruby","checksum":"1014adb57ec2599a2455c63884229f367a2fff6a63a77fd68ce5d804c83dd6cf"},
-{"name":"rspec-core","version":"3.10.1","platform":"ruby","checksum":"ac9abdc9577a3a34e9e92815603da8343931055ab4fba1c2a49de6dd3b749673"},
+{"name":"rspec-core","version":"3.10.2","platform":"ruby","checksum":"005659ce9dd356dd5d2acb4bcdcc5915291f4a312447b500af3b75aab564951b"},
{"name":"rspec-expectations","version":"3.10.1","platform":"ruby","checksum":"27acf5d5df13f8cc8f7158001ebf572513bcec3d45404ba76e0a8998895ce9eb"},
{"name":"rspec-mocks","version":"3.10.3","platform":"ruby","checksum":"d2f6f3d8b7569b1e846703d164cb23e24c7f530d38217fc06da2beaf6024260a"},
{"name":"rspec-parameterized","version":"0.5.0","platform":"ruby","checksum":"f163ac07b5edd1eeb13136480623db7020852c70cf0ad2fa98e31384ae162454"},
{"name":"rspec-rails","version":"5.0.1","platform":"ruby","checksum":"c61e7f35db2266f83b3cc58a340fc3ec0bd6344818040430fd5ddc99775242de"},
{"name":"rspec-retry","version":"0.6.1","platform":"ruby","checksum":"86b7e8513c5b0c713c2e28854f4d996deb8efa6304eef50f0ad68ee6c563d8da"},
-{"name":"rspec-support","version":"3.10.2","platform":"ruby","checksum":"74315f89069fbaf2a710e2117340373b77ee45eceb026de87e0cad9dd5154596"},
-{"name":"rspec_junit_formatter","version":"0.4.1","platform":"ruby","checksum":"3788f9b3fabc6284b93493cf4b3a80cba2b59b3a774b95f39dd7886d5faed6ab"},
+{"name":"rspec-support","version":"3.10.3","platform":"ruby","checksum":"65c88f8cbe579461f411097682e6402960eae327eef08e86ef581b8c609e4c5e"},
+{"name":"rspec_junit_formatter","version":"0.6.0","platform":"ruby","checksum":"40dde674e6ae4e6cc0ff560da25497677e34fefd2338cc467a8972f602b62b15"},
{"name":"rspec_profiling","version":"0.0.6","platform":"ruby","checksum":"7a45697f79dcec9a174a0e26703465f6bd52ee78e8d798741240bfcef38f6e6e"},
-{"name":"rubocop","version":"0.93.1","platform":"ruby","checksum":"73b44fbbe872edbd3f14487175b6369a0f48e952c155f305896ffa56c48b195e"},
+{"name":"rubocop","version":"1.36.0","platform":"ruby","checksum":"368e47dcab8417419949bbadb11ec41fd94e6b785f8bff4f9cc56a1ddf60ffac"},
{"name":"rubocop-ast","version":"1.21.0","platform":"ruby","checksum":"8f5d98611343498602de2d41bc583aca71599daad16daeadaeeee60f134c9568"},
{"name":"rubocop-gitlab-security","version":"0.1.1","platform":"ruby","checksum":"96f6ed727847a5876ddfc89ee0399438a1aef7934db773c7efce907e2720006c"},
{"name":"rubocop-graphql","version":"0.14.6","platform":"ruby","checksum":"b40f2cbac9990ece44eb85eec5c5ae04fca1e197c07c790ac1ca60600b55bdad"},
-{"name":"rubocop-performance","version":"1.9.2","platform":"ruby","checksum":"3373ad82b70189fa16b593b6237eb06186da669d468b7d6483bca64c0a844a05"},
-{"name":"rubocop-rails","version":"2.9.1","platform":"ruby","checksum":"2d8d113c3ae074c78c89cb706b4a08116d730bf92dbef148798498171435c540"},
-{"name":"rubocop-rspec","version":"1.44.1","platform":"ruby","checksum":"7b2238e7d6cf17a925a90992914f3cd8ecd68b65b31710d60a3f7f647f8a8b2a"},
+{"name":"rubocop-performance","version":"1.14.3","platform":"ruby","checksum":"ee45ae3e40388ff809d9c5e2ef6ef9d59dc86c59c97110f96d5540267f860751"},
+{"name":"rubocop-rails","version":"2.15.2","platform":"ruby","checksum":"1891ab46a6eaf36b841ad27c9c8a22e77a2c3ae85bc334111d3f8075e417643c"},
+{"name":"rubocop-rspec","version":"2.12.1","platform":"ruby","checksum":"9278d22d4525261caf30d591eef3d47910a125e74f75f41ffa470acd208423f9"},
{"name":"ruby-fogbugz","version":"0.2.1","platform":"ruby","checksum":"15b2e7fe7e95b021a94ee6e9d8bb32fdad6ae44e820c2ce0dc312fe6e77d40ca"},
{"name":"ruby-magic","version":"0.5.4","platform":"ruby","checksum":"2c17b185130d10a83791f63a40baa358c4b138af37da3f4dab53690121c421d5"},
-{"name":"ruby-prof","version":"1.3.1","platform":"ruby","checksum":"e735d20c92954e1fa2a4475539c99dfc8d0166b4cc6915ca309e8ee2dd19323c"},
-{"name":"ruby-prof","version":"1.3.1","platform":"x64-mingw32","checksum":"a97bb6ff0abb01131ecba88799222d492d9124e057535db8e5bd47119f2a58ba"},
{"name":"ruby-progressbar","version":"1.11.0","platform":"ruby","checksum":"cc127db3866dc414ffccbf92928a241e585b3aa2b758a5563e74a6ee0f57d50a"},
{"name":"ruby-saml","version":"1.13.0","platform":"ruby","checksum":"d31cbdf5fb8fdd6aa3187e48dba3085cfeb751af30276a5739aa3659a66f069c"},
{"name":"ruby-statistics","version":"3.0.0","platform":"ruby","checksum":"610301370346931cb701e3a8d3d3e28eb65681162cae6066c0c11abf20efdc81"},
@@ -533,7 +535,7 @@
{"name":"shellany","version":"0.0.1","platform":"ruby","checksum":"0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7"},
{"name":"shoulda-matchers","version":"5.1.0","platform":"ruby","checksum":"a01d20589989e9653ab4a28c67d9db2b82bcf0a2496cf01d5e1a95a4aaaf5b07"},
{"name":"sidekiq","version":"6.4.2","platform":"ruby","checksum":"0d3c05fecb5fbace5ff5efc63da707e02a9c4673fb8e33ceca10b5ec0e9f062c"},
-{"name":"sidekiq-cron","version":"1.4.0","platform":"ruby","checksum":"21612ade25ea79b4eeb8eacd7fb559a85a1abf6bf1da1aca1aa0079cafd3376d"},
+{"name":"sidekiq-cron","version":"1.8.0","platform":"ruby","checksum":"47da72ca73ce5b71896aaf7e7c4391386ec517dd003f184c50c0b727d82eb0ca"},
{"name":"sigdump","version":"0.2.4","platform":"ruby","checksum":"0bf2176e55c1a262788623fe5ea57caddd6ba2abebe5e349d9d5e7c3a3010ed7"},
{"name":"signet","version":"0.17.0","platform":"ruby","checksum":"1d2831930dc28da32e34bec68cf7ded97ee2867b208f97c500ee293829cb0004"},
{"name":"simple_po_parser","version":"1.1.6","platform":"ruby","checksum":"122687d44d3de516a0e69e2f383a4180f5015e8c5ed5a7f2258f2b376f64cbf3"},
@@ -544,8 +546,9 @@
{"name":"simplecov_json_formatter","version":"0.1.4","platform":"ruby","checksum":"529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428"},
{"name":"sixarm_ruby_unaccent","version":"1.2.0","platform":"ruby","checksum":"0043a6077bdf2c4b03040152676a07f8bf77144f9b007b1960ee5c94d13a4384"},
{"name":"slack-messenger","version":"2.3.4","platform":"ruby","checksum":"49c611d2be5b0f9c250a3a957b9cc09b9c07b81dacb9843642d87b6fa35609c1"},
+{"name":"snaky_hash","version":"2.0.0","platform":"ruby","checksum":"fe8b2e39e8ff69320f7812af73ea06401579e29ff1734a7009567391600687de"},
{"name":"snowplow-tracker","version":"0.6.1","platform":"ruby","checksum":"9cec52fd060619f4974b3dc1f7d9a2776c5e31b668a6ead53145b9780e312314"},
-{"name":"solargraph","version":"0.46.0","platform":"ruby","checksum":"1da9fd8c364501f18b0454e54506e7098bc38dae719219713fe5f246dfc91465"},
+{"name":"solargraph","version":"0.47.2","platform":"ruby","checksum":"87ca4b799b9155c2c31c15954c483e952fdacd800f52d6709b901dd447bcac6a"},
{"name":"sorted_set","version":"1.0.3","platform":"java","checksum":"996283f2e5c6e838825bcdcee31d6306515ae5f24bcb0ee4ce09dfff32919b8c"},
{"name":"sorted_set","version":"1.0.3","platform":"ruby","checksum":"4f2b8bee6e8c59cbd296228c0f1f81679357177a8b6859dcc2a99e86cce6372f"},
{"name":"spamcheck","version":"1.0.0","platform":"ruby","checksum":"dfeea085184091353e17d729d2f3d714b07cba36aaf64c32dfc35ce9b466fc9c"},
@@ -577,12 +580,12 @@
{"name":"text","version":"1.3.1","platform":"ruby","checksum":"2fbbbc82c1ce79c4195b13018a87cbb00d762bda39241bb3cdc32792759dd3f4"},
{"name":"thor","version":"1.2.1","platform":"ruby","checksum":"b1752153dc9c6b8d3fcaa665e9e1a00a3e73f28da5e238b81c404502e539d446"},
{"name":"thrift","version":"0.16.0","platform":"ruby","checksum":"d023286ea89e30444c9f1c28dd76107f87d8aaf85fe1742da1d8cd3b5417dcce"},
-{"name":"tilt","version":"2.0.10","platform":"ruby","checksum":"9b664f0e9ae2b500cfa00f9c65c34abc6ff1799cf0034a8c0a0412d520fac866"},
+{"name":"tilt","version":"2.0.11","platform":"ruby","checksum":"7b180fc472cbdeb186c85d31c0f2d1e61a2c0d77e1d9fd0ca28482a9d972d6a0"},
{"name":"timecop","version":"0.9.1","platform":"ruby","checksum":"374b543f0961dbd487e96d09ac812d4fdfeb603ec705bbff241ba060d0a9f534"},
{"name":"timeliness","version":"0.3.10","platform":"ruby","checksum":"c357233ce19dc53148e8b29dfddde134689f18f52b32928e9dfe12ebcf4a773f"},
{"name":"timfel-krb5-auth","version":"0.8.3","platform":"ruby","checksum":"ab388c9d747fa3cd95baf2cc1c03253e372d8c680adcc543670f4f099854bb80"},
-{"name":"tins","version":"1.31.0","platform":"ruby","checksum":"20b5ea997dc046358fd05f15d39636bd7946798591b9c5741cc41f69853c7894"},
-{"name":"toml-rb","version":"2.0.1","platform":"ruby","checksum":"5016c6c77ac72bca5fe67c372722bdfdd4479a6fe1a1c4ff2a486e247849b274"},
+{"name":"tins","version":"1.31.1","platform":"ruby","checksum":"51c4a347c25c630d310cbc2c040ffb84e266c8227f2ade881f1130ee4f9fbecf"},
+{"name":"toml-rb","version":"2.2.0","platform":"ruby","checksum":"a1e2c54ac3cc9d49861004f75f0648b3622ac03a76abe105358c31553227d9a6"},
{"name":"tomlrb","version":"1.3.0","platform":"ruby","checksum":"68666bf53fa70ba686a48a7435ce7e086f5227c58c4c993bd9792f4760f2a503"},
{"name":"tpm-key_attestation","version":"0.9.0","platform":"ruby","checksum":"e469ad9111a68dab4d04596e1c0621d7c877c2e3e247f765af3c04f1adf2b8cd"},
{"name":"train-core","version":"3.4.9","platform":"ruby","checksum":"d7ad8fa9a379c43a30baaaf1141af1cb28349d386c054f7fc81d169a625d6edd"},
@@ -614,7 +617,7 @@
{"name":"validate_email","version":"0.1.6","platform":"ruby","checksum":"9dfe9016d527b17a8d3a6e95e4dc50a125400eef899d13d4cc2a254393f82ee4"},
{"name":"validate_url","version":"1.0.15","platform":"ruby","checksum":"72fe164c0713d63a9970bd6700bea948babbfbdcec392f2342b6704042f57451"},
{"name":"validates_hostname","version":"1.0.11","platform":"ruby","checksum":"d506bae0342ec14c920eb319e057fc1886c321a59b85b4b6e966ee4b88fab8c3"},
-{"name":"version_gem","version":"1.0.0","platform":"ruby","checksum":"929c93a4d46482bb3b0359980c7a5fb1b5a833548f1202a480b08a6f0a5f8f2f"},
+{"name":"version_gem","version":"1.1.0","platform":"ruby","checksum":"6b009518020db57f51ec7b410213fae2bf692baea9f1b51770db97fbc93d9a80"},
{"name":"version_sorter","version":"2.2.4","platform":"ruby","checksum":"7ad071609edfaa3cf28c42d83b1a03096e43512244ae5a9e2fce1404f7e06d41"},
{"name":"view_component","version":"2.71.0","platform":"ruby","checksum":"c1880647800d9cfb03ff4ba92313db624a4a4b3d5753e137effe86e5f2b3662b"},
{"name":"vmstat","version":"2.3.0","platform":"ruby","checksum":"ab5446a3e3bd0a9cdb9d9ac69a0bbd119c4f161d945a0846a519dd7018af656d"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 9074b48c56b..8bf67a41f45 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,4 +1,10 @@
PATH
+ remote: vendor/gems/attr_encrypted
+ specs:
+ attr_encrypted (3.2.4)
+ encryptor (~> 3.0.0)
+
+PATH
remote: vendor/gems/bundler-checksum
specs:
bundler-checksum (0.1.0)
@@ -9,6 +15,7 @@ PATH
specs:
devise-pbkdf2-encryptable (0.0.0)
devise (~> 4.0)
+ devise-two-factor (~> 4.0)
PATH
remote: vendor/gems/error_tracking_open_api
@@ -58,16 +65,7 @@ PATH
specs:
omniauth-gitlab (4.0.0)
omniauth (~> 2.0)
- omniauth-oauth2 (~> 1.7.1)
-
-PATH
- remote: vendor/gems/omniauth-google-oauth2
- specs:
- omniauth-google-oauth2 (1.0.1)
- jwt (>= 2.0)
- oauth2 (~> 2.0)
- omniauth (~> 2.0)
- omniauth-oauth2 (~> 1.7.1)
+ omniauth-oauth2 (~> 1.8)
PATH
remote: vendor/gems/omniauth-salesforce
@@ -87,6 +85,8 @@ PATH
GEM
remote: https://rubygems.org/
specs:
+ CFPropertyList (3.0.5)
+ rexml
RedCloth (4.3.2)
acme-client (2.0.11)
faraday (>= 1.0, < 3.0.0)
@@ -155,14 +155,15 @@ GEM
zeitwerk (~> 2.3)
acts-as-taggable-on (9.0.0)
activerecord (>= 6.0, < 7.1)
- addressable (2.8.0)
- public_suffix (>= 2.0.2, < 5.0)
+ addressable (2.8.1)
+ public_suffix (>= 2.0.2, < 6.0)
aes_key_wrap (1.1.0)
akismet (3.0.0)
android_key_attestation (0.3.0)
apollo_upload_server (2.1.0)
actionpack (>= 4.2)
graphql (>= 1.8)
+ arr-pm (0.0.12)
asana (0.10.13)
faraday (~> 1.0)
faraday_middleware (~> 1.0)
@@ -178,19 +179,17 @@ GEM
ast (2.4.2)
atlassian-jwt (0.2.0)
jwt (~> 2.1.0)
- attr_encrypted (3.1.0)
- encryptor (~> 3.0.0)
attr_required (1.0.1)
autoprefixer-rails (10.2.5.1)
execjs (> 0)
awesome_print (1.9.2)
awrence (1.1.1)
aws-eventstream (1.2.0)
- aws-partitions (1.600.0)
+ aws-partitions (1.644.0)
aws-sdk-cloudformation (1.41.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
- aws-sdk-core (3.131.1)
+ aws-sdk-core (3.159.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
@@ -202,7 +201,7 @@ GEM
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
- aws-sigv4 (1.5.0)
+ aws-sigv4 (1.5.1)
aws-eventstream (~> 1, >= 1.0.2)
azure-storage-blob (2.0.3)
azure-storage-common (~> 2.0)
@@ -228,7 +227,7 @@ GEM
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
- bindata (2.4.10)
+ bindata (2.4.11)
binding_ninja (0.2.3)
bootsnap (1.13.0)
msgpack (~> 1.2)
@@ -282,9 +281,9 @@ GEM
open4 (~> 1.3)
coderay (1.1.3)
colored2 (3.1.2)
- commonmarker (0.23.4)
+ commonmarker (0.23.6)
concurrent-ruby (1.1.10)
- connection_pool (2.2.5)
+ connection_pool (2.3.0)
contracts (0.11.0)
cork (0.3.0)
colored2 (~> 3.1)
@@ -301,8 +300,9 @@ GEM
creole (0.5.0)
crystalball (0.7.0)
git
- css_parser (1.11.0)
+ css_parser (1.12.0)
addressable
+ cvss-suite (3.0.1)
danger (8.6.1)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
@@ -412,7 +412,7 @@ GEM
launchy (~> 2.1)
mail (~> 2.7)
encryptor (3.0.0)
- erubi (1.9.0)
+ erubi (1.11.0)
escape_utils (1.2.1)
et-orbi (1.2.7)
tzinfo
@@ -420,6 +420,8 @@ GEM
ffi (>= 1.15.0)
excon (0.90.0)
execjs (2.8.1)
+ expgen (0.1.1)
+ parslet
expression_parser (0.9.0)
extended-markdown-filter (0.6.0)
html-pipeline (~> 2.0)
@@ -585,13 +587,13 @@ GEM
openid_connect (~> 1.2)
gitlab-sidekiq-fetcher (0.8.0)
sidekiq (~> 6.1)
- gitlab-styles (8.0.0)
- rubocop (~> 0.91, >= 0.91.1)
+ gitlab-styles (9.0.0)
+ rubocop (~> 1.36.0)
rubocop-gitlab-security (~> 0.1.1)
- rubocop-graphql (~> 0.10)
- rubocop-performance (~> 1.9.2)
- rubocop-rails (~> 2.9)
- rubocop-rspec (~> 1.44)
+ rubocop-graphql (~> 0.14)
+ rubocop-performance (~> 1.14)
+ rubocop-rails (~> 2.15)
+ rubocop-rspec (~> 2.12)
gitlab_chronic_duration (0.10.6.2)
numerizer (~> 0.2)
gitlab_omniauth-ldap (2.2.0)
@@ -617,7 +619,7 @@ GEM
signet (~> 0.12)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
- google-protobuf (3.21.5)
+ google-protobuf (3.21.7)
googleapis-common-protos-types (1.3.0)
google-protobuf (~> 3.14)
googleauth (0.14.0)
@@ -644,6 +646,11 @@ GEM
grape (~> 1.3)
rake (> 12)
ruby2_keywords (~> 0.0.2)
+ grape-swagger (1.5.0)
+ grape (~> 1.3)
+ grape-swagger-entity (0.5.1)
+ grape-entity (>= 0.6.0)
+ grape-swagger (>= 1.2.0)
grape_logging (1.8.4)
grape
rack
@@ -705,7 +712,7 @@ GEM
hashie (4.1.0)
hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0)
- health_check (3.0.0)
+ health_check (3.1.0)
railties (>= 5.0)
heapy (0.2.0)
thor
@@ -739,6 +746,7 @@ GEM
parser (>= 2.5, != 2.5.1.1)
invisible_captcha (1.1.0)
rails (>= 4.2)
+ ipaddr (1.2.2)
ipaddress (0.8.3)
jaeger-client (1.1.0)
opentracing (~> 0.3)
@@ -755,10 +763,11 @@ GEM
regexp_parser (~> 2.1)
regexp_property_values (~> 1.0)
json (2.5.1)
- json-jwt (1.13.0)
+ json-jwt (1.15.3)
activesupport (>= 4.2)
aes_key_wrap
bindata
+ httpclient
json_schemer (0.2.18)
ecma-re-validator (~> 0.3)
hana (~> 1.3)
@@ -794,7 +803,7 @@ GEM
rest-client (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
- lefthook (1.1.1)
+ lefthook (1.1.3)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (2.0.0)
@@ -826,10 +835,10 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.18.0)
+ loofah (2.19.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- lookbook (1.0.3)
+ lookbook (1.0.8)
actioncable
css_parser
htmlbeautifier (~> 1.3)
@@ -845,9 +854,9 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (1.0.2)
- marginalia (1.10.0)
- actionpack (>= 2.3)
- activerecord (>= 2.3)
+ marginalia (1.11.1)
+ actionpack (>= 5.2)
+ activerecord (>= 5.2)
memoist (0.16.2)
memory_profiler (0.9.14)
method_source (1.0.0)
@@ -903,13 +912,13 @@ GEM
shellany (~> 0.0)
numerizer (0.2.0)
oauth (0.5.6)
- oauth2 (2.0.3)
+ oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_xml (~> 0.5)
- rack (>= 1.2, < 3)
- rash_alt (>= 0.4, < 1)
- version_gem (~> 1.0)
+ rack (>= 1.2, < 4)
+ snaky_hash (~> 2.0)
+ version_gem (~> 1.1)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
@@ -931,8 +940,8 @@ GEM
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
- omniauth-alicloud (1.0.1)
- omniauth-oauth2 (~> 1.7.1)
+ omniauth-alicloud (2.0.0)
+ omniauth-oauth2 (~> 1.8)
omniauth-atlassian-oauth2 (0.2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.5)
@@ -941,26 +950,29 @@ GEM
omniauth-authentiq (0.3.3)
jwt (>= 1.5)
omniauth-oauth2 (>= 1.5)
- omniauth-azure-activedirectory-v2 (1.0.0)
- omniauth-oauth2 (~> 1.7)
+ omniauth-azure-activedirectory-v2 (2.0.0)
+ omniauth-oauth2 (~> 1.8)
omniauth-dingtalk-oauth2 (1.0.1)
omniauth-oauth2 (~> 1.7)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
- omniauth-github (2.0.0)
+ omniauth-github (2.0.1)
+ omniauth (~> 2.0)
+ omniauth-oauth2 (~> 1.8)
+ omniauth-google-oauth2 (1.1.1)
+ jwt (>= 2.0)
+ oauth2 (~> 2.0.6)
omniauth (~> 2.0)
- omniauth-oauth2 (~> 1.7.1)
+ omniauth-oauth2 (~> 1.8.0)
omniauth-oauth (1.2.0)
oauth
omniauth (>= 1.0, < 3)
- omniauth-oauth2 (1.7.3)
+ omniauth-oauth2 (1.8.0)
oauth2 (>= 1.4, < 3)
- omniauth (>= 1.9, < 3)
- omniauth-oauth2-generic (0.2.2)
- omniauth-oauth2 (~> 1.0)
- omniauth-rails_csrf_protection (1.0.1)
- actionpack (>= 4.2)
omniauth (~> 2.0)
+ omniauth-oauth2-generic (0.2.8)
+ omniauth-oauth2 (~> 1.0)
+ rake
omniauth-saml (2.0.0)
omniauth (~> 2.0)
ruby-saml (~> 1.9)
@@ -980,7 +992,8 @@ GEM
validate_email
validate_url
webfinger (>= 1.0.1)
- openssl (2.2.0)
+ openssl (2.2.1)
+ ipaddr
openssl-signature_algorithm (0.4.0)
opentracing (0.5.0)
optimist (3.0.1)
@@ -988,29 +1001,29 @@ GEM
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.1.1)
- pact (1.59.0)
+ pact (1.63.0)
pact-mock_service (~> 3.0, >= 3.3.1)
- pact-support (~> 1.15)
- rack-test (>= 0.6.3, < 2.0.0)
+ pact-support (~> 1.16, >= 1.16.9)
+ rack-test (>= 0.6.3, < 3.0.0)
rspec (~> 3.0)
term-ansicolor (~> 1.0)
thor (>= 0.20, < 2.0)
webrick (~> 1.3)
- pact-mock_service (3.6.2)
+ pact-mock_service (3.10.0)
filelock (~> 1.1)
find_a_port (~> 1.0.1)
json
- pact-support (~> 1.12, >= 1.12.0)
+ pact-support (~> 1.16, >= 1.16.4)
rack (~> 2.0)
rspec (>= 2.14)
term-ansicolor (~> 1.0)
thor (>= 0.19, < 2.0)
webrick (~> 1.3)
- pact-support (1.15.1)
- awesome_print (~> 1.1)
- randexp (~> 0.1.7)
- rspec (>= 2.14)
- term-ansicolor (~> 1.0)
+ pact-support (1.18.1)
+ awesome_print (~> 1.9)
+ diff-lcs (~> 1.4)
+ expgen (~> 0.1)
+ rainbow (~> 3.1.1)
parallel (1.22.1)
parser (3.1.2.1)
ast (~> 2.4.1)
@@ -1019,7 +1032,7 @@ GEM
tty-color (~> 0.5)
peek (1.1.0)
railties (>= 4.0.0)
- pg (1.4.1)
+ pg (1.4.3)
pg_query (2.1.4)
google-protobuf (>= 3.19.2)
plist (3.6.0)
@@ -1050,7 +1063,7 @@ GEM
pry (~> 0.13.0)
tty-markdown
tty-prompt
- public_suffix (4.0.7)
+ public_suffix (5.0.0)
puma (5.6.5)
nio4r (~> 2.0)
puma_worker_killer (0.3.1)
@@ -1066,7 +1079,7 @@ GEM
rack (>= 1.0, < 3)
rack-cors (1.1.1)
rack (>= 2.0.0)
- rack-oauth2 (1.21.2)
+ rack-oauth2 (1.21.3)
activesupport
attr_required
httpclient
@@ -1074,11 +1087,11 @@ GEM
rack (>= 2.1.0)
rack-protection (2.2.2)
rack
- rack-proxy (0.7.2)
+ rack-proxy (0.7.4)
rack
- rack-test (1.1.0)
- rack (>= 1.0, < 3)
- rack-timeout (0.6.0)
+ rack-test (2.0.2)
+ rack (>= 1.3)
+ rack-timeout (0.6.3)
rails (6.1.6.1)
actioncable (= 6.1.6.1)
actionmailbox (= 6.1.6.1)
@@ -1114,9 +1127,6 @@ GEM
thor (~> 1.0)
rainbow (3.1.1)
rake (13.0.6)
- randexp (0.1.7)
- rash_alt (0.4.12)
- hashie (>= 3.4)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
@@ -1127,7 +1137,7 @@ GEM
rbtree (0.4.4)
rchardet (1.8.0)
rdoc (6.3.2)
- re2 (1.4.0)
+ re2 (1.5.0)
recaptcha (4.13.1)
json
recursive-open-struct (1.1.3)
@@ -1137,14 +1147,14 @@ GEM
actionpack (>= 5, < 8)
redis-rack (>= 2.1.0, < 3)
redis-store (>= 1.1.0, < 2)
- redis-namespace (1.8.1)
- redis (>= 3.0.4)
+ redis-namespace (1.9.0)
+ redis (>= 4)
redis-rack (2.1.4)
rack (>= 2.0.8, < 3)
redis-store (>= 1.2, < 2)
redis-store (1.9.1)
redis (>= 4, < 5)
- regexp_parser (2.5.0)
+ regexp_parser (2.6.0)
regexp_property_values (1.0.0)
representable (3.0.4)
declarative (< 0.1.0)
@@ -1180,7 +1190,7 @@ GEM
benchmark-perf (~> 0.6)
benchmark-trend (~> 0.4)
rspec (>= 3.0)
- rspec-core (3.10.1)
+ rspec-core (3.10.2)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
@@ -1204,44 +1214,43 @@ GEM
rspec-support (~> 3.10)
rspec-retry (0.6.1)
rspec-core (> 3.3)
- rspec-support (3.10.2)
- rspec_junit_formatter (0.4.1)
+ rspec-support (3.10.3)
+ rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rspec_profiling (0.0.6)
activerecord
pg
rails
sqlite3
- rubocop (0.93.1)
+ rubocop (1.36.0)
+ json (~> 2.3)
parallel (~> 1.10)
- parser (>= 2.7.1.5)
+ parser (>= 3.1.2.1)
rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.8)
- rexml
- rubocop-ast (>= 0.6.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml (>= 3.2.5, < 4.0)
+ rubocop-ast (>= 1.20.1, < 2.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 2.0)
+ unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.21.0)
parser (>= 3.1.1.0)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
rubocop-graphql (0.14.6)
rubocop (>= 0.87, < 2)
- rubocop-performance (1.9.2)
- rubocop (>= 0.90.0, < 2.0)
+ rubocop-performance (1.14.3)
+ rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
- rubocop-rails (2.9.1)
+ rubocop-rails (2.15.2)
activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.90.0, < 2.0)
- rubocop-rspec (1.44.1)
- rubocop (~> 0.87)
- rubocop-ast (>= 0.7.1)
+ rubocop (>= 1.7.0, < 2.0)
+ rubocop-rspec (2.12.1)
+ rubocop (~> 1.31)
ruby-fogbugz (0.2.1)
crack (~> 0.4)
ruby-magic (0.5.4)
mini_portile2 (~> 2.6)
- ruby-prof (1.3.1)
ruby-progressbar (1.11.0)
ruby-saml (1.13.0)
nokogiri (>= 1.10.5)
@@ -1307,7 +1316,7 @@ GEM
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
- sidekiq-cron (1.4.0)
+ sidekiq-cron (1.8.0)
fugit (~> 1)
sidekiq (>= 4.2.1)
sigdump (0.2.4)
@@ -1328,9 +1337,12 @@ GEM
simplecov_json_formatter (0.1.4)
sixarm_ruby_unaccent (1.2.0)
slack-messenger (2.3.4)
+ snaky_hash (2.0.0)
+ hashie
+ version_gem (~> 1.1)
snowplow-tracker (0.6.1)
contracts (~> 0.7, <= 0.11)
- solargraph (0.46.0)
+ solargraph (0.47.2)
backport (~> 1.2)
benchmark
bundler (>= 1.17.2)
@@ -1399,13 +1411,13 @@ GEM
text (1.3.1)
thor (1.2.1)
thrift (0.16.0)
- tilt (2.0.10)
+ tilt (2.0.11)
timecop (0.9.1)
timeliness (0.3.10)
timfel-krb5-auth (0.8.3)
- tins (1.31.0)
+ tins (1.31.1)
sync
- toml-rb (2.0.1)
+ toml-rb (2.2.0)
citrus (~> 3.0, > 3.0)
tomlrb (1.3.0)
tpm-key_attestation (0.9.0)
@@ -1472,7 +1484,7 @@ GEM
validates_hostname (1.0.11)
activerecord (>= 3.0)
activesupport (>= 3.0)
- version_gem (1.0.0)
+ version_gem (1.1.0)
version_sorter (2.2.4)
view_component (2.71.0)
activesupport (>= 5.0.0, < 8.0)
@@ -1522,6 +1534,7 @@ PLATFORMS
ruby
DEPENDENCIES
+ CFPropertyList
RedCloth (~> 4.3.2)
acme-client (~> 2.0)
activerecord-explain-analyze (~> 0.1)
@@ -1529,17 +1542,18 @@ DEPENDENCIES
addressable (~> 2.8)
akismet (~> 3.0)
apollo_upload_server (~> 2.1.0)
+ arr-pm (~> 0.0.12)
asana (~> 0.10.13)
asciidoctor (~> 2.0.17)
asciidoctor-include-ext (~> 0.4.0)
asciidoctor-kroki (~> 0.5.0)
asciidoctor-plantuml (~> 0.0.16)
atlassian-jwt (~> 0.2.0)
- attr_encrypted (~> 3.1.0)
+ attr_encrypted (~> 3.2.4)!
autoprefixer-rails (= 10.2.5.1)
awesome_print
aws-sdk-cloudformation (~> 1)
- aws-sdk-core (~> 3.131.0)
+ aws-sdk-core (~> 3.159.0)
aws-sdk-s3 (~> 1.114.0)
babosa (~> 1.0.4)
base32 (~> 0.3.0)
@@ -1558,12 +1572,13 @@ DEPENDENCIES
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.7)
- commonmarker (~> 0.23.4)
+ commonmarker (~> 0.23.6)
concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
countries (~> 3.0)
creole (~> 0.5.0)
crystalball (~> 0.7.0)
+ cvss-suite (~> 3.0.1)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
declarative_policy (~> 1.1.0)
@@ -1586,8 +1601,6 @@ DEPENDENCIES
email_reply_trimmer (~> 0.1)
email_spec (~> 2.2.0)
error_tracking_open_api!
- erubi (~> 1.9.0)
- escape_utils (~> 1.1)
factory_bot_rails (~> 6.2.0)
faraday (~> 1.0)
faraday_middleware-aws-sigv4 (~> 0.3.0)
@@ -1622,7 +1635,7 @@ DEPENDENCIES
gitlab-net-dns (~> 0.9.1)
gitlab-omniauth-openid-connect (~> 0.10.0)
gitlab-sidekiq-fetcher (= 0.8.0)
- gitlab-styles (~> 8.0.0)
+ gitlab-styles (~> 9.0.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.2.0)
gon (~> 6.4.0)
@@ -1632,6 +1645,8 @@ DEPENDENCIES
grape (~> 1.5.2)
grape-entity (~> 0.10.0)
grape-path-helpers (~> 1.7.1)
+ grape-swagger (~> 1.5.0)
+ grape-swagger-entity (~> 0.5.1)
grape_logging (~> 1.8)
graphiql-rails (~> 1.8)
graphlient (~> 0.5.0)
@@ -1652,6 +1667,7 @@ DEPENDENCIES
httparty (~> 0.16.4)
icalendar
invisible_captcha (~> 1.1.0)
+ ipaddr (= 1.2.2)
ipaddress (~> 0.8.3)
ipynbdiff!
jira-ruby (~> 2.1.4)
@@ -1664,18 +1680,18 @@ DEPENDENCIES
knapsack (~> 1.21.1)
kramdown (~> 2.3.1)
kubeclient (~> 4.9.3)
- lefthook (~> 1.1.1)
+ lefthook (~> 1.1.3)
letter_opener_web (~> 2.0.0)
license_finder (~> 7.0)
licensee (~> 9.15)
lockbox (~> 0.6.2)
lograge (~> 0.5)
- loofah (~> 2.18.0)
- lookbook (~> 1.0)
+ loofah (~> 2.19.0)
+ lookbook (~> 1.0, >= 1.0.8)
lru_redux
mail (= 2.7.1)
mail-smtp_pool (~> 0.1.0)!
- marginalia (~> 1.10.0)
+ marginalia (~> 1.11.1)
memory_profiler (~> 0.9)
microsoft_graph_mailer (~> 0.1.0)!
mini_magick (~> 4.10.1)
@@ -1689,32 +1705,32 @@ DEPENDENCIES
ohai (~> 16.10)
oj (~> 3.13.21)
omniauth (~> 2.1.0)
- omniauth-alicloud (~> 1.0.1)
+ omniauth-alicloud (~> 2.0.0)
omniauth-atlassian-oauth2 (~> 0.2.0)
omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.3)
- omniauth-azure-activedirectory-v2 (~> 1.0)
+ omniauth-azure-activedirectory-v2 (~> 2.0)
omniauth-azure-oauth2 (~> 0.0.9)!
omniauth-cas3 (~> 1.1.4)!
omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)
- omniauth-github (= 2.0.0)
+ omniauth-github (= 2.0.1)
omniauth-gitlab (~> 4.0.0)!
- omniauth-google-oauth2 (~> 1.0.1)!
+ omniauth-google-oauth2 (~> 1.1)
omniauth-oauth2-generic (~> 0.2.2)
- omniauth-rails_csrf_protection
omniauth-salesforce (~> 1.0.5)!
omniauth-saml (~> 2.0.0)
omniauth-shibboleth (~> 1.3.0)
omniauth-twitter (~> 1.4)
omniauth_crowd (~> 2.4.0)!
+ openssl (= 2.2.1)
org-ruby (~> 0.9.12)
- pact (~> 1.12)
+ pact (~> 1.63)
parallel (~> 1.19)
parslet (~> 1.8)
peek (~> 1.1)
- pg (~> 1.4.0)
- pg_query (~> 2.1.0)
+ pg (~> 1.4.3)
+ pg_query (~> 2.1.4)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.16)
@@ -1724,22 +1740,22 @@ DEPENDENCIES
puma (~> 5.6.5)
puma_worker_killer (~> 0.3.1)
rack (~> 2.2.4)
- rack-attack (~> 6.6.0)
- rack-cors (~> 1.1.0)
- rack-oauth2 (~> 1.21.2)
- rack-proxy (~> 0.7.2)
- rack-timeout (~> 0.6.0)
+ rack-attack (~> 6.6.1)
+ rack-cors (~> 1.1.1)
+ rack-oauth2 (~> 1.21.3)
+ rack-proxy (~> 0.7.4)
+ rack-timeout (~> 0.6.3)
rails (~> 6.1.6.1)
rails-controller-testing
rails-i18n (~> 7.0)
rainbow (~> 3.0)
rbtrace (~> 0.4)
rdoc (~> 6.3.2)
- re2 (~> 1.4.0)
+ re2 (~> 1.5.0)
recaptcha (~> 4.11)
redis (~> 4.7.0)
redis-actionpack (~> 5.3.0)
- redis-namespace (~> 1.8.1)
+ redis-namespace (~> 1.9.0)
request_store (~> 1.5)
responders (~> 3.0)
retriable (~> 3.1.2)
@@ -1755,7 +1771,6 @@ DEPENDENCIES
rubocop
ruby-fogbugz (~> 0.2.1)
ruby-magic (~> 0.5)
- ruby-prof (~> 1.3.0)
ruby-progressbar (~> 1.10)
ruby-saml (~> 1.13.0)
ruby_parser (~> 3.15)
@@ -1773,7 +1788,7 @@ DEPENDENCIES
settingslogic (~> 2.0.9)
shoulda-matchers (~> 5.1.0)
sidekiq (~> 6.4.0)
- sidekiq-cron (~> 1.4.0)
+ sidekiq-cron (~> 1.8.0)
sigdump (~> 0.2.4)
simple_po_parser (~> 1.1.6)
simplecov (~> 0.21)
@@ -1781,7 +1796,7 @@ DEPENDENCIES
simplecov-lcov (~> 0.8.0)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
- solargraph (~> 0.46.0)
+ solargraph (~> 0.47.2)
spamcheck (~> 1.0.0)
spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
@@ -1798,7 +1813,7 @@ DEPENDENCIES
thrift (>= 0.16.0)
timecop (~> 0.9.1)
timfel-krb5-auth (~> 0.8)
- toml-rb (~> 2.0)
+ toml-rb (~> 2.2.0)
truncato (~> 0.7.12)
typhoeus (~> 1.4.0)
u2f (~> 0.2.1)
@@ -1818,4 +1833,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.3)
BUNDLED WITH
- 2.3.15
+ 2.3.23
diff --git a/PROCESS.md b/PROCESS.md
index 2757075e354..699a08bc9c8 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -1,221 +1,3 @@
-## GitLab core team & GitLab Inc. contribution process
+The content of this document was moved to [another location](https://docs.gitlab.com/ee/development/contributing/).
----
-
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Purpose of describing the contributing process](#purpose-of-describing-the-contributing-process)
-- [Common actions](#common-actions)
- - [Merge request coaching](#merge-request-coaching)
-- [Assigning issues](#assigning-issues)
-- [Be kind](#be-kind)
-- [Bugs](#bugs)
- - [Regressions](#regressions)
- - [Managing bugs](#managing-bugs)
-- [Release retrospective and kickoff](#release-retrospective-and-kickoff)
-- [Copy & paste responses](#copy--paste-responses)
- - [Improperly formatted issue](#improperly-formatted-issue)
- - [Issue report for old version](#issue-report-for-old-version)
- - [Support requests and configuration questions](#support-requests-and-configuration-questions)
- - [Code format](#code-format)
- - [Issue fixed in newer version](#issue-fixed-in-newer-version)
- - [Improperly formatted merge request](#improperly-formatted-merge-request)
- - [Seeking community contributions](#seeking-community-contributions)
- - [Only accepting merge requests with green tests](#only-accepting-merge-requests-with-green-tests)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
----
-
-## Purpose of describing the contributing process
-
-Below we describe the contributing process to GitLab for two reasons:
-
-1. Contributors know what to expect from maintainers (possible responses, friendly
- treatment, etc.)
-1. Maintainers know what to expect from contributors (use the latest version,
- ensure that the issue is addressed, friendly treatment, etc.).
-
-- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
-
-## Common actions
-
-### Merge request coaching
-
-Several people from the [GitLab team][team] are helping community members to get
-their contributions accepted by meeting our [Definition of done][done].
-
-What you can expect from them is described at https://about.gitlab.com/job-families/expert/merge-request-coach/.
-
-### Milestones on community contribution issues
-
-The milestone of an issue that is currently being worked on by a community contributor
-should not be set to a named GitLab milestone (e.g. 11.7, 11.8), until the associated
-merge request is very close to being merged, and we will likely know in which named
-GitLab milestone the issue will land. There are many factors that influence when
-a community contributor finishes an issue, or even at all. So we should set this
-milestone only when we have more certainty.
-
-Note this only applies to issues currently assigned to community contributors. For
-issues assigned to GitLabbers, we are [ambitious in assigning milestones to issues](https://about.gitlab.com/direction/#how-we-plan-releases).
-
-## Assigning issues
-
-If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
-
-## Be kind
-
-Be kind to people trying to contribute. Be aware that people may be a non-native
-English speaker, they might not understand things or they might be very
-sensitive as to how you word things. Use Emoji to express your feelings (heart,
-star, smile, etc.). Some good tips about code reviews can be found in our
-[Code Review Guidelines].
-
-[Code Review Guidelines]: https://docs.gitlab.com/ee/development/code_review.html
-
-## Feature flags
-
-Overview and details of feature flag processes in development of GitLab itself is described in [feature flags process documentation](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/).
-
-Guides on how to include feature flags in your backend/frontend code while developing GitLab are described in [developing with feature flags documentation](https://docs.gitlab.com/ee/development/feature_flags).
-
-Getting access and how to expose the feature to users is detailed in [controlling feature flags documentation](https://docs.gitlab.com/ee/development/feature_flags/controls.html).
-
-## Feature proposals from the 22nd to the 1st
-
-To allow the Product and Engineering teams time to discuss issues that will be placed into an upcoming milestone,
-Product Managers must have their proposal for that milestone ready by the 22nd of each month.
-
-This proposal will be shared with Engineering for discussion, feedback, and planning.
-The plan for the upcoming milestone must be finalized by the 1st of the month, one week before kickoff on the 8th.
-
-## Bugs
-
-A ~bug is a defect, error, failure which causes the system to behave incorrectly or prevents it from fulfilling the product requirements.
-
-The level of impact of a ~bug can vary from blocking a whole functionality
-or a feature usability bug. A bug should always be linked to a severity level.
-Refer to our [severity levels](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#severity-labels)
-
-Whether the bug is also a regression or not, the triage process should start as soon as possible.
-Ensure that the Engineering Manager and/or the Product Manager for the relative area is involved to prioritize the work as needed.
-
-### Regressions
-
-A ~regression implies that a previously **verified working functionality** no longer works.
-Regressions are a subset of bugs. We use the ~regression label to imply that the defect caused the functionality to regress.
-The label tells us that something worked before and it needs extra attention from Engineering and Product Managers to schedule/reschedule.
-
-The regression label does not apply to ~bugs for new features for which functionality was **never verified as working**.
-These, by definition, are not regressions.
-
-A regression should always have the `regression:xx.x` label on it to designate when it was introduced.
-
-Regressions should be considered high priority issues that should be solved as soon as possible, especially if they have severe impact on users.
-
-### Managing bugs
-
-**Prioritization:** We give higher priority to regressions on features that worked in the last recent monthly release and the current release candidates.
-
-When a bug is found:
-1. Create an issue describing the problem in the most detailed way possible.
-1. If possible, provide links to real examples and how to reproduce the problem.
-1. Label the issue properly, by respecting the [Partial triage level](https://about.gitlab.com/handbook/engineering/issue-triage/#partial-triage).
-1. Notify the respective Engineering Manager to evaluate and apply the [Severity label](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#severity-labels) and [Priority label](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#priority-labels).
-The counterpart Product Manager is included to weigh-in on prioritization as needed.
-1. If the ~bug is **NOT** a regression:
- 1. The Engineering Manager decides which milestone the bug will be fixed. The appropriate milestone is applied.
-1. If the bug is a ~regression:
- 1. Determine the release that the regression affects and add the corresponding `regression:xx.x` label.
- 1. If the affected release version can't be determined, add the generic ~regression label for the time being.
- 1. If the affected version `xx.x` in `regression:xx.x` is the **current release**, it's recommended to schedule the fix for the current milestone.
- 1. This falls under regressions which worked in the last release and the current RCs. More detailed explanations in the **Prioritization** section above.
- 1. If the affected version `xx.x` in `regression:xx.x` is older than the **current release**
- 1. If the regression is an ~S1 severity, it's recommended to schedule the fix for the current milestone. We would like to fix the highest severity regression as soon as we can.
- 1. If the regression is an ~S2, ~S3 or ~S4 severity, the regression may be scheduled for later milestones at the discretion of the Engineering Manager and Product Manager.
-
-## Release retrospective and kickoff
-
-- [Retrospective](https://about.gitlab.com/handbook/engineering/workflow/#retrospective)
-- [Kickoff](https://about.gitlab.com/handbook/engineering/workflow/#kickoff)
-
-## Copy & paste responses
-
-### Improperly formatted issue
-
-```
-Thanks for the issue report. Please reformat your issue to conform to the
-[contributing guidelines](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#issue-tracker-guidelines).
-```
-
-### Issue report for old version
-
-```
-Thanks for the issue report but we only support issues for the latest stable version of GitLab.
-I'm closing this issue but if you still experience this problem in the latest stable version,
-please open a new issue (but also reference the old issue(s)).
-Make sure to also include the necessary debugging information conforming to the issue tracker
-guidelines found in our [contributing guidelines](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#issue-tracker-guidelines).
-```
-
-### Support requests and configuration questions
-
-```
-Thanks for your interest in GitLab. We don't use the issue tracker for support
-requests and configuration questions. Please check our
-[getting help](https://about.gitlab.com/getting-help/) page to see all of the available
-support options. Also, have a look at the [contribution guidelines](https://docs.gitlab.com/ee/development/contributing/index.html)
-for more information.
-```
-
-### Code format
-
-```
-Please use \`\`\` to format console output, logs, and code as it's very hard to read otherwise.
-```
-
-### Issue fixed in newer version
-
-```
-Thanks for the issue report. This issue has already been fixed in newer versions of GitLab.
-Due to the size of this project and our limited resources we are only able to support the
-latest stable release as outlined in our [contributing guidelines](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html).
-In order to get this bug fix and enjoy many new features please
-[upgrade](https://gitlab.com/gitlab-org/gitlab/tree/master/doc/update).
-If you still experience issues at that time please open a new issue following our issue
-tracker guidelines found in the [contributing guidelines](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#issue-tracker-guidelines).
-```
-
-### Improperly formatted merge request
-
-```
-Thanks for your interest in improving the GitLab codebase!
-Please update your merge request according to the [contributing guidelines](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/contributing/merge_request_workflow.md#merge-request-guidelines).
-```
-
-### Seeking community contributions
-
-```
-Is there an issue on the
-[issue tracker](https://gitlab.com/gitlab-org/gitlab/issues) that is
-similar to this? Could you please link it here?
-Please be aware that new functionality that is not marked
-[`Seeking community contributions`](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#label-for-community-contributors)
-might not make it into GitLab.
-```
-
-### Only accepting merge requests with green tests
-
-```
-We can only accept a merge request if all the tests are green. I've just
-restarted the build. When the tests are still not passing after this restart and
-you're sure that is does not have anything to do with your code changes, please
-rebase with master to see if that solves the issue.
-```
-
-[team]: https://about.gitlab.com/team/
-[done]: https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#definition-of-done
-[automatic_ce_ee_merge]: https://docs.gitlab.com/ee/development/automatic_ce_ee_merge.html
-[ee_features]: https://docs.gitlab.com/ee/development/ee_features.html
+<!-- This redirect file can be deleted after <2023-10-01>. -->
diff --git a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
index 461b2dad479..57a237c3e84 100644
--- a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
+++ b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
@@ -45,16 +45,34 @@ export default {
'initialActiveAccessTokens',
'noActiveTokensMessage',
'showRole',
+ 'information',
],
data() {
return {
- activeAccessTokens: this.initialActiveAccessTokens,
+ activeAccessTokens: convertObjectPropsToCamelCase(this.initialActiveAccessTokens, {
+ deep: true,
+ }),
currentPage: INITIAL_PAGE,
};
},
computed: {
filteredFields() {
- return this.showRole ? FIELDS : FIELDS.filter((field) => field.key !== 'role');
+ const ignoredFields = [];
+
+ // Show 'action' column only when there are no active tokens or when some of them have a revokePath
+ const showAction =
+ this.activeAccessTokens.length === 0 ||
+ this.activeAccessTokens.some((token) => token.revokePath);
+
+ if (!showAction) {
+ ignoredFields.push('action');
+ }
+
+ if (!this.showRole) {
+ ignoredFields.push('role');
+ }
+
+ return FIELDS.filter(({ key }) => !ignoredFields.includes(key));
},
header() {
return sprintf(this.$options.i18n.header, {
@@ -100,6 +118,10 @@ export default {
<hr />
<h5>{{ header }}</h5>
+ <p v-if="information" data-testid="information-section">
+ {{ information }}
+ </p>
+
<gl-table
data-testid="active-tokens"
:empty-text="noActiveTokensMessage"
diff --git a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
index 6b52bd84656..ce5342ad1ea 100644
--- a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
+++ b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
@@ -2,10 +2,13 @@
import { GlAlert } from '@gitlab/ui';
import { createAlert, VARIANT_INFO } from '~/flash';
import { __, n__, sprintf } from '~/locale';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
import { EVENT_ERROR, EVENT_SUCCESS, FORM_SELECTOR } from './constants';
+const convertEventDetail = (event) => convertObjectPropsToCamelCase(event.detail, { deep: true });
+
export default {
EVENT_ERROR,
EVENT_SUCCESS,
@@ -54,8 +57,8 @@ export default {
/** @type {HTMLFormElement} */
this.form = document.querySelector(FORM_SELECTOR);
- /** @type {HTMLInputElement} */
- this.submitButton = this.form.querySelector('input[type=submit]');
+ /** @type {HTMLButtonElement} */
+ this.submitButton = this.form.querySelector('[type=submit]');
},
methods: {
beforeDisplayResults() {
@@ -68,20 +71,21 @@ export default {
onError(event) {
this.beforeDisplayResults();
- const [{ errors }] = event.detail;
+ const [{ errors }] = convertEventDetail(event);
this.errors = errors;
this.submitButton.classList.remove('disabled');
+ this.submitButton.removeAttribute('disabled');
},
onSuccess(event) {
this.beforeDisplayResults();
- const [{ new_token: newToken }] = event.detail;
+ const [{ newToken }] = convertEventDetail(event);
this.newToken = newToken;
this.infoAlert = createAlert({ message: this.alertInfoMessage, variant: VARIANT_INFO });
- // Selectively reset all input fields except for the date picker and submit.
+ // Selectively reset all input fields except for the date picker.
// The form token creation is not controlled by Vue.
this.form.querySelectorAll('input[type=text]:not([id$=expires_at])').forEach((el) => {
el.value = '';
diff --git a/app/assets/javascripts/access_tokens/components/tokens_app.vue b/app/assets/javascripts/access_tokens/components/tokens_app.vue
index 10d4d62d803..1f72f5e19e2 100644
--- a/app/assets/javascripts/access_tokens/components/tokens_app.vue
+++ b/app/assets/javascripts/access_tokens/components/tokens_app.vue
@@ -79,7 +79,7 @@ export default {
</script>
<template>
- <div>
+ <div class="js-search-settings-section">
<token
v-for="(tokenData, tokenType) in enabledTokenTypes"
:key="tokenType"
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index f0c1b415157..510f118bbb5 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -20,6 +20,7 @@ export const initAccessTokenTableApp = () => {
const {
accessTokenType,
accessTokenTypePlural,
+ information,
initialActiveAccessTokens: initialActiveAccessTokensJson,
noActiveTokensMessage: noTokensMessage,
} = el.dataset;
@@ -30,12 +31,7 @@ export const initAccessTokenTableApp = () => {
sprintf(__('This user has no active %{accessTokenTypePlural}.'), { accessTokenTypePlural });
const showRole = 'showRole' in el.dataset;
- const initialActiveAccessTokens = convertObjectPropsToCamelCase(
- JSON.parse(initialActiveAccessTokensJson),
- {
- deep: true,
- },
- );
+ const initialActiveAccessTokens = JSON.parse(initialActiveAccessTokensJson);
return new Vue({
el,
@@ -43,6 +39,7 @@ export const initAccessTokenTableApp = () => {
provide: {
accessTokenType,
accessTokenTypePlural,
+ information,
initialActiveAccessTokens,
noActiveTokensMessage,
showRole,
@@ -103,7 +100,7 @@ export const initNewAccessTokenApp = () => {
export const initTokensApp = () => {
const el = document.getElementById('js-tokens-app');
- if (!el) return false;
+ if (!el) return null;
const tokensData = convertObjectPropsToCamelCase(JSON.parse(el.dataset.tokensData), {
deep: true,
diff --git a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
index 8ad218ab97b..a41ff42df20 100644
--- a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
+++ b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
@@ -2,7 +2,7 @@
import { GlModal, GlTabs, GlTab, GlSearchBoxByType, GlSprintf, GlBadge } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import ReviewTabContainer from '~/add_context_commits_modal/components/review_tab_container.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
@@ -193,7 +193,7 @@ export default {
window.location.reload();
}
if (!values[0] && !values[1]) {
- createFlash({
+ createAlert({
message: s__(
'ContextCommits|Failed to create/remove context commits. Please try again.',
),
diff --git a/app/assets/javascripts/add_context_commits_modal/store/actions.js b/app/assets/javascripts/add_context_commits_modal/store/actions.js
index 4e5a2c7b371..d4c9db2fa33 100644
--- a/app/assets/javascripts/add_context_commits_modal/store/actions.js
+++ b/app/assets/javascripts/add_context_commits_modal/store/actions.js
@@ -1,6 +1,6 @@
import _ from 'lodash';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -71,7 +71,7 @@ export const createContextCommits = ({ state }, { commits, forceReload = false }
})
.catch(() => {
if (forceReload) {
- createFlash({
+ createAlert({
message: s__('ContextCommits|Failed to create context commits. Please try again.'),
});
}
@@ -113,7 +113,7 @@ export const removeContextCommits = ({ state }, forceReload = false) =>
})
.catch(() => {
if (forceReload) {
- createFlash({
+ createAlert({
message: s__('ContextCommits|Failed to delete context commits. Please try again.'),
});
}
diff --git a/app/assets/javascripts/admin/background_migrations/components/database_listbox.vue b/app/assets/javascripts/admin/background_migrations/components/database_listbox.vue
index 7f6e5dc4f35..80c216024a0 100644
--- a/app/assets/javascripts/admin/background_migrations/components/database_listbox.vue
+++ b/app/assets/javascripts/admin/background_migrations/components/database_listbox.vue
@@ -44,7 +44,7 @@ export default {
:items="databases"
right
:toggle-text="selectedDatabase"
- aria-labelledby="label"
+ toggle-aria-labelled-by="label"
@select="selectDatabase"
/>
</div>
diff --git a/app/assets/javascripts/admin/broadcast_messages/components/base.vue b/app/assets/javascripts/admin/broadcast_messages/components/base.vue
new file mode 100644
index 00000000000..b7bafe46327
--- /dev/null
+++ b/app/assets/javascripts/admin/broadcast_messages/components/base.vue
@@ -0,0 +1,112 @@
+<script>
+import { GlPagination } from '@gitlab/ui';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+import { createAlert, VARIANT_DANGER } from '~/flash';
+import { s__ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import MessagesTable from './messages_table.vue';
+
+const PER_PAGE = 20;
+
+export default {
+ name: 'BroadcastMessagesBase',
+ components: {
+ GlPagination,
+ MessagesTable,
+ },
+
+ props: {
+ page: {
+ type: Number,
+ required: true,
+ },
+ messagesCount: {
+ type: Number,
+ required: true,
+ },
+ messages: {
+ type: Array,
+ required: true,
+ },
+ },
+
+ i18n: {
+ deleteError: s__(
+ 'BroadcastMessages|There was an issue deleting this message, please try again later.',
+ ),
+ },
+
+ data() {
+ return {
+ currentPage: this.page,
+ totalMessages: this.messagesCount,
+ visibleMessages: this.messages.map((message) => ({
+ ...message,
+ disable_delete: false,
+ })),
+ };
+ },
+
+ computed: {
+ hasVisibleMessages() {
+ return this.visibleMessages.length > 0;
+ },
+ },
+
+ watch: {
+ totalMessages(newVal, oldVal) {
+ // Pagination controls disappear when there is only
+ // one page worth of messages. Since we're relying on static data,
+ // this could hide messages on the next page, or leave the user
+ // stranded on page 2 when deleting the last message.
+ // Force a page reload to avoid this edge case.
+ if (newVal === PER_PAGE && oldVal === PER_PAGE + 1) {
+ redirectTo(this.buildPageUrl(1));
+ }
+ },
+ },
+
+ methods: {
+ buildPageUrl(newPage) {
+ return buildUrlWithCurrentLocation(`?page=${newPage}`);
+ },
+
+ async deleteMessage(messageId) {
+ const index = this.visibleMessages.findIndex((m) => m.id === messageId);
+ if (!index === -1) return;
+
+ const message = this.visibleMessages[index];
+ this.$set(this.visibleMessages, index, { ...message, disable_delete: true });
+
+ try {
+ await axios.delete(message.delete_path);
+ } catch (e) {
+ this.$set(this.visibleMessages, index, { ...message, disable_delete: false });
+ createAlert({ message: this.$options.i18n.deleteError, variant: VARIANT_DANGER });
+ return;
+ }
+
+ // Remove the message from the table
+ this.visibleMessages = this.visibleMessages.filter((m) => m.id !== messageId);
+ this.totalMessages -= 1;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <messages-table
+ v-if="hasVisibleMessages"
+ :messages="visibleMessages"
+ @delete-message="deleteMessage"
+ />
+ <gl-pagination
+ v-model="currentPage"
+ :total-items="totalMessages"
+ :link-gen="buildPageUrl"
+ align="center"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/broadcast_messages/components/messages_table.vue b/app/assets/javascripts/admin/broadcast_messages/components/messages_table.vue
new file mode 100644
index 00000000000..1408312d3e4
--- /dev/null
+++ b/app/assets/javascripts/admin/broadcast_messages/components/messages_table.vue
@@ -0,0 +1,113 @@
+<script>
+import { GlButton, GlTableLite, GlSafeHtmlDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+const DEFAULT_TD_CLASSES = 'gl-vertical-align-middle!';
+
+export default {
+ name: 'MessagesTable',
+ components: {
+ GlButton,
+ GlTableLite,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ i18n: {
+ edit: __('Edit'),
+ delete: __('Delete'),
+ },
+ props: {
+ messages: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ fields() {
+ if (this.glFeatures.roleTargetedBroadcastMessages) return this.$options.allFields;
+ return this.$options.allFields.filter((f) => f.key !== 'target_roles');
+ },
+ },
+ allFields: [
+ {
+ key: 'status',
+ label: __('Status'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'preview',
+ label: __('Preview'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'starts_at',
+ label: __('Starts'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'ends_at',
+ label: __('Ends'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'target_roles',
+ label: __('Target roles'),
+ tdClass: DEFAULT_TD_CLASSES,
+ thAttr: { 'data-testid': 'target-roles-th' },
+ },
+ {
+ key: 'target_path',
+ label: __('Target Path'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'type',
+ label: __('Type'),
+ tdClass: DEFAULT_TD_CLASSES,
+ },
+ {
+ key: 'buttons',
+ label: '',
+ tdClass: `${DEFAULT_TD_CLASSES} gl-white-space-nowrap`,
+ },
+ ],
+ safeHtmlConfig: {
+ ADD_TAGS: ['use'],
+ },
+};
+</script>
+<template>
+ <gl-table-lite
+ :items="messages"
+ :fields="fields"
+ :tbody-tr-attr="{ 'data-testid': 'message-row' }"
+ stacked="md"
+ >
+ <template #cell(preview)="{ item: { preview } }">
+ <div v-safe-html:[$options.safeHtmlConfig]="preview"></div>
+ </template>
+
+ <template #cell(buttons)="{ item: { id, edit_path, disable_delete } }">
+ <gl-button
+ icon="pencil"
+ :aria-label="$options.i18n.edit"
+ :href="edit_path"
+ data-testid="edit-message"
+ />
+
+ <gl-button
+ class="gl-ml-3"
+ icon="remove"
+ variant="danger"
+ :aria-label="$options.i18n.delete"
+ rel="nofollow"
+ :disabled="disable_delete"
+ :data-testid="`delete-message-${id}`"
+ @click="$emit('delete-message', id)"
+ />
+ </template>
+ </gl-table-lite>
+</template>
diff --git a/app/assets/javascripts/admin/broadcast_messages/index.js b/app/assets/javascripts/admin/broadcast_messages/index.js
new file mode 100644
index 00000000000..81952d2033e
--- /dev/null
+++ b/app/assets/javascripts/admin/broadcast_messages/index.js
@@ -0,0 +1,21 @@
+import Vue from 'vue';
+import BroadcastMessagesBase from './components/base.vue';
+
+export default () => {
+ const el = document.querySelector('#js-broadcast-messages');
+ const { page, messagesCount, messages } = el.dataset;
+
+ return new Vue({
+ el,
+ name: 'BroadcastMessages',
+ render(createElement) {
+ return createElement(BroadcastMessagesBase, {
+ props: {
+ page: Number(page),
+ messagesCount: Number(messagesCount),
+ messages: JSON.parse(messages),
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/admin/deploy_keys/components/table.vue b/app/assets/javascripts/admin/deploy_keys/components/table.vue
index 6b140590938..be85ee43891 100644
--- a/app/assets/javascripts/admin/deploy_keys/components/table.vue
+++ b/app/assets/javascripts/admin/deploy_keys/components/table.vue
@@ -5,7 +5,7 @@ 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 { createAlert } from '~/flash';
import csrf from '~/lib/utils/csrf';
export default {
@@ -151,7 +151,7 @@ export default {
}),
);
} catch (error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.apiErrorMessage,
captureError: true,
error,
diff --git a/app/assets/javascripts/admin/statistics_panel/store/actions.js b/app/assets/javascripts/admin/statistics_panel/store/actions.js
index 77782cdc187..4f952698d7a 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/actions.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -21,7 +21,7 @@ export const receiveStatisticsSuccess = ({ commit }, statistics) =>
export const receiveStatisticsError = ({ commit }, error) => {
commit(types.RECEIVE_STATISTICS_ERROR, error);
- createFlash({
+ createAlert({
message: s__('AdminDashboard|Error loading the statistics. Please try again'),
});
};
diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue
index b4b84594276..f569cda0a4b 100644
--- a/app/assets/javascripts/admin/users/components/users_table.vue
+++ b/app/assets/javascripts/admin/users/components/users_table.vue
@@ -1,6 +1,6 @@
<script>
import { GlSkeletonLoader, GlTable } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { convertNodeIdsFromGraphQLIds } from '~/graphql_shared/utils';
import { thWidthPercent } from '~/lib/utils/table_utility';
import { s__, __ } from '~/locale';
@@ -50,7 +50,7 @@ export default {
}, {});
},
error(error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.groupCountFetchError,
captureError: true,
error,
diff --git a/app/assets/javascripts/alert_management/components/alert_management_table.vue b/app/assets/javascripts/alert_management/components/alert_management_table.vue
index 37a6ea16018..c0cac958a42 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -216,8 +216,11 @@ export default {
this.pagination = initialPaginationState;
this.sort = sortObjectToString({ sortBy, sortDesc });
},
+ showAlertLink({ iid }) {
+ return joinPaths(window.location.pathname, iid, 'details');
+ },
navigateToAlertDetails({ iid }, index, { metaKey }) {
- return visitUrl(joinPaths(window.location.pathname, iid, 'details'), metaKey);
+ return visitUrl(this.showAlertLink({ iid }), metaKey);
},
hasAssignees(assignees) {
return Boolean(assignees.nodes?.length);
@@ -357,7 +360,7 @@ export default {
:title="`${item.iid} - ${item.title}`"
data-testid="idField"
>
- #{{ item.iid }} {{ item.title }}
+ <gl-link :href="showAlertLink(item)"> #{{ item.iid }} {{ item.title }} </gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index 1f970ef1846..bf456b6adaa 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -2,7 +2,7 @@
import { GlButton, GlAlert, GlTabs, GlTab } from '@gitlab/ui';
import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_SUCCESS } from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import httpStatusCodes from '~/lib/utils/http_status';
import { typeSet, i18n, tabIndices } from '../constants';
@@ -75,7 +75,7 @@ export default {
return nodes;
},
error(err) {
- createFlash({ message: err });
+ createAlert({ message: err });
},
},
currentIntegration: {
@@ -125,7 +125,7 @@ export default {
.then(({ data: { httpIntegrationCreate, prometheusIntegrationCreate } = {} } = {}) => {
const error = httpIntegrationCreate?.errors[0] || prometheusIntegrationCreate?.errors[0];
if (error) {
- createFlash({ message: error });
+ createAlert({ message: error });
return;
}
@@ -140,7 +140,7 @@ export default {
}
})
.catch(() => {
- createFlash({ message: ADD_INTEGRATION_ERROR });
+ createAlert({ message: ADD_INTEGRATION_ERROR });
})
.finally(() => {
this.isUpdating = false;
@@ -161,7 +161,7 @@ export default {
.then(({ data: { httpIntegrationUpdate, prometheusIntegrationUpdate } = {} } = {}) => {
const error = httpIntegrationUpdate?.errors[0] || prometheusIntegrationUpdate?.errors[0];
if (error) {
- createFlash({ message: error });
+ createAlert({ message: error });
return;
}
@@ -174,13 +174,13 @@ export default {
this.clearCurrentIntegration({ type });
}
- createFlash({
+ createAlert({
message: this.$options.i18n.changesSaved,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
})
.catch(() => {
- createFlash({ message: UPDATE_INTEGRATION_ERROR });
+ createAlert({ message: UPDATE_INTEGRATION_ERROR });
})
.finally(() => {
this.isUpdating = false;
@@ -198,7 +198,7 @@ export default {
const [error] =
httpIntegrationResetToken?.errors || prometheusIntegrationResetToken.errors;
if (error) {
- return createFlash({ message: error });
+ return createAlert({ message: error });
}
const integration =
@@ -212,14 +212,14 @@ export default {
variables: integration,
});
- return createFlash({
+ return createAlert({
message: this.$options.i18n.changesSaved,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
},
)
.catch(() => {
- createFlash({ message: RESET_INTEGRATION_TOKEN_ERROR });
+ createAlert({ message: RESET_INTEGRATION_TOKEN_ERROR });
})
.finally(() => {
this.isUpdating = false;
@@ -252,7 +252,7 @@ export default {
);
},
error() {
- createFlash({ message: DEFAULT_ERROR });
+ createAlert({ message: DEFAULT_ERROR });
},
});
} else {
@@ -272,7 +272,7 @@ export default {
this.tabIndex = tabIndex;
})
.catch(() => {
- createFlash({ message: DEFAULT_ERROR });
+ createAlert({ message: DEFAULT_ERROR });
});
},
deleteIntegration({ id, type }) {
@@ -290,16 +290,16 @@ export default {
.then(({ data: { httpIntegrationDestroy } = {} } = {}) => {
const error = httpIntegrationDestroy?.errors[0];
if (error) {
- return createFlash({ message: error });
+ return createAlert({ message: error });
}
this.clearCurrentIntegration({ type });
- return createFlash({
+ return createAlert({
message: this.$options.i18n.integrationRemoved,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
})
.catch(() => {
- createFlash({ message: DELETE_INTEGRATION_ERROR });
+ createAlert({ message: DELETE_INTEGRATION_ERROR });
})
.finally(() => {
this.isUpdating = false;
@@ -320,9 +320,9 @@ export default {
return service
.updateTestAlert(payload)
.then(() => {
- return createFlash({
+ return createAlert({
message: this.$options.i18n.alertSent,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
})
.catch((error) => {
@@ -330,7 +330,7 @@ export default {
if (error.response?.status === httpStatusCodes.FORBIDDEN) {
message = INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR;
}
- createFlash({ message });
+ createAlert({ message });
});
},
saveAndTestAlertPayload(integration, payload) {
diff --git a/app/assets/javascripts/alerts_settings/utils/cache_updates.js b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
index a50b6515afa..2e64312b0e0 100644
--- a/app/assets/javascripts/alerts_settings/utils/cache_updates.js
+++ b/app/assets/javascripts/alerts_settings/utils/cache_updates.js
@@ -1,5 +1,5 @@
import produce from 'immer';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { DELETE_INTEGRATION_ERROR, ADD_INTEGRATION_ERROR } from './error_messages';
@@ -59,7 +59,7 @@ const addIntegrationToStore = (
};
const onError = (data, message) => {
- createFlash({ message });
+ createAlert({ message });
throw new Error(data.errors);
};
diff --git a/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue b/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue
index 567e534d9cf..ffb61230661 100644
--- a/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue
+++ b/app/assets/javascripts/analytics/shared/components/value_stream_metrics.vue
@@ -1,7 +1,7 @@
<script>
import { GlSkeletonLoader } from '@gitlab/ui';
import { flatten, isEqual, keyBy } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { sprintf, s__ } from '~/locale';
import { METRICS_POPOVER_CONTENT } from '../constants';
import { removeFlash, prepareTimeMetricsData } from '../utils';
@@ -17,7 +17,7 @@ const requestData = ({ request, endpoint, path, params, name }) => {
),
{ requestTypeName: name },
);
- createFlash({ message });
+ createAlert({ message });
});
};
diff --git a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
index 457a52d3807..5651789e2c7 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
+++ b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
@@ -1,7 +1,7 @@
<script>
import { GlSkeletonLoader } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { number } from '~/lib/utils/unit_format';
import { __, s__ } from '~/locale';
import usageTrendsCountQuery from '../graphql/queries/usage_trends_count.query.graphql';
@@ -35,7 +35,7 @@ export default {
});
},
error(error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.loadCountsError,
captureError: true,
error,
diff --git a/app/assets/javascripts/api/projects_api.js b/app/assets/javascripts/api/projects_api.js
index 667aa878261..5b5abbdf50b 100644
--- a/app/assets/javascripts/api/projects_api.js
+++ b/app/assets/javascripts/api/projects_api.js
@@ -5,6 +5,7 @@ import { buildApiUrl } from './api_utils';
const PROJECTS_PATH = '/api/:version/projects.json';
const PROJECT_IMPORT_MEMBERS_PATH = '/api/:version/projects/:id/import_project_members/:project_id';
const PROJECT_REPOSITORY_SIZE_PATH = '/api/:version/projects/:id/repository_size';
+const PROJECT_TRANSFER_LOCATIONS_PATH = 'api/:version/projects/:id/transfer_locations';
export function getProjects(query, options, callback = () => {}) {
const url = buildApiUrl(PROJECTS_PATH);
@@ -42,3 +43,10 @@ export function updateRepositorySize(projectPath) {
);
return axios.post(url);
}
+
+export const getTransferLocations = (projectId, params = {}) => {
+ const url = buildApiUrl(PROJECT_TRANSFER_LOCATIONS_PATH).replace(':id', projectId);
+ const defaultParams = { per_page: DEFAULT_PER_PAGE };
+
+ return axios.get(url, { params: { ...defaultParams, ...params } });
+};
diff --git a/app/assets/javascripts/api/user_api.js b/app/assets/javascripts/api/user_api.js
index c743b18d572..369abe95d49 100644
--- a/app/assets/javascripts/api/user_api.js
+++ b/app/assets/javascripts/api/user_api.js
@@ -1,5 +1,5 @@
import { DEFAULT_PER_PAGE } from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
@@ -55,7 +55,7 @@ export function getUserProjects(userId, query, options, callback) {
})
.then(({ data }) => callback(data))
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong while fetching projects'),
}),
);
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index a3ffb4df7b7..9ab1d6bfd80 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -7,7 +7,7 @@ import { getEmojiScoreWithIntent } from '~/emoji/utils';
import { getCookie, setCookie, scrollToElement } from '~/lib/utils/common_utils';
import * as Emoji from '~/emoji';
import { dispose, fixTitle } from '~/tooltips';
-import createFlash from './flash';
+import { createAlert } from '~/flash';
import axios from './lib/utils/axios_utils';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { __ } from './locale';
@@ -491,7 +491,7 @@ export class AwardsHandler {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong on our end.'),
}),
);
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index d1570e16639..f68666f8a0c 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -2,7 +2,7 @@
import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton, GlSafeHtmlDirective } from '@gitlab/ui';
import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/flash';
import { s__, sprintf } from '~/locale';
import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue';
@@ -136,14 +136,14 @@ export default {
if (this.isEditing) {
return this.saveBadge()
.then(() => {
- createFlash({
+ createAlert({
message: s__('Badges|Badge saved.'),
- type: 'notice',
+ variant: VARIANT_INFO,
});
this.wasValidated = false;
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__(
'Badges|Saving the badge failed, please check the entered URLs and try again.',
),
@@ -154,14 +154,14 @@ export default {
return this.addBadge()
.then(() => {
- createFlash({
+ createAlert({
message: s__('Badges|New badge added.'),
- type: 'notice',
+ variant: VARIANT_INFO,
});
this.wasValidated = false;
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__(
'Badges|Adding the badge failed, please check the entered URLs and try again.',
),
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 0303930de5d..a7a21d65475 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf, GlModal } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/flash';
import { __, s__ } from '~/locale';
import Badge from './badge.vue';
import BadgeForm from './badge_form.vue';
@@ -40,13 +40,13 @@ export default {
onSubmitModal() {
this.deleteBadge(this.badgeInModal)
.then(() => {
- createFlash({
+ createAlert({
message: s__('Badges|The badge was deleted.'),
- type: 'notice',
+ variant: VARIANT_INFO,
});
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__('Badges|Deleting the badge failed, please try again.'),
});
throw error;
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
index 2b0aaa74e83..feac6f10b1e 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
@@ -1,5 +1,5 @@
import { isEmpty } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { scrollToElement } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants';
@@ -18,7 +18,7 @@ export const addDraftToDiscussion = ({ commit }, { endpoint, data }) =>
return res;
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('An error occurred adding a draft to the thread.'),
});
});
@@ -32,7 +32,7 @@ export const createNewDraft = ({ commit }, { endpoint, data }) =>
return res;
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('An error occurred adding a new draft.'),
});
});
@@ -44,7 +44,7 @@ export const deleteDraft = ({ commit, getters }, draft) =>
commit(types.DELETE_DRAFT, draft.id);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while deleting the comment'),
}),
);
@@ -62,7 +62,7 @@ export const fetchDrafts = ({ commit, getters, state, dispatch }) =>
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while fetching pending comments'),
}),
);
@@ -122,7 +122,7 @@ export const updateDraft = (
.then((data) => commit(types.RECEIVE_DRAFT_UPDATE_SUCCESS, data))
.then(callback)
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while updating the comment'),
}),
);
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
index df5214ea7ab..75e4ae63c18 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js
@@ -22,7 +22,11 @@ export const draftsPerFileHashAndLine = (state) =>
acc[draft.file_hash] = {};
}
- acc[draft.file_hash][draft.line_code] = draft;
+ if (!acc[draft.file_hash][draft.line_code]) {
+ acc[draft.file_hash][draft.line_code] = [];
+ }
+
+ acc[draft.file_hash][draft.line_code].push(draft);
}
return acc;
@@ -61,18 +65,15 @@ export const shouldRenderDraftRowInDiscussion = (state, getters) => (discussionI
export const draftForDiscussion = (state, getters) => (discussionId) =>
getters.draftsPerDiscussionId[discussionId] || {};
-export const draftForLine = (state, getters) => (diffFileSha, line, side = null) => {
+export const draftsForLine = (state, getters) => (diffFileSha, line, side = null) => {
const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha];
-
const key = side !== null ? parallelLineKey(line, side) : line.line_code;
+ const showDraftsForThisSide = showDraftOnSide(line, side);
- if (draftsForFile) {
- const draft = draftsForFile[key];
- if (draft && showDraftOnSide(line, side)) {
- return draft;
- }
+ if (showDraftsForThisSide && draftsForFile?.[key]) {
+ return draftsForFile[key];
}
- return {};
+ return [];
};
export const draftsForFile = (state) => (diffFileSha) =>
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 679940d1317..68f5180cc03 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names */
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -80,7 +80,7 @@ MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) {
success(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while fetching Markdown preview'),
}),
);
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
index 23b66405844..3239375bf7c 100644
--- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js
+++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
@@ -145,6 +145,20 @@ export const LINK_TEXT = {
customizable: false,
};
+export const INDENT_LINE = {
+ id: 'editing.indentLine',
+ description: __('Indent line'),
+ defaultKeys: ['mod+]'], // eslint-disable-line @gitlab/require-i18n-strings
+ customizable: false,
+};
+
+export const OUTDENT_LINE = {
+ id: 'editing.outdentLine',
+ description: __('Outdent line'),
+ defaultKeys: ['mod+['], // eslint-disable-line @gitlab/require-i18n-strings
+ customizable: false,
+};
+
export const TOGGLE_MARKDOWN_PREVIEW = {
id: 'editing.toggleMarkdownPreview',
description: __('Toggle Markdown preview'),
diff --git a/app/assets/javascripts/blame/blame_redirect.js b/app/assets/javascripts/blame/blame_redirect.js
new file mode 100644
index 00000000000..155e2a3a2cd
--- /dev/null
+++ b/app/assets/javascripts/blame/blame_redirect.js
@@ -0,0 +1,23 @@
+import { setUrlParams } from '~/lib/utils/url_utility';
+import { createAlert } from '~/flash';
+import { __ } from '~/locale';
+
+export default function redirectToCorrectBlamePage() {
+ const { hash } = window.location;
+ const linesPerPage = parseInt(document.querySelector('.js-per-page').dataset.perPage, 10);
+ const params = new URLSearchParams(window.location.search);
+ const currentPage = parseInt(params.get('page'), 10);
+ const isPaginationDisabled = params.get('no_pagination');
+ if (hash && linesPerPage && !isPaginationDisabled) {
+ const lineNumber = parseInt(hash.split('#L')[1], 10);
+ const pageToRedirect = Math.ceil(lineNumber / linesPerPage);
+ const isRedirectNeeded =
+ (pageToRedirect > 1 && pageToRedirect !== currentPage) || pageToRedirect < currentPage;
+ if (isRedirectNeeded) {
+ createAlert({
+ message: __('Please wait a few moments while we load the file history for this line.'),
+ });
+ window.location.href = setUrlParams({ page: pageToRedirect });
+ }
+ }
+}
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js
index 2831c37838b..4fbc9044cf0 100644
--- a/app/assets/javascripts/blob/3d_viewer/index.js
+++ b/app/assets/javascripts/blob/3d_viewer/index.js
@@ -1,6 +1,6 @@
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';
-import * as THREE from 'three/build/three.module';
+import * as THREE from 'three';
import MeshObject from './mesh_object';
export default class Renderer {
diff --git a/app/assets/javascripts/blob/3d_viewer/mesh_object.js b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
index 5322dc00e86..6c816b2d07f 100644
--- a/app/assets/javascripts/blob/3d_viewer/mesh_object.js
+++ b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
@@ -1,4 +1,4 @@
-import { Matrix4, MeshLambertMaterial, Mesh } from 'three/build/three.module';
+import { Matrix4, MeshLambertMaterial, Mesh } from 'three';
const defaultColor = 0xe24329;
const materials = {
diff --git a/app/assets/javascripts/blob/blob_line_permalink_updater.js b/app/assets/javascripts/blob/blob_line_permalink_updater.js
index 0a5bcf326a1..df38c5400e2 100644
--- a/app/assets/javascripts/blob/blob_line_permalink_updater.js
+++ b/app/assets/javascripts/blob/blob_line_permalink_updater.js
@@ -22,6 +22,7 @@ const updateLineNumbersOnBlobPermalinks = (linksToUpdate) => {
};
function BlobLinePermalinkUpdater(blobContentHolder, lineNumberSelector, elementsToUpdate) {
+ if (!blobContentHolder) return;
const updateBlameAndBlobPermalinkCb = () => {
// Wait for the hash to update from the LineHighlighter callback
setTimeout(() => {
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue
index 07da262ec9a..b3410b94b98 100644
--- a/app/assets/javascripts/blob/components/table_contents.vue
+++ b/app/assets/javascripts/blob/components/table_contents.vue
@@ -26,6 +26,8 @@ export default {
} else if (blobViewerAttr('data-loaded') === 'true') {
this.isHidden = false;
this.generateHeaders();
+
+ this.observer.disconnect();
}
});
@@ -47,13 +49,11 @@ export default {
if (headers.length) {
const firstHeader = getHeaderNumber(headers[0]);
- headers.forEach((el) => {
- this.items.push({
- text: el.textContent.trim(),
- anchor: el.querySelector('a').getAttribute('id'),
- spacing: Math.max((getHeaderNumber(el) - firstHeader) * 8, 0),
- });
- });
+ this.items = headers.map((el) => ({
+ text: el.textContent.trim(),
+ anchor: el.querySelector('a').getAttribute('id'),
+ spacing: Math.max((getHeaderNumber(el) - firstHeader) * 8, 0),
+ }));
}
},
},
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index 991f98c89e7..adc2649e5df 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import Api from '~/api';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
@@ -155,7 +155,7 @@ export default class FileTemplateMediator {
}
})
.catch((err) =>
- createFlash({
+ createAlert({
message: __(`An error occurred while fetching the template: ${err}`),
}),
);
diff --git a/app/assets/javascripts/blob/openapi/index.js b/app/assets/javascripts/blob/openapi/index.js
index 4c497db9842..44b75cc3e68 100644
--- a/app/assets/javascripts/blob/openapi/index.js
+++ b/app/assets/javascripts/blob/openapi/index.js
@@ -1,5 +1,5 @@
import { SwaggerUIBundle } from 'swagger-ui-dist';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
export default () => {
@@ -15,7 +15,7 @@ export default () => {
});
})
.catch((error) => {
- createFlash({
+ createAlert({
message: __('Something went wrong while initializing the OpenAPI viewer'),
});
throw error;
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 5ca3f131d99..8d323c335d3 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import {
REPO_BLOB_LOAD_VIEWER_START,
@@ -69,7 +69,7 @@ export const handleBlobRichViewer = (viewer, type) => {
loadRichBlobViewer(type)
.then((module) => module?.default(viewer))
.catch((error) => {
- createFlash({
+ createAlert({
message: __('Error loading file viewer.'),
});
throw error;
@@ -221,7 +221,7 @@ export class BlobViewer {
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error loading viewer'),
}),
);
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index d73e1cc43b0..1c9c99dcc2f 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -2,7 +2,7 @@
import $ from 'jquery';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
import BlobFileDropzone from '../blob/blob_file_dropzone';
@@ -79,7 +79,7 @@ export default () => {
initPopovers();
})
.catch((e) =>
- createFlash({
+ createAlert({
message: e,
}),
);
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 2ee2e199358..78e3f934183 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -3,7 +3,7 @@ import { SourceEditorExtension } from '~/editor/extensions/source_editor_extensi
import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import { ToolbarExtension } from '~/editor/extensions/source_editor_toolbar_ext';
import SourceEditor from '~/editor/source_editor';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import { insertFinalNewline } from '~/lib/utils/text_utility';
@@ -44,7 +44,7 @@ export default class EditBlob {
},
]);
} catch (e) {
- createFlash({
+ createAlert({
message: `${BLOB_EDITOR_ERROR}: ${e}`,
});
}
@@ -130,7 +130,7 @@ export default class EditBlob {
currentPane.renderGFM();
})
.catch(() =>
- createFlash({
+ createAlert({
message: BLOB_PREVIEW_ERROR,
}),
);
diff --git a/app/assets/javascripts/boards/components/board_blocked_icon.vue b/app/assets/javascripts/boards/components/board_blocked_icon.vue
deleted file mode 100644
index 3f8a596abd8..00000000000
--- a/app/assets/javascripts/boards/components/board_blocked_icon.vue
+++ /dev/null
@@ -1,207 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
-import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
-import { TYPE_ISSUE, TYPE_EPIC } from '~/graphql_shared/constants';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import { truncate } from '~/lib/utils/text_utility';
-import { __, n__, s__, sprintf } from '~/locale';
-
-export default {
- i18n: {
- issuableType: {
- [issuableTypes.issue]: __('issue'),
- [issuableTypes.epic]: __('epic'),
- },
- },
- graphQLIdType: {
- [issuableTypes.issue]: TYPE_ISSUE,
- [issuableTypes.epic]: TYPE_EPIC,
- },
- referenceFormatter: {
- [issuableTypes.issue]: (r) => r.split('/')[1],
- },
- defaultDisplayLimit: 3,
- textTruncateWidth: 80,
- components: {
- GlIcon,
- GlPopover,
- GlLink,
- GlLoadingIcon,
- },
- blockingIssuablesQueries,
- props: {
- item: {
- type: Object,
- required: true,
- },
- uniqueId: {
- type: String,
- required: true,
- },
- issuableType: {
- type: String,
- required: true,
- validator(value) {
- return [issuableTypes.issue, issuableTypes.epic].includes(value);
- },
- },
- },
- apollo: {
- blockingIssuables: {
- skip() {
- return this.skip;
- },
- query() {
- return blockingIssuablesQueries[this.issuableType].query;
- },
- variables() {
- if (this.isEpic) {
- return {
- fullPath: this.item.group.fullPath,
- iid: Number(this.item.iid),
- };
- }
- return {
- id: convertToGraphQLId(this.$options.graphQLIdType[this.issuableType], this.item.id),
- };
- },
- update(data) {
- this.skip = true;
- const issuable = this.isEpic ? data?.group?.issuable : data?.issuable;
-
- return issuable?.blockingIssuables?.nodes || [];
- },
- error(error) {
- const message = sprintf(s__('Boards|Failed to fetch blocking %{issuableType}s'), {
- issuableType: this.issuableTypeText,
- });
- this.$emit('blocking-issuables-error', { error, message });
- },
- },
- },
- data() {
- return {
- skip: true,
- blockingIssuables: [],
- };
- },
- computed: {
- isEpic() {
- return this.issuableType === issuableTypes.epic;
- },
- displayedIssuables() {
- const { defaultDisplayLimit, referenceFormatter } = this.$options;
- return this.blockingIssuables.slice(0, defaultDisplayLimit).map((i) => {
- return {
- ...i,
- title: truncate(i.title, this.$options.textTruncateWidth),
- reference: this.isEpic ? i.reference : referenceFormatter[this.issuableType](i.reference),
- };
- });
- },
- loading() {
- return this.$apollo.queries.blockingIssuables.loading;
- },
- issuableTypeText() {
- return this.$options.i18n.issuableType[this.issuableType];
- },
- blockedLabel() {
- return sprintf(
- n__(
- 'Boards|Blocked by %{blockedByCount} %{issuableType}',
- 'Boards|Blocked by %{blockedByCount} %{issuableType}s',
- this.item.blockedByCount,
- ),
- {
- blockedByCount: this.item.blockedByCount,
- issuableType: this.issuableTypeText,
- },
- );
- },
- blockIcon() {
- return this.issuableType === issuableTypes.issue ? 'issue-block' : 'entity-blocked';
- },
- glIconId() {
- return `blocked-icon-${this.uniqueId}`;
- },
- hasMoreIssuables() {
- return this.item.blockedByCount > this.$options.defaultDisplayLimit;
- },
- displayedIssuablesCount() {
- return this.hasMoreIssuables
- ? this.item.blockedByCount - this.$options.defaultDisplayLimit
- : this.item.blockedByCount;
- },
- moreIssuablesText() {
- return sprintf(
- n__(
- 'Boards|+ %{displayedIssuablesCount} more %{issuableType}',
- 'Boards|+ %{displayedIssuablesCount} more %{issuableType}s',
- this.displayedIssuablesCount,
- ),
- {
- displayedIssuablesCount: this.displayedIssuablesCount,
- issuableType: this.issuableTypeText,
- },
- );
- },
- viewAllIssuablesText() {
- return sprintf(s__('Boards|View all blocking %{issuableType}s'), {
- issuableType: this.issuableTypeText,
- });
- },
- loadingMessage() {
- return sprintf(s__('Boards|Retrieving blocking %{issuableType}s'), {
- issuableType: this.issuableTypeText,
- });
- },
- },
- methods: {
- handleMouseEnter() {
- this.skip = false;
- },
- },
-};
-</script>
-<template>
- <div class="gl-display-inline">
- <gl-icon
- :id="glIconId"
- ref="icon"
- :name="blockIcon"
- class="issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500"
- data-testid="issue-blocked-icon"
- @mouseenter="handleMouseEnter"
- />
- <gl-popover :target="glIconId" placement="top">
- <template #title
- ><span data-testid="popover-title">{{ blockedLabel }}</span></template
- >
- <template v-if="loading">
- <gl-loading-icon size="sm" />
- <p class="gl-mt-4 gl-mb-0 gl-font-small">{{ loadingMessage }}</p>
- </template>
- <template v-else>
- <ul class="gl-list-style-none gl-p-0">
- <li v-for="issuable in displayedIssuables" :key="issuable.id">
- <gl-link :href="issuable.webUrl" class="gl-text-blue-500! gl-font-sm">{{
- issuable.reference
- }}</gl-link>
- <p class="gl-mb-3 gl-display-block!" data-testid="issuable-title">
- {{ issuable.title }}
- </p>
- </li>
- </ul>
- <div v-if="hasMoreIssuables" class="gl-mt-4">
- <p class="gl-mb-3" data-testid="hidden-blocking-count">{{ moreIssuablesText }}</p>
- <gl-link
- data-testid="view-all-issues"
- :href="`${item.webUrl}#related-issues`"
- class="gl-text-blue-500! gl-font-sm"
- >{{ viewAllIssuablesText }}</gl-link
- >
- </div>
- </template>
- </gl-popover>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 92a623d65d4..3a2b11a649d 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -17,9 +17,9 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/toolt
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
import { ListType } from '../constants';
import eventHub from '../eventhub';
-import BoardBlockedIcon from './board_blocked_icon.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
@@ -34,7 +34,7 @@ export default {
IssueDueDate,
IssueTimeEstimate,
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
- BoardBlockedIcon,
+ IssuableBlockedIcon,
GlSprintf,
BoardCardMoveToPosition,
WorkItemTypeIcon,
@@ -218,7 +218,7 @@ export default {
<div>
<div class="gl-display-flex" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0 gl-mr-3 gl-font-base gl-overflow-break-word">
- <board-blocked-icon
+ <issuable-blocked-icon
v-if="item.blocked"
:item="item"
:unique-id="`${item.id}${list.id}`"
@@ -250,7 +250,8 @@ export default {
>{{ item.title }}</a
>
</h4>
- <board-card-move-to-position :item="item" :list="list" :index="index" />
+ <!-- TODO: remove the condition when https://gitlab.com/gitlab-org/gitlab/-/issues/377862 is resolved -->
+ <board-card-move-to-position v-if="!isEpicBoard" :item="item" :list="list" :index="index" />
</div>
<div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
<template v-for="label in orderedLabels">
@@ -397,7 +398,6 @@ export default {
:img-size="avatarSize"
class="js-no-trigger user-avatar-link"
tooltip-placement="bottom"
- :enforce-gl-avatar="true"
>
<span class="js-assignee-tooltip">
<span class="gl-font-weight-bold gl-display-block">{{ __('Assignee') }}</span>
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index fa0c798ca9d..11a5d89cc8c 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -8,6 +8,7 @@ import { __ } from '~/locale';
import {
FILTERED_SEARCH_TERM,
FILTER_ANY,
+ TOKEN_TYPE_HEALTH,
} from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import { AssigneeFilterType } from '~/boards/constants';
@@ -55,6 +56,7 @@ export default {
myReactionEmoji,
releaseTag,
confidential,
+ healthStatus,
} = this.filterParams;
const filteredSearchValue = [];
@@ -154,6 +156,13 @@ export default {
});
}
+ if (healthStatus) {
+ filteredSearchValue.push({
+ type: TOKEN_TYPE_HEALTH,
+ value: { data: healthStatus, operator: '=' },
+ });
+ }
+
if (this.filterParams['not[authorUsername]']) {
filteredSearchValue.push({
type: 'author',
@@ -248,6 +257,7 @@ export default {
iterationCadenceId,
releaseTag,
confidential,
+ healthStatus,
} = this.filterParams;
let iteration = iterationId;
let cadence = iterationCadenceId;
@@ -292,6 +302,7 @@ export default {
my_reaction_emoji: myReactionEmoji,
release_tag: releaseTag,
confidential,
+ [TOKEN_TYPE_HEALTH]: healthStatus,
},
(value) => {
if (value || value === false) {
@@ -390,6 +401,9 @@ export default {
case 'filtered-search-term':
if (filter.value.data) plainText.push(filter.value.data);
break;
+ case TOKEN_TYPE_HEALTH:
+ filterParams.healthStatus = filter.value.data;
+ break;
default:
break;
}
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 9f359a25234..eb889344c1e 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -4,7 +4,6 @@ import { mapGetters, mapActions, mapState } from 'vuex';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { visitUrl, updateHistory, getParameterByName } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { formType } from '../constants';
import createBoardMutation from '../graphql/board_create.mutation.graphql';
@@ -45,7 +44,6 @@ export default {
BoardConfigurationOptions,
GlAlert,
},
- mixins: [glFeatureFlagMixin()],
inject: {
fullPath: {
default: '',
@@ -233,9 +231,8 @@ export default {
}
},
setIteration(iteration) {
- if (this.glFeatures.iterationCadences) {
- this.board.iterationCadenceId = iteration.iterationCadenceId;
- }
+ this.board.iterationCadenceId = iteration.iterationCadenceId;
+
this.$set(this.board, 'iteration', {
id: iteration.id,
});
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index ed22a375271..91b7f5004ad 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -2,8 +2,6 @@ import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql
import { __ } from '~/locale';
import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql';
import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
-import boardBlockingIssuesQuery from './graphql/board_blocking_issues.query.graphql';
-import boardBlockingEpicsQuery from './graphql/board_blocking_epics.query.graphql';
import destroyBoardListMutation from './graphql/board_list_destroy.mutation.graphql';
import updateBoardListMutation from './graphql/board_list_update.mutation.graphql';
@@ -67,15 +65,6 @@ export const listsQuery = {
},
};
-export const blockingIssuablesQueries = {
- [issuableTypes.issue]: {
- query: boardBlockingIssuesQuery,
- },
- [issuableTypes.epic]: {
- query: boardBlockingEpicsQuery,
- },
-};
-
export const updateListQueries = {
[issuableTypes.issue]: {
mutation: updateBoardListMutation,
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql b/app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql
deleted file mode 100644
index 071a6d7410f..00000000000
--- a/app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-query BoardBlockingEpics($fullPath: ID!, $iid: ID) {
- group(fullPath: $fullPath) {
- id
- issuable: epic(iid: $iid) {
- id
- blockingIssuables: blockedByEpics {
- nodes {
- id
- iid
- title
- reference(full: true)
- webUrl
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql b/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
deleted file mode 100644
index 01fab571733..00000000000
--- a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
+++ /dev/null
@@ -1,14 +0,0 @@
-query BoardBlockingIssues($id: IssueID!) {
- issuable: issue(id: $id) {
- id
- blockingIssuables: blockedByIssues {
- nodes {
- id
- iid
- title
- reference(full: true)
- webUrl
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 854717ed4c4..a7003edba47 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -86,6 +86,7 @@ function mountBoardApp(el) {
milestoneListsAvailable: parseBoolean(el.dataset.milestoneListsAvailable),
assigneeListsAvailable: parseBoolean(el.dataset.assigneeListsAvailable),
iterationListsAvailable: parseBoolean(el.dataset.iterationListsAvailable),
+ healthStatusFeatureAvailable: parseBoolean(el.dataset.healthStatusFeatureAvailable),
allowScopedLabels: parseBoolean(el.dataset.scopedLabels),
swimlanesFeatureAvailable: gon.licensed_features?.swimlanes,
multipleIssueBoardsAvailable: parseBoolean(el.dataset.multipleBoardsAvailable),
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index 17fd3939441..d05b53f1a50 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import DivergenceGraph from './components/divergence_graph.vue';
@@ -51,7 +51,7 @@ export default (endpoint, defaultBranch) => {
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error fetching diverging counts for branches. Please try again.'),
}),
);
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 fea4b56153f..1f8096da94d 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
@@ -1,5 +1,13 @@
<script>
-import { GlTable, GlButton, GlBadge, GlTooltipDirective, GlAvatarLink, GlAvatar } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlAvatar,
+ GlAvatarLink,
+ GlBadge,
+ GlButton,
+ GlTable,
+ 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';
@@ -15,14 +23,15 @@ export default {
),
},
components: {
- GlTable,
- GlButton,
- GlBadge,
ClipboardButton,
- TooltipOnTruncate,
- GlAvatarLink,
+ GlAlert,
GlAvatar,
+ GlAvatarLink,
+ GlBadge,
+ GlButton,
+ GlTable,
TimeAgoTooltip,
+ TooltipOnTruncate,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -138,13 +147,15 @@ export default {
/>
</template>
</gl-table>
- <div
+ <gl-alert
v-else
+ variant="warning"
+ :dismissible="false"
+ :show-icon="false"
data-testid="no_triggers_content"
data-qa-selector="no_triggers_content"
- class="settings-message gl-text-center gl-mb-3"
>
{{ s__('Pipelines|No triggers have been created yet. Add one using the form above.') }}
- </div>
+ </gl-alert>
</div>
</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
index 59ddf4b19d8..8d891ff1746 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
@@ -1,5 +1,7 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
+import { __ } from '~/locale';
+import { reportMessageToSentry } from '../utils';
import getAdminVariables from '../graphql/queries/variables.query.graphql';
import {
ADD_MUTATION_ACTION,
@@ -21,7 +23,11 @@ export default {
data() {
return {
adminVariables: [],
+ hasNextPage: false,
isInitialLoading: true,
+ isLoadingMoreItems: false,
+ loadingCounter: 0,
+ pageInfo: {},
};
},
apollo: {
@@ -30,8 +36,29 @@ export default {
update(data) {
return data?.ciVariables?.nodes || [];
},
+ result({ data }) {
+ this.pageInfo = data?.ciVariables?.pageInfo || this.pageInfo;
+ this.hasNextPage = this.pageInfo?.hasNextPage || false;
+
+ // Because graphQL has a limit of 100 items,
+ // we batch load all the variables by making successive queries
+ // to keep the same UX. As a safeguard, we make sure that we cannot go over
+ // 20 consecutive API calls, which means 2000 variables loaded maximum.
+ if (!this.hasNextPage) {
+ this.isLoadingMoreItems = false;
+ } else if (this.loadingCounter < 20) {
+ this.hasNextPage = false;
+ this.fetchMoreVariables();
+ this.loadingCounter += 1;
+ } else {
+ createAlert({ message: this.$options.tooManyCallsError });
+ reportMessageToSentry(this.$options.componentName, this.$options.tooManyCallsError, {});
+ }
+ },
error() {
- createFlash({ message: variableFetchErrorText });
+ this.isLoadingMoreItems = false;
+ this.hasNextPage = false;
+ createAlert({ message: variableFetchErrorText });
},
watchLoading(flag) {
if (!flag) {
@@ -42,7 +69,10 @@ export default {
},
computed: {
isLoading() {
- return this.$apollo.queries.adminVariables.loading && this.isInitialLoading;
+ return (
+ (this.$apollo.queries.adminVariables.loading && this.isInitialLoading) ||
+ this.isLoadingMoreItems
+ );
},
},
methods: {
@@ -52,6 +82,15 @@ export default {
deleteVariable(variable) {
this.variableMutation(DELETE_MUTATION_ACTION, variable);
},
+ fetchMoreVariables() {
+ this.isLoadingMoreItems = true;
+
+ this.$apollo.queries.adminVariables.fetchMore({
+ variables: {
+ after: this.pageInfo.endCursor,
+ },
+ });
+ },
updateVariable(variable) {
this.variableMutation(UPDATE_MUTATION_ACTION, variable);
},
@@ -66,10 +105,9 @@ export default {
},
});
- const { errors } = data[currentMutation.name];
-
- if (errors.length > 0) {
- createFlash({ message: errors[0] });
+ if (data[currentMutation.name]?.errors?.length) {
+ const { errors } = data[currentMutation.name];
+ createAlert({ message: errors[0] });
} else {
// The writing to cache for admin variable is not working
// because there is no ID in the cache at the top level.
@@ -77,10 +115,14 @@ export default {
this.$apollo.queries.adminVariables.refetch();
}
} catch {
- createFlash({ message: genericMutationErrorText });
+ createAlert({ message: genericMutationErrorText });
}
},
},
+ componentName: 'InstanceVariables',
+ i18n: {
+ tooManyCallsError: __('Maximum number of variables loaded (2000)'),
+ },
mutationData: {
[ADD_MUTATION_ACTION]: { action: addAdminVariable, name: 'addAdminVariable' },
[UPDATE_MUTATION_ACTION]: { action: updateAdminVariable, name: 'updateAdminVariable' },
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
index 3522243e3e7..4af696b8dab 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
@@ -1,7 +1,9 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
+import { __ } from '~/locale';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { reportMessageToSentry } from '../utils';
import getGroupVariables from '../graphql/queries/group_variables.query.graphql';
import {
ADD_MUTATION_ACTION,
@@ -25,6 +27,10 @@ export default {
data() {
return {
groupVariables: [],
+ hasNextPage: false,
+ isLoadingMoreItems: false,
+ loadingCounter: 0,
+ pageInfo: {},
};
},
apollo: {
@@ -38,8 +44,28 @@ export default {
update(data) {
return data?.group?.ciVariables?.nodes || [];
},
+ result({ data }) {
+ this.pageInfo = data?.group?.ciVariables?.pageInfo || this.pageInfo;
+ this.hasNextPage = this.pageInfo?.hasNextPage || false;
+ // Because graphQL has a limit of 100 items,
+ // we batch load all the variables by making successive queries
+ // to keep the same UX. As a safeguard, we make sure that we cannot go over
+ // 20 consecutive API calls, which means 2000 variables loaded maximum.
+ if (!this.hasNextPage) {
+ this.isLoadingMoreItems = false;
+ } else if (this.loadingCounter < 20) {
+ this.hasNextPage = false;
+ this.fetchMoreVariables();
+ this.loadingCounter += 1;
+ } else {
+ createAlert({ message: this.$options.tooManyCallsError });
+ reportMessageToSentry(this.$options.componentName, this.$options.tooManyCallsError, {});
+ }
+ },
error() {
- createFlash({ message: variableFetchErrorText });
+ this.isLoadingMoreItems = false;
+ this.hasNextPage = false;
+ createAlert({ message: variableFetchErrorText });
},
},
},
@@ -48,7 +74,7 @@ export default {
return this.glFeatures.groupScopedCiVariables;
},
isLoading() {
- return this.$apollo.queries.groupVariables.loading;
+ return this.$apollo.queries.groupVariables.loading || this.isLoadingMoreItems;
},
},
methods: {
@@ -58,6 +84,16 @@ export default {
deleteVariable(variable) {
this.variableMutation(DELETE_MUTATION_ACTION, variable);
},
+ fetchMoreVariables() {
+ this.isLoadingMoreItems = true;
+
+ this.$apollo.queries.groupVariables.fetchMore({
+ variables: {
+ fullPath: this.groupPath,
+ after: this.pageInfo.endCursor,
+ },
+ });
+ },
updateVariable(variable) {
this.variableMutation(UPDATE_MUTATION_ACTION, variable);
},
@@ -74,16 +110,19 @@ export default {
},
});
- const { errors } = data[currentMutation.name];
-
- if (errors.length > 0) {
- createFlash({ message: errors[0] });
+ if (data[currentMutation.name]?.errors?.length) {
+ const { errors } = data[currentMutation.name];
+ createAlert({ message: errors[0] });
}
} catch {
- createFlash({ message: genericMutationErrorText });
+ createAlert({ message: genericMutationErrorText });
}
},
},
+ componentName: 'GroupVariables',
+ i18n: {
+ tooManyCallsError: __('Maximum number of variables loaded (2000)'),
+ },
mutationData: {
[ADD_MUTATION_ACTION]: { action: addGroupVariable, name: 'addGroupVariable' },
[UPDATE_MUTATION_ACTION]: { action: updateGroupVariable, name: 'updateGroupVariable' },
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue
index 29db02a3c59..6bd549817f8 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue
@@ -1,9 +1,10 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
+import { __ } from '~/locale';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import getProjectEnvironments from '../graphql/queries/project_environments.query.graphql';
import getProjectVariables from '../graphql/queries/project_variables.query.graphql';
-import { mapEnvironmentNames } from '../utils';
+import { mapEnvironmentNames, reportMessageToSentry } from '../utils';
import {
ADD_MUTATION_ACTION,
DELETE_MUTATION_ACTION,
@@ -25,6 +26,10 @@ export default {
inject: ['endpoint', 'projectFullPath', 'projectId'],
data() {
return {
+ hasNextPage: false,
+ isLoadingMoreItems: false,
+ loadingCounter: 0,
+ pageInfo: {},
projectEnvironments: [],
projectVariables: [],
};
@@ -41,21 +46,42 @@ export default {
return mapEnvironmentNames(data?.project?.environments?.nodes);
},
error() {
- createFlash({ message: environmentFetchErrorText });
+ createAlert({ message: environmentFetchErrorText });
},
},
projectVariables: {
query: getProjectVariables,
variables() {
return {
+ after: null,
fullPath: this.projectFullPath,
};
},
update(data) {
return data?.project?.ciVariables?.nodes || [];
},
+ result({ data }) {
+ this.pageInfo = data?.project?.ciVariables?.pageInfo || this.pageInfo;
+ this.hasNextPage = this.pageInfo?.hasNextPage || false;
+ // Because graphQL has a limit of 100 items,
+ // we batch load all the variables by making successive queries
+ // to keep the same UX. As a safeguard, we make sure that we cannot go over
+ // 20 consecutive API calls, which means 2000 variables loaded maximum.
+ if (!this.hasNextPage) {
+ this.isLoadingMoreItems = false;
+ } else if (this.loadingCounter < 20) {
+ this.hasNextPage = false;
+ this.fetchMoreVariables();
+ this.loadingCounter += 1;
+ } else {
+ createAlert({ message: this.$options.tooManyCallsError });
+ reportMessageToSentry(this.$options.componentName, this.$options.tooManyCallsError, {});
+ }
+ },
error() {
- createFlash({ message: variableFetchErrorText });
+ this.isLoadingMoreItems = false;
+ this.hasNextPage = false;
+ createAlert({ message: variableFetchErrorText });
},
},
},
@@ -63,7 +89,8 @@ export default {
isLoading() {
return (
this.$apollo.queries.projectVariables.loading ||
- this.$apollo.queries.projectEnvironments.loading
+ this.$apollo.queries.projectEnvironments.loading ||
+ this.isLoadingMoreItems
);
},
},
@@ -74,6 +101,16 @@ export default {
deleteVariable(variable) {
this.variableMutation(DELETE_MUTATION_ACTION, variable);
},
+ fetchMoreVariables() {
+ this.isLoadingMoreItems = true;
+
+ this.$apollo.queries.projectVariables.fetchMore({
+ variables: {
+ fullPath: this.projectFullPath,
+ after: this.pageInfo.endCursor,
+ },
+ });
+ },
updateVariable(variable) {
this.variableMutation(UPDATE_MUTATION_ACTION, variable);
},
@@ -89,16 +126,19 @@ export default {
variable,
},
});
-
- const { errors } = data[currentMutation.name];
- if (errors.length > 0) {
- createFlash({ message: errors[0] });
+ if (data[currentMutation.name]?.errors?.length) {
+ const { errors } = data[currentMutation.name];
+ createAlert({ message: errors[0] });
}
- } catch (e) {
- createFlash({ message: genericMutationErrorText });
+ } catch {
+ createAlert({ message: genericMutationErrorText });
}
},
},
+ componentName: 'ProjectVariables',
+ i18n: {
+ tooManyCallsError: __('Maximum number of variables loaded (2000)'),
+ },
mutationData: {
[ADD_MUTATION_ACTION]: { action: addProjectVariable, name: 'addProjectVariable' },
[UPDATE_MUTATION_ACTION]: { action: updateProjectVariable, name: 'updateProjectVariable' },
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 1bb94080694..959ef6864fb 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
@@ -75,8 +75,7 @@ export default {
props: {
isLoading: {
type: Boolean,
- required: false,
- default: false,
+ required: true,
},
variables: {
type: Array,
diff --git a/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_settings.vue b/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_settings.vue
index 9acc9fbffb6..f1fe188348d 100644
--- a/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_settings.vue
+++ b/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_settings.vue
@@ -9,10 +9,10 @@ export default {
LegacyCiVariableTable,
},
computed: {
- ...mapState(['isGroup']),
+ ...mapState(['isGroup', 'isProject']),
},
mounted() {
- if (!this.isGroup) {
+ if (this.isProject) {
this.fetchEnvironments();
}
},
diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js
index e2dd28cdaa1..ccad08ef8b6 100644
--- a/app/assets/javascripts/ci_variable_list/constants.js
+++ b/app/assets/javascripts/ci_variable_list/constants.js
@@ -52,7 +52,7 @@ export const groupString = 'Group';
// eslint-disable-next-line @gitlab/require-i18n-strings
export const instanceString = 'Instance';
// eslint-disable-next-line @gitlab/require-i18n-strings
-export const projectString = 'Instance';
+export const projectString = 'Project';
export const AWS_TIP_DISMISSED_COOKIE_NAME = 'ci_variable_list_constants_aws_tip_dismissed';
export const AWS_TIP_MESSAGE = __(
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
index c6dd6d4faaf..b5555fe4401 100644
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
+++ b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
@@ -1,9 +1,13 @@
#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-query getGroupVariables($fullPath: ID!) {
+query getGroupVariables($after: String, $first: Int = 100, $fullPath: ID!) {
group(fullPath: $fullPath) {
id
- ciVariables {
+ ciVariables(after: $after, first: $first) {
+ pageInfo {
+ ...PageInfo
+ }
nodes {
...BaseCiVariable
... on CiGroupVariable {
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql
index a60a50e4bc4..08b5bf7af16 100644
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql
+++ b/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql
@@ -1,9 +1,13 @@
#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-query getProjectVariables($fullPath: ID!) {
+query getProjectVariables($after: String, $first: Int = 100, $fullPath: ID!) {
project(fullPath: $fullPath) {
id
- ciVariables {
+ ciVariables(after: $after, first: $first) {
+ pageInfo {
+ ...PageInfo
+ }
nodes {
...BaseCiVariable
environmentScope
diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
index 95056842b49..2667d6606fe 100644
--- a/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
+++ b/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
@@ -1,7 +1,11 @@
#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-query getVariables {
- ciVariables {
+query getVariables($after: String, $first: Int = 100) {
+ ciVariables(after: $after, first: $first) {
+ pageInfo {
+ ...PageInfo
+ }
nodes {
...BaseCiVariable
... on CiInstanceVariable {
diff --git a/app/assets/javascripts/ci_variable_list/graphql/resolvers.js b/app/assets/javascripts/ci_variable_list/graphql/resolvers.js
deleted file mode 100644
index c041531ae30..00000000000
--- a/app/assets/javascripts/ci_variable_list/graphql/resolvers.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import axios from 'axios';
-import {
- convertObjectPropsToCamelCase,
- convertObjectPropsToSnakeCase,
-} from '../../lib/utils/common_utils';
-import { getIdFromGraphQLId } from '../../graphql_shared/utils';
-import {
- GRAPHQL_GROUP_TYPE,
- GRAPHQL_PROJECT_TYPE,
- groupString,
- instanceString,
- projectString,
-} from '../constants';
-import getProjectVariables from './queries/project_variables.query.graphql';
-import getGroupVariables from './queries/group_variables.query.graphql';
-import getAdminVariables from './queries/variables.query.graphql';
-
-const prepareVariableForApi = ({ variable, destroy = false }) => {
- return {
- ...convertObjectPropsToSnakeCase(variable),
- id: getIdFromGraphQLId(variable?.id),
- variable_type: variable.variableType.toLowerCase(),
- secret_value: variable.value,
- _destroy: destroy,
- };
-};
-
-const mapVariableTypes = (variables = [], kind) => {
- return variables.map((ciVar) => {
- return {
- __typename: `Ci${kind}Variable`,
- ...convertObjectPropsToCamelCase(ciVar),
- variableType: ciVar.variable_type ? ciVar.variable_type.toUpperCase() : ciVar.variableType,
- };
- });
-};
-
-const prepareProjectGraphQLResponse = ({ data, projectId, errors = [] }) => {
- return {
- errors,
- project: {
- __typename: GRAPHQL_PROJECT_TYPE,
- id: projectId,
- ciVariables: {
- __typename: 'CiVariableConnection',
- nodes: mapVariableTypes(data.variables, projectString),
- },
- },
- };
-};
-
-const prepareGroupGraphQLResponse = ({ data, groupId, errors = [] }) => {
- return {
- errors,
- group: {
- __typename: GRAPHQL_GROUP_TYPE,
- id: groupId,
- ciVariables: {
- __typename: 'CiVariableConnection',
- nodes: mapVariableTypes(data.variables, groupString),
- },
- },
- };
-};
-
-const prepareAdminGraphQLResponse = ({ data, errors = [] }) => {
- return {
- errors,
- ciVariables: {
- __typename: `Ci${instanceString}VariableConnection`,
- nodes: mapVariableTypes(data.variables, instanceString),
- },
- };
-};
-
-const callProjectEndpoint = async ({
- endpoint,
- fullPath,
- variable,
- projectId,
- cache,
- destroy = false,
-}) => {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
- return prepareProjectGraphQLResponse({ data, projectId });
- } catch (e) {
- return prepareProjectGraphQLResponse({
- data: cache.readQuery({ query: getProjectVariables, variables: { fullPath } }),
- projectId,
- errors: [...e.response.data],
- });
- }
-};
-
-const callGroupEndpoint = async ({
- endpoint,
- fullPath,
- variable,
- groupId,
- cache,
- destroy = false,
-}) => {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
- return prepareGroupGraphQLResponse({ data, groupId });
- } catch (e) {
- return prepareGroupGraphQLResponse({
- data: cache.readQuery({ query: getGroupVariables, variables: { fullPath } }),
- groupId,
- errors: [...e.response.data],
- });
- }
-};
-
-const callAdminEndpoint = async ({ endpoint, variable, cache, destroy = false }) => {
- try {
- const { data } = await axios.patch(endpoint, {
- variables_attributes: [prepareVariableForApi({ variable, destroy })],
- });
-
- return prepareAdminGraphQLResponse({ data });
- } catch (e) {
- return prepareAdminGraphQLResponse({
- data: cache.readQuery({ query: getAdminVariables }),
- errors: [...e.response.data],
- });
- }
-};
-
-export const resolvers = {
- Mutation: {
- addProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache });
- },
- updateProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache });
- },
- deleteProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
- return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache, destroy: true });
- },
- addGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache });
- },
- updateGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache });
- },
- deleteGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
- return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache, destroy: true });
- },
- addAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache });
- },
- updateAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache });
- },
- deleteAdminVariable: async (_, { endpoint, variable }, { cache }) => {
- return callAdminEndpoint({ endpoint, variable, cache, destroy: true });
- },
- },
-};
diff --git a/app/assets/javascripts/ci_variable_list/graphql/settings.js b/app/assets/javascripts/ci_variable_list/graphql/settings.js
new file mode 100644
index 00000000000..ecdc4f220bd
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/settings.js
@@ -0,0 +1,256 @@
+import axios from 'axios';
+import {
+ convertObjectPropsToCamelCase,
+ convertObjectPropsToSnakeCase,
+} from '../../lib/utils/common_utils';
+import { convertToGraphQLId, getIdFromGraphQLId } from '../../graphql_shared/utils';
+import {
+ GRAPHQL_GROUP_TYPE,
+ GRAPHQL_PROJECT_TYPE,
+ groupString,
+ instanceString,
+ projectString,
+} from '../constants';
+import getProjectVariables from './queries/project_variables.query.graphql';
+import getGroupVariables from './queries/group_variables.query.graphql';
+import getAdminVariables from './queries/variables.query.graphql';
+
+const prepareVariableForApi = ({ variable, destroy = false }) => {
+ return {
+ ...convertObjectPropsToSnakeCase(variable),
+ id: getIdFromGraphQLId(variable?.id),
+ variable_type: variable.variableType.toLowerCase(),
+ secret_value: variable.value,
+ _destroy: destroy,
+ };
+};
+
+const mapVariableTypes = (variables = [], kind) => {
+ return variables.map((ciVar) => {
+ return {
+ __typename: `Ci${kind}Variable`,
+ ...convertObjectPropsToCamelCase(ciVar),
+ id: convertToGraphQLId('Ci::Variable', ciVar.id),
+ variableType: ciVar.variable_type ? ciVar.variable_type.toUpperCase() : ciVar.variableType,
+ };
+ });
+};
+
+const prepareProjectGraphQLResponse = ({ data, projectId, errors = [] }) => {
+ return {
+ errors,
+ project: {
+ __typename: GRAPHQL_PROJECT_TYPE,
+ id: convertToGraphQLId(GRAPHQL_PROJECT_TYPE, projectId),
+ ciVariables: {
+ __typename: `Ci${GRAPHQL_PROJECT_TYPE}VariableConnection`,
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ nodes: mapVariableTypes(data.variables, projectString),
+ },
+ },
+ };
+};
+
+const prepareGroupGraphQLResponse = ({ data, groupId, errors = [] }) => {
+ return {
+ errors,
+ group: {
+ __typename: GRAPHQL_GROUP_TYPE,
+ id: convertToGraphQLId(GRAPHQL_GROUP_TYPE, groupId),
+ ciVariables: {
+ __typename: `Ci${GRAPHQL_GROUP_TYPE}VariableConnection`,
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ nodes: mapVariableTypes(data.variables, groupString),
+ },
+ },
+ };
+};
+
+const prepareAdminGraphQLResponse = ({ data, errors = [] }) => {
+ return {
+ errors,
+ ciVariables: {
+ __typename: `Ci${instanceString}VariableConnection`,
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ nodes: mapVariableTypes(data.variables, instanceString),
+ },
+ };
+};
+
+async function callProjectEndpoint({
+ endpoint,
+ fullPath,
+ variable,
+ projectId,
+ cache,
+ destroy = false,
+}) {
+ try {
+ const { data } = await axios.patch(endpoint, {
+ variables_attributes: [prepareVariableForApi({ variable, destroy })],
+ });
+
+ const graphqlData = prepareProjectGraphQLResponse({ data, projectId });
+
+ cache.writeQuery({
+ query: getProjectVariables,
+ variables: {
+ fullPath,
+ after: null,
+ },
+ data: graphqlData,
+ });
+ return graphqlData;
+ } catch (e) {
+ return prepareProjectGraphQLResponse({
+ data: cache.readQuery({ query: getProjectVariables, variables: { fullPath } }),
+ projectId,
+ errors: [...e.response.data],
+ });
+ }
+}
+
+const callGroupEndpoint = async ({
+ endpoint,
+ fullPath,
+ variable,
+ groupId,
+ cache,
+ destroy = false,
+}) => {
+ try {
+ const { data } = await axios.patch(endpoint, {
+ variables_attributes: [prepareVariableForApi({ variable, destroy })],
+ });
+
+ const graphqlData = prepareGroupGraphQLResponse({ data, groupId });
+
+ cache.writeQuery({
+ query: getGroupVariables,
+ data: graphqlData,
+ });
+
+ return graphqlData;
+ } catch (e) {
+ return prepareGroupGraphQLResponse({
+ data: cache.readQuery({ query: getGroupVariables, variables: { fullPath } }),
+ groupId,
+ errors: [...e.response.data],
+ });
+ }
+};
+
+const callAdminEndpoint = async ({ endpoint, variable, cache, destroy = false }) => {
+ try {
+ const { data } = await axios.patch(endpoint, {
+ variables_attributes: [prepareVariableForApi({ variable, destroy })],
+ });
+
+ const graphqlData = prepareAdminGraphQLResponse({ data });
+
+ cache.writeQuery({
+ query: getAdminVariables,
+ data: graphqlData,
+ });
+
+ return graphqlData;
+ } catch (e) {
+ return prepareAdminGraphQLResponse({
+ data: cache.readQuery({ query: getAdminVariables }),
+ errors: [...e.response.data],
+ });
+ }
+};
+
+export const resolvers = {
+ Mutation: {
+ addProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
+ return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache });
+ },
+ updateProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
+ return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache });
+ },
+ deleteProjectVariable: async (_, { endpoint, fullPath, variable, projectId }, { cache }) => {
+ return callProjectEndpoint({ endpoint, fullPath, variable, projectId, cache, destroy: true });
+ },
+ addGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
+ return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache });
+ },
+ updateGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
+ return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache });
+ },
+ deleteGroupVariable: async (_, { endpoint, fullPath, variable, groupId }, { cache }) => {
+ return callGroupEndpoint({ endpoint, fullPath, variable, groupId, cache, destroy: true });
+ },
+ addAdminVariable: async (_, { endpoint, variable }, { cache }) => {
+ return callAdminEndpoint({ endpoint, variable, cache });
+ },
+ updateAdminVariable: async (_, { endpoint, variable }, { cache }) => {
+ return callAdminEndpoint({ endpoint, variable, cache });
+ },
+ deleteAdminVariable: async (_, { endpoint, variable }, { cache }) => {
+ return callAdminEndpoint({ endpoint, variable, cache, destroy: true });
+ },
+ },
+};
+
+export const mergeVariables = (existing, incoming, { args }) => {
+ if (!existing || !args?.after) {
+ return incoming;
+ }
+
+ const { nodes, ...rest } = incoming;
+ const result = rest;
+ result.nodes = [...existing.nodes, ...nodes];
+
+ return result;
+};
+
+export const cacheConfig = {
+ cacheConfig: {
+ typePolicies: {
+ Query: {
+ fields: {
+ ciVariables: {
+ keyArgs: false,
+ merge: mergeVariables,
+ },
+ },
+ },
+ Project: {
+ fields: {
+ ciVariables: {
+ keyArgs: ['fullPath', 'endpoint', 'projectId'],
+ merge: mergeVariables,
+ },
+ },
+ },
+ Group: {
+ fields: {
+ ciVariables: {
+ keyArgs: ['fullPath'],
+ merge: mergeVariables,
+ },
+ },
+ },
+ },
+ },
+};
diff --git a/app/assets/javascripts/ci_variable_list/index.js b/app/assets/javascripts/ci_variable_list/index.js
index f5bdd4c7b1e..1b69da9e086 100644
--- a/app/assets/javascripts/ci_variable_list/index.js
+++ b/app/assets/javascripts/ci_variable_list/index.js
@@ -6,7 +6,7 @@ import CiAdminVariables from './components/ci_admin_variables.vue';
import CiGroupVariables from './components/ci_group_variables.vue';
import CiProjectVariables from './components/ci_project_variables.vue';
import LegacyCiVariableSettings from './components/legacy_ci_variable_settings.vue';
-import { resolvers } from './graphql/resolvers';
+import { cacheConfig, resolvers } from './graphql/settings';
import createStore from './store';
const mountCiVariableListApp = (containerEl) => {
@@ -45,7 +45,7 @@ const mountCiVariableListApp = (containerEl) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(resolvers),
+ defaultClient: createDefaultClient(resolvers, cacheConfig),
});
return new Vue({
@@ -81,6 +81,7 @@ const mountLegacyCiVariableListApp = (containerEl) => {
endpoint,
projectId,
isGroup,
+ isProject,
maskableRegex,
protectedByDefault,
awsLogoSvgPath,
@@ -92,6 +93,8 @@ const mountLegacyCiVariableListApp = (containerEl) => {
maskedEnvironmentVariablesLink,
environmentScopeLink,
} = containerEl.dataset;
+
+ const parsedIsProject = parseBoolean(isProject);
const parsedIsGroup = parseBoolean(isGroup);
const isProtectedByDefault = parseBoolean(protectedByDefault);
@@ -99,6 +102,7 @@ const mountLegacyCiVariableListApp = (containerEl) => {
endpoint,
projectId,
isGroup: parsedIsGroup,
+ isProject: parsedIsProject,
maskableRegex,
isProtectedByDefault,
awsLogoSvgPath,
diff --git a/app/assets/javascripts/ci_variable_list/store/actions.js b/app/assets/javascripts/ci_variable_list/store/actions.js
index 8a182737e7b..ac31e845b0d 100644
--- a/app/assets/javascripts/ci_variable_list/store/actions.js
+++ b/app/assets/javascripts/ci_variable_list/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -48,7 +48,7 @@ export const addVariable = ({ state, dispatch }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash({
+ createAlert({
message: error.response.data[0],
});
dispatch('receiveAddVariableError', error);
@@ -80,7 +80,7 @@ export const updateVariable = ({ state, dispatch }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash({
+ createAlert({
message: error.response.data[0],
});
dispatch('receiveUpdateVariableError', error);
@@ -109,7 +109,7 @@ export const fetchVariables = ({ dispatch, state }) => {
dispatch('receiveVariablesSuccess', prepareDataForDisplay(data.variables));
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('There was an error fetching the variables.'),
});
});
@@ -139,7 +139,7 @@ export const deleteVariable = ({ dispatch, state }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash({
+ createAlert({
message: error.response.data[0],
});
dispatch('receiveDeleteVariableError', error);
@@ -162,7 +162,7 @@ export const fetchEnvironments = ({ dispatch, state }) => {
dispatch('receiveEnvironmentsSuccess', prepareEnvironments(res.data));
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('There was an error fetching the environments information.'),
});
});
diff --git a/app/assets/javascripts/ci_variable_list/utils.js b/app/assets/javascripts/ci_variable_list/utils.js
index 1faa97a5f73..eeca69274ce 100644
--- a/app/assets/javascripts/ci_variable_list/utils.js
+++ b/app/assets/javascripts/ci_variable_list/utils.js
@@ -1,3 +1,4 @@
+import * as Sentry from '@sentry/browser';
import { uniq } from 'lodash';
import { allEnvironments } from './constants';
@@ -48,3 +49,12 @@ export const convertEnvironmentScope = (environmentScope = '') => {
export const mapEnvironmentNames = (nodes = []) => {
return nodes.map((env) => env.name);
};
+
+export const reportMessageToSentry = (component, message, context) => {
+ Sentry.withScope((scope) => {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ scope.setContext('Vue data', context);
+ scope.setTag('component', component);
+ Sentry.captureMessage(message);
+ });
+};
diff --git a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
index 18c6503bfb2..ca65665b9ed 100644
--- a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
+++ b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
@@ -132,11 +132,7 @@ export default {
:key="key"
class="agent-activity-list issuable-discussion"
>
- <h4
- class="gl-pb-4 gl-ml-5"
- :class="$options.borderClasses"
- data-testid="activity-section-title"
- >
+ <h4 class="gl-pb-4" :class="$options.borderClasses" data-testid="activity-section-title">
{{ key }}
</h4>
diff --git a/app/assets/javascripts/clusters/agents/components/activity_history_item.vue b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
index 7792d89a575..ed11fe1130d 100644
--- a/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
+++ b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
@@ -45,8 +45,8 @@ export default {
};
</script>
<template>
- <history-item :icon="eventDetails.eventTypeIcon" class="gl-my-0! gl-pr-0!">
- <strong>
+ <history-item :icon="eventDetails.eventTypeIcon" class="gl-my-0! gl-px-0! gl-pb-0!">
+ <strong class="gl-pl-3 gl-font-lg">
<gl-sprintf :message="eventDetails.title"
><template v-if="eventDetails.titleIcon" #titleIcon
><gl-icon
@@ -61,15 +61,15 @@ export default {
</strong>
<template #body>
- <p class="gl-mt-2 gl-mb-0 gl-pb-2" :class="bodyClass">
+ <p class="gl-mt-2 gl-mb-0 gl-ml-3 gl-pb-3 gl-text-secondary" :class="bodyClass">
<gl-sprintf :message="eventDetails.body">
<template #userName>
- <span class="gl-font-weight-bold">{{ eventDetails.user.name }}</span>
+ <span class="gl-font-weight-bold gl-text-body">{{ 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>
+ <span class="gl-font-weight-bold gl-text-body"> {{ content }} </span>
</template>
</gl-sprintf>
<time-ago-tooltip :time="eventDetails.recordedAt" />
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index a8fef372637..21524c5b29e 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,7 +1,7 @@
import { GlToast } from '@gitlab/ui';
import Visibility from 'visibilityjs';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import AccessorUtilities from '~/lib/utils/accessor';
import initProjectSelectDropdown from '~/project_select';
import Poll from '~/lib/utils/poll';
@@ -196,7 +196,7 @@ export default class Clusters {
}
static handleError() {
- createFlash({
+ createAlert({
message: s__('ClusterIntegration|Something went wrong on our end.'),
});
}
diff --git a/app/assets/javascripts/clusters_list/store/actions.js b/app/assets/javascripts/clusters_list/store/actions.js
index d70b36e63bc..77d6d5eb009 100644
--- a/app/assets/javascripts/clusters_list/store/actions.js
+++ b/app/assets/javascripts/clusters_list/store/actions.js
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/browser';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import Poll from '~/lib/utils/poll';
@@ -70,7 +70,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
commit(types.SET_LOADING_CLUSTERS, false);
commit(types.SET_LOADING_NODES, false);
- createFlash({
+ createAlert({
message: s__('Clusters|An error occurred while loading clusters'),
});
diff --git a/app/assets/javascripts/code_navigation/utils/dom_utils.js b/app/assets/javascripts/code_navigation/utils/dom_utils.js
index 90af31b715c..66770cca8a2 100644
--- a/app/assets/javascripts/code_navigation/utils/dom_utils.js
+++ b/app/assets/javascripts/code_navigation/utils/dom_utils.js
@@ -6,26 +6,28 @@ const isBlank = (str) => !str || /^\s*$/.test(str);
const isMatch = (s1, s2) => !isBlank(s1) && s1.trim() === s2.trim();
-const createSpan = (content) => {
+const createSpan = (content, classList) => {
const span = document.createElement('span');
span.innerText = content;
+ span.classList = classList || '';
return span;
};
-const wrapSpacesWithSpans = (text) => text.replace(/ /g, createSpan(' ').outerHTML);
+const wrapSpacesWithSpans = (text) =>
+ text.replace(/ /g, createSpan(' ').outerHTML).replace(/\t/g, createSpan(' ').outerHTML);
-const wrapTextWithSpan = (el, text) => {
+const wrapTextWithSpan = (el, text, classList) => {
if (isTextNode(el) && isMatch(el.textContent, text)) {
- const newEl = createSpan(text.trim());
+ const newEl = createSpan(text.trim(), classList);
el.replaceWith(newEl);
}
};
-const wrapNodes = (text) => {
+const wrapNodes = (text, classList) => {
const wrapper = createSpan();
// eslint-disable-next-line no-unsanitized/property
wrapper.innerHTML = wrapSpacesWithSpans(text);
- wrapper.childNodes.forEach((el) => wrapTextWithSpan(el, text));
+ wrapper.childNodes.forEach((el) => wrapTextWithSpan(el, text, classList));
return wrapper.childNodes;
};
diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js
index 46038df2f86..7a5fa9f4a35 100644
--- a/app/assets/javascripts/code_navigation/utils/index.js
+++ b/app/assets/javascripts/code_navigation/utils/index.js
@@ -17,11 +17,9 @@ export const addInteractionClass = ({ path, d, wrapTextNodes }) => {
if (wrapTextNodes) {
line.childNodes.forEach((elm) => {
- if (isTextNode(elm)) {
- // Highlight.js does not wrap all text nodes by default
- // We need all text nodes to be wrapped in order to append code nav attributes
- elm.replaceWith(...wrapNodes(elm.textContent));
- }
+ // Highlight.js does not wrap all text nodes by default
+ // We need all text nodes to be wrapped in order to append code nav attributes
+ elm.replaceWith(...wrapNodes(elm.textContent, elm.classList));
});
}
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 6890d7f6f44..b0a1c46e619 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -205,6 +205,12 @@ export default {
mrPipelinesDocsPath: helpPagePath('ci/pipelines/merge_request_pipelines.md', {
anchor: 'prerequisites',
}),
+ runPipelinesInTheParentProjectHelpPath: helpPagePath(
+ '/ci/pipelines/merge_request_pipelines.html',
+ {
+ anchor: 'run-pipelines-in-the-parent-project',
+ },
+ ),
};
</script>
<template>
@@ -321,10 +327,7 @@ export default {
s__('Pipelines|If you are unsure, please ask a project maintainer to review it for you.')
}}
</p>
- <gl-link
- href="/help/ci/pipelines/merge_request_pipelines.html#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project"
- target="_blank"
- >
+ <gl-link :href="$options.runPipelinesInTheParentProjectHelpPath" target="_blank">
{{ s__('Pipelines|More Information') }}
</gl-link>
</gl-modal>
diff --git a/app/assets/javascripts/commit_merge_requests.js b/app/assets/javascripts/commit_merge_requests.js
index f973bf51b57..d40cbe589c0 100644
--- a/app/assets/javascripts/commit_merge_requests.js
+++ b/app/assets/javascripts/commit_merge_requests.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import createFlash from './flash';
+import { createAlert } from '~/flash';
import axios from './lib/utils/axios_utils';
import { n__, s__ } from './locale';
@@ -71,7 +71,7 @@ export function fetchCommitMergeRequests() {
$container.html($content);
})
.catch(() =>
- createFlash({
+ createAlert({
message: s__('Commits|An error occurred while fetching merge requests data.'),
}),
);
diff --git a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
index af049738016..e95424eef4d 100644
--- a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
+++ b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
@@ -1,6 +1,6 @@
<script>
import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
import state from '../state';
@@ -80,7 +80,7 @@ export default {
this.selectProject(this.projects[0]);
})
.catch((e) => {
- createFlash({
+ createAlert({
message: __('Error fetching forked projects. Please try again.'),
});
throw e;
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index 659c447e861..22381377389 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -3,7 +3,7 @@ import { EditorContent as TiptapEditorContent } from '@tiptap/vue-2';
import { __ } from '~/locale';
import { VARIANT_DANGER } from '~/flash';
import { createContentEditor } from '../services/create_content_editor';
-import { ALERT_EVENT } from '../constants';
+import { ALERT_EVENT, TIPTAP_AUTOFOCUS_OPTIONS } from '../constants';
import ContentEditorAlert from './content_editor_alert.vue';
import ContentEditorProvider from './content_editor_provider.vue';
import EditorStateObserver from './editor_state_observer.vue';
@@ -51,6 +51,12 @@ export default {
required: false,
default: '',
},
+ autofocus: {
+ type: [String, Boolean],
+ required: false,
+ default: false,
+ validator: (autofocus) => TIPTAP_AUTOFOCUS_OPTIONS.includes(autofocus),
+ },
},
data() {
return {
@@ -67,7 +73,7 @@ export default {
},
},
created() {
- const { renderMarkdown, uploadsPath, extensions, serializerConfig } = this;
+ const { renderMarkdown, uploadsPath, extensions, serializerConfig, autofocus } = this;
// This is a non-reactive attribute intentionally since this is a complex object.
this.contentEditor = createContentEditor({
@@ -75,6 +81,9 @@ export default {
uploadsPath,
extensions,
serializerConfig,
+ tiptapOptions: {
+ autofocus,
+ },
});
},
mounted() {
@@ -141,7 +150,12 @@ export default {
<template>
<content-editor-provider :content-editor="contentEditor">
<div>
- <editor-state-observer @docUpdate="notifyChange" @focus="focus" @blur="blur" />
+ <editor-state-observer
+ @docUpdate="notifyChange"
+ @focus="focus"
+ @blur="blur"
+ @keydown="$emit('keydown', $event)"
+ />
<content-editor-alert />
<div
data-testid="content-editor"
diff --git a/app/assets/javascripts/content_editor/components/editor_state_observer.vue b/app/assets/javascripts/content_editor/components/editor_state_observer.vue
index 41c3771bf41..ccb46e3b593 100644
--- a/app/assets/javascripts/content_editor/components/editor_state_observer.vue
+++ b/app/assets/javascripts/content_editor/components/editor_state_observer.vue
@@ -1,6 +1,6 @@
<script>
import { debounce } from 'lodash';
-import { ALERT_EVENT } from '../constants';
+import { ALERT_EVENT, KEYDOWN_EVENT } from '../constants';
export const tiptapToComponentMap = {
update: 'docUpdate',
@@ -10,7 +10,7 @@ export const tiptapToComponentMap = {
blur: 'blur',
};
-export const eventHubEvents = [ALERT_EVENT];
+export const eventHubEvents = [ALERT_EVENT, KEYDOWN_EVENT];
const getComponentEventName = (tiptapEventName) => tiptapToComponentMap[tiptapEventName];
diff --git a/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue b/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue
new file mode 100644
index 00000000000..987b7044272
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue
@@ -0,0 +1,264 @@
+<script>
+import { GlDropdownItem, GlAvatarLabeled } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownItem,
+ GlAvatarLabeled,
+ },
+
+ props: {
+ char: {
+ type: String,
+ required: true,
+ },
+
+ nodeType: {
+ type: String,
+ required: true,
+ },
+
+ nodeProps: {
+ type: Object,
+ required: true,
+ },
+
+ items: {
+ type: Array,
+ required: true,
+ },
+
+ command: {
+ type: Function,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ selectedIndex: 0,
+ };
+ },
+
+ computed: {
+ isReference() {
+ return this.nodeType.startsWith('reference');
+ },
+
+ isCommand() {
+ return this.isReference && this.nodeProps.referenceType === 'command';
+ },
+
+ isUser() {
+ return this.isReference && this.nodeProps.referenceType === 'user';
+ },
+
+ isIssue() {
+ return this.isReference && this.nodeProps.referenceType === 'issue';
+ },
+
+ isLabel() {
+ return this.isReference && this.nodeProps.referenceType === 'label';
+ },
+
+ isEpic() {
+ return this.isReference && this.nodeProps.referenceType === 'epic';
+ },
+
+ isSnippet() {
+ return this.isReference && this.nodeProps.referenceType === 'snippet';
+ },
+
+ isVulnerability() {
+ return this.isReference && this.nodeProps.referenceType === 'vulnerability';
+ },
+
+ isMergeRequest() {
+ return this.isReference && this.nodeProps.referenceType === 'merge_request';
+ },
+
+ isMilestone() {
+ return this.isReference && this.nodeProps.referenceType === 'milestone';
+ },
+
+ isEmoji() {
+ return this.nodeType === 'emoji';
+ },
+ },
+
+ watch: {
+ items() {
+ this.selectedIndex = 0;
+ },
+ },
+
+ methods: {
+ getText(item) {
+ if (this.isEmoji) return item.e;
+
+ switch (this.isReference && this.nodeProps.referenceType) {
+ case 'user':
+ return `${this.char}${item.username}`;
+ case 'issue':
+ case 'merge_request':
+ return `${this.char}${item.iid}`;
+ case 'snippet':
+ return `${this.char}${item.id}`;
+ case 'milestone':
+ return `${this.char}${item.title}`;
+ case 'label':
+ return item.title;
+ case 'command':
+ return `${this.char}${item.name}`;
+ case 'epic':
+ return item.reference;
+ case 'vulnerability':
+ return `[vulnerability:${item.id}]`;
+ default:
+ return '';
+ }
+ },
+
+ getProps(item) {
+ const props = {};
+
+ if (this.isEmoji) {
+ Object.assign(props, {
+ name: item.name,
+ unicodeVersion: item.u,
+ title: item.d,
+ moji: item.e,
+ });
+ }
+
+ if (this.isLabel || this.isMilestone) {
+ Object.assign(props, {
+ originalText: `${this.char}${
+ /\W/.test(item.title) ? JSON.stringify(item.title) : item.title
+ }`,
+ });
+ }
+
+ if (this.isLabel) {
+ Object.assign(props, {
+ text: item.title,
+ color: item.color,
+ });
+ }
+
+ Object.assign(props, this.nodeProps);
+
+ return props;
+ },
+
+ onKeyDown({ event }) {
+ if (event.key === 'ArrowUp') {
+ this.upHandler();
+ return true;
+ }
+
+ if (event.key === 'ArrowDown') {
+ this.downHandler();
+ return true;
+ }
+
+ if (event.key === 'Enter') {
+ this.enterHandler();
+ return true;
+ }
+
+ return false;
+ },
+
+ upHandler() {
+ this.selectedIndex = (this.selectedIndex + this.items.length - 1) % this.items.length;
+ },
+
+ downHandler() {
+ this.selectedIndex = (this.selectedIndex + 1) % this.items.length;
+ },
+
+ enterHandler() {
+ this.selectItem(this.selectedIndex);
+ },
+
+ selectItem(index) {
+ const item = this.items[index];
+
+ if (item) {
+ this.command({
+ text: this.getText(item),
+ ...this.getProps(item),
+ });
+ }
+ },
+
+ avatarSubLabel(item) {
+ return item.count ? `${item.name} (${item.count})` : item.name;
+ },
+ },
+};
+</script>
+
+<template>
+ <ul
+ :class="{ show: items.length > 0 }"
+ class="gl-new-dropdown dropdown-menu gl-relative"
+ data-testid="content-editor-suggestions-dropdown"
+ >
+ <div class="gl-new-dropdown-inner gl-overflow-y-auto">
+ <gl-dropdown-item
+ v-for="(item, index) in items"
+ :key="index"
+ :class="{ 'gl-bg-gray-50': index === selectedIndex }"
+ @click="selectItem(index)"
+ >
+ <gl-avatar-labeled
+ v-if="isUser"
+ :label="item.username"
+ :sub-label="avatarSubLabel(item)"
+ :src="item.avatar_url"
+ :entity-name="item.username"
+ :shape="item.type === 'Group' ? 'rect' : 'circle'"
+ :size="32"
+ />
+ <span v-if="isIssue || isMergeRequest">
+ <small>{{ item.iid }}</small>
+ {{ item.title }}
+ </span>
+ <span v-if="isVulnerability || isSnippet">
+ <small>{{ item.id }}</small>
+ {{ item.title }}
+ </span>
+ <span v-if="isEpic">
+ <small>{{ item.reference }}</small>
+ {{ item.title }}
+ </span>
+ <span v-if="isMilestone">
+ {{ item.title }}
+ </span>
+ <span v-if="isLabel" class="gl-display-flex gl-align-items-center">
+ <span
+ data-testid="label-color-box"
+ class="gl-rounded-base gl-display-block gl-w-5 gl-h-5 gl-mr-3"
+ :style="{ backgroundColor: item.color }"
+ ></span>
+ {{ item.title }}
+ </span>
+ <span v-if="isCommand">
+ /{{ item.name }} <small> {{ item.params[0] }} </small><br />
+ <em>
+ <small> {{ item.description }} </small>
+ </em>
+ </span>
+ <div v-if="isEmoji" class="gl-display-flex gl-align-items-center">
+ <div class="gl-pr-4 gl-font-lg">{{ item.e }}</div>
+ <div class="gl-flex-grow-1">
+ {{ item.name }}<br />
+ <small>{{ item.d }}</small>
+ </div>
+ </div>
+ </gl-dropdown-item>
+ </div>
+ </ul>
+</template>
diff --git a/app/assets/javascripts/content_editor/components/wrappers/label.vue b/app/assets/javascripts/content_editor/components/wrappers/label.vue
new file mode 100644
index 00000000000..4206c866032
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/wrappers/label.vue
@@ -0,0 +1,34 @@
+<script>
+import { NodeViewWrapper } from '@tiptap/vue-2';
+import { GlLabel } from '@gitlab/ui';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+
+export default {
+ name: 'DetailsWrapper',
+ components: {
+ NodeViewWrapper,
+ GlLabel,
+ },
+ props: {
+ node: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ isScopedLabel() {
+ return isScopedLabel({ title: this.node.attrs.originalText });
+ },
+ },
+};
+</script>
+<template>
+ <node-view-wrapper class="gl-display-inline-block">
+ <gl-label
+ size="sm"
+ :scoped="isScopedLabel"
+ :background-color="node.attrs.color"
+ :title="node.attrs.text"
+ />
+ </node-view-wrapper>
+</template>
diff --git a/app/assets/javascripts/content_editor/constants/index.js b/app/assets/javascripts/content_editor/constants/index.js
index 564cca23afa..14862727811 100644
--- a/app/assets/javascripts/content_editor/constants/index.js
+++ b/app/assets/javascripts/content_editor/constants/index.js
@@ -42,10 +42,8 @@ export const TEXT_STYLE_DROPDOWN_ITEMS = [
},
];
-export const LOADING_CONTENT_EVENT = 'loading';
-export const LOADING_SUCCESS_EVENT = 'loadingSuccess';
-export const LOADING_ERROR_EVENT = 'loadingError';
export const ALERT_EVENT = 'alert';
+export const KEYDOWN_EVENT = 'keydown';
export const PARSE_HTML_PRIORITY_LOWEST = 1;
export const PARSE_HTML_PRIORITY_DEFAULT = 50;
@@ -66,3 +64,5 @@ export const SAFE_VIDEO_EXT = ['mp4', 'm4v', 'mov', 'webm', 'ogv'];
export const SAFE_AUDIO_EXT = ['mp3', 'oga', 'ogg', 'spx', 'wav'];
export const DIAGRAM_LANGUAGES = ['plantuml', 'mermaid'];
+
+export const TIPTAP_AUTOFOCUS_OPTIONS = [true, false, 'start', 'end', 'all'];
diff --git a/app/assets/javascripts/content_editor/extensions/diagram.js b/app/assets/javascripts/content_editor/extensions/diagram.js
index d9983b8c1c5..7c4a56468eb 100644
--- a/app/assets/javascripts/content_editor/extensions/diagram.js
+++ b/app/assets/javascripts/content_editor/extensions/diagram.js
@@ -1,5 +1,6 @@
import { lowlight } from 'lowlight/lib/core';
import { textblockTypeInputRule } from '@tiptap/core';
+import { base64DecodeUnicode } from '~/lib/utils/text_utility';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import languageLoader from '../services/code_block_language_loader';
import CodeBlockHighlight from './code_block_highlight';
@@ -45,7 +46,9 @@ export default CodeBlockHighlight.extend({
priority: PARSE_HTML_PRIORITY_HIGHEST,
tag: '[data-diagram]',
getContent(element, schema) {
- const source = atob(element.dataset.diagramSrc.replace('data:text/plain;base64,', ''));
+ const source = base64DecodeUnicode(
+ element.dataset.diagramSrc.replace('data:text/plain;base64,', ''),
+ );
const node = schema.node('paragraph', {}, [schema.text(source)]);
return node.content;
},
diff --git a/app/assets/javascripts/content_editor/extensions/external_keydown_handler.js b/app/assets/javascripts/content_editor/extensions/external_keydown_handler.js
new file mode 100644
index 00000000000..e940614083e
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/external_keydown_handler.js
@@ -0,0 +1,38 @@
+import { Extension } from '@tiptap/core';
+import { Plugin, PluginKey } from 'prosemirror-state';
+import { KEYDOWN_EVENT } from '../constants';
+
+/**
+ * This extension bubbles up the keydown event, captured by ProseMirror in the
+ * contenteditale element, to the presentation layer implemented in vue.
+ *
+ * The purpose of this mechanism is allowing clients of the
+ * content editor to attach keyboard shortcuts for behavior outside
+ * of the Content Editor’s boundaries, i.e. submitting a form to save changes.
+ */
+export default Extension.create({
+ name: 'keyboardShortcut',
+ addOptions() {
+ return {
+ eventHub: null,
+ };
+ },
+ addProseMirrorPlugins() {
+ return [
+ new Plugin({
+ key: new PluginKey('keyboardShortcut'),
+ props: {
+ handleKeyDown: (_, event) => {
+ const {
+ options: { eventHub },
+ } = this;
+
+ eventHub.$emit(KEYDOWN_EVENT, event);
+
+ return false;
+ },
+ },
+ }),
+ ];
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/heading.js b/app/assets/javascripts/content_editor/extensions/heading.js
index 48303cdeca4..41903162ba5 100644
--- a/app/assets/javascripts/content_editor/extensions/heading.js
+++ b/app/assets/javascripts/content_editor/extensions/heading.js
@@ -1 +1,15 @@
-export { Heading as default } from '@tiptap/extension-heading';
+import { Heading } from '@tiptap/extension-heading';
+import { textblockTypeInputRule } from '@tiptap/core';
+
+export default Heading.extend({
+ addInputRules() {
+ return this.options.levels.map((level) => {
+ return textblockTypeInputRule({
+ // make sure heading regex doesn't conflict with issue references
+ find: new RegExp(`^(#{1,${level}})[ \t]$`),
+ type: this.type,
+ getAttributes: { level },
+ });
+ });
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/reference.js b/app/assets/javascripts/content_editor/extensions/reference.js
index 5e459e65de2..707beaf1231 100644
--- a/app/assets/javascripts/content_editor/extensions/reference.js
+++ b/app/assets/javascripts/content_editor/extensions/reference.js
@@ -46,22 +46,10 @@ export default Node.create({
tag: 'a.gfm:not([data-link=true])',
priority: PARSE_HTML_PRIORITY_HIGHEST,
},
- {
- tag: 'span.gl-label',
- },
];
},
renderHTML({ node }) {
- return [
- 'a',
- {
- class: node.attrs.className,
- href: node.attrs.href,
- 'data-reference-type': node.attrs.referenceType,
- 'data-original': node.attrs.originalText,
- },
- node.attrs.text,
- ];
+ return ['a', { href: '#' }, node.attrs.text];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/reference_label.js b/app/assets/javascripts/content_editor/extensions/reference_label.js
new file mode 100644
index 00000000000..716e191c3d5
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/reference_label.js
@@ -0,0 +1,35 @@
+import { VueNodeViewRenderer } from '@tiptap/vue-2';
+import { SCOPED_LABEL_DELIMITER } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
+import LabelWrapper from '../components/wrappers/label.vue';
+import Reference from './reference';
+
+export default Reference.extend({
+ name: 'reference_label',
+
+ addAttributes() {
+ return {
+ ...this.parent(),
+ text: {
+ default: null,
+ parseHTML: (element) => {
+ const text = element.querySelector('.gl-label-text').textContent;
+ const scopedText = element.querySelector('.gl-label-text-scoped')?.textContent;
+ if (!scopedText) return text;
+ return `${text}${SCOPED_LABEL_DELIMITER}${scopedText}`;
+ },
+ },
+ color: {
+ default: null,
+ parseHTML: (element) => element.querySelector('.gl-label-text').style.backgroundColor,
+ },
+ };
+ },
+
+ parseHTML() {
+ return [{ tag: 'span.gl-label' }];
+ },
+
+ addNodeView() {
+ return new VueNodeViewRenderer(LabelWrapper);
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/suggestions.js b/app/assets/javascripts/content_editor/extensions/suggestions.js
new file mode 100644
index 00000000000..8976b9cafee
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/suggestions.js
@@ -0,0 +1,227 @@
+import { Node } from '@tiptap/core';
+import { VueRenderer } from '@tiptap/vue-2';
+import tippy from 'tippy.js';
+import Suggestion from '@tiptap/suggestion';
+import { PluginKey } from 'prosemirror-state';
+import { isFunction, uniqueId, memoize } from 'lodash';
+import axios from '~/lib/utils/axios_utils';
+import { initEmojiMap, getAllEmoji } from '~/emoji';
+import SuggestionsDropdown from '../components/suggestions_dropdown.vue';
+
+function find(haystack, needle) {
+ return String(haystack).toLocaleLowerCase().includes(String(needle).toLocaleLowerCase());
+}
+
+function createSuggestionPlugin({
+ editor,
+ char,
+ dataSource,
+ search,
+ limit = Infinity,
+ nodeType,
+ nodeProps = {},
+}) {
+ const fetchData = memoize(
+ isFunction(dataSource) ? dataSource : async () => (await axios.get(dataSource)).data,
+ );
+
+ return Suggestion({
+ editor,
+ char,
+ pluginKey: new PluginKey(uniqueId('suggestions')),
+
+ command: ({ editor: tiptapEditor, range, props }) => {
+ tiptapEditor
+ .chain()
+ .focus()
+ .insertContentAt(range, [
+ { type: nodeType, attrs: props },
+ { type: 'text', text: ' ' },
+ ])
+ .run();
+ },
+
+ async items({ query }) {
+ if (!dataSource) return [];
+
+ try {
+ const items = await fetchData();
+
+ return items.filter(search(query)).slice(0, limit);
+ } catch {
+ return [];
+ }
+ },
+
+ render: () => {
+ let component;
+ let popup;
+
+ return {
+ onStart: (props) => {
+ component = new VueRenderer(SuggestionsDropdown, {
+ propsData: {
+ ...props,
+ char,
+ nodeType,
+ nodeProps,
+ },
+ editor: props.editor,
+ });
+
+ if (!props.clientRect) {
+ return;
+ }
+
+ popup = tippy('body', {
+ getReferenceClientRect: props.clientRect,
+ appendTo: () => document.body,
+ content: component.element,
+ showOnCreate: true,
+ interactive: true,
+ trigger: 'manual',
+ placement: 'bottom-start',
+ });
+ },
+
+ onUpdate(props) {
+ component?.updateProps(props);
+
+ if (!props.clientRect) {
+ return;
+ }
+
+ popup?.[0].setProps({
+ getReferenceClientRect: props.clientRect,
+ });
+ },
+
+ onKeyDown(props) {
+ if (props.event.key === 'Escape') {
+ popup?.[0].hide();
+
+ return true;
+ }
+
+ return component?.ref?.onKeyDown(props);
+ },
+
+ onExit() {
+ popup?.[0].destroy();
+ component?.destroy();
+ },
+ };
+ },
+ });
+}
+
+export default Node.create({
+ name: 'suggestions',
+
+ addProseMirrorPlugins() {
+ return [
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '@',
+ dataSource: gl.GfmAutoComplete?.dataSources.members,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'user',
+ },
+ search: (query) => ({ name, username }) => find(name, query) || find(username, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '#',
+ dataSource: gl.GfmAutoComplete?.dataSources.issues,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'issue',
+ },
+ search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '$',
+ dataSource: gl.GfmAutoComplete?.dataSources.snippets,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'snippet',
+ },
+ search: (query) => ({ id, title }) => find(id, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '~',
+ dataSource: gl.GfmAutoComplete?.dataSources.labels,
+ nodeType: 'reference_label',
+ nodeProps: {
+ referenceType: 'label',
+ },
+ search: (query) => ({ title }) => find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '&',
+ dataSource: gl.GfmAutoComplete?.dataSources.epics,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'epic',
+ },
+ search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '[vulnerability:',
+ dataSource: gl.GfmAutoComplete?.dataSources.vulnerabilities,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'vulnerability',
+ },
+ search: (query) => ({ id, title }) => find(id, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '!',
+ dataSource: gl.GfmAutoComplete?.dataSources.mergeRequests,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'merge_request',
+ },
+ search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '%',
+ dataSource: gl.GfmAutoComplete?.dataSources.milestones,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'milestone',
+ },
+ search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: '/',
+ dataSource: gl.GfmAutoComplete?.dataSources.commands,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType: 'command',
+ },
+ search: (query) => ({ name }) => find(name, query),
+ }),
+ createSuggestionPlugin({
+ editor: this.editor,
+ char: ':',
+ dataSource: () => Object.values(getAllEmoji()),
+ nodeType: 'emoji',
+ search: (query) => ({ d, name }) => find(d, query) || find(name, query),
+ limit: 10,
+ }),
+ ];
+ },
+
+ onCreate() {
+ initEmojiMap();
+ },
+});
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 5ed7f3dc23d..0d78390e769 100644
--- a/app/assets/javascripts/content_editor/services/create_content_editor.js
+++ b/app/assets/javascripts/content_editor/services/create_content_editor.js
@@ -18,6 +18,7 @@ import Diagram from '../extensions/diagram';
import Document from '../extensions/document';
import Dropcursor from '../extensions/dropcursor';
import Emoji from '../extensions/emoji';
+import ExternalKeydownHandler from '../extensions/external_keydown_handler';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
import FootnoteDefinition from '../extensions/footnote_definition';
@@ -42,10 +43,12 @@ import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph';
import PasteMarkdown from '../extensions/paste_markdown';
import Reference from '../extensions/reference';
+import ReferenceLabel from '../extensions/reference_label';
import ReferenceDefinition from '../extensions/reference_definition';
import Sourcemap from '../extensions/sourcemap';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
+import Suggestions from '../extensions/suggestions';
import Superscript from '../extensions/superscript';
import Table from '../extensions/table';
import TableCell from '../extensions/table_cell';
@@ -121,6 +124,7 @@ export const createContentEditor = ({
Image,
InlineDiff,
Italic,
+ ExternalKeydownHandler.configure({ eventHub }),
Link,
ListItem,
Loading,
@@ -129,10 +133,12 @@ export const createContentEditor = ({
Paragraph,
PasteMarkdown.configure({ eventHub, renderMarkdown }),
Reference,
+ ReferenceLabel,
ReferenceDefinition,
Sourcemap,
Strike,
Subscript,
+ Suggestions,
Superscript,
TableCell,
TableHeader,
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index ba0cad6c91c..c990f6cf0b3 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -33,6 +33,7 @@ import MathInline from '../extensions/math_inline';
import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph';
import Reference from '../extensions/reference';
+import ReferenceLabel from '../extensions/reference_label';
import ReferenceDefinition from '../extensions/reference_definition';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
@@ -61,6 +62,7 @@ import {
renderHTMLNode,
renderContent,
renderBulletList,
+ renderReference,
preserveUnchanged,
bold,
italic,
@@ -184,9 +186,8 @@ const defaultSerializerConfig = {
[ListItem.name]: preserveUnchanged(defaultMarkdownSerializer.nodes.list_item),
[OrderedList.name]: preserveUnchanged(renderOrderedList),
[Paragraph.name]: preserveUnchanged(defaultMarkdownSerializer.nodes.paragraph),
- [Reference.name]: (state, node) => {
- state.write(node.attrs.originalText || node.attrs.text);
- },
+ [Reference.name]: renderReference,
+ [ReferenceLabel.name]: renderReference,
[ReferenceDefinition.name]: preserveUnchanged({
render: (state, node, parent, index, same, sourceMarkdown) => {
const nextSibling = parent.maybeChild(index + 1);
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index 41114571df7..5c0cb21075a 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -280,6 +280,7 @@ export function renderTableRow(state, node) {
}
export function renderTable(state, node) {
+ state.flushClose();
setIsInBlockTable(node, shouldRenderHTMLTable(node));
if (isInBlockTable(node)) renderTagOpen(state, 'table');
@@ -422,6 +423,10 @@ export function renderOrderedList(state, node) {
});
}
+export function renderReference(state, node) {
+ state.write(node.attrs.originalText || node.attrs.text);
+}
+
const generateBoldTags = (wrapTagName = openTag) => {
return (_, mark) => {
const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1];
diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue
index 512f060e2ea..4e4c21328ca 100644
--- a/app/assets/javascripts/contributors/components/contributors.vue
+++ b/app/assets/javascripts/contributors/components/contributors.vue
@@ -196,7 +196,7 @@ export default {
<template>
<div>
- <div v-if="loading" class="contributors-loader text-center">
+ <div v-if="loading" class="gl-text-center gl-pt-13">
<gl-loading-icon :inline="true" size="xl" />
</div>
diff --git a/app/assets/javascripts/contributors/stores/actions.js b/app/assets/javascripts/contributors/stores/actions.js
index 4cc0a6a6509..3a6f4191031 100644
--- a/app/assets/javascripts/contributors/stores/actions.js
+++ b/app/assets/javascripts/contributors/stores/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import service from '../services/contributors_service';
import * as types from './mutation_types';
@@ -14,7 +14,7 @@ export const fetchChartData = ({ commit }, endpoint) => {
commit(types.SET_LOADING_STATE, false);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while loading chart data'),
}),
);
diff --git a/app/assets/javascripts/crm/contacts/components/contacts_root.vue b/app/assets/javascripts/crm/contacts/components/contacts_root.vue
index 562363ff88e..2be17d1f80f 100644
--- a/app/assets/javascripts/crm/contacts/components/contacts_root.vue
+++ b/app/assets/javascripts/crm/contacts/components/contacts_root.vue
@@ -86,7 +86,7 @@ export default {
},
methods: {
errorAlertDismissed() {
- this.error = true;
+ this.error = false;
},
extractContacts(data) {
const contacts = data?.group?.contacts?.nodes || [];
@@ -146,7 +146,7 @@ export default {
editButtonLabel: __('Edit'),
title: s__('Crm|Customer relations contacts'),
newContact: s__('Crm|New contact'),
- errorText: __('Something went wrong. Please try again.'),
+ errorMsg: __('Something went wrong. Please try again.'),
},
EDIT_ROUTE_NAME,
NEW_ROUTE_NAME,
@@ -176,7 +176,7 @@ export default {
<div>
<paginated-table-with-search-and-tabs
:show-items="true"
- :show-error-msg="false"
+ :show-error-msg="error"
:i18n="$options.i18n"
:items="contacts.list"
:page-info="contacts.pageInfo"
@@ -243,10 +243,7 @@ export default {
</template>
<template #empty>
- <span v-if="error">
- {{ $options.i18n.errorText }}
- </span>
- <span v-else>
+ <span>
{{ $options.i18n.emptyText }}
</span>
</template>
diff --git a/app/assets/javascripts/crm/organizations/components/organizations_root.vue b/app/assets/javascripts/crm/organizations/components/organizations_root.vue
index 155c8f00537..28f0b34f031 100644
--- a/app/assets/javascripts/crm/organizations/components/organizations_root.vue
+++ b/app/assets/javascripts/crm/organizations/components/organizations_root.vue
@@ -137,7 +137,7 @@ export default {
editButtonLabel: __('Edit'),
title: s__('Crm|Customer relations organizations'),
newOrganization: s__('Crm|New organization'),
- errorText: __('Something went wrong. Please try again.'),
+ errorMsg: __('Something went wrong. Please try again.'),
},
EDIT_ROUTE_NAME,
NEW_ROUTE_NAME,
@@ -167,7 +167,7 @@ export default {
<div>
<paginated-table-with-search-and-tabs
:show-items="true"
- :show-error-msg="false"
+ :show-error-msg="error"
:i18n="$options.i18n"
:items="organizations.list"
:page-info="organizations.pageInfo"
@@ -238,10 +238,7 @@ export default {
</template>
<template #empty>
- <span v-if="error">
- {{ $options.i18n.errorText }}
- </span>
- <span v-else>
+ <span>
{{ $options.i18n.emptyText }}
</span>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/store/actions.js b/app/assets/javascripts/cycle_analytics/store/actions.js
index 5c2e29bfa74..4a201e00582 100644
--- a/app/assets/javascripts/cycle_analytics/store/actions.js
+++ b/app/assets/javascripts/cycle_analytics/store/actions.js
@@ -6,7 +6,7 @@ import {
getValueStreamStageCounts,
} from '~/api/analytics_api';
import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { DEFAULT_VALUE_STREAM, I18N_VSA_ERROR_STAGE_MEDIAN } from '../constants';
import * as types from './mutation_types';
@@ -97,7 +97,7 @@ export const fetchStageMedians = ({
.then((data) => commit(types.RECEIVE_STAGE_MEDIANS_SUCCESS, data))
.catch((error) => {
commit(types.RECEIVE_STAGE_MEDIANS_ERROR, error);
- createFlash({ message: I18N_VSA_ERROR_STAGE_MEDIAN });
+ createAlert({ message: I18N_VSA_ERROR_STAGE_MEDIAN });
});
};
@@ -126,7 +126,7 @@ export const fetchStageCountValues = ({
.then((data) => commit(types.RECEIVE_STAGE_COUNTS_SUCCESS, data))
.catch((error) => {
commit(types.RECEIVE_STAGE_COUNTS_ERROR, error);
- createFlash({
+ createAlert({
message: __('There was an error fetching stage total counts'),
});
});
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
index 814a4b672a2..c67b544eacd 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
@@ -3,7 +3,7 @@ import { GlFormGroup, GlFormInput, GlModal, GlSprintf, GlLink } from '@gitlab/ui
import { isValidCron } from 'cron-validator';
import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
-import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
+import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
import { mapComputed } from '~/vuex_shared/bindings';
export default {
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index 1ac6781a0e3..76a4eaaff3f 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { logError } from '~/lib/logger';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -27,7 +27,7 @@ const receiveFreezePeriod = (store, request) => {
dispatch('fetchFreezePeriods');
})
.catch((error) => {
- createFlash({
+ createAlert({
message: __('Error: Unable to create deploy freeze'),
});
dispatch('receiveFreezePeriodError', error);
@@ -59,7 +59,7 @@ export const deleteFreezePeriod = ({ state, commit }, { id }) => {
return Api.deleteFreezePeriod(state.projectId, id)
.then(() => commit(types.RECEIVE_DELETE_FREEZE_PERIOD_SUCCESS, id))
.catch((e) => {
- createFlash({
+ createAlert({
message: __('Error: Unable to delete deploy freeze'),
});
commit(types.RECEIVE_DELETE_FREEZE_PERIOD_ERROR, id);
@@ -76,7 +76,7 @@ export const fetchFreezePeriods = ({ commit, state }) => {
commit(types.RECEIVE_FREEZE_PERIODS_SUCCESS, data);
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('There was an error fetching the deploy freezes.'),
});
});
diff --git a/app/assets/javascripts/deploy_freeze/store/mutations.js b/app/assets/javascripts/deploy_freeze/store/mutations.js
index 151f7f39f5a..edb455a8dd5 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutations.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutations.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { secondsToHours } from '~/lib/utils/datetime_utility';
+import { formatTimezone } from '~/lib/utils/datetime_utility';
import * as types from './mutation_types';
const formatTimezoneName = (freezePeriod, timezoneList) => {
@@ -8,7 +8,7 @@ const formatTimezoneName = (freezePeriod, timezoneList) => {
return convertObjectPropsToCamelCase({
...freezePeriod,
cron_timezone: {
- formattedTimezone: tz && `[UTC ${secondsToHours(tz.offset)}] ${tz.name}`,
+ formattedTimezone: tz && formatTimezone(tz),
identifier: freezePeriod.cron_timezone,
},
});
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index 36d54f586f1..db5e9a954cf 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import eventHub from '../eventhub';
@@ -93,7 +93,7 @@ export default {
.catch(() => {
this.isLoading = false;
this.store.keys = {};
- return createFlash({
+ return createAlert({
message: s__('DeployKeys|Error getting deploy keys'),
});
});
@@ -103,7 +103,7 @@ export default {
.enableKey(deployKey.id)
.then(this.fetchKeys)
.catch(() =>
- createFlash({
+ createAlert({
message: s__('DeployKeys|Error enabling deploy key'),
}),
);
@@ -119,7 +119,7 @@ export default {
.then(this.fetchKeys)
.then(hideModal)
.catch(() =>
- createFlash({
+ createAlert({
message: s__('DeployKeys|Error removing deploy key'),
}),
);
diff --git a/app/assets/javascripts/deploy_tokens/components/new_deploy_token.vue b/app/assets/javascripts/deploy_tokens/components/new_deploy_token.vue
new file mode 100644
index 00000000000..639dd21bd7b
--- /dev/null
+++ b/app/assets/javascripts/deploy_tokens/components/new_deploy_token.vue
@@ -0,0 +1,332 @@
+<script>
+import {
+ GlFormGroup,
+ GlFormInput,
+ GlFormCheckbox,
+ GlButton,
+ GlDatepicker,
+ GlFormInputGroup,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
+import { createAlert, VARIANT_INFO } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { s__ } from '~/locale';
+
+function defaultData() {
+ return {
+ expiresAt: null,
+ name: '',
+ newTokenDetails: null,
+ readRepository: false,
+ writeRepository: false,
+ readRegistry: false,
+ writeRegistry: false,
+ readPackageRegistry: false,
+ writePackageRegistry: false,
+ username: '',
+ placeholders: {
+ link: { link: ['link_start', 'link_end'] },
+ i: { i: ['i_start', 'i_end'] },
+ code: { code: ['code_start', 'code_end'] },
+ },
+ };
+}
+
+export default {
+ components: {
+ GlFormGroup,
+ GlFormInput,
+ GlDatepicker,
+ GlFormCheckbox,
+ GlButton,
+ GlFormInputGroup,
+ ClipboardButton,
+ GlSprintf,
+ GlLink,
+ },
+
+ props: {
+ createNewTokenPath: {
+ type: String,
+ required: true,
+ },
+ deployTokensHelpUrl: {
+ type: String,
+ required: true,
+ },
+ containerRegistryEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ packagesRegistryEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ tokenType: {
+ type: String,
+ required: true,
+ },
+ },
+
+ data() {
+ return defaultData();
+ },
+ translations: {
+ addTokenButton: s__('DeployTokens|Create deploy token'),
+ addTokenExpiryLabel: s__('DeployTokens|Expiration date (optional)'),
+ addTokenExpiryDescription: s__(
+ 'DeployTokens|Enter an expiration date for your token. Defaults to never expire.',
+ ),
+ addTokenHeader: s__('DeployTokens|New deploy token'),
+ addTokenDescription: s__(
+ 'DeployTokens|Create a new deploy token for all projects in this group. %{link_start}What are deploy tokens?%{link_end}',
+ ),
+ addTokenNameLabel: s__('DeployTokens|Name'),
+ addTokenNameDescription: s__('DeployTokens|Enter a unique name for your deploy token.'),
+ addTokenScopesLabel: s__('DeployTokens|Scopes (select at least one)'),
+ addTokenUsernameDescription: s__(
+ 'DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}.',
+ ),
+ addTokenUsernameLabel: s__('DeployTokens|Username (optional)'),
+ newTokenCopyMessage: s__('DeployTokens|Copy deploy token'),
+ newProjectTokenCreated: s__('DeployTokens|Your new project deploy token has been created.'),
+ newGroupTokenCreated: s__('DeployTokens|Your new group deploy token has been created.'),
+ newTokenDescription: s__(
+ 'DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered.',
+ ),
+ newTokenMessage: s__('DeployTokens|Your New Deploy Token'),
+ newTokenUsernameCopy: s__('DeployTokens|Copy username'),
+ newTokenUsernameDescription: s__(
+ 'DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}',
+ ),
+ readRepositoryHelp: s__('DeployTokens|Allows read-only access to the repository.'),
+ readRegistryHelp: s__('DeployTokens|Allows read-only access to registry images.'),
+ writeRegistryHelp: s__('DeployTokens|Allows read and write access to registry images.'),
+ readPackageRegistryHelp: s__('DeployTokens|Allows read-only access to the package registry.'),
+ writePackageRegistryHelp: s__(
+ 'DeployTokens|Allows read and write access to the package registry.',
+ ),
+ },
+ computed: {
+ formattedExpiryDate() {
+ return formatDate(this.expiresAt, 'yyyy-mm-dd');
+ },
+ newTokenCreatedMessage() {
+ return this.tokenType === 'group'
+ ? this.$options.translations.newGroupTokenCreated
+ : this.$options.translations.newProjectTokenCreated;
+ },
+ },
+ methods: {
+ createDeployToken() {
+ return axios
+ .post(this.createNewTokenPath, {
+ deploy_token: {
+ expires_at: this.expiresAt,
+ name: this.name,
+ read_repository: this.readRepository,
+ read_registry: this.readRegistry,
+ username: this.username,
+ },
+ })
+ .then((response) => {
+ this.newTokenDetails = response.data;
+ this.resetData();
+ createAlert({
+ variant: VARIANT_INFO,
+ message: this.newTokenCreatedMessage,
+ });
+ })
+ .catch((error) => {
+ createAlert({
+ message: error.response.data.message,
+ });
+ });
+ },
+ resetData() {
+ const newData = defaultData();
+ delete newData.newTokenDetails;
+ Object.keys(newData).forEach((k) => {
+ this[k] = newData[k];
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div v-if="newTokenDetails" class="created-deploy-token-container info-well">
+ <div class="well-segment">
+ <h5>{{ $options.translations.newTokenMessage }}</h5>
+ <gl-form-group>
+ <template #description>
+ <div class="deploy-token-help-block gl-mt-2 text-success">
+ <gl-sprintf
+ :message="$options.translations.newTokenUsernameDescription"
+ :placeholders="placeholders.link"
+ >
+ <template #link="{ content }">
+ <gl-link :href="deployTokensHelpUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+ </template>
+ <gl-form-input-group
+ name="deploy-token-user"
+ :value="newTokenDetails.username"
+ select-on-click
+ readonly
+ >
+ <template #append>
+ <clipboard-button
+ :text="newTokenDetails.username"
+ :title="$options.translations.newTokenUsernameCopy"
+ />
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
+ <gl-form-group>
+ <template #description>
+ <div class="deploy-token-help-block gl-mt-2 text-danger">
+ <gl-sprintf
+ :message="$options.translations.newTokenDescription"
+ :placeholders="placeholders.i"
+ >
+ <template #i="{ content }">
+ <i>{{ content }}</i>
+ </template>
+ </gl-sprintf>
+ </div>
+ </template>
+ <gl-form-input-group :value="newTokenDetails.token" name="deploy-token" readonly>
+ <template #append>
+ <clipboard-button
+ :text="newTokenDetails.token"
+ :title="$options.translations.newTokenCopyMessage"
+ />
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
+ </div>
+ </div>
+ <h5>{{ $options.translations.addTokenHeader }}</h5>
+ <p class="profile-settings-content">
+ <gl-sprintf
+ :message="$options.translations.addTokenDescription"
+ :placeholders="placeholders.link"
+ >
+ <template #link="{ content }">
+ <gl-link :href="deployTokensHelpUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <gl-form-group
+ :label="$options.translations.addTokenNameLabel"
+ :description="$options.translations.addTokenNameDescription"
+ label-for="deploy_token_name"
+ >
+ <gl-form-input
+ id="deploy_token_name"
+ v-model="name"
+ name="deploy_token_name"
+ class="qa-deploy-token-name"
+ data-qa-selector="deploy_token_name_field"
+ />
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.translations.addTokenExpiryLabel"
+ :description="$options.translations.addTokenExpiryDescription"
+ label-for="deploy_token_expires_at"
+ >
+ <gl-form-input
+ id="deploy_token_expires_at"
+ name="deploy_token_expires_at"
+ :value="formattedExpiryDate"
+ data-qa-selector="deploy_token_expires_at_field"
+ />
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.translations.addTokenUsernameLabel"
+ label-for="deploy_token_username"
+ >
+ <template #description>
+ <gl-sprintf
+ :message="$options.translations.addTokenUsernameDescription"
+ :placeholders="placeholders.code"
+ >
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ </template>
+ <gl-form-input id="deploy_token_username" v-model="username" />
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.translations.addTokenScopesLabel"
+ label-for="deploy-token-scopes"
+ >
+ <div id="deploy-token-scopes">
+ <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
+ <gl-form-checkbox
+ id="deploy_token_read_repository"
+ v-model="readRepository"
+ name="deploy_token_read_repository"
+ data-qa-selector="deploy_token_read_repository_checkbox"
+ >
+ read_repository
+ <template #help>{{ $options.translations.readRepositoryHelp }}</template>
+ </gl-form-checkbox>
+ <gl-form-checkbox
+ v-if="containerRegistryEnabled"
+ id="deploy_token_read_registry"
+ v-model="readRegistry"
+ name="deploy_token_read_registry"
+ data-qa-selector="deploy_token_read_registry_checkbox"
+ >
+ read_registry
+ <template #help>{{ $options.translations.readRegistryHelp }}</template>
+ </gl-form-checkbox>
+ <gl-form-checkbox
+ v-if="containerRegistryEnabled"
+ id="deploy_token_write_registry"
+ v-model="writeRegistry"
+ name="deploy_token_write_registry"
+ data-qa-selector="deploy_token_write_registry_checkbox"
+ >
+ write_registry
+ <template #help>{{ $options.translations.writeRegistryHelp }}</template>
+ </gl-form-checkbox>
+ <gl-form-checkbox
+ v-if="packagesRegistryEnabled"
+ id="deploy_token_read_package_registry"
+ v-model="readPackageRegistry"
+ name="deploy_token_read_package_registry"
+ data-qa-selector="deploy_token_read_package_registry_checkbox"
+ >
+ read_package_registry
+ <template #help>{{ $options.translations.readPackageRegistryHelp }}</template>
+ </gl-form-checkbox>
+ <gl-form-checkbox
+ v-if="packagesRegistryEnabled"
+ id="deploy_token_write_package_registry"
+ v-model="writePackageRegistry"
+ name="deploy_token_write_package_registry"
+ data-qa-selector="deploy_token_write_package_registry_checkbox"
+ >
+ write_package_registry
+ <template #help>{{ $options.translations.writePackageRegistryHelp }}</template>
+ </gl-form-checkbox>
+ <!-- eslint-enable @gitlab/vue-require-i18n-strings -->
+ </div>
+ </gl-form-group>
+ <div>
+ <gl-button variant="success" @click="createDeployToken">
+ {{ $options.translations.addTokenButton }}
+ </gl-button>
+ </div>
+ <gl-datepicker v-model="expiresAt" target="#deploy_token_expires_at" container="body" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/deploy_tokens/index.js b/app/assets/javascripts/deploy_tokens/index.js
new file mode 100644
index 00000000000..334c9930f4b
--- /dev/null
+++ b/app/assets/javascripts/deploy_tokens/index.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import NewDeployToken from './components/new_deploy_token.vue';
+
+export default function initDeployTokens() {
+ const el = document.getElementById('js-new-deploy-token');
+
+ if (el == null) return null;
+
+ const {
+ createNewTokenPath,
+ deployTokensHelpUrl,
+ containerRegistryEnabled,
+ packagesRegistryEnabled,
+ tokenType,
+ } = el.dataset;
+ return new Vue({
+ el,
+ components: {
+ NewDeployToken,
+ },
+ render(createElement) {
+ return createElement(NewDeployToken, {
+ props: {
+ createNewTokenPath,
+ deployTokensHelpUrl,
+ containerRegistryEnabled: containerRegistryEnabled !== undefined,
+ packagesRegistryEnabled: packagesRegistryEnabled !== undefined,
+ tokenType,
+ },
+ });
+ },
+ });
+}
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 124780df8a5..a4430b15752 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,7 +1,7 @@
<script>
import { GlButton, GlLink, GlTooltipDirective } from '@gitlab/ui';
import { ApolloMutation } from 'vue-apollo';
-import createFlash from '~/flash';
+import { createAlert } 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';
@@ -155,7 +155,7 @@ export default {
methods: {
onDone({ data: { createNote } }) {
if (hasErrors(createNote)) {
- createFlash({ message: ADD_DISCUSSION_COMMENT_ERROR });
+ createAlert({ message: ADD_DISCUSSION_COMMENT_ERROR });
}
this.discussionComment = '';
this.hideForm();
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue b/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
index 4faeba3983b..5a6b220e532 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlModal } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import $ from 'jquery';
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
@@ -7,13 +7,23 @@ import Autosave from '~/autosave';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
export default {
name: 'DesignReplyForm',
+ i18n: {
+ primaryBtn: s__('DesignManagement|Discard changes'),
+ cancelBtnCreate: s__('DesignManagement|Continue creating'),
+ cancelBtnUpdate: s__('DesignManagement|Continue editing'),
+ cancelCreate: s__('DesignManagement|Are you sure you want to cancel creating this comment?'),
+ cancelUpdate: s__('DesignManagement|Are you sure you want to cancel editing this comment?'),
+ newCommentButton: s__('DesignManagement|Comment'),
+ updateCommentButton: s__('DesignManagement|Save comment'),
+ },
+ markdownDocsPath: helpPagePath('user/markdown'),
components: {
MarkdownField,
GlButton,
- GlModal,
},
props: {
markdownPreviewPath: {
@@ -54,29 +64,10 @@ export default {
hasValue() {
return this.value.trim().length > 0;
},
- modalSettings() {
- if (this.isNewComment) {
- return {
- title: s__('DesignManagement|Cancel comment confirmation'),
- okTitle: s__('DesignManagement|Discard comment'),
- cancelTitle: s__('DesignManagement|Keep comment'),
- content: s__('DesignManagement|Are you sure you want to cancel creating this comment?'),
- };
- }
- return {
- title: s__('DesignManagement|Cancel comment update confirmation'),
- okTitle: s__('DesignManagement|Cancel changes'),
- cancelTitle: s__('DesignManagement|Keep changes'),
- content: s__('DesignManagement|Are you sure you want to cancel changes to this comment?'),
- };
- },
buttonText() {
return this.isNewComment
- ? s__('DesignManagement|Comment')
- : s__('DesignManagement|Save comment');
- },
- markdownDocsPath() {
- return helpPagePath('user/markdown');
+ ? this.$options.i18n.newCommentButton
+ : this.$options.i18n.updateCommentButton;
},
shortDiscussionId() {
return isGid(this.discussionId) ? getIdFromGraphQLId(this.discussionId) : this.discussionId;
@@ -94,12 +85,30 @@ export default {
},
cancelComment() {
if (this.hasValue && this.formText !== this.value) {
- this.$refs.cancelCommentModal.show();
+ this.confirmCancelCommentModal();
} else {
this.$emit('cancel-form');
}
},
- confirmCancelCommentModal() {
+ async confirmCancelCommentModal() {
+ const msg = this.isNewComment
+ ? this.$options.i18n.cancelCreate
+ : this.$options.i18n.cancelUpdate;
+
+ const cancelBtn = this.isNewComment
+ ? this.$options.i18n.cancelBtnCreate
+ : this.$options.i18n.cancelBtnUpdate;
+
+ const confirmed = await confirmAction(msg, {
+ primaryBtnText: this.$options.i18n.primaryBtn,
+ cancelBtnText: cancelBtn,
+ primaryBtnVariant: 'danger',
+ });
+
+ if (!confirmed) {
+ return;
+ }
+
this.$emit('cancel-form');
this.autosaveDiscussion.reset();
},
@@ -126,7 +135,7 @@ export default {
:markdown-preview-path="markdownPreviewPath"
:enable-autocomplete="true"
:textarea-value="value"
- :markdown-docs-path="markdownDocsPath"
+ :markdown-docs-path="$options.markdownDocsPath"
class="bordered-box"
>
<template #textarea>
@@ -171,15 +180,5 @@ export default {
>{{ __('Cancel') }}</gl-button
>
</div>
- <gl-modal
- ref="cancelCommentModal"
- ok-variant="danger"
- :title="modalSettings.title"
- :ok-title="modalSettings.okTitle"
- :cancel-title="modalSettings.cancelTitle"
- modal-id="cancel-comment-modal"
- @ok="confirmCancelCommentModal"
- >{{ modalSettings.content }}
- </gl-modal>
</form>
</template>
diff --git a/app/assets/javascripts/design_management/mixins/all_designs.js b/app/assets/javascripts/design_management/mixins/all_designs.js
index e92f8006a0d..b783ec43cd1 100644
--- a/app/assets/javascripts/design_management/mixins/all_designs.js
+++ b/app/assets/javascripts/design_management/mixins/all_designs.js
@@ -1,6 +1,6 @@
import { propertyOf } from 'lodash';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_WARNING } from '~/flash';
import { s__ } from '~/locale';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
import allVersionsMixin from './all_versions';
@@ -36,7 +36,7 @@ export default {
},
result() {
if (this.$route.query.version && !this.hasValidVersion) {
- createFlash({
+ createAlert({
message: s__(
'DesignManagement|Requested design version does not exist. Showing latest version instead',
),
@@ -44,11 +44,11 @@ export default {
this.$router.replace({ name: DESIGNS_ROUTE_NAME, query: { version: undefined } });
}
if (this.designCollection.copyState === 'ERROR') {
- createFlash({
+ createAlert({
message: s__(
'DesignManagement|There was an error moving your designs. Please upload your designs below.',
),
- type: FLASH_TYPES.WARNING,
+ variant: VARIANT_WARNING,
});
}
},
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 228ad637b9e..d4c177e2e5f 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -4,7 +4,7 @@ import { isNull } from 'lodash';
import Mousetrap from 'mousetrap';
import { ApolloMutation } from 'vue-apollo';
import { keysFor, ISSUE_CLOSE_DESIGN } from '~/behaviors/shortcuts/keybindings';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import { updateGlobalTodoCount } from '~/vue_shared/components/sidebar/todo_toggle/utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -250,7 +250,7 @@ export default {
onQueryError(message) {
// because we redirect user to /designs (the issue page),
// we want to create these flashes on the issue page
- createFlash({ message });
+ createAlert({ message });
this.$router.push({ name: this.$options.DESIGNS_ROUTE_NAME });
},
onError(message, e) {
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 07f7a19f7d4..fba73cd4bec 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -133,9 +133,13 @@ export default {
return this.designCollection && this.designCollection.copyState === 'IN_PROGRESS';
},
designDropzoneWrapperClass() {
- return this.isDesignListEmpty
- ? 'col-12'
- : 'gl-flex-direction-column col-md-6 col-lg-3 gl-mt-5';
+ if (!this.isDesignListEmpty) {
+ return 'gl-flex-direction-column col-md-6 col-lg-3 gl-mt-5';
+ }
+ if (this.showToolbar) {
+ return 'col-12 gl-mt-5';
+ }
+ return 'col-12';
},
},
mounted() {
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index c8f445bfb88..cfec5828c85 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -2,7 +2,7 @@
import produce from 'immer';
import { differenceBy } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
import {
ADD_IMAGE_DIFF_NOTE_ERROR,
@@ -234,7 +234,7 @@ export const deletePendingTodoFromStore = (store, todoMarkDone, query, queryVari
};
const onError = (data, message) => {
- createFlash({ message });
+ createAlert({ message });
throw new Error(data.errors);
};
@@ -283,7 +283,7 @@ export const updateStoreAfterUploadDesign = (store, data, query) => {
export const updateDesignsOnStoreAfterReorder = (store, data, query) => {
if (hasErrors(data)) {
- createFlash({ message: data.errors[0] });
+ createAlert({ message: data.errors[0] });
} else {
moveDesignInStore(store, data, query);
}
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index 833fbb8789e..23eb470503e 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { merge } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import FilesCommentButton from './files_comment_button';
@@ -82,7 +82,7 @@ export default class Diff {
.get(link, { params })
.then(({ data }) => $target.parent().replaceWith(data))
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while loading diff'),
}),
);
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index f5c0776ca35..bc49464a560 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -11,7 +11,7 @@ import {
MR_COMMITS_NEXT_COMMIT,
MR_COMMITS_PREVIOUS_COMMIT,
} from '~/behaviors/shortcuts/keybindings';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
import { helpPagePath } from '~/helpers/help_page_helper';
import { parseBoolean } from '~/lib/utils/common_utils';
@@ -471,8 +471,8 @@ export default {
},
fetchData(toggleTree = true) {
this.fetchDiffFilesMeta()
- .then(({ real_size }) => {
- this.diffFilesLength = parseInt(real_size, 10);
+ .then(({ real_size = 0 }) => {
+ this.diffFilesLength = parseInt(real_size, 10) || 0;
if (toggleTree) {
this.setTreeDisplay();
}
@@ -480,7 +480,7 @@ export default {
this.updateChangesTabCount();
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again!'),
});
});
@@ -495,7 +495,7 @@ export default {
this.setDiscussions();
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again!'),
});
});
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 0e5acd0928b..5a45797ed98 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -128,7 +128,7 @@ export default {
:img-src="authorAvatar"
:img-alt="authorName"
:img-size="32"
- class="avatar-cell d-none d-sm-block"
+ class="avatar-cell d-none d-sm-block gl-my-2 gl-mr-4"
/>
</div>
<div
@@ -172,7 +172,7 @@ export default {
v-if="commit.description_html"
v-safe-html:[$options.safeHtmlConfig]="commitDescription"
:class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
- class="commit-row-description gl-mb-3 gl-text-body"
+ class="commit-row-description gl-mb-3 gl-text-body gl-white-space-pre-line"
></pre>
</div>
</li>
diff --git a/app/assets/javascripts/diffs/components/commit_widget.vue b/app/assets/javascripts/diffs/components/commit_widget.vue
index b1a2b2a72ea..facfc553053 100644
--- a/app/assets/javascripts/diffs/components/commit_widget.vue
+++ b/app/assets/javascripts/diffs/components/commit_widget.vue
@@ -22,7 +22,7 @@ export default {
<template>
<div class="info-well mw-100 mx-0">
<div class="well-segment">
- <ul class="blob-commit-info">
+ <ul class="gl-list-style-none gl-m-0 gl-p-0">
<commit-item :commit="commit" :collapsible="collapsible" />
</ul>
</div>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 8a5325cf218..6104a304fbd 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -80,7 +80,7 @@ export default {
<template>
<div class="mr-version-controls">
- <div class="mr-version-menus-container content-block">
+ <div class="mr-version-menus-container gl-px-5 gl-pt-3 gl-pb-2">
<gl-button
v-if="hasChanges"
v-gl-tooltip.hover
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 3082ba0f16f..b2098b9e82d 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective, GlSafeHtmlDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mapActions } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__, sprintf } from '~/locale';
import { UNFOLD_COUNT, INLINE_DIFF_LINES_KEY } from '../constants';
import * as utils from '../store/utils';
@@ -92,7 +92,7 @@ export default {
) {
this.loadMoreLines({ endpoint, params, lineNumbers, fileHash, isExpandDown, nextLineNumbers })
.catch(() => {
- createFlash({
+ createAlert({
message: s__('Diffs|Something went wrong while fetching diff lines.'),
});
})
@@ -224,6 +224,7 @@ export default {
<button
v-if="showExpandDown"
:title="s__('Diffs|Next 20 lines')"
+ :aria-label="s__('Diffs|Next 20 lines')"
:disabled="loading.down"
type="button"
class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
@@ -235,6 +236,7 @@ export default {
<button
v-if="lineCountBetween !== -1 && lineCountBetween < 20"
:title="s__('Diffs|Expand all lines')"
+ :aria-label="s__('Diffs|Expand all lines')"
:disabled="loading.all"
type="button"
class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
@@ -246,6 +248,7 @@ export default {
<button
v-if="showExpandUp"
:title="s__('Diffs|Previous 20 lines')"
+ :aria-label="s__('Diffs|Previous 20 lines')"
:disabled="loading.up"
type="button"
class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index aec608007d5..422bf52a1fa 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -10,7 +10,7 @@ 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 { createAlert } from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
import { diffViewerErrors } from '~/ide/constants';
import { scrollToElement } from '~/lib/utils/common_utils';
@@ -309,7 +309,7 @@ export default {
})
.catch(() => {
idState.isLoadingCollapsedDiff = false;
- createFlash({
+ createAlert({
message: this.$options.i18n.genericError,
});
});
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 705b43a222d..91c3df39e32 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -281,7 +281,7 @@ export default {
'gl-z-dropdown-menu!': idState.moreActionsShown,
'is-sidebar-moved': glFeatures.movedMrSidebar,
}"
- class="js-file-title file-title file-title-flex-parent"
+ class="js-file-title file-title file-title-flex-parent gl-border"
data-qa-selector="file_title_container"
:data-qa-file-name="filePath"
@click.self="handleToggleFile"
diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js
index f610ac979ca..7732badde34 100644
--- a/app/assets/javascripts/diffs/components/diff_row_utils.js
+++ b/app/assets/javascripts/diffs/components/diff_row_utils.js
@@ -108,7 +108,7 @@ export const mapParallel = (content) => (line) => {
...left,
renderDiscussion: hasExpandedDiscussionOnLeft,
hasDraft: content.hasParallelDraftLeft(content.diffFile.file_hash, line),
- lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'left'),
+ lineDrafts: content.draftsForLine(content.diffFile.file_hash, line, 'left'),
hasCommentForm: left.hasForm,
isConflictMarker:
line.left.type === CONFLICT_MARKER_OUR || line.left.type === CONFLICT_MARKER_THEIR,
@@ -123,7 +123,7 @@ export const mapParallel = (content) => (line) => {
hasExpandedDiscussionOnRight && right.type && right.type !== EXPANDED_LINE_TYPE,
),
hasDraft: content.hasParallelDraftRight(content.diffFile.file_hash, line),
- lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'right'),
+ lineDrafts: content.draftsForLine(content.diffFile.file_hash, line, 'right'),
hasCommentForm: Boolean(right.hasForm && right.type && right.type !== EXPANDED_LINE_TYPE),
emptyCellClassMap: { conflict_their: line.left?.type === CONFLICT_OUR },
addCommentTooltip: addCommentTooltip(line.right),
@@ -145,7 +145,7 @@ export const mapParallel = (content) => (line) => {
lineCode: lineCode(line),
isMetaLineLeft: isMetaLine(left?.type),
isMetaLineRight: isMetaLine(right?.type),
- draftRowClasses: left?.lineDraft > 0 || right?.lineDraft > 0 ? '' : 'js-temp-notes-holder',
+ draftRowClasses: left?.hasDraft || right?.hasDraft ? '' : 'js-temp-notes-holder',
renderCommentRow,
commentRowClasses: hasDiscussions(left) || hasDiscussions(right) ? '' : 'js-temp-notes-holder',
};
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 91bf3283379..5ea118afe78 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -177,6 +177,12 @@ export default {
getCodeQualityLine(line) {
return (line.left ?? line.right)?.codequality?.[0]?.line;
},
+ lineDrafts(line, side) {
+ return (line[side]?.lineDrafts || []).filter((entry) => entry.isDraft);
+ },
+ lineHasDrafts(line, side) {
+ return this.lineDrafts(line, side).length > 0;
+ },
},
userColorScheme: window.gon.user_color_scheme,
};
@@ -297,19 +303,19 @@ export default {
class="diff-grid-drafts diff-tr notes_holder"
>
<div
- v-if="!inline || (line.left && line.left.lineDraft.isDraft)"
+ v-if="!inline || lineHasDrafts(line, 'left')"
class="diff-td notes-content parallel old"
>
- <div v-if="line.left && line.left.lineDraft.isDraft" class="content">
- <draft-note :draft="line.left.lineDraft" :line="line.left" />
+ <div v-for="draft in lineDrafts(line, 'left')" :key="draft.id" class="content">
+ <draft-note :draft="draft" :line="line.left" />
</div>
</div>
<div
- v-if="!inline || (line.right && line.right.lineDraft.isDraft)"
+ v-if="!inline || lineHasDrafts(line, 'right')"
class="diff-td notes-content parallel new"
>
- <div v-if="line.right && line.right.lineDraft.isDraft" class="content">
- <draft-note :draft="line.right.lineDraft" :line="line.right" />
+ <div v-for="draft in lineDrafts(line, 'right')" :key="draft.id" class="content">
+ <draft-note :draft="draft" :line="line.right" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/mixins/draft_comments.js b/app/assets/javascripts/diffs/mixins/draft_comments.js
index 693b4a84694..d41bb160e96 100644
--- a/app/assets/javascripts/diffs/mixins/draft_comments.js
+++ b/app/assets/javascripts/diffs/mixins/draft_comments.js
@@ -5,7 +5,7 @@ export default {
...mapGetters('batchComments', [
'shouldRenderDraftRow',
'shouldRenderParallelDraftRow',
- 'draftForLine',
+ 'draftsForLine',
'draftsForFile',
'hasParallelDraftLeft',
'hasParallelDraftRight',
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 5e74a7206b3..5234be44b05 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -5,7 +5,7 @@ import {
historyPushState,
scrollToElement,
} from '~/lib/utils/common_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { diffViewerModes } from '~/ide/constants';
import axios from '~/lib/utils/axios_utils';
@@ -202,6 +202,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
const worker = new TreeWorker();
const urlParams = {
view: 'inline',
+ w: state.showWhitespace ? '0' : '1',
};
commit(types.SET_LOADING, true);
@@ -246,7 +247,7 @@ export const fetchCoverageFiles = ({ commit, state }) => {
}
},
errorCallback: () =>
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again!'),
}),
});
@@ -509,7 +510,7 @@ export const saveDiffDiscussion = ({ state, dispatch }, { note, formData }) => {
.then(() => dispatch('updateResolvableDiscussionsCounts', null, { root: true }))
.then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash))
.catch(() =>
- createFlash({
+ createAlert({
message: s__('MergeRequests|Saving the comment failed'),
}),
);
@@ -619,7 +620,7 @@ export const cacheTreeListWidth = (_, size) => {
export const receiveFullDiffError = ({ commit }, filePath) => {
commit(types.RECEIVE_FULL_DIFF_ERROR, filePath);
- createFlash({
+ createAlert({
message: s__('MergeRequest|Error loading full diff. Please try again.'),
});
};
@@ -757,7 +758,7 @@ export const setSuggestPopoverDismissed = ({ commit, state }) =>
commit(types.SET_SHOW_SUGGEST_POPOVER);
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__('MergeRequest|Error dismissing suggestion popover. Please try again.'),
});
});
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
index bc3cb163c39..999e91eed19 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
@@ -1,7 +1,7 @@
import { KeyMod, KeyCode } from 'monaco-editor';
import { debounce } from 'lodash';
import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
import syntaxHighlight from '~/syntax_highlight';
@@ -152,7 +152,7 @@ export class EditorMarkdownPreviewExtension {
syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
previewEl.style.display = 'block';
})
- .catch(() => createFlash(BLOB_PREVIEW_ERROR));
+ .catch(() => createAlert(BLOB_PREVIEW_ERROR));
}
setupPreviewAction(instance) {
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index 848ba7dbeef..e56932a9a31 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -1,7 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gitlab.com/.gitlab-ci.yml",
- "title": "Gitlab CI configuration",
"markdownDescription": "Gitlab has a built-in solution for doing CI called Gitlab CI. It is configured by supplying a file called `.gitlab-ci.yml`, which will list all the jobs that are going to run for the project. A full list of all options can be found [here](https://docs.gitlab.com/ee/ci/yaml). [Learn More](https://docs.gitlab.com/ee/ci/index.html).",
"type": "object",
"properties": {
@@ -9,34 +8,74 @@
"type": "string",
"format": "uri"
},
- "image": { "$ref": "#/definitions/image" },
- "services": { "$ref": "#/definitions/services" },
- "before_script": { "$ref": "#/definitions/before_script" },
- "after_script": { "$ref": "#/definitions/after_script" },
- "variables": { "$ref": "#/definitions/globalVariables" },
- "cache": { "$ref": "#/definitions/cache" },
- "!reference": {"$ref" : "#/definitions/!reference"},
+ "image": {
+ "$ref": "#/definitions/image"
+ },
+ "services": {
+ "$ref": "#/definitions/services"
+ },
+ "before_script": {
+ "$ref": "#/definitions/before_script"
+ },
+ "after_script": {
+ "$ref": "#/definitions/after_script"
+ },
+ "variables": {
+ "$ref": "#/definitions/globalVariables"
+ },
+ "cache": {
+ "$ref": "#/definitions/cache"
+ },
+ "!reference": {
+ "$ref": "#/definitions/!reference"
+ },
"default": {
"type": "object",
"properties": {
- "after_script": { "$ref": "#/definitions/after_script" },
- "artifacts": { "$ref": "#/definitions/artifacts" },
- "before_script": { "$ref": "#/definitions/before_script" },
- "cache": { "$ref": "#/definitions/cache" },
- "image": { "$ref": "#/definitions/image" },
- "interruptible": { "$ref": "#/definitions/interruptible" },
- "retry": { "$ref": "#/definitions/retry" },
- "services": { "$ref": "#/definitions/services" },
- "tags": { "$ref": "#/definitions/tags" },
- "timeout": { "$ref": "#/definitions/timeout" },
- "!reference": {"$ref" : "#/definitions/!reference"}
+ "after_script": {
+ "$ref": "#/definitions/after_script"
+ },
+ "artifacts": {
+ "$ref": "#/definitions/artifacts"
+ },
+ "before_script": {
+ "$ref": "#/definitions/before_script"
+ },
+ "cache": {
+ "$ref": "#/definitions/cache"
+ },
+ "image": {
+ "$ref": "#/definitions/image"
+ },
+ "interruptible": {
+ "$ref": "#/definitions/interruptible"
+ },
+ "retry": {
+ "$ref": "#/definitions/retry"
+ },
+ "services": {
+ "$ref": "#/definitions/services"
+ },
+ "tags": {
+ "$ref": "#/definitions/tags"
+ },
+ "timeout": {
+ "$ref": "#/definitions/timeout"
+ },
+ "!reference": {
+ "$ref": "#/definitions/!reference"
+ }
},
"additionalProperties": false
},
"stages": {
"type": "array",
"markdownDescription": "Groups jobs into stages. All jobs in one stage must complete before next stage is executed. Defaults to ['build', 'test', 'deploy']. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#stages).",
- "default": ["build", "test", "deploy"],
+ "default": [
+ "build",
+ "test",
+ "deploy"
+ ],
"items": {
"type": "string"
},
@@ -46,10 +85,14 @@
"include": {
"markdownDescription": "Can be `IncludeItem` or `IncludeItem[]`. Each `IncludeItem` will be a string, or an object with properties for the method if including external YAML file. The external content will be fetched, included and evaluated along the `.gitlab-ci.yml`. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#include).",
"oneOf": [
- { "$ref": "#/definitions/include_item" },
+ {
+ "$ref": "#/definitions/include_item"
+ },
{
"type": "array",
- "items": { "$ref": "#/definitions/include_item" }
+ "items": {
+ "$ref": "#/definitions/include_item"
+ }
}
]
},
@@ -60,21 +103,41 @@
"workflow": {
"type": "object",
"properties": {
+ "name": { "$ref": "#/definitions/workflowName" },
"rules": {
"type": "array",
"items": {
"anyOf": [
- {"type": "object"},
- {"type": "array", "minLength": 1, "items": { "type": "string" }}
+ {
+ "type": "object"
+ },
+ {
+ "type": "array",
+ "minLength": 1,
+ "items": {
+ "type": "string"
+ }
+ }
],
"properties": {
- "if": { "$ref": "#/definitions/if" },
- "changes": { "$ref": "#/definitions/changes" },
- "exists": { "$ref": "#/definitions/exists" },
- "variables": { "$ref": "#/definitions/variables" },
+ "if": {
+ "$ref": "#/definitions/if"
+ },
+ "changes": {
+ "$ref": "#/definitions/changes"
+ },
+ "exists": {
+ "$ref": "#/definitions/exists"
+ },
+ "variables": {
+ "$ref": "#/definitions/variables"
+ },
"when": {
"type": "string",
- "enum": ["always", "never"]
+ "enum": [
+ "always",
+ "never"
+ ]
}
},
"additionalProperties": false
@@ -87,8 +150,12 @@
"^[.]": {
"description": "Hidden keys.",
"anyOf": [
- { "$ref": "#/definitions/job_template" },
- { "description": "Arbitrary YAML anchor." }
+ {
+ "$ref": "#/definitions/job_template"
+ },
+ {
+ "description": "Arbitrary YAML anchor."
+ }
]
}
},
@@ -135,15 +202,21 @@
"default": "on_success",
"oneOf": [
{
- "enum": ["on_success"],
+ "enum": [
+ "on_success"
+ ],
"description": "Upload artifacts only when the job succeeds (this is the default)."
},
{
- "enum": ["on_failure"],
+ "enum": [
+ "on_failure"
+ ],
"description": "Upload artifacts only when the job fails."
},
{
- "enum": ["always"],
+ "enum": [
+ "always"
+ ],
"description": "Upload artifacts regardless of job status."
}
]
@@ -181,7 +254,9 @@
"properties": {
"coverage_format": {
"description": "Code coverage format used by the test framework.",
- "enum": ["cobertura"]
+ "enum": [
+ "cobertura"
+ ]
},
"path": {
"description": "Path to the coverage report file that should be parsed.",
@@ -285,18 +360,22 @@
"format": "uri-reference",
"pattern": "\\.ya?ml$"
},
- "rules": { "$ref": "#/definitions/rules" }
+ "rules": {
+ "$ref": "#/definitions/rules"
+ }
},
- "required": ["local"]
+ "required": [
+ "local"
+ ]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"project": {
- "description": "Path to the project, e.g. `group/project`, or `group/sub-group/project`.",
+ "description": "Path to the project, e.g. `group/project`, or `group/sub-group/project` [Learn more](https://docs.gitlab.com/ee/ci/yaml/index.html#includefile).",
"type": "string",
- "pattern": "\\S/\\S|\\$(\\S+)"
+ "pattern": "(?:\\S/\\S|\\$\\S+)"
},
"ref": {
"description": "Branch/Tag/Commit-hash for the target project.",
@@ -320,7 +399,10 @@
]
}
},
- "required": ["project", "file"]
+ "required": [
+ "project",
+ "file"
+ ]
},
{
"type": "object",
@@ -333,7 +415,9 @@
"pattern": "\\.ya?ml$"
}
},
- "required": ["template"]
+ "required": [
+ "template"
+ ]
},
{
"type": "object",
@@ -346,7 +430,9 @@
"pattern": "^https?://.+\\.ya?ml$"
}
},
- "required": ["remote"]
+ "required": [
+ "remote"
+ ]
}
]
},
@@ -407,7 +493,16 @@
]
}
},
- "required": ["name"]
+ "required": [
+ "name"
+ ]
+ },
+ {
+ "type": "array",
+ "minLength": 1,
+ "items": {
+ "type": "string"
+ }
}
],
"markdownDescription": "Specifies the docker image to use for the job or globally for all jobs. Job configuration takes precedence over global setting. Requires a certain kind of Gitlab runner executor. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#image)."
@@ -481,7 +576,9 @@
"minLength": 1
}
},
- "required": ["name"]
+ "required": [
+ "name"
+ ]
}
]
}
@@ -505,20 +602,37 @@
"engine": {
"type": "object",
"properties": {
- "name": { "type": "string" },
- "path": { "type": "string" }
+ "name": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ }
},
- "required": ["name", "path"]
+ "required": [
+ "name",
+ "path"
+ ]
+ },
+ "path": {
+ "type": "string"
},
- "path": { "type": "string" },
- "field": { "type": "string" }
+ "field": {
+ "type": "string"
+ }
},
- "required": ["engine", "path", "field"]
+ "required": [
+ "engine",
+ "path",
+ "field"
+ ]
}
]
}
},
- "required": ["vault"]
+ "required": [
+ "vault"
+ ]
}
},
"before_script": {
@@ -564,45 +678,77 @@
"type": "object",
"additionalProperties": false,
"properties": {
- "if": { "$ref": "#/definitions/if" },
- "changes": { "$ref": "#/definitions/changes" },
- "exists": { "$ref": "#/definitions/exists" },
- "variables": { "$ref": "#/definitions/variables" },
- "when": { "$ref": "#/definitions/when" },
- "start_in": { "$ref": "#/definitions/start_in" },
- "allow_failure": { "$ref": "#/definitions/allow_failure" }
+ "if": {
+ "$ref": "#/definitions/if"
+ },
+ "changes": {
+ "$ref": "#/definitions/changes"
+ },
+ "exists": {
+ "$ref": "#/definitions/exists"
+ },
+ "variables": {
+ "$ref": "#/definitions/variables"
+ },
+ "when": {
+ "$ref": "#/definitions/when"
+ },
+ "start_in": {
+ "$ref": "#/definitions/start_in"
+ },
+ "allow_failure": {
+ "$ref": "#/definitions/allow_failure"
+ }
}
},
- {"type": "string", "minLength": 1},
- {"type": "array", "minLength": 1, "items": { "type": "string" }}
+ {
+ "type": "string",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "minLength": 1,
+ "items": {
+ "type": "string"
+ }
+ }
]
}
},
+ "workflowName": {
+ "type": "string",
+ "markdownDescription": "Defines the pipeline name. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#workflowname).",
+ "minLength": 1,
+ "maxLength": 255
+ },
"globalVariables": {
- "markdownDescription": "Defines environment variables globally. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. You can use the value and description keywords to define variables that are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
- "anyOf": [
- {"type": "object"},
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ],
- "additionalProperties": {
- "anyOf": [
- {"type": ["string", "integer", "array"]},
- {
- "type": "object",
- "properties": {
- "value": { "type": "string" },
- "description": {
- "type": "string",
- "description": "Explains what the variable is used for, what the acceptable values are."
- }
+ "markdownDescription": "Defines default variables for all jobs. Job level property overrides global variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "oneOf": [
+ {
+ "type": [
+ "string",
+ "number"
+ ]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "markdownDescription": "Explains what the variable is used for, what the acceptable values are. Variables with `description` are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variablesdescription)."
+ }
+ },
+ "additionalProperties": false
}
- }
- ]
+ ]
+ },
+ "additionalProperties": false
}
},
"if": {
@@ -615,7 +761,9 @@
{
"type": "object",
"additionalProperties": false,
- "required": ["paths"],
+ "required": [
+ "paths"
+ ],
"properties": {
"paths": {
"type": "array",
@@ -646,21 +794,17 @@
}
},
"variables": {
- "markdownDescription": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables).",
- "anyOf": [
- {
- "type": "object",
- "additionalProperties": {
- "type": ["string", "integer", "array"]
- }
+ "markdownDescription": "Defines environment variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "type": [
+ "string",
+ "number"
+ ]
},
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
+ "additionalProperties": false
+ }
},
"timeout": {
"type": "string",
@@ -684,7 +828,9 @@
"description": "Exit code that are not considered failure. The job fails for any other exit code.",
"type": "object",
"additionalProperties": false,
- "required": ["exit_codes"],
+ "required": [
+ "exit_codes"
+ ],
"properties": {
"exit_codes": {
"type": "integer"
@@ -695,7 +841,9 @@
"description": "You can list which exit codes are not considered failures. The job fails for any other exit code.",
"type": "object",
"additionalProperties": false,
- "required": ["exit_codes"],
+ "required": [
+ "exit_codes"
+ ],
"properties": {
"exit_codes": {
"type": "array",
@@ -714,27 +862,39 @@
"default": "on_success",
"oneOf": [
{
- "enum": ["on_success"],
+ "enum": [
+ "on_success"
+ ],
"description": "Execute job only when all jobs from prior stages succeed."
},
{
- "enum": ["on_failure"],
+ "enum": [
+ "on_failure"
+ ],
"description": "Execute job when at least one job from prior stages fails."
},
{
- "enum": ["always"],
+ "enum": [
+ "always"
+ ],
"description": "Execute job regardless of the status from prior stages."
},
{
- "enum": ["manual"],
+ "enum": [
+ "manual"
+ ],
"markdownDescription": "Execute the job manually from Gitlab UI or API. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#when)."
},
{
- "enum": ["delayed"],
+ "enum": [
+ "delayed"
+ ],
"markdownDescription": "Execute a job after the time limit in 'start_in' expires. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#when)."
},
{
- "enum": ["never"],
+ "enum": [
+ "never"
+ ],
"description": "Never execute the job."
}
]
@@ -746,15 +906,21 @@
"default": "on_success",
"oneOf": [
{
- "enum": ["on_success"],
+ "enum": [
+ "on_success"
+ ],
"description": "Save the cache only when the job succeeds."
},
{
- "enum": ["on_failure"],
+ "enum": [
+ "on_failure"
+ ],
"description": "Save the cache only when the job fails. "
},
{
- "enum": ["always"],
+ "enum": [
+ "always"
+ ],
"description": "Always save the cache. "
}
]
@@ -806,15 +972,21 @@
"default": "pull-push",
"oneOf": [
{
- "enum": ["pull"],
+ "enum": [
+ "pull"
+ ],
"description": "Pull will download cache but skip uploading after job completes."
},
{
- "enum": ["push"],
+ "enum": [
+ "push"
+ ],
"description": "Push will skip downloading cache and always recreate cache after job completes."
},
{
- "enum": ["pull-push"],
+ "enum": [
+ "pull-push"
+ ],
"description": "Pull-push will both download cache at job start and upload cache on job success."
}
]
@@ -829,39 +1001,57 @@
{
"oneOf": [
{
- "enum": ["branches"],
+ "enum": [
+ "branches"
+ ],
"description": "When a branch is pushed."
},
{
- "enum": ["tags"],
+ "enum": [
+ "tags"
+ ],
"description": "When a tag is pushed."
},
{
- "enum": ["api"],
+ "enum": [
+ "api"
+ ],
"description": "When a pipeline has been triggered by a second pipelines API (not triggers API)."
},
{
- "enum": ["external"],
+ "enum": [
+ "external"
+ ],
"description": "When using CI services other than Gitlab"
},
{
- "enum": ["pipelines"],
+ "enum": [
+ "pipelines"
+ ],
"description": "For multi-project triggers, created using the API with 'CI_JOB_TOKEN'."
},
{
- "enum": ["pushes"],
+ "enum": [
+ "pushes"
+ ],
"description": "Pipeline is triggered by a `git push` by the user"
},
{
- "enum": ["schedules"],
+ "enum": [
+ "schedules"
+ ],
"description": "For scheduled pipelines."
},
{
- "enum": ["triggers"],
+ "enum": [
+ "triggers"
+ ],
"description": "For pipelines created using a trigger token."
},
{
- "enum": ["web"],
+ "enum": [
+ "web"
+ ],
"description": "For pipelines created using *Run pipeline* button in Gitlab UI (under your project's *Pipelines*)."
}
]
@@ -889,7 +1079,9 @@
"$ref": "#/definitions/filter_refs"
},
"kubernetes": {
- "enum": ["active"],
+ "enum": [
+ "active"
+ ],
"description": "Filter job based on if Kubernetes integration is active."
},
"variables": {
@@ -913,16 +1105,22 @@
"retry": {
"markdownDescription": "Retry a job if it fails. Can be a simple integer or object definition. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#retry).",
"oneOf": [
- { "$ref": "#/definitions/retry_max" },
+ {
+ "$ref": "#/definitions/retry_max"
+ },
{
"type": "object",
"additionalProperties": false,
"properties": {
- "max": { "$ref": "#/definitions/retry_max" },
+ "max": {
+ "$ref": "#/definitions/retry_max"
+ },
"when": {
"markdownDescription": "Either a single or array of error types to trigger job retry. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#retrywhen).",
"oneOf": [
- { "$ref": "#/definitions/retry_errors" },
+ {
+ "$ref": "#/definitions/retry_errors"
+ },
{
"type": "array",
"items": {
@@ -1005,21 +1203,39 @@
},
"job": {
"allOf": [
- { "$ref": "#/definitions/job_template" }
+ {
+ "$ref": "#/definitions/job_template"
+ }
]
},
"job_template": {
"type": "object",
"additionalProperties": false,
"properties": {
- "image": { "$ref": "#/definitions/image" },
- "services": { "$ref": "#/definitions/services" },
- "before_script": { "$ref": "#/definitions/before_script" },
- "after_script": { "$ref": "#/definitions/after_script" },
- "rules": { "$ref": "#/definitions/rules" },
- "variables": { "$ref": "#/definitions/variables" },
- "cache": { "$ref": "#/definitions/cache" },
- "secrets": { "$ref": "#/definitions/secrets" },
+ "image": {
+ "$ref": "#/definitions/image"
+ },
+ "services": {
+ "$ref": "#/definitions/services"
+ },
+ "before_script": {
+ "$ref": "#/definitions/before_script"
+ },
+ "after_script": {
+ "$ref": "#/definitions/after_script"
+ },
+ "rules": {
+ "$ref": "#/definitions/rules"
+ },
+ "variables": {
+ "$ref": "#/definitions/variables"
+ },
+ "cache": {
+ "$ref": "#/definitions/cache"
+ },
+ "secrets": {
+ "$ref": "#/definitions/secrets"
+ },
"script": {
"markdownDescription": "Shell scripts executed by the Runner. The only required property of jobs. Be careful with special characters (e.g. `:`, `{`, `}`, `&`) and use single or double quotes to avoid issues. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#script)",
"oneOf": [
@@ -1047,9 +1263,20 @@
]
},
"stage": {
- "type": "string",
"description": "Define what stage the job will run in.",
- "minLength": 1
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "minLength": 1,
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
},
"only": {
"$ref": "#/definitions/filter",
@@ -1092,7 +1319,9 @@
"type": "boolean"
}
},
- "required": ["job"]
+ "required": [
+ "job"
+ ]
},
{
"type": "object",
@@ -1108,7 +1337,10 @@
"type": "boolean"
}
},
- "required": ["job", "pipeline"]
+ "required": [
+ "job",
+ "pipeline"
+ ]
},
{
"type": "object",
@@ -1127,7 +1359,11 @@
"type": "boolean"
}
},
- "required": ["job", "project", "ref"]
+ "required": [
+ "job",
+ "project",
+ "ref"
+ ]
}
]
}
@@ -1164,7 +1400,9 @@
"environment": {
"description": "Used to associate environment metadata with a deploy. Environment can have a name and URL attached to it, and will be displayed under /environments under the project.",
"oneOf": [
- { "type": "string" },
+ {
+ "type": "string"
+ },
{
"type": "object",
"additionalProperties": false,
@@ -1185,7 +1423,13 @@
"description": "The name of a job to execute when the environment is about to be stopped."
},
"action": {
- "enum": ["start", "prepare", "stop", "verify", "access"],
+ "enum": [
+ "start",
+ "prepare",
+ "stop",
+ "verify",
+ "access"
+ ],
"description": "Specifies what this job will do. 'start' (default) indicates the job will start the deployment. 'prepare'/'verify'/'access' indicates this will not affect the deployment. 'stop' indicates this will stop the deployment.",
"default": "start"
},
@@ -1216,7 +1460,9 @@
]
}
},
- "required": ["name"]
+ "required": [
+ "name"
+ ]
}
]
},
@@ -1296,15 +1542,23 @@
]
}
},
- "required": ["name", "url"]
+ "required": [
+ "name",
+ "url"
+ ]
},
"minItems": 1
}
},
- "required": ["links"]
+ "required": [
+ "links"
+ ]
}
},
- "required": ["tag_name", "description"]
+ "required": [
+ "tag_name",
+ "description"
+ ]
},
"coverage": {
"type": "string",
@@ -1335,14 +1589,20 @@
"type": "object",
"description": "Defines environment variables for specific job.",
"additionalProperties": {
- "type": ["string", "number", "array"]
+ "type": [
+ "string",
+ "number",
+ "array"
+ ]
}
},
"maxItems": 50
}
},
"additionalProperties": false,
- "required": ["matrix"]
+ "required": [
+ "matrix"
+ ]
}
]
},
@@ -1364,7 +1624,7 @@
"project": {
"description": "Path to the project, e.g. `group/project`, or `group/sub-group/project`.",
"type": "string",
- "pattern": "\\S/\\S"
+ "pattern": "(?:\\S/\\S|\\$\\S+)"
},
"branch": {
"description": "The branch name that a downstream pipeline will use",
@@ -1373,7 +1633,9 @@
"strategy": {
"description": "You can mirror the pipeline status from the triggered pipeline to the source bridge job by using strategy: depend",
"type": "string",
- "enum": ["depend"]
+ "enum": [
+ "depend"
+ ]
},
"forward": {
"description": "Specify what to forward to the downstream pipeline.",
@@ -1393,9 +1655,13 @@
}
}
},
- "required": ["project"],
+ "required": [
+ "project"
+ ],
"dependencies": {
- "branch": ["project"]
+ "branch": [
+ "project"
+ ]
}
},
{
@@ -1456,7 +1722,10 @@
"type": "string"
}
},
- "required": ["artifact", "job"]
+ "required": [
+ "artifact",
+ "job"
+ ]
},
{
"type": "object",
@@ -1465,7 +1734,7 @@
"project": {
"description": "Path to another private project under the same GitLab instance, like `group/project` or `group/sub-group/project`.",
"type": "string",
- "pattern": "\\S/\\S"
+ "pattern": "(?:\\S/\\S|\\$\\S+)"
},
"ref": {
"description": "Branch/Tag/Commit hash for the target project.",
@@ -1479,7 +1748,10 @@
"pattern": "\\.ya?ml$"
}
},
- "required": ["project", "file"]
+ "required": [
+ "project",
+ "file"
+ ]
}
]
}
@@ -1489,7 +1761,9 @@
"strategy": {
"description": "You can mirror the pipeline status from the triggered pipeline to the source bridge job by using strategy: depend",
"type": "string",
- "enum": ["depend"]
+ "enum": [
+ "depend"
+ ]
},
"forward": {
"description": "Specify what to forward to the downstream pipeline.",
@@ -1511,9 +1785,9 @@
}
},
{
- "markdownDescription": "Path to the project, e.g. `group/project`, or `group/sub-group/project`. [Learn More](https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#define-multi-project-pipelines-in-your-gitlab-ciyml-file).",
+ "markdownDescription": "Path to the project, e.g. `group/project`, or `group/sub-group/project`. [Learn More](https://docs.gitlab.com/ee/ci/yaml/index.html#trigger).",
"type": "string",
- "pattern": "\\S/\\S"
+ "pattern": "(?:\\S/\\S|\\$\\S+)"
}
]
},
@@ -1550,7 +1824,9 @@
"variables": {
"markdownDescription": "Whether to inherit all globally-defined variables or not. Or subset of inherited variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#inheritvariables).",
"oneOf": [
- { "type": "boolean" },
+ {
+ "type": "boolean"
+ },
{
"type": "array",
"items": {
@@ -1566,15 +1842,24 @@
"oneOf": [
{
"properties": {
- "when": { "enum": ["delayed"] }
+ "when": {
+ "enum": [
+ "delayed"
+ ]
+ }
},
- "required": ["when", "start_in"]
+ "required": [
+ "when",
+ "start_in"
+ ]
},
{
"properties": {
"when": {
"not": {
- "enum": ["delayed"]
+ "enum": [
+ "delayed"
+ ]
}
}
}
@@ -1583,10 +1868,23 @@
},
"tags": {
"type": "array",
+ "minLength": 1,
"markdownDescription": "Used to select runners from the list of available runners. A runner must have all tags listed here to run the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#tags).",
"items": {
- "type": "string"
+ "anyOf": [
+ {
+ "type": "string",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "minLength": 1,
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
}
}
}
-}
+} \ No newline at end of file
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
index 3173c2bd644..78e1b8d5cb2 100644
--- a/app/assets/javascripts/environments/components/delete_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlModal } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
import deleteEnvironmentMutation from '../graphql/mutations/delete_environment.mutation.graphql';
@@ -65,11 +65,11 @@ export default {
.then(({ data }) => {
const [message] = data?.deleteEvironment?.errors ?? [];
if (message) {
- createFlash({ message });
+ createAlert({ message });
}
})
.catch((error) =>
- createFlash({
+ createAlert({
message: s__(
'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
),
diff --git a/app/assets/javascripts/environments/components/deployment.vue b/app/assets/javascripts/environments/components/deployment.vue
index 3475b38c8c9..b00a0777a03 100644
--- a/app/assets/javascripts/environments/components/deployment.vue
+++ b/app/assets/javascripts/environments/components/deployment.vue
@@ -10,7 +10,7 @@ import {
import { __, s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import deploymentDetails from '../graphql/queries/deployment_details.query.graphql';
import DeploymentStatusBadge from './deployment_status_badge.vue';
import Commit from './commit.vue';
@@ -119,7 +119,7 @@ export default {
return data?.project?.deployment?.tags;
},
error(error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.LOAD_ERROR_MESSAGE,
captureError: true,
error,
diff --git a/app/assets/javascripts/environments/components/edit_environment.vue b/app/assets/javascripts/environments/components/edit_environment.vue
index 96742a11ebb..901d0f5b34d 100644
--- a/app/assets/javascripts/environments/components/edit_environment.vue
+++ b/app/assets/javascripts/environments/components/edit_environment.vue
@@ -1,5 +1,5 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import EnvironmentForm from './environment_form.vue';
@@ -39,7 +39,7 @@ export default {
.then(({ data: { path } }) => visitUrl(path))
.catch((error) => {
const message = error.response.data.message[0];
- createFlash({ message });
+ createAlert({ message });
this.loading = false;
});
},
diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue
index 563fa6c96fb..e40c37b5095 100644
--- a/app/assets/javascripts/environments/components/empty_state.vue
+++ b/app/assets/javascripts/environments/components/empty_state.vue
@@ -1,9 +1,14 @@
<script>
+import { GlEmptyState, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import { ENVIRONMENTS_SCOPE } from '../constants';
export default {
- name: 'EnvironmentsEmptyState',
+ components: {
+ GlEmptyState,
+ GlLink,
+ },
+ inject: ['newEnvironmentPath'],
props: {
helpPath: {
type: String,
@@ -13,10 +18,23 @@ export default {
type: String,
required: true,
},
+ hasTerm: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
title() {
- return this.$options.i18n.title[this.scope];
+ return this.hasTerm
+ ? this.$options.i18n.searchingTitle
+ : this.$options.i18n.title[this.scope];
+ },
+ content() {
+ return this.hasTerm ? this.$options.i18n.searchingContent : this.$options.i18n.content;
+ },
+ buttonText() {
+ return this.hasTerm ? this.$options.i18n.newEnvironmentButtonLabel : '';
},
},
i18n: {
@@ -27,20 +45,21 @@ export default {
content: s__(
'Environments|Environments are places where code gets deployed, such as staging or production.',
),
+ searchingTitle: s__('Environments|No results found'),
+ searchingContent: s__('Environments|Edit your search and try again'),
link: s__('Environments|How do I create an environment?'),
+ newEnvironmentButtonLabel: s__('Environments|New environment'),
},
};
</script>
<template>
- <div class="empty-state">
- <div class="text-content">
- <h4 class="js-blank-state-title">
- {{ title }}
- </h4>
- <p>
- {{ $options.i18n.content }}
- <a :href="helpPath"> {{ $options.i18n.link }} </a>
- </p>
- </div>
- </div>
+ <gl-empty-state :primary-button-text="buttonText" :primary-button-link="newEnvironmentPath">
+ <template #title>
+ <h4>{{ title }}</h4>
+ </template>
+ <template #description>
+ <p>{{ content }}</p>
+ <gl-link v-if="!hasTerm" :href="helpPath">{{ $options.i18n.link }}</gl-link>
+ </template>
+ </gl-empty-state>
</template>
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 6343fe8702a..420ad3d9c42 100644
--- a/app/assets/javascripts/environments/components/enable_review_app_modal.vue
+++ b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
@@ -1,18 +1,19 @@
<script>
-import { GlLink, GlModal, GlSprintf } from '@gitlab/ui';
+import { GlLink, GlModal, GlSprintf, GlIcon, GlPopover } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { s__ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import { REVIEW_APP_MODAL_I18N as i18n } from '../constants';
export default {
components: {
GlLink,
GlModal,
GlSprintf,
+ GlIcon,
+ GlPopover,
ModalCopyButton,
},
- inject: ['defaultBranchName'],
model: {
prop: 'visible',
event: 'change',
@@ -28,25 +29,6 @@ export default {
default: false,
},
},
- instructionText: {
- step1: s__(
- 'EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}.',
- ),
- step2: s__('EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:'),
- step3: s__(
- `EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file.`,
- ),
- step4: s__(
- `EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}.`,
- ),
- },
- modalInfo: {
- closeText: s__('EnableReviewApp|Close'),
- copyToClipboardText: s__('EnableReviewApp|Copy snippet text'),
- title: s__('ReviewApp|Enable Review App'),
- },
- visualReviewsDocs: helpPagePath('ci/review_apps/index.md', { anchor: 'visual-reviews' }),
- connectClusterDocs: helpPagePath('user/clusters/agent/index'),
data() {
const modalInfoCopyId = uniqueId('enable-review-app-copy-string-');
@@ -57,81 +39,99 @@ export default {
return `deploy_review:
stage: deploy
script:
- - echo "Deploy a review app"
+ - echo "Add script here that deploys the code to your infrastructure"
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG.example.com
- only:
- - branches
- except:
- - ${this.defaultBranchName}`;
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"`;
+ },
+ },
+ methods: {
+ commaOrPeriod(index, length) {
+ return index + 1 === length ? '.' : ',';
},
},
+ i18n,
+ configuringReviewAppsPath: helpPagePath('ci/review_apps/index.md', {
+ anchor: 'configuring-review-apps',
+ }),
+ reviewAppsExamplesPath: helpPagePath('ci/review_apps/index.md', {
+ anchor: 'review-apps-examples',
+ }),
};
</script>
<template>
<gl-modal
:visible="visible"
:modal-id="modalId"
- :title="$options.modalInfo.title"
+ :title="$options.i18n.title"
static
size="lg"
- ok-only
- ok-variant="light"
- :ok-title="$options.modalInfo.closeText"
+ hide-footer
@change="$emit('change', $event)"
>
+ <p>{{ $options.i18n.intro }}</p>
<p>
- <gl-sprintf :message="$options.instructionText.step1">
- <template #step="{ content }">
- <strong>{{ content }}</strong>
- </template>
- <template #link="{ content }">
- <gl-link :href="$options.connectClusterDocs" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
+ <strong>{{ $options.i18n.instructions.title }}</strong>
</p>
- <div>
- <p>
- <gl-sprintf :message="$options.instructionText.step2">
- <template #step="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </p>
- <div class="gl-display-flex align-items-start">
- <pre :id="modalInfoCopyId" class="gl-w-full" data-testid="enable-review-app-copy-string">
- {{ modalInfoCopyStr }} </pre
- >
- <modal-copy-button
- :title="$options.modalInfo.copyToClipboardText"
- :modal-id="modalId"
- css-classes="border-0"
- :target="`#${modalInfoCopyId}`"
- />
- </div>
+ <div class="gl-mb-6">
+ <ol class="gl-px-6">
+ <li>
+ {{ $options.i18n.instructions.step1 }}
+ <gl-icon
+ ref="informationIcon"
+ name="information-o"
+ class="gl-text-blue-600 gl-hover-cursor-pointer"
+ />
+ <gl-popover
+ :target="() => $refs.informationIcon.$el"
+ :title="$options.i18n.staticSitePopover.title"
+ triggers="hover focus"
+ >
+ {{ $options.i18n.staticSitePopover.body }}
+ </gl-popover>
+ </li>
+ <li>{{ $options.i18n.instructions.step2 }}</li>
+ <li>
+ {{ $options.i18n.instructions.step3 }}
+ <ul class="gl-px-4 gl-py-2">
+ <li>{{ $options.i18n.instructions.step3a }}</li>
+ <li>
+ <gl-sprintf :message="$options.i18n.instructions.step3b">
+ <template #code="{ content }"
+ ><code>{{ content }}</code></template
+ >
+ </gl-sprintf>
+ </li>
+ <li class="gl-list-style-none">
+ <div class="gl-display-flex align-items-start">
+ <pre
+ :id="modalInfoCopyId"
+ class="gl-w-full"
+ data-testid="enable-review-app-copy-string"
+ >{{ modalInfoCopyStr }}</pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyToClipboardText"
+ :modal-id="modalId"
+ css-classes="border-0"
+ :target="`#${modalInfoCopyId}`"
+ />
+ </div>
+ </li>
+ </ul>
+ </li>
+ <li>{{ $options.i18n.instructions.step4 }}</li>
+ </ol>
+ <gl-link :href="$options.configuringReviewAppsPath" target="_blank">
+ {{ $options.i18n.learnMore }}
+ <gl-icon name="external-link" />
+ </gl-link>
+ <gl-link :href="$options.reviewAppsExamplesPath" target="_blank" class="gl-ml-6">
+ {{ $options.i18n.viewMoreExampleProjects }}
+ <gl-icon name="external-link" />
+ </gl-link>
</div>
- <p>
- <gl-sprintf :message="$options.instructionText.step3">
- <template #step="{ content }">
- <strong>{{ content }}</strong>
- </template>
- <template #link="{ content }">
- <gl-link :href="`blob/${defaultBranchName}/.gitlab-ci.yml`" target="_blank">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- <p>
- <gl-sprintf :message="$options.instructionText.step4">
- <template #step="{ content }">
- <strong>{{ content }}</strong>
- </template>
- <template #link="{ content }">
- <gl-link :href="$options.visualReviewsDocs" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue
index b8def676e7d..04a390fbba7 100644
--- a/app/assets/javascripts/environments/components/environment_external_url.vue
+++ b/app/assets/javascripts/environments/components/environment_external_url.vue
@@ -1,6 +1,8 @@
<script>
import { GlTooltipDirective, GlButton } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import { s__, __ } from '~/locale';
+import { isSafeURL } from '~/lib/utils/url_utility';
/**
* Renders the external url link in environments table.
@@ -8,6 +10,7 @@ import { s__ } from '~/locale';
export default {
components: {
GlButton,
+ ModalCopyButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -21,11 +24,19 @@ export default {
i18n: {
title: s__('Environments|Open live environment'),
open: s__('Environments|Open'),
+ copy: __('Copy URL'),
+ copyTitle: s__('Environments|Copy live environment URL'),
+ },
+ computed: {
+ isSafeUrl() {
+ return isSafeURL(this.externalUrl);
+ },
},
};
</script>
<template>
<gl-button
+ v-if="isSafeUrl"
v-gl-tooltip
:title="$options.i18n.title"
:aria-label="$options.i18n.title"
@@ -37,4 +48,7 @@ export default {
>
{{ $options.i18n.open }}
</gl-button>
+ <modal-copy-button v-else :title="$options.i18n.copyTitle" :text="externalUrl">
+ {{ $options.i18n.copy }}
+ </modal-copy-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_folder.vue b/app/assets/javascripts/environments/components/environment_folder.vue
index 881f404340d..2f6c54e4707 100644
--- a/app/assets/javascripts/environments/components/environment_folder.vue
+++ b/app/assets/javascripts/environments/components/environment_folder.vue
@@ -24,6 +24,10 @@ export default {
type: String,
required: true,
},
+ search: {
+ type: String,
+ required: true,
+ },
},
data() {
return { visible: false, interval: undefined };
@@ -32,7 +36,11 @@ export default {
folder: {
query: folderQuery,
variables() {
- return { environment: this.nestedEnvironment.latest, scope: this.scope };
+ return {
+ environment: this.nestedEnvironment.latest,
+ scope: this.scope,
+ search: this.search,
+ };
},
},
interval: {
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index f44182e822b..55e6a891e27 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -1,7 +1,9 @@
<script>
-import { GlBadge, GlPagination, GlTab, GlTabs } from '@gitlab/ui';
+import { GlBadge, GlPagination, GlSearchBoxByType, GlTab, GlTabs } from '@gitlab/ui';
+import { debounce } from 'lodash';
import { s__, __, sprintf } from '~/locale';
import { updateHistory, setUrlParams, queryToObject } from '~/lib/utils/url_utility';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
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';
@@ -31,6 +33,7 @@ export default {
StopEnvironmentModal,
GlBadge,
GlPagination,
+ GlSearchBoxByType,
GlTab,
GlTabs,
},
@@ -41,11 +44,10 @@ export default {
return {
scope: this.scope,
page: this.page ?? 1,
+ search: this.search,
};
},
- pollInterval() {
- return this.interval;
- },
+ pollInterval: 3000,
},
interval: {
query: pollIntervalQuery,
@@ -80,10 +82,11 @@ export default {
next: __('Next'),
prev: __('Prev'),
goto: (page) => sprintf(__('Go to page %{page}'), { page }),
+ searchPlaceholder: s__('Environments|Search by environment name'),
},
modalId: 'enable-review-app-info',
data() {
- const { page = '1', scope } = queryToObject(window.location.search);
+ const { page = '1', search = '', scope } = queryToObject(window.location.search);
return {
interval: undefined,
isReviewAppModalVisible: false,
@@ -97,6 +100,7 @@ export default {
environmentToStop: {},
environmentToChangeCanary: {},
weight: 0,
+ search,
};
},
computed: {
@@ -112,6 +116,9 @@ export default {
hasEnvironments() {
return this.environments.length > 0 || this.folders.length > 0;
},
+ hasSearch() {
+ return Boolean(this.search);
+ },
availableCount() {
return this.environmentApp?.availableCount;
},
@@ -152,11 +159,19 @@ export default {
return this.pageInfo?.perPage;
},
},
+ watch: {
+ interval(val) {
+ this.$apollo.queries.environmentApp.stopPolling();
+ this.$apollo.queries.environmentApp.startPolling(val);
+ },
+ },
mounted() {
window.addEventListener('popstate', this.syncPageFromQueryParams);
+ window.addEventListener('popstate', this.syncSearchFromQueryParams);
},
destroyed() {
window.removeEventListener('popstate', this.syncPageFromQueryParams);
+ window.removeEventListener('popstate', this.syncSearchFromQueryParams);
this.$apollo.queries.environmentApp.stopPolling();
},
methods: {
@@ -173,23 +188,24 @@ export default {
moveToPage(page) {
this.page = page;
updateHistory({
- url: setUrlParams({ page: this.page }),
+ url: setUrlParams({ page: this.page, scope: this.scope, search: this.search }),
title: document.title,
});
- this.resetPolling();
},
+ setSearch: debounce(function setSearch(input) {
+ this.search = input;
+ this.moveToPage(1);
+ }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
syncPageFromQueryParams() {
const { page = '1' } = queryToObject(window.location.search);
this.page = parseInt(page, 10);
},
- resetPolling() {
- this.$apollo.queries.environmentApp.stopPolling();
+ syncSearchFromQueryParams() {
+ const { search = '' } = queryToObject(window.location.search);
+ this.search = search;
+ },
+ refetchEnvironments() {
this.$apollo.queries.environmentApp.refetch();
- this.$nextTick(() => {
- if (this.interval) {
- this.$apollo.queries.environmentApp.startPolling(this.interval);
- }
- });
},
},
ENVIRONMENTS_SCOPE,
@@ -237,12 +253,19 @@ export default {
</template>
</gl-tab>
</gl-tabs>
+ <gl-search-box-by-type
+ class="gl-mb-4"
+ :value="search"
+ :placeholder="$options.i18n.searchPlaceholder"
+ @input="setSearch"
+ />
<template v-if="hasEnvironments">
<environment-folder
v-for="folder in folders"
:key="folder.name"
class="gl-mb-3"
:scope="scope"
+ :search="search"
:nested-environment="folder"
/>
<environment-item
@@ -250,10 +273,15 @@ export default {
:key="environment.name"
class="gl-mb-3 gl-border-gray-100 gl-border-1 gl-border-b-solid"
:environment="environment.latest"
- @change="resetPolling"
+ @change="refetchEnvironments"
/>
</template>
- <empty-state v-else :help-path="helpPagePath" :scope="scope" />
+ <empty-state
+ v-else-if="!$apollo.queries.environmentApp.loading"
+ :help-path="helpPagePath"
+ :scope="scope"
+ :has-term="hasSearch"
+ />
<gl-pagination
align="center"
:total-items="totalItems"
diff --git a/app/assets/javascripts/environments/components/environments_detail_header.vue b/app/assets/javascripts/environments/components/environments_detail_header.vue
index bd67908a6b4..bb2f053b3fc 100644
--- a/app/assets/javascripts/environments/components/environments_detail_header.vue
+++ b/app/assets/javascripts/environments/components/environments_detail_header.vue
@@ -4,6 +4,8 @@ import csrf from '~/lib/utils/csrf';
import { __, s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import { isSafeURL } from '~/lib/utils/url_utility';
import DeleteEnvironmentModal from './delete_environment_modal.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
@@ -16,6 +18,7 @@ export default {
TimeAgo,
DeleteEnvironmentModal,
StopEnvironmentModal,
+ ModalCopyButton,
},
directives: {
GlModalDirective,
@@ -73,6 +76,8 @@ export default {
deleteButtonText: s__('Environments|Delete'),
externalButtonTitle: s__('Environments|Open live environment'),
externalButtonText: __('View deployment'),
+ copyUrlText: __('Copy URL'),
+ copyUrlTitle: s__('Environments|Copy live environment URL'),
cancelAutoStopButtonTitle: __('Prevent environment from auto-stopping'),
},
computed: {
@@ -82,6 +87,9 @@ export default {
shouldShowExternalUrlButton() {
return Boolean(this.environment.externalUrl);
},
+ isSafeUrl() {
+ return isSafeURL(this.environment.externalUrl);
+ },
shouldShowStopButton() {
return this.canStopEnvironment && this.environment.isAvailable;
},
@@ -123,16 +131,25 @@ export default {
:href="terminalPath"
icon="terminal"
/>
- <gl-button
- v-if="shouldShowExternalUrlButton"
- v-gl-tooltip.hover
- data-testid="external-url-button"
- :title="$options.i18n.externalButtonTitle"
- :href="environment.externalUrl"
- icon="external-link"
- target="_blank"
- >{{ $options.i18n.externalButtonText }}</gl-button
- >
+ <template v-if="shouldShowExternalUrlButton">
+ <gl-button
+ v-if="isSafeUrl"
+ v-gl-tooltip.hover
+ data-testid="external-url-button"
+ :title="$options.i18n.externalButtonTitle"
+ :href="environment.externalUrl"
+ icon="external-link"
+ target="_blank"
+ >{{ $options.i18n.externalButtonText }}</gl-button
+ >
+ <modal-copy-button
+ v-else
+ :title="$options.i18n.copyUrlTitle"
+ :text="environment.externalUrl"
+ >
+ {{ $options.i18n.copyUrlText }}
+ </modal-copy-button>
+ </template>
<gl-button
v-if="shouldShowExternalUrlButton"
v-gl-tooltip.hover
diff --git a/app/assets/javascripts/environments/components/new_environment.vue b/app/assets/javascripts/environments/components/new_environment.vue
index 14da2668417..bb4d6ab3428 100644
--- a/app/assets/javascripts/environments/components/new_environment.vue
+++ b/app/assets/javascripts/environments/components/new_environment.vue
@@ -1,5 +1,5 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import EnvironmentForm from './environment_form.vue';
@@ -32,7 +32,7 @@ export default {
.then(({ data: { path } }) => visitUrl(path))
.catch((error) => {
const message = error.response.data.message[0];
- createFlash({ message });
+ createAlert({ message });
this.loading = false;
});
},
diff --git a/app/assets/javascripts/environments/constants.js b/app/assets/javascripts/environments/constants.js
index 942491039d6..c4d02da9d21 100644
--- a/app/assets/javascripts/environments/constants.js
+++ b/app/assets/javascripts/environments/constants.js
@@ -1,4 +1,4 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
// These statuses are based on how the backend defines pod phases here
// lib/gitlab/kubernetes/pod.rb
@@ -48,3 +48,32 @@ export const ENVIRONMENT_COUNT_BY_SCOPE = {
[ENVIRONMENTS_SCOPE.AVAILABLE]: 'availableCount',
[ENVIRONMENTS_SCOPE.STOPPED]: 'stoppedCount',
};
+
+export const REVIEW_APP_MODAL_I18N = {
+ title: s__('ReviewApp|Enable Review App'),
+ intro: s__(
+ 'EnableReviewApp|Review apps are dynamic environments that you can use to provide a live preview of changes made in a feature branch.',
+ ),
+ instructions: {
+ title: s__('EnableReviewApp|To configure a dynamic review app, you must:'),
+ step1: s__(
+ 'EnableReviewApp|Have access to infrastructure that can host and deploy the review apps.',
+ ),
+ step2: s__('EnableReviewApp|Install and configure a runner to do the deployment.'),
+ step3: s__('EnableReviewApp|Add a job in your CI/CD configuration that:'),
+ step3a: s__('EnableReviewApp|Only runs for feature branches or merge requests.'),
+ step3b: s__(
+ 'EnableReviewApp|Uses a predefined CI/CD variable like %{codeStart}$(CI_COMMIT_REF_SLUG)%{codeEnd} to dynamically create the review app environments. For example, for a configuration using merge request pipelines:',
+ ),
+ step4: s__('EnableReviewApp|Recommended: Set up a job that manually stops the Review Apps.'),
+ },
+ staticSitePopover: {
+ title: s__('EnableReviewApp|Using a static site?'),
+ body: s__(
+ 'EnableReviewApp|Make sure your project has an environment configured with the target URL set to your website URL. If not, create a new one before continuing.',
+ ),
+ },
+ learnMore: __('Learn more'),
+ viewMoreExampleProjects: s__('EnableReviewApp|View more example projects'),
+ copyToClipboardText: s__('EnableReviewApp|Copy snippet'),
+};
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
index c3ab9cf7fca..1a572208a1c 100644
--- a/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
+++ b/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
@@ -1,5 +1,5 @@
-query getEnvironmentApp($page: Int, $scope: String) {
- environmentApp(page: $page, scope: $scope) @client {
+query getEnvironmentApp($page: Int, $scope: String, $search: String) {
+ environmentApp(page: $page, scope: $scope, search: $search) @client {
availableCount
stoppedCount
environments
diff --git a/app/assets/javascripts/environments/graphql/queries/folder.query.graphql b/app/assets/javascripts/environments/graphql/queries/folder.query.graphql
index e8c145ee916..c662acb8f93 100644
--- a/app/assets/javascripts/environments/graphql/queries/folder.query.graphql
+++ b/app/assets/javascripts/environments/graphql/queries/folder.query.graphql
@@ -1,5 +1,5 @@
-query getEnvironmentFolder($environment: NestedLocalEnvironment, $scope: String) {
- folder(environment: $environment, scope: $scope) @client {
+query getEnvironmentFolder($environment: NestedLocalEnvironment, $scope: String, $search: String) {
+ folder(environment: $environment, scope: $scope, search: $search) @client {
availableCount
environments
stoppedCount
diff --git a/app/assets/javascripts/environments/graphql/resolvers.js b/app/assets/javascripts/environments/graphql/resolvers.js
index 722bb78bcf9..afd56d0cf0d 100644
--- a/app/assets/javascripts/environments/graphql/resolvers.js
+++ b/app/assets/javascripts/environments/graphql/resolvers.js
@@ -30,8 +30,8 @@ const mapEnvironment = (env) => ({
export const resolvers = (endpoint) => ({
Query: {
- environmentApp(_context, { page, scope }, { cache }) {
- return axios.get(endpoint, { params: { nested: true, page, scope } }).then((res) => {
+ environmentApp(_context, { page, scope, search }, { cache }) {
+ return axios.get(endpoint, { params: { nested: true, page, scope, search } }).then((res) => {
const headers = normalizeHeaders(res.headers);
const interval = headers['POLL-INTERVAL'];
const pageInfo = { ...parseIntPagination(headers), __typename: 'LocalPageInfo' };
@@ -59,8 +59,8 @@ export const resolvers = (endpoint) => ({
};
});
},
- folder(_, { environment: { folderPath }, scope }) {
- return axios.get(folderPath, { params: { scope, per_page: 3 } }).then((res) => ({
+ folder(_, { environment: { folderPath }, scope, search }) {
+ return axios.get(folderPath, { params: { scope, search, per_page: 3 } }).then((res) => ({
availableCount: res.data.available_count,
environments: res.data.environments.map(mapEnvironment),
stoppedCount: res.data.stopped_count,
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 8957a3074ed..5e936ad8c96 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -3,7 +3,7 @@
*/
import { isEqual, isFunction, omitBy } from 'lodash';
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Poll from '~/lib/utils/poll';
import { getParameterByName } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
@@ -94,7 +94,7 @@ export default {
errorCallback() {
this.isLoading = false;
- createFlash({
+ createAlert({
message: s__('Environments|An error occurred while fetching the environments.'),
});
},
@@ -123,7 +123,7 @@ export default {
})
.catch((err) => {
this.isLoading = false;
- createFlash({
+ createAlert({
message: isFunction(errorMessage) ? errorMessage(err.response.data) : errorMessage,
});
});
@@ -179,7 +179,7 @@ export default {
window.location.href = url.join('/');
})
.catch(() => {
- createFlash({
+ createAlert({
message: errorMessage,
});
});
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index a602c92a840..b02c3cd2cba 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -13,7 +13,7 @@ import {
GlIcon,
} from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_WARNING } from '~/flash';
import { __, sprintf, n__ } from '~/locale';
import Tracking from '~/tracking';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -89,7 +89,7 @@ export default {
pollInterval: 2000,
update: (data) => data.project.sentryErrors.detailedError,
error: () =>
- createFlash({
+ createAlert({
message: __('Failed to load error details from Sentry.'),
}),
result(res) {
@@ -234,9 +234,9 @@ export default {
if (Date.now() > this.errorPollTimeout) {
this.$apollo.queries.error.stopPolling();
this.errorLoading = false;
- createFlash({
+ createAlert({
message: __('Could not connect to Sentry. Refresh the page to try again.'),
- type: 'warning',
+ variant: VARIANT_WARNING,
});
}
},
diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js
index fbfcd6ce2df..603f8611005 100644
--- a/app/assets/javascripts/error_tracking/store/actions.js
+++ b/app/assets/javascripts/error_tracking/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import service from '../services';
@@ -18,7 +18,7 @@ export const updateStatus = ({ commit }, { endpoint, redirectUrl, status }) =>
return resp.data.result;
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Failed to update issue status'),
}),
);
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index 09fa650f64b..1409399940a 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import service from '../../services';
@@ -26,7 +26,7 @@ export function startPollingStacktrace({ commit }, endpoint) {
},
errorCallback: () => {
commit(types.SET_LOADING_STACKTRACE, false);
- createFlash({
+ createAlert({
message: __('Failed to load stacktrace.'),
});
},
diff --git a/app/assets/javascripts/error_tracking/store/list/actions.js b/app/assets/javascripts/error_tracking/store/list/actions.js
index 418056314f6..f633711add3 100644
--- a/app/assets/javascripts/error_tracking/store/list/actions.js
+++ b/app/assets/javascripts/error_tracking/store/list/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import Service from '../../services';
@@ -33,7 +33,7 @@ export function startPolling({ state, commit, dispatch }) {
},
errorCallback: () => {
commit(types.SET_LOADING, false);
- createFlash({
+ createAlert({
message: __('Failed to load errors from Sentry.'),
});
},
diff --git a/app/assets/javascripts/error_tracking_settings/components/app.vue b/app/assets/javascripts/error_tracking_settings/components/app.vue
index 70fb1fa9cd7..3bc91a2adbf 100644
--- a/app/assets/javascripts/error_tracking_settings/components/app.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/app.vue
@@ -190,7 +190,7 @@ export default {
<gl-form-radio name="error-tracking-integrated" :value="true">
{{ __('GitLab') }}
<template #help>
- {{ __('Uses GitLab as a lightweight alternative to Sentry.') }}
+ {{ __('Uses GitLab as an alternative to Sentry.') }}
</template>
</gl-form-radio>
</gl-form-radio-group>
diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js
index 972ad58c617..4d6fe767f3a 100644
--- a/app/assets/javascripts/error_tracking_settings/store/actions.js
+++ b/app/assets/javascripts/error_tracking_settings/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -46,7 +46,7 @@ export const requestSettings = ({ commit }) => {
export const receiveSettingsError = ({ commit }, { response = {} }) => {
const message = response.data && response.data.message ? response.data.message : '';
- createFlash({
+ createAlert({
message: `${__('There was an error saving your changes.')} ${message}`,
});
commit(types.UPDATE_SETTINGS_LOADING, false);
diff --git a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
index 70b60b4b113..ce5f7915dbf 100644
--- a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlSearchBoxByType } from '@gitlab/ui';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -87,7 +87,7 @@ export default {
.catch(() => {
this.isLoading = false;
this.closeSuggestions();
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again.'),
});
});
diff --git a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
index 98982920121..89400bc4742 100644
--- a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
@@ -8,7 +8,7 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
@@ -52,7 +52,7 @@ export default {
this.results = data || [];
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again.'),
});
})
diff --git a/app/assets/javascripts/feature_flags/store/edit/actions.js b/app/assets/javascripts/feature_flags/store/edit/actions.js
index 8656479190a..97c22781ac5 100644
--- a/app/assets/javascripts/feature_flags/store/edit/actions.js
+++ b/app/assets/javascripts/feature_flags/store/edit/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -49,7 +49,7 @@ export const receiveFeatureFlagSuccess = ({ commit }, response) =>
commit(types.RECEIVE_FEATURE_FLAG_SUCCESS, response);
export const receiveFeatureFlagError = ({ commit }) => {
commit(types.RECEIVE_FEATURE_FLAG_ERROR);
- createFlash({
+ createAlert({
message: __('Something went wrong on our end. Please try again!'),
});
};
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
index b26a96499ba..a9542a9667e 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -10,7 +10,7 @@ export function dismiss(endpoint, highlightId) {
feature_name: highlightId,
})
.catch(() =>
- createFlash({
+ createAlert({
message: __(
'An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.',
),
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
index 9726b2164b7..23591fc0667 100644
--- a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import AjaxFilter from './droplab/plugins/ajax_filter';
import DropdownUtils from './dropdown_utils';
@@ -27,7 +27,7 @@ export default class DropdownAjaxFilter extends FilteredSearchDropdown {
searchValueFunction: this.getSearchInput.bind(this),
loadingTemplate: this.loadingTemplate,
onError() {
- createFlash({
+ createAlert({
message: __('An error occurred fetching the dropdown data.'),
});
},
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index aeea66bf51c..8c50c1860ec 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import Ajax from './droplab/plugins/ajax';
import Filter from './droplab/plugins/filter';
@@ -14,7 +14,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
method: 'setData',
loadingTemplate: this.loadingTemplate,
onError() {
- createFlash({
+ createAlert({
message: __('An error occurred fetching the dropdown data.'),
});
},
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index ddc3c06a9d1..ab95986dc62 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import Ajax from './droplab/plugins/ajax';
import Filter from './droplab/plugins/filter';
@@ -17,7 +17,7 @@ export default class DropdownNonUser extends FilteredSearchDropdown {
loadingTemplate: this.loadingTemplate,
preprocessing,
onError() {
- createFlash({
+ createAlert({
message: __('An error occurred fetching the dropdown data.'),
});
},
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index ac2cf27e873..bc0f5398b4c 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -1,7 +1,7 @@
import { last } from 'lodash';
import recentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import {
ENTER_KEY_CODE,
BACKSPACE_KEY_CODE,
@@ -91,7 +91,7 @@ export default class FilteredSearchManager {
.fetch()
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
- createFlash({
+ createAlert({
message: __('An error occurred while parsing recent searches'),
});
// Gracefully fail to empty array
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index 0d144398531..1ad2006d689 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -4,7 +4,7 @@ import * as Emoji from '~/emoji';
import FilteredSearchContainer from '~/filtered_search/container';
import DropdownUtils from '~/filtered_search/dropdown_utils';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import AjaxCache from '~/lib/utils/ajax_cache';
import UsersCache from '~/lib/utils/users_cache';
import { __ } from '~/locale';
@@ -85,7 +85,7 @@ export default class VisualTokenValue {
);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while fetching label colors.'),
}),
);
@@ -111,7 +111,7 @@ export default class VisualTokenValue {
VisualTokenValue.replaceEpicTitle(tokenValueContainer, matchingEpic.title, matchingEpic.id);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while adding formatted title for epic'),
}),
);
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index edf83a33812..5665231e613 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -158,7 +158,7 @@ const createAlert = function createAlert({
onDismiss();
}
this.$destroy();
- this.$el.parentNode.removeChild(this.$el);
+ this.$el.parentNode?.removeChild(this.$el);
},
},
render(h) {
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index d376c9f76ba..0a4733de65f 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { queryToObject } from '~/lib/utils/url_utility';
import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
@@ -19,7 +19,7 @@ export default class GpgBadges {
badges.children().attr('aria-label', __('Loading'));
const displayError = () =>
- createFlash({
+ createAlert({
message: __('An error occurred while loading commit signatures'),
});
diff --git a/app/assets/javascripts/grafana_integration/store/actions.js b/app/assets/javascripts/grafana_integration/store/actions.js
index 25347ad6433..db2fd3cc256 100644
--- a/app/assets/javascripts/grafana_integration/store/actions.js
+++ b/app/assets/javascripts/grafana_integration/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -38,7 +38,7 @@ export const receiveGrafanaIntegrationUpdateError = (_, error) => {
const { response } = error;
const message = response.data && response.data.message ? response.data.message : '';
- createFlash({
+ createAlert({
message: `${__('There was an error saving your changes.')} ${message}`,
});
};
diff --git a/app/assets/javascripts/graphql_shared/issuable_client.js b/app/assets/javascripts/graphql_shared/issuable_client.js
index e86103c332b..3b737dfff33 100644
--- a/app/assets/javascripts/graphql_shared/issuable_client.js
+++ b/app/assets/javascripts/graphql_shared/issuable_client.js
@@ -4,14 +4,13 @@ import { concatPagination } from '@apollo/client/utilities';
import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.graphql';
import createDefaultClient from '~/lib/graphql';
import typeDefs from '~/work_items/graphql/typedefs.graphql';
-import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
-import { WIDGET_TYPE_LABELS } from '~/work_items/constants';
+import { WIDGET_TYPE_MILESTONE } from '~/work_items/constants';
export const temporaryConfig = {
typeDefs,
cacheConfig: {
possibleTypes: {
- LocalWorkItemWidget: ['LocalWorkItemLabels'],
+ LocalWorkItemWidget: ['LocalWorkItemMilestone'],
},
typePolicies: {
Project: {
@@ -28,18 +27,32 @@ export const temporaryConfig = {
return (
widgets || [
{
- __typename: 'LocalWorkItemLabels',
- type: WIDGET_TYPE_LABELS,
- allowScopedLabels: true,
- nodes: [],
+ __typename: 'LocalWorkItemMilestone',
+ type: WIDGET_TYPE_MILESTONE,
+ nodes: [
+ {
+ dueDate: null,
+ expired: false,
+ id: 'gid://gitlab/Milestone/30',
+ title: 'v4.0',
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ __typename: 'Milestone',
+ },
+ ],
},
]
);
},
},
widgets: {
- merge(_, incoming) {
- return incoming;
+ merge(existing = [], incoming) {
+ if (existing.length === 0) {
+ return incoming;
+ }
+ return existing.map((existingWidget) => {
+ const incomingWidget = incoming.find((w) => w.type === existingWidget.type);
+ return incomingWidget || existingWidget;
+ });
},
},
},
@@ -62,27 +75,6 @@ export const resolvers = {
});
cache.writeQuery({ query: getIssueStateQuery, data });
},
- localUpdateWorkItem(_, { input }, { cache }) {
- const sourceData = cache.readQuery({
- query: workItemQuery,
- variables: { id: input.id },
- });
-
- const data = produce(sourceData, (draftData) => {
- if (input.labels) {
- const labelsWidget = draftData.workItem.mockWidgets.find(
- (widget) => widget.type === WIDGET_TYPE_LABELS,
- );
- labelsWidget.nodes = [...input.labels];
- }
- });
-
- cache.writeQuery({
- query: workItemQuery,
- variables: { id: input.id },
- data,
- });
- },
},
};
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index c6bd9e563c0..545c150e536 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -144,7 +144,7 @@
"WorkItemWidgetIteration",
"WorkItemWidgetLabels",
"WorkItemWidgetStartAndDueDate",
- "WorkItemWidgetVerificationStatus",
+ "WorkItemWidgetStatus",
"WorkItemWidgetWeight"
]
}
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 f64c4276deb..c05b4a5950c 100644
--- a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
@@ -9,6 +9,7 @@ query projectUsersSearch($search: String!, $fullPath: ID!, $after: String, $firs
relations: [DIRECT, INHERITED, INVITED_GROUPS]
first: $first
after: $after
+ sort: USER_FULL_NAME_ASC
) {
pageInfo {
hasNextPage
diff --git a/app/assets/javascripts/graphql_shared/queries/users_search_with_mr_permissions.graphql b/app/assets/javascripts/graphql_shared/queries/users_search_with_mr_permissions.graphql
index 2bd016feb19..5a589b094de 100644
--- a/app/assets/javascripts/graphql_shared/queries/users_search_with_mr_permissions.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/users_search_with_mr_permissions.graphql
@@ -8,7 +8,11 @@ query projectUsersSearchWithMRPermissions(
) {
workspace: project(fullPath: $fullPath) {
id
- users: projectMembers(search: $search, relations: [DIRECT, INHERITED, INVITED_GROUPS]) {
+ users: projectMembers(
+ search: $search
+ relations: [DIRECT, INHERITED, INVITED_GROUPS]
+ sort: USER_FULL_NAME_ASC
+ ) {
nodes {
id
mergeRequestInteraction(id: $mergeRequestId) {
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index 49e7dd28ff6..cc70d832edc 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -1,6 +1,6 @@
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { getGroupPathAvailability } from '~/rest_api';
import axios from '~/lib/utils/axios_utils';
@@ -77,7 +77,7 @@ export default class Group {
element.value = suggestedSlug;
});
} else if (exists && !suggests.length) {
- createFlash({
+ createAlert({
message: __('Unable to suggest a path. Please refresh and try again.'),
});
}
@@ -87,7 +87,7 @@ export default class Group {
return;
}
- createFlash({
+ createAlert({
message: __('An error occurred while checking group path. Please refresh and try again.'),
});
});
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 0bd7371d39b..15f5a3518a5 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon, GlModal } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { mergeUrlParams, getParameterByName } from '~/lib/utils/url_utility';
import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { __, s__, sprintf } from '~/locale';
@@ -51,7 +51,6 @@ export default {
isModalVisible: false,
isLoading: true,
isSearchEmpty: false,
- searchEmptyMessage: '',
targetGroup: null,
targetParentGroup: null,
showEmptyState: false,
@@ -88,15 +87,12 @@ export default {
},
},
created() {
- this.searchEmptyMessage = this.hideProjects
- ? COMMON_STR.GROUP_SEARCH_EMPTY
- : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY;
-
eventHub.$on(`${this.action}fetchPage`, this.fetchPage);
eventHub.$on(`${this.action}toggleChildren`, this.toggleChildren);
eventHub.$on(`${this.action}showLeaveGroupModal`, this.showLeaveGroupModal);
eventHub.$on(`${this.action}updatePagination`, this.updatePagination);
eventHub.$on(`${this.action}updateGroups`, this.updateGroups);
+ eventHub.$on(`${this.action}fetchFilteredAndSortedGroups`, this.fetchFilteredAndSortedGroups);
},
mounted() {
this.fetchAllGroups();
@@ -111,6 +107,7 @@ export default {
eventHub.$off(`${this.action}showLeaveGroupModal`, this.showLeaveGroupModal);
eventHub.$off(`${this.action}updatePagination`, this.updatePagination);
eventHub.$off(`${this.action}updateGroups`, this.updateGroups);
+ eventHub.$off(`${this.action}fetchFilteredAndSortedGroups`, this.fetchFilteredAndSortedGroups);
},
methods: {
hideModal() {
@@ -132,7 +129,7 @@ export default {
this.isLoading = false;
window.scrollTo({ top: 0, behavior: 'smooth' });
- createFlash({ message: COMMON_STR.FAILURE });
+ createAlert({ message: COMMON_STR.FAILURE });
});
},
fetchAllGroups() {
@@ -153,6 +150,18 @@ export default {
this.updateGroups(res, Boolean(this.filterGroupsBy));
});
},
+ fetchFilteredAndSortedGroups({ filterGroupsBy, sortBy }) {
+ this.isLoading = true;
+
+ return this.fetchGroups({
+ filterGroupsBy,
+ sortBy,
+ updatePagination: true,
+ }).then((res) => {
+ this.isLoading = false;
+ this.updateGroups(res, Boolean(filterGroupsBy));
+ });
+ },
fetchPage({ page, filterGroupsBy, sortBy, archived }) {
this.isLoading = true;
@@ -218,7 +227,7 @@ export default {
if (err.status === 403) {
message = COMMON_STR.LEAVE_FORBIDDEN;
}
- createFlash({ message });
+ createAlert({ message });
this.targetGroup.isBeingRemoved = false;
});
},
@@ -245,7 +254,7 @@ export default {
const hasGroups = groups && groups.length > 0;
if (this.renderEmptyState) {
- this.isSearchEmpty = this.filterGroupsBy !== null && !hasGroups;
+ this.isSearchEmpty = fromSearch && !hasGroups;
} else {
this.isSearchEmpty = !hasGroups;
}
@@ -280,7 +289,6 @@ export default {
v-else
:groups="groups"
:search-empty="isSearchEmpty"
- :search-empty-message="searchEmptyMessage"
:page-info="pageInfo"
:action="action"
/>
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
index 3a05c308a2a..43aa0753082 100644
--- a/app/assets/javascripts/groups/components/groups.vue
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -1,11 +1,18 @@
<script>
+import { GlEmptyState } from '@gitlab/ui';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import { getParameterByName } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import eventHub from '../event_hub';
export default {
+ i18n: {
+ emptyStateTitle: __('No results found'),
+ emptyStateDescription: __('Edit your search and try again'),
+ },
components: {
PaginationLinks,
+ GlEmptyState,
},
props: {
groups: {
@@ -20,10 +27,6 @@ export default {
type: Boolean,
required: true,
},
- searchEmptyMessage: {
- type: String,
- required: true,
- },
action: {
type: String,
required: false,
@@ -43,12 +46,11 @@ export default {
<template>
<div class="groups-list-tree-container" data-qa-selector="groups_list_tree_container">
- <div
+ <gl-empty-state
v-if="searchEmpty"
- class="has-no-search-results gl-font-style-italic gl-text-center gl-text-gray-600 gl-p-5"
- >
- {{ searchEmptyMessage }}
- </div>
+ :title="$options.i18n.emptyStateTitle"
+ :description="$options.i18n.emptyStateDescription"
+ />
<template v-else>
<group-folder :groups="groups" :action="action" />
<pagination-links
diff --git a/app/assets/javascripts/groups/components/new_top_level_group_alert.vue b/app/assets/javascripts/groups/components/new_top_level_group_alert.vue
new file mode 100644
index 00000000000..c6af6cdb59f
--- /dev/null
+++ b/app/assets/javascripts/groups/components/new_top_level_group_alert.vue
@@ -0,0 +1,40 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export default {
+ name: 'NewTopLevelGroupAlert',
+ components: {
+ GlAlert,
+ UserCalloutDismisser,
+ },
+ i18n: {
+ titleText: s__("Groups|You're creating a new top-level group"),
+ bodyText: s__(
+ 'Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?',
+ ),
+ primaryBtnText: s__('Groups|Learn more about subgroups'),
+ },
+ subgroupsDocsPath: helpPagePath('user/group/subgroups/index'),
+};
+</script>
+
+<template>
+ <user-callout-dismisser feature-name="new_top_level_group_alert">
+ <template #default="{ dismiss, shouldShowCallout }">
+ <gl-alert
+ v-if="shouldShowCallout"
+ ref="newTopLevelAlert"
+ data-testid="new-top-level-alert"
+ :title="$options.i18n.titleText"
+ :primary-button-text="$options.i18n.primaryBtnText"
+ :primary-button-link="$options.subgroupsDocsPath"
+ @dismiss="dismiss"
+ >
+ {{ $options.i18n.bodyText }}
+ </gl-alert>
+ </template>
+ </user-callout-dismisser>
+</template>
diff --git a/app/assets/javascripts/groups/components/overview_tabs.vue b/app/assets/javascripts/groups/components/overview_tabs.vue
index 325e42af0f8..d0c5846ac88 100644
--- a/app/assets/javascripts/groups/components/overview_tabs.vue
+++ b/app/assets/javascripts/groups/components/overview_tabs.vue
@@ -1,58 +1,77 @@
<script>
-import { GlTabs, GlTab } from '@gitlab/ui';
-import { isString } from 'lodash';
+import { GlTabs, GlTab, GlSearchBoxByType, GlSorting, GlSortingItem } from '@gitlab/ui';
+import { isString, debounce } from 'lodash';
import { __ } from '~/locale';
+import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
import GroupsStore from '../store/groups_store';
import GroupsService from '../service/groups_service';
import {
ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
ACTIVE_TAB_SHARED,
ACTIVE_TAB_ARCHIVED,
+ OVERVIEW_TABS_SORTING_ITEMS,
} from '../constants';
+import eventHub from '../event_hub';
import GroupsApp from './app.vue';
+const [SORTING_ITEM_NAME] = OVERVIEW_TABS_SORTING_ITEMS;
+
export default {
- components: { GlTabs, GlTab, GroupsApp },
- inject: ['endpoints'],
+ components: { GlTabs, GlTab, GroupsApp, GlSearchBoxByType, GlSorting, GlSortingItem },
+ inject: ['endpoints', 'initialSort'],
data() {
+ const tabs = [
+ {
+ title: this.$options.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
+ key: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
+ renderEmptyState: true,
+ lazy: this.$route.name !== ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
+ service: new GroupsService(this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
+ store: new GroupsStore({ showSchemaMarkup: true }),
+ },
+ {
+ title: this.$options.i18n[ACTIVE_TAB_SHARED],
+ key: ACTIVE_TAB_SHARED,
+ renderEmptyState: false,
+ lazy: this.$route.name !== ACTIVE_TAB_SHARED,
+ service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED]),
+ store: new GroupsStore(),
+ },
+ {
+ title: this.$options.i18n[ACTIVE_TAB_ARCHIVED],
+ key: ACTIVE_TAB_ARCHIVED,
+ renderEmptyState: false,
+ lazy: this.$route.name !== ACTIVE_TAB_ARCHIVED,
+ service: new GroupsService(this.endpoints[ACTIVE_TAB_ARCHIVED]),
+ store: new GroupsStore(),
+ },
+ ];
return {
- tabs: [
- {
- title: this.$options.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
- key: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
- renderEmptyState: true,
- lazy: false,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
- store: new GroupsStore({ showSchemaMarkup: true }),
- },
- {
- title: this.$options.i18n[ACTIVE_TAB_SHARED],
- key: ACTIVE_TAB_SHARED,
- renderEmptyState: false,
- lazy: true,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED]),
- store: new GroupsStore(),
- },
- {
- title: this.$options.i18n[ACTIVE_TAB_ARCHIVED],
- key: ACTIVE_TAB_ARCHIVED,
- renderEmptyState: false,
- lazy: true,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_ARCHIVED]),
- store: new GroupsStore(),
- },
- ],
- activeTabIndex: 0,
+ tabs,
+ activeTabIndex: tabs.findIndex((tab) => tab.key === this.$route.name),
+ sort: SORTING_ITEM_NAME,
+ isAscending: true,
+ search: '',
};
},
+ computed: {
+ activeTab() {
+ return this.tabs[this.activeTabIndex];
+ },
+ sortQueryStringValue() {
+ return this.isAscending ? this.sort.asc : this.sort.desc;
+ },
+ },
mounted() {
- const activeTabIndex = this.tabs.findIndex((tab) => tab.key === this.$route.name);
-
- if (activeTabIndex === -1) {
- return;
- }
+ this.search = this.$route.query?.filter || '';
- this.activeTabIndex = activeTabIndex;
+ const sortQueryStringValue = this.$route.query?.sort || this.initialSort;
+ const sort =
+ OVERVIEW_TABS_SORTING_ITEMS.find((sortOption) =>
+ [sortOption.asc, sortOption.desc].includes(sortQueryStringValue),
+ ) || SORTING_ITEM_NAME;
+ this.sort = sort;
+ this.isAscending = sort.asc === sortQueryStringValue;
},
methods: {
handleTabInput(tabIndex) {
@@ -72,14 +91,64 @@ export default {
? this.$route.params.group.split('/')
: this.$route.params.group;
- this.$router.push({ name: tab.key, params: { group: groupParam } });
+ this.$router.push({ name: tab.key, params: { group: groupParam }, query: this.$route.query });
+ },
+ handleSearchOrSortChange() {
+ // Update query string
+ const query = {};
+ if (this.sortQueryStringValue !== this.initialSort) {
+ query.sort = this.isAscending ? this.sort.asc : this.sort.desc;
+ }
+ if (this.search) {
+ query.filter = this.search;
+ }
+ this.$router.push({ query });
+
+ // Reset `lazy` prop so that groups/projects are fetched with updated `sort` and `filter` params when switching tabs
+ this.tabs.forEach((tab, index) => {
+ if (index === this.activeTabIndex) {
+ return;
+ }
+ // eslint-disable-next-line no-param-reassign
+ tab.lazy = true;
+ });
+
+ // Update data
+ eventHub.$emit(`${this.activeTab.key}fetchFilteredAndSortedGroups`, {
+ filterGroupsBy: this.search,
+ sortBy: this.sortQueryStringValue,
+ });
+ },
+ handleSortDirectionChange() {
+ this.isAscending = !this.isAscending;
+
+ this.handleSearchOrSortChange();
+ },
+ handleSortingItemClick(sortingItem) {
+ if (sortingItem === this.sort) {
+ return;
+ }
+
+ this.sort = sortingItem;
+
+ this.handleSearchOrSortChange();
+ },
+ handleSearchInput(value) {
+ this.search = value;
+
+ this.debouncedSearch();
},
+ debouncedSearch: debounce(async function debouncedSearch() {
+ this.handleSearchOrSortChange();
+ }, DEBOUNCE_DELAY),
},
i18n: {
[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]: __('Subgroups and projects'),
[ACTIVE_TAB_SHARED]: __('Shared projects'),
[ACTIVE_TAB_ARCHIVED]: __('Archived projects'),
+ searchPlaceholder: __('Search'),
},
+ OVERVIEW_TABS_SORTING_ITEMS,
};
</script>
@@ -99,5 +168,37 @@ export default {
:render-empty-state="renderEmptyState"
/>
</gl-tab>
+ <template #tabs-end>
+ <li class="gl-flex-grow-1 gl-align-self-center gl-w-full gl-lg-w-auto gl-py-2">
+ <div class="gl-lg-display-flex gl-justify-content-end gl-mx-n2 gl-my-n2">
+ <div class="gl-p-2 gl-lg-form-input-md gl-w-full">
+ <gl-search-box-by-type
+ :value="search"
+ :placeholder="$options.i18n.searchPlaceholder"
+ data-qa-selector="groups_filter_field"
+ @input="handleSearchInput"
+ />
+ </div>
+ <div class="gl-p-2 gl-w-full gl-lg-w-auto">
+ <gl-sorting
+ class="gl-w-full"
+ dropdown-class="gl-w-full"
+ data-testid="group_sort_by_dropdown"
+ :text="sort.label"
+ :is-ascending="isAscending"
+ @sortDirectionChange="handleSortDirectionChange"
+ >
+ <gl-sorting-item
+ v-for="sortingItem in $options.OVERVIEW_TABS_SORTING_ITEMS"
+ :key="sortingItem.label"
+ :active="sortingItem === sort"
+ @click="handleSortingItemClick(sortingItem)"
+ >{{ sortingItem.label }}</gl-sorting-item
+ >
+ </gl-sorting>
+ </div>
+ </div>
+ </li>
+ </template>
</gl-tabs>
</template>
diff --git a/app/assets/javascripts/groups/components/transfer_group_form.vue b/app/assets/javascripts/groups/components/transfer_group_form.vue
index 7e7282a27b0..e28459811d7 100644
--- a/app/assets/javascripts/groups/components/transfer_group_form.vue
+++ b/app/assets/javascripts/groups/components/transfer_group_form.vue
@@ -2,7 +2,7 @@
import { GlFormGroup } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
-import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select_deprecated.vue';
export const i18n = {
confirmationMessage: __(
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index 223c2975c11..6fb12cd6270 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -24,8 +24,6 @@ export const COMMON_STR = {
EDIT_BTN_TITLE: s__('GroupsTree|Edit'),
REMOVE_BTN_TITLE: s__('GroupsTree|Delete'),
OPTIONS_DROPDOWN_TITLE: s__('GroupsTree|Options'),
- GROUP_SEARCH_EMPTY: s__('GroupsTree|No groups matched your search'),
- GROUP_PROJECT_SEARCH_EMPTY: s__('GroupsTree|No groups or projects matched your search'),
};
export const ITEM_TYPE = {
@@ -62,3 +60,26 @@ export const VISIBILITY_TYPE_ICON = {
[VISIBILITY_LEVEL_INTERNAL_STRING]: 'shield',
[VISIBILITY_LEVEL_PRIVATE_STRING]: 'lock',
};
+
+export const OVERVIEW_TABS_SORTING_ITEMS = [
+ {
+ label: __('Name'),
+ asc: 'name_asc',
+ desc: 'name_desc',
+ },
+ {
+ label: __('Created'),
+ asc: 'created_asc',
+ desc: 'created_desc',
+ },
+ {
+ label: __('Updated'),
+ asc: 'latest_activity_asc',
+ desc: 'latest_activity_desc',
+ },
+ {
+ label: __('Stars'),
+ asc: 'stars_asc',
+ desc: 'stars_desc',
+ },
+];
diff --git a/app/assets/javascripts/groups/init_overview_tabs.js b/app/assets/javascripts/groups/init_overview_tabs.js
index 4fa3682c729..664d07ca13d 100644
--- a/app/assets/javascripts/groups/init_overview_tabs.js
+++ b/app/assets/javascripts/groups/init_overview_tabs.js
@@ -51,6 +51,7 @@ export const initGroupOverviewTabs = () => {
subgroupsAndProjectsEndpoint,
sharedProjectsEndpoint,
archivedProjectsEndpoint,
+ initialSort,
} = el.dataset;
return new Vue({
@@ -70,6 +71,7 @@ export const initGroupOverviewTabs = () => {
[ACTIVE_TAB_SHARED]: sharedProjectsEndpoint,
[ACTIVE_TAB_ARCHIVED]: archivedProjectsEndpoint,
},
+ initialSort,
},
render(createElement) {
return createElement(OverviewTabs);
diff --git a/app/assets/javascripts/groups/settings/components/access_dropdown.vue b/app/assets/javascripts/groups/settings/components/access_dropdown.vue
index 28f059fa23e..db8e424e166 100644
--- a/app/assets/javascripts/groups/settings/components/access_dropdown.vue
+++ b/app/assets/javascripts/groups/settings/components/access_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
import { debounce, intersectionWith, groupBy, differenceBy, intersectionBy } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, s__, n__ } from '~/locale';
import { getSubGroups } from '../api/access_dropdown_api';
import { LEVEL_TYPES } from '../constants';
@@ -98,7 +98,7 @@ export default {
this.consolidateData(groupsResponse.data);
this.setSelected({ initial });
})
- .catch(() => createFlash({ message: __('Failed to load groups.') }))
+ .catch(() => createAlert({ message: __('Failed to load groups.') }))
.finally(() => {
this.initialLoading = false;
this.loading = false;
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 64bba91eb4d..34e984a9bb9 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -1,21 +1,11 @@
import $ from 'jquery';
import { escape } from 'lodash';
+import { groupsPath } from '~/vue_shared/components/group_select/utils';
import { __ } from '~/locale';
import Api from './api';
import { loadCSSFile } from './lib/utils/css_utils';
import { select2AxiosTransport } from './lib/utils/select2_utils';
-const groupsPath = (groupsFilter, parentGroupID) => {
- switch (groupsFilter) {
- case 'descendant_groups':
- return Api.descendantGroupsPath.replace(':id', parentGroupID);
- case 'subgroups':
- return Api.subgroupsPath.replace(':id', parentGroupID);
- default:
- return Api.groupsPath;
- }
-};
-
const groupsSelect = () => {
loadCSSFile(gon.select2_css_path)
.then(() => {
diff --git a/app/assets/javascripts/header_search/components/app.vue b/app/assets/javascripts/header_search/components/app.vue
index f4b939fb20f..8fc0ce48e61 100644
--- a/app/assets/javascripts/header_search/components/app.vue
+++ b/app/assets/javascripts/header_search/components/app.vue
@@ -14,6 +14,7 @@ import { visitUrl } from '~/lib/utils/url_utility';
import { truncate } from '~/lib/utils/text_utility';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale';
+import Tracking from '~/tracking';
import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
import {
FIRST_DROPDOWN_INDEX,
@@ -163,8 +164,17 @@ export default {
...mapActions(['setSearch', 'fetchAutocompleteOptions', 'clearAutocomplete']),
openDropdown() {
this.showDropdown = true;
- this.isFocused = true;
- this.$emit('expandSearchBar', true);
+
+ // check isFocused state to avoid firing duplicate events
+ if (!this.isFocused) {
+ this.isFocused = true;
+ this.$emit('expandSearchBar', true);
+
+ Tracking.event(undefined, 'focus_input', {
+ label: 'global_search',
+ property: 'top_navigation',
+ });
+ }
},
closeDropdown() {
this.showDropdown = false;
@@ -178,6 +188,11 @@ export default {
this.showDropdown = false;
this.isFocused = false;
this.$emit('collapseSearchBar');
+
+ Tracking.event(undefined, 'blur_input', {
+ label: 'global_search',
+ property: 'top_navigation',
+ });
}, 200);
},
submitSearch() {
diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue
index c184e25f67f..00059d01308 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/description.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue
@@ -23,7 +23,12 @@ export default {
<template>
<div class="d-flex align-items-center">
- <ci-icon is-borderless :status="job.status" :size="24" class="d-flex" />
+ <ci-icon
+ is-borderless
+ :status="job.status"
+ :size="24"
+ class="gl-align-items-center gl-border gl-display-inline-flex gl-z-index-1"
+ />
<span class="gl-ml-3">
{{ job.name }}
<a
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 2284ffb8480..4d8c62d3430 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon, GlIcon, GlTooltipDirective, GlBadge } from '@gitlab/ui';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { __ } from '~/locale';
import Item from './item.vue';
export default {
@@ -10,7 +10,6 @@ export default {
components: {
GlIcon,
GlBadge,
- CiIcon,
Item,
GlLoadingIcon,
},
@@ -27,11 +26,15 @@ export default {
},
computed: {
collapseIcon() {
- return this.stage.isCollapsed ? 'chevron-lg-left' : 'chevron-lg-down';
+ return this.stage.isCollapsed ? 'chevron-lg-down' : 'chevron-lg-up';
},
showLoadingIcon() {
return this.stage.isLoading && !this.stage.jobs.length;
},
+ stageTitle() {
+ const prefix = __('Stage');
+ return `${prefix}: ${this.stage.name}`;
+ },
jobsCount() {
return this.stage.jobs.length;
},
@@ -57,29 +60,29 @@ export default {
<template>
<div class="ide-stage card gl-mt-3">
<div
- ref="cardHeader"
:class="{
'border-bottom-0': stage.isCollapsed,
}"
- class="card-header"
+ class="card-header gl-align-items-center gl-cursor-pointer gl-display-flex"
+ data-testid="card-header"
@click="toggleCollapsed"
>
- <ci-icon :status="stage.status" :size="24" />
<strong
ref="stageTitle"
v-gl-tooltip="showTooltip"
:title="showTooltip ? stage.name : null"
data-container="body"
- class="gl-ml-3 text-truncate"
+ class="gl-text-truncate"
+ data-testid="stage-title"
>
- {{ stage.name }}
+ {{ stageTitle }}
</strong>
<div v-if="!stage.isLoading || stage.jobs.length" class="gl-mr-3 gl-ml-2">
<gl-badge>{{ jobsCount }}</gl-badge>
</div>
- <gl-icon :name="collapseIcon" class="ide-stage-collapse-icon" />
+ <gl-icon :name="collapseIcon" class="gl-absolute gl-right-5" />
</div>
- <div v-show="!stage.isCollapsed" ref="jobList" class="card-body p-0">
+ <div v-show="!stage.isCollapsed" class="card-body p-0" data-testid="job-list">
<gl-loading-icon v-if="showLoadingIcon" size="sm" />
<template v-else>
<item v-for="job in stage.jobs" :key="job.id" :job="job" @clickViewLog="clickViewLog" />
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 9684bf8f18c..dbfaeba9708 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlModal, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, sprintf } from '~/locale';
import { modalTypes } from '../../constants';
import { trimPathComponents, getPathParent } from '../../utils';
@@ -77,7 +77,7 @@ export default {
if (this.modalType === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
- createFlash({
+ createAlert({
message: sprintf(__('The name "%{name}" is already taken in this directory.'), {
name: this.entryName,
}),
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index a1396995a3b..5f35dbdc5e7 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -11,7 +11,7 @@ import {
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';
+import { createAlert } from '~/flash';
import ModelManager from '~/ide/lib/common/model_manager';
import { defaultDiffEditorOptions, defaultEditorOptions } from '~/ide/lib/editor_options';
import { __ } from '~/locale';
@@ -239,7 +239,7 @@ export default {
this.createEditorInstance();
})
.catch((err) => {
- createFlash({
+ createAlert({
message: __('Error setting up editor. Please try again.'),
fadeTransition: false,
addBodyClass: true,
@@ -331,7 +331,7 @@ export default {
useLivePreviewExtension();
})
.catch((e) =>
- createFlash({
+ createAlert({
message: e,
}),
);
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 10e9f6a9488..1a191f6f76f 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -99,7 +99,9 @@ export function startIde(options) {
return;
}
- if (gon.features?.vscodeWebIde) {
+ const useNewWebIde = parseBoolean(ideElement.dataset.useNewWebIde);
+
+ if (useNewWebIde) {
initGitlabWebIDE(ideElement);
} else {
resetServiceWorkersPublicPath();
diff --git a/app/assets/javascripts/ide/init_gitlab_web_ide.js b/app/assets/javascripts/ide/init_gitlab_web_ide.js
index a061da38d4f..140f2895a29 100644
--- a/app/assets/javascripts/ide/init_gitlab_web_ide.js
+++ b/app/assets/javascripts/ide/init_gitlab_web_ide.js
@@ -7,8 +7,7 @@ export const initGitlabWebIDE = async (el) => {
const baseUrl = new URL(process.env.GITLAB_WEB_IDE_PUBLIC_PATH, window.location.origin);
// what: Pull what we need from the element. We will replace it soon.
- const { path_with_namespace: projectPath } = JSON.parse(el.dataset.project);
- const { cspNonce: nonce, branchName: ref } = el.dataset;
+ const { cspNonce: nonce, branchName: ref, projectPath } = el.dataset;
// what: Clean up the element, but preserve id.
// why: This way we don't inherit any `ide-loading` side-effects. This
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index b22e58a376d..dc0f3a1d7e9 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -1,6 +1,6 @@
import { escape } from 'lodash';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
import {
@@ -36,7 +36,7 @@ export const createTempEntry = (
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
if (getters.entryExists(name)) {
- createFlash({
+ createAlert({
message: sprintf(__('The name "%{name}" is already taken in this directory.'), {
name: name.split('/').pop(),
}),
@@ -281,7 +281,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force =
if (e.response.status === 404) {
reject(e);
} else {
- createFlash({
+ createAlert({
message: __('Error loading branch data. Please try again.'),
fadeTransition: false,
addBodyClass: true,
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index f3f603d4ae9..cd8088bf667 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '../../constants';
import service from '../../services';
@@ -34,7 +34,7 @@ export const getMergeRequestsForBranch = (
}
})
.catch((e) => {
- createFlash({
+ createAlert({
message: __(`Error fetching merge requests for ${branchId}`),
fadeTransition: false,
addBodyClass: true,
@@ -233,7 +233,7 @@ export const openMergeRequest = async (
await dispatch('openMergeRequestChanges', changes);
} catch (e) {
- createFlash({ message: __('Error while loading the merge request. Please try again.') });
+ createAlert({ message: __('Error while loading the merge request. Please try again.') });
throw e;
}
};
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 37a405e3fac..7a6a267e7d0 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -1,5 +1,5 @@
import { escape } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, sprintf } from '~/locale';
import { logError } from '~/lib/logger';
import api from '~/api';
@@ -11,7 +11,7 @@ const ERROR_LOADING_PROJECT = __('Error loading project data. Please try again.'
const errorFetchingData = (e) => {
logError(ERROR_LOADING_PROJECT, e);
- createFlash({
+ createAlert({
message: ERROR_LOADING_PROJECT,
fadeTransition: false,
addBodyClass: true,
@@ -51,7 +51,7 @@ export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {})
});
})
.catch((e) => {
- createFlash({
+ createAlert({
message: __('Error loading last commit.'),
fadeTransition: false,
addBodyClass: true,
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 2ff71523b1b..cbc6e0fe519 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { addNumericSuffix } from '~/ide/utils';
import { sprintf, __ } from '~/locale';
import { leftSidebarViews } from '../../../constants';
@@ -143,7 +143,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
commit(types.UPDATE_LOADING, false);
if (!data.short_id) {
- createFlash({
+ createAlert({
message: data.message,
fadeTransition: false,
addBodyClass: true,
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
index 82d9300d30b..91868132a5a 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import * as terminalService from '../../../../services/terminals';
@@ -26,7 +26,7 @@ export const receiveStartSessionSuccess = ({ commit, dispatch }, data) => {
};
export const receiveStartSessionError = ({ dispatch }) => {
- createFlash({ message: messages.UNEXPECTED_ERROR_STARTING });
+ createAlert({ message: messages.UNEXPECTED_ERROR_STARTING });
dispatch('killSession');
};
@@ -59,7 +59,7 @@ export const receiveStopSessionSuccess = ({ dispatch }) => {
};
export const receiveStopSessionError = ({ dispatch }) => {
- createFlash({ message: messages.UNEXPECTED_ERROR_STOPPING });
+ createAlert({ message: messages.UNEXPECTED_ERROR_STOPPING });
dispatch('killSession');
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
index 7fe1a8cc2df..4aa0768d394 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as messages from '../messages';
import * as types from '../mutation_types';
@@ -42,7 +42,7 @@ export const receiveSessionStatusSuccess = ({ commit, dispatch }, data) => {
};
export const receiveSessionStatusError = ({ dispatch }) => {
- createFlash({ message: messages.UNEXPECTED_ERROR_STATUS });
+ createAlert({ message: messages.UNEXPECTED_ERROR_STATUS });
dispatch('killSession');
};
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index a7e6506b045..83a3d7f2ac3 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -1,5 +1,6 @@
import { flatten, isString } from 'lodash';
import { languages } from 'monaco-editor';
+import { setDiagnosticsOptions as yamlDiagnosticsOptions } from 'monaco-yaml';
import { performanceMarkAndMeasure } from '~/performance/utils';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
@@ -82,17 +83,16 @@ export function registerLanguages(def, ...defs) {
}
export function registerSchema(schema, options = {}) {
- const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
- defaults.forEach((d) =>
- d.setDiagnosticsOptions({
- validate: true,
- enableSchemaRequest: true,
- hover: true,
- completion: true,
- schemas: [schema],
- ...options,
- }),
- );
+ const defaultOptions = {
+ validate: true,
+ enableSchemaRequest: true,
+ hover: true,
+ completion: true,
+ schemas: [schema],
+ ...options,
+ };
+ languages.json.jsonDefaults.setDiagnosticsOptions(defaultOptions);
+ yamlDiagnosticsOptions(defaultOptions);
}
export const otherSide = (side) => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
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 98ee858ca91..0cdd64b1b98 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
@@ -12,7 +12,7 @@ import {
GlFormCheckbox,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__, __, n__, sprintf } from '~/locale';
import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
@@ -150,6 +150,10 @@ export default {
},
groupsTableData() {
+ if (!this.availableNamespaces) {
+ return [];
+ }
+
return this.groups.map((group) => {
const importTarget = this.getImportTarget(group);
const status = this.getStatus(group);
@@ -232,6 +236,10 @@ export default {
version: this.bulkImportSourceGroups.versionValidation.features.sourceInstanceVersion,
});
},
+
+ pageInfo() {
+ return this.bulkImportSourceGroups?.pageInfo ?? {};
+ },
},
watch: {
@@ -342,7 +350,7 @@ export default {
variables: { importRequests },
});
} catch (error) {
- createFlash({
+ createAlert({
message: i18n.ERROR_IMPORT,
captureError: true,
error,
@@ -503,6 +511,7 @@ export default {
permissionsHelpPath: helpPagePath('user/permissions', { anchor: 'group-members-permissions' }),
popoverOptions: { title: __('What is listed here?') },
i18n,
+ LOCAL_STORAGE_KEY: 'gl-bulk-imports-status-page-size-v1',
};
</script>
@@ -696,14 +705,15 @@ export default {
/>
</template>
</gl-table>
- <pagination-bar
- v-if="hasGroups"
- :page-info="bulkImportSourceGroups.pageInfo"
- class="gl-mt-3"
- @set-page="setPage"
- @set-page-size="setPageSize"
- />
</template>
</template>
+ <pagination-bar
+ v-show="!$apollo.loading && hasGroups"
+ :page-info="pageInfo"
+ class="gl-mt-3"
+ :storage-key="$options.LOCAL_STORAGE_KEY"
+ @set-page="setPage"
+ @set-page-size="setPageSize"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/import_entities/import_groups/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/services/status_poller.js
index ba0f2bb947a..6ad5e448a40 100644
--- a/app/assets/javascripts/import_entities/import_groups/services/status_poller.js
+++ b/app/assets/javascripts/import_entities/import_groups/services/status_poller.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
import { s__ } from '~/locale';
@@ -15,7 +15,7 @@ export class StatusPoller {
statuses.forEach((status) => updateImportStatus(status));
},
errorCallback: () =>
- createFlash({
+ createAlert({
message: s__('BulkImport|Update of import statuses with realtime changes failed'),
}),
});
diff --git a/app/assets/javascripts/import_entities/import_projects/components/advanced_settings.vue b/app/assets/javascripts/import_entities/import_projects/components/advanced_settings.vue
new file mode 100644
index 00000000000..a8fdf9b9ec5
--- /dev/null
+++ b/app/assets/javascripts/import_entities/import_projects/components/advanced_settings.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlAccordion, GlAccordionItem, GlAlert, GlForm, GlFormCheckbox } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlAccordion,
+ GlAccordionItem,
+ GlAlert,
+ GlForm,
+ GlFormCheckbox,
+ },
+ props: {
+ stages: {
+ required: true,
+ type: Array,
+ },
+ value: {
+ required: true,
+ type: Object,
+ },
+ isInitiallyExpanded: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+<template>
+ <gl-accordion :header-level="3">
+ <gl-accordion-item
+ :title="s__('ImportProjects|Advanced import settings')"
+ :visible="isInitiallyExpanded"
+ >
+ <gl-alert variant="warning" class="gl-mb-5" :dismissible="false">{{
+ s__('ImportProjects|The more information you select, the longer it will take to import')
+ }}</gl-alert>
+ <gl-form>
+ <gl-form-checkbox
+ v-for="{ name, label, details } in stages"
+ :key="name"
+ :checked="value[name]"
+ @change="$emit('input', { ...value, [name]: $event })"
+ >
+ {{ label }}
+ <template v-if="details" #help>{{ details }} </template>
+ </gl-form-checkbox>
+ </gl-form>
+ </gl-accordion-item>
+ </gl-accordion>
+</template>
diff --git a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
index 848c7361601..97a7ed4bf55 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
@@ -9,10 +9,12 @@ import {
import { mapActions, mapState, mapGetters } from 'vuex';
import { n__, __, sprintf } from '~/locale';
import ProviderRepoTableRow from './provider_repo_table_row.vue';
+import AdvancedSettings from './advanced_settings.vue';
export default {
name: 'ImportProjectsTable',
components: {
+ AdvancedSettings,
ProviderRepoTableRow,
GlLoadingIcon,
GlButton,
@@ -35,6 +37,24 @@ export default {
required: false,
default: false,
},
+ optionalStages: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isAdvancedSettingsPanelInitiallyExpanded: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+
+ data() {
+ return {
+ optionalStagesSelection: Object.fromEntries(
+ this.optionalStages.map(({ name }) => [name, false]),
+ ),
+ };
},
computed: {
@@ -127,7 +147,7 @@ export default {
modal-id="import-all-modal"
:title="s__('ImportProjects|Import repositories')"
:ok-title="__('Import')"
- @ok="importAll"
+ @ok="importAll({ optionalStages: optionalStagesSelection })"
>
{{
n__(
@@ -150,6 +170,13 @@ export default {
/>
</form>
</div>
+ <advanced-settings
+ v-if="optionalStages && optionalStages.length"
+ v-model="optionalStagesSelection"
+ :stages="optionalStages"
+ :is-initially-expanded="isAdvancedSettingsPanelInitiallyExpanded"
+ class="gl-mb-5"
+ />
<div v-if="repositories.length" class="gl-w-full">
<table>
<thead class="gl-border-0 gl-border-solid gl-border-t-1 gl-border-gray-100">
@@ -171,6 +198,7 @@ export default {
:repo="repo"
:available-namespaces="namespaces"
:user-namespace="defaultTargetNamespace"
+ :optional-stages="optionalStagesSelection"
/>
</template>
</tbody>
diff --git a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
index e4090a378e1..458e0fb1cb1 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
@@ -43,6 +43,10 @@ export default {
type: Array,
required: true,
},
+ optionalStages: {
+ type: Object,
+ required: true,
+ },
},
computed: {
@@ -177,7 +181,7 @@ export default {
v-if="isImportNotStarted"
type="button"
data-qa-selector="import_button"
- @click="fetchImport(repo.importSource.id)"
+ @click="fetchImport({ repoId: repo.importSource.id, optionalStages })"
>
{{ importButtonText }}
</gl-button>
diff --git a/app/assets/javascripts/import_entities/import_projects/index.js b/app/assets/javascripts/import_entities/import_projects/index.js
index 5146a0eb461..4daa9e8a1b8 100644
--- a/app/assets/javascripts/import_entities/import_projects/index.js
+++ b/app/assets/javascripts/import_entities/import_projects/index.js
@@ -42,6 +42,7 @@ export function initPropsFromElement(element) {
providerTitle: element.dataset.provider,
filterable: parseBoolean(element.dataset.filterable),
paginatable: parseBoolean(element.dataset.paginatable),
+ optionalStages: JSON.parse(element.dataset.optionalStages),
};
}
diff --git a/app/assets/javascripts/import_entities/import_projects/store/actions.js b/app/assets/javascripts/import_entities/import_projects/store/actions.js
index 92be028b8a9..a30c14f9d28 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/actions.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -43,11 +43,14 @@ const restartJobsPolling = () => {
const setImportTarget = ({ commit }, { repoId, importTarget }) =>
commit(types.SET_IMPORT_TARGET, { repoId, importTarget });
-const importAll = ({ state, dispatch }) => {
+const importAll = ({ state, dispatch }, config = {}) => {
return Promise.all(
- state.repositories
- .filter(isProjectImportable)
- .map((r) => dispatch('fetchImport', r.importSource.id)),
+ state.repositories.filter(isProjectImportable).map((r) =>
+ dispatch('fetchImport', {
+ repoId: r.importSource.id,
+ optionalStages: config?.optionalStages,
+ }),
+ ),
);
};
@@ -73,7 +76,7 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else if (tooManyRequests(e)) {
- createFlash({
+ createAlert({
message: sprintf(s__('ImportProjects|%{provider} rate limit exceeded. Try again later'), {
provider: capitalizeFirstCharacter(provider),
}),
@@ -81,7 +84,7 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
commit(types.RECEIVE_REPOS_ERROR);
} else {
- createFlash({
+ createAlert({
message: sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
provider,
}),
@@ -92,7 +95,10 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
});
};
-const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, getters }, repoId) => {
+const fetchImportFactory = (importPath = isRequired()) => (
+ { state, commit, getters },
+ { repoId, optionalStages },
+) => {
const { ciCdOnly } = state;
const importTarget = getters.getImportTarget(repoId);
@@ -105,6 +111,7 @@ const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, gett
ci_cd_only: ciCdOnly,
new_name: newName,
target_namespace: targetNamespace,
+ ...(Object.keys(optionalStages).length ? { optional_stages: optionalStages } : {}),
})
.then(({ data }) => {
commit(types.RECEIVE_IMPORT_SUCCESS, {
@@ -124,7 +131,7 @@ const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, gett
)
: s__('ImportProjects|Importing the project failed');
- createFlash({
+ createAlert({
message: flashMessage,
});
@@ -149,7 +156,7 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
- createFlash({
+ createAlert({
message: s__('ImportProjects|Update of imported projects with realtime changes failed'),
});
}
@@ -177,7 +184,7 @@ const fetchNamespacesFactory = (namespacesPath = isRequired()) => ({ commit }) =
commit(types.RECEIVE_NAMESPACES_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })),
)
.catch(() => {
- createFlash({
+ createAlert({
message: s__('ImportProjects|Requesting namespaces failed'),
});
diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js
index 437bcc39886..2806b785816 100644
--- a/app/assets/javascripts/integrations/constants.js
+++ b/app/assets/javascripts/integrations/constants.js
@@ -91,3 +91,5 @@ export const placeholderForType = {
[INTEGRATION_TYPE_SLACK]: __('#general, #development'),
[INTEGRATION_TYPE_MATTERMOST]: __('my-channel'),
};
+
+export const INTEGRATION_FORM_TYPE_SLACK = 'gitlab_slack_application';
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index 7a6f1a953a8..15f76c16516 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -14,12 +14,14 @@ import {
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
+ INTEGRATION_FORM_TYPE_SLACK,
integrationLevels,
integrationFormSectionComponents,
billingPlanNames,
} from '~/integrations/constants';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import csrf from '~/lib/utils/csrf';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue';
import ConfirmationModal from './confirmation_modal.vue';
@@ -65,6 +67,7 @@ export default {
GlModal: GlModalDirective,
SafeHtml,
},
+ mixins: [glFeatureFlagsMixin()],
inject: {
helpHtml: {
default: '',
@@ -101,6 +104,9 @@ export default {
return Boolean(this.isSaving || this.isResetting || this.isTesting);
},
hasSections() {
+ if (this.hasSlackNotificationsDisabled) {
+ return false;
+ }
return this.customState.sections.length !== 0;
},
fieldsWithoutSection() {
@@ -108,6 +114,24 @@ export default {
? this.propsSource.fields.filter((field) => !field.section)
: this.propsSource.fields;
},
+ hasFieldsWithoutSection() {
+ if (this.hasSlackNotificationsDisabled) {
+ return false;
+ }
+ return this.fieldsWithoutSection.length;
+ },
+ isSlackIntegration() {
+ return this.propsSource.type === INTEGRATION_FORM_TYPE_SLACK;
+ },
+ hasSlackNotificationsDisabled() {
+ return this.isSlackIntegration && !this.glFeatures.integrationSlackAppNotifications;
+ },
+ showHelpHtml() {
+ if (this.isSlackIntegration) {
+ return this.helpHtml;
+ }
+ return !this.hasSections && this.helpHtml;
+ },
},
methods: {
...mapActions(['setOverride', 'requestJiraIssueTypes']),
@@ -227,6 +251,31 @@ export default {
@change="setOverride"
/>
+ <section v-if="showHelpHtml" class="gl-lg-display-flex gl-justify-content-end gl-mb-6">
+ <!-- helpHtml is trusted input -->
+ <div
+ v-safe-html:[$options.helpHtmlConfig]="helpHtml"
+ data-testid="help-html"
+ class="gl-flex-basis-two-thirds"
+ ></div>
+ </section>
+
+ <section v-if="!hasSections" class="gl-lg-display-flex gl-justify-content-end">
+ <div class="gl-flex-basis-two-thirds">
+ <active-checkbox
+ v-if="propsSource.showActive"
+ :key="`${currentKey}-active-checkbox`"
+ @toggle-integration-active="onToggleIntegrationState"
+ />
+ <trigger-fields
+ v-if="propsSource.triggerEvents.length"
+ :key="`${currentKey}-trigger-fields`"
+ :events="propsSource.triggerEvents"
+ :type="propsSource.type"
+ />
+ </div>
+ </section>
+
<template v-if="hasSections">
<div
v-for="(section, index) in customState.sections"
@@ -234,8 +283,8 @@ export default {
:class="{ 'gl-border-b gl-pb-3 gl-mb-6': index !== customState.sections.length - 1 }"
data-testid="integration-section"
>
- <div class="row">
- <div class="col-lg-4">
+ <section class="gl-lg-display-flex">
+ <div class="gl-flex-basis-third gl-mr-4">
<h4 class="gl-mt-0">
{{ section.title
}}<gl-badge
@@ -253,7 +302,7 @@ export default {
<p v-safe-html="section.description"></p>
</div>
- <div class="col-lg-8">
+ <div class="gl-flex-basis-two-thirds">
<component
:is="$options.integrationFormSectionComponents[section.type]"
:fields="fieldsForSection(section)"
@@ -262,28 +311,12 @@ export default {
@request-jira-issue-types="onRequestJiraIssueTypes"
/>
</div>
- </div>
+ </section>
</div>
</template>
- <div class="row">
- <div class="col-lg-4"></div>
-
- <div class="col-lg-8">
- <!-- helpHtml is trusted input -->
- <div v-if="helpHtml && !hasSections" v-safe-html:[$options.helpHtmlConfig]="helpHtml"></div>
-
- <active-checkbox
- v-if="propsSource.showActive && !hasSections"
- :key="`${currentKey}-active-checkbox`"
- @toggle-integration-active="onToggleIntegrationState"
- />
- <trigger-fields
- v-if="propsSource.triggerEvents.length && !hasSections"
- :key="`${currentKey}-trigger-fields`"
- :events="propsSource.triggerEvents"
- :type="propsSource.type"
- />
+ <section v-if="hasFieldsWithoutSection" class="gl-lg-display-flex gl-justify-content-end">
+ <div class="gl-flex-basis-two-thirds">
<dynamic-field
v-for="field in fieldsWithoutSection"
:key="`${currentKey}-${field.name}`"
@@ -292,12 +325,12 @@ export default {
:data-qa-selector="`${field.name}_div`"
/>
</div>
- </div>
+ </section>
- <div v-if="isEditable" class="row">
- <div :class="hasSections ? 'col' : 'col-lg-8 offset-lg-4'">
+ <section v-if="isEditable" :class="!hasSections && 'gl-lg-display-flex gl-justify-content-end'">
+ <div :class="!hasSections && 'gl-flex-basis-two-thirds'">
<div
- class="footer-block row-content-block gl-display-flex gl-justify-content-space-between"
+ class="footer-block row-content-block gl-lg-display-flex gl-justify-content-space-between"
>
<div>
<template v-if="isInstanceOrGroupLevel">
@@ -359,6 +392,6 @@ export default {
</template>
</div>
</div>
- </div>
+ </section>
</gl-form>
</template>
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
deleted file mode 100644
index 243d82f55aa..00000000000
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import $ from 'jquery';
-import { loadCSSFile } from '../lib/utils/css_utils';
-
-let instanceCount = 0;
-
-class AutoWidthDropdownSelect {
- constructor(selectElement) {
- this.$selectElement = $(selectElement);
- this.dropdownClass = `js-auto-width-select-dropdown-${instanceCount}`;
- instanceCount += 1;
- }
-
- init() {
- const { dropdownClass } = this;
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(() => {
- // eslint-disable-next-line promise/no-nesting
- loadCSSFile(gon.select2_css_path)
- .then(() => {
- this.$selectElement.select2({
- dropdownCssClass: dropdownClass,
- ...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
- });
- })
- .catch(() => {});
- })
- .catch(() => {});
-
- return this;
- }
-
- static selectOptions(dropdownClass) {
- return {
- dropdownCss() {
- let resultantWidth = 'auto';
- const $dropdown = $(`.${dropdownClass}`);
-
- // We have to look at the parent because
- // `offsetParent` on a `display: none;` is `null`
- const offsetParentWidth = $(this).parent().offsetParent().width();
- // Reset any width to let it naturally flow
- $dropdown.css('width', 'auto');
- if ($dropdown.outerWidth(false) > offsetParentWidth) {
- resultantWidth = offsetParentWidth;
- }
-
- return {
- width: resultantWidth,
- maxWidth: offsetParentWidth,
- };
- },
- };
- }
-}
-
-export default AutoWidthDropdownSelect;
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue
new file mode 100644
index 00000000000..ba94932289e
--- /dev/null
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { statusDropdownOptions } from '../constants';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ data() {
+ return {
+ status: null,
+ };
+ },
+ computed: {
+ dropdownText() {
+ return this.status?.text ?? this.$options.i18n.defaultDropdownText;
+ },
+ selectedValue() {
+ return this.status?.value;
+ },
+ },
+ methods: {
+ onDropdownItemClick(statusOption) {
+ // clear status if the currently checked status is clicked again
+ if (this.status?.value === statusOption.value) {
+ this.status = null;
+ } else {
+ this.status = statusOption;
+ }
+ },
+ },
+ i18n: {
+ dropdownTitle: __('Change status'),
+ defaultDropdownText: __('Select status'),
+ },
+ statusDropdownOptions,
+};
+</script>
+<template>
+ <div>
+ <input type="hidden" name="update[state_event]" :value="selectedValue" />
+ <gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full">
+ <gl-dropdown-item
+ v-for="statusOption in $options.statusDropdownOptions"
+ :key="statusOption.value"
+ :is-checked="selectedValue === statusOption.value"
+ is-check-item
+ :title="statusOption.text"
+ @click="onDropdownItemClick(statusOption)"
+ >
+ {{ statusOption.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
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
deleted file mode 100644
index 9509399e91d..00000000000
--- a/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_select.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { __ } from '~/locale';
-import { ISSUE_STATUS_SELECT_OPTIONS } from '../constants';
-
-export default {
- name: 'StatusSelect',
- components: {
- GlDropdown,
- GlDropdownItem,
- },
- data() {
- return {
- status: null,
- };
- },
- computed: {
- dropdownText() {
- return this.status?.text ?? this.$options.i18n.defaultDropdownText;
- },
- selectedValue() {
- return this.status?.value;
- },
- },
- methods: {
- onDropdownItemClick(statusOption) {
- // clear status if the currently checked status is clicked again
- if (this.status?.value === statusOption.value) {
- this.status = null;
- } else {
- this.status = statusOption;
- }
- },
- },
- i18n: {
- dropdownTitle: __('Change status'),
- defaultDropdownText: __('Select status'),
- },
- ISSUE_STATUS_SELECT_OPTIONS,
-};
-</script>
-<template>
- <div>
- <input type="hidden" name="update[state_event]" :value="selectedValue" />
- <gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full">
- <gl-dropdown-item
- v-for="statusOption in $options.ISSUE_STATUS_SELECT_OPTIONS"
- :key="statusOption.value"
- :is-checked="selectedValue === statusOption.value"
- is-check-item
- :title="statusOption.text"
- @click="onDropdownItemClick(statusOption)"
- >
- {{ statusOption.text }}
- </gl-dropdown-item>
- </gl-dropdown>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue
new file mode 100644
index 00000000000..8774b065c22
--- /dev/null
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { subscriptionsDropdownOptions } from '../constants';
+
+export default {
+ subscriptionsDropdownOptions,
+ i18n: {
+ defaultDropdownText: __('Select subscription'),
+ headerText: __('Change subscription'),
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ data() {
+ return {
+ subscription: undefined,
+ };
+ },
+ computed: {
+ dropdownText() {
+ return this.subscription?.text ?? this.$options.i18n.defaultDropdownText;
+ },
+ selectedValue() {
+ return this.subscription?.value;
+ },
+ },
+ methods: {
+ handleClick(option) {
+ this.subscription = option.value === this.subscription?.value ? undefined : option;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <input type="hidden" name="update[subscription_event]" :value="selectedValue" />
+ <gl-dropdown class="gl-w-full" :header-text="$options.i18n.headerText" :text="dropdownText">
+ <gl-dropdown-item
+ v-for="subscriptionsOption in $options.subscriptionsDropdownOptions"
+ :key="subscriptionsOption.value"
+ is-check-item
+ :is-checked="selectedValue === subscriptionsOption.value"
+ @click="handleClick(subscriptionsOption)"
+ >
+ {{ subscriptionsOption.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js b/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js
index ad15b25f9cf..68133ceb3c7 100644
--- a/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js
@@ -1,17 +1,23 @@
import { __ } from '~/locale';
-export const ISSUE_STATUS_MODIFIERS = {
- REOPEN: 'reopen',
- CLOSE: 'close',
-};
-
-export const ISSUE_STATUS_SELECT_OPTIONS = [
+export const statusDropdownOptions = [
{
- value: ISSUE_STATUS_MODIFIERS.REOPEN,
text: __('Open'),
+ value: 'reopen',
},
{
- value: ISSUE_STATUS_MODIFIERS.CLOSE,
text: __('Closed'),
+ value: 'close',
+ },
+];
+
+export const subscriptionsDropdownOptions = [
+ {
+ text: __('Subscribe'),
+ value: 'subscribe',
+ },
+ {
+ text: __('Unsubscribe'),
+ value: 'unsubscribe',
},
];
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js b/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
index 967996b859e..4657771353f 100644
--- a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/index.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
-import StatusSelect from './components/status_select.vue';
+import StatusDropdown from './components/status_dropdown.vue';
+import SubscriptionsDropdown from './components/subscriptions_dropdown.vue';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
@@ -14,8 +15,8 @@ export function initBulkUpdateSidebar(prefixId) {
new IssuableBulkUpdateSidebar(); // eslint-disable-line no-new
}
-export function initIssueStatusSelect() {
- const el = document.querySelector('.js-issue-status');
+export function initStatusDropdown() {
+ const el = document.querySelector('.js-status-dropdown');
if (!el) {
return null;
@@ -23,7 +24,21 @@ export function initIssueStatusSelect() {
return new Vue({
el,
- name: 'StatusSelectRoot',
- render: (createElement) => createElement(StatusSelect),
+ name: 'StatusDropdownRoot',
+ render: (createElement) => createElement(StatusDropdown),
+ });
+}
+
+export function initSubscriptionsDropdown() {
+ const el = document.querySelector('.js-subscriptions-dropdown');
+
+ if (!el) {
+ return null;
+ }
+
+ return new Vue({
+ el,
+ name: 'SubscriptionsDropdownRoot',
+ render: (createElement) => createElement(SubscriptionsDropdown),
});
}
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
index 8a55176fed0..a33c6ae8030 100644
--- 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
@@ -5,7 +5,6 @@ import issuableEventHub from '~/issues/list/eventhub';
import LabelsSelect from '~/labels/labels_select';
import MilestoneSelect from '~/milestones/milestone_select';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
-import subscriptionSelect from './subscription_select';
const HIDDEN_CLASS = 'hidden';
const DISABLED_CONTENT_CLASS = 'disabled-content';
@@ -52,7 +51,6 @@ export default class IssuableBulkUpdateSidebar {
initDropdowns() {
new LabelsSelect();
new MilestoneSelect();
- subscriptionSelect();
// Checking IS_EE and using ee_else_ce is odd, but we do it here to satisfy
// the import/no-unresolved lint rule when FOSS_ONLY=1, even though at
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js b/app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js
deleted file mode 100644
index b12ac776b4f..00000000000
--- a/app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'jquery';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __ } from '~/locale';
-
-export default function subscriptionSelect() {
- $('.js-subscription-event').each((i, element) => {
- const fieldName = $(element).data('fieldName');
-
- return initDeprecatedJQueryDropdown($(element), {
- selectable: true,
- fieldName,
- toggleLabel(selected, el, instance) {
- let label = __('Subscription');
- const $item = instance.dropdown.find('.is-active');
- if ($item.length) {
- label = $item.text();
- }
- return label;
- },
- clicked(options) {
- return options.e.preventDefault();
- },
- id(obj, el) {
- return $(el).data('id');
- },
- });
- });
-}
diff --git a/app/assets/javascripts/issuable/issuable_context.js b/app/assets/javascripts/issuable/issuable_context.js
index 37001d00a27..8c2e2a5df67 100644
--- a/app/assets/javascripts/issuable/issuable_context.js
+++ b/app/assets/javascripts/issuable/issuable_context.js
@@ -1,7 +1,6 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import { setCookie } from '~/lib/utils/common_utils';
-import { loadCSSFile } from '~/lib/utils/css_utils';
import UsersSelect from '~/users_select';
export default class IssuableContext {
@@ -9,24 +8,6 @@ export default class IssuableContext {
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();
});
diff --git a/app/assets/javascripts/issuable/issuable_form.js b/app/assets/javascripts/issuable/issuable_form.js
index 81bf7ca6ccc..e8ba99e0e9e 100644
--- a/app/assets/javascripts/issuable/issuable_form.js
+++ b/app/assets/javascripts/issuable/issuable_form.js
@@ -2,10 +2,7 @@ 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';
@@ -118,12 +115,6 @@ export default class IssuableForm {
});
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
}
-
- this.$targetBranchSelect = $('.js-target-branch-select', this.form);
-
- if (this.$targetBranchSelect.length) {
- this.initTargetBranchDropdown();
- }
}
initAutosave() {
@@ -214,47 +205,4 @@ export default class IssuableForm {
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/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue
index 0b424d105b9..acb6aa93f0f 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -247,8 +247,8 @@ export default {
},
defaultWorkItemTypes() {
return this.isWorkItemsEnabled
- ? defaultWorkItemTypes.concat(WORK_ITEM_TYPE_ENUM_TASK)
- : defaultWorkItemTypes;
+ ? defaultWorkItemTypes
+ : defaultWorkItemTypes.filter((type) => type !== WORK_ITEM_TYPE_ENUM_TASK);
},
typeTokenOptions() {
return this.isWorkItemsEnabled
@@ -563,7 +563,8 @@ export default {
if (!this.hasInitBulkEdit) {
const bulkUpdateSidebar = await import('~/issuable/bulk_update_sidebar');
bulkUpdateSidebar.initBulkUpdateSidebar('issuable_');
- bulkUpdateSidebar.initIssueStatusSelect();
+ bulkUpdateSidebar.initStatusDropdown();
+ bulkUpdateSidebar.initSubscriptionsDropdown();
const usersSelect = await import('~/users_select');
const UsersSelect = usersSelect.default;
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index 27738d7a3e6..9fe8899ab39 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -7,11 +7,13 @@ import {
FILTER_UPCOMING,
OPERATOR_IS,
OPERATOR_IS_NOT,
+ TOKEN_TYPE_HEALTH,
} from '~/vue_shared/components/filtered_search_bar/constants';
import {
WORK_ITEM_TYPE_ENUM_INCIDENT,
WORK_ITEM_TYPE_ENUM_ISSUE,
WORK_ITEM_TYPE_ENUM_TEST_CASE,
+ WORK_ITEM_TYPE_ENUM_TASK,
} from '~/work_items/constants';
export const i18n = {
@@ -147,14 +149,16 @@ export const TOKEN_TYPE_EPIC = 'epic_id';
export const TOKEN_TYPE_WEIGHT = 'weight';
export const TOKEN_TYPE_CONTACT = 'crm_contact';
export const TOKEN_TYPE_ORGANIZATION = 'crm_organization';
-export const TOKEN_TYPE_HEALTH = 'health_status';
-export const TYPE_TOKEN_TASK_OPTION = { icon: 'task-done', title: 'task', value: 'task' };
+export const TYPE_TOKEN_TASK_OPTION = { icon: 'issue-type-task', title: 'task', value: 'task' };
+// This should be consistent with Issue::TYPES_FOR_LIST in the backend
+// https://gitlab.com/gitlab-org/gitlab/-/blob/1379c2d7bffe2a8d809f23ac5ef9b4114f789c07/app/models/issue.rb#L48
export const defaultWorkItemTypes = [
WORK_ITEM_TYPE_ENUM_ISSUE,
WORK_ITEM_TYPE_ENUM_INCIDENT,
WORK_ITEM_TYPE_ENUM_TEST_CASE,
+ WORK_ITEM_TYPE_ENUM_TASK,
];
export const defaultTypeTokenOptions = [
@@ -327,10 +331,12 @@ export const filters = {
[TOKEN_TYPE_HEALTH]: {
[API_PARAM]: {
[NORMAL_FILTER]: 'healthStatus',
+ [SPECIAL_FILTER]: 'healthStatus',
},
[URL_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'health_status',
+ [SPECIAL_FILTER]: 'health_status',
},
},
},
diff --git a/app/assets/javascripts/issues/show/components/edited.vue b/app/assets/javascripts/issues/show/components/edited.vue
index 4c5f783cd66..5138a4530e9 100644
--- a/app/assets/javascripts/issues/show/components/edited.vue
+++ b/app/assets/javascripts/issues/show/components/edited.vue
@@ -1,10 +1,11 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
+import { GlSprintf } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
TimeAgoTooltip,
+ GlSprintf,
},
props: {
updatedAt: {
@@ -33,13 +34,27 @@ export default {
<template>
<small class="edited-text js-issue-widgets">
- 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>
+ <gl-sprintf v-if="!hasUpdatedBy" :message="__('Edited %{timeago}')">
+ <template #timeago>
+ <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" />
+ </template>
+ </gl-sprintf>
+ <gl-sprintf v-else-if="!updatedAt" :message="__('Edited by %{author}')">
+ <template #author>
+ <a :href="updatedByPath" class="author-link gl-hover-text-decoration-underline">
+ <span>{{ updatedByName }}</span>
+ </a>
+ </template>
+ </gl-sprintf>
+ <gl-sprintf v-else :message="__('Edited %{timeago} by %{author}')">
+ <template #timeago>
+ <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" />
+ </template>
+ <template #author>
+ <a :href="updatedByPath" class="author-link gl-hover-text-decoration-underline">
+ <span>{{ updatedByName }}</span>
+ </a>
+ </template>
+ </gl-sprintf>
</small>
</template>
diff --git a/app/assets/javascripts/issues/show/components/fields/description.vue b/app/assets/javascripts/issues/show/components/fields/description.vue
index c2ab7c4f298..dbe634e7295 100644
--- a/app/assets/javascripts/issues/show/components/fields/description.vue
+++ b/app/assets/javascripts/issues/show/components/fields/description.vue
@@ -1,13 +1,16 @@
<script>
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
+import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
+import glFeaturesFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import updateMixin from '../../mixins/update';
export default {
components: {
MarkdownField,
+ MarkdownEditor,
},
- mixins: [updateMixin],
+ mixins: [updateMixin, glFeaturesFlagMixin()],
props: {
value: {
type: String,
@@ -38,7 +41,12 @@ export default {
},
},
mounted() {
- this.$refs.textarea.focus();
+ this.focus();
+ },
+ methods: {
+ focus() {
+ this.$refs.textarea?.focus();
+ },
},
};
</script>
@@ -46,7 +54,26 @@ export default {
<template>
<div class="common-note-form">
<label class="sr-only" for="issue-description">{{ __('Description') }}</label>
+ <markdown-editor
+ v-if="glFeatures.contentEditorOnIssues"
+ class="gl-mt-3"
+ :value="value"
+ :render-markdown-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ :form-field-aria-label="__('Description')"
+ :form-field-placeholder="__('Write a comment or drag your files here…')"
+ form-field-id="issue-description"
+ form-field-name="issue-description"
+ :quick-actions-docs-path="quickActionsDocsPath"
+ :enable-autocomplete="enableAutocomplete"
+ supports-quick-actions
+ init-on-autofocus
+ @input="$emit('input', $event)"
+ @keydown.meta.enter="updateIssuable"
+ @keydown.ctrl.enter="updateIssuable"
+ />
<markdown-field
+ v-else
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
:quick-actions-docs-path="quickActionsDocsPath"
diff --git a/app/assets/javascripts/issues/show/components/form.vue b/app/assets/javascripts/issues/show/components/form.vue
index f479c8ae78d..0c6b61fb893 100644
--- a/app/assets/javascripts/issues/show/components/form.vue
+++ b/app/assets/javascripts/issues/show/components/form.vue
@@ -1,7 +1,6 @@
<script>
import { GlAlert } from '@gitlab/ui';
-import $ from 'jquery';
-import Autosave from '~/autosave';
+import { getDraft, updateDraft, getLockVersion, clearDraft } from '~/lib/utils/autosave';
import { IssuableType } from '~/issues/constants';
import eventHub from '../event_hub';
import EditActions from './edit_actions.vue';
@@ -76,10 +75,17 @@ export default {
},
},
data() {
+ const autosaveKey = [document.location.pathname, document.location.search];
+ const descriptionAutosaveKey = [...autosaveKey, 'description'];
+ const titleAutosaveKey = [...autosaveKey, 'title'];
+
return {
+ titleAutosaveKey,
+ descriptionAutosaveKey,
+ autosaveReset: false,
formData: {
- title: this.formState.title,
- description: this.formState.description,
+ title: getDraft(titleAutosaveKey) || this.formState.title,
+ description: getDraft(descriptionAutosaveKey) || this.formState.description,
},
showOutdatedDescriptionWarning: false,
};
@@ -118,58 +124,40 @@ export default {
},
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();
+ const savedLockVersion = getLockVersion(this.descriptionAutosaveKey);
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();
+ this.autosaveReset = true;
+ clearDraft(this.descriptionAutosaveKey);
+ clearDraft(this.titleAutosaveKey);
},
keepAutosave() {
- const {
- description: {
- $refs: { textarea },
- },
- } = this.$refs;
-
- textarea.focus();
+ this.$refs.description.focus();
this.showOutdatedDescriptionWarning = false;
},
discardAutosave() {
- const {
- description: {
- $refs: { textarea },
- },
- } = this.$refs;
-
- textarea.value = this.initialDescriptionText;
- textarea.focus();
+ this.formData.description = this.initialDescriptionText;
+ clearDraft(this.descriptionAutosaveKey);
+ this.$refs.description.focus();
this.showOutdatedDescriptionWarning = false;
},
+ updateTitleDraft(title) {
+ updateDraft(this.titleAutosaveKey, title);
+ },
+ updateDescriptionDraft(description) {
+ /*
+ * This conditional statement prevents a race-condition
+ * between clearing the draft and submitting a new draft
+ * update while the user is typing. It happens when saving
+ * using the cmd + enter keyboard shortcut.
+ */
+ if (!this.autosaveReset) {
+ updateDraft(this.descriptionAutosaveKey, description, this.formState.lock_version);
+ }
+ },
},
};
</script>
@@ -194,7 +182,7 @@ export default {
>
<div class="row gl-mb-3">
<div class="col-12">
- <issuable-title-field ref="title" v-model="formData.title" />
+ <issuable-title-field ref="title" v-model="formData.title" @input="updateTitleDraft" />
</div>
</div>
<div class="row">
@@ -220,6 +208,7 @@ export default {
:markdown-docs-path="markdownDocsPath"
:can-attach-file="canAttachFile"
:enable-autocomplete="enableAutocomplete"
+ @input="updateDescriptionDraft"
/>
<edit-actions :endpoint="endpoint" :form-state="formState" :issuable-type="issuableType" />
diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue
index adf449aca7b..74d166f82bb 100644
--- a/app/assets/javascripts/issues/show/components/header_actions.vue
+++ b/app/assets/javascripts/issues/show/components/header_actions.vue
@@ -229,7 +229,7 @@ export default {
</script>
<template>
- <div class="detail-page-header-actions gl-display-flex">
+ <div class="detail-page-header-actions gl-display-flex gl-align-self-start">
<gl-dropdown
v-if="hasMobileDropdown"
class="gl-sm-display-none! w-100"
diff --git a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
index dd84a1d7d67..5725d0f8d6a 100644
--- a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
+++ b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
@@ -52,9 +52,6 @@ export default {
loading() {
return this.$apollo.queries.alert.loading;
},
- incidentTabEnabled() {
- return this.glFeatures.incidentTimeline;
- },
},
mounted() {
this.trackPageViews();
@@ -112,7 +109,7 @@ export default {
>
<alert-details-table :alert="alert" :loading="loading" />
</gl-tab>
- <timeline-tab v-if="incidentTabEnabled" />
+ <timeline-tab />
</gl-tabs>
</div>
</template>
diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue
index b7ae18372ab..55cd8b5f606 100644
--- a/app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue
+++ b/app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue
@@ -74,6 +74,9 @@ export default {
return utcDate.toISOString();
},
+ hasTimelineText() {
+ return this.timelineText.length > 0;
+ },
},
mounted() {
this.focusDate();
@@ -167,6 +170,8 @@ export default {
variant="confirm"
category="primary"
class="gl-mr-3"
+ data-testid="save-button"
+ :disabled="!hasTimelineText"
:loading="isEventProcessed"
@click="handleSave(false)"
>
@@ -177,6 +182,8 @@ export default {
variant="confirm"
category="secondary"
class="gl-mr-3 gl-ml-n2"
+ data-testid="save-and-add-button"
+ :disabled="!hasTimelineText"
:loading="isEventProcessed"
@click="handleSave(true)"
>
diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js
index e5eed9f6b79..3cb5007ab0d 100644
--- a/app/assets/javascripts/issues/show/index.js
+++ b/app/assets/javascripts/issues/show/index.js
@@ -60,6 +60,7 @@ export function initIncidentApp(issueData = {}) {
projectId,
slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
+ contentEditorOnIssues: gon.features.contentEditorOnIssues,
},
render(createElement) {
return createElement(IssueApp, {
diff --git a/app/assets/javascripts/jobs/components/table/constants.js b/app/assets/javascripts/jobs/components/table/constants.js
index 853834ed51d..f73241aed6b 100644
--- a/app/assets/javascripts/jobs/components/table/constants.js
+++ b/app/assets/javascripts/jobs/components/table/constants.js
@@ -1,5 +1,4 @@
import { s__, __ } from '~/locale';
-import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
/* Error constants */
export const POST_FAILURE = 'post_failure';
@@ -29,62 +28,46 @@ export const PLAY_JOB_CONFIRMATION_MESSAGE = s__(
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,
+ tdClass: 'gl-display-none! gl-lg-display-table-cell!',
columnClass: 'gl-w-10p',
},
{
key: 'actions',
label: '',
- ...defaultTableClasses,
columnClass: 'gl-w-10p',
},
];
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
index 0a4757d11a8..3209fc4b90d 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlAlert, GlSkeletonLoader, GlIntersectionObserver, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { setUrlParams, updateHistory, queryToObject } from '~/lib/utils/url_utility';
import JobsFilteredSearch from '../filtered_search/jobs_filtered_search.vue';
import { validateQueryString } from '../filtered_search/utils';
@@ -134,7 +134,7 @@ export default {
// when a user enters raw text we alert them that it is
// not supported and we do not make an additional API call
if (!filter.type) {
- createFlash({
+ createAlert({
message: RAW_TEXT_WARNING,
type: 'warning',
});
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index 927ba7c7e1e..272181f830c 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -100,7 +100,7 @@ export const receiveJobSuccess = ({ commit }, data = {}) => {
};
export const receiveJobError = ({ commit }) => {
commit(types.RECEIVE_JOB_ERROR);
- createFlash({
+ createAlert({
message: __('An error occurred while fetching the job.'),
});
resetFavicon();
@@ -205,14 +205,14 @@ export const receiveJobLogSuccess = ({ commit }, log) => commit(types.RECEIVE_JO
export const receiveJobLogError = ({ dispatch }) => {
dispatch('stopPollingJobLog');
- createFlash({
+ createAlert({
message: __('An error occurred while fetching the job log.'),
});
};
export const receiveJobLogUnauthorizedError = ({ dispatch }) => {
dispatch('stopPollingJobLog');
- createFlash({
+ createAlert({
message: __('The current user is not authorized to access the job log.'),
});
};
@@ -254,7 +254,7 @@ export const receiveJobsForStageSuccess = ({ commit }, data) =>
export const receiveJobsForStageError = ({ commit }) => {
commit(types.RECEIVE_JOBS_FOR_STAGE_ERROR);
- createFlash({
+ createAlert({
message: __('An error occurred while fetching the jobs.'),
});
};
@@ -271,7 +271,7 @@ export const triggerManualJob = ({ state }, variables) => {
job_variables_attributes: parsedVariables,
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while triggering the job.'),
}),
);
diff --git a/app/assets/javascripts/labels/components/promote_label_modal.vue b/app/assets/javascripts/labels/components/promote_label_modal.vue
index 8598500c842..1b99a094c48 100644
--- a/app/assets/javascripts/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/labels/components/promote_label_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlSprintf, GlModal } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
@@ -70,7 +70,7 @@ export default {
labelUrl: this.url,
successful: false,
});
- createFlash({
+ createAlert({
message: error,
});
});
diff --git a/app/assets/javascripts/labels/group_label_subscription.js b/app/assets/javascripts/labels/group_label_subscription.js
index ea69e6585e6..c4f80d32a83 100644
--- a/app/assets/javascripts/labels/group_label_subscription.js
+++ b/app/assets/javascripts/labels/group_label_subscription.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { __ } from '~/locale';
import { fixTitle, hide } from '~/tooltips';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
const tooltipTitles = {
@@ -31,7 +31,7 @@ export default class GroupLabelSubscription {
this.$unsubscribeButtons.removeAttr('data-url');
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was an error when unsubscribing from this label.'),
}),
);
@@ -50,7 +50,7 @@ export default class GroupLabelSubscription {
.then(() => GroupLabelSubscription.setNewTooltip($btn))
.then(() => this.toggleSubscriptionButtons())
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was an error when subscribing to this label.'),
}),
);
diff --git a/app/assets/javascripts/labels/label_manager.js b/app/assets/javascripts/labels/label_manager.js
index 1927ac6e1ec..be515869bff 100644
--- a/app/assets/javascripts/labels/label_manager.js
+++ b/app/assets/javascripts/labels/label_manager.js
@@ -3,7 +3,7 @@
import $ from 'jquery';
import Sortable from 'sortablejs';
import { dispose } from '~/tooltips';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -112,7 +112,7 @@ export default class LabelManager {
onPrioritySortUpdate() {
this.savePrioritySort().catch(() =>
- createFlash({
+ createAlert({
message: this.errorMessage,
}),
);
@@ -127,7 +127,7 @@ export default class LabelManager {
rollbackLabelPosition($label, originalAction) {
const action = originalAction === 'remove' ? 'add' : 'remove';
this.toggleLabelPriority($label, action, false);
- createFlash({
+ createAlert({
message: this.errorMessage,
});
}
diff --git a/app/assets/javascripts/labels/labels_select.js b/app/assets/javascripts/labels/labels_select.js
index 51fedac339b..65dda804a20 100644
--- a/app/assets/javascripts/labels/labels_select.js
+++ b/app/assets/javascripts/labels/labels_select.js
@@ -6,7 +6,7 @@ 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 { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { sprintf, __ } from '~/locale';
import CreateLabelDropdown from './create_label_dropdown';
@@ -146,7 +146,7 @@ export default class LabelsSelect {
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error saving label update.'),
}),
);
@@ -185,7 +185,7 @@ export default class LabelsSelect {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error fetching labels.'),
}),
);
diff --git a/app/assets/javascripts/labels/project_label_subscription.js b/app/assets/javascripts/labels/project_label_subscription.js
index b2612e9ede0..9ca6ee5609c 100644
--- a/app/assets/javascripts/labels/project_label_subscription.js
+++ b/app/assets/javascripts/labels/project_label_subscription.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { fixTitle } from '~/tooltips';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -61,7 +61,7 @@ export default class ProjectLabelSubscription {
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was an error subscribing to this label.'),
}),
);
diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js
index 6f24590f9e7..27760e483aa 100644
--- a/app/assets/javascripts/lib/dompurify.js
+++ b/app/assets/javascripts/lib/dompurify.js
@@ -3,12 +3,21 @@ import { getNormalizedURL, getBaseURL, relativePathToAbsolute } from '~/lib/util
const { sanitize: dompurifySanitize, addHook, isValidAttribute } = DOMPurify;
-const defaultConfig = {
+export const defaultConfig = {
// Safely allow SVG <use> tags
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'],
+ FORBID_ATTR: [
+ 'data-remote',
+ 'data-url',
+ 'data-type',
+ 'data-method',
+ 'data-disable-with',
+ 'data-disabled',
+ 'data-disable',
+ 'data-turbo',
+ ],
FORBID_TAGS: ['style', 'mstyle'],
ALLOW_UNKNOWN_PROTOCOLS: true,
};
diff --git a/app/assets/javascripts/lib/utils/autosave.js b/app/assets/javascripts/lib/utils/autosave.js
index dac1da743a2..01316be06a2 100644
--- a/app/assets/javascripts/lib/utils/autosave.js
+++ b/app/assets/javascripts/lib/utils/autosave.js
@@ -1,8 +1,27 @@
+import { isString } from 'lodash';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+const normalizeKey = (autosaveKey) => {
+ let normalizedKey;
+
+ if (Array.isArray(autosaveKey) && autosaveKey.every(isString)) {
+ normalizedKey = autosaveKey.join('/');
+ } else if (isString(autosaveKey)) {
+ normalizedKey = autosaveKey;
+ } else {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ throw new Error('Invalid autosave key');
+ }
+
+ return `autosave/${normalizedKey}`;
+};
+
+const lockVersionKey = (autosaveKey) => `${normalizeKey(autosaveKey)}/lockVersion`;
+
export const clearDraft = (autosaveKey) => {
try {
- window.localStorage.removeItem(`autosave/${autosaveKey}`);
+ window.localStorage.removeItem(normalizeKey(autosaveKey));
+ window.localStorage.removeItem(lockVersionKey(autosaveKey));
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
@@ -11,7 +30,17 @@ export const clearDraft = (autosaveKey) => {
export const getDraft = (autosaveKey) => {
try {
- return window.localStorage.getItem(`autosave/${autosaveKey}`);
+ return window.localStorage.getItem(normalizeKey(autosaveKey));
+ } catch (e) {
+ // eslint-disable-next-line no-console
+ console.error(e);
+ return null;
+ }
+};
+
+export const getLockVersion = (autosaveKey) => {
+ try {
+ return window.localStorage.getItem(lockVersionKey(autosaveKey));
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
@@ -19,9 +48,12 @@ export const getDraft = (autosaveKey) => {
}
};
-export const updateDraft = (autosaveKey, text) => {
+export const updateDraft = (autosaveKey, text, lockVersion) => {
try {
- window.localStorage.setItem(`autosave/${autosaveKey}`, text);
+ window.localStorage.setItem(normalizeKey(autosaveKey), text);
+ if (lockVersion) {
+ window.localStorage.setItem(lockVersionKey(autosaveKey), lockVersion);
+ }
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 7925a10344a..4448a106bb6 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -60,6 +60,15 @@ export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventNa
});
};
+/**
+ * Return the given element's offset height, or 0 if the element doesn't exist.
+ * Probably not useful outside of handleLocationHash.
+ *
+ * @param {HTMLElement} element The element to measure.
+ * @returns {number} The element's offset height.
+ */
+const getElementOffsetHeight = (element) => element?.offsetHeight ?? 0;
+
// automatically adjust scroll position for hash urls taking the height of the navbar into account
// https://github.com/twitter/bootstrap/issues/1768
export const handleLocationHash = () => {
@@ -84,40 +93,26 @@ export const handleLocationHash = () => {
const fixedIssuableTitle = document.querySelector('.issue-sticky-header');
let adjustment = 0;
- if (fixedNav) adjustment -= fixedNav.offsetHeight;
-
- if (target && target.scrollIntoView) {
- target.scrollIntoView(true);
- }
- if (fixedTabs) {
- adjustment -= fixedTabs.offsetHeight;
- }
-
- if (fixedDiffStats) {
- adjustment -= fixedDiffStats.offsetHeight;
- }
-
- if (performanceBar) {
- adjustment -= performanceBar.offsetHeight;
- }
-
- if (diffFileHeader) {
- adjustment -= diffFileHeader.offsetHeight;
- }
-
- if (versionMenusContainer) {
- adjustment -= versionMenusContainer.offsetHeight;
- }
+ adjustment -= getElementOffsetHeight(fixedNav);
+ adjustment -= getElementOffsetHeight(fixedTabs);
+ adjustment -= getElementOffsetHeight(fixedDiffStats);
+ adjustment -= getElementOffsetHeight(performanceBar);
+ adjustment -= getElementOffsetHeight(diffFileHeader);
+ adjustment -= getElementOffsetHeight(versionMenusContainer);
if (isInIssuePage()) {
- adjustment -= fixedIssuableTitle.offsetHeight;
+ adjustment -= getElementOffsetHeight(fixedIssuableTitle);
}
if (isInMRPage()) {
adjustment -= topPadding;
}
+ if (target?.scrollIntoView) {
+ target.scrollIntoView(true);
+ }
+
setTimeout(() => {
window.scrollBy(0, adjustment);
});
@@ -172,7 +167,7 @@ export const contentTop = () => {
return size;
},
- () => getOuterHeight('.merge-request-tabs'),
+ () => getOuterHeight('.merge-request-sticky-header, .merge-request-tabs'),
() => getOuterHeight('.js-diff-files-changed'),
() => getOuterHeight('.issue-sticky-header.gl-fixed'),
({ desktop }) => {
@@ -180,7 +175,9 @@ export const contentTop = () => {
let size;
if (desktop && diffsTabIsActive) {
- size = getOuterHeight('.diff-file .file-title-flex-parent:not([style="display:none"])');
+ size = getOuterHeight(
+ '.diffs .diff-file .file-title-flex-parent:not([style="display:none"])',
+ );
}
return size;
diff --git a/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js
index 6c5d4ecc901..c11cf1a7882 100644
--- a/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js
@@ -271,24 +271,6 @@ export const secondsToMilliseconds = (seconds) => seconds * 1000;
export const secondsToDays = (seconds) => Math.round(seconds / 86400);
/**
- * Converts a numeric utc offset in seconds to +/- hours
- * ie -32400 => -9 hours
- * ie -12600 => -3.5 hours
- *
- * @param {Number} offset UTC offset in seconds as a integer
- *
- * @return {String} the + or - offset in hours
- */
-export const secondsToHours = (offset) => {
- const parsed = parseInt(offset, 10);
- if (Number.isNaN(parsed) || parsed === 0) {
- return `0`;
- }
- const num = offset / 3600;
- return parseInt(num, 10) !== num ? num.toFixed(1) : num;
-};
-
-/**
* Returns the date `n` days after the date provided
*
* @param {Date} date the initial date
diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
index d07abb72210..737c18d1bce 100644
--- a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
@@ -406,3 +406,29 @@ export const durationTimeFormatted = (duration) => {
return `${hh}:${mm}:${ss}`;
};
+
+/**
+ * Converts a numeric utc offset in seconds to +/- hours
+ * ie -32400 => -9 hours
+ * ie -12600 => -3.5 hours
+ *
+ * @param {Number} offset UTC offset in seconds as a integer
+ *
+ * @return {String} the + or - offset in hours, e.g. `- 10`, `0`, `+ 4`
+ */
+export const formatUtcOffset = (offset) => {
+ const parsed = parseInt(offset, 10);
+ if (Number.isNaN(parsed) || parsed === 0) {
+ return `0`;
+ }
+ const prefix = offset > 0 ? '+' : '-';
+ return `${prefix} ${Math.abs(offset / 3600)}`;
+};
+
+/**
+ * Returns formatted timezone
+ *
+ * @param {Object} timezone item with offset and name
+ * @returns {String} the UTC timezone with the offset, e.g. `[UTC + 2] Berlin`
+ */
+export const formatTimezone = ({ offset, name }) => `[UTC ${formatUtcOffset(offset)}] ${name}`;
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 48be8af3ff6..3894ec36a0b 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -391,13 +391,15 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo
/**
* Indents selected lines to the right by 2 spaces
*
- * @param {Object} textArea - the targeted text area
+ * @param {Object} textArea - jQuery object with the targeted text area
*/
-function indentLines(textArea) {
+function indentLines($textArea) {
+ const textArea = $textArea.get(0);
const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);
const shiftedLines = [];
let totalAdded = 0;
+ textArea.focus();
textArea.setSelectionRange(startPos, endPos);
lines.forEach((line) => {
@@ -418,13 +420,15 @@ function indentLines(textArea) {
*
* @param {Object} textArea - the targeted text area
*/
-function outdentLines(textArea) {
+function outdentLines($textArea) {
+ const textArea = $textArea.get(0);
const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);
const shiftedLines = [];
let totalRemoved = 0;
let removedFromFirstline = -1;
let removedFromLine = 0;
+ textArea.focus();
textArea.setSelectionRange(startPos, endPos);
lines.forEach((line) => {
@@ -460,28 +464,10 @@ function outdentLines(textArea) {
);
}
-function handleIndentOutdent(e, textArea) {
- if (e.altKey || e.ctrlKey || e.shiftKey) return;
- if (!e.metaKey) return;
-
- switch (e.key) {
- case ']':
- e.preventDefault();
- indentLines(textArea);
- break;
- case '[':
- e.preventDefault();
- outdentLines(textArea);
- break;
- default:
- break;
- }
-}
-
/* eslint-disable @gitlab/require-i18n-strings */
function handleSurroundSelectedText(e, textArea) {
if (!gon.markdown_surround_selection) return;
- if (e.metaKey) return;
+ if (e.metaKey || e.ctrlKey) return;
if (textArea.selectionStart === textArea.selectionEnd) return;
const keys = {
@@ -532,6 +518,7 @@ function continueOlText(listLineMatch, nextLineMatch) {
}
function handleContinueList(e, textArea) {
+ if (!gon.markdown_automatic_lists) return;
if (!(e.key === 'Enter')) return;
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
if (textArea.selectionStart !== textArea.selectionEnd) return;
@@ -586,7 +573,6 @@ export function keypressNoteText(e) {
if ($(textArea).atwho?.('isSelecting')) return;
- handleIndentOutdent(e, textArea);
handleContinueList(e, textArea);
handleSurroundSelectedText(e, textArea);
}
@@ -600,15 +586,26 @@ export function compositionEndNoteText() {
}
export function updateTextForToolbarBtn($toolbarBtn) {
- return updateText({
- textArea: $toolbarBtn.closest('.md-area').find('textarea'),
- tag: $toolbarBtn.data('mdTag'),
- cursorOffset: $toolbarBtn.data('mdCursorOffset'),
- blockTag: $toolbarBtn.data('mdBlock'),
- wrap: !$toolbarBtn.data('mdPrepend'),
- select: $toolbarBtn.data('mdSelect'),
- tagContent: $toolbarBtn.attr('data-md-tag-content'),
- });
+ const $textArea = $toolbarBtn.closest('.md-area').find('textarea');
+
+ switch ($toolbarBtn.data('mdCommand')) {
+ case 'indentLines':
+ indentLines($textArea);
+ break;
+ case 'outdentLines':
+ outdentLines($textArea);
+ break;
+ default:
+ return updateText({
+ textArea: $textArea,
+ tag: $toolbarBtn.data('mdTag'),
+ cursorOffset: $toolbarBtn.data('mdCursorOffset'),
+ blockTag: $toolbarBtn.data('mdBlock'),
+ wrap: !$toolbarBtn.data('mdPrepend'),
+ select: $toolbarBtn.data('mdSelect'),
+ tagContent: $toolbarBtn.attr('data-md-tag-content'),
+ });
+ }
}
export function addMarkdownListeners(form) {
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 59645d50e29..367180714df 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -1,5 +1,5 @@
import { isString, memoize } from 'lodash';
-
+import { base64ToBuffer, bufferToBase64 } from '~/authentication/webauthn/util';
import {
TRUNCATE_WIDTH_DEFAULT_WIDTH,
TRUNCATE_WIDTH_DEFAULT_FONT_SIZE,
@@ -513,3 +513,15 @@ export const limitedCounterWithDelimiter = (count) => {
return count > limit ? '1,000+' : count;
};
+
+// Encoding UTF8 ⇢ base64
+export function base64EncodeUnicode(str) {
+ const encoder = new TextEncoder('utf8');
+ return bufferToBase64(encoder.encode(str));
+}
+
+// Decoding base64 ⇢ UTF8
+export function base64DecodeUnicode(str) {
+ const decoder = new TextDecoder('utf8');
+ return decoder.decode(base64ToBuffer(str));
+}
diff --git a/app/assets/javascripts/listbox/index.js b/app/assets/javascripts/listbox/index.js
index f63171e2785..7eacbf7fcdd 100644
--- a/app/assets/javascripts/listbox/index.js
+++ b/app/assets/javascripts/listbox/index.js
@@ -1,4 +1,4 @@
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlListbox } from '@gitlab/ui';
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
@@ -31,37 +31,25 @@ export function initListbox(el, { onChange } = {}) {
},
},
render(h) {
- return h(
- GlDropdown,
- {
- props: {
- text: this.text,
- right,
+ return h(GlListbox, {
+ props: {
+ items,
+ right,
+ selected: this.selected,
+ toggleText: this.text,
+ },
+ class: className,
+ on: {
+ select: (selectedValue) => {
+ this.selected = selectedValue;
+ const selectedItem = items.find(({ value }) => value === selectedValue);
+
+ if (typeof onChange === 'function') {
+ onChange(selectedItem);
+ }
},
- class: className,
},
- items.map((item) =>
- h(
- GlDropdownItem,
- {
- props: {
- isCheckItem: true,
- isChecked: this.selected === item.value,
- },
- on: {
- click: () => {
- this.selected = item.value;
-
- if (typeof onChange === 'function') {
- onChange(item);
- }
- },
- },
- },
- item.text,
- ),
- ),
- );
+ });
},
});
}
diff --git a/app/assets/javascripts/logo.js b/app/assets/javascripts/logo.js
index c570f8810a8..ca3f1caec67 100644
--- a/app/assets/javascripts/logo.js
+++ b/app/assets/javascripts/logo.js
@@ -1,5 +1,5 @@
export default function initLogoAnimation() {
window.addEventListener('beforeunload', () => {
- document.querySelector('.tanuki-logo').classList.add('animate');
+ document.querySelector('.tanuki-logo')?.classList.add('animate');
});
}
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index c16ed68096d..8e4ebd510aa 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -21,7 +21,7 @@ import initTodoToggle from './header';
import initLayoutNav from './layout_nav';
import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
import { localTimeAgo } from './lib/utils/datetime/timeago_utility';
-import { getLocationHash, visitUrl } from './lib/utils/url_utility';
+import { getLocationHash, visitUrl, mergeUrlParams } from './lib/utils/url_utility';
// everything else
import initFeatureHighlight from './feature_highlight';
@@ -250,11 +250,10 @@ $('form.filter-form').on('submit', function filterFormSubmitCallback(event) {
const link = document.createElement('a');
link.href = this.action;
- const action = `${this.action}${link.search === '' ? '?' : '&'}`;
+ const action = mergeUrlParams(Object.fromEntries(new FormData(this)), this.action);
event.preventDefault();
- // eslint-disable-next-line no-jquery/no-serialize
- visitUrl(`${action}${$(this).serialize()}`);
+ visitUrl(action);
});
const flashContainer = document.querySelector('.flash-container');
diff --git a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
index ce28283ccdf..01f145e0862 100644
--- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
+++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
@@ -4,6 +4,7 @@ import { mapState } from 'vuex';
import { visitUrl } from '~/lib/utils/url_utility';
import { FIELDS } from '~/members/constants';
import { parseSortParam, buildSortHref } from '~/members/utils';
+import { SORT_DIRECTION_UI } from '~/search/sort/constants';
export default {
name: 'SortDropdown',
@@ -30,6 +31,9 @@ export default {
isAscending() {
return !this.sort.sortDesc;
},
+ sortDirectionData() {
+ return this.isAscending ? SORT_DIRECTION_UI.asc : SORT_DIRECTION_UI.desc;
+ },
filteredOptions() {
return FIELDS.filter(
(field) => this.tableSortableFields.includes(field.key) && field.sort,
@@ -70,7 +74,7 @@ export default {
data-testid="members-sort-dropdown"
:text="activeOptionLabel"
:is-ascending="isAscending"
- :sort-direction-tool-tip="__('Sort direction')"
+ :sort-direction-tool-tip="sortDirectionData.tooltip"
@sortDirectionChange="handleSortDirectionChange"
>
<gl-sorting-item
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index 460dc0041ab..0512bc04085 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -2,7 +2,7 @@
import { GlTable, GlBadge, GlPagination } from '@gitlab/ui';
import { mapState } from 'vuex';
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
-import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils';
+import { canUnban, canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import UserDate from '~/vue_shared/components/user_date.vue';
import {
@@ -90,7 +90,8 @@ export default {
canRemove(member) ||
canResend(member) ||
canUpdate(member, this.currentUserId) ||
- canOverride(member)
+ canOverride(member) ||
+ canUnban(member)
);
},
showField(field) {
diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js
index 0da44b7d468..bf87ab53d36 100644
--- a/app/assets/javascripts/members/utils.js
+++ b/app/assets/javascripts/members/utils.js
@@ -105,9 +105,12 @@ export const buildSortHref = ({
return setUrlParams({ ...filterParams, sort: sortParam }, window.location.href, true);
};
-// Defined in `ee/app/assets/javascripts/vue_shared/components/members/utils.js`
+// Defined in `ee/app/assets/javascripts/members/utils.js`
export const canOverride = () => false;
+// Defined in `ee/app/assets/javascripts/members/utils.js`
+export const canUnban = () => false;
+
export const parseDataAttributes = (el) => {
const { membersData } = el.dataset;
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
index 7168efa28ad..707e8a0645f 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
@@ -2,7 +2,7 @@
import { GlButton } from '@gitlab/ui';
import { debounce } from 'lodash';
import { mapActions } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import { INTERACTIVE_RESOLVE_MODE } from '../constants';
@@ -75,7 +75,7 @@ export default {
},
)
.catch(() => {
- createFlash({
+ createAlert({
message: __('An error occurred while loading the file'),
});
});
diff --git a/app/assets/javascripts/merge_conflicts/store/actions.js b/app/assets/javascripts/merge_conflicts/store/actions.js
index 9c101da52f5..f84eaabf9e7 100644
--- a/app/assets/javascripts/merge_conflicts/store/actions.js
+++ b/app/assets/javascripts/merge_conflicts/store/actions.js
@@ -1,5 +1,5 @@
import { setCookie } from '~/lib/utils/common_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import { INTERACTIVE_RESOLVE_MODE, EDIT_RESOLVE_MODE } from '../constants';
@@ -33,7 +33,7 @@ export const submitResolvedConflicts = async ({ commit, getters }, resolveConfli
window.location.assign(data.redirect_to);
} catch (e) {
commit(types.SET_SUBMIT_STATE, false);
- createFlash({ message: __('Failed to save merge conflicts resolutions. Please try again!') });
+ createAlert({ message: __('Failed to save merge conflicts resolutions. Please try again!') });
}
};
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 8cdb9eb5fc4..57b5e9809d2 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, no-underscore-dangle, consistent-return */
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -44,7 +44,7 @@ function MergeRequest(opts) {
}
},
onError: () => {
- createFlash({
+ createAlert({
message: __(
'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
),
@@ -98,7 +98,7 @@ MergeRequest.prototype.initMRBtnListeners = function () {
MergeRequest.toggleDraftStatus(data.title, wipEvent === 'ready');
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
})
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 0b53a8ede64..17ee2a0d8b6 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,12 +1,12 @@
/* eslint-disable no-new, class-methods-use-this */
import $ from 'jquery';
import Vue from 'vue';
+import { createAlert } from '~/flash';
import { getCookie, isMetaClick, parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
import { parseUrlPathname } from '~/lib/utils/url_utility';
import createEventHub from '~/helpers/event_hub_factory';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import Diff from './diff';
-import createFlash from './flash';
import { initDiffStatsDropdown } from './init_diff_stats_dropdown';
import axios from './lib/utils/axios_utils';
@@ -447,7 +447,7 @@ export default class MergeRequestTabs {
.then((m) => m.default())
.catch(() => {
toggleLoader(false);
- createFlash({
+ createAlert({
message: __('An error occurred while fetching this tab.'),
});
});
@@ -480,7 +480,7 @@ export default class MergeRequestTabs {
this.diffsLoaded = true;
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('An error occurred while fetching this tab.'),
});
})
diff --git a/app/assets/javascripts/merge_requests/components/sticky_header.vue b/app/assets/javascripts/merge_requests/components/sticky_header.vue
index f067982fce1..b7629ba001f 100644
--- a/app/assets/javascripts/merge_requests/components/sticky_header.vue
+++ b/app/assets/javascripts/merge_requests/components/sticky_header.vue
@@ -86,6 +86,7 @@ export default {
<template>
<gl-intersection-observer
+ class="gl-relative gl-top-2"
@appear="setStickyHeaderVisible(false)"
@disappear="setStickyHeaderVisible(true)"
>
diff --git a/app/assets/javascripts/milestones/components/promote_milestone_modal.vue b/app/assets/javascripts/milestones/components/promote_milestone_modal.vue
index cac6d722ced..9e537fa2c82 100644
--- a/app/assets/javascripts/milestones/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/milestones/components/promote_milestone_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlModal } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
@@ -63,7 +63,7 @@ export default {
visitUrl(response.data.url);
})
.catch((error) => {
- createFlash({
+ createAlert({
message: error,
});
})
diff --git a/app/assets/javascripts/milestones/milestone.js b/app/assets/javascripts/milestones/milestone.js
index 8f2721c2a5b..d9e72340d62 100644
--- a/app/assets/javascripts/milestones/milestone.js
+++ b/app/assets/javascripts/milestones/milestone.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -34,7 +34,7 @@ export default class Milestone {
this.loadedTabs.add(tab);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error loading milestone tab'),
}),
);
diff --git a/app/assets/javascripts/milestones/milestone_select.js b/app/assets/javascripts/milestones/milestone_select.js
index c95ec3dd10b..d4876c3dbe8 100644
--- a/app/assets/javascripts/milestones/milestone_select.js
+++ b/app/assets/javascripts/milestones/milestone_select.js
@@ -121,7 +121,7 @@ export default class MilestoneSelect {
title: __('Started'),
});
}
- if (extraOptions.length) {
+ if (extraOptions.length && data.length) {
extraOptions.push({ type: 'divider' });
}
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
index 5bf08be1ead..2995f19c470 100644
--- a/app/assets/javascripts/mirrors/mirror_repos.js
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import { hide } from '~/tooltips';
@@ -120,7 +120,7 @@ export default class MirrorRepos {
.put(this.mirrorEndpoint, payload)
.then(() => this.removeRow($target))
.catch(() =>
- createFlash({
+ createAlert({
message: __('Failed to remove mirror.'),
}),
);
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
index eb7c43034a4..3b7e5a5f2ee 100644
--- a/app/assets/javascripts/mirrors/ssh_mirror.js
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { escape } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { backOff } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
@@ -115,7 +115,7 @@ export default class SSHMirror {
const failureMessage = response.data
? response.data.message
: __('An error occurred while detecting host keys');
- createFlash({
+ createAlert({
message: failureMessage,
});
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index e3fcdf716d4..b6ad2d21757 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -11,7 +11,7 @@ import {
import Mousetrap from 'mousetrap';
import VueDraggable from 'vuedraggable';
import { mapActions, mapState, mapGetters } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import invalidUrl from '~/lib/utils/invalid_url';
import { ESC_KEY } from '~/lib/utils/keys';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
@@ -176,7 +176,7 @@ export default {
this.setExpandedPanel(expandedPanel);
}
} catch {
- createFlash({
+ createAlert({
message: s__(
'Metrics|Link contains invalid chart information, please verify the link to see the expanded panel.',
),
@@ -201,7 +201,7 @@ export default {
* This watcher is set for future SPA behaviour of the dashboard
*/
if (hasWarnings) {
- createFlash({
+ createAlert({
message: s__(
'Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema.',
),
@@ -319,7 +319,7 @@ export default {
this.isRearrangingPanels = isRearrangingPanels;
},
onDateTimePickerInvalid() {
- createFlash({
+ createAlert({
message: s__(
'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
),
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 5c99dbc0d98..0ef365c6368 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/browser';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
@@ -134,7 +134,7 @@ export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
if (state.showErrorBanner) {
if (error.response.data && error.response.data.message) {
const { message } = error.response.data;
- createFlash({
+ createAlert({
message: sprintf(
s__('Metrics|There was an error while retrieving metrics. %{message}'),
{ message },
@@ -142,7 +142,7 @@ export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
),
});
} else {
- createFlash({
+ createAlert({
message: s__('Metrics|There was an error while retrieving metrics'),
});
}
@@ -176,7 +176,7 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
dispatch('fetchDeploymentsData');
if (!state.timeRange) {
- createFlash({
+ createAlert({
message: s__(`Metrics|Invalid time range, please verify.`),
type: 'warning',
});
@@ -207,7 +207,7 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
});
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__(`Metrics|There was an error while retrieving metrics`),
type: 'warning',
});
@@ -246,7 +246,7 @@ export const fetchPrometheusMetric = (
Sentry.captureException(error);
commit(types.RECEIVE_METRIC_RESULT_FAILURE, { metricId: metric.metricId, error });
- // Continue to throw error so the dashboard can notify using createFlash
+ // Continue to throw error so the dashboard can notify using createAlert
throw error;
});
};
@@ -262,7 +262,7 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
.then((resp) => resp.data)
.then((response) => {
if (!response || !response.deployments) {
- createFlash({
+ createAlert({
message: s__('Metrics|Unexpected deployment data response from prometheus endpoint'),
});
}
@@ -272,7 +272,7 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
.catch((error) => {
Sentry.captureException(error);
dispatch('receiveDeploymentsDataFailure');
- createFlash({
+ createAlert({
message: s__('Metrics|There was an error getting deployment information.'),
});
});
@@ -302,7 +302,7 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
)
.then((environments) => {
if (!environments) {
- createFlash({
+ createAlert({
message: s__(
'Metrics|There was an error fetching the environments data, please try again',
),
@@ -314,7 +314,7 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveEnvironmentsDataFailure');
- createFlash({
+ createAlert({
message: s__('Metrics|There was an error getting environments information.'),
});
});
@@ -348,7 +348,7 @@ export const fetchAnnotations = ({ state, dispatch, getters }) => {
.then(parseAnnotationsResponse)
.then((annotations) => {
if (!annotations) {
- createFlash({
+ createAlert({
message: s__('Metrics|There was an error fetching annotations. Please try again.'),
});
}
@@ -358,7 +358,7 @@ export const fetchAnnotations = ({ state, dispatch, getters }) => {
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveAnnotationsFailure');
- createFlash({
+ createAlert({
message: s__('Metrics|There was an error getting annotations information.'),
});
});
@@ -397,7 +397,7 @@ export const fetchDashboardValidationWarnings = ({ state, dispatch, getters }) =
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveDashboardValidationWarningsFailure');
- createFlash({
+ createAlert({
message: s__(
'Metrics|There was an error getting dashboard validation warnings information.',
),
@@ -502,7 +502,7 @@ export const fetchVariableMetricLabelValues = ({ state, commit }, { defaultQuery
commit(types.UPDATE_VARIABLE_METRIC_LABEL_VALUES, { variable, label, data });
})
.catch(() => {
- createFlash({
+ createAlert({
message: sprintf(
s__('Metrics|There was an error getting options for variable "%{name}".'),
{
@@ -569,7 +569,7 @@ export const fetchPanelPreviewMetrics = ({ state, commit }) => {
Sentry.captureException(error);
commit(types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_FAILURE, { index, error });
- // Continue to throw error so the panel builder can notify using createFlash
+ // Continue to throw error so the panel builder can notify using createAlert
throw error;
});
});
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index 297420bf94d..c32a1f4c2ac 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -6,7 +6,6 @@ import initDiffsApp from '../diffs';
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
import MergeRequest from '../merge_request';
import DiscussionCounter from '../notes/components/discussion_counter.vue';
-import initDiscussionFilters from '../notes/discussion_filters';
import initNotesApp from './init_notes';
export default function initMrNotes() {
@@ -49,7 +48,5 @@ export default function initMrNotes() {
},
});
}
-
- initDiscussionFilters(store);
});
}
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
index e4a7a7bd9fc..3a67e7925c3 100644
--- a/app/assets/javascripts/mr_notes/init_notes.js
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -5,19 +5,27 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import store from '~/mr_notes/stores';
import discussionNavigator from '../notes/components/discussion_navigator.vue';
import NotesApp from '../notes/components/notes_app.vue';
+import { getNotesFilterData } from '../notes/utils/get_notes_filter_data';
import initWidget from '../vue_merge_request_widget';
export default () => {
+ const el = document.getElementById('js-vue-mr-discussions');
+ if (!el) {
+ return;
+ }
+
+ const notesFilterProps = getNotesFilterData(el);
+
// eslint-disable-next-line no-new
new Vue({
- el: '#js-vue-mr-discussions',
+ el,
name: 'MergeRequestDiscussions',
components: {
NotesApp,
},
store,
data() {
- const notesDataset = document.getElementById('js-vue-mr-discussions').dataset;
+ const notesDataset = el.dataset;
const noteableData = JSON.parse(notesDataset.noteableData);
noteableData.noteableType = notesDataset.noteableType;
noteableData.targetType = notesDataset.targetType;
@@ -95,6 +103,7 @@ export default () => {
userData: this.currentUserData,
shouldShow: this.isShowTabActive,
helpPagePath: this.helpPagePath,
+ ...notesFilterProps,
},
}),
]);
diff --git a/app/assets/javascripts/namespaces/leave_by_url.js b/app/assets/javascripts/namespaces/leave_by_url.js
index e00c2abfbef..09757ce17fa 100644
--- a/app/assets/javascripts/namespaces/leave_by_url.js
+++ b/app/assets/javascripts/namespaces/leave_by_url.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { initRails } from '~/lib/utils/rails_ujs';
import { getParameterByName } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
@@ -18,7 +18,7 @@ export default function leaveByUrl(namespaceType) {
if (leaveLink) {
leaveLink.click();
} else {
- createFlash({
+ createAlert({
message: sprintf(__('You do not have permission to leave this %{namespaceType}.'), {
namespaceType,
}),
diff --git a/app/assets/javascripts/nav/components/top_nav_app.vue b/app/assets/javascripts/nav/components/top_nav_app.vue
index ca6e6567f74..e55bf25a60c 100644
--- a/app/assets/javascripts/nav/components/top_nav_app.vue
+++ b/app/assets/javascripts/nav/components/top_nav_app.vue
@@ -1,5 +1,6 @@
<script>
import { GlNav, GlIcon, GlNavItemDropdown, GlDropdownForm, GlTooltipDirective } from '@gitlab/ui';
+import Tracking from '~/tracking';
import TopNavDropdownMenu from './top_nav_dropdown_menu.vue';
export default {
@@ -19,6 +20,14 @@ export default {
required: true,
},
},
+ methods: {
+ trackToggleEvent() {
+ Tracking.event(undefined, 'click_nav', {
+ label: 'hamburger_menu',
+ property: 'top_navigation',
+ });
+ },
+ },
};
</script>
@@ -32,6 +41,7 @@ export default {
toggle-class="top-nav-toggle js-top-nav-dropdown-toggle gl-px-3!"
no-flip
no-caret
+ @toggle="trackToggleEvent"
>
<template #button-content>
<gl-icon name="hamburger" />
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index fdcea300388..5437a607e8a 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -44,7 +44,7 @@ export default {
sandbox
:srcdoc="rawCode"
frameborder="0"
- scrolling="no"
+ scrolling="auto"
width="100%"
class="gl-overflow-auto"
></iframe>
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index bf35d5c3b25..0d7ff022f8f 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -5,7 +5,7 @@ import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
import Autosave from '~/autosave';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { badgeState } from '~/issuable/components/status_box.vue';
import httpStatusCodes from '~/lib/utils/http_status';
import {
@@ -111,7 +111,10 @@ export default {
return this.getNoteableData.current_user.can_create_note;
},
canSetInternalNote() {
- return this.getNoteableData.current_user.can_update && (this.isIssue || this.isEpic);
+ return (
+ this.getNoteableData.current_user.can_create_confidential_note &&
+ (this.isIssue || this.isEpic)
+ );
},
issueActionButtonTitle() {
const openOrClose = this.isOpen ? 'close' : 'reopen';
@@ -276,7 +279,7 @@ export default {
.then(() => badgeState.updateStatus && badgeState.updateStatus())
.then(refreshUserMergeRequestCounts)
.catch(() =>
- createFlash({
+ createAlert({
message: constants.toggleStateErrorMessage[this.noteableType][this.openState],
}),
);
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index 1b1923a90f7..cf6474270a2 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -84,8 +84,8 @@ export default {
return sprintf(text, { commitDisplay, linkStart, linkEnd }, false);
},
- adaptiveAvatarSize() {
- return { default: 24, md: 32 };
+ toggleClass() {
+ return this.discussion.expanded ? 'expanded' : 'collapsed';
},
},
methods: {
@@ -98,16 +98,13 @@ export default {
</script>
<template>
- <div class="discussion-header gl-display-flex gl-align-items-center gl-p-5">
- <div
- v-once
- class="timeline-icon gl-align-self-start gl-flex-shrink-0 gl-flex-shrink gl-mx-3 gl-md-ml-2 gl-md-mr-5"
- >
+ <div class="discussion-header gl-display-flex gl-align-items-center">
+ <div v-once class="timeline-avatar gl-align-self-start gl-flex-shrink-0 gl-flex-shrink">
<gl-avatar-link v-if="author" :href="author.path">
- <gl-avatar :src="author.avatar_url" :alt="author.name" :size="adaptiveAvatarSize" />
+ <gl-avatar :src="author.avatar_url" :alt="author.name" :size="32" />
</gl-avatar-link>
</div>
- <div class="timeline-content w-100">
+ <div class="timeline-content w-100 gl-ml-3" :class="toggleClass">
<note-header
:author="author"
:created-at="firstNote.created_at"
@@ -123,14 +120,14 @@ export default {
:edited-at="discussion.resolved_at"
:edited-by="discussion.resolved_by"
:action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline gl-pl-2"
+ class-name="discussion-headline-light js-discussion-headline gl-pl-3"
/>
<note-edited-text
v-else-if="lastUpdatedAt"
:edited-at="lastUpdatedAt"
:edited-by="lastUpdatedBy"
:action-text="__('Last updated')"
- class-name="discussion-headline-light js-discussion-headline gl-pl-2"
+ class-name="discussion-headline-light js-discussion-headline gl-pl-3"
/>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 6521b86edbb..37935e9c3c6 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -81,16 +81,18 @@ export default {
:class="{
'gl-bg-orange-50': blocksMerge && !allResolved,
'gl-bg-gray-50': !blocksMerge || allResolved,
- 'gl-pr-2': !allResolved,
}"
data-testid="discussions-counter-text"
>
<template v-if="allResolved">
{{ __('All threads resolved!') }}
<gl-dropdown
+ v-gl-tooltip:discussionCounter.hover.bottom
size="small"
category="tertiary"
right
+ :title="__('Thread options')"
+ :aria-label="__('Thread options')"
toggle-class="btn-icon"
class="gl-pt-0! gl-px-2 gl-h-full gl-ml-2"
>
@@ -133,9 +135,12 @@ export default {
@click="jumpNext"
/>
<gl-dropdown
+ v-gl-tooltip:discussionCounter.hover.bottom
size="small"
category="tertiary"
right
+ :title="__('Thread options')"
+ :aria-label="__('Thread options')"
toggle-class="btn-icon"
class="gl-pt-0! gl-px-2"
>
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 8a42fb6bd85..21b48a2a666 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -168,7 +168,7 @@ export default {
id="discussion-preferences-dropdown"
class="full-width-mobile"
data-qa-selector="discussion_preferences_dropdown"
- text="Sort or filter"
+ :text="__('Sort or filter')"
:disabled="isLoading"
right
>
diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue
index 61af0b06535..39b3df899a5 100644
--- a/app/assets/javascripts/notes/components/discussion_filter_note.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue
@@ -31,7 +31,7 @@ export default {
<div class="timeline-icon d-none d-lg-flex">
<gl-icon name="comment" />
</div>
- <div class="timeline-content">
+ <div class="timeline-content gl-pl-8">
<div data-testid="discussion-filter-timeline-content">
<gl-sprintf :message="$options.i18n.information">
<template #bold="{ content }">
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index 6fcfa66ea49..2dbc9b10836 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -142,7 +142,7 @@ export default {
:edited-at="discussion.resolved_at"
:edited-by="discussion.resolved_by"
:action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
+ class-name="discussion-headline-light js-discussion-headline discussion-resolved-text gl-mb-2 gl-ml-3"
/>
</template>
<template #avatar-badge>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index 9806f8e5dc2..930876e90b1 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -3,7 +3,7 @@ import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui
import { mapActions, mapGetters, mapState } from 'vuex';
import Api from '~/api';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import eventHub from '~/sidebar/event_hub';
@@ -238,7 +238,7 @@ export default {
})
.then(() => this.handleAssigneeUpdate(assignees))
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong while updating assignees'),
}),
);
@@ -281,6 +281,7 @@ export default {
>
{{ __('Contributor') }}
</user-access-role-badge>
+ <span class="note-actions__mobile-spacer"></span>
<gl-button
v-if="canResolve"
ref="resolveButton"
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 835750cc137..9d59994788e 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import AwardsList from '~/vue_shared/components/awards_list.vue';
@@ -49,7 +49,7 @@ export default {
};
this.toggleAwardRequest(data).catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong on our end.'),
}),
);
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index f700802d6bc..f3530344181 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -9,8 +9,6 @@ import {
import { mapActions } from 'vuex';
import { __, s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
@@ -21,13 +19,11 @@ export default {
GlIcon,
GlBadge,
GlLoadingIcon,
- UserNameWithStatus,
},
directives: {
SafeHtml,
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagsMixin()],
props: {
author: {
type: Object,
@@ -74,12 +70,15 @@ export default {
required: false,
default: false,
},
+ isSystemNote: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
isUsernameLinkHovered: false,
- emojiTitle: '',
- authorStatusHasTooltip: false,
};
},
computed: {
@@ -100,15 +99,6 @@ export default {
'js-user-link': true,
};
},
- authorStatus() {
- if (this.author?.show_status) {
- return this.author.status_tooltip_html;
- }
- return false;
- },
- emojiElement() {
- return this.$refs?.authorStatus?.querySelector('gl-emoji');
- },
authorName() {
return this.author.name;
},
@@ -116,14 +106,6 @@ export default {
return s__('Notes|This internal note will always remain confidential');
},
},
- mounted() {
- this.emojiTitle = this.emojiElement ? this.emojiElement.getAttribute('title') : '';
-
- const authorStatusTitle = this.$refs?.authorStatus
- ?.querySelector('.user-status-emoji')
- ?.getAttribute('title');
- this.authorStatusHasTooltip = authorStatusTitle && authorStatusTitle !== '';
- },
methods: {
...mapActions(['setTargetNoteHash']),
handleToggle() {
@@ -134,12 +116,6 @@ export default {
this.setTargetNoteHash(this.noteTimestampLink);
}
},
- removeEmojiTitle() {
- this.emojiElement.removeAttribute('title');
- },
- addEmojiTitle() {
- this.emojiElement.setAttribute('title', this.emojiTitle);
- },
handleUsernameMouseEnter() {
this.$refs.authorNameLink.dispatchEvent(new Event('mouseenter'));
this.isUsernameLinkHovered = true;
@@ -148,9 +124,6 @@ export default {
this.$refs.authorNameLink.dispatchEvent(new Event('mouseleave'));
this.isUsernameLinkHovered = false;
},
- userAvailability(selectedAuthor) {
- return selectedAuthor?.availability || '';
- },
},
i18n: {
showThread: __('Show thread'),
@@ -185,35 +158,11 @@ export default {
:data-user-id="author.id"
:data-username="author.username"
>
- <span
- v-if="glFeatures.removeUserAttributesProjects || glFeatures.removeUserAttributesGroups"
- class="note-header-author-name gl-font-weight-bold"
- >
+ <span class="note-header-author-name gl-font-weight-bold">
{{ authorName }}
</span>
- <user-name-with-status
- v-else
- :name="authorName"
- :availability="userAvailability(author)"
- container-classes="note-header-author-name gl-font-weight-bold"
- />
</a>
- <span
- v-if="
- authorStatus &&
- !glFeatures.removeUserAttributesProjects &&
- !glFeatures.removeUserAttributesGroups
- "
- ref="authorStatus"
- v-safe-html:[$options.safeHtmlConfig]="authorStatus"
- v-on="
- authorStatusHasTooltip ? { mouseenter: removeEmojiTitle, mouseleave: addEmojiTitle } : {}
- "
- ></span>
- <span
- v-if="!glFeatures.removeUserAttributesProjects && !glFeatures.removeUserAttributesGroups"
- class="text-nowrap author-username"
- >
+ <span v-if="!isSystemNote" class="text-nowrap author-username">
<a
ref="authorUsernameLink"
class="author-username-link"
@@ -252,7 +201,7 @@ export default {
data-testid="internalNoteIndicator"
variant="warning"
size="sm"
- class="gl-mb-3 gl-ml-2"
+ class="gl-ml-2"
:title="internalNoteTooltip"
>
{{ __('Internal note') }}
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index afa5e39d8b0..50d166b6db5 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -2,7 +2,7 @@
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import DraftNote from '~/batch_comments/components/draft_note.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
@@ -247,7 +247,7 @@ export default {
const msg = __(
'Your comment could not be submitted! Please check your network connection and try again.',
);
- createFlash({
+ createAlert({
message: msg,
parent: this.$el,
});
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index e51969f95c7..c4b3111b919 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -5,7 +5,7 @@ import { escape, isEmpty } from 'lodash';
import { mapGetters, mapActions } from 'vuex';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { truncateSha } from '~/lib/utils/text_utility';
@@ -199,9 +199,6 @@ export default {
isMRDiffView() {
return this.line && !this.isOverviewTab;
},
- authorAvatarAdaptiveSize() {
- return { default: 24, md: 32 };
- },
},
created() {
const line = this.note.position?.line_range?.start || this.line;
@@ -273,7 +270,7 @@ export default {
this.isDeleting = false;
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong while deleting your note. Please try again.'),
});
this.isDeleting = false;
@@ -352,7 +349,7 @@ export default {
},
handleUpdateError() {
const msg = __('Something went wrong while editing your comment. Please try again.');
- createFlash({
+ createAlert({
message: msg,
parent: this.$el,
});
@@ -409,13 +406,13 @@ export default {
:class="{ ...classNameBindings, 'internal-note': note.internal }"
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
- class="note note-wrapper"
+ class="note note-wrapper note-comment"
data-qa-selector="noteable_note_container"
>
<div
v-if="showMultiLineComment"
data-testid="multiline-comment"
- class="gl-mb-5 gl-text-gray-500 gl-border-gray-100 gl-border-b-solid gl-border-b-1 gl-pb-4"
+ class="gl-text-gray-500 gl-border-gray-100 gl-border-b-solid gl-border-b-1 gl-px-5 gl-py-3"
>
<gl-sprintf :message="__('Comment on lines %{startLine} to %{endLine}')">
<template #startLine>
@@ -427,7 +424,7 @@ export default {
</gl-sprintf>
</div>
- <div v-if="isMRDiffView" class="gl-float-left gl-mt-n1 gl-mr-3">
+ <div v-if="isMRDiffView" class="timeline-avatar gl-float-left gl-pt-2">
<gl-avatar-link :href="author.path">
<gl-avatar
:src="author.avatar_url"
@@ -440,13 +437,13 @@ export default {
</gl-avatar-link>
</div>
- <div v-else class="gl-float-left gl-pl-3 gl-md-pl-2">
+ <div v-else class="timeline-avatar gl-float-left">
<gl-avatar-link :href="author.path">
<gl-avatar
:src="author.avatar_url"
:entity-name="author.username"
:alt="author.name"
- :size="authorAvatarAdaptiveSize"
+ :size="32"
/>
<slot name="avatar-badge"></slot>
diff --git a/app/assets/javascripts/notes/components/notes_activity_header.vue b/app/assets/javascripts/notes/components/notes_activity_header.vue
new file mode 100644
index 00000000000..e4f88962731
--- /dev/null
+++ b/app/assets/javascripts/notes/components/notes_activity_header.vue
@@ -0,0 +1,38 @@
+<script>
+import DiscussionFilter from './discussion_filter.vue';
+
+export default {
+ components: {
+ TimelineToggle: () => import('./timeline_toggle.vue'),
+ DiscussionFilter,
+ },
+ inject: {
+ showTimelineViewToggle: {
+ default: false,
+ },
+ },
+ props: {
+ notesFilters: {
+ type: Array,
+ required: true,
+ },
+ notesFilterValue: {
+ type: Number,
+ default: undefined,
+ required: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-sm-align-items-center gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-space-between gl-pt-5 gl-mt-5 gl-border-t"
+ >
+ <h2 class="gl-font-size-h1 gl-m-0">{{ __('Activity') }}</h2>
+ <div class="gl-display-flex gl-gap-3 gl-w-full gl-sm-w-auto gl-mt-3 gl-sm-mt-0">
+ <timeline-toggle v-if="showTimelineViewToggle" />
+ <discussion-filter :filters="notesFilters" :selected-value="notesFilterValue" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 37bc8bad305..9c2ff2c3e7f 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -1,7 +1,7 @@
<script>
import { mapGetters, mapActions } from 'vuex';
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
@@ -19,10 +19,12 @@ import DiscussionFilterNote from './discussion_filter_note.vue';
import NoteableDiscussion from './noteable_discussion.vue';
import NoteableNote from './noteable_note.vue';
import SidebarSubscription from './sidebar_subscription.vue';
+import NotesActivityHeader from './notes_activity_header.vue';
export default {
name: 'NotesApp',
components: {
+ NotesActivityHeader,
NoteableNote,
NoteableDiscussion,
SystemNote,
@@ -46,6 +48,15 @@ export default {
type: Object,
required: true,
},
+ notesFilters: {
+ type: Array,
+ required: true,
+ },
+ notesFilterValue: {
+ type: Number,
+ default: undefined,
+ required: false,
+ },
userData: {
type: Object,
required: false,
@@ -221,7 +232,7 @@ export default {
.catch(() => {
this.setLoadingState(false);
this.setNotesFetchedState(true);
- createFlash({
+ createAlert({
message: __('Something went wrong while fetching comments. Please try again.'),
});
});
@@ -281,6 +292,7 @@ export default {
<template>
<div v-show="shouldShow" id="notes">
<sidebar-subscription :iid="noteableData.iid" :noteable-data="noteableData" />
+ <notes-activity-header :notes-filters="notesFilters" :notes-filter-value="notesFilterValue" />
<ordered-layout :slot-keys="slotKeys">
<template #form>
<comment-form
@@ -292,7 +304,11 @@ export default {
<template #comments>
<ul id="notes-list" class="notes main-notes-list timeline">
<template v-for="discussion in allDiscussions">
- <skeleton-loading-container v-if="discussion.isSkeletonNote" :key="discussion.id" />
+ <skeleton-loading-container
+ v-if="discussion.isSkeletonNote"
+ :key="discussion.id"
+ class="note-skeleton"
+ />
<timeline-entry-item v-else-if="discussion.isDraft" :key="discussion.id">
<draft-note :draft="discussion" />
</timeline-entry-item>
@@ -327,7 +343,7 @@ export default {
:help-page-path="helpPagePath"
/>
</template>
- <discussion-filter-note v-show="commentsDisabled" />
+ <discussion-filter-note v-if="commentsDisabled" />
</ul>
</template>
</ordered-layout>
diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue
index 8632eea5d8e..59a3cc2d306 100644
--- a/app/assets/javascripts/notes/components/timeline_toggle.vue
+++ b/app/assets/javascripts/notes/components/timeline_toggle.vue
@@ -53,6 +53,7 @@ export default {
:selected="timelineEnabled"
:title="tooltip"
:aria-label="tooltip"
+ data-testid="timeline-toggle-button"
@click="toggleTimeline"
/>
</template>
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index 2bd3488ae1b..734e08dd586 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -61,7 +61,7 @@ export default {
<template>
<li
:class="liClasses"
- class="gl-display-flex! gl-align-items-center gl-flex-wrap gl-bg-gray-10 gl-py-3 gl-px-5 gl-border-t"
+ class="toggle-replies-widget gl-display-flex! gl-align-items-center gl-flex-wrap gl-bg-gray-10 gl-py-3 gl-px-5 gl-border"
>
<gl-button
ref="toggle"
@@ -75,7 +75,7 @@ export default {
<user-avatar-link
v-for="author in uniqueAuthors"
:key="author.username"
- class="gl-mr-3"
+ class="gl-mr-3 reply-author-avatar"
:link-href="author.path"
:img-alt="author.name"
img-css-classes="gl-mr-0!"
diff --git a/app/assets/javascripts/notes/discussion_filters.js b/app/assets/javascripts/notes/discussion_filters.js
deleted file mode 100644
index 104e9d4183a..00000000000
--- a/app/assets/javascripts/notes/discussion_filters.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import Vue from 'vue';
-import DiscussionFilter from './components/discussion_filter.vue';
-
-export default (store) => {
- const discussionFilterEl = document.getElementById('js-vue-discussion-filter');
-
- if (discussionFilterEl) {
- const { defaultFilter, notesFilters } = discussionFilterEl.dataset;
- const filterValues = notesFilters ? JSON.parse(notesFilters) : {};
- const filters = Object.keys(filterValues).map((entry) => ({
- title: entry,
- value: filterValues[entry],
- }));
- const props = { filters };
-
- if (defaultFilter) {
- props.selectedValue = parseInt(defaultFilter, 10);
- }
-
- return new Vue({
- el: discussionFilterEl,
- name: 'DiscussionFilterRoot',
- components: {
- DiscussionFilter,
- },
- store,
- render(createElement) {
- return createElement('discussion-filter', { props });
- },
- });
- }
-
- return null;
-};
diff --git a/app/assets/javascripts/notes/i18n.js b/app/assets/javascripts/notes/i18n.js
index 08792fd1a3f..9b5fd69f816 100644
--- a/app/assets/javascripts/notes/i18n.js
+++ b/app/assets/javascripts/notes/i18n.js
@@ -16,7 +16,7 @@ export const COMMENT_FORM = {
bodyPlaceholderInternal: __('Write an internal note or drag your files here…'),
internal: s__('Notes|Make this an internal note'),
internalVisibility: s__(
- 'Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher',
+ 'Notes|Internal notes are only visible to members with the role of Reporter or higher',
),
discussionThatNeedsResolution: __(
'Discuss a specific suggestion or question that needs to be resolved.',
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 054a5bd36e2..defcb0533b7 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -1,9 +1,8 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import NotesApp from './components/notes_app.vue';
-import initDiscussionFilters from './discussion_filters';
import { store } from './stores';
-import initTimelineToggle from './timeline';
+import { getNotesFilterData } from './utils/get_notes_filter_data';
export default () => {
const el = document.getElementById('js-vue-notes');
@@ -11,6 +10,9 @@ export default () => {
return;
}
+ const notesFilterProps = getNotesFilterData(el);
+ const showTimelineViewToggle = parseBoolean(el.dataset.showTimelineViewToggle);
+
// eslint-disable-next-line no-new
new Vue({
el,
@@ -19,6 +21,9 @@ export default () => {
NotesApp,
},
store,
+ provide: {
+ showTimelineViewToggle,
+ },
data() {
const notesDataset = el.dataset;
const parsedUserData = JSON.parse(notesDataset.currentUserData);
@@ -56,11 +61,9 @@ export default () => {
noteableData: this.noteableData,
notesData: this.notesData,
userData: this.currentUserData,
+ ...notesFilterProps,
},
});
},
});
-
- initDiscussionFilters(store);
- initTimelineToggle(store);
};
diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
index 7b9c0959464..9a140029c07 100644
--- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -1,7 +1,7 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils';
import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { clearDraft } from '~/lib/utils/autosave';
import { s__ } from '~/locale';
import { formatLineRange } from '~/notes/components/multiline_comment_utils';
@@ -42,7 +42,7 @@ export default {
this.handleClearForm(this.discussion.line_code);
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__('MergeRequests|An error occurred while saving the draft comment.'),
});
});
@@ -82,7 +82,7 @@ export default {
}
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__('MergeRequests|An error occurred while saving the draft comment.'),
});
});
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js
index db5f9ebf3f0..d75a4158440 100644
--- a/app/assets/javascripts/notes/mixins/discussion_navigation.js
+++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js
@@ -1,136 +1,12 @@
import { mapGetters, mapActions, mapState } from 'vuex';
-import { scrollToElementWithContext, scrollToElement, contentTop } from '~/lib/utils/common_utils';
-import { updateHistory } from '~/lib/utils/url_utility';
-import eventHub from '../event_hub';
-
-/**
- * @param {string} selector
- * @returns {boolean}
- */
-function scrollTo(selector, { withoutContext = false, offset = 0 } = {}) {
- const el = document.querySelector(selector);
- const scrollFunction = withoutContext ? scrollToElement : scrollToElementWithContext;
-
- if (el) {
- scrollFunction(el, {
- behavior: 'auto',
- offset,
- });
- return true;
- }
-
- return false;
-}
-
-function updateUrlWithNoteId(noteId) {
- const newHistoryEntry = {
- state: null,
- title: window.title,
- url: `#note_${noteId}`,
- replace: true,
- };
-
- if (noteId) {
- // Temporarily mask the ID to avoid the browser default
- // scrolling taking over which is broken with virtual
- // scrolling enabled.
- const note = document.querySelector(`#note_${noteId}`);
- note?.setAttribute('id', `masked::${note.id}`);
-
- // Update the hash now that the ID "doesn't exist" in the page
- updateHistory(newHistoryEntry);
-
- // Unmask the note's ID
- note?.setAttribute('id', `note_${noteId}`);
- }
-}
-
-/**
- * @param {object} self Component instance with mixin applied
- * @param {string} id Discussion id we are jumping to
- */
-function diffsJump({ expandDiscussion }, id, firstNoteId) {
- const selector = `ul.notes[data-discussion-id="${id}"]`;
-
- eventHub.$once('scrollToDiscussion', () => {
- scrollTo(selector);
- // Wait for the discussion scroll before updating to the more specific ID
- setTimeout(() => updateUrlWithNoteId(firstNoteId), 0);
- });
- expandDiscussion({ discussionId: id });
-}
-
-/**
- * @param {object} self Component instance with mixin applied
- * @param {string} id Discussion id we are jumping to
- * @returns {boolean}
- */
-function discussionJump({ expandDiscussion }, id) {
- const selector = `div.discussion[data-discussion-id="${id}"]`;
- expandDiscussion({ discussionId: id });
- return scrollTo(selector, {
- withoutContext: true,
- offset: window.gon?.features?.movedMrSidebar ? -28 : 0,
- });
-}
-
-/**
- * @param {object} self Component instance with mixin applied
- * @param {string} id Discussion id we are jumping to
- */
-function switchToDiscussionsTabAndJumpTo(self, id) {
- window.mrTabs.eventHub.$once('MergeRequestTabChange', () => {
- setTimeout(() => discussionJump(self, id), 0);
- });
-
- window.mrTabs.tabShown('show');
-}
-
-/**
- * @param {object} self Component instance with mixin applied
- * @param {object} discussion Discussion we are jumping to
- */
-function jumpToDiscussion(self, discussion) {
- const { id, diff_discussion: isDiffDiscussion, notes } = discussion;
- const firstNoteId = notes?.[0]?.id;
- if (id) {
- const activeTab = window.mrTabs.currentAction;
-
- if (activeTab === 'diffs' && isDiffDiscussion) {
- diffsJump(self, id, firstNoteId);
- } else {
- switchToDiscussionsTabAndJumpTo(self, id);
- }
- }
-}
-
-/**
- * @param {object} self Component instance with mixin applied
- * @param {function} fn Which function used to get the target discussion's id
- */
-function handleDiscussionJump(self, fn) {
- const isDiffView = window.mrTabs.currentAction === 'diffs';
- const targetId = fn(self.currentDiscussionId, isDiffView);
- const discussion = self.getDiscussion(targetId);
- const discussionFilePath = discussion?.diff_file?.file_path;
-
- window.location.hash = '';
-
- if (discussionFilePath) {
- self.scrollToFile({
- path: discussionFilePath,
- });
- }
-
- self.$nextTick(() => {
- jumpToDiscussion(self, discussion);
- self.setCurrentDiscussionId(targetId);
- });
-}
+import { scrollToElement, contentTop } from '~/lib/utils/common_utils';
function getAllDiscussionElements() {
+ const containerEl = window.mrTabs?.currentAction === 'diffs' ? '.diffs' : '.notes';
return Array.from(
- document.querySelectorAll('[data-discussion-id]:not([data-discussion-resolved])'),
+ document.querySelectorAll(
+ `${containerEl} div[data-discussion-id]:not([data-discussion-resolved])`,
+ ),
);
}
@@ -182,14 +58,10 @@ function getPreviousDiscussion() {
}
function handleJumpForBothPages(getDiscussion, ctx, fn, scrollOptions) {
- if (window.mrTabs.currentAction !== 'show') {
- handleDiscussionJump(ctx, fn);
- } else {
- const discussion = getDiscussion();
- const id = discussion.dataset.discussionId;
- ctx.expandDiscussion({ discussionId: id });
- scrollToElement(discussion, scrollOptions);
- }
+ const discussion = getDiscussion();
+ const id = discussion.dataset.discussionId;
+ ctx.expandDiscussion({ discussionId: id });
+ scrollToElement(discussion, scrollOptions);
}
export default {
@@ -205,9 +77,11 @@ export default {
},
methods: {
...mapActions(['expandDiscussion', 'setCurrentDiscussionId']),
- ...mapActions('diffs', ['scrollToFile']),
+ ...mapActions('diffs', ['scrollToFile', 'disableVirtualScroller']),
+
+ async jumpToNextDiscussion(scrollOptions) {
+ await this.disableVirtualScroller();
- jumpToNextDiscussion(scrollOptions) {
handleJumpForBothPages(
getNextDiscussion,
this,
@@ -216,7 +90,9 @@ export default {
);
},
- jumpToPreviousDiscussion(scrollOptions) {
+ async jumpToPreviousDiscussion(scrollOptions) {
+ await this.disableVirtualScroller();
+
handleJumpForBothPages(
getPreviousDiscussion,
this,
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index 9783def1b46..44751020173 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
export default {
@@ -46,7 +46,7 @@ export default {
this.isResolving = false;
const msg = __('Something went wrong while resolving this discussion. Please try again.');
- createFlash({
+ createAlert({
message: msg,
parent: this.$el,
});
diff --git a/app/assets/javascripts/notes/timeline.js b/app/assets/javascripts/notes/timeline.js
deleted file mode 100644
index df6d1b21400..00000000000
--- a/app/assets/javascripts/notes/timeline.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import Vue from 'vue';
-import TimelineToggle from './components/timeline_toggle.vue';
-
-export default function initTimelineToggle(store) {
- const el = document.getElementById('js-incidents-timeline-toggle');
-
- if (!el) return null;
-
- return new Vue({
- el,
- store,
- render(createElement) {
- return createElement(TimelineToggle);
- },
- });
-}
diff --git a/app/assets/javascripts/notes/utils/get_notes_filter_data.js b/app/assets/javascripts/notes/utils/get_notes_filter_data.js
new file mode 100644
index 00000000000..6d62ab5e91b
--- /dev/null
+++ b/app/assets/javascripts/notes/utils/get_notes_filter_data.js
@@ -0,0 +1,21 @@
+/**
+ * Returns parsed notes filter data from a given element's dataset
+ *
+ * @param {Element} el containing info in the dataset
+ */
+export const getNotesFilterData = (el) => {
+ const { notesFilterValue: valueData, notesFilters: filtersData } = el.dataset;
+
+ const filtersParsed = filtersData ? JSON.parse(filtersData) : {};
+ const filters = Object.keys(filtersParsed).map((key) => ({
+ title: key,
+ value: filtersParsed[key],
+ }));
+
+ const value = valueData ? Number(valueData) : undefined;
+
+ return {
+ notesFilters: filters,
+ notesFilterValue: value,
+ };
+};
diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js
index 529eb7d207b..5f60cab8bdd 100644
--- a/app/assets/javascripts/operation_settings/store/actions.js
+++ b/app/assets/javascripts/operation_settings/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -35,7 +35,7 @@ export const receiveSaveChangesError = (_, error) => {
const { response = {} } = error;
const message = response.data && response.data.message ? response.data.message : '';
- createFlash({
+ createAlert({
message: `${__('There was an error saving your changes.')} ${message}`,
});
};
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 9e8eb92d87a..597df2b9bc3 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,6 +1,6 @@
<script>
import { GlEmptyState } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { n__ } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
@@ -69,7 +69,7 @@ export default {
return this.queryVariables;
},
error() {
- createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ createAlert({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
},
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 9ebbdfa920d..8b66165a57a 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
@@ -1,7 +1,7 @@
<script>
import { GlResizeObserverDirective, GlEmptyState } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
@@ -66,7 +66,7 @@ export default {
this.updateBreadcrumb();
},
error() {
- createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ createAlert({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
},
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 c1bd71de646..794be8d5195 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
@@ -10,7 +10,7 @@ import {
} from '@gitlab/ui';
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import Tracking from '~/tracking';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
@@ -100,7 +100,7 @@ export default {
this.containerRepositoriesCount = data[this.graphqlResource]?.containerRepositoriesCount;
},
error() {
- createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ createAlert({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
additionalDetails: {
@@ -115,7 +115,7 @@ export default {
return data[this.graphqlResource]?.containerRepositories.nodes;
},
error() {
- createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
+ createAlert({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
},
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 26d4aa13715..223f427ce0e 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
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
import {
DELETE_PACKAGE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
@@ -20,7 +20,7 @@ export const fetchPackageVersions = ({ commit, state }) => {
}
})
.catch(() => {
- createFlash({ message: FETCH_PACKAGE_VERSIONS_ERROR, type: 'warning' });
+ createAlert({ message: FETCH_PACKAGE_VERSIONS_ERROR, variant: VARIANT_WARNING });
})
.finally(() => {
commit(types.SET_LOADING, false);
@@ -33,7 +33,7 @@ export const deletePackage = ({
},
}) => {
return Api.deleteProjectPackage(project_id, id).catch(() => {
- createFlash({ message: DELETE_PACKAGE_ERROR_MESSAGE, type: 'warning' });
+ createAlert({ message: DELETE_PACKAGE_ERROR_MESSAGE, variant: VARIANT_WARNING });
});
};
@@ -51,9 +51,9 @@ export const deletePackageFile = (
.then(() => {
const filtered = packageFiles.filter((f) => f.id !== fileId);
commit(types.UPDATE_PACKAGE_FILES, filtered);
- createFlash({ message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, type: 'success' });
+ createAlert({ message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, variant: VARIANT_SUCCESS });
})
.catch(() => {
- createFlash({ message: DELETE_PACKAGE_FILE_ERROR_MESSAGE, type: 'warning' });
+ createAlert({ message: DELETE_PACKAGE_FILE_ERROR_MESSAGE, variant: VARIANT_WARNING });
});
};
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
index dab4a051d0c..8b6a5c59847 100644
--- 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
@@ -81,10 +81,9 @@ export default {
},
},
i18n: {
- deleteModalContent: s__(
- 'PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?',
- ),
- modalAction: s__('PackageRegistry|Delete package'),
+ deleteModalContent: s__('PackageRegistry|You are about to delete %{name}, are you sure?'),
+ modalTitle: s__('PackageRegistry|Delete package'),
+ modalAction: s__('PackageRegistry|Permanently delete'),
},
};
</script>
@@ -120,13 +119,13 @@ export default {
<gl-modal
ref="packageListDeleteModal"
size="sm"
- modal-id="confirm-delete-pacakge"
+ modal-id="confirm-delete-package"
:action-primary="deleteModalActionPrimaryProps"
:action-cancel="deleteModalActionCancelProps"
@ok="deleteItemConfirmation"
@cancel="deleteItemCanceled"
>
- <template #modal-title>{{ $options.i18n.modalAction }}</template>
+ <template #modal-title>{{ $options.i18n.modalTitle }}</template>
<gl-sprintf :message="$options.i18n.deleteModalContent">
<template #name>
<strong>{{ deletePackageName }}</strong>
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
index 184a24047eb..2adf6187c4b 100644
--- 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
@@ -1,7 +1,7 @@
<script>
import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import {
@@ -84,7 +84,7 @@ export default {
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' });
+ createAlert({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, variant: VARIANT_INFO });
const cleanUrl = window.location.href.split('?')[0];
historyReplaceState(cleanUrl);
}
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
index 51a38c434cb..37b51797490 100644
--- 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
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages_and_registries/shared/constants';
import {
@@ -43,7 +43,7 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
dispatch('receivePackagesListSuccess', { data, headers });
})
.catch(() => {
- createFlash({
+ createAlert({
message: FETCH_PACKAGES_LIST_ERROR_MESSAGE,
});
})
@@ -54,7 +54,7 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
if (!_links || !_links.delete_api_path) {
- createFlash({
+ createAlert({
message: DELETE_PACKAGE_ERROR_MESSAGE,
});
const error = new Error(MISSING_DELETE_PATH_ERROR);
@@ -69,14 +69,14 @@ export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
const page = getNewPaginationPage(currentPage, perPage, total - 1);
dispatch('requestPackagesList', { page });
- createFlash({
+ createAlert({
message: DELETE_PACKAGE_SUCCESS_MESSAGE,
- type: 'success',
+ variant: VARIANT_SUCCESS,
});
})
.catch(() => {
dispatch('setLoading', false);
- createFlash({
+ createAlert({
message: DELETE_PACKAGE_ERROR_MESSAGE,
});
});
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 11fd0db3106..cee976656f9 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
@@ -2,7 +2,8 @@
import { GlSprintf, GlBadge, GlResizeObserverDirective } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { __ } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
+import { formatDate } from '~/lib/utils/datetime_utility';
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';
@@ -25,6 +26,7 @@ export default {
},
inject: ['isGroupPage'],
i18n: {
+ lastDownloadedAt: s__('PackageRegistry|Last downloaded %{dateTime}'),
packageInfo: __('v%{version} published %{timeAgo}'),
},
props: {
@@ -39,6 +41,11 @@ export default {
};
},
computed: {
+ packageLastDownloadedAtDisplay() {
+ return sprintf(this.$options.i18n.lastDownloadedAt, {
+ dateTime: formatDate(this.packageEntity.lastDownloadedAt, 'mmm d, yyyy'),
+ });
+ },
packageTypeDisplay() {
return getPackageTypeLabel(this.packageEntity.packageType);
},
@@ -136,6 +143,15 @@ export default {
<metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
</template>
+ <template v-if="packageEntity.lastDownloadedAt" #metadata-last-downloaded-at>
+ <metadata-item
+ data-testid="package-last-downloaded-at"
+ icon="download"
+ :text="packageLastDownloadedAtDisplay"
+ size="m"
+ />
+ </template>
+
<template #right-actions>
<slot name="delete-button"></slot>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue
index 7a85fd3052e..e1cf4883029 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue
@@ -1,6 +1,6 @@
<script>
import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
import { s__ } from '~/locale';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/package_registry/constants';
@@ -39,15 +39,15 @@ export default {
throw data.destroyPackage.errors[0];
}
if (this.showSuccessAlert) {
- createFlash({
+ createAlert({
message: this.$options.i18n.successMessage,
- type: 'success',
+ variant: VARIANT_SUCCESS,
});
}
} catch (error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.errorMessage,
- type: 'warning',
+ variant: VARIANT_WARNING,
captureError: true,
error,
});
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 e84f181e9b2..c6583b8f09f 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
@@ -122,10 +122,9 @@ export default {
},
},
i18n: {
- deleteModalContent: s__(
- 'PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?',
- ),
- modalAction: s__('PackageRegistry|Delete package'),
+ deleteModalContent: s__('PackageRegistry|You are about to delete %{name}, are you sure?'),
+ modalTitle: s__('PackageRegistry|Delete package'),
+ modalAction: s__('PackageRegistry|Permanently delete'),
errorMessageBodyAlert: s__(
'PackageRegistry|There was a timeout and the package was not published. Delete this package and try again.',
),
@@ -172,14 +171,14 @@ export default {
<gl-modal
v-model="showDeleteModal"
- modal-id="confirm-delete-pacakge"
+ modal-id="confirm-delete-package"
size="sm"
:action-primary="deleteModalActionPrimaryProps"
:action-cancel="deleteModalActionCancelProps"
@ok="deleteItemConfirmation"
@cancel="deleteItemCanceled"
>
- <template #modal-title>{{ $options.i18n.modalAction }}</template>
+ <template #modal-title>{{ $options.i18n.modalTitle }}</template>
<gl-sprintf :message="$options.i18n.deleteModalContent">
<template #name>
<strong>{{ deletePackageName }}</strong>
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 06a04ee248a..4e35176c757 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -78,6 +78,17 @@ export const TRACKING_ACTION_CLICK_COMMIT_LINK = 'click_commit_link_from_package
export const TRACKING_LABEL_PACKAGE_HISTORY = 'package_history';
export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
+
+export const DELETE_MODAL_TITLE = s__('PackageRegistry|Delete package version');
+export const DELETE_MODAL_CONTENT = s__(
+ `PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?`,
+);
+export const DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT = s__(
+ `PackageRegistry|Deleting all package assets will remove version %{version} of %{name}. Are you sure?`,
+);
+export const DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT = s__(
+ `PackageRegistry|Deleting the last package asset will remove version %{version} of %{name}. Are you sure?`,
+);
export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
'PackageRegistry|Something went wrong while deleting the package asset.',
);
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 f3f0d096d10..8e50c95b10b 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
@@ -4,6 +4,7 @@ query getPackageDetails($id: PackagesPackageID!) {
name
packageType
version
+ lastDownloadedAt
createdAt
updatedAt
status
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
index c10fc914d56..eeed56b77c3 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
@@ -10,7 +10,7 @@ import {
GlTabs,
GlSprintf,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { objectToQuery } from '~/lib/utils/url_utility';
@@ -44,6 +44,10 @@ import {
DELETE_PACKAGE_FILES_ERROR_MESSAGE,
DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
+ DELETE_MODAL_TITLE,
+ DELETE_MODAL_CONTENT,
+ DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT,
+ DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT,
} from '~/packages_and_registries/package_registry/constants';
import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
@@ -86,6 +90,7 @@ export default {
},
data() {
return {
+ deletePackageModalContent: DELETE_MODAL_CONTENT,
filesToDelete: [],
mutationLoading: false,
packageEntity: {},
@@ -101,7 +106,7 @@ export default {
return data.package || {};
},
error(error) {
- createFlash({
+ createAlert({
message: FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
captureError: true,
error,
@@ -205,20 +210,18 @@ export default {
if (data?.destroyPackageFiles?.errors[0]) {
throw data.destroyPackageFiles.errors[0];
}
- createFlash({
- message:
- ids.length === 1
- ? DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
- : DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
- type: 'success',
+ createAlert({
+ message: this.isLastItem(ids)
+ ? DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
+ : DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
+ variant: VARIANT_SUCCESS,
});
} catch (error) {
- createFlash({
- message:
- ids.length === 1
- ? DELETE_PACKAGE_FILE_ERROR_MESSAGE
- : DELETE_PACKAGE_FILES_ERROR_MESSAGE,
- type: 'warning',
+ createAlert({
+ message: this.isLastItem(ids)
+ ? DELETE_PACKAGE_FILE_ERROR_MESSAGE
+ : DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ variant: VARIANT_WARNING,
captureError: true,
error,
});
@@ -231,18 +234,26 @@ export default {
files.length === this.packageFiles.length &&
!this.packageEntity.packageFiles?.pageInfo?.hasNextPage
) {
+ if (this.isLastItem(files)) {
+ this.deletePackageModalContent = DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT;
+ } else {
+ this.deletePackageModalContent = DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT;
+ }
this.$refs.deleteModal.show();
} else {
this.filesToDelete = files;
- if (files.length === 1) {
+ if (this.isLastItem(files)) {
this.$refs.deleteFileModal.show();
} else if (files.length > 1) {
this.$refs.deleteFilesModal.show();
}
}
},
+ isLastItem(items) {
+ return items.length === 1;
+ },
confirmFilesDelete() {
- if (this.filesToDelete.length === 1) {
+ if (this.isLastItem(this.filesToDelete)) {
this.track(DELETE_PACKAGE_FILE_TRACKING_ACTION);
} else {
this.track(DELETE_PACKAGE_FILES_TRACKING_ACTION);
@@ -250,12 +261,12 @@ export default {
this.deletePackageFiles(this.filesToDelete.map((file) => file.id));
this.filesToDelete = [];
},
+ resetDeleteModalContent() {
+ this.deletePackageModalContent = DELETE_MODAL_CONTENT;
+ },
},
i18n: {
- deleteModalTitle: s__(`PackageRegistry|Delete Package Version`),
- deleteModalContent: s__(
- `PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?`,
- ),
+ DELETE_MODAL_TITLE,
deleteFileModalTitle: s__(`PackageRegistry|Delete package asset`),
deleteFileModalContent: s__(
`PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?`,
@@ -263,7 +274,7 @@ export default {
},
modal: {
packageDeletePrimaryAction: {
- text: __('Delete'),
+ text: s__('PackageRegistry|Permanently delete'),
attributes: [
{ variant: 'danger' },
{ category: 'primary' },
@@ -371,10 +382,11 @@ export default {
:action-primary="$options.modal.packageDeletePrimaryAction"
:action-cancel="$options.modal.cancelAction"
@primary="deletePackage(packageEntity)"
+ @hidden="resetDeleteModalContent"
@canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE)"
>
- <template #modal-title>{{ $options.i18n.deleteModalTitle }}</template>
- <gl-sprintf :message="$options.i18n.deleteModalContent">
+ <template #modal-title>{{ $options.i18n.DELETE_MODAL_TITLE }}</template>
+ <gl-sprintf :message="deletePackageModalContent">
<template #version>
<strong>{{ packageEntity.version }}</strong>
</template>
@@ -398,7 +410,7 @@ export default {
@canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
>
<template #modal-title>{{ $options.i18n.deleteFileModalTitle }}</template>
- <gl-sprintf v-if="filesToDelete.length === 1" :message="$options.i18n.deleteFileModalContent">
+ <gl-sprintf v-if="isLastItem(filesToDelete)" :message="$options.i18n.deleteFileModalContent">
<template #filename>
<strong>{{ filesToDelete[0].fileName }}</strong>
</template>
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
index 38df701157a..ed9ab0367dd 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
@@ -1,6 +1,6 @@
<script>
import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages_and_registries/shared/constants';
@@ -105,7 +105,7 @@ export default {
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' });
+ createAlert({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, variant: VARIANT_INFO });
const cleanUrl = window.location.href.split('?')[0];
historyReplaceState(cleanUrl);
}
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/cleanup_image_tags.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/cleanup_image_tags.vue
index 72e68aca070..b8405b09840 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/cleanup_image_tags.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/cleanup_image_tags.vue
@@ -57,6 +57,9 @@ export default {
isEnabled() {
return this.containerExpirationPolicy || this.enableHistoricEntries;
},
+ isLoading() {
+ return this.$apollo.queries.containerExpirationPolicy.loading;
+ },
showDisabledFormMessage() {
return !this.isEnabled && !this.fetchSettingsError;
},
@@ -86,10 +89,10 @@ export default {
<container-expiration-policy-form
v-if="isEnabled"
v-model="workingCopy"
- :is-loading="$apollo.queries.containerExpirationPolicy.loading"
+ :is-loading="isLoading"
:is-edited="isEdited"
/>
- <template v-else>
+ <template v-if="!isLoading">
<gl-alert
v-if="showDisabledFormMessage"
:dismissible="false"
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
index b003b6aeb6b..1dd88d69d30 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue
@@ -110,7 +110,7 @@ export default {
{{ cleanupRulesButtonText }}
</gl-button>
</gl-card>
- <template v-else>
+ <template v-if="!$apollo.queries.containerExpirationPolicy.loading">
<gl-alert
v-if="showDisabledFormMessage"
:dismissible="false"
diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js
index 8cecc1d3ef7..97fb64f9971 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -29,7 +29,7 @@ export default class PayloadDownloader {
PayloadDownloader.downloadFile(data);
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Error fetching payload data.'),
});
})
diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
index 616005565c4..1cd19fc09a8 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -43,7 +43,7 @@ export default class PayloadPreviewer {
})
.catch(() => {
this.spinner.classList.remove('gl-display-inline');
- createFlash({
+ createAlert({
message: __('Error fetching payload data.'),
});
});
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
index 18ba89f8856..40348e0b18a 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { __ } from '~/locale';
@@ -30,7 +30,7 @@ export default () => {
$jsBroadcastMessagePreview.html(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while rendering preview broadcast message'),
}),
);
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/index.js b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
index f687423594d..ffd976be8c6 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/index.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
@@ -1,5 +1,10 @@
+import initBroadcastMessages from '~/admin/broadcast_messages';
import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
import initBroadcastMessagesForm from './broadcast_message';
-initBroadcastMessagesForm();
-initDeprecatedRemoveRowBehavior();
+if (gon.features.vueBroadcastMessages) {
+ initBroadcastMessages();
+} else {
+ initBroadcastMessagesForm();
+ initDeprecatedRemoveRowBehavior();
+}
diff --git a/app/assets/javascripts/pages/admin/dashboard/index.js b/app/assets/javascripts/pages/admin/dashboard/index.js
new file mode 100644
index 00000000000..b63e612be47
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/dashboard/index.js
@@ -0,0 +1,3 @@
+import initGitlabVersionCheck from '~/gitlab_version_check';
+
+initGitlabVersionCheck();
diff --git a/app/assets/javascripts/pages/admin/groups/show/index.js b/app/assets/javascripts/pages/admin/groups/show/index.js
deleted file mode 100644
index 86b80a0ba5b..00000000000
--- a/app/assets/javascripts/pages/admin/groups/show/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import UsersSelect from '~/users_select';
-
-new UsersSelect(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js
index a249864fa36..eaee625c047 100644
--- a/app/assets/javascripts/pages/admin/index.js
+++ b/app/assets/javascripts/pages/admin/index.js
@@ -1,10 +1,8 @@
-import initGitlabVersionCheck from '~/gitlab_version_check';
import initAdminStatisticsPanel from '~/admin/statistics_panel/index';
import initVueAlerts from '~/vue_alerts';
import initAdmin from './admin';
initVueAlerts();
-initGitlabVersionCheck();
const statisticsPanelContainer = document.getElementById('js-admin-statistics-container');
initAdmin();
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
index 63b98f4143b..4f42ef2892d 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlModal } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
@@ -31,7 +31,7 @@ export default {
redirectTo(response.request.responseURL);
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__('AdminArea|Stopping jobs failed'),
});
throw error;
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index b6f42a27002..2a7619da8cc 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -4,7 +4,7 @@ import $ from 'jquery';
import { getGroups } from '~/api/groups_api';
import { getProjects } from '~/api/projects_api';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { isMetaClick } from '~/lib/utils/common_utils';
import { addDelimiter } from '~/lib/utils/text_utility';
@@ -119,7 +119,7 @@ export default class Todos {
})
.catch(() => {
this.updateRowState(target, true);
- return createFlash({
+ return createAlert({
message: __('Error updating status of to-do item.'),
});
});
@@ -168,7 +168,7 @@ export default class Todos {
this.updateBadges(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error updating status for all to-do items.'),
}),
);
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index de28f027126..377ba0f13a9 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -1,6 +1,10 @@
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 { initBulkUpdateSidebar } from '~/issuable/bulk_update_sidebar';
+import {
+ initBulkUpdateSidebar,
+ initStatusDropdown,
+ initSubscriptionsDropdown,
+} from '~/issuable/bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
@@ -9,6 +13,8 @@ const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_';
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
initBulkUpdateSidebar(ISSUABLE_BULK_UPDATE_PREFIX);
+initStatusDropdown();
+initSubscriptionsDropdown();
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
diff --git a/app/assets/javascripts/pages/groups/new/group_path_validator.js b/app/assets/javascripts/pages/groups/new/group_path_validator.js
index 8ce73be6e74..fa111032b2e 100644
--- a/app/assets/javascripts/pages/groups/new/group_path_validator.js
+++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js
@@ -1,6 +1,6 @@
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import InputValidator from '~/validators/input_validator';
import { getGroupPathAvailability } from '~/rest_api';
@@ -62,7 +62,7 @@ export default class GroupPathValidator extends InputValidator {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while validating group path'),
}),
);
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 7dab5258b24..a555038ed5c 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -1,4 +1,6 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import BindInOut from '~/behaviors/bind_in_out';
import initFilePickers from '~/file_pickers';
import Group from '~/group';
@@ -8,6 +10,8 @@ import NewGroupCreationApp from './components/app.vue';
import GroupPathValidator from './group_path_validator';
import initToggleInviteMembers from './toggle_invite_members';
+Vue.use(VueApollo);
+
new GroupPathValidator(); // eslint-disable-line no-new
new Group(); // eslint-disable-line no-new
initGroupNameAndPath();
@@ -31,8 +35,13 @@ function initNewGroupCreation(el) {
hasErrors: parseBoolean(hasErrors),
};
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
return new Vue({
el,
+ apolloProvider,
provide: {
verificationRequired: parseBoolean(verificationRequired),
verificationFormUrl,
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 bf77d968e7d..b1a1cc21764 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
@@ -2,9 +2,11 @@ import initStaleRunnerCleanupSetting from 'ee_else_ce/group_settings/stale_runne
import initVariableList from '~/ci_variable_list';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
import initSettingsPanels from '~/settings_panels';
+import initDeployTokens from '~/deploy_tokens';
// Initialize expandable settings panels
initSettingsPanels();
+initDeployTokens();
initSharedRunnersForm();
initStaleRunnerCleanupSetting();
diff --git a/app/assets/javascripts/pages/groups/settings/index.js b/app/assets/javascripts/pages/groups/settings/index.js
index cb787c60002..7e97cd865b7 100644
--- a/app/assets/javascripts/pages/groups/settings/index.js
+++ b/app/assets/javascripts/pages/groups/settings/index.js
@@ -1,5 +1,7 @@
import initRevokeButton from '~/deploy_tokens/init_revoke_button';
import initSearchSettings from '~/search_settings';
+import initDeployTokens from '~/deploy_tokens';
+initDeployTokens();
initSearchSettings();
initRevokeButton();
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 9cce6723bf7..6feb4c2188f 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
@@ -2,7 +2,7 @@
import { GlButton, GlEmptyState, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { s__, __ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { getBulkImportsHistory } from '~/rest_api';
@@ -107,7 +107,7 @@ export default {
this.pageInfo = parseIntPagination(normalizeHeaders(headers));
this.historyItems = historyItems;
} catch (e) {
- createFlash({ message: DEFAULT_ERROR, captureError: true, error: e });
+ createAlert({ message: DEFAULT_ERROR, captureError: true, error: e });
} finally {
this.loading = false;
}
diff --git a/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue b/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue
new file mode 100644
index 00000000000..20ce296bbec
--- /dev/null
+++ b/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlAvatarLabeled, GlListbox } from '@gitlab/ui';
+import { __ } from '~/locale';
+import searchUsersQuery from '~/graphql_shared/queries/users_search_all.query.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+
+const USERS_PER_PAGE = 20;
+
+export default {
+ components: {
+ GlAvatarLabeled,
+ GlListbox,
+ },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ usersQuery: {
+ query: searchUsersQuery,
+ variables() {
+ return {
+ search: this.search,
+ first: USERS_PER_PAGE,
+ };
+ },
+ update(data) {
+ return data;
+ },
+ debounce: DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
+ },
+ },
+ data() {
+ return {
+ user: '',
+ search: '',
+ };
+ },
+ computed: {
+ userId() {
+ return getIdFromGraphQLId(this.user);
+ },
+ users() {
+ return [
+ { text: __('(no user)'), value: '' },
+ ...(this.usersQuery?.users.nodes || []).map((u) => ({
+ username: `@${u.username}`,
+ avatarUrl: u.avatarUrl,
+ text: u.name,
+ value: u.id,
+ })),
+ ];
+ },
+ },
+ methods: {
+ clearTransform() {
+ // FIXME: workaround for listbox issue
+ // https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1986
+ const { listbox } = this.$refs;
+ if (listbox.querySelector('.dropdown-menu')) {
+ listbox.querySelector('.dropdown-menu').style.transform = '';
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-listbox
+ ref="listbox"
+ v-model="user"
+ :items="users"
+ searchable
+ is-check-centered
+ :searching="$apollo.loading"
+ @click.capture.native="clearTransform"
+ @search="search = $event"
+ >
+ <template #list-item="{ item }">
+ <gl-avatar-labeled
+ shape="circle"
+ :size="32"
+ :src="item.avatarUrl"
+ :label="item.text"
+ :sub-label="item.username"
+ />
+ </template>
+ </gl-listbox>
+ <input type="hidden" :name="name" :value="userId" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
index 86b80a0ba5b..ef549f20cf3 100644
--- a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
+++ b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
@@ -1,3 +1,19 @@
-import UsersSelect from '~/users_select';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import UserSelect from './components/user_select.vue';
-new UsersSelect(); // eslint-disable-line no-new
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+Array.from(document.querySelectorAll('.js-gitlab-user')).forEach(
+ (node) =>
+ new Vue({
+ el: node,
+ apolloProvider,
+ render: (h) => h(UserSelect, { props: { name: node.dataset.name } }),
+ }),
+);
diff --git a/app/assets/javascripts/pages/import/history/components/import_history_app.vue b/app/assets/javascripts/pages/import/history/components/import_history_app.vue
index db6f0c23dbd..09b1b3a9c0f 100644
--- a/app/assets/javascripts/pages/import/history/components/import_history_app.vue
+++ b/app/assets/javascripts/pages/import/history/components/import_history_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlEmptyState, GlIcon, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { s__, __ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { getProjects } from '~/rest_api';
import ImportStatus from '~/import_entities/components/import_status.vue';
@@ -104,7 +104,7 @@ export default {
this.pageInfo = parseIntPagination(normalizeHeaders(headers));
this.historyItems = historyItems;
} catch (e) {
- createFlash({ message: DEFAULT_ERROR, captureError: true, error: e });
+ createAlert({ message: DEFAULT_ERROR, captureError: true, error: e });
} finally {
this.loading = false;
}
diff --git a/app/assets/javascripts/pages/profiles/index.js b/app/assets/javascripts/pages/profiles/index.js
index 6afb3636998..91b20a05196 100644
--- a/app/assets/javascripts/pages/profiles/index.js
+++ b/app/assets/javascripts/pages/profiles/index.js
@@ -3,6 +3,7 @@ import '~/profile/gl_crop';
import Profile from '~/profile/profile';
import initSearchSettings from '~/search_settings';
import initPasswordPrompt from './password_prompt';
+import { initTimezoneDropdown } from './init_timezone_dropdown';
// eslint-disable-next-line func-names
$(document).on('input.ssh_key', '#key_key', function () {
@@ -21,3 +22,4 @@ new Profile(); // eslint-disable-line no-new
initSearchSettings();
initPasswordPrompt();
+initTimezoneDropdown();
diff --git a/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js b/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js
new file mode 100644
index 00000000000..80b911493a8
--- /dev/null
+++ b/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js
@@ -0,0 +1,34 @@
+import Vue from 'vue';
+import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
+
+export const initTimezoneDropdown = () => {
+ const el = document.querySelector('.js-timezone-dropdown');
+
+ if (!el) {
+ return null;
+ }
+
+ const { timezoneData, initialValue } = el.dataset;
+ const timezones = JSON.parse(timezoneData);
+
+ const timezoneDropdown = new Vue({
+ el,
+ data() {
+ return {
+ value: initialValue,
+ };
+ },
+ render(h) {
+ return h(TimezoneDropdown, {
+ props: {
+ value: this.value,
+ timezoneData: timezones,
+ name: 'user[timezone]',
+ },
+ class: 'gl-md-form-input-lg',
+ });
+ },
+ });
+
+ return timezoneDropdown;
+};
diff --git a/app/assets/javascripts/pages/projects/blame/show/index.js b/app/assets/javascripts/pages/projects/blame/show/index.js
index fa22c11d1d7..1e4b9de90f2 100644
--- a/app/assets/javascripts/pages/projects/blame/show/index.js
+++ b/app/assets/javascripts/pages/projects/blame/show/index.js
@@ -1,3 +1,5 @@
import initBlob from '~/pages/projects/init_blob';
+import redirectToCorrectPage from '~/blame/blame_redirect';
+redirectToCorrectPage();
initBlob();
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index eca3cf7ab13..af0097b415c 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import loadAwardsHandler from '~/awards_handler';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import Diff from '~/diff';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import initDeprecatedNotes from '~/init_deprecated_notes';
import { initDiffStatsDropdown } from '~/init_diff_stats_dropdown';
import axios from '~/lib/utils/axios_utils';
@@ -69,7 +69,7 @@ if (filesContainer.length) {
loadDiffStats();
})
.catch(() => {
- createFlash({ message: __('An error occurred while retrieving diff files') });
+ createAlert({ message: __('An error occurred while retrieving diff files') });
});
} else {
new Diff();
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
index b415e36bf09..30cefa3d717 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
@@ -12,7 +12,7 @@ import {
} from '@gitlab/ui';
import { kebabCase } from 'lodash';
import { buildApiUrl } from '~/api/api_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import csrf from '~/lib/utils/csrf';
import { redirectTo } from '~/lib/utils/url_utility';
@@ -220,7 +220,7 @@ export default {
redirectTo(data.web_url);
return;
} catch (error) {
- createFlash({
+ createAlert({
message: s__(
'ForkProject|An error occurred while forking the project. Please try again.',
),
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
index 2b3055ecd66..00e0649deed 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
@@ -9,7 +9,7 @@ import {
GlSearchBoxByType,
GlTruncate,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
import { s__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -41,7 +41,7 @@ export default {
return length > 0 && length < MINIMUM_SEARCH_LENGTH;
},
error(error) {
- createFlash({
+ createAlert({
message: s__(
'ForkProject|Something went wrong while loading data. Please refresh the page to try again.',
),
diff --git a/app/assets/javascripts/pages/projects/hooks/index.js b/app/assets/javascripts/pages/projects/hooks/index.js
index 2a120a690ef..ed476d25f8b 100644
--- a/app/assets/javascripts/pages/projects/hooks/index.js
+++ b/app/assets/javascripts/pages/projects/hooks/index.js
@@ -1,3 +1,5 @@
import initSearchSettings from '~/search_settings';
+import initWebhookForm from '~/webhooks';
initSearchSettings();
+initWebhookForm();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js
index 9a38c2cc765..65942464e2b 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js
@@ -2,7 +2,7 @@
import $ from 'jquery';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
@@ -39,7 +39,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error fetching refs'),
}),
);
diff --git a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
index 5179d1b31ab..406959c80ea 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -33,7 +33,7 @@ function initTargetBranchSelector() {
callback(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error fetching branches'),
}),
);
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 e284e7b2c5e..2399aafc9b5 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -2,14 +2,19 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
-import { initBulkUpdateSidebar, initIssueStatusSelect } from '~/issuable/bulk_update_sidebar';
+import {
+ initBulkUpdateSidebar,
+ initStatusDropdown,
+ initSubscriptionsDropdown,
+} from '~/issuable/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';
initBulkUpdateSidebar(ISSUABLE_INDEX.MERGE_REQUEST);
-initIssueStatusSelect();
+initStatusDropdown();
+initSubscriptionsDropdown();
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
IssuableFilteredSearchTokenKeys.removeTokensForKeys('iteration');
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
index 6dd21380bec..0edce2db0a3 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
@@ -1,3 +1,8 @@
+import initPipelineSchedulesFormApp from '~/pipeline_schedules/mount_pipeline_schedules_form_app';
import initForm from '../shared/init_form';
-initForm();
+if (gon.features?.pipelineSchedulesVue) {
+ initPipelineSchedulesFormApp('#pipeline-schedules-form-edit');
+} else {
+ initForm();
+}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
index 9513f42d9c9..7d0930f6424 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -1,9 +1,10 @@
import Vue from 'vue';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import initPipelineSchedulesApp from '~/pipeline_schedules/mount_pipeline_schedules_app';
import PipelineSchedulesTakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
-function initPipelineSchedules() {
+function initPipelineSchedulesCallout() {
const el = document.getElementById('pipeline-schedules-callout');
if (!el) {
@@ -15,6 +16,7 @@ function initPipelineSchedules() {
// eslint-disable-next-line no-new
new Vue({
el,
+ name: 'PipelineSchedulesCalloutRoot',
provide: {
docsUrl,
illustrationUrl,
@@ -25,6 +27,8 @@ function initPipelineSchedules() {
});
}
+// TODO: move take ownership feature into new Vue app
+// located in directory app/assets/javascripts/pipeline_schedules/components
function initTakeownershipModal() {
const modalId = 'pipeline-take-ownership-modal';
const buttonSelector = 'js-take-ownership-button';
@@ -63,5 +67,10 @@ function initTakeownershipModal() {
});
}
-initPipelineSchedules();
-initTakeownershipModal();
+initPipelineSchedulesCallout();
+
+if (gon.features?.pipelineSchedulesVue) {
+ initPipelineSchedulesApp();
+} else {
+ initTakeownershipModal();
+}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
index 6dd21380bec..06084fa729b 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
@@ -1,3 +1,8 @@
+import initPipelineSchedulesFormApp from '~/pipeline_schedules/mount_pipeline_schedules_form_app';
import initForm from '../shared/init_form';
-initForm();
+if (gon.features?.pipelineSchedulesVue) {
+ initPipelineSchedulesFormApp('#pipeline-schedules-form-new');
+} else {
+ initForm();
+}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
index 277d2e0d30a..bc467952551 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
@@ -1,4 +1,5 @@
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { formatTimezone } from '~/lib/utils/datetime_utility';
const defaultTimezone = { identifier: 'Etc/UTC', name: 'UTC', offset: 0 };
const defaults = {
@@ -17,8 +18,6 @@ export const formatUtcOffset = (offset) => {
return `${prefix} ${Math.abs(offset / 3600)}`;
};
-export const formatTimezone = (item) => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
-
export const findTimezoneByIdentifier = (tzList = [], identifier = null) => {
if (tzList && tzList.length && identifier && identifier.length) {
return tzList.find((tz) => tz.identifier === identifier) || null;
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index ccabaad5b2e..d177c67f133 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -4,7 +4,7 @@ import $ from 'jquery';
import { setCookie } from '~/lib/utils/common_utils';
import initClonePanel from '~/clone_panel';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { serializeForm } from '~/lib/utils/forms';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -80,7 +80,7 @@ export default class Project {
})
.then(({ data }) => callback(data))
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while getting projects'),
}),
);
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 6a9bd34db22..8909ff1f221 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -10,6 +10,7 @@ import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_to
import initSettingsPanels from '~/settings_panels';
import { initTokenAccess } from '~/token_access';
import { initCiSecureFiles } from '~/ci_secure_files';
+import initDeployTokens from '~/deploy_tokens';
// Initialize expandable settings panels
initSettingsPanels();
@@ -34,6 +35,7 @@ document.querySelector('.js-toggle-extra-settings').addEventListener('click', (e
});
registrySettingsApp();
+initDeployTokens();
initDeployFreeze();
initSettingsPipelinesTriggers();
diff --git a/app/assets/javascripts/pages/projects/settings/index.js b/app/assets/javascripts/pages/projects/settings/index.js
index cb787c60002..7e97cd865b7 100644
--- a/app/assets/javascripts/pages/projects/settings/index.js
+++ b/app/assets/javascripts/pages/projects/settings/index.js
@@ -1,5 +1,7 @@
import initRevokeButton from '~/deploy_tokens/init_revoke_button';
import initSearchSettings from '~/search_settings';
+import initDeployTokens from '~/deploy_tokens';
+initDeployTokens();
initSearchSettings();
initRevokeButton();
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index 655243eee30..d2263fa815d 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,5 +1,7 @@
import MirrorRepos from '~/mirrors/mirror_repos';
import mountBranchRules from '~/projects/settings/repository/branch_rules/mount_branch_rules';
+import mountDefaultBranchSelector from '~/projects/settings/mount_default_branch_selector';
+
import initForm from '../form';
initForm();
@@ -8,3 +10,4 @@ const mirrorReposContainer = document.querySelector('.js-mirror-settings');
if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
mountBranchRules(document.getElementById('js-branch-rules'));
+mountDefaultBranchSelector(document.querySelector('.js-select-default-branch'));
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index a82f485bf44..3e5c02bbf19 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -898,7 +898,9 @@ export default {
:help-path="pagesHelpPath"
:label="$options.i18n.pagesLabel"
:help-text="
- s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab.')
+ s__(
+ 'ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute.',
+ )
"
>
<project-feature-setting
@@ -979,20 +981,20 @@ export default {
name="project[project_feature_attributes][feature_flags_access_level]"
/>
</project-setting-row>
- <project-setting-row
- ref="releases-settings"
- :label="$options.i18n.releasesLabel"
- :help-text="$options.i18n.releasesHelpText"
- :help-path="releasesHelpPath"
- >
- <project-feature-setting
- v-model="releasesAccessLevel"
- :label="$options.i18n.releasesLabel"
- :options="featureAccessLevelOptions"
- name="project[project_feature_attributes][releases_access_level]"
- />
- </project-setting-row>
</template>
+ <project-setting-row
+ ref="releases-settings"
+ :label="$options.i18n.releasesLabel"
+ :help-text="$options.i18n.releasesHelpText"
+ :help-path="releasesHelpPath"
+ >
+ <project-feature-setting
+ v-model="releasesAccessLevel"
+ :label="$options.i18n.releasesLabel"
+ :options="featureAccessLevelOptions"
+ name="project[project_feature_attributes][releases_access_level]"
+ />
+ </project-setting-row>
</div>
<project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3">
<label class="js-emails-disabled">
diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js
index 7ea744a68a6..1848aa70cf0 100644
--- a/app/assets/javascripts/pages/sessions/new/username_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/username_validator.js
@@ -1,6 +1,6 @@
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import InputValidator from '~/validators/input_validator';
@@ -51,7 +51,7 @@ export default class UsernameValidator extends InputValidator {
);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while validating username'),
}),
);
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
index 10b95fd6f3c..b72579276e8 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
@@ -1,6 +1,6 @@
<script>
import { GlSkeletonLoader, GlSafeHtmlDirective, GlAlert } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { handleLocationHash } from '~/lib/utils/common_utils';
@@ -47,7 +47,7 @@ export default {
handleLocationHash();
})
.catch(() =>
- createFlash({
+ createAlert({
message: this.$options.i18n.renderingContentFailed,
}),
);
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 9acc1cb62a1..7b9656de362 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -8,21 +8,19 @@ import {
GlFormGroup,
GlFormInput,
GlFormSelect,
- GlSegmentedControl,
} from '@gitlab/ui';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-import axios from '~/lib/utils/axios_utils';
+import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave';
import csrf from '~/lib/utils/csrf';
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 MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import {
- CONTENT_EDITOR_LOADED_ACTION,
SAVED_USING_CONTENT_EDITOR_ACTION,
WIKI_CONTENT_EDITOR_TRACKING_LABEL,
WIKI_FORMAT_LABEL,
WIKI_FORMAT_UPDATED_ACTION,
+ CONTENT_EDITOR_LOADED_ACTION,
} from '../constants';
const trackingMixin = Tracking.mixin({
@@ -36,6 +34,29 @@ const MARKDOWN_LINK_TEXT = {
org: '[[page-slug]]',
};
+function getPagePath(pageInfo) {
+ return pageInfo.persisted ? pageInfo.path : pageInfo.createPath;
+}
+
+const autosaveKey = (pageInfo, field) => {
+ const path = pageInfo.persisted ? pageInfo.path : pageInfo.createPath;
+
+ return `${path}/${field}`;
+};
+
+const titleAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'title');
+const formatAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'format');
+const contentAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'content');
+const commitAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'commit');
+
+const getTitle = (pageInfo) => getDraft(titleAutosaveKey(pageInfo)) || pageInfo.title?.trim() || '';
+const getFormat = (pageInfo) =>
+ getDraft(formatAutosaveKey(pageInfo)) || pageInfo.format || 'markdown';
+const getContent = (pageInfo) => getDraft(contentAutosaveKey(pageInfo)) || pageInfo.content || '';
+const getCommitMessage = (pageInfo) =>
+ getDraft(commitAutosaveKey(pageInfo)) || pageInfo.commitMessage || '';
+const getIsFormDirty = (pageInfo) => Boolean(getDraft(titleAutosaveKey(pageInfo)));
+
export default {
i18n: {
title: {
@@ -74,10 +95,6 @@ export default {
},
cancel: s__('WikiPage|Cancel'),
},
- switchEditingControlOptions: [
- { text: s__('Wiki Page|Source'), value: 'source' },
- { text: s__('Wiki Page|Rich text'), value: 'richText' },
- ],
components: {
GlIcon,
GlForm,
@@ -87,26 +104,21 @@ export default {
GlSprintf,
GlLink,
GlButton,
- GlSegmentedControl,
- MarkdownField,
- LocalStorageSync,
- ContentEditor: () =>
- import(
- /* webpackChunkName: 'content_editor' */ '~/content_editor/components/content_editor.vue'
- ),
+ MarkdownEditor,
},
mixins: [trackingMixin],
inject: ['formatOptions', 'pageInfo'],
data() {
return {
editingMode: 'source',
- title: this.pageInfo.title?.trim() || '',
- format: this.pageInfo.format || 'markdown',
- content: this.pageInfo.content || '',
- commitMessage: '',
- isDirty: false,
+ title: getTitle(this.pageInfo),
+ format: getFormat(this.pageInfo),
+ content: getContent(this.pageInfo),
+ commitMessage: getCommitMessage(this.pageInfo),
contentEditorEmpty: false,
+ isContentEditorActive: false,
switchEditingControlDisabled: false,
+ isFormDirty: getIsFormDirty(this.pageInfo),
};
},
computed: {
@@ -117,7 +129,7 @@ export default {
return csrf.token;
},
formAction() {
- return this.pageInfo.persisted ? this.pageInfo.path : this.pageInfo.createPath;
+ return getPagePath(this.pageInfo);
},
helpPath() {
return setUrlFragment(
@@ -162,15 +174,9 @@ export default {
disableSubmitButton() {
return this.noContent || !this.title;
},
- isContentEditorActive() {
- return this.isMarkdownFormat && this.useContentEditor;
- },
- useContentEditor() {
- return this.editingMode === 'richText';
- },
},
mounted() {
- this.updateCommitMessage();
+ if (!this.commitMessage) this.updateCommitMessage();
window.addEventListener('beforeunload', this.onPageUnload);
},
@@ -178,51 +184,45 @@ export default {
window.removeEventListener('beforeunload', this.onPageUnload);
},
methods: {
- renderMarkdown(content) {
- return axios
- .post(this.pageInfo.markdownPreviewPath, { text: content })
- .then(({ data }) => data.body);
- },
-
- setEditingMode(editingMode) {
- this.editingMode = editingMode;
- },
-
async handleFormSubmit(e) {
- e.preventDefault();
+ this.isFormDirty = false;
- if (this.useContentEditor) {
- this.trackFormSubmit();
- }
+ e.preventDefault();
+ this.trackFormSubmit();
this.trackWikiFormat();
// Wait until form field values are refreshed
await this.$nextTick();
e.target.submit();
+ },
- this.isDirty = false;
+ updateDrafts() {
+ updateDraft(titleAutosaveKey(this.pageInfo), this.title);
+ updateDraft(formatAutosaveKey(this.pageInfo), this.format);
+ updateDraft(contentAutosaveKey(this.pageInfo), this.content);
+ updateDraft(commitAutosaveKey(this.pageInfo), this.commitMessage);
},
- handleContentChange() {
- this.isDirty = true;
+ clearDrafts() {
+ clearDraft(titleAutosaveKey(this.pageInfo));
+ clearDraft(formatAutosaveKey(this.pageInfo));
+ clearDraft(contentAutosaveKey(this.pageInfo));
+ clearDraft(commitAutosaveKey(this.pageInfo));
},
- handleContentEditorChange({ empty, markdown, changed }) {
+ handleContentEditorChange({ empty, markdown }) {
this.contentEditorEmpty = empty;
- this.isDirty = changed;
this.content = markdown;
},
- onPageUnload(event) {
- if (!this.isDirty) return undefined;
-
- event.preventDefault();
-
- // eslint-disable-next-line no-param-reassign
- event.returnValue = '';
- return '';
+ onPageUnload() {
+ if (this.isFormDirty) {
+ this.updateDrafts();
+ } else {
+ this.clearDrafts();
+ }
},
updateCommitMessage() {
@@ -235,8 +235,13 @@ export default {
this.commitMessage = newCommitMessage;
},
- trackContentEditorLoaded() {
- this.track(CONTENT_EDITOR_LOADED_ACTION);
+ notifyContentEditorActive() {
+ this.isContentEditorActive = true;
+ this.trackContentEditorLoaded();
+ },
+
+ notifyContentEditorInactive() {
+ this.isContentEditorActive = false;
},
trackFormSubmit() {
@@ -256,12 +261,12 @@ export default {
});
},
- enableSwitchEditingControl() {
- this.switchEditingControlDisabled = false;
+ trackContentEditorLoaded() {
+ this.track(CONTENT_EDITOR_LOADED_ACTION);
},
- disableSwitchEditingControl() {
- this.switchEditingControlDisabled = true;
+ submitFormWithShortcut() {
+ this.$refs.form.submit();
},
},
};
@@ -269,10 +274,12 @@ export default {
<template>
<gl-form
+ ref="form"
:action="formAction"
method="post"
class="wiki-form common-note-form gl-mt-3 js-quick-submit"
@submit="handleFormSubmit"
+ @input="isFormDirty = true"
>
<input :value="csrfToken" type="hidden" name="authenticity_token" />
<input v-if="pageInfo.persisted" type="hidden" name="_method" value="put" />
@@ -329,74 +336,23 @@ export default {
<div class="row" data-testid="wiki-form-content-fieldset">
<div class="col-sm-12 row-sm-5">
<gl-form-group>
- <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-start gl-mb-3">
- <gl-segmented-control
- data-testid="toggle-editing-mode-button"
- data-qa-selector="editing_mode_button"
- class="gl-display-flex"
- :checked="editingMode"
- :options="$options.switchEditingControlOptions"
- :disabled="switchEditingControlDisabled"
- @input="setEditingMode"
- />
- </div>
- <local-storage-sync
- storage-key="gl-wiki-content-editor-enabled"
- :value="editingMode"
- @input="setEditingMode"
- />
- <markdown-field
- v-if="!isContentEditorActive"
- :markdown-preview-path="pageInfo.markdownPreviewPath"
- :can-attach-file="true"
- :enable-autocomplete="true"
- :textarea-value="content"
+ <markdown-editor
+ v-model="content"
+ :render-markdown-path="pageInfo.markdownPreviewPath"
:markdown-docs-path="pageInfo.markdownHelpPath"
:uploads-path="pageInfo.uploadsPath"
+ :enable-content-editor="isMarkdownFormat"
:enable-preview="isMarkdownFormat"
- class="bordered-box"
- >
- <template #textarea>
- <textarea
- id="wiki_content"
- ref="textarea"
- v-model="content"
- name="wiki[content]"
- class="note-textarea js-gfm-input js-autosize markdown-area"
- dir="auto"
- data-supports-quick-actions="false"
- data-qa-selector="wiki_content_textarea"
- :autofocus="pageInfo.persisted"
- :aria-label="$options.i18n.content.label"
- :placeholder="$options.i18n.content.placeholder"
- @input="handleContentChange"
- >
- </textarea>
- </template>
- </markdown-field>
- <div v-if="isContentEditorActive">
- <content-editor
- :render-markdown="renderMarkdown"
- :uploads-path="pageInfo.uploadsPath"
- :markdown="content"
- @initialized="trackContentEditorLoaded"
- @change="handleContentEditorChange"
- @loading="disableSwitchEditingControl"
- @loadingSuccess="enableSwitchEditingControl"
- @loadingError="enableSwitchEditingControl"
- />
- <input
- id="wiki_content"
- v-model.trim="content"
- type="hidden"
- name="wiki[content]"
- data-qa-selector="wiki_hidden_content"
- />
- </div>
-
- <div class="clearfix"></div>
- <div class="error-alert"></div>
-
+ :init-on-autofocus="pageInfo.persisted"
+ :form-field-placeholder="$options.i18n.content.placeholder"
+ :form-field-aria-label="$options.i18n.content.label"
+ form-field-id="wiki_content"
+ form-field-name="wiki[content]"
+ @contentEditor="notifyContentEditorActive"
+ @markdownField="notifyContentEditorInactive"
+ @keydown.ctrl.enter="submitFormShortcut"
+ @keydown.meta.enter="submitFormShortcut"
+ />
<div class="form-text gl-text-gray-600">
<gl-sprintf
v-if="displayWikiSpecificMarkdownHelp"
@@ -447,9 +403,14 @@ export default {
:disabled="disableSubmitButton"
>{{ submitButtonText }}</gl-button
>
- <gl-button data-testid="wiki-cancel-button" :href="cancelFormPath" class="float-right">{{
- $options.i18n.cancel
- }}</gl-button>
+ <gl-button
+ data-testid="wiki-cancel-button"
+ :href="cancelFormPath"
+ class="float-right"
+ @click="isFormDirty = false"
+ >
+ {{ $options.i18n.cancel }}</gl-button
+ >
</div>
</gl-form>
</template>
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 9e0af426f6e..fb761725c43 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -1,7 +1,7 @@
import { select } from 'd3-selection';
import $ from 'jquery';
import { last } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import dateFormat from '~/lib/dateformat';
import axios from '~/lib/utils/axios_utils';
import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
@@ -151,7 +151,7 @@ export default class ActivityCalendar {
.select(container)
.append('svg')
.attr('width', width)
- .attr('height', 167)
+ .attr('height', 169)
.attr('class', 'contrib-calendar');
}
@@ -302,7 +302,7 @@ export default class ActivityCalendar {
});
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while retrieving calendar activity'),
}),
);
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index ddc880db227..f35f9341fa1 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -1,9 +1,10 @@
<script>
-import pdfjsLib from 'pdfjs-dist/build/pdf';
-import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
+import { getDocument, GlobalWorkerOptions } from 'pdfjs-dist/legacy/build/pdf';
import Page from './page/index.vue';
+GlobalWorkerOptions.workerSrc = '/assets/webpack/pdfjs/pdf.worker.min.js';
+
export default {
components: { Page },
props: {
@@ -30,18 +31,16 @@ export default {
},
watch: { pdf: 'load' },
mounted() {
- pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
if (this.hasPDF) this.load();
},
methods: {
load() {
this.pages = [];
- return pdfjsLib
- .getDocument({
- url: this.document,
- cMapUrl: '/assets/webpack/cmaps/',
- cMapPacked: true,
- })
+ return getDocument({
+ url: this.document,
+ cMapUrl: '/assets/webpack/pdfjs/cmaps/',
+ cMapPacked: true,
+ })
.promise.then(this.renderPages)
.then((pages) => {
this.pages = pages;
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index 7e331bdd91d..6ee33902a01 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -1,4 +1,4 @@
-import createFlash from './flash';
+import { createAlert } from '~/flash';
import axios from './lib/utils/axios_utils';
import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
@@ -73,7 +73,7 @@ export default class PersistentUserCallout {
}
})
.catch(() => {
- createFlash({
+ createAlert({
message: __(
'An error occurred while dismissing the alert. Refresh the page and try again.',
),
@@ -94,7 +94,7 @@ export default class PersistentUserCallout {
window.location.assign(href);
})
.catch(() => {
- createFlash({
+ createAlert({
message: __(
'An error occurred while acknowledging the notification. Refresh the page and try again.',
),
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
index 3e87088e77e..7d2b9cd3d42 100644
--- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
+++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
@@ -15,11 +15,20 @@ export default {
'Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started.',
),
btnText: __('Configure pipeline'),
+ externalCiNote: __("This project's pipeline configuration is located outside this repository"),
+ externalCiInstructions: __(
+ 'To edit the pipeline configuration, you must go to the project or external site that hosts the file.',
+ ),
},
inject: {
emptyStateIllustrationPath: {
default: '',
},
+ usesExternalConfig: {
+ default: false,
+ type: Boolean,
+ required: false,
+ },
},
methods: {
createEmptyConfigFile() {
@@ -33,22 +42,31 @@ export default {
<pipeline-editor-file-nav v-on="$listeners" />
<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>
- <p class="gl-mt-3">
- <gl-sprintf :message="$options.i18n.body">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
- <gl-button
- variant="confirm"
- class="gl-mt-3"
- data-qa-selector="create_new_ci_button"
- @click="createEmptyConfigFile"
+ <div
+ v-if="usesExternalConfig"
+ class="gl-display-flex gl-flex-direction-column gl-align-items-center"
>
- {{ $options.i18n.btnText }}
- </gl-button>
+ <h1 class="gl-font-size-h1">{{ $options.i18n.externalCiNote }}</h1>
+ <p class="gl-mt-3">{{ $options.i18n.externalCiInstructions }}</p>
+ </div>
+ <div v-else class="gl-display-flex gl-flex-direction-column gl-align-items-center">
+ <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
+ <p class="gl-mt-3">
+ <gl-sprintf :message="$options.i18n.body">
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+ <gl-button
+ variant="confirm"
+ class="gl-mt-3"
+ data-qa-selector="create_new_ci_button"
+ @click="createEmptyConfigFile"
+ >
+ {{ $options.i18n.btnText }}
+ </gl-button>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 13dad0b2459..6d91c339833 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import { parseBoolean } from '~/lib/utils/common_utils';
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.query.graphql';
@@ -42,6 +43,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectNamespace,
simulatePipelineHelpPagePath,
totalBranches,
+ usesExternalConfig,
validateTabIllustrationPath,
ymlHelpPagePath,
} = el.dataset;
@@ -133,6 +135,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectNamespace,
simulatePipelineHelpPagePath,
totalBranches: parseInt(totalBranches, 10),
+ usesExternalConfig: parseBoolean(usesExternalConfig),
validateTabIllustrationPath,
ymlHelpPagePath,
},
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 548769eb214..ff848a973e3 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -40,7 +40,7 @@ export default {
PipelineEditorHome,
PipelineEditorMessages,
},
- inject: ['ciConfigPath', 'newMergeRequestPath', 'projectFullPath'],
+ inject: ['ciConfigPath', 'newMergeRequestPath', 'projectFullPath', 'usesExternalConfig'],
data() {
return {
ciConfigData: {},
@@ -397,7 +397,7 @@ export default {
<div class="gl-mt-4 gl-relative" data-qa-selector="pipeline_editor_app">
<gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
<pipeline-editor-empty-state
- v-else-if="showStartScreen"
+ v-else-if="showStartScreen || usesExternalConfig"
@createEmptyConfigFile="setNewEmptyCiConfigFile"
@refetchContent="refetchContent"
/>
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
index 2d5c01a58b7..1972125ed56 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -162,7 +162,7 @@ export default {
</div>
</div>
<commit-section
- v-if="showCommitForm"
+ v-show="showCommitForm"
:ref="$options.commitSectionRef"
:ci-file-content="ciFileContent"
:commit-sha="commitSha"
diff --git a/app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue b/app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue
index 529ec4897b4..cd7cb7f8393 100644
--- a/app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue
@@ -401,7 +401,7 @@ export default {
<div
v-for="(variable, index) in variables"
:key="variable.uniqueId"
- class="gl-mb-3 gl-ml-n3 gl-pb-2"
+ class="gl-mb-3 gl-pb-2"
data-testid="ci-variable-row"
data-qa-selector="ci_variable_row_container"
>
diff --git a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
index 529ec4897b4..a9af1181027 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -17,17 +17,11 @@ import {
import * as Sentry from '@sentry/browser';
import { uniqueId } from 'lodash';
import Vue from 'vue';
-import axios from '~/lib/utils/axios_utils';
-import { backOff } from '~/lib/utils/common_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__, __, n__ } from '~/locale';
-import {
- VARIABLE_TYPE,
- FILE_TYPE,
- CONFIG_VARIABLES_TIMEOUT,
- CC_VALIDATION_REQUIRED_ERROR,
-} from '../constants';
+import { VARIABLE_TYPE, FILE_TYPE, CC_VALIDATION_REQUIRED_ERROR } from '../constants';
+import createPipelineMutation from '../graphql/mutations/create_pipeline.mutation.graphql';
+import ciConfigVariablesQuery from '../graphql/queries/ci_config_variables.graphql';
import filterVariables from '../utils/filter_variables';
import RefsDropdown from './refs_dropdown.vue';
@@ -76,10 +70,6 @@ export default {
type: String,
required: true,
},
- configVariablesPath: {
- type: String,
- required: true,
- },
defaultBranch: {
type: String,
required: true,
@@ -97,6 +87,10 @@ export default {
required: false,
default: () => ({}),
},
+ projectPath: {
+ type: String,
+ required: true,
+ },
refParam: {
type: String,
required: false,
@@ -116,19 +110,77 @@ export default {
return {
refValue: {
shortName: this.refParam,
+ // this is needed until we add support for ref type in url query strings
+ // ensure default branch is called with full ref on load
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/287815
+ fullName: this.refParam === this.defaultBranch ? `refs/heads/${this.refParam}` : undefined,
},
form: {},
errorTitle: null,
error: null,
+ predefinedValueOptions: {},
warnings: [],
totalWarnings: 0,
isWarningDismissed: false,
- isLoading: false,
submitted: false,
ccAlertDismissed: false,
};
},
+ apollo: {
+ ciConfigVariables: {
+ query: ciConfigVariablesQuery,
+ // Skip when variables already cached in `form`
+ skip() {
+ return Object.keys(this.form).includes(this.refFullName);
+ },
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ ref: this.refQueryParam,
+ };
+ },
+ update({ project }) {
+ return project?.ciConfigVariables || [];
+ },
+ result({ data }) {
+ const predefinedVars = data?.project?.ciConfigVariables || [];
+ const params = {};
+ const descriptions = {};
+
+ predefinedVars.forEach(({ description, key, value, valueOptions }) => {
+ if (description) {
+ params[key] = value;
+ descriptions[key] = description;
+ this.predefinedValueOptions[key] = valueOptions;
+ }
+ });
+
+ Vue.set(this.form, this.refFullName, { descriptions, variables: [] });
+
+ // Add default variables from yml
+ this.setVariableParams(this.refFullName, VARIABLE_TYPE, params);
+
+ // Add/update variables, e.g. from query string
+ if (this.variableParams) {
+ this.setVariableParams(this.refFullName, VARIABLE_TYPE, this.variableParams);
+ }
+
+ if (this.fileParams) {
+ this.setVariableParams(this.refFullName, FILE_TYPE, this.fileParams);
+ }
+
+ // Adds empty var at the end of the form
+ this.addEmptyVariable(this.refFullName);
+ },
+ error(error) {
+ Sentry.captureException(error);
+ },
+ },
+ },
computed: {
+ isLoading() {
+ return this.$apollo.queries.ciConfigVariables.loading;
+ },
overMaxWarningsLimit() {
return this.totalWarnings > this.maxWarnings;
},
@@ -147,6 +199,9 @@ export default {
refFullName() {
return this.refValue.fullName;
},
+ refQueryParam() {
+ return this.refFullName || this.refShortName;
+ },
variables() {
return this.form[this.refFullName]?.variables ?? [];
},
@@ -157,21 +212,6 @@ export default {
return this.error === CC_VALIDATION_REQUIRED_ERROR && !this.ccAlertDismissed;
},
},
- watch: {
- refValue() {
- this.loadConfigVariablesForm();
- },
- },
- created() {
- // this is needed until we add support for ref type in url query strings
- // ensure default branch is called with full ref on load
- // https://gitlab.com/gitlab-org/gitlab/-/issues/287815
- if (this.refValue.shortName === this.defaultBranch) {
- this.refValue.fullName = `refs/heads/${this.refValue.shortName}`;
- }
-
- this.loadConfigVariablesForm();
- },
methods: {
addEmptyVariable(refValue) {
const { variables } = this.form[refValue];
@@ -204,132 +244,57 @@ export default {
});
}
},
- setVariableType(key, type) {
+ setVariableAttribute(key, attribute, value) {
const { variables } = this.form[this.refFullName];
const variable = variables.find((v) => v.key === key);
- variable.variable_type = type;
+ variable[attribute] = value;
},
setVariableParams(refValue, type, paramsObj) {
Object.entries(paramsObj).forEach(([key, value]) => {
this.setVariable(refValue, type, key, value);
});
},
+ shouldShowValuesDropdown(key) {
+ return this.predefinedValueOptions[key]?.length > 1;
+ },
removeVariable(index) {
this.variables.splice(index, 1);
},
canRemove(index) {
return index < this.variables.length - 1;
},
- loadConfigVariablesForm() {
- // Skip when variables already cached in `form`
- if (this.form[this.refFullName]) {
- return;
- }
-
- this.fetchConfigVariables(this.refFullName || this.refShortName)
- .then(({ descriptions, params }) => {
- Vue.set(this.form, this.refFullName, {
- variables: [],
- descriptions,
- });
-
- // Add default variables from yml
- this.setVariableParams(this.refFullName, VARIABLE_TYPE, params);
- })
- .catch(() => {
- Vue.set(this.form, this.refFullName, {
- variables: [],
- descriptions: {},
- });
- })
- .finally(() => {
- // Add/update variables, e.g. from query string
- if (this.variableParams) {
- this.setVariableParams(this.refFullName, VARIABLE_TYPE, this.variableParams);
- }
- if (this.fileParams) {
- this.setVariableParams(this.refFullName, FILE_TYPE, this.fileParams);
- }
-
- // Adds empty var at the end of the form
- this.addEmptyVariable(this.refFullName);
- });
- },
- fetchConfigVariables(refValue) {
- this.isLoading = true;
-
- return backOff((next, stop) => {
- axios
- .get(this.configVariablesPath, {
- params: {
- sha: refValue,
- },
- })
- .then(({ data, status }) => {
- if (status === httpStatusCodes.NO_CONTENT) {
- next();
- } else {
- this.isLoading = false;
- stop(data);
- }
- })
- .catch((error) => {
- stop(error);
- });
- }, CONFIG_VARIABLES_TIMEOUT)
- .then((data) => {
- const params = {};
- const descriptions = {};
-
- Object.entries(data).forEach(([key, { value, description }]) => {
- if (description) {
- params[key] = value;
- descriptions[key] = description;
- }
- });
-
- return { params, descriptions };
- })
- .catch((error) => {
- this.isLoading = false;
-
- Sentry.captureException(error);
-
- return { params: {}, descriptions: {} };
- });
- },
- createPipeline() {
+ async createPipeline() {
this.submitted = true;
this.ccAlertDismissed = false;
- return axios
- .post(this.pipelinesPath, {
+ const { data } = await this.$apollo.mutate({
+ mutation: createPipelineMutation,
+ variables: {
+ endpoint: this.pipelinesPath,
// send shortName as fall back for query params
// https://gitlab.com/gitlab-org/gitlab/-/issues/287815
- ref: this.refValue.fullName || this.refShortName,
- variables_attributes: filterVariables(this.variables),
- })
- .then(({ data }) => {
- redirectTo(`${this.pipelinesPath}/${data.id}`);
- })
- .catch((err) => {
- // always re-enable submit button
- this.submitted = false;
+ ref: this.refQueryParam,
+ variablesAttributes: filterVariables(this.variables),
+ },
+ });
- const {
- errors = [],
- warnings = [],
- total_warnings: totalWarnings = 0,
- } = err.response.data;
- const [error] = errors;
+ const { id, errors, totalWarnings, warnings } = data.createPipeline;
- this.reportError({
- title: i18n.submitErrorTitle,
- error,
- warnings,
- totalWarnings,
- });
- });
+ if (id) {
+ redirectTo(`${this.pipelinesPath}/${id}`);
+ return;
+ }
+
+ // always re-enable submit button
+ this.submitted = false;
+ const [error] = errors;
+
+ this.reportError({
+ title: i18n.submitErrorTitle,
+ error,
+ warnings,
+ totalWarnings,
+ });
},
onRefsLoadingError(error) {
this.reportError({ title: i18n.refsLoadingErrorTitle });
@@ -401,7 +366,7 @@ export default {
<div
v-for="(variable, index) in variables"
:key="variable.uniqueId"
- class="gl-mb-3 gl-ml-n3 gl-pb-2"
+ class="gl-mb-3 gl-pb-2"
data-testid="ci-variable-row"
data-qa-selector="ci_variable_row_container"
>
@@ -416,7 +381,7 @@ export default {
<gl-dropdown-item
v-for="type in Object.keys($options.typeOptions)"
:key="type"
- @click="setVariableType(variable.key, type)"
+ @click="setVariableAttribute(variable.key, 'variable_type', type)"
>
{{ $options.typeOptions[type] }}
</gl-dropdown-item>
@@ -429,7 +394,24 @@ export default {
data-qa-selector="ci_variable_key_field"
@change="addEmptyVariable(refFullName)"
/>
+ <gl-dropdown
+ v-if="shouldShowValuesDropdown(variable.key)"
+ :text="variable.value"
+ :class="$options.formElementClasses"
+ class="gl-flex-grow-1 gl-mr-0!"
+ data-testid="pipeline-form-ci-variable-value-dropdown"
+ >
+ <gl-dropdown-item
+ v-for="value in predefinedValueOptions[variable.key]"
+ :key="value"
+ data-testid="pipeline-form-ci-variable-value-dropdown-items"
+ @click="setVariableAttribute(variable.key, 'value', value)"
+ >
+ {{ value }}
+ </gl-dropdown-item>
+ </gl-dropdown>
<gl-form-textarea
+ v-else
v-model="variable.value"
:placeholder="s__('CiVariables|Input variable value')"
class="gl-mb-3"
diff --git a/app/assets/javascripts/pipeline_new/graphql/mutations/create_pipeline.mutation.graphql b/app/assets/javascripts/pipeline_new/graphql/mutations/create_pipeline.mutation.graphql
new file mode 100644
index 00000000000..a76e8f6b95b
--- /dev/null
+++ b/app/assets/javascripts/pipeline_new/graphql/mutations/create_pipeline.mutation.graphql
@@ -0,0 +1,9 @@
+mutation createPipeline($endpoint: String, $ref: String, $variablesAttributes: Array) {
+ createPipeline(endpoint: $endpoint, ref: $ref, variablesAttributes: $variablesAttributes)
+ @client {
+ id
+ errors
+ totalWarnings
+ warnings
+ }
+}
diff --git a/app/assets/javascripts/pipeline_new/graphql/queries/ci_config_variables.graphql b/app/assets/javascripts/pipeline_new/graphql/queries/ci_config_variables.graphql
new file mode 100644
index 00000000000..648cd8b66b5
--- /dev/null
+++ b/app/assets/javascripts/pipeline_new/graphql/queries/ci_config_variables.graphql
@@ -0,0 +1,11 @@
+query ciConfigVariables($fullPath: ID!, $ref: String!) {
+ project(fullPath: $fullPath) {
+ id
+ ciConfigVariables(sha: $ref) {
+ description
+ key
+ value
+ valueOptions
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_new/graphql/resolvers.js b/app/assets/javascripts/pipeline_new/graphql/resolvers.js
new file mode 100644
index 00000000000..7b0f58e8cf9
--- /dev/null
+++ b/app/assets/javascripts/pipeline_new/graphql/resolvers.js
@@ -0,0 +1,29 @@
+import axios from '~/lib/utils/axios_utils';
+
+export const resolvers = {
+ Mutation: {
+ createPipeline: (_, { endpoint, ref, variablesAttributes }) => {
+ return axios
+ .post(endpoint, { ref, variables_attributes: variablesAttributes })
+ .then((response) => {
+ const { id } = response.data;
+ return {
+ id,
+ errors: [],
+ totalWarnings: 0,
+ warnings: [],
+ };
+ })
+ .catch((err) => {
+ const { errors = [], totalWarnings = 0, warnings = [] } = err.response.data;
+
+ return {
+ id: null,
+ errors,
+ totalWarnings,
+ warnings,
+ };
+ });
+ },
+ },
+};
diff --git a/app/assets/javascripts/pipeline_new/index.js b/app/assets/javascripts/pipeline_new/index.js
index e3f363f4ada..60b4c93d1d5 100644
--- a/app/assets/javascripts/pipeline_new/index.js
+++ b/app/assets/javascripts/pipeline_new/index.js
@@ -1,6 +1,9 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import LegacyPipelineNewForm from './components/legacy_pipeline_new_form.vue';
import PipelineNewForm from './components/pipeline_new_form.vue';
+import { resolvers } from './graphql/resolvers';
const mountLegacyPipelineNewForm = (el) => {
const {
@@ -51,12 +54,12 @@ const mountPipelineNewForm = (el) => {
projectRefsEndpoint,
// props
- configVariablesPath,
defaultBranch,
fileParam,
maxWarnings,
pipelinesPath,
projectId,
+ projectPath,
refParam,
settingsLink,
varParam,
@@ -65,22 +68,27 @@ const mountPipelineNewForm = (el) => {
const variableParams = JSON.parse(varParam);
const fileParams = JSON.parse(fileParam);
- // TODO: add apolloProvider
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(resolvers),
+ });
return new Vue({
el,
+ apolloProvider,
provide: {
projectRefsEndpoint,
},
render(createElement) {
return createElement(PipelineNewForm, {
props: {
- configVariablesPath,
defaultBranch,
fileParams,
maxWarnings: Number(maxWarnings),
pipelinesPath,
projectId,
+ projectPath,
refParam,
settingsLink,
variableParams,
diff --git a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules.vue b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules.vue
new file mode 100644
index 00000000000..4a08a82275a
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules.vue
@@ -0,0 +1,134 @@
+<script>
+import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+import deletePipelineScheduleMutation from '../graphql/mutations/delete_pipeline_schedule.mutation.graphql';
+import getPipelineSchedulesQuery from '../graphql/queries/get_pipeline_schedules.query.graphql';
+import PipelineSchedulesTable from './table/pipeline_schedules_table.vue';
+
+export default {
+ i18n: {
+ schedulesFetchError: s__('PipelineSchedules|There was a problem fetching pipeline schedules.'),
+ scheduleDeleteError: s__(
+ 'PipelineSchedules|There was a problem deleting the pipeline schedule.',
+ ),
+ },
+ modal: {
+ id: 'delete-pipeline-schedule-modal',
+ deleteConfirmation: s__(
+ 'PipelineSchedules|Are you sure you want to delete this pipeline schedule?',
+ ),
+ actionPrimary: {
+ text: s__('PipelineSchedules|Delete pipeline schedule'),
+ attributes: [{ variant: 'danger' }],
+ },
+ actionCancel: {
+ text: __('Cancel'),
+ attributes: [],
+ },
+ },
+ components: {
+ GlAlert,
+ GlLoadingIcon,
+ GlModal,
+ PipelineSchedulesTable,
+ },
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ schedules: {
+ query: getPipelineSchedulesQuery,
+ variables() {
+ return {
+ projectPath: this.fullPath,
+ };
+ },
+ update({ project }) {
+ return project?.pipelineSchedules?.nodes || [];
+ },
+ error() {
+ this.reportError(this.$options.i18n.schedulesFetchError);
+ },
+ },
+ },
+ data() {
+ return {
+ schedules: [],
+ hasError: false,
+ errorMessage: '',
+ scheduleToDeleteId: null,
+ showModal: false,
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.schedules.loading;
+ },
+ },
+ methods: {
+ reportError(error) {
+ this.hasError = true;
+ this.errorMessage = error;
+ },
+ showDeleteModal(id) {
+ this.showModal = true;
+ this.scheduleToDeleteId = id;
+ },
+ hideModal() {
+ this.showModal = false;
+ this.scheduleToDeleteId = null;
+ },
+ async deleteSchedule() {
+ try {
+ const {
+ data: {
+ pipelineScheduleDelete: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: deletePipelineScheduleMutation,
+ variables: { id: this.scheduleToDeleteId },
+ });
+
+ if (errors.length > 0) {
+ throw new Error();
+ } else {
+ this.$apollo.queries.schedules.refetch();
+ }
+ } catch {
+ this.reportError(this.$options.i18n.scheduleDeleteError);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert v-if="hasError" class="gl-mb-2" variant="danger" @dismiss="hasError = false">
+ {{ errorMessage }}
+ </gl-alert>
+
+ <gl-loading-icon v-if="isLoading" size="lg" />
+
+ <!-- Tabs will be addressed in #371989 -->
+
+ <template v-else>
+ <pipeline-schedules-table :schedules="schedules" @showDeleteModal="showDeleteModal" />
+
+ <gl-modal
+ :visible="showModal"
+ :title="$options.modal.actionPrimary.text"
+ :modal-id="$options.modal.id"
+ :action-primary="$options.modal.actionPrimary"
+ :action-cancel="$options.modal.actionCancel"
+ size="sm"
+ @primary="deleteSchedule"
+ @hide="hideModal"
+ >
+ {{ $options.modal.deleteConfirmation }}
+ </gl-modal>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_form.vue b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_form.vue
new file mode 100644
index 00000000000..6e24ac6b8d4
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_form.vue
@@ -0,0 +1,18 @@
+<script>
+import { GlForm } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlForm,
+ },
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form />
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_actions.vue b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_actions.vue
new file mode 100644
index 00000000000..76d118bf52d
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_actions.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlButton, GlButtonGroup, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export const i18n = {
+ playTooltip: s__('PipelineSchedules|Run pipeline schedule'),
+ editTooltip: s__('PipelineSchedules|Edit pipeline schedule'),
+ deleteTooltip: s__('PipelineSchedules|Delete pipeline schedule'),
+ takeOwnershipTooltip: s__('PipelineSchedules|Take ownership of pipeline schedule'),
+};
+
+export default {
+ i18n,
+ components: {
+ GlButton,
+ GlButtonGroup,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ schedule: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ canPlay() {
+ return this.schedule.userPermissions.playPipelineSchedule;
+ },
+ canTakeOwnership() {
+ return this.schedule.userPermissions.takeOwnershipPipelineSchedule;
+ },
+ canUpdate() {
+ return this.schedule.userPermissions.updatePipelineSchedule;
+ },
+ canRemove() {
+ return this.schedule.userPermissions.adminPipelineSchedule;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-justify-content-end">
+ <gl-button-group>
+ <gl-button v-if="canPlay" v-gl-tooltip :title="$options.i18n.playTooltip" icon="play" />
+ <gl-button
+ v-if="canTakeOwnership"
+ v-gl-tooltip
+ :title="$options.i18n.takeOwnershipTooltip"
+ icon="user"
+ />
+ <gl-button v-if="canUpdate" v-gl-tooltip :title="$options.i18n.editTooltip" icon="pencil" />
+ <gl-button
+ v-if="canRemove"
+ v-gl-tooltip
+ :title="$options.i18n.deleteTooltip"
+ icon="remove"
+ variant="danger"
+ data-testid="delete-pipeline-schedule-btn"
+ @click="$emit('showDeleteModal', schedule.id)"
+ />
+ </gl-button-group>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline.vue b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline.vue
new file mode 100644
index 00000000000..216796b357c
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline.vue
@@ -0,0 +1,32 @@
+<script>
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+
+export default {
+ components: {
+ CiBadge,
+ },
+ props: {
+ schedule: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ hasPipeline() {
+ return this.schedule.lastPipeline;
+ },
+ lastPipelineStatus() {
+ return this.schedule?.lastPipeline?.detailedStatus;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <ci-badge v-if="hasPipeline" :status="lastPipelineStatus" class="gl-vertical-align-middle" />
+ <span v-else data-testid="pipeline-schedule-status-text">
+ {{ s__('PipelineSchedules|None') }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_next_run.vue b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_next_run.vue
new file mode 100644
index 00000000000..48d59bf6e7c
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_next_run.vue
@@ -0,0 +1,32 @@
+<script>
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+export default {
+ components: {
+ TimeAgoTooltip,
+ },
+ props: {
+ schedule: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ showTimeAgo() {
+ return this.schedule.active && this.schedule.nextRunAt;
+ },
+ realNextRunTime() {
+ return this.schedule.realNextRun;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <time-ago-tooltip v-if="showTimeAgo" :time="realNextRunTime" />
+ <span v-else data-testid="pipeline-schedule-inactive">
+ {{ s__('PipelineSchedules|Inactive') }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_owner.vue b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_owner.vue
new file mode 100644
index 00000000000..e7fa94eb7fc
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_owner.vue
@@ -0,0 +1,29 @@
+<script>
+import { GlAvatar, GlAvatarLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlAvatar,
+ GlAvatarLink,
+ },
+ props: {
+ schedule: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ owner() {
+ return this.schedule.owner;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-avatar-link :href="owner.webPath" :title="owner.name" class="gl-ml-3">
+ <gl-avatar :size="32" :src="owner.avatarUrl" />
+ </gl-avatar-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_target.vue b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_target.vue
new file mode 100644
index 00000000000..08efa794bcc
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/cells/pipeline_schedule_target.vue
@@ -0,0 +1,36 @@
+<script>
+import { GlIcon, GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ GlLink,
+ },
+ props: {
+ schedule: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ iconName() {
+ return this.schedule.forTag ? 'tag' : 'fork';
+ },
+ refPath() {
+ return this.schedule.refPath;
+ },
+ refDisplay() {
+ return this.schedule.refForDisplay;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-icon :name="iconName" />
+ <span v-if="refPath">
+ <gl-link :href="refPath" class="gl-text-gray-900">{{ refDisplay }}</gl-link>
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/components/table/pipeline_schedules_table.vue b/app/assets/javascripts/pipeline_schedules/components/table/pipeline_schedules_table.vue
new file mode 100644
index 00000000000..d54008b81b2
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/table/pipeline_schedules_table.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlTableLite } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import PipelineScheduleActions from './cells/pipeline_schedule_actions.vue';
+import PipelineScheduleLastPipeline from './cells/pipeline_schedule_last_pipeline.vue';
+import PipelineScheduleNextRun from './cells/pipeline_schedule_next_run.vue';
+import PipelineScheduleOwner from './cells/pipeline_schedule_owner.vue';
+import PipelineScheduleTarget from './cells/pipeline_schedule_target.vue';
+
+export default {
+ fields: [
+ {
+ key: 'description',
+ label: s__('PipelineSchedules|Description'),
+ columnClass: 'gl-w-40p',
+ },
+ {
+ key: 'target',
+ label: s__('PipelineSchedules|Target'),
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'pipeline',
+ label: s__('PipelineSchedules|Last Pipeline'),
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'next',
+ label: s__('PipelineSchedules|Next Run'),
+ columnClass: 'gl-w-15p',
+ },
+ {
+ key: 'owner',
+ label: s__('PipelineSchedules|Owner'),
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'actions',
+ label: '',
+ columnClass: 'gl-w-15p',
+ },
+ ],
+ components: {
+ GlTableLite,
+ PipelineScheduleActions,
+ PipelineScheduleLastPipeline,
+ PipelineScheduleNextRun,
+ PipelineScheduleOwner,
+ PipelineScheduleTarget,
+ },
+ props: {
+ schedules: {
+ type: Array,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-table-lite :fields="$options.fields" :items="schedules" stacked="md">
+ <template #table-colgroup="{ fields }">
+ <col v-for="field in fields" :key="field.key" :class="field.columnClass" />
+ </template>
+
+ <template #cell(description)="{ item }">
+ <span data-testid="pipeline-schedule-description">
+ {{ item.description }}
+ </span>
+ </template>
+
+ <template #cell(target)="{ item }">
+ <pipeline-schedule-target :schedule="item" />
+ </template>
+
+ <template #cell(pipeline)="{ item }">
+ <pipeline-schedule-last-pipeline :schedule="item" />
+ </template>
+
+ <template #cell(next)="{ item }">
+ <pipeline-schedule-next-run :schedule="item" />
+ </template>
+
+ <template #cell(owner)="{ item }">
+ <pipeline-schedule-owner :schedule="item" />
+ </template>
+
+ <template #cell(actions)="{ item }">
+ <pipeline-schedule-actions
+ :schedule="item"
+ @showDeleteModal="$emit('showDeleteModal', $event)"
+ />
+ </template>
+ </gl-table-lite>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql b/app/assets/javascripts/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql
new file mode 100644
index 00000000000..8aab0b3fbde
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql
@@ -0,0 +1,6 @@
+mutation deletePipelineSchedule($id: CiPipelineScheduleID!) {
+ pipelineScheduleDelete(input: { id: $id }) {
+ clientMutationId
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql b/app/assets/javascripts/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql
new file mode 100644
index 00000000000..7d9d658b1b6
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql
@@ -0,0 +1,40 @@
+query getPipelineSchedulesQuery($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ id
+ pipelineSchedules {
+ nodes {
+ id
+ description
+ forTag
+ refPath
+ refForDisplay
+ lastPipeline {
+ id
+ detailedStatus {
+ id
+ group
+ icon
+ label
+ text
+ detailsPath
+ }
+ }
+ active
+ nextRunAt
+ realNextRun
+ owner {
+ id
+ avatarUrl
+ name
+ webPath
+ }
+ userPermissions {
+ playPipelineSchedule
+ takeOwnershipPipelineSchedule
+ updatePipelineSchedule
+ adminPipelineSchedule
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_app.js b/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_app.js
new file mode 100644
index 00000000000..8f77e06c19a
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_app.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import PipelineSchedules from './components/pipeline_schedules.vue';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default () => {
+ const containerEl = document.querySelector('#pipeline-schedules-app');
+
+ if (!containerEl) {
+ return false;
+ }
+
+ const { fullPath } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ name: 'PipelineSchedulesRoot',
+ apolloProvider,
+ provide: {
+ fullPath,
+ },
+ render(createElement) {
+ return createElement(PipelineSchedules);
+ },
+ });
+};
diff --git a/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_form_app.js b/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_form_app.js
new file mode 100644
index 00000000000..d83417ab84a
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/mount_pipeline_schedules_form_app.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import PipelineSchedulesForm from './components/pipeline_schedules_form.vue';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default (selector) => {
+ const containerEl = document.querySelector(selector);
+
+ if (!containerEl) {
+ return false;
+ }
+
+ const { fullPath } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ name: 'PipelineSchedulesFormRoot',
+ apolloProvider,
+ provide: {
+ fullPath,
+ },
+ render(createElement) {
+ return createElement(PipelineSchedulesForm);
+ },
+ });
+};
diff --git a/app/assets/javascripts/pipeline_wizard/components/widgets/list.vue b/app/assets/javascripts/pipeline_wizard/components/widgets/list.vue
index a5ce56daf07..bc62d6d4465 100644
--- a/app/assets/javascripts/pipeline_wizard/components/widgets/list.vue
+++ b/app/assets/javascripts/pipeline_wizard/components/widgets/list.vue
@@ -176,7 +176,7 @@ export default {
category="secondary"
data-testid="remove-step-button"
icon="remove"
- @click="removeValue"
+ @click="() => removeValue(i)"
/>
</template>
</gl-form-input-group>
diff --git a/app/assets/javascripts/pipelines/components/jobs/failed_jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/failed_jobs_app.vue
index 9e886fd7a48..605d40eddee 100644
--- a/app/assets/javascripts/pipelines/components/jobs/failed_jobs_app.vue
+++ b/app/assets/javascripts/pipelines/components/jobs/failed_jobs_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import GetFailedJobsQuery from '../../graphql/queries/get_failed_jobs.query.graphql';
import { prepareFailedJobs } from './utils';
@@ -47,7 +47,7 @@ export default {
this.preparedFailedJobs = prepareFailedJobs(this.failedJobs, this.failedJobsSummary);
},
error() {
- createFlash({ message: s__('Jobs|There was a problem fetching the failed jobs.') });
+ createAlert({ message: s__('Jobs|There was a problem fetching the failed jobs.') });
},
},
},
diff --git a/app/assets/javascripts/pipelines/components/jobs/failed_jobs_table.vue b/app/assets/javascripts/pipelines/components/jobs/failed_jobs_table.vue
index 0c6b8b9ed2b..18607bfae1c 100644
--- a/app/assets/javascripts/pipelines/components/jobs/failed_jobs_table.vue
+++ b/app/assets/javascripts/pipelines/components/jobs/failed_jobs_table.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlLink, GlSafeHtmlDirective, GlTableLite } from '@gitlab/ui';
import { __, s__ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import RetryFailedJobMutation from '../../graphql/mutations/retry_failed_job.mutation.graphql';
@@ -49,7 +49,7 @@ export default {
return job.retryable && job.userPermissions.updateBuild;
},
showErrorMessage() {
- createFlash({ message: s__('Job|There was a problem retrying the failed job.') });
+ createAlert({ message: s__('Job|There was a problem retrying the failed job.') });
},
},
};
diff --git a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
index 18e9ffa23cf..f1ad312dcaa 100644
--- a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
+++ b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlIntersectionObserver, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import produce from 'immer';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import eventHub from '~/jobs/components/table/event_hub';
import JobsTable from '~/jobs/components/table/jobs_table.vue';
@@ -42,7 +42,7 @@ export default {
this.jobsPageInfo = data.project?.pipeline?.jobs?.pageInfo || {};
},
error() {
- createFlash({ message: __('An error occurred while fetching the pipelines jobs.') });
+ createAlert({ message: __('An error occurred while fetching the pipelines jobs.') });
},
},
},
diff --git a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
index ca2537ca4f4..7ee5ec48f44 100644
--- a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { dasherize } from '~/lib/utils/text_utility';
@@ -81,7 +81,7 @@ export default {
reportToSentry('action_component', err);
- createFlash({
+ createAlert({
message: __('An error occurred while making the request.'),
});
});
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue
index a68797a7235..f1c6c6633eb 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue
@@ -14,7 +14,7 @@
import { GlDropdown, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
import eventHub from '../../event_hub';
@@ -94,7 +94,7 @@ export default {
this.$refs.dropdown.hide();
this.isLoading = false;
- createFlash({
+ createAlert({
message: __('Something went wrong on our end.'),
});
});
diff --git a/app/assets/javascripts/pipelines/components/pipeline_tabs.vue b/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
index df59962569e..2a78636261b 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
@@ -56,7 +56,12 @@ export default {
<template>
<gl-tabs>
- <gl-tab ref="pipelineTab" :title="$options.i18n.tabs.pipelineTitle" data-testid="pipeline-tab">
+ <gl-tab
+ ref="pipelineTab"
+ :title="$options.i18n.tabs.pipelineTitle"
+ data-testid="pipeline-tab"
+ lazy
+ >
<pipeline-graph-wrapper />
</gl-tab>
<gl-tab
@@ -64,6 +69,7 @@ export default {
:title="$options.i18n.tabs.needsTitle"
:active="isActive($options.tabNames.needs)"
data-testid="dag-tab"
+ lazy
>
<dag />
</gl-tab>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
index 2d2f649f651..73a255f392b 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
@@ -55,6 +55,9 @@ export default {
};
},
computed: {
+ hasArtifacts() {
+ return this.artifacts.length > 0;
+ },
filteredArtifacts() {
return this.searchQuery.length > 0
? fuzzaldrinPlus.filter(this.artifacts, this.searchQuery, { key: 'name' })
@@ -86,7 +89,9 @@ export default {
});
},
handleDropdownShown() {
- this.$refs.searchInput.focusInput();
+ if (this.hasArtifacts) {
+ this.$refs.searchInput.focusInput();
+ }
},
},
};
@@ -112,12 +117,12 @@ export default {
<gl-loading-icon v-else-if="isLoading" size="sm" />
- <gl-dropdown-item v-else-if="!artifacts.length" data-testid="artifacts-empty-message">
+ <gl-dropdown-item v-else-if="!hasArtifacts" data-testid="artifacts-empty-message">
{{ $options.i18n.emptyArtifactsMessage }}
</gl-dropdown-item>
<template #header>
- <gl-search-box-by-type v-if="artifacts.length" ref="searchInput" v-model.trim="searchQuery" />
+ <gl-search-box-by-type v-if="hasArtifacts" ref="searchInput" v-model.trim="searchQuery" />
</template>
<gl-dropdown-item
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index f9022be888a..30528ce8d17 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlEmptyState, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { isEqual } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO, VARIANT_WARNING } from '~/flash';
import { getParameterByName } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
@@ -249,7 +249,7 @@ export default {
this.updateContent(params);
- this.track('click_filter_tabs', { label: TRACKING_CATEGORIES.tabs });
+ this.track('click_filter_tabs', { label: TRACKING_CATEGORIES.tabs, property: scope });
},
successCallback(resp) {
// Because we are polling & the user is interacting verify if the response received
@@ -267,14 +267,14 @@ export default {
.postAction(endpoint)
.then(() => {
this.isResetCacheButtonLoading = false;
- createFlash({
+ createAlert({
message: s__('Pipelines|Project cache successfully reset.'),
- type: 'notice',
+ variant: VARIANT_INFO,
});
})
.catch(() => {
this.isResetCacheButtonLoading = false;
- createFlash({
+ createAlert({
message: s__('Pipelines|Something went wrong while cleaning runners cache.'),
});
});
@@ -301,9 +301,9 @@ export default {
}
if (!filter.type) {
- createFlash({
+ createAlert({
message: RAW_TEXT_WARNING,
- type: 'warning',
+ variant: VARIANT_WARNING,
});
}
});
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
index 16a747f6165..f34b3f56c5b 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
@@ -1,6 +1,6 @@
<script>
import { GlDropdown, GlDropdownItem, GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { s__, __, sprintf } from '~/locale';
@@ -66,7 +66,7 @@ export default {
})
.catch(() => {
this.isLoading = false;
- createFlash({ message: __('An error occurred while making the request.') });
+ createAlert({ message: __('An error occurred while making the request.') });
});
},
isActionDisabled(action) {
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
index 1db2898b72a..b57d0ac1fd7 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
@@ -2,7 +2,7 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { FETCH_BRANCH_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
@@ -45,7 +45,7 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash({
+ createAlert({
message: FETCH_BRANCH_ERROR_MESSAGE,
});
this.loading = false;
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
index afcdd63b664..5846a1f6ed9 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
@@ -2,7 +2,7 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { FETCH_TAG_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
@@ -38,7 +38,7 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash({
+ createAlert({
message: FETCH_TAG_ERROR_MESSAGE,
});
this.loading = false;
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
index 746cf238646..73f7d3f52c3 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
@@ -8,7 +8,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import {
ANY_TRIGGER_AUTHOR,
FETCH_AUTHOR_ERROR_MESSAGE,
@@ -61,7 +61,7 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash({
+ createAlert({
message: FETCH_AUTHOR_ERROR_MESSAGE,
});
this.loading = false;
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index e8e49cc652e..9602ca1ba88 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import createFlash, { createAlert } from '~/flash';
+import { createAlert } from '~/flash';
import { helpPagePath } from '~/helpers/help_page_helper';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -172,7 +172,7 @@ export default {
.postAction(endpoint)
.then(() => this.updateTable())
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while making the request.'),
}),
);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 8bdf18da348..3744649e9d5 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, s__ } from '~/locale';
import createDagApp from './pipeline_details_dag';
import { createPipelinesDetailApp } from './pipeline_details_graph';
@@ -24,7 +24,7 @@ export default async function initPipelineDetailsBundle() {
try {
createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER, apolloProvider, dataset.graphqlResourceEtag);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading a section of this page.'),
});
}
@@ -37,7 +37,7 @@ export default async function initPipelineDetailsBundle() {
const appOptions = createAppOptions(SELECTORS.PIPELINE_TABS, apolloProvider);
createPipelineTabs(appOptions);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading a section of this page.'),
});
}
@@ -45,7 +45,7 @@ export default async function initPipelineDetailsBundle() {
try {
createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, apolloProvider, dataset);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading the pipeline.'),
});
}
@@ -53,7 +53,7 @@ export default async function initPipelineDetailsBundle() {
try {
createDagApp(apolloProvider);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading the Needs tab.'),
});
}
@@ -61,7 +61,7 @@ export default async function initPipelineDetailsBundle() {
try {
createTestDetails(SELECTORS.PIPELINE_TESTS);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading the Test Reports tab.'),
});
}
@@ -69,7 +69,7 @@ export default async function initPipelineDetailsBundle() {
try {
createPipelineJobsApp(SELECTORS.PIPELINE_JOBS);
} catch {
- createFlash({
+ createAlert({
message: __('An error occurred while loading the Jobs tab.'),
});
}
@@ -77,7 +77,7 @@ export default async function initPipelineDetailsBundle() {
try {
createPipelineFailedJobsApp(SELECTORS.PIPELINE_FAILED_JOBS);
} catch {
- createFlash({
+ createAlert({
message: s__('Jobs|An error occurred while loading the Failed Jobs tab.'),
});
}
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/actions.js b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
index b785fd1753c..c77b4813e33 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/actions.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -12,7 +12,7 @@ export const fetchSummary = ({ state, commit, dispatch }) => {
commit(types.SET_SUMMARY, data);
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__('TestReports|There was an error fetching the summary.'),
});
})
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/mutations.js b/app/assets/javascripts/pipelines/stores/test_reports/mutations.js
index 68ee063dda7..bff30acfe36 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/mutations.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/mutations.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -21,7 +21,7 @@ export default {
if (errorMessage) {
state.errorMessage = errorMessage;
} else {
- createFlash({
+ createAlert({
message: s__('TestReports|There was an error fetching the test suite.'),
});
}
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index c99133fd251..b038b78088f 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,7 +1,7 @@
<script>
import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { escape } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, s__, sprintf } from '~/locale';
@@ -85,12 +85,12 @@ Please update your Git repository remotes as soon as possible.`),
return axios
.put(this.actionUrl, putData)
.then((result) => {
- createFlash({ message: result.data.message, type: 'notice' });
+ createAlert({ message: result.data.message, variant: VARIANT_INFO });
this.username = username;
this.isRequestPending = false;
})
.catch((error) => {
- createFlash({
+ createAlert({
message:
error?.response?.data?.message ||
s__('Profiles|An error occurred while updating your username, please try again.'),
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index 722f7d467a2..050b004f657 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -165,6 +165,7 @@ import { loadCSSFile } from '../lib/utils/css_utils';
setPreview() {
const filename = this.fileInput.val().replace(FILENAMEREGEX, '');
this.previewImage.attr('src', this.dataURL);
+ this.previewImage.attr('srcset', this.dataURL);
return this.filename.text(filename);
}
diff --git a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
index 7542f81a361..a33a20b49f6 100644
--- a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
+++ b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
@@ -1,6 +1,6 @@
<script>
import { GlButton } from '@gitlab/ui';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_DANGER, VARIANT_INFO } from '~/flash';
import { INTEGRATION_VIEW_CONFIGS, i18n } from '../constants';
import IntegrationView from './integration_view.vue';
@@ -94,15 +94,15 @@ export default {
return;
}
updateClasses(this.bodyClasses, this.getSelectedTheme().css_class, this.selectedLayout);
- const { message = this.$options.i18n.defaultSuccess, type = FLASH_TYPES.NOTICE } =
+ const { message = this.$options.i18n.defaultSuccess, variant = VARIANT_INFO } =
customEvent?.detail?.[0] || {};
- createFlash({ message, type });
+ createAlert({ message, variant });
this.isSubmitEnabled = true;
},
handleError(customEvent) {
- const { message = this.$options.i18n.defaultError, type = FLASH_TYPES.ALERT } =
+ const { message = this.$options.i18n.defaultError, variant = VARIANT_DANGER } =
customEvent?.detail?.[0] || {};
- createFlash({ message, type });
+ createAlert({ message, variant });
this.isSubmitEnabled = true;
},
},
@@ -110,7 +110,7 @@ export default {
</script>
<template>
- <div class="row gl-mt-3 js-preferences-form">
+ <div class="row gl-mt-3 js-preferences-form js-search-settings-section">
<div v-if="integrationViews.length" class="col-sm-12">
<hr data-testid="profile-preferences-integrations-rule" />
</div>
@@ -131,9 +131,9 @@ export default {
:message-url="view.message_url"
:config="$options.integrationViewConfigs[view.name]"
/>
- </div>
- <div class="col-sm-12">
<hr />
+ </div>
+ <div class="col-sm-12 js-hide-when-nothing-matches-search">
<gl-button
category="primary"
variant="confirm"
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index af5beeb686c..93bc203d391 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -5,9 +5,6 @@ import axios from '~/lib/utils/axios_utils';
import { parseBoolean } from '~/lib/utils/common_utils';
import { parseRailsFormFields } from '~/lib/utils/forms';
import { Rails } from '~/lib/utils/rails_ujs';
-import TimezoneDropdown, {
- formatTimezone,
-} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
import UserProfileSetStatusWrapper from '~/set_status_modal/user_profile_set_status_wrapper.vue';
export default class Profile {
@@ -17,21 +14,12 @@ export default class Profile {
this.setRepoRadio();
this.bindEvents();
this.initAvatarGlCrop();
-
- this.$inputEl = $('#user_timezone');
-
- this.timezoneDropdown = new TimezoneDropdown({
- $inputEl: this.$inputEl,
- $dropdownEl: $('.js-timezone-dropdown'),
- displayFormat: (selectedItem) => formatTimezone(selectedItem),
- allowEmpty: true,
- });
}
initAvatarGlCrop() {
const cropOpts = {
filename: '.js-avatar-filename',
- previewImage: '.avatar-image .avatar',
+ previewImage: '.avatar-image .gl-avatar',
modalCrop: '.modal-profile-crop',
pickImageEl: '.js-choose-user-avatar-button',
uploadImageBtn: '.js-upload-user-avatar',
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 09acf98001c..705234537a8 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names */
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Api from './api';
import { loadCSSFile } from './lib/utils/css_utils';
import { s__ } from './locale';
@@ -67,7 +67,7 @@ const projectSelect = async () => {
},
projectsCallback,
).catch(() => {
- createFlash({
+ createAlert({
message: s__('ProjectSelect|Something went wrong while fetching projects'),
});
});
diff --git a/app/assets/javascripts/projects/commit/store/actions.js b/app/assets/javascripts/projects/commit/store/actions.js
index 2b25082eced..cfff93eac5a 100644
--- a/app/assets/javascripts/projects/commit/store/actions.js
+++ b/app/assets/javascripts/projects/commit/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { PROJECT_BRANCHES_ERROR } from '../constants';
import * as types from './mutation_types';
@@ -26,7 +26,7 @@ export const fetchBranches = ({ commit, dispatch, state }, query) => {
commit(types.RECEIVE_BRANCHES_SUCCESS, data.Branches?.length ? data.Branches : data);
})
.catch(() => {
- createFlash({ message: PROJECT_BRANCHES_ERROR });
+ createAlert({ message: PROJECT_BRANCHES_ERROR });
});
};
diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
index 4505dd1f85c..2802e4a90b9 100644
--- a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
+++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import {
getQueryHeaders,
@@ -59,7 +59,7 @@ export default {
return project?.pipeline;
},
error() {
- createFlash({ message: this.$options.i18n.linkedPipelinesFetchError });
+ createAlert({ message: this.$options.i18n.linkedPipelinesFetchError });
},
},
pipelineStages: {
@@ -78,7 +78,7 @@ export default {
return project?.pipeline?.stages?.nodes || [];
},
error() {
- createFlash({ message: this.$options.i18n.stagesFetchError });
+ createAlert({ message: this.$options.i18n.stagesFetchError });
},
},
},
@@ -108,7 +108,7 @@ export default {
try {
this.formattedStages = formatStages(this.pipelineStages, this.stages);
} catch (error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.stageConversionError,
captureError: true,
error,
diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue
index 5a9d3129809..62b1209131c 100644
--- a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue
+++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon, GlLink } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import {
getQueryHeaders,
toggleQueryPollingByVisibility,
@@ -44,7 +44,7 @@ export default {
return project?.pipeline?.detailedStatus || {};
},
error() {
- createFlash({ message: this.$options.PIPELINE_STATUS_FETCH_ERROR });
+ createAlert({ message: this.$options.PIPELINE_STATUS_FETCH_ERROR });
},
},
},
diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js
index 795c293d14b..603fdfdf80a 100644
--- a/app/assets/javascripts/projects/commits/store/actions.js
+++ b/app/assets/javascripts/projects/commits/store/actions.js
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/browser';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -13,7 +13,7 @@ export default {
commit(types.COMMITS_AUTHORS, authors);
},
receiveAuthorsError() {
- createFlash({
+ createAlert({
message: __('An error occurred fetching the project authors.'),
});
},
diff --git a/app/assets/javascripts/projects/compare/components/app.vue b/app/assets/javascripts/projects/compare/components/app.vue
index 4ba7156b026..271694863e8 100644
--- a/app/assets/javascripts/projects/compare/components/app.vue
+++ b/app/assets/javascripts/projects/compare/components/app.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
import { joinPaths } from '~/lib/utils/url_utility';
import RevisionCard from './revision_card.vue';
@@ -9,6 +9,8 @@ export default {
components: {
RevisionCard,
GlButton,
+ GlDropdown,
+ GlDropdownItem,
},
props: {
projectCompareIndexPath: {
@@ -53,6 +55,10 @@ export default {
type: Array,
required: true,
},
+ straight: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
@@ -67,8 +73,27 @@ export default {
revision: this.paramsTo,
refsProjectPath: this.sourceProjectRefsPath,
},
+ isStraight: this.straight,
};
},
+ computed: {
+ straightModeDropdownItems() {
+ return [
+ {
+ modeType: 'off',
+ isEnabled: false,
+ content: '..',
+ testId: 'disableStraightModeButton',
+ },
+ {
+ modeType: 'on',
+ isEnabled: true,
+ content: '...',
+ testId: 'enableStraightModeButton',
+ },
+ ];
+ },
+ },
methods: {
onSubmit() {
this.$refs.form.submit();
@@ -85,6 +110,9 @@ export default {
onSwapRevision() {
[this.from, this.to] = [this.to, this.from]; // swaps 'from' and 'to'
},
+ setStraightMode(isStraight) {
+ this.isStraight = isStraight;
+ },
},
};
</script>
@@ -112,10 +140,22 @@ export default {
@selectRevision="onSelectRevision"
/>
<div
- class="compare-ellipsis gl-display-flex gl-justify-content-center gl-align-items-center gl-align-self-end gl-my-4 gl-md-my-0"
+ class="gl-display-flex gl-justify-content-center gl-align-items-center gl-align-self-end gl-my-3 gl-md-my-0 gl-pl-3 gl-pr-3"
data-testid="ellipsis"
>
- ...
+ <input :value="isStraight ? 'true' : 'false'" type="hidden" name="straight" />
+ <gl-dropdown data-testid="modeDropdown" :text="isStraight ? '...' : '..'" size="small">
+ <gl-dropdown-item
+ v-for="mode in straightModeDropdownItems"
+ :key="mode.modeType"
+ :is-check-item="true"
+ :is-checked="isStraight == mode.isEnabled"
+ :data-testid="mode.testId"
+ @click="setStraightMode(mode.isEnabled)"
+ >
+ <span class="dropdown-menu-inner-content"> {{ mode.content }} </span>
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
<revision-card
data-testid="targetRevisionCard"
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
index f0b8e73e528..10531e950f9 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
import { debounce } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
@@ -76,7 +76,7 @@ export default {
this.tags = data.Tags || [];
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__(
'CompareRevisions|There was an error while searching the branch/tag list. Please try again.',
),
@@ -97,7 +97,7 @@ export default {
this.tags = data.Tags || [];
})
.catch(() => {
- createFlash({
+ createAlert({
message: s__(
'CompareRevisions|There was an error while loading the branch/tag list. Please try again.',
),
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
index 19cf4cda2be..1e1677e947c 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
@@ -1,6 +1,6 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
@@ -74,7 +74,7 @@ export default {
this.tags = data.Tags || [];
})
.catch(() => {
- createFlash({
+ createAlert({
message: `${s__(
'CompareRevisions|There was an error while updating the branch/tag list. Please try again.',
)}`,
diff --git a/app/assets/javascripts/projects/compare/index.js b/app/assets/javascripts/projects/compare/index.js
index 074b8565c3c..284cee6d7f1 100644
--- a/app/assets/javascripts/projects/compare/index.js
+++ b/app/assets/javascripts/projects/compare/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import CompareApp from './components/app.vue';
export default function init() {
@@ -9,6 +10,7 @@ export default function init() {
targetProjectRefsPath,
paramsFrom,
paramsTo,
+ straight,
projectCompareIndexPath,
projectMergeRequestPath,
createMrPath,
@@ -29,6 +31,7 @@ export default function init() {
targetProjectRefsPath,
paramsFrom,
paramsTo,
+ straight: parseBoolean(straight),
projectCompareIndexPath,
projectMergeRequestPath,
createMrPath,
diff --git a/app/assets/javascripts/projects/project_find_file.js b/app/assets/javascripts/projects/project_find_file.js
index d295c06928f..71329c4f461 100644
--- a/app/assets/javascripts/projects/project_find_file.js
+++ b/app/assets/javascripts/projects/project_find_file.js
@@ -2,7 +2,7 @@
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from '~/lib/utils/common_utils';
@@ -89,7 +89,7 @@ export default class ProjectFindFile {
this.element.find('.files-slider tr.tree-item').eq(0).addClass('selected').focus();
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while loading filenames'),
}),
);
diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js
index 060178a3cfb..335545c802a 100644
--- a/app/assets/javascripts/projects/settings/access_dropdown.js
+++ b/app/assets/javascripts/projects/settings/access_dropdown.js
@@ -1,7 +1,7 @@
/* eslint-disable no-underscore-dangle, class-methods-use-this */
import { escape, find, countBy } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { n__, s__, __, sprintf } from '~/locale';
import { getUsers, getGroups, getDeployKeys } from './api/access_dropdown_api';
import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVELS, ACCESS_LEVEL_NONE } from './constants';
@@ -326,12 +326,12 @@ export default class AccessDropdown {
);
})
.catch(() => {
- createFlash({ message: __('Failed to load groups, users and deploy keys.') });
+ createAlert({ message: __('Failed to load groups, users and deploy keys.') });
});
} else {
getDeployKeys(query)
.then((deployKeysResponse) => callback(this.consolidateData(deployKeysResponse.data)))
- .catch(() => createFlash({ message: __('Failed to load deploy keys.') }));
+ .catch(() => createAlert({ message: __('Failed to load deploy keys.') }));
}
}
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue b/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue
deleted file mode 100644
index 6ba2ef7da99..00000000000
--- a/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue
+++ /dev/null
@@ -1,137 +0,0 @@
-<script>
-import {
- GlDropdown,
- GlDropdownItem,
- GlDropdownDivider,
- GlSearchBoxByType,
- GlSprintf,
- GlLink,
-} from '@gitlab/ui';
-import { createAlert } from '~/flash';
-import { s__, sprintf } from '~/locale';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import branchesQuery from '../queries/branches.query.graphql';
-
-export const i18n = {
- fetchBranchesError: s__('BranchRules|An error occurred while fetching branches.'),
- noMatch: s__('BranchRules|No matching results'),
- branchHelpText: s__(
- 'BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported.',
- ),
- wildCardSearchHelp: s__('BranchRules|Create wildcard: %{searchTerm}'),
-};
-
-export default {
- i18n,
- name: 'BranchDropdown',
- components: {
- GlDropdown,
- GlDropdownItem,
- GlDropdownDivider,
- GlSearchBoxByType,
- GlSprintf,
- GlLink,
- },
- apollo: {
- branchNames: {
- query: branchesQuery,
- variables() {
- return {
- projectPath: this.projectPath,
- searchPattern: `*${this.searchTerm}*`,
- };
- },
- update({ project: { repository = {} } } = {}) {
- return repository.branchNames || [];
- },
- error(e) {
- createAlert({
- message: this.$options.i18n.fetchBranchesError,
- captureError: true,
- error: e,
- });
- },
- },
- },
- searchInputDelay: 250,
- wildcardsHelpPath: helpPagePath('user/project/protected_branches', {
- anchor: 'configure-multiple-protected-branches-by-using-a-wildcard',
- }),
- props: {
- projectPath: {
- type: String,
- required: true,
- },
- value: {
- type: String,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- searchTerm: '',
- branchNames: [],
- };
- },
- computed: {
- createButtonLabel() {
- return sprintf(this.$options.i18n.wildCardSearchHelp, {
- searchTerm: this.searchTerm,
- });
- },
- shouldRenderCreateButton() {
- return this.searchTerm && !this.branchNames.includes(this.searchTerm);
- },
- isLoading() {
- return this.$apollo.queries.branchNames.loading;
- },
- },
- methods: {
- selectBranch(selected) {
- this.$emit('input', selected);
- },
- createWildcard() {
- this.$emit('createWildcard', this.searchTerm);
- },
- isSelected(branch) {
- return this.value === branch;
- },
- },
-};
-</script>
-<template>
- <div>
- <gl-dropdown :text="value || branchNames[0]" class="gl-w-full">
- <gl-search-box-by-type
- v-model.trim="searchTerm"
- data-testid="branch-search"
- :debounce="$options.searchInputDelay"
- :is-loading="isLoading"
- />
- <gl-dropdown-item
- v-for="branch in branchNames"
- :key="branch"
- :is-checked="isSelected(branch)"
- is-check-item
- @click="selectBranch(branch)"
- >
- {{ branch }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="!branchNames.length && !isLoading" data-testid="no-data">{{
- $options.i18n.noMatch
- }}</gl-dropdown-item>
- <template v-if="shouldRenderCreateButton">
- <gl-dropdown-divider />
- <gl-dropdown-item data-testid="create-wildcard-button" @click="createWildcard">
- {{ createButtonLabel }}
- </gl-dropdown-item>
- </template>
- </gl-dropdown>
- <gl-sprintf :message="$options.i18n.branchHelpText">
- <template #link="{ content }">
- <gl-link :href="$options.wildcardsHelpPath">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
-</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue
new file mode 100644
index 00000000000..f2b1c749abc
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue
@@ -0,0 +1,137 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlSearchBoxByType,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
+import { createAlert } from '~/flash';
+import { s__, sprintf } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import branchesQuery from '../../queries/branches.query.graphql';
+
+export const i18n = {
+ fetchBranchesError: s__('BranchRules|An error occurred while fetching branches.'),
+ noMatch: s__('BranchRules|No matching results'),
+ branchHelpText: s__(
+ 'BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported.',
+ ),
+ wildCardSearchHelp: s__('BranchRules|Create wildcard: %{searchTerm}'),
+};
+
+export default {
+ i18n,
+ name: 'BranchDropdown',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlSearchBoxByType,
+ GlSprintf,
+ GlLink,
+ },
+ apollo: {
+ branchNames: {
+ query: branchesQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ searchPattern: `*${this.searchTerm}*`,
+ };
+ },
+ update({ project: { repository = {} } } = {}) {
+ return repository.branchNames || [];
+ },
+ error(e) {
+ createAlert({
+ message: this.$options.i18n.fetchBranchesError,
+ captureError: true,
+ error: e,
+ });
+ },
+ },
+ },
+ searchInputDelay: 250,
+ wildcardsHelpPath: helpPagePath('user/project/protected_branches', {
+ anchor: 'configure-multiple-protected-branches-by-using-a-wildcard',
+ }),
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ branchNames: [],
+ };
+ },
+ computed: {
+ createButtonLabel() {
+ return sprintf(this.$options.i18n.wildCardSearchHelp, {
+ searchTerm: this.searchTerm,
+ });
+ },
+ shouldRenderCreateButton() {
+ return this.searchTerm && !this.branchNames.includes(this.searchTerm);
+ },
+ isLoading() {
+ return this.$apollo.queries.branchNames.loading;
+ },
+ },
+ methods: {
+ selectBranch(selected) {
+ this.$emit('input', selected);
+ },
+ createWildcard() {
+ this.$emit('createWildcard', this.searchTerm);
+ },
+ isSelected(branch) {
+ return this.value === branch;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-dropdown :text="value || branchNames[0]" class="gl-w-full">
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ data-testid="branch-search"
+ :debounce="$options.searchInputDelay"
+ :is-loading="isLoading"
+ />
+ <gl-dropdown-item
+ v-for="branch in branchNames"
+ :key="branch"
+ :is-checked="isSelected(branch)"
+ is-check-item
+ @click="selectBranch(branch)"
+ >
+ {{ branch }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="!branchNames.length && !isLoading" data-testid="no-data">{{
+ $options.i18n.noMatch
+ }}</gl-dropdown-item>
+ <template v-if="shouldRenderCreateButton">
+ <gl-dropdown-divider />
+ <gl-dropdown-item data-testid="create-wildcard-button" @click="createWildcard">
+ {{ createButtonLabel }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+ <gl-sprintf :message="$options.i18n.branchHelpText">
+ <template #link="{ content }">
+ <gl-link :href="$options.wildcardsHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/index.vue
index ad3eb7d2899..ad3eb7d2899 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/index.vue
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/index.vue
index bcc0f64d667..bcc0f64d667 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/index.vue
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/merge_protections.vue
index 85f168af4a8..85f168af4a8 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/merge_protections.vue
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue
index 541923bb735..541923bb735 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
new file mode 100644
index 00000000000..264c2629433
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
@@ -0,0 +1,42 @@
+import { s__ } from '~/locale';
+
+export const I18N = {
+ manageProtectionsLinkTitle: s__('BranchRules|Manage in Protected Branches'),
+ targetBranch: s__('BranchRules|Target Branch'),
+ branchNameOrPattern: s__('BranchRules|Branch name or pattern'),
+ branch: s__('BranchRules|Target Branch'),
+ allBranches: s__('BranchRules|All branches'),
+ protectBranchTitle: s__('BranchRules|Protect branch'),
+ protectBranchDescription: s__(
+ 'BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}',
+ ),
+ wildcardsHelpText: s__(
+ 'BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported',
+ ),
+ forcePushTitle: s__('BranchRules|Force push'),
+ allowForcePushDescription: s__(
+ 'BranchRules|All users with push access are allowed to force push.',
+ ),
+ disallowForcePushDescription: s__('BranchRules|Force push is not allowed.'),
+ approvalsTitle: s__('BranchRules|Approvals'),
+ manageApprovalsLinkTitle: s__('BranchRules|Manage in Merge Request Approvals'),
+ approvalsDescription: s__(
+ 'BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}',
+ ),
+ statusChecksTitle: s__('BranchRules|Status checks'),
+ allowedToPushHeader: s__('BranchRules|Allowed to push (%{total})'),
+ allowedToMergeHeader: s__('BranchRules|Allowed to merge (%{total})'),
+ approvalsHeader: s__('BranchRules|Required approvals (%{total})'),
+ noData: s__('BranchRules|No data to display'),
+};
+
+export const BRANCH_PARAM_NAME = 'branch';
+
+export const ALL_BRANCHES_WILDCARD = '*';
+
+export const WILDCARDS_HELP_PATH =
+ 'user/project/protected_branches#configure-multiple-protected-branches-by-using-a-wildcard';
+
+export const PROTECTED_BRANCHES_HELP_PATH = 'user/project/protected_branches';
+
+export const APPROVALS_HELP_PATH = 'user/project/merge_requests/approvals/index.md';
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue b/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue
new file mode 100644
index 00000000000..318940478a8
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue
@@ -0,0 +1,207 @@
+<script>
+import { GlSprintf, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { sprintf } from '~/locale';
+import { getParameterByName } from '~/lib/utils/url_utility';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import branchRulesQuery from '../../queries/branch_rules_details.query.graphql';
+import Protection from './protection.vue';
+import {
+ I18N,
+ ALL_BRANCHES_WILDCARD,
+ BRANCH_PARAM_NAME,
+ WILDCARDS_HELP_PATH,
+ PROTECTED_BRANCHES_HELP_PATH,
+ APPROVALS_HELP_PATH,
+} from './constants';
+
+const wildcardsHelpDocLink = helpPagePath(WILDCARDS_HELP_PATH);
+const protectedBranchesHelpDocLink = helpPagePath(PROTECTED_BRANCHES_HELP_PATH);
+const approvalsHelpDocLink = helpPagePath(APPROVALS_HELP_PATH);
+
+export default {
+ name: 'RuleView',
+ i18n: I18N,
+ wildcardsHelpDocLink,
+ protectedBranchesHelpDocLink,
+ approvalsHelpDocLink,
+ components: { Protection, GlSprintf, GlLink, GlLoadingIcon },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ protectedBranchesPath: {
+ default: '',
+ },
+ approvalRulesPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ project: {
+ query: branchRulesQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update({ project: { branchRules } }) {
+ this.branchProtection = branchRules.nodes.find(
+ (rule) => rule.name === this.branch,
+ )?.branchProtection;
+ },
+ },
+ },
+ data() {
+ return {
+ branch: getParameterByName(BRANCH_PARAM_NAME),
+ branchProtection: {
+ approvalRules: {},
+ },
+ };
+ },
+ computed: {
+ forcePushDescription() {
+ return this.branchProtection?.allowForcePush
+ ? this.$options.i18n.allowForcePushDescription
+ : this.$options.i18n.disallowForcePushDescription;
+ },
+ mergeAccessLevels() {
+ const { mergeAccessLevels } = this.branchProtection || {};
+ return this.getAccessLevels(mergeAccessLevels);
+ },
+ pushAccessLevels() {
+ const { pushAccessLevels } = this.branchProtection || {};
+ return this.getAccessLevels(pushAccessLevels);
+ },
+ allowedToMergeHeader() {
+ return sprintf(this.$options.i18n.allowedToMergeHeader, {
+ total: this.mergeAccessLevels.total,
+ });
+ },
+ allowedToPushHeader() {
+ return sprintf(this.$options.i18n.allowedToPushHeader, {
+ total: this.pushAccessLevels.total,
+ });
+ },
+ approvalsHeader() {
+ const total = this.approvals.reduce(
+ (sum, { approvalsRequired }) => sum + approvalsRequired,
+ 0,
+ );
+ return sprintf(this.$options.i18n.approvalsHeader, {
+ total,
+ });
+ },
+ allBranches() {
+ return this.branch === ALL_BRANCHES_WILDCARD;
+ },
+ allBranchesLabel() {
+ return this.$options.i18n.allBranches;
+ },
+ branchTitle() {
+ return this.allBranches
+ ? this.$options.i18n.targetBranch
+ : this.$options.i18n.branchNameOrPattern;
+ },
+ approvals() {
+ return this.branchProtection?.approvalRules?.nodes || [];
+ },
+ },
+ methods: {
+ getAccessLevels(accessLevels = {}) {
+ const total = accessLevels.edges?.length;
+ const accessLevelTypes = { total, users: [], groups: [], roles: [] };
+
+ accessLevels.edges?.forEach(({ node }) => {
+ if (node.user) {
+ const src = node.user.avatarUrl;
+ accessLevelTypes.users.push({ src, ...node.user });
+ } else if (node.group) {
+ accessLevelTypes.groups.push(node);
+ } else {
+ accessLevelTypes.roles.push(node);
+ }
+ });
+
+ return accessLevelTypes;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-loading-icon v-if="$apollo.loading" />
+ <div v-else-if="!branchProtection">{{ $options.i18n.noData }}</div>
+ <div v-else>
+ <strong data-testid="branch-title">{{ branchTitle }}</strong>
+ <p v-if="!allBranches" class="gl-mb-3 gl-text-gray-400">
+ <gl-sprintf :message="$options.i18n.wildcardsHelpText">
+ <template #link="{ content }">
+ <gl-link :href="$options.wildcardsHelpDocLink">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <div v-if="allBranches" class="gl-mt-2" data-testid="branch">
+ {{ allBranchesLabel }}
+ </div>
+ <code v-else class="gl-mt-2" data-testid="branch">{{ branch }}</code>
+
+ <h4 class="gl-mb-1 gl-mt-5">{{ $options.i18n.protectBranchTitle }}</h4>
+ <gl-sprintf :message="$options.i18n.protectBranchDescription">
+ <template #link="{ content }">
+ <gl-link :href="$options.protectedBranchesHelpDocLink">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+
+ <!-- Allowed to push -->
+ <protection
+ class="gl-mt-3"
+ :header="allowedToPushHeader"
+ :header-link-title="$options.i18n.manageProtectionsLinkTitle"
+ :header-link-href="protectedBranchesPath"
+ :roles="pushAccessLevels.roles"
+ :users="pushAccessLevels.users"
+ :groups="pushAccessLevels.groups"
+ />
+
+ <!-- Force push -->
+ <strong>{{ $options.i18n.forcePushTitle }}</strong>
+ <p>{{ forcePushDescription }}</p>
+
+ <!-- Allowed to merge -->
+ <protection
+ :header="allowedToMergeHeader"
+ :header-link-title="$options.i18n.manageProtectionsLinkTitle"
+ :header-link-href="protectedBranchesPath"
+ :roles="mergeAccessLevels.roles"
+ :users="mergeAccessLevels.users"
+ :groups="mergeAccessLevels.groups"
+ />
+
+ <!-- Approvals -->
+ <h4 class="gl-mb-1 gl-mt-5">{{ $options.i18n.approvalsTitle }}</h4>
+ <gl-sprintf :message="$options.i18n.approvalsDescription">
+ <template #link="{ content }">
+ <gl-link :href="$options.approvalsHelpDocLink">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+
+ <protection
+ class="gl-mt-3"
+ :header="approvalsHeader"
+ :header-link-title="$options.i18n.manageApprovalsLinkTitle"
+ :header-link-href="approvalRulesPath"
+ :approvals="approvals"
+ />
+
+ <!-- Status checks -->
+ <!-- Follow-up: add status checks section (https://gitlab.com/gitlab-org/gitlab/-/issues/372362) -->
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/protection.vue b/app/assets/javascripts/projects/settings/branch_rules/components/view/protection.vue
new file mode 100644
index 00000000000..cfe2df0dbda
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/protection.vue
@@ -0,0 +1,99 @@
+<script>
+import { GlCard, GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import ProtectionRow from './protection_row.vue';
+
+export const i18n = {
+ rolesTitle: s__('BranchRules|Roles'),
+ usersTitle: s__('BranchRules|Users'),
+ groupsTitle: s__('BranchRules|Groups'),
+};
+
+export default {
+ name: 'ProtectionDetail',
+ i18n,
+ components: { GlCard, GlLink, ProtectionRow },
+ props: {
+ header: {
+ type: String,
+ required: true,
+ },
+ headerLinkTitle: {
+ type: String,
+ required: true,
+ },
+ headerLinkHref: {
+ type: String,
+ required: true,
+ },
+ roles: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ users: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ groups: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ approvals: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ computed: {
+ showUsersDivider() {
+ return Boolean(this.roles.length);
+ },
+ showGroupsDivider() {
+ return Boolean(this.roles.length || this.users.length);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-card class="gl-mb-5" body-class="gl-py-0">
+ <template #header>
+ <div class="gl-display-flex gl-justify-content-space-between">
+ <strong>{{ header }}</strong>
+ <gl-link :href="headerLinkHref">{{ headerLinkTitle }}</gl-link>
+ </div>
+ </template>
+
+ <!-- Roles -->
+ <protection-row v-if="roles.length" :title="$options.i18n.rolesTitle" :access-levels="roles" />
+
+ <!-- Users -->
+ <protection-row
+ v-if="users.length"
+ :show-divider="showUsersDivider"
+ :users="users"
+ :title="$options.i18n.usersTitle"
+ />
+
+ <!-- Groups -->
+ <protection-row
+ v-if="groups.length"
+ :show-divider="showGroupsDivider"
+ :title="$options.i18n.groupsTitle"
+ :access-levels="groups"
+ />
+
+ <!-- Approvals -->
+ <protection-row
+ v-for="(approval, index) in approvals"
+ :key="approval.name"
+ :show-divider="index !== 0"
+ :title="approval.name"
+ :users="approval.eligibleApprovers.nodes"
+ :approvals-required="approval.approvalsRequired"
+ />
+ </gl-card>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue b/app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue
new file mode 100644
index 00000000000..28a1c09fa82
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue
@@ -0,0 +1,110 @@
+<script>
+import { GlAvatarsInline, GlAvatar, GlAvatarLink, GlTooltipDirective } from '@gitlab/ui';
+import { n__ } from '~/locale';
+
+const AVATAR_TOOLTIP_MAX_CHARS = 100;
+export const MAX_VISIBLE_AVATARS = 4;
+export const AVATAR_SIZE = 32;
+
+export default {
+ name: 'ProtectionRow',
+ AVATAR_TOOLTIP_MAX_CHARS,
+ MAX_VISIBLE_AVATARS,
+ AVATAR_SIZE,
+ components: { GlAvatarsInline, GlAvatar, GlAvatarLink },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ accessLevels: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ showDivider: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ users: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ approvalsRequired: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ },
+ computed: {
+ avatarBadgeSrOnlyText() {
+ return n__(
+ '%d additional user',
+ '%d additional users',
+ this.users.length - this.$options.MAX_VISIBLE_AVATARS,
+ );
+ },
+ commaSeparateList() {
+ return this.accessLevels.length > 1;
+ },
+ approvalsRequiredTitle() {
+ return this.approvalsRequired
+ ? n__('%d approval required', '%d approvals required', this.approvalsRequired)
+ : null;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-align-items-center gl-border-gray-100 gl-mb-4 gl-pt-4"
+ :class="{ 'gl-border-t-solid': showDivider }"
+ >
+ <div class="gl-display-flex gl-w-half gl-justify-content-space-between">
+ <div class="gl-mr-7 gl-w-quarter">{{ title }}</div>
+
+ <gl-avatars-inline
+ v-if="users.length"
+ class="gl-w-quarter!"
+ :avatars="users"
+ :collapsed="true"
+ :max-visible="$options.MAX_VISIBLE_AVATARS"
+ :avatar-size="$options.AVATAR_SIZE"
+ badge-tooltip-prop="name"
+ :badge-tooltip-max-chars="$options.AVATAR_TOOLTIP_MAX_CHARS"
+ :badge-sr-only-text="avatarBadgeSrOnlyText"
+ >
+ <template #avatar="{ avatar }">
+ <gl-avatar-link
+ :key="avatar.username"
+ v-gl-tooltip
+ target="_blank"
+ :href="avatar.webUrl"
+ :title="avatar.name"
+ >
+ <gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="$options.AVATAR_SIZE" />
+ </gl-avatar-link>
+ </template>
+ </gl-avatars-inline>
+
+ <div
+ v-for="(item, index) in accessLevels"
+ :key="index"
+ data-testid="access-level"
+ class="gl-w-quarter"
+ >
+ <span v-if="commaSeparateList && index > 0" data-testid="comma-separator">,</span>
+ {{ item.accessLevelDescription }}
+ </div>
+
+ <div class="gl-ml-7 gl-w-quarter">{{ approvalsRequiredTitle }}</div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
index 8452542540e..07fd0a7080f 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
+++ b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import RuleEdit from './components/rule_edit.vue';
+import View from './components/view/index.vue';
export default function mountBranchRules(el) {
if (!el) {
@@ -14,13 +14,18 @@ export default function mountBranchRules(el) {
defaultClient: createDefaultClient(),
});
- const { projectPath } = el.dataset;
+ const { projectPath, protectedBranchesPath, approvalRulesPath } = el.dataset;
return new Vue({
el,
apolloProvider,
+ provide: {
+ projectPath,
+ protectedBranchesPath,
+ approvalRulesPath,
+ },
render(h) {
- return h(RuleEdit, { props: { projectPath } });
+ return h(View);
},
});
}
diff --git a/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql b/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql
new file mode 100644
index 00000000000..3ac165498a1
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql
@@ -0,0 +1,50 @@
+query getBranchRulesDetails($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ id
+ branchRules {
+ nodes {
+ name
+ branchProtection {
+ allowForcePush
+ codeOwnerApprovalRequired
+ mergeAccessLevels {
+ edges {
+ node {
+ accessLevel
+ accessLevelDescription
+ group {
+ id
+ avatarUrl
+ }
+ user {
+ id
+ name
+ avatarUrl
+ webUrl
+ }
+ }
+ }
+ }
+ pushAccessLevels {
+ edges {
+ node {
+ accessLevel
+ accessLevelDescription
+ group {
+ id
+ avatarUrl
+ }
+ user {
+ id
+ name
+ avatarUrl
+ webUrl
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/projects/settings/components/access_dropdown.vue b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
index 2209172c06d..cc47496971d 100644
--- a/app/assets/javascripts/projects/settings/components/access_dropdown.vue
+++ b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
@@ -9,7 +9,7 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { debounce, intersectionWith, groupBy, differenceBy, intersectionBy } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, s__, n__ } from '~/locale';
import { getUsers, getGroups, getDeployKeys } from '../api/access_dropdown_api';
import { LEVEL_TYPES, ACCESS_LEVELS } from '../constants';
@@ -163,7 +163,7 @@ export default {
this.setSelected({ initial });
})
.catch(() =>
- createFlash({ message: __('Failed to load groups, users and deploy keys.') }),
+ createAlert({ message: __('Failed to load groups, users and deploy keys.') }),
)
.finally(() => {
this.initialLoading = false;
@@ -175,7 +175,7 @@ export default {
this.consolidateData(deployKeysResponse.data);
this.setSelected({ initial });
})
- .catch(() => createFlash({ message: __('Failed to load deploy keys.') }))
+ .catch(() => createAlert({ message: __('Failed to load deploy keys.') }))
.finally(() => {
this.initialLoading = false;
this.loading = false;
diff --git a/app/assets/javascripts/projects/settings/components/default_branch_selector.vue b/app/assets/javascripts/projects/settings/components/default_branch_selector.vue
new file mode 100644
index 00000000000..fee2f591216
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/components/default_branch_selector.vue
@@ -0,0 +1,38 @@
+<script>
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { REF_TYPE_BRANCHES } from '~/ref/constants';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ RefSelector,
+ },
+ props: {
+ persistedDefaultBranch: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: String,
+ required: true,
+ },
+ },
+ refTypes: [REF_TYPE_BRANCHES],
+ i18n: {
+ dropdownHeader: __('Select default branch'),
+ searchPlaceholder: __('Search branch'),
+ },
+};
+</script>
+<template>
+ <ref-selector
+ :value="persistedDefaultBranch"
+ class="gl-w-full"
+ :project-id="projectId"
+ :enabled-ref-types="$options.refTypes"
+ :translations="$options.i18n"
+ name="project[default_branch]"
+ data-testid="default-branch-dropdown"
+ data-qa-selector="default_branch_dropdown"
+ />
+</template>
diff --git a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
index c13753da00b..55420c9c732 100644
--- a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
+++ b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
@@ -1,13 +1,14 @@
<script>
-import { GlFormGroup } from '@gitlab/ui';
-import produce from 'immer';
+import { GlFormGroup, GlAlert } from '@gitlab/ui';
+import { debounce } from 'lodash';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
-import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select_deprecated.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { getTransferLocations } from '~/api/projects_api';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
-import searchNamespacesWhereUserCanTransferProjects from '../graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql';
-
-const GROUPS_PER_PAGE = 25;
+import { s__, __ } from '~/locale';
+import currentUserNamespace from '../graphql/queries/current_user_namespace.query.graphql';
export default {
name: 'TransferProjectForm',
@@ -15,7 +16,15 @@ export default {
GlFormGroup,
NamespaceSelect,
ConfirmDanger,
+ GlAlert,
+ },
+ i18n: {
+ errorMessage: s__(
+ 'ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again.',
+ ),
+ alertDismissAlert: __('Dismiss'),
},
+ inject: ['projectId'],
props: {
confirmationPhrase: {
type: String,
@@ -26,93 +35,131 @@ export default {
required: true,
},
},
- apollo: {
- currentUser: {
- query: searchNamespacesWhereUserCanTransferProjects,
- debounce: DEBOUNCE_DELAY,
- variables() {
- return {
- search: this.searchTerm,
- after: null,
- first: GROUPS_PER_PAGE,
- };
- },
- result() {
- this.isLoadingMoreGroups = false;
- this.isSearchLoading = false;
- },
- },
- },
data() {
return {
- currentUser: {},
+ userNamespaces: [],
+ groupNamespaces: [],
+ initialNamespacesLoaded: false,
selectedNamespace: null,
- isLoadingMoreGroups: false,
+ hasError: false,
+ isLoading: false,
isSearchLoading: false,
searchTerm: '',
+ page: 1,
+ totalPages: 1,
};
},
computed: {
hasSelectedNamespace() {
return Boolean(this.selectedNamespace?.id);
},
- groupNamespaces() {
- return this.currentUser.groups?.nodes?.map(this.formatNamespace) || [];
- },
- userNamespaces() {
- const { namespace } = this.currentUser;
-
- return namespace ? [this.formatNamespace(namespace)] : [];
- },
hasNextPageOfGroups() {
- return this.currentUser.groups?.pageInfo?.hasNextPage || false;
+ return this.page < this.totalPages;
},
},
methods: {
+ async handleShow() {
+ if (this.initialNamespacesLoaded) {
+ return;
+ }
+
+ this.isLoading = true;
+
+ [this.groupNamespaces, this.userNamespaces] = await Promise.all([
+ this.getGroupNamespaces(),
+ this.getUserNamespaces(),
+ ]);
+
+ this.isLoading = false;
+ this.initialNamespacesLoaded = true;
+ },
handleSelect(selectedNamespace) {
this.selectedNamespace = selectedNamespace;
this.$emit('selectNamespace', selectedNamespace.id);
},
- handleLoadMoreGroups() {
- this.isLoadingMoreGroups = true;
+ async getGroupNamespaces() {
+ try {
+ const { data: groupNamespaces, headers } = await getTransferLocations(this.projectId, {
+ page: this.page,
+ search: this.searchTerm,
+ });
+
+ const { totalPages } = parseIntPagination(normalizeHeaders(headers));
+ this.totalPages = totalPages;
- this.$apollo.queries.currentUser.fetchMore({
- variables: {
- after: this.currentUser.groups.pageInfo.endCursor,
- first: GROUPS_PER_PAGE,
- },
- updateQuery(
- previousResult,
+ return groupNamespaces.map(({ id, full_name: humanName }) => ({
+ id,
+ humanName,
+ }));
+ } catch (error) {
+ this.hasError = true;
+
+ return [];
+ }
+ },
+ async getUserNamespaces() {
+ try {
+ const {
+ data: {
+ currentUser: { namespace },
+ },
+ } = await this.$apollo.query({
+ query: currentUserNamespace,
+ });
+
+ if (!namespace) {
+ return [];
+ }
+
+ return [
{
- fetchMoreResult: {
- currentUser: { groups: newGroups },
- },
+ id: getIdFromGraphQLId(namespace.id),
+ humanName: namespace.fullName,
},
- ) {
- const previousGroups = previousResult.currentUser.groups;
+ ];
+ } catch (error) {
+ this.hasError = true;
- return produce(previousResult, (draftData) => {
- draftData.currentUser.groups.nodes = [...previousGroups.nodes, ...newGroups.nodes];
- draftData.currentUser.groups.pageInfo = newGroups.pageInfo;
- });
- },
- });
+ return [];
+ }
},
- handleSearch(searchTerm) {
+ async handleLoadMoreGroups() {
+ this.isLoading = true;
+ this.page += 1;
+
+ const groupNamespaces = await this.getGroupNamespaces();
+ this.groupNamespaces.push(...groupNamespaces);
+
+ this.isLoading = false;
+ },
+ debouncedSearch: debounce(async function debouncedSearch() {
this.isSearchLoading = true;
+
+ this.groupNamespaces = await this.getGroupNamespaces();
+
+ this.isSearchLoading = false;
+ }, DEBOUNCE_DELAY),
+ handleSearch(searchTerm) {
this.searchTerm = searchTerm;
+ this.page = 1;
+
+ this.debouncedSearch();
},
- formatNamespace({ id, fullName }) {
- return {
- id: getIdFromGraphQLId(id),
- humanName: fullName,
- };
+ handleAlertDismiss() {
+ this.hasError = false;
},
},
};
</script>
<template>
<div>
+ <gl-alert
+ v-if="hasError"
+ variant="danger"
+ :dismiss-label="$options.i18n.alertDismissLabel"
+ @dismiss="handleAlertDismiss"
+ >{{ $options.i18n.errorMessage }}</gl-alert
+ >
<gl-form-group>
<namespace-select
data-testid="transfer-project-namespace"
@@ -121,12 +168,13 @@ export default {
:user-namespaces="userNamespaces"
:selected-namespace="selectedNamespace"
:has-next-page-of-groups="hasNextPageOfGroups"
- :is-loading-more-groups="isLoadingMoreGroups"
+ :is-loading="isLoading"
:is-search-loading="isSearchLoading"
:should-filter-namespaces="false"
@select="handleSelect"
@load-more-groups="handleLoadMoreGroups"
@search="handleSearch"
+ @show="handleShow"
/>
</gl-form-group>
<confirm-danger
diff --git a/app/assets/javascripts/projects/settings/graphql/queries/current_user_namespace.query.graphql b/app/assets/javascripts/projects/settings/graphql/queries/current_user_namespace.query.graphql
new file mode 100644
index 00000000000..7ae6ee1428b
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/graphql/queries/current_user_namespace.query.graphql
@@ -0,0 +1,9 @@
+query currentUserNamespace {
+ currentUser {
+ id
+ namespace {
+ id
+ fullName
+ }
+ }
+}
diff --git a/app/assets/javascripts/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql b/app/assets/javascripts/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql
deleted file mode 100644
index d4bcb8c869c..00000000000
--- a/app/assets/javascripts/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql
+++ /dev/null
@@ -1,24 +0,0 @@
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-
-query searchNamespacesWhereUserCanTransferProjects(
- $search: String = ""
- $after: String = ""
- $first: Int = null
-) {
- currentUser {
- id
- groups(permissionScope: TRANSFER_PROJECTS, search: $search, after: $after, first: $first) {
- nodes {
- id
- fullName
- }
- pageInfo {
- ...PageInfo
- }
- }
- namespace {
- id
- fullName
- }
- }
-}
diff --git a/app/assets/javascripts/projects/settings/init_transfer_project_form.js b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
index bc1aff640d2..89c158a9ba8 100644
--- a/app/assets/javascripts/projects/settings/init_transfer_project_form.js
+++ b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
@@ -12,6 +12,7 @@ export default () => {
Vue.use(VueApollo);
const {
+ projectId,
targetFormId = null,
targetHiddenInputId = null,
buttonText: confirmButtonText = '',
@@ -26,6 +27,7 @@ export default () => {
}),
provide: {
confirmDangerMessage,
+ projectId,
},
render(createElement) {
return createElement(TransferProjectForm, {
diff --git a/app/assets/javascripts/projects/settings/mount_default_branch_selector.js b/app/assets/javascripts/projects/settings/mount_default_branch_selector.js
new file mode 100644
index 00000000000..611561e38f2
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/mount_default_branch_selector.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import DefaultBranchSelector from './components/default_branch_selector.vue';
+
+export default (el) => {
+ if (!el) {
+ return null;
+ }
+
+ const { projectId, defaultBranch } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(DefaultBranchSelector, {
+ props: {
+ persistedDefaultBranch: defaultBranch,
+ projectId,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
index e8eaf0a70b2..94793a535cc 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
@@ -1,6 +1,6 @@
<script>
import { s__ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import branchRulesQuery from './graphql/queries/branch_rules.query.graphql';
import BranchRule from './components/branch_rule.vue';
@@ -31,14 +31,13 @@ export default {
return data.project?.branchRules?.nodes || [];
},
error() {
- createFlash({ message: this.$options.i18n.queryError });
+ createAlert({ message: this.$options.i18n.queryError });
},
},
},
- props: {
+ inject: {
projectPath: {
- type: String,
- required: true,
+ default: '',
},
},
data() {
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
index 68750318029..2b88f8561d7 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
@@ -1,10 +1,11 @@
<script>
-import { GlBadge } from '@gitlab/ui';
+import { GlBadge, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale';
export const i18n = {
defaultLabel: s__('BranchRules|default'),
protectedLabel: s__('BranchRules|protected'),
+ detailsButtonLabel: s__('BranchRules|Details'),
};
export default {
@@ -12,6 +13,12 @@ export default {
i18n,
components: {
GlBadge,
+ GlButton,
+ },
+ inject: {
+ branchRulesPath: {
+ default: '',
+ },
},
props: {
name: {
@@ -38,24 +45,30 @@ export default {
hasApprovalDetails() {
return this.approvalDetails && this.approvalDetails.length;
},
+ detailsPath() {
+ return `${this.branchRulesPath}?branch=${this.name}`;
+ },
},
};
</script>
<template>
- <div class="gl-border-b gl-pt-5 gl-pb-5">
- <strong class="gl-font-monospace">{{ name }}</strong>
+ <div class="gl-border-b gl-pt-5 gl-pb-5 gl-display-flex gl-justify-content-space-between">
+ <div>
+ <strong class="gl-font-monospace">{{ name }}</strong>
- <gl-badge v-if="isDefault" variant="info" size="sm" class="gl-ml-2">{{
- $options.i18n.defaultLabel
- }}</gl-badge>
+ <gl-badge v-if="isDefault" variant="info" size="sm" class="gl-ml-2">{{
+ $options.i18n.defaultLabel
+ }}</gl-badge>
- <gl-badge v-if="isProtected" variant="success" size="sm" class="gl-ml-2">{{
- $options.i18n.protectedLabel
- }}</gl-badge>
+ <gl-badge v-if="isProtected" variant="success" size="sm" class="gl-ml-2">{{
+ $options.i18n.protectedLabel
+ }}</gl-badge>
- <ul v-if="hasApprovalDetails" class="gl-pl-6 gl-mt-2 gl-mb-0 gl-text-gray-500">
- <li v-for="(detail, index) in approvalDetails" :key="index">{{ detail }}</li>
- </ul>
+ <ul v-if="hasApprovalDetails" class="gl-pl-6 gl-mt-2 gl-mb-0 gl-text-gray-500">
+ <li v-for="(detail, index) in approvalDetails" :key="index">{{ detail }}</li>
+ </ul>
+ </div>
+ <gl-button :href="detailsPath"> {{ $options.i18n.detailsButtonLabel }}</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js
index 35322e2e466..042be089e09 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/mount_branch_rules.js
@@ -12,17 +12,17 @@ const apolloProvider = new VueApollo({
export default function mountBranchRules(el) {
if (!el) return null;
- const { projectPath } = el.dataset;
+ const { projectPath, branchRulesPath } = el.dataset;
return new Vue({
el,
apolloProvider,
+ provide: {
+ projectPath,
+ branchRulesPath,
+ },
render(createElement) {
- return createElement(BranchRulesApp, {
- props: {
- projectPath,
- },
- });
+ return createElement(BranchRulesApp);
},
});
}
diff --git a/app/assets/javascripts/projects/star.js b/app/assets/javascripts/projects/star.js
index e063064663b..55c3d68cd11 100644
--- a/app/assets/javascripts/projects/star.js
+++ b/app/assets/javascripts/projects/star.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from '~/lib/utils/common_utils';
import { __, s__ } from '~/locale';
@@ -7,7 +7,7 @@ export default class Star {
constructor(containerSelector = '.project-home-panel') {
const container = document.querySelector(containerSelector);
const starToggle = container.querySelector('.toggle-star');
- starToggle.addEventListener('click', function toggleStarClickCallback() {
+ starToggle?.addEventListener('click', function toggleStarClickCallback() {
const starSpan = starToggle.querySelector('span');
const starIcon = starToggle.querySelector('svg');
const iconClasses = Array.from(starIcon.classList.values());
@@ -34,7 +34,7 @@ export default class Star {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Star toggle failed. Try again later.'),
}),
);
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index 6b14ebadacc..9f9b6424125 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Poll from '~/lib/utils/poll';
import { __, s__, sprintf } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -57,7 +57,7 @@ export default {
group: 'notfound',
};
this.isLoading = false;
- createFlash({
+ createAlert({
message: __('Something went wrong on our end'),
});
},
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js
index 16eb5c3de32..120f75d4f0c 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import CreateItemDropdown from '~/create_item_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import AccessorUtilities from '~/lib/utils/accessor';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -74,7 +74,7 @@ export default class ProtectedBranchCreate {
$allowedToPush.length
);
- this.$form.find('input[type="submit"]').attr('disabled', toggle);
+ this.$form.find('button[type="submit"]').attr('disabled', toggle);
}
static getProtectedBranches(term, callback) {
@@ -130,7 +130,7 @@ export default class ProtectedBranchCreate {
window.location.reload();
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Failed to protect the branch'),
}),
);
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index 15e706e38c6..1693d869b54 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -1,5 +1,5 @@
import { find } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import AccessDropdown from '~/projects/settings/access_dropdown';
@@ -74,7 +74,7 @@ export default class ProtectedBranchEdit {
})
.then(callback)
.catch(() => {
- createFlash({ message: __('Failed to update branch!') });
+ createAlert({ message: __('Failed to update branch!') });
});
}
@@ -141,7 +141,7 @@ export default class ProtectedBranchEdit {
.catch(() => {
this.$allowedToMergeDropdown.enable();
this.$allowedToPushDropdown.enable();
- createFlash({ message: __('Failed to update branch!') });
+ createAlert({ message: __('Failed to update branch!') });
});
}
diff --git a/app/assets/javascripts/protected_tags/protected_tag_edit.js b/app/assets/javascripts/protected_tags/protected_tag_edit.js
index 1fe9a753e1e..40c52eba99e 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_edit.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_edit.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '../lib/utils/axios_utils';
import { FAILED_TO_UPDATE_TAG_MESSAGE } from './constants';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
@@ -49,7 +49,7 @@ export default class ProtectedTagEdit {
this.$allowedToCreateDropdownButton.enable();
window.scrollTo({ top: 0, behavior: 'smooth' });
- createFlash({
+ createAlert({
message: FAILED_TO_UPDATE_TAG_MESSAGE,
});
});
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index 1343ad8246c..b75958e2ced 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -29,6 +29,7 @@ export default {
GlLoadingIcon,
RefResultsSection,
},
+ inheritAttrs: false,
props: {
enabledRefTypes: {
type: Array,
@@ -70,6 +71,15 @@ export default {
required: false,
default: true,
},
+
+ /* Underlying form field name for scenarios where ref_selector
+ * is used as part of submitting an HTML form
+ */
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -213,89 +223,103 @@ export default {
</script>
<template>
- <gl-dropdown
- :header-text="i18n.dropdownHeader"
- :toggle-class="toggleButtonClass"
- :text="buttonText"
- class="ref-selector"
- v-bind="$attrs"
- v-on="$listeners"
- @shown="focusSearchBox"
- >
- <template #header>
- <gl-search-box-by-type
- ref="searchBox"
- v-model.trim="query"
- :placeholder="i18n.searchPlaceholder"
- autocomplete="off"
- @input="onSearchBoxInput"
- @keydown.enter.prevent="onSearchBoxEnter"
- />
- </template>
+ <div>
+ <gl-dropdown
+ :header-text="i18n.dropdownHeader"
+ :toggle-class="toggleButtonClass"
+ :text="buttonText"
+ class="ref-selector gl-w-full"
+ v-bind="$attrs"
+ v-on="$listeners"
+ @shown="focusSearchBox"
+ >
+ <template #header>
+ <gl-search-box-by-type
+ ref="searchBox"
+ v-model.trim="query"
+ :placeholder="i18n.searchPlaceholder"
+ autocomplete="off"
+ data-qa-selector="ref_selector_searchbox"
+ @input="onSearchBoxInput"
+ @keydown.enter.prevent="onSearchBoxEnter"
+ />
+ </template>
- <gl-loading-icon v-if="isLoading" size="lg" class="gl-my-3" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-my-3" />
- <div v-else-if="showNoResults" class="gl-text-center gl-mx-3 gl-py-3" data-testid="no-results">
- <gl-sprintf v-if="lastQuery" :message="i18n.noResultsWithQuery">
- <template #query>
- <b class="gl-word-break-all">{{ lastQuery }}</b>
- </template>
- </gl-sprintf>
+ <div
+ v-else-if="showNoResults"
+ class="gl-text-center gl-mx-3 gl-py-3"
+ data-testid="no-results"
+ >
+ <gl-sprintf v-if="lastQuery" :message="i18n.noResultsWithQuery">
+ <template #query>
+ <b class="gl-word-break-all">{{ lastQuery }}</b>
+ </template>
+ </gl-sprintf>
- <span v-else>{{ i18n.noResults }}</span>
- </div>
+ <span v-else>{{ i18n.noResults }}</span>
+ </div>
- <template v-else>
- <template v-if="showBranchesSection">
- <ref-results-section
- :section-title="i18n.branches"
- :total-count="matches.branches.totalCount"
- :items="matches.branches.list"
- :selected-ref="selectedRef"
- :error="matches.branches.error"
- :error-message="i18n.branchesErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="branches-section"
- data-qa-selector="branches_section"
- @selected="selectRef($event)"
- />
+ <template v-else>
+ <template v-if="showBranchesSection">
+ <ref-results-section
+ :section-title="i18n.branches"
+ :total-count="matches.branches.totalCount"
+ :items="matches.branches.list"
+ :selected-ref="selectedRef"
+ :error="matches.branches.error"
+ :error-message="i18n.branchesErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="branches-section"
+ data-qa-selector="branches_section"
+ @selected="selectRef($event)"
+ />
- <gl-dropdown-divider v-if="showTagsSection || showCommitsSection" />
- </template>
+ <gl-dropdown-divider v-if="showTagsSection || showCommitsSection" />
+ </template>
- <template v-if="showTagsSection">
- <ref-results-section
- :section-title="i18n.tags"
- :total-count="matches.tags.totalCount"
- :items="matches.tags.list"
- :selected-ref="selectedRef"
- :error="matches.tags.error"
- :error-message="i18n.tagsErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="tags-section"
- @selected="selectRef($event)"
- />
+ <template v-if="showTagsSection">
+ <ref-results-section
+ :section-title="i18n.tags"
+ :total-count="matches.tags.totalCount"
+ :items="matches.tags.list"
+ :selected-ref="selectedRef"
+ :error="matches.tags.error"
+ :error-message="i18n.tagsErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="tags-section"
+ @selected="selectRef($event)"
+ />
- <gl-dropdown-divider v-if="showCommitsSection" />
- </template>
+ <gl-dropdown-divider v-if="showCommitsSection" />
+ </template>
- <template v-if="showCommitsSection">
- <ref-results-section
- :section-title="i18n.commits"
- :total-count="matches.commits.totalCount"
- :items="matches.commits.list"
- :selected-ref="selectedRef"
- :error="matches.commits.error"
- :error-message="i18n.commitsErrorMessage"
- :show-header="showSectionHeaders"
- data-testid="commits-section"
- @selected="selectRef($event)"
- />
+ <template v-if="showCommitsSection">
+ <ref-results-section
+ :section-title="i18n.commits"
+ :total-count="matches.commits.totalCount"
+ :items="matches.commits.list"
+ :selected-ref="selectedRef"
+ :error="matches.commits.error"
+ :error-message="i18n.commitsErrorMessage"
+ :show-header="showSectionHeaders"
+ data-testid="commits-section"
+ @selected="selectRef($event)"
+ />
+ </template>
</template>
- </template>
- <template #footer>
- <slot name="footer" v-bind="footerSlotProps"></slot>
- </template>
- </gl-dropdown>
+ <template #footer>
+ <slot name="footer" v-bind="footerSlotProps"></slot>
+ </template>
+ </gl-dropdown>
+ <input
+ v-if="name"
+ data-testid="selected-ref-form-field"
+ type="hidden"
+ :value="selectedRef"
+ :name="name"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/related_issues/components/related_issues_block.vue b/app/assets/javascripts/related_issues/components/related_issues_block.vue
index 53f2dbbbbd7..1ab41ee2f0a 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -233,6 +233,7 @@ export default {
<div
v-if="isFormVisible"
class="js-add-related-issues-form-area card-body bordered-box bg-white"
+ :class="{ 'gl-mb-5': shouldShowTokenBody }"
>
<add-issuable-form
:show-categorized-issues="showCategorizedIssues"
@@ -253,7 +254,7 @@ export default {
</div>
<template v-if="shouldShowTokenBody">
<related-issues-list
- v-for="category in categorisedIssues"
+ v-for="(category, index) in categorisedIssues"
:key="category.linkType"
:list-link-type="category.linkType"
:heading="$options.linkedIssueTypesTextMap[category.linkType]"
@@ -263,6 +264,7 @@ export default {
:issuable-type="issuableType"
:path-id-separator="pathIdSeparator"
:related-issues="category.issues"
+ :class="{ 'gl-mt-5': index > 0 }"
@relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)"
@saveReorder="$emit('saveReorder', $event)"
/>
diff --git a/app/assets/javascripts/related_issues/components/related_issues_root.vue b/app/assets/javascripts/related_issues/components/related_issues_root.vue
index ae40232df6f..38e1d6e9d4f 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_root.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -23,7 +23,7 @@ Your caret can stop touching a `rawReference` can happen in a variety of ways:
and hide the `AddIssuableForm` area.
*/
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import {
@@ -141,11 +141,11 @@ export default {
})
.catch((res) => {
if (res && res.status !== 404) {
- createFlash({ message: relatedIssuesRemoveErrorMap[this.issuableType] });
+ createAlert({ message: relatedIssuesRemoveErrorMap[this.issuableType] });
}
});
} else {
- createFlash({ message: pathIndeterminateErrorMap[this.issuableType] });
+ createAlert({ message: pathIndeterminateErrorMap[this.issuableType] });
}
},
onToggleAddRelatedIssuesForm() {
@@ -174,7 +174,7 @@ export default {
if (response && response.data && response.data.message) {
errorMessage = response.data.message;
}
- createFlash({ message: errorMessage });
+ createAlert({ message: errorMessage });
})
.finally(() => {
this.isSubmitting = false;
@@ -195,7 +195,7 @@ export default {
})
.catch(() => {
this.store.setRelatedIssues([]);
- createFlash({ message: __('An error occurred while fetching issues.') });
+ createAlert({ message: __('An error occurred while fetching issues.') });
})
.finally(() => {
this.isFetching = false;
@@ -216,7 +216,7 @@ export default {
}
})
.catch(() => {
- createFlash({ message: __('An error occurred while reordering issues.') });
+ createAlert({ message: __('An error occurred while reordering issues.') });
});
}
},
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index d63a83d1a08..6dc8240e680 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -1,6 +1,6 @@
<script>
import { GlButton } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { historyPushState } from '~/lib/utils/common_utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
import { setUrlParams, getParameterByName } from '~/lib/utils/url_utility';
@@ -71,7 +71,7 @@ export default {
error(error) {
this.fullRequestError = true;
- createFlash({
+ createAlert({
message: this.$options.i18n.errorMessage,
captureError: true,
error,
diff --git a/app/assets/javascripts/releases/components/app_show.vue b/app/assets/javascripts/releases/components/app_show.vue
index fdb0f99b735..7147cfa01c8 100644
--- a/app/assets/javascripts/releases/components/app_show.vue
+++ b/app/assets/javascripts/releases/components/app_show.vue
@@ -1,5 +1,5 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import oneReleaseQuery from '../graphql/queries/one_release.query.graphql';
import { convertGraphQLRelease } from '../util';
@@ -51,7 +51,7 @@ export default {
},
methods: {
showFlash(error) {
- createFlash({
+ createAlert({
message: s__('Release|Something went wrong while getting the release details.'),
captureError: true,
error,
diff --git a/app/assets/javascripts/releases/components/tag_field_new.vue b/app/assets/javascripts/releases/components/tag_field_new.vue
index 08b727dcca0..2ddab5dddea 100644
--- a/app/assets/javascripts/releases/components/tag_field_new.vue
+++ b/app/assets/javascripts/releases/components/tag_field_new.vue
@@ -1,8 +1,15 @@
<script>
-import { GlFormGroup, GlDropdownItem, GlSprintf } from '@gitlab/ui';
+import {
+ GlCollapse,
+ GlLink,
+ GlFormGroup,
+ GlFormTextarea,
+ GlDropdownItem,
+ GlSprintf,
+} from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { mapState, mapActions, mapGetters } from 'vuex';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import { REF_TYPE_TAGS } from '~/ref/constants';
import FormFieldContainer from './form_field_container.vue';
@@ -10,7 +17,10 @@ import FormFieldContainer from './form_field_container.vue';
export default {
name: 'TagFieldNew',
components: {
+ GlCollapse,
GlFormGroup,
+ GlFormTextarea,
+ GlLink,
RefSelector,
FormFieldContainer,
GlDropdownItem,
@@ -41,6 +51,14 @@ export default {
this.updateShowCreateFrom(false);
},
},
+ tagMessage: {
+ get() {
+ return this.release.tagMessage;
+ },
+ set(tagMessage) {
+ this.updateReleaseTagMessage(tagMessage);
+ },
+ },
createFromModel: {
get() {
return this.createFrom;
@@ -70,6 +88,7 @@ export default {
methods: {
...mapActions('editNew', [
'updateReleaseTagName',
+ 'updateReleaseTagMessage',
'updateCreateFrom',
'fetchTagNotes',
'updateShowCreateFrom',
@@ -113,9 +132,20 @@ export default {
noRefSelected: __('No source selected'),
searchPlaceholder: __('Search branches, tags, and commits'),
dropdownHeader: __('Select source'),
+ label: __('Create from'),
+ description: __('Existing branch name, tag, or commit SHA'),
+ },
+ annotatedTag: {
+ label: s__('CreateGitTag|Set tag message'),
+ description: s__(
+ 'CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}.',
+ ),
},
},
+ tagMessageId: uniqueId('tag-message-'),
+
tagNameEnabledRefTypes: [REF_TYPE_TAGS],
+ gitTagDocsLink: 'https://git-scm.com/book/en/v2/Git-Basics-Tagging/',
};
</script>
<template>
@@ -156,23 +186,45 @@ export default {
</ref-selector>
</form-field-container>
</gl-form-group>
- <gl-form-group
- v-if="showCreateFrom"
- :label="__('Create from')"
- :label-for="createFromSelectorId"
- data-testid="create-from-field"
- >
- <form-field-container>
- <ref-selector
- :id="createFromSelectorId"
- v-model="createFromModel"
- :project-id="projectId"
- :translations="$options.translations.createFrom"
- />
- </form-field-container>
- <template #description>
- {{ __('Existing branch name, tag, or commit SHA') }}
- </template>
- </gl-form-group>
+ <gl-collapse :visible="showCreateFrom">
+ <div class="gl-pl-6 gl-border-l-1 gl-border-l-solid gl-border-gray-300">
+ <gl-form-group
+ v-if="showCreateFrom"
+ :label="$options.translations.createFrom.label"
+ :label-for="createFromSelectorId"
+ data-testid="create-from-field"
+ >
+ <form-field-container>
+ <ref-selector
+ :id="createFromSelectorId"
+ v-model="createFromModel"
+ :project-id="projectId"
+ :translations="$options.translations.createFrom"
+ />
+ </form-field-container>
+ <template #description>{{ $options.translations.createFrom.description }}</template>
+ </gl-form-group>
+ <gl-form-group
+ v-if="showCreateFrom"
+ :label="$options.translations.annotatedTag.label"
+ :label-for="$options.tagMessageId"
+ data-testid="annotated-tag-message-field"
+ >
+ <gl-form-textarea :id="$options.tagMessageId" v-model="tagMessage" />
+ <template #description>
+ <gl-sprintf :message="$options.translations.annotatedTag.description">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.gitTagDocsLink"
+ rel="noopener noreferrer"
+ target="_blank"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-form-group>
+ </div>
+ </gl-collapse>
</div>
</template>
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
index 669e5928143..42ceed81c00 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
@@ -1,5 +1,5 @@
import { getTag } from '~/rest_api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import createReleaseMutation from '~/releases/graphql/mutations/create_release.mutation.graphql';
@@ -48,7 +48,7 @@ export const fetchRelease = async ({ commit, state }) => {
commit(types.RECEIVE_RELEASE_SUCCESS, release);
} catch (error) {
commit(types.RECEIVE_RELEASE_ERROR, error);
- createFlash({
+ createAlert({
message: s__('Release|Something went wrong while getting the release details.'),
});
}
@@ -57,6 +57,9 @@ export const fetchRelease = async ({ commit, state }) => {
export const updateReleaseTagName = ({ commit }, tagName) =>
commit(types.UPDATE_RELEASE_TAG_NAME, tagName);
+export const updateReleaseTagMessage = ({ commit }, tagMessage) =>
+ commit(types.UPDATE_RELEASE_TAG_MESSAGE, tagMessage);
+
export const updateCreateFrom = ({ commit }, createFrom) =>
commit(types.UPDATE_CREATE_FROM, createFrom);
@@ -133,11 +136,11 @@ export const createRelease = async ({ commit, dispatch, getters }) => {
} catch (error) {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
if (error instanceof GraphQLError) {
- createFlash({
+ createAlert({
message: error.message,
});
} else {
- createFlash({
+ createAlert({
message: s__('Release|Something went wrong while creating a new release.'),
});
}
@@ -219,7 +222,7 @@ export const updateRelease = async ({ commit, dispatch, state, getters }) => {
dispatch('receiveSaveReleaseSuccess', state.release._links.self);
} catch (error) {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash({
+ createAlert({
message: s__('Release|Something went wrong while saving the release details.'),
});
}
@@ -233,7 +236,7 @@ export const fetchTagNotes = ({ commit, state }, tagName) => {
commit(types.RECEIVE_TAG_NOTES_SUCCESS, data);
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__('Release|Unable to fetch the tag notes.'),
});
@@ -266,7 +269,7 @@ export const deleteRelease = ({ commit, getters, dispatch, state }) => {
})
.catch((error) => {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash({
+ createAlert({
message: s__('Release|Something went wrong while deleting the release.'),
});
});
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/getters.js b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js
index ccca9ca8250..0d77095d099 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/getters.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js
@@ -145,6 +145,7 @@ export const releaseCreateMutatationVariables = (state, getters) => {
input: {
...getters.releaseUpdateMutatationVariables.input,
ref: state.createFrom,
+ tagMessage: state.release.tagMessage,
assets: {
links: getters.releaseLinksToCreate.map(({ name, url, linkType }) => ({
name: name.trim(),
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js
index 0ef017f4eb4..e52eccd6a21 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js
@@ -5,6 +5,7 @@ export const RECEIVE_RELEASE_SUCCESS = 'RECEIVE_RELEASE_SUCCESS';
export const RECEIVE_RELEASE_ERROR = 'RECEIVE_RELEASE_ERROR';
export const UPDATE_RELEASE_TAG_NAME = 'UPDATE_RELEASE_TAG_NAME';
+export const UPDATE_RELEASE_TAG_MESSAGE = 'UPDATE_RELEASE_TAG_MESSAGE';
export const UPDATE_CREATE_FROM = 'UPDATE_CREATE_FROM';
export const UPDATE_SHOW_CREATE_FROM = 'UPDATE_SHOW_CREATE_FROM';
export const UPDATE_RELEASE_TITLE = 'UPDATE_RELEASE_TITLE';
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js
index 34361f84a5a..f80e75501c9 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js
@@ -10,6 +10,7 @@ export default {
[types.INITIALIZE_EMPTY_RELEASE](state) {
state.release = {
tagName: state.tagName,
+ tagMessage: '',
name: '',
description: '',
milestones: [],
@@ -40,6 +41,9 @@ export default {
[types.UPDATE_RELEASE_TAG_NAME](state, tagName) {
state.release.tagName = tagName;
},
+ [types.UPDATE_RELEASE_TAG_MESSAGE](state, tagMessage) {
+ state.release.tagMessage = tagMessage;
+ },
[types.UPDATE_CREATE_FROM](state, createFrom) {
state.createFrom = createFrom;
},
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/state.js b/app/assets/javascripts/releases/stores/modules/edit_new/state.js
index 11a2f9df59b..3112becfa9e 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/state.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/state.js
@@ -37,7 +37,7 @@ export default ({
* When creating a new release, this is the default from the URL
*/
tagName,
- showCreateFrom: !tagName,
+ showCreateFrom: false,
defaultBranch,
createFrom: defaultBranch,
diff --git a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
deleted file mode 100644
index 05ab5c2cc90..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlBadge, GlLink } from '@gitlab/ui';
-
-export default {
- name: 'AccessibilityIssueBody',
- components: {
- GlBadge,
- GlLink,
- },
- props: {
- issue: {
- type: Object,
- required: true,
- },
- isNew: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- parsedTECHSCode() {
- /*
- * In issue code looks like "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail"
- * or "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent"
- *
- * The TECHS code is the "G18", "G168", "H91", etc. from the code which is used for the documentation.
- * Here we simply split the string on `.` and get the code in the 5th position
- */
- return this.issue.code?.split('.')[4];
- },
- learnMoreUrl() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `https://www.w3.org/TR/WCAG20-TECHS/${this.parsedTECHSCode || 'Overview'}.html`;
- },
- },
-};
-</script>
-<template>
- <div class="report-block-list-issue-description gl-mt-2 gl-mb-2">
- <div ref="accessibility-issue-description" class="report-block-list-issue-description-text">
- <gl-badge v-if="isNew" class="gl-mr-2" variant="danger">{{
- s__('AccessibilityReport|New')
- }}</gl-badge>
- <div>
- {{
- sprintf(
- s__(
- 'AccessibilityReport|The accessibility scanning found an error of the following type: %{code}',
- ),
- { code: issue.code },
- )
- }}
- <gl-link ref="accessibility-issue-learn-more" :href="learnMoreUrl" target="_blank">{{
- s__('AccessibilityReport|Learn more')
- }}</gl-link>
- </div>
- {{ sprintf(s__('AccessibilityReport|Message: %{message}'), { message: issue.message }) }}
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
deleted file mode 100644
index 99cdeae545e..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { mapActions, mapGetters } from 'vuex';
-import { componentNames } from '~/reports/components/issue_body';
-import IssuesList from '~/reports/components/issues_list.vue';
-import ReportSection from '~/reports/components/report_section.vue';
-import createStore from './store';
-
-export default {
- name: 'GroupedAccessibilityReportsApp',
- store: createStore(),
- components: {
- ReportSection,
- IssuesList,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- componentNames,
- computed: {
- ...mapGetters([
- 'summaryStatus',
- 'groupedSummaryText',
- 'shouldRenderIssuesList',
- 'unresolvedIssues',
- 'resolvedIssues',
- 'newIssues',
- ]),
- },
- created() {
- this.setEndpoint(this.endpoint);
-
- this.fetchReport();
- },
- methods: {
- ...mapActions(['fetchReport', 'setEndpoint']),
- },
-};
-</script>
-<template>
- <report-section
- :status="summaryStatus"
- :success-text="groupedSummaryText"
- :loading-text="groupedSummaryText"
- :error-text="groupedSummaryText"
- :has-issues="shouldRenderIssuesList"
- track-action="users_expanding_testing_accessibility_report"
- class="mr-widget-section grouped-security-reports mr-report"
- >
- <template #body>
- <div class="mr-widget-grouped-section report-block">
- <issues-list
- v-if="shouldRenderIssuesList"
- :unresolved-issues="unresolvedIssues"
- :new-issues="newIssues"
- :resolved-issues="resolvedIssues"
- :component="$options.componentNames.AccessibilityIssueBody"
- class="report-block-group-list"
- />
- </div>
- </template>
- </report-section>
-</template>
diff --git a/app/assets/javascripts/reports/accessibility_report/store/actions.js b/app/assets/javascripts/reports/accessibility_report/store/actions.js
deleted file mode 100644
index e0142a35291..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/actions.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Visibility from 'visibilityjs';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
-import Poll from '~/lib/utils/poll';
-import * as types from './mutation_types';
-
-let eTagPoll;
-
-export const clearEtagPoll = () => {
- eTagPoll = null;
-};
-
-export const stopPolling = () => {
- if (eTagPoll) eTagPoll.stop();
-};
-
-export const restartPolling = () => {
- if (eTagPoll) eTagPoll.restart();
-};
-
-export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
-
-/**
- * We need to poll the report endpoint while they are being parsed in the Backend.
- * This can take up to one minute.
- *
- * Poll.js will handle etag response.
- * While http status code is 204, it means it's parsing, and we'll keep polling
- * When http status code is 200, it means parsing is done, we can show the results & stop polling
- * When http status code is 500, it means parsing went wrong and we stop polling
- */
-export const fetchReport = ({ state, dispatch, commit }) => {
- commit(types.REQUEST_REPORT);
-
- eTagPoll = new Poll({
- resource: {
- getReport(endpoint) {
- return axios.get(endpoint);
- },
- },
- data: state.endpoint,
- method: 'getReport',
- successCallback: ({ status, data }) => dispatch('receiveReportSuccess', { status, data }),
- errorCallback: () => dispatch('receiveReportError'),
- });
-
- if (!Visibility.hidden()) {
- eTagPoll.makeRequest();
- } else {
- axios
- .get(state.endpoint)
- .then(({ status, data }) => dispatch('receiveReportSuccess', { status, data }))
- .catch(() => dispatch('receiveReportError'));
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden() && state.isLoading) {
- dispatch('restartPolling');
- } else {
- dispatch('stopPolling');
- }
- });
-};
-
-export const receiveReportSuccess = ({ commit, dispatch }, { status, data }) => {
- if (status === httpStatusCodes.OK) {
- commit(types.RECEIVE_REPORT_SUCCESS, data);
- // Stop polling since we have the information already parsed and it won't be changing
- dispatch('stopPolling');
- }
-};
-
-export const receiveReportError = ({ commit, dispatch }) => {
- commit(types.RECEIVE_REPORT_ERROR);
- dispatch('stopPolling');
-};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js
deleted file mode 100644
index 20506b1bfd1..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/getters.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { s__, n__ } from '~/locale';
-import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants';
-
-export const groupedSummaryText = (state) => {
- if (state.isLoading) {
- return s__('Reports|Accessibility scanning results are being parsed');
- }
-
- if (state.hasError) {
- return s__('Reports|Accessibility scanning failed loading results');
- }
-
- const numberOfResults = state.report?.summary?.errored || 0;
- if (numberOfResults === 0) {
- return s__('Reports|Accessibility scanning detected no issues for the source branch only');
- }
-
- return n__(
- 'Reports|Accessibility scanning detected %d issue for the source branch only',
- 'Reports|Accessibility scanning detected %d issues for the source branch only',
- numberOfResults,
- );
-};
-
-export const summaryStatus = (state) => {
- if (state.isLoading) {
- return LOADING;
- }
-
- if (state.hasError || state.status === STATUS_FAILED) {
- return ERROR;
- }
-
- return SUCCESS;
-};
-
-export const shouldRenderIssuesList = (state) =>
- Object.values(state.report).some((x) => Array.isArray(x) && x.length > 0);
-
-// We could just map state, but we're going to iterate in the future
-// to add notes and warnings to these issue lists, so I'm going to
-// keep these as getters
-export const unresolvedIssues = (state) => state.report.existing_errors;
-export const resolvedIssues = (state) => state.report.resolved_errors;
-export const newIssues = (state) => state.report.new_errors;
diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js
deleted file mode 100644
index 5bfcd69edec..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import * as actions from './actions';
-import * as getters from './getters';
-import mutations from './mutations';
-import state from './state';
-
-Vue.use(Vuex);
-
-export const getStoreConfig = (initialState) => ({
- actions,
- getters,
- mutations,
- state: state(initialState),
-});
-
-export default (initialState) => new Vuex.Store(getStoreConfig(initialState));
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js b/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
deleted file mode 100644
index 22e2330e1ea..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const SET_ENDPOINT = 'SET_ENDPOINT';
-
-export const REQUEST_REPORT = 'REQUEST_REPORT';
-export const RECEIVE_REPORT_SUCCESS = 'RECEIVE_REPORT_SUCCESS';
-export const RECEIVE_REPORT_ERROR = 'RECEIVE_REPORT_ERROR';
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutations.js b/app/assets/javascripts/reports/accessibility_report/store/mutations.js
deleted file mode 100644
index 20d3e5be9a3..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/mutations.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as types from './mutation_types';
-
-export default {
- [types.SET_ENDPOINT](state, endpoint) {
- state.endpoint = endpoint;
- },
- [types.REQUEST_REPORT](state) {
- state.isLoading = true;
- },
- [types.RECEIVE_REPORT_SUCCESS](state, report) {
- state.hasError = false;
- state.isLoading = false;
- state.report = report;
- },
- [types.RECEIVE_REPORT_ERROR](state) {
- state.isLoading = false;
- state.hasError = true;
- state.report = {};
- },
-};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/state.js b/app/assets/javascripts/reports/accessibility_report/store/state.js
deleted file mode 100644
index 2a4cefea5e6..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/state.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export default (initialState = {}) => ({
- endpoint: initialState.endpoint || '',
-
- isLoading: initialState.isLoading || false,
- hasError: initialState.hasError || false,
-
- /**
- * Report will have the following format:
- * {
- * status: {String},
- * summary: {
- * total: {Number},
- * resolved: {Number},
- * errored: {Number},
- * },
- * existing_errors: {Array.<Object>},
- * existing_notes: {Array.<Object>},
- * existing_warnings: {Array.<Object>},
- * new_errors: {Array.<Object>},
- * new_notes: {Array.<Object>},
- * new_warnings: {Array.<Object>},
- * resolved_errors: {Array.<Object>},
- * resolved_notes: {Array.<Object>},
- * resolved_warnings: {Array.<Object>},
- * }
- */
- report: initialState.report || {},
-});
diff --git a/app/assets/javascripts/reports/components/issue_body.js b/app/assets/javascripts/reports/components/issue_body.js
index 04e72809e62..a76a6f45c07 100644
--- a/app/assets/javascripts/reports/components/issue_body.js
+++ b/app/assets/javascripts/reports/components/issue_body.js
@@ -1,14 +1,11 @@
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
export const components = {
- AccessibilityIssueBody: () =>
- import('../accessibility_report/components/accessibility_issue_body.vue'),
CodequalityIssueBody: () => import('../codequality_report/components/codequality_issue_body.vue'),
TestIssueBody: () => import('../grouped_test_report/components/test_issue_body.vue'),
};
export const componentNames = {
- AccessibilityIssueBody: 'AccessibilityIssueBody',
CodequalityIssueBody: 'CodequalityIssueBody',
TestIssueBody: 'TestIssueBody',
};
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index 6061be465ca..bb86695b9a3 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -1,7 +1,6 @@
<script>
import { GlButton } from '@gitlab/ui';
import api from '~/api';
-import { __ } from '~/locale';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -115,9 +114,6 @@ export default {
},
computed: {
- collapseText() {
- return this.isCollapsed ? __('Expand') : __('Collapse');
- },
isLoading() {
return this.status === status.LOADING;
},
@@ -172,6 +168,11 @@ export default {
},
methods: {
toggleCollapsed() {
+ // Because the top-level div is always clickable, we need to check if we can collapse.
+ if (!this.isCollapsible) {
+ return;
+ }
+
if (this.trackAction) {
api.trackRedisHllUserEvent(this.trackAction);
}
@@ -186,10 +187,13 @@ export default {
</script>
<template>
<section class="media-section">
- <div class="media">
+ <div class="media" :class="{ 'gl-cursor-pointer': isCollapsible }" @click="toggleCollapsed">
<status-icon :status="statusIconName" :size="24" class="align-self-center" />
- <div class="media-body d-flex flex-align-self-center align-items-center">
- <div data-testid="report-section-code-text" class="js-code-text code-text">
+ <div class="media-body gl-display-flex gl-align-items-flex-start gl-flex-direction-row!">
+ <div
+ data-testid="report-section-code-text"
+ class="js-code-text code-text gl-align-self-center gl-flex-grow-1"
+ >
<div class="gl-display-flex gl-align-items-center">
<p class="gl-line-height-normal gl-m-0">{{ headerText }}</p>
<slot :name="slotName"></slot>
@@ -204,14 +208,19 @@ export default {
<slot name="action-buttons" :is-collapsible="isCollapsible"></slot>
- <gl-button
+ <div
v-if="isCollapsible"
- data-testid="report-section-expand-button"
- data-qa-selector="expand_report_button"
- @click="toggleCollapsed"
+ class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3"
>
- {{ collapseText }}
- </gl-button>
+ <gl-button
+ data-testid="report-section-expand-button"
+ data-qa-selector="expand_report_button"
+ category="tertiary"
+ size="small"
+ :icon="isExpanded ? 'chevron-lg-up' : 'chevron-lg-down'"
+ @click.stop="toggleCollapsed"
+ />
+ </div>
</div>
</div>
diff --git a/app/assets/javascripts/repository/commits_service.js b/app/assets/javascripts/repository/commits_service.js
index 5fd9cfd4e53..f009c0310c5 100644
--- a/app/assets/javascripts/repository/commits_service.js
+++ b/app/assets/javascripts/repository/commits_service.js
@@ -1,7 +1,7 @@
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { normalizeData } from 'ee_else_ce/repository/utils/commit';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { COMMIT_BATCH_SIZE, I18N_COMMIT_DATA_FETCH_ERROR } from './constants';
let requestedOffsets = [];
@@ -43,7 +43,7 @@ const fetchData = (projectPath, path, ref, offset) => {
return axios
.get(url, { params: { format: 'json', offset } })
.then(({ data }) => normalizeData(data, path))
- .catch(() => createFlash({ message: I18N_COMMIT_DATA_FETCH_ERROR }));
+ .catch(() => createAlert({ message: I18N_COMMIT_DATA_FETCH_ERROR }));
};
export const loadCommits = async (projectPath, path, ref, offset) => {
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 902077ba3e4..bf1667d8734 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -4,7 +4,7 @@ import { uniqueId } from 'lodash';
import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import { SIMPLE_BLOB_VIEWER, RICH_BLOB_VIEWER } from '~/blob/components/constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
@@ -271,7 +271,7 @@ export default {
.catch(() => this.displayError());
},
displayError() {
- createFlash({ message: __('An error occurred while loading the file. Please try again.') });
+ createAlert({ message: __('An error occurred while loading the file. Please try again.') });
},
switchViewer(newViewer) {
this.activeViewerType = newViewer || SIMPLE_BLOB_VIEWER;
diff --git a/app/assets/javascripts/repository/components/blob_controls.vue b/app/assets/javascripts/repository/components/blob_controls.vue
index fb1227f0df9..29c2c3762fc 100644
--- a/app/assets/javascripts/repository/components/blob_controls.vue
+++ b/app/assets/javascripts/repository/components/blob_controls.vue
@@ -1,9 +1,11 @@
<script>
import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import getRefMixin from '~/repository/mixins/get_ref';
import initSourcegraph from '~/sourcegraph';
+import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';
+import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import { updateElementsVisibility } from '../utils/dom';
import blobControlsQuery from '../queries/blob_controls.query.graphql';
@@ -34,7 +36,7 @@ export default {
return !this.filePath;
},
error() {
- createFlash({ message: this.$options.i18n.errorMessage });
+ createAlert({ message: this.$options.i18n.errorMessage });
},
},
},
@@ -84,6 +86,33 @@ export default {
},
blobInfo() {
initSourcegraph();
+ this.$nextTick(() => {
+ this.initShortcuts();
+ this.initLinksUpdate();
+ });
+ },
+ },
+ methods: {
+ initShortcuts() {
+ const fileBlobPermalinkUrlElement = document.querySelector(
+ '.js-data-file-blob-permalink-url',
+ );
+ const fileBlobPermalinkUrl =
+ fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
+ // eslint-disable-next-line no-new
+ new ShortcutsBlob({
+ skipResetBindings: true,
+ fileBlobPermalinkUrl,
+ fileBlobPermalinkUrlElement,
+ });
+ },
+ initLinksUpdate() {
+ // eslint-disable-next-line no-new
+ new BlobLinePermalinkUpdater(
+ document.querySelector('.tree-holder'),
+ '.file-line-num[data-line-number], .file-line-num[data-line-number] *',
+ document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'),
+ );
},
},
};
@@ -99,6 +128,7 @@ export default {
data-testid="blame"
:href="blobInfo.blamePath"
:class="$options.buttonClassList"
+ class="js-blob-blame-link"
>
{{ $options.i18n.blame }}
</gl-button>
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 22fe3fe440e..05d64077866 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -122,14 +122,12 @@ export default {
:link-href="commit.author.webPath"
:img-src="commit.author.avatarUrl"
:img-size="32"
- :img-css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (7731 epics) */"
class="gl-my-2 gl-mr-4"
/>
<user-avatar-image
v-else
class="gl-my-2 gl-mr-4"
:img-src="commit.authorGravatar || $options.defaultAvatarUrl"
- :css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (7731 epics) */"
:size="32"
/>
<div
@@ -171,7 +169,7 @@ export default {
v-if="commitDescription"
v-safe-html:[$options.safeHtmlConfig]="commitDescription"
:class="{ 'd-block': showDescription }"
- class="commit-row-description gl-mb-3"
+ class="commit-row-description gl-mb-3 gl-white-space-pre-line"
></pre>
</div>
<div class="gl-flex-grow-1"></div>
diff --git a/app/assets/javascripts/repository/components/new_directory_modal.vue b/app/assets/javascripts/repository/components/new_directory_modal.vue
index 6c5797bf5b2..b28ebe7bb1e 100644
--- a/app/assets/javascripts/repository/components/new_directory_modal.vue
+++ b/app/assets/javascripts/repository/components/new_directory_modal.vue
@@ -8,7 +8,7 @@ import {
GlFormTextarea,
GlToggle,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -140,7 +140,7 @@ export default {
})
.catch(() => {
this.loading = false;
- createFlash({ message: ERROR_MESSAGE });
+ createAlert({ message: ERROR_MESSAGE });
});
},
},
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index c8cd64b5311..f3c5ace75fc 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -260,19 +260,19 @@ export default {
class="ml-1"
/>
</td>
- <td class="d-none d-sm-table-cell tree-commit cursor-default">
+ <td class="d-none d-sm-table-cell tree-commit cursor-default gl-text-secondary">
<gl-link
v-if="commitData"
v-safe-html:[$options.safeHtmlConfig]="commitData.titleHtml"
:href="commitData.commitPath"
:title="commitData.message"
- class="str-truncated-100 tree-commit-link"
+ class="str-truncated-100 tree-commit-link gl-text-secondary"
/>
<gl-intersection-observer @appear="rowAppeared" @disappear="rowDisappeared">
<gl-skeleton-loader v-if="showSkeletonLoader" :lines="1" />
</gl-intersection-observer>
</td>
- <td class="tree-time-ago text-right cursor-default">
+ <td class="tree-time-ago text-right cursor-default gl-text-secondary">
<timeago-tooltip v-if="commitData" :time="commitData.committedDate" />
<gl-skeleton-loader v-if="showSkeletonLoader" :lines="1" />
</td>
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 2200e999c75..8a45a351c35 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -1,6 +1,6 @@
<script>
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __ } from '~/locale';
import {
@@ -142,7 +142,7 @@ export default {
}
})
.catch((error) => {
- createFlash({
+ createAlert({
message: __('An error occurred while fetching folder content.'),
});
throw error;
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index 7fcaf772aac..4603ea2710d 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -9,7 +9,7 @@ import {
GlButton,
GlAlert,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { ContentTypeMultipartFormData } from '~/lib/utils/headers';
import { numberToHumanSize } from '~/lib/utils/number_utils';
@@ -171,7 +171,7 @@ export default {
})
.catch(() => {
this.loading = false;
- createFlash({ message: ERROR_MESSAGE });
+ createAlert({ message: ERROR_MESSAGE });
});
},
formData() {
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 f5620876783..dbaabb35cde 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -17,8 +17,6 @@ import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_cou
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerStackedLayoutBanner from '../components/runner_stacked_layout_banner.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
-import RunnerBulkDelete from '../components/runner_bulk_delete.vue';
-import RunnerBulkDeleteCheckbox from '../components/runner_bulk_delete_checkbox.vue';
import RunnerList from '../components/runner_list.vue';
import RunnerListEmptyState from '../components/runner_list_empty_state.vue';
import RunnerName from '../components/runner_name.vue';
@@ -30,7 +28,12 @@ import RunnerActionsCell from '../components/cells/runner_actions_cell.vue';
import { pausedTokenConfig } from '../components/search_tokens/paused_token_config';
import { statusTokenConfig } from '../components/search_tokens/status_token_config';
import { tagTokenConfig } from '../components/search_tokens/tag_token_config';
-import { ADMIN_FILTERED_SEARCH_NAMESPACE, INSTANCE_TYPE, I18N_FETCH_ERROR } from '../constants';
+import {
+ ADMIN_FILTERED_SEARCH_NAMESPACE,
+ INSTANCE_TYPE,
+ I18N_FETCH_ERROR,
+ FILTER_CSS_CLASSES,
+} from '../constants';
import { captureException } from '../sentry_utils';
export default {
@@ -40,8 +43,6 @@ export default {
RegistrationDropdown,
RunnerStackedLayoutBanner,
RunnerFilteredSearchBar,
- RunnerBulkDelete,
- RunnerBulkDeleteCheckbox,
RunnerList,
RunnerListEmptyState,
RunnerName,
@@ -51,7 +52,7 @@ export default {
RunnerActionsCell,
},
mixins: [glFeatureFlagMixin()],
- inject: ['emptyStateSvgPath', 'emptyStateFilteredSvgPath', 'localMutations'],
+ inject: ['emptyStateSvgPath', 'emptyStateFilteredSvgPath'],
props: {
registrationToken: {
type: String,
@@ -114,11 +115,6 @@ export default {
upgradeStatusTokenConfig,
];
},
- isBulkDeleteEnabled() {
- // Feature flag: admin_runners_bulk_delete
- // Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/353981
- return this.glFeatures.adminRunnersBulkDelete;
- },
isSearchFiltered() {
return isSearchFiltered(this.search);
},
@@ -155,18 +151,13 @@ export default {
reportToSentry(error) {
captureException({ error, component: this.$options.name });
},
- onChecked({ runner, isChecked }) {
- this.localMutations.setRunnerChecked({
- runner,
- isChecked,
- });
- },
onPaginationInput(value) {
this.search.pagination = value;
},
},
filteredSearchNamespace: ADMIN_FILTERED_SEARCH_NAMESPACE,
INSTANCE_TYPE,
+ FILTER_CSS_CLASSES,
};
</script>
<template>
@@ -195,6 +186,7 @@ export default {
<runner-filtered-search-bar
v-model="search"
+ :class="$options.FILTER_CSS_CLASSES"
:tokens="searchTokens"
:namespace="$options.filteredSearchNamespace"
/>
@@ -209,20 +201,12 @@ export default {
:filtered-svg-path="emptyStateFilteredSvgPath"
/>
<template v-else>
- <runner-bulk-delete
- v-if="isBulkDeleteEnabled"
- :runners="runners.items"
- @deleted="onDeleted"
- />
<runner-list
:runners="runners.items"
:loading="runnersLoading"
- :checkable="isBulkDeleteEnabled"
- @checked="onChecked"
+ :checkable="true"
+ @deleted="onDeleted"
>
- <template v-if="isBulkDeleteEnabled" #head-checkbox>
- <runner-bulk-delete-checkbox :runners="runners.items" />
- </template>
<template #runner-name="{ runner }">
<gl-link :href="runner.adminUrl">
<runner-name :runner="runner" />
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 7a4760f81ee..13f520c4edb 100644
--- a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
@@ -52,11 +52,6 @@ export default {
:compact="true"
@toggledPaused="onToggledPaused"
/>
- <runner-delete-button
- :disabled="!canDelete"
- :runner="runner"
- :compact="true"
- @deleted="onDeleted"
- />
+ <runner-delete-button v-if="canDelete" :runner="runner" :compact="true" @deleted="onDeleted" />
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_owner_cell.vue b/app/assets/javascripts/runner/components/cells/runner_owner_cell.vue
new file mode 100644
index 00000000000..cb43760b2d6
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/runner_owner_cell.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE, I18N_ADMIN } from '../../constants';
+
+export default {
+ components: {
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ cell() {
+ switch (this.runner?.runnerType) {
+ case INSTANCE_TYPE:
+ return {
+ text: I18N_ADMIN,
+ };
+ case GROUP_TYPE: {
+ const { name, fullName, webUrl } = this.runner?.groups?.nodes[0] || {};
+
+ return {
+ text: name,
+ href: webUrl,
+ tooltip: fullName !== name ? fullName : '',
+ };
+ }
+ case PROJECT_TYPE: {
+ const { name, nameWithNamespace, webUrl } = this.runner?.ownerProject || {};
+
+ return {
+ text: name,
+ href: webUrl,
+ tooltip: nameWithNamespace !== name ? nameWithNamespace : '',
+ };
+ }
+ default:
+ return {};
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-link
+ v-if="cell.href"
+ v-gl-tooltip="cell.tooltip"
+ :href="cell.href"
+ class="gl-text-body gl-text-decoration-underline"
+ >
+ {{ cell.text }}
+ </gl-link>
+ <span v-else>{{ cell.text }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue b/app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue
index dde5a5a4a05..75afb7a00bc 100644
--- a/app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue
+++ b/app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue
@@ -1,5 +1,6 @@
<script>
import { GlFormCheckbox } from '@gitlab/ui';
+import { s__ } from '~/locale';
import checkedRunnerIdsQuery from '../graphql/list/checked_runner_ids.query.graphql';
export default {
@@ -25,14 +26,20 @@ export default {
},
},
computed: {
+ deletableRunners() {
+ return this.runners.filter((runner) => runner.userPermissions?.deleteRunner);
+ },
disabled() {
- return !this.runners.length;
+ return !this.deletableRunners.length;
},
checked() {
- return Boolean(this.runners.length) && this.runners.every(this.isChecked);
+ return Boolean(this.deletableRunners.length) && this.deletableRunners.every(this.isChecked);
},
indeterminate() {
- return !this.checked && this.runners.some(this.isChecked);
+ return !this.checked && this.deletableRunners.some(this.isChecked);
+ },
+ label() {
+ return this.checked ? s__('Runners|Unselect all') : s__('Runners|Select all');
},
},
methods: {
@@ -41,7 +48,7 @@ export default {
},
onChange($event) {
this.localMutations.setRunnersChecked({
- runners: this.runners,
+ runners: this.deletableRunners,
isChecked: $event,
});
},
@@ -51,6 +58,7 @@ export default {
<template>
<gl-form-checkbox
+ :aria-label="label"
:indeterminate="indeterminate"
:checked="checked"
:disabled="disabled"
diff --git a/app/assets/javascripts/runner/components/runner_delete_button.vue b/app/assets/javascripts/runner/components/runner_delete_button.vue
index 62382891df0..b4f022a7d14 100644
--- a/app/assets/javascripts/runner/components/runner_delete_button.vue
+++ b/app/assets/javascripts/runner/components/runner_delete_button.vue
@@ -5,12 +5,7 @@ import { createAlert } from '~/flash';
import { sprintf } from '~/locale';
import { captureException } from '~/runner/sentry_utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import {
- I18N_DELETE_DISABLED_MANY_PROJECTS,
- I18N_DELETE_DISABLED_UNKNOWN_REASON,
- I18N_DELETE_RUNNER,
- I18N_DELETED_TOAST,
-} from '../constants';
+import { I18N_DELETE_RUNNER, I18N_DELETED_TOAST } from '../constants';
import RunnerDeleteModal from './runner_delete_modal.vue';
export default {
@@ -31,11 +26,6 @@ export default {
return runner?.id && runner?.shortSha;
},
},
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
compact: {
type: Boolean,
required: false,
@@ -85,29 +75,14 @@ export default {
return null;
},
tooltip() {
- if (this.disabled && this.runner.projectCount > 1) {
- return I18N_DELETE_DISABLED_MANY_PROJECTS;
- }
- if (this.disabled) {
- return I18N_DELETE_DISABLED_UNKNOWN_REASON;
- }
-
// Only show basic "delete" tooltip when compact.
// Also prevent a "sticky" tooltip: If this button is
- // disabled, mouseout listeners don't run leaving the tooltip stuck
+ // loading, mouseout listeners don't run leaving the tooltip stuck
if (this.compact && !this.deleting) {
return I18N_DELETE_RUNNER;
}
return '';
},
- wrapperTabindex() {
- if (this.disabled) {
- // Trigger tooltip on keyboard-focusable wrapper
- // See https://bootstrap-vue.org/docs/directives/tooltip
- return '0';
- }
- return null;
- },
},
methods: {
async onDelete() {
@@ -156,14 +131,13 @@ export default {
</script>
<template>
- <div v-gl-tooltip="tooltip" class="btn-group" :tabindex="wrapperTabindex">
+ <div v-gl-tooltip="tooltip" class="btn-group">
<gl-button
v-gl-modal="runnerDeleteModalId"
:aria-label="ariaLabel"
:icon="icon"
:class="buttonClass"
:loading="deleting"
- :disabled="disabled"
variant="danger"
category="secondary"
v-bind="$attrs"
diff --git a/app/assets/javascripts/runner/components/runner_details.vue b/app/assets/javascripts/runner/components/runner_details.vue
index 79f934764c6..3d72abcd393 100644
--- a/app/assets/javascripts/runner/components/runner_details.vue
+++ b/app/assets/javascripts/runner/components/runner_details.vue
@@ -4,7 +4,6 @@ import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import { ACCESS_LEVEL_REF_PROTECTED, GROUP_TYPE, PROJECT_TYPE } from '../constants';
import RunnerDetail from './runner_detail.vue';
@@ -29,7 +28,6 @@ export default {
RunnerTags,
TimeAgo,
},
- mixins: [glFeatureFlagMixin()],
props: {
runner: {
type: Object,
@@ -117,10 +115,7 @@ export default {
</template>
</runner-detail>
<runner-detail :label="s__('Runners|Maximum job timeout')" :value="maximumTimeout" />
- <runner-detail
- v-if="glFeatures.enforceRunnerTokenExpiresAt"
- :empty-value="s__('Runners|Never expires')"
- >
+ <runner-detail :empty-value="s__('Runners|Never expires')">
<template #label>
{{ s__('Runners|Token expiry') }}
<help-popover :options="tokenExpirationHelpPopoverOptions">
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 5a9ab21a457..da59de9a9eb 100644
--- a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -85,7 +85,6 @@ export default {
</script>
<template>
<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"
v-bind="$attrs"
:namespace="namespace"
recent-searches-storage-key="runners-search"
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index 26f1f3ce08c..e895537dcdc 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -2,15 +2,20 @@
import { GlFormCheckbox, GlTableLite, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { s__ } from '~/locale';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
import checkedRunnerIdsQuery from '../graphql/list/checked_runner_ids.query.graphql';
import { formatJobCount, tableField } from '../utils';
+import RunnerBulkDelete from './runner_bulk_delete.vue';
+import RunnerBulkDeleteCheckbox from './runner_bulk_delete_checkbox.vue';
import RunnerStackedSummaryCell from './cells/runner_stacked_summary_cell.vue';
import RunnerStatusPopover from './runner_status_popover.vue';
import RunnerStatusCell from './cells/runner_status_cell.vue';
+import RunnerOwnerCell from './cells/runner_owner_cell.vue';
const defaultFields = [
tableField({ key: 'status', label: s__('Runners|Status'), thClasses: ['gl-w-15p'] }),
tableField({ key: 'summary', label: s__('Runners|Runner') }),
+ tableField({ key: 'owner', label: s__('Runners|Owner'), thClasses: ['gl-w-20p'] }),
tableField({ key: 'actions', label: '', thClasses: ['gl-w-15p'] }),
];
@@ -19,9 +24,13 @@ export default {
GlFormCheckbox,
GlTableLite,
GlSkeletonLoader,
+ HelpPopover,
+ RunnerBulkDelete,
+ RunnerBulkDeleteCheckbox,
RunnerStatusPopover,
RunnerStackedSummaryCell,
RunnerStatusCell,
+ RunnerOwnerCell,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -34,6 +43,7 @@ export default {
},
},
},
+ inject: ['localMutations'],
props: {
checkable: {
type: Boolean,
@@ -50,7 +60,7 @@ export default {
required: true,
},
},
- emits: ['checked'],
+ emits: ['deleted'],
data() {
return { checkedRunnerIds: [] };
},
@@ -79,6 +89,12 @@ export default {
},
},
methods: {
+ canDelete(runner) {
+ return runner.userPermissions?.deleteRunner;
+ },
+ onDeleted(event) {
+ this.$emit('deleted', event);
+ },
formatJobCount(jobCount) {
return formatJobCount(jobCount);
},
@@ -91,7 +107,7 @@ export default {
return {};
},
onCheckboxChange(runner, isChecked) {
- this.$emit('checked', {
+ this.localMutations.setRunnerChecked({
runner,
isChecked,
});
@@ -104,6 +120,7 @@ export default {
</script>
<template>
<div>
+ <runner-bulk-delete v-if="checkable" :runners="runners" @deleted="onDeleted" />
<gl-table-lite
:aria-busy="loading"
:class="tableClass"
@@ -116,11 +133,15 @@ export default {
fixed
>
<template #head(checkbox)>
- <slot name="head-checkbox"></slot>
+ <runner-bulk-delete-checkbox :runners="runners" />
</template>
<template #cell(checkbox)="{ item }">
- <gl-form-checkbox :checked="isChecked(item)" @change="onCheckboxChange(item, $event)" />
+ <gl-form-checkbox
+ v-if="canDelete(item)"
+ :checked="isChecked(item)"
+ @change="onCheckboxChange(item, $event)"
+ />
</template>
<template #head(status)="{ label }">
@@ -140,6 +161,21 @@ export default {
</runner-stacked-summary-cell>
</template>
+ <template #head(owner)="{ label }">
+ {{ label }}
+ <help-popover>
+ {{
+ s__(
+ 'Runners|The project, group or instance where the runner was registered. Instance runners are always owned by Administrator.',
+ )
+ }}
+ </help-popover>
+ </template>
+
+ <template #cell(owner)="{ item }">
+ <runner-owner-cell :runner="item" />
+ </template>
+
<template #cell(actions)="{ item }">
<slot name="runner-actions-cell" :runner="item"></slot>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_list_empty_state.vue b/app/assets/javascripts/runner/components/runner_list_empty_state.vue
index ab9cde6a401..e6576c83e69 100644
--- a/app/assets/javascripts/runner/components/runner_list_empty_state.vue
+++ b/app/assets/javascripts/runner/components/runner_list_empty_state.vue
@@ -53,7 +53,7 @@ export default {
:svg-path="svgPath"
:svg-height="$options.svgHeight"
>
- <template #description>
+ <template v-if="registrationToken" #description>
<gl-sprintf
:message="
s__(
@@ -71,5 +71,12 @@ export default {
:registration-token="registrationToken"
/>
</template>
+ <template v-else #description>
+ {{
+ s__(
+ 'Runners|Runners are the agents that run your CI/CD jobs. To register new runners, please contact your administrator.',
+ )
+ }}
+ </template>
</gl-empty-state>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_membership_toggle.vue b/app/assets/javascripts/runner/components/runner_membership_toggle.vue
new file mode 100644
index 00000000000..2b37b1cc797
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_membership_toggle.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlToggle } from '@gitlab/ui';
+import {
+ I18N_SHOW_ONLY_INHERITED,
+ MEMBERSHIP_DESCENDANTS,
+ MEMBERSHIP_ALL_AVAILABLE,
+} from '../constants';
+
+export default {
+ components: {
+ GlToggle,
+ },
+ props: {
+ value: {
+ type: String,
+ default: MEMBERSHIP_DESCENDANTS,
+ required: false,
+ },
+ },
+ computed: {
+ toggle() {
+ return this.value === MEMBERSHIP_DESCENDANTS;
+ },
+ },
+ methods: {
+ onChange(value) {
+ this.$emit('input', value ? MEMBERSHIP_DESCENDANTS : MEMBERSHIP_ALL_AVAILABLE);
+ },
+ },
+ I18N_SHOW_ONLY_INHERITED,
+};
+</script>
+
+<template>
+ <gl-toggle
+ data-testid="runner-membership-toggle"
+ :value="toggle"
+ :label="$options.I18N_SHOW_ONLY_INHERITED"
+ label-position="left"
+ @change="onChange"
+ />
+</template>
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 59230bb809e..6e7c41885f8 100644
--- a/app/assets/javascripts/runner/components/search_tokens/tag_token.vue
+++ b/app/assets/javascripts/runner/components/search_tokens/tag_token.vue
@@ -7,6 +7,12 @@ import { s__ } from '~/locale';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { RUNNER_TAG_BG_CLASS } from '../../constants';
+// TODO This should be implemented via a GraphQL API
+// The API should
+// 1) scope to the rights of the user
+// 2) stay up to date to the removal of old tags
+// 3) consider the scope of search, like searching within the tags of a group
+// See: https://gitlab.com/gitlab-org/gitlab/-/issues/333796
export const TAG_SUGGESTIONS_PATH = '/admin/runners/tag_list.json';
export default {
@@ -29,12 +35,6 @@ export default {
},
methods: {
getTagsOptions(search) {
- // TODO This should be implemented via a GraphQL API
- // The API should
- // 1) scope to the rights of the user
- // 2) stay up to date to the removal of old tags
- // 3) consider the scope of search, like searching within the tags of a group
- // See: https://gitlab.com/gitlab-org/gitlab/-/issues/333796
return axios
.get(TAG_SUGGESTIONS_PATH, {
params: {
@@ -46,6 +46,12 @@ export default {
});
},
async fetchTags(searchTerm) {
+ // Note: Suggestions should only be enabled for admin users
+ if (this.config.suggestionsDisabled) {
+ this.tags = [];
+ return;
+ }
+
this.loading = true;
try {
this.tags = await this.getTagsOptions(searchTerm);
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index 3009577599f..dfc5f0c4152 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -11,6 +11,9 @@ export const RUNNER_DETAILS_JOBS_PAGE_SIZE = 30;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
+export const FILTER_CSS_CLASSES =
+ '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';
+
// Type
export const I18N_ALL_TYPES = s__('Runners|All');
@@ -76,12 +79,6 @@ export const I18N_RESUME = __('Resume');
export const I18N_RESUME_TOOLTIP = s__('Runners|Resume accepting jobs');
export const I18N_DELETE_RUNNER = s__('Runners|Delete runner');
-export const I18N_DELETE_DISABLED_MANY_PROJECTS = s__(
- 'Runners|Multi-project runners cannot be deleted',
-);
-export const I18N_DELETE_DISABLED_UNKNOWN_REASON = s__(
- 'Runners|Runner cannot be deleted, please contact your administrator',
-);
export const I18N_DELETED_TOAST = s__('Runners|Runner %{name} was deleted');
// List
@@ -91,6 +88,8 @@ export const I18N_LOCKED_RUNNER_DESCRIPTION = s__(
export const I18N_VERSION_LABEL = s__('Runners|Version %{version}');
export const I18N_LAST_CONTACT_LABEL = s__('Runners|Last contact: %{timeAgo}');
export const I18N_CREATED_AT_LABEL = s__('Runners|Created %{timeAgo}');
+export const I18N_SHOW_ONLY_INHERITED = s__('Runners|Show only inherited');
+export const I18N_ADMIN = s__('Runners|Administrator');
// Runner details
@@ -116,6 +115,7 @@ export const PARAM_KEY_PAUSED = 'paused';
export const PARAM_KEY_RUNNER_TYPE = 'runner_type';
export const PARAM_KEY_TAG = 'tag';
export const PARAM_KEY_SEARCH = 'search';
+export const PARAM_KEY_MEMBERSHIP = 'membership';
export const PARAM_KEY_SORT = 'sort';
export const PARAM_KEY_AFTER = 'after';
@@ -148,6 +148,13 @@ export const CONTACTED_ASC = 'CONTACTED_ASC';
export const DEFAULT_SORT = CREATED_DESC;
+// CiRunnerMembershipFilter
+
+export const MEMBERSHIP_DESCENDANTS = 'DESCENDANTS';
+export const MEMBERSHIP_ALL_AVAILABLE = 'ALL_AVAILABLE';
+
+export const DEFAULT_MEMBERSHIP = MEMBERSHIP_DESCENDANTS;
+
// Local storage namespaces
export const ADMIN_FILTERED_SEARCH_NAMESPACE = 'admin_runners';
diff --git a/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql b/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql
index 4c519b9b867..95f9dd1beb9 100644
--- a/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql
@@ -2,6 +2,7 @@
query getGroupRunners(
$groupFullPath: ID!
+ $membership: CiRunnerMembershipFilter
$before: String
$after: String
$first: Int
@@ -9,13 +10,14 @@ query getGroupRunners(
$paused: Boolean
$status: CiRunnerStatus
$type: CiRunnerType
+ $tagList: [String!]
$search: String
$sort: CiRunnerSort
) {
group(fullPath: $groupFullPath) {
id # Apollo required
runners(
- membership: DESCENDANTS
+ membership: $membership
before: $before
after: $after
first: $first
@@ -23,6 +25,7 @@ query getGroupRunners(
paused: $paused
status: $status
type: $type
+ tagList: $tagList
search: $search
sort: $sort
) {
diff --git a/app/assets/javascripts/runner/graphql/list/group_runners_count.query.graphql b/app/assets/javascripts/runner/graphql/list/group_runners_count.query.graphql
index 958b4ea0dd3..e88a2c2e7e6 100644
--- a/app/assets/javascripts/runner/graphql/list/group_runners_count.query.graphql
+++ b/app/assets/javascripts/runner/graphql/list/group_runners_count.query.graphql
@@ -1,5 +1,6 @@
query getGroupRunnersCount(
$groupFullPath: ID!
+ $membership: CiRunnerMembershipFilter
$paused: Boolean
$status: CiRunnerStatus
$type: CiRunnerType
@@ -9,7 +10,7 @@ query getGroupRunnersCount(
group(fullPath: $groupFullPath) {
id # Apollo required
runners(
- membership: DESCENDANTS
+ membership: $membership
paused: $paused
status: $status
type: $type
diff --git a/app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql b/app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql
index a12ba7a751a..0dff011daaa 100644
--- a/app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql
@@ -16,4 +16,18 @@ fragment ListItemShared on CiRunner {
updateRunner
deleteRunner
}
+ groups(first: 1) {
+ nodes {
+ id
+ name
+ fullName
+ webUrl
+ }
+ }
+ ownerProject {
+ id
+ name
+ nameWithNamespace
+ webUrl
+ }
}
diff --git a/app/assets/javascripts/runner/graphql/list/local_state.js b/app/assets/javascripts/runner/graphql/list/local_state.js
index 154af261bba..e0477c660b4 100644
--- a/app/assets/javascripts/runner/graphql/list/local_state.js
+++ b/app/assets/javascripts/runner/graphql/list/local_state.js
@@ -20,10 +20,6 @@ import typeDefs from './typedefs.graphql';
* localMutations.setRunnerChecked( ... )
* ```
*
- * Note: Currently only in use behind a feature flag:
- * admin_runners_bulk_delete for the admin list, rollout issue:
- * https://gitlab.com/gitlab-org/gitlab/-/issues/353981
- *
* @returns {Object} An object to configure an Apollo client:
* contains cacheConfig, typeDefs, localMutations.
*/
@@ -52,16 +48,18 @@ export const createLocalState = () => {
const localMutations = {
setRunnerChecked({ runner, isChecked }) {
- checkedRunnerIdsVar({
- ...checkedRunnerIdsVar(),
- [runner.id]: isChecked,
- });
+ const { id, userPermissions } = runner;
+ if (userPermissions?.deleteRunner) {
+ checkedRunnerIdsVar({
+ ...checkedRunnerIdsVar(),
+ [id]: isChecked,
+ });
+ }
},
setRunnersChecked({ runners, isChecked }) {
- const newVal = runners.reduce(
- (acc, { id }) => ({ ...acc, [id]: isChecked }),
- checkedRunnerIdsVar(),
- );
+ const newVal = runners
+ .filter(({ userPermissions }) => userPermissions?.deleteRunner)
+ .reduce((acc, { id }) => ({ ...acc, [id]: isChecked }), checkedRunnerIdsVar());
checkedRunnerIdsVar(newVal);
},
clearChecked() {
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 70826a6bfa1..7f56d895682 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -10,7 +10,9 @@ import {
fromSearchToVariables,
isSearchFiltered,
} from 'ee_else_ce/runner/runner_search_utils';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import groupRunnersQuery from 'ee_else_ce/runner/graphql/list/group_runners.query.graphql';
+import groupRunnersCountQuery from 'ee_else_ce/runner/graphql/list/group_runners_count.query.graphql';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerStackedLayoutBanner from '../components/runner_stacked_layout_banner.vue';
@@ -22,14 +24,17 @@ import RunnerStats from '../components/stat/runner_stats.vue';
import RunnerPagination from '../components/runner_pagination.vue';
import RunnerTypeTabs from '../components/runner_type_tabs.vue';
import RunnerActionsCell from '../components/cells/runner_actions_cell.vue';
+import RunnerMembershipToggle from '../components/runner_membership_toggle.vue';
import { pausedTokenConfig } from '../components/search_tokens/paused_token_config';
import { statusTokenConfig } from '../components/search_tokens/status_token_config';
+import { tagTokenConfig } from '../components/search_tokens/tag_token_config';
import {
GROUP_FILTERED_SEARCH_NAMESPACE,
GROUP_TYPE,
PROJECT_TYPE,
I18N_FETCH_ERROR,
+ FILTER_CSS_CLASSES,
} from '../constants';
import { captureException } from '../sentry_utils';
@@ -43,11 +48,13 @@ export default {
RunnerList,
RunnerListEmptyState,
RunnerName,
+ RunnerMembershipToggle,
RunnerStats,
RunnerPagination,
RunnerTypeTabs,
RunnerActionsCell,
},
+ mixins: [glFeatureFlagMixin()],
inject: ['emptyStateSvgPath', 'emptyStateFilteredSvgPath'],
props: {
registrationToken: {
@@ -126,12 +133,20 @@ export default {
noRunnersFound() {
return !this.runnersLoading && !this.runners.items.length;
},
- searchTokens() {
- return [pausedTokenConfig, statusTokenConfig, upgradeStatusTokenConfig];
- },
filteredSearchNamespace() {
return `${GROUP_FILTERED_SEARCH_NAMESPACE}/${this.groupFullPath}`;
},
+ searchTokens() {
+ return [
+ pausedTokenConfig,
+ statusTokenConfig,
+ {
+ ...tagTokenConfig,
+ suggestionsDisabled: true,
+ },
+ upgradeStatusTokenConfig,
+ ];
+ },
isSearchFiltered() {
return isSearchFiltered(this.search);
},
@@ -159,13 +174,17 @@ export default {
editUrl(runner) {
return this.runners.urlsById[runner.id]?.edit;
},
+ refetchCounts() {
+ this.$apollo.getClient().refetchQueries({ include: [groupRunnersCountQuery] });
+ },
onToggledPaused() {
// When a runner becomes Paused, the tab count can
// become stale, refetch outdated counts.
- this.$refs['runner-type-tabs'].refetch();
+ this.refetchCounts();
},
onDeleted({ message }) {
this.$root.$toast?.show(message);
+ this.refetchCounts();
},
reportToSentry(error) {
captureException({ error, component: this.$options.name });
@@ -176,6 +195,7 @@ export default {
},
TABS_RUNNER_TYPES: [GROUP_TYPE, PROJECT_TYPE],
GROUP_TYPE,
+ FILTER_CSS_CLASSES,
};
</script>
@@ -204,11 +224,21 @@ export default {
/>
</div>
- <runner-filtered-search-bar
- v-model="search"
- :tokens="searchTokens"
- :namespace="filteredSearchNamespace"
- />
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-gap-3"
+ :class="$options.FILTER_CSS_CLASSES"
+ >
+ <runner-filtered-search-bar
+ v-model="search"
+ :tokens="searchTokens"
+ :namespace="filteredSearchNamespace"
+ class="gl-flex-grow-1 gl-align-self-stretch"
+ />
+ <runner-membership-toggle
+ v-model="search.membership"
+ class="gl-align-self-end gl-md-align-self-center"
+ />
+ </div>
<runner-stats :scope="$options.GROUP_TYPE" :variables="countVariables" />
@@ -220,7 +250,7 @@ export default {
:filtered-svg-path="emptyStateFilteredSvgPath"
/>
<template v-else>
- <runner-list :runners="runners.items" :loading="runnersLoading">
+ <runner-list :runners="runners.items" :loading="runnersLoading" @deleted="onDeleted">
<template #runner-name="{ runner }">
<gl-link :href="webUrl(runner)">
<runner-name :runner="runner" />
diff --git a/app/assets/javascripts/runner/group_runners/index.js b/app/assets/javascripts/runner/group_runners/index.js
index feed6b0ceb7..0e7efd2b8a1 100644
--- a/app/assets/javascripts/runner/group_runners/index.js
+++ b/app/assets/javascripts/runner/group_runners/index.js
@@ -2,6 +2,7 @@ import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import { createLocalState } from '../graphql/list/local_state';
import GroupRunnersApp from './group_runners_app.vue';
Vue.use(GlToast);
@@ -26,8 +27,10 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
emptyStateFilteredSvgPath,
} = el.dataset;
+ const { cacheConfig, typeDefs, localMutations } = createLocalState();
+
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ defaultClient: createDefaultClient({}, { cacheConfig, typeDefs }),
});
return new Vue({
@@ -35,6 +38,7 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
apolloProvider,
provide: {
runnerInstallHelpPage,
+ localMutations,
groupId,
onlineContactTimeoutSecs: parseInt(onlineContactTimeoutSecs, 10),
staleTimeoutSecs: parseInt(staleTimeoutSecs, 10),
diff --git a/app/assets/javascripts/runner/runner_search_utils.js b/app/assets/javascripts/runner/runner_search_utils.js
index dc582ccbac1..adc832b0600 100644
--- a/app/assets/javascripts/runner/runner_search_utils.js
+++ b/app/assets/javascripts/runner/runner_search_utils.js
@@ -13,10 +13,12 @@ import {
PARAM_KEY_RUNNER_TYPE,
PARAM_KEY_TAG,
PARAM_KEY_SEARCH,
+ PARAM_KEY_MEMBERSHIP,
PARAM_KEY_SORT,
PARAM_KEY_AFTER,
PARAM_KEY_BEFORE,
DEFAULT_SORT,
+ DEFAULT_MEMBERSHIP,
RUNNER_PAGE_SIZE,
} from './constants';
import { getPaginationVariables } from './utils';
@@ -57,9 +59,10 @@ import { getPaginationVariables } from './utils';
* @param {Object} search
* @returns {boolean} True if the value follows the search format.
*/
-export const searchValidator = ({ runnerType, filters, sort }) => {
+export const searchValidator = ({ runnerType, membership, filters, sort }) => {
return (
(runnerType === null || typeof runnerType === 'string') &&
+ (membership === null || typeof membership === 'string') &&
Array.isArray(filters) &&
typeof sort === 'string'
);
@@ -140,9 +143,11 @@ export const updateOutdatedUrl = (url = window.location.href) => {
export const fromUrlQueryToSearch = (query = window.location.search) => {
const params = queryToObject(query, { gatherArrays: true });
const runnerType = params[PARAM_KEY_RUNNER_TYPE]?.[0] || null;
+ const membership = params[PARAM_KEY_MEMBERSHIP]?.[0] || null;
return {
runnerType,
+ membership: membership || DEFAULT_MEMBERSHIP,
filters: prepareTokens(
urlQueryToFilter(query, {
filterNamesAllowList: [PARAM_KEY_PAUSED, PARAM_KEY_STATUS, PARAM_KEY_TAG],
@@ -162,13 +167,14 @@ export const fromUrlQueryToSearch = (query = window.location.search) => {
* @returns {String} New URL for the page
*/
export const fromSearchToUrl = (
- { runnerType = null, filters = [], sort = null, pagination = {} },
+ { runnerType = null, membership = null, filters = [], sort = null, pagination = {} },
url = window.location.href,
) => {
const filterParams = {
// Defaults
[PARAM_KEY_STATUS]: [],
[PARAM_KEY_RUNNER_TYPE]: [],
+ [PARAM_KEY_MEMBERSHIP]: [],
[PARAM_KEY_TAG]: [],
// Current filters
...filterToQueryObject(processFilters(filters), {
@@ -180,6 +186,10 @@ export const fromSearchToUrl = (
filterParams[PARAM_KEY_RUNNER_TYPE] = [runnerType];
}
+ if (membership && membership !== DEFAULT_MEMBERSHIP) {
+ filterParams[PARAM_KEY_MEMBERSHIP] = [membership];
+ }
+
if (!filterParams[PARAM_KEY_SEARCH]) {
filterParams[PARAM_KEY_SEARCH] = null;
}
@@ -203,6 +213,7 @@ export const fromSearchToUrl = (
*/
export const fromSearchToVariables = ({
runnerType = null,
+ membership = null,
filters = [],
sort = null,
pagination = {},
@@ -226,6 +237,9 @@ export const fromSearchToVariables = ({
if (runnerType) {
filterVariables.type = runnerType;
}
+ if (membership) {
+ filterVariables.membership = membership;
+ }
if (sort) {
filterVariables.sort = sort;
}
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 446ab7f433c..ba12f31ef87 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,7 +1,7 @@
import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import { queryToObject } from '~/lib/utils/url_utility';
import refreshCounts from '~/pages/search/show/refresh_counts';
-import { initSidebar } from './sidebar';
+import { initSidebar, sidebarInitState } from './sidebar';
import { initSearchSort } from './sort';
import createStore from './store';
import { initTopbar } from './topbar';
@@ -9,14 +9,18 @@ import { initBlobRefSwitcher } from './under_topbar';
export const initSearchApp = () => {
const query = queryToObject(window.location.search);
+ const navigation = sidebarInitState();
- const store = createStore({ query });
+ const store = createStore({ query, navigation });
initTopbar(store);
initSidebar(store);
initSearchSort(store);
setHighlightClass(query.search); // Code Highlighting
- refreshCounts(); // Other Scope Tab Counts
initBlobRefSwitcher(); // Code Search Branch Picker
+
+ if (!gon.features?.searchPageVerticalNav) {
+ refreshCounts(); // Other Scope Tab Counts
+ }
};
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index 5c7cbeac5b2..789efc8f09d 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -17,6 +17,9 @@ export default {
showReset() {
return this.urlQuery.state || this.urlQuery.confidential;
},
+ showSidebar() {
+ return this.urlQuery.scope === 'issues' || this.urlQuery.scope === 'merge_requests';
+ },
},
methods: {
...mapActions(['applyQuery', 'resetQuery']),
@@ -29,15 +32,17 @@ export default {
class="search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4 gl-mb-6 gl-mt-5"
@submit.prevent="applyQuery"
>
- <status-filter />
- <confidentiality-filter />
- <div class="gl-display-flex gl-align-items-center gl-mt-3">
- <gl-button category="primary" variant="confirm" type="submit" :disabled="!sidebarDirty">
- {{ __('Apply') }}
- </gl-button>
- <gl-link v-if="showReset" class="gl-ml-auto" @click="resetQuery">{{
- __('Reset filters')
- }}</gl-link>
- </div>
+ <template v-if="showSidebar">
+ <status-filter />
+ <confidentiality-filter />
+ <div class="gl-display-flex gl-align-items-center gl-mt-3">
+ <gl-button category="primary" variant="confirm" type="submit" :disabled="!sidebarDirty">
+ {{ __('Apply') }}
+ </gl-button>
+ <gl-link v-if="showReset" class="gl-ml-auto" @click="resetQuery">{{
+ __('Reset filters')
+ }}</gl-link>
+ </div>
+ </template>
</form>
</template>
diff --git a/app/assets/javascripts/search/sidebar/index.js b/app/assets/javascripts/search/sidebar/index.js
index 1414adcac27..c6b1257c4ef 100644
--- a/app/assets/javascripts/search/sidebar/index.js
+++ b/app/assets/javascripts/search/sidebar/index.js
@@ -4,6 +4,15 @@ import GlobalSearchSidebar from './components/app.vue';
Vue.use(Translate);
+export const sidebarInitState = () => {
+ const el = document.getElementById('js-search-sidebar');
+
+ if (!el) return {};
+
+ const { navigation } = el.dataset;
+ return JSON.parse(navigation);
+};
+
export const initSidebar = (store) => {
const el = document.getElementById('js-search-sidebar');
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index dc8b6201953..be5742e5949 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY, SIDEBAR_PARAMS } from './constants';
@@ -13,7 +13,7 @@ export const fetchGroups = ({ commit }, search) => {
commit(types.RECEIVE_GROUPS_SUCCESS, data);
})
.catch(() => {
- createFlash({ message: __('There was a problem fetching groups.') });
+ createAlert({ message: __('There was a problem fetching groups.') });
commit(types.RECEIVE_GROUPS_ERROR);
});
};
@@ -23,7 +23,7 @@ export const fetchProjects = ({ commit, state }, search) => {
const groupId = state.query?.group_id;
const handleCatch = () => {
- createFlash({ message: __('There was an error fetching projects') });
+ createAlert({ message: __('There was an error fetching projects') });
commit(types.RECEIVE_PROJECTS_ERROR);
};
const handleSuccess = ({ data }) => {
@@ -59,7 +59,7 @@ export const loadFrequentGroups = async ({ commit, state }) => {
const inflatedData = mergeById(await Promise.all(promises), storedData);
commit(types.LOAD_FREQUENT_ITEMS, { key: GROUPS_LOCAL_STORAGE_KEY, data: inflatedData });
} catch {
- createFlash({ message: __('There was a problem fetching recent groups.') });
+ createAlert({ message: __('There was a problem fetching recent groups.') });
}
};
@@ -70,7 +70,7 @@ export const loadFrequentProjects = async ({ commit, state }) => {
const inflatedData = mergeById(await Promise.all(promises), storedData);
commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data: inflatedData });
} catch {
- createFlash({ message: __('There was a problem fetching recent projects.') });
+ createAlert({ message: __('There was a problem fetching recent projects.') });
}
};
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
index f27dae8249d..d0fcbb0d83b 100644
--- a/app/assets/javascripts/search/topbar/components/app.vue
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -1,7 +1,9 @@
<script>
import { GlSearchBoxByClick } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale';
+import { parseBoolean } from '~/lib/utils/common_utils';
import GroupFilter from './group_filter.vue';
import ProjectFilter from './project_filter.vue';
@@ -16,6 +18,7 @@ export default {
GroupFilter,
ProjectFilter,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
groupInitialData: {
type: Object,
@@ -39,7 +42,10 @@ export default {
},
},
showFilters() {
- return !this.query.snippets || this.query.snippets === 'false';
+ return !parseBoolean(this.query.snippets);
+ },
+ hasVerticalNav() {
+ return this.glFeatures.searchPageVerticalNav;
},
},
created() {
@@ -52,24 +58,27 @@ export default {
</script>
<template>
- <section class="search-page-form gl-lg-display-flex gl-align-items-flex-end">
- <div class="gl-flex-grow-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
- <label>{{ $options.i18n.searchLabel }}</label>
- <gl-search-box-by-click
- id="dashboard_search"
- v-model="search"
- name="search"
- :placeholder="$options.i18n.searchPlaceholder"
- @submit="applyQuery"
- />
- </div>
- <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
- <label class="gl-display-block">{{ __('Group') }}</label>
- <group-filter :initial-data="groupInitialData" />
- </div>
- <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
- <label class="gl-display-block">{{ __('Project') }}</label>
- <project-filter :initial-data="projectInitialData" />
+ <section class="search-page-form gl-lg-display-flex gl-flex-direction-column">
+ <div class="gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-end">
+ <div class="gl-flex-grow-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
+ <label>{{ $options.i18n.searchLabel }}</label>
+ <gl-search-box-by-click
+ id="dashboard_search"
+ v-model="search"
+ name="search"
+ :placeholder="$options.i18n.searchPlaceholder"
+ @submit="applyQuery"
+ />
+ </div>
+ <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
+ <label class="gl-display-block">{{ __('Group') }}</label>
+ <group-filter :initial-data="groupInitialData" />
+ </div>
+ <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
+ <label class="gl-display-block">{{ __('Project') }}</label>
+ <project-filter :initial-data="projectInitialData" />
+ </div>
</div>
+ <hr v-if="hasVerticalNav" class="gl-mt-5 gl-mb-0 gl-border-gray-100" />
</section>
</template>
diff --git a/app/assets/javascripts/search_settings/components/search_settings.vue b/app/assets/javascripts/search_settings/components/search_settings.vue
index e9cc9616fd0..3fc279f363a 100644
--- a/app/assets/javascripts/search_settings/components/search_settings.vue
+++ b/app/assets/javascripts/search_settings/components/search_settings.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSearchBoxByType } from '@gitlab/ui';
+import { GlEmptyState, GlSearchBoxByType } from '@gitlab/ui';
import { escapeRegExp } from 'lodash';
import {
EXCLUDED_NODES,
@@ -96,6 +96,8 @@ const displayResults = ({ sectionSelector, expandSection, searchTerm }, matching
hideSectionsExcept(sectionSelector, sections);
sections.forEach(expandSection);
highlightText(matchingTextNodes, searchTerm);
+
+ return sections.length > 0;
};
const clearResults = (params) => {
@@ -126,6 +128,7 @@ const search = (root, searchTerm) => {
export default {
components: {
+ GlEmptyState,
GlSearchBoxByType,
},
props: {
@@ -137,6 +140,11 @@ export default {
type: String,
required: true,
},
+ hideWhenEmptySelector: {
+ type: String,
+ required: true,
+ default: null,
+ },
isExpandedFn: {
type: Function,
required: false,
@@ -147,8 +155,16 @@ export default {
data() {
return {
searchTerm: '',
+ hasMatches: true,
};
},
+ watch: {
+ hasMatches(newHasMatches) {
+ document.querySelectorAll(this.hideWhenEmptySelector).forEach((section) => {
+ section.classList.toggle(HIDE_CLASS, !newHasMatches);
+ });
+ },
+ },
methods: {
search(value) {
this.searchTerm = value;
@@ -161,11 +177,12 @@ export default {
};
clearResults(displayOptions);
+ this.hasMatches = true;
if (value.length) {
saveExpansionState(document.querySelectorAll(this.sectionSelector), displayOptions);
- displayResults(displayOptions, search(this.searchRoot, this.searchTerm));
+ this.hasMatches = displayResults(displayOptions, search(this.searchRoot, this.searchTerm));
} else {
restoreExpansionState(displayOptions);
}
@@ -181,10 +198,18 @@ export default {
};
</script>
<template>
- <gl-search-box-by-type
- :value="searchTerm"
- :debounce="$options.TYPING_DELAY"
- :placeholder="__('Search page')"
- @input="search"
- />
+ <div>
+ <gl-search-box-by-type
+ :value="searchTerm"
+ :debounce="$options.TYPING_DELAY"
+ :placeholder="__('Search page')"
+ @input="search"
+ />
+
+ <gl-empty-state
+ v-if="!hasMatches"
+ :title="__('No results found')"
+ :description="__('Edit your search and try again')"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/search_settings/mount.js b/app/assets/javascripts/search_settings/mount.js
index b1086f9ca1f..b727b55781a 100644
--- a/app/assets/javascripts/search_settings/mount.js
+++ b/app/assets/javascripts/search_settings/mount.js
@@ -11,6 +11,7 @@ const mountSearch = ({ el }) =>
props: {
searchRoot: document.querySelector('#content-body'),
sectionSelector: '.js-search-settings-section, section.settings',
+ hideWhenEmptySelector: '.js-hide-when-nothing-matches-search',
isExpandedFn: isExpanded,
},
on: {
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index ecde9235e93..7828efc358a 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -21,7 +21,9 @@ export const i18n = {
),
description: s__(
`SecurityConfiguration|Once you've enabled a scan for the default branch,
- any subsequent feature branch you create will include the scan.`,
+ any subsequent feature branch you create will include the scan. An enabled
+ scanner will not be reflected as such until the pipeline has been
+ successfully executed and it has generated valid artifacts.`,
),
securityConfiguration: __('Security Configuration'),
vulnerabilityManagement: s__('SecurityConfiguration|Vulnerability Management'),
@@ -165,7 +167,12 @@ export default {
</template>
</user-callout-dismisser>
- <gl-tabs content-class="gl-pt-0" sync-active-tab-with-query-params lazy>
+ <gl-tabs
+ content-class="gl-pt-0"
+ data-qa-selector="security_configuration_container"
+ sync-active-tab-with-query-params
+ lazy
+ >
<gl-tab
data-testid="security-testing-tab"
:title="$options.i18n.securityTesting"
diff --git a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
index 891d7bf2eb0..eaff1ce6055 100644
--- a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
+++ b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
@@ -22,7 +22,7 @@ export default {
s__('SecurityConfiguration|High-level vulnerability statistics across projects and groups'),
s__('SecurityConfiguration|Runtime security metrics for application environments'),
s__(
- 'SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance',
+ 'SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance',
),
],
buttonText: s__('SecurityConfiguration|Upgrade or start a free trial'),
diff --git a/app/assets/javascripts/service_ping_consent.js b/app/assets/javascripts/service_ping_consent.js
index f145a1b30db..f2c3f28cefa 100644
--- a/app/assets/javascripts/service_ping_consent.js
+++ b/app/assets/javascripts/service_ping_consent.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import createFlash, { hideFlash } from './flash';
+import { createAlert, hideFlash } from './flash';
import axios from './lib/utils/axios_utils';
import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
@@ -27,7 +27,7 @@ export default () => {
})
.catch(() => {
hideConsentMessage();
- createFlash({
+ createAlert({
message: __('Something went wrong. Try again later.'),
});
});
diff --git a/app/assets/javascripts/set_status_modal/set_status_form.vue b/app/assets/javascripts/set_status_modal/set_status_form.vue
index 7f9a30b7ff1..86049a2b781 100644
--- a/app/assets/javascripts/set_status_modal/set_status_form.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_form.vue
@@ -131,9 +131,9 @@ export default {
i18n: {
statusMessagePlaceholder: s__(`SetStatusModal|What's your status?`),
clearStatusButtonLabel: s__('SetStatusModal|Clear status'),
- availabilityCheckboxLabel: s__('SetStatusModal|Busy'),
+ availabilityCheckboxLabel: s__('SetStatusModal|Set yourself as busy'),
availabilityCheckboxHelpText: s__(
- 'SetStatusModal|An indicator appears next to your name and avatar',
+ 'SetStatusModal|Displays that you are busy or not able to respond',
),
clearStatusAfterDropdownLabel: s__('SetStatusModal|Clear status after'),
clearStatusAfterMessage: s__('SetStatusModal|Your status resets on %{date}.'),
@@ -161,11 +161,7 @@ export default {
@click="handleEmojiClick"
>
<template #button-content>
- <span
- v-if="noEmoji"
- class="no-emoji-placeholder position-relative"
- data-testid="no-emoji-placeholder"
- >
+ <span v-if="noEmoji" class="gl-relative" data-testid="no-emoji-placeholder">
<gl-icon name="slight-smile" class="award-control-icon-neutral" />
<gl-icon name="smiley" class="award-control-icon-positive" />
<gl-icon name="smile" class="award-control-icon-super-positive" />
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 80b1cb8c4d5..80158c55dbc 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -1,7 +1,7 @@
<script>
import { GlToast, GlTooltipDirective, GlSafeHtmlDirective, GlModal } from '@gitlab/ui';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import { updateUserStatus } from '~/rest_api';
@@ -89,7 +89,7 @@ export default {
window.location.reload();
},
onUpdateFail() {
- createFlash({
+ createAlert({
message: s__(
"SetStatusModal|Sorry, we weren't able to set your status. Please try again later.",
),
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index 18b26c7d8bd..15fd365b4da 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -1,6 +1,6 @@
<script>
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
@@ -113,7 +113,7 @@ export default {
})
.catch(() => {
this.loading = false;
- return createFlash({
+ return createAlert({
message: __('Error occurred when saving assignees'),
});
});
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 26fda2a823c..395dcf73693 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { IssuableType } from '~/issues/constants';
import { __, n__ } from '~/locale';
import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
@@ -111,7 +111,7 @@ export default {
}
},
error() {
- createFlash({ message: __('An error occurred while fetching participants.') });
+ createAlert({ message: __('An error occurred while fetching participants.') });
},
},
},
@@ -191,7 +191,7 @@ export default {
return data;
})
.catch(() => {
- createFlash({ message: __('An error occurred while updating assignees.') });
+ createAlert({ message: __('An error occurred while updating assignees.') });
})
.finally(() => {
this.isSettingAssignees = false;
@@ -220,7 +220,7 @@ export default {
this.$refs.userSelect.showDropdown();
},
showError() {
- createFlash({ message: __('An error occurred while fetching participants.') });
+ createAlert({ message: __('An error occurred while fetching participants.') });
},
setDirtyState() {
this.isDirty = true;
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
index 0ed40f56bea..29298ef7627 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
@@ -58,7 +58,7 @@ export default {
v-if="hasCannotMergeIcon"
name="warning-solid"
aria-hidden="true"
- class="merge-icon gl-left-6 gl-bottom-0"
+ class="merge-icon"
:size="12"
/>
</template>
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 c44ce8b0057..3532b75b6e7 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
@@ -1,6 +1,6 @@
<script>
import { GlSprintf, GlButton } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { IssuableType } from '~/issues/constants';
import { __, sprintf } from '~/locale';
import { confidentialityQueries } from '~/sidebar/constants';
@@ -92,7 +92,7 @@ export default {
},
}) => {
if (errors.length) {
- createFlash({
+ createAlert({
message: errors[0],
});
} else {
@@ -101,7 +101,7 @@ export default {
},
)
.catch(() => {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} confidentiality.'),
{
diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
index f234c5ea3c9..f3bd58c11d4 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
@@ -1,7 +1,7 @@
<script>
import produce from 'immer';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, sprintf } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { confidentialityQueries, Tracking } from '~/sidebar/constants';
@@ -72,7 +72,7 @@ export default {
this.$emit('confidentialityUpdated', data.workspace?.issuable?.confidential);
},
error() {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} confidentiality.'),
{
diff --git a/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue b/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue
index 67f36f65b5d..81090bfa062 100644
--- a/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue
+++ b/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlLink, GlPopover, GlTooltipDirective } from '@gitlab/ui';
import { __, n__, sprintf } from '~/locale';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { TYPE_ISSUE } from '~/graphql_shared/constants';
import getIssueCrmContactsQuery from './queries/get_issue_crm_contacts.query.graphql';
@@ -41,7 +41,7 @@ export default {
return data?.issue?.customerRelationsContacts?.nodes;
},
error(error) {
- createFlash({
+ createAlert({
message: __('Something went wrong trying to load issue contacts.'),
error,
captureError: true,
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 ef99d540c86..98468583992 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
@@ -1,6 +1,6 @@
<script>
import { GlIcon, GlDatepicker, GlTooltipDirective, GlLink, GlPopover } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { IssuableType } from '~/issues/constants';
import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
@@ -92,7 +92,7 @@ export default {
this.$emit(`${this.dateType}Updated`, data.workspace?.issuable?.[this.dateType]);
},
error() {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} %{dateType} date.'),
{
@@ -205,7 +205,7 @@ export default {
},
}) => {
if (errors.length) {
- createFlash({
+ createAlert({
message: errors[0],
});
} else {
@@ -214,7 +214,7 @@ export default {
},
)
.catch(() => {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} %{dateType} date.'),
{
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
index 8145506f32c..df03af346c0 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -2,7 +2,7 @@
import { GlButton } from '@gitlab/ui';
import $ from 'jquery';
import { mapActions } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, sprintf } from '~/locale';
import eventHub from '../../event_hub';
@@ -52,7 +52,7 @@ export default {
const flashMessage = __(
'Something went wrong trying to change the locked state of this %{issuableDisplayName}',
);
- createFlash({
+ createAlert({
message: sprintf(flashMessage, { issuableDisplayName: this.issuableDisplayName }),
});
})
diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
index 286bd50f6dd..d32d8a7b044 100644
--- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
@@ -3,7 +3,7 @@ import { GlIcon, GlTooltipDirective, GlOutsideDirective as Outside } from '@gitl
import { mapGetters, mapActions } from 'vuex';
import { __, sprintf } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import eventHub from '~/sidebar/event_hub';
import toast from '~/vue_shared/plugins/global_toast';
import EditForm from './edit_form.vue';
@@ -95,7 +95,7 @@ export default {
const flashMessage = __(
'Something went wrong trying to change the locked state of this %{issuableDisplayName}',
);
- createFlash({
+ createAlert({
message: sprintf(flashMessage, { issuableDisplayName: this.issuableDisplayName }),
});
})
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
index 933b9b11b40..55bb214aa65 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
@@ -43,6 +43,7 @@ export default {
data-track-action="click_edit_button"
data-track-label="right_sidebar"
data-track-property="reviewer"
+ data-qa-selector="reviewers_edit_button"
>
{{ __('Edit') }}
</a>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index b0d820ddd15..ad061dd2e6b 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -3,7 +3,7 @@
// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736
import Vue from 'vue';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
@@ -64,7 +64,7 @@ export default {
this.initialLoading = false;
},
error() {
- createFlash({ message: __('An error occurred while fetching reviewers.') });
+ createAlert({ message: __('An error occurred while fetching reviewers.') });
},
},
},
@@ -85,7 +85,7 @@ export default {
return this.loading || this.$apollo.queries.issuable.loading;
},
canUpdate() {
- return this.issuable.userPermissions?.updateMergeRequest || false;
+ return this.issuable.userPermissions?.adminMergeRequest || false;
},
},
created() {
@@ -120,7 +120,7 @@ export default {
})
.catch(() => {
this.loading = false;
- return createFlash({
+ return createAlert({
message: __('Error occurred when saving reviewers'),
});
});
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index a562df4ecd6..f02e0c783e1 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -7,7 +7,7 @@ import {
GlSprintf,
GlButton,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { INCIDENT_SEVERITY, ISSUABLE_TYPES, I18N } from './constants';
import updateIssuableSeverity from './graphql/mutations/update_issuable_severity.mutation.graphql';
import SeverityToken from './severity.vue';
@@ -123,7 +123,7 @@ export default {
this.severity = severity;
})
.catch(() =>
- createFlash({
+ createAlert({
message: `${this.$options.i18n.UPDATE_SEVERITY_ERROR} ${this.$options.i18n.TRY_AGAIN}`,
}),
)
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index 6c615109bb8..c33b1468ca4 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -13,7 +13,7 @@ import {
GlButton,
} from '@gitlab/ui';
import { kebabCase, snakeCase } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { IssuableType } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
@@ -25,6 +25,8 @@ import {
Tracking,
IssuableAttributeState,
IssuableAttributeType,
+ LocalizedIssuableAttributeType,
+ IssuableAttributeTypeKeyMap,
issuableAttributesQueries,
noAttributeId,
defaultEpicSort,
@@ -125,7 +127,7 @@ export default {
return data?.workspace?.issuable.attribute;
},
error(error) {
- createFlash({
+ createAlert({
message: this.i18n.currentFetchError,
captureError: true,
error,
@@ -179,7 +181,7 @@ export default {
return [];
},
error(error) {
- createFlash({ message: this.i18n.listFetchError, captureError: true, error });
+ createAlert({ message: this.i18n.listFetchError, captureError: true, error });
},
},
},
@@ -229,7 +231,9 @@ export default {
return timeFor(this.currentAttribute?.dueDate);
},
i18n() {
- return dropdowni18nText(this.issuableAttribute, this.issuableType);
+ const localizedAttribute =
+ LocalizedIssuableAttributeType[IssuableAttributeTypeKeyMap[this.issuableAttribute]];
+ return dropdowni18nText(localizedAttribute, this.issuableType);
},
isEpic() {
// MV to EE https://gitlab.com/gitlab-org/gitlab/-/issues/345311
@@ -280,7 +284,7 @@ export default {
})
.then(({ data }) => {
if (data.issuableSetAttribute?.errors?.length) {
- createFlash({
+ createAlert({
message: data.issuableSetAttribute.errors[0],
captureError: true,
error: data.issuableSetAttribute.errors[0],
@@ -290,7 +294,7 @@ export default {
}
})
.catch((error) => {
- createFlash({ message: this.i18n.updateError, captureError: true, error });
+ createAlert({ message: this.i18n.updateError, captureError: true, error });
})
.finally(() => {
this.updating = false;
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
index cc88812c7b0..1680e42e5e4 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -89,7 +89,9 @@ export default {
return;
}
- this.edit = true;
+ if (this.canEdit && this.canUpdate) {
+ this.edit = true;
+ }
this.$emit('open');
window.addEventListener('click', this.collapseWhenOffClick);
window.addEventListener('keyup', this.collapseOnEscape);
@@ -125,7 +127,7 @@ export default {
<template>
<div>
<div
- class="gl-display-flex gl-align-items-center gl-line-height-20 gl-mb-2 gl-text-gray-900 gl-font-weight-bold"
+ class="gl-display-flex gl-align-items-center gl-line-height-20 gl-text-gray-900 gl-font-weight-bold"
@click.self="collapse"
>
<span class="hide-collapsed" data-testid="title" @click="collapse">
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 e5bee4df9b8..99e7c825b72 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
@@ -1,6 +1,6 @@
<script>
-import { GlIcon, GlLoadingIcon, GlToggle, GlTooltipDirective } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { GlDropdownForm, GlIcon, GlLoadingIcon, GlToggle, GlTooltipDirective } from '@gitlab/ui';
+import { createAlert } from '~/flash';
import { IssuableType } from '~/issues/constants';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __, sprintf } from '~/locale';
@@ -22,6 +22,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
+ GlDropdownForm,
GlIcon,
GlLoadingIcon,
GlToggle,
@@ -73,7 +74,7 @@ export default {
this.$emit('subscribedUpdated', data.workspace?.issuable?.subscribed);
},
error() {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} notifications.'),
{
@@ -137,7 +138,7 @@ export default {
},
}) => {
if (errors.length) {
- createFlash({
+ createAlert({
message: errors[0],
});
}
@@ -148,7 +149,7 @@ export default {
},
)
.catch(() => {
- createFlash({
+ createAlert({
message: sprintf(
__('Something went wrong while setting %{issuableType} notifications.'),
{
@@ -181,7 +182,7 @@ export default {
</script>
<template>
- <div v-if="isMergeRequest" class="gl-new-dropdown-item">
+ <gl-dropdown-form v-if="isMergeRequest" class="gl-new-dropdown-item">
<div class="gl-px-5 gl-pb-2 gl-pt-1">
<gl-toggle
:value="subscribed"
@@ -192,7 +193,7 @@ export default {
@change="toggleSubscribed"
/>
</div>
- </div>
+ </gl-dropdown-form>
<sidebar-editable-item
v-else
ref="editable"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
index d751816bd94..124464088cf 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon, GlTableLite, GlButton, GlTooltipDirective } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { formatDate, parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
@@ -47,7 +47,7 @@ export default {
return this.extractTimelogs(data);
},
error() {
- createFlash({ message: __('Something went wrong. Please try again.') });
+ createAlert({ message: __('Something went wrong. Please try again.') });
},
},
},
@@ -105,7 +105,7 @@ export default {
}
})
.catch((error) => {
- createFlash({
+ createAlert({
message: s__('TimeTracking|An error occurred while removing the timelog.'),
captureError: true,
error,
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index d472b67d976..62b05421884 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -61,7 +61,7 @@ export default {
</script>
<template>
- <div class="block">
+ <div class="block time-tracking">
<issuable-time-tracker
:full-path="fullPath"
:issuable-id="issuableId"
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
index 42e16aae312..5da2d65723a 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { produce } from 'immer';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, sprintf } from '~/locale';
import { todoQueries, TodoMutationTypes, todoMutations } from '~/sidebar/constants';
import { todoLabel } from '~/vue_shared/components/sidebar/todo_toggle//utils';
@@ -73,7 +73,7 @@ export default {
this.$emit('todoUpdated', currentUserTodos.length > 0);
},
error() {
- createFlash({
+ createAlert({
message: sprintf(__('Something went wrong while setting %{issuableType} to-do item.'), {
issuableType: this.issuableType,
}),
@@ -155,7 +155,7 @@ export default {
},
}) => {
if (errors.length) {
- createFlash({
+ createAlert({
message: errors[0],
});
}
@@ -166,7 +166,7 @@ export default {
},
)
.catch(() => {
- createFlash({
+ createAlert({
message: sprintf(__('Something went wrong while setting %{issuableType} to-do item.'), {
issuableType: this.issuableType,
}),
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index 60cb4cff727..6248bcb8e2d 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -1,3 +1,4 @@
+import { invert } from 'lodash';
import { s__, __, sprintf } from '~/locale';
import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
@@ -251,6 +252,12 @@ export const IssuableAttributeType = {
Milestone: 'milestone',
};
+export const LocalizedIssuableAttributeType = {
+ Milestone: s__('Issuable|milestone'),
+};
+
+export const IssuableAttributeTypeKeyMap = invert(IssuableAttributeType);
+
export const IssuableAttributeState = {
[IssuableAttributeType.Milestone]: 'active',
};
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 5a3122e83d0..2cce27df598 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { escape } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
function isValidProjectId(id) {
@@ -44,7 +44,7 @@ class SidebarMoveIssue {
.fetchAutocompleteProjects(searchTerm)
.then(callback)
.catch(() =>
- createFlash({
+ createAlert({
message: __('An error occurred while fetching projects autocomplete.'),
}),
);
@@ -79,7 +79,7 @@ class SidebarMoveIssue {
this.$confirmButton.disable().addClass('is-loading');
this.mediator.moveIssue().catch(() => {
- createFlash({ message: __('An error occurred while moving the issue.') });
+ createAlert({ message: __('An error occurred while moving the issue.') });
this.$confirmButton.enable().removeClass('is-loading');
});
}
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 1cb3c30b9e0..9b5bad710dd 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -161,7 +161,7 @@ function mountAssigneesComponent() {
fullPath,
issuableType,
issuableId: id,
- allowMultipleAssignees: !el.dataset.maxAssignees,
+ allowMultipleAssignees: !el.dataset.maxAssignees || el.dataset.maxAssignees > 1,
editable,
},
scopedSlots: {
diff --git a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
index d665ca1e084..71ce58fb9cc 100644
--- a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
@@ -1,5 +1,4 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
-#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
query epicParticipants($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
@@ -9,7 +8,6 @@ query epicParticipants($fullPath: ID!, $iid: ID) {
participants {
nodes {
...User
- ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/sidebar/queries/sidebar_details.query.graphql b/app/assets/javascripts/sidebar/queries/sidebar_details.query.graphql
deleted file mode 100644
index 90d1a7794ea..00000000000
--- a/app/assets/javascripts/sidebar/queries/sidebar_details.query.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-query sidebarDetails($fullPath: ID!, $iid: String!) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- id
- iid
- }
- }
-}
diff --git a/app/assets/javascripts/sidebar/queries/sidebar_details_mr.query.graphql b/app/assets/javascripts/sidebar/queries/sidebar_details_mr.query.graphql
deleted file mode 100644
index 0505f88773d..00000000000
--- a/app/assets/javascripts/sidebar/queries/sidebar_details_mr.query.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-query mergeRequestSidebarDetails($fullPath: ID!, $iid: String!) {
- project(fullPath: $fullPath) {
- id
- mergeRequest(iid: $iid) {
- id
- iid # currently unused.
- }
- }
-}
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index beacdeb559c..00d3177b75a 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -1,15 +1,8 @@
-import sidebarDetailsIssueQuery from 'ee_else_ce/sidebar/queries/sidebar_details.query.graphql';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
import reviewerRereviewMutation from '../queries/reviewer_rereview.mutation.graphql';
-import sidebarDetailsMRQuery from '../queries/sidebar_details_mr.query.graphql';
-
-const queries = {
- merge_request: sidebarDetailsMRQuery,
- issue: sidebarDetailsIssueQuery,
-};
export const gqClient = createGqClient(
{},
@@ -36,37 +29,13 @@ export default class SidebarService {
}
get() {
- return Promise.all([
- axios.get(this.endpoint),
- gqClient.query({
- query: this.sidebarDetailsQuery(),
- variables: {
- fullPath: this.fullPath,
- iid: this.iid.toString(),
- },
- }),
- ]);
- }
-
- sidebarDetailsQuery() {
- return queries[this.issuableType];
+ return axios.get(this.endpoint);
}
update(key, data) {
return axios.put(this.endpoint, { [key]: data });
}
- updateWithGraphQl(mutation, variables) {
- return gqClient.mutate({
- mutation,
- variables: {
- ...variables,
- projectPath: this.fullPath,
- iid: this.iid.toString(),
- },
- });
- }
-
getProjectsAutocomplete(searchTerm) {
return axios.get(this.projectsAutocompleteEndpoint, {
params: {
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index f7c93b6903c..912f0fdcbef 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,5 +1,5 @@
import Store from '~/sidebar/stores/sidebar_store';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
import { visitUrl } from '../lib/utils/url_utility';
@@ -93,11 +93,11 @@ export default class SidebarMediator {
fetch() {
return this.service
.get()
- .then(([restResponse, graphQlResponse]) => {
- this.processFetchedData(restResponse.data, graphQlResponse.data);
+ .then(({ data }) => {
+ this.processFetchedData(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error occurred when fetching sidebar data'),
}),
);
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 26838682fc8..6e5b2ce4dbe 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -1,10 +1,10 @@
/* eslint-disable consistent-return */
import $ from 'jquery';
+import { createAlert } from '~/flash';
import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
import { spriteIcon } from '~/lib/utils/common_utils';
import FilesCommentButton from './files_comment_button';
-import createFlash from './flash';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
@@ -96,7 +96,7 @@ export default class SingleFileDiff {
if (cb) cb();
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('An error occurred while retrieving diff'),
});
});
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index 2537ec78850..4a7528d9c8e 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -2,7 +2,7 @@
import { GlButton, GlLoadingIcon, GlFormInput, GlFormGroup } from '@gitlab/ui';
import eventHub from '~/blob/components/eventhub';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { redirectTo, joinPaths } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
import {
@@ -145,7 +145,7 @@ export default {
const defaultErrorMsg = this.newSnippet
? SNIPPET_CREATE_MUTATION_ERROR
: SNIPPET_UPDATE_MUTATION_ERROR;
- createFlash({
+ createAlert({
message: sprintf(defaultErrorMsg, { err }),
});
this.isUpdating = false;
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index fe169775f96..7e80928cbea 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale';
@@ -63,7 +63,7 @@ export default {
.catch((e) => this.flashAPIFailure(e));
},
flashAPIFailure(err) {
- createFlash({ message: sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }) });
+ createAlert({ message: sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }) });
},
},
};
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index 86cbc2c31b3..360ffdd34e0 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -53,7 +53,9 @@ export default {
return {
blobContent: '',
activeViewerType:
- this.blob?.richViewer && !window.location.hash ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER,
+ this.blob?.richViewer && !window.location.hash?.startsWith('#LC')
+ ? RICH_BLOB_VIEWER
+ : SIMPLE_BLOB_VIEWER,
};
},
computed: {
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index dd8f2897018..759a3f31a05 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -19,7 +19,7 @@ import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_DANGER, VARIANT_SUCCESS } from '~/flash';
import DeleteSnippetMutation from '../mutations/delete_snippet.mutation.graphql';
@@ -196,12 +196,12 @@ export default {
try {
this.isSubmittingSpam = true;
await axios.post(this.reportAbusePath);
- createFlash({
+ createAlert({
message: this.$options.i18n.snippetSpamSuccess,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
} catch (error) {
- createFlash({ message: this.$options.i18n.snippetSpamFailure });
+ createAlert({ message: this.$options.i18n.snippetSpamFailure, variant: VARIANT_DANGER });
} finally {
this.isSubmittingSpam = false;
}
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index 6e72d95c8e6..a7760ad5d0b 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import 'deckar01-task_list';
import { __ } from '~/locale';
-import createFlash from './flash';
+import { createAlert } from '~/flash';
import axios from './lib/utils/axios_utils';
export default class TaskList {
@@ -23,7 +23,7 @@ export default class TaskList {
errorMessages = e.response.data.errors.join(' ');
}
- return createFlash({
+ return createAlert({
message: errorMessages || __('Update failed'),
});
};
diff --git a/app/assets/javascripts/token_access/components/token_access.vue b/app/assets/javascripts/token_access/components/token_access.vue
index 363a9d58d65..4b91872d80d 100644
--- a/app/assets/javascripts/token_access/components/token_access.vue
+++ b/app/assets/javascripts/token_access/components/token_access.vue
@@ -1,5 +1,6 @@
<script>
import {
+ GlAlert,
GlButton,
GlCard,
GlFormInput,
@@ -8,7 +9,7 @@ import {
GlSprintf,
GlToggle,
} from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __, s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import addProjectCIJobTokenScopeMutation from '../graphql/mutations/add_project_ci_job_token_scope.mutation.graphql';
@@ -25,6 +26,9 @@ export default {
`CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}`,
),
cardHeaderTitle: s__('CICD|Add an existing project to the scope'),
+ settingDisabledMessage: s__(
+ 'CICD|Enable feature to limit job token access to the following projects.',
+ ),
addProject: __('Add project'),
cancel: __('Cancel'),
addProjectPlaceholder: __('Paste project path (i.e. gitlab-org/gitlab)'),
@@ -32,6 +36,7 @@ export default {
scopeFetchError: __('There was a problem fetching the job token scope value'),
},
components: {
+ GlAlert,
GlButton,
GlCard,
GlFormInput,
@@ -58,7 +63,7 @@ export default {
return data.project.ciCdSettings.jobTokenScopeEnabled;
},
error() {
- createFlash({ message: this.$options.i18n.scopeFetchError });
+ createAlert({ message: this.$options.i18n.scopeFetchError });
},
},
projects: {
@@ -72,7 +77,7 @@ export default {
return data.project?.ciJobTokenScope?.projects?.nodes ?? [];
},
error() {
- createFlash({ message: this.$options.i18n.projectsFetchError });
+ createAlert({ message: this.$options.i18n.projectsFetchError });
},
},
},
@@ -112,7 +117,7 @@ export default {
throw new Error(errors[0]);
}
} catch (error) {
- createFlash({ message: error });
+ createAlert({ message: error });
}
},
async addProject() {
@@ -135,7 +140,7 @@ export default {
throw new Error(errors[0]);
}
} catch (error) {
- createFlash({ message: error });
+ createAlert({ message: error });
} finally {
this.clearTargetProjectPath();
this.getProjects();
@@ -161,7 +166,7 @@ export default {
throw new Error(errors[0]);
}
} catch (error) {
- createFlash({ message: error });
+ createAlert({ message: error });
} finally {
this.getProjects();
}
@@ -195,8 +200,8 @@ export default {
</template>
</gl-toggle>
- <div data-testid="token-section">
- <gl-card class="gl-mt-5">
+ <div>
+ <gl-card class="gl-mt-5 gl-mb-3">
<template #header>
<h5 class="gl-my-0">{{ $options.i18n.cardHeaderTitle }}</h5>
</template>
@@ -213,7 +218,16 @@ export default {
<gl-button @click="clearTargetProjectPath">{{ $options.i18n.cancel }}</gl-button>
</template>
</gl-card>
-
+ <gl-alert
+ v-if="!jobTokenScopeEnabled"
+ class="gl-mb-3"
+ variant="warning"
+ :dismissible="false"
+ :show-icon="false"
+ data-testid="token-disabled-alert"
+ >
+ {{ $options.i18n.settingDisabledMessage }}
+ </gl-alert>
<token-projects-table :projects="projects" @removeProject="removeProject" />
</div>
</template>
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index 94b4ee77e7e..bd425bdc2a8 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -50,6 +50,7 @@ function UsersSelect(currentUser, els, options = {}) {
options.iid = $dropdown.data('iid');
options.issuableType = $dropdown.data('issuableType');
options.targetBranch = $dropdown.data('targetBranch');
+ options.showSuggested = $dropdown.data('showSuggested');
const showNullUser = $dropdown.data('nullUser');
const defaultNullUser = $dropdown.data('nullUserDefault');
const showMenuAbove = $dropdown.data('showMenuAbove');
@@ -340,6 +341,16 @@ function UsersSelect(currentUser, els, options = {}) {
if ($dropdown.hasClass('js-multiselect')) {
const selected = getSelected().filter((i) => i !== 0);
+ if ($dropdown.data('showSuggested')) {
+ const suggested = this.suggestedUsers(users);
+ if (suggested.length) {
+ users = users.filter(
+ (u) => !u.suggested || (u.suggested && selected.indexOf(u.id) !== -1),
+ );
+ users.splice(showDivider + 1, 0, ...suggested);
+ }
+ }
+
if (selected.length > 0) {
if ($dropdown.data('dropdownHeader')) {
showDivider += 1;
@@ -370,6 +381,19 @@ function UsersSelect(currentUser, els, options = {}) {
$dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
}
},
+ suggestedUsers(users) {
+ const selected = getSelected().filter((i) => i !== 0);
+ const suggestedUsers = users.filter((u) => u.suggested && selected.indexOf(u.id) === -1);
+
+ if (!suggestedUsers.length) return [];
+
+ const items = [
+ { type: 'header', content: $dropdown.data('suggestedReviewersHeader') },
+ ...suggestedUsers,
+ { type: 'header', content: $dropdown.data('allMembersHeader') },
+ ];
+ return items;
+ },
filterable: true,
filterRemote: true,
search: {
@@ -760,6 +784,10 @@ UsersSelect.prototype.users = function (query, options, callback) {
params.approval_rules = true;
}
+ if (isMergeRequest && options.showSuggested) {
+ params.show_suggested = true;
+ }
+
if (isNewMergeRequest) {
params.target_branch = options.targetBranch || null;
}
@@ -791,13 +819,14 @@ UsersSelect.prototype.renderRow = function (
const tooltipAttributes = tooltip
? `data-container="body" data-placement="left" data-title="${tooltip}"`
: '';
+ const dataUserSuggested = user.suggested ? `data-user-suggested=${user.suggested}` : '';
const name =
user?.availability && isUserBusy(user.availability)
? sprintf(__('%{name} (Busy)'), { name: user.name })
: user.name;
return `
- <li data-user-id=${user.id}>
+ <li data-user-id=${user.id} ${dataUserSuggested}>
<a href="#" class="dropdown-menu-user-link gl-display-flex! gl-align-items-center ${linkClasses}" ${tooltipAttributes}>
${this.renderRowAvatar(issuableType, user, img)}
<span class="gl-display-flex gl-flex-direction-column gl-overflow-hidden">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
index 30a0e7c383c..5339d7faf85 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
@@ -74,9 +74,11 @@ export default {
</script>
<template>
- <div>
+ <div class="gl-display-flex gl-align-items-flex-start">
<gl-dropdown
v-if="tertiaryButtons.length"
+ v-gl-tooltip
+ :title="__('Options')"
:text="dropdownLabel"
icon="ellipsis_v"
no-caret
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
index f782c28ea19..2cfeb7a4bcb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
@@ -1,6 +1,6 @@
<script>
import { GlButton, GlSprintf, GlLink } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__, __ } from '~/locale';
@@ -139,7 +139,7 @@ export default {
this.fetchingApprovals = false;
})
.catch(() =>
- createFlash({
+ createAlert({
message: FETCH_ERROR,
}),
);
@@ -154,7 +154,7 @@ export default {
this.updateApproval(
() => this.service.approveMergeRequest(),
() =>
- createFlash({
+ createAlert({
message: APPROVE_ERROR,
}),
);
@@ -167,7 +167,7 @@ export default {
this.hasApprovalAuthError = true;
return;
}
- createFlash({
+ createAlert({
message: APPROVE_ERROR,
});
},
@@ -177,7 +177,7 @@ export default {
this.updateApproval(
() => this.service.unapproveMergeRequest(),
() =>
- createFlash({
+ createAlert({
message: UNAPPROVE_ERROR,
}),
);
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
index 7ba387c79b1..d6d1cae4029 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
@@ -1,9 +1,10 @@
<script>
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import eventHub from '../../event_hub';
import MRWidgetService from '../../services/mr_widget_service';
import {
MANUAL_DEPLOY,
@@ -129,11 +130,12 @@ export default {
}
})
.catch(() => {
- createFlash({
+ createAlert({
message: errorMessage,
});
})
.finally(() => {
+ eventHub.$emit('FetchDeployments');
this.actionInProgress = null;
});
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
index 1e363b0f5fb..5efa0e2879e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
@@ -7,7 +7,10 @@ import {
GlLink,
GlSearchBoxByType,
} from '@gitlab/ui';
+import { isSafeURL } from '~/lib/utils/url_utility';
+import { s__, __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import ReviewAppLink from '../review_app_link.vue';
export default {
@@ -19,6 +22,7 @@ export default {
GlIcon,
GlLink,
GlSearchBoxByType,
+ ModalCopyButton,
ReviewAppLink,
},
directives: {
@@ -50,6 +54,13 @@ export default {
filteredChanges() {
return this.deployment?.changes?.filter((change) => change.path.includes(this.searchTerm));
},
+ isSafeUrl() {
+ return isSafeURL(this.deploymentExternalUrl);
+ },
+ },
+ i18n: {
+ copy: __('Copy URL'),
+ copyTitle: s__('Environments|Copy live environment URL'),
},
};
</script>
@@ -57,11 +68,20 @@ export default {
<span class="gl-display-inline-flex">
<gl-button-group v-if="shouldRenderDropdown" size="small">
<review-app-link
+ v-if="isSafeUrl"
:display="appButtonText"
:link="deploymentExternalUrl"
size="small"
css-class="deploy-link js-deploy-url inline gl-ml-3"
/>
+ <modal-copy-button
+ v-else
+ :title="$options.i18n.copyTitle"
+ :text="deploymentExternalUrl"
+ size="small"
+ >
+ {{ $options.i18n.copy }}
+ </modal-copy-button>
<gl-dropdown toggle-class="gl-px-2!" size="small" class="js-mr-wigdet-deployment-dropdown">
<template #button-content>
<gl-icon
@@ -90,12 +110,22 @@ export default {
</gl-dropdown-item>
</gl-dropdown>
</gl-button-group>
- <review-app-link
- v-else
- :display="appButtonText"
- :link="deploymentExternalUrl"
- size="small"
- css-class="js-deploy-url deploy-link btn btn-default btn-sm inline gl-ml-3"
- />
+ <template v-else>
+ <review-app-link
+ v-if="isSafeUrl"
+ :display="appButtonText"
+ :link="deploymentExternalUrl"
+ size="small"
+ css-class="deploy-link js-deploy-url inline gl-ml-3"
+ />
+ <modal-copy-button
+ v-else
+ :title="$options.i18n.copyTitle"
+ :text="deploymentExternalUrl"
+ size="small"
+ >
+ {{ $options.i18n.copy }}
+ </modal-copy-button>
+ </template>
</span>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index 300e2a672cb..3d03dbd9db3 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
@@ -315,7 +315,6 @@ export default {
data-qa-selector="mr_widget_extension"
>
<state-container
- :mr="mr"
:status="statusIconName"
:is-loading="isLoadingSummary"
:class="{ 'gl-cursor-pointer': isCollapsible }"
@@ -324,7 +323,7 @@ export default {
@mouseup="onRowMouseUp"
>
<div
- class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
+ class="media-body gl-display-flex gl-flex-direction-row! gl-w-full"
data-testid="widget-extension-top-level"
>
<div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
index d67ff11f297..e3f87c08ad4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
@@ -28,7 +28,7 @@ const nonStandardEvents = {
},
counter: {},
},
- testReport: {
+ testSummary: {
uniqueUser: {
expand: ['i_testing_summary_widget_total'],
},
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 94a1b805b99..870972156c5 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
@@ -26,16 +26,6 @@ export default {
required: false,
default: true,
},
- divergedCommitsCount: {
- type: Number,
- required: false,
- default: 0,
- },
- targetBranchPath: {
- type: String,
- required: false,
- default: '',
- },
},
computed: {
closesText() {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
index 822c5a68093..932659f3c89 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
@@ -16,7 +16,8 @@ export default {
props: {
mr: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
isLoading: {
type: Boolean,
@@ -80,6 +81,7 @@ export default {
</div>
</div>
<div
+ v-if="mr"
class="gl-md-display-none gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6 gl-mt-1"
>
<gl-button
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 e2a9caf5419..2b22033514f 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
@@ -1,6 +1,7 @@
<script>
import { s__ } from '~/locale';
import StatusIcon from '../mr_widget_status_icon.vue';
+import { DETAILED_MERGE_STATUS } from '../../constants';
export default {
i18n: {
@@ -22,7 +23,7 @@ export default {
failedText() {
if (this.mr.approvals && !this.mr.isApproved) {
return this.$options.i18n.approvalNeeded;
- } else if (this.mr.blockingMergeRequests?.total_count > 0) {
+ } else if (this.mr.detailedMergeStatus === DETAILED_MERGE_STATUS.BLOCKED_STATUS) {
return this.$options.i18n.blockingMergeRequests;
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 3c6c2a44e70..92a7fa39cdc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -2,7 +2,7 @@
import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import autoMergeEnabledQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { AUTO_MERGE_STRATEGIES } from '../../constants';
@@ -113,7 +113,7 @@ export default {
})
.catch(() => {
this.isCancellingAutoMerge = false;
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
});
@@ -141,7 +141,7 @@ export default {
})
.catch(() => {
this.isRemovingSourceBranch = false;
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index e9298b0c856..46392565088 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
import api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__, __ } from '~/locale';
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
import modalEventHub from '~/projects/commit/event_hub';
@@ -131,7 +131,7 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
});
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 37c8d5d15f3..f6843c1f3d3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -1,6 +1,6 @@
<script>
import { GlButton, GlSkeletonLoader } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import toast from '~/vue_shared/plugins/global_toast';
@@ -111,7 +111,7 @@ export default {
if (error.response && error.response.data && error.response.data.merge_error) {
this.rebasingError = error.response.data.merge_error;
} else {
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
}
@@ -142,7 +142,7 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
stopPolling();
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
index 3cbd171a035..853895a4296 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
@@ -11,6 +11,12 @@ export default {
GlSprintf,
StatusIcon,
},
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ },
computed: {
troubleshootingDocsPath() {
return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' });
@@ -29,7 +35,14 @@ export default {
<status-icon status="failed" />
<div class="media-body space-children">
<span class="gl-font-weight-bold">
- <gl-sprintf :message="$options.i18n.failedMessage">
+ <span v-if="mr.isPipelineBlocked">
+ {{
+ s__(
+ `mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`,
+ )
+ }}
+ </span>
+ <gl-sprintf v-else :message="$options.i18n.failedMessage">
<template #link="{ content }">
<gl-link :href="troubleshootingDocsPath" target="_blank">
{{ content }}
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 78430abcfe9..1298c1316e2 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
@@ -14,10 +14,10 @@ import {
import { isEmpty } from 'lodash';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import simplePoll from '~/lib/utils/simple_poll';
-import { __, s__ } from '~/locale';
+import { __, s__, n__ } from '~/locale';
import SmartInterval from '~/smart_interval';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { helpPagePath } from '~/helpers/help_page_helper';
@@ -325,15 +325,20 @@ export default {
);
},
sourceBranchDeletedText() {
- if (this.removeSourceBranch) {
- return this.mr.state === 'merged'
- ? __('Deleted the source branch.')
- : __('Source branch will be deleted.');
+ const isPreMerge = this.mr.state !== 'merged';
+
+ if (isPreMerge) {
+ return this.mr.shouldRemoveSourceBranch
+ ? __('Source branch will be deleted.')
+ : __('Source branch will not be deleted.');
}
- return this.mr.state === 'merged'
- ? __('Did not delete the source branch.')
- : __('Source branch will not be deleted.');
+ return this.mr.sourceBranchRemoved
+ ? __('Deleted the source branch.')
+ : __('Did not delete the source branch.');
+ },
+ sourceHasDivergedFromTarget() {
+ return this.mr.divergedCommitsCount > 0;
},
showMergeDetailsHeader() {
return ['readyToMerge'].indexOf(this.mr.state) >= 0;
@@ -439,7 +444,7 @@ export default {
.catch(() => {
this.isMakingRequest = false;
this.mr.transitionStateMachine({ transition: MERGE_FAILURE });
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
});
@@ -483,7 +488,7 @@ export default {
}
})
.catch(() => {
- createFlash({
+ createAlert({
message: __('Something went wrong while deleting the source branch. Please try again.'),
});
});
@@ -507,6 +512,8 @@ export default {
mergeAndSquashCommitTemplatesHintText: s__(
'mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}',
),
+ sourceDivergedFromTargetText: s__('mrWidget|The source branch is %{link} the target branch'),
+ divergedCommits: (count) => n__('%d commit behind', '%d commits behind', count),
},
};
</script>
@@ -530,130 +537,148 @@ export default {
<div class="mr-widget-body mr-widget-body-ready-merge media mr-widget-body-line-height-1">
<div class="media-body">
<div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap">
- <gl-button-group v-if="shouldShowMergeControls" class="gl-align-self-start">
- <gl-button
- size="medium"
- category="primary"
- class="accept-merge-request"
- data-testid="merge-button"
- variant="confirm"
- :disabled="isMergeButtonDisabled"
- :loading="isMakingRequest"
- data-qa-selector="merge_button"
- @click="handleMergeButtonClick(isAutoMergeAvailable)"
- >{{ mergeButtonText }}</gl-button
- >
- <gl-dropdown
- v-if="shouldShowMergeImmediatelyDropdown"
- v-gl-tooltip.hover.focus="__('Select merge moment')"
- :disabled="isMergeButtonDisabled"
- variant="confirm"
- data-qa-selector="merge_moment_dropdown"
- toggle-class="btn-icon js-merge-moment"
- >
- <template #button-content>
- <gl-icon name="chevron-down" class="mr-0" />
- <span class="sr-only">{{ __('Select merge moment') }}</span>
- </template>
- <gl-dropdown-item
- icon-name="warning"
- button-class="accept-merge-request js-merge-immediately-button"
- data-qa-selector="merge_immediately_menu_item"
- @click="handleMergeImmediatelyButtonClick"
+ <template v-if="shouldShowMergeControls">
+ <div class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-mb-5">
+ <gl-form-checkbox
+ v-if="canRemoveSourceBranch"
+ id="remove-source-branch-input"
+ v-model="removeSourceBranch"
+ :disabled="isRemoveSourceBranchButtonDisabled"
+ class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
>
- {{ __('Merge immediately') }}
- </gl-dropdown-item>
- <merge-immediately-confirmation-dialog
- ref="confirmationDialog"
- :docs-url="mr.mergeImmediatelyDocsPath"
- @mergeImmediately="onMergeImmediatelyConfirmation"
+ {{ __('Delete source branch') }}
+ </gl-form-checkbox>
+
+ <!-- Placeholder for EE extension of this component -->
+ <squash-before-merge
+ v-if="shouldShowSquashBeforeMerge"
+ v-model="squashBeforeMerge"
+ :help-path="mr.squashBeforeMergeHelpPath"
+ :is-disabled="isSquashReadOnly"
+ class="gl-mr-5"
/>
- </gl-dropdown>
- <merge-train-failed-pipeline-confirmation-dialog
- :visible="isPipelineFailedModalVisibleMergeTrain"
- @startMergeTrain="onStartMergeTrainConfirmation"
- @cancel="isPipelineFailedModalVisibleMergeTrain = false"
- />
- <merge-failed-pipeline-confirmation-dialog
- :visible="isPipelineFailedModalVisibleNormalMerge"
- @mergeWithFailedPipeline="onMergeWithFailedPipelineConfirmation"
- @cancel="isPipelineFailedModalVisibleNormalMerge = false"
- />
- </gl-button-group>
- <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
- <div
- v-if="shouldShowMergeControls"
- class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-order-n1 gl-mb-5"
- >
- <gl-form-checkbox
- v-if="canRemoveSourceBranch"
- id="remove-source-branch-input"
- v-model="removeSourceBranch"
- :disabled="isRemoveSourceBranchButtonDisabled"
- class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
- >
- {{ __('Delete source branch') }}
- </gl-form-checkbox>
-
- <!-- Placeholder for EE extension of this component -->
- <squash-before-merge
- v-if="shouldShowSquashBeforeMerge"
- v-model="squashBeforeMerge"
- :help-path="mr.squashBeforeMergeHelpPath"
- :is-disabled="isSquashReadOnly"
- class="gl-mr-5"
- />
-
- <gl-form-checkbox
- v-if="shouldShowSquashEdit || shouldShowMergeEdit"
- v-model="editCommitMessage"
- data-testid="widget_edit_commit_message"
- class="gl-display-flex gl-align-items-center"
- >
- {{ __('Edit commit message') }}
- </gl-form-checkbox>
- </div>
- <div
- v-if="editCommitMessage"
- class="gl-w-full gl-order-n1"
- data-testid="edit_commit_message"
- >
- <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4">
- <commit-edit
- v-if="shouldShowSquashEdit"
- :value="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setSquashCommitMessage"
+
+ <gl-form-checkbox
+ v-if="shouldShowSquashEdit || shouldShowMergeEdit"
+ v-model="editCommitMessage"
+ data-testid="widget_edit_commit_message"
+ class="gl-display-flex gl-align-items-center"
>
- <template #header>
- <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ {{ __('Edit commit message') }}
+ </gl-form-checkbox>
+ </div>
+ <div class="gl-w-full gl-text-gray-500 gl-mb-5">
+ <added-commit-message
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
+ />
+ <template v-if="mr.relatedLinks">
+ &middot;
+ <related-links
+ :state="mr.state"
+ :related-links="mr.relatedLinks"
+ :show-assign-to-me="false"
+ :diverged-commits-count="mr.divergedCommitsCount"
+ :target-branch-path="mr.targetBranchPath"
+ class="mr-ready-merge-related-links gl-display-inline"
+ />
+ </template>
+ </div>
+ <div v-if="editCommitMessage" class="gl-w-full" data-testid="edit_commit_message">
+ <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4">
+ <commit-edit
+ v-if="shouldShowSquashEdit"
+ :value="squashCommitMessage"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setSquashCommitMessage"
+ >
+ <template #header>
+ <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ </template>
+ </commit-edit>
+ <commit-edit
+ v-if="shouldShowMergeEdit"
+ :value="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setCommitMessage"
+ />
+ <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>
+ <gl-button-group class="gl-align-self-start">
+ <gl-button
+ size="medium"
+ category="primary"
+ class="accept-merge-request"
+ data-testid="merge-button"
+ variant="confirm"
+ :disabled="isMergeButtonDisabled"
+ :loading="isMakingRequest"
+ data-qa-selector="merge_button"
+ @click="handleMergeButtonClick(isAutoMergeAvailable)"
+ >{{ mergeButtonText }}</gl-button
+ >
+ <gl-dropdown
+ v-if="shouldShowMergeImmediatelyDropdown"
+ v-gl-tooltip.hover.focus="__('Select merge moment')"
+ :disabled="isMergeButtonDisabled"
+ variant="confirm"
+ data-qa-selector="merge_moment_dropdown"
+ toggle-class="btn-icon js-merge-moment"
+ >
+ <template #button-content>
+ <gl-icon name="chevron-down" class="mr-0" />
+ <span class="sr-only">{{ __('Select merge moment') }}</span>
</template>
- </commit-edit>
- <commit-edit
- v-if="shouldShowMergeEdit"
- :value="commitMessage"
- :label="__('Merge commit message')"
- input-id="merge-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setCommitMessage"
+ <gl-dropdown-item
+ icon-name="warning"
+ button-class="accept-merge-request js-merge-immediately-button"
+ data-qa-selector="merge_immediately_menu_item"
+ @click="handleMergeImmediatelyButtonClick"
+ >
+ {{ __('Merge immediately') }}
+ </gl-dropdown-item>
+ <merge-immediately-confirmation-dialog
+ ref="confirmationDialog"
+ :docs-url="mr.mergeImmediatelyDocsPath"
+ @mergeImmediately="onMergeImmediatelyConfirmation"
+ />
+ </gl-dropdown>
+ <merge-train-failed-pipeline-confirmation-dialog
+ :visible="isPipelineFailedModalVisibleMergeTrain"
+ @startMergeTrain="onStartMergeTrainConfirmation"
+ @cancel="isPipelineFailedModalVisibleMergeTrain = false"
/>
- <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>
+ <merge-failed-pipeline-confirmation-dialog
+ :visible="isPipelineFailedModalVisibleNormalMerge"
+ @mergeWithFailedPipeline="onMergeWithFailedPipelineConfirmation"
+ @cancel="isPipelineFailedModalVisibleNormalMerge = false"
+ />
+ </gl-button-group>
+ <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
+ </template>
<div
- v-if="!shouldShowMergeControls"
+ v-else
class="gl-w-full gl-order-n1 mr-widget-merge-details"
data-qa-selector="merged_status_content"
>
@@ -661,13 +686,11 @@ export default {
{{ __('Merge details') }}
</p>
<ul class="gl-pl-4 gl-mb-0 gl-ml-3 gl-text-gray-600">
- <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal">
- <gl-sprintf
- :message="s__('mrWidget|The source branch is %{link} the target branch')"
- >
+ <li v-if="sourceHasDivergedFromTarget" class="gl-line-height-normal">
+ <gl-sprintf :message="$options.i18n.sourceDivergedFromTargetText">
<template #link>
<gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
+ $options.i18n.divergedCommits(mr.divergedCommitsCount)
}}</gl-link>
</template>
</gl-sprintf>
@@ -696,29 +719,6 @@ export default {
</li>
</ul>
</div>
- <div
- v-else
- :class="{ 'gl-mb-5': shouldShowMergeControls }"
- class="gl-w-full gl-order-n1 gl-text-gray-500"
- >
- <added-commit-message
- :is-squash-enabled="squashBeforeMerge"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- />
- <template v-if="mr.relatedLinks">
- &middot;
- <related-links
- :state="mr.state"
- :related-links="mr.relatedLinks"
- :show-assign-to-me="false"
- :diverged-commits-count="mr.divergedCommitsCount"
- :target-branch-path="mr.targetBranchPath"
- class="mr-ready-merge-related-links gl-display-inline"
- />
- </template>
- </div>
</div>
</div>
</div>
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 0458e9dfaf5..dee27a5d5b5 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
@@ -2,7 +2,7 @@
import { GlButton } from '@gitlab/ui';
import { produce } from 'immer';
import $ from 'jquery';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale';
import MergeRequest from '~/merge_request';
@@ -77,7 +77,7 @@ export default {
},
) {
if (errors?.length) {
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
@@ -130,7 +130,7 @@ export default {
},
)
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
}),
)
@@ -152,7 +152,7 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
});
});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
deleted file mode 100644
index 18fdb29ba54..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
+++ /dev/null
@@ -1,137 +0,0 @@
-<script>
-import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import { n__ } from '~/locale';
-import MrWidgetExpanableSection from '../mr_widget_expandable_section.vue';
-import TerraformPlan from './terraform_plan.vue';
-
-export default {
- name: 'MRWidgetTerraformContainer',
- components: {
- GlSkeletonLoader,
- GlSprintf,
- MrWidgetExpanableSection,
- TerraformPlan,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- loading: true,
- plansObject: {},
- poll: null,
- };
- },
- computed: {
- inValidPlanCountText() {
- if (this.numberOfInvalidPlans === 0) {
- return null;
- }
-
- return n__(
- 'Terraform|%{number} Terraform report failed to generate',
- 'Terraform|%{number} Terraform reports failed to generate',
- this.numberOfInvalidPlans,
- );
- },
- numberOfInvalidPlans() {
- return Object.values(this.plansObject).filter((plan) => plan.tf_report_error).length;
- },
- numberOfPlans() {
- return Object.keys(this.plansObject).length;
- },
- numberOfValidPlans() {
- return this.numberOfPlans - this.numberOfInvalidPlans;
- },
- validPlanCountText() {
- if (this.numberOfValidPlans === 0) {
- return null;
- }
-
- return n__(
- 'Terraform|%{number} Terraform report was generated in your pipelines',
- 'Terraform|%{number} Terraform reports were generated in your pipelines',
- this.numberOfValidPlans,
- );
- },
- },
- created() {
- this.fetchPlans();
- },
- beforeDestroy() {
- this.poll.stop();
- },
- methods: {
- fetchPlans() {
- this.loading = true;
-
- this.poll = new Poll({
- resource: {
- fetchPlans: () => axios.get(this.endpoint),
- },
- data: this.endpoint,
- method: 'fetchPlans',
- successCallback: ({ data }) => {
- this.plansObject = data;
-
- if (this.numberOfPlans > 0) {
- this.loading = false;
- this.poll.stop();
- }
- },
- errorCallback: () => {
- this.plansObject = { bad_plan: { tf_report_error: 'api_error' } };
- this.loading = false;
- this.poll.stop();
- },
- });
-
- this.poll.makeRequest();
- },
- },
-};
-</script>
-
-<template>
- <section class="mr-widget-section">
- <div v-if="loading" class="mr-widget-body">
- <gl-skeleton-loader />
- </div>
-
- <mr-widget-expanable-section v-else>
- <template #header>
- <div
- data-testid="terraform-header-text"
- class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column"
- >
- <p v-if="validPlanCountText" class="gl-m-0">
- <gl-sprintf :message="validPlanCountText">
- <template #number>
- <strong>{{ numberOfValidPlans }}</strong>
- </template>
- </gl-sprintf>
- </p>
-
- <p v-if="inValidPlanCountText" class="gl-m-0">
- <gl-sprintf :message="inValidPlanCountText">
- <template #number>
- <strong>{{ numberOfInvalidPlans }}</strong>
- </template>
- </gl-sprintf>
- </p>
- </div>
- </template>
-
- <template #content>
- <div class="mr-widget-body gl-pb-1">
- <terraform-plan v-for="(plan, key) in plansObject" :key="key" :plan="plan" />
- </div>
- </template>
- </mr-widget-expanable-section>
- </section>
-</template>
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
deleted file mode 100644
index 1e5f7361966..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
+++ /dev/null
@@ -1,119 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import { s__ } from '~/locale';
-
-export default {
- name: 'TerraformPlan',
- components: {
- GlIcon,
- GlLink,
- GlSprintf,
- },
- props: {
- plan: {
- required: true,
- type: Object,
- },
- },
- i18n: {
- changes: s__(
- '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 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.'),
- },
- computed: {
- addNum() {
- return Number(this.plan.create);
- },
- changeNum() {
- return Number(this.plan.update);
- },
- deleteNum() {
- return Number(this.plan.delete);
- },
- iconType() {
- return this.validPlanValues ? 'doc-changes' : 'warning';
- },
- reportChangeText() {
- if (this.validPlanValues) {
- return this.$options.i18n.changes;
- }
-
- return this.$options.i18n.generationErrored;
- },
- reportHeaderText() {
- if (this.validPlanValues) {
- return this.plan.job_name
- ? this.$options.i18n.namedReportGenerated
- : this.$options.i18n.reportGenerated;
- }
-
- return this.plan.job_name
- ? this.$options.i18n.namedReportFailed
- : this.$options.i18n.reportFailed;
- },
- validPlanValues() {
- return this.addNum + this.changeNum + this.deleteNum >= 0;
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-display-flex gl-pb-3">
- <span
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-px-2"
- >
- <gl-icon :name="iconType" :size="16" data-testid="change-type-icon" />
- </span>
-
- <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column flex-md-row gl-pl-3">
- <div class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-pr-3">
- <p class="gl-mb-3 gl-line-height-normal">
- <gl-sprintf :message="reportHeaderText">
- <template #name>
- <strong>{{ plan.job_name }}</strong>
- </template>
- </gl-sprintf>
- </p>
-
- <p class="gl-mb-3 gl-line-height-normal">
- <gl-sprintf :message="reportChangeText">
- <template #addNum>
- <strong>{{ addNum }}</strong>
- </template>
-
- <template #changeNum>
- <strong>{{ changeNum }}</strong>
- </template>
-
- <template #deleteNum>
- <strong>{{ deleteNum }}</strong>
- </template>
- </gl-sprintf>
- </p>
- </div>
-
- <div>
- <gl-link
- v-if="plan.job_path"
- :href="plan.job_path"
- target="_blank"
- data-testid="terraform-report-link"
- data-track-action="click_terraform_mr_plan_button"
- data-track-label="mr_widget_terraform_mr_plan_button"
- data-track-property="terraform_mr_plan_button"
- class="btn btn-sm"
- rel="noopener"
- >
- {{ __('View full log') }}
- <gl-icon name="external-link" />
- </gl-link>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue
new file mode 100644
index 00000000000..d1ade2886f4
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue
@@ -0,0 +1,98 @@
+<script>
+import { GlBadge, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
+import Actions from '../action_buttons.vue';
+import { generateText } from '../extensions/utils';
+import ContentRow from './widget_content_row.vue';
+
+export default {
+ name: 'DynamicContent',
+ components: {
+ GlBadge,
+ GlLink,
+ Actions,
+ ContentRow,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ props: {
+ data: {
+ type: Object,
+ required: true,
+ },
+ widgetName: {
+ type: String,
+ required: true,
+ },
+ level: {
+ type: Number,
+ required: false,
+ default: 2,
+ },
+ },
+ computed: {
+ statusIcon() {
+ return this.data.icon?.name || undefined;
+ },
+ generatedText() {
+ return generateText(this.data.text);
+ },
+ generatedSubtext() {
+ return generateText(this.data.subtext);
+ },
+ generatedSupportingText() {
+ return generateText(this.data.supportingText);
+ },
+ },
+ methods: {
+ onClickedAction(action) {
+ this.$emit('clickedAction', action);
+ },
+ },
+};
+</script>
+
+<template>
+ <content-row
+ :level="level"
+ :status-icon-name="statusIcon"
+ :widget-name="widgetName"
+ :header="data.header"
+ >
+ <template #body>
+ <div class="gl-display-flex gl-flex-direction-column">
+ <div>
+ <p v-safe-html="generatedText" class="gl-mb-0"></p>
+ <gl-link v-if="data.link" :href="data.link.href">{{ data.link.text }}</gl-link>
+ <p v-if="data.supportingText" v-safe-html="generatedSupportingText" class="gl-mb-0"></p>
+ <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
+ {{ data.badge.text }}
+ </gl-badge>
+ <actions
+ :widget="widgetName"
+ :tertiary-buttons="data.actions"
+ class="gl-ml-auto gl-pl-3"
+ @clickedAction="onClickedAction"
+ />
+ <p v-if="data.subtext" v-safe-html="generatedSubtext" class="gl-m-0 gl-font-sm"></p>
+ </div>
+ <ul
+ v-if="data.children && data.children.length > 0 && level === 2"
+ class="gl-m-0 gl-p-0 gl-list-style-none"
+ >
+ <li>
+ <dynamic-content
+ v-for="(childData, index) in data.children"
+ :key="childData.id || index"
+ :data="childData"
+ :widget-name="widgetName"
+ :level="3"
+ data-qa-selector="child_content"
+ @clickedAction="onClickedAction"
+ />
+ </li>
+ </ul>
+ </div>
+ </template>
+ </content-row>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue
new file mode 100644
index 00000000000..ff17de343d6
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { EXTENSION_ICON_CLASS, EXTENSION_ICON_NAMES } from '../../constants';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlIcon,
+ },
+ props: {
+ level: {
+ type: Number,
+ required: false,
+ default: 1,
+ },
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ iconName: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ iconAriaLabel() {
+ return `${capitalizeFirstCharacter(this.iconName)} ${this.name}`;
+ },
+ iconSize() {
+ return this.level === 1 ? 16 : 12;
+ },
+ },
+ EXTENSION_ICON_NAMES,
+ EXTENSION_ICON_CLASS,
+};
+</script>
+
+<template>
+ <div :class="[$options.EXTENSION_ICON_CLASS[iconName]]" class="gl-mr-3">
+ <gl-loading-icon v-if="isLoading" size="md" inline />
+ <div
+ v-else
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-rounded-full gl-bg-gray-10"
+ :class="{
+ 'gl-p-2': level === 1,
+ }"
+ >
+ <div class="gl-rounded-full gl-bg-white">
+ <gl-icon
+ :name="$options.EXTENSION_ICON_NAMES[iconName]"
+ :size="iconSize"
+ :aria-label="iconAriaLabel"
+ :data-qa-selector="`status_${iconName}_icon`"
+ class="gl-display-block"
+ />
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
index c9fc2dde0bd..94359d7d6ac 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -4,10 +4,11 @@ import * as Sentry from '@sentry/browser';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { sprintf, __ } from '~/locale';
import Poll from '~/lib/utils/poll';
-import StatusIcon from '../extensions/status_icon.vue';
import ActionButtons from '../action_buttons.vue';
import { EXTENSION_ICONS } from '../../constants';
-import ContentSection from './widget_content_section.vue';
+import ContentRow from './widget_content_row.vue';
+import DynamicContent from './dynamic_content.vue';
+import StatusIcon from './status_icon.vue';
const FETCH_TYPE_COLLAPSED = 'collapsed';
const FETCH_TYPE_EXPANDED = 'expanded';
@@ -18,7 +19,8 @@ export default {
StatusIcon,
GlButton,
GlLoadingIcon,
- ContentSection,
+ ContentRow,
+ DynamicContent,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -59,7 +61,7 @@ export default {
},
// If the content slot is not used, this value will be used as a fallback.
content: {
- type: Object,
+ type: Array,
required: false,
default: undefined,
},
@@ -187,7 +189,7 @@ export default {
<template>
<section class="media-section" data-testid="widget-extension">
- <div class="media gl-p-5">
+ <div class="gl-p-5 gl-align-items-center gl-display-flex">
<status-icon
:level="1"
:name="widgetName"
@@ -227,23 +229,34 @@ export default {
</div>
<div
v-if="!isCollapsed || contentError"
- class="mr-widget-grouped-section gl-relative"
+ class="gl-relative gl-bg-gray-10"
data-testid="widget-extension-collapsed-section"
>
<div v-if="isLoadingExpandedContent" class="report-block-container gl-text-center">
- <gl-loading-icon size="sm" inline /> {{ __('Loading...') }}
+ <gl-loading-icon size="sm" inline /> {{ loadingText }}
+ </div>
+ <div v-else class="gl-px-5 gl-display-flex">
+ <content-row
+ v-if="contentError"
+ :level="2"
+ :status-icon-name="$options.failedStatusIcon"
+ :widget-name="widgetName"
+ >
+ <template #body>
+ {{ contentError }}
+ </template>
+ </content-row>
+ <div v-else class="gl-w-full">
+ <slot name="content">
+ <dynamic-content
+ v-for="(data, index) in content"
+ :key="data.id || index"
+ :data="data"
+ :widget-name="widgetName"
+ />
+ </slot>
+ </div>
</div>
- <content-section
- v-else-if="contentError"
- class="report-block-container"
- :status-icon-name="$options.failedStatusIcon"
- :widget-name="widgetName"
- >
- {{ contentError }}
- </content-section>
- <slot v-else name="content">
- {{ content }}
- </slot>
</div>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue
new file mode 100644
index 00000000000..ee81f0950a8
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlSafeHtmlDirective } from '@gitlab/ui';
+import { EXTENSION_ICONS } from '../../constants';
+import { generateText } from '../extensions/utils';
+import StatusIcon from './status_icon.vue';
+
+export default {
+ components: {
+ StatusIcon,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ props: {
+ level: {
+ type: Number,
+ required: true,
+ validator: (value) => value === 2 || value === 3,
+ },
+ statusIconName: {
+ type: String,
+ default: '',
+ required: false,
+ validator: (value) => value === '' || Object.keys(EXTENSION_ICONS).includes(value),
+ },
+ widgetName: {
+ type: String,
+ required: true,
+ },
+ header: {
+ type: [String, Array],
+ default: '',
+ required: false,
+ },
+ },
+ computed: {
+ generatedHeader() {
+ return generateText(Array.isArray(this.header) ? this.header[0] : this.header);
+ },
+ generatedSubheader() {
+ return Array.isArray(this.header) && this.header[1] ? generateText(this.header[1]) : '';
+ },
+ },
+};
+</script>
+<template>
+ <div
+ class="gl-w-full gl-display-flex mr-widget-content-row gl-align-items-baseline"
+ :class="{ 'gl-border-t gl-py-3 gl-pl-7': level === 2 }"
+ >
+ <status-icon v-if="statusIconName" :level="2" :name="widgetName" :icon-name="statusIconName" />
+ <div>
+ <slot name="header">
+ <div v-if="header" class="gl-mb-2">
+ <strong v-safe-html="generatedHeader" class="gl-display-block"></strong
+ ><span
+ v-if="generatedSubheader"
+ v-safe-html="generatedSubheader"
+ class="gl-display-block"
+ ></span>
+ </div>
+ </slot>
+ <div class="gl-display-flex gl-align-items-baseline gl-w-full">
+ <slot name="body"></slot>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_section.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_section.vue
deleted file mode 100644
index 61e3744b5dc..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_section.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<script>
-import { EXTENSION_ICONS } from '../../constants';
-import StatusIcon from '../extensions/status_icon.vue';
-
-export default {
- components: {
- StatusIcon,
- },
- props: {
- statusIconName: {
- type: String,
- default: '',
- required: false,
- validator: (value) => value === '' || Object.keys(EXTENSION_ICONS).includes(value),
- },
- widgetName: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-<template>
- <div class="gl-px-7">
- <div class="gl-pl-4 gl-display-flex">
- <status-icon
- v-if="statusIconName"
- :level="2"
- :name="widgetName"
- :icon-name="statusIconName"
- />
- <slot name="default"></slot>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index be4e34ffff0..c6baf3b46ff 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -180,3 +180,16 @@ export const INVALID_RULES_DOCS_PATH = helpPagePath(
anchor: 'invalid-rules',
},
);
+
+export const DETAILED_MERGE_STATUS = {
+ MERGEABLE: 'MERGEABLE',
+ CHECKING: 'CHECKING',
+ NOT_OPEN: 'NOT_OPEN',
+ DISCUSSIONS_NOT_RESOLVED: 'DISCUSSIONS_NOT_RESOLVED',
+ NOT_APPROVED: 'NOT_APPROVED',
+ DRAFT_STATUS: 'DRAFT_STATUS',
+ BLOCKED_STATUS: 'BLOCKED_STATUS',
+ POLICIES_DENIED: 'POLICIES_DENIED',
+ CI_MUST_PASS: 'CI_MUST_PASS',
+ CI_STILL_RUNNING: 'CI_STILL_RUNNING',
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index c8a2a8d119b..a3f70b551bf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -6,7 +6,7 @@ import MrWidgetApprovals from 'ee_else_ce/vue_merge_request_widget/components/ap
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
import { stateToComponentMap as classState } from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import notify from '~/lib/utils/notify';
import { sprintf, s__, __ } from '~/locale';
@@ -86,9 +86,6 @@ export default {
import('../reports/codequality_report/grouped_codequality_reports_app.vue'),
GroupedTestReportsApp: () =>
import('../reports/grouped_test_report/grouped_test_reports_app.vue'),
- TerraformPlan: () => import('./components/terraform/mr_widget_terraform_container.vue'),
- GroupedAccessibilityReportsApp: () =>
- import('../reports/accessibility_report/grouped_accessibility_reports_app.vue'),
MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
@@ -218,12 +215,6 @@ export default {
hasAlerts() {
return this.hasMergeError || this.showMergePipelineForkWarning;
},
- shouldShowExtension() {
- return (
- window.gon?.features?.refactorMrWidgetsExtensions ||
- window.gon?.features?.refactorMrWidgetsExtensionsUser
- );
- },
shouldShowSecurityExtension() {
return window.gon?.features?.refactorSecurityExtension;
},
@@ -276,7 +267,7 @@ export default {
this.initWidget(data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Unable to load the merge request widget. Try reloading the page.'),
}),
);
@@ -368,7 +359,7 @@ export default {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
}),
);
@@ -427,7 +418,7 @@ export default {
.catch(() => this.throwDeploymentsError());
},
throwDeploymentsError() {
- createFlash({
+ createAlert({
message: __(
'Something went wrong while fetching the environments for this merge request. Please try again.',
),
@@ -447,7 +438,7 @@ export default {
}
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('Something went wrong. Please try again.'),
}),
);
@@ -506,17 +497,24 @@ export default {
eventHub.$on('DisablePolling', () => {
this.stopPolling();
});
+
+ eventHub.$on('FetchDeployments', () => {
+ this.fetchPreMergeDeployments();
+ if (this.shouldRenderMergedPipeline) {
+ this.fetchPostMergeDeployments();
+ }
+ });
},
dismissSuggestPipelines() {
this.mr.isDismissedSuggestPipeline = true;
},
registerTerraformPlans() {
- if (this.shouldRenderTerraformPlans && this.shouldShowExtension) {
+ if (this.shouldRenderTerraformPlans) {
registerExtension(terraformExtension);
}
},
registerAccessibilityExtension() {
- if (this.shouldShowAccessibilityReport && this.shouldShowExtension) {
+ if (this.shouldShowAccessibilityReport) {
registerExtension(accessibilityExtension);
}
},
@@ -620,16 +618,6 @@ export default {
:pipeline-path="mr.pipeline.path"
/>
- <terraform-plan
- v-if="mr.terraformReportsPath && !shouldShowExtension"
- :endpoint="mr.terraformReportsPath"
- />
-
- <grouped-accessibility-reports-app
- v-if="shouldShowAccessibilityReport && !shouldShowExtension"
- :endpoint="mr.accessibilityReportPath"
- />
-
<div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
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 eac72ffb2f2..516ba104d7b 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
@@ -10,6 +10,7 @@ query getState($projectPath: ID!, $iid: String!) {
availableAutoMergeStrategies
commitCount
conflicts
+ detailedMergeStatus
diffHeadSha
mergeError
mergeStatus
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 7a458f9ce7e..81cb20475cc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -1,3 +1,4 @@
+import { DETAILED_MERGE_STATUS } from '../constants';
import { stateKey } from './state_maps';
export default function deviseState() {
@@ -7,7 +8,7 @@ export default function deviseState() {
return stateKey.archived;
} else if (this.branchMissing) {
return stateKey.missingBranch;
- } else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') {
+ } else if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.CHECKING) {
return stateKey.checking;
} else if (this.hasConflicts) {
return stateKey.conflicts;
@@ -15,19 +16,20 @@ export default function deviseState() {
return stateKey.rebase;
} else if (this.hasMergeChecksFailed && !this.autoMergeEnabled) {
return stateKey.mergeChecksFailed;
- } else if (this.onlyAllowMergeIfPipelineSucceeds && this.isPipelineFailed) {
+ } else if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.CI_MUST_PASS) {
return stateKey.pipelineFailed;
- } else if (this.draft) {
+ } else if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.DRAFT_STATUS) {
return stateKey.draft;
- } else if (this.hasMergeableDiscussionsState && !this.autoMergeEnabled) {
+ } else if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.DISCUSSIONS_NOT_RESOLVED) {
return stateKey.unresolvedDiscussions;
- } else if (this.isPipelineBlocked) {
- return stateKey.pipelineBlocked;
} else if (this.canMerge && this.isSHAMismatch) {
return stateKey.shaMismatch;
} else if (this.autoMergeEnabled && !this.mergeError) {
return stateKey.autoMergeEnabled;
- } else if (this.canBeMerged) {
+ } else if (
+ this.detailedMergeStatus === DETAILED_MERGE_STATUS.MERGEABLE ||
+ this.detailedMergeStatus === DETAILED_MERGE_STATUS.CI_STILL_RUNNING
+ ) {
return stateKey.readyToMerge;
}
return null;
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 e6ff586892f..731d3886f61 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
@@ -219,6 +219,7 @@ export default class MergeRequestStore {
this.shouldBeRebased = mergeRequest.shouldBeRebased;
this.draft = mergeRequest.draft;
this.mergeRequestState = mergeRequest.state;
+ this.detailedMergeStatus = mergeRequest.detailedMergeStatus;
this.setState();
}
@@ -291,6 +292,7 @@ export default class MergeRequestStore {
this.suggestPipelineFeatureId = data.suggest_pipeline_feature_id;
this.isDismissedSuggestPipeline = data.is_dismissed_suggest_pipeline;
this.securityReportsDocsPath = data.security_reports_docs_path;
+ this.securityConfigurationPath = data.security_configuration_path;
// code quality
const blobPath = data.blob_path || {};
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index 84bd6bca601..c93057c491c 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -1,6 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import { visitUrl } from '~/lib/utils/url_utility';
+import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import CiIcon from './ci_icon.vue';
/**
* Renders CI Badge link with CI icon and status text based on
@@ -27,6 +26,7 @@ import CiIcon from './ci_icon.vue';
export default {
components: {
+ GlLink,
CiIcon,
},
directives: {
@@ -61,29 +61,21 @@ export default {
return className ? `ci-status ci-${className}` : 'ci-status';
},
},
- methods: {
- navigateToPipeline() {
- visitUrl(this.detailsPath);
-
- // event used for tracking
- this.$emit('ciStatusBadgeClick');
- },
- },
};
</script>
<template>
- <a
+ <gl-link
v-gl-tooltip
:class="cssClass"
- class="gl-cursor-pointer"
:title="title"
data-qa-selector="status_badge_link"
- @click="navigateToPipeline"
+ :href="detailsPath"
+ @click="$emit('ciStatusBadgeClick')"
>
<ci-icon :status="status" :css-classes="iconClasses" />
<template v-if="showText">
{{ status.text }}
</template>
- </a>
+ </gl-link>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/color_select_dropdown/color_select_root.vue b/app/assets/javascripts/vue_shared/components/color_select_dropdown/color_select_root.vue
index a88a4ca5cb8..75386a3cd01 100644
--- a/app/assets/javascripts/vue_shared/components/color_select_dropdown/color_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/color_select_dropdown/color_select_root.vue
@@ -1,6 +1,6 @@
<script>
import { isString } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { DEFAULT_COLOR, COLOR_WIDGET_COLOR, DROPDOWN_VARIANT, ISSUABLE_COLORS } from './constants';
@@ -97,7 +97,7 @@ export default {
return DEFAULT_COLOR;
},
error() {
- createFlash({
+ createAlert({
message: this.$options.i18n.fetchingError,
captureError: true,
});
@@ -161,7 +161,7 @@ export default {
});
})
.catch((error) =>
- createFlash({
+ createAlert({
message: this.$options.i18n.updatingError,
captureError: true,
error,
diff --git a/app/assets/javascripts/vue_shared/components/confidentiality_badge.vue b/app/assets/javascripts/vue_shared/components/confidentiality_badge.vue
index 298c7bc50cc..31c98d1e3a7 100644
--- a/app/assets/javascripts/vue_shared/components/confidentiality_badge.vue
+++ b/app/assets/javascripts/vue_shared/components/confidentiality_badge.vue
@@ -33,7 +33,7 @@ export default {
:title="confidentialTooltip"
icon="eye-slash"
variant="warning"
- class="gl-display-inline gl-mr-2"
+ class="gl-display-inline gl-mr-3"
>{{ __('Confidential') }}</gl-badge
>
</template>
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 ffe09634a3b..4873996d357 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
@@ -56,3 +56,9 @@ export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_ORGANIZATION = s__('Crm|Organization');
export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_TYPE = __('Type');
+
+// As health status gets reused between issue lists and boards
+// this is in the shared constants. Until we have not decoupled the EE filtered search bar
+// from the CE component, we need to keep this in the CE code.
+// https://gitlab.com/gitlab-org/gitlab/-/issues/377838
+export const TOKEN_TYPE_HEALTH = 'health_status';
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index e311df6e66f..8821084ef35 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
@@ -12,7 +12,7 @@ import {
import RecentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { SortDirection } from './constants';
@@ -197,7 +197,7 @@ export default {
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
- createFlash({
+ createAlert({
message: __('An error occurred while parsing recent searches'),
});
@@ -346,6 +346,11 @@ export default {
:suggestions-list-class="suggestionsListClass"
:search-button-attributes="searchButtonAttributes"
:search-input-attributes="searchInputAttributes"
+ :recent-searches-header="__('Recent searches')"
+ :clear-button-title="__('Clear')"
+ :close-button-title="__('Close')"
+ :clear-recent-searches-text="__('Clear recent searches')"
+ :no-recent-searches-text="__(`You don't have any recent searches`)"
class="flex-grow-1"
@history-item-selected="handleHistoryItemSelected"
@clear="onClear"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
index 7c4e372dda1..8a6053b7001 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -24,7 +24,7 @@ export function fetchBranches({ commit, state }, search = '') {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_BRANCHES_ERROR, status);
- createFlash({
+ createAlert({
message: __('Failed to load branches. Please try again.'),
});
});
@@ -43,7 +43,7 @@ export const fetchMilestones = ({ commit, state }, searchTitle = '') => {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_MILESTONES_ERROR, status);
- createFlash({
+ createAlert({
message: __('Failed to load milestones. Please try again.'),
});
});
@@ -61,7 +61,7 @@ export const fetchLabels = ({ commit, state }, search = '') => {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_LABELS_ERROR, status);
- createFlash({
+ createAlert({
message: __('Failed to load labels. Please try again.'),
});
});
@@ -86,7 +86,7 @@ function fetchUser(options = {}) {
.catch(({ response }) => {
const { status } = response;
commit(`RECEIVE_${action}_ERROR`, status);
- createFlash({
+ createAlert({
message: errorMessage,
});
});
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 848c49c48c7..7c184a3c391 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
@@ -1,7 +1,7 @@
<script>
import { GlAvatar, GlFilteredSearchSuggestion } from '@gitlab/ui';
import { compact } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { DEFAULT_NONE_ANY } from '../constants';
@@ -65,7 +65,7 @@ export default {
this.authors = Array.isArray(res) ? compact(res) : compact(res.data);
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was a problem fetching users.'),
}),
)
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
index aa5161ca93c..741395b3193 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
@@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -46,7 +46,7 @@ export default {
this.branches = data;
})
.catch(() => {
- createFlash({ message: __('There was a problem fetching branches.') });
+ createAlert({ message: __('There was a problem fetching branches.') });
})
.finally(() => {
this.loading = false;
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue
index adfe0559b62..d34cfb922a9 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue
@@ -3,7 +3,7 @@ import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import { ITEM_TYPE } from '~/groups/constants';
import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { isPositiveInteger } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
import searchCrmContactsQuery from '../queries/search_crm_contacts.query.graphql';
@@ -81,7 +81,7 @@ export default {
: data[this.namespace]?.contacts.nodes;
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was a problem fetching CRM contacts.'),
}),
)
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue
index e6ab944449e..c7c9350ee93 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue
@@ -3,7 +3,7 @@ import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import { ITEM_TYPE } from '~/groups/constants';
import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { isPositiveInteger } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
import searchCrmOrganizationsQuery from '../queries/search_crm_organizations.query.graphql';
@@ -78,7 +78,7 @@ export default {
: data[this.namespace]?.organizations.nodes;
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was a problem fetching CRM organizations.'),
}),
)
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
index 210d814d22a..929823f7308 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
@@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_NONE_ANY } from '../constants';
@@ -48,7 +48,7 @@ export default {
this.emojis = Array.isArray(response) ? response : response.data;
})
.catch(() => {
- createFlash({ message: __('There was a problem fetching emojis.') });
+ createAlert({ message: __('There was a problem fetching emojis.') });
})
.finally(() => {
this.loading = false;
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 178c57a5666..bce0c11aafd 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
@@ -1,7 +1,7 @@
<script>
import { GlToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
@@ -81,7 +81,7 @@ export default {
this.labels = Array.isArray(res) ? res : res.data;
})
.catch(() =>
- createFlash({
+ createAlert({
message: __('There was a problem fetching labels.'),
}),
)
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 69265d0fdc9..b9ee4d51db1 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
@@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { sortMilestonesByDueDate } from '~/milestones/utils';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -65,7 +65,7 @@ export default {
}
})
.catch(() => {
- createFlash({ message: __('There was a problem fetching milestones.') });
+ createAlert({ message: __('There was a problem fetching milestones.') });
})
.finally(() => {
this.loading = false;
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue
index 9e68c92af5d..59701b4959e 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue
@@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_NONE_ANY } from '../constants';
@@ -47,7 +47,7 @@ export default {
this.releases = response;
})
.catch(() => {
- createFlash({ message: __('There was a problem fetching releases.') });
+ createAlert({ message: __('There was a problem fetching releases.') });
})
.finally(() => {
this.loading = false;
diff --git a/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue b/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue
index 72148a0aa7c..c2be5e4f7a1 100644
--- a/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue
+++ b/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue
@@ -1,8 +1,10 @@
<script>
import { GlBadge } from '@gitlab/ui';
import { s__ } from '~/locale';
+import Tracking from '~/tracking';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
+import { helpPagePath } from '~/helpers/help_page_helper';
const STATUS_TYPES = {
SUCCESS: 'success',
@@ -10,11 +12,14 @@ const STATUS_TYPES = {
DANGER: 'danger',
};
+const UPGRADE_DOCS_URL = helpPagePath('update/index');
+
export default {
name: 'GitlabVersionCheck',
components: {
GlBadge,
},
+ mixins: [Tracking.mixin()],
props: {
size: {
type: String,
@@ -50,6 +55,10 @@ export default {
.then((res) => {
if (res.data) {
this.status = res.data.severity;
+
+ this.track('rendered_version_badge', {
+ label: this.title,
+ });
}
})
.catch(() => {
@@ -57,12 +66,24 @@ export default {
this.status = null;
});
},
+ onClick() {
+ this.track('click_version_badge', { label: this.title });
+ },
},
+ UPGRADE_DOCS_URL,
};
</script>
<template>
- <gl-badge v-if="status" class="version-check-badge" :variant="status" :size="size">{{
- title
- }}</gl-badge>
+ <!-- TODO: remove the span element once bootstrap-vue is updated to version 2.21.1 -->
+ <!-- TODO: https://github.com/bootstrap-vue/bootstrap-vue/issues/6219 -->
+ <span v-if="status" data-testid="badge-click-wrapper" @click="onClick">
+ <gl-badge
+ :href="$options.UPGRADE_DOCS_URL"
+ class="version-check-badge"
+ :variant="status"
+ :size="size"
+ >{{ title }}</gl-badge
+ >
+ </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/group_select/utils.js b/app/assets/javascripts/vue_shared/components/group_select/utils.js
new file mode 100644
index 00000000000..0a4622269f4
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/group_select/utils.js
@@ -0,0 +1,15 @@
+import Api from '~/api';
+
+export const groupsPath = (groupsFilter, parentGroupID) => {
+ if (groupsFilter !== undefined && parentGroupID === undefined) {
+ throw new Error('Cannot use groupsFilter without a parentGroupID');
+ }
+ switch (groupsFilter) {
+ case 'descendant_groups':
+ return Api.descendantGroupsPath.replace(':id', parentGroupID);
+ case 'subgroups':
+ return Api.subgroupsPath.replace(':id', parentGroupID);
+ default:
+ return Api.groupsPath;
+ }
+};
diff --git a/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js
new file mode 100644
index 00000000000..d80c1ff8b0c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js
@@ -0,0 +1,12 @@
+import { issuableTypes } from '~/boards/constants';
+import blockingIssuesQuery from './graphql/blocking_issues.query.graphql';
+import blockingEpicsQuery from './graphql/blocking_epics.query.graphql';
+
+export const blockingIssuablesQueries = {
+ [issuableTypes.issue]: {
+ query: blockingIssuesQuery,
+ },
+ [issuableTypes.epic]: {
+ query: blockingEpicsQuery,
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql
new file mode 100644
index 00000000000..4b9a9243052
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql
@@ -0,0 +1,17 @@
+query BlockingEpics($fullPath: ID!, $iid: ID) {
+ group(fullPath: $fullPath) {
+ id
+ issuable: epic(iid: $iid) {
+ id
+ blockingIssuables: blockedByEpics {
+ nodes {
+ id
+ iid
+ title
+ reference(full: true)
+ webUrl
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql
new file mode 100644
index 00000000000..279c2202740
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql
@@ -0,0 +1,14 @@
+query BlockingIssues($id: IssueID!) {
+ issuable: issue(id: $id) {
+ id
+ blockingIssuables: blockedByIssues {
+ nodes {
+ id
+ iid
+ title
+ reference(full: true)
+ webUrl
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue
new file mode 100644
index 00000000000..253aca8837d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue
@@ -0,0 +1,214 @@
+<script>
+import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
+import { issuableTypes } from '~/boards/constants';
+import { TYPE_ISSUE, TYPE_EPIC } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { truncate } from '~/lib/utils/text_utility';
+import { __, n__, s__, sprintf } from '~/locale';
+import { blockingIssuablesQueries } from './constants';
+
+export default {
+ i18n: {
+ issuableType: {
+ [issuableTypes.issue]: __('issue'),
+ [issuableTypes.epic]: __('epic'),
+ },
+ },
+ graphQLIdType: {
+ [issuableTypes.issue]: TYPE_ISSUE,
+ [issuableTypes.epic]: TYPE_EPIC,
+ },
+ referenceFormatter: {
+ [issuableTypes.issue]: (r) => r.split('/')[1],
+ },
+ defaultDisplayLimit: 3,
+ textTruncateWidth: 80,
+ components: {
+ GlIcon,
+ GlPopover,
+ GlLink,
+ GlLoadingIcon,
+ },
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ uniqueId: {
+ type: String,
+ required: true,
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ validator(value) {
+ return [issuableTypes.issue, issuableTypes.epic].includes(value);
+ },
+ },
+ },
+ apollo: {
+ blockingIssuables: {
+ skip() {
+ return this.skip;
+ },
+ query() {
+ return blockingIssuablesQueries[this.issuableType].query;
+ },
+ variables() {
+ if (this.isEpic) {
+ return {
+ fullPath: this.item.group.fullPath,
+ iid: Number(this.item.iid),
+ };
+ }
+ return {
+ id: convertToGraphQLId(this.$options.graphQLIdType[this.issuableType], this.item.id),
+ };
+ },
+ update(data) {
+ this.skip = true;
+ const issuable = this.isEpic ? data?.group?.issuable : data?.issuable;
+
+ return issuable?.blockingIssuables?.nodes || [];
+ },
+ error(error) {
+ const message = sprintf(s__('Boards|Failed to fetch blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ this.$emit('blocking-issuables-error', { error, message });
+ },
+ },
+ },
+ data() {
+ return {
+ skip: true,
+ blockingIssuables: [],
+ };
+ },
+ computed: {
+ isEpic() {
+ return this.issuableType === issuableTypes.epic;
+ },
+ displayedIssuables() {
+ const { defaultDisplayLimit, referenceFormatter } = this.$options;
+ return this.blockingIssuables.slice(0, defaultDisplayLimit).map((i) => {
+ return {
+ ...i,
+ title: truncate(i.title, this.$options.textTruncateWidth),
+ reference: this.isEpic ? i.reference : referenceFormatter[this.issuableType](i.reference),
+ };
+ });
+ },
+ loading() {
+ return this.$apollo.queries.blockingIssuables.loading;
+ },
+ issuableTypeText() {
+ return this.$options.i18n.issuableType[this.issuableType];
+ },
+ blockedLabel() {
+ return sprintf(
+ n__(
+ 'Boards|Blocked by %{blockedByCount} %{issuableType}',
+ 'Boards|Blocked by %{blockedByCount} %{issuableType}s',
+ this.item.blockedByCount,
+ ),
+ {
+ blockedByCount: this.item.blockedByCount,
+ issuableType: this.issuableTypeText,
+ },
+ );
+ },
+ blockIcon() {
+ return this.issuableType === issuableTypes.issue ? 'issue-block' : 'entity-blocked';
+ },
+ glIconId() {
+ return `blocked-icon-${this.uniqueId}`;
+ },
+ hasMoreIssuables() {
+ return this.item.blockedByCount > this.$options.defaultDisplayLimit;
+ },
+ displayedIssuablesCount() {
+ return this.hasMoreIssuables
+ ? this.item.blockedByCount - this.$options.defaultDisplayLimit
+ : this.item.blockedByCount;
+ },
+ moreIssuablesText() {
+ return sprintf(
+ n__(
+ 'Boards|+ %{displayedIssuablesCount} more %{issuableType}',
+ 'Boards|+ %{displayedIssuablesCount} more %{issuableType}s',
+ this.displayedIssuablesCount,
+ ),
+ {
+ displayedIssuablesCount: this.displayedIssuablesCount,
+ issuableType: this.issuableTypeText,
+ },
+ );
+ },
+ viewAllIssuablesText() {
+ return sprintf(s__('Boards|View all blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ },
+ loadingMessage() {
+ return sprintf(s__('Boards|Retrieving blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ },
+ },
+ methods: {
+ handleMouseEnter() {
+ this.skip = false;
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-inline">
+ <gl-icon
+ :id="glIconId"
+ ref="icon"
+ :name="blockIcon"
+ class="issuable-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500"
+ data-testid="issuable-blocked-icon"
+ @mouseenter="handleMouseEnter"
+ />
+ <gl-popover :target="glIconId" placement="top">
+ <template #title
+ ><span data-testid="popover-title">{{ blockedLabel }}</span></template
+ >
+ <template v-if="loading">
+ <gl-loading-icon size="sm" />
+ <p class="gl-mt-4 gl-mb-0 gl-font-small">{{ loadingMessage }}</p>
+ </template>
+ <template v-else>
+ <ul class="gl-list-style-none gl-p-0 gl-mb-0">
+ <li v-for="(issuable, index) in displayedIssuables" :key="issuable.id">
+ <gl-link :href="issuable.webUrl" class="gl-text-blue-500! gl-font-sm">{{
+ issuable.reference
+ }}</gl-link>
+ <p
+ class="gl-display-block!"
+ :class="{
+ 'gl-mb-3': index < displayedIssuables.length - 1,
+ 'gl-mb-0': index === displayedIssuables.length - 1,
+ }"
+ data-testid="issuable-title"
+ >
+ {{ issuable.title }}
+ </p>
+ </li>
+ </ul>
+ <div v-if="hasMoreIssuables" class="gl-mt-4">
+ <p class="gl-mb-3" data-testid="hidden-blocking-count">{{ moreIssuablesText }}</p>
+ <gl-link
+ data-testid="view-all-issues"
+ :href="`${item.webUrl}#related-issues`"
+ class="gl-text-blue-500! gl-font-sm"
+ >{{ viewAllIssuablesText }}</gl-link
+ >
+ </div>
+ </template>
+ </gl-popover>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index 926034efd10..caec49c557a 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -51,6 +51,7 @@ export default {
<gl-dropdown
:text="dropdownText"
:disabled="disabled"
+ size="small"
boundary="window"
right
lazy
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 32b3a0e22c2..657e4498b53 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -3,7 +3,7 @@ import { GlIcon, GlSafeHtmlDirective } from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { debounce, unescape } from 'lodash';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import GLForm from '~/gl_form';
import axios from '~/lib/utils/axios_utils';
import { stripHtml } from '~/lib/utils/text_utility';
@@ -272,7 +272,7 @@ export default {
this.fetchMarkdown()
.then((data) => this.renderMarkdown(data))
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error loading markdown preview'),
}),
);
@@ -315,7 +315,7 @@ export default {
this.$nextTick()
.then(() => $(this.$refs['markdown-preview']).renderGFM())
.catch(() =>
- createFlash({
+ createAlert({
message: __('Error rendering Markdown preview'),
}),
);
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 458dfe0ed23..89fffdedbfd 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -7,6 +7,8 @@ import {
ITALIC_TEXT,
STRIKETHROUGH_TEXT,
LINK_TEXT,
+ INDENT_LINE,
+ OUTDENT_LINE,
} from '~/behaviors/shortcuts/keybindings';
import { getSelectedFragment } from '~/lib/utils/common_utils';
import { s__, __ } from '~/locale';
@@ -68,12 +70,15 @@ export default {
},
computed: {
mdTable() {
+ const header = s__('MarkdownEditor|header');
+ const divider = '-'.repeat(header.length);
+ const cell = ' '.repeat(header.length);
+
return [
- // False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
- '| header | header |', // eslint-disable-line @gitlab/require-i18n-strings
- '| ------ | ------ |',
- '| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings
- '| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings
+ `| ${header} | ${header} |`,
+ `| ${divider} | ${divider} |`,
+ `| ${cell} | ${cell} |`,
+ `| ${cell} | ${cell} |`,
].join('\n');
},
mdSuggestion() {
@@ -82,7 +87,8 @@ export default {
);
},
mdCollapsibleSection() {
- return ['<details><summary>Click to expand</summary>', `{text}`, '</details>'].join('\n');
+ const expandText = s__('MarkdownEditor|Click to expand');
+ return [`<details><summary>${expandText}</summary>`, `{text}`, '</details>'].join('\n');
},
isMac() {
// Accessing properties using ?. to allow tests to use
@@ -170,6 +176,8 @@ export default {
italic: keysFor(ITALIC_TEXT),
strikethrough: keysFor(STRIKETHROUGH_TEXT),
link: keysFor(LINK_TEXT),
+ indent: keysFor(INDENT_LINE),
+ outdent: keysFor(OUTDENT_LINE),
},
i18n: {
writeTabTitle: __('Write'),
@@ -235,6 +243,7 @@ export default {
variant="confirm"
category="primary"
size="small"
+ data-qa-selector="dismiss_suggestion_popover_button"
@click="handleSuggestDismissed"
>
{{ __('Got it') }}
@@ -318,6 +327,32 @@ export default {
icon="list-task"
/>
<toolbar-button
+ v-if="!restrictedToolBarItems.includes('indent')"
+ class="gl-display-none"
+ :button-title="
+ /* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */
+ sprintf(s__('MarkdownEditor|Indent line (%{modifierKey}])'), {
+ modifierKey /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */,
+ })
+ "
+ :shortcuts="$options.shortcuts.indent"
+ command="indentLines"
+ icon="list-indent"
+ />
+ <toolbar-button
+ v-if="!restrictedToolBarItems.includes('outdent')"
+ class="gl-display-none"
+ :button-title="
+ /* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */
+ sprintf(s__('MarkdownEditor|Outdent line (%{modifierKey}[)'), {
+ modifierKey /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */,
+ })
+ "
+ :shortcuts="$options.shortcuts.outdent"
+ command="outdentLines"
+ icon="list-outdent"
+ />
+ <toolbar-button
v-if="!restrictedToolBarItems.includes('collapsible-section')"
:tag="mdCollapsibleSection"
:prepend="true"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue
new file mode 100644
index 00000000000..b38772d5aa5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue
@@ -0,0 +1,216 @@
+<script>
+import { GlSegmentedControl } from '@gitlab/ui';
+import { __ } from '~/locale';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import axios from '~/lib/utils/axios_utils';
+import { EDITING_MODE_MARKDOWN_FIELD, EDITING_MODE_CONTENT_EDITOR } from '../../constants';
+import MarkdownField from './field.vue';
+
+export default {
+ components: {
+ MarkdownField,
+ LocalStorageSync,
+ GlSegmentedControl,
+ ContentEditor: () =>
+ import(
+ /* webpackChunkName: 'content_editor' */ '~/content_editor/components/content_editor.vue'
+ ),
+ },
+ props: {
+ value: {
+ type: String,
+ required: true,
+ },
+ renderMarkdownPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ quickActionsDocsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ uploadsPath: {
+ type: String,
+ required: false,
+ default: () => window.uploads_path,
+ },
+ enableContentEditor: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ formFieldId: {
+ type: String,
+ required: true,
+ },
+ formFieldName: {
+ type: String,
+ required: true,
+ },
+ enablePreview: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ formFieldPlaceholder: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ formFieldAriaLabel: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initOnAutofocus: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ supportsQuickActions: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ editingMode: EDITING_MODE_MARKDOWN_FIELD,
+ switchEditingControlEnabled: true,
+ autofocus: this.initOnAutofocus,
+ };
+ },
+ computed: {
+ isContentEditorActive() {
+ return this.enableContentEditor && this.editingMode === EDITING_MODE_CONTENT_EDITOR;
+ },
+ contentEditorAutofocus() {
+ // Match textarea focus behavior
+ return this.autofocus ? 'end' : false;
+ },
+ },
+ mounted() {
+ this.autofocusTextarea(this.editingMode);
+ },
+ methods: {
+ updateMarkdownFromContentEditor({ markdown }) {
+ this.$emit('input', markdown);
+ },
+ updateMarkdownFromMarkdownField({ target }) {
+ this.$emit('input', target.value);
+ },
+ enableSwitchEditingControl() {
+ this.switchEditingControlEnabled = true;
+ },
+ disableSwitchEditingControl() {
+ this.switchEditingControlEnabled = false;
+ },
+ renderMarkdown(markdown) {
+ return axios.post(this.renderMarkdownPath, { text: markdown }).then(({ data }) => data.body);
+ },
+ onEditingModeChange(editingMode) {
+ this.notifyEditingModeChange(editingMode);
+ this.enableAutofocus(editingMode);
+ },
+ onEditingModeRestored(editingMode) {
+ this.notifyEditingModeChange(editingMode);
+ },
+ notifyEditingModeChange(editingMode) {
+ this.$emit(editingMode);
+ },
+ enableAutofocus(editingMode) {
+ this.autofocus = true;
+ this.autofocusTextarea(editingMode);
+ },
+ autofocusTextarea(editingMode) {
+ if (this.autofocus && editingMode === EDITING_MODE_MARKDOWN_FIELD) {
+ this.$refs.textarea.focus();
+ }
+ },
+ },
+ switchEditingControlOptions: [
+ { text: __('Source'), value: EDITING_MODE_MARKDOWN_FIELD },
+ { text: __('Rich text'), value: EDITING_MODE_CONTENT_EDITOR },
+ ],
+};
+</script>
+<template>
+ <div>
+ <div class="gl-display-flex gl-justify-content-start gl-mb-3">
+ <gl-segmented-control
+ v-model="editingMode"
+ data-testid="toggle-editing-mode-button"
+ data-qa-selector="editing_mode_button"
+ class="gl-display-flex"
+ :options="$options.switchEditingControlOptions"
+ :disabled="!enableContentEditor || !switchEditingControlEnabled"
+ @change="onEditingModeChange"
+ />
+ </div>
+ <local-storage-sync
+ v-model="editingMode"
+ storage-key="gl-wiki-content-editor-enabled"
+ @input="onEditingModeRestored"
+ />
+ <markdown-field
+ v-if="!isContentEditorActive"
+ :markdown-preview-path="renderMarkdownPath"
+ can-attach-file
+ :enable-autocomplete="enableAutocomplete"
+ :textarea-value="value"
+ :markdown-docs-path="markdownDocsPath"
+ :quick-actions-docs-path="quickActionsDocsPath"
+ :uploads-path="uploadsPath"
+ :enable-preview="enablePreview"
+ class="bordered-box"
+ >
+ <template #textarea>
+ <textarea
+ :id="formFieldId"
+ ref="textarea"
+ :value="value"
+ :name="formFieldName"
+ class="note-textarea js-gfm-input js-autosize markdown-area"
+ dir="auto"
+ :data-supports-quick-actions="supportsQuickActions"
+ data-qa-selector="markdown_editor_form_field"
+ :aria-label="formFieldAriaLabel"
+ :placeholder="formFieldPlaceholder"
+ @input="updateMarkdownFromMarkdownField"
+ @keydown="$emit('keydown', $event)"
+ >
+ </textarea>
+ </template>
+ </markdown-field>
+ <div v-else>
+ <content-editor
+ :render-markdown="renderMarkdown"
+ :uploads-path="uploadsPath"
+ :markdown="value"
+ :autofocus="contentEditorAutofocus"
+ @change="updateMarkdownFromContentEditor"
+ @loading="disableSwitchEditingControl"
+ @loadingSuccess="enableSwitchEditingControl"
+ @loadingError="enableSwitchEditingControl"
+ @keydown="$emit('keydown', $event)"
+ />
+ <input
+ :id="formFieldId"
+ :value="value"
+ :name="formFieldName"
+ data-qa-selector="markdown_editor_form_field"
+ type="hidden"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index 7646a8718d6..855c7a449c4 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -139,7 +139,7 @@ export default {
</script>
<template>
- <div class="md-suggestion-header border-bottom-0 gl-mt-3">
+ <div class="md-suggestion-header border-bottom-0 gl-px-4 gl-py-3">
<div class="js-suggestion-diff-header gl-font-weight-bold">
{{ __('Suggested change') }}
<a v-if="helpPagePath" :href="helpPagePath" :aria-label="__('Help')" class="js-help-btn">
@@ -162,6 +162,7 @@ export default {
<gl-button
class="btn-inverted js-remove-from-batch-btn btn-grouped"
:disabled="isApplying"
+ size="small"
@click="removeSuggestionFromBatch"
>
{{ __('Remove from batch') }}
@@ -172,6 +173,7 @@ export default {
class="btn-inverted js-add-to-batch-btn btn-grouped"
data-qa-selector="add_suggestion_batch_button"
:disabled="isDisableButton"
+ size="small"
@click="addSuggestionToBatch"
>
{{ __('Add suggestion to batch') }}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 9b81444fc04..30d72332c90 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -1,7 +1,7 @@
<script>
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import Vue from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import SuggestionDiff from './suggestion_diff.vue';
@@ -91,7 +91,7 @@ export default {
const suggestionElements = container.querySelectorAll('.js-render-suggestion');
if (this.lineType === 'old') {
- createFlash({
+ createAlert({
message: __('Unable to apply suggestions to a deleted line.'),
parent: this.$el,
});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
index 49217e38a1b..5ca21522d33 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -47,6 +47,11 @@ export default {
required: false,
default: 0,
},
+ command: {
+ type: String,
+ required: false,
+ default: '',
+ },
/**
* A string (or an array of strings) of
@@ -81,6 +86,7 @@ export default {
:data-md-tag-content="tagContent"
:data-md-prepend="prepend"
:data-md-shortcuts="shortcutsString"
+ :data-md-command="command"
:title="buttonTitle"
:aria-label="buttonTitle"
:icon="icon"
diff --git a/app/assets/javascripts/vue_shared/components/metric_images/store/actions.js b/app/assets/javascripts/vue_shared/components/metric_images/store/actions.js
index 832fb891838..1c4e8d332a9 100644
--- a/app/assets/javascripts/vue_shared/components/metric_images/store/actions.js
+++ b/app/assets/javascripts/vue_shared/components/metric_images/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -11,7 +11,7 @@ export const fetchImagesFactory = (service) => async ({ state, commit }) => {
commit(types.RECEIVE_METRIC_IMAGES_SUCCESS, response);
} catch (error) {
commit(types.RECEIVE_METRIC_IMAGES_ERROR);
- createFlash({ message: s__('MetricImages|There was an issue loading metric images.') });
+ createAlert({ message: s__('MetricImages|There was an issue loading metric images.') });
}
};
@@ -34,7 +34,7 @@ export const uploadImageFactory = (service) => async (
commit(types.RECEIVE_METRIC_UPLOAD_SUCCESS, response);
} catch (error) {
commit(types.RECEIVE_METRIC_UPLOAD_ERROR);
- createFlash({ message: s__('MetricImages|There was an issue uploading your image.') });
+ createAlert({ message: s__('MetricImages|There was an issue uploading your image.') });
}
};
@@ -57,7 +57,7 @@ export const updateImageFactory = (service) => async (
commit(types.RECEIVE_METRIC_UPDATE_SUCCESS, response);
} catch (error) {
commit(types.RECEIVE_METRIC_UPLOAD_ERROR);
- createFlash({ message: s__('MetricImages|There was an issue updating your image.') });
+ createAlert({ message: s__('MetricImages|There was an issue updating your image.') });
}
};
@@ -68,7 +68,7 @@ export const deleteImageFactory = (service) => async ({ state, commit }, imageId
await service.deleteMetricImage({ imageId, id: projectId, modelIid });
commit(types.RECEIVE_METRIC_DELETE_SUCCESS, imageId);
} catch (error) {
- createFlash({ message: s__('MetricImages|There was an issue deleting the image.') });
+ createAlert({ message: s__('MetricImages|There was an issue deleting the image.') });
}
};
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
index d4f50e347cb..41c92fdba4f 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -61,6 +61,11 @@ export default {
required: false,
default: 'primary',
},
+ size: {
+ type: String,
+ required: false,
+ default: 'medium',
+ },
},
computed: {
modalDomId() {
@@ -103,6 +108,9 @@ export default {
:title="title"
:aria-label="title"
:category="category"
+ :size="size"
icon="copy-to-clipboard"
- />
+ >
+ <slot></slot>
+ </gl-button>
</template>
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
deleted file mode 100644
index e9f278a5db5..00000000000
--- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
+++ /dev/null
@@ -1,208 +0,0 @@
-<script>
-import {
- GlDropdown,
- GlDropdownDivider,
- GlDropdownItem,
- GlDropdownSectionHeader,
- GlSearchBoxByType,
- GlIntersectionObserver,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export const EMPTY_NAMESPACE_ID = -1;
-export const i18n = {
- DEFAULT_TEXT: __('Select a new namespace'),
- DEFAULT_EMPTY_NAMESPACE_TEXT: __('No namespace'),
- GROUPS: __('Groups'),
- USERS: __('Users'),
-};
-
-const filterByName = (data, searchTerm = '') => {
- if (!searchTerm) {
- return data;
- }
-
- return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase()));
-};
-
-export default {
- name: 'NamespaceSelect',
- components: {
- GlDropdown,
- GlDropdownDivider,
- GlDropdownItem,
- GlDropdownSectionHeader,
- GlSearchBoxByType,
- GlIntersectionObserver,
- GlLoadingIcon,
- },
- props: {
- groupNamespaces: {
- type: Array,
- required: false,
- default: () => [],
- },
- userNamespaces: {
- type: Array,
- required: false,
- default: () => [],
- },
- fullWidth: {
- type: Boolean,
- required: false,
- default: false,
- },
- defaultText: {
- type: String,
- required: false,
- default: i18n.DEFAULT_TEXT,
- },
- includeHeaders: {
- type: Boolean,
- required: false,
- default: true,
- },
- emptyNamespaceTitle: {
- type: String,
- required: false,
- default: i18n.DEFAULT_EMPTY_NAMESPACE_TEXT,
- },
- includeEmptyNamespace: {
- type: Boolean,
- required: false,
- default: false,
- },
- hasNextPageOfGroups: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoadingMoreGroups: {
- type: Boolean,
- required: false,
- default: false,
- },
- isSearchLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- shouldFilterNamespaces: {
- type: Boolean,
- required: false,
- default: true,
- },
- },
- data() {
- return {
- searchTerm: '',
- selectedNamespace: null,
- };
- },
- computed: {
- hasUserNamespaces() {
- return this.userNamespaces.length;
- },
- hasGroupNamespaces() {
- return this.groupNamespaces.length;
- },
- filteredGroupNamespaces() {
- if (!this.shouldFilterNamespaces) return this.groupNamespaces;
- if (!this.hasGroupNamespaces) return [];
- return filterByName(this.groupNamespaces, this.searchTerm);
- },
- filteredUserNamespaces() {
- if (!this.shouldFilterNamespaces) return this.userNamespaces;
- if (!this.hasUserNamespaces) return [];
- return filterByName(this.userNamespaces, this.searchTerm);
- },
- selectedNamespaceText() {
- return this.selectedNamespace?.humanName || this.defaultText;
- },
- filteredEmptyNamespaceTitle() {
- const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
-
- if (!includeEmptyNamespace) {
- return '';
- }
- if (!searchTerm) {
- return emptyNamespaceTitle;
- }
-
- return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase());
- },
- },
- watch: {
- searchTerm() {
- this.$emit('search', this.searchTerm);
- },
- },
- methods: {
- handleSelect(item) {
- this.selectedNamespace = item;
- this.searchTerm = '';
- this.$emit('select', item);
- },
- handleSelectEmptyNamespace() {
- this.handleSelect({ id: EMPTY_NAMESPACE_ID, humanName: this.emptyNamespaceTitle });
- },
- },
- i18n,
-};
-</script>
-<template>
- <gl-dropdown :text="selectedNamespaceText" :block="fullWidth" data-qa-selector="namespaces_list">
- <template #header>
- <gl-search-box-by-type
- v-model.trim="searchTerm"
- :is-loading="isSearchLoading"
- data-qa-selector="namespaces_list_search"
- />
- </template>
- <div v-if="filteredEmptyNamespaceTitle">
- <gl-dropdown-item
- data-qa-selector="namespaces_list_item"
- @click="handleSelectEmptyNamespace()"
- >
- {{ emptyNamespaceTitle }}
- </gl-dropdown-item>
- <gl-dropdown-divider />
- </div>
- <div
- v-if="hasUserNamespaces"
- data-qa-selector="namespaces_list_users"
- data-testid="namespace-list-users"
- >
- <gl-dropdown-section-header v-if="includeHeaders">{{
- $options.i18n.USERS
- }}</gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="item in filteredUserNamespaces"
- :key="item.id"
- data-qa-selector="namespaces_list_item"
- @click="handleSelect(item)"
- >{{ item.humanName }}</gl-dropdown-item
- >
- </div>
- <div
- v-if="hasGroupNamespaces"
- data-qa-selector="namespaces_list_groups"
- data-testid="namespace-list-groups"
- >
- <gl-dropdown-section-header v-if="includeHeaders">{{
- $options.i18n.GROUPS
- }}</gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="item in filteredGroupNamespaces"
- :key="item.id"
- data-qa-selector="namespaces_list_item"
- @click="handleSelect(item)"
- >{{ item.humanName }}</gl-dropdown-item
- >
- </div>
- <gl-intersection-observer v-if="hasNextPageOfGroups" @appear="$emit('load-more-groups')">
- <gl-loading-icon v-if="isLoadingMoreGroups" class="gl-mb-3" size="sm" />
- </gl-intersection-observer>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select_deprecated.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select_deprecated.vue
new file mode 100644
index 00000000000..ba9edc7620a
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select_deprecated.vue
@@ -0,0 +1,212 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export const EMPTY_NAMESPACE_ID = -1;
+export const i18n = {
+ DEFAULT_TEXT: __('Select a new namespace'),
+ DEFAULT_EMPTY_NAMESPACE_TEXT: __('No namespace'),
+ GROUPS: __('Groups'),
+ USERS: __('Users'),
+};
+
+const filterByName = (data, searchTerm = '') => {
+ if (!searchTerm) {
+ return data;
+ }
+
+ return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase()));
+};
+
+export default {
+ name: 'NamespaceSelectDeprecated',
+ components: {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
+ },
+ props: {
+ groupNamespaces: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ userNamespaces: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ fullWidth: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ defaultText: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_TEXT,
+ },
+ includeHeaders: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ emptyNamespaceTitle: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_EMPTY_NAMESPACE_TEXT,
+ },
+ includeEmptyNamespace: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ hasNextPageOfGroups: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isSearchLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ shouldFilterNamespaces: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ selectedNamespace: null,
+ };
+ },
+ computed: {
+ hasUserNamespaces() {
+ return this.userNamespaces.length;
+ },
+ hasGroupNamespaces() {
+ return this.groupNamespaces.length;
+ },
+ filteredGroupNamespaces() {
+ if (!this.shouldFilterNamespaces) return this.groupNamespaces;
+ if (!this.hasGroupNamespaces) return [];
+ return filterByName(this.groupNamespaces, this.searchTerm);
+ },
+ filteredUserNamespaces() {
+ if (!this.shouldFilterNamespaces) return this.userNamespaces;
+ if (!this.hasUserNamespaces) return [];
+ return filterByName(this.userNamespaces, this.searchTerm);
+ },
+ selectedNamespaceText() {
+ return this.selectedNamespace?.humanName || this.defaultText;
+ },
+ filteredEmptyNamespaceTitle() {
+ const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
+
+ if (!includeEmptyNamespace) {
+ return '';
+ }
+ if (!searchTerm) {
+ return emptyNamespaceTitle;
+ }
+
+ return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase());
+ },
+ },
+ watch: {
+ searchTerm() {
+ this.$emit('search', this.searchTerm);
+ },
+ },
+ methods: {
+ handleSelect(item) {
+ this.selectedNamespace = item;
+ this.searchTerm = '';
+ this.$emit('select', item);
+ },
+ handleSelectEmptyNamespace() {
+ this.handleSelect({ id: EMPTY_NAMESPACE_ID, humanName: this.emptyNamespaceTitle });
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <gl-dropdown
+ :text="selectedNamespaceText"
+ :block="fullWidth"
+ data-qa-selector="namespaces_list"
+ @show="$emit('show')"
+ >
+ <template #header>
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ :is-loading="isSearchLoading"
+ data-qa-selector="namespaces_list_search"
+ />
+ </template>
+ <div v-if="filteredEmptyNamespaceTitle">
+ <gl-dropdown-item
+ data-qa-selector="namespaces_list_item"
+ @click="handleSelectEmptyNamespace()"
+ >
+ {{ emptyNamespaceTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </div>
+ <div
+ v-if="hasUserNamespaces"
+ data-qa-selector="namespaces_list_users"
+ data-testid="namespace-list-users"
+ >
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.USERS
+ }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="item in filteredUserNamespaces"
+ :key="item.id"
+ data-qa-selector="namespaces_list_item"
+ @click="handleSelect(item)"
+ >{{ item.humanName }}</gl-dropdown-item
+ >
+ </div>
+ <div
+ v-if="hasGroupNamespaces"
+ data-qa-selector="namespaces_list_groups"
+ data-testid="namespace-list-groups"
+ >
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.GROUPS
+ }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="item in filteredGroupNamespaces"
+ :key="item.id"
+ data-qa-selector="namespaces_list_item"
+ @click="handleSelect(item)"
+ >{{ item.humanName }}</gl-dropdown-item
+ >
+ </div>
+ <gl-loading-icon v-if="isLoading" class="gl-mb-3" size="sm" />
+ <gl-intersection-observer v-if="hasNextPageOfGroups" @appear="$emit('load-more-groups')" />
+ </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 0cb4a5bc39f..cf34a60c363 100644
--- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
@@ -50,29 +50,19 @@ export default {
renderedNote() {
return renderMarkdown(this.note.body);
},
- avatarSize() {
- if (this.line && !this.isOverviewTab) {
- return 24;
- }
-
- return {
- default: 24,
- md: 32,
- };
- },
},
};
</script>
<template>
- <timeline-entry-item class="note note-wrapper being-posted fade-in-half">
- <div class="timeline-icon">
- <gl-avatar-link class="gl-mr-3" :href="getUserData.path">
+ <timeline-entry-item class="note note-wrapper note-comment being-posted fade-in-half">
+ <div class="timeline-avatar gl-float-left">
+ <gl-avatar-link :href="getUserData.path">
<gl-avatar
:src="getUserData.avatar_url"
:entity-name="getUserData.username"
:alt="getUserData.name"
- :size="avatarSize"
+ :size="32"
/>
</gl-avatar-link>
</div>
@@ -85,8 +75,10 @@ export default {
</a>
</div>
</div>
- <div class="note-body">
- <div v-safe-html="renderedNote" class="note-text md"></div>
+ <div class="timeline-discussion-body">
+ <div class="note-body">
+ <div v-safe-html="renderedNote" class="note-text md"></div>
+ </div>
</div>
</div>
</timeline-entry-item>
diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
index 2206ae98c73..e091fe74717 100644
--- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
@@ -16,7 +16,7 @@ export default {
<div class="timeline-icon"></div>
<div class="timeline-content">
<div class="note-header"></div>
- <div class="note-body"><gl-skeleton-loader /></div>
+ <div class="note-body gl-mt-4"><gl-skeleton-loader /></div>
</div>
</timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 7e99f1b01b2..1ae5045b34f 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -129,7 +129,12 @@ export default {
<div v-safe-html:[$options.safeHtmlConfig]="iconHtml" class="timeline-icon"></div>
<div class="timeline-content">
<div class="note-header">
- <note-header :author="note.author" :created-at="note.created_at" :note-id="note.id">
+ <note-header
+ :author="note.author"
+ :created-at="note.created_at"
+ :note-id="note.id"
+ :is-system-note="true"
+ >
<span ref="gfm-content" v-safe-html="actionTextHtml"></span>
<template
v-if="canSeeDescriptionVersion || note.outdated_line_change_path"
@@ -141,7 +146,7 @@ export default {
variant="link"
:icon="descriptionVersionToggleIcon"
data-testid="compare-btn"
- class="gl-vertical-align-text-bottom"
+ class="gl-vertical-align-text-bottom gl-font-sm!"
@click="toggleDescriptionVersion"
>{{ __('Compare with previous version') }}</gl-button
>
@@ -150,7 +155,7 @@ export default {
:icon="showLines ? 'chevron-up' : 'chevron-down'"
variant="link"
data-testid="outdated-lines-change-btn"
- class="gl-vertical-align-text-bottom"
+ class="gl-vertical-align-text-bottom gl-font-sm!"
@click="toggleDiff"
>
{{ __('Compare changes') }}
@@ -190,7 +195,7 @@ export default {
</div>
<div
v-if="lines.length && showLines"
- class="diff-content gl-border-solid gl-border-1 gl-border-gray-200 gl-mt-4 gl-rounded-small gl-overflow-hidden"
+ class="diff-content outdated-lines-wrapper gl-border-solid gl-border-1 gl-border-gray-200 gl-mt-4 gl-rounded-small gl-overflow-hidden"
>
<table
:class="$options.userColorSchemeClass"
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/constants.js b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/constants.js
index b7768cfa5b9..df1188d365b 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/constants.js
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/constants.js
@@ -4,7 +4,7 @@ export const tdClass =
'table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap';
export const thClass = 'gl-hover-bg-blue-50';
export const bodyTrClass =
- 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-cursor-pointer gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200';
+ 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-cursor-pointer gl-hover-bg-gray-50 gl-hover-border-b-solid';
export const defaultPageSize = 20;
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
index 6867b5a75e3..a5027d2ca5c 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
@@ -275,7 +275,7 @@ export default {
<template>
<div class="incident-management-list">
<gl-alert v-if="showErrorMsg" variant="danger" @dismiss="$emit('error-alert-dismissed')">
- <p v-safe-html="serverErrorMessage || i18n.errorMsg"></p>
+ <span v-safe-html="serverErrorMessage || i18n.errorMsg"></span>
</gl-alert>
<div
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
index b4d565991f5..c1246b2bf44 100644
--- a/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue
+++ b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue
@@ -2,6 +2,7 @@
import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
const DEFAULT_PAGE_SIZES = [20, 50, 100];
@@ -12,6 +13,7 @@ export default {
GlDropdownItem,
GlIcon,
GlSprintf,
+ LocalStorageSync,
},
props: {
pageInfo: {
@@ -23,6 +25,11 @@ export default {
type: Array,
default: () => DEFAULT_PAGE_SIZES,
},
+ storageKey: {
+ required: false,
+ type: String,
+ default: null,
+ },
},
computed: {
@@ -66,6 +73,12 @@ export default {
<template>
<div class="gl-display-flex gl-align-items-center">
+ <local-storage-sync
+ v-if="storageKey"
+ :storage-key="storageKey"
+ :value="pageInfo.perPage"
+ @input="setPageSize"
+ />
<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>
diff --git a/app/assets/javascripts/vue_shared/components/registry/history_item.vue b/app/assets/javascripts/vue_shared/components/registry/history_item.vue
index a60b630b207..384b084ce09 100644
--- a/app/assets/javascripts/vue_shared/components/registry/history_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/history_item.vue
@@ -18,15 +18,15 @@ export default {
</script>
<template>
- <timeline-entry-item class="system-note note-wrapper gl-mb-6!">
+ <timeline-entry-item class="system-note note-wrapper">
<div class="timeline-icon">
<gl-icon :name="icon" />
</div>
<div class="timeline-content">
<div class="note-header">
- <span>
+ <div class="note-header-info">
<slot></slot>
- </span>
+ </div>
</div>
<div class="note-body">
<slot name="body"></slot>
diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
index 1948a6778f4..8c9c7c63db1 100644
--- a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
@@ -1,6 +1,7 @@
<script>
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import { SORT_DIRECTION_UI } from '~/search/sort/constants';
const ASCENDING_ORDER = 'asc';
const DESCENDING_ORDER = 'desc';
@@ -52,6 +53,9 @@ export default {
return acc;
}, {});
},
+ sortDirectionData() {
+ return this.isSortAscending ? SORT_DIRECTION_UI.asc : SORT_DIRECTION_UI.desc;
+ },
},
methods: {
generateQueryData({ sorting = {}, filter = [] } = {}) {
@@ -119,6 +123,7 @@ export default {
data-testid="registry-sort-dropdown"
:text="sortText"
:is-ascending="isSortAscending"
+ :sort-direction-tool-tip="sortDirectionData.tooltip"
@sortDirectionChange="onDirectionChange"
>
<gl-sorting-item
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 b61996cdcdb..e6c29e24f0c 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
@@ -53,6 +53,11 @@ export default {
required: false,
default: false,
},
+ allowMultipleScopedLabels: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
variant: {
type: String,
required: false,
@@ -164,6 +169,7 @@ export default {
allowLabelCreate: this.allowLabelCreate,
allowMultiselect: this.allowMultiselect,
allowScopedLabels: this.allowScopedLabels,
+ allowMultipleScopedLabels: this.allowMultipleScopedLabels,
dropdownButtonText: this.dropdownButtonText,
selectedLabels: this.selectedLabels,
labelsFetchPath: this.labelsFetchPath,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
index 0c697e624ab..2dab97826b9 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
@@ -1,4 +1,4 @@
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -16,7 +16,7 @@ export const receiveLabelsSuccess = ({ commit }, labels) =>
commit(types.RECEIVE_SET_LABELS_SUCCESS, labels);
export const receiveLabelsFailure = ({ commit }) => {
commit(types.RECEIVE_SET_LABELS_FAILURE);
- createFlash({
+ createAlert({
message: __('Error fetching labels.'),
});
};
@@ -38,7 +38,7 @@ export const requestCreateLabel = ({ commit }) => commit(types.REQUEST_CREATE_LA
export const receiveCreateLabelSuccess = ({ commit }) => commit(types.RECEIVE_CREATE_LABEL_SUCCESS);
export const receiveCreateLabelFailure = ({ commit }) => {
commit(types.RECEIVE_CREATE_LABEL_FAILURE);
- createFlash({
+ createAlert({
message: __('Error creating label.'),
});
};
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
index 43b23994cdf..c85d9befcbb 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
@@ -94,14 +94,13 @@ export default {
candidateLabel.indeterminate = false;
}
- if (isScopedLabel(candidateLabel)) {
+ if (isScopedLabel(candidateLabel) && !state.allowMultipleScopedLabels) {
const currentActiveScopedLabel = state.labels.find(
({ set, title }) =>
set &&
title !== candidateLabel.title &&
scopedLabelKey({ title }) === scopedLabelKey(candidateLabel),
);
-
if (currentActiveScopedLabel) {
currentActiveScopedLabel.set = false;
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
index 5f344ae4214..ce93ad216ec 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
@@ -8,7 +8,7 @@ import {
GlLoadingIcon,
} from '@gitlab/ui';
import produce from 'immer';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { __ } from '~/locale';
import { workspaceLabelsQueries } from '~/sidebar/constants';
import createLabelMutation from './graphql/create_label.mutation.graphql';
@@ -129,7 +129,7 @@ export default {
this.$emit('hideCreateView');
}
} catch {
- createFlash({ message: errorMessage });
+ createAlert({ message: errorMessage });
}
this.labelCreateInProgress = false;
},
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index 8d3d4d5f86a..1d854505d11 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdownForm, GlDropdownItem, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import { workspaceLabelsQueries } from '~/sidebar/constants';
@@ -62,7 +62,7 @@ export default {
},
update: (data) => data.workspace?.labels?.nodes || [],
error() {
- createFlash({ message: __('Error fetching labels.') });
+ createAlert({ message: __('Error fetching 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 522fbc07f5e..0e8da7281d8 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,7 +2,7 @@
import { debounce } from 'lodash';
import issuableLabelsSubscription from 'ee_else_ce/sidebar/queries/issuable_labels.subscription.graphql';
import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { IssuableType } from '~/issues/constants';
@@ -151,7 +151,7 @@ export default {
return data.workspace?.issuable;
},
error() {
- createFlash({ message: __('Error fetching labels.') });
+ createAlert({ message: __('Error fetching labels.') });
},
subscribeToMore: {
document() {
@@ -275,7 +275,7 @@ export default {
});
})
.catch((error) =>
- createFlash({
+ createAlert({
message: __('An error occurred while updating labels.'),
captureError: true,
error,
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 445817d3e52..eae5e96ac46 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
@@ -1,7 +1,7 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
-query issueParticipants($fullPath: ID!, $iid: String!) {
+query issueParticipants($fullPath: ID!, $iid: String!, $getStatus: Boolean = false) {
workspace: project(fullPath: $fullPath) {
id
issuable: issue(iid: $iid) {
@@ -9,7 +9,7 @@ query issueParticipants($fullPath: ID!, $iid: String!) {
participants {
nodes {
...User
- ...UserAvailability
+ ...UserAvailability @include(if: $getStatus)
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql
index 05de680ab05..f087ca6c982 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql
@@ -19,7 +19,7 @@ query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
}
}
userPermissions {
- updateMergeRequest
+ adminMergeRequest
}
}
}
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 3496d5f4a2e..2781ac71f31 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
@@ -1,7 +1,7 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
-query getMrParticipants($fullPath: ID!, $iid: String!) {
+query getMrParticipants($fullPath: ID!, $iid: String!, $getStatus: Boolean = false) {
workspace: project(fullPath: $fullPath) {
id
issuable: mergeRequest(iid: $iid) {
@@ -9,7 +9,7 @@ query getMrParticipants($fullPath: ID!, $iid: String!) {
participants {
nodes {
...User
- ...UserAvailability
+ ...UserAvailability @include(if: $getStatus)
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue
index 257b9f57222..ffd0eea63a1 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue
@@ -1,8 +1,6 @@
<script>
import { GlSafeHtmlDirective } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { setAttributes } from '~/lib/utils/dom_utils';
-import { BIDI_CHARS, BIDI_CHARS_CLASS_LIST, BIDI_CHAR_TOOLTIP } from '../constants';
export default {
directives: {
@@ -27,34 +25,6 @@ export default {
required: true,
},
},
- computed: {
- formattedContent() {
- let { content } = this;
-
- BIDI_CHARS.forEach((bidiChar) => {
- if (content.includes(bidiChar)) {
- content = content.replace(bidiChar, this.wrapBidiChar(bidiChar));
- }
- });
-
- return content;
- },
- },
- methods: {
- wrapBidiChar(bidiChar) {
- const span = document.createElement('span');
-
- setAttributes(span, {
- class: BIDI_CHARS_CLASS_LIST,
- title: BIDI_CHAR_TOOLTIP,
- 'data-testid': 'bidi-wrapper',
- });
-
- span.innerText = bidiChar;
-
- return span.outerHTML;
- },
- },
};
</script>
<template>
@@ -78,7 +48,7 @@ export default {
</div>
<pre
- class="gl-p-0! gl-w-full gl-overflow-visible! gl-border-none! code highlight gl-line-height-normal"
- ><code><span :id="`LC${number}`" v-safe-html="formattedContent" :lang="language" class="line" data-testid="content"></span></code></pre>
+ class="gl-p-0! gl-w-full gl-overflow-visible! gl-border-none! code highlight gl-line-height-0"
+ ><code><span :id="`LC${number}`" v-safe-html="content" :lang="language" class="line" data-testid="content"></span></code></pre>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
index 30f57f506a6..a28460dd58e 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
@@ -1,5 +1,3 @@
-import { __ } from '~/locale';
-
// Language map from Rouge::Lexer to highlight.js
// Rouge::Lexer - We use it on the BE to determine the language of a source file (https://github.com/rouge-ruby/rouge/blob/master/docs/Languages.md).
// Highlight.js - We use it on the FE to highlight the syntax of a source file (https://github.com/highlightjs/highlight.js/tree/main/src/languages).
@@ -139,13 +137,6 @@ export const BIDI_CHARS = [
export const BIDI_CHARS_CLASS_LIST = 'unicode-bidi has-tooltip';
-export const BIDI_CHAR_TOOLTIP = __(
- 'Potentially unwanted character detected: Unicode BiDi Control',
-);
-
-export const HLJS_COMMENT_SELECTOR = 'hljs-comment';
+export const BIDI_CHAR_TOOLTIP = 'Potentially unwanted character detected: Unicode BiDi Control';
export const HLJS_ON_AFTER_HIGHLIGHT = 'after:highlight';
-
-export const NPM_URL = 'https://npmjs.com/package';
-export const GEM_URL = 'https://rubygems.org/gems';
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js
index 5d24a3d110b..d694adf7147 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js
@@ -1,6 +1,8 @@
-import { HLJS_ON_AFTER_HIGHLIGHT } from '../constants';
-import wrapComments from './wrap_comments';
+import wrapChildNodes from './wrap_child_nodes';
import linkDependencies from './link_dependencies';
+import wrapBidiChars from './wrap_bidi_chars';
+
+export const HLJS_ON_AFTER_HIGHLIGHT = 'after:highlight';
/**
* Registers our plugins for Highlight.js
@@ -10,7 +12,8 @@ import linkDependencies from './link_dependencies';
* @param {Object} hljs - the Highlight.js instance.
*/
export const registerPlugins = (hljs, fileType, rawContent) => {
- hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapComments });
+ hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapChildNodes });
+ hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapBidiChars });
hljs.addPlugin({
[HLJS_ON_AFTER_HIGHLIGHT]: (result) => linkDependencies(result, fileType, rawContent),
});
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js
index dbe6812cf16..49704421d6e 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js
@@ -1,16 +1,7 @@
import { escape } from 'lodash';
-import { setAttributes } from '~/lib/utils/dom_utils';
-export const createLink = (href, innerText) => {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- const rel = 'nofollow noreferrer noopener';
- const link = document.createElement('a');
-
- setAttributes(link, { href: escape(href), rel });
- link.textContent = innerText;
-
- return link.outerHTML;
-};
+export const createLink = (href, innerText) =>
+ `<a href="${escape(href)}" rel="nofollow noreferrer noopener">${escape(innerText)}</a>`;
export const generateHLJSOpenTag = (type, delimiter = '&quot;') =>
`<span class="hljs-${escape(type)}">${delimiter}`;
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js
index 35de8fd13d6..46c9dc38300 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js
@@ -1,7 +1,6 @@
-import { joinPaths } from '~/lib/utils/url_utility';
-import { GEM_URL } from '../../constants';
import { createLink, generateHLJSOpenTag } from './dependency_linker_util';
+const GEM_URL = 'https://rubygems.org/gems/';
const methodRegex = '.*add_dependency.*|.*add_runtime_dependency.*|.*add_development_dependency.*';
const openTagRegex = generateHLJSOpenTag('string', '(&.*;)');
const closeTagRegex = '&.*</span>';
@@ -24,7 +23,7 @@ const DEPENDENCY_REGEX = new RegExp(
const handleReplace = (method, delimiter, packageName, closeTag, rest) => {
// eslint-disable-next-line @gitlab/require-i18n-strings
const openTag = generateHLJSOpenTag('string linked', delimiter);
- const href = joinPaths(GEM_URL, packageName);
+ const href = `${GEM_URL}${packageName}`;
const packageLink = createLink(href, packageName);
return `${method}${openTag}${packageLink}${closeTag}${rest}`;
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js
index 3c6fc23c138..4bfd5ec2431 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js
@@ -1,8 +1,7 @@
import { unescape } from 'lodash';
-import { joinPaths } from '~/lib/utils/url_utility';
-import { NPM_URL } from '../../constants';
import { createLink, generateHLJSOpenTag } from './dependency_linker_util';
+const NPM_URL = 'https://npmjs.com/package/';
const attrOpenTag = generateHLJSOpenTag('attr');
const stringOpenTag = generateHLJSOpenTag('string');
const closeTag = '&quot;</span>';
@@ -20,7 +19,7 @@ const DEPENDENCY_REGEX = new RegExp(
const handleReplace = (original, packageName, version, dependenciesToLink) => {
const unescapedPackageName = unescape(packageName);
const unescapedVersion = unescape(version);
- const href = joinPaths(NPM_URL, unescapedPackageName);
+ const href = `${NPM_URL}${unescapedPackageName}`;
const packageLink = createLink(href, unescapedPackageName);
const versionLink = createLink(href, unescapedVersion);
const closeAndOpenTag = `${closeTag}: ${attrOpenTag}`;
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_bidi_chars.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_bidi_chars.js
new file mode 100644
index 00000000000..3b6cd96ef78
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_bidi_chars.js
@@ -0,0 +1,30 @@
+import {
+ BIDI_CHARS,
+ BIDI_CHARS_CLASS_LIST,
+ BIDI_CHAR_TOOLTIP,
+} from '~/vue_shared/components/source_viewer/constants';
+
+/**
+ * Highlight.js plugin for wrapping BIDI chars.
+ * This ensures potentially dangerous BIDI characters are highlighted.
+ *
+ * Plugin API: https://github.com/highlightjs/highlight.js/blob/main/docs/plugin-api.rst
+ *
+ * @param {Object} Result - an object that represents the highlighted result from Highlight.js
+ */
+
+function wrapBidiChar(bidiChar) {
+ return `<span class="${BIDI_CHARS_CLASS_LIST}" title="${BIDI_CHAR_TOOLTIP}">${bidiChar}</span>`;
+}
+
+export default (result) => {
+ let { value } = result;
+ BIDI_CHARS.forEach((bidiChar) => {
+ if (value.includes(bidiChar)) {
+ value = value.replace(bidiChar, wrapBidiChar(bidiChar));
+ }
+ });
+
+ // eslint-disable-next-line no-param-reassign
+ result.value = value; // Highlight.js expects the result param to be mutated for plugins to work
+};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js
new file mode 100644
index 00000000000..e0ba4b730a7
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js
@@ -0,0 +1,45 @@
+import { escape } from 'lodash';
+
+/**
+ * Highlight.js plugin for wrapping nodes with the correct selectors to ensure
+ * child-elements are highlighted correctly after we split up the result into chunks and lines.
+ *
+ * Plugin API: https://github.com/highlightjs/highlight.js/blob/main/docs/plugin-api.rst
+ *
+ * @param {Object} Result - an object that represents the highlighted result from Highlight.js
+ */
+const newlineRegex = /\r?\n/;
+const generateClassName = (suffix) => (suffix ? `hljs-${escape(suffix)}` : '');
+const generateCloseTag = (includeClose) => (includeClose ? '</span>' : '');
+const generateHLJSTag = (kind, content = '', includeClose) =>
+ `<span class="${generateClassName(kind)}">${escape(content)}${generateCloseTag(includeClose)}`;
+
+const format = (node, kind = '') => {
+ let buffer = '';
+
+ if (typeof node === 'string') {
+ buffer += node
+ .split(newlineRegex)
+ .map((newline) => generateHLJSTag(kind, newline, true))
+ .join('\n');
+ } else if (node.kind) {
+ const { children } = node;
+ if (children.length && children.length === 1) {
+ buffer += format(children[0], node.kind);
+ } else {
+ buffer += generateHLJSTag(node.kind);
+ children.forEach((subChild) => {
+ buffer += format(subChild, node.kind);
+ });
+ buffer += `</span>`;
+ }
+ }
+
+ return buffer;
+};
+
+export default (result) => {
+ // NOTE: We're using the private Emitter API here as we expect the Emitter API to be publicly available soon (https://github.com/highlightjs/highlight.js/issues/3621)
+ // eslint-disable-next-line no-param-reassign, no-underscore-dangle
+ result.value = result._emitter.rootNode.children.reduce((val, node) => val + format(node), ''); // Highlight.js expects the result param to be mutated for plugins to work
+};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js
deleted file mode 100644
index 8b52df83fdf..00000000000
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { HLJS_COMMENT_SELECTOR } from '../constants';
-
-const createWrapper = (content) => {
- const span = document.createElement('span');
- span.className = HLJS_COMMENT_SELECTOR;
-
- // eslint-disable-next-line no-unsanitized/property
- span.innerHTML = content;
- return span.outerHTML;
-};
-
-/**
- * Highlight.js plugin for wrapping multi-line comments in the `hljs-comment` class.
- * This ensures that multi-line comments are rendered correctly in the GitLab UI.
- *
- * Plugin API: https://github.com/highlightjs/highlight.js/blob/main/docs/plugin-api.rst
- *
- * @param {Object} Result - an object that represents the highlighted result from Highlight.js
- */
-export default (result) => {
- if (!result.value.includes(HLJS_COMMENT_SELECTOR)) return;
-
- let wrapComment = false;
-
- // eslint-disable-next-line no-param-reassign
- result.value = result.value // Highlight.js expects the result param to be mutated for plugins to work
- .split('\n')
- .map((lineContent) => {
- const includesClosingTag = lineContent.includes('</span>');
- if (lineContent.includes(HLJS_COMMENT_SELECTOR) && !includesClosingTag) {
- wrapComment = true;
- return lineContent;
- }
- const line = wrapComment ? createWrapper(lineContent) : lineContent;
- if (includesClosingTag) {
- wrapComment = false;
- }
- return line;
- })
- .join('\n');
-};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
index 9c6c12eac7d..536b2c8a281 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
@@ -53,7 +53,7 @@ export default {
},
computed: {
splitContent() {
- return this.content.split('\n');
+ return this.content.split(/\r?\n/);
},
lineNumbers() {
return this.splitContent.length;
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight.js b/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight.js
new file mode 100644
index 00000000000..535e857d7a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight.js
@@ -0,0 +1,10 @@
+import { highlight } from './highlight_utils';
+
+/**
+ * A webworker for highlighting large amounts of content with Highlight.js
+ */
+// eslint-disable-next-line no-restricted-globals
+self.addEventListener('message', ({ data: { fileType, content, language } }) => {
+ // eslint-disable-next-line no-restricted-globals
+ self.postMessage(highlight(fileType, content, language));
+});
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight_utils.js b/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight_utils.js
new file mode 100644
index 00000000000..0da57f9e6fa
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/workers/highlight_utils.js
@@ -0,0 +1,15 @@
+import hljs from 'highlight.js/lib/core';
+import languageLoader from '~/content_editor/services/highlight_js_language_loader';
+import { registerPlugins } from '../plugins/index';
+
+const initHighlightJs = async (fileType, content, language) => {
+ const languageDefinition = await languageLoader[language]();
+
+ registerPlugins(hljs, fileType, content);
+ hljs.registerLanguage(language, languageDefinition.default);
+};
+
+export const highlight = (fileType, content, language) => {
+ initHighlightJs(fileType, content, language);
+ return hljs.highlight(content, { language }).value;
+};
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
deleted file mode 100644
index ce65266cbc9..00000000000
--- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
+++ /dev/null
@@ -1,88 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
-import { secondsToHours } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
-import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
-
-export default {
- name: 'TimezoneDropdown',
- components: {
- GlDropdown,
- GlDropdownItem,
- GlSearchBoxByType,
- },
- directives: {
- autofocusonshow,
- },
- props: {
- value: {
- type: String,
- required: true,
- default: '',
- },
- timezoneData: {
- type: Array,
- required: true,
- default: () => [],
- },
- },
- data() {
- return {
- searchTerm: '',
- };
- },
- tranlations: {
- noResultsText: __('No matching results'),
- },
- computed: {
- timezones() {
- return this.timezoneData.map((timezone) => ({
- formattedTimezone: this.formatTimezone(timezone),
- identifier: timezone.identifier,
- }));
- },
- filteredResults() {
- const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.timezones.filter((timezone) =>
- timezone.formattedTimezone.toLowerCase().includes(lowerCasedSearchTerm),
- );
- },
- selectedTimezoneLabel() {
- return this.value || __('Select timezone');
- },
- },
- methods: {
- selectTimezone(selectedTimezone) {
- this.$emit('input', selectedTimezone);
- this.searchTerm = '';
- },
- isSelected(timezone) {
- return this.value === timezone.formattedTimezone;
- },
- formatTimezone(item) {
- return `[UTC ${secondsToHours(item.offset)}] ${item.name}`;
- },
- },
-};
-</script>
-<template>
- <gl-dropdown :text="selectedTimezoneLabel" block lazy menu-class="gl-w-full!" v-bind="$attrs">
- <gl-search-box-by-type v-model.trim="searchTerm" v-autofocusonshow autofocus />
- <gl-dropdown-item
- v-for="timezone in filteredResults"
- :key="timezone.formattedTimezone"
- :is-checked="isSelected(timezone)"
- is-check-item
- @click="selectTimezone(timezone)"
- >
- {{ timezone.formattedTimezone }}
- </gl-dropdown-item>
- <gl-dropdown-item
- v-if="!filteredResults.length"
- class="gl-pointer-events-none"
- data-testid="noMatchingResults"
- >
- {{ $options.tranlations.noResultsText }}
- </gl-dropdown-item>
- </gl-dropdown>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown/timezone_dropdown.vue
new file mode 100644
index 00000000000..423501265d7
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown/timezone_dropdown.vue
@@ -0,0 +1,119 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { __ } from '~/locale';
+import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
+import { formatTimezone } from '~/lib/utils/datetime_utility';
+
+export default {
+ name: 'TimezoneDropdown',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ },
+ directives: {
+ autofocusonshow,
+ },
+ props: {
+ value: {
+ type: String,
+ required: true,
+ default: '',
+ },
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ timezoneData: {
+ type: Array,
+ required: true,
+ default: () => [],
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ tzValue: this.initialTimezone(this.timezoneData, this.value),
+ };
+ },
+ translations: {
+ noResultsText: __('No matching results'),
+ },
+ computed: {
+ timezones() {
+ return this.timezoneData.map((timezone) => ({
+ formattedTimezone: formatTimezone(timezone),
+ identifier: timezone.identifier,
+ }));
+ },
+ filteredResults() {
+ const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
+ return this.timezones.filter((timezone) =>
+ timezone.formattedTimezone.toLowerCase().includes(lowerCasedSearchTerm),
+ );
+ },
+ selectedTimezoneLabel() {
+ return this.tzValue || __('Select timezone');
+ },
+ timezoneIdentifier() {
+ return this.tzValue
+ ? this.timezones.find((timezone) => timezone.formattedTimezone === this.tzValue).identifier
+ : undefined;
+ },
+ },
+ methods: {
+ selectTimezone(selectedTimezone) {
+ this.tzValue = selectedTimezone.formattedTimezone;
+ this.$emit('input', selectedTimezone);
+ this.searchTerm = '';
+ },
+ isSelected(timezone) {
+ return this.tzValue === timezone.formattedTimezone;
+ },
+ initialTimezone(timezones, value) {
+ if (!value) {
+ return undefined;
+ }
+
+ const initialTimezone = timezones.find((timezone) => timezone.identifier === value);
+
+ if (initialTimezone) {
+ return formatTimezone(initialTimezone);
+ }
+
+ return undefined;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <input
+ v-if="name"
+ id="user_timezone"
+ :name="name"
+ :value="timezoneIdentifier || value"
+ type="hidden"
+ />
+ <gl-dropdown :text="selectedTimezoneLabel" block lazy menu-class="gl-w-full!" v-bind="$attrs">
+ <gl-search-box-by-type v-model.trim="searchTerm" v-autofocusonshow autofocus />
+ <gl-dropdown-item
+ v-for="timezone in filteredResults"
+ :key="timezone.formattedTimezone"
+ :is-checked="isSelected(timezone)"
+ is-check-item
+ @click="selectTimezone(timezone)"
+ >
+ {{ timezone.formattedTimezone }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="!filteredResults.length"
+ class="gl-pointer-events-none"
+ data-testid="noMatchingResults"
+ >
+ {{ $options.translations.noResultsText }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/url_sync.vue b/app/assets/javascripts/vue_shared/components/url_sync.vue
index 925c6008836..bd5b7b77017 100644
--- a/app/assets/javascripts/vue_shared/components/url_sync.vue
+++ b/app/assets/javascripts/vue_shared/components/url_sync.vue
@@ -1,6 +1,9 @@
<script>
import { historyPushState } from '~/lib/utils/common_utils';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { mergeUrlParams, setUrlParams } from '~/lib/utils/url_utility';
+
+export const URL_SET_PARAMS_STRATEGY = 'set';
+export const URL_MERGE_PARAMS_STRATEGY = 'merge';
/**
* Renderless component to update the query string,
@@ -15,6 +18,12 @@ export default {
required: false,
default: null,
},
+ urlParamsUpdateStrategy: {
+ type: String,
+ required: false,
+ default: URL_MERGE_PARAMS_STRATEGY,
+ validator: (value) => [URL_MERGE_PARAMS_STRATEGY, URL_SET_PARAMS_STRATEGY].includes(value),
+ },
},
watch: {
query: {
@@ -29,7 +38,11 @@ export default {
},
methods: {
updateQuery(newQuery) {
- historyPushState(mergeUrlParams(newQuery, window.location.href, { spreadArrays: true }));
+ const url =
+ this.urlParamsUpdateStrategy === URL_SET_PARAMS_STRATEGY
+ ? setUrlParams(this.query, window.location.href, true)
+ : mergeUrlParams(newQuery, window.location.href, { spreadArrays: true });
+ historyPushState(url);
},
},
render() {
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
index c1e618620d8..6552a874c3a 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
@@ -5,29 +5,29 @@
Sample configuration:
- <user-avatar-image
+ <user-avatar
lazy
:img-src="userAvatarSrc"
:img-alt="tooltipText"
:tooltip-text="tooltipText"
tooltip-placement="top"
+ :size="24"
/>
*/
+import { GlTooltip, GlAvatar } from '@gitlab/ui';
+import { isObject } from 'lodash';
import defaultAvatarUrl from 'images/no_avatar.png';
import { __ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import UserAvatarImageNew from './user_avatar_image_new.vue';
-import UserAvatarImageOld from './user_avatar_image_old.vue';
+import { placeholderImage } from '~/lazy_loader';
export default {
name: 'UserAvatarImage',
components: {
- UserAvatarImageNew,
- UserAvatarImageOld,
+ GlTooltip,
+ GlAvatar,
},
- mixins: [glFeatureFlagMixin()],
props: {
lazy: {
type: Boolean,
@@ -51,8 +51,7 @@ export default {
},
size: {
type: [Number, Object],
- required: false,
- default: 20,
+ required: true,
},
tooltipText: {
type: String,
@@ -64,22 +63,52 @@ export default {
required: false,
default: 'top',
},
- enforceGlAvatar: {
- type: Boolean,
- required: false,
+ },
+ computed: {
+ // API response sends null when gravatar is disabled and
+ // we provide an empty string when we use it inside user avatar link.
+ // In both cases we should render the defaultAvatarUrl
+ sanitizedSource() {
+ let baseSrc = this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
+ // Only adds the width to the URL if its not a base64 data image
+ if (!(baseSrc.indexOf('data:') === 0) && !baseSrc.includes('?'))
+ baseSrc += `?width=${this.maximumSize}`;
+ return baseSrc;
+ },
+ maximumSize() {
+ if (isObject(this.size)) {
+ return Math.max(...Object.values(this.size));
+ }
+
+ return this.size;
+ },
+ resultantSrcAttribute() {
+ return this.lazy ? placeholderImage : this.sanitizedSource;
},
},
};
</script>
<template>
- <user-avatar-image-new
- v-if="glFeatures.glAvatarForAllUserAvatars || enforceGlAvatar"
- v-bind="$props"
- >
- <slot></slot>
- </user-avatar-image-new>
- <user-avatar-image-old v-else v-bind="$props">
- <slot></slot>
- </user-avatar-image-old>
+ <span ref="userAvatar">
+ <gl-avatar
+ :class="{
+ lazy: lazy,
+ [cssClasses]: true,
+ }"
+ :src="resultantSrcAttribute"
+ :data-src="sanitizedSource"
+ :size="size"
+ :alt="imgAlt"
+ />
+
+ <gl-tooltip
+ v-if="tooltipText || $scopedSlots.default"
+ :target="() => $refs.userAvatar"
+ :placement="tooltipPlacement"
+ boundary="window"
+ >
+ <slot>{{ tooltipText }}</slot>
+ </gl-tooltip>
+ </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue
deleted file mode 100644
index 6bd66981860..00000000000
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue
+++ /dev/null
@@ -1,117 +0,0 @@
-<script>
-/* This is a re-usable vue component for rendering a user avatar that
- does not need to link to the user's profile. The image and an optional
- tooltip can be configured by props passed to this component.
-
- Sample configuration:
-
- <user-avatar
- lazy
- :img-src="userAvatarSrc"
- :img-alt="tooltipText"
- :tooltip-text="tooltipText"
- tooltip-placement="top"
- />
-
- */
-
-import { GlTooltip, GlAvatar } from '@gitlab/ui';
-import { isObject } from 'lodash';
-import defaultAvatarUrl from 'images/no_avatar.png';
-import { __ } from '~/locale';
-import { placeholderImage } from '~/lazy_loader';
-
-export default {
- name: 'UserAvatarImageNew',
- components: {
- GlTooltip,
- GlAvatar,
- },
- props: {
- lazy: {
- type: Boolean,
- required: false,
- default: false,
- },
- imgSrc: {
- type: String,
- required: false,
- default: defaultAvatarUrl,
- },
- cssClasses: {
- type: String,
- required: false,
- default: '',
- },
- imgAlt: {
- type: String,
- required: false,
- default: __('user avatar'),
- },
- size: {
- type: [Number, Object],
- required: false,
- default: 20,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
- },
- computed: {
- // API response sends null when gravatar is disabled and
- // we provide an empty string when we use it inside user avatar link.
- // In both cases we should render the defaultAvatarUrl
- sanitizedSource() {
- let baseSrc = this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
- // Only adds the width to the URL if its not a base64 data image
- if (!(baseSrc.indexOf('data:') === 0) && !baseSrc.includes('?'))
- baseSrc += `?width=${this.maximumSize}`;
- return baseSrc;
- },
- maximumSize() {
- if (isObject(this.size)) {
- return Math.max(...Object.values(this.size));
- }
-
- return this.size;
- },
- resultantSrcAttribute() {
- return this.lazy ? placeholderImage : this.sanitizedSource;
- },
- },
-};
-</script>
-
-<template>
- <span ref="userAvatar">
- <gl-avatar
- :class="{
- lazy: lazy,
- [cssClasses]: true,
- }"
- :src="resultantSrcAttribute"
- :data-src="sanitizedSource"
- :size="size"
- :alt="imgAlt"
- />
-
- <gl-tooltip
- v-if="
- tooltipText ||
- $slots.default /* eslint-disable-line @gitlab/vue-prefer-dollar-scopedslots */
- "
- :target="() => $refs.userAvatar"
- :placement="tooltipPlacement"
- boundary="window"
- >
- <slot>{{ tooltipText }}</slot>
- </gl-tooltip>
- </span>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_old.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_old.vue
deleted file mode 100644
index 6e8c200d5c3..00000000000
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_old.vue
+++ /dev/null
@@ -1,114 +0,0 @@
-<script>
-/* This is a re-usable vue component for rendering a user avatar that
- does not need to link to the user's profile. The image and an optional
- tooltip can be configured by props passed to this component.
-
- Sample configuration:
-
- <user-avatar-image
- lazy
- :img-src="userAvatarSrc"
- :img-alt="tooltipText"
- :tooltip-text="tooltipText"
- tooltip-placement="top"
- />
-
- */
-
-import { GlTooltip } from '@gitlab/ui';
-import defaultAvatarUrl from 'images/no_avatar.png';
-import { __ } from '~/locale';
-import { placeholderImage } from '~/lazy_loader';
-
-export default {
- name: 'UserAvatarImageOld',
- components: {
- GlTooltip,
- },
- props: {
- lazy: {
- type: Boolean,
- required: false,
- default: false,
- },
- imgSrc: {
- type: String,
- required: false,
- default: defaultAvatarUrl,
- },
- cssClasses: {
- type: String,
- required: false,
- default: '',
- },
- imgAlt: {
- type: String,
- required: false,
- default: __('user avatar'),
- },
- size: {
- type: Number,
- required: false,
- default: 20,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
- },
- computed: {
- // API response sends null when gravatar is disabled and
- // we provide an empty string when we use it inside user avatar link.
- // In both cases we should render the defaultAvatarUrl
- sanitizedSource() {
- let baseSrc = this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
- // Only adds the width to the URL if its not a base64 data image
- if (!(baseSrc.indexOf('data:') === 0) && !baseSrc.includes('?'))
- baseSrc += `?width=${this.size}`;
- return baseSrc;
- },
- resultantSrcAttribute() {
- return this.lazy ? placeholderImage : this.sanitizedSource;
- },
- avatarSizeClass() {
- return `s${this.size}`;
- },
- },
-};
-</script>
-
-<template>
- <span>
- <img
- ref="userAvatarImage"
- :class="{
- lazy: lazy,
- [avatarSizeClass]: true,
- [cssClasses]: true,
- }"
- :src="resultantSrcAttribute"
- :width="size"
- :height="size"
- :alt="imgAlt"
- :data-src="sanitizedSource"
- class="avatar"
- />
- <gl-tooltip
- v-if="
- tooltipText ||
- $slots.default /* eslint-disable-line @gitlab/vue-prefer-dollar-scopedslots */
- "
- :target="() => $refs.userAvatarImage"
- :placement="tooltipPlacement"
- boundary="window"
- >
- <slot>{{ tooltipText }}</slot>
- </gl-tooltip>
- </span>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
index f80abed4d69..1a81da3eb0d 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
@@ -9,7 +9,7 @@
:link-href="userProfileUrl"
:img-src="userAvatarSrc"
:img-alt="tooltipText"
- :img-size="20"
+ :img-size="32"
:tooltip-text="tooltipText"
:tooltip-placement="top"
:username="username"
@@ -17,17 +17,18 @@
*/
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import UserAvatarLinkNew from './user_avatar_link_new.vue';
-import UserAvatarLinkOld from './user_avatar_link_old.vue';
+import { GlAvatarLink, GlTooltipDirective } from '@gitlab/ui';
+import UserAvatarImage from './user_avatar_image.vue';
export default {
- name: 'UserAvatarLink',
+ name: 'UserAvatarLinkNew',
components: {
- UserAvatarLinkNew,
- UserAvatarLinkOld,
+ UserAvatarImage,
+ GlAvatarLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagMixin()],
props: {
lazy: {
type: Boolean,
@@ -56,8 +57,7 @@ export default {
},
imgSize: {
type: [Number, Object],
- required: false,
- default: 20,
+ required: true,
},
tooltipText: {
type: String,
@@ -74,29 +74,43 @@ export default {
required: false,
default: '',
},
- enforceGlAvatar: {
- type: Boolean,
- required: false,
+ },
+ computed: {
+ shouldShowUsername() {
+ return this.username.length > 0;
+ },
+ avatarTooltipText() {
+ return this.shouldShowUsername ? '' : this.tooltipText;
},
},
};
</script>
<template>
- <user-avatar-link-new
- v-if="glFeatures.glAvatarForAllUserAvatars || enforceGlAvatar"
- v-bind="$props"
- >
- <slot></slot>
- <template #avatar-badge>
- <slot name="avatar-badge"></slot>
- </template>
- </user-avatar-link-new>
+ <gl-avatar-link :href="linkHref" class="user-avatar-link">
+ <user-avatar-image
+ :img-src="imgSrc"
+ :img-alt="imgAlt"
+ :css-classes="imgCssClasses"
+ :size="imgSize"
+ :tooltip-text="avatarTooltipText"
+ :tooltip-placement="tooltipPlacement"
+ :lazy="lazy"
+ >
+ <slot></slot>
+ </user-avatar-image>
+
+ <span
+ v-if="shouldShowUsername"
+ v-gl-tooltip
+ :title="tooltipText"
+ :tooltip-placement="tooltipPlacement"
+ class="gl-ml-3"
+ data-testid="user-avatar-link-username"
+ >
+ {{ username }}
+ </span>
- <user-avatar-link-old v-else v-bind="$props">
- <slot></slot>
- <template #avatar-badge>
- <slot name="avatar-badge"></slot>
- </template>
- </user-avatar-link-old>
+ <slot name="avatar-badge"></slot>
+ </gl-avatar-link>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_new.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_new.vue
deleted file mode 100644
index 83551c689c4..00000000000
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_new.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<script>
-/* This is a re-usable vue component for rendering a user avatar wrapped in
- a clickable link (likely to the user's profile). The link, image, and
- tooltip can be configured by props passed to this component.
-
- Sample configuration:
-
- <user-avatar-link
- :link-href="userProfileUrl"
- :img-src="userAvatarSrc"
- :img-alt="tooltipText"
- :img-size="20"
- :tooltip-text="tooltipText"
- :tooltip-placement="top"
- :username="username"
- />
-
-*/
-
-import { GlAvatarLink, GlTooltipDirective } from '@gitlab/ui';
-import UserAvatarImage from './user_avatar_image.vue';
-
-export default {
- name: 'UserAvatarLinkNew',
- components: {
- UserAvatarImage,
- GlAvatarLink,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- lazy: {
- type: Boolean,
- required: false,
- default: false,
- },
- linkHref: {
- type: String,
- required: false,
- default: '',
- },
- imgSrc: {
- type: String,
- required: false,
- default: '',
- },
- imgAlt: {
- type: String,
- required: false,
- default: '',
- },
- imgCssClasses: {
- type: String,
- required: false,
- default: '',
- },
- imgSize: {
- type: [Number, Object],
- required: false,
- default: 20,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
- username: {
- type: String,
- required: false,
- default: '',
- },
- enforceGlAvatar: {
- type: Boolean,
- required: false,
- },
- },
- computed: {
- shouldShowUsername() {
- return this.username.length > 0;
- },
- avatarTooltipText() {
- return this.shouldShowUsername ? '' : this.tooltipText;
- },
- },
-};
-</script>
-
-<template>
- <gl-avatar-link :href="linkHref" class="user-avatar-link">
- <user-avatar-image
- :img-src="imgSrc"
- :img-alt="imgAlt"
- :css-classes="imgCssClasses"
- :size="imgSize"
- :tooltip-text="avatarTooltipText"
- :tooltip-placement="tooltipPlacement"
- :lazy="lazy"
- :enforce-gl-avatar="enforceGlAvatar"
- >
- <slot></slot>
- </user-avatar-image>
-
- <span
- v-if="shouldShowUsername"
- v-gl-tooltip
- :title="tooltipText"
- :tooltip-placement="tooltipPlacement"
- class="gl-ml-3"
- data-testid="user-avatar-link-username"
- >
- {{ username }}
- </span>
-
- <slot name="avatar-badge"></slot>
- </gl-avatar-link>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_old.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_old.vue
deleted file mode 100644
index c2e46e61e1b..00000000000
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_old.vue
+++ /dev/null
@@ -1,117 +0,0 @@
-<script>
-/* This is a re-usable vue component for rendering a user avatar wrapped in
- a clickable link (likely to the user's profile). The link, image, and
- tooltip can be configured by props passed to this component.
-
- Sample configuration:
-
- <user-avatar-link
- :link-href="userProfileUrl"
- :img-src="userAvatarSrc"
- :img-alt="tooltipText"
- :img-size="20"
- :tooltip-text="tooltipText"
- :tooltip-placement="top"
- :username="username"
- />
-
-*/
-
-import { GlLink, GlTooltipDirective } from '@gitlab/ui';
-import UserAvatarImage from './user_avatar_image.vue';
-
-export default {
- name: 'UserAvatarLinkOld',
- components: {
- GlLink,
- UserAvatarImage,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- lazy: {
- type: Boolean,
- required: false,
- default: false,
- },
- linkHref: {
- type: String,
- required: false,
- default: '',
- },
- imgSrc: {
- type: String,
- required: false,
- default: '',
- },
- imgAlt: {
- type: String,
- required: false,
- default: '',
- },
- imgCssClasses: {
- type: String,
- required: false,
- default: '',
- },
- imgSize: {
- type: Number,
- required: false,
- default: 20,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
- username: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- shouldShowUsername() {
- return this.username.length > 0;
- },
- avatarTooltipText() {
- return this.shouldShowUsername ? '' : this.tooltipText;
- },
- },
-};
-</script>
-
-<template>
- <span>
- <gl-link :href="linkHref" class="user-avatar-link">
- <user-avatar-image
- :img-src="imgSrc"
- :img-alt="imgAlt"
- :css-classes="imgCssClasses"
- :size="imgSize"
- :tooltip-text="avatarTooltipText"
- :tooltip-placement="tooltipPlacement"
- :lazy="lazy"
- >
- <slot></slot>
- </user-avatar-image>
-
- <span
- v-if="shouldShowUsername"
- v-gl-tooltip
- :title="tooltipText"
- :tooltip-placement="tooltipPlacement"
- data-testid="user-avatar-link-username"
- >
- {{ username }}
- </span>
- <slot name="avatar-badge"></slot>
- </gl-link>
- </span>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue
index 9da298ad705..231f5ff3d1f 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue
@@ -1,6 +1,5 @@
<script>
import { GlButton } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { sprintf, __ } from '~/locale';
import UserAvatarLink from './user_avatar_link.vue';
@@ -9,7 +8,6 @@ export default {
UserAvatarLink,
GlButton,
},
- mixins: [glFeatureFlagMixin()],
props: {
items: {
type: Array,
@@ -22,8 +20,7 @@ export default {
},
imgSize: {
type: [Number, Object],
- required: false,
- default: 20,
+ required: true,
},
emptyText: {
type: String,
@@ -59,9 +56,6 @@ export default {
return sprintf(__('%{count} more'), { count });
},
- imgCssClasses() {
- return this.glFeatures.glAvatarForAllUserAvatars ? 'gl-mr-3' : '';
- },
},
methods: {
expand() {
@@ -85,7 +79,7 @@ export default {
:img-alt="item.name"
:tooltip-text="item.name"
:img-size="imgSize"
- :img-css-classes="imgCssClasses"
+ img-css-classes="gl-mr-3"
/>
<template v-if="hasBreakpoint">
<gl-button v-if="hasHiddenItems" variant="link" @click="expand">
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index 4b39a8e45bb..80c1fcbacfa 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -10,7 +10,7 @@ import {
GlAvatarLabeled,
} from '@gitlab/ui';
import { glEmojiTag } from '~/emoji';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { followUser, unfollowUser } from '~/rest_api';
import { isUserBusy } from '~/set_status_modal/utils';
import Tracking from '~/tracking';
@@ -83,6 +83,8 @@ export default {
return `${glEmojiTag(this.user.status.emoji)} ${this.user.status.message_html}`;
} else if (this.user.status.message_html) {
return this.user.status.message_html;
+ } else if (this.user.status.emoji) {
+ return glEmojiTag(this.user.status.emoji);
}
return '';
@@ -139,8 +141,9 @@ export default {
await followUser(this.user.id);
this.$emit('follow');
} catch (error) {
- createFlash({
- message: I18N_ERROR_FOLLOW,
+ const message = error.response?.data?.message || I18N_ERROR_FOLLOW;
+ createAlert({
+ message,
error,
captureError: true,
});
@@ -159,7 +162,7 @@ export default {
await unfollowUser(this.user.id);
this.$emit('unfollow');
} catch (error) {
- createFlash({
+ createAlert({
message: I18N_ERROR_UNFOLLOW,
error,
captureError: true,
diff --git a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
index 3180bd0d283..86a99b8f0ed 100644
--- a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
+++ b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
@@ -103,6 +103,7 @@ export default {
return {
iid: this.iid,
fullPath: this.fullPath,
+ getStatus: true,
};
},
update(data) {
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index b6d69faebb5..a851f84ed2f 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -93,3 +93,6 @@ export const confidentialityInfoText = (workspaceType, issuableType) =>
: __('at least the Reporter role'),
},
);
+
+export const EDITING_MODE_MARKDOWN_FIELD = 'markdownField';
+export const EDITING_MODE_CONTENT_EDITOR = 'contentEditor';
diff --git a/app/assets/javascripts/vue_shared/directives/safe_html.js b/app/assets/javascripts/vue_shared/directives/safe_html.js
new file mode 100644
index 00000000000..450c7fc1bc5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/directives/safe_html.js
@@ -0,0 +1,25 @@
+import { sanitize } from '~/lib/dompurify';
+
+// Mitigate against future dompurify mXSS bypasses by
+// avoiding additional serialize/parse round trip.
+// See https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1782
+// and https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2127
+// for more details.
+const DEFAULT_CONFIG = {
+ RETURN_DOM_FRAGMENT: true,
+};
+
+const transform = (el, binding) => {
+ if (binding.oldValue !== binding.value) {
+ const config = { ...DEFAULT_CONFIG, ...(binding.arg ?? {}) };
+
+ el.textContent = '';
+
+ el.appendChild(sanitize(binding.value, config));
+ }
+};
+
+export default {
+ bind: transform,
+ update: transform,
+};
diff --git a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
index 232749a2d01..624ae7027d5 100644
--- a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
+++ b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
@@ -1,11 +1,13 @@
<script>
import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import NewTopLevelGroupAlert from '~/groups/components/new_top_level_group_alert.vue';
import LegacyContainer from './components/legacy_container.vue';
import WelcomePage from './components/welcome.vue';
export default {
components: {
+ NewTopLevelGroupAlert,
GlBreadcrumb,
GlIcon,
WelcomePage,
@@ -79,6 +81,14 @@ export default {
shouldVerify() {
return this.verificationRequired && !this.verificationCompleted;
},
+
+ showNewTopLevelGroupAlert() {
+ if (this.activePanel.detailProps === undefined) {
+ return false;
+ }
+
+ return this.activePanel.detailProps.parentGroupName === '';
+ },
},
created() {
@@ -130,6 +140,7 @@ export default {
<slot name="extra-description"></slot>
</div>
<div class="col-lg-9">
+ <new-top-level-group-alert v-if="showNewTopLevelGroupAlert" />
<gl-breadcrumb v-if="breadcrumbs" :items="breadcrumbs" />
<legacy-container :key="activePanel.name" :selector="activePanel.selector" />
</div>
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
index e0669b3ed27..a4fb30a03a1 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
@@ -1,6 +1,6 @@
<script>
import { reportTypeToSecurityReportTypeEnum } from 'ee_else_ce/vue_shared/security_reports/constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql';
@@ -67,7 +67,7 @@ export default {
},
methods: {
showError(error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.apiError,
captureError: true,
error,
diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
index f6d85599dba..0e1975e1c09 100644
--- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { s__ } from '~/locale';
import ReportSection from '~/reports/components/report_section.vue';
import { ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/reports/constants';
@@ -160,7 +160,7 @@ export default {
this.fetchCounts();
},
showError(error) {
- createFlash({
+ createAlert({
message: this.$options.i18n.apiError,
captureError: true,
error,
diff --git a/app/assets/javascripts/webhooks/components/form_url_app.vue b/app/assets/javascripts/webhooks/components/form_url_app.vue
new file mode 100644
index 00000000000..5ec16d4ba15
--- /dev/null
+++ b/app/assets/javascripts/webhooks/components/form_url_app.vue
@@ -0,0 +1,134 @@
+<script>
+import { isEmpty } from 'lodash';
+import { GlFormGroup, GlFormInput, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+
+import FormUrlMaskItem from './form_url_mask_item.vue';
+
+export default {
+ components: {
+ FormUrlMaskItem,
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlLink,
+ },
+ props: {
+ initialUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ initialUrlVariables: {
+ type: Array,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ maskEnabled: !isEmpty(this.initialUrlVariables),
+ url: this.initialUrl,
+ items: isEmpty(this.initialUrlVariables) ? [{}] : this.initialUrlVariables,
+ };
+ },
+ computed: {
+ maskedUrl() {
+ if (!this.url) {
+ return null;
+ }
+
+ let maskedUrl = this.url;
+
+ this.items.forEach(({ key, value }) => {
+ if (!key || !value) {
+ return;
+ }
+
+ const replacementExpression = new RegExp(value, 'g');
+ maskedUrl = maskedUrl.replace(replacementExpression, `{${key}}`);
+ });
+
+ return maskedUrl;
+ },
+ },
+ methods: {
+ onItemInput({ index, key, value }) {
+ this.$set(this.items, index, { key, value });
+ },
+ addItem() {
+ this.items.push({});
+ },
+ removeItem(index) {
+ this.items.splice(index, 1);
+ },
+ },
+ i18n: {
+ addItem: s__('Webhooks|+ Mask another portion of URL'),
+ radioFullUrlText: s__('Webhooks|Show full URL'),
+ radioMaskUrlText: s__('Webhooks|Mask portions of URL'),
+ radioMaskUrlHelp: s__('Webhooks|Do not show sensitive data such as tokens in the UI.'),
+ urlDescription: s__(
+ 'Webhooks|URL must be percent-encoded if it contains one or more special characters.',
+ ),
+ urlLabel: __('URL'),
+ urlPlaceholder: 'http://example.com/trigger-ci.json',
+ urlPreview: s__('Webhooks|URL preview'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-form-group
+ :label="$options.i18n.urlLabel"
+ label-for="webhook-url"
+ :description="$options.i18n.urlDescription"
+ >
+ <gl-form-input
+ id="webhook-url"
+ v-model="url"
+ name="hook[url]"
+ :placeholder="$options.i18n.urlPlaceholder"
+ data-testid="form-url"
+ />
+ </gl-form-group>
+ <div class="gl-mt-5">
+ <gl-form-radio-group v-model="maskEnabled">
+ <gl-form-radio :value="false">{{ $options.i18n.radioFullUrlText }}</gl-form-radio>
+ <gl-form-radio :value="true"
+ >{{ $options.i18n.radioMaskUrlText }}
+ <template #help>
+ {{ $options.i18n.radioMaskUrlHelp }}
+ </template>
+ </gl-form-radio>
+ </gl-form-radio-group>
+
+ <div v-if="maskEnabled" class="gl-ml-6" data-testid="url-mask-section">
+ <form-url-mask-item
+ v-for="({ key, value }, index) in items"
+ :key="index"
+ :index="index"
+ :item-key="key"
+ :item-value="value"
+ @input="onItemInput"
+ @remove="removeItem"
+ />
+ <div class="gl-mb-5">
+ <gl-link @click="addItem">{{ $options.i18n.addItem }}</gl-link>
+ </div>
+
+ <gl-form-group :label="$options.i18n.urlPreview" label-for="webhook-url-preview">
+ <gl-form-input
+ id="webhook-url-preview"
+ :value="maskedUrl"
+ readonly
+ name="hook[url]"
+ data-testid="form-url-preview"
+ />
+ </gl-form-group>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/webhooks/components/form_url_mask_item.vue b/app/assets/javascripts/webhooks/components/form_url_mask_item.vue
new file mode 100644
index 00000000000..3b75f9b6c0d
--- /dev/null
+++ b/app/assets/javascripts/webhooks/components/form_url_mask_item.vue
@@ -0,0 +1,90 @@
+<script>
+import { GlButton, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ components: {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ },
+ props: {
+ index: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ itemKey: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ itemValue: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ keyInputId() {
+ return this.inputId('key');
+ },
+ valueInputId() {
+ return this.inputId('value');
+ },
+ },
+ methods: {
+ inputId(type) {
+ return `webhook-url-mask-item-${type}-${this.index}`;
+ },
+ inputName(type) {
+ return `hook[url_variables][][${type}]`;
+ },
+ onKeyInput(key) {
+ this.$emit('input', { index: this.index, key, value: this.itemValue });
+ },
+ onValueInput(value) {
+ this.$emit('input', { index: this.index, key: this.itemKey, value });
+ },
+ onRemoveClick() {
+ this.$emit('remove', this.index);
+ },
+ },
+ i18n: {
+ keyLabel: s__('Webhooks|How it looks in the UI'),
+ valueLabel: s__('Webhooks|Sensitive portion of URL'),
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-flex-end gl-gap-3 gl-mb-3">
+ <gl-form-group
+ :label="$options.i18n.valueLabel"
+ :label-for="valueInputId"
+ class="gl-flex-grow-1 gl-mb-0"
+ data-testid="mask-item-value"
+ >
+ <gl-form-input
+ :id="valueInputId"
+ :name="inputName('value')"
+ :value="itemValue"
+ @input="onValueInput"
+ />
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.i18n.keyLabel"
+ :label-for="keyInputId"
+ class="gl-flex-grow-1 gl-mb-0"
+ data-testid="mask-item-key"
+ >
+ <gl-form-input
+ :id="keyInputId"
+ :name="inputName('key')"
+ :value="itemKey"
+ @input="onKeyInput"
+ />
+ </gl-form-group>
+ <gl-button icon="remove" :aria-label="__('Remove')" @click="onRemoveClick" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/webhooks/index.js b/app/assets/javascripts/webhooks/index.js
new file mode 100644
index 00000000000..1b2b33e44c1
--- /dev/null
+++ b/app/assets/javascripts/webhooks/index.js
@@ -0,0 +1,25 @@
+import Vue from 'vue';
+import FormUrlApp from './components/form_url_app.vue';
+
+export default () => {
+ const el = document.querySelector('.js-vue-webhook-form');
+
+ if (!el) {
+ return null;
+ }
+
+ const { url: initialUrl, urlVariables } = el.dataset;
+
+ return new Vue({
+ el,
+ name: 'WebhookFormRoot',
+ render(createElement) {
+ return createElement(FormUrlApp, {
+ props: {
+ initialUrl,
+ initialUrlVariables: urlVariables ? JSON.parse(urlVariables) : undefined,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/work_items/components/work_item_assignees.vue b/app/assets/javascripts/work_items/components/work_item_assignees.vue
index 4585426edaa..4d6a27f61ac 100644
--- a/app/assets/javascripts/work_items/components/work_item_assignees.vue
+++ b/app/assets/javascripts/work_items/components/work_item_assignees.vue
@@ -10,7 +10,7 @@ import {
GlDropdownDivider,
GlIntersectionObserver,
} from '@gitlab/ui';
-import { debounce } from 'lodash';
+import { debounce, uniqueId } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
@@ -126,6 +126,9 @@ export default {
},
},
computed: {
+ assigneesTitleId() {
+ return uniqueId('assignees-title-');
+ },
searchUsers() {
return this.users.nodes.map((node) => addClass({ ...node, ...node.user }));
},
@@ -139,9 +142,6 @@ export default {
property: `type_${this.workItemType}`,
};
},
- assigneeListEmpty() {
- return this.assignees.length === 0;
- },
containerClass() {
return !this.isEditing ? 'gl-shadow-none!' : '';
},
@@ -296,12 +296,14 @@ export default {
<template>
<div class="form-row gl-mb-5 work-item-assignees gl-relative gl-flex-nowrap">
<span
+ :id="assigneesTitleId"
class="gl-font-weight-bold col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
data-testid="assignees-title"
>{{ assigneeText }}</span
>
<gl-token-selector
ref="tokenSelector"
+ :aria-labelledby="assigneesTitleId"
:selected-tokens="localAssignees"
:container-class="containerClass"
:class="{ 'gl-hover-border-gray-200': canUpdate }"
@@ -319,7 +321,7 @@ export default {
>
<template #empty-placeholder>
<div
- class="add-assignees gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-gray-300 gl-pr-4 gl-pl-2 gl-top-2"
+ class="add-assignees gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-secondary gl-pr-4 gl-pl-2 gl-top-2"
data-testid="empty-state"
>
<gl-icon name="profile" />
diff --git a/app/assets/javascripts/work_items/components/work_item_description.vue b/app/assets/javascripts/work_items/components/work_item_description.vue
index c2e4a50fe31..57babe4569d 100644
--- a/app/assets/javascripts/work_items/components/work_item_description.vue
+++ b/app/assets/javascripts/work_items/components/work_item_description.vue
@@ -5,6 +5,7 @@ import { helpPagePath } from '~/helpers/help_page_helper';
import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { __, s__ } from '~/locale';
+import EditedAt from '~/issues/show/components/edited.vue';
import Tracking from '~/tracking';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import workItemQuery from '../graphql/work_item.query.graphql';
@@ -16,6 +17,7 @@ export default {
SafeHtml: GlSafeHtmlDirective,
},
components: {
+ EditedAt,
GlButton,
GlFormGroup,
MarkdownField,
@@ -89,6 +91,15 @@ export default {
workItemType() {
return this.workItem?.workItemType?.name;
},
+ lastEditedAt() {
+ return this.workItemDescription?.lastEditedAt;
+ },
+ lastEditedByName() {
+ return this.workItemDescription?.lastEditedBy?.name;
+ },
+ lastEditedByPath() {
+ return this.workItemDescription?.lastEditedBy?.webPath;
+ },
markdownPreviewPath() {
return `${gon.relative_url_root || ''}/${this.fullPath}/preview_markdown?target_type=${
this.workItemType
@@ -228,12 +239,18 @@ export default {
class="gl-ml-auto"
icon="pencil"
data-testid="edit-description"
- :aria-label="__('Edit')"
+ :aria-label="__('Edit description')"
@click="startEditing"
/>
</div>
<div v-if="descriptionEmpty" class="gl-text-secondary gl-mb-5">{{ __('None') }}</div>
<div v-else v-safe-html="descriptionHtml" class="md gl-mb-5 gl-min-h-8"></div>
+ <edited-at
+ v-if="lastEditedAt"
+ :updated-at="lastEditedAt"
+ :updated-by-name="lastEditedByName"
+ :updated-by-path="lastEditedByPath"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 3d25df9fcb8..af9b8c6101a 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -7,7 +7,10 @@ import {
GlBadge,
GlButton,
GlTooltipDirective,
+ GlEmptyState,
} from '@gitlab/ui';
+import noAccessSvg from '@gitlab/svgs/dist/illustrations/analytics/no-access.svg';
+import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
@@ -20,11 +23,14 @@ import {
WIDGET_TYPE_WEIGHT,
WIDGET_TYPE_HIERARCHY,
WORK_ITEM_VIEWED_STORAGE_KEY,
+ WIDGET_TYPE_MILESTONE,
+ WIDGET_TYPE_ITERATION,
} from '../constants';
import workItemQuery from '../graphql/work_item.query.graphql';
import workItemDatesSubscription from '../graphql/work_item_dates.subscription.graphql';
import workItemTitleSubscription from '../graphql/work_item_title.subscription.graphql';
+import workItemAssigneesSubscription from '../graphql/work_item_assignees.subscription.graphql';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import updateWorkItemTaskMutation from '../graphql/update_work_item_task.mutation.graphql';
@@ -35,6 +41,7 @@ import WorkItemDescription from './work_item_description.vue';
import WorkItemDueDate from './work_item_due_date.vue';
import WorkItemAssignees from './work_item_assignees.vue';
import WorkItemLabels from './work_item_labels.vue';
+import WorkItemMilestone from './work_item_milestone.vue';
import WorkItemInformation from './work_item_information.vue';
export default {
@@ -49,6 +56,7 @@ export default {
GlLoadingIcon,
GlSkeletonLoader,
GlIcon,
+ GlEmptyState,
WorkItemAssignees,
WorkItemActions,
WorkItemDescription,
@@ -60,6 +68,8 @@ export default {
WorkItemInformation,
LocalStorageSync,
WorkItemTypeIcon,
+ WorkItemIteration: () => import('ee_component/work_items/components/work_item_iteration.vue'),
+ WorkItemMilestone,
},
mixins: [glFeatureFlagMixin()],
props: {
@@ -82,6 +92,7 @@ export default {
data() {
return {
error: undefined,
+ updateError: undefined,
workItem: {},
showInfoBanner: true,
updateInProgress: false,
@@ -100,9 +111,10 @@ export default {
},
error() {
this.error = this.$options.i18n.fetchError;
+ document.title = s__('404|Not found');
},
result() {
- if (!this.isModal) {
+ if (!this.isModal && this.workItem.project) {
const path = this.workItem.project?.fullPath
? ` · ${this.workItem.project.fullPath}`
: '';
@@ -127,7 +139,18 @@ export default {
};
},
skip() {
- return !this.workItemDueDate;
+ return !this.isWidgetPresent(WIDGET_TYPE_START_AND_DUE_DATE);
+ },
+ },
+ {
+ document: workItemAssigneesSubscription,
+ variables() {
+ return {
+ issuableId: this.workItemId,
+ };
+ },
+ skip() {
+ return !this.isWidgetPresent(WIDGET_TYPE_ASSIGNEES);
},
},
],
@@ -152,37 +175,44 @@ export default {
workItemsMvc2Enabled() {
return this.glFeatures.workItemsMvc2;
},
+ parentWorkItem() {
+ return this.isWidgetPresent(WIDGET_TYPE_HIERARCHY)?.parent;
+ },
+ parentWorkItemConfidentiality() {
+ return this.parentWorkItem?.confidential;
+ },
+ parentUrl() {
+ return `../../issues/${this.parentWorkItem?.iid}`;
+ },
+ workItemIconName() {
+ return this.workItem?.workItemType?.iconName;
+ },
+ noAccessSvgPath() {
+ return `data:image/svg+xml;utf8,${encodeURIComponent(noAccessSvg)}`;
+ },
hasDescriptionWidget() {
- return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_DESCRIPTION);
+ return this.isWidgetPresent(WIDGET_TYPE_DESCRIPTION);
},
workItemAssignees() {
- return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_ASSIGNEES);
+ return this.isWidgetPresent(WIDGET_TYPE_ASSIGNEES);
},
workItemLabels() {
- return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_LABELS);
+ return this.isWidgetPresent(WIDGET_TYPE_LABELS);
},
workItemDueDate() {
- return this.workItem?.widgets?.find(
- (widget) => widget.type === WIDGET_TYPE_START_AND_DUE_DATE,
- );
+ return this.isWidgetPresent(WIDGET_TYPE_START_AND_DUE_DATE);
},
workItemWeight() {
- return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_WEIGHT);
+ return this.isWidgetPresent(WIDGET_TYPE_WEIGHT);
},
workItemHierarchy() {
- return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY);
+ return this.isWidgetPresent(WIDGET_TYPE_HIERARCHY);
},
- parentWorkItem() {
- return this.workItemHierarchy?.parent;
+ workItemIteration() {
+ return this.isWidgetPresent(WIDGET_TYPE_ITERATION);
},
- parentWorkItemConfidentiality() {
- return this.parentWorkItem?.confidential;
- },
- parentUrl() {
- return `../../issues/${this.parentWorkItem?.iid}`;
- },
- workItemIconName() {
- return this.workItem?.workItemType?.iconName;
+ workItemMilestone() {
+ return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_MILESTONE);
},
},
beforeDestroy() {
@@ -191,6 +221,9 @@ export default {
this.dismissBanner();
},
methods: {
+ isWidgetPresent(type) {
+ return this.workItem?.widgets?.find((widget) => widget.type === type);
+ },
dismissBanner() {
this.showInfoBanner = false;
},
@@ -236,7 +269,7 @@ export default {
},
)
.catch((error) => {
- this.error = error.message;
+ this.updateError = error.message;
})
.finally(() => {
this.updateInProgress = false;
@@ -249,8 +282,13 @@ export default {
<template>
<section class="gl-pt-5">
- <gl-alert v-if="error" class="gl-mb-3" variant="danger" @dismiss="error = undefined">
- {{ error }}
+ <gl-alert
+ v-if="updateError"
+ class="gl-mb-3"
+ variant="danger"
+ @dismiss="updateError = undefined"
+ >
+ {{ updateError }}
</gl-alert>
<div v-if="workItemLoading" class="gl-max-w-26 gl-py-5">
@@ -289,7 +327,7 @@ export default {
</li>
</ul>
<work-item-type-icon
- v-else
+ v-else-if="!error"
:work-item-icon-name="workItemIconName"
:work-item-type="workItemType && workItemType.toUpperCase()"
show-text
@@ -316,7 +354,7 @@ export default {
:is-parent-confidential="parentWorkItemConfidentiality"
@deleteWorkItem="$emit('deleteWorkItem', workItemType)"
@toggleWorkItemConfidentiality="toggleConfidentiality"
- @error="error = $event"
+ @error="updateError = $event"
/>
<gl-button
v-if="isModal"
@@ -332,24 +370,25 @@ export default {
:storage-key="$options.WORK_ITEM_VIEWED_STORAGE_KEY"
>
<work-item-information
- v-if="showInfoBanner"
+ v-if="showInfoBanner && !error"
:show-info-banner="showInfoBanner"
@work-item-banner-dismissed="dismissBanner"
/>
</local-storage-sync>
<work-item-title
+ v-if="workItem.title"
:work-item-id="workItem.id"
:work-item-title="workItem.title"
:work-item-type="workItemType"
:work-item-parent-id="workItemParentId"
:can-update="canUpdate"
- @error="error = $event"
+ @error="updateError = $event"
/>
<work-item-state
:work-item="workItem"
:work-item-parent-id="workItemParentId"
:can-update="canUpdate"
- @error="error = $event"
+ @error="updateError = $event"
/>
<work-item-assignees
v-if="workItemAssignees"
@@ -360,24 +399,33 @@ export default {
:work-item-type="workItemType"
:can-invite-members="workItemAssignees.canInviteMembers"
:full-path="fullPath"
- @error="error = $event"
+ @error="updateError = $event"
+ />
+ <work-item-labels
+ v-if="workItemLabels"
+ :work-item-id="workItem.id"
+ :can-update="canUpdate"
+ :full-path="fullPath"
+ @error="updateError = $event"
+ />
+ <work-item-due-date
+ v-if="workItemDueDate"
+ :can-update="canUpdate"
+ :due-date="workItemDueDate.dueDate"
+ :start-date="workItemDueDate.startDate"
+ :work-item-id="workItem.id"
+ :work-item-type="workItemType"
+ @error="updateError = $event"
/>
<template v-if="workItemsMvc2Enabled">
- <work-item-labels
- v-if="workItemLabels"
+ <work-item-milestone
+ v-if="workItemMilestone"
:work-item-id="workItem.id"
+ :work-item-milestone="workItemMilestone.nodes[0]"
+ :work-item-type="workItemType"
:can-update="canUpdate"
:full-path="fullPath"
- @error="error = $event"
- />
- <work-item-due-date
- v-if="workItemDueDate"
- :can-update="canUpdate"
- :due-date="workItemDueDate.dueDate"
- :start-date="workItemDueDate.startDate"
- :work-item-id="workItem.id"
- :work-item-type="workItemType"
- @error="error = $event"
+ @error="updateError = $event"
/>
</template>
<work-item-weight
@@ -387,14 +435,31 @@ export default {
:weight="workItemWeight.weight"
:work-item-id="workItem.id"
:work-item-type="workItemType"
- @error="error = $event"
+ @error="updateError = $event"
/>
+ <template v-if="workItemsMvc2Enabled">
+ <work-item-iteration
+ v-if="workItemIteration"
+ class="gl-mb-5"
+ :iteration="workItemIteration.iteration"
+ :can-update="canUpdate"
+ :work-item-id="workItem.id"
+ :work-item-type="workItemType"
+ @error="updateError = $event"
+ />
+ </template>
<work-item-description
v-if="hasDescriptionWidget"
:work-item-id="workItem.id"
:full-path="fullPath"
class="gl-pt-5"
- @error="error = $event"
+ @error="updateError = $event"
+ />
+ <gl-empty-state
+ v-if="error"
+ :title="$options.i18n.fetchErrorTitle"
+ :description="error"
+ :svg-path="noAccessSvgPath"
/>
</template>
</section>
diff --git a/app/assets/javascripts/work_items/components/work_item_due_date.vue b/app/assets/javascripts/work_items/components/work_item_due_date.vue
index 05f8fa8f5e1..eae11c2bb2f 100644
--- a/app/assets/javascripts/work_items/components/work_item_due_date.vue
+++ b/app/assets/javascripts/work_items/components/work_item_due_date.vue
@@ -198,7 +198,7 @@ export default {
label-cols="3"
label-cols-lg="2"
>
- <span v-if="isReadonlyWithNoDates" class="gl-text-gray-400 gl-ml-4">
+ <span v-if="isReadonlyWithNoDates" class="gl-text-secondary gl-ml-4">
{{ $options.i18n.none }}
</span>
<div v-else class="gl-display-flex gl-flex-wrap gl-gap-5">
diff --git a/app/assets/javascripts/work_items/components/work_item_labels.vue b/app/assets/javascripts/work_items/components/work_item_labels.vue
index b8b5198be57..05077862690 100644
--- a/app/assets/javascripts/work_items/components/work_item_labels.vue
+++ b/app/assets/javascripts/work_items/components/work_item_labels.vue
@@ -1,16 +1,22 @@
<script>
import { GlTokenSelector, GlLabel, GlSkeletonLoader } from '@gitlab/ui';
-import { debounce } from 'lodash';
+import { debounce, uniqueId, without } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import Tracking from '~/tracking';
import labelSearchQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql';
import LabelItem from '~/vue_shared/components/sidebar/labels_select_widget/label_item.vue';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import { isScopedLabel, scopedLabelKey } from '~/lib/utils/common_utils';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import workItemLabelsSubscription from 'ee_else_ce/work_items/graphql/work_item_labels.subscription.graphql';
import workItemQuery from '../graphql/work_item.query.graphql';
-import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
+import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
-import { i18n, TRACKING_CATEGORY_SHOW, WIDGET_TYPE_LABELS } from '../constants';
+import {
+ i18n,
+ I18N_WORK_ITEM_ERROR_FETCHING_LABELS,
+ TRACKING_CATEGORY_SHOW,
+ WIDGET_TYPE_LABELS,
+} from '../constants';
function isTokenSelectorElement(el) {
return el?.classList.contains('gl-label-close') || el?.classList.contains('dropdown-item');
@@ -52,6 +58,8 @@ export default {
localLabels: [],
searchKey: '',
searchLabels: [],
+ addLabelIds: [],
+ removeLabelIds: [],
};
},
apollo: {
@@ -68,13 +76,21 @@ export default {
error() {
this.$emit('error', i18n.fetchError);
},
+ subscribeToMore: {
+ document: workItemLabelsSubscription,
+ variables() {
+ return {
+ issuableId: this.workItemId,
+ };
+ },
+ },
},
searchLabels: {
query: labelSearchQuery,
variables() {
return {
fullPath: this.fullPath,
- search: this.searchKey,
+ searchTerm: this.searchKey,
};
},
skip() {
@@ -84,11 +100,14 @@ export default {
return data.workspace?.labels?.nodes.map((node) => addClass({ ...node, ...node.label }));
},
error() {
- this.$emit('error', i18n.fetchError);
+ this.$emit('error', I18N_WORK_ITEM_ERROR_FETCHING_LABELS);
},
},
},
computed: {
+ labelsTitleId() {
+ return uniqueId('labels-title-');
+ },
tracking() {
return {
category: TRACKING_CATEGORY_SHOW,
@@ -97,10 +116,7 @@ export default {
};
},
allowScopedLabels() {
- return this.labelsWidget.allowScopedLabels;
- },
- listEmpty() {
- return this.labels.length === 0;
+ return this.labelsWidget?.allowsScopedLabels;
},
containerClass() {
return !this.isEditing ? 'gl-shadow-none!' : '';
@@ -109,10 +125,10 @@ export default {
return this.$apollo.queries.searchLabels.loading;
},
labelsWidget() {
- return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_LABELS);
+ return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_LABELS);
},
labels() {
- return this.labelsWidget?.nodes || [];
+ return this.labelsWidget?.labels?.nodes || [];
},
},
watch: {
@@ -131,44 +147,74 @@ export default {
},
removeLabel({ id }) {
this.localLabels = this.localLabels.filter((label) => label.id !== id);
+ this.removeLabelIds.push(id);
+ this.setLabels();
},
- setLabels(event) {
+ async setLabels() {
+ if (this.addLabelIds.length === 0 && this.removeLabelIds.length === 0) return;
+
this.searchKey = '';
- if (isTokenSelectorElement(event.relatedTarget) || !this.isEditing) return;
this.isEditing = false;
- this.$apollo
- .mutate({
- mutation: localUpdateWorkItemMutation,
+ try {
+ const {
+ data: {
+ workItemUpdate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: updateWorkItemMutation,
variables: {
input: {
id: this.workItemId,
- labels: this.localLabels,
+ labelsWidget: {
+ addLabelIds: this.addLabelIds,
+ removeLabelIds: this.removeLabelIds,
+ },
},
},
- })
- .catch((e) => {
- this.$emit('error', e);
});
- this.track('updated_labels');
+
+ if (errors.length > 0) {
+ this.throwUpdateError();
+ return;
+ }
+
+ this.addLabelIds = [];
+ this.removeLabelIds = [];
+
+ this.track('updated_labels');
+ } catch {
+ this.throwUpdateError();
+ }
+ },
+ throwUpdateError() {
+ this.$emit('error', i18n.updateError);
+ // If mutation is rejected, we're rolling back to initial state
+ this.localLabels = this.labels.map(addClass);
+ this.addLabelIds = [];
+ this.removeLabelIds = [];
+ },
+ handleBlur(event) {
+ if (isTokenSelectorElement(event.relatedTarget) || !this.isEditing) return;
+ this.setLabels();
},
handleFocus() {
this.isEditing = true;
this.searchStarted = true;
},
async focusTokenSelector(labels) {
- if (this.allowScopedLabels) {
- const newLabel = labels[labels.length - 1];
- const existingLabels = labels.slice(0, labels.length - 1);
-
- const newLabelKey = scopedLabelKey(newLabel);
+ const labelsToAdd = without(labels, ...this.localLabels).map((label) => label.id);
+ const labelsToRemove = without(this.localLabels, ...labels).map((label) => label.id);
- const removeLabelsWithSameScope = existingLabels.filter((label) => {
- const sameKey = newLabelKey === scopedLabelKey(label);
- return !sameKey;
- });
+ if (labelsToAdd.length > 0) {
+ this.addLabelIds.push(...labelsToAdd);
+ }
- this.localLabels = [...removeLabelsWithSameScope, newLabel];
+ if (labelsToRemove.length > 0) {
+ this.removeLabelIds.push(...labelsToRemove);
}
+
+ this.localLabels = labels;
+
this.handleFocus();
await this.$nextTick();
this.$refs.tokenSelector.focusTextInput();
@@ -194,13 +240,15 @@ export default {
<template>
<div class="form-row gl-mb-5 work-item-labels gl-relative gl-flex-nowrap">
<span
+ :id="labelsTitleId"
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
data-testid="labels-title"
>{{ __('Labels') }}</span
>
<gl-token-selector
ref="tokenSelector"
- v-model="localLabels"
+ :selected-tokens="localLabels"
+ :aria-labelledby="labelsTitleId"
:container-class="containerClass"
:dropdown-items="searchLabels"
:loading="isLoading"
@@ -210,13 +258,13 @@ export default {
@input="focusTokenSelector"
@text-input="debouncedSearchKeyUpdate"
@focus="handleFocus"
- @blur="setLabels"
+ @blur="handleBlur"
@mouseover.native="handleMouseOver"
@mouseout.native="handleMouseOut"
>
<template #empty-placeholder>
<div
- class="add-labels gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-gray-400 gl-pr-4 gl-top-2"
+ class="add-labels gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-secondary gl-pr-4 gl-top-2"
data-testid="empty-state"
>
<span v-if="canUpdate" class="gl-ml-2">{{ __('Add labels') }}</span>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/index.js b/app/assets/javascripts/work_items/components/work_item_links/index.js
index 8f31b07b6a3..37aa48be6e5 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/index.js
+++ b/app/assets/javascripts/work_items/components/work_item_links/index.js
@@ -16,7 +16,13 @@ export default function initWorkItemLinks() {
return;
}
- const { projectPath, wiHasIssueWeightsFeature, iid } = workItemLinksRoot.dataset;
+ const {
+ projectPath,
+ wiHasIssueWeightsFeature,
+ iid,
+ wiHasIterationsFeature,
+ projectNamespace,
+ } = workItemLinksRoot.dataset;
// eslint-disable-next-line no-new
new Vue({
@@ -31,6 +37,8 @@ export default function initWorkItemLinks() {
iid,
fullPath: projectPath,
hasIssueWeightsFeature: wiHasIssueWeightsFeature,
+ hasIterationsFeature: wiHasIterationsFeature,
+ projectNamespace,
},
render: (createElement) =>
createElement('work-item-links', {
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
index 840fd910272..0d3e951de7e 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
@@ -5,7 +5,7 @@ import { s__ } from '~/locale';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { TYPE_WORK_ITEM } from '~/graphql_shared/constants';
-import issueConfidentialQuery from '~/sidebar/queries/issue_confidential.query.graphql';
+import getIssueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql';
import { isMetaKey } from '~/lib/utils/common_utils';
import { setUrlParams, updateHistory } from '~/lib/utils/url_utility';
@@ -59,7 +59,7 @@ export default {
},
},
parentIssue: {
- query: issueConfidentialQuery,
+ query: getIssueDetailsQuery,
variables() {
return {
fullPath: this.projectPath,
@@ -86,6 +86,9 @@ export default {
confidential() {
return this.parentIssue?.confidential || this.workItem?.confidential || false;
},
+ issuableIteration() {
+ return this.parentIssue?.iteration;
+ },
children() {
return (
this.workItem?.widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY)?.children
@@ -257,7 +260,7 @@ export default {
class="gl-display-inline-flex gl-align-items-center gl-line-height-24 gl-ml-3"
data-testid="children-count"
>
- <gl-icon :name="$options.WIDGET_TYPE_TASK_ICON" class="gl-mr-2 gl-text-gray-500" />
+ <gl-icon :name="$options.WIDGET_TYPE_TASK_ICON" class="gl-mr-2 gl-text-secondary" />
{{ childrenCountLabel }}
</span>
</div>
@@ -294,7 +297,7 @@ export default {
<template v-else>
<div v-if="isChildrenEmpty && !isShownAddForm && !error" data-testid="links-empty">
- <p class="gl-mt-3 gl-mb-4">
+ <p class="gl-mb-3">
{{ $options.i18n.emptyStateMessage }}
</p>
</div>
@@ -305,6 +308,7 @@ export default {
:issuable-gid="issuableGid"
:children-ids="childrenIds"
:parent-confidential="confidential"
+ :parent-iteration="issuableIteration"
@cancel="hideAddForm"
@addWorkItemChild="addChild"
/>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
index 8b848995d44..a01f4616cab 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
@@ -16,7 +16,7 @@ export default {
GlFormGroup,
GlFormInput,
},
- inject: ['projectPath'],
+ inject: ['projectPath', 'hasIterationsFeature'],
props: {
issuableGid: {
type: String,
@@ -33,6 +33,11 @@ export default {
required: false,
default: false,
},
+ parentIteration: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
},
apollo: {
workItemTypes: {
@@ -77,6 +82,9 @@ export default {
taskWorkItemType() {
return this.workItemTypes.find((type) => type.name === TASK_TYPE_NAME)?.id;
},
+ parentIterationId() {
+ return this.parentIteration?.id;
+ },
},
methods: {
getIdFromGraphQLId,
@@ -133,6 +141,13 @@ export default {
} else {
this.unsetError();
this.$emit('addWorkItemChild', data.workItemCreate.workItem);
+ /**
+ * call update mutation only when there is an iteration associated with the issue
+ */
+ // TODO: setting the iteration should be moved to the creation mutation once the backend is done
+ if (this.parentIterationId && this.hasIterationsFeature) {
+ this.addIterationToWorkItem(data.workItemCreate.workItem.id);
+ }
}
})
.catch(() => {
@@ -143,6 +158,19 @@ export default {
this.childToCreateTitle = null;
});
},
+ async addIterationToWorkItem(workItemId) {
+ await this.$apollo.mutate({
+ mutation: updateWorkItemMutation,
+ variables: {
+ input: {
+ id: workItemId,
+ iterationWidget: {
+ iterationId: this.parentIterationId,
+ },
+ },
+ },
+ });
+ },
},
i18n: {
inputLabel: __('Title'),
@@ -182,7 +210,7 @@ export default {
>
<template #result="{ item }">
<div class="gl-display-flex">
- <div class="gl-text-gray-400 gl-mr-4">{{ getIdFromGraphQLId(item.id) }}</div>
+ <div class="gl-text-secondary gl-mr-4">{{ getIdFromGraphQLId(item.id) }}</div>
<div>{{ item.title }}</div>
</div>
</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_milestone.vue b/app/assets/javascripts/work_items/components/work_item_milestone.vue
new file mode 100644
index 00000000000..c4a36e36555
--- /dev/null
+++ b/app/assets/javascripts/work_items/components/work_item_milestone.vue
@@ -0,0 +1,248 @@
+<script>
+import {
+ GlFormGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlSkeletonLoader,
+ GlSearchBoxByType,
+ GlDropdownText,
+} from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import { debounce } from 'lodash';
+import Tracking from '~/tracking';
+import { s__ } from '~/locale';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import projectMilestonesQuery from '~/sidebar/queries/project_milestones.query.graphql';
+import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
+import {
+ I18N_WORK_ITEM_ERROR_UPDATING,
+ sprintfWorkItem,
+ TRACKING_CATEGORY_SHOW,
+} from '../constants';
+
+const noMilestoneId = 'no-milestone-id';
+
+export default {
+ i18n: {
+ MILESTONE: s__('WorkItem|Milestone'),
+ NONE: s__('WorkItem|None'),
+ MILESTONE_PLACEHOLDER: s__('WorkItem|Add to milestone'),
+ NO_MATCHING_RESULTS: s__('WorkItem|No matching results'),
+ NO_MILESTONE: s__('WorkItem|No milestone'),
+ MILESTONE_FETCH_ERROR: s__(
+ 'WorkItem|Something went wrong while fetching milestones. Please try again.',
+ ),
+ },
+ components: {
+ GlFormGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlSkeletonLoader,
+ GlSearchBoxByType,
+ GlDropdownText,
+ },
+ mixins: [Tracking.mixin()],
+ props: {
+ workItemId: {
+ type: String,
+ required: true,
+ },
+ workItemMilestone: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ workItemType: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ canUpdate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ localMilestone: this.workItemMilestone,
+ searchTerm: '',
+ shouldFetch: false,
+ updateInProgress: false,
+ isFocused: false,
+ milestones: [],
+ };
+ },
+ computed: {
+ tracking() {
+ return {
+ category: TRACKING_CATEGORY_SHOW,
+ label: 'item_milestone',
+ property: `type_${this.workItemType}`,
+ };
+ },
+ emptyPlaceholder() {
+ return this.canUpdate ? this.$options.i18n.MILESTONE_PLACEHOLDER : this.$options.i18n.NONE;
+ },
+ dropdownText() {
+ return this.localMilestone?.title || this.emptyPlaceholder;
+ },
+ isLoadingMilestones() {
+ return this.$apollo.queries.milestones.loading;
+ },
+ isNoMilestone() {
+ return this.localMilestone?.id === noMilestoneId || !this.localMilestone?.id;
+ },
+ dropdownClasses() {
+ return {
+ 'gl-text-gray-500!': this.canUpdate && this.isNoMilestone,
+ 'is-not-focused': !this.isFocused,
+ };
+ },
+ },
+ created() {
+ this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
+ apollo: {
+ milestones: {
+ query: projectMilestonesQuery,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ title: this.searchTerm,
+ first: 20,
+ };
+ },
+ skip() {
+ return !this.shouldFetch;
+ },
+ update(data) {
+ return data?.workspace?.attributes?.nodes || [];
+ },
+ error() {
+ this.$emit('error', this.i18n.MILESTONE_FETCH_ERROR);
+ },
+ },
+ },
+ methods: {
+ handleMilestoneClick(milestone) {
+ this.localMilestone = milestone;
+ },
+ onDropdownShown() {
+ this.$refs.search.focusInput();
+ this.shouldFetch = true;
+ this.isFocused = true;
+ },
+ onDropdownHide() {
+ this.isFocused = false;
+ this.searchTerm = '';
+ this.shouldFetch = false;
+ this.updateMilestone();
+ },
+ setSearchKey(value) {
+ this.searchTerm = value;
+ },
+ isMilestoneChecked(milestone) {
+ return this.localMilestone?.id === milestone?.id;
+ },
+ updateMilestone() {
+ if (this.workItemMilestone?.id === this.localMilestone?.id) {
+ return;
+ }
+
+ this.track('updated_milestone');
+ this.updateInProgress = true;
+ this.$apollo
+ .mutate({
+ mutation: localUpdateWorkItemMutation,
+ variables: {
+ input: {
+ id: this.workItemId,
+ milestone: {
+ milestoneId: this.localMilestone?.id,
+ },
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.workItemUpdate.errors.length) {
+ throw new Error(data.workItemUpdate.errors.join('\n'));
+ }
+ })
+ .catch((error) => {
+ const msg = sprintfWorkItem(I18N_WORK_ITEM_ERROR_UPDATING, this.workItemType);
+ this.$emit('error', msg);
+ Sentry.captureException(error);
+ })
+ .finally(() => {
+ this.updateInProgress = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group
+ class="work-item-dropdown"
+ :label="$options.i18n.MILESTONE"
+ label-class="gl-pb-0! gl-overflow-wrap-break gl-mt-3"
+ label-cols="3"
+ label-cols-lg="2"
+ >
+ <span
+ v-if="!canUpdate"
+ class="gl-text-secondary gl-ml-4 gl-mt-3 gl-display-inline-block gl-line-height-normal"
+ data-testid="disabled-text"
+ >
+ {{ dropdownText }}
+ </span>
+ <gl-dropdown
+ v-else
+ :toggle-class="dropdownClasses"
+ :text="dropdownText"
+ :loading="updateInProgress"
+ @shown="onDropdownShown"
+ @hide="onDropdownHide"
+ >
+ <template #header>
+ <gl-search-box-by-type ref="search" :value="searchTerm" @input="debouncedSearchKeyUpdate" />
+ </template>
+ <gl-dropdown-item
+ data-testid="no-milestone"
+ is-check-item
+ :is-checked="isNoMilestone"
+ @click="handleMilestoneClick({ id: 'no-milestone-id' })"
+ >
+ {{ $options.i18n.NO_MILESTONE }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-text v-if="isLoadingMilestones">
+ <gl-skeleton-loader :height="90">
+ <rect width="380" height="10" x="10" y="15" rx="4" />
+ <rect width="280" height="10" x="10" y="30" rx="4" />
+ <rect width="380" height="10" x="10" y="50" rx="4" />
+ <rect width="280" height="10" x="10" y="65" rx="4" />
+ </gl-skeleton-loader>
+ </gl-dropdown-text>
+ <template v-else-if="milestones.length">
+ <gl-dropdown-item
+ v-for="milestone in milestones"
+ :key="milestone.id"
+ is-check-item
+ :is-checked="isMilestoneChecked(milestone)"
+ @click="handleMilestoneClick(milestone)"
+ >
+ {{ milestone.title }}
+ </gl-dropdown-item>
+ </template>
+ <gl-dropdown-text v-else>{{ $options.i18n.NO_MATCHING_RESULTS }}</gl-dropdown-text>
+ </gl-dropdown>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_type_icon.vue b/app/assets/javascripts/work_items/components/work_item_type_icon.vue
index 31e75663055..96a6493357c 100644
--- a/app/assets/javascripts/work_items/components/work_item_type_icon.vue
+++ b/app/assets/javascripts/work_items/components/work_item_type_icon.vue
@@ -53,7 +53,7 @@ export default {
v-gl-tooltip.hover="showTooltipOnHover"
:name="iconName"
:title="workItemTooltipTitle"
- class="gl-mr-2 gl-text-gray-500"
+ class="gl-mr-2 gl-text-secondary"
/>
<span v-if="workItemTypeName" :class="{ 'gl-sr-only': !showText }">{{ workItemTypeName }}</span>
</span>
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
index 78219e62d01..7737c535650 100644
--- a/app/assets/javascripts/work_items/constants.js
+++ b/app/assets/javascripts/work_items/constants.js
@@ -17,6 +17,9 @@ export const WIDGET_TYPE_LABELS = 'LABELS';
export const WIDGET_TYPE_START_AND_DUE_DATE = 'START_AND_DUE_DATE';
export const WIDGET_TYPE_WEIGHT = 'WEIGHT';
export const WIDGET_TYPE_HIERARCHY = 'HIERARCHY';
+export const WIDGET_TYPE_MILESTONE = 'MILESTONE';
+export const WIDGET_TYPE_ITERATION = 'ITERATION';
+
export const WORK_ITEM_VIEWED_STORAGE_KEY = 'gl-show-work-item-banner';
export const WORK_ITEM_TYPE_ENUM_INCIDENT = 'INCIDENT';
@@ -26,13 +29,19 @@ export const WORK_ITEM_TYPE_ENUM_TEST_CASE = 'TEST_CASE';
export const WORK_ITEM_TYPE_ENUM_REQUIREMENTS = 'REQUIREMENTS';
export const i18n = {
- fetchError: s__('WorkItem|Something went wrong when fetching the work item. Please try again.'),
+ fetchErrorTitle: s__('WorkItem|Work item not found'),
+ fetchError: s__(
+ "WorkItem|This work item is not available. It either doesn't exist or you don't have permission to view it.",
+ ),
updateError: s__('WorkItem|Something went wrong while updating the work item. Please try again.'),
confidentialTooltip: s__(
'WorkItem|Only project members with at least the Reporter role, the author, and assignees can view or be notified about this task.',
),
};
+export const I18N_WORK_ITEM_ERROR_FETCHING_LABELS = s__(
+ 'WorkItem|Something went wrong when fetching labels. Please try again.',
+);
export const I18N_WORK_ITEM_ERROR_CREATING = s__(
'WorkItem|Something went wrong when creating %{workItemType}. Please try again.',
);
@@ -48,6 +57,10 @@ export const I18N_WORK_ITEM_ARE_YOU_SURE_DELETE = s__(
);
export const I18N_WORK_ITEM_DELETED = s__('WorkItem|%{workItemType} deleted');
+export const I18N_WORK_ITEM_FETCH_ITERATIONS_ERROR = s__(
+ 'WorkItem|Something went wrong when fetching iterations. Please try again.',
+);
+
export const sprintfWorkItem = (msg, workItemTypeArg) => {
const workItemType = workItemTypeArg || s__('WorkItem|Work item');
return capitalizeFirstCharacter(
diff --git a/app/assets/javascripts/work_items/graphql/get_issue_details.query.graphql b/app/assets/javascripts/work_items/graphql/get_issue_details.query.graphql
new file mode 100644
index 00000000000..6edb6c89f16
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/get_issue_details.query.graphql
@@ -0,0 +1,9 @@
+query issuableDetails($fullPath: ID!, $iid: String) {
+ workspace: project(fullPath: $fullPath) {
+ id
+ issuable: issue(iid: $iid) {
+ id
+ confidential
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql
index 36ffba8a540..36779dfe11e 100644
--- a/app/assets/javascripts/work_items/graphql/typedefs.graphql
+++ b/app/assets/javascripts/work_items/graphql/typedefs.graphql
@@ -1,6 +1,6 @@
enum LocalWidgetType {
ASSIGNEES
- LABELS
+ MILESTONE
}
interface LocalWorkItemWidget {
@@ -12,10 +12,9 @@ type LocalWorkItemAssignees implements LocalWorkItemWidget {
nodes: [UserCore]
}
-type LocalWorkItemLabels implements LocalWorkItemWidget {
+type LocalWorkItemMilestone implements LocalWorkItemWidget {
type: LocalWidgetType!
- allowScopedLabels: Boolean!
- nodes: [Label!]
+ nodes: [Milestone!]
}
extend type WorkItem {
@@ -30,17 +29,14 @@ input LocalUserInput {
avatarUrl: String
}
-input LocalLabelInput {
- id: ID!
- title: String!
- color: String
- description: String
+input LocalMilestoneInput {
+ milestoneId: ID!
}
input LocalUpdateWorkItemInput {
id: WorkItemID!
assignees: [LocalUserInput!]
- labels: [LocalLabelInput]
+ milestone: LocalMilestoneInput!
}
type LocalWorkItemPayload {
diff --git a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
index f4c77ed2ec0..bb05c9b2135 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
@@ -1,4 +1,3 @@
-#import "~/graphql_shared/fragments/user.fragment.graphql"
#import "ee_else_ce/work_items/graphql/work_item_widgets.fragment.graphql"
fragment WorkItem on WorkItem {
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 276061af193..fa0ab56df75 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.query.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
@@ -1,15 +1,16 @@
-#import "~/graphql_shared/fragments/label.fragment.graphql"
#import "./work_item.fragment.graphql"
query workItem($id: WorkItemID!) {
workItem(id: $id) {
...WorkItem
mockWidgets @client {
- ... on LocalWorkItemLabels {
+ ... on LocalWorkItemMilestone {
type
- allowScopedLabels
nodes {
- ...Label
+ id
+ title
+ expired
+ dueDate
}
}
}
diff --git a/app/assets/javascripts/work_items/graphql/work_item_assignees.subscription.graphql b/app/assets/javascripts/work_items/graphql/work_item_assignees.subscription.graphql
new file mode 100644
index 00000000000..d5b2de8c4c6
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/work_item_assignees.subscription.graphql
@@ -0,0 +1,21 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+subscription issuableAssignees($issuableId: IssuableID!) {
+ issuableAssigneesUpdated(issuableId: $issuableId) {
+ ... on WorkItem {
+ id
+ widgets {
+ ... on WorkItemWidgetAssignees {
+ type
+ allowsMultipleAssignees
+ canInviteMembers
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/work_item_dates.subscription.graphql b/app/assets/javascripts/work_items/graphql/work_item_dates.subscription.graphql
index 7e045fdf431..d8760f147e1 100644
--- a/app/assets/javascripts/work_items/graphql/work_item_dates.subscription.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item_dates.subscription.graphql
@@ -4,6 +4,7 @@ subscription issuableDatesUpdated($issuableId: IssuableID!) {
id
widgets {
... on WorkItemWidgetStartAndDueDate {
+ type
dueDate
startDate
}
diff --git a/app/assets/javascripts/work_items/graphql/work_item_labels.subscription.graphql b/app/assets/javascripts/work_items/graphql/work_item_labels.subscription.graphql
new file mode 100644
index 00000000000..86d936bf4dd
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/work_item_labels.subscription.graphql
@@ -0,0 +1,19 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
+subscription workItemLabels($issuableId: IssuableID!) {
+ issuableLabelsUpdated(issuableId: $issuableId) {
+ ... on WorkItem {
+ id
+ widgets {
+ ... on WorkItemWidgetLabels {
+ type
+ labels {
+ nodes {
+ ...Label
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql b/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql
index 3005069f59a..d404cfb10ed 100644
--- a/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item_widgets.fragment.graphql
@@ -1,8 +1,16 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
fragment WorkItemWidgets on WorkItemWidget {
... on WorkItemWidgetDescription {
type
description
descriptionHtml
+ lastEditedAt
+ lastEditedBy {
+ name
+ webPath
+ }
}
... on WorkItemWidgetAssignees {
type
@@ -14,6 +22,14 @@ fragment WorkItemWidgets on WorkItemWidget {
}
}
}
+ ... on WorkItemWidgetLabels {
+ type
+ labels {
+ nodes {
+ ...Label
+ }
+ }
+ }
... on WorkItemWidgetStartAndDueDate {
type
dueDate
diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js
index bb4c7052238..f872d8c6b12 100644
--- a/app/assets/javascripts/work_items/index.js
+++ b/app/assets/javascripts/work_items/index.js
@@ -6,7 +6,13 @@ import { createRouter } from './router';
export const initWorkItemsRoot = () => {
const el = document.querySelector('#js-work-items');
- const { fullPath, hasIssueWeightsFeature, issuesListPath } = el.dataset;
+ const {
+ fullPath,
+ hasIssueWeightsFeature,
+ issuesListPath,
+ projectNamespace,
+ hasIterationsFeature,
+ } = el.dataset;
return new Vue({
el,
@@ -17,6 +23,8 @@ export const initWorkItemsRoot = () => {
fullPath,
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
issuesListPath,
+ projectNamespace,
+ hasIterationsFeature: parseBoolean(hasIterationsFeature),
},
render(createElement) {
return createElement(App);
diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue
index 3b7257591e2..4908b99e5b0 100644
--- a/app/assets/javascripts/work_items/pages/create_work_item.vue
+++ b/app/assets/javascripts/work_items/pages/create_work_item.vue
@@ -6,7 +6,6 @@ import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { sprintfWorkItem, I18N_WORK_ITEM_ERROR_CREATING } from '../constants';
import workItemQuery from '../graphql/work_item.query.graphql';
import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
-import createWorkItemFromTaskMutation from '../graphql/create_work_item_from_task.mutation.graphql';
import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
import ItemTitle from '../components/item_title.vue';
@@ -29,26 +28,6 @@ export default {
required: false,
default: '',
},
- issueGid: {
- type: String,
- required: false,
- default: '',
- },
- lockVersion: {
- type: Number,
- required: false,
- default: null,
- },
- lineNumberStart: {
- type: String,
- required: false,
- default: null,
- },
- lineNumberEnd: {
- type: String,
- required: false,
- default: null,
- },
},
data() {
return {
@@ -136,28 +115,6 @@ export default {
this.error = this.createErrorText;
}
},
- async createWorkItemFromTask() {
- try {
- const { data } = await this.$apollo.mutate({
- mutation: createWorkItemFromTaskMutation,
- variables: {
- input: {
- id: this.issueGid,
- workItemData: {
- lockVersion: this.lockVersion,
- title: this.title,
- lineNumberStart: Number(this.lineNumberStart),
- lineNumberEnd: Number(this.lineNumberEnd),
- workItemTypeId: this.selectedWorkItemType,
- },
- },
- },
- });
- this.$emit('onCreate', data.workItemCreateFromTask.workItem.descriptionHtml);
- } catch {
- this.error = this.createErrorText;
- }
- },
handleTitleInput(title) {
this.title = title;
},
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index 9e81e1d4771..21d9db26382 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -1,13 +1,9 @@
@import './pages/branches';
-@import './pages/clusters';
@import './pages/colors';
@import './pages/commits';
-@import './pages/deploy_keys';
@import './pages/detail_page';
-@import './pages/environment_logs';
@import './pages/events';
@import './pages/groups';
-@import './pages/help';
@import './pages/hierarchy';
@import './pages/issuable';
@import './pages/issues';
@@ -21,11 +17,8 @@
@import './pages/pipelines';
@import './pages/profile';
@import './pages/projects';
-@import './pages/prometheus';
@import './pages/registry';
@import './pages/search';
-@import './pages/service_desk';
@import './pages/settings';
@import './pages/storage_quota';
-@import './pages/tree';
@import './pages/users';
diff --git a/app/assets/stylesheets/bootstrap_migration_reset.scss b/app/assets/stylesheets/bootstrap_migration_reset.scss
index ad315c4ada1..fb112a2ee84 100644
--- a/app/assets/stylesheets/bootstrap_migration_reset.scss
+++ b/app/assets/stylesheets/bootstrap_migration_reset.scss
@@ -54,10 +54,6 @@ strong {
font-weight: bold;
}
-a {
- color: $blue-600;
-}
-
hr {
overflow: hidden;
}
diff --git a/app/assets/stylesheets/components/batch_comments/review_bar.scss b/app/assets/stylesheets/components/batch_comments/review_bar.scss
deleted file mode 100644
index 5e1128dc4ce..00000000000
--- a/app/assets/stylesheets/components/batch_comments/review_bar.scss
+++ /dev/null
@@ -1,71 +0,0 @@
-.review-bar-component {
- position: fixed;
- bottom: 0;
- left: 0;
- z-index: $zindex-dropdown-menu;
- display: flex;
- align-items: center;
- width: 100%;
- height: $toggle-sidebar-height;
- padding-left: $contextual-sidebar-width;
- padding-right: $gutter_collapsed_width;
- background: $white;
- border-top: 1px solid $border-color;
- transition: padding $gl-transition-duration-medium;
-
- .page-with-icon-sidebar & {
- padding-left: $contextual-sidebar-collapsed-width;
- }
-
- .right-sidebar-expanded & {
- padding-right: $gutter_width;
- }
-
- @media (max-width: map-get($grid-breakpoints, sm)-1) {
- padding-left: 0;
- padding-right: 0;
- }
-
- .dropdown {
- margin-left: $grid-size;
- }
-}
-
-.review-bar-content {
- max-width: $limited-layout-width;
- padding: 0 $gl-padding;
- width: 100%;
- margin: 0 auto;
-}
-
-.review-preview-item-header {
- display: flex;
- align-items: center;
- width: 100%;
- margin-bottom: 4px;
-
- > .bold {
- display: flex;
- min-width: 0;
- line-height: 16px;
- }
-}
-
-.review-preview-item-footer {
- display: flex;
- align-items: center;
- margin-top: 4px;
-}
-
-.review-preview-item-content {
- width: 100%;
-
- p {
- display: block;
- width: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- margin-bottom: 0;
- }
-}
diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss
deleted file mode 100644
index 1dcaa47470b..00000000000
--- a/app/assets/stylesheets/components/dashboard_skeleton.scss
+++ /dev/null
@@ -1,78 +0,0 @@
-.dashboard-cards {
- margin-right: -$gl-padding-8;
- margin-left: -$gl-padding-8;
-}
-
-.dashboard-card {
- @include gl-cursor-grab;
-
- &-header {
- &-warning {
- background-color: $orange-100;
- }
- }
-
- &-body {
- min-height: 120px;
-
- &-warning {
- background-color: $orange-50;
- }
-
- &-failed {
- background-color: $red-50;
- }
- }
-
- &-icon {
- color: $gray-300;
- }
-
- &-footer {
- border-radius: $gl-padding;
- height: $gl-padding-32;
-
- &-arrow {
- color: $gray-200;
- }
-
- &-downstream {
- margin-right: -$gl-padding-8;
- }
-
- &-extra {
- background-color: $gray-200;
- font-size: 10px;
- line-height: $gl-line-height;
- width: $gl-padding;
- }
- }
-
- &-header {
- &-failed {
- background-color: $red-100;
- }
- }
-
- &-skeleton-info {
- border-radius: $gl-padding;
- height: $gl-padding;
- overflow: hidden;
-
- &::after {
- content: ' ';
- display: block;
- animation: blockTextShine 1s linear infinite forwards;
- background-repeat: no-repeat;
- background-size: cover;
- background-image: linear-gradient(to right,
- $gray-50 0%,
- $gray-10 20%,
- $gray-50 40%,
- $gray-50 100%);
- border-radius: $gl-padding;
- height: $gl-padding;
- margin-top: -$gl-padding-8;
- }
- }
-}
diff --git a/app/assets/stylesheets/components/date_time_picker.scss b/app/assets/stylesheets/components/date_time_picker.scss
deleted file mode 100644
index 21f085cdaf1..00000000000
--- a/app/assets/stylesheets/components/date_time_picker.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-.date-time-picker {
- .date-time-picker-menu {
- width: 400px;
- }
-}
diff --git a/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
deleted file mode 100644
index b8bd1000bfd..00000000000
--- a/app/assets/stylesheets/components/design_management/design.scss
+++ /dev/null
@@ -1,193 +0,0 @@
-$design-pin-diameter: 28px;
-$design-pin-diameter-sm: 24px;
-$t-gray-a-16-design-pin: rgba($black, 0.16);
-
-.layout-page.design-detail-layout {
- max-height: 100vh;
-}
-
-.design-detail {
- background-color: rgba($modal-backdrop-bg, $modal-backdrop-opacity);
-
- .with-performance-bar & {
- top: 35px;
- }
-
- .comment-indicator {
- border-radius: 50%;
- }
-
- .comment-indicator,
- .frame .design-note-pin {
- &:active {
- cursor: grabbing;
- }
- }
-}
-
-.design-scaler-wrapper {
- bottom: 0;
- left: 50%;
- transform: translateX(-50%);
-}
-
-.design-checkbox {
- position: absolute;
- top: $gl-padding;
- left: 30px;
-}
-
-.image-notes {
- overflow-y: scroll;
- padding: $gl-padding;
- padding-top: 50px;
- background-color: $white;
- flex-shrink: 0;
- min-width: 400px;
- flex-basis: 28%;
-
- .link-inherit-color {
- &:hover,
- &:active,
- &:focus {
- color: inherit;
- text-decoration: none;
- }
- }
-
- .toggle-comments {
- line-height: 20px;
- border-top: 1px solid $border-color;
-
- &.expanded {
- border-bottom: 1px solid $border-color;
- }
-
- .toggle-comments-button:focus {
- text-decoration: none;
- color: $blue-600;
- }
- }
-
- .design-note-pin {
- margin-left: $gl-padding;
- }
-
- .design-discussion {
- margin: $gl-padding 0;
-
- &::before {
- content: '';
- border-left: 1px solid $gray-100;
- position: absolute;
- left: 28px;
- top: -17px;
- height: 17px;
- }
-
- .design-note {
- padding: $gl-padding;
- list-style: none;
- transition: background $gl-transition-duration-medium $general-hover-transition-curve;
- border-top-left-radius: $border-radius-default; // same border radius used by .bordered-box
- border-top-right-radius: $border-radius-default;
-
- a {
- color: inherit;
- }
-
- .note-text a {
- color: $blue-600;
- }
- }
-
- .reply-wrapper {
- padding: $gl-padding;
- }
- }
-
- .reply-wrapper {
- border-top: 1px solid $border-color;
- }
-
- .new-discussion-disclaimer {
- line-height: 20px;
- }
-}
-
-@media (max-width: map-get($grid-breakpoints, lg)) {
- .design-detail {
- overflow-y: scroll;
- }
-
- .image-notes {
- overflow-y: auto;
- min-width: 100%;
- flex-grow: 1;
- flex-basis: auto;
- }
-}
-
-.design-card-header {
- background: transparent;
-}
-
-.design-note-pin {
- display: flex;
- height: $design-pin-diameter;
- width: $design-pin-diameter;
- box-sizing: content-box;
- background-color: $purple-500;
- color: $white;
- font-weight: $gl-font-weight-bold;
- border-radius: 50%;
- z-index: 1;
- padding: 0;
- border: 0;
-
- &.draft {
- background-color: $orange-500;
- }
-
- &.resolved {
- background-color: $gray-500;
- }
-
- &.on-image {
- 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;
- // NOTE: verbose transition property required for Safari
- transition: transform $general-hover-transition-duration linear, box-shadow $general-hover-transition-duration linear, opacity $general-hover-transition-duration linear;
- transform-origin: 0 0;
- transform: translate(-50%, -50%);
-
- &:hover {
- transform: scale(1.2) translate(-50%, -50%);
- }
-
- &:active {
- box-shadow: 0 0 4px $t-gray-a-16-design-pin, 0 4px 12px $t-gray-a-16-design-pin;
- }
-
- &.inactive {
- @include gl-opacity-5;
-
- &:hover {
- @include gl-opacity-10;
- }
- }
- }
-
- &.small {
- position: absolute;
- border: 1px solid $white;
- height: $design-pin-diameter-sm;
- width: $design-pin-diameter-sm;
- }
-
- &.user-avatar {
- top: 25px;
- right: 8px;
- }
-}
diff --git a/app/assets/stylesheets/components/design_management/design_list_item.scss b/app/assets/stylesheets/components/design_management/design_list_item.scss
deleted file mode 100644
index 09af4da37e9..00000000000
--- a/app/assets/stylesheets/components/design_management/design_list_item.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.design-list-item {
- height: 280px;
- text-decoration: none;
-
- .icon-version-status {
- position: absolute;
- right: 10px;
- top: 10px;
- }
-
- .card-body {
- height: 230px;
- }
-}
-
-// This is temporary class to be removed after feature flag removal: https://gitlab.com/gitlab-org/gitlab/-/issues/223197
-.design-list-item-new {
- height: 210px;
-}
diff --git a/app/assets/stylesheets/components/feature_highlight.scss b/app/assets/stylesheets/components/feature_highlight.scss
deleted file mode 100644
index 4d301cc5617..00000000000
--- a/app/assets/stylesheets/components/feature_highlight.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-.gl-sm-mr-3 {
- @media (min-width: $breakpoint-sm) {
- @include gl-mr-3;
- }
-}
diff --git a/app/assets/stylesheets/components/milestone_combobox.scss b/app/assets/stylesheets/components/milestone_combobox.scss
deleted file mode 100644
index 94d295c324b..00000000000
--- a/app/assets/stylesheets/components/milestone_combobox.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-.milestone-combobox {
- .dropdown-menu.show {
- overflow: hidden;
- }
-}
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
index 3bb889b6ba0..293caf6fc87 100644
--- a/app/assets/stylesheets/components/related_items_list.scss
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -75,19 +75,6 @@ $item-remove-button-space: 42px;
}
}
-.item-body,
-.card-header {
- .health-label-short {
- max-width: 0;
- }
-}
-
-.card-header {
- .health-label-short {
- display: initial;
- }
-}
-
.item-meta {
flex-basis: 100%;
font-size: $gl-font-size;
@@ -212,11 +199,6 @@ $item-remove-button-space: 42px;
max-width: 90%;
}
- .card-header {
- .health-label-short {
- max-width: 30px;
- }
- }
}
/* Small devices (landscape phones, 768px and up) */
@@ -239,11 +221,6 @@ $item-remove-button-space: 42px;
}
}
- .card-header {
- .health-label-short {
- max-width: 60px;
- }
- }
}
/* Medium devices (desktops, 992px and up) */
@@ -257,12 +234,6 @@ $item-remove-button-space: 42px;
font-size: inherit; // Base size given to `item-meta` is `$gl-font-size-small`
}
}
-
- .card-header {
- .health-label-short {
- max-width: 100px;
- }
- }
}
/* Large devices (large desktops, 1200px and up) */
@@ -309,15 +280,3 @@ $item-remove-button-space: 42px;
flex-basis: auto;
}
}
-
-@media only screen and (min-width: 1500px) {
- .card-header {
- .health-label-short {
- display: none;
- }
-
- .health-label-long {
- display: block;
- }
- }
-}
diff --git a/app/assets/stylesheets/components/release_block.scss b/app/assets/stylesheets/components/release_block.scss
deleted file mode 100644
index 7e82d0960d7..00000000000
--- a/app/assets/stylesheets/components/release_block.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.release-block {
- transition: background-color 1s linear;
-}
diff --git a/app/assets/stylesheets/components/release_block_milestone_info.scss b/app/assets/stylesheets/components/release_block_milestone_info.scss
deleted file mode 100644
index b6a85ae965a..00000000000
--- a/app/assets/stylesheets/components/release_block_milestone_info.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-.release-block-milestone-info {
- .milestone-progress-bar-container {
- width: 300px;
- min-height: 46px;
- }
-}
diff --git a/app/assets/stylesheets/components/shortcuts_help.scss b/app/assets/stylesheets/components/shortcuts_help.scss
new file mode 100644
index 00000000000..ea2281538b4
--- /dev/null
+++ b/app/assets/stylesheets/components/shortcuts_help.scss
@@ -0,0 +1,29 @@
+.shortcut-help {
+ &-body {
+ height: 80vh;
+ overflow-y: scroll;
+ }
+
+ &-container {
+ column-count: 1;
+ @include media-breakpoint-up(md) {
+ column-count: 2;
+ }
+ column-gap: 1rem;
+ }
+
+ &-mapping {
+ overflow: hidden;
+ break-inside: avoid;
+
+ &-title {
+ margin-left: 40%;
+ }
+
+ kbd {
+ margin: 0.1rem 0;
+ line-height: unset;
+ font-size: unset;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index e977fb92928..07db6b3c147 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -42,7 +42,6 @@
@import 'framework/notes';
@import 'framework/tabs';
@import 'framework/timeline';
-@import 'framework/toggle';
@import 'framework/typography';
@import 'framework/zen';
@import 'framework/wells';
@@ -54,14 +53,11 @@
@import 'framework/emojis';
@import 'framework/icons';
@import 'framework/snippets';
-@import 'framework/memory_graph';
@import 'framework/responsive_tables';
@import 'framework/stacked_progress_bar';
@import 'framework/sortable';
-@import 'framework/ci_variable_list';
@import 'framework/feature_highlight';
@import 'framework/read_more';
-@import 'framework/flex_grid';
@import 'framework/system_messages';
@import 'framework/spinner';
@import 'framework/card';
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index f947042ba51..799777977ed 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -66,7 +66,6 @@
}
&.content-component-block {
- padding: 8px 0;
background-color: $body-bg;
}
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index b1e5ca50a8b..e69d7b4462d 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,9 +1,17 @@
.user-contrib-cell {
+ stroke: $t-gray-a-08;
+
&:hover {
cursor: pointer;
stroke: $black;
}
+ &:focus {
+ @include gl-outline-none;
+ stroke: $white;
+ filter: drop-shadow(1px 0 0.5px $blue-400) drop-shadow(0 1px 0.5px $blue-400) drop-shadow(-1px 0 0.5px $blue-400) drop-shadow(0 -1px 0.5px $blue-400);
+ }
+
// `app/assets/javascripts/pages/users/activity_calendar.js` sets this attribute
@for $i from 1 through length($calendar-activity-colors) {
$color: nth($calendar-activity-colors, $i);
diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss
deleted file mode 100644
index ef4355ad157..00000000000
--- a/app/assets/stylesheets/framework/ci_variable_list.scss
+++ /dev/null
@@ -1,77 +0,0 @@
-.ci-variable-list {
- margin-left: 0;
- margin-bottom: 0;
- padding-left: 0;
- list-style: none;
- clear: both;
-}
-
-.ci-variable-row {
- display: flex;
- align-items: flex-start;
-
- @include media-breakpoint-down(xs) {
- align-items: flex-end;
- }
-
- &:not(:last-child) {
- margin-bottom: $gl-btn-padding;
-
- @include media-breakpoint-down(xs) {
- margin-bottom: 3 * $gl-btn-padding;
- }
- }
-
- &:last-child {
- .ci-variable-body-item:last-child {
- margin-right: $ci-variable-remove-button-width;
-
- @include media-breakpoint-down(xs) {
- margin-right: 0;
- }
- }
-
- .ci-variable-row-remove-button {
- display: none;
- }
-
- @include media-breakpoint-down(xs) {
- .ci-variable-row-body {
- margin-right: $ci-variable-remove-button-width;
- }
- }
- }
-}
-
-.ci-variable-row-body {
- display: flex;
- align-items: flex-start;
- width: 100%;
- padding-bottom: $gl-padding;
-
- @include media-breakpoint-down(xs) {
- display: block;
- }
-}
-
-.ci-variable-body-item {
- flex: 1;
-
- &:not(:last-child) {
- margin-right: $gl-btn-padding;
-
- @include media-breakpoint-down(xs) {
- margin-right: 0;
- margin-bottom: $gl-btn-padding;
- }
- }
-}
-
-.ci-variable-masked-item,
-.ci-variable-protected-item {
- flex: 0 1 auto;
- display: flex;
- align-items: center;
- padding-top: 5px;
- padding-bottom: 5px;
-}
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index 8d1fb5eb55f..f7cd5d7e183 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -43,7 +43,7 @@
z-index: 120;
&.is-sidebar-moved {
- --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 28px});
+ --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 24px});
}
.with-system-header & {
@@ -578,78 +578,6 @@ table.code {
}
}
-// Merge request diff grid layout
-.diff-grid {
- .diff-td {
- // By default min-width is auto with 1fr which causes some overflow problems
- // https://gitlab.com/gitlab-org/gitlab/-/issues/296222
- min-width: 0;
- }
-
- .diff-grid-row {
- display: grid;
- grid-template-columns: 1fr 1fr;
-
- &.diff-grid-row-full {
- grid-template-columns: 1fr;
- }
- }
-
- .diff-grid-left,
- .diff-grid-right {
- display: grid;
- // Zero width column is a placeholder for the EE inline code quality diff
- // see ee/.../diffs.scss for more details
- grid-template-columns: 50px 8px 0 1fr;
- }
-
- .diff-grid-2-col {
- grid-template-columns: 100px 1fr !important;
-
- &.parallel {
- grid-template-columns: 50px 1fr !important;
- }
- }
-
- .diff-grid-comments {
- display: grid;
- grid-template-columns: 1fr 1fr;
- }
-
- .diff-grid-drafts {
- display: grid;
- grid-template-columns: 1fr 1fr;
- }
-
- &.inline-diff-view {
- .diff-grid-comments {
- display: grid;
- grid-template-columns: 1fr;
- }
-
- .diff-grid-drafts {
- display: grid;
- grid-template-columns: 1fr;
- }
-
- .diff-grid-row {
- grid-template-columns: 1fr;
- }
-
- .diff-grid-left,
- .diff-grid-right {
- // Zero width column is a placeholder for the EE inline code quality diff
- // see ee/../diffs.scss for more details
- grid-template-columns: 50px 50px 8px 0 1fr;
- }
- }
-}
-
-// Merge request diff grid layout overrides
-.diff-table.code .diff-tr.line_holder .diff-td.line_content.parallel {
- width: unset;
-}
-
.diff-stats {
align-items: center;
padding: 0 1rem;
@@ -730,68 +658,6 @@ table.code {
}
}
-.diff-comment-avatar-holders {
- position: absolute;
- margin-left: -$gl-padding;
- z-index: 100;
- @include code-icon-size();
-
- &:hover {
- .diff-comment-avatar,
- .diff-comments-more-count {
- @for $i from 1 through 4 {
- $x-pos: 14px;
-
- &:nth-child(#{$i}) {
- @if $i == 4 {
- $x-pos: 14.5px;
- }
-
- transform: translateX((($i * $x-pos) - $x-pos));
-
- &:hover {
- transform: translateX((($i * $x-pos) - $x-pos));
- }
- }
- }
- }
-
- .diff-comments-more-count {
- padding-left: 2px;
- padding-right: 2px;
- width: auto;
- }
- }
-}
-
-.diff-comment-avatar,
-.diff-comments-more-count {
- position: absolute;
- left: 0;
- margin-right: 0;
- border-color: $white;
- cursor: pointer;
- transition: all 0.1s ease-out;
- @include code-icon-size();
-
- @for $i from 1 through 4 {
- &:nth-child(#{$i}) {
- z-index: (4 - $i);
- }
- }
-
- .avatar {
- @include code-icon-size();
- }
-}
-
-.diff-comments-more-count {
- padding-left: 0;
- padding-right: 0;
- overflow: hidden;
- @include code-icon-size();
-}
-
.diff-comments-more-count,
.diff-notes-collapse,
.diff-codequality-collapse {
@@ -867,70 +733,6 @@ table.code {
}
}
-
-.diff-file-changes {
- max-width: 560px;
- width: 100%;
- z-index: 150;
- min-height: $dropdown-min-height;
- max-height: $dropdown-max-height;
- overflow-y: auto;
- margin-bottom: 0;
-
- @include media-breakpoint-up(sm) {
- left: $gl-padding;
- }
-
- .dropdown-input .dropdown-input-search {
- pointer-events: all;
- }
-
- .diff-changed-file {
- display: flex;
- padding-top: 8px;
- padding-bottom: 8px;
- min-width: 0;
- }
-
- .diff-file-changed-icon {
- margin-top: 2px;
- }
-
- .diff-changed-file-content {
- display: flex;
- flex-direction: column;
- min-width: 0;
- }
-
- .diff-changed-file-name,
- .diff-changed-blank-file-name {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .diff-changed-blank-file-name {
- color: $gl-text-color-tertiary;
- font-style: italic;
- }
-
- .diff-changed-file-path {
- color: $gl-text-color-tertiary;
- }
-
- .diff-changed-stats {
- margin-left: auto;
- white-space: nowrap;
- }
-}
-
-.diff-file-changes-path {
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
.note-container {
background-color: $gray-light;
border-top: 1px solid $white-normal;
@@ -1007,27 +809,6 @@ table.code {
}
}
-// Notes tweaks for the Changes tab ONLY
-.diff-tr {
- .timeline-discussion-body {
- clear: left;
-
- .note-body {
- margin-top: 0 !important;
- }
- }
-
- .timeline-entry img.avatar {
- margin-top: -2px;
- margin-right: $gl-padding-8;
- }
-
- // tiny adjustment to vertical align with the note header text
- .discussion-collapsible .timeline-icon {
- padding-top: 2px;
- }
-}
-
.files:not([data-can-create-note]) .frame {
cursor: auto;
}
@@ -1097,6 +878,7 @@ table.code {
.discussion-notes {
min-height: 35px;
+ background-color: transparent;
&:first-child {
// First child does not have the jagged borders
@@ -1121,6 +903,17 @@ table.code {
display: none;
}
}
+
+ ul.notes {
+ li.toggle-replies-widget,
+ .discussion-reply-holder {
+ margin-left: 2.5rem;
+
+ .reply-author-avatar {
+ height: 1.5rem;
+ }
+ }
+ }
}
.discussion-body .image .frame {
@@ -1183,9 +976,15 @@ table.code {
bottom: 100vh;
}
-.diff-line-expand-button {
- &:hover,
- &:focus {
- @include gl-bg-gray-200;
+.diff-grid-row.expansion.match {
+ border-top: 1px solid var(--diff-expansion-background-color);
+ border-bottom: 1px solid var(--diff-expansion-background-color);
+
+ &:first-child {
+ border-top: 0;
+ }
+
+ &:last-child {
+ border-bottom: 0;
}
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index d91524d99e6..d561a7d9450 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -469,6 +469,7 @@
.sidebar-participant {
.merge-icon {
top: calc(50% + 5px);
+ left: 3rem;
}
}
}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index b51daf0e4dc..b63365e8159 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -46,12 +46,14 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
.flash-notice,
.flash-success,
.flash-warning {
- padding: $gl-padding $gl-padding-32 $gl-padding ($gl-padding + $gl-padding-4);
- margin-top: 10px;
-
- .container-fluid,
- .container-fluid.container-limited {
- background: transparent;
+ &:not(.gl-alert) {
+ padding: $gl-padding $gl-padding-32 $gl-padding ($gl-padding + $gl-padding-4);
+ margin-top: 10px;
+
+ .container-fluid,
+ .container-fluid.container-limited {
+ background: transparent;
+ }
}
}
@@ -79,6 +81,19 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
.gl-alert {
@include gl-my-4;
}
+
+ &.flash-container-no-margin {
+ .gl-alert {
+ @include gl-my-0;
+ }
+
+ .flash-alert,
+ .flash-notice,
+ .flash-success,
+ .flash-warning {
+ @include gl-mt-0;
+ }
+ }
}
@include media-breakpoint-down(sm) {
diff --git a/app/assets/stylesheets/framework/flex_grid.scss b/app/assets/stylesheets/framework/flex_grid.scss
deleted file mode 100644
index 10537fd5549..00000000000
--- a/app/assets/stylesheets/framework/flex_grid.scss
+++ /dev/null
@@ -1,52 +0,0 @@
-.flex-grid {
- .grid-row {
- border-bottom: 1px solid $border-color;
- padding: 0;
-
- &:last-child {
- border-bottom: 0;
- }
-
- @include media-breakpoint-down(md) {
- border-bottom: 0;
- border-right: 1px solid $border-color;
-
- &:last-child {
- border-right: 0;
- }
- }
-
- @include media-breakpoint-down(xs) {
- border-right: 0;
- border-bottom: 1px solid $border-color;
-
- &:last-child {
- border-bottom: 0;
- }
- }
- }
-
- .grid-cell {
- padding: 10px $gl-padding;
- border-right: 1px solid $border-color;
-
- &:last-child {
- border-right: 0;
- }
-
- @include media-breakpoint-up(md) {
- flex: 1;
- }
-
- @include media-breakpoint-down(md) {
- border-right: 0;
- flex: none;
- }
- }
-}
-
-.card {
- .card-body.flex-grid {
- padding: 0;
- }
-}
diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
index 40e11b50eba..66d163f608a 100644
--- a/app/assets/stylesheets/framework/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -8,13 +8,15 @@
font-size: 95%;
}
-.gfm-project_member {
+.gfm-project_member,
+.md a.gfm-project_member {
padding: 0 2px;
background-color: $blue-100;
border-radius: $border-radius-default;
+ color: $blue-700;
&.current-user {
- background-color: $orange-50;
+ background-color: $orange-100;
}
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index d2bb1e3d555..e9a507ebb6b 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -109,12 +109,6 @@ ul.content-list {
color: $gl-text-color;
word-break: break-word;
- &.no-description {
- .title {
- line-height: $list-text-height;
- }
- }
-
.title {
font-weight: $gl-font-weight-bold;
}
@@ -221,6 +215,7 @@ ul.content-list {
}
}
+ul.content-list.content-list-items-padding > li,
ul.content-list.issuable-list > li,
ul.content-list.todos-list > li,
.card > .content-list > li {
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index b623f18c4ae..c40cadafb9c 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -44,12 +44,6 @@
}
}
-.div-dropzone-alert {
- margin-top: 5px;
- margin-bottom: 0;
- transition: opacity 200ms ease-in-out;
-}
-
.md-header {
.nav-links {
a {
@@ -155,8 +149,16 @@
.md-suggestion-diff {
display: table !important;
border: 1px solid $border-color !important;
- width: 100% !important;
- font-family: $monospace-font !important;
+
+ td {
+ border: 0 !important;
+ }
+
+ tr.old {
+ td {
+ border-radius: 0 !important;
+ }
+ }
}
.suggestions.md > .markdown-code-block {
@@ -164,23 +166,12 @@
}
.md-suggestion-header {
- height: $suggestion-header-height;
display: flex;
align-items: center;
justify-content: space-between;
background-color: $gray-light;
border: 1px solid $border-color;
- padding: $gl-padding;
border-radius: $border-radius-default $border-radius-default 0 0;
-
- svg {
- vertical-align: middle;
- margin-bottom: 3px;
- }
-
- .dropdown-chevron {
- margin-bottom: 0;
- }
}
@include media-breakpoint-down(xs) {
diff --git a/app/assets/stylesheets/framework/memory_graph.scss b/app/assets/stylesheets/framework/memory_graph.scss
deleted file mode 100644
index 510969e149a..00000000000
--- a/app/assets/stylesheets/framework/memory_graph.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-.memory-graph-container {
- background: $white;
- border: 1px solid $gray-100;
-}
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index f39d53c5b1c..8b2a494527b 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -4,22 +4,6 @@
}
table {
- /*
- * TODO
- * This is a temporary workaround until we fix the neutral
- * color palette in https://gitlab.com/gitlab-org/gitlab/-/issues/213570
- *
- * The overwrites here affected the following areas:
- * - The subscription seats table. When removing this code, the .seats-table
- * <th> and margin overrides should be removed there.
- *
- * Remove this code as soon as this happens
- *
- */
- &.gl-table {
- @include gl-text-gray-500;
- }
-
&.table {
.thead-white {
th {
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index 43effbdd7d7..32e9bba8712 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -28,15 +28,9 @@
.timeline-entry {
color: $gl-text-color;
- // [dark-theme]: only give background color to actual notes
- // in the timeline, the note form textarea has a background
- // of it's own
- &:not(.note-form) {
- background-color: $white;
- }
-
- &:not(.note-form).internal-note {
- background-color: $orange-50;
+ &:not(.note-form).internal-note .timeline-content,
+ &:not(.note-form).draft-note .timeline-content {
+ background-color: $orange-50 !important;
}
.timeline-entry-inner {
@@ -45,23 +39,15 @@
&:target,
&.target {
- background: $line-target-blue;
+ .timeline-content {
+ background: $line-target-blue !important;
+ }
&.system-note .note-body .note-text.system-note-commit-list::after {
background: linear-gradient(rgba($line-target-blue, 0.1) -100px, $line-target-blue 100%);
}
}
- img.avatar {
- margin-right: $gl-padding-12;
-
- @include media-breakpoint-down(sm) {
- width: $gl-spacing-scale-6;
- height: $gl-spacing-scale-6;
- margin-right: $gl-padding-8;
- }
- }
-
.controls {
padding-top: 10px;
float: right;
diff --git a/app/assets/stylesheets/framework/toggle.scss b/app/assets/stylesheets/framework/toggle.scss
deleted file mode 100644
index fd888fdec65..00000000000
--- a/app/assets/stylesheets/framework/toggle.scss
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
-* Toggle button
-*
-* @usage
-* ### Active and Inactive text should be provided as data attributes:
-* <button type="button" class="project-feature-toggle" data-enabled-text="Enabled" data-disabled-text="Disabled">
-* <span class="gl-spinner loading-icon hidden" aria-label="Loading"></span>
-* </button>
-
-* ### Checked should have `is-checked` class
-* <button type="button" class="project-feature-toggle is-checked" data-enabled-text="Enabled" data-disabled-text="Disabled">
-* <span class="gl-spinner loading-icon hidden" aria-label="Loading"></span>
-* </button>
-
-* ### Disabled should have `is-disabled` class
-* <button type="button" class="project-feature-toggle is-disabled" data-enabled-text="Enabled" data-disabled-text="Disabled" disabled="true">
-* <span class="gl-spinner loading-icon hidden" aria-label="Loading"></span>
-* </button>
-
-* ### Loading should have `is-loading` and an icon with `loading-icon` class
-* <button type="button" class="project-feature-toggle is-loading" data-enabled-text="Enabled" data-disabled-text="Disabled">
-* <span class="gl-spinner loading-icon" aria-label="Loading"></span>
-* </button>
-*/
-.project-feature-toggle {
- position: relative;
- border: 0;
- outline: 0;
- display: block;
- width: 50px;
- height: 24px;
- cursor: pointer;
- user-select: none;
- background: $gray-400;
- border-radius: 12px;
- padding: 3px;
- transition: all 0.4s ease;
-
- &::selection,
- &::before::selection,
- &::after::selection {
- background: none;
- }
-
- &:focus {
- outline: none;
- }
-
- .toggle-icon {
- position: relative;
- display: block;
- left: 0;
- border-radius: 9px;
- background: $white;
- transition: all 0.2s ease;
- width: $default-icon-size;
- height: $default-icon-size;
- }
-
- .loading-icon {
- display: none;
- font-size: 12px;
- color: $white;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
-
- &.is-loading {
- .loading-icon {
- display: block;
-
- &::before {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
- }
- }
-
- &.is-checked {
- background: $blue-400;
-
- .toggle-icon {
- left: calc(100% - 18px);
- }
- }
-
- &.is-checked .toggle-icon .toggle-status-checked,
- .toggle-icon .toggle-status-unchecked {
- display: inline;
- }
-
- &.is-checked .toggle-icon .toggle-status-unchecked,
- &.is-loading .toggle-icon,
- .toggle-icon .toggle-status-checked {
- display: none;
- }
-
- &.is-disabled {
- opacity: 0.4;
- cursor: not-allowed;
- }
-
- @include media-breakpoint-down(xs) {
- width: 50px;
-
- &::before,
- &.is-checked::before {
- display: none;
- }
- }
-
- @keyframes animate-enabled {
- 0%,
-
- 35% { opacity: 0; }
-
- 100% { opacity: 1; }
- }
-
- @keyframes animate-disabled {
- 0%,
-
- 35% { opacity: 0; }
-
- 100% { opacity: 1; }
- }
-}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index e79fb843967..2c2d8a2b592 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -33,14 +33,6 @@
}
}
- a {
- color: $blue-600;
-
- > code {
- color: $blue-600;
- }
- }
-
.media-container {
display: inline-flex;
flex-direction: column;
@@ -717,10 +709,6 @@ textarea.js-gfm-input {
font-size: $gl-font-size-monospace;
}
-.strikethrough {
- text-decoration: line-through;
-}
-
h1,
h2,
h3,
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index bd32a817d5d..9cfc5a0201e 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -382,6 +382,8 @@ $gl-text-color-quaternary: #d6d6d6;
$gl-text-color-inverted: $white;
$gl-text-color-secondary-inverted: rgba($white, 0.85);
$gl-text-color-disabled: $gray-400;
+$link-color: $blue-500 !default;
+$link-hover-color: $blue-500 !default;
$gl-grayish-blue: #7f8fa4;
$gl-header-color: #4c4e54;
$gl-font-size-12: 12px;
@@ -440,7 +442,6 @@ $browser-scrollbar-size: 10px;
$header-height: var(--header-height, 48px);
$header-zindex: 1000;
$zindex-dropdown-menu: 300;
-$suggestion-header-height: 46px;
$ide-statusbar-height: 25px;
$fixed-layout-width: 1280px;
$limited-layout-width: 990px;
@@ -650,14 +651,6 @@ $calendar-border-color: rgba(#000, 0.1);
$calendar-user-contrib-text: #959494;
/*
- * Value Stream Analytics
- */
-$cycle-analytics-box-padding: 30px;
-$cycle-analytics-box-text-color: #8c8c8c;
-$cycle-analytics-big-font: 19px;
-$cycle-analytics-dismiss-icon-color: #b2b2b2;
-
-/*
* CI
*/
$ci-skipped-color: #888;
@@ -717,11 +710,11 @@ $job-arrow-margin: 55px;
*/
// See https://gitlab.com/gitlab-org/gitlab/-/issues/332150 to align with Pajamas Design System
$calendar-activity-colors: (
- #ededed,
- #acd5f2,
- #7fa8c9,
- #527ba0,
- #254e77,
+ #f5f5f5,
+ #d4dcfa,
+ #748eff,
+ #3547de,
+ #11118a,
) !default;
/*
diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss
index cfd215b81b8..cb9c623c8fc 100644
--- a/app/assets/stylesheets/framework/wells.scss
+++ b/app/assets/stylesheets/framework/wells.scss
@@ -70,15 +70,6 @@
}
}
-.light-well {
- background-color: $gray-light;
- padding: 15px;
-}
-
-.dark-well {
- background-color: $gray-normal;
-}
-
.card.card-body-centered {
h1 {
font-weight: $gl-font-weight-normal;
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 5e6e10e44be..7fb2bf9a875 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -175,6 +175,8 @@ $dark-il: #de935f;
}
&.diff-grid-row {
+ --diff-expansion-background-color: #{$gray-600};
+
@include dark-diff-expansion-line;
}
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 19c3d6926e7..66cada9181c 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -168,6 +168,8 @@ $monokai-gh: #75715e;
}
&.diff-grid-row {
+ --diff-expansion-background-color: #{$gray-600};
+
@include dark-diff-expansion-line;
}
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 4c716d20ddf..fa1f7211b3e 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -76,6 +76,10 @@
@include match-line;
}
+ &.diff-grid-row {
+ --diff-expansion-background-color: #{$gray-100};
+ }
+
.line-coverage {
@include line-coverage-border-color($green-500, $orange-500);
}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index 70086be1606..a1bba8720a2 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -171,6 +171,8 @@ $solarized-dark-il: #2aa198;
}
&.diff-grid-row {
+ --diff-expansion-background-color: #{lighten($solarized-dark-pre-bg, 10%)};
+
@include dark-diff-expansion-line;
}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 8d223d1fdb1..33945f7cda9 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -156,6 +156,10 @@ $solarized-light-il: #2aa198;
@include match-line;
}
+ &.diff-grid-row {
+ --diff-expansion-background-color: #{$gray-100};
+ }
+
&.diff-grid-row.expansion .diff-td {
background-color: $solarized-light-matchline-bg;
}
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 9761e3961dd..816aa88cfde 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -154,6 +154,8 @@ pre.code,
}
&.diff-grid-row {
+ --diff-expansion-background-color: #{$gray-100};
+
@include diff-match-line;
}
diff --git a/app/assets/stylesheets/lazy_bundles/gridstack.scss b/app/assets/stylesheets/lazy_bundles/gridstack.scss
new file mode 100644
index 00000000000..235b225d747
--- /dev/null
+++ b/app/assets/stylesheets/lazy_bundles/gridstack.scss
@@ -0,0 +1 @@
+@import 'gridstack/dist/gridstack';
diff --git a/app/assets/stylesheets/page_bundles/admin/geo_nodes.scss b/app/assets/stylesheets/page_bundles/admin/geo_nodes.scss
new file mode 100644
index 00000000000..b0aaa48569a
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/admin/geo_nodes.scss
@@ -0,0 +1,45 @@
+@import '../mixins_and_variables_and_functions';
+
+.geo-node-header-grid-columns {
+ grid-template-columns: 1fr auto;
+ grid-gap: $gl-spacing-scale-5;
+
+ @include media-breakpoint-up(md) {
+ grid-template-columns: 3fr 1fr;
+ }
+}
+
+.geo-node-details-grid-columns {
+ grid-gap: $gl-spacing-scale-5;
+
+ @include media-breakpoint-up(lg) {
+ grid-template-columns: 1fr 3fr;
+ }
+}
+
+.geo-node-core-details-grid-columns {
+ grid-template-columns: 1fr 1fr;
+ grid-gap: $gl-spacing-scale-5;
+}
+
+.geo-node-replication-details-grid-columns {
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 1rem;
+
+ @include media-breakpoint-up(md) {
+ grid-template-columns: 1fr 1fr 2fr 2fr;
+ }
+}
+
+.geo-node-filter-grid-columns {
+ grid-template-columns: 1fr;
+
+ @include media-breakpoint-up(md) {
+ grid-template-columns: 3fr 1fr;
+ }
+}
+
+.geo-node-replication-counts-grid {
+ grid-template-columns: 2fr 1fr 1fr;
+ grid-gap: 1rem;
+}
diff --git a/app/assets/stylesheets/page_bundles/admin/geo_replicable.scss b/app/assets/stylesheets/page_bundles/admin/geo_replicable.scss
new file mode 100644
index 00000000000..691d4abd195
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/admin/geo_replicable.scss
@@ -0,0 +1,18 @@
+@import '../mixins_and_variables_and_functions';
+
+.geo-replicable-item-grid {
+ grid-template-columns: 8ch 1fr auto;
+ grid-gap: 1rem;
+}
+
+.geo-replicable-filter-grid {
+ grid-template-columns: 1fr;
+
+ @include media-breakpoint-up(md) {
+ grid-template-columns: 2fr 1fr;
+ }
+
+ @include media-breakpoint-up(xl) {
+ grid-template-columns: 1fr 1fr;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/cluster_agents.scss b/app/assets/stylesheets/page_bundles/cluster_agents.scss
new file mode 100644
index 00000000000..d1fab55738f
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/cluster_agents.scss
@@ -0,0 +1,13 @@
+@import 'mixins_and_variables_and_functions';
+
+.agent-activity-list {
+ .system-note .timeline-entry-inner {
+ .timeline-icon {
+ @include gl-mt-1;
+ }
+ }
+
+ .timeline-entry::before {
+ @include gl-mt-4;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/clusters.scss b/app/assets/stylesheets/page_bundles/clusters.scss
new file mode 100644
index 00000000000..a877ae72e31
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/clusters.scss
@@ -0,0 +1,22 @@
+@import 'mixins_and_variables_and_functions';
+
+.clusters-container {
+ @include media-breakpoint-down(xs) {
+ .nav-controls {
+ @include gl-w-full;
+ order: -1;
+
+ .gl-new-dropdown,
+ .split-content-button {
+ @include gl-w-full;
+ }
+ }
+ }
+}
+
+.cluster-card-item {
+ @include media-breakpoint-up(sm) {
+ @include gl-pt-2;
+ min-height: 372px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/graph_charts.scss b/app/assets/stylesheets/page_bundles/graph_charts.scss
new file mode 100644
index 00000000000..37a75f92a7e
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/graph_charts.scss
@@ -0,0 +1,27 @@
+@import 'page_bundles/mixins_and_variables_and_functions';
+
+.repo-charts {
+ .sub-header {
+ margin: 20px 0;
+ }
+
+ .sub-header-block.border-top {
+ margin-top: 20px;
+ padding: 0;
+ border-top: 1px solid var(--border-color, $border-color);
+ border-bottom: 0;
+ }
+
+ .commit-stats li {
+ font-size: 16px;
+ }
+
+ .tree-ref-header {
+ margin-bottom: 20px;
+
+ h4 {
+ margin: 0;
+ line-height: 36px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index a4a82fdcef3..3951f72112f 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -970,9 +970,6 @@ $ide-commit-header-height: 48px;
.ide-stage {
.card-header {
- display: flex;
- cursor: pointer;
-
.ci-status-icon {
display: flex;
align-items: center;
@@ -980,10 +977,6 @@ $ide-commit-header-height: 48px;
}
}
-.ide-stage-collapse-icon {
- margin: auto 0 auto auto;
-}
-
.ide-job-header {
min-height: 60px;
padding: 0 $gl-padding;
diff --git a/app/assets/stylesheets/page_bundles/incidents.scss b/app/assets/stylesheets/page_bundles/incidents.scss
new file mode 100644
index 00000000000..de246fa14b9
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/incidents.scss
@@ -0,0 +1,73 @@
+@import 'mixins_and_variables_and_functions';
+
+.issuable-discussion.incident-timeline-events {
+ .main-notes-list::before {
+ content: none;
+ }
+
+ .timeline-event-note {
+ p {
+ margin-bottom: 0;
+ font-size: 0.875rem;
+ }
+ }
+}
+
+/**
+ * We have a very specific design proposal where we cannot
+ * use `vertical-line` mixin as it is and have to use
+ * custom styles, see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81284#note_904867444
+ */
+.timeline-entry-vertical-line {
+ &::before,
+ &::after {
+ content: '';
+ border-left: 2px solid $gray-50;
+ position: absolute;
+ left: 20px;
+ height: calc(100% + #{$gl-spacing-scale-5});
+ top: -#{$gl-spacing-scale-5};
+ }
+
+ &:first-child::before {
+ content: none;
+ }
+
+ &:first-child {
+ &::after {
+ top: $gl-spacing-scale-5;
+ height: calc(100% + #{$gl-spacing-scale-5});
+ }
+ }
+
+ &:last-child,
+ &.create-timeline-event {
+ &::before {
+ top: - #{$gl-spacing-scale-5} !important; // Override default positioning
+ @include gl-h-8;
+ }
+
+ &::after {
+ content: none;
+ }
+ }
+}
+
+.timeline-entry:not(:last-child) {
+ .timeline-event-border {
+ @include gl-pb-5;
+ @include gl-border-gray-50;
+ @include gl-border-1;
+ @include gl-border-b-solid;
+ }
+}
+
+.timeline-group:last-child {
+ .timeline-entry:last-child,
+ .create-timeline-event {
+ .timeline-event-bottom-border {
+ @include gl-border-b;
+ @include gl-pt-5;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/issues_show.scss b/app/assets/stylesheets/page_bundles/issues_show.scss
index 26d694f7421..bbdcf1ea0c6 100644
--- a/app/assets/stylesheets/page_bundles/issues_show.scss
+++ b/app/assets/stylesheets/page_bundles/issues_show.scss
@@ -1,5 +1,9 @@
@import 'mixins_and_variables_and_functions';
+$design-pin-diameter: 28px;
+$design-pin-diameter-sm: 24px;
+$t-gray-a-16-design-pin: rgba($black, 0.16);
+
.description {
li {
position: relative;
@@ -23,6 +27,216 @@
}
}
+.design-card-header {
+ background: transparent;
+}
+
+.design-checkbox {
+ position: absolute;
+ top: $gl-padding;
+ left: 30px;
+}
+
+.layout-page.design-detail-layout {
+ max-height: 100vh;
+}
+
+.design-detail {
+ background-color: rgba($modal-backdrop-bg, $modal-backdrop-opacity);
+
+ .with-performance-bar & {
+ top: 35px;
+ }
+
+ .comment-indicator {
+ border-radius: 50%;
+ }
+
+ .comment-indicator,
+ .frame .design-note-pin {
+ &:active {
+ cursor: grabbing;
+ }
+ }
+}
+
+.design-list-item {
+ height: 280px;
+ text-decoration: none;
+
+ .icon-version-status {
+ position: absolute;
+ right: 10px;
+ top: 10px;
+ }
+
+ .card-body {
+ height: 230px;
+ }
+}
+
+// This is temporary class to be removed after feature flag removal: https://gitlab.com/gitlab-org/gitlab/-/issues/223197
+.design-list-item-new {
+ height: 210px;
+}
+
+.design-note-pin {
+ display: flex;
+ height: $design-pin-diameter;
+ width: $design-pin-diameter;
+ box-sizing: content-box;
+ background-color: var(--purple-500, $purple-500);
+ color: var(--white, $white);
+ font-weight: $gl-font-weight-bold;
+ border-radius: 50%;
+ z-index: 1;
+ padding: 0;
+ border: 0;
+
+ &.draft {
+ background-color: var(--orange-500, $orange-500);
+ }
+
+ &.resolved {
+ background-color: var(--gray-500, $gray-500);
+ }
+
+ &.on-image {
+ box-shadow: 0 2px 4px $t-gray-a-08, 0 0 1px $t-gray-a-24;
+ border: var(--white, $white) 2px solid;
+ will-change: transform, box-shadow, opacity;
+ // NOTE: verbose transition property required for Safari
+ transition: transform $general-hover-transition-duration linear, box-shadow $general-hover-transition-duration linear, opacity $general-hover-transition-duration linear;
+ transform-origin: 0 0;
+ transform: translate(-50%, -50%);
+
+ &:hover {
+ transform: scale(1.2) translate(-50%, -50%);
+ }
+
+ &:active {
+ box-shadow: 0 0 4px $t-gray-a-16-design-pin, 0 4px 12px $t-gray-a-16-design-pin;
+ }
+
+ &.inactive {
+ @include gl-opacity-5;
+
+ &:hover {
+ @include gl-opacity-10;
+ }
+ }
+ }
+
+ &.small {
+ position: absolute;
+ border: 1px solid var(--white, $white);
+ height: $design-pin-diameter-sm;
+ width: $design-pin-diameter-sm;
+ }
+
+ &.user-avatar {
+ top: 25px;
+ right: 8px;
+ }
+}
+
+.design-scaler-wrapper {
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+}
+
+.image-notes {
+ overflow-y: scroll;
+ padding: $gl-padding;
+ padding-top: 50px;
+ background-color: var(--white, $white);
+ flex-shrink: 0;
+ min-width: 400px;
+ flex-basis: 28%;
+
+ .link-inherit-color {
+ &:hover,
+ &:active,
+ &:focus {
+ color: inherit;
+ text-decoration: none;
+ }
+ }
+
+ .toggle-comments {
+ line-height: 20px;
+ border-top: 1px solid var(--border-color, $border-color);
+
+ &.expanded {
+ border-bottom: 1px solid var(--border-color, $border-color);
+ }
+
+ .toggle-comments-button:focus {
+ text-decoration: none;
+ color: var(--blue-600, $blue-600);
+ }
+ }
+
+ .design-note-pin {
+ margin-left: $gl-padding;
+ }
+
+ .design-discussion {
+ margin: $gl-padding 0;
+
+ &::before {
+ content: '';
+ border-left: 1px solid var(--gray-100, $gray-100);
+ position: absolute;
+ left: 28px;
+ top: -17px;
+ height: 17px;
+ }
+
+ .design-note {
+ padding: $gl-padding;
+ list-style: none;
+ transition: background $gl-transition-duration-medium $general-hover-transition-curve;
+ border-top-left-radius: $border-radius-default; // same border radius used by .bordered-box
+ border-top-right-radius: $border-radius-default;
+
+ a {
+ color: inherit;
+ }
+
+ .note-text a {
+ color: var(--blue-600, $blue-600);
+ }
+ }
+
+ .reply-wrapper {
+ padding: $gl-padding;
+ }
+ }
+
+ .reply-wrapper {
+ border-top: 1px solid var(--border-color, $border-color);
+ }
+
+ .new-discussion-disclaimer {
+ line-height: 20px;
+ }
+}
+
+@media (max-width: map-get($grid-breakpoints, lg)) {
+ .design-detail {
+ overflow-y: scroll;
+ }
+
+ .image-notes {
+ overflow-y: auto;
+ min-width: 100%;
+ flex-grow: 1;
+ flex-basis: auto;
+ }
+}
+
.is-ghost {
opacity: 0.3;
pointer-events: none;
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 463c8f74342..b2fbce7cb4b 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -9,6 +9,124 @@ $tabs-holder-z-index: 250;
min-width: 0;
}
+.diff-comment-avatar-holders {
+ position: absolute;
+ margin-left: -$gl-padding;
+ z-index: 100;
+ @include code-icon-size();
+
+ &:hover {
+ .diff-comment-avatar,
+ .diff-comments-more-count {
+ @for $i from 1 through 4 {
+ $x-pos: 14px;
+
+ &:nth-child(#{$i}) {
+ @if $i == 4 {
+ $x-pos: 14.5px;
+ }
+
+ transform: translateX((($i * $x-pos) - $x-pos));
+
+ &:hover {
+ transform: translateX((($i * $x-pos) - $x-pos));
+ }
+ }
+ }
+ }
+
+ .diff-comments-more-count {
+ padding-left: 2px;
+ padding-right: 2px;
+ width: auto;
+ }
+ }
+}
+
+.diff-comment-avatar,
+.diff-comments-more-count {
+ position: absolute;
+ left: 0;
+ margin-right: 0;
+ border-color: var(--white, $white);
+ cursor: pointer;
+ transition: all 0.1s ease-out;
+ @include code-icon-size();
+
+ @for $i from 1 through 4 {
+ &:nth-child(#{$i}) {
+ z-index: (4 - $i);
+ }
+ }
+
+ .avatar {
+ @include code-icon-size();
+ }
+}
+
+.diff-comments-more-count {
+ padding-left: 0;
+ padding-right: 0;
+ overflow: hidden;
+ @include code-icon-size();
+}
+
+.diff-file-changes {
+ max-width: 560px;
+ width: 100%;
+ z-index: 150;
+ min-height: $dropdown-min-height;
+ max-height: $dropdown-max-height;
+ overflow-y: auto;
+ margin-bottom: 0;
+
+ @include media-breakpoint-up(sm) {
+ left: $gl-padding;
+ }
+
+ .dropdown-input .dropdown-input-search {
+ pointer-events: all;
+ }
+
+ .diff-changed-file {
+ display: flex;
+ padding-top: 8px;
+ padding-bottom: 8px;
+ min-width: 0;
+ }
+
+ .diff-file-changed-icon {
+ margin-top: 2px;
+ }
+
+ .diff-changed-file-content {
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ }
+
+ .diff-changed-file-name,
+ .diff-changed-blank-file-name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .diff-changed-blank-file-name {
+ color: var(--gray-400, $gray-400);
+ font-style: italic;
+ }
+
+ .diff-changed-file-path {
+ color: var(--gray-400, $gray-400);
+ }
+
+ .diff-changed-stats {
+ margin-left: auto;
+ white-space: nowrap;
+ }
+}
+
.diff-files-holder {
flex: 1;
min-width: 0;
@@ -19,6 +137,111 @@ $tabs-holder-z-index: 250;
}
}
+.diff-grid {
+ .diff-td {
+ // By default min-width is auto with 1fr which causes some overflow problems
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/296222
+ min-width: 0;
+ }
+
+ .diff-grid-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+
+ &.diff-grid-row-full {
+ grid-template-columns: 1fr;
+ }
+ }
+
+ .diff-grid-left,
+ .diff-grid-right {
+ display: grid;
+ // Zero width column is a placeholder for the EE inline code quality diff
+ // see ee/.../diffs.scss for more details
+ grid-template-columns: 50px 8px 0 1fr;
+ }
+
+ .diff-grid-2-col {
+ grid-template-columns: 100px 1fr !important;
+
+ &.parallel {
+ grid-template-columns: 50px 1fr !important;
+ }
+ }
+
+ .diff-grid-comments {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+
+ .diff-grid-drafts {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+
+ .content + .content {
+ @include gl-border-t;
+ }
+ }
+
+ &.inline-diff-view {
+ .diff-grid-comments {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-drafts {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-row {
+ grid-template-columns: 1fr;
+ }
+
+ .diff-grid-left,
+ .diff-grid-right {
+ // Zero width column is a placeholder for the EE inline code quality diff
+ // see ee/../diffs.scss for more details
+ grid-template-columns: 50px 50px 8px 0 1fr;
+ }
+ }
+}
+
+.diff-line-expand-button {
+ &:hover,
+ &:focus {
+ background-color: var(--gray-200, $gray-200);
+ }
+}
+
+.diff-table.code .diff-tr.line_holder .diff-td.line_content.parallel {
+ width: unset;
+}
+
+.diff-tr {
+ .timeline-discussion-body {
+ clear: left;
+
+ .note-body {
+ padding: 0 0 $gl-padding-8;
+ }
+ }
+
+ .timeline-entry img.avatar {
+ margin-top: -2px;
+ margin-right: $gl-padding-8;
+ }
+
+ // tiny adjustment to vertical align with the note header text
+ .discussion-collapsible {
+ margin-left: 1rem;
+
+ .timeline-icon {
+ padding-top: 2px;
+ }
+ }
+}
+
.with-system-header {
--system-header-height: #{$system-header-height};
}
@@ -497,10 +720,6 @@ $tabs-holder-z-index: 250;
}
@include media-breakpoint-down(xs) {
- p {
- font-size: 13px;
- }
-
.btn-grouped {
float: none;
margin-right: 0;
@@ -661,10 +880,10 @@ $tabs-holder-z-index: 250;
&:not(:last-child)::before {
content: '';
- border-left: 1px solid var(--gray-100, $gray-100);
+ border-left: 2px solid var(--gray-10, $gray-10);
position: absolute;
- left: 28px;
bottom: -17px;
+ left: calc(1rem - 1px);
height: 16px;
}
}
@@ -677,7 +896,6 @@ $tabs-holder-z-index: 250;
display: flex;
align-items: center;
flex-wrap: wrap;
- padding: 16px;
z-index: 199;
white-space: nowrap;
@@ -833,6 +1051,12 @@ $tabs-holder-z-index: 250;
.detail-page-header-actions {
.gl-toggle {
@include gl-ml-auto;
+ @include gl-rounded-pill;
+ @include gl-w-9;
+
+ &.is-checked:hover {
+ background-color: $blue-500;
+ }
}
}
@@ -845,3 +1069,88 @@ $tabs-holder-z-index: 250;
@include gl-font-weight-normal;
}
}
+
+.dropdown-menu li button.gl-toggle:not(.is-checked) {
+ background: $gray-400;
+}
+
+.mr-widget-content-row:first-child {
+ border-top: 0;
+}
+
+.memory-graph-container {
+ background: var(--white, $white);
+ border: 1px solid var(--gray-100, $gray-100);
+}
+
+.review-bar-component {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ z-index: $zindex-dropdown-menu;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: $toggle-sidebar-height;
+ padding-left: $contextual-sidebar-width;
+ padding-right: $gutter_collapsed_width;
+ background: var(--white, $white);
+ border-top: 1px solid var(--border-color, $border-color);
+ transition: padding $gl-transition-duration-medium;
+
+ .page-with-icon-sidebar & {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+
+ .right-sidebar-expanded & {
+ padding-right: $gutter_width;
+ }
+
+ @media (max-width: map-get($grid-breakpoints, sm)-1) {
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ .dropdown {
+ margin-left: $grid-size;
+ }
+}
+
+.review-bar-content {
+ max-width: $limited-layout-width;
+ padding: 0 $gl-padding;
+ width: 100%;
+ margin: 0 auto;
+}
+
+.review-preview-item-header {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ margin-bottom: 4px;
+
+ > .bold {
+ display: flex;
+ min-width: 0;
+ line-height: 16px;
+ }
+}
+
+.review-preview-item-footer {
+ display: flex;
+ align-items: center;
+ margin-top: 4px;
+}
+
+.review-preview-item-content {
+ width: 100%;
+
+ p {
+ display: block;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-bottom: 0;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/milestone.scss b/app/assets/stylesheets/page_bundles/milestone.scss
index c401f1a4902..63bcb83e747 100644
--- a/app/assets/stylesheets/page_bundles/milestone.scss
+++ b/app/assets/stylesheets/page_bundles/milestone.scss
@@ -1,4 +1,4 @@
-@import 'mixins_and_variables_and_functions';
+@import 'page_bundles/mixins_and_variables_and_functions';
$status-box-line-height: 26px;
@@ -40,39 +40,6 @@ $status-box-line-height: 26px;
}
}
}
-
- .card-header {
- line-height: $line-height-base;
- padding: 14px 16px;
- display: flex;
- justify-content: space-between;
-
- .title {
- flex: 1;
- flex-grow: 2;
- }
-
- .issuable-count-weight {
- white-space: nowrap;
-
- .counter,
- .weight {
- color: var(--gray-500, $gray-500);
- font-weight: $gl-font-weight-bold;
- }
- }
-
- &.text-white {
- .issuable-count-weight svg {
- fill: $white;
- }
-
- .issuable-count-weight .counter,
- .weight {
- color: var(--white, $white);
- }
- }
- }
}
.milestone-sidebar {
diff --git a/app/assets/stylesheets/page_bundles/operations.scss b/app/assets/stylesheets/page_bundles/operations.scss
new file mode 100644
index 00000000000..497cb63033c
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/operations.scss
@@ -0,0 +1,80 @@
+@import 'mixins_and_variables_and_functions';
+
+.dashboard-cards {
+ margin-right: -$gl-padding-8;
+ margin-left: -$gl-padding-8;
+}
+
+.dashboard-card {
+ @include gl-cursor-grab;
+
+ &-header {
+ &-warning {
+ background-color: var(--orange-100, $orange-100);
+ }
+ }
+
+ &-body {
+ min-height: 120px;
+
+ &-warning {
+ background-color: var(--orange-50, $orange-50);
+ }
+
+ &-failed {
+ background-color: var(--red-50, $red-50);
+ }
+ }
+
+ &-icon {
+ color: var(--gray-300, $gray-300);
+ }
+
+ &-footer {
+ border-radius: $gl-padding;
+ height: $gl-padding-32;
+
+ &-arrow {
+ color: var(--gray-200, $gray-200);
+ }
+
+ &-downstream {
+ margin-right: -$gl-padding-8;
+ }
+
+ &-extra {
+ background-color: var(--gray-200, $gray-200);
+ font-size: 10px;
+ line-height: $gl-line-height;
+ width: $gl-padding;
+ }
+ }
+
+ &-header {
+ &-failed {
+ background-color: var(--red-100, $red-100);
+ }
+ }
+
+ &-skeleton-info {
+ border-radius: $gl-padding;
+ height: $gl-padding;
+ overflow: hidden;
+
+ &::after {
+ content: ' ';
+ display: block;
+ animation: blockTextShine 1s linear infinite forwards;
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-image: linear-gradient(to right,
+ var(--gray-50, $gray-50) 0%,
+ var(--gray-10, $gray-10) 20%,
+ var(--gray-50, $gray-50) 40%,
+ var(--gray-50, $gray-50) 100%);
+ border-radius: $gl-padding;
+ height: $gl-padding;
+ margin-top: -$gl-padding-8;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/pipeline_schedules.scss b/app/assets/stylesheets/page_bundles/pipeline_schedules.scss
index 0c73bece035..af2dac7739e 100644
--- a/app/assets/stylesheets/page_bundles/pipeline_schedules.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline_schedules.scss
@@ -1,60 +1,82 @@
@import 'mixins_and_variables_and_functions';
-.pipeline-schedule-form {
- .gl-field-error {
- margin: 10px 0 0;
- }
+.ci-variable-list {
+ margin-left: 0;
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ clear: both;
}
-.interval-pattern-form-group {
- label {
- margin-right: 10px;
- font-weight: $gl-font-weight-normal;
+.ci-variable-row {
+ display: flex;
+ align-items: flex-start;
- &[for='custom'] {
- margin-right: 0;
- }
+ @include media-breakpoint-down(xs) {
+ align-items: flex-end;
}
- .cron-interval-input-wrapper {
- padding-left: 0;
- }
+ &:not(:last-child) {
+ margin-bottom: $gl-btn-padding;
- .cron-interval-input {
- margin: 10px 10px 0 0;
+ @include media-breakpoint-down(xs) {
+ margin-bottom: 3 * $gl-btn-padding;
+ }
}
-}
-.pipeline-schedule-table-row {
- .branch-name-cell {
- max-width: 300px;
- }
+ &:last-child {
+ .ci-variable-body-item:last-child {
+ margin-right: $ci-variable-remove-button-width;
- a {
- color: var(--gl-text-color, $gl-text-color);
- }
+ @include media-breakpoint-down(xs) {
+ margin-right: 0;
+ }
+ }
+
+ .ci-variable-row-remove-button {
+ display: none;
+ }
- svg {
- vertical-align: middle;
+ @include media-breakpoint-down(xs) {
+ .ci-variable-row-body {
+ margin-right: $ci-variable-remove-button-width;
+ }
+ }
}
}
-.pipeline-schedules-user-callout {
- .bordered-box.content-block {
- border: 1px solid var(--border-color, $border-color);
- background-color: transparent;
+.ci-variable-row-body {
+ display: flex;
+ align-items: flex-start;
+ width: 100%;
+ padding-bottom: $gl-padding;
+
+ @include media-breakpoint-down(xs) {
+ display: block;
}
}
-.cron-preset-radio-input {
- display: inline-block;
+.ci-variable-body-item {
+ flex: 1;
- @include media-breakpoint-down(md) {
- display: block;
- margin: 0 0 5px 5px;
+ &:not(:last-child) {
+ margin-right: $gl-btn-padding;
+
+ @include media-breakpoint-down(xs) {
+ margin-right: 0;
+ margin-bottom: $gl-btn-padding;
+ }
}
+}
- input {
- margin-right: 3px;
+.pipeline-schedule-form {
+ .gl-field-error {
+ margin: 10px 0 0;
+ }
+}
+
+.pipeline-schedule-table-row {
+ a {
+ color: var(--gl-text-color, $gl-text-color);
}
}
diff --git a/app/assets/stylesheets/page_bundles/profile.scss b/app/assets/stylesheets/page_bundles/profile.scss
index 59b8823c113..ac1e9fb024b 100644
--- a/app/assets/stylesheets/page_bundles/profile.scss
+++ b/app/assets/stylesheets/page_bundles/profile.scss
@@ -1,4 +1,33 @@
@import 'mixins_and_variables_and_functions';
+@import 'framework/buttons';
+
+.edit-user {
+ .emoji-menu-toggle-button {
+ @include emoji-menu-toggle-button;
+ }
+
+ @include media-breakpoint-down(sm) {
+ .input-md,
+ .input-lg {
+ max-width: 100%;
+ }
+ }
+}
+
+.modal-profile-crop {
+ .modal-dialog {
+ width: 380px;
+
+ @include media-breakpoint-down(xs) {
+ width: auto;
+ }
+ }
+
+ .profile-crop-image-container {
+ height: 300px;
+ margin: 0 auto;
+ }
+}
.calendar-block {
padding-left: 0;
@@ -210,3 +239,32 @@
.twitter-icon {
color: $twitter;
}
+
+.key-created-at {
+ line-height: 42px;
+}
+
+.key-list-item {
+ .key-list-item-info {
+ @include media-breakpoint-up(sm) {
+ float: left;
+ }
+ }
+}
+
+.ssh-keys-list {
+ .last-used-at,
+ .expires,
+ .key-created-at {
+ line-height: 32px;
+ }
+}
+
+.subkeys-list {
+ @include basic-list;
+
+ li {
+ padding: 3px 0;
+ border: 0;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/project.scss b/app/assets/stylesheets/page_bundles/project.scss
index eec5ebdb383..68bf2fa0f82 100644
--- a/app/assets/stylesheets/page_bundles/project.scss
+++ b/app/assets/stylesheets/page_bundles/project.scss
@@ -191,12 +191,4 @@
h5 {
color: var(--gl-text-color, $gl-text-color);
}
-
- .light-well {
- border-radius: 2px;
-
- color: var(--gray-600, $well-light-text-color);
- font-size: 13px;
- line-height: 1.6em;
- }
}
diff --git a/app/assets/stylesheets/page_bundles/prometheus.scss b/app/assets/stylesheets/page_bundles/prometheus.scss
new file mode 100644
index 00000000000..702c0e4dd72
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/prometheus.scss
@@ -0,0 +1,113 @@
+@import 'mixins_and_variables_and_functions';
+
+.date-time-picker {
+ .date-time-picker-menu {
+ width: 400px;
+ }
+}
+
+.prometheus-graphs {
+ .dropdown-buttons {
+ > div {
+ margin-left: auto;
+ }
+ }
+
+ .col-form-label {
+ line-height: 1;
+ padding-top: 0;
+ }
+
+ .form-group {
+ margin-bottom: map-get($spacing-scale, 3);
+ }
+
+ .variables-section {
+ input {
+ @include media-breakpoint-up(sm) {
+ width: 160px;
+ }
+ }
+ }
+
+ .links-section {
+ .gl-hover-text-blue-600-children:hover {
+ * {
+ @include gl-text-blue-600;
+ }
+ }
+ }
+}
+
+.draggable {
+ &.draggable-enabled {
+ .draggable-panel {
+ border: $gray-100 1px solid;
+ border-radius: $border-radius-default;
+ margin: -1px;
+ cursor: grab;
+ }
+
+ .prometheus-graph {
+ // Make dragging easier by disabling use of chart
+ pointer-events: none;
+ }
+ }
+
+ &.sortable-chosen .draggable-panel {
+ background: $white;
+ box-shadow: 0 0 4px $gray-300;
+ }
+
+ .draggable-remove {
+ z-index: 1;
+
+ .draggable-remove-link {
+ cursor: pointer;
+ color: $gray-400;
+ background-color: $white;
+ }
+ }
+}
+
+.prometheus-graphs-header {
+ .monitor-environment-dropdown-menu,
+ .monitor-dashboard-dropdown-menu {
+ &.show {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ }
+
+ .no-matches-message {
+ padding: $gl-padding-8 $gl-padding-12;
+ }
+ }
+
+ .show-last-dropdown {
+ // same as in .dropdown-menu-toggle
+ // see app/assets/stylesheets/framework/dropdowns.scss
+ width: 160px;
+ }
+}
+
+.prometheus-panel {
+ margin-top: 20px;
+}
+
+.prometheus-graph-group {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.prometheus-graph {
+ padding: $gl-padding-8;
+}
+
+.prometheus-panel-builder {
+ .preview-date-time-picker {
+ // same as in .dropdown-menu-toggle
+ // see app/assets/stylesheets/framework/dropdowns.scss
+ width: 160px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/releases.scss b/app/assets/stylesheets/page_bundles/releases.scss
new file mode 100644
index 00000000000..24ffbf9b90c
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/releases.scss
@@ -0,0 +1,12 @@
+@import 'mixins_and_variables_and_functions';
+
+.release-block {
+ transition: background-color 1s linear;
+}
+
+.release-block-milestone-info {
+ .milestone-progress-bar-container {
+ width: 300px;
+ min-height: 46px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/tree.scss b/app/assets/stylesheets/page_bundles/tree.scss
new file mode 100644
index 00000000000..58e55e11f7e
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/tree.scss
@@ -0,0 +1,207 @@
+@import 'mixins_and_variables_and_functions';
+
+.project-last-commit {
+ min-height: 4.75rem;
+}
+
+.tree-holder {
+ .nav-block {
+ margin: 16px 0;
+
+ .tree-ref-holder {
+ margin-right: 15px;
+ }
+
+ @include media-breakpoint-up(sm) {
+ display: flex;
+
+ .tree-ref-container {
+ flex: 1;
+ }
+
+ .tree-controls {
+ text-align: right;
+
+ .control {
+ float: left;
+ margin-left: 8px;
+ }
+ }
+
+ .tree-ref-holder {
+ float: left;
+ }
+
+ .tree-ref-target-holder {
+ display: inline-block;
+ }
+
+ .repo-breadcrumb {
+ li:last-of-type {
+ position: relative;
+ }
+ }
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .tree-ref-container {
+ justify-content: space-between;
+ }
+
+ .repo-breadcrumb {
+ position: relative;
+
+ .dropdown-menu {
+ left: inherit;
+ right: 0;
+ }
+ }
+
+ .add-to-tree-dropdown {
+ position: absolute;
+ left: 0;
+ right: 0;
+ }
+
+ .tree-controls {
+ margin-bottom: 10px;
+
+ .btn:not(.dropdown-toggle-split),
+ .dropdown,
+ .btn-group {
+ width: 100%;
+ }
+
+ .btn {
+ margin-top: 10px;
+ }
+ }
+ }
+
+ .file-finder {
+ max-width: 500px;
+ width: 100%;
+
+ .file-finder-input {
+ width: 95%;
+ display: inline-block;
+ }
+ }
+
+ .add-to-tree {
+ vertical-align: top;
+ padding: 8px;
+
+ svg {
+ top: 0;
+ }
+ }
+
+ table.tree-table {
+ margin-bottom: 0;
+
+ tr {
+ border-bottom: 1px solid var(--gray-50, $gray-50);
+ border-top: 1px solid var(--gray-50, $gray-50);
+
+ &:last-of-type {
+ border-bottom-color: transparent;
+ }
+
+ td,
+ th {
+ line-height: 21px;
+ }
+
+ th {
+ border: 0;
+ }
+
+ td {
+ border-color: var(--border-color, $border-color);
+ }
+
+ &:hover:not(.tree-truncated-warning) {
+ td {
+ background-color: var(--blue-50, $blue-50);
+ background-clip: padding-box;
+ border-top: 1px solid var(--blue-200, $blue-200);
+ border-bottom: 1px solid var(--blue-200, $blue-200);
+ cursor: pointer;
+ }
+ }
+
+ &.selected {
+ td {
+ background: var(--gray-50, $gray-50);
+ border-top: 1px solid var(--border-color, $border-color);
+ border-bottom: 1px solid var(--border-color, $border-color);
+ }
+ }
+ }
+ }
+
+ .tree-item {
+ .link-container {
+ padding: 0;
+
+ a {
+ padding: 10px $gl-padding;
+ display: block;
+ }
+ }
+
+ .tree-item-file-name {
+ max-width: 320px;
+ vertical-align: middle;
+
+ i,
+ a {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ img {
+ position: relative;
+ top: -1px;
+ }
+ }
+
+ .tree-item-file-external-link {
+ margin-right: 4px;
+
+ span {
+ text-decoration: inherit;
+ }
+ }
+ }
+
+ .tree-truncated-warning {
+ color: var(--orange-600, $orange-600);
+ background-color: var(--orange-50, $orange-50);
+ }
+
+ .tree-time-ago {
+ min-width: 135px;
+ }
+
+ .tree-commit {
+ max-width: 320px;
+
+ .tree-commit-link {
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+}
+
+.blob-commit-info {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.blob-content-holder {
+ margin-top: $gl-padding;
+}
diff --git a/app/assets/stylesheets/page_bundles/work_items.scss b/app/assets/stylesheets/page_bundles/work_items.scss
index d0fc011dde7..820a1a0b53e 100644
--- a/app/assets/stylesheets/page_bundles/work_items.scss
+++ b/app/assets/stylesheets/page_bundles/work_items.scss
@@ -63,3 +63,22 @@
display: none;
}
}
+
+.work-item-dropdown {
+ .gl-dropdown-toggle {
+ background: none !important;
+
+ &:hover,
+ &:focus {
+ box-shadow: inset 0 0 0 $gl-border-size-1 var(--gray-darkest, $gray-darkest) !important;
+ }
+
+ &.is-not-focused:not(:hover, :focus) {
+ box-shadow: none;
+
+ .gl-button-icon {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
deleted file mode 100644
index 27d81d8e53b..00000000000
--- a/app/assets/stylesheets/pages/clusters.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-.clusters-container {
- @include media-breakpoint-down(xs) {
- .nav-controls {
- @include gl-w-full;
- order: -1;
-
- .gl-new-dropdown,
- .split-content-button {
- @include gl-w-full;
- }
- }
- }
-}
-
-.cluster-card-item {
- @include media-breakpoint-up(sm) {
- @include gl-pt-2;
- min-height: 372px;
- }
-}
-
-.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/deploy_keys.scss b/app/assets/stylesheets/pages/deploy_keys.scss
deleted file mode 100644
index 997e42a8fd5..00000000000
--- a/app/assets/stylesheets/pages/deploy_keys.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-.deploy-keys-title {
- padding-bottom: 2px;
- line-height: 2;
-}
diff --git a/app/assets/stylesheets/pages/environment_logs.scss b/app/assets/stylesheets/pages/environment_logs.scss
deleted file mode 100644
index f8f40076142..00000000000
--- a/app/assets/stylesheets/pages/environment_logs.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-.environment-logs-page {
- .content-wrapper {
- padding-bottom: 0;
- }
-}
-
-.environment-logs-viewer {
- height: calc(100vh - #{$environment-logs-difference-xs-up});
- min-height: 700px;
-
- @include media-breakpoint-up(md) {
- height: calc(100vh - #{$environment-logs-difference-md-up});
- }
-
- .with-performance-bar & {
- height: calc(100vh - #{$environment-logs-difference-xs-up} - #{$performance-bar-height});
-
- @include media-breakpoint-up(md) {
- height: calc(100vh - #{$environment-logs-difference-md-up} - #{$performance-bar-height});
- }
- }
-
- .top-bar {
- .date-time-picker-wrapper,
- .dropdown-toggle {
- @include media-breakpoint-up(md) {
- width: 140px;
- }
-
- @include media-breakpoint-up(lg) {
- width: 160px;
- }
- }
- }
-
- .log-lines,
- .gl-infinite-scroll-container {
- // makes scrollbar visible by creating contrast
- background: $black;
- height: 100%;
- }
-
- .build-log {
- @include build-log($black);
- }
-
- .gl-infinite-scroll-legend {
- margin: 0;
- }
-
- .build-loader-animation {
- @include build-loader-animation;
- }
-}
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 33d00027404..ce8dd6684f2 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -84,6 +84,10 @@
iframe.twitter-share-button {
vertical-align: bottom;
}
+
+ .gl-label-scoped.gl-label-sm {
+ --label-inset-border: inset 0 0 0 1px currentColor;
+ }
}
code {
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
deleted file mode 100644
index 9182292ffd3..00000000000
--- a/app/assets/stylesheets/pages/help.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-.shortcut-help {
- &-body {
- height: 80vh;
- overflow-y: scroll;
- }
-
- &-container {
- column-count: 1;
- @include media-breakpoint-up(md) {
- column-count: 2;
- }
- column-gap: 1rem;
- }
-
- &-mapping {
- overflow: hidden;
- break-inside: avoid;
-
- &-title {
- margin-left: 40%;
- }
-
- kbd {
- margin: 0.1rem 0;
- line-height: unset;
- font-size: unset;
- }
- }
-}
-
-.documentation {
- padding: 7px;
- font-size: $gl-font-size-large;
-}
-
-.card.links-card {
- a {
- color: $blue-600;
- }
-}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 85205f4d5ac..6070311dcb6 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -199,12 +199,15 @@
.sidebar-contained-width,
.issuable-sidebar-header {
width: 100%;
- border-bottom: 0;
}
.block {
@include media-breakpoint-up(lg) {
- padding: $gl-spacing-scale-5 0;
+ padding: $gl-spacing-scale-4 0 $gl-spacing-scale-5;
+ }
+
+ &.participants {
+ border-bottom: 0;
}
}
}
@@ -213,7 +216,8 @@
.sidebar-contained-width,
.issuable-sidebar-header {
@include clearfix;
- padding: $gl-padding 0;
+ padding: $gl-spacing-scale-4 0 $gl-spacing-scale-5;
+ border-bottom: 1px solid $border-gray-normal;
// This prevents the mess when resizing the sidebar
// of elements repositioning themselves..
width: $gutter-inner-width;
@@ -235,6 +239,13 @@
}
}
}
+
+ &.time-tracking,
+ &.participants,
+ &.subscriptions,
+ &.with-sub-blocks {
+ padding-top: $gl-spacing-scale-5;
+ }
}
.block-first {
@@ -724,13 +735,7 @@
}
.issue-check {
- padding-right: $gl-padding;
- margin-bottom: 10px;
min-width: 15px;
-
- .selected-issuable {
- vertical-align: text-top;
- }
}
.issuable-milestone,
@@ -851,24 +856,6 @@
}
}
-.issuable-todo-btn {
- .gl-spinner {
- display: none;
- }
-
- &.is-loading {
- .gl-spinner {
- display: inline-block;
- }
-
- &.sidebar-collapsed-icon {
- .issuable-todo-inner {
- display: none;
- }
- }
- }
-}
-
/*
* Following overrides are done to prevent
* legacy dropdown styles from influencing
@@ -927,88 +914,3 @@
}
}
}
-
-.icon-overlap-and-shadow {
- filter:
- drop-shadow(0 1px 0.5px #fff)
- drop-shadow(1px 0 0.5px #fff)
- drop-shadow(0 -1px 0.5px #fff)
- drop-shadow(-1px 0 0.5px #fff);
- margin-right: -7px;
- z-index: 1;
-}
-
-.issuable-discussion.incident-timeline-events {
- .main-notes-list::before {
- content: none;
- }
-
- .timeline-event-note {
- p {
- margin-bottom: 0;
- }
- }
-}
-
-/**
- * We have a very specific design proposal where we cannot
- * use `vertical-line` mixin as it is and have to use
- * custom styles, see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81284#note_904867444
- */
-.timeline-entry-vertical-line {
- &::before,
- &::after {
- content: '';
- border-left: 2px solid $gray-50;
- position: absolute;
- left: 39px;
- height: calc(100% + #{$gl-spacing-scale-5});
- top: -#{$gl-spacing-scale-5};
- }
-
- &:first-child::before {
- content: none;
- }
-
- &:first-child {
- &::after {
- top: $gl-spacing-scale-5;
- height: calc(100% + #{$gl-spacing-scale-5});
- }
- }
-
- &:last-child,
- &.create-timeline-event {
- &::before {
- top: - #{$gl-spacing-scale-5} !important; // Override default positioning
- @include gl-h-8;
- }
-
- &::after {
- content: none;
- }
- }
-}
-
-.timeline-event-note-form {
- padding-left: 20px;
-}
-
-.timeline-entry:not(:last-child) {
- .timeline-event-border {
- @include gl-pb-5;
- @include gl-border-gray-50;
- @include gl-border-1;
- @include gl-border-b-solid;
- }
-}
-
-.timeline-group:last-child {
- .timeline-entry:last-child,
- .create-timeline-event {
- .timeline-event-bottom-border {
- @include gl-border-b;
- @include gl-pt-5;
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 843daec8cda..c88834c088f 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -123,6 +123,9 @@ ul.related-merge-requests > li gl-emoji {
}
.new-branch-col {
+ @include gl-pb-3;
+ @include gl-my-2;
+
.discussion-filter-container {
&:not(:last-child) {
margin-right: $gl-spacing-scale-3;
@@ -221,7 +224,7 @@ ul.related-merge-requests > li gl-emoji {
display: flex;
.new-branch-col {
- padding-top: 0;
+ @include gl-pb-0;
align-self: center;
}
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index fc1b78bf730..438b7b1afa6 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -1,15 +1,15 @@
-$system-note-icon-size: 32px;
-$system-note-svg-size: 16px;
+$system-note-icon-size: 2rem;
+$system-note-svg-size: 1rem;
@mixin vertical-line($left) {
&::before {
content: '';
- border-left: 2px solid $gray-10;
+ border-left: 2px solid var(--gray-10, $gray-10);
position: absolute;
top: 0;
bottom: 0;
- left: $left;
- height: calc(100% - 20px);
+ left: calc(#{$left} - 1px);
+ height: calc(100% + 1.5rem);
}
}
@@ -19,17 +19,10 @@ $system-note-svg-size: 16px;
border-radius: $border-radius-default;
}
-.note-wrapper {
- padding: $gl-padding $gl-padding-8 $gl-padding $gl-padding;
-
- &.outlined {
- @include outline-comment();
- }
-}
-
-.issuable-discussion {
- .main-notes-list {
- @include vertical-line(35px);
+.issuable-discussion:not(.incident-timeline-events),
+.limited-width-notes {
+ .main-notes-list > li.timeline-entry:not(:last-of-type) {
+ @include vertical-line(1rem);
}
}
@@ -41,8 +34,6 @@ $system-note-svg-size: 16px;
position: relative;
&.timeline > .timeline-entry {
- border: 1px solid $border-color;
- border-radius: $border-radius-default;
margin: $gl-padding 0;
&.system-note,
@@ -50,6 +41,117 @@ $system-note-svg-size: 16px;
border: 0;
}
+ .timeline-avatar {
+ height: 2rem;
+ }
+
+ &.note-comment,
+ &.note-skeleton,
+ .draft-note {
+ .timeline-avatar {
+ margin-top: 5px;
+ }
+
+ .timeline-content:not(.flash-container) {
+ margin-left: 2.5rem;
+ border: 1px solid $border-color;
+ border-radius: $gl-border-radius-base;
+ background-color: $white;
+ padding: $gl-padding-4 $gl-padding-8;
+ }
+
+ .note-header-info {
+ min-height: 2rem;
+ display: flex;
+ align-items: center;
+ gap: 0 0.25rem;
+ flex-wrap: wrap;
+ }
+ }
+
+ &.note-discussion {
+ .timeline-content .discussion-wrapper {
+ background-color: transparent;
+ }
+
+ .timeline-content {
+ ul li {
+ &:first-of-type {
+ .timeline-avatar {
+ margin-top: 5px;
+ }
+
+ .timeline-content {
+ margin-left: 2.5rem;
+ border-left: 1px solid $border-color;
+ border-right: 1px solid $border-color;
+ border-top: 1px solid $border-color;
+ border-top-left-radius: $gl-border-radius-base;
+ border-top-right-radius: $gl-border-radius-base;
+ background-color: $white;
+ padding: $gl-padding-4 $gl-padding-8;
+ }
+ }
+
+ &:not(:first-of-type) .timeline-entry-inner {
+ margin-left: 2.5rem;
+ border-left: 1px solid $border-color;
+ border-right: 1px solid $border-color;
+ background-color: $white;
+
+ .timeline-content {
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
+ }
+
+ .timeline-avatar {
+ margin: $gl-padding-8 0 0 $gl-padding;
+ }
+
+ .timeline-discussion-body {
+ margin-left: 2rem;
+ }
+ }
+ }
+
+ .diff-content {
+ ul li:first-of-type {
+ .timeline-avatar {
+ margin-top: 0;
+ }
+
+ .timeline-content {
+ margin-left: 0;
+ border: 0;
+ padding: 0;
+ }
+
+ .timeline-entry-inner {
+ margin-left: 2.5rem;
+ border-left: 1px solid $border-color;
+ border-right: 1px solid $border-color;
+ background-color: $white;
+
+ .timeline-content {
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
+ }
+
+ .timeline-avatar {
+ margin: $gl-padding-8 0 0 $gl-padding;
+ }
+
+ .timeline-discussion-body {
+ margin-left: 2rem;
+ }
+ }
+ }
+ }
+ }
+
+ .discussion-reply-holder {
+ border: 1px solid $border-color;
+ }
+ }
+
&.note-form {
margin-left: 0;
@@ -88,10 +190,14 @@ $system-note-svg-size: 16px;
.card {
margin-bottom: 0;
}
- }
- .timeline-discussion-body {
- margin-top: -$gl-padding-8;
+ .note-header-info {
+ min-height: 2rem;
+ display: flex;
+ align-items: center;
+ gap: 0 0.25rem;
+ flex-wrap: wrap;
+ }
}
.discussion {
@@ -116,16 +222,11 @@ $system-note-svg-size: 16px;
&.being-posted {
pointer-events: none;
opacity: 0.5;
- padding: $gl-padding;
.dummy-avatar {
background-color: $gray-100;
border: 1px solid darken($gray-100, 25%);
}
-
- .note-headline-light {
- margin-left: 3px;
- }
}
.editing-spinner {
@@ -156,6 +257,7 @@ $system-note-svg-size: 16px;
.note-edit-form {
display: block;
margin-left: 0;
+ margin-top: 0.5rem;
&.current-note-edit-form + .note-awards {
display: none;
@@ -164,13 +266,17 @@ $system-note-svg-size: 16px;
}
.note-body {
- padding: $gl-padding-4 $gl-padding-4 $gl-padding-4 $gl-padding-8;
+ padding: 0 $gl-padding-8 $gl-padding-8;
overflow-x: auto;
overflow-y: hidden;
.note-text {
word-wrap: break-word;
}
+
+ .suggestions {
+ margin-top: 4px;
+ }
}
.note-awards {
@@ -186,9 +292,10 @@ $system-note-svg-size: 16px;
}
.system-note {
- padding: $gl-padding-4 20px;
+ padding: $gl-padding-8 0;
margin: $gl-padding 0;
background-color: transparent;
+ font-size: $gl-font-size;
.note-header-info {
padding-bottom: 0;
@@ -229,6 +336,15 @@ $system-note-svg-size: 16px;
.note-body {
overflow: hidden;
+ padding: 0;
+
+ ul {
+ margin: 0.5rem 0;
+ }
+
+ p {
+ margin-left: 1rem;
+ }
.description-version {
position: relative;
@@ -305,7 +421,7 @@ $system-note-svg-size: 16px;
height: $system-note-icon-size;
border: 1px solid $gray-10;
border-radius: $system-note-icon-size;
- margin: -6px 0 0;
+ margin: -8px 0 0;
svg {
width: $system-note-svg-size;
@@ -319,25 +435,38 @@ $system-note-svg-size: 16px;
.discussion-filter-note {
.timeline-icon {
- width: $system-note-icon-size + 6;
- height: $system-note-icon-size + 6;
+ width: $system-note-icon-size;
+ height: $system-note-icon-size;
margin-top: -8px;
}
}
}
+.card .notes {
+ .system-note {
+ margin: 0;
+ padding: 0;
+ }
+
+ .timeline-icon {
+ margin: 8px 0 0 14px;
+ }
+}
+
+
// Diff code in discussion view
.discussion-body .diff-file {
.file-title {
cursor: default;
- border-top: 1px solid $border-color;
+ border-top: 0;
border-radius: 0;
+ margin-left: 2.5rem;
@media (min-width: map-get($grid-breakpoints, md)) {
--initial-top: calc(#{$header-height} + #{$mr-tabs-height});
&.is-sidebar-moved {
- --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 28px});
+ --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 24px});
}
.with-performance-bar & {
@@ -357,6 +486,40 @@ $system-note-svg-size: 16px;
.line_content {
white-space: pre-wrap;
}
+
+ .diff-content {
+ margin-left: 2.5rem;
+
+ &.outdated-lines-wrapper {
+ margin-left: 0;
+ }
+
+ .line_holder td:first-of-type {
+ @include gl-border-l;
+ }
+
+ .line_holder td:last-of-type {
+ @include gl-border-r;
+ }
+
+ .discussion-notes {
+ margin-left: -2.5rem;
+
+ .notes {
+ background-color: transparent;
+ }
+
+ .notes-content {
+ border: 0;
+ }
+
+ .timeline-content {
+ border-top: 0 !important;
+ border-top-left-radius: 0 !important;
+ border-top-right-radius: 0 !important;
+ }
+ }
+ }
}
.tab-pane.notes {
@@ -394,8 +557,17 @@ $system-note-svg-size: 16px;
}
.system-note {
- background-color: $white;
- padding: $gl-padding;
+ background-color: transparent;
+ padding: 0;
+
+ .timeline-icon {
+ margin-top: -2px;
+ }
+
+ .timeline-entry-inner .timeline-icon {
+ margin-top: $grid-size;
+ margin-left: 14px;
+ }
}
}
@@ -487,6 +659,19 @@ $system-note-svg-size: 16px;
.code-commit .notes-content,
.diff-viewer > .image ~ .note-container {
background-color: $white;
+
+ li.note-comment {
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
+
+ .avatar {
+ margin-right: 0;
+ }
+
+ .note-body {
+ padding: $gl-padding-4 0 $gl-padding-8;
+ margin-left: 2.5rem;
+ }
+ }
}
.diff-viewer > .image ~ .note-container form.new-note {
@@ -540,9 +725,21 @@ $system-note-svg-size: 16px;
padding-bottom: 0;
}
+ .timeline-avatar {
+ margin-top: 5px;
+ }
+
.timeline-content {
overflow-x: auto;
overflow-y: hidden;
+ border-radius: $gl-border-radius-base;
+ padding: $gl-padding-8 !important;
+ @include gl-border;
+
+ &.expanded {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
}
&.note-wrapper {
@@ -568,19 +765,10 @@ $system-note-svg-size: 16px;
.note {
@include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
.note-header {
- .note-actions {
- flex-wrap: wrap;
- margin-bottom: $gl-padding-12;
-
- > :first-child {
- margin-left: 0;
- }
+ .note-actions > :first-child {
+ margin-left: 0;
}
}
-
- .note-header-author-name {
- display: block;
- }
}
}
@@ -593,11 +781,6 @@ $system-note-svg-size: 16px;
}
}
-.note-header-info,
-.note-actions {
- padding-bottom: $gl-padding-4;
-}
-
.system-note .note-header-info {
padding-bottom: 0;
}
@@ -618,10 +801,6 @@ $system-note-svg-size: 16px;
}
.note-headline-meta {
- .system-note-separator {
- color: $gray-500;
- }
-
.note-timestamp {
white-space: nowrap;
}
@@ -667,18 +846,20 @@ $system-note-svg-size: 16px;
}
.note-actions {
- align-self: flex-start;
justify-content: flex-end;
flex-shrink: 1;
display: inline-flex;
align-items: center;
- margin-left: 10px;
+ margin-left: $gl-padding-8;
color: $gray-400;
- margin-top: -4px;
@include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
+ justify-content: flex-start;
float: none;
- margin-left: 0;
+
+ .note-actions__mobile-spacer {
+ flex-grow: 1;
+ }
}
}
@@ -719,7 +900,7 @@ $system-note-svg-size: 16px;
}
.discussion-toggle-button {
- padding: 0;
+ padding: 0 $gl-padding-8 0 0;
background-color: transparent;
border: 0;
line-height: 20px;
@@ -868,6 +1049,28 @@ $system-note-svg-size: 16px;
.note-discussion.timeline-entry {
padding-left: 0;
+ ul.notes li.note-wrapper {
+ .timeline-content {
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
+ }
+
+ .timeline-avatar {
+ margin: $gl-padding-8 0 0 $gl-padding;
+ }
+ }
+
+ ul.notes {
+ li.toggle-replies-widget {
+ margin-left: 0;
+ border-left: 0;
+ border-right: 0;
+ }
+
+ div.discussion-reply-holder {
+ margin-left: 0;
+ }
+ }
+
&:last-child {
border-bottom: 0;
}
@@ -894,6 +1097,16 @@ $system-note-svg-size: 16px;
}
}
+ .draft-note-component .draft-note.timeline-entry {
+ .timeline-content:not(.flash-container) {
+ padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
+ }
+
+ .timeline-avatar {
+ margin: $gl-padding-8 0 0 $gl-padding;
+ }
+ }
+
.diff-comment-form {
display: block;
}
@@ -909,8 +1122,7 @@ $system-note-svg-size: 16px;
// See https://gitlab.com/gitlab-org/gitlab-foss/issues/53918#note_117038785
.unstyled-comments {
.discussion-header {
- padding: $gl-padding;
- border-bottom: 1px solid $border-color;
+ padding: $gl-padding 0;
}
.discussion-form-container {
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 951e31ef768..8e4dd39e498 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -1,22 +1,3 @@
-.avatar-image {
- margin-bottom: $grid-size;
-
- .avatar {
- float: none;
- }
-
- @include media-breakpoint-up(sm) {
- float: left;
- margin-bottom: 0;
- }
-}
-
-.avatar-file-name {
- position: relative;
- top: 2px;
- display: inline-block;
-}
-
.account-well {
padding: 10px;
background-color: $gray-light;
@@ -29,42 +10,6 @@
}
}
-.user-avatar-button {
- .file-name {
- display: inline-block;
- padding-left: 10px;
- }
-}
-
-.subkeys-list {
- @include basic-list;
-
- li {
- padding: 3px 0;
- border: 0;
- }
-}
-
-.key-list-item {
- .key-list-item-info {
- @include media-breakpoint-up(sm) {
- float: left;
- }
- }
-}
-
-.ssh-keys-list {
- .last-used-at,
- .expires,
- .key-created-at {
- line-height: 32px;
- }
-}
-
-.key-created-at {
- line-height: 42px;
-}
-
.provider-btn-group {
display: inline-block;
margin-right: 10px;
@@ -113,26 +58,6 @@
}
}
-.modal-profile-crop {
- .modal-dialog {
- width: 380px;
-
- @include media-breakpoint-down(xs) {
- width: auto;
- }
- }
-
- .profile-crop-image-container {
- height: 300px;
- margin: 0 auto;
- }
-
- .crop-controls {
- padding: 10px 0 0;
- text-align: center;
- }
-}
-
.created-personal-access-token-container {
.btn-clipboard {
border: 1px solid $border-color;
@@ -247,36 +172,6 @@ table.u2f-registrations {
}
}
-.edit-user {
- svg {
- fill: $gl-text-color-secondary;
- }
-
- .form-group > label {
- font-weight: $gl-font-weight-bold;
- }
-
- .form-group > .form-text {
- font-size: $gl-font-size;
- }
-
- .emoji-menu-toggle-button {
- @include emoji-menu-toggle-button;
- padding: 6px 10px;
-
- .no-emoji-placeholder {
- position: relative;
- }
- }
-
- @include media-breakpoint-down(sm) {
- .input-md,
- .input-lg {
- max-width: 100%;
- }
- }
-}
-
.help-block {
color: $gl-text-color-secondary;
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 0d45beab983..be8707dcd50 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -269,49 +269,27 @@
color: $gray-200;
}
-pre.light-well {
- border-color: $well-light-border;
-}
-
/*
* Projects list rendered on dashboard and user page
*/
+
+.project-row {
+ .description p {
+ margin-bottom: 0;
+ color: $gl-text-color-secondary;
+ }
+}
+
.projects-list {
@include basic-list;
display: flex;
flex-direction: column;
- // Disable Flexbox for admin page
- &.admin-projects,
- &.group-settings-projects {
- display: block;
-
- .project-row {
- display: block;
-
- .description > p {
- margin-bottom: 0;
- }
- }
- }
-
.project-row {
@include basic-list-stats;
display: flex;
align-items: center;
padding: $gl-padding-12 0;
-
- &.no-description {
- @include media-breakpoint-up(sm) {
- .avatar-container {
- align-self: center;
- }
-
- .metadata-info {
- margin-bottom: 0;
- }
- }
- }
}
h2 {
@@ -634,24 +612,6 @@ pre.light-well {
}
}
-.clearable-input {
- position: relative;
-
- .clear-icon {
- display: none;
- position: absolute;
- right: 9px;
- top: 9px;
- }
-
- &.has-value {
- .clear-icon {
- cursor: pointer;
- display: block;
- }
- }
-}
-
.project-path {
.form-control {
min-width: 100px;
@@ -810,10 +770,3 @@ pre.light-well {
}
}
}
-
-@include media-breakpoint-down(xs) {
- .fork-filtered-search {
- width: 100%;
- margin: $gl-spacing-scale-2 0;
- }
-}
diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss
deleted file mode 100644
index 71cbd7d9613..00000000000
--- a/app/assets/stylesheets/pages/prometheus.scss
+++ /dev/null
@@ -1,114 +0,0 @@
-.prometheus-graphs {
- .dropdown-buttons {
- > div {
- margin-left: auto;
- }
- }
-
- .col-form-label {
- line-height: 1;
- padding-top: 0;
- }
-
- .form-group {
- margin-bottom: map-get($spacing-scale, 3);
- }
-
- .variables-section {
- input {
- @include media-breakpoint-up(sm) {
- width: 160px;
- }
- }
- }
-
- .links-section {
- .gl-hover-text-blue-600-children:hover {
- * {
- @include gl-text-blue-600;
- }
- }
- }
-}
-
-.draggable {
- &.draggable-enabled {
- .draggable-panel {
- border: $gray-100 1px solid;
- border-radius: $border-radius-default;
- margin: -1px;
- cursor: grab;
- }
-
- .prometheus-graph {
- // Make dragging easier by disabling use of chart
- pointer-events: none;
- }
- }
-
- &.sortable-chosen .draggable-panel {
- background: $white;
- box-shadow: 0 0 4px $gray-300;
- }
-
- .draggable-remove {
- z-index: 1;
-
- .draggable-remove-link {
- cursor: pointer;
- color: $gray-400;
- background-color: $white;
- }
- }
-}
-
-.prometheus-graphs-header {
- .monitor-environment-dropdown-menu,
- .monitor-dashboard-dropdown-menu {
- &.show {
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
-
- .no-matches-message {
- padding: $gl-padding-8 $gl-padding-12;
- }
- }
-
- .show-last-dropdown {
- // same as in .dropdown-menu-toggle
- // see app/assets/stylesheets/framework/dropdowns.scss
- width: 160px;
- }
-}
-
-.prometheus-panel {
- margin-top: 20px;
-}
-
-.prometheus-graph-group {
- display: flex;
- flex-wrap: wrap;
-}
-
-.prometheus-graph {
- padding: $gl-padding-8;
-}
-
-.alert-current-setting {
- max-width: 240px;
-
- .badge.badge-danger {
- color: $red-500;
- background-color: $red-100;
- }
-}
-
-.prometheus-panel-builder {
- .preview-date-time-picker {
- // same as in .dropdown-menu-toggle
- // see app/assets/stylesheets/framework/dropdowns.scss
- width: 160px;
- }
-}
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index e8f71c8a21c..a8027d2a5f5 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -268,16 +268,6 @@ input[type='checkbox']:hover {
}
}
- .search-clear {
- position: absolute;
- right: 10px;
- top: 9px;
- padding: 0;
- line-height: 0;
- background: none;
- border: 0;
- }
-
.search-icon {
position: absolute;
left: 10px;
@@ -327,15 +317,6 @@ input[type='checkbox']:hover {
}
}
-.search-clear {
- color: $gray-darkest;
-
- &:hover,
- &:focus {
- color: $blue-600;
- }
-}
-
.search-page-form {
.dropdown-menu-toggle,
.btn-search {
diff --git a/app/assets/stylesheets/pages/service_desk.scss b/app/assets/stylesheets/pages/service_desk.scss
deleted file mode 100644
index 34ab5eb1b74..00000000000
--- a/app/assets/stylesheets/pages/service_desk.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.service-desk-issues {
- .non-empty-state {
- text-align: left;
- padding-bottom: $gl-padding-top;
- border-bottom: 1px solid $border-color;
- }
-}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 56acf6de828..c364b233803 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -188,31 +188,6 @@
}
}
-.nested-settings {
- padding-left: 20px;
-}
-
-.input-btn-group {
- display: flex;
-
- .input-large {
- flex: 1;
- }
-
- .btn {
- margin-left: 10px;
- }
-}
-
-.content-list > .settings-flex-row {
- display: flex;
- align-items: center;
-
- .float-right {
- margin-left: auto;
- }
-}
-
.prometheus-metrics-monitoring {
.card {
.card-toggle {
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
deleted file mode 100644
index a9fbff8958d..00000000000
--- a/app/assets/stylesheets/pages/tree.scss
+++ /dev/null
@@ -1,246 +0,0 @@
-.project-last-commit {
- min-height: 4.75rem;
-}
-
-.tree-holder {
- .nav-block {
- margin: 16px 0;
-
- .tree-ref-holder {
- margin-right: 15px;
- }
-
- @include media-breakpoint-up(sm) {
- display: flex;
-
- .tree-ref-container {
- flex: 1;
- }
-
- .tree-controls {
- text-align: right;
-
- .control {
- float: left;
- margin-left: 8px;
- }
- }
-
- .tree-ref-holder {
- float: left;
- }
-
- .tree-ref-target-holder {
- display: inline-block;
- }
-
- .repo-breadcrumb {
- li:last-of-type {
- position: relative;
- }
- }
- }
- }
-
- @include media-breakpoint-down(xs) {
- .tree-ref-container {
- justify-content: space-between;
- }
-
- .repo-breadcrumb {
- position: relative;
-
- .dropdown-menu {
- left: inherit;
- right: 0;
- }
- }
-
- .add-to-tree-dropdown {
- position: absolute;
- left: 0;
- right: 0;
- }
-
- .tree-controls {
- margin-bottom: 10px;
-
- .btn:not(.dropdown-toggle-split),
- .dropdown,
- .btn-group {
- width: 100%;
- }
-
- .btn {
- margin-top: 10px;
- }
- }
- }
-
- .file-finder {
- max-width: 500px;
- width: 100%;
-
- .file-finder-input {
- width: 95%;
- display: inline-block;
- }
- }
-
- .add-to-tree {
- vertical-align: top;
- padding: 8px;
-
- svg {
- top: 0;
- }
- }
-
- table.tree-table {
- margin-bottom: 0;
-
- tr {
- border-bottom: 1px solid $white-normal;
- border-top: 1px solid $white-normal;
-
- &:last-of-type {
- border-bottom-color: $white;
- }
-
- td,
- th {
- line-height: 21px;
- }
-
- th {
- border: 0;
- }
-
- td {
- border-color: $border-color;
- }
-
- &:hover:not(.tree-truncated-warning) {
- td {
- background-color: $blue-50;
- background-clip: padding-box;
- border-top: 1px solid $blue-200;
- border-bottom: 1px solid $blue-200;
- cursor: pointer;
- }
- }
-
- &.selected {
- td {
- background: $white-normal;
- border-top: 1px solid $border-white-normal;
- border-bottom: 1px solid $border-white-normal;
- }
- }
- }
- }
-
- .tree-item {
- .link-container {
- padding: 0;
-
- a {
- padding: 10px $gl-padding;
- display: block;
- }
- }
-
- .tree-item-file-name {
- max-width: 320px;
- vertical-align: middle;
-
- i,
- a {
- color: $gl-text-color;
- }
-
- img {
- position: relative;
- top: -1px;
- }
- }
-
- .tree-item-file-external-link {
- margin-right: 4px;
-
- span {
- text-decoration: inherit;
- }
- }
- }
-
- .tree-truncated-warning {
- color: $orange-600;
- background-color: $orange-50;
- }
-
- .tree-time-ago {
- min-width: 135px;
- color: $gl-text-color-secondary;
- }
-
- .tree-commit {
- max-width: 320px;
- color: $gl-text-color-secondary;
-
- .tree-commit-link {
- color: $gl-text-color-secondary;
-
- &:hover {
- text-decoration: underline;
- }
- }
- }
-}
-
-.blob-commit-info {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-.blob-content-holder {
- margin-top: $gl-padding;
-}
-
-.blob-upload-dropzone-previews {
- display: flex;
- justify-content: center;
- align-items: center;
- text-align: center;
- border: 2px;
- border-style: dashed;
- border-color: $border-color;
- min-height: 200px;
-}
-
-.repo-charts {
- .sub-header {
- margin: 20px 0;
- }
-
- .sub-header-block.border-top {
- margin-top: 20px;
- padding: 0;
- border-top: 1px solid $white-dark;
- border-bottom: 0;
- }
-
- .commit-stats li {
- font-size: 16px;
- }
-
- .tree-ref-header {
- margin-bottom: 20px;
-
- h4 {
- margin: 0;
- line-height: 36px;
- }
- }
-}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 0450b3d9a44..32c3ce1ba8c 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -57,7 +57,7 @@ strong {
font-weight: bolder;
}
a {
- color: #007bff;
+ color: #428fdc;
text-decoration: none;
background-color: transparent;
}
@@ -368,6 +368,23 @@ kbd kbd {
white-space: nowrap;
border: 0;
}
+.gl-avatar {
+ border-width: 1px;
+ border-style: solid;
+ border-color: rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ flex-shrink: 0;
+}
+.gl-avatar-s24 {
+ width: 1.5rem;
+ height: 1.5rem;
+ font-size: 0.75rem;
+ line-height: 1rem;
+ border-radius: 0.25rem;
+}
+.gl-avatar-circle {
+ border-radius: 50%;
+}
.gl-badge {
display: inline-flex;
align-items: center;
@@ -552,9 +569,6 @@ html [type="button"],
strong {
font-weight: bold;
}
-a {
- color: #63a6e9;
-}
svg {
vertical-align: baseline;
}
@@ -1783,10 +1797,15 @@ body.gl-dark {
background-color: #262626;
border-right: 1px solid #303030;
}
+.gl-avatar:not(.gl-avatar-identicon),
.avatar-container,
.avatar {
background: rgba(255, 255, 255, 0.04);
}
+.gl-avatar {
+ border-style: none;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
+}
body.gl-dark {
--gl-theme-accent: #868686;
}
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 356fb58b4c8..61a2ce8dd62 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -38,7 +38,7 @@ strong {
font-weight: bolder;
}
a {
- color: #007bff;
+ color: #1f75cb;
text-decoration: none;
background-color: transparent;
}
@@ -349,6 +349,23 @@ kbd kbd {
white-space: nowrap;
border: 0;
}
+.gl-avatar {
+ border-width: 1px;
+ border-style: solid;
+ border-color: rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ flex-shrink: 0;
+}
+.gl-avatar-s24 {
+ width: 1.5rem;
+ height: 1.5rem;
+ font-size: 0.75rem;
+ line-height: 1rem;
+ border-radius: 0.25rem;
+}
+.gl-avatar-circle {
+ border-radius: 50%;
+}
.gl-badge {
display: inline-flex;
align-items: center;
@@ -533,9 +550,6 @@ html [type="button"],
strong {
font-weight: bold;
}
-a {
- color: #1068bf;
-}
svg {
vertical-align: baseline;
}
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index edc579f48f6..33e10b9bd62 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -41,7 +41,7 @@ p {
margin-bottom: 1rem;
}
a {
- color: #007bff;
+ color: #1f75cb;
text-decoration: none;
background-color: transparent;
}
@@ -498,7 +498,7 @@ input.btn-block[type="button"] {
.custom-control-input:checked:disabled
~ .custom-control-label::before,
.gl-form-checkbox.custom-control
- .custom-control-input:indeterminate:disabled
+ .custom-control-input[type="checkbox"]:indeterminate:disabled
~ .custom-control-label::before {
background-color: #dbdbdb;
border-color: #dbdbdb;
@@ -507,7 +507,7 @@ input.btn-block[type="button"] {
.custom-control-input:checked:disabled
~ .custom-control-label::after,
.gl-form-checkbox.custom-control
- .custom-control-input:indeterminate:disabled
+ .custom-control-input[type="checkbox"]:indeterminate:disabled
~ .custom-control-label::after {
background-color: #5e5e5e;
}
@@ -595,9 +595,6 @@ h3 {
margin-top: 20px;
margin-bottom: 10px;
}
-a {
- color: #1068bf;
-}
hr {
overflow: hidden;
}
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index 4b74e449e06..8e8cabbe511 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -269,9 +269,9 @@ $well-expand-item: $gray-200;
$well-inner-border: $gray-200;
$calendar-activity-colors: (
- #303030,
- #333861,
- #4a5593,
- #6172c5,
- #788ff7
+ #404040,
+ #1e23a8,
+ #445cf2,
+ #97acff,
+ #e9ebff
);
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index e1ba2a69420..a0d19c3de2a 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -141,7 +141,8 @@ body.gl-dark {
}
}
-.timeline-entry.internal-note:not(.note-form) {
+.timeline-entry.internal-note:not(.note-form) .timeline-content,
+.timeline-entry.draft-note:not(.note-form) .timeline-content {
// soften on darkmode
- background-color: mix($gray-50, $orange-50, 75%);
+ background-color: mix($gray-50, $orange-50, 75%) !important;
}
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index bdb8f758137..4be4fc82d04 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -75,10 +75,8 @@
// .gl-font-size-inherit will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1466
.gl-font-size-inherit,
.font-size-inherit { font-size: inherit; }
-.gl-w-8 { width: px-to-rem($grid-size); }
.gl-w-16 { width: px-to-rem($grid-size * 2); }
.gl-w-64 { width: px-to-rem($grid-size * 8); }
-.gl-h-8 { height: px-to-rem($grid-size); }
.gl-h-32 { height: px-to-rem($grid-size * 4); }
.gl-h-64 { height: px-to-rem($grid-size * 8); }
@@ -119,13 +117,6 @@
flex-basis: 25%;
}
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1168
-.gl-md-ml-3 {
- @media (min-width: $breakpoint-md) {
- margin-left: $gl-spacing-scale-3;
- }
-}
-
// Will be moved to @gitlab/ui (without the !important) in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1462
// We only need the bang (!) version until the non-bang version is added to
// @gitlab/ui utitlities.scss. Once there, it will get loaded in the correct
@@ -152,48 +143,6 @@
display: flex;
}
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1085
-.gl-md-flex-direction-column {
- @media (min-width: $breakpoint-md) {
- flex-direction: column;
- }
-}
-
-// Same as above
-.gl-md-flex-direction-column\! {
- @media (min-width: $breakpoint-md) {
- flex-direction: column !important;
- }
-}
-
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1165
-.gl-xs-mb-4 {
- @media (max-width: $breakpoint-sm) {
- margin-bottom: $gl-spacing-scale-4;
- }
-}
-
-// Same as above
-.gl-xs-mb-4\! {
- @media (max-width: $breakpoint-sm) {
- margin-bottom: $gl-spacing-scale-4 !important;
- }
-}
-
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1168
-.gl-sm-pr-3 {
- @media (min-width: $breakpoint-sm) {
- padding-right: $gl-spacing-scale-3;
- }
-}
-
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1168
-.gl-sm-w-half {
- @media (min-width: $breakpoint-sm) {
- width: 50%;
- }
-}
-
.gl-sm-mr-3 {
@include media-breakpoint-up(sm) {
margin-right: $gl-spacing-scale-3;
@@ -206,21 +155,10 @@
}
}
-.gl-mb-n3 {
- margin-bottom: -$gl-spacing-scale-3;
-}
-
.gl-mr-n2 {
margin-right: -$gl-spacing-scale-2;
}
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1408
-$gl-line-height-42: px-to-rem(42px);
-
-.gl-line-height-42 {
- line-height: $gl-line-height-42;
-}
-
.gl-w-grid-size-30 {
width: $grid-size * 30;
}
@@ -229,26 +167,6 @@ $gl-line-height-42: px-to-rem(42px);
width: $grid-size * 40;
}
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2209
-.gl-max-w-none\! {
- max-width: none !important;
-}
-
-// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2209
-.gl-max-h-none\! {
- 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%;
}
@@ -271,36 +189,15 @@ $gl-line-height-42: px-to-rem(42px);
}
}
-// Will both be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1465
-.gl-text-transparent {
- color: transparent;
-}
-
+// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1465
.gl-focus-ring-border-1-gray-900\! {
@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/2600
-.gl-pr-10 {
- padding-right: $gl-spacing-scale-10;
-}
-
/*
All of the following (up until the "End gitlab-ui#1709" comment) will be moved
to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
*/
-.gl-sm-grid-template-columns-2 {
- @include media-breakpoint-up(sm) {
- grid-template-columns: 1fr 1fr;
- }
-}
-
-.gl-md-grid-template-columns-2 {
- @include media-breakpoint-up(md) {
- grid-template-columns: 1fr 1fr;
- }
-}
-
.gl-md-grid-template-columns-3 {
@include media-breakpoint-up(md) {
grid-template-columns: repeat(3, 1fr);
@@ -313,10 +210,6 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
}
}
-.gl-gap-6 {
- gap: $gl-spacing-scale-6;
-}
-
.gl-max-w-48 {
max-width: $gl-spacing-scale-48;
}
@@ -346,18 +239,6 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
/* End gitlab-ui#1709 */
/*
- * The below two styles will be moved to @gitlab/ui by
- * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1750
- */
-.gl-max-w-34 {
- max-width: 34 * $grid-size;
-}
-
-.gl-max-w-80 {
- max-width: 80 * $grid-size;
-}
-
-/*
* The below style will be moved to @gitlab/ui by
* https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1751
*/
@@ -370,13 +251,3 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
.gl-flex-flow-row-wrap {
flex-flow: row wrap;
}
-
-/*
- * The below style will be moved to @gitlab/ui by
- * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1963
- */
-.gl-gap-y-3 {
- > * + * {
- margin-top: $gl-spacing-scale-3;
- }
-}
diff --git a/app/components/pajamas/alert_component.rb b/app/components/pajamas/alert_component.rb
index cfab34f537e..4475f4cde6e 100644
--- a/app/components/pajamas/alert_component.rb
+++ b/app/components/pajamas/alert_component.rb
@@ -12,8 +12,8 @@ module Pajamas
def initialize(
title: nil, variant: :info, dismissible: true, show_icon: true,
alert_options: {}, close_button_options: {})
- @title = title
- @variant = variant
+ @title = title.presence
+ @variant = filter_attribute(variant&.to_sym, VARIANT_ICONS.keys, default: :info)
@dismissible = dismissible
@show_icon = show_icon
@alert_options = alert_options
@@ -35,7 +35,7 @@ module Pajamas
renders_one :body
renders_one :actions
- ICONS = {
+ VARIANT_ICONS = {
info: 'information-o',
warning: 'warning',
success: 'check-circle',
@@ -44,7 +44,7 @@ module Pajamas
}.freeze
def icon
- ICONS[@variant]
+ VARIANT_ICONS[@variant]
end
def icon_classes
diff --git a/app/components/pajamas/progress_component.html.haml b/app/components/pajamas/progress_component.html.haml
new file mode 100644
index 00000000000..9368fe8b161
--- /dev/null
+++ b/app/components/pajamas/progress_component.html.haml
@@ -0,0 +1,2 @@
+.progress
+ .progress-bar{ class: "bg-#{@variant}", style: "width: #{@value}%;" }
diff --git a/app/components/pajamas/progress_component.rb b/app/components/pajamas/progress_component.rb
new file mode 100644
index 00000000000..1365da13863
--- /dev/null
+++ b/app/components/pajamas/progress_component.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Pajamas
+ class ProgressComponent < Pajamas::Component
+ def initialize(value: 0, variant: :primary)
+ @value = value
+ @variant = filter_attribute(variant, VARIANT_OPTIONS, default: :primary)
+ end
+
+ VARIANT_OPTIONS = [:primary, :success].freeze
+ end
+end
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index 251ba9e29f2..edd85414696 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -10,6 +10,9 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def index
+ push_frontend_feature_flag(:vue_broadcast_messages, current_user)
+ push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user)
+
@broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page])
@broadcast_message = BroadcastMessage.new
end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 2ae0442c005..f3c4244269d 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -60,17 +60,6 @@ class Admin::GroupsController < Admin::ApplicationController
end
end
- def members_update
- member_params = params.permit(:user_id, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group, invite_source: 'admin-group-page')).execute
-
- if result[:status] == :success
- redirect_to [:admin, @group], notice: _('Users were successfully added.')
- else
- redirect_to [:admin, @group], alert: result[:message]
- end
- end
-
def destroy
Groups::DestroyService.new(@group, current_user).async_execute
diff --git a/app/controllers/admin/impersonation_tokens_controller.rb b/app/controllers/admin/impersonation_tokens_controller.rb
index eb279298baf..9d884478e98 100644
--- a/app/controllers/admin/impersonation_tokens_controller.rb
+++ b/app/controllers/admin/impersonation_tokens_controller.rb
@@ -14,11 +14,10 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token = finder.build(impersonation_token_params)
if @impersonation_token.save
- PersonalAccessToken.redis_store!(current_user.id, @impersonation_token.token)
- redirect_to admin_user_impersonation_tokens_path, notice: _("A new impersonation token has been created.")
+ render json: { new_token: @impersonation_token.token,
+ active_access_tokens: active_impersonation_tokens }, status: :ok
else
- set_index_vars
- render :index
+ render json: { errors: @impersonation_token.errors.full_messages }, status: :unprocessable_entity
end
end
@@ -50,19 +49,19 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
PersonalAccessTokensFinder.new({ user: user, impersonation: true }.merge(options))
end
+ def active_impersonation_tokens
+ tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute
+ ::ImpersonationAccessTokenSerializer.new.represent(tokens)
+ end
+
def impersonation_token_params
params.require(:personal_access_token).permit(:name, :expires_at, :impersonation, scopes: [])
end
- # rubocop: disable CodeReuse/ActiveRecord
def set_index_vars
@scopes = Gitlab::Auth.available_scopes_for(current_user)
@impersonation_token ||= finder.build
- @inactive_impersonation_tokens = finder(state: 'inactive').execute
- @active_impersonation_tokens = finder(state: 'active').execute.order(:expires_at)
-
- @new_impersonation_token = PersonalAccessToken.redis_getdel(current_user.id)
+ @active_impersonation_tokens = active_impersonation_tokens
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index a0f72f5e58c..96fe0c9331d 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -4,13 +4,6 @@ class Admin::RunnersController < Admin::ApplicationController
include RunnerSetupScripts
before_action :runner, except: [:index, :tag_list, :runner_setup_scripts]
- before_action only: [:index] do
- push_frontend_feature_flag(:admin_runners_bulk_delete)
- end
-
- before_action only: [:show] do
- push_frontend_feature_flag(:enforce_runner_token_expires_at)
- end
feature_category :runner
urgency :low
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 71d9910b4b8..84efb8b0da8 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -16,7 +16,6 @@ class ApplicationController < ActionController::Base
include SessionlessAuthentication
include SessionsHelper
include ConfirmEmailWarning
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
include Impersonation
include Gitlab::Logging::CloudflareHelper
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 88592efcec7..45585ab84b4 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -25,7 +25,20 @@ class AutocompleteController < ApplicationController
.new(params: params, current_user: current_user, project: project, group: group)
.execute
- render json: UserSerializer.new(params.merge({ current_user: current_user })).represent(users, project: project)
+ presented_users = UserSerializer
+ .new(params.merge({ current_user: current_user }))
+ .represent(users, project: project)
+
+ extra_users = presented_suggested_users
+
+ if extra_users.present?
+ presented_users.reject! do |user|
+ extra_users.any? { |suggested_user| suggested_user[:id] == user[:id] }
+ end
+ presented_users += extra_users
+ end
+
+ render json: presented_users
end
def user
@@ -80,6 +93,11 @@ class AutocompleteController < ApplicationController
def target_branch_params
params.permit(:group_id, :project_id).select { |_, v| v.present? }
end
+
+ # overridden in EE
+ def presented_suggested_users
+ []
+ end
end
AutocompleteController.prepend_mod_with('AutocompleteController')
diff --git a/app/controllers/boards/application_controller.rb b/app/controllers/boards/application_controller.rb
deleted file mode 100644
index 15ef6698472..00000000000
--- a/app/controllers/boards/application_controller.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class ApplicationController < ::ApplicationController
- respond_to :json
-
- rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
-
- private
-
- def board
- @board ||= Board.find(params[:board_id])
- end
-
- def board_parent
- @board_parent ||= board.resource_parent
- end
-
- def record_not_found(exception)
- render json: { error: exception.message }, status: :not_found
- end
- end
-end
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
deleted file mode 100644
index 5028544795c..00000000000
--- a/app/controllers/boards/issues_controller.rb
+++ /dev/null
@@ -1,162 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class IssuesController < Boards::ApplicationController
- # This is the maximum amount of issues which can be moved by one request to
- # bulk_move for now. This is temporary and might be removed in future by
- # introducing an alternative (async?) approach.
- # (related: https://gitlab.com/groups/gitlab-org/-/epics/382)
- MAX_MOVE_ISSUES_COUNT = 50
-
- include BoardsResponses
- include ControllerWithCrossProjectAccessCheck
-
- requires_cross_project_access if: -> { board&.group_board? }
-
- before_action :disable_query_limiting, only: [:bulk_move]
- before_action :authorize_read_issue, only: [:index]
- before_action :authorize_create_issue, only: [:create]
- before_action :authorize_update_issue, only: [:update]
- skip_before_action :authenticate_user!, only: [:index]
- before_action :validate_id_list, only: [:bulk_move]
- before_action :can_move_issues?, only: [:bulk_move]
-
- feature_category :team_planning
- urgency :low
-
- def index
- list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params)
- issues = issues_from(list_service)
-
- ::Boards::Issues::ListService.initialize_relative_positions(board, current_user, issues)
-
- render_issues(issues, list_service.metadata)
- end
-
- def create
- service = Boards::Issues::CreateService.new(board_parent, project, current_user, issue_params)
- issue = service.execute
-
- if issue.valid?
- render json: serialize_as_json(issue)
- else
- render json: issue.errors, status: :unprocessable_entity
- end
- end
-
- def bulk_move
- service = Boards::Issues::MoveService.new(board_parent, current_user, move_params(true))
-
- issues = Issue.find(params[:ids])
-
- render json: service.execute_multiple(issues)
- end
-
- def update
- service = Boards::Issues::MoveService.new(board_parent, current_user, move_params)
-
- if service.execute(issue)
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- private
-
- def issues_from(list_service)
- issues = list_service.execute
- issues.page(params[:page]).per(params[:per] || 20)
- .without_count
- .preload(associations_to_preload) # rubocop: disable CodeReuse/ActiveRecord
- .load
- end
-
- def associations_to_preload
- [
- :milestone,
- :assignees,
- project: [
- :route,
- {
- namespace: [:route]
- }
- ],
- labels: [:priorities],
- notes: [:award_emoji, :author]
- ]
- end
-
- def can_move_issues?
- head(:forbidden) unless can?(current_user, :admin_issue, board)
- end
-
- def serializer_options(issues)
- {}
- end
-
- def render_issues(issues, metadata)
- data = { issues: serialize_as_json(issues, opts: serializer_options(issues)) }
- data.merge!(metadata)
-
- render json: data
- end
-
- def issue
- @issue ||= issues_finder.find(params[:id])
- end
-
- def filter_params
- params.permit(*Boards::Issues::ListService.valid_params).merge(board_id: params[:board_id], id: params[:list_id])
- .reject { |_, value| value.nil? }
- end
-
- def issues_finder
- if board.group_board?
- IssuesFinder.new(current_user, group_id: board_parent.id)
- else
- IssuesFinder.new(current_user, project_id: board_parent.id)
- end
- end
-
- def project
- @project ||= if board.group_board?
- Project.find(issue_params[:project_id])
- else
- board_parent
- end
- end
-
- def move_params(multiple = false)
- id_param = multiple ? :ids : :id
- params.permit(id_param, :board_id, :from_list_id, :to_list_id, :move_before_id, :move_after_id)
- end
-
- def issue_params
- params.require(:issue)
- .permit(:title, :milestone_id, :project_id)
- .merge(board_id: params[:board_id], list_id: params[:list_id])
- end
-
- def serializer
- IssueSerializer.new(current_user: current_user)
- end
-
- def serialize_as_json(resource, opts: {})
- opts.merge!(include_full_project_path: board.group_board?, serializer: 'board')
-
- serializer.represent(resource, opts)
- end
-
- def disable_query_limiting
- Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/35174')
- end
-
- def validate_id_list
- head(:bad_request) unless params[:ids].is_a?(Array)
- head(:unprocessable_entity) if params[:ids].size > MAX_MOVE_ISSUES_COUNT
- end
- end
-end
-
-Boards::IssuesController.prepend_mod_with('Boards::IssuesController')
diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb
deleted file mode 100644
index c3b5a887920..00000000000
--- a/app/controllers/boards/lists_controller.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class ListsController < Boards::ApplicationController
- include BoardsResponses
-
- before_action :authorize_admin_list, only: [:create, :destroy, :generate]
- before_action :authorize_read_list, only: [:index]
- skip_before_action :authenticate_user!, only: [:index]
-
- feature_category :team_planning
- urgency :low
-
- def index
- lists = Boards::Lists::ListService.new(board.resource_parent, current_user).execute(board)
-
- List.preload_preferences_for_user(lists, current_user)
-
- render json: serialize_as_json(lists)
- end
-
- def create
- response = Boards::Lists::CreateService.new(board.resource_parent, current_user, create_list_params).execute(board)
-
- if response.success?
- render json: serialize_as_json(response.payload[:list])
- else
- render json: { errors: response.errors }, status: :unprocessable_entity
- end
- end
-
- def update
- list = board.lists.find(params[:id])
- service = Boards::Lists::UpdateService.new(board_parent, current_user, update_list_params)
- result = service.execute(list)
-
- if result.success?
- head :ok
- else
- head result.http_status
- end
- end
-
- def destroy
- list = board.lists.destroyable.find(params[:id])
- service = Boards::Lists::DestroyService.new(board_parent, current_user)
-
- if service.execute(list).success?
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- def generate
- service = Boards::Lists::GenerateService.new(board_parent, current_user)
-
- if service.execute(board)
- lists = board.lists.movable.preload_associated_models
-
- List.preload_preferences_for_user(lists, current_user)
-
- render json: serialize_as_json(lists)
- else
- head :unprocessable_entity
- end
- end
-
- private
-
- def list_creation_attrs
- %i[label_id]
- end
-
- def list_update_attrs
- %i[collapsed position]
- end
-
- def create_list_params
- params.require(:list).permit(list_creation_attrs)
- end
-
- def update_list_params
- params.require(:list).permit(list_update_attrs)
- end
-
- def serialize_as_json(resource)
- resource.as_json(serialization_attrs)
- end
-
- def serialization_attrs
- {
- only: [:id, :list_type, :position],
- methods: [:title],
- label: true,
- collapsed: true,
- current_user: current_user
- }
- end
- end
-end
-
-Boards::ListsController.prepend_mod_with('Boards::ListsController')
diff --git a/app/controllers/concerns/access_tokens_actions.rb b/app/controllers/concerns/access_tokens_actions.rb
index 451841c43bb..6e43be5594d 100644
--- a/app/controllers/concerns/access_tokens_actions.rb
+++ b/app/controllers/concerns/access_tokens_actions.rb
@@ -22,11 +22,10 @@ module AccessTokensActions
if token_response.success?
@resource_access_token = token_response.payload[:access_token]
- PersonalAccessToken.redis_store!(key_identity, @resource_access_token.token)
-
- redirect_to resource_access_tokens_path, notice: _("Your new access token has been created.")
+ render json: { new_token: @resource_access_token.token,
+ active_access_tokens: active_resource_access_tokens }, status: :ok
else
- redirect_to resource_access_tokens_path, alert: _("Failed to create new access token: %{token_response_message}") % { token_response_message: token_response.message }
+ render json: { errors: token_response.errors }, status: :unprocessable_entity
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -63,12 +62,15 @@ module AccessTokensActions
resource.members.load
@scopes = Gitlab::Auth.resource_bot_scopes
- @active_resource_access_tokens = finder(state: 'active').execute.preload_users
- @inactive_resource_access_tokens = finder(state: 'inactive', sort: 'expires_at_asc').execute.preload_users
- @new_resource_access_token = PersonalAccessToken.redis_getdel(key_identity)
+ @active_resource_access_tokens = active_resource_access_tokens
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
+ def active_resource_access_tokens
+ tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users
+ represent(tokens)
+ end
+
def finder(options = {})
PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options))
end
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index 4228a93d310..fbaa754124c 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -89,6 +89,7 @@ module AuthenticatesWithTwoFactor
user.save!
sign_in(user, message: :two_factor_authenticated, event: :authentication)
else
+ send_two_factor_otp_attempt_failed_email(user)
handle_two_factor_failure(user, 'OTP', _('Invalid two-factor code.'))
end
end
@@ -158,6 +159,10 @@ module AuthenticatesWithTwoFactor
prompt_for_two_factor(user)
end
+ def send_two_factor_otp_attempt_failed_email(user)
+ user.notification_service.two_factor_otp_attempt_failed(user, request.remote_ip)
+ end
+
def log_failed_two_factor(user, method)
# overridden in EE
end
diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb
index 2f9edfad12d..42bf6c68aa7 100644
--- a/app/controllers/concerns/boards_actions.rb
+++ b/app/controllers/concerns/boards_actions.rb
@@ -5,41 +5,38 @@ module BoardsActions
extend ActiveSupport::Concern
included do
- include BoardsResponses
-
before_action :authorize_read_board!, only: [:index, :show]
- before_action :boards, only: :index
- before_action :board, only: :show
+ before_action :redirect_to_recent_board, only: [:index]
+ before_action :board, only: [:index, :show]
before_action :push_licensed_features, only: [:index, :show]
end
def index
- respond_with_boards
+ # if no board exists, create one
+ @board = board_create_service.execute.payload unless board # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def show
- # Add / update the board in the recent visits table
- board_visit_service.new(parent, current_user).execute(board) if request.format.html?
+ return render_404 unless board
- respond_with_board
+ # Add / update the board in the recent visits table
+ board_visit_service.new(parent, current_user).execute(board)
end
private
- # Noop on FOSS
- def push_licensed_features
+ def redirect_to_recent_board
+ return if !parent.multiple_issue_boards_available? || !latest_visited_board
+
+ redirect_to board_path(latest_visited_board.board)
end
- def boards
- strong_memoize(:boards) do
- existing_boards = boards_finder.execute
- if existing_boards.any?
- existing_boards
- else
- # if no board exists, create one
- [board_create_service.execute.payload]
- end
- end
+ def latest_visited_board
+ @latest_visited_board ||= Boards::VisitsFinder.new(parent, current_user).latest
+ end
+
+ # Noop on FOSS
+ def push_licensed_features
end
def board
@@ -48,20 +45,26 @@ module BoardsActions
end
end
- def board_type
- board_klass.to_type
- end
-
def board_visit_service
Boards::Visits::CreateService
end
- def serializer
- BoardSerializer.new(current_user: current_user)
+ def parent
+ strong_memoize(:parent) do
+ group? ? group : project
+ end
+ end
+
+ def board_path(board)
+ if group?
+ group_board_path(parent, board)
+ else
+ project_board_path(parent, board)
+ end
end
- def serialize_as_json(resource)
- serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
+ def group?
+ instance_variable_defined?(:@group)
end
end
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
deleted file mode 100644
index eb7392648a1..00000000000
--- a/app/controllers/concerns/boards_responses.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-module BoardsResponses
- include Gitlab::Utils::StrongMemoize
-
- # Overridden on EE module
- def board_params
- params.require(:board).permit(:name)
- end
-
- def parent
- strong_memoize(:parent) do
- group? ? group : project
- end
- end
-
- def boards_path
- if group?
- group_boards_path(parent)
- else
- project_boards_path(parent)
- end
- end
-
- def board_path(board)
- if group?
- group_board_path(parent, board)
- else
- project_board_path(parent, board)
- end
- end
-
- def group?
- instance_variable_defined?(:@group)
- end
-
- def authorize_read_list
- authorize_action_for!(board, :read_issue_board_list)
- end
-
- def authorize_read_issue
- authorize_action_for!(board, :read_issue)
- end
-
- def authorize_update_issue
- authorize_action_for!(issue, :admin_issue)
- end
-
- def authorize_create_issue
- list = List.find(issue_params[:list_id])
- action = list.backlog? ? :create_issue : :admin_issue
-
- authorize_action_for!(project, action)
- end
-
- def authorize_admin_list
- authorize_action_for!(board, :admin_issue_board_list)
- end
-
- def authorize_action_for!(resource, ability)
- return render_403 unless can?(current_user, ability, resource)
- end
-
- def respond_with_boards
- respond_with(@boards) # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
-
- def respond_with_board
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- return render_404 unless @board
-
- respond_with(@board)
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
- end
-
- def serialize_as_json(resource)
- serializer.represent(resource).as_json
- end
-
- def respond_with(resource)
- respond_to do |format|
- format.html
- format.json do
- render json: serialize_as_json(resource)
- end
- end
- end
-
- def serializer
- BoardSerializer.new
- end
-end
-
-BoardsResponses.prepend_mod_with('BoardsResponses')
diff --git a/app/controllers/concerns/import/github_oauth.rb b/app/controllers/concerns/import/github_oauth.rb
new file mode 100644
index 00000000000..d53022aabf2
--- /dev/null
+++ b/app/controllers/concerns/import/github_oauth.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+module Import
+ module GithubOauth
+ extend ActiveSupport::Concern
+
+ OAuthConfigMissingError = Class.new(StandardError)
+
+ included do
+ rescue_from OAuthConfigMissingError, with: :missing_oauth_config
+ end
+
+ private
+
+ def provider_auth
+ return if session[access_token_key].present?
+
+ go_to_provider_for_permissions unless ci_cd_only?
+ end
+
+ def ci_cd_only?
+ %w[1 true].include?(params[:ci_cd_only])
+ end
+
+ def go_to_provider_for_permissions
+ redirect_to authorize_url
+ end
+
+ def oauth_client
+ raise OAuthConfigMissingError unless oauth_config
+
+ oauth_client_from_config
+ end
+
+ def oauth_client_from_config
+ @oauth_client_from_config ||= ::OAuth2::Client.new(
+ oauth_config.app_id,
+ oauth_config.app_secret,
+ oauth_options.merge(ssl: { verify: oauth_config['verify_ssl'] })
+ )
+ end
+
+ def oauth_config
+ @oauth_config ||= Gitlab::Auth::OAuth::Provider.config_for('github')
+ end
+
+ def oauth_options
+ return unless oauth_config
+
+ oauth_config.dig('args', 'client_options').deep_symbolize_keys
+ end
+
+ def authorize_url
+ state = SecureRandom.base64(64)
+ session[auth_state_key] = state
+ if Feature.enabled?(:remove_legacy_github_client)
+ oauth_client.auth_code.authorize_url(
+ redirect_uri: callback_import_url,
+ scope: 'repo, user, user:email',
+ state: state
+ )
+ else
+ client.authorize_url(callback_import_url, state)
+ end
+ end
+
+ def get_token(code)
+ if Feature.enabled?(:remove_legacy_github_client)
+ oauth_client.auth_code.get_token(code).token
+ else
+ client.get_token(code)
+ end
+ end
+
+ def missing_oauth_config
+ session[access_token_key] = nil
+
+ message = _('Missing OAuth configuration for GitHub.')
+
+ respond_to do |format|
+ format.json do
+ render json: { errors: message }, status: :unauthorized
+ end
+
+ format.any do
+ redirect_to new_import_url,
+ alert: message
+ end
+ end
+ end
+
+ def callback_import_url
+ public_send("users_import_#{provider_name}_callback_url", extra_import_params.merge({ namespace_id: params[:namespace_id] })) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def extra_import_params
+ {}
+ end
+ end
+end
diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb
index 96cf6021ea9..e03d1de7bf9 100644
--- a/app/controllers/concerns/issuable_collections_action.rb
+++ b/app/controllers/concerns/issuable_collections_action.rb
@@ -59,9 +59,12 @@ module IssuableCollectionsAction
end
def finder_options
+ issue_types = Issue::TYPES_FOR_LIST
+ issue_types = issue_types.excluding('task') unless Feature.enabled?(:work_items)
+
super.merge(
non_archived: true,
- issue_types: Issue::TYPES_FOR_LIST
+ issue_types: issue_types
)
end
end
diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb
deleted file mode 100644
index 685c93fc2a2..00000000000
--- a/app/controllers/concerns/multiple_boards_actions.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-module MultipleBoardsActions
- include Gitlab::Utils::StrongMemoize
- extend ActiveSupport::Concern
-
- included do
- include BoardsActions
-
- before_action :redirect_to_recent_board, only: [:index]
- before_action :authenticate_user!, only: [:recent]
- before_action :authorize_create_board!, only: [:create]
- before_action :authorize_admin_board!, only: [:create, :update, :destroy]
- end
-
- def recent
- recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(Board::RECENT_BOARDS_SIZE)
- recent_boards = recent_visits.map(&:board)
-
- render json: serialize_as_json(recent_boards)
- end
-
- def create
- response = Boards::CreateService.new(parent, current_user, board_params).execute
-
- respond_to do |format|
- format.json do
- board = response.payload
-
- if response.success?
- extra_json = { board_path: board_path(board) }
- render json: serialize_as_json(board).merge(extra_json)
- else
- render json: board.errors, status: :unprocessable_entity
- end
- end
- end
- end
-
- def update
- service = Boards::UpdateService.new(parent, current_user, board_params)
-
- respond_to do |format|
- format.json do
- if service.execute(board)
- extra_json = { board_path: board_path(board) }
- render json: serialize_as_json(board).merge(extra_json)
- else
- render json: board.errors, status: :unprocessable_entity
- end
- end
- end
- end
-
- def destroy
- service = Boards::DestroyService.new(parent, current_user)
- service.execute(board)
-
- respond_to do |format|
- format.json { head :ok }
- format.html { redirect_to boards_path, status: :found }
- end
- end
-
- private
-
- def redirect_to_recent_board
- return unless board_type == Board.to_type
- return if request.format.json? || !parent.multiple_issue_boards_available? || !latest_visited_board
-
- redirect_to board_path(latest_visited_board.board)
- end
-
- def latest_visited_board
- @latest_visited_board ||= Boards::VisitsFinder.new(parent, current_user).latest
- end
-
- def authorize_create_board!
- check_multiple_group_issue_boards_available! if group?
- end
-
- def authorize_admin_board!
- return render_404 unless can?(current_user, :admin_issue_board, parent)
- end
-
- def serializer
- BoardSerializer.new(current_user: current_user)
- end
-
- def serialize_as_json(resource)
- serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
- end
-end
diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb
index 1d2f9e31c46..79b3fa28660 100644
--- a/app/controllers/concerns/preview_markdown.rb
+++ b/app/controllers/concerns/preview_markdown.rb
@@ -26,16 +26,24 @@ module PreviewMarkdown
}
end
+ def timeline_events_filter_params
+ {
+ issuable_reference_expansion_enabled: true,
+ pipeline: :'incident_management/timeline_event'
+ }
+ end
+
def markdown_service_params
params
end
def markdown_context_params
case controller_name
- when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] }
- when 'snippets' then { skip_project_check: true }
- when 'groups' then { group: group }
- when 'projects' then projects_filter_params
+ when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] }
+ when 'snippets' then { skip_project_check: true }
+ when 'groups' then { group: group }
+ when 'projects' then projects_filter_params
+ when 'timeline_events' then timeline_events_filter_params
else {}
end.merge(requested_path: params[:path], ref: params[:ref])
end
diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb
index 8e936782e5a..4f96cc5c895 100644
--- a/app/controllers/concerns/product_analytics_tracking.rb
+++ b/app/controllers/concerns/product_analytics_tracking.rb
@@ -29,7 +29,13 @@ module ProductAnalyticsTracking
track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
if destinations.include?(:snowplow) && event_enabled?(name)
- Gitlab::Tracking.event(self.class.to_s, name, namespace: tracking_namespace_source, user: current_user)
+ Gitlab::Tracking.event(
+ self.class.to_s,
+ name,
+ namespace: tracking_namespace_source,
+ user: current_user,
+ context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context]
+ )
end
end
@@ -49,6 +55,7 @@ module ProductAnalyticsTracking
user: current_user,
property: name,
label: label,
+ context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context],
**optional_arguments
)
end
diff --git a/app/controllers/concerns/registrations_tracking.rb b/app/controllers/concerns/registrations_tracking.rb
new file mode 100644
index 00000000000..14743349c1a
--- /dev/null
+++ b/app/controllers/concerns/registrations_tracking.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module RegistrationsTracking
+ extend ActiveSupport::Concern
+
+ included do
+ helper_method :glm_tracking_params
+ end
+
+ private
+
+ def glm_tracking_params
+ params.permit(:glm_source, :glm_content)
+ end
+end
diff --git a/app/controllers/concerns/sends_blob.rb b/app/controllers/concerns/sends_blob.rb
index 381f2eba352..3cf260c9f1b 100644
--- a/app/controllers/concerns/sends_blob.rb
+++ b/app/controllers/concerns/sends_blob.rb
@@ -27,12 +27,14 @@ module SendsBlob
private
def cached_blob?(blob, allow_caching: false)
- stale = stale?(etag: blob.id) # The #stale? method sets cache headers.
-
- # Because we are opinionated we set the cache headers ourselves.
- response.cache_control[:public] = allow_caching
+ stale =
+ if Feature.enabled?(:improve_blobs_cache_headers)
+ stale?(strong_etag: blob.id)
+ else
+ stale?(etag: blob.id)
+ end
- response.cache_control[:max_age] =
+ max_age =
if @ref && @commit && @ref == @commit.id # rubocop:disable Gitlab/ModuleWithInstanceVariables
# This is a link to a commit by its commit SHA. That means that the blob
# is immutable. The only reason to invalidate the cache is if the commit
@@ -44,6 +46,16 @@ module SendsBlob
Blob::CACHE_TIME
end
+ # Because we are opinionated we set the cache headers ourselves.
+ if Feature.enabled?(:improve_blobs_cache_headers)
+ expires_in(max_age,
+ public: allow_caching, must_revalidate: true, stale_if_error: 5.minutes,
+ stale_while_revalidate: 1.minute, 's-maxage': 1.minute)
+ else
+ response.cache_control[:public] = allow_caching
+ response.cache_control[:max_age] = max_age
+ end
+
!stale
end
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index 83447744013..2b781c528ad 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -209,9 +209,7 @@ module WikiActions
def wiki
strong_memoize(:wiki) do
wiki = Wiki.for_container(container, current_user)
-
- # Call #wiki to make sure the Wiki Repo is initialized
- wiki.wiki
+ wiki.create_wiki_repository
wiki
end
@@ -242,7 +240,7 @@ module WikiActions
def wiki_pages
strong_memoize(:wiki_pages) do
Kaminari.paginate_array(
- wiki.list_pages(sort: params[:sort], direction: params[:direction])
+ wiki.list_pages(direction: params[:direction])
).page(params[:page])
end
end
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index aec3247f4b2..f8cfa996447 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -67,6 +67,10 @@ class Groups::ApplicationController < ApplicationController
end
end
+ def authorize_billings_page!
+ render_404 unless can?(current_user, :read_billing, group)
+ end
+
def authorize_read_group_member!
unless can?(current_user, :read_group_member, group)
render_403
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index e64d838b7d1..14b70df0feb 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -5,7 +5,6 @@ class Groups::BoardsController < Groups::ApplicationController
include RecordUserLastActivity
include Gitlab::Utils::StrongMemoize
- before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:board_multi_select, group)
push_frontend_feature_flag(:realtime_labels, group)
@@ -20,16 +19,6 @@ class Groups::BoardsController < Groups::ApplicationController
private
- def board_klass
- Board
- end
-
- def boards_finder
- strong_memoize :boards_finder do
- Boards::BoardsFinder.new(parent, current_user)
- end
- end
-
def board_finder
strong_memoize :board_finder do
Boards::BoardsFinder.new(parent, current_user, board_id: params[:id])
@@ -42,10 +31,6 @@ class Groups::BoardsController < Groups::ApplicationController
end
end
- def assign_endpoint_vars
- @boards_endpoint = group_boards_path(group)
- end
-
def authorize_read_board!
access_denied! unless can?(current_user, :read_issue_board, group)
end
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index 652f12e34ba..18b055b3f05 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -2,13 +2,9 @@
class Groups::RunnersController < Groups::ApplicationController
before_action :authorize_read_group_runners!, only: [:index, :show]
- before_action :authorize_admin_group_runners!, only: [:edit, :update, :destroy, :pause, :resume]
+ before_action :authorize_update_runner!, only: [:edit, :update, :destroy, :pause, :resume]
before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
- before_action only: [:show] do
- push_frontend_feature_flag(:enforce_runner_token_expires_at)
- end
-
feature_category :runner
urgency :low
@@ -37,7 +33,9 @@ class Groups::RunnersController < Groups::ApplicationController
private
def runner
- @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute
+ group_params = { group: @group, membership: :all_available }
+
+ @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: group_params).execute
.except(:limit, :offset)
.find(params[:id])
end
@@ -45,6 +43,12 @@ class Groups::RunnersController < Groups::ApplicationController
def runner_params
params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
end
+
+ def authorize_update_runner!
+ return if can?(current_user, :admin_group_runners, group) && can?(current_user, :update_runner, runner)
+
+ render_404
+ end
end
Groups::RunnersController.prepend_mod
diff --git a/app/controllers/groups/settings/access_tokens_controller.rb b/app/controllers/groups/settings/access_tokens_controller.rb
index b9ab2e008cc..f01b2b779e3 100644
--- a/app/controllers/groups/settings/access_tokens_controller.rb
+++ b/app/controllers/groups/settings/access_tokens_controller.rb
@@ -13,6 +13,12 @@ module Groups
def resource_access_tokens_path
group_settings_access_tokens_path
end
+
+ private
+
+ def represent(tokens)
+ ::GroupAccessTokenSerializer.new.represent(tokens, group: resource)
+ end
end
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 9316204d89c..269342a6c22 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -81,9 +81,9 @@ class GroupsController < Groups::ApplicationController
successful_creation_hooks
notice = if @group.chat_team.present?
- "Group '#{@group.name}' and its Mattermost team were successfully created."
+ format(_("Group %{group_name} and its Mattermost team were successfully created."), group_name: @group.name)
else
- "Group '#{@group.name}' was successfully created."
+ format(_("Group %{group_name} was successfully created."), group_name: @group.name)
end
redirect_to @group, notice: notice
@@ -393,7 +393,7 @@ class GroupsController < Groups::ApplicationController
end
def captcha_enabled?
- Gitlab::Recaptcha.enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops)
+ helpers.recaptcha_enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops)
end
def captcha_required?
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index 58a985cbc46..fcf6871d137 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class IdeController < ApplicationController
- layout 'fullscreen'
-
include ClientsidePreviewCSP
include StaticObjectExternalStorageCSP
include Gitlab::Utils::StrongMemoize
@@ -13,7 +11,6 @@ class IdeController < ApplicationController
push_frontend_feature_flag(:build_service_proxy)
push_frontend_feature_flag(:schema_linting)
push_frontend_feature_flag(:reject_unsigned_commits_by_gitlab)
- push_frontend_feature_flag(:vscode_web_ide, current_user)
define_index_vars
end
@@ -28,6 +25,8 @@ class IdeController < ApplicationController
Gitlab::Tracking.event(self.class.to_s, 'web_ide_views',
namespace: project&.namespace, user: current_user)
end
+
+ render layout: 'fullscreen', locals: { minimal: helpers.use_new_web_ide? }
end
private
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 893c0b6ac54..655fc7854fe 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -47,6 +47,8 @@ class Import::BulkImportsController < ApplicationController
end
def create
+ return render json: { success: false }, status: :unprocessable_entity unless valid_create_params?
+
responses = create_params.map do |entry|
if entry[:destination_name]
entry[:destination_slug] ||= entry[:destination_name]
@@ -102,6 +104,10 @@ class Import::BulkImportsController < ApplicationController
params.permit(bulk_import: bulk_import_params)[:bulk_import]
end
+ def valid_create_params?
+ create_params.all? { _1[:source_type] == 'group_entity' }
+ end
+
def bulk_import_params
%i[
source_type
@@ -113,7 +119,7 @@ class Import::BulkImportsController < ApplicationController
end
def ensure_group_import_enabled
- render_404 unless Feature.enabled?(:bulk_import)
+ render_404 unless ::BulkImports::Features.enabled?
end
def access_token_key
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index 8a3e6809736..92763e09ba3 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -5,14 +5,12 @@ class Import::GithubController < Import::BaseController
include ImportHelper
include ActionView::Helpers::SanitizeHelper
+ include Import::GithubOauth
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :realtime_changes, :create]
before_action :expire_etag_cache, only: [:status, :create]
- OAuthConfigMissingError = Class.new(StandardError)
-
- rescue_from OAuthConfigMissingError, with: :missing_oauth_config
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
rescue_from Octokit::TooManyRequests, with: :provider_rate_limit
rescue_from Gitlab::GithubImport::RateLimitError, with: :rate_limit_threshold_exceeded
@@ -73,6 +71,17 @@ class Import::GithubController < Import::BaseController
}
end
+ def cancel
+ project = Project.imported_from(provider_name).find(params[:project_id])
+ result = Import::Github::CancelProjectImportService.new(project, current_user).execute
+
+ if result[:status] == :success
+ render json: serialized_imported_projects(result[:project])
+ else
+ render json: { errors: result[:message] }, status: result[:http_status]
+ end
+ end
+
protected
override :importable_repos
@@ -104,7 +113,7 @@ class Import::GithubController < Import::BaseController
end
def permitted_import_params
- [:repo_id, :new_name, :target_namespace]
+ [:repo_id, :new_name, :target_namespace, { optional_stages: {} }]
end
def serialized_imported_projects(projects = already_added_projects)
@@ -143,58 +152,10 @@ class Import::GithubController < Import::BaseController
@filter = @filter&.tr(' ', '')&.tr(':', '')
end
- def oauth_client
- raise OAuthConfigMissingError unless oauth_config
-
- @oauth_client ||= ::OAuth2::Client.new(
- oauth_config.app_id,
- oauth_config.app_secret,
- oauth_options.merge(ssl: { verify: oauth_config['verify_ssl'] })
- )
- end
-
- def oauth_config
- @oauth_config ||= Gitlab::Auth::OAuth::Provider.config_for('github')
- end
-
- def oauth_options
- if oauth_config
- oauth_config.dig('args', 'client_options').deep_symbolize_keys
- else
- OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys
- end
- end
-
- def authorize_url
- state = SecureRandom.base64(64)
- session[auth_state_key] = state
- if Feature.enabled?(:remove_legacy_github_client)
- oauth_client.auth_code.authorize_url(
- redirect_uri: callback_import_url,
- scope: 'repo, user, user:email',
- state: state
- )
- else
- client.authorize_url(callback_import_url, state)
- end
- end
-
- def get_token(code)
- if Feature.enabled?(:remove_legacy_github_client)
- oauth_client.auth_code.get_token(code).token
- else
- client.get_token(code)
- end
- end
-
def verify_import_enabled
render_404 unless import_enabled?
end
- def go_to_provider_for_permissions
- redirect_to authorize_url
- end
-
def import_enabled?
__send__("#{provider_name}_import_enabled?") # rubocop:disable GitlabSecurity/PublicSend
end
@@ -211,10 +172,6 @@ class Import::GithubController < Import::BaseController
public_send("status_import_#{provider_name}_url", extra_import_params.merge({ namespace_id: params[:namespace_id].presence })) # rubocop:disable GitlabSecurity/PublicSend
end
- def callback_import_url
- public_send("users_import_#{provider_name}_callback_url", extra_import_params.merge({ namespace_id: params[:namespace_id] })) # rubocop:disable GitlabSecurity/PublicSend
- end
-
def provider_unauthorized
session[access_token_key] = nil
redirect_to new_import_url,
@@ -228,12 +185,6 @@ class Import::GithubController < Import::BaseController
alert: _("GitHub API rate limit exceeded. Try again after %{reset_time}") % { reset_time: reset_time }
end
- def missing_oauth_config
- session[access_token_key] = nil
- redirect_to new_import_url,
- alert: _('Missing OAuth configuration for GitHub.')
- end
-
def auth_state_key
:"#{provider_name}_auth_state_key"
end
@@ -252,24 +203,10 @@ class Import::GithubController < Import::BaseController
end
# rubocop: enable CodeReuse/ActiveRecord
- def provider_auth
- if !ci_cd_only? && session[access_token_key].blank?
- go_to_provider_for_permissions
- end
- end
-
- def ci_cd_only?
- %w[1 true].include?(params[:ci_cd_only])
- end
-
def client_options
{ wait_for_rate_limit_reset: false }
end
- def extra_import_params
- {}
- end
-
def rate_limit_threshold_exceeded
head :too_many_requests
end
diff --git a/app/controllers/import/github_groups_controller.rb b/app/controllers/import/github_groups_controller.rb
new file mode 100644
index 00000000000..6c0773bcfb3
--- /dev/null
+++ b/app/controllers/import/github_groups_controller.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Import
+ class GithubGroupsController < ApplicationController
+ include Import::GithubOauth
+
+ before_action :provider_auth, only: [:status]
+ feature_category :importers
+
+ PAGE_LENGTH = 25
+
+ def status
+ respond_to do |format|
+ format.json do
+ render json: { provider_groups: serialized_provider_groups }
+ end
+ end
+ end
+
+ private
+
+ def serialized_provider_groups
+ Import::GithubOrgSerializer.new.represent(importable_orgs)
+ end
+
+ def importable_orgs
+ client_orgs.to_a
+ end
+
+ def client_orgs
+ @client_orgs ||= client.octokit.organizations(nil, pagination_options)
+ end
+
+ def client
+ @client ||= Gitlab::GithubImport::Client.new(session[access_token_key])
+ end
+
+ def pagination_options
+ {
+ page: [1, params[:page].to_i].max,
+ per_page: PAGE_LENGTH
+ }
+ end
+
+ def auth_state_key
+ :"#{provider_name}_auth_state_key"
+ end
+
+ def access_token_key
+ :"#{provider_name}_access_token"
+ end
+
+ def provider_name
+ :github
+ end
+ end
+end
diff --git a/app/controllers/jira_connect/public_keys_controller.rb b/app/controllers/jira_connect/public_keys_controller.rb
new file mode 100644
index 00000000000..b3144993edb
--- /dev/null
+++ b/app/controllers/jira_connect/public_keys_controller.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class PublicKeysController < ::ApplicationController
+ # This is not inheriting from JiraConnect::Application controller because
+ # it doesn't need to handle JWT authentication.
+
+ feature_category :integrations
+
+ skip_before_action :authenticate_user!
+
+ def show
+ return render_404 if Feature.disabled?(:jira_connect_oauth_self_managed) || !Gitlab.com?
+
+ render plain: public_key.key
+ end
+
+ private
+
+ def public_key
+ JiraConnect::PublicKey.find(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index ff466fd5fbb..3b78b997da1 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -4,7 +4,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
include Gitlab::GonHelper
include PageLayoutHelper
include OauthApplications
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
# Defined by the `Doorkeeper::ApplicationsController` and is redundant as we call `authenticate_user!` below. Not
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index 2e9fbb1d0d9..bf8b61db2e5 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
include Gitlab::Utils::StrongMemoize
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 817f272d458..f3f0ddd968a 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -181,6 +181,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
accept_pending_invitations(user: user) if new_user
+ persist_accepted_terms_if_required(user) if new_user
+
store_after_sign_up_path_for_user if intent_to_register?
sign_in_and_redirect(user, event: :authentication)
end
@@ -301,6 +303,15 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_admin_session_path, alert: _('Invalid login or password')
end
+ def persist_accepted_terms_if_required(user)
+ return unless Feature.enabled?(:update_oauth_registration_flow)
+ return unless user.persisted?
+ return unless Gitlab::CurrentSettings.current_application_settings.enforce_terms?
+
+ terms = ApplicationSetting::Term.latest
+ Users::RespondToTermsService.new(user, terms).execute(accepted: true)
+ end
+
def store_after_sign_up_path_for_user
store_location_for(:user, users_sign_up_welcome_path)
end
diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb
index 8ed67c26f19..4cf26d3e1e2 100644
--- a/app/controllers/profiles/personal_access_tokens_controller.rb
+++ b/app/controllers/profiles/personal_access_tokens_controller.rb
@@ -3,6 +3,8 @@
class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
feature_category :authentication_and_authorization
+ before_action :check_personal_access_tokens_enabled
+
def index
set_index_vars
scopes = params[:scopes].split(',').map(&:squish).select(&:present?).map(&:to_sym) unless params[:scopes].nil?
@@ -83,4 +85,8 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
def page
(params[:page] || 1).to_i
end
+
+ def check_personal_access_tokens_enabled
+ render_404 if Gitlab::CurrentSettings.personal_access_tokens_disabled?
+ end
end
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 7aca76c2fb1..a57c87bf691 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -55,7 +55,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:sourcegraph_enabled,
:gitpod_enabled,
:render_whitespace_in_code,
- :markdown_surround_selection
+ :markdown_surround_selection,
+ :markdown_automatic_lists,
+ :use_legacy_web_ide
]
end
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 0b7d4626c6d..0933f2bb7ea 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -15,31 +15,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
feature_category :authentication_and_authorization
def show
- if two_factor_authentication_required? && !current_user.two_factor_enabled?
- two_factor_authentication_reason(
- global: lambda do
- flash.now[:alert] =
- _('The global settings require you to enable Two-Factor Authentication for your account.')
- end,
- group: lambda do |groups|
- flash.now[:alert] = groups_notification(groups)
- end
- )
-
- unless two_factor_grace_period_expired?
- grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
- flash.now[:alert] = flash.now[:alert] + _(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
- end
- end
-
- @qr_code = build_qr_code
- @account_string = account_string
-
- if Feature.enabled?(:webauthn)
- setup_webauthn_registration
- else
- setup_u2f_registration
- end
+ setup_show_page
end
def create
@@ -147,7 +123,11 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
current_user.increment_failed_attempts!
- redirect_to profile_two_factor_auth_path, alert: _('You must provide a valid current password')
+ @error = { message: _('You must provide a valid current password') }
+
+ setup_show_page
+
+ render 'show'
end
def current_password_required?
@@ -245,4 +225,32 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
redirect_to profile_emails_path, notice: s_('You need to verify your primary email first before enabling Two-Factor Authentication.')
end
end
+
+ def setup_show_page
+ if two_factor_authentication_required? && !current_user.two_factor_enabled?
+ two_factor_authentication_reason(
+ global: lambda do
+ flash.now[:alert] =
+ _('The global settings require you to enable Two-Factor Authentication for your account.')
+ end,
+ group: lambda do |groups|
+ flash.now[:alert] = groups_notification(groups)
+ end
+ )
+
+ unless two_factor_grace_period_expired?
+ grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
+ flash.now[:alert] = flash.now[:alert] + _(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
+ end
+ end
+
+ @qr_code = build_qr_code
+ @account_string = account_string
+
+ if Feature.enabled?(:webauthn)
+ setup_webauthn_registration
+ else
+ setup_u2f_registration
+ end
+ end
end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 028b7af02c9..2256471047d 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -39,8 +39,8 @@ class Projects::ApplicationController < ApplicationController
access_denied!(
_('You must have developer or higher permissions in the associated project to view job logs when debug trace ' \
"is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline " \
- 'configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to ' \
- 'the project with developer permissions or higher.')
+ 'configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add ' \
+ 'you to the project with developer permissions or higher.')
)
else
access_denied!(_('The current user is not authorized to access the job log.'))
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index 9dbf989ca3f..7755effe1da 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -41,7 +41,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
end
def contacts
- render json: autocomplete_service.contacts
+ render json: autocomplete_service.contacts(target)
end
private
@@ -51,9 +51,12 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
end
def target
+ # type_id is not required in general
+ target_type = params.require(:type)
+
QuickActions::TargetService
.new(project, current_user)
- .execute(params[:type], params[:type_id])
+ .execute(target_type, params[:type_id])
end
def authorize_read_crm_contact!
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 2a20c67a23d..01ed5473b41 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -26,7 +26,10 @@ class Projects::BlameController < Projects::ApplicationController
blame_service = Projects::BlameService.new(@blob, @commit, params.permit(:page, :no_pagination))
@blame = Gitlab::View::Presenter::Factory.new(blame_service.blame, project: @project, path: @path, page: blame_service.page).fabricate!
+
@blame_pagination = blame_service.pagination
+
+ @blame_per_page = blame_service.per_page
end
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 82b35a22669..6a6701ead15 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
class Projects::BoardsController < Projects::ApplicationController
- include MultipleBoardsActions
+ include BoardsActions
include IssuableCollections
before_action :check_issues_available!
- before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:board_multi_select, project)
push_frontend_feature_flag(:realtime_labels, project&.group)
@@ -20,16 +19,6 @@ class Projects::BoardsController < Projects::ApplicationController
private
- def board_klass
- Board
- end
-
- def boards_finder
- strong_memoize :boards_finder do
- Boards::BoardsFinder.new(parent, current_user)
- end
- end
-
def board_finder
strong_memoize :board_finder do
Boards::BoardsFinder.new(parent, current_user, board_id: params[:id])
@@ -42,11 +31,6 @@ class Projects::BoardsController < Projects::ApplicationController
end
end
- def assign_endpoint_vars
- @boards_endpoint = project_boards_path(project)
- @bulk_issues_path = bulk_update_project_issues_path(project)
- end
-
def authorize_read_board!
access_denied! unless can?(current_user, :read_issue_board, project)
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index d7fd65f02a8..61308f24412 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -47,7 +47,8 @@ class Projects::CompareController < Projects::ApplicationController
from_to_vars = {
from: compare_params[:from].presence,
to: compare_params[:to].presence,
- from_project_id: compare_params[:from_project_id].presence
+ from_project_id: compare_params[:from_project_id].presence,
+ straight: compare_params[:straight].presence
}
if from_to_vars[:from].blank? || from_to_vars[:to].blank?
@@ -112,7 +113,11 @@ class Projects::CompareController < Projects::ApplicationController
def compare
return @compare if defined?(@compare)
- @compare = CompareService.new(source_project, head_ref).execute(target_project, start_ref)
+ @compare = CompareService.new(source_project, head_ref).execute(target_project, start_ref, straight: straight)
+ end
+
+ def straight
+ compare_params[:straight] == "true"
end
def start_ref
@@ -160,6 +165,6 @@ class Projects::CompareController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def compare_params
- @compare_params ||= params.permit(:from, :to, :from_project_id)
+ @compare_params ||= params.permit(:from, :to, :from_project_id, :straight)
end
end
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 96afe9dbb9f..22a42d22914 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -27,11 +27,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def create
- @key = DeployKeys::CreateService.new(current_user, create_params).execute(project: @project)
+ @key = DeployKeys::CreateService.new(current_user, create_params).execute(project: @project).present
- unless @key.valid?
- flash[:alert] = @key.errors.full_messages.join(', ').html_safe
- end
+ flash[:alert] = @key.humanized_error_message unless @key.valid?
redirect_to_repository
end
diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb
index 8f7554f248b..77ee830fd24 100644
--- a/app/controllers/projects/google_cloud/databases_controller.rb
+++ b/app/controllers/projects/google_cloud/databases_controller.rb
@@ -50,16 +50,15 @@ module Projects
track_event(:error_enable_cloudsql_services)
flash[:error] = error_message(enable_response[:message])
else
- permitted_params = params.permit(:gcp_project, :ref, :database_version, :tier)
create_response = ::GoogleCloud::CreateCloudsqlInstanceService
- .new(project, current_user, create_service_params(permitted_params))
+ .new(project, current_user, create_service_params)
.execute
if create_response[:status] == :error
track_event(:error_create_cloudsql_instance)
flash[:warning] = error_message(create_response[:message])
else
- track_event(:create_cloudsql_instance, permitted_params.to_s)
+ track_event(:create_cloudsql_instance, permitted_params_create.to_s)
flash[:notice] = success_message
end
end
@@ -69,17 +68,25 @@ module Projects
private
+ def permitted_params_create
+ params.permit(:gcp_project, :ref, :database_version, :tier)
+ end
+
def enable_service_params
- { google_oauth2_token: token_in_session }
+ {
+ google_oauth2_token: token_in_session,
+ gcp_project_id: permitted_params_create[:gcp_project],
+ environment_name: permitted_params_create[:ref]
+ }
end
- def create_service_params(permitted_params)
+ def create_service_params
{
google_oauth2_token: token_in_session,
- gcp_project_id: permitted_params[:gcp_project],
- environment_name: permitted_params[:ref],
- database_version: permitted_params[:database_version],
- tier: permitted_params[:tier]
+ gcp_project_id: permitted_params_create[:gcp_project],
+ environment_name: permitted_params_create[:ref],
+ database_version: permitted_params_create[:database_version],
+ tier: permitted_params_create[:tier]
}
end
diff --git a/app/controllers/projects/incident_management/timeline_events_controller.rb b/app/controllers/projects/incident_management/timeline_events_controller.rb
new file mode 100644
index 00000000000..7e7a4758e48
--- /dev/null
+++ b/app/controllers/projects/incident_management/timeline_events_controller.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Projects
+ module IncidentManagement
+ class TimelineEventsController < Projects::ApplicationController
+ include PreviewMarkdown
+
+ before_action :authenticate_user!
+
+ respond_to :json
+
+ feature_category :incident_management
+ urgency :low
+ end
+ end
+end
diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb
index cbf0c756e1e..089ee860ea6 100644
--- a/app/controllers/projects/incidents_controller.rb
+++ b/app/controllers/projects/incidents_controller.rb
@@ -7,11 +7,9 @@ class Projects::IncidentsController < Projects::ApplicationController
before_action :authorize_read_issue!
before_action :load_incident, only: [:show]
before_action do
- push_frontend_feature_flag(:incident_timeline, @project)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:work_items_hierarchy, @project)
- push_frontend_feature_flag(:remove_user_attributes_projects, @project)
end
feature_category :incident_management
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 800a7df2566..5b1117c0224 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -41,8 +41,8 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_download_code!, only: [:related_branches]
before_action do
- push_frontend_feature_flag(:incident_timeline, project)
- push_frontend_feature_flag(:remove_user_attributes_projects, project)
+ push_frontend_feature_flag(:preserve_unchanged_markdown, project)
+ push_frontend_feature_flag(:content_editor_on_issues, project)
end
before_action only: [:index, :show] do
@@ -147,19 +147,26 @@ class Projects::IssuesController < Projects::ApplicationController
spam_params = ::Spam::SpamParams.new_from_request(request: request)
service = ::Issues::CreateService.new(project: project, current_user: current_user, params: create_params, spam_params: spam_params)
- @issue = service.execute
+ result = service.execute
- create_vulnerability_issue_feedback(issue)
-
- if service.discussions_to_resolve.count(&:resolved?) > 0
- flash[:notice] = if service.discussion_to_resolve_id
- _("Resolved 1 discussion.")
- else
- _("Resolved all discussions.")
- end
+ # Only irrecoverable errors such as unauthorized user won't contain an issue in the response
+ if result.error? && result[:issue].blank?
+ render_by_create_result_error(result) && return
end
- if @issue.valid?
+ @issue = result[:issue]
+
+ if result.success?
+ create_vulnerability_issue_feedback(@issue)
+
+ if service.discussions_to_resolve.count(&:resolved?) > 0
+ flash[:notice] = if service.discussion_to_resolve_id
+ _("Resolved 1 discussion.")
+ else
+ _("Resolved all discussions.")
+ end
+ end
+
redirect_to project_issue_path(@project, @issue)
else
# NOTE: this CAPTCHA support method is indirectly included via IssuableActions
@@ -372,6 +379,21 @@ class Projects::IssuesController < Projects::ApplicationController
private
+ def render_by_create_result_error(result)
+ Gitlab::AppLogger.warn(
+ message: 'Cannot create issue',
+ errors: result.errors,
+ http_status: result.http_status
+ )
+ error_method_name = "render_#{result.http_status}".to_sym
+
+ if respond_to?(error_method_name, true)
+ send(error_method_name) # rubocop:disable GitlabSecurity/PublicSend
+ else
+ render_404
+ end
+ end
+
def clean_params(all_params)
issue_type = all_params[:issue_type].to_s
all_params.delete(:issue_type) unless WorkItems::Type.allowed_types_for_issues.include?(issue_type)
@@ -383,6 +405,7 @@ class Projects::IssuesController < Projects::ApplicationController
options = super
options[:issue_types] = Issue::TYPES_FOR_LIST
+ options[:issue_types] = options[:issue_types].excluding('task') unless project.work_items_feature_flag_enabled?
if service_desk?
options.reject! { |key| key == 'author_username' || key == 'author_id' }
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index a68c2ffa06d..418e7233e21 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -4,6 +4,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
include DiffHelper
include RendersNotes
include Gitlab::Cache::Helpers
+ include Gitlab::Tracking::Helpers
before_action :commit
before_action :define_diff_vars
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 5a212e9a152..9c139733248 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -34,7 +34,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action only: [:show] do
push_frontend_feature_flag(:merge_request_widget_graphql, project)
push_frontend_feature_flag(:core_security_mr_widget_counts, project)
- push_frontend_feature_flag(:refactor_mr_widgets_extensions, project)
push_frontend_feature_flag(:refactor_code_quality_extension, project)
push_frontend_feature_flag(:refactor_mr_widget_test_summary, project)
push_frontend_feature_flag(:issue_assignees_widget, @project)
@@ -45,7 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:paginated_mr_discussions, project)
push_frontend_feature_flag(:mr_review_submit_comment, project)
push_frontend_feature_flag(:mr_experience_survey, project)
- push_frontend_feature_flag(:remove_user_attributes_projects, @project)
end
before_action do
@@ -451,15 +449,16 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
return :failed
end
+ squashing = params.fetch(:squash, false)
merge_service = ::MergeRequests::MergeService.new(project: @project, current_user: current_user, params: merge_params)
- unless merge_service.hooks_validation_pass?(@merge_request)
+ unless merge_service.hooks_validation_pass?(@merge_request, validate_squash_message: squashing)
return :hook_validation_error
end
return :sha_mismatch if params[:sha] != @merge_request.diff_head_sha
- @merge_request.update(merge_error: nil, squash: params.fetch(:squash, false))
+ @merge_request.update(merge_error: nil, squash: squashing)
if auto_merge_requested?
if merge_request.auto_merge_enabled?
@@ -555,7 +554,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def endpoint_metadata_url(project, merge_request)
- params = request.query_parameters.merge(view: 'inline', diff_head: true)
+ params = request.query_parameters.merge(view: 'inline', diff_head: true, w: current_user&.show_whitespace_in_diffs ? '0' : '1')
diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params)
end
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index cfb67b7b4ff..78108cf3478 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -4,8 +4,11 @@ class Projects::MilestonesController < Projects::ApplicationController
include Gitlab::Utils::StrongMemoize
include MilestoneActions
+ REDIRECT_TARGETS = [:new_release].freeze
+
before_action :check_issuables_available!
before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote]
+ before_action :redirect_path, only: [:new, :create]
# Allow read any milestone
before_action :authorize_read_milestone!
@@ -59,7 +62,11 @@ class Projects::MilestonesController < Projects::ApplicationController
@milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute
if @milestone.valid?
- redirect_to project_milestone_path(@project, @milestone)
+ if @redirect_path == :new_release
+ redirect_to new_project_release_path(@project)
+ else
+ redirect_to project_milestone_path(@project, @milestone)
+ end
else
render "new"
end
@@ -113,6 +120,11 @@ class Projects::MilestonesController < Projects::ApplicationController
protected
+ def redirect_path
+ path = params[:redirect_path]&.to_sym
+ @redirect_path = path if REDIRECT_TARGETS.include?(path)
+ end
+
def project_group
strong_memoize(:project_group) do
project.group
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index a6b22a28b17..43952a2efe4 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -41,9 +41,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def create
- @domain = @project.pages_domains.create(create_params)
+ @domain = PagesDomains::CreateService.new(@project, current_user, create_params).execute
- if @domain.valid?
+ if @domain&.persisted?
redirect_to project_pages_domain_path(@project, @domain)
else
render 'new'
@@ -51,7 +51,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def update
- if @domain.update(update_params)
+ service = ::PagesDomains::UpdateService.new(@project, current_user, update_params)
+
+ if service.execute(@domain)
redirect_to project_pages_path(@project),
status: :found,
notice: 'Domain was updated'
@@ -61,7 +63,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def destroy
- @domain.destroy
+ PagesDomains::DeleteService
+ .new(@project, current_user)
+ .execute(@domain)
respond_to do |format|
format.html do
@@ -74,9 +78,10 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def clean_certificate
- unless @domain.update(user_provided_certificate: nil, user_provided_key: nil)
- flash[:alert] = @domain.errors.full_messages.join(', ')
- end
+ update_params = { user_provided_certificate: nil, user_provided_key: nil }
+ service = ::PagesDomains::UpdateService.new(@project, current_user, update_params)
+
+ flash[:alert] = @domain.errors.full_messages.join(', ') unless service.execute(@domain)
redirect_to project_pages_domain_path(@project, @domain)
end
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index a23d7fb3e6b..ca787785901 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -10,6 +10,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :authorize_update_pipeline_schedule!, only: [:edit, :update]
before_action :authorize_take_ownership_pipeline_schedule!, only: [:take_ownership]
before_action :authorize_admin_pipeline_schedule!, only: [:destroy]
+ before_action :push_schedule_feature_flag, only: [:index, :new, :edit]
feature_category :continuous_integration
urgency :low
@@ -115,4 +116,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
def authorize_admin_pipeline_schedule!
return access_denied! unless can?(current_user, :admin_pipeline_schedule, schedule)
end
+
+ def push_schedule_feature_flag
+ push_frontend_feature_flag(:pipeline_schedules_vue, @project)
+ end
end
diff --git a/app/controllers/projects/product_analytics_controller.rb b/app/controllers/projects/product_analytics_controller.rb
index c89cd52530a..8085b0a6334 100644
--- a/app/controllers/projects/product_analytics_controller.rb
+++ b/app/controllers/projects/product_analytics_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Projects::ProductAnalyticsController < Projects::ApplicationController
- before_action :feature_enabled!
+ before_action :feature_enabled!, only: [:index, :setup, :test, :graphs]
before_action :authorize_read_product_analytics!
before_action :tracker_variables, only: [:setup, :test]
@@ -57,3 +57,5 @@ class Projects::ProductAnalyticsController < Projects::ApplicationController
render_404 unless Feature.enabled?(:product_analytics, @project)
end
end
+
+Projects::ProductAnalyticsController.prepend_mod_with('Projects::ProductAnalyticsController')
diff --git a/app/controllers/projects/protected_refs_controller.rb b/app/controllers/projects/protected_refs_controller.rb
index abbfe9ce22a..69a540158c6 100644
--- a/app/controllers/projects/protected_refs_controller.rb
+++ b/app/controllers/projects/protected_refs_controller.rb
@@ -4,7 +4,6 @@ class Projects::ProtectedRefsController < Projects::ApplicationController
include RepositorySettingsRedirect
# Authorize
- before_action :require_non_empty_project
before_action :authorize_admin_project!
before_action :load_protected_ref, only: [:show, :update, :destroy]
diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb
index 32916831ecd..bac35583a97 100644
--- a/app/controllers/projects/settings/access_tokens_controller.rb
+++ b/app/controllers/projects/settings/access_tokens_controller.rb
@@ -13,6 +13,12 @@ module Projects
def resource_access_tokens_path
namespace_project_settings_access_tokens_path
end
+
+ private
+
+ def represent(tokens)
+ ::ProjectAccessTokenSerializer.new.represent(tokens, project: resource)
+ end
end
end
end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index c861b24d9ec..76e2da6eb57 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -14,7 +14,7 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController
before_action :authorize_read_snippet!, except: [:new, :index]
before_action :authorize_update_snippet!, only: :edit
- urgency :low, [:index]
+ urgency :low, [:index, :show]
def index
@snippet_counts = ::Snippets::CountService
diff --git a/app/controllers/projects/web_ide_terminals_controller.rb b/app/controllers/projects/web_ide_terminals_controller.rb
index 350b091edfa..cfccc949244 100644
--- a/app/controllers/projects/web_ide_terminals_controller.rb
+++ b/app/controllers/projects/web_ide_terminals_controller.rb
@@ -10,6 +10,8 @@ class Projects::WebIdeTerminalsController < Projects::ApplicationController
feature_category :web_ide
+ urgency :low, [:check_config]
+
def check_config
return respond_422 unless branch_sha
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 5ceedbc1e01..b7b6e6534fb 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -311,8 +311,6 @@ class ProjectsController < Projects::ApplicationController
find_tags = true
find_commits = true
- use_gitaly_pagination = Feature.enabled?(:use_gitaly_pagination_for_refs, @project)
-
unless find_refs.nil?
find_branches = find_refs.include?('branches')
find_tags = find_refs.include?('tags')
@@ -323,7 +321,7 @@ class ProjectsController < Projects::ApplicationController
if find_branches
branches = BranchesFinder.new(@repository, refs_params.merge(per_page: REFS_LIMIT))
- .execute(gitaly_pagination: use_gitaly_pagination)
+ .execute(gitaly_pagination: true)
.take(REFS_LIMIT)
.map(&:name)
@@ -332,7 +330,7 @@ class ProjectsController < Projects::ApplicationController
if find_tags && @repository.tag_count.nonzero?
tags = TagsFinder.new(@repository, refs_params.merge(per_page: REFS_LIMIT))
- .execute(gitaly_pagination: use_gitaly_pagination)
+ .execute(gitaly_pagination: true)
.take(REFS_LIMIT)
.map(&:name)
@@ -435,14 +433,14 @@ class ProjectsController < Projects::ApplicationController
analytics_access_level
security_and_compliance_access_level
container_registry_access_level
+ releases_access_level
] + operations_feature_attributes
end
def operations_feature_attributes
if Feature.enabled?(:split_operations_visibility_permissions, project)
%i[
- environments_access_level feature_flags_access_level releases_access_level
- monitor_access_level
+ environments_access_level feature_flags_access_level monitor_access_level
]
else
%i[operations_access_level]
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 4e18e6a3b20..a49b82319da 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -4,6 +4,7 @@ module Registrations
class WelcomeController < ApplicationController
include OneTrustCSP
include GoogleAnalyticsCSP
+ include RegistrationsTracking
layout 'minimal'
skip_before_action :authenticate_user!, :required_signup_info, :check_two_factor_requirement, only: [:show, :update]
@@ -25,7 +26,7 @@ module Registrations
members = current_user.members
- if members.count == 1 && members.last.source.present?
+ if registering_from_invite?(members)
redirect_to members_activity_path(members), notice: helpers.invite_accepted_notice(members.last)
else
redirect_to path_for_signed_in_user(current_user)
@@ -37,6 +38,10 @@ module Registrations
private
+ def registering_from_invite?(members)
+ members.count == 1 && members.last.source.present?
+ end
+
def require_current_user
return redirect_to new_user_registration_path unless current_user
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 0bd266bb490..31fe30f3f06 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -8,6 +8,7 @@ class RegistrationsController < Devise::RegistrationsController
include OneTrustCSP
include BizibleCSP
include GoogleAnalyticsCSP
+ include RegistrationsTracking
layout 'devise'
@@ -114,13 +115,18 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
- users_sign_up_welcome_path
+ users_sign_up_welcome_path(glm_tracking_params)
end
def after_inactive_sign_up_path_for(resource)
Gitlab::AppLogger.info(user_created_message)
return new_user_session_path(anchor: 'login-pane') if resource.blocked_pending_approval?
return dashboard_projects_path if Feature.enabled?(:soft_email_confirmation)
+
+ # when email confirmation is enabled, path to redirect is saved
+ # after user confirms and comes back, he will be redirected
+ store_location_for(:redirect, users_sign_up_welcome_path(glm_tracking_params))
+
return identity_verification_redirect_path if custom_confirmation_enabled?(resource)
users_almost_there_path(email: resource.email)
@@ -183,7 +189,7 @@ class RegistrationsController < Devise::RegistrationsController
def resource
@resource ||= Users::RegistrationsBuildService
- .new(current_user, sign_up_params.merge({ skip_confirmation: skip_email_confirmation? }))
+ .new(current_user, sign_up_params.merge({ skip_confirmation: registered_with_invite_email? }))
.execute
end
@@ -191,7 +197,7 @@ class RegistrationsController < Devise::RegistrationsController
@devise_mapping ||= Devise.mappings[:user]
end
- def skip_email_confirmation?
+ def registered_with_invite_email?
invite_email = session.delete(:invite_email)
sign_up_params[:email] == invite_email
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 9f87ad6aaf6..7d4dd04c6d4 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -25,6 +25,10 @@ class SearchController < ApplicationController
end
before_action :check_search_rate_limit!, only: search_rate_limited_endpoints
+ before_action only: :show do
+ push_frontend_feature_flag(:search_page_vertical_nav, current_user)
+ end
+
rescue_from ActiveRecord::QueryCanceled, with: :render_timeout
layout 'search'
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index fe3b8d9b8b4..5c969c437f4 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -107,11 +107,11 @@ class SessionsController < Devise::SessionsController
end
def captcha_enabled?
- request.headers[CAPTCHA_HEADER] && Gitlab::Recaptcha.enabled?
+ request.headers[CAPTCHA_HEADER] && helpers.recaptcha_enabled?
end
def captcha_on_login_required?
- Gitlab::Recaptcha.enabled_on_login? && unverified_anonymous_user?
+ helpers.recaptcha_enabled_on_login? && unverified_anonymous_user?
end
# From https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise#devisepasswordscontroller
diff --git a/app/controllers/users/namespace_callouts_controller.rb b/app/controllers/users/namespace_callouts_controller.rb
deleted file mode 100644
index d4876382dfe..00000000000
--- a/app/controllers/users/namespace_callouts_controller.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class NamespaceCalloutsController < Users::CalloutsController
- private
-
- def callout
- Users::DismissNamespaceCalloutService.new(
- container: nil, current_user: current_user, params: callout_params
- ).execute
- end
-
- def callout_params
- params.permit(:namespace_id).merge(feature_name: feature_name)
- end
- end
-end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 3c1a3534912..c35aa8e4346 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -35,7 +35,7 @@ class UsersController < ApplicationController
feature_category :source_code_management, [:gpg_keys]
# TODO: Set higher urgency after resolving https://gitlab.com/gitlab-org/gitlab/-/issues/357914
- urgency :low, [:show, :calendar_activities, :contributed, :activity, :projects, :groups, :calendar]
+ urgency :low, [:show, :calendar_activities, :contributed, :activity, :projects, :groups, :calendar, :snippets]
urgency :default, [:followers, :following, :starred]
urgency :high, [:exists]
@@ -174,8 +174,9 @@ class UsersController < ApplicationController
end
def follow
- current_user.follow(user)
+ followee = current_user.follow(user)
+ flash[:alert] = followee.errors.full_messages.join(', ') if followee&.errors&.any?
redirect_path = referer_path(request) || @user
redirect_to redirect_path
diff --git a/app/events/pages_domains/pages_domain_created_event.rb b/app/events/pages_domains/pages_domain_created_event.rb
new file mode 100644
index 00000000000..a86718f4681
--- /dev/null
+++ b/app/events/pages_domains/pages_domain_created_event.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class PagesDomainCreatedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'domain' => { 'type' => 'string' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/pages_domains/pages_domain_deleted_event.rb b/app/events/pages_domains/pages_domain_deleted_event.rb
new file mode 100644
index 00000000000..7fe165a7249
--- /dev/null
+++ b/app/events/pages_domains/pages_domain_deleted_event.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class PagesDomainDeletedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'domain' => { 'type' => 'string' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/pages_domains/pages_domain_updated_event.rb b/app/events/pages_domains/pages_domain_updated_event.rb
new file mode 100644
index 00000000000..641fb2f6a53
--- /dev/null
+++ b/app/events/pages_domains/pages_domain_updated_event.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class PagesDomainUpdatedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'domain' => { 'type' => 'string' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/projects/project_attributes_changed_event.rb b/app/events/projects/project_attributes_changed_event.rb
new file mode 100644
index 00000000000..f7c27fa65e6
--- /dev/null
+++ b/app/events/projects/project_attributes_changed_event.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Projects
+ class ProjectAttributesChangedEvent < ::Gitlab::EventStore::Event
+ PAGES_RELATED_ATTRIBUTES = %w[
+ pages_https_only
+ visibility_level
+ ].freeze
+
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'attributes' => { 'type' => 'array' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id attributes]
+ }
+ end
+
+ def pages_related?
+ PAGES_RELATED_ATTRIBUTES.any? do |attribute|
+ data[:attributes].include?(attribute)
+ end
+ end
+ end
+end
diff --git a/app/events/projects/project_features_changed_event.rb b/app/events/projects/project_features_changed_event.rb
new file mode 100644
index 00000000000..a0c6fa1a3f9
--- /dev/null
+++ b/app/events/projects/project_features_changed_event.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Projects
+ class ProjectFeaturesChangedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'features' => { 'type' => 'array' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id features]
+ }
+ end
+
+ def pages_related?
+ data[:features].include?("pages_access_level")
+ end
+ end
+end
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 774947a35b7..d0d98a59677 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -55,6 +55,12 @@ module Ci
Ci::Runner.belonging_to_group(@group.id)
when :descendants, nil
Ci::Runner.belonging_to_group_or_project_descendants(@group.id)
+ when :all_available
+ unless can?(@current_user, :read_group_all_available_runners, @group)
+ raise Gitlab::Access::AccessDeniedError
+ end
+
+ Ci::Runner.usable_from_scope(@group)
else
raise ArgumentError, 'Invalid membership filter'
end
diff --git a/app/finders/clusters/agent_authorizations_finder.rb b/app/finders/clusters/agent_authorizations_finder.rb
index 373cf7fe8b9..8b939f5d646 100644
--- a/app/finders/clusters/agent_authorizations_finder.rb
+++ b/app/finders/clusters/agent_authorizations_finder.rb
@@ -24,13 +24,21 @@ module Clusters
# rubocop: disable CodeReuse/ActiveRecord
def project_authorizations
- ancestor_ids = project.group ? project.ancestors.select(:id) : project.namespace_id
+ namespace_ids = if project.group
+ if include_descendants?
+ all_namespace_ids
+ else
+ ancestor_namespace_ids
+ end
+ else
+ project.namespace_id
+ end
Clusters::Agents::ProjectAuthorization
.where(project_id: project.id)
.joins(agent: :project)
.preload(agent: :project)
- .where(cluster_agents: { projects: { namespace_id: ancestor_ids } })
+ .where(cluster_agents: { projects: { namespace_id: namespace_ids } })
.with_available_ci_access_fields(project)
.to_a
end
@@ -49,17 +57,35 @@ module Clusters
authorizations[:group_id].eq(ordered_ancestors_cte.table[:id])
).join_sources
- Clusters::Agents::GroupAuthorization
+ authorized_groups = Clusters::Agents::GroupAuthorization
.with(ordered_ancestors_cte.to_arel)
.joins(cte_join_sources)
.joins(agent: :project)
- .where('projects.namespace_id IN (SELECT id FROM ordered_ancestors)')
.with_available_ci_access_fields(project)
.order(Arel.sql('agent_id, array_position(ARRAY(SELECT id FROM ordered_ancestors)::bigint[], agent_group_authorizations.group_id)'))
.select('DISTINCT ON (agent_id) agent_group_authorizations.*')
.preload(agent: :project)
- .to_a
+
+ authorized_groups = if include_descendants?
+ authorized_groups.where(projects: { namespace_id: all_namespace_ids })
+ else
+ authorized_groups.where('projects.namespace_id IN (SELECT id FROM ordered_ancestors)')
+ end
+
+ authorized_groups.to_a
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def ancestor_namespace_ids
+ project.ancestors.select(:id)
+ end
+
+ def all_namespace_ids
+ project.root_ancestor.self_and_descendants.select(:id)
+ end
+
+ def include_descendants?
+ Feature.enabled?(:agent_authorization_include_descendants, project)
+ end
end
end
diff --git a/app/finders/groups/accepting_group_transfers_finder.rb b/app/finders/groups/accepting_group_transfers_finder.rb
index df67f940d20..c95318d0098 100644
--- a/app/finders/groups/accepting_group_transfers_finder.rb
+++ b/app/finders/groups/accepting_group_transfers_finder.rb
@@ -13,12 +13,7 @@ module Groups
def execute
return Group.none unless can_transfer_group?
- items = if Feature.enabled?(:include_groups_from_group_shares_in_group_transfer_locations)
- find_all_groups
- else
- find_groups
- end
-
+ items = find_all_groups
items = by_search(items)
sort(items)
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index ecd6270ed47..9f9d0da6efd 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -19,7 +19,7 @@ class LabelsFinder < UnionFinder
items = with_title(items)
items = by_subscription(items)
items = by_search(items)
- sort(items)
+ sort(items.with_preloaded_container)
end
private
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 1d1ae59674a..3a068252d5c 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -22,7 +22,7 @@ module Packages
def packages_for_group_projects(installable_only: false)
packages = ::Packages::Package
- .including_project_route
+ .including_project_namespace_route
.including_tags
.for_projects(group_projects_visible_to_current_user.select(:id))
.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}")
diff --git a/app/finders/packages/helm/packages_finder.rb b/app/finders/packages/helm/packages_finder.rb
index c58d9292e9f..e1b831ca864 100644
--- a/app/finders/packages/helm/packages_finder.rb
+++ b/app/finders/packages/helm/packages_finder.rb
@@ -5,7 +5,7 @@ module Packages
class PackagesFinder
include ::Packages::FinderHelper
- MAX_PACKAGES_COUNT = 300
+ MAX_PACKAGES_COUNT = 1000
def initialize(project, channel)
@project = project
diff --git a/app/finders/packages/nuget/package_finder.rb b/app/finders/packages/nuget/package_finder.rb
index 9ae52745bb2..23345f29198 100644
--- a/app/finders/packages/nuget/package_finder.rb
+++ b/app/finders/packages/nuget/package_finder.rb
@@ -15,7 +15,7 @@ module Packages
result = base.nuget
.has_version
.with_name_like(@params[:package_name])
- result = result.with_version(@params[:package_version]) if @params[:package_version].present?
+ result = result.with_case_insensitive_version(@params[:package_version]) if @params[:package_version].present?
result
end
end
diff --git a/app/finders/packages/package_finder.rb b/app/finders/packages/package_finder.rb
index e482a0503f0..9e667b7a63c 100644
--- a/app/finders/packages/package_finder.rb
+++ b/app/finders/packages/package_finder.rb
@@ -10,7 +10,7 @@ module Packages
@project
.packages
.preload_pipelines
- .including_project_route
+ .including_project_namespace_route
.including_tags
.displayable
.find(@package_id)
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index b3d14e15953..31fbbfb7937 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -14,7 +14,7 @@ module Packages
def execute
packages = project.packages
- .including_project_route
+ .including_project_namespace_route
.including_tags
packages = packages.preload_pipelines if preload_pipelines
diff --git a/app/finders/personal_access_tokens_finder.rb b/app/finders/personal_access_tokens_finder.rb
index 7d356c1014c..8403c531945 100644
--- a/app/finders/personal_access_tokens_finder.rb
+++ b/app/finders/personal_access_tokens_finder.rb
@@ -18,6 +18,12 @@ class PersonalAccessTokensFinder
tokens = by_impersonation(tokens)
tokens = by_state(tokens)
tokens = by_owner_type(tokens)
+ tokens = by_revoked_state(tokens)
+ tokens = by_created_before(tokens)
+ tokens = by_created_after(tokens)
+ tokens = by_last_used_before(tokens)
+ tokens = by_last_used_after(tokens)
+ tokens = by_search(tokens)
sort(tokens)
end
@@ -83,4 +89,40 @@ class PersonalAccessTokensFinder
tokens
end
end
+
+ def by_revoked_state(tokens)
+ return tokens unless params.has_key?(:revoked)
+
+ params[:revoked] ? tokens.revoked : tokens.not_revoked
+ end
+
+ def by_created_before(tokens)
+ return tokens unless params[:created_before]
+
+ tokens.created_before(params[:created_before])
+ end
+
+ def by_created_after(tokens)
+ return tokens unless params[:created_after]
+
+ tokens.created_after(params[:created_after])
+ end
+
+ def by_last_used_before(tokens)
+ return tokens unless params[:last_used_before]
+
+ tokens.last_used_before(params[:last_used_before])
+ end
+
+ def by_last_used_after(tokens)
+ return tokens unless params[:last_used_after]
+
+ tokens.last_used_after(params[:last_used_after])
+ end
+
+ def by_search(tokens)
+ return tokens unless params[:search]
+
+ tokens.search(params[:search])
+ end
end
diff --git a/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb b/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb
new file mode 100644
index 00000000000..c1b35d3eaf7
--- /dev/null
+++ b/app/graphql/batch_loaders/award_emoji_votes_batch_loader.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module BatchLoaders
+ module AwardEmojiVotesBatchLoader
+ private
+
+ def load_votes(object, vote_type)
+ BatchLoader::GraphQL.for(object.id).batch(key: "#{object.issuing_parent_id}-#{vote_type}") do |ids, loader, args|
+ counts = AwardEmoji.votes_for_collection(ids, object.class.name).named(vote_type).index_by(&:awardable_id)
+
+ ids.each do |id|
+ loader.call(id, counts[id]&.count || 0)
+ end
+ end
+ end
+
+ def authorized_resource?(object)
+ Ability.allowed?(current_user, "read_#{object.to_ability_name}".to_sym, object)
+ end
+ end
+end
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index c0e063a34d5..37adf4c2d3b 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -137,6 +137,19 @@ class GitlabSchema < GraphQL::Schema
gid
end
+ # Parse an array of strings to an array of GlobalIDs, raising ArgumentError if there are problems
+ # with it.
+ # See #parse_gid
+ #
+ # ```
+ # gids = GitlabSchema.parse_gids(my_array_of_strings, expected_type: ::Project)
+ # project_ids = gids.map(&:model_id)
+ # gids.all? { |gid| gid.model_class == ::Project }
+ # ```
+ def parse_gids(global_ids, ctx = {})
+ global_ids.map { |gid| parse_gid(gid, ctx) }
+ end
+
private
def max_query_complexity(ctx)
diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb
index 8086d8c02a4..dc4f838ae36 100644
--- a/app/graphql/graphql_triggers.rb
+++ b/app/graphql/graphql_triggers.rb
@@ -13,6 +13,10 @@ module GraphqlTriggers
GitlabSchema.subscriptions.trigger('issuableTitleUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+ def self.issuable_description_updated(issuable)
+ GitlabSchema.subscriptions.trigger('issuableDescriptionUpdated', { issuable_id: issuable.to_gid }, issuable)
+ end
+
def self.issuable_labels_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableLabelsUpdated', { issuable_id: issuable.to_gid }, issuable)
end
@@ -20,6 +24,22 @@ module GraphqlTriggers
def self.issuable_dates_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableDatesUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+
+ def self.merge_request_reviewers_updated(merge_request)
+ GitlabSchema.subscriptions.trigger(
+ 'mergeRequestReviewersUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ )
+ end
+
+ def self.merge_request_merge_status_updated(merge_request)
+ GitlabSchema.subscriptions.trigger(
+ 'mergeRequestMergeStatusUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ )
+ end
end
GraphqlTriggers.prepend_mod
diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb
index 2c128e1b339..77a7d7a4147 100644
--- a/app/graphql/mutations/alert_management/create_alert_issue.rb
+++ b/app/graphql/mutations/alert_management/create_alert_issue.rb
@@ -24,8 +24,8 @@ module Mutations
def prepare_response(alert, result)
{
alert: alert,
- issue: result.payload[:issue],
- errors: Array(result.message)
+ issue: result[:issue],
+ errors: result.errors
}
end
end
diff --git a/app/graphql/mutations/ci/job/artifacts_destroy.rb b/app/graphql/mutations/ci/job/artifacts_destroy.rb
index c27ab9c4d89..34c58fc1240 100644
--- a/app/graphql/mutations/ci/job/artifacts_destroy.rb
+++ b/app/graphql/mutations/ci/job/artifacts_destroy.rb
@@ -25,12 +25,21 @@ module Mutations
def resolve(id:)
job = authorized_find!(id: id)
- result = ::Ci::JobArtifacts::DestroyBatchService.new(job.job_artifacts, pick_up_at: Time.current).execute
- {
- job: job,
- destroyed_artifacts_count: result[:destroyed_artifacts_count],
- errors: Array(result[:errors])
- }
+ result = ::Ci::JobArtifacts::DeleteService.new(job).execute
+
+ if result.success?
+ {
+ job: job,
+ destroyed_artifacts_count: result.payload[:destroyed_artifacts_count],
+ errors: Array(result.payload[:errors])
+ }
+ else
+ {
+ job: job,
+ destroyed_artifacts_count: 0,
+ errors: Array(result.message)
+ }
+ end
end
end
end
diff --git a/app/graphql/mutations/ci/pipeline_schedule/base.rb b/app/graphql/mutations/ci/pipeline_schedule/base.rb
new file mode 100644
index 00000000000..a737ccce575
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_schedule/base.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module PipelineSchedule
+ class Base < BaseMutation
+ PipelineScheduleID = ::Types::GlobalIDType[::Ci::PipelineSchedule]
+
+ argument :id, PipelineScheduleID,
+ required: true,
+ description: 'ID of the pipeline schedule to mutate.'
+
+ private
+
+ def find_object(id:)
+ GlobalID::Locator.locate(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/pipeline_schedule/delete.rb b/app/graphql/mutations/ci/pipeline_schedule/delete.rb
new file mode 100644
index 00000000000..ead9a43161d
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_schedule/delete.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module PipelineSchedule
+ class Delete < Base
+ graphql_name 'PipelineScheduleDelete'
+
+ authorize :admin_pipeline_schedule
+
+ def resolve(id:)
+ schedule = authorized_find!(id: id)
+
+ if schedule.destroy
+ {
+ errors: []
+ }
+ else
+ {
+ errors: ['Failed to remove the pipeline schedule']
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
index b0cffa2c088..27b066ffcf6 100644
--- a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
+++ b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb
@@ -19,7 +19,13 @@ module Mutations
argument :job_token_scope_enabled, GraphQL::Types::Boolean,
required: false,
- description: 'Indicates CI job tokens generated in this project have restricted access to resources.'
+ description: 'Indicates CI/CD job tokens generated in this project ' \
+ 'have restricted access to other projects.'
+
+ argument :inbound_job_token_scope_enabled, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Indicates CI/CD job tokens generated in other projects ' \
+ 'have restricted access to this project.'
field :ci_cd_settings,
Types::Ci::CiCdSettingType,
@@ -28,6 +34,9 @@ module Mutations
def resolve(full_path:, **args)
project = authorized_find!(full_path)
+
+ args.delete(:inbound_job_token_scope_enabled) unless Feature.enabled?(:ci_inbound_job_token_scope, project)
+
settings = project.ci_cd_settings
settings.update(args)
diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb
index f98138646be..2f2c8c4c668 100644
--- a/app/graphql/mutations/ci/runner/update.rb
+++ b/app/graphql/mutations/ci/runner/update.rb
@@ -94,6 +94,7 @@ module Mutations
).execute
return if result.success?
+ response[:runner] = nil
response[:errors] = result.errors
raise ActiveRecord::Rollback
end
@@ -102,6 +103,7 @@ module Mutations
result = ::Ci::Runners::UpdateRunnerService.new(runner).execute(attrs)
return if result.success?
+ response[:runner] = nil
response[:errors] = result.errors
raise ActiveRecord::Rollback
end
diff --git a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
index 1f90f394521..e42e59de78f 100644
--- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
+++ b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
@@ -30,6 +30,9 @@ module Mutations
argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
required: false,
description: 'Input for start and due date widget.'
+ argument :labels_widget, ::Types::WorkItems::Widgets::LabelsUpdateInputType,
+ required: false,
+ description: 'Input for labels widget.'
end
end
end
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 6bf8caf82d7..0389a482822 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -83,13 +83,13 @@ module Mutations
params = build_create_issue_params(attributes.merge(author_id: current_user.id), project)
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
- issue = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
+ result = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
- check_spam_action_response!(issue)
+ check_spam_action_response!(result[:issue]) if result[:issue]
{
- issue: issue.valid? ? issue : nil,
- errors: errors_on_object(issue)
+ issue: result.success? ? result[:issue] : nil,
+ errors: result.errors
}
end
diff --git a/app/graphql/mutations/namespace/package_settings/update.rb b/app/graphql/mutations/namespace/package_settings/update.rb
index e499e646781..ea72b71715c 100644
--- a/app/graphql/mutations/namespace/package_settings/update.rb
+++ b/app/graphql/mutations/namespace/package_settings/update.rb
@@ -35,6 +35,36 @@ module Mutations
required: false,
description: copy_field_description(Types::Namespace::PackageSettingsType, :generic_duplicate_exception_regex)
+ argument :maven_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_package_requests_forwarding)
+
+ argument :npm_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :npm_package_requests_forwarding)
+
+ argument :pypi_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :pypi_package_requests_forwarding)
+
+ argument :lock_maven_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_maven_package_requests_forwarding)
+
+ argument :lock_npm_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_npm_package_requests_forwarding)
+
+ argument :lock_pypi_package_requests_forwarding,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: copy_field_description(Types::Namespace::PackageSettingsType, :lock_pypi_package_requests_forwarding)
+
field :package_settings,
Types::Namespace::PackageSettingsType,
null: true,
diff --git a/app/graphql/mutations/packages/bulk_destroy.rb b/app/graphql/mutations/packages/bulk_destroy.rb
new file mode 100644
index 00000000000..a0756d0c3f9
--- /dev/null
+++ b/app/graphql/mutations/packages/bulk_destroy.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Packages
+ class BulkDestroy < ::Mutations::BaseMutation
+ graphql_name 'DestroyPackages'
+
+ MAX_PACKAGES = 20
+ TOO_MANY_IDS_ERROR = "Cannot delete more than #{MAX_PACKAGES} packages"
+
+ argument :ids,
+ [::Types::GlobalIDType[::Packages::Package]],
+ required: true,
+ description: "Global IDs of the Packages. Max #{MAX_PACKAGES}"
+
+ def resolve(ids:)
+ raise_resource_not_available_error!(TOO_MANY_IDS_ERROR) if ids.size > MAX_PACKAGES
+
+ ids = GitlabSchema.parse_gids(ids, expected_type: ::Packages::Package)
+ .map(&:model_id)
+
+ service = ::Packages::MarkPackagesForDestructionService.new(
+ packages: packages_from(ids),
+ current_user: current_user
+ )
+ result = service.execute
+
+ raise_resource_not_available_error! if result.reason == :unauthorized
+
+ errors = result.error? ? Array.wrap(result[:message]) : []
+
+ { errors: errors }
+ end
+
+ private
+
+ def packages_from(ids)
+ ::Packages::Package.displayable
+ .id_in(ids)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/packages/destroy_files.rb b/app/graphql/mutations/packages/destroy_files.rb
index 3900a2c46ae..60a21be20d8 100644
--- a/app/graphql/mutations/packages/destroy_files.rb
+++ b/app/graphql/mutations/packages/destroy_files.rb
@@ -25,7 +25,7 @@ module Mutations
project = authorized_find!(project_path)
raise_resource_not_available_error! "Cannot delete more than #{MAXIMUM_FILES} files" if ids.size > MAXIMUM_FILES
- package_files = ::Packages::PackageFile.where(id: parse_gids(ids)) # rubocop:disable CodeReuse/ActiveRecord
+ package_files = ::Packages::PackageFile.id_in(parse_gids(ids))
ensure_file_access!(project, package_files)
@@ -47,7 +47,7 @@ module Mutations
end
def parse_gids(gids)
- gids.map { |gid| GitlabSchema.parse_gid(gid, expected_type: ::Packages::PackageFile).model_id }
+ GitlabSchema.parse_gids(gids, expected_type: ::Packages::PackageFile).map(&:model_id)
end
end
end
diff --git a/app/graphql/mutations/work_items/update_widgets.rb b/app/graphql/mutations/work_items/update_widgets.rb
deleted file mode 100644
index 7037b7e5a2a..00000000000
--- a/app/graphql/mutations/work_items/update_widgets.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module WorkItems
- # TODO: Deprecate in favor of using WorkItemUpdate. See https://gitlab.com/gitlab-org/gitlab/-/issues/366300
- class UpdateWidgets < BaseMutation
- graphql_name 'WorkItemUpdateWidgets'
- description "Updates the attributes of a work item's widgets by global ID." \
- " Available only when feature flag `work_items` is enabled."
-
- include Mutations::SpamProtection
-
- authorize :update_work_item
-
- argument :id, ::Types::GlobalIDType[::WorkItem],
- required: true,
- description: 'Global ID of the work item.'
-
- argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
- required: false,
- description: 'Input for description widget.'
-
- field :work_item, Types::WorkItemType,
- null: true,
- description: 'Updated work item.'
-
- def resolve(id:, **widget_attributes)
- work_item = authorized_find!(id: id)
-
- unless work_item.project.work_items_feature_flag_enabled?
- return { errors: ['`work_items` feature flag disabled for this project'] }
- end
-
- spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
-
- ::WorkItems::UpdateService.new(
- project: work_item.project,
- current_user: current_user,
- # Cannot use prepare to use `.to_h` on each input due to
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87472#note_945199865
- widget_params: widget_attributes.transform_values { |values| values.to_h },
- spam_params: spam_params
- ).execute(work_item)
-
- check_spam_action_response!(work_item)
-
- {
- work_item: work_item.valid? ? work_item : nil,
- errors: errors_on_object(work_item)
- }
- end
-
- private
-
- def find_object(id:)
- GitlabSchema.find_by_gid(id)
- end
- end
- end
-end
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
index ec47a8996eb..6357132705e 100644
--- a/app/graphql/resolvers/base_issues_resolver.rb
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -47,8 +47,8 @@ module Resolvers
def preloads
{
alert_management_alert: [:alert_management_alert],
- labels: [:labels],
assignees: [:assignees],
+ participants: Issue.participant_includes,
timelogs: [:timelogs],
customer_relations_contacts: { customer_relations_contacts: [:group] },
escalation_status: [:incident_management_issuable_escalation_status]
diff --git a/app/graphql/resolvers/bulk_labels_resolver.rb b/app/graphql/resolvers/bulk_labels_resolver.rb
new file mode 100644
index 00000000000..7362e257fb6
--- /dev/null
+++ b/app/graphql/resolvers/bulk_labels_resolver.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class BulkLabelsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::LabelType.connection_type, null: true
+
+ def resolve
+ authorize!(object)
+
+ BatchLoader::GraphQL.for(object.id).batch(cache: false) do |ids, loader, args|
+ labels = Label.for_targets(object.class.id_in(ids)).group_by(&:target_id)
+
+ ids.each do |id|
+ loader.call(id, labels[id] || [])
+ end
+ end
+ end
+
+ private
+
+ def authorized_resource?(object)
+ Ability.allowed?(current_user, :read_label, object.issuing_parent)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/all_jobs_resolver.rb b/app/graphql/resolvers/ci/all_jobs_resolver.rb
new file mode 100644
index 00000000000..d918bed9f57
--- /dev/null
+++ b/app/graphql/resolvers/ci/all_jobs_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class AllJobsResolver < BaseResolver
+ type ::Types::Ci::JobType.connection_type, null: true
+
+ argument :statuses, [::Types::Ci::JobStatusEnum],
+ required: false,
+ description: 'Filter jobs by status.'
+
+ def resolve(statuses: nil)
+ ::Ci::JobsFinder.new(current_user: current_user, params: { scope: statuses }).execute
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runner_projects_resolver.rb b/app/graphql/resolvers/ci/runner_projects_resolver.rb
index ca3b4ebb797..af9a67acfda 100644
--- a/app/graphql/resolvers/ci/runner_projects_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_projects_resolver.rb
@@ -21,8 +21,8 @@ module Resolvers
'Specify `"id_asc"` if query results\' order is important',
milestone: '15.4'
},
- description: "Sort order of results. Format: '<field_name>_<sort_direction>', " \
- "for example: 'id_desc' or 'name_asc'"
+ description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
+ "for example: `id_desc` or `name_asc`"
def resolve_with_lookahead(**args)
return unless runner.project_type?
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index b548dc1e175..81099c04e9f 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -32,16 +32,37 @@ module LooksAhead
{}
end
+ def nested_preloads
+ {}
+ end
+
def filtered_preloads
nodes = node_selection
return [] unless nodes
selected_fields = nodes.selections.map(&:name)
+ root_level_preloads = preloads_from_node_selection(selected_fields, preloads)
- preloads.each.flat_map do |name, requirements|
- selected_fields.include?(name) ? requirements : []
- end
+ root_level_preloads + nested_filtered_preloads(nodes, selected_fields)
+ end
+
+ def nested_filtered_preloads(nodes, selected_root_fields)
+ return [] if nested_preloads.empty?
+
+ nested_preloads.each_with_object([]) do |(root_field, fields), result|
+ next unless selected_root_fields.include?(root_field)
+
+ selected_fields = nodes.selection(root_field).selections.map(&:name)
+
+ result << preloads_from_node_selection(selected_fields, fields)
+ end.flatten
+ end
+
+ def preloads_from_node_selection(selected_fields, fields)
+ fields.each_with_object([]) do |(field, requirements), result|
+ result << requirements if selected_fields.include?(field)
+ end.flatten
end
def node_selection
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
index 697cc6f5b03..d56951bc821 100644
--- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -42,7 +42,6 @@ module ResolvesMergeRequests
assignees: [:assignees],
reviewers: [:reviewers],
participants: MergeRequest.participant_includes,
- labels: [:labels],
author: [:author],
merged_at: [:metrics],
commit_count: [:metrics],
@@ -53,7 +52,8 @@ module ResolvesMergeRequests
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
timelogs: [:timelogs],
pipelines: [:merge_request_diffs], # used by `recent_diff_head_shas` to load pipelines
- committers: [merge_request_diff: [:merge_request_diff_commits]]
+ committers: [merge_request_diff: [:merge_request_diff_commits]],
+ suggested_reviewers: [:predictions]
}
end
end
diff --git a/app/graphql/resolvers/down_votes_count_resolver.rb b/app/graphql/resolvers/down_votes_count_resolver.rb
new file mode 100644
index 00000000000..0e7772f988a
--- /dev/null
+++ b/app/graphql/resolvers/down_votes_count_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class DownVotesCountResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include BatchLoaders::AwardEmojiVotesBatchLoader
+
+ type GraphQL::Types::Int, null: true
+
+ def resolve
+ authorize!(object)
+ load_votes(object, AwardEmoji::DOWNVOTE_NAME)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/project_pipeline_schedules_resolver.rb b/app/graphql/resolvers/project_pipeline_schedules_resolver.rb
new file mode 100644
index 00000000000..eb980f72717
--- /dev/null
+++ b/app/graphql/resolvers/project_pipeline_schedules_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ProjectPipelineSchedulesResolver < BaseResolver
+ alias_method :project, :object
+
+ type ::Types::Ci::PipelineScheduleType.connection_type, null: true
+
+ argument :status, ::Types::Ci::PipelineScheduleStatusEnum,
+ required: false,
+ description: 'Filter pipeline schedules by active status.'
+
+ def resolve(status: nil)
+ ::Ci::PipelineSchedulesFinder.new(project).execute(scope: status)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/projects/branch_rules_resolver.rb b/app/graphql/resolvers/projects/branch_rules_resolver.rb
index 6c8b416bcea..e99d7ae4d5f 100644
--- a/app/graphql/resolvers/projects/branch_rules_resolver.rb
+++ b/app/graphql/resolvers/projects/branch_rules_resolver.rb
@@ -3,13 +3,17 @@
module Resolvers
module Projects
class BranchRulesResolver < BaseResolver
+ include LooksAhead
+
type Types::Projects::BranchRuleType.connection_type, null: false
alias_method :project, :object
- def resolve(**args)
- project.protected_branches
+ def resolve_with_lookahead(**args)
+ apply_lookahead(project.protected_branches)
end
end
end
end
+
+Resolvers::Projects::BranchRulesResolver.prepend_mod_with('Resolvers::Projects::BranchRulesResolver')
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index 4d1e1b867da..0bdba53c7af 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -12,8 +12,8 @@ module Resolvers
argument :sort, GraphQL::Types::String,
required: false,
- description: "Sort order of results. Format: '<field_name>_<sort_direction>', " \
- "for example: 'id_desc' or 'name_asc'"
+ description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
+ "for example: `id_desc` or `name_asc`"
def resolve(**args)
ProjectsFinder
diff --git a/app/graphql/resolvers/up_votes_count_resolver.rb b/app/graphql/resolvers/up_votes_count_resolver.rb
new file mode 100644
index 00000000000..1c78facb694
--- /dev/null
+++ b/app/graphql/resolvers/up_votes_count_resolver.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class UpVotesCountResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include BatchLoaders::AwardEmojiVotesBatchLoader
+
+ type GraphQL::Types::Int, null: true
+
+ def resolve
+ authorize!(object)
+ load_votes(object, AwardEmoji::UPVOTE_NAME)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb
index a8c0d363325..a4cbcc61ead 100644
--- a/app/graphql/resolvers/work_items_resolver.rb
+++ b/app/graphql/resolvers/work_items_resolver.rb
@@ -37,20 +37,26 @@ module Resolvers
def preloads
{
- last_edited_by: :last_edited_by,
- web_url: { project: { namespace: :route } }
+ work_item_type: :work_item_type,
+ web_url: { project: { namespace: :route } },
+ widgets: :work_item_type
}
end
- # Allows to apply lookahead for fields
- # selected from WidgetInterface
- override :node_selection
- def node_selection
- selected_fields = super
-
- return unless selected_fields
+ def nested_preloads
+ {
+ widgets: widget_preloads,
+ user_permissions: { update_work_item: :assignees }
+ }
+ end
- selected_fields.selection(:widgets)
+ def widget_preloads
+ {
+ last_edited_by: :last_edited_by,
+ assignees: :assignees,
+ parent: :work_item_parent,
+ labels: :labels
+ }
end
def unconditional_includes
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index bec8c72e783..574791b79e6 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -10,8 +10,17 @@ module Types
field :job_token_scope_enabled,
GraphQL::Types::Boolean,
null: true,
- description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
+ description: 'Indicates CI/CD job tokens generated in this project ' \
+ 'have restricted access to other projects.',
method: :job_token_scope_enabled?
+
+ field :inbound_job_token_scope_enabled,
+ GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates CI/CD job tokens generated in other projects ' \
+ 'have restricted access to this project.',
+ method: :inbound_job_token_scope_enabled?
+
field :keep_latest_artifact, GraphQL::Types::Boolean, null: true,
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
diff --git a/app/graphql/types/ci/config_variable_type.rb b/app/graphql/types/ci/config_variable_type.rb
index 87ae026c2c1..5b5890fd5a5 100644
--- a/app/graphql/types/ci/config_variable_type.rb
+++ b/app/graphql/types/ci/config_variable_type.rb
@@ -17,6 +17,10 @@ module Types
field :value, GraphQL::Types::String,
null: true,
description: 'Value of the variable.'
+
+ field :value_options, [GraphQL::Types::String],
+ null: true,
+ description: 'Value options for the variable.'
end
end
end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index ab6103d9469..4447a10a74e 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -56,6 +56,8 @@ module Types
description: 'Indicates the job is active.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
description: 'Artifacts generated by the job.'
+ field :browse_artifacts_path, GraphQL::Types::String, null: true,
+ description: "URL for browsing the artifact's archive."
field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?,
description: 'Indicates the job can be canceled.'
field :commit_path, GraphQL::Types::String, null: true,
@@ -148,17 +150,7 @@ module Types
end
def stage
- ::Gitlab::Graphql::Lazy.with_value(pipeline) do |pl|
- BatchLoader::GraphQL.for([pl, object.stage]).batch do |ids, loader|
- by_pipeline = ids
- .group_by(&:first)
- .transform_values { |grp| grp.map(&:second) }
-
- by_pipeline.each do |p, names|
- p.stages.by_name(names).each { |s| loader.call([p, s.name], s) }
- end
- end
- end
+ ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Stage, object.stage_id).find
end
# This class is a secret union!
@@ -187,6 +179,10 @@ module Types
::Gitlab::Routing.url_helpers.project_job_path(object.project, object)
end
+ def browse_artifacts_path
+ ::Gitlab::Routing.url_helpers.browse_project_job_artifacts_path(object.project, object)
+ end
+
def coverage
object&.coverage
end
diff --git a/app/graphql/types/ci/pipeline_schedule_status_enum.rb b/app/graphql/types/ci/pipeline_schedule_status_enum.rb
new file mode 100644
index 00000000000..61bae7daff8
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_schedule_status_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScheduleStatusEnum < BaseEnum
+ graphql_name 'PipelineScheduleStatus'
+
+ value 'ACTIVE', value: "active", description: 'Active pipeline schedules.'
+ value 'INACTIVE', value: "inactive", description: 'Inactive pipeline schedules.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_schedule_type.rb b/app/graphql/types/ci/pipeline_schedule_type.rb
new file mode 100644
index 00000000000..04f9fc78a92
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_schedule_type.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScheduleType < BaseObject
+ graphql_name 'PipelineSchedule'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ expose_permissions Types::PermissionTypes::Ci::PipelineSchedules
+
+ authorize :read_pipeline_schedule
+
+ field :id, GraphQL::Types::ID, null: false, description: 'ID of the pipeline schedule.'
+
+ field :description, GraphQL::Types::String, null: true, description: 'Description of the pipeline schedule.'
+
+ field :owner, ::Types::UserType, null: false, description: 'Owner of the pipeline schedule.'
+
+ field :active, GraphQL::Types::Boolean, null: false, description: 'Indicates if a pipeline schedule is active.'
+
+ field :next_run_at, Types::TimeType, null: false, description: 'Time when the next pipeline will run.'
+
+ field :real_next_run, Types::TimeType, null: false, description: 'Time when the next pipeline will run.'
+
+ field :last_pipeline, PipelineType, null: true, description: 'Last pipeline object.'
+
+ field :ref_for_display, GraphQL::Types::String,
+ null: true, description: 'Git ref for the pipeline schedule.', method: :ref_for_display
+
+ field :ref_path, GraphQL::Types::String, null: true, description: 'Path to the ref that triggered the pipeline.'
+
+ field :for_tag, GraphQL::Types::Boolean,
+ null: false, description: 'Indicates if a pipelines schedule belongs to a tag.', method: :for_tag?
+
+ field :cron, GraphQL::Types::String, null: false, description: 'Cron notation for the schedule.'
+
+ field :cron_timezone, GraphQL::Types::String, null: false, description: 'Timezone for the pipeline schedule.'
+
+ def ref_path
+ ::Gitlab::Routing.url_helpers.project_commits_path(object.project, object.ref_for_display)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/runner_membership_filter_enum.rb b/app/graphql/types/ci/runner_membership_filter_enum.rb
index 4fd7e0749b0..d59a68b427b 100644
--- a/app/graphql/types/ci/runner_membership_filter_enum.rb
+++ b/app/graphql/types/ci/runner_membership_filter_enum.rb
@@ -15,6 +15,13 @@ module Types
description: "Include runners that have either a direct or inherited relationship. " \
"These runners can be specific to a project or a group.",
value: :descendants
+
+ value 'ALL_AVAILABLE',
+ description:
+ "Include all runners. This list includes runners for all projects in the group " \
+ "and subgroups, as well as for the parent groups and instance.",
+ value: :all_available,
+ deprecated: { milestone: '15.5', reason: :alpha }
end
end
end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index eb4e7b1dabf..dd2286d333d 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -57,7 +57,7 @@ module Types
field :deployments,
Types::DeploymentType.connection_type,
null: true,
- description: 'Deployments of the environment. This field can only be resolved for one project in any single request.',
+ description: 'Deployments of the environment. This field can only be resolved for one environment in any single request.',
resolver: Resolvers::DeploymentsResolver do
extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1
end
@@ -72,3 +72,5 @@ module Types
end
end
end
+
+Types::EnvironmentType.prepend_mod_with('Types::EnvironmentType')
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index d897f3cde48..76fac831199 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -43,8 +43,10 @@ module Types
field :updated_by, Types::UserType, null: true,
description: 'User that last updated the issue.'
- field :labels, Types::LabelType.connection_type, null: true,
- description: 'Labels of the issue.'
+ field :labels, Types::LabelType.connection_type,
+ null: true,
+ description: 'Labels of the issue.',
+ resolver: Resolvers::BulkLabelsResolver
field :milestone, Types::MilestoneType, null: true,
description: 'Milestone of the issue.'
@@ -58,15 +60,20 @@ module Types
description: 'Indicates the issue is hidden because the author has been banned. ' \
'Will always return `null` if `ban_user_feature_flag` feature flag is disabled.'
- field :downvotes, GraphQL::Types::Int, null: false,
- description: 'Number of downvotes the issue has received.'
+ field :downvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of downvotes the issue has received.',
+ resolver: Resolvers::DownVotesCountResolver
field :merge_requests_count, GraphQL::Types::Int, null: false,
description: 'Number of merge requests that close the issue on merge.',
resolver: Resolvers::MergeRequestsCountResolver
field :relative_position, GraphQL::Types::Int, null: true,
description: 'Relative position of the issue (used for positioning in epic tree and issue boards).'
- field :upvotes, GraphQL::Types::Int, null: false,
- description: 'Number of upvotes the issue has received.'
+ field :upvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of upvotes the issue has received.',
+ resolver: Resolvers::UpVotesCountResolver
+
field :user_discussions_count, GraphQL::Types::Int, null: false,
description: 'Number of user discussions in the issue.',
resolver: Resolvers::UserDiscussionsCountResolver
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 399dcc8e03d..8cc600fc68e 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -75,8 +75,12 @@ module Types
null: false, calls_gitaly: true,
method: :diverged_from_target_branch?,
description: 'Indicates if the source branch is behind the target branch.'
- field :downvotes, GraphQL::Types::Int, null: false,
- description: 'Number of downvotes for the merge request.'
+
+ field :downvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of downvotes for the merge request.',
+ resolver: Resolvers::DownVotesCountResolver
+
field :force_remove_source_branch, GraphQL::Types::Boolean, method: :force_remove_source_branch?, null: true,
description: 'Indicates if the project settings will lead to source branch deletion after merge.'
field :in_progress_merge_commit_sha, GraphQL::Types::String, null: true,
@@ -118,8 +122,12 @@ module Types
null: false, calls_gitaly: true,
method: :target_branch_exists?,
description: 'Indicates if the target branch of the merge request exists.'
- field :upvotes, GraphQL::Types::Int, null: false,
- description: 'Number of upvotes for the merge request.'
+
+ field :upvotes, GraphQL::Types::Int,
+ null: false,
+ description: 'Number of upvotes for the merge request.',
+ resolver: Resolvers::UpVotesCountResolver
+
field :user_discussions_count, GraphQL::Types::Int, null: true,
description: 'Number of user discussions in the merge request.',
resolver: Resolvers::UserDiscussionsCountResolver
@@ -150,8 +158,11 @@ module Types
description: 'Human-readable time estimate of the merge request.'
field :human_total_time_spent, GraphQL::Types::String, null: true,
description: 'Human-readable total time reported as spent on the merge request.'
- field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
- description: 'Labels of the merge request.'
+ field :labels, Types::LabelType.connection_type,
+ null: true, complexity: 5,
+ description: 'Labels of the merge request.',
+ resolver: Resolvers::BulkLabelsResolver
+
field :milestone, Types::MilestoneType, null: true,
description: 'Milestone of the merge request.'
field :participants, Types::MergeRequests::ParticipantType.connection_type, null: true, complexity: 15,
diff --git a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
index 3de6296154d..1ba72ae33b5 100644
--- a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
+++ b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
@@ -42,6 +42,9 @@ module Types
value 'POLICIES_DENIED',
value: :policies_denied,
description: 'There are denied policies for the merge request.'
+ value 'EXTERNAL_STATUS_CHECKS',
+ value: :status_checks_must_pass,
+ description: 'Status checks must pass.'
end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index ea833b35085..5ffc1aeacad 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -114,6 +114,7 @@ module Types
mount_mutation Mutations::Ci::Pipeline::Cancel
mount_mutation Mutations::Ci::Pipeline::Destroy
mount_mutation Mutations::Ci::Pipeline::Retry
+ mount_mutation Mutations::Ci::PipelineSchedule::Delete
mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: {
reason: :renamed,
replacement: 'ProjectCiCdSettingsUpdate',
@@ -137,6 +138,8 @@ module Types
mount_mutation Mutations::UserCallouts::Create
mount_mutation Mutations::UserPreferences::Update
mount_mutation Mutations::Packages::Destroy
+ mount_mutation Mutations::Packages::BulkDestroy,
+ extensions: [::Gitlab::Graphql::Limit::FieldCallCount => { limit: 1 }]
mount_mutation Mutations::Packages::DestroyFile
mount_mutation Mutations::Packages::DestroyFiles
mount_mutation Mutations::Packages::Cleanup::Policy::Update
@@ -146,7 +149,6 @@ module Types
mount_mutation Mutations::WorkItems::Delete, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::DeleteTask, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::Update, alpha: { milestone: '15.1' }
- mount_mutation Mutations::WorkItems::UpdateWidgets, alpha: { milestone: '15.1' }
mount_mutation Mutations::WorkItems::UpdateTask, alpha: { milestone: '15.1' }
mount_mutation Mutations::SavedReplies::Create
mount_mutation Mutations::SavedReplies::Update
diff --git a/app/graphql/types/namespace/package_settings_type.rb b/app/graphql/types/namespace/package_settings_type.rb
index 7a0abe619a5..84becba8001 100644
--- a/app/graphql/types/namespace/package_settings_type.rb
+++ b/app/graphql/types/namespace/package_settings_type.rb
@@ -8,9 +8,50 @@ module Types
authorize :admin_package
- field :generic_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
- field :generic_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
- field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
- field :maven_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
+ field :generic_duplicate_exception_regex, Types::UntrustedRegexp,
+ null: true,
+ description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
+ field :generic_duplicates_allowed, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
+ field :maven_duplicate_exception_regex, Types::UntrustedRegexp,
+ null: true,
+ description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
+ field :maven_duplicates_allowed, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
+
+ field :maven_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether Maven package forwarding is allowed for this namespace.'
+ field :npm_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether npm package forwarding is allowed for this namespace.'
+ field :pypi_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether PyPI package forwarding is allowed for this namespace.'
+
+ field :lock_maven_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether Maven package forwarding is locked for all descendent namespaces.'
+ field :lock_npm_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether npm package forwarding is locked for all descendent namespaces.'
+ field :lock_pypi_package_requests_forwarding, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates whether PyPI package forwarding is locked for all descendent namespaces.'
+
+ field :maven_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :maven_package_requests_forwarding_locked?,
+ description: 'Indicates whether Maven package forwarding settings are locked by a parent namespace.'
+ field :npm_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :npm_package_requests_forwarding_locked?,
+ description: 'Indicates whether npm package forwarding settings are locked by a parent namespace.'
+ field :pypi_package_requests_forwarding_locked, GraphQL::Types::Boolean,
+ null: false,
+ method: :pypi_package_requests_forwarding_locked?,
+ description: 'Indicates whether PyPI package forwarding settings are locked by a parent namespace.'
end
end
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index c254460a51f..eef5ce40bde 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -41,7 +41,7 @@ module Types
deprecated: {
reason: :renamed,
replacement: 'internal',
- milestone: '15.3'
+ milestone: '15.5'
}
field :internal, GraphQL::Types::Boolean, null: true,
diff --git a/app/graphql/types/permission_types/ci/pipeline_schedules.rb b/app/graphql/types/permission_types/ci/pipeline_schedules.rb
new file mode 100644
index 00000000000..268ac6096d0
--- /dev/null
+++ b/app/graphql/types/permission_types/ci/pipeline_schedules.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module PermissionTypes
+ module Ci
+ class PipelineSchedules < BasePermissionType
+ graphql_name 'PipelineSchedulePermissions'
+
+ abilities :take_ownership_pipeline_schedule,
+ :update_pipeline_schedule,
+ :admin_pipeline_schedule
+
+ ability_field :play_pipeline_schedule, calls_gitaly: true
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index f43f5c27dac..a41af34ef4c 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -309,6 +309,12 @@ module Types
extras: [:lookahead],
resolver: Resolvers::ProjectPipelinesResolver
+ field :pipeline_schedules,
+ type: Types::Ci::PipelineScheduleType.connection_type,
+ null: true,
+ description: 'Pipeline schedules of the project. This field can only be resolved for one project per request.',
+ resolver: Resolvers::ProjectPipelineSchedulesResolver
+
field :pipeline, Types::Ci::PipelineType,
null: true,
description: 'Build pipeline of the project.',
diff --git a/app/graphql/types/projects/branch_rule_type.rb b/app/graphql/types/projects/branch_rule_type.rb
index 866cff0f439..e7632c17cca 100644
--- a/app/graphql/types/projects/branch_rule_type.rb
+++ b/app/graphql/types/projects/branch_rule_type.rb
@@ -13,6 +13,13 @@ module Types
null: false,
description: 'Branch name, with wildcards, for the branch rules.'
+ field :is_default,
+ type: GraphQL::Types::Boolean,
+ null: false,
+ method: :default_branch?,
+ calls_gitaly: true,
+ description: "Check if this branch rule protects the project's default branch."
+
field :branch_protection,
type: Types::BranchRules::BranchProtectionType,
null: false,
@@ -31,3 +38,5 @@ module Types
end
end
end
+
+Types::Projects::BranchRuleType.prepend_mod
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 78463a1804a..1b39f43659e 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -154,6 +154,12 @@ module Types
null: true,
description: "Whether Gitpod is enabled in application settings."
+ field :jobs,
+ ::Types::Ci::JobType.connection_type,
+ null: true,
+ description: 'All jobs on this GitLab instance.',
+ resolver: ::Resolvers::Ci::AllJobsResolver
+
def design_management
DesignManagementObject.new(nil)
end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index ef701bbfc10..3b8f5c64beb 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -13,6 +13,9 @@ module Types
field :issuable_title_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the title of an issuable is updated.'
+ field :issuable_description_updated, subscription: Subscriptions::IssuableUpdated, null: true,
+ description: 'Triggered when the description of an issuable is updated.'
+
field :issuable_labels_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the labels of an issuable are updated.'
@@ -23,6 +26,11 @@ module Types
subscription: Subscriptions::IssuableUpdated,
null: true,
description: 'Triggered when the reviewers of a merge request are updated.'
+
+ field :merge_request_merge_status_updated,
+ subscription: Subscriptions::IssuableUpdated,
+ null: true,
+ description: 'Triggered when the merge status of a merge request is updated.'
end
end
diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb
index eca8c8d845a..a3943361114 100644
--- a/app/graphql/types/work_items/widget_interface.rb
+++ b/app/graphql/types/work_items/widget_interface.rb
@@ -23,6 +23,9 @@ module Types
ORPHAN_TYPES
end
+ # Whenever a new widget is added make sure to update the spec to avoid N + 1 queries in
+ # spec/requests/api/graphql/project/work_items_spec.rb and add the necessary preloads
+ # in app/graphql/resolvers/work_items_resolver.rb
def self.resolve_type(object, context)
case object
when ::WorkItems::Widgets::Description
diff --git a/app/graphql/types/work_items/widgets/labels_update_input_type.rb b/app/graphql/types/work_items/widgets/labels_update_input_type.rb
new file mode 100644
index 00000000000..d38b8cefa63
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/labels_update_input_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ class LabelsUpdateInputType < BaseInputObject
+ graphql_name 'WorkItemWidgetLabelsUpdateInput'
+
+ argument :add_label_ids, [Types::GlobalIDType[::Label]],
+ required: false,
+ description: 'Global IDs of labels to be added to the work item.',
+ prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
+ argument :remove_label_ids, [Types::GlobalIDType[::Label]],
+ required: false,
+ description: 'Global IDs of labels to be removed from the work item.',
+ prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
+ end
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a75c1b16145..32af1599bd1 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -313,7 +313,6 @@ module ApplicationHelper
class_names = []
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
class_names << 'epic-boards-page gl-overflow-auto' if current_controller?(:epic_boards)
- class_names << 'environment-logs-page' if current_controller?(:logs)
class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << system_message_class
class_names << marketing_header_experiment_class
@@ -428,7 +427,7 @@ module ApplicationHelper
milestones: milestones_project_autocomplete_sources_path(object),
commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
snippets: snippets_project_autocomplete_sources_path(object),
- contacts: contacts_project_autocomplete_sources_path(object)
+ contacts: contacts_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id])
}
end
end
@@ -448,6 +447,10 @@ module ApplicationHelper
form_for(record, *(args << options.merge({ builder: ::Gitlab::FormBuilders::GitlabUiFormBuilder })), &block)
end
+ def gitlab_ui_form_with(**args, &block)
+ form_with(**args.merge({ builder: ::Gitlab::FormBuilders::GitlabUiFormBuilder }), &block)
+ end
+
private
def appearance
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index ddc682bc08a..21b18203677 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -441,7 +441,8 @@ module ApplicationSettingsHelper
:group_runner_token_expiration_interval,
:project_runner_token_expiration_interval,
:pipeline_limit_per_project_user_sha,
- :invitation_flow_enforcement
+ :invitation_flow_enforcement,
+ :can_create_group
].tap do |settings|
next if Gitlab.com?
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index f98e70e41d8..db6cf27566f 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -2,18 +2,15 @@
module BoardsHelper
def board
- @board ||= @board || @boards.first
+ @board
end
def board_data
{
- boards_endpoint: @boards_endpoint,
- lists_endpoint: board_lists_path(board),
board_id: board.id,
disabled: board.disabled_for?(current_user).to_s,
root_path: root_path,
full_path: full_path,
- bulk_update_path: @bulk_issues_path,
can_update: can_update?.to_s,
can_admin_list: can_admin_list?.to_s,
can_admin_board: can_admin_board?.to_s,
@@ -94,14 +91,6 @@ module BoardsHelper
!multiple_boards_available? && current_board_parent.boards.size > 1
end
- def current_board_path(board)
- @current_board_path ||= if board.group_board?
- group_board_path(current_board_parent, board)
- else
- project_board_path(current_board_parent, board)
- end
- end
-
def current_board_parent
@current_board_parent ||= @group || @project
end
@@ -121,18 +110,6 @@ module BoardsHelper
def can_admin_board?
can?(current_user, :admin_issue_board, current_board_parent)
end
-
- def can_admin_issue?
- can?(current_user, :admin_issue, current_board_parent)
- end
-
- def serializer
- CurrentBoardSerializer.new
- end
-
- def current_board_json
- serializer.represent(board).as_json
- end
end
BoardsHelper.prepend_mod_with('BoardsHelper')
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index d00301678dd..99a92ba9b59 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -11,7 +11,6 @@ module Ci
def js_pipeline_editor_data(project)
initial_branch = params[:branch_name]
latest_commit = project.repository.commit(initial_branch) || project.commit
- commit_sha = latest_commit ? latest_commit.sha : ''
total_branches = project.repository_exists? ? project.repository.branch_count : 0
{
@@ -27,17 +26,26 @@ module Ci
"lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
"needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
"new-merge-request-path" => namespace_project_new_merge_request_path,
- "pipeline_etag" => latest_commit ? graphql_etag_pipeline_sha_path(commit_sha) : '',
+ "pipeline_etag" => latest_commit ? graphql_etag_pipeline_sha_path(latest_commit.sha) : '',
"pipeline-page-path" => project_pipelines_path(project),
"project-path" => project.path,
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
"total-branches" => total_branches,
+ "uses-external-config" => uses_external_config?(project) ? 'true' : 'false',
"validate-tab-illustration-path" => image_path('illustrations/project-run-CICD-pipelines-sm.svg'),
"yml-help-page-path" => help_page_path('ci/yaml/index')
}
end
+
+ private
+
+ def uses_external_config?(project)
+ ci_config_source = Gitlab::Ci::ProjectConfig.new(project: project, sha: nil).source
+
+ [:external_project_source, :remote_source].include?(ci_config_source)
+ end
end
end
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index a67771116b9..c93c8dd8d76 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -69,7 +69,8 @@ module Ci
end
def has_pipeline_badges?(pipeline)
- pipeline.child? ||
+ pipeline.schedule? ||
+ pipeline.child? ||
pipeline.latest? ||
pipeline.merge_train_pipeline? ||
pipeline.has_yaml_errors? ||
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index e955ad4cfda..9ecf780f55b 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -42,7 +42,8 @@ module CompareHelper
source_project_refs_path: refs_project_path(project),
target_project_refs_path: refs_project_path(@target_project),
params_from: params[:from],
- params_to: params[:to]
+ params_to: params[:to],
+ straight: params[:straight]
}.tap do |data|
data[:projects_from] = target_projects(project).map do |target_project|
{ id: target_project.id, name: target_project.full_path }
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index bcddb889cf4..b717cbcc312 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -16,6 +16,54 @@ module EventsHelper
'joined' => 'users'
}.freeze
+ def localized_action_name_map
+ {
+ accepted: s_('Event|accepted'),
+ approved: s_('Event|approved'),
+ closed: s_('Event|closed'),
+ 'commented on': s_('Event|commented on'),
+ created: s_('Event|created'),
+ destroyed: s_('Event|destroyed'),
+ joined: s_('Event|joined'),
+ left: s_('Event|left'),
+ opened: s_('Event|opened'),
+ updated: s_('Event|updated'),
+ 'removed due to membership expiration from': s_('Event|removed due to membership expiration from')
+ }.merge(localized_push_action_name_map,
+ localized_created_project_action_name_map,
+ localized_design_action_names
+ ).freeze
+ end
+
+ def localized_push_action_name_map
+ {
+ 'pushed new': s_('Event|pushed new'),
+ deleted: s_('Event|deleted'),
+ 'pushed to': s_('Event|pushed to')
+ }.freeze
+ end
+
+ def localized_created_project_action_name_map
+ {
+ created: s_('Event|created'),
+ imported: s_('Event|imported')
+ }.freeze
+ end
+
+ def localized_design_action_names
+ {
+ added: s_('Event|added'),
+ updated: s_('Event|updated'),
+ removed: s_('Event|removed')
+ }.freeze
+ end
+
+ def localized_action_name(event)
+ action_name = event.action_name
+ # The action fallback is used to cover the types were not included in the maps.
+ localized_action_name_map[action_name.to_sym] || action_name
+ end
+
def link_to_author(event, self_added: false)
author = event.author
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index f2e24f54391..9e42aeea9ce 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -39,13 +39,13 @@ module FormHelper
end
end
- def dropdown_max_select(data)
- return data[:'max-select'] unless Feature.enabled?(:limit_reviewer_and_assignee_size)
+ def dropdown_max_select(data, feature_flag)
+ return data[:'max-select'] unless Feature.enabled?(feature_flag)
- if data[:'max-select'] && data[:'max-select'] < MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ if data[:'max-select'] && data[:'max-select'] < ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
data[:'max-select']
else
- MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
end
end
@@ -117,10 +117,16 @@ module FormHelper
dropdown_data = multiple_reviewers_dropdown_options(dropdown_data)
end
+ dropdown_data[:data].merge!(reviewers_dropdown_options_for_suggested_reviewers)
dropdown_data
end
# Overwritten
+ def reviewers_dropdown_options_for_suggested_reviewers
+ {}
+ end
+
+ # Overwritten
def issue_supports_multiple_assignees?
false
end
@@ -156,7 +162,12 @@ module FormHelper
new_options[:title] = _('Select assignee(s)')
new_options[:data][:'dropdown-header'] = 'Assignee(s)'
- new_options[:data].delete(:'max-select')
+
+ if Feature.enabled?(:limit_assignees_per_issuable)
+ new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ else
+ new_options[:data].delete(:'max-select')
+ end
new_options
end
@@ -168,7 +179,7 @@ module FormHelper
new_options[:data][:'dropdown-header'] = _('Reviewer(s)')
if Feature.enabled?(:limit_reviewer_and_assignee_size)
- new_options[:data][:'max-select'] = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
else
new_options[:data].delete(:'max-select')
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index f77bd6621f9..6b00c213875 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -126,8 +126,8 @@ module GroupsHelper
group.root? && current_user.can?(:admin_setting_to_allow_project_access_token_creation, group)
end
- def show_thanks_for_purchase_alert?
- params.key?(:purchased_quantity) && params[:purchased_quantity].to_i > 0
+ def show_thanks_for_purchase_alert?(quantity)
+ quantity.to_i > 0
end
def project_list_sort_by
@@ -177,7 +177,8 @@ module GroupsHelper
subgroups_and_projects_endpoint: group_children_path(group, format: :json),
shared_projects_endpoint: group_shared_projects_path(group, format: :json),
archived_projects_endpoint: group_children_path(group, format: :json, archived: 'only'),
- current_group_visibility: group.visibility
+ current_group_visibility: group.visibility,
+ initial_sort: project_list_sort_by
}.merge(subgroups_and_projects_list_app_data(group))
end
diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb
index 1e50033e0e0..e050ccc0e40 100644
--- a/app/helpers/hooks_helper.rb
+++ b/app/helpers/hooks_helper.rb
@@ -1,6 +1,13 @@
# frozen_string_literal: true
module HooksHelper
+ def webhook_form_data(hook)
+ {
+ url: hook.url,
+ url_variables: nil
+ }
+ end
+
def link_to_test_hook(hook, trigger)
path = test_hook_path(hook, trigger)
trigger_human_name = trigger.to_s.tr('_', ' ').camelize
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index ec1327cf7ae..5b3ca25b5af 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -3,6 +3,32 @@
module IdeHelper
def ide_data
{
+ 'can-use-new-web-ide' => can_use_new_web_ide?.to_s,
+ 'use-new-web-ide' => use_new_web_ide?.to_s,
+ 'user-preferences-path' => profile_preferences_path,
+ 'branch-name' => @branch
+ }.merge(use_new_web_ide? ? new_ide_data : legacy_ide_data)
+ end
+
+ def can_use_new_web_ide?
+ Feature.enabled?(:vscode_web_ide, current_user)
+ end
+
+ def use_new_web_ide?
+ can_use_new_web_ide? && !current_user.use_legacy_web_ide
+ end
+
+ private
+
+ def new_ide_data
+ {
+ 'project-path' => @project&.path_with_namespace,
+ 'csp-nonce' => content_security_policy_nonce
+ }
+ end
+
+ def legacy_ide_data
+ {
'empty-state-svg-path' => image_path('illustrations/multi_file_editor_empty.svg'),
'no-changes-state-svg-path' => image_path('illustrations/multi-editor_no_changes_empty.svg'),
'committed-state-svg-path' => image_path('illustrations/multi-editor_all_changes_committed_empty.svg'),
@@ -13,7 +39,6 @@ module IdeHelper
'clientside-preview-enabled': Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s,
'render-whitespace-in-code': current_user.render_whitespace_in_code.to_s,
'codesandbox-bundler-url': Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url,
- 'branch-name' => @branch,
'default-branch' => @project && @project.default_branch,
'file-path' => @path,
'merge-request' => @merge_request,
@@ -24,13 +49,10 @@ module IdeHelper
'web-terminal-svg-path' => image_path('illustrations/web-ide_promotion.svg'),
'web-terminal-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'interactive-web-terminals-for-the-web-ide'),
'web-terminal-config-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'web-ide-configuration-file'),
- 'web-terminal-runners-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'runner-configuration'),
- 'csp-nonce' => content_security_policy_nonce
+ 'web-terminal-runners-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'runner-configuration')
}
end
- private
-
def convert_to_project_entity_json(project)
return unless project
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 96daf398243..2804a58da9e 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -157,9 +157,9 @@ module IssuablesHelper
if issuable.respond_to?(:work_item_type) && WorkItems::Type::WI_TYPES_WITH_CREATED_HEADER.include?(issuable.work_item_type.base_type)
output << content_tag(:span, sprite_icon("#{issuable.work_item_type.icon_name}", css_class: 'gl-icon gl-vertical-align-middle gl-text-gray-500'), class: 'gl-mr-2', aria: { hidden: 'true' })
- output << s_('IssuableStatus|%{wi_type} created %{created_at} by ').html_safe % { wi_type: issuable.issue_type.capitalize, created_at: time_ago_with_tooltip(issuable.created_at) }
+ output << content_tag(:span, s_('IssuableStatus|%{wi_type} created %{created_at} by ').html_safe % { wi_type: issuable.issue_type.capitalize, created_at: time_ago_with_tooltip(issuable.created_at) }, class: 'gl-mr-2' )
else
- output << s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) }
+ output << content_tag(:span, s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) }, class: 'gl-mr-2' )
end
if issuable.is_a?(Issue) && issuable.service_desk_reply_to
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index a157b1b7b21..115cdd432e3 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -3,6 +3,10 @@
module IssuesHelper
include Issues::IssueTypeHelpers
+ def can_admin_issue?
+ can?(current_user, :admin_issue, @group || @project)
+ end
+
def issue_css_classes(issue)
classes = ["issue"]
classes << "closed" if issue.closed?
@@ -11,6 +15,11 @@ module IssuesHelper
classes.join(' ')
end
+ def show_timeline_view_toggle?(issue)
+ # Overridden in EE
+ false
+ end
+
def issue_manual_ordering_class
is_sorting_by_relative_position = @sort == 'relative_position'
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index fc558958ca3..866399f3021 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -12,22 +12,6 @@ module MarkupHelper
# https://gitlab.com/gitlab-org/gitlab/-/issues/365358
RENDER_TIMEOUT = 5.seconds
- def plain?(filename)
- Gitlab::MarkupHelper.plain?(filename)
- end
-
- def markup?(filename)
- Gitlab::MarkupHelper.markup?(filename)
- end
-
- def gitlab_markdown?(filename)
- Gitlab::MarkupHelper.gitlab_markdown?(filename)
- end
-
- def asciidoc?(filename)
- Gitlab::MarkupHelper.asciidoc?(filename)
- end
-
# Use this in places where you would normally use link_to(gfm(...), ...).
def link_to_markdown(body, url, html_options = {})
return '' if body.blank?
@@ -88,8 +72,10 @@ module MarkupHelper
tags = %w(a gl-emoji b strong i em pre code p span)
tags << 'img' if options[:allow_images]
- text = truncate_visible(md, max_chars || md.length)
- text = prepare_for_rendering(text, markdown_field_render_context(object, attribute, options))
+ context = markdown_field_render_context(object, attribute, options)
+ context.reverse_merge!(truncate_visible_max_chars: max_chars || md.length)
+
+ text = prepare_for_rendering(md, context)
text = sanitize(
text,
tags: tags,
@@ -146,11 +132,11 @@ module MarkupHelper
return '' unless text.present?
markup = proc do
- if gitlab_markdown?(file_name)
+ if Gitlab::MarkupHelper.gitlab_markdown?(file_name)
markdown_unsafe(text, context)
- elsif asciidoc?(file_name)
+ elsif Gitlab::MarkupHelper.asciidoc?(file_name)
asciidoc_unsafe(text, context)
- elsif plain?(file_name)
+ elsif Gitlab::MarkupHelper.plain?(file_name)
plain_unsafe(text)
else
other_markup_unsafe(file_name, text, context)
@@ -207,55 +193,6 @@ module MarkupHelper
{ project: wiki.container }
end
- # Return +text+, truncated to +max_chars+ characters, excluding any HTML
- # tags.
- def truncate_visible(text, max_chars)
- doc = Nokogiri::HTML.fragment(text)
- content_length = 0
- truncated = false
-
- doc.traverse do |node|
- if node.text? || node.content.empty?
- if truncated
- node.remove
- next
- end
-
- # Handle line breaks within a node
- if node.content.strip.lines.length > 1
- node.content = "#{node.content.lines.first.chomp}..."
- truncated = true
- end
-
- num_remaining = max_chars - content_length
- if node.content.length > num_remaining
- node.content = node.content.truncate(num_remaining)
- truncated = true
- end
-
- content_length += node.content.length
- end
-
- truncated = truncate_if_block(node, truncated)
- end
-
- doc.to_html
- end
-
- # Used by #truncate_visible. If +node+ is the first block element, and the
- # text hasn't already been truncated, then append "..." to the node contents
- # and return true. Otherwise return false.
- def truncate_if_block(node, truncated)
- return true if truncated
-
- if node.element? && (node.description&.block? || node.matches?('pre > code > .line'))
- node.inner_html = "#{node.inner_html}..." if node.next_sibling
- true
- else
- truncated
- end
- end
-
def strip_empty_link_tags(text)
scrubber = Loofah::Scrubber.new do |node|
node.remove if node.name == 'a' && node.children.empty?
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
new file mode 100644
index 00000000000..272a3970bc2
--- /dev/null
+++ b/app/helpers/milestones_helper.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module MilestonesHelper
+ def milestone_header_class(primary, issuables)
+ header_color = milestone_header_color(primary: primary)
+ header_border = milestone_header_border(issuables)
+
+ "#{header_color} #{header_border} gl-display-flex"
+ end
+
+ def milestone_counter_class(primary)
+ primary ? 'gl-text-white' : 'gl-text-gray-500'
+ end
+
+ private
+
+ def milestone_header_color(primary: false)
+ return '' unless primary
+
+ 'gl-bg-blue-500 gl-text-white'
+ end
+
+ def milestone_header_border(issuables)
+ issuables.empty? ? 'gl-border-bottom-0 gl-rounded-base' : ''
+ end
+end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 4d6ab7b8bf9..0cf2c5cea4c 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -49,7 +49,7 @@ module NavHelper
end
def page_has_markdown?
- current_path?('merge_requests#show') ||
+ current_path?('projects/merge_requests#show') ||
current_path?('projects/merge_requests/conflicts#show') ||
current_path?('issues#show') ||
current_path?('milestones#show') ||
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index e760fad7be9..cddcdf77710 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -471,8 +471,24 @@ module ProjectsHelper
}
end
+ def localized_project_human_access(access)
+ localized_access_names[access] || Gitlab::Access.human_access(access)
+ end
+
private
+ def localized_access_names
+ {
+ Gitlab::Access::NO_ACCESS => _('No access'),
+ Gitlab::Access::MINIMAL_ACCESS => _("Minimal Access"),
+ Gitlab::Access::GUEST => _('Guest'),
+ Gitlab::Access::REPORTER => _('Reporter'),
+ Gitlab::Access::DEVELOPER => _('Developer'),
+ Gitlab::Access::MAINTAINER => _('Maintainer'),
+ Gitlab::Access::OWNER => _('Owner')
+ }
+ end
+
def configure_oauth_import_message(provider, help_url)
str = if current_user.admin?
'ImportProjects|To enable importing projects from %{provider}, as administrator you need to configure %{link_start}OAuth integration%{link_end}'
diff --git a/app/helpers/recaptcha_helper.rb b/app/helpers/recaptcha_helper.rb
index 5b17ab4b815..59f0dc8f819 100644
--- a/app/helpers/recaptcha_helper.rb
+++ b/app/helpers/recaptcha_helper.rb
@@ -2,9 +2,27 @@
module RecaptchaHelper
def recaptcha_enabled?
+ return false if gitlab_qa?
+
!!Gitlab::Recaptcha.enabled?
end
alias_method :show_recaptcha_sign_up?, :recaptcha_enabled?
+
+ def recaptcha_enabled_on_login?
+ return false if gitlab_qa?
+
+ Gitlab::Recaptcha.enabled_on_login?
+ end
+
+ private
+
+ def gitlab_qa?
+ return false unless Gitlab.com?
+ return false unless request.user_agent.present?
+ return false unless Gitlab::Environment.qa_user_agent.present?
+
+ ActiveSupport::SecurityUtils.secure_compare(request.user_agent, Gitlab::Environment.qa_user_agent)
+ end
end
RecaptchaHelper.prepend_mod
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index 50089c7edab..e0db40ebaee 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -82,7 +82,7 @@ module ReleasesHelper
markdown_docs_path: help_page_path('user/markdown'),
release_assets_docs_path: releases_help_page_path(anchor: 'release-assets'),
manage_milestones_path: project_milestones_path(@project),
- new_milestone_path: new_project_milestone_path(@project),
+ new_milestone_path: new_project_milestone_path(@project, redirect_path: 'new_release'),
edit_release_docs_path: releases_help_page_path(anchor: 'edit-a-release'),
upcoming_release_docs_path: releases_help_page_path(anchor: 'upcoming-releases')
}
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index b16235893ae..f2b88287277 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -380,6 +380,40 @@ module SearchHelper
end
end
+ def search_filter_link_json(scope, label, data, search)
+ scope_name = scope.to_s
+ search_params = params.merge(search).merge({ scope: scope_name }).permit(SEARCH_GENERIC_PARAMS)
+ active_scope = @scope == scope_name
+
+ result = { label: label, scope: scope_name, data: data, link: search_path(search_params), active: active_scope }
+ result[:count] = @search_results.formatted_count(scope_name) if active_scope && !@timeout
+ result[:count_link] = search_count_path(search_params) unless active_scope
+
+ result
+ end
+
+ # search page scope navigation
+ def search_navigation
+ {
+ projects: { label: _("Projects"), data: { qa_selector: 'projects_tab' }, condition: @project.nil? },
+ blobs: { label: _("Code"), data: { qa_selector: 'code_tab' }, condition: project_search_tabs?(:blobs) || search_service.show_elasticsearch_tabs? || feature_flag_tab_enabled?(:global_search_code_tab) },
+ issues: { label: _("Issues"), condition: project_search_tabs?(:issues) || feature_flag_tab_enabled?(:global_search_issues_tab) },
+ merge_requests: { label: _("Merge requests"), condition: project_search_tabs?(:merge_requests) || feature_flag_tab_enabled?(:global_search_merge_requests_tab) },
+ wiki_blobs: { label: _("Wiki"), condition: project_search_tabs?(:wiki) || search_service.show_elasticsearch_tabs? },
+ commits: { label: _("Commits"), condition: project_search_tabs?(:commits) || (search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_commits_tab)) },
+ notes: { label: _("Comments"), condition: project_search_tabs?(:notes) || search_service.show_elasticsearch_tabs? },
+ milestones: { label: _("Milestones"), condition: project_search_tabs?(:milestones) || @project.nil? },
+ users: { label: _("Users"), condition: show_user_search_tab? },
+ snippet_titles: { label: _("Titles and Descriptions"), search: { snippets: true, group_id: nil, project_id: nil }, condition: @show_snippets.present? && @project.nil? }
+ }
+ end
+
+ def search_navigation_json
+ search_navigation.each_with_object({}) do |(key, value), hash|
+ hash[key] = search_filter_link_json(key, value[:label], value[:data], value[:search]) if value[:condition]
+ end.to_json
+ end
+
def search_filter_input_options(type, placeholder = _('Search or filter results...'))
opts =
{
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index 88aff31af54..14ee6007a43 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -39,11 +39,6 @@ module SelectsHelper
select2_tag(id, opts)
end
- def namespace_select_tag(id, opts = {})
- opts[:class] = [*opts[:class], 'ajax-namespace-select'].join(' ')
- select2_tag(id, opts)
- end
-
def project_select_tag(id, opts = {})
opts[:class] = [*opts[:class], 'ajax-project-select'].join(' ')
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
index 129180d1ccf..56138ba95c2 100644
--- a/app/helpers/sessions_helper.rb
+++ b/app/helpers/sessions_helper.rb
@@ -49,6 +49,6 @@ module SessionsHelper
match = regex.match(email)
return email unless match
- match[1] + '*' * match[2].length + match[3] + '*' * match[4].length + match[5]
+ match[1] + '*' * (match[2] || '').length + match[3] + '*' * (match[4] || '').length + match[5]
end
end
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index ecedbfb2a4f..cb6f60ab79b 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -8,12 +8,12 @@ module TimeHelper
if minutes >= 1
if seconds % 60 == 0
- pluralize(minutes, "minute")
+ n_('%d minute', '%d minutes', minutes) % minutes
else
- [pluralize(minutes, "minute"), pluralize(seconds, "second")].to_sentence
+ [n_('%d minute', '%d minutes', minutes) % minutes, n_('%d second', '%d seconds', seconds) % seconds].to_sentence
end
else
- pluralize(seconds, "second")
+ n_('%d second', '%d seconds', seconds) % seconds
end
end
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
index 11d09a79dcf..e0e6229bc6d 100644
--- a/app/helpers/timeboxes_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -77,14 +77,10 @@ module TimeboxesHelper
end
def milestone_progress_bar(milestone)
- options = {
- class: 'progress-bar bg-success',
- style: "width: #{milestone.percent_complete}%;"
- }
-
- content_tag :div, class: 'progress' do
- content_tag :div, nil, options
- end
+ render Pajamas::ProgressComponent.new(
+ value: milestone.percent_complete,
+ variant: :success
+ )
end
def milestone_time_for(date, date_type)
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index ecf29c41100..520cde9ecee 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -130,12 +130,12 @@ module TodosHelper
def todos_filter_params
{
- state: params[:state],
+ state: params[:state].presence,
project_id: params[:project_id],
author_id: params[:author_id],
type: params[:type],
action_id: params[:action_id]
- }
+ }.compact
end
def todos_filter_empty?
@@ -168,22 +168,22 @@ module TodosHelper
def todo_actions_options
[
- { id: '', text: 'Any Action' },
- { id: Todo::ASSIGNED, text: 'Assigned' },
- { id: Todo::REVIEW_REQUESTED, text: 'Review requested' },
- { id: Todo::MENTIONED, text: 'Mentioned' },
- { id: Todo::MARKED, text: 'Added' },
- { id: Todo::BUILD_FAILED, text: 'Pipelines' }
+ { id: '', text: s_('Todos|Any Action') },
+ { id: Todo::ASSIGNED, text: s_('Todos|Assigned') },
+ { id: Todo::REVIEW_REQUESTED, text: s_('Todos|Review requested') },
+ { id: Todo::MENTIONED, text: s_('Todos|Mentioned') },
+ { id: Todo::MARKED, text: s_('Todos|Added') },
+ { id: Todo::BUILD_FAILED, text: s_('Todos|Pipelines') }
]
end
def todo_types_options
[
- { id: '', text: 'Any Type' },
- { id: 'Issue', text: 'Issue' },
- { id: 'MergeRequest', text: 'Merge request' },
- { id: 'DesignManagement::Design', text: 'Design' },
- { id: 'AlertManagement::Alert', text: 'Alert' }
+ { id: '', text: s_('Todos|Any Type') },
+ { id: 'Issue', text: s_('Todos|Issue') },
+ { id: 'MergeRequest', text: s_('Todos|Merge request') },
+ { id: 'DesignManagement::Design', text: s_('Todos|Design') },
+ { id: 'AlertManagement::Alert', text: s_('Todos|Alert') }
]
end
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
index d8baa185370..a9fd219bbac 100644
--- a/app/helpers/users/callouts_helper.rb
+++ b/app/helpers/users/callouts_helper.rb
@@ -76,8 +76,8 @@ module Users
user_dismissed?(WEB_HOOK_DISABLED, last_failure, project: project)
end
- def show_merge_request_settings_callout?
- !user_dismissed?(MERGE_REQUEST_SETTINGS_MOVED_CALLOUT)
+ def show_merge_request_settings_callout?(project)
+ !user_dismissed?(MERGE_REQUEST_SETTINGS_MOVED_CALLOUT) && project.merge_requests_enabled?
end
def ultimate_feature_removal_banner_dismissed?(project)
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 271fa47dd97..4f345fdeb9c 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -287,6 +287,21 @@ module UsersHelper
}
]
end
+
+ # the keys should match the user model defined roles in app/models/user.rb
+ def localized_user_roles
+ {
+ software_developer: s_('User|Software Developer'),
+ development_team_lead: s_('User|Development Team Lead'),
+ devops_engineer: s_('User|Devops Engineer'),
+ systems_administrator: s_('User|Systems Administrator'),
+ security_analyst: s_('User|Security Analyst'),
+ data_analyst: s_('User|Data Analyst'),
+ product_manager: s_('User|Product Manager'),
+ product_designer: s_('User|Product Designer'),
+ other: s_('User|Other')
+ }.with_indifferent_access.freeze
+ end
end
UsersHelper.prepend_mod_with('UsersHelper')
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index d6ffd3deafe..017a1861905 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -59,14 +59,16 @@ module WikiHelper
end
end
- def wiki_sort_controls(wiki, sort, direction)
- sort ||= Wiki::TITLE_ORDER
+ def wiki_sort_controls(wiki, direction)
link_class = 'gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
reversed_direction = direction == 'desc' ? 'asc' : 'desc'
icon_class = direction == 'desc' ? 'highest' : 'lowest'
+ title = direction == 'desc' ? _('Sort direction: Descending') : _('Sort direction: Ascending')
- link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction),
- type: 'button', class: link_class, title: _('Sort direction')) do
+ link_options = { action: :pages, direction: reversed_direction }
+
+ link_to(wiki_path(wiki, **link_options),
+ type: 'button', class: link_class, title: title) do
sprite_icon("sort-#{icon_class}")
end
end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index 8fe471a48f2..65ea90d0b5d 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -94,6 +94,18 @@ module Emails
end
end
+ def access_token_revoked_email(user, token_name)
+ return unless user&.active?
+
+ @user = user
+ @token_name = token_name
+ @target_url = profile_personal_access_tokens_url
+
+ Gitlab::I18n.with_locale(@user.preferred_language) do
+ mail_with_locale(to: @user.notification_email_or_default, subject: subject(_("A personal access token has been revoked")))
+ end
+ end
+
def ssh_key_expired_email(user, fingerprints)
return unless user&.active?
@@ -131,6 +143,18 @@ module Emails
end
end
+ def two_factor_otp_attempt_failed_email(user, ip, time = Time.current)
+ @user = user
+ @ip = ip
+ @time = time
+
+ Gitlab::I18n.with_locale(@user.preferred_language) do
+ email_with_layout(
+ to: @user.notification_email_or_default,
+ subject: subject(_("Attempted sign in to %{host} using a wrong two-factor authentication code") % { host: Gitlab.config.gitlab.host }))
+ end
+ end
+
def disabled_two_factor_email(user)
return unless user
diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb
index c5e60ecaadd..206518e582b 100644
--- a/app/mailers/previews/notify_preview.rb
+++ b/app/mailers/previews/notify_preview.rb
@@ -181,6 +181,10 @@ class NotifyPreview < ActionMailer::Preview
Notify.unknown_sign_in_email(user, '127.0.0.1', Time.current).message
end
+ def two_factor_otp_attempt_failed_email
+ Notify.two_factor_otp_attempt_failed_email(user, '127.0.0.1').message
+ end
+
def new_email_address_added_email
Notify.new_email_address_added_email(user, 'someone@gitlab.com').message
end
@@ -209,6 +213,18 @@ class NotifyPreview < ActionMailer::Preview
Notify.verification_instructions_email(user.id, token: '123456', expires_in: 60).message
end
+ def project_was_exported_email
+ Notify.project_was_exported_email(user, project).message
+ end
+
+ def request_review_merge_request_email
+ Notify.request_review_merge_request_email(user.id, merge_request.id, user.id).message
+ end
+
+ def project_was_moved_email
+ Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab").message
+ end
+
private
def project
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index edb9a2053b1..361b1a8dca9 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -120,7 +120,7 @@ class ApplicationSetting < ApplicationRecord
if: :help_page_support_url_column_exists?
validates :help_page_documentation_base_url,
- length: { maximum: 255, message: _("is too long (maximum is %{count} characters)") },
+ length: { maximum: 255, message: N_("is too long (maximum is %{count} characters)") },
allow_blank: true,
addressable_url: true
@@ -148,7 +148,7 @@ class ApplicationSetting < ApplicationRecord
if: :akismet_enabled
validates :spam_check_api_key,
- length: { maximum: 2000, message: _('is too long (maximum is %{count} characters)') },
+ length: { maximum: 2000, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true
validates :unique_ips_limit_per_user,
@@ -228,7 +228,7 @@ class ApplicationSetting < ApplicationRecord
validates :default_artifacts_expire_in, presence: true, duration: true
validates :container_expiration_policies_enable_historic_entries,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :container_registry_token_expire_delay,
presence: true,
@@ -320,8 +320,8 @@ class ApplicationSetting < ApplicationRecord
validates :personal_access_token_prefix,
format: { with: %r{\A[a-zA-Z0-9_+=/@:.-]+\z},
- message: _("can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'") },
- length: { maximum: 20, message: _('is too long (maximum is %{count} characters)') },
+ message: N_("can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'") },
+ length: { maximum: 20, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true
validates :commit_email_hostname, format: { with: /\A[^@]+\z/ }
@@ -369,7 +369,7 @@ class ApplicationSetting < ApplicationRecord
validates :email_restrictions, untrusted_regexp: true
- validates :hashed_storage_enabled, inclusion: { in: [true], message: _("Hashed storage can't be disabled anymore for new projects") }
+ validates :hashed_storage_enabled, inclusion: { in: [true], message: N_("Hashed storage can't be disabled anymore for new projects") }
validates :container_registry_delete_tags_service_timeout,
:container_registry_cleanup_tags_service_max_list_size,
@@ -377,7 +377,7 @@ class ApplicationSetting < ApplicationRecord
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :container_registry_expiration_policies_caching,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :container_registry_import_max_tags_count,
:container_registry_import_max_retries,
@@ -404,11 +404,18 @@ class ApplicationSetting < ApplicationRecord
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :invisible_captcha_enabled,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
- validates :invitation_flow_enforcement,
+ validates :invitation_flow_enforcement, :can_create_group,
allow_nil: false,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
+
+ # rubocop:disable Cop/StaticTranslationDefinition
+ validates :deactivate_dormant_users_period,
+ presence: true,
+ numericality: { only_integer: true, greater_than_or_equal_to: 90, message: _("'%{value}' days of inactivity must be greater than or equal to 90") },
+ if: :deactivate_dormant_users?
+ # rubocop:enable Cop/StaticTranslationDefinition
Gitlab::SSHPublicKey.supported_types.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
@@ -513,11 +520,11 @@ class ApplicationSetting < ApplicationRecord
rsa_key: true, allow_nil: true
validates :rate_limiting_response_text,
- length: { maximum: 255, message: _('is too long (maximum is %{count} characters)') },
+ length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true
validates :jira_connect_application_key,
- length: { maximum: 255, message: _('is too long (maximum is %{count} characters)') },
+ length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true
with_options(presence: true, numericality: { only_integer: true, greater_than: 0 }) do
@@ -561,7 +568,7 @@ class ApplicationSetting < ApplicationRecord
allow_nil: false
validates :admin_mode,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :external_pipeline_validation_service_url,
addressable_url: true, allow_blank: true
@@ -574,7 +581,7 @@ class ApplicationSetting < ApplicationRecord
inclusion: { in: ApplicationSetting.whats_new_variants.keys }
validates :floc_enabled,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
enum sidekiq_job_limiter_mode: {
Gitlab::SidekiqMiddleware::SizeLimiter::Validator::TRACK_MODE => 0,
@@ -589,7 +596,7 @@ class ApplicationSetting < ApplicationRecord
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :sentry_enabled,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :sentry_dsn,
addressable_url: true, presence: true, length: { maximum: 255 },
if: :sentry_enabled?
@@ -601,7 +608,7 @@ class ApplicationSetting < ApplicationRecord
if: :sentry_enabled?
validates :error_tracking_enabled,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :error_tracking_api_url,
presence: true,
addressable_url: true,
@@ -667,9 +674,10 @@ class ApplicationSetting < ApplicationRecord
attr_encrypted :arkose_labs_public_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
attr_encrypted :arkose_labs_private_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
attr_encrypted :cube_api_key, encryption_options_base_32_aes_256_gcm
+ attr_encrypted :jitsu_administrator_password, encryption_options_base_32_aes_256_gcm
validates :disable_feed_token,
- inclusion: { in: [true, false], message: _('must be a boolean value') }
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
before_validation :ensure_uuid!
before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed?
@@ -791,6 +799,10 @@ class ApplicationSetting < ApplicationRecord
::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
end
+ def personal_access_tokens_disabled?
+ false
+ end
+
private
def parsed_grafana_url
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 4d377855dea..dee4bd07fd9 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -240,7 +240,8 @@ module ApplicationSettingImplementation
search_rate_limit: 30,
search_rate_limit_unauthenticated: 10,
users_get_by_id_limit: 300,
- users_get_by_id_limit_allowlist: []
+ users_get_by_id_limit_allowlist: [],
+ can_create_group: true
}
end
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb
index 5430575ace7..e9530a80d9f 100644
--- a/app/models/award_emoji.rb
+++ b/app/models/award_emoji.rb
@@ -73,4 +73,8 @@ class AwardEmoji < ApplicationRecord
awardable.expire_etag_cache if awardable.is_a?(Note)
awardable.try(:update_upvotes_count) if upvote?
end
+
+ def to_ability_name
+ 'emoji'
+ end
end
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index e0a616b5fb4..a2542e669e1 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -116,8 +116,20 @@ class BulkImports::Entity < ApplicationRecord
"/#{pluralized_name}/#{encoded_source_full_path}"
end
+ def base_xid_resource_url_path
+ "/#{pluralized_name}/#{source_xid}"
+ end
+
+ def base_resource_path
+ if source_xid.present?
+ base_xid_resource_url_path
+ else
+ base_resource_url_path
+ end
+ end
+
def export_relations_url_path
- "#{base_resource_url_path}/export_relations"
+ "#{base_resource_path}/export_relations"
end
def relation_download_url_path(relation)
@@ -125,7 +137,7 @@ class BulkImports::Entity < ApplicationRecord
end
def wikis_url_path
- "#{base_resource_url_path}/wikis"
+ "#{base_resource_path}/wikis"
end
def project?
@@ -149,6 +161,13 @@ class BulkImports::Entity < ApplicationRecord
end
def validate_imported_entity_type
+ if project_entity? && !BulkImports::Features.project_migration_enabled?(destination_namespace)
+ errors.add(
+ :base,
+ s_('BulkImport|invalid entity source type')
+ )
+ end
+
if group.present? && project_entity?
errors.add(
:group,
diff --git a/app/models/bulk_imports/export_status.rb b/app/models/bulk_imports/export_status.rb
index 4fea62edb2a..cbd7b189007 100644
--- a/app/models/bulk_imports/export_status.rb
+++ b/app/models/bulk_imports/export_status.rb
@@ -30,14 +30,18 @@ module BulkImports
private
- attr_reader :client, :entity, :relation
+ attr_reader :client, :entity, :relation, :pipeline_tracker
def export_status
strong_memoize(:export_status) do
fetch_export_status&.find { |item| item['relation'] == relation }
+ rescue BulkImports::NetworkError => e
+ raise BulkImports::RetryPipelineError.new(e.message, 2.seconds) if e.retriable?(pipeline_tracker)
+
+ default_error_response(e.message)
+ rescue StandardError => e
+ default_error_response(e.message)
end
- rescue StandardError => e
- { 'status' => Export::FAILED, 'error' => e.message }
end
def fetch_export_status
@@ -47,5 +51,9 @@ module BulkImports
def status_endpoint
File.join(entity.export_relations_url_path, 'status')
end
+
+ def default_error_response(message)
+ { 'status' => Export::FAILED, 'error' => message }
+ end
end
end
diff --git a/app/models/bulk_imports/failure.rb b/app/models/bulk_imports/failure.rb
index a6f7582c3b0..44d16618c77 100644
--- a/app/models/bulk_imports/failure.rb
+++ b/app/models/bulk_imports/failure.rb
@@ -10,4 +10,24 @@ class BulkImports::Failure < ApplicationRecord
optional: false
validates :entity, presence: true
+
+ def relation
+ pipeline_relation || default_relation
+ end
+
+ private
+
+ def pipeline_relation
+ klass = pipeline_class.constantize
+
+ return unless klass.ancestors.include?(BulkImports::Pipeline)
+
+ klass.relation
+ rescue NameError
+ nil
+ end
+
+ def default_relation
+ pipeline_class.demodulize.chomp('Pipeline').underscore
+ end
end
diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb
index fa38b7617d2..357f4629078 100644
--- a/app/models/bulk_imports/tracker.rb
+++ b/app/models/bulk_imports/tracker.rb
@@ -60,6 +60,8 @@ class BulkImports::Tracker < ApplicationRecord
event :retry do
transition started: :enqueued
+ # To avoid errors when retrying a pipeline in case of network errors
+ transition enqueued: :enqueued
end
event :enqueue do
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 4e58f877217..b8511536e32 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -108,10 +108,12 @@ module Ci
validates :ref, presence: true
scope :not_interruptible, -> do
- joins(:metadata).where.not('ci_builds_metadata.id' => Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
+ joins(:metadata)
+ .where.not(Ci::BuildMetadata.table_name => { id: Ci::BuildMetadata.scoped_build.with_interruptible.select(:id) })
end
scope :unstarted, -> { where(runner_id: nil) }
+
scope :with_downloadable_artifacts, -> do
where('EXISTS (?)',
Ci::JobArtifact.select(1)
@@ -120,6 +122,14 @@ module Ci
)
end
+ scope :with_erasable_artifacts, -> do
+ where('EXISTS (?)',
+ Ci::JobArtifact.select(1)
+ .where('ci_builds.id = ci_job_artifacts.job_id')
+ .where(file_type: Ci::JobArtifact.erasable_file_types)
+ )
+ end
+
scope :in_pipelines, ->(pipelines) do
where(pipeline: pipelines)
end
@@ -178,7 +188,7 @@ module Ci
scope :license_management_jobs, -> { where(name: %i(license_management license_scanning)) } # handle license rename https://gitlab.com/gitlab-org/gitlab/issues/8911
scope :with_secure_reports_from_config_options, -> (job_types) do
- joins(:metadata).where("ci_builds_metadata.config_options -> 'artifacts' -> 'reports' ?| array[:job_types]", job_types: job_types)
+ joins(:metadata).where("#{Ci::BuildMetadata.quoted_table_name}.config_options -> 'artifacts' -> 'reports' ?| array[:job_types]", job_types: job_types)
end
scope :with_coverage, -> { where.not(coverage: nil) }
@@ -218,7 +228,7 @@ module Ci
yaml_variables when environment coverage_regex
description tag_list protected needs_attributes
job_variables_attributes resource_group scheduling_type
- ci_stage partition_id].freeze
+ ci_stage partition_id id_tokens].freeze
end
end
@@ -407,18 +417,10 @@ module Ci
pipeline.manual_actions.reject { |action| action.name == self.name }
end
- def environment_manual_actions
- pipeline.manual_actions.filter { |action| action.expanded_environment_name == self.expanded_environment_name }
- end
-
def other_scheduled_actions
pipeline.scheduled_actions.reject { |action| action.name == self.name }
end
- def environment_scheduled_actions
- pipeline.scheduled_actions.filter { |action| action.expanded_environment_name == self.expanded_environment_name }
- end
-
def pages_generator?
Gitlab.config.pages.enabled &&
self.name == 'pages'
@@ -445,8 +447,7 @@ module Ci
def prevent_rollback_deployment?
strong_memoize(:prevent_rollback_deployment) do
- Feature.enabled?(:prevent_outdated_deployment_jobs, project) &&
- starts_environment? &&
+ starts_environment? &&
project.ci_forward_deployment_enabled? &&
deployment&.older_than_last_successful_deployment?
end
@@ -1195,6 +1196,14 @@ module Ci
end
def job_jwt_variables
+ if project.ci_cd_settings.opt_in_jwt?
+ id_tokens_variables
+ else
+ legacy_jwt_variables.concat(id_tokens_variables)
+ end
+ end
+
+ def legacy_jwt_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless Feature.enabled?(:ci_job_jwt, project)
@@ -1208,6 +1217,20 @@ module Ci
end
end
+ def id_tokens_variables
+ return [] unless id_tokens?
+
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ id_tokens.each do |var_name, token_data|
+ token = Gitlab::Ci::JwtV2.for_build(self, aud: token_data['id_token']['aud'])
+
+ variables.append(key: var_name, value: token, public: false, masked: true)
+ end
+ rescue OpenSSL::PKey::RSAError, Gitlab::Ci::Jwt::NoSigningKeyError => e
+ Gitlab::ErrorTracking.track_exception(e)
+ end
+ end
+
def cache_for_online_runners(&block)
Rails.cache.fetch(
['has-online-runners', id],
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 3bdf2f90acb..33092e881f0 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -6,11 +6,14 @@ module Ci
class BuildMetadata < Ci::ApplicationRecord
BuildTimeout = Struct.new(:value, :source)
+ include Ci::Partitionable
include Presentable
include ChronicDurationAttribute
include Gitlab::Utils::StrongMemoize
self.table_name = 'ci_builds_metadata'
+ self.primary_key = 'id'
+ partitionable scope: :build
belongs_to :build, class_name: 'CommitStatus'
belongs_to :project
@@ -27,7 +30,7 @@ module Ci
chronic_duration_attr_reader :timeout_human_readable, :timeout
- scope :scoped_build, -> { where('ci_builds_metadata.build_id = ci_builds.id') }
+ scope :scoped_build, -> { where("#{quoted_table_name}.build_id = #{Ci::Build.quoted_table_name}.id") }
scope :with_interruptible, -> { where(interruptible: true) }
scope :with_exposed_artifacts, -> { where(has_exposed_artifacts: true) }
diff --git a/app/models/ci/job_token/project_scope_link.rb b/app/models/ci/job_token/project_scope_link.rb
index c2ab8ca0929..3fdf07123e6 100644
--- a/app/models/ci/job_token/project_scope_link.rb
+++ b/app/models/ci/job_token/project_scope_link.rb
@@ -19,6 +19,11 @@ module Ci
validates :target_project, presence: true
validate :not_self_referential_link
+ enum direction: {
+ outbound: 0,
+ inbound: 1
+ }
+
def self.for_source_and_target(source_project, target_project)
self.find_by(source_project: source_project, target_project: target_project)
end
diff --git a/app/models/ci/job_token/scope.rb b/app/models/ci/job_token/scope.rb
index 26a49d6a730..1aa49b95201 100644
--- a/app/models/ci/job_token/scope.rb
+++ b/app/models/ci/job_token/scope.rb
@@ -23,7 +23,7 @@ module Ci
def includes?(target_project)
# if the setting is disabled any project is considered to be in scope.
- return true unless source_project.ci_job_token_scope_enabled?
+ return true unless source_project.ci_outbound_job_token_scope_enabled?
target_project.id == source_project.id ||
Ci::JobToken::ProjectScopeLink.from_project(source_project).to_project(target_project).exists?
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 1e328c3c573..950e0a583bc 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -112,6 +112,8 @@ module Ci
has_one :pipeline_config, class_name: 'Ci::PipelineConfig', inverse_of: :pipeline
+ has_one :pipeline_metadata, class_name: 'Ci::PipelineMetadata', inverse_of: :pipeline
+
has_many :daily_build_group_report_results, class_name: 'Ci::DailyBuildGroupReportResult', foreign_key: :last_pipeline_id
has_many :latest_builds_report_results, through: :latest_builds, source: :report_results
has_many :pipeline_artifacts, class_name: 'Ci::PipelineArtifact', inverse_of: :pipeline, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -119,6 +121,7 @@ module Ci
accepts_nested_attributes_for :variables, reject_if: :persisted?
delegate :full_path, to: :project, prefix: true
+ delegate :title, to: :pipeline_metadata, allow_nil: true
validates :sha, presence: { unless: :importing? }
validates :ref, presence: { unless: :importing? }
@@ -614,6 +617,15 @@ module Ci
# auto_canceled_by_pipeline_id - store the pipeline_id of the pipeline that triggered cancellation
# execute_async - if true cancel the children asyncronously
def cancel_running(retries: 1, cascade_to_children: true, auto_canceled_by_pipeline_id: nil, execute_async: true)
+ Gitlab::AppJsonLogger.info(
+ event: 'pipeline_cancel_running',
+ pipeline_id: id,
+ auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id,
+ cascade_to_children: cascade_to_children,
+ execute_async: execute_async,
+ **Gitlab::ApplicationContext.current
+ )
+
update(auto_canceled_by_id: auto_canceled_by_pipeline_id) if auto_canceled_by_pipeline_id
cancel_jobs(cancelable_statuses, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id)
@@ -760,8 +772,14 @@ module Ci
# There is no ActiveRecord relation between Ci::Pipeline and notes
# as they are related to a commit sha. This method helps importing
# them using the +Gitlab::ImportExport::Project::RelationFactory+ class.
- def notes=(notes)
- notes.each do |note|
+ def notes=(notes_to_save)
+ notes_to_save.reject! do |note_to_save|
+ notes.any? do |note|
+ [note_to_save.note, note_to_save.created_at.to_i] == [note.note, note.created_at.to_i]
+ end
+ end
+
+ notes_to_save.each do |note|
note[:id] = nil
note[:commit_id] = sha
note[:noteable_id] = self['id']
@@ -850,7 +868,6 @@ module Ci
variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref)
variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug)
variables.append(key: 'CI_COMMIT_BRANCH', value: ref) if branch?
- variables.append(key: 'CI_COMMIT_TAG', value: ref) if tag?
variables.append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
@@ -863,7 +880,8 @@ module Ci
variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref)
variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug)
- variables.append(key: 'CI_BUILD_TAG', value: ref) if tag?
+
+ variables.concat(predefined_commit_tag_variables)
end
end
end
@@ -888,6 +906,20 @@ module Ci
end
end
+ def predefined_commit_tag_variables
+ strong_memoize(:predefined_commit_ref_variables) do
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ next variables unless tag?
+
+ variables.append(key: 'CI_COMMIT_TAG', value: ref)
+ variables.append(key: 'CI_COMMIT_TAG_MESSAGE', value: project.repository.find_tag(ref).message)
+
+ # legacy variable
+ variables.append(key: 'CI_BUILD_TAG', value: ref)
+ end
+ end
+ end
+
def queued_duration
return unless started_at
@@ -972,8 +1004,8 @@ module Ci
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700
expanded_environment_names =
builds_in_self_and_project_descendants.joins(:metadata)
- .where.not('ci_builds_metadata.expanded_environment_name' => nil)
- .distinct('ci_builds_metadata.expanded_environment_name')
+ .where.not(Ci::BuildMetadata.table_name => { expanded_environment_name: nil })
+ .distinct("#{Ci::BuildMetadata.quoted_table_name}.expanded_environment_name")
.limit(100)
.pluck(:expanded_environment_name)
@@ -1162,6 +1194,10 @@ module Ci
complete? && builds.latest.with_exposed_artifacts.exists?
end
+ def has_erasable_artifacts?
+ complete? && builds.latest.with_erasable_artifacts.exists?
+ end
+
def branch_updated?
strong_memoize(:branch_updated) do
push_details.branch_updated?
@@ -1328,9 +1364,9 @@ module Ci
self.builds.latest.build_matchers(project)
end
- def authorized_cluster_agents
- strong_memoize(:authorized_cluster_agents) do
- ::Clusters::AgentAuthorizationsFinder.new(project).execute.map(&:agent)
+ def cluster_agent_authorizations
+ strong_memoize(:cluster_agent_authorizations) do
+ ::Clusters::AgentAuthorizationsFinder.new(project).execute
end
end
diff --git a/app/models/ci/pipeline_metadata.rb b/app/models/ci/pipeline_metadata.rb
new file mode 100644
index 00000000000..c96b395b45f
--- /dev/null
+++ b/app/models/ci/pipeline_metadata.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Ci
+ class PipelineMetadata < Ci::ApplicationRecord
+ self.primary_key = :pipeline_id
+
+ belongs_to :pipeline, class_name: "Ci::Pipeline", inverse_of: :pipeline_metadata
+ belongs_to :project, class_name: "Project", inverse_of: :pipeline_metadata
+
+ validates :pipeline, presence: true
+ validates :project, presence: true
+ validates :title, presence: true, length: { minimum: 1, maximum: 255 }
+ end
+end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 28d9edcc135..3be627989b1 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -14,7 +14,7 @@ module Ci
include Presentable
include EachBatch
- add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration, expiration_enforced?: :token_expiration_enforced?
+ add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration
enum access_level: {
not_protected: 0,
@@ -99,27 +99,26 @@ module Ci
}
scope :belonging_to_group, -> (group_id) {
- joins(:runner_namespaces)
- .where(ci_runner_namespaces: { namespace_id: group_id })
+ joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: group_id })
}
scope :belonging_to_group_or_project_descendants, -> (group_id) {
group_ids = Ci::NamespaceMirror.by_group_and_descendants(group_id).select(:namespace_id)
project_ids = Ci::ProjectMirror.by_namespace_id(group_ids).select(:project_id)
- group_runners = joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: group_ids })
- project_runners = joins(:runner_projects).where(ci_runner_projects: { project_id: project_ids })
+ group_runners = belonging_to_group(group_ids)
+ project_runners = belonging_to_project(project_ids).distinct
- union_sql = ::Gitlab::SQL::Union.new([group_runners, project_runners]).to_sql
-
- from("(#{union_sql}) #{table_name}")
+ from_union(
+ [group_runners, project_runners],
+ remove_duplicates: false
+ )
}
scope :belonging_to_group_and_ancestors, -> (group_id) {
group_self_and_ancestors_ids = ::Group.find_by(id: group_id)&.self_and_ancestor_ids
- joins(:runner_namespaces)
- .where(ci_runner_namespaces: { namespace_id: group_self_and_ancestors_ids })
+ belonging_to_group(group_self_and_ancestors_ids)
}
scope :belonging_to_parent_group_of_project, -> (project_id) {
@@ -153,6 +152,17 @@ module Ci
)
end
+ scope :usable_from_scope, -> (group) do
+ from_union(
+ [
+ belonging_to_group(group.ancestor_ids),
+ belonging_to_group_or_project_descendants(group.id),
+ group.shared_runners
+ ],
+ remove_duplicates: false
+ )
+ end
+
scope :assignable_for, ->(project) do
# FIXME: That `to_sql` is needed to workaround a weird Rails bug.
# Without that, placeholders would miss one and couldn't match.
@@ -205,7 +215,7 @@ module Ci
validates :maintenance_note, length: { maximum: 1024 }
- alias_attribute :maintenance_note, :maintainer_note
+ alias_attribute :maintenance_note, :maintainer_note # NOTE: Need to keep until REST v5 is implemented
# Searches for runners matching the given query.
#
@@ -335,7 +345,7 @@ module Ci
end
# DEPRECATED
- # TODO Remove in %16.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ # TODO Remove in v5 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
def deprecated_rest_status
return :stale if stale?
@@ -470,10 +480,6 @@ module Ci
end
end
- def self.token_expiration_enforced?
- Feature.enabled?(:enforce_runner_token_expires_at)
- end
-
private
scope :with_upgrade_status, ->(upgrade_status) do
diff --git a/app/models/ci/secure_file.rb b/app/models/ci/secure_file.rb
index 9a35f1876c9..ffff7eebbee 100644
--- a/app/models/ci/secure_file.rb
+++ b/app/models/ci/secure_file.rb
@@ -7,6 +7,7 @@ module Ci
FILE_SIZE_LIMIT = 5.megabytes.freeze
CHECKSUM_ALGORITHM = 'sha256'
+ PARSABLE_EXTENSIONS = %w[cer p12 mobileprovision].freeze
self.limit_scope = :project
self.limit_name = 'project_ci_secure_files'
@@ -16,6 +17,7 @@ module Ci
validates :file, presence: true, file_size: { maximum: FILE_SIZE_LIMIT }
validates :checksum, :file_store, :name, :project_id, presence: true
validates :name, uniqueness: { scope: :project }
+ validates :metadata, json_schema: { filename: "ci_secure_file_metadata" }, allow_nil: true
after_initialize :generate_key_data
before_validation :assign_checksum
@@ -23,6 +25,8 @@ module Ci
scope :order_by_created_at, -> { order(created_at: :desc) }
scope :project_id_in, ->(ids) { where(project_id: ids) }
+ serialize :metadata, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
+
default_value_for(:file_store) { Ci::SecureFileUploader.default_store }
mount_file_store_uploader Ci::SecureFileUploader
@@ -31,6 +35,41 @@ module Ci
CHECKSUM_ALGORITHM
end
+ def file_extension
+ File.extname(name).delete_prefix('.')
+ end
+
+ def metadata_parsable?
+ PARSABLE_EXTENSIONS.include?(file_extension)
+ end
+
+ def metadata_parser
+ return unless metadata_parsable?
+
+ case file_extension
+ when 'cer'
+ Gitlab::Ci::SecureFiles::Cer.new(file.read)
+ when 'p12'
+ Gitlab::Ci::SecureFiles::P12.new(file.read)
+ when 'mobileprovision'
+ Gitlab::Ci::SecureFiles::MobileProvision.new(file.read)
+ end
+ end
+
+ def update_metadata!
+ return unless metadata_parser
+
+ begin
+ parser = metadata_parser
+ self.metadata = parser.metadata
+ self.expires_at = parser.metadata[:expires_at]
+ save!
+ rescue StandardError => err
+ Gitlab::AppLogger.error("Secure File Parser Failure (#{id}): #{err.message} - #{parser.error}.")
+ nil
+ end
+ end
+
private
def assign_checksum
diff --git a/app/models/clusters/agents/implicit_authorization.rb b/app/models/clusters/agents/implicit_authorization.rb
index 9f7f653ed65..a365ccdc568 100644
--- a/app/models/clusters/agents/implicit_authorization.rb
+++ b/app/models/clusters/agents/implicit_authorization.rb
@@ -16,7 +16,7 @@ module Clusters
end
def config
- nil
+ {}
end
end
end
diff --git a/app/models/concerns/approvable.rb b/app/models/concerns/approvable.rb
index 1566c53217d..55e138d84fb 100644
--- a/app/models/concerns/approvable.rb
+++ b/app/models/concerns/approvable.rb
@@ -50,11 +50,11 @@ module Approvable
approvals.where(user: user).any?
end
- def can_be_approved_by?(user)
+ def eligible_for_approval_by?(user)
user && !approved_by?(user) && user.can?(:approve_merge_request, self)
end
- def can_be_unapproved_by?(user)
+ def eligible_for_unapproval_by?(user)
user && approved_by?(user) && user.can?(:approve_merge_request, self)
end
end
diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb
index 88f577c3e23..14be924f9da 100644
--- a/app/models/concerns/atomic_internal_id.rb
+++ b/app/models/concerns/atomic_internal_id.rb
@@ -174,6 +174,13 @@ module AtomicInternalId
#
# bulk_insert(attributes)
# end
+ #
+ # - track_#{scope}_#{column}!
+ # This method can be used to set a new greatest IID value during import operations.
+ #
+ # Example:
+ #
+ # MyClass.track_project_iid!(project, value)
def define_singleton_internal_id_methods(scope, column, init)
define_singleton_method("with_#{scope}_#{column}_supply") do |scope_value, &block|
subject = find_by(scope => scope_value) || self
@@ -183,6 +190,16 @@ module AtomicInternalId
supply = Supply.new(-> { InternalId.generate_next(subject, scope_attrs, usage, init) })
block.call(supply)
end
+
+ define_singleton_method("track_#{scope}_#{column}!") do |scope_value, value|
+ InternalId.track_greatest(
+ self,
+ ::AtomicInternalId.scope_attrs(scope_value),
+ ::AtomicInternalId.scope_usage(self),
+ value,
+ init
+ )
+ end
end
end
diff --git a/app/models/concerns/boards/listable.rb b/app/models/concerns/boards/listable.rb
index b9827a79422..b09ef7e612d 100644
--- a/app/models/concerns/boards/listable.rb
+++ b/app/models/concerns/boards/listable.rb
@@ -13,7 +13,7 @@ module Boards
scope :ordered, -> { order(:list_type, :position) }
scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
- scope :without_types, ->(list_types) { where.not(list_type: list_types) }
+ scope :with_types, ->(list_types) { where(list_type: list_types) }
class << self
def preload_preferences_for_user(lists, user)
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 9ee0fd1db1d..ec0cf36d875 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -237,3 +237,5 @@ module CacheMarkdownField
end
end
end
+
+CacheMarkdownField.prepend_mod
diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb
index 71b26b70bbf..ff884984099 100644
--- a/app/models/concerns/ci/metadatable.rb
+++ b/app/models/concerns/ci/metadatable.rb
@@ -80,7 +80,7 @@ module Ci
end
def id_tokens?
- !!metadata&.id_tokens?
+ metadata&.id_tokens.present?
end
def id_tokens=(value)
diff --git a/app/models/concerns/ci/partitionable.rb b/app/models/concerns/ci/partitionable.rb
index 710ee1ba64f..df803180e77 100644
--- a/app/models/concerns/ci/partitionable.rb
+++ b/app/models/concerns/ci/partitionable.rb
@@ -19,7 +19,32 @@ module Ci
extend ActiveSupport::Concern
include ::Gitlab::Utils::StrongMemoize
+ module Testing
+ InclusionError = Class.new(StandardError)
+
+ PARTITIONABLE_MODELS = %w[
+ CommitStatus
+ Ci::BuildMetadata
+ Ci::Stage
+ Ci::JobArtifact
+ Ci::PipelineVariable
+ Ci::Pipeline
+ ].freeze
+
+ def self.check_inclusion(klass)
+ return if PARTITIONABLE_MODELS.include?(klass.name)
+
+ raise Partitionable::Testing::InclusionError,
+ "#{klass} must be included in PARTITIONABLE_MODELS"
+
+ rescue InclusionError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+ end
+
included do
+ Partitionable::Testing.check_inclusion(self)
+
before_validation :set_partition_id, on: :create
validates :partition_id, presence: true
@@ -37,6 +62,8 @@ module Ci
def partitionable(scope:)
define_method(:partition_scope_value) do
strong_memoize(:partition_scope_value) do
+ next Ci::Pipeline.current_partition_value if respond_to?(:importing?) && importing?
+
record = scope.to_proc.call(self)
record.respond_to?(:partition_id) ? record.partition_id : record
end
diff --git a/app/models/concerns/counter_attribute.rb b/app/models/concerns/counter_attribute.rb
index 64d178b7507..03e062a9855 100644
--- a/app/models/concerns/counter_attribute.rb
+++ b/app/models/concerns/counter_attribute.rb
@@ -95,7 +95,7 @@ module CounterAttribute
next if increment_value == 0
transaction do
- unsafe_update_counters(id, attribute => increment_value)
+ update_counters_with_lease({ attribute => increment_value })
redis_state { |redis| redis.del(flushed_key) }
new_db_value = reset.read_attribute(attribute)
end
@@ -130,9 +130,18 @@ module CounterAttribute
end
end
- def clear_counter!(attribute)
+ def update_counters_with_lease(increments)
+ detect_race_on_record(log_fields: { caller: __method__, attributes: increments.keys }) do
+ self.class.update_counters(id, increments)
+ end
+ end
+
+ def reset_counter!(attribute)
if counter_attribute_enabled?(attribute)
- redis_state { |redis| redis.del(counter_key(attribute)) }
+ detect_race_on_record(log_fields: { caller: __method__, attributes: attribute }) do
+ update!(attribute => 0)
+ clear_counter!(attribute)
+ end
log_clear_counter(attribute)
end
@@ -164,14 +173,20 @@ module CounterAttribute
private
+ def database_lock_key
+ "project:{#{project_id}}:#{self.class}:#{id}"
+ end
+
def steal_increments(increment_key, flushed_key)
redis_state do |redis|
redis.eval(LUA_STEAL_INCREMENT_SCRIPT, keys: [increment_key, flushed_key])
end
end
- def unsafe_update_counters(id, increments)
- self.class.update_counters(id, increments)
+ def clear_counter!(attribute)
+ redis_state do |redis|
+ redis.del(counter_key(attribute))
+ end
end
def execute_after_flush_callbacks
@@ -192,6 +207,44 @@ module CounterAttribute
# a worker is already updating the counters
end
+ # detect_race_on_record uses a lease to monitor access
+ # to the project statistics row. This is needed to detect
+ # concurrent attempts to increment columns, which could result in a
+ # race condition.
+ #
+ # As the purpose is to detect and warn concurrent attempts,
+ # it falls back to direct update on the row if it fails to obtain the lease.
+ #
+ # It does not guarantee that there will not be any concurrent updates.
+ def detect_race_on_record(log_fields: {})
+ return yield unless Feature.enabled?(:counter_attribute_db_lease_for_update, project)
+
+ # Ensure attributes is always an array before we log
+ log_fields[:attributes] = Array(log_fields[:attributes])
+
+ Gitlab::AppLogger.info(
+ message: 'Acquiring lease for project statistics update',
+ project_statistics_id: id,
+ project_id: project.id,
+ **log_fields,
+ **Gitlab::ApplicationContext.current
+ )
+
+ in_lock(database_lock_key, retries: 0) do
+ yield
+ end
+ rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
+ Gitlab::AppLogger.warn(
+ message: 'Concurrent project statistics update detected',
+ project_statistics_id: id,
+ project_id: project.id,
+ **log_fields,
+ **Gitlab::ApplicationContext.current
+ )
+
+ yield
+ end
+
def log_increment_counter(attribute, increment, new_value)
payload = Gitlab::ApplicationContext.current.merge(
message: 'Increment counter attribute',
diff --git a/app/models/concerns/has_wiki.rb b/app/models/concerns/has_wiki.rb
index 89bcabafb84..53016ce62f4 100644
--- a/app/models/concerns/has_wiki.rb
+++ b/app/models/concerns/has_wiki.rb
@@ -8,7 +8,7 @@ module HasWiki
end
def create_wiki
- wiki.wiki
+ wiki.create_wiki_repository
true
rescue Wiki::CouldNotCreateWikiError
errors.add(:base, _('Failed to create wiki'))
diff --git a/app/models/concerns/integrations/base_data_fields.rb b/app/models/concerns/integrations/base_data_fields.rb
index 2870922d90d..4319d63abb9 100644
--- a/app/models/concerns/integrations/base_data_fields.rb
+++ b/app/models/concerns/integrations/base_data_fields.rb
@@ -5,8 +5,6 @@ module Integrations
extend ActiveSupport::Concern
included do
- # TODO: Once we rename the tables we can't rely on `table_name` anymore.
- # https://gitlab.com/gitlab-org/gitlab/-/issues/331953
belongs_to :integration, inverse_of: self.table_name.to_sym, foreign_key: :integration_id
validates :integration, presence: true
diff --git a/app/models/concerns/integrations/has_web_hook.rb b/app/models/concerns/integrations/has_web_hook.rb
index 5fd71f3d72f..e622faf4a51 100644
--- a/app/models/concerns/integrations/has_web_hook.rb
+++ b/app/models/concerns/integrations/has_web_hook.rb
@@ -6,7 +6,7 @@ module Integrations
included do
after_save :update_web_hook!, if: :activated?
- has_one :service_hook, inverse_of: :integration, foreign_key: :service_id
+ has_one :service_hook, inverse_of: :integration, foreign_key: :integration_id
end
# Return the URL to be used for the webhook.
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index b81a9b51e1c..f8389865f91 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -33,6 +33,7 @@ module Issuable
DESCRIPTION_LENGTH_MAX = 1.megabyte
DESCRIPTION_HTML_LENGTH_MAX = 5.megabytes
SEARCHABLE_FIELDS = %w(title description).freeze
+ MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 200
STATE_ID_MAP = {
opened: 1,
@@ -95,6 +96,7 @@ module Issuable
# to avoid breaking the existing Issuables which may have their descriptions longer
validates :description, length: { maximum: DESCRIPTION_LENGTH_MAX }, allow_blank: true, on: :create
validate :description_max_length_for_new_records_is_valid, on: :update
+ validate :validate_assignee_size_length, unless: :importing?
before_validation :truncate_description_on_import!
@@ -166,6 +168,11 @@ module Issuable
def locking_enabled?
false
end
+
+ def max_number_of_assignees_or_reviewers_message
+ # Assignees will be included in https://gitlab.com/gitlab-org/gitlab/-/issues/368936
+ format(_("total must be less than or equal to %{size}"), size: MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS)
+ end
end
# We want to use optimistic lock for cases when only title or description are involved
@@ -227,11 +234,19 @@ module Issuable
def truncate_description_on_import!
self.description = description&.slice(0, Issuable::DESCRIPTION_LENGTH_MAX) if importing?
end
+
+ def validate_assignee_size_length
+ return true unless Feature.enabled?(:limit_assignees_per_issuable)
+ return true unless assignees.size > MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+
+ errors.add :assignees,
+ -> (_object, _data) { self.class.max_number_of_assignees_or_reviewers_message }
+ end
end
class_methods do
def participant_includes
- [:assignees, :author, { notes: [:author, :award_emoji] }]
+ [:author, :award_emoji, { notes: [:author, :award_emoji, :system_note_metadata] }]
end
# Searches for records with a matching title.
@@ -383,10 +398,12 @@ module Issuable
milestone_table = Milestone.arel_table
grouping_columns << milestone_table[:id]
grouping_columns << milestone_table[:due_date]
- elsif %w(merged_at_desc merged_at_asc).include?(sort)
+ elsif %w(merged_at_desc merged_at_asc merged_at).include?(sort)
+ grouping_columns << MergeRequest::Metrics.arel_table[:id]
grouping_columns << MergeRequest::Metrics.arel_table[:merged_at]
- elsif %w(closed_at_desc closed_at_asc).include?(sort)
- grouping_columns << MergeRequest::Metrics.arel_table[:closed_at]
+ elsif %w(closed_at_desc closed_at_asc closed_at).include?(sort)
+ grouping_columns << MergeRequest::Metrics.arel_table[:id]
+ grouping_columns << MergeRequest::Metrics.arel_table[:latest_closed_at]
end
grouping_columns
@@ -431,7 +448,16 @@ module Issuable
end
def assignee_or_author?(user)
- author_id == user.id || assignees.exists?(user.id)
+ author_id == user.id || assignee?(user)
+ end
+
+ def assignee?(user)
+ # Necessary so we can preload the association and avoid N + 1 queries
+ if assignees.loaded?
+ assignees.to_a.include?(user)
+ else
+ assignees.exists?(user.id)
+ end
end
def today?
@@ -630,6 +656,14 @@ module Issuable
def draftless_title_changed(old_title)
old_title != title
end
+
+ def read_ability_for(participable_source)
+ return super if participable_source == self
+
+ name = participable_source.try(:issuable_ability_name) || :read_issuable_participables
+
+ { name: name, subject: self }
+ end
end
Issuable.prepend_mod_with('Issuable')
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 8130adf05f1..6035cb87c9b 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -152,7 +152,9 @@ module Participable
end
def source_visible_to_user?(source, user)
- Ability.allowed?(user, "read_#{source.model_name.element}".to_sym, source)
+ ability = read_ability_for(source)
+
+ Ability.allowed?(user, ability[:name], ability[:subject])
end
def filter_by_ability(participants)
@@ -172,6 +174,14 @@ module Participable
participant.can?(:read_project, project)
end
end
+
+ # Returns Hash containing ability name and subject needed to read a specific participable.
+ # Should be overridden if a different ability is required.
+ def read_ability_for(participable_source)
+ name = participable_source.try(:to_ability_name) || participable_source.model_name.element
+
+ { name: "read_#{name}".to_sym, subject: participable_source }
+ end
end
Participable.prepend_mod_with('Participable')
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb
index 5b759dedb26..262839a3fa6 100644
--- a/app/models/concerns/routable.rb
+++ b/app/models/concerns/routable.rb
@@ -17,6 +17,9 @@ module Routable
def self.find_by_full_path(path, follow_redirects: false, route_scope: Route, redirect_route_scope: RedirectRoute)
return unless path.present?
+ # Convert path to string to prevent DB error: function lower(integer) does not exist
+ path = path.to_s
+
# Case sensitive match first (it's cheaper and the usual case)
# If we didn't have an exact match, we perform a case insensitive search
#
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb
index d53594eb5af..5b74e88429c 100644
--- a/app/models/concerns/timebox.rb
+++ b/app/models/concerns/timebox.rb
@@ -3,13 +3,10 @@
module Timebox
extend ActiveSupport::Concern
- include AtomicInternalId
include CacheMarkdownField
include Gitlab::SQL::Pattern
- include IidRoutes
include Referable
include StripAttribute
- include FromUnion
TimeboxStruct = Struct.new(:title, :name, :id, :class_name) do
# Ensure these models match the interface required for exporting
@@ -42,39 +39,19 @@ module Timebox
alias_method :timebox_id, :id
- validates :group, presence: true, unless: :project
- validates :project, presence: true, unless: :group
-
- validate :timebox_type_check
validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? }
validate :dates_within_4_digits
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description, issuable_reference_expansion_enabled: true
- belongs_to :project
- belongs_to :group
-
has_many :issues
has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
has_many :merge_requests
- scope :of_projects, ->(ids) { where(project_id: ids) }
- scope :of_groups, ->(ids) { where(group_id: ids) }
scope :closed, -> { with_state(:closed) }
- scope :for_projects, -> { where(group: nil).includes(:project) }
scope :with_title, -> (title) { where(title: title) }
- scope :for_projects_and_groups, -> (projects, groups) do
- projects = projects.compact if projects.is_a? Array
- projects = [] if projects.nil?
-
- groups = groups.compact if groups.is_a? Array
- groups = [] if groups.nil?
-
- from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false)
- end
-
# A timebox is within the timeframe (start_date, end_date) if it overlaps
# with that timeframe:
#
@@ -132,10 +109,6 @@ module Timebox
end
end
- def count_by_state
- reorder(nil).group(:state).count
- end
-
def predefined_id?(id)
[Any.id, None.id, Upcoming.id, Started.id].include?(id)
end
@@ -145,29 +118,8 @@ module Timebox
end
end
- ##
- # Returns the String necessary to reference a Timebox in Markdown. Group
- # timeboxes only support name references, and do not support cross-project
- # references.
- #
- # format - Symbol format to use (default: :iid, optional: :name)
- #
- # Examples:
- #
- # Milestone.first.to_reference # => "%1"
- # Iteration.first.to_reference(format: :name) # => "*iteration:\"goal\""
- # Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-foss%1"
- # Iteration.first.to_reference(same_namespace_project) # => "gitlab-foss*iteration:1"
- #
- def to_reference(from = nil, format: :name, full: false)
- format_reference = timebox_format_reference(format)
- reference = "#{self.class.reference_prefix}#{format_reference}"
-
- if project
- "#{project.to_reference_base(from, full: full)}#{reference}"
- else
- reference
- end
+ def to_reference
+ raise NotImplementedError
end
def reference_link_text(from = nil)
@@ -182,20 +134,12 @@ module Timebox
model_name.singular
end
- def group_timebox?
- group_id.present?
- end
-
- def project_timebox?
- project_id.present?
- end
-
def safe_title
title.to_slug.normalize.to_s
end
def resource_parent
- group || project
+ raise NotImplementedError
end
def to_ability_name
@@ -203,13 +147,7 @@ module Timebox
end
def merge_requests_enabled?
- if group_timebox?
- # Assume that groups have at least one project with merge requests enabled.
- # Otherwise, we would need to load all of the projects from the database.
- true
- elsif project_timebox?
- project&.merge_requests_enabled?
- end
+ raise NotImplementedError
end
def weight_available?
@@ -218,28 +156,6 @@ module Timebox
private
- def timebox_format_reference(format = :iid)
- raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format)
-
- if group_timebox? && format == :iid
- raise ArgumentError, _('Cannot refer to a group %{timebox_type} by an internal id!') % { timebox_type: timebox_name }
- end
-
- if format == :name && !name.include?('"')
- %("#{name}")
- else
- iid
- end
- end
-
- # Timebox should be either a project timebox or a group timebox
- def timebox_type_check
- if group_id && project_id
- field = project_id_changed? ? :project_id : :group_id
- errors.add(field, _("%{timebox_name} should belong either to a project or a group.") % { timebox_name: timebox_name })
- end
- end
-
def start_date_should_be_less_than_due_date
if due_date <= start_date
errors.add(:due_date, _("must be greater than start date"))
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 94ac2405f61..2563fd484f1 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -4,6 +4,7 @@ class DeployKey < Key
include FromUnion
include IgnorableColumns
include PolicyActor
+ include Presentable
has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :deploy_keys_projects
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index dafcbc593be..20841bc14cd 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -105,6 +105,7 @@ class Deployment < ApplicationRecord
after_transition any => :running do |deployment|
next unless deployment.project.ci_forward_deployment_enabled?
+ next if Feature.enabled?(:prevent_outdated_deployment_jobs, deployment.project)
deployment.run_after_commit do
Deployments::DropOlderDeploymentsWorker.perform_async(id)
@@ -282,27 +283,11 @@ class Deployment < ApplicationRecord
end
def manual_actions
- environment_manual_actions
- end
-
- def other_manual_actions
- @other_manual_actions ||= deployable.try(:other_manual_actions)
- end
-
- def environment_manual_actions
- @environment_manual_actions ||= deployable.try(:environment_manual_actions)
+ @manual_actions ||= deployable.try(:other_manual_actions)
end
def scheduled_actions
- environment_scheduled_actions
- end
-
- def environment_scheduled_actions
- @environment_scheduled_actions ||= deployable.try(:environment_scheduled_actions)
- end
-
- def other_scheduled_actions
- @other_scheduled_actions ||= deployable.try(:other_scheduled_actions)
+ @scheduled_actions ||= deployable.try(:other_scheduled_actions)
end
def playable_build
diff --git a/app/models/diff_viewer/server_side.rb b/app/models/diff_viewer/server_side.rb
index 0877c9dddec..a1defb2594f 100644
--- a/app/models/diff_viewer/server_side.rb
+++ b/app/models/diff_viewer/server_side.rb
@@ -10,6 +10,9 @@ module DiffViewer
end
def prepare!
+ return if Feature.enabled?(:disable_load_entire_blob_for_diff_viewer, diff_file.repository.project)
+
+ # TODO: remove this after resolving #342703
diff_file.old_blob&.load_all_data!
diff_file.new_blob&.load_all_data!
end
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 4b98cd02e3b..2d3f342953f 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -71,7 +71,7 @@ class Environment < ApplicationRecord
validate :safe_external_url
validate :merge_request_not_changed
- delegate :manual_actions, :other_manual_actions, to: :last_deployment, allow_nil: true
+ delegate :manual_actions, to: :last_deployment, allow_nil: true
delegate :auto_rollback_enabled?, to: :project
scope :available, -> { with_state(:available) }
@@ -332,9 +332,9 @@ class Environment < ApplicationRecord
end
def actions_for(environment)
- return [] unless other_manual_actions
+ return [] unless manual_actions
- other_manual_actions.select do |action|
+ manual_actions.select do |action|
action.expanded_environment_name == environment
end
end
@@ -441,11 +441,15 @@ class Environment < ApplicationRecord
end
def auto_stop_in=(value)
- return unless value
+ if value.nil?
+ # Handles edge case when auto_stop_at is already set and the new value is nil.
+ # Possible by setting `auto_stop_in: null` in the CI configuration yml.
+ self.auto_stop_at = nil
- parser = ::Gitlab::Ci::Build::DurationParser.new(value)
+ return
+ end
- return if parser.seconds_from_now.nil? && auto_stop_at.nil?
+ parser = ::Gitlab::Ci::Build::DurationParser.new(value)
self.auto_stop_at = parser.seconds_from_now
rescue ChronicDuration::DurationParseError => ex
@@ -540,7 +544,7 @@ class Environment < ApplicationRecord
self.class.tiers[:development]
when /(test|tst|int|ac(ce|)pt|qa|qc|control|quality)/i
self.class.tiers[:testing]
- when /(st(a|)g|mod(e|)l|pre|demo)/i
+ when /(st(a|)g|mod(e|)l|pre|demo|non)/i
self.class.tiers[:staging]
when /(pr(o|)d|live)/i
self.class.tiers[:production]
diff --git a/app/models/event.rb b/app/models/event.rb
index a20ca0dc423..4c1793d3f13 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -10,9 +10,6 @@ class Event < ApplicationRecord
include UsageStatistics
include ShaAttribute
- # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/358088
- default_scope { reorder(nil) } # rubocop:disable Cop/DefaultScope
-
ACTIONS = HashWithIndifferentAccess.new(
created: 1,
updated: 2,
@@ -281,6 +278,7 @@ class Event < ApplicationRecord
"opened"
end
end
+
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop: enable Metrics/PerceivedComplexity
@@ -448,9 +446,9 @@ class Event < ApplicationRecord
def design_action_names
{
- created: _('added'),
- updated: _('updated'),
- destroyed: _('removed')
+ created: 'added',
+ updated: 'updated',
+ destroyed: 'removed'
}
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 1445e71b0bc..38623d91705 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -904,11 +904,7 @@ class Group < Namespace
end
def packages_policy_subject
- if Feature.enabled?(:read_package_policy_rule, self)
- ::Packages::Policies::Group.new(self)
- else
- self
- end
+ ::Packages::Policies::Group.new(self)
end
def update_two_factor_requirement_for_members
diff --git a/app/models/group_group_link.rb b/app/models/group_group_link.rb
index 7005c8593bd..15949570f9c 100644
--- a/app/models/group_group_link.rb
+++ b/app/models/group_group_link.rb
@@ -8,7 +8,7 @@ class GroupGroupLink < ApplicationRecord
validates :shared_group, presence: true
validates :shared_group_id, uniqueness: { scope: [:shared_with_group_id],
- message: _('The group has already been shared with this group') }
+ message: N_('The group has already been shared with this group') }
validates :shared_with_group, presence: true
validates :group_access, inclusion: { in: Gitlab::Access.all_values },
presence: true
diff --git a/app/models/group_label.rb b/app/models/group_label.rb
index ff14529c6e6..0d2eb524929 100644
--- a/app/models/group_label.rb
+++ b/app/models/group_label.rb
@@ -2,6 +2,7 @@
class GroupLabel < Label
belongs_to :group
+ belongs_to :parent_container, foreign_key: :group_id, class_name: 'Group'
validates :group, presence: true
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index bcbf43ee38b..dcba136d163 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -55,13 +55,6 @@ class ProjectHook < WebHook
redis.set(key, time) if !prev || prev < time
end
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/service_hook.rb b/app/models/hooks/service_hook.rb
index 80e167b350b..27119d3a95a 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -4,7 +4,7 @@ class ServiceHook < WebHook
include Presentable
extend ::Gitlab::Utils::Override
- belongs_to :integration, foreign_key: :service_id
+ belongs_to :integration
validates :integration, presence: true
def execute(data, hook_name = 'service_hook')
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 84ee23d77ce..71794964c99 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -7,7 +7,7 @@ class WebHook < ApplicationRecord
MAX_FAILURES = 100
FAILURE_THRESHOLD = 3 # three strikes
- INITIAL_BACKOFF = 10.minutes
+ INITIAL_BACKOFF = 1.minute
MAX_BACKOFF = 1.day
BACKOFF_GROWTH_FACTOR = 2.0
@@ -53,18 +53,24 @@ class WebHook < ApplicationRecord
where('recent_failures > ? OR disabled_until >= ?', FAILURE_THRESHOLD, Time.current)
end
+ def self.web_hooks_disable_failed?(hook)
+ Feature.enabled?(:web_hooks_disable_failed, hook.parent)
+ end
+
def executable?
!temporarily_disabled? && !permanently_disabled?
end
def temporarily_disabled?
return false unless web_hooks_disable_failed?
+ return false if recent_failures <= FAILURE_THRESHOLD
disabled_until.present? && disabled_until >= Time.current
end
def permanently_disabled?
return false unless web_hooks_disable_failed?
+ return false if disabled_until.present?
recent_failures > FAILURE_THRESHOLD
end
@@ -112,17 +118,26 @@ class WebHook < ApplicationRecord
save(validate: false)
end
+ # Don't actually back-off until FAILURE_THRESHOLD failures have been seen
+ # we mark the grace-period using the recent_failures counter
def backoff!
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))
+ attrs = { recent_failures: recent_failures + 1 }
+
+ if recent_failures >= FAILURE_THRESHOLD
+ attrs[:backoff_count] = backoff_count.succ.clamp(1, MAX_FAILURES)
+ attrs[:disabled_until] = next_backoff.from_now
+ end
+
+ assign_attributes(attrs)
save(validate: false)
end
def failed!
return unless recent_failures < MAX_FAILURES
- assign_attributes(recent_failures: recent_failures + 1)
+ assign_attributes(disabled_until: nil, backoff_count: 0, recent_failures: recent_failures + 1)
save(validate: false)
end
@@ -186,7 +201,7 @@ class WebHook < ApplicationRecord
private
def web_hooks_disable_failed?
- Feature.enabled?(:web_hooks_disable_failed)
+ self.class.web_hooks_disable_failed?(self)
end
def initialize_url_variables
diff --git a/app/models/incident_management/timeline_event.rb b/app/models/incident_management/timeline_event.rb
index dd0d3c6585d..735d4e4298c 100644
--- a/app/models/incident_management/timeline_event.rb
+++ b/app/models/incident_management/timeline_event.rb
@@ -18,7 +18,13 @@ module IncidentManagement
validates :project, :incident, :occurred_at, presence: true
validates :action, presence: true, length: { maximum: 128 }
- validates :note, :note_html, presence: true, length: { maximum: 10_000 }
+ validates :note, presence: true, length: { maximum: 10_000 }
+ validates :note_html, length: { maximum: 10_000 }
+
+ has_many :timeline_event_tag_links, class_name: 'IncidentManagement::TimelineEventTagLink'
+ has_many :timeline_event_tags,
+ class_name: 'IncidentManagement::TimelineEventTag',
+ through: :timeline_event_tag_links
scope :order_occurred_at_asc_id_asc, -> { reorder(occurred_at: :asc, id: :asc) }
end
diff --git a/app/models/incident_management/timeline_event_tag.rb b/app/models/incident_management/timeline_event_tag.rb
new file mode 100644
index 00000000000..cde3afcaa16
--- /dev/null
+++ b/app/models/incident_management/timeline_event_tag.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ class TimelineEventTag < ApplicationRecord
+ self.table_name = 'incident_management_timeline_event_tags'
+
+ belongs_to :project, inverse_of: :incident_management_timeline_event_tags
+
+ has_many :timeline_event_tag_links,
+ class_name: 'IncidentManagement::TimelineEventTagLink'
+
+ has_many :timeline_events,
+ class_name: 'IncidentManagement::TimelineEvent',
+ through: :timeline_event_tag_links
+
+ validates :name, presence: true, format: { with: /\A[^,]+\z/ }
+ validates :name, uniqueness: { scope: :project_id }
+ validates :name, length: { maximum: 255 }
+ end
+end
diff --git a/app/models/incident_management/timeline_event_tag_link.rb b/app/models/incident_management/timeline_event_tag_link.rb
new file mode 100644
index 00000000000..912339717a8
--- /dev/null
+++ b/app/models/incident_management/timeline_event_tag_link.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ class TimelineEventTagLink < ApplicationRecord
+ self.table_name = 'incident_management_timeline_event_tag_links'
+
+ belongs_to :timeline_event_tag, class_name: 'IncidentManagement::TimelineEventTag'
+
+ belongs_to :timeline_event, class_name: 'IncidentManagement::TimelineEvent'
+ end
+end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index aecf9529a14..23688a87cbd 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -147,6 +147,8 @@ class Integration < ApplicationRecord
fields << ::Integrations::Field.new(name: name, integration_class: self, **attrs)
case storage
+ when :attribute
+ # noop
when :properties
prop_accessor(name)
when :data_fields
@@ -155,7 +157,7 @@ class Integration < ApplicationRecord
raise ArgumentError, "Unknown field storage: #{storage}"
end
- boolean_accessor(name) if attrs[:type] == 'checkbox'
+ boolean_accessor(name) if attrs[:type] == 'checkbox' && storage != :attribute
end
# :nocov:
diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb
index c9407aa738e..ab0fdbd777f 100644
--- a/app/models/integrations/datadog.rb
+++ b/app/models/integrations/datadog.rb
@@ -15,7 +15,77 @@ module Integrations
TAG_KEY_VALUE_RE = %r{\A [\w-]+ : .*\S.* \z}x.freeze
- prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env, :datadog_tags
+ field :datadog_site,
+ placeholder: DEFAULT_DOMAIN,
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}.')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe
+ }
+ end
+
+ field :api_url,
+ exposes_secrets: true,
+ title: -> { s_('DatadogIntegration|API URL') },
+ help: -> { s_('DatadogIntegration|(Advanced) The full URL for your Datadog site.') }
+
+ field :api_key,
+ type: 'password',
+ title: -> { _('API key') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new API key') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key') },
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.')
+ ) % {
+ linkOpen: %Q{<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">}.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end,
+ required: true
+
+ field :archive_trace_events,
+ storage: :attribute,
+ type: 'checkbox',
+ title: -> { s_('Logs') },
+ checkbox_label: -> { s_('Enable logs collection') },
+ help: -> { s_('When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces.') }
+
+ field :datadog_service,
+ title: -> { s_('DatadogIntegration|Service') },
+ placeholder: 'gitlab-ci',
+ help: -> { s_('DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments.') }
+
+ field :datadog_env,
+ title: -> { s_('DatadogIntegration|Environment') },
+ placeholder: 'ci',
+ help: -> do
+ ERB::Util.html_escape(
+ s_('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}')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe,
+ linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end
+
+ field :datadog_tags,
+ type: 'textarea',
+ title: -> { s_('DatadogIntegration|Tags') },
+ placeholder: "tag:value\nanother_tag:value",
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe,
+ linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end
before_validation :strip_properties
@@ -68,87 +138,6 @@ module Integrations
'datadog'
end
- def fields
- [
- {
- type: 'text',
- name: 'datadog_site',
- placeholder: DEFAULT_DOMAIN,
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}.')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe
- },
- required: false
- },
- {
- type: 'text',
- name: 'api_url',
- title: s_('DatadogIntegration|API URL'),
- help: s_('DatadogIntegration|(Advanced) The full URL for your Datadog site.'),
- required: false
- },
- {
- type: 'password',
- name: 'api_key',
- title: _('API key'),
- non_empty_password_title: s_('ProjectService|Enter new API key'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current API key'),
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.')
- ) % {
- linkOpen: %Q{<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">}.html_safe,
- linkClose: '</a>'.html_safe
- },
- required: true
- },
- {
- type: 'checkbox',
- name: 'archive_trace_events',
- title: s_('Logs'),
- checkbox_label: s_('Enable logs collection'),
- help: s_('When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces.'),
- required: false
- },
- {
- type: 'text',
- name: 'datadog_service',
- title: s_('DatadogIntegration|Service'),
- placeholder: 'gitlab-ci',
- help: s_('DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments.')
- },
- {
- type: 'text',
- name: 'datadog_env',
- title: s_('DatadogIntegration|Environment'),
- placeholder: 'ci',
- help: ERB::Util.html_escape(
- s_('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}')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe,
- linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
- linkClose: '</a>'.html_safe
- }
- },
- {
- type: 'textarea',
- name: 'datadog_tags',
- title: s_('DatadogIntegration|Tags'),
- placeholder: "tag:value\nanother_tag:value",
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe,
- linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
- linkClose: '</a>'.html_safe
- }
- }
- ]
- end
-
override :hook_url
def hook_url
url = api_url.presence || sprintf(URL_TEMPLATE, datadog_domain: datadog_domain)
diff --git a/app/models/integrations/harbor.rb b/app/models/integrations/harbor.rb
index 58eabcfd378..01a04743d5d 100644
--- a/app/models/integrations/harbor.rb
+++ b/app/models/integrations/harbor.rb
@@ -3,14 +3,33 @@ require 'uri'
module Integrations
class Harbor < Integration
- prop_accessor :url, :project_name, :username, :password
-
validates :url, public_url: true, presence: true, addressable_url: { allow_localhost: false, allow_local_network: false }, if: :activated?
validates :project_name, presence: true, if: :activated?
validates :username, presence: true, if: :activated?
validates :password, format: { with: ::Ci::Maskable::REGEX }, if: :activated?
- before_validation :reset_username_and_password
+ field :url,
+ title: -> { s_('HarborIntegration|Harbor URL') },
+ placeholder: 'https://demo.goharbor.io',
+ help: -> { s_('HarborIntegration|Base URL of the Harbor instance.') },
+ exposes_secrets: true,
+ required: true
+
+ field :project_name,
+ title: -> { s_('HarborIntegration|Harbor project name') },
+ help: -> { s_('HarborIntegration|The name of the project in Harbor.') }
+
+ field :username,
+ title: -> { s_('HarborIntegration|Harbor username') },
+ required: true
+
+ field :password,
+ type: 'password',
+ title: -> { s_('HarborIntegration|Harbor password') },
+ help: -> { s_('HarborIntegration|Password for your Harbor username.') },
+ non_empty_password_title: -> { s_('HarborIntegration|Enter new Harbor password') },
+ non_empty_password_help: -> { s_('HarborIntegration|Leave blank to use your current password.') },
+ required: true
def title
'Harbor'
@@ -21,7 +40,7 @@ module Integrations
end
def help
- s_("HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use.")
+ s_("HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use.")
end
def hostname
@@ -46,40 +65,6 @@ module Integrations
client.ping
end
- def fields
- [
- {
- type: 'text',
- name: 'url',
- title: s_('HarborIntegration|Harbor URL'),
- placeholder: 'https://demo.goharbor.io',
- help: s_('HarborIntegration|Base URL of the Harbor instance.'),
- required: true
- },
- {
- type: 'text',
- name: 'project_name',
- title: s_('HarborIntegration|Harbor project name'),
- help: s_('HarborIntegration|The name of the project in Harbor.')
- },
- {
- type: 'text',
- name: 'username',
- title: s_('HarborIntegration|Harbor username'),
- required: true
- },
- {
- type: 'password',
- name: 'password',
- title: s_('HarborIntegration|Harbor password'),
- help: s_('HarborIntegration|Password for your Harbor username.'),
- non_empty_password_title: s_('HarborIntegration|Enter new Harbor password'),
- non_empty_password_help: s_('HarborIntegration|Leave blank to use your current password.'),
- required: true
- }
- ]
- end
-
def ci_variables
return [] unless activated?
@@ -100,15 +85,5 @@ module Integrations
def client
@client ||= ::Gitlab::Harbor::Client.new(self)
end
-
- def reset_username_and_password
- if url_changed? && !password_touched?
- self.password = nil
- end
-
- if url_changed? && !username_touched?
- self.username = nil
- end
- end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 754591b8017..ea7acf9a5d1 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -40,10 +40,15 @@ class Issue < ApplicationRecord
SORTING_PREFERENCE_FIELD = :issues_sort
- # Types of issues that should be displayed on lists across the app
- # for example, project issues list, group issues list and issue boards.
- # Some issue types, like test cases, should be hidden by default.
- TYPES_FOR_LIST = %w(issue incident).freeze
+ # Types of issues that should be displayed on issue lists across the app
+ # for example, project issues list, group issues list, and issues dashboard.
+ #
+ # This should be kept consistent with the enums used for the GraphQL issue list query in
+ # https://gitlab.com/gitlab-org/gitlab/-/blob/1379c2d7bffe2a8d809f23ac5ef9b4114f789c07/app/assets/javascripts/issues/list/constants.js#L154-158
+ TYPES_FOR_LIST = %w(issue incident test_case task).freeze
+
+ # Types of issues that should be displayed on issue board lists
+ TYPES_FOR_BOARD_LIST = %w(issue incident).freeze
belongs_to :project
belongs_to :namespace, inverse_of: :issues
@@ -107,6 +112,7 @@ class Issue < ApplicationRecord
enum issue_type: WorkItems::Type.base_types
alias_method :issuing_parent, :project
+ alias_attribute :issuing_parent_id, :project_id
alias_attribute :external_author, :service_desk_reply_to
@@ -270,6 +276,10 @@ class Issue < ApplicationRecord
end
end
+ def self.participant_includes
+ [:assignees] + super
+ end
+
def next_object_by_relative_position(ignoring: nil, order: :asc)
array_mapping_scope = -> (id_expression) do
relation = Issue.where(Issue.arel_table[:project_id].eq(id_expression))
diff --git a/app/models/iteration.rb b/app/models/iteration.rb
index 71ecbcf1c1a..ed73793c78f 100644
--- a/app/models/iteration.rb
+++ b/app/models/iteration.rb
@@ -2,6 +2,12 @@
# Placeholder class for model that is implemented in EE
class Iteration < ApplicationRecord
+ include IgnorableColumns
+
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/372125
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/372126
+ ignore_column :project_id, remove_with: '15.6', remove_after: '2022-09-17'
+
self.table_name = 'sprints'
def self.reference_prefix
diff --git a/app/models/jira_connect/public_key.rb b/app/models/jira_connect/public_key.rb
new file mode 100644
index 00000000000..8959884861b
--- /dev/null
+++ b/app/models/jira_connect/public_key.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class PublicKey
+ # Public keys are created with JWT tokens via JiraConnect::CreateAsymmetricJwtService
+ # They need to be available for third party applications to verify the token.
+ # This should happen right after the application received the token so public keys
+ # only need to exist for a few minutes.
+ REDIS_EXPIRY_TIME = 5.minutes.to_i.freeze
+
+ attr_reader :key, :uuid
+
+ def self.create!(key:)
+ new(key: key, uuid: Gitlab::UUID.v5(SecureRandom.hex)).save!
+ end
+
+ def self.find(uuid)
+ Gitlab::Redis::SharedState.with do |redis|
+ key = redis.get(redis_key(uuid))
+
+ raise ActiveRecord::RecordNotFound if key.nil?
+
+ new(key: key, uuid: uuid)
+ end
+ end
+
+ def initialize(key:, uuid:)
+ key = OpenSSL::PKey.read(key) unless key.is_a?(OpenSSL::PKey::RSA)
+
+ @key = key.to_s
+ @uuid = uuid
+ rescue OpenSSL::PKey::PKeyError
+ raise ArgumentError, 'Invalid public key'
+ end
+
+ def save!
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(self.class.redis_key(uuid), key, ex: REDIS_EXPIRY_TIME)
+ end
+
+ self
+ end
+
+ def self.redis_key(uuid)
+ "JiraConnect:public_key:uuid=#{uuid}"
+ end
+ end
+end
diff --git a/app/models/jira_connect_installation.rb b/app/models/jira_connect_installation.rb
index 0a2d3ba0749..23813fa138f 100644
--- a/app/models/jira_connect_installation.rb
+++ b/app/models/jira_connect_installation.rb
@@ -21,6 +21,9 @@ class JiraConnectInstallation < ApplicationRecord
})
}
+ scope :direct_installations, -> { joins(:subscriptions) }
+ scope :proxy_installations, -> { where.not(instance_url: nil) }
+
def client
Atlassian::JiraConnect::Client.new(base_url, shared_secret)
end
@@ -30,4 +33,20 @@ class JiraConnectInstallation < ApplicationRecord
instance_url
end
+
+ def audience_url
+ return unless proxy?
+
+ Gitlab::Utils.append_path(instance_url, '/-/jira_connect')
+ end
+
+ def audience_installed_event_url
+ return unless proxy?
+
+ Gitlab::Utils.append_path(instance_url, '/-/jira_connect/events/installed')
+ end
+
+ def proxy?
+ instance_url.present?
+ end
end
diff --git a/app/models/jira_import_state.rb b/app/models/jira_import_state.rb
index 76b5f1def6a..97d6cd00fb8 100644
--- a/app/models/jira_import_state.rb
+++ b/app/models/jira_import_state.rb
@@ -24,7 +24,7 @@ class JiraImportState < ApplicationRecord
validates :project, uniqueness: {
conditions: -> { where.not(status: STATUSES.values_at(:failed, :finished)) },
- message: _('Cannot have multiple Jira imports running at the same time')
+ message: N_('Cannot have multiple Jira imports running at the same time')
}
before_save :ensure_error_message_size
diff --git a/app/models/label.rb b/app/models/label.rb
index 6608a0573cb..483d51099b1 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -42,6 +42,7 @@ class Label < ApplicationRecord
scope :order_name_asc, -> { reorder(title: :asc) }
scope :order_name_desc, -> { reorder(title: :desc) }
scope :subscribed_by, ->(user_id) { joins(:subscriptions).where(subscriptions: { user_id: user_id, subscribed: true }) }
+ scope :with_preloaded_container, -> { preload(parent_container: :route) }
scope :top_labels_by_target, -> (target_relation) {
label_id_column = arel_table[:id]
@@ -59,6 +60,13 @@ class Label < ApplicationRecord
.distinct
}
+ scope :for_targets, ->(target_relation) do
+ joins(:label_links)
+ .merge(LabelLink.where(target: target_relation))
+ .select(arel_table[Arel.star], LabelLink.arel_table[:target_id])
+ .with_preloaded_container
+ end
+
def self.prioritized(project)
joins(:priorities)
.where(label_priorities: { project_id: project })
diff --git a/app/models/member.rb b/app/models/member.rb
index c5351d5447b..ff1d8f18c25 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -55,7 +55,7 @@ class Member < ApplicationRecord
validate :signup_email_valid?, on: :create, if: ->(member) { member.invite_email.present? }
validates :user_id,
uniqueness: {
- message: _('project bots cannot be added to other groups / projects')
+ message: N_('project bots cannot be added to other groups / projects')
},
if: :project_bot?
validate :access_level_inclusion
@@ -627,7 +627,6 @@ class Member < ApplicationRecord
end
def blocking_refresh
- return true unless Feature.enabled?(:allow_non_blocking_member_refresh)
return true if @blocking_refresh.nil?
@blocking_refresh
diff --git a/app/models/members/member_role.rb b/app/models/members/member_role.rb
index 2e8532fa739..b4e3d6874ef 100644
--- a/app/models/members/member_role.rb
+++ b/app/models/members/member_role.rb
@@ -4,6 +4,15 @@ class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass
has_many :members
belongs_to :namespace
- validates :namespace_id, presence: true
+ validates :namespace, presence: true
validates :base_access_level, presence: true
+ validate :belongs_to_top_level_namespace
+
+ private
+
+ def belongs_to_top_level_namespace
+ return if !namespace || namespace.root?
+
+ errors.add(:namespace, s_("must be top-level namespace"))
+ end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index a57cb97e936..fb20d91fa20 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -41,8 +41,6 @@ class MergeRequest < ApplicationRecord
'Ci::CompareCodequalityReportsService' => ->(project) { true }
}.freeze
- MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 100
-
belongs_to :target_project, class_name: "Project"
belongs_to :source_project, class_name: "Project"
belongs_to :merge_user, class_name: "User"
@@ -73,6 +71,11 @@ class MergeRequest < ApplicationRecord
belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff'
manual_inverse_association :latest_merge_request_diff, :merge_request
+ # method overriden in EE
+ def suggested_reviewer_users
+ User.none
+ end
+
# This is the same as latest_merge_request_diff unless:
# 1. There are arguments - in which case we might be trying to force-reload.
# 2. This association is already loaded.
@@ -238,6 +241,12 @@ class MergeRequest < ApplicationRecord
Gitlab::Timeless.timeless(merge_request, &block)
end
+ after_transition any => [:unchecked, :cannot_be_merged_recheck, :checking, :cannot_be_merged_rechecking, :can_be_merged, :cannot_be_merged] do |merge_request, transition|
+ if Feature.enabled?(:trigger_mr_subscription_on_merge_status_change, merge_request.project)
+ GraphqlTriggers.merge_request_merge_status_updated(merge_request)
+ end
+ end
+
# rubocop: disable CodeReuse/ServiceClass
after_transition [:unchecked, :checking] => :cannot_be_merged do |merge_request, transition|
if merge_request.notify_conflict?
@@ -269,7 +278,7 @@ class MergeRequest < ApplicationRecord
validate :validate_branches, unless: [:allow_broken, :importing?, :closed_or_merged_without_fork?]
validate :validate_fork, unless: :closed_or_merged_without_fork?
validate :validate_target_project, on: :create
- validate :validate_reviewer_and_assignee_size_length, unless: :importing?
+ validate :validate_reviewer_size_length, unless: :importing?
scope :by_source_or_target_branch, ->(branch_name) do
where("source_branch = :branch OR target_branch = :branch", branch: branch_name)
@@ -438,6 +447,7 @@ class MergeRequest < ApplicationRecord
# we'd eventually rename the column for avoiding confusions, but in the mean time
# please use `auto_merge_enabled` alias instead of `merge_when_pipeline_succeeds`.
alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds
+ alias_attribute :issuing_parent_id, :target_project_id
alias_method :issuing_parent, :target_project
delegate :builds_with_coverage, to: :head_pipeline, prefix: true, allow_nil: true
@@ -602,7 +612,7 @@ class MergeRequest < ApplicationRecord
end
def self.participant_includes
- [:reviewers, :award_emoji] + super
+ [:assignees, :reviewers] + super
end
def committers
@@ -988,18 +998,12 @@ class MergeRequest < ApplicationRecord
'Source project is not a fork of the target project'
end
- def self.max_number_of_assignees_or_reviewers_message
- # Assignees will be included in https://gitlab.com/gitlab-org/gitlab/-/issues/368936
- _("total must be less than or equal to %{size}") % { size: MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS }
- end
-
- def validate_reviewer_and_assignee_size_length
- # Assigness will be added in a subsequent MR https://gitlab.com/gitlab-org/gitlab/-/issues/368936
+ def validate_reviewer_size_length
return true unless Feature.enabled?(:limit_reviewer_and_assignee_size)
return true unless reviewers.size > MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
errors.add :reviewers,
- -> (_object, _data) { MergeRequest.max_number_of_assignees_or_reviewers_message }
+ -> (_object, _data) { self.class.max_number_of_assignees_or_reviewers_message }
end
def merge_ongoing?
@@ -1989,6 +1993,10 @@ class MergeRequest < ApplicationRecord
# rubocop: enable CodeReuse/ServiceClass
end
+ def can_suggest_reviewers?
+ false # overridden in EE
+ end
+
private
attr_accessor :skip_fetch_ref
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index 36902e43a77..04b322ef5a6 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -25,6 +25,10 @@ class MergeRequestDiffFile < ApplicationRecord
return '' if fetched_diff.blank?
encode_utf8(fetched_diff) if fetched_diff.respond_to?(:encoding)
+ rescue StandardError => e
+ log_exception('Failed fetching merge request diff', e)
+
+ ''
end
def diff
@@ -75,15 +79,19 @@ class MergeRequestDiffFile < ApplicationRecord
content
rescue StandardError => e
+ log_exception('Cached external diff export failed', e)
+
+ diff
+ end
+
+ def log_exception(message, exception)
log_payload = {
- message: 'Cached external diff export failed',
+ message: message,
merge_request_diff_file_id: id,
merge_request_diff_id: merge_request_diff&.id
}
- Gitlab::ExceptionLogFormatter.format!(e, log_payload)
+ Gitlab::ExceptionLogFormatter.format!(exception, log_payload)
Gitlab::AppLogger.warn(log_payload)
-
- diff
end
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index ff4fadb0f13..da07d8dd9fc 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
class Milestone < ApplicationRecord
+ include AtomicInternalId
include Sortable
include Timebox
include Milestoneish
include FromUnion
include Importable
+ include IidRoutes
prepend_mod_with('Milestone') # rubocop: disable Cop/InjectEnterpriseEditionModule
@@ -13,6 +15,9 @@ class Milestone < ApplicationRecord
ALL = [::Timebox::None, ::Timebox::Any, ::Timebox::Started, ::Timebox::Upcoming].freeze
end
+ belongs_to :project
+ belongs_to :group
+
has_many :milestone_releases
has_many :releases, through: :milestone_releases
@@ -30,13 +35,28 @@ class Milestone < ApplicationRecord
.order(:project_id, :group_id, :due_date)
end
+ scope :of_projects, ->(ids) { where(project_id: ids) }
+ scope :for_projects, -> { where(group: nil).includes(:project) }
+ scope :for_projects_and_groups, -> (projects, groups) do
+ projects = projects.compact if projects.is_a? Array
+ projects = [] if projects.nil?
+
+ groups = groups.compact if groups.is_a? Array
+ groups = [] if groups.nil?
+
+ from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false)
+ end
+
scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) }
scope :reorder_by_due_date_asc, -> { reorder(arel_table[:due_date].asc.nulls_last) }
scope :with_api_entity_associations, -> { preload(project: [:project_feature, :route, namespace: :route]) }
scope :order_by_dates_and_title, -> { order(due_date: :asc, start_date: :asc, title: :asc) }
+ validates :group, presence: true, unless: :project
+ validates :project, presence: true, unless: :group
validates :title, presence: true
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
+ validate :parent_type_check
validate :uniqueness_of_title, if: :title_changed?
state_machine :state, initial: :active do
@@ -176,10 +196,18 @@ class Milestone < ApplicationRecord
# TODO: remove after all code paths use `timebox_id`
# https://gitlab.com/gitlab-org/gitlab/-/issues/215688
alias_method :milestoneish_id, :timebox_id
- # TODO: remove after all code paths use (group|project)_timebox?
- # https://gitlab.com/gitlab-org/gitlab/-/issues/215690
- alias_method :group_milestone?, :group_timebox?
- alias_method :project_milestone?, :project_timebox?
+
+ def group_milestone?
+ group_id.present?
+ end
+
+ def project_milestone?
+ project_id.present?
+ end
+
+ def resource_parent
+ group || project
+ end
def parent
if group_milestone?
@@ -193,8 +221,63 @@ class Milestone < ApplicationRecord
group_milestone? && parent.subgroup?
end
+ def merge_requests_enabled?
+ if group_milestone?
+ # Assume that groups have at least one project with merge requests enabled.
+ # Otherwise, we would need to load all of the projects from the database.
+ true
+ elsif project_milestone?
+ project&.merge_requests_enabled?
+ end
+ end
+
+ ##
+ # Returns the String necessary to reference a milestone in Markdown. Group
+ # milestones only support name references, and do not support cross-project
+ # references.
+ #
+ # format - Symbol format to use (default: :iid, optional: :name)
+ #
+ # Examples:
+ #
+ # Milestone.first.to_reference # => "%1"
+ # Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-foss%1"
+ #
+ def to_reference(from = nil, format: :name, full: false)
+ format_reference = timebox_format_reference(format)
+ reference = "#{self.class.reference_prefix}#{format_reference}"
+
+ if project
+ "#{project.to_reference_base(from, full: full)}#{reference}"
+ else
+ reference
+ end
+ end
+
private
+ def timebox_format_reference(format = :iid)
+ raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format)
+
+ if group_milestone? && format == :iid
+ raise ArgumentError, _('Cannot refer to a group milestone by an internal id!')
+ end
+
+ if format == :name && !name.include?('"')
+ %("#{name}")
+ else
+ iid
+ end
+ end
+
+ # Milestone should be either a project milestone or a group milestone
+ def parent_type_check
+ return unless group_id && project_id
+
+ field = project_id_changed? ? :project_id : :group_id
+ errors.add(field, _("milestone should belong either to a project or a group.") % { timebox_name: timebox_name })
+ end
+
def issues_finder_params
{ project_id: project_id, group_id: group_id, include_subgroups: group_id.present? }.compact
end
diff --git a/app/models/ml/candidate_param.rb b/app/models/ml/candidate_param.rb
index cbdddcc8a1a..a259e059379 100644
--- a/app/models/ml/candidate_param.rb
+++ b/app/models/ml/candidate_param.rb
@@ -3,6 +3,7 @@
module Ml
class CandidateParam < ApplicationRecord
validates :candidate, presence: true
+ validates :name, uniqueness: { scope: :candidate }
validates :name, :value, length: { maximum: 250 }, presence: true
belongs_to :candidate, class_name: 'Ml::Candidate'
diff --git a/app/models/ml/experiment.rb b/app/models/ml/experiment.rb
index e4e9baac4c8..a32099e8a0c 100644
--- a/app/models/ml/experiment.rb
+++ b/app/models/ml/experiment.rb
@@ -13,10 +13,6 @@ module Ml
has_internal_id :iid, scope: :project
- def artifact_location
- 'not_implemented'
- end
-
class << self
def by_project_id_and_iid(project_id, iid)
find_by(project_id: project_id, iid: iid)
@@ -26,8 +22,8 @@ module Ml
find_by(project_id: project_id, name: name)
end
- def has_record?(project_id, name)
- where(project_id: project_id, name: name).exists?
+ def by_project_id(project_id)
+ where(project_id: project_id)
end
end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 0ffd5c446d3..42f362876bb 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -130,6 +130,10 @@ class Namespace < ApplicationRecord
to: :namespace_settings, allow_nil: true
delegate :show_diff_preview_in_email, :show_diff_preview_in_email?, :show_diff_preview_in_email=,
to: :namespace_settings
+ delegate :maven_package_requests_forwarding,
+ :pypi_package_requests_forwarding,
+ :npm_package_requests_forwarding,
+ to: :package_settings
after_save :reload_namespace_details
diff --git a/app/models/namespace/aggregation_schedule.rb b/app/models/namespace/aggregation_schedule.rb
index ed61c807519..cd7d4fc409a 100644
--- a/app/models/namespace/aggregation_schedule.rb
+++ b/app/models/namespace/aggregation_schedule.rb
@@ -6,13 +6,20 @@ class Namespace::AggregationSchedule < ApplicationRecord
self.primary_key = :namespace_id
- DEFAULT_LEASE_TIMEOUT = 1.5.hours.to_i
REDIS_SHARED_KEY = 'gitlab:update_namespace_statistics_delay'
belongs_to :namespace
after_create :schedule_root_storage_statistics
+ def self.default_lease_timeout
+ if Feature.enabled?(:remove_namespace_aggregator_delay)
+ 30.minutes.to_i
+ else
+ 1.hour.to_i
+ end
+ end
+
def schedule_root_storage_statistics
run_after_commit_or_now do
try_obtain_lease do
@@ -20,7 +27,7 @@ class Namespace::AggregationSchedule < ApplicationRecord
.perform_async(namespace_id)
Namespaces::RootStatisticsWorker
- .perform_in(DEFAULT_LEASE_TIMEOUT, namespace_id)
+ .perform_in(self.class.default_lease_timeout, namespace_id)
end
end
end
@@ -29,7 +36,7 @@ class Namespace::AggregationSchedule < ApplicationRecord
# Used by ExclusiveLeaseGuard
def lease_timeout
- DEFAULT_LEASE_TIMEOUT
+ self.class.default_lease_timeout
end
# Used by ExclusiveLeaseGuard
diff --git a/app/models/namespace/detail.rb b/app/models/namespace/detail.rb
index dbbf9f4944a..a5643ab9f79 100644
--- a/app/models/namespace/detail.rb
+++ b/app/models/namespace/detail.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class Namespace::Detail < ApplicationRecord
+ include IgnorableColumns
+
+ ignore_column :free_user_cap_over_limt_notified_at, remove_with: '15.7', remove_after: '2022-11-22'
+
belongs_to :namespace, inverse_of: :namespace_details
validates :namespace, presence: true
validates :description, length: { maximum: 255 }
diff --git a/app/models/namespace/package_setting.rb b/app/models/namespace/package_setting.rb
index 881b2f3acb3..22c3e41ff21 100644
--- a/app/models/namespace/package_setting.rb
+++ b/app/models/namespace/package_setting.rb
@@ -1,9 +1,15 @@
# frozen_string_literal: true
class Namespace::PackageSetting < ApplicationRecord
+ include CascadingNamespaceSettingAttribute
+
self.primary_key = :namespace_id
self.table_name = 'namespace_package_settings'
+ cascading_attr :maven_package_requests_forwarding
+ cascading_attr :npm_package_requests_forwarding
+ cascading_attr :pypi_package_requests_forwarding
+
PackageSettingNotImplemented = Class.new(StandardError)
PACKAGES_WITH_SETTINGS = %w[maven generic].freeze
diff --git a/app/models/note.rb b/app/models/note.rb
index daac489757b..e444111119b 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -22,6 +22,7 @@ class Note < ApplicationRecord
include ThrottledTouch
include FromUnion
include Sortable
+ include EachBatch
ISSUE_TASK_SYSTEM_NOTE_PATTERN = /\A.*marked\sthe\stask.+as\s(completed|incomplete).*\z/.freeze
@@ -693,7 +694,7 @@ class Note < ApplicationRecord
# Method necesary while we transition into the new format for task system notes
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923
def note
- return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
+ return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
super.sub!('task', 'checklist item')
end
@@ -701,11 +702,15 @@ class Note < ApplicationRecord
# Method necesary while we transition into the new format for task system notes
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923
def note_html
- return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
+ return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
super.sub!('task', 'checklist item')
end
+ def issuable_ability_name
+ confidential? ? :read_internal_note : :read_note
+ end
+
private
def system_note_viewable_by?(user)
diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb
index caa24377791..20d5a5ae1a1 100644
--- a/app/models/notification_recipient.rb
+++ b/app/models/notification_recipient.rb
@@ -97,8 +97,6 @@ class NotificationRecipient
end
def email_blocked?
- return false if Feature.disabled?(:block_emails_with_failures)
-
recipient_email = user.notification_email_for(@group)
Gitlab::ApplicationRateLimiter.peek(:permanent_email_failure, scope: recipient_email) ||
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index b4c09d99bb0..317db51f4ef 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -114,13 +114,18 @@ class Packages::Package < ApplicationRecord
)
end
+ scope :with_case_insensitive_version, ->(version) do
+ where('LOWER(version) = ?', version.downcase)
+ end
+
scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) }
scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) }
scope :without_package_type, ->(package_type) { where.not(package_type: package_type) }
scope :displayable, -> { with_status(DISPLAYABLE_STATUSES) }
- scope :including_project_route, -> { includes(project: { namespace: :route }) }
+ scope :including_project_route, -> { includes(project: :route) }
+ scope :including_project_namespace_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) }
scope :including_dependency_links, -> { includes(dependency_links: :dependency) }
diff --git a/app/models/packages/rpm/repository_file.rb b/app/models/packages/rpm/repository_file.rb
new file mode 100644
index 00000000000..4b5fa59c6ee
--- /dev/null
+++ b/app/models/packages/rpm/repository_file.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+module Packages
+ module Rpm
+ class RepositoryFile < ApplicationRecord
+ include EachBatch
+ include UpdateProjectStatistics
+ include FileStoreMounter
+ include Packages::Installable
+
+ INSTALLABLE_STATUSES = [:default].freeze
+
+ enum status: { default: 0, pending_destruction: 1, processing: 2, error: 3 }
+
+ belongs_to :project, inverse_of: :repository_files
+
+ validates :project, presence: true
+ validates :file, presence: true
+ validates :file_name, presence: true
+
+ mount_file_store_uploader Packages::Rpm::RepositoryFileUploader
+
+ update_project_statistics project_statistics_name: :packages_size
+ end
+ end
+end
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index e7d455085c0..c1056d4f6cb 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -32,7 +32,9 @@ module Pages
{
type: 'zip',
- path: deployment.file.url_or_file_path(expire_at: 1.day.from_now),
+ path: deployment.file.url_or_file_path(
+ expire_at: ::Gitlab::Pages::CacheControl::DEPLOYMENT_EXPIRATION.from_now
+ ),
global_id: global_id,
sha256: deployment.file_sha256,
file_size: deployment.size,
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 9ed25c56ed6..f0ed1822da6 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -5,6 +5,8 @@ class PersonalAccessToken < ApplicationRecord
include TokenAuthenticatable
include Sortable
include EachBatch
+ include CreatedAtFilterable
+ include Gitlab::SQL::Pattern
extend ::Gitlab::Utils::Override
add_authentication_token_field :token, digest: true
@@ -24,7 +26,6 @@ class PersonalAccessToken < ApplicationRecord
scope :expiring_and_not_notified, ->(date) { where(["revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= ?", date]) }
scope :expired_today_and_not_notified, -> { where(["revoked = false AND expires_at = CURRENT_DATE AND after_expiry_notification_delivered = false"]) }
scope :inactive, -> { where("revoked = true OR expires_at < CURRENT_DATE") }
- scope :created_before, -> (date) { where("personal_access_tokens.created_at < :date", date: date) }
scope :last_used_before_or_unused, -> (date) { where("personal_access_tokens.created_at < :date AND (last_used_at < :date OR last_used_at IS NULL)", date: date) }
scope :with_impersonation, -> { where(impersonation: true) }
scope :without_impersonation, -> { where(impersonation: false) }
@@ -38,6 +39,8 @@ class PersonalAccessToken < ApplicationRecord
scope :order_expires_at_asc_id_desc, -> { reorder(expires_at: :asc, id: :desc) }
scope :project_access_token, -> { includes(:user).where(user: { user_type: :project_bot }) }
scope :owner_is_human, -> { includes(:user).where(user: { user_type: :human }) }
+ scope :last_used_before, -> (date) { where("last_used_at <= ?", date) }
+ scope :last_used_after, -> (date) { where("last_used_at >= ?", date) }
validates :scopes, presence: true
validate :validate_scopes
@@ -90,6 +93,10 @@ class PersonalAccessToken < ApplicationRecord
Gitlab::CurrentSettings.current_application_settings.personal_access_token_prefix
end
+ def self.search(query)
+ fuzzy_search(query, [:name])
+ end
+
override :format_token
def format_token(token)
"#{self.class.token_prefix}#{token}"
diff --git a/app/models/preloaders/labels_preloader.rb b/app/models/preloaders/labels_preloader.rb
index 722d588d8bc..b6e73c1cd02 100644
--- a/app/models/preloaders/labels_preloader.rb
+++ b/app/models/preloaders/labels_preloader.rb
@@ -21,8 +21,10 @@ module Preloaders
def preload_all
preloader = ActiveRecord::Associations::Preloader.new
+ preloader.preload(labels, parent_container: :route)
preloader.preload(labels.select { |l| l.is_a? ProjectLabel }, { project: [:project_feature, namespace: :route] })
preloader.preload(labels.select { |l| l.is_a? GroupLabel }, { group: :route })
+
labels.each do |label|
label.lazy_subscription(user)
label.lazy_subscription(user, project) if project.present?
diff --git a/app/models/preloaders/project_root_ancestor_preloader.rb b/app/models/preloaders/project_root_ancestor_preloader.rb
index 8d04e71774c..1e935249407 100644
--- a/app/models/preloaders/project_root_ancestor_preloader.rb
+++ b/app/models/preloaders/project_root_ancestor_preloader.rb
@@ -21,7 +21,8 @@ module Preloaders
ActiveRecord::Associations::Preloader.new.preload(@projects, :namespace)
@projects.each do |project|
- project.namespace.root_ancestor = root_ancestors_by_id[project.id]&.first
+ root_ancestor = root_ancestors_by_id[project.id]&.first
+ project.namespace.root_ancestor = root_ancestor if root_ancestor.present?
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index c5fad189f87..7b61010ab01 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -32,7 +32,6 @@ class Project < ApplicationRecord
include FeatureGate
include OptionallySearch
include FromUnion
- include IgnorableColumns
include Repositories::CanHousekeepRepository
include EachBatch
include GitlabRoutingHelper
@@ -49,8 +48,6 @@ class Project < ApplicationRecord
BoardLimitExceeded = Class.new(StandardError)
ExportLimitExceeded = Class.new(StandardError)
- ignore_columns :build_coverage_regex, remove_after: '2022-10-22', remove_with: '15.5'
-
STATISTICS_ATTRIBUTE = 'repositories_count'
UNKNOWN_IMPORT_URL = 'http://unknown.git'
# Hashed Storage versions handle rolling out new storage to project and dependents models:
@@ -239,6 +236,9 @@ class Project < ApplicationRecord
# Packages
has_many :packages, class_name: 'Packages::Package'
has_many :package_files, through: :packages, class_name: 'Packages::PackageFile'
+ # repository_files must be destroyed by ruby code in order to properly remove carrierwave uploads
+ has_many :repository_files, inverse_of: :project, class_name: 'Packages::Rpm::RepositoryFile',
+ dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
# debian_distributions and associated component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
has_many :debian_distributions, class_name: 'Packages::Debian::ProjectDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :packages_cleanup_policy, class_name: 'Packages::Cleanup::Policy', inverse_of: :project
@@ -262,11 +262,11 @@ class Project < ApplicationRecord
has_many :source_of_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
has_many :issues
has_many :incident_management_issuable_escalation_statuses, through: :issues, inverse_of: :project, class_name: 'IncidentManagement::IssuableEscalationStatus'
+ has_many :incident_management_timeline_event_tags, inverse_of: :project, class_name: 'IncidentManagement::TimelineEventTag'
has_many :labels, class_name: 'ProjectLabel'
has_many :integrations
has_many :events
has_many :milestones
- has_many :iterations
# Projects with a very large number of notes may time out destroying them
# through the foreign key. Additionally, the deprecated attachment uploader
@@ -353,6 +353,7 @@ class Project < ApplicationRecord
has_many :stages, class_name: 'Ci::Stage', inverse_of: :project
has_many :ci_refs, class_name: 'Ci::Ref', inverse_of: :project
+ has_many :pipeline_metadata, class_name: 'Ci::PipelineMetadata', inverse_of: :project
has_many :pending_builds, class_name: 'Ci::PendingBuild'
has_many :builds, class_name: 'Ci::Build', inverse_of: :project
has_many :processables, class_name: 'Ci::Processable', inverse_of: :project
@@ -476,7 +477,8 @@ class Project < ApplicationRecord
delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true
delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
delegate :forward_deployment_enabled, :forward_deployment_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
- delegate :job_token_scope_enabled, :job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
+ delegate :job_token_scope_enabled, :job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci_outbound, allow_nil: true
+ delegate :inbound_job_token_scope_enabled, :inbound_job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
delegate :keep_latest_artifact, :keep_latest_artifact=, to: :ci_cd_settings, allow_nil: true
delegate :opt_in_jwt, :opt_in_jwt=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
delegate :allow_fork_pipelines_to_run_in_parent_project, :allow_fork_pipelines_to_run_in_parent_project=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
@@ -492,12 +494,17 @@ class Project < ApplicationRecord
delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
+ delegate :maven_package_requests_forwarding,
+ :pypi_package_requests_forwarding,
+ :npm_package_requests_forwarding,
+ to: :namespace
+
# Validations
validates :creator, presence: true, on: :create
validates :description, length: { maximum: 2000 }, allow_blank: true
validates :ci_config_path,
format: { without: %r{(\.{2}|\A/)},
- message: _('cannot include leading slash or directory traversal.') },
+ message: N_('cannot include leading slash or directory traversal.') },
length: { maximum: 255 },
allow_blank: true
validates :name,
@@ -693,13 +700,13 @@ class Project < ApplicationRecord
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
- default: 3600, error_message: _('Maximum job timeout has a value which could not be accepted')
+ default: 3600, error_message: N_('Maximum job timeout has a value which could not be accepted')
validates :build_timeout, allow_nil: true,
numericality: { greater_than_or_equal_to: 10.minutes,
less_than: MAX_BUILD_TIMEOUT,
only_integer: true,
- message: _('needs to be between 10 minutes and 1 month') }
+ message: N_('needs to be between 10 minutes and 1 month') }
# Used by Projects::CleanupService to hold a map of rewritten object IDs
mount_uploader :bfg_object_map, AttachmentUploader
@@ -1280,6 +1287,8 @@ class Project < ApplicationRecord
valid?(:import_url) || errors.messages[:import_url].nil?
end
+ # TODO: rename to build_or_assign_import_data as it doesn't save record
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/377319
def create_or_update_import_data(data: nil, credentials: nil)
return if data.nil? && credentials.nil?
@@ -2720,6 +2729,7 @@ class Project < ApplicationRecord
ci_config_path.blank? || ci_config_path == Gitlab::FileDetector::PATTERNS[:gitlab_ci]
end
+ # DO NOT USE. This method will be deprecated soon
def uses_external_project_ci_config?
!!(ci_config_path =~ %r{@.+/.+})
end
@@ -2844,6 +2854,7 @@ class Project < ApplicationRecord
repository.gitlab_ci_yml_for(sha, ci_config_path_or_default)
end
+ # DO NOT USE. This method will be deprecated soon
def ci_config_external_project
Project.find_by_full_path(ci_config_path.split('@', 2).last)
end
@@ -2886,12 +2897,18 @@ class Project < ApplicationRecord
ci_cd_settings.allow_fork_pipelines_to_run_in_parent_project?
end
- def ci_job_token_scope_enabled?
+ def ci_outbound_job_token_scope_enabled?
return false unless ci_cd_settings
ci_cd_settings.job_token_scope_enabled?
end
+ def ci_inbound_job_token_scope_enabled?
+ return false unless ci_cd_settings
+
+ ci_cd_settings.inbound_job_token_scope_enabled?
+ end
+
def restrict_user_defined_variables?
return false unless ci_cd_settings
@@ -2939,12 +2956,6 @@ 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
-
def enforced_runner_token_expiration_interval
all_parent_groups = Gitlab::ObjectHierarchy.new(Group.where(id: group)).base_and_ancestors
all_group_settings = NamespaceSetting.where(namespace_id: all_parent_groups)
@@ -3023,11 +3034,7 @@ class Project < ApplicationRecord
end
def packages_policy_subject
- if Feature.enabled?(:read_package_policy_rule, group)
- ::Packages::Policies::Project.new(self)
- else
- self
- end
+ ::Packages::Policies::Project.new(self)
end
def destroy_deployment_by_id(deployment_id)
@@ -3040,6 +3047,16 @@ class Project < ApplicationRecord
pages_domains.count < Gitlab::CurrentSettings.max_pages_custom_domains_per_project
end
+ # overridden in EE
+ def can_suggest_reviewers?
+ false
+ end
+
+ # overridden in EE
+ def suggested_reviewers_available?
+ false
+ end
+
private
# overridden in EE
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 5c6fdec16ca..8b43e5e5d63 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
class ProjectAuthorization < ApplicationRecord
+ BATCH_SIZE = 1000
+ SLEEP_DELAY = 0.1
+
extend SuppressCompositePrimaryKeyWarning
include FromUnion
@@ -26,11 +29,45 @@ class ProjectAuthorization < ApplicationRecord
super(attributes, unique_by: connection.schema_cache.primary_keys(table_name))
end
- def self.insert_all_in_batches(attributes, per_batch = 1000)
+ def self.insert_all_in_batches(attributes, per_batch = BATCH_SIZE)
+ add_delay = add_delay_between_batches?(entire_size: attributes.size, batch_size: per_batch)
+
attributes.each_slice(per_batch) do |attributes_batch|
insert_all(attributes_batch)
+ perform_delay if add_delay
+ end
+ end
+
+ def self.delete_all_in_batches_for_project(project:, user_ids:, per_batch: BATCH_SIZE)
+ add_delay = add_delay_between_batches?(entire_size: user_ids.size, batch_size: per_batch)
+
+ user_ids.each_slice(per_batch) do |user_ids_batch|
+ project.project_authorizations.where(user_id: user_ids_batch).delete_all
+ perform_delay if add_delay
+ end
+ end
+
+ def self.delete_all_in_batches_for_user(user:, project_ids:, per_batch: BATCH_SIZE)
+ add_delay = add_delay_between_batches?(entire_size: project_ids.size, batch_size: per_batch)
+
+ project_ids.each_slice(per_batch) do |project_ids_batch|
+ user.project_authorizations.where(project_id: project_ids_batch).delete_all
+ perform_delay if add_delay
end
end
+
+ private_class_method def self.add_delay_between_batches?(entire_size:, batch_size:)
+ # The reason for adding a delay is to give the replica database enough time to
+ # catch up with the primary when large batches of records are being added/removed.
+ # Hance, we add a delay only if the GitLab installation has a replica database configured.
+ entire_size > batch_size &&
+ !::Gitlab::Database::LoadBalancing.primary_only? &&
+ Feature.enabled?(:enable_minor_delay_during_project_authorizations_refresh)
+ end
+
+ private_class_method def self.perform_delay
+ sleep(SLEEP_DELAY)
+ end
end
ProjectAuthorization.prepend_mod_with('ProjectAuthorization')
diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb
index 38740aa20dd..d7a5d0d9d84 100644
--- a/app/models/project_ci_cd_setting.rb
+++ b/app/models/project_ci_cd_setting.rb
@@ -22,10 +22,6 @@ class ProjectCiCdSetting < ApplicationRecord
chronic_duration_attr :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval
- def forward_deployment_enabled?
- super && ::Feature.enabled?(:forward_deployment_enabled, project)
- end
-
def keep_latest_artifacts_available?
# The project level feature can only be enabled when the feature is enabled instance wide
Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact? && keep_latest_artifact?
diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb
index 2ba3c74df5b..9f9447c1de2 100644
--- a/app/models/project_group_link.rb
+++ b/app/models/project_group_link.rb
@@ -9,7 +9,7 @@ class ProjectGroupLink < ApplicationRecord
validates :project_id, presence: true
validates :group, presence: true
- validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") }
+ validates :group_id, uniqueness: { scope: [:project_id], message: N_("already shared with this group") }
validates :group_access, presence: true
validates :group_access, inclusion: { in: Gitlab::Access.values }, presence: true
validate :different_group
diff --git a/app/models/project_label.rb b/app/models/project_label.rb
index d0b16cc98b4..dc647901b46 100644
--- a/app/models/project_label.rb
+++ b/app/models/project_label.rb
@@ -4,6 +4,7 @@ class ProjectLabel < Label
MAX_NUMBER_OF_PRIORITIES = 1
belongs_to :project
+ belongs_to :parent_container, foreign_key: :project_id, class_name: 'Project'
validates :project, presence: true
diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb
index f5c346eda30..6d40544fad4 100644
--- a/app/models/project_setting.rb
+++ b/app/models/project_setting.rb
@@ -21,6 +21,7 @@ class ProjectSetting < ApplicationRecord
validates :merge_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
validates :squash_commit_template, length: { maximum: Project::MAX_COMMIT_TEMPLATE_LENGTH }
validates :target_platforms, inclusion: { in: ALLOWED_TARGET_PLATFORMS }
+ validates :suggested_reviewers_enabled, inclusion: { in: [true, false] }
validate :validates_mr_default_target_self
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index a91e0291438..f108e43015e 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -27,6 +27,16 @@ class ProjectStatistics < ApplicationRecord
snippets_size: %i[storage_size]
}.freeze
NAMESPACE_RELATABLE_COLUMNS = [:repository_size, :wiki_size, :lfs_objects_size, :uploads_size, :container_registry_size].freeze
+ STORAGE_SIZE_COMPONENTS = [
+ :repository_size,
+ :wiki_size,
+ :lfs_objects_size,
+ :build_artifacts_size,
+ :packages_size,
+ :snippets_size,
+ :pipeline_artifacts_size,
+ :uploads_size
+ ].freeze
scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
@@ -39,17 +49,18 @@ class ProjectStatistics < ApplicationRecord
def refresh!(only: [])
return if Gitlab::Database.read_only?
- COLUMNS_TO_REFRESH.each do |column, generator|
- if only.empty? || only.include?(column)
- public_send("update_#{column}") # rubocop:disable GitlabSecurity/PublicSend
- end
+ columns_to_update = only.empty? ? COLUMNS_TO_REFRESH : COLUMNS_TO_REFRESH & only
+ columns_to_update.each do |column|
+ public_send("update_#{column}") # rubocop:disable GitlabSecurity/PublicSend
end
if only.empty? || only.any? { |column| NAMESPACE_RELATABLE_COLUMNS.include?(column) }
schedule_namespace_aggregation_worker
end
- save!
+ detect_race_on_record(log_fields: { caller: __method__, attributes: columns_to_update }) do
+ save!
+ end
end
def update_commit_count
@@ -97,21 +108,13 @@ class ProjectStatistics < ApplicationRecord
end
def update_storage_size
- storage_size = repository_size +
- wiki_size +
- lfs_objects_size +
- build_artifacts_size +
- packages_size +
- snippets_size +
- pipeline_artifacts_size +
- uploads_size
-
- self.storage_size = storage_size
+ self.storage_size = storage_size_components.sum { |component| method(component).call }
end
def refresh_storage_size!
- update_storage_size
- save!
+ detect_race_on_record(log_fields: { caller: __method__, attributes: :storage_size }) do
+ update!(storage_size: storage_size_sum)
+ end
end
# Since this incremental update method does not call update_storage_size above through before_save,
@@ -129,35 +132,41 @@ class ProjectStatistics < ApplicationRecord
if counter_attribute_enabled?(key)
project_statistics.delayed_increment_counter(key, amount)
else
- legacy_increment_statistic(project, key, amount)
+ project_statistics.legacy_increment_statistic(key, amount)
end
end
end
- def self.legacy_increment_statistic(project, key, amount)
- where(project_id: project.id).columns_to_increment(key, amount)
+ def self.incrementable_attribute?(key)
+ INCREMENTABLE_COLUMNS.key?(key) || counter_attribute_enabled?(key)
+ end
+
+ def legacy_increment_statistic(key, amount)
+ increment_columns!(key, amount)
Namespaces::ScheduleAggregationWorker.perform_async( # rubocop: disable CodeReuse/Worker
project.namespace_id)
end
- def self.columns_to_increment(key, amount)
- updates = ["#{key} = COALESCE(#{key}, 0) + (#{amount})"]
-
- if (additional = INCREMENTABLE_COLUMNS[key])
- additional.each do |column|
- updates << "#{column} = COALESCE(#{column}, 0) + (#{amount})"
- end
- end
+ private
- update_all(updates.join(', '))
+ def storage_size_components
+ STORAGE_SIZE_COMPONENTS
end
- def self.incrementable_attribute?(key)
- INCREMENTABLE_COLUMNS.key?(key) || counter_attribute_enabled?(key)
+ def storage_size_sum
+ storage_size_components.map { |component| "COALESCE (#{component}, 0)" }.join(' + ').freeze
end
- private
+ def increment_columns!(key, amount)
+ increments = { key => amount }
+ additional = INCREMENTABLE_COLUMNS.fetch(key, [])
+ additional.each do |column|
+ increments[column] = amount
+ end
+
+ update_counters_with_lease(increments)
+ end
def schedule_namespace_aggregation_worker
run_after_commit do
diff --git a/app/models/projects/build_artifacts_size_refresh.rb b/app/models/projects/build_artifacts_size_refresh.rb
index e66e1d5b42f..2ffc7478178 100644
--- a/app/models/projects/build_artifacts_size_refresh.rb
+++ b/app/models/projects/build_artifacts_size_refresh.rb
@@ -80,9 +80,7 @@ module Projects
end
def reset_project_statistics!
- statistics = project.statistics
- statistics.update!(build_artifacts_size: 0)
- statistics.clear_counter!(:build_artifacts_size)
+ project.statistics.reset_counter!(:build_artifacts_size)
end
def next_batch(limit:)
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index b3a918d8952..dfd5c315f6e 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -95,6 +95,10 @@ class ProtectedBranch < ApplicationRecord
def self.downcase_humanized_name
name.underscore.humanize.downcase
end
+
+ def default_branch?
+ name == project.default_branch
+ end
end
ProtectedBranch.prepend_mod_with('ProtectedBranch')
diff --git a/app/models/protected_branch/merge_access_level.rb b/app/models/protected_branch/merge_access_level.rb
index de240e40316..df75c557717 100644
--- a/app/models/protected_branch/merge_access_level.rb
+++ b/app/models/protected_branch/merge_access_level.rb
@@ -2,4 +2,6 @@
class ProtectedBranch::MergeAccessLevel < ApplicationRecord
include ProtectedBranchAccess
+ # default value for the access_level column
+ GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER
end
diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb
index 5248834a2f2..6076fab20b7 100644
--- a/app/models/protected_branch/push_access_level.rb
+++ b/app/models/protected_branch/push_access_level.rb
@@ -2,6 +2,8 @@
class ProtectedBranch::PushAccessLevel < ApplicationRecord
include ProtectedBranchAccess
+ # default value for the access_level column
+ GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER
belongs_to :deploy_key
diff --git a/app/models/repository.rb b/app/models/repository.rb
index ee1bea0e8d2..3413b3e3424 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -48,22 +48,19 @@ class Repository
# For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `commit_count` cache key.
CACHED_METHODS = %i(size commit_count readme_path contribution_guide
- changelog license_blob license_key gitignore
+ changelog license_blob license_licensee license_gitaly gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref merged_branch_names
has_visible_content? issue_template_names_hash merge_request_template_names_hash
user_defined_metrics_dashboard_paths xcode_project? has_ambiguous_refs?).freeze
- # Methods that use cache_method but only memoize the value
- MEMOIZED_CACHED_METHODS = %i(license).freeze
-
# Certain method caches should be refreshed when certain types of files are
# changed. This Hash maps file types (as returned by Gitlab::FileDetector) to
# the corresponding methods to call for refreshing caches.
METHOD_CACHES_FOR_FILE_TYPES = {
readme: %i(readme_path),
changelog: :changelog,
- license: %i(license_blob license_key license),
+ license: %i(license_blob license_licensee license_gitaly),
contributing: :contribution_guide,
gitignore: :gitignore,
gitlab_ci: :gitlab_ci_yml,
@@ -650,25 +647,30 @@ class Repository
cache_method :license_blob
def license_key
- return unless exists?
-
- raw_repository.license_short_name
+ license&.key
end
- cache_method :license_key
def license
- return unless license_key
+ if Feature.enabled?(:license_from_gitaly)
+ license_gitaly
+ else
+ license_licensee
+ end
+ end
- licensee_object = Licensee::License.new(license_key)
+ def license_licensee
+ return unless exists?
- return if licensee_object.name.blank?
+ raw_repository.license(false)
+ end
+ cache_method :license_licensee
- licensee_object
- rescue Licensee::InvalidLicense => e
- Gitlab::ErrorTracking.track_exception(e)
- nil
+ def license_gitaly
+ return unless exists?
+
+ raw_repository.license(true)
end
- memoize_method :license
+ cache_method :license_gitaly
def gitignore
file_on_head(:gitignore)
@@ -787,8 +789,8 @@ class Repository
Commit.order_by(collection: commits, order_by: order_by, sort: sort)
end
- def branch_names_contains(sha)
- raw_repository.branch_names_contains_sha(sha)
+ def branch_names_contains(sha, limit: 0)
+ raw_repository.branch_names_contains_sha(sha, limit: limit)
end
def tag_names_contains(sha, limit: 0)
diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb
index 0a59d9cef9b..a1753df9294 100644
--- a/app/models/resource_label_event.rb
+++ b/app/models/resource_label_event.rb
@@ -115,7 +115,7 @@ class ResourceLabelEvent < ResourceEvent
end
def discussion_id_key
- [self.class.name, created_at, user_id]
+ [self.class.name, created_at.to_f, user_id]
end
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 9b7c37dd23e..9ec685c5580 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -350,7 +350,7 @@ class Snippet < ApplicationRecord
end
def can_cache_field?(field)
- field != :content || MarkupHelper.gitlab_markdown?(file_name)
+ field != :content || Gitlab::MarkupHelper.gitlab_markdown?(file_name)
end
def hexdigest
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 941d0394b94..c6adf5c263c 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Tree
- include Gitlab::MarkupHelper
include Gitlab::Utils::StrongMemoize
attr_accessor :repository, :sha, :path, :entries, :cursor
@@ -24,11 +23,11 @@ class Tree
end
previewable_readmes = available_readmes.select do |blob|
- previewable?(blob.name)
+ Gitlab::MarkupHelper.previewable?(blob.name)
end
plain_readmes = available_readmes.select do |blob|
- plain?(blob.name)
+ Gitlab::MarkupHelper.plain?(blob.name)
end
# Prioritize previewable over plain readmes
diff --git a/app/models/user.rb b/app/models/user.rb
index 3f07e1b1ec0..6d198fc755b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -60,7 +60,7 @@ class User < ApplicationRecord
default_value_for :admin, false
default_value_for(:external) { Gitlab::CurrentSettings.user_default_external }
- default_value_for :can_create_group, gitlab_config.default_can_create_group
+ default_value_for(:can_create_group) { Gitlab::CurrentSettings.can_create_group }
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
default_value_for :hide_no_password, false
@@ -79,6 +79,7 @@ class User < ApplicationRecord
otp_secret_encryption_key: Gitlab::Application.secrets.otp_key_base
devise :two_factor_backupable, otp_number_of_backup_codes: 10
+ devise :two_factor_backupable_pbkdf2
serialize :otp_backup_codes, JSON # rubocop:disable Cop/ActiveRecordSerialize
devise :lockable, :recoverable, :rememberable, :trackable,
@@ -168,6 +169,10 @@ class User < ApplicationRecord
through: :group_members,
source: :group
alias_attribute :masters_groups, :maintainers_groups
+ has_many :developer_maintainer_owned_groups,
+ -> { where(members: { access_level: [Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER] }) },
+ through: :group_members,
+ source: :group
has_many :reporter_developer_maintainer_owned_groups,
-> { where(members: { access_level: [Gitlab::Access::REPORTER, Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER] }) },
through: :group_members,
@@ -193,6 +198,10 @@ class User < ApplicationRecord
has_many :snippets, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :notes, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
+ has_many :legacy_assigned_merge_requests, class_name: 'MergeRequest', dependent: :nullify, foreign_key: :assignee_id # rubocop:disable Cop/ActiveRecordDependent
+ has_many :merged_merge_requests, class_name: 'MergeRequest::Metrics', dependent: :nullify, foreign_key: :merged_by_id # rubocop:disable Cop/ActiveRecordDependent
+ has_many :closed_merge_requests, class_name: 'MergeRequest::Metrics', dependent: :nullify, foreign_key: :latest_closed_by_id # rubocop:disable Cop/ActiveRecordDependent
+ has_many :updated_merge_requests, class_name: 'MergeRequest', dependent: :nullify, foreign_key: :updated_by_id # rubocop:disable Cop/ActiveRecordDependent
has_many :updated_issues, class_name: 'Issue', dependent: :nullify, foreign_key: :updated_by_id # rubocop:disable Cop/ActiveRecordDependent
has_many :closed_issues, class_name: 'Issue', dependent: :nullify, foreign_key: :closed_by_id # rubocop:disable Cop/ActiveRecordDependent
has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
@@ -205,14 +214,15 @@ class User < ApplicationRecord
has_many :spam_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :builds, class_name: 'Ci::Build'
has_many :pipelines, class_name: 'Ci::Pipeline'
- has_many :todos
+ has_many :todos, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :authored_todos, class_name: 'Todo', dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :notification_settings
has_many :award_emoji, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :triggers, class_name: 'Ci::Trigger', foreign_key: :owner_id
has_many :issue_assignees, inverse_of: :assignee
- has_many :merge_request_assignees, inverse_of: :assignee
- has_many :merge_request_reviewers, inverse_of: :reviewer
+ has_many :merge_request_assignees, inverse_of: :assignee, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :merge_request_reviewers, inverse_of: :reviewer, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :assigned_issues, class_name: "Issue", through: :issue_assignees, source: :issue
has_many :assigned_merge_requests, class_name: "MergeRequest", through: :merge_request_assignees, source: :merge_request
has_many :created_custom_emoji, class_name: 'CustomEmoji', inverse_of: :creator
@@ -223,7 +233,6 @@ class User < ApplicationRecord
has_many :callouts, class_name: 'Users::Callout'
has_many :group_callouts, class_name: 'Users::GroupCallout'
has_many :project_callouts, class_name: 'Users::ProjectCallout'
- has_many :namespace_callouts, class_name: 'Users::NamespaceCallout'
has_many :term_agreements
belongs_to :accepted_term, class_name: 'ApplicationSetting::Term'
@@ -235,6 +244,7 @@ class User < ApplicationRecord
has_one :user_highest_role
has_one :user_canonical_email
has_one :credit_card_validation, class_name: '::Users::CreditCardValidation'
+ has_one :phone_number_validation, class_name: '::Users::PhoneNumberValidation'
has_one :atlassian_identity, class_name: 'Atlassian::Identity'
has_one :banned_user, class_name: '::Users::BannedUser'
@@ -245,6 +255,8 @@ class User < ApplicationRecord
has_many :timelogs
has_many :resource_label_events, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
+ has_many :resource_state_events, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
+ has_many :authored_events, class_name: 'Event', dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
#
# Validations
@@ -274,10 +286,10 @@ class User < ApplicationRecord
validate :check_username_format, if: :username_changed?
validates :theme_id, allow_nil: true, inclusion: { in: Gitlab::Themes.valid_ids,
- message: _("%{placeholder} is not a valid theme") % { placeholder: '%{value}' } }
+ message: ->(*) { _("%{placeholder} is not a valid theme") % { placeholder: '%{value}' } } }
validates :color_scheme_id, allow_nil: true, inclusion: { in: Gitlab::ColorSchemes.valid_ids,
- message: _("%{placeholder} is not a valid color scheme") % { placeholder: '%{value}' } }
+ message: ->(*) { _("%{placeholder} is not a valid color scheme") % { placeholder: '%{value}' } } }
validates :website_url, allow_blank: true, url: true, if: :website_url_changed?
@@ -289,6 +301,7 @@ class User < ApplicationRecord
before_save :check_for_verified_email, if: ->(user) { user.email_changed? && !user.new_record? }
before_validation :ensure_namespace_correct
before_save :ensure_namespace_correct # in case validation is skipped
+ before_save :ensure_user_detail_assigned
after_validation :set_username_errors
after_update :username_changed_hook, if: :saved_change_to_username?
after_destroy :post_destroy_hook
@@ -338,8 +351,10 @@ class User < ApplicationRecord
:setup_for_company, :setup_for_company=,
:render_whitespace_in_code, :render_whitespace_in_code=,
:markdown_surround_selection, :markdown_surround_selection=,
+ :markdown_automatic_lists, :markdown_automatic_lists=,
:diffs_deletion_color, :diffs_deletion_color=,
:diffs_addition_color, :diffs_addition_color=,
+ :use_legacy_web_ide, :use_legacy_web_ide=,
to: :user_preference
delegate :path, to: :namespace, allow_nil: true, prefix: true
@@ -934,6 +949,7 @@ class User < ApplicationRecord
# that the password is the user's password
def valid_password?(password)
return false unless password_allowed?(password)
+ return false if password_automatically_set?
return super if Feature.enabled?(:pbkdf2_password_encryption)
Devise::Encryptor.compare(self.class, encrypted_password, password)
@@ -943,6 +959,22 @@ class User < ApplicationRecord
false
end
+ def generate_otp_backup_codes!
+ if Gitlab::FIPS.enabled?
+ generate_otp_backup_codes_pbkdf2!
+ else
+ super
+ end
+ end
+
+ def invalidate_otp_backup_code!(code)
+ if Gitlab::FIPS.enabled? && pbkdf2?
+ invalidate_otp_backup_code_pdkdf2!(code)
+ else
+ super(code)
+ end
+ end
+
# This method should be removed once the :pbkdf2_password_encryption feature flag is removed.
def password=(new_password)
if Feature.enabled?(:pbkdf2_password_encryption) && Feature.enabled?(:pbkdf2_password_encryption_write, self)
@@ -1129,12 +1161,6 @@ class User < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
- def remove_project_authorizations(project_ids, per_batch = 1000)
- project_ids.each_slice(per_batch) do |project_ids_batch|
- project_authorizations.where(project_id: project_ids_batch).delete_all
- end
- end
-
def authorized_projects(min_access_level = nil)
# We're overriding an association, so explicitly call super with no
# arguments or it would be passed as `force_reload` to the association
@@ -1565,6 +1591,11 @@ class User < ApplicationRecord
end
end
+ # Temporary, will be removed when user_detail fields are fully migrated
+ def ensure_user_detail_assigned
+ user_detail.assign_changed_fields_from_user if UserDetail.user_fields_changed?(self)
+ end
+
def set_username_errors
namespace_path_errors = self.errors.delete(:"namespace.path")
@@ -1647,8 +1678,9 @@ class User < ApplicationRecord
begin
followee = Users::UserFollowUser.create(follower_id: self.id, followee_id: user.id)
self.followees.reset if followee.persisted?
+ followee
rescue ActiveRecord::RecordNotUnique
- false
+ nil
end
end
@@ -1737,7 +1769,7 @@ class User < ApplicationRecord
end
def authorized_project_mirrors(level)
- projects = Ci::ProjectMirror.by_project_id(ci_project_mirrors_for_project_members(level))
+ projects = Ci::ProjectMirror.by_project_id(ci_project_ids_for_project_members(level))
namespace_projects = Ci::ProjectMirror.by_namespace_id(ci_namespace_mirrors_for_group_members(level).select(:namespace_id))
@@ -2075,14 +2107,6 @@ class User < ApplicationRecord
callout_dismissed?(callout, ignore_dismissal_earlier_than)
end
- # Deprecated: do not use. See: https://gitlab.com/gitlab-org/gitlab/-/issues/371017
- def dismissed_callout_for_namespace?(feature_name:, namespace:, ignore_dismissal_earlier_than: nil)
- source_feature_name = "#{feature_name}_#{namespace.id}"
- callout = namespace_callouts_by_feature_name[source_feature_name]
-
- callout_dismissed?(callout, ignore_dismissal_earlier_than)
- end
-
def dismissed_callout_for_project?(feature_name:, project:, ignore_dismissal_earlier_than: nil)
callout = project_callouts.find_by(feature_name: feature_name, project: project)
@@ -2115,11 +2139,6 @@ class User < ApplicationRecord
.find_or_initialize_by(feature_name: ::Users::GroupCallout.feature_names[feature_name], group_id: group_id)
end
- def find_or_initialize_namespace_callout(feature_name, namespace_id)
- namespace_callouts
- .find_or_initialize_by(feature_name: ::Users::NamespaceCallout.feature_names[feature_name], namespace_id: namespace_id)
- end
-
def find_or_initialize_project_callout(feature_name, project_id)
project_callouts
.find_or_initialize_by(feature_name: ::Users::ProjectCallout.feature_names[feature_name], project_id: project_id)
@@ -2198,6 +2217,12 @@ class User < ApplicationRecord
private
+ def pbkdf2?
+ return false unless otp_backup_codes&.any?
+
+ otp_backup_codes.first.start_with?("$pbkdf2-sha512$")
+ end
+
# To enable JiHu repository to modify the default language options
def default_preferred_language
'en'
@@ -2209,7 +2234,7 @@ class User < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
- def ci_project_mirrors_for_project_members(level)
+ def ci_project_ids_for_project_members(level)
project_members.where('access_level >= ?', level).pluck(:source_id)
end
@@ -2246,10 +2271,6 @@ class User < ApplicationRecord
@group_callouts_by_feature_name ||= group_callouts.index_by(&:source_feature_name)
end
- def namespace_callouts_by_feature_name
- @namespace_callouts_by_feature_name ||= namespace_callouts.index_by(&:source_feature_name)
- end
-
def authorized_groups_without_shared_membership
Group.from_union(
[
@@ -2298,7 +2319,7 @@ class User < ApplicationRecord
self.projects_limit = 0
else
# Only revert these back to the default if they weren't specifically changed in this update.
- self.can_create_group = gitlab_config.default_can_create_group unless can_create_group_changed?
+ self.can_create_group = Gitlab::CurrentSettings.can_create_group unless can_create_group_changed?
self.projects_limit = Gitlab::CurrentSettings.default_projects_limit unless projects_limit_changed?
end
end
@@ -2363,7 +2384,7 @@ class User < ApplicationRecord
end
def ci_owned_project_runners_from_project_members
- project_ids = ci_project_mirrors_for_project_members(Gitlab::Access::MAINTAINER)
+ project_ids = ci_project_ids_for_project_members(Gitlab::Access::MAINTAINER)
Ci::Runner
.joins(:runner_projects)
diff --git a/app/models/user_detail.rb b/app/models/user_detail.rb
index b9b69d12729..2e662faea6a 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 :other_role, remove_after: '2022-07-22', remove_with: '15.3'
REGISTRATION_OBJECTIVE_PAIRS = { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5, joining_team: 6 }.freeze
@@ -15,15 +12,55 @@ class UserDetail < ApplicationRecord
validates :job_title, length: { maximum: 200 }
validates :bio, length: { maximum: 255 }, allow_blank: true
+ DEFAULT_FIELD_LENGTH = 500
+
+ validates :linkedin, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
+ validates :twitter, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
+ validates :skype, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
+ validates :location, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
+ validates :organization, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
+ validates :website_url, length: { maximum: DEFAULT_FIELD_LENGTH }, url: true, allow_blank: true
+
+ before_validation :sanitize_attrs
before_save :prevent_nil_bio
enum registration_objective: REGISTRATION_OBJECTIVE_PAIRS, _suffix: true
+ def self.user_fields_changed?(user)
+ (%w[linkedin skype twitter website_url location organization] & user.changed).any?
+ end
+
+ def sanitize_attrs
+ %i[linkedin skype twitter website_url].each do |attr|
+ value = self[attr]
+ self[attr] = Sanitize.clean(value) if value.present?
+ end
+ %i[location organization].each do |attr|
+ value = self[attr]
+ self[attr] = Sanitize.clean(value).gsub('&amp;', '&') if value.present?
+ end
+ end
+
+ def assign_changed_fields_from_user
+ self.linkedin = trim_field(user.linkedin) if user.linkedin_changed?
+ self.twitter = trim_field(user.twitter) if user.twitter_changed?
+ self.skype = trim_field(user.skype) if user.skype_changed?
+ self.website_url = trim_field(user.website_url) if user.website_url_changed?
+ self.location = trim_field(user.location) if user.location_changed?
+ self.organization = trim_field(user.organization) if user.organization_changed?
+ end
+
private
def prevent_nil_bio
self.bio = '' if bio_changed? && bio.nil?
end
+
+ def trim_field(value)
+ return '' unless value
+
+ value.first(DEFAULT_FIELD_LENGTH)
+ end
end
UserDetail.prepend_mod_with('UserDetail')
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 9b4c0a2527a..c6ebd550daf 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -22,6 +22,7 @@ class UserPreference < ApplicationRecord
validates :diffs_deletion_color, :diffs_addition_color,
format: { with: ColorsHelper::HEX_COLOR_PATTERN },
allow_blank: true
+ validates :use_legacy_web_ide, allow_nil: false, inclusion: { in: [true, false] }
ignore_columns :experience_level, remove_with: '14.10', remove_after: '2021-03-22'
@@ -29,7 +30,6 @@ class UserPreference < ApplicationRecord
default_value_for :time_display_relative, value: true, allows_nil: false
default_value_for :time_format_in_24h, value: false, allows_nil: false
default_value_for :render_whitespace_in_code, value: false, allows_nil: false
- default_value_for :markdown_surround_selection, value: true, allows_nil: false
class << self
def notes_filters
diff --git a/app/models/users/banned_user.rb b/app/models/users/banned_user.rb
index c52b6d4b728..615668e2b55 100644
--- a/app/models/users/banned_user.rb
+++ b/app/models/users/banned_user.rb
@@ -7,6 +7,6 @@ module Users
belongs_to :user
validates :user, presence: true
- validates :user_id, uniqueness: { message: _("banned user already exists") }
+ validates :user_id, uniqueness: { message: N_("banned user already exists") }
end
end
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
index 03841ee48fa..ae6950d800c 100644
--- a/app/models/users/callout.rb
+++ b/app/models/users/callout.rb
@@ -61,7 +61,8 @@ module Users
namespace_storage_limit_banner_alert_threshold: 57, # EE-only
namespace_storage_limit_banner_error_threshold: 58, # EE-only
project_quality_summary_feedback: 59, # EE-only
- merge_request_settings_moved_callout: 60
+ merge_request_settings_moved_callout: 60,
+ new_top_level_group_alert: 61
}
validates :feature_name,
diff --git a/app/models/users/namespace_callout.rb b/app/models/users/namespace_callout.rb
deleted file mode 100644
index 4e655a96b57..00000000000
--- a/app/models/users/namespace_callout.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class NamespaceCallout < ApplicationRecord
- include Users::Calloutable
-
- self.table_name = 'user_namespace_callouts'
-
- belongs_to :namespace
-
- enum feature_name: {
- invite_members_banner: 1,
- approaching_seat_count_threshold: 2, # EE-only
- storage_enforcement_banner_first_enforcement_threshold: 3, # EE-only
- storage_enforcement_banner_second_enforcement_threshold: 4, # EE-only
- storage_enforcement_banner_third_enforcement_threshold: 5, # EE-only
- storage_enforcement_banner_fourth_enforcement_threshold: 6, # EE-only
- preview_user_over_limit_free_plan_alert: 7, # EE-only
- user_reached_limit_free_plan_alert: 8, # EE-only
- web_hook_disabled: 9
- }
-
- validates :namespace, presence: true
- validates :feature_name,
- presence: true,
- uniqueness: { scope: [:user_id, :namespace_id] },
- inclusion: { in: NamespaceCallout.feature_names.keys }
-
- def source_feature_name
- "#{feature_name}_#{namespace_id}"
- end
- end
-end
diff --git a/app/models/users/phone_number_validation.rb b/app/models/users/phone_number_validation.rb
new file mode 100644
index 00000000000..f6123c01fd0
--- /dev/null
+++ b/app/models/users/phone_number_validation.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Users
+ class PhoneNumberValidation < ApplicationRecord
+ self.primary_key = :user_id
+ self.table_name = 'user_phone_number_validations'
+
+ belongs_to :user, foreign_key: :user_id
+ belongs_to :banned_user, class_name: '::Users::BannedUser', foreign_key: :user_id
+
+ validates :country,
+ presence: true,
+ length: { maximum: 3 }
+
+ validates :international_dial_code,
+ presence: true,
+ numericality: {
+ only_integer: true,
+ greater_than_or_equal_to: 1,
+ less_than_or_equal_to: 999
+ }
+
+ validates :phone_number,
+ presence: true,
+ format: {
+ with: /\A\d+\Z/,
+ message: -> (object, data) { _('can contain only digits') }
+ },
+ length: { maximum: 12 }
+
+ validates :telesign_reference_xid,
+ length: { maximum: 255 }
+
+ def self.related_to_banned_user?(international_dial_code, phone_number)
+ joins(:banned_user).where(
+ international_dial_code: international_dial_code,
+ phone_number: phone_number
+ ).exists?
+ end
+ end
+end
diff --git a/app/models/users/project_callout.rb b/app/models/users/project_callout.rb
index 98dacbe394a..c73b3a4ee71 100644
--- a/app/models/users/project_callout.rb
+++ b/app/models/users/project_callout.rb
@@ -11,7 +11,11 @@ module Users
enum feature_name: {
awaiting_members_banner: 1, # EE-only
web_hook_disabled: 2,
- ultimate_feature_removal_banner: 3
+ ultimate_feature_removal_banner: 3,
+ storage_enforcement_banner_first_enforcement_threshold: 4, # EE-only
+ storage_enforcement_banner_second_enforcement_threshold: 5, # EE-only
+ storage_enforcement_banner_third_enforcement_threshold: 6, # EE-only
+ storage_enforcement_banner_fourth_enforcement_threshold: 7 # EE-only
}
validates :project, presence: true
diff --git a/app/models/users/user_follow_user.rb b/app/models/users/user_follow_user.rb
index a94239a746c..5a82a81364a 100644
--- a/app/models/users/user_follow_user.rb
+++ b/app/models/users/user_follow_user.rb
@@ -1,7 +1,22 @@
# frozen_string_literal: true
module Users
class UserFollowUser < ApplicationRecord
+ MAX_FOLLOWEE_LIMIT = 300
+
belongs_to :follower, class_name: 'User'
belongs_to :followee, class_name: 'User'
+
+ validate :max_follow_limit
+
+ private
+
+ def max_follow_limit
+ followee_count = self.class.where(follower_id: follower_id).limit(MAX_FOLLOWEE_LIMIT).count
+ return if followee_count < MAX_FOLLOWEE_LIMIT
+
+ errors.add(:base, format(
+ _("You can't follow more than %{limit} users. To follow more users, unfollow some others."),
+ limit: MAX_FOLLOWEE_LIMIT))
+ end
end
end
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index fac79a8194a..b718c3a096f 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -9,6 +9,8 @@ class Wiki
extend ActiveModel::Naming
+ DuplicatePageError = Class.new(StandardError)
+
MARKUPS = { # rubocop:disable Style/MultilineIfModifier
markdown: {
name: 'Markdown',
@@ -109,11 +111,34 @@ class Wiki
end
def sluggified_title(title)
- title = Gitlab::EncodingHelper.encode_utf8_no_detect(title)
- title = File.expand_path(title, '/')
+ title = Gitlab::EncodingHelper.encode_utf8_no_detect(title.to_s.strip)
+ title = File.absolute_path(title, '/')
title = Pathname.new(title).relative_path_from('/').to_s
title.tr(' ', '-')
end
+
+ def canonicalize_filename(filename)
+ ::File.basename(filename, ::File.extname(filename)).tr('-', ' ')
+ end
+
+ def cname(name, char_white_sub = '-', char_other_sub = '-')
+ name.to_s.gsub(/\s/, char_white_sub).gsub(/[<>+]/, char_other_sub)
+ end
+
+ def preview_slug(title, format)
+ ext = format == :markdown ? "md" : format.to_s
+ name = cname(title) + '.' + ext
+ canonical_name = canonicalize_filename(name)
+
+ path =
+ if name.include?('/')
+ name.sub(%r{/[^/]+$}, '/')
+ else
+ ''
+ end
+
+ path + cname(canonical_name, '-', '-')
+ end
end
def initialize(container, user = nil)
@@ -145,14 +170,6 @@ class Wiki
container.path + '.wiki'
end
- # Returns the Gitlab::Git::Wiki object.
- def wiki
- strong_memoize(:wiki) do
- create_wiki_repository
- Gitlab::Git::Wiki.new(repository.raw)
- end
- end
-
def create_wiki_repository
repository.create_if_not_exists(default_branch)
@@ -173,7 +190,7 @@ class Wiki
end
def empty?
- !repository_exists? || list_pages(limit: 1).empty?
+ !repository_exists? || list_page_paths.empty?
end
def exists?
@@ -190,15 +207,9 @@ class Wiki
#
# Returns an Array of GitLab WikiPage instances or an
# empty Array if this Wiki has no pages.
- def list_pages(limit: 0, sort: nil, direction: DIRECTION_ASC, load_content: false)
- wiki.list_pages(
- limit: limit,
- sort: sort,
- direction_desc: direction == DIRECTION_DESC,
- load_content: load_content
- ).map do |page|
- WikiPage.new(self, page)
- end
+ def list_pages(limit: 0, direction: DIRECTION_ASC, load_content: false)
+ create_wiki_repository unless repository_exists?
+ list_pages_with_repository_rpcs(limit: limit, direction: direction, load_content: load_content)
end
def sidebar_entries(limit: Gitlab::WikiPages::MAX_SIDEBAR_PAGES, **options)
@@ -217,19 +228,15 @@ class Wiki
#
# Returns an initialized WikiPage instance or nil
def find_page(title, version = nil, load_content: true)
- if find_page_with_repository_rpcs?
- create_wiki_repository unless repository_exists?
- find_page_with_repository_rpcs(title, version, load_content: load_content)
- else
- find_page_with_legacy_wiki_service(title, version, load_content: load_content)
- end
+ create_wiki_repository unless repository_exists?
+ find_page_with_repository_rpcs(title, version, load_content: load_content)
end
def find_sidebar(version = nil)
find_page(SIDEBAR, version)
end
- def find_file(name, version = 'HEAD', load_content: true)
+ def find_file(name, version = default_branch, load_content: true)
data_limit = load_content ? -1 : 0
blobs = repository.blobs_at([[version, name]], blob_size_limit: data_limit)
@@ -256,7 +263,7 @@ class Wiki
raise_duplicate_page_error!
end
end
- rescue Gitlab::Git::Wiki::DuplicatePageError => e
+ rescue DuplicatePageError => e
@error_message = _("Duplicate page: %{error_message}" % { error_message: e.message })
false
@@ -272,6 +279,7 @@ class Wiki
extension = page.format != format.to_sym ? default_extension : File.extname(page.path).downcase[1..]
capture_git_error(:updated) do
+ create_wiki_repository unless repository_exists?
repository.update_file(
user,
sluggified_full_path(title, extension),
@@ -290,6 +298,7 @@ class Wiki
return unless page
capture_git_error(:deleted) do
+ create_wiki_repository unless repository_exists?
repository.delete_file(user, page.path, **multi_commit_options(:deleted, message, page.title))
after_wiki_activity
@@ -306,8 +315,10 @@ class Wiki
[title, title_array.join("/")]
end
+ # TODO: This method is redundant. Should be replaced by create_wiki_repository
def ensure_repository
- raise CouldNotCreateWikiError unless wiki.repository_exists?
+ create_wiki_repository
+ raise CouldNotCreateWikiError unless repository_exists?
end
def hook_attrs
@@ -343,7 +354,7 @@ class Wiki
override :default_branch
def default_branch
- super || Gitlab::Git::Wiki.default_ref(container)
+ super || Gitlab::DefaultBranch.value(object: container)
end
def wiki_base_path
@@ -423,11 +434,11 @@ class Wiki
escaped_title = Regexp.escape(sluggified_title(title))
regex = Regexp.new("^#{escaped_title}\.#{ALLOWED_EXTENSIONS_REGEX}$", 'i')
- repository.ls_files('HEAD').any? { |s| s =~ regex }
+ repository.ls_files(default_branch).any? { |s| s =~ regex }
end
def raise_duplicate_page_error!
- raise Gitlab::Git::Wiki::DuplicatePageError, _('A page with that title already exists')
+ raise ::Wiki::DuplicatePageError, _('A page with that title already exists')
end
def sluggified_full_path(title, extension)
@@ -439,27 +450,12 @@ class Wiki
end
def canonicalize_filename(filename)
- Gitlab::Git::Wiki::GollumSlug.canonicalize_filename(filename)
- end
-
- def find_page_with_legacy_wiki_service(title, version, load_content: false)
- page_title, page_dir = page_title_and_dir(title)
-
- if page = wiki.page(title: page_title, version: version, dir: page_dir, load_content: load_content)
- WikiPage.new(self, page)
- end
+ self.class.canonicalize_filename(filename)
end
def find_matched_file(title, version)
escaped_path = RE2::Regexp.escape(sluggified_title(title))
- # We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with
- # Regexp.union. The result combination complicated modifiers:
- # /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../
- # Regexp used by Gitaly is Go's Regexp package. It does not support those
- # features. So, we have to compose another more-friendly regexp to pass to
- # Gitaly side.
- extension_regexp = Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|")
- path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{extension_regexp})$")
+ path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{file_extension_regexp})$")
matched_files = repository.search_files_by_regexp(path_regexp, version)
return if matched_files.blank?
@@ -473,11 +469,11 @@ class Wiki
end
def check_page_historical(path, commit)
- repository.last_commit_for_path('HEAD', path).id != commit.id
+ repository.last_commit_for_path(default_branch, path)&.id != commit&.id
end
def find_page_with_repository_rpcs(title, version, load_content: true)
- version = version.presence || 'HEAD'
+ version = version.presence || default_branch
path = find_matched_file(title, version)
return if path.blank?
@@ -487,27 +483,81 @@ class Wiki
format = find_page_format(path)
page = Gitlab::Git::WikiPage.new(
- url_path: sluggified_title(path.sub(/\.[^.]+\z/, "")),
+ url_path: sluggified_title(strip_extension(path)),
title: canonicalize_filename(path),
format: format,
path: sluggified_title(path),
raw_data: blob.data,
name: canonicalize_filename(path),
- historical: version == 'HEAD' ? false : check_page_historical(path, commit),
+ historical: version == default_branch ? false : check_page_historical(path, commit),
version: Gitlab::Git::WikiPageVersion.new(commit, format)
)
WikiPage.new(self, page)
end
- def find_page_with_repository_rpcs?
- group =
- if container.is_a?(::Group)
- container
- else
- container.group
- end
+ def file_extension_regexp
+ # We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with
+ # Regexp.union. The result combination complicated modifiers:
+ # /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../
+ # Regexp used by Gitaly is Go's Regexp package. It does not support those
+ # features. So, we have to compose another more-friendly regexp to pass to
+ # Gitaly side.
+ Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|")
+ end
+
+ def strip_extension(path)
+ path.sub(/\.[^.]+\z/, "")
+ end
- Feature.enabled?(:wiki_find_page_with_normal_repository_rpcs, group, type: :development)
+ def list_page_paths
+ return [] if repository.empty?
+
+ path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)\\.(#{file_extension_regexp})$")
+ repository.search_files_by_regexp(path_regexp, default_branch)
+ end
+
+ def list_pages_with_repository_rpcs(limit:, direction:, load_content:)
+ paths = list_page_paths
+ return [] if paths.empty?
+
+ pages = paths.map do |path|
+ page = Gitlab::Git::WikiPage.new(
+ url_path: sluggified_title(strip_extension(path)),
+ title: canonicalize_filename(path),
+ format: find_page_format(path),
+ path: sluggified_title(path),
+ raw_data: '',
+ name: canonicalize_filename(path),
+ historical: false
+ )
+ WikiPage.new(self, page)
+ end
+ sort_pages!(pages, direction)
+ pages = pages.take(limit) if limit > 0
+ fetch_pages_content!(pages) if load_content
+
+ pages
+ end
+
+ # After migrating to normal repository RPCs, it's very expensive to sort the
+ # pages by created_at. We have to either ListLastCommitsForTree RPC call or
+ # N+1 LastCommitForPath. Either are efficient for a large repository.
+ # Therefore, we decide to sort the title only.
+ def sort_pages!(pages, direction)
+ # Sort by path to ensure the files inside a sub-folder are grouped and sorted together
+ pages.sort_by!(&:path)
+ pages.reverse! if direction == DIRECTION_DESC
+ end
+
+ def fetch_pages_content!(pages)
+ blobs =
+ repository
+ .blobs_at(pages.map { |page| [default_branch, page.path] } )
+ .to_h { |blob| [blob.path, blob.data] }
+
+ pages.each do |page|
+ page.raw_content = blobs[page.path]
+ end
end
end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 63c60f5a89e..24b0b94eeb7 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -73,7 +73,7 @@ class WikiPage
# The escaped URL path of this page.
def slug
- attributes[:slug].presence || wiki.wiki.preview_slug(title, format)
+ attributes[:slug].presence || ::Wiki.preview_slug(title, format)
end
alias_method :id, :slug # required to use build_stubbed
@@ -99,6 +99,13 @@ class WikiPage
attributes[:content] ||= page&.text_data
end
+ def raw_content=(content)
+ return if page.nil?
+
+ page.raw_data = content
+ attributes[:content] = page.text_data
+ end
+
# The hierarchy of the directory this page is contained in.
def directory
wiki.page_title_and_dir(slug)&.last.to_s
@@ -118,7 +125,7 @@ class WikiPage
def version
return unless persisted?
- @version ||= @page.version
+ @version ||= @page.version || last_version
end
def path
@@ -138,7 +145,7 @@ class WikiPage
default_per_page = Kaminari.config.default_per_page
offset = [options[:page].to_i - 1, 0].max * options.fetch(:per_page, default_per_page)
- wiki.repository.commits('HEAD',
+ wiki.repository.commits(wiki.default_branch,
path: page.path,
limit: options.fetch(:limit, default_per_page),
offset: offset)
@@ -147,11 +154,11 @@ class WikiPage
def count_versions
return [] unless persisted?
- wiki.wiki.count_page_versions(page.path)
+ wiki.repository.count_commits(ref: wiki.default_branch, path: page.path)
end
def last_version
- @last_version ||= versions(limit: 1).first
+ @last_version ||= wiki.repository.last_commit_for_path(wiki.default_branch, page.path) if page
end
def last_commit_sha
diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb
index a52dac446ea..1c23b367489 100644
--- a/app/policies/ci/runner_policy.rb
+++ b/app/policies/ci/runner_policy.rb
@@ -20,8 +20,8 @@ module Ci
end
with_options scope: :user, score: 5
- condition(:any_developer_groups_inheriting_shared_runners) do
- @user.developer_groups.with_shared_runners_enabled.any?
+ condition(:any_developer_maintainer_owned_groups_inheriting_shared_runners) do
+ @user.developer_maintainer_owned_groups.with_shared_runners_enabled.any?
end
with_options scope: :user, score: 5
@@ -31,7 +31,7 @@ module Ci
with_options score: 10
condition(:any_associated_projects_in_group_runner_inheriting_group_runners) do
- # Check if any projects where user is a developer are inheriting group runners
+ # Check if any projects where user is a developer+ are inheriting group runners
@subject.groups&.any? do |group|
group.all_projects
.with_group_runners_enabled
@@ -48,13 +48,10 @@ module Ci
rule { admin | owned_runner }.policy do
enable :read_builds
- end
-
- rule { admin | owned_runner }.policy do
enable :read_runner
end
- rule { is_instance_runner & any_developer_groups_inheriting_shared_runners }.policy do
+ rule { is_instance_runner & any_developer_maintainer_owned_groups_inheriting_shared_runners }.policy do
enable :read_runner
end
diff --git a/app/policies/group_label_policy.rb b/app/policies/group_label_policy.rb
index 9f3acd44b23..4a848e44fec 100644
--- a/app/policies/group_label_policy.rb
+++ b/app/policies/group_label_policy.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class GroupLabelPolicy < BasePolicy
- delegate { @subject.group }
+ delegate { @subject.parent_container }
end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 96da0518dc0..7a0fb10928a 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -35,15 +35,15 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
with_options scope: :subject, score: 0
condition(:request_access_enabled) { @subject.request_access_enabled }
- condition(:create_projects_disabled) do
+ condition(:create_projects_disabled, scope: :subject) do
@subject.project_creation_level == ::Gitlab::Access::NO_ONE_PROJECT_ACCESS
end
- condition(:developer_maintainer_access) do
+ condition(:developer_maintainer_access, scope: :subject) do
@subject.project_creation_level == ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS
end
- condition(:maintainer_can_create_group) do
+ condition(:maintainer_can_create_group, scope: :subject) do
@subject.subgroup_creation_level == ::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS
end
@@ -51,7 +51,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
group_projects_for(user: @user, group: @subject, only_owned: false).any? { |p| p.design_management_enabled? }
end
- condition(:dependency_proxy_available) do
+ condition(:dependency_proxy_available, scope: :subject) do
@subject.dependency_proxy_feature_available?
end
@@ -59,7 +59,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
access_level(for_any_session: true) >= GroupMember::GUEST || valid_dependency_proxy_deploy_token
end
- condition(:observability_enabled) do
+ condition(:observability_enabled, scope: :subject) do
Feature.enabled?(:observability_group_tab, @subject)
end
@@ -80,10 +80,11 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
+ with_scope :subject
condition(:crm_enabled, score: 0, scope: :subject) { @subject.crm_enabled? }
- condition(:group_runner_registration_allowed) do
- Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?('group')
+ condition(:group_runner_registration_allowed, scope: :global) do
+ Gitlab::CurrentSettings.valid_runner_registrars.include?('group')
end
rule { can?(:read_group) & design_management_enabled }.policy do
@@ -149,6 +150,8 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :admin_crm_organization
enable :admin_crm_contact
enable :read_cluster
+
+ enable :read_group_all_available_runners
end
rule { reporter }.policy do
@@ -204,6 +207,9 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :destroy_deploy_token
enable :update_runners_registration_token
enable :owner_access
+
+ enable :read_billing
+ enable :edit_billing
end
rule { can?(:read_nested_project_resources) }.policy do
diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb
index e864ce8752a..df065b24e64 100644
--- a/app/policies/issuable_policy.rb
+++ b/app/policies/issuable_policy.rb
@@ -22,12 +22,6 @@ class IssuablePolicy < BasePolicy
enable :reopen_issue
end
- # This rule replicates permissions in NotePolicy#can_read_confidential and it's used in
- # TodoPolicy for performance reasons
- rule { can?(:reporter_access) | assignee_or_author | admin }.policy do
- enable :read_confidential_notes
- end
-
rule { can?(:read_merge_request) & assignee_or_author }.policy do
enable :update_merge_request
enable :reopen_merge_request
@@ -58,6 +52,12 @@ class IssuablePolicy < BasePolicy
rule { can_read_issuable }.policy do
enable :read_issuable
+ enable :read_issuable_participables
+ end
+
+ # This rule replicates permissions in NotePolicy#can_read_confidential
+ rule { can?(:reporter_access) | assignee_or_author | admin }.policy do
+ enable :read_internal_note
end
end
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index 0a0a35d41cc..87db228a698 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -81,6 +81,10 @@ class IssuePolicy < IssuablePolicy
rule { can?(:set_issue_metadata) & can_read_crm_contacts }.policy do
enable :set_issue_crm_contacts
end
+
+ rule { can?(:reporter_access) }.policy do
+ enable :mark_note_as_confidential
+ end
end
IssuePolicy.prepend_mod_with('IssuePolicy')
diff --git a/app/policies/namespaces/user_namespace_policy.rb b/app/policies/namespaces/user_namespace_policy.rb
index 028247497e5..89158578ac1 100644
--- a/app/policies/namespaces/user_namespace_policy.rb
+++ b/app/policies/namespaces/user_namespace_policy.rb
@@ -15,6 +15,8 @@ module Namespaces
enable :read_statistics
enable :create_jira_connect_subscription
enable :admin_package
+ enable :read_billing
+ enable :edit_billing
end
rule { ~can_create_personal_project }.prevent :create_projects
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index 1bffcc5aea2..dbfc63a0069 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -20,7 +20,8 @@ class NotePolicy < BasePolicy
condition(:confidential, scope: :subject) { @subject.confidential? }
- # If this condition changes IssuablePolicy#read_confidential_notes should be updated too
+ # Should be matched with IssuablePolicy#read_internal_note
+ # and EpicPolicy#read_internal_note
condition(:can_read_confidential) do
access_level >= Gitlab::Access::REPORTER || @subject.noteable_assignee_or_author?(@user) || admin?
end
diff --git a/app/policies/project_label_policy.rb b/app/policies/project_label_policy.rb
index 5ce896ecaf2..6656d5990a5 100644
--- a/app/policies/project_label_policy.rb
+++ b/app/policies/project_label_policy.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class ProjectLabelPolicy < BasePolicy
- delegate { @subject.project }
+ delegate { @subject.parent_container }
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index fb162d03955..77bdf9d62fc 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -222,7 +222,7 @@ class ProjectPolicy < BasePolicy
end
condition(:project_runner_registration_allowed) do
- Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?('project')
+ Gitlab::CurrentSettings.valid_runner_registrars.include?('project')
end
condition :registry_enabled do
@@ -399,7 +399,7 @@ class ProjectPolicy < BasePolicy
prevent(:admin_feature_flags_client)
end
- rule { split_operations_visibility_permissions & releases_disabled }.policy do
+ rule { releases_disabled }.policy do
prevent(*create_read_update_admin_destroy(:release))
end
@@ -574,6 +574,7 @@ class ProjectPolicy < BasePolicy
rule { issues_disabled & merge_requests_disabled }.policy do
prevent(*create_read_update_admin_destroy(:label))
prevent(*create_read_update_admin_destroy(:milestone))
+ prevent(:read_cycle_analytics)
end
rule { snippets_disabled }.policy do
@@ -793,7 +794,7 @@ class ProjectPolicy < BasePolicy
rule { project_bot }.enable :project_bot_access
- rule { can?(:read_all_resources) }.enable :read_resource_access_tokens
+ rule { can?(:read_all_resources) & resource_access_token_feature_available }.enable :read_resource_access_tokens
rule { can?(:admin_project) & resource_access_token_feature_available }.policy do
enable :read_resource_access_tokens
diff --git a/app/policies/todo_policy.rb b/app/policies/todo_policy.rb
index 5c24964f24a..d63eb9407f8 100644
--- a/app/policies/todo_policy.rb
+++ b/app/policies/todo_policy.rb
@@ -16,7 +16,7 @@ class TodoPolicy < BasePolicy
desc "User can read the todo's confidential note"
condition(:can_read_todo_confidential_note) do
- @user && @user.can?(:read_confidential_notes, @subject.target)
+ @user && @user.can?(:read_internal_note, @subject.target)
end
rule { own_todo & can_read_target }.enable :read_todo
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 71a05ef2c72..706608e3029 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -34,7 +34,9 @@ module Ci
def runner_variables
stop_expanding_file_vars = ::Feature.enabled?(:ci_stop_expanding_file_vars_for_runners, project)
- variables.sort_and_expand_all(keep_undefined: true, expand_file_vars: !stop_expanding_file_vars).to_runner_variables
+ variables
+ .sort_and_expand_all(keep_undefined: true, expand_file_vars: !stop_expanding_file_vars, project: project)
+ .to_runner_variables
end
def refspecs
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 32a7d205f46..fed4ae7837b 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -92,7 +92,7 @@ module Ci
if all_related_merge_requests.none?
_("No related merge requests found.")
else
- _("%{count} related %{pluralized_subject}: %{links}" % {
+ (_("%{count} related %{pluralized_subject}: %{links}") % {
count: all_related_merge_requests.count,
pluralized_subject: n_('merge request', 'merge requests', all_related_merge_requests.count),
links: all_related_merge_request_links(limit: limit).join(', ')
diff --git a/app/presenters/deploy_key_presenter.rb b/app/presenters/deploy_key_presenter.rb
new file mode 100644
index 00000000000..6f32487b6f6
--- /dev/null
+++ b/app/presenters/deploy_key_presenter.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class DeployKeyPresenter < KeyPresenter # rubocop:disable Gitlab/NamespacedClass
+ presents ::DeployKey, as: :deploy_key
+
+ def humanized_error_message
+ super(type: :deploy_key)
+ end
+end
diff --git a/app/presenters/event_presenter.rb b/app/presenters/event_presenter.rb
index 7fa87d33c0d..2f2fb1aa3ba 100644
--- a/app/presenters/event_presenter.rb
+++ b/app/presenters/event_presenter.rb
@@ -36,6 +36,8 @@ class EventPresenter < Gitlab::View::Presenter::Delegated
'Design'
elsif wiki_page?
'Wiki Page'
+ elsif issue? || work_item?
+ target.issue_type
elsif target_type.present?
target_type.titleize
else
diff --git a/app/presenters/key_presenter.rb b/app/presenters/key_presenter.rb
new file mode 100644
index 00000000000..e3eb5feedbf
--- /dev/null
+++ b/app/presenters/key_presenter.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class KeyPresenter < Gitlab::View::Presenter::Delegated # rubocop:disable Gitlab/NamespacedClass
+ presents ::Key, as: :key_object
+
+ def humanized_error_message(type: :key)
+ if !key_object.public_key.valid?
+ help_link = help_page_link(_('supported SSH public key.'), 'user/ssh', 'supported-ssh-key-types')
+
+ _('%{type} must be a %{help_link}').html_safe % { type: type.to_s.titleize, help_link: help_link }
+ else
+ key_object.errors.full_messages.join(', ').html_safe
+ end
+ end
+
+ private
+
+ def help_page_link(title, path, anchor)
+ ActionController::Base.helpers.link_to(title, help_page_path(path, anchor: anchor),
+ target: '_blank', rel: 'noopener noreferrer')
+ end
+end
diff --git a/app/serializers/board_serializer.rb b/app/serializers/board_serializer.rb
deleted file mode 100644
index 70a4c9ae282..00000000000
--- a/app/serializers/board_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class BoardSerializer < BaseSerializer
- entity BoardSimpleEntity
-end
diff --git a/app/serializers/board_simple_entity.rb b/app/serializers/board_simple_entity.rb
deleted file mode 100644
index ab625490966..00000000000
--- a/app/serializers/board_simple_entity.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-class BoardSimpleEntity < Grape::Entity
- expose :id
- expose :name
-end
-
-BoardSimpleEntity.prepend_mod_with('BoardSimpleEntity')
diff --git a/app/serializers/current_board_entity.rb b/app/serializers/current_board_entity.rb
deleted file mode 100644
index 530f7f5dea3..00000000000
--- a/app/serializers/current_board_entity.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class CurrentBoardEntity < Grape::Entity
- expose :id
- expose :name
- expose :hide_backlog_list
- expose :hide_closed_list
-end
-
-CurrentBoardEntity.prepend_mod_with('CurrentBoardEntity')
diff --git a/app/serializers/current_board_serializer.rb b/app/serializers/current_board_serializer.rb
deleted file mode 100644
index c58c77194f2..00000000000
--- a/app/serializers/current_board_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class CurrentBoardSerializer < BaseSerializer
- entity CurrentBoardEntity
-end
diff --git a/app/serializers/group_access_token_entity.rb b/app/serializers/group_access_token_entity.rb
index ab1fbb8ab46..83e8284e4e2 100644
--- a/app/serializers/group_access_token_entity.rb
+++ b/app/serializers/group_access_token_entity.rb
@@ -11,7 +11,7 @@ class GroupAccessTokenEntity < AccessTokenEntityBase
revoke_group_settings_access_token_path(
id: token,
- group_id: group.path)
+ group_id: group.full_path)
end
expose :role do |token, options|
diff --git a/app/serializers/import/github_org_entity.rb b/app/serializers/import/github_org_entity.rb
new file mode 100644
index 00000000000..a250a9b60f5
--- /dev/null
+++ b/app/serializers/import/github_org_entity.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Import
+ class GithubOrgEntity < Grape::Entity
+ expose :login, as: :name
+ expose :description
+ end
+end
diff --git a/app/serializers/import/github_org_serializer.rb b/app/serializers/import/github_org_serializer.rb
new file mode 100644
index 00000000000..69a598e4b24
--- /dev/null
+++ b/app/serializers/import/github_org_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Import
+ class GithubOrgSerializer < BaseSerializer
+ entity Import::GithubOrgEntity
+ end
+end
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 7ff75927fcd..3d94d2e2e9d 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -43,6 +43,10 @@ class IssueEntity < IssuableEntity
can?(request.current_user, :create_note, issue)
end
+ expose :can_create_confidential_note do |issue|
+ can?(request.current_user, :mark_note_as_confidential, issue)
+ end
+
expose :can_update do |issue|
can?(request.current_user, :update_issue, issue)
end
diff --git a/app/serializers/merge_request_noteable_entity.rb b/app/serializers/merge_request_noteable_entity.rb
index 29bd26c3a15..07d7d19d1f3 100644
--- a/app/serializers/merge_request_noteable_entity.rb
+++ b/app/serializers/merge_request_noteable_entity.rb
@@ -51,7 +51,7 @@ class MergeRequestNoteableEntity < IssuableEntity
end
expose :can_approve do |merge_request|
- merge_request.can_be_approved_by?(current_user)
+ merge_request.eligible_for_approval_by?(current_user)
end
end
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index 36825d14062..caf2e4c89b6 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -25,6 +25,10 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
# makes one query per merge request, whereas #approved_by? makes one per user
options[:merge_request].approvals.any? { |app| app.user_id == user.id }
end
+
+ expose :suggested, if: satisfies(:present?) do |user, options|
+ options[:suggested]
+ end
end
MergeRequestUserEntity.prepend_mod_with('MergeRequestUserEntity')
diff --git a/app/serializers/project_access_token_entity.rb b/app/serializers/project_access_token_entity.rb
index 52bb7b05d4e..548fb24173a 100644
--- a/app/serializers/project_access_token_entity.rb
+++ b/app/serializers/project_access_token_entity.rb
@@ -11,7 +11,7 @@ class ProjectAccessTokenEntity < AccessTokenEntityBase
revoke_namespace_project_settings_access_token_path(
id: token,
- namespace_id: project.namespace.path,
+ namespace_id: project.namespace.full_path,
project_id: project.path)
end
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 5e7dab31e8a..5082b84978a 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -8,7 +8,7 @@ class UserSerializer < BaseSerializer
merge_request = opts[:project].merge_requests.find_by_iid!(params[:merge_request_iid])
preload_max_member_access(merge_request.project, Array(resource))
- super(resource, opts.merge(merge_request: merge_request), MergeRequestUserEntity)
+ super(resource, opts.merge(merge_request: merge_request, suggested: params[:suggested]), MergeRequestUserEntity)
else
super
end
diff --git a/app/services/admin/set_feature_flag_service.rb b/app/services/admin/set_feature_flag_service.rb
new file mode 100644
index 00000000000..d72a18a6a58
--- /dev/null
+++ b/app/services/admin/set_feature_flag_service.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Admin
+ class SetFeatureFlagService
+ def initialize(feature_flag_name:, params:)
+ @name = feature_flag_name
+ @params = params
+ end
+
+ def execute
+ unless params[:force]
+ error = validate_feature_flag_name
+ return ServiceResponse.error(message: error, reason: :invalid_feature_flag) if error
+ end
+
+ flag_target = Feature::Target.new(params)
+ value = gate_value(params)
+
+ case value
+ when true
+ enable!(flag_target)
+ when false
+ disable!(flag_target)
+ else
+ enable_partially!(value, params)
+ end
+
+ feature_flag = Feature.get(name) # rubocop:disable Gitlab/AvoidFeatureGet
+
+ ServiceResponse.success(payload: { feature_flag: feature_flag })
+ rescue Feature::Target::UnknowTargetError => e
+ ServiceResponse.error(message: e.message, reason: :actor_not_found)
+ end
+
+ private
+
+ attr_reader :name, :params
+
+ def enable!(flag_target)
+ if flag_target.gate_specified?
+ flag_target.targets.each { |target| Feature.enable(name, target) }
+ else
+ Feature.enable(name)
+ end
+ end
+
+ def disable!(flag_target)
+ if flag_target.gate_specified?
+ flag_target.targets.each { |target| Feature.disable(name, target) }
+ else
+ Feature.disable(name)
+ end
+ end
+
+ def enable_partially!(value, params)
+ if params[:key] == 'percentage_of_actors'
+ Feature.enable_percentage_of_actors(name, value)
+ else
+ Feature.enable_percentage_of_time(name, value)
+ end
+ end
+
+ def validate_feature_flag_name
+ # overridden in EE
+ end
+
+ def gate_value(params)
+ case params[:value]
+ when 'true'
+ true
+ when '0', 'false'
+ false
+ else
+ # https://github.com/jnunemaker/flipper/blob/master/lib/flipper/typecast.rb#L47
+ if params[:value].to_s.include?('.')
+ params[:value].to_f
+ else
+ params[:value].to_i
+ end
+ end
+ end
+ end
+end
+
+Admin::SetFeatureFlagService.prepend_mod
diff --git a/app/services/alert_management/create_alert_issue_service.rb b/app/services/alert_management/create_alert_issue_service.rb
index 34c2003bd01..28e312a6fa3 100644
--- a/app/services/alert_management/create_alert_issue_service.rb
+++ b/app/services/alert_management/create_alert_issue_service.rb
@@ -21,7 +21,7 @@ module AlertManagement
result = create_incident
return result unless result.success?
- issue = result.payload[:issue]
+ issue = result[:issue]
perform_after_create_tasks(issue)
result
diff --git a/app/services/authorized_project_update/project_recalculate_service.rb b/app/services/authorized_project_update/project_recalculate_service.rb
index e0b8158417c..8d60fffd959 100644
--- a/app/services/authorized_project_update/project_recalculate_service.rb
+++ b/app/services/authorized_project_update/project_recalculate_service.rb
@@ -64,7 +64,12 @@ module AuthorizedProjectUpdate
end
def refresh_authorizations
- project.remove_project_authorizations(user_ids_to_remove) if user_ids_to_remove.any?
+ if user_ids_to_remove.any?
+ ProjectAuthorization.delete_all_in_batches_for_project(
+ project: project,
+ user_ids: user_ids_to_remove)
+ end
+
ProjectAuthorization.insert_all_in_batches(authorizations_to_create) if authorizations_to_create.any?
end
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index 465025ef2e9..fcaa74555ca 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -50,7 +50,7 @@ module Boards
end
def set_issue_types
- params[:issue_types] ||= Issue::TYPES_FOR_LIST
+ params[:issue_types] ||= Issue::TYPES_FOR_BOARD_LIST
end
def item_model
diff --git a/app/services/boards/lists/generate_service.rb b/app/services/boards/lists/generate_service.rb
deleted file mode 100644
index d74320e92a3..00000000000
--- a/app/services/boards/lists/generate_service.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- module Lists
- class GenerateService < Boards::BaseService
- def execute(board)
- return false unless board.lists.movable.empty?
-
- List.transaction do
- label_params.each do |params|
- response = create_list(board, params)
-
- raise ActiveRecord::Rollback unless response.success?
- end
- end
-
- true
- end
-
- private
-
- def create_list(board, params)
- label = find_or_create_label(params)
- Lists::CreateService.new(parent, current_user, label_id: label.id).execute(board)
- end
-
- def find_or_create_label(params)
- ::Labels::FindOrCreateService.new(current_user, parent, params).execute
- end
-
- def label_params
- [
- { name: 'To Do', color: '#F0AD4E' },
- { name: 'Doing', color: '#5CB85C' }
- ]
- end
- end
- end
-end
diff --git a/app/services/boards/lists/list_service.rb b/app/services/boards/lists/list_service.rb
index e81ef467a4e..cf15db4314c 100644
--- a/app/services/boards/lists/list_service.rb
+++ b/app/services/boards/lists/list_service.rb
@@ -9,23 +9,27 @@ module Boards
end
lists = board.lists.preload_associated_models
+ lists = lists.with_types(available_list_types_for(board))
return lists.id_in(params[:list_id]) if params[:list_id].present?
- list_types = unavailable_list_types_for(board)
- lists.without_types(list_types)
+ lists
end
private
- def unavailable_list_types_for(board)
- hidden_lists_for(board)
+ def available_list_types_for(board)
+ licensed_list_types(board) + visible_lists(board)
end
- def hidden_lists_for(board)
- [].tap do |hidden|
- hidden << ::List.list_types[:backlog] if board.hide_backlog_list?
- hidden << ::List.list_types[:closed] if board.hide_closed_list?
+ def licensed_list_types(board)
+ [List.list_types[:label]]
+ end
+
+ def visible_lists(board)
+ [].tap do |visible|
+ visible << ::List.list_types[:backlog] unless board.hide_backlog_list?
+ visible << ::List.list_types[:closed] unless board.hide_closed_list?
end
end
end
diff --git a/app/services/bulk_imports/create_pipeline_trackers_service.rb b/app/services/bulk_imports/create_pipeline_trackers_service.rb
index af97aec09b5..f5b944e6df5 100644
--- a/app/services/bulk_imports/create_pipeline_trackers_service.rb
+++ b/app/services/bulk_imports/create_pipeline_trackers_service.rb
@@ -53,11 +53,13 @@ module BulkImports
def log_skipped_pipeline(pipeline, minimum_version, maximum_version)
logger.info(
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
pipeline_name: pipeline[:pipeline],
minimum_source_version: minimum_version,
maximum_source_version: maximum_version,
- source_version: source_version.to_s
+ source_version: source_version.to_s,
+ importer: 'gitlab_migration'
)
end
diff --git a/app/services/bulk_imports/create_service.rb b/app/services/bulk_imports/create_service.rb
index 31e1a822e78..d3c6dcca588 100644
--- a/app/services/bulk_imports/create_service.rb
+++ b/app/services/bulk_imports/create_service.rb
@@ -38,6 +38,8 @@ module BulkImports
def execute
bulk_import = create_bulk_import
+ Gitlab::Tracking.event(self.class.name, 'create', label: 'bulk_import_group')
+
BulkImportWorker.perform_async(bulk_import.id)
ServiceResponse.success(payload: bulk_import)
diff --git a/app/services/bulk_imports/repository_bundle_export_service.rb b/app/services/bulk_imports/repository_bundle_export_service.rb
index 31a2ed6d1af..86159f5189d 100644
--- a/app/services/bulk_imports/repository_bundle_export_service.rb
+++ b/app/services/bulk_imports/repository_bundle_export_service.rb
@@ -9,13 +9,19 @@ module BulkImports
end
def execute
- repository.bundle_to_disk(bundle_filepath) if repository.exists?
+ return unless repository_exists?
+
+ repository.bundle_to_disk(bundle_filepath)
end
private
attr_reader :repository, :export_path, :export_filename
+ def repository_exists?
+ repository.exists? && !repository.empty?
+ end
+
def bundle_filepath
File.join(export_path, "#{export_filename}.bundle")
end
diff --git a/app/services/bulk_imports/uploads_export_service.rb b/app/services/bulk_imports/uploads_export_service.rb
index 7f5ee7b8624..315590bea31 100644
--- a/app/services/bulk_imports/uploads_export_service.rb
+++ b/app/services/bulk_imports/uploads_export_service.rb
@@ -22,8 +22,9 @@ module BulkImports
subdir_path = export_subdir_path(upload)
mkdir_p(subdir_path)
download_or_copy_upload(uploader, File.join(subdir_path, uploader.filename))
- rescue Errno::ENAMETOOLONG => e
- # Do not fail entire export process if downloaded file has filename that exceeds 255 characters.
+ rescue StandardError => e
+ # Do not fail entire project export if something goes wrong during file download
+ # (e.g. downloaded file has filename that exceeds 255 characters).
# Ignore raised exception, skip such upload, log the error and keep going with the export instead.
Gitlab::ErrorTracking.log_exception(e, portable_id: portable.id, portable_class: portable.class.name, upload_id: upload.id)
end
diff --git a/app/services/ci/after_requeue_job_service.rb b/app/services/ci/after_requeue_job_service.rb
index 634c547a623..9d54207d75d 100644
--- a/app/services/ci/after_requeue_job_service.rb
+++ b/app/services/ci/after_requeue_job_service.rb
@@ -26,7 +26,7 @@ module Ci
return legacy_dependent_jobs unless ::Feature.enabled?(:ci_requeue_with_dag_object_hierarchy, project)
ordered_by_dag(
- ::Ci::Processable
+ @processable.pipeline.processables
.from_union(needs_dependent_jobs, stage_dependent_jobs)
.skipped
.ordered_by_stage
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index af175b8da1c..0b49beffcb5 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -26,6 +26,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::AssignPartition,
Gitlab::Ci::Pipeline::Chain::Seed,
Gitlab::Ci::Pipeline::Chain::Limit::Size,
+ Gitlab::Ci::Pipeline::Chain::Limit::ActiveJobs,
Gitlab::Ci::Pipeline::Chain::Limit::Deployments,
Gitlab::Ci::Pipeline::Chain::Validate::External,
Gitlab::Ci::Pipeline::Chain::Populate,
@@ -36,7 +37,6 @@ module Ci
Gitlab::Ci::Pipeline::Chain::CreateDeployments,
Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations,
Gitlab::Ci::Pipeline::Chain::Limit::Activity,
- Gitlab::Ci::Pipeline::Chain::Limit::JobActivity,
Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines,
Gitlab::Ci::Pipeline::Chain::Metrics,
Gitlab::Ci::Pipeline::Chain::TemplateUsage,
@@ -140,7 +140,7 @@ module Ci
end
def create_namespace_onboarding_action
- Namespaces::OnboardingPipelineCreatedWorker.perform_async(project.namespace_id)
+ Onboarding::PipelineCreatedWorker.perform_async(project.namespace_id)
end
def extra_options(content: nil, dry_run: false)
diff --git a/app/services/ci/generate_kubeconfig_service.rb b/app/services/ci/generate_kubeconfig_service.rb
index 894ab8e8505..347bc99dbf5 100644
--- a/app/services/ci/generate_kubeconfig_service.rb
+++ b/app/services/ci/generate_kubeconfig_service.rb
@@ -14,7 +14,8 @@ module Ci
url: Gitlab::Kas.tunnel_url
)
- agents.each do |agent|
+ agent_authorizations.each do |authorization|
+ agent = authorization.agent
user = user_name(agent)
template.add_user(
@@ -24,6 +25,7 @@ module Ci
template.add_context(
name: context_name(agent),
+ namespace: context_namespace(authorization),
cluster: cluster_name,
user: user
)
@@ -36,8 +38,8 @@ module Ci
attr_reader :pipeline, :token, :template
- def agents
- pipeline.authorized_cluster_agents
+ def agent_authorizations
+ pipeline.cluster_agent_authorizations
end
def cluster_name
@@ -52,6 +54,10 @@ module Ci
[agent.project.full_path, agent.name].join(delimiter)
end
+ def context_namespace(authorization)
+ authorization.config['default_namespace']
+ end
+
def agent_token(agent)
['ci', agent.id, token].join(delimiter)
end
diff --git a/app/services/ci/job_artifacts/delete_service.rb b/app/services/ci/job_artifacts/delete_service.rb
index 65cae03312e..c9d590eccc4 100644
--- a/app/services/ci/job_artifacts/delete_service.rb
+++ b/app/services/ci/job_artifacts/delete_service.rb
@@ -15,13 +15,23 @@ module Ci
method: 'Ci::JobArtifacts::DeleteService#execute',
project_id: build.project_id
)
+ return ServiceResponse.error(
+ message: 'Action temporarily disabled. The project this job belongs to is undergoing stats refresh.',
+ reason: :project_stats_refresh
+ )
end
- # fix_expire_at is false because in this case we want to explicitly delete the job artifacts
- # this flag is a workaround that will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/355833
- Ci::JobArtifacts::DestroyBatchService.new(build.job_artifacts.erasable, fix_expire_at: false).execute
+ result = Ci::JobArtifacts::DestroyBatchService.new(build.job_artifacts.erasable).execute
- ServiceResponse.success
+ if result.fetch(:status) == :success
+ ServiceResponse.success(payload:
+ {
+ destroyed_artifacts_count: result.fetch(:destroyed_artifacts_count),
+ statistics_updates: result.fetch(:statistics_updates)
+ })
+ else
+ ServiceResponse.error(message: result.fetch(:message))
+ end
end
private
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index fd13ed245cf..14e8dc41cf5 100644
--- a/app/services/ci/parse_dotenv_artifact_service.rb
+++ b/app/services/ci/parse_dotenv_artifact_service.rb
@@ -40,7 +40,7 @@ module Ci
key, value = scan_line!(line)
variables[key] = Ci::JobVariable.new(job_id: artifact.job_id,
- source: :dotenv, key: key, value: value)
+ source: :dotenv, key: key, value: value, raw: false)
end
end
diff --git a/app/services/ci/pipeline_artifacts/coverage_report_service.rb b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
index 99877603554..9c6fdb7a405 100644
--- a/app/services/ci/pipeline_artifacts/coverage_report_service.rb
+++ b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
@@ -27,18 +27,13 @@ module Ci
end
def pipeline_artifact_params
- attributes = {
+ {
pipeline: pipeline,
file_type: :code_coverage,
file: carrierwave_file,
- size: carrierwave_file['tempfile'].size
+ size: carrierwave_file['tempfile'].size,
+ locked: pipeline.locked
}
-
- if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project)
- attributes[:locked] = pipeline.locked
- end
-
- attributes
end
def carrierwave_file
diff --git a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb
index aeb68a75f88..a0746ef32b2 100644
--- a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb
+++ b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb
@@ -23,20 +23,15 @@ module Ci
def artifact_attributes
file = build_carrierwave_file!
- attributes = {
+ {
project_id: pipeline.project_id,
file_type: :code_quality_mr_diff,
file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_quality_mr_diff),
size: file["tempfile"].size,
file: file,
- expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now
+ expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now,
+ locked: pipeline.locked
}
-
- if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project)
- attributes[:locked] = pipeline.locked
- end
-
- attributes
end
def merge_requests
diff --git a/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb b/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb
index 17c039885e5..8dddf3c3f6c 100644
--- a/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb
+++ b/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb
@@ -3,20 +3,26 @@
module Ci
module PipelineArtifacts
class DestroyAllExpiredService
+ include ::Gitlab::ExclusiveLeaseHelpers
include ::Gitlab::LoopHelpers
include ::Gitlab::Utils::StrongMemoize
BATCH_SIZE = 100
- LOOP_TIMEOUT = 5.minutes
LOOP_LIMIT = 1000
+ LOOP_TIMEOUT = 5.minutes
+ LOCK_TIMEOUT = 10.minutes
+ EXCLUSIVE_LOCK_KEY = 'expired_pipeline_artifacts:destroy:lock'
def initialize
@removed_artifacts_count = 0
+ @start_at = Time.current
end
def execute
- loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- destroy_artifacts_batch
+ in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
+ destroy_unlocked_pipeline_artifacts
+
+ legacy_destroy_pipeline_artifacts
end
@removed_artifacts_count
@@ -24,10 +30,30 @@ module Ci
private
+ def destroy_unlocked_pipeline_artifacts
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ artifacts = Ci::PipelineArtifact.expired_before(@start_at).artifact_unlocked.limit(BATCH_SIZE)
+
+ break if artifacts.empty?
+
+ destroy_batch(artifacts)
+ end
+ end
+
+ def legacy_destroy_pipeline_artifacts
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ destroy_artifacts_batch
+ end
+ end
+
def destroy_artifacts_batch
artifacts = ::Ci::PipelineArtifact.unlocked.expired.limit(BATCH_SIZE).to_a
return false if artifacts.empty?
+ destroy_batch(artifacts)
+ end
+
+ def destroy_batch(artifacts)
artifacts.each(&:destroy!)
increment_stats(artifacts.size)
diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb
index e6ec65fcc91..22cd267806d 100644
--- a/app/services/ci/process_build_service.rb
+++ b/app/services/ci/process_build_service.rb
@@ -25,6 +25,8 @@ module Ci
end
def enqueue(build)
+ return build.drop!(:failed_outdated_deployment_job) if build.prevent_rollback_deployment?
+
build.enqueue
end
diff --git a/app/services/ci/runners/register_runner_service.rb b/app/services/ci/runners/register_runner_service.rb
index ae9b8bc8a16..abd32610cec 100644
--- a/app/services/ci/runners/register_runner_service.rb
+++ b/app/services/ci/runners/register_runner_service.rb
@@ -59,7 +59,7 @@ module Ci
end
def runner_registrar_valid?(type)
- Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?(type)
+ Gitlab::CurrentSettings.valid_runner_registrars.include?(type)
end
def token_scope
diff --git a/app/services/ci/unlock_artifacts_service.rb b/app/services/ci/unlock_artifacts_service.rb
index 1fee31da4fc..574cdae6480 100644
--- a/app/services/ci/unlock_artifacts_service.rb
+++ b/app/services/ci/unlock_artifacts_service.rb
@@ -11,8 +11,6 @@ module Ci
unlocked_pipeline_artifacts: 0
}
- unlock_pipeline_artifacts_enabled = ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, ci_ref.project)
-
if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, ci_ref.project)
loop do
unlocked_pipelines = []
@@ -22,9 +20,7 @@ module Ci
unlocked_pipelines = unlock_pipelines(ci_ref, before_pipeline)
unlocked_job_artifacts = unlock_job_artifacts(unlocked_pipelines)
- if unlock_pipeline_artifacts_enabled
- results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines)
- end
+ results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines)
end
break if unlocked_pipelines.empty?
diff --git a/app/services/clusters/applications/destroy_service.rb b/app/services/clusters/applications/destroy_service.rb
deleted file mode 100644
index d666682487b..00000000000
--- a/app/services/clusters/applications/destroy_service.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class DestroyService < ::Clusters::Applications::BaseService
- def execute(_request)
- instantiate_application.tap do |application|
- break unless application.can_uninstall?
-
- application.make_scheduled!
-
- Clusters::Applications::UninstallWorker.perform_async(application.name, application.id)
- end
- end
-
- private
-
- def builder
- cluster.public_send(application_class.association_name) # rubocop:disable GitlabSecurity/PublicSend
- end
- end
- end
-end
diff --git a/app/services/clusters/applications/uninstall_service.rb b/app/services/clusters/applications/uninstall_service.rb
deleted file mode 100644
index 50c8d806c14..00000000000
--- a/app/services/clusters/applications/uninstall_service.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class UninstallService < BaseHelmService
- def execute
- return unless app.scheduled?
-
- app.make_uninstalling!
- uninstall
- end
-
- private
-
- def uninstall
- helm_api.uninstall(app.uninstall_command)
-
- Clusters::Applications::WaitForUninstallAppWorker.perform_in(
- Clusters::Applications::WaitForUninstallAppWorker::INTERVAL, app.name, app.id)
- rescue Kubeclient::HttpError => e
- log_error(e)
- app.make_errored!("Kubernetes error: #{e.error_code}")
- rescue StandardError => e
- log_error(e)
- app.make_errored!('Failed to uninstall.')
- end
- end
- end
-end
diff --git a/app/services/concerns/users/participable_service.rb b/app/services/concerns/users/participable_service.rb
index c1c93aa604e..281b2508090 100644
--- a/app/services/concerns/users/participable_service.rb
+++ b/app/services/concerns/users/participable_service.rb
@@ -32,6 +32,8 @@ module Users
end
def groups
+ return [] unless current_user
+
current_user.authorized_groups.with_route.sort_by(&:path)
end
diff --git a/app/services/concerns/work_items/widgetable_service.rb b/app/services/concerns/work_items/widgetable_service.rb
index beb614c7b76..24ade9336b2 100644
--- a/app/services/concerns/work_items/widgetable_service.rb
+++ b/app/services/concerns/work_items/widgetable_service.rb
@@ -2,18 +2,22 @@
module WorkItems
module WidgetableService
- def execute_widgets(work_item:, callback:, widget_params: {})
+ def execute_widgets(work_item:, callback:, widget_params: {}, service_params: {})
work_item.widgets.each do |widget|
- widget_service(widget).try(callback, params: widget_params[widget.class.api_symbol])
+ widget_service(widget, service_params).try(callback, params: widget_params[widget.class.api_symbol])
end
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
- def widget_service(widget)
+ def widget_service(widget, service_params)
@widget_services ||= {}
return @widget_services[widget] if @widget_services.has_key?(widget)
- @widget_services[widget] = widget_service_class(widget)&.new(widget: widget, current_user: current_user)
+ @widget_services[widget] = widget_service_class(widget)&.new(
+ widget: widget,
+ current_user: current_user,
+ service_params: service_params
+ )
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/app/services/google_cloud/enable_cloudsql_service.rb b/app/services/google_cloud/enable_cloudsql_service.rb
index e4a411d0fab..911cccca5ca 100644
--- a/app/services/google_cloud/enable_cloudsql_service.rb
+++ b/app/services/google_cloud/enable_cloudsql_service.rb
@@ -3,7 +3,7 @@
module GoogleCloud
class EnableCloudsqlService < ::GoogleCloud::BaseService
def execute
- return no_projects_error if unique_gcp_project_ids.empty?
+ create_or_replace_project_vars(environment_name, 'GCP_PROJECT_ID', gcp_project_id, ci_var_protected?)
unique_gcp_project_ids.each do |gcp_project_id|
google_api_client.enable_cloud_sql_admin(gcp_project_id)
@@ -18,8 +18,8 @@ module GoogleCloud
private
- def no_projects_error
- error("No GCP projects found. Configure a service account or GCP_PROJECT_ID CI variable.")
+ def ci_var_protected?
+ ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name)
end
end
end
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index db52a272bf2..4092ded67bc 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -26,6 +26,8 @@ module Groups
end
def execute
+ Gitlab::Tracking.event(self.class.name, 'create', label: 'import_group_from_file')
+
if valid_user_permissions? && import_file && restorers.all?(&:restore)
notify_success
diff --git a/app/services/import/github/cancel_project_import_service.rb b/app/services/import/github/cancel_project_import_service.rb
new file mode 100644
index 00000000000..5dce5e73662
--- /dev/null
+++ b/app/services/import/github/cancel_project_import_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Import
+ module Github
+ class CancelProjectImportService < ::BaseService
+ def execute
+ return error('Not Found', :not_found) unless authorized_to_read?
+ return error('Unauthorized access', :forbidden) unless authorized_to_cancel?
+
+ if project.import_in_progress?
+ project.import_state.cancel
+ success(project: project)
+ else
+ error(cannot_cancel_error_message, :bad_request)
+ end
+ end
+
+ private
+
+ def authorized_to_read?
+ can?(current_user, :read_project, project)
+ end
+
+ def authorized_to_cancel?
+ can?(current_user, :owner_access, project)
+ end
+
+ def cannot_cancel_error_message
+ format(
+ _('The import cannot be canceled because it is %{project_status}'),
+ project_status: project.import_state.status
+ )
+ end
+ end
+ end
+end
diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb
index 53297d2412c..a60963e28c7 100644
--- a/app/services/import/github_service.rb
+++ b/app/services/import/github_service.rb
@@ -9,21 +9,13 @@ module Import
attr_reader :params, :current_user
def execute(access_params, provider)
- if blocked_url?
- return log_and_return_error("Invalid URL: #{url}", _("Invalid URL: %{url}") % { url: url }, :bad_request)
- end
-
- unless authorized?
- return error(_('This namespace has already been taken! Please choose another one.'), :unprocessable_entity)
- end
-
- if oversized?
- return error(oversize_error_message, :unprocessable_entity)
- end
+ context_error = validate_context
+ return context_error if context_error
project = create_project(access_params, provider)
if project.persisted?
+ store_import_settings(project)
success(project)
elsif project.errors[:import_source_disabled].present?
error(project.errors[:import_source_disabled], :forbidden)
@@ -108,6 +100,16 @@ module Import
private
+ def validate_context
+ if blocked_url?
+ log_and_return_error("Invalid URL: #{url}", _("Invalid URL: %{url}") % { url: url }, :bad_request)
+ elsif !authorized?
+ error(_('This namespace has already been taken. Choose a different one.'), :unprocessable_entity)
+ elsif oversized?
+ error(oversize_error_message, :unprocessable_entity)
+ end
+ end
+
def log_error(exception)
Gitlab::GithubImport::Logger.error(
message: 'Import failed due to a GitHub error',
@@ -126,6 +128,10 @@ module Import
error(translated_message, http_status)
end
+
+ def store_import_settings(project)
+ Gitlab::GithubImport::Settings.new(project).write(params[:optional_stages])
+ end
end
end
diff --git a/app/services/incident_management/incidents/create_service.rb b/app/services/incident_management/incidents/create_service.rb
index ef66325fdcc..f44842650b7 100644
--- a/app/services/incident_management/incidents/create_service.rb
+++ b/app/services/incident_management/incidents/create_service.rb
@@ -15,7 +15,7 @@ module IncidentManagement
end
def execute
- issue = Issues::CreateService.new(
+ create_result = Issues::CreateService.new(
project: project,
current_user: current_user,
params: {
@@ -29,22 +29,16 @@ module IncidentManagement
).execute
if alert
- return error(alert.errors.full_messages.to_sentence, issue) unless alert.valid?
+ return error(alert.errors.full_messages, create_result[:issue]) unless alert.valid?
end
- return error(issue.errors.full_messages.to_sentence, issue) unless issue.valid?
-
- success(issue)
+ create_result
end
private
attr_reader :title, :description, :severity, :alert
- def success(issue)
- ServiceResponse.success(payload: { issue: issue })
- end
-
def error(message, issue = nil)
ServiceResponse.error(payload: { issue: issue }, message: message)
end
diff --git a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
index 58777848151..d495ec5cab6 100644
--- a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
@@ -11,7 +11,7 @@ module IncidentManagement
@issuable = issuable
@param_errors = []
- super(project: issuable.project, current_user: current_user, params: Hash(params))
+ super(project: issuable.project, current_user: current_user, params: params)
end
def execute
diff --git a/app/services/incident_management/timeline_events/create_service.rb b/app/services/incident_management/timeline_events/create_service.rb
index 40ce9097c88..5422b4ad6d2 100644
--- a/app/services/incident_management/timeline_events/create_service.rb
+++ b/app/services/incident_management/timeline_events/create_service.rb
@@ -109,7 +109,6 @@ module IncidentManagement
def add_system_note(timeline_event)
return if auto_created
- return unless Feature.enabled?(:incident_timeline, project)
SystemNoteService.add_timeline_event(timeline_event)
end
diff --git a/app/services/incident_management/timeline_events/destroy_service.rb b/app/services/incident_management/timeline_events/destroy_service.rb
index 90e95ae8869..e1c6bbbdb85 100644
--- a/app/services/incident_management/timeline_events/destroy_service.rb
+++ b/app/services/incident_management/timeline_events/destroy_service.rb
@@ -30,8 +30,6 @@ module IncidentManagement
attr_reader :project, :timeline_event, :user, :incident
def add_system_note(incident, user)
- return unless Feature.enabled?(:incident_timeline, project)
-
SystemNoteService.delete_timeline_event(incident, user)
end
end
diff --git a/app/services/incident_management/timeline_events/update_service.rb b/app/services/incident_management/timeline_events/update_service.rb
index 5c5de4717bc..012e2f0e260 100644
--- a/app/services/incident_management/timeline_events/update_service.rb
+++ b/app/services/incident_management/timeline_events/update_service.rb
@@ -38,8 +38,6 @@ module IncidentManagement
end
def add_system_note(timeline_event)
- return unless Feature.enabled?(:incident_timeline, incident.project)
-
changes = was_changed(timeline_event)
return if changes == :none
diff --git a/app/services/issuable/import_csv/base_service.rb b/app/services/issuable/import_csv/base_service.rb
index 822e3cd787c..e84d1032e41 100644
--- a/app/services/issuable/import_csv/base_service.rb
+++ b/app/services/issuable/import_csv/base_service.rb
@@ -23,7 +23,7 @@ module Issuable
with_csv_lines.each do |row, line_no|
attributes = issuable_attributes_for(row)
- if create_issuable(attributes).persisted?
+ if create_issuable(attributes)&.persisted?
@results[:success] += 1
else
@results[:error_lines].push(line_no)
diff --git a/app/services/issuable/process_assignees.rb b/app/services/issuable/process_assignees.rb
index 1ef6d3d9c42..72f727c134d 100644
--- a/app/services/issuable/process_assignees.rb
+++ b/app/services/issuable/process_assignees.rb
@@ -6,11 +6,11 @@
module Issuable
class ProcessAssignees
def initialize(assignee_ids:, add_assignee_ids:, remove_assignee_ids:, existing_assignee_ids: nil, extra_assignee_ids: nil)
- @assignee_ids = assignee_ids
- @add_assignee_ids = add_assignee_ids
- @remove_assignee_ids = remove_assignee_ids
- @existing_assignee_ids = existing_assignee_ids || []
- @extra_assignee_ids = extra_assignee_ids || []
+ @assignee_ids = assignee_ids&.map(&:to_i)
+ @add_assignee_ids = add_assignee_ids&.map(&:to_i)
+ @remove_assignee_ids = remove_assignee_ids&.map(&:to_i)
+ @existing_assignee_ids = existing_assignee_ids&.map(&:to_i) || []
+ @extra_assignee_ids = extra_assignee_ids&.map(&:to_i) || []
end
def execute
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 70ad97f8436..e24ae8f59f0 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -67,22 +67,14 @@ class IssuableBaseService < ::BaseProjectService
end
def filter_assignees(issuable)
- filter_assignees_with_key(issuable, :assignee_ids, :assignees)
- filter_assignees_with_key(issuable, :add_assignee_ids, :add_assignees)
- filter_assignees_with_key(issuable, :remove_assignee_ids, :remove_assignees)
+ filter_assignees_using_checks(issuable, :assignee_ids)
+ filter_assignees_using_checks(issuable, :add_assignee_ids)
+ filter_assignees_using_checks(issuable, :remove_assignee_ids)
end
- def filter_assignees_with_key(issuable, id_key, key)
- if params[key] && params[id_key].blank?
- params[id_key] = params[key].map(&:id)
- end
-
+ def filter_assignees_using_checks(issuable, id_key)
return if params[id_key].blank?
- filter_assignees_using_checks(issuable, id_key)
- end
-
- def filter_assignees_using_checks(issuable, id_key)
unless issuable.allows_multiple_assignees?
params[id_key] = params[id_key].first(1)
end
@@ -154,10 +146,13 @@ class IssuableBaseService < ::BaseProjectService
end
def filter_escalation_status(issuable)
+ status_params = params.delete(:escalation_status) || {}
+ status_params.permit! if status_params.respond_to?(:permit!)
+
result = ::IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService.new(
issuable,
current_user,
- params.delete(:escalation_status)
+ status_params
).execute
return unless result.success? && result[:escalation_status].present?
@@ -266,11 +261,23 @@ class IssuableBaseService < ::BaseProjectService
# To be overridden by subclasses
end
- def after_update(issuable)
+ def prepare_update_params(issuable)
# To be overridden by subclasses
end
+ def after_update(issuable, old_associations)
+ handle_description_updated(issuable)
+ handle_label_changes(issuable, old_associations[:labels])
+ end
+
+ def handle_description_updated(issuable)
+ return unless issuable.previous_changes.include?('description')
+
+ GraphqlTriggers.issuable_description_updated(issuable)
+ end
+
def update(issuable)
+ prepare_update_params(issuable)
handle_quick_actions(issuable)
filter_params(issuable)
@@ -316,7 +323,7 @@ class IssuableBaseService < ::BaseProjectService
affected_assignees = (old_associations[:assignees] + new_assignees) - (old_associations[:assignees] & new_assignees)
invalidate_cache_counts(issuable, users: affected_assignees.compact)
- after_update(issuable)
+ after_update(issuable, old_associations)
issuable.create_new_cross_references!(current_user)
execute_hooks(
issuable,
@@ -356,7 +363,8 @@ class IssuableBaseService < ::BaseProjectService
handle_task_changes(issuable)
invalidate_cache_counts(issuable, users: issuable.assignees.to_a)
- after_update(issuable)
+ # not passing old_associations here to keep `update_task` as fast as possible
+ after_update(issuable, {})
execute_hooks(issuable, 'update', old_associations: nil)
if issuable.is_a?(MergeRequest)
@@ -531,6 +539,8 @@ class IssuableBaseService < ::BaseProjectService
end
def has_label_changes?(issuable, old_labels)
+ return false if old_labels.nil?
+
Set.new(issuable.labels) != Set.new(old_labels)
end
@@ -542,12 +552,15 @@ class IssuableBaseService < ::BaseProjectService
# override if needed
def handle_label_changes(issuable, old_labels)
- return unless has_label_changes?(issuable, old_labels)
+ return false unless has_label_changes?(issuable, old_labels)
# reset to preserve the label sort order (title ASC)
issuable.labels.reset
GraphqlTriggers.issuable_labels_updated(issuable)
+
+ # return true here to avoid checking for label changes in sub classes
+ true
end
# override if needed
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index d75e74f3b19..28ea6b0ebf8 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -68,6 +68,19 @@ module Issues
rebalance_if_needed(issue)
end
+ def handle_escalation_status_change(issue)
+ return unless issue.supports_escalation?
+
+ if issue.escalation_status
+ ::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(
+ issue,
+ current_user
+ ).execute
+ else
+ ::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute
+ end
+ end
+
def issuable_for_positioning(id, positioning_scope)
return unless id
diff --git a/app/services/issues/clone_service.rb b/app/services/issues/clone_service.rb
index 07dd9a98f89..8b05a1c2acd 100644
--- a/app/services/issues/clone_service.rb
+++ b/app/services/issues/clone_service.rb
@@ -75,7 +75,16 @@ module Issues
# Skip creation of system notes for existing attributes of the issue when cloning with notes.
# The system notes of the old issue are copied over so we don't want to end up with duplicate notes.
# When cloning without notes, we want to generate system notes for the attributes that were copied.
- CreateService.new(project: target_project, current_user: current_user, params: new_params, spam_params: spam_params).execute(skip_system_notes: with_notes)
+ create_result = CreateService.new(
+ project: target_project,
+ current_user: current_user,
+ params: new_params,
+ spam_params: spam_params
+ ).execute(skip_system_notes: with_notes)
+
+ raise CloneError, create_result.errors.join(', ') if create_result.error? && create_result[:issue].blank?
+
+ create_result[:issue]
end
def queue_copy_designs
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 92cf4811439..89b35bbab24 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -4,6 +4,7 @@ module Issues
class CreateService < Issues::BaseService
include ResolveDiscussions
prepend RateLimitedService
+ include ::Services::ReturnServiceResponses
rate_limit key: :issues_create,
opts: { scope: [:project, :current_user, :external_author] }
@@ -20,6 +21,8 @@ module Issues
end
def execute(skip_system_notes: false)
+ return error(_('Operation not allowed'), 403) unless @current_user.can?(authorization_action, @project)
+
@issue = @build_service.execute
handle_move_between_ids(@issue)
@@ -27,7 +30,13 @@ module Issues
@add_related_issue ||= params.delete(:add_related_issue)
filter_resolve_discussion_params
- create(@issue, skip_system_notes: skip_system_notes)
+ issue = create(@issue, skip_system_notes: skip_system_notes)
+
+ if issue.persisted?
+ success(issue: issue)
+ else
+ error(issue.errors.full_messages, 422, pass_back: { issue: issue })
+ end
end
def external_author
@@ -47,7 +56,7 @@ module Issues
issue.run_after_commit do
NewIssueWorker.perform_async(issue.id, user.id, issue.class.to_s)
Issues::PlacementWorker.perform_async(nil, issue.project_id)
- Namespaces::OnboardingIssueCreatedWorker.perform_async(issue.project.namespace_id)
+ Onboarding::IssueCreatedWorker.perform_async(issue.project.namespace_id)
end
end
@@ -56,7 +65,7 @@ module Issues
user_agent_detail_service.create
handle_add_related_issue(issue)
resolve_discussions_with_issue(issue)
- create_escalation_status(issue)
+ handle_escalation_status_change(issue)
create_timeline_event(issue)
try_to_associate_contacts(issue)
@@ -87,12 +96,12 @@ module Issues
private
- attr_reader :spam_params, :extra_params
-
- def create_escalation_status(issue)
- ::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
+ def authorization_action
+ :create_issue
end
+ attr_reader :spam_params, :extra_params
+
def create_timeline_event(issue)
return unless issue.incident?
diff --git a/app/services/issues/import_csv_service.rb b/app/services/issues/import_csv_service.rb
index bce3ecc8bef..83e550583f6 100644
--- a/app/services/issues/import_csv_service.rb
+++ b/app/services/issues/import_csv_service.rb
@@ -14,6 +14,10 @@ module Issues
private
+ def create_issuable(attributes)
+ super[:issue]
+ end
+
def create_issuable_class
Issues::CreateService
end
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index edab62b1fdf..6366ff4076b 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -83,7 +83,16 @@ module Issues
# Skip creation of system notes for existing attributes of the issue. The system notes of the old
# issue are copied over so we don't want to end up with duplicate notes.
- CreateService.new(project: @target_project, current_user: @current_user, params: new_params, spam_params: spam_params).execute(skip_system_notes: true)
+ create_result = CreateService.new(
+ project: @target_project,
+ current_user: @current_user,
+ params: new_params,
+ spam_params: spam_params
+ ).execute(skip_system_notes: true)
+
+ raise MoveError, create_result.errors.join(', ') if create_result.error? && create_result[:issue].blank?
+
+ create_result[:issue]
end
def queue_copy_designs
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 46c28d82ddc..e5feb4422f6 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -63,7 +63,6 @@ module Issues
handle_assignee_changes(issue, old_assignees)
handle_confidential_change(issue)
- handle_label_changes(issue, old_labels)
handle_added_labels(issue, old_labels)
handle_milestone_change(issue)
handle_added_mentions(issue, old_mentioned_users)
@@ -201,15 +200,6 @@ module Issues
::IncidentManagement::AddSeveritySystemNoteWorker.perform_async(issue.id, current_user.id)
end
- def handle_escalation_status_change(issue)
- return unless issue.supports_escalation? && issue.escalation_status
-
- ::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(
- issue,
- current_user
- ).execute
- end
-
def create_confidentiality_note(issue)
SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user)
end
diff --git a/app/services/jira_connect/create_asymmetric_jwt_service.rb b/app/services/jira_connect/create_asymmetric_jwt_service.rb
new file mode 100644
index 00000000000..71aba6feddd
--- /dev/null
+++ b/app/services/jira_connect/create_asymmetric_jwt_service.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class CreateAsymmetricJwtService
+ ARGUMENT_ERROR_MESSAGE = 'jira_connect_installation is not a proxy installation'
+
+ def initialize(jira_connect_installation)
+ raise ArgumentError, ARGUMENT_ERROR_MESSAGE unless jira_connect_installation.proxy?
+
+ @jira_connect_installation = jira_connect_installation
+ end
+
+ def execute
+ JWT.encode(jwt_claims, private_key, 'RS256', jwt_headers)
+ end
+
+ private
+
+ def jwt_claims
+ { aud: aud_claim, iss: iss_claim, qsh: qsh_claim }
+ end
+
+ def aud_claim
+ @jira_connect_installation.audience_url
+ end
+
+ def iss_claim
+ @jira_connect_installation.client_key
+ end
+
+ def qsh_claim
+ Atlassian::Jwt.create_query_string_hash(
+ @jira_connect_installation.audience_installed_event_url,
+ 'POST',
+ @jira_connect_installation.audience_url
+ )
+ end
+
+ def private_key
+ @private_key ||= OpenSSL::PKey::RSA.generate(3072)
+ end
+
+ def public_key_storage
+ @public_key_storage ||= JiraConnect::PublicKey.create!(key: private_key.public_key)
+ end
+
+ def jwt_headers
+ { kid: public_key_storage.uuid }
+ end
+ end
+end
diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb
index e3b110f8f26..2786a2e357e 100644
--- a/app/services/labels/promote_service.rb
+++ b/app/services/labels/promote_service.rb
@@ -9,7 +9,7 @@ module Labels
return unless project.group &&
label.is_a?(ProjectLabel)
- Label.transaction do
+ ProjectLabel.transaction do
# use the existing group label if it exists
group_label = find_or_create_group_label(label)
@@ -50,7 +50,7 @@ module Labels
.new(current_user, title: group_label.title, group_id: project.group.id)
.execute(skip_authorization: true)
.where.not(id: group_label)
- .select(:id) # Can't use pluck() to avoid object-creation because of the batching
+ .select(:id, :project_id, :group_id, :type) # Can't use pluck() to avoid object-creation because of the batching
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index 38bebc1d09d..aba075c3644 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -179,7 +179,7 @@ module Members
def enqueue_onboarding_progress_action
return unless member_created_namespace_id
- Namespaces::OnboardingUserAddedWorker.perform_async(member_created_namespace_id)
+ Onboarding::UserAddedWorker.perform_async(member_created_namespace_id)
end
def result
@@ -195,6 +195,8 @@ module Members
end
def publish_event!
+ return unless member_created_namespace_id
+
Gitlab::EventStore.publish(
Members::MembersAddedEvent.new(data: {
source_id: source.id,
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index 0a8344c58db..ce79907e8a8 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -2,6 +2,8 @@
module Members
class DestroyService < Members::BaseService
+ include Gitlab::ExclusiveLeaseHelpers
+
def execute(member, skip_authorization: false, skip_subresources: false, unassign_issuables: false, destroy_bot: false)
unless skip_authorization
raise Gitlab::Access::AccessDeniedError unless authorized?(member, destroy_bot)
@@ -11,13 +13,26 @@ module Members
end
@skip_auth = skip_authorization
+ last_owner = true
+
+ in_lock("delete_members:#{member.source.class}:#{member.source.id}") do
+ break if member.is_a?(GroupMember) && member.source.last_owner?(member.user)
+
+ last_owner = false
+ member.destroy
+ member.user&.invalidate_cache_counts
+ end
- return member if member.is_a?(GroupMember) && member.source.last_owner?(member.user)
+ unless last_owner
+ delete_member_associations(member, skip_subresources, unassign_issuables)
+ end
- member.destroy
+ member
+ end
- member.user&.invalidate_cache_counts
+ private
+ def delete_member_associations(member, skip_subresources, unassign_issuables)
if member.request? && member.user != current_user
notification_service.decline_access_request(member)
end
@@ -28,12 +43,8 @@ module Members
enqueue_unassign_issuables(member) if unassign_issuables
after_execute(member: member)
-
- member
end
- private
-
def authorized?(member, destroy_bot)
return can_destroy_bot_member?(member) if destroy_bot
diff --git a/app/services/merge_requests/approval_service.rb b/app/services/merge_requests/approval_service.rb
index 64ae33c9b15..5761e34caff 100644
--- a/app/services/merge_requests/approval_service.rb
+++ b/app/services/merge_requests/approval_service.rb
@@ -3,7 +3,7 @@
module MergeRequests
class ApprovalService < MergeRequests::BaseService
def execute(merge_request)
- return unless can_be_approved?(merge_request)
+ return unless eligible_for_approval?(merge_request)
approval = merge_request.approvals.new(user: current_user)
@@ -28,8 +28,8 @@ module MergeRequests
private
- def can_be_approved?(merge_request)
- merge_request.can_be_approved_by?(current_user)
+ def eligible_for_approval?(merge_request)
+ merge_request.eligible_for_approval_by?(current_user)
end
def save_approval(approval)
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 6cefd9169f5..cfd7c645b7e 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -58,6 +58,7 @@ 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)
+ trigger_merge_request_reviewers_updated(merge_request)
end
def cleanup_environments(merge_request)
@@ -244,6 +245,10 @@ module MergeRequests
Milestones::MergeRequestsCountService.new(milestone).delete_cache
end
+
+ def trigger_merge_request_reviewers_updated(merge_request)
+ GraphqlTriggers.merge_request_reviewers_updated(merge_request)
+ end
end
end
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index f83b14c7269..da3a9652d69 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -23,6 +23,7 @@ module MergeRequests
cleanup_environments(merge_request)
abort_auto_merge(merge_request, 'merge request was closed')
cleanup_refs(merge_request)
+ trigger_merge_request_merge_status_updated(merge_request)
end
merge_request
@@ -38,5 +39,9 @@ module MergeRequests
merge_request_metrics_service(merge_request).close(close_event)
end
end
+
+ def trigger_merge_request_merge_status_updated(merge_request)
+ GraphqlTriggers.merge_request_merge_status_updated(merge_request)
+ end
end
end
diff --git a/app/services/merge_requests/mark_reviewer_reviewed_service.rb b/app/services/merge_requests/mark_reviewer_reviewed_service.rb
index 766a4ca0a49..96747eabcf6 100644
--- a/app/services/merge_requests/mark_reviewer_reviewed_service.rb
+++ b/app/services/merge_requests/mark_reviewer_reviewed_service.rb
@@ -10,6 +10,8 @@ module MergeRequests
if reviewer
return error("Failed to update reviewer") unless reviewer.update(state: :reviewed)
+ trigger_merge_request_reviewers_updated(merge_request)
+
success
else
error("Reviewer not found")
diff --git a/app/services/merge_requests/merge_base_service.rb b/app/services/merge_requests/merge_base_service.rb
index 3e630d40b3d..2a3c1e8bc26 100644
--- a/app/services/merge_requests/merge_base_service.rb
+++ b/app/services/merge_requests/merge_base_service.rb
@@ -9,12 +9,12 @@ module MergeRequests
attr_reader :merge_request
# Overridden in EE.
- def hooks_validation_pass?(_merge_request)
+ def hooks_validation_pass?(merge_request, validate_squash_message: false)
true
end
# Overridden in EE.
- def hooks_validation_error(_merge_request)
+ def hooks_validation_error(merge_request, validate_squash_message: false)
# No-op
end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 6d31a29f5a7..6b4f9dbe509 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -26,6 +26,7 @@ module MergeRequests
@merge_request = merge_request
@options = options
+ jid = merge_jid
validate!
@@ -37,7 +38,7 @@ module MergeRequests
end
end
- log_info("Merge process finished on JID #{merge_jid} with state #{state}")
+ log_info("Merge process finished on JID #{jid} with state #{state}")
rescue MergeError => e
handle_merge_error(log_message: e.message, save_message_on_model: true)
ensure
@@ -159,17 +160,32 @@ module MergeRequests
end
def handle_merge_error(log_message:, save_message_on_model: false)
- Gitlab::AppLogger.error("MergeService ERROR: #{merge_request_info} - #{log_message}")
+ log_error("MergeService ERROR: #{merge_request_info} - #{log_message}")
@merge_request.update(merge_error: log_message) if save_message_on_model
end
def log_info(message)
+ payload = log_payload("#{merge_request_info} - #{message}")
+ logger.info(**payload)
+ end
+
+ def log_error(message)
+ payload = log_payload(message)
+ logger.error(**payload)
+ end
+
+ def logger
@logger ||= Gitlab::AppLogger
- @logger.info("#{merge_request_info} - #{message}")
+ end
+
+ def log_payload(message)
+ Gitlab::ApplicationContext.current
+ .merge(merge_request_info: merge_request_info,
+ message: message)
end
def merge_request_info
- merge_request.to_reference(full: true)
+ @merge_request_info ||= merge_request.to_reference(full: true)
end
def source_matches?
diff --git a/app/services/merge_requests/mergeability/logger.rb b/app/services/merge_requests/mergeability/logger.rb
index 8b45d231e03..88ef6d81eaa 100644
--- a/app/services/merge_requests/mergeability/logger.rb
+++ b/app/services/merge_requests/mergeability/logger.rb
@@ -11,16 +11,12 @@ module MergeRequests
end
def commit
- return unless enabled?
-
commit_logs
end
def instrument(mergeability_name:)
raise ArgumentError, 'block not given' unless block_given?
- return yield unless enabled?
-
op_start_db_counters = current_db_counter_payload
op_started_at = current_monotonic_time
@@ -38,15 +34,11 @@ module MergeRequests
attr_reader :destination, :merge_request
def observe(name, value)
- return unless enabled?
-
observations[name.to_s].push(value)
end
def commit_logs
- attributes = Gitlab::ApplicationContext.current.merge({
- mergeability_project_id: merge_request.project.id
- })
+ attributes = Gitlab::ApplicationContext.current.merge({ mergeability_project_id: merge_request.project.id })
attributes[:mergeability_merge_request_id] = merge_request.id
attributes.merge!(observations_hash)
@@ -89,12 +81,6 @@ module MergeRequests
::Gitlab::Metrics::Subscribers::ActiveRecord.db_counter_payload
end
- def enabled?
- strong_memoize(:enabled) do
- ::Feature.enabled?(:mergeability_checks_logger, merge_request.project)
- end
- end
-
def current_monotonic_time
::Gitlab::Metrics::System.monotonic_time
end
diff --git a/app/services/merge_requests/push_options_handler_service.rb b/app/services/merge_requests/push_options_handler_service.rb
index ef251f121ae..aa52349b0ee 100644
--- a/app/services/merge_requests/push_options_handler_service.rb
+++ b/app/services/merge_requests/push_options_handler_service.rb
@@ -104,7 +104,7 @@ module MergeRequests
merge_request = ::MergeRequests::CreateService.new(
project: project,
current_user: current_user,
- params: merge_request.attributes.merge(assignees: merge_request.assignees,
+ params: merge_request.attributes.merge(assignee_ids: merge_request.assignee_ids,
label_ids: merge_request.label_ids)
).execute
end
@@ -140,8 +140,8 @@ module MergeRequests
params[:add_labels] = params.delete(:label).keys if params.has_key?(:label)
params[:remove_labels] = params.delete(:unlabel).keys if params.has_key?(:unlabel)
- params[:add_assignee_ids] = params.delete(:assign).keys if params.has_key?(:assign)
- params[:remove_assignee_ids] = params.delete(:unassign).keys if params.has_key?(:unassign)
+ params[:add_assignee_ids] = convert_to_user_ids(params.delete(:assign).keys) if params.has_key?(:assign)
+ params[:remove_assignee_ids] = convert_to_user_ids(params.delete(:unassign).keys) if params.has_key?(:unassign)
if push_options[:milestone]
milestone = Milestone.for_projects_and_groups(@project, @project.ancestors_upto)&.find_by_name(push_options[:milestone])
@@ -169,7 +169,7 @@ module MergeRequests
params = base_params
params.merge!(
- assignees: [current_user],
+ assignee_ids: [current_user.id],
source_branch: branch,
source_project: project,
target_project: target_project
@@ -186,6 +186,12 @@ module MergeRequests
base_params.merge(merge_params(merge_request.source_branch))
end
+ def convert_to_user_ids(ids_or_usernames)
+ ids, usernames = ids_or_usernames.partition { |id_or_username| id_or_username.is_a?(Numeric) || id_or_username.match?(/\A\d+\z/) }
+ ids += User.by_username(usernames).pluck(:id) unless usernames.empty? # rubocop:disable CodeReuse/ActiveRecord
+ ids
+ end
+
def collect_errors_from_merge_request(merge_request)
merge_request.errors.full_messages.each do |error|
errors << error
diff --git a/app/services/merge_requests/request_review_service.rb b/app/services/merge_requests/request_review_service.rb
index b061ed45fee..ebbae98352b 100644
--- a/app/services/merge_requests/request_review_service.rb
+++ b/app/services/merge_requests/request_review_service.rb
@@ -11,6 +11,7 @@ module MergeRequests
return error("Failed to update reviewer") unless reviewer.update(state: :unreviewed)
notify_reviewer(merge_request, user)
+ trigger_merge_request_reviewers_updated(merge_request)
success
else
diff --git a/app/services/merge_requests/update_assignees_service.rb b/app/services/merge_requests/update_assignees_service.rb
index a13db52e34b..79a3e9f3c22 100644
--- a/app/services/merge_requests/update_assignees_service.rb
+++ b/app/services/merge_requests/update_assignees_service.rb
@@ -18,7 +18,17 @@ module MergeRequests
return merge_request if old_ids.to_set == new_ids.to_set # no-change
attrs = update_attrs.merge(assignee_ids: new_ids)
- merge_request.update!(**attrs)
+
+ # We now have assignees validation on merge request
+ # If we use an update with bang, it will explode,
+ # instead we need to check if its valid then return if its not valid.
+ if Feature.enabled?(:limit_assignees_per_issuable)
+ merge_request.update(**attrs)
+
+ return merge_request unless merge_request.valid?
+ else
+ merge_request.update!(**attrs)
+ end
# Defer the more expensive operations (handle_assignee_changes) to the background
MergeRequests::HandleAssigneesChangeService
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 6d518edc88f..745647b727c 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -38,7 +38,6 @@ module MergeRequests
handle_target_branch_change(merge_request)
handle_milestone_change(merge_request)
handle_draft_status_change(merge_request, changed_fields)
- handle_label_changes(merge_request, old_labels)
track_title_and_desc_edits(changed_fields)
track_discussion_lock_toggle(merge_request, changed_fields)
@@ -71,7 +70,8 @@ module MergeRequests
MergeRequests::CloseService
end
- def after_update(issuable)
+ def after_update(issuable, old_associations)
+ super
issuable.cache_merge_request_closes_issues!(current_user)
end
@@ -179,9 +179,12 @@ module MergeRequests
old_title_draft = MergeRequest.draft?(old_title)
new_title_draft = MergeRequest.draft?(new_title)
- # notify the draft status changed. Added/removed message is handled in the
- # email template itself, see `change_in_merge_request_draft_status_email` template.
- notify_draft_status_changed(merge_request) if old_title_draft || new_title_draft
+ if old_title_draft || new_title_draft
+ # notify the draft status changed. Added/removed message is handled in the
+ # email template itself, see `change_in_merge_request_draft_status_email` template.
+ notify_draft_status_changed(merge_request)
+ trigger_merge_request_status_updated(merge_request)
+ end
if !old_title_draft && new_title_draft
# Marked as Draft
@@ -320,6 +323,10 @@ module MergeRequests
def filter_sentinel_values(param)
param.reject { _1 == 0 }
end
+
+ def trigger_merge_request_status_updated(merge_request)
+ GraphqlTriggers.merge_request_merge_status_updated(merge_request)
+ end
end
end
diff --git a/app/services/ml/experiment_tracking/candidate_repository.rb b/app/services/ml/experiment_tracking/candidate_repository.rb
new file mode 100644
index 00000000000..b6f87995185
--- /dev/null
+++ b/app/services/ml/experiment_tracking/candidate_repository.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Ml
+ module ExperimentTracking
+ class CandidateRepository
+ attr_accessor :project, :user, :experiment, :candidate
+
+ def initialize(project, user)
+ @project = project
+ @user = user
+ end
+
+ def by_iid(iid)
+ ::Ml::Candidate.with_project_id_and_iid(project.id, iid)
+ end
+
+ def create!(experiment, start_time)
+ experiment.candidates.create!(
+ user: user,
+ start_time: start_time || 0
+ )
+ end
+
+ def update(candidate, status, end_time)
+ candidate.status = status.downcase if status
+ candidate.end_time = end_time if end_time
+
+ candidate.save
+ end
+
+ def add_metric!(candidate, name, value, tracked_at, step)
+ candidate.metrics.create!(
+ name: name,
+ value: value,
+ tracked_at: tracked_at,
+ step: step
+ )
+ end
+
+ def add_param!(candidate, name, value)
+ candidate.params.create!(name: name, value: value)
+ end
+
+ def add_metrics(candidate, metric_definitions)
+ return unless candidate.present?
+
+ metrics = metric_definitions.map do |metric|
+ {
+ candidate_id: candidate.id,
+ name: metric[:key],
+ value: metric[:value],
+ tracked_at: metric[:timestamp],
+ step: metric[:step],
+ **timestamps
+ }
+ end
+
+ ::Ml::CandidateMetric.insert_all(metrics, returning: false) unless metrics.empty?
+ end
+
+ def add_params(candidate, param_definitions)
+ return unless candidate.present?
+
+ parameters = param_definitions.map do |p|
+ {
+ candidate_id: candidate.id,
+ name: p[:key],
+ value: p[:value],
+ **timestamps
+ }
+ end
+
+ ::Ml::CandidateParam.insert_all(parameters, returning: false) unless parameters.empty?
+ end
+
+ private
+
+ def timestamps
+ current_time = Time.zone.now
+
+ { created_at: current_time, updated_at: current_time }
+ end
+ end
+ end
+end
diff --git a/app/services/ml/experiment_tracking/experiment_repository.rb b/app/services/ml/experiment_tracking/experiment_repository.rb
new file mode 100644
index 00000000000..891674adc2a
--- /dev/null
+++ b/app/services/ml/experiment_tracking/experiment_repository.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Ml
+ module ExperimentTracking
+ class ExperimentRepository
+ attr_accessor :project, :user
+
+ def initialize(project, user = nil)
+ @project = project
+ @user = user
+ end
+
+ def by_iid_or_name(iid: nil, name: nil)
+ return ::Ml::Experiment.by_project_id_and_iid(project.id, iid) if iid
+
+ ::Ml::Experiment.by_project_id_and_name(project.id, name) if name
+ end
+
+ def all
+ ::Ml::Experiment.by_project_id(project.id)
+ end
+
+ def create!(name)
+ ::Ml::Experiment.create!(name: name,
+ user: user,
+ project: project)
+ end
+ end
+ end
+end
diff --git a/app/services/namespaces/package_settings/update_service.rb b/app/services/namespaces/package_settings/update_service.rb
index c0af0900450..0c6fcee9113 100644
--- a/app/services/namespaces/package_settings/update_service.rb
+++ b/app/services/namespaces/package_settings/update_service.rb
@@ -8,7 +8,13 @@ module Namespaces
ALLOWED_ATTRIBUTES = %i[maven_duplicates_allowed
maven_duplicate_exception_regex
generic_duplicates_allowed
- generic_duplicate_exception_regex].freeze
+ generic_duplicate_exception_regex
+ maven_package_requests_forwarding
+ npm_package_requests_forwarding
+ pypi_package_requests_forwarding
+ lock_maven_package_requests_forwarding
+ lock_npm_package_requests_forwarding
+ lock_pypi_package_requests_forwarding].freeze
def execute
return ServiceResponse.error(message: 'Access Denied', http_status: 403) unless allowed?
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index b7e6a50fa5c..1aaf7fb769a 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -88,12 +88,14 @@ module Notes
return if quick_actions_service.commands_executed_count.to_i == 0
if update_params.present?
- if check_for_reviewer_validity(message, update_params)
+ invalid_message = validate_commands(note, update_params)
+
+ if invalid_message
+ note.errors.add(:validation, invalid_message)
+ message = invalid_message
+ else
quick_actions_service.apply_updates(update_params, note)
note.commands_changes = update_params
- else
- message = "Reviewers #{MergeRequest.max_number_of_assignees_or_reviewers_message}"
- note.errors.add(:validation, message)
end
end
@@ -114,16 +116,36 @@ module Notes
}
end
- def check_for_reviewer_validity(message, update_params)
- return true unless Feature.enabled?(:limit_reviewer_and_assignee_size)
+ def validate_commands(note, update_params)
+ if invalid_reviewers?(update_params)
+ "Reviewers #{note.noteable.class.max_number_of_assignees_or_reviewers_message}"
+ elsif invalid_assignees?(update_params)
+ "Assignees #{note.noteable.class.max_number_of_assignees_or_reviewers_message}"
+ end
+ end
+
+ def invalid_reviewers?(update_params)
+ return false unless Feature.enabled?(:limit_reviewer_and_assignee_size)
if update_params.key?(:reviewer_ids)
possible_reviewers = update_params[:reviewer_ids]&.uniq&.size
- return false if possible_reviewers > MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ possible_reviewers > ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ else
+ false
end
+ end
+
+ def invalid_assignees?(update_params)
+ return false unless Feature.enabled?(:limit_assignees_per_issuable)
- true
+ if update_params.key?(:assignee_ids)
+ possible_assignees = update_params[:assignee_ids]&.uniq&.size
+
+ possible_assignees > ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ else
+ false
+ end
end
def track_event(note, user)
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 5a92adfd25a..1224cf80b76 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -87,6 +87,13 @@ class NotificationService
mailer.access_token_expired_email(user).deliver_later
end
+ # Notify the user when one of their personal access tokens is revoked
+ def access_token_revoked(user, token_name)
+ return unless user.can?(:receive_notifications)
+
+ mailer.access_token_revoked_email(user, token_name).deliver_later
+ end
+
# Notify the user when at least one of their ssh key has expired today
def ssh_key_expired(user, fingerprints)
return unless user.can?(:receive_notifications)
@@ -109,6 +116,14 @@ class NotificationService
mailer.unknown_sign_in_email(user, ip, time).deliver_later
end
+ # Notify a user when a wrong 2FA OTP has been entered to
+ # try to sign in to their account
+ def two_factor_otp_attempt_failed(user, ip)
+ return unless user.can?(:receive_notifications)
+
+ mailer.two_factor_otp_attempt_failed_email(user, ip).deliver_later
+ end
+
# Notify a user when a new email address is added to the their account
def new_email_address_added(user, email)
return unless user.can?(:receive_notifications)
diff --git a/app/services/onboarding/progress_service.rb b/app/services/onboarding/progress_service.rb
index 66f7f2bc33d..c67669b49ab 100644
--- a/app/services/onboarding/progress_service.rb
+++ b/app/services/onboarding/progress_service.rb
@@ -12,7 +12,7 @@ module Onboarding
def execute(action:)
return unless Onboarding::Progress.not_completed?(namespace_id, action)
- Namespaces::OnboardingProgressWorker.perform_async(namespace_id, action)
+ Onboarding::ProgressWorker.perform_async(namespace_id, action)
end
end
diff --git a/app/services/packages/debian/create_package_file_service.rb b/app/services/packages/debian/create_package_file_service.rb
index 53275fdc9bb..19e68183ea2 100644
--- a/app/services/packages/debian/create_package_file_service.rb
+++ b/app/services/packages/debian/create_package_file_service.rb
@@ -5,18 +5,20 @@ module Packages
class CreatePackageFileService
include ::Packages::FIPS
- def initialize(package, params)
+ def initialize(package:, current_user:, params: {})
@package = package
+ @current_user = current_user
@params = params
end
def execute
raise DisabledError, 'Debian registry is not FIPS compliant' if Gitlab::FIPS.enabled?
raise ArgumentError, "Invalid package" unless package.present?
+ raise ArgumentError, "Invalid user" unless current_user.present?
# Debian package file are first uploaded to incoming with empty metadata,
# and are moved later by Packages::Debian::ProcessChangesService
- package.package_files.create!(
+ package_file = package.package_files.create!(
file: params[:file],
size: params[:file]&.size,
file_name: params[:file_name],
@@ -29,11 +31,17 @@ module Packages
fields: nil
}
)
+
+ if params[:file_name].end_with? '.changes'
+ ::Packages::Debian::ProcessChangesWorker.perform_async(package_file.id, current_user.id)
+ end
+
+ package_file
end
private
- attr_reader :package, :params
+ attr_reader :package, :current_user, :params
end
end
end
diff --git a/app/services/packages/mark_packages_for_destruction_service.rb b/app/services/packages/mark_packages_for_destruction_service.rb
new file mode 100644
index 00000000000..023392cf2d9
--- /dev/null
+++ b/app/services/packages/mark_packages_for_destruction_service.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Packages
+ class MarkPackagesForDestructionService
+ include BaseServiceUtility
+
+ BATCH_SIZE = 20
+
+ UNAUTHORIZED_RESPONSE = ServiceResponse.error(
+ message: "You don't have the permission to perform this action",
+ reason: :unauthorized
+ ).freeze
+
+ ERROR_RESPONSE = ServiceResponse.error(
+ message: 'Failed to mark the packages as pending destruction'
+ ).freeze
+
+ SUCCESS_RESPONSE = ServiceResponse.success(
+ message: 'Packages were successfully marked as pending destruction'
+ ).freeze
+
+ # Initialize this service with the given packages and user.
+ #
+ # * `packages`: must be an ActiveRecord relationship.
+ # * `current_user`: an User object. Could be nil.
+ def initialize(packages:, current_user: nil)
+ @packages = packages
+ @current_user = current_user
+ end
+
+ def execute(batch_size: BATCH_SIZE)
+ no_access = false
+ min_batch_size = [batch_size, BATCH_SIZE].min
+
+ @packages.each_batch(of: min_batch_size) do |batched_packages|
+ loaded_packages = batched_packages.including_project_route.to_a
+
+ break no_access = true unless can_destroy_packages?(loaded_packages)
+
+ ::Packages::Package.id_in(loaded_packages.map(&:id))
+ .update_all(status: :pending_destruction)
+
+ sync_maven_metadata(loaded_packages)
+ mark_package_files_for_destruction(loaded_packages)
+ end
+
+ return UNAUTHORIZED_RESPONSE if no_access
+
+ SUCCESS_RESPONSE
+ rescue StandardError
+ ERROR_RESPONSE
+ end
+
+ private
+
+ def mark_package_files_for_destruction(packages)
+ ::Packages::MarkPackageFilesForDestructionWorker.bulk_perform_async_with_contexts(
+ packages,
+ arguments_proc: -> (package) { package.id },
+ context_proc: -> (package) { { project: package.project, user: @current_user } }
+ )
+ end
+
+ def sync_maven_metadata(packages)
+ maven_packages_with_version = packages.select { |pkg| pkg.maven? && pkg.version? }
+ ::Packages::Maven::Metadata::SyncWorker.bulk_perform_async_with_contexts(
+ maven_packages_with_version,
+ arguments_proc: -> (package) { [@current_user.id, package.project_id, package.name] },
+ context_proc: -> (package) { { project: package.project, user: @current_user } }
+ )
+ end
+
+ def can_destroy_packages?(packages)
+ packages.all? do |package|
+ can?(@current_user, :destroy_package, package)
+ end
+ end
+ end
+end
diff --git a/app/services/packages/rpm/parse_package_service.rb b/app/services/packages/rpm/parse_package_service.rb
new file mode 100644
index 00000000000..689a161a81a
--- /dev/null
+++ b/app/services/packages/rpm/parse_package_service.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rpm
+ class ParsePackageService
+ include ::Gitlab::Utils::StrongMemoize
+
+ BUILD_ATTRIBUTES_METHOD_NAMES = %i[changelogs requirements provides].freeze
+ STATIC_ATTRIBUTES = %i[name version release summary description arch
+ license sourcerpm group buildhost packager vendor].freeze
+
+ CHANGELOGS_RPM_KEYS = %i[changelogtext changelogtime].freeze
+ REQUIREMENTS_RPM_KEYS = %i[requirename requireversion requireflags].freeze
+ PROVIDES_RPM_KEYS = %i[providename provideflags provideversion].freeze
+
+ def initialize(package_file)
+ @rpm = RPM::File.new(package_file)
+ end
+
+ def execute
+ raise ArgumentError, 'Unable to parse package' unless valid_package?
+
+ {
+ files: rpm.files || [],
+ epoch: package_tags[:epoch] || '0',
+ changelogs: build_changelogs,
+ requirements: build_requirements,
+ provides: build_provides
+ }.merge(extract_static_attributes)
+ end
+
+ private
+
+ attr_reader :rpm
+
+ def valid_package?
+ rpm.files && package_tags && true
+ rescue RuntimeError
+ # if arr-pm throws an error due to an incorrect file format,
+ # we just want this validation to fail rather than throw an exception
+ false
+ end
+
+ def package_tags
+ strong_memoize(:package_tags) do
+ rpm.tags
+ end
+ end
+
+ def extract_static_attributes
+ STATIC_ATTRIBUTES.each_with_object({}) do |attribute, hash|
+ hash[attribute] = package_tags[attribute]
+ end
+ end
+
+ # Define methods for building RPM attribute data from parsed package
+ # Transform
+ # changelogtime: [123, 234],
+ # changelogname: ["First", "Second"]
+ # changelogtext: ["Work1", "Work2"]
+ # Into
+ # changelog: [
+ # {changelogname: "First", changelogtext: "Work1", changelogtime: 123},
+ # {changelogname: "Second", changelogtext: "Work2", changelogtime: 234}
+ # ]
+ BUILD_ATTRIBUTES_METHOD_NAMES.each do |resource|
+ define_method("build_#{resource}") do
+ resource_keys = self.class.const_get("#{resource.upcase}_RPM_KEYS", false).dup
+ return [] if resource_keys.any? { package_tags[_1].blank? }
+
+ first_attributes = package_tags[resource_keys.first]
+ zipped_data = first_attributes.zip(*resource_keys[1..].map { package_tags[_1] })
+ build_hashes(resource_keys, zipped_data)
+ end
+ end
+
+ def build_hashes(resource_keys, zipped_data)
+ zipped_data.map do |data|
+ resource_keys.zip(data).to_h
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/rpm/repository_metadata/base_builder.rb b/app/services/packages/rpm/repository_metadata/base_builder.rb
index 9d76336d764..2c0a11457ec 100644
--- a/app/services/packages/rpm/repository_metadata/base_builder.rb
+++ b/app/services/packages/rpm/repository_metadata/base_builder.rb
@@ -3,17 +3,43 @@ module Packages
module Rpm
module RepositoryMetadata
class BaseBuilder
+ def initialize(xml: nil, data: {})
+ @xml = Nokogiri::XML(xml) if xml.present?
+ @data = data
+ end
+
def execute
- build_empty_structure
+ return build_empty_structure if xml.blank?
+
+ update_xml_document
+ update_package_count
+ xml.to_xml
end
private
+ attr_reader :xml, :data
+
def build_empty_structure
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
- xml.public_send(self.class::ROOT_TAG, self.class::ROOT_ATTRIBUTES) # rubocop:disable GitlabSecurity/PublicSend
+ xml.method_missing(self.class::ROOT_TAG, self.class::ROOT_ATTRIBUTES)
end.to_xml
end
+
+ def update_xml_document
+ # Add to the root xml element a new package metadata node
+ xml.at(self.class::ROOT_TAG).add_child(build_new_node)
+ end
+
+ def update_package_count
+ packages_count = xml.css("//#{self.class::ROOT_TAG}/package").count
+
+ xml.at(self.class::ROOT_TAG).attributes["packages"].value = packages_count.to_s
+ end
+
+ def build_new_node
+ raise NotImplementedError, "#{self.class} should implement #{__method__}"
+ end
end
end
end
diff --git a/app/services/packages/rpm/repository_metadata/build_primary_xml.rb b/app/services/packages/rpm/repository_metadata/build_primary_xml.rb
index affb41677c2..580bf844a0c 100644
--- a/app/services/packages/rpm/repository_metadata/build_primary_xml.rb
+++ b/app/services/packages/rpm/repository_metadata/build_primary_xml.rb
@@ -9,6 +9,79 @@ module Packages
'xmlns:rpm': 'http://linux.duke.edu/metadata/rpm',
packages: '0'
}.freeze
+
+ # Nodes that have only text without attributes
+ REQUIRED_BASE_ATTRIBUTES = %i[name arch summary description].freeze
+ NOT_REQUIRED_BASE_ATTRIBUTES = %i[url packager].freeze
+ FORMAT_NODE_BASE_ATTRIBUTES = %i[license vendor group buildhost sourcerpm].freeze
+
+ private
+
+ def build_new_node
+ builder = Nokogiri::XML::Builder.new do |xml|
+ xml.package(type: :rpm, 'xmlns:rpm': 'http://linux.duke.edu/metadata/rpm') do
+ build_required_base_attributes(xml)
+ build_not_required_base_attributes(xml)
+ xml.version epoch: data[:epoch], ver: data[:version], rel: data[:release]
+ xml.checksum data[:checksum], type: 'sha256', pkgid: 'YES'
+ xml.size package: data[:packagesize], installed: data[:installedsize], archive: data[:archivesize]
+ xml.time file: data[:filetime], build: data[:buildtime]
+ xml.location href: data[:location] if data[:location].present?
+ build_format_node(xml)
+ end
+ end
+
+ Nokogiri::XML(builder.to_xml).at('package')
+ end
+
+ def build_required_base_attributes(xml)
+ REQUIRED_BASE_ATTRIBUTES.each do |attribute|
+ xml.method_missing(attribute, data[attribute])
+ end
+ end
+
+ def build_not_required_base_attributes(xml)
+ NOT_REQUIRED_BASE_ATTRIBUTES.each do |attribute|
+ xml.method_missing(attribute, data[attribute]) if data[attribute].present?
+ end
+ end
+
+ def build_format_node(xml)
+ xml.format do
+ build_base_format_attributes(xml)
+ build_provides_node(xml)
+ build_requires_node(xml)
+ end
+ end
+
+ def build_base_format_attributes(xml)
+ FORMAT_NODE_BASE_ATTRIBUTES.each do |attribute|
+ xml[:rpm].method_missing(attribute, data[attribute]) if data[attribute].present?
+ end
+ end
+
+ def build_requires_node(xml)
+ xml[:rpm].requires do
+ data[:requirements].each do |requires|
+ xml[:rpm].entry(
+ name: requires[:requirename],
+ flags: requires[:requireflags],
+ ver: requires[:requireversion]
+ )
+ end
+ end
+ end
+
+ def build_provides_node(xml)
+ xml[:rpm].provides do
+ data[:provides].each do |provides|
+ xml[:rpm].entry(
+ name: provides[:providename],
+ flags: provides[:provideflags],
+ ver: provides[:provideversion])
+ end
+ end
+ end
end
end
end
diff --git a/app/services/packages/rpm/repository_metadata/build_repomd_xml.rb b/app/services/packages/rpm/repository_metadata/build_repomd_xml.rb
index c6cfd77815d..84614196254 100644
--- a/app/services/packages/rpm/repository_metadata/build_repomd_xml.rb
+++ b/app/services/packages/rpm/repository_metadata/build_repomd_xml.rb
@@ -9,6 +9,7 @@ module Packages
xmlns: 'http://linux.duke.edu/metadata/repo',
'xmlns:rpm': 'http://linux.duke.edu/metadata/rpm'
}.freeze
+ ALLOWED_DATA_VALUE_KEYS = %i[checksum open-checksum location timestamp size open-size].freeze
# Expected `data` structure
#
@@ -48,9 +49,9 @@ module Packages
end
def build_file_info(info, xml)
- info.each do |key, attributes|
+ info.slice(*ALLOWED_DATA_VALUE_KEYS).each do |key, attributes|
value = attributes.delete(:value)
- xml.public_send(key, value, attributes) # rubocop:disable GitlabSecurity/PublicSend
+ xml.method_missing(key, value, attributes)
end
end
end
diff --git a/app/services/pages_domains/create_acme_order_service.rb b/app/services/pages_domains/create_acme_order_service.rb
index e289a78091b..c600f497fa5 100644
--- a/app/services/pages_domains/create_acme_order_service.rb
+++ b/app/services/pages_domains/create_acme_order_service.rb
@@ -2,9 +2,6 @@
module PagesDomains
class CreateAcmeOrderService
- # elliptic curve algorithm to generate the private key
- ECDSA_CURVE = "prime256v1"
-
attr_reader :pages_domain
def initialize(pages_domain)
@@ -17,12 +14,7 @@ module PagesDomains
challenge = order.new_challenge
- private_key = if Feature.enabled?(:pages_lets_encrypt_ecdsa, pages_domain.project)
- OpenSSL::PKey::EC.generate(ECDSA_CURVE)
- else
- OpenSSL::PKey::RSA.new(4096)
- end
-
+ private_key = OpenSSL::PKey::RSA.new(4096)
saved_order = pages_domain.acme_orders.create!(
url: order.url,
expires_at: order.expires,
diff --git a/app/services/pages_domains/create_service.rb b/app/services/pages_domains/create_service.rb
new file mode 100644
index 00000000000..1f771ca3a05
--- /dev/null
+++ b/app/services/pages_domains/create_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class CreateService < BaseService
+ def execute
+ return unless authorized?
+
+ domain = project.pages_domains.create(params)
+
+ publish_event(domain) if domain.persisted?
+
+ domain
+ end
+
+ private
+
+ def authorized?
+ current_user.can?(:update_pages, project)
+ end
+
+ def publish_event(domain)
+ event = PagesDomainCreatedEvent.new(
+ data: {
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id,
+ domain: domain.domain
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
+ end
+end
diff --git a/app/services/pages_domains/delete_service.rb b/app/services/pages_domains/delete_service.rb
new file mode 100644
index 00000000000..af69e1845a9
--- /dev/null
+++ b/app/services/pages_domains/delete_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class DeleteService < BaseService
+ def execute(domain)
+ return unless authorized?
+
+ domain.destroy
+
+ publish_event(domain)
+ end
+
+ private
+
+ def authorized?
+ current_user.can?(:update_pages, project)
+ end
+
+ def publish_event(domain)
+ event = PagesDomainDeletedEvent.new(
+ data: {
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id,
+ domain: domain.domain
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
+ end
+end
diff --git a/app/services/pages_domains/update_service.rb b/app/services/pages_domains/update_service.rb
new file mode 100644
index 00000000000..b038aaa95b6
--- /dev/null
+++ b/app/services/pages_domains/update_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class UpdateService < BaseService
+ def execute(domain)
+ return unless authorized?
+
+ return false unless domain.update(params)
+
+ publish_event(domain)
+
+ true
+ end
+
+ private
+
+ def authorized?
+ current_user.can?(:update_pages, project)
+ end
+
+ def publish_event(domain)
+ event = PagesDomainUpdatedEvent.new(
+ data: {
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id,
+ domain: domain.domain
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
+ end
+end
diff --git a/app/services/personal_access_tokens/revoke_service.rb b/app/services/personal_access_tokens/revoke_service.rb
index 0275d03bcc9..732da75da3a 100644
--- a/app/services/personal_access_tokens/revoke_service.rb
+++ b/app/services/personal_access_tokens/revoke_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module PersonalAccessTokens
- class RevokeService
+ class RevokeService < BaseService
attr_reader :token, :current_user, :group
def initialize(current_user = nil, token: nil, group: nil )
@@ -15,6 +15,7 @@ module PersonalAccessTokens
if token.revoke!
log_event
+ notification_service.access_token_revoked(token.user, token.name)
ServiceResponse.success(message: success_message)
else
ServiceResponse.error(message: error_message)
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index e6b1b33a82a..ae5aae87a77 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -24,7 +24,7 @@ module Projects
end
def commands(noteable, type)
- return [] unless noteable
+ return [] unless noteable && current_user
QuickActions::InterpretService.new(project, current_user).available_commands(noteable)
end
@@ -33,9 +33,21 @@ module Projects
SnippetsFinder.new(current_user, project: project).execute.select([:id, :title])
end
- def contacts
- Crm::ContactsFinder.new(current_user, group: project.group).execute
- .select([:id, :email, :first_name, :last_name])
+ def contacts(target)
+ available_contacts = Crm::ContactsFinder.new(current_user, group: project.group).execute
+ .select([:id, :email, :first_name, :last_name, :state])
+
+ contact_hashes = available_contacts.as_json
+
+ return contact_hashes unless target.is_a?(Issue)
+
+ ids = target.customer_relations_contacts.ids # rubocop:disable CodeReuse/ActiveRecord
+
+ contact_hashes.each do |hash|
+ hash[:set] = ids.include?(hash['id'])
+ end
+
+ contact_hashes
end
def labels_as_hash(target)
diff --git a/app/services/projects/blame_service.rb b/app/services/projects/blame_service.rb
index 57b913b04e6..58e146e5a32 100644
--- a/app/services/projects/blame_service.rb
+++ b/app/services/projects/blame_service.rb
@@ -27,6 +27,10 @@ module Projects
.page(page)
end
+ def per_page
+ PER_PAGE
+ end
+
private
attr_reader :blob, :commit, :pagination_enabled
@@ -48,10 +52,6 @@ module Projects
page
end
- def per_page
- PER_PAGE
- end
-
def pagination_state(params)
return false if Gitlab::Utils.to_boolean(params[:no_pagination], default: false)
diff --git a/app/services/projects/container_repository/cleanup_tags_base_service.rb b/app/services/projects/container_repository/cleanup_tags_base_service.rb
index 8ea4ae4830a..5393c2c080d 100644
--- a/app/services/projects/container_repository/cleanup_tags_base_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_base_service.rb
@@ -60,23 +60,6 @@ module Projects
service.execute(container_repository)
end
- def can_destroy?
- return true if container_expiration_policy
-
- can?(current_user, :destroy_container_image, project)
- end
-
- def valid_regex?
- %w[name_regex_delete name_regex name_regex_keep].each do |param_name|
- regex = params[param_name]
- ::Gitlab::UntrustedRegexp.new(regex) unless regex.blank?
- end
- true
- rescue RegexpError => e
- ::Gitlab::ErrorTracking.log_exception(e, project_id: project.id)
- false
- end
-
def older_than
params['older_than']
end
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
index 285c3e252ef..cf2eb81e5f3 100644
--- a/app/services/projects/container_repository/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -2,101 +2,57 @@
module Projects
module ContainerRepository
- class CleanupTagsService < CleanupTagsBaseService
- def initialize(container_repository:, current_user: nil, params: {})
- super
-
- @params = params.dup
- @counts = { cached_tags_count: 0 }
- end
-
+ class CleanupTagsService < BaseContainerRepositoryService
def execute
return error('access denied') unless can_destroy?
return error('invalid regex') unless valid_regex?
- tags = container_repository.tags
- @counts[:original_size] = tags.size
-
- filter_out_latest!(tags)
- filter_by_name!(tags)
-
- tags = truncate(tags)
- populate_from_cache(tags)
-
- tags = filter_keep_n(tags)
- tags = filter_by_older_than(tags)
-
- @counts[:before_delete_size] = tags.size
-
- delete_tags(tags).merge(@counts).tap do |result|
- result[:deleted_size] = result[:deleted]&.size
-
- result[:status] = :error if @counts[:before_truncate_size] != @counts[:after_truncate_size]
- end
+ cleanup_tags_service_class.new(container_repository: container_repository, current_user: current_user, params: params)
+ .execute
end
private
- def filter_keep_n(tags)
- tags, tags_to_keep = partition_by_keep_n(tags)
-
- cache_tags(tags_to_keep)
-
- tags
- end
-
- def filter_by_older_than(tags)
- tags, tags_to_keep = partition_by_older_than(tags)
-
- cache_tags(tags_to_keep)
-
- tags
+ def cleanup_tags_service_class
+ log_data = {
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ project_id: project.id
+ }
+
+ if use_gitlab_service?
+ log_info(log_data.merge(gitlab_cleanup_tags_service: true))
+ ::Projects::ContainerRepository::Gitlab::CleanupTagsService
+ else
+ log_info(log_data.merge(third_party_cleanup_tags_service: true))
+ ::Projects::ContainerRepository::ThirdParty::CleanupTagsService
+ end
end
- def pushed_at(tag)
- tag.created_at
+ def use_gitlab_service?
+ container_repository.migrated? &&
+ container_repository.gitlab_api_client.supports_gitlab_api?
end
- def truncate(tags)
- @counts[:before_truncate_size] = tags.size
- @counts[:after_truncate_size] = tags.size
-
- return tags if max_list_size == 0
-
- # truncate the list to make sure that after the #filter_keep_n
- # execution, the resulting list will be max_list_size
- truncated_size = max_list_size + keep_n_as_integer
-
- return tags if tags.size <= truncated_size
+ def can_destroy?
+ return true if container_expiration_policy
- tags = tags.sample(truncated_size)
- @counts[:after_truncate_size] = tags.size
- tags
+ can?(current_user, :destroy_container_image, project)
end
- def populate_from_cache(tags)
- @counts[:cached_tags_count] = cache.populate(tags) if caching_enabled?
- end
-
- def cache_tags(tags)
- cache.insert(tags, older_than_in_seconds) if caching_enabled?
- end
-
- def cache
- strong_memoize(:cache) do
- ::Gitlab::ContainerRepository::Tags::Cache.new(container_repository)
+ def valid_regex?
+ %w[name_regex_delete name_regex name_regex_keep].each do |param_name|
+ regex = params[param_name]
+ ::Gitlab::UntrustedRegexp.new(regex) unless regex.blank?
end
+ true
+ rescue RegexpError => e
+ ::Gitlab::ErrorTracking.log_exception(e, project_id: project.id)
+ false
end
- def caching_enabled?
- result = ::Gitlab::CurrentSettings.current_application_settings.container_registry_expiration_policies_caching &&
- container_expiration_policy &&
- older_than.present?
- !!result
- end
-
- def max_list_size
- ::Gitlab::CurrentSettings.current_application_settings.container_registry_cleanup_tags_service_max_list_size.to_i
+ def container_expiration_policy
+ params['container_expiration_policy']
end
end
end
diff --git a/app/services/projects/container_repository/gitlab/cleanup_tags_service.rb b/app/services/projects/container_repository/gitlab/cleanup_tags_service.rb
index 81bb94c867a..e947e9575e2 100644
--- a/app/services/projects/container_repository/gitlab/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/gitlab/cleanup_tags_service.rb
@@ -14,9 +14,6 @@ module Projects
end
def execute
- return error('access denied') unless can_destroy?
- return error('invalid regex') unless valid_regex?
-
with_timeout do |start_time, result|
container_repository.each_tags_page(page_size: TAGS_PAGE_SIZE) do |tags|
execute_for_tags(tags, result)
diff --git a/app/services/projects/container_repository/third_party/cleanup_tags_service.rb b/app/services/projects/container_repository/third_party/cleanup_tags_service.rb
new file mode 100644
index 00000000000..c6335629b52
--- /dev/null
+++ b/app/services/projects/container_repository/third_party/cleanup_tags_service.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Projects
+ module ContainerRepository
+ module ThirdParty
+ class CleanupTagsService < CleanupTagsBaseService
+ def initialize(container_repository:, current_user: nil, params: {})
+ super
+
+ @params = params.dup
+ @counts = { cached_tags_count: 0 }
+ end
+
+ def execute
+ tags = container_repository.tags
+ @counts[:original_size] = tags.size
+
+ filter_out_latest!(tags)
+ filter_by_name!(tags)
+
+ tags = truncate(tags)
+ populate_from_cache(tags)
+
+ tags = filter_keep_n(tags)
+ tags = filter_by_older_than(tags)
+
+ @counts[:before_delete_size] = tags.size
+
+ delete_tags(tags).merge(@counts).tap do |result|
+ result[:deleted_size] = result[:deleted]&.size
+
+ result[:status] = :error if @counts[:before_truncate_size] != @counts[:after_truncate_size]
+ end
+ end
+
+ private
+
+ def filter_keep_n(tags)
+ tags, tags_to_keep = partition_by_keep_n(tags)
+
+ cache_tags(tags_to_keep)
+
+ tags
+ end
+
+ def filter_by_older_than(tags)
+ tags, tags_to_keep = partition_by_older_than(tags)
+
+ cache_tags(tags_to_keep)
+
+ tags
+ end
+
+ def pushed_at(tag)
+ tag.created_at
+ end
+
+ def truncate(tags)
+ @counts[:before_truncate_size] = tags.size
+ @counts[:after_truncate_size] = tags.size
+
+ return tags if max_list_size == 0
+
+ # truncate the list to make sure that after the #filter_keep_n
+ # execution, the resulting list will be max_list_size
+ truncated_size = max_list_size + keep_n_as_integer
+
+ return tags if tags.size <= truncated_size
+
+ tags = tags.sample(truncated_size)
+ @counts[:after_truncate_size] = tags.size
+ tags
+ end
+
+ def populate_from_cache(tags)
+ @counts[:cached_tags_count] = cache.populate(tags) if caching_enabled?
+ end
+
+ def cache_tags(tags)
+ cache.insert(tags, older_than_in_seconds) if caching_enabled?
+ end
+
+ def cache
+ strong_memoize(:cache) do
+ ::Gitlab::ContainerRepository::Tags::Cache.new(container_repository)
+ end
+ end
+
+ def caching_enabled?
+ result = current_application_settings.container_registry_expiration_policies_caching &&
+ container_expiration_policy &&
+ older_than.present?
+ !!result
+ end
+
+ def max_list_size
+ current_application_settings.container_registry_cleanup_tags_service_max_list_size.to_i
+ end
+
+ def current_application_settings
+ ::Gitlab::CurrentSettings.current_application_settings
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index f1525ed9763..4e883f682fb 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -134,7 +134,7 @@ module Projects
destroy_ci_records!
destroy_mr_diff_relations!
- destroy_merge_request_diffs! if ::Feature.enabled?(:extract_mr_diff_deletions)
+ destroy_merge_request_diffs!
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index 4979af6dfe1..de7ede4eabf 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -64,7 +64,11 @@ module Projects
def add_repository_to_project
if project.external_import? && !unknown_url?
begin
- Gitlab::UrlBlocker.validate!(project.import_url, ports: Project::VALID_IMPORT_PORTS)
+ Gitlab::UrlBlocker.validate!(
+ project.import_url,
+ schemes: Project::VALID_IMPORT_PROTOCOLS,
+ ports: Project::VALID_IMPORT_PORTS
+ )
rescue Gitlab::UrlBlocker::BlockedUrlError => e
raise e, s_("ImportProjects|Blocked import URL: %{message}") % { message: e.message }
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index d757b0700b9..f9a2c825608 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -122,7 +122,7 @@ module Projects
update_pending_builds if runners_settings_toggled?
- publish_event
+ publish_events
end
def after_rename_service(project)
@@ -212,7 +212,13 @@ module Projects
end
end
- def publish_event
+ def publish_events
+ publish_project_archived_event
+ publish_project_attributed_changed_event
+ publish_project_features_changed_event
+ end
+
+ def publish_project_archived_event
return unless project.archived_previously_changed?
event = Projects::ProjectArchivedEvent.new(data: {
@@ -223,6 +229,36 @@ module Projects
Gitlab::EventStore.publish(event)
end
+
+ def publish_project_attributed_changed_event
+ changes = @project.previous_changes
+
+ return if changes.blank?
+
+ event = Projects::ProjectAttributesChangedEvent.new(data: {
+ project_id: @project.id,
+ namespace_id: @project.namespace_id,
+ root_namespace_id: @project.root_namespace.id,
+ attributes: changes.keys
+ })
+
+ Gitlab::EventStore.publish(event)
+ end
+
+ def publish_project_features_changed_event
+ changes = @project.project_feature.previous_changes
+
+ return if changes.blank?
+
+ event = Projects::ProjectFeaturesChangedEvent.new(data: {
+ project_id: @project.id,
+ namespace_id: @project.namespace_id,
+ root_namespace_id: @project.root_namespace.id,
+ features: changes.keys
+ })
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index b7df201824a..01dd6323d94 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -3,10 +3,10 @@
module Releases
class CreateService < Releases::BaseService
def execute
- return error('Access Denied', 403) unless allowed?
- return error('You are not allowed to create this tag as it is protected.', 403) unless can_create_tag?
- return error('Release already exists', 409) if release
- return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ return error(_('Access Denied'), 403) unless allowed?
+ return error(_('You are not allowed to create this tag as it is protected.'), 403) unless can_create_tag?
+ return error(_('Release already exists'), 409) if release
+ return error(format(_("Milestone(s) not found: %{milestones}"), milestones: inexistent_milestones.join(', ')), 400) if inexistent_milestones.any? # rubocop:disable Layout/LineLength
# should be found before the creation of new tag
# because tag creation can spawn new pipeline
diff --git a/app/services/releases/destroy_service.rb b/app/services/releases/destroy_service.rb
index 8abf9308689..ff2b3a7bd18 100644
--- a/app/services/releases/destroy_service.rb
+++ b/app/services/releases/destroy_service.rb
@@ -3,8 +3,8 @@
module Releases
class DestroyService < Releases::BaseService
def execute
- return error('Release does not exist', 404) unless release
- return error('Access Denied', 403) unless allowed?
+ return error(_('Release does not exist'), 404) unless release
+ return error(_('Access Denied'), 403) unless allowed?
if release.destroy
success(tag: existing_tag, release: release)
diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb
index 2e0a2f8488a..b9b2aba9805 100644
--- a/app/services/releases/update_service.rb
+++ b/app/services/releases/update_service.rb
@@ -31,11 +31,11 @@ module Releases
private
def validate
- return error('Tag does not exist', 404) unless existing_tag
- return error('Release does not exist', 404) unless release
- return error('Access Denied', 403) unless allowed?
- return error('params is empty', 400) if empty_params?
- return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ return error(_('Tag does not exist'), 404) unless existing_tag
+ return error(_('Release does not exist'), 404) unless release
+ return error(_('Access Denied'), 403) unless allowed?
+ return error(_('params is empty'), 400) if empty_params?
+ return error(format(_("Milestone(s) not found: %{milestones}"), milestones: inexistent_milestones.join(', ')), 400) if inexistent_milestones.any? # rubocop:disable Layout/LineLength
end
def allowed?
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index eed03ba22fe..b8a210c0a95 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -13,7 +13,6 @@ module ResourceAccessTokens
return error("User does not have permission to create #{resource_type} access token") unless has_permission_to_create?
access_level = params[:access_level] || Gitlab::Access::MAINTAINER
- return error("Could not provision owner access to project access token") if do_not_allow_owner_access_level_for_project_bot?(access_level)
user = create_user
@@ -48,9 +47,9 @@ module ResourceAccessTokens
end
def create_user
- # Even project maintainers can create project access tokens, which in turn
+ # Even project maintainers/owners can create project access tokens, which in turn
# creates a bot user, and so it becomes necessary to have `skip_authorization: true`
- # since someone like a project maintainer does not inherently have the ability
+ # since someone like a project maintainer/owner does not inherently have the ability
# to create a new user in the system.
::Users::AuthorizedCreateService.new(current_user, default_user_params).execute
@@ -108,7 +107,7 @@ module ResourceAccessTokens
end
def create_membership(resource, user, access_level)
- resource.add_member(user, access_level, expires_at: params[:expires_at])
+ resource.add_member(user, access_level, current_user: current_user, expires_at: params[:expires_at])
end
def log_event(token)
@@ -122,12 +121,6 @@ module ResourceAccessTokens
def success(access_token)
ServiceResponse.success(payload: { access_token: access_token })
end
-
- def do_not_allow_owner_access_level_for_project_bot?(access_level)
- resource.is_a?(Project) &&
- access_level == Gitlab::Access::OWNER &&
- !current_user.can?(:manage_owners, resource)
- end
end
end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index cea7fc5769e..f38522b9764 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -102,6 +102,16 @@ class SearchService
end
end
+ def show_elasticsearch_tabs?
+ # overridden in EE
+ false
+ end
+
+ def show_epics?
+ # overridden in EE
+ false
+ end
+
private
def page
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index ddb20a835e1..0fa1bb96b13 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -106,6 +106,8 @@ module Users
def build_user_params_for_non_admin
@user_params = params.slice(*signup_params)
+ # if skip_confirmation is set to `true`, devise will set confirmed_at
+ # see: https://github.com/heartcombo/devise/blob/8593801130f2df94a50863b5db535c272b00efe1/lib/devise/models/confirmable.rb#L156
@user_params[:skip_confirmation] = skip_user_confirmation_email_from_setting if assign_skip_confirmation_from_settings?
@user_params[:name] = fallback_name if use_fallback_name?
end
diff --git a/app/services/users/dismiss_namespace_callout_service.rb b/app/services/users/dismiss_namespace_callout_service.rb
deleted file mode 100644
index 51261a93e20..00000000000
--- a/app/services/users/dismiss_namespace_callout_service.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class DismissNamespaceCalloutService < DismissCalloutService
- private
-
- def callout
- current_user.find_or_initialize_namespace_callout(params[:feature_name], params[:namespace_id])
- end
- end
-end
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index fe61335f3ed..b1ffd006795 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -62,12 +62,12 @@ module Users
# Updates the list of authorizations for the current user.
#
- # remove - The IDs of the authorization rows to remove.
+ # remove - The project IDs of the authorization rows to remove.
# 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) if remove.any?
+ ProjectAuthorization.delete_all_in_batches_for_user(user: user, project_ids: remove) if remove.any?
ProjectAuthorization.insert_all_in_batches(add) if add.any?
# Since we batch insert authorization rows, Rails' associations may get
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index cd2c7402713..e5e5e375198 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -194,7 +194,8 @@ class WebHookService
headers = {
'Content-Type' => 'application/json',
'User-Agent' => "GitLab/#{Gitlab::VERSION}",
- Gitlab::WebHooks::GITLAB_EVENT_HEADER => self.class.hook_to_event(hook_name)
+ Gitlab::WebHooks::GITLAB_EVENT_HEADER => self.class.hook_to_event(hook_name),
+ Gitlab::WebHooks::GITLAB_INSTANCE_HEADER => Gitlab.config.gitlab.base_url
}
headers['X-Gitlab-Token'] = Gitlab::Utils.remove_line_breaks(hook.token) if hook.token.present?
diff --git a/app/services/web_hooks/log_execution_service.rb b/app/services/web_hooks/log_execution_service.rb
index 5be8aee3ae8..1a40c877bda 100644
--- a/app/services/web_hooks/log_execution_service.rb
+++ b/app/services/web_hooks/log_execution_service.rb
@@ -17,7 +17,7 @@ module WebHooks
end
def execute
- update_hook_failure_state
+ update_hook_failure_state if WebHook.web_hooks_disable_failed?(hook)
log_execution
end
diff --git a/app/services/work_items/create_service.rb b/app/services/work_items/create_service.rb
index c2ceb701a2f..ebda043e873 100644
--- a/app/services/work_items/create_service.rb
+++ b/app/services/work_items/create_service.rb
@@ -2,7 +2,6 @@
module WorkItems
class CreateService < Issues::CreateService
- include ::Services::ReturnServiceResponses
include WidgetableService
def initialize(project:, current_user: nil, params: {}, spam_params:, widget_params: {})
@@ -17,11 +16,10 @@ module WorkItems
end
def execute
- unless @current_user.can?(:create_work_item, @project)
- return error(_('Operation not allowed'), :forbidden)
- end
+ result = super
+ return result if result.error?
- work_item = super
+ work_item = result[:issue]
if work_item.valid?
success(payload(work_item))
@@ -43,6 +41,10 @@ module WorkItems
private
+ def authorization_action
+ :create_work_item
+ end
+
def payload(work_item)
{ work_item: work_item }
end
diff --git a/app/services/work_items/update_service.rb b/app/services/work_items/update_service.rb
index 2deb8c82741..1351445f6f3 100644
--- a/app/services/work_items/update_service.rb
+++ b/app/services/work_items/update_service.rb
@@ -26,6 +26,17 @@ module WorkItems
private
+ def prepare_update_params(work_item)
+ execute_widgets(
+ work_item: work_item,
+ callback: :prepare_update_params,
+ widget_params: @widget_params,
+ service_params: params
+ )
+
+ super
+ end
+
def before_update(work_item, skip_spam_check: false)
execute_widgets(work_item: work_item, callback: :before_update_callback, widget_params: @widget_params)
@@ -38,7 +49,7 @@ module WorkItems
super
end
- def after_update(work_item)
+ def after_update(work_item, old_associations)
super
GraphqlTriggers.issuable_title_updated(work_item) if work_item.previous_changes.key?(:title)
@@ -47,5 +58,13 @@ module WorkItems
def payload(work_item)
{ work_item: work_item }
end
+
+ def handle_label_changes(issuable, old_labels)
+ return false unless super
+
+ Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter.track_work_item_labels_changed_action(
+ author: current_user
+ )
+ end
end
end
diff --git a/app/services/work_items/widgets/base_service.rb b/app/services/work_items/widgets/base_service.rb
index 37ed2bf4b05..1ff03a09f9f 100644
--- a/app/services/work_items/widgets/base_service.rb
+++ b/app/services/work_items/widgets/base_service.rb
@@ -5,12 +5,13 @@ module WorkItems
class BaseService < ::BaseService
WidgetError = Class.new(StandardError)
- attr_reader :widget, :work_item, :current_user
+ attr_reader :widget, :work_item, :current_user, :service_params
- def initialize(widget:, current_user:)
+ def initialize(widget:, current_user:, service_params: {})
@widget = widget
@work_item = widget.work_item
@current_user = current_user
+ @service_params = service_params
end
private
diff --git a/app/services/work_items/widgets/labels_service/update_service.rb b/app/services/work_items/widgets/labels_service/update_service.rb
new file mode 100644
index 00000000000..f00ea5c95ca
--- /dev/null
+++ b/app/services/work_items/widgets/labels_service/update_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ module LabelsService
+ class UpdateService < WorkItems::Widgets::BaseService
+ def prepare_update_params(params: {})
+ return if params.blank?
+
+ service_params.merge!(params.slice(:add_label_ids, :remove_label_ids))
+ end
+ end
+ end
+ end
+end
diff --git a/app/uploaders/job_artifact_uploader.rb b/app/uploaders/job_artifact_uploader.rb
index 83dc1030606..b38e7d93eac 100644
--- a/app/uploaders/job_artifact_uploader.rb
+++ b/app/uploaders/job_artifact_uploader.rb
@@ -3,6 +3,7 @@
class JobArtifactUploader < GitlabUploader
extend Workhorse::UploadPath
include ObjectStorage::Concern
+ include ObjectStorage::CDN::Concern
UnknownFileLocationError = Class.new(StandardError)
diff --git a/app/uploaders/object_storage/cdn.rb b/app/uploaders/object_storage/cdn.rb
index 0711ab0bd28..e49e2780147 100644
--- a/app/uploaders/object_storage/cdn.rb
+++ b/app/uploaders/object_storage/cdn.rb
@@ -10,6 +10,16 @@ module ObjectStorage
include Gitlab::Utils::StrongMemoize
+ UrlResult = Struct.new(:url, :used_cdn)
+
+ def cdn_enabled_url(project, ip_address)
+ if Feature.enabled?(:ci_job_artifacts_cdn, project) && use_cdn?(ip_address)
+ UrlResult.new(cdn_signed_url, true)
+ else
+ UrlResult.new(url, false)
+ end
+ end
+
def use_cdn?(request_ip)
return false unless cdn_options.is_a?(Hash) && cdn_options['provider']
return false unless cdn_provider
diff --git a/app/uploaders/object_storage/cdn/google_cdn.rb b/app/uploaders/object_storage/cdn/google_cdn.rb
index ea7683f131c..91bad1f8d6b 100644
--- a/app/uploaders/object_storage/cdn/google_cdn.rb
+++ b/app/uploaders/object_storage/cdn/google_cdn.rb
@@ -19,7 +19,7 @@ module ObjectStorage
ip = IPAddr.new(request_ip)
- return false if ip.private?
+ return false if ip.private? || ip.link_local? || ip.loopback?
!GoogleIpCache.google_ip?(request_ip)
end
@@ -41,7 +41,7 @@ module ObjectStorage
private
def config_valid?
- [key_name, decoded_key, cdn_url].all?(&:present?)
+ [key_name, decoded_key, cdn_url].all?(&:present?) && cdn_url.start_with?('https://')
end
def key_name
diff --git a/app/uploaders/packages/rpm/repository_file_uploader.rb b/app/uploaders/packages/rpm/repository_file_uploader.rb
new file mode 100644
index 00000000000..ff7e2bc719a
--- /dev/null
+++ b/app/uploaders/packages/rpm/repository_file_uploader.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+module Packages
+ module Rpm
+ class RepositoryFileUploader < GitlabUploader
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.packages
+
+ after :store, :schedule_background_upload
+
+ alias_method :upload, :model
+
+ def filename
+ model.file_name
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ raise ObjectNotReadyError, 'Repository file model not ready' unless model.id
+
+ Gitlab::HashedPath.new(
+ 'projects', model.project_id, 'rpm', 'repository_files', model.id,
+ root_hash: model.project_id
+ )
+ end
+ end
+ end
+end
diff --git a/app/validators/json_schemas/build_metadata_secrets.json b/app/validators/json_schemas/build_metadata_secrets.json
index 3c8035d0dcf..5dcd33a2cf0 100644
--- a/app/validators/json_schemas/build_metadata_secrets.json
+++ b/app/validators/json_schemas/build_metadata_secrets.json
@@ -24,7 +24,8 @@
},
"additionalProperties": false
},
- "^file$": { "type": "boolean" }
+ "^file$": { "type": "boolean" },
+ "^token$": { "type": "string" }
},
"additionalProperties": false
}
diff --git a/app/validators/json_schemas/ci_secure_file_metadata.json b/app/validators/json_schemas/ci_secure_file_metadata.json
new file mode 100644
index 00000000000..46a7ff60b8f
--- /dev/null
+++ b/app/validators/json_schemas/ci_secure_file_metadata.json
@@ -0,0 +1,22 @@
+{
+ "description": "CI Secure File Metadata",
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "team_name": { "type": "string" },
+ "team_id": { "type": "string" },
+ "app_name": { "type": "string" },
+ "app_id": { "type": "string" },
+ "app_id_prefix": { "type": "string" },
+ "xcode_managed": { "type": "boolean" },
+ "entitlements": { "type": "object" },
+ "devices": { "type": "array" },
+ "certificate_ids": { "type": "array" },
+ "issuer": { "type": "object" },
+ "subject": { "type": "object" }
+ },
+ "additionalProperties": true,
+ "required": [
+ "id"
+ ]
+}
diff --git a/app/validators/json_schemas/merge_request_predictions_suggested_reviewers.json b/app/validators/json_schemas/merge_request_predictions_suggested_reviewers.json
index 70112d7e414..8e80b52d9b8 100644
--- a/app/validators/json_schemas/merge_request_predictions_suggested_reviewers.json
+++ b/app/validators/json_schemas/merge_request_predictions_suggested_reviewers.json
@@ -4,7 +4,7 @@
"properties": {
"top_n": { "type": "number" },
"version": { "type": "string" },
- "changes": { "type": "array" }
+ "reviewers": { "type": "array" }
},
"additionalProperties": true
}
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 c0e42f22119..c091a2180c5 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -17,14 +17,14 @@
.form-group
= f.label :receive_max_input_size, _('Maximum push size (MB)'), class: 'label-light'
- = f.number_field :receive_max_input_size, class: 'form-control gl-form-input qa-receive-max-input-size-field', title: _('Maximum size limit for a single commit.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :receive_max_input_size, class: 'form-control gl-form-input', title: _('Maximum size limit for a single commit.'), data: { toggle: 'tooltip', container: 'body', qa_selector: 'receive_max_input_size_field' }
.form-group
= f.label :max_export_size, _('Maximum export size (MB)'), class: 'label-light'
= f.number_field :max_export_size, class: 'form-control gl-form-input', title: _('Maximum size of export files.'), data: { toggle: 'tooltip', container: 'body' }
%span.form-text.text-muted= _('Set to 0 for no size limit.')
.form-group
= f.label :max_import_size, _('Maximum import size (MB)'), class: 'label-light'
- = f.number_field :max_import_size, class: 'form-control gl-form-input qa-receive-max-import-size-field', title: _('Maximum size of import files.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :max_import_size, class: 'form-control gl-form-input', title: _('Maximum size of import files.'), data: { toggle: 'tooltip', container: 'body' }
%span.form-text.text-muted= _('Only effective when remote storage is enabled. Set to 0 for no size limit.')
.form-group
= f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light'
@@ -54,10 +54,10 @@
- dormant_users_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: dormant_users_help_link }
= f.gitlab_ui_checkbox_component :deactivate_dormant_users, _('Deactivate dormant users after a period of inactivity'), help_text: _('Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}').html_safe % { link_start: dormant_users_help_link_start, link_end: '</a>'.html_safe }
.form-group
- = f.label :deactivate_dormant_users_period, _('Period of inactivity (days)'), class: 'label-light'
- = f.number_field :deactivate_dormant_users_period, class: 'form-control gl-form-input', min: '1'
+ = f.label :deactivate_dormant_users_period, _('Days of inactivity before deactivation'), class: 'label-light'
+ = f.number_field :deactivate_dormant_users_period, class: 'form-control gl-form-input', min: '90', step: '1'
.form-text.text-muted
- = _('Period of inactivity before deactivation.')
+ = _('Must be 90 days or more.')
.form-group
= f.label :personal_access_token_prefix, _('Personal Access Token prefix'), class: 'label-light'
@@ -67,6 +67,6 @@
= f.gitlab_ui_checkbox_component :user_show_add_ssh_key_message, _("Inform users without uploaded SSH keys that they can't push over SSH until one is added")
= render 'admin/application_settings/invitation_flow_enforcement', form: f
- = render_if_exists 'admin/application_settings/updating_name_disabled_for_users', form: f
+ = render 'admin/application_settings/user_restrictions', form: f
= render_if_exists 'admin/application_settings/availability_on_namespace_setting', form: f
- = f.submit _('Save changes'), class: 'qa-save-changes-button', pajamas_button: true
+ = f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 05aea2b343d..f6635ad17ef 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -53,8 +53,7 @@
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'specify-a-custom-cicd-configuration-file'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= f.gitlab_ui_checkbox_component :suggest_pipeline_enabled, s_('AdminSettings|Enable pipeline suggestion banner'), help_text: s_('AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file.')
- - if Feature.enabled?(:enforce_runner_token_expires_at)
- #js-runner-token-expiration-intervals{ data: runner_token_expiration_interval_attributes }
+ #js-runner-token-expiration-intervals{ data: runner_token_expiration_interval_attributes }
= f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_eks.html.haml b/app/views/admin/application_settings/_eks.html.haml
index 0bb9be497d9..62c61ad356f 100644
--- a/app/views/admin/application_settings/_eks.html.haml
+++ b/app/views/admin/application_settings/_eks.html.haml
@@ -31,4 +31,4 @@
.form-text.text-muted
= _('Only required if not using role instance credentials.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_email.html.haml b/app/views/admin/application_settings/_email.html.haml
index fd65d4029f5..e0ff1f4be43 100644
--- a/app/views/admin/application_settings/_email.html.haml
+++ b/app/views/admin/application_settings/_email.html.haml
@@ -21,4 +21,4 @@
.form-group
= f.gitlab_ui_checkbox_component :user_deactivation_emails_enabled, _('Enable user deactivation emails'), help_text: _('Send emails to users upon account deactivation.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index 7919fde631f..a5e10846488 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -47,4 +47,4 @@
= f.text_field :external_authorization_service_default_label, class: 'form-control gl-form-input'
%span.form-text.text-muted
= external_authorization_client_url_help_text
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_floc.html.haml b/app/views/admin/application_settings/_floc.html.haml
index e56ba635890..cb8b2d3dfcd 100644
--- a/app/views/admin/application_settings/_floc.html.haml
+++ b/app/views/admin/application_settings/_floc.html.haml
@@ -19,4 +19,4 @@
.form-group
= f.gitlab_ui_checkbox_component :floc_enabled,
s_('FloC|Participate in FLoC')
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_gitaly.html.haml b/app/views/admin/application_settings/_gitaly.html.haml
index ade6dac606a..f459ff5abc4 100644
--- a/app/views/admin/application_settings/_gitaly.html.haml
+++ b/app/views/admin/application_settings/_gitaly.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -18,4 +18,4 @@
.form-text.text-muted
= _('Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index df534f18bde..09817a9172f 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -26,4 +26,4 @@
= s_('Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com.')
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('integration/gitpod', anchor: 'enable-gitpod-in-your-user-settings') }
= s_('Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} ').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_help_page.html.haml b/app/views/admin/application_settings/_help_page.html.haml
index 21eb4caf579..11ebad07e9a 100644
--- a/app/views/admin/application_settings/_help_page.html.haml
+++ b/app/views/admin/application_settings/_help_page.html.haml
@@ -21,4 +21,4 @@
- docs_link_url = help_page_path('user/admin_area/settings/help_page', anchor: 'destination-requirements')
- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
%span.form-text.text-muted#support_help_block= html_escape(_('Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}')) % { code_start: '<code>'.html_safe, help_text_url: help_url, code_end: '</code>'.html_safe, docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_import_export_limits.html.haml b/app/views/admin/application_settings/_import_export_limits.html.haml
index bc4a1577f90..8cb7915f847 100644
--- a/app/views/admin/application_settings/_import_export_limits.html.haml
+++ b/app/views/admin/application_settings/_import_export_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-import-export-limits-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-import-export-limits-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -35,4 +35,4 @@
= f.label :group_download_export_limit, _('Maximum group export download requests per minute'), class: 'label-bold'
= f.number_field :group_download_export_limit, class: 'form-control gl-form-input'
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml
index 4362ae9cb9b..01d7bf0af67 100644
--- a/app/views/admin/application_settings/_ip_limits.html.haml
+++ b/app/views/admin/application_settings/_ip_limits.html.haml
@@ -66,4 +66,4 @@
.form-text.text-muted
= html_escape(_("If blank, defaults to %{code_open}Retry later%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_issue_limits.html.haml b/app/views/admin/application_settings/_issue_limits.html.haml
index 431e2a64c46..147aab443b2 100644
--- a/app/views/admin/application_settings/_issue_limits.html.haml
+++ b/app/views/admin/application_settings/_issue_limits.html.haml
@@ -6,4 +6,4 @@
= f.label :issues_create_limit, _('Maximum number of requests per minute')
= f.number_field :issues_create_limit, class: 'form-control gl-form-input'
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_jira_connect_application_key.html.haml b/app/views/admin/application_settings/_jira_connect_application_key.html.haml
index e3df408cd4c..b67e7680720 100644
--- a/app/views/admin/application_settings/_jira_connect_application_key.html.haml
+++ b/app/views/admin/application_settings/_jira_connect_application_key.html.haml
@@ -18,4 +18,4 @@
.form-group
= f.label :jira_connect_application_key, s_('JiraConnect|Jira Connect Application ID'), class: 'label-bold'
= f.text_field :jira_connect_application_key, class: 'form-control gl-form-input'
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_localization.html.haml b/app/views/admin/application_settings/_localization.html.haml
index a6ed48ef4fe..90cb34395d8 100644
--- a/app/views/admin/application_settings/_localization.html.haml
+++ b/app/views/admin/application_settings/_localization.html.haml
@@ -15,5 +15,5 @@
- time_tracking_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: time_tracking_help_link }
= f.gitlab_ui_checkbox_component :time_tracking_limit_to_hours, _('Limit display of time tracking units to hours.'), help_text: _('Display time tracking in issues in total hours only. %{link_start}What is time tracking?%{link_end}').html_safe % { link_start: time_tracking_help_link_start, link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_network_rate_limits.html.haml b/app/views/admin/application_settings/_network_rate_limits.html.haml
index f1857a9749a..300180f7b9a 100644
--- a/app/views/admin/application_settings/_network_rate_limits.html.haml
+++ b/app/views/admin/application_settings/_network_rate_limits.html.haml
@@ -30,4 +30,4 @@
= f.label :"throttle_authenticated_#{setting_fragment}_period_in_seconds", _('Authenticated API rate limit period in seconds'), class: 'label-bold'
= f.number_field :"throttle_authenticated_#{setting_fragment}_period_in_seconds", class: 'form-control gl-form-input'
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_note_limits.html.haml b/app/views/admin/application_settings/_note_limits.html.haml
index 40760b3c45e..99cf0ebc669 100644
--- a/app/views/admin/application_settings/_note_limits.html.haml
+++ b/app/views/admin/application_settings/_note_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-note-limits-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-note-limits-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -12,4 +12,4 @@
= _('List of users who are allowed to exceed the rate limit. Example: username1, username2')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index bacfe056683..3505a3bf3ee 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -22,4 +22,4 @@
s_('OutboundRequests|Enforce DNS rebinding attack protection'),
help_text: _('OutboundRequests|Resolve IP addresses once and uses them to submit requests.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index 4bdfa5bfe83..3506038ca68 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -20,12 +20,12 @@
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs.mb-3
- @plans.each_with_index do |plan, index|
%li
- = link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
+ = link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan-package#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
= plan.name.capitalize
.tab-content
- @plans.each_with_index do |plan, index|
- .tab-pane{ :id => "plan#{index}", class: index == 0 ? 'active': '' }
- = form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
+ .tab-pane{ :id => "plan-package#{index}", class: index == 0 ? 'active': '' }
+ = gitlab_ui_form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
= form_errors(plan)
%fieldset
= f.hidden_field(:plan_id, value: plan.id)
@@ -53,4 +53,4 @@
.form-group
= f.label :generic_packages_max_file_size, _('Generic package file size in bytes'), class: 'label-bold'
= f.number_field :generic_packages_max_file_size, class: 'form-control gl-form-input'
- = f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, class: 'btn gl-button btn-confirm'
+ = f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index cf43d3ddeca..97d9426581e 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -46,4 +46,4 @@
= f.gitlab_ui_checkbox_component :lets_encrypt_terms_of_service_accepted,
s_("AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF).").html_safe % { link_start: terms_of_service_link_start, link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_performance.html.haml b/app/views/admin/application_settings/_performance.html.haml
index e0ba8d93fbd..86a01e1785e 100644
--- a/app/views/admin/application_settings/_performance.html.haml
+++ b/app/views/admin/application_settings/_performance.html.haml
@@ -23,4 +23,4 @@
.form-text.text-muted
= _('Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3).')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index 4e37c4c3c98..d4f6d84ea74 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -10,4 +10,4 @@
= f.label :performance_bar_allowed_group_path, _('Allow access to members of the following group'), class: 'label-bold'
= f.text_field :performance_bar_allowed_group_path, class: 'form-control gl-form-input', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm qa-save-changes-button'
+ = f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_pipeline_limits.html.haml b/app/views/admin/application_settings/_pipeline_limits.html.haml
index e93823172db..b7dffe63777 100644
--- a/app/views/admin/application_settings/_pipeline_limits.html.haml
+++ b/app/views/admin/application_settings/_pipeline_limits.html.haml
@@ -6,4 +6,4 @@
= f.label :pipeline_limit_per_project_user_sha, _('Maximum number of requests per minute')
= f.number_field :pipeline_limit_per_project_user_sha, class: 'form-control gl-form-input'
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_prometheus.html.haml b/app/views/admin/application_settings/_prometheus.html.haml
index 982531e9a2f..3db1272c77b 100644
--- a/app/views/admin/application_settings/_prometheus.html.haml
+++ b/app/views/admin/application_settings/_prometheus.html.haml
@@ -18,4 +18,4 @@
.form-text.text-muted
Only track method calls that take longer to complete than the given duration.
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_protected_paths.html.haml b/app/views/admin/application_settings/_protected_paths.html.haml
index 1f3f67c71c7..3a7a951d137 100644
--- a/app/views/admin/application_settings/_protected_paths.html.haml
+++ b/app/views/admin/application_settings/_protected_paths.html.haml
@@ -21,4 +21,4 @@
- relative_url_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: relative_url_link }
= _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index 856db32e088..6a8ef86a56e 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -34,4 +34,4 @@
= f.gitlab_ui_checkbox_component :container_registry_expiration_policies_caching, _("Enable container expiration caching."),
help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_repository_mirrors_form.html.haml b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
index dad8d5f3fae..869f26ceb10 100644
--- a/app/views/admin/application_settings/_repository_mirrors_form.html.haml
+++ b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
@@ -9,4 +9,4 @@
= render_if_exists 'admin/application_settings/mirror_settings', form: f
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index 9e7f2812d64..12dd8816783 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -27,4 +27,4 @@
= storage_form.text_field storage, class: 'form-text-input'
= storage_form.label storage, storage, class: 'label-bold form-check-label'
%br
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_sentry.html.haml b/app/views/admin/application_settings/_sentry.html.haml
index cfd34f6ca15..20164cfe88d 100644
--- a/app/views/admin/application_settings/_sentry.html.haml
+++ b/app/views/admin/application_settings/_sentry.html.haml
@@ -17,4 +17,4 @@
= f.label :sentry_environment, _('Environment'), class: 'label-light'
= f.text_field :sentry_environment, class: 'form-control gl-form-input', placeholder: Rails.env
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_sidekiq_job_limits.html.haml b/app/views/admin/application_settings/_sidekiq_job_limits.html.haml
index eaf4bbf4702..068a8155450 100644
--- a/app/views/admin/application_settings/_sidekiq_job_limits.html.haml
+++ b/app/views/admin/application_settings/_sidekiq_job_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-sidekiq-job-limits-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-sidekiq-job-limits-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -18,4 +18,4 @@
.form-text.text-muted
= _("Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs.")
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 48f0b9b2c31..3e2551d753a 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -55,4 +55,4 @@
= f.label :sign_in_text, _('Sign-in text'), class: 'label-bold'
= f.text_area :sign_in_text, class: 'form-control gl-form-input', rows: 4
%span.form-text.text-muted#home_help_block= _("Add text to the sign-in page. Markdown enabled.")
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 8684b909853..4e7d9b8ab21 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -31,4 +31,4 @@
.form-text.text-muted
= _('The Snowplow cookie domain.')
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_sourcegraph.html.haml b/app/views/admin/application_settings/_sourcegraph.html.haml
index 9e99b496ad0..b56ca12baec 100644
--- a/app/views/admin/application_settings/_sourcegraph.html.haml
+++ b/app/views/admin/application_settings/_sourcegraph.html.haml
@@ -29,4 +29,4 @@
= f.text_field :sourcegraph_url, class: 'form-control gl-form-input', placeholder: s_('SourcegraphAdmin|https://sourcegraph.example.com')
.form-text.text-muted
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
- = f.submit s_('SourcegraphAdmin|Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit s_('SourcegraphAdmin|Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_terms.html.haml b/app/views/admin/application_settings/_terms.html.haml
index a4b6e061c43..8da441d5245 100644
--- a/app/views/admin/application_settings/_terms.html.haml
+++ b/app/views/admin/application_settings/_terms.html.haml
@@ -11,4 +11,4 @@
.form-text.text-muted
= _("Markdown supported.")
= link_to _('What is Markdown?'), help_page_path('user/markdown.md'), target: '_blank', rel: 'noopener noreferrer'
- = f.submit _("Save changes"), class: "gl-button btn btn-confirm"
+ = f.submit _("Save changes"), pajamas_button: true
diff --git a/app/views/admin/application_settings/_third_party_offers.html.haml b/app/views/admin/application_settings/_third_party_offers.html.haml
index 20a60ac870a..ed809c6db52 100644
--- a/app/views/admin/application_settings/_third_party_offers.html.haml
+++ b/app/views/admin/application_settings/_third_party_offers.html.haml
@@ -16,4 +16,4 @@
= f.gitlab_ui_checkbox_component :hide_third_party_offers,
_('Do not display content for customer experience improvement and offers from third parties')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 046b59dbd18..2eda3eab8c7 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -50,4 +50,4 @@
%li
= s_('AdminSettings|Restrict group access by IP address. %{link_start}Learn more%{link_end}.').html_safe % { link_start: restrict_ip_link, link_end: link_end }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_user_restrictions.html.haml b/app/views/admin/application_settings/_user_restrictions.html.haml
new file mode 100644
index 00000000000..de8faa6705f
--- /dev/null
+++ b/app/views/admin/application_settings/_user_restrictions.html.haml
@@ -0,0 +1,6 @@
+- form = local_assigns.fetch(:form)
+
+.form-group
+ = label_tag _('User restrictions')
+ = render_if_exists 'admin/application_settings/updating_name_disabled_for_users', form: form
+ = form.gitlab_ui_checkbox_component :can_create_group, _("Allow users to create top-level groups")
diff --git a/app/views/admin/application_settings/_users_api_limits.html.haml b/app/views/admin/application_settings/_users_api_limits.html.haml
index 3918c76b12c..ca6f1113c4a 100644
--- a/app/views/admin/application_settings/_users_api_limits.html.haml
+++ b/app/views/admin/application_settings/_users_api_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-users-api-limits-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-users-api-limits-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -11,4 +11,4 @@
.form-text.text-muted{ id: 'users-api-limit-users-allowlist-field-description' }
= _('List of users who are allowed to exceed the rate limit. Example: username1, username2')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_whats_new.html.haml b/app/views/admin/application_settings/_whats_new.html.haml
index 3248969ca16..986402ad5f1 100644
--- a/app/views/admin/application_settings/_whats_new.html.haml
+++ b/app/views/admin/application_settings/_whats_new.html.haml
@@ -5,4 +5,4 @@
.gl-mb-4
= f.gitlab_ui_radio_component :whats_new_variant, variant, whats_new_variants_label(variant), help_text: whats_new_variants_description(variant)
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/appearances/preview_sign_in.html.haml b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
index 2e4ab714048..1c2350e2835 100644
--- a/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
+++ b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
@@ -9,5 +9,5 @@
= label_tag :password
= password_field_tag :password, nil, disabled: true, class: "form-control gl-form-input bottom", title: title
.form-group
- = button_tag _("Sign in"), disabled: true, class: "btn gl-button btn-confirm", type: "button", title: title
-
+ = render Pajamas::ButtonComponent.new(variant: :confirm, disabled: true, button_options: { title: title }) do
+ = _("Sign in")
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index f0f7e6868da..b7244c45871 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -10,7 +10,7 @@
%p.settings-message.text-center
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/index', anchor: 'protected-cicd-variables') }
= s_('Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- #js-instance-variables{ data: { endpoint: admin_ci_variables_path, group: 'true', maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
+ #js-instance-variables{ data: { endpoint: admin_ci_variables_path, maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
@@ -38,12 +38,11 @@
.settings-content
= render 'registry'
-- if Feature.enabled?(:runner_registration_control)
- %section.settings.as-runner.no-animate#js-runner-settings{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = s_('Runners|Runner registration')
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
- = expanded_by_default? ? 'Collapse' : 'Expand'
- .settings-content
- = render 'runner_registrars_form'
+%section.settings.as-runner.no-animate#js-runner-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
+ = s_('Runners|Runner registration')
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
+ = expanded_by_default? ? 'Collapse' : 'Expand'
+ .settings-content
+ = render 'runner_registrars_form'
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index cd63873a893..ec5d1ef4a34 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -24,6 +24,8 @@
.settings-content
= render 'account_and_limit'
+= render_if_exists 'admin/application_settings/free_user_cap'
+
%section.settings.as-diff-limits.no-animate#js-merge-request-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
@@ -102,7 +104,7 @@
= f.gitlab_ui_checkbox_component :web_ide_clientside_preview_enabled,
s_('IDE|Live Preview'),
help_text: s_('Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} ').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
= render_if_exists 'admin/application_settings/maintenance_mode_settings_form'
= render 'admin/application_settings/gitpod'
diff --git a/app/views/admin/application_settings/service_usage_data.html.haml b/app/views/admin/application_settings/service_usage_data.html.haml
index 25c8bd12345..06bb9df84c4 100644
--- a/app/views/admin/application_settings/service_usage_data.html.haml
+++ b/app/views/admin/application_settings/service_usage_data.html.haml
@@ -5,25 +5,26 @@
- @content_class = "limit-container-width" unless fluid_layout
- payload_class = 'js-service-ping-payload'
-%h3= name
+%section.js-search-settings-section
+ %h3= name
-- if @service_ping_data_present
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-payload-preview-trigger gl-mr-2', data: { payload_selector: ".#{payload_class}" } } ) do
- = gl_loading_icon(css_class: 'js-spinner gl-display-none', inline: true)
- %span.js-text.gl-display-inline= _('Preview payload')
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-payload-download-trigger gl-mr-2', data: { endpoint: usage_data_admin_application_settings_path(format: :json) } } ) do
- = gl_loading_icon(css_class: 'js-spinner gl-display-none', inline: true)
- %span.js-text.gl-display-inline= _('Download payload')
- %pre.js-syntax-highlight.code.highlight.gl-mt-2.gl-display-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
-- else
- = render Pajamas::AlertComponent.new(variant: :warning,
- dismissible: false,
- title: _('Service Ping payload not found in the application cache')) do |c|
+ - if @service_ping_data_present
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-payload-preview-trigger gl-mr-2', data: { payload_selector: ".#{payload_class}" } } ) do
+ = gl_loading_icon(css_class: 'js-spinner gl-display-none', inline: true)
+ %span.js-text.gl-display-inline= _('Preview payload')
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-payload-download-trigger gl-mr-2', data: { endpoint: usage_data_admin_application_settings_path(format: :json) } } ) do
+ = gl_loading_icon(css_class: 'js-spinner gl-display-none', inline: true)
+ %span.js-text.gl-display-inline= _('Download payload')
+ %pre.js-syntax-highlight.code.highlight.gl-mt-2.gl-display-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
+ - else
+ = render Pajamas::AlertComponent.new(variant: :warning,
+ dismissible: false,
+ title: _('Service Ping payload not found in the application cache')) do |c|
- = c.body do
- - enable_service_ping_link_url = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'enable-or-disable-usage-statistics')
- - enable_service_ping_link = '<a href="%{url}">'.html_safe % { url: enable_service_ping_link_url }
- - generate_manually_link_url = help_page_path('administration/troubleshooting/gitlab_rails_cheat_sheet', anchor: 'generate-service-ping')
- - generate_manually_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: generate_manually_link_url }
+ = c.body do
+ - enable_service_ping_link_url = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'enable-or-disable-usage-statistics')
+ - enable_service_ping_link = '<a href="%{url}">'.html_safe % { url: enable_service_ping_link_url }
+ - generate_manually_link_url = help_page_path('administration/troubleshooting/gitlab_rails_cheat_sheet', anchor: 'generate-service-ping')
+ - generate_manually_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: generate_manually_link_url }
- = html_escape(s_('%{enable_service_ping_link_start}Enable%{link_end} or %{generate_manually_link_start}generate%{link_end} Service Ping to preview and download service usage data payload.')) % { enable_service_ping_link_start: enable_service_ping_link, generate_manually_link_start: generate_manually_link, link_end: '</a>'.html_safe }
+ = html_escape(s_('%{enable_service_ping_link_start}Enable%{link_end} or %{generate_manually_link_start}generate%{link_end} Service Ping to preview and download service usage data payload.')) % { enable_service_ping_link_start: enable_service_ping_link, generate_manually_link_start: generate_manually_link, link_end: '</a>'.html_safe }
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index fd73d4c5671..83347034cc5 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -36,5 +36,5 @@
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes, f: f
.form-actions
- = f.submit _('Save application'), class: "gl-button btn btn-confirm wide"
+ = f.submit _('Save application'), pajamas_button: true
= link_to _('Cancel'), admin_applications_path, class: "gl-button btn btn-default btn-cancel"
diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml
index 6d2cab06010..15ce9b692f0 100644
--- a/app/views/admin/background_jobs/show.html.haml
+++ b/app/views/admin/background_jobs/show.html.haml
@@ -7,5 +7,4 @@
= html_escape(_('GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs')) % { linkStart: sidekiq_link_start, linkEnd: '</a>'.html_safe }
%hr
-.card.gl-rounded-0
- %iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" }
+%iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" }
diff --git a/app/views/admin/broadcast_messages/_table.html.haml b/app/views/admin/broadcast_messages/_table.html.haml
new file mode 100644
index 00000000000..c5cd333f9dd
--- /dev/null
+++ b/app/views/admin/broadcast_messages/_table.html.haml
@@ -0,0 +1,38 @@
+- targeted_broadcast_messages_enabled = Feature.enabled?(:role_targeted_broadcast_messages)
+
+- if @broadcast_messages.any?
+ .table-responsive
+ %table.table.b-table.gl-table
+ %thead
+ %tr
+ %th= _('Status')
+ %th= _('Preview')
+ %th= _('Starts')
+ %th= _('Ends')
+ - if targeted_broadcast_messages_enabled
+ %th= _('Target roles')
+ %th= _('Target Path')
+ %th= _('Type')
+ %th &nbsp;
+ %tbody
+ - @broadcast_messages.each do |message|
+ %tr
+ %td
+ = broadcast_message_status(message)
+ %td
+ = broadcast_message(message, preview: true)
+ %td
+ = message.starts_at
+ %td
+ = message.ends_at
+ - if targeted_broadcast_messages_enabled
+ %td
+ = target_access_levels_display(message.target_access_levels)
+ %td
+ = message.target_path
+ %td
+ = message.broadcast_type.capitalize
+ %td.gl-white-space-nowrap<
+ = link_to sprite_icon('pencil', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: _('Edit'), class: 'btn btn-icon gl-button'
+ = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: _('Remove'), class: 'js-remove-tr btn btn-icon gl-button btn-danger gl-ml-3'
+ = paginate @broadcast_messages, theme: 'gitlab'
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 46924393a27..7559365e49a 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -1,49 +1,30 @@
- breadcrumb_title _("Messages")
- page_title _("Broadcast Messages")
-- targeted_broadcast_messages_enabled = Feature.enabled?(:role_targeted_broadcast_messages)
+- vue_app_enabled = Feature.enabled?(:vue_broadcast_messages, current_user)
%h1.page-title.gl-font-size-h-display
= _('Broadcast Messages')
%p.light
= _('Use banners and notifications to notify your users about scheduled maintenance, recent upgrades, and more.')
-= render 'form'
-
-%br.clearfix
-
-- if @broadcast_messages.any?
- .table-responsive
- %table.table.b-table.gl-table
- %thead
- %tr
- %th= _('Status')
- %th= _('Preview')
- %th= _('Starts')
- %th= _('Ends')
- - if targeted_broadcast_messages_enabled
- %th= _('Target roles')
- %th= _('Target Path')
- %th= _('Type')
- %th &nbsp;
- %tbody
- - @broadcast_messages.each do |message|
- %tr
- %td
- = broadcast_message_status(message)
- %td
- = broadcast_message(message, preview: true)
- %td
- = message.starts_at
- %td
- = message.ends_at
- - if targeted_broadcast_messages_enabled
- %td
- = target_access_levels_display(message.target_access_levels)
- %td
- = message.target_path
- %td
- = message.broadcast_type.capitalize
- %td.gl-white-space-nowrap<
- = link_to sprite_icon('pencil', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: _('Edit'), class: 'btn btn-icon gl-button'
- = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: _('Remove'), class: 'js-remove-tr btn btn-icon gl-button btn-danger gl-ml-3'
- = paginate @broadcast_messages, theme: 'gitlab'
+- if vue_app_enabled
+ #js-broadcast-messages{ data: {
+ page: params[:page] || 1,
+ messages_count: @broadcast_messages.total_count,
+ messages: @broadcast_messages.map { |message| {
+ id: message.id,
+ status: broadcast_message_status(message),
+ preview: broadcast_message(message, preview: true),
+ starts_at: message.starts_at.to_s,
+ ends_at: message.ends_at.to_s,
+ target_roles: target_access_levels_display(message.target_access_levels),
+ target_path: message.target_path,
+ type: message.broadcast_type.capitalize,
+ edit_path: edit_admin_broadcast_message_path(message),
+ delete_path: admin_broadcast_message_path(message) + '.js'
+ } }.to_json
+ } }
+- else
+ = render 'form'
+ %br.clearfix
+ = render 'table'
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 271f89a6b08..ccea1714973 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -35,7 +35,7 @@
= link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-default")
= c.footer do
.d-flex.align-items-center
- = link_to(s_('AdminArea|View latest projects'), admin_projects_path)
+ = link_to(s_('AdminArea|View latest projects'), admin_projects_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
@@ -71,7 +71,7 @@
= link_to(s_('AdminArea|New group'), new_admin_group_path, class: "btn gl-button btn-default")
= c.footer do
.d-flex.align-items-center
- = link_to(s_('AdminArea|View latest groups'), admin_groups_path)
+ = link_to(s_('AdminArea|View latest groups'), admin_groups_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.row
.col-md-4.gl-mb-6
diff --git a/app/views/admin/deploy_keys/edit.html.haml b/app/views/admin/deploy_keys/edit.html.haml
index 12a1c0c3de2..acdf503727d 100644
--- a/app/views/admin/deploy_keys/edit.html.haml
+++ b/app/views/admin/deploy_keys/edit.html.haml
@@ -3,8 +3,8 @@
%hr
%div
- = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
+ = gitlab_ui_form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
= link_to _('Cancel'), admin_deploy_keys_path, class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml
index 74882900756..a03d6cb5a94 100644
--- a/app/views/admin/deploy_keys/new.html.haml
+++ b/app/views/admin/deploy_keys/new.html.haml
@@ -3,8 +3,9 @@
%hr
%div
- = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
+ = gitlab_ui_form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
- = f.submit 'Create', class: 'btn gl-button btn-confirm', data: { qa_selector: "add_deploy_key_button" }
- = link_to _('Cancel'), admin_deploy_keys_path, class: 'btn gl-button btn-default btn-cancel'
+ = f.submit 'Create', data: { qa_selector: "add_deploy_key_button" }, pajamas_button: true
+ = render Pajamas::ButtonComponent.new(href: admin_deploy_keys_path) do
+ = _('Cancel')
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 69e9e4260b4..7adba0d023b 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -35,10 +35,10 @@
= c.body do
= render 'shared/group_tips'
.gl-mt-5
- = f.submit _('Create group'), class: "gl-button btn btn-confirm"
+ = f.submit _('Create group'), pajamas_button: true
= link_to _('Cancel'), admin_groups_path, class: "gl-button btn btn-default btn-cancel"
- else
.gl-mt-5
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
= link_to _('Cancel'), admin_group_path(@group), class: "gl-button btn btn-cancel"
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index c27ff348f59..a1afb1ddbfa 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -1,7 +1,6 @@
- group = local_assigns.fetch(:group)
-- css_class = "gl-display-flex!#{' no-description' if group.description.blank?}"
-%li.group-row.gl-py-3.gl-align-items-center{ class: css_class, data: { qa_selector: 'group_row_content' } }
+%li.group-row.gl-py-3.gl-align-items-center{ class: 'gl-display-flex!', data: { qa_selector: 'group_row_content' } }
.avatar-container.rect-avatar.s40.gl-flex-shrink-0
= group_icon(group, class: "avatar s40")
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index a57d3170cbd..6d370919460 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -13,123 +13,112 @@
%hr
.row
.col-md-6
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
+ - c.header do
= _('Group info:')
- %ul.content-list
- %li
- .avatar-container.rect-avatar.s60
- = group_icon(@group, class: "avatar s60")
- %li
- %span.light= _('Name:')
- %strong
- = link_to @group.name, group_path(@group)
- %li
- %span.light= _('Path:')
- %strong
- = @group.path
-
- %li
- %span.light= _('Description:')
- %strong
- = @group.description
-
- %li
- %span.light= _('Visibility level:')
- %strong
- = visibility_level_label(@group.visibility_level)
-
- %li
- %span.light= _('Created on:')
- %strong
- = @group.created_at.to_s(:medium)
-
- %li
- %span.light= _('ID:')
- %strong
- = @group.id
-
- = render_if_exists 'admin/namespace_plan_info', namespace: @group
-
- %li
- = render 'shared/storage_counter_statistics', storage_size: @group.storage_size, storage_details: @group
-
- %li
- %span.light= _('Group Git LFS status:')
- %strong
- = group_lfs_status(@group)
- = link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
-
- = render_if_exists 'namespaces/shared_runner_status', namespace: @group
- = render_if_exists 'namespaces/additional_minutes_status', namespace: @group
+ - c.body do
+ %ul.content-list.content-list-items-padding
+ %li
+ .avatar-container.rect-avatar.s60
+ = group_icon(@group, class: "avatar s60")
+ %li
+ %span.light= _('Name:')
+ %strong
+ = link_to @group.name, group_path(@group)
+ %li
+ %span.light= _('Path:')
+ %strong
+ = @group.path
+
+ %li
+ %span.light= _('Description:')
+ %strong
+ = @group.description
+
+ %li
+ %span.light= _('Visibility level:')
+ %strong
+ = visibility_level_label(@group.visibility_level)
+
+ %li
+ %span.light= _('Created on:')
+ %strong
+ = @group.created_at.to_s(:medium)
+
+ %li
+ %span.light= _('ID:')
+ %strong
+ = @group.id
+
+ = render_if_exists 'admin/namespace_plan_info', namespace: @group
+
+ %li
+ = render 'shared/storage_counter_statistics', storage_size: @group.storage_size, storage_details: @group
+
+ %li
+ %span.light= _('Group Git LFS status:')
+ %strong
+ = group_lfs_status(@group)
+ = link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
+
+ = render_if_exists 'namespaces/shared_runner_status', namespace: @group
+ = render_if_exists 'namespaces/additional_minutes_status', namespace: @group
= render 'shared/custom_attributes', custom_attributes: @group.custom_attributes
= render_if_exists 'ldap_group_links/ldap_group_links_show', group: @group
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
+ - c.header do
= _('Projects')
= gl_badge_tag @group.projects.count
- %ul.content-list
- - @projects.each do |project|
- %li
- %strong
- = link_to project.full_name, [:admin, project]
- = 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
- .card-footer
- = paginate @projects, param_name: 'projects_page', theme: 'gitlab'
-
- - shared_projects = @group.shared_projects.sort_by(&:name)
- - unless shared_projects.empty?
- .card
- .card-header
- = _('Projects shared with %{group_name}') % { group_name: @group.name }
- = gl_badge_tag shared_projects.size
- %ul.content-list
- - shared_projects.each do |project|
+ - c.body do
+ %ul.content-list.content-list-items-padding
+ - @projects.each do |project|
%li
%strong
= link_to project.full_name, [:admin, project]
= 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
+ - c.footer do
+ = paginate @projects, param_name: 'projects_page', theme: 'gitlab'
+
+ - shared_projects = @group.shared_projects.sort_by(&:name)
+ - unless shared_projects.empty?
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
+ - c.header do
+ = _('Projects shared with %{group_name}') % { group_name: @group.name }
+ = gl_badge_tag shared_projects.size
+ - c.body do
+ %ul.content-list.content-list-items-padding
+ - shared_projects.each do |project|
+ %li
+ %strong
+ = link_to project.full_name, [:admin, project]
+ = gl_badge_tag storage_counter(project.statistics.storage_size)
+ %span.float-right.light
+ %span.monospace= project.full_path + '.git'
.col-md-6
= render 'shared/admin/admin_note'
- if can?(current_user, :admin_group_member, @group)
- .card
- .card-header
- = _('Add user(s) to the group:')
- .card-body.form-holder
- %p.light
- - help_link_open = '<strong><a href="%{help_url}">'.html_safe % { help_url: help_page_url("user/permissions") }
- = html_escape(_('Read more about project permissions %{help_link_open}here%{help_link_close}')) % { help_link_open: help_link_open, help_link_close: '</a></strong>'.html_safe }
-
- = form_tag admin_group_members_update_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
- %div
- = users_select_tag(:user_id, multiple: true, email_user: true, skip_ldap: @group.ldap_synced?, scope: :all)
- .gl-mt-3
- = select_tag :access_level, options_for_select(@group.access_level_roles), class: "project-access-select select2"
- %hr
- = button_tag _('Add users to group'), class: "gl-button btn btn-confirm"
= render 'shared/members/requests', membership_source: @group, group: @group, requesters: @requesters, force_mobile_view: true
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
+ - c.header do
= html_escape(_("%{group_name} group members")) % { group_name: "<strong>#{html_escape(@group.name)}</strong>".html_safe }
= 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',
- collection: @members, as: :member,
- locals: { membership_source: @group,
- group: @group,
- current_user_is_group_owner: current_user_is_group_owner }
+ - c.body do
+ %ul.content-list.group-users-list.members-list
+ = render partial: 'shared/members/member',
+ collection: @members, as: :member,
+ locals: { membership_source: @group,
+ group: @group,
+ current_user_is_group_owner: current_user_is_group_owner }
- unless @members.size < Kaminari.config.default_per_page
- .card-footer
+ - c.footer do
= paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml
index 224afbff39a..14d37b77a41 100644
--- a/app/views/admin/hooks/edit.html.haml
+++ b/app/views/admin/hooks/edit.html.haml
@@ -11,7 +11,7 @@
= gitlab_ui_form_for @hook, as: :hook, url: admin_hook_path do |f|
= render partial: 'form', locals: { form: f, hook: @hook }
.form-actions
- %span>= f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mr-3'
+ %span>= f.submit _('Save changes'), class: 'gl-mr-3', pajamas_button: true
= render 'shared/web_hooks/test_button', hook: @hook
= link_to _('Delete'), admin_hook_path(@hook), method: :delete, class: 'btn gl-button btn-danger float-right', aria: { label: s_('Webhooks|Delete webhook') }, data: { confirm: s_('Webhooks|Are you sure you want to delete this webhook?'), confirm_btn_variant: 'danger' }
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index f23d77c8da5..d4aeb8dc7e8 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -7,7 +7,7 @@
.col-lg-8.gl-mb-3
= gitlab_ui_form_for @hook, as: :hook, url: admin_hooks_path do |f|
= render partial: 'form', locals: { form: f, hook: @hook }
- = f.submit _('Add system hook'), class: 'btn gl-button btn-confirm'
+ = f.submit _('Add system hook'), pajamas_button: true
= render 'shared/web_hooks/index', hooks: @hooks, hook_class: @hook.class
diff --git a/app/views/admin/impersonation_tokens/index.html.haml b/app/views/admin/impersonation_tokens/index.html.haml
index 2c526bb38d8..8cf1d8555ce 100644
--- a/app/views/admin/impersonation_tokens/index.html.haml
+++ b/app/views/admin/impersonation_tokens/index.html.haml
@@ -8,12 +8,10 @@
.row.gl-mt-3
.col-lg-12
- - if @new_impersonation_token
- = render 'shared/access_tokens/created_container',
- type: type,
- new_token_value: @new_impersonation_token
+ #js-new-access-token-app{ data: { access_token_type: type } }
= render 'shared/access_tokens/form',
+ ajax: true,
type: type,
title: _('Add an impersonation token'),
path: admin_user_impersonation_tokens_path,
@@ -22,9 +20,4 @@
scopes: @scopes,
help_path: help_page_path('api/index', anchor: 'impersonation-tokens')
- = render 'shared/access_tokens/table',
- type: type,
- type_plural: type_plural,
- impersonation: true,
- active_tokens: @active_impersonation_tokens,
- revoke_route_helper: ->(token) { revoke_admin_user_impersonation_token_path(token.user, token) }
+ #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_impersonation_tokens.to_json, information: _("To see all the user's personal access tokens you must impersonate them first.") } }
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index f56b77813b5..c7c30673d74 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -1,32 +1,33 @@
.js-projects-list-holder
- if @projects.any?
- %ul.projects-list.content-list.admin-projects
+ %ul.content-list
- @projects.each do |project|
- %li.project-row{ class: ('no-description' if project.description.blank?) }
- .controls
- = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button btn-default"
- %button.delete-project-button.gl-button.btn.btn-danger{ data: { delete_project_url: admin_project_path(project), project_name: project.name } }
- = s_('AdminProjects|Delete')
+ %li.project-row.gl-align-items-center{ class: 'gl-display-flex!' }
+ .avatar-container.rect-avatar.s40.gl-flex-shrink-0
+ = project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
+ .gl-min-w-0.gl-flex-grow-1
+ .title
+ = link_to(admin_project_path(project)) do
+ %span.project-full-name
+ %span.namespace-name
+ - if project.namespace
+ = project.namespace.human_name
+ \/
+ %span.project-name
+ = project.name
- .stats
+ - if project.description.present?
+ .description
+ = markdown_field(project, :description)
+ .stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
= 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
- .dash-project-avatar
- .avatar-container.rect-avatar.s40
- = project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
- %span.project-full-name
- %span.namespace-name
- - if project.namespace
- = project.namespace.human_name
- \/
- %span.project-name
- = project.name
- - if project.description.present?
- .description
- = markdown_field(project, :description)
+ .controls.gl-flex-shrink-0.gl-ml-5
+ = render Pajamas::ButtonComponent.new(href: edit_project_path(project), button_options: { id: dom_id(project, :edit) }) do
+ = s_('Edit')
+ = render Pajamas::ButtonComponent.new(variant: :danger, button_options: { class: 'delete-project-button', data: { delete_project_url: admin_project_path(project), project_name: project.name } } ) do
+ = s_('AdminProjects|Delete')
= paginate @projects, theme: 'gitlab'
- else
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index eabb7e51227..a60c3996cf2 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -2,7 +2,6 @@
- add_to_breadcrumbs _("Projects"), admin_projects_path
- breadcrumb_title @project.full_name
- page_title @project.full_name, _("Projects")
-- @content_class = "admin-projects"
- current_user_is_group_owner = @group && @group.has_owner?(current_user)
%h1.page-title.gl-font-size-h-display
diff --git a/app/views/admin/users/_projects.html.haml b/app/views/admin/users/_projects.html.haml
index a9f5c560b41..3ccf3ef4f2a 100644
--- a/app/views/admin/users/_projects.html.haml
+++ b/app/views/admin/users/_projects.html.haml
@@ -1,13 +1,17 @@
- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
- .card.contributed-projects
- .card-header= _('Projects contributed to')
- = render 'shared/projects/list',
- projects: contributed_projects.sort_by(&:star_count).reverse,
- projects_limit: 5, stars: true, avatar: false
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }) do |c|
+ - c.header do
+ = _('Projects contributed to')
+ - c.body do
+ = render 'shared/projects/list',
+ projects: contributed_projects.sort_by(&:star_count).reverse,
+ projects_limit: 5, stars: true, avatar: false
- if local_assigns.has_key?(:projects) && projects.present?
- .card
- .card-header= _('Personal projects')
- = render 'shared/projects/list',
- projects: projects.sort_by(&:star_count).reverse,
- projects_limit: 10, stars: true, avatar: false
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }) do |c|
+ - c.header do
+ = _('Personal projects')
+ - c.body do
+ = render 'shared/projects/list',
+ projects: projects.sort_by(&:star_count).reverse,
+ projects_limit: 10, stars: true, avatar: false
diff --git a/app/views/admin/users/_user_detail_note.html.haml b/app/views/admin/users/_user_detail_note.html.haml
index cc4827327c9..c8625833a70 100644
--- a/app/views/admin/users/_user_detail_note.html.haml
+++ b/app/views/admin/users/_user_detail_note.html.haml
@@ -1,7 +1,7 @@
- if @user.note.present?
- text = @user.note
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-pb-0'}) do |c|
+ - c.header do
= _('Admin Note')
- .card-body
+ - c.body do
%p= text
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index 2f6c08f123e..ff87cf8f866 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -4,20 +4,22 @@
= render 'admin/users/head'
- if @user.groups.any?
- .card
- .card-header= _('Groups')
- %ul.hover-list
- - @user.group_members.includes(:source).each do |group_member| # rubocop: disable CodeReuse/ActiveRecord
- - group = group_member.group
- %li.group_member
- %strong= link_to group.name, admin_group_path(group)
- &ndash; access to
- #{pluralize(group.projects.count, 'project')}
- .float-right
- %span.light.vertical-align-middle= group_member.human_access
- - unless group_member.owner?
- = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), confirm_btn_variant: 'danger', testid: 'remove-user' }, aria: { label: _('Remove') }, 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('remove', size: 16, css_class: 'gl-icon')
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0 gl-px-0'}) do |c|
+ - c.header do
+ = _('Groups')
+ - c.body do
+ %ul.hover-list
+ - @user.group_members.includes(:source).each do |group_member| # rubocop: disable CodeReuse/ActiveRecord
+ - group = group_member.group
+ %li.group_member
+ %strong= link_to group.name, admin_group_path(group)
+ &ndash; access to
+ #{pluralize(group.projects.count, 'project')}
+ .float-right
+ %span.light.vertical-align-middle= group_member.human_access
+ - unless group_member.owner?
+ = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), confirm_btn_variant: 'danger', testid: 'remove-user' }, aria: { label: _('Remove') }, 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('remove', size: 16, css_class: 'gl-icon')
.row
.col-md-6
@@ -28,23 +30,25 @@
.col-md-6
- .card
- .card-header= _('Joined projects (%{projects_count})') % { projects_count: @joined_projects.count }
- %ul.hover-list
- - @joined_projects.sort_by(&:full_name).each do |project|
- - member = project.team.find_member(@user.id)
- %li.project_member
- .list-item-name
- = link_to admin_project_path(project), class: dom_class(project) do
- = project.full_name
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0 gl-px-0'}) do |c|
+ - c.header do
+ = _('Joined projects (%{projects_count})') % { projects_count: @joined_projects.count }
+ - c.body do
+ %ul.hover-list
+ - @joined_projects.sort_by(&:full_name).each do |project|
+ - member = project.team.find_member(@user.id)
+ %li.project_member
+ .list-item-name
+ = link_to admin_project_path(project), class: dom_class(project) do
+ = project.full_name
- - if member
- .float-right
- - if member.owner?
- %span.light= _('Owner')
- - else
- %span.light.vertical-align-middle= member.human_access
+ - if member
+ .float-right
+ - if member.owner?
+ %span.light= _('Owner')
+ - else
+ %span.light.vertical-align-middle= member.human_access
- - if member.respond_to? :project
- = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member), confirm_btn_variant: 'danger' }, aria: { label: _('Remove') }, 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('remove', size: 16, css_class: 'gl-icon')
+ - if member.respond_to? :project
+ = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member), confirm_btn_variant: 'danger' }, aria: { label: _('Remove') }, 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('remove', size: 16, css_class: 'gl-icon')
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 9197d6684e0..7edea81a123 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -5,138 +5,140 @@
.row
.col-md-6
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-2'}) do |c|
+ - c.header do
= @user.name
- %ul.content-list
- %li
- = image_tag avatar_icon_for_user(@user, 60, current_user: current_user), class: "avatar s60"
- %li
- %span.light= _('Profile page:')
- %strong
- = link_to user_path(@user) do
- = @user.username
+ - c.body do
+ %ul.content-list
+ %li
+ = render Pajamas::AvatarComponent.new(@user, size: 64, class: 'gl-mr-3')
+ %li
+ %span.light= _('Profile page:')
+ %strong
+ = link_to user_path(@user) do
+ = @user.username
-# Rendered on mobile only so order of cards can be different on desktop vs mobile
.gl-md-display-none
= render 'admin/users/profile', user: @user
= render 'admin/users/user_detail_note'
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-2'}) do |c|
+ - c.header do
= _('Account:')
- %ul.content-list
- %li
- %span.light= _('Name:')
- %strong= @user.name
- %li
- %span.light= _('Username:')
- %strong
- = @user.username
- %li
- %span.light= _('Email:')
- %strong
- = render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
- - @user.emails.reject(&:user_primary_email?).each do |email|
- %li
- %span.light= _('Secondary email:')
+ - c.body do
+ %ul.content-list
+ %li
+ %span.light= _('Name:')
+ %strong= @user.name
+ %li
+ %span.light= _('Username:')
%strong
- = render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
- = link_to remove_email_admin_user_path(@user, email), data: { confirm: _("Are you sure you want to remove %{email}?") % { email: email.email }, 'confirm-btn-variant': 'danger' }, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon float-right", title: _('Remove secondary email'), id: "remove_email_#{email.id}" do
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
- %li
- %span.light ID:
- %strong{ data: { qa_selector: 'user_id_content' } }
- = @user.id
- %li
- %span.light= _('Namespace ID:')
- %strong
- = @user.namespace_id
-
- %li.two-factor-status
- %span.light= _('Two-factor Authentication:')
- %strong{ class: @user.two_factor_enabled? ? 'cgreen' : 'cred' }
- - if @user.two_factor_enabled?
- = _('Enabled')
- = link_to _('Disable'), disable_two_factor_admin_user_path(@user), aria: { label: _('Disable') }, data: { confirm: _('Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :patch, class: 'btn gl-button btn-sm btn-danger float-right', title: _('Disable Two-factor Authentication')
- - else
- = _('Disabled')
-
- = render_if_exists 'admin/namespace_plan_info', namespace: @user.namespace
-
- %li
- %span.light= _('External User:')
- %strong
- = @user.external? ? _('Yes') : _('No')
-
- = render_if_exists 'admin/users/provisioned_by', user: @user
-
- %li
- %span.light= _('Can create groups:')
- %strong
- = @user.can_create_group ? _('Yes') : _('No')
- %li
- %span.light= _('Personal projects limit:')
- %strong
- = @user.projects_limit
- %li
- %span.light= _('Member since:')
- %strong
- = @user.created_at.to_s(:medium)
- - if @user.confirmed_at
- %li
- %span.light= _('Confirmed at:')
+ = @user.username
+ %li
+ %span.light= _('Email:')
%strong
- = @user.confirmed_at.to_s(:medium)
- - else
+ = render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
+ - @user.emails.reject(&:user_primary_email?).each do |email|
+ %li
+ %span.light= _('Secondary email:')
+ %strong
+ = render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
+ = link_to remove_email_admin_user_path(@user, email), data: { confirm: _("Are you sure you want to remove %{email}?") % { email: email.email }, 'confirm-btn-variant': 'danger' }, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon float-right", title: _('Remove secondary email'), id: "remove_email_#{email.id}" do
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
%li
- %span.ligh= _('Confirmed:')
- %strong.cred
- = _('No')
+ %span.light ID:
+ %strong{ data: { qa_selector: 'user_id_content' } }
+ = @user.id
+ %li
+ %span.light= _('Namespace ID:')
+ %strong
+ = @user.namespace_id
- %li
- %span.light= _('Current sign-in IP:')
- %strong
- = @user.current_sign_in_ip || _('never')
+ %li.two-factor-status
+ %span.light= _('Two-factor Authentication:')
+ %strong{ class: @user.two_factor_enabled? ? 'cgreen' : 'cred' }
+ - if @user.two_factor_enabled?
+ = _('Enabled')
+ = link_to _('Disable'), disable_two_factor_admin_user_path(@user), aria: { label: _('Disable') }, data: { confirm: _('Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :patch, class: 'btn gl-button btn-sm btn-danger float-right', title: _('Disable Two-factor Authentication')
+ - else
+ = _('Disabled')
- %li
- %span.light= _('Current sign-in at:')
- %strong
- = @user.current_sign_in_at&.to_s(:medium) || _('never')
+ = render_if_exists 'admin/namespace_plan_info', namespace: @user.namespace
- %li
- %span.light= _('Last sign-in IP:')
- %strong
- = @user.last_sign_in_ip || _('never')
+ %li
+ %span.light= _('External User:')
+ %strong
+ = @user.external? ? _('Yes') : _('No')
- %li
- %span.light= _('Last sign-in at:')
- %strong
- = @user.last_sign_in_at&.to_s(:medium) || _('never')
+ = render_if_exists 'admin/users/provisioned_by', user: @user
- %li
- %span.light= _('Sign-in count:')
- %strong
- = @user.sign_in_count
+ %li
+ %span.light= _('Can create groups:')
+ %strong
+ = @user.can_create_group ? _('Yes') : _('No')
+ %li
+ %span.light= _('Personal projects limit:')
+ %strong
+ = @user.projects_limit
+ %li
+ %span.light= _('Member since:')
+ %strong
+ = @user.created_at.to_s(:medium)
+ - if @user.confirmed_at
+ %li
+ %span.light= _('Confirmed at:')
+ %strong
+ = @user.confirmed_at.to_s(:medium)
+ - else
+ %li
+ %span.ligh= _('Confirmed:')
+ %strong.cred
+ = _('No')
- %li
- %span.light= _("Highest role:")
- %strong
- = Gitlab::Access.human_access_with_none(@user.highest_role)
+ %li
+ %span.light= _('Current sign-in IP:')
+ %strong
+ = @user.current_sign_in_ip || _('never')
- = render_if_exists 'admin/users/using_license_seat', user: @user
+ %li
+ %span.light= _('Current sign-in at:')
+ %strong
+ = @user.current_sign_in_at&.to_s(:medium) || _('never')
- - if @user.ldap_user?
%li
- %span.light= _('LDAP uid:')
+ %span.light= _('Last sign-in IP:')
%strong
- = @user.ldap_identity.extern_uid
+ = @user.last_sign_in_ip || _('never')
- - if @user.created_by
%li
- %span.light= _('Created by:')
+ %span.light= _('Last sign-in at:')
%strong
- = link_to @user.created_by.name, [:admin, @user.created_by]
+ = @user.last_sign_in_at&.to_s(:medium) || _('never')
+
+ %li
+ %span.light= _('Sign-in count:')
+ %strong
+ = @user.sign_in_count
+
+ %li
+ %span.light= _("Highest role:")
+ %strong
+ = Gitlab::Access.human_access_with_none(@user.highest_role)
+
+ = render_if_exists 'admin/users/using_license_seat', user: @user
+
+ - if @user.ldap_user?
+ %li
+ %span.light= _('LDAP uid:')
+ %strong
+ = @user.ldap_identity.extern_uid
+
+ - if @user.created_by
+ %li
+ %span.light= _('Created by:')
+ %strong
+ = link_to @user.created_by.name, [:admin, @user.created_by]
- = render_if_exists 'namespaces/shared_runner_status', namespace: @user.namespace
+ = render_if_exists 'namespaces/shared_runner_status', namespace: @user.namespace
= render_if_exists 'admin/users/credit_card_info', user: @user, link_to_match_page: true
diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml
index 6ed46847482..3952a450c4a 100644
--- a/app/views/award_emoji/_awards_block.html.haml
+++ b/app/views/award_emoji/_awards_block.html.haml
@@ -1,7 +1,7 @@
- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
- if api_awards_path
- .gl-display-flex.gl-flex-wrap.gl-justify-content-space-between
+ .gl-display-flex.gl-flex-wrap.gl-justify-content-space-between.gl-py-3
#js-vue-awards-block{ data: { path: api_awards_path, can_award_emoji: can?(current_user, :award_emoji, awardable).to_s } }
= yield
- else
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index 02c468cebd7..9ca11b35064 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -1,9 +1,11 @@
- save_endpoint = local_assigns.fetch(:save_endpoint, nil)
- if ci_variable_protected_by_default?
- %p.settings-message.text-center
- - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/index', anchor: 'protected-cicd-variables') }
- = s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = render Pajamas::AlertComponent.new(variant: :warning, show_icon: false, dismissible: false,
+ alert_options: { class: 'gl-mb-3'}) do |c|
+ = c.body do
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/index', anchor: 'protected-cicd-variables') }
+ = _('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- is_group = !@group.nil?
- is_project = !@project.nil?
diff --git a/app/views/ci/variables/_url_query_variable_row.html.haml b/app/views/ci/variables/_url_query_variable_row.html.haml
index 9c34daf88bd..77bcacdb94b 100644
--- a/app/views/ci/variables/_url_query_variable_row.html.haml
+++ b/app/views/ci/variables/_url_query_variable_row.html.haml
@@ -15,12 +15,12 @@
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
%select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control.custom-select.table-section.section-15{ name: variable_type_input_name }
= options_for_select(ci_variable_type_options, variable_type)
- %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.table-section.section-15{ type: "text",
+ %input.js-ci-variable-input-key.ci-variable-body-item.form-control.table-section.section-15{ type: "text",
name: key_input_name,
value: key,
placeholder: s_('CiVariables|Input variable key') }
.ci-variable-body-item.gl-show-field-errors.table-section.section-15.border-top-0.p-0
- %textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control{ rows: 1,
+ %textarea.js-ci-variable-input-value.js-secret-value.form-control{ rows: 1,
name: value_input_name,
placeholder: s_('CiVariables|Input variable value') }
= value
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index 483c767d029..c5e518d8526 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -18,14 +18,14 @@
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
%select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control.custom-select.table-section.section-15{ name: variable_type_input_name }
= options_for_select(ci_variable_type_options, variable_type)
- %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.gl-form-input.table-section.section-15{ type: "text",
+ %input.js-ci-variable-input-key.ci-variable-body-item.form-control.gl-form-input.table-section.section-15{ type: "text",
name: key_input_name,
value: key,
placeholder: s_('CiVariables|Input variable key') }
.ci-variable-body-item.gl-show-field-errors.table-section.section-15.border-top-0.p-0
- .form-control.js-secret-value-placeholder.qa-ci-variable-input-value.overflow-hidden{ class: ('hide' unless id) }
+ .form-control.js-secret-value-placeholder.overflow-hidden{ class: ('hide' unless id) }
= '*' * 17
- %textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control.gl-form-input{ class: ('hide' if id),
+ %textarea.js-ci-variable-input-value.js-secret-value.form-control.gl-form-input{ class: ('hide' if id),
rows: 1,
name: value_input_name,
placeholder: s_('CiVariables|Input variable value') }
diff --git a/app/views/clusters/clusters/_health.html.haml b/app/views/clusters/clusters/_health.html.haml
index 75609465eb3..9e7820d3136 100644
--- a/app/views/clusters/clusters/_health.html.haml
+++ b/app/views/clusters/clusters/_health.html.haml
@@ -1,4 +1,6 @@
-%section.settings.no-animate.expanded.cluster-health-graphs.qa-cluster-health-section#cluster-health
+- add_page_specific_style 'page_bundles/prometheus'
+
+%section.settings.no-animate.expanded.cluster-health-graphs#cluster-health
- if @cluster&.integration_prometheus_available?
#prometheus-graphs{ data: @cluster.health_data(clusterable) }
diff --git a/app/views/clusters/clusters/index.html.haml b/app/views/clusters/clusters/index.html.haml
index abe9cc9f27d..7bc782df119 100644
--- a/app/views/clusters/clusters/index.html.haml
+++ b/app/views/clusters/clusters/index.html.haml
@@ -1,3 +1,4 @@
+- add_page_specific_style 'page_bundles/clusters'
- breadcrumb_title _('Kubernetes')
- page_title _('Kubernetes Clusters')
diff --git a/app/views/clusters/clusters/user/_form.html.haml b/app/views/clusters/clusters/user/_form.html.haml
index bf7b24181c1..557c95f8478 100644
--- a/app/views/clusters/clusters/user/_form.html.haml
+++ b/app/views/clusters/clusters/user/_form.html.haml
@@ -36,7 +36,7 @@
= platform_kubernetes_field.form_group :authorization_type,
{ help: '%{help_text} %{help_link}'.html_safe % { help_text: rbac_help_text, help_link: rbac_help_link } } do
= platform_kubernetes_field.check_box :authorization_type,
- { class: 'qa-rbac-checkbox', label: s_('ClusterIntegration|RBAC-enabled cluster'),
+ { data: { qa_selector: 'rbac_checkbox'}, label: s_('ClusterIntegration|RBAC-enabled cluster'),
label_class: 'label-bold', inline: true }, 'rbac', 'abac'
.form-group
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index b6719834358..8a960602536 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -9,7 +9,7 @@
.signup-page
= render 'devise/shared/signup_box',
- url: registration_path(resource_name),
+ url: registration_path(resource_name, glm_tracking_params.to_hash),
button_text: _('Register'),
borderless: Feature.enabled?(:restyle_login_page, @project),
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index d06043c1750..7affbafbdeb 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -10,10 +10,10 @@
= label_tag :password
= password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control gl-form-input bottom", title: _("This field is required."), data: { qa_selector: 'password_field' }, required: true }
- if !hide_remember_me && devise_mapping.rememberable?
- .remember-me.gl-px-5
- %label{ for: "remember_me" }
- = check_box_tag :remember_me, '1', false, id: 'remember_me'
- %span= _('Remember me')
+ .gl-px-5
+ = render Pajamas::CheckboxTagComponent.new(name: 'remember_me') do |c|
+ = c.label do
+ = _('Remember me')
.submit-container.move-submit-down.gl-px-5.gl-pb-5
= submit_tag submit_message, class: "gl-button btn btn-confirm", data: { qa_selector: 'sign_in_button' }
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index d4f34a1cb3f..439a2fc4d96 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -13,8 +13,6 @@
%span.gl-button-text
= label_for_provider(provider)
- unless hide_remember_me
- %fieldset
- %label{ class: restyle_login_page_enabled ? 'gl-font-weight-normal' : '' }
- = check_box_tag :remember_me, nil, false
- %span
- = _('Remember me')
+ = render Pajamas::CheckboxTagComponent.new(name: 'remember_me', value: nil) do |c|
+ = c.label do
+ = _('Remember me')
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index e81a5928983..76c4cf41a2d 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -1,7 +1,7 @@
- show_password_form = local_assigns.fetch(:show_password_form, password_authentication_enabled_for_web?)
- render_signup_link = local_assigns.fetch(:render_signup_link, true)
-%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{"custom-provider-tabs" if any_form_based_providers_enabled?} #{"nav-links-unboxed" if Feature.enabled?(:restyle_login_page, @project)}" }
+%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{'custom-provider-tabs' if any_form_based_providers_enabled?} #{'nav-links-unboxed' if Feature.enabled?(:restyle_login_page, @project)}" }
- if crowd_enabled?
%li.nav-item
= link_to _("Crowd"), "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab', role: 'tab'
diff --git a/app/views/discussions/_discussion.html.haml b/app/views/discussions/_discussion.html.haml
index 477f6c73388..224930e28df 100644
--- a/app/views/discussions/_discussion.html.haml
+++ b/app/views/discussions/_discussion.html.haml
@@ -3,19 +3,13 @@
.timeline-entry-inner
.timeline-content
.discussion.js-toggle-container{ data: { discussion_id: discussion.id, is_expanded: expanded.to_s } }
- .discussion-header
- .timeline-icon
+ .discussion-header.gl-display-flex.gl--flex-center
+ .timeline-icon.gl-flex-shrink-0
= link_to user_path(discussion.author) do
- = image_tag avatar_icon_for_user(discussion.author), class: "avatar s40"
- .discussion-actions
- %button.note-action-button.discussion-toggle-button.js-toggle-button{ type: "button", class: ("js-toggle-lazy-diff" unless expanded) }
- = sprite_icon('chevron-up', css_class: "js-sidebar-collapse #{'hidden' unless expanded}")
- = sprite_icon('chevron-down', css_class: "js-sidebar-expand #{'hidden' if expanded}")
- %span.js-sidebar-collapse{ class: "#{'hidden' unless expanded}" }= _('Hide thread')
- %span.js-sidebar-expand{ class: "#{'hidden' if expanded}" }= _('Show thread')
+ = render Pajamas::AvatarComponent.new(discussion.author, size: 32, class: 'gl-mr-3')
= link_to_member(@project, discussion.author, avatar: false)
- .inline.discussion-headline-light
+ .inline.discussion-headline-light.gl-mx-3
= discussion.author.to_reference
started a thread
@@ -42,10 +36,16 @@
an old version of
the diff
-
= time_ago_with_tooltip(discussion.created_at, placement: "bottom", html_class: "note-created-ago")
= render "discussions/headline", discussion: discussion
+ .discussion-actions.gl-ml-auto
+ %button.note-action-button.discussion-toggle-button.js-toggle-button{ type: "button", class: ("js-toggle-lazy-diff" unless expanded) }
+ = sprite_icon('chevron-up', css_class: "js-sidebar-collapse #{'hidden' unless expanded}")
+ = sprite_icon('chevron-down', css_class: "js-sidebar-expand #{'hidden' if expanded}")
+ %span.js-sidebar-collapse{ class: "#{'hidden' unless expanded}" }= _('Hide thread')
+ %span.js-sidebar-expand{ class: "#{'hidden' if expanded}" }= _('Show thread')
+
.discussion-body.js-toggle-content{ class: ("hide" unless expanded) }
- if discussion.diff_discussion? && discussion.diff_file
= render "discussions/diff_with_notes", discussion: discussion
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index 1f6ac29bffc..7ef3461a7fb 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -6,7 +6,7 @@
= inline_event_icon(event)
- if event.target
%span.event-type.d-inline-block.gl-mr-2{ class: event.action_name }
- = event.action_name
+ = localized_action_name(event)
%span.event-target-type.gl-mr-2= event.target_type_name
= link_to event_target_path(event), class: 'has-tooltip event-target-link gl-mr-2', title: event.target_title do
= event.target.reference_link_text
diff --git a/app/views/groups/_import_group_from_another_instance_panel.html.haml b/app/views/groups/_import_group_from_another_instance_panel.html.haml
index a9234753aa2..d48bf0173a4 100644
--- a/app/views/groups/_import_group_from_another_instance_panel.html.haml
+++ b/app/views/groups/_import_group_from_another_instance_panel.html.haml
@@ -1,5 +1,5 @@
-= form_with url: configure_import_bulk_imports_path(namespace_id: params[:parent_id]), class: 'group-form gl-show-field-errors' do |f|
- .gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
+= gitlab_ui_form_with url: configure_import_bulk_imports_path(namespace_id: params[:parent_id]), class: 'gl-show-field-errors' do |f|
+ .gl-border-l-solid.gl-border-r-solid.gl-border-t-solid.gl-border-gray-100.gl-border-1.gl-p-5.gl-mt-4
.gl-display-flex.gl-align-items-center
%h4.gl-display-flex
= s_('GroupsNew|Import groups from another instance of GitLab')
@@ -32,4 +32,4 @@
id: 'import_gitlab_token',
data: { qa_selector: 'import_gitlab_token' }
.gl-border-gray-100.gl-border-solid.gl-border-1.gl-bg-gray-10.gl-p-5
- = f.submit s_('GroupsNew|Connect instance'), class: 'btn gl-button btn-confirm', data: { qa_selector: 'connect_instance_button' }
+ = f.submit s_('GroupsNew|Connect instance'), pajamas_button: true, data: { qa_selector: 'connect_instance_button' }
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 022777eea27..35e8b7dc977 100644
--- a/app/views/groups/_import_group_from_file_panel.html.haml
+++ b/app/views/groups/_import_group_from_file_panel.html.haml
@@ -2,7 +2,7 @@
- group_path = root_url
- group_path << parent.full_path + '/' if parent
-= form_for '', url: import_gitlab_group_path, namespace: 'import_group', class: 'group-form gl-show-field-errors', multipart: true do |f|
+= gitlab_ui_form_for '', url: import_gitlab_group_path, namespace: 'import_group', class: 'group-form gl-show-field-errors', multipart: true do |f|
.gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
%h4
= _('Import group from file')
@@ -22,4 +22,4 @@
.gl-mt-3
= render 'shared/file_picker_button', f: f, field: :file, help_text: nil, classes: 'gl-button btn-confirm-secondary gl-mr-2'
.gl-border-gray-100.gl-border-solid.gl-border-1.gl-bg-gray-10.gl-p-5
- = f.submit _('Import'), class: 'btn gl-button btn-confirm'
+ = f.submit _('Import'), pajamas_button: true
diff --git a/app/views/groups/_personalize.html.haml b/app/views/groups/_personalize.html.haml
index bae76952ef8..2f55aefb817 100644
--- a/app/views/groups/_personalize.html.haml
+++ b/app/views/groups/_personalize.html.haml
@@ -8,7 +8,7 @@
.row
.form-group.col-sm-4
= label :user, :role, _('Role')
- = select :user, :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { selected: @current_user.role }, class: 'form-control'
+ = select :user, :role, ::User.roles.keys.map { |role| [localized_user_roles[role] || role.titleize, role] }, { selected: @current_user.role }, class: 'form-control'
.row
.form-group.col-sm-4
diff --git a/app/views/groups/boards/index.html.haml b/app/views/groups/boards/index.html.haml
index bb56769bd3f..e5b5f6404bb 100644
--- a/app/views/groups/boards/index.html.haml
+++ b/app/views/groups/boards/index.html.haml
@@ -1 +1 @@
-= render "shared/boards/show", board: @boards.first
+= render "shared/boards/show", board: @board
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 33fcda6129c..6c4a8b53764 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,24 +1,18 @@
-- @can_bulk_update = can?(current_user, :admin_merge_request, @group) && @group.licensed_feature_available?(:group_bulk_edit)
+- @can_bulk_update = can?(current_user, :admin_merge_request, @group) && @group.licensed_feature_available?(:group_bulk_edit) && issuables_count_for_state(:merge_requests, :all) > 0
- page_title _("Merge requests")
-- if issuables_count_for_state(:merge_requests, :all) == 0
- = render 'shared/issuable/search_bar', type: :merge_requests
+.top-area
+ = render 'shared/issuable/nav', type: :merge_requests
+ - if current_user
+ .nav-controls
+ - if @can_bulk_update
+ = render_if_exists 'projects/merge_requests/bulk_update_button'
- = render 'shared/empty_states/merge_requests', project_select_button: true
-- else
- .top-area
- = render 'shared/issuable/nav', type: :merge_requests
- - if current_user
- .nav-controls
- - if @can_bulk_update
- = render_if_exists 'projects/merge_requests/bulk_update_button'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: _("merge request"), type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: _("merge request"), type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
+= render 'shared/issuable/search_bar', type: :merge_requests
+- if @can_bulk_update
+ = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :merge_requests
- = render 'shared/issuable/search_bar', type: :merge_requests
-
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :merge_requests
-
- = render 'shared/merge_requests'
+= render 'shared/merge_requests'
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index 3864b30eb1e..d4b1c3c27f1 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -21,8 +21,8 @@
.form-actions
- if @milestone.new_record?
- = f.submit _('Create milestone'), class: "btn-confirm gl-button btn", data: { qa_selector: "create_milestone_button" }
+ = f.submit _('Create milestone'), data: { qa_selector: "create_milestone_button" }, pajamas_button: true
= link_to _("Cancel"), group_milestones_path(@group), class: "btn gl-button btn-cancel"
- else
- = f.submit _('Update milestone'), class: "btn-confirm gl-button btn"
+ = f.submit _('Update milestone'), pajamas_button: true
= link_to _("Cancel"), group_milestone_path(@group, @milestone), class: "btn gl-button btn-cancel"
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 8384c906eeb..657a582bdc5 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -16,7 +16,7 @@
#import-group-pane.tab-pane
- if import_sources_enabled?
- - if Feature.enabled?(:bulk_import)
+ - if BulkImports::Features.enabled?
= render 'import_group_from_another_instance_panel'
.gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
= render 'import_group_from_file_panel'
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index d5c22d9b1f2..e7ae54a8879 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -2,45 +2,46 @@
- page_title _("Projects")
- @content_class = "limit-container-width" unless fluid_layout
-.card.gl-mt-3
- .card-header
- %strong= @group.name
- projects:
+= render Pajamas::CardComponent.new(card_options: { class: 'gl-mt-3 js-search-settings-section' }, header_options: { class: 'gl-display-flex' }, body_options: { class: 'gl-py-0' }) do |c|
+ - c.header do
+ .gl-flex-grow-1
+ = html_escape(_("%{strong_open}%{group_name}%{strong_close} projects:")) % { strong_open: '<strong>'.html_safe, group_name: @group.name, strong_close: '</strong>'.html_safe }
- if can? current_user, :admin_group, @group
.controls
- = link_to new_project_path(namespace_id: @group.id), class: "btn gl-button btn-sm btn-confirm" do
- New project
- %ul.projects-list.content-list.group-settings-projects
- - @projects.each do |project|
- %li.project-row{ class: ('no-description' if project.description.blank?) }
- .controls
- = link_to _('Members'), project_project_members_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button"
- = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button"
- = render 'delete_project_button', project: project
+ = render Pajamas::ButtonComponent.new(href: new_project_path(namespace_id: @group.id), size: :small, variant: :confirm) do
+ = _("New project")
+ - c.body do
+ %ul.content-list
+ - @projects.each do |project|
+ %li.project-row.gl-align-items-center{ class: 'gl-display-flex!' }
+ .avatar-container.rect-avatar.s40.gl-flex-shrink-0
+ = project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
+ .gl-min-w-0.gl-flex-grow-1
+ .title
+ = link_to project_path(project), class: 'js-prefetch-document' do
+ %span.project-full-name
+ %span.namespace-name
+ - if project.namespace
+ = project.namespace.human_name
+ \/
+ %span.project-name
+ = project.name
+ %span{ class: visibility_level_color(project.visibility_level) }
+ = visibility_level_icon(project.visibility_level)
- .stats
- = gl_badge_tag storage_counter(project.statistics&.storage_size)
- = render 'project_badges', project: project
+ - if project.description.present?
+ .description
+ = markdown_field(project, :description)
- .title
- = 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)
- %span.project-full-name
- %span.namespace-name
- - if project.namespace
- = project.namespace.human_name
- \/
- %span.project-name
- = project.name
- %span{ class: visibility_level_color(project.visibility_level) }
- = visibility_level_icon(project.visibility_level)
+ .stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
+ = gl_badge_tag storage_counter(project.statistics&.storage_size)
+ = render 'project_badges', project: project
- - if project.description.present?
- .description
- = markdown_field(project, :description)
- - if @projects.blank?
- .nothing-here-block This group has no projects yet
+ .controls.gl-flex-shrink-0.gl-ml-5
+ = link_to _('Members'), project_project_members_path(project), id: dom_id(project, :edit), class: "btn gl-button"
+ = link_to _('Edit'), edit_project_path(project), id: dom_id(project, :edit), class: "btn gl-button"
+ = render 'delete_project_button', project: project
+ - if @projects.blank?
+ .nothing-here-block= _("This group has no projects yet")
= paginate @projects, theme: "gitlab"
diff --git a/app/views/groups/settings/_pages_settings.html.haml b/app/views/groups/settings/_pages_settings.html.haml
index 456e0b0f1d0..441e9333630 100644
--- a/app/views/groups/settings/_pages_settings.html.haml
+++ b/app/views/groups/settings/_pages_settings.html.haml
@@ -1,5 +1,5 @@
-= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
+= gitlab_ui_form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
= render_if_exists 'shared/pages/max_pages_size_input', form: f
.gl-mt-3
- = f.submit s_('GitLabPages|Save changes'), class: 'btn gl-button btn-confirm'
+ = f.submit s_('GitLabPages|Save changes'), pajamas_button: true
diff --git a/app/views/groups/settings/access_tokens/index.html.haml b/app/views/groups/settings/access_tokens/index.html.haml
index ac6c5d1842c..5e3d814687e 100644
--- a/app/views/groups/settings/access_tokens/index.html.haml
+++ b/app/views/groups/settings/access_tokens/index.html.haml
@@ -4,7 +4,7 @@
- type_plural = _('group access tokens')
- @content_class = 'limit-container-width' unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4
%h4.gl-mt-0
= page_title
@@ -24,13 +24,11 @@
= _('You can enable group access token creation in %{link_start}group settings%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.col-lg-8
- - if @new_resource_access_token
- = render 'shared/access_tokens/created_container',
- type: type,
- new_token_value: @new_resource_access_token
+ #js-new-access-token-app{ data: { access_token_type: type } }
- if current_user.can?(:create_resource_access_tokens, @group)
= render 'shared/access_tokens/form',
+ ajax: true,
type: type,
path: group_settings_access_tokens_path(@group),
resource: @group,
@@ -41,10 +39,6 @@
prefix: :resource_access_token,
help_path: help_page_path('user/group/settings/group_access_tokens', anchor: 'scopes-for-a-group-access-token')
- = render 'shared/access_tokens/table',
- active_tokens: @active_resource_access_tokens,
- resource: @group,
- type: type,
- type_plural: type_plural,
- revoke_route_helper: ->(token) { revoke_group_settings_access_token_path(id: token) },
- no_active_tokens_message: _('This group has no active access tokens.')
+ #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_resource_access_tokens.to_json, no_active_tokens_message: _('This group has no active access tokens.'), show_role: true
+ } }
+
diff --git a/app/views/groups/settings/ci_cd/_form.html.haml b/app/views/groups/settings/ci_cd/_form.html.haml
index 59c67197f81..89e353b94b0 100644
--- a/app/views/groups/settings/ci_cd/_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_form.html.haml
@@ -1,6 +1,6 @@
.row.gl-mt-3
.col-lg-12
- = form_for group, url: group_settings_ci_cd_path(group, anchor: 'js-general-pipeline-settings') do |f|
+ = gitlab_ui_form_for group, url: group_settings_ci_cd_path(group, anchor: 'js-general-pipeline-settings') do |f|
%fieldset.builds-feature
.form-group
= f.label :max_artifacts_size, _('Maximum artifacts size'), class: 'label-bold'
@@ -8,4 +8,4 @@
%p.form-text.text-muted
= _("The maximum file size in megabytes for individual job artifacts.")
= link_to s_('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank', rel: 'noopener noreferrer'
- = f.submit _('Save changes'), class: "btn gl-button btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 88352ea351c..67b87f842f9 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -44,7 +44,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
- auto_devops_url = help_page_path('topics/autodevops/index')
- - quickstart_url = help_page_path('topics/autodevops/quick_start_guide')
+ - quickstart_url = help_page_path('topics/autodevops/cloud_deployments/auto_devops_with_gke')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
- quickstart_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: quickstart_url }
= s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
diff --git a/app/views/groups/settings/integrations/index.html.haml b/app/views/groups/settings/integrations/index.html.haml
index 1db8edb040b..ec99ceb5f8d 100644
--- a/app/views/groups/settings/integrations/index.html.haml
+++ b/app/views/groups/settings/integrations/index.html.haml
@@ -2,8 +2,9 @@
- page_title s_('Integrations|Group-level integration management')
- @content_class = 'limit-container-width' unless fluid_layout
-%h3= s_('Integrations|Group-level integration management')
+%section.js-search-settings-section
+ %h3= s_('Integrations|Group-level integration management')
-- integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
-%p= s_("Integrations|GitLab administrators can set up integrations that all projects in a group inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a project if the settings are necessary at that level. Learn more about %{integrations_link_start}group-level integration management%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, link_end: "</a>".html_safe }
-= render 'shared/integrations/index', integrations: @integrations
+ - integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
+ %p= s_("Integrations|GitLab administrators can set up integrations that all projects in a group inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a project if the settings are necessary at that level. Learn more about %{integrations_link_start}group-level integration management%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, link_end: "</a>".html_safe }
+ = render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index f474f8fbd3b..012a31c1ecf 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -3,9 +3,6 @@
- @skip_current_level_breadcrumb = true
- add_page_specific_style 'page_bundles/group'
-- if show_thanks_for_purchase_alert?
- = render_if_exists 'shared/thanks_for_purchase_alert', plan_title: plan_title, quantity: params[:purchased_quantity].to_i
-
= render_if_exists 'shared/qrtly_reconciliation_alert', group: @group
= render_if_exists 'shared/free_user_cap_alert', source: @group
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 3992cb527ed..eaa58580454 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -34,14 +34,14 @@
.row.gl-mt-3
.col-md-8
- .documentation-index.md
+ .md
= markdown(@help_index)
.col-md-4
.card.links-card
.card-header
= _('Quick help')
%ul.content-list
- %li= link_to _('See our website for help'), support_url
+ %li= link_to _('See our website for help'), support_url, { class: 'gl-text-blue-600!' }
%li
%button.btn-blank.btn-link.js-trigger-search-bar{ type: 'button' }
= _('Use the search bar on the top of this page')
@@ -49,5 +49,5 @@
%button.btn-blank.btn-link.js-trigger-shortcut{ type: 'button' }
= _('Use shortcuts')
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
- %li= link_to _('Get a support subscription'), "https://#{ApplicationHelper.promo_host}/pricing/"
- %li= link_to _('Compare GitLab editions'), "https://#{ApplicationHelper.promo_host}/features/#compare"
+ %li= link_to _('Get a support subscription'), "https://#{ApplicationHelper.promo_host}/pricing/", { class: 'gl-text-blue-600!' }
+ %li= link_to _('Compare GitLab editions'), "https://#{ApplicationHelper.promo_host}/features/#compare", { class: 'gl-text-blue-600!' }
diff --git a/app/views/help/instance_configuration.html.haml b/app/views/help/instance_configuration.html.haml
index b6d27123be4..4baedca820f 100644
--- a/app/views/help/instance_configuration.html.haml
+++ b/app/views/help/instance_configuration.html.haml
@@ -1,5 +1,5 @@
- page_title _('Instance Configuration')
-.documentation.md
+.md.gl-font-lg.gl-mt-3
%h1= _('Instance Configuration')
%p
diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml
index c41f6ea3ed4..39f45e8b649 100644
--- a/app/views/help/show.html.haml
+++ b/app/views/help/show.html.haml
@@ -1,5 +1,5 @@
- page_title @path.split("/").reverse.map(&:humanize)
- @content_class = "limit-container-width" unless fluid_layout
-.documentation.md.gl-mt-3
+.md.gl-font-lg.gl-mt-3
= markdown @markdown
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index 35fd5d6eda6..9ea52a8f82f 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -5,6 +5,7 @@
- paginatable = local_assigns.fetch(:paginatable, false)
- default_namespace_path = (local_assigns[:default_namespace] || current_user.namespace).full_path
- provider_title = Gitlab::ImportSources.title(provider)
+- optional_stages = local_assigns.fetch(:optional_stages, [])
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
@@ -18,4 +19,5 @@
default_target_namespace: default_namespace_path,
import_path: url_for([:import, provider, { format: :json }]),
filterable: filterable.to_s,
- paginatable: paginatable.to_s }.merge(extra_data) }
+ paginatable: paginatable.to_s,
+ optional_stages: optional_stages.to_json }.merge(extra_data) }
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 28836055e0e..9d4c0f62134 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -23,23 +23,21 @@
%p
= html_escape(_('Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. "By %{link_open}@johnsmith%{link_close}"). It will also associate and/or assign these issues and comments with the selected user.')) % { link_open: '<a href="#">'.html_safe, link_close: '</a>'.html_safe }
- .table-holder
- %table.table
- %thead
+ %table.table
+ %thead
+ %tr
+ %th= _("ID")
+ %th= _("Name")
+ %th= _("Email")
+ %th= _("GitLab User")
+ %tbody
+ - @user_map.each do |id, user|
%tr
- %th= _("ID")
- %th= _("Name")
- %th= _("Email")
- %th= _("GitLab User")
- %tbody
- - @user_map.each do |id, user|
- %tr
- %td= id
- %td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
- %td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
- %td
- = users_select_tag("users[#{id}][gitlab_user]", class: 'custom-form-control',
- scope: :all, email_user: true, selected: user[:gitlab_user])
+ %td= id
+ %td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control gl-form-input'
+ %td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control gl-form-input'
+ %td
+ .js-gitlab-user{ data: { name: "users[#{id}][gitlab_user]" } }
.form-actions
= submit_tag _('Continue to the next step'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index 1b556cd0f7f..25afe9a7b1b 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -7,4 +7,7 @@
- paginatable = Feature.enabled?(:remove_legacy_github_client)
-= render 'import/githubish_status', provider: 'github', paginatable: paginatable, default_namespace: @namespace
+= render 'import/githubish_status',
+ provider: 'github', paginatable: paginatable,
+ default_namespace: @namespace,
+ optional_stages: Gitlab::GithubImport::Settings.stages_array
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index ab4b3cf6afd..5a558d42802 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,8 +1,10 @@
--# We currently only support `alert`, `notice`, `success`, 'toast', and 'raw'
-- icons = {'alert' => 'error', 'notice' => 'information-o', 'success' => 'check-circle'}
-- type_to_variant = {'alert' => 'danger', 'notice' => 'info', 'success' => 'success'}
+- flash_container_no_margin = local_assigns.fetch(:flash_container_no_margin, false)
+- flash_container_class = ('flash-container-no-margin' if flash_container_no_margin)
+
+-# We currently only support `alert`, `notice`, `success`, `warning`, 'toast', and 'raw'
+- type_to_variant = {'alert' => 'danger', 'notice' => 'info', 'success' => 'success', 'warning' => 'warning'}
- closable = %w[alert notice success]
-.flash-container.flash-container-page.sticky{ data: { qa_selector: 'flash_container' } }
+.flash-container.flash-container-page.sticky{ data: { qa_selector: 'flash_container' }, class: flash_container_class }
- flash.each do |key, value|
- if key == 'toast' && value
.js-toast-message{ data: { message: value } }
@@ -11,9 +13,5 @@
- elsif value == I18n.t('devise.failure.unconfirmed')
= render 'shared/confirm_your_email_alert'
- elsif value
- %div{ class: "flash-#{key} mb-2", data: { testid: "alert-#{type_to_variant[key]}" } }
- = sprite_icon(icons[key], css_class: 'align-middle mr-1') unless icons[key].nil?
- %span= value
- - if closable.include?(key)
- %div{ class: "close-icon-wrapper js-close-icon" }
- = sprite_icon('close', css_class: 'close-icon gl-vertical-align-baseline!')
+ = render Pajamas::AlertComponent.new(variant: type_to_variant[key], dismissible: closable.include?(key), alert_options: {class: "flash-#{key}", data: { testid: "alert-#{type_to_variant[key]}" }}) do |c|
+ = c.with_body { value }
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 84eb2706929..2ac926a7fc3 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,5 +1,5 @@
- page_description brand_title unless page_description
-- site_name = "GitLab"
+- site_name = _('GitLab')
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml
index 61a57240ed5..f4f9f39c20e 100644
--- a/app/views/layouts/fullscreen.html.haml
+++ b/app/views/layouts/fullscreen.html.haml
@@ -1,11 +1,13 @@
+- minimal = local_assigns.fetch(:minimal, false)
!!! 5
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
%body{ class: "#{user_application_theme} #{user_tab_width} #{@body_class} fullscreen-layout", data: { page: body_data_page } }
= render 'peek/bar'
= header_message
- = render partial: "layouts/header/default", locals: { project: @project, group: @group }
- .mobile-overlay
+ - unless minimal
+ = render partial: "layouts/header/default", locals: { project: @project, group: @group }
+ .mobile-overlay
.hide-when-top-nav-responsive-open.gl--flex-full.gl-h-full{ class: nav ? ["layout-page", page_with_sidebar_class, "gl-mt-0!"]: '' }
- if defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
@@ -14,8 +16,9 @@
= render 'shared/outdated_browser'
= render "layouts/broadcast"
= yield :flash_message
- = render "layouts/flash"
+ = render "layouts/flash", flash_container_no_margin: true
.content-wrapper{ id: "content-body", class: "d-flex flex-column align-items-stretch" }
= yield
- = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto"
+ - unless minimal
+ = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto"
= footer_message
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index a00c5c186cc..b74dfd4d3a1 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -132,7 +132,7 @@
- if header_link?(:user_dropdown)
%li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { track_label: "profile_dropdown", track_action: "click_dropdown", track_value: "", qa_selector: 'user_menu', testid: 'user-menu' }, class: ('mr-0' if has_impersonation_link) }
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
- = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar", alt: current_user.name
+ = render Pajamas::AvatarComponent.new(current_user, size: 24, class: 'header-user-avatar', avatar_options: { data: { qa_selector: 'user_avatar_content' } })
= render_if_exists 'layouts/header/user_notification_dot', project: project, namespace: group
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu.dropdown-menu-right
diff --git a/app/views/layouts/header/_gitlab_version.html.haml b/app/views/layouts/header/_gitlab_version.html.haml
index 125fbaa084c..fae6926a687 100644
--- a/app/views/layouts/header/_gitlab_version.html.haml
+++ b/app/views/layouts/header/_gitlab_version.html.haml
@@ -1,6 +1,6 @@
- return unless show_version_check?
-.gl-display-flex.gl-flex-direction-column.gl-px-4.gl-py-3
+%a{ class: 'gl-display-flex! gl-flex-direction-column gl-px-4! gl-py-3! gl-line-height-24!', href: help_page_path('update/index'), 'data-testid': 'gitlab-version-container' }
%span
= s_("VersionCheck|Your GitLab Version")
= emoji_icon('rocket')
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 3a8f9c1ae8d..bdd1ae291fd 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -1,6 +1,7 @@
%ul
- if current_user_menu?(:help)
- = render 'layouts/header/gitlab_version'
+ %li
+ = render 'layouts/header/gitlab_version'
= render_if_exists 'layouts/header/help_dropdown/cross_stage_fdm'
= render 'layouts/header/whats_new_dropdown_item'
%li
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
index e5b03acbe3b..9801b0cc055 100644
--- a/app/views/layouts/header/_new_dropdown.html.haml
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -24,4 +24,4 @@
= menu_item.fetch(:title)
- if menu_item.fetch(:emoji)
-# We need to insert a space between the title and emoji
- = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe
+ = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 56f333664df..8815dec5a6b 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,4 +1,4 @@
-%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation'), data: { qa_selector: 'admin_sidebar_content' } }
.nav-sidebar-inner-scroll
.context-header
= link_to admin_root_path, title: _('Admin Overview'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
@@ -6,7 +6,7 @@
= sprite_icon('admin', size: 18)
%span.sidebar-context-title
= _('Admin Area')
- %ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
+ %ul.sidebar-top-level-items{ data: { qa_selector: 'admin_overview_submenu_content' } }
= nav_link(controller: %w[dashboard admin admin/projects users groups admin/topics jobs runners gitaly_servers cohorts], html_options: {class: 'home'}) do
= link_to admin_root_path, class: 'has-sub-items' do
.nav-icon-container
@@ -28,15 +28,15 @@
%span
= _('Projects')
= nav_link(controller: %w[users cohorts]) do
- = link_to admin_users_path, title: _('Users'), data: { qa_selector: 'users_overview_link' } do
+ = link_to admin_users_path, title: _('Users'), data: { qa_selector: 'admin_overview_users_link' } do
%span
= _('Users')
= nav_link(controller: :groups) do
- = link_to admin_groups_path, title: _('Groups'), data: { qa_selector: 'groups_overview_link' } do
+ = link_to admin_groups_path, title: _('Groups'), data: { qa_selector: 'admin_overview_groups_link' } do
%span
= _('Groups')
= nav_link(controller: [:admin, 'admin/topics']) do
- = link_to admin_topics_path, title: _('Topics'), data: { qa_selector: 'topics_overview_link' } do
+ = link_to admin_topics_path, title: _('Topics') do
%span
= _('Topics')
= nav_link path: 'jobs#index' do
@@ -75,13 +75,13 @@
= _('Usage Trends')
= nav_link(controller: admin_monitoring_nav_links) do
- = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' }, class: 'has-sub-items' do
+ = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_menu_link' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('monitor')
%span.nav-item-name
= _('Monitoring')
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_monitoring_submenu_content' } }
+ %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_monitoring_submenu_content' } }
= nav_link(controller: admin_monitoring_nav_links, html_options: { class: "fly-out-top-item" } ) do
= link_to admin_system_info_path do
%strong.fly-out-top-item-name
@@ -222,10 +222,10 @@
= link_to general_admin_application_settings_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('settings')
- %span.nav-item-name.qa-admin-settings-item
+ %span.nav-item-name{ data: { qa_selector: 'admin_settings_menu_link' } }
= _('Settings')
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_settings_submenu_content' } }
+ %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_settings_submenu_content' } }
-# This active_nav_link check is also used in `app/views/layouts/admin.html.haml`
= nav_link(controller: [:application_settings, :integrations, :appearances], html_options: { class: "fly-out-top-item" } ) do
= link_to general_admin_application_settings_path do
@@ -233,24 +233,24 @@
= _('Settings')
%li.divider.fly-out-top-item
= nav_link(path: 'application_settings#general') do
- = link_to general_admin_application_settings_path, title: _('General'), class: 'qa-admin-settings-general-item' do
+ = link_to general_admin_application_settings_path, title: _('General'), data: { qa_selector: 'admin_settings_general_link' } do
%span
= _('General')
- = render_if_exists 'layouts/nav/sidebar/advanced_search', class: 'qa-admin-settings-advanced-search'
+ = render_if_exists 'layouts/nav/sidebar/advanced_search', data: { qa_selector: 'admin_settings_advanced_search_link' }
- if instance_level_integrations?
= nav_link(path: ['application_settings#integrations', 'integrations#edit']) do
- = link_to integrations_admin_application_settings_path, title: _('Integrations'), data: { qa_selector: 'integration_settings_link' } do
+ = link_to integrations_admin_application_settings_path, title: _('Integrations'), data: { qa_selector: 'admin_settings_integrations_link' } do
%span
= _('Integrations')
= nav_link(path: 'application_settings#repository') do
- = link_to repository_admin_application_settings_path, title: _('Repository'), class: 'qa-admin-settings-repository-item' do
+ = link_to repository_admin_application_settings_path, title: _('Repository'), data: { qa_selector: 'admin_settings_repository_link' } do
%span
= _('Repository')
- if Gitlab.ee? && License.feature_available?(:custom_file_templates)
= nav_link(path: 'application_settings#templates') do
- = link_to templates_admin_application_settings_path, title: _('Templates'), class: 'qa-admin-settings-template-item' do
+ = link_to templates_admin_application_settings_path, title: _('Templates'), data: { qa_selector: 'admin_settings_templates_link' } do
%span
= _('Templates')
= nav_link(path: 'application_settings#ci_cd') do
@@ -262,7 +262,7 @@
%span
= _('Reporting')
= nav_link(path: 'application_settings#metrics_and_profiling') do
- = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), class: 'qa-admin-settings-metrics-and-profiling-item' do
+ = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), data: { qa_selector: 'admin_settings_metrics_and_profiling_link' } do
%span
= _('Metrics and profiling')
= nav_link(path: ['application_settings#service_usage_data']) do
@@ -270,7 +270,7 @@
%span
= _('Service usage data')
= nav_link(path: 'application_settings#network') do
- = link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do
+ = link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_link' } do
%span
= _('Network')
= nav_link(controller: :appearances ) do
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index cf1f84790a2..0e3327935ca 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -2,8 +2,7 @@
.nav-sidebar-inner-scroll
.context-header
= link_to profile_path, title: _('Profile Settings'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
- %span{ class: ['avatar-container', 'settings-avatar', 's32'] }
- = image_tag avatar_icon_for_user(current_user, 32), class: ['avatar', 'avatar-tile', 'js-sidebar-user-avatar', 's32', 'gl-rounded-full!'], alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
+ = render Pajamas::AvatarComponent.new(current_user, size: 32, alt: current_user.name, class: 'gl-mr-3 js-sidebar-user-avatar', avatar_options: { data: { testid: 'sidebar-user-avatar' } })
%span.sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
@@ -52,17 +51,18 @@
= link_to profile_chat_names_path do
%strong.fly-out-top-item-name
= _('Chat')
- = nav_link(controller: :personal_access_tokens) do
- = link_to profile_personal_access_tokens_path do
- .nav-icon-container
- = sprite_icon('token')
- %span.nav-item-name
- = _('Access Tokens')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :personal_access_tokens, html_options: { class: "fly-out-top-item" } ) do
- = link_to profile_personal_access_tokens_path do
- %strong.fly-out-top-item-name
- = _('Access Tokens')
+ - unless Gitlab::CurrentSettings.personal_access_tokens_disabled?
+ = nav_link(controller: :personal_access_tokens) do
+ = link_to profile_personal_access_tokens_path do
+ .nav-icon-container
+ = sprite_icon('token')
+ %span.nav-item-name
+ = _('Access Tokens')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :personal_access_tokens, html_options: { class: "fly-out-top-item" } ) do
+ = link_to profile_personal_access_tokens_path do
+ %strong.fly-out-top-item-name
+ = _('Access Tokens')
= nav_link(controller: :emails) do
= link_to profile_emails_path, data: { qa_selector: 'profile_emails_link' } do
.nav-icon-container
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index d05b6951fbf..c557dc36534 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -24,7 +24,7 @@
- if @reply_by_email
= _('Reply to this email directly or %{view_it_on_gitlab}.').html_safe % { view_it_on_gitlab: link_to(_("view it on GitLab"), @target_url) }
- else
- #{link_to _("View it on GitLab"), @target_url}.
+ #{link_to _('View it on GitLab'), @target_url}.
%br
= notification_reason_text(reason: @reason, show_manage_notifications_link: !@labels_url, show_help_link: true, manage_label_subscriptions_url: @labels_url, unsubscribe_url: @unsubscribe_url, format: :html)
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index c9baf0cd2b8..032be73f70c 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -25,7 +25,7 @@
%ul.nav.navbar-nav
%li.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
- = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar", data: { qa_selector: 'user_avatar' }
+ = render Pajamas::AvatarComponent.new(current_user, size: 24, class: 'gl-mr-3', avatar_options: { data: { qa_selector: 'user_avatar_content' } })
= sprite_icon('chevron-down')
.dropdown-menu.dropdown-menu-right
= render 'layouts/header/current_user_dropdown'
diff --git a/app/views/notify/access_token_revoked_email.html.haml b/app/views/notify/access_token_revoked_email.html.haml
new file mode 100644
index 00000000000..4d9b9e14d14
--- /dev/null
+++ b/app/views/notify/access_token_revoked_email.html.haml
@@ -0,0 +1,7 @@
+%p
+ = _('Hi %{username}!') % { username: sanitize_name(@user.name) }
+%p
+ = html_escape(_('A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked.')) % { code_start: '<code>'.html_safe, token_name: @token_name, code_end: '</code>'.html_safe }
+%p
+ - pat_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: @target_url }
+ = html_escape(_('You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}.')) % { pat_link_start: pat_link_start, pat_link_end: '</a>'.html_safe }
diff --git a/app/views/notify/access_token_revoked_email.text.erb b/app/views/notify/access_token_revoked_email.text.erb
new file mode 100644
index 00000000000..17dd628d76c
--- /dev/null
+++ b/app/views/notify/access_token_revoked_email.text.erb
@@ -0,0 +1,5 @@
+<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
+
+<%= _('A personal access token, named %{token_name}, has been revoked.') % { token_name: @token_name } %>
+
+<%= _('You can check your tokens or create a new one in your personal access tokens settings %{pat_link}.') % { pat_link: @target_url } %>
diff --git a/app/views/notify/project_was_exported_email.html.haml b/app/views/notify/project_was_exported_email.html.haml
index 71c62f6be4e..11d761414ff 100644
--- a/app/views/notify/project_was_exported_email.html.haml
+++ b/app/views/notify/project_was_exported_email.html.haml
@@ -1,8 +1,8 @@
%p
- Project #{@project.name} was exported successfully.
+ = s_('Notify|Project %{project_name} was exported successfully.') % {project_name: @project.name}
%p
- The project export can be downloaded from:
- = link_to download_export_project_url(@project), rel: 'nofollow', download: '' do
- = @project.full_name + " export"
+ - project_link_url = download_export_project_url(@project)
+ - project_link_start = '<a href="%{url}" target="_blank" rel="nofollow" download="">'.html_safe % { url: project_link_url }
+ = html_escape(s_('Notify|%{project_link_start}Download%{project_link_end} the project export.')) % {project_link_start: project_link_start, project_link_end: '</a>'.html_safe}
%p
- The download link will expire in 24 hours.
+ = s_('Notify|The download link will expire in 24 hours.')
diff --git a/app/views/notify/project_was_moved_email.html.haml b/app/views/notify/project_was_moved_email.html.haml
index 1b6b1a81665..45bec221e08 100644
--- a/app/views/notify/project_was_moved_email.html.haml
+++ b/app/views/notify/project_was_moved_email.html.haml
@@ -1,15 +1,9 @@
+- repo_url_styles = "background: #f5f5f5; padding:10px; border:1px solid #ddd"
+- ssh_url_to_repo = content_tag(:p, "git remote set-url origin #{strip_tags(@project.ssh_url_to_repo)}", style: repo_url_styles)
+- http_url_to_repo = content_tag(:p, "git remote set-url origin #{strip_tags(@project.http_url_to_repo)}", style: repo_url_styles)
%p
- Project #{@old_path_with_namespace} was moved to another location
+ = s_('Notify|Project %{old_path_with_namespace} was moved to another location.') % { old_path_with_namespace: @old_path_with_namespace }
%p
- The project is now located under
- = link_to project_url(@project) do
- = @project.full_name
-%p
- To update the remote url in your local repository run (for ssh):
-%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
- git remote set-url origin #{@project.ssh_url_to_repo}
-%p
- or for http(s):
-%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
- git remote set-url origin #{@project.http_url_to_repo}
-%br
+ - project_full_name_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: project_url(@project) }
+ = html_escape(s_('Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}.')) % { project_full_name_link_start: project_full_name_link_start, link_end: '</a>'.html_safe, project_full_name: @project.full_name }
+= html_escape(s_('Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}')) % { p_start: '<p>'.html_safe, p_end: '</p>'.html_safe, ssh_url_to_repo: ssh_url_to_repo, http_url_to_repo: http_url_to_repo }
diff --git a/app/views/notify/project_was_not_exported_email.html.haml b/app/views/notify/project_was_not_exported_email.html.haml
index c888da29c17..dcd212099b5 100644
--- a/app/views/notify/project_was_not_exported_email.html.haml
+++ b/app/views/notify/project_was_not_exported_email.html.haml
@@ -1,7 +1,7 @@
%p
- Project #{@project.name} couldn't be exported.
+ = s_("Notify|Project %{project_name} couldn't be exported.") % {project_name: @project.name}
%p
- The errors we encountered were:
+ = s_('Notify|The errors we encountered were:')
%ul
- @errors.each do |error|
diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml
index 895d8807e47..2ba0a2cf4ab 100644
--- a/app/views/notify/repository_push_email.text.haml
+++ b/app/views/notify/repository_push_email.text.haml
@@ -13,7 +13,7 @@
\- - - - -
\
\
- #{pluralize @message.diffs_count, "changed file"}:
+ #{pluralize @message.diffs_count, 'changed file'}:
\
- @message.diffs.each do |diff_file|
- if diff_file.deleted_file?
diff --git a/app/views/notify/request_review_merge_request_email.html.haml b/app/views/notify/request_review_merge_request_email.html.haml
index d1f72f6529a..a8c7df79ff3 100644
--- a/app/views/notify/request_review_merge_request_email.html.haml
+++ b/app/views/notify/request_review_merge_request_email.html.haml
@@ -1,2 +1,2 @@
%p
- #{sanitize_name(@updated_by.name)} requested a new review on #{merge_request_reference_link(@merge_request)}.
+ = html_escape(s_('Notify|%{name} requested a new review on %{mr_link}.')) % {name: sanitize_name(@updated_by.name), mr_link: merge_request_reference_link(@merge_request).html_safe}
diff --git a/app/views/notify/send_unsubscribed_notification.html.haml b/app/views/notify/send_unsubscribed_notification.html.haml
index 9f68feeaa31..ef1577dde97 100644
--- a/app/views/notify/send_unsubscribed_notification.html.haml
+++ b/app/views/notify/send_unsubscribed_notification.html.haml
@@ -1,2 +1,2 @@
%p
- You have been unsubscribed from receiving GitLab administrator notifications.
+ = s_('Notify|You have been unsubscribed from receiving GitLab administrator notifications.')
diff --git a/app/views/notify/two_factor_otp_attempt_failed_email.html.haml b/app/views/notify/two_factor_otp_attempt_failed_email.html.haml
new file mode 100644
index 00000000000..fec7083e524
--- /dev/null
+++ b/app/views/notify/two_factor_otp_attempt_failed_email.html.haml
@@ -0,0 +1,51 @@
+- default_font = "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;"
+- default_style = "#{default_font}font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;"
+- spacer_style = "#{default_font};height:18px;font-size:18px;line-height:18px;"
+
+%tr.alert
+ %td{ style: "#{default_font}padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
+ %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
+ %tbody
+ %tr
+ %td{ style: "#{default_font}vertical-align:middle;color:#ffffff;text-align:center;" }
+ %span
+ = _("We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code") % { host: Gitlab.config.gitlab.host }
+%tr.spacer
+ %td{ style: spacer_style }
+ &nbsp;
+%tr.section
+ %td{ style: "#{default_font};padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
+ %table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
+ %tbody
+ %tr
+ %td{ style: default_style }
+ = _('Hostname')
+ %td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;" }
+ = Gitlab.config.gitlab.host
+ %tr
+ %td{ style: "#{default_style}border-top:1px solid #ededed;" }
+ = _('IP Address')
+ %td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
+ %span.muted{ style: "color:#333333;text-decoration:none;" }
+ = @ip
+ %tr
+ %td{ style: "#{default_style}border-top:1px solid #ededed;" }
+ = _('Time')
+ %td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
+ = @time.strftime('%Y-%m-%d %H:%M:%S %Z')
+%tr.spacer
+ %td{ style: spacer_style }
+ &nbsp;
+%tr.section
+ %td{ style: "#{default_font};line-height:1.4;text-align:center;padding:0 15px;overflow:hidden;" }
+ %table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
+ %tbody
+ %tr{ style: 'width:100%;' }
+ %td{ style: "#{default_style}text-align:center;" }
+ - password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
+ = _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
+
+ - if password_authentication_enabled_for_web?
+ %p
+ = _('If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}.').html_safe % { password_link_start: password_link_start, password_link_end: '</a>'.html_safe }
+ = _('Make sure you choose a strong, unique password.')
diff --git a/app/views/notify/two_factor_otp_attempt_failed_email.text.haml b/app/views/notify/two_factor_otp_attempt_failed_email.text.haml
new file mode 100644
index 00000000000..8f839cd83ee
--- /dev/null
+++ b/app/views/notify/two_factor_otp_attempt_failed_email.text.haml
@@ -0,0 +1,7 @@
+= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
+
+= _('We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}') % { host: Gitlab.config.gitlab.host, ip: @ip, time: @time }
+
+= _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
+= _('If you did not recently try to sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
+= _('Make sure you choose a strong, unique password.')
diff --git a/app/views/notify/unknown_sign_in_email.html.haml b/app/views/notify/unknown_sign_in_email.html.haml
index 47c5656db27..b1c79274e26 100644
--- a/app/views/notify/unknown_sign_in_email.html.haml
+++ b/app/views/notify/unknown_sign_in_email.html.haml
@@ -42,7 +42,7 @@
%tbody
%tr{ style: 'width:100%;' }
%td{ style: "#{default_style}text-align:center;" }
- - password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
+ - password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('If you recently signed in and recognize the IP address, you may disregard this email.')
- if password_authentication_enabled_for_web?
diff --git a/app/views/notify/unknown_sign_in_email.text.haml b/app/views/notify/unknown_sign_in_email.text.haml
index f3efc4c4fcd..54c7a245ab9 100644
--- a/app/views/notify/unknown_sign_in_email.text.haml
+++ b/app/views/notify/unknown_sign_in_email.text.haml
@@ -3,7 +3,7 @@
= _('A sign-in to your account has been made from the following IP address: %{ip}') % { ip: @ip }
= _('If you recently signed in and recognize the IP address, you may disregard this email.')
-= _('If you did not recently sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
+= _('If you did not recently sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('Passwords should be unique and not used for any other sites or services.')
- unless @user.two_factor_enabled?
diff --git a/app/views/profiles/active_sessions/index.html.haml b/app/views/profiles/active_sessions/index.html.haml
index be835233528..e9e6ca3ecce 100644
--- a/app/views/profiles/active_sessions/index.html.haml
+++ b/app/views/profiles/active_sessions/index.html.haml
@@ -1,7 +1,7 @@
- page_title _('Active Sessions')
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml
index 4bbb4a21b39..9997c8c4b4c 100644
--- a/app/views/profiles/audit_log.html.haml
+++ b/app/views/profiles/audit_log.html.haml
@@ -1,7 +1,7 @@
- page_title _('Authentication log')
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
index 54c34228800..41bd81d0250 100644
--- a/app/views/profiles/chat_names/index.html.haml
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -1,7 +1,7 @@
- page_title _('Chat')
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 1b8f0328a04..f4513d15a30 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -1,7 +1,7 @@
- page_title _('Emails')
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
@@ -10,12 +10,12 @@
.col-lg-8
%h4.gl-mt-0
= _('Add email address')
- = form_for 'email', url: profile_emails_path do |f|
+ = gitlab_ui_form_for 'email', url: profile_emails_path do |f|
.form-group
= f.label :email, _('Email'), class: 'label-bold'
= f.text_field :email, class: 'form-control gl-form-input', data: { qa_selector: 'email_address_field' }
.gl-mt-3
- = f.submit _('Add email address'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_email_address_button' }
+ = f.submit _('Add email address'), data: { qa_selector: 'add_email_address_button' }, pajamas_button: true
%hr
%h4.gl-mt-0
= _('Linked emails (%{email_count})') % { email_count: @emails.load.size }
diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml
index 9804a3b7735..ffd8bc3de27 100644
--- a/app/views/profiles/gpg_keys/_form.html.haml
+++ b/app/views/profiles/gpg_keys/_form.html.haml
@@ -1,5 +1,5 @@
%div
- = form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f|
+ = gitlab_ui_form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f|
= form_errors(@gpg_key)
.form-group
@@ -7,4 +7,4 @@
= f.text_area :key, class: "form-control gl-form-input", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.")
.gl-mt-3
- = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm"
+ = f.submit s_('Profiles|Add key'), pajamas_button: true
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 91af6953ee1..539a0cd1f0e 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -1,7 +1,8 @@
- page_title _('GPG Keys')
+- add_page_specific_style 'page_bundles/profile'
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 6f7eb21b7e0..b37a0d9cc1a 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -1,6 +1,6 @@
- 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|
+ = gitlab_ui_form_for [:profile, @key], html: { class: 'js-requires-input' } do |f|
= form_errors(@key)
.form-group
@@ -29,4 +29,4 @@
button_options: { class: 'js-add-ssh-key-validation-confirm-submit' }) do
= _("Yes, add it")
.gl-mt-3
- = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm js-add-ssh-key-validation-original-submit qa-add-key-button"
+ = f.submit s_('Profiles|Add key'), class: "js-add-ssh-key-validation-original-submit qa-add-key-button", pajamas_button: true
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index 8016d989ff1..04fa1d96204 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -1,39 +1,40 @@
- is_admin = defined?(admin) ? true : false
.row.gl-mt-3
.col-md-4
- .card
- .card-header
+ = render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0'}) do |c|
+ - c.header do
= _('SSH Key')
- %ul.content-list
- %li
- %span.light= _('Title:')
- %strong= @key.title
- %li
- %span.light= _('Created on:')
- %strong= @key.created_at.to_s(:medium)
- %li
- %span.light= _('Expires:')
- %strong= @key.expires_at.try(:to_s, :medium) || _('Never')
- %li
- %span.light= _('Last used on:')
- %strong= @key.last_used_at.try(:to_s, :medium) || _('Never')
+ - c.body do
+ %ul.content-list
+ %li
+ %span.light= _('Title:')
+ %strong= @key.title
+ %li
+ %span.light= _('Created on:')
+ %strong= @key.created_at.to_s(:medium)
+ %li
+ %span.light= _('Expires:')
+ %strong= @key.expires_at.try(:to_s, :medium) || _('Never')
+ %li
+ %span.light= _('Last used on:')
+ %strong= @key.last_used_at.try(:to_s, :medium) || _('Never')
.col-md-8
= form_errors(@key, type: 'key') unless @key.valid?
%pre.well-pre
= @key.key
- .card
- .card-header
+ = render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0'}) do |c|
+ - c.header do
= _('Fingerprints')
- %ul.content-list
- %li
- %span.light= 'MD5:'
- %code.key-fingerprint= @key.fingerprint
- - if @key.fingerprint_sha256.present?
+ - c.body do
+ %ul.content-list
%li
- %span.light= 'SHA256:'
- %code.key-fingerprint= @key.fingerprint_sha256
-
+ %span.light= 'MD5:'
+ %code.key-fingerprint= @key.fingerprint
+ - if @key.fingerprint_sha256.present?
+ %li
+ %span.light= 'SHA256:'
+ %code.key-fingerprint= @key.fingerprint_sha256
.col-md-12
.float-right
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 35bf7d81502..69e92b9e508 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -1,7 +1,8 @@
- page_title _('SSH Keys')
+- add_page_specific_style 'page_bundles/profile'
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index 0f4b130a774..23a0d824bfe 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -10,7 +10,7 @@
%li= msg
= hidden_field_tag :notification_type, 'global'
- .row.gl-mt-3
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 257255eb4d7..99c89dcebb4 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -2,7 +2,7 @@
- page_title _('Password')
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
@@ -14,7 +14,7 @@
= _('Change your password')
- else
= _('Change your password or recover your current one')
- = form_for @user, url: profile_password_path, method: :put, html: {class: "update-password"} do |f|
+ = gitlab_ui_form_for @user, url: profile_password_path, method: :put, html: {class: "update-password"} do |f|
= form_errors(@user)
- unless @user.password_automatically_set?
@@ -31,6 +31,7 @@
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
= f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.gl-mt-3.gl-mb-3
- = f.submit _('Save password'), class: "gl-button btn btn-confirm gl-mr-3", data: { qa_selector: 'save_password_button' }
+ = f.submit _('Save password'), class: "gl-mr-3", data: { qa_selector: 'save_password_button' }, pajamas_button: true
- unless @user.password_automatically_set?
- = link_to _('I forgot my password'), reset_profile_password_path, method: :put
+ = render Pajamas::ButtonComponent.new(href: reset_profile_password_path, variant: :link, method: :put) do
+ = _('I forgot my password')
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index 6f260eb4cc0..a0a9077afe4 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -3,7 +3,7 @@
%h1.page-title.gl-font-size-h-display= _('Set up new password')
%hr
-= form_for @user, url: profile_password_path, method: :post do |f|
+= gitlab_ui_form_for @user, url: profile_password_path, method: :post do |f|
%p.slead
= _('Please set a new password before proceeding.')
%br
@@ -29,4 +29,4 @@
.col-sm-10
= f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.form-actions
- = f.submit _('Set new password'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'set_new_password_button' }
+ = f.submit _('Set new password'), data: { qa_selector: 'set_new_password_button' }, pajamas_button: true
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index e16108c5c22..a1d6ef3fec5 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -104,6 +104,10 @@
= f.gitlab_ui_checkbox_component :markdown_surround_selection,
s_('Preferences|Surround text selection when typing quotes or brackets'),
help_text: sprintf(s_( "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."), { supported_characters: supported_characters }).html_safe
+ .form-group
+ = f.gitlab_ui_checkbox_component :markdown_automatic_lists,
+ s_('Preferences|Automatically add new list items'),
+ help_text: html_escape(s_('Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below.')) % { kbdOpen: '<kbd>'.html_safe, kbdClose: '</kbd>'.html_safe }
.form-group
= f.label :tab_width, s_('Preferences|Tab width'), class: 'label-bold'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index f38d6021b18..dfaa4c31cdf 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -1,5 +1,6 @@
- breadcrumb_title s_("Profiles|Edit Profile")
- page_title s_("Profiles|Edit Profile")
+- add_page_specific_style 'page_bundles/profile'
- @content_class = "limit-container-width" unless fluid_layout
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
@@ -25,15 +26,21 @@
.col-lg-8
.avatar-image
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 96), alt: '', class: 'avatar s96'
+ = render Pajamas::AvatarComponent.new(@user, size: 96, alt: "", class: 'gl-float-left gl-mr-5')
%h5.gl-mt-0= s_("Profiles|Upload new avatar")
- .gl-my-3
- %button.gl-button.btn.btn-default.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
- %span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.")
+ .gl-display-flex.gl-align-items-center.gl-my-3
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-choose-user-avatar-button' }) do
+ = s_("Profiles|Choose file...")
+ %span.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.")
= f.file_field :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*'
.gl-text-gray-500= s_("Profiles|The maximum file size allowed is 200KB.")
- if @user.avatar?
- = link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger-secondary btn-sm gl-mt-5'
+ = render Pajamas::ButtonComponent.new(variant: :danger,
+ category: :secondary,
+ href: profile_avatar_path,
+ button_options: { class: 'gl-mt-3', data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") } },
+ method: :delete) do
+ = s_("Profiles|Remove avatar")
.col-lg-12
%hr
.row.js-search-settings-section
@@ -54,9 +61,8 @@
%h4.gl-mt-0= s_("Profiles|Time settings")
%p= s_("Profiles|Set your local time zone.")
.col-lg-8
- %h5= _("Time zone")
- = dropdown_tag(_("Select a time zone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg gl-w-full!', title: _("Select a time zone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
- %input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
+ = f.label :user_timezone, _("Time zone")
+ .js-timezone-dropdown{ data: { timezone_data: timezone_data.to_json, initial_value: @user.timezone } }
.col-lg-12
%hr
.row.js-search-settings-section
@@ -134,9 +140,12 @@
= f.gitlab_ui_checkbox_component :include_private_contributions,
s_('Profiles|Include private contributions on my profile'),
help_text: s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information.")
- %hr
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm gl-mr-3 js-password-prompt-btn'
- = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-default btn-cancel'
+ .row.js-hide-when-nothing-matches-search
+ .col-lg-12
+ %hr
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-mr-3 js-password-prompt-btn', pajamas_button: true
+ = render Pajamas::ButtonComponent.new(href: user_path(current_user)) do
+ = s_('TagsPage|Cancel')
#password-prompt-modal
@@ -146,19 +155,19 @@
.modal-header
%h4.modal-title
= s_("Profiles|Position and size your new avatar")
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _("Close") }
- %span{ "aria-hidden": "true" } &times;
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ icon: 'close',
+ button_options: { class: 'close', "data-dismiss": "modal", "aria-label" => _("Close") })
.modal-body
.profile-crop-image-container
%img.modal-profile-crop-image{ alt: s_("Profiles|Avatar cropper") }
- .crop-controls
+ .gl-text-center.gl-mt-4
.btn-group
- %button.btn.gl-button.btn-default{ data: { method: 'zoom', option: '-0.1' } }
- %span
- = sprite_icon('search-minus')
- %button.btn.gl-button.btn-default{ data: { method: 'zoom', option: '0.1' } }
- %span
- = sprite_icon('search-plus')
+ = render Pajamas::ButtonComponent.new(icon: 'search-minus',
+ button_options: {data: { method: 'zoom', option: '-0.1' }})
+ = render Pajamas::ButtonComponent.new(icon: 'search-plus',
+ button_options: {data: { method: 'zoom', option: '0.1' }})
.modal-footer
- %button.btn.gl-button.btn-confirm.js-upload-user-avatar{ type: 'button' }
+ = render Pajamas::ButtonComponent.new(variant: :confirm,
+ button_options: { class: 'js-upload-user-avatar'}) do
= s_("Profiles|Set new profile picture")
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 855c73fd323..4c045574834 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -17,6 +17,13 @@
= _("You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.")
%p
= _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
+ - if @error
+ = render Pajamas::AlertComponent.new(title: @error[:message],
+ variant: :danger,
+ alert_options: { class: 'gl-mb-3' },
+ dismissible: false) do |c|
+ = c.body do
+ = link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
.js-manage-two-factor-form{ data: { webauthn_enabled: webauthn_enabled, current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
- else
@@ -46,6 +53,7 @@
- if @error
= render Pajamas::AlertComponent.new(title: @error[:message],
variant: :danger,
+ alert_options: { class: 'gl-mb-3' },
dismissible: false) do |c|
= c.body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/_fork_suggestion.html.haml b/app/views/projects/_fork_suggestion.html.haml
index 55e609c0ffb..47d60593b4a 100644
--- a/app/views/projects/_fork_suggestion.html.haml
+++ b/app/views/projects/_fork_suggestion.html.haml
@@ -2,6 +2,7 @@
- message = message_base.html_safe % { edit_start: '<span class="js-file-fork-suggestion-section-action">'.html_safe, edit_end: '</span>'.html_safe }
.js-file-fork-suggestion-section.file-fork-suggestion.hidden
%span.file-fork-suggestion-note= message
- = link_to s_('ForkSuggestion|Fork'), nil, method: :post, class: 'js-fork-suggestion-button gl-button btn btn-grouped btn-confirm-secondary'
- %button.js-cancel-fork-suggestion-button.gl-button.btn.btn-grouped{ type: 'button' }
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, category: :secondary, button_options: { class: "js-fork-suggestion-button btn-grouped" }) do
+ = s_('ForkSuggestion|Fork')
+ = render Pajamas::ButtonComponent.new(button_options: { class: "js-cancel-fork-suggestion-button btn-grouped" }) do
= s_('ForkSuggestion|Cancel')
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 7ff58d12b9c..a862b841008 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -24,7 +24,7 @@
%span.gl-ml-3.gl-mb-3
= render 'shared/members/access_request_links', source: @project
- = cache_if(cache_enabled, [@project, :buttons, current_user, @notification_setting], expires_in: 1.day) do
+ = cache_if(cache_enabled, [@project, @project.star_count, @project.forks_count, :buttons, current_user, @notification_setting], expires_in: 1.day) do
.project-repo-buttons.gl-display-flex.gl-justify-content-md-end.gl-align-items-start.gl-flex-wrap.gl-mt-5
- if current_user
- if current_user.admin?
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 98cd831d6f1..0699e39b420 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -92,5 +92,5 @@
-# this partial is from JiHu, see details in https://jihulab.com/gitlab-cn/gitlab/-/merge_requests/675
= render_if_exists 'shared/other_project_options', f: f, visibility_level: visibility_level, track_label: track_label
-= f.submit _('Create project'), class: "btn gl-button btn-confirm js-create-project-button", data: { qa_selector: 'project_create_button', track_label: "#{track_label}", track_action: "click_button", track_property: "create_project", track_value: "" }
+= f.submit _('Create project'), class: "js-create-project-button", data: { qa_selector: 'project_create_button', track_label: "#{track_label}", track_action: "click_button", track_property: "create_project", track_value: "" }, pajamas_button: true
= 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/_transfer.html.haml b/app/views/projects/_transfer.html.haml
index 02aa1f7e93b..e3aa2d8afc9 100644
--- a/app/views/projects/_transfer.html.haml
+++ b/app/views/projects/_transfer.html.haml
@@ -1,7 +1,7 @@
- return unless can?(current_user, :change_namespace, @project)
- form_id = "transfer-project-form"
- hidden_input_id = "new_namespace_id"
-- initial_data = { 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 }
+- initial_data = { 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, project_id: @project.id }
.sub-section
%h4.danger-title= _('Transfer project')
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index 3ebac785d55..c91dfe6d28e 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -1,5 +1,6 @@
- breadcrumb_title _('Artifacts')
- page_title @path.presence, _('Artifacts'), "#{@build.name} (##{@build.id})", _('Jobs')
+- add_page_specific_style 'page_bundles/tree'
= render "projects/jobs/header"
diff --git a/app/views/projects/artifacts/file.html.haml b/app/views/projects/artifacts/file.html.haml
index 1ad70506be4..e16e3ef266d 100644
--- a/app/views/projects/artifacts/file.html.haml
+++ b/app/views/projects/artifacts/file.html.haml
@@ -1,4 +1,5 @@
- page_title @path, _('Artifacts'), "#{@build.name} (##{@build.id})", _('Jobs')
+- add_page_specific_style 'page_bundles/tree'
= render "projects/jobs/header"
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index f2c4fe017f2..dd041377b49 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,6 +1,7 @@
- page_title _("Blame"), @blob.path, @ref
+- add_page_specific_style 'page_bundles/tree'
-#blob-content-holder.tree-holder{ data: { testid: 'blob-content-holder' } }
+#blob-content-holder.tree-holder.js-per-page{ data: { testid: 'blob-content-holder', per_page: @blame_per_page } }
= render "projects/blob/breadcrumb", blob: @blob, blame: true
.file-holder.gl-overflow-hidden
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 4139be053f8..9fd542e0cfb 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -10,7 +10,7 @@
%ul.blob-commit-info
= render 'projects/commits/commit', commit: @last_commit, project: @project, ref: @ref
- = render_if_exists 'projects/blob/owners', blob: blob
+ #js-code-owners{ data: { blob_path: blob.path, project_path: @project.full_path, branch: @ref } }
= render "projects/blob/auxiliary_viewer", blob: blob
#blob-content-holder.blob-content-holder
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 398ca3dd27c..bd08ab67cd3 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -28,16 +28,12 @@
.file-buttons.gl-display-flex.gl-align-items-center.gl-justify-content-end
- if is_markdown
- = render 'shared/blob/markdown_buttons', show_fullscreen_button: false
- = button_tag class: 'soft-wrap-toggle btn gl-button btn-default', type: 'button', tabindex: '-1' do
- .no-wrap
- = sprite_icon('soft-unwrap', css_class: 'gl-button-icon')
- %span.gl-button-text
- No wrap
- .soft-wrap
- = sprite_icon('soft-wrap', css_class: 'gl-button-icon')
- %span.gl-button-text
- Soft wrap
+ = render 'shared/blob/markdown_buttons', show_fullscreen_button: false, supports_file_upload: false
+ %span.soft-wrap-toggle
+ = render Pajamas::ButtonComponent.new(icon: 'soft-unwrap', button_options: { class: 'no-wrap' }) do
+ = _("No wrap")
+ = render Pajamas::ButtonComponent.new(icon: 'soft-wrap', button_options: { class: 'soft-wrap' }) do
+ = _("Soft wrap")
.file-editor.code
- if Feature.enabled?(:source_editor_toolbar, current_user)
diff --git a/app/views/projects/blob/_pipeline_tour_success.html.haml b/app/views/projects/blob/_pipeline_tour_success.html.haml
index 8f1c2f93162..0fa4a90e28b 100644
--- a/app/views/projects/blob/_pipeline_tour_success.html.haml
+++ b/app/views/projects/blob/_pipeline_tour_success.html.haml
@@ -2,5 +2,5 @@
'go-to-pipelines-path': project_pipelines_path(@project),
'project-merge-requests-path': project_merge_requests_path(@project),
'example-link': help_page_path('ci/examples/index.md', anchor: 'gitlab-cicd-examples'),
- 'code-quality-link': help_page_path('user/project/merge_requests/code_quality'),
+ 'code-quality-link': help_page_path('ci/testing/code_quality'),
'human-access': @project.team.human_max_access(current_user&.id) } }
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index a76e61bc3dd..249c474587c 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -2,14 +2,14 @@
.template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden
- toggle_text = should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : 'Select a template type'
- = dropdown_tag(_(toggle_text), options: { toggle_class: 'js-template-type-selector qa-template-type-dropdown', dropdown_class: 'dropdown-menu-selectable' })
+ = dropdown_tag(_(toggle_text), options: { toggle_class: 'js-template-type-selector', dropdown_class: 'dropdown-menu-selectable', data: { qa_selector: 'template_type_dropdown' } })
.license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-license-selector qa-license-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: licenses_for_select(@project), project: @project.name, fullname: @project.namespace.human_name } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-license-selector', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: licenses_for_select(@project), project: @project.name, fullname: @project.namespace.human_name, qa_selector: 'license_dropdown' } } )
.gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitignore-selector qa-gitignore-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitignore_names(@project) } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitignore-selector', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitignore_names(@project), qa_selector: 'gitignore_dropdown' } } )
.metrics-dashboard-selector.js-metrics-dashboard-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-metrics-dashboard-selector qa-metrics-dashboard-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: metrics_dashboard_ymls(@project) } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-metrics-dashboard-selector', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: metrics_dashboard_ymls(@project), qa_selector: 'metrics_dashboard_dropdown' } } )
#gitlab-ci-yml-selector.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project), selected: params[:template] } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitlab-ci-yml-selector', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project), selected: params[:template], qa_selector: 'gitlab_ci_yml_dropdown' } } )
.dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-dockerfile-selector qa-dockerfile-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: dockerfile_names(@project) } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-dockerfile-selector', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: dockerfile_names(@project), qa_selector: 'dockerfile_dropdown' } } )
diff --git a/app/views/projects/blob/preview.html.haml b/app/views/projects/blob/preview.html.haml
index 41a0045be89..6f559708d40 100644
--- a/app/views/projects/blob/preview.html.haml
+++ b/app/views/projects/blob/preview.html.haml
@@ -1,4 +1,4 @@
-- if markup?(@blob.name)
+- if Gitlab::MarkupHelper.markup?(@blob.name)
.file-content.md
= markup(@blob.name, @content)
- else
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 33b2229f5d1..c8cf12c36f9 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -1,5 +1,6 @@
- breadcrumb_title _('Repository')
- page_title @blob.path, @ref
+- add_page_specific_style 'page_bundles/tree'
- signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit, limit: 1)
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco', prefetch: true)
diff --git a/app/views/projects/boards/index.html.haml b/app/views/projects/boards/index.html.haml
index bb56769bd3f..e5b5f6404bb 100644
--- a/app/views/projects/boards/index.html.haml
+++ b/app/views/projects/boards/index.html.haml
@@ -1 +1 @@
-= render "shared/boards/show", board: @boards.first
+= render "shared/boards/show", board: @board
diff --git a/app/views/projects/branch_rules/_show.html.haml b/app/views/projects/branch_rules/_show.html.haml
index 46665fdb450..27525b441ab 100644
--- a/app/views/projects/branch_rules/_show.html.haml
+++ b/app/views/projects/branch_rules/_show.html.haml
@@ -9,4 +9,4 @@
= _('Define rules for who can push, merge, and the required approvals for each branch.')
.settings-content.gl-pr-0
- #js-branch-rules{ data: { project_path: @project.full_path } }
+ #js-branch-rules{ data: { project_path: @project.full_path, branch_rules_path: project_settings_repository_branch_rules_path(@project) } }
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index 10a6bc6b524..34aecd31c57 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -2,17 +2,17 @@
- dropdown_class = local_assigns.fetch(:dropdown_class, '')
.git-clone-holder.js-git-clone-holder
- %a#clone-dropdown.gl-button.btn.btn-confirm.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %a#clone-dropdown.gl-button.btn.btn-confirm.clone-dropdown-btn{ href: '#', data: { toggle: 'dropdown', qa_selector: 'clone_dropdown' } }
%span.gl-mr-2.js-clone-dropdown-label
= _('Clone')
= sprite_icon("chevron-down", css_class: "icon")
- %ul.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options{ class: dropdown_class }
+ %ul.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown{ class: dropdown_class, data: { qa_selector: 'clone_dropdown_content' } }
- if ssh_enabled?
%li{ class: 'gl-px-4!' }
%label.label-bold
= _('Clone with SSH')
.input-group.btn-group
- = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control qa-ssh-clone-url", readonly: true, aria: { label: _('Repository clone URL') }
+ = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'ssh_clone_url_content' }
.input-group-append
= clipboard_button(target: '#ssh_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default")
= render_if_exists 'projects/buttons/geo'
@@ -21,7 +21,7 @@
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group.btn-group
- = text_field_tag :http_project_clone, project.http_url_to_repo, class: "js-select-on-focus form-control qa-http-clone-url", readonly: true, aria: { label: _('Repository clone URL') }
+ = text_field_tag :http_project_clone, project.http_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'http_clone_url_content' }
.input-group-append
= clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default")
= render_if_exists 'projects/buttons/geo'
diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml
index f6084cfcde8..d36aed44e18 100644
--- a/app/views/projects/buttons/_download_links.html.haml
+++ b/app/views/projects/buttons/_download_links.html.haml
@@ -1,4 +1,4 @@
.btn-group.ml-0.w-100
- Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index|
- archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt)
- = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? "btn-confirm" : "btn-default"}"
+ = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? 'btn-confirm' : 'btn-default'}"
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index c57b6dbe28c..3621853430d 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -14,5 +14,5 @@
= 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 #{count_class}" 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 fork-count #{count_class}" do
= @project.forks_count
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index f607a21ad21..eaf906ad89f 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -1,15 +1,13 @@
- if current_user
+ - starred = current_user.starred?(@project)
+ - icon = starred ? 'star' : 'star-o'
+ - button_text = starred ? s_('ProjectOverview|Unstar') : s_('ProjectOverview|Star')
+ - button_text_classes = starred ? 'starred' : ''
.count-badge.d-inline-flex.align-item-stretch.gl-mr-3.btn-group
- %button.gl-button.btn.btn-default.btn-sm.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }
- - if current_user.starred?(@project)
- = sprite_icon('star', css_class: 'icon')
- %span.starred= s_('ProjectOverview|Unstar')
- - else
- = sprite_icon('star-o', css_class: 'icon')
- %span= s_('ProjectOverview|Star')
+ = render Pajamas::ButtonComponent.new(size: :small, icon: icon, button_text_classes: button_text_classes, button_options: { class: 'star-btn toggle-star', data: { endpoint: toggle_star_project_path(@project, :json) } }) do
+ - button_text
= link_to project_starrers_path(@project), title: n_(s_('ProjectOverview|Starrer'), s_('ProjectOverview|Starrers'), @project.star_count), class: 'gl-button btn btn-default btn-sm has-tooltip star-count count' do
= @project.star_count
-
- else
.count-badge.d-inline-flex.align-item-stretch.gl-mr-3.btn-group
= link_to new_user_session_path, class: 'gl-button btn btn-default btn-sm has-tooltip star-btn', title: s_('ProjectOverview|You must sign in to star a project') do
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index c53205b6c58..d00d9f62999 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -16,7 +16,7 @@
.settings-content
- url = cleanup_namespace_project_settings_repository_path(@project.namespace, @project)
- = form_for @project, url: url, method: :post, authenticity_token: true, html: { class: 'js-requires-input' } do |f|
+ = gitlab_ui_form_for @project, url: url, method: :post, authenticity_token: true, html: { class: 'js-requires-input' } do |f|
%fieldset.gl-mt-0.gl-mb-3
.gl-mb-3
%h5.gl-mt-0
@@ -29,4 +29,4 @@
.form-text.text-muted
= _("The maximum file size is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
- = f.submit _('Start cleanup'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Start cleanup'), pajamas_button: true
diff --git a/app/views/projects/cluster_agents/show.html.haml b/app/views/projects/cluster_agents/show.html.haml
index a2d3426d99c..98a2c9c3e6d 100644
--- a/app/views/projects/cluster_agents/show.html.haml
+++ b/app/views/projects/cluster_agents/show.html.haml
@@ -1,3 +1,4 @@
+- add_page_specific_style 'page_bundles/cluster_agents'
- add_to_breadcrumbs _('Kubernetes'), project_clusters_path(@project)
- page_title @agent_name
diff --git a/app/views/projects/commit/_signature.html.haml b/app/views/projects/commit/_signature.html.haml
index fb31ac44118..978d83bf2b4 100644
--- a/app/views/projects/commit/_signature.html.haml
+++ b/app/views/projects/commit/_signature.html.haml
@@ -1,3 +1,3 @@
- if signature
- - uri = "projects/commit/#{"x509/" if x509_signature?(signature)}"
+ - uri = "projects/commit/#{'x509/' if x509_signature?(signature)}"
= render partial: "#{uri}#{signature.verification_status}_signature_badge", locals: { signature: signature }
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index 7c896cd71ef..fb30bfc2953 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -17,7 +17,7 @@
- content = capture do
- if show_user
.clearfix
- - uri_signature_badge_user = "projects/commit/#{"x509/" if x509_signature?(signature)}signature_badge_user"
+ - uri_signature_badge_user = "projects/commit/#{'x509/' if x509_signature?(signature)}signature_badge_user"
= render partial: "#{uri_signature_badge_user}", locals: { signature: signature }
- if x509_signature?(signature)
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 6f44c130603..bf6b628dd36 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -29,7 +29,7 @@
- if view_details && merge_request
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: ["commit-row-message item-title js-onboarding-commit-item", ("font-italic" if commit.message.empty?)]
- else
- = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}", data: link_data_attrs)
+ = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{'font-italic' if commit.message.empty?}", data: link_data_attrs)
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id
@@ -51,7 +51,7 @@
= render_if_exists 'projects/commits/project_namespace', show_project_name: show_project_name, project: project
- if commit.description?
- %pre{ class: ["commit-row-description gl-mb-3", (collapsible ? "js-toggle-content" : "d-block")] }
+ %pre{ class: ["commit-row-description gl-mb-3 gl-white-space-pre-line", (collapsible ? "js-toggle-content" : "d-block")] }
= preserve(markdown_field(commit, :description))
.commit-actions.flex-row
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 6b06584ea25..ae68a13929e 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -1,5 +1,5 @@
- breadcrumb_title _("Commits")
-
+- add_page_specific_style 'page_bundles/tree'
- page_title _("Commits"), @ref
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_commits_path(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index 95186b85838..1bdf3d1e6e3 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -5,7 +5,7 @@
.js-signature-container{ data: { 'signatures-path' => signatures_namespace_project_compare_index_path } }
#js-compare-selector{ data: project_compare_selector_data(@project, @merge_request, params) }
-- if @commits.present?
+- if @commits.present? || @diffs.present?
-# Only show commit list in the first page
- hide_commit_list = params[:page].present? && params[:page] != '1'
= render "projects/commits/commit_list" unless hide_commit_list
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index eba0f336f80..04712cd59f7 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -17,7 +17,7 @@
- else
.form-group
= f.label :default_branch, _("Default branch"), class: 'label-bold'
- = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide', data: { qa_selector: 'default_branch_dropdown' }})
+ .js-select-default-branch{ data: { default_branch: @project.default_branch, project_id: @project.id } }
.form-group
- help_text = _("When merge requests and commits in the default branch close, any issues they reference also close.")
@@ -26,4 +26,4 @@
_("Auto-close referenced issues on default branch"),
help_text: (help_text + "&nbsp;" + help_icon).html_safe
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/projects/deploy_keys/edit.html.haml b/app/views/projects/deploy_keys/edit.html.haml
index 04e364d6b15..91444a00334 100644
--- a/app/views/projects/deploy_keys/edit.html.haml
+++ b/app/views/projects/deploy_keys/edit.html.haml
@@ -6,5 +6,5 @@
= gitlab_ui_form_for [@project, @deploy_key], include_id: false, html: { class: 'js-requires-input' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
= link_to _('Cancel'), project_settings_repository_path(@project), class: 'gl-button btn btn-default btn-cancel'
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index e92297a5a6a..e3688c8d323 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -23,7 +23,7 @@
- if deployment.deployable
.table-mobile-content
.flex-truncate-parent
- .flex-truncate-child
+ .flex-truncate-child.has-tooltip.gl-white-space-normal.gl-md-white-space-nowrap{ :title => "#{deployment.deployable.name} (##{deployment.deployable.id})", data: { container: 'body' } }
= link_to deployment_path(deployment), class: 'build-link' do
#{deployment.deployable.name} (##{deployment.deployable.id})
- else
diff --git a/app/views/projects/deployments/_rollback.haml b/app/views/projects/deployments/_rollback.haml
index a7befabdc96..223f7520b47 100644
--- a/app/views/projects/deployments/_rollback.haml
+++ b/app/views/projects/deployments/_rollback.haml
@@ -1,7 +1,4 @@
- if deployment.deployable && can?(current_user, :create_deployment, deployment)
- tooltip = deployment.last? ? s_('Environments|Re-deploy to environment') : s_('Environments|Rollback environment')
- = button_tag class: 'js-confirm-rollback-modal-button gl-button btn btn-default btn-icon has-tooltip', type: 'button', data: { environment_name: @environment.name, commit_short_sha: deployment.short_sha, commit_url: project_commit_path(@project, deployment.sha), is_last_deployment: deployment.last?.to_s, retry_path: retry_project_job_path(@environment.project, deployment.deployable) }, title: tooltip do
- - if deployment.last?
- = sprite_icon('repeat', css_class: 'gl-icon')
- - else
- = sprite_icon('redo', css_class: 'gl-icon')
+ - icon = deployment.last? ? 'repeat' : 'redo'
+ = render Pajamas::ButtonComponent.new(icon: icon, button_options: { title: tooltip, class: 'js-confirm-rollback-modal-button has-tooltip', data: { environment_name: @environment.name, commit_short_sha: deployment.short_sha, commit_url: project_commit_path(@project, deployment.sha), is_last_deployment: deployment.last?.to_s, retry_path: retry_project_job_path(@environment.project, deployment.deployable) } })
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 70df995cdf3..f6e3c15c08b 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -28,7 +28,7 @@
%template.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data(@project).to_json.html_safe
.js-project-permissions-form{ data: visibility_confirm_modal_data(@project, reduce_visibility_form_id) }
-- if show_merge_request_settings_callout?
+- if show_merge_request_settings_callout?(@project)
%section.settings.expanded
= render Pajamas::AlertComponent.new(variant: :info,
title: _('Merge requests and approvals settings have moved.'),
diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml
index cd7339edd1a..31041d124e4 100644
--- a/app/views/projects/environments/metrics.html.haml
+++ b/app/views/projects/environments/metrics.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/prometheus'
+
- page_title _("Metrics Dashboard"), @environment.name
.prometheus-container
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 2e024b8ffc4..7cd4ab08680 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -1,4 +1,5 @@
- page_title _("Find File"), @ref
+- add_page_specific_style 'page_bundles/tree'
.file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, format: :json))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @ref)) }
.nav-block
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index 04d400688d4..edf8f71c673 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -1,4 +1,5 @@
- page_title _("Repository Analytics")
+- add_page_specific_style 'page_bundles/graph_charts'
.mb-3
%h3
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index b350455807d..ca71990f5e3 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -12,7 +12,7 @@
= gitlab_ui_form_for [@project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mr-3'
+ = f.submit _('Save changes'), pajamas_button: true
= render 'shared/web_hooks/test_button', hook: @hook
= link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn gl-button btn-danger float-right', aria: { label: s_('Webhooks|Delete webhook') }, data: { confirm: s_('Webhooks|Are you sure you want to delete this project hook?'), confirm_btn_variant: 'danger' }
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 7d62a851aa1..0476193c2cb 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -2,13 +2,13 @@
- breadcrumb_title _('Webhook Settings')
- page_title _('Webhooks')
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4
= render 'shared/web_hooks/title_and_docs', hook: @hook
.col-lg-8.gl-mb-3
= gitlab_ui_form_for @hook, as: :hook, url: polymorphic_path([@project, :hooks]) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- = f.submit 'Add webhook', class: 'gl-button btn btn-confirm'
+ = f.submit 'Add webhook', pajamas_button: true
= render 'shared/web_hooks/index', hooks: @hooks, hook_class: @hook.class
diff --git a/app/views/projects/incidents/show.html.haml b/app/views/projects/incidents/show.html.haml
index 5043f94bd5c..7a1e7f503f8 100644
--- a/app/views/projects/incidents/show.html.haml
+++ b/app/views/projects/incidents/show.html.haml
@@ -2,6 +2,7 @@
- add_to_breadcrumbs _("Incidents"), project_incidents_path(@project)
- breadcrumb_title @issue.to_reference
- page_title "#{@issue.title} (#{@issue.to_reference})", _("Incidents")
+- add_page_specific_style 'page_bundles/incidents'
- add_page_specific_style 'page_bundles/issues_show'
= render 'projects/issuable/show', issuable: @issue
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 11b652cc818..40935ab6f70 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -6,6 +6,9 @@
#js-vue-notes{ data: { notes_data: notes_data(@issue).to_json,
noteable_data: serialize_issuable(@issue, with_blocking_issues: true),
noteable_type: 'Issue',
+ notes_filters: UserPreference.notes_filters.to_json,
+ notes_filter_value: current_user&.notes_filter_for(@issue),
target_type: 'issue',
+ show_timeline_view_toggle: show_timeline_view_toggle?(@issue).to_s,
current_user_data: UserSerializer.new.represent(current_user, {only_path: true}, CurrentUserEntity).to_json,
can_add_timeline_events: "#{can?(current_user, :admin_incident_management_timeline_event, @issue)}" } }
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 4d4645c7087..1d3320e4f82 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -1,10 +1,5 @@
%li{ id: dom_id(issue), class: issue_css_classes(issue), url: issue_path(issue), data: { labels: issue.label_ids, id: issue.id, qa_selector: 'issue_container', qa_issue_title: issue.title } }
.issuable-info-container
- - if @can_bulk_update
- .issue-check.hidden
- - checkbox_id = dom_id(issue, "selected")
- %label.gl-sr-only{ for: checkbox_id }= issue.title
- = check_box_tag checkbox_id, nil, false, 'data-id' => issue.id, class: "selected-issuable"
.issuable-main-info
.issue-title.title
%span.issue-title-text.js-onboarding-issue-item{ dir: "auto" }
diff --git a/app/views/projects/issues/_work_item_links.html.haml b/app/views/projects/issues/_work_item_links.html.haml
index bc2136b89fb..c0de711136a 100644
--- a/app/views/projects/issues/_work_item_links.html.haml
+++ b/app/views/projects/issues/_work_item_links.html.haml
@@ -1,2 +1,2 @@
- if Feature.enabled?(:work_items_hierarchy, @project)
- .js-work-item-links-root{ data: { issuable_id: @issue.id, iid: @issue.iid, project_path: @project.full_path, wi: work_items_index_data(@project) } }
+ .js-work-item-links-root{ data: { issuable_id: @issue.id, iid: @issue.iid, project_namespace: @project.namespace.path, project_path: @project.full_path, wi: work_items_index_data(@project) } }
diff --git a/app/views/projects/issues/service_desk/_service_desk_info_content.html.haml b/app/views/projects/issues/service_desk/_service_desk_info_content.html.haml
index bad75ac2cd9..2ed5675c0ad 100644
--- a/app/views/projects/issues/service_desk/_service_desk_info_content.html.haml
+++ b/app/views/projects/issues/service_desk/_service_desk_info_content.html.haml
@@ -4,7 +4,7 @@
- can_admin_issues = can?(current_user, :admin_issue, @project)
- title_text = s_("ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab")
-.non-empty-state.media
+.media.gl-border-b.gl-pb-3.gl-text-left
.svg-content
= render partial: 'shared/empty_states/icons/service_desk_callout', formats: :svg
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 06c422fc4d6..76b725d140c 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -2,6 +2,7 @@
- add_to_breadcrumbs _("Issues"), project_issues_path(@project)
- breadcrumb_title @issue.to_reference
- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
+- add_page_specific_style 'page_bundles/incidents'
- add_page_specific_style 'page_bundles/issues_show'
- add_page_specific_style 'page_bundles/work_items'
diff --git a/app/views/projects/jobs/_user.html.haml b/app/views/projects/jobs/_user.html.haml
index 90ce581a903..03cbabb0c2a 100644
--- a/app/views/projects/jobs/_user.html.haml
+++ b/app/views/projects/jobs/_user.html.haml
@@ -1,7 +1,7 @@
by
%a{ href: user_path(@build.user) }
%span.d-none.d-sm-inline
- = image_tag avatar_icon_for_user(@build.user, 24), class: "avatar s24"
+ = render Pajamas::AvatarComponent.new(@build.user, size: 24, alt: "")
%strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } }
= @build.user.name
%strong.d-inline.d-sm-none= @build.user.to_reference
diff --git a/app/views/projects/merge_requests/_awards_block.html.haml b/app/views/projects/merge_requests/_awards_block.html.haml
index 64d35b4dfe6..820927fdd1a 100644
--- a/app/views/projects/merge_requests/_awards_block.html.haml
+++ b/app/views/projects/merge_requests/_awards_block.html.haml
@@ -1,5 +1,2 @@
.content-block.emoji-block.emoji-list-container.js-noteable-awards
- = render 'award_emoji/awards_block', awardable: @merge_request, inline: true, api_awards_path: award_emoji_merge_request_api_path(@merge_request) do
- .gl-my-2.gl-xs-w-full
- #js-vue-sort-issue-discussions
- = render "projects/merge_requests/discussion_filter"
+ = render 'award_emoji/awards_block', awardable: @merge_request, inline: true, api_awards_path: award_emoji_merge_request_api_path(@merge_request)
diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
index 22571b11639..478db70877d 100644
--- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
+++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
@@ -1,8 +1,7 @@
- display_issuable_type = issuable_display_type(@merge_request)
.float-left.btn-group.gl-md-ml-3.gl-display-flex.dropdown.gl-new-dropdown.gl-md-w-auto.gl-w-full
- = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret gl-display-none! gl-md-display-inline-flex!", data: { 'toggle' => 'dropdown' } do
- %span.gl-sr-only= _('Toggle dropdown')
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Merge request actions'), testid: 'merge-request-actions' } do
= sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
%span.gl-new-dropdown-button-text= _('Merge request actions')
@@ -11,7 +10,7 @@
.gl-new-dropdown-inner
.gl-new-dropdown-contents
%ul
- - if !@merge_request.merged? && current_user && moved_mr_sidebar_enabled?
+ - if current_user && moved_mr_sidebar_enabled?
%li.gl-new-dropdown-item.js-sidebar-subscriptions-entry-point
%li.gl-new-dropdown-divider
%hr.dropdown-divider
diff --git a/app/views/projects/merge_requests/_discussion_filter.html.haml b/app/views/projects/merge_requests/_discussion_filter.html.haml
deleted file mode 100644
index 96886661a8d..00000000000
--- a/app/views/projects/merge_requests/_discussion_filter.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@merge_request),
- notes_filters: UserPreference.notes_filters.to_json } }
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 98d2928fc97..71f8e4c32f5 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,9 +1,12 @@
%li{ id: dom_id(merge_request), class: mr_css_classes(merge_request), data: { labels: merge_request.label_ids, id: merge_request.id } }
- if @can_bulk_update
- .issue-check.hidden
- - checkbox_id = dom_id(merge_request, "selected")
- %label.gl-sr-only{ for: checkbox_id }= merge_request.title
- = check_box_tag checkbox_id, nil, false, 'data-id' => merge_request.id, class: "selected-issuable"
+ .issue-check.gl-mr-3.hidden
+ = render Pajamas::CheckboxTagComponent.new(name: dom_id(merge_request, "selected"),
+ value: nil,
+ checkbox_options: { 'data-id' => merge_request.id }) do |c|
+ = c.label do
+ %span.gl-sr-only
+ = merge_request.title
.issuable-info-container
.issuable-main-info
diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml
index 00d12423eb9..1efea6a1d37 100644
--- a/app/views/projects/merge_requests/_nav_btns.html.haml
+++ b/app/views/projects/merge_requests/_nav_btns.html.haml
@@ -5,7 +5,8 @@
.js-csv-import-export-buttons{ data: { show_export_button: "true", issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_merge_requests_path(@project, request.query_parameters), container_class: 'gl-mr-3' } }
- if @can_bulk_update
- = button_tag _("Edit merge requests"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
+ = render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-mr-3 js-bulk-update-toggle' }) do
+ = _("Edit merge requests")
- if merge_project
- = link_to new_merge_request_path, class: "gl-button btn btn-confirm", title: _("New merge request") do
- = _('New merge request')
+ = render Pajamas::ButtonComponent.new(href: new_merge_request_path, variant: :confirm) do
+ = _("New merge request")
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 783e3ac97c1..4f6983c6fe3 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -12,6 +12,7 @@
window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'require-a-successful-pipeline-for-merge')}';
window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
+ window.gl.mrWidgetData.security_configuration_path = '#{project_security_configuration_path(@project)}';
window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/approvals/rules.md', anchor: 'eligible-approvers')}';
window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/approvals/index.md")}';
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index d34848c801d..d77d5231a7d 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -60,10 +60,10 @@
%section
.issuable-discussion.js-vue-notes-event
- if @merge_request.description.present?
- .detail-page-description
+ .detail-page-description.gl-pb-0
= render "projects/merge_requests/description"
- = render "projects/merge_requests/widget"
= render "projects/merge_requests/awards_block"
+ = render "projects/merge_requests/widget"
- if mr_action === "show"
- add_page_startup_api_call Feature.enabled?(:paginated_mr_discussions, @project) ? discussions_path(@merge_request, per_page: 20) : discussions_path(@merge_request)
- add_page_startup_api_call widget_project_json_merge_request_path(@project, @merge_request, format: :json)
@@ -72,6 +72,8 @@
endpoint_metadata: @endpoint_metadata_url,
noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'),
noteable_type: 'MergeRequest',
+ notes_filters: UserPreference.notes_filters.to_json,
+ notes_filter_value: current_user&.notes_filter_for(@merge_request),
target_type: 'merge_request',
help_page_path: suggest_changes_help_path,
current_user_data: @current_user_data,
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index c11d5e7c9b6..fb7c1130f5c 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -1,6 +1,8 @@
= gitlab_ui_form_for [@project, @milestone],
html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone)
+ - if @redirect_path.present?
+ = f.hidden_field(:redirect_path, name: :redirect_path, id: :redirect_path, value: @redirect_path)
.form-group.row
.col-form-label.col-sm-2
= f.label :title, _('Title')
diff --git a/app/views/projects/mirrors/_authentication_method.html.haml b/app/views/projects/mirrors/_authentication_method.html.haml
index 28b433b2514..4b549aaf1cd 100644
--- a/app/views/projects/mirrors/_authentication_method.html.haml
+++ b/app/views/projects/mirrors/_authentication_method.html.haml
@@ -3,12 +3,10 @@
.form-group
= f.label :auth_method, _('Authentication method'), class: 'label-bold'
- .select-wrapper
- = f.select :auth_method,
- options_for_select(auth_options, mirror.auth_method),
- {}, { class: "form-control gl-form-select select-control js-mirror-auth-type qa-authentication-method" }
- = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
- = f.hidden_field :auth_method, value: "password", class: "js-hidden-mirror-auth-type"
+ = f.select :auth_method,
+ options_for_select(auth_options, mirror.auth_method),
+ {}, { class: "custom-select gl-form-select js-mirror-auth-type qa-authentication-method" }
+ = f.hidden_field :auth_method, value: "password", class: "js-hidden-mirror-auth-type"
.form-group
.well-password-auth.collapse.js-well-password-auth
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 2ae7d300979..c98f88fa31e 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -35,7 +35,7 @@
= link_to _('Learn more.'), help_page_path('user/project/repository/mirror/index.md', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
.panel-footer
- = f.submit _('Mirror repository'), class: 'gl-button btn btn-confirm js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
+ = f.submit _('Mirror repository'), class: 'js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror, pajamas_button: true
- else
= render Pajamas::AlertComponent.new(dismissible: false) do |c|
= c.body do
diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml
index 701cb37a1c8..e430dc2f372 100644
--- a/app/views/projects/network/_head.html.haml
+++ b/app/views/projects/network/_head.html.haml
@@ -1,4 +1,4 @@
-.row-content-block.second-block.content-component-block
+.row-content-block.second-block.content-component-block.gl-px-0.gl-py-3
.tree-ref-holder
= render partial: 'shared/ref_switcher', locals: {destination: 'graph'}
diff --git a/app/views/projects/pages/_destroy.haml b/app/views/projects/pages/_destroy.haml
index 993026d2884..ff30c9ce1ea 100644
--- a/app/views/projects/pages/_destroy.haml
+++ b/app/views/projects/pages/_destroy.haml
@@ -1,14 +1,16 @@
- if @project.pages_deployed?
- if can?(current_user, :remove_pages, @project)
- .card.border-danger
- .card-header.bg-danger.text-white
+ = render Pajamas::CardComponent.new(card_options: { class: 'border-danger' }, header_options: {class: 'bg-danger text-white'}) do |c|
+ - c.with_header do
= s_('GitLabPages|Remove pages')
- .errors-holder
- .card-body
- %p.gl-mb-0
- = s_('GitLabPages|Removing pages will prevent them from being exposed to the outside world.')
- .card-footer
- = link_to s_('GitLabPages|Remove pages'), project_pages_path(@project), data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, method: :delete, class: "btn gl-button btn-danger", "aria-label": s_('GitLabPages|Remove pages')
+ - c.with_body do
+ = s_('GitLabPages|Removing pages will prevent them from being exposed to the outside world.')
+ - c.with_footer do
+ = render Pajamas::ButtonComponent.new(href: project_pages_path(@project),
+ variant: :danger,
+ method: :delete,
+ button_options: {data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_('GitLabPages|Remove pages')}) do
+ = s_('GitLabPages|Remove pages')
- else
.nothing-here-block
= s_('GitLabPages|Only project maintainers can remove pages')
diff --git a/app/views/projects/pages/new.html.haml b/app/views/projects/pages/new.html.haml
index 5dea6b02e36..f1f3510d0f8 100644
--- a/app/views/projects/pages/new.html.haml
+++ b/app/views/projects/pages/new.html.haml
@@ -1,7 +1,8 @@
-- if Feature.enabled?(:use_pipeline_wizard_for_pages, @project.group)
- #js-pages{ data: @pipeline_wizard_data }
+%section.js-search-settings-section
+ - if Feature.enabled?(:use_pipeline_wizard_for_pages, @project.group)
+ #js-pages{ data: @pipeline_wizard_data }
-- else
- = render 'header'
+ - else
+ = render 'header'
- = render 'use'
+ = render 'use'
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 5d5ca2aaaf3..ab692d1830a 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -39,5 +39,5 @@
%div
= f.gitlab_ui_checkbox_component :active, _('Active'), checkbox_options: { value: @schedule.active, required: false }
.footer-block
- = f.submit _('Save pipeline schedule'), class: 'btn gl-button btn-confirm'
+ = f.submit _('Save pipeline schedule'), pajamas_button: true
= link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 10dc74647b2..7b16564dfa2 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -4,9 +4,9 @@
= pipeline_schedule.description
%td.branch-name-cell.gl-text-truncate
- if pipeline_schedule.for_tag?
- = sprite_icon('tag', size: 12)
+ = sprite_icon('tag', size: 12, css_class: 'gl-vertical-align-middle!' )
- else
- = sprite_icon('fork', size: 12)
+ = sprite_icon('fork', size: 12, css_class: 'gl-vertical-align-middle!')
- if pipeline_schedule.ref.present?
= link_to pipeline_schedule.ref_for_display, project_ref_path(@project, pipeline_schedule.ref_for_display), class: "ref-name"
%td
@@ -24,7 +24,7 @@
= s_("PipelineSchedules|Inactive")
%td
- if pipeline_schedule.owner
- = image_tag avatar_icon_for_user(pipeline_schedule.owner, 20), class: "avatar s20"
+ = render Pajamas::AvatarComponent.new(pipeline_schedule.owner, size: 24, class: "gl-mr-2")
= link_to user_path(pipeline_schedule.owner) do
= pipeline_schedule.owner&.name
%td
diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml
index 642b458eea6..3f843ce6aec 100644
--- a/app/views/projects/pipeline_schedules/edit.html.haml
+++ b/app/views/projects/pipeline_schedules/edit.html.haml
@@ -7,4 +7,7 @@
= _("Edit Pipeline Schedule")
%hr
-= render "form"
+- if Feature.enabled?(:pipeline_schedules_vue, @project)
+ #pipeline-schedules-form-edit{ data: { full_path: @project.full_path } }
+- else
+ = render "form"
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 661cf465081..47ad8cc826d 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -1,22 +1,28 @@
- breadcrumb_title _("Schedules")
- page_title _("Pipeline Schedules")
- add_page_specific_style 'page_bundles/pipeline_schedules'
+- add_page_specific_style 'page_bundles/ci_status'
#pipeline-schedules-callout{ data: { docs_url: help_page_path('ci/pipelines/schedules'), illustration_url: image_path('illustrations/pipeline_schedule_callout.svg') } }
-.top-area
- - schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) }
- = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
- - if can?(current_user, :create_pipeline_schedule, @project)
- .nav-controls
- = link_to new_project_pipeline_schedule_path(@project), class: 'btn gl-button btn-confirm' do
- %span= _('New schedule')
-
-- if @schedules.present?
- %ul.content-list
- = render partial: "table"
+- if Feature.enabled?(:pipeline_schedules_vue, @project)
+ #pipeline-schedules-app{ data: { full_path: @project.full_path } }
- else
- .card.bg-light.gl-mt-3
- .nothing-here-block= _("No schedules")
+ .top-area
+ - schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) }
+ = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
+
+ - if can?(current_user, :create_pipeline_schedule, @project)
+ .nav-controls
+ = link_to new_project_pipeline_schedule_path(@project), class: 'btn gl-button btn-confirm' do
+ %span= _('New schedule')
+
+ - if @schedules.present?
+ %ul.content-list
+ = render partial: "table"
+ - else
+ = render Pajamas::CardComponent.new(card_options: { class: 'bg-light gl-mt-3 gl-text-center' }) do |c|
+ - c.body do
+ = _("No schedules")
-#pipeline-take-ownership-modal
+ #pipeline-take-ownership-modal
diff --git a/app/views/projects/pipeline_schedules/new.html.haml b/app/views/projects/pipeline_schedules/new.html.haml
index 3b4acf5b8c5..d3757d0e339 100644
--- a/app/views/projects/pipeline_schedules/new.html.haml
+++ b/app/views/projects/pipeline_schedules/new.html.haml
@@ -8,4 +8,7 @@
%h1.page-title.gl-font-size-h-display
= _("Schedule a new pipeline")
-= render "form"
+- if Feature.enabled?(:pipeline_schedules_vue, @project)
+ #pipeline-schedules-form-new{ data: { full_path: @project.full_path } }
+- else
+ = render "form"
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 07e299d71ea..2e403358e2e 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -9,18 +9,21 @@
.well-segment.pipeline-info{ class: "gl-align-items-baseline!" }
.icon-container
= sprite_icon('clock', css_class: 'gl-top-0!')
- = pluralize @pipeline.total_size, "job"
- = @pipeline.ref_text
+ - jobs = n_('%d job', '%d jobs', @pipeline.total_size) % @pipeline.total_size
- if @pipeline.duration
- in
- = time_interval_in_words(@pipeline.duration)
+ = s_('Pipelines|%{jobs} %{ref_text} in %{duration}').html_safe % { jobs: jobs, ref_text: @pipeline.ref_text, duration: time_interval_in_words(@pipeline.duration) }
+ - else
+ = jobs
+ = @pipeline.ref_text
- if @pipeline.queued_duration
- = "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
+ = s_("Pipelines|(queued for %{queued_duration})") % { queued_duration: time_interval_in_words(@pipeline.queued_duration)}
- if has_pipeline_badges?(@pipeline)
.well-segment.qa-pipeline-badges
.icon-container
= sprite_icon('flag', css_class: 'gl-top-0!')
+ - if @pipeline.schedule?
+ = gl_badge_tag _('Scheduled'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-scheduled', title: _('This pipeline was triggered by a schedule.') }
- if @pipeline.child?
- text = sprintf(s_('Pipelines|Child pipeline (%{link_start}parent%{link_end})'), { link_start: "<a href='#{pipeline_path(@pipeline.triggered_by_pipeline)}' class='text-underline'>", link_end: "</a>"}).html_safe
= gl_badge_tag text, { variant: :info, size: :sm }, { class: 'js-pipeline-child has-tooltip', title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index a4144f8ab0d..d2b2a58fcf8 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -12,6 +12,7 @@
ref_param: params[:ref] || @project.default_branch,
var_param: params[:var].to_json,
file_param: params[:file_var].to_json,
+ project_path: @project.full_path,
project_refs_endpoint: refs_project_path(@project, sort: 'updated_desc'),
settings_link: project_settings_ci_cd_path(@project),
max_warnings: ::Gitlab::Ci::Warnings::MAX_LIMIT } }
diff --git a/app/views/projects/project_templates/_project_fields_form.html.haml b/app/views/projects/project_templates/_project_fields_form.html.haml
index 7908550ca88..c3528b421b9 100644
--- a/app/views/projects/project_templates/_project_fields_form.html.haml
+++ b/app/views/projects/project_templates/_project_fields_form.html.haml
@@ -8,5 +8,5 @@
.selected-icon.gl-mr-3
.selected-template
.input-group-append
- %button.btn.gl-button.btn-default.change-template{ type: "button" }
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'change-template' }) do
= _('Change template')
diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml
index 34fe9a29068..76aadc3be28 100644
--- a/app/views/projects/protected_branches/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml
@@ -1,12 +1,12 @@
- content_for :merge_access_levels do
.merge_access_levels-container
- = dropdown_tag('Select',
+ = dropdown_tag(_('Select'),
options: { toggle_class: 'js-allowed-to-merge wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header', dropdown_qa_selector: 'allowed_to_merge_dropdown_content', dropdown_testid: 'allowed-to-merge-dropdown',
data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes', qa_selector: 'allowed_to_merge_dropdown' }})
- content_for :push_access_levels do
.push_access_levels-container
- = dropdown_tag('Select',
+ = dropdown_tag(_('Select'),
options: { toggle_class: "js-allowed-to-push js-multiselect wide",
dropdown_class: 'dropdown-menu-selectable capitalize-header', dropdown_qa_selector: 'allowed_to_push_dropdown_content' , dropdown_testid: 'allowed-to-push-dropdown',
data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes', qa_selector: 'allowed_to_push_dropdown' }})
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index 277cbf00034..770d79943b3 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -1,4 +1,4 @@
-= form_for [@project, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
+= gitlab_ui_form_for [@project, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-branches-settings' }
= render Pajamas::CardComponent.new(card_options: { class: "gl-mb-5" }) do |c|
- c.header do
@@ -32,4 +32,4 @@
= (s_("ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}.") % { tag_start: force_push_link_start, tag_end: '</a>' }).html_safe
= render_if_exists 'projects/protected_branches/ee/code_owner_approval_form', f: f
- c.footer do
- = f.submit s_('ProtectedBranch|Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_button' }
+ = f.submit s_('ProtectedBranch|Protect'), disabled: true, data: { qa_selector: 'protect_button' }, pajamas_button: true
diff --git a/app/views/projects/protected_branches/shared/_dropdown.html.haml b/app/views/projects/protected_branches/shared/_dropdown.html.haml
index 4b09d36e7c3..d5111bd8be5 100644
--- a/app/views/projects/protected_branches/shared/_dropdown.html.haml
+++ b/app/views/projects/protected_branches/shared/_dropdown.html.haml
@@ -2,11 +2,11 @@
= f.hidden_field(:name)
-= dropdown_tag('Select branch or create wildcard',
+= dropdown_tag(_('Select branch or create wildcard'),
options: { toggle_class: "js-protected-branch-select js-filter-submit wide monospace qa-protected-branch-select #{toggle_classes}",
filter: true,
dropdown_class: "dropdown-menu-selectable git-revision-dropdown qa-protected-branch-dropdown",
- placeholder: "Search protected branches",
+ placeholder: _("Search protected branches"),
footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true,
selected: params[:protected_branch_name],
@@ -14,6 +14,6 @@
%ul.dropdown-footer-list
%li
- %button{ class: "dropdown-create-new-item-button js-dropdown-create-new-item", title: "New Protected Branch" }
- Create wildcard
+ %button{ class: "dropdown-create-new-item-button js-dropdown-create-new-item", title: _("New Protected Branch") }
+ = _('Create wildcard')
%code
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index ba0935fff7d..9ea7f397c0a 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -1,9 +1,9 @@
= form_for [@project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-tags-settings' }
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }) do |c|
+ - c.header do
= _('Protect a tag')
- .card-body
+ - c.body do
= form_errors(@protected_tag)
.form-group.row
= f.label :name, _('Tag:'), class: 'col-md-2 text-left text-md-right'
@@ -19,5 +19,5 @@
.create_access_levels-container
= yield :create_access_levels
- .card-footer
+ - c.footer do
= f.submit _('Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_tag_button' }
diff --git a/app/views/projects/releases/index.html.haml b/app/views/projects/releases/index.html.haml
index 9ddf2201fad..975abaefc6c 100644
--- a/app/views/projects/releases/index.html.haml
+++ b/app/views/projects/releases/index.html.haml
@@ -1,4 +1,5 @@
- page_title _('Releases')
+- add_page_specific_style 'page_bundles/releases'
- if use_startup_query_for_index_page?
- add_page_startup_graphql_call('releases/all_releases', index_page_startup_query_variables)
diff --git a/app/views/projects/releases/show.html.haml b/app/views/projects/releases/show.html.haml
index 91ee9ad70a3..66b187c8c72 100644
--- a/app/views/projects/releases/show.html.haml
+++ b/app/views/projects/releases/show.html.haml
@@ -1,5 +1,6 @@
- add_to_breadcrumbs _("Releases"), project_releases_path(@project)
- page_title @release.name
- page_description @release.description_html
+- add_page_specific_style 'page_bundles/releases'
#js-show-release-page{ data: data_for_show_page }
diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml
deleted file mode 100644
index ae0d9ab9908..00000000000
--- a/app/views/projects/repositories/_feed.html.haml
+++ /dev/null
@@ -1,18 +0,0 @@
-- commit = update
-%tr
- %td
- = link_to project_commits_path(@project, commit.head.name) do
- %strong
- = commit.head.name
- - if @project.root_ref?(commit.head.name)
- %span.label default
-
- %td
- %div
- = link_to project_commits_path(@project, commit.id) do
- %code= commit.short_id
- = image_tag avatar_icon_for_email(commit.author_email), class: "", width: 16, alt: ''
- = markdown(truncate(commit.title, length: 40), pipeline: :single_line, author: commit.author)
- %td
- %span.float-right.cgray
- = time_ago_with_tooltip(commit.committed_date)
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index 3df4f3a0bd0..4689e70d907 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -5,6 +5,6 @@
- if @shared_runners_count == 0
= _('This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area.')
- else
- %h4.underlined-title #{_('Available shared runners:')} #{@shared_runners_count}
+ %h5.gl-mt-6.gl-mb-0 #{_('Available shared runners:')} #{@shared_runners_count}
%ul.bordered-list.available-shared-runners
= render partial: 'projects/runners/runner', collection: @shared_runners, as: :runner
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index 7ecc8004334..9f598ffb2d1 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -4,7 +4,7 @@
- type_plural = _('project access tokens')
- @content_class = 'limit-container-width' unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4
%h4.gl-mt-0
= page_title
@@ -24,13 +24,11 @@
= _('You can enable project access token creation in %{link_start}group settings%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.col-lg-8
- - if @new_resource_access_token
- = render 'shared/access_tokens/created_container',
- type: type,
- new_token_value: @new_resource_access_token
+ #js-new-access-token-app{ data: { access_token_type: type } }
- if current_user.can?(:create_resource_access_tokens, @project)
= render 'shared/access_tokens/form',
+ ajax: true,
type: type,
path: project_settings_access_tokens_path(@project),
resource: @project,
@@ -39,12 +37,8 @@
access_levels: ProjectMember.permissible_access_level_roles(current_user, @project),
default_access_level: Gitlab::Access::GUEST,
prefix: :resource_access_token,
+ description_prefix: :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_resource_access_tokens,
- resource: @project,
- type: type,
- type_plural: type_plural,
- revoke_route_helper: ->(token) { revoke_namespace_project_settings_access_token_path(id: token) },
- no_active_tokens_message: _('This project has no active access tokens.')
+ #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_resource_access_tokens.to_json, no_active_tokens_message: _('This project has no active access tokens.'), show_role: true
+ } }
diff --git a/app/views/projects/settings/branch_rules/index.html.haml b/app/views/projects/settings/branch_rules/index.html.haml
index 384d504e51f..a7e80101a88 100644
--- a/app/views/projects/settings/branch_rules/index.html.haml
+++ b/app/views/projects/settings/branch_rules/index.html.haml
@@ -1,6 +1,6 @@
- add_to_breadcrumbs _('Repository Settings'), project_settings_repository_path(@project)
-- page_title _('Branch rules')
+- page_title s_('BranchRules|Branch rules details')
-%h3= _('Branch rules')
+%h3.gl-mb-5= s_('BranchRules|Branch rules details')
-#js-branch-rules{ data: { project_path: @project.full_path } }
+#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings'), approval_rules_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-approval-settings') } }
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 81526685bfc..5748b4b0330 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -41,4 +41,4 @@
= form.gitlab_ui_radio_component :deploy_strategy, 'timed_incremental', (s_('CICD|Continuous deployment to production using timed incremental rollout') + ' ' + help_link_timed).html_safe
= form.gitlab_ui_radio_component :deploy_strategy, 'manual', (s_('CICD|Automatic deployment to staging, manual deployment to production') + ' ' + help_link_incremental).html_safe
- = f.submit _('Save changes'), class: "btn gl-button btn-confirm gl-mt-5", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), class: "gl-mt-5", data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/projects/settings/ci_cd/_badge.html.haml b/app/views/projects/settings/ci_cd/_badge.html.haml
index 38d8c8d26e1..99eef38827b 100644
--- a/app/views/projects/settings/ci_cd/_badge.html.haml
+++ b/app/views/projects/settings/ci_cd/_badge.html.haml
@@ -2,15 +2,15 @@
.col-lg-12
%h4
= badge.title.capitalize
- .card
- .card-header
- %b
- = badge.title.capitalize
- &middot;
- = badge.to_html
- .float-right
- = render 'shared/ref_switcher', destination: 'badges', align_right: true
- .card-body
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, header_options: { class: 'gl-display-flex gl-align-items-center' }) do |c|
+ - c.header do
+ .gl-flex-grow-1
+ %b
+ = badge.title.capitalize
+ &middot;
+ = badge.to_html
+ = render 'shared/ref_switcher', destination: 'badges', align_right: true
+ - c.body do
.row
.col-md-2.gl-text-center
Markdown
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 9419dacc16f..51d28411b30 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -77,7 +77,7 @@
= _("The maximum file size in megabytes for individual job artifacts.")
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank', rel: 'noopener noreferrer'
- = f.submit _('Save changes'), class: "btn gl-button btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
%hr
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index c1df7b88352..c4f589f3f91 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -24,7 +24,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
- auto_devops_url = help_page_path('topics/autodevops/index')
- - quickstart_url = help_page_path('topics/autodevops/quick_start_guide')
+ - quickstart_url = help_page_path('topics/autodevops/cloud_deployments/auto_devops_with_gke')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
- quickstart_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: quickstart_url }
= s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
@@ -119,4 +119,3 @@
= link_to _('Learn more'), help_page_path('ci/secure_files/index'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
#js-ci-secure-files{ data: { project_id: @project.id, admin: can?(current_user, :admin_secure_files, @project).to_s, file_size_limit: Ci::SecureFile::FILE_SIZE_LIMIT.to_mb } }
-
diff --git a/app/views/projects/settings/integrations/index.html.haml b/app/views/projects/settings/integrations/index.html.haml
index 84635941436..2077d244b24 100644
--- a/app/views/projects/settings/integrations/index.html.haml
+++ b/app/views/projects/settings/integrations/index.html.haml
@@ -2,8 +2,9 @@
- breadcrumb_title _('Integration Settings')
- page_title _('Integrations')
-%h3= _('Integrations')
-- integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/overview') }
-- webhooks_link_start = '<a href="%{url}">'.html_safe % { url: project_hooks_path(@project) }
-%p= _("%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, webhooks_link_start: webhooks_link_start, link_end: '</a>'.html_safe }
-= render 'shared/integrations/index', integrations: @integrations
+%section.js-search-settings-section
+ %h3= _('Integrations')
+ - integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/index') }
+ - webhooks_link_start = '<a href="%{url}">'.html_safe % { url: project_hooks_path(@project) }
+ %p= _("%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, webhooks_link_start: webhooks_link_start, link_end: '</a>'.html_safe }
+ = render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/projects/settings/merge_requests/show.html.haml b/app/views/projects/settings/merge_requests/show.html.haml
index 886e276dea5..7dfd304e07b 100644
--- a/app/views/projects/settings/merge_requests/show.html.haml
+++ b/app/views/projects/settings/merge_requests/show.html.haml
@@ -4,7 +4,7 @@
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings.expanded{ class: [('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { qa_selector: 'merge_request_settings_content' } }
.settings-header
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Merge requests')
+ %h4= _('Merge requests')
= render_if_exists 'projects/merge_request_settings_description_text'
.settings-content
@@ -13,6 +13,7 @@
= gitlab_ui_form_for @project, url: project_settings_merge_requests_path(@project), html: { multipart: true, class: "merge-request-settings-form js-mr-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' }
= render 'projects/merge_request_settings', form: f
- = f.submit _('Save changes'), class: "btn gl-button btn-confirm rspec-save-merge-request-changes", data: { qa_selector: 'save_merge_request_changes_button' }
+ = f.submit _('Save changes'), class: "rspec-save-merge-request-changes", data: { qa_selector: 'save_merge_request_changes_button' }, pajamas_button: true
= render_if_exists 'projects/settings/merge_requests/merge_request_approvals_settings', expanded: true
+= render_if_exists 'projects/settings/merge_requests/suggested_reviewers_settings', expanded: true
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index e9d1661a4f1..c7ac28fa194 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -2,6 +2,7 @@
- @content_class = "limit-container-width" unless fluid_layout
- @skip_current_level_breadcrumb = true
- add_page_specific_style 'page_bundles/project'
+- add_page_specific_style 'page_bundles/tree'
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index 3e6acdb130a..ddebc19be15 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -5,7 +5,7 @@
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
-.row-content-block.top-block.content-component-block
+.row-content-block.top-block.content-component-block.gl-px-0.gl-py-2
= render 'award_emoji/awards_block', awardable: @snippet, inline: true, api_awards_path: project_snippets_award_api_path(@snippet)
#notes.limited-width-notes= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml
index e24276fcaea..c1cd2488142 100644
--- a/app/views/projects/starrers/_starrer.html.haml
+++ b/app/views/projects/starrers/_starrer.html.haml
@@ -2,8 +2,8 @@
.col-lg-3.col-md-4.col-sm-12
.card
- .card-body
- = image_tag avatar_icon_for_user(starrer.user, 40), class: "avatar s40", alt: ''
+ .card-body.gl-display-flex
+ = render Pajamas::AvatarComponent.new(starrer.user, size: 48, alt: "", class: 'gl-mr-3')
.user-info
.block-truncated
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 79fc1a64790..ed06c90efa8 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -9,6 +9,11 @@
%h1.page-title.gl-font-size-h-display
= s_('TagsPage|New Tag')
+%p.gl-text-secondary
+ - link_start = '<a href="%{url}">'.html_safe % { url: new_namespace_project_release_path }
+ - link_end = '</a>'.html_safe
+ = s_('TagsPage|Do you want to create a release with the new tag? You can do that in the %{link_start}New release page%{link_end}.').html_safe % { link_start: link_start, link_end: link_end }
+
= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "common-note-form tag-form js-quick-submit js-requires-input" do
.form-group.row
.col-sm-12
@@ -31,22 +36,7 @@
= text_area_tag :message, @message, required: false, class: 'form-control', rows: 5, data: { qa_selector: "tag_message_field" }
.form-text.text-muted
= tag_description_help_text
- .form-group.row
- .col-sm-12
- = label_tag :release_description, s_('TagsPage|Release notes'), class: 'gl-mb-0'
- .form-text.mb-3
- - link_start = '<a href="%{url}" rel="noopener noreferrer" target="_blank">'.html_safe
- - releases_page_path = project_releases_path(@project)
- - releases_page_link_start = link_start % { url: releases_page_path }
- - docs_url = help_page_path('user/project/releases/index.md', anchor: 'create-a-release')
- - docs_link_start = link_start % { url: docs_url }
- - link_end = '</a>'.html_safe
- - replacements = { releases_page_link_start: releases_page_link_start, docs_link_start: docs_link_start, link_end: link_end }
- = s_('TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}').html_safe % replacements
- = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
- = render 'shared/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here…'), current_text: @release_description, qa_selector: 'release_notes_field'
- = render 'shared/notes/hints'
.gl-display-flex
= render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'gl-mr-3', data: { qa_selector: "create_tag_button" }, type: 'submit' }) do
= s_('TagsPage|Create tag')
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 1553eda1cfb..6d1ab80bdc5 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,3 +1,4 @@
+- add_page_specific_style 'page_bundles/tree'
- current_route_path = request.fullpath.match(%r{-/tree/[^/]+/(.+$)}).to_a[1]
- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
- add_page_startup_graphql_call('repository/permissions', { projectPath: @project.full_path })
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index 0c53ed48210..a7f29b5cbf9 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -1,11 +1,11 @@
.row.gl-mt-3.gl-mb-3
.col-lg-12
- .card
- .card-header
+ = render Pajamas::CardComponent.new do |c|
+ - c.header do
= _("Manage your project's triggers")
- .card-body
+ - c.body do
= render 'projects/triggers/form', btn_text: _('Add trigger')
- %hr
+ .gl-mb-5
- if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project)
#js-ci-pipeline-triggers-list.triggers-list{ data: { triggers: @triggers_json } }
- else
@@ -28,11 +28,11 @@
%th
= render partial: 'projects/triggers/trigger', collection: @triggers, as: :trigger
- else
- %p.settings-message.text-center.gl-mb-3{ data: { testid: 'no_triggers_content' } }
- = _('No triggers exist yet. Use the form above to create one.')
-
- .card-footer
-
+ = render Pajamas::AlertComponent.new(variant: :warning, show_icon: false, dismissible: false,
+ alert_options: { data: { testid: 'no_triggers_content' }}) do |c|
+ = c.body do
+ = _('No triggers exist yet. Use the form above to create one.')
+ - c.footer do
%p
= _("These examples show how to trigger this project's pipeline for a branch or tag.")
diff --git a/app/views/projects/work_items/index.html.haml b/app/views/projects/work_items/index.html.haml
index 8575fd10ad3..69597aab7ef 100644
--- a/app/views/projects/work_items/index.html.haml
+++ b/app/views/projects/work_items/index.html.haml
@@ -1,5 +1,7 @@
- page_title s_('WorkItem|Work Items')
- add_page_specific_style 'page_bundles/work_items'
+- @gfm_form = true
+- @noteable_type = 'WorkItem'
#js-work-items{ data: work_items_index_data(@project) }
= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index 911ba5e8042..fe455f4a0bc 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -17,7 +17,11 @@
%p.gl-text-center= html_escape(_('%{gitlab_experience_text}. We won\'t share this information with anyone.')) % { gitlab_experience_text: gitlab_experience_text }
- else
%p.gl-text-center= html_escape(_('%{gitlab_experience_text}. Don\'t worry, this information isn\'t shared outside of your self-managed GitLab instance.')) % { gitlab_experience_text: gitlab_experience_text }
- = gitlab_ui_form_for(current_user, url: users_sign_up_welcome_path, html: { class: 'card gl-w-full! gl-p-5 js-users-signup-welcome', 'aria-live' => 'assertive' }) do |f|
+ = gitlab_ui_form_for(current_user,
+ url: users_sign_up_welcome_path(glm_tracking_params),
+ html: { class: 'card gl-w-full! gl-p-5 js-users-signup-welcome',
+ 'aria-live' => 'assertive',
+ data: { testid: 'welcome-form' } }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: current_user
.row
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 168f4ca10bc..8262c3c90e1 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,26 +1,19 @@
- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
+
= render_if_exists 'shared/promotions/promote_advanced_search'
-= render partial: 'search/results_status', locals: { search_service: @search_service } unless @search_objects.to_a.empty?
+- if Feature.enabled?(:search_page_vertical_nav, current_user) && %w[issues merge_requests].include?(@scope)
+ .results.gl-md-display-flex.gl-mt-0
+ #js-search-sidebar{ class: search_bar_classes, data: { navigation: search_navigation_json } }
+ .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
+ = render partial: 'search/results_status', locals: { search_service: @search_service } unless @search_objects.to_a.empty?
+ = render partial: 'search/results_list'
+
+- else
+ = render partial: 'search/results_status', locals: { search_service: @search_service } unless @search_objects.to_a.empty?
-.results.gl-md-display-flex.gl-mt-3
- - if %w[issues merge_requests].include?(@scope)
- #js-search-sidebar{ class: search_bar_classes }
- .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
- - if @timeout
- = render partial: "search/results/timeout"
- - elsif @search_objects.to_a.empty?
- = render partial: "search/results/empty"
- - else
- - if @scope == 'commits'
- %ul.content-list.commit-list
- = render partial: "search/results/commit", collection: @search_objects
- - else
- .search-results
- - if @scope == 'projects'
- .term
- = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
- - else
- = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
+ .results.gl-md-display-flex.gl-mt-3
+ - if %w[issues merge_requests].include?(@scope)
+ #js-search-sidebar{ class: search_bar_classes, data: { navigation: search_navigation_json } }
- - if @scope != 'projects'
- = paginate_collection(@search_objects)
+ .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
+ = render partial: 'search/results_list'
diff --git a/app/views/search/_results_list.html.haml b/app/views/search/_results_list.html.haml
new file mode 100644
index 00000000000..cf910402ad4
--- /dev/null
+++ b/app/views/search/_results_list.html.haml
@@ -0,0 +1,18 @@
+- if @timeout
+ = render partial: "search/results/timeout"
+- elsif @search_objects.to_a.empty?
+ = render partial: "search/results/empty"
+- else
+ - if @scope == 'commits'
+ %ul.content-list.commit-list
+ = render partial: "search/results/commit", collection: @search_objects
+ - else
+ .search-results
+ - if @scope == 'projects'
+ .term
+ = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
+ - else
+ = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
+
+ - if @scope != 'projects'
+ = paginate_collection(@search_objects)
diff --git a/app/views/search/_results_status.html.haml b/app/views/search/_results_status.html.haml
index ef5e3e83103..e6bb0c18b90 100644
--- a/app/views/search/_results_status.html.haml
+++ b/app/views/search/_results_status.html.haml
@@ -2,24 +2,8 @@
- return unless search_service.show_results_status?
-.search-results-status
- .row-content-block.gl-display-flex
- .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
- - unless search_service.without_count?
- = search_entries_info(search_service.search_objects, search_service.scope, params[:search])
- - unless search_service.show_snippets?
- - if search_service.project
- - link_to_project = link_to(search_service.project.full_name, search_service.project, class: 'ml-md-1')
- - if search_service.scope == 'blobs'
- = _("in")
- .mx-md-1
- #js-blob-ref-switcher{ data: { "project-id" => search_service.project.id, "ref" => repository_ref(search_service.project), "field-name": "repository_ref" } }
- = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
- - else
- = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
- - elsif search_service.group
- - link_to_group = link_to(search_service.group.name, search_service.group, class: 'ml-md-1')
- = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
- - if search_service.show_sort_dropdown?
- .gl-md-display-flex.gl-flex-direction-column
- #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
+- if Feature.enabled?(:search_page_vertical_nav, current_user)
+ = render partial: 'search/results_status_vert_nav', locals: { search_service: @search_service }
+
+- else
+ = render partial: 'search/results_status_horiz_nav', locals: { search_service: @search_service }
diff --git a/app/views/search/_results_status_horiz_nav.html.haml b/app/views/search/_results_status_horiz_nav.html.haml
new file mode 100644
index 00000000000..fe6ee0f12ec
--- /dev/null
+++ b/app/views/search/_results_status_horiz_nav.html.haml
@@ -0,0 +1,22 @@
+.search-results-status
+ .row-content-block.gl-display-flex
+ .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
+ - unless search_service.without_count?
+ = search_entries_info(search_service.search_objects, search_service.scope, params[:search])
+ - unless search_service.show_snippets?
+ - if search_service.project
+ - link_to_project = link_to(search_service.project.full_name, search_service.project, class: 'ml-md-1')
+ - if search_service.scope == 'blobs'
+ = _("in")
+ .mx-md-1
+ #js-blob-ref-switcher{ data: { "project-id" => search_service.project.id, "ref" => repository_ref(search_service.project), "field-name": "repository_ref" } }
+ = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
+ - else
+ = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
+ - elsif search_service.group
+ - link_to_group = link_to(search_service.group.name, search_service.group, class: 'ml-md-1')
+ = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
+ - if search_service.show_sort_dropdown?
+ .gl-md-display-flex.gl-flex-direction-column
+ #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
+
diff --git a/app/views/search/_results_status_vert_nav.html.haml b/app/views/search/_results_status_vert_nav.html.haml
new file mode 100644
index 00000000000..03916911f43
--- /dev/null
+++ b/app/views/search/_results_status_vert_nav.html.haml
@@ -0,0 +1,23 @@
+.search-results-status
+ .gl-display-flex.gl-flex-direction-column
+ .gl-p-5.gl-display-flex
+ .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
+ - unless search_service.without_count?
+ = search_entries_info(search_service.search_objects, search_service.scope, params[:search])
+ - unless search_service.show_snippets?
+ - if search_service.project
+ - link_to_project = link_to(search_service.project.full_name, search_service.project, class: 'ml-md-1')
+ - if search_service.scope == 'blobs'
+ = _("in")
+ .mx-md-1
+ #js-blob-ref-switcher{ data: { "project-id" => search_service.project.id, "ref" => repository_ref(search_service.project), "field-name": "repository_ref" } }
+ = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
+ - else
+ = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
+ - elsif search_service.group
+ - link_to_group = link_to(search_service.group.name, search_service.group, class: 'ml-md-1')
+ = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
+ - if search_service.show_sort_dropdown?
+ .gl-md-display-flex.gl-flex-direction-column
+ #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
+ %hr.gl-mb-5.gl-mt-0.gl-border-gray-100.gl-w-full
diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml
index a28d9effbdd..a811dabf399 100644
--- a/app/views/search/results/_snippet_title.html.haml
+++ b/app/views/search/results/_snippet_title.html.haml
@@ -15,6 +15,6 @@
%span
by
= link_to user_snippets_path(snippet_title.author) do
- = image_tag avatar_icon_for_user(snippet_title.author), class: "avatar avatar-inline s16", alt: ''
+ = render Pajamas::AvatarComponent.new(snippet_title.author, size: 16, class: 'gl-mt-n1')
= snippet_title.author_name
%span.light= time_ago_with_tooltip(snippet_title.created_at)
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index b59275c35df..d6900c397a0 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -4,6 +4,6 @@
%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' }
%span.gl-display-flex.gl-align-items-center
= link_to wiki_blob_link, data: { track_action: 'click_text', track_label: "wiki_title", track_property: 'search_result' }, class: 'gl-w-full' do
- %span.term.str-truncated.gl-font-weight-bold= ::Gitlab::Git::Wiki::GollumSlug.canonicalize_filename(wiki_blob.path)
+ %span.term.str-truncated.gl-font-weight-bold= ::Wiki.canonicalize_filename(wiki_blob.path)
.description.term.col-sm-10.gl-px-0
= simple_search_highlight_and_truncate(wiki_blob.data, @search_term)
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 5a45e512579..9d812e77ad4 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -22,5 +22,6 @@
.gl-mt-3
#js-search-topbar{ data: { "group-initial-data": group_attributes.to_json, "project-initial-data": project_attributes.to_json } }
- if @search_term
- = render 'search/category'
+ - if Feature.disabled?(:search_page_vertical_nav, current_user)
+ = render 'search/category'
= render 'search/results'
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 6b502ee928e..48ae1f7eb1d 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -9,14 +9,14 @@
%span.js-clone-dropdown-label
= default_clone_protocol.upcase
= sprite_icon('chevron-down', css_class: 'gl-icon')
- %ul.dropdown-menu.dropdown-menu-selectable.clone-options-dropdown
+ %ul.dropdown-menu.dropdown-menu-selectable.clone-options-dropdown{ data: { qa_selector: 'clone_dropdown_content' } }
%li
= ssh_clone_button(container)
%li
= http_clone_button(container)
= render_if_exists 'shared/kerberos_clone_button', container: container
- = text_field_tag :clone_url, default_url_to_repo(container), class: "js-select-on-focus btn gl-button", readonly: true, aria: { label: _('Repository clone URL') }
+ = text_field_tag :clone_url, default_url_to_repo(container), class: "js-select-on-focus btn gl-button", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'clone_url_content' }
.input-group-append
= clipboard_button(target: '#clone_url', title: _("Copy URL"), class: "input-group-text gl-button btn-default btn-clipboard")
diff --git a/app/views/shared/_commit_well.html.haml b/app/views/shared/_commit_well.html.haml
deleted file mode 100644
index 48fe258d01f..00000000000
--- a/app/views/shared/_commit_well.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-.info-well.d-none.d-sm-block.project-last-commit.gl-mb-3
- .well-segment
- %ul.blob-commit-info
- = render 'projects/commits/commit', commit: commit, ref: ref, project: project
diff --git a/app/views/shared/_custom_attributes.html.haml b/app/views/shared/_custom_attributes.html.haml
index 966ab8e3cb1..6e5f1cb063c 100644
--- a/app/views/shared/_custom_attributes.html.haml
+++ b/app/views/shared/_custom_attributes.html.haml
@@ -1,12 +1,13 @@
- return unless custom_attributes.present?
-.card
- .card-header
+= render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0' }) do |c|
+ - c.header do
= link_to(_('Custom Attributes'), help_page_path('api/custom_attributes.md'))
- %ul.content-list
- - custom_attributes.each do |custom_attribute|
- %li
- %span.light
- = custom_attribute.key
- %strong
- = custom_attribute.value
+ - c.body do
+ %ul.content-list
+ - custom_attributes.each do |custom_attribute|
+ %li
+ %span.light
+ = custom_attribute.key
+ %strong
+ = custom_attribute.value
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index 89be816fc76..73ace033dc6 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -4,11 +4,10 @@
- blame_path = project_blame_path(@project, tree_join(@ref, blob.path))
.line-numbers{ class: "gl-px-0!", data: { blame_path: blame_path } }
- if blob.data.present?
- - link = blob_link if defined?(blob_link)
- blob.data.each_line.each_with_index do |_, index|
- i = index + offset
-# We're not using `link_to` because it is too slow once we get to thousands of lines.
- %a.file-line-num.diff-line-num{ class: ("js-line-links" if Feature.enabled?(:file_line_blame)), href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
+ %a.file-line-num.diff-line-num{ class: ("js-line-links" if Feature.enabled?(:file_line_blame)), href: "#L#{i}", id: "L#{i}", 'data-line-number' => i }
= i
- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
.blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index 0c88ac66b8b..eada58091b7 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -1,6 +1,7 @@
- ajax = local_assigns.fetch(:ajax, false)
- title = local_assigns.fetch(:title, _('Add a %{type}') % { type: type })
- prefix = local_assigns.fetch(:prefix, :personal_access_token)
+- description_prefix = local_assigns.fetch(:description_prefix, prefix)
- help_path = local_assigns.fetch(:help_path)
- resource = local_assigns.fetch(:resource, false)
- access_levels = local_assigns.fetch(:access_levels, false)
@@ -43,7 +44,7 @@
%p.text-secondary#select_scope_help_text
= s_('Tokens|Scopes set the permission levels granted to the token.')
= link_to _("Learn more."), help_path, target: '_blank', rel: 'noopener noreferrer'
- = render 'shared/tokens/scopes_form', prefix: prefix, token: token, scopes: scopes, f: f
+ = render 'shared/tokens/scopes_form', prefix: prefix, description_prefix: description_prefix, token: token, scopes: scopes, f: f
.gl-mt-3
- = f.submit _('Create %{type}') % { type: type }, class: 'gl-button btn btn-confirm', data: { qa_selector: 'create_token_button' }
+ = f.submit _('Create %{type}') % { type: type }, data: { qa_selector: 'create_token_button' }, pajamas_button: true
diff --git a/app/views/shared/blob/_markdown_buttons.html.haml b/app/views/shared/blob/_markdown_buttons.html.haml
index 4db1d20e81b..db53d78dadb 100644
--- a/app/views/shared/blob/_markdown_buttons.html.haml
+++ b/app/views/shared/blob/_markdown_buttons.html.haml
@@ -1,4 +1,5 @@
- modifier_key = client_js_flags[:isMac] ? '⌘' : s_('KeyboardKey|Ctrl+')
+- supports_file_upload = local_assigns.fetch(:supports_file_upload, true)
.md-header-toolbar.active
= markdown_toolbar_button({ icon: "bold",
@@ -23,14 +24,19 @@
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "- ", "md-prepend" => true }, title: _("Add a bullet list") })
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
= markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a checklist") })
+ = markdown_toolbar_button({ icon: "list-indent",
+ data: { "md-command" => 'indentLines', "md-shortcuts": '["mod+]"]' },
+ css_class: 'gl-display-none',
+ title: sprintf(s_("MarkdownEditor|Indent line (%{modifier_key}])") % { modifier_key: modifier_key }) })
+ = markdown_toolbar_button({ icon: "list-outdent",
+ data: { "md-command" => 'outdentLines', "md-shortcuts": '["mod+["]' },
+ css_class: 'gl-display-none',
+ title: sprintf(s_("MarkdownEditor|Outdent line (%{modifier_key}[)") % { modifier_key: modifier_key }) })
= markdown_toolbar_button({ icon: "details-block",
data: { "md-tag" => "<details><summary>Click to expand</summary>\n{text}\n</details>", "md-prepend" => true, "md-select" => "Click to expand" },
title: _("Add a collapsible section") })
- = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: _("Add a table") })
- = markdown_toolbar_button({ icon: "paperclip",
- data: { "testid" => "button-attach-file" },
- css_class: 'js-attach-file-button markdown-selector',
- title: _("Attach a file or image") })
+ = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| | |\n| | |", "md-prepend" => true }, title: _("Add a table") })
+ - if supports_file_upload
+ = render Pajamas::ButtonComponent.new(icon: 'paperclip', category: :tertiary, button_options: { 'aria-label': _("Attach a file or image"), class: 'has-tooltip js-attach-file-button', data: { testid: 'button-attach-file', container: 'body' } })
- if show_fullscreen_button
- %button.gl-button.btn.btn-default-tertiary.btn-icon.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: _("Go full screen"), data: { container: "body" } }
- = sprite_icon("maximize")
+ = render Pajamas::ButtonComponent.new(icon: 'maximize', category: :tertiary, button_options: { 'tabindex': -1, 'aria-label': _("Go full screen"), class: 'has-tooltip js-zen-enter', data: { container: 'body' } })
diff --git a/app/views/shared/deploy_keys/_project_group_form.html.haml b/app/views/shared/deploy_keys/_project_group_form.html.haml
index d76ef8feb62..11fa44fe282 100644
--- a/app/views/shared/deploy_keys/_project_group_form.html.haml
+++ b/app/views/shared/deploy_keys/_project_group_form.html.haml
@@ -17,4 +17,4 @@
help_text: _('Allow this key to push to this repository')
.form-group.row
- = f.submit _("Add key"), class: "btn gl-button btn-confirm", data: { qa_selector: "add_deploy_key_button"}
+ = f.submit _("Add key"), data: { qa_selector: "add_deploy_key_button"}, pajamas_button: true
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index eade973d72a..1b48843eb10 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -34,4 +34,4 @@
= f.gitlab_ui_checkbox_component :write_package_registry, 'write_package_registry', help_text: s_('DeployTokens|Allows read and write access to the package registry.'), checkbox_options: { data: { qa_selector: 'deploy_token_write_package_registry_checkbox' } }
.gl-mt-3
- = f.submit s_('DeployTokens|Create deploy token'), class: 'btn gl-button btn-confirm', data: { qa_selector: 'create_deploy_token_button' }
+ = f.submit s_('DeployTokens|Create deploy token'), data: { qa_selector: 'create_deploy_token_button' }, pajamas_button: true
diff --git a/app/views/shared/deploy_tokens/_index.html.haml b/app/views/shared/deploy_tokens/_index.html.haml
index 79bf35e2726..faec379e42b 100644
--- a/app/views/shared/deploy_tokens/_index.html.haml
+++ b/app/views/shared/deploy_tokens/_index.html.haml
@@ -8,10 +8,20 @@
%p
= description
.settings-content
- - if @created_deploy_token
- = render 'shared/deploy_tokens/new_deploy_token', deploy_token: @created_deploy_token
- %h5.gl-mt-0
- = s_('DeployTokens|New deploy token')
- = render 'shared/deploy_tokens/form', group_or_project: group_or_project, token: @new_deploy_token, presenter: @deploy_tokens
+ - if Feature.enabled?(:ajax_new_deploy_token, group_or_project)
+ #js-new-deploy-token{ data: {
+ container_registry_enabled: container_registry_enabled?(group_or_project),
+ packages_registry_enabled: packages_registry_enabled?(group_or_project),
+ create_new_token_path: create_deploy_token_path(group_or_project),
+ token_type: group_or_project.is_a?(Group) ? 'group' : 'project',
+ deploy_tokens_help_url: help_page_path('user/project/deploy_tokens/index.md')
+ }
+ }
+ - else
+ - if @created_deploy_token
+ = render 'shared/deploy_tokens/new_deploy_token', deploy_token: @created_deploy_token
+ %h5.gl-mt-0
+ = s_('DeployTokens|New deploy token')
+ = render 'shared/deploy_tokens/form', group_or_project: group_or_project, token: @new_deploy_token, presenter: @deploy_tokens
%hr
= render 'shared/deploy_tokens/table', group_or_project: group_or_project, active_tokens: @deploy_tokens
diff --git a/app/views/shared/doorkeeper/applications/_index.html.haml b/app/views/shared/doorkeeper/applications/_index.html.haml
index b14ff9b2508..6a770a4fcb2 100644
--- a/app/views/shared/doorkeeper/applications/_index.html.haml
+++ b/app/views/shared/doorkeeper/applications/_index.html.haml
@@ -1,6 +1,6 @@
- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index 0bec94f70ea..e6bdefc64d2 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -14,7 +14,7 @@
.block
.title
= _('Status')
- .js-issue-status
+ .js-status-dropdown
.block
.title
= _('Assignee')
@@ -41,15 +41,7 @@
.block
.title
= _('Subscriptions')
- .filter-item
- = dropdown_tag(_("Select subscription"), options: { toggle_class: "js-subscription-event", title: _("Change subscription"), dropdown_class: "dropdown-menu-selectable", data: { field_name: "update[subscription_event]", default_label: _("Subscription") } } ) do
- %ul
- %li
- %a{ href: "#", data: { id: "subscribe" } }
- = _('Subscribe')
- %li
- %a{ href: "#", data: { id: "unsubscribe" } }
- = _('Unsubscribe')
+ .js-subscriptions-dropdown
= hidden_field_tag "update[issuable_ids]", []
= hidden_field_tag :state_event, params[:state_event]
diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml
index 69ff477d415..94b7fe14721 100644
--- a/app/views/shared/issuable/_feed_buttons.html.haml
+++ b/app/views/shared/issuable/_feed_buttons.html.haml
@@ -1,8 +1,8 @@
- show_calendar_button = local_assigns.fetch(:show_calendar_button, true)
-= link_to safe_params.merge(rss_url_options), class: 'btn gl-button btn-default btn-icon has-tooltip', data: { container: 'body', testid: 'rss-feed-link' }, title: _('Subscribe to RSS feed') , 'aria-label': _('Subscribe to RSS feed') do
- = sprite_icon('rss')
+= render Pajamas::ButtonComponent.new(href: safe_params.merge(rss_url_options), icon: 'rss', button_options: { class: 'has-tooltip', 'aria-label': _('Subscribe to RSS feed'), data: { container: 'body', testid: 'rss-feed-link' } }) do
+ = _('Subscribe to RSS feed')
- if show_calendar_button
- = link_to safe_params.merge(calendar_url_options), class: 'btn gl-button btn-default btn-icon has-tooltip', data: { container: 'body' }, title: _('Subscribe to calendar'), 'aria-label': _('Subscribe to calendar') do
- = sprite_icon('calendar')
+ = render Pajamas::ButtonComponent.new(href: safe_params.merge(calendar_url_options), icon: 'calendar', button_options: { class: 'has-tooltip', 'aria-label': _('Subscribe to calendar'), data: { container: 'body' } }) do
+ = _('Subscribe to calendar')
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 53eb6f4c63b..5b7f9c4226c 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -62,9 +62,9 @@
= sanitize(html_escape(_('Please review the %{linkStart}contribution guidelines%{linkEnd} for this project.')) % { linkStart: contribution_guidelines_start, linkEnd: contribution_guidelines_end })
- 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', track_experiment: 'promote_mr_approvals_in_free', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit "#{_('Create')} #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-confirm gl-mr-2', data: { qa_selector: 'issuable_create_button', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- else
- = form.submit _('Save changes'), class: 'gl-button btn btn-confirm gl-mr-2', data: { track_experiment: 'promote_mr_approvals_in_free', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit _('Save changes'), class: 'gl-button btn btn-confirm gl-mr-2', data: { track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- if issuable.new_record?
= link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'btn gl-button btn-default js-reset-autosave'
diff --git a/app/views/shared/issuable/_label_page_create.html.haml b/app/views/shared/issuable/_label_page_create.html.haml
index ec78b3f7ce3..eb3acd8e055 100644
--- a/app/views/shared/issuable/_label_page_create.html.haml
+++ b/app/views/shared/issuable/_label_page_create.html.haml
@@ -19,7 +19,7 @@
%input.js-add-list{ type: "checkbox", name: "add_list", checked: add_list }
%span= _('Add list')
.clearfix
- %button.gl-button.btn.btn-confirm.float-left.js-new-label-btn{ type: "button" }
+ = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'float-left js-new-label-btn' }) do
= _('Create')
- %button.gl-button.btn.btn-default.float-right.js-cancel-label-btn{ type: "button" }
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'float-right js-cancel-label-btn' }) do
= _('Cancel')
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
index ef539029272..58108ceeb76 100644
--- a/app/views/shared/issuable/_milestone_dropdown.html.haml
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -11,10 +11,6 @@
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'), qa_selector: "issuable_milestone_dropdown", testid: "issuable-milestone-dropdown" } }) 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')
%li
= link_to project_milestones_path(project) do
- if can? current_user, :admin_milestone, project
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 21716710015..72940b64801 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -11,10 +11,11 @@
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
- .check-all-holder.gl-display-none.gl-sm-display-block.hidden.gl-float-left.gl-mr-5.gl-line-height-36
- - checkbox_id = 'check-all-issues'
- %label.gl-sr-only{ for: checkbox_id }= _('Select all')
- = check_box_tag checkbox_id, nil, false, class: "check-all-issues left"
+ .check-all-holder.gl-display-none.gl-sm-display-block.hidden.gl-float-left.gl-mr-3.gl-line-height-36
+ = render Pajamas::CheckboxTagComponent.new(name: 'check-all-issues', value: nil) do |c|
+ = c.label do
+ %span.gl-sr-only
+ = _('Select all')
.issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
.filtered-search-box
- if type != :boards
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index f2ce0676a9a..4199b7e870b 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -27,7 +27,7 @@
#js-severity
- if reviewers
- .block.reviewer
+ .block.reviewer{ data: { qa_selector: 'reviewers_block_container' } }
= render "shared/issuable/sidebar_reviewers", issuable_sidebar: issuable_sidebar, reviewers: reviewers, signed_in: signed_in
- if issuable_sidebar[:supports_escalation]
@@ -65,7 +65,7 @@
= gl_loading_icon(inline: true)
- if issuable_sidebar.dig(:features_available, :health_status)
- .js-sidebar-status-entry-point{ data: sidebar_status_data(issuable_sidebar, @project) }
+ .js-sidebar-health-status-entry-point{ data: sidebar_status_data(issuable_sidebar, @project) }
- if issuable_sidebar.has_key?(:confidential)
-# haml-lint:disable InlineJavaScript
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index e9b04579808..62221fb8218 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -39,7 +39,7 @@
- data[:multi_select] = true
- data['dropdown-title'] = title
- data['dropdown-header'] = dropdown_options[:data][:'dropdown-header']
- - data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select']
+ - data['max-select'] = dropdown_max_select(dropdown_options[:data], :limit_assignees_per_issuable)
- options[:data].merge!(data)
= render 'shared/issuable/sidebar_user_dropdown',
diff --git a/app/views/shared/issuable/_sidebar_reviewers.html.haml b/app/views/shared/issuable/_sidebar_reviewers.html.haml
index 3f78f29ea24..771db8af6a8 100644
--- a/app/views/shared/issuable/_sidebar_reviewers.html.haml
+++ b/app/views/shared/issuable/_sidebar_reviewers.html.haml
@@ -36,7 +36,10 @@
- data[:multi_select] = true
- data['dropdown-title'] = title
- data['dropdown-header'] = dropdown_options[:data][:'dropdown-header']
- - data['max-select'] = dropdown_max_select(dropdown_options[:data])
+ - data[:suggested_reviewers_header] = dropdown_options[:data][:suggested_reviewers_header]
+ - data[:all_members_header] = dropdown_options[:data][:all_members_header]
+ - data[:show_suggested] = dropdown_options[:data][:show_suggested]
+ - data['max-select'] = dropdown_max_select(dropdown_options[:data], :limit_reviewer_and_assignee_size)
- options[:data].merge!(data)
= render 'shared/issuable/sidebar_user_dropdown',
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index e36c4cd6be0..ccc1a9fda6e 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -1,5 +1,5 @@
- viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues'
-- viewing_merge_requests = controller.controller_name == 'merge_requests'
+- viewing_merge_requests = controller.controller_name == 'merge_requests' || controller.action_name == 'merge_requests'
- items = issuable_sort_options(viewing_issues, viewing_merge_requests)
- selected = issuable_sort_option_overrides[@sort] || @sort
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
index 369aa53586f..8a9b71fd91e 100644
--- a/app/views/shared/issue_type/_details_content.html.haml
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -2,7 +2,7 @@
- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
.issue-details.issuable-details.js-issue-details
- .detail-page-description.content-block.js-detail-page-description
+ .detail-page-description.content-block.js-detail-page-description.gl-pb-0.gl-border-none
#js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json, issuable_id: issuable.id, full_path: @project.full_path } }
.title-container
%h1.title.page-title.gl-font-size-h-display= markdown_field(issuable, :title)
@@ -12,6 +12,9 @@
= edited_time_ago_with_tooltip(issuable, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago')
+ .js-issue-widgets
+ = render 'shared/issue_type/emoji_block', issuable: issuable, api_awards_path: api_awards_path
+
.js-issue-widgets
= render 'shared/issue_type/sentry_stack_trace', issuable: issuable
@@ -32,7 +35,6 @@
-# This element is filled in using JavaScript.
.js-issue-widgets
- = render 'shared/issue_type/emoji_block', issuable: issuable, api_awards_path: api_awards_path
= render 'projects/issues/discussion'
diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml
index 08fba712d5e..ccb501dae11 100644
--- a/app/views/shared/issue_type/_details_header.html.haml
+++ b/app/views/shared/issue_type/_details_header.html.haml
@@ -2,7 +2,7 @@
- badge_classes = 'issuable-status-badge gl-mr-3'
.detail-page-header
- .detail-page-header-body
+ .detail-page-header-body.gl-flex-wrap-wrap
= gl_badge_tag({ variant: :info, icon: 'issue-closed', icon_classes: 'gl-mr-0!' }, { class: "#{issue_status_visibility(issuable, status_box: :closed)} #{badge_classes} issuable-status-badge-closed" }) do
.gl-display-none.gl-sm-display-block.gl-ml-2
= issue_closed_text(issuable, current_user)
@@ -13,9 +13,8 @@
%span.gl-display-none.gl-sm-display-block.gl-ml-2
= _('Open')
- .issuable-meta
- #js-issuable-header-warnings{ data: { hidden: issue_hidden?(issuable).to_s } }
- = issuable_meta(issuable, @project)
+ #js-issuable-header-warnings{ data: { hidden: issue_hidden?(issuable).to_s } }
+ = issuable_meta(issuable, @project)
%a.btn.gl-button.btn-default.btn-icon.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
= sprite_icon('chevron-double-lg-left')
diff --git a/app/views/shared/issue_type/_emoji_block.html.haml b/app/views/shared/issue_type/_emoji_block.html.haml
index 61e28f18d3b..a5c71fb1d24 100644
--- a/app/views/shared/issue_type/_emoji_block.html.haml
+++ b/app/views/shared/issue_type/_emoji_block.html.haml
@@ -4,7 +4,5 @@
.row.gl-m-0.gl-justify-content-space-between
.js-noteable-awards
= render 'award_emoji/awards_block', awardable: issuable, inline: true, api_awards_path: api_awards_path
- .new-branch-col.gl-display-flex.gl-my-2.gl-font-size-0.gl-gap-3
- = render_if_exists "projects/issues/timeline_toggle", issuable: issuable
- #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(issuable), notes_filters: UserPreference.notes_filters.to_json } }
+ .new-branch-col.gl-font-size-0
= render 'new_branch' if show_new_branch_button?
diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml
index e6d6d0998dc..c6932d49d33 100644
--- a/app/views/shared/labels/_form.html.haml
+++ b/app/views/shared/labels/_form.html.haml
@@ -1,4 +1,4 @@
-= form_for @label, as: :label, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f|
+= gitlab_ui_form_for @label, as: :label, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f|
= form_errors(@label)
.form-group.row
@@ -26,9 +26,9 @@
.gl-display-flex.gl-justify-content-space-between
%div
- if @label.persisted?
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2'
+ = f.submit _('Save changes'), class: 'js-save-button gl-mr-2', pajamas_button: true
- else
- = f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2', data: { qa_selector: 'label_create_button' }
+ = f.submit _('Create label'), class: 'js-save-button gl-mr-2', data: { qa_selector: 'label_create_button' }, pajamas_button: true
= link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel gl-mr-2'
- if @label.persisted?
- presented_label = @label.present
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 23f78f4be45..376e51a6b15 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -12,7 +12,7 @@
%li.member.js-member.py-2.px-3.d-flex.flex-column{ class: [dom_class(member), ("flex-md-row" unless force_mobile_view)], id: dom_id(member), data: { qa_selector: 'member_row' } }
%span.list-item-name.mb-2.m-md-0
- if user
- = image_tag avatar_icon_for_user(user, 40), class: "avatar s40 flex-shrink-0 flex-grow-0", alt: ''
+ = render Pajamas::AvatarComponent.new(user, size: 32, class: 'gl-mr-3 flex-shrink-0 flex-grow-0')
.user-info
%span.mr-1
= link_to user.name, user_path(user), class: 'member js-user-link', data: { user_id: user.id }
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index 98e2c6c43b1..31625c22a94 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -5,7 +5,7 @@
- return if requesters.empty?
-= render Pajamas::CardComponent.new(card_options: { class: 'gl-mt-3 gl-mb-5', data: { testid: 'access-requests' } }, body_options: { class: 'gl-p-0' }) do |c|
+= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5', data: { testid: 'access-requests' } }, body_options: { class: 'gl-p-0' }) do |c|
- c.header do
= _('Users requesting access to')
%strong= membership_source.name
diff --git a/app/views/shared/milestones/_issuables.html.haml b/app/views/shared/milestones/_issuables.html.haml
index 460ddd0897c..2502f7fca62 100644
--- a/app/views/shared/milestones/_issuables.html.haml
+++ b/app/views/shared/milestones/_issuables.html.haml
@@ -1,22 +1,20 @@
- show_counter = local_assigns.fetch(:show_counter, false)
- primary = local_assigns.fetch(:primary, false)
-- panel_class = primary ? 'bg-primary text-white' : ''
-.card
- .card-header{ class: panel_class }
- .header.gl-mb-2
- .title
- = title
- .issuable-count-weight.gl-ml-3
+= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }, header_options: { class: milestone_header_class(primary, issuables) }) do |c|
+ - c.header do
+ .gl-flex-grow-2
+ = title
+ .gl-ml-3.gl-flex-shrink-0.gl-font-weight-bold.gl-white-space-nowrap{ class: milestone_counter_class(primary) }
- if show_counter
- %span.counter
+ %span
= sprite_icon('issues', css_class: 'gl-vertical-align-text-bottom')
= number_with_delimiter(issuables.length)
= render_if_exists "shared/milestones/issuables_weight", issuables: issuables
-
- - class_prefix = dom_class(issuables).pluralize
- %ul{ class: "content-list milestone-#{class_prefix}-list", id: "#{class_prefix}-list-#{id}" }
- = render partial: 'shared/milestones/issuable',
- collection: issuables,
- as: :issuable,
- locals: { show_project_name: show_project_name }
+ = c.body do
+ - class_prefix = dom_class(issuables).pluralize
+ %ul{ class: "content-list milestone-#{class_prefix}-list", id: "#{class_prefix}-list-#{id}" }
+ = render partial: 'shared/milestones/issuable',
+ collection: issuables,
+ as: :issuable,
+ locals: { show_project_name: show_project_name }
diff --git a/app/views/shared/milestones/_participants_tab.html.haml b/app/views/shared/milestones/_participants_tab.html.haml
index fe83040c168..f90967c3b15 100644
--- a/app/views/shared/milestones/_participants_tab.html.haml
+++ b/app/views/shared/milestones/_participants_tab.html.haml
@@ -1,8 +1,8 @@
%ul.bordered-list
- users.each do |user|
%li
- = link_to user, title: user.name, class: "darken" do
- = image_tag avatar_icon_for_user(user, 32), class: "avatar s32"
- %strong= truncate(user.name, length: 40)
- %div
+ = link_to user, title: user.name, class: "gl-display-flex" do
+ = render Pajamas::AvatarComponent.new(user, size: 32, class: "gl-mr-3")
+ .gl-display-flex.gl-flex-direction-column
+ %strong= truncate(user.name, length: 40)
%small.cgray= user.username
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index 3ab8514aebf..c552e94ac57 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -6,17 +6,18 @@
- note_counter = local_assigns.fetch(:note_counter, 0)
%li.timeline-entry.note-wrapper{ id: dom_id(note),
- class: ["note", "note-row-#{note.id}", ('system-note' if note.system)],
+ class: ["note", "note-comment", "note-row-#{note.id}", ('system-note' if note.system)],
data: { author_id: note.author.id,
editable: note_editable,
note_id: note.id } }
.timeline-entry-inner
- .timeline-icon
- - if note.system
+ - if note.system
+ .timeline-icon
= icon_for_system_note(note)
- - else
+ - else
+ .timeline-avatar.gl-float-left
%a.image-diff-avatar-link{ href: user_path(note.author) }
- = image_tag avatar_icon_for_user(note.author), alt: '', class: 'avatar s40'
+ = render Pajamas::AvatarComponent.new(note.author, size: 32, alt: '')
- if note.is_a?(DiffNote) && note.on_image?
- if show_image_comment_badge && note_counter == 0
-# Only show this for the first comment in the discussion
@@ -34,9 +35,9 @@
%span.note-header-author-name.bold
= note.author.name
= user_status(note.author)
- %span.note-headline-light{ data: { qa_selector: 'note_author_content' } }
+ %spannote-headline-light{ data: { qa_selector: 'note_author_content' } }
= note.author.to_reference
- %span.note-headline-light.note-headline-meta
+ %span.note-headline-ligh.note-headline-meta
- if note.system
%span.system-note-message
= markdown_field(note, :note)
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index ae264f2188f..81e2e066bd3 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -9,7 +9,7 @@
- compact_mode = false unless local_assigns[:compact_mode] == true
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && can_show_last_commit_in_list?(project)
- css_class = '' unless local_assigns[:css_class]
-- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
+- css_class += " gl-display-flex!"
- cache_key = project_list_cache_key(project, pipeline_status: pipeline_status)
- updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
- show_pipeline_status_icon = pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
@@ -18,15 +18,15 @@
- css_controls_class << "with-pipeline-status" if show_pipeline_status_icon && last_pipeline.present?
- avatar_container_class = project.creator && use_creator_avatar ? '' : 'rect-avatar'
-%li.project-row.d-flex{ class: css_class }
+%li.project-row.gl-align-items-center{ class: css_class }
= cache(cache_key) do
- if avatar
- .avatar-container.s48.flex-grow-0.flex-shrink-0{ class: avatar_container_class }
+ .flex-grow-0.flex-shrink-0{ class: avatar_container_class }
= link_to project_path(project), class: dom_class(project) do
- if project.creator && use_creator_avatar
- = image_tag avatar_icon_for_user(project.creator, 48), class: "avatar s48", alt: ''
+ = render Pajamas::AvatarComponent.new(project.creator, size: 48, alt: '', class: 'gl-mr-5')
- else
- = project_icon(project, alt: '', class: 'avatar project-avatar s48', width: 48, height: 48)
+ = render Pajamas::AvatarComponent.new(project, size: 48, alt: '', class: 'gl-mr-5')
.project-details.d-sm-flex.flex-sm-fill.align-items-center{ data: { qa_selector: 'project_content', qa_project_name: project.name } }
.flex-wrapper
.d-flex.align-items-center.flex-wrap.project-title
@@ -52,7 +52,7 @@
-# haml-lint:disable UnnecessaryStringOutput
= ' ' # prevent haml from eating the space between elements
.metadata-info.gl-mt-3
- %span.user-access-role.d-block{ data: { qa_selector: 'user_role_content' } }= Gitlab::Access.human_access(access)
+ %span.user-access-role.gl-display-block{ data: { qa_selector: 'user_role_content' } }= localized_project_human_access(access)
- if !explore_projects_tab?
.metadata-info.gl-mt-3
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index a5170b199e8..e598343d698 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -1,4 +1,4 @@
-- form_field_classes = local_assigns[:admin_view] || !Feature.enabled?(:project_list_filter_bar) ? 'input-short js-projects-list-filter' : ''
+- form_field_classes = local_assigns[:admin_view] || !Feature.enabled?(:project_list_filter_bar) ? 'input-short js-projects-list-filter' : 'gl-w-full! gl-pl-7 '
- placeholder = local_assigns[:search_form_placeholder] ? search_form_placeholder : _('Filter by name')
= form_tag filter_projects_path, method: :get, class: 'project-filter-form', data: { qa_selector: 'project_filter_form_container' }, id: 'project-filter-form' do |f|
diff --git a/app/views/shared/runners/_runner_description.html.haml b/app/views/shared/runners/_runner_description.html.haml
index 436dbfd2b49..dc689303f77 100644
--- a/app/views/shared/runners/_runner_description.html.haml
+++ b/app/views/shared/runners/_runner_description.html.haml
@@ -1,6 +1,12 @@
.light.gl-mt-3
%p
- = _("Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:")
+ = s_("Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine.")
+
+ %h5
+ = s_("Runners|How do runners pick up jobs?")
+
+ %p
+ = s_("Runners|Runners are either:")
%div
%ul
@@ -10,3 +16,7 @@
%li
= gl_badge_tag s_("Runners|paused"), variant: :danger, size: :sm
= _('- Not available to run jobs.')
+
+ %p
+ = s_("Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run.")
+ = link_to _("Learn more."), help_page_path("ci/runners/configure_runners", anchor: "use-tags-to-control-which-jobs-a-runner-can-run"), target: '_blank'
diff --git a/app/views/shared/runners/_shared_runners_description.html.haml b/app/views/shared/runners/_shared_runners_description.html.haml
index 2779901ca0c..c8ddb5d5176 100644
--- a/app/views/shared/runners/_shared_runners_description.html.haml
+++ b/app/views/shared/runners/_shared_runners_description.html.haml
@@ -1,12 +1,9 @@
--# "MaxBuilds" is a runner configuration keyword so it must not be translated.
-- link = link_to 'MaxBuilds', 'https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section', target: '_blank', rel: 'noopener noreferrer'
+- shared_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('ci/runners/runners_scope.md', anchor: 'shared-runners') }
%h4
= _('Shared runners')
.bs-callout{ data: { testid: 'shared-runners-description' } }
- %p= _('These runners are shared across this GitLab instance.')
+ %p= s_('Runners|%{link_start}These runners%{link_end} are available to all groups and projects.').html_safe % { link_start: shared_link_start, link_end: '</a>'.html_safe }
- if Gitlab::CurrentSettings.shared_runners_text.present?
= markdown(Gitlab::CurrentSettings.current_application_settings.shared_runners_text)
- - else
- %p= _('The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com).').html_safe % { link: link }
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index 3cd70dab4d5..6caadeb0ba4 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -2,7 +2,7 @@
- notes_count = @noteable_meta_data[snippet.id].user_notes_count
%li.snippet-row.py-3{ data: { qa_selector: 'snippet_link', qa_snippet_title: snippet.title } }
- = image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 d-none d-sm-block", alt: ''
+ = render Pajamas::AvatarComponent.new(snippet.author, size: 48, alt: "", class: 'gl-display-none gl-sm-display-block gl-float-left gl-mr-3')
= link_to gitlab_snippet_path(snippet), class: "title" do
= snippet.title
@@ -20,16 +20,15 @@
= visibility_level_icon(snippet.visibility_level)
.snippet-info
- #{snippet.to_reference} &middot;
- authored #{time_ago_with_tooltip(snippet.created_at, placement: 'bottom', html_class: 'snippet-created-ago')}
- by
- = link_to user_snippets_path(snippet.author), class: "js-user-link", data: { user_id: snippet.author.id } do
- = snippet.author_name
- - if link_project && snippet.project_id?
- %span.d-none.d-sm-inline-block
- in
- = link_to project_path(snippet.project) do
- = snippet.project.full_name
+ .gl-display-inline{ data: { testid: 'snippet-created-at'} }
+ - created_at = time_ago_with_tooltip(snippet.created_at, placement: 'bottom')
+ - author = link_to(snippet.author_name, user_snippets_path(snippet.author), data: { user_id: snippet.author.id })
+ #{snippet.to_reference} &middot;
+ - if link_project && snippet.project_id?
+ - project_link = link_to(snippet.project.full_name, project_path(snippet.project))
+ = _('created %{timeAgo} by %{author} in %{project_link}').html_safe % { timeAgo: created_at, author: author, project_link: project_link }
+ - else
+ = _('created %{timeAgo} by %{author}').html_safe % { timeAgo: created_at, author: author }
- .float-right.snippet-updated-at
- %span updated #{time_ago_with_tooltip(snippet.updated_at, placement: 'bottom')}
+ .float-right
+ = _('updated %{timeAgo}').html_safe % { timeAgo: time_ago_with_tooltip(snippet.updated_at, placement: 'bottom') }
diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml
index 010376464f1..1c63ce490ed 100644
--- a/app/views/shared/tokens/_scopes_form.html.haml
+++ b/app/views/shared/tokens/_scopes_form.html.haml
@@ -1,11 +1,12 @@
- scopes = local_assigns.fetch(:scopes)
- prefix = local_assigns.fetch(:prefix)
+- description_prefix = local_assigns.fetch(:description_prefix, prefix)
- token = local_assigns.fetch(:token)
- f = local_assigns.fetch(:f)
%fieldset
- scopes.each do |scope|
- - help_text = t scope, scope: scope_description(prefix)
+ - help_text = t scope, scope: scope_description(description_prefix)
= f.gitlab_ui_checkbox_component :scopes, scope,
help_text: help_text,
checkbox_options: { checked: token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}", multiple: true, data: { qa_selector: "#{scope}_checkbox" } },
diff --git a/app/views/shared/users/_user.html.haml b/app/views/shared/users/_user.html.haml
index 93b3ce5f319..51eb24f6d4a 100644
--- a/app/views/shared/users/_user.html.haml
+++ b/app/views/shared/users/_user.html.haml
@@ -3,7 +3,7 @@
.col-lg-3.col-md-4.col-sm-12
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }) do |c|
= c.body do
- = image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
+ = render Pajamas::AvatarComponent.new(user, size: 48, alt: "", class: 'gl-float-left gl-mr-3')
.user-info
.block-truncated
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index afe72767b9a..c95e63bdc83 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -1,10 +1,13 @@
= form_errors(hook)
-.form-group
- = form.label :url, s_('Webhooks|URL'), class: 'label-bold'
- = form.text_field :url, class: 'form-control gl-form-input', placeholder: 'http://example.com/trigger-ci.json'
- %p.form-text.text-muted
- = s_('Webhooks|URL must be percent-encoded if it contains one or more special characters.')
+- if Feature.enabled?(:webhook_form_mask_url)
+ .js-vue-webhook-form{ data: webhook_form_data(hook) }
+- else
+ .form-group
+ = form.label :url, s_('Webhooks|URL'), class: 'label-bold'
+ = form.text_field :url, class: 'form-control gl-form-input', placeholder: 'http://example.com/trigger-ci.json'
+ %p.form-text.text-muted
+ = s_('Webhooks|URL must be percent-encoded if it contains one or more special characters.')
.form-group
= form.label :token, s_('Webhooks|Secret token'), class: 'label-bold'
= form.text_field :token, class: 'form-control gl-form-input', placeholder: ''
diff --git a/app/views/shared/web_hooks/_hook_errors.html.haml b/app/views/shared/web_hooks/_hook_errors.html.haml
index d95efe83e15..098cc19c435 100644
--- a/app/views/shared/web_hooks/_hook_errors.html.haml
+++ b/app/views/shared/web_hooks/_hook_errors.html.haml
@@ -4,16 +4,12 @@
- 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 Pajamas::AlertComponent.new(title: s_('Webhooks|Webhook was automatically disabled'),
+ - placeholders = { limit: number_with_delimiter(hook.rate_limit),
+ root_namespace: hook.parent.root_namespace.path }
+ = render Pajamas::AlertComponent.new(title: s_('Webhooks|Webhook rate limit has been reached'),
variant: :danger) do |c|
= c.body do
- = 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
+ = s_("Webhooks|Webhooks for %{root_namespace} are now disabled because they've been triggered more than %{limit} times per minute. They'll be automatically re-enabled in the next minute.").html_safe % placeholders
- elsif hook.permanently_disabled?
= render Pajamas::AlertComponent.new(title: s_('Webhooks|Webhook failed to connect'),
variant: :danger) do |c|
diff --git a/app/views/shared/web_hooks/_index.html.haml b/app/views/shared/web_hooks/_index.html.haml
index 5ec82ad6702..868633143cd 100644
--- a/app/views/shared/web_hooks/_index.html.haml
+++ b/app/views/shared/web_hooks/_index.html.haml
@@ -1,14 +1,13 @@
%hr
-.card#webhooks-index
- .card-header
- %h5
- = hook_class.underscore.humanize.titleize.pluralize
- (#{hooks.size})
-
- - if hooks.any?
- %ul.content-list
- - hooks.each do |hook|
- = render 'shared/web_hooks/hook', hook: hook
- - else
- %p.text-center.gl-mt-3.gl-mb-3
- = _('No webhooks enabled. Select trigger events above.')
+= render Pajamas::CardComponent.new(card_options: { id: 'webhooks-index' }, body_options: { class: 'gl-py-0'}) do |c|
+ - c.header do
+ = hook_class.underscore.humanize.titleize.pluralize
+ (#{hooks.size})
+ - c.body do
+ - if hooks.any?
+ %ul.content-list
+ - hooks.each do |hook|
+ = render 'shared/web_hooks/hook', hook: hook
+ - else
+ %p.text-center.gl-mt-3.gl-mb-3
+ = _('No webhooks enabled. Select trigger events above.')
diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml
index 21d63a6db3d..e1252e91c10 100644
--- a/app/views/shared/wikis/pages.html.haml
+++ b/app/views/shared/wikis/pages.html.haml
@@ -2,7 +2,6 @@
- breadcrumb_title s_("Wiki|Pages")
- page_title s_("Wiki|Pages"), _("Wiki")
- add_page_specific_style 'page_bundles/wiki'
-- wiki_sort_options = [{ text: s_("Wiki|Title"), value: 'title', href: wiki_path(@wiki, action: :pages, sort: Wiki::TITLE_ORDER)}, { text: s_("Wiki|Created date"), value: 'created_at', href: wiki_path(@wiki, action: :pages, sort: Wiki::CREATED_AT_ORDER) }]
.wiki-page-header.top-area.flex-column.flex-lg-row
%h1.page-title.gl-font-size-h-display.gl-flex-grow-1
@@ -15,8 +14,7 @@
.dropdown.inline.wiki-sort-dropdown
.btn-group{ role: 'group' }
- = gl_redirect_listbox_tag wiki_sort_options, params[:sort], data: { right: true }
- = wiki_sort_controls(@wiki, params[:sort], params[:direction])
+ = wiki_sort_controls(@wiki, params[:direction])
%ul.wiki-pages-list.content-list
= render @wiki_entries, context: 'pages'
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index f1093a3b730..47ccc449e1b 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -14,7 +14,7 @@
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
-.row-content-block.top-block.content-component-block
+.row-content-block.top-block.content-component-block.gl-px-0.gl-py-2
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
#notes.limited-width-notes= render "shared/notes/notes_with_form", :autocomplete => false
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 9b282340d0a..a0f6da57f9e 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1020,6 +1020,42 @@
:weight: 1
:idempotent: false
:tags: []
+- :name: github_importer:github_import_attachments_import_issue
+ :worker_name: Gitlab::GithubImport::Attachments::ImportIssueWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
+- :name: github_importer:github_import_attachments_import_merge_request
+ :worker_name: Gitlab::GithubImport::Attachments::ImportMergeRequestWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
+- :name: github_importer:github_import_attachments_import_note
+ :worker_name: Gitlab::GithubImport::Attachments::ImportNoteWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
+- :name: github_importer:github_import_attachments_import_release
+ :worker_name: Gitlab::GithubImport::Attachments::ImportReleaseWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
- :name: github_importer:github_import_import_diff_note
:worker_name: Gitlab::GithubImport::ImportDiffNoteWorker
:feature_category: :importers
@@ -2181,6 +2217,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: ci_parse_secure_file_metadata
+ :worker_name: Ci::ParseSecureFileMetadataWorker
+ :feature_category: :mobile_signing_deployment
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: ci_runners_process_runner_version_update
:worker_name: Ci::Runners::ProcessRunnerVersionUpdateWorker
:feature_category: :runner_fleet
@@ -2352,15 +2397,6 @@
:weight: 1
:idempotent: false
:tags: []
-- :name: experiments_record_conversion_event
- :worker_name: Experiments::RecordConversionEventWorker
- :feature_category: :users
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: export_csv
:worker_name: ExportCsvWorker
:feature_category: :team_planning
@@ -2739,42 +2775,6 @@
:weight: 1
:idempotent: false
:tags: []
-- :name: namespaces_onboarding_issue_created
- :worker_name: Namespaces::OnboardingIssueCreatedWorker
- :feature_category: :onboarding
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
-- :name: namespaces_onboarding_pipeline_created
- :worker_name: Namespaces::OnboardingPipelineCreatedWorker
- :feature_category: :onboarding
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
-- :name: namespaces_onboarding_progress
- :worker_name: Namespaces::OnboardingProgressWorker
- :feature_category: :onboarding
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :cpu
- :weight: 1
- :idempotent: true
- :tags: []
-- :name: namespaces_onboarding_user_added
- :worker_name: Namespaces::OnboardingUserAddedWorker
- :feature_category: :onboarding
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: namespaces_process_sync_events
:worker_name: Namespaces::ProcessSyncEventsWorker
:feature_category: :pods
@@ -2820,6 +2820,42 @@
:weight: 2
:idempotent: false
:tags: []
+- :name: onboarding_issue_created
+ :worker_name: Onboarding::IssueCreatedWorker
+ :feature_category: :onboarding
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: onboarding_pipeline_created
+ :worker_name: Onboarding::PipelineCreatedWorker
+ :feature_category: :onboarding
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: onboarding_progress
+ :worker_name: Onboarding::ProgressWorker
+ :feature_category: :onboarding
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: onboarding_user_added
+ :worker_name: Onboarding::UserAddedWorker
+ :feature_category: :onboarding
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: packages_composer_cache_update
:worker_name: Packages::Composer::CacheUpdateWorker
:feature_category: :package_registry
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index c7efc92b25e..d5eca86744e 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -22,10 +22,9 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
created_entities.find_each do |entity|
BulkImports::CreatePipelineTrackersService.new(entity).execute!
- BulkImports::ExportRequestWorker.perform_async(entity.id)
- BulkImports::EntityWorker.perform_async(entity.id)
-
entity.start!
+
+ BulkImports::ExportRequestWorker.perform_async(entity.id)
end
re_enqueue
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index f6b1c693fe4..ada3210624c 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -15,9 +15,11 @@ module BulkImports
if stage_running?(entity_id, current_stage)
logger.info(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
+ bulk_import_id: bulk_import_id(entity_id),
current_stage: current_stage,
- message: 'Stage running'
+ message: 'Stage running',
+ importer: 'gitlab_migration'
)
)
@@ -26,9 +28,11 @@ module BulkImports
logger.info(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
+ bulk_import_id: bulk_import_id(entity_id),
current_stage: current_stage,
- message: 'Stage starting'
+ message: 'Stage starting',
+ importer: 'gitlab_migration'
)
)
@@ -42,13 +46,17 @@ module BulkImports
rescue StandardError => e
logger.error(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
+ bulk_import_id: bulk_import_id(entity_id),
current_stage: current_stage,
- message: e.message
+ message: e.message,
+ importer: 'gitlab_migration'
)
)
- Gitlab::ErrorTracking.track_exception(e, entity_id: entity_id)
+ Gitlab::ErrorTracking.track_exception(
+ e, bulk_import_entity_id: entity_id, bulk_import_id: bulk_import_id(entity_id), importer: 'gitlab_migration'
+ )
end
private
@@ -63,6 +71,10 @@ module BulkImports
BulkImports::Tracker.next_pipeline_trackers_for(entity_id).update(status_event: 'enqueue')
end
+ def bulk_import_id(entity_id)
+ @bulk_import_id ||= Entity.find(entity_id).bulk_import_id
+ end
+
def logger
@logger ||= Gitlab::Import::Logger.build
end
diff --git a/app/workers/bulk_imports/export_request_worker.rb b/app/workers/bulk_imports/export_request_worker.rb
index 0d3e4f013dd..a57071ddcf1 100644
--- a/app/workers/bulk_imports/export_request_worker.rb
+++ b/app/workers/bulk_imports/export_request_worker.rb
@@ -13,45 +13,112 @@ module BulkImports
def perform(entity_id)
entity = BulkImports::Entity.find(entity_id)
+ entity.update!(source_xid: entity_source_xid(entity)) if entity.source_xid.nil?
+
request_export(entity)
+
+ BulkImports::EntityWorker.perform_async(entity_id)
rescue BulkImports::NetworkError => e
- log_export_failure(e, entity)
+ if e.retriable?(entity)
+ retry_request(e, entity)
+ else
+ log_export_failure(e, entity)
- entity.fail_op!
+ entity.fail_op!
+ end
end
private
def request_export(entity)
- http_client(entity.bulk_import.configuration).post(entity.export_relations_url_path)
+ http_client(entity).post(entity.export_relations_url_path)
end
- def http_client(configuration)
+ def http_client(entity)
@client ||= Clients::HTTP.new(
- url: configuration.url,
- token: configuration.access_token
+ url: entity.bulk_import.configuration.url,
+ token: entity.bulk_import.configuration.access_token
)
end
def log_export_failure(exception, entity)
- attributes = {
+ Gitlab::Import::Logger.error(
+ structured_payload(
+ log_attributes(exception, entity).merge(
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ message: "Request to export #{entity.source_type} failed",
+ importer: 'gitlab_migration'
+ )
+ )
+ )
+
+ BulkImports::Failure.create(log_attributes(exception, entity))
+ end
+
+ def log_attributes(exception, entity)
+ {
bulk_import_entity_id: entity.id,
pipeline_class: 'ExportRequestWorker',
exception_class: exception.class.to_s,
exception_message: exception.message.truncate(255),
correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id
}
+ end
+
+ def graphql_client(entity)
+ @graphql_client ||= BulkImports::Clients::Graphql.new(
+ url: entity.bulk_import.configuration.url,
+ token: entity.bulk_import.configuration.access_token
+ )
+ end
+
+ def entity_source_xid(entity)
+ query = entity_query(entity)
+ client = graphql_client(entity)
+
+ response = client.execute(
+ client.parse(query.to_s),
+ { full_path: entity.source_full_path }
+ ).original_hash
+
+ ::GlobalID.parse(response.dig(*query.data_path, 'id')).model_id
+ rescue StandardError => e
+ Gitlab::Import::Logger.error(
+ structured_payload(
+ log_attributes(e, entity).merge(
+ message: 'Failed to fetch source entity id',
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ importer: 'gitlab_migration'
+ )
+ )
+ )
+
+ nil
+ end
+
+ def entity_query(entity)
+ if entity.group?
+ BulkImports::Groups::Graphql::GetGroupQuery.new(context: nil)
+ else
+ BulkImports::Projects::Graphql::GetProjectQuery.new(context: nil)
+ end
+ end
+ def retry_request(exception, entity)
Gitlab::Import::Logger.error(
structured_payload(
- attributes.merge(
- bulk_import_id: entity.bulk_import.id,
- bulk_import_entity_type: entity.source_type
+ log_attributes(exception, entity).merge(
+ message: 'Retrying export request',
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ importer: 'gitlab_migration'
)
)
)
- BulkImports::Failure.create(attributes)
+ self.class.perform_in(2.seconds, entity.id)
end
end
end
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
index e171ec1e194..6d314774cff 100644
--- a/app/workers/bulk_imports/pipeline_worker.rb
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -19,8 +19,11 @@ module BulkImports
if pipeline_tracker.present?
logger.info(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
- pipeline_name: pipeline_tracker.pipeline_name
+ bulk_import_entity_id: pipeline_tracker.entity.id,
+ bulk_import_id: pipeline_tracker.entity.bulk_import_id,
+ pipeline_name: pipeline_tracker.pipeline_name,
+ message: 'Pipeline starting',
+ importer: 'gitlab_migration'
)
)
@@ -28,9 +31,11 @@ module BulkImports
else
logger.error(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
+ bulk_import_id: bulk_import_id(entity_id),
pipeline_tracker_id: pipeline_tracker_id,
- message: 'Unstarted pipeline not found'
+ message: 'Unstarted pipeline not found',
+ importer: 'gitlab_migration'
)
)
end
@@ -44,9 +49,10 @@ module BulkImports
attr_reader :pipeline_tracker
def run
- raise(Entity::FailedError, 'Failed entity status') if pipeline_tracker.entity.failed?
+ return skip_tracker if pipeline_tracker.entity.failed?
+
raise(Pipeline::ExpiredError, 'Pipeline timeout') if job_timeout?
- raise(Pipeline::FailedError, export_status.error) if export_failed?
+ raise(Pipeline::FailedError, "Export from source instance failed: #{export_status.error}") if export_failed?
return re_enqueue if export_empty? || export_started?
@@ -59,21 +65,29 @@ module BulkImports
fail_tracker(e)
end
+ def bulk_import_id(entity_id)
+ @bulk_import_id ||= Entity.find(entity_id).bulk_import_id
+ end
+
def fail_tracker(exception)
pipeline_tracker.update!(status_event: 'fail_op', jid: jid)
logger.error(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
+ bulk_import_id: pipeline_tracker.entity.bulk_import_id,
pipeline_name: pipeline_tracker.pipeline_name,
- message: exception.message
+ message: exception.message,
+ importer: 'gitlab_migration'
)
)
Gitlab::ErrorTracking.track_exception(
exception,
- entity_id: pipeline_tracker.entity.id,
- pipeline_name: pipeline_tracker.pipeline_name
+ bulk_import_entity_id: pipeline_tracker.entity.id,
+ bulk_import_id: pipeline_tracker.entity.bulk_import_id,
+ pipeline_name: pipeline_tracker.pipeline_name,
+ importer: 'gitlab_migration'
)
BulkImports::Failure.create(
@@ -138,9 +152,11 @@ module BulkImports
def retry_tracker(exception)
logger.error(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
+ bulk_import_id: pipeline_tracker.entity.bulk_import_id,
pipeline_name: pipeline_tracker.pipeline_name,
- message: "Retrying error: #{exception.message}"
+ message: "Retrying error: #{exception.message}",
+ importer: 'gitlab_migration'
)
)
@@ -148,5 +164,19 @@ module BulkImports
re_enqueue(exception.retry_delay)
end
+
+ def skip_tracker
+ logger.info(
+ structured_payload(
+ bulk_import_entity_id: pipeline_tracker.entity.id,
+ bulk_import_id: pipeline_tracker.entity.bulk_import_id,
+ pipeline_name: pipeline_tracker.pipeline_name,
+ message: 'Skipping pipeline due to failed entity',
+ importer: 'gitlab_migration'
+ )
+ )
+
+ pipeline_tracker.update!(status_event: 'skip', jid: jid)
+ end
end
end
diff --git a/app/workers/ci/cancel_pipeline_worker.rb b/app/workers/ci/cancel_pipeline_worker.rb
index 147839a0625..2735498b6bb 100644
--- a/app/workers/ci/cancel_pipeline_worker.rb
+++ b/app/workers/ci/cancel_pipeline_worker.rb
@@ -10,6 +10,7 @@ module Ci
idempotent!
deduplicate :until_executed
urgency :high
+ loggable_arguments 1
def perform(pipeline_id, auto_canceled_by_pipeline_id)
::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
diff --git a/app/workers/ci/parse_secure_file_metadata_worker.rb b/app/workers/ci/parse_secure_file_metadata_worker.rb
new file mode 100644
index 00000000000..0d2495d3155
--- /dev/null
+++ b/app/workers/ci/parse_secure_file_metadata_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Ci
+ class ParseSecureFileMetadataWorker
+ include ::ApplicationWorker
+
+ feature_category :mobile_signing_deployment
+ urgency :low
+ idempotent!
+
+ def perform(secure_file_id)
+ ::Ci::SecureFile.find_by_id(secure_file_id).try(&:update_metadata!)
+ end
+ end
+end
diff --git a/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb b/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
index 590514424bb..2a1f492cacb 100644
--- a/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
+++ b/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
@@ -13,7 +13,9 @@ module Ci
def perform(pipeline_id)
::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
- break unless pipeline.has_archive_artifacts?
+ # TODO: Move this check inside the Ci::UnlockArtifactsService
+ # once the feature flags in it have been removed.
+ break unless pipeline.has_erasable_artifacts?
results = ::Ci::UnlockArtifactsService
.new(pipeline.project, pipeline.user)
diff --git a/app/workers/clusters/applications/uninstall_worker.rb b/app/workers/clusters/applications/uninstall_worker.rb
index da290eaf1f6..b71f87014aa 100644
--- a/app/workers/clusters/applications/uninstall_worker.rb
+++ b/app/workers/clusters/applications/uninstall_worker.rb
@@ -14,11 +14,7 @@ module Clusters
worker_has_external_dependencies!
loggable_arguments 0
- def perform(app_name, app_id)
- find_application(app_name, app_id) do |app|
- Clusters::Applications::UninstallService.new(app).execute
- end
- end
+ def perform(app_name, app_id); end
end
end
end
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index c1fec4f0196..f51c2852da6 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -2,7 +2,7 @@
require 'sidekiq/api'
-Sidekiq::Worker.extend ActiveSupport::Concern
+Sidekiq::Worker.extend ActiveSupport::Concern # rubocop:disable Cop/SidekiqApiUsage
module ApplicationWorker
extend ActiveSupport::Concern
@@ -134,10 +134,6 @@ module ApplicationWorker
@log_bulk_perform_async = true
end
- def queue_size
- Sidekiq::Queue.new(queue).size
- end
-
def bulk_perform_async(args_list)
if log_bulk_perform_async?
Sidekiq.logger.info('class' => self.name, 'args_list' => args_list, 'args_list_count' => args_list.length, 'message' => 'Inserting multiple jobs')
@@ -177,7 +173,7 @@ module ApplicationWorker
end
in_safe_limit_batches(args_list, schedule_at) do |args_batch, schedule_at_for_batch|
- Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch, 'at' => schedule_at_for_batch)
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch, 'at' => schedule_at_for_batch) # rubocop:disable Cop/SidekiqApiUsage
end
end
@@ -185,7 +181,7 @@ module ApplicationWorker
def do_push_bulk(args_list)
in_safe_limit_batches(args_list) do |args_batch, _|
- Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch)
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch) # rubocop:disable Cop/SidekiqApiUsage
end
end
diff --git a/app/workers/concerns/gitlab/github_import/object_importer.rb b/app/workers/concerns/gitlab/github_import/object_importer.rb
index c2cd50d8c21..9793278ac0c 100644
--- a/app/workers/concerns/gitlab/github_import/object_importer.rb
+++ b/app/workers/concerns/gitlab/github_import/object_importer.rb
@@ -37,27 +37,22 @@ module Gitlab
importer_class.new(object, project, client).execute
- Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :imported)
+ if increment_object_counter?(object)
+ Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :imported)
+ end
info(project.id, message: 'importer finished')
rescue NoMethodError => e
# This exception will be more useful in development when a new
# Representation is created but the developer forgot to add a
# `:github_identifiers` field.
- Gitlab::Import::ImportFailureService.track(
- project_id: project.id,
- error_source: importer_class.name,
- exception: e,
- fail_import: true
- )
-
- raise(e)
+ track_and_raise_exception(project, e, fail_import: true)
rescue StandardError => e
- Gitlab::Import::ImportFailureService.track(
- project_id: project.id,
- error_source: importer_class.name,
- exception: e
- )
+ track_and_raise_exception(project, e)
+ end
+
+ def increment_object_counter?(_object)
+ true
end
def object_type
@@ -90,6 +85,17 @@ module Gitlab
github_identifiers: github_identifiers
)
end
+
+ def track_and_raise_exception(project, exception, fail_import: false)
+ Gitlab::Import::ImportFailureService.track(
+ project_id: project.id,
+ error_source: importer_class.name,
+ exception: exception,
+ fail_import: fail_import
+ )
+
+ raise(exception)
+ end
end
end
end
diff --git a/app/workers/concerns/gitlab/github_import/stage_methods.rb b/app/workers/concerns/gitlab/github_import/stage_methods.rb
index b12c2311ea8..1feaaf917b2 100644
--- a/app/workers/concerns/gitlab/github_import/stage_methods.rb
+++ b/app/workers/concerns/gitlab/github_import/stage_methods.rb
@@ -63,6 +63,10 @@ module Gitlab
import_stage: self.class.name
)
end
+
+ def import_settings(project)
+ Gitlab::GithubImport::Settings.new(project)
+ end
end
end
end
diff --git a/app/workers/experiments/record_conversion_event_worker.rb b/app/workers/experiments/record_conversion_event_worker.rb
deleted file mode 100644
index 6487f030628..00000000000
--- a/app/workers/experiments/record_conversion_event_worker.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Experiments
- class RecordConversionEventWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :users
- urgency :low
-
- idempotent!
-
- def perform(experiment, user_id)
- return unless Gitlab::Experimentation.active?(experiment)
-
- ::Experiment.record_conversion_event(experiment, user_id)
- end
- end
-end
diff --git a/app/workers/gitlab/github_import/attachments/import_issue_worker.rb b/app/workers/gitlab/github_import/attachments/import_issue_worker.rb
new file mode 100644
index 00000000000..1a9fa15b850
--- /dev/null
+++ b/app/workers/gitlab/github_import/attachments/import_issue_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Attachments
+ class ImportIssueWorker # rubocop:disable Scalability/IdempotentWorker
+ include ObjectImporter
+
+ def representation_class
+ Representation::NoteText
+ end
+
+ def importer_class
+ Importer::NoteAttachmentsImporter
+ end
+
+ def object_type
+ :issue_attachment
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/github_import/attachments/import_merge_request_worker.rb b/app/workers/gitlab/github_import/attachments/import_merge_request_worker.rb
new file mode 100644
index 00000000000..a86852b094f
--- /dev/null
+++ b/app/workers/gitlab/github_import/attachments/import_merge_request_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Attachments
+ class ImportMergeRequestWorker # rubocop:disable Scalability/IdempotentWorker
+ include ObjectImporter
+
+ def representation_class
+ Representation::NoteText
+ end
+
+ def importer_class
+ Importer::NoteAttachmentsImporter
+ end
+
+ def object_type
+ :merge_request_attachment
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/github_import/attachments/import_note_worker.rb b/app/workers/gitlab/github_import/attachments/import_note_worker.rb
new file mode 100644
index 00000000000..2f5bc50ee0b
--- /dev/null
+++ b/app/workers/gitlab/github_import/attachments/import_note_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Attachments
+ class ImportNoteWorker # rubocop:disable Scalability/IdempotentWorker
+ include ObjectImporter
+
+ def representation_class
+ Representation::NoteText
+ end
+
+ def importer_class
+ Importer::NoteAttachmentsImporter
+ end
+
+ def object_type
+ :note_attachment
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/github_import/attachments/import_release_worker.rb b/app/workers/gitlab/github_import/attachments/import_release_worker.rb
new file mode 100644
index 00000000000..5eea5702d3c
--- /dev/null
+++ b/app/workers/gitlab/github_import/attachments/import_release_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Attachments
+ class ImportReleaseWorker # rubocop:disable Scalability/IdempotentWorker
+ include ObjectImporter
+
+ def representation_class
+ Representation::NoteText
+ end
+
+ def importer_class
+ Importer::NoteAttachmentsImporter
+ end
+
+ def object_type
+ :release_attachment
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/github_import/import_issue_worker.rb b/app/workers/gitlab/github_import/import_issue_worker.rb
index 8fdc0219ffd..7d6a28f4a96 100644
--- a/app/workers/gitlab/github_import/import_issue_worker.rb
+++ b/app/workers/gitlab/github_import/import_issue_worker.rb
@@ -16,6 +16,10 @@ module Gitlab
def object_type
:issue
end
+
+ def increment_object_counter?(object)
+ !object.pull_request?
+ end
end
end
end
diff --git a/app/workers/gitlab/github_import/import_release_attachments_worker.rb b/app/workers/gitlab/github_import/import_release_attachments_worker.rb
index c6f45ec1d7c..bf901f2f7b8 100644
--- a/app/workers/gitlab/github_import/import_release_attachments_worker.rb
+++ b/app/workers/gitlab/github_import/import_release_attachments_worker.rb
@@ -1,16 +1,18 @@
# frozen_string_literal: true
+# TODO: remove in 16.X milestone
+# https://gitlab.com/gitlab-org/gitlab/-/issues/377059
module Gitlab
module GithubImport
class ImportReleaseAttachmentsWorker # rubocop:disable Scalability/IdempotentWorker
include ObjectImporter
def representation_class
- Representation::ReleaseAttachments
+ Representation::NoteText
end
def importer_class
- Importer::ReleaseAttachmentsImporter
+ Importer::NoteAttachmentsImporter
end
def object_type
diff --git a/app/workers/gitlab/github_import/stage/import_attachments_worker.rb b/app/workers/gitlab/github_import/stage/import_attachments_worker.rb
index e9086dca503..e4a413b4081 100644
--- a/app/workers/gitlab/github_import/stage/import_attachments_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_attachments_worker.rb
@@ -28,7 +28,12 @@ module Gitlab
# For future issue/mr/milestone/etc attachments importers
def importers
- [::Gitlab::GithubImport::Importer::ReleasesAttachmentsImporter]
+ [
+ ::Gitlab::GithubImport::Importer::Attachments::ReleasesImporter,
+ ::Gitlab::GithubImport::Importer::Attachments::NotesImporter,
+ ::Gitlab::GithubImport::Importer::Attachments::IssuesImporter,
+ ::Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporter
+ ]
end
def start_importer(project, importer, client)
@@ -50,7 +55,7 @@ module Gitlab
end
def feature_disabled?(project)
- Feature.disabled?(:github_importer_attachments_import, project.group, type: :ops)
+ import_settings(project).disabled?(:attachments_import)
end
end
end
diff --git a/app/workers/gitlab/github_import/stage/import_issue_events_worker.rb b/app/workers/gitlab/github_import/stage/import_issue_events_worker.rb
index 0ec0a1b58d2..54ed4c47e78 100644
--- a/app/workers/gitlab/github_import/stage/import_issue_events_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_issue_events_worker.rb
@@ -15,9 +15,9 @@ module Gitlab
# client - An instance of Gitlab::GithubImport::Client.
# project - An instance of Project.
def import(client, project)
- importer = importer_class(project)
- return skip_to_next_stage(project) if importer.nil?
+ return skip_to_next_stage(project) if import_settings(project).disabled?(:single_endpoint_issue_events_import)
+ importer = ::Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
info(project.id, message: "starting importer", importer: importer.name)
waiter = importer.new(project, client).execute
move_to_next_stage(project, { waiter.key => waiter.jobs_remaining })
@@ -25,16 +25,6 @@ module Gitlab
private
- def importer_class(project)
- if Feature.enabled?(:github_importer_single_endpoint_issue_events_import, project.group, type: :ops)
- ::Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
- elsif Feature.enabled?(:github_importer_issue_events_import, project.group, type: :ops)
- ::Gitlab::GithubImport::Importer::IssueEventsImporter
- else
- nil
- end
- end
-
def skip_to_next_stage(project)
info(project.id, message: "skipping importer", importer: "IssueEventsImporter")
move_to_next_stage(project)
diff --git a/app/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker.rb b/app/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker.rb
index 7922c1113c4..3d1a8437da2 100644
--- a/app/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker.rb
@@ -36,7 +36,7 @@ module Gitlab
private
def diff_notes_importer(project)
- if project.group.present? && Feature.enabled?(:github_importer_single_endpoint_notes_import, project.group, type: :ops)
+ if import_settings(project).enabled?(:single_endpoint_notes_import)
Importer::SingleEndpointDiffNotesImporter
else
Importer::DiffNotesImporter
diff --git a/app/workers/gitlab/github_import/stage/import_notes_worker.rb b/app/workers/gitlab/github_import/stage/import_notes_worker.rb
index b53e31ce40e..40ca12b130f 100644
--- a/app/workers/gitlab/github_import/stage/import_notes_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_notes_worker.rb
@@ -25,7 +25,7 @@ module Gitlab
end
def importers(project)
- if project.group.present? && Feature.enabled?(:github_importer_single_endpoint_notes_import, project.group, type: :ops)
+ if import_settings(project).enabled?(:single_endpoint_notes_import)
[
Importer::SingleEndpointMergeRequestNotesImporter,
Importer::SingleEndpointIssueNotesImporter
diff --git a/app/workers/gitlab/github_import/stage/import_repository_worker.rb b/app/workers/gitlab/github_import/stage/import_repository_worker.rb
index 3e914cc7590..8c1a2cd2677 100644
--- a/app/workers/gitlab/github_import/stage/import_repository_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_repository_worker.rb
@@ -26,6 +26,11 @@ module Gitlab
RefreshImportJidWorker.perform_in_the_future(project.id, jid)
info(project.id, message: "starting importer", importer: 'Importer::RepositoryImporter')
+
+ # If a user creates an issue while the import is in progress, this can lead to an import failure.
+ # The workaround is to allocate IIDs before starting the importer.
+ allocate_issues_internal_id!(project, client)
+
importer = Importer::RepositoryImporter.new(project, client)
importer.execute
@@ -56,6 +61,19 @@ module Gitlab
def abort_on_failure
true
end
+
+ private
+
+ def allocate_issues_internal_id!(project, client)
+ return if InternalId.exists?(project: project, usage: :issues) # rubocop: disable CodeReuse/ActiveRecord
+
+ options = { state: 'all', sort: 'number', direction: 'desc', per_page: '1' }
+ last_github_issue = client.each_object(:issues, project.import_source, options).first
+
+ return unless last_github_issue
+
+ Issue.track_project_iid!(project, last_github_issue[:number])
+ end
end
end
end
diff --git a/app/workers/incident_management/pager_duty/process_incident_worker.rb b/app/workers/incident_management/pager_duty/process_incident_worker.rb
index 933d8e12d25..181e336e6b0 100644
--- a/app/workers/incident_management/pager_duty/process_incident_worker.rb
+++ b/app/workers/incident_management/pager_duty/process_incident_worker.rb
@@ -38,7 +38,7 @@ module IncidentManagement
def log_error(result)
Gitlab::AppLogger.warn(
message: 'Cannot create issue for PagerDuty incident',
- issue_errors: result.message
+ issue_errors: result.errors.join(', ')
)
end
end
diff --git a/app/workers/incident_management/process_alert_worker_v2.rb b/app/workers/incident_management/process_alert_worker_v2.rb
index f3049560bcd..04c02d17704 100644
--- a/app/workers/incident_management/process_alert_worker_v2.rb
+++ b/app/workers/incident_management/process_alert_worker_v2.rb
@@ -37,13 +37,13 @@ module IncidentManagement
end
def log_warning(alert, result)
- issue_id = result.payload[:issue]&.id
+ issue_id = result[:issue]&.id
Gitlab::AppLogger.warn(
message: 'Cannot process an Incident',
issue_id: issue_id,
alert_id: alert.id,
- errors: result.message
+ errors: result.errors.join(', ')
)
end
end
diff --git a/app/workers/merge_requests/delete_source_branch_worker.rb b/app/workers/merge_requests/delete_source_branch_worker.rb
index 69bd3949e9d..66392c670b5 100644
--- a/app/workers/merge_requests/delete_source_branch_worker.rb
+++ b/app/workers/merge_requests/delete_source_branch_worker.rb
@@ -18,9 +18,13 @@ class MergeRequests::DeleteSourceBranchWorker
# Source branch changed while it's being removed
return if merge_request.source_branch_sha != source_branch_sha
- ::Branches::DeleteService.new(merge_request.source_project, user)
+ delete_service_result = ::Branches::DeleteService.new(merge_request.source_project, user)
.execute(merge_request.source_branch)
+ if Feature.enabled?(:track_delete_source_errors, merge_request.source_project)
+ delete_service_result.track_exception if delete_service_result&.error?
+ end
+
::MergeRequests::RetargetChainService.new(project: merge_request.source_project, current_user: user)
.execute(merge_request)
rescue ActiveRecord::RecordNotFound
diff --git a/app/workers/namespaces/onboarding_issue_created_worker.rb b/app/workers/namespaces/onboarding_issue_created_worker.rb
deleted file mode 100644
index 4f0cc71cd91..00000000000
--- a/app/workers/namespaces/onboarding_issue_created_worker.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Namespaces
- class OnboardingIssueCreatedWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :onboarding
- urgency :low
-
- deduplicate :until_executing
- idempotent!
-
- def perform(namespace_id)
- namespace = Namespace.find_by_id(namespace_id)
- return unless namespace
-
- Onboarding::ProgressService.new(namespace).execute(action: :issue_created)
- end
- end
-end
diff --git a/app/workers/namespaces/onboarding_pipeline_created_worker.rb b/app/workers/namespaces/onboarding_pipeline_created_worker.rb
deleted file mode 100644
index c3850880df0..00000000000
--- a/app/workers/namespaces/onboarding_pipeline_created_worker.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Namespaces
- class OnboardingPipelineCreatedWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :onboarding
- urgency :low
-
- deduplicate :until_executing
- idempotent!
-
- def perform(namespace_id)
- namespace = Namespace.find_by_id(namespace_id)
- return unless namespace
-
- Onboarding::ProgressService.new(namespace).execute(action: :pipeline_created)
- end
- end
-end
diff --git a/app/workers/namespaces/onboarding_progress_worker.rb b/app/workers/namespaces/onboarding_progress_worker.rb
deleted file mode 100644
index 49629428459..00000000000
--- a/app/workers/namespaces/onboarding_progress_worker.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Namespaces
- class OnboardingProgressWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :onboarding
- worker_resource_boundary :cpu
- urgency :low
-
- deduplicate :until_executed
- idempotent!
-
- def perform(namespace_id, action)
- namespace = Namespace.find_by_id(namespace_id)
- return unless namespace && action
-
- Onboarding::ProgressService.new(namespace).execute(action: action.to_sym)
- end
- end
-end
diff --git a/app/workers/namespaces/onboarding_user_added_worker.rb b/app/workers/namespaces/onboarding_user_added_worker.rb
deleted file mode 100644
index a1b349eedd3..00000000000
--- a/app/workers/namespaces/onboarding_user_added_worker.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Namespaces
- class OnboardingUserAddedWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :onboarding
- urgency :low
-
- idempotent!
-
- def perform(namespace_id)
- namespace = Namespace.find(namespace_id)
- Onboarding::ProgressService.new(namespace).execute(action: :user_added)
- end
- end
-end
diff --git a/app/workers/onboarding/issue_created_worker.rb b/app/workers/onboarding/issue_created_worker.rb
new file mode 100644
index 00000000000..ff39fefad81
--- /dev/null
+++ b/app/workers/onboarding/issue_created_worker.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Onboarding
+ class IssueCreatedWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ feature_category :onboarding
+ urgency :low
+
+ deduplicate :until_executing
+ idempotent!
+
+ def perform(namespace_id)
+ namespace = Namespace.find_by_id(namespace_id)
+ return unless namespace
+
+ Onboarding::ProgressService.new(namespace).execute(action: :issue_created)
+ end
+ end
+end
+
+# remove in %15.6 as per https://gitlab.com/gitlab-org/gitlab/-/issues/372432
+Namespaces::OnboardingIssueCreatedWorker = Onboarding::IssueCreatedWorker
diff --git a/app/workers/onboarding/pipeline_created_worker.rb b/app/workers/onboarding/pipeline_created_worker.rb
new file mode 100644
index 00000000000..6bd5863b0e0
--- /dev/null
+++ b/app/workers/onboarding/pipeline_created_worker.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Onboarding
+ class PipelineCreatedWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ feature_category :onboarding
+ urgency :low
+
+ deduplicate :until_executing
+ idempotent!
+
+ def perform(namespace_id)
+ namespace = Namespace.find_by_id(namespace_id)
+ return unless namespace
+
+ Onboarding::ProgressService.new(namespace).execute(action: :pipeline_created)
+ end
+ end
+end
+
+# remove in %15.6 as per https://gitlab.com/gitlab-org/gitlab/-/issues/372432
+Namespaces::OnboardingPipelineCreatedWorker = Onboarding::PipelineCreatedWorker
diff --git a/app/workers/onboarding/progress_worker.rb b/app/workers/onboarding/progress_worker.rb
new file mode 100644
index 00000000000..525934c4a7c
--- /dev/null
+++ b/app/workers/onboarding/progress_worker.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Onboarding
+ class ProgressWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ feature_category :onboarding
+ worker_resource_boundary :cpu
+ urgency :low
+
+ deduplicate :until_executed
+ idempotent!
+
+ def perform(namespace_id, action)
+ namespace = Namespace.find_by_id(namespace_id)
+ return unless namespace && action
+
+ Onboarding::ProgressService.new(namespace).execute(action: action.to_sym)
+ end
+ end
+end
+
+# remove in %15.6 as per https://gitlab.com/gitlab-org/gitlab/-/issues/372432
+Namespaces::OnboardingProgressWorker = Onboarding::ProgressWorker
diff --git a/app/workers/onboarding/user_added_worker.rb b/app/workers/onboarding/user_added_worker.rb
new file mode 100644
index 00000000000..38e9cd063ea
--- /dev/null
+++ b/app/workers/onboarding/user_added_worker.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Onboarding
+ class UserAddedWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ feature_category :onboarding
+ urgency :low
+
+ idempotent!
+
+ def perform(namespace_id)
+ namespace = Namespace.find(namespace_id)
+ Onboarding::ProgressService.new(namespace).execute(action: :user_added)
+ end
+ end
+end
+
+# remove in %15.6 as per https://gitlab.com/gitlab-org/gitlab/-/issues/372432
+Namespaces::OnboardingUserAddedWorker = Onboarding::UserAddedWorker
diff --git a/app/workers/process_commit_worker.rb b/app/workers/process_commit_worker.rb
index cd6ce6eb28b..708dd3433cb 100644
--- a/app/workers/process_commit_worker.rb
+++ b/app/workers/process_commit_worker.rb
@@ -51,23 +51,13 @@ class ProcessCommitWorker
end
def close_issues(project, user, author, commit, issues)
- if Feature.enabled?(:process_issue_closure_in_background, project)
- Issues::CloseWorker.bulk_perform_async_with_contexts(
- issues,
- arguments_proc: -> (issue) {
- [project.id, issue.id, issue.class.to_s, { closed_by: author.id, commit_hash: commit.to_hash }]
- },
- context_proc: -> (issue) { { project: project } }
- )
- else
- # We don't want to run permission related queries for every single issue,
- # therefore we use IssueCollection here and skip the authorization check in
- # Issues::CloseService#execute.
- IssueCollection.new(issues).updatable_by_user(user).each do |issue|
- Issues::CloseService.new(project: project, current_user: author)
- .close_issue(issue, closed_via: commit)
- end
- end
+ Issues::CloseWorker.bulk_perform_async_with_contexts(
+ issues,
+ arguments_proc: -> (issue) {
+ [project.id, issue.id, issue.class.to_s, { closed_by: author.id, commit_hash: commit.to_hash }]
+ },
+ context_proc: -> (issue) { { project: project } }
+ )
end
def issues_to_close(project, commit, user)
diff --git a/bin/diagnostic-reports-uploader b/bin/diagnostic-reports-uploader
new file mode 100755
index 00000000000..a19fe15dcb9
--- /dev/null
+++ b/bin/diagnostic-reports-uploader
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'fog/google'
+
+require_relative '../lib/gitlab/memory/reports_uploader'
+require_relative '../lib/gitlab/memory/upload_and_cleanup_reports'
+require_relative '../lib/gitlab/memory/diagnostic_reports_logger'
+
+# Fail fast if the necessary ENV vars are not set.
+reports_path = ENV["GITLAB_DIAGNOSTIC_REPORTS_PATH"].to_s
+raise 'GITLAB_DIAGNOSTIC_REPORTS_PATH dir is missing' unless Dir.exist?(reports_path)
+
+gcs_key = ENV["GITLAB_GCP_KEY_PATH"].to_s
+raise "GCS keyfile not found: #{gcs_key}" unless File.exist?(gcs_key)
+
+gcs_project = ENV["GITLAB_DIAGNOSTIC_REPORTS_PROJECT"].to_s
+raise 'GITLAB_DIAGNOSTIC_REPORTS_PROJECT is missing' unless gcs_project && !gcs_project.empty?
+
+gcs_bucket = ENV["GITLAB_DIAGNOSTIC_REPORTS_BUCKET"].to_s
+raise 'GITLAB_DIAGNOSTIC_REPORTS_BUCKET is missing' unless gcs_bucket && !gcs_bucket.empty?
+
+rails_root = File.expand_path("..", __dir__)
+log_file = File.expand_path('log/diagnostic_reports_json.log', rails_root)
+logger = Gitlab::Memory::DiagnosticReportsLogger.new(log_file)
+
+uploader = Gitlab::Memory::ReportsUploader.new(gcs_key: gcs_key, gcs_project: gcs_project, gcs_bucket: gcs_bucket,
+ logger: logger)
+Gitlab::Memory::UploadAndCleanupReports.new(uploader: uploader, reports_path: reports_path, logger: logger).call
diff --git a/bin/profile-url b/bin/profile-url
index 9e8585aabba..6047cb70b8d 100755
--- a/bin/profile-url
+++ b/bin/profile-url
@@ -8,15 +8,15 @@ opt_parser = OptionParser.new do |opt|
Profile a URL on this GitLab instance.
Usage:
- #{__FILE__} url --output=<profile-html> --sql=<sql-log> [--user=<user>] [--post=<post-data>]
+ #{__FILE__} url --output=<profile-dump> --sql=<sql-log> [--user=<user>] [--post=<post-data>]
Example:
- #{__FILE__} /dashboard/issues --output=dashboard-profile.html --sql=dashboard.log --user=root
+ #{__FILE__} /dashboard/issues --output=dashboard-profile.dump --sql=dashboard.log --user=root
DOCSTRING
opt.separator ''
opt.separator 'Options:'
- opt.on('-o', '--output=/tmp/profile.html', 'profile output filename') do |output|
+ opt.on('-o', '--output=/tmp/profile.dump', 'profile output filename') do |output|
options[:profile_output] = output
end
@@ -45,13 +45,9 @@ end
require File.expand_path('../config/environment', File.dirname(__FILE__))
-result = Gitlab::Profiler.profile(options[:url],
- logger: Logger.new(options[:sql_output]),
- post_data: options[:post_data],
- user: UserFinder.new(options[:username]).find_by_username,
- private_token: ENV['PRIVATE_TOKEN'])
-
-printer = RubyProf::CallStackPrinter.new(result)
-file = File.open(options[:profile_output], 'w')
-printer.print(file)
-file.close
+Gitlab::Profiler.profile(options[:url],
+ logger: Logger.new(options[:sql_output]),
+ post_data: options[:post_data],
+ user: UserFinder.new(options[:username]).find_by_username,
+ private_token: ENV['PRIVATE_TOKEN'],
+ profiler_options: { out: options[:profile_output] })
diff --git a/bin/rubocop-profile b/bin/rubocop-profile
new file mode 100755
index 00000000000..d1e31edbeed
--- /dev/null
+++ b/bin/rubocop-profile
@@ -0,0 +1,39 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+# Profile bundled RuboCop version.
+#
+# See https://github.com/rubocop/rubocop/blob/master/bin/rubocop-profile
+
+if ARGV.include?('-h') || ARGV.include?('--help')
+ puts "Usage: same as main `rubocop` command but gathers profiling info"
+ puts "Additional option: `--memory` to print memory usage"
+ exit(0)
+end
+with_mem = ARGV.delete('--memory')
+ARGV.unshift '--cache', 'false' unless ARGV.include?('--cache')
+
+require 'stackprof'
+if with_mem
+ require 'memory_profiler'
+ MemoryProfiler.start
+end
+StackProf.start
+start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+begin
+ require 'rubocop'
+
+ exit RuboCop::CLI.new.run
+ensure
+ delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
+ puts "Finished in #{delta.round(1)} seconds"
+ StackProf.stop
+ if with_mem
+ puts "Building memory report..."
+ report = MemoryProfiler.stop
+ end
+ Dir.mkdir('tmp') unless File.exist?('tmp')
+ StackProf.results('tmp/stackprof.dump')
+ report&.pretty_print(scale_bytes: true)
+ puts "StackProf written to `tmp/stackprof.dump`."
+end
diff --git a/config/application.rb b/config/application.rb
index 03c8eadc4b0..368036ce064 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -255,12 +255,17 @@ module Gitlab
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "page_bundles/_mixins_and_variables_and_functions.css"
config.assets.precompile << "page_bundles/admin/application_settings_metrics_and_profiling.css"
+ config.assets.precompile << "page_bundles/admin/geo_nodes.css"
+ config.assets.precompile << "page_bundles/admin/geo_replicable.css"
config.assets.precompile << "page_bundles/admin/jobs_index.css"
config.assets.precompile << "page_bundles/alert_management_details.css"
config.assets.precompile << "page_bundles/alert_management_settings.css"
+ config.assets.precompile << "page_bundles/billings.css"
config.assets.precompile << "page_bundles/boards.css"
config.assets.precompile << "page_bundles/build.css"
config.assets.precompile << "page_bundles/ci_status.css"
+ config.assets.precompile << "page_bundles/cluster_agents.css"
+ config.assets.precompile << "page_bundles/clusters.css"
config.assets.precompile << "page_bundles/cycle_analytics.css"
config.assets.precompile << "page_bundles/dashboard_projects.css"
config.assets.precompile << "page_bundles/dev_ops_reports.css"
@@ -269,10 +274,13 @@ module Gitlab
config.assets.precompile << "page_bundles/epics.css"
config.assets.precompile << "page_bundles/error_tracking_details.css"
config.assets.precompile << "page_bundles/error_tracking_index.css"
+ config.assets.precompile << "page_bundles/graph_charts.css"
config.assets.precompile << "page_bundles/group.css"
config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/import.css"
config.assets.precompile << "page_bundles/incident_management_list.css"
+ config.assets.precompile << "page_bundles/incidents.css"
+ config.assets.precompile << "page_bundles/issues_analytics.css"
config.assets.precompile << "page_bundles/issues_list.css"
config.assets.precompile << "page_bundles/issues_show.css"
config.assets.precompile << "page_bundles/jira_connect.css"
@@ -281,10 +289,12 @@ module Gitlab
config.assets.precompile << "page_bundles/marketing_popover.css"
config.assets.precompile << "page_bundles/members.css"
config.assets.precompile << "page_bundles/merge_conflicts.css"
+ config.assets.precompile << "page_bundles/merge_request_analytics.css"
config.assets.precompile << "page_bundles/merge_requests.css"
config.assets.precompile << "page_bundles/milestone.css"
config.assets.precompile << "page_bundles/new_namespace.css"
config.assets.precompile << "page_bundles/oncall_schedules.css"
+ config.assets.precompile << "page_bundles/operations.css"
config.assets.precompile << "page_bundles/escalation_policies.css"
config.assets.precompile << "page_bundles/pipeline.css"
config.assets.precompile << "page_bundles/pipeline_schedules.css"
@@ -296,6 +306,8 @@ module Gitlab
config.assets.precompile << "page_bundles/profiles/preferences.css"
config.assets.precompile << "page_bundles/project.css"
config.assets.precompile << "page_bundles/projects_edit.css"
+ config.assets.precompile << "page_bundles/prometheus.css"
+ config.assets.precompile << "page_bundles/releases.css"
config.assets.precompile << "page_bundles/reports.css"
config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/requirements.css"
@@ -306,11 +318,13 @@ module Gitlab
config.assets.precompile << "page_bundles/terminal.css"
config.assets.precompile << "page_bundles/terms.css"
config.assets.precompile << "page_bundles/todos.css"
+ config.assets.precompile << "page_bundles/tree.css"
config.assets.precompile << "page_bundles/wiki.css"
config.assets.precompile << "page_bundles/work_items.css"
config.assets.precompile << "page_bundles/xterm.css"
config.assets.precompile << "lazy_bundles/cropper.css"
config.assets.precompile << "lazy_bundles/select2.css"
+ config.assets.precompile << "lazy_bundles/gridstack.css"
config.assets.precompile << "performance_bar.css"
config.assets.precompile << "disable_animations.css"
config.assets.precompile << "test_environment.css"
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index b8689c1c461..c3d9179a160 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -362,3 +362,10 @@
:why: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79864#note_845406018
:versions: [2.0.1]
:when: 2022-02-24 10:44:26.669326000 Z
+- - :license
+ - gridstack
+ - MIT
+ - :who: Balasankar C
+ :why: https://github.com/gridstack/gridstack.js/blob/v7.0.0/LICENSE
+ :versions: []
+ :when: 2022-10-18 16:24:56.611523399 Z
diff --git a/config/esbuild.config.js b/config/esbuild.config.js
new file mode 100644
index 00000000000..e876436e864
--- /dev/null
+++ b/config/esbuild.config.js
@@ -0,0 +1,59 @@
+const browserslist = require('browserslist');
+const esbuild = require('esbuild');
+
+const ESBUILD_SUPPORTED_TARGETS = new Set([
+ 'chrome',
+ 'edge',
+ 'firefox',
+ 'hermes',
+ 'ie',
+ 'ios',
+ 'node',
+ 'opera',
+ 'rhino',
+ 'safari',
+]);
+
+const parseBrowserslist = (browserslistResult) => {
+ return browserslistResult.map((browsers) => {
+ const [family, version] = browsers.split(' ');
+ let normalizedVersion = version;
+
+ // browserslist can return a range: safari15.2-15.4
+ if (version.indexOf('-') >= -1) {
+ // we take the lowest version
+ [normalizedVersion] = version.split('-');
+ }
+
+ return {
+ family,
+ version: normalizedVersion,
+ };
+ });
+};
+
+const mapBrowserslistToESBuildTarget = (browsersList) => {
+ return parseBrowserslist(browsersList)
+ .filter(({ family, version }) => {
+ if (!ESBUILD_SUPPORTED_TARGETS.has(family)) {
+ console.warning('Unknown ESBuild target %s, version %s', family, version);
+ return false;
+ }
+
+ return true;
+ })
+ .map(({ family, version }) => {
+ return `${family}${version}`;
+ });
+};
+
+module.exports = {
+ target: mapBrowserslistToESBuildTarget(browserslist()),
+ supported: {
+ 'optional-chain': false,
+ 'nullish-coalescing': false,
+ 'class-static-field': false,
+ 'class-field': false,
+ },
+ implementation: esbuild,
+};
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index ca27ece9196..66aa6071502 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -10,6 +10,7 @@
- advanced_deployments
- advisory_database
- api_security
+- application_instrumentation
- application_performance
- attack_emulation
- audit_events
@@ -25,6 +26,7 @@
- code_quality
- code_review
- code_testing
+- commerce_integrations
- compliance_management
- container_registry
- container_scanning
@@ -38,6 +40,7 @@
- dedicated
- delivery
- dependency_firewall
+- dependency_management
- dependency_proxy
- dependency_scanning
- deployment_management
diff --git a/config/feature_flags/development/about_your_company_registration_flow.yml b/config/feature_flags/development/about_your_company_registration_flow.yml
deleted file mode 100644
index 63c1e42972a..00000000000
--- a/config/feature_flags/development/about_your_company_registration_flow.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: about_your_company_registration_flow
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83345
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355909
-milestone: '14.10'
-type: development
-group: group::acquisition
-default_enabled: false
diff --git a/config/feature_flags/development/add_timing_to_certain_cache_actions.yml b/config/feature_flags/development/add_timing_to_certain_cache_actions.yml
deleted file mode 100644
index c03e49dae8d..00000000000
--- a/config/feature_flags/development/add_timing_to_certain_cache_actions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: add_timing_to_certain_cache_actions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94966
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371657
-milestone: '15.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/admin_runners_bulk_delete.yml b/config/feature_flags/development/admin_runners_bulk_delete.yml
deleted file mode 100644
index ff285855e96..00000000000
--- a/config/feature_flags/development/admin_runners_bulk_delete.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: admin_runners_bulk_delete
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81894
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353981
-milestone: '14.9'
-type: development
-group: group::runner
-default_enabled: false
diff --git a/config/feature_flags/development/agent_authorization_include_descendants.yml b/config/feature_flags/development/agent_authorization_include_descendants.yml
new file mode 100644
index 00000000000..17d3a484395
--- /dev/null
+++ b/config/feature_flags/development/agent_authorization_include_descendants.yml
@@ -0,0 +1,8 @@
+---
+name: agent_authorization_include_descendants
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95774
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371310
+milestone: '15.5'
+type: development
+group: group::configure
+default_enabled: false
diff --git a/config/feature_flags/development/allow_non_blocking_member_refresh.yml b/config/feature_flags/development/allow_non_blocking_member_refresh.yml
deleted file mode 100644
index 44ab1c13e7e..00000000000
--- a/config/feature_flags/development/allow_non_blocking_member_refresh.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: allow_non_blocking_member_refresh
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83619
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357281
-milestone: '14.10'
-type: development
-group: group::authentication and authorization
-default_enabled: false
diff --git a/config/feature_flags/development/approval_rules_eligible_filter.yml b/config/feature_flags/development/approval_rules_eligible_filter.yml
new file mode 100644
index 00000000000..e8d925d08a7
--- /dev/null
+++ b/config/feature_flags/development/approval_rules_eligible_filter.yml
@@ -0,0 +1,8 @@
+---
+name: approval_rules_eligible_filter
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100192
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376331
+milestone: '15.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/audit_invalid_approver_rules.yml b/config/feature_flags/development/audit_invalid_approver_rules.yml
new file mode 100644
index 00000000000..eca5ffc25bb
--- /dev/null
+++ b/config/feature_flags/development/audit_invalid_approver_rules.yml
@@ -0,0 +1,8 @@
+---
+name: audit_invalid_approver_rules
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98636
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375060
+milestone: '15.5'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/block_emails_with_failures.yml b/config/feature_flags/development/block_emails_with_failures.yml
deleted file mode 100644
index c06d49346b3..00000000000
--- a/config/feature_flags/development/block_emails_with_failures.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: block_emails_with_failures
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96902
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373159
-milestone: '15.4'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/bypass_batch_pop_queueing_for_merge_trains.yml b/config/feature_flags/development/bypass_batch_pop_queueing_for_merge_trains.yml
deleted file mode 100644
index 4517bd5360e..00000000000
--- a/config/feature_flags/development/bypass_batch_pop_queueing_for_merge_trains.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: bypass_batch_pop_queueing_for_merge_trains
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96793
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372366
-milestone: '15.4'
-type: development
-group: group::scalability
-default_enabled: false
diff --git a/config/feature_flags/development/cache_issue_sums.yml b/config/feature_flags/development/cache_issue_sums.yml
deleted file mode 100644
index 7b8bfc44ce2..00000000000
--- a/config/feature_flags/development/cache_issue_sums.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cache_issue_sums
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95048
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365940
-milestone: '15.4'
-type: development
-group: group::product planning
-default_enabled: false
diff --git a/config/feature_flags/development/cascade_package_forwarding_settings.yml b/config/feature_flags/development/cascade_package_forwarding_settings.yml
new file mode 100644
index 00000000000..2b09c25d6f9
--- /dev/null
+++ b/config/feature_flags/development/cascade_package_forwarding_settings.yml
@@ -0,0 +1,8 @@
+---
+name: cascade_package_forwarding_settings
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99285
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375761
+milestone: '15.5'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/ci_inbound_job_token_scope.yml b/config/feature_flags/development/ci_inbound_job_token_scope.yml
new file mode 100644
index 00000000000..0a7a618531c
--- /dev/null
+++ b/config/feature_flags/development/ci_inbound_job_token_scope.yml
@@ -0,0 +1,8 @@
+---
+name: ci_inbound_job_token_scope
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99165
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376063
+milestone: '15.5'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_increase_includes_to_250.yml b/config/feature_flags/development/ci_increase_includes_to_250.yml
deleted file mode 100644
index b6291ab0cd3..00000000000
--- a/config/feature_flags/development/ci_increase_includes_to_250.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_increase_includes_to_250
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64934
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344449
-milestone: '15.2'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_job_artifacts_cdn.yml b/config/feature_flags/development/ci_job_artifacts_cdn.yml
new file mode 100644
index 00000000000..4a019312ee7
--- /dev/null
+++ b/config/feature_flags/development/ci_job_artifacts_cdn.yml
@@ -0,0 +1,8 @@
+---
+name: ci_job_artifacts_cdn
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98010
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373860
+milestone: '15.5'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_limit_active_jobs_early.yml b/config/feature_flags/development/ci_limit_active_jobs_early.yml
deleted file mode 100644
index b7dba0f81e9..00000000000
--- a/config/feature_flags/development/ci_limit_active_jobs_early.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_limit_active_jobs_early
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97700
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373284
-milestone: '15.4'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_limit_complete_hierarchy_size.yml b/config/feature_flags/development/ci_limit_complete_hierarchy_size.yml
index ad0dd85a25a..d6cc8787333 100644
--- a/config/feature_flags/development/ci_limit_complete_hierarchy_size.yml
+++ b/config/feature_flags/development/ci_limit_complete_hierarchy_size.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373719
milestone: '15.4'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_project_pipeline_config_refactoring.yml b/config/feature_flags/development/ci_project_pipeline_config_refactoring.yml
deleted file mode 100644
index 0338b81caf7..00000000000
--- a/config/feature_flags/development/ci_project_pipeline_config_refactoring.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_project_pipeline_config_refactoring
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97240
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372867
-milestone: '15.4'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_requeue_with_dag_object_hierarchy.yml b/config/feature_flags/development/ci_requeue_with_dag_object_hierarchy.yml
index 5e27510629c..b6f4974915b 100644
--- a/config/feature_flags/development/ci_requeue_with_dag_object_hierarchy.yml
+++ b/config/feature_flags/development/ci_requeue_with_dag_object_hierarchy.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373148
milestone: '15.4'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_rules_changes_compare.yml b/config/feature_flags/development/ci_rules_changes_compare.yml
deleted file mode 100644
index 094692def26..00000000000
--- a/config/feature_flags/development/ci_rules_changes_compare.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_rules_changes_compare
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90968
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366412
-milestone: '15.3'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_skip_auto_cancelation_on_child_pipelines.yml b/config/feature_flags/development/ci_skip_auto_cancelation_on_child_pipelines.yml
new file mode 100644
index 00000000000..71d5836bee1
--- /dev/null
+++ b/config/feature_flags/development/ci_skip_auto_cancelation_on_child_pipelines.yml
@@ -0,0 +1,8 @@
+---
+name: ci_skip_auto_cancelation_on_child_pipelines
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100854"
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377712
+milestone: '15.5'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml b/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml
deleted file mode 100644
index ffcd5352751..00000000000
--- a/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_update_unlocked_pipeline_artifacts
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97228
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372835
-milestone: '15.4'
-type: development
-group: group::pipeline insights
-default_enabled: false
diff --git a/config/feature_flags/development/ci_variables_refactoring_to_variable.yml b/config/feature_flags/development/ci_variables_refactoring_to_variable.yml
deleted file mode 100644
index 131df28d104..00000000000
--- a/config/feature_flags/development/ci_variables_refactoring_to_variable.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_variables_refactoring_to_variable
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95390
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371559
-milestone: '15.4'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/content_editor_on_issues.yml b/config/feature_flags/development/content_editor_on_issues.yml
new file mode 100644
index 00000000000..4527ea3b807
--- /dev/null
+++ b/config/feature_flags/development/content_editor_on_issues.yml
@@ -0,0 +1,8 @@
+---
+name: content_editor_on_issues
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98703
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375172
+milestone: '15.5'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/contribution_analytics_optimized_base_query.yml b/config/feature_flags/development/contribution_analytics_optimized_base_query.yml
deleted file mode 100644
index 05ee44a7ee2..00000000000
--- a/config/feature_flags/development/contribution_analytics_optimized_base_query.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: contribution_analytics_optimized_base_query
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91468
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367090
-milestone: '15.2'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/counter_attribute_db_lease_for_update.yml b/config/feature_flags/development/counter_attribute_db_lease_for_update.yml
new file mode 100644
index 00000000000..7c30bb3e913
--- /dev/null
+++ b/config/feature_flags/development/counter_attribute_db_lease_for_update.yml
@@ -0,0 +1,8 @@
+---
+name: counter_attribute_db_lease_for_update
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97912
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/374596
+milestone: '15.5'
+type: development
+group: group::pipeline insights
+default_enabled: false
diff --git a/config/feature_flags/development/disable_load_entire_blob_for_diff_viewer.yml b/config/feature_flags/development/disable_load_entire_blob_for_diff_viewer.yml
new file mode 100644
index 00000000000..5e767e3540b
--- /dev/null
+++ b/config/feature_flags/development/disable_load_entire_blob_for_diff_viewer.yml
@@ -0,0 +1,8 @@
+---
+name: disable_load_entire_blob_for_diff_viewer
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99029
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376330
+milestone: '15.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/enable_minor_delay_during_project_authorizations_refresh.yml b/config/feature_flags/development/enable_minor_delay_during_project_authorizations_refresh.yml
new file mode 100644
index 00000000000..cacc564df73
--- /dev/null
+++ b/config/feature_flags/development/enable_minor_delay_during_project_authorizations_refresh.yml
@@ -0,0 +1,8 @@
+---
+name: enable_minor_delay_during_project_authorizations_refresh
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97805
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373672
+milestone: '15.4'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/enforce_runner_token_expires_at.yml b/config/feature_flags/development/enforce_runner_token_expires_at.yml
deleted file mode 100644
index a1cb3bdcfdd..00000000000
--- a/config/feature_flags/development/enforce_runner_token_expires_at.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: enforce_runner_token_expires_at
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78557
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352008
-milestone: '14.8'
-type: development
-group: group::runner
-default_enabled: false
diff --git a/config/feature_flags/development/escape_gitaly_refs.yml b/config/feature_flags/development/escape_gitaly_refs.yml
deleted file mode 100644
index b42cc4c07e5..00000000000
--- a/config/feature_flags/development/escape_gitaly_refs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: escape_gitaly_refs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91058
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366437
-milestone: '15.2'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/extract_mr_diff_deletions.yml b/config/feature_flags/development/extract_mr_diff_deletions.yml
deleted file mode 100644
index 24067f95074..00000000000
--- a/config/feature_flags/development/extract_mr_diff_deletions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: extract_mr_diff_deletions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96455
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372060
-milestone: '15.4'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/forward_deployment_enabled.yml b/config/feature_flags/development/forward_deployment_enabled.yml
deleted file mode 100644
index 750fad15f15..00000000000
--- a/config/feature_flags/development/forward_deployment_enabled.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: forward_deployment_enabled
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24412
-rollout_issue_url:
-milestone: '12.8'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/geo_container_repository_replication.yml b/config/feature_flags/development/geo_container_repository_replication.yml
new file mode 100644
index 00000000000..94682cc63cc
--- /dev/null
+++ b/config/feature_flags/development/geo_container_repository_replication.yml
@@ -0,0 +1,8 @@
+---
+name: geo_container_repository_replication
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93690"
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366662
+milestone: '15.5'
+type: development
+group: group::geo
+default_enabled: true
diff --git a/config/feature_flags/development/gitlab_shell_jwt_token.yml b/config/feature_flags/development/gitlab_shell_jwt_token.yml
deleted file mode 100644
index 7cb6da2b49f..00000000000
--- a/config/feature_flags/development/gitlab_shell_jwt_token.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitlab_shell_jwt_token
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86148
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/360808
-milestone: '15.3'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/gl_avatar_for_all_user_avatars.yml b/config/feature_flags/development/gl_avatar_for_all_user_avatars.yml
deleted file mode 100644
index a3fee67a7f6..00000000000
--- a/config/feature_flags/development/gl_avatar_for_all_user_avatars.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gl_avatar_for_all_user_avatars
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81437
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353477
-milestone: '14.9'
-type: development
-group: group::foundations
-default_enabled: false
diff --git a/config/feature_flags/development/global_search_custom_slis.yml b/config/feature_flags/development/global_search_custom_slis.yml
deleted file mode 100644
index 6dd7cfb12f0..00000000000
--- a/config/feature_flags/development/global_search_custom_slis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: global_search_custom_slis
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95182
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372107
-milestone: '15.4'
-type: development
-group: group::application performance
-default_enabled: false
diff --git a/config/feature_flags/development/graphql_keyset_pagination_without_next_page_query.yml b/config/feature_flags/development/graphql_keyset_pagination_without_next_page_query.yml
index e289ad9af50..7b4c884a82f 100644
--- a/config/feature_flags/development/graphql_keyset_pagination_without_next_page_query.yml
+++ b/config/feature_flags/development/graphql_keyset_pagination_without_next_page_query.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373792
milestone: '15.4'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/group_analytics_dashboards_page.yml b/config/feature_flags/development/group_analytics_dashboards_page.yml
new file mode 100644
index 00000000000..8002ddb9204
--- /dev/null
+++ b/config/feature_flags/development/group_analytics_dashboards_page.yml
@@ -0,0 +1,8 @@
+---
+name: group_analytics_dashboards_page
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98767'
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375251
+milestone: '15.5'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/hash_oauth_tokens.yml b/config/feature_flags/development/hash_oauth_tokens.yml
index 43cd5672fc4..96bd4a3702e 100644
--- a/config/feature_flags/development/hash_oauth_tokens.yml
+++ b/config/feature_flags/development/hash_oauth_tokens.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367570
milestone: '15.3'
type: development
group: group::authentication and authorization
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/highlight_diffs_renewable_expiration.yml b/config/feature_flags/development/highlight_diffs_renewable_expiration.yml
deleted file mode 100644
index 80635b96240..00000000000
--- a/config/feature_flags/development/highlight_diffs_renewable_expiration.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: highlight_diffs_renewable_expiration
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95356
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370728
-milestone: '15.3'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/highlight_diffs_short_renewable_expiration.yml b/config/feature_flags/development/highlight_diffs_short_renewable_expiration.yml
deleted file mode 100644
index 1f20678b4a6..00000000000
--- a/config/feature_flags/development/highlight_diffs_short_renewable_expiration.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: highlight_diffs_short_renewable_expiration
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95356
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370728
-milestone: '15.3'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/import_export_web_upload_stream.yml b/config/feature_flags/development/import_export_web_upload_stream.yml
deleted file mode 100644
index 59e06fbec43..00000000000
--- a/config/feature_flags/development/import_export_web_upload_stream.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: import_export_web_upload_stream
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93379
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370127
-milestone: '15.3'
-type: development
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/development/improve_blobs_cache_headers.yml b/config/feature_flags/development/improve_blobs_cache_headers.yml
new file mode 100644
index 00000000000..33fb9669106
--- /dev/null
+++ b/config/feature_flags/development/improve_blobs_cache_headers.yml
@@ -0,0 +1,8 @@
+---
+name: improve_blobs_cache_headers
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98110
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/374126
+milestone: '15.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/incident_timeline.yml b/config/feature_flags/development/incident_timeline.yml
deleted file mode 100644
index 587ef8b55e8..00000000000
--- a/config/feature_flags/development/incident_timeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: incident_timeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80802
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353426
-milestone: '14.9'
-type: development
-group: group::respond
-default_enabled: true
diff --git a/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml b/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml
deleted file mode 100644
index f92a6b2b1b0..00000000000
--- a/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: include_groups_from_group_shares_in_group_transfer_locations
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96347
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371961
-milestone: '15.4'
-type: development
-group: group::workspace
-default_enabled: false
diff --git a/config/feature_flags/development/incubation_5mp_google_cloud.yml b/config/feature_flags/development/incubation_5mp_google_cloud.yml
index 1b3ba503f5d..e2118e65961 100644
--- a/config/feature_flags/development/incubation_5mp_google_cloud.yml
+++ b/config/feature_flags/development/incubation_5mp_google_cloud.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371332
milestone: '14.3'
type: development
group: group::incubation
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/indifferent_wal_location_keys.yml b/config/feature_flags/development/indifferent_wal_location_keys.yml
new file mode 100644
index 00000000000..2d89ad82085
--- /dev/null
+++ b/config/feature_flags/development/indifferent_wal_location_keys.yml
@@ -0,0 +1,8 @@
+---
+name: indifferent_wal_location_keys
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101096
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377989
+milestone: '15.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/integration_slack_app_notifications.yml b/config/feature_flags/development/integration_slack_app_notifications.yml
new file mode 100644
index 00000000000..d233194c6d4
--- /dev/null
+++ b/config/feature_flags/development/integration_slack_app_notifications.yml
@@ -0,0 +1,8 @@
+---
+name: integration_slack_app_notifications
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98663
+rollout_issue_url:
+milestone: '15.5'
+type: development
+group: group::integrations
+default_enabled: false
diff --git a/config/feature_flags/development/license_from_gitaly.yml b/config/feature_flags/development/license_from_gitaly.yml
new file mode 100644
index 00000000000..ad79d56a8ab
--- /dev/null
+++ b/config/feature_flags/development/license_from_gitaly.yml
@@ -0,0 +1,8 @@
+---
+name: license_from_gitaly
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77041
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/374300
+milestone: '15.5'
+type: development
+group: group::gitaly
+default_enabled: false
diff --git a/config/feature_flags/development/limit_assignees_per_issuable.yml b/config/feature_flags/development/limit_assignees_per_issuable.yml
new file mode 100644
index 00000000000..d950b8c2f09
--- /dev/null
+++ b/config/feature_flags/development/limit_assignees_per_issuable.yml
@@ -0,0 +1,8 @@
+---
+name: limit_assignees_per_issuable
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95673
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373237
+milestone: '15.5'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/mergeability_checks_logger.yml b/config/feature_flags/development/mergeability_checks_logger.yml
deleted file mode 100644
index 3476d6f2133..00000000000
--- a/config/feature_flags/development/mergeability_checks_logger.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: mergeability_checks_logger
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96128
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371717
-milestone: '15.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml b/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml
new file mode 100644
index 00000000000..b5fd39354ec
--- /dev/null
+++ b/config/feature_flags/development/only_allow_merge_if_all_status_checks_passed.yml
@@ -0,0 +1,8 @@
+---
+name: only_allow_merge_if_all_status_checks_passed
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96765"
+rollout_issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/372340"
+milestone: '15.5'
+type: development
+group: group::compliance
+default_enabled: false
diff --git a/config/feature_flags/development/operational_vulnerabilities_filters.yml b/config/feature_flags/development/operational_vulnerabilities_filters.yml
index 0a96954ef66..93206935a94 100644
--- a/config/feature_flags/development/operational_vulnerabilities_filters.yml
+++ b/config/feature_flags/development/operational_vulnerabilities_filters.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365986
milestone: '15.2'
type: development
group: group::container security
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml b/config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml
deleted file mode 100644
index 7e7789e2e8f..00000000000
--- a/config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: override_group_level_protected_environment_settings_permission
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92801
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369875
-milestone: '15.3'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/pages_lets_encrypt_ecdsa.yml b/config/feature_flags/development/pages_lets_encrypt_ecdsa.yml
deleted file mode 100644
index 866c2438e9f..00000000000
--- a/config/feature_flags/development/pages_lets_encrypt_ecdsa.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pages_lets_encrypt_ecdsa
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88125
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363026
-milestone: '15.1'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/pipeline_name.yml b/config/feature_flags/development/pipeline_name.yml
new file mode 100644
index 00000000000..40557a7d01e
--- /dev/null
+++ b/config/feature_flags/development/pipeline_name.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_name
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97502
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376095
+milestone: '15.5'
+type: development
+group: group::delivery
+default_enabled: false
diff --git a/config/feature_flags/development/pipeline_schedules_vue.yml b/config/feature_flags/development/pipeline_schedules_vue.yml
new file mode 100644
index 00000000000..69106660c35
--- /dev/null
+++ b/config/feature_flags/development/pipeline_schedules_vue.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_schedules_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99155
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375139
+milestone: '15.5'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/present_groups_select_all.yml b/config/feature_flags/development/present_groups_select_all.yml
new file mode 100644
index 00000000000..4d8ac160fa0
--- /dev/null
+++ b/config/feature_flags/development/present_groups_select_all.yml
@@ -0,0 +1,8 @@
+---
+name: present_groups_select_all
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93633
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370306
+milestone: '15.5'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/process_issue_closure_in_background.yml b/config/feature_flags/development/process_issue_closure_in_background.yml
deleted file mode 100644
index 6a97cbf888e..00000000000
--- a/config/feature_flags/development/process_issue_closure_in_background.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: process_issue_closure_in_background
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94981
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371024
-milestone: '15.4'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/read_package_policy_rule.yml b/config/feature_flags/development/read_package_policy_rule.yml
deleted file mode 100644
index 151c5a8c0b5..00000000000
--- a/config/feature_flags/development/read_package_policy_rule.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: read_package_policy_rule
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90963
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366711
-milestone: '15.4'
-type: development
-group: group::package
-default_enabled: false
diff --git a/config/feature_flags/development/realtime_labels.yml b/config/feature_flags/development/realtime_labels.yml
index 6072a4b044a..0c047a09a6d 100644
--- a/config/feature_flags/development/realtime_labels.yml
+++ b/config/feature_flags/development/realtime_labels.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357370
milestone: '14.10'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/refactor_mr_widgets_extensions.yml b/config/feature_flags/development/refactor_mr_widgets_extensions.yml
deleted file mode 100644
index 3f71e786f99..00000000000
--- a/config/feature_flags/development/refactor_mr_widgets_extensions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refactor_mr_widgets_extensions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70993
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341759
-milestone: '14.4'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml b/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml
deleted file mode 100644
index aa3c2799100..00000000000
--- a/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refactor_mr_widgets_extensions_user
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70993
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341759
-milestone: '14.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/remove_namespace_aggregator_delay.yml b/config/feature_flags/development/remove_namespace_aggregator_delay.yml
new file mode 100644
index 00000000000..e9e0268fb55
--- /dev/null
+++ b/config/feature_flags/development/remove_namespace_aggregator_delay.yml
@@ -0,0 +1,8 @@
+---
+name: remove_namespace_aggregator_delay
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99226
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375722
+milestone: '15.5'
+type: development
+group: group::utilization
+default_enabled: false
diff --git a/config/feature_flags/development/remove_user_attributes_groups.yml b/config/feature_flags/development/remove_user_attributes_groups.yml
deleted file mode 100644
index 069d83455f9..00000000000
--- a/config/feature_flags/development/remove_user_attributes_groups.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: remove_user_attributes_groups
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97520
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372047
-milestone: '15.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/remove_user_attributes_projects.yml b/config/feature_flags/development/remove_user_attributes_projects.yml
deleted file mode 100644
index fc1beb42a73..00000000000
--- a/config/feature_flags/development/remove_user_attributes_projects.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: remove_user_attributes_projects
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97520
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372047
-milestone: '15.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/runner_registration_control.yml b/config/feature_flags/development/runner_registration_control.yml
deleted file mode 100644
index 56c01bf36e5..00000000000
--- a/config/feature_flags/development/runner_registration_control.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: runner_registration_control
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61407
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336087
-milestone: '14.1'
-type: development
-group: group::runner
-default_enabled: false
diff --git a/config/feature_flags/development/scan_execution_rule_mode.yml b/config/feature_flags/development/scan_execution_rule_mode.yml
index 44c985d6814..6e3dd6acf92 100644
--- a/config/feature_flags/development/scan_execution_rule_mode.yml
+++ b/config/feature_flags/development/scan_execution_rule_mode.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359883
milestone: '15.2'
type: development
group: group::container security
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/search_page_vertical_nav.yml b/config/feature_flags/development/search_page_vertical_nav.yml
new file mode 100644
index 00000000000..58088cee802
--- /dev/null
+++ b/config/feature_flags/development/search_page_vertical_nav.yml
@@ -0,0 +1,8 @@
+---
+name: search_page_vertical_nav
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97784
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373613
+milestone: '15.5'
+type: development
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/development/secure_files_metadata_parsers.yml b/config/feature_flags/development/secure_files_metadata_parsers.yml
new file mode 100644
index 00000000000..2d6eed27f4b
--- /dev/null
+++ b/config/feature_flags/development/secure_files_metadata_parsers.yml
@@ -0,0 +1,8 @@
+---
+name: secure_files_metadata_parsers
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99046
+rollout_issue_url:
+milestone: '15.5'
+type: development
+group: group::incubation
+default_enabled: false
diff --git a/config/feature_flags/development/set_feature_flag_service.yml b/config/feature_flags/development/set_feature_flag_service.yml
new file mode 100644
index 00000000000..f25076177d6
--- /dev/null
+++ b/config/feature_flags/development/set_feature_flag_service.yml
@@ -0,0 +1,8 @@
+---
+name: set_feature_flag_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87028
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373176
+milestone: '15.4'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/skip_checking_namespace_in_query.yml b/config/feature_flags/development/skip_checking_namespace_in_query.yml
deleted file mode 100644
index 2b9e3cbfe0b..00000000000
--- a/config/feature_flags/development/skip_checking_namespace_in_query.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: skip_checking_namespace_in_query
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96559
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370742
-milestone: '15.4'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/skip_scheduling_mirrors_for_free.yml b/config/feature_flags/development/skip_scheduling_mirrors_for_free.yml
deleted file mode 100644
index 09f41fa9ff4..00000000000
--- a/config/feature_flags/development/skip_scheduling_mirrors_for_free.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: skip_scheduling_mirrors_for_free
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92377
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367712
-milestone: '15.2'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/track_delete_source_errors.yml b/config/feature_flags/development/track_delete_source_errors.yml
new file mode 100644
index 00000000000..57152ed86cd
--- /dev/null
+++ b/config/feature_flags/development/track_delete_source_errors.yml
@@ -0,0 +1,8 @@
+---
+name: track_delete_source_errors
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99028
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377258
+milestone: '15.5'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/trigger_mr_subscription_on_merge_status_change.yml b/config/feature_flags/development/trigger_mr_subscription_on_merge_status_change.yml
new file mode 100644
index 00000000000..058fde35110
--- /dev/null
+++ b/config/feature_flags/development/trigger_mr_subscription_on_merge_status_change.yml
@@ -0,0 +1,8 @@
+---
+name: trigger_mr_subscription_on_merge_status_change
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99213"
+rollout_issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/375704"
+milestone: '15.5'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_ci_i_testing_test_report_uploaded.yml b/config/feature_flags/development/usage_data_ci_i_testing_test_report_uploaded.yml
deleted file mode 100644
index 1635427485b..00000000000
--- a/config/feature_flags/development/usage_data_ci_i_testing_test_report_uploaded.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_ci_i_testing_test_report_uploaded
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95112
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339720
-milestone: '15.4'
-type: development
-group: group::pipeline insights
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml b/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
deleted file mode 100644
index 0019b949a98..00000000000
--- a/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_i_ci_secrets_management_vault_build_created
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46515
-rollout_issue_url:
-milestone: '13.6'
-type: development
-group: group::configure
-default_enabled: true
diff --git a/config/feature_flags/development/use_gitaly_pagination_for_refs.yml b/config/feature_flags/development/use_gitaly_pagination_for_refs.yml
deleted file mode 100644
index f44233e8d0b..00000000000
--- a/config/feature_flags/development/use_gitaly_pagination_for_refs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_gitaly_pagination_for_refs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96448
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372049
-milestone: '15.4'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/vue_broadcast_messages.yml b/config/feature_flags/development/vue_broadcast_messages.yml
new file mode 100644
index 00000000000..bc9425e93ba
--- /dev/null
+++ b/config/feature_flags/development/vue_broadcast_messages.yml
@@ -0,0 +1,8 @@
+---
+name: vue_broadcast_messages
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98127"
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368847
+milestone: '15.4'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/webhook_form_mask_url.yml b/config/feature_flags/development/webhook_form_mask_url.yml
new file mode 100644
index 00000000000..445fcb0b6b3
--- /dev/null
+++ b/config/feature_flags/development/webhook_form_mask_url.yml
@@ -0,0 +1,8 @@
+---
+name: webhook_form_mask_url
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99995
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/376106
+milestone: '15.5'
+type: development
+group: group::integrations
+default_enabled: false
diff --git a/config/feature_flags/development/wiki_find_page_with_normal_repository_rpcs.yml b/config/feature_flags/development/wiki_find_page_with_normal_repository_rpcs.yml
deleted file mode 100644
index bad0578d50a..00000000000
--- a/config/feature_flags/development/wiki_find_page_with_normal_repository_rpcs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: wiki_find_page_with_normal_repository_rpcs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95897
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371487
-milestone: '15.4'
-type: development
-group: group::gitaly
-default_enabled: false
diff --git a/config/feature_flags/ops/github_importer_attachments_import.yml b/config/feature_flags/ops/github_importer_attachments_import.yml
deleted file mode 100644
index ec4fe144933..00000000000
--- a/config/feature_flags/ops/github_importer_attachments_import.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_importer_attachments_import
-introduced_by_url:
-rollout_issue_url:
-milestone: '15.4'
-type: ops
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/ops/github_importer_issue_events_import.yml b/config/feature_flags/ops/github_importer_issue_events_import.yml
deleted file mode 100644
index 58660ceb287..00000000000
--- a/config/feature_flags/ops/github_importer_issue_events_import.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_importer_issue_events_import
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89134
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365977
-milestone: '15.3'
-type: ops
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml b/config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml
deleted file mode 100644
index 88e9db6721f..00000000000
--- a/config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_importer_single_endpoint_issue_events_import
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89134
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365977
-milestone: '15.3'
-type: ops
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/ops/github_importer_single_endpoint_notes_import.yml b/config/feature_flags/ops/github_importer_single_endpoint_notes_import.yml
deleted file mode 100644
index 7bbc6fba9e0..00000000000
--- a/config/feature_flags/ops/github_importer_single_endpoint_notes_import.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: github_importer_single_endpoint_notes_import
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67150
-rollout_issue_url:
-milestone: '14.2'
-type: ops
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/ops/increase_branch_cache_expiry.yml b/config/feature_flags/ops/increase_branch_cache_expiry.yml
deleted file mode 100644
index 61b9d5b9c42..00000000000
--- a/config/feature_flags/ops/increase_branch_cache_expiry.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: increase_branch_cache_expiry
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96739
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372331
-milestone: '15.4'
-type: ops
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/ops/jira_raise_timeouts.yml b/config/feature_flags/ops/jira_raise_timeouts.yml
index d1ab0ff0670..ac572b172fc 100644
--- a/config/feature_flags/ops/jira_raise_timeouts.yml
+++ b/config/feature_flags/ops/jira_raise_timeouts.yml
@@ -1,7 +1,7 @@
---
name: jira_raise_timeouts
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86439
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375587
milestone: '15.0'
type: ops
group: group::integrations
diff --git a/config/feature_flags/ops/sidekiq_memory_killer_read_only_mode.yml b/config/feature_flags/ops/sidekiq_memory_killer_read_only_mode.yml
new file mode 100644
index 00000000000..aa5cb754aff
--- /dev/null
+++ b/config/feature_flags/ops/sidekiq_memory_killer_read_only_mode.yml
@@ -0,0 +1,7 @@
+---
+name: sidekiq_memory_killer_read_only_mode
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98519
+milestone: '15.5'
+type: ops
+group: group::application performance
+default_enabled: false
diff --git a/config/feature_flags/undefined/gitaly_simplify_find_local_branches_response.yml b/config/feature_flags/undefined/gitaly_simplify_find_local_branches_response.yml
deleted file mode 100644
index c82f8ee26b7..00000000000
--- a/config/feature_flags/undefined/gitaly_simplify_find_local_branches_response.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitaly_simplify_find_local_branches_response
-introduced_by_url: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4850
-rollout_issue_url: https://gitlab.com/gitlab-org/gitaly/-/issues/4452
-milestone: '15.4'
-type: undefined
-group: group::gitaly
-default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index da950c54fbf..050d112843f 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -505,6 +505,11 @@ production: &base
# Periodically executed jobs, to self-heal GitLab, do external synchronizations, etc.
# Please read here for more information: https://github.com/ondrejbartas/sidekiq-cron#adding-cron-job
cron_jobs:
+ # Interval, in seconds, for each Sidekiq process to check for scheduled cron jobs that need to be enqueued. If set
+ # to 0, disable polling for cron jobs entirely. This is useful in setups with multiple Sidekiq processes if you want
+ # to limit which ones perform this task. Note that at least one process in your instance needs to have polling
+ # enabled for cron jobs to be executed.
+ poll_interval: 30
# Flag stuck CI jobs as failed
stuck_ci_jobs_worker:
cron: "0 * * * *"
diff --git a/config/gitlab_loose_foreign_keys.yml b/config/gitlab_loose_foreign_keys.yml
index c5c2d0a61b9..1530c681eb0 100644
--- a/config/gitlab_loose_foreign_keys.yml
+++ b/config/gitlab_loose_foreign_keys.yml
@@ -70,6 +70,10 @@ ci_pipeline_chat_data:
- table: chat_names
column: chat_name_id
on_delete: async_delete
+ci_pipeline_metadata:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
ci_pipeline_schedules:
- table: users
column: owner_id
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 3fc4b56f458..45307c3454b 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -183,6 +183,7 @@ Settings.gitlab['default_project_creation'] ||= ::Gitlab::Access::DEVELOPER_MAIN
Settings.gitlab['default_project_deletion_protection'] ||= false
Settings.gitlab['default_projects_limit'] ||= 100000
Settings.gitlab['default_branch_protection'] ||= 2
+# `default_can_create_group` is deprecated since GitLab 15.5 in favour of the `can_create_group` column on `ApplicationSetting`.
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
Settings.gitlab['default_theme'] = Gitlab::Themes::APPLICATION_DEFAULT if Settings.gitlab['default_theme'].nil?
Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost'
@@ -456,6 +457,7 @@ if Gitlab.ee? && Settings['ee_cron_jobs']
Settings.cron_jobs.merge!(Settings.ee_cron_jobs)
end
+Settings.cron_jobs['poll_interval'] ||= 30
Settings.cron_jobs['stuck_ci_jobs_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['stuck_ci_jobs_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['stuck_ci_jobs_worker']['job_class'] = 'StuckCiJobsWorker'
@@ -655,7 +657,7 @@ Settings.cron_jobs['ci_runner_versions_reconciliation_worker'] ||= Settingslogic
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['cron'] ||= '@daily'
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['job_class'] = 'Ci::Runners::ReconcileExistingRunnerVersionsCronWorker'
Settings.cron_jobs['users_migrate_records_to_ghost_user_in_batches_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['users_migrate_records_to_ghost_user_in_batches_worker']['cron'] ||= '*/1 * * * *'
+Settings.cron_jobs['users_migrate_records_to_ghost_user_in_batches_worker']['cron'] ||= '*/2 * * * *'
Settings.cron_jobs['users_migrate_records_to_ghost_user_in_batches_worker']['job_class'] = 'Users::MigrateRecordsToGhostUserInBatchesWorker'
Gitlab.ee do
@@ -779,9 +781,9 @@ Gitlab.ee do
Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker']['cron'] ||= '*/15 * * * *'
Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker']['job_class'] = 'Security::OrchestrationPolicyRuleScheduleWorker'
- Settings.cron_jobs['security_findings_cleanup_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['security_findings_cleanup_worker']['cron'] ||= '0 */4 * * 6,0'
- Settings.cron_jobs['security_findings_cleanup_worker']['job_class'] = 'Security::Findings::CleanupWorker'
+ Settings.cron_jobs['security_scans_purge_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['security_scans_purge_worker']['cron'] ||= '0 */4 * * 6,0'
+ Settings.cron_jobs['security_scans_purge_worker']['job_class'] = 'Security::Scans::PurgeWorker'
Settings.cron_jobs['app_sec_dast_profile_schedule_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['cron'] ||= '7-59/15 * * * *'
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['job_class'] = 'AppSec::Dast::ProfileScheduleWorker'
@@ -1045,6 +1047,7 @@ Settings.shutdown['blackout_seconds'] ||= 10
#
if Rails.env.test?
Settings.gitlab['default_projects_limit'] = 42
+ # `default_can_create_group` is deprecated since GitLab 15.5 in favour of the `can_create_group` column on `ApplicationSetting`.
Settings.gitlab['default_can_create_group'] = true
Settings.gitlab['default_can_create_team'] = false
end
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
index 1e2786db413..7773740fec4 100644
--- a/config/initializers/7_redis.rb
+++ b/config/initializers/7_redis.rb
@@ -4,12 +4,6 @@ require 'gitlab/redis'
Redis.raise_deprecations = true unless Rails.env.production?
-# We set the instance variable directly to suppress warnings.
-# We cannot switch to the new behavior until we change all existing `redis.exists` calls to `redis.exists?`.
-# Some gems also need to be updated
-# https://gitlab.com/gitlab-org/gitlab/-/issues/340602
-Redis.instance_variable_set(:@exists_returns_integer, false)
-
Redis::Client.prepend(Gitlab::Instrumentation::RedisInterceptor)
# Make sure we initialize a Redis connection pool before multi-threaded
diff --git a/config/initializers/attr_encrypted_no_db_connection.rb b/config/initializers/attr_encrypted_no_db_connection.rb
deleted file mode 100644
index d9e943bd249..00000000000
--- a/config/initializers/attr_encrypted_no_db_connection.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-raise 'This patch is only tested with attr_encrypted v3.1.0' unless AttrEncrypted::Version.string == '3.1.0'
-
-module AttrEncrypted
- module Adapters
- module ActiveRecord
- module GitlabMonkeyPatches
- # Prevent attr_encrypted from defining virtual accessors for encryption
- # data when the code and schema are out of sync. See this issue for more
- # details: https://github.com/attr-encrypted/attr_encrypted/issues/332
- def attribute_instance_methods_as_symbols_available?
- false
- end
-
- protected
-
- # The attr_encrypted gem is not actively maintained
- # At the same time it contains the code that raises kwargs deprecation warnings:
- # https://github.com/attr-encrypted/attr_encrypted/blob/master/lib/attr_encrypted/adapters/active_record.rb#L65
- #
- def attr_encrypted(*attrs)
- super
-
- attr = attrs.first
-
- redefine_method(:"#{attr}_changed?") do |**options|
- attribute_changed?(attr, **options)
- end
- end
- end
- end
- end
-end
-
-# As of v3.1.0, the attr_encrypted gem defines the AttrEncrypted and
-# AttrEncrypted::Adapters::ActiveRecord modules, and uses "extend" to mix them
-# into the ActiveRecord::Base class. This intervention overrides utility methods
-# defined by attr_encrypted to fix two bugs, as detailed above.
-#
-# The methods are used here: https://github.com/attr-encrypted/attr_encrypted/blob/3.1.0/lib/attr_encrypted.rb#L145-158
-ActiveSupport.on_load(:active_record) do
- extend AttrEncrypted::Adapters::ActiveRecord::GitlabMonkeyPatches
-end
diff --git a/config/initializers/attr_encrypted_thread_safe.rb b/config/initializers/attr_encrypted_thread_safe.rb
deleted file mode 100644
index be0bb56ffdc..00000000000
--- a/config/initializers/attr_encrypted_thread_safe.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-# As of v3.1.0, attr_encrypted is not thread-safe because all instances share the same `encrypted_attributes`
-# This was fixed in https://github.com/attr-encrypted/attr_encrypted/commit/d4ca0e2073ca6ba5035997ce25f7fc0b4bfbe39e
-# but no release was made after that so we have to patch it ourselves here
-
-module AttrEncrypted
- module InstanceMethods
- def encrypted_attributes
- @encrypted_attributes ||= begin
- duplicated = {}
- self.class.encrypted_attributes.map { |key, value| duplicated[key] = value.dup }
- duplicated
- end
- end
- end
-end
diff --git a/config/initializers/countries.rb b/config/initializers/countries.rb
index 9f8592ba641..52537b5d885 100644
--- a/config/initializers/countries.rb
+++ b/config/initializers/countries.rb
@@ -4,8 +4,9 @@ ISO3166.configure do |config|
config.locales = [:en]
end
-# GitLab permits users to sign up in Ukraine except the Crimean Region: https://about.gitlab.com/handbook/people-operations/code-of-conduct/#trade-compliance-exportimport-control
-# This overrides the display name for Ukraine to Ukraine (except Crimean Region)
+# GitLab permits users to sign up in Ukraine except for the regions: Crimea, Donetsk, and Luhansk: https://about.gitlab.com/handbook/people-operations/code-of-conduct/#trade-compliance-exportimport-control
+# This overrides the display name for Ukraine to 'Ukraine (except the Crimea, Donetsk, and Luhansk regions)'
+# See: https://gitlab.com/gitlab-org/gitlab/-/issues/374946
# To be removed after https://gitlab.com/gitlab-org/gitlab/issues/14784 is implemented
# Data fetched is based on https://github.com/hexorx/countries/blob/master/lib/countries/data/countries/UA.yaml
ISO3166::Data.register(
@@ -22,7 +23,7 @@ ISO3166::Data.register(
international_prefix: '810',
ioc: "UKR",
gec: "UP",
- name: "Ukraine (except Crimean Region)",
+ name: "Ukraine (except the Crimea, Donetsk, and Luhansk regions)",
national_destination_code_lengths: [2],
national_number_lengths: [8, 9],
national_prefix: '8',
diff --git a/config/initializers/diagnostic_reports.rb b/config/initializers/diagnostic_reports.rb
index b9932822a0b..47266f99f2d 100644
--- a/config/initializers/diagnostic_reports.rb
+++ b/config/initializers/diagnostic_reports.rb
@@ -2,9 +2,7 @@
return unless Gitlab::Utils.to_boolean(ENV['GITLAB_DIAGNOSTIC_REPORTS_ENABLED'])
-# Any actions beyond this check should only execute outside of tests,
-# when running in application context (i.e. not in the Rails console or rspec)
-return unless Gitlab::Runtime.application?
+return unless Gitlab::Runtime.puma?
Gitlab::Cluster::LifecycleEvents.on_worker_start do
Gitlab::Memory::ReportsDaemon.instance.start
diff --git a/config/initializers/licensee_license_patch.rb b/config/initializers/licensee_license_patch.rb
new file mode 100644
index 00000000000..d4680db5071
--- /dev/null
+++ b/config/initializers/licensee_license_patch.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'licensee/license'
+
+module Licensee
+ module LicensePatch
+ # Patch from https://github.com/licensee/licensee/pull/589
+ def ==(other)
+ other.is_a?(self.class) && key == other.key
+ end
+ end
+
+ License.prepend LicensePatch
+end
diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb
index bcc62a6be5d..aa621602573 100644
--- a/config/initializers/load_balancing.rb
+++ b/config/initializers/load_balancing.rb
@@ -2,6 +2,15 @@
Gitlab::Application.configure do |config|
config.middleware.use(Gitlab::Database::LoadBalancing::RackMiddleware)
+
+ # We need re-rerun the setup when code reloads in development
+ config.reloader.to_prepare do
+ if Gitlab.dev_or_test_env?
+ Gitlab::Database::LoadBalancing.base_models.each do |model|
+ Gitlab::Database::LoadBalancing::Setup.new(model).setup
+ end
+ end
+ end
end
Gitlab::Database::LoadBalancing.base_models.each do |model|
@@ -14,13 +23,6 @@ Gitlab::Database::LoadBalancing.base_models.each do |model|
# information.
Gitlab::Database::LoadBalancing::Setup.new(model).setup
- # We need re-rerun the setup when code reloads in development
- Rails.application.reloader.to_prepare do
- if Rails.env.development? || Rails.env.test?
- Gitlab::Database::LoadBalancing::Setup.new(model).setup
- end
- end
-
# Database queries may be run before we fork, so we must set up the load
# balancer as early as possible. When we do fork, we need to make sure all the
# hosts are disconnected.
diff --git a/config/initializers/memory_watchdog.rb b/config/initializers/memory_watchdog.rb
index 82ad615ce25..ce8e5029e7a 100644
--- a/config/initializers/memory_watchdog.rb
+++ b/config/initializers/memory_watchdog.rb
@@ -4,17 +4,33 @@ return unless Gitlab::Runtime.application?
return unless Gitlab::Utils.to_boolean(ENV['GITLAB_MEMORY_WATCHDOG_ENABLED'])
Gitlab::Cluster::LifecycleEvents.on_worker_start do
- handler =
- if Gitlab::Runtime.puma?
- Gitlab::Memory::Watchdog::PumaHandler.new
- elsif Gitlab::Runtime.sidekiq?
- Gitlab::Memory::Watchdog::TermProcessHandler.new
- else
- Gitlab::Memory::Watchdog::NullHandler.instance
- end
+ watchdog = Gitlab::Memory::Watchdog.new
+ max_strikes = ENV.fetch('GITLAB_MEMWD_MAX_STRIKES', 5).to_i
+ sleep_time_seconds = ENV.fetch('GITLAB_MEMWD_SLEEP_TIME_SEC', 60).to_i
+ max_mem_growth = ENV.fetch('GITLAB_MEMWD_MAX_MEM_GROWTH', 3.0).to_f
+ max_heap_frag = ENV.fetch('GITLAB_MEMWD_MAX_HEAP_FRAG', 0.5).to_f
+
+ watchdog.configure do |config|
+ config.handler =
+ if Gitlab::Runtime.puma?
+ Gitlab::Memory::Watchdog::PumaHandler.new
+ elsif Gitlab::Runtime.sidekiq?
+ Gitlab::Memory::Watchdog::TermProcessHandler.new
+ else
+ Gitlab::Memory::Watchdog::NullHandler.instance
+ end
+
+ config.logger = Gitlab::AppLogger
+ config.sleep_time_seconds = sleep_time_seconds
+ # config.monitor.use MonitorClass, args*, max_strikes:, kwargs**, &block
+ config.monitors.use Gitlab::Memory::Watchdog::Monitor::HeapFragmentation,
+ max_heap_fragmentation: max_heap_frag,
+ max_strikes: max_strikes
+
+ config.monitors.use Gitlab::Memory::Watchdog::Monitor::UniqueMemoryGrowth,
+ max_mem_growth: max_mem_growth,
+ max_strikes: max_strikes
+ end
- watchdog = Gitlab::Memory::Watchdog.new(
- handler: handler, logger: Gitlab::AppLogger
- )
Gitlab::BackgroundTask.new(watchdog).start
end
diff --git a/config/initializers/multi_json.rb b/config/initializers/multi_json.rb
index 5f98ce1961f..f382e2cb995 100644
--- a/config/initializers/multi_json.rb
+++ b/config/initializers/multi_json.rb
@@ -1,5 +1,10 @@
# frozen_string_literal: true
# Explicitly set the JSON adapter used by MultiJson
-# Currently we want this to default to the existing json gem
+#
+# This changes the default JSON adapter used by any gem dependencies
+# we have that rely on MultiJson for their JSON handling. We set this
+# to `oj` for a universal performance improvement in JSON handling
+# across those gems.
+
MultiJson.use(:oj)
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 2454b5ea818..707e4efe7bf 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -11,23 +11,12 @@ if Gitlab::Auth::Ldap::Config.enabled?
end
end
-module OmniAuth
- module Strategies
- class AzureActivedirectoryV2
- # override until https://github.com/RIPAGlobal/omniauth-azure-activedirectory-v2/pull/6 is merged
- def callback_url
- full_host + callback_path
- end
- end
- end
-end
-
OmniAuth.config.full_host = Gitlab::OmniauthInitializer.full_host
OmniAuth.config.allowed_request_methods = [:post]
# In case of auto sign-in, the GET method is used (users don't get to click on a button)
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
-OmniAuth.config.before_request_phase do |env|
+OmniAuth.config.request_validation_phase do |env|
Gitlab::RequestForgeryProtection.call(env)
end
diff --git a/config/initializers/sawyer_patch.rb b/config/initializers/sawyer_patch.rb
index 08d249645cc..34d2843d165 100644
--- a/config/initializers/sawyer_patch.rb
+++ b/config/initializers/sawyer_patch.rb
@@ -24,6 +24,16 @@ module SawyerClassPatch
end
else
define_method attribute do
+ Gitlab::Import::Logger.warn(
+ Gitlab::ApplicationContext.current.merge(
+ {
+ message: 'Sawyer attribute called',
+ attribute: attribute,
+ caller: Gitlab::BacktraceCleaner.clean_backtrace(caller)
+ }
+ )
+ )
+
@attrs[attribute.to_sym]
end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 262ef1dea21..cef34425bf4 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -5,6 +5,16 @@ module SidekiqLogArguments
end
end
+def load_cron_jobs!
+ Sidekiq::Cron::Job.load_from_hash! Gitlab::SidekiqConfig.cron_jobs
+
+ Gitlab.ee do
+ Gitlab::Mirror.configure_cron_job!
+
+ Gitlab::Geo.configure_cron_jobs!
+ end
+end
+
def enable_reliable_fetch?
return true unless Feature::FlipperFeature.table_exists?
@@ -23,8 +33,6 @@ queues_config_hash[:namespace] = Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE
enable_json_logs = Gitlab.config.sidekiq.log_format == 'json'
enable_sidekiq_memory_killer = ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'].to_i.nonzero?
-use_sidekiq_daemon_memory_killer = ENV.fetch("SIDEKIQ_DAEMON_MEMORY_KILLER", 1).to_i.nonzero?
-use_sidekiq_legacy_memory_killer = !use_sidekiq_daemon_memory_killer
Sidekiq.configure_server do |config|
config.options[:strict] = false
@@ -45,8 +53,7 @@ Sidekiq.configure_server do |config|
config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator(
metrics: Settings.monitoring.sidekiq_exporter,
- arguments_logger: SidekiqLogArguments.enabled? && !enable_json_logs,
- memory_killer: enable_sidekiq_memory_killer && use_sidekiq_legacy_memory_killer
+ arguments_logger: SidekiqLogArguments.enabled? && !enable_json_logs
))
config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)
@@ -62,7 +69,7 @@ Sidekiq.configure_server do |config|
# To cancel job, it requires `SIDEKIQ_MONITOR_WORKER=1` to enable notification channel
Gitlab::SidekiqDaemon::Monitor.instance.start
- Gitlab::SidekiqDaemon::MemoryKiller.instance.start if enable_sidekiq_memory_killer && use_sidekiq_daemon_memory_killer
+ Gitlab::SidekiqDaemon::MemoryKiller.instance.start if enable_sidekiq_memory_killer
first_sidekiq_worker = !ENV['SIDEKIQ_WORKER_ID'] || ENV['SIDEKIQ_WORKER_ID'] == '0'
health_checks = Settings.monitoring.sidekiq_health_checks
@@ -81,30 +88,10 @@ Sidekiq.configure_server do |config|
Sidekiq::ReliableFetch.setup_reliable_fetch!(config)
end
- Gitlab.config.load_dynamic_cron_schedules!
-
- # Sidekiq-cron: load recurring jobs from gitlab.yml
- # UGLY Hack to get nested hash from settingslogic
- cron_jobs = Gitlab::Json.parse(Gitlab.config.cron_jobs.to_json)
- # UGLY hack: Settingslogic doesn't allow 'class' key
- cron_jobs_required_keys = %w(job_class cron)
- cron_jobs.each do |k, v|
- if cron_jobs[k] && cron_jobs_required_keys.all? { |s| cron_jobs[k].key?(s) }
- cron_jobs[k]['class'] = cron_jobs[k].delete('job_class')
- else
- cron_jobs.delete(k)
- Gitlab::AppLogger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
- end
- end
- Sidekiq::Cron::Job.load_from_hash! cron_jobs
-
Gitlab::SidekiqVersioning.install!
- Gitlab.ee do
- Gitlab::Mirror.configure_cron_job!
-
- Gitlab::Geo.configure_cron_jobs!
- end
+ config.options[:cron_poll_interval] = Gitlab.config.cron_jobs.poll_interval
+ load_cron_jobs!
# Avoid autoload issue such as 'Mail::Parsers::AddressStruct'
# https://github.com/mikel/mail/issues/912#issuecomment-214850355
@@ -127,4 +114,3 @@ end
Sidekiq::Scheduled::Poller.prepend Gitlab::Patch::SidekiqPoller
Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqPoller
-Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index 81e4f73e6b2..0b3b5af48a1 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -98,17 +98,17 @@ en:
Grants read-only access to the user's primary email address using OpenID Connect.
project_access_token_scope_desc:
api:
- Grants complete read/write access to the scoped project API.
+ Grants complete read and write access to the scoped project API, including the Package Registry.
read_api:
- Grants read access to the scoped project API.
+ Grants read access to the scoped project API, including the Package Registry.
read_repository:
- Allows read-only access (pull) to the repository.
+ Grants read access (pull) to the repository.
write_repository:
- Allows read-write access (pull, push) to the repository.
+ Grants read and write access (pull and push) to the repository.
read_registry:
- Allows read-access (pull) to container registry images if the project is private and authorization is required.
+ Grants read access (pull) to the Container Registry images if a project is private and authorization is required.
write_registry:
- Allows write-access (push) to container registry.
+ Grants write access (push) to the Container Registry.
flash:
applications:
create:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 56df8f93113..3c33cdac3f1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -5,6 +5,8 @@ en:
hello: "Hello world"
activerecord:
attributes:
+ incident_management/timeline_event:
+ note: 'Timeline text'
issue_link:
source: Source issue
target: Target issue
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
deleted file mode 100644
index e58707b20a5..00000000000
--- a/config/metrics/aggregates/code_review.yml
+++ /dev/null
@@ -1,246 +0,0 @@
-# NOTE: Please read the following to check if and which aggregate the metric should be added to.
-#
-# code_review_extension_category_monthly_active_users
-# This is only metrics related to the VS Code Extension for now.
-#
-# code_review_category_monthly_active_users
-# This is the user based metrics. These should only be user based metrics and only be related to the Code Review things inside of GitLab.
-#
-# code_review_group_monthly_active_users
-# This is an aggregation of both of the above aggregations. It's intended to represent all users who interact with our group across all of our categories.
----
-- name: code_review_group_monthly_active_users
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'i_code_review_user_single_file_diffs'
- - 'i_code_review_user_create_mr'
- - 'i_code_review_user_close_mr'
- - 'i_code_review_user_reopen_mr'
- - 'i_code_review_user_resolve_thread'
- - 'i_code_review_user_unresolve_thread'
- - 'i_code_review_edit_mr_title'
- - 'i_code_review_edit_mr_desc'
- - 'i_code_review_user_merge_mr'
- - 'i_code_review_user_create_mr_comment'
- - 'i_code_review_user_edit_mr_comment'
- - 'i_code_review_user_remove_mr_comment'
- - 'i_code_review_user_create_review_note'
- - 'i_code_review_user_publish_review'
- - 'i_code_review_user_create_multiline_mr_comment'
- - 'i_code_review_user_edit_multiline_mr_comment'
- - 'i_code_review_user_remove_multiline_mr_comment'
- - 'i_code_review_user_add_suggestion'
- - 'i_code_review_user_apply_suggestion'
- - 'i_code_review_user_assigned'
- - 'i_code_review_user_review_requested'
- - 'i_code_review_user_approve_mr'
- - 'i_code_review_user_unapprove_mr'
- - 'i_code_review_user_marked_as_draft'
- - 'i_code_review_user_unmarked_as_draft'
- - 'i_code_review_user_approval_rule_added'
- - 'i_code_review_user_approval_rule_deleted'
- - 'i_code_review_user_approval_rule_edited'
- - 'i_code_review_user_vs_code_api_request'
- - 'i_code_review_user_toggled_task_item_status'
- - 'i_code_review_user_create_mr_from_issue'
- - 'i_code_review_user_mr_discussion_locked'
- - 'i_code_review_user_mr_discussion_unlocked'
- - 'i_code_review_user_time_estimate_changed'
- - 'i_code_review_user_time_spent_changed'
- - 'i_code_review_user_assignees_changed'
- - 'i_code_review_user_reviewers_changed'
- - 'i_code_review_user_milestone_changed'
- - 'i_code_review_user_labels_changed'
- - 'i_code_review_click_diff_view_setting'
- - 'i_code_review_click_single_file_mode_setting'
- - 'i_code_review_click_file_browser_setting'
- - 'i_code_review_click_whitespace_setting'
- - 'i_code_review_diff_view_inline'
- - 'i_code_review_diff_view_parallel'
- - 'i_code_review_file_browser_tree_view'
- - 'i_code_review_file_browser_list_view'
- - 'i_code_review_diff_show_whitespace'
- - 'i_code_review_diff_hide_whitespace'
- - 'i_code_review_diff_single_file'
- - 'i_code_review_diff_multiple_files'
- - 'i_code_review_user_load_conflict_ui'
- - 'i_code_review_user_resolve_conflict'
- - 'i_code_review_user_searches_diff'
- - 'i_code_review_user_resolve_thread_in_issue'
- - 'i_code_review_widget_nothing_merge_click_new_file'
- - 'i_code_review_post_merge_delete_branch'
- - 'i_code_review_post_merge_click_revert'
- - 'i_code_review_post_merge_click_cherry_pick'
- - 'i_code_review_post_merge_submit_revert_modal'
- - 'i_code_review_post_merge_submit_cherry_pick_modal'
- - 'i_code_review_user_jetbrains_api_request'
- - 'i_code_review_user_gitlab_cli_api_request'
- - 'i_code_review_user_create_note_in_ipynb_diff'
- - 'i_code_review_user_create_note_in_ipynb_diff_mr'
- - 'i_code_review_user_create_note_in_ipynb_diff_commit'
- - 'i_code_review_merge_request_widget_test_summary_view'
- - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
- - 'i_code_review_merge_request_widget_test_summary_expand'
- - 'i_code_review_merge_request_widget_test_summary_expand_success'
- - 'i_code_review_merge_request_widget_test_summary_expand_warning'
- - 'i_code_review_merge_request_widget_test_summary_expand_failed'
- - 'i_code_review_merge_request_widget_accessibility_view'
- - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
- - 'i_code_review_merge_request_widget_accessibility_expand'
- - 'i_code_review_merge_request_widget_accessibility_expand_success'
- - 'i_code_review_merge_request_widget_accessibility_expand_warning'
- - 'i_code_review_merge_request_widget_accessibility_expand_failed'
- - 'i_code_review_merge_request_widget_code_quality_view'
- - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
- - 'i_code_review_merge_request_widget_code_quality_expand'
- - 'i_code_review_merge_request_widget_code_quality_expand_success'
- - 'i_code_review_merge_request_widget_code_quality_expand_warning'
- - 'i_code_review_merge_request_widget_code_quality_expand_failed'
- - 'i_code_review_merge_request_widget_terraform_view'
- - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
- - 'i_code_review_merge_request_widget_terraform_expand'
- - 'i_code_review_merge_request_widget_terraform_expand_success'
- - 'i_code_review_merge_request_widget_terraform_expand_warning'
- - 'i_code_review_merge_request_widget_terraform_expand_failed'
- - 'i_code_review_merge_request_widget_metrics_view'
- - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
- - 'i_code_review_merge_request_widget_metrics_expand'
- - 'i_code_review_merge_request_widget_metrics_expand_success'
- - 'i_code_review_merge_request_widget_metrics_expand_warning'
- - 'i_code_review_merge_request_widget_metrics_expand_failed'
- - 'i_code_review_merge_request_widget_status_checks_view'
- - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
- - 'i_code_review_merge_request_widget_status_checks_expand'
- - 'i_code_review_merge_request_widget_status_checks_expand_success'
- - 'i_code_review_merge_request_widget_status_checks_expand_warning'
- - 'i_code_review_merge_request_widget_status_checks_expand_failed'
- - 'i_code_review_submit_review_approve'
- - 'i_code_review_submit_review_comment'
- - 'i_code_review_merge_request_widget_license_compliance_view'
- - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
- - 'i_code_review_merge_request_widget_license_compliance_expand'
- - 'i_code_review_merge_request_widget_license_compliance_expand_success'
- - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
-- name: code_review_category_monthly_active_users
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'i_code_review_user_single_file_diffs'
- - 'i_code_review_user_create_mr'
- - 'i_code_review_user_close_mr'
- - 'i_code_review_user_reopen_mr'
- - 'i_code_review_user_resolve_thread'
- - 'i_code_review_user_unresolve_thread'
- - 'i_code_review_edit_mr_title'
- - 'i_code_review_edit_mr_desc'
- - 'i_code_review_user_merge_mr'
- - 'i_code_review_user_create_mr_comment'
- - 'i_code_review_user_edit_mr_comment'
- - 'i_code_review_user_remove_mr_comment'
- - 'i_code_review_user_create_review_note'
- - 'i_code_review_user_publish_review'
- - 'i_code_review_user_create_multiline_mr_comment'
- - 'i_code_review_user_edit_multiline_mr_comment'
- - 'i_code_review_user_remove_multiline_mr_comment'
- - 'i_code_review_user_add_suggestion'
- - 'i_code_review_user_apply_suggestion'
- - 'i_code_review_user_assigned'
- - 'i_code_review_user_review_requested'
- - 'i_code_review_user_approve_mr'
- - 'i_code_review_user_unapprove_mr'
- - 'i_code_review_user_marked_as_draft'
- - 'i_code_review_user_unmarked_as_draft'
- - 'i_code_review_user_approval_rule_added'
- - 'i_code_review_user_approval_rule_deleted'
- - 'i_code_review_user_approval_rule_edited'
- - 'i_code_review_user_toggled_task_item_status'
- - 'i_code_review_user_create_mr_from_issue'
- - 'i_code_review_user_mr_discussion_locked'
- - 'i_code_review_user_mr_discussion_unlocked'
- - 'i_code_review_user_time_estimate_changed'
- - 'i_code_review_user_time_spent_changed'
- - 'i_code_review_user_assignees_changed'
- - 'i_code_review_user_reviewers_changed'
- - 'i_code_review_user_milestone_changed'
- - 'i_code_review_user_labels_changed'
- - 'i_code_review_click_diff_view_setting'
- - 'i_code_review_click_single_file_mode_setting'
- - 'i_code_review_click_file_browser_setting'
- - 'i_code_review_click_whitespace_setting'
- - 'i_code_review_diff_view_inline'
- - 'i_code_review_diff_view_parallel'
- - 'i_code_review_file_browser_tree_view'
- - 'i_code_review_file_browser_list_view'
- - 'i_code_review_diff_show_whitespace'
- - 'i_code_review_diff_hide_whitespace'
- - 'i_code_review_diff_single_file'
- - 'i_code_review_diff_multiple_files'
- - 'i_code_review_user_load_conflict_ui'
- - 'i_code_review_user_resolve_conflict'
- - 'i_code_review_user_searches_diff'
- - 'i_code_review_user_resolve_thread_in_issue'
- - 'i_code_review_widget_nothing_merge_click_new_file'
- - 'i_code_review_post_merge_delete_branch'
- - 'i_code_review_post_merge_click_revert'
- - 'i_code_review_post_merge_click_cherry_pick'
- - 'i_code_review_post_merge_submit_revert_modal'
- - 'i_code_review_post_merge_submit_cherry_pick_modal'
- - 'i_code_review_user_create_note_in_ipynb_diff'
- - 'i_code_review_user_create_note_in_ipynb_diff_mr'
- - 'i_code_review_user_create_note_in_ipynb_diff_commit'
- - 'i_code_review_merge_request_widget_test_summary_view'
- - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
- - 'i_code_review_merge_request_widget_test_summary_expand'
- - 'i_code_review_merge_request_widget_test_summary_expand_success'
- - 'i_code_review_merge_request_widget_test_summary_expand_warning'
- - 'i_code_review_merge_request_widget_test_summary_expand_failed'
- - 'i_code_review_merge_request_widget_accessibility_view'
- - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
- - 'i_code_review_merge_request_widget_accessibility_expand'
- - 'i_code_review_merge_request_widget_accessibility_expand_success'
- - 'i_code_review_merge_request_widget_accessibility_expand_warning'
- - 'i_code_review_merge_request_widget_accessibility_expand_failed'
- - 'i_code_review_merge_request_widget_code_quality_view'
- - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
- - 'i_code_review_merge_request_widget_code_quality_expand'
- - 'i_code_review_merge_request_widget_code_quality_expand_success'
- - 'i_code_review_merge_request_widget_code_quality_expand_warning'
- - 'i_code_review_merge_request_widget_code_quality_expand_failed'
- - 'i_code_review_merge_request_widget_terraform_view'
- - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
- - 'i_code_review_merge_request_widget_terraform_expand'
- - 'i_code_review_merge_request_widget_terraform_expand_success'
- - 'i_code_review_merge_request_widget_terraform_expand_warning'
- - 'i_code_review_merge_request_widget_terraform_expand_failed'
- - 'i_code_review_merge_request_widget_metrics_view'
- - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
- - 'i_code_review_merge_request_widget_metrics_expand'
- - 'i_code_review_merge_request_widget_metrics_expand_success'
- - 'i_code_review_merge_request_widget_metrics_expand_warning'
- - 'i_code_review_merge_request_widget_metrics_expand_failed'
- - 'i_code_review_merge_request_widget_status_checks_view'
- - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
- - 'i_code_review_merge_request_widget_status_checks_expand'
- - 'i_code_review_merge_request_widget_status_checks_expand_success'
- - 'i_code_review_merge_request_widget_status_checks_expand_warning'
- - 'i_code_review_merge_request_widget_status_checks_expand_failed'
- - 'i_code_review_submit_review_approve'
- - 'i_code_review_submit_review_comment'
- - 'i_code_review_merge_request_widget_license_compliance_view'
- - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
- - 'i_code_review_merge_request_widget_license_compliance_expand'
- - 'i_code_review_merge_request_widget_license_compliance_expand_success'
- - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
- - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
-- name: code_review_extension_category_monthly_active_users
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'i_code_review_user_vs_code_api_request'
- - 'i_code_review_user_jetbrains_api_request'
- - 'i_code_review_user_gitlab_cli_api_request'
diff --git a/config/metrics/aggregates/common.yml b/config/metrics/aggregates/common.yml
deleted file mode 100644
index 35311858c64..00000000000
--- a/config/metrics/aggregates/common.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/config/metrics/aggregates/common.yml
-# instead of this file.
-# - name: unique name of aggregated metric
-# operator: aggregation operator. Valid values are:
-# - "OR": counts unique elements that were observed triggering any of following events
-# - "AND": counts unique elements that were observed triggering all of following events
-# events: list of events names to aggregate into metric. All events in this list must have the same 'redis_slot' and 'aggregation' attributes
-# see from lib/gitlab/usage_data_counters/known_events/ for the list of valid events.
-# source: defines which datasource will be used to locate events that should be included in aggregated metric. Valid values are:
-# - database
-# - redis
-# time_frame: defines time frames for aggregated metrics:
-# - 7d - last 7 days
-# - 28d - last 28 days
-# - all - all historical available data, this time frame is not available for redis source
-# feature_flag: name of development feature flag that will be checked before metrics aggregation is performed.
-# Corresponding feature flag should have `default_enabled` attribute set to `false`.
-# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
----
-- name: incident_management_alerts_total_unique_counts
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'incident_management_alert_status_changed'
- - 'incident_management_alert_assigned'
- - 'incident_management_alert_todo'
- - 'incident_management_alert_create_incident'
-- name: incident_management_incidents_total_unique_counts
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'incident_management_incident_created'
- - 'incident_management_incident_reopened'
- - 'incident_management_incident_closed'
- - 'incident_management_incident_assigned'
- - 'incident_management_incident_todo'
- - 'incident_management_incident_comment'
- - 'incident_management_incident_zoom_meeting'
- - 'incident_management_incident_published'
- - 'incident_management_incident_relate'
- - 'incident_management_incident_unrelate'
- - 'incident_management_incident_change_confidential'
-- name: xmau_plan
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - users_creating_work_items
- - users_updating_work_item_title
- - users_updating_work_item_dates
- feature_flag: track_work_items_activity
-- name: xmau_project_management
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - users_creating_work_items
- - users_updating_work_item_title
- - users_updating_work_item_dates
- feature_flag: track_work_items_activity
-- name: users_work_items
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - users_creating_work_items
- - users_updating_work_item_title
- - users_updating_work_item_dates
- feature_flag: track_work_items_activity
diff --git a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
index fbf4be136cb..df64125b058 100644
--- a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
+++ b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- users_viewing_analytics_group_devops_adoption
- i_analytics_dev_ops_adoption
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 30de14c43f0..1f8175bd480 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
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- users_viewing_analytics_group_devops_adoption
- i_analytics_dev_ops_adoption
diff --git a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
index 6aadaed5180..1745055d11e 100644
--- a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- g_edit_by_web_ide
- g_edit_by_sfe
diff --git a/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml
index b38129071bf..a62b15af694 100644
--- a/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml
@@ -13,8 +13,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_search_total
- i_search_advanced
diff --git a/config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml b/config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml
index 1632aed611a..3b61fb65911 100644
--- a/config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml
+++ b/config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml
@@ -9,7 +9,17 @@ product_category: incident_management
value_type: number
status: active
time_frame: 28d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'incident_management_alert_status_changed'
+ - 'incident_management_alert_assigned'
+ - 'incident_management_alert_todo'
+ - 'incident_management_alert_create_incident'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml b/config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml
index 3174894384a..b5afcfa7ae6 100644
--- a/config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml
+++ b/config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml
@@ -9,7 +9,24 @@ product_category: incident_management
value_type: number
status: active
time_frame: 28d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'incident_management_incident_created'
+ - 'incident_management_incident_reopened'
+ - 'incident_management_incident_closed'
+ - 'incident_management_incident_assigned'
+ - 'incident_management_incident_todo'
+ - 'incident_management_incident_comment'
+ - 'incident_management_incident_zoom_meeting'
+ - 'incident_management_incident_published'
+ - 'incident_management_incident_relate'
+ - 'incident_management_incident_unrelate'
+ - 'incident_management_incident_change_confidential'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml
index d9aa7d17f43..68335a034a1 100644
--- a/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- incident_management_incident_created
- incident_management_incident_reopened
diff --git a/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
index fd67504fee9..bd654f16cd5 100644
--- a/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- g_project_management_issue_title_changed
- g_project_management_issue_description_changed
diff --git a/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml b/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml
new file mode 100644
index 00000000000..3c2cad5831e
--- /dev/null
+++ b/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml
@@ -0,0 +1,24 @@
+---
+data_category: optional
+key_path: redis_hll_counters.quickactions.i_quickactions_assign_multiple_monthly
+description: Count of MAU using the `/assign @user1 @user2` quick action
+product_section: dev
+product_stage: plan
+product_group: project_management
+product_category: issue_tracking
+value_type: number
+status: active
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_assign_multiple
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181939_releases.yml b/config/metrics/counts_28d/20210216181939_releases.yml
index a2a5a4adb0b..c2530b288b9 100644
--- a/config/metrics/counts_28d/20210216181939_releases.yml
+++ b/config/metrics/counts_28d/20210216181939_releases.yml
@@ -20,4 +20,5 @@ tier:
performance_indicator_type:
- gmau
- paid_gmau
+- smau
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml b/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml
index 7901b72ea4b..bd3b35ae0e9 100644
--- a/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml
+++ b/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml
@@ -13,8 +13,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_search_total
- i_search_advanced
diff --git a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
index 4d8e4409e73..e7eb6a01f82 100644
--- a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_code_review_click_diff_view_setting
- i_code_review_click_file_browser_setting
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 2c6b21b0f6f..554b5c57bb6 100755
--- 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
@@ -46,6 +46,7 @@ options:
- p_ci_templates_security_secret_detection
- p_ci_templates_security_license_scanning
- p_ci_templates_security_coverage_fuzzing
+ - p_ci_templates_security_coverage_fuzzing_latest
- p_ci_templates_security_api_fuzzing_latest
- p_ci_templates_security_secure_binaries
- p_ci_templates_security_dast_api
@@ -56,7 +57,6 @@ options:
- p_ci_templates_security_dependency_scanning
- p_ci_templates_security_api_fuzzing
- p_ci_templates_security_dast
- - p_ci_templates_security_cluster_image_scanning
- p_ci_templates_ios_fastlane
- p_ci_templates_composer
- p_ci_templates_c
@@ -143,9 +143,7 @@ options:
- p_ci_templates_implicit_jobs_code_intelligence
- p_ci_templates_implicit_jobs_code_quality
- p_ci_templates_implicit_jobs_dependency_scanning
- - p_ci_templates_implicit_jobs_dependency_scanning_latest
- p_ci_templates_implicit_jobs_license_scanning
- - p_ci_templates_implicit_jobs_license_scanning_latest
- p_ci_templates_implicit_jobs_deploy_ecs
- p_ci_templates_implicit_jobs_deploy_ec2
- p_ci_templates_implicit_auto_devops_deploy
@@ -153,27 +151,21 @@ options:
- p_ci_templates_implicit_jobs_browser_performance_testing
- p_ci_templates_implicit_jobs_test
- p_ci_templates_implicit_auto_devops_deploy_latest
- - p_ci_templates_implicit_jobs_browser_performance_testing_latest
- p_ci_templates_implicit_jobs_cf_provision
- - p_ci_templates_implicit_jobs_build_latest
- - p_ci_templates_implicit_jobs_sast_iac
- p_ci_templates_implicit_security_sast
- p_ci_templates_implicit_security_dast_runner_validation
- p_ci_templates_implicit_security_dast_on_demand_scan
- p_ci_templates_implicit_security_secret_detection
- p_ci_templates_implicit_security_license_scanning
- p_ci_templates_implicit_security_coverage_fuzzing
- - 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_container_scanning_latest
- p_ci_templates_implicit_security_dast_latest
- p_ci_templates_implicit_security_dependency_scanning
- p_ci_templates_implicit_security_api_fuzzing
- p_ci_templates_implicit_security_dast
- - p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_implicit_security_sast_iac
- p_ci_templates_kaniko
- p_ci_templates_qualys_iac_security
diff --git a/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
index c5e686a5353..fdd30477ed3 100644
--- a/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_quickactions_approve
- i_quickactions_assign_single
@@ -43,6 +46,7 @@ options:
- i_quickactions_parent_epic
- i_quickactions_promote
- i_quickactions_publish
+ - i_quickactions_ready
- i_quickactions_reassign
- i_quickactions_reassign_reviewer
- i_quickactions_rebase
diff --git a/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
index 6b6c40495a6..59427c74b0f 100644
--- a/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
@@ -1,7 +1,7 @@
---
data_category: optional
key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_monthly
-description: A monthly count of packages published to the registry using a deploy
+description: A monthly count of unique users who published packages to the registry using a deploy
token
product_section: ops
product_stage: package
@@ -11,8 +11,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_package_composer_deploy_token
- i_package_conan_deploy_token
diff --git a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
index e758f06bea9..5223f5c746e 100644
--- a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_package_composer_user
- i_package_conan_user
diff --git a/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
index 2d9e5402ffa..9f62f61a967 100644
--- a/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_ecosystem_jira_service_close_issue
- i_ecosystem_jira_service_cross_reference
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 f3df451f720..6f7b82ec793 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
@@ -9,13 +9,126 @@ product_category:
value_type: number
status: active
milestone: "13.12"
-time_frame: 28d
-data_source: redis_hll
distribution:
-- ce
-- ee
+ - ce
+ - ee
tier:
-- free
-- premium
-- ultimate
+ - free
+ - premium
+ - ultimate
performance_indicator_type: []
+time_frame: 28d
+instrumentation_class: AggregatedMetric
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
+ - 'i_code_review_click_single_file_mode_setting'
+ - 'i_code_review_click_file_browser_setting'
+ - 'i_code_review_click_whitespace_setting'
+ - 'i_code_review_diff_view_inline'
+ - 'i_code_review_diff_view_parallel'
+ - 'i_code_review_file_browser_tree_view'
+ - 'i_code_review_file_browser_list_view'
+ - 'i_code_review_diff_show_whitespace'
+ - 'i_code_review_diff_hide_whitespace'
+ - 'i_code_review_diff_single_file'
+ - 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
+ - 'i_code_review_user_searches_diff'
+ - 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
+ - 'i_code_review_user_create_note_in_ipynb_diff'
+ - 'i_code_review_user_create_note_in_ipynb_diff_mr'
+ - 'i_code_review_user_create_note_in_ipynb_diff_commit'
+ - 'i_code_review_merge_request_widget_test_summary_view'
+ - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
+ - 'i_code_review_merge_request_widget_test_summary_expand'
+ - 'i_code_review_merge_request_widget_test_summary_expand_success'
+ - 'i_code_review_merge_request_widget_test_summary_expand_warning'
+ - 'i_code_review_merge_request_widget_test_summary_expand_failed'
+ - 'i_code_review_merge_request_widget_accessibility_view'
+ - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
+ - 'i_code_review_merge_request_widget_accessibility_expand'
+ - 'i_code_review_merge_request_widget_accessibility_expand_success'
+ - 'i_code_review_merge_request_widget_accessibility_expand_warning'
+ - 'i_code_review_merge_request_widget_accessibility_expand_failed'
+ - 'i_code_review_merge_request_widget_code_quality_view'
+ - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
+ - 'i_code_review_merge_request_widget_code_quality_expand'
+ - 'i_code_review_merge_request_widget_code_quality_expand_success'
+ - 'i_code_review_merge_request_widget_code_quality_expand_warning'
+ - 'i_code_review_merge_request_widget_code_quality_expand_failed'
+ - 'i_code_review_merge_request_widget_terraform_view'
+ - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
+ - 'i_code_review_merge_request_widget_terraform_expand'
+ - 'i_code_review_merge_request_widget_terraform_expand_success'
+ - 'i_code_review_merge_request_widget_terraform_expand_warning'
+ - 'i_code_review_merge_request_widget_terraform_expand_failed'
+ - 'i_code_review_merge_request_widget_metrics_view'
+ - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
+ - 'i_code_review_merge_request_widget_metrics_expand'
+ - 'i_code_review_merge_request_widget_metrics_expand_success'
+ - 'i_code_review_merge_request_widget_metrics_expand_warning'
+ - 'i_code_review_merge_request_widget_metrics_expand_failed'
+ - 'i_code_review_merge_request_widget_status_checks_view'
+ - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
+ - 'i_code_review_merge_request_widget_status_checks_expand'
+ - 'i_code_review_merge_request_widget_status_checks_expand_success'
+ - 'i_code_review_merge_request_widget_status_checks_expand_warning'
+ - 'i_code_review_merge_request_widget_status_checks_expand_failed'
+ - 'i_code_review_submit_review_approve'
+ - 'i_code_review_submit_review_comment'
+ - 'i_code_review_merge_request_widget_license_compliance_view'
+ - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
+ - 'i_code_review_merge_request_widget_license_compliance_expand'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_success'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
diff --git a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
index 4594539267d..379307a2f44 100644
--- a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
@@ -11,7 +11,16 @@ status: active
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53553
time_frame: 28d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_jetbrains_api_request'
+ - 'i_code_review_user_gitlab_cli_api_request'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
index 939e8d69063..ce14aa19f9c 100644
--- a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
@@ -10,8 +10,6 @@ value_type: number
status: active
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53553
-time_frame: 28d
-data_source: redis_hll
distribution:
- ce
- ee
@@ -20,3 +18,121 @@ tier:
- premium
- ultimate
performance_indicator_type: []
+instrumentation_class: AggregatedMetric
+time_frame: 28d
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
+ - 'i_code_review_click_single_file_mode_setting'
+ - 'i_code_review_click_file_browser_setting'
+ - 'i_code_review_click_whitespace_setting'
+ - 'i_code_review_diff_view_inline'
+ - 'i_code_review_diff_view_parallel'
+ - 'i_code_review_file_browser_tree_view'
+ - 'i_code_review_file_browser_list_view'
+ - 'i_code_review_diff_show_whitespace'
+ - 'i_code_review_diff_hide_whitespace'
+ - 'i_code_review_diff_single_file'
+ - 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
+ - 'i_code_review_user_searches_diff'
+ - 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
+ - 'i_code_review_user_jetbrains_api_request'
+ - 'i_code_review_user_gitlab_cli_api_request'
+ - 'i_code_review_user_create_note_in_ipynb_diff'
+ - 'i_code_review_user_create_note_in_ipynb_diff_mr'
+ - 'i_code_review_user_create_note_in_ipynb_diff_commit'
+ - 'i_code_review_merge_request_widget_test_summary_view'
+ - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
+ - 'i_code_review_merge_request_widget_test_summary_expand'
+ - 'i_code_review_merge_request_widget_test_summary_expand_success'
+ - 'i_code_review_merge_request_widget_test_summary_expand_warning'
+ - 'i_code_review_merge_request_widget_test_summary_expand_failed'
+ - 'i_code_review_merge_request_widget_accessibility_view'
+ - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
+ - 'i_code_review_merge_request_widget_accessibility_expand'
+ - 'i_code_review_merge_request_widget_accessibility_expand_success'
+ - 'i_code_review_merge_request_widget_accessibility_expand_warning'
+ - 'i_code_review_merge_request_widget_accessibility_expand_failed'
+ - 'i_code_review_merge_request_widget_code_quality_view'
+ - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
+ - 'i_code_review_merge_request_widget_code_quality_expand'
+ - 'i_code_review_merge_request_widget_code_quality_expand_success'
+ - 'i_code_review_merge_request_widget_code_quality_expand_warning'
+ - 'i_code_review_merge_request_widget_code_quality_expand_failed'
+ - 'i_code_review_merge_request_widget_terraform_view'
+ - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
+ - 'i_code_review_merge_request_widget_terraform_expand'
+ - 'i_code_review_merge_request_widget_terraform_expand_success'
+ - 'i_code_review_merge_request_widget_terraform_expand_warning'
+ - 'i_code_review_merge_request_widget_terraform_expand_failed'
+ - 'i_code_review_merge_request_widget_metrics_view'
+ - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
+ - 'i_code_review_merge_request_widget_metrics_expand'
+ - 'i_code_review_merge_request_widget_metrics_expand_success'
+ - 'i_code_review_merge_request_widget_metrics_expand_warning'
+ - 'i_code_review_merge_request_widget_metrics_expand_failed'
+ - 'i_code_review_merge_request_widget_status_checks_view'
+ - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
+ - 'i_code_review_merge_request_widget_status_checks_expand'
+ - 'i_code_review_merge_request_widget_status_checks_expand_success'
+ - 'i_code_review_merge_request_widget_status_checks_expand_warning'
+ - 'i_code_review_merge_request_widget_status_checks_expand_failed'
+ - 'i_code_review_submit_review_approve'
+ - 'i_code_review_submit_review_comment'
+ - 'i_code_review_merge_request_widget_license_compliance_view'
+ - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
+ - 'i_code_review_merge_request_widget_license_compliance_expand'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_success'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
diff --git a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
index a3f1a052531..698928834ed 100644
--- a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
@@ -12,8 +12,11 @@ milestone: "13.12"
introduced_by_url:
time_frame: 28d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- o_pipeline_authoring_unique_users_committing_ciconfigfile
- o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
diff --git a/config/metrics/counts_28d/20210901223532_p_ci_templates_implicit_jobs_load_performance_testing_monthly.yml b/config/metrics/counts_28d/20210901223532_p_ci_templates_implicit_jobs_load_performance_testing_monthly.yml
index c5ce964bfaa..539781592bd 100644
--- a/config/metrics/counts_28d/20210901223532_p_ci_templates_implicit_jobs_load_performance_testing_monthly.yml
+++ b/config/metrics/counts_28d/20210901223532_p_ci_templates_implicit_jobs_load_performance_testing_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_load_performance_testing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223702_p_ci_templates_implicit_jobs_browser_performance_testing_latest_monthly.yml b/config/metrics/counts_28d/20210901223702_p_ci_templates_implicit_jobs_browser_performance_testing_latest_monthly.yml
index 5bd79adf6e5..d5dd0372093 100644
--- a/config/metrics/counts_28d/20210901223702_p_ci_templates_implicit_jobs_browser_performance_testing_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210901223702_p_ci_templates_implicit_jobs_browser_performance_testing_latest_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_browser_performance_testing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223711_p_ci_templates_implicit_jobs_cf_provision_monthly.yml b/config/metrics/counts_28d/20210901223711_p_ci_templates_implicit_jobs_cf_provision_monthly.yml
index 362aed75e00..f8f018a6a28 100644
--- a/config/metrics/counts_28d/20210901223711_p_ci_templates_implicit_jobs_cf_provision_monthly.yml
+++ b/config/metrics/counts_28d/20210901223711_p_ci_templates_implicit_jobs_cf_provision_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_cf_provision
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223721_p_ci_templates_implicit_jobs_build_latest_monthly.yml b/config/metrics/counts_28d/20210901223721_p_ci_templates_implicit_jobs_build_latest_monthly.yml
index d7c78554423..81a1a37e050 100644
--- a/config/metrics/counts_28d/20210901223721_p_ci_templates_implicit_jobs_build_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210901223721_p_ci_templates_implicit_jobs_build_latest_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_build_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223730_p_ci_templates_implicit_security_dast_runner_validation_monthly.yml b/config/metrics/counts_28d/20210901223730_p_ci_templates_implicit_security_dast_runner_validation_monthly.yml
index a688785bc0f..49f7d1e9cf1 100644
--- a/config/metrics/counts_28d/20210901223730_p_ci_templates_implicit_security_dast_runner_validation_monthly.yml
+++ b/config/metrics/counts_28d/20210901223730_p_ci_templates_implicit_security_dast_runner_validation_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_runner_validation
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223739_p_ci_templates_implicit_security_dast_on_demand_scan_monthly.yml b/config/metrics/counts_28d/20210901223739_p_ci_templates_implicit_security_dast_on_demand_scan_monthly.yml
index 97bd575f2f3..b3deccc2520 100644
--- a/config/metrics/counts_28d/20210901223739_p_ci_templates_implicit_security_dast_on_demand_scan_monthly.yml
+++ b/config/metrics/counts_28d/20210901223739_p_ci_templates_implicit_security_dast_on_demand_scan_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_on_demand_scan
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223758_p_ci_templates_implicit_security_coverage_fuzzing_monthly.yml b/config/metrics/counts_28d/20210901223758_p_ci_templates_implicit_security_coverage_fuzzing_monthly.yml
index 8735c299082..ba4ec3b4fa3 100644
--- a/config/metrics/counts_28d/20210901223758_p_ci_templates_implicit_security_coverage_fuzzing_monthly.yml
+++ b/config/metrics/counts_28d/20210901223758_p_ci_templates_implicit_security_coverage_fuzzing_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_coverage_fuzzing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223806_p_ci_templates_implicit_security_api_fuzzing_latest_monthly.yml b/config/metrics/counts_28d/20210901223806_p_ci_templates_implicit_security_api_fuzzing_latest_monthly.yml
index 70f42f3861e..176964c3cdc 100644
--- a/config/metrics/counts_28d/20210901223806_p_ci_templates_implicit_security_api_fuzzing_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210901223806_p_ci_templates_implicit_security_api_fuzzing_latest_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_api_fuzzing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223815_p_ci_templates_implicit_security_secure_binaries_monthly.yml b/config/metrics/counts_28d/20210901223815_p_ci_templates_implicit_security_secure_binaries_monthly.yml
index 35235a85b19..0c8001e6f77 100644
--- a/config/metrics/counts_28d/20210901223815_p_ci_templates_implicit_security_secure_binaries_monthly.yml
+++ b/config/metrics/counts_28d/20210901223815_p_ci_templates_implicit_security_secure_binaries_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_secure_binaries
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223824_p_ci_templates_implicit_security_dast_api_monthly.yml b/config/metrics/counts_28d/20210901223824_p_ci_templates_implicit_security_dast_api_monthly.yml
index 087a55fd275..9c22a733f84 100644
--- a/config/metrics/counts_28d/20210901223824_p_ci_templates_implicit_security_dast_api_monthly.yml
+++ b/config/metrics/counts_28d/20210901223824_p_ci_templates_implicit_security_dast_api_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_api
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223841_p_ci_templates_implicit_security_dast_latest_monthly.yml b/config/metrics/counts_28d/20210901223841_p_ci_templates_implicit_security_dast_latest_monthly.yml
index 0adb938298c..de98bdd43b7 100644
--- a/config/metrics/counts_28d/20210901223841_p_ci_templates_implicit_security_dast_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210901223841_p_ci_templates_implicit_security_dast_latest_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210901223858_p_ci_templates_implicit_security_api_fuzzing_monthly.yml b/config/metrics/counts_28d/20210901223858_p_ci_templates_implicit_security_api_fuzzing_monthly.yml
index 85868e0c79c..d0e9b20316b 100644
--- a/config/metrics/counts_28d/20210901223858_p_ci_templates_implicit_security_api_fuzzing_monthly.yml
+++ b/config/metrics/counts_28d/20210901223858_p_ci_templates_implicit_security_api_fuzzing_monthly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_api_fuzzing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml b/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
index 28ed156f483..73141ddf341 100644
--- a/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
@@ -6,8 +6,8 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
-milestone: "14.4"
+status: removed
+milestone: '14.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71157
time_frame: 28d
data_source: redis_hll
@@ -22,4 +22,6 @@ tier:
- ultimate
options:
events:
- - p_ci_templates_implicit_jobs_deploy_latest
+ - p_ci_templates_implicit_jobs_deploy_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml
index 72a061f831b..781dbbe7b60 100644
--- a/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml
+++ b/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml
@@ -3,11 +3,11 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_
description: Count of pipelines with implicit runs using the latest SAST IaC template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "14.5"
+status: removed
+milestone: '14.5'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
time_frame: 28d
data_source: redis_hll
@@ -24,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_sast_iac_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml
index 2a34553de79..c676750d92d 100644
--- a/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml
+++ b/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml
@@ -3,11 +3,11 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_
description: Count of pipelines with implicit runs using the latest SAST IaC template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "14.5"
+status: removed
+milestone: '14.5'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
time_frame: 28d
data_source: redis_hll
@@ -24,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
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
index 4b9bf4120f5..ec67d0a713f 100644
--- 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
@@ -6,7 +6,7 @@ product_stage: secure
product_group: dynamic_analysis
product_category: dynamic_application_security_testing
value_type: number
-status: active
+status: removed
milestone: '14.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
time_frame: 28d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_api_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220222215951_xmau_plan.yml b/config/metrics/counts_28d/20220222215951_xmau_plan.yml
index aaa9558d5a6..c254ad942c2 100644
--- a/config/metrics/counts_28d/20220222215951_xmau_plan.yml
+++ b/config/metrics/counts_28d/20220222215951_xmau_plan.yml
@@ -10,7 +10,18 @@ status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_28d/20220222215952_xmau_project_management.yml b/config/metrics/counts_28d/20220222215952_xmau_project_management.yml
index ede46c85292..0dad4fd0979 100644
--- a/config/metrics/counts_28d/20220222215952_xmau_project_management.yml
+++ b/config/metrics/counts_28d/20220222215952_xmau_project_management.yml
@@ -10,7 +10,18 @@ status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_28d/20220222215955_users_work_items.yml b/config/metrics/counts_28d/20220222215955_users_work_items.yml
index a0f892fcef2..ec07fb25f11 100644
--- a/config/metrics/counts_28d/20220222215955_users_work_items.yml
+++ b/config/metrics/counts_28d/20220222215955_users_work_items.yml
@@ -10,7 +10,18 @@ status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_28d/20220310213320_p_ci_templates_implicit_jobs_secret_detection_latest_monthly.yml b/config/metrics/counts_28d/20220310213320_p_ci_templates_implicit_jobs_secret_detection_latest_monthly.yml
index d627a61d553..64f0bc79682 100644
--- a/config/metrics/counts_28d/20220310213320_p_ci_templates_implicit_jobs_secret_detection_latest_monthly.yml
+++ b/config/metrics/counts_28d/20220310213320_p_ci_templates_implicit_jobs_secret_detection_latest_monthly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_secret_detection_latest_monthly
-description: Weekly counts for implicit use of Secret Detection CI Latest template (Jobs folder)
+description: Weekly counts for implicit use of Secret Detection CI Latest template
+ (Jobs folder)
product_section: sec
product_stage: secure
product_group: static_analysis
product_category: static_application_security_testing
value_type: number
-status: active
-milestone: "15.0"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847'
+status: removed
+milestone: '15.0'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847
time_frame: 28d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_secret_detection_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220310213749_p_ci_templates_implicit_jobs_sast_latest_monthly.yml b/config/metrics/counts_28d/20220310213749_p_ci_templates_implicit_jobs_sast_latest_monthly.yml
index a9902f76feb..e77e4044894 100644
--- a/config/metrics/counts_28d/20220310213749_p_ci_templates_implicit_jobs_sast_latest_monthly.yml
+++ b/config/metrics/counts_28d/20220310213749_p_ci_templates_implicit_jobs_sast_latest_monthly.yml
@@ -6,9 +6,9 @@ product_stage: secure
product_group: static_analysis
product_category: static_application_security_testing
value_type: number
-status: active
-milestone: "15.0"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847'
+status: removed
+milestone: '15.0'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847
time_frame: 28d
data_source: redis_hll
data_category: optional
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220315223227_error_tracking_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20220315223227_error_tracking_total_unique_counts_monthly.yml
index 50a854eb455..646260aa65e 100644
--- a/config/metrics/counts_28d/20220315223227_error_tracking_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20220315223227_error_tracking_total_unique_counts_monthly.yml
@@ -12,8 +12,11 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82543
time_frame: 28d
data_source: redis_hll
data_category: optional
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- error_tracking_view_list
- error_tracking_view_details
diff --git a/config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml
index cfdd8987275..d379cf39983 100644
--- a/config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml
@@ -13,8 +13,11 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90205
time_frame: 28d
data_source: redis_hll
data_category: optional
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- incident_management_timeline_event_created
- incident_management_timeline_event_edited
diff --git a/config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml b/config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml
index 56c9fb62bd3..574c9f41128 100644
--- a/config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml
+++ b/config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml
@@ -6,8 +6,8 @@ product_stage: secure
product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.3"
+status: removed
+milestone: '15.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
time_frame: 28d
data_source: redis_hll
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_fortify_fod_sast
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220906065651_incident_management_timeline_event_created_monthly.yml b/config/metrics/counts_28d/20220906065651_incident_management_timeline_event_created_monthly.yml
new file mode 100644
index 00000000000..86b11489af0
--- /dev/null
+++ b/config/metrics/counts_28d/20220906065651_incident_management_timeline_event_created_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_created_monthly
+description: Count of unique users created timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_created
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220906070355_incident_management_timeline_event_edited_monthly.yml b/config/metrics/counts_28d/20220906070355_incident_management_timeline_event_edited_monthly.yml
new file mode 100644
index 00000000000..31815426918
--- /dev/null
+++ b/config/metrics/counts_28d/20220906070355_incident_management_timeline_event_edited_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_edited_monthly
+description: Count of unique users edited timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_edited
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220906070634_incident_management_timeline_event_deleted_monthly.yml b/config/metrics/counts_28d/20220906070634_incident_management_timeline_event_deleted_monthly.yml
new file mode 100644
index 00000000000..dbc3ac61071
--- /dev/null
+++ b/config/metrics/counts_28d/20220906070634_incident_management_timeline_event_deleted_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_deleted_monthly
+description: Count of unique users deleted timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_deleted
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220907032044_i_quickactions_ready_monthly.yml b/config/metrics/counts_28d/20220907032044_i_quickactions_ready_monthly.yml
new file mode 100644
index 00000000000..943a1ba235c
--- /dev/null
+++ b/config/metrics/counts_28d/20220907032044_i_quickactions_ready_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.project_management.i_quickactions_ready_monthly
+description: Count of MAU using the `/ready` quick action
+product_section: dev
+product_stage: plan
+product_group: project_management
+product_category: issue_tracking
+value_type: number
+data_source: redis_hll
+status: active
+milestone: "15.4"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97115"
+time_frame: 28d
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_ready
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20220907084347_p_ci_templates_implicit_security_sast_iac_monthly.yml b/config/metrics/counts_28d/20220907084347_p_ci_templates_implicit_security_sast_iac_monthly.yml
index 2f32d5a3569..47068af05e2 100644
--- a/config/metrics/counts_28d/20220907084347_p_ci_templates_implicit_security_sast_iac_monthly.yml
+++ b/config/metrics/counts_28d/20220907084347_p_ci_templates_implicit_security_sast_iac_monthly.yml
@@ -1,13 +1,14 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_monthly
-description: Count of pipelines with implicit SAST runs using the stable SAST IaC template
+description: Count of pipelines with implicit SAST runs using the stable SAST IaC
+ template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.4"
+status: removed
+milestone: '15.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86275
time_frame: 28d
data_source: redis_hll
@@ -24,3 +25,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220907102714_p_ci_templates_implicit_jobs_sast_iac_monthly.yml b/config/metrics/counts_28d/20220907102714_p_ci_templates_implicit_jobs_sast_iac_monthly.yml
index 368c15653e9..0bcdad370ce 100644
--- a/config/metrics/counts_28d/20220907102714_p_ci_templates_implicit_jobs_sast_iac_monthly.yml
+++ b/config/metrics/counts_28d/20220907102714_p_ci_templates_implicit_jobs_sast_iac_monthly.yml
@@ -1,13 +1,14 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_monthly
-description: Count of pipelines with implicit SAST jobs using the stable SAST IaC template
+description: Count of pipelines with implicit SAST jobs using the stable SAST IaC
+ template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.4"
+status: removed
+milestone: '15.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86275
time_frame: 28d
data_source: redis_hll
@@ -24,3 +25,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml
index a3a435fca09..8e51d7e163a 100644
--- a/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml
+++ b/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly
-description: Monthly counts for implicit Dependency Scanning CI Latest template (Jobs folder)
+description: Monthly counts for implicit Dependency Scanning CI Latest template (Jobs
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: dependency_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 28d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_dependency_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml
index acc48ff2a44..8ad48955bea 100644
--- a/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml
+++ b/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_latest_monthly
-description: Monthly counts for implicit License Scanning CI Latest template (Jobs folder)
+description: Monthly counts for implicit License Scanning CI Latest template (Jobs
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: license_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 28d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_license_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml
index 2aebbc3a9eb..3d5db04c7b8 100644
--- a/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml
+++ b/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_container_scanning_latest_monthly
-description: Monthly counts for implicit Container Scanning CI Latest template (Security folder)
+description: Monthly counts for implicit Container Scanning CI Latest template (Security
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: container_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 28d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_container_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220913225020_p_ci_templates_security_coverage_fuzzing_latest_monthly.yml b/config/metrics/counts_28d/20220913225020_p_ci_templates_security_coverage_fuzzing_latest_monthly.yml
new file mode 100644
index 00000000000..c4fad8d7545
--- /dev/null
+++ b/config/metrics/counts_28d/20220913225020_p_ci_templates_security_coverage_fuzzing_latest_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_coverage_fuzzing_latest_monthly
+description: Monthly counts for Coverage Fuzzing 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: "15.5"
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97886'
+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_coverage_fuzzing_latest
diff --git a/config/metrics/counts_28d/20220913225303_p_ci_templates_implicit_security_coverage_fuzzing_latest_monthly.yml b/config/metrics/counts_28d/20220913225303_p_ci_templates_implicit_security_coverage_fuzzing_latest_monthly.yml
new file mode 100644
index 00000000000..a66558a3537
--- /dev/null
+++ b/config/metrics/counts_28d/20220913225303_p_ci_templates_implicit_security_coverage_fuzzing_latest_monthly.yml
@@ -0,0 +1,27 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_coverage_fuzzing_latest_monthly
+description: Monthly counts for implicit Coverage Fuzzing latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: removed
+milestone: '15.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97886
+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_coverage_fuzzing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_28d/20220922042106_users_updating_work_item_iteration_monthly.yml b/config/metrics/counts_28d/20220922042106_users_updating_work_item_iteration_monthly.yml
new file mode 100644
index 00000000000..4c19e4e3261
--- /dev/null
+++ b/config/metrics/counts_28d/20220922042106_users_updating_work_item_iteration_monthly.yml
@@ -0,0 +1,24 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_iteration_monthly
+description: Unique users updating a work item's iteration
+product_section: team planning
+product_stage: dev
+product_group: plan
+product_category: project_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98539
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_iteration
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20221006065524_i_quickactions_link_monthly.yml b/config/metrics/counts_28d/20221006065524_i_quickactions_link_monthly.yml
new file mode 100644
index 00000000000..52b75a90a03
--- /dev/null
+++ b/config/metrics/counts_28d/20221006065524_i_quickactions_link_monthly.yml
@@ -0,0 +1,26 @@
+key_path: redis_hll_counters.quickactions.i_quickactions_link_monthly
+name: quickactions_timeline_monthly
+description: Count of MAU using the `/link` quick action
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99963
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_link
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20221007011350_users_updating_work_item_labels_monthly.yml b/config/metrics/counts_28d/20221007011350_users_updating_work_item_labels_monthly.yml
new file mode 100644
index 00000000000..5ebb56ea936
--- /dev/null
+++ b/config/metrics/counts_28d/20221007011350_users_updating_work_item_labels_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_labels_monthly
+description: Unique users updating a work item's labels
+product_category: team_planning
+product_section: dev
+product_stage: plan
+product_group: project_management
+value_type: number
+status: active
+milestone: '15.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100485
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_labels
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216174908_analytics_unique_visits_for_any_target.yml b/config/metrics/counts_7d/20210216174908_analytics_unique_visits_for_any_target.yml
index 9865183388f..424552f54e4 100644
--- a/config/metrics/counts_7d/20210216174908_analytics_unique_visits_for_any_target.yml
+++ b/config/metrics/counts_7d/20210216174908_analytics_unique_visits_for_any_target.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- users_viewing_analytics_group_devops_adoption
- i_analytics_dev_ops_adoption
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 09940ac08dd..88ed638d23d 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
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- users_viewing_analytics_group_devops_adoption
- i_analytics_dev_ops_adoption
diff --git a/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
index ef67ab7f11e..2b136ef96dd 100644
--- a/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
@@ -9,9 +9,12 @@ product_category: web_ide
value_type: number
status: active
time_frame: 7d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- g_edit_by_web_ide
- g_edit_by_sfe
diff --git a/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml
index b3f32ed28c6..4f55e279459 100644
--- a/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_search_total
- i_search_advanced
diff --git a/config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml b/config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml
index eeb751682c7..e4089d589cc 100644
--- a/config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml
+++ b/config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml
@@ -9,7 +9,17 @@ product_category: incident_management
value_type: number
status: active
time_frame: 7d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'incident_management_alert_status_changed'
+ - 'incident_management_alert_assigned'
+ - 'incident_management_alert_todo'
+ - 'incident_management_alert_create_incident'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml b/config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml
index 6089b36401e..93228309855 100644
--- a/config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml
+++ b/config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml
@@ -9,7 +9,24 @@ product_category: incident_management
value_type: number
status: active
time_frame: 7d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'incident_management_incident_created'
+ - 'incident_management_incident_reopened'
+ - 'incident_management_incident_closed'
+ - 'incident_management_incident_assigned'
+ - 'incident_management_incident_todo'
+ - 'incident_management_incident_comment'
+ - 'incident_management_incident_zoom_meeting'
+ - 'incident_management_incident_published'
+ - 'incident_management_incident_relate'
+ - 'incident_management_incident_unrelate'
+ - 'incident_management_incident_change_confidential'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml
index 5863d5c6d33..8fce94a17e2 100644
--- a/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- g_project_management_issue_title_changed
- g_project_management_issue_description_changed
diff --git a/config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml b/config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml
new file mode 100644
index 00000000000..3ca7b226545
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml
@@ -0,0 +1,24 @@
+---
+data_category: optional
+key_path: redis_hll_counters.quickactions.i_quickactions_assign_multiple_weekly
+description: Count of WAU using the `/assign @user1 @user2` quick action
+product_section: dev
+product_stage: plan
+product_group: project_management
+product_category: issue_tracking
+value_type: number
+status: active
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_assign_multiple
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "<13.9"
diff --git a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
index 60619deb786..420926c825c 100644
--- a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_code_review_click_diff_view_setting
- i_code_review_click_file_browser_setting
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 16186a412b8..f3758f5bd06 100755
--- 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
@@ -46,6 +46,7 @@ options:
- p_ci_templates_security_secret_detection
- p_ci_templates_security_license_scanning
- p_ci_templates_security_coverage_fuzzing
+ - p_ci_templates_security_coverage_fuzzing_latest
- p_ci_templates_security_api_fuzzing_latest
- p_ci_templates_security_secure_binaries
- p_ci_templates_security_dast_api
@@ -56,7 +57,6 @@ options:
- p_ci_templates_security_dependency_scanning
- p_ci_templates_security_api_fuzzing
- p_ci_templates_security_dast
- - p_ci_templates_security_cluster_image_scanning
- p_ci_templates_ios_fastlane
- p_ci_templates_composer
- p_ci_templates_c
@@ -160,7 +160,6 @@ options:
- p_ci_templates_implicit_security_secret_detection
- p_ci_templates_implicit_security_license_scanning
- p_ci_templates_implicit_security_coverage_fuzzing
- - 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
@@ -169,7 +168,6 @@ options:
- p_ci_templates_implicit_security_dependency_scanning
- p_ci_templates_implicit_security_api_fuzzing
- p_ci_templates_implicit_security_dast
- - p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
- p_ci_templates_qualys_iac_security
- p_ci_templates_liquibase
diff --git a/config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml
index f66f4acd853..039e65bcbaa 100644
--- a/config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_quickactions_approve
- i_quickactions_assign_single
@@ -43,6 +46,7 @@ options:
- i_quickactions_parent_epic
- i_quickactions_promote
- i_quickactions_publish
+ - i_quickactions_ready
- i_quickactions_reassign
- i_quickactions_reassign_reviewer
- i_quickactions_rebase
diff --git a/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml
index 28adf6d6d01..19bb7f0ba3c 100644
--- a/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml
@@ -1,7 +1,8 @@
---
data_category: optional
key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_weekly
-description: A weekly count of packages published to the registry using a deploy token
+description: A weekly count of unique users who published packages to the registry using a deploy
+ token
product_section: ops
product_stage: package
product_group: package
@@ -10,8 +11,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_package_composer_deploy_token
- i_package_conan_deploy_token
diff --git a/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
index e7465b79667..d5576772b91 100644
--- a/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_package_composer_user
- i_package_conan_user
diff --git a/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml
index 513b3ba1f5e..350a7032493 100644
--- a/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml
@@ -10,8 +10,11 @@ value_type: number
status: active
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- i_ecosystem_jira_service_close_issue
- i_ecosystem_jira_service_cross_reference
diff --git a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
index bb909bd10b2..f29f4d0cf28 100644
--- a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
@@ -9,8 +9,6 @@ product_category:
value_type: number
status: active
milestone: "13.12"
-time_frame: 7d
-data_source: redis_hll
distribution:
- ce
- ee
@@ -18,3 +16,121 @@ tier:
- free
- premium
- ultimate
+instrumentation_class: AggregatedMetric
+time_frame: 7d
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
+ - 'i_code_review_click_single_file_mode_setting'
+ - 'i_code_review_click_file_browser_setting'
+ - 'i_code_review_click_whitespace_setting'
+ - 'i_code_review_diff_view_inline'
+ - 'i_code_review_diff_view_parallel'
+ - 'i_code_review_file_browser_tree_view'
+ - 'i_code_review_file_browser_list_view'
+ - 'i_code_review_diff_show_whitespace'
+ - 'i_code_review_diff_hide_whitespace'
+ - 'i_code_review_diff_single_file'
+ - 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
+ - 'i_code_review_user_searches_diff'
+ - 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
+ - 'i_code_review_user_jetbrains_api_request'
+ - 'i_code_review_user_gitlab_cli_api_request'
+ - 'i_code_review_user_create_note_in_ipynb_diff'
+ - 'i_code_review_user_create_note_in_ipynb_diff_mr'
+ - 'i_code_review_user_create_note_in_ipynb_diff_commit'
+ - 'i_code_review_merge_request_widget_test_summary_view'
+ - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
+ - 'i_code_review_merge_request_widget_test_summary_expand'
+ - 'i_code_review_merge_request_widget_test_summary_expand_success'
+ - 'i_code_review_merge_request_widget_test_summary_expand_warning'
+ - 'i_code_review_merge_request_widget_test_summary_expand_failed'
+ - 'i_code_review_merge_request_widget_accessibility_view'
+ - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
+ - 'i_code_review_merge_request_widget_accessibility_expand'
+ - 'i_code_review_merge_request_widget_accessibility_expand_success'
+ - 'i_code_review_merge_request_widget_accessibility_expand_warning'
+ - 'i_code_review_merge_request_widget_accessibility_expand_failed'
+ - 'i_code_review_merge_request_widget_code_quality_view'
+ - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
+ - 'i_code_review_merge_request_widget_code_quality_expand'
+ - 'i_code_review_merge_request_widget_code_quality_expand_success'
+ - 'i_code_review_merge_request_widget_code_quality_expand_warning'
+ - 'i_code_review_merge_request_widget_code_quality_expand_failed'
+ - 'i_code_review_merge_request_widget_terraform_view'
+ - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
+ - 'i_code_review_merge_request_widget_terraform_expand'
+ - 'i_code_review_merge_request_widget_terraform_expand_success'
+ - 'i_code_review_merge_request_widget_terraform_expand_warning'
+ - 'i_code_review_merge_request_widget_terraform_expand_failed'
+ - 'i_code_review_merge_request_widget_metrics_view'
+ - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
+ - 'i_code_review_merge_request_widget_metrics_expand'
+ - 'i_code_review_merge_request_widget_metrics_expand_success'
+ - 'i_code_review_merge_request_widget_metrics_expand_warning'
+ - 'i_code_review_merge_request_widget_metrics_expand_failed'
+ - 'i_code_review_merge_request_widget_status_checks_view'
+ - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
+ - 'i_code_review_merge_request_widget_status_checks_expand'
+ - 'i_code_review_merge_request_widget_status_checks_expand_success'
+ - 'i_code_review_merge_request_widget_status_checks_expand_warning'
+ - 'i_code_review_merge_request_widget_status_checks_expand_failed'
+ - 'i_code_review_submit_review_approve'
+ - 'i_code_review_submit_review_comment'
+ - 'i_code_review_merge_request_widget_license_compliance_view'
+ - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
+ - 'i_code_review_merge_request_widget_license_compliance_expand'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_success'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
diff --git a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
index ce6093ed7fc..e40e7c7f19a 100644
--- a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
@@ -10,8 +10,6 @@ value_type: number
status: active
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53553/
-time_frame: 7d
-data_source: redis_hll
distribution:
- ce
- ee
@@ -19,3 +17,118 @@ tier:
- free
- premium
- ultimate
+time_frame: 7d
+instrumentation_class: AggregatedMetric
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
+ - 'i_code_review_click_single_file_mode_setting'
+ - 'i_code_review_click_file_browser_setting'
+ - 'i_code_review_click_whitespace_setting'
+ - 'i_code_review_diff_view_inline'
+ - 'i_code_review_diff_view_parallel'
+ - 'i_code_review_file_browser_tree_view'
+ - 'i_code_review_file_browser_list_view'
+ - 'i_code_review_diff_show_whitespace'
+ - 'i_code_review_diff_hide_whitespace'
+ - 'i_code_review_diff_single_file'
+ - 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
+ - 'i_code_review_user_searches_diff'
+ - 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
+ - 'i_code_review_user_create_note_in_ipynb_diff'
+ - 'i_code_review_user_create_note_in_ipynb_diff_mr'
+ - 'i_code_review_user_create_note_in_ipynb_diff_commit'
+ - 'i_code_review_merge_request_widget_test_summary_view'
+ - 'i_code_review_merge_request_widget_test_summary_full_report_clicked'
+ - 'i_code_review_merge_request_widget_test_summary_expand'
+ - 'i_code_review_merge_request_widget_test_summary_expand_success'
+ - 'i_code_review_merge_request_widget_test_summary_expand_warning'
+ - 'i_code_review_merge_request_widget_test_summary_expand_failed'
+ - 'i_code_review_merge_request_widget_accessibility_view'
+ - 'i_code_review_merge_request_widget_accessibility_full_report_clicked'
+ - 'i_code_review_merge_request_widget_accessibility_expand'
+ - 'i_code_review_merge_request_widget_accessibility_expand_success'
+ - 'i_code_review_merge_request_widget_accessibility_expand_warning'
+ - 'i_code_review_merge_request_widget_accessibility_expand_failed'
+ - 'i_code_review_merge_request_widget_code_quality_view'
+ - 'i_code_review_merge_request_widget_code_quality_full_report_clicked'
+ - 'i_code_review_merge_request_widget_code_quality_expand'
+ - 'i_code_review_merge_request_widget_code_quality_expand_success'
+ - 'i_code_review_merge_request_widget_code_quality_expand_warning'
+ - 'i_code_review_merge_request_widget_code_quality_expand_failed'
+ - 'i_code_review_merge_request_widget_terraform_view'
+ - 'i_code_review_merge_request_widget_terraform_full_report_clicked'
+ - 'i_code_review_merge_request_widget_terraform_expand'
+ - 'i_code_review_merge_request_widget_terraform_expand_success'
+ - 'i_code_review_merge_request_widget_terraform_expand_warning'
+ - 'i_code_review_merge_request_widget_terraform_expand_failed'
+ - 'i_code_review_merge_request_widget_metrics_view'
+ - 'i_code_review_merge_request_widget_metrics_full_report_clicked'
+ - 'i_code_review_merge_request_widget_metrics_expand'
+ - 'i_code_review_merge_request_widget_metrics_expand_success'
+ - 'i_code_review_merge_request_widget_metrics_expand_warning'
+ - 'i_code_review_merge_request_widget_metrics_expand_failed'
+ - 'i_code_review_merge_request_widget_status_checks_view'
+ - 'i_code_review_merge_request_widget_status_checks_full_report_clicked'
+ - 'i_code_review_merge_request_widget_status_checks_expand'
+ - 'i_code_review_merge_request_widget_status_checks_expand_success'
+ - 'i_code_review_merge_request_widget_status_checks_expand_warning'
+ - 'i_code_review_merge_request_widget_status_checks_expand_failed'
+ - 'i_code_review_submit_review_approve'
+ - 'i_code_review_submit_review_comment'
+ - 'i_code_review_merge_request_widget_license_compliance_view'
+ - 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
+ - 'i_code_review_merge_request_widget_license_compliance_expand'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_success'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_warning'
+ - 'i_code_review_merge_request_widget_license_compliance_expand_failed'
diff --git a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
index 0ca1e03ab11..f5e8a10506f 100644
--- a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
@@ -11,7 +11,16 @@ status: active
milestone: "13.12"
introduced_by_url:
time_frame: 7d
+instrumentation_class: AggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_jetbrains_api_request'
+ - 'i_code_review_user_gitlab_cli_api_request'
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
index 1439c31a1cb..3f688886a67 100644
--- a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
@@ -12,8 +12,11 @@ milestone: "13.12"
introduced_by_url:
time_frame: 7d
data_source: redis_hll
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- o_pipeline_authoring_unique_users_committing_ciconfigfile
- o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
diff --git a/config/metrics/counts_7d/20210901223528_p_ci_templates_implicit_jobs_load_performance_testing_weekly.yml b/config/metrics/counts_7d/20210901223528_p_ci_templates_implicit_jobs_load_performance_testing_weekly.yml
index a38c2396a5f..41743fd820c 100644
--- a/config/metrics/counts_7d/20210901223528_p_ci_templates_implicit_jobs_load_performance_testing_weekly.yml
+++ b/config/metrics/counts_7d/20210901223528_p_ci_templates_implicit_jobs_load_performance_testing_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_load_performance_testing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223658_p_ci_templates_implicit_jobs_browser_performance_testing_latest_weekly.yml b/config/metrics/counts_7d/20210901223658_p_ci_templates_implicit_jobs_browser_performance_testing_latest_weekly.yml
index 2c1aee4d4ca..9fe2fcedc8f 100644
--- a/config/metrics/counts_7d/20210901223658_p_ci_templates_implicit_jobs_browser_performance_testing_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210901223658_p_ci_templates_implicit_jobs_browser_performance_testing_latest_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_browser_performance_testing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223707_p_ci_templates_implicit_jobs_cf_provision_weekly.yml b/config/metrics/counts_7d/20210901223707_p_ci_templates_implicit_jobs_cf_provision_weekly.yml
index d325ed2644f..4bbe644cf05 100644
--- a/config/metrics/counts_7d/20210901223707_p_ci_templates_implicit_jobs_cf_provision_weekly.yml
+++ b/config/metrics/counts_7d/20210901223707_p_ci_templates_implicit_jobs_cf_provision_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_cf_provision
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223716_p_ci_templates_implicit_jobs_build_latest_weekly.yml b/config/metrics/counts_7d/20210901223716_p_ci_templates_implicit_jobs_build_latest_weekly.yml
index 8936d4ce21a..8b997583966 100644
--- a/config/metrics/counts_7d/20210901223716_p_ci_templates_implicit_jobs_build_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210901223716_p_ci_templates_implicit_jobs_build_latest_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_build_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223725_p_ci_templates_implicit_security_dast_runner_validation_weekly.yml b/config/metrics/counts_7d/20210901223725_p_ci_templates_implicit_security_dast_runner_validation_weekly.yml
index c0d3299d9bf..2b9e53aec36 100644
--- a/config/metrics/counts_7d/20210901223725_p_ci_templates_implicit_security_dast_runner_validation_weekly.yml
+++ b/config/metrics/counts_7d/20210901223725_p_ci_templates_implicit_security_dast_runner_validation_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_runner_validation
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223735_p_ci_templates_implicit_security_dast_on_demand_scan_weekly.yml b/config/metrics/counts_7d/20210901223735_p_ci_templates_implicit_security_dast_on_demand_scan_weekly.yml
index 8d39fc698a8..d45893a2022 100644
--- a/config/metrics/counts_7d/20210901223735_p_ci_templates_implicit_security_dast_on_demand_scan_weekly.yml
+++ b/config/metrics/counts_7d/20210901223735_p_ci_templates_implicit_security_dast_on_demand_scan_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_on_demand_scan
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223753_p_ci_templates_implicit_security_coverage_fuzzing_weekly.yml b/config/metrics/counts_7d/20210901223753_p_ci_templates_implicit_security_coverage_fuzzing_weekly.yml
index 97a44953b1e..952afc72aec 100644
--- a/config/metrics/counts_7d/20210901223753_p_ci_templates_implicit_security_coverage_fuzzing_weekly.yml
+++ b/config/metrics/counts_7d/20210901223753_p_ci_templates_implicit_security_coverage_fuzzing_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_coverage_fuzzing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223802_p_ci_templates_implicit_security_api_fuzzing_latest_weekly.yml b/config/metrics/counts_7d/20210901223802_p_ci_templates_implicit_security_api_fuzzing_latest_weekly.yml
index 4f4e3a05b4d..e08cb7f719f 100644
--- a/config/metrics/counts_7d/20210901223802_p_ci_templates_implicit_security_api_fuzzing_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210901223802_p_ci_templates_implicit_security_api_fuzzing_latest_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_api_fuzzing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223811_p_ci_templates_implicit_security_secure_binaries_weekly.yml b/config/metrics/counts_7d/20210901223811_p_ci_templates_implicit_security_secure_binaries_weekly.yml
index 08f8340acbd..5b2d521fb07 100644
--- a/config/metrics/counts_7d/20210901223811_p_ci_templates_implicit_security_secure_binaries_weekly.yml
+++ b/config/metrics/counts_7d/20210901223811_p_ci_templates_implicit_security_secure_binaries_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_secure_binaries
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223819_p_ci_templates_implicit_security_dast_api_weekly.yml b/config/metrics/counts_7d/20210901223819_p_ci_templates_implicit_security_dast_api_weekly.yml
index b4197326e5c..b10780260cd 100644
--- a/config/metrics/counts_7d/20210901223819_p_ci_templates_implicit_security_dast_api_weekly.yml
+++ b/config/metrics/counts_7d/20210901223819_p_ci_templates_implicit_security_dast_api_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_api
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223837_p_ci_templates_implicit_security_dast_latest_weekly.yml b/config/metrics/counts_7d/20210901223837_p_ci_templates_implicit_security_dast_latest_weekly.yml
index 2c804015f3b..37d4e3760d0 100644
--- a/config/metrics/counts_7d/20210901223837_p_ci_templates_implicit_security_dast_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210901223837_p_ci_templates_implicit_security_dast_latest_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210901223854_p_ci_templates_implicit_security_api_fuzzing_weekly.yml b/config/metrics/counts_7d/20210901223854_p_ci_templates_implicit_security_api_fuzzing_weekly.yml
index f79388fdfc5..450574ee2ef 100644
--- a/config/metrics/counts_7d/20210901223854_p_ci_templates_implicit_security_api_fuzzing_weekly.yml
+++ b/config/metrics/counts_7d/20210901223854_p_ci_templates_implicit_security_api_fuzzing_weekly.yml
@@ -6,7 +6,7 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_api_fuzzing
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20210929102731_p_ci_templates_implicit_jobs_deploy_latest_weekly.yml b/config/metrics/counts_7d/20210929102731_p_ci_templates_implicit_jobs_deploy_latest_weekly.yml
index f4d0ac7ff98..5f107f95479 100644
--- a/config/metrics/counts_7d/20210929102731_p_ci_templates_implicit_jobs_deploy_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210929102731_p_ci_templates_implicit_jobs_deploy_latest_weekly.yml
@@ -6,8 +6,8 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
-milestone: "14.4"
+status: removed
+milestone: '14.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71157
time_frame: 7d
data_source: redis_hll
@@ -22,4 +22,6 @@ tier:
- ultimate
options:
events:
- - p_ci_templates_implicit_jobs_deploy_latest
+ - p_ci_templates_implicit_jobs_deploy_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml
index fd4b22fd1e5..c27caf6248e 100644
--- a/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml
+++ b/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml
@@ -3,11 +3,11 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_
description: Count of pipelines with implicit runs using the latest SAST IaC template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "14.5"
+status: removed
+milestone: '14.5'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
time_frame: 7d
data_source: redis_hll
@@ -24,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_sast_iac_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml
index 9b71c66ca77..5f91c203d6f 100644
--- a/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml
+++ b/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml
@@ -3,11 +3,11 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_
description: Count of pipelines with implicit runs using the latest SAST IaC template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "14.5"
+status: removed
+milestone: '14.5'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
time_frame: 7d
data_source: redis_hll
@@ -24,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
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
index 8d0415dedd2..8b9b17b3519 100644
--- 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
@@ -6,7 +6,7 @@ product_stage: secure
product_group: dynamic_analysis
product_category: dynamic_application_security_testing
value_type: number
-status: active
+status: removed
milestone: '14.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
time_frame: 7d
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_dast_api_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220222215851_xmau_plan.yml b/config/metrics/counts_7d/20220222215851_xmau_plan.yml
index 170b1c595de..77325a205ee 100644
--- a/config/metrics/counts_7d/20220222215851_xmau_plan.yml
+++ b/config/metrics/counts_7d/20220222215851_xmau_plan.yml
@@ -9,8 +9,19 @@ value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
-time_frame: 7d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+time_frame: 7d
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_7d/20220222215852_xmau_project_management.yml b/config/metrics/counts_7d/20220222215852_xmau_project_management.yml
index 061ee13722b..c7e712cf92a 100644
--- a/config/metrics/counts_7d/20220222215852_xmau_project_management.yml
+++ b/config/metrics/counts_7d/20220222215852_xmau_project_management.yml
@@ -10,7 +10,18 @@ status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 7d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_7d/20220222215855_users_work_items.yml b/config/metrics/counts_7d/20220222215855_users_work_items.yml
index b749a7c9430..0985f38c83b 100644
--- a/config/metrics/counts_7d/20220222215855_users_work_items.yml
+++ b/config/metrics/counts_7d/20220222215855_users_work_items.yml
@@ -10,7 +10,18 @@ status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 7d
+instrumentation_class: WorkItemsActivityAggregatedMetric
data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - users_creating_work_items
+ - users_updating_work_item_title
+ - users_updating_work_item_dates
+ - users_updating_work_item_labels
+ - users_updating_work_item_iteration
data_category: optional
distribution:
- ce
diff --git a/config/metrics/counts_7d/20220310213315_p_ci_templates_implicit_jobs_secret_detection_latest_weekly.yml b/config/metrics/counts_7d/20220310213315_p_ci_templates_implicit_jobs_secret_detection_latest_weekly.yml
index 85e32e385fb..75b4e85a2db 100644
--- a/config/metrics/counts_7d/20220310213315_p_ci_templates_implicit_jobs_secret_detection_latest_weekly.yml
+++ b/config/metrics/counts_7d/20220310213315_p_ci_templates_implicit_jobs_secret_detection_latest_weekly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_secret_detection_latest_weekly
-description: Weekly counts for implicit use of Secret Detection CI Latest template (Jobs folder)
+description: Weekly counts for implicit use of Secret Detection CI Latest template
+ (Jobs folder)
product_section: sec
product_stage: secure
product_group: static_analysis
product_category: static_application_security_testing
value_type: number
-status: active
-milestone: "15.0"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847'
+status: removed
+milestone: '15.0'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847
time_frame: 7d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_secret_detection_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220310213743_p_ci_templates_implicit_jobs_sast_latest_weekly.yml b/config/metrics/counts_7d/20220310213743_p_ci_templates_implicit_jobs_sast_latest_weekly.yml
index 61d3ceff055..81ee9ea1a68 100644
--- a/config/metrics/counts_7d/20220310213743_p_ci_templates_implicit_jobs_sast_latest_weekly.yml
+++ b/config/metrics/counts_7d/20220310213743_p_ci_templates_implicit_jobs_sast_latest_weekly.yml
@@ -6,9 +6,9 @@ product_stage: secure
product_group: static_analysis
product_category: static_application_security_testing
value_type: number
-status: active
-milestone: "15.0"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847'
+status: removed
+milestone: '15.0'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81847
time_frame: 7d
data_source: redis_hll
data_category: optional
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220315223220_error_tracking_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20220315223220_error_tracking_total_unique_counts_weekly.yml
index 851fd6d0925..e40a7d4cba6 100644
--- a/config/metrics/counts_7d/20220315223220_error_tracking_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20220315223220_error_tracking_total_unique_counts_weekly.yml
@@ -12,8 +12,11 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82543
time_frame: 7d
data_source: redis_hll
data_category: optional
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- error_tracking_view_list
- error_tracking_view_details
diff --git a/config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml
index 964297bde96..9146e2c7c8b 100644
--- a/config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml
@@ -13,8 +13,11 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90205
time_frame: 7d
data_source: redis_hll
data_category: optional
-instrumentation_class: RedisHLLMetric
+instrumentation_class: AggregatedMetric
options:
+ aggregate:
+ operator: OR
+ attribute: user_id
events:
- incident_management_timeline_event_created
- incident_management_timeline_event_edited
diff --git a/config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml b/config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml
index 4f3cfcc25d4..a234b29127d 100644
--- a/config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml
+++ b/config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml
@@ -6,8 +6,8 @@ product_stage: secure
product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.3"
+status: removed
+milestone: '15.3'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
time_frame: 7d
data_source: redis_hll
@@ -23,3 +23,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_fortify_fod_sast
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220906065645_incident_management_timeline_event_created_weekly.yml b/config/metrics/counts_7d/20220906065645_incident_management_timeline_event_created_weekly.yml
new file mode 100644
index 00000000000..e249dade5ca
--- /dev/null
+++ b/config/metrics/counts_7d/20220906065645_incident_management_timeline_event_created_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_created_weekly
+description: Count of unique users created timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_created
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220906070351_incident_management_timeline_event_edited_weekly.yml b/config/metrics/counts_7d/20220906070351_incident_management_timeline_event_edited_weekly.yml
new file mode 100644
index 00000000000..82be8c1d859
--- /dev/null
+++ b/config/metrics/counts_7d/20220906070351_incident_management_timeline_event_edited_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_edited_weekly
+description: Count of unique users edited timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_edited
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20220906070629_incident_management_timeline_event_deleted_weekly.yml b/config/metrics/counts_7d/20220906070629_incident_management_timeline_event_deleted_weekly.yml
new file mode 100644
index 00000000000..dbe8ad10298
--- /dev/null
+++ b/config/metrics/counts_7d/20220906070629_incident_management_timeline_event_deleted_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.incident_management.incident_management_timeline_event_deleted_weekly
+description: Count of unique users deleted timeline events
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97006"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - incident_management_timeline_event_deleted
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20220907032041_i_quickactions_ready_weekly.yml b/config/metrics/counts_7d/20220907032041_i_quickactions_ready_weekly.yml
new file mode 100644
index 00000000000..4e1ec52769e
--- /dev/null
+++ b/config/metrics/counts_7d/20220907032041_i_quickactions_ready_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.project_management.i_quickactions_ready_weekly
+description: Count of WAU using the `/ready` quick action
+product_section: dev
+product_stage: plan
+product_group: project_management
+product_category: issue_tracking
+value_type: number
+data_source: redis_hll
+status: active
+milestone: "15.4"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97115"
+time_frame: 7d
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_ready
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220907084343_p_ci_templates_implicit_security_sast_iac_weekly.yml b/config/metrics/counts_7d/20220907084343_p_ci_templates_implicit_security_sast_iac_weekly.yml
index c8e4c285492..5a07581ac29 100644
--- a/config/metrics/counts_7d/20220907084343_p_ci_templates_implicit_security_sast_iac_weekly.yml
+++ b/config/metrics/counts_7d/20220907084343_p_ci_templates_implicit_security_sast_iac_weekly.yml
@@ -1,13 +1,14 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_weekly
-description: Count of pipelines with implicit SAST runs using the stable SAST IaC template
+description: Count of pipelines with implicit SAST runs using the stable SAST IaC
+ template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.4"
+status: removed
+milestone: '15.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86275
time_frame: 7d
data_source: redis_hll
@@ -24,3 +25,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220907102710_p_ci_templates_implicit_jobs_sast_iac_weekly.yml b/config/metrics/counts_7d/20220907102710_p_ci_templates_implicit_jobs_sast_iac_weekly.yml
index faf4df4b772..07ad434778f 100644
--- a/config/metrics/counts_7d/20220907102710_p_ci_templates_implicit_jobs_sast_iac_weekly.yml
+++ b/config/metrics/counts_7d/20220907102710_p_ci_templates_implicit_jobs_sast_iac_weekly.yml
@@ -1,13 +1,14 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_weekly
-description: Count of pipelines with implicit SAST jobs using the stable SAST IaC template
+description: Count of pipelines with implicit SAST jobs using the stable SAST IaC
+ template
product_section: sec
product_stage: secure
-product_group: "static_analysis"
+product_group: static_analysis
product_category: SAST
value_type: number
-status: active
-milestone: "15.4"
+status: removed
+milestone: '15.4'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86275
time_frame: 7d
data_source: redis_hll
@@ -24,3 +25,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_sast_iac
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml
index 243d24bcf50..baa9796fff0 100644
--- a/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml
+++ b/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly
-description: Weekly counts for implicit Dependency Scanning CI Latest template (Jobs folder)
+description: Weekly counts for implicit Dependency Scanning CI Latest template (Jobs
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: dependency_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 7d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_dependency_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml
index 8fdd6c15c1d..cf4727f2da4 100644
--- a/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml
+++ b/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_latest_weekly
-description: Weekly counts for implicit License Scanning CI Latest template (Jobs folder)
+description: Weekly counts for implicit License Scanning CI Latest template (Jobs
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: license_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 7d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_jobs_license_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml
index c3818fb819c..e4901cfa05a 100644
--- a/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml
+++ b/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml
@@ -1,14 +1,15 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_container_scanning_latest_weekly
-description: Weekly counts for implicit Container Scanning CI Latest template (Security folder)
+description: Weekly counts for implicit Container Scanning CI Latest template (Security
+ folder)
product_section: sec
product_stage: secure
product_group: composition_analysis
product_category: container_scanning
value_type: number
-status: active
-milestone: "15.4"
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
+status: removed
+milestone: '15.4'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323
time_frame: 7d
data_source: redis_hll
data_category: optional
@@ -23,3 +24,5 @@ tier:
options:
events:
- p_ci_templates_implicit_security_container_scanning_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220913225013_p_ci_templates_security_coverage_fuzzing_latest_weekly.yml b/config/metrics/counts_7d/20220913225013_p_ci_templates_security_coverage_fuzzing_latest_weekly.yml
new file mode 100644
index 00000000000..768390de49d
--- /dev/null
+++ b/config/metrics/counts_7d/20220913225013_p_ci_templates_security_coverage_fuzzing_latest_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_coverage_fuzzing_latest_weekly
+description: Weekly counts for Coverage Fuzzing 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: "15.5"
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97886'
+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_coverage_fuzzing_latest
diff --git a/config/metrics/counts_7d/20220913225257_p_ci_templates_implicit_security_coverage_fuzzing_latest_weekly.yml b/config/metrics/counts_7d/20220913225257_p_ci_templates_implicit_security_coverage_fuzzing_latest_weekly.yml
new file mode 100644
index 00000000000..ea231267825
--- /dev/null
+++ b/config/metrics/counts_7d/20220913225257_p_ci_templates_implicit_security_coverage_fuzzing_latest_weekly.yml
@@ -0,0 +1,27 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_coverage_fuzzing_latest_weekly
+description: Weekly counts for implicit Coverage Fuzzing latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: removed
+milestone: '15.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97886
+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_coverage_fuzzing_latest
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90163
+milestone_removed: '15.5'
diff --git a/config/metrics/counts_7d/20220922042528_users_updating_work_item_iteration_weekly.yml b/config/metrics/counts_7d/20220922042528_users_updating_work_item_iteration_weekly.yml
new file mode 100644
index 00000000000..aad949867cf
--- /dev/null
+++ b/config/metrics/counts_7d/20220922042528_users_updating_work_item_iteration_weekly.yml
@@ -0,0 +1,24 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_iteration_weekly
+description: Unique users updating a work item's iteration
+product_section: team planning
+product_stage: dev
+product_group: plan
+product_category: project_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98539
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_iteration
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20221006065521_i_quickactions_link_weekly.yml b/config/metrics/counts_7d/20221006065521_i_quickactions_link_weekly.yml
new file mode 100644
index 00000000000..c136840fccf
--- /dev/null
+++ b/config/metrics/counts_7d/20221006065521_i_quickactions_link_weekly.yml
@@ -0,0 +1,26 @@
+key_path: redis_hll_counters.quickactions.i_quickactions_link_weekly
+name: quickactions_timeline_weekly
+description: Count of WAU using the `/link` quick action
+product_section: ops
+product_stage: monitor
+product_group: respond
+product_category: incident_management
+value_type: number
+status: active
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99963
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_link
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20221007010950_users_updating_work_item_labels_weekly.yml b/config/metrics/counts_7d/20221007010950_users_updating_work_item_labels_weekly.yml
new file mode 100644
index 00000000000..55e651328e6
--- /dev/null
+++ b/config/metrics/counts_7d/20221007010950_users_updating_work_item_labels_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_labels_weekly
+description: Unique users updating a work item's labels
+product_category: team_planning
+product_section: dev
+product_stage: plan
+product_group: project_management
+value_type: number
+status: active
+milestone: '15.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100485
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_labels
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml b/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
index d7b16d01d8b..8f3749cc481 100644
--- a/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
+++ b/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: cycle_analytics
+ event: views
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216175041_merge_request_comment.yml b/config/metrics/counts_all/20210216175041_merge_request_comment.yml
index 2c060e57c49..3713aafe259 100644
--- a/config/metrics/counts_all/20210216175041_merge_request_comment.yml
+++ b/config/metrics/counts_all/20210216175041_merge_request_comment.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: note
+ event: create_mergerequest
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
index fb8c3b61355..7e82df12c95 100644
--- a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
+++ b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
@@ -4,9 +4,9 @@ key_path: counts.ingress_modsecurity_packets_processed
description: Cumulative count of packets processed by ModSecurity since Usage Ping
was last reported
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
index ba3575f8b0b..c034d791224 100644
--- a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
+++ b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
@@ -4,9 +4,9 @@ key_path: counts.ingress_modsecurity_packets_anomalous
description: Cumulative count of packets identified as anomalous by ModSecurity since
Usage Ping was last reported
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216175446_network_policy_forwards.yml b/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
index 92774a9aa54..cbdd3ce0261 100644
--- a/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
+++ b/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
@@ -4,9 +4,9 @@ key_path: counts.network_policy_forwards
description: Cumulative count of packets forwarded by Cilium (Container Network Security)
since Usage Ping was last reported
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: container_network_security
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: container_network_security_category_was_removed
value_type: number
status: removed
removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86351
diff --git a/config/metrics/counts_all/20210216175448_network_policy_drops.yml b/config/metrics/counts_all/20210216175448_network_policy_drops.yml
index 10b6a79205b..2b1dc57255d 100644
--- a/config/metrics/counts_all/20210216175448_network_policy_drops.yml
+++ b/config/metrics/counts_all/20210216175448_network_policy_drops.yml
@@ -4,9 +4,9 @@ key_path: counts.network_policy_drops
description: Cumulative count of packets dropped by Cilium (Container Network Security)
since Usage Ping was last reported
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: container_network_security
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: container_network_security_category_was_removed
value_type: number
status: removed
removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86351
diff --git a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
index 3255aa90e63..1dce2aa9922 100644
--- a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
+++ b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
@@ -3,9 +3,9 @@ data_category: operational
key_path: counts.ingress_modsecurity_logging
description: Whether or not ModSecurity is set to logging mode
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
index 4589c483ae2..2b1a487838e 100644
--- a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
+++ b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
@@ -3,9 +3,9 @@ data_category: operational
key_path: counts.ingress_modsecurity_blocking
description: Whether or not ModSecurity is set to blocking mode
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
index 9213bbcefb7..8794bfec930 100644
--- a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
+++ b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
@@ -3,9 +3,9 @@ data_category: operational
key_path: counts.ingress_modsecurity_disabled
description: Whether or not ModSecurity is disabled within Ingress
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
index 659a3b66a8b..9781fa90536 100644
--- a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
+++ b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
@@ -3,9 +3,9 @@ data_category: operational
key_path: counts.ingress_modsecurity_not_installed
description: Whether or not ModSecurity has not been installed into the cluster
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: number
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/counts_all/20210216180253_snippet_comment.yml b/config/metrics/counts_all/20210216180253_snippet_comment.yml
index f01f62f361d..03e45717517 100644
--- a/config/metrics/counts_all/20210216180253_snippet_comment.yml
+++ b/config/metrics/counts_all/20210216180253_snippet_comment.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: note
+ event: create_snippet
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180255_snippet_create.yml b/config/metrics/counts_all/20210216180255_snippet_create.yml
index 7cea58039e1..9c69c99d694 100644
--- a/config/metrics/counts_all/20210216180255_snippet_create.yml
+++ b/config/metrics/counts_all/20210216180255_snippet_create.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: snippet
+ event: create
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180257_snippet_update.yml b/config/metrics/counts_all/20210216180257_snippet_update.yml
index 5cb80f5e830..d8fee7daa90 100644
--- a/config/metrics/counts_all/20210216180257_snippet_update.yml
+++ b/config/metrics/counts_all/20210216180257_snippet_update.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: snippet
+ event: update
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180413_all_searches.yml b/config/metrics/counts_all/20210216180413_all_searches.yml
index 2f45e0c6e20..abd2e31b8d8 100644
--- a/config/metrics/counts_all/20210216180413_all_searches.yml
+++ b/config/metrics/counts_all/20210216180413_all_searches.yml
@@ -11,6 +11,11 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: null
+ event: all_searches_count
+ include_usage_prefix: false
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180414_navbar_searches.yml b/config/metrics/counts_all/20210216180414_navbar_searches.yml
index b2af79bb43c..9ba086ed271 100644
--- a/config/metrics/counts_all/20210216180414_navbar_searches.yml
+++ b/config/metrics/counts_all/20210216180414_navbar_searches.yml
@@ -11,6 +11,11 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: null
+ event: navbar_searches_count
+ include_usage_prefix: false
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180734_wiki_pages_create.yml b/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
index 675a9db7a7b..08121468e38 100644
--- a/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
+++ b/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: wiki_pages
+ event: create
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180736_wiki_pages_update.yml b/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
index c985d876c96..ffb2ed4227c 100644
--- a/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
+++ b/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: wiki_pages
+ event: update
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml b/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
index 6ac0825996c..75c2d13d744 100644
--- a/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
+++ b/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: wiki_pages
+ event: delete
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
index 1d71cc632c4..c2294650494 100644
--- a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
+++ b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
@@ -10,6 +10,7 @@ value_type: number
status: active
time_frame: all
data_source: database
+instrumentation_class: DistinctCountProjectsWithExpirationPolicyDisabledMetric
distribution:
- ee
- ce
diff --git a/config/metrics/counts_all/20210216182004_commit_comment.yml b/config/metrics/counts_all/20210216182004_commit_comment.yml
index 7755fec3a2c..6de9b8476d4 100644
--- a/config/metrics/counts_all/20210216182004_commit_comment.yml
+++ b/config/metrics/counts_all/20210216182004_commit_comment.yml
@@ -10,6 +10,10 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: note
+ event: create_commit
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216183023_wiki_pages_view.yml b/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
index 059087a406d..278524f6d79 100644
--- a/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
+++ b/config/metrics/counts_all/20210216183023_wiki_pages_view.yml
@@ -12,6 +12,10 @@ milestone: "13.3"
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38784"
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: wiki_pages
+ event: view
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
index 185e8a199b6..fcb2be99fab 100644
--- a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
+++ b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
@@ -12,6 +12,10 @@ milestone: '13.12'
introduced_by_url:
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: kubernetes_agent
+ event: k8s_api_proxy_request
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml b/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml
index 79d9f062999..e84cad9b9a9 100644
--- a/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml
+++ b/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_view
+ event: view
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml b/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml
index b4887bbe219..92c5605f5fa 100644
--- a/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml
+++ b/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_full_report_clicked
+ event: full_report_clicked
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml b/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml
index 1898fa971fa..6501152e564 100644
--- a/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml
+++ b/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_expand
+ event: expand
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml b/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml
index 91cd4d7a232..4be50d63e30 100644
--- a/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml
+++ b/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_expand_success
+ event: expand_success
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml b/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml
index 970d843c58e..d5e36376b4a 100644
--- a/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml
+++ b/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_expand_warning
+ event: expand_warning
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml b/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml
index 9b7c5c61602..fbb2684fa11 100644
--- a/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml
+++ b/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_test_summary_count_expand_failed
+ event: expand_failed
+ widget: test_summary
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml b/config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml
index 215bf8f0a1b..235b5ed838a 100644
--- a/config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml
+++ b/config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_view
+ event: view
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml b/config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml
index a8792444287..25f62dd0184 100644
--- a/config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml
+++ b/config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_full_report_clicked
+ event: full_report_clicked
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml b/config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml
index d5679b65533..a747a6252e9 100644
--- a/config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml
+++ b/config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_expand
+ event: expand
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml b/config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml
index 25ef6ab85ca..9d1b51a2bce 100644
--- a/config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml
+++ b/config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_expand_success
+ event: expand_success
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml b/config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml
index 7939fb8ac7f..3d98561d8eb 100644
--- a/config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml
+++ b/config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_expand_warning
+ event: expand_warning
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml b/config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml
index 9e348eb8e27..b3312480433 100644
--- a/config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml
+++ b/config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_accessibility_count_expand_failed
+ event: expand_failed
+ widget: accessibility
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml b/config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml
index 1687d346e34..918ff9b362c 100644
--- a/config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml
+++ b/config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_view
+ event: view
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml b/config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml
index 21ff87b8e39..1fb7bbc070b 100644
--- a/config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml
+++ b/config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_full_report_clicked
+ event: full_report_clicked
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml b/config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml
index 49123b462d9..65315c78f2b 100644
--- a/config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml
+++ b/config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_expand
+ event: expand
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml b/config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml
index 8b349e04d21..a32d388e58d 100644
--- a/config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml
+++ b/config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_expand_success
+ event: expand_success
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml b/config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml
index e94c6999711..7287000128e 100644
--- a/config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml
+++ b/config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_expand_warning
+ event: expand_warning
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml b/config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml
index 5e49393afff..1e4d668ba98 100644
--- a/config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml
+++ b/config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_code_quality_count_expand_failed
+ event: expand_failed
+ widget: code_quality
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml b/config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml
index f523b91b5d9..4f3c66162c3 100644
--- a/config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml
+++ b/config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_view
+ event: view
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml b/config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml
index 53eb5770ed5..f98b80e3741 100644
--- a/config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml
+++ b/config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_full_report_clicked
+ event: full_report_clicked
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml b/config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml
index 0406b84d457..9d4d25d5514 100644
--- a/config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml
+++ b/config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_expand
+ event: expand
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml b/config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml
index c497758b543..92f9e149377 100644
--- a/config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml
+++ b/config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_expand_success
+ event: expand_success
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml b/config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml
index 1a0a112dc89..aaece878b05 100644
--- a/config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml
+++ b/config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_expand_warning
+ event: expand_warning
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml b/config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml
index 3e1ac7db1d5..1a382cc30ac 100644
--- a/config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml
+++ b/config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_terraform_count_expand_failed
+ event: expand_failed
+ widget: terraform
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml b/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml
index 3542f4fd8ac..39d1bea3536 100644
--- a/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml
+++ b/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_view
+ event: view
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml b/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml
index 580d0d4dff3..1258a40add0 100644
--- a/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml
+++ b/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_full_report_clicked
+ event: full_report_clicked
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml b/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml
index 1829e1c87c0..07a8ac69ae1 100644
--- a/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml
+++ b/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_expand
+ event: expand
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml b/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml
index 4a8f35a7c5b..2785964ed25 100644
--- a/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml
+++ b/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_expand_success
+ event: expand_success
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml b/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml
index 1ebc20fca26..eabef1927c6 100644
--- a/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml
+++ b/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_expand_warning
+ event: expand_warning
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml b/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml
index 7fe8263a53e..39d252fa1b3 100644
--- a/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml
+++ b/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml
@@ -12,9 +12,10 @@ introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
time_frame: all
data_source: redis
data_category: optional
+instrumentation_class: MergeRequestWidgetExtensionMetric
options:
- events:
- - i_code_review_merge_request_widget_license_compliance_count_expand_failed
+ event: expand_failed
+ widget: license_compliance
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20220912145754_gitlab_for_jira_app_direct_installations.yml b/config/metrics/counts_all/20220912145754_gitlab_for_jira_app_direct_installations.yml
new file mode 100644
index 00000000000..a538e097254
--- /dev/null
+++ b/config/metrics/counts_all/20220912145754_gitlab_for_jira_app_direct_installations.yml
@@ -0,0 +1,23 @@
+---
+key_path: counts.gitlab_for_jira_app_direct_installations
+description: Count active Jira Cloud direct installations
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+data_category: optional
+instrumentation_class: GitlabForJiraAppDirectInstallationsCountMetric
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97674
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20220913083454_gitlab_for_jira_app_proxy_installations.yml b/config/metrics/counts_all/20220913083454_gitlab_for_jira_app_proxy_installations.yml
new file mode 100644
index 00000000000..fcab9fd1794
--- /dev/null
+++ b/config/metrics/counts_all/20220913083454_gitlab_for_jira_app_proxy_installations.yml
@@ -0,0 +1,23 @@
+---
+key_path: counts.gitlab_for_jira_app_proxy_installations
+description: Count active Jira Cloud installations that are using GitLab as a proxy
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+data_category: optional
+instrumentation_class: GitlabForJiraAppProxyInstallationsCountMetric
+milestone: "15.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97674
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
index afd8478ae1c..7653505a19f 100644
--- a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
+++ b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
@@ -3,9 +3,9 @@ data_category: operational
key_path: ingress_modsecurity_enabled
description: Whether or not ModSecurity is enabled within Ingress
product_section: sec
-product_stage: protect
-product_group: container_security
-product_category: web_firewall
+product_stage: protect_stage_was_removed
+product_group: container_security_group_was_removed
+product_category: web_firewall_category_was_removed
value_type: boolean
status: removed
milestone_removed: 14.0
diff --git a/config/metrics/settings/20211201012652_flavor.yml b/config/metrics/settings/20211201012652_flavor.yml
index 8148ad7ad89..01c73de57c0 100644
--- a/config/metrics/settings/20211201012652_flavor.yml
+++ b/config/metrics/settings/20211201012652_flavor.yml
@@ -3,7 +3,7 @@ key_path: database.flavor
description: What PostgreSQL flavor is being used. Possible values are
"Amazon Aurora PostgreSQL", "PostgreSQL on Amazon RDS", "Cloud SQL for PostgreSQL",
"Azure Database for PostgreSQL - Single Server", "Azure Database for PostgreSQL - Flexible Server",
- or "null".
+ "AlloyDB for PostgreSQL", or "null".
product_section: enablement
product_stage: enablement
product_group: database
diff --git a/config/object_store_settings.rb b/config/object_store_settings.rb
index e55032d3987..173ce5a5982 100644
--- a/config/object_store_settings.rb
+++ b/config/object_store_settings.rb
@@ -3,7 +3,7 @@
# Set default values for object_store settings
class ObjectStoreSettings
SUPPORTED_TYPES = %w(artifacts external_diffs lfs uploads packages dependency_proxy terraform_state pages secure_files).freeze
- ALLOWED_OBJECT_STORE_OVERRIDES = %w(bucket enabled proxy_download).freeze
+ ALLOWED_OBJECT_STORE_OVERRIDES = %w(bucket enabled proxy_download cdn).freeze
# To ensure the one Workhorse credential matches the Rails config, we
# enforce consolidated settings on those accelerated
diff --git a/config/open_api.yml b/config/open_api.yml
new file mode 100644
index 00000000000..8415a6bff3d
--- /dev/null
+++ b/config/open_api.yml
@@ -0,0 +1,18 @@
+metadata:
+ doc_version: v4
+ info:
+ title: GitLab API
+ termsOfService: https://about.gitlab.com/terms/
+ host: gitlab.com
+ security_definitions:
+ access_token_header:
+ type: apiKey
+ name: PRIVATE-TOKEN
+ in: header
+ access_token_query:
+ type: apiKey
+ name: private_token
+ in: query
+ tags:
+ - name: metadata
+ description: Operations related to metadata of the GitLab instance
diff --git a/config/plugins/monaco_webpack.js b/config/plugins/monaco_webpack.js
deleted file mode 100644
index 01d88ca37db..00000000000
--- a/config/plugins/monaco_webpack.js
+++ /dev/null
@@ -1,17 +0,0 @@
-const { languagesArr } = require('monaco-editor-webpack-plugin/out/languages');
-
-// monaco-yaml library doesn't play so well with monaco-editor-webpack-plugin
-// so the only way to include its workers is by patching the list of languages
-// in monaco-editor-webpack-plugin and adding support for yaml workers. This is
-// a known issue in the library and this workaround was suggested here:
-// https://github.com/pengx17/monaco-yaml/issues/20
-
-const yamlLang = languagesArr.find((t) => t.label === 'yaml');
-
-yamlLang.entry = [yamlLang.entry, '../../monaco-yaml/lib/esm/monaco.contribution'];
-yamlLang.worker = {
- id: 'vs/language/yaml/yamlWorker',
- entry: '../../monaco-yaml/lib/esm/yaml.worker.js',
-};
-
-module.exports = require('monaco-editor-webpack-plugin');
diff --git a/config/routes.rb b/config/routes.rb
index 704405bbcbd..28c08e9bbe7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -70,11 +70,6 @@ InitializerConnections.with_disabled_database_connections do
Gitlab.ee do
resource :company, only: [:new, :create], controller: 'company'
-
- # legacy - to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/371996
- get 'groups/new', to: redirect('users/sign_up/groups_projects/new')
- get 'projects/new', to: redirect('users/sign_up/groups_projects/new')
-
resources :groups_projects, only: [:new, :create] do
collection do
post :import
@@ -141,28 +136,6 @@ InitializerConnections.with_disabled_database_connections do
get 'runner_setup/platforms' => 'runner_setup#platforms'
- # Boards resources shared between group and projects
- resources :boards, only: [] do
- resources :lists, module: :boards, only: [:index, :create, :update, :destroy] do
- collection do
- post :generate
- end
-
- resources :issues, only: [:index, :create, :update]
- end
-
- resources :issues, module: :boards, only: [:index, :update] do
- collection do
- put :bulk_move, format: :json
- end
- end
-
- Gitlab.ee do
- resources :users, module: :boards, only: [:index]
- resources :milestones, module: :boards, only: [:index]
- end
- end
-
get 'acme-challenge/' => 'acme_challenges#show'
scope :ide, as: :ide, format: false do
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 228c5776197..004839d22a7 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -23,6 +23,7 @@ namespace :import do
get :status
get :callback
get :realtime_changes
+ post :cancel
end
resource :gitea, only: [:create, :new], controller: :gitea do
@@ -68,6 +69,10 @@ namespace :import do
post :authorize
end
+ resource :github_group, only: [] do
+ get :status
+ end
+
resource :bulk_imports, only: [:create] do
post :configure
get :status
diff --git a/config/routes/jira_connect.rb b/config/routes/jira_connect.rb
index 202d2574ad0..f45f524935a 100644
--- a/config/routes/jira_connect.rb
+++ b/config/routes/jira_connect.rb
@@ -14,6 +14,7 @@ namespace :jira_connect do
resources :subscriptions, only: [:index, :create, :destroy]
resources :branches, only: [:new]
+ resources :public_keys, only: :show
resources :installations, only: [:index] do
collection do
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 79ca13e3d8c..cd9315ba2aa 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -223,11 +223,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :boards, only: [:index, :show, :create, :update, :destroy], constraints: { id: /\d+/ } do
- collection do
- get :recent
- end
- end
+ resources :boards, only: [:index, :show], constraints: { id: /\d+/ }
get 'releases/permalink/latest(/)(*suffix_path)', to: 'releases#latest_permalink', as: :latest_release_permalink, format: false
@@ -368,6 +364,14 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :incidents, only: [:index]
+ namespace :incident_management do
+ resources :timeline_events, only: [] do
+ collection do
+ post :preview_markdown
+ end
+ end
+ end
+
get 'issues/incident/:id' => 'incidents#show', as: :issues_incident
namespace :error_tracking do
diff --git a/config/routes/user.rb b/config/routes/user.rb
index a9e0d7df88f..0c1bc1956a9 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -64,7 +64,6 @@ scope '-/users', module: :users do
end
resources :callouts, only: [:create]
- resources :namespace_callouts, only: [:create]
resources :group_callouts, only: [:create]
resources :project_callouts, only: [:create]
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 4527efe5a1c..eff83e3f3c4 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -93,6 +93,8 @@
- 1
- - ci_job_artifacts_expire_project_build_artifacts
- 1
+- - ci_parse_secure_file_metadata
+ - 1
- - ci_runners_process_runner_version_update
- 1
- - ci_upstream_projects_subscriptions_cleanup
@@ -103,6 +105,8 @@
- 1
- - compliance_management_merge_requests_compliance_violations
- 1
+- - compliance_management_update_default_framework
+ - 1
- - container_repository
- 1
- - create_commit_signature
@@ -175,8 +179,6 @@
- 1
- - error_tracking_issue_link
- 1
-- - experiments_record_conversion_event
- - 1
- - export_csv
- 1
- - external_service_reactive_caching
@@ -319,14 +321,6 @@
- 1
- - migrate_external_diffs
- 1
-- - namespaces_onboarding_issue_created
- - 1
-- - namespaces_onboarding_pipeline_created
- - 1
-- - namespaces_onboarding_progress
- - 1
-- - namespaces_onboarding_user_added
- - 1
- - namespaces_process_sync_events
- 1
- - namespaces_sync_namespace_name
@@ -347,6 +341,14 @@
- 1
- - onboarding_create_learn_gitlab
- 1
+- - onboarding_issue_created
+ - 1
+- - onboarding_pipeline_created
+ - 1
+- - onboarding_progress
+ - 1
+- - onboarding_user_added
+ - 1
- - package_cleanup
- 1
- - package_repositories
@@ -379,6 +381,8 @@
- 5
- - process_commit
- 3
+- - product_analytics_initialize_analytics
+ - 1
- - project_cache
- 1
- - project_destroy
@@ -405,6 +409,8 @@
- 1
- - projects_refresh_build_artifacts_size_statistics
- 1
+- - projects_register_suggested_reviewers_project
+ - 1
- - projects_schedule_bulk_repository_shard_moves
- 1
- - projects_update_repository_storage
@@ -449,12 +455,14 @@
- 1
- - security_auto_fix
- 1
-- - security_findings_delete_by_job_id
- - 1
- - security_orchestration_policy_rule_schedule_namespace
- 1
+- - security_process_scan_result_policy
+ - 1
- - security_scans
- 2
+- - security_scans_purge_by_job_id
+ - 1
- - security_sync_scan_policies
- 1
- - self_monitoring_project_create
@@ -495,6 +503,8 @@
- 1
- - upload_checksum
- 1
+- - vulnerabilities_mark_dropped_as_resolved
+ - 1
- - vulnerabilities_statistics_adjustment
- 1
- - vulnerability_exports_export
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 146e9b48442..05523952769 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -16,17 +16,20 @@ const VueLoaderPlugin = require('vue-loader/lib/plugin');
const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
const VUE_VERSION = require('vue/package.json').version;
+const { ESBuildMinifyPlugin } = require('esbuild-loader');
+
const webpack = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const { StatsWriterPlugin } = require('webpack-stats-plugin');
const WEBPACK_VERSION = require('webpack/package.json').version;
+const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
+const esbuildConfiguration = require('./esbuild.config');
const createIncrementalWebpackCompiler = require('./helpers/incremental_webpack_compiler');
const IS_EE = require('./helpers/is_ee_env');
const IS_JH = require('./helpers/is_jh_env');
const vendorDllHash = require('./helpers/vendor_dll_hash');
-const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
const GraphqlKnownOperationsPlugin = require('./plugins/graphql_known_operations_plugin');
const ROOT_PATH = path.resolve(__dirname, '..');
@@ -40,6 +43,8 @@ const VENDOR_DLL = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_
const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
const IS_DEV_SERVER = process.env.WEBPACK_SERVE === 'true';
+const WEBPACK_USE_ESBUILD_LOADER =
+ process.env.WEBPACK_USE_ESBUILD_LOADER && process.env.WEBPACK_USE_ESBUILD_LOADER !== 'false';
const { DEV_SERVER_HOST, DEV_SERVER_PUBLIC_ADDR } = process.env;
const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10);
@@ -49,9 +54,11 @@ const DEV_SERVER_LIVERELOAD = IS_DEV_SERVER && process.env.DEV_SERVER_LIVERELOAD
const INCREMENTAL_COMPILER_ENABLED =
IS_DEV_SERVER &&
process.env.DEV_SERVER_INCREMENTAL &&
- process.env.DEV_SERVER_INCREMENTAL !== 'false';
+ process.env.DEV_SERVER_INCREMENTAL !== 'false' &&
+ !WEBPACK_USE_ESBUILD_LOADER;
const INCREMENTAL_COMPILER_TTL = Number(process.env.DEV_SERVER_INCREMENTAL_TTL) || Infinity;
-const INCREMENTAL_COMPILER_RECORD_HISTORY = IS_DEV_SERVER && !process.env.CI;
+const INCREMENTAL_COMPILER_RECORD_HISTORY =
+ IS_DEV_SERVER && !process.env.CI && !WEBPACK_USE_ESBUILD_LOADER;
const WEBPACK_REPORT = process.env.WEBPACK_REPORT && process.env.WEBPACK_REPORT !== 'false';
const WEBPACK_MEMORY_TEST =
process.env.WEBPACK_MEMORY_TEST && process.env.WEBPACK_MEMORY_TEST !== 'false';
@@ -250,6 +257,24 @@ if (VENDOR_DLL && !IS_PRODUCTION) {
};
}
+const defaultJsOptions = {
+ cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
+ cacheIdentifier: [
+ process.env.BABEL_ENV || process.env.NODE_ENV || 'development',
+ webpack.version,
+ BABEL_VERSION,
+ BABEL_LOADER_VERSION,
+ // Ensure that changing supported browsers will refresh the cache
+ // in order to not pull in outdated files that import core-js
+ SUPPORTED_BROWSERS_HASH,
+ ].join('|'),
+ cacheCompression: false,
+};
+
+if (WEBPACK_USE_ESBUILD_LOADER) {
+ console.log('esbuild-loader is active');
+}
+
module.exports = {
mode: IS_PRODUCTION ? 'production' : 'development',
@@ -280,23 +305,39 @@ module.exports = {
test: /\.mjs$/,
use: [],
},
- {
+ WEBPACK_USE_ESBUILD_LOADER && {
test: /\.js$/,
exclude: (modulePath) =>
/node_modules|vendor[\\/]assets/.test(modulePath) && !/\.vue\.js/.test(modulePath),
+ loader: 'esbuild-loader',
+ options: esbuildConfiguration,
+ },
+ !WEBPACK_USE_ESBUILD_LOADER && {
+ test: /\.js$/,
+ exclude: (modulePath) =>
+ /node_modules|vendor[\\/]assets/.test(modulePath) && !/\.vue\.js/.test(modulePath),
+ loader: 'babel-loader',
+ options: defaultJsOptions,
+ },
+ WEBPACK_USE_ESBUILD_LOADER && {
+ test: /\.js$/,
+ include: (modulePath) =>
+ /node_modules\/(monaco-worker-manager|monaco-marker-data-provider)\/index\.js/.test(
+ modulePath,
+ ) || /node_modules\/yaml/.test(modulePath),
+ loader: 'esbuild-loader',
+ options: esbuildConfiguration,
+ },
+ !WEBPACK_USE_ESBUILD_LOADER && {
+ test: /\.js$/,
+ include: (modulePath) =>
+ /node_modules\/(monaco-worker-manager|monaco-marker-data-provider)\/index\.js/.test(
+ modulePath,
+ ) || /node_modules\/yaml/.test(modulePath),
loader: 'babel-loader',
options: {
- cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
- cacheIdentifier: [
- process.env.BABEL_ENV || process.env.NODE_ENV || 'development',
- webpack.version,
- BABEL_VERSION,
- BABEL_LOADER_VERSION,
- // Ensure that changing supported browsers will refresh the cache
- // in order to not pull in outdated files that import core-js
- SUPPORTED_BROWSERS_HASH,
- ].join('|'),
- cacheCompression: false,
+ plugins: ['@babel/plugin-proposal-numeric-separator'],
+ ...defaultJsOptions,
},
},
{
@@ -389,7 +430,7 @@ module.exports = {
test: /\.(yml|yaml)$/,
loader: 'raw-loader',
},
- ],
+ ].filter(Boolean),
},
optimization: {
@@ -460,6 +501,9 @@ module.exports = {
},
},
},
+ ...(WEBPACK_USE_ESBUILD_LOADER
+ ? { minimizer: [new ESBuildMinifyPlugin(esbuildConfiguration)] }
+ : {}),
},
plugins: [
@@ -492,6 +536,16 @@ module.exports = {
// automatically configure monaco editor web workers
new MonacoWebpackPlugin({
filename: '[name].[contenthash:8].worker.js',
+ customLanguages: [
+ {
+ label: 'yaml',
+ entry: 'monaco-yaml',
+ worker: {
+ id: 'monaco-yaml/yamlWorker',
+ entry: 'monaco-yaml/yaml.worker',
+ },
+ },
+ ],
}),
new GraphqlKnownOperationsPlugin({ filename: 'graphql_known_operations.yml' }),
@@ -592,7 +646,11 @@ module.exports = {
patterns: [
{
from: path.join(ROOT_PATH, 'node_modules/pdfjs-dist/cmaps/'),
- to: path.join(WEBPACK_OUTPUT_PATH, 'cmaps/'),
+ to: path.join(WEBPACK_OUTPUT_PATH, 'pdfjs/cmaps/'),
+ },
+ {
+ from: path.join(ROOT_PATH, 'node_modules/pdfjs-dist/legacy/build/pdf.worker.min.js'),
+ to: path.join(WEBPACK_OUTPUT_PATH, 'pdfjs/'),
},
{
from: path.join(ROOT_PATH, 'node_modules', SOURCEGRAPH_PACKAGE, '/'),
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index 903607679a4..1300bf16e56 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -26,8 +26,6 @@ module.exports = {
entry: {
vendor: [
'jquery/dist/jquery.slim.js',
- 'pdfjs-dist/build/pdf',
- 'pdfjs-dist/build/pdf.worker.min',
'core-js',
'echarts',
'lodash',
@@ -79,6 +77,8 @@ module.exports = {
https://gitlab.com/gitlab-org/gitlab/-/issues/219353
*/
'chokidar',
+ // We are ignoring esbuild as we want to force a newer version than what esbuild-loader provides
+ 'esbuild',
// We are ignoring ts-jest, because we force a newer version, compatible with our current jest version
'ts-jest',
].join('|'),
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 41c75a9f176..eaa1839c8e5 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -5,7 +5,7 @@ def feature_mr?
end
DOCUMENTATION_UPDATE_MISSING = <<~MSG
-~"feature::addition" and ~"feature::enhancement" merge requests normally have a documentation change. Consider adding a documentation update or confirming the documentation plan with the [Technical Writer counterpart](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+~"feature::addition" and ~"feature::enhancement" merge requests normally have a documentation change. Consider adding a documentation update or confirming the documentation plan with the [Technical Writer counterpart](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
For more information, see:
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index c3f7806069c..ca5a671ef29 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -56,8 +56,8 @@ OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
NOT_AVAILABLE_TEMPLATES = {
default: 'No %{role} available',
product_intelligence: group_not_available_template('#g_product_intelligence', '@gitlab-org/analytics-section/product-intelligence/engineers'),
- integrations_be: group_not_available_template('#g_ecosystem_integrations', '@gitlab-org/ecosystem-stage/integrations'),
- integrations_fe: group_not_available_template('#g_ecosystem_integrations', '@gitlab-org/ecosystem-stage/integrations')
+ integrations_be: group_not_available_template('#g_manage_integrations', '@gitlab-org/manage/integrations'),
+ integrations_fe: group_not_available_template('#g_manage_integrations', '@gitlab-org/manage/integrations')
}.freeze
def note_for_spin_role(spin, role, category)
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index dc9809b20b5..145f7237458 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -55,4 +55,5 @@ end
specs.changed_specs_files.each do |filename|
specs.add_suggestions_for_match_with_array(filename)
+ specs.add_suggestions_for_project_factory_usage(filename)
end
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 5acfac45ca2..41124638509 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,11 +1,12 @@
-- name: "REST and GraphQL API Runner status will not return `paused`"
+- name: "GraphQL API Runner status will not return `paused`"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "16.0" # the milestone when this feature is planned to be removed
removal_date: "2023-04-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: | # Do not modify this line, instead modify the lines below.
- The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 16.0.
+ The GitLab Runner GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 16.0.
+ In a future v5 of the REST API, the endpoints for GitLab Runner will also not return `paused` or `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.
diff --git a/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml b/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml
index 99af852c13e..223c1439191 100644
--- a/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml
+++ b/data/deprecations/14-8-runner-api-active-field-replaced-with-paused-breaking-change.yml
@@ -6,15 +6,16 @@
breaking_change: true
reporter: pedropombeiro
body: |
- Occurrences of the `active` identifier in the GitLab Runner REST and GraphQL API endpoints will be
- renamed to `paused` in GitLab 16.0, namely:
+ Occurrences of the `active` identifier in the GitLab Runner GraphQL API endpoints will be
+ renamed to `paused` in GitLab 16.0.
- - GraphQL API:
- - the `CiRunner` property;
- - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation;
- - the `runners` and `Group.runners` queries.
- - REST API:
- - endpoints taking or returning `active` properties, such as:
+ - For the GraphQL API, this change affects:
+ - the `CiRunner` property
+ - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation
+ - the `runners` and `Group.runners` queries
+ - In v4 of the REST API, starting in GitLab 14.8, you can use the `paused` property in place of `active`
+ - In v5 of the REST API, this change will affect:
+ - endpoints taking or returning `active` property, such as:
- `GET /runners`
- `GET /runners/all`
- `GET /runners/:id` / `PUT /runners/:id`
@@ -22,9 +23,7 @@
- `GET /projects/:id/runners` / `POST /projects/:id/runners`
- `GET /groups/:id/runners`
- The 16.0 release of the GitLab Runner will start using the `paused` property when registering runners, and therefore
- will only be compatible with GitLab 16.0 and later. Until 16.0, GitLab will accept the deprecated `active` flag from
- existing runners.
+ The 16.0 release of GitLab Runner will start using the `paused` property when registering runners.
stage: Verify
tiers: [Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351109
diff --git a/data/deprecations/14-8-runner-api-project_type-breaking-change.yml b/data/deprecations/14-8-runner-api-project_type-breaking-change.yml
deleted file mode 100644
index d965d830c58..00000000000
--- a/data/deprecations/14-8-runner-api-project_type-breaking-change.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-- name: "REST API endpoint to list group runners no longer accepts `project_type` value for `type` argument"
- announcement_milestone: "14.8"
- announcement_date: "2022-02-22"
- removal_milestone: "16.0"
- removal_date: "2023-04-22"
- breaking_change: true
- reporter: pedropombeiro
- body: |
- The `GET /groups/:id/runners?type=project_type` endpoint will be removed in GitLab 16.0. The endpoint always returned an empty collection.
- stage: Verify
- tiers: [Core, Premium, Ultimate]
- issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351466
- documentation_url: https://docs.gitlab.com/ee/api/runners.html
- 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-8-runner-api-status-filter-does-accept-active-or-paused.yml b/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml
index 174e51f5f5d..376a27c8863 100644
--- a/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml
+++ b/data/deprecations/14-8-runner-api-status-filter-does-accept-active-or-paused.yml
@@ -1,17 +1,20 @@
-- name: "REST API Runner will not accept `status` filter values of `active` or `paused`"
+- name: "GraphQL API Runner will not accept `status` filter values of `active` or `paused`"
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-02-22"
removal_milestone: "16.0"
removal_date: "2023-04-22"
breaking_change: true
body: | # Do not modify this line, instead modify the lines below.
- The GitLab Runner REST endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
+ The GitLab Runner GraphQL endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
A runner's status will only relate to runner contact status, such as: `online`, `offline`.
Status values `paused` or `active` will no longer be accepted and will be replaced by the `paused` query parameter.
- When checking for paused runners, API users are advised to specify `paused=true` as the query parameter.
- When checking for active runners, specify `paused=false`.
+ When checking for paused runners, API users are advised to specify `paused: true` as the query parameter.
+ When checking for active runners, specify `paused: false`.
+
+ The REST API endpoints will follow in the same direction in a future REST v5 API, however the new `paused`
+ status value can be used in place of `active` since GitLab 14.8.
stage: Verify
tiers: [Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351109
diff --git a/data/deprecations/15-5-confidential-field-on-notes.yml b/data/deprecations/15-5-confidential-field-on-notes.yml
new file mode 100644
index 00000000000..5ec5c3adab9
--- /dev/null
+++ b/data/deprecations/15-5-confidential-field-on-notes.yml
@@ -0,0 +1,12 @@
+- name: 'GraphQL field `confidential` changed to `internal` on notes'
+ announcement_milestone: '15.5'
+ announcement_date: '2022-10-22'
+ removal_milestone: '16.0'
+ removal_date: '2023-05-22'
+ breaking_change: true
+ reporter: nicolasdular
+ stage: plan
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371485
+ body: |
+ The `confidential` field for a `Note` will be deprecated and renamed to `internal`.
+ documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/index.html#note
diff --git a/data/deprecations/15-5-vulnerabilityFindingDismiss-mutation.yml b/data/deprecations/15-5-vulnerabilityFindingDismiss-mutation.yml
new file mode 100644
index 00000000000..949aa40e5ce
--- /dev/null
+++ b/data/deprecations/15-5-vulnerabilityFindingDismiss-mutation.yml
@@ -0,0 +1,13 @@
+- name: "vulnerabilityFindingDismiss GraphQL mutation"
+ announcement_milestone: "15.5"
+ announcement_date: "2022-10-22"
+ removal_milestone: "16.0"
+ removal_date: "2023-05-22"
+ breaking_change: true
+ reporter: matt_wilson
+ stage: govern
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375645
+ body: |
+ The `VulnerabilityFindingDismiss` GraphQL mutation is being deprecated and will be removed in GitLab 16.0. This mutation was not used often as the Vulnerability Finding ID was not available to users (this field was [deprecated in 15.3](https://docs.gitlab.com/ee/update/deprecations.html#use-of-id-field-in-vulnerabilityfindingdismiss-mutation)). Users should instead use `VulnerabilityDismiss` to dismiss vulnerabilities in the Vulnerability Report or `SecurityFindingDismiss` for security findings in the CI Pipeline Security tab.
+ tiers: "Ultimate"
+ documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/index.html#mutationvulnerabilityfindingdismiss
diff --git a/data/deprecations/templates/_deprecation_template.md.erb b/data/deprecations/templates/_deprecation_template.md.erb
index 0725ce2891e..4fd2ca29bc8 100644
--- a/data/deprecations/templates/_deprecation_template.md.erb
+++ b/data/deprecations/templates/_deprecation_template.md.erb
@@ -1,7 +1,7 @@
---
stage: none
group: none
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Deprecations by version
diff --git a/data/removals/templates/_removal_template.md.erb b/data/removals/templates/_removal_template.md.erb
index dc779323096..ad0298a6596 100644
--- a/data/removals/templates/_removal_template.md.erb
+++ b/data/removals/templates/_removal_template.md.erb
@@ -1,7 +1,7 @@
---
stage: none
group: none
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Removals by version
diff --git a/db/docs/ci_pipeline_metadata.yml b/db/docs/ci_pipeline_metadata.yml
new file mode 100644
index 00000000000..ed0bd896841
--- /dev/null
+++ b/db/docs/ci_pipeline_metadata.yml
@@ -0,0 +1,9 @@
+---
+table_name: ci_pipelines_metadata
+classes:
+- Ci::PipelineMetadata
+feature_categories:
+- continuous_integration
+description: 'Stores additional information about CI pipelines'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97139
+milestone: '15.5'
diff --git a/db/docs/incident_management_timeline_event_tag_links.yml b/db/docs/incident_management_timeline_event_tag_links.yml
new file mode 100644
index 00000000000..429371aefb7
--- /dev/null
+++ b/db/docs/incident_management_timeline_event_tag_links.yml
@@ -0,0 +1,9 @@
+---
+table_name: incident_management_timeline_event_tag_links
+classes:
+- IncidentManagement::TimelineEventTagLink
+feature_categories:
+- incident_management
+description: Persists links between timeline event tags and timeline events.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100271
+milestone: '15.6'
diff --git a/db/docs/incident_management_timeline_event_tags.yml b/db/docs/incident_management_timeline_event_tags.yml
new file mode 100644
index 00000000000..47dedaf3de2
--- /dev/null
+++ b/db/docs/incident_management_timeline_event_tags.yml
@@ -0,0 +1,9 @@
+---
+table_name: incident_management_timeline_event_tags
+classes:
+- IncidentManagement::TimelineEventTag
+feature_categories:
+- incident_management
+description: Persists tags for timeline events in a project.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100271
+milestone: '15.6'
diff --git a/db/docs/packages_rpm_repository_files.yml b/db/docs/packages_rpm_repository_files.yml
new file mode 100644
index 00000000000..3aac984265c
--- /dev/null
+++ b/db/docs/packages_rpm_repository_files.yml
@@ -0,0 +1,9 @@
+---
+table_name: packages_rpm_repository_files
+classes:
+- Packages::RPM::RepositoryFile
+feature_categories:
+- package_registry
+description: Package registry file links and file metadata for RPM packages
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97484
+milestone: '15.5'
diff --git a/db/docs/project_wiki_repository_states.yml b/db/docs/project_wiki_repository_states.yml
new file mode 100644
index 00000000000..b074eca3c89
--- /dev/null
+++ b/db/docs/project_wiki_repository_states.yml
@@ -0,0 +1,9 @@
+---
+table_name: project_wiki_repository_states
+classes:
+- ProjectWikiRepositoryState
+feature_categories:
+- geo_replication
+description: Separate table for project wikis containing Geo verification metadata.
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99168
+milestone: '15.5'
diff --git a/db/docs/push_rules.yml b/db/docs/push_rules.yml
index 6b62013892b..6a51fc79b33 100644
--- a/db/docs/push_rules.yml
+++ b/db/docs/push_rules.yml
@@ -3,7 +3,7 @@ table_name: push_rules
classes:
- PushRule
feature_categories:
-- compliance_management
+- source_code_management
description: TODO
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/1b98b5ab97ce3e9997df542059cbf3c6ce0bf0e1
milestone: '8.10'
diff --git a/db/docs/sbom_component_versions.yml b/db/docs/sbom_component_versions.yml
index 7fb9b7fcec5..1bee0ddb3fb 100644
--- a/db/docs/sbom_component_versions.yml
+++ b/db/docs/sbom_component_versions.yml
@@ -3,9 +3,7 @@ table_name: sbom_component_versions
classes:
- Sbom::ComponentVersion
feature_categories:
-- container_scanning
-- dependency_scanning
-- license_compliance
+- dependency_management
description: Stores version information for software components produced by a Software Bill of Materials (SBoM)
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90809
milestone: '15.2'
diff --git a/db/docs/sbom_components.yml b/db/docs/sbom_components.yml
index 8860c253cd5..0bb1a4d7b30 100644
--- a/db/docs/sbom_components.yml
+++ b/db/docs/sbom_components.yml
@@ -3,9 +3,7 @@ table_name: sbom_components
classes:
- Sbom::Component
feature_categories:
-- container_scanning
-- dependency_scanning
-- license_compliance
+- dependency_management
description: Stores information about software components produced by a Software Bill of Materials (SBoM)
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90809
milestone: '15.2'
diff --git a/db/docs/sbom_occurrences.yml b/db/docs/sbom_occurrences.yml
index 82d9e21aa42..b30bac79698 100644
--- a/db/docs/sbom_occurrences.yml
+++ b/db/docs/sbom_occurrences.yml
@@ -3,9 +3,7 @@ table_name: sbom_occurrences
classes:
- Sbom::Occurrence
feature_categories:
-- container_scanning
-- dependency_scanning
-- license_compliance
+- dependency_management
description: Tracks each occurrence of an SBoM component
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90814
milestone: '15.2'
diff --git a/db/docs/sbom_sources.yml b/db/docs/sbom_sources.yml
index 514386536da..dd17b02a3dd 100644
--- a/db/docs/sbom_sources.yml
+++ b/db/docs/sbom_sources.yml
@@ -3,9 +3,7 @@ table_name: sbom_sources
classes:
- Sbom::Source
feature_categories:
-- container_scanning
-- dependency_scanning
-- license_compliance
+- dependency_management
description: Stores information about where an SBoM component originated from
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90812
milestone: '15.2'
diff --git a/db/docs/sbom_vulnerable_component_versions.yml b/db/docs/sbom_vulnerable_component_versions.yml
index 147af9c046b..bb67c6e4f68 100644
--- a/db/docs/sbom_vulnerable_component_versions.yml
+++ b/db/docs/sbom_vulnerable_component_versions.yml
@@ -3,9 +3,7 @@ table_name: sbom_vulnerable_component_versions
classes:
- Sbom::VulnerableComponentVersion
feature_categories:
-- container_scanning
-- dependency_scanning
-- license_compliance
+- dependency_management
description: Stores information about vulnerable SBoM components
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95622
milestone: '15.4'
diff --git a/db/docs/user_phone_number_validations.yml b/db/docs/user_phone_number_validations.yml
new file mode 100644
index 00000000000..9feacd76c5a
--- /dev/null
+++ b/db/docs/user_phone_number_validations.yml
@@ -0,0 +1,9 @@
+---
+table_name: user_phone_number_validations
+classes:
+- Users::PhoneNumberValidation
+feature_categories:
+- onboarding
+description: Stores whether the user has verified their phone number
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97762
+milestone: '15.5'
diff --git a/db/migrate/20220126191624_add_scan_file_path_to_dast_site_profile.rb b/db/migrate/20220126191624_add_scan_file_path_to_dast_site_profile.rb
new file mode 100644
index 00000000000..eab02663e26
--- /dev/null
+++ b/db/migrate/20220126191624_add_scan_file_path_to_dast_site_profile.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddScanFilePathToDastSiteProfile < Gitlab::Database::Migration[2.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20221012135524_add_scan_file_path_limit_for_dast_site_profile
+ def up
+ add_column :dast_site_profiles, :scan_file_path, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+
+ def down
+ remove_column :dast_site_profiles, :scan_file_path, :text
+ end
+end
diff --git a/db/migrate/20220615172230_add_user_preference_to_turn_off_automatic_lists.rb b/db/migrate/20220615172230_add_user_preference_to_turn_off_automatic_lists.rb
new file mode 100644
index 00000000000..4a0255aad06
--- /dev/null
+++ b/db/migrate/20220615172230_add_user_preference_to_turn_off_automatic_lists.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddUserPreferenceToTurnOffAutomaticLists < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ add_column :user_preferences, :markdown_automatic_lists, :boolean, default: true, null: false
+ end
+
+ def down
+ remove_column :user_preferences, :markdown_automatic_lists, :boolean
+ end
+end
diff --git a/db/migrate/20220802200719_add_user_details_profile_fields.rb b/db/migrate/20220802200719_add_user_details_profile_fields.rb
new file mode 100644
index 00000000000..952b0bc1d9a
--- /dev/null
+++ b/db/migrate/20220802200719_add_user_details_profile_fields.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddUserDetailsProfileFields < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limits are added in 20220802202505_add_user_details_field_limits
+ def change
+ add_column :user_details, :linkedin, :text, null: false, default: ''
+ add_column :user_details, :twitter, :text, null: false, default: ''
+ add_column :user_details, :skype, :text, null: false, default: ''
+ add_column :user_details, :website_url, :text, null: false, default: ''
+ add_column :user_details, :location, :text, null: false, default: ''
+ add_column :user_details, :organization, :text, null: false, default: ''
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20220802202505_add_user_details_field_limits.rb b/db/migrate/20220802202505_add_user_details_field_limits.rb
new file mode 100644
index 00000000000..83b6a4528d3
--- /dev/null
+++ b/db/migrate/20220802202505_add_user_details_field_limits.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddUserDetailsFieldLimits < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ USER_DETAILS_FIELD_LIMIT = 500
+
+ def up
+ add_text_limit :user_details, :linkedin, USER_DETAILS_FIELD_LIMIT
+ add_text_limit :user_details, :twitter, USER_DETAILS_FIELD_LIMIT
+ add_text_limit :user_details, :skype, USER_DETAILS_FIELD_LIMIT
+ add_text_limit :user_details, :website_url, USER_DETAILS_FIELD_LIMIT
+ add_text_limit :user_details, :location, USER_DETAILS_FIELD_LIMIT
+ add_text_limit :user_details, :organization, USER_DETAILS_FIELD_LIMIT
+ end
+
+ def down
+ remove_text_limit :user_details, :linkedin
+ remove_text_limit :user_details, :twitter
+ remove_text_limit :user_details, :skype
+ remove_text_limit :user_details, :website_url
+ remove_text_limit :user_details, :location
+ remove_text_limit :user_details, :organization
+ end
+end
diff --git a/db/migrate/20220805180311_add_unique_index_on_sbom_component_type_and_name.rb b/db/migrate/20220805180311_add_unique_index_on_sbom_component_type_and_name.rb
new file mode 100644
index 00000000000..852b1283e92
--- /dev/null
+++ b/db/migrate/20220805180311_add_unique_index_on_sbom_component_type_and_name.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexOnSbomComponentTypeAndName < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_sbom_components_on_component_type_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_components, [:component_type, :name], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :sbom_components, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220805183952_add_unique_index_to_sbom_component_versions_on_component_id_and_version.rb b/db/migrate/20220805183952_add_unique_index_to_sbom_component_versions_on_component_id_and_version.rb
new file mode 100644
index 00000000000..03023bc6f2c
--- /dev/null
+++ b/db/migrate/20220805183952_add_unique_index_to_sbom_component_versions_on_component_id_and_version.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexToSbomComponentVersionsOnComponentIdAndVersion < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_sbom_component_versions_on_component_id_and_version'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_component_versions, [:component_id, :version], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :sbom_component_versions, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220805193117_add_unique_index_to_sbom_sources_on_source_type_and_source.rb b/db/migrate/20220805193117_add_unique_index_to_sbom_sources_on_source_type_and_source.rb
new file mode 100644
index 00000000000..973cacaec5b
--- /dev/null
+++ b/db/migrate/20220805193117_add_unique_index_to_sbom_sources_on_source_type_and_source.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexToSbomSourcesOnSourceTypeAndSource < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_sbom_sources_on_source_type_and_source'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_sources, [:source_type, :source], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :sbom_sources, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220818125332_add_jitsu_tracking_columns_to_application_settings.rb b/db/migrate/20220818125332_add_jitsu_tracking_columns_to_application_settings.rb
new file mode 100644
index 00000000000..9013168c2c5
--- /dev/null
+++ b/db/migrate/20220818125332_add_jitsu_tracking_columns_to_application_settings.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddJitsuTrackingColumnsToApplicationSettings < Gitlab::Database::Migration[2.0]
+ def change
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20220818125703_add_jitsu_tracking_columns_to_application_settings_text_limits.rb
+ add_column :application_settings, :jitsu_host, :text
+ add_column :application_settings, :jitsu_project_xid, :text
+ add_column :application_settings, :clickhouse_connection_string, :text
+ add_column :application_settings, :jitsu_administrator_email, :text
+ add_column :application_settings, :encrypted_jitsu_administrator_password, :binary
+ add_column :application_settings, :encrypted_jitsu_administrator_password_iv, :binary
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+end
diff --git a/db/migrate/20220818125703_add_jitsu_tracking_columns_to_application_settings_text_limits.rb b/db/migrate/20220818125703_add_jitsu_tracking_columns_to_application_settings_text_limits.rb
new file mode 100644
index 00000000000..41de6e34724
--- /dev/null
+++ b/db/migrate/20220818125703_add_jitsu_tracking_columns_to_application_settings_text_limits.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddJitsuTrackingColumnsToApplicationSettingsTextLimits < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :jitsu_host, 255
+ add_text_limit :application_settings, :jitsu_project_xid, 255
+ add_text_limit :application_settings, :clickhouse_connection_string, 1024
+ add_text_limit :application_settings, :jitsu_administrator_email, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :jitsu_host
+ remove_text_limit :application_settings, :jitsu_project_xid
+ remove_text_limit :application_settings, :clickhouse_connection_string
+ remove_text_limit :application_settings, :jitsu_administrator_email
+ end
+end
diff --git a/db/migrate/20220818140553_add_unique_index_to_sbom_occurrences_on_ingestion_attributes.rb b/db/migrate/20220818140553_add_unique_index_to_sbom_occurrences_on_ingestion_attributes.rb
new file mode 100644
index 00000000000..2538017e287
--- /dev/null
+++ b/db/migrate/20220818140553_add_unique_index_to_sbom_occurrences_on_ingestion_attributes.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexToSbomOccurrencesOnIngestionAttributes < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_sbom_occurrences_on_ingestion_attributes'
+ ATTRIBUTES = %i[
+ project_id
+ component_id
+ component_version_id
+ source_id
+ commit_sha
+ ].freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_occurrences, ATTRIBUTES, unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :sbom_occurrences, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220819184945_add_dashboard_limit_to_application_settings.rb b/db/migrate/20220819184945_add_dashboard_limit_to_application_settings.rb
new file mode 100644
index 00000000000..f2ab4a043ea
--- /dev/null
+++ b/db/migrate/20220819184945_add_dashboard_limit_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDashboardLimitToApplicationSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :application_settings, :dashboard_limit_enabled, :boolean, default: false, null: false
+ add_column :application_settings, :dashboard_limit, :integer, default: 0, null: false
+ add_column :application_settings, :dashboard_notification_limit, :integer, default: 0, null: false
+ add_column :application_settings, :dashboard_enforcement_limit, :integer, default: 0, null: false
+ add_column :application_settings, :dashboard_limit_new_namespace_creation_enforcement_date, :date
+ end
+end
diff --git a/db/migrate/20220901090004_add_can_create_group_to_application_settings.rb b/db/migrate/20220901090004_add_can_create_group_to_application_settings.rb
new file mode 100644
index 00000000000..a61f7c9a080
--- /dev/null
+++ b/db/migrate/20220901090004_add_can_create_group_to_application_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddCanCreateGroupToApplicationSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column(:application_settings, :can_create_group, :boolean, default: true, null: false)
+ end
+end
diff --git a/db/migrate/20220901092853_update_can_create_group_application_setting.rb b/db/migrate/20220901092853_update_can_create_group_application_setting.rb
new file mode 100644
index 00000000000..42508184d62
--- /dev/null
+++ b/db/migrate/20220901092853_update_can_create_group_application_setting.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class UpdateCanCreateGroupApplicationSetting < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ value = gitlab_config.respond_to?(:default_can_create_group) ? gitlab_config.default_can_create_group : true
+ value = Gitlab::Utils.to_boolean(value, default: true)
+
+ execute_update(value: value)
+ end
+
+ def down
+ execute_update(value: true)
+ end
+
+ private
+
+ def execute_update(value:)
+ execute "UPDATE application_settings SET can_create_group = #{value}"
+ end
+
+ def gitlab_config
+ Gitlab.config.gitlab
+ end
+end
diff --git a/db/migrate/20220901114501_only_allow_merge_if_all_status_checks_passed.rb b/db/migrate/20220901114501_only_allow_merge_if_all_status_checks_passed.rb
new file mode 100644
index 00000000000..059ed657264
--- /dev/null
+++ b/db/migrate/20220901114501_only_allow_merge_if_all_status_checks_passed.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class OnlyAllowMergeIfAllStatusChecksPassed < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :project_settings, :only_allow_merge_if_all_status_checks_passed, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20220907115806_add_security_orchestration_policy_configuration_id.rb b/db/migrate/20220907115806_add_security_orchestration_policy_configuration_id.rb
new file mode 100644
index 00000000000..de83288a0ca
--- /dev/null
+++ b/db/migrate/20220907115806_add_security_orchestration_policy_configuration_id.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+class AddSecurityOrchestrationPolicyConfigurationId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ PROJECT_INDEX_NAME = 'idx_approval_project_rules_on_sec_orchestration_config_id'
+ MERGE_REQUEST_INDEX_NAME = 'idx_approval_merge_request_rules_on_sec_orchestration_config_id'
+
+ def up
+ with_lock_retries do
+ unless column_exists?(:approval_project_rules, :security_orchestration_policy_configuration_id)
+ add_column :approval_project_rules, :security_orchestration_policy_configuration_id, :bigint
+ end
+ end
+
+ with_lock_retries do
+ unless column_exists?(:approval_merge_request_rules, :security_orchestration_policy_configuration_id)
+ add_column :approval_merge_request_rules, :security_orchestration_policy_configuration_id, :bigint
+ end
+ end
+
+ add_concurrent_index :approval_project_rules,
+ :security_orchestration_policy_configuration_id,
+ name: PROJECT_INDEX_NAME
+ add_concurrent_index :approval_merge_request_rules,
+ :security_orchestration_policy_configuration_id,
+ name: MERGE_REQUEST_INDEX_NAME
+
+ add_concurrent_foreign_key :approval_project_rules,
+ :security_orchestration_policy_configurations,
+ column: :security_orchestration_policy_configuration_id,
+ on_delete: :cascade
+ add_concurrent_foreign_key :approval_merge_request_rules,
+ :security_orchestration_policy_configurations,
+ column: :security_orchestration_policy_configuration_id,
+ on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ if column_exists?(:approval_project_rules, :security_orchestration_policy_configuration_id)
+ remove_column :approval_project_rules, :security_orchestration_policy_configuration_id
+ end
+ end
+
+ with_lock_retries do
+ if column_exists?(:approval_merge_request_rules, :security_orchestration_policy_configuration_id)
+ remove_column :approval_merge_request_rules, :security_orchestration_policy_configuration_id
+ end
+ end
+
+ remove_foreign_key_if_exists :approval_project_rules, column: :security_orchestration_policy_configuration_id
+ remove_foreign_key_if_exists :approval_merge_request_rules, column: :security_orchestration_policy_configuration_id
+
+ remove_concurrent_index_by_name :approval_project_rules, name: PROJECT_INDEX_NAME
+ remove_concurrent_index_by_name :approval_merge_request_rules, name: MERGE_REQUEST_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220912153839_create_packages_rpm_repository_file.rb b/db/migrate/20220912153839_create_packages_rpm_repository_file.rb
new file mode 100644
index 00000000000..889720df233
--- /dev/null
+++ b/db/migrate/20220912153839_create_packages_rpm_repository_file.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreatePackagesRpmRepositoryFile < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :packages_rpm_repository_files do |t|
+ t.timestamps_with_timezone
+
+ t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }, type: :bigint
+ t.integer :file_store, default: 1
+ t.integer :status, default: 0, null: false, limit: 2
+ t.integer :size
+ t.binary :file_md5
+ t.binary :file_sha1
+ t.binary :file_sha256
+ t.text :file, null: false, limit: 255
+ t.text :file_name, null: false, limit: 255
+ end
+ end
+
+ def down
+ drop_table :packages_rpm_repository_files
+ end
+end
diff --git a/db/migrate/20220913043728_create_user_phone_number_validations.rb b/db/migrate/20220913043728_create_user_phone_number_validations.rb
new file mode 100644
index 00000000000..21a5b4d5519
--- /dev/null
+++ b/db/migrate/20220913043728_create_user_phone_number_validations.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class CreateUserPhoneNumberValidations < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :user_phone_number_validations, id: false do |t|
+ t.references :user, primary_key: true, default: nil, type: :bigint, index: false,
+ foreign_key: { on_delete: :cascade }
+
+ t.datetime_with_timezone :validated_at
+ t.timestamps_with_timezone null: false
+
+ t.integer :international_dial_code, null: false, limit: 1
+ t.integer :verification_attempts, null: false, default: 0, limit: 1
+ t.integer :risk_score, null: false, default: 0, limit: 1
+
+ t.text :country, null: false, limit: 3
+ t.text :phone_number, null: false, limit: 12
+ t.text :telesign_reference_xid, limit: 255
+
+ t.index [:international_dial_code, :phone_number], name: :index_user_phone_validations_on_dial_code_phone_number
+ end
+ end
+
+ def down
+ drop_table :user_phone_number_validations
+ end
+end
diff --git a/db/migrate/20220913082824_finalize_invalid_group_member_cleanup.rb b/db/migrate/20220913082824_finalize_invalid_group_member_cleanup.rb
new file mode 100644
index 00000000000..d5fb04f3fa3
--- /dev/null
+++ b/db/migrate/20220913082824_finalize_invalid_group_member_cleanup.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class FinalizeInvalidGroupMemberCleanup < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ # noop: this fails because the cleanup invalid members migration(ScheduleDestroyInvalidGroupMembers)
+ # cannot succeed, so we need to cleanup that first.
+ #
+ # issue with some details: https://gitlab.com/gitlab-org/gitlab/-/issues/365028#note_1107166816
+ # # incident: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7779
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/migrate/20220913084123_add_timestamp_to_ml_candidate_metrics.rb b/db/migrate/20220913084123_add_timestamp_to_ml_candidate_metrics.rb
new file mode 100644
index 00000000000..293bca2d6d7
--- /dev/null
+++ b/db/migrate/20220913084123_add_timestamp_to_ml_candidate_metrics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddTimestampToMlCandidateMetrics < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :ml_candidate_metrics, :tracked_at, :bigint
+ end
+end
diff --git a/db/migrate/20220914070927_finalize_invalid_project_member_cleanup.rb b/db/migrate/20220914070927_finalize_invalid_project_member_cleanup.rb
new file mode 100644
index 00000000000..30f6519ed0f
--- /dev/null
+++ b/db/migrate/20220914070927_finalize_invalid_project_member_cleanup.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class FinalizeInvalidProjectMemberCleanup < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ # noop: this fails because the cleanup invalid members migration(ScheduleDestroyInvalidProjectMembers)
+ # cannot succeed, so we need to cleanup that first.
+ #
+ # issue with some details: https://gitlab.com/gitlab-org/gitlab/-/issues/365028#note_1107166816
+ # # incident: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7779
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb b/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb
new file mode 100644
index 00000000000..caf30961ace
--- /dev/null
+++ b/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToCandidateIdAndNameOnMlCandidateParams < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ml_candidate_params_on_candidate_id_on_name'
+
+ def up
+ add_concurrent_index :ml_candidate_params, [:candidate_id, :name], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:ml_candidate_params, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20220914112457_add_reject_non_dco_commits_to_push_rules.rb b/db/migrate/20220914112457_add_reject_non_dco_commits_to_push_rules.rb
new file mode 100644
index 00000000000..57b3c209660
--- /dev/null
+++ b/db/migrate/20220914112457_add_reject_non_dco_commits_to_push_rules.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddRejectNonDcoCommitsToPushRules < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :push_rules, :reject_non_dco_commits, :boolean
+ end
+end
diff --git a/db/migrate/20220914130800_add_jitsu_key_to_projects.rb b/db/migrate/20220914130800_add_jitsu_key_to_projects.rb
new file mode 100644
index 00000000000..91c0695c4a6
--- /dev/null
+++ b/db/migrate/20220914130800_add_jitsu_key_to_projects.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# rubocop:disable Migration/AddLimitToTextColumns
+# limit is added in 20220914131449_add_text_limit_to_projects_jitsu_key.rb
+class AddJitsuKeyToProjects < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :project_settings, :jitsu_key, :text
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_settings, :jitsu_key
+ end
+ end
+end
+# rubocop:enable Migration/AddLimitToTextColumns
diff --git a/db/migrate/20220914131449_add_text_limit_to_projects_jitsu_key.rb b/db/migrate/20220914131449_add_text_limit_to_projects_jitsu_key.rb
new file mode 100644
index 00000000000..93aa27ffaa2
--- /dev/null
+++ b/db/migrate/20220914131449_add_text_limit_to_projects_jitsu_key.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToProjectsJitsuKey < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :project_settings, :jitsu_key, 100
+ end
+
+ def down
+ remove_text_limit :project_settings, :jitsu_key
+ end
+end
diff --git a/db/migrate/20220914174705_remove_not_null_constraint_from_sbom_source_fingerprint.rb b/db/migrate/20220914174705_remove_not_null_constraint_from_sbom_source_fingerprint.rb
new file mode 100644
index 00000000000..6e819b1cdef
--- /dev/null
+++ b/db/migrate/20220914174705_remove_not_null_constraint_from_sbom_source_fingerprint.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class RemoveNotNullConstraintFromSbomSourceFingerprint < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ change_column_null :sbom_sources, :fingerprint, true
+ end
+end
diff --git a/db/migrate/20220916094641_add_source_id_to_bulk_import_entities.rb b/db/migrate/20220916094641_add_source_id_to_bulk_import_entities.rb
new file mode 100644
index 00000000000..b077fee9045
--- /dev/null
+++ b/db/migrate/20220916094641_add_source_id_to_bulk_import_entities.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddSourceIdToBulkImportEntities < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :bulk_import_entities, :source_xid, :integer
+ end
+end
diff --git a/db/migrate/20220916103311_add_index_on_jira_connect_installations_instance_url.rb b/db/migrate/20220916103311_add_index_on_jira_connect_installations_instance_url.rb
new file mode 100644
index 00000000000..806c7d65f16
--- /dev/null
+++ b/db/migrate/20220916103311_add_index_on_jira_connect_installations_instance_url.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnJiraConnectInstallationsInstanceUrl < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_jira_connect_installations_on_instance_url'
+
+ def up
+ add_concurrent_index :jira_connect_installations, :instance_url, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :jira_connect_installations, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220918124223_add_suggested_reviewers_enabled_to_project_settings.rb b/db/migrate/20220918124223_add_suggested_reviewers_enabled_to_project_settings.rb
new file mode 100644
index 00000000000..1a762d68bdc
--- /dev/null
+++ b/db/migrate/20220918124223_add_suggested_reviewers_enabled_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddSuggestedReviewersEnabledToProjectSettings < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :suggested_reviewers_enabled, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb b/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb
new file mode 100644
index 00000000000..23b58522639
--- /dev/null
+++ b/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexPackagesPackagesOnProjectIdAndLowerVersionToPackages < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_packages_on_project_id_and_lower_version'
+ NUGET_PACKAGE_TYPE = 4
+
+ def up
+ add_concurrent_index(
+ :packages_packages,
+ 'project_id, LOWER(version)',
+ name: INDEX_NAME,
+ where: "package_type = #{NUGET_PACKAGE_TYPE}"
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20220920022404_remove_temp_index_null_project_namespace_id.rb b/db/migrate/20220920022404_remove_temp_index_null_project_namespace_id.rb
new file mode 100644
index 00000000000..5541afcee40
--- /dev/null
+++ b/db/migrate/20220920022404_remove_temp_index_null_project_namespace_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveTempIndexNullProjectNamespaceId < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'tmp_index_for_null_project_namespace_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :projects, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :projects, :id, name: INDEX_NAME, where: 'project_namespace_id IS NULL'
+ end
+end
diff --git a/db/migrate/20220921174815_add_secure_files_metadata.rb b/db/migrate/20220921174815_add_secure_files_metadata.rb
new file mode 100644
index 00000000000..74cc1d95867
--- /dev/null
+++ b/db/migrate/20220921174815_add_secure_files_metadata.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class AddSecureFilesMetadata < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :ci_secure_files, :metadata, :jsonb
+ add_column :ci_secure_files, :expires_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20220921201347_add_maven_package_requests_forwarding_to_namespace_package_settings.rb b/db/migrate/20220921201347_add_maven_package_requests_forwarding_to_namespace_package_settings.rb
new file mode 100644
index 00000000000..8f858eb7960
--- /dev/null
+++ b/db/migrate/20220921201347_add_maven_package_requests_forwarding_to_namespace_package_settings.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddMavenPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
+ def change
+ # adds columns to match the format used in
+ # Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
+ add_column(:namespace_package_settings,
+ :maven_package_requests_forwarding,
+ :boolean,
+ null: true,
+ default: nil
+ )
+
+ add_column(:namespace_package_settings,
+ :lock_maven_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+
+ add_column(:application_settings,
+ :lock_maven_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+ end
+end
diff --git a/db/migrate/20220922143612_add_inbound_ci_job_token_project_scope_links.rb b/db/migrate/20220922143612_add_inbound_ci_job_token_project_scope_links.rb
new file mode 100644
index 00000000000..50b43ee4db8
--- /dev/null
+++ b/db/migrate/20220922143612_add_inbound_ci_job_token_project_scope_links.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddInboundCiJobTokenProjectScopeLinks < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ add_column :ci_job_token_project_scope_links, :direction, :integer, limit: 2, default: 0, null: false
+ end
+
+ def down
+ remove_column :ci_job_token_project_scope_links, :direction
+ end
+end
diff --git a/db/migrate/20220923103006_add_ci_pipeline_metadata_title.rb b/db/migrate/20220923103006_add_ci_pipeline_metadata_title.rb
new file mode 100644
index 00000000000..3b2f02924a1
--- /dev/null
+++ b/db/migrate/20220923103006_add_ci_pipeline_metadata_title.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddCiPipelineMetadataTitle < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :ci_pipeline_metadata, id: false do |t|
+ t.bigint :project_id, null: false
+
+ t.references :pipeline,
+ null: false,
+ primary_key: true,
+ default: nil,
+ index: false,
+ foreign_key: { to_table: :ci_pipelines, on_delete: :cascade }
+
+ t.text :title, null: false, limit: 255
+
+ t.index [:pipeline_id, :title], name: 'index_ci_pipeline_metadata_on_pipeline_id_title'
+ t.index [:project_id], name: 'index_ci_pipeline_metadata_on_project_id'
+ end
+ end
+
+ def down
+ drop_table :ci_pipeline_metadata
+ end
+end
diff --git a/db/migrate/20220927155407_add_column_inbound_job_token_scope_enabled_to_ci_cd_setting.rb b/db/migrate/20220927155407_add_column_inbound_job_token_scope_enabled_to_ci_cd_setting.rb
new file mode 100644
index 00000000000..811138cd2f2
--- /dev/null
+++ b/db/migrate/20220927155407_add_column_inbound_job_token_scope_enabled_to_ci_cd_setting.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddColumnInboundJobTokenScopeEnabledToCiCdSetting < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ add_column :project_ci_cd_settings, :inbound_job_token_scope_enabled, :boolean, default: false, null: false
+ end
+
+ def down
+ remove_column :project_ci_cd_settings, :inbound_job_token_scope_enabled
+ end
+end
diff --git a/db/migrate/20220928201920_create_project_wiki_repository_states.rb b/db/migrate/20220928201920_create_project_wiki_repository_states.rb
new file mode 100644
index 00000000000..17ad5cf6b7a
--- /dev/null
+++ b/db/migrate/20220928201920_create_project_wiki_repository_states.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class CreateProjectWikiRepositoryStates < Gitlab::Database::Migration[2.0]
+ VERIFICATION_STATE_INDEX_NAME = "index_project_wiki_repository_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_project_wiki_repository_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_project_wiki_repository_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_project_wiki_repository_states_needs_verification"
+
+ enable_lock_retries!
+
+ def up
+ create_table :project_wiki_repository_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 :project, primary_key: true, default: nil, index: 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 :project_wiki_repository_states
+ end
+end
diff --git a/db/migrate/20220929171925_add_pypi_package_requests_forwarding_to_namespace_package_settings.rb b/db/migrate/20220929171925_add_pypi_package_requests_forwarding_to_namespace_package_settings.rb
new file mode 100644
index 00000000000..e99640d471f
--- /dev/null
+++ b/db/migrate/20220929171925_add_pypi_package_requests_forwarding_to_namespace_package_settings.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddPypiPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
+ def change
+ # adds columns to match the format used in
+ # Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
+ add_column(:namespace_package_settings,
+ :pypi_package_requests_forwarding,
+ :boolean,
+ null: true,
+ default: nil
+ )
+
+ add_column(:namespace_package_settings,
+ :lock_pypi_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+
+ add_column(:application_settings,
+ :lock_pypi_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+ end
+end
diff --git a/db/migrate/20220929172356_add_npm_package_requests_forwarding_to_namespace_package_settings.rb b/db/migrate/20220929172356_add_npm_package_requests_forwarding_to_namespace_package_settings.rb
new file mode 100644
index 00000000000..61cc2c26ec7
--- /dev/null
+++ b/db/migrate/20220929172356_add_npm_package_requests_forwarding_to_namespace_package_settings.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddNpmPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
+ def change
+ # adds columns to match the format used in
+ # Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
+ add_column(:namespace_package_settings,
+ :npm_package_requests_forwarding,
+ :boolean,
+ null: true,
+ default: nil
+ )
+
+ add_column(:namespace_package_settings,
+ :lock_npm_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+
+ add_column(:application_settings,
+ :lock_npm_package_requests_forwarding,
+ :boolean,
+ default: false,
+ null: false
+ )
+ end
+end
diff --git a/db/migrate/20220930125609_add_migrated_to_state_transition_to_vulnerability_feedback.rb b/db/migrate/20220930125609_add_migrated_to_state_transition_to_vulnerability_feedback.rb
new file mode 100644
index 00000000000..b6736a71761
--- /dev/null
+++ b/db/migrate/20220930125609_add_migrated_to_state_transition_to_vulnerability_feedback.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddMigratedToStateTransitionToVulnerabilityFeedback < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :vulnerability_feedback, :migrated_to_state_transition, :boolean, default: false
+ end
+end
diff --git a/db/migrate/20221005072353_create_incident_management_timeline_event_tags.rb b/db/migrate/20221005072353_create_incident_management_timeline_event_tags.rb
new file mode 100644
index 00000000000..c046548af01
--- /dev/null
+++ b/db/migrate/20221005072353_create_incident_management_timeline_event_tags.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateIncidentManagementTimelineEventTags < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :incident_management_timeline_event_tags do |t|
+ t.timestamps_with_timezone null: false
+ t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }
+ t.text :name, limit: 255, null: false
+
+ t.index [:project_id, :name], unique: true, name: 'index_im_timeline_event_tags_name_project_id'
+ end
+ end
+
+ def down
+ drop_table :incident_management_timeline_event_tags
+ end
+end
diff --git a/db/migrate/20221005094926_create_incident_management_timeline_event_tag_links.rb b/db/migrate/20221005094926_create_incident_management_timeline_event_tag_links.rb
new file mode 100644
index 00000000000..b3ec8f97738
--- /dev/null
+++ b/db/migrate/20221005094926_create_incident_management_timeline_event_tag_links.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CreateIncidentManagementTimelineEventTagLinks < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :incident_management_timeline_event_tag_links do |t|
+ t.references :timeline_event,
+ null: false,
+ index: { name: 'index_im_timeline_event_id' },
+ foreign_key: { to_table: :incident_management_timeline_events, column: :timeline_event_id, on_delete: :cascade }
+
+ t.references :timeline_event_tag,
+ null: false,
+ index: false,
+ foreign_key: {
+ to_table: :incident_management_timeline_event_tags,
+ column: :timeline_event_tag_id,
+ on_delete: :cascade
+ }
+
+ t.index [:timeline_event_tag_id, :timeline_event_id],
+ unique: true,
+ name: 'index_im_timeline_event_tags_on_tag_id_and_event_id'
+
+ t.datetime_with_timezone :created_at, null: false
+ end
+ end
+
+ def down
+ drop_table :incident_management_timeline_event_tag_links
+ end
+end
diff --git a/db/migrate/20221005103010_add_index_project_id_on_scan_finding_approval_project_rules.rb b/db/migrate/20221005103010_add_index_project_id_on_scan_finding_approval_project_rules.rb
new file mode 100644
index 00000000000..990188aa418
--- /dev/null
+++ b/db/migrate/20221005103010_add_index_project_id_on_scan_finding_approval_project_rules.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddIndexProjectIdOnScanFindingApprovalProjectRules < Gitlab::Database::Migration[2.0]
+ INDEX_NAME_ALL = 'scan_finding_approval_project_rule_index_project_id'
+ INDEX_NAME_28D = 'scan_finding_approval_project_rule_index_created_at_project_id'
+ SCAN_FINDING_REPORT_TYPE = 4
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :approval_project_rules, %i[created_at project_id],
+ where: "report_type = #{SCAN_FINDING_REPORT_TYPE}", name: INDEX_NAME_28D
+
+ add_concurrent_index :approval_project_rules, :project_id,
+ where: "report_type = #{SCAN_FINDING_REPORT_TYPE}", name: INDEX_NAME_ALL
+ end
+
+ def down
+ remove_concurrent_index_by_name :approval_project_rules, INDEX_NAME_ALL
+ remove_concurrent_index_by_name :approval_project_rules, INDEX_NAME_28D
+ end
+end
diff --git a/db/migrate/20221006131506_add_free_user_cap_over_limit_notified_at_to_namespace_details.rb b/db/migrate/20221006131506_add_free_user_cap_over_limit_notified_at_to_namespace_details.rb
new file mode 100644
index 00000000000..7237eee18f0
--- /dev/null
+++ b/db/migrate/20221006131506_add_free_user_cap_over_limit_notified_at_to_namespace_details.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddFreeUserCapOverLimitNotifiedAtToNamespaceDetails < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = 'namespace_details'
+ COLUMN_NAME = 'free_user_cap_over_limit_notified_at'
+
+ def up
+ with_lock_retries do
+ add_column(TABLE_NAME, COLUMN_NAME, :datetime_with_timezone)
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column TABLE_NAME, COLUMN_NAME
+ end
+ end
+end
diff --git a/db/migrate/20221006141145_add_targets_to_elastic_reindexing_tasks.rb b/db/migrate/20221006141145_add_targets_to_elastic_reindexing_tasks.rb
new file mode 100644
index 00000000000..1631f8ae57e
--- /dev/null
+++ b/db/migrate/20221006141145_add_targets_to_elastic_reindexing_tasks.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddTargetsToElasticReindexingTasks < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :elastic_reindexing_tasks, :targets, :text, array: true
+ end
+end
diff --git a/db/migrate/20221008032350_add_password_expiration_migration.rb b/db/migrate/20221008032350_add_password_expiration_migration.rb
new file mode 100644
index 00000000000..7dbc73294bb
--- /dev/null
+++ b/db/migrate/20221008032350_add_password_expiration_migration.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddPasswordExpirationMigration < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :application_settings, :password_expiration_enabled, :boolean, default: false, null: false,
+ comment: 'JiHu-specific column'
+ add_column :application_settings, :password_expires_in_days, :integer, default: 90, null: false,
+ comment: 'JiHu-specific column'
+ add_column :application_settings, :password_expires_notice_before_days, :integer, default: 7, null: false,
+ comment: 'JiHu-specific column'
+ end
+end
diff --git a/db/migrate/20221009085130_add_mr_checks_columns_to_namespace_settings.rb b/db/migrate/20221009085130_add_mr_checks_columns_to_namespace_settings.rb
new file mode 100644
index 00000000000..947a662575a
--- /dev/null
+++ b/db/migrate/20221009085130_add_mr_checks_columns_to_namespace_settings.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddMrChecksColumnsToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :namespace_settings, :only_allow_merge_if_pipeline_succeeds, :boolean, default: false, null: false
+ add_column :namespace_settings, :allow_merge_on_skipped_pipeline, :boolean, default: false, null: false
+ add_column :namespace_settings, :only_allow_merge_if_all_discussions_are_resolved, \
+ :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20221011162637_add_partial_index_project_incident_management_settings_on_project_id_and_sla_timer.rb b/db/migrate/20221011162637_add_partial_index_project_incident_management_settings_on_project_id_and_sla_timer.rb
new file mode 100644
index 00000000000..4238311005c
--- /dev/null
+++ b/db/migrate/20221011162637_add_partial_index_project_incident_management_settings_on_project_id_and_sla_timer.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddPartialIndexProjectIncidentManagementSettingsOnProjectIdAndSlaTimer < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_project_incident_management_settings_on_p_id_sla_timer'
+
+ def up
+ add_concurrent_index :project_incident_management_settings, :project_id,
+ name: INDEX_NAME,
+ where: 'sla_timer = TRUE'
+ end
+
+ def down
+ remove_concurrent_index_by_name :project_incident_management_settings, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20221011210455_add_use_legacy_web_ide_to_user_preferences.rb b/db/migrate/20221011210455_add_use_legacy_web_ide_to_user_preferences.rb
new file mode 100644
index 00000000000..1b434e10ab0
--- /dev/null
+++ b/db/migrate/20221011210455_add_use_legacy_web_ide_to_user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddUseLegacyWebIdeToUserPreferences < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :user_preferences, :use_legacy_web_ide, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20221012033107_add_password_last_changed_at_to_user_details.rb b/db/migrate/20221012033107_add_password_last_changed_at_to_user_details.rb
new file mode 100644
index 00000000000..db2f411ab92
--- /dev/null
+++ b/db/migrate/20221012033107_add_password_last_changed_at_to_user_details.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddPasswordLastChangedAtToUserDetails < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :user_details, :password_last_changed_at, :datetime_with_timezone, comment: 'JiHu-specific column'
+ end
+end
diff --git a/db/migrate/20221012135524_add_scan_file_path_limit_for_dast_site_profile.rb b/db/migrate/20221012135524_add_scan_file_path_limit_for_dast_site_profile.rb
new file mode 100644
index 00000000000..ab8846c8043
--- /dev/null
+++ b/db/migrate/20221012135524_add_scan_file_path_limit_for_dast_site_profile.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddScanFilePathLimitForDastSiteProfile < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :dast_site_profiles, :scan_file_path, 1024
+ end
+
+ def down
+ remove_text_limit :dast_site_profiles, :scan_file_path
+ end
+end
diff --git a/db/migrate/20221014031033_add_temp_index_to_project_features_where_releases_access_level_gt_repository.rb b/db/migrate/20221014031033_add_temp_index_to_project_features_where_releases_access_level_gt_repository.rb
new file mode 100644
index 00000000000..14077e30780
--- /dev/null
+++ b/db/migrate/20221014031033_add_temp_index_to_project_features_where_releases_access_level_gt_repository.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddTempIndexToProjectFeaturesWhereReleasesAccessLevelGtRepository < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_idx_project_features_on_releases_al_and_repo_al_partial'
+
+ # Temporary index to be removed in 15.6 https://gitlab.com/gitlab-org/gitlab/-/issues/377915
+ def up
+ add_concurrent_index :project_features,
+ [:releases_access_level, :repository_access_level],
+ name: INDEX_NAME,
+ where: 'releases_access_level > repository_access_level'
+ end
+
+ def down
+ remove_concurrent_index_by_name :project_features, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20221014034338_populate_releases_access_level_from_repository.rb b/db/migrate/20221014034338_populate_releases_access_level_from_repository.rb
new file mode 100644
index 00000000000..6e61d972bf6
--- /dev/null
+++ b/db/migrate/20221014034338_populate_releases_access_level_from_repository.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class PopulateReleasesAccessLevelFromRepository < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ disable_ddl_transaction!
+
+ def up
+ update_column_in_batches(
+ :project_features,
+ :releases_access_level,
+ Arel.sql('repository_access_level')
+ ) do |table, query|
+ query.where(table[:releases_access_level].gt(table[:repository_access_level]))
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20221014190040_drop_notes_note_trigram_index.rb b/db/migrate/20221014190040_drop_notes_note_trigram_index.rb
new file mode 100644
index 00000000000..efa35b24d98
--- /dev/null
+++ b/db/migrate/20221014190040_drop_notes_note_trigram_index.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class DropNotesNoteTrigramIndex < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_notes_on_note_gin_trigram'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :notes, INDEX_NAME
+ end
+
+ def down
+ # no-op
+ # we never want to add this index back since it doesn't exist in production
+ # we are only using this migration to cleanup other environments where this index does exist
+ end
+end
diff --git a/db/migrate/20221018081416_members_remove_member_namespace_id_not_null_constraint.rb b/db/migrate/20221018081416_members_remove_member_namespace_id_not_null_constraint.rb
new file mode 100644
index 00000000000..e4cbcd24bc4
--- /dev/null
+++ b/db/migrate/20221018081416_members_remove_member_namespace_id_not_null_constraint.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class MembersRemoveMemberNamespaceIdNotNullConstraint < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'check_508774aac0'
+
+ def up
+ remove_not_null_constraint :members, :member_namespace_id, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ add_not_null_constraint :members, :member_namespace_id, validate: false, constraint_name: CONSTRAINT_NAME
+ end
+end
diff --git a/db/post_migrate/20220809002011_schedule_destroy_invalid_group_members.rb b/db/post_migrate/20220809002011_schedule_destroy_invalid_group_members.rb
index 3db21c290b9..e5d97d890ab 100644
--- a/db/post_migrate/20220809002011_schedule_destroy_invalid_group_members.rb
+++ b/db/post_migrate/20220809002011_schedule_destroy_invalid_group_members.rb
@@ -12,19 +12,11 @@ class ScheduleDestroyInvalidGroupMembers < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
- queue_batched_background_migration(
- MIGRATION,
- :members,
- :id,
- job_interval: DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- max_batch_size: MAX_BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE,
- gitlab_schema: :gitlab_main
- )
+ # no-op
+ # We want to no-op this due to potential inconsistencies in SM upgrade path
end
def down
- delete_batched_background_migration(MIGRATION, :members, :id, [])
+ # no-op
end
end
diff --git a/db/post_migrate/20220831090454_cleanup_web_hooks_service_id.rb b/db/post_migrate/20220831090454_cleanup_web_hooks_service_id.rb
new file mode 100644
index 00000000000..7beb89038e5
--- /dev/null
+++ b/db/post_migrate/20220831090454_cleanup_web_hooks_service_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CleanupWebHooksServiceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :web_hooks, :service_id, :integration_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :web_hooks, :service_id, :integration_id
+ end
+end
diff --git a/db/post_migrate/20220901035725_schedule_destroy_invalid_project_members.rb b/db/post_migrate/20220901035725_schedule_destroy_invalid_project_members.rb
index bc90232f855..9de3ac34669 100644
--- a/db/post_migrate/20220901035725_schedule_destroy_invalid_project_members.rb
+++ b/db/post_migrate/20220901035725_schedule_destroy_invalid_project_members.rb
@@ -10,19 +10,11 @@ class ScheduleDestroyInvalidProjectMembers < Gitlab::Database::Migration[2.0]
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
- queue_batched_background_migration(
- MIGRATION,
- :members,
- :id,
- job_interval: DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- max_batch_size: MAX_BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE,
- gitlab_schema: :gitlab_main
- )
+ # no-op
+ # We want to no-op this due to potential inconsistencies in SM upgrade path
end
def down
- delete_batched_background_migration(MIGRATION, :members, :id, [])
+ # no-op
end
end
diff --git a/db/post_migrate/20220905120848_backfill_epic_cache_counts.rb b/db/post_migrate/20220905120848_backfill_epic_cache_counts.rb
new file mode 100644
index 00000000000..32fe04eb99c
--- /dev/null
+++ b/db/post_migrate/20220905120848_backfill_epic_cache_counts.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class BackfillEpicCacheCounts < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'BackfillEpicCacheCounts'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 200
+ MAX_BATCH_SIZE = 1000
+ SUB_BATCH_SIZE = 20
+
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :epics,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE,
+ gitlab_schema: :gitlab_main
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :epics, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220907122648_populate_security_orchestration_policy_configuration_id.rb b/db/post_migrate/20220907122648_populate_security_orchestration_policy_configuration_id.rb
new file mode 100644
index 00000000000..441113c0ba3
--- /dev/null
+++ b/db/post_migrate/20220907122648_populate_security_orchestration_policy_configuration_id.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class PopulateSecurityOrchestrationPolicyConfigurationId < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ BATCH_SIZE = 1000
+ SUB_BATCH_SIZE = 500
+ MERGE_REQUEST_MIGRATION = 'PopulateApprovalMergeRequestRulesWithSecurityOrchestration'
+ PROJECT_MIGRATION = 'PopulateApprovalProjectRulesWithSecurityOrchestration'
+ INTERVAL = 2.minutes
+
+ def up
+ return unless Gitlab.ee?
+
+ queue_batched_background_migration(
+ PROJECT_MIGRATION,
+ :approval_project_rules,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+
+ queue_batched_background_migration(
+ MERGE_REQUEST_MIGRATION,
+ :approval_merge_request_rules,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(PROJECT_MIGRATION, :approval_project_rules, :id, [])
+ delete_batched_background_migration(MERGE_REQUEST_MIGRATION, :approval_merge_request_rules, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220915192521_prepare_async_trigram_index_for_vulnerability_reads_container_images.rb b/db/post_migrate/20220915192521_prepare_async_trigram_index_for_vulnerability_reads_container_images.rb
new file mode 100644
index 00000000000..18ed1b2cd2b
--- /dev/null
+++ b/db/post_migrate/20220915192521_prepare_async_trigram_index_for_vulnerability_reads_container_images.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class PrepareAsyncTrigramIndexForVulnerabilityReadsContainerImages < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerability_reads_on_location_image_trigram'
+ REPORT_TYPES = { container_scanning: 2, cluster_image_scanning: 7 }.freeze
+
+ def up
+ prepare_async_index :vulnerability_reads, :location_image,
+ name: INDEX_NAME,
+ using: :gin, opclass: { location_image: :gin_trgm_ops },
+ where: "report_type = ANY (ARRAY[#{REPORT_TYPES.values.join(', ')}]) AND location_image IS NOT NULL"
+ end
+
+ def down
+ unprepare_async_index :vulnerability_reads, :location_image, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220916054103_remove_experience_level_column.rb b/db/post_migrate/20220916054103_remove_experience_level_column.rb
new file mode 100644
index 00000000000..dff5a9a6580
--- /dev/null
+++ b/db/post_migrate/20220916054103_remove_experience_level_column.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveExperienceLevelColumn < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ remove_column :user_preferences, :experience_level
+ end
+
+ def down
+ add_column :user_preferences, :experience_level, :integer, limit: 2
+ end
+end
diff --git a/db/post_migrate/20220916065418_add_index_id_partition_id_to_ci_builds_metadata.rb b/db/post_migrate/20220916065418_add_index_id_partition_id_to_ci_builds_metadata.rb
new file mode 100644
index 00000000000..c781f2a9ef9
--- /dev/null
+++ b/db/post_migrate/20220916065418_add_index_id_partition_id_to_ci_builds_metadata.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddIndexIdPartitionIdToCiBuildsMetadata < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :ci_builds_metadata
+ INDEX_NAME = :index_ci_builds_metadata_on_id_partition_id_unique
+
+ def up
+ add_concurrent_index(TABLE_NAME, %i[id partition_id], unique: true, name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220916070101_add_index_build_id_partition_id_to_ci_build_metadata.rb b/db/post_migrate/20220916070101_add_index_build_id_partition_id_to_ci_build_metadata.rb
new file mode 100644
index 00000000000..18c24c47325
--- /dev/null
+++ b/db/post_migrate/20220916070101_add_index_build_id_partition_id_to_ci_build_metadata.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddIndexBuildIdPartitionIdToCiBuildMetadata < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :ci_builds_metadata
+ INDEX_NAME = :index_ci_builds_metadata_on_build_id_partition_id_unique
+
+ def up
+ add_concurrent_index(TABLE_NAME, %i[build_id partition_id], unique: true, name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220919023208_drop_unused_fields_from_merge_request_assignees.rb b/db/post_migrate/20220919023208_drop_unused_fields_from_merge_request_assignees.rb
new file mode 100644
index 00000000000..f1afbb41893
--- /dev/null
+++ b/db/post_migrate/20220919023208_drop_unused_fields_from_merge_request_assignees.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class DropUnusedFieldsFromMergeRequestAssignees < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ if column_exists?(:merge_request_assignees, :state) # rubocop:disable Style/IfUnlessModifier
+ remove_column :merge_request_assignees, :state
+ end
+
+ if column_exists?(:merge_request_assignees, :updated_state_by_user_id)
+ remove_column :merge_request_assignees, :updated_state_by_user_id
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ unless column_exists?(:merge_request_assignees, :state)
+ add_column :merge_request_assignees, :state, :smallint, default: 0, null: false
+ end
+
+ unless column_exists?(:merge_request_assignees, :updated_state_by_user_id)
+ add_column :merge_request_assignees, :updated_state_by_user_id, :bigint
+ end
+ end
+
+ add_concurrent_index :merge_request_assignees, [:user_id, :state],
+ where: 'state = 2',
+ name: 'index_on_merge_request_assignees_user_id_and_state'
+
+ add_concurrent_index :merge_request_assignees, :updated_state_by_user_id,
+ name: 'index_on_merge_request_assignees_updated_state_by_user_id'
+
+ add_concurrent_foreign_key :merge_request_assignees, :users,
+ column: :updated_state_by_user_id,
+ on_delete: :nullify
+ end
+end
diff --git a/db/post_migrate/20220919041604_drop_unused_fields_from_merge_request_reviewers.rb b/db/post_migrate/20220919041604_drop_unused_fields_from_merge_request_reviewers.rb
new file mode 100644
index 00000000000..d9f98557f75
--- /dev/null
+++ b/db/post_migrate/20220919041604_drop_unused_fields_from_merge_request_reviewers.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class DropUnusedFieldsFromMergeRequestReviewers < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ if column_exists?(:merge_request_reviewers, :updated_state_by_user_id)
+ remove_column :merge_request_reviewers, :updated_state_by_user_id
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ unless column_exists?(:merge_request_reviewers, :updated_state_by_user_id)
+ add_column :merge_request_reviewers, :updated_state_by_user_id, :bigint
+ end
+ end
+
+ add_concurrent_index :merge_request_reviewers, :updated_state_by_user_id,
+ name: 'index_on_merge_request_reviewers_updated_state_by_user_id'
+
+ add_concurrent_foreign_key :merge_request_reviewers, :users, column: :updated_state_by_user_id, on_delete: :nullify
+ end
+end
diff --git a/db/post_migrate/20220919050555_drop_tmp_index_user_callouts_on_attention_request_feature_names.rb b/db/post_migrate/20220919050555_drop_tmp_index_user_callouts_on_attention_request_feature_names.rb
new file mode 100644
index 00000000000..e456a91fe3f
--- /dev/null
+++ b/db/post_migrate/20220919050555_drop_tmp_index_user_callouts_on_attention_request_feature_names.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class DropTmpIndexUserCalloutsOnAttentionRequestFeatureNames < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "tmp_index_user_callouts_on_attention_request_feature_names"
+ ATTENTION_REQUEST_CALLOUTS = [47, 48]
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :user_callouts, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :user_callouts, [:id],
+ where: "feature_name IN (#{ATTENTION_REQUEST_CALLOUTS.join(',')})",
+ name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220920081631_prepare_ci_builds_metadata_for_partitioning_primary_key.rb b/db/post_migrate/20220920081631_prepare_ci_builds_metadata_for_partitioning_primary_key.rb
new file mode 100644
index 00000000000..90727178624
--- /dev/null
+++ b/db/post_migrate/20220920081631_prepare_ci_builds_metadata_for_partitioning_primary_key.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class PrepareCiBuildsMetadataForPartitioningPrimaryKey < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = 'ci_builds_metadata'
+ PRIMARY_KEY = 'ci_builds_metadata_pkey'
+ NEW_INDEX_NAME = 'index_ci_builds_metadata_on_id_partition_id_unique'
+ OLD_INDEX_NAME = 'index_ci_builds_metadata_on_id_unique'
+
+ def up
+ with_lock_retries(raise_on_exhaustion: true) do
+ execute("ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT #{PRIMARY_KEY} CASCADE")
+
+ rename_index(TABLE_NAME, NEW_INDEX_NAME, PRIMARY_KEY)
+
+ execute("ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT #{PRIMARY_KEY} " \
+ "PRIMARY KEY USING INDEX #{PRIMARY_KEY}")
+ end
+ end
+
+ # rolling back this migration is time consuming with the creation of these two indexes
+ def down
+ add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_INDEX_NAME)
+ add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_INDEX_NAME)
+
+ with_lock_retries(raise_on_exhaustion: true) do
+ execute("ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT #{PRIMARY_KEY} CASCADE")
+
+ rename_index(TABLE_NAME, OLD_INDEX_NAME, PRIMARY_KEY)
+
+ execute("ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT #{PRIMARY_KEY} " \
+ "PRIMARY KEY USING INDEX #{PRIMARY_KEY}")
+ end
+ end
+end
diff --git a/db/post_migrate/20220920122121_schedule_index_removal_for_ci_builds_metadata.rb b/db/post_migrate/20220920122121_schedule_index_removal_for_ci_builds_metadata.rb
new file mode 100644
index 00000000000..57475a08c93
--- /dev/null
+++ b/db/post_migrate/20220920122121_schedule_index_removal_for_ci_builds_metadata.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class ScheduleIndexRemovalForCiBuildsMetadata < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :ci_builds_metadata
+ INDEX_NAME = :index_ci_builds_metadata_on_build_id
+
+ def up
+ prepare_async_index_removal(TABLE_NAME, :build_id, name: INDEX_NAME)
+ end
+
+ def down
+ unprepare_async_index(TABLE_NAME, :build_id, name: INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220920124709_backfill_internal_on_notes.rb b/db/post_migrate/20220920124709_backfill_internal_on_notes.rb
new file mode 100644
index 00000000000..0d737195907
--- /dev/null
+++ b/db/post_migrate/20220920124709_backfill_internal_on_notes.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class BackfillInternalOnNotes < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'BackfillInternalOnNotes'
+ DELAY_INTERVAL = 2.minutes
+ TABLE = :notes
+ BATCH_SIZE = 2000
+ SUB_BATCH_SIZE = 10
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ TABLE,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, TABLE, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220920135356_tiebreak_user_type_index.rb b/db/post_migrate/20220920135356_tiebreak_user_type_index.rb
new file mode 100644
index 00000000000..778a957086f
--- /dev/null
+++ b/db/post_migrate/20220920135356_tiebreak_user_type_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class TiebreakUserTypeIndex < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'index_users_on_user_type_and_id'
+ OLD_INDEX_NAME = 'index_users_on_user_type'
+
+ def up
+ add_concurrent_index :users, [:user_type, :id], name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :users, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :users, :user_type, name: OLD_INDEX_NAME
+ remove_concurrent_index_by_name :users, NEW_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220920141001_add_index_on_internal_notes.rb b/db/post_migrate/20220920141001_add_index_on_internal_notes.rb
new file mode 100644
index 00000000000..466ad7b5a8d
--- /dev/null
+++ b/db/post_migrate/20220920141001_add_index_on_internal_notes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnInternalNotes < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_notes_on_id_where_internal'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :notes, :id, where: 'internal = true', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :notes, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220920213504_finalize_task_system_note_renaming.rb b/db/post_migrate/20220920213504_finalize_task_system_note_renaming.rb
new file mode 100644
index 00000000000..d9307c14ccb
--- /dev/null
+++ b/db/post_migrate/20220920213504_finalize_task_system_note_renaming.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class FinalizeTaskSystemNoteRenaming < Gitlab::Database::Migration[2.0]
+ def up
+ # no-op
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/post_migrate/20220920214524_remove_task_system_note_rename_temp_index.rb b/db/post_migrate/20220920214524_remove_task_system_note_rename_temp_index.rb
new file mode 100644
index 00000000000..d3671d24578
--- /dev/null
+++ b/db/post_migrate/20220920214524_remove_task_system_note_rename_temp_index.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RemoveTaskSystemNoteRenameTempIndex < Gitlab::Database::Migration[2.0]
+ def up
+ # no-op
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220921093355_schedule_backfill_namespace_details.rb b/db/post_migrate/20220921093355_schedule_backfill_namespace_details.rb
new file mode 100644
index 00000000000..16ce9bd5c85
--- /dev/null
+++ b/db/post_migrate/20220921093355_schedule_backfill_namespace_details.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class ScheduleBackfillNamespaceDetails < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'BackfillNamespaceDetails'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 1_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 200
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :namespaces,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :namespaces, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220921111823_remove_and_add_ci_pipeline_variables_raw_with_new_default.rb b/db/post_migrate/20220921111823_remove_and_add_ci_pipeline_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..fd56a8f320a
--- /dev/null
+++ b/db/post_migrate/20220921111823_remove_and_add_ci_pipeline_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiPipelineVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_pipeline_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_pipeline_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921111831_remove_and_add_ci_group_variables_raw_with_new_default.rb b/db/post_migrate/20220921111831_remove_and_add_ci_group_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..f4b7de3faf4
--- /dev/null
+++ b/db/post_migrate/20220921111831_remove_and_add_ci_group_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiGroupVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_group_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_group_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921111840_remove_and_add_ci_instance_variables_raw_with_new_default.rb b/db/post_migrate/20220921111840_remove_and_add_ci_instance_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..019db1bbaa3
--- /dev/null
+++ b/db/post_migrate/20220921111840_remove_and_add_ci_instance_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiInstanceVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_instance_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_instance_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921111849_remove_and_add_ci_job_variables_raw_with_new_default.rb b/db/post_migrate/20220921111849_remove_and_add_ci_job_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..736cd46382d
--- /dev/null
+++ b/db/post_migrate/20220921111849_remove_and_add_ci_job_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiJobVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_job_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_job_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921111857_remove_and_add_ci_pipeline_schedule_variables_raw_with_new_default.rb b/db/post_migrate/20220921111857_remove_and_add_ci_pipeline_schedule_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..159b0303d71
--- /dev/null
+++ b/db/post_migrate/20220921111857_remove_and_add_ci_pipeline_schedule_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiPipelineScheduleVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_pipeline_schedule_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_pipeline_schedule_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921111907_remove_and_add_ci_variables_raw_with_new_default.rb b/db/post_migrate/20220921111907_remove_and_add_ci_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..129e5b1f020
--- /dev/null
+++ b/db/post_migrate/20220921111907_remove_and_add_ci_variables_raw_with_new_default.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class RemoveAndAddCiVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_variables, :raw, :boolean, null: false, default: true
+ add_column :ci_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20220921144258_remove_orphan_group_token_users.rb b/db/post_migrate/20220921144258_remove_orphan_group_token_users.rb
new file mode 100644
index 00000000000..a2483f611a3
--- /dev/null
+++ b/db/post_migrate/20220921144258_remove_orphan_group_token_users.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class RemoveOrphanGroupTokenUsers < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ disable_ddl_transaction!
+
+ class MigrationUser < MigrationRecord
+ include EachBatch
+
+ self.table_name = 'users'
+
+ scope :project_bots, -> { where(user_type: 6) }
+ scope :without_memberships, -> { where("NOT EXISTS (SELECT 1 FROM members where members.user_id = users.id)") }
+ end
+
+ class MigrationPersonalAccessToken < MigrationRecord
+ self.table_name = 'personal_access_tokens'
+ end
+
+ def up
+ delete_worker = 'DeleteUserWorker'.safe_constantize
+
+ MigrationUser.project_bots.each_batch(of: 1000) do |batch|
+ bot_ids = batch.without_memberships.pluck(:id)
+
+ MigrationPersonalAccessToken.where(user_id: bot_ids).delete_all
+
+ next unless delete_worker && delete_worker.respond_to?(:perform_async)
+
+ bot_ids.each do |bot_id|
+ delete_worker.perform_async(bot_id, bot_id, skip_authorization: true)
+ end
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220922090236_remove_trace_column_from_ci_builds.rb b/db/post_migrate/20220922090236_remove_trace_column_from_ci_builds.rb
new file mode 100644
index 00000000000..e1871a9799f
--- /dev/null
+++ b/db/post_migrate/20220922090236_remove_trace_column_from_ci_builds.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class RemoveTraceColumnFromCiBuilds < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_builds, :trace, :text
+ end
+end
diff --git a/db/post_migrate/20220922143143_schedule_reset_duplicate_ci_runners_token_values.rb b/db/post_migrate/20220922143143_schedule_reset_duplicate_ci_runners_token_values.rb
new file mode 100644
index 00000000000..fd02bda8004
--- /dev/null
+++ b/db/post_migrate/20220922143143_schedule_reset_duplicate_ci_runners_token_values.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class ScheduleResetDuplicateCiRunnersTokenValues < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_ci
+ disable_ddl_transaction!
+
+ MIGRATION = 'ResetDuplicateCiRunnersTokenValues'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 2_000
+ MAX_BATCH_SIZE = 100_000
+ SUB_BATCH_SIZE = 500
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :ci_runners,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :ci_runners, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values.rb b/db/post_migrate/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values.rb
new file mode 100644
index 00000000000..bbbf9a1db44
--- /dev/null
+++ b/db/post_migrate/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class ScheduleResetDuplicateCiRunnersTokenEncryptedValues < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_ci
+ disable_ddl_transaction!
+
+ MIGRATION = 'ResetDuplicateCiRunnersTokenEncryptedValues'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 2_000
+ MAX_BATCH_SIZE = 100_000
+ SUB_BATCH_SIZE = 500
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :ci_runners,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :ci_runners, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220922204106_remove_index_for_requested_non_invited_awaiting_members.rb b/db/post_migrate/20220922204106_remove_index_for_requested_non_invited_awaiting_members.rb
new file mode 100644
index 00000000000..033b04a75f8
--- /dev/null
+++ b/db/post_migrate/20220922204106_remove_index_for_requested_non_invited_awaiting_members.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexForRequestedNonInvitedAwaitingMembers < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_members_on_non_requested_non_invited_and_state_awaiting'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :members, INDEX_NAME
+ end
+
+ def down
+ clause = '((requested_at IS NULL) AND (invite_token IS NULL) AND (access_level > 5) AND (state = 1))'
+
+ add_concurrent_index :members, :source_id, where: clause, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220923052531_remove_tmp_index_merge_request_reviewers_on_attention_requested_state.rb b/db/post_migrate/20220923052531_remove_tmp_index_merge_request_reviewers_on_attention_requested_state.rb
new file mode 100644
index 00000000000..27d9c1641bc
--- /dev/null
+++ b/db/post_migrate/20220923052531_remove_tmp_index_merge_request_reviewers_on_attention_requested_state.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveTmpIndexMergeRequestReviewersOnAttentionRequestedState < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "tmp_index_merge_request_reviewers_on_attention_requested_state"
+ ATTENTION_REQUESTED_STATE = 2
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :merge_request_reviewers, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :merge_request_reviewers, [:id],
+ where: "state = #{ATTENTION_REQUESTED_STATE}",
+ name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220923060226_remove_tmp_index_system_note_metadata_on_attention_request_actions.rb b/db/post_migrate/20220923060226_remove_tmp_index_system_note_metadata_on_attention_request_actions.rb
new file mode 100644
index 00000000000..40e8c1cfdb5
--- /dev/null
+++ b/db/post_migrate/20220923060226_remove_tmp_index_system_note_metadata_on_attention_request_actions.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveTmpIndexSystemNoteMetadataOnAttentionRequestActions < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "tmp_index_system_note_metadata_on_attention_request_actions"
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :system_note_metadata, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :system_note_metadata, [:id],
+ where: "action IN ('attention_requested', 'attention_request_removed')",
+ name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status.rb b/db/post_migrate/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status.rb
new file mode 100644
index 00000000000..0d7a5dc4bec
--- /dev/null
+++ b/db/post_migrate/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class ScheduleUpdateCiPipelineArtifactsLockedStatus < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ MIGRATION = 'UpdateCiPipelineArtifactsUnknownLockedStatus'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 1_000
+ SUB_BATCH_SIZE = 500
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_ci
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :ci_pipeline_artifacts,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :ci_pipeline_artifacts, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220929081645_tmp_idx_null_member_namespace_id.rb b/db/post_migrate/20220929081645_tmp_idx_null_member_namespace_id.rb
new file mode 100644
index 00000000000..58d6c653e6f
--- /dev/null
+++ b/db/post_migrate/20220929081645_tmp_idx_null_member_namespace_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class TmpIdxNullMemberNamespaceId < Gitlab::Database::Migration[2.0]
+ TMP_INDEX_FOR_NULL_MEMBER_NAMESPACE_ID = 'tmp_index_for_null_member_namespace_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :members, :member_namespace_id,
+ name: TMP_INDEX_FOR_NULL_MEMBER_NAMESPACE_ID,
+ where: 'member_namespace_id IS NULL'
+ end
+
+ def down
+ remove_concurrent_index_by_name :members, name: TMP_INDEX_FOR_NULL_MEMBER_NAMESPACE_ID
+ end
+end
diff --git a/db/post_migrate/20220929091500_add_tmp_index_vulns_on_report_type.rb b/db/post_migrate/20220929091500_add_tmp_index_vulns_on_report_type.rb
new file mode 100644
index 00000000000..19100e1d0cc
--- /dev/null
+++ b/db/post_migrate/20220929091500_add_tmp_index_vulns_on_report_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+class AddTmpIndexVulnsOnReportType < Gitlab::Database::Migration[2.0]
+ # Temporary index to perform migration removing invalid vulnerabilities
+ INDEX_NAME = 'tmp_idx_vulnerabilities_on_id_where_report_type_7_99'
+
+ REPORT_TYPES = {
+ cluster_image_scanning: 7,
+ custom: 99
+ }
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerabilities, :id,
+ where: "report_type IN (#{REPORT_TYPES.values.join(', ')})",
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220929101947_delete_remove_invalid_member_migration.rb b/db/post_migrate/20220929101947_delete_remove_invalid_member_migration.rb
new file mode 100644
index 00000000000..6fb358e57ab
--- /dev/null
+++ b/db/post_migrate/20220929101947_delete_remove_invalid_member_migration.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DeleteRemoveInvalidMemberMigration < Gitlab::Database::Migration[2.0]
+ PROJECT_MEMBER_MIGRATION = 'ScheduleDestroyInvalidProjectMembers'
+ GROUP_MEMBER_MIGRATION = 'ScheduleDestroyInvalidGroupMembers'
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ delete_batched_background_migration(PROJECT_MEMBER_MIGRATION, :members, :id, [])
+ delete_batched_background_migration(GROUP_MEMBER_MIGRATION, :members, :id, [])
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220929194453_add_index_releases_project_id_id.rb b/db/post_migrate/20220929194453_add_index_releases_project_id_id.rb
new file mode 100644
index 00000000000..179b5a636f0
--- /dev/null
+++ b/db/post_migrate/20220929194453_add_index_releases_project_id_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexReleasesProjectIdId < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_releases_on_project_id_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :releases, %i[project_id id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :releases, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220929213730_schedule_delete_orphaned_operational_vulnerabilities.rb b/db/post_migrate/20220929213730_schedule_delete_orphaned_operational_vulnerabilities.rb
new file mode 100644
index 00000000000..c03358b1fda
--- /dev/null
+++ b/db/post_migrate/20220929213730_schedule_delete_orphaned_operational_vulnerabilities.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ScheduleDeleteOrphanedOperationalVulnerabilities < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'DeleteOrphanedOperationalVulnerabilities'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 10_000
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :vulnerabilities,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :vulnerabilities, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220930110127_remove_unique_index_build_id_to_ci_builds_metadata.rb b/db/post_migrate/20220930110127_remove_unique_index_build_id_to_ci_builds_metadata.rb
new file mode 100644
index 00000000000..4c23cdc5284
--- /dev/null
+++ b/db/post_migrate/20220930110127_remove_unique_index_build_id_to_ci_builds_metadata.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class RemoveUniqueIndexBuildIdToCiBuildsMetadata < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :ci_builds_metadata
+ INDEX_NAME = :index_ci_builds_metadata_on_build_id
+
+ def up
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, :build_id, unique: true, name: INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20221003192827_add_index_resolved_on_default_branch_to_vulnerabilities_read.rb b/db/post_migrate/20221003192827_add_index_resolved_on_default_branch_to_vulnerabilities_read.rb
new file mode 100644
index 00000000000..e352e324187
--- /dev/null
+++ b/db/post_migrate/20221003192827_add_index_resolved_on_default_branch_to_vulnerabilities_read.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexResolvedOnDefaultBranchToVulnerabilitiesRead < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vuln_reads_on_resolved_on_default_branch'
+ COLUMNS = %i[project_id state id]
+
+ def up
+ add_concurrent_index :vulnerability_reads, COLUMNS,
+ where: 'resolved_on_default_branch IS TRUE',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_reads, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221004092038_tmp_index_members_on_id_where_namespace_id_null.rb b/db/post_migrate/20221004092038_tmp_index_members_on_id_where_namespace_id_null.rb
new file mode 100644
index 00000000000..68a707e99c2
--- /dev/null
+++ b/db/post_migrate/20221004092038_tmp_index_members_on_id_where_namespace_id_null.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class TmpIndexMembersOnIdWhereNamespaceIdNull < Gitlab::Database::Migration[2.0]
+ TMP_INDEX = 'tmp_index_members_on_id_where_namespace_id_null'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :members, :id,
+ name: TMP_INDEX,
+ where: 'member_namespace_id IS NULL'
+ end
+
+ def down
+ remove_concurrent_index_by_name :members, name: TMP_INDEX
+ end
+end
diff --git a/db/post_migrate/20221004094814_schedule_destroy_invalid_members.rb b/db/post_migrate/20221004094814_schedule_destroy_invalid_members.rb
new file mode 100644
index 00000000000..fa6a1fd5f72
--- /dev/null
+++ b/db/post_migrate/20221004094814_schedule_destroy_invalid_members.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+class ScheduleDestroyInvalidMembers < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'DestroyInvalidMembers'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 1_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 200
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :members,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE,
+ gitlab_schema: :gitlab_main
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :members, :id, [])
+ end
+end
diff --git a/db/post_migrate/20221005103000_add_index_merge_request_id_on_scan_finding_approval_merge_request_rules.rb b/db/post_migrate/20221005103000_add_index_merge_request_id_on_scan_finding_approval_merge_request_rules.rb
new file mode 100644
index 00000000000..06bf21b894a
--- /dev/null
+++ b/db/post_migrate/20221005103000_add_index_merge_request_id_on_scan_finding_approval_merge_request_rules.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexMergeRequestIdOnScanFindingApprovalMergeRequestRules < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'scan_finding_approval_mr_rule_index_merge_request_id'
+ SCAN_FINDING_REPORT_TYPE = 4
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :approval_merge_request_rules, :merge_request_id,
+ where: "report_type = #{SCAN_FINDING_REPORT_TYPE}", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :approval_merge_request_rules, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221006083240_prepare_partial_trigram_indexes_for_issues_attempt_2.rb b/db/post_migrate/20221006083240_prepare_partial_trigram_indexes_for_issues_attempt_2.rb
new file mode 100644
index 00000000000..6ca2ba222ae
--- /dev/null
+++ b/db/post_migrate/20221006083240_prepare_partial_trigram_indexes_for_issues_attempt_2.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class PreparePartialTrigramIndexesForIssuesAttempt2 < Gitlab::Database::Migration[2.0]
+ TITLE_INDEX_NAME = 'index_issues_on_title_trigram_non_latin'
+ DESCRIPTION_INDEX_NAME = 'index_issues_on_description_trigram_non_latin'
+
+ def up
+ prepare_async_index :issues, :title,
+ name: TITLE_INDEX_NAME,
+ using: :gin, opclass: { description: :gin_trgm_ops },
+ where: "title NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*' " \
+ "OR description NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*'"
+
+ prepare_async_index :issues, :description,
+ name: DESCRIPTION_INDEX_NAME,
+ using: :gin, opclass: { description: :gin_trgm_ops },
+ where: "title NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*' " \
+ "OR description NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*'"
+ end
+
+ def down
+ unprepare_async_index_by_name :issues, DESCRIPTION_INDEX_NAME
+ unprepare_async_index_by_name :issues, TITLE_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221006172302_adjust_task_note_rename_background_migration_values.rb b/db/post_migrate/20221006172302_adjust_task_note_rename_background_migration_values.rb
new file mode 100644
index 00000000000..2af16fb6d3c
--- /dev/null
+++ b/db/post_migrate/20221006172302_adjust_task_note_rename_background_migration_values.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+class AdjustTaskNoteRenameBackgroundMigrationValues < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ JOB_CLASS_NAME = 'RenameTaskSystemNoteToChecklistItem'
+ MIGRATION_FAILED_STATUS = 4
+ MIGRATION_FINISHED_STATUS = 3
+ MIGRATION_ACTIVE_STATUS = 1
+ JOB_FAILED_STATUS = 2
+
+ OLD_BATCH_SIZE = 10_000
+ NEW_BATCH_SIZE = 5_000
+
+ OLD_SUB_BATCH_SIZE = 100
+ NEW_SUB_BATCH_SIZE = 10
+
+ class InlineBatchedMigration < MigrationRecord
+ self.table_name = :batched_background_migrations
+
+ scope :for_configuration, ->(job_class_name, table_name, column_name, job_arguments) do
+ where(job_class_name: job_class_name, table_name: table_name, column_name: column_name)
+ .where("job_arguments = ?", job_arguments.to_json) # rubocop:disable Rails/WhereEquals
+ end
+ end
+
+ class InlineBatchedJob < MigrationRecord
+ include EachBatch
+ self.table_name = :batched_background_migration_jobs
+ end
+
+ def up
+ migration = InlineBatchedMigration.for_configuration(
+ JOB_CLASS_NAME,
+ :system_note_metadata,
+ :id,
+ []
+ ).first
+ return if migration.blank? || migration.status == MIGRATION_FINISHED_STATUS
+
+ InlineBatchedJob.where(
+ batched_background_migration_id: migration.id,
+ status: JOB_FAILED_STATUS
+ ).each_batch(of: 100) do |batch|
+ batch.update_all(attempts: 0, sub_batch_size: NEW_SUB_BATCH_SIZE)
+ end
+
+ update_params = { batch_size: NEW_BATCH_SIZE, sub_batch_size: NEW_SUB_BATCH_SIZE }
+
+ if migration.status == MIGRATION_FAILED_STATUS
+ update_params[:status] = MIGRATION_ACTIVE_STATUS
+ update_params[:started_at] = Time.zone.now if migration.respond_to?(:started_at)
+ end
+
+ migration.update!(**update_params)
+ end
+
+ def down
+ migration = InlineBatchedMigration.for_configuration(
+ JOB_CLASS_NAME,
+ :system_note_metadata,
+ :id,
+ []
+ ).first
+ return if migration.blank?
+
+ migration.update!(
+ batch_size: OLD_BATCH_SIZE,
+ sub_batch_size: OLD_SUB_BATCH_SIZE
+ )
+ end
+end
diff --git a/db/post_migrate/20221010074914_migrate_security_findings_delete_queues.rb b/db/post_migrate/20221010074914_migrate_security_findings_delete_queues.rb
new file mode 100644
index 00000000000..ce593e19859
--- /dev/null
+++ b/db/post_migrate/20221010074914_migrate_security_findings_delete_queues.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class MigrateSecurityFindingsDeleteQueues < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+ disable_ddl_transaction!
+
+ def up
+ sidekiq_queue_migrate 'security_findings_delete_by_job_id', to: 'security_scans_purge_by_job_id'
+ sidekiq_queue_migrate 'cronjob:security_findings_cleanup', to: 'cronjob:security_scans_purge'
+ end
+
+ def down
+ sidekiq_queue_migrate 'security_scans_purge_by_job_id', to: 'security_findings_delete_by_job_id'
+ sidekiq_queue_migrate 'cronjob:security_scans_purge', to: 'cronjob:security_findings_cleanup'
+ end
+end
diff --git a/db/post_migrate/20221010121510_prepare_async_index_author_id_target_project_id_on_merge_requests.rb b/db/post_migrate/20221010121510_prepare_async_index_author_id_target_project_id_on_merge_requests.rb
new file mode 100644
index 00000000000..cd9035dd9f9
--- /dev/null
+++ b/db/post_migrate/20221010121510_prepare_async_index_author_id_target_project_id_on_merge_requests.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class PrepareAsyncIndexAuthorIdTargetProjectIdOnMergeRequests < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_merge_requests_on_author_id_and_target_project_id'
+
+ disable_ddl_transaction!
+
+ def up
+ prepare_async_index :merge_requests, %i[author_id target_project_id], name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :merge_requests, %i[author_id target_project_id], name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221010121807_add_compliance_framework_id_to_namespace_settings.rb b/db/post_migrate/20221010121807_add_compliance_framework_id_to_namespace_settings.rb
new file mode 100644
index 00000000000..e07f19242d5
--- /dev/null
+++ b/db/post_migrate/20221010121807_add_compliance_framework_id_to_namespace_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddComplianceFrameworkIdToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :namespace_settings, :default_compliance_framework_id, :bigint
+ end
+end
diff --git a/db/post_migrate/20221010122138_add_async_index_author_id_target_project_id_on_merge_requests.rb b/db/post_migrate/20221010122138_add_async_index_author_id_target_project_id_on_merge_requests.rb
new file mode 100644
index 00000000000..0689c090d09
--- /dev/null
+++ b/db/post_migrate/20221010122138_add_async_index_author_id_target_project_id_on_merge_requests.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddAsyncIndexAuthorIdTargetProjectIdOnMergeRequests < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_merge_requests_on_author_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ prepare_async_index :merge_requests, %i[author_id id], name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :merge_requests, %i[author_id id], name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221010122352_add_index_to_namespace_settings_on_default_compliance_framework_id.rb b/db/post_migrate/20221010122352_add_index_to_namespace_settings_on_default_compliance_framework_id.rb
new file mode 100644
index 00000000000..63de7942208
--- /dev/null
+++ b/db/post_migrate/20221010122352_add_index_to_namespace_settings_on_default_compliance_framework_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToNamespaceSettingsOnDefaultComplianceFrameworkId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'idx_namespace_settings_on_default_compliance_framework_id'
+
+ def up
+ add_concurrent_index :namespace_settings, :default_compliance_framework_id, unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :namespace_settings, :default_compliance_framework_id, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20221010123040_add_compliance_framework_fk_to_namespace_settings.rb b/db/post_migrate/20221010123040_add_compliance_framework_fk_to_namespace_settings.rb
new file mode 100644
index 00000000000..5d4966fd580
--- /dev/null
+++ b/db/post_migrate/20221010123040_add_compliance_framework_fk_to_namespace_settings.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddComplianceFrameworkFkToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :namespace_settings, :compliance_management_frameworks,
+ column: :default_compliance_framework_id, on_delete: :nullify, reverse_lock_order: true
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :namespace_settings, column: :default_compliance_framework_id
+ end
+ end
+end
diff --git a/db/post_migrate/20221011113928_redo_remove_and_add_ci_job_variables_raw_with_new_default.rb b/db/post_migrate/20221011113928_redo_remove_and_add_ci_job_variables_raw_with_new_default.rb
new file mode 100644
index 00000000000..a377b78803e
--- /dev/null
+++ b/db/post_migrate/20221011113928_redo_remove_and_add_ci_job_variables_raw_with_new_default.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class RedoRemoveAndAddCiJobVariablesRawWithNewDefault < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ # We are removing and adding the same column with the same parameters to refresh the table
+ # because we have some wrong `ci_job_variables.raw` data (`TRUE`) in the database.
+ def change
+ remove_column :ci_job_variables, :raw, :boolean, null: false, default: false
+ add_column :ci_job_variables, :raw, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20221012182701_remove_namespace_settings_cohort_free_user_cap_columns.rb b/db/post_migrate/20221012182701_remove_namespace_settings_cohort_free_user_cap_columns.rb
new file mode 100644
index 00000000000..36408ad19ed
--- /dev/null
+++ b/db/post_migrate/20221012182701_remove_namespace_settings_cohort_free_user_cap_columns.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveNamespaceSettingsCohortFreeUserCapColumns < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ remove_column :namespace_settings, :exclude_from_free_user_cap
+ remove_column :namespace_settings, :include_for_free_user_cap_preview
+ end
+
+ def down
+ add_column :namespace_settings, :exclude_from_free_user_cap, :boolean, null: false, default: false
+ add_column :namespace_settings, :include_for_free_user_cap_preview, :boolean, null: false, default: false
+ end
+end
diff --git a/db/post_migrate/20221013154159_update_invalid_dormant_user_setting.rb b/db/post_migrate/20221013154159_update_invalid_dormant_user_setting.rb
new file mode 100644
index 00000000000..1f1e47fdac1
--- /dev/null
+++ b/db/post_migrate/20221013154159_update_invalid_dormant_user_setting.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class UpdateInvalidDormantUserSetting < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ # rubocop:disable Layout/LineLength
+ def up
+ execute("update application_settings set deactivate_dormant_users_period=90 where deactivate_dormant_users_period < 90")
+ end
+ # rubocop:enable Layout/LineLength
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
deleted file mode 100644
index 26ce2ed69c4..00000000000
--- a/db/schema.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# Disabled in favour of structure.sql
-# Please refer to https://gitlab.com/gitlab-org/gitlab/-/issues/211487 for details
-
-raise 'schema.rb should not be used anymore, use structure.sql instead'
-
diff --git a/db/schema_migrations/20220126191624 b/db/schema_migrations/20220126191624
new file mode 100644
index 00000000000..f8cbab24379
--- /dev/null
+++ b/db/schema_migrations/20220126191624
@@ -0,0 +1 @@
+33170856a78b469c63d4821692929a1df0c41e4b9d98093e771b122b462c9c03 \ No newline at end of file
diff --git a/db/schema_migrations/20220615172230 b/db/schema_migrations/20220615172230
new file mode 100644
index 00000000000..43057debe67
--- /dev/null
+++ b/db/schema_migrations/20220615172230
@@ -0,0 +1 @@
+364a2f729196e4bd4bde635f7550df3cf0c005fa002840fa12745d8919a99147 \ No newline at end of file
diff --git a/db/schema_migrations/20220802200719 b/db/schema_migrations/20220802200719
new file mode 100644
index 00000000000..a4798a7e79e
--- /dev/null
+++ b/db/schema_migrations/20220802200719
@@ -0,0 +1 @@
+e27e9430a06f0586dd4ed9419c8f5747d64509e89f4f3481d8341261cfec82c5 \ No newline at end of file
diff --git a/db/schema_migrations/20220802202505 b/db/schema_migrations/20220802202505
new file mode 100644
index 00000000000..f6a72f8c3c5
--- /dev/null
+++ b/db/schema_migrations/20220802202505
@@ -0,0 +1 @@
+aacf5e416de30f594ea012c3dd3cb1a3bd10d2edd2d312aedf7147a8cde32928 \ No newline at end of file
diff --git a/db/schema_migrations/20220805180311 b/db/schema_migrations/20220805180311
new file mode 100644
index 00000000000..dff18ebd3fc
--- /dev/null
+++ b/db/schema_migrations/20220805180311
@@ -0,0 +1 @@
+35335f40a192889c45f71a8a3b25dd0e7024919ff823b01c2086c0e6959869e0 \ No newline at end of file
diff --git a/db/schema_migrations/20220805183952 b/db/schema_migrations/20220805183952
new file mode 100644
index 00000000000..c1a1c03dcef
--- /dev/null
+++ b/db/schema_migrations/20220805183952
@@ -0,0 +1 @@
+a90c4b56f6cf16ec62d4a37e03add702ce8d64640b1c61f6f0b18b2d9720f24e \ No newline at end of file
diff --git a/db/schema_migrations/20220805193117 b/db/schema_migrations/20220805193117
new file mode 100644
index 00000000000..36523ba0866
--- /dev/null
+++ b/db/schema_migrations/20220805193117
@@ -0,0 +1 @@
+f64b85003dde31c4f0ba37cb0b550fb50b8d7753bbae3043f28ed51858349572 \ No newline at end of file
diff --git a/db/schema_migrations/20220818125332 b/db/schema_migrations/20220818125332
new file mode 100644
index 00000000000..35c76c4318f
--- /dev/null
+++ b/db/schema_migrations/20220818125332
@@ -0,0 +1 @@
+ebcf446aa6579d93c57c2e96e8b670a43bcb6e20216f33a7f535e1bed50ace62 \ No newline at end of file
diff --git a/db/schema_migrations/20220818125703 b/db/schema_migrations/20220818125703
new file mode 100644
index 00000000000..1bfebfc50ad
--- /dev/null
+++ b/db/schema_migrations/20220818125703
@@ -0,0 +1 @@
+b60f36cd83174ce257baba4a74f0fcba6cd462fa2af6530ff5a3341536058e12 \ No newline at end of file
diff --git a/db/schema_migrations/20220818140553 b/db/schema_migrations/20220818140553
new file mode 100644
index 00000000000..deedcc9d4b8
--- /dev/null
+++ b/db/schema_migrations/20220818140553
@@ -0,0 +1 @@
+f46a411a6519723cd2ee0a5b287f26f987195ba76e5753febe47502b1152a543 \ No newline at end of file
diff --git a/db/schema_migrations/20220819184945 b/db/schema_migrations/20220819184945
new file mode 100644
index 00000000000..511b13fc6cd
--- /dev/null
+++ b/db/schema_migrations/20220819184945
@@ -0,0 +1 @@
+3655ee5c3c963d0e413bce86eb9c74cc7bc71c3ab5acb54c76daacff8ff07354 \ No newline at end of file
diff --git a/db/schema_migrations/20220831090454 b/db/schema_migrations/20220831090454
new file mode 100644
index 00000000000..70f41257873
--- /dev/null
+++ b/db/schema_migrations/20220831090454
@@ -0,0 +1 @@
+681514d675382385f77cbcb5ec22038555670f95a35f1ced42554452718bd193 \ No newline at end of file
diff --git a/db/schema_migrations/20220901090004 b/db/schema_migrations/20220901090004
new file mode 100644
index 00000000000..a0302cfe1ed
--- /dev/null
+++ b/db/schema_migrations/20220901090004
@@ -0,0 +1 @@
+eab8630158a70df1246bf5c12c2d93d9fa855140c65bde4665d1d13f371b561c \ No newline at end of file
diff --git a/db/schema_migrations/20220901092853 b/db/schema_migrations/20220901092853
new file mode 100644
index 00000000000..2ebe0b9ffee
--- /dev/null
+++ b/db/schema_migrations/20220901092853
@@ -0,0 +1 @@
+0d134b0f3ba5adcc515072a2c1f995f3f3a89f298ee84f1f58c2f7afb0b85a0f \ No newline at end of file
diff --git a/db/schema_migrations/20220901114501 b/db/schema_migrations/20220901114501
new file mode 100644
index 00000000000..e3367fb7612
--- /dev/null
+++ b/db/schema_migrations/20220901114501
@@ -0,0 +1 @@
+2c18be04f3b5800c84a50763e7650229a6ae02619a2913966af2c936d3d9aec1 \ No newline at end of file
diff --git a/db/schema_migrations/20220905120848 b/db/schema_migrations/20220905120848
new file mode 100644
index 00000000000..ebfd3a0b59c
--- /dev/null
+++ b/db/schema_migrations/20220905120848
@@ -0,0 +1 @@
+f8196de8a4c8f6e8c6790c0d741b0deb455c533a35f665fffeb70c833d0ecd29 \ No newline at end of file
diff --git a/db/schema_migrations/20220907115806 b/db/schema_migrations/20220907115806
new file mode 100644
index 00000000000..878ac923880
--- /dev/null
+++ b/db/schema_migrations/20220907115806
@@ -0,0 +1 @@
+bfc9595c9e33afecd07721ab03548bdc5d9dda5be8fff180d84fc644f6c8c977 \ No newline at end of file
diff --git a/db/schema_migrations/20220907122648 b/db/schema_migrations/20220907122648
new file mode 100644
index 00000000000..1f743d593c2
--- /dev/null
+++ b/db/schema_migrations/20220907122648
@@ -0,0 +1 @@
+b576db8eb36b1d214788d301fd756d247c3fa33e13b7083e27c42735b48483e0 \ No newline at end of file
diff --git a/db/schema_migrations/20220912153839 b/db/schema_migrations/20220912153839
new file mode 100644
index 00000000000..26666148feb
--- /dev/null
+++ b/db/schema_migrations/20220912153839
@@ -0,0 +1 @@
+9cb59a045dd09fc956683e976d127f8f2346b2b26c25eeeadc4b0ef838fa1d02 \ No newline at end of file
diff --git a/db/schema_migrations/20220913043728 b/db/schema_migrations/20220913043728
new file mode 100644
index 00000000000..80dd2b0c9a4
--- /dev/null
+++ b/db/schema_migrations/20220913043728
@@ -0,0 +1 @@
+ae25d97cf0f867578fd0308ac4b2dea82710973bb2b6d9df58531b1586462838 \ No newline at end of file
diff --git a/db/schema_migrations/20220913082824 b/db/schema_migrations/20220913082824
new file mode 100644
index 00000000000..550ef78804b
--- /dev/null
+++ b/db/schema_migrations/20220913082824
@@ -0,0 +1 @@
+8776d132d5f95969003edf7f56213206f2321bc1963b80a50006d07f0c9f3bf4 \ No newline at end of file
diff --git a/db/schema_migrations/20220913084123 b/db/schema_migrations/20220913084123
new file mode 100644
index 00000000000..1791350c1fc
--- /dev/null
+++ b/db/schema_migrations/20220913084123
@@ -0,0 +1 @@
+e43e754e52339fe333bb91c0b098a394cb211c1dcec36fad023cfa954ecfe5c0 \ No newline at end of file
diff --git a/db/schema_migrations/20220914070927 b/db/schema_migrations/20220914070927
new file mode 100644
index 00000000000..7ff18f80def
--- /dev/null
+++ b/db/schema_migrations/20220914070927
@@ -0,0 +1 @@
+d8a610c72f2009f3beb89ef2da4d703d3d79e4abfc9c18579eecb03bde4e0683 \ No newline at end of file
diff --git a/db/schema_migrations/20220914080716 b/db/schema_migrations/20220914080716
new file mode 100644
index 00000000000..7c807e61c26
--- /dev/null
+++ b/db/schema_migrations/20220914080716
@@ -0,0 +1 @@
+ffa421a7ffc279cb2751ed9e74c212ab60a3b6f7722d15023d39f7ad97ff1e6c \ No newline at end of file
diff --git a/db/schema_migrations/20220914112457 b/db/schema_migrations/20220914112457
new file mode 100644
index 00000000000..ab67d0abb99
--- /dev/null
+++ b/db/schema_migrations/20220914112457
@@ -0,0 +1 @@
+766866e84cdafce6506f18e574e1cfb760a581fa7464ce7e29c31d9778c687c0 \ No newline at end of file
diff --git a/db/schema_migrations/20220914130800 b/db/schema_migrations/20220914130800
new file mode 100644
index 00000000000..2fab1dfd4b9
--- /dev/null
+++ b/db/schema_migrations/20220914130800
@@ -0,0 +1 @@
+c0a3269fbd44428439932f3b12b154425eafaab0b0638f7f27a03e784d0f0e32 \ No newline at end of file
diff --git a/db/schema_migrations/20220914131449 b/db/schema_migrations/20220914131449
new file mode 100644
index 00000000000..f735b7867d1
--- /dev/null
+++ b/db/schema_migrations/20220914131449
@@ -0,0 +1 @@
+205f1fee1ed33a2b069e51a76b94c72702300c72c4705569be2368f8804f3bce \ No newline at end of file
diff --git a/db/schema_migrations/20220914174705 b/db/schema_migrations/20220914174705
new file mode 100644
index 00000000000..2ef8c90a31f
--- /dev/null
+++ b/db/schema_migrations/20220914174705
@@ -0,0 +1 @@
+f481a617b3fc4fa95daec75619029dc8ef3a02d55e86b940eda78d6a93e6e78b \ No newline at end of file
diff --git a/db/schema_migrations/20220915192521 b/db/schema_migrations/20220915192521
new file mode 100644
index 00000000000..ce848d0f186
--- /dev/null
+++ b/db/schema_migrations/20220915192521
@@ -0,0 +1 @@
+9686a948e67f25d64f66187db27699b838b2caef11f27884dd6e868e4bcf7d47 \ No newline at end of file
diff --git a/db/schema_migrations/20220916054103 b/db/schema_migrations/20220916054103
new file mode 100644
index 00000000000..ab7f027f7ce
--- /dev/null
+++ b/db/schema_migrations/20220916054103
@@ -0,0 +1 @@
+d410d105f8af6948dba3efc37469048435237c1e21faa10e66836c85acf33728 \ No newline at end of file
diff --git a/db/schema_migrations/20220916065418 b/db/schema_migrations/20220916065418
new file mode 100644
index 00000000000..f78f7149e66
--- /dev/null
+++ b/db/schema_migrations/20220916065418
@@ -0,0 +1 @@
+2950f1826c77539072f66fcc46fefb77dcbcafe4cc8e5d0bdc090b19fc1600c7 \ No newline at end of file
diff --git a/db/schema_migrations/20220916070101 b/db/schema_migrations/20220916070101
new file mode 100644
index 00000000000..90afdffcddb
--- /dev/null
+++ b/db/schema_migrations/20220916070101
@@ -0,0 +1 @@
+e63bd78b80b7a5a475f0246fb8d2dcb1164f410705dfae44579dce5579655841 \ No newline at end of file
diff --git a/db/schema_migrations/20220916094641 b/db/schema_migrations/20220916094641
new file mode 100644
index 00000000000..d3ab02d6c59
--- /dev/null
+++ b/db/schema_migrations/20220916094641
@@ -0,0 +1 @@
+a5fc50591f5070766ae1d8b4dee195ec91df5fb1aa635c0d39d3d897e54393a5 \ No newline at end of file
diff --git a/db/schema_migrations/20220916103311 b/db/schema_migrations/20220916103311
new file mode 100644
index 00000000000..cc265c0800e
--- /dev/null
+++ b/db/schema_migrations/20220916103311
@@ -0,0 +1 @@
+dbaeae67bb734a491dd40860159285b41d25a3336198f55a52f28190a8f6aeac \ No newline at end of file
diff --git a/db/schema_migrations/20220918124223 b/db/schema_migrations/20220918124223
new file mode 100644
index 00000000000..227bca2ab75
--- /dev/null
+++ b/db/schema_migrations/20220918124223
@@ -0,0 +1 @@
+ff995d7a3c23959c4d4e6c6d0adfd338be36f6c07c98bacd26f282d84b2fa33d \ No newline at end of file
diff --git a/db/schema_migrations/20220919023208 b/db/schema_migrations/20220919023208
new file mode 100644
index 00000000000..30c305baaeb
--- /dev/null
+++ b/db/schema_migrations/20220919023208
@@ -0,0 +1 @@
+e4e86511961bf3618bd3683e1bc97a8382bfa1369bd76186f01cfac9e80e0593 \ No newline at end of file
diff --git a/db/schema_migrations/20220919041604 b/db/schema_migrations/20220919041604
new file mode 100644
index 00000000000..e6943902bf3
--- /dev/null
+++ b/db/schema_migrations/20220919041604
@@ -0,0 +1 @@
+a4115d5542d236a030db180363cf2c816ff68cd2c2a54e74a6b3ba916a40816e \ No newline at end of file
diff --git a/db/schema_migrations/20220919050555 b/db/schema_migrations/20220919050555
new file mode 100644
index 00000000000..29d8d150809
--- /dev/null
+++ b/db/schema_migrations/20220919050555
@@ -0,0 +1 @@
+ac61a72c2c197735404e6bccf3f2ceb9c3f5ff79c7df58f83b6ab1b55b81e532 \ No newline at end of file
diff --git a/db/schema_migrations/20220919225631 b/db/schema_migrations/20220919225631
new file mode 100644
index 00000000000..e30af0fd9f7
--- /dev/null
+++ b/db/schema_migrations/20220919225631
@@ -0,0 +1 @@
+03accc241b8955f0ccfa3b40168e9f194360704d8937cd531683191b8fe4f8c8 \ No newline at end of file
diff --git a/db/schema_migrations/20220920022404 b/db/schema_migrations/20220920022404
new file mode 100644
index 00000000000..cbf8fedc39d
--- /dev/null
+++ b/db/schema_migrations/20220920022404
@@ -0,0 +1 @@
+eec898c4b2ab4d0585d8259b9d0c1e644720c0ba665429434abea9a1062be367 \ No newline at end of file
diff --git a/db/schema_migrations/20220920081631 b/db/schema_migrations/20220920081631
new file mode 100644
index 00000000000..071ef93fc7a
--- /dev/null
+++ b/db/schema_migrations/20220920081631
@@ -0,0 +1 @@
+081480492cbe6e631f0357b181a883a2bc7f34566f23f119c0ba4df59ee363d6 \ No newline at end of file
diff --git a/db/schema_migrations/20220920122121 b/db/schema_migrations/20220920122121
new file mode 100644
index 00000000000..7da41e83a11
--- /dev/null
+++ b/db/schema_migrations/20220920122121
@@ -0,0 +1 @@
+fb6b88494168ef86863f41570a2bad1141d6c6e2305522bf622413702e3b3493 \ No newline at end of file
diff --git a/db/schema_migrations/20220920124709 b/db/schema_migrations/20220920124709
new file mode 100644
index 00000000000..e3b015d44a7
--- /dev/null
+++ b/db/schema_migrations/20220920124709
@@ -0,0 +1 @@
+4a975867dc0539049902229521b4d94f940817ffd9196810856c8eb962c57e62 \ No newline at end of file
diff --git a/db/schema_migrations/20220920135356 b/db/schema_migrations/20220920135356
new file mode 100644
index 00000000000..714228b2518
--- /dev/null
+++ b/db/schema_migrations/20220920135356
@@ -0,0 +1 @@
+477f7b75c7d9b162add500924e5bbd9240ef76f3c56851748af8c6a59d912b7e \ No newline at end of file
diff --git a/db/schema_migrations/20220920141001 b/db/schema_migrations/20220920141001
new file mode 100644
index 00000000000..2e221e49afc
--- /dev/null
+++ b/db/schema_migrations/20220920141001
@@ -0,0 +1 @@
+368d6e417d6ac9c4ed3815b67f3247d55a6e4ec8a6e7ac255c7f9f24d3721f59 \ No newline at end of file
diff --git a/db/schema_migrations/20220920213504 b/db/schema_migrations/20220920213504
new file mode 100644
index 00000000000..53d31de208d
--- /dev/null
+++ b/db/schema_migrations/20220920213504
@@ -0,0 +1 @@
+e683bd10619f9ceee2a5d330ca4d6b9d396ad8934095b707a0eec5d49cdaf2be \ No newline at end of file
diff --git a/db/schema_migrations/20220920214524 b/db/schema_migrations/20220920214524
new file mode 100644
index 00000000000..fc708e05214
--- /dev/null
+++ b/db/schema_migrations/20220920214524
@@ -0,0 +1 @@
+6a4677165bca249c369214aee9fae331fde4dc716544bac93c06f0ee33222455 \ No newline at end of file
diff --git a/db/schema_migrations/20220921093355 b/db/schema_migrations/20220921093355
new file mode 100644
index 00000000000..6083a370279
--- /dev/null
+++ b/db/schema_migrations/20220921093355
@@ -0,0 +1 @@
+d7640b3756cf8cddf9f798362d6d8445a1d37092e4dff9ae263fe39a661b1e55 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111823 b/db/schema_migrations/20220921111823
new file mode 100644
index 00000000000..eeca2c10dad
--- /dev/null
+++ b/db/schema_migrations/20220921111823
@@ -0,0 +1 @@
+f06d7555d3541abbb9fd671df3718645203aef111674b91ad386dac434c4ede2 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111831 b/db/schema_migrations/20220921111831
new file mode 100644
index 00000000000..a03ad3f67dd
--- /dev/null
+++ b/db/schema_migrations/20220921111831
@@ -0,0 +1 @@
+a515d3e34f4b467c5e6fbd9b55135a676277ff6388eb1e3fc14df4b11d8eb3c0 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111840 b/db/schema_migrations/20220921111840
new file mode 100644
index 00000000000..7e84d96f124
--- /dev/null
+++ b/db/schema_migrations/20220921111840
@@ -0,0 +1 @@
+0fdbb888bdbd4f68619466a8f4384e44062b0cf854790c648a6a060ab1e71806 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111849 b/db/schema_migrations/20220921111849
new file mode 100644
index 00000000000..3989dd78aeb
--- /dev/null
+++ b/db/schema_migrations/20220921111849
@@ -0,0 +1 @@
+2041cb81c534be0cc45b1cc77fa7fd2e31615129e1ba60a146cca88d58b77605 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111857 b/db/schema_migrations/20220921111857
new file mode 100644
index 00000000000..578b2c853f4
--- /dev/null
+++ b/db/schema_migrations/20220921111857
@@ -0,0 +1 @@
+cbef1d036abb0035d710cf912e554e32fa88df3abaed17cb938e0b18032c7448 \ No newline at end of file
diff --git a/db/schema_migrations/20220921111907 b/db/schema_migrations/20220921111907
new file mode 100644
index 00000000000..013f79024c9
--- /dev/null
+++ b/db/schema_migrations/20220921111907
@@ -0,0 +1 @@
+fbc4c12aedd9d0f183e9444f2cb42c11a2b894c11684e80a5dbe847c7bccb21f \ No newline at end of file
diff --git a/db/schema_migrations/20220921144258 b/db/schema_migrations/20220921144258
new file mode 100644
index 00000000000..e3d9ad6a4de
--- /dev/null
+++ b/db/schema_migrations/20220921144258
@@ -0,0 +1 @@
+531758adf94d39b646e47601989f5f969eda8e9cbc2b2d6285826f9704575d3d \ No newline at end of file
diff --git a/db/schema_migrations/20220921174815 b/db/schema_migrations/20220921174815
new file mode 100644
index 00000000000..d67929e2029
--- /dev/null
+++ b/db/schema_migrations/20220921174815
@@ -0,0 +1 @@
+2e20cfa3c1ebe77968ba923b381e0c95cb427613f2bfbed212ced4023bd4334e \ No newline at end of file
diff --git a/db/schema_migrations/20220921201347 b/db/schema_migrations/20220921201347
new file mode 100644
index 00000000000..d58f316fd02
--- /dev/null
+++ b/db/schema_migrations/20220921201347
@@ -0,0 +1 @@
+f7c4b6a31434a0f6487fef89ba0c60fd38169e901437667bb6ccf60ba1a3bd4d \ No newline at end of file
diff --git a/db/schema_migrations/20220922090236 b/db/schema_migrations/20220922090236
new file mode 100644
index 00000000000..9f873bd86c2
--- /dev/null
+++ b/db/schema_migrations/20220922090236
@@ -0,0 +1 @@
+6ce159118651ec93989e8f111528ad2134e46f359c483b60239290d677f9f4f4 \ No newline at end of file
diff --git a/db/schema_migrations/20220922143143 b/db/schema_migrations/20220922143143
new file mode 100644
index 00000000000..72074c1efb3
--- /dev/null
+++ b/db/schema_migrations/20220922143143
@@ -0,0 +1 @@
+79aa2360fdf84d7bee402cf51e29813b9c25acfe809123ac5a3218644a63c71f \ No newline at end of file
diff --git a/db/schema_migrations/20220922143612 b/db/schema_migrations/20220922143612
new file mode 100644
index 00000000000..4f93a218c74
--- /dev/null
+++ b/db/schema_migrations/20220922143612
@@ -0,0 +1 @@
+4685b471f00f8ef5e8d8e521c50dc276c757c9f9caa50b1aa20c1f98b8b008c5 \ No newline at end of file
diff --git a/db/schema_migrations/20220922143634 b/db/schema_migrations/20220922143634
new file mode 100644
index 00000000000..50d07dcf9de
--- /dev/null
+++ b/db/schema_migrations/20220922143634
@@ -0,0 +1 @@
+f48217567db22e6a4d3a32c607911da9f9a39a37d75be158a893ce840f718f02 \ No newline at end of file
diff --git a/db/schema_migrations/20220922204106 b/db/schema_migrations/20220922204106
new file mode 100644
index 00000000000..0eabc077b58
--- /dev/null
+++ b/db/schema_migrations/20220922204106
@@ -0,0 +1 @@
+e1106d4b77704a1ac4c185e0a6b500966dc61f46569de55650875aa6a89b7f9d \ No newline at end of file
diff --git a/db/schema_migrations/20220923052531 b/db/schema_migrations/20220923052531
new file mode 100644
index 00000000000..db7d24075f1
--- /dev/null
+++ b/db/schema_migrations/20220923052531
@@ -0,0 +1 @@
+198d1447a8a857ea18409fe99e5a5a616d966b480bb6fc8f05613a651fdcd8a9 \ No newline at end of file
diff --git a/db/schema_migrations/20220923060226 b/db/schema_migrations/20220923060226
new file mode 100644
index 00000000000..daaf2407607
--- /dev/null
+++ b/db/schema_migrations/20220923060226
@@ -0,0 +1 @@
+19799d51a2b9acc7b1642edebea85ca8a19d2dd8368c4f0814c6c7a4c529ef98 \ No newline at end of file
diff --git a/db/schema_migrations/20220923103006 b/db/schema_migrations/20220923103006
new file mode 100644
index 00000000000..8a11ebc8f8f
--- /dev/null
+++ b/db/schema_migrations/20220923103006
@@ -0,0 +1 @@
+184e634f62549f3fa2f183003957a2f5a5c53b34394ec3430eb0293076ae177a \ No newline at end of file
diff --git a/db/schema_migrations/20220927155407 b/db/schema_migrations/20220927155407
new file mode 100644
index 00000000000..a704ba7cb41
--- /dev/null
+++ b/db/schema_migrations/20220927155407
@@ -0,0 +1 @@
+97bdc9d31ed93897f3133459779207b3b750530b615e243a625681d433090e94 \ No newline at end of file
diff --git a/db/schema_migrations/20220928201920 b/db/schema_migrations/20220928201920
new file mode 100644
index 00000000000..e77f9abf6a0
--- /dev/null
+++ b/db/schema_migrations/20220928201920
@@ -0,0 +1 @@
+b2492ebefc3738dfe706379ef664d3f28315102acc1c0681ba67e6aae62861d7 \ No newline at end of file
diff --git a/db/schema_migrations/20220928225711 b/db/schema_migrations/20220928225711
new file mode 100644
index 00000000000..fd7a8b303d1
--- /dev/null
+++ b/db/schema_migrations/20220928225711
@@ -0,0 +1 @@
+5ec9b3f36a986cbb86c8005a4425307f0f4399a4a4030460e715370630cb9490 \ No newline at end of file
diff --git a/db/schema_migrations/20220929081645 b/db/schema_migrations/20220929081645
new file mode 100644
index 00000000000..a6fb1a6a74d
--- /dev/null
+++ b/db/schema_migrations/20220929081645
@@ -0,0 +1 @@
+ac34f2215272e69efc486affa8ad06347221d63ddadafe995f6e98f355a49936 \ No newline at end of file
diff --git a/db/schema_migrations/20220929091500 b/db/schema_migrations/20220929091500
new file mode 100644
index 00000000000..66997dd37d9
--- /dev/null
+++ b/db/schema_migrations/20220929091500
@@ -0,0 +1 @@
+c636f10079d7b718b777b78c22b66ca8828518d9dc8a3f6abe47e25af14ae20b \ No newline at end of file
diff --git a/db/schema_migrations/20220929101947 b/db/schema_migrations/20220929101947
new file mode 100644
index 00000000000..4969db4f283
--- /dev/null
+++ b/db/schema_migrations/20220929101947
@@ -0,0 +1 @@
+946e773d09863fe029507ac44b41a61ed0b6b766f7296759743cf09addfacfcd \ No newline at end of file
diff --git a/db/schema_migrations/20220929171925 b/db/schema_migrations/20220929171925
new file mode 100644
index 00000000000..b2e471bb32c
--- /dev/null
+++ b/db/schema_migrations/20220929171925
@@ -0,0 +1 @@
+352e1b200a7e5074c58fdcfd0c9ae9b3535054a0b3d9852caabde635d9a1ad94 \ No newline at end of file
diff --git a/db/schema_migrations/20220929172356 b/db/schema_migrations/20220929172356
new file mode 100644
index 00000000000..3200898ddb5
--- /dev/null
+++ b/db/schema_migrations/20220929172356
@@ -0,0 +1 @@
+9cdc6169dc4925f43aabb2f4bcf597333a4112135001a5d1a6961853a78c90da \ No newline at end of file
diff --git a/db/schema_migrations/20220929194453 b/db/schema_migrations/20220929194453
new file mode 100644
index 00000000000..25d512b792b
--- /dev/null
+++ b/db/schema_migrations/20220929194453
@@ -0,0 +1 @@
+0f625bd9df16d035dd8cd73d5097e5b5f4d1b900183bd6ccf4b1489319535df6 \ No newline at end of file
diff --git a/db/schema_migrations/20220929213730 b/db/schema_migrations/20220929213730
new file mode 100644
index 00000000000..469e84f8217
--- /dev/null
+++ b/db/schema_migrations/20220929213730
@@ -0,0 +1 @@
+f74b8524fcdabd1646bbb47a32f8e3a29a848eb457f465d33a9e81bf4462e2ea \ No newline at end of file
diff --git a/db/schema_migrations/20220930110127 b/db/schema_migrations/20220930110127
new file mode 100644
index 00000000000..b88603e17d9
--- /dev/null
+++ b/db/schema_migrations/20220930110127
@@ -0,0 +1 @@
+6a37ea8ea1ae2b90d12db67b2fa6adac2ed5b936f6c45d2142dc8390883f764a \ No newline at end of file
diff --git a/db/schema_migrations/20220930125609 b/db/schema_migrations/20220930125609
new file mode 100644
index 00000000000..65e00dbd945
--- /dev/null
+++ b/db/schema_migrations/20220930125609
@@ -0,0 +1 @@
+cba5fad6379efe681dfc19a02522de7c904705790de588d07ed12f032fab760e \ No newline at end of file
diff --git a/db/schema_migrations/20221003192827 b/db/schema_migrations/20221003192827
new file mode 100644
index 00000000000..803c269b6e0
--- /dev/null
+++ b/db/schema_migrations/20221003192827
@@ -0,0 +1 @@
+7fe33b22601469d1f15ee67241775e7a14d96841a49129fe98bfd2f44cf6666f \ No newline at end of file
diff --git a/db/schema_migrations/20221004092038 b/db/schema_migrations/20221004092038
new file mode 100644
index 00000000000..c7305a46cfd
--- /dev/null
+++ b/db/schema_migrations/20221004092038
@@ -0,0 +1 @@
+584d43304f92cc638783ffc5c8ab2dc8e511169c76da7661cb4c5ddded6c02d1 \ No newline at end of file
diff --git a/db/schema_migrations/20221004094814 b/db/schema_migrations/20221004094814
new file mode 100644
index 00000000000..f3ac2ccb0d3
--- /dev/null
+++ b/db/schema_migrations/20221004094814
@@ -0,0 +1 @@
+b274eaa3ef886e5de6fe5dacb11ab72a724a07a5022da6c01b94309fdaebfd0b \ No newline at end of file
diff --git a/db/schema_migrations/20221005072353 b/db/schema_migrations/20221005072353
new file mode 100644
index 00000000000..3249a062aa7
--- /dev/null
+++ b/db/schema_migrations/20221005072353
@@ -0,0 +1 @@
+6b90dfb738c597a45ecaae792e97e1ae0decb93779ecc35fbc2fbaedafb5b9d1 \ No newline at end of file
diff --git a/db/schema_migrations/20221005094926 b/db/schema_migrations/20221005094926
new file mode 100644
index 00000000000..7606c06170f
--- /dev/null
+++ b/db/schema_migrations/20221005094926
@@ -0,0 +1 @@
+ab93968543b6aec0bc304a2c0dc051f63a29b4765df11432fba45325e5e75e55 \ No newline at end of file
diff --git a/db/schema_migrations/20221005103000 b/db/schema_migrations/20221005103000
new file mode 100644
index 00000000000..6403e3106a2
--- /dev/null
+++ b/db/schema_migrations/20221005103000
@@ -0,0 +1 @@
+ac1aa3697f6e4230bfdc41f34e2e87ef49f697cfa46139fe3ac91a42b7bf4b91 \ No newline at end of file
diff --git a/db/schema_migrations/20221005103010 b/db/schema_migrations/20221005103010
new file mode 100644
index 00000000000..9bf2bba87ca
--- /dev/null
+++ b/db/schema_migrations/20221005103010
@@ -0,0 +1 @@
+85deb0dcce9b1d43b3c978f2615afabe1f29304f65cf01a82d9b116d3276337f \ No newline at end of file
diff --git a/db/schema_migrations/20221006083240 b/db/schema_migrations/20221006083240
new file mode 100644
index 00000000000..51c509f471c
--- /dev/null
+++ b/db/schema_migrations/20221006083240
@@ -0,0 +1 @@
+0ad92f76e14b2e9286b2f77f32c00dba8ae29b64035f79641451edfdc725c92a \ No newline at end of file
diff --git a/db/schema_migrations/20221006131506 b/db/schema_migrations/20221006131506
new file mode 100644
index 00000000000..cafb6518fdd
--- /dev/null
+++ b/db/schema_migrations/20221006131506
@@ -0,0 +1 @@
+2652f733d5998b4dacc89a7c43af45e6d411235efcdc120be02bbf04eb1c55d6 \ No newline at end of file
diff --git a/db/schema_migrations/20221006141145 b/db/schema_migrations/20221006141145
new file mode 100644
index 00000000000..269913ca389
--- /dev/null
+++ b/db/schema_migrations/20221006141145
@@ -0,0 +1 @@
+ae45bc7d67354b64e359ac7fadefec6a0d81cd529f5ae2517a6a6a5d250f9024 \ No newline at end of file
diff --git a/db/schema_migrations/20221006172302 b/db/schema_migrations/20221006172302
new file mode 100644
index 00000000000..361fdd78086
--- /dev/null
+++ b/db/schema_migrations/20221006172302
@@ -0,0 +1 @@
+19e5ca6f9716fd41bfe8a103dab8a1dc37107f99503abedbdcb8175b699283f2 \ No newline at end of file
diff --git a/db/schema_migrations/20221008032350 b/db/schema_migrations/20221008032350
new file mode 100644
index 00000000000..8b76b056a77
--- /dev/null
+++ b/db/schema_migrations/20221008032350
@@ -0,0 +1 @@
+c5e373b1b416455b67b7bc0affe244295e1f1a2f105fe8ef6efddf8b07da2a86 \ No newline at end of file
diff --git a/db/schema_migrations/20221009085130 b/db/schema_migrations/20221009085130
new file mode 100644
index 00000000000..cbdfb3014cd
--- /dev/null
+++ b/db/schema_migrations/20221009085130
@@ -0,0 +1 @@
+125ce9bf81966840774eb69be7995c1a8e2abd901fe5f19b73df43a577a9dc44 \ No newline at end of file
diff --git a/db/schema_migrations/20221010074914 b/db/schema_migrations/20221010074914
new file mode 100644
index 00000000000..272a8d038cc
--- /dev/null
+++ b/db/schema_migrations/20221010074914
@@ -0,0 +1 @@
+c5ef65edf6e87495bc4dc16c636b2f2d8cbd63f3903cf5ed1364206b83411ba9 \ No newline at end of file
diff --git a/db/schema_migrations/20221010121510 b/db/schema_migrations/20221010121510
new file mode 100644
index 00000000000..4c73958df10
--- /dev/null
+++ b/db/schema_migrations/20221010121510
@@ -0,0 +1 @@
+ab9ab20d1a220e715a758f6175fcaf5c62cb240f49a2ad4227f7cd11f030fa1d \ No newline at end of file
diff --git a/db/schema_migrations/20221010121807 b/db/schema_migrations/20221010121807
new file mode 100644
index 00000000000..e5ca8007519
--- /dev/null
+++ b/db/schema_migrations/20221010121807
@@ -0,0 +1 @@
+44e6b2519ef285366d1a2b4ea6efe18a9c22bfdb545c11502eae9383123b6001 \ No newline at end of file
diff --git a/db/schema_migrations/20221010122138 b/db/schema_migrations/20221010122138
new file mode 100644
index 00000000000..9a9898a37b0
--- /dev/null
+++ b/db/schema_migrations/20221010122138
@@ -0,0 +1 @@
+1275aff394d75cc254e664a81f52880bc248343dad7a07162973cafe268d40e6 \ No newline at end of file
diff --git a/db/schema_migrations/20221010122352 b/db/schema_migrations/20221010122352
new file mode 100644
index 00000000000..a785dc22539
--- /dev/null
+++ b/db/schema_migrations/20221010122352
@@ -0,0 +1 @@
+a982eed3131805db693882a8da7c5c5d1572f7825eb51a45c468bd5dfbded58b \ No newline at end of file
diff --git a/db/schema_migrations/20221010123040 b/db/schema_migrations/20221010123040
new file mode 100644
index 00000000000..85ad72c702b
--- /dev/null
+++ b/db/schema_migrations/20221010123040
@@ -0,0 +1 @@
+a3c66e57959f3e183a5b933138c9deedb5575e0b90b3a862b7b8e20331ffa31e \ No newline at end of file
diff --git a/db/schema_migrations/20221011113928 b/db/schema_migrations/20221011113928
new file mode 100644
index 00000000000..1552b7193f3
--- /dev/null
+++ b/db/schema_migrations/20221011113928
@@ -0,0 +1 @@
+70f78c3af8d43ea71a795d0cd28bf74aa8a5232ea5e5b9dcb59699b5f8cccfaa \ No newline at end of file
diff --git a/db/schema_migrations/20221011162637 b/db/schema_migrations/20221011162637
new file mode 100644
index 00000000000..c16e511e516
--- /dev/null
+++ b/db/schema_migrations/20221011162637
@@ -0,0 +1 @@
+b39261356f0ca89d543f680e1b28f3e3bdf468b02d6f8ea21c6ea1a1af91420c \ No newline at end of file
diff --git a/db/schema_migrations/20221011210455 b/db/schema_migrations/20221011210455
new file mode 100644
index 00000000000..2a6a7349f5d
--- /dev/null
+++ b/db/schema_migrations/20221011210455
@@ -0,0 +1 @@
+3c2445871613743560b2dd0a111fafab30f503b1c462e7ba7aee03f85e25f775 \ No newline at end of file
diff --git a/db/schema_migrations/20221012033107 b/db/schema_migrations/20221012033107
new file mode 100644
index 00000000000..ba1df6370d3
--- /dev/null
+++ b/db/schema_migrations/20221012033107
@@ -0,0 +1 @@
+23252a63b8aab6a062cf22db563f8518213d40110449732866e6d8d5092d369e \ No newline at end of file
diff --git a/db/schema_migrations/20221012135524 b/db/schema_migrations/20221012135524
new file mode 100644
index 00000000000..7a4503dde08
--- /dev/null
+++ b/db/schema_migrations/20221012135524
@@ -0,0 +1 @@
+e5fc4ce0fdba01b55de0a1d5a968ab9b1ad3bc930ab61c6187a223e62252c8bc \ No newline at end of file
diff --git a/db/schema_migrations/20221012182701 b/db/schema_migrations/20221012182701
new file mode 100644
index 00000000000..5a6b47c4026
--- /dev/null
+++ b/db/schema_migrations/20221012182701
@@ -0,0 +1 @@
+82f67746e79bcc63e5674f2e009eb9a827e019409c9277f6cd1ce2e41c50c296 \ No newline at end of file
diff --git a/db/schema_migrations/20221013154159 b/db/schema_migrations/20221013154159
new file mode 100644
index 00000000000..2e147bb199d
--- /dev/null
+++ b/db/schema_migrations/20221013154159
@@ -0,0 +1 @@
+dbf241baf6d3deb1ef29a7cdca012050cab51c5f86762a0363d9dc4dc14fd804 \ No newline at end of file
diff --git a/db/schema_migrations/20221014031033 b/db/schema_migrations/20221014031033
new file mode 100644
index 00000000000..6a24a2027c7
--- /dev/null
+++ b/db/schema_migrations/20221014031033
@@ -0,0 +1 @@
+bc05939dc672c078161cd9b7dbd7f92601edb6888a77c62adb014964e30c6ae8 \ No newline at end of file
diff --git a/db/schema_migrations/20221014034338 b/db/schema_migrations/20221014034338
new file mode 100644
index 00000000000..c90dfebb72b
--- /dev/null
+++ b/db/schema_migrations/20221014034338
@@ -0,0 +1 @@
+58ee7f51a0da4ee4ec471d4492106d1fc3124419ba83591913967d6bd38105e5 \ No newline at end of file
diff --git a/db/schema_migrations/20221014190040 b/db/schema_migrations/20221014190040
new file mode 100644
index 00000000000..ce6387c3e43
--- /dev/null
+++ b/db/schema_migrations/20221014190040
@@ -0,0 +1 @@
+2ac315a49a5026938abc21a98974fd42b39b7535d86530085a01fc7f5687bb0e \ No newline at end of file
diff --git a/db/schema_migrations/20221018081416 b/db/schema_migrations/20221018081416
new file mode 100644
index 00000000000..4b92b46709a
--- /dev/null
+++ b/db/schema_migrations/20221018081416
@@ -0,0 +1 @@
+25030e3ba7c6632fa86100c2db320d1e0c431f992e2b3e333a98e7e03bd31a49 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index bfdb4e508f2..2dab5e7abc9 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -22,40 +22,6 @@ RETURN NULL;
END
$$;
-CREATE FUNCTION function_for_trigger_a645cee67576() RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- NEW."service_id" := NEW."integration_id";
- RETURN NEW;
-END
-$$;
-
-CREATE FUNCTION function_for_trigger_a87bcfdf0f0b() RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- IF NEW."service_id" IS NULL AND NEW."integration_id" IS NOT NULL THEN
- NEW."service_id" = NEW."integration_id";
- END IF;
-
- IF NEW."integration_id" IS NULL AND NEW."service_id" IS NOT NULL THEN
- NEW."integration_id" = NEW."service_id";
- END IF;
-
- RETURN NEW;
-END
-$$;
-
-CREATE FUNCTION function_for_trigger_aca5c963d732() RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- NEW."integration_id" := NEW."service_id";
- RETURN NEW;
-END
-$$;
-
CREATE FUNCTION gitlab_schema_prevent_write() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -11507,6 +11473,24 @@ CREATE TABLE application_settings (
cube_api_base_url text,
encrypted_cube_api_key bytea,
encrypted_cube_api_key_iv bytea,
+ jitsu_host text,
+ jitsu_project_xid text,
+ clickhouse_connection_string text,
+ jitsu_administrator_email text,
+ encrypted_jitsu_administrator_password bytea,
+ encrypted_jitsu_administrator_password_iv bytea,
+ dashboard_limit_enabled boolean DEFAULT false NOT NULL,
+ dashboard_limit integer DEFAULT 0 NOT NULL,
+ dashboard_notification_limit integer DEFAULT 0 NOT NULL,
+ dashboard_enforcement_limit integer DEFAULT 0 NOT NULL,
+ dashboard_limit_new_namespace_creation_enforcement_date date,
+ can_create_group boolean DEFAULT true NOT NULL,
+ lock_maven_package_requests_forwarding boolean DEFAULT false NOT NULL,
+ lock_pypi_package_requests_forwarding boolean DEFAULT false NOT NULL,
+ lock_npm_package_requests_forwarding boolean DEFAULT false NOT NULL,
+ password_expiration_enabled boolean DEFAULT false NOT NULL,
+ password_expires_in_days integer DEFAULT 90 NOT NULL,
+ password_expires_notice_before_days integer DEFAULT 7 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_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
@@ -11543,12 +11527,16 @@ CREATE TABLE application_settings (
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
CONSTRAINT check_a5704163cc CHECK ((char_length(secret_detection_revocation_token_types_url) <= 255)),
CONSTRAINT check_d03919528d CHECK ((char_length(container_registry_vendor) <= 255)),
+ CONSTRAINT check_d4865d70f3 CHECK ((char_length(clickhouse_connection_string) <= 1024)),
CONSTRAINT check_d820146492 CHECK ((char_length(spam_check_endpoint_url) <= 255)),
+ CONSTRAINT check_dea8792229 CHECK ((char_length(jitsu_host) <= 255)),
CONSTRAINT check_e2dd6e290a CHECK ((char_length(jira_connect_application_key) <= 255)),
CONSTRAINT check_e5024c8801 CHECK ((char_length(elasticsearch_username) <= 255)),
CONSTRAINT check_e5aba18f02 CHECK ((char_length(container_registry_version) <= 255)),
+ CONSTRAINT check_ec3ca9aa8d CHECK ((char_length(jitsu_administrator_email) <= 255)),
CONSTRAINT check_ef6176834f CHECK ((char_length(encrypted_cloud_license_auth_token_iv) <= 255)),
- CONSTRAINT check_f6563bc000 CHECK ((char_length(arkose_labs_verify_api_url) <= 255))
+ CONSTRAINT check_f6563bc000 CHECK ((char_length(arkose_labs_verify_api_url) <= 255)),
+ CONSTRAINT check_fc732c181e CHECK ((char_length(jitsu_project_xid) <= 255))
);
COMMENT ON COLUMN application_settings.content_validation_endpoint_url IS 'JiHu-specific column';
@@ -11585,6 +11573,12 @@ COMMENT ON COLUMN application_settings.encrypted_feishu_app_secret IS 'JiHu-spec
COMMENT ON COLUMN application_settings.encrypted_feishu_app_secret_iv IS 'JiHu-specific column';
+COMMENT ON COLUMN application_settings.password_expiration_enabled IS 'JiHu-specific column';
+
+COMMENT ON COLUMN application_settings.password_expires_in_days IS 'JiHu-specific column';
+
+COMMENT ON COLUMN application_settings.password_expires_notice_before_days IS 'JiHu-specific column';
+
CREATE SEQUENCE application_settings_id_seq
START WITH 1
INCREMENT BY 1
@@ -11625,6 +11619,7 @@ CREATE TABLE approval_merge_request_rules (
scanners text[] DEFAULT '{}'::text[] NOT NULL,
severity_levels text[] DEFAULT '{}'::text[] NOT NULL,
vulnerability_states text[] DEFAULT '{newly_detected}'::text[] NOT NULL,
+ security_orchestration_policy_configuration_id bigint,
CONSTRAINT check_6fca5928b2 CHECK ((char_length(section) <= 255))
);
@@ -11696,7 +11691,8 @@ CREATE TABLE approval_project_rules (
report_type smallint,
vulnerability_states text[] DEFAULT '{newly_detected}'::text[] NOT NULL,
orchestration_policy_idx smallint,
- applies_to_all_protected_branches boolean DEFAULT false NOT NULL
+ applies_to_all_protected_branches boolean DEFAULT false NOT NULL,
+ security_orchestration_policy_configuration_id bigint
);
CREATE TABLE approval_project_rules_groups (
@@ -12354,6 +12350,7 @@ CREATE TABLE bulk_import_entities (
jid text,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
+ source_xid integer,
CONSTRAINT check_13f279f7da CHECK ((char_length(source_full_path) <= 255)),
CONSTRAINT check_715d725ea2 CHECK ((char_length(destination_name) <= 255)),
CONSTRAINT check_796a4d9cc6 CHECK ((char_length(jid) <= 255)),
@@ -12595,7 +12592,6 @@ CREATE TABLE ci_build_trace_metadata (
CREATE TABLE ci_builds (
status character varying,
finished_at timestamp without time zone,
- trace text,
created_at timestamp without time zone,
updated_at timestamp without time zone,
started_at timestamp without time zone,
@@ -12766,7 +12762,7 @@ CREATE TABLE ci_group_variables (
masked boolean DEFAULT false NOT NULL,
variable_type smallint DEFAULT 1 NOT NULL,
environment_scope text DEFAULT '*'::text NOT NULL,
- raw boolean DEFAULT true NOT NULL,
+ raw boolean DEFAULT false NOT NULL,
CONSTRAINT check_dfe009485a CHECK ((char_length(environment_scope) <= 255))
);
@@ -12787,7 +12783,7 @@ CREATE TABLE ci_instance_variables (
key text NOT NULL,
encrypted_value text,
encrypted_value_iv text,
- raw boolean DEFAULT true NOT NULL,
+ raw boolean DEFAULT false NOT NULL,
CONSTRAINT check_07a45a5bcb CHECK ((char_length(encrypted_value_iv) <= 255)),
CONSTRAINT check_5aede12208 CHECK ((char_length(key) <= 255)),
CONSTRAINT check_956afd70f1 CHECK ((char_length(encrypted_value) <= 13579))
@@ -12849,7 +12845,8 @@ CREATE TABLE ci_job_token_project_scope_links (
source_project_id bigint NOT NULL,
target_project_id bigint NOT NULL,
added_by_id bigint,
- created_at timestamp with time zone NOT NULL
+ created_at timestamp with time zone NOT NULL,
+ direction smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_job_token_project_scope_links_id_seq
@@ -12869,7 +12866,7 @@ CREATE TABLE ci_job_variables (
job_id bigint NOT NULL,
variable_type smallint DEFAULT 1 NOT NULL,
source smallint DEFAULT 0 NOT NULL,
- raw boolean DEFAULT true NOT NULL
+ raw boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE ci_job_variables_id_seq
@@ -13040,6 +13037,13 @@ CREATE SEQUENCE ci_pipeline_messages_id_seq
ALTER SEQUENCE ci_pipeline_messages_id_seq OWNED BY ci_pipeline_messages.id;
+CREATE TABLE ci_pipeline_metadata (
+ project_id bigint NOT NULL,
+ pipeline_id bigint NOT NULL,
+ title text NOT NULL,
+ CONSTRAINT check_e6a636a3f3 CHECK ((char_length(title) <= 255))
+);
+
CREATE TABLE ci_pipeline_schedule_variables (
id integer NOT NULL,
key character varying NOT NULL,
@@ -13051,7 +13055,7 @@ CREATE TABLE ci_pipeline_schedule_variables (
created_at timestamp with time zone,
updated_at timestamp with time zone,
variable_type smallint DEFAULT 1 NOT NULL,
- raw boolean DEFAULT true NOT NULL
+ raw boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE ci_pipeline_schedule_variables_id_seq
@@ -13095,8 +13099,8 @@ CREATE TABLE ci_pipeline_variables (
encrypted_value_iv character varying,
pipeline_id integer NOT NULL,
variable_type smallint DEFAULT 1 NOT NULL,
- raw boolean DEFAULT true NOT NULL,
- partition_id bigint DEFAULT 100 NOT NULL
+ partition_id bigint DEFAULT 100 NOT NULL,
+ raw boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE ci_pipeline_variables_id_seq
@@ -13386,6 +13390,8 @@ CREATE TABLE ci_secure_files (
file text NOT NULL,
checksum bytea NOT NULL,
key_data text,
+ metadata jsonb,
+ expires_at timestamp with time zone,
CONSTRAINT check_320790634d CHECK ((char_length(file) <= 255)),
CONSTRAINT check_402c7b4a56 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_7279b4e293 CHECK ((char_length(key_data) <= 128))
@@ -13558,7 +13564,7 @@ CREATE TABLE ci_variables (
environment_scope character varying DEFAULT '*'::character varying NOT NULL,
masked boolean DEFAULT false NOT NULL,
variable_type smallint DEFAULT 1 NOT NULL,
- raw boolean DEFAULT true NOT NULL
+ raw boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE ci_variables_id_seq
@@ -14400,8 +14406,10 @@ CREATE TABLE dast_site_profiles (
target_type smallint DEFAULT 0 NOT NULL,
scan_method smallint DEFAULT 0 NOT NULL,
auth_submit_field text,
+ scan_file_path text,
CONSTRAINT check_5203110fee CHECK ((char_length(auth_username_field) <= 255)),
CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_8d2aa0f66d CHECK ((char_length(scan_file_path) <= 1024)),
CONSTRAINT check_af44f54c96 CHECK ((char_length(auth_submit_field) <= 255)),
CONSTRAINT check_c329dffdba CHECK ((char_length(auth_password_field) <= 255)),
CONSTRAINT check_d446f7047b CHECK ((char_length(auth_url) <= 1024)),
@@ -14973,6 +14981,7 @@ CREATE TABLE elastic_reindexing_tasks (
delete_original_index_at timestamp with time zone,
max_slices_running smallint DEFAULT 60 NOT NULL,
slice_multiplier smallint DEFAULT 2 NOT NULL,
+ targets text[],
CONSTRAINT check_7f64acda8e CHECK ((char_length(error_message) <= 255))
);
@@ -16403,6 +16412,40 @@ 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_event_tag_links (
+ id bigint NOT NULL,
+ timeline_event_id bigint NOT NULL,
+ timeline_event_tag_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE incident_management_timeline_event_tag_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_timeline_event_tag_links_id_seq OWNED BY incident_management_timeline_event_tag_links.id;
+
+CREATE TABLE incident_management_timeline_event_tags (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_8717184e2c CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE incident_management_timeline_event_tags_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_timeline_event_tags_id_seq OWNED BY incident_management_timeline_event_tags.id;
+
CREATE TABLE incident_management_timeline_events (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -17269,9 +17312,7 @@ CREATE TABLE merge_request_assignees (
id bigint NOT NULL,
user_id integer NOT NULL,
merge_request_id integer NOT NULL,
- created_at timestamp with time zone,
- state smallint DEFAULT 0 NOT NULL,
- updated_state_by_user_id bigint
+ created_at timestamp with time zone
);
CREATE SEQUENCE merge_request_assignees_id_seq
@@ -17513,8 +17554,7 @@ CREATE TABLE merge_request_reviewers (
user_id bigint NOT NULL,
merge_request_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
- state smallint DEFAULT 0 NOT NULL,
- updated_state_by_user_id bigint
+ state smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE merge_request_reviewers_id_seq
@@ -17735,6 +17775,7 @@ CREATE TABLE ml_candidate_metrics (
step integer,
is_nan bytea,
name text NOT NULL,
+ tracked_at bigint,
CONSTRAINT check_3bb4a3fbd9 CHECK ((char_length(name) <= 250))
);
@@ -17860,7 +17901,8 @@ CREATE TABLE namespace_details (
cached_markdown_version integer,
description text,
description_html text,
- free_user_cap_over_limt_notified_at timestamp with time zone
+ free_user_cap_over_limt_notified_at timestamp with time zone,
+ free_user_cap_over_limit_notified_at timestamp with time zone
);
CREATE TABLE namespace_limits (
@@ -17876,6 +17918,12 @@ CREATE TABLE namespace_package_settings (
maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
generic_duplicates_allowed boolean DEFAULT true NOT NULL,
generic_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
+ maven_package_requests_forwarding boolean,
+ lock_maven_package_requests_forwarding boolean DEFAULT false NOT NULL,
+ pypi_package_requests_forwarding boolean,
+ lock_pypi_package_requests_forwarding boolean DEFAULT false NOT NULL,
+ npm_package_requests_forwarding boolean,
+ lock_npm_package_requests_forwarding boolean DEFAULT false NOT NULL,
CONSTRAINT check_31340211b1 CHECK ((char_length(generic_duplicate_exception_regex) <= 255)),
CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255))
);
@@ -17915,15 +17963,17 @@ CREATE TABLE namespace_settings (
runner_token_expiration_interval integer,
subgroup_runner_token_expiration_interval integer,
project_runner_token_expiration_interval integer,
- exclude_from_free_user_cap boolean DEFAULT false NOT NULL,
show_diff_preview_in_email boolean DEFAULT true NOT NULL,
enabled_git_access_protocol smallint DEFAULT 0 NOT NULL,
unique_project_download_limit smallint DEFAULT 0 NOT NULL,
unique_project_download_limit_interval_in_seconds integer DEFAULT 0 NOT NULL,
project_import_level smallint DEFAULT 50 NOT NULL,
- include_for_free_user_cap_preview boolean DEFAULT false NOT NULL,
unique_project_download_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
auto_ban_user_on_excessive_projects_download boolean DEFAULT false NOT NULL,
+ only_allow_merge_if_pipeline_succeeds boolean DEFAULT false NOT NULL,
+ allow_merge_on_skipped_pipeline boolean DEFAULT false NOT NULL,
+ only_allow_merge_if_all_discussions_are_resolved boolean DEFAULT false NOT NULL,
+ default_compliance_framework_id bigint,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
);
@@ -18946,6 +18996,32 @@ CREATE TABLE packages_rpm_metadata (
CONSTRAINT check_c3e2fc2e89 CHECK ((char_length(release) <= 128))
);
+CREATE TABLE packages_rpm_repository_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ file_store integer DEFAULT 1,
+ status smallint DEFAULT 0 NOT NULL,
+ size integer,
+ file_md5 bytea,
+ file_sha1 bytea,
+ file_sha256 bytea,
+ file text NOT NULL,
+ file_name text NOT NULL,
+ CONSTRAINT check_a9fef187f5 CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_b6b721b275 CHECK ((char_length(file_name) <= 255))
+);
+
+CREATE SEQUENCE packages_rpm_repository_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_rpm_repository_files_id_seq OWNED BY packages_rpm_repository_files.id;
+
CREATE TABLE packages_rubygems_metadata (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -19662,7 +19738,8 @@ CREATE TABLE project_ci_cd_settings (
runner_token_expiration_interval integer,
separated_caches boolean DEFAULT true NOT NULL,
opt_in_jwt boolean DEFAULT false NOT NULL,
- allow_fork_pipelines_to_run_in_parent_project boolean DEFAULT true NOT NULL
+ allow_fork_pipelines_to_run_in_parent_project boolean DEFAULT true NOT NULL,
+ inbound_job_token_scope_enabled boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -20071,6 +20148,10 @@ CREATE TABLE project_settings (
enforce_auth_checks_on_uploads boolean DEFAULT true NOT NULL,
selective_code_owner_removals boolean DEFAULT false NOT NULL,
show_diff_preview_in_email boolean DEFAULT true NOT NULL,
+ jitsu_key text,
+ suggested_reviewers_enabled boolean DEFAULT false NOT NULL,
+ only_allow_merge_if_all_status_checks_passed boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_2981f15877 CHECK ((char_length(jitsu_key) <= 100)),
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)),
@@ -20124,6 +20205,18 @@ CREATE SEQUENCE project_topics_id_seq
ALTER SEQUENCE project_topics_id_seq OWNED BY project_topics.id;
+CREATE TABLE project_wiki_repository_states (
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ project_id bigint NOT NULL,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_119f134b68 CHECK ((char_length(verification_failure) <= 255))
+);
+
CREATE TABLE projects (
id integer NOT NULL,
name character varying,
@@ -20505,7 +20598,8 @@ CREATE TABLE push_rules (
reject_unsigned_commits boolean,
commit_committer_check boolean,
regexp_uses_re2 boolean DEFAULT true,
- commit_message_negative_regex character varying
+ commit_message_negative_regex character varying,
+ reject_non_dco_commits boolean
);
CREATE SEQUENCE push_rules_id_seq
@@ -20979,7 +21073,7 @@ CREATE TABLE sbom_sources (
updated_at timestamp with time zone NOT NULL,
source_type smallint NOT NULL,
source jsonb DEFAULT '{}'::jsonb NOT NULL,
- fingerprint bytea NOT NULL
+ fingerprint bytea
);
CREATE SEQUENCE sbom_sources_id_seq
@@ -22032,7 +22126,20 @@ CREATE TABLE user_details (
registration_objective smallint,
phone text,
requires_credit_card_verification boolean DEFAULT false NOT NULL,
+ password_last_changed_at timestamp with time zone,
+ linkedin text DEFAULT ''::text NOT NULL,
+ twitter text DEFAULT ''::text NOT NULL,
+ skype text DEFAULT ''::text NOT NULL,
+ website_url text DEFAULT ''::text NOT NULL,
+ location text DEFAULT ''::text NOT NULL,
+ organization text DEFAULT ''::text NOT NULL,
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
+ CONSTRAINT check_444573ee52 CHECK ((char_length(skype) <= 500)),
+ CONSTRAINT check_466a25be35 CHECK ((char_length(twitter) <= 500)),
+ CONSTRAINT check_7b246dad73 CHECK ((char_length(organization) <= 500)),
+ CONSTRAINT check_7d6489f8f3 CHECK ((char_length(linkedin) <= 500)),
+ CONSTRAINT check_7fe2044093 CHECK ((char_length(website_url) <= 500)),
+ CONSTRAINT check_8a7fcf8a60 CHECK ((char_length(location) <= 500)),
CONSTRAINT check_a73b398c60 CHECK ((char_length(phone) <= 50)),
CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)),
CONSTRAINT check_f932ed37db CHECK ((char_length(pronunciation) <= 255))
@@ -22040,6 +22147,8 @@ CREATE TABLE user_details (
COMMENT ON COLUMN user_details.phone IS 'JiHu-specific column';
+COMMENT ON COLUMN user_details.password_last_changed_at IS 'JiHu-specific column';
+
CREATE SEQUENCE user_details_user_id_seq
START WITH 1
INCREMENT BY 1
@@ -22119,6 +22228,22 @@ CREATE SEQUENCE user_permission_export_uploads_id_seq
ALTER SEQUENCE user_permission_export_uploads_id_seq OWNED BY user_permission_export_uploads.id;
+CREATE TABLE user_phone_number_validations (
+ user_id bigint NOT NULL,
+ validated_at timestamp with time zone,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ international_dial_code smallint NOT NULL,
+ verification_attempts smallint DEFAULT 0 NOT NULL,
+ risk_score smallint DEFAULT 0 NOT NULL,
+ country text NOT NULL,
+ phone_number text NOT NULL,
+ telesign_reference_xid text,
+ CONSTRAINT check_193736da9f CHECK ((char_length(country) <= 3)),
+ CONSTRAINT check_d2f31fc815 CHECK ((char_length(phone_number) <= 12)),
+ CONSTRAINT check_d7af4d3eb5 CHECK ((char_length(telesign_reference_xid) <= 255))
+);
+
CREATE TABLE user_preferences (
id integer NOT NULL,
user_id integer NOT NULL,
@@ -22142,12 +22267,13 @@ CREATE TABLE user_preferences (
setup_for_company boolean,
render_whitespace_in_code boolean,
tab_width smallint,
- experience_level smallint,
view_diffs_file_by_file boolean DEFAULT false NOT NULL,
gitpod_enabled boolean DEFAULT false NOT NULL,
markdown_surround_selection boolean DEFAULT true NOT NULL,
diffs_deletion_color text,
diffs_addition_color text,
+ markdown_automatic_lists boolean DEFAULT true NOT NULL,
+ use_legacy_web_ide boolean DEFAULT false NOT NULL,
CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)),
CONSTRAINT check_d07ccd35f7 CHECK ((char_length(diffs_addition_color) <= 7))
);
@@ -22522,7 +22648,8 @@ CREATE TABLE vulnerability_feedback (
comment text,
comment_timestamp timestamp with time zone,
finding_uuid uuid,
- dismissal_reason smallint
+ dismissal_reason smallint,
+ migrated_to_state_transition boolean DEFAULT false
);
CREATE SEQUENCE vulnerability_feedback_id_seq
@@ -22932,7 +23059,6 @@ CREATE TABLE web_hooks (
created_at timestamp without time zone,
updated_at timestamp without time zone,
type character varying DEFAULT 'ProjectHook'::character varying,
- service_id integer,
push_events boolean DEFAULT true NOT NULL,
issues_events boolean DEFAULT false NOT NULL,
merge_requests_events boolean DEFAULT false NOT NULL,
@@ -23653,6 +23779,10 @@ 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_event_tag_links ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_event_tag_links_id_seq'::regclass);
+
+ALTER TABLE ONLY incident_management_timeline_event_tags ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_event_tags_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);
@@ -23861,6 +23991,8 @@ ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('pac
ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass);
+ALTER TABLE ONLY packages_rpm_repository_files ALTER COLUMN id SET DEFAULT nextval('packages_rpm_repository_files_id_seq'::regclass);
+
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);
@@ -25010,9 +25142,6 @@ ALTER TABLE ONLY chat_teams
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
-ALTER TABLE members
- ADD CONSTRAINT check_508774aac0 CHECK ((member_namespace_id IS NOT NULL)) NOT VALID;
-
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
@@ -25041,7 +25170,7 @@ ALTER TABLE ONLY ci_build_trace_metadata
ADD CONSTRAINT ci_build_trace_metadata_pkey PRIMARY KEY (build_id);
ALTER TABLE ONLY ci_builds_metadata
- ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
+ ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT ci_builds_pkey PRIMARY KEY (id);
@@ -25100,6 +25229,9 @@ ALTER TABLE ONLY ci_pipeline_chat_data
ALTER TABLE ONLY ci_pipeline_messages
ADD CONSTRAINT ci_pipeline_messages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_pipeline_metadata
+ ADD CONSTRAINT ci_pipeline_metadata_pkey PRIMARY KEY (pipeline_id);
+
ALTER TABLE ONLY ci_pipeline_schedule_variables
ADD CONSTRAINT ci_pipeline_schedule_variables_pkey PRIMARY KEY (id);
@@ -25607,6 +25739,12 @@ 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_event_tag_links
+ ADD CONSTRAINT incident_management_timeline_event_tag_links_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY incident_management_timeline_event_tags
+ ADD CONSTRAINT incident_management_timeline_event_tags_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY incident_management_timeline_events
ADD CONSTRAINT incident_management_timeline_events_pkey PRIMARY KEY (id);
@@ -25994,6 +26132,9 @@ ALTER TABLE ONLY packages_pypi_metadata
ALTER TABLE ONLY packages_rpm_metadata
ADD CONSTRAINT packages_rpm_metadata_pkey PRIMARY KEY (package_id);
+ALTER TABLE ONLY packages_rpm_repository_files
+ ADD CONSTRAINT packages_rpm_repository_files_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_rubygems_metadata
ADD CONSTRAINT packages_rubygems_metadata_pkey PRIMARY KEY (package_id);
@@ -26132,6 +26273,9 @@ ALTER TABLE ONLY project_statistics
ALTER TABLE ONLY project_topics
ADD CONSTRAINT project_topics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_wiki_repository_states
+ ADD CONSTRAINT project_wiki_repository_states_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY projects
ADD CONSTRAINT projects_pkey PRIMARY KEY (id);
@@ -26441,6 +26585,9 @@ ALTER TABLE ONLY user_namespace_callouts
ALTER TABLE ONLY user_permission_export_uploads
ADD CONSTRAINT user_permission_export_uploads_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY user_phone_number_validations
+ ADD CONSTRAINT user_phone_number_validations_pkey PRIMARY KEY (user_id);
+
ALTER TABLE ONLY user_preferences
ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id);
@@ -27556,6 +27703,10 @@ CREATE INDEX idx_analytics_devops_adoption_segments_on_namespace_id ON analytics
CREATE INDEX idx_analytics_devops_adoption_snapshots_finalized ON analytics_devops_adoption_snapshots USING btree (namespace_id, end_time) WHERE (recorded_at >= end_time);
+CREATE INDEX idx_approval_merge_request_rules_on_sec_orchestration_config_id ON approval_merge_request_rules USING btree (security_orchestration_policy_configuration_id);
+
+CREATE INDEX idx_approval_project_rules_on_sec_orchestration_config_id ON approval_project_rules USING btree (security_orchestration_policy_configuration_id);
+
CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
CREATE INDEX idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id ON award_emoji USING btree (user_id, name, awardable_type, awardable_id);
@@ -27642,6 +27793,8 @@ CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_c
CREATE INDEX idx_mrs_on_target_id_and_created_at_and_state_id ON merge_requests USING btree (target_project_id, state_id, created_at, id);
+CREATE UNIQUE INDEX idx_namespace_settings_on_default_compliance_framework_id ON namespace_settings USING btree (default_compliance_framework_id);
+
CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
CREATE UNIQUE INDEX idx_on_external_approval_rules_project_id_external_url ON external_approval_rules USING btree (project_id, external_url);
@@ -28028,12 +28181,14 @@ CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON c
CREATE INDEX index_ci_build_trace_metadata_on_trace_artifact_id ON ci_build_trace_metadata USING btree (trace_artifact_id);
-CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id ON ci_builds_metadata USING btree (build_id);
-
CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
CREATE INDEX index_ci_builds_metadata_on_build_id_and_id_and_interruptible ON ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true);
+CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id_partition_id_unique ON ci_builds_metadata USING btree (build_id, partition_id);
+
+CREATE UNIQUE INDEX index_ci_builds_metadata_on_id_partition_id_unique ON ci_builds_metadata USING btree (id, partition_id);
+
CREATE INDEX index_ci_builds_metadata_on_project_id ON ci_builds_metadata USING btree (project_id);
CREATE INDEX index_ci_builds_on_auto_canceled_by_id ON ci_builds USING btree (auto_canceled_by_id);
@@ -28164,6 +28319,10 @@ CREATE UNIQUE INDEX index_ci_pipeline_chat_data_on_pipeline_id ON ci_pipeline_ch
CREATE INDEX index_ci_pipeline_messages_on_pipeline_id ON ci_pipeline_messages USING btree (pipeline_id);
+CREATE INDEX index_ci_pipeline_metadata_on_pipeline_id_title ON ci_pipeline_metadata USING btree (pipeline_id, title);
+
+CREATE INDEX index_ci_pipeline_metadata_on_project_id ON ci_pipeline_metadata USING btree (project_id);
+
CREATE UNIQUE INDEX index_ci_pipeline_schedule_variables_on_schedule_id_and_key ON ci_pipeline_schedule_variables USING btree (pipeline_schedule_id, key);
CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON ci_pipeline_schedules USING btree (next_run_at, active);
@@ -28938,6 +29097,12 @@ 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_event_id ON incident_management_timeline_event_tag_links USING btree (timeline_event_id);
+
+CREATE UNIQUE INDEX index_im_timeline_event_tags_name_project_id ON incident_management_timeline_event_tags USING btree (project_id, name);
+
+CREATE UNIQUE INDEX index_im_timeline_event_tags_on_tag_id_and_event_id ON incident_management_timeline_event_tag_links USING btree (timeline_event_tag_id, timeline_event_id);
+
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);
@@ -29116,6 +29281,8 @@ CREATE INDEX index_iterations_cadences_on_group_id ON iterations_cadences USING
CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON jira_connect_installations USING btree (client_key);
+CREATE INDEX index_jira_connect_installations_on_instance_url ON jira_connect_installations USING btree (instance_url);
+
CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON jira_connect_subscriptions USING btree (namespace_id);
CREATE INDEX index_jira_imports_on_label_id ON jira_imports USING btree (label_id);
@@ -29236,8 +29403,6 @@ CREATE INDEX index_members_on_member_namespace_id ON members USING btree (member
CREATE INDEX index_members_on_member_role_id ON members USING btree (member_role_id);
-CREATE INDEX index_members_on_non_requested_non_invited_and_state_awaiting ON members USING btree (source_id) WHERE ((requested_at IS NULL) AND (invite_token IS NULL) AND (access_level > 5) AND (state = 1));
-
CREATE INDEX index_members_on_requested_at ON members USING btree (requested_at);
CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (source_id, source_type);
@@ -29398,6 +29563,8 @@ CREATE INDEX index_ml_candidate_metrics_on_candidate_id ON ml_candidate_metrics
CREATE INDEX index_ml_candidate_params_on_candidate_id ON ml_candidate_params USING btree (candidate_id);
+CREATE UNIQUE INDEX index_ml_candidate_params_on_candidate_id_on_name ON ml_candidate_params USING btree (candidate_id, name);
+
CREATE UNIQUE INDEX index_ml_candidates_on_experiment_id_and_iid ON ml_candidates USING btree (experiment_id, iid);
CREATE INDEX index_ml_candidates_on_user_id ON ml_candidates USING btree (user_id);
@@ -29490,6 +29657,8 @@ CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
CREATE INDEX index_notes_on_id_where_confidential ON notes USING btree (id) WHERE (confidential = true);
+CREATE INDEX index_notes_on_id_where_internal ON notes USING btree (id) WHERE (internal = true);
+
CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);
@@ -29540,12 +29709,6 @@ CREATE INDEX index_on_issues_closed_incidents_by_project_id_and_closed_at ON iss
CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
-CREATE INDEX index_on_merge_request_assignees_updated_state_by_user_id ON merge_request_assignees USING btree (updated_state_by_user_id);
-
-CREATE INDEX index_on_merge_request_assignees_user_id_and_state ON merge_request_assignees USING btree (user_id, state) WHERE (state = 2);
-
-CREATE INDEX index_on_merge_request_reviewers_updated_state_by_user_id ON merge_request_reviewers USING btree (updated_state_by_user_id);
-
CREATE INDEX index_on_merge_request_reviewers_user_id_and_state ON merge_request_reviewers USING btree (user_id, state) WHERE (state = 2);
CREATE INDEX index_on_merge_requests_for_latest_diffs ON merge_requests USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id);
@@ -29682,6 +29845,8 @@ CREATE INDEX index_packages_packages_on_name_trigram ON packages_packages USING
CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_packages USING btree (project_id, created_at);
+CREATE INDEX index_packages_packages_on_project_id_and_lower_version ON packages_packages USING btree (project_id, lower((version)::text)) WHERE (package_type = 4);
+
CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type);
CREATE INDEX index_packages_packages_on_project_id_and_status_and_id ON packages_packages USING btree (project_id, status, id);
@@ -29692,6 +29857,8 @@ CREATE INDEX index_packages_project_id_name_partial_for_nuget ON packages_packag
CREATE INDEX index_packages_rpm_metadata_on_package_id ON packages_rpm_metadata USING btree (package_id);
+CREATE INDEX index_packages_rpm_repository_files_on_project_id ON packages_rpm_repository_files USING btree (project_id);
+
CREATE INDEX index_packages_tags_on_package_id ON packages_tags USING btree (package_id);
CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON packages_tags USING btree (package_id, updated_at DESC);
@@ -29832,6 +29999,8 @@ CREATE INDEX index_project_group_links_on_project_id ON project_group_links USIN
CREATE INDEX index_project_import_data_on_project_id ON project_import_data USING btree (project_id);
+CREATE INDEX index_project_incident_management_settings_on_p_id_sla_timer ON project_incident_management_settings USING btree (project_id) WHERE (sla_timer = true);
+
CREATE INDEX index_project_members_on_id_temp ON members USING btree (id) WHERE ((source_type)::text = 'Project'::text);
CREATE INDEX index_project_mirror_data_on_last_successful_update_at ON project_mirror_data USING btree (last_successful_update_at);
@@ -29890,6 +30059,14 @@ CREATE INDEX index_project_topics_on_topic_id ON project_topics USING btree (top
CREATE UNIQUE INDEX index_project_user_callouts_feature ON user_project_callouts USING btree (user_id, feature_name, project_id);
+CREATE INDEX index_project_wiki_repository_states_failed_verification ON project_wiki_repository_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_project_wiki_repository_states_needs_verification ON project_wiki_repository_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX index_project_wiki_repository_states_on_verification_state ON project_wiki_repository_states USING btree (verification_state);
+
+CREATE INDEX index_project_wiki_repository_states_pending_verification ON project_wiki_repository_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
CREATE INDEX index_projects_aimed_for_deletion ON projects USING btree (marked_for_deletion_at) WHERE ((marked_for_deletion_at IS NOT NULL) AND (pending_delete = false));
CREATE INDEX index_projects_api_created_at_id_desc ON projects USING btree (created_at, id DESC);
@@ -30068,6 +30245,8 @@ CREATE INDEX index_releases_on_author_id_id_created_at ON releases USING btree (
CREATE INDEX index_releases_on_project_id_and_released_at_and_id ON releases USING btree (project_id, released_at, id);
+CREATE INDEX index_releases_on_project_id_id ON releases USING btree (project_id, id);
+
CREATE UNIQUE INDEX index_releases_on_project_tag_unique ON releases USING btree (project_id, tag);
CREATE INDEX index_releases_on_released_at ON releases USING btree (released_at);
@@ -30178,16 +30357,24 @@ CREATE UNIQUE INDEX index_saved_replies_on_name_text_pattern_ops ON saved_replie
CREATE INDEX index_sbom_component_versions_on_component_id ON sbom_component_versions USING btree (component_id);
+CREATE UNIQUE INDEX index_sbom_component_versions_on_component_id_and_version ON sbom_component_versions USING btree (component_id, version);
+
+CREATE UNIQUE INDEX index_sbom_components_on_component_type_and_name ON sbom_components USING btree (component_type, name);
+
CREATE INDEX index_sbom_occurrences_on_component_id ON sbom_occurrences USING btree (component_id);
CREATE INDEX index_sbom_occurrences_on_component_version_id ON sbom_occurrences USING btree (component_version_id);
+CREATE UNIQUE INDEX index_sbom_occurrences_on_ingestion_attributes ON sbom_occurrences USING btree (project_id, component_id, component_version_id, source_id, commit_sha);
+
CREATE INDEX index_sbom_occurrences_on_pipeline_id ON sbom_occurrences USING btree (pipeline_id);
CREATE INDEX index_sbom_occurrences_on_project_id ON sbom_occurrences USING btree (project_id);
CREATE INDEX index_sbom_occurrences_on_source_id ON sbom_occurrences USING btree (source_id);
+CREATE UNIQUE INDEX index_sbom_sources_on_source_type_and_source ON sbom_sources USING btree (source_type, source);
+
CREATE INDEX index_scim_identities_on_group_id ON scim_identities USING btree (group_id);
CREATE UNIQUE INDEX index_scim_identities_on_lower_extern_uid_and_group_id ON scim_identities USING btree (lower((extern_uid)::text), group_id);
@@ -30510,6 +30697,8 @@ CREATE INDEX index_user_namespace_callouts_on_namespace_id ON user_namespace_cal
CREATE INDEX index_user_permission_export_uploads_on_user_id_and_status ON user_permission_export_uploads USING btree (user_id, status);
+CREATE INDEX index_user_phone_validations_on_dial_code_phone_number ON user_phone_number_validations USING btree (international_dial_code, phone_number);
+
CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING btree (gitpod_enabled);
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
@@ -30564,7 +30753,7 @@ CREATE INDEX index_users_on_unconfirmed_email ON users USING btree (unconfirmed_
CREATE UNIQUE INDEX index_users_on_unlock_token ON users USING btree (unlock_token);
-CREATE INDEX index_users_on_user_type ON users USING btree (user_type);
+CREATE INDEX index_users_on_user_type_and_id ON users USING btree (user_type, id);
CREATE INDEX index_users_on_username ON users USING btree (username);
@@ -30596,6 +30785,8 @@ CREATE INDEX index_vuln_reads_on_namespace_id_state_severity_and_vuln_id ON vuln
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_vuln_reads_on_resolved_on_default_branch ON vulnerability_reads USING btree (project_id, state, id) WHERE (resolved_on_default_branch IS TRUE);
+
CREATE INDEX index_vulnerabilities_common_finder_query_on_default_branch ON vulnerabilities USING btree (project_id, state, report_type, present_on_default_branch, severity, id);
CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id);
@@ -30752,8 +30943,6 @@ CREATE INDEX index_web_hooks_on_project_id ON web_hooks USING btree (project_id)
CREATE INDEX index_web_hooks_on_project_id_recent_failures ON web_hooks USING btree (project_id, recent_failures);
-CREATE INDEX index_web_hooks_on_service_id ON web_hooks USING btree (service_id);
-
CREATE INDEX index_web_hooks_on_type ON web_hooks USING btree (type);
CREATE UNIQUE INDEX index_webauthn_registrations_on_credential_xid ON webauthn_registrations USING btree (credential_xid);
@@ -30842,6 +31031,12 @@ CREATE UNIQUE INDEX partial_index_sop_configs_on_project_id ON security_orchestr
CREATE INDEX partial_index_user_id_app_id_created_at_token_not_revoked ON oauth_access_tokens USING btree (resource_owner_id, application_id, created_at) WHERE (revoked_at IS NULL);
+CREATE INDEX scan_finding_approval_mr_rule_index_merge_request_id ON approval_merge_request_rules USING btree (merge_request_id) WHERE (report_type = 4);
+
+CREATE INDEX scan_finding_approval_project_rule_index_created_at_project_id ON approval_project_rules USING btree (created_at, project_id) WHERE (report_type = 4);
+
+CREATE INDEX scan_finding_approval_project_rule_index_project_id ON approval_project_rules USING btree (project_id) WHERE (report_type = 4);
+
CREATE INDEX security_findings_confidence_idx ON ONLY security_findings USING btree (confidence);
CREATE INDEX security_findings_project_fingerprint_idx ON ONLY security_findings USING btree (project_fingerprint);
@@ -30864,6 +31059,10 @@ CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, t
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
+CREATE INDEX tmp_idx_project_features_on_releases_al_and_repo_al_partial ON project_features USING btree (releases_access_level, repository_access_level) WHERE (releases_access_level > repository_access_level);
+
+CREATE INDEX tmp_idx_vulnerabilities_on_id_where_report_type_7_99 ON vulnerabilities USING btree (id) WHERE (report_type = ANY (ARRAY[7, 99]));
+
CREATE INDEX tmp_index_approval_merge_request_rules_on_report_type_equal_one ON approval_merge_request_rules USING btree (id, report_type) WHERE (report_type = 1);
CREATE INDEX tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown ON ci_job_artifacts USING btree (expire_at, job_id) WHERE ((locked = 2) AND (expire_at IS NOT NULL));
@@ -30876,15 +31075,15 @@ CREATE INDEX tmp_index_container_repos_on_non_migrated ON container_repositories
CREATE INDEX tmp_index_container_repositories_on_id_migration_state ON container_repositories USING btree (id, migration_state);
-CREATE INDEX tmp_index_for_null_project_namespace_id ON projects USING btree (id) WHERE (project_namespace_id IS NULL);
+CREATE INDEX tmp_index_for_null_member_namespace_id ON members USING btree (member_namespace_id) WHERE (member_namespace_id IS NULL);
CREATE INDEX tmp_index_for_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
CREATE INDEX tmp_index_issues_on_issue_type_and_id ON issues USING btree (issue_type, id);
-CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
+CREATE INDEX tmp_index_members_on_id_where_namespace_id_null ON members USING btree (id) WHERE (member_namespace_id IS NULL);
-CREATE INDEX tmp_index_merge_request_reviewers_on_attention_requested_state ON merge_request_reviewers USING btree (id) WHERE (state = 2);
+CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
CREATE INDEX tmp_index_migrated_container_registries ON container_repositories USING btree (project_id) WHERE ((migration_state = 'import_done'::text) OR (created_at >= '2022-01-23 00:00:00'::timestamp without time zone));
@@ -30894,12 +31093,8 @@ CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING
CREATE INDEX tmp_index_project_statistics_cont_registry_size ON project_statistics USING btree (project_id) WHERE (container_registry_size = 0);
-CREATE INDEX tmp_index_system_note_metadata_on_attention_request_actions ON system_note_metadata USING btree (id) WHERE ((action)::text = ANY ((ARRAY['attention_requested'::character varying, 'attention_request_removed'::character varying])::text[]));
-
CREATE INDEX tmp_index_system_note_metadata_on_id_where_task ON system_note_metadata USING btree (id, action) WHERE ((action)::text = 'task'::text);
-CREATE INDEX tmp_index_user_callouts_on_attention_request_feature_names ON user_callouts USING btree (id) WHERE (feature_name = ANY (ARRAY[47, 48]));
-
CREATE INDEX tmp_index_vulnerability_occurrences_on_id_and_scanner_id ON vulnerability_occurrences USING btree (id, scanner_id) WHERE (report_type = ANY (ARRAY[7, 99]));
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
@@ -32232,12 +32427,6 @@ CREATE TRIGGER nullify_merge_request_metrics_build_data_on_update BEFORE UPDATE
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_a645cee67576 BEFORE UPDATE OF integration_id ON web_hooks FOR EACH ROW EXECUTE FUNCTION function_for_trigger_a645cee67576();
-
-CREATE TRIGGER trigger_a87bcfdf0f0b BEFORE INSERT ON web_hooks FOR EACH ROW EXECUTE FUNCTION function_for_trigger_a87bcfdf0f0b();
-
-CREATE TRIGGER trigger_aca5c963d732 BEFORE UPDATE OF service_id ON web_hooks FOR EACH ROW EXECUTE FUNCTION function_for_trigger_aca5c963d732();
-
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();
@@ -32393,6 +32582,9 @@ ALTER TABLE ONLY ghost_user_migrations
ALTER TABLE ONLY coverage_fuzzing_corpuses
ADD CONSTRAINT fk_204d40056a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_settings
+ ADD CONSTRAINT fk_20cf0eb2f9 FOREIGN KEY (default_compliance_framework_id) REFERENCES compliance_management_frameworks(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY geo_container_repository_updated_events
ADD CONSTRAINT fk_212c89c706 FOREIGN KEY (container_repository_id) REFERENCES container_repositories(id) ON DELETE CASCADE;
@@ -32513,9 +32705,6 @@ ALTER TABLE ONLY epics
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_3d34ab2e06 FOREIGN KEY (pipeline_schedule_id) REFERENCES ci_pipeline_schedules(id) ON DELETE SET NULL;
-ALTER TABLE ONLY merge_request_reviewers
- ADD CONSTRAINT fk_3d674b9f23 FOREIGN KEY (updated_state_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY protected_environment_approval_rules
ADD CONSTRAINT fk_405568b491 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -32579,6 +32768,9 @@ ALTER TABLE ONLY vulnerability_feedback
ALTER TABLE ONLY ml_candidates
ADD CONSTRAINT fk_56d6ed4d3d FOREIGN KEY (experiment_id) REFERENCES ml_experiments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules
+ ADD CONSTRAINT fk_5822f009ea FOREIGN KEY (security_orchestration_policy_configuration_id) REFERENCES security_orchestration_policy_configurations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY deploy_keys_projects
ADD CONSTRAINT fk_58a901ca7e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -32894,9 +33086,6 @@ ALTER TABLE ONLY vulnerability_reads
ALTER TABLE ONLY dast_profile_schedules
ADD CONSTRAINT fk_aef03d62e5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY merge_request_assignees
- ADD CONSTRAINT fk_af036e3261 FOREIGN KEY (updated_state_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_analytics_cycle_analytics_group_stages_group_value_stream_id FOREIGN KEY (group_value_stream_id) REFERENCES analytics_cycle_analytics_group_value_streams(id) ON DELETE CASCADE;
@@ -33047,9 +33236,6 @@ ALTER TABLE ONLY environments
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_d3130c9a7f FOREIGN KEY (commit_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY web_hooks
- ADD CONSTRAINT fk_d47999a98a FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_d4e29af7d7 FOREIGN KEY (source_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
@@ -33158,6 +33344,9 @@ ALTER TABLE ONLY events
ALTER TABLE ONLY coverage_fuzzing_corpuses
ADD CONSTRAINT fk_ef5ebf339f FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules
+ ADD CONSTRAINT fk_efa5a1e3fb FOREIGN KEY (security_orchestration_policy_configuration_id) REFERENCES security_orchestration_policy_configurations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_efb96ab1e2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -33749,6 +33938,9 @@ ALTER TABLE ONLY resource_iteration_events
ALTER TABLE ONLY status_page_settings
ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_metadata
+ ADD CONSTRAINT fk_rails_50c1e9ea10 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_repository_storage_moves
ADD CONSTRAINT fk_rails_5106dbd44a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -33782,6 +33974,9 @@ ALTER TABLE ONLY issue_user_mentions
ALTER TABLE ONLY merge_request_assignees
ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_event_tag_links
+ ADD CONSTRAINT fk_rails_57baccd7f9 FOREIGN KEY (timeline_event_id) REFERENCES incident_management_timeline_events(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_debian_project_architectures
ADD CONSTRAINT fk_rails_5808663adf FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
@@ -33986,6 +34181,9 @@ ALTER TABLE ONLY group_crm_settings
ALTER TABLE ONLY clusters_applications_ingress
ADD CONSTRAINT fk_rails_753a7b41c1 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_event_tag_links
+ ADD CONSTRAINT fk_rails_753b8b6ee3 FOREIGN KEY (timeline_event_tag_id) REFERENCES incident_management_timeline_event_tags(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY release_links
ADD CONSTRAINT fk_rails_753be7ae29 FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
@@ -34175,6 +34373,9 @@ ALTER TABLE ONLY packages_debian_project_distributions
ALTER TABLE ONLY packages_rubygems_metadata
ADD CONSTRAINT fk_rails_95a3f5ce78 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_wiki_repository_states
+ ADD CONSTRAINT fk_rails_9647227ce1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_pypi_metadata
ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
@@ -34325,6 +34526,9 @@ ALTER TABLE ONLY clusters
ALTER TABLE ONLY packages_composer_metadata
ADD CONSTRAINT fk_rails_ad48c2e5bb FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_phone_number_validations
+ ADD CONSTRAINT fk_rails_ad6686f3d8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_rails_ae5da3409b FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -34574,6 +34778,9 @@ ALTER TABLE ONLY geo_hashed_storage_attachments_events
ALTER TABLE ONLY ml_candidate_params
ADD CONSTRAINT fk_rails_d4a51d1185 FOREIGN KEY (candidate_id) REFERENCES ml_candidates(id);
+ALTER TABLE ONLY packages_rpm_repository_files
+ ADD CONSTRAINT fk_rails_d545cfaed2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_rpm_metadata
ADD CONSTRAINT fk_rails_d79f02264b FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
@@ -34604,6 +34811,9 @@ ALTER TABLE ONLY deployment_merge_requests
ALTER TABLE ONLY packages_debian_group_component_files
ADD CONSTRAINT fk_rails_dd262386e9 FOREIGN KEY (component_id) REFERENCES packages_debian_group_components(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY incident_management_timeline_event_tags
+ ADD CONSTRAINT fk_rails_dd5c91484e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY user_callouts
ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 43ccaf6bd7a..5d268fdb241 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -143,6 +143,7 @@ crosslinks
Crossplane
Crowdin
CSV
+customappsso
cybersecurity
Dangerfile
Datadog
@@ -439,6 +440,7 @@ onboarding
OpenID
OpenShift
Opsgenie
+outdent
Overcommit
Packagist
parallelization
@@ -642,6 +644,8 @@ stunnel
stylelint
subchart
subcharts
+subcommand
+subcommands
subfolder
subfolders
subgraph
diff --git a/doc/administration/application_settings_cache.md b/doc/administration/application_settings_cache.md
index 88e39a50b6c..d04056beb96 100644
--- a/doc/administration/application_settings_cache.md
+++ b/doc/administration/application_settings_cache.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Application Performance
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application cache interval **(FREE SELF)**
diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md
index 9ec7b81bfd0..ca60b6142fe 100644
--- a/doc/administration/audit_event_streaming.md
+++ b/doc/administration/audit_event_streaming.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Audit event streaming **(ULTIMATE)**
@@ -831,3 +831,49 @@ X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
"event_type": "project_group_link_destroy"
}
```
+
+## Audit event streaming on invalid merge request approver state
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/374566) in GitLab 15.5.
+
+Stream audit events that relate to invalid merge request approver states within a project.
+
+### Headers
+
+Headers are formatted as follows:
+
+```plaintext
+POST /logs HTTP/1.1
+Host: <DESTINATION_HOST>
+Content-Type: application/x-www-form-urlencoded
+X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
+X-Gitlab-Audit-Event-Type: audit_operation
+```
+
+### Example payload
+
+```json
+{
+ "id": 1,
+ "author_id": 1,
+ "entity_id": 6,
+ "entity_type": "Project",
+ "details": {
+ "author_name": "example_username",
+ "target_id": 20,
+ "target_type": "MergeRequest",
+ "target_details": { title: "Merge request title", iid: "Merge request iid", id: "Merge request id" },
+ "custom_message": "Invalid merge request approver rules",
+ "ip_address": "127.0.0.1",
+ "entity_path": "example-group/example-project"
+ },
+ "ip_address": "127.0.0.1",
+ "author_name": "example_username",
+ "entity_path": "example-group/example-project",
+ "target_details": "merge request title",
+ "created_at": "2022-03-09T06:53:11.181Z",
+ "target_type": "MergeRequest",
+ "target_id": 20,
+ "event_type": "audit_operation"
+}
+```
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index b6c267bfd0c..11600bc2da6 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Audit Events **(PREMIUM)**
diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md
index e363e7862ea..8e91466d345 100644
--- a/doc/administration/audit_reports.md
+++ b/doc/administration/audit_reports.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Learn how to create evidence artifacts typically requested by a 3rd party auditor.'
---
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index bd48cfdbc4f..a047e7c1f0b 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Auditor users **(PREMIUM SELF)**
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
index 1d20d87bdf4..b02ac06b67f 100644
--- a/doc/administration/auth/atlassian.md
+++ b/doc/administration/auth/atlassian.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Atlassian OmniAuth Provider **(FREE SELF)**
@@ -11,7 +11,7 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
## Atlassian application registration
-1. Go to <https://developer.atlassian.com/console/myapps/> and sign-in with the Atlassian
+1. Go to the [Atlassian developer console](https://developer.atlassian.com/console/myapps/) and sign-in with the Atlassian
account to administer the application.
1. Select **Create a new app**.
1. Choose an App Name, such as 'GitLab', and select **Create**.
@@ -51,8 +51,8 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
{
name: "atlassian_oauth2",
# label: "Provider name", # optional label for login button, defaults to "Atlassian"
- app_id: "YOUR_CLIENT_ID",
- app_secret: "YOUR_CLIENT_SECRET",
+ app_id: "<your_client_id>",
+ app_secret: "<your_client_secret>",
args: { scope: "offline_access read:jira-user read:jira-work", prompt: "consent" }
}
]
@@ -63,13 +63,13 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
```yaml
- { name: "atlassian_oauth2",
# label: "Provider name", # optional label for login button, defaults to "Atlassian"
- app_id: "YOUR_CLIENT_ID",
- app_secret: "YOUR_CLIENT_SECRET",
+ app_id: "<your_client_id>",
+ app_secret: "<your_client_secret>",
args: { scope: "offline_access read:jira-user read:jira-work", prompt: "consent" }
}
```
-1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in [application registration](#atlassian-application-registration) steps.
+1. Change `<your_client_id>` and `<your_client_secret>` to the Client credentials you received during [application registration](#atlassian-application-registration).
1. Save the configuration file.
1. For the changes to take effect:
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 61ce2b5ab25..1ac62b06fe7 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -2,12 +2,12 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Authentiq OmniAuth Provider **(FREE SELF)**
-To enable the Authentiq OmniAuth provider for passwordless authentication you must register an application with Authentiq.
+To enable the Authentiq OmniAuth provider for passwordless authentication, you must register an application with Authentiq.
Authentiq generates a Client ID and the accompanying Client Secret for you to use.
@@ -38,8 +38,8 @@ Authentiq generates a Client ID and the accompanying Client Secret for you to us
{
name: "authentiq",
# label: "Provider name", # optional label for login button, defaults to "Authentiq"
- app_id: "YOUR_CLIENT_ID",
- app_secret: "YOUR_CLIENT_SECRET",
+ app_id: "<your_client_id>",
+ app_secret: "<your_client_secret>",
args: {
"scope": 'aq:name email~rs address aq:push'
}
@@ -52,22 +52,28 @@ 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',
+ app_id: '<your_client_id>',
+ app_secret: '<your_client_secret>',
args: {
scope: 'aq:name email~rs address aq:push'
}
}
```
-1. The `scope` is set to request the user's name, email (required and signed), and permission to send push notifications to sign in on subsequent visits.
+1. The `scope` is set to request the:
+ - User's name.
+ - Required and signed email.
+ - Permission to send push notifications to sign in on subsequent visits.
+
See [OmniAuth Authentiq strategy](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Scopes,-callback-url-configuration-and-responses) for more information on scopes and modifiers.
-1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in step 1.
+1. Change `<your_client_id>` and `<your_client_secret>` to the Client credentials you received from Authentiq.
1. Save the configuration file.
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) if you installed GitLab using Omnibus.
+ - [Restart GitLab](../restart_gitlab.md#installations-from-source) if you installed GitLab from source.
On the sign in page there should now be an Authentiq icon below the regular sign in form. Select the
icon to begin the authentication process. If the user:
@@ -77,7 +83,7 @@ icon to begin the authentication process. If the user:
1. Decide what personal details to share.
1. Sign in to your GitLab installation.
- Does not have the app installed, they are prompted to download the app and then follow the
- procedure above.
+ previous procedure.
If everything works, the user is returned to GitLab and is signed in.
diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index db8cdd3e7bb..bb06d5d1a58 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -2,41 +2,42 @@
type: concepts, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Amazon Web Services Cognito **(FREE SELF)**
Amazon Cognito lets you add user sign-up, sign-in, and access control to your GitLab instance.
-The following documentation enables Cognito as an OAuth2 provider.
+The following documentation enables Cognito as an OAuth 2.0 provider.
## Configure AWS Cognito
-To enable the [AWS Cognito](https://aws.amazon.com/cognito/) OAuth2 OmniAuth provider, register your application with Cognito. This process generates a Client ID and Client Secret for your application.
-Any settings you configure in the following procedure can be modified later.
-The following steps enable AWS Cognito as an authentication provider:
+To enable the [AWS Cognito](https://aws.amazon.com/cognito/) OAuth 2.0 OmniAuth provider, register your application with Cognito. This process generates a Client ID and Client Secret for your application.
+To enable AWS Cognito as an authentication provider, complete the following steps. You can modify any settings you configure later.
1. Sign in to the [AWS console](https://console.aws.amazon.com/console/home).
-1. Select **Cognito** from the **Services** menu.
-1. Select **Manage User Pools**, and select the **Create a user pool** button in the top right corner.
-1. Enter the pool name and then select the **Step through settings** button.
+1. From the **Services** menu, select **Cognito**.
+1. Select **Manage User Pools** and then select **Create a user pool** in the top right corner.
+1. Enter the user pool name and then select **Step through settings**.
1. Under **How do you want your end users to sign in?**, select **Email address or phone number** and **Allow email addresses**.
1. Under **Which standard attributes do you want to require?**, select **email**.
-1. Go to the next steps of configuration and set the rest of the settings to suit your needs - in the basic setup they are not related to GitLab configuration.
-1. In the **App clients** settings, select **Add an app client**, add **App client name** and select the **Enable username password based authentication** checkbox.
+1. Configure the remaining settings to suit your needs. In the basic setup, these settings do not affect GitLab configuration.
+1. In the **App clients** settings:
+ 1. Select **Add an app client**.
+ 1. Add the **App client name**.
+ 1. Select the **Enable username password based authentication** checkbox.
1. Select **Create app client**.
-1. In the next step, you can set up AWS Lambda functions for sending emails. You can then finish creating the pool.
+1. Set up the AWS Lambda functions for sending emails and finish creating the user pool.
1. After creating the user pool, go to **App client settings** and provide the required information:
- **Enabled Identity Providers** - select all
- - **Callback URL** - `https://gitlab.example.com/users/auth/cognito/callback`
- - Substitute the URL of your GitLab instance for `gitlab.example.com`
+ - **Callback URL** - `https://<your_gitlab_instance_url>/users/auth/cognito/callback`
- **Allowed OAuth Flows** - Authorization code grant
- **Allowed OAuth2 Scopes** - `email`, `openid`, and `profile`
1. Save changes for the app client settings.
-1. Under **Domain name** include the AWS domain name for your AWS Cognito application.
-1. Under **App Clients**, find your app client ID and app client secret. These values correspond to the OAuth2 Client ID and Client Secret. Save these values.
+1. Under **Domain name**, include the AWS domain name for your AWS Cognito application.
+1. Under **App Clients**, find your app client ID. Select **Show details* to display the app client secret. These values correspond to the OAuth 2.0 Client ID and Client Secret. Save these values.
## Configure GitLab
@@ -49,8 +50,13 @@ The following steps enable AWS Cognito as an authentication provider:
sudo editor /etc/gitlab/gitlab.rb
```
-1. In the following code block, substitute the Client ID (`app_id`), Client Secret (`app_secret`), and the Amazon domain name (`site`) for your AWS Cognito application.
-Include the code block in the `/etc/gitlab/gitlab.rb` file:
+1. In the following code block, enter your AWS Cognito application information in the following parameters:
+
+ - `app_id`: Your client ID.
+ - `app_secret`: Your client secret.
+ - `site`: Your Amazon domain and region.
+
+ Include the code block in the `/etc/gitlab/gitlab.rb` file:
```ruby
gitlab_rails['omniauth_allow_single_sign_on'] = ['cognito']
@@ -59,12 +65,12 @@ Include the code block in the `/etc/gitlab/gitlab.rb` file:
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",
+ app_id: "<client_id>",
+ app_secret: "<client_secret>",
args: {
scope: "openid profile email",
client_options: {
- site: "https://your_domain.auth.your_region.amazoncognito.com",
+ site: "https://<your_domain>.auth.<your_region>.amazoncognito.com",
authorize_url: "/oauth2/authorize",
token_url: "/oauth2/token",
user_info_url: "/oauth2/userInfo"
@@ -84,8 +90,9 @@ Include the code block in the `/etc/gitlab/gitlab.rb` file:
1. Save the configuration file.
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
-Your sign-in page should now display a Cognito button below the regular sign-in form.
-To begin the authentication process, select the icon, and AWS Cognito asks the user to sign in and authorize the GitLab application.
-If successful, the user is redirected and signed in to your GitLab instance.
+Your sign-in page should now display a Cognito option below the regular sign-in form.
+Select this option to begin the authentication process.
+AWS Cognito then asks you to sign in and authorize the GitLab application.
+If the authorization is successful, you're redirected and signed in to your GitLab instance.
For more information, see [Configure initial settings](../../integration/omniauth.md#configure-initial-settings).
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index ced7cdb7119..4395309e91e 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Atlassian Crowd OmniAuth provider (deprecated) **(FREE SELF)**
diff --git a/doc/administration/auth/index.md b/doc/administration/auth/index.md
index 2644e3a1f50..307d9a4518d 100644
--- a/doc/administration/auth/index.md
+++ b/doc/administration/auth/index.md
@@ -3,7 +3,7 @@ comments: false
type: index
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab authentication and authorization **(FREE SELF)**
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 71ab084065a..c7e7253ef72 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# JWT OmniAuth provider **(FREE SELF)**
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index 7f399f7e730..2077c6f7baf 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Google Secure LDAP **(FREE SELF)**
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 19f656d2f14..3bb9350e960 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrate LDAP with GitLab **(FREE SELF)**
@@ -13,7 +13,7 @@ to support user authentication.
This integration works with most LDAP-compliant directory servers, including:
- Microsoft Active Directory.
- [Microsoft Active Directory Trusts](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771568(v=ws.10))
+ [Microsoft Active Directory Trusts](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771568(v=ws.10))
are not supported.
- Apple Open Directory.
- Open LDAP.
@@ -98,7 +98,7 @@ gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'LDAP',
'host' => 'ldap.mydomain.com',
- 'port' => 389,
+ 'port' => 636,
'uid' => 'sAMAccountName',
'encryption' => 'simple_tls',
'verify_certificates' => true,
@@ -312,7 +312,7 @@ To limit access to the nested members of an Active Directory group, use the foll
```
For more information about `LDAP_MATCHING_RULE_IN_CHAIN` filters, see
-[Search Filter Syntax](https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax).
+[Search Filter Syntax](https://learn.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax).
Support for nested members in the user filter shouldn't be confused with
[group sync nested groups](ldap_synchronization.md#supported-ldap-group-typesattributes) support.
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index a68e6ae2649..0ec482648a9 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting LDAP **(FREE SELF)**
@@ -866,3 +866,36 @@ To enable debug output in the rails console, [enter the rails console](#rails-co
```ruby
Rails.logger.level = Logger::DEBUG
```
+
+#### Get all error messages associated with groups, subgroups, members, and requesters
+
+Collect error messages associated with groups, subgroups, members, and requesters. This
+captures error messages that may not appear in the Web interface. This can be especially helpful
+for troubleshooting issues with [LDAP group sync](ldap_synchronization.md#group-sync)
+and unexpected behavior with users and their membership in groups and subgroups.
+
+```ruby
+# Find the group and subgroup
+group = Group.find_by_full_path("parent_group")
+subgroup = Group.find_by_full_path("parent_group/child_group")
+
+# Group and subgroup errors
+group.valid?
+group.errors.map(&:full_messages)
+
+subgroup.valid?
+subgroup.errors.map(&:full_messages)
+
+# Group and subgroup errors for the members AND requesters
+group.requesters.map(&:valid?)
+group.requesters.map(&:errors).map(&:full_messages)
+group.members.map(&:valid?)
+group.members.map(&:errors).map(&:full_messages)
+group.members_and_requesters.map(&:errors).map(&:full_messages)
+
+subgroup.requesters.map(&:valid?)
+subgroup.requesters.map(&:errors).map(&:full_messages)
+subgroup.members.map(&:valid?)
+subgroup.members.map(&:errors).map(&:full_messages)
+subgroup.members_and_requesters.map(&:errors).map(&:full_messages)
+```
diff --git a/doc/administration/auth/ldap/ldap_synchronization.md b/doc/administration/auth/ldap/ldap_synchronization.md
index 37a27fc058e..af2b1400670 100644
--- a/doc/administration/auth/ldap/ldap_synchronization.md
+++ b/doc/administration/auth/ldap/ldap_synchronization.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# LDAP synchronization **(PREMIUM SELF)**
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 9f3c96902f8..bb263512e06 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -2,14 +2,16 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# OpenID Connect OmniAuth provider **(FREE SELF)**
-GitLab can use [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) as an OmniAuth provider.
+GitLab can use [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html)
+as an OmniAuth provider.
-To enable the OpenID Connect OmniAuth provider, you must register your application with an OpenID Connect provider.
+To enable the OpenID Connect OmniAuth provider, you must register your application
+with an OpenID Connect provider.
The OpenID Connect provides you with a client's details and secret for you to use.
1. On your GitLab server, open the configuration file.
@@ -27,7 +29,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
sudo -u git -H editor config/gitlab.yml
```
- See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings.
+1. [Configure initial settings](../../integration/omniauth.md#configure-initial-settings).
1. Add the provider configuration.
@@ -83,32 +85,51 @@ The OpenID Connect provides you with a client's details and secret for you to us
```
NOTE:
- For more information on each configuration option refer to the [OmniAuth OpenID Connect usage documentation](https://github.com/m0n9oose/omniauth_openid_connect#usage)
- and the [OpenID Connect Core 1.0 specification](https://openid.net/specs/openid-connect-core-1_0.html).
+ For more information on each configuration option, refer to the:
+
+ - [OmniAuth OpenID Connect usage documentation](https://github.com/m0n9oose/omniauth_openid_connect#usage).
+ - [OpenID Connect Core 1.0 specification](https://openid.net/specs/openid-connect-core-1_0.html).
+
+1. For the provider configuration, change the values for the provider to match your
+ OpenID Connect client setup. Use the following as a guide:
-1. For the configuration above, change the values for the provider to match your OpenID Connect client setup. Use the following as a guide:
- `<your_oidc_label>` is the label that appears on the login page.
- - `<custom_provider_icon>` (optional) is the icon that appears on the login page. Icons for the major social login platforms are built-in into GitLab,
- but can be overridden by specifying this parameter. Both local paths and absolute URLs are accepted.
- - `<your_oidc_url>` (optional) is the URL that points to the OpenID Connect provider. For example, `https://example.com/auth/realms/your-realm`.
- If this value is not provided, the URL is constructed from the `client_options` in the following format: `<client_options.scheme>://<client_options.host>:<client_options.port>`.
- - If `discovery` is set to `true`, the OpenID Connect provider attempts to auto discover the client options using `<your_oidc_url>/.well-known/openid-configuration`. Defaults to `false`.
- - `client_auth_method` (optional) specifies the method used for authenticating the client with the OpenID Connect provider.
+ - `<custom_provider_icon>` (optional) is the icon that appears on the login page.
+ Icons for the major social login platforms are built into GitLab,
+ but you can override these icons by specifying this parameter. GitLab accepts both
+ local paths and absolute URLs.
+ - `<your_oidc_url>` (optional) is the URL that points to the OpenID Connect
+ provider (for example, `https://example.com/auth/realms/your-realm`).
+ If this value is not provided, the URL is constructed from `client_options`
+ in the following format: `<client_options.scheme>://<client_options.host>:<client_options.port>`.
+ - If `discovery` is set to `true`, the OpenID Connect provider attempts to automatically
+ discover the client options using `<your_oidc_url>/.well-known/openid-configuration`.
+ Defaults to `false`.
+ - `client_auth_method` (optional) specifies the method used for authenticating
+ the client with the OpenID Connect provider.
- Supported values are:
- - `basic` - HTTP Basic Authentication
- - `jwt_bearer` - JWT based authentication (private key and client secret signing)
- - `mtls` - Mutual TLS or X.509 certificate validation
- - Any other value POSTs the client ID and secret in the request body
- - If not specified, defaults to `basic`.
- - `<uid_field>` (optional) is the field name from the `user_info.raw_attributes` that defines the value for `uid`. For example, `preferred_username`.
- If this value is not provided or the field with the configured value is missing from the `user_info.raw_attributes` details, the `uid` uses the `sub` field.
- - `send_scope_to_token_endpoint` is `true` by default. In other words, the `scope` parameter is normally included in requests to the token endpoint.
- However, if your OpenID Connect provider does not accept the `scope` parameter in such requests, set this to `false`.
+ - `basic` - HTTP Basic Authentication.
+ - `jwt_bearer` - JWT-based authentication (private key and client secret signing).
+ - `mtls` - Mutual TLS or X.509 certificate validation.
+ - Any other value posts the client ID and secret in the request body.
+ - If not specified, this value defaults to `basic`.
+ - `<uid_field>` (optional) is the field name from `user_info.raw_attributes`
+ that defines the value for `uid` (for example, `preferred_username`).
+ If you do not provide this value, or the field with the configured value is missing
+ from the `user_info.raw_attributes` details, `uid` uses the `sub` field.
+ - `send_scope_to_token_endpoint` is `true` by default, so the `scope` parameter
+ is normally included in requests to the token endpoint.
+ However, if your OpenID Connect provider does not accept the `scope` parameter
+ in such requests, set this to `false`.
- `client_options` are the OpenID Connect client-specific options. Specifically:
- `identifier` is the client identifier as configured in the OpenID Connect service provider.
- - `secret` is the client secret as configured in the OpenID Connect service provider.
- - `redirect_uri` is the GitLab URL to redirect the user to after successful login. For example, `http://example.com/users/auth/openid_connect/callback`.
- - `end_session_endpoint` (optional) is the URL to the endpoint that end the session (logout). Can be provided if auto-discovery disabled or unsuccessful.
+ - `secret` is the client secret as configured in the OpenID Connect service provider. For example,
+ [OmniAuth OpenIDConnect](https://github.com/omniauth/omniauth_openid_connect)) requires this. If the service provider doesn't require a secret,
+ provide any value and it is ignored.
+ - `redirect_uri` is the GitLab URL to redirect the user to after successful login
+ (for example, `http://example.com/users/auth/openid_connect/callback`).
+ - `end_session_endpoint` (optional) is the URL to the endpoint that ends the
+ session. You can provide this URL if auto-discovery is disabled or unsuccessful.
- The following `client_options` are optional unless auto-discovery is disabled or unsuccessful:
- `authorization_endpoint` is the URL to the endpoint that authorizes the end user.
- `token_endpoint` is the URL to the endpoint that provides Access Token.
@@ -116,20 +137,22 @@ The OpenID Connect provides you with a client's details and secret for you to us
- `jwks_uri` is the URL to the endpoint where the Token signer publishes its keys.
1. Save the configuration file.
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source)
- for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+1. For changes to take effect, if you installed GitLab:
+
+ - With Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - From source, [restart GitLab](../restart_gitlab.md#installations-from-source).
-On the sign in page, there should now be an OpenID Connect icon below the regular sign in form.
-Select the icon to begin the authentication process. The OpenID Connect provider asks the user to
-sign in and authorize the GitLab application (if confirmation required by the client). If everything goes well, the user
-is redirected to GitLab and signed in.
+On the sign in page, you have an OpenID Connect option below the regular sign in form.
+Select this option to begin the authentication process. The OpenID Connect provider
+asks you to sign in and authorize the GitLab application if confirmation is required
+by the client. You are redirected to GitLab and signed in.
## Example configurations
The following configurations illustrate how to set up OpenID with
different providers with Omnibus GitLab.
-### Google
+### Configure Google
See the [Google documentation](https://developers.google.com/identity/protocols/oauth2/openid-connect)
for more details:
@@ -157,16 +180,16 @@ gitlab_rails['omniauth_providers'] = [
]
```
-### Microsoft Azure
+### Configure Microsoft Azure
-The OpenID Connect (OIDC) protocol for Microsoft Azure uses the [Microsoft identity platform (v2) endpoints](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison).
-To get started, sign in to the [Azure Portal](https://portal.azure.com). For your app, you need the
-following information:
+The OpenID Connect (OIDC) protocol for Microsoft Azure uses the [Microsoft identity platform (v2) endpoints](https://learn.microsoft.com/en-us/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison).
+To get started, sign in to the [Azure Portal](https://portal.azure.com). For your app,
+you need the following information:
-- A tenant ID. You may already have one. For more information, review the
- [Microsoft Azure Tenant](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
+- A tenant ID. You may already have one. For more information, see the
+ [Microsoft Azure Tenant](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
- A client ID and a client secret. Follow the instructions in the
- [Microsoft Quickstart Register an Application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) documentation
+ [Microsoft Quickstart Register an Application](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) documentation
to obtain the tenant ID, client ID, and client secret for your app.
Example Omnibus configuration block:
@@ -194,49 +217,51 @@ gitlab_rails['omniauth_providers'] = [
]
```
-Microsoft has documented how its platform works with [the OIDC protocol](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc).
+Microsoft has documented how its platform works with [the OIDC protocol](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc).
-### Microsoft Azure Active Directory B2C
+### Configure Microsoft Azure Active Directory B2C
-While GitLab works with [Azure Active Directory B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/overview), it requires special
-configuration to work. To get started, sign in to the [Azure Portal](https://portal.azure.com).
+GitLab requires special
+configuration to work with [Azure Active Directory B2C](https://learn.microsoft.com/en-us/azure/active-directory-b2c/overview). To get started, sign in to the [Azure Portal](https://portal.azure.com).
For your app, you need the following information from Azure:
- A tenant ID. You may already have one. For more information, review the
- [Microsoft Azure Tenant](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
+ [Microsoft Azure Tenant](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
- A client ID and a client secret. Follow the instructions in the
- [Microsoft tutorial](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga) documentation to obtain the
+ [Microsoft tutorial](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga) documentation to obtain the
client ID and client secret for your app.
-- The user flow or policy name. Follow the instructions in the [Microsoft tutorial](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-user-flow).
+- The user flow or policy name. Follow the instructions in the [Microsoft tutorial](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-user-flow).
-If your GitLab domain is `gitlab.example.com`, ensure the app has the following `Redirect URI`:
+Configure the app:
-`https://gitlab.example.com/users/auth/openid_connect/callback`
+1. Set the app `Redirect URI`. For example, If your GitLab domain is `gitlab.example.com`,
+ set the app `Redirect URI` to `https://gitlab.example.com/users/auth/openid_connect/callback`.
-In addition, ensure that [ID tokens are enabled](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga#enable-id-token-implicit-grant).
+1. [Enable the ID tokens](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga#enable-id-token-implicit-grant).
-Add the following API permissions to the app:
+1. Add the following API permissions to the app:
-- `openid`
-- `offline_access`
+ - `openid`
+ - `offline_access`
#### Configure custom policies
-Azure B2C [offers two ways of defining the business logic for logging in a user](https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview):
+Azure B2C [offers two ways of defining the business logic for logging in a user](https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview):
-- [User flows](https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview#user-flows)
-- [Custom policies](https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview#custom-policies)
+- [User flows](https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview#user-flows)
+- [Custom policies](https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview#custom-policies)
-While cumbersome to configure, custom policies are required because
-standard Azure B2C user flows [do not send the OpenID `email` claim](https://github.com/MicrosoftDocs/azure-docs/issues/16566). In
-other words, they do not work with the [`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#configure-initial-settings).
+Custom policies are required because standard Azure B2C user flows
+[do not send the OpenID `email` claim](https://github.com/MicrosoftDocs/azure-docs/issues/16566).
+Therefore, the standard user flows do not work with the
+[`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#configure-initial-settings).
With a standard Azure B2C policy, GitLab cannot create a new account or
-link to an existing one with an email address.
+link to an existing account with an email address.
-Carefully follow the instructions for [creating a custom policy](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy).
+First, [create a custom policy](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy).
-The Microsoft instructions use `SocialAndLocalAccounts` in the [custom policy starter pack](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#custom-policy-starter-pack),
-but `LocalAccounts` works for authenticating against local, Active Directory accounts. Before you follow the instructions to [upload the polices](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#upload-the-policies), do the following:
+The Microsoft instructions use `SocialAndLocalAccounts` in the [custom policy starter pack](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#custom-policy-starter-pack),
+but `LocalAccounts` authenticates against local Active Directory accounts. Before you [upload the polices](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#upload-the-policies), do the following:
1. To export the `email` claim, modify the `SignUpOrSignin.xml`. Replace the following line:
@@ -250,9 +275,9 @@ but `LocalAccounts` works for authenticating against local, Active Directory acc
<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email" />
```
-1. For OIDC discovery to work with B2C, the policy must be configured with an issuer compatible with the
+1. For OIDC discovery to work with B2C, configure the policy with an issuer compatible with the
[OIDC specification](https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.4.3).
- See the [token compatibility settings](https://docs.microsoft.com/en-us/azure/active-directory-b2c/configure-tokens?pivots=b2c-custom-policy#token-compatibility-settings).
+ See the [token compatibility settings](https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-tokens?pivots=b2c-custom-policy#token-compatibility-settings).
In `TrustFrameworkBase.xml` under `JwtIssuer`, set `IssuanceClaimPattern` to `AuthorityWithTfp`:
```xml
@@ -268,22 +293,22 @@ but `LocalAccounts` works for authenticating against local, Active Directory acc
...
```
-1. Now [upload the policy](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#upload-the-policies). Overwrite
+1. [Upload the policy](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#upload-the-policies). Overwrite
the existing files if you are updating an existing policy.
-1. Determine the issuer URL using the sign-in policy. The issuer URL is in the form:
+1. To determine the issuer URL, use the sign-in policy. The issuer URL is in the form:
```markdown
https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/<YOUR-SIGN-IN-POLICY-NAME>/v2.0/
```
- The policy name is lowercased in the URL. For example, `B2C_1A_signup_signin`
+ The policy name is lowercase in the URL. For example, `B2C_1A_signup_signin`
policy appears as `b2c_1a_signup_sigin`.
-The trailing forward slash is required.
+ Ensure you include the trailing forward slash.
-1. Verify the operation of the OIDC discovery URL and issuer URL, append `.well-known/openid-configuration`
- to the issuer URL:
+1. Verify the operation of the OIDC discovery URL and issuer URL and append
+ `.well-known/openid-configuration` to the issuer URL:
```markdown
https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/<YOUR-SIGN-IN-POLICY-NAME>/v2.0/.well-known/openid-configuration
@@ -327,33 +352,35 @@ The trailing forward slash is required.
- Ensure all occurrences of `yourtenant.onmicrosoft.com`, `ProxyIdentityExperienceFrameworkAppId`, and `IdentityExperienceFrameworkAppId` match your B2C tenant hostname and
the respective client IDs in the XML policy files.
-- Add `https://jwt.ms` as a redirect URI to the app, and use the [custom policy tester](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#test-the-custom-policy).
- Make sure the payload includes `email` that matches the user's email access.
-- After you enable the custom policy, users might see "Invalid username or password" after they try to sign in. This might be a configuration
- issue with the `IdentityExperienceFramework` app. See [this Microsoft comment](https://docs.microsoft.com/en-us/answers/questions/50355/unable-to-sign-on-using-custom-policy.html?childToView=122370#comment-122370)
- that suggests checking that the app manifest contains these settings:
+- Add `https://jwt.ms` as a redirect URI to the app, and use the [custom policy tester](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#test-the-custom-policy).
+ Ensure the payload includes `email` that matches the user's email access.
+- After you enable the custom policy, users might see `Invalid username or password`
+ after they try to sign in. This might be a configuration issue with the `IdentityExperienceFramework`
+ app. See [this Microsoft comment](https://learn.microsoft.com/en-us/answers/questions/50355/unable-to-sign-on-using-custom-policy.html?childToView=122370#comment-122370) that suggests you check that the app manifest
+ contains these settings:
- `"accessTokenAcceptedVersion": null`
- `"signInAudience": "AzureADMyOrg"`
This configuration corresponds with the `Supported account types` setting used when
- creating the `IdentityExperienceFramework` app.
+creating the `IdentityExperienceFramework` app.
-### Keycloak
+### Configure Keycloak
-GitLab works with OpenID providers that use HTTPS. Although a Keycloak
-server can be set up using HTTP, GitLab can only communicate
-with a Keycloak server that uses HTTPS.
+GitLab works with OpenID providers that use HTTPS. Although you can set up a
+Keycloak server that uses HTTP, GitLab can only communicate with a Keycloak server
+that uses HTTPS.
-We highly recommend configuring Keycloak to use public key encryption algorithms (for example,
-RSA256, RSA512, and so on) instead of symmetric key encryption algorithms (for example, HS256 or HS358) to
-sign tokens. Public key encryption algorithms are:
+Configure Keycloak to use public key encryption algorithms (for example,
+RSA256 or RSA512) instead of symmetric key encryption algorithms (for example,
+HS256 or HS358) to sign tokens. Public key encryption algorithms are:
- Easier to configure.
- More secure because leaking the private key has severe security consequences.
-The signature algorithm can be configured in the Keycloak administration console under
-**Realm Settings > Tokens > Default Signature Algorithm**.
+1. Open the Keycloak administration console.
+1. Select **Realm Settings > Tokens > Default Signature Algorithm**.
+1. Configure the signature algorithm.
Example Omnibus configuration block:
@@ -385,38 +412,40 @@ gitlab_rails['omniauth_providers'] = [
> Introduced in GitLab 14.2.
WARNING:
-The instructions below are included for completeness, but symmetric key
-encryption should only be used when absolutely necessary.
+The following instructions are included for completeness, but only use symmetric key
+encryption if absolutely necessary.
To use symmetric key encryption:
-1. Extract the secret key from the Keycloak database. Keycloak doesn't expose this value in the Web
- interface. The client secret seen in the Web interface is the OAuth2 client secret, which is
- different from the secret used to sign JSON Web Tokens.
-
- For example, if you're using PostgreSQL as the backend database for Keycloak, log in to the
- database console and extract the key via this SQL query:
-
- ```sql
- $ psql -U keycloak
- psql (13.3 (Debian 13.3-1.pgdg100+1))
- Type "help" for help.
-
- keycloak=# SELECT c.name, value FROM component_config CC INNER JOIN component C ON(CC.component_id = C.id) WHERE C.realm_id = 'master' and provider_id = 'hmac-generated' AND CC.name = 'secret';
- -[ RECORD 1 ]---------------------------------------------------------------------------------
- name | hmac-generated
- value | lo6cqjD6Ika8pk7qc3fpFx9ysrhf7E62-sqGc8drp3XW-wr93zru8PFsQokHZZuJJbaUXvmiOftCZM3C4KW3-g
- -[ RECORD 2 ]---------------------------------------------------------------------------------
- name | fallback-HS384
- value | UfVqmIs--U61UYsRH-NYBH3_mlluLONpg_zN7CXEwkJcO9xdRNlzZfmfDLPtf2xSTMvqu08R2VhLr-8G-oZ47A
- ```
+1. Extract the secret key from the Keycloak database. Keycloak does not expose this
+ value in the web interface. The client secret seen in the web interface is the
+ OAuth 2.0 client secret, which is different from the secret used to sign JSON Web Tokens.
- In this example, there are two private keys: one for HS256 (`hmac-generated`), and another for
- HS384 (`fallback-HS384`). We use the first `value` to configure GitLab.
+ For example, if you use PostgreSQL as the backend database for Keycloak:
-1. Convert `value` to standard base64. As [discussed in the post](https://keycloak.discourse.group/t/invalid-signature-with-hs256-token/3228/9),
- `value` is encoded in ["Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5).
- This needs to be converted to [standard base64 as defined in RFC 2045](https://datatracker.ietf.org/doc/html/rfc2045).
+ - Sign into the database console.
+ - Run the following SQL query to extract the key:
+
+ ```sql
+ $ psql -U keycloak
+ psql (13.3 (Debian 13.3-1.pgdg100+1))
+ Type "help" for help.
+
+ keycloak=# SELECT c.name, value FROM component_config CC INNER JOIN component C ON(CC.component_id = C.id) WHERE C.realm_id = 'master' and provider_id = 'hmac-generated' AND CC.name = 'secret';
+ -[ RECORD 1 ]---------------------------------------------------------------------------------
+ name | hmac-generated
+ value | lo6cqjD6Ika8pk7qc3fpFx9ysrhf7E62-sqGc8drp3XW-wr93zru8PFsQokHZZuJJbaUXvmiOftCZM3C4KW3-g
+ -[ RECORD 2 ]---------------------------------------------------------------------------------
+ name | fallback-HS384
+ value | UfVqmIs--U61UYsRH-NYBH3_mlluLONpg_zN7CXEwkJcO9xdRNlzZfmfDLPtf2xSTMvqu08R2VhLr-8G-oZ47A
+ ```
+
+ In this example, there are two private keys: one for HS256 (`hmac-generated`)
+ and another for HS384 (`fallback-HS384`). We use the first `value` to configure GitLab.
+
+1. Convert `value` to standard base64. As discussed in the [**Invalid signature with HS256 token** post](https://keycloak.discourse.group/t/invalid-signature-with-hs256-token/3228/9),
+ `value` is encoded in the [**Base 64 Encoding with URL and Filename Safe Alphabet** section](https://datatracker.ietf.org/doc/html/rfc4648#section-5) of RFC 4648.
+ This must be converted to [standard base64 as defined in RFC 2045](https://datatracker.ietf.org/doc/html/rfc2045).
The following Ruby script does this:
```ruby
@@ -458,17 +487,19 @@ To use symmetric key encryption:
]
```
-If after reconfiguring, you see the error `JSON::JWS::VerificationFailed` error message, this means
-the incorrect secret was specified.
+If you see a `JSON::JWS::VerificationFailed` error,
+you have specified the wrong secret.
### Casdoor
-GitLab works with OpenID providers that use HTTPS. To connect to GitLab using OpenID with Casdoor, use HTTPS instead of HTTP.
+GitLab works with OpenID providers that use HTTPS. Use HTTPS to connect to GitLab
+through OpenID with Casdoor.
For your app, complete the following steps on Casdoor:
1. Get a client ID and a client secret.
-1. Add your GitLab redirect URL. For example, if your GitLab domain is `gitlab.example.com`, ensure the Casdoor app has the following
+1. Add your GitLab redirect URL. For example, if your GitLab domain is `gitlab.example.com`,
+ ensure the Casdoor app has the following
`Redirect URI`: `https://gitlab.example.com/users/auth/openid_connect/callback`.
See the [Casdoor documentation](https://casdoor.org/docs/integration/gitlab) for more details.
@@ -520,23 +551,21 @@ Example installations from source configuration (file path: `config/gitlab.yml`)
}
```
-## General troubleshooting
-
-If you're having trouble, here are some tips:
+## Troubleshooting
-1. Ensure `discovery` is set to `true`. Setting it to `false` requires
- specifying all the URLs and keys required to make OpenID work.
+1. Ensure `discovery` is set to `true`. If you set it to `false`, you must
+ specify all the URLs and keys required to make OpenID work.
1. Check your system clock to ensure the time is synchronized properly.
-1. As mentioned in [the documentation](https://github.com/m0n9oose/omniauth_openid_connect),
+1. As mentioned in [the OmniAuth OpenID Connect documentation](https://github.com/m0n9oose/omniauth_openid_connect),
make sure `issuer` corresponds to the base URL of the Discovery URL. For
example, `https://accounts.google.com` is used for the URL
`https://accounts.google.com/.well-known/openid-configuration`.
1. The OpenID Connect client uses HTTP Basic Authentication to send the
- OAuth2 access token if `client_auth_method` is not defined or if set to `basic`.
- If you are seeing 401 errors upon retrieving the `userinfo` endpoint, you may
- want to check your OpenID Web server configuration. For example, for
- [`oauth2-server-php`](https://github.com/bshaffer/oauth2-server-php), you
- may need to [add a configuration parameter to Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
+ OAuth 2.0 access token if `client_auth_method` is not defined or if set to `basic`.
+ If you see 401 errors when retrieving the `userinfo` endpoint, check
+ your OpenID web server configuration. For example, for
+ [`oauth2-server-php`](https://github.com/bshaffer/oauth2-server-php), you may have to
+ [add a configuration parameter to Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
index 0590410bf31..11117e8a74c 100644
--- a/doc/administration/auth/smartcard.md
+++ b/doc/administration/auth/smartcard.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -13,7 +13,7 @@ GitLab supports authentication using smartcards.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33669) in GitLab 12.6.
-By default, existing users can continue to log in with a username and password when smartcard
+By default, existing users can continue to sign in with a username and password when smartcard
authentication is enabled.
To force existing users to use only smartcard authentication,
@@ -101,7 +101,7 @@ Certificate:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7693) in GitLab 11.8 as an experimental feature. Smartcard authentication against an LDAP server may change or be removed completely in the future.
GitLab implements a standard way of certificate matching following
-[RFC4523](https://tools.ietf.org/html/rfc4523). It uses the
+[RFC4523](https://www.rfc-editor.org/rfc/rfc4523). It uses the
`certificateExactMatch` certificate matching rule against the `userCertificate`
attribute. As a prerequisite, you must use an LDAP server that:
diff --git a/doc/administration/cicd.md b/doc/administration/cicd.md
index 5e061320c5b..6899b572e8f 100644
--- a/doc/administration/cicd.md
+++ b/doc/administration/cicd.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -69,7 +69,8 @@ can choose a custom limit. For example, to set the limit to `100`:
Plan.default.actual_limits.update!(ci_needs_size_limit: 100)
```
-To disable directed acyclic graphs (DAG), set the limit to `0`.
+To disable directed acyclic graphs (DAG), set the limit to `0`. Pipelines with jobs
+configured to use `needs` then return the error `job can only need 0 others`.
## Change maximum scheduled pipeline frequency
diff --git a/doc/administration/clusters/kas.md b/doc/administration/clusters/kas.md
index 82bb1a35e02..d7e1c9af1de 100644
--- a/doc/administration/clusters/kas.md
+++ b/doc/administration/clusters/kas.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install the GitLab agent server for Kubernetes (KAS) **(FREE SELF)**
@@ -28,9 +28,13 @@ Or, you can [use an external agent server](#use-an-external-installation).
### For Omnibus
-For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
+You can enable the agent server for [Omnibus](https://docs.gitlab.com/omnibus/) package installations on a single node, or on multiple nodes at once.
-1. To enable the agent server, edit `/etc/gitlab/gitlab.rb`:
+#### Enable on a single node
+
+To enable the agent server on a single node:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_kas['enable'] = true
@@ -41,6 +45,33 @@ For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
For additional configuration options, see the **Enable GitLab KAS** section of the
[`gitlab.rb.template`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-config-template/gitlab.rb.template).
+#### Enable on multiple nodes
+
+To enable the agent server on multiple nodes:
+
+1. For each agent server node, edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_kas['enable'] = true
+ gitlab_kas['api_secret_key'] = '<32_bytes_long_base64_encoded_value>'
+ gitlab_kas['private_api_secret_key'] = '<32_bytes_long_base64_encoded_value>'
+ gitlab_kas['private_api_listen_address'] = '0.0.0.0:8155'
+ gitlab_kas['env'] = {
+ 'SSL_CERT_DIR' => "/opt/gitlab/embedded/ssl/certs/",
+ 'OWN_PRIVATE_API_URL' => 'grpc://<ip_or_hostname_of_this_host>:8155'
+ }
+ ```
+
+ In this configuration:
+
+ - `gitlab_kas['private_api_listen_address']` is the address the agent server listens on. You can set it to `0.0.0.0` or an IP address reachable by other nodes in the cluster.
+ - `OWN_PRIVATE_API_URL` is the environment variable used by the KAS process for service discovery. You can set it to a hostname or IP address of the node you're configuring. The node must be reachable by other nodes in the cluster.
+ - `gitlab_kas['api_secret_key']` is the shared secret used for authentication between KAS and GitLab. This value must be Base64-encoded and exactly 32 bytes long.
+ - `gitlab_kas['private_api_secret_key']` is the shared secret used for authentication between different KAS instances. This value must be Base64-encoded and exactly 32 bytes long.
+
+1. For each application node, follow the steps in: [Use an external installation](../clusters/kas.md#use-an-external-installation).
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
### For GitLab Helm Chart
For GitLab [Helm Chart](https://docs.gitlab.com/charts/) installations:
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 573ffbf4686..ad345461776 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Compliance features **(FREE)**
@@ -48,9 +48,9 @@ settings and automation to ensure that whatever a compliance team has configured
stays configured and working correctly. These features can help you automate
compliance:
-- [**Compliance frameworks**](../user/project/settings/index.md#compliance-frameworks) (for groups): Create a custom
+- [**Compliance frameworks**](../user/group/manage.md#compliance-frameworks) (for groups): Create a custom
compliance framework at the group level to describe the type of compliance requirements any child project needs to follow.
-- [**Compliance pipelines**](../user/project/settings/index.md#compliance-pipeline-configuration) (for groups): Define a
+- [**Compliance pipelines**](../user/group/manage.md#configure-a-compliance-pipeline) (for groups): Define a
pipeline configuration to run for any projects with a given compliance framework.
## Audit management
diff --git a/doc/administration/configure.md b/doc/administration/configure.md
index 4335c6d972f..40f03d25e8d 100644
--- a/doc/administration/configure.md
+++ b/doc/administration/configure.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/consul.md b/doc/administration/consul.md
index e282960c857..a6f76882c4d 100644
--- a/doc/administration/consul.md
+++ b/doc/administration/consul.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/docs_self_host.md b/doc/administration/docs_self_host.md
index 3f5d4adc95c..9021a795523 100644
--- a/doc/administration/docs_self_host.md
+++ b/doc/administration/docs_self_host.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Host the GitLab product documentation **(FREE SELF)**
@@ -261,7 +261,7 @@ To upgrade to a later version [using your own web-server](#self-host-the-product
If you self-host the product documentation:
-- The version dropdown displays additional versions that don't exist. Selecting
+- The version dropdown list displays additional versions that don't exist. Selecting
these versions displays a `404 Not Found` page.
- The search displays results from `docs.gitlab.com` and not the local site.
- By default, the landing page redirects to the
diff --git a/doc/administration/encrypted_configuration.md b/doc/administration/encrypted_configuration.md
index a96a4c4405d..648f6d7018e 100644
--- a/doc/administration/encrypted_configuration.md
+++ b/doc/administration/encrypted_configuration.md
@@ -1,7 +1,7 @@
---
stage: Systems
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
@@ -17,17 +17,17 @@ GitLab can read settings for certain features from encrypted settings files. The
To enable the encrypted configuration settings, a new base key must be generated for
`encrypted_settings_key_base`. The secret can be generated in the following ways:
-**Omnibus Installation**
+**Omnibus**
Starting with 13.7 the new secret is automatically generated for you, but you must ensure your
`/etc/gitlab/gitlab-secrets.json` contains the same values on all nodes.
-**GitLab Cloud Native Helm Chart**
+**Helm chart**
Starting with GitLab 13.7, the new secret is automatically generated if you have the `shared-secrets` chart enabled. Otherwise, you need
to follow the [secrets guide for adding the secret](https://docs.gitlab.com/charts/installation/secrets.html#gitlab-rails-secret).
-**Source Installation**
+**Source**
The new secret can be generated by running:
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index e70758e2774..beaef7afe57 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index b9bf0cfdc50..e6f825f7cb8 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 75e65c2a9d6..4f8f7c22a55 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "GitLab administrator: enable and disable GitLab features deployed behind feature flags"
---
@@ -27,8 +27,9 @@ Features behind flags can be gradually rolled out, typically:
1. The feature flag is removed.
These features can be enabled and disabled to allow or prevent users from using
-them. It can be done by GitLab administrators with access to GitLab Rails
-console.
+them. It can be done by GitLab administrators with access to the
+[Rails console](#how-to-enable-and-disable-features-behind-flags) or the
+[Feature flags API](../api/features.md).
When you disable a feature flag, the feature is hidden from users and all of the functionality is turned off.
For example, data is not recorded and services do not run.
diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md
index ed5dbd83a8e..8fafb258593 100644
--- a/doc/administration/file_hooks.md
+++ b/doc/administration/file_hooks.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/administration/geo/disaster_recovery/background_verification.md b/doc/administration/geo/disaster_recovery/background_verification.md
index d3aa2c97833..699fe6851eb 100644
--- a/doc/administration/geo/disaster_recovery/background_verification.md
+++ b/doc/administration/geo/disaster_recovery/background_verification.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Automatic background verification **(PREMIUM SELF)**
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index 1991b747af0..dda2c5d34d3 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index e82c130ba01..156a87614e6 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Disaster Recovery (Geo) **(PREMIUM SELF)**
@@ -10,8 +10,6 @@ Geo replicates your database, your Git repositories, and few other assets,
but there are some [limitations](../index.md#limitations).
WARNING:
-Disaster recovery for multi-secondary configurations is in [**Alpha**](../../../policy/alpha-beta-support.md#alpha-features).
-For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/3574).
Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and
causes downtime.
@@ -342,7 +340,7 @@ with the **secondary** site:
1. Promote the replica database associated with the **secondary** site. This
sets the database to read-write. The instructions vary depending on where your database is hosted:
- [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
- - [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal#stop-replication)
+ - [Azure PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal#stop-replication)
- [Google Cloud SQL](https://cloud.google.com/sql/docs/mysql/replication/manage-replicas#promote-replica)
- For other external PostgreSQL databases, save the following script in your
secondary site, for example `/tmp/geo_promote.sh`, and modify the connection
@@ -413,7 +411,7 @@ required:
1. Promote the replica database associated with the **secondary** site. This
sets the database to read-write. The instructions vary depending on where your database is hosted:
- [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
- - [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal#stop-replication)
+ - [Azure PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal#stop-replication)
- [Google Cloud SQL](https://cloud.google.com/sql/docs/mysql/replication/manage-replicas#promote-replica)
- For other external PostgreSQL databases, save the following script in your
secondary site, for example `/tmp/geo_promote.sh`, and modify the connection
@@ -617,9 +615,9 @@ Now we need to make each **secondary** site listen to changes on the new **prima
to [initiate the replication process](../setup/database.md#step-3-initiate-the-replication-process) again but this time
for another **primary** site. All the old replication settings are overwritten.
-## Promoting a secondary Geo cluster in GitLab Cloud Native Helm Charts
+## Promoting a secondary Geo cluster in the GitLab Helm chart
-When updating a Cloud Native Geo deployment, the process for updating any node that is external to the secondary Kubernetes cluster does not differ from the non Cloud Native approach. As such, you can always defer to [Promoting a secondary Geo site in single-secondary configurations](#promoting-a-secondary-geo-site-in-single-secondary-configurations) for more information.
+When updating a cloud-native Geo deployment, the process for updating any node that is external to the secondary Kubernetes cluster does not differ from the non cloud-native approach. As such, you can always defer to [Promoting a secondary Geo site in single-secondary configurations](#promoting-a-secondary-geo-site-in-single-secondary-configurations) for more information.
The following sections assume you are using the `gitlab` namespace. If you used a different namespace when setting up your cluster, you should also replace `--namespace gitlab` with your namespace.
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index d0dbecce43a..60101f5af8e 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -233,7 +233,7 @@ At this point, your **secondary** site contains an up-to-date copy of everything
## Promote the **secondary** site
-After the replication is finished, [promote the **secondary** site to a **primary** site](index.md). This process causes a brief outage on the **secondary** site, and users may need to log in again. If you follow the steps correctly, the old primary Geo site should still be disabled and user traffic should go to the newly-promoted site instead.
+After the replication is finished, [promote the **secondary** site to a **primary** site](index.md). This process causes a brief outage on the **secondary** site, and users may need to sign in again. If you follow the steps correctly, the old primary Geo site should still be disabled and user traffic should go to the newly-promoted site instead.
When the promotion is completed, the maintenance window is over, and your new **primary** site now
begins to diverge from the old one. If problems do arise at this point, failing
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 11baf383c67..8c18aaa944d 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
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -121,7 +121,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.
+ **primary** site. They are also unable to sign in to the **secondary** site.
However, existing sessions must work for the remainder of the maintenance period, and
so public data is accessible throughout.
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 2958c119c20..f9d99095951 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
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -106,7 +106,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.
+ **primary** site. They are also unable to sign in to the **secondary** site.
However, existing sessions need to work for the remainder of the maintenance period, and
so public data is accessible throughout.
diff --git a/doc/administration/geo/glossary.md b/doc/administration/geo/glossary.md
index c9d4ccacae3..9abd7ea9347 100644
--- a/doc/administration/geo/glossary.md
+++ b/doc/administration/geo/glossary.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index db298d4fdfc..a336f5ff8bc 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo **(PREMIUM SELF)**
@@ -206,6 +206,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories and files are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases.
- [Pages access control](../../user/project/pages/pages_access_control.md) doesn't work on secondaries. See [GitLab issue #9336](https://gitlab.com/gitlab-org/gitlab/-/issues/9336) for details.
- [GitLab chart with Geo](https://docs.gitlab.com/charts/advanced/geo/) does not support [Unified URLs](secondary_proxy/index.md#set-up-a-unified-url-for-geo-sites). See [GitLab issue #3522](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3522) for more details.
+- [Disaster recovery](disaster_recovery/index.md) for multi-secondary sites causes downtime due to the complete re-synchronization and re-configuration of all non-promoted secondaries.
### Limitations on replication/verification
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 39d1f5ae602..fa74f16cdc8 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/container_registry.md b/doc/administration/geo/replication/container_registry.md
index 01ba81b6dbe..abf34efa56e 100644
--- a/doc/administration/geo/replication/container_registry.md
+++ b/doc/administration/geo/replication/container_registry.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index 40b71684bac..566df2ee509 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -59,6 +59,10 @@ verification methods:
| Blobs | Pages _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | CI Secure Files _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | CI Secure Files _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Incident Metric Images _(file system)_ | Geo with API/Managed | SHA256 checksum |
+| Blobs | Incident Metric Images _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Alert Metric Images _(file system)_ | Geo with API | SHA256 checksum |
+| Blobs | Alert Metric Images _(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.
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
@@ -197,7 +201,8 @@ successfully, you must replicate their data using some other means.
|[CI job artifacts](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
|[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) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Persists additional artifacts after a pipeline completes. |
|[CI Secure Files](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/secure_file.rb) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_ci_secure_file_replication`, enabled by default in 15.3. |
-|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | No | Disabled by default. See [instructions](container_registry.md) to enable. |
+|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3)* | No | No | No | Replication is behind feature flag `geo_container_repository_replication`, enabled by default.
+Requires additional configuration. See [instructions](container_registry.md) to set up the Container Registry replication. |
|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | 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) | N/A | N/A | Designs also require replication of LFS objects and Uploads. |
|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
@@ -206,9 +211,11 @@ successfully, you must replicate their data using some other means.
|[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) | N/A | N/A | 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** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
|[Project-level Secure files](../../../ci/secure_files/index.md) | **Yes** (15.3) | **Yes** (15.3) | **Yes** (15.3) | [No](object_storage.md#verification-of-files-in-object-storage) | |
-|[Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | No | |
-|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/362564) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362564) | No | No | |
+| [Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | **Yes** (15.5) | **Yes**(15.5) | **Yes** (15.5) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication/Verification is handled via the Uploads data type. | |
+|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | **Yes** (15.5) | **Yes** (15.5) | **Yes** (15.5) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication/Verification is handled via the Uploads data type. |
|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | N/A | N/A | 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 | 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 | 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. |
+|[Elasticsearch integration](../../../integration/advanced_search/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | 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) | [Planned](https://gitlab.com/groups/gitlab-org/-/epics/8833) | No | 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/index.md#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | No | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
+
+\* Migrated to [self-service framework](../../../development/geo/framework.md) in 15.5. See GitLab issue [#337436](https://gitlab.com/gitlab-org/gitlab/-/issues/337436) for more details.
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index 84bc2e034b9..3230a92136f 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -63,7 +63,7 @@ Geo node in a PostgreSQL console (`sudo gitlab-psql`):
## Remove Geo-related configuration
-1. For each node on your primary Geo site, SSH into the node and log in as root:
+1. For each node on your primary Geo site, SSH into the node and sign in as root:
```shell
sudo -i
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index 7a67af1cfa2..81afcc19bb1 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo Frequently Asked Questions **(PREMIUM SELF)**
@@ -69,6 +69,6 @@ That's totally fine. We use HTTP(s) to fetch repository changes from the **prima
Yes. See [Container Registry for a **secondary** site](container_registry.md).
-## Can you log in to a secondary site?
+## Can you sign in to a secondary site?
Yes, but secondary sites receive all authentication data (like user accounts and logins) from the primary instance. This means you are re-directed to the primary for authentication and then routed back.
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index 7b59cdda1aa..8fa5a45b579 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo validation tests **(PREMIUM SELF)**
diff --git a/doc/administration/geo/replication/location_aware_git_url.md b/doc/administration/geo/replication/location_aware_git_url.md
index 18103211580..e0e113eebbd 100644
--- a/doc/administration/geo/replication/location_aware_git_url.md
+++ b/doc/administration/geo/replication/location_aware_git_url.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/multiple_servers.md b/doc/administration/geo/replication/multiple_servers.md
index afa4f4eb552..5be7d40890c 100644
--- a/doc/administration/geo/replication/multiple_servers.md
+++ b/doc/administration/geo/replication/multiple_servers.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -53,7 +53,7 @@ you already have a working GitLab instance that is in-use, it can be used as a
The second GitLab site serves as the Geo **secondary** site. Again, use the
[GitLab reference architectures documentation](../../reference_architectures/index.md) to set this up.
-It's a good idea to log in and test it. However, be aware that its data is
+It's a good idea to sign in and test it. However, be aware that its data is
wiped out as part of the process of replicating from the **primary** site.
## Configure a GitLab site to be the Geo **primary** site
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index 0336a1669f9..8128eaf5310 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/remove_geo_site.md b/doc/administration/geo/replication/remove_geo_site.md
index b136f6cc8b8..62b1d9fdf7b 100644
--- a/doc/administration/geo/replication/remove_geo_site.md
+++ b/doc/administration/geo/replication/remove_geo_site.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
index bc08b7b71e7..0231da53b9c 100644
--- a/doc/administration/geo/replication/security_review.md
+++ b/doc/administration/geo/replication/security_review.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index d64ad2549e8..3f16c1552ad 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Geo **(PREMIUM SELF)**
@@ -311,6 +311,51 @@ sudo gitlab-rake gitlab:geo:check
When performing a PostgreSQL major version (9 > 10) update this is expected. Follow
the [initiate-the-replication-process](../setup/database.md#step-3-initiate-the-replication-process).
+### Repository verification failures
+
+[Start a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session)
+to gather the following, basic troubleshooting information.
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+#### Get the number of verification failed repositories
+
+```ruby
+Geo::ProjectRegistry.verification_failed('repository').count
+```
+
+#### Find the verification failed repositories
+
+```ruby
+Geo::ProjectRegistry.verification_failed('repository')
+```
+
+#### Find repositories that failed to sync
+
+```ruby
+Geo::ProjectRegistry.sync_failed('repository')
+```
+
+### Resync repositories
+
+[Start a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session)
+to enact the following, basic troubleshooting steps.
+
+#### Queue up all repositories for resync. Sidekiq handles each sync
+
+```ruby
+Geo::ProjectRegistry.update_all(resync_repository: true, resync_wiki: true)
+```
+
+#### Sync individual repository now
+
+```ruby
+project = Project.find_by_full_path('<group/project>')
+
+Geo::RepositorySyncService.new(project).execute
+```
+
## Fixing replication errors
The following sections outline troubleshooting steps for fixing replication
@@ -779,7 +824,7 @@ This behavior affects only the following data types through GitLab 14.6:
| Data type | From version |
| ------------------------ | ------------ |
| Package Registry | 13.10 |
-| Pipeline Artifacts | 13.11 |
+| CI Pipeline Artifacts | 13.11 |
| Terraform State Versions | 13.12 |
| Infrastructure Registry | 14.0 |
| External MR diffs | 14.6 |
@@ -792,6 +837,120 @@ This behavior affects only the following data types through GitLab 14.6:
to make Geo visibly surface data loss risks. The sync/verification loop is
therefore short-circuited. `last_sync_failure` is now set to `The file is missing on the Geo primary site`.
+### Blob types
+
+- `Ci::JobArtifact`
+- `Ci::PipelineArtifact`
+- `Ci::SecureFile`
+- `LfsObject`
+- `MergeRequestDiff`
+- `Packages::PackageFile`
+- `PagesDeployment`
+- `Terraform::StateVersion`
+- `Upload`
+
+`Packages::PackageFile` is used in the following
+[Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session)
+examples, but things generally work the same for the other types.
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+#### The Replicator
+
+The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it):
+
+```ruby
+model_record = Packages::PackageFile.last
+model_record.replicator.registry.replicator.model_record # just showing that these methods exist
+```
+
+#### Replicate a package file, synchronously, given an ID
+
+```ruby
+model_record = Packages::PackageFile.find(id)
+model_record.replicator.send(:download)
+```
+
+#### Replicate a package file, synchronously, given a registry ID
+
+```ruby
+registry = Geo::PackageFileRegistry.find(registry_id)
+registry.replicator.send(:download)
+```
+
+#### Verify package files on the secondary manually
+
+This iterates over all package files on the secondary, looking at the
+`verification_checksum` stored in the database (which came from the primary)
+and then calculate this value on the secondary to check if they match. This
+does not change anything in the UI:
+
+```ruby
+# Run on secondary
+status = {}
+
+Packages::PackageFile.find_each do |package_file|
+ primary_checksum = package_file.verification_checksum
+ secondary_checksum = Packages::PackageFile.hexdigest(package_file.file.path)
+ verification_status = (primary_checksum == secondary_checksum)
+
+ status[verification_status.to_s] ||= []
+ status[verification_status.to_s] << package_file.id
+end
+
+# Count how many of each value we get
+status.keys.each {|key| puts "#{key} count: #{status[key].count}"}
+
+# See the output in its entirety
+status
+```
+
+### Repository types newer than project/wiki repositories
+
+- `SnippetRepository`
+- `GroupWikiRepository`
+
+`SnippetRepository` is used in the examples below, but things generally work the same for the other Repository types.
+
+#### The Replicator
+
+The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it).
+
+```ruby
+model_record = SnippetRepository.last
+model_record.replicator.registry.replicator.model_record # just showing that these methods exist
+```
+
+#### Replicate a snippet repository, synchronously, given an ID
+
+```ruby
+model_record = SnippetRepository.find(id)
+model_record.replicator.send(:sync_repository)
+```
+
+#### Replicate a snippet repository, synchronously, given a registry ID
+
+```ruby
+registry = Geo::SnippetRepositoryRegistry.find(registry_id)
+registry.replicator.send(:sync_repository)
+```
+
+### Find failed artifacts
+
+[Start a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session)
+to run the following commands:
+
+```ruby
+Geo::JobArtifactRegistry.failed
+```
+
+#### Find `ID` of synced artifacts that are missing on primary
+
+```ruby
+Geo::JobArtifactRegistry.synced.missing_on_primary.pluck(:artifact_id)
+```
+
#### Failed syncs with GitLab-managed object storage replication
There is [an issue in GitLab 14.2 through 14.7](https://gitlab.com/gitlab-org/gitlab/-/issues/299819#note_822629467)
diff --git a/doc/administration/geo/replication/tuning.md b/doc/administration/geo/replication/tuning.md
index 370c50c93db..ab9263ad344 100644
--- a/doc/administration/geo/replication/tuning.md
+++ b/doc/administration/geo/replication/tuning.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/upgrading_the_geo_sites.md b/doc/administration/geo/replication/upgrading_the_geo_sites.md
index ce1ff4fe6a5..55395a55857 100644
--- a/doc/administration/geo/replication/upgrading_the_geo_sites.md
+++ b/doc/administration/geo/replication/upgrading_the_geo_sites.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/replication/usage.md b/doc/administration/geo/replication/usage.md
index fe0e06e7ea4..cfaa02e1a17 100644
--- a/doc/administration/geo/replication/usage.md
+++ b/doc/administration/geo/replication/usage.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
<!-- Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved) -->
diff --git a/doc/administration/geo/replication/version_specific_upgrades.md b/doc/administration/geo/replication/version_specific_upgrades.md
index 6211b5689b1..9aad5cdeaa7 100644
--- a/doc/administration/geo/replication/version_specific_upgrades.md
+++ b/doc/administration/geo/replication/version_specific_upgrades.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Version-specific upgrade instructions **(PREMIUM SELF)**
@@ -10,6 +10,12 @@ Review this page for upgrade instructions for your version. These steps
accompany the [general steps](upgrading_the_geo_sites.md#general-upgrade-steps)
for upgrading Geo sites.
+## Upgrading to 15.1
+
+[Geo proxying](../secondary_proxy/index.md) was [enabled by default for different URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/346112) in 15.1. This may be a breaking change. If needed, you may [disable Geo proxying](../secondary_proxy/index.md#disable-geo-proxying).
+
+If you are using SAML with different URLs, there is a [known issue which requires proxying to be disabled](https://gitlab.com/gitlab-org/gitlab/-/issues/377372).
+
## Upgrading to 14.9
**Do not** upgrade to GitLab 14.9.0. Instead, use 14.9.1 or later.
@@ -33,6 +39,10 @@ results in a loop that consistently fails for all objects stored in object stora
For information on how to fix this, see
[Troubleshooting - Failed syncs with GitLab-managed object storage replication](troubleshooting.md#failed-syncs-with-gitlab-managed-object-storage-replication).
+## Upgrading to 14.6
+
+[Geo proxying](../secondary_proxy/index.md) was [enabled by default for unified URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/325732) in 14.6. This may be a breaking change. If needed, you may [disable Geo proxying](../secondary_proxy/index.md#disable-geo-proxying).
+
## Upgrading 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.
@@ -80,9 +90,9 @@ GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab
## Upgrading to GitLab 14.0/14.1
-### Primary sites can not be removed from the UI
+### Primary sites cannot be removed from the UI
-We found an issue where [Primary sites can not be removed from the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/338231).
+We found an issue where [Primary sites cannot be removed from the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/338231).
This bug only exists in the UI and does not block the removal of Primary sites using any other method.
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index 731b5012663..2786982bb51 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -147,6 +147,13 @@ for details.
- [Viewing projects and designs data from a primary site is not possible when using a unified URL](../index.md#view-replication-data-on-the-primary-site).
+- When secondary proxying is used together with separate URLs, registering [GitLab runners](https://docs.gitlab.com/runner/) to clone from
+secondary sites is not supported. The runner registration will succeed, but the clone URL will default to the primary site. The runner
+[clone URL](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) is configured per GitLab deployment
+and cannot be configured per Geo site. Therefore, all runners will clone from the primary site (or configured clone URL) irrespective of
+which Geo site they register on. For information about GitLab CI using a specific Geo secondary to clone from, see issue
+[3294](https://gitlab.com/gitlab-org/gitlab/-/issues/3294#note_1009488466).
+
## Behavior of secondary sites when the primary Geo site is down
Considering that web traffic is proxied to the primary, the behavior of the secondary sites differs when the primary
diff --git a/doc/administration/geo/secondary_proxy/location_aware_external_url.md b/doc/administration/geo/secondary_proxy/location_aware_external_url.md
index 1430e99557f..b983230a314 100644
--- a/doc/administration/geo/secondary_proxy/location_aware_external_url.md
+++ b/doc/administration/geo/secondary_proxy/location_aware_external_url.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 8a919a0a269..8ea8d6c4d8e 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/geo/setup/external_database.md b/doc/administration/geo/setup/external_database.md
index b87baa658a1..eabed7c10f3 100644
--- a/doc/administration/geo/setup/external_database.md
+++ b/doc/administration/geo/setup/external_database.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo with external PostgreSQL instances **(PREMIUM SELF)**
@@ -69,14 +69,13 @@ To set up an external database, you can either:
Given you have a primary site set up on AWS EC2 that uses RDS.
You can now just create a read-only replica in a different region and the
-replication process is managed by AWS. Make sure you've set Network ACL (Access Control List), Subnet, and
-Security Group according to your needs, so the secondary Rails node(s) can access the database.
+replication process is managed by AWS. Make sure you've set Network ACL (Access Control List), Subnet, and Security Group according to your needs, so the secondary Rails nodes can access the database.
The following instructions detail how to create a read-only replica for common
cloud providers:
- Amazon RDS - [Creating a Read Replica](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create)
-- Azure Database for PostgreSQL - [Create and manage read replicas in Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal)
+- Azure Database for PostgreSQL - [Create and manage read replicas in Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/single-server/how-to-read-replicas-portal)
- Google Cloud SQL - [Creating read replicas](https://cloud.google.com/sql/docs/postgres/replication/create-replica)
Once your read-only replica is set up, you can skip to [configure your secondary site](#configure-secondary-site-to-use-the-external-read-replica)
@@ -195,7 +194,7 @@ to grant additional roles to your tracking database user (by default, this is
`gitlab_geo`):
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
-- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/single-server/how-to-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
+- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://learn.microsoft.com/en-us/azure/postgresql/single-server/how-to-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
- Google Cloud SQL requires the [`cloudsqlsuperuser`](https://cloud.google.com/sql/docs/postgres/users#default-users) role.
This is for the installation of extensions during installation and upgrades. As an alternative,
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
index 79b52ef71da..c794b8ef219 100644
--- a/doc/administration/geo/setup/index.md
+++ b/doc/administration/geo/setup/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -16,14 +16,14 @@ You must use a [GitLab Premium](https://about.gitlab.com/pricing/) license or hi
but you only need one license for all the sites.
WARNING:
-The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all sites. Do not create an account or log in to the new secondary.**
+The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all sites. Do not create an account or sign in to the new secondary.**
## Using Omnibus GitLab
If you installed GitLab using the Omnibus packages (highly recommended):
1. Confirm the [requirements for running Geo](../index.md#requirements-for-running-geo) are met.
-1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the nodes that serve as the **secondary** site. **Do not create an account or log in** to the new **secondary** site. The **GitLab version must match** across primary and secondary sites.
+1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the nodes that serve as the **secondary** site. **Do not create an account or sign in** to the new **secondary** site. The **GitLab version must match** across primary and secondary sites.
1. [Add the GitLab License](../../../user/admin_area/license.md) on the **primary** site to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
1. [Confirm network connectivity](../index.md#firewall-rules) between the **primary** and **secondary** site.
1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md
index 44b09ef185a..4099ddc16f8 100644
--- a/doc/administration/get_started.md
+++ b/doc/administration/get_started.md
@@ -1,5 +1,5 @@
---
-info: For assistance with this TAM Onboarding page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this TAM Onboarding page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
stage: none
group: unassigned
---
@@ -283,7 +283,7 @@ You can learn more about how to administer GitLab.
### Free GitLab training
-- GitLab basics: Discover self-service guides on [Git and GitLab basics](../gitlab-basics/index.md).
+- GitLab basics: Discover self-service guides on [Git and GitLab basics](../tutorials/index.md).
- GitLab Learn: Learn new GitLab skills in a structured course at [GitLab Learn](https://about.gitlab.com/learn/).
### Third-party training
diff --git a/doc/administration/git_protocol.md b/doc/administration/git_protocol.md
index 3612487f456..f900c5a6867 100644
--- a/doc/administration/git_protocol.md
+++ b/doc/administration/git_protocol.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Set and configure Git protocol v2"
---
@@ -15,7 +15,7 @@ configuration is required by an administrator.
More details about the new features and improvements are available in
the [Google Open Source Blog](https://opensource.googleblog.com/2018/05/introducing-git-protocol-version-2.html)
-and the [protocol documentation](https://github.com/git/git/blob/master/Documentation/technical/protocol-v2.txt).
+and the [protocol documentation](https://github.com/git/git/blob/master/Documentation/gitprotocol-v2.txt).
## Requirements
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index bfd252a9f42..e4aef2db9a8 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure Gitaly **(FREE SELF)**
@@ -555,12 +555,15 @@ Additionally, the certificate (or its certificate authority) must be installed o
- Gitaly servers.
- Gitaly clients that communicate with it.
-Note the following:
+### Certificate requirements
- The certificate must specify the address you use to access the Gitaly server. You must add the hostname or IP address as a Subject Alternative Name to the certificate.
- You can configure Gitaly servers with both an unencrypted listening address `listen_addr` and an
encrypted listening address `tls_listen_addr` at the same time. This allows you to gradually
transition from unencrypted to encrypted traffic if necessary.
+- The certificate's Common Name field is ignored.
+
+### Configure Gitaly with TLS
To configure Gitaly with TLS:
diff --git a/doc/administration/gitaly/faq.md b/doc/administration/gitaly/faq.md
deleted file mode 100644
index f6571295200..00000000000
--- a/doc/administration/gitaly/faq.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-redirect_to: 'index.md'
-remove_date: '2022-08-24'
----
-
-This document was moved to [another location](index.md).
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index c7f7c4c58a5..96447239116 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gitaly and Gitaly Cluster **(FREE SELF)**
diff --git a/doc/administration/gitaly/monitoring.md b/doc/administration/gitaly/monitoring.md
index a435fff74fc..9b7acd536b3 100644
--- a/doc/administration/gitaly/monitoring.md
+++ b/doc/administration/gitaly/monitoring.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring Gitaly and Gitaly Cluster
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index bd03aa1bdbc..e3b198d1012 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure Gitaly Cluster **(FREE SELF)**
@@ -1320,7 +1320,7 @@ Deletions are disabled by default due to a race condition with repository rename
deletions. This is especially prominent in Geo instances as Geo performs more renames than instances without Geo.
You should enable deletions only if the [`gitaly_praefect_generated_replica_paths` feature flag](index.md#praefect-generated-replica-paths-gitlab-150-and-later) is enabled.
-By default, the worker does not delete invalid metadata records but simply logs them and outputs Prometheus
+By default, the worker does not delete invalid metadata records but logs them and outputs Prometheus
metrics for them.
You can enable deleting invalid metadata records with:
diff --git a/doc/administration/gitaly/recovery.md b/doc/administration/gitaly/recovery.md
index 4bbf25d7cdd..b51454aa44e 100644
--- a/doc/administration/gitaly/recovery.md
+++ b/doc/administration/gitaly/recovery.md
@@ -1,14 +1,15 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Recovery options
+# Gitaly Cluster recovery options and tools
-Gitaly Cluster can [recover from certain types of failure](recovery.md).
+Gitaly Cluster can recover from primary-node failure and unavailable repositories. Gitaly Cluster can perform data
+recovery and has Praefect tracking database tools.
-## Primary Node Failure
+## Primary node failure
Gitaly Cluster recovers from a failing primary Gitaly node by promoting a healthy secondary as the
new primary.
@@ -29,14 +30,12 @@ To minimize data loss in GitLab 13.0 to 14.0, Gitaly Cluster:
> - Introduced in GitLab 13.0 as [generally available](../../policy/alpha-beta-support.md#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).
+> - [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. 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.
+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:
@@ -46,7 +45,7 @@ To enable writes again in GitLab 13.0 to 14.0, an administrator can:
[accept data loss](#enable-writes-or-accept-data-loss) if necessary, depending on the version of
GitLab.
-## Unavailable repositories
+### 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.
@@ -252,7 +251,7 @@ These tools reconcile the outdated repositories to bring them fully up to date a
> [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
+five minutes. For each outdated repository on a healthy Gitaly node, 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.
@@ -296,7 +295,7 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
> - [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.
-> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4715) in GitLab 15.3, support for removing repositories from Praefect's database.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4715) in GitLab 15.3, support for removing repositories from the Praefect tracking database.
The `remove-repository` Praefect sub-command removes a repository from a Gitaly Cluster, and all state associated with a given repository including:
@@ -311,9 +310,9 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
- 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 15.3 and later, add `-db-only` to remove the Praefect database entry without removing the on-disk repository. Use this option to remove orphaned database entries and to
+- In GitLab 15.3 and later, add `-db-only` to remove the Praefect tracking database entry without removing the on-disk repository. Use this option to remove orphaned database entries and to
protect on-disk repository data from deletion when a valid repository is accidentally specified. If the database entry is accidentally deleted, re-track the repository with the
- [`track-repository` command](#manually-track-repositories).
+ [`track-repository` command](#manually-add-a-single-repository-to-the-tracking-database).
- In GitLab 14.6 and later, add `-apply` to run the command outside of dry-run mode and remove the repository. For example:
```shell
@@ -349,7 +348,11 @@ Parts of the repository can continue to exist after running `remove-repository`.
If this occurs, run `remove-repository` again.
-### Manually list untracked repositories
+## Praefect tracking database maintenance
+
+Common maintenance tasks on the Praefect tracking database are documented in this section.
+
+### List untracked repositories
> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3926) in GitLab 14.4.
> - `older-than` option added in GitLab 15.0.
@@ -357,10 +360,14 @@ If this occurs, run `remove-repository` again.
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.
+- Aren't tracked in the Praefect tracking database.
+
+Add the `-older-than` option to avoid showing repositories that:
-Add the `-older-than` option to avoid showing repositories that are the process of being created and for which a record doesn't yet exist in the
-Praefect database. Replace `<duration>` with a time duration (for example, `5s`, `10m`, or `1h`). Defaults to `6h`.
+- Are in the process of being created.
+- For which a record doesn't yet exist in the Praefect tracking database.
+
+Replace `<duration>` with a time duration (for example, `5s`, `10m`, or `1h`). Defaults to `6h`.
```shell
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories -older-than <duration>
@@ -382,12 +389,12 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}
```
-### Manually track repositories
+### Manually add a single repository to the tracking database
> - [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.
+The `track-repository` Praefect sub-command adds repositories on disk to the Praefect tracking database to be tracked.
```shell
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -authoritative-storage <storage-name> -repository <repository> -replicate-immediately
@@ -427,15 +434,17 @@ The command outputs:
This command fails if:
-- The repository is already being tracked by the Praefect database.
+- The repository is already being tracked by the Praefect tracking database.
- The repository does not exist on disk.
-### Manually track large numbers of repositories
+### Manually add many repositories to the tracking database
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/6319) in GitLab 15.4.
-The `track-repositories` Praefect sub-command adds large batches of on-disk repositories to the Praefect database for tracking. This can
-be useful when migrating an existing instance to new infrastructure and ingesting all existing repositories into a fresh Gitaly Cluster.
+Migrations using the API automatically add repositories to the Praefect tracking database.
+
+If you are instead manually copying repositories over from existing infrastructure, you can use the `track-repositories`
+Praefect subcommand. This subcommand adds large batches of on-disk repositories to the Praefect tracking database.
```shell
# Omnibus GitLab install
@@ -449,21 +458,21 @@ The command validates that all entries:
- Are formatted correctly and contain required fields.
- Correspond to a valid Git repository on disk.
-- Are not currently tracked in the Praefect database.
+- Are not currently tracked in the Praefect tracking database.
If any entry fails these checks, the command aborts prior to attempting to track a repository.
- `input-path` is the path to a file containing a list of repositories formatted as newline-delimited JSON objects. Objects must contain the following keys:
- - `relative_path`: corresponds with `repository` in [track-repositories](#manually-track-repositories).
+ - `relative_path`: corresponds with `repository` in [`track-repository`](#manually-add-a-single-repository-to-the-tracking-database).
- `authoritative-storage`: the storage Praefect is to treat as the primary.
- `virtual-storage`: the virtual storage the repository is located in.
- For example:
+ For example:
- ```json
- {"relative_path":"@hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git","authoritative_storage":"gitaly-1","virtual_storage":"default"}
- {"relative_path":"@hashed/f8/9f/f89f8d0e735a91c5269ab08d72fa27670d000e7561698d6e664e7b603f5c4e40.git","authoritative_storage":"gitaly-2","virtual_storage":"default"}
- ```
+ ```json
+ {"relative_path":"@hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git","authoritative_storage":"gitaly-1","virtual_storage":"default"}
+ {"relative_path":"@hashed/f8/9f/f89f8d0e735a91c5269ab08d72fa27670d000e7561698d6e664e7b603f5c4e40.git","authoritative_storage":"gitaly-2","virtual_storage":"default"}
+ ```
- `-replicate-immediately`, 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.
diff --git a/doc/administration/gitaly/reference.md b/doc/administration/gitaly/reference.md
index 2542848c7a8..3bf1e3136c0 100644
--- a/doc/administration/gitaly/reference.md
+++ b/doc/administration/gitaly/reference.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gitaly reference **(FREE SELF)**
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index 285ec3d2631..1c5f0d43864 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Gitaly and Gitaly Cluster **(FREE SELF)**
@@ -67,6 +67,13 @@ remote: GitLab: 401 Unauthorized
You need to sync your `gitlab-secrets.json` file with your GitLab
application nodes.
+### 500 and `fetching folder content` errors on repository pages
+
+`Fetching folder content`, and in some cases `500`, errors indicate
+connectivity problems between GitLab and Gitaly.
+Consult the [client-side gRPC logs](#client-side-grpc-logs)
+for details.
+
### Client side gRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
@@ -81,6 +88,19 @@ You can run a gRPC trace with:
sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
```
+If this command fails with a `failed to connect to all addresses` error,
+check for an SSL or TLS problem:
+
+```shell
+/opt/gitlab/embedded/bin/openssl s_client -connect <gitaly-ipaddress>:<port> -verify_return_error
+```
+
+Check whether `Verify return code` field indicates a
+[known Omnibus GitLab configuration problem](https://docs.gitlab.com/omnibus/settings/ssl.html).
+
+If `openssl` succeeds but `gitlab-rake gitlab:gitaly:check` fails,
+check [certificate requirements](configure_gitaly.md#certificate-requirements) for Gitaly.
+
### Server side gRPC logs
gRPC tracing can also be enabled in Gitaly itself with the `GODEBUG=http2debug`
diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md
index cb0156f8e2d..15287b917e7 100644
--- a/doc/administration/housekeeping.md
+++ b/doc/administration/housekeeping.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Housekeeping **(FREE SELF)**
diff --git a/doc/administration/inactive_project_deletion.md b/doc/administration/inactive_project_deletion.md
index 824a444fdd2..88d8e3fc648 100644
--- a/doc/administration/inactive_project_deletion.md
+++ b/doc/administration/inactive_project_deletion.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Inactive project deletion **(FREE SELF)**
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 9351a101ee4..4959bacaaa4 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Incoming email **(FREE SELF)**
@@ -775,7 +775,7 @@ mailboxes.
To configure GitLab for Microsoft Graph, you will need to register an
OAuth2 application in your Azure Active Directory that has the
`Mail.ReadWrite` permission for all mailboxes. See the [MailRoom step-by-step guide](https://github.com/tpitale/mail_room/#microsoft-graph-configuration)
-and [Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
+and [Microsoft instructions](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
for more details.
Record the following when you configure your OAuth2 application:
@@ -792,7 +792,7 @@ to read/write mail in *all* mailboxes.
To mitigate security concerns, we recommend configuring an application access
policy which limits the mailbox access for all accounts, as described in
-[Microsoft documentation](https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access).
+[Microsoft documentation](https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access).
This example for Omnibus GitLab assumes you're using the following mailbox: `incoming@example.onmicrosoft.com`:
@@ -822,7 +822,7 @@ gitlab_rails['incoming_email_inbox_options'] = {
}
```
-For Microsoft Cloud for US Government or [other Azure deployments](https://docs.microsoft.com/en-us/graph/deployments), configure the `azure_ad_endpoint` and `graph_endpoint` settings.
+For Microsoft Cloud for US Government or [other Azure deployments](https://learn.microsoft.com/en-us/graph/deployments), configure the `azure_ad_endpoint` and `graph_endpoint` settings.
- Example for Microsoft Cloud for US Government:
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 58284a74bf7..7d684daf5a6 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
description: 'Learn how to install, configure, update, and maintain your GitLab instance.'
---
@@ -194,7 +194,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Monitoring GitLab](monitoring/index.md):
- [Monitoring uptime](../user/admin_area/monitoring/health_check.md): Check the server status using the health check endpoint.
- - [IP allowlist](monitoring/ip_whitelist.md): Monitor endpoints that provide health check information when probed.
+ - [IP allowlist](monitoring/ip_allowlist.md): Monitor endpoints that provide health check information when probed.
- [Monitoring GitHub imports](monitoring/github_imports.md): The GitLab GitHub Importer displays Prometheus metrics to monitor the health and progress of the importer.
### Performance Monitoring
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 0cf2e3a1131..3f44b53a6d5 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -165,7 +165,7 @@ This setting limits global search requests as follows:
| Authenticated user | 30 |
| Unauthenticated user | 10 |
-Depending on the number of enabled [scopes](../user/search/advanced_search.md#global-search-scopes), a global search request can consume two to seven requests per minute. You may want to disable one or more scopes to use fewer requests. Global search requests that exceed the search rate limit per minute return the following error:
+Depending on the number of enabled [scopes](../user/search/index.md#global-search-scopes), a global search request can consume two to seven requests per minute. You may want to disable one or more scopes to use fewer requests. Global search requests that exceed the search rate limit per minute return the following error:
```plaintext
This endpoint has been requested too many times. Try again later.
@@ -289,6 +289,29 @@ For GitLab.com, see the [webhook limits for GitLab.com](../user/gitlab_com/index
The maximum webhook payload size is 25 MB.
+### Webhook timeout
+
+The number of seconds GitLab waits for an HTTP response after sending a webhook.
+
+To change the webhook timeout value:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['webhook_timeout'] = 60
+ ```
+
+1. Save the file.
+1. Reconfigure and restart GitLab for the changes to
+ take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ gitlab-ctl restart
+ ```
+
+See also [webhook limits for GitLab.com](../user/gitlab_com/index.md#other-limits).
+
### Recursive webhooks
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329743) in GitLab 14.8.
diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md
index d9126036a16..5516a47637d 100644
--- a/doc/administration/instance_review.md
+++ b/doc/administration/instance_review.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Instance review **(FREE SELF)**
diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md
index fb4659175b0..aa029be90e7 100644
--- a/doc/administration/integration/kroki.md
+++ b/doc/administration/integration/kroki.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Kroki diagrams **(FREE SELF)**
@@ -54,7 +54,7 @@ read the [Kroki installation](https://docs.kroki.io/kroki/setup/install/#_images
## Enable Kroki in GitLab
You need to enable Kroki integration from Settings under Admin Area.
-To do that, log in with an administrator account and follow these steps:
+To do that, sign in with an administrator account and follow these steps:
1. On the top bar, select **Main menu > Admin**.
1. Go to **Settings > General**.
diff --git a/doc/administration/integration/mailgun.md b/doc/administration/integration/mailgun.md
index 37e81f220cf..baf9e8c8a3b 100644
--- a/doc/administration/integration/mailgun.md
+++ b/doc/administration/integration/mailgun.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -45,7 +45,7 @@ you're ready to enable the Mailgun integration:
1. Sign in to GitLab as an [Administrator](../../user/permissions.md) user.
1. On the top bar, select **Main menu >** **{admin}** **Admin**.
1. On the left sidebar, go to **Settings > General** and expand the **Mailgun** section.
-1. Select the **Enable Mailgun** check box.
+1. Select the **Enable Mailgun** checkbox.
1. Enter the Mailgun HTTP webhook signing key as described in
[the Mailgun documentation](https://documentation.mailgun.com/en/latest/user_manual.html#webhooks-1) and
shown in the [API security](https://app.mailgun.com/app/account/security/api_keys) section for your Mailgun account.
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index de790c7ce40..f0b3e949b35 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
---
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index 41984bbe7a7..14da70f6efb 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Web terminals (DEPRECATED) **(FREE)**
diff --git a/doc/administration/invalidate_markdown_cache.md b/doc/administration/invalidate_markdown_cache.md
index 20a77691bbc..366cbea5711 100644
--- a/doc/administration/invalidate_markdown_cache.md
+++ b/doc/administration/invalidate_markdown_cache.md
@@ -1,7 +1,7 @@
---
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md
index 31e9944d9a4..d10f5320109 100644
--- a/doc/administration/issue_closing_pattern.md
+++ b/doc/administration/issue_closing_pattern.md
@@ -1,7 +1,7 @@
---
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 14749a9c7f6..1e9f20ded55 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jobs artifacts administration **(FREE SELF)**
@@ -233,8 +233,6 @@ by the `gitlab:artifacts:migrate` Rake task.
To migrate back to local storage:
-1. Set both `direct_upload` and `background_upload` to `false` in `gitlab.rb`, under the artifacts object storage settings.
-1. [Reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Run `gitlab-rake gitlab:artifacts:migrate_to_local`.
1. Disable object_storage for artifacts in `gitlab.rb`:
- Set `gitlab_rails['artifacts_object_store_enabled'] = false`.
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index 84da4e31d92..5aa0e8f3948 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index 2fcf7d2f276..1b01c665ab8 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs_administration.html'
---
@@ -220,7 +220,6 @@ end
To migrate back to local storage:
-1. Set both `direct_upload` and `background_upload` to `false` under the LFS object storage settings. Don't forget to restart GitLab.
1. Run `rake gitlab:lfs:migrate_to_local` on your console.
1. Disable `object_storage` for LFS objects in `gitlab.rb`. Remember to restart GitLab afterwards.
diff --git a/doc/administration/libravatar.md b/doc/administration/libravatar.md
index 88a46759924..5b2334bff8a 100644
--- a/doc/administration/libravatar.md
+++ b/doc/administration/libravatar.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md
index 87b63c6272d..ad89d32183b 100644
--- a/doc/administration/load_balancer.md
+++ b/doc/administration/load_balancer.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Load Balancer for multi-node GitLab **(FREE SELF)**
diff --git a/doc/administration/logs/index.md b/doc/administration/logs/index.md
index d3529de08db..2bcda759442 100644
--- a/doc/administration/logs/index.md
+++ b/doc/administration/logs/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Log system **(FREE SELF)**
diff --git a/doc/administration/logs/log_parsing.md b/doc/administration/logs/log_parsing.md
index 20b439af49b..dfe434ed1f2 100644
--- a/doc/administration/logs/log_parsing.md
+++ b/doc/administration/logs/log_parsing.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Parsing GitLab logs with `jq` **(FREE SELF)**
diff --git a/doc/administration/logs/tracing_correlation_id.md b/doc/administration/logs/tracing_correlation_id.md
index 1d3e4955d3a..f651455a088 100644
--- a/doc/administration/logs/tracing_correlation_id.md
+++ b/doc/administration/logs/tracing_correlation_id.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Find relevant log entries with a correlation ID **(FREE SELF)**
@@ -28,7 +28,7 @@ documentation for some popular browsers.
- [Network Monitor - Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor)
- [Inspect Network Activity In Chrome DevTools](https://developer.chrome.com/docs/devtools/network/)
- [Safari Web Development Tools](https://developer.apple.com/safari/tools/)
-- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/network/)
+- [Microsoft Edge Network panel](https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/network/)
To locate a relevant request and view its correlation ID:
@@ -187,7 +187,7 @@ You can then view the database details for this request:
![Paste request ID into progress bar](img/paste-request-id-into-progress-bar_v14_3.png)
-1. A new request is inserted into the `Request Selector` dropdown on the right-hand side of the Performance Bar. Select the new request to view the metrics of the API request:
+1. A new request is inserted into the `Request Selector` dropdown list on the right-hand side of the Performance Bar. Select the new request to view the metrics of the API request:
![Select request ID from request selector drop down menu](img/select-request-id-from-request-selector-drop-down-menu_v14_3.png)
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
index 60de8e2fd3a..12f3c4c1cc3 100644
--- a/doc/administration/maintenance_mode/index.md
+++ b/doc/administration/maintenance_mode/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Maintenance Mode **(PREMIUM SELF)**
@@ -82,7 +82,7 @@ them to disable Maintenance Mode after it's been enabled.
### Authentication
-All users can log in and out of the GitLab instance but no new users can be created.
+All users can sign in and out of the GitLab instance but no new users can be created.
If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#general-setup) fail.
@@ -113,9 +113,9 @@ For most JSON requests, `POST`, `PUT`, `PATCH`, and `DELETE` are blocked, and th
|:----:|:--------------------------------------:|:----:|
| `POST` | `/admin/application_settings/general` | To allow updating application settings in the administrator UI |
| `PUT` | `/api/v4/application/settings` | To allow updating application settings with the API |
-| `POST` | `/users/sign_in` | To allow users to log in. |
-| `POST` | `/users/sign_out`| To allow users to log out. |
-| `POST` | `/oauth/token` | To allow users to log in to a Geo secondary for the first time. |
+| `POST` | `/users/sign_in` | To allow users to sign in. |
+| `POST` | `/users/sign_out`| To allow users to sign out. |
+| `POST` | `/oauth/token` | To allow users to sign in to a Geo secondary for the first time. |
| `POST` | `/admin/session`, `/admin/session/destroy` | To allow [Admin Mode for GitLab administrators](https://gitlab.com/groups/gitlab-org/-/epics/2158) |
| `POST` | Paths ending with `/compare`| Git revision routes. |
| `POST` | `.git/git-upload-pack` | To allow Git pull/clone. |
diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md
index fe1c74b0e24..4dec9e52c19 100644
--- a/doc/administration/merge_request_diffs.md
+++ b/doc/administration/merge_request_diffs.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request diffs storage **(FREE SELF)**
@@ -271,3 +271,11 @@ By default, `sudo` does not preserve existing environment variables. You should
```shell
sudo gitlab-rake gitlab:external_diffs:force_object_storage START_ID=59946109 END_ID=59946109 UPDATE_DELAY=5
```
+
+## Switching from external storage to object storage
+
+Automatic migration moves diffs stored in the database, but it does not move diffs between storage types.
+To switch from external storage to object storage:
+
+1. Move files stored on local or NFS storage to object storage manually.
+1. Run the Rake task in the [previous section](#correcting-incorrectly-migrated-diffs) to change their location in the database.
diff --git a/doc/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md
index e16e9bb0336..097109585af 100644
--- a/doc/administration/monitoring/github_imports.md
+++ b/doc/administration/monitoring/github_imports.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring GitHub imports **(FREE SELF)**
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index 4b62a8ae931..ad864255f02 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Self-monitoring project (DEPRECATED) **(FREE SELF)**
diff --git a/doc/administration/monitoring/index.md b/doc/administration/monitoring/index.md
index 82a6da1d56a..e57156e6513 100644
--- a/doc/administration/monitoring/index.md
+++ b/doc/administration/monitoring/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring GitLab **(FREE SELF)**
@@ -20,7 +20,7 @@ Explore our features to monitor your GitLab instance:
importer with various Prometheus metrics.
- [Monitoring uptime](../../user/admin_area/monitoring/health_check.md): Check the
server status using the health check endpoint.
- - [IP allowlists](ip_whitelist.md): Configure GitLab for monitoring endpoints that
+ - [IP allowlists](ip_allowlist.md): Configure GitLab for monitoring endpoints that
provide health check information when probed.
- [`nginx_status`](https://docs.gitlab.com/omnibus/settings/nginx.html#enablingdisabling-nginx_status):
Monitor your NGINX server status.
diff --git a/doc/administration/monitoring/ip_allowlist.md b/doc/administration/monitoring/ip_allowlist.md
index 3151b696182..400c70d0fde 100644
--- a/doc/administration/monitoring/ip_allowlist.md
+++ b/doc/administration/monitoring/ip_allowlist.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Application Performance
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# IP whitelist **(FREE SELF)**
@@ -15,7 +15,7 @@ that provide health check information when probed.
To control access to those endpoints via IP whitelisting, you can add single
hosts or use IP ranges:
-**For Omnibus installations**
+**Omnibus**
1. Open `/etc/gitlab/gitlab.rb` and add or uncomment the following:
@@ -27,7 +27,7 @@ hosts or use IP ranges:
---
-**For installations using cloud native Helm charts**
+**Helm chart**
You can set the required IPs under the `gitlab.webservice.monitoring.ipWhitelist` key. For example:
@@ -42,7 +42,7 @@ gitlab:
---
-**For installations from source**
+**Source**
1. Edit `config/gitlab.yml`:
diff --git a/doc/administration/monitoring/ip_whitelist.md b/doc/administration/monitoring/ip_whitelist.md
deleted file mode 100644
index 9fb4ffe3089..00000000000
--- a/doc/administration/monitoring/ip_whitelist.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'ip_allowlist.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](ip_allowlist.md).
-
-<!-- This redirect file can be deleted after <2022-08-31>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index 74db35eebc2..cb5852a7dac 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Configuration **(FREE SELF)**
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index 6e9ea0d8d42..a003a3f25bc 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Grafana Configuration **(FREE SELF)**
@@ -81,7 +81,7 @@ GitLab displays your link in the **Main menu > Admin > Monitoring > Metrics Dash
When setting up Grafana through the process above, no scope shows in the screen at
**Main menu > Admin > Applications > GitLab Grafana**. However, the `read_user` scope is
required and is provided to the application automatically. Setting any scope other than
-`read_user` without also including `read_user` leads to this error when you try to log in using
+`read_user` without also including `read_user` leads to this error when you try to sign in using
GitLab as the OAuth provider:
```plaintext
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index b063a20dc7f..0bea0836191 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Performance Monitoring **(FREE SELF)**
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index c23046158e1..de6178a3151 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Performance bar **(FREE SELF)**
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
deleted file mode 100644
index d0d05c16ea0..00000000000
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-stage: Monitor
-group: Respond
-info: 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
-remove_date: '2022-07-26'
-redirect_to: 'index.md'
----
-
-# Request profiling (removed) **(FREE SELF)**
-
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352488) in GitLab 14.8
-and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) in 15.0.
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index 15ec880533e..bce35306505 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 00dae8e4dd5..e8bdacb0e14 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Prometheus metrics **(FREE SELF)**
@@ -11,7 +11,7 @@ To enable the GitLab Prometheus metrics:
1. Log in to GitLab as a user with administrator access.
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
-1. Find the **Metrics - Prometheus** section, and select **Add link to Prometheus**.
+1. Find the **Metrics - Prometheus** section, and select **Enable GitLab Prometheus metrics endpoint**.
1. [Restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart) for the changes to take effect.
For installations from source you must configure it yourself.
@@ -20,7 +20,7 @@ For installations from source you must configure it yourself.
GitLab monitors its own internal service metrics, and makes them available at the
`/-/metrics` endpoint. Unlike other [Prometheus](https://prometheus.io) exporters, to access
-the metrics, the client IP address must be [explicitly allowed](../ip_whitelist.md).
+the metrics, the client IP address must be [explicitly allowed](../ip_allowlist.md).
These metrics are enabled and collected for [Omnibus GitLab](https://docs.gitlab.com/omnibus/)
and Chart installations. For source installations, these metrics must be enabled
@@ -302,6 +302,10 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `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` |
+| `geo_container_repositories` | Gauge | 15.4 | Number of container repositories on primary | `url` |
+| `geo_container_repositories_synced` | Gauge | 15.4 | Number of container repositories synced on secondary | `url` |
+| `geo_container_repositories_failed` | Gauge | 15.4 | Number of syncable container repositories failed to sync on secondary | `url` |
+| `geo_container_repositories_registry` | Gauge | 15.4 | Number of container repositories in the registry | `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 successful requests that met the target duration for their urgency. Divide by `gitlab_sli:rails_requests_apdex:total` to get a success ratio | `endpoint_id`, `feature_category`, `request_urgency` |
| `geo_ci_secure_files` | Gauge | 15.3 | Number of secure files on primary | `url` |
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index c4aa607fa4d..56583deca89 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring GitLab with Prometheus **(FREE SELF)**
@@ -205,7 +205,7 @@ To use an external Prometheus server:
```
1. Install and set up a dedicated Prometheus instance, if necessary, using the [official installation instructions](https://prometheus.io/docs/prometheus/latest/installation/).
-1. Add the Prometheus server IP address to the [monitoring IP allowlist](../ip_whitelist.md). For example:
+1. Add the Prometheus server IP address to the [monitoring IP allowlist](../ip_allowlist.md). For example:
```ruby
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
@@ -353,7 +353,7 @@ To add a Prometheus dashboard for a single server GitLab setup:
1. Create a new data source in Grafana.
1. Name your data source (such as GitLab).
-1. Select `Prometheus` in the type dropdown box.
+1. Select `Prometheus` in the type dropdown list.
1. Add your Prometheus listen address as the URL, and set access to `Browser`.
1. Set the HTTP method to `GET`.
1. Save and test your configuration to verify that it works.
@@ -381,7 +381,7 @@ memory, disk, and CPU utilization.
The web exporter is a dedicated metrics server that allows splitting end-user and Prometheus traffic
into two separate applications to improve performance and availability.
-[Read more about the web exporter](puma_exporter.md).
+[Read more about the web exporter](web_exporter.md).
### Redis exporter
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index d7a4a96cd9a..c2f84773b3a 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Node exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index 979a6bcd232..56da3155fd9 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PgBouncer exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 95a6540bd19..0458a4a5bae 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PostgreSQL Server Exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/puma_exporter.md b/doc/administration/monitoring/prometheus/puma_exporter.md
deleted file mode 100644
index a3e095f5f09..00000000000
--- a/doc/administration/monitoring/prometheus/puma_exporter.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'web_exporter.md'
-remove_date: '2022-09-01'
----
-
-This document was moved to [another location](web_exporter.md).
-
-<!-- This redirect file can be deleted after <2022-09-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> \ No newline at end of file
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index a5f12bbc52f..b50a2a4aebf 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Redis exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/registry_exporter.md b/doc/administration/monitoring/prometheus/registry_exporter.md
index f4fa35c206e..b79e97bd937 100644
--- a/doc/administration/monitoring/prometheus/registry_exporter.md
+++ b/doc/administration/monitoring/prometheus/registry_exporter.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Registry exporter **(FREE SELF)**
diff --git a/doc/administration/monitoring/prometheus/web_exporter.md b/doc/administration/monitoring/prometheus/web_exporter.md
index 45a8e8d5640..5539526c501 100644
--- a/doc/administration/monitoring/prometheus/web_exporter.md
+++ b/doc/administration/monitoring/prometheus/web_exporter.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Application Performance
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Web exporter (dedicated metrics server) **(FREE SELF)**
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 9967cce5b73..9072bd1f344 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index fd9ab9b5972..0e85635b3d2 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Object storage **(FREE SELF)**
@@ -20,7 +20,7 @@ GitLab has been tested by vendors and customers on a number of object storage pr
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatible mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
+- [Azure Blob storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors, whose list is not officially established.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -247,9 +247,9 @@ The connection settings match those provided by [fog-aws](https://github.com/fog
| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
| `region` | AWS region. | |
-| `host` | S3 compatible host for when not using AWS. For example, `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
-| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
-| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false`. |
+| `host` | DEPRECATED: Use `endpoint` instead. S3 compatible host for when not using AWS. For example, `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
+| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. Always use `endpoint` for consolidated form. | (optional) |
+| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Set to `true` for using [MinIO](https://min.io). Leave as `false` for AWS S3. | `false`. |
| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys. | `false` |
| `aws_credentials_refresh_threshold_seconds` | Sets the [automatic refresh threshold](https://github.com/fog/fog-aws#controlling-credential-refresh-time-with-iam-authentication) when using temporary credentials in IAM. | `15` |
@@ -277,10 +277,13 @@ Here are the valid connection parameters for GCS:
|------------------------------|-------------------|---------|
| `provider` | Provider name. | `Google` |
| `google_project` | GCP project name. | `gcp-project-12345` |
-| `google_client_email` | Email address of the service account. | `foo@gcp-project-12345.iam.gserviceaccount.com` |
| `google_json_key_location` | JSON key path. | `/path/to/gcp-project-12345-abcde.json` |
+| `google_json_key_string` | JSON key string. | `{ "type": "service_account", "project_id": "example-project-382839", ... }` |
| `google_application_default` | Set to `true` to use [Google Cloud Application Default Credentials](https://cloud.google.com/docs/authentication/production#automatically) to locate service account credentials. | |
+GitLab reads the value of `google_json_key_location`, then `google_json_key_string`, and finally, `google_application_default`.
+It uses the first of these settings that has a value.
+
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).
@@ -296,7 +299,6 @@ For Omnibus installations, this is an example of the `connection` setting:
gitlab_rails['object_store']['connection'] = {
'provider' => 'Google',
'google_project' => '<GOOGLE PROJECT>',
- 'google_client_email' => '<GOOGLE CLIENT EMAIL>',
'google_json_key_location' => '<FILENAME>'
}
```
@@ -342,7 +344,7 @@ containers. The [storage-specific form](#storage-specific-configuration)
is not supported. For more details, see [how to transition to consolidated form](#transition-to-consolidated-form).
The following are the valid connection parameters for Azure. Read the
-[Azure Blob storage documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
+[Azure Blob storage documentation](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
to learn more.
| Setting | Description | Example |
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index 8523b881730..7aeb05457c0 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Fast lookup of authorized SSH keys in the database **(FREE SELF)**
@@ -157,7 +157,7 @@ The capabilities of GitLab Shell are not limited to Git operations.
If you are considering switching from OpenSSH to `gitlab-sshd`, consider these concerns:
- The `gitlab-sshd` component is only available for
- [Cloud Native Helm Charts](https://docs.gitlab.com/charts/) deployments.
+ [GitLab Helm chart](https://docs.gitlab.com/charts/) deployments.
- `gitlab-sshd` supports the PROXY protocol. It can run behind proxy servers that rely
on it, such as HAProxy. The PROXY protocol not enabled by default, but can be enabled with a Helm chart setting.
- By default, `gitlab-sshd` binds to port 22, but you can configure a different port in the Helm chart.
diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md
index a5c4795efea..ec2975baf52 100644
--- a/doc/administration/operations/filesystem_benchmarking.md
+++ b/doc/administration/operations/filesystem_benchmarking.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# File system performance benchmarking **(FREE SELF)**
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index 179958c6df1..d18f41becd5 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Performing operations in GitLab **(FREE SELF)**
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 4228b792fdc..75078568c44 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Moving repositories managed by GitLab **(FREE SELF)**
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 8e7594dfc2d..eb326c06e6a 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure the bundled Puma instance of the GitLab package **(FREE SELF)**
@@ -401,4 +401,4 @@ The output in `/tmp/puma.txt` may help diagnose the root cause.
## Related topics
-- [Use a dedicated metrics server to export web metrics](../monitoring/prometheus/puma_exporter.md)
+- [Use a dedicated metrics server to export web metrics](../monitoring/prometheus/web_exporter.md)
diff --git a/doc/administration/operations/rails_console.md b/doc/administration/operations/rails_console.md
index 627dfbeb66c..1ef985b8938 100644
--- a/doc/administration/operations/rails_console.md
+++ b/doc/administration/operations/rails_console.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rails console **(FREE SELF)**
@@ -240,6 +240,24 @@ project.id
# => 2537
```
+## Time an operation
+
+If you'd like to time one or more operations, use the following format, replacing
+the placeholder `<operation>` with your Ruby or Rails commands of choice:
+
+```ruby
+# A single operation
+Benchmark.measure { <operation> }
+
+# A breakdown of multiple operations
+Benchmark.bm do |x|
+ x.report(:label1) { <operation_1> }
+ x.report(:label2) { <operation_2> }
+end
+```
+
+For more information, review [our developer documentation about benchmarks](../../development/performance.md#benchmarks).
+
## Active Record objects
### Looking up database-persisted objects
@@ -680,3 +698,21 @@ unlike with issues or merge requests.
```ruby
ApplicationSetting.current
```
+
+### Open object in `irb`
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
+
+```ruby
+Object.define_method(:irb) { binding.irb }
+
+project = Project.last
+# => #<Project id:2537 root/discard>>
+project.irb
+# Notice new context
+irb(#<Project>)> web_url
+# => "https://gitlab-example/root/discard"
+```
diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md
index 8069dad4d8d..401451d58b4 100644
--- a/doc/administration/operations/ssh_certificates.md
+++ b/doc/administration/operations/ssh_certificates.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# User lookup via OpenSSH's AuthorizedPrincipalsCommand **(FREE SELF)**
@@ -74,7 +74,7 @@ $ ssh-add -L | grep cert | ssh-keygen -L -f -
```
Technically that's not strictly true, for example, it could be
-`prod-aearnfjord` if it's a SSH certificate you'd normally log in to
+`prod-aearnfjord` if it's a SSH certificate you'd normally sign in to
servers as the `prod-aearnfjord` user, but then you must specify your
own `AuthorizedPrincipalsCommand` to do that mapping instead of using
our provided default.
@@ -108,7 +108,7 @@ Where `{KEY_ID}` is the `%i` argument passed to the script
You need to customize the `sshUsers` part of that. It should be
some principal that's guaranteed to be part of the key for all users
-who can log in to GitLab, or you must provide a list of principals,
+who can sign in to GitLab, or you must provide a list of principals,
one of which is present for the user, for example:
```plaintext
@@ -123,7 +123,7 @@ into multiple lines of `authorized_keys` output, as described in the
`AuthorizedPrincipalsFile` documentation in `sshd_config(5)`.
Normally when using the `AuthorizedKeysCommand` with OpenSSH the
-principal is some "group" that's allowed to log into that
+principal is some "group" that's allowed to sign in to that
server. However with GitLab it's only used to appease OpenSSH's
requirement for it, we effectively only care about the "key ID" being
correct. Once that's extracted GitLab enforces its own ACLs for
diff --git a/doc/administration/package_information/defaults.md b/doc/administration/package_information/defaults.md
index 65cb8ef1e6c..c6a33ed7ba9 100644
--- a/doc/administration/package_information/defaults.md
+++ b/doc/administration/package_information/defaults.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package defaults **(FREE SELF)**
diff --git a/doc/administration/package_information/deprecation_policy.md b/doc/administration/package_information/deprecation_policy.md
index 73059514e1c..d8f4551ca09 100644
--- a/doc/administration/package_information/deprecation_policy.md
+++ b/doc/administration/package_information/deprecation_policy.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Omnibus GitLab deprecation policy **(FREE SELF)**
diff --git a/doc/administration/package_information/index.md b/doc/administration/package_information/index.md
index d3a82b87116..4758b453135 100644
--- a/doc/administration/package_information/index.md
+++ b/doc/administration/package_information/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package information **(FREE SELF)**
@@ -53,7 +53,7 @@ Documentation on package signatures can be found at [Signed Packages](signed_pac
Configuration file in `/etc/gitlab/gitlab.rb` is created on initial installation
of the Omnibus GitLab package. On subsequent package upgrades, the configuration
-file is not updated with new configuration. This is done in order to avoid
+file is not updated with new configuration. This is done to avoid
accidental overwrite of user configuration provided in `/etc/gitlab/gitlab.rb`.
New configuration options are noted in the
@@ -76,7 +76,7 @@ characters on each line.
## Init system detection
-Omnibus GitLab attempts to query the underlying system in order to
+Omnibus GitLab attempts to query the underlying system 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/licensing.md b/doc/administration/package_information/licensing.md
index e5afe6b85dd..0e46289a308 100644
--- a/doc/administration/package_information/licensing.md
+++ b/doc/administration/package_information/licensing.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Licensing **(FREE SELF)**
diff --git a/doc/administration/package_information/omnibus_packages.md b/doc/administration/package_information/omnibus_packages.md
index d19f5f67b74..ec406f8b458 100644
--- a/doc/administration/package_information/omnibus_packages.md
+++ b/doc/administration/package_information/omnibus_packages.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Omnibus based packages and images **(FREE SELF)**
diff --git a/doc/administration/package_information/postgresql_versions.md b/doc/administration/package_information/postgresql_versions.md
index d831e8cea7f..6409c5fdbc9 100644
--- a/doc/administration/package_information/postgresql_versions.md
+++ b/doc/administration/package_information/postgresql_versions.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PostgreSQL versions shipped with Omnibus GitLab **(FREE SELF)**
diff --git a/doc/administration/package_information/signed_packages.md b/doc/administration/package_information/signed_packages.md
index 351c2ac5d5f..34c8148e807 100644
--- a/doc/administration/package_information/signed_packages.md
+++ b/doc/administration/package_information/signed_packages.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Signatures **(FREE SELF)**
diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md
index 5ccabd66ed0..00f1bc1eec3 100644
--- a/doc/administration/package_information/supported_os.md
+++ b/doc/administration/package_information/supported_os.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Supported operating systems **(FREE SELF)**
@@ -31,6 +31,7 @@ The following lists the currently supported OSs and their possible EOL dates.
| Ubuntu 20.04 | GitLab CE / GitLab EE 13.2.0 | amd64, arm64 | [Ubuntu Install Documentation](https://about.gitlab.com/install/#ubuntu) | April 2025 | <https://wiki.ubuntu.com/Releases> |
| Amazon Linux 2 | GitLab CE / GitLab EE 14.9.0 | amd64, arm64 | [Amazon Linux 2 Install Documentation](https://about.gitlab.com/install/#amazonlinux-2) | June 2023 | <https://aws.amazon.com/amazon-linux-2/faqs/> |
| Raspberry Pi OS (Buster) (formerly known as Raspbian Buster) | GitLab CE 12.2.0 | armhf | [Raspberry Pi Install Documentation](https://about.gitlab.com/install/#raspberry-pi-os) | 2024 | [Raspberry Pi Details](https://www.raspberrypi.com/news/new-old-functionality-with-raspberry-pi-os-legacy/) |
+| Raspberry Pi OS (Bullseye) | GitLab CE 15.5.0 | armhf | [Raspberry Pi Install Documentation](https://about.gitlab.com/install/#raspberry-pi-os) | 2026 | [Raspberry Pi Details](https://www.raspberrypi.com/news/raspberry-pi-os-debian-bullseye/) |
NOTE:
CentOS 8 was EOL on December 31, 2021. In GitLab 14.5 and later,
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 537840ce785..d04e3217f57 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Container Registry administration **(FREE SELF)**
@@ -40,7 +40,9 @@ if you want to implement this.
If you have installed GitLab from source:
-1. You must [install Registry](https://docs.docker.com/registry/deploying/) by yourself.
+1. You must [deploy a registry](https://docs.docker.com/registry/deploying/) using the image corresponding to the
+ version of GitLab you are installing
+ (for example: `registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v3.15.0-gitlab`)
1. After the installation is complete, to enable it, you must configure the Registry's
settings in `gitlab.yml`.
1. Use the sample NGINX configuration file from under
@@ -158,7 +160,7 @@ If your certificate provider provides the CA Bundle certificates, append them to
An administrator may want the container registry listening on an arbitrary port such as `5678`.
However, the registry and application server are behind an AWS application load balancer that only
-listens on ports `80` and `443`. The administrator may simply remove the port number for
+listens on ports `80` and `443`. The administrator may remove the port number for
`registry_external_url`, so HTTP or HTTPS is assumed. Then, the rules apply that map the load
balancer to the registry from ports `80` or `443` to the arbitrary port. This is important if users
rely on the `docker login` example in the container registry. Here's an example:
@@ -882,10 +884,41 @@ point to the correct registry URL and copy the `registry.key` file to each Sidek
information, see the [Sidekiq configuration](../sidekiq.md)
page.
-To reduce the amount of [Container Registry disk space used by a given project](../troubleshooting/gitlab_rails_cheat_sheet.md#registry-disk-space-usage-by-project),
+To reduce the amount of [Container Registry disk space used by a given project](#registry-disk-space-usage-by-project),
administrators can clean up image tags
and [run garbage collection](#container-registry-garbage-collection).
+### Registry Disk Space Usage by Project
+
+To find the disk space used by each project, run the following in the
+[GitLab Rails console](../operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]]
+# You need to specify the projects that you want to look through. You can get these in any manner.
+projects = Project.last(100)
+
+projects.each do |p|
+ project_total_size = 0
+ container_repositories = p.container_repositories
+
+ container_repositories.each do |c|
+ c.tags.each do |t|
+ project_total_size = project_total_size + t.total_size unless t.total_size.nil?
+ end
+ end
+
+ if project_total_size > 0
+ projects_and_size << [p.project_id, p.creator.id, project_total_size, p.full_path]
+ end
+end
+
+# print it as comma separated output
+projects_and_size.each do |ps|
+ puts "%s,%s,%s,%s" % ps
+end
+```
+
To remove image tags by running the cleanup policy, run the following commands in the
[GitLab Rails console](../operations/rails_console.md):
@@ -935,7 +968,7 @@ provided by `gitlab-ctl`.
Prerequisites:
- You must have installed GitLab by using an Omnibus package or the
- [cloud native chart](https://docs.gitlab.com/charts/charts/registry/#garbage-collection).
+ [GitLab Helm chart](https://docs.gitlab.com/charts/charts/registry/#garbage-collection).
- You must set the Registry to [read-only mode](#performing-garbage-collection-without-downtime).
Running garbage collection causes downtime for the Container Registry. When you run this command
on an instance in an environment where another instance is still writing to the Registry storage,
@@ -1192,7 +1225,7 @@ and signed with the private key.
The Registry then verifies that the signature matches the registry certificate
specified in its configuration and allows the operation.
GitLab background jobs processing (through Sidekiq) also interacts with Registry.
-These jobs talk directly to Registry in order to handle image deletion.
+These jobs talk directly to Registry to handle image deletion.
## Troubleshooting
@@ -1292,8 +1325,8 @@ Check which files are in use:
The output of these `openssl` commands should match, proving that the cert-key pair is a match:
```shell
-openssl x509 -noout -modulus -in /var/opt/gitlab/registry/gitlab-registry.crt | openssl sha256
-openssl rsa -noout -modulus -in /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key | openssl sha256
+/opt/gitlab/embedded/bin/openssl x509 -noout -modulus -in /var/opt/gitlab/registry/gitlab-registry.crt | /opt/gitlab/embedded/bin/openssl sha256
+/opt/gitlab/embedded/bin/openssl rsa -noout -modulus -in /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key | /opt/gitlab/embedded/bin/openssl sha256
```
If the two pieces of the certificate do not align, remove the files and run `gitlab-ctl reconfigure`
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index 40c1b9d795a..789863e8ed0 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Dependency Proxy administration **(FREE SELF)**
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 56786f334b0..a7ab0fb3246 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Package Registry administration **(FREE SELF)**
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 024fb12a51f..922f9a27aad 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Learn how to administer GitLab Pages.'
---
@@ -243,7 +243,6 @@ control over how the Pages daemon runs and serves content in your environment.
| `artifacts_server_url` | API URL to proxy artifact requests to. Defaults to GitLab `external URL` + `/api/v4`, for example `https://gitlab.com/api/v4`. When running a [separate Pages server](#running-gitlab-pages-on-a-separate-server), this URL must point to the main GitLab server's API. |
| `auth_redirect_uri` | Callback URL for authenticating with GitLab. Defaults to project's subdomain of `pages_external_url` + `/auth`. |
| `auth_secret` | Secret key for signing authentication requests. Leave blank to pull automatically from GitLab during OAuth registration. |
-| `client_cert_key_pairs` | Client certificates and keys used for mutual TLS with the GitLab API. See [Support mutual TLS when calling the GitLab API](#support-mutual-tls-when-calling-the-gitlab-api) for details. [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) in GitLab 14.8. |
| `dir` | Working directory for configuration and secrets files. |
| `enable` | Enable or disable GitLab Pages on the current system. |
| `external_http` | Configure Pages to bind to one or more secondary IP addresses, serving HTTP requests. Multiple addresses can be given as an array, along with exact ports, for example `['1.2.3.4', '1.2.3.5:8063']`. Sets value for `listen_http`. |
@@ -525,22 +524,6 @@ Authority (CA) in the system certificate store.
For Omnibus, this is fixed by [installing a custom CA in Omnibus GitLab](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
-### Support mutual TLS when calling the GitLab API
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) in GitLab 14.8.
-
-If GitLab has been [configured to require mutual TLS](https://docs.gitlab.com/omnibus/settings/ssl.html#enable-2-way-ssl-client-authentication), you need to add the client certificates to Pages:
-
-1. Configure in `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_pages['client_cert_key_pairs'] = ['</path/to/cert>:</path/to/key>']
- ```
-
- Where `</path/to/cert>` and `</path/to/key>` are the file paths to the client certificate and its respective key file.
- Both of these files must be encoded in PEM format.
-1. To configure Pages to validate the server certificates, [add the root CA to the system trust store](#using-a-custom-certificate-authority-ca).
-
### ZIP serving and cache configuration
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/392) in GitLab 13.7.
@@ -754,7 +737,7 @@ To set the maximum number of GitLab Pages custom domains for a project:
## Running GitLab Pages on a separate server
You can run the GitLab Pages daemon on a separate server to decrease the load on
-your main application server.
+your main application server. This configuration does not support mutual TLS (mTLS). See the [corresponding feature proposal](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) for more information.
To configure GitLab Pages on a separate server:
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 14ac05e0293..52556809845 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Pages administration for source installations **(FREE SELF)**
diff --git a/doc/administration/polling.md b/doc/administration/polling.md
index 7f1e7a047cf..11f26f081cb 100644
--- a/doc/administration/polling.md
+++ b/doc/administration/polling.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Polling interval multiplier **(FREE SELF)**
diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md
index f53b50192eb..6bf36ef4794 100644
--- a/doc/administration/postgresql/database_load_balancing.md
+++ b/doc/administration/postgresql/database_load_balancing.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database Load Balancing **(FREE SELF)**
diff --git a/doc/administration/postgresql/external.md b/doc/administration/postgresql/external.md
index 7036502e377..8605ee94255 100644
--- a/doc/administration/postgresql/external.md
+++ b/doc/administration/postgresql/external.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure GitLab using an external PostgreSQL service **(FREE SELF)**
@@ -21,7 +21,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL instance:
1. If you are using a cloud-managed service, you may need to grant additional
roles to your `gitlab` user:
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
- - Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/single-server/how-to-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role. Azure Database for PostgreSQL - Flexible Server requires [allow-listing extensions before they can be installed](https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions).
+ - Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://learn.microsoft.com/en-us/azure/postgresql/single-server/how-to-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role. Azure Database for PostgreSQL - Flexible Server requires [allow-listing extensions before they can be installed](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions).
- Google Cloud SQL requires the [`cloudsqlsuperuser`](https://cloud.google.com/sql/docs/postgres/users#default-users) role.
This is for the installation of extensions during installation and upgrades. As an alternative,
diff --git a/doc/administration/postgresql/index.md b/doc/administration/postgresql/index.md
index 8b811deee16..f48e537064a 100644
--- a/doc/administration/postgresql/index.md
+++ b/doc/administration/postgresql/index.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configuring PostgreSQL for scaling **(FREE SELF)**
diff --git a/doc/administration/postgresql/moving.md b/doc/administration/postgresql/moving.md
index 23d377dba37..96076205281 100644
--- a/doc/administration/postgresql/moving.md
+++ b/doc/administration/postgresql/moving.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Moving GitLab databases to a different PostgreSQL instance **(FREE SELF)**
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index b12edd4b9ad..91c689fadea 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 37471a4f491..0ee48047944 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
@@ -1123,7 +1123,7 @@ postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
### Reinitialize a replica
-If a replica cannot start or rejoin the cluster, or when it lags behind and can not catch up, it might be necessary to reinitialize the replica:
+If a replica cannot start or rejoin the cluster, or when it lags behind and cannot catch up, it might be necessary to reinitialize the replica:
1. [Check the replication status](#check-replication-status) to confirm which server
needs to be reinitialized. For example:
diff --git a/doc/administration/postgresql/standalone.md b/doc/administration/postgresql/standalone.md
index 5428e44ccc0..77ff9fd2fe1 100644
--- a/doc/administration/postgresql/standalone.md
+++ b/doc/administration/postgresql/standalone.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Standalone PostgreSQL using Omnibus GitLab **(FREE SELF)**
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
deleted file mode 100644
index 8f27d41b75f..00000000000
--- a/doc/administration/pseudonymizer.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Systems
-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
-remove_date: '2022-08-22'
-redirect_to: 'index.md'
----
-
-# Pseudonymizer (removed) **(ULTIMATE)**
-
-> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/219952) in GitLab 14.7 and removed in 15.0.
-
-WARNING:
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/219952) in GitLab 14.7.
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index cf569cd81d0..2660caa80b3 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrity check Rake task **(FREE SELF)**
diff --git a/doc/administration/raketasks/geo.md b/doc/administration/raketasks/geo.md
index 5c6c99d099b..a4d027101dd 100644
--- a/doc/administration/raketasks/geo.md
+++ b/doc/administration/raketasks/geo.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo Rake Tasks **(PREMIUM SELF)**
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index 0d724bfd4dc..224ed63d3e6 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitHub import **(FREE SELF)**
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index cdad323733d..f6c5f84c500 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# LDAP Rake tasks **(FREE SELF)**
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index c4401b49180..293efb1b7ae 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Maintenance Rake tasks **(FREE SELF)**
@@ -310,6 +310,12 @@ To check the status of specific migrations, you can use the following Rake task:
sudo gitlab-rake db:migrate:status
```
+To check the [tracking database on a Geo secondary site](../geo/setup/external_database.md#configure-the-tracking-database), you can use the following Rake task:
+
+```shell
+sudo gitlab-rake db:migrate:status:geo
+```
+
This outputs a table with a `Status` of `up` or `down` for
each Migration ID.
diff --git a/doc/administration/raketasks/praefect.md b/doc/administration/raketasks/praefect.md
index b7db3f26a60..d1dbc83ad86 100644
--- a/doc/administration/raketasks/praefect.md
+++ b/doc/administration/raketasks/praefect.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Praefect Rake tasks **(FREE SELF)**
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index 00bd71af6c5..e43fbac25e9 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project import/export administration **(FREE SELF)**
diff --git a/doc/administration/raketasks/smtp.md b/doc/administration/raketasks/smtp.md
index 49274501809..5e9e3544902 100644
--- a/doc/administration/raketasks/smtp.md
+++ b/doc/administration/raketasks/smtp.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SMTP Rake tasks **(FREE SELF)**
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index fc0ff23c5b1..d740aaa9c96 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository storage Rake tasks **(FREE SELF)**
@@ -185,8 +185,7 @@ as most of the fixes are relatively high risk, involving running code on the Rai
### Read only projects
-If you have [set projects read only](../troubleshooting/gitlab_rails_cheat_sheet.md#make-a-project-read-only-can-only-be-done-in-the-console)
-they might fail to migrate.
+If you have set projects as read only they might fail to migrate.
1. [Start a Rails console](../operations/rails_console.md#starting-a-rails-console-session).
@@ -233,7 +232,7 @@ Delete the project using the Rails console:
- Replace `admin_handle` with the handle of an instance administrator or with `root`.
- Verify the output before proceeding. **There are no other checks performed**.
-1. [Destroy the project](../troubleshooting/gitlab_rails_cheat_sheet.md#destroy-a-project) **immediately**:
+1. [Destroy the project](../../user/project/working_with_projects.md#delete-a-project-using-console) **immediately**:
```ruby
Projects::DestroyService.new(project, user).execute
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index 216c0875645..b6f14bc6fa4 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Uploads migrate Rake tasks **(FREE SELF)**
@@ -166,33 +166,22 @@ GitLab provides a wrapper Rake task that migrates all uploaded files (for exampl
attachments, and favicon) to local storage in one step. The wrapper task invokes individual Rake
tasks to migrate files falling under each of these categories one by one.
-For details on these Rake tasks, refer to [Individual Rake tasks](#individual-rake-tasks),
-keeping in mind the task name in this case is `gitlab:uploads:migrate_to_local`.
+For details on these Rake tasks, refer to [Individual Rake tasks](#individual-rake-tasks).
+Keep in mind the task name in this case is `gitlab:uploads:migrate_to_local`.
-To migrate uploads from object storage to local storage:
+To migrate uploads from object storage to local storage, run the following Rake task:
-1. Disable both `direct_upload` and `background_upload` under `uploads` settings in `gitlab.rb`:
+**Omnibus GitLab installation**
- ```ruby
- gitlab_rails['uploads_object_store_direct_upload'] = false
- gitlab_rails['uploads_object_store_background_upload'] = false
- ```
-
- Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-1. Run the Rake task:
-
- **Omnibus Installation**
-
- ```shell
- gitlab-rake "gitlab:uploads:migrate_to_local:all"
- ```
+```shell
+gitlab-rake "gitlab:uploads:migrate_to_local:all"
+```
- **Source Installation**
+**Source installation**
- ```shell
- sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate_to_local:all
- ```
+```shell
+sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate_to_local:all
+```
After running the Rake task, you can disable object storage by undoing the changes described
in the instructions to [configure object storage](../../uploads.md#using-object-storage).
diff --git a/doc/administration/raketasks/uploads/sanitize.md b/doc/administration/raketasks/uploads/sanitize.md
index bf6dc4fd776..831abee9739 100644
--- a/doc/administration/raketasks/uploads/sanitize.md
+++ b/doc/administration/raketasks/uploads/sanitize.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Uploads sanitize Rake tasks **(FREE SELF)**
diff --git a/doc/administration/read_only_gitlab.md b/doc/administration/read_only_gitlab.md
index 387a1a75393..3718741e2e9 100644
--- a/doc/administration/read_only_gitlab.md
+++ b/doc/administration/read_only_gitlab.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Place GitLab into a read-only state **(FREE SELF)**
diff --git a/doc/administration/redis/index.md b/doc/administration/redis/index.md
index fb5f6cc3a54..31ea879b289 100644
--- a/doc/administration/redis/index.md
+++ b/doc/administration/redis/index.md
@@ -2,7 +2,7 @@
type: index
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configuring Redis for scaling **(FREE SELF)**
diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md
index b775b579fd4..1c2515099fe 100644
--- a/doc/administration/redis/replication_and_failover.md
+++ b/doc/administration/redis/replication_and_failover.md
@@ -2,7 +2,7 @@
type: howto
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Redis replication and failover with Omnibus GitLab **(PREMIUM SELF)**
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index d624fe28f80..7904fb1ded8 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -2,7 +2,7 @@
type: howto
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Redis replication and failover providing your own instance **(FREE SELF)**
diff --git a/doc/administration/redis/standalone.md b/doc/administration/redis/standalone.md
index bd5b30efb7b..c36d75a566d 100644
--- a/doc/administration/redis/standalone.md
+++ b/doc/administration/redis/standalone.md
@@ -2,7 +2,7 @@
type: howto
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Standalone Redis using Omnibus GitLab **(FREE SELF)**
diff --git a/doc/administration/redis/troubleshooting.md b/doc/administration/redis/troubleshooting.md
index f9e5390c227..e568daed961 100644
--- a/doc/administration/redis/troubleshooting.md
+++ b/doc/administration/redis/troubleshooting.md
@@ -2,7 +2,7 @@
type: reference
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Redis **(FREE SELF)**
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 5d676dac000..45939b48f78 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 10,000 users **(PREMIUM SELF)**
@@ -17,30 +17,37 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)**
-
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|------------------------------------------|-------|-------------------------|------------------|----------------|-----------|
-| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL<sup>1</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
-| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Gitaly<sup>5</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
-| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage<sup>4</sup> | - | - | - | - | - |
-| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
+
+| Service | Nodes | Configuration | GCP | AWS |
+|------------------------------------------|-------|-------------------------|------------------|----------------|
+| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| PostgreSQL<sup>1</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` |
+| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Gitaly<sup>5</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` |
+| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Object storage<sup>4</sup> | - | - | - | - |
+| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
<!-- 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
@@ -151,13 +158,9 @@ Any "burstable" instance types are not recommended due to inconsistent performan
### 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:
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP) 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.
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Praefect PostgreSQL
@@ -293,7 +296,7 @@ for details on managing SSL certificates and configuring NGINX.
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
@@ -506,7 +509,7 @@ cluster to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -1276,7 +1279,7 @@ you are using Geo, where separate database instances are required for handling r
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
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/).
@@ -1693,7 +1696,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1861,7 +1866,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
The following IPs will be used as an example:
@@ -2012,46 +2019,7 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. If you're [using NFS](#configure-nfs-optional):
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` will depend on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
- 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
-
- ```ruby
- ## Prevent GitLab from starting if NFS data mounts are not available
- high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
-
- ## Ensure UIDs and GIDs match between servers for permissions via NFS
- user['uid'] = 9000
- user['gid'] = 9000
- web_server['uid'] = 9001
- web_server['gid'] = 9001
- registry['uid'] = 9002
- registry['gid'] = 9002
- ```
-
- 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. Confirm the node can connect to Gitaly:
@@ -2189,7 +2157,6 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -2319,9 +2286,15 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index 96b1e541f92..a8e0e23512f 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 1,000 users **(FREE SELF)**
@@ -12,7 +12,7 @@ full list of reference architectures, see
If you are serving up to 1,000 users and you don't have strict availability
requirements, a single-node solution with
-[frequent backups](index.md#automated-backups) is appropriate for
+[frequent backups](index.md#backups) is appropriate for
many organizations.
> - **Supported users (approximate):** 1,000
@@ -24,6 +24,7 @@ many organizations.
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)**
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Users | Configuration | GCP | AWS | Azure |
|--------------|-------------------------|----------------|--------------|----------|
@@ -83,11 +84,7 @@ Any "burstable" instance types are not recommended due to inconsistent performan
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:
-
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Swap
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 423dbc7abfb..7d67ac48b73 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 25,000 users **(PREMIUM SELF)**
@@ -17,30 +17,37 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)**
-
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|------------------------------------------|-------|-------------------------|------------------|--------------|-----------|
-| External load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL<sup>1</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
-| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Gitaly<sup>5</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
-| Praefect<sup>5</sup> | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage<sup>4</sup> | - | - | - | - | - |
-| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
+
+| Service | Nodes | Configuration | GCP | AWS |
+|------------------------------------------|-------|-------------------------|------------------|--------------|
+| External load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| PostgreSQL<sup>1</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` |
+| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Internal load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Gitaly<sup>5</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` |
+| Praefect<sup>5</sup> | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Object storage<sup>4</sup> | - | - | - | - |
+| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
<!-- 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
@@ -151,13 +158,9 @@ Any "burstable" instance types are not recommended due to inconsistent performan
### 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:
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP) 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.
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Praefect PostgreSQL
@@ -295,7 +298,7 @@ for details on managing SSL certificates and configuring NGINX.
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
@@ -508,7 +511,7 @@ cluster to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -1281,7 +1284,7 @@ you are using Geo, where separate database instances are required for handling r
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1696,7 +1699,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1864,7 +1869,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
The following IPs will be used as an example:
@@ -2017,46 +2024,8 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. If you're [using NFS](#configure-nfs-optional):
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` will depend on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
- 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
-
- ```ruby
- ## Prevent GitLab from starting if NFS data mounts are not available
- high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
-
- ## Ensure UIDs and GIDs match between servers for permissions via NFS
- user['uid'] = 9000
- user['gid'] = 9000
- web_server['uid'] = 9001
- web_server['gid'] = 9001
- registry['uid'] = 9002
- registry['gid'] = 9002
- ```
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
- 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell
@@ -2192,7 +2161,6 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -2322,9 +2290,15 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 99cc6d47f6a..61ea435f63f 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 2,000 users **(FREE SELF)**
@@ -18,6 +18,7 @@ For a full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)**
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|----------------------------|-------|------------------------|-----------------|--------------|----------|
@@ -31,9 +32,15 @@ For a full list of reference architectures, see
| 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and [Azure Database for PostgreSQL](https://azure.microsoft.com/en-gb/services/postgresql/) is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
<!-- markdownlint-enable MD029 -->
@@ -89,11 +96,7 @@ Any "burstable" instance types are not recommended due to inconsistent performan
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:
-
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
## Setup components
@@ -177,7 +180,7 @@ details about managing SSL certificates and configuring NGINX, see the
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
@@ -249,7 +252,7 @@ to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -589,31 +592,6 @@ but this is dependent on workload.
On each node perform the following:
-1. If you're [using NFS](#configure-nfs-optional):
-
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` will depend on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@@ -742,7 +720,10 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
+
1. Tail the logs to see the requests:
```shell
@@ -899,7 +880,7 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
+- [Azure Blob storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -1026,8 +1007,13 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and [Azure Database for PostgreSQL](https://azure.microsoft.com/en-gb/services/postgresql/) is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
3. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 5c227e3dc27..7484fafe1b0 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 3,000 users **(PREMIUM SELF)**
@@ -27,29 +27,36 @@ For a full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)**
-
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|-------------------------------------------|-------|-----------------------|-----------------|--------------|----------|
-| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL<sup>1</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Gitaly<sup>5</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage<sup>4</sup> | - | - | - | - | - |
-| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
+
+| Service | Nodes | Configuration | GCP | AWS |
+|-------------------------------------------|-------|-----------------------|-----------------|--------------|
+| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` |
+| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| PostgreSQL<sup>1</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` |
+| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Gitaly<sup>5</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` |
+| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Object storage<sup>4</sup> | - | - | - | - |
+| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
<!-- 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
@@ -157,13 +164,9 @@ Any "burstable" instance types are not recommended due to inconsistent performan
### 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:
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP) 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.
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Praefect PostgreSQL
@@ -296,7 +299,7 @@ for details on managing SSL certificates and configuring NGINX.
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
@@ -790,7 +793,7 @@ cluster to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -1221,7 +1224,7 @@ you are using Geo, where separate database instances are required for handling r
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1636,7 +1639,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
The following IPs will be used as an example:
@@ -1803,35 +1808,12 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
On each node perform the following:
-1. If you're [using NFS](#configure-nfs-optional):
-
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` will depend on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@@ -1979,7 +1961,10 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
+
1. Tail the logs to see the requests:
```shell
@@ -2129,7 +2114,6 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -2198,12 +2182,12 @@ cluster alongside your instance, read how to
## Supported modifications for lower user counts (HA)
-The 3k GitLab reference architecture is the smallest we recommend that achieves High Availability (HA).
-However, for environments that need to serve less users but maintain HA, there's several
+The 3,000 user GitLab reference architecture is the smallest we recommend that achieves High Availability (HA).
+However, for environments that need to serve fewer users but maintain HA, there are several
supported modifications you can make to this architecture to reduce complexity and cost.
-It should be noted that to achieve HA with GitLab, this architecture's makeup is ultimately what is
-required. Each component has various considerations and rules to follow and this architecture
+It should be noted that to achieve HA with GitLab, the 3,000 user architecture's makeup is ultimately what is
+required. Each component has various considerations and rules to follow, and the 3,000 user architecture
meets all of these. Smaller versions of this architecture will be fundamentally the same,
but with smaller performance requirements, several modifications can be considered as follows:
@@ -2283,9 +2267,15 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index bddec55ba71..88fc3649b3f 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 50,000 users **(PREMIUM SELF)**
@@ -17,30 +17,37 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)**
-
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|------------------------------------------|-------|-------------------------|------------------|---------------|-----------|
-| External load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL<sup>1</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
-| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Gitaly<sup>5</sup> | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` | `D64s v3` |
-| Praefect<sup>5</sup> | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage<sup>4</sup> | - | - | - | - | - |
-| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
+
+| Service | Nodes | Configuration | GCP | AWS |
+|------------------------------------------|-------|-------------------------|------------------|---------------|
+| External load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` |
+| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| PostgreSQL<sup>1</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` |
+| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Internal load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` |
+| Redis/Sentinel - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Redis/Sentinel - Persistent<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| Gitaly<sup>5</sup> | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` |
+| Praefect<sup>5</sup> | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
+| Object storage<sup>4</sup> | - | - | - | - |
+| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
<!-- 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
@@ -151,13 +158,9 @@ Any "burstable" instance types are not recommended due to inconsistent performan
### 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:
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP) 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.
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Praefect PostgreSQL
@@ -302,7 +305,7 @@ for details on managing SSL certificates and configuring NGINX.
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
@@ -515,7 +518,7 @@ cluster to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -1289,7 +1292,7 @@ you are using Geo, where separate database instances are required for handling r
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
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/).
@@ -1706,7 +1709,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1874,7 +1879,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
The following IPs will be used as an example:
@@ -2034,46 +2041,8 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. If you're [using NFS](#configure-nfs-optional):
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` will depend on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
- 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
-
- ```ruby
- ## Prevent GitLab from starting if NFS data mounts are not available
- high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
-
- ## Ensure UIDs and GIDs match between servers for permissions via NFS
- user['uid'] = 9000
- user['gid'] = 9000
- web_server['uid'] = 9001
- web_server['gid'] = 9001
- registry['uid'] = 9002
- registry['gid'] = 9002
- ```
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
- 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell
@@ -2209,7 +2178,6 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -2339,9 +2307,15 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 0e599df7c1f..c8cf35a2e59 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architecture: up to 5,000 users **(PREMIUM SELF)**
@@ -24,29 +24,36 @@ costly-to-operate environment by using the
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)**
-
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|-------------------------------------------|-------|-------------------------|-----------------|--------------|----------|
-| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL<sup>1</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Gitaly<sup>5</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
-| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2`|
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage<sup>4</sup> | - | - | - | - | - |
-| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
+
+| Service | Nodes | Configuration | GCP | AWS |
+|-------------------------------------------|-------|-------------------------|-----------------|--------------|
+| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` |
+| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| PostgreSQL<sup>1</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` |
+| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Gitaly<sup>5</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` |
+| Praefect<sup>5</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` |
+| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | `c5.4xlarge` |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` |
+| Object storage<sup>4</sup> | - | - | - | - |
+| NFS server (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` |
<!-- 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
@@ -154,13 +161,9 @@ Any "burstable" instance types are not recommended due to inconsistent performan
### 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:
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP) 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.
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [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.
+See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Praefect PostgreSQL
@@ -293,7 +296,7 @@ for details on managing SSL certificates and configuring NGINX.
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
-all require [additional configuration](../monitoring/ip_whitelist.md)
+all require [additional configuration](../monitoring/ip_allowlist.md)
on the nodes being checked, otherwise, the external load balancer is not able to
connect.
@@ -786,7 +789,7 @@ cluster to be used with GitLab.
If you're hosting GitLab on a cloud provider, you can optionally use a
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -1218,7 +1221,7 @@ you are using Geo, where separate database instances are required for handling r
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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+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, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1633,7 +1636,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
- `10.6.0.71`: Sidekiq 1
- `10.6.0.72`: Sidekiq 2
@@ -1799,35 +1804,12 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
-[Object storage](#configure-the-object-storage) is also required to be configured.
+Since it's recommended to use [Object storage](#configure-the-object-storage)
+over [NFS](#configure-nfs-optional) for data objects, the following examples
+include the Object storage configuration.
On each node perform the following:
-1. If you're [using NFS](#configure-nfs-optional):
-
- 1. If necessary, install the NFS client utility packages using the following
- commands:
-
- ```shell
- # Ubuntu/Debian
- apt-get install nfs-common
-
- # CentOS/Red Hat
- yum install nfs-utils nfs-utils-lib
- ```
-
- 1. Specify the necessary NFS mounts in `/etc/fstab`.
- The exact contents of `/etc/fstab` depends on how you chose
- to configure your NFS server. See the [NFS documentation](../nfs.md)
- for examples and the various options.
-
- 1. Create the shared directories. These may be different depending on your NFS
- mount locations.
-
- ```shell
- mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
- ```
-
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@@ -1978,7 +1960,10 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
+
1. Tail the logs to see the requests:
```shell
@@ -2128,7 +2113,6 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
-- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
There are two ways of specifying object storage configuration in GitLab:
@@ -2257,9 +2241,15 @@ 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](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work. However, Amazon Aurora is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440), and 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, Consul 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.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [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.
+ - [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+ - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is **incompatible** with load balancing enabled by default in [14.4.0](../../update/index.md#1440).
+ - Consul is primarily used for Omnibus PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However, Consul is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Memorystore](https://cloud.google.com/memorystore) and [Amazon ElastiCache](https://aws.amazon.com/elasticache/) are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
+ - [Google Cloud Load Balancing](https://cloud.google.com/load-balancing) and [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) are known to work.
4. Should be run on reputable Cloud Provider or Self Managed solutions. More information can be found in the [Configure the object storage](#configure-the-object-storage) section.
5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/img/reference-architectures.png b/doc/administration/reference_architectures/img/reference-architectures.png
deleted file mode 100644
index 0f8e663b57b..00000000000
--- a/doc/administration/reference_architectures/img/reference-architectures.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 7be12e12386..2cf9f2a1e83 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -2,44 +2,20 @@
type: reference, concepts
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference architectures **(FREE SELF)**
-You can set up GitLab on a single server or scale it up to serve many users.
-This page details the recommended Reference Architectures that were built and
-verified by the GitLab Quality and Support teams.
-
-Below is a chart representing each architecture tier and the number of users
-they can handle. As your number of users grow with time, it's recommended that
-you scale GitLab accordingly.
-
-![Reference Architectures](img/reference-architectures.png)
-<!-- Internal link: https://docs.google.com/spreadsheets/d/1obYP4fLKkVVDOljaI3-ozhmCiPtEeMblbBKkf2OADKs/edit#gid=1403207183 -->
-
-For GitLab instances with less than 2,000 users, it's recommended that you use
-the [default setup](#automated-backups) by
-[installing GitLab](../../install/index.md) on a single machine to minimize
-maintenance and resource costs.
-
-If your organization has more than 2,000 users, the recommendation is to scale the
-GitLab components to multiple machine nodes. The machine nodes are grouped by
-components. The addition of these nodes increases the performance and
-scalability of to your GitLab instance.
-
-When scaling GitLab, there are several factors to consider:
-
-- Multiple application nodes to handle frontend traffic.
-- A load balancer is added in front to distribute traffic across the application nodes.
-- The application nodes connects to a shared file server and PostgreSQL and Redis services on the backend.
+The GitLab Reference Architectures have been designed and tested by the
+GitLab Quality and Support teams to provide recommended deployments at scale.
## Available reference architectures
Depending on your workflow, the following recommended reference architectures
may need to be adapted accordingly. Your workload is influenced by factors
including how active your users are, how much automation you use, mirroring,
-and repository/change size. Additionally the displayed memory values are
+and repository/change size. Additionally, the displayed memory values are
provided by [GCP machine types](https://cloud.google.com/compute/docs/machine-types).
For different cloud vendors, attempt to select options that best match the
provided architecture.
@@ -70,7 +46,183 @@ The following Cloud Native Hybrid reference architectures, where select recommen
A GitLab [Premium or Ultimate](https://about.gitlab.com/pricing/#self-managed) license is required
to get assistance from Support with troubleshooting the [2,000 users](2k_users.md)
and higher reference architectures.
-[Read more about our definition of scaled architectures](https://about.gitlab.com/support/#definition-of-scaled-architecture).
+[Read more about our definition of scaled architectures](https://about.gitlab.com/support/definitions/#definition-of-scaled-architecture).
+
+## Deciding which architecture to use
+
+The Reference Architectures are designed to strike a balance between two important factors--performance and resilience.
+
+While they are designed to make it easier to set up GitLab at scale, it can still be a challenge to know which one will meet your requirements.
+
+As a general guide, **the more performant and/or resilient you want your environment to be, the more involved it will be**.
+
+This section explains the designs you can choose from. It begins with the least complexity, goes to the most, and ends with a decision tree.
+
+### Backups
+
+For environments serving 2,000 or fewer users we generally recommend that an [automated backup](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups) strategy is used instead of HA.
+
+Backups can provide a good level of RPO / RTO while avoiding the complexities that come with HA.
+
+### High Availability (HA)
+
+High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. To achieve this however is involved, and the environments required can be sizable.
+
+For environments serving 3,000 or more users we generally recommend that a HA strategy is used as at this level outages will have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason.
+
+For users who still need to have HA for a lower number of users this can also be achieved with an [adjusted 3K architecture as detailed here](3k_users.md#supported-modifications-for-lower-user-counts-ha).
+
+#### Do you need High Availability (HA)?
+
+As mentioned above, achieving HA does come at a cost. The environment's required are sizable as each component needs to be multiplied, which comes with additional actual and maintenance costs.
+
+For a lot of our customers with fewer than 3,000 users, we've found a backup strategy is sufficient and even preferable. While this does have a slower recovery time, it also means you have a much smaller architecture and less maintenance costs as a result.
+
+In general then, we'd only recommend you employ HA in the following scenarios:
+
+- When you have 3,000 or more users.
+- When GitLab being down would critically impact your workflow.
+
+#### Zero Downtime Upgrades
+
+[Zero Downtime Upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is not supported at this time). This allows for an environment to stay up during an upgrade, but the process is more involved as a result and has some limitations as detailed in the documentation.
+
+When going through this process it's worth noting that there may still be brief moments of downtime when the HA mechanisms tale effect.
+
+In most cases the downtime required for doing an upgrade in general shouldn't be substantial, so this is only recommended if it's a key requirement for you.
+
+### Cloud Native Hybrid (Kubernetes HA)
+
+As an additional layer of HA resilience you can deploy select components in Kubernetes, known as a Cloud Native Hybrid Reference Architecture.
+
+Note that this is an alternative and more **advanced** setup compared to a standard Reference Architecture. Running services in Kubernetes is well known to be complex. **This setup is only recommended** if you have strong working knowledge and experience in Kubernetes.
+
+### GitLab Geo (Cross Regional Distribution / Disaster Recovery)
+
+With [GitLab Geo](../geo/index.md) you can have both distributed environments in different regions and a full Disaster Recovery (DR) setup in place. With this setup you would have 2 or more separate environments, with one being a primary that gets replicated to the others. In the rare event the primary site went down completely you could fail over to one of the other environments.
+
+This is an **advanced and involved** setup and should only be undertaken if you have DR as a key requirement. Decisions then on how each environment are configured would also need to be taken, such as if each environment itself would be the full size and / or have HA.
+
+### Decision Tree
+
+Below you can find the above guidance in the form of a decision tree. It's recommended you read through the above guidance in full first before though.
+
+```mermaid
+%%{init: { 'theme': 'base' } }%%
+graph TD
+ L1A(<b>What Reference Architecture should I use?</b>) --> L2A(More than 3000 users?)
+ L2A -->|No| L3A("<a href=#do-you-need-high-availability-ha>Do you need HA?</a><br>(or Zero-Downtime Upgrades)") --> |Yes| L4A><b>Recommendation</b><br><br>3K architecture with HA<br>including supported modifications]
+ L3A -->|No| L4B><b>Recommendation</b><br><br>Architecture closest to user<br>count with Backups]
+ L2A -->|Yes| L3B[Do you have experience with<br/>and want additional resilience<br/>with select components in Kubernetes?]
+ L3B -->|No| L4C><b>Recommendation</b><br><br>Architecture closest to user<br>count with HA]
+ L3B -->|Yes| L4D><b>Recommendation</b><br><br>Cloud Native Hybrid architecture<br>closest to user count]
+
+ L5A("<a href=#gitlab-geo-cross-regional-distribution-disaster-recovery>Do you need cross regional distribution or disaster recovery?"</a>) --> |Yes| L6A><b>Additional Recommendation</b><br><br> GitLab Geo]
+ L4A -.- L5A
+ L4B -.- L5A
+ L4C -.- L5A
+ L4D -.- L5A
+
+classDef default fill:#FCA326
+linkStyle default fill:none,stroke:#7759C2
+```
+
+## Recommended cloud providers and services
+
+NOTE:
+The following lists are non-exhaustive. Generally, other cloud providers not listed
+here likely work with the same specs, but this hasn't been validated.
+Additionally, when it comes to other cloud provider services not listed here,
+it's advised to be cautious as each implementation can be notably different
+and should be tested thoroughly before production use.
+
+Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers:
+
+<table>
+<thead>
+ <tr>
+ <th>Reference Architecture</th>
+ <th>GCP</th>
+ <th>AWS</th>
+ <th>Azure</th>
+ <th>Bare Metal</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>Omnibus</td>
+ <td>🟢</td>
+ <td>🟢</td>
+ <td>🟡<sup>1</sup></td>
+ <td>🟢</td>
+ </tr>
+ <tr>
+ <td>Cloud Native Hybrid</td>
+ <td>🟢</td>
+ <td>🟢</td>
+ <td></td>
+ <td></td>
+ </tr>
+</tbody>
+</table>
+
+1. We only recommend smaller setups (up to 2k) at this time on Azure due to performance issues at larger scales. See the [Recommendation Notes for Azure](#recommendation-notes-for-azure) section for more info.
+
+Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures:
+
+<table>
+<thead>
+ <tr>
+ <th>Cloud Service</th>
+ <th>GCP</th>
+ <th>AWS</th>
+ <th>Bare Metal</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td>Object Storage</td>
+ <td>🟢 &nbsp; <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
+ <td>🟢 &nbsp; <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
+ <td>🟢 &nbsp; <a href="https://min.io/" target="_blank">MinIO</a></td>
+ </tr>
+ <tr>
+ <td>Database</td>
+ <td>🟢 &nbsp; <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
+ <td>🟢 &nbsp; <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Redis</td>
+ <td></td>
+ <td>🟢 &nbsp; <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td>
+ <td></td>
+ </tr>
+</tbody>
+</table>
+
+### Recommendation notes for the database services
+
+When selecting a database service, it should run a standard, performant, and [supported version](../../install/requirements.md#postgresql-requirements) of PostgreSQL with the following features:
+
+- Read Replicas for [Database Load Balancing](../postgresql/database_load_balancing.md).
+- Cross Region replication for [GitLab Geo](../geo/index.md).
+
+Several cloud provider services are known not to support the above or have been found to have other issues and aren't recommended:
+
+- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible and not supported. See [14.4.0](../../update/index.md#1440) for more details.
+- [Azure Database for PostgreSQL Single Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is **strongly not recommended** for use due to notable performance / stability issues or missing functionality. See [Recommendation Notes for Azure](#recommendation-notes-for-azure) for more details.
+- [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
+
+### Recommendation notes for Azure
+
+Due to performance issues that we found with several key Azure services, we only recommend smaller architectures (up to 2k) to be deployed to Azure. For larger architectures, we recommend using another cloud provider.
+
+In addition to the above, you should be aware of the additional specific guidance for Azure:
+
+- **We outright strongly do not recommend [Azure Database for PostgreSQL Single Server](https://learn.microsoft.com/en-us/azure/postgresql/single-server/overview-single-server)** specifically due to significant performance and stability issues found. **For GitLab 14.0 and higher the service is not supported** due to it only supporting up to PostgreSQL 11.
+ - A new service, [Azure Database for Postgres Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/) has been released but due to it missing some functionality we don't recommend it at this time.
+- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. However, this has only been seen in larger architectures.
## Validation and test results
@@ -97,7 +249,7 @@ Network latency on the test environments between components on all Cloud Provide
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.
-The Standard Reference Architectures are designed to be platform agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
+The Standard Reference Architectures are designed to be platform-agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
Testing on these reference architectures is performed with the
[GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)
@@ -111,14 +263,14 @@ per 1,000 users:
- API: 20 RPS
- Web: 2 RPS
- Git (Pull): 2 RPS
-- Git (Push): 0.4 RPS (rounded to nearest integer)
+- Git (Push): 0.4 RPS (rounded to the nearest integer)
### How to interpret the results
NOTE:
Read our blog post on [how our QA team leverages GitLab performance testing tool](https://about.gitlab.com/blog/2020/02/18/how-were-building-up-performance-testing-of-gitlab/).
-Testing is done publicly and all results are shared.
+Testing is done publicly, and all results are shared.
The following table details the testing done against the reference architectures along with the frequency and results. Additional testing is continuously evaluated, and the table is updated accordingly.
@@ -292,170 +444,6 @@ The following table details the cost to run the different reference architecture
</tr>
</table>
-## Recommended cloud providers and services
-
-NOTE:
-The following lists are non exhaustive. Generally, other cloud providers not listed
-here likely work with the same specs, but this hasn't been validated.
-Additionally, when it comes to other cloud provider services not listed here,
-it's advised to be cautious as each implementation can be notably different
-and should be tested thoroughly before production use.
-
-Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers:
-
-<table>
-<thead>
- <tr>
- <th>Reference Architecture</th>
- <th>GCP</th>
- <th>AWS</th>
- <th>Azure</th>
- <th>Bare Metal</th>
- </tr>
-</thead>
-<tbody>
- <tr>
- <td>Omnibus</td>
- <td>✅</td>
- <td>✅</td>
- <td>✅</td>
- <td>✅</td>
- </tr>
- <tr>
- <td>Cloud Native Hybrid</td>
- <td>✅</td>
- <td>✅</td>
- <td></td>
- <td></td>
- </tr>
-</tbody>
-</table>
-
-Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures:
-
-<table>
-<thead>
- <tr>
- <th>Cloud Service</th>
- <th>GCP</th>
- <th>AWS</th>
- <th>Bare Metal</th>
- </tr>
-</thead>
-<tbody>
- <tr>
- <td>Object Storage</td>
- <td>✅ &nbsp; <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
- <td>✅ &nbsp; <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
- <td>✅ &nbsp; <a href="https://min.io/" target="_blank">MinIO</a></td>
- </tr>
- <tr>
- <td>Database</td>
- <td>✅ &nbsp; <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
- <td>✅ &nbsp; <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td>
- <td></td>
- </tr>
- <tr>
- <td>Redis</td>
- <td></td>
- <td>✅ &nbsp; <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td>
- <td></td>
- </tr>
-</tbody>
-</table>
-
-The following specific cloud provider services have been found to have issues in terms of either functionality or performance. As such, they either have caveats that should be considered or are not recommended:
-
-- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
-- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. For larger Reference Architectures the service may not be sufficient for production use and an alternative is recommended for use instead.
-- [Azure Database for PostgreSQL Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is not recommended for use due to notable performance issues or missing functionality.
-
-NOTE:
-As a general rule we unfortunately don't recommend Azure Services at this time.
-If required, we advise thorough testing is done at your intended scale
-over a sustained period to validate if the service is suitable.
-
-## Availability Components
-
-GitLab comes with the following components for your use, listed from least to
-most complex:
-
-- [Automated backups](#automated-backups)
-- [Traffic load balancer](#traffic-load-balancer)
-- [Zero downtime updates](#zero-downtime-updates)
-- [Automated database failover](#automated-database-failover)
-- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo)
-
-As you implement these components, begin with a single server and then do
-backups. Only after completing the first server should you proceed to the next.
-
-Also, not implementing extra servers for GitLab doesn't necessarily mean that you have
-more downtime. Depending on your needs and experience level, single servers can
-have more actual perceived uptime for your users.
-
-### Automated backups
-
-> - Level of complexity: **Low**
-> - Required domain knowledge: PostgreSQL, GitLab configurations, Git
-
-This solution is appropriate for many teams that have the default GitLab installation.
-With automatic backups of the GitLab repositories, configuration, and the database,
-this can be an optimal solution if you don't have strict requirements.
-[Automated backups](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups)
-is the least complex to setup. This provides a point-in-time recovery of a predetermined schedule.
-
-### Traffic load balancer **(PREMIUM SELF)**
-
-> - Level of complexity: **Medium**
-> - Required domain knowledge: HAProxy, shared storage, distributed systems
-
-This requires separating out GitLab into multiple application nodes with an added
-[load balancer](../load_balancer.md). The load balancer distributes traffic
-across GitLab application nodes. Meanwhile, each application node connects to a
-shared file server and database systems on the back end. This way, if one of the
-application servers fails, the workflow is not interrupted.
-[HAProxy](https://www.haproxy.org/) is recommended as the load balancer.
-
-With this added component you have a number of advantages compared
-to the default installation:
-
-- Increase the number of users.
-- Enable zero-downtime upgrades.
-- Increase availability.
-
-For more details on how to configure a traffic load balancer with GitLab, you can refer
-to any of the [available reference architectures](#available-reference-architectures) with more than 1,000 users.
-
-### Zero downtime updates **(PREMIUM SELF)**
-
-> - Level of complexity: **Medium**
-> - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems
-
-GitLab supports [zero-downtime upgrades](../../update/zero_downtime.md).
-Single GitLab nodes can be updated with only a [few minutes of downtime](../../update/index.md#upgrade-based-on-installation-method).
-To avoid this, we recommend to separate GitLab into several application nodes.
-As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity is not interrupted during the update.
-
-### Automated database failover **(PREMIUM SELF)**
-
-> - Level of complexity: **High**
-> - Required domain knowledge: PgBouncer, Patroni, shared storage, distributed systems
-
-By adding automatic failover for database systems, you can enable higher uptime
-with additional database nodes. This extends the default database with
-cluster management and failover policies.
-[PgBouncer in conjunction with Patroni](../postgresql/replication_and_failover.md)
-is recommended.
-
-### Instance level replication with GitLab Geo **(PREMIUM SELF)**
-
-> - Level of complexity: **Very High**
-> - Required domain knowledge: Storage replication
-
-[GitLab Geo](../geo/index.md) allows you to replicate your GitLab
-instance to other geographical locations as a read-only fully operational instance
-that can also be promoted in case of disaster.
-
## Deviating from the suggested reference architectures
As a general guideline, the further away you move from the Reference Architectures,
@@ -475,11 +463,3 @@ However, it is still an additional layer and may still add some support complexi
Other technologies, like [Docker swarm](https://docs.docker.com/engine/swarm/)
are not officially supported, but can be implemented at your own risk. In that
case, GitLab Support is not able to help you.
-
-## Supported modifications for lower user count HA reference architectures
-
-The reference architectures for user counts [3,000](3k_users.md) and up support High Availability (HA).
-
-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).
diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md
index 13fa8450996..6e97ffc3b47 100644
--- a/doc/administration/reply_by_email.md
+++ b/doc/administration/reply_by_email.md
@@ -1,7 +1,7 @@
---
stage: Plan
group: Certify
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reply by email **(FREE SELF)**
@@ -54,4 +54,4 @@ If it finds a reply key, it leaves your reply as a comment on
the entity the notification was about (issue, merge request, commit...).
For more details about the `Message-ID`, `In-Reply-To`, and `References headers`,
-see [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.6.4).
+see [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322#section-3.6.4).
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
index 0fbb4562995..ef6fd82a460 100644
--- a/doc/administration/reply_by_email_postfix_setup.md
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up Postfix for incoming email **(FREE SELF)**
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index 4615499d6fa..08c1df3d5eb 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository checks **(FREE SELF)**
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index 482cbd97e37..492c5306b26 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository storage **(FREE SELF)**
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 865daba9e89..77a5eae3747 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository storage types **(FREE SELF)**
@@ -167,6 +167,10 @@ For example:
"@groups/#{hash[0..1]}/#{hash[2..3]}/#{hash}.wiki.git"
```
+### Gitaly Cluster storage
+
+If Gitaly Cluster is used, Praefect manages storage locations. For more information, see [Praefect-generated replica paths](gitaly/index.md#praefect-generated-replica-paths-gitlab-150-and-later).
+
### Object storage support
This table shows which storable objects are storable in each storage type:
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index e5ec12054b8..1a1194e16a9 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# How to restart GitLab **(FREE SELF)**
@@ -119,7 +119,7 @@ This should restart Puma, Sidekiq, GitLab Workhorse, and [Mailroom](reply_by_ema
## Helm chart installations
There is no single command to restart the entire GitLab application installed via
-the [cloud native Helm Chart](https://docs.gitlab.com/charts/). Usually, it should be
+the [cloud-native Helm chart](https://docs.gitlab.com/charts/). Usually, it should be
enough to restart a specific component separately (for example, `gitaly`, `puma`,
`workhorse`, or `gitlab-shell`) by deleting all the pods related to it:
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 4148abf1bdc..6ab4f476e5e 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/administration/custom_hooks.html'
---
diff --git a/doc/administration/sidekiq/extra_sidekiq_processes.md b/doc/administration/sidekiq/extra_sidekiq_processes.md
index b774b0d3e14..feaaa55aa59 100644
--- a/doc/administration/sidekiq/extra_sidekiq_processes.md
+++ b/doc/administration/sidekiq/extra_sidekiq_processes.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Run multiple Sidekiq processes **(FREE SELF)**
@@ -75,6 +75,9 @@ To start multiple processes:
]
```
+ `*` which matches all workers.
+ As a result, the wildcard query must stay at the end of the list or the rules after it are ignored.
+
`*` cannot be combined with concrete queue names - `*, mailers`
just handles the `mailers` queue.
diff --git a/doc/administration/sidekiq/extra_sidekiq_routing.md b/doc/administration/sidekiq/extra_sidekiq_routing.md
index ebbf4059290..56c51beb758 100644
--- a/doc/administration/sidekiq/extra_sidekiq_routing.md
+++ b/doc/administration/sidekiq/extra_sidekiq_routing.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Queue routing rules **(FREE SELF)**
@@ -161,20 +161,3 @@ After the Sidekiq routing rules are changed, administrators must take care
with the migration to avoid losing jobs entirely, especially in a system with
long queues of jobs. The migration can be done by following the migration steps
mentioned in [Sidekiq job migration](sidekiq_job_migration.md)
-
-### Workers that cannot be migrated
-
-Some workers cannot share a queue with other workers - typically because
-they check the size of their own queue - and so must be excluded from
-this process. We recommend excluding these from any further worker
-routing by adding a rule to keep them in their own queue, for example:
-
-```ruby
-sidekiq['routing_rules'] = [
- ['tags=needs_own_queue', nil],
- # ...
-]
-```
-
-These queues must also be included in at least one
-[Sidekiq queue group](extra_sidekiq_processes.md#start-multiple-processes).
diff --git a/doc/administration/sidekiq/index.md b/doc/administration/sidekiq/index.md
index f4e67fcb6dd..f17c248e60e 100644
--- a/doc/administration/sidekiq/index.md
+++ b/doc/administration/sidekiq/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure an external Sidekiq instance **(FREE SELF)**
@@ -377,6 +377,10 @@ To enable LDAP with the synchronization worker for Sidekiq:
sudo gitlab-ctl reconfigure
```
+## Configure SAML Groups for SAML Group Sync
+
+If you use [SAML Group Sync](../../user/group/saml_sso/group_sync.md), you must configure [SAML Groups](../../integration/saml.md#saml-groups) on all your Sidekiq nodes.
+
## 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),
diff --git a/doc/administration/sidekiq/sidekiq_health_check.md b/doc/administration/sidekiq/sidekiq_health_check.md
index 3477320a2ac..74b478c1913 100644
--- a/doc/administration/sidekiq/sidekiq_health_check.md
+++ b/doc/administration/sidekiq/sidekiq_health_check.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq Health Check **(FREE SELF)**
diff --git a/doc/administration/sidekiq/sidekiq_job_migration.md b/doc/administration/sidekiq/sidekiq_job_migration.md
index a3bc8b2959a..f61021ad4e7 100644
--- a/doc/administration/sidekiq/sidekiq_job_migration.md
+++ b/doc/administration/sidekiq/sidekiq_job_migration.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq job migration **(FREE SELF)**
diff --git a/doc/administration/sidekiq/sidekiq_memory_killer.md b/doc/administration/sidekiq/sidekiq_memory_killer.md
index 12381808523..bbf95bc45ce 100644
--- a/doc/administration/sidekiq/sidekiq_memory_killer.md
+++ b/doc/administration/sidekiq/sidekiq_memory_killer.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
-group: Memory
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+group: Application Performance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq MemoryKiller **(FREE SELF)**
@@ -32,26 +32,12 @@ run as a process group leader (for example, using `chpst -P`). If using Omnibus
The MemoryKiller is controlled using environment variables.
-- `SIDEKIQ_DAEMON_MEMORY_KILLER`: defaults to 1. When set to 0, the MemoryKiller
- works in _legacy_ mode. Otherwise, the MemoryKiller works in _daemon_ mode.
-
- In _legacy_ mode, the MemoryKiller checks the Sidekiq process RSS
- ([Resident Set Size](https://github.com/mperham/sidekiq/wiki/Memory#rss))
- after each job.
-
- In _daemon_ mode, the MemoryKiller checks the Sidekiq process RSS every 3 seconds
- (defined by `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL`).
-
- `SIDEKIQ_MEMORY_KILLER_MAX_RSS` (KB): if this variable is set, and its value is greater
than 0, the MemoryKiller is enabled. Otherwise the MemoryKiller is disabled.
`SIDEKIQ_MEMORY_KILLER_MAX_RSS` defines the Sidekiq process allowed RSS.
- In _legacy_ mode, if the Sidekiq process exceeds the allowed RSS then an irreversible
- delayed graceful restart is triggered. The restart of Sidekiq happens
- after `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` seconds.
-
- In _daemon_ mode, if the Sidekiq process exceeds the allowed RSS for longer than
+ If the Sidekiq process exceeds the allowed RSS for longer than
`SIDEKIQ_MEMORY_KILLER_GRACE_TIME` the graceful restart is triggered. If the
Sidekiq process go below the allowed RSS within `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`,
the restart is aborted.
@@ -59,11 +45,11 @@ The MemoryKiller is controlled using environment variables.
The default value for Omnibus packages is set
[in the Omnibus GitLab repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb).
-- `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` (KB): is used by _daemon_ mode. If the Sidekiq
+- `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` (KB): If the Sidekiq
process RSS (expressed in kilobytes) exceeds `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS`,
an immediate graceful restart of Sidekiq is triggered.
-- `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL`: used in _daemon_ mode to define how
+- `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL`: Define how
often to check process RSS, default to 3 seconds.
- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults to 900 seconds (15 minutes).
diff --git a/doc/administration/sidekiq/sidekiq_troubleshooting.md b/doc/administration/sidekiq/sidekiq_troubleshooting.md
index 9bc8e473409..d2afe171e9c 100644
--- a/doc/administration/sidekiq/sidekiq_troubleshooting.md
+++ b/doc/administration/sidekiq/sidekiq_troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Sidekiq **(FREE SELF)**
@@ -306,7 +306,7 @@ end
### Remove Sidekiq jobs for given parameters (destructive)
The general method to kill jobs conditionally is the following command, which
-removes jobs that are queued but not started. Running jobs can not be killed.
+removes jobs that are queued but not started. Running jobs cannot be killed.
```ruby
queue = Sidekiq::Queue.new('<queue name>')
diff --git a/doc/administration/smime_signing_email.md b/doc/administration/smime_signing_email.md
index c9647129104..4e49eef44df 100644
--- a/doc/administration/smime_signing_email.md
+++ b/doc/administration/smime_signing_email.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Signing outgoing email with S/MIME **(FREE SELF)**
diff --git a/doc/administration/snippets/index.md b/doc/administration/snippets/index.md
index 61d0b1ec50a..89a571946af 100644
--- a/doc/administration/snippets/index.md
+++ b/doc/administration/snippets/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Create
group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Snippets settings **(FREE SELF)**
diff --git a/doc/administration/static_objects_external_storage.md b/doc/administration/static_objects_external_storage.md
index a288b19f164..ef89e38be6f 100644
--- a/doc/administration/static_objects_external_storage.md
+++ b/doc/administration/static_objects_external_storage.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/administration/system_hooks.md b/doc/administration/system_hooks.md
index 0d70744e942..56e73150616 100644
--- a/doc/administration/system_hooks.md
+++ b/doc/administration/system_hooks.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 5a272025987..61fda91ba71 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Terraform state administration **(FREE)**
diff --git a/doc/administration/timezone.md b/doc/administration/timezone.md
index 93419751251..b0dc995c684 100644
--- a/doc/administration/timezone.md
+++ b/doc/administration/timezone.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Changing your time zone **(FREE SELF)**
@@ -27,7 +27,7 @@ This Rake task does not list time zones in TZInfo format required by Omnibus Git
GitLab defaults its time zone to UTC. It has a global time zone configuration parameter in `/etc/gitlab/gitlab.rb`.
-To obtain a list of time zones, log in to your GitLab application server and run a command that generates a list of time zones in TZInfo format for the server. For example, install `timedatectl` and run `timedatectl list-timezones`.
+To obtain a list of time zones, sign in to your GitLab application server and run a command that generates a list of time zones in TZInfo format for the server. For example, install `timedatectl` and run `timedatectl list-timezones`.
To update, add the time zone that best applies to your location. For example:
diff --git a/doc/administration/troubleshooting/diagnostics_tools.md b/doc/administration/troubleshooting/diagnostics_tools.md
index faddf12b97d..32b07d8c4af 100644
--- a/doc/administration/troubleshooting/diagnostics_tools.md
+++ b/doc/administration/troubleshooting/diagnostics_tools.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -26,4 +26,4 @@ and summarize raw `strace` data.
## `kubesos`
-The [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) utility retrieves GitLab cluster configuration and logs from GitLab Cloud Native chart deployments.
+The [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) utility retrieves GitLab cluster configuration and logs from GitLab Helm chart deployments.
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 40bb15ecb70..20ce52a9094 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Rails Console Cheat Sheet **(FREE SELF)**
@@ -62,308 +62,6 @@ Notify.test_email(e, "Test email for #{n}", 'Test email').deliver_now
Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
```
-## Open object in `irb`
-
-Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
-
-```ruby
-Object.define_method(:irb) { binding.irb }
-
-project = Project.last
-# => #<Project id:2537 root/discard>>
-project.irb
-# Notice new context
-irb(#<Project>)> web_url
-# => "https://gitlab-example/root/discard"
-```
-
-## View all keys in cache
-
-```ruby
-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}")
-
-# From 11.6.0
-admin = User.find_by_username('<admin-username>')
-Gitlab::Profiler.with_user(admin) { app.get(url) }
-```
-
-## Using the GitLab profiler inside console (used as of 10.5)
-
-```ruby
-logger = Logger.new($stdout)
-admin = User.find_by_username('<admin-username>')
-Gitlab::Profiler.profile('<url/of/the/page>', logger: logger, user: admin)
-```
-
-## Time an operation
-
-```ruby
-# A single operation
-Benchmark.measure { <operation> }
-
-# A breakdown of multiple operations
-Benchmark.bm do |x|
- x.report(:label1) { <operation_1> }
- x.report(:label2) { <operation_2> }
-end
-```
-
-## Projects
-
-### Clear a project's cache
-
-```ruby
-ProjectCacheWorker.perform_async(project.id)
-```
-
-### Expire the .exists? cache
-
-```ruby
-project.repository.expire_exists_cache
-```
-
-### Make all projects private
-
-```ruby
-Project.update_all(visibility_level: 0)
-```
-
-### Find projects that are pending deletion
-
-```ruby
-#
-# This section lists all the projects which are pending deletion
-#
-projects = Project.where(pending_delete: true)
-projects.each do |p|
- puts "Project ID: #{p.id}"
- puts "Project name: #{p.name}"
- puts "Repository path: #{p.repository.full_path}"
-end
-
-#
-# Assign a user (the root user does)
-#
-user = User.find_by_username('root')
-
-#
-# For each project listed repeat these two commands
-#
-
-# Find the project, update the xxx-changeme values from above
-project = Project.find_by_full_path('group-changeme/project-changeme')
-
-# Immediately delete the project
-::Projects::DestroyService.new(project, user, {}).execute
-```
-
-### Destroy a project
-
-```ruby
-project = Project.find_by_full_path('<project_path>')
-user = User.find_by_username('<username>')
-ProjectDestroyWorker.perform_async(project.id, user.id, {})
-# or ProjectDestroyWorker.new.perform(project.id, user.id, {})
-# or Projects::DestroyService.new(project, user).execute
-```
-
-If this fails, display why it doesn't work with:
-
-```ruby
-project = Project.find_by_full_path('<project_path>')
-project.delete_error
-```
-
-### Remove fork relationship manually
-
-```ruby
-p = Project.find_by_full_path('<project_path>')
-u = User.find_by_username('<username>')
-::Projects::UnlinkForkService.new(p, u).execute
-```
-
-### Make a project read-only (can only be done in the console)
-
-```ruby
-# Make a project read-only
-project.repository_read_only = true; project.save
-
-# OR
-project.update!(repository_read_only: true)
-```
-
-### Transfer project from one namespace to another
-
-```ruby
-p = Project.find_by_full_path('<project_path>')
-
- # To set the owner of the project
- current_user= p.creator
-
-# Namespace where you want this to be moved.
-namespace = Namespace.find_by_full_path("<new_namespace>")
-
-::Projects::TransferService.new(p, current_user).execute(namespace)
-```
-
-### Bulk update service integration password for _all_ projects
-
-For example, change the Jira user's password for all projects that have the Jira
-integration active:
-
-```ruby
-p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN services s ON p.id = s.project_id WHERE s.type = 'JiraService' AND s.active = true")
-
-p.each do |project|
- project.jira_integration.update_attribute(:password, '<your-new-password>')
-end
-```
-
-### Bulk update push rules for _all_ projects
-
-For example, enable **Check whether the commit author is a GitLab user** and **Do not allow users to remove Git tags with `git push`** checkboxes, and create a filter for allowing commits from a specific email domain only:
-
-``` ruby
-Project.find_each do |p|
- pr = p.push_rule || PushRule.new(project: p)
- # Check whether the commit author is a GitLab user
- pr.member_check = true
- # Do not allow users to remove Git tags with `git push`
- pr.deny_delete_tag = true
- # Commit author's email
- pr.author_email_regex = '@domain\.com$'
- pr.save!
-end
-```
-
-### Bulk update to change all the Jira integrations to Jira instance-level values
-
-To change all Jira project to use the instance-level integration settings:
-
-1. In a Rails console:
-
- ```ruby
- jira_integration_instance_id = Integrations::Jira.find_by(instance: true).id
- Integrations::Jira.where(active: true, instance: false, template: false, inherit_from_id: nil).find_each do |integration|
- integration.update_attribute(:inherit_from_id, jira_integration_instance_id)
- end
- ```
-
-1. Modify and save again the instance-level integration from the UI to propagate the changes to all the group-level and project-level integrations.
-
-### Check if Jira Cloud is linked to a namespace
-
-```ruby
-JiraConnectSubscription.where(namespace: Namespace.by_path('group/subgroup'))
-```
-
-### Check if Jira Cloud is linked to a project
-
-```ruby
-Project.find_by_full_path('path/to/project').jira_subscription_exists?
-```
-
-### Check if Jira Cloud URL is linked to any namespace
-
-```ruby
-installation = JiraConnectInstallation.find_by_base_url("https://customer_name.atlassian.net")
-installation.subscriptions
-```
-
-### Bulk update to disable the Slack Notification service
-
-To disable notifications for all projects that have Slack service enabled, do:
-
-```ruby
-# Grab all projects that have the Slack notifications enabled
-p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN services s ON p.id = s.project_id WHERE s.type = 'SlackService' AND s.active = true")
-
-# Disable the service on each of the projects that were found.
-p.each do |project|
- project.slack_service.update_attribute(:active, false)
-end
-```
-
-### Incorrect repository statistics shown in the GUI
-
-After [reducing a repository size with third-party tools](../../user/project/repository/reducing_the_repo_size_using_git.md)
-the displayed size may still show old sizes or commit numbers. To force an update, do:
-
-```ruby
-p = Project.find_by_full_path('<namespace>/<project>')
-pp p.statistics
-p.statistics.refresh!
-pp p.statistics
-# compare with earlier values
-
-# check the total artifact storage space separately
-builds_with_artifacts = p.builds.with_downloadable_artifacts.all
-
-artifact_storage = 0
-builds_with_artifacts.find_each do |build|
- artifact_storage += build.artifacts_size
-end
-
-puts "#{artifact_storage} bytes"
-```
-
-### Identify deploy keys associated with blocked and non-member users
-
-When the user who created a deploy key is blocked or removed from the project, the key
-can no longer be used to push to protected branches in a private project (see [issue #329742](https://gitlab.com/gitlab-org/gitlab/-/issues/329742)).
-The following script identifies unusable deploy keys:
-
-```ruby
-ghost_user_id = User.ghost.id
-
-DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
- project = deploy_key_mapping.project
- deploy_key = deploy_key_mapping.deploy_key
- user = deploy_key.user
-
- access_checker = Gitlab::DeployKeyAccess.new(deploy_key, container: project)
-
- # can_push_for_ref? tests if deploy_key can push to default branch, which is likely to be protected
- can_push = access_checker.can_do_action?(:push_code)
- can_push_to_default = access_checker.can_push_for_ref?(project.repository.root_ref)
-
- next if access_checker.allowed? && can_push && can_push_to_default
-
- if user.nil? || user.id == ghost_user_id
- username = 'none'
- state = '-'
- else
- username = user.username
- user_state = user.state
- end
-
- puts "Deploy key: #{deploy_key.id}, Project: #{project.full_path}, Can push?: " + (can_push ? 'YES' : 'NO') +
- ", Can push to default branch #{project.repository.root_ref}?: " + (can_push_to_default ? 'YES' : 'NO') +
- ", User: #{username}, User state: #{user_state}"
-end
-```
-
-### Find projects using an SQL query
-
-Find and store an array of projects based on an SQL query:
-
-```ruby
-# Finds projects that end with '%ject'
-projects = Project.find_by_sql("SELECT * FROM projects WHERE name LIKE '%ject'")
-=> [#<Project id:12 root/my-first-project>>, #<Project id:13 root/my-second-project>>]
-```
-
## Imports and exports
### Import a project
@@ -435,37 +133,6 @@ 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
-
-If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
-[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
-describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../server_hooks.md) that changes a HEAD ref via a `git reset` operation.
-
-If you look at the output from the sample code below for the target branch, you
-see a discontinuity in the from/to commits as you step through the output. The `commit_from` of each new push should equal the `commit_to` of the previous push. A break in that sequence indicates one or more commits have been "lost" from the repository history.
-
-The following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
-
-```ruby
-p = Project.find_by_full_path('u/p')
-p.events.pushed_action.last(100).each do |e|
- printf "%-20.20s %8s...%8s (%s)
-", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
-end
-```
-
-Example output showing break in sequence at line 4:
-
-```plaintext
-master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de (root)
-master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b (root)
-master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 (root)
-master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce (root)
-master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 (root)
-```
-
## Mirrors
### Find mirrors with "bad decrypt" errors
@@ -474,36 +141,7 @@ This content has been converted to a Rake task, see [verify database values can
### Transfer mirror users and tokens to a single service account
-Use case: If you have multiple users using their own GitHub credentials to set up
-repository mirroring, mirroring breaks when people leave the company. Use this
-script to migrate disparate mirroring users and tokens into a single service account:
-
-```ruby
-svc_user = User.find_by(username: 'ourServiceUser')
-token = 'githubAccessToken'
-
-Project.where(mirror: true).each do |project|
- import_url = project.import_url
-
- # The url we want is https://token@project/path.git
- repo_url = if import_url.include?('@')
- # Case 1: The url is something like https://23423432@project/path.git
- import_url.split('@').last
- elsif import_url.include?('//')
- # Case 2: The url is something like https://project/path.git
- import_url.split('//').last
- end
-
- next unless repo_url
-
- final_url = "https://#{token}@#{repo_url}"
-
- project.mirror_user = svc_user
- project.import_url = final_url
- project.username_only_import_url = final_url
- project.save
-end
-```
+This content has been moved to [Troubleshooting Repository mirroring](../../user/project/repository/mirror/index.md#transfer-mirror-users-and-tokens-to-a-single-service-account-in-rails-console).
## Users
@@ -627,147 +265,6 @@ group = Group.find_by_full_path 'group'
user.max_member_access_for_group group.id
```
-## Groups
-
-### Transfer group to another location
-
-```ruby
-user = User.find_by_username('<username>')
-group = Group.find_by_name("<group_name>")
-parent_group = Group.find_by(id: "<group_id>")
-service = ::Groups::TransferService.new(group, user)
-service.execute(parent_group)
-```
-
-### Count unique users in a group and subgroups
-
-```ruby
-group = Group.find_by_path_or_name("groupname")
-members = []
-for member in group.members_with_descendants
- members.push(member.user_name)
-end
-
-members.uniq.length
-```
-
-```ruby
-group = Group.find_by_path_or_name("groupname")
-
-# Count users from subgroup and up (inherited)
-group.members_with_parents.count
-
-# Count users from the parent group and down (specific grants)
-parent.members_with_descendants.count
-```
-
-### Find groups that are pending deletion
-
-```ruby
-#
-# This section lists all the groups which are pending deletion
-#
-Group.all.each do |g|
- if g.marked_for_deletion?
- puts "Group ID: #{g.id}"
- puts "Group name: #{g.name}"
- puts "Group path: #{g.full_path}"
- end
-end
-```
-
-### Delete a group
-
-```ruby
-GroupDestroyWorker.perform_async(group_id, user_id)
-```
-
-### Modify group project creation
-
-```ruby
-# Project creation levels: 0 - No one, 1 - Maintainers, 2 - Developers + Maintainers
-group = Group.find_by_path_or_name('group-name')
-group.project_creation_level=0
-```
-
-### Modify group - disable 2FA requirement
-
-WARNING:
-When disabling the 2FA Requirement on a subgroup, the whole parent group (including all subgroups) is affected by this change.
-
-```ruby
-group = Group.find_by_path_or_name('group-name')
-group.require_two_factor_authentication=false
-group.save
-```
-
-### Check and toggle a feature for all projects in a group
-
-```ruby
-projects = Group.find_by_name('_group_name').projects
-projects.each do |p|
- state = p.<feature-name>?
-
- if state
- puts "#{p.name} has <feature-name> already enabled. Skipping..."
- else
- puts "#{p.name} didn't have <feature-name> enabled. Enabling..."
- p.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
- end
-end
-```
-
-To find features that can be toggled, run `pp p.project_feature`.
-Available permission levels are listed in
-[concerns/featurable.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/featurable.rb).
-
-### Get all error messages associated with groups, subgroups, members, and requesters
-
-Collect error messages associated with groups, subgroups, members, and requesters. This
-captures error messages that may not appear in the Web interface. This can be especially helpful
-for troubleshooting issues with [LDAP group sync](../auth/ldap/ldap_synchronization.md#group-sync)
-and unexpected behavior with users and their membership in groups and subgroups.
-
-```ruby
-# Find the group and subgroup
-group = Group.find_by_full_path("parent_group")
-subgroup = Group.find_by_full_path("parent_group/child_group")
-
-# Group and subgroup errors
-group.valid?
-group.errors.map(&:full_messages)
-
-subgroup.valid?
-subgroup.errors.map(&:full_messages)
-
-# Group and subgroup errors for the members AND requesters
-group.requesters.map(&:valid?)
-group.requesters.map(&:errors).map(&:full_messages)
-group.members.map(&:valid?)
-group.members.map(&:errors).map(&:full_messages)
-group.members_and_requesters.map(&:errors).map(&:full_messages)
-
-subgroup.requesters.map(&:valid?)
-subgroup.requesters.map(&:errors).map(&:full_messages)
-subgroup.members.map(&:valid?)
-subgroup.members.map(&:errors).map(&:full_messages)
-subgroup.members_and_requesters.map(&:errors).map(&:full_messages)
-```
-
-## Routes
-
-### Remove redirecting routes
-
-See <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41758#note_54828133>.
-
-```ruby
-path = 'foo'
-conflicting_permanent_redirects = RedirectRoute.matching_path_and_descendants(path)
-
-# Check that conflicting_permanent_redirects is as expected
-conflicting_permanent_redirects.destroy_all
-```
-
## Merge requests
### Close a merge request
@@ -972,37 +469,7 @@ License.select(&TYPE).each(&:destroy!)
### Registry Disk Space Usage by Project
-As a GitLab administrator, you may want to reduce disk space consumption.
-A common culprit is Docker Registry images that are no longer in use. To find
-the storage broken down by each project, run the following in the
-[GitLab Rails console](../operations/rails_console.md):
-
-```ruby
-projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]]
-# You need to specify the projects that you want to look through. You can get these in any manner.
-projects = Project.last(100)
-
-projects.each do |p|
- project_total_size = 0
- container_repositories = p.container_repositories
-
- container_repositories.each do |c|
- c.tags.each do |t|
- project_total_size = project_total_size + t.total_size unless t.total_size.nil?
- end
- end
-
- if project_total_size > 0
- projects_and_size << [p.project_id, p.creator.id, project_total_size, p.full_path]
- end
-end
-
-# projects_and_size is filled out now
-# maybe print it as comma separated output?
-projects_and_size.each do |ps|
- puts "%s,%s,%s,%s" % ps
-end
-```
+Find this content in the [Container Registry troubleshooting documentation](../packages/container_registry.md#registry-disk-space-usage-by-project).
### Run the Cleanup policy now
@@ -1012,14 +479,6 @@ Find this content in the [Container Registry troubleshooting documentation](../p
This content has been moved to [Troubleshooting Sidekiq](sidekiq.md).
-## Redis
-
-### Connect to Redis (omnibus)
-
-```shell
-/opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket
-```
-
## LFS
### Get information about LFS objects and associated project
@@ -1124,152 +583,19 @@ There is an [issue to implement this functionality in the Admin UI](https://gitl
### Artifacts
-#### Find failed artifacts
-
-```ruby
-Geo::JobArtifactRegistry.failed
-```
-
-#### Get a count of the synced artifacts
-
-```ruby
-Geo::JobArtifactRegistry.synced.count
-```
-
-#### Find `ID` of synced artifacts that are missing on primary
-
-```ruby
-Geo::JobArtifactRegistry.synced.missing_on_primary.pluck(:artifact_id)
-```
+Moved to [Geo replication troubleshooting](../geo/replication/troubleshooting.md#find-failed-artifacts).
### Repository verification failures
-#### Get the number of verification failed repositories
-
-```ruby
-Geo::ProjectRegistry.verification_failed('repository').count
-```
-
-#### Find the verification failed repositories
-
-```ruby
-Geo::ProjectRegistry.verification_failed('repository')
-```
-
-### Find repositories that failed to sync
-
-```ruby
-Geo::ProjectRegistry.sync_failed('repository')
-```
+Moved to [Geo replication troubleshooting](../geo/replication/troubleshooting.md#repository-verification-failures).
### Resync repositories
-#### Queue up all repositories for resync. Sidekiq handles each sync
-
-```ruby
-Geo::ProjectRegistry.update_all(resync_repository: true, resync_wiki: true)
-```
-
-#### Sync individual repository now
-
-```ruby
-project = Project.find_by_full_path('<group/project>')
-
-Geo::RepositorySyncService.new(project).execute
-```
+Moved to [Geo replication troubleshooting](../geo/replication/troubleshooting.md#resync-repositories).
### Blob types
-- `Ci::JobArtifact`
-- `Ci::PipelineArtifact`
-- `LfsObject`
-- `MergeRequestDiff`
-- `Packages::PackageFile`
-- `PagesDeployment`
-- `Terraform::StateVersion`
-- `Upload`
-
-`Packages::PackageFile` is used in the following examples, but things generally work the same for the other Blob types.
-
-#### The Replicator
-
-The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it):
-
-```ruby
-model_record = Packages::PackageFile.last
-model_record.replicator.registry.replicator.model_record # just showing that these methods exist
-```
-
-#### Replicate a package file, synchronously, given an ID
-
-```ruby
-model_record = Packages::PackageFile.find(id)
-model_record.replicator.send(:download)
-```
-
-#### Replicate a package file, synchronously, given a registry ID
-
-```ruby
-registry = Geo::PackageFileRegistry.find(registry_id)
-registry.replicator.send(:download)
-```
-
-#### Verify package files on the secondary manually
-
-This iterates over all package files on the secondary, looking at the
-`verification_checksum` stored in the database (which came from the primary)
-and then calculate this value on the secondary to check if they match. This
-does not change anything in the UI:
-
-```ruby
-# Run on secondary
-status = {}
-
-Packages::PackageFile.find_each do |package_file|
- primary_checksum = package_file.verification_checksum
- secondary_checksum = Packages::PackageFile.hexdigest(package_file.file.path)
- verification_status = (primary_checksum == secondary_checksum)
-
- status[verification_status.to_s] ||= []
- status[verification_status.to_s] << package_file.id
-end
-
-# Count how many of each value we get
-status.keys.each {|key| puts "#{key} count: #{status[key].count}"}
-
-# See the output in its entirety
-status
-```
-
-### Repository types newer than project/wiki repositories
-
-- `SnippetRepository`
-- `GroupWikiRepository`
-
-`SnippetRepository` is used in the examples below, but things generally work the same for the other Repository types.
-
-#### The Replicator
-
-The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it).
-
-```ruby
-model_record = SnippetRepository.last
-model_record.replicator.registry.replicator.model_record # just showing that these methods exist
-```
-
-#### Replicate a snippet repository, synchronously, given an ID
-
-```ruby
-model_record = SnippetRepository.find(id)
-model_record.replicator.send(:sync_repository)
-```
-
-#### Replicate a snippet repository, synchronously, given a registry ID
-
-```ruby
-registry = Geo::SnippetRepositoryRegistry.find(registry_id)
-registry.replicator.send(:sync_repository)
-```
+Moved to [Geo replication troubleshooting](../geo/replication/troubleshooting.md#blob-types).
## Generate Service Ping
@@ -1311,3 +637,24 @@ Prints the metrics saved in `conversational_development_index_metrics`.
```shell
rake gitlab:usage_data:generate_and_send
```
+
+## GraphQL
+
+Call a [GraphQL](../../api/graphql/getting_started.md) endpoint through the Rails console:
+
+```ruby
+query = <<~EOQ
+query securityGetProjects($search: String!) {
+ projects(search: $search) {
+ nodes {
+ path
+ }
+ }
+}
+EOQ
+
+variables = { "search": "gitlab" }
+
+result = GitlabSchema.execute(query, variables: variables, context: { current_user: current_user })
+result.to_h
+```
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 429dc79e95f..ce548f9e100 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting a GitLab installation **(FREE SELF)**
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index c1a428018c2..0c6fcd31d1d 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 9e3d3d47a10..8a76d4f88ab 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PostgreSQL **(FREE SELF)**
@@ -109,7 +109,7 @@ This section is for links to information elsewhere in the GitLab documentation.
- Deploying PostgreSQL on Azure Database for PostgreSQL - Flexible Server may result in an error stating `extension "btree_gist" is not allow-listed for "azure_pg_admin" users in Azure Database for PostgreSQL`
- To resolve the above error, [allow-list the extension](https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions) prior to install.
+ To resolve the above error, [allow-list the extension](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions) prior to install.
## Support topics
diff --git a/doc/administration/troubleshooting/ssl.md b/doc/administration/troubleshooting/ssl.md
index c5f3f0ed8d1..245ff9f4982 100644
--- a/doc/administration/troubleshooting/ssl.md
+++ b/doc/administration/troubleshooting/ssl.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -50,7 +50,7 @@ following issues:
- `openssl` works when specifying the path to the certificate:
```shell
- /opt/gitlab/embedded/bin/openssl s_client -CAfile /root/my-cert.crt -connect gitlab.domain.tld:443
+ /opt/gitlab/embedded/bin/openssl s_client -CAfile /root/my-cert.crt -connect gitlab.domain.tld:443 -servername gitlab.domain.tld
```
If you have the previously described issues, add your certificate to
diff --git a/doc/administration/troubleshooting/test_environments.md b/doc/administration/troubleshooting/test_environments.md
index d240103a51c..a249d5bd133 100644
--- a/doc/administration/troubleshooting/test_environments.md
+++ b/doc/administration/troubleshooting/test_environments.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 2dd8f1ed819..f0def7320cc 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Uploads administration **(FREE SELF)**
diff --git a/doc/administration/user_settings.md b/doc/administration/user_settings.md
index 0a3f351c695..a767132db0f 100644
--- a/doc/administration/user_settings.md
+++ b/doc/administration/user_settings.md
@@ -1,17 +1,24 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Modify global user settings **(FREE SELF)**
GitLab administrators can modify user settings for the entire GitLab instance.
-## Prevent new users from creating top-level groups
+## Use configuration files to prevent new users from creating top-level groups
By default, new users can create top-level groups. To disable new users'
-ability to create top-level groups (does not affect existing users' setting):
+ability to create top-level groups (does not affect existing users' setting), GitLab administrators can modify this setting:
+
+- In GitLab 15.5 and later, using either:
+ - The [GitLab UI](../user/admin_area/settings/account_and_limit_settings.md#prevent-users-from-creating-top-level-groups).
+ - The [application setting API](../api/settings.md#change-application-settings).
+- In GitLab 15.4 and earlier, in a configuration file by following the steps in this section.
+
+To disable new users' ability to create top-level groups using the configuation file:
**Omnibus GitLab installations**
diff --git a/doc/administration/whats-new.md b/doc/administration/whats-new.md
index d8003d579ac..d9c8a991577 100644
--- a/doc/administration/whats-new.md
+++ b/doc/administration/whats-new.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: For assistance with this What's new page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this What's new page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
---
# What's new **(FREE)**
diff --git a/doc/administration/wikis/index.md b/doc/administration/wikis/index.md
index 01c175e014e..f3442e23160 100644
--- a/doc/administration/wikis/index.md
+++ b/doc/administration/wikis/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Wiki settings **(FREE SELF)**
diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md
index adaae78f1b5..9eab35a32d8 100644
--- a/doc/api/access_requests.md
+++ b/doc/api/access_requests.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: "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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Group and project access requests API **(FREE)**
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index 2b3cce80257..e5d60587dea 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq queues administration API **(FREE SELF)**
diff --git a/doc/api/alert_management_alerts.md b/doc/api/alert_management_alerts.md
index 2323cecfd6a..bf3d6287341 100644
--- a/doc/api/alert_management_alerts.md
+++ b/doc/api/alert_management_alerts.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Alert Management alerts API **(FREE)**
@@ -79,7 +79,7 @@ Example response:
## Update metric image
```plaintext
-PUT /projects/:id/alert_management_alerts/:alert_iid/metric_image/:image_id
+PUT /projects/:id/alert_management_alerts/:alert_iid/metric_images/:image_id
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 7d613852d23..531d679a34d 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# REST API resources **(FREE)**
@@ -99,7 +99,7 @@ The following API resources are available in the project context:
| [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` |
-| [Terraform modules](packages/terraform-modules.md) | `/projects/:id/packages/terraform/mdoules` (also available standalone) |
+| [Terraform modules](packages/terraform-modules.md) | `/projects/:id/packages/terraform/modules` (also available standalone) |
| [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` |
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index 7ad79fd66fe..f8926f8a91d 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Appearance API **(FREE SELF)**
diff --git a/doc/api/applications.md b/doc/api/applications.md
index aeb6a0452c5..f7b646d2351 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Applications API **(FREE)**
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 5bff3cf49fc..db89262c84f 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Audit Events API **(PREMIUM)**
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index bc47d3a4d9e..d6b9c9f70b7 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Avatar API **(FREE)**
diff --git a/doc/api/award_emoji.md b/doc/api/award_emoji.md
index 5b350dd88c6..ca6761ed6be 100644
--- a/doc/api/award_emoji.md
+++ b/doc/api/award_emoji.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Award emoji API **(FREE)**
diff --git a/doc/api/boards.md b/doc/api/boards.md
index ab9bd4ea3f1..79f5cca4a0d 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project issue boards API **(FREE)**
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 4e2a0306845..0c9df88cf85 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
@@ -84,7 +84,7 @@ Parameters:
| Attribute | Type | Required | Description |
|:----------|:---------------|:---------|:-------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `branch` | string | yes | Name of the branch. |
+| `branch` | string | yes | [URL-encoded name](index.md#namespaced-path-encoding) of the branch. |
Example request:
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index 6c95bf2fda5..cc777a8bf53 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Broadcast Messages API **(FREE SELF)**
diff --git a/doc/api/bulk_imports.md b/doc/api/bulk_imports.md
index 913dc6ce4f1..e18a77df6df 100644
--- a/doc/api/bulk_imports.md
+++ b/doc/api/bulk_imports.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Migrations (Bulk Imports) API **(FREE)**
@@ -150,11 +150,14 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
"updated_at": "2021-06-24T10:40:46.590Z",
"failures": [
{
- "pipeline_class": "BulkImports::Groups::Pipelines::GroupPipeline",
- "pipeline_step": "extractor",
+ "relation": "group",
+ "step": "extractor",
+ "exception_message": "Error!",
"exception_class": "Exception",
"correlation_id_value": "dfcf583058ed4508e4c7c617bd7f0edd",
- "created_at": "2021-06-24T10:40:46.495Z"
+ "created_at": "2021-06-24T10:40:46.495Z",
+ "pipeline_class": "BulkImports::Groups::Pipelines::GroupPipeline",
+ "pipeline_step": "extractor"
}
]
}
diff --git a/doc/api/cluster_agents.md b/doc/api/cluster_agents.md
index 16eed70fd48..718871884fb 100644
--- a/doc/api/cluster_agents.md
+++ b/doc/api/cluster_agents.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Agents API **(FREE)**
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 3b9a72e1568..f08fe5ba881 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Commits API **(FREE)**
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index f23641abb4f..6e8911df098 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Container Registry API **(FREE)**
diff --git a/doc/api/custom_attributes.md b/doc/api/custom_attributes.md
index e15ed4bceee..5ce2aa34744 100644
--- a/doc/api/custom_attributes.md
+++ b/doc/api/custom_attributes.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Custom Attributes API **(FREE SELF)**
diff --git a/doc/api/dependencies.md b/doc/api/dependencies.md
index 85ad6085fb2..dce928046bc 100644
--- a/doc/api/dependencies.md
+++ b/doc/api/dependencies.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependencies API **(ULTIMATE)**
@@ -49,18 +49,34 @@ Example response:
"version": "5.0.1",
"package_manager": "bundler",
"dependency_file_path": "Gemfile.lock",
- "vulnerabilities": [{
- "name": "DDoS",
- "severity": "unknown"
- }]
+ "vulnerabilities": [
+ {
+ "name": "DDoS",
+ "severity": "unknown",
+ "id": 144827,
+ "url": "https://gitlab.example.com/group/project/-/security/vulnerabilities/144827"
+ }
+ ],
+ "licenses": [
+ {
+ "name": "MIT",
+ "url": "https://opensource.org/licenses/MIT"
+ }
+ ]
},
{
- "name": "hanami",
- "version": "1.3.1",
- "package_manager": "bundler",
- "dependency_file_path": "Gemfile.lock",
- "vulnerabilities": []
- }
+ "name": "hanami",
+ "version": "1.3.1",
+ "package_manager": "bundler",
+ "dependency_file_path": "Gemfile.lock",
+ "vulnerabilities": [],
+ "licenses": [
+ {
+ "name": "MIT",
+ "url": "https://opensource.org/licenses/MIT"
+ }
+ ]
+ }
]
```
diff --git a/doc/api/dependency_proxy.md b/doc/api/dependency_proxy.md
index 028584e69ff..05e144f5810 100644
--- a/doc/api/dependency_proxy.md
+++ b/doc/api/dependency_proxy.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency Proxy API **(FREE)**
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 40641c6e2f7..bc5852db457 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy keys API **(FREE)**
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index ace7e55f882..5c4c99f3ba3 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy Tokens API **(FREE)**
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 8b99c21a385..9618d57013f 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 60ce10590e1..e82f6927e0b 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api
---
diff --git a/doc/api/dora/metrics.md b/doc/api/dora/metrics.md
index 543b6583fde..d902f5eb91f 100644
--- a/doc/api/dora/metrics.md
+++ b/doc/api/dora/metrics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api
---
diff --git a/doc/api/environments.md b/doc/api/environments.md
index 3f5f711e10b..0f969ea4fd3 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -342,6 +342,7 @@ It schedules for deletion multiple environments that have already been
[stopped](../ci/environments/index.md#stop-an-environment) and
are [in the review app folder](../ci/review_apps/index.md).
The actual deletion is performed after 1 week from the time of execution.
+By default, it only deletes environments 30 days or older. You can change this default using the `before` parameter.
```plaintext
DELETE /projects/:id/environments/review_apps
diff --git a/doc/api/epic_issues.md b/doc/api/epic_issues.md
index dfc54cd81aa..4bbd0b21136 100644
--- a/doc/api/epic_issues.md
+++ b/doc/api/epic_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Epic Issues API **(PREMIUM)**
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
index d87b44f43a7..91560512ffc 100644
--- a/doc/api/epic_links.md
+++ b/doc/api/epic_links.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Epic Links API **(ULTIMATE)**
diff --git a/doc/api/epics.md b/doc/api/epics.md
index de20af08915..85a127696f6 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Epics API **(PREMIUM)**
diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md
index dbf832b301f..c8f795ed88c 100644
--- a/doc/api/error_tracking.md
+++ b/doc/api/error_tracking.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Error Tracking settings API **(FREE)**
diff --git a/doc/api/events.md b/doc/api/events.md
index e4490459030..632f573be47 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Events API **(FREE)**
diff --git a/doc/api/experiments.md b/doc/api/experiments.md
index 6393a358e51..8e34868b282 100644
--- a/doc/api/experiments.md
+++ b/doc/api/experiments.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Experiments API (GitLab team only) **(FREE SAAS)**
diff --git a/doc/api/feature_flag_specs.md b/doc/api/feature_flag_specs.md
index f2853efc5f2..b549c790aaa 100644
--- a/doc/api/feature_flag_specs.md
+++ b/doc/api/feature_flag_specs.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Feature Flag Specs API **(PREMIUM)**
diff --git a/doc/api/feature_flag_user_lists.md b/doc/api/feature_flag_user_lists.md
index 46ed44d8808..ef65da64668 100644
--- a/doc/api/feature_flag_user_lists.md
+++ b/doc/api/feature_flag_user_lists.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Feature flag user lists API **(FREE)**
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index b00917674b0..c4d766a6319 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -1,19 +1,19 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Feature Flags API **(FREE)**
+# Feature flags API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
-API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
+API for accessing resources of [GitLab feature flags](../operations/feature_flags.md).
-Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API.
+Users with Developer or higher [permissions](../user/permissions.md) can access the feature flag API.
-## Feature Flags pagination
+## Feature flags pagination
By default, `GET` requests return 20 results at a time because the API results
are [paginated](index.md#pagination).
@@ -144,7 +144,7 @@ POST /projects/:id/feature_flags
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `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. |
-| `version` | string | yes | The version of the feature flag. Must be `new_version_flag`. Omit or set to `legacy_flag` to create a Legacy Feature Flag. |
+| `version` | string | yes | The version of the feature flag. Must be `new_version_flag`. Omit or set to `legacy_flag` to create a Legacy feature flag. |
| `description` | string | no | The description of the feature flag. |
| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). |
diff --git a/doc/api/features.md b/doc/api/features.md
index f006fa07188..6f3af683020 100644
--- a/doc/api/features.md
+++ b/doc/api/features.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Feature flags API **(FREE SELF)**
diff --git a/doc/api/freeze_periods.md b/doc/api/freeze_periods.md
index 6dc4e8745d6..36d069df607 100644
--- a/doc/api/freeze_periods.md
+++ b/doc/api/freeze_periods.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index b5b920ec0cd..fe25b6661a0 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo Nodes API **(PREMIUM SELF)**
@@ -339,10 +339,6 @@ Example response:
"job_artifacts_failed_count": null,
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "0.00%",
- "container_repositories_count": 3,
- "container_repositories_synced_count": null,
- "container_repositories_failed_count": null,
- "container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
"design_repositories_synced_count": null,
"design_repositories_failed_count": null,
@@ -507,7 +503,13 @@ Example response:
"ci_secure_files_verification_failed_count": 0,
"ci_secure_files_synced_in_percentage": "100.00%",
"ci_secure_files_verified_in_percentage": "100.00%",
- "ci_secure_files_synced_missing_on_primary_count": 0,
+ "ci_secure_files_synced_missing_on_primary_count": 0,
+ "container_repositories_count": 5,
+ "container_repositories_synced_count": 5,
+ "container_repositories_failed_count": 0,
+ "container_repositories_registry_count": 5,
+ "container_repositories_synced_in_percentage": "100.00%",
+ "container_repositories_synced_missing_on_primary_count": 0,
},
{
"geo_node_id": 2,
@@ -533,10 +535,6 @@ Example response:
"job_artifacts_failed_count": 1,
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "50.00%",
- "container_repositories_count": 3,
- "container_repositories_synced_count": null,
- "container_repositories_failed_count": null,
- "container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
"design_repositories_synced_count": null,
"design_repositories_failed_count": null,
@@ -677,6 +675,12 @@ Example response:
"job_artifacts_synced_in_percentage": "100.00%",
"job_artifacts_verified_in_percentage": "100.00%",
"job_artifacts_synced_missing_on_primary_count": 0,
+ "container_repositories_count": 5,
+ "container_repositories_synced_count": 5,
+ "container_repositories_failed_count": 0,
+ "container_repositories_registry_count": 5,
+ "container_repositories_synced_in_percentage": "100.00%",
+ "container_repositories_synced_missing_on_primary_count": 0,
}
]
```
@@ -718,10 +722,6 @@ Example response:
"job_artifacts_failed_count": 1,
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "50.00%",
- "container_repositories_count": 3,
- "container_repositories_synced_count": null,
- "container_repositories_failed_count": null,
- "container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
"design_repositories_synced_count": null,
"design_repositories_failed_count": null,
@@ -856,6 +856,12 @@ Example response:
"ci_secure_files_synced_in_percentage": "100.00%",
"ci_secure_files_verified_in_percentage": "100.00%",
"ci_secure_files_synced_missing_on_primary_count": 0,
+ "container_repositories_count": 5,
+ "container_repositories_synced_count": 5,
+ "container_repositories_failed_count": 0,
+ "container_repositories_registry_count": 5,
+ "container_repositories_synced_in_percentage": "100.00%",
+ "container_repositories_synced_missing_on_primary_count": 0,
}
```
diff --git a/doc/api/graphql/audit_report.md b/doc/api/graphql/audit_report.md
index dc7eb10b810..2f96bc5ecdd 100644
--- a/doc/api/graphql/audit_report.md
+++ b/doc/api/graphql/audit_report.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up an Audit Report with GraphQL **(FREE)**
diff --git a/doc/api/graphql/custom_emoji.md b/doc/api/graphql/custom_emoji.md
index e7fd9837b0f..ea90b02a069 100644
--- a/doc/api/graphql/custom_emoji.md
+++ b/doc/api/graphql/custom_emoji.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use custom emojis with GraphQL **(FREE)**
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index 386ef6c403b..20fb2f030f2 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Get started with GitLab GraphQL API **(FREE)**
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index eab48d65742..40e1ed115a3 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL API **(FREE)**
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index cf218d6e2d7..11a60671008 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
<!---
@@ -226,6 +226,22 @@ Returns [`Iteration`](#iteration).
| ---- | ---- | ----------- |
| <a id="queryiterationid"></a>`id` | [`IterationID!`](#iterationid) | Find an iteration by its ID. |
+### `Query.jobs`
+
+All jobs on this GitLab instance.
+
+Returns [`CiJobConnection`](#cijobconnection).
+
+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="queryjobsstatuses"></a>`statuses` | [`[CiJobStatus!]`](#cijobstatus) | Filter jobs by status. |
+
### `Query.licenseHistoryEntries`
Fields related to entries in the license history.
@@ -320,7 +336,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="queryprojectsmembership"></a>`membership` | [`Boolean`](#boolean) | Return only projects that the current user is a member of. |
| <a id="queryprojectssearch"></a>`search` | [`String`](#string) | Search query, which can be for the project name, a path, or a description. |
| <a id="queryprojectssearchnamespaces"></a>`searchNamespaces` | [`Boolean`](#boolean) | Include namespace in project search. |
-| <a id="queryprojectssort"></a>`sort` | [`String`](#string) | Sort order of results. Format: '<field_name>_<sort_direction>', for example: 'id_desc' or 'name_asc'. |
+| <a id="queryprojectssort"></a>`sort` | [`String`](#string) | Sort order of results. Format: `<field_name>_<sort_direction>`, for example: `id_desc` or `name_asc`. |
| <a id="queryprojectstopics"></a>`topics` | [`[String!]`](#string) | Filter projects by topics. |
### `Query.queryComplexity`
@@ -640,6 +656,7 @@ Input type: `AdminSidekiqQueuesDeleteJobsInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationadminsidekiqqueuesdeletejobsartifactsize"></a>`artifactSize` | [`String`](#string) | Delete jobs matching artifact_size in the context metadata. |
+| <a id="mutationadminsidekiqqueuesdeletejobsartifactusedcdn"></a>`artifactUsedCdn` | [`String`](#string) | Delete jobs matching artifact_used_cdn in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobsartifactsdependenciescount"></a>`artifactsDependenciesCount` | [`String`](#string) | Delete jobs matching artifacts_dependencies_count in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobsartifactsdependenciessize"></a>`artifactsDependenciesSize` | [`String`](#string) | Delete jobs matching artifacts_dependencies_size in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobscallerid"></a>`callerId` | [`String`](#string) | Delete jobs matching caller_id in the context metadata. |
@@ -1011,7 +1028,8 @@ Input type: `CiCdSettingsUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationcicdsettingsupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcicdsettingsupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Full Path of the project the settings belong to. |
-| <a id="mutationcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI job tokens generated in this project have restricted access to resources. |
+| <a id="mutationcicdsettingsupdateinboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in other projects have restricted access to this project. |
+| <a id="mutationcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in this project have restricted access to other projects. |
| <a id="mutationcicdsettingsupdatekeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates if the latest artifact should be kept for this project. |
| <a id="mutationcicdsettingsupdatemergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates if merge pipelines are enabled for the project. |
| <a id="mutationcicdsettingsupdatemergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Indicates if merge trains are enabled for the project. |
@@ -1989,6 +2007,7 @@ Input type: `DastSiteProfileCreateInput`
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofilecreatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. Will not be saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofilecreatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
@@ -2036,6 +2055,7 @@ Input type: `DastSiteProfileUpdateInput`
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofileupdatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. Will not be saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofileupdatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
@@ -2406,6 +2426,24 @@ Input type: `DestroyPackageFilesInput`
| <a id="mutationdestroypackagefilesclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationdestroypackagefileserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.destroyPackages`
+
+Input type: `DestroyPackagesInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationdestroypackagesclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationdestroypackagesids"></a>`ids` | [`[PackagesPackageID!]!`](#packagespackageid) | Global IDs of the Packages. Max 20. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationdestroypackagesclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationdestroypackageserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.destroySnippet`
Input type: `DestroySnippetInput`
@@ -2874,6 +2912,7 @@ Input type: `GitlabSubscriptionActivateInput`
| ---- | ---- | ----------- |
| <a id="mutationgitlabsubscriptionactivateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationgitlabsubscriptionactivateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationgitlabsubscriptionactivatefuturesubscriptions"></a>`futureSubscriptions` | [`[SubscriptionFutureEntry!]`](#subscriptionfutureentry) | Array of future subscriptions. |
| <a id="mutationgitlabsubscriptionactivatelicense"></a>`license` | [`CurrentLicense`](#currentlicense) | Current license. |
### `Mutation.groupUpdate`
@@ -4141,6 +4180,24 @@ Input type: `PipelineRetryInput`
| <a id="mutationpipelineretryerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationpipelineretrypipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline after mutation. |
+### `Mutation.pipelineScheduleDelete`
+
+Input type: `PipelineScheduleDeleteInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationpipelinescheduledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationpipelinescheduledeleteid"></a>`id` | [`CiPipelineScheduleID!`](#cipipelinescheduleid) | ID of the pipeline schedule to mutate. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationpipelinescheduledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationpipelinescheduledeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.projectCiCdSettingsUpdate`
Input type: `ProjectCiCdSettingsUpdateInput`
@@ -4151,7 +4208,8 @@ Input type: `ProjectCiCdSettingsUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationprojectcicdsettingsupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationprojectcicdsettingsupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Full Path of the project the settings belong to. |
-| <a id="mutationprojectcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI job tokens generated in this project have restricted access to resources. |
+| <a id="mutationprojectcicdsettingsupdateinboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in other projects have restricted access to this project. |
+| <a id="mutationprojectcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in this project have restricted access to other projects. |
| <a id="mutationprojectcicdsettingsupdatekeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates if the latest artifact should be kept for this project. |
| <a id="mutationprojectcicdsettingsupdatemergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates if merge pipelines are enabled for the project. |
| <a id="mutationprojectcicdsettingsupdatemergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Indicates if merge trains are enabled for the project. |
@@ -5350,9 +5408,15 @@ Input type: `UpdateNamespacePackageSettingsInput`
| <a id="mutationupdatenamespacepackagesettingsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdatenamespacepackagesettingsgenericduplicateexceptionregex"></a>`genericDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="mutationupdatenamespacepackagesettingsgenericduplicatesallowed"></a>`genericDuplicatesAllowed` | [`Boolean`](#boolean) | Indicates whether duplicate generic packages are allowed for this namespace. |
+| <a id="mutationupdatenamespacepackagesettingslockmavenpackagerequestsforwarding"></a>`lockMavenPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether Maven package forwarding is locked for all descendent namespaces. |
+| <a id="mutationupdatenamespacepackagesettingslocknpmpackagerequestsforwarding"></a>`lockNpmPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether npm package forwarding is locked for all descendent namespaces. |
+| <a id="mutationupdatenamespacepackagesettingslockpypipackagerequestsforwarding"></a>`lockPypiPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether PyPI package forwarding is locked for all descendent namespaces. |
| <a id="mutationupdatenamespacepackagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="mutationupdatenamespacepackagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. |
+| <a id="mutationupdatenamespacepackagesettingsmavenpackagerequestsforwarding"></a>`mavenPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether Maven package forwarding is allowed for this namespace. |
| <a id="mutationupdatenamespacepackagesettingsnamespacepath"></a>`namespacePath` | [`ID!`](#id) | Namespace path where the namespace package setting is located. |
+| <a id="mutationupdatenamespacepackagesettingsnpmpackagerequestsforwarding"></a>`npmPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether npm package forwarding is allowed for this namespace. |
+| <a id="mutationupdatenamespacepackagesettingspypipackagerequestsforwarding"></a>`pypiPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether PyPI package forwarding is allowed for this namespace. |
#### Fields
@@ -5630,6 +5694,10 @@ Input type: `VulnerabilityExternalIssueLinkDestroyInput`
### `Mutation.vulnerabilityFindingDismiss`
+WARNING:
+**Deprecated** in 15.5.
+Use VulnerabilityDismiss for vulnerabilities or SecurityFindingDismiss for pipeline findings.
+
Input type: `VulnerabilityFindingDismissInput`
#### Arguments
@@ -5818,8 +5886,10 @@ Input type: `WorkItemUpdateInput`
| <a id="mutationworkitemupdatehierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyUpdateInput`](#workitemwidgethierarchyupdateinput) | Input for hierarchy widget. |
| <a id="mutationworkitemupdateid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
| <a id="mutationworkitemupdateiterationwidget"></a>`iterationWidget` | [`WorkItemWidgetIterationInput`](#workitemwidgetiterationinput) | Input for iteration widget. |
+| <a id="mutationworkitemupdatelabelswidget"></a>`labelsWidget` | [`WorkItemWidgetLabelsUpdateInput`](#workitemwidgetlabelsupdateinput) | Input for labels widget. |
| <a id="mutationworkitemupdatestartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
+| <a id="mutationworkitemupdatestatuswidget"></a>`statusWidget` | [`StatusInput`](#statusinput) | Input for status widget. |
| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
| <a id="mutationworkitemupdateweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
@@ -5858,32 +5928,6 @@ Input type: `WorkItemUpdateTaskInput`
| <a id="mutationworkitemupdatetasktask"></a>`task` | [`WorkItem`](#workitem) | Updated task. |
| <a id="mutationworkitemupdatetaskworkitem"></a>`workItem` | [`WorkItem`](#workitem) | Updated work item. |
-### `Mutation.workItemUpdateWidgets`
-
-Updates the attributes of a work item's widgets by global ID. Available only when feature flag `work_items` is enabled.
-
-WARNING:
-**Introduced** in 15.1.
-This feature is in Alpha. It can be changed or removed at any time.
-
-Input type: `WorkItemUpdateWidgetsInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationworkitemupdatewidgetsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationworkitemupdatewidgetsdescriptionwidget"></a>`descriptionWidget` | [`WorkItemWidgetDescriptionInput`](#workitemwidgetdescriptioninput) | Input for description widget. |
-| <a id="mutationworkitemupdatewidgetsid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationworkitemupdatewidgetsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationworkitemupdatewidgetserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationworkitemupdatewidgetsworkitem"></a>`workItem` | [`WorkItem`](#workitem) | Updated work item. |
-
## Connections
Some types in our schema are `Connection` types - they represent a paginated
@@ -6015,6 +6059,29 @@ The edge type for [`AlertManagementIntegration`](#alertmanagementintegration).
| <a id="alertmanagementintegrationedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="alertmanagementintegrationedgenode"></a>`node` | [`AlertManagementIntegration`](#alertmanagementintegration) | The item at the end of the edge. |
+#### `ApprovalProjectRuleConnection`
+
+The connection type for [`ApprovalProjectRule`](#approvalprojectrule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="approvalprojectruleconnectionedges"></a>`edges` | [`[ApprovalProjectRuleEdge]`](#approvalprojectruleedge) | A list of edges. |
+| <a id="approvalprojectruleconnectionnodes"></a>`nodes` | [`[ApprovalProjectRule]`](#approvalprojectrule) | A list of nodes. |
+| <a id="approvalprojectruleconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ApprovalProjectRuleEdge`
+
+The edge type for [`ApprovalProjectRule`](#approvalprojectrule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="approvalprojectruleedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="approvalprojectruleedgenode"></a>`node` | [`ApprovalProjectRule`](#approvalprojectrule) | The item at the end of the edge. |
+
#### `AuditEventStreamingHeaderConnection`
The connection type for [`AuditEventStreamingHeader`](#auditeventstreamingheader).
@@ -6821,6 +6888,29 @@ The edge type for [`ContainerRepository`](#containerrepository).
| <a id="containerrepositoryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="containerrepositoryedgenode"></a>`node` | [`ContainerRepository`](#containerrepository) | The item at the end of the edge. |
+#### `ContainerRepositoryRegistryConnection`
+
+The connection type for [`ContainerRepositoryRegistry`](#containerrepositoryregistry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="containerrepositoryregistryconnectionedges"></a>`edges` | [`[ContainerRepositoryRegistryEdge]`](#containerrepositoryregistryedge) | A list of edges. |
+| <a id="containerrepositoryregistryconnectionnodes"></a>`nodes` | [`[ContainerRepositoryRegistry]`](#containerrepositoryregistry) | A list of nodes. |
+| <a id="containerrepositoryregistryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ContainerRepositoryRegistryEdge`
+
+The edge type for [`ContainerRepositoryRegistry`](#containerrepositoryregistry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="containerrepositoryregistryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="containerrepositoryregistryedgenode"></a>`node` | [`ContainerRepositoryRegistry`](#containerrepositoryregistry) | The item at the end of the edge. |
+
#### `ContainerRepositoryTagConnection`
The connection type for [`ContainerRepositoryTag`](#containerrepositorytag).
@@ -8351,6 +8441,30 @@ The edge type for [`Pipeline`](#pipeline).
| <a id="pipelineedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="pipelineedgenode"></a>`node` | [`Pipeline`](#pipeline) | The item at the end of the edge. |
+#### `PipelineScheduleConnection`
+
+The connection type for [`PipelineSchedule`](#pipelineschedule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pipelinescheduleconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
+| <a id="pipelinescheduleconnectionedges"></a>`edges` | [`[PipelineScheduleEdge]`](#pipelinescheduleedge) | A list of edges. |
+| <a id="pipelinescheduleconnectionnodes"></a>`nodes` | [`[PipelineSchedule]`](#pipelineschedule) | A list of nodes. |
+| <a id="pipelinescheduleconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `PipelineScheduleEdge`
+
+The edge type for [`PipelineSchedule`](#pipelineschedule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pipelinescheduleedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="pipelinescheduleedgenode"></a>`node` | [`PipelineSchedule`](#pipelineschedule) | The item at the end of the edge. |
+
#### `PipelineSecurityReportFindingConnection`
The connection type for [`PipelineSecurityReportFinding`](#pipelinesecurityreportfinding).
@@ -8421,6 +8535,75 @@ The edge type for [`ProjectMember`](#projectmember).
| <a id="projectmemberedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="projectmemberedgenode"></a>`node` | [`ProjectMember`](#projectmember) | The item at the end of the edge. |
+#### `ProtectedEnvironmentApprovalRuleConnection`
+
+The connection type for [`ProtectedEnvironmentApprovalRule`](#protectedenvironmentapprovalrule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentapprovalruleconnectionedges"></a>`edges` | [`[ProtectedEnvironmentApprovalRuleEdge]`](#protectedenvironmentapprovalruleedge) | A list of edges. |
+| <a id="protectedenvironmentapprovalruleconnectionnodes"></a>`nodes` | [`[ProtectedEnvironmentApprovalRule]`](#protectedenvironmentapprovalrule) | A list of nodes. |
+| <a id="protectedenvironmentapprovalruleconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ProtectedEnvironmentApprovalRuleEdge`
+
+The edge type for [`ProtectedEnvironmentApprovalRule`](#protectedenvironmentapprovalrule).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentapprovalruleedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="protectedenvironmentapprovalruleedgenode"></a>`node` | [`ProtectedEnvironmentApprovalRule`](#protectedenvironmentapprovalrule) | The item at the end of the edge. |
+
+#### `ProtectedEnvironmentConnection`
+
+The connection type for [`ProtectedEnvironment`](#protectedenvironment).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentconnectionedges"></a>`edges` | [`[ProtectedEnvironmentEdge]`](#protectedenvironmentedge) | A list of edges. |
+| <a id="protectedenvironmentconnectionnodes"></a>`nodes` | [`[ProtectedEnvironment]`](#protectedenvironment) | A list of nodes. |
+| <a id="protectedenvironmentconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ProtectedEnvironmentDeployAccessLevelConnection`
+
+The connection type for [`ProtectedEnvironmentDeployAccessLevel`](#protectedenvironmentdeployaccesslevel).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentdeployaccesslevelconnectionedges"></a>`edges` | [`[ProtectedEnvironmentDeployAccessLevelEdge]`](#protectedenvironmentdeployaccessleveledge) | A list of edges. |
+| <a id="protectedenvironmentdeployaccesslevelconnectionnodes"></a>`nodes` | [`[ProtectedEnvironmentDeployAccessLevel]`](#protectedenvironmentdeployaccesslevel) | A list of nodes. |
+| <a id="protectedenvironmentdeployaccesslevelconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ProtectedEnvironmentDeployAccessLevelEdge`
+
+The edge type for [`ProtectedEnvironmentDeployAccessLevel`](#protectedenvironmentdeployaccesslevel).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentdeployaccessleveledgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="protectedenvironmentdeployaccessleveledgenode"></a>`node` | [`ProtectedEnvironmentDeployAccessLevel`](#protectedenvironmentdeployaccesslevel) | The item at the end of the edge. |
+
+#### `ProtectedEnvironmentEdge`
+
+The edge type for [`ProtectedEnvironment`](#protectedenvironment).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="protectedenvironmentedgenode"></a>`node` | [`ProtectedEnvironment`](#protectedenvironment) | The item at the end of the edge. |
+
#### `PushAccessLevelConnection`
The connection type for [`PushAccessLevel`](#pushaccesslevel).
@@ -9732,6 +9915,20 @@ An API Fuzzing scan profile.
| <a id="apifuzzingscanprofilename"></a>`name` | [`String`](#string) | Unique name of the profile. |
| <a id="apifuzzingscanprofileyaml"></a>`yaml` | [`String`](#string) | Syntax highlighted HTML representation of the YAML. |
+### `ApprovalProjectRule`
+
+Describes a project approval rule regarding who can approve merge requests.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="approvalprojectruleapprovalsrequired"></a>`approvalsRequired` | [`Int`](#int) | Number of required approvals. |
+| <a id="approvalprojectruleeligibleapprovers"></a>`eligibleApprovers` | [`UserCoreConnection`](#usercoreconnection) | List of users eligible to approve merge requests for this approval rule. (see [Connections](#connections)) |
+| <a id="approvalprojectruleid"></a>`id` | [`GlobalID!`](#globalid) | ID of the rule. |
+| <a id="approvalprojectrulename"></a>`name` | [`String`](#string) | Name of the rule. |
+| <a id="approvalprojectruletype"></a>`type` | [`ApprovalRuleType`](#approvalruletype) | Type of the rule. |
+
### `ApprovalRule`
Describes a rule for who can approve merge requests.
@@ -10145,8 +10342,10 @@ List of branch rules for a project, grouped by branch name.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="branchruleapprovalrules"></a>`approvalRules` | [`ApprovalProjectRuleConnection`](#approvalprojectruleconnection) | Merge request approval rules configured for this branch rule. (see [Connections](#connections)) |
| <a id="branchrulebranchprotection"></a>`branchProtection` | [`BranchProtection!`](#branchprotection) | Branch protections configured for this branch rule. |
| <a id="branchrulecreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the branch rule was created. |
+| <a id="branchruleisdefault"></a>`isDefault` | [`Boolean!`](#boolean) | Check if this branch rule protects the project's default branch. |
| <a id="branchrulename"></a>`name` | [`String!`](#string) | Branch name, with wildcards, for the branch rules. |
| <a id="branchruleupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the branch rule was last updated. |
@@ -10274,6 +10473,7 @@ CI/CD config variables.
| <a id="ciconfigvariabledescription"></a>`description` | [`String`](#string) | Description for the CI/CD config variable. |
| <a id="ciconfigvariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
| <a id="ciconfigvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="ciconfigvariablevalueoptions"></a>`valueOptions` | [`[String!]`](#string) | Value options for the variable. |
### `CiGroup`
@@ -10330,6 +10530,7 @@ CI/CD variables for a GitLab instance.
| <a id="cijobactive"></a>`active` | [`Boolean!`](#boolean) | Indicates the job is active. |
| <a id="cijoballowfailure"></a>`allowFailure` | [`Boolean!`](#boolean) | Whether the job is allowed to fail. |
| <a id="cijobartifacts"></a>`artifacts` | [`CiJobArtifactConnection`](#cijobartifactconnection) | Artifacts generated by the job. (see [Connections](#connections)) |
+| <a id="cijobbrowseartifactspath"></a>`browseArtifactsPath` | [`String`](#string) | URL for browsing the artifact's archive. |
| <a id="cijobcancelable"></a>`cancelable` | [`Boolean!`](#boolean) | Indicates the job can be canceled. |
| <a id="cijobcommitpath"></a>`commitPath` | [`String`](#string) | Path to the commit that triggered the job. |
| <a id="cijobcoverage"></a>`coverage` | [`Float`](#float) | Coverage level of the job. |
@@ -10903,6 +11104,25 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="containerrepositorydetailstagsname"></a>`name` | [`String`](#string) | Search by tag name. |
| <a id="containerrepositorydetailstagssort"></a>`sort` | [`ContainerRepositoryTagSort`](#containerrepositorytagsort) | Sort tags by these criteria. |
+### `ContainerRepositoryRegistry`
+
+Represents the Geo replication and verification state of an Container Repository.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="containerrepositoryregistrycontainerrepositoryid"></a>`containerRepositoryId` | [`ID!`](#id) | ID of the ContainerRepository. |
+| <a id="containerrepositoryregistrycreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp when the ContainerRepositoryRegistry was created. |
+| <a id="containerrepositoryregistryid"></a>`id` | [`ID!`](#id) | ID of the ContainerRepositoryRegistry. |
+| <a id="containerrepositoryregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the ContainerRepositoryRegistry. |
+| <a id="containerrepositoryregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the ContainerRepositoryRegistry. |
+| <a id="containerrepositoryregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the ContainerRepositoryRegistry is resynced. |
+| <a id="containerrepositoryregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the ContainerRepositoryRegistry. |
+| <a id="containerrepositoryregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the ContainerRepositoryRegistry. |
+| <a id="containerrepositoryregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the ContainerRepositoryRegistry is reverified. |
+| <a id="containerrepositoryregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the ContainerRepositoryRegistry. |
+
### `ContainerRepositoryTag`
A tag from a container repository.
@@ -11090,6 +11310,7 @@ Represents a DAST Site Profile.
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | Name of the site profile. |
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="dastsiteprofilescanfilepath"></a>`scanFilePath` | [`String`](#string) | Scan File Path used as input for the scanner. Will always return `null` if `dast_api_scanner` feature flag is disabled. |
| <a id="dastsiteprofilescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method used by the scanner. Always returns `null` if `dast_api_scanner` feature flag is disabled. |
| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
@@ -11133,6 +11354,7 @@ Represents a DAST Site Validation.
| <a id="dastsitevalidationid"></a>`id` | [`DastSiteValidationID!`](#dastsitevalidationid) | Global ID of the site validation. |
| <a id="dastsitevalidationnormalizedtargeturl"></a>`normalizedTargetUrl` | [`String`](#string) | Normalized URL of the target to be validated. |
| <a id="dastsitevalidationstatus"></a>`status` | [`DastSiteProfileValidationStatusEnum!`](#dastsiteprofilevalidationstatusenum) | Status of the site validation. |
+| <a id="dastsitevalidationvalidationstartedat"></a>`validationStartedAt` | [`Time`](#time) | Timestamp of when the validation started. |
### `DeleteJobsResponse`
@@ -11685,6 +11907,7 @@ Describes where code is deployed for a project.
| <a id="environmentlatestopenedmostseverealert"></a>`latestOpenedMostSevereAlert` | [`AlertManagementAlert`](#alertmanagementalert) | Most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. |
| <a id="environmentname"></a>`name` | [`String!`](#string) | Human-readable name of the environment. |
| <a id="environmentpath"></a>`path` | [`String!`](#string) | Path to the environment. |
+| <a id="environmentprotectedenvironments"></a>`protectedEnvironments` | [`ProtectedEnvironmentConnection`](#protectedenvironmentconnection) | Protected Environments for the environment. (see [Connections](#connections)) |
| <a id="environmentslug"></a>`slug` | [`String`](#string) | Slug of the environment. |
| <a id="environmentstate"></a>`state` | [`String!`](#string) | State of the environment, for example: available/stopped. |
| <a id="environmenttier"></a>`tier` | [`DeploymentTier`](#deploymenttier) | Deployment tier of the environment. |
@@ -11694,7 +11917,7 @@ Describes where code is deployed for a project.
##### `Environment.deployments`
-Deployments of the environment. This field can only be resolved for one project in any single request.
+Deployments of the environment. This field can only be resolved for one environment in any single request.
Returns [`DeploymentConnection`](#deploymentconnection).
@@ -12279,6 +12502,28 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="geonodecisecurefileregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
| <a id="geonodecisecurefileregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
+##### `GeoNode.containerRepositoryRegistries`
+
+Find Container Repository registries on this Geo node. Ignored if `geo_container_repository_replication` feature flag is disabled.
+
+WARNING:
+**Introduced** in 15.5.
+This feature is in Alpha. It can be changed or removed at any time.
+
+Returns [`ContainerRepositoryRegistryConnection`](#containerrepositoryregistryconnection).
+
+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="geonodecontainerrepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodecontainerrepositoryregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodecontainerrepositoryregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
+
##### `GeoNode.groupWikiRepositoryRegistries`
Find group wiki repository registries on this Geo node.
@@ -12775,6 +13020,21 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupepicsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Epics updated after this date. |
| <a id="groupepicsupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Epics updated before this date. |
+##### `Group.gitlabSubscriptionsPreviewBillableUserChange`
+
+Preview Billable User Changes.
+
+Returns [`PreviewBillableUserChange`](#previewbillableuserchange).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="groupgitlabsubscriptionspreviewbillableuserchangeaddgroupid"></a>`addGroupId` | [`Int`](#int) | Group ID to add. |
+| <a id="groupgitlabsubscriptionspreviewbillableuserchangeadduseremails"></a>`addUserEmails` | [`[String!]`](#string) | User emails to add. |
+| <a id="groupgitlabsubscriptionspreviewbillableuserchangeadduserids"></a>`addUserIds` | [`[Int!]`](#int) | User IDs to add. |
+| <a id="groupgitlabsubscriptionspreviewbillableuserchangerole"></a>`role` | [`GitlabSubscriptionsUserRole!`](#gitlabsubscriptionsuserrole) | Role of users being added to group. |
+
##### `Group.groupMembers`
A membership of a user within this group.
@@ -12820,7 +13080,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupissuescrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="groupissuescrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="groupissuesepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
-| <a id="groupissueshealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Health status of the issue. |
+| <a id="groupissueshealthstatus"></a>`healthStatus` **{warning-solid}** | [`HealthStatus`](#healthstatus) | **Deprecated** in 15.4. Use `healthStatusFilter`. |
+| <a id="groupissueshealthstatusfilter"></a>`healthStatusFilter` | [`HealthStatusFilter`](#healthstatusfilter) | Health status of the issue, "none" and "any" values are supported. |
| <a id="groupissuesiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="groupissuesiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
| <a id="groupissuesin"></a>`in` | [`[IssuableSearchableField!]`](#issuablesearchablefield) | Specify the fields to perform the search in. Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'. |
@@ -13653,7 +13914,7 @@ Represents an iteration object.
| <a id="iterationsequence"></a>`sequence` | [`Int!`](#int) | Sequence number for the iteration when you sort the containing cadence's iterations by the start and end date. The earliest starting and ending iteration is assigned 1. |
| <a id="iterationstartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the iteration start date. |
| <a id="iterationstate"></a>`state` | [`IterationState!`](#iterationstate) | State of the iteration. |
-| <a id="iterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. Title must be specified unless iteration_cadences feature flag is enabled. |
+| <a id="iterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
| <a id="iterationupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of last iteration update. |
| <a id="iterationwebpath"></a>`webPath` | [`String!`](#string) | Web path of the iteration. |
| <a id="iterationweburl"></a>`webUrl` | [`String!`](#string) | Web URL of the iteration. |
@@ -15253,7 +15514,7 @@ Represents the network policy.
| <a id="noteauthor"></a>`author` | [`UserCore!`](#usercore) | User who wrote this note. |
| <a id="notebody"></a>`body` | [`String!`](#string) | Content of the note. |
| <a id="notebodyhtml"></a>`bodyHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `note`. |
-| <a id="noteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 15.3. This was renamed. Use: `internal`. |
+| <a id="noteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 15.5. This was renamed. Use: `internal`. |
| <a id="notecreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of the note creation. |
| <a id="notediscussion"></a>`discussion` | [`Discussion`](#discussion) | Discussion this note is a part of. |
| <a id="noteid"></a>`id` | [`NoteID!`](#noteid) | ID of the note. |
@@ -15558,8 +15819,17 @@ Namespace-level Package Registry settings.
| ---- | ---- | ----------- |
| <a id="packagesettingsgenericduplicateexceptionregex"></a>`genericDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="packagesettingsgenericduplicatesallowed"></a>`genericDuplicatesAllowed` | [`Boolean!`](#boolean) | Indicates whether duplicate generic packages are allowed for this namespace. |
+| <a id="packagesettingslockmavenpackagerequestsforwarding"></a>`lockMavenPackageRequestsForwarding` | [`Boolean!`](#boolean) | Indicates whether Maven package forwarding is locked for all descendent namespaces. |
+| <a id="packagesettingslocknpmpackagerequestsforwarding"></a>`lockNpmPackageRequestsForwarding` | [`Boolean!`](#boolean) | Indicates whether npm package forwarding is locked for all descendent namespaces. |
+| <a id="packagesettingslockpypipackagerequestsforwarding"></a>`lockPypiPackageRequestsForwarding` | [`Boolean!`](#boolean) | Indicates whether PyPI package forwarding is locked for all descendent namespaces. |
| <a id="packagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="packagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean!`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. |
+| <a id="packagesettingsmavenpackagerequestsforwarding"></a>`mavenPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether Maven package forwarding is allowed for this namespace. |
+| <a id="packagesettingsmavenpackagerequestsforwardinglocked"></a>`mavenPackageRequestsForwardingLocked` | [`Boolean!`](#boolean) | Indicates whether Maven package forwarding settings are locked by a parent namespace. |
+| <a id="packagesettingsnpmpackagerequestsforwarding"></a>`npmPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether npm package forwarding is allowed for this namespace. |
+| <a id="packagesettingsnpmpackagerequestsforwardinglocked"></a>`npmPackageRequestsForwardingLocked` | [`Boolean!`](#boolean) | Indicates whether npm package forwarding settings are locked by a parent namespace. |
+| <a id="packagesettingspypipackagerequestsforwarding"></a>`pypiPackageRequestsForwarding` | [`Boolean`](#boolean) | Indicates whether PyPI package forwarding is allowed for this namespace. |
+| <a id="packagesettingspypipackagerequestsforwardinglocked"></a>`pypiPackageRequestsForwardingLocked` | [`Boolean!`](#boolean) | Indicates whether PyPI package forwarding settings are locked by a parent namespace. |
### `PackageTag`
@@ -15820,6 +16090,37 @@ Represents pipeline counts for the project.
| <a id="pipelinepermissionsdestroypipeline"></a>`destroyPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pipeline` on this resource. |
| <a id="pipelinepermissionsupdatepipeline"></a>`updatePipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline` on this resource. |
+### `PipelineSchedule`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pipelinescheduleactive"></a>`active` | [`Boolean!`](#boolean) | Indicates if a pipeline schedule is active. |
+| <a id="pipelineschedulecron"></a>`cron` | [`String!`](#string) | Cron notation for the schedule. |
+| <a id="pipelineschedulecrontimezone"></a>`cronTimezone` | [`String!`](#string) | Timezone for the pipeline schedule. |
+| <a id="pipelinescheduledescription"></a>`description` | [`String`](#string) | Description of the pipeline schedule. |
+| <a id="pipelineschedulefortag"></a>`forTag` | [`Boolean!`](#boolean) | Indicates if a pipelines schedule belongs to a tag. |
+| <a id="pipelinescheduleid"></a>`id` | [`ID!`](#id) | ID of the pipeline schedule. |
+| <a id="pipelineschedulelastpipeline"></a>`lastPipeline` | [`Pipeline`](#pipeline) | Last pipeline object. |
+| <a id="pipelineschedulenextrunat"></a>`nextRunAt` | [`Time!`](#time) | Time when the next pipeline will run. |
+| <a id="pipelinescheduleowner"></a>`owner` | [`UserCore!`](#usercore) | Owner of the pipeline schedule. |
+| <a id="pipelineschedulerealnextrun"></a>`realNextRun` | [`Time!`](#time) | Time when the next pipeline will run. |
+| <a id="pipelineschedulereffordisplay"></a>`refForDisplay` | [`String`](#string) | Git ref for the pipeline schedule. |
+| <a id="pipelineschedulerefpath"></a>`refPath` | [`String`](#string) | Path to the ref that triggered the pipeline. |
+| <a id="pipelinescheduleuserpermissions"></a>`userPermissions` | [`PipelineSchedulePermissions!`](#pipelineschedulepermissions) | Permissions for the current user on the resource. |
+
+### `PipelineSchedulePermissions`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pipelineschedulepermissionsadminpipelineschedule"></a>`adminPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionsplaypipelineschedule"></a>`playPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `play_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionstakeownershippipelineschedule"></a>`takeOwnershipPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `take_ownership_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionsupdatepipelineschedule"></a>`updatePipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline_schedule` on this resource. |
+
### `PipelineSecurityReportFinding`
Represents vulnerability finding of a security report on the pipeline.
@@ -15848,6 +16149,16 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="pipelinesecurityreportfindingtitle"></a>`title` | [`String`](#string) | Title of the vulnerability finding. |
| <a id="pipelinesecurityreportfindinguuid"></a>`uuid` | [`String`](#string) | Name of the vulnerability finding. |
+### `PreviewBillableUserChange`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="previewbillableuserchangehasoverage"></a>`hasOverage` | [`Boolean`](#boolean) | If the group has an overage after change. |
+| <a id="previewbillableuserchangenewbillableusercount"></a>`newBillableUserCount` | [`Int`](#int) | Total number of billable users after change. |
+| <a id="previewbillableuserchangeseatsinsubscription"></a>`seatsInSubscription` | [`Int`](#int) | Number of seats in subscription. |
+
### `Project`
#### Fields
@@ -15898,6 +16209,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectnamewithnamespace"></a>`nameWithNamespace` | [`String!`](#string) | Full name of the project with its namespace. |
| <a id="projectnamespace"></a>`namespace` | [`Namespace`](#namespace) | Namespace of the project. |
| <a id="projectonlyallowmergeifalldiscussionsareresolved"></a>`onlyAllowMergeIfAllDiscussionsAreResolved` | [`Boolean`](#boolean) | Indicates if merge requests of the project can only be merged when all the discussions are resolved. |
+| <a id="projectonlyallowmergeifallstatuscheckspassed"></a>`onlyAllowMergeIfAllStatusChecksPassed` | [`Boolean`](#boolean) | Indicates that merges of merge requests should be blocked unless all status checks have passed. |
| <a id="projectonlyallowmergeifpipelinesucceeds"></a>`onlyAllowMergeIfPipelineSucceeds` | [`Boolean`](#boolean) | Indicates if merge requests of the project can only be merged with successful jobs. |
| <a id="projectopenissuescount"></a>`openIssuesCount` | [`Int`](#int) | Number of open issues for the project. |
| <a id="projectpackagescleanuppolicy"></a>`packagesCleanupPolicy` | [`PackagesCleanupPolicy`](#packagescleanuppolicy) | Packages cleanup policy for the project. |
@@ -16256,6 +16568,21 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="projectforktargetssearch"></a>`search` | [`String`](#string) | Search query for path or name. |
+##### `Project.gitlabSubscriptionsPreviewBillableUserChange`
+
+Preview Billable User Changes.
+
+Returns [`PreviewBillableUserChange`](#previewbillableuserchange).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectgitlabsubscriptionspreviewbillableuserchangeaddgroupid"></a>`addGroupId` | [`Int`](#int) | Group ID to add. |
+| <a id="projectgitlabsubscriptionspreviewbillableuserchangeadduseremails"></a>`addUserEmails` | [`[String!]`](#string) | User emails to add. |
+| <a id="projectgitlabsubscriptionspreviewbillableuserchangeadduserids"></a>`addUserIds` | [`[Int!]`](#int) | User IDs to add. |
+| <a id="projectgitlabsubscriptionspreviewbillableuserchangerole"></a>`role` | [`GitlabSubscriptionsUserRole!`](#gitlabsubscriptionsuserrole) | Role of users being added to group. |
+
##### `Project.incidentManagementEscalationPolicies`
Incident Management escalation policies of the project.
@@ -16352,7 +16679,8 @@ Returns [`Issue`](#issue).
| <a id="projectissuecrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="projectissuecrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="projectissueepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
-| <a id="projectissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Health status of the issue. |
+| <a id="projectissuehealthstatus"></a>`healthStatus` **{warning-solid}** | [`HealthStatus`](#healthstatus) | **Deprecated** in 15.4. Use `healthStatusFilter`. |
+| <a id="projectissuehealthstatusfilter"></a>`healthStatusFilter` | [`HealthStatusFilter`](#healthstatusfilter) | Health status of the issue, "none" and "any" values are supported. |
| <a id="projectissueiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="projectissueiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
| <a id="projectissuein"></a>`in` | [`[IssuableSearchableField!]`](#issuablesearchablefield) | Specify the fields to perform the search in. Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'. |
@@ -16436,7 +16764,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectissuescrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="projectissuescrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="projectissuesepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
-| <a id="projectissueshealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Health status of the issue. |
+| <a id="projectissueshealthstatus"></a>`healthStatus` **{warning-solid}** | [`HealthStatus`](#healthstatus) | **Deprecated** in 15.4. Use `healthStatusFilter`. |
+| <a id="projectissueshealthstatusfilter"></a>`healthStatusFilter` | [`HealthStatusFilter`](#healthstatusfilter) | Health status of the issue, "none" and "any" values are supported. |
| <a id="projectissuesiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="projectissuesiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
| <a id="projectissuesin"></a>`in` | [`[IssuableSearchableField!]`](#issuablesearchablefield) | Specify the fields to perform the search in. Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'. |
@@ -16700,6 +17029,22 @@ Returns [`PipelineCounts`](#pipelinecounts).
| <a id="projectpipelinecountssha"></a>`sha` | [`String`](#string) | Filter pipelines by the SHA of the commit they are run for. |
| <a id="projectpipelinecountssource"></a>`source` | [`String`](#string) | Filter pipelines by their source. |
+##### `Project.pipelineSchedules`
+
+Pipeline schedules of the project. This field can only be resolved for one project per request.
+
+Returns [`PipelineScheduleConnection`](#pipelinescheduleconnection).
+
+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="projectpipelineschedulesstatus"></a>`status` | [`PipelineScheduleStatus`](#pipelineschedulestatus) | Filter pipeline schedules by active status. |
+
##### `Project.pipelines`
Build pipelines of the project.
@@ -17044,7 +17389,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="projectcicdsettingjobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI job tokens generated in this project have restricted access to resources. |
+| <a id="projectcicdsettinginboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in other projects have restricted access to this project. |
+| <a id="projectcicdsettingjobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in this project have restricted access to other projects. |
| <a id="projectcicdsettingkeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Whether to keep the latest builds artifacts. |
| <a id="projectcicdsettingmergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Whether merge pipelines are enabled. |
| <a id="projectcicdsettingmergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Whether merge trains are enabled. |
@@ -17185,6 +17531,45 @@ The alert condition for Prometheus.
| <a id="prometheusalerthumanizedtext"></a>`humanizedText` | [`String!`](#string) | Human-readable text of the alert condition. |
| <a id="prometheusalertid"></a>`id` | [`ID!`](#id) | ID of the alert condition. |
+### `ProtectedEnvironment`
+
+Protected Environments of the environment.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentapprovalrules"></a>`approvalRules` | [`ProtectedEnvironmentApprovalRuleConnection`](#protectedenvironmentapprovalruleconnection) | Which group, user or role is allowed to approve deployments to the environment. (see [Connections](#connections)) |
+| <a id="protectedenvironmentdeployaccesslevels"></a>`deployAccessLevels` | [`ProtectedEnvironmentDeployAccessLevelConnection`](#protectedenvironmentdeployaccesslevelconnection) | Which group, user or role is allowed to execute deployments to the environment. (see [Connections](#connections)) |
+| <a id="protectedenvironmentgroup"></a>`group` | [`Group`](#group) | Group details. Present if it's group-level protected environment. |
+| <a id="protectedenvironmentname"></a>`name` | [`String`](#string) | Name of the environment if it's a project-level protected environment. Tier of the environment if it's a group-level protected environment. |
+| <a id="protectedenvironmentproject"></a>`project` | [`Project`](#project) | Project details. Present if it's project-level protected environment. |
+
+### `ProtectedEnvironmentApprovalRule`
+
+Which group, user or role is allowed to approve deployments to the environment.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentapprovalruleaccesslevel"></a>`accessLevel` | [`AccessLevel`](#accesslevel) | Role details. Present if it's role specific access control. |
+| <a id="protectedenvironmentapprovalrulegroup"></a>`group` | [`Group`](#group) | Group details. Present if it's group specific access control. |
+| <a id="protectedenvironmentapprovalrulerequiredapprovals"></a>`requiredApprovals` | [`Int`](#int) | Number of required approvals. |
+| <a id="protectedenvironmentapprovalruleuser"></a>`user` | [`UserCore`](#usercore) | User details. Present if it's user specific access control. |
+
+### `ProtectedEnvironmentDeployAccessLevel`
+
+Which group, user or role is allowed to execute deployments to the environment.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="protectedenvironmentdeployaccesslevelaccesslevel"></a>`accessLevel` | [`AccessLevel`](#accesslevel) | Role details. Present if it's role specific access control. |
+| <a id="protectedenvironmentdeployaccesslevelgroup"></a>`group` | [`Group`](#group) | Group details. Present if it's group specific access control. |
+| <a id="protectedenvironmentdeployaccessleveluser"></a>`user` | [`UserCore`](#usercore) | User details. Present if it's user specific access control. |
+
### `PushAccessLevel`
Represents the push access level of a branch protection.
@@ -17464,7 +17849,7 @@ Represents a requirement.
| <a id="requirementauthor"></a>`author` | [`UserCore!`](#usercore) | Author of the requirement. |
| <a id="requirementcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the requirement was created. |
| <a id="requirementdescription"></a>`description` | [`String`](#string) | Description of the requirement. |
-| <a id="requirementdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
+| <a id="requirementdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | GitLab Flavored Markdown rendering of `description`. |
| <a id="requirementid"></a>`id` | [`ID!`](#id) | ID of the requirement. |
| <a id="requirementiid"></a>`iid` | [`ID!`](#id) | Internal ID of the requirement. |
| <a id="requirementlasttestreportmanuallycreated"></a>`lastTestReportManuallyCreated` | [`Boolean`](#boolean) | Indicates if latest test report was created by user. |
@@ -17472,7 +17857,7 @@ Represents a requirement.
| <a id="requirementproject"></a>`project` | [`Project!`](#project) | Project to which the requirement belongs. |
| <a id="requirementstate"></a>`state` | [`RequirementState!`](#requirementstate) | State of the requirement. |
| <a id="requirementtitle"></a>`title` | [`String`](#string) | Title of the requirement. |
-| <a id="requirementtitlehtml"></a>`titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
+| <a id="requirementtitlehtml"></a>`titleHtml` | [`String`](#string) | GitLab Flavored Markdown rendering of `title`. |
| <a id="requirementupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the requirement was last updated. |
| <a id="requirementuserpermissions"></a>`userPermissions` | [`RequirementPermissions!`](#requirementpermissions) | Permissions for the current user on the resource. |
@@ -19439,16 +19824,16 @@ Represents a start and due date widget.
| <a id="workitemwidgetstartandduedatestartdate"></a>`startDate` | [`Date`](#date) | Start date of the work item. |
| <a id="workitemwidgetstartandduedatetype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
-### `WorkItemWidgetVerificationStatus`
+### `WorkItemWidgetStatus`
-Represents a verification status widget.
+Represents a status widget.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="workitemwidgetverificationstatustype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
-| <a id="workitemwidgetverificationstatusverificationstatus"></a>`verificationStatus` | [`String`](#string) | Verification status of the work item. |
+| <a id="workitemwidgetstatusstatus"></a>`status` | [`String`](#string) | Status of the work item. |
+| <a id="workitemwidgetstatustype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
### `WorkItemWidgetWeight`
@@ -19696,6 +20081,7 @@ Values for filtering runners in namespaces. The previous type name `RunnerMember
| Value | Description |
| ----- | ----------- |
+| <a id="cirunnermembershipfilterall_available"></a>`ALL_AVAILABLE` **{warning-solid}** | **Introduced** in 15.5. This feature is in Alpha. It can be changed or removed at any time. Include all runners. This list includes runners for all projects in the group and subgroups, as well as for the parent groups and instance. |
| <a id="cirunnermembershipfilterdescendants"></a>`DESCENDANTS` | Include runners that have either a direct or inherited relationship. These runners can be specific to a project or a group. |
| <a id="cirunnermembershipfilterdirect"></a>`DIRECT` | Include runners that have a direct relationship. |
@@ -20105,6 +20491,7 @@ Detailed representation of whether a GitLab merge request can be merged.
| <a id="detailedmergestatusci_still_running"></a>`CI_STILL_RUNNING` | Pipeline is still running. |
| <a id="detailedmergestatusdiscussions_not_resolved"></a>`DISCUSSIONS_NOT_RESOLVED` | Discussions must be resolved before merging. |
| <a id="detailedmergestatusdraft_status"></a>`DRAFT_STATUS` | Merge request must not be draft before merging. |
+| <a id="detailedmergestatusexternal_status_checks"></a>`EXTERNAL_STATUS_CHECKS` | Status checks must pass. |
| <a id="detailedmergestatusmergeable"></a>`MERGEABLE` | Branch can be merged. |
| <a id="detailedmergestatusnot_approved"></a>`NOT_APPROVED` | Merge request must be approved before merging. |
| <a id="detailedmergestatusnot_open"></a>`NOT_OPEN` | Merge request must be open before merging. |
@@ -20228,6 +20615,18 @@ Event action.
| <a id="eventactionreopened"></a>`REOPENED` | Reopened action. |
| <a id="eventactionupdated"></a>`UPDATED` | Updated action. |
+### `GitlabSubscriptionsUserRole`
+
+Role of User.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="gitlabsubscriptionsuserroledeveloper"></a>`DEVELOPER` | Developer. |
+| <a id="gitlabsubscriptionsuserroleguest"></a>`GUEST` | Guest. |
+| <a id="gitlabsubscriptionsuserrolemaintainer"></a>`MAINTAINER` | Maintainer. |
+| <a id="gitlabsubscriptionsuserroleowner"></a>`OWNER` | Owner. |
+| <a id="gitlabsubscriptionsuserrolereporter"></a>`REPORTER` | Reporter. |
+
### `GroupMemberRelation`
Group member relation.
@@ -20258,6 +20657,18 @@ Health status of an issue or epic.
| <a id="healthstatusneedsattention"></a>`needsAttention` | Needs attention. |
| <a id="healthstatusontrack"></a>`onTrack` | On track. |
+### `HealthStatusFilter`
+
+Health status of an issue or epic for filtering.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="healthstatusfilterany"></a>`ANY` | Any health status is assigned. |
+| <a id="healthstatusfilternone"></a>`NONE` | No health status is assigned. |
+| <a id="healthstatusfilteratrisk"></a>`atRisk` | At risk. |
+| <a id="healthstatusfilterneedsattention"></a>`needsAttention` | Needs attention. |
+| <a id="healthstatusfilterontrack"></a>`onTrack` | On track. |
+
### `IssuableResourceLinkType`
Issuable resource link type enum.
@@ -20408,7 +20819,8 @@ Iteration sort values.
| Value | Description |
| ----- | ----------- |
-| <a id="iterationsortcadence_and_due_date_asc"></a>`CADENCE_AND_DUE_DATE_ASC` | Sort by cadence id and due date in ascending order. |
+| <a id="iterationsortcadence_and_due_date_asc"></a>`CADENCE_AND_DUE_DATE_ASC` | Sort by cadence id in ascending and due date in ascending order. |
+| <a id="iterationsortcadence_and_due_date_desc"></a>`CADENCE_AND_DUE_DATE_DESC` | Sort by cadence id in ascending and due date in descending order. |
### `IterationState`
@@ -20818,6 +21230,13 @@ Event type of the pipeline associated with a merge request.
| <a id="pipelinemergerequesteventtypemerged_result"></a>`MERGED_RESULT` | Pipeline run on the changes from the source branch combined with the target branch. |
| <a id="pipelinemergerequesteventtypemerge_train"></a>`MERGE_TRAIN` | Pipeline ran as part of a merge train. |
+### `PipelineScheduleStatus`
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="pipelineschedulestatusactive"></a>`ACTIVE` | Active pipeline schedules. |
+| <a id="pipelineschedulestatusinactive"></a>`INACTIVE` | Inactive pipeline schedules. |
+
### `PipelineScopeEnum`
| Value | Description |
@@ -21211,6 +21630,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_error_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_ERROR_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_error_threshold. |
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_info_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_INFO_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_info_threshold. |
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_warning_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_WARNING_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_warning_threshold. |
+| <a id="usercalloutfeaturenameenumnew_top_level_group_alert"></a>`NEW_TOP_LEVEL_GROUP_ALERT` | Callout feature name for new_top_level_group_alert. |
| <a id="usercalloutfeaturenameenumnew_user_signups_cap_reached"></a>`NEW_USER_SIGNUPS_CAP_REACHED` | Callout feature name for new_user_signups_cap_reached. |
| <a id="usercalloutfeaturenameenumpersonal_access_token_expiry"></a>`PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for personal_access_token_expiry. |
| <a id="usercalloutfeaturenameenumpersonal_project_limitations_banner"></a>`PERSONAL_PROJECT_LIMITATIONS_BANNER` | Callout feature name for personal_project_limitations_banner. |
@@ -21450,7 +21870,7 @@ Type of a work item widget.
| <a id="workitemwidgettypeiteration"></a>`ITERATION` | Iteration widget. |
| <a id="workitemwidgettypelabels"></a>`LABELS` | Labels widget. |
| <a id="workitemwidgettypestart_and_due_date"></a>`START_AND_DUE_DATE` | Start And Due Date widget. |
-| <a id="workitemwidgettypeverification_status"></a>`VERIFICATION_STATUS` | Verification Status widget. |
+| <a id="workitemwidgettypestatus"></a>`STATUS` | Status widget. |
| <a id="workitemwidgettypeweight"></a>`WEIGHT` | Weight widget. |
## Scalar types
@@ -21544,6 +21964,12 @@ A `CiPipelineID` is a global ID. It is encoded as a string.
An example `CiPipelineID` is: `"gid://gitlab/Ci::Pipeline/1"`.
+### `CiPipelineScheduleID`
+
+A `CiPipelineScheduleID` is a global ID. It is encoded as a string.
+
+An example `CiPipelineScheduleID` is: `"gid://gitlab/Ci::PipelineSchedule/1"`.
+
### `CiRunnerID`
A `CiRunnerID` is a global ID. It is encoded as a string.
@@ -22714,7 +23140,7 @@ Implementations:
- [`WorkItemWidgetIteration`](#workitemwidgetiteration)
- [`WorkItemWidgetLabels`](#workitemwidgetlabels)
- [`WorkItemWidgetStartAndDueDate`](#workitemwidgetstartandduedate)
-- [`WorkItemWidgetVerificationStatus`](#workitemwidgetverificationstatus)
+- [`WorkItemWidgetStatus`](#workitemwidgetstatus)
- [`WorkItemWidgetWeight`](#workitemwidgetweight)
##### Fields
@@ -22756,6 +23182,7 @@ Field that are available while modifying the custom mapping attributes for an HT
| <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="boardissueinputhealthstatusfilter"></a>`healthStatusFilter` | [`HealthStatusFilter`](#healthstatusfilter) | Health status of the issue, "none" and "any" values are supported. |
| <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. |
@@ -23142,6 +23569,14 @@ Represents an action to perform over a snippet file.
| <a id="snippetblobactioninputtypefilepath"></a>`filePath` | [`String!`](#string) | Path of the snippet file. |
| <a id="snippetblobactioninputtypepreviouspath"></a>`previousPath` | [`String`](#string) | Previous path of the snippet file. |
+### `StatusInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="statusinputstatus"></a>`status` | [`TestReportState!`](#testreportstate) | Status to assign to the work item. |
+
### `Timeframe`
A time-frame defined as a closed inclusive range of two dates.
@@ -23228,6 +23663,7 @@ A time-frame defined as a closed inclusive range of two dates.
| <a id="workitemupdatedtaskinputdescriptionwidget"></a>`descriptionWidget` | [`WorkItemWidgetDescriptionInput`](#workitemwidgetdescriptioninput) | Input for description widget. |
| <a id="workitemupdatedtaskinputhierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyUpdateInput`](#workitemwidgethierarchyupdateinput) | Input for hierarchy widget. |
| <a id="workitemupdatedtaskinputid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
+| <a id="workitemupdatedtaskinputlabelswidget"></a>`labelsWidget` | [`WorkItemWidgetLabelsUpdateInput`](#workitemwidgetlabelsupdateinput) | Input for labels widget. |
| <a id="workitemupdatedtaskinputstartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
| <a id="workitemupdatedtaskinputstateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
| <a id="workitemupdatedtaskinputtitle"></a>`title` | [`String`](#string) | Title of the work item. |
@@ -23273,6 +23709,15 @@ A time-frame defined as a closed inclusive range of two dates.
| ---- | ---- | ----------- |
| <a id="workitemwidgetiterationinputiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | Iteration to assign to the work item. |
+### `WorkItemWidgetLabelsUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetlabelsupdateinputaddlabelids"></a>`addLabelIds` | [`[LabelID!]`](#labelid) | Global IDs of labels to be added to the work item. |
+| <a id="workitemwidgetlabelsupdateinputremovelabelids"></a>`removeLabelIds` | [`[LabelID!]`](#labelid) | Global IDs of labels to be removed from the work item. |
+
### `WorkItemWidgetStartAndDueDateUpdateInput`
#### Arguments
diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md
index 6778a0c2aab..57f1c49290f 100644
--- a/doc/api/graphql/removed_items.md
+++ b/doc/api/graphql/removed_items.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL API removed items **(FREE)**
diff --git a/doc/api/graphql/sample_issue_boards.md b/doc/api/graphql/sample_issue_boards.md
index 7fe8046b27d..1a189914b28 100644
--- a/doc/api/graphql/sample_issue_boards.md
+++ b/doc/api/graphql/sample_issue_boards.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Identify issue boards with GraphQL **(FREE)**
diff --git a/doc/api/graphql/users_example.md b/doc/api/graphql/users_example.md
index 1c366587e5f..96bbeeb2d06 100644
--- a/doc/api/graphql/users_example.md
+++ b/doc/api/graphql/users_example.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Query users with GraphQL **(FREE)**
diff --git a/doc/api/group_access_tokens.md b/doc/api/group_access_tokens.md
index 1c707f92ebd..2f3459a6121 100644
--- a/doc/api/group_access_tokens.md
+++ b/doc/api/group_access_tokens.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group access tokens API **(FREE)**
diff --git a/doc/api/group_activity_analytics.md b/doc/api/group_activity_analytics.md
index 9206b0a1bd6..6d1c1ec155a 100644
--- a/doc/api/group_activity_analytics.md
+++ b/doc/api/group_activity_analytics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group Activity Analytics API **(PREMIUM)**
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index b1166ba5b54..cc99c137a47 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group badges API **(FREE)**
diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md
index 6178a3fdc04..d08a84aea61 100644
--- a/doc/api/group_boards.md
+++ b/doc/api/group_boards.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group issue boards API **(FREE)**
diff --git a/doc/api/group_clusters.md b/doc/api/group_clusters.md
index dfb6e7e4778..ed50594c73a 100644
--- a/doc/api/group_clusters.md
+++ b/doc/api/group_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group clusters API (certificate-based) (DEPRECATED) **(FREE)**
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index dbdc2c3669e..1efed80699b 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group import/export API **(FREE)**
diff --git a/doc/api/group_iterations.md b/doc/api/group_iterations.md
index 7f663515fee..92333de701c 100644
--- a/doc/api/group_iterations.md
+++ b/doc/api/group_iterations.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group iterations API **(PREMIUM)**
diff --git a/doc/api/group_labels.md b/doc/api/group_labels.md
index e0f1b451231..f33f181336f 100644
--- a/doc/api/group_labels.md
+++ b/doc/api/group_labels.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group labels API **(FREE)**
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index 7c51de47bc7..cdda15d9610 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group-level Variables API **(FREE)**
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index 8b9c09ef1a0..824c4eb4678 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group milestones API **(FREE)**
diff --git a/doc/api/group_protected_environments.md b/doc/api/group_protected_environments.md
index 3f1d932e0c8..4cf87cb4305 100644
--- a/doc/api/group_protected_environments.md
+++ b/doc/api/group_protected_environments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -112,7 +112,7 @@ POST /groups/:id/protected_environments
| `approval_rules` | array | no | Array of access levels allowed to approve, with each described by a hash. One of `user_id`, `group_id` or `access_level`. They take the form of `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}` respectively. You can also specify the number of required approvals from the specified entity with `required_approvals` field. See [Multiple approval rules](../ci/environments/deployment_approvals.md#multiple-approval-rules) for more information. |
The assignable `user_id` are the users who belong to the given group with the Maintainer role (or above).
-The assignable `group_id` are the sub-groups under the given group.
+The assignable `group_id` are the subgroups under the given group.
```shell
curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/22034114/protected_environments"
@@ -157,7 +157,7 @@ PUT /groups/:id/protected_environments/:name
To update:
- **`user_id`**: Ensure the updated user belongs to the given group with the Maintainer role (or above). You must also pass the `id` of either a `deploy_access_level` or `approval_rule` in the respective hash.
-- **`group_id`**: Ensure the updated group is a sub-group of the group this protected environment belongs to. You must also pass the `id` of either a `deploy_access_level` or `approval_rule` in the respective hash.
+- **`group_id`**: Ensure the updated group is a subgroup of the group this protected environment belongs to. You must also pass the `id` of either a `deploy_access_level` or `approval_rule` in the respective hash.
To delete:
diff --git a/doc/api/group_relations_export.md b/doc/api/group_relations_export.md
index 4dbf0f6d54c..065ae03259a 100644
--- a/doc/api/group_relations_export.md
+++ b/doc/api/group_relations_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group Relations Export API **(FREE)**
diff --git a/doc/api/group_releases.md b/doc/api/group_releases.md
index 06ce55b7d48..1918d0a54b9 100644
--- a/doc/api/group_releases.md
+++ b/doc/api/group_releases.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group releases API **(FREE)**
diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md
index f1ad7f51ea0..a4baf7936dd 100644
--- a/doc/api/group_repository_storage_moves.md
+++ b/doc/api/group_repository_storage_moves.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md
index 50bb67b8173..cba64269942 100644
--- a/doc/api/group_wikis.md
+++ b/doc/api/group_wikis.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/groups.md b/doc/api/groups.md
index d3c0d659d08..c1effc78a4d 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Groups API **(FREE)**
@@ -125,13 +125,16 @@ GET /groups?custom_attributes[key]=value&custom_attributes[other_key]=other_valu
## List a group's subgroups
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15142) in GitLab 10.3.
-
Get a list of visible direct subgroups in this group.
-When accessed without authentication, only public groups are returned.
By default, this request returns 20 results at a time because the API results [are paginated](index.md#pagination).
+If you request this list as:
+
+- An unauthenticated user, the response returns only public groups.
+- An authenticated user, the response returns only the groups you're
+a member of and does not include public groups.
+
Parameters:
| Attribute | Type | Required | Description |
@@ -284,7 +287,7 @@ Parameters:
| `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 |
+| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `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` |
@@ -367,7 +370,7 @@ Parameters:
| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Return list of authorized projects matching the search criteria |
-| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
+| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `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` |
diff --git a/doc/api/import.md b/doc/api/import.md
index 1baea5d1500..78b9beb1815 100644
--- a/doc/api/import.md
+++ b/doc/api/import.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import API **(FREE)**
@@ -14,13 +14,14 @@ Import your projects from GitHub to GitLab via the API.
POST /import/github
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `personal_access_token` | string | yes | GitHub personal access token |
-| `repo_id` | integer | yes | GitHub repository ID |
-| `new_name` | string | no | New repository name |
-| `target_namespace` | string | yes | Namespace to import repository into. Supports subgroups like `/namespace/subgroup`. |
-| `github_hostname` | string | no | Custom GitHub Enterprise hostname. Do not set for GitHub.com. |
+| Attribute | Type | Required | Description |
+|-------------------------|---------|----------|-------------------------------------------------------------------------------------|
+| `personal_access_token` | string | yes | GitHub personal access token |
+| `repo_id` | integer | yes | GitHub repository ID |
+| `new_name` | string | no | New repository name |
+| `target_namespace` | string | yes | Namespace to import repository into. Supports subgroups like `/namespace/subgroup` |
+| `github_hostname` | string | no | Custom GitHub Enterprise hostname. Do not set for GitHub.com. |
+| `optional_stages` | object | no | [Additional items to import](../user/project/import/github.md#select-additional-items-to-import). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/373705) in GitLab 15.5 |
```shell
curl --request POST \
@@ -32,10 +33,23 @@ curl --request POST \
"repo_id": "12345",
"target_namespace": "group/subgroup",
"new_name": "NEW-NAME",
- "github_hostname": "https://github.example.com"
+ "github_hostname": "https://github.example.com",
+ "optional_stages": {
+ "single_endpoint_issue_events_import": true,
+ "single_endpoint_notes_import": true,
+ "attachments_import": true
+ }
}'
```
+The following keys are available for `optional_stages`:
+
+- `single_endpoint_issue_events_import`, for issue and pull request events import.
+- `single_endpoint_notes_import`, for an alternative and more thorough comments import.
+- `attachments_import`, for Markdown attachments import.
+
+For more information, see [Select additional items to import](../user/project/import/github.md#select-additional-items-to-import).
+
Example response:
```json
@@ -47,6 +61,51 @@ Example response:
}
```
+## Cancel GitHub project import
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364783) in GitLab 15.5.
+
+Cancel an in-progress GitHub project import using the API.
+
+```plaintext
+POST /import/github/cancel
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `project_id` | integer | yes | GitLab project ID |
+
+```shell
+curl --request POST \
+ --url "https://gitlab.example.com/api/v4/import/github/cancel" \
+ --header "content-type: application/json" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data '{
+ "project_id": 12345
+}'
+```
+
+Example response:
+
+```json
+{
+ "id": 160,
+ "name": "my-repo",
+ "full_path": "/root/my-repo",
+ "full_name": "Administrator / my-repo",
+ "import_source": "source/source-repo",
+ "import_status": "canceled",
+ "human_import_status_name": "canceled",
+ "provider_link": "/source/source-repo"
+}
+```
+
+Returns the following status codes:
+
+- `200 OK`: the project import is being canceled.
+- `400 Bad Request`: the project import cannot be canceled.
+- `404 Not Found`: the project associated with `project_id` does not exist.
+
## Import repository from Bitbucket Server
Import your projects from Bitbucket Server to GitLab via the API.
diff --git a/doc/api/index.md b/doc/api/index.md
index 15d0b0fd65f..7e14137b0fe 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# API Docs **(FREE)**
@@ -29,7 +29,7 @@ For an introduction and basic steps, see
## SCIM API **(PREMIUM SAAS)**
GitLab provides a [SCIM API](scim.md) that both implements
-[the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides the
+[the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644) and provides the
`/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`.
## GraphQL API
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index 3d2c35a0ab0..45243003004 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Instance clusters API (certificate-based) (DEPRECATED) **(FREE SELF)**
diff --git a/doc/api/instance_level_ci_variables.md b/doc/api/instance_level_ci_variables.md
index 2b2579425b5..776b1000651 100644
--- a/doc/api/instance_level_ci_variables.md
+++ b/doc/api/instance_level_ci_variables.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Instance-level CI/CD variables API **(FREE SELF)**
diff --git a/doc/api/integrations.md b/doc/api/integrations.md
index b7e110a7eef..176ed931d38 100644
--- a/doc/api/integrations.md
+++ b/doc/api/integrations.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrations API **(FREE)**
@@ -276,7 +276,7 @@ Parameters:
| Parameter | Type | Required | Description |
|---------------|---------|----------|---------------------------------------------------------------------------------------------|
-| `token` | string | true | Campfire API token. To find it, log into Campfire and select **My info**. |
+| `token` | string | true | Campfire API token. To find it, sign in to Campfire and select **My info**. |
| `subdomain` | string | false | Campfire subdomain. Text between `https://` and `.campfirenow.com` when you're logged in. |
| `room` | string | false | Campfire room. The last part of the URL when you're in a room. |
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 96c820536de..94362b097af 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Invitations API **(FREE)**
diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md
index eb9e8e8adc0..253be9109c7 100644
--- a/doc/api/issue_links.md
+++ b/doc/api/issue_links.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue links API **(FREE)**
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 6e8aaa3d489..a0eb518f23e 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issues API **(FREE)**
@@ -54,37 +54,38 @@ GET /issues?state=closed
GET /issues?state=opened
```
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. |
-| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE, the `assignee_username` array should only contain a single value. Otherwise, an invalid parameter error is returned. |
-| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
-| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
-| `confidential` | boolean | no | Filter confidential or public issues. |
-| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
-| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
-| `iids[]` | integer array | no | Return only the issues having the given `iid` |
-| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
-| `issue_type` | string | no | Filter to a given type of issue. One of `issue`, `incident`, or `test_case`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260375) in GitLab 13.12)_ |
-| `iteration_id` **(PREMIUM)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
-| `iteration_title` **(PREMIUM)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
-| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
-| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. Using `None` or `Any` will be [deprecated in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/336044). Please use `milestone_id` attribute instead. `milestone` and `milestone_id` are mutually exclusive. |
-| `milestone_id` | string | no | Returns issues assigned to milestones with a given timebox value (`None`, `Any`, `Upcoming`, and `Started`). `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. `Upcoming` lists all issues assigned to milestones due in the future. `Started` lists all issues assigned to open, started milestones. `milestone` and `milestone_id` are mutually exclusive. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335939) in GitLab 14.3)_ |
-| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
-| `non_archived` | boolean | no | Return issues only from non-archived projects. If `false`, the response returns issues from both archived and non-archived projects. Default is `true`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197170) in GitLab 13.0)_ |
-| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `assignee_id`, `assignee_username`, `author_id`, `author_username`, `iids`, `iteration_id`, `iteration_title`, `labels`, `milestone`, `milestone_id` and `weight`. |
-| `order_by` | string | no | Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, `updated_at`, or `weight` fields. Default is `created_at`. |
-| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`. |
-| `search` | string | no | Search issues against their `title` and `description` |
-| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
-| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
-| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `weight` **(PREMIUM)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
-| `with_labels_details` | boolean | no | If `true`, the response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. The `description_html` attribute was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7|
+| Attribute | Type | Required | Description |
+|---------------------------------|---------------| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. |
+| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE, the `assignee_username` array should only contain a single value. Otherwise, an invalid parameter error is returned. |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
+| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
+| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
+| `health_status` **(ULTIMATE)** | string | no | Return issues with the specified `health_status`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/370721) in GitLab 15.4)._ In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/370721), `None` returns issues with no health status assigned, and `Any` returns issues with a health status assigned.
+| `iids[]` | integer array | no | Return only the issues having the given `iid` |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
+| `issue_type` | string | no | Filter to a given type of issue. One of `issue`, `incident`, or `test_case`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260375) in GitLab 13.12)_ |
+| `iteration_id` **(PREMIUM)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
+| `iteration_title` **(PREMIUM)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. Using `None` or `Any` will be [deprecated in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/336044). Please use `milestone_id` attribute instead. `milestone` and `milestone_id` are mutually exclusive. |
+| `milestone_id` | string | no | Returns issues assigned to milestones with a given timebox value (`None`, `Any`, `Upcoming`, and `Started`). `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. `Upcoming` lists all issues assigned to milestones due in the future. `Started` lists all issues assigned to open, started milestones. `milestone` and `milestone_id` are mutually exclusive. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335939) in GitLab 14.3)_ |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
+| `non_archived` | boolean | no | Return issues only from non-archived projects. If `false`, the response returns issues from both archived and non-archived projects. Default is `true`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197170) in GitLab 13.0)_ |
+| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `assignee_id`, `assignee_username`, `author_id`, `author_username`, `iids`, `iteration_id`, `iteration_title`, `labels`, `milestone`, `milestone_id` and `weight`. |
+| `order_by` | string | no | Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, `updated_at`, or `weight` fields. Default is `created_at`. |
+| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`. |
+| `search` | string | no | Search issues against their `title` and `description` |
+| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
+| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
+| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
+| `weight` **(PREMIUM)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `with_labels_details` | boolean | no | If `true`, the response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. The `description_html` attribute was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7|
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/issues"
diff --git a/doc/api/issues_statistics.md b/doc/api/issues_statistics.md
index 7687124fb3a..cb08dc26b64 100644
--- a/doc/api/issues_statistics.md
+++ b/doc/api/issues_statistics.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issues statistics API **(FREE)**
diff --git a/doc/api/iterations.md b/doc/api/iterations.md
index c39c397f27e..5704bcd3418 100644
--- a/doc/api/iterations.md
+++ b/doc/api/iterations.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project iterations API **(PREMIUM)**
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index d1bd40b91b9..2a40f7c15ef 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Job Artifacts API **(FREE)**
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 1548045d7c2..fc2de00c3d2 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jobs API **(FREE)**
@@ -76,6 +76,9 @@ Example of response
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
+ "project": {
+ "ci_job_token_scope_enabled": false
+ },
"user": {
"id": 1,
"name": "Administrator",
@@ -132,6 +135,9 @@ Example of response
"failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
+ "project": {
+ "ci_job_token_scope_enabled": false
+ },
"user": {
"id": 1,
"name": "Administrator",
@@ -216,6 +222,9 @@ Example of response
"failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
+ "project": {
+ "ci_job_token_scope_enabled": false
+ },
"user": {
"id": 1,
"name": "Administrator",
@@ -281,6 +290,9 @@ Example of response
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
+ "project": {
+ "ci_job_token_scope_enabled": false
+ },
"user": {
"id": 1,
"name": "Administrator",
diff --git a/doc/api/keys.md b/doc/api/keys.md
index 99c9745d8f2..74d8bc4383f 100644
--- a/doc/api/keys.md
+++ b/doc/api/keys.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/labels.md b/doc/api/labels.md
index 5de227c8e1f..5851138a3a3 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Labels API **(FREE)**
diff --git a/doc/api/license.md b/doc/api/license.md
index eb576117d4a..72589710590 100644
--- a/doc/api/license.md
+++ b/doc/api/license.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Utilization
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# License **(FREE SELF)**
diff --git a/doc/api/linked_epics.md b/doc/api/linked_epics.md
index 0d2176dfc61..77540f37054 100644
--- a/doc/api/linked_epics.md
+++ b/doc/api/linked_epics.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Linked epics API **(ULTIMATE)**
diff --git a/doc/api/lint.md b/doc/api/lint.md
index ff7aa2f1fb9..c1d95f65a86 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# CI Lint API **(FREE)**
diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md
index 1a9be725b88..e9cab7f878a 100644
--- a/doc/api/managed_licenses.md
+++ b/doc/api/managed_licenses.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Utilization
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Managed Licenses API **(ULTIMATE)**
diff --git a/doc/api/markdown.md b/doc/api/markdown.md
index b66a07dc1d5..b4b700d24d6 100644
--- a/doc/api/markdown.md
+++ b/doc/api/markdown.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Markdown API **(FREE)**
diff --git a/doc/api/members.md b/doc/api/members.md
index aff601ba33f..52bc3f6f468 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group and project members API **(FREE)**
@@ -365,7 +365,8 @@ Example response:
"last_activity_on": "2021-01-27",
"membership_type": "group_member",
"removable": true,
- "created_at": "2021-01-03T12:16:02.000Z"
+ "created_at": "2021-01-03T12:16:02.000Z",
+ "last_login_at": "2022-10-09T01:33:06.000Z"
},
{
"id": 2,
@@ -378,7 +379,8 @@ Example response:
"last_activity_on": "2021-01-25",
"membership_type": "group_member",
"removable": true,
- "created_at": "2021-01-04T18:46:42.000Z"
+ "created_at": "2021-01-04T18:46:42.000Z",
+ "last_login_at": "2022-09-29T22:18:46.000Z"
},
{
"id": 3,
@@ -390,7 +392,8 @@ Example response:
"last_activity_on": "2021-01-20",
"membership_type": "group_invite",
"removable": false,
- "created_at": "2021-01-09T07:12:31.000Z"
+ "created_at": "2021-01-09T07:12:31.000Z",
+ "last_login_at": "2022-10-10T07:28:56.000Z"
}
]
```
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index 1fcce40a5b0..e65263030b1 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Merge request approvals API **(PREMIUM)**
diff --git a/doc/api/merge_request_context_commits.md b/doc/api/merge_request_context_commits.md
index 08020e5a613..f5e22c469a3 100644
--- a/doc/api/merge_request_context_commits.md
+++ b/doc/api/merge_request_context_commits.md
@@ -1,7 +1,7 @@
---
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 82125aec366..4667e48f233 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge requests API **(FREE)**
diff --git a/doc/api/merge_trains.md b/doc/api/merge_trains.md
index 1a4dfdbac2c..64ca2bf9b97 100644
--- a/doc/api/merge_trains.md
+++ b/doc/api/merge_trains.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge Trains API **(PREMIUM)**
diff --git a/doc/api/metadata.md b/doc/api/metadata.md
index 0f27960937d..3803173b0b8 100644
--- a/doc/api/metadata.md
+++ b/doc/api/metadata.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Metadata API **(FREE)**
diff --git a/doc/api/metrics_dashboard_annotations.md b/doc/api/metrics_dashboard_annotations.md
index 7732bf61d77..99d7b01d1a0 100644
--- a/doc/api/metrics_dashboard_annotations.md
+++ b/doc/api/metrics_dashboard_annotations.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/metrics_user_starred_dashboards.md b/doc/api/metrics_user_starred_dashboards.md
index 4f5fe1c909a..dbc6f64044f 100644
--- a/doc/api/metrics_user_starred_dashboards.md
+++ b/doc/api/metrics_user_starred_dashboards.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 48b6143a020..df09e374395 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project milestones API **(FREE)**
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 50c97d55f45..f75ebe5a881 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Namespaces API **(FREE)**
diff --git a/doc/api/notes.md b/doc/api/notes.md
index e0799cdd380..188d2697e6d 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Notes API **(FREE)**
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index 4b70a643263..d3e4a058b11 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Notification settings API **(FREE)**
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 0b7e0ba08eb..aca6ee74b15 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# OAuth 2.0 identity provider API **(FREE)**
@@ -37,7 +37,7 @@ For example, the `X-Requested-With` header can't be used for preflight requests.
GitLab supports the following authorization flows:
-- **Authorization code with [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636):**
+- **Authorization code with [Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636):**
Most secure. Without PKCE, you'd have to include client secrets on mobile clients,
and is recommended for both client and server apps.
- **Authorization code:** Secure and common flow. Recommended option for secure
@@ -48,7 +48,7 @@ GitLab supports the following authorization flows:
The draft specification for [OAuth 2.1](https://oauth.net/2.1/) specifically omits both the
Implicit grant and Resource Owner Password Credentials flows.
-Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out
+Refer to the [OAuth RFC](https://www.rfc-editor.org/rfc/rfc6749) to find out
how all those flows work and pick the right one for your use case.
Authorization code (with or without PKCE) flow requires `application` to be
@@ -75,15 +75,15 @@ For production, please use HTTPS for your `redirect_uri`.
For development, GitLab allows insecure HTTP redirect URIs.
As OAuth 2.0 bases its security entirely on the transport layer, you should not use unprotected
-URIs. For more information, see the [OAuth 2.0 RFC](https://tools.ietf.org/html/rfc6749#section-3.1.2.1)
-and the [OAuth 2.0 Threat Model RFC](https://tools.ietf.org/html/rfc6819#section-4.4.2.1).
+URIs. For more information, see the [OAuth 2.0 RFC](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2.1)
+and the [OAuth 2.0 Threat Model RFC](https://www.rfc-editor.org/rfc/rfc6819#section-4.4.2.1).
In the following sections you can find detailed instructions on how to obtain
authorization with each flow.
### Authorization code with Proof Key for Code Exchange (PKCE)
-The [PKCE RFC](https://tools.ietf.org/html/rfc7636#section-1.1) includes a
+The [PKCE RFC](https://www.rfc-editor.org/rfc/rfc7636#section-1.1) includes a
detailed flow description, from authorization request through access token.
The following steps describe our implementation of the flow.
@@ -177,7 +177,7 @@ You can now make requests to the API with the access token.
### Authorization code flow
NOTE:
-Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.1) for a
+Check the [RFC spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) for a
detailed flow description.
The authorization code flow is essentially the same as
@@ -257,7 +257,7 @@ You can now make requests to the API with the access token returned.
### Resource owner password credentials flow
NOTE:
-Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.3) for a
+Check the [RFC spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.3) for a
detailed flow description.
NOTE:
diff --git a/doc/api/openapi/openapi_interactive.md b/doc/api/openapi/openapi_interactive.md
index f83ac985131..1cf6ba6482c 100644
--- a/doc/api/openapi/openapi_interactive.md
+++ b/doc/api/openapi/openapi_interactive.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Interactive API documentation
diff --git a/doc/api/openapi/openapi_v2.yaml b/doc/api/openapi/openapi_v2.yaml
new file mode 100644
index 00000000000..59b21ecd048
--- /dev/null
+++ b/doc/api/openapi/openapi_v2.yaml
@@ -0,0 +1,90 @@
+---
+info:
+ title: GitLab API
+ version: v4
+swagger: '2.0'
+produces:
+- application/json
+securityDefinitions:
+ access_token_header:
+ type: apiKey
+ name: PRIVATE-TOKEN
+ in: header
+ access_token_query:
+ type: apiKey
+ name: private_token
+ in: query
+host: gitlab.com
+tags:
+- name: metadata
+ description: Operations related to metadata of the GitLab instance
+paths:
+ "/api/v4/metadata":
+ get:
+ summary: Retrieve metadata information for this GitLab instance.
+ description: This feature was introduced in GitLab 15.2.
+ produces:
+ - application/json
+ responses:
+ '200':
+ description: successful operation
+ schema:
+ "$ref": "#/definitions/API_Entities_Metadata"
+ examples:
+ successful_response:
+ value:
+ version: 15.0-pre
+ revision: c401a659d0c
+ kas:
+ enabled: true
+ externalUrl: grpc://gitlab.example.com:8150
+ version: 15.0.0
+ '401':
+ description: unauthorized operation
+ tags:
+ - metadata
+ operationId: getApiV4Metadata
+ "/api/v4/version":
+ get:
+ summary: Get the version information of the GitLab instance.
+ description: This feature was introduced in GitLab 8.13 and deprecated in 15.5.
+ We recommend you instead use the Metadata API.
+ produces:
+ - application/json
+ responses:
+ '200':
+ description: successful operation
+ schema:
+ "$ref": "#/definitions/API_Entities_Metadata"
+ examples:
+ Example:
+ value:
+ version: 15.0-pre
+ revision: c401a659d0c
+ kas:
+ enabled: true
+ externalUrl: grpc://gitlab.example.com:8150
+ version: 15.0.0
+ '401':
+ description: unauthorized operation
+ tags:
+ - metadata
+ operationId: getApiV4Version
+definitions:
+ API_Entities_Metadata:
+ type: object
+ properties:
+ version:
+ type: string
+ revision:
+ type: string
+ kas:
+ type: object
+ properties:
+ enabled:
+ type: boolean
+ externalUrl:
+ type: string
+ version:
+ type: string
+ description: API_Entities_Metadata model
diff --git a/doc/api/packages.md b/doc/api/packages.md
index d91f4f0de7b..4fd21a43a92 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Packages API **(FREE)**
diff --git a/doc/api/packages/composer.md b/doc/api/packages/composer.md
index ea2e917bbba..913831776d9 100644
--- a/doc/api/packages/composer.md
+++ b/doc/api/packages/composer.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Composer API **(FREE)**
diff --git a/doc/api/packages/conan.md b/doc/api/packages/conan.md
index 637c3d27d75..d0077d18c11 100644
--- a/doc/api/packages/conan.md
+++ b/doc/api/packages/conan.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Conan API **(FREE)**
diff --git a/doc/api/packages/debian.md b/doc/api/packages/debian.md
index 598124ba2b9..0e85e554f01 100644
--- a/doc/api/packages/debian.md
+++ b/doc/api/packages/debian.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Debian API **(FREE SELF)**
diff --git a/doc/api/packages/debian_group_distributions.md b/doc/api/packages/debian_group_distributions.md
index 0d0a4cb2cde..e3fabd92c51 100644
--- a/doc/api/packages/debian_group_distributions.md
+++ b/doc/api/packages/debian_group_distributions.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Debian group distributions API **(FREE SELF)**
diff --git a/doc/api/packages/debian_project_distributions.md b/doc/api/packages/debian_project_distributions.md
index 4f3ac62f576..f8ad7259866 100644
--- a/doc/api/packages/debian_project_distributions.md
+++ b/doc/api/packages/debian_project_distributions.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Debian project distributions API **(FREE SELF)**
diff --git a/doc/api/packages/go_proxy.md b/doc/api/packages/go_proxy.md
index ffafc387951..3a98c5acd2f 100644
--- a/doc/api/packages/go_proxy.md
+++ b/doc/api/packages/go_proxy.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Go Proxy API **(FREE SELF)**
diff --git a/doc/api/packages/helm.md b/doc/api/packages/helm.md
index 82b3f5225b0..b9888f2eed7 100644
--- a/doc/api/packages/helm.md
+++ b/doc/api/packages/helm.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Helm API **(FREE)**
diff --git a/doc/api/packages/maven.md b/doc/api/packages/maven.md
index 27bc4da07a1..6eb343dc7ab 100644
--- a/doc/api/packages/maven.md
+++ b/doc/api/packages/maven.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Maven API **(FREE)**
diff --git a/doc/api/packages/npm.md b/doc/api/packages/npm.md
index 846271015cc..a35fe630075 100644
--- a/doc/api/packages/npm.md
+++ b/doc/api/packages/npm.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.example/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.example/handbook/product/ux/technical-writing/#assignments
---
# npm API **(FREE)**
diff --git a/doc/api/packages/nuget.md b/doc/api/packages/nuget.md
index f25a3a25754..4c63524291b 100644
--- a/doc/api/packages/nuget.md
+++ b/doc/api/packages/nuget.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about..example/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about..example/handbook/product/ux/technical-writing/#assignments
---
# NuGet API **(FREE)**
diff --git a/doc/api/packages/pypi.md b/doc/api/packages/pypi.md
index e6204d87e1f..061de5bb9dd 100644
--- a/doc/api/packages/pypi.md
+++ b/doc/api/packages/pypi.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PyPI API **(FREE)**
diff --git a/doc/api/packages/rubygems.md b/doc/api/packages/rubygems.md
index 10dcaafda42..a87df17ab43 100644
--- a/doc/api/packages/rubygems.md
+++ b/doc/api/packages/rubygems.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ruby gems API **(FREE SELF)**
diff --git a/doc/api/packages/terraform-modules.md b/doc/api/packages/terraform-modules.md
index daafe0579e7..4c32e3f7cb4 100644
--- a/doc/api/packages/terraform-modules.md
+++ b/doc/api/packages/terraform-modules.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Terraform Registry API **(FREE)**
@@ -25,12 +25,12 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `module_namespace` | string | yes | The group to which Terraform module's project belongs. |
+| `module_namespace` | string | yes | The top-level group (namespace) to which Terraform module's project or subgroup belongs.|
| `module_name` | string | yes | The module name. |
| `module_system` | string | yes | The name of the module system or [provider](https://www.terraform.io/registry/providers). |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/versions"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/versions"
```
Example response:
@@ -88,7 +88,7 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system
| `module_system` | string | yes | The name of the module system or [provider](https://www.terraform.io/registry/providers). |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local"
```
Example response:
@@ -127,7 +127,7 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/
| `module_system` | string | yes | The name of the module system or [provider](https://www.terraform.io/registry/providers). |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0"
```
Example response:
@@ -166,7 +166,7 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/
| `module_system` | string | yes | The name of the module system or [provider](https://www.terraform.io/registry/providers). |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/download"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/download"
```
Example response:
@@ -195,7 +195,7 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/
| `module_version` | string | yes | Specific module version to download. |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/download"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/download"
```
Example response:
@@ -220,11 +220,11 @@ GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/
| `module_version` | string | yes | Specific module version to download. |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file"
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file"
```
To write the output to file:
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file" --output hello-world-local.tgz
+curl --header "Authorization: Bearer <personal_access_token>" "https://gitlab.example.com/api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file" --output hello-world-local.tgz
```
diff --git a/doc/api/pages.md b/doc/api/pages.md
index 57982188858..1855eaf153f 100644
--- a/doc/api/pages.md
+++ b/doc/api/pages.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pages API **(FREE)**
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index 1c2cfef8e1b..511098fa380 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pages domains API **(FREE)**
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index 849b5c75684..717e995f510 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Personal access tokens API **(FREE)**
@@ -12,24 +12,56 @@ You can read more about [personal access tokens](../user/profile/personal_access
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in GitLab 13.3.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) from GitLab Ultimate to GitLab Free in 13.6.
+> - `created_after`, `created_before`, `last_used_after`, `last_used_before`, `revoked`, `search` and `state` filters were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362248) in GitLab 15.5.
-Get a list of personal access tokens.
+Get all personal access tokens the authenticated user has access to. By default, returns an unfiltered list of:
+
+- Only personal access tokens created by the current user to a non-administrator.
+- All personal access tokens to an administrator.
+
+Administrators:
+
+- Can use the `user_id` parameter to filter by a user.
+- Can use other filters on all personal access tokens (GitLab 15.5 and later).
+
+Non-administrators:
+
+- Cannot use the `user_id` parameter to filter on any user except themselves, otherwise they receive a `401 Unauthorized` response.
+- Can only filter on their own personal access tokens (GitLab 15.5 and later).
```plaintext
GET /personal_access_tokens
+GET /personal_access_tokens?created_after=2022-01-01T00:00:00
+GET /personal_access_tokens?created_before=2022-01-01T00:00:00
+GET /personal_access_tokens?last_used_after=2022-01-01T00:00:00
+GET /personal_access_tokens?last_used_before=2022-01-01T00:00:00
+GET /personal_access_tokens?revoked=true
+GET /personal_access_tokens?search=name
+GET /personal_access_tokens?state=inactive
+GET /personal_access_tokens?user_id=1
```
-| Attribute | Type | required | Description |
-|-----------|---------|----------|---------------------|
-| `user_id` | integer/string | no | The ID of the user to filter by |
+Supported attributes:
-NOTE:
-Administrators can use the `user_id` parameter to filter by a user. Non-administrators cannot filter by any user except themselves. Attempting to do so will result in a `401 Unauthorized` response.
+| Attribute | Type | Required | Description |
+|---------------------|----------------|----------|---------------------|
+| `created_after` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs created after specified time. |
+| `created_before` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs created before specified time. |
+| `last_used_after` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs last used after specified time. |
+| `last_used_before` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs last used before specified time. |
+| `revoked` | boolean | **{dotted-circle}** No | Limit results to PATs with specified revoked state. Valid values are `true` and `false`. |
+| `search` | string | **{dotted-circle}** No | Limit results to PATs with name containing search string. |
+| `state` | string | **{dotted-circle}** No | Limit results to PATs with specified state. Valid values are `active` and `inactive`. |
+| `user_id` | integer or string | **{dotted-circle}** No | Limit results to PATs owned by specified user. |
+
+Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens"
```
+Example response:
+
```json
[
{
@@ -48,10 +80,14 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
+Example request:
+
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens?user_id=3"
```
+Example response:
+
```json
[
{
@@ -70,7 +106,46 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
-## Get single personal access token by ID
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens?revoked=true"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 41,
+ "name": "Revoked Test Token",
+ "revoked": true,
+ "created_at": "2022-01-01T14:31:47.729Z",
+ "scopes": [
+ "api"
+ ],
+ "user_id": 8,
+ "last_used_at": "2022-05-18T17:58:37.550Z",
+ "active": false,
+ "expires_at": null
+ }
+]
+```
+
+You can filter by merged attributes with:
+
+```plaintext
+GET /personal_access_tokens?revoked=true&created_before=2022-01-01
+```
+
+## Get single personal access token
+
+Get a personal access token by either:
+
+- Using the ID of the personal access token.
+- Passing it to the API in a header.
+
+### Using a personal access token ID
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362239) in GitLab 15.1.
@@ -81,7 +156,7 @@ Administrators can get any token.
GET /personal_access_tokens/:id
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer/string | yes | ID of personal access token |
@@ -89,7 +164,7 @@ GET /personal_access_tokens/:id
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens/<id>"
```
-### Responses
+#### Responses
> `404` HTTP status code [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93650) in GitLab 15.3.
@@ -98,6 +173,38 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
- The token with the specified ID doesn't exist.
- `404: Not Found` if the user is an administrator but the token with the specified ID doesn't exist.
+### Using a request header
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/373999) in GitLab 15.5
+
+Get a single personal access token by using passing the token in a header.
+
+```plaintext
+GET /personal_access_tokens/self
+```
+
+```shell
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens/self"
+```
+
+Example response:
+
+```json
+{
+ "id": 4,
+ "name": "Test Token",
+ "revoked": false,
+ "created_at": "2020-07-23T14:31:47.729Z",
+ "scopes": [
+ "api"
+ ],
+ "user_id": 3,
+ "last_used_at": "2021-10-06T17:58:37.550Z",
+ "active": true,
+ "expires_at": null
+}
+```
+
## Revoke a personal access token
Revoke a personal access token by either:
@@ -116,7 +223,7 @@ Revoke a personal access token using its ID.
DELETE /personal_access_tokens/:id
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer/string | yes | ID of personal access token |
diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md
index bbaf38aaaae..edab87f3478 100644
--- a/doc/api/pipeline_schedules.md
+++ b/doc/api/pipeline_schedules.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipeline schedules API **(FREE)**
diff --git a/doc/api/pipeline_triggers.md b/doc/api/pipeline_triggers.md
index 9f3120bd5d7..1fc29d2a654 100644
--- a/doc/api/pipeline_triggers.md
+++ b/doc/api/pipeline_triggers.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipeline trigger tokens API **(FREE)**
@@ -153,7 +153,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
Trigger a pipeline by using a pipeline [trigger token](../ci/triggers/index.md#create-a-trigger-token)
or a [CI/CD job token](../ci/jobs/ci_job_token.md) for authentication.
-With a CI/CD job token, the [triggered pipeline is a multi-project pipeline](../ci/jobs/ci_job_token.md#trigger-a-multi-project-pipeline-by-using-a-cicd-job-token).
+With a CI/CD job token, the [triggered pipeline is a multi-project pipeline](../ci/pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-by-using-the-api).
The job that authenticates the request becomes associated with the upstream pipeline,
which is visible on the [pipeline graph](../ci/pipelines/downstream_pipelines.md#view-multi-project-pipelines-in-pipeline-graphs).
@@ -170,7 +170,7 @@ Supported attributes:
| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `ref` | string | **{check-circle}** Yes | The branch or tag to run the pipeline on. |
| `token` | string | **{check-circle}** Yes | The trigger token or CI/CD job token. |
-| `variables` | array | **{dotted-circle}** 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`. |
+| `variables` | array | **{dotted-circle}** No | An [array of hashes](index.md#array-of-hashes) 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`. |
Example request:
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 23c55cfb177..a44d02982c0 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipelines API **(FREE)**
diff --git a/doc/api/plan_limits.md b/doc/api/plan_limits.md
index 0b6f89675d0..8f6a7ae3e8d 100644
--- a/doc/api/plan_limits.md
+++ b/doc/api/plan_limits.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Plan limits API **(FREE SELF)**
diff --git a/doc/api/product_analytics.md b/doc/api/product_analytics.md
index c3114baff8a..4653a52732a 100644
--- a/doc/api/product_analytics.md
+++ b/doc/api/product_analytics.md
@@ -1,7 +1,7 @@
---
stage: Analyze
group: Product Analytics
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Product analytics API
@@ -21,7 +21,7 @@ Make sure to define the `cube_api_base_url` and `cube_api_key` application setti
Generate an access token that can be used to query the Cube API. For example:
```plaintext
-POST /projects/:id/product_analytics/request
+POST /projects/:id/product_analytics/request/load
```
| Attribute | Type | Required | Description |
@@ -62,6 +62,7 @@ The body of the request should be a valid Cube query.
"Jitsu.docPath"
],
"limit": 23
- }
+ },
+ "queryType": "multi"
}
```
diff --git a/doc/api/project_access_tokens.md b/doc/api/project_access_tokens.md
index f76795f424e..4b74dacb996 100644
--- a/doc/api/project_access_tokens.md
+++ b/doc/api/project_access_tokens.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project access tokens API **(FREE)**
diff --git a/doc/api/project_aliases.md b/doc/api/project_aliases.md
index 0d130f6f484..6bad94f48b3 100644
--- a/doc/api/project_aliases.md
+++ b/doc/api/project_aliases.md
@@ -1,14 +1,12 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
# Project Aliases API **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in GitLab 12.1.
-
All methods require administrator authorization.
## List all project aliases
@@ -50,7 +48,7 @@ GET /project_aliases/:name
| Attribute | Type | Required | Description |
|-----------|--------|----------|-----------------------|
-| `name` | string | yes | The name of the alias |
+| `name` | string | **{check-circle}** Yes | The name of the alias. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_aliases/gitlab"
@@ -77,8 +75,8 @@ POST /project_aliases
| Attribute | Type | Required | Description |
|--------------|----------------|----------|----------------------------------------|
-| `project_id` | integer/string | yes | The ID or path of the project. |
-| `name` | string | yes | The name of the alias. Must be unique. |
+| `name` | string | **{check-circle}** Yes | The name of the alias. Must be unique. |
+| `project_id` | integer or string | **{check-circle}** Yes | The ID or path of the project. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@@ -113,7 +111,7 @@ DELETE /project_aliases/:name
| Attribute | Type | Required | Description |
|-----------|--------|----------|-----------------------|
-| `name` | string | yes | The name of the alias |
+| `name` | string | **{check-circle}** Yes | The name of the alias. |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_aliases/gitlab"
diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md
index 846c0241dd1..d83aa370808 100644
--- a/doc/api/project_badges.md
+++ b/doc/api/project_badges.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project badges API **(FREE)**
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index 87a629372d5..48fc669fe59 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project clusters API (certificate-based) (DEPRECATED) **(FREE)**
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 49a9b68227d..83d8746e1d0 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project import/export API **(FREE)**
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 39e7f441b42..d900e1da78c 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api
---
diff --git a/doc/api/project_relations_export.md b/doc/api/project_relations_export.md
index 74fdc91e420..fa6bdfa2900 100644
--- a/doc/api/project_relations_export.md
+++ b/doc/api/project_relations_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project Relations Export API **(FREE)**
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index 48c22ff2d93..429cb97c404 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project repository storage moves API **(FREE SELF)**
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index 0429c8abe3c..29d3b38f977 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project snippets **(FREE)**
diff --git a/doc/api/project_statistics.md b/doc/api/project_statistics.md
index c0a1227b295..7d8cc19457a 100644
--- a/doc/api/project_statistics.md
+++ b/doc/api/project_statistics.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index 14dd0761487..ae366e35f91 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project templates API **(FREE)**
diff --git a/doc/api/project_vulnerabilities.md b/doc/api/project_vulnerabilities.md
index 1267f748633..b1eb1b958ee 100644
--- a/doc/api/project_vulnerabilities.md
+++ b/doc/api/project_vulnerabilities.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 26733801b45..470b3721b23 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Projects API **(FREE)**
@@ -61,7 +61,7 @@ GET /projects
| `repository_storage` | string | **{dotted-circle}** No | Limit results to projects stored on `repository_storage`. _(administrators only)_ |
| `search_namespaces` | boolean | **{dotted-circle}** No | Include ancestor namespaces when matching search criteria. Default is `false`. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
-| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. Only available to Reporter or higher level role members. |
@@ -336,7 +336,7 @@ GET /users/:user_id/projects
| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
-| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. Only available to Reporter or higher level role members. |
@@ -591,7 +591,7 @@ GET /users/:user_id/starred_projects
| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
-| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. Only available to Reporter or higher level role members. |
@@ -1014,6 +1014,19 @@ can also see the `approvals_before_merge` parameter:
}
```
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/)
+can also see the `only_allow_merge_if_all_status_checks_passed`
+parameters using GitLab 15.5 and later:
+
+```json
+{
+ "id": 1,
+ "project_id": 3,
+ "only_allow_merge_if_all_status_checks_passed": false,
+ ...
+}
+```
+
If the project is a fork, the `forked_from_project` field appears in the response.
For this field, if the upstream project is private, a valid token for authentication must be provided.
The field `mr_default_target_self` appears as well. If this value is `false`, then all merge requests
@@ -1188,6 +1201,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your-token>" \
| `name` | string | **{check-circle}** Yes (if path isn't provided) | The name of the new project. Equals path if not provided. |
| `path` | string | **{check-circle}** Yes (if name isn't provided) | Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes). Starting with GitLab 14.9, path must not start or end with a special character and must not contain consecutive special characters. |
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `only_allow_merge_if_all_status_checks_passed` **(ULTIMATE)** | boolean | **{dotted-circle}** No | Indicates that merges of merge requests should be blocked unless all status checks have passed. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369859) in GitLab 15.5 with feature flag `only_allow_merge_if_all_status_checks_passed` disabled by default. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
@@ -1229,6 +1243,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your-token>" \
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
| `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. |
+| `releases_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrator only)_ |
@@ -1266,6 +1281,7 @@ POST /projects/user/:user_id
| `user_id` | integer | **{check-circle}** Yes | The user ID of the project owner. |
| `name` | string | **{check-circle}** Yes | The name of the new project. |
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `only_allow_merge_if_all_status_checks_passed` **(ULTIMATE)** | boolean | **{dotted-circle}** No | Indicates that merges of merge requests should be blocked unless all status checks have passed. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369859) in GitLab 15.5 with feature flag `only_allow_merge_if_all_status_checks_passed` disabled by default. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
@@ -1307,6 +1323,7 @@ POST /projects/user/:user_id
| `path` | string | **{dotted-circle}** No | Custom repository name for new project. By default generated based on name. |
| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project-members. |
+| `releases_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrators only)_ |
@@ -1355,6 +1372,7 @@ Supported attributes:
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
+| `only_allow_merge_if_all_status_checks_passed` **(ULTIMATE)** | boolean | **{dotted-circle}** No | Indicates that merges of merge requests should be blocked unless all status checks have passed. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369859) in GitLab 15.5 with feature flag `only_allow_merge_if_all_status_checks_passed` disabled by default. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
@@ -1408,6 +1426,7 @@ Supported attributes:
| `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. |
+| `releases_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `repository_storage` | string | **{dotted-circle}** No | Which storage shard the repository is on. _(administrators only)_ |
@@ -1473,7 +1492,7 @@ GET /projects/:id/forks
| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
| `owned` | boolean | **{dotted-circle}** No | Limit by projects explicitly owned by the current user. |
| `search` | string | **{dotted-circle}** No | Return list of projects matching the search criteria. |
-| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `simple` | boolean | **{dotted-circle}** No | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. Only available to Reporter or higher level role members. |
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index ea2412515a0..620cb0e0bae 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Protected branches API **(FREE)**
diff --git a/doc/api/protected_environments.md b/doc/api/protected_environments.md
index 5b52d11feda..9ff3c34d2d7 100644
--- a/doc/api/protected_environments.md
+++ b/doc/api/protected_environments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md
index b2ab3227a7e..c8e7117e5a9 100644
--- a/doc/api/protected_tags.md
+++ b/doc/api/protected_tags.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Protected tags API **(FREE)**
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index e286fefc462..e3b1d9230f6 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Releases API **(FREE)**
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
index f9e07991948..050d7cabdf9 100644
--- a/doc/api/releases/links.md
+++ b/doc/api/releases/links.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Release links API **(FREE)**
diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md
index 351706e8514..1013ffb49fb 100644
--- a/doc/api/remote_mirrors.md
+++ b/doc/api/remote_mirrors.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 7d94edc0872..751bbd75c7a 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
@@ -9,16 +9,19 @@ type: reference, api
## List repository tree
+> Iterating pages of results with a number (`?page=2`) [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67509) in GitLab 14.3.
+
Get a list of repository files and directories in a project. This endpoint can
be accessed without authentication if the repository is publicly accessible.
-This command provides essentially the same functionality as the `git ls-tree` command. For more information, see the section _Tree Objects_ in the [Git internals documentation](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects/#_tree_objects).
+This command provides essentially the same features as the `git ls-tree`
+command. For more information, refer to the section
+[Tree Objects](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects/#_tree_objects)
+in the Git internals documentation.
WARNING:
-This endpoint is changing to keyset-based pagination. Iterating pages of results
-with a number (`?page=2`) [is deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67509).
-Support for iterating with a number became supported in GitLab 15.0. Use
-the new [keyset pagination system](index.md#keyset-based-pagination) instead.
+This endpoint changed to [keyset-based pagination](index.md#keyset-based-pagination)
+in GitLab 15.0. Iterating pages of results with a number (`?page=2`) is unsupported.
```plaintext
GET /projects/:id/repository/tree
@@ -29,12 +32,12 @@ Supported attributes:
| 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. |
-| `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). |
-| `per_page` | integer | no | Number of results to show per page. If not specified, defaults to `20`. [Learn more on pagination](index.md#pagination). |
-| `pagination` | string | no | If set to `keyset`, use the new keyset pagination method. |
| `page_token` | string | no | The tree record ID at which to fetch the next page. Used only with keyset pagination. |
+| `pagination` | string | no | If `keyset`, use the [keyset-based pagination method](index.md#keyset-based-pagination). |
+| `path` | string | no | The path inside the repository. Used to get content of subdirectories. |
+| `per_page` | integer | no | Number of results to show per page. If not specified, defaults to `20`. [Learn more on pagination](index.md#pagination). |
+| `recursive` | boolean | no | Boolean value used to get a recursive tree. Default is `false`. |
+| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch. |
```json
[
@@ -92,9 +95,9 @@ Supported attributes:
## Get a blob from repository
-Allows you to receive information about blob in repository like size and
-content. Blob content is Base64 encoded. This endpoint can be accessed
-without authentication if the repository is publicly accessible.
+Allows you to receive information, such as size and content, about blobs in a repository.
+Blob content is Base64 encoded. This endpoint can be accessed without authentication,
+if the repository is publicly accessible.
```plaintext
GET /projects/:id/repository/blobs/:sha
@@ -109,7 +112,7 @@ Supported attributes:
## Raw blob content
-Get the raw file contents for a blob by blob SHA. This endpoint can be accessed
+Get the raw file contents for a blob, by blob SHA. This endpoint can be accessed
without authentication if the repository is publicly accessible.
```plaintext
@@ -131,24 +134,32 @@ Supported attributes:
Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
-This endpoint has a rate limit threshold of 5 requests per minute for GitLab.com users.
+For GitLab.com users, this endpoint has a rate limit threshold of 5 requests per minute.
```plaintext
GET /projects/:id/repository/archive[.format]
```
-`format` is an optional suffix for the archive format. Default is
-`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, `tbz2`, `tb2`,
-`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
-would send an archive in ZIP format.
+`format` is an optional suffix for the archive format, and defaults to
+`tar.gz`. For example, specifying `archive.zip` sends an archive in ZIP format.
+Available options are:
+
+- `bz2`
+- `tar`
+- `tar.bz2`
+- `tar.gz`
+- `tb2`
+- `tbz`
+- `tbz2`
+- `zip`
Supported attributes:
| 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. |
-| `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). |
+| `path` | string | no | The subpath of the repository to download. If an empty string, defaults to the whole repository. |
+| `sha` | string | no | The commit SHA to download. A tag, branch reference, or SHA can be used. If not specified, defaults to the tip of the default branch. |
Example request:
@@ -159,7 +170,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/pr
## Compare branches, tags or commits
This endpoint can be accessed without authentication if the repository is
-publicly accessible. Diffs can have an empty diff string if [diff limits](../development/diffs.md#diff-limits) are reached.
+publicly accessible. Diffs can have an empty diff string if
+[diff limits](../development/diffs.md#diff-limits) are reached.
```plaintext
GET /projects/:id/repository/compare
@@ -172,8 +184,8 @@ Supported attributes:
| `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 |
-| `straight` | boolean | no | Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`. |
+| `from_project_id` | integer | no | The ID to compare from. |
+| `straight` | boolean | no | Comparison method: `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`. |
```plaintext
GET /projects/:id/repository/compare?from=master&to=feature
@@ -217,6 +229,9 @@ Example response:
## Contributors
+> - Attributes `additions` and `deletions` [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39653) in GitLab 13.4, because they [always returned `0`](https://gitlab.com/gitlab-org/gitlab/-/issues/233119).
+> - Attributes `additions` and `deletions` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38920) in GitLab 14.0.
+
Get repository contributors list. This endpoint can be accessed without
authentication if the repository is publicly accessible.
@@ -224,9 +239,6 @@ authentication if the repository is publicly accessible.
GET /projects/:id/repository/contributors
```
-WARNING:
-The `additions` and `deletions` attributes are [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39653) as of GitLab 13.4, because they [always return `0`](https://gitlab.com/gitlab-org/gitlab/-/issues/233119).
-
Supported attributes:
| Attribute | Type | Required | Description |
@@ -255,16 +267,16 @@ Example response:
## Merge Base
-Get the common ancestor for 2 or more refs (commit SHAs, branch names or tags).
+Get the common ancestor for 2 or more refs, such as commit SHAs, branch names, or tags.
```plaintext
GET /projects/:id/repository/merge_base
```
| Attribute | Type | Required | Description |
-| --------- | -------------- | -------- | ------------------------------------------------------------------------------- |
-| `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 |
+| --------- | -------------- | -------- | ---------------------------------------------------------------------------------- |
+| `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. Accepts multiple refs. |
Example request:
@@ -293,17 +305,16 @@ Example response:
## Add changelog data to a changelog file
-> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/351) in GitLab 13.9.
+> - [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/351) in GitLab 13.9.
+> - Commit range limits [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89032) in GitLab 15.1 [with a flag](../administration/feature_flags.md) named `changelog_commits_limitation`. Enabled by default.
Generate changelog data based on commits in a repository.
-Given a version (using [semantic versioning](https://semver.org/)) and a range
+Given a [semantic version](https://semver.org/) and a range
of commits, GitLab generates a changelog for all commits that use a particular
-[Git trailer](https://git-scm.com/docs/git-interpret-trailers).
-
-The output of this process is a new section in a changelog file in the Git
-repository of the given project. The output format is in Markdown, and can be
-customized.
+[Git trailer](https://git-scm.com/docs/git-interpret-trailers). GitLab adds
+a new Markdown-formatted section to a changelog file in the Git repository of
+the project. The output format can be customized.
```plaintext
POST /projects/:id/repository/changelog
@@ -314,30 +325,21 @@ 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, defaults to the current time. |
-| `branch` | string | no | The branch to commit the changelog changes to, defaults to the project's default branch. |
-| `trailer` | string | no | The Git trailer to use for including commits, defaults to `Changelog`. |
+| `branch` | string | no | The branch to commit the changelog changes to. Defaults to the project's default branch. |
| `config_file` | string | no | Path to the changelog configuration file in the project's Git repository. Defaults to `.gitlab/changelog_config.yml`. |
-| `file` | string | no | The file to commit the changes to, defaults to `CHANGELOG.md`. |
-| `message` | string | no | The commit message to produce when committing the changes, defaults to `Add changelog for version X` where X is the value of the `version` argument. |
+| `date` | datetime | no | The date and time of the release. Defaults to the current time. |
+| `file` | string | no | The file to commit the changes to. Defaults to `CHANGELOG.md`. |
+| `from` | string | no | The SHA of the commit that marks the beginning of the range of commits to include in the changelog. This commit isn't included in the changelog. |
+| `message` | string | no | The commit message to use when committing the changes. Defaults to `Add changelog for version X`, where `X` is the value of the `version` argument. |
+| `to` | string | no | The SHA of the commit that marks the end of the range of commits to include in the changelog. This commit _is_ included in the changelog. Defaults to the branch specified in the `branch` attribute. Limited to 15000 commits unless the feature flag `changelog_commits_limitation` is disabled. |
+| `trailer` | string | no | The Git trailer to use for including commits. Defaults to `Changelog`. Case-sensitive: `Example` does not match `example` or `eXaMpLE`. |
-WARNING:
-GitLab treats trailers case-sensitively. If you set the `trailer` field to
-`Example`, GitLab _won't_ include commits that use the trailer `example`,
-`eXaMpLE`, or anything else that isn't _exactly_ `Example`.
-
-WARNING:
-The allowed commits range between `from` and `to` is limited to 15000 commits. To disable
-this restriction, [turn off the feature flag](../administration/feature_flags.md)
-`changelog_commits_limitation`.
+### Requirements for `from` attribute
If the `from` attribute is unspecified, GitLab uses the Git tag of the last
stable version that came before the version specified in the `version`
-attribute. This requires that Git tag names follow a specific format, allowing
-GitLab to extract a version from the tag names. By default, GitLab considers
-tags using these formats:
+attribute. For GitLab to extract version numbers from tag names, Git tag names
+must follow a specific format. By default, GitLab considers tags using these formats:
- `vX.Y.Z`
- `X.Y.Z`
@@ -350,7 +352,7 @@ For example, consider a project with the following tags:
- v1.1.0
- v2.0.0
-If the `version` attribute is `2.1.0`, GitLab uses tag v2.0.0. And when the
+If the `version` attribute is `2.1.0`, GitLab uses tag `v2.0.0`. And when the
version is `1.1.1`, or `1.2.0`, GitLab uses tag v1.1.0. The tag `v1.0.0-pre1` is
never used, because pre-release tags are ignored.
@@ -372,7 +374,8 @@ This command generates a changelog for version `1.0.0`.
The commit range:
- Starts with the tag of the last release.
-- Ends with the last commit on the target branch. The default target branch is the project's default branch.
+- Ends with the last commit on the target branch. The default target branch is
+ the project's default branch.
If the last tag is `v0.9.0` and the default branch is `main`, the range of commits
included in this example is `v0.9.0..main`:
@@ -638,28 +641,28 @@ At the top level, the following variable is available:
In a category, the following variables are available:
-- `title`: the title of the category (after it has been remapped).
- `count`: the number of entries in this category.
+- `entries`: the entries that belong to this category.
- `single_change`: a boolean that indicates if there is only one change (`true`),
or multiple changes (`false`).
-- `entries`: the entries that belong to this category.
+- `title`: the title of the category (after it has been remapped).
In an entry, the following variables are available (here `foo.bar` means that
`bar` is a sub-field of `foo`):
-- `title`: the title of the changelog entry (this is the commit title).
-- `commit.reference`: a reference to the commit, for example,
- `gitlab-org/gitlab@0a4cdd86ab31748ba6dac0f69a8653f206e5cfc7`.
-- `commit.trailers`: an object containing all the Git trailers that were present
- in the commit body.
-- `author.reference`: a reference to the commit author (for example, `@alice`).
- `author.contributor`: a boolean set to `true` when the author is not a project
member, otherwise `false`.
- `author.credit`: a boolean set to `true` when `author.contributor` is `true` or
when `include_groups` is configured, and the author is a member of one of the
groups.
+- `author.reference`: a reference to the commit author (for example, `@alice`).
+- `commit.reference`: a reference to the commit, for example,
+ `gitlab-org/gitlab@0a4cdd86ab31748ba6dac0f69a8653f206e5cfc7`.
+- `commit.trailers`: an object containing all the Git trailers that were present
+ in the commit body.
- `merge_request.reference`: a reference to the merge request that first
introduced the change (for example, `gitlab-org/gitlab!50063`).
+- `title`: the title of the changelog entry (this is the commit title).
The `author` and `merge_request` objects might not be present if the data
couldn't be determined. For example, when a commit is created without a
@@ -732,11 +735,11 @@ 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/). |
+| `config_file` | string | no | The path of changelog configuration file in the project's Git repository, defaults to `.gitlab/changelog_config.yml`. |
+| `date` | datetime | no | The date and time of the release, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z`. Defaults to the current time. |
| `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`. |
-| `config_file` | string | no | The path of changelog configuration file in the project's Git repository, defaults to `.gitlab/changelog_config.yml`. |
```shell
curl --header "PRIVATE-TOKEN: token" "https://gitlab.com/api/v4/projects/42/repository/changelog?version=1.0.0"
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 8097fecea87..9f06467964b 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md
index cbd6a369e97..1dd65ed60b8 100644
--- a/doc/api/repository_submodules.md
+++ b/doc/api/repository_submodules.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository submodules API **(FREE)**
diff --git a/doc/api/resource_groups.md b/doc/api/resource_groups.md
index f70ad2f09e7..114dc4e383e 100644
--- a/doc/api/resource_groups.md
+++ b/doc/api/resource_groups.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource group API **(FREE)**
@@ -63,6 +63,101 @@ Example of response
}
```
+## List upcoming jobs for a specific resource group
+
+```plaintext
+GET /projects/:id/resource_groups/:key/upcoming_jobs
+```
+
+| 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 |
+| `key` | string | yes | The key of the resource group |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/50/resource_groups/production/upcoming_jobs"
+```
+
+Example of response
+
+```json
+[
+ {
+ "id": 1154,
+ "status": "waiting_for_resource",
+ "stage": "deploy",
+ "name": "deploy_to_production",
+ "ref": "main",
+ "tag": false,
+ "coverage": null,
+ "allow_failure": false,
+ "created_at": "2022-09-28T09:57:04.590Z",
+ "started_at": null,
+ "finished_at": null,
+ "duration": null,
+ "queued_duration": null,
+ "user": {
+ "id": 1,
+ "username": "john_smith",
+ "name": "John Smith",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/2d691a4d0427ca8db6efc3924a6408ba?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/john_smith",
+ "created_at": "2022-05-27T19:19:17.526Z",
+ "bio": "",
+ "location": null,
+ "public_email": null,
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": null,
+ "job_title": "",
+ "pronouns": null,
+ "bot": false,
+ "work_information": null,
+ "followers": 0,
+ "following": 0,
+ "local_time": null
+ },
+ "commit": {
+ "id": "3177f39064891bbbf5124b27850c339da331f02f",
+ "short_id": "3177f390",
+ "created_at": "2022-09-27T17:55:31.000+02:00",
+ "parent_ids": [
+ "18059e45a16eaaeaddf6fc0daf061481549a89df"
+ ],
+ "title": "List upcoming jobs",
+ "message": "List upcoming jobs",
+ "author_name": "Example User",
+ "author_email": "user@example.com",
+ "authored_date": "2022-09-27T17:55:31.000+02:00",
+ "committer_name": "Example User",
+ "committer_email": "user@example.com",
+ "committed_date": "2022-09-27T17:55:31.000+02:00",
+ "trailers": {},
+ "web_url": "https://gitlab.example.com/test/gitlab/-/commit/3177f39064891bbbf5124b27850c339da331f02f"
+ },
+ "pipeline": {
+ "id": 274,
+ "iid": 9,
+ "project_id": 50,
+ "sha": "3177f39064891bbbf5124b27850c339da331f02f",
+ "ref": "main",
+ "status": "waiting_for_resource",
+ "source": "web",
+ "created_at": "2022-09-28T09:57:04.538Z",
+ "updated_at": "2022-09-28T09:57:13.537Z",
+ "web_url": "https://gitlab.example.com/test/gitlab/-/pipelines/274"
+ },
+ "web_url": "https://gitlab.example.com/test/gitlab/-/jobs/1154",
+ "project": {
+ "ci_job_token_scope_enabled": false
+ }
+ }
+]
+```
+
## Edit an existing resource group
Updates an existing resource group's properties.
diff --git a/doc/api/resource_iteration_events.md b/doc/api/resource_iteration_events.md
index 37a945b140e..41e1ddd725b 100644
--- a/doc/api/resource_iteration_events.md
+++ b/doc/api/resource_iteration_events.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource iteration events API **(PREMIUM)**
diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md
index da265972f28..62a37806459 100644
--- a/doc/api/resource_label_events.md
+++ b/doc/api/resource_label_events.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource label events API **(FREE)**
diff --git a/doc/api/resource_milestone_events.md b/doc/api/resource_milestone_events.md
index 448ec6e2c1d..d1e0b4fe053 100644
--- a/doc/api/resource_milestone_events.md
+++ b/doc/api/resource_milestone_events.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource milestone events API **(FREE)**
diff --git a/doc/api/resource_state_events.md b/doc/api/resource_state_events.md
index 8e957df8145..5ea588167a0 100644
--- a/doc/api/resource_state_events.md
+++ b/doc/api/resource_state_events.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource state events API **(FREE)**
diff --git a/doc/api/resource_weight_events.md b/doc/api/resource_weight_events.md
index faa2d543c50..14596556b7b 100644
--- a/doc/api/resource_weight_events.md
+++ b/doc/api/resource_weight_events.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource weight events API **(FREE)**
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 8af388a2b74..657eb4d470c 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Runners API **(FREE)**
diff --git a/doc/api/saml.md b/doc/api/saml.md
new file mode 100644
index 00000000000..810ed382d49
--- /dev/null
+++ b/doc/api/saml.md
@@ -0,0 +1,78 @@
+---
+stage: Manage
+group: Authentication and Authorization
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# SAML API **(PREMIUM SAAS)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5.
+
+API for accessing SAML features.
+
+## Get SAML identities for a group
+
+```plaintext
+GET /groups/:id/saml/identities
+```
+
+Fetch SAML identities for a group.
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:------------------|:--------|:---------|:----------------------|
+| `id` | integer | Yes | Group ID for the group to return SAML identities. |
+
+If successful, returns [`200`](index.md#status-codes) and the following
+response attributes:
+
+| Attribute | Type | Description |
+| ------------ | ------ | ------------------------- |
+| `extern_uid` | string | External UID for the user |
+| `user_id` | string | ID for the user |
+
+Example request:
+
+```shell
+curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/saml/identities" \
+--header "<PRIVATE-TOKEN>" \
+--form "extern_uid=<ID_TO_BE_UPDATED>" \
+```
+
+Example response:
+
+```json
+[
+ {
+ "extern_uid": "4",
+ "user_id": 48
+ }
+]
+```
+
+## Update `extern_uid` field for a SAML identity
+
+Update `extern_uid` field for a SAML identity. Field that can be updated are:
+
+| SAML IdP attribute | GitLab field |
+| ------------------ | ------------ |
+| `id/externalId` | `extern_uid` |
+
+```plaintext
+PATCH groups/:groups_id/saml/:uid
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ------------------------- |
+| `uid` | string | yes | External UID of the user. |
+
+Example request:
+
+```shell
+curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/saml/sydney_jones" \
+--header "<PRIVATE TOKEN>" \
+--form "extern_uid=sydney_jones_new" \
+```
diff --git a/doc/api/scim.md b/doc/api/scim.md
index 9c88997b94c..b1763a44fc4 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -2,253 +2,82 @@
type: reference, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
+# SCIM API **(PREMIUM SAAS)**
-# SCIM API (SYSTEM ONLY) **(PREMIUM SAAS)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10.
-
-The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc7644). As this API is for
-**system** use for SCIM provider integration, it is subject to change without notice.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98354) in GitLab 15.5.
To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group.
This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities.
-## Get a list of SCIM provisioned users
-
-This endpoint is used as part of the SCIM syncing mechanism. It only returns
-a single user based on a unique ID which should match the `extern_uid` of the user.
-
-```plaintext
-GET /api/scim/v2/groups/:group_path/Users
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
-| `filter` | string | no | A [filter](#available-filters) expression. |
-| `group_path` | string | yes | Full path to the group. |
-| `startIndex` | integer | no | The 1-based index indicating where to start returning results from. A value of less than one will be interpreted as 1. |
-| `count` | integer | no | Desired maximum number of query results. |
-
-NOTE:
-Pagination follows the [SCIM spec](https://tools.ietf.org/html/rfc7644#section-3.4.2.4) rather than GitLab pagination as used elsewhere. If records change between requests it is possible for a page to either be missing records that have moved to a different page or repeat records from a previous request.
-
-Example request:
-
-```shell
-curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" \
- --header "Authorization: Bearer <your_scim_token>" \
- --header "Content-Type: application/scim+json"
-```
-
-Example response:
+Not to be confused with the [internal SCIM API](../development/internal_api/index.md#scim-api).
-```json
-{
- "schemas": [
- "urn:ietf:params:scim:api:messages:2.0:ListResponse"
- ],
- "totalResults": 1,
- "itemsPerPage": 20,
- "startIndex": 1,
- "Resources": [
- {
- "schemas": [
- "urn:ietf:params:scim:schemas:core:2.0:User"
- ],
- "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
- "active": true,
- "name.formatted": "Test User",
- "userName": "username",
- "meta": { "resourceType":"User" },
- "emails": [
- {
- "type": "work",
- "value": "name@example.com",
- "primary": true
- }
- ]
- }
- ]
-}
-```
+## Get SCIM identities for a group
-## Get a single SCIM provisioned user
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5.
```plaintext
-GET /api/scim/v2/groups/:group_path/Users/:id
+GET /groups/:id/scim/identities
```
-Parameters:
+Supported attributes:
-| Attribute | Type | Required | Description |
-|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | string | yes | External UID of the user. |
-| `group_path` | string | yes | Full path to the group. |
+| Attribute | Type | Required | Description |
+|:------------------|:--------|:---------|:----------------------|
+| `id` | integer | Yes | Return SAML identities for the given group ID. |
-Example request:
+If successful, returns [`200`](index.md#status-codes) and the following
+response attributes:
-```shell
-curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
- --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
-```
+| Attribute | Type | Description |
+| ------------ | ------ | ------------------------- |
+| `extern_uid` | string | External UID for the user |
+| `user_id` | string | ID for the user |
Example response:
```json
-{
- "schemas": [
- "urn:ietf:params:scim:schemas:core:2.0:User"
- ],
- "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
- "active": true,
- "name.formatted": "Test User",
- "userName": "username",
- "meta": { "resourceType":"User" },
- "emails": [
+[
{
- "type": "work",
- "value": "name@example.com",
- "primary": true
+ "extern_uid": "4",
+ "user_id": 48
}
- ]
-}
+]
```
-## Create a SCIM provisioned user
-
-```plaintext
-POST /api/scim/v2/groups/:group_path/Users/
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|:---------------|:----------|:----|:--------------------------|
-| `externalId` | string | yes | External UID of the user. |
-| `userName` | string | yes | Username of the user. |
-| `emails` | JSON string | yes | Work email. |
-| `name` | JSON string | yes | Name of the user. |
-| `meta` | string | no | Resource type (`User`). |
-
Example request:
```shell
-curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" \
- --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' \
- --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
-```
-
-Example response:
-
-```json
-{
- "schemas": [
- "urn:ietf:params:scim:schemas:core:2.0:User"
- ],
- "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
- "active": true,
- "name.formatted": "Test User",
- "userName": "username",
- "meta": { "resourceType":"User" },
- "emails": [
- {
- "type": "work",
- "value": "name@example.com",
- "primary": true
- }
- ]
-}
+curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/scim/identities" \
+--header "<PRIVATE-TOKEN>" \
+--form "extern_uid=<ID_TO_BE_UPDATED>" \
```
-Returns a `201` status code if successful.
+## Update extern_uid field for a SCIM identity
-## Update a single SCIM provisioned user
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5.
Fields that can be updated are:
-| SCIM/IdP field | GitLab field |
-|:---------------------------------|:-----------------------------------------------------------------------------|
-| `id/externalId` | `extern_uid` |
-| `name.formatted` | `name` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
-| `emails\[type eq "work"\].value` | `email` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
-| `active` | Identity removal if `active` = `false` |
-| `userName` | `username` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
-
-```plaintext
-PATCH /api/scim/v2/groups/:group_path/Users/:id
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | string | yes | External UID of the user. |
-| `group_path` | string | yes | Full path to the group. |
-| `Operations` | JSON string | yes | An [operations](#available-operations) expression. |
-
-Example request:
-
-```shell
-curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
- --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' \
- --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
-```
-
-Returns an empty response with a `204` status code if successful.
-
-## Remove a single SCIM provisioned user
-
-Removes the user's SSO identity and group membership.
+| SCIM/IdP field | GitLab field |
+| --------------- | ------------ |
+| `id/externalId` | `extern_uid` |
```plaintext
-DELETE /api/scim/v2/groups/:group_path/Users/:id
+PATCH groups/:groups_id/scim/:uid
```
Parameters:
-| Attribute | Type | Required | Description |
-|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | string | yes | External UID of the user. |
-| `group_path` | string | yes | Full path to the group. |
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ------------------------- |
+| `uid` | string | yes | External UID of the user. |
Example request:
```shell
-curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
- --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
-```
-
-Returns an empty response with a `204` status code if successful.
-
-## Available filters
-
-They match an expression as specified in [the RFC7644 filtering section](https://tools.ietf.org/html/rfc7644#section-3.4.2.2).
-
-| Filter | Description |
-| ----- | ----------- |
-| `eq` | The attribute matches exactly the specified value. |
-
-Example:
-
-```plaintext
-id eq a-b-c-d
-```
-
-## Available operations
-
-They perform an operation as specified in [the RFC7644 update section](https://tools.ietf.org/html/rfc7644#section-3.5.2).
-
-| Operator | Description |
-| ----- | ----------- |
-| `Replace` | The attribute's value is updated. |
-| `Add` | The attribute has a new value. |
-
-Example:
-
-```json
-{ "op": "Add", "path": "name.formatted", "value": "New Name" }
+curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/scim/sydney_jones" \
+--header "<PRIVATE TOKEN>" \
+--form "extern_uid=sydney_jones_new" \
```
diff --git a/doc/api/search.md b/doc/api/search.md
index 4e644a6c087..a59f943319c 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -1,6 +1,6 @@
---
-stage: Create
-group: Source Code
+stage: Data Stores
+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
---
@@ -10,28 +10,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Every API call to search must be authenticated.
+## Additional scopes **(PREMIUM)**
+
+Additional scopes are available for the [Advanced Search API](#advanced-search-api)
+and [Group Search API](#group-search-api) if
+[Elasticsearch is enabled](../integration/advanced_search/elasticsearch.md):
+`blobs`, `commits`, `notes`, `wiki_blobs`.
+
## Advanced Search API
-Search globally across the GitLab instance.
+Search for an expression globally across the GitLab instance, in a specified scope.
+The response depends on the requested scope.
```plaintext
GET /search
```
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `scope` | string | yes | The scope to search in |
-| `search` | string | yes | The search query |
-| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
-| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-
-Search the expression in the specified scope. These scopes are supported: `projects`, `issues`, `merge_requests`, `milestones`, `snippet_titles`, `users`.
-
-If Elasticsearch is enabled additional scopes available are `blobs`, `wiki_blobs`, `notes`, and `commits`. Find more about [the feature](../integration/advanced_search/elasticsearch.md). **(PREMIUM)**
-
-The response depends on the requested scope.
+| Attribute | Type | Required | Description |
+| ------------- | -------- | ---------- | ------------|
+| `scope` | string | Yes | The scope to search in. Values include `projects`, `issues`, `merge_requests`, `milestones`, `snippet_titles`, `users`. [Additional scopes](#additional-scopes): `blobs`, `commits`, `notes`, `wiki_blobs`. |
+| `search` | string | Yes | The search query. |
+| `confidential` | boolean | No | Filter by confidentiality. Supports `issues` scope; other scopes are ignored. |
+| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `state` | string | No | Filter by state. Supports `issues` and `merge_requests` scopes; other scopes are ignored. |
### Scope: `projects`
@@ -129,7 +131,7 @@ Example response:
```
NOTE:
-`assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+The `assignee` column is deprecated. It is shown as a single-sized array `assignees` to conform to the GitLab EE API.
### Scope: `merge_requests`
@@ -432,27 +434,23 @@ Example response:
## Group Search API
-Search in the specified group.
+Search for an expression in the specified group.
-If a user is not a member of a group and the group is private, a `GET` request on that group results in a `404` status code.
+If a user is not a member of a group and the group is private, a `GET` request on that group results in a `404 Not Found` status code.
```plaintext
GET /groups/:id/search
```
-| 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 |
-| `scope` | string | yes | The scope to search in |
-| `search` | string | yes | The search query |
-| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
-| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-
-Search the expression in the specified scope. These scopes are supported: `projects`, `issues`, `merge_requests`, `milestones`, `users`.
-
-If Elasticsearch is enabled additional scopes available are `blobs`, `wiki_blobs`, `notes`, and `commits`. Find more about [the feature](../integration/advanced_search/elasticsearch.md). **(PREMIUM)**
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | -------------|
+| `id` | integer or string | Yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `scope` | string | Yes | The scope to search in. Values include `issues`, `merge_requests`, `milestones`, `projects`, `users`. [Additional scopes](#additional-scopes): `blobs`, `commits`, `notes`, `wiki_blobs`. |
+| `search` | string | Yes | The search query. |
+| `confidential` | boolean | No | Filter by confidentiality. Supports only `issues` scope; other scopes are ignored. |
+| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `state` | string | No | Filter by state. Supports `issues` and `merge_requests` only; other scopes are ignored. |
The response depends on the requested scope.
@@ -824,7 +822,7 @@ Example response:
## Project Search API
-Search in the specified project.
+Search for an expression in the specified project.
If a user is not a member of a project and the project is private, a `GET` request on that project results in a `404` status code.
@@ -832,18 +830,16 @@ If a user is not a member of a project and the project is private, a `GET` reque
GET /projects/:id/search
```
-| 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 |
-| `scope` | string | yes | The scope to search in |
-| `search` | string | yes | The search query |
-| `ref` | string | no | The name of a repository branch or tag to search on. The project's default branch is used by default. This is only applicable for scopes: `commits`, `blobs`, and `wiki_blobs`. |
-| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
-| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
-| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
-
-Search the expression in the specified scope. These scopes are supported: `issues`, `merge_requests`, `milestones`, `notes`, `wiki_blobs`, `commits`, `blobs`, `users`.
+| 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. |
+| `scope` | string | Yes | The scope to search in. Values include `blobs`, `commits`, `issues`, `merge_requests`, `milestones`, `notes`, `users`, and `wiki_blobs`. |
+| `search` | string | Yes | The search query. |
+| `confidential` | boolean | No | Filter by confidentiality. Supports `issues` scope; other scopes are ignored. |
+| `ref` | string | No | The name of a repository branch or tag to search on. The project's default branch is used by default. Applicable only for scopes `blobs`, `commits`, and `wiki_blobs`. |
+| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
+| `state` | string | No | Filter by state. Supports the `issues` and `merge_requests` scopes; other scopes are ignored. |
The response depends on the requested scope.
@@ -1144,9 +1140,9 @@ This scope is available only if [Elasticsearch](../integration/advanced_search/e
Filters are available for this scope:
-- filename
-- path
-- extension
+- Filename
+- Path
+- Extension
To use a filter, include it in your query. For example: `a query filename:some_name*`.
You may use wildcards (`*`) to use glob matching.
diff --git a/doc/api/secure_files.md b/doc/api/secure_files.md
index b4fe7bb6dd8..0c34dd30cdf 100644
--- a/doc/api/secure_files.md
+++ b/doc/api/secure_files.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api
---
@@ -127,7 +127,7 @@ Example response:
Download the contents of a project's secure file.
```plaintext
-GET /projects/:project_id/download/:id
+GET /projects/:project_id/secure_files/:id/download
```
Supported attributes:
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 467fa6bfc37..3d8d02b8429 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application settings API **(FREE SELF)**
@@ -216,7 +216,8 @@ Example response:
"admin_mode": false,
"external_pipeline_validation_service_timeout": null,
"external_pipeline_validation_service_token": null,
- "external_pipeline_validation_service_url": null
+ "external_pipeline_validation_service_url": null,
+ "can_create_group": false
}
```
@@ -266,6 +267,7 @@ 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. |
+| `can_create_group` | boolean | no | Indicates whether users can create top-level groups. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367754) in GitLab 15.5. Defaults to `true`. |
| `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_expiration_policies_enable_historic_entries` | boolean | no | Enable [cleanup policies](../user/packages/container_registry/reduce_container_registry_storage.md#enable-the-cleanup-policy) for all projects. |
@@ -352,7 +354,7 @@ listed in the descriptions of the relevant settings.
| `gravatar_enabled` | boolean | no | Enable Gravatar. |
| `hashed_storage_enabled` | boolean | no | Create new projects using hashed storage paths: Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance. (Always enabled in GitLab versions 13.0 and later, configuration is scheduled for removal in 14.0) |
| `help_page_hide_commercial_content` | boolean | no | Hide marketing-related entries from help. |
-| `help_page_support_url` | string | no | Alternate support URL for help page and help dropdown. |
+| `help_page_support_url` | string | no | Alternate support URL for help page and help dropdown list. |
| `help_page_text` | string | no | Custom text displayed on the help page. |
| `help_text` **(PREMIUM)** | string | no | GitLab server administrator information. |
| `hide_third_party_offers` | boolean | no | Do not display offers from third parties in GitLab. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index dedd28d6cf6..a6422d8545a 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq Metrics API **(FREE SELF)**
diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md
index a73542c8505..1ef5299668d 100644
--- a/doc/api/snippet_repository_storage_moves.md
+++ b/doc/api/snippet_repository_storage_moves.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index e3bc3573ed7..593985b5d5f 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Snippets API **(FREE)**
diff --git a/doc/api/statistics.md b/doc/api/statistics.md
index 17daf2fc71f..691b03505a7 100644
--- a/doc/api/statistics.md
+++ b/doc/api/statistics.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application statistics API **(FREE SELF)**
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Get current application statistics
List the current statistics of the GitLab instance. You have to be an
-administrator in order to perform this action.
+administrator to perform this action.
NOTE:
These statistics are approximate.
diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md
index 1cedd2d3730..a30bfbd4dfb 100644
--- a/doc/api/status_checks.md
+++ b/doc/api/status_checks.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md
index c174c0f5264..9771225ad31 100644
--- a/doc/api/suggestions.md
+++ b/doc/api/suggestions.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 14339460270..1b72ef1da53 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# System hooks API **(FREE SELF)**
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 45c621f534e..35085baf93f 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tags API **(FREE)**
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
index 5f862201571..9636393dfe9 100644
--- a/doc/api/templates/dockerfiles.md
+++ b/doc/api/templates/dockerfiles.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
index 71b791de16a..7c68daa5c48 100644
--- a/doc/api/templates/gitignores.md
+++ b/doc/api/templates/gitignores.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index ab97823fe07..152f3373ad6 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/templates/licenses.md b/doc/api/templates/licenses.md
index adba4f75255..e676da2e999 100644
--- a/doc/api/templates/licenses.md
+++ b/doc/api/templates/licenses.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 98f254f6620..8fd76864f1c 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab To-Do List API **(FREE)**
diff --git a/doc/api/topics.md b/doc/api/topics.md
index 38d99244bb6..13a5eabf8f9 100644
--- a/doc/api/topics.md
+++ b/doc/api/topics.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Topics API **(FREE)**
diff --git a/doc/api/usage_data.md b/doc/api/usage_data.md
index a01ed3e83a5..33126521901 100644
--- a/doc/api/usage_data.md
+++ b/doc/api/usage_data.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api
---
diff --git a/doc/api/users.md b/doc/api/users.md
index c30bac3c542..4a924f3b5f3 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Users API **(FREE)**
@@ -106,7 +106,8 @@ GET /users?without_project_bots=true
### For administrators **(FREE SELF)**
-> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /users
@@ -161,7 +162,8 @@ GET /users
"private_profile": false,
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22",
- "namespace_id": 1
+ "namespace_id": 1,
+ "created_by": null
},
{
"id": 2,
@@ -196,7 +198,8 @@ GET /users
"private_profile": false,
"current_sign_in_ip": "10.165.1.102",
"last_sign_in_ip": "172.127.2.22",
- "namespace_id": 2
+ "namespace_id": 2,
+ "created_by": null
}
]
```
@@ -269,6 +272,13 @@ You can include the users' [custom attributes](custom_attributes.md) in the resp
GET /users?with_custom_attributes=true
```
+You can use the `created_by` parameter to see if a user account was created:
+
+- [Manually by an administrator](../user/profile/account/create_accounts.md#create-users-in-admin-area).
+- As a [project bot user](../user/project/settings/project_access_tokens.md#bot-users-for-projects).
+
+If the returned value is `null`, the account was created by a user who registered an account themselves.
+
## Single user
Get a single user.
@@ -315,7 +325,8 @@ Parameters:
### For administrators **(FREE SELF)**
-> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /users/:id
@@ -378,7 +389,8 @@ Example Responses:
"plan": "gold",
"trial": true,
"sign_in_count": 1337,
- "namespace_id": 1
+ "namespace_id": 1,
+ "created_by": null
}
```
@@ -419,6 +431,13 @@ see the `group_saml` option and `provisioned_by_group_id` parameter:
}
```
+Administrators can use the `created_by` parameter to see if a user account was created:
+
+- [Manually by an administrator](../user/profile/account/create_accounts.md#create-users-in-admin-area).
+- As a [project bot user](../user/project/settings/project_access_tokens.md#bot-users-for-projects).
+
+If the returned value is `null`, the account was created by a user who registered an account themselves.
+
You can include the user's [custom attributes](custom_attributes.md) in the response with:
```plaintext
@@ -505,6 +524,7 @@ Parameters:
| `bio` | No | User's biography |
| `can_create_group` | No | User can create groups - true or false |
| `color_scheme_id` | No | User's color scheme for the file viewer (see [the user preference docs](../user/profile/preferences.md#syntax-highlighting-theme) for more information) |
+| `commit_email` | No | User's commit email. Set to `_private` to use the private commit email. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375148) in GitLab 15.5. |
| `email` | No | Email |
| `extern_uid` | No | External UID |
| `external` | No | Flags the user as external - true or false (default) |
@@ -519,6 +539,7 @@ Parameters:
| `password` | No | Password |
| `private_profile` | No | User's profile is private - true, false (default), or null (is converted to false) |
| `projects_limit` | No | Limit projects each user can create |
+| `pronouns` | No | Pronouns |
| `provider` | No | External provider name |
| `public_email` | No | Public email of the user (must be already verified) |
| `shared_runners_minutes_limit` **(PREMIUM)** | No | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this user. Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0`. |
@@ -628,7 +649,8 @@ Users on [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
### For administrators **(FREE SELF)**
-> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
+> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /user
@@ -681,6 +703,7 @@ Parameters:
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22",
"namespace_id": 1,
+ "created_by": null,
"note": null
}
```
diff --git a/doc/api/version.md b/doc/api/version.md
index efdf2b8b626..0ceab92b9d6 100644
--- a/doc/api/version.md
+++ b/doc/api/version.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Version API **(FREE)**
@@ -9,8 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
NOTE:
We recommend you use the [Metadata API](metadata.md) instead of the Version API.
It contains additional information and is aligned with the GraphQL metadata endpoint.
+As of GitLab 15.5, the Version API is a mirror of the Metadata API.
-Retrieve version information for this GitLab instance. Responds `200 OK` for
+Retrieves version information for the GitLab instance. Responds with `200 OK` for
authenticated users.
```plaintext
@@ -21,7 +22,13 @@ GET /version
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/version"
```
-Example response:
+## Example responses
+
+### GitLab 15.5 and later
+
+See [Metadata API](metadata.md) for the response.
+
+### GitLab 15.4 and earlier
```json
{
diff --git a/doc/api/visual_review_discussions.md b/doc/api/visual_review_discussions.md
index 7f91b829061..4b9a7d4f88a 100644
--- a/doc/api/visual_review_discussions.md
+++ b/doc/api/visual_review_discussions.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Visual Review discussions API **(PREMIUM)**
diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
index c90dc226661..b82e2b6cbdd 100644
--- a/doc/api/vulnerabilities.md
+++ b/doc/api/vulnerabilities.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerabilities API **(ULTIMATE)**
diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md
index 59943ede3e6..14966d2e925 100644
--- a/doc/api/vulnerability_exports.md
+++ b/doc/api/vulnerability_exports.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerability export API **(ULTIMATE)**
diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md
index fcfef848f14..a236960bc68 100644
--- a/doc/api/vulnerability_findings.md
+++ b/doc/api/vulnerability_findings.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerability Findings API **(ULTIMATE)**
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index ebdaa700aa7..b092338aaa5 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project wikis API **(FREE)**
diff --git a/doc/architecture/blueprints/_template.md b/doc/architecture/blueprints/_template.md
index e99ce61970a..7637c3bf5fa 100644
--- a/doc/architecture/blueprints/_template.md
+++ b/doc/architecture/blueprints/_template.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
status: proposed
creation-date: yyyy-mm-dd
authors: [ "@username" ]
@@ -52,7 +55,10 @@ good title can help communicate what the blueprint is and should be considered
as part of any review.
-->
-[[_TOC_]]
+<!--
+For long pages, consider creating a table of contents.
+The `[_TOC_]` function is not supported on docs.gitlab.com.
+-->
## Summary
diff --git a/doc/architecture/blueprints/ci_data_decay/index.md b/doc/architecture/blueprints/ci_data_decay/index.md
index 23c8e9df1bb..221c2364f79 100644
--- a/doc/architecture/blueprints/ci_data_decay/index.md
+++ b/doc/architecture/blueprints/ci_data_decay/index.md
@@ -102,9 +102,9 @@ Epic: [Reduce the rate of builds metadata table growth](https://gitlab.com/group
### Partition CI/CD pipelines database tables
-After we move CI/CD metadata to a different store, or reduce the rate of
+Even if we move CI/CD metadata to a different store, or reduce the rate of
metadata growth in a different way, the problem of having billions of rows
-describing pipelines, builds and artifacts, remains. We still need to keep
+describing pipelines, builds and artifacts, remains. We still may need to keep
reference to the metadata we might store in object storage and we still do need
to be able to retrieve this information reliably in bulk (or search through
it).
@@ -123,12 +123,12 @@ multiple smaller ones, using PostgreSQL partitioning features.
There are a few approaches we can take to partition CI/CD data. A promising one
is using list-based partitioning where a partition number is assigned a
pipeline, and gets propagated to all resources that are related to this
-pipeline. We assign the partition number based on when the pipeline was created
-or when we observed the last processing activity in it. This is very flexible
-because we can extend this partitioning strategy at will; for example with this
-strategy we can assign an arbitrary partition number based on multiple
-partitioning keys, combining time-decay-based partitioning with tenant-based
-partitioning on the application level.
+pipeline. We will assign a partition number using a
+[uniform logical partition ID](pipeline_partitioning.md#why-do-we-want-to-use-explicit-logical-partition-ids)
+This is very flexible because we can extend this partitioning strategy at will;
+for example with this strategy we can assign an arbitrary partition number
+based on multiple partitioning keys, combining time-decay-based partitioning
+with tenant-based partitioning on the application level if desired.
Partitioning rarely accessed data should also follow the policy defined for
builds archival, to make it consistent and reliable.
@@ -177,7 +177,7 @@ everyone to understand the vision described in this architectural blueprint.
### Removing pipeline data
-While it might be tempting to simply remove old or archived data from our
+While it might be tempting to remove old or archived data from our
databases this should be avoided. It is usually not desired to permanently
remove user data unless consent is given to do so. We can, however, move data
to a different data store, like object storage.
@@ -245,6 +245,7 @@ In progress.
- 2022-04-15: Partitioned pipeline data associations PoC [shipped](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84071).
- 2022-04-30: Additional [benchmarking started](https://gitlab.com/gitlab-org/gitlab/-/issues/361019) to evaluate impact.
- 2022-06-31: [Pipeline partitioning design](pipeline_partitioning.md) document [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87683) merged.
+- 2022-09-01: Engineering effort started to implement partitioning.
## Who
@@ -273,6 +274,7 @@ Domain experts:
|------------------------------|------------------------|
| Verify / Pipeline execution | Fabio Pitino |
| Verify / Pipeline execution | Marius Bobin |
+| Verify / Pipeline insights | Maxime Orefice |
| PostgreSQL Database | Andreas Brandl |
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
index baec14e3f0f..5f907ecdaa4 100644
--- a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
+++ b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
@@ -60,7 +60,7 @@ out of a database to a different place when data is no longer relevant or
needed. Our dataset is extremely large (tens of terabytes), so moving such a
high volume of data is challenging. When time-decay is implemented using
partitioning, we can archive the entire partition (or set of partitions) by
-simply updating a single record in one of our database tables. It is one of the
+updating a single record in one of our database tables. It is one of the
least expensive ways to implement time-decay patterns at a database level.
![decomposition_partitioning_comparison.png](decomposition_partitioning_comparison.png)
@@ -87,6 +87,7 @@ incidents, over the last couple of months, for example:
- S2: 2022-04-12 [Transactions detected that have been running for more than 10m](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6821)
- S2: 2022-04-06 [Database contention plausibly caused by excessive `ci_builds` reads](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6773)
- S2: 2022-03-18 [Unable to remove a foreign key on `ci_builds`](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6642)
+- S2: 2022-10-10 [The queuing_queries_duration SLI apdex violating SLO](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7852#note_1130123525)
We have approximately 50 `ci_*` prefixed database tables, and some of them
would benefit from partitioning.
@@ -259,7 +260,7 @@ smart enough to move rows between partitions on its own.
A partitioned table is called a **routing** table and it will use the `p_`
prefix which should help us with building automated tooling for query analysis.
-A table partition will be simply called **partition** and it can use the a
+A table partition will be called **partition** and it can use the a
physical partition ID as suffix, leaded by a `p` letter, for example
`ci_builds_p101`. Existing CI tables will become **zero partitions** of the
new routing tables. Depending on the chosen
@@ -278,6 +279,20 @@ also find information about which logical partitions are "active" or
"archived", which will help us to implement a time-decay pattern using database
declarative partitioning.
+Doing that will also allow us to use a Unified Resource Identifier for
+partitioned resources, that will contain a pointer to a pipeline ID, we could
+then use to efficiently lookup a partition the resource is stored in. It might
+be important when a resources can be directly referenced by an URL, in UI or
+API. We could use an ID like `1e240-5ba0` for pipeline `123456`, build `23456`.
+Using a dash `-` can prevent an identifier from being highlighted and copied
+with a mouse double-click. If we want to avoid this problem, we can use any
+character of written representation that is not present in base-16 numeral
+system - any letter from `g` to `z` in Latin alphabet, for example `x`. In that
+case an example of an URI would look like `1e240x5ba0`. If we decide to update
+the primary identifier of a partitioned resource (today it is just a big
+integer) it is important to design a system that is resilient to migrating data
+between partitions, to avoid changing idenfiers when rebalancing happens.
+
`ci_partitions` table will store information about a partition identifier,
pipeline ids range it is valid for and whether the partitions have been
archived or not. Additional columns with timestamps may be helpful too.
@@ -304,7 +319,7 @@ of storing archived data in PostgreSQL will be reduced significantly this way.
There are some technical details here that are out of the scope of this
description, but by using this strategy we can "archive" data, and make it much
-less expensive to reside in our PostgreSQL cluster by simply toggling a boolean
+less expensive to reside in our PostgreSQL cluster by toggling a boolean
column value.
## Accessing partitioned data
@@ -317,7 +332,7 @@ with its `partition_id`, and we will be able to find the partition that the
pipeline data is stored in.
We will need to constrain access to searching through pipelines, builds,
-artifacts etc. Search can not be done through all partitions, as it would not
+artifacts etc. Search cannot be done through all partitions, as it would not
be efficient enough, hence we will need to find a better way of searching
through archived pipelines data. It will be necessary to have different access
patterns to access archived data in the UI and API.
@@ -343,7 +358,7 @@ has_many :builds, -> (pipeline) { where(partition_id: pipeline.partition_id) }
```
The problem with this approach is that it makes preloading much more difficult
-as instance dependent associations can not be used with preloads:
+as instance dependent associations cannot be used with preloads:
```plaintext
ArgumentError: The association scope 'builds' is instance dependent (the
@@ -351,6 +366,33 @@ scope block takes an argument). Preloading instance dependent scopes is not
supported.
```
+### Primary key
+
+Primary key must include the partitioning key column to partition the table.
+
+We first create a unique index including the `(id, partition_id)`.
+Then, we drop the primary key constraint and use the new index created to set
+the new primary key constraint.
+
+`ActiveRecord` [does not support](https://github.com/rails/rails/blob/6-1-stable/activerecord/lib/active_record/attribute_methods/primary_key.rb#L126)
+composite primary keys, so we must force it to treat the `id` column as a primary key:
+
+```ruby
+class Model < ApplicationRecord
+ self.primary_key = 'id'
+end
+```
+
+The application layer is now ignorant of the database structure and all of the
+existing queries from `ActiveRecord` continue to use the `id` column to access
+the data. There is some risk to this approach because it is possible to
+construct application code that results in duplicate models with the same `id`
+value, but on a different `partition_id`. To mitigate this risk we must ensure
+that all inserts use the database sequence to populate the `id` since they are
+[guaranteed](https://www.postgresql.org/docs/12/sql-createsequence.html#id-1.9.3.81.7)
+to allocate distinct values and rewrite the access patterns to include the
+`partition_id` value. Manually assigning the ids during inserts must be avoided.
+
### Foreign keys
Foreign keys must reference columns that either are a primary key or form a
@@ -403,7 +445,7 @@ partition, `auto_canceled_by_partition_id`, and the FK becomes:
```sql
ALTER TABLE ONLY p_ci_pipelines
- ADD CONSTRAINT fk_cancel_redundant_pieplines
+ ADD CONSTRAINT fk_cancel_redundant_pipelines
FOREIGN KEY (auto_canceled_by_id, auto_canceled_by_partition_id)
REFERENCES p_ci_pipelines(id, partition_id) ON DELETE SET NULL;
```
@@ -610,6 +652,40 @@ application-wide outage.
1. Make it possible to create partitions in an automatic way.
1. Deliver the new architecture to self-managed instances.
+The diagram below visualizes this plan on Gantt chart. Please note that dates
+on the chart below are just estimates to visualize the plan better, these are
+not deadlines and can change at any time.
+
+```mermaid
+gantt
+ title CI Data Partitioning Timeline
+ dateFormat YYYY-MM-DD
+ axisFormat %m-%y
+
+ section Phase 0
+ Build data partitioning strategy :done, 0_1, 2022-06-01, 90d
+ section Phase 1
+ Partition biggest CI tables :1_1, after 0_1, 140d
+ Biggest table partitioned :milestone, metadata, 2022-12-01, 1min
+ Tables larger than 100GB partitioned :milestone, 100gb, after 1_1, 1min
+ section Phase 2
+ Add paritioning keys to SQL queries :2_1, after 1_1, 120d
+ Emergency partition detachment possible :milestone, detachment, 2023-04-01, 1min
+ All SQL queries are routed to partitions :milestone, routing, after 2_1, 1min
+ section Phase 3
+ Build new data access patterns :3_1, 2023-03-01, 120d
+ New API endpoint created for inactive data :milestone, api1, 2023-05-01, 1min
+ Filtering added to existing API endpoints :milestone, api2, 2023-07-01, 1min
+ section Phase 4
+ Introduce time-decay mechanisms :4_1, 2023-06-01, 120d
+ Inactive partitions are not being read :milestone, part1, 2023-08-01, 1min
+ Performance of the database cluster improves :milestone, part2, 2023-09-01, 1min
+ section Phase 5
+ Introduce auto-partitioning mechanisms :5_1, 2023-07-01, 120d
+ New partitions are being created automatically :milestone, part3, 2023-10-01, 1min
+ Partitioning is made available on self-managed :milestone, part4, 2023-11-01, 1min
+```
+
## Conclusions
We want to build a solid strategy for partitioning CI/CD data. We are aware of
@@ -637,8 +713,8 @@ Authors:
Recommenders:
-| Role | Who |
-|------------------------|-----------------|
-| Distingiushed Engineer | Kamil Trzciński |
+| Role | Who |
+|-------------------------------|-----------------|
+| Senior Distingiushed Engineer | Kamil Trzciński |
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/ci_pipeline_components/index.md b/doc/architecture/blueprints/ci_pipeline_components/index.md
index 94ec3e2f894..115f6909d2d 100644
--- a/doc/architecture/blueprints/ci_pipeline_components/index.md
+++ b/doc/architecture/blueprints/ci_pipeline_components/index.md
@@ -1,7 +1,7 @@
---
stage: Stage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Create a catalog of shareable pipeline constructs'
---
@@ -107,7 +107,18 @@ identifying abstract concepts and are subject to changes as we refine the design
- **Catalog** is the collection of projects that are set to contain components.
- **Version** is the release name of a tag in the project, which allows components to be pinned to a specific revision.
-## Characteristics of a component
+## Definition of pipeline component
+
+A pipeline component is a reusable single-purpose building block that abstracts away a single pipeline configuration unit. Components are used to compose a part or entire pipeline configuration.
+It can optionally take input parameters and set output data to be adaptable and reusable in different pipeline contexts,
+while encapsulating and isolating implementation details.
+
+Components allow a pipeline to be assembled by using abstractions instead of having all the details defined in one place.
+When using a component in a pipeline, a user shouldn't need to know the implementation details of the component and should
+only rely on the provided interface. The interface will have a version / revision, so that users understand which revision they are interfacing with.
+
+A pipeline component defines its type which indicates in which context of the pipeline configuration the component can be used.
+For example, a component of type X can only be used according to the type X use-case.
For best experience with any systems made of components it's fundamental that components are single purpose,
isolated, reusable and resolvable.
@@ -118,7 +129,7 @@ isolated, reusable and resolvable.
- **Reusability:** a component is designed to be used in different pipelines.
Depending on the assumptions it's built on a component can be more or less generic.
Generic components are more reusable but may require more customization.
-- **Resolvable:** When a component depends on another component, this dependency needs to be explicit and trackable. Hidden dependencies can lead to myriads of problems.
+- **Resolvable:** When a component depends on another component, this dependency must be explicit and trackable.
## Proposal
diff --git a/doc/architecture/blueprints/ci_scale/index.md b/doc/architecture/blueprints/ci_scale/index.md
index 75c4d05c334..c02fb35974b 100644
--- a/doc/architecture/blueprints/ci_scale/index.md
+++ b/doc/architecture/blueprints/ci_scale/index.md
@@ -17,11 +17,15 @@ and has become [one of the most beloved CI/CD solutions](https://about.gitlab.co
GitLab CI/CD has come a long way since the initial release, but the design of
the data storage for pipeline builds remains almost the same since 2012. We
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.
+creating more than 5 million builds each day on GitLab.com we are reaching
+database limits that are slowing our development velocity down.
-On February 1st, 2021, GitLab.com surpassed 1 billion CI/CD builds created and the number of
-builds continues to grow exponentially.
+On February 1st, 2021, GitLab.com surpassed 1 billion CI/CD builds created. In
+February 2022 we reached 2 billion of CI/CD build stored in the database. The
+number of builds continues to grow exponentially.
+
+The screenshot below shows our forecast created at the beginning of 2021, that
+turned out to be quite accurate.
![CI builds cumulative with forecast](ci_builds_cumulative_forecast.png)
@@ -34,9 +38,9 @@ builds continues to grow exponentially.
The current state of CI/CD product architecture needs to be updated if we want
to sustain future growth.
-### We are running out of the capacity to store primary keys
+### We were running out of the capacity to store primary keys: DONE
-The primary key in `ci_builds` table is an integer generated in a sequence.
+The primary key in `ci_builds` table is an integer value, generated in a sequence.
Historically, Rails used to use [integer](https://www.postgresql.org/docs/14/datatype-numeric.html)
type when creating primary keys for a table. We did use the default when we
[created the `ci_builds` table in 2012](https://gitlab.com/gitlab-org/gitlab/-/blob/046b28312704f3131e72dcd2dbdacc5264d4aa62/db/ci/migrate/20121004165038_create_builds.rb).
@@ -45,34 +49,32 @@ since the release of Rails 5. The framework is now using `bigint` type that is 8
bytes long, however we have not migrated primary keys for `ci_builds` table to
`bigint` yet.
-We will run out of the capacity of the integer type to store primary keys in
-`ci_builds` table before December 2021. When it happens without a viable
-workaround or an emergency plan, GitLab.com will go down.
-
-`ci_builds` is just one of the tables that are running out of the primary keys
-available in Int4 sequence. There are multiple other tables storing CI/CD data
-that have the same problem.
+In early 2021 we had estimated that would run out of the capacity of the integer
+type to store primary keys in `ci_builds` table before December 2021. If it had
+happened without a viable workaround or an emergency plan, GitLab.com would go
+down. `ci_builds` was just one of many tables that were running out of the
+primary keys available in Int4 sequence.
-Primary keys problem will be tackled by our Database Team.
+Before October 2021, our Database team had managed to migrate all the risky
+tables' primary keys to big integers.
-**Status**: In October 2021, the primary keys in CI tables were migrated
-to big integers. See the [related Epic](https://gitlab.com/groups/gitlab-org/-/epics/5657) for more details.
+See the [related Epic](https://gitlab.com/groups/gitlab-org/-/epics/5657) for more details.
-### The table is too large
+### Some CI/CD database tables are too large: IN PROGRESS
-There is more than a billion rows in `ci_builds` table. We store more than 2
-terabytes of data in that table, and the total size of indexes is more than 1
-terabyte (as of February 2021).
+There is more than two billion rows in `ci_builds` table. We store many
+terabytes of data in that table, and the total size of indexes is measured in
+terabytes as well.
-This amount of data contributes to a significant performance problems we
-experience on our primary PostgreSQL database.
+This amount of data contributes to a significant number of performance
+problems we experience on our CI PostgreSQL database.
-Most of the problem are related to how PostgreSQL database works internally,
+Most of the problems are related to how PostgreSQL database works internally,
and how it is making use of resources on a node the database runs on. We are at
-the limits of vertical scaling of the primary database nodes and we frequently
-see a negative impact of the `ci_builds` table on the overall performance,
-stability, scalability and predictability of the database GitLab.com depends
-on.
+the limits of vertical scaling of the CI primary database nodes and we
+frequently see a negative impact of the `ci_builds` table on the overall
+performance, stability, scalability and predictability of the CI database
+GitLab.com depends on.
The size of the table also hinders development velocity because queries that
seem fine in the development environment may not work on GitLab.com. The
@@ -90,41 +92,40 @@ environment.
We also expect a significant, exponential growth in the upcoming years.
One of the forecasts done using [Facebook's Prophet](https://facebook.github.io/prophet/)
-shows that in the first half of
-2024 we expect seeing 20M builds created on GitLab.com each day. In comparison
-to around 2M we see created today, this is 10x growth our product might need to
-sustain in upcoming years.
+shows that in the first half of 2024 we expect seeing 20M builds created on
+GitLab.com each day. In comparison to around 5M we see created today. This is
+10x growth from numbers we saw in 2021.
![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.
+by writing build options and variables to `ci_builds_metadata` table. We are
+also working on partitioning the largest CI/CD database tables using
+[time decay pattern](../ci_data_decay/index.md).
-### Queuing mechanisms are using the large table
+### Queuing mechanisms were using the large table: DONE
-Because of how large the table is, mechanisms that we use to build queues of
-pending builds (there is more than one queue), are not very efficient. Pending
-builds represent a small fraction of what we store in the `ci_builds` table,
-yet we need to find them in this big dataset to determine an order in which we
-want to process them.
+Because of how large the table is, mechanisms that we used to build queues of
+pending builds (there is more than one queue), were not very efficient. Pending
+builds represented a small fraction of what we store in the `ci_builds` table,
+yet we needed to find them in this big dataset to determine an order in which we
+wanted to process them.
-This mechanism is very inefficient, and it has been causing problems on the
-production environment frequently. This usually results in a significant drop
-of the CI/CD Apdex score, and sometimes even causes a significant performance
+This mechanism was very inefficient, and it had been causing problems on the
+production environment frequently. This usually resulted in a significant drop
+of the CI/CD Apdex score, and sometimes even caused a significant performance
degradation in the production environment.
-There are multiple other strategies that can improve performance and
-reliability. We can use [Redis queuing](https://gitlab.com/gitlab-org/gitlab/-/issues/322972), or
-[a separate table that will accelerate SQL queries used to build queues](https://gitlab.com/gitlab-org/gitlab/-/issues/322766)
-and we want to explore them.
+There were multiple other strategies that we considered to improve performance and
+reliability. We evaluated using [Redis queuing](https://gitlab.com/gitlab-org/gitlab/-/issues/322972), or
+[a separate table that would accelerate SQL queries used to build queues](https://gitlab.com/gitlab-org/gitlab/-/issues/322766).
+We decided to proceed with the latter.
-**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).
+In October 2021 we finished shipping the new architecture of builds queuing
+[on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908).
+We then made the new architecture [generally available](https://gitlab.com/groups/gitlab-org/-/epics/6954).
-### Moving big amounts of data is challenging
+### Moving big amounts of data is challenging: IN PROGRESS
We store a significant amount of data in `ci_builds` table. Some of the columns
in that table store a serialized user-provided data. Column `ci_builds.options`
@@ -144,24 +145,27 @@ described in a separate architectural blueprint.
## Proposal
-Making GitLab CI/CD product ready for the scale we expect to see in the
-upcoming years is a multi-phase effort.
-
-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 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.
-
-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.
+Below you can find the original proposal made in early 2021 about how we want
+to move forward with CI Scaling effort:
+
+> Making GitLab CI/CD product ready for the scale we expect to see in the
+> upcoming years is a multi-phase effort.
+>
+> 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 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.
+>
+> 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
@@ -170,15 +174,12 @@ Work required to achieve our next CI/CD scaling target is tracked in the
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](https://gitlab.com/groups/gitlab-org/-/epics/6954).
+1. ✓ [Make the new builds queuing architecture generally available](https://gitlab.com/groups/gitlab-org/-/epics/6954).
1. [Partition CI/CD data using time-decay pattern](../ci_data_decay/index.md).
## Status
-|-------------|--------------|
-| Created at | 21.01.2021 |
-| Approved at | 26.04.2021 |
-| Updated at | 28.02.2022 |
+Created at 21.01.2021, approved at 26.04.2021.
Status: In progress.
diff --git a/doc/architecture/blueprints/cloud_native_build_logs/index.md b/doc/architecture/blueprints/cloud_native_build_logs/index.md
index 3a06d73141b..b77d7998fc8 100644
--- a/doc/architecture/blueprints/cloud_native_build_logs/index.md
+++ b/doc/architecture/blueprints/cloud_native_build_logs/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Next iteration of build logs architecture at GitLab'
---
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index 431bc19ad84..127badabb71 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Making GitLab Pages a Cloud Native application - architecture blueprint.'
---
@@ -20,7 +20,7 @@ company behind the project.
This effort is described in more detail
[in the infrastructure team handbook page](https://about.gitlab.com/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/).
-GitLab Pages is tightly coupled with NFS and in order to unblock Kubernetes
+GitLab Pages is tightly coupled with NFS and to unblock Kubernetes
migration a significant change to GitLab Pages' architecture is required. This
is an ongoing work that we have started more than a year ago. This blueprint
might be useful to understand why it is important, and what is the roadmap.
diff --git a/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md b/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md
index 5f0f0a7aa63..4111e2ef056 100644
--- a/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md
+++ b/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Making a GitLab codebase composable - allowing to run parts of the application'
---
@@ -50,7 +50,7 @@ codebase without clear boundaries results in a number of problems and inefficien
we usually need to run a whole test suite to confidently know which parts are affected. This to
some extent can be improved by building a heuristic to aid this process, but it is prone to errors and hard
to keep accurate at all times
-- All components need to be loaded at all times in order to run only parts of the application
+- All components need to be loaded at all times to run only parts of the application
- Increased resource usage, as we load parts of the application that are rarely used in a given context
- The high memory usage results in slowing the whole application as it increases GC cycles duration
creating significantly longer latency for processing requests or worse cache usage of CPUs
@@ -208,7 +208,7 @@ graph LR
### Application Layers on GitLab.com
-Due to its scale, GitLab.com requires much more attention to run. This is needed in order to better manage resources
+Due to its scale, GitLab.com requires much more attention to run. This is needed to better manage resources
and provide SLAs for different functional parts. The chart below provides a simplistic view of GitLab.com application layers.
It does not include all components, like Object Storage nor Gitaly nodes, but shows the GitLab Rails dependencies between
different components and how they are configured on GitLab.com today:
@@ -543,7 +543,7 @@ Controllers, Serializers, some presenters and some of the Grape:Entities are als
Potential challenges with moving Controllers:
-- We needed to extend `Gitlab::Patch::DrawRoute` in order to support `engines/web_engine/config/routes` and `engines/web_engine/ee/config/routes` in case when `web_engine` is loaded. Here is potential [solution](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720#note_506957398).
+- We needed to extend `Gitlab::Patch::DrawRoute` to support `engines/web_engine/config/routes` and `engines/web_engine/ee/config/routes` in case when `web_engine` is loaded. Here is potential [solution](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720#note_506957398).
- `Gitlab::Routing.url_helpers` paths are used in models and services, that could be used by Sidekiq (for example `Gitlab::Routing.url_helpers.project_pipelines_path` is used by [ExpirePipelineCacheService](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/expire_pipeline_cache_service.rb#L20) in [ExpirePipelineCacheWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/expire_pipeline_cache_worker.rb#L18)))
### Packwerk
diff --git a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
index df8686ed0aa..433c23bf188 100644
--- a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
+++ b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: Consolidating groups and projects
---
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index 9d40593d7ce..58d59fe5737 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Container Registry metadata database'
---
diff --git a/doc/architecture/blueprints/database/scalability/patterns/index.md b/doc/architecture/blueprints/database/scalability/patterns/index.md
index 4a9bb003763..ec00d757377 100644
--- a/doc/architecture/blueprints/database/scalability/patterns/index.md
+++ b/doc/architecture/blueprints/database/scalability/patterns/index.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Learn how to scale the database through the use of best-of-class database scalability patterns'
---
diff --git a/doc/architecture/blueprints/database/scalability/patterns/read_mostly.md b/doc/architecture/blueprints/database/scalability/patterns/read_mostly.md
index 0780ae3c4d5..6cf8e17edeb 100644
--- a/doc/architecture/blueprints/database/scalability/patterns/read_mostly.md
+++ b/doc/architecture/blueprints/database/scalability/patterns/read_mostly.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Learn how to scale operating on read-mostly data at scale'
---
diff --git a/doc/architecture/blueprints/database/scalability/patterns/time_decay.md b/doc/architecture/blueprints/database/scalability/patterns/time_decay.md
index 7a64f0cb7c6..ff5f7c25ea1 100644
--- a/doc/architecture/blueprints/database/scalability/patterns/time_decay.md
+++ b/doc/architecture/blueprints/database/scalability/patterns/time_decay.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Learn how to operate on large time-decay data'
---
@@ -27,7 +27,7 @@ application.
Let's first consider entities with no inherent time-related bias for their data.
A record for a user or a project may be equally important and frequently accessed, irrelevant to when
-it was created. We can not predict by using a user's `id` or `created_at` how often the related
+it was created. We cannot predict by using a user's `id` or `created_at` how often the related
record is accessed or updated.
On the other hand, a good example for datasets with extreme time-decay effects are logs and time
@@ -91,7 +91,7 @@ a maximum of a month of events, restricted to 6 months in the past.
### Immutability
The third characteristic of time-decay data is that their **time-decay status does not change**.
-Once they are considered "old", they can not switch back to "new" or relevant again.
+Once they are considered "old", they cannot switch back to "new" or relevant again.
This definition may sound trivial, but we have to be able to make operations over "old" data **more**
expensive (for example, by archiving or moving them to less expensive storage) without having to worry about
diff --git a/doc/architecture/blueprints/database_testing/index.md b/doc/architecture/blueprints/database_testing/index.md
index 5bc9528d568..3f8041ea416 100644
--- a/doc/architecture/blueprints/database_testing/index.md
+++ b/doc/architecture/blueprints/database_testing/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Database Testing'
---
@@ -84,7 +84,7 @@ The short-term focus is on testing regular migrations (typically schema changes)
In order to secure this process and meet compliance goals, the runner environment is treated as a *production* environment and similarly locked down, monitored and audited. Only Database Maintainers have access to the CI pipeline and its job output. Everyone else can only see the results and statistics posted back on the merge request.
-We implement a secured CI pipeline on <https://ops.gitlab.net> that adds the execution steps outlined above. The goal is to secure this pipeline in order to solve the following problem:
+We implement a secured CI pipeline on <https://ops.gitlab.net> that adds the execution steps outlined above. The goal is to secure this pipeline to solve the following problem:
Make sure we strongly protect production data, even though we allow everyone (GitLab team/developers) to execute arbitrary code on the thin-clone which contains production data.
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index 08253ac883c..866be9d8a70 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -1,12 +1,12 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Internal usage of Feature Flags for GitLab development'
---
-# Usage of Feature Flags for GitLab development
+# Architectural discussion of feature flags
Usage of feature flags become crucial for the development of GitLab. The
feature flags are a convenient way to ship changes early, and safely rollout
diff --git a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
index b22636ac1d9..19fd995bead 100644
--- a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
+++ b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'GitLab to Kubernetes communication'
---
diff --git a/doc/architecture/blueprints/image_resizing/index.md b/doc/architecture/blueprints/image_resizing/index.md
index f2fd7543b90..dd7ce27f459 100644
--- a/doc/architecture/blueprints/image_resizing/index.md
+++ b/doc/architecture/blueprints/image_resizing/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Image Resizing'
---
diff --git a/doc/architecture/blueprints/pods/index.md b/doc/architecture/blueprints/pods/index.md
index fc33a4f441b..01d56c483ea 100644
--- a/doc/architecture/blueprints/pods/index.md
+++ b/doc/architecture/blueprints/pods/index.md
@@ -22,12 +22,14 @@ We use the following terms to describe components and properties of the Pods arc
### Pod
-A Pod is a set of infrastructure components that contains multiple workspaces that belong to different organizations. The components include both datastores (PostgreSQL, Redis etc.) and stateless services (web etc.). The infrastructure components provided within a Pod are shared among workspaces but not shared with other Pods. This isolation of infrastructure components means that Pods are independent from each other.
+A Pod is a set of infrastructure components that contains multiple top-level namespaces that belong to different organizations. The components include both datastores (PostgreSQL, Redis etc.) and stateless services (web etc.). The infrastructure components provided within a Pod are shared among organizations and their top-level namespaces but not shared with other Pods. This isolation of infrastructure components means that Pods are independent from each other.
+
+![Term Pod](term-pod.png)
#### Pod properties
- Each pod is independent from the others
-- Infrastructure components are shared by workspaces within a Pod
+- Infrastructure components are shared by organizations and their top-level namespaces within a Pod
- More Pods can be provisioned to provide horizontal scalability
- A failing Pod does not lead to failure of other Pods
- Noisy neighbor effects are limited to within a Pod
@@ -36,23 +38,50 @@ A Pod is a set of infrastructure components that contains multiple workspaces th
Discouraged synonyms: GitLab instance, cluster, shard
-### Workspace
+### Cluster
+
+A cluster is a collection of Pods.
+
+![Term Cluster](term-cluster.png)
+
+#### Cluster properties
+
+- A cluster holds cluster-wide metadata, for example Users, Routes, Settings.
+
+Discouraged synonyms: whale
+
+### Organizations
+
+GitLab references [Organizations in the initial set up](../../../topics/set_up_organization.md) and users can add a (free text) organization to their profile. There is no Organization entity established in the GitLab codebase.
+
+As part of delivering Pods, we propose the introduction of an `organization` entity. Organizations would represent billable entities or customers.
+
+Organizations are a known concept, present for example in [AWS](https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/core-concepts.html) and [GCP](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy#organizations).
+
+Organizations work under the following assumptions:
+
+1. Users care about what happens within their organizations.
+1. Features need to work within an organization.
+1. Only few features need to work across organizations.
+1. Users understand that the majority of pages they view are only scoped to a single organization at a time.
+1. Organizations are located on a single pod.
-A [workspace](../../../user/workspace/index.md) is the name for the top-level namespace that is used by organizations to manage everything GitLab. It will provide similar administrative capabilities to a self-managed instance.
+![Term Organization](term-organization.png)
-See more in the [workspace group overview](https://about.gitlab.com/direction/manage/workspace/#overview).
+#### Organization properties
-#### Workspace properties
+- Top-level namespaces belong to organizations
+- Users can be members of different organizations
+- Organizations are isolated from each other by default meaning that cross-namespace features will only work for namespaces that exist within a single organization
+- User namespaces must not belong to an organization
-- Workspaces are isolated from each other by default
-- A workspace is located on a single Pod
-- Workspaces share the resources provided by a Pod
+Discouraged synonyms: Billable entities, customers
### Top-Level namespace
A top-level namespace is the logical object container in the code that represents all groups, subgroups and projects that belong to an organization.
-A top-level namespace is the root of nested collection namespaces and projects. The namespace and its related entities form a tree-like hierarchy: Namespaces are the nodes of the tree, projects are the leaves. An organization usually contains a single top-level namespace, called a workspace.
+A top-level namespace is the root of nested collection namespaces and projects. The namespace and its related entities form a tree-like hierarchy: Namespaces are the nodes of the tree, projects are the leaves.
Example:
@@ -61,21 +90,30 @@ Example:
- `gitlab-org` is a `top-level namespace`; the root for all groups and projects of an organization
- `gitlab` is a `project`; a project of the organization.
+Top-level namespaces may [be replaced by workspaces](https://gitlab.com/gitlab-org/gitlab/-/issues/368237#high-level-goals). This proposal only uses the term top-level namespaces as the workspace definition is ongoing.
+
Discouraged synonyms: Root-level namespace
+![Term Top-level Namespace](term-top-level-namespace.png)
+
#### Top-level namespace properties
-Same as workspaces.
+- Top-level namespaces belonging to an organization are located on the same Pod
+- Top-level namespaces can interact with other top-level namespaces that belong to the same organization
### Users
-Users are available globally and not restricted to a single Pod. Users can create multiple workspaces and they may be members of several workspaces and contribute to them. Because users' activity is not limited to an individual Pod, their activity needs to be aggregated across Pods to reflect all their contributions (for example TODOs). This means, the Pods architecture may need to provide a central dashboard.
+Users are available globally and not restricted to a single Pod. Users can be members of many different organizations with varying permissions. Inside organizations, users can create multiple top-level namespaces. User activity is not limited to a single organization but their contributions (for example TODOs) are only aggregated within an organization. This avoids the need for aggregating across pods.
#### User properties
- Users are shared globally across all Pods
-- Users can create multiple workspaces
-- Users can be a member of multiple workspaces
+- Users can create multiple top-level namespaces
+- Users can be a member of multiple top-level namespaces
+- Users can be a member of multiple organizations
+- Users can administrate organizations
+- User activity is aggregated within an organization
+- Every user has one personal namespace
## Goals
@@ -87,7 +125,7 @@ Pods provide a horizontally scalable solution because additional Pods can be cre
### Increased availability
-A major challenge for shared-infrastructure architectures is a lack of isolation between workspaces. This can lead to noisy neighbor effects. A organization's behavior inside a workspace can impact all other workspaces. This is highly undesirable. Pods provide isolation at the pod level. A group of organizations is fully isolated from other organizations located on a different Pod. This minimizes noisy neighbor effects while still benefiting from the cost-efficiency of shared infrastructure.
+A major challenge for shared-infrastructure architectures is a lack of isolation between top-level namespaces. This can lead to noisy neighbor effects. A organization's behavior inside a top-level namespace can impact all other organizations. This is highly undesirable. Pods provide isolation at the pod level. A group of organizations is fully isolated from other organizations located on a different Pod. This minimizes noisy neighbor effects while still benefiting from the cost-efficiency of shared infrastructure.
Additionally, Pods provide a way to implement disaster recovery capabilities. Entire Pods may be replicated to read-only standbys with automatic failover capabilities.
@@ -105,35 +143,113 @@ Pods would provide a solution for organizations in the small to medium business
(See [segmentation definitions](https://about.gitlab.com/handbook/sales/field-operations/gtm-resources/#segmentation).)
Larger organizations may benefit substantially from [GitLab Dedicated](../../../subscriptions/gitlab_dedicated/index.md).
+At this moment, GitLab.com has "social-network"-like capabilities that may not fit well into a more isolated organization model. Removing those features, however, possesses some challenges:
+
+1. How will existing `gitlab-org` contributors contribute to the namespace??
+1. How do we move existing top-level namespaces into the new model (effectively breaking their social features)?
+
+We should evaluate if the SMB and mid market segment is interested in these features, or if not having them is acceptable in most cases.
+
## High-level architecture problems to solve
A number of technical issues need to be resolved to implement Pods (in no particular order). This section will be expanded.
-1. How are users of an organization routed to the correct Pod containing their workspace?
+1. How are users of an organization routed to the correct Pod?
1. How do users authenticate?
1. How are Pods rebalanced?
1. How are Pods provisioned?
1. How can Pods implement disaster recovery capabilities?
-## Iteration 1
+## Iteration plan
+
+We can't ship the entire Pods architecture in one go - it is too large. Instead, we are adopting an iteration plan that provides value along the way.
+
+1. Introduce organizations
+1. Migrate existing top-level namespaces to organizations
+1. Create new organizations on `pod_0`
+1. Migrate existing organizations from `pod_0` to `pod_n`
+1. Add additional Pod capabilities (DR, Regions)
+
+### Iteration 0: Introduce organizations
+
+In the first iteration, we introduce the concept of an organization
+as a way to group top-level namespaces together. Support for organizations **does not require any Pods work** but having them will make all subsequent iterations of Pods simpler. This is mainly because we can group top-level namespaces for a single organization onto a Pod. Within an organization all interactions work as normal but we eliminate any cross-organizational interactions except in well defined cases (e.g. forking).
+
+This means that we don't have a large number of cross-pod interactions.
+
+Introducing organizations allows GitLab to move towards a multi-tenant system that is similar to Discord's with a single user account but many different "servers" - our organizations - that allow users to switch context. This model harmonizes the UX across self-managed and our SaaS Platforms and is a good fit for Pods.
+
+Organizations solve the following problems:
+
+1. We can group top-level namespaces by organization. It is very similar to the initial concept of "instance groups". For example these two top-level namespaces would belong to the organization `GitLab`:
+ 1. `https://gitlab.com/gitlab-org/`
+ 1. `https://gitlab.com/gitlab-com/`
+1. We can isolate organizations from each other. Top-level namespaces of the same organization can interact within organizations but are not allowed to interact with other namespaces in other organizations. This is useful for customers because it means an organization provides clear boundaries - similar to a self-managed instance. This means we don't have to aggregate user dashboards across everything and can locally scope them to organizations.
+1. We don't need to define hierarchies inside an organization. It is a container that could be filled with whatever hierarchy / entity set makes sense (workspaces, top-level namespaces etc.)
+1. Self-managed instances would set a default organization.
+1. Organizations can control user-profiles in a central way. This could be achieved by having an organization specific user-profile. Such a profile makes it possible for the organization administrators to control the user role in a company, enforce user emails, or show a graphical indicator of a user being part of the organization. An example would be a "GitLab Employee stamp" on comments.
+
+![Move to Organizations](iteration0-organizations-introduction.png)
+
+#### Why would customers opt-in to Organizations?
+
+By introducing organizations and Pods we can improve the reliability, performance and availability of our SaaS Platforms.
+
+The first iteration of organizations would also have some benefits by providing more isolation. A simple example would be that `@` mentions could be scoped to an organization.
+
+Future iterations would create additional value but are beyond the scope of this blueprint.
+
+Organizations will likely be required in the future as well.
+
+#### Initial user experience
+
+1. We create a default `GitLab.com public` organization and assign all public top-level namespaces to it. This allows existing users to access all the data on GitLab.com, exactly as it does now.
+1. Any user wanting to opt-in to the benefits of organizations will need to set a single default organization. Any attempts for these users to load a global page like `/dashboard` will end up redirecting to `/-/organizations/<DEFAULT_ORGANIZATION>/dashboard`.
+1. New users that opted in to organizations will only ever see data that is related to a single organization. Upon login, data is shown for the default organization. It will be clear to the user how they can switch to a different organization. Users can still navigate to the `GitLab.com` organization but they won't see TODOs from their new organizations in any such views. Instead they'd need to navigate directly to `/organizations/my-company/-/dashboard`.
+
+### Migrating to Organizations
+
+Existing customers could also opt-in to migrate their existing top-level paid namespaces to become part of an organization. In most cases this will be a 1-to-1 mapping. But in some cases it may allow a customer to move multiple top-level namespaces into one organization (for example GitLab).
+
+Migrating to Organizations would be optional. We could even recruit a few beta testers early on to see if this works for them. GitLab itself could dogfood organizations and we'd surface a lot of issues restricting interactions with other namespaces.
+
+## Iteration 1 - Introduce Pod US 0
+
+### GitLab.com as Pod US0
+
+GitLab.com will be treated as the first pod `Pod US 0`. It will be unique and much larger compared to newly created pods. All existing top-level namespaces and organizations will remain on `Pod US 0` in the first iteration.
+
+### Users are globally available
+
+Users are globally available and the same for all pods. This means that user data needs to be handled separately, for example via decomposition, see [!95941](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95941).
+
+### Pod groundwork
+
+In this iteration, we'll lay all the groundwork to support a second Pod for new organizations. This will be transparent to customers.
+
+## Iteration 2 - Introduce Pod US 1
+
+### Add new organizations to Pod US 1
+
+After we are ready to support a second Pod, newly created organizations are located by default on `Pod US 1`. The user experience for organizations is already well established.
+
+### Migrate existing organizations from Pod US 0 to Pod US 1
-Ultimately, a Pods architecture should offer the same user experience as self-managed and GitLab dedicated. However, at this moment GitLab.com has many more "social-network"-like capabilities that will be difficult to implement with a Pods architecture. We should evaluate if the SMB and mid market segment is interested in these features, or if not having them is acceptable in most cases.
+We know that we'll have to move organizations from `Pod US 0` to other pods to reduce its size and ultimately retire the existing GitLab.com architecture.
-The first iteration of Pods will still contain some limitations that would break cross-workspace workflows. This means it may only be acceptable for new customers, or for existing customers that are briefed.
+By introducing organizations early, we should be able to draw strong "boundaries" across organizations and support migrating existing organizations to a new Pod.
-Limitations are:
+This is likely going to be GitLab itself - if we can dogfood this, we are likely going to be successful with other organizations as well.
-- An organization can create only a single workspace.
-- Workspaces are isolated from each other. This means cross-workspace workflows are broken.
+## Iteration 3 - Introduce Regions
-## Iteration 2
+We can now leverage the Pods architecture to introduce Regions.
-Based on user research, we may want to change certain features to work across namespaces to allow organizations to interact with each other in specific circumstances. We may also allow organizations to have more than one workspace. This is particularly relevant for organizations with sub-divisions, or multi-national organizations that want to have workspaces in different regions.
+## Iteration 4 - Introduce cross-organizational interactions as needed
-Additional features:
+Based on user research, we may want to change certain features to work across organizations. Examples include:
-- Specific features allow for cross-workspace interactions, for example forking, search.
-- An organization can own multiple workspaces on different Pods.
+- Specific features allow for cross-organization interactions, for example forking, search.
### Links
diff --git a/doc/architecture/blueprints/pods/iteration0-organizations-introduction.png b/doc/architecture/blueprints/pods/iteration0-organizations-introduction.png
new file mode 100644
index 00000000000..5f5cad7b169
--- /dev/null
+++ b/doc/architecture/blueprints/pods/iteration0-organizations-introduction.png
Binary files differ
diff --git a/doc/architecture/blueprints/pods/term-cluster.png b/doc/architecture/blueprints/pods/term-cluster.png
new file mode 100644
index 00000000000..f52e31b52ad
--- /dev/null
+++ b/doc/architecture/blueprints/pods/term-cluster.png
Binary files differ
diff --git a/doc/architecture/blueprints/pods/term-organization.png b/doc/architecture/blueprints/pods/term-organization.png
new file mode 100644
index 00000000000..f605adb124d
--- /dev/null
+++ b/doc/architecture/blueprints/pods/term-organization.png
Binary files differ
diff --git a/doc/architecture/blueprints/pods/term-pod.png b/doc/architecture/blueprints/pods/term-pod.png
new file mode 100644
index 00000000000..d8f79df2f29
--- /dev/null
+++ b/doc/architecture/blueprints/pods/term-pod.png
Binary files differ
diff --git a/doc/architecture/blueprints/pods/term-top-level-namespace.png b/doc/architecture/blueprints/pods/term-top-level-namespace.png
new file mode 100644
index 00000000000..c1cd317d878
--- /dev/null
+++ b/doc/architecture/blueprints/pods/term-top-level-namespace.png
Binary files differ
diff --git a/doc/architecture/blueprints/rate_limiting/index.md b/doc/architecture/blueprints/rate_limiting/index.md
index 692cef4b11d..2ed66f22b53 100644
--- a/doc/architecture/blueprints/rate_limiting/index.md
+++ b/doc/architecture/blueprints/rate_limiting/index.md
@@ -65,7 +65,7 @@ Inc._
- There is no way to automatically notify a user when they are approaching thresholds.
- There is no single way to change limits for a namespace / project / user / customer.
- There is no single way to monitor limits through real-time metrics.
-- There is no framework for hierarchical limit configuration (instance / namespace / sub-group / project).
+- There is no framework for hierarchical limit configuration (instance / namespace / subgroup / project).
- We allow disabling rate-limiting for some marquee SaaS customers, but this
increases a risk for those same customers. We should instead be able to set
higher limits.
@@ -357,7 +357,7 @@ hierarchy. Choosing a proper solution will require a thoughtful research.
1. Build application limits API in a way that it can be easily extracted to a separate service.
1. Build application limits definition in a way that is independent from the Rails application.
1. Build tooling that produce consistent behavior and results across programming languages.
-1. Build the new framework in a way that we can extend to allow self-managed admins to customize limits.
+1. Build the new framework in a way that we can extend to allow self-managed administrators to customize limits.
1. Maintain consistent features and behavior across SaaS and self-managed codebase.
1. Be mindful about a cognitive load added by the hierarchical limits, aim to reduce it.
@@ -388,7 +388,7 @@ Proposal:
| Author | Hayley Swimelar |
| Engineering Leader | Sam Goldstein |
| Product Manager | |
-| Architecture Evolution Coach | |
+| Architecture Evolution Coach | Andrew Newdigate |
| Recommender | |
| Recommender | |
| Recommender | |
diff --git a/doc/architecture/blueprints/runner_scaling/index.md b/doc/architecture/blueprints/runner_scaling/index.md
index 8f7062a1148..415884449ed 100644
--- a/doc/architecture/blueprints/runner_scaling/index.md
+++ b/doc/architecture/blueprints/runner_scaling/index.md
@@ -43,10 +43,10 @@ to be able to keep using this and ship fixes and updates needed for our use case
and the documentation for it has been removed from the official page. This
means that the original reason to use Docker Machine is no longer valid too.
-To keep supporting our customers and the wider community we need to design a
-new mechanism for GitLab Runner auto-scaling. It not only needs to support
-auto-scaling, but it also needs to do that in the way to enable us to build on
-top of it to improve efficiency, reliability and availability.
+To keep supporting our customers and the wider community and to improve our SaaS runners
+maintenance we need to design a new mechanism for GitLab Runner auto-scaling. It not only
+needs to support auto-scaling, but it also needs to do that in the way to enable us to
+build on top of it to improve efficiency, reliability and availability.
We call this new mechanism the "next GitLab Runner Scaling architecture".
@@ -62,6 +62,66 @@ subject to change or delay. The development, release and timing of any
products, features, or functionality remain at the sole discretion of GitLab
Inc._
+## Continuing building on Docker Machine
+
+At this moment one of our core products - GitLab Runner - and one of its most
+important features - ability to auto-scale job execution environments - depends
+on an external product that is abandoned.
+
+Docker Machine project itself is also hard to maintain. Its design starts to
+show its age, which makes it hard to bring new features and fixes. A huge
+codebase that it brings with a lack of internal knowledge about it makes it
+hard for our maintainers to support and properly handle incoming feature
+requests and community contributions.
+
+Docker Machine and it integrated 20+ drivers for cloud and virtualization
+providers creates also another subset of problems, like:
+
+- Each cloud/virtualization environment brings features that come and go
+ and we would need to maintain support for them (add new features, fix
+ bugs).
+
+- We basically need to become experts for each of the virtualization/cloud
+ provider to properly support integration with their API,
+
+- Every single provider that Docker Machine integrates with has its
+ bugs, security releases, vulnerabilities - to maintain the project properly
+ we would need to be on top of all of that and handle updates whenever
+ they are needed.
+
+Another problem is the fact that Docker Machine, from its beginnings, was
+focused on managing Linux based instances only. Despite that at some moment
+Docker got official and native integration on Windows, Docker Machine never
+followed this step. Nor its designed to make such integration easy.
+
+There is also no support for MacOS. This one is obvious - Docker Machine is a
+tool to maintain hosts for Docker Engine and there is no native Docker Engine
+for MacOS. And by native we mean MacOS containers executed within MacOS
+operating system. Docker for MacOS product is not a native support - it's just
+a tooling and a virtualized Linux instance installed with it that makes it
+easier to develop **Linux containers** on MacOS development instances.
+
+This means that only one of three of our officially supported platforms -
+Linux, Windows and MacOS - have a fully-featured support for CI/CD
+auto-scaling. For Windows there is a possibility to use Kubernetes (which in
+some cases have limitations) and maybe with a lot of effort we could bring
+support for Windows into Docker Machine. But for MacOS, there is no
+auto-scaling solution provided natively by GitLab Runner.
+
+This is a huge limitation for our users and a frequently requested feature.
+It's also a limitation for our SaaS runners offering. We've maintained to
+create some sort of auto-scaling for our SaaS Windows and SaaS MacOS runners
+hacking around Custom executor. But experiences from past three years show
+that it's not the best way of doing this. And yet, after this time, Windows
+and MacOS runners autoscaling lacks a lot of performance and feature support
+that we have with our SaaS Linux runners.
+
+To keep supporting our customers and the wider community and to improve our
+SaaS runners maintenance we need to design a new mechanism for GitLab Runner
+auto-scaling. It not only needs to support auto-scaling, but it also needs to
+do that in the way to enable us to build on top of it to improve efficiency,
+reliability and availability.
+
## Proposal
Currently, GitLab Runner auto-scaling can be configured in a few ways. Some
@@ -94,7 +154,7 @@ data that can be shared between job runs.
Because there is no viable replacement and we might be unable to support all
cloud providers that Docker Machine used to support, the key design requirement
is to make it really simple and easy for the wider community to write a custom
-GitLab auto-scaling plugin, whatever cloud provider they might be using. We
+GitLab plugin for whatever cloud provider they might be using. We
want to design a simple abstraction that users will be able to build on top, as
will we to support existing workflows on GitLab.com.
@@ -129,12 +189,11 @@ the need of rebuilding GitLab Runner whenever it happens.
### 💡 Write a solid documentation about how to build your own plugin
-It is important to show users how to build an auto-scaling plugin, so that they
+It is important to show users how to build a plugin, so that they
can implement support for their own cloud infrastructure.
-Building new plugins should be simple, and with the support of great
-documentation it should not require advanced skills, like understanding how
-gRPC works. We want to design the plugin system in a way that the entry barrier
+Building new plugins should be simple and supported with great
+documentation. We want to design the plugin system in a way that the entry barrier
for contributing new plugins is very low.
### 💡 Build a PoC to run multiple builds on a single machine
@@ -171,7 +230,128 @@ configures the Docker daemon there to allow external authenticated requests. It
stores credentials to such ephemeral Docker environments on disk. Once a
machine has been provisioned and made available for GitLab Runner Manager to
run builds, it is using one of the existing executors to run a user-provided
-script. In auto-scaling, this is typically done using Docker executor.
+script. In auto-scaling, this is typically done using the Docker executor.
+
+### Separation of concerns
+
+There are several concerns represented in the current architecture. They are
+coupled in the current implementation so we will break them out here to consider
+them each separately.
+
+- **Virtual Machine (VM) shape**. The underlying provider of a VM requires configuration to
+ know what kind of machine to create. E.g. Cores, memory, failure domain,
+ etc... This information is very provider specific.
+- **VM lifecycle management**. Multiple machines will be created and a
+ system must keep track of which machines belong to this executor. Typically
+ a cloud provider will have a way to manage a set of homogenous machines.
+ E.g. GCE Instance Group. The basic operations are increase, decrease and
+ usually delete a specific machine.
+- **VM autoscaling**. In addition to low-level lifecycle management,
+ job-aware capacity decisions must be made to the set of machines to provide
+ capacity when it is needed but not maintain excess capacity for cost reasons.
+- **Job to VM mapping (routing)**. Currently the system assigns only one job to a
+ given a machine. A machine may be reused based on the specific executor
+ configuration.
+- **In-VM job execution**. Within each VM a job must be driven through
+ various pre-defined stages and results and trace information returned
+ to the Runner system. These details are highly dependent on the VM
+ architecture and operating system as well as Executor type.
+
+The current architecture has several points of coupling between concerns.
+Coupling reduces opportunities for abstraction (e.g. community supported
+plugins) and increases complexity, making the code harder to understand,
+test, maintain and extend.
+
+A primary design decision will be which concerns to externalize to the plugin
+and which should remain with the runner system. The current implementation
+has several abstractions internally which could be used as cut points for a
+new abstraction.
+
+For example the [`Build`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/build.go#L125)
+type uses the [`GetExecutorProvider`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/executor.go#L171)
+function to get an executor provider based on a dispatching executor string.
+Various executor types register with the system by being imported and calling
+[`RegisterExecutorProvider`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/executor.go#L154)
+during initialization. Here the abstractions are the [`ExecutorProvider`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/executor.go#L80)
+and [`Executor`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/executor.go#L59)
+interfaces.
+
+Within the `docker+autoscaling` executor the [`machineExecutor`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/executors/docker/machine/machine.go#L19)
+type has a [`Machine`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/helpers/docker/machine.go#L7)
+interface which it uses to aquire a VM during the common [`Prepare`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/executors/docker/machine/machine.go#L71)
+phase. This abstraction primarily creates, accesses and deletes VMs.
+
+There is no current abstraction for the VM autoscaling logic. It is tightly
+coupled with the VM lifecycle and job routing logic. Creating idle capacity
+happens as a side-effect of calling [`Acquire`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/executors/docker/machine/provider.go#L449) on the `machineProvider` while binding a job to a VM.
+
+There is also no current abstraction for in-VM job execution. VM-specific
+commands are generated by the Runner Manager using the [`GenerateShellScript`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/build.go#L336)
+function and [injected](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/267f40d871cd260dd063f7fbd36a921fedc62241/common/build.go#L373)
+into the VM as the manager drives the job execution stages.
+
+### Design principles
+
+Our goal is to design a GitLab Runner plugin system interface that is flexible
+and simple for the wider community to consume. As we cannot build plugins for
+all cloud platforms, we want to ensure a low entry barrier for anyone who needs
+to develop a plugin. We want to allow everyone to contribute.
+
+To achieve this goal, we will follow a few critical design principles. These
+principles will guide our development process for the new plugin system
+abstraction.
+
+#### General high-level principles
+
+- Design the new auto-scaling architecture aiming for having more choices and
+ flexibility in the future, instead of imposing new constraints.
+- Design the new auto-scaling architecture to experiment with running multiple
+ jobs in parallel, on a single machine.
+- Design the new provisioning architecture to replace Docker Machine in a way
+ that the wider community can easily build on top of the new abstractions.
+- New auto-scaling method should become a core component of GitLab Runner product so that
+ we can simplify maintenance, use the same tooling, test configuration and Go language
+ setup as we do in our other main products.
+- It should support multiple job execution environments - not only Docker containers
+ on Linux operating system.
+
+ The best design would be to bring auto-scaling as a feature wrapped around
+ our current executors like Docker or Shell.
+
+#### Principles for the new plugin system
+
+- Make the entry barrier for writing a new plugin low.
+- Developing a new plugin should be simple and require only basic knowledge of
+ a programming language and a cloud provider's API.
+- Strive for a balance between the plugin system's simplicity and flexibility.
+ These are not mutually exclusive.
+- Abstract away as many technical details as possible but do not hide them completely.
+- Build an abstraction that serves our community well but allows us to ship it quickly.
+- Invest in a flexible solution, avoid one-way-door decisions, foster iteration.
+- When in doubts err on the side of making things more simple for the wider community.
+- Limit coupling between concerns to make the system more simple and extensible.
+- Concerns should live on one side of the plug or the other--not both, which
+ duplicates effort and increases coupling.
+
+#### The most important technical details
+
+- Favor gRPC communication between a plugin and GitLab Runner.
+- Make it possible to version communication interface and support many versions.
+- Make Go a primary language for writing plugins but accept other languages too.
+- Autoscaling mechanism should be fully owned by GitLab.
+
+ Cloud provider autoscalers don't know which VM to delete when scaling down so
+ they make sub-optimal decisions. Rather than teaching all autoscalers about GitLab
+ jobs, we prefer to have one, GitLab-owned autoscaler (not in the plugin).
+
+ It will also ensure that we can shape the future of the mechanism and make decisions
+ that fit our needs and requirements.
+
+## Plugin boundary proposals
+
+The following are proposals for where to draw the plugin boundary. We will evaluate
+these proposals and others by the design principles and technical constraints
+listed above.
### Custom provider
@@ -204,43 +384,33 @@ document, define requirements and score the solution accordingly. This will
allow us to choose a solution that will work best for us and the wider
community.
-### Design principles
-
-Our goal is to design a GitLab Runner plugin system interface that is flexible
-and simple for the wider community to consume. As we cannot build plugins for
-all cloud platforms, we want to ensure a low entry barrier for anyone who needs
-to develop a plugin. We want to allow everyone to contribute.
+This proposal places VM lifecycle and autoscaling concerns as well as job to
+VM mapping (routing) into the plugin. The build need only ask for a VM and
+it will get one with all aspects of lifecycle and routing already accounted
+for by the plugin.
-To achieve this goal, we will follow a few critical design principles. These
-principles will guide our development process for the new plugin system
-abstraction.
+Rationale: [Description of the Custom Executor Provider proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28848#note_823321515)
-#### General high-level principles
+### Fleeting VM provider
-1. Design the new auto-scaling architecture aiming for having more choices and
- flexibility in the future, instead of imposing new constraints.
-1. Design the new auto-scaling architecture to experiment with running multiple
- jobs in parallel, on a single machine.
-1. Design the new provisioning architecture to replace Docker Machine in a way
- that the wider community can easily build on top of the new abstractions.
+We can introduce a more simple version of the `Machine` abstraction in the
+form of a "Fleeting" interface. Fleeting provides a low-level interface to
+a homogenous VM group which allows increasing and decreasing the set size
+as well as consuming a VM from within the set.
-#### Principles for the new plugin system
+Plugins for cloud providers and other VM sources are implemented via the
+Hashicorp go-plugin library. This is in practice gRPC over STDIN/STDOUT
+but other wire protocols can be used also.
-1. Make the entry barrier for writing a new plugin low.
-1. Developing a new plugin should be simple and require only basic knowledge of
- a programming language and a cloud provider's API.
-1. Strive for a balance between the plugin system's simplicity and flexibility.
- These are not mutually exclusive.
-1. Abstract away as many technical details as possible but do not hide them completely.
-1. Build an abstraction that serves our community well but allows us to ship it quickly.
-1. Invest in a flexible solution, avoid one-way-door decisions, foster iteration.
-1. When in doubts err on the side of making things more simple for the wider community.
+In order to make use of the new interface, the autoscaling logic is pulled
+out of the Docker Executor and placed into a new Taskscaler library.
-#### The most important technical details
+This places the concerns of VM lifecycle, VM shape and job routing within
+the plugin. It also places the conern of VM autoscaling into a separate
+component so it can be used by multiple Runner Executors (not just `docker+autoscaling`).
-1. Favor gRPC communication between a plugin and GitLab Runner.
-1. Make it possible to version communication interface and support many versions.
-1. Make Go a primary language for writing plugins but accept other languages too.
+Rationale: [Description of the InstanceGroup / Fleeting proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28848#note_823430883)
+POC: [Merge request](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3315)
## Status
@@ -252,26 +422,26 @@ Proposal:
<!-- vale gitlab.Spelling = NO -->
-| Role | Who
-|------------------------------|------------------------------------------|
-| Authors | Grzegorz Bizon, Tomasz Maczukin |
-| Architecture Evolution Coach | Kamil Trzciński |
-| Engineering Leader | Elliot Rushton, Cheryl Li |
-| Product Manager | Darren Eastman, Jackie Porter |
-| Domain Expert / Runner | Arran Walker |
+| Role | Who |
+|------------------------------|-------------------------------------------------|
+| Authors | Grzegorz Bizon, Tomasz Maczukin, Joseph Burnett |
+| Architecture Evolution Coach | Kamil Trzciński |
+| Engineering Leader | Elliot Rushton, Cheryl Li |
+| Product Manager | Darren Eastman, Jackie Porter |
+| Domain Expert / Runner | Arran Walker |
DRIs:
-| Role | Who
-|------------------------------|------------------------|
-| Leadership | Elliot Rushton |
-| Product | Darren Eastman |
-| Engineering | Tomasz Maczukin |
+| Role | Who |
+|-------------|-----------------|
+| Leadership | Elliot Rushton |
+| Product | Darren Eastman |
+| Engineering | Tomasz Maczukin |
Domain experts:
-| Area | Who
-|------------------------------|------------------------|
-| Domain Expert / Runner | Arran Walker |
+| Area | Who |
+|------------------------|--------------|
+| Domain Expert / Runner | Arran Walker |
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/work_items/index.md b/doc/architecture/blueprints/work_items/index.md
new file mode 100644
index 00000000000..42864e7112e
--- /dev/null
+++ b/doc/architecture/blueprints/work_items/index.md
@@ -0,0 +1,130 @@
+---
+stage: Plan
+group: Project Management
+comments: false
+description: 'Work Items'
+---
+
+# Work Items
+
+DISCLAIMER:
+This page may contain information related to upcoming products, features and functionality. It is important to note that the information presented is for informational purposes only, so please do not rely on the information for purchasing or planning purposes. Just like with all projects, the items mentioned on the page are subject to change or delay, and the development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
+
+This document is a work-in-progress. Some aspects are not documented, though we expect to add them in the future.
+
+## Summary
+
+Work Items is a new architecture created to support the various types of built and planned entities throughout the product, such as issues, requirements, and incidents. It will make these types easy to extend and customize while sharing the same core functionality.
+
+## Terminology
+
+We use the following terms to describe components and properties of the Work items architecture.
+
+### Work Item
+
+Base type for issue, requirement, test case, incident and task (this list is planned to extend in the future). Different work items have the same set of base properties but their [widgets](#work-item-widgets) list is different.
+
+### Work Item types
+
+A set of predefined types for different categories of work items. Currently, the available types are:
+
+- Issue
+- Incident
+- Test case
+- Requirement
+- Task
+
+#### Work Item properties
+
+Every Work Item type has the following common properties:
+
+- `id` - a unique Work Item global identifier;
+- `iid` - internal ID of the Work Item, relative to the parent workspace (currently workspace can only be a project)
+- Work Item type;
+- properties related to Work Item modification time: `createdAt`, `updatedAt`, `closedAt`;
+- title string;
+- Work Item confidentiality state;
+- Work Item state (can be open or closed);
+- lock version, incremented each time the work item is updated;
+- permissions for the current user on the resource
+- a list of [Work Item widgets](#work-item-widgets)
+
+### Work Item widgets
+
+All Work Item types share the same pool of predefined widgets and are customized by which widgets are active on a specific type. The list of widgets for any certain Work Item type is currently predefined and is not customizable. However, in the future we plan to allow users to create new Work Item types and define a set of widgets for them.
+
+### Work Item widget types (updating)
+
+- assignees
+- description
+- hierarchy
+- iteration
+- labels
+- start and due date
+- verification status
+- weight
+
+### Work Item view
+
+The new frontend view that renders Work Items of any type using global Work Item `id` as an identifier.
+
+### Task
+
+Task is a special Work Item type. Tasks can be added to issues as child items and can be displayed in the modal on the issue view.
+
+## Motivation
+
+Work Items main goal is to enhance the planning toolset to become the most popular collaboration tool for knowledge workers in any industry.
+
+- Puts all like-items (issues, incidents, epics, test cases etc.) on a standard platform to simplify maintenance and increase consistency in experience
+- Enables first-class support of common planning concepts to lower complexity and allow users to plan without learning GitLab-specific nuances.
+
+## Goals
+
+### Scalability
+
+Currently, different entities like issues, epics, merge requests etc share many similar features but these features are implemented separately for every entity type. This makes implementing new features or refactoring existing ones problematic: for example, if we plan to add new feature to issues and incidents, we would need to implement it separately on issue and incident types respectively. With work items, any new feature is implemented via widgets for all existing types which makes the architecture more scalable.
+
+### Flexibility
+
+With existing implementation, we have a rigid structure for issuables, merge requests, epics etc. This structure is defined on both backend and frontend, so any change requires a coordinated effort. Also, it would be very hard to make this structure customizable for the user without introducing a set of flags to enable/disable any existing feature. Work Item architecture allows frontend to display Work Item widgets in a flexible way: whatever is present in Work Item widgets, will be rendered on the page. This allows us to make changes fast and makes the structure way more flexible. For example, if we want to stop displaying labels on the Incident page, we remove labels widget from Incident Work Item type on the backend. Also, in the future this will allow users to define the set of widgets they want to see on custom Work Item types.
+
+### A consistent experience
+
+As much as we try to have consistent behavior for similar features on different entities, we still have differences in the implementation. For example, updating labels on merge request via GraphQL API can be done with dedicated `setMergeRequestLabels` mutation, while for the issue we call more coarse-grained `updateIssue`. This provides inconsistent experience for both frontend and external API users. As a result, epics, issues, requirements, and others all have similar but just subtle enough differences in common interactions that the user needs to hold a complicated mental model of how they each behave.
+
+Work Item architecture is designed with making all the features for all the types consistent, implemented as Work Item widgets.
+
+## High-level architecture problems to solve
+
+- how can we bypass groups and projects consolidation to migrate epics to Work Item type;
+- dealing with parent-child relationships for certain Work Item types: epic > issue > task, and to the same Work Item types: issue > issue.
+- [implementing custom Work Item types and custom widgets](https://gitlab.com/gitlab-org/gitlab/-/issues/335110)
+
+### Links
+
+- [Work items initiative epic](https://gitlab.com/groups/gitlab-org/-/epics/6033)
+- [Tasks roadmap](https://gitlab.com/groups/gitlab-org/-/epics/7103?_gl=1*zqatx*_ga*NzUyOTc3NTc1LjE2NjEzNDcwMDQ.*_ga_ENFH3X7M5Y*MTY2MjU0MDQ0MC43LjEuMTY2MjU0MDc2MC4wLjAuMA..)
+- [Work Item "Vision" Prototype](https://gitlab.com/gitlab-org/gitlab/-/issues/368607)
+- [Work Item Discussions](https://gitlab.com/groups/gitlab-org/-/epics/7060)
+
+### Who
+
+| Role | Who
+|------------------------------|-----------------------------|
+| Author | Natalia Tepluhina |
+| Architecture Evolution Coach | Kamil Trzciński |
+| Engineering Leader | TBD |
+| Product Manager | Gabe Weaver |
+| Domain Expert / Frontend | Natalia Tepluhina |
+| Domain Expert / Backend | Heinrich Lee Yu |
+| Domain Expert / Backend | Jan Provaznik |
+| Domain Expert / Backend | Mario Celi |
+
+DRIs:
+
+| Role | Who
+|------------------------------|------------------------|
+| Leadership | TBD |
+| Product | Gabe Weaver |
+| Engineering | TBD |
diff --git a/doc/architecture/index.md b/doc/architecture/index.md
index 5dee2fd8a80..643f5766b0a 100644
--- a/doc/architecture/index.md
+++ b/doc/architecture/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Architecture Practice at GitLab'
---
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index d34f44ea9ba..c93d2b6a82a 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Caching in GitLab CI/CD **(FREE)**
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index 21b970536bc..3354c94aff2 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, concepts, howto
---
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index cfe7be064fb..6256f11f1ea 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md
index a48822fc214..18cc430c225 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index 7c0889a329a..7b9145050bf 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, howto
---
diff --git a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
index 2d1c3f927e2..4a6b96736df 100644
--- a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
+++ b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy to Amazon Elastic Container Service **(FREE)**
diff --git a/doc/ci/cloud_deployment/ecs/quick_start_guide.md b/doc/ci/cloud_deployment/ecs/quick_start_guide.md
deleted file mode 100644
index 7522bc80d0d..00000000000
--- a/doc/ci/cloud_deployment/ecs/quick_start_guide.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'deploy_to_aws_ecs.md'
-remove_date: '2022-09-18'
----
-
-This document was moved to [another location](deploy_to_aws_ecs.md).
-
-<!-- This redirect file can be deleted after <2022-09-18>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> \ No newline at end of file
diff --git a/doc/ci/cloud_deployment/heroku.md b/doc/ci/cloud_deployment/heroku.md
index 4e627675b01..541ba89dca8 100644
--- a/doc/ci/cloud_deployment/heroku.md
+++ b/doc/ci/cloud_deployment/heroku.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use GitLab CI/CD to deploy to Heroku
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 82d914f0a6a..83774f63566 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -11,7 +11,7 @@ GitLab provides Docker images with the libraries and tools you need to deploy
to AWS. You can reference these images in your CI/CD pipeline.
If you're using GitLab.com and deploying to the [Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (ECS),
-read about [deploying to ECS](ecs/quick_start_guide.md).
+read about [deploying to ECS](ecs/deploy_to_aws_ecs.md).
## Authenticate GitLab with AWS
diff --git a/doc/ci/cloud_services/aws/index.md b/doc/ci/cloud_services/aws/index.md
index 2e1abf83a11..cc4dd53b29f 100644
--- a/doc/ci/cloud_services/aws/index.md
+++ b/doc/ci/cloud_services/aws/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure OpenID Connect in AWS to retrieve temporary credentials
diff --git a/doc/ci/cloud_services/azure/index.md b/doc/ci/cloud_services/azure/index.md
index 901b36afde6..944f95c03e2 100644
--- a/doc/ci/cloud_services/azure/index.md
+++ b/doc/ci/cloud_services/azure/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure OpenID Connect in Azure to retrieve temporary credentials
@@ -16,7 +16,7 @@ Prerequisites:
- Access to an existing Azure Subscription with `Owner` access level.
- Access to the corresponding Azure Active Directory Tenant with at least the `Application Developer` access level.
-- A local installation of the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli).
+- A local installation of the [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli).
Alternatively, you can follow all the steps below with the [Azure Cloud Shell](https://shell.azure.com/).
- A GitLab project.
@@ -27,11 +27,11 @@ To complete this tutorial:
1. [Grant permissions for the service principal](#grant-permissions-for-the-service-principal).
1. [Retrieve a temporary credential](#retrieve-a-temporary-credential).
-For more information, review Azure's documentation on [Workload identity federation](https://docs.microsoft.com/azure/active-directory/develop/workload-identity-federation).
+For more information, review Azure's documentation on [Workload identity federation](https://learn.microsoft.com/azure/active-directory/develop/workload-identity-federation).
## Create Azure AD application and service principal
-To create an [Azure AD application](https://docs.microsoft.com/cli/azure/ad/app?view=azure-cli-latest#az-ad-app-create)
+To create an [Azure AD application](https://learn.microsoft.com/cli/azure/ad/app?view=azure-cli-latest#az-ad-app-create)
and service principal:
1. In the Azure CLI, create the AD application:
@@ -43,13 +43,13 @@ and service principal:
Save the `appId` (Application client ID) output, as you need it later
to configure your GitLab CI/CD pipeline.
-1. Create a corresponding [Service Principal](https://docs.microsoft.com/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create):
+1. Create a corresponding [Service Principal](https://learn.microsoft.com/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create):
```shell
az ad sp create --id $appId --query appId -otsv
```
-Instead of the Azure CLI, you can [use the Azure Portal to create these resources](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).
+Instead of the Azure CLI, you can [use the Azure Portal to create these resources](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).
## Create Azure AD federated identity credentials
@@ -88,7 +88,7 @@ identity credentials from the Azure Portal:
## Grant permissions for the service principal
-After you create the credentials, use [`role assignment`](https://docs.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az-role-assignment-create)
+After you create the credentials, use [`role assignment`](https://learn.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az-role-assignment-create)
to grant permissions to the above service principal to access to Azure resources:
```shell
@@ -97,13 +97,13 @@ az role assignment create --assignee $appId --role Reader --scope /subscriptions
You can find your subscription ID in:
-- The [Azure Portal](https://docs.microsoft.com/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription).
-- The [Azure CLI](https://docs.microsoft.com/cli/azure/manage-azure-subscriptions-azure-cli#get-the-active-subscription).
+- The [Azure Portal](https://learn.microsoft.com/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription).
+- The [Azure CLI](https://learn.microsoft.com/cli/azure/manage-azure-subscriptions-azure-cli#get-the-active-subscription).
## Retrieve a temporary credential
After you configure the Azure AD application and federated identity credentials,
-the CI/CD job can retrieve a temporary credential by using the [Azure CLI](https://docs.microsoft.com/cli/azure/reference-index?view=azure-cli-latest#az-login):
+the CI/CD job can retrieve a temporary credential by using the [Azure CLI](https://learn.microsoft.com/cli/azure/reference-index?view=azure-cli-latest#az-login):
```yaml
default:
@@ -123,7 +123,7 @@ The CI/CD variables are:
- `AZURE_CLIENT_ID`: The [application client ID you saved earlier](#create-azure-ad-application-and-service-principal).
- `AZURE_TENANT_ID`: Your Azure Active Directory. You can
- [find it by using the Azure CLI or Azure Portal](https://docs.microsoft.com/azure/active-directory/fundamentals/active-directory-how-to-find-tenant).
+ [find it by using the Azure CLI or Azure Portal](https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-how-to-find-tenant).
- `CI_JOB_JWT_V2`: The JSON web token is a [predefined CI/CD variable](../../variables/predefined_variables.md).
## Troubleshooting
diff --git a/doc/ci/cloud_services/google_cloud/index.md b/doc/ci/cloud_services/google_cloud/index.md
index 54265816868..ba6efa4d35c 100644
--- a/doc/ci/cloud_services/google_cloud/index.md
+++ b/doc/ci/cloud_services/google_cloud/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure OpenID Connect with GCP Workload Identity Federation
diff --git a/doc/ci/cloud_services/index.md b/doc/ci/cloud_services/index.md
index 93fedb0ffca..b7129d92205 100644
--- a/doc/ci/cloud_services/index.md
+++ b/doc/ci/cloud_services/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connect to cloud services
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index f63ecc57028..ded91edeff5 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/docker/index.md b/doc/ci/docker/index.md
index 4f6da72af12..e976700c160 100644
--- a/doc/ci/docker/index.md
+++ b/doc/ci/docker/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index
---
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 4c9cb2923d7..06197d71690 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -608,7 +608,7 @@ build:
- docker run my-docker-image /script/to/run/tests
```
-To log in to Docker Hub, leave `$DOCKER_REGISTRY`
+To sign in to Docker Hub, leave `$DOCKER_REGISTRY`
empty or remove it.
### Option 2: Mount `~/.docker/config.json` on each job
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index f985b02be33..70680a44ed2 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -282,8 +282,8 @@ Use one of the following methods to determine the value for `DOCKER_AUTH_CONFIG`
configuration JSON manually. Open a terminal and execute the following command:
```shell
- # The use of "-n" - prevents encoding a newline in the password.
- echo -n "my_username:my_password" | base64
+ # The use of printf (as opposed to echo) prevents encoding a newline in the password.
+ printf "my_username:my_password" | openssl base64 -A
# Example output to copy
bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
@@ -402,7 +402,7 @@ pulling from Docker Hub fails. Docker daemon tries to use the same credentials f
> Introduced in GitLab Runner 12.0.
As an example, let's assume that you want to use the `<aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest`
-image. This image is private and requires you to log in into a private container registry.
+image. This image is private and requires you to sign in to a private container registry.
To configure access for `<aws_account_id>.dkr.ecr.<region>.amazonaws.com`, follow these steps:
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index ee8d73dd113..37b9ea87d7a 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md
index bac06972c7b..adb9b5a87d5 100644
--- a/doc/ci/enable_or_disable_ci.md
+++ b/doc/ci/enable_or_disable_ci.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/ci/environments/deployment_approvals.md b/doc/ci/environments/deployment_approvals.md
index 26461d9827f..5f5ec027827 100644
--- a/doc/ci/environments/deployment_approvals.md
+++ b/doc/ci/environments/deployment_approvals.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Require approvals prior to deploying to a Protected Environment
---
@@ -10,9 +10,6 @@ description: Require approvals prior to deploying to a Protected Environment
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 with a flag named `deployment_approvals`. Disabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/347342) in GitLab 14.8.
-WARNING:
-This feature is in a [Beta](../../policy/alpha-beta-support.md#beta-features) stage and subject to change without prior notice.
-
It may be useful to require additional approvals before deploying to certain protected environments (for example, production). This pre-deployment approval requirement is useful to accommodate testing, security, or compliance processes that must happen before each deployment.
When a protected environment requires one or more approvals, all deployments to that environment become blocked and wait for the required approvals from the `Allowed to Deploy` list before running.
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 90efc7ba9ef..665aeb23d28 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deployment safety **(FREE)**
diff --git a/doc/ci/environments/environments_dashboard.md b/doc/ci/environments/environments_dashboard.md
index 11e9fe90e25..f662c156f55 100644
--- a/doc/ci/environments/environments_dashboard.md
+++ b/doc/ci/environments/environments_dashboard.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md
index ee2e708f822..af431a9812e 100644
--- a/doc/ci/environments/incremental_rollouts.md
+++ b/doc/ci/environments/incremental_rollouts.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index c34a978709b..63641a9b7c3 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/ci/environments.html'
---
@@ -43,6 +43,18 @@ To view a list of environments and deployments:
Deployments show up in this list only after a deployment job has created them.
+## Search environments
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10754) in GitLab 15.5.
+
+To search environments by name:
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Environments**.
+1. In the search bar, enter your search term. Matching applies from the
+ beginning of the environment name. For example, `devel` matches the
+ environment name `development`, but `elop` does not.
+
## Types of environments
There are two types of environments:
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index e63777dc0e0..0f943679c07 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Protected environments **(PREMIUM)**
@@ -26,7 +26,7 @@ Maintainer role.
Prerequisites:
-- When granting the **Allowed to deploy** permission to a group or sub-group, the user configuring the protected environment must be a **direct member** of the group or sub-group to be added. Otherwise, the group or sub-group will not show up in the dropdown. For more information see [issue #345140](https://gitlab.com/gitlab-org/gitlab/-/issues/345140).
+- When granting the **Allowed to deploy** permission to a group or subgroup, the user configuring the protected environment must be a **direct member** of the group or subgroup to be added. Otherwise, the group or subgroup will not show up in the dropdown. For more information see [issue #345140](https://gitlab.com/gitlab-org/gitlab/-/issues/345140).
To protect an environment:
@@ -133,7 +133,7 @@ they have the following privileges:
Users granted access to a protected environment, but not push or merge access
to the branch deployed to it, are only granted access to deploy the environment.
[Invited groups](../../user/project/members/share_project_with_groups.md#share-a-project-with-a-group-of-users) added
-to the project with [Reporter role](../../user/permissions.md#project-members-permissions), appear in the dropdown menu for deployment-only access.
+to the project with [Reporter role](../../user/permissions.md#project-members-permissions), appear in the dropdown list for deployment-only access.
To add deployment-only access:
@@ -146,7 +146,7 @@ To add deployment-only access:
Maintainers can:
- Update existing protected environments at any time by changing the access in the
- **Allowed to Deploy** dropdown menu.
+ **Allowed to Deploy** dropdown list.
- Unprotect a protected environment by clicking the **Unprotect** button for that environment.
After an environment is unprotected, all access entries are deleted and must
@@ -194,7 +194,7 @@ and are protected at the same time.
### Configure group-level memberships
> - Operators are required to have Owner+ role from the original Maintainer+ role and this role change is introduced from GitLab 15.3 [with a flag](https://gitlab.com/gitlab-org/gitlab/-/issues/369873) named `group_level_protected_environment_settings_permission`. Enabled by default.
-> - Original behavior where Operators are required to have Maintainer+ role can be achieved by enabling [flag](https://gitlab.com/gitlab-org/gitlab/-/issues/369875) named `override_group_level_protected_environment_settings_permission`. Disabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/369873) in GitLab 15.4.
To maximize the effectiveness of group-level protected environments,
[group-level memberships](../../user/group/index.md) must be correctly
@@ -214,8 +214,8 @@ configured:
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:
- - Regarding [sub-groups](../../user/group/subgroups/index.md), if a higher
+- For subgroups and child projects:
+ - Regarding [subgroups](../../user/group/subgroups/index.md), if a higher
group has configured the group-level protected environment, the lower groups
cannot override it.
- [Project-level protected environments](#protecting-environments) can be
@@ -257,14 +257,10 @@ Configure the group-level protected environments by using the [REST API](../../a
Protected environments can also be used to require manual approvals before deployments. See [Deployment approvals](deployment_approvals.md) for more information.
-<!-- ## Troubleshooting
+## Troubleshooting
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
+### Reporter can't run a trigger job that deploys to a protected environment in downstream pipeline
-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. -->
+A user who has [deployment-only access to protected environments](#deployment-only-access-to-protected-environments) might **not** be able to run a job if it's with a [`trigger`](../yaml/index.md#trigger) keyword. This is because the job is missing the [`environment`](../yaml/index.md#environment) keyword definition to associate the job with the protected environment, therefore the job is recognized as a normal job that uses [regular CI/CD permission model](../../user/permissions.md#gitlab-cicd-permissions).
+
+Please see [this issue](https://gitlab.com/groups/gitlab-org/-/epics/8483) for more information about supporting `environment` keyword with `trigger` keyword.
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 00025a66936..59e377dbb09 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index aa4055c00ea..f14372757a9 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
diff --git a/doc/ci/examples/deployment/index.md b/doc/ci/examples/deployment/index.md
index b097f1fac76..7a20bfc2e0a 100644
--- a/doc/ci/examples/deployment/index.md
+++ b/doc/ci/examples/deployment/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
@@ -36,7 +36,7 @@ apt-get install ruby-dev
```
The Dpl provides support for vast number of services, including: Heroku, Cloud Foundry, AWS/S3, and more.
-To use it simply define provider and any additional parameters required by the provider.
+To use it, define provider and any additional parameters required by the provider.
For example if you want to use it to deploy your application to Heroku, you need to specify `heroku` as provider, specify `api_key` and `app`.
All possible parameters can be found in the [Heroku API section](https://github.com/travis-ci/dpl#heroku-api).
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/index.md b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
index 5ff99755242..e9f126b0409 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
author: Vincent Tunru
author_gitlab: Vinnl
description: 'Confidence checking your entire app every time a new feature is added can quickly become repetitive. Learn how to automate it with GitLab CI/CD.'
@@ -86,7 +86,7 @@ steering the browser. In this case, we can use
[`browser.url`](http://v4.webdriver.io/api/protocol/url.html) to visit `/page-that-does-not-exist` to
hit our 404 page. We can then use [`browser.getUrl`](http://v4.webdriver.io/api/property/getUrl.html)
to verify that the current page is indeed at the location we specified. To interact with the page,
-we can simply pass CSS selectors to
+we can pass CSS selectors to
[`browser.element`](http://v4.webdriver.io/api/protocol/element.html) to get access to elements on the
page and to interact with them - for example, to click on the link back to the home page.
diff --git a/doc/ci/examples/index.md b/doc/ci/examples/index.md
index 77591ad2ca6..361061d0d75 100644
--- a/doc/ci/examples/index.md
+++ b/doc/ci/examples/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index
---
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index 0735029f0be..80e476f2a87 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html'
author: Mehran Rasulian
author_gitlab: mehranrasulian
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index 9b9f87fffbb..2d0c6382dd8 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
@@ -189,7 +189,7 @@ phpenv config-add my_config.ini
Since this is a pretty bare installation of the PHP environment, you may need
some extensions that are not currently present on the build machine.
-To install additional extensions simply execute:
+To install additional extensions, execute:
```shell
pecl install <extension>
@@ -272,5 +272,5 @@ We have set up an [Example PHP Project](https://gitlab.com/gitlab-examples/php)
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/index.md).
-Want to hack on it? Simply fork it, commit, and push your changes. Within a few
+Want to hack on it? Fork it, commit, and push your changes. Within a few
moments the changes are picked by a public runner and the job begins.
diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md
index eaa7d8ebcfa..88e63a7f36f 100644
--- a/doc/ci/examples/semantic-release.md
+++ b/doc/ci/examples/semantic-release.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Publish npm packages to the GitLab Package Registry using semantic-release **(FREE)**
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index fbecb1cd964..ee9d15894fe 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -60,6 +60,14 @@ To make submodules work correctly in CI/CD jobs:
GIT_SUBMODULE_STRATEGY: recursive
```
+1. You can filter or exclude specific submodules to control which submodules will be synced using
+ [`GIT_SUBMODULE_PATHS`](runners/configure_runners.md#git-submodule-paths).
+
+ ```yaml
+ variables:
+ GIT_SUBMODULE_PATHS: submoduleA submoduleB
+ ```
+
1. You can provide additional flags to control advanced checkout behavior using
[`GIT_SUBMODULE_UPDATE_FLAGS`](runners/configure_runners.md#git-submodule-update-flags).
diff --git a/doc/ci/index.md b/doc/ci/index.md
index be7088ab153..ddc9ba5d475 100644
--- a/doc/ci/index.md
+++ b/doc/ci/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: "Learn how to use GitLab CI/CD, the GitLab built-in Continuous Integration, Continuous Deployment, and Continuous Delivery toolset to build, test, and deploy your application."
type: index
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index 03c905184cf..a1df55cfc38 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index add47c95051..ccf7ebccb2c 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "An overview of Continuous Integration, Continuous Delivery, and Continuous Deployment, as well as an introduction to GitLab CI/CD."
type: concepts
---
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index 812683ef2c1..7282ebb0909 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab CI/CD job token **(FREE)**
@@ -20,7 +20,8 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
(scoped to the job's project, when the `ci_job_token_scope` feature flag is enabled).
- [Get job artifacts](../../api/job_artifacts.md#get-job-artifacts).
- [Get job token's job](../../api/jobs.md#get-job-tokens-job).
-- [Pipeline triggers](../../api/pipeline_triggers.md), using the `token=` parameter.
+- [Pipeline triggers](../../api/pipeline_triggers.md), using the `token=` parameter
+ to [trigger a multi-project pipeline](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-by-using-the-api).
- [Releases](../../api/releases/index.md) and [Release links](../../api/releases/links.md).
- [Terraform plan](../../user/infrastructure/index.md).
@@ -78,7 +79,7 @@ to be accessed by authenticating with the current project's job token. By defaul
the token scope only allows access to the same project where the token comes from.
Other projects can be added and removed by maintainers with access to both projects.
-This setting is disabled by default for all new projects. It is recommended that project maintainers enable this
+This setting is disabled by default for all new projects. It is recommended that project maintainers or owners enable this
setting at all times, and configure the allowlist for cross-project access if needed.
For example, when the setting is enabled, jobs in a pipeline in project `A` have
@@ -99,28 +100,6 @@ The job token scope is only for controlling access to private projects.
There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559) to improve
the feature with more strategic control of the access permissions.
-## Trigger a multi-project pipeline by using a CI/CD job token
-
-> `CI_JOB_TOKEN` for multi-project pipelines was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/31573) from GitLab Premium to GitLab Free in 12.4.
-
-You can use the `CI_JOB_TOKEN` to [trigger multi-project pipelines](../../api/pipeline_triggers.md#trigger-a-pipeline-with-a-token)
-from a CI/CD job.
-
-For example:
-
-```yaml
-trigger_pipeline:
- stage: deploy
- script:
- - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
- rules:
- - if: $CI_COMMIT_TAG
- environment: production
-```
-
-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#configure-cicd-jobs-to-run-in-triggered-pipelines).
-
## Download an artifact from a different pipeline **(PREMIUM)**
> `CI_JOB_TOKEN` for artifacts download with the API was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346) in GitLab 9.5.
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index 806837e3dc8..d1a4f1e35bf 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jobs **(FREE)**
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index 5a94c2e9bbc..39ab0998291 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Choose when to run jobs **(FREE)**
@@ -624,8 +624,9 @@ by authorized users.
Use [`when: delayed`](../yaml/index.md#when) to execute scripts after a waiting period, or if you want to avoid
jobs immediately entering the `pending` state.
-You can set the period with `start_in` keyword. The value of `start_in` is an elapsed time in seconds, unless a unit is
-provided. `start_in` must be less than or equal to one week. Examples of valid values include:
+You can set the period with `start_in` keyword. The value of `start_in` is an elapsed time
+in seconds, unless a unit is provided. The minimum is one second, and the maximum is one week.
+Examples of valid values include:
- `'5'` (a value with no unit must be surrounded by single quotes)
- `5 seconds`
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 3904a527a8f..c7ecc25dc44 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -260,3 +260,8 @@ For very active repositories with a large number of references and files, you ca
- 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
[SaaS runners on Linux](../runners/saas/linux_saas_runner.md#pre-clone-script) for details.
+ Besides speeding up pipelines in large and active projects,
+ seeding the repository data also helps avoid
+ `429 Too many requests` errors from Cloudflare.
+ This error can occur if you have many runners behind a single,
+ NAT'ed IP address that pulls from GitLab.com.
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index 8c64d968b8b..c297cab1822 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Validate GitLab CI/CD configuration **(FREE)**
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
deleted file mode 100644
index c3ab3392f36..00000000000
--- a/doc/ci/metrics_reports.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'testing/metrics_reports.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](testing/metrics_reports.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index efe11466674..5354e406e34 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index, howto
---
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 35c5a7e56c8..300de610aa7 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index, howto
---
@@ -66,6 +66,9 @@ of transition, by letting you delay the migration of less urgent pipelines for a
If you are interested in helping GitLab test the wrapper, join our [public testing issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215675) for instructions and to provide your feedback.
+NOTE:
+If you have a paid GitLab subscription, note that the JenkinsFile Wrapper is not packaged as part of GitLab, and falls outside of the scope of support. For more information, see the [Statement of Support](https://about.gitlab.com/support/statement-of-support.html).
+
## Important product differences
There are some high level differences between the products worth mentioning:
@@ -208,7 +211,7 @@ For advanced CI/CD teams, project templates can enable the reuse of pipeline con
as well as encourage inner sourcing.
In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.md).
-Development teams across the whole organization can select templates from a dropdown menu.
+Development teams across the whole organization can select templates from a dropdown list.
A group maintainer or a group owner is able to set a group to use as the source for the
[custom project templates](../../user/admin_area/custom_project_templates.md), which can
be used by all projects in the group. An instance administrator can set a group as
diff --git a/doc/ci/mobile_devops.md b/doc/ci/mobile_devops.md
index 6eb56434a1b..1359191f6a6 100644
--- a/doc/ci/mobile_devops.md
+++ b/doc/ci/mobile_devops.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index 87c2b3f1c71..c4416d41ab4 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md
index 02a74883244..a5484fcdf5a 100644
--- a/doc/ci/pipelines/cicd_minutes.md
+++ b/doc/ci/pipelines/cicd_minutes.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -139,6 +139,8 @@ Premium license:
If you use `13,000` minutes during the month, the next month your additional minutes become
`2,000`. If you use `9,000` minutes during the month, your additional minutes remain the same.
+If you bought additional CI/CD minutes while on a trial subscription those minutes will be available after the trial ends or you upgrade to a paid plan.
+
You can find pricing for additional CI/CD minutes on the
[GitLab Pricing page](https://about.gitlab.com/pricing/).
@@ -205,8 +207,8 @@ The cost factors for jobs running on shared runners on GitLab.com are:
- `0.5` for public projects in the [GitLab for Open Source program](../../subscriptions/index.md#gitlab-for-open-source).
- `0.008` for public forks of public projects in the [GitLab for Open Source program](../../subscriptions/index.md#gitlab-for-open-source). For every 125 minutes of job execution time,
you use 1 CI/CD minute.
-- `0.04` for other public projects, after September 1, 2022 (previously `0.008`).
- For every 25 minutes of job execution time, you use 1 CI/CD minute.
+- `1` for other public projects, after October 1, 2022 (previously `0.04`).
+ For every 1 minute of job execution time, you use 1 CI/CD minute.
- Calculated differently for [community contributions to GitLab projects](#cost-factor-for-community-contributions-to-gitlab-projects).
The cost factors on self-managed instances are:
@@ -246,7 +248,6 @@ GitLab SaaS runners have different cost factors, depending on the runner type (L
| Linux OS + Docker executor| Small |1|
| Linux OS + Docker executor| Medium |2|
| Linux OS + Docker executor| Large |3|
-| macOS + shell executor | Large| 6 |
### Monthly reset of CI/CD minutes
diff --git a/doc/ci/pipelines/downstream_pipelines.md b/doc/ci/pipelines/downstream_pipelines.md
index 6c7ec8e98ec..0b1963e1874 100644
--- a/doc/ci/pipelines/downstream_pipelines.md
+++ b/doc/ci/pipelines/downstream_pipelines.md
@@ -1,39 +1,65 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Downstream pipelines **(FREE)**
A downstream pipeline is any GitLab CI/CD pipeline triggered by another pipeline.
-A downstream pipeline can be either:
+Downstream pipelines run independently and concurrently to the upstream pipeline
+that triggered them.
-- A [parent-child pipeline](downstream_pipelines.md#parent-child-pipelines), which is a downstream pipeline triggered
- in the same project as the first pipeline.
-- A [multi-project pipeline](#multi-project-pipelines), which is a downstream pipeline triggered
- in a different project than the first pipeline.
+- A [parent-child pipeline](downstream_pipelines.md#parent-child-pipelines) is a downstream pipeline
+ triggered in the *same* project as the first pipeline.
+- A [multi-project pipeline](#multi-project-pipelines) is a downstream pipeline triggered
+ in a *different* project than the first pipeline.
-Parent-child pipelines and multi-project pipelines can sometimes be used for similar purposes,
-but there are some key differences.
+You can sometimes use parent-child pipelines and multi-project pipelines for similar purposes,
+but there are [key differences](pipeline_architectures.md).
-Parent-child pipelines:
+## Parent-child pipelines
+
+A parent pipeline is one that triggers a downstream pipeline in the same project.
+The downstream pipeline is called a child pipeline. Child pipelines:
- Run under the same project, ref, and commit SHA as the parent pipeline.
-- Affect the overall status of the ref the pipeline runs against. For example,
+- Do not directly affect the overall status of the ref the pipeline runs against. For example,
if a pipeline fails for the main branch, it's common to say that "main is broken".
- The status of child pipelines don't directly affect the status of the ref, unless the child
+ The status of child pipelines only affects the status of the ref if the child
pipeline is triggered with [`strategy:depend`](../yaml/index.md#triggerstrategy).
- Are automatically canceled if the pipeline is configured with [`interruptible`](../yaml/index.md#interruptible)
when a new pipeline is created for the same ref.
-- Display only the parent pipelines in the pipeline index page. Child pipelines are
- visible when visiting their parent pipeline's page.
-- Are limited to 2 levels of nesting. A parent pipeline can trigger multiple child pipelines,
- and those child pipeline can trigger multiple child pipelines (`A -> B -> C`).
+- Are not displayed in the pipeline index page. You can only view child pipelines on
+ their parent pipeline's page.
+
+### Nested child pipelines
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243747) in GitLab 13.5.
+
+Parent and child pipelines were introduced with a maximum depth of one level of child
+pipelines, which was later increased to two. A parent pipeline can trigger many child
+pipelines, and these child pipelines can trigger their own child pipelines. It's not
+possible to trigger another level of child pipelines.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M).
+
+## Multi-project pipelines
+
+A pipeline in one project can trigger downstream pipelines in another project,
+called multi-project pipelines. The user triggering the upstream pipeline must be able to
+start pipelines in the downstream project, otherwise [the downstream pipeline fails to start](#trigger-job-fails-and-does-not-create-multi-project-pipeline).
+
+For example, you might deploy your web application from three different GitLab projects.
+With multi-project pipelines you can trigger a pipeline in each project, where each
+has its own build, test, and deploy process. You can visualize the connected pipelines
+in one place, including all cross-project interdependencies.
Multi-project pipelines:
-- Are triggered from another pipeline, but the upstream (triggering) pipeline does
+- Are triggered from another project's pipeline, but the upstream (triggering) pipeline does
not have much control over the downstream (triggered) pipeline. However, it can
choose the ref of the downstream pipeline, and pass CI/CD variables to it.
- Affect the overall status of the ref of the project it runs in, but does not
@@ -46,75 +72,86 @@ Multi-project pipelines:
that happened to be triggered by an external project. They are all visible on the pipeline index page.
- Are independent, so there are no nesting limits.
-## Multi-project pipelines
+Learn more in the "Cross-project Pipeline Triggering and Visualization" demo at
+[GitLab@learn](https://about.gitlab.com/learn/), in the Continuous Integration section.
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
+If you use a public project to trigger downstream pipelines in a private project,
+make sure there are no confidentiality problems. The upstream project's pipelines page
+always displays:
-You can set up [GitLab CI/CD](../index.md) across multiple projects, so that a pipeline
-in one project can trigger a downstream pipeline in another project. You can visualize the entire pipeline
-in one place, including all cross-project interdependencies.
-
-For example, you might deploy your web application from three different projects in GitLab.
-Each project has its own build, test, and deploy process. With multi-project pipelines you can
-visualize the entire pipeline, including all build and test stages for all three projects.
+- The name of the downstream project.
+- The status of the pipeline.
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see the [Multi-project pipelines demo](https://www.youtube.com/watch?v=g_PIwBM1J84).
+## Trigger a downstream pipeline from a job in the `.gitlab-ci.yml` file
-Multi-project pipelines are also useful for larger products that require cross-project interdependencies, like those
-with a [microservices architecture](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/).
-Learn more in the [Cross-project Pipeline Triggering and Visualization demo](https://about.gitlab.com/learn/)
-at GitLab@learn, in the Continuous Integration section.
+Use the [`trigger`](../yaml/index.md#trigger) keyword in your `.gitlab-ci.yml` file
+to create a job that triggers a downstream pipeline. This job is called a trigger job.
-If you trigger a pipeline in a downstream private project, on the upstream project's pipelines page,
-you can view:
+After the trigger job starts, the initial status of the job is `pending` while GitLab
+attempts to create the downstream pipeline. If the downstream pipeline is created,
+GitLab marks the job as passed, otherwise the job failed. Alternatively,
+you can [set the trigger job to show the downstream pipeline's status](#mirror-the-status-of-a-downstream-pipeline-in-the-trigger-job)
+instead.
-- The name of the project.
-- The status of the pipeline.
+For example:
-If you have a public project that can trigger downstream pipelines in a private project,
-make sure there are no confidentiality problems.
+::Tabs
-### Trigger a multi-project pipeline from a job in your `.gitlab-ci.yml` file
+:::TabTitle Multi-project pipeline
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
+```yaml
+trigger_job:
+ trigger:
+ project: project-group/my-downstream-project
+```
-When you use the [`trigger`](../yaml/index.md#trigger) keyword to create a multi-project
-pipeline in your `.gitlab-ci.yml` file, you create what is called a *trigger job*. For example:
+:::TabTitle Parent-child pipeline
```yaml
-rspec:
- stage: test
- script: bundle exec rspec
-
-staging:
- variables:
- ENVIRONMENT: staging
- stage: deploy
- trigger: my/deployment
+trigger_job:
+ trigger:
+ include:
+ - local: path/to/child-pipeline.yml
```
-In this example, after the `rspec` job succeeds in the `test` stage,
-the `staging` trigger job starts. The initial status of this
-job is `pending`.
+::EndTabs
-GitLab then creates a downstream pipeline in the
-`my/deployment` project and, as soon as the pipeline is created, the
-`staging` job succeeds. The full path to the project is `my/deployment`.
+### Use `rules` to control downstream pipeline jobs
-You can view the status for the pipeline, or you can display
-[the downstream pipeline's status instead](#mirror-the-status-of-a-downstream-pipeline-in-the-trigger-job).
+You can use CI/CD variables or the [`rules`](../yaml/index.md#rulesif) keyword to
+[control job behavior](../jobs/job_control.md) for downstream pipelines.
-The user that creates the upstream pipeline must be able to create pipelines in the
-downstream project (`my/deployment`) too. If the downstream project is not found,
-or the user does not have [permission](../../user/permissions.md) to create a pipeline there,
-the `staging` job is marked as _failed_.
+When a downstream pipeline is triggered with the [`trigger`](../yaml/index.md#trigger) keyword,
+the value of the [`$CI_PIPELINE_SOURCE` predefined variable](../variables/predefined_variables.md)
+for all jobs is:
-#### Specify a downstream pipeline branch
+- `pipeline` for multi-project pipelines.
+- `parent` for parent-child pipelines.
-You can specify a branch name for the downstream pipeline to use.
-GitLab uses the commit on the head of the branch to
-create the downstream pipeline.
+For example, with a multi-project pipeline:
+
+```yaml
+job1:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "pipeline"
+ script: echo "This job runs in multi-project pipelines only"
+
+job2:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script: echo "This job runs in merge request pipelines only"
+
+job3:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "pipeline"
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script: echo "This job runs in both multi-project and merge request pipelines"
+```
+
+### Specify a branch for multi-project pipelines
+
+You can specify a branch name for a multi-project pipeline to use. GitLab uses
+the commit on the head of the branch to create the downstream pipeline:
```yaml
rspec:
@@ -137,100 +174,25 @@ Use:
In [GitLab 12.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/10126), variable expansion is
supported.
-Pipelines triggered on a protected branch in a downstream project use the [role](../../user/permissions.md)
-of the user that ran the trigger job in the upstream project. If the user does not
-have permission to run CI/CD pipelines against the protected branch, the pipeline fails. See
-[pipeline security for protected branches](index.md#pipeline-security-on-protected-branches).
-
-#### Use `rules` or `only`/`except` with multi-project pipelines
-
-You can use CI/CD variables or the [`rules`](../yaml/index.md#rulesif) keyword to
-[control job behavior](../jobs/job_control.md) for multi-project pipelines. When a
-downstream pipeline is triggered with the [`trigger`](../yaml/index.md#trigger) keyword,
-the value of the [`$CI_PIPELINE_SOURCE` predefined variable](../variables/predefined_variables.md)
-is `pipeline` for all its jobs.
-
-If you use [`only/except`](../yaml/index.md#only--except) to control job behavior, use the
-[`pipelines`](../yaml/index.md#onlyrefs--exceptrefs) keyword.
-
-### Trigger a multi-project pipeline by using the API
-
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/31573) to GitLab Free in 12.4.
-
-When you use the [`CI_JOB_TOKEN` to trigger pipelines](../jobs/ci_job_token.md),
-GitLab recognizes the source of the job token. The pipelines become related,
-so you can visualize their relationships on pipeline graphs.
-
-These relationships are displayed in the pipeline graph by showing inbound and
-outbound connections for upstream and downstream pipeline dependencies.
-
-When using:
-
-- CI/CD variables or [`rules`](../yaml/index.md#rulesif) to control job behavior, the value of
- the [`$CI_PIPELINE_SOURCE` predefined variable](../variables/predefined_variables.md) is
- `pipeline` for multi-project pipeline triggered through the API with `CI_JOB_TOKEN`.
-- [`only/except`](../yaml/index.md#only--except) to control job behavior, use the
- `pipelines` keyword.
-
-## Parent-child pipelines
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7.
-
-As pipelines grow more complex, a few related problems start to emerge:
-
-- The staged structure, where all steps in a stage must be completed before the first
- job in next stage begins, causes arbitrary waits, slowing things down.
-- Configuration for the single global pipeline becomes very long and complicated,
- making it hard to manage.
-- Imports with [`include`](../yaml/index.md#include) increase the complexity of the configuration, and create the potential
- for namespace collisions where jobs are unintentionally duplicated.
-- Pipeline UX can become unwieldy with so many jobs and stages to work with.
+### Use a child pipeline configuration file in a different project
-Additionally, sometimes the behavior of a pipeline needs to be more dynamic. The ability
-to choose to start sub-pipelines (or not) is a powerful ability, especially if the
-YAML is dynamically generated.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205157) in GitLab 13.5.
-![Parent pipeline graph expanded](img/parent_pipeline_graph_expanded_v14_3.png)
-
-Similarly to [multi-project pipelines](#multi-project-pipelines), a pipeline can trigger a
-set of concurrently running downstream child pipelines, but in 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. 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.
-
-Child pipelines work well with other GitLab CI/CD features:
-
-- Use [`rules: changes`](../yaml/index.md#ruleschanges) to trigger pipelines only when
- certain files change. This is useful for monorepos, for example.
-- 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
-include the child pipeline configuration.
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Parent-Child Pipelines feature demo](https://youtu.be/n8KpBSqZNbk).
-
-NOTE:
-The artifact containing the generated YAML file must not be larger than 5MB.
-
-### Trigger a parent-child pipeline
-
-The simplest case is [triggering a child pipeline](../yaml/index.md#trigger) using a
-local YAML file to define the pipeline configuration. In this case, the parent pipeline
-triggers the child pipeline, and continues without waiting:
+You can use [`include:file`](../yaml/index.md#includefile) to trigger child pipelines
+with a configuration file in a different project:
```yaml
microservice_a:
trigger:
- include: path/to/microservice_a.yml
+ include:
+ - project: 'my-group/my-pipeline-library'
+ ref: 'main'
+ file: '/path/to/child-pipeline.yml'
```
-You can include multiple files when defining a child pipeline. The child pipeline's
+### Combine multiple child pipeline configuration files
+
+You can include up to three configuration files when defining a child pipeline. The child pipeline's
configuration is composed of all configuration files merged together:
```yaml
@@ -239,134 +201,139 @@ microservice_a:
include:
- local: path/to/microservice_a.yml
- template: Security/SAST.gitlab-ci.yml
-```
-
-In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/205157),
-you can use [`include:file`](../yaml/index.md#includefile) to trigger child pipelines
-with a configuration file in a different project:
-
-```yaml
-microservice_a:
- trigger:
- include:
- project: 'my-group/my-pipeline-library'
ref: 'main'
file: '/path/to/child-pipeline.yml'
```
-The maximum number of entries that are accepted for `trigger:include` is three.
+### Dynamic child pipelines
-### Merge request child pipelines
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9.
-To trigger a child pipeline as a [merge request pipeline](merge_request_pipelines.md) we need to:
+You can trigger a child pipeline from a YAML file generated in a job, instead of a
+static file saved in your project. This technique can be very powerful for generating pipelines
+targeting content that changed or to build a matrix of targets and architectures.
-- Set the trigger job to run on merge requests:
+The artifact containing the generated YAML file must not be [larger than 5MB](https://gitlab.com/gitlab-org/gitlab/-/issues/249140).
-```yaml
-# parent .gitlab-ci.yml
-microservice_a:
- trigger:
- include: path/to/microservice_a.yml
- rules:
- - if: $CI_MERGE_REQUEST_ID
-```
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM).
-- Configure the child pipeline by either:
+For an example project that generates a dynamic child pipeline, see
+[Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet).
+This project shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime.
+You can use a similar process for other templating languages like
+[Dhall](https://dhall-lang.org/) or [ytt](https://get-ytt.io/).
- - Setting all jobs in the child pipeline to evaluate in the context of a merge request:
+#### Trigger a dynamic child pipeline
- ```yaml
- # child path/to/microservice_a.yml
- workflow:
- rules:
- - if: $CI_MERGE_REQUEST_ID
+To trigger a child pipeline from a dynamically generated configuration file:
- job1:
- script: ...
+1. Generate the configuration file in a job and save it as an [artifact](../yaml/index.md#artifactspaths):
- job2:
- script: ...
- ```
+ ```yaml
+ generate-config:
+ stage: build
+ script: generate-ci-config > generated-config.yml
+ artifacts:
+ paths:
+ - generated-config.yml
+ ```
- - Alternatively, setting the rule per job. For example, to create only `job1` in
- the context of merge request pipelines:
+1. Configure the trigger job to run after the job that generated the configuration file,
+ and set `include: artifact` to the generated artifact:
- ```yaml
- # child path/to/microservice_a.yml
- job1:
- script: ...
- rules:
- - if: $CI_MERGE_REQUEST_ID
+ ```yaml
+ child-pipeline:
+ stage: test
+ trigger:
+ include:
+ - artifact: generated-config.yml
+ job: generate-config
+ ```
- job2:
- script: ...
- ```
+In this example, `generated-config.yml` is extracted from the artifacts and used as the configuration
+for triggering the child pipeline.
-### Dynamic child pipelines
+The artifact path is parsed by GitLab, not the runner, so the path must match the
+syntax for the OS running GitLab. If GitLab is running on Linux but using a Windows
+runner for testing, the path separator for the trigger job is `/`. Other CI/CD
+configuration for jobs that use the Windows runner, like scripts, use `\`.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9.
+### Run child pipelines with merge request pipelines
-Instead of running a child pipeline from a static YAML file, you can define a job that runs
-your own script to generate a YAML file, which is then used to trigger a child pipeline.
+To trigger a child pipeline as a [merge request pipeline](merge_request_pipelines.md):
-This technique can be very powerful in generating pipelines targeting content that changed or to
-build a matrix of targets and architectures.
+1. Set the trigger job to run on merge requests:
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM).
+ ```yaml
+ # parent .gitlab-ci.yml
+ microservice_a:
+ trigger:
+ include: path/to/microservice_a.yml
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ ```
-We also have an example project using
-[Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet)
-which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime.
-You could use a similar process for other templating languages like
-[Dhall](https://dhall-lang.org/) or [ytt](https://get-ytt.io/).
+1. Configure the child pipeline jobs to run in merge request pipelines:
-The artifact path is parsed by GitLab, not the runner, so the path must match the
-syntax for the OS running GitLab. If GitLab is running on Linux but using a Windows
-runner for testing, the path separator for the trigger job would be `/`. Other CI/CD
-configuration for jobs, like scripts, that use the Windows runner would use `\`.
+ - With [`workflow:rules`](../yaml/index.md#workflowrules):
-For example, to trigger a child pipeline from a dynamically generated configuration file:
+ ```yaml
+ # child path/to/microservice_a.yml
+ workflow:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-```yaml
-generate-config:
- stage: build
- script: generate-ci-config > generated-config.yml
- artifacts:
- paths:
- - generated-config.yml
-
-child-pipeline:
- stage: test
- trigger:
- include:
- - artifact: generated-config.yml
- job: generate-config
-```
+ job1:
+ script: ...
-The `generated-config.yml` is extracted from the artifacts and used as the configuration
-for triggering the child pipeline.
+ job2:
+ script: ...
+ ```
-In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail.
-This is [resolved](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) in GitLab 12.10.
+ - By configuring [rules](../yaml/index.md#rules) for each job:
-### Nested child pipelines
+ ```yaml
+ # child path/to/microservice_a.yml
+ job1:
+ script: ...
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243747) in GitLab 13.5.
+ job2:
+ script: ...
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ ```
-Parent and child pipelines were introduced with a maximum depth of one level of child
-pipelines, which was later increased to two. A parent pipeline can trigger many child
-pipelines, and these child pipelines can trigger their own child pipelines. It's not
-possible to trigger another level of child pipelines.
+## Trigger a multi-project pipeline by using the API
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M).
+You can use the [CI/CD job token (`CI_JOB_TOKEN`)](../jobs/ci_job_token.md) with the
+[pipeline trigger API endpoint](../../api/pipeline_triggers.md#trigger-a-pipeline-with-a-token)
+to trigger multi-project pipelines from a CI/CD job. GitLab recognizes the source of the job token
+and marks the pipelines as related. In the pipeline graph, the relationships are displayed
+as inbound and outbound connections for upstream and downstream pipeline dependencies.
+
+For example:
+
+```yaml
+trigger_pipeline:
+ stage: deploy
+ script:
+ - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
+ rules:
+ - if: $CI_COMMIT_TAG
+ environment: production
+```
## View a downstream pipeline
+> Hover behavior for pipeline cards [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/) in GitLab 13.2.
+
In the [pipeline graph view](index.md#view-full-pipeline-graph), downstream pipelines display
-as a list of cards on the right of the graph.
+as a list of cards on the right of the graph. Hover over the pipeline's card to view
+which job triggered the downstream pipeline.
### Retry a downstream pipeline
@@ -390,9 +357,6 @@ To cancel a downstream pipeline that is still running, select **Cancel** (**{can
### Mirror the status of a downstream pipeline in the trigger job
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) in GitLab Premium 12.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
-
You can mirror the pipeline status from the triggered pipeline to the source trigger job
by using [`strategy: depend`](../yaml/index.md#triggerstrategy):
@@ -549,8 +513,9 @@ The `ENVIRONMENT` variable is passed to every job defined in a downstream
pipeline. It is available as a variable when GitLab Runner picks a job.
In the following configuration, the `MY_VARIABLE` variable is passed to the downstream pipeline
-that is created when the `trigger-downstream` job is queued. This is because `trigger-downstream`
-job inherits variables declared in global variables blocks, and then we pass these variables to a downstream pipeline.
+that is created when the `trigger-downstream` job is queued. This behavior is because `trigger-downstream`
+job inherits variables declared in [global `variables`](../yaml/index.md#variables) blocks,
+and then GitLab passes these variables to the downstream pipeline.
```yaml
variables:
@@ -562,7 +527,7 @@ trigger-downstream:
trigger: my/project
```
-### Prevent global variables from being passed
+#### Prevent global variables from being passed
You can stop global variables from reaching the downstream pipeline by using the [`inherit:variables` keyword](../yaml/index.md#inheritvariables).
For example, in a [multi-project pipeline](#multi-project-pipelines):
@@ -645,3 +610,16 @@ For example, in a [multi-project pipeline](#multi-project-pipelines):
ref: master
artifacts: true
```
+
+## Troubleshooting
+
+### Trigger job fails and does not create multi-project pipeline
+
+With multi-project pipelines, the trigger job fails and does not create the downstream pipeline if:
+
+- The downstream project is not found.
+- The user that creates the upstream pipeline does not have [permission](../../user/permissions.md)
+ to create pipelines in the downstream project.
+- The downstream pipeline targets a protected branch and the user does not have permission
+ to run pipelines against the protected branch. See [pipeline security for protected branches](index.md#pipeline-security-on-protected-branches)
+ for more information.
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index 2696d3adabd..ed0583e0872 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/ci/pipelines.html'
type: reference
---
@@ -155,26 +155,38 @@ The pipeline now executes the jobs as configured.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) in GitLab 13.7.
-You can use the [`value` and `description`](../yaml/index.md#variablesdescription)
-keywords to define
-[pipeline-level (global) variables](../variables/index.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file)
-that are prefilled when running a pipeline manually.
+You can use the [`description` and `value`](../yaml/index.md#variablesdescription)
+keywords to define [pipeline-level (global) variables](../variables/index.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file)
+that are prefilled when running a pipeline manually. Use the description to explain
+what the variable is used for, what the acceptable values are, and so on.
-In pipelines triggered manually, the **Run pipelines** page displays all top-level variables
-with a `description` and `value` defined in the `.gitlab-ci.yml` file. The values
-can then be modified if needed, which overrides the value for that single pipeline run.
+Job-level variables cannot be pre-filled.
-The description is displayed next to the variable. It can be used to explain what
-the variable is used for, what the acceptable values are, and so on:
+In manually-triggered pipelines, the **Run pipeline** page displays all pipeline-level variables
+with a `description` defined in the `.gitlab-ci.yml` file. The description displays
+below the variable.
+
+You can change the prefilled value, which overrides the value for that single pipeline run.
+If you do not define a `value` for the variable in the configuration file, the variable still displays,
+but the value field is blank.
+
+For example:
```yaml
variables:
+ TEST_SUITE:
+ description: "The test suite that will run. Valid options are: 'default', 'short', 'full'."
+ value: "default"
DEPLOY_ENVIRONMENT:
- value: "staging" # Deploy to staging by default
- description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
+ description: "Select the deployment target. Valid options are: 'canary', 'staging', 'production', or a stable branch of your choice."
```
-You cannot set job-level variables to be pre-filled when you run a pipeline manually.
+In this example:
+
+- `TEST_SUITE` is pre-filled in the **Run pipeline** page with `default`,
+ and the message explains the other options.
+- `DEPLOY_ENVIRONMENT` is listed in the **Run pipeline** page, but with no value set.
+ The user is expected to define the value each time the pipeline is run manually.
### Run a pipeline by using a URL query string
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index f30ae32efb2..33a9069240b 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/job_artifacts.html'
---
diff --git a/doc/ci/pipelines/merge_request_pipelines.md b/doc/ci/pipelines/merge_request_pipelines.md
index f6c93356046..714e96d7954 100644
--- a/doc/ci/pipelines/merge_request_pipelines.md
+++ b/doc/ci/pipelines/merge_request_pipelines.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
diff --git a/doc/ci/pipelines/merge_trains.md b/doc/ci/pipelines/merge_trains.md
index 88ab6163f3c..c501d2a7904 100644
--- a/doc/ci/pipelines/merge_trains.md
+++ b/doc/ci/pipelines/merge_trains.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge trains **(PREMIUM)**
@@ -91,7 +91,7 @@ In GitLab 13.5 and earlier, there is only one checkbox, named
**Enable merge trains and pipelines for merged results**.
WARNING:
-If you select the check box but don't configure your CI/CD to use
+If you select the checkbox but don't configure your CI/CD to use
merge request pipelines, your merge requests may become stuck in an
unresolved state or your pipelines may be dropped.
diff --git a/doc/ci/pipelines/merged_results_pipelines.md b/doc/ci/pipelines/merged_results_pipelines.md
index 7209a6b9a77..097f6bad87c 100644
--- a/doc/ci/pipelines/merged_results_pipelines.md
+++ b/doc/ci/pipelines/merged_results_pipelines.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merged results pipelines **(PREMIUM)**
@@ -33,7 +33,7 @@ To use merged results pipelines:
[run jobs in merge request pipelines](merge_request_pipelines.md#prerequisites).
- Your repository must be a GitLab repository, not an
[external repository](../ci_cd_for_external_repos/index.md).
-- You must not be using [fast forward merges](../../user/project/merge_requests/fast_forward_merge.md).
+- You must not be using [fast forward merges](../../user/project/merge_requests/methods/index.md).
[An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/26996) to change this behavior.
## Enable merged results pipelines
diff --git a/doc/ci/pipelines/multi_project_pipelines.md b/doc/ci/pipelines/multi_project_pipelines.md
index 824f1445818..25ac9e13185 100644
--- a/doc/ci/pipelines/multi_project_pipelines.md
+++ b/doc/ci/pipelines/multi_project_pipelines.md
@@ -1,11 +1,11 @@
---
redirect_to: 'downstream_pipelines.md'
-remove_date: '2022-11-31'
+remove_date: '2022-11-30'
---
This document was moved to [another location](downstream_pipelines.md).
-<!-- This redirect file can be deleted after <2022-11-31>. -->
+<!-- This redirect file can be deleted after <2022-11-30>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/ci/pipelines/pipeline_architectures.md b/doc/ci/pipelines/pipeline_architectures.md
index a02ac7ba067..e36eb24055f 100644
--- a/doc/ci/pipelines/pipeline_architectures.md
+++ b/doc/ci/pipelines/pipeline_architectures.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -10,15 +10,21 @@ type: reference
Pipelines are the fundamental building blocks for CI/CD in GitLab. This page documents
some of the important concepts related to them.
-There are three main ways to structure your pipelines, each with their
+You can structure your pipelines with different methods, each with their
own advantages. These methods can be mixed and matched if needed:
- [Basic](#basic-pipelines): Good for straightforward projects where all the configuration is in one easy to find place.
- [Directed Acyclic Graph](#directed-acyclic-graph-pipelines): Good for large, complex projects that need efficient execution.
-- [Child/Parent Pipelines](#child--parent-pipelines): Good for monorepos and projects with lots of independently defined components.
+- [Parent-child pipelines](#parent-child-pipelines): Good for monorepos and projects with lots of independently defined components.
-For more details about
-any of the keywords used below, check out our [CI YAML reference](../yaml/index.md) for details.
+ <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+ For an overview, see the [Parent-Child Pipelines feature demo](https://youtu.be/n8KpBSqZNbk).
+
+- [Multi-project pipelines](downstream_pipelines.md#multi-project-pipelines): Good for larger products that require cross-project interdependencies,
+ like those with a [microservices architecture](https://about.gitlab.com/blog/2016/08/16/trends-in-version-control-land-microservices/).
+
+ <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+ For an overview, see the [Multi-project pipelines demo](https://www.youtube.com/watch?v=g_PIwBM1J84).
## Basic Pipelines
@@ -163,12 +169,29 @@ deploy_b:
environment: production
```
-## Child / Parent Pipelines
+## Parent-child pipelines
+
+As pipelines grow more complex, a few related problems start to emerge:
+
+- The staged structure, where all steps in a stage must complete before the first
+ job in next stage begins, causes waits that slow things down.
+- Configuration for the single global pipeline becomes
+ hard to manage.
+- Imports with [`include`](../yaml/index.md#include) increase the complexity of the configuration, and can cause
+ namespace collisions where jobs are unintentionally duplicated.
+- Pipeline UX has too many jobs and stages to work with.
+
+Additionally, sometimes the behavior of a pipeline needs to be more dynamic. The ability
+to choose to start sub-pipelines (or not) is a powerful ability, especially if the
+YAML is dynamically generated.
+
+![Parent pipeline graph expanded](img/parent_pipeline_graph_expanded_v14_3.png)
-In the examples above, it's clear we've got two types of things that could be built independently.
-This is an ideal case for using [Child / Parent Pipelines](downstream_pipelines.md#parent-child-pipelines)) via
-the [`trigger` keyword](../yaml/index.md#trigger). It separates out the configuration
-into multiple files, keeping things very simple. You can also combine this with:
+In the [basic pipeline](#basic-pipelines) and [directed acyclic graph](#directed-acyclic-graph-pipelines)
+examples above, there are two packages that could be built independently.
+These cases are ideal for using [parent-child pipelines](downstream_pipelines.md#parent-child-pipelines).
+It separates out the configuration into multiple files, keeping things simpler.
+You can combine parent-child pipelines with:
- The [`rules` keyword](../yaml/index.md#rules): For example, have the child pipelines triggered only
when there are changes to that area.
diff --git a/doc/ci/pipelines/pipeline_artifacts.md b/doc/ci/pipelines/pipeline_artifacts.md
index 07e1c8a6d99..aacaa110041 100644
--- a/doc/ci/pipelines/pipeline_artifacts.md
+++ b/doc/ci/pipelines/pipeline_artifacts.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipeline artifacts **(FREE)**
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index 72711f9b9dd..aa2f074693a 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index 897caa340f9..0eeb0eada87 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/schedules.html'
type: reference, howto
---
@@ -39,6 +39,9 @@ To add a pipeline schedule:
These variables are available only when the scheduled pipeline runs,
and not in any other pipeline run.
+If the project already has the [maximum number of pipeline schedules](../../administration/instance_limits.md#number-of-pipeline-schedules),
+you must delete unused schedules before you can add another.
+
## Edit a pipeline schedule
> Introduced in GitLab 14.8, only a pipeline schedule owner can edit the schedule.
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index d663dea7de8..d7155004359 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/settings.html'
type: reference, howto
---
@@ -159,13 +159,13 @@ If the CI/CD configuration file is in a different project:
- The file must exist on its default branch, or specify the branch as refname.
- The path must be relative to the root directory in the other project.
-- The path must include the group and project name at the end.
+- The path must be followed by an `@` symbol and the full group and project path.
For example:
-- `.gitlab-ci.yml@mygroup/another-project`
-- `my/path/.my-custom-file.yml@mygroup/another-project`
-- `my/path/.my-custom-file.yml@mygroup/another-project:refname`
+- `.gitlab-ci.yml@namespace/another-project`
+- `my/path/.my-custom-file.yml@namespace/sub-group/another-project`
+- `my/path/.my-custom-file.yml@namespace/sub-group1/sub-group2/another-project:refname`
If the configuration file is in a separate project, you can set more granular permissions. For example:
@@ -329,7 +329,7 @@ you can view a graph or download a CSV file with this data.
1. On the top bar, select **Main menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Repository**.
-The historic data for each job is listed in the dropdown above the graph.
+The historic data for each job is listed in the dropdown list above the graph.
To view a CSV file of the data, select **Download raw data (`.csv`)**.
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
index 2b44cf3b898..ad41e4fa88a 100644
--- a/doc/ci/quick_start/index.md
+++ b/doc/ci/quick_start/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md
index dff52a742a8..2803ddba828 100644
--- a/doc/ci/resource_groups/index.md
+++ b/doc/ci/resource_groups/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Control the job concurrency in GitLab CI/CD
---
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 9bafb69482b..2f23ebbfd9f 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Review Apps **(FREE)**
@@ -95,9 +95,14 @@ after a given period of time.
The following are example projects that demonstrate Review App configuration:
-- [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx).
-- [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift).
-- [HashiCorp Nomad](https://gitlab.com/gitlab-examples/review-apps-nomad).
+| Project | Configuration file |
+|-------------------------------------------------------------------------|--------------------|
+| [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-nginx/-/blob/b9c1f6a8a7a0dfd9c8784cbf233c0a7b6a28ff27/.gitlab-ci.yml#L20) |
+| [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-openshift/-/blob/82ebd572334793deef2d5ddc379f38942f3488be/.gitlab-ci.yml#L42) |
+| [HashiCorp Nomad](https://gitlab.com/gitlab-examples/review-apps-nomad) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-nomad/-/blob/ca372c778be7aaed5e82d3be24e98c3f10a465af/.gitlab-ci.yml#L110) |
+| [GitLab Documentation](https://gitlab.com/gitlab-org/gitlab-docs/) | [`build-and-deploy.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/a715625496303cbd90ff89f3d3658ea8d36ce0f3/.gitlab/ci/build-and-deploy.gitlab-ci.yml#L59) |
+| [`https://about.gitlab.com/`](https://gitlab.com/gitlab-com/www-gitlab-com/) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/6ffcdc3cb9af2abed490cbe5b7417df3e83cd76c/.gitlab-ci.yml#L332) |
+| [GitLab Insights](https://gitlab.com/gitlab-org/gitlab-insights/) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-insights/-/blob/9e63f44ac2a5a4defc965d0d61d411a768e20546/.gitlab-ci.yml#L234) |
Other examples of Review Apps:
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index 9d26ec63f96..19e0c1e3c81 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configuring runners **(FREE)**
@@ -198,7 +198,7 @@ To make a runner pick untagged jobs:
1. Select **Save changes** for the changes to take effect.
NOTE:
-The runner tags list can not be empty when it's not allowed to pick untagged jobs.
+The runner tags list cannot be empty when it's not allowed to pick untagged jobs.
Below are some example scenarios of different variations.
@@ -302,6 +302,7 @@ globally or for individual jobs:
- [`GIT_CHECKOUT`](#git-checkout)
- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
+- [`GIT_SUBMODULE_PATHS`](#git-submodule-paths)
- [`GIT_SUBMODULE_UPDATE_FLAGS`](#git-submodule-update-flags)
- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
@@ -488,6 +489,32 @@ git fetch origin $REFSPECS --depth 50 --prune
Where `$REFSPECS` is a value provided to the runner internally by GitLab.
+### Git submodule paths
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/2249) in GitLab Runner 14.0.
+
+Use the `GIT_SUBMODULE_PATHS` variable to control which submodules have to be synced or updated.
+You can set it globally or per-job in the [`variables`](../yaml/index.md#variables) section.
+
+This variable can be very useful for projects which have a large number of submodules which not all of them
+need to be synced or updated in all CI jobs.
+
+The path syntax is the same as [`git submodule`](https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-ltpathgt82308203):
+
+- To sync and update specific paths:
+
+ ```yaml
+ variables:
+ GIT_SUBMODULE_PATHS: submoduleA submoduleB
+ ```
+
+- To exclude specific paths:
+
+ ```yaml
+ variables:
+ GIT_SUBMODULE_PATHS: :(exclude)submoduleA :(exclude)submoduleB
+ ```
+
### Git submodule update flags
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3192) in GitLab Runner 14.8.
@@ -915,12 +942,8 @@ To determine which runners need to be upgraded:
## Authentication token security
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30942) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `enforce_runner_token_expires_at`. 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 `enforce_runner_token_expires_at`.
-On GitLab.com, this feature is not available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30942) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `enforce_runner_token_expires_at`. Disabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/377902) in GitLab 15.5. Feature flag `enforce_runner_token_expires_at` removed.
Each runner has an [authentication token](../../api/runners.md#registration-and-authentication-tokens)
to connect with the GitLab instance.
diff --git a/doc/ci/runners/index.md b/doc/ci/runners/index.md
index 1de24efa8aa..405310fb8ba 100644
--- a/doc/ci/runners/index.md
+++ b/doc/ci/runners/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md
index f8a33ea6861..4be4ed33feb 100644
--- a/doc/ci/runners/runners_scope.md
+++ b/doc/ci/runners/runners_scope.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -172,8 +172,12 @@ To create a group runner:
1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **CI/CD > Runners**.
-1. Note the URL and token.
-1. [Register the runner](https://docs.gitlab.com/runner/register/).
+1. In the top-right corner, select **Register a group runner**.
+1. Select **Show runner installation and registration instructions**.
+ These instructions include the token, URL, and a command to register a runner.
+
+Alternately, you can copy the registration token and follow the documentation for
+how to [register a runner](https://docs.gitlab.com/runner/register/).
### View and manage group runners
@@ -188,6 +192,23 @@ You must have the Owner role for the group.
From this page, you can edit, pause, and remove runners from the group, its subgroups, and projects.
+#### Filter group runners to show only inherited
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/337838/) in GitLab 15.5.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101099) in GitLab 15.5. Feature flag `runners_finder_all_available` removed.
+
+You can choose to show all runners in the list, or show only
+those that are inherited from the instance or other groups.
+
+By default, only those that are inherited are shown.
+
+To show all runners available in the instance, including shared runners and
+those in other groups:
+
+1. On the top bar, select **Main menu > Groups** and find your group.
+1. On the left sidebar, select **CI/CD > Runners**.
+1. Above the list, turn off the **Show only inherited** toggle.
+
### Pause or remove a group runner
You can pause or remove a group runner for your self-managed GitLab instance or for GitLab.com.
diff --git a/doc/ci/runners/saas/linux_saas_runner.md b/doc/ci/runners/saas/linux_saas_runner.md
index a7d1b8722a5..d1c63ab7291 100644
--- a/doc/ci/runners/saas/linux_saas_runner.md
+++ b/doc/ci/runners/saas/linux_saas_runner.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SaaS runners on Linux
diff --git a/doc/ci/runners/saas/macos/codesigning.md b/doc/ci/runners/saas/macos/codesigning.md
index 71fdc61f0b6..697f138eec6 100644
--- a/doc/ci/runners/saas/macos/codesigning.md
+++ b/doc/ci/runners/saas/macos/codesigning.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code signing for SaaS runners on macOS
diff --git a/doc/ci/runners/saas/macos/environment.md b/doc/ci/runners/saas/macos/environment.md
index edd897e4c23..1fc7afea7e6 100644
--- a/doc/ci/runners/saas/macos/environment.md
+++ b/doc/ci/runners/saas/macos/environment.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# VM instances and images for SaaS runners on macOS **(PREMIUM SAAS)**
@@ -57,5 +57,6 @@ Each image is running a specific version of macOS and Xcode.
| `macos-10.14-xcode-10` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
| `macos-10.15-xcode-11` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
| `macos-11-xcode-12` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
-| `macos-12-xcode-13` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
+| `macos-12-xcode-13` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
+| `macos-12-xcode-14` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
| (none, awaiting macOS 13) | `beta` | |
diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md
index 5a2d84b6996..50c24349712 100644
--- a/doc/ci/runners/saas/macos_saas_runner.md
+++ b/doc/ci/runners/saas/macos_saas_runner.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SaaS runners on macOS (Beta) **(PREMIUM SAAS)**
@@ -14,10 +14,6 @@ Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS
of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
build environment.
-CI/CD minutes used on GitLab SaaS macOS runners are included in your CI/CD minute consumption totals. CI jobs that run on macOS **will** consume CI minutes at a faster rate than CI jobs on the GitLab SaaS runners on Linux.
-
-Refer to the CI/CD minutes [cost factor](../../../ci/pipelines/cicd_minutes.md#cost-factor) for the cost factor applied to the GitLab SaaS macOS runners.
-
Jobs handled by macOS shared runners on GitLab.com **time out after 2 hours**, regardless of the timeout configured in a project.
## Access request process
diff --git a/doc/ci/runners/saas/windows_saas_runner.md b/doc/ci/runners/saas/windows_saas_runner.md
index f9fe6290220..2c6540833b0 100644
--- a/doc/ci/runners/saas/windows_saas_runner.md
+++ b/doc/ci/runners/saas/windows_saas_runner.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SaaS runners on Windows (beta) **(FREE SAAS)**
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index fb91aeb6240..62350905bd4 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -56,7 +56,7 @@ 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
+ server the [JSON Web Key Set](https://www.rfc-editor.org/rfc/rfc7517) (JWKS) endpoint for your GitLab instance, so Vault
can fetch the public signing key and verify the JSON Web Token (JWT) when authenticating:
```shell
diff --git a/doc/ci/secure_files/index.md b/doc/ci/secure_files/index.md
index ff5c29cdb06..bba8a3e4c27 100644
--- a/doc/ci/secure_files/index.md
+++ b/doc/ci/secure_files/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -13,7 +13,13 @@ 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 `ci_secure_files`. Limited to 100 secure files per project. Files must be smaller
-than 5 MB. The feature is not ready for production use.
+than 5 MB. Project-level Secure Files is an experimental feature developed by [GitLab Incubation Engineering](https://about.gitlab.com/handbook/engineering/incubation/).
+
+Project-level Secure Files is still in development, but you can:
+
+- [Request a feature](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/feedback/-/issues/new?issuable_template=feature_request).
+- [Report a bug](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/feedback/-/issues/new?issuable_template=report_bug).
+- [Share feedback](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/feedback/-/issues/new?issuable_template=general_feedback).
You can securely store files for use in CI/CD pipelines as "secure files". These files
are stored securely outside of your project's repository, and are not version controlled.
diff --git a/doc/ci/services/gitlab.md b/doc/ci/services/gitlab.md
index 689ce884ae4..f2ea969f430 100644
--- a/doc/ci/services/gitlab.md
+++ b/doc/ci/services/gitlab.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 9b2bcc39b3e..0f82f2301c7 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index
---
@@ -370,8 +370,11 @@ access-service:
curlimages/curl:7.74.0 curl "http://tutum-wordpress"
```
-For this solution to work, you must use
-[the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job).
+For this solution to work, you must:
+
+- Use [the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job).
+- [Not use the Docker executor with Docker socket binding](../docker/using_docker_build.md#use-the-docker-executor-with-docker-socket-binding).
+ If you must, then in the above example, instead of `host`, use the dynamic network name created for this job.
## How Docker integration works
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index d0ac123ba62..ea11719cef1 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index c2ff4c60771..139a4a2f742 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md
index a3446fc2677..a7a28116aa4 100644
--- a/doc/ci/services/redis.md
+++ b/doc/ci/services/redis.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -69,5 +69,5 @@ We have set up an [Example Redis Project](https://gitlab.com/gitlab-examples/red
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/index.md).
-Want to hack on it? Simply fork it, commit and push your changes. Within a few
+Want to hack on it? Fork it, commit and push your changes. Within a few
moments the changes are picked by a public runner and the job begins.
diff --git a/doc/ci/ssh_keys/index.md b/doc/ci/ssh_keys/index.md
index 30b688c0b96..972e9494126 100644
--- a/doc/ci/ssh_keys/index.md
+++ b/doc/ci/ssh_keys/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
@@ -10,13 +10,13 @@ type: tutorial
GitLab currently doesn't have built-in support for managing SSH keys in a build
environment (where the GitLab Runner runs).
-Use SSH keys when:
+Use SSH keys when you want to:
-1. You want to checkout internal submodules
-1. You want to download private packages using your package manager (for example, Bundler)
-1. You want to deploy your application to your own server, or, for example, Heroku
-1. You want to execute SSH commands from the build environment to a remote server
-1. You want to rsync files from the build environment to a remote server
+- Check out internal submodules.
+- Download private packages using your package manager. For example, Bundler.
+- Deploy your application to your own server or, for example, Heroku.
+- Execute SSH commands from the build environment to a remote server.
+- Rsync files from the build environment to a remote server.
If anything of the above rings a bell, then you most likely need an SSH key.
@@ -115,9 +115,9 @@ SSH key.
You can generate the SSH key from the machine that GitLab Runner is installed
on, and use that key for all projects that are run on this machine.
-1. First, log in to the server that runs your jobs.
+1. First, sign in to the server that runs your jobs.
-1. Then, from the terminal, log in as the `gitlab-runner` user:
+1. Then, from the terminal, sign in as the `gitlab-runner` user:
```shell
sudo su - gitlab-runner
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 3ef25a4924b..8d2788539d8 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -1,7 +1,7 @@
---
stage: Plan
group: Certify
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Test cases in GitLab can help your teams create testing scenarios in their existing development platform.
type: reference
---
@@ -36,7 +36,10 @@ issue list with a search query, including labels or the test case's title.
Prerequisite:
-- You must have at least the Guest role.
+Whether you can view an test case depends on the [project visibility level](../../user/public_access.md):
+
+- Public project: You don't have to be a member of the project.
+- Private project: You must have at least the Guest role for the project.
To view a test case:
diff --git a/doc/ci/testing/accessibility_testing.md b/doc/ci/testing/accessibility_testing.md
index 7940b27acf7..fa57371a7d5 100644
--- a/doc/ci/testing/accessibility_testing.md
+++ b/doc/ci/testing/accessibility_testing.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Accessibility testing **(FREE)**
diff --git a/doc/ci/testing/browser_performance_testing.md b/doc/ci/testing/browser_performance_testing.md
index 260ecf6108d..ff013f0037e 100644
--- a/doc/ci/testing/browser_performance_testing.md
+++ b/doc/ci/testing/browser_performance_testing.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Browser Performance Testing **(PREMIUM)**
diff --git a/doc/ci/testing/code_quality.md b/doc/ci/testing/code_quality.md
index 401279b9601..7345c7ca5eb 100644
--- a/doc/ci/testing/code_quality.md
+++ b/doc/ci/testing/code_quality.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code Quality **(FREE)**
@@ -313,7 +313,7 @@ the nested architecture of container execution, the registry prefix must
be specifically configured to be passed down into CodeClimate's subsequent
`docker pull` commands for individual engines.
-The following two variables can address all of the required image pulls:
+The following variables can address all of the required image pulls:
- `CODE_QUALITY_IMAGE`: A fully prefixed image name that can be located anywhere
accessible from your job environment. GitLab Container Registry can be used here
@@ -322,6 +322,8 @@ The following two variables can address all of the required image pulls:
is a configuration option supported by [CodeClimate CLI](https://github.com/codeclimate/codeclimate/pull/948). You must:
- Include a trailing slash (`/`).
- Not include a protocol prefix, such as `https://`.
+- `CODECLIMATE_REGISTRY_USERNAME`: An optional variable to specify the username for the registry domain parsed from `CODECLIMATE_PREFIX`.
+- `CODECLIMATE_REGISTRY_PASSWORD`: An optional variable to specify the password for the registry domain parsed from `CODECLIMATE_PREFIX`.
```yaml
include:
@@ -333,13 +335,49 @@ code_quality:
CODECLIMATE_PREFIX: "my-private-registry.local:12345/"
```
-The images in the private container image registry must be available without authentication.
-Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/355814) for more information.
-
This example is specific to GitLab Code Quality. For more general
instructions on how to configure DinD with a registry mirror, see the
relevant [documentation](../docker/using_docker_build.md#enable-registry-mirror-for-dockerdind-service).
+#### Configure Code Quality to use the Dependency Proxy
+
+Prerequisite:
+
+- The project must be in a group where the [Dependency Proxy](../../user/packages/dependency_proxy/index.md) is enabled.
+
+Here is an example of how to configure Code Quality to use the Dependency Proxy:
+
+```yaml
+include:
+ - template: Jobs/Code-Quality.gitlab-ci.yml
+
+code_quality:
+ variables:
+ CODE_QUALITY_IMAGE: "$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/codequality:0.85.24"
+ ## You must add a trailing slash to `$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`.
+ CODECLIMATE_PREFIX: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/
+ CODECLIMATE_REGISTRY_USERNAME: $CI_DEPENDENCY_PROXY_USER
+ CODECLIMATE_REGISTRY_PASSWORD: $CI_DEPENDENCY_PROXY_PASSWORD
+```
+
+#### Configure Code Quality to use Dockerhub with authentication
+
+Here is an example of how to configure Code Quality to use Dockerhub with authentication:
+
+```yaml
+include:
+ - template: Jobs/Code-Quality.gitlab-ci.yml
+
+code_quality:
+ variables:
+ CODECLIMATE_PREFIX: "registry-1.docker.io/"
+ CODECLIMATE_REGISTRY_USERNAME: $DOCKERHUB_USERNAME
+ CODECLIMATE_REGISTRY_PASSWORD: $DOCKERHUB_PASSWORD
+```
+
+You should add the username and password as [protected CI/CD variables](../variables/index.md#add-a-cicd-variable-to-a-project)
+in the project.
+
## Configuring jobs using variables
The Code Quality job supports environment variables that users can set to
diff --git a/doc/ci/testing/fail_fast_testing.md b/doc/ci/testing/fail_fast_testing.md
index 7b95b1ac54a..58471a626da 100644
--- a/doc/ci/testing/fail_fast_testing.md
+++ b/doc/ci/testing/fail_fast_testing.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Fail Fast Testing **(PREMIUM)**
diff --git a/doc/ci/testing/index.md b/doc/ci/testing/index.md
index a8f06ec695c..41d474f0e60 100644
--- a/doc/ci/testing/index.md
+++ b/doc/ci/testing/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Test with GitLab CI/CD and generate reports in merge requests **(FREE)**
diff --git a/doc/ci/testing/load_performance_testing.md b/doc/ci/testing/load_performance_testing.md
index e15b3944c2b..6e1b440f252 100644
--- a/doc/ci/testing/load_performance_testing.md
+++ b/doc/ci/testing/load_performance_testing.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Load Performance Testing **(PREMIUM)**
diff --git a/doc/ci/testing/metrics_reports.md b/doc/ci/testing/metrics_reports.md
index e855074ddea..e084e4d3bc7 100644
--- a/doc/ci/testing/metrics_reports.md
+++ b/doc/ci/testing/metrics_reports.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Metrics Reports **(PREMIUM)**
diff --git a/doc/ci/testing/test_coverage_visualization.md b/doc/ci/testing/test_coverage_visualization.md
index 472cfca99be..ee6b47e69a5 100644
--- a/doc/ci/testing/test_coverage_visualization.md
+++ b/doc/ci/testing/test_coverage_visualization.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Test coverage visualization **(FREE)**
diff --git a/doc/ci/testing/unit_test_report_examples.md b/doc/ci/testing/unit_test_report_examples.md
index b49ac29be65..c14e4eedd7c 100644
--- a/doc/ci/testing/unit_test_report_examples.md
+++ b/doc/ci/testing/unit_test_report_examples.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Unit test report examples **(FREE)**
@@ -183,7 +183,11 @@ the `javascript` job uses Jest to generate the test reports:
```yaml
javascript:
+ image: node:latest
stage: test
+ before_script:
+ - 'yarn global add jest'
+ - 'yarn add --dev jest-junit'
script:
- 'jest --ci --reporters=default --reporters=jest-junit'
artifacts:
@@ -193,6 +197,9 @@ javascript:
- junit.xml
```
+To make the job pass when there are no `.test.js` files with unit tests, add the
+`--passWithNoTests` flag to the end of the `jest` command in the `script:` section.
+
### Karma
The [Karma-junit-reporter](https://github.com/karma-runner/karma-junit-reporter)
diff --git a/doc/ci/testing/unit_test_reports.md b/doc/ci/testing/unit_test_reports.md
index 28356a62c99..0fe9b2b6d64 100644
--- a/doc/ci/testing/unit_test_reports.md
+++ b/doc/ci/testing/unit_test_reports.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Unit test reports **(FREE)**
diff --git a/doc/ci/triggers/index.md b/doc/ci/triggers/index.md
index 36d136727b0..cafa64c4832 100644
--- a/doc/ci/triggers/index.md
+++ b/doc/ci/triggers/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: tutorial
---
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 8a03ec0b56f..8f78469af18 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
deleted file mode 100644
index 7578a1e6009..00000000000
--- a/doc/ci/unit_test_reports.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'testing/unit_test_reports.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](testing/unit_test_reports.md).
-
-<!-- This redirect file can be deleted after <2022-08-31>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index 25178903c9a..7ad42aaf96b 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -193,7 +193,7 @@ The output is:
> Support for environment scopes [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2874) in GitLab Premium 13.11
-To make a CI/CD variable available to all projects in a group, define a group CI/CD variable.
+To make a CI/CD variable available to all projects in a group, define a group CI/CD variable. Only group owners can add or update group-level CI/CD variables.
Use group variables to store secrets like passwords, SSH keys, and credentials, if you:
@@ -682,7 +682,10 @@ The order of precedence for variables is (from highest to lowest):
- [Manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
- Variables added when [creating a pipeline with the API](../../api/pipelines.md#create-a-new-pipeline).
1. Project [variables](#custom-cicd-variables).
-1. Group [variables](#add-a-cicd-variable-to-a-group).
+1. Group [variables](#add-a-cicd-variable-to-a-group). If the same variable name exists in a
+ group and its subgroups, the job uses the value from the closest subgroup. For example, if
+ you have `Group > Subgroup 1 > Subgroup 2 > Project`, the variable defined in
+ `Subgroup 2` takes precedence.
1. Instance [variables](#add-a-cicd-variable-to-an-instance).
1. [Inherited variables](#pass-an-environment-variable-to-another-job).
1. Variables defined in jobs in the `.gitlab-ci.yml` file.
@@ -768,7 +771,7 @@ for [deployment jobs](../environments/index.md).
For example, the [Kubernetes integration](../../user/project/clusters/deploy_to_cluster.md#deployment-variables)
defines deployment variables that you can use with the integration.
-The [documentation for each integration](../../user/project/integrations/overview.md)
+The [documentation for each integration](../../user/project/integrations/index.md)
explains if the integration has any deployment variables available.
## Auto DevOps environment variables
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 77005e1cec4..606847ee756 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -39,6 +39,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_COMMIT_SHA` | 9.0 | all | The commit revision the project is built for. |
| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA`. |
| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Available only in pipelines for tags. |
+| `CI_COMMIT_TAG_MESSAGE` | 15.5 | all | The commit tag message. Available only in pipelines for tags. |
| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. |
| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit. The full first line of the message. |
| `CI_CONCURRENT_ID` | all | 11.10 | The unique ID of build execution in a single executor. |
@@ -60,6 +61,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Available if [`environment:url`](../yaml/index.md#environmenturl) is set. |
| `CI_ENVIRONMENT_ACTION` | 13.11 | all | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/index.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. |
| `CI_ENVIRONMENT_TIER` | 14.0 | all | The [deployment tier of the environment](../environments/index.md#deployment-tier-of-environments) for this job. |
+| `CI_RELEASE_DESCRIPTION` | 15.5 | all | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters.|
| `CI_GITLAB_FIPS_MODE` | 14.10 | all | The configuration setting for whether FIPS mode is enabled in the GitLab instance. |
| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/index.md). `true` when available. |
| `CI_JOB_ID` | 9.0 | all | The internal ID of the job, unique across all jobs in the GitLab instance. |
@@ -69,11 +71,12 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_JOB_JWT_V2` | 14.6 | all | A newly formatted RS256 JSON web token to increase compatibility. Similar to `CI_JOB_JWT`, except the issuer (`iss`) claim is changed from `gitlab.com` to `https://gitlab.com`, `sub` has changed from `job_id` to a string that contains the project path, and an `aud` claim is added. Format is subject to change. Be aware, the `aud` field is a constant value. Trusting JWTs in multiple relying parties can lead to [one RP sending a JWT to another one and acting maliciously as a job](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72555#note_769112331). **Note:** The `CI_JOB_JWT_V2` variable is available for testing, but the full feature is planned to be generally available when [issue 360657](https://gitlab.com/gitlab-org/gitlab/-/issues/360657) is complete.|
| `CI_JOB_MANUAL` | 8.12 | all | Only available if the job was started manually. `true` when available. |
| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job. |
+| `CI_JOB_NAME_SLUG` | 15.4 | all | `CI_JOB_NAME_SLUG` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in paths. |
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the job's stage. |
| `CI_JOB_STATUS` | all | 13.5 | The status of the job as each runner stage is executed. Use with [`after_script`](../yaml/index.md#after_script). Can be `success`, `failed`, or `canceled`. |
| `CI_JOB_TOKEN` | 9.0 | 1.2 | A token to authenticate with [certain API endpoints](../jobs/ci_job_token.md). The token is valid as long as the job is running. |
| `CI_JOB_URL` | 11.1 | 0.5 | The job details URL. |
-| `CI_JOB_STARTED_AT` | 13.10 | all | The UTC datetime when a job started, in [ISO 8601](https://tools.ietf.org/html/rfc3339#appendix-A) format. |
+| `CI_JOB_STARTED_AT` | 13.10 | all | The UTC datetime when a job started, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. |
| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Only available if the pipeline has a Kubernetes cluster available for deployments. `true` when available. |
| `CI_NODE_INDEX` | 11.5 | all | The index of the job in the job set. Only available if the job uses [`parallel`](../yaml/index.md#parallel). |
| `CI_NODE_TOTAL` | 11.5 | all | The total number of instances of this job running in parallel. Set to `1` if the job does not use [`parallel`](../yaml/index.md#parallel). |
@@ -85,7 +88,7 @@ as it can cause the pipeline to behave unexpectedly.
| `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). For a description of each value, see [Common `if` clauses for `rules`](../jobs/job_control.md#common-if-clauses-for-rules), which uses this variable to control when jobs run. |
| `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. |
+| `CI_PIPELINE_CREATED_AT` | 13.10 | all | The UTC datetime when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. |
| `CI_PROJECT_CONFIG_PATH` | 13.8 to 13.12 | all | [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/322807) in GitLab 14.0. Use `CI_CONFIG_PATH`. |
| `CI_PROJECT_DIR` | all | all | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_PROJECT_ID` | all | all | The ID of the current project. This ID is unique across all projects on the GitLab instance. |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 6c1737f7c65..7e5451658f2 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/yaml/artifacts_reports.md b/doc/ci/yaml/artifacts_reports.md
index 56a9da7cb84..67cbe989f74 100644
--- a/doc/ci/yaml/artifacts_reports.md
+++ b/doc/ci/yaml/artifacts_reports.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab CI/CD artifacts reports types **(FREE)**
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index f3773fbf143..7b4834b3719 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index 5158f80ea64..2b9f42e1c75 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 8aa3ebd4759..e06abe1dc69 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -379,7 +379,7 @@ start. Jobs in the current stage are not stopped and continue to run.
- 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):
+ which can help [compliance pipeline configurations](../../user/group/manage.md#configure-a-compliance-pipeline):
- 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.
@@ -398,6 +398,30 @@ Use [`workflow`](workflow.md) to control pipeline behavior.
- [`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:name`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/372538) in GitLab 15.5 [with a flag](../../administration/feature_flags.md) named `pipeline_name`. 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 `pipeline_name`.
+The feature is not ready for production use.
+
+You can use `name` in `workflow:` to define a name for pipelines.
+
+All pipelines are assigned the defined name. Any leading or trailing spaces in the name are removed.
+
+**Possible inputs**:
+
+- A string.
+
+**Example of `workflow:name`**:
+
+```yaml
+workflow:
+ name: 'Pipeline name'
+```
+
#### `workflow:rules`
The `rules` keyword in `workflow` is similar to [`rules` defined in jobs](#rules),
@@ -1238,7 +1262,11 @@ is not found, the prefix is added to `default`, so the key in the example would
#### `cache:untracked`
-Use `untracked: true` to cache all files that are untracked in your Git repository:
+Use `untracked: true` to cache all files that are untracked in your Git repository.
+Untracked files include files that are:
+
+- Ignored due to [`.gitignore` configuration](https://git-scm.com/docs/gitignore).
+- Created, but not added to the checkout with [`git add`](https://git-scm.com/docs/git-add).
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
@@ -1259,7 +1287,7 @@ rspec:
**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:
+ as well as files in the configured paths. This is useful for including files that are not tracked because of a `.gitignore` configuration. For example:
```yaml
rspec:
@@ -2161,7 +2189,7 @@ This example creates four paths of execution:
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.
+ a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create. In GitLab 13.10 and later, use the [`needs:optional`](#needsoptional) keyword to resolve a failed pipeline creation.
#### `needs:artifacts`
@@ -3260,8 +3288,19 @@ branch or merge request pipelines.
**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).
-- Alternatively, the array of file paths can be in [`rules:changes:paths`](#ruleschangespaths).
+An array including any number of:
+
+- Paths to files. In GitLab 13.6 and later, [file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
+ A file path array can also be in [`rules:changes:paths`](#ruleschangespaths).
+- Wildcard paths for:
+ - Single directories, for example `path/to/directory/*`.
+ - 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}`.
+ See the [Ruby `fnmatch` documentation](https://docs.ruby-lang.org/en/master/File.html#method-c-fnmatch)
+ for the supported syntax list.
+- Wildcard paths to files in the root directory, or all directories, wrapped in double quotes.
+ For example `"*.json"` or `"**/*.json"`.
**Example of `rules:changes`**:
@@ -3332,7 +3371,8 @@ In this example, both jobs have the same behavior.
##### `rules:changes:compare_to`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293645) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `ci_rules_changes_compare`. Enabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293645) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `ci_rules_changes_compare`. Enabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/366412) in GitLab 15.5. Feature flag `ci_rules_changes_compare` removed.
Use `rules:changes:compare_to` to specify which ref to compare against for changes to the files
listed under [`rules:changes:paths`](#ruleschangespaths).
@@ -3938,7 +3978,7 @@ trigger-multi-project-pipeline:
**Related topics**:
-- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-from-a-job-in-your-gitlab-ciyml-file).
+- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-downstream-pipeline-from-a-job-in-the-gitlab-ciyml-file).
- 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.
@@ -3966,7 +4006,7 @@ trigger-child-pipeline:
**Related topics**:
-- [Child pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-parent-child-pipeline).
+- [Child pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-downstream-pipeline-from-a-job-in-the-gitlab-ciyml-file).
#### `trigger:project`
@@ -4002,7 +4042,7 @@ trigger-multi-project-pipeline:
**Related topics**:
-- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-from-a-job-in-your-gitlab-ciyml-file).
+- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-downstream-pipeline-from-a-job-in-the-gitlab-ciyml-file).
- To run a pipeline for a specific branch, tag, or commit, you can also 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.
@@ -4160,9 +4200,9 @@ deploy_review_job:
Use the `description` keyword to define a [pipeline-level (global) variable that is prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
-Must be used with `value`, for the variable value.
+If used with `value`, the variable value is also prefilled when running a pipeline manually.
-**Keyword type**: Global keyword. You cannot set job-level variables to be pre-filled when you run a pipeline manually.
+**Keyword type**: Global keyword. You cannot use it for job-level variables.
**Possible inputs**:
@@ -4173,10 +4213,15 @@ Must be used with `value`, for the variable value.
```yaml
variables:
DEPLOY_ENVIRONMENT:
- value: "staging"
description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
+ value: "staging"
```
+**Additional details**:
+
+- A global variable defined with `value` but no `description` behaves the same as
+ [`variables`](#variables).
+
### `when`
Use `when` to configure the conditions for when jobs run. If not defined in a job,
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index bd8d7f02a17..1d3186a4047 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Format scripts and job logs **(FREE)**
diff --git a/doc/ci/yaml/workflow.md b/doc/ci/yaml/workflow.md
index d3e815c742d..3d6314c8e03 100644
--- a/doc/ci/yaml/workflow.md
+++ b/doc/ci/yaml/workflow.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab CI/CD `workflow` keyword **(FREE)**
diff --git a/doc/ci/yaml/yaml_optimization.md b/doc/ci/yaml/yaml_optimization.md
index e5d9e011230..f4774619713 100644
--- a/doc/ci/yaml/yaml_optimization.md
+++ b/doc/ci/yaml/yaml_optimization.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -220,7 +220,7 @@ multiple jobs. It is similar to [YAML anchors](#anchors), but simpler and you ca
[use `extends` with `includes`](#use-extends-and-include-together).
`extends` supports multi-level inheritance. You should avoid using more than three levels,
-but you can use as many as eleven. The following example has two levels of inheritance:
+due to the additional complexity, but you can use as many as eleven. The following example has two levels of inheritance:
```yaml
.tests:
diff --git a/doc/cloud_seed/index.md b/doc/cloud_seed/index.md
index 4c56b6c4aaa..bf51da88cb4 100644
--- a/doc/cloud_seed/index.md
+++ b/doc/cloud_seed/index.md
@@ -4,17 +4,15 @@ group: Incubation
info: Cloud Seed (formerly 5mp) is a GitLab Incubation Engineering program. No technical writer assigned to this group.
---
-# Cloud Seed
+# Cloud Seed **(FREE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371332) in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `google_cloud`. Disabled by default.
+> - [Enabled on self-managed and GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100545) in GitLab 15.5.
Cloud Seed is an open-source program led
by [GitLab Incubation Engineering](https://about.gitlab.com/handbook/engineering/incubation/) in collaboration with
[Google Cloud](https://cloud.google.com/).
-Cloud Seed is in `private-testing` mode and is available to a select group of users. If you are interested in joining
-this group, please fill in
-the [Cloud Seed Trusted Testers invitation form](https://docs.google.com/forms/d/e/1FAIpQLSeJPtFE8Vpqs_YTAKkFK42p5mO9zIYA2jr_PiP2h32cs8R39Q/viewform)
-and we will reach out to you.
-
## Purpose
We believe that it should be **trivial** to deploy web applications (and other workloads) from GitLab to major cloud
diff --git a/doc/development/adding_service_component.md b/doc/development/adding_service_component.md
index c00d9da5d16..0048b10c9da 100644
--- a/doc/development/adding_service_component.md
+++ b/doc/development/adding_service_component.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Adding a new Service Component to GitLab
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 673ec692bf4..d3053a1ca5f 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL API style guide
@@ -436,7 +436,7 @@ By default, fields add `1` to a query's complexity score. This can be overridden
[providing a custom `complexity`](https://graphql-ruby.org/queries/complexity_and_depth.html) value for a field.
Developers should specify higher complexity for fields that cause more _work_ to be performed
-by the server in order to return data. Fields that represent data that can be returned
+by the server to return data. Fields that represent data that can be returned
with little-to-no _work_, for example in most cases; `id` or `title`, can be given a complexity of `0`.
### `calls_gitaly`
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 7f7d78bb58e..f74ed8db50f 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# API style guide
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index ceb3c124d1a..edf159a116a 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application limits development
diff --git a/doc/development/application_secrets.md b/doc/development/application_secrets.md
index 93e43856b34..526cc6c3f61 100644
--- a/doc/development/application_secrets.md
+++ b/doc/development/application_secrets.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application secrets
diff --git a/doc/development/application_slis/index.md b/doc/development/application_slis/index.md
index cb2eb9b8d90..75dd066680e 100644
--- a/doc/development/application_slis/index.md
+++ b/doc/development/application_slis/index.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Application Service Level Indicators (SLIs)
@@ -26,6 +26,8 @@ to be emitted from the rails application:
1. [`rails_request_apdex`](rails_request_apdex.md)
1. `global_search_apdex`
+1. `global_search_error_rate`
+1. `global_search_indexing_apdex`
## Defining a new SLI
diff --git a/doc/development/application_slis/rails_request_apdex.md b/doc/development/application_slis/rails_request_apdex.md
index 033bffbf608..2fa9f5f4869 100644
--- a/doc/development/application_slis/rails_request_apdex.md
+++ b/doc/development/application_slis/rails_request_apdex.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rails request Apdex SLI
diff --git a/doc/development/approval_rules.md b/doc/development/approval_rules.md
index 922a0cd46a2..ce774b1e8f9 100644
--- a/doc/development/approval_rules.md
+++ b/doc/development/approval_rules.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Approval Rules development guide **(FREE)**
diff --git a/doc/development/appsec/index.md b/doc/development/appsec/index.md
deleted file mode 100644
index 8361170c3d2..00000000000
--- a/doc/development/appsec/index.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../index.md'
-remove_date: '2022-09-23'
----
-
-This document was moved to [another location](../index.md).
-
-<!-- This redirect file can be deleted after <2022-09-23>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index a813072a976..a731e661a80 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab architecture overview
diff --git a/doc/development/audit_event_guide/index.md b/doc/development/audit_event_guide/index.md
index 50d7eeed107..5c8938aa46a 100644
--- a/doc/development/audit_event_guide/index.md
+++ b/doc/development/audit_event_guide/index.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Audit Event Guide
@@ -19,7 +19,7 @@ actions performed across the application.
While any events could trigger an Audit Event, not all events should. In general, events that are not good candidates for audit events are:
- Not attributable to one specific user.
-- Not of specific interest to an admin or owner persona.
+- Not of specific interest to an administrator or owner persona.
- Are tracking information for product feature adoption.
- Are covered in the direction page's discussion on [what is not planned](https://about.gitlab.com/direction/manage/compliance/audit-events/#what-is-not-planned-right-now).
diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md
index b9b8770207e..7a684f64d64 100644
--- a/doc/development/auto_devops.md
+++ b/doc/development/auto_devops.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Auto DevOps development guide **(FREE)**
diff --git a/doc/development/avoiding_downtime_in_migrations.md b/doc/development/avoiding_downtime_in_migrations.md
deleted file mode 100644
index d4c225b62c5..00000000000
--- a/doc/development/avoiding_downtime_in_migrations.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'database/avoiding_downtime_in_migrations.md'
-remove_date: '2022-07-08'
----
-
-This document was moved to [another location](database/avoiding_downtime_in_migrations.md).
-
-<!-- This redirect file can be deleted after <2022-07-08>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/backend/create_source_code_be/gitaly_touch_points.md b/doc/development/backend/create_source_code_be/gitaly_touch_points.md
index 5ac362e709f..6ee2c7f0e51 100644
--- a/doc/development/backend/create_source_code_be/gitaly_touch_points.md
+++ b/doc/development/backend/create_source_code_be/gitaly_touch_points.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Source Code - Gitaly Touch Points
diff --git a/doc/development/backend/create_source_code_be/index.md b/doc/development/backend/create_source_code_be/index.md
index a1322b3fa25..8a1a541fac9 100644
--- a/doc/development/backend/create_source_code_be/index.md
+++ b/doc/development/backend/create_source_code_be/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create: Source Code Backend
diff --git a/doc/development/backend/create_source_code_be/rest_endpoints.md b/doc/development/backend/create_source_code_be/rest_endpoints.md
index dd43bb914c9..2130d76d014 100644
--- a/doc/development/backend/create_source_code_be/rest_endpoints.md
+++ b/doc/development/backend/create_source_code_be/rest_endpoints.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Source Code REST endpoints
diff --git a/doc/development/backend/ruby_style_guide.md b/doc/development/backend/ruby_style_guide.md
index 6ba5b8dd2c5..9b5a68e4292 100644
--- a/doc/development/backend/ruby_style_guide.md
+++ b/doc/development/backend/ruby_style_guide.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ruby style guide
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
deleted file mode 100644
index 3c9c34bccf8..00000000000
--- a/doc/development/background_migrations.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'database/background_migrations.md'
-remove_date: '2022-07-08'
----
-
-This document was moved to [another location](database/background_migrations.md).
-
-<!-- This redirect file can be deleted after <2022-07-08>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/batched_background_migrations.md b/doc/development/batched_background_migrations.md
deleted file mode 100644
index f5f3655944b..00000000000
--- a/doc/development/batched_background_migrations.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'database/batched_background_migrations.md'
-remove_date: '2022-07-26'
----
-
-This document was moved to [another location](database/batched_background_migrations.md).
-
-<!-- This redirect file can be deleted after <2022-07-26>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md
index 97dd24fc522..70aa328bf8a 100644
--- a/doc/development/build_test_package.md
+++ b/doc/development/build_test_package.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Building a package for testing
diff --git a/doc/development/bulk_import.md b/doc/development/bulk_import.md
index a2620faed35..92236594f8e 100644
--- a/doc/development/bulk_import.md
+++ b/doc/development/bulk_import.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Group Migration
diff --git a/doc/development/cached_queries.md b/doc/development/cached_queries.md
index 7af4c302e93..fbb857106be 100644
--- a/doc/development/cached_queries.md
+++ b/doc/development/cached_queries.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Application Performance
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cached queries guidelines
diff --git a/doc/development/caching.md b/doc/development/caching.md
index 5ae6484436e..36fbfc7010e 100644
--- a/doc/development/caching.md
+++ b/doc/development/caching.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Caching guidelines
diff --git a/doc/development/cascading_settings.md b/doc/development/cascading_settings.md
index 56699ff5ffc..22f146c3f5a 100644
--- a/doc/development/cascading_settings.md
+++ b/doc/development/cascading_settings.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cascading Settings
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index c0296a6d75e..7dc3ae0a80b 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Changelog entries
@@ -114,7 +114,7 @@ making it both concise and descriptive, err on the side of descriptive.
- **Bad:** Go to a project order.
- **Good:** Show a user's starred projects at the top of the "Go to project"
- dropdown.
+ dropdown list.
The first example provides no context of where the change was made, or why, or
how it benefits the user.
@@ -126,9 +126,9 @@ how it benefits the user.
Again, the first example is too vague and provides no context.
- **Bad:** Fixes and Improves CSS and HTML problems in mini pipeline graph and
- builds dropdown.
+ builds dropdown list.
- **Good:** Fix tooltips and hover states in mini pipeline graph and builds
- dropdown.
+ dropdown list.
The first example is too focused on implementation details. The user doesn't
care that we changed CSS and HTML, they care about the _end result_ of those
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index 838235fd795..008c3700253 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Generating chaos in a test GitLab instance
@@ -77,7 +77,7 @@ curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10&token=s
## CPU spin
-This endpoint attempts to fully utilise a single core, at 100%, for the given period.
+This endpoint attempts to fully use a single core, at 100%, for the given period.
Depending on your rack server setup, your request may timeout after a predetermined period (normally 60 seconds).
@@ -100,7 +100,7 @@ curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60&token=secret"
## DB spin
-This endpoint attempts to fully utilise a single core, and interleave it with DB request, for the given period.
+This endpoint attempts to fully use a single core, and interleave it with DB request, for the given period.
This endpoint can be used to model yielding execution to another threads when running concurrently.
Depending on your rack server setup, your request may timeout after a predetermined period (normally 60 seconds).
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index 7309b92c702..16dc17dd229 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# ChatOps on GitLab.com
diff --git a/doc/development/cicd/cicd_reference_documentation_guide.md b/doc/development/cicd/cicd_reference_documentation_guide.md
index 0da1717f53c..8c75e66c33a 100644
--- a/doc/development/cicd/cicd_reference_documentation_guide.md
+++ b/doc/development/cicd/cicd_reference_documentation_guide.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Documenting the `.gitlab-ci.yml` keywords **(FREE)**
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index 7a2dfa01d1e..cd31038ddd1 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, concepts, howto
---
@@ -96,6 +96,9 @@ when transitioning to the `pending` state. This job is responsible for creating
a multi-project or child pipeline. The workflow loop starts again
from the `CreatePipelineService` every time a downstream pipeline is triggered.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+You can watch a walkthrough of the architecture in [CI Backend Architectural Walkthrough](https://www.youtube.com/watch?v=ew4BwohS5OY).
+
## Job scheduling
When a Pipeline is created all its jobs are created at once for all stages, with an initial state of `created`. This makes it possible to visualize the full content of a pipeline.
diff --git a/doc/development/cicd/pipeline_wizard.md b/doc/development/cicd/pipeline_wizard.md
index 227a49d85db..eb6d1c60bb1 100644
--- a/doc/development/cicd/pipeline_wizard.md
+++ b/doc/development/cicd/pipeline_wizard.md
@@ -1,7 +1,7 @@
---
stage: none
group: Incubation Engineering
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipeline Wizard
diff --git a/doc/development/cicd/schema.md b/doc/development/cicd/schema.md
index ee5b5e4359a..22896594443 100644
--- a/doc/development/cicd/schema.md
+++ b/doc/development/cicd/schema.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, howto
---
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index d0c56fb18bc..85ac58e749d 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -1,13 +1,13 @@
---
stage: Verify
group: Pipeline Authoring
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, concepts, howto
---
# Development guide for GitLab CI/CD templates **(FREE)**
-This document explains how to develop [GitLab CI/CD templates](../../ci/examples/index.md).
+This document explains how to develop [GitLab CI/CD templates](../../ci/examples/index.md#cicd-templates).
## Requirements for CI/CD templates
@@ -391,7 +391,7 @@ This is useful information for reviewers to make sure the template is safe to be
### Make sure the new template can be selected in UI
Templates located under some directories are also [selectable in the **New file** UI](#template-directories).
-When you add a template into one of those directories, make sure that it correctly appears in the dropdown:
+When you add a template into one of those directories, make sure that it correctly appears in the dropdown list:
![CI/CD template selection](img/ci_template_selection_v13_1.png)
diff --git a/doc/development/code_comments.md b/doc/development/code_comments.md
index b1db781b9ee..306f371f306 100644
--- a/doc/development/code_comments.md
+++ b/doc/development/code_comments.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code comments
diff --git a/doc/development/code_intelligence/index.md b/doc/development/code_intelligence/index.md
index 87697a5e252..f8fb794053d 100644
--- a/doc/development/code_intelligence/index.md
+++ b/doc/development/code_intelligence/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code Intelligence **(FREE)**
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index c320540401f..5b745f06d22 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code Review Guidelines
@@ -57,7 +57,7 @@ We make the following assumption with regards to automatically being considered
- Team members working on a specific feature (for example, search) are considered domain experts for that feature.
We default to assigning reviews to team members with domain expertise.
-When a suitable [domain expert](#domain-experts) isn't available, you can choose any team member to review the MR, or simply follow the [Reviewer roulette](#reviewer-roulette) recommendation.
+When a suitable [domain expert](#domain-experts) isn't available, you can choose any team member to review the MR, or follow the [Reviewer roulette](#reviewer-roulette) recommendation.
To find a domain expert:
@@ -75,9 +75,9 @@ NOTE:
Reviewer roulette is an internal tool for use on GitLab.com, and not available for use on customer installations.
The [Danger bot](dangerbot.md) randomly picks a reviewer and a maintainer for
-each area of the codebase that your merge request seems to touch. It only makes
-**recommendations** and you should override it if you think someone else is a better
-fit!
+each area of the codebase that your merge request seems to touch. It makes
+**recommendations** for developer reviewers and you should override it if you think someone else is a better
+fit. User-facing changes are required to have a UX review, too. Default to the recommended UX reviewer suggested.
It picks reviewers and maintainers from the list at the
[engineering projects](https://about.gitlab.com/handbook/engineering/projects/)
@@ -149,7 +149,7 @@ with [domain expertise](#domain-experts).
| `~UX` user-facing changes (*3*) | [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX). Refer to the [design and user interface guidelines](contributing/design.md) for details. |
| Adding a new JavaScript library (*1*) | - [Frontend foundations member](https://about.gitlab.com/direction/ecosystem/foundations/) if the library significantly increases the [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md).<br/>- A [legal department member](https://about.gitlab.com/handbook/legal/) if the license used by the new library hasn't been approved for use in GitLab.<br/><br/>More information about license compatibility can be found in our [GitLab Licensing and Compatibility documentation](licensing.md). |
| A new dependency or a file system change | - [Distribution team member](https://about.gitlab.com/company/team/). See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution) for more details.<br/>- For Rubygems, request an [AppSec review](gemfile.md#request-an-appsec-review). |
-| `~documentation` changes | [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
+| `~documentation` or `~UI text` changes | [Technical writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
| Changes to development guidelines | Follow the [review process](development_processes.md#development-guidelines-review) and get the approvals accordingly. |
| End-to-end **and** non-end-to-end changes (*4*) | [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors). |
| Only End-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa). |
@@ -208,7 +208,7 @@ See the [test engineering process](https://about.gitlab.com/handbook/engineering
1. I have included changelog trailers, or I have decided that they are not needed.
- [Does this MR need a changelog?](changelog.md#what-warrants-a-changelog-entry)
1. I have added/updated documentation or decided that documentation changes are unnecessary for this MR.
- - [Is documentation required?](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#when-documentation-is-required)
+ - [Is documentation required?](https://about.gitlab.com/handbook/product/ux/technical-writing/workflow/#when-documentation-is-required)
##### Security
@@ -442,8 +442,7 @@ first time.
### Requesting a review
When you are ready to have your merge request reviewed,
-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 should [request an initial review](../user/project/merge_requests/getting_started.md#reviewer) by selecting a reviewer based on the [approval guidelines](#approval-guidelines).
When a merge request has multiple areas for review, it is recommended you specify which area a reviewer should be reviewing, and at which stage (first or second).
This will help team members who qualify as a reviewer for multiple areas to know which area they're being requested to review.
@@ -662,9 +661,10 @@ Enterprise Edition instance. This has some implications:
- Regular migrations run before the new code is running on the instance.
- [Post-deployment migrations](database/post_deployment_migrations.md) run _after_
the new code is deployed, when the instance is configured to do that.
- - [Background migrations](database/background_migrations.md) run in Sidekiq, and
- should only be done for migrations that would take an extreme amount of
- time at GitLab.com scale.
+ - [Batched background migrations](database/batched_background_migrations.md) run in Sidekiq, and
+ should be used for migrations that
+ [exceed the post-deployment migration time limit](migration_style_guide.md#how-long-a-migration-should-take)
+ GitLab.com scale.
1. **Sidekiq workers** [cannot change in a backwards-incompatible way](sidekiq/compatibility_across_updates.md):
1. Sidekiq queues are not drained before a deploy happens, so there are
workers in the queue from the previous version of GitLab.
diff --git a/doc/development/contributing/community_roles.md b/doc/development/contributing/community_roles.md
index 37c3c24a7d1..8aa219d72a1 100644
--- a/doc/development/contributing/community_roles.md
+++ b/doc/development/contributing/community_roles.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Community members & roles
@@ -12,7 +12,7 @@ GitLab community members and their privileges/responsibilities.
|-------|------------------|--------------|
| Maintainer | Accepts merge requests on several GitLab projects | Added to the [team page](https://about.gitlab.com/company/team/). An expert on code reviews and knows the product/codebase |
| Reviewer | Performs code reviews on MRs | Added to the [team page](https://about.gitlab.com/company/team/) |
-| Developer |Has access to GitLab internal infrastructure & issues (for example, HR-related) | GitLab employee or a Core Team member (with an NDA) |
+| Developer | Has access to GitLab internal infrastructure & issues (for example, HR-related) | GitLab employee or a Core Team member (with an NDA) |
| Contributor | Can make contributions to all GitLab public projects | Have a GitLab.com account |
-[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce).
+[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab).
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index 04915985dc8..9e54b92337a 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Design and user interface changes
@@ -17,11 +17,15 @@ with additions and improvements.
## Merge request reviews
-As a merge request (MR) author, you must include _Before_ and _After_
+As a merge request (MR) author, you must:
+
+- Include _Before_ and _After_
screenshots (or videos) of your changes in the description, as explained in our
[MR workflow](merge_request_workflow.md). These screenshots/videos are very helpful
for all reviewers and can speed up the review process, especially if the changes
are small.
+- Attach the ~UX label to any merge request that impacts the user experience. This will enable Product Designers to [review](https://about.gitlab.com/handbook/engineering/ux/product-designer/mr-reviews/#stage-group-mrs/) any user facing changes.
+- Assign the Product Designer suggested by Reviewer Roulette as the reviewer of your merge request. The reviewer does not have to be the domain expert unless this is a community contribution.
## Checklist
@@ -35,7 +39,7 @@ Check these aspects both when _designing_ and _reviewing_ UI changes.
- Use clear and consistent [terminology](https://design.gitlab.com/content/terminology/).
- Check grammar and spelling.
- Consider help content and follow its [guidelines](https://design.gitlab.com/usability/helping-users/).
-- Request review from the [appropriate Technical Writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments),
+- Request review from the [appropriate Technical Writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments),
indicating any specific files or lines they should review, and how to preview
or understand the location/context of the text from the user's perspective.
@@ -100,7 +104,7 @@ When the design is ready, _before_ starting its implementation:
- Share design specifications in the related issue, preferably through a [Figma link](https://help.figma.com/hc/en-us/articles/360040531773-Share-Files-with-anyone-using-Link-Sharing#copy-link)
link or [GitLab Designs feature](../../user/project/issues/design_management.md).
- See [when you should use each tool](https://about.gitlab.com/handbook/engineering/ux/product-designer/#deliver).
+ See [when you should use each tool](https://about.gitlab.com/handbook/product/ux/product-designer/#deliver).
- Document user flow and states (for example, using [Mermaid flowcharts in Markdown](../../user/markdown.md#mermaid)).
- Document animations and transitions.
- Document responsive behaviors.
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 2ff51e765a3..cbccd832d78 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Contribute to GitLab
@@ -26,11 +26,6 @@ Throughout this guide you will see references to CE and EE for abbreviation.
To get an overview of GitLab community membership, including those that would review or merge
your contributions, visit [the community roles page](community_roles.md).
-If you want to know how the GitLab [core team](https://about.gitlab.com/community/core-team/)
-operates, see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md).
-
-GitLab Inc engineers should refer to the [engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/).
-
## Security vulnerability disclosure
Report suspected security vulnerabilities by following the
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index d557319b41f..df337bb2809 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issues workflow
@@ -373,7 +373,7 @@ below will make it easy to manage this, without unnecessary overhead.
which might lead to many hard problems to solve. Changing some text in GitLab
is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
1. If something is very large, it should probably be split up in multiple
- issues or chunks. You can simply not set the weight of a parent issue and set
+ issues or chunks. You can not set the weight of a parent issue and set
weights to children issues.
## Regression issues
@@ -432,7 +432,7 @@ original merge request - or not tracked at all!
The overheads of scheduling, and rate of change in the GitLab codebase, mean
that the cost of a trivial technical debt issue can quickly exceed the value of
tracking it. This generally means we should resolve these in the original merge
-request - or simply not create a follow-up issue at all.
+request - or not create a follow-up issue at all.
For example, a typo in a comment that is being copied between files is worth
fixing in the same MR, but not worth creating a follow-up issue for. Renaming a
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 0e9ac569558..b40df01cbe9 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge requests workflow
@@ -14,7 +14,7 @@ label, but you are free to contribute to any issue you want.
If an issue is marked for the current milestone at any time, even
when you are working on it, a GitLab Inc. team member may take over the merge request
-in order to ensure the work is finished before the release date.
+to ensure the work is finished before the release date.
If you want to add a new feature that is not labeled, it is best to first create
an issue (if there isn't one already) and leave a comment asking for it
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index 2e696cf517b..9d04e1590d0 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Style guides
@@ -41,13 +41,13 @@ We were using Overcommit prior to Lefthook, so you may want to uninstall it firs
bundle exec lefthook install
```
-1. Test Lefthook is working by running the Lefthook `prepare-commit-msg` Git hook:
+1. Test Lefthook is working by running the Lefthook `pre-push` Git hook:
```shell
- bundle exec lefthook run prepare-commit-msg
+ bundle exec lefthook run pre-push
```
-This should return a fully qualified path command with no other output.
+This should return the lefthook version and the list of executable commands with output.
### Lefthook configuration
@@ -153,11 +153,37 @@ to add it to our [GitLab Styles](https://gitlab.com/gitlab-org/gitlab-styles) ge
If the Cop targets rules that only apply to the main GitLab application,
it should be added to [GitLab](https://gitlab.com/gitlab-org/gitlab) instead.
+### Cop grace period
+
+A cop is in a "grace period" if it is enabled and has `Details: grace period` defined in its TODO YAML configuration.
+
+On the default branch, all of the offenses from cops in the ["grace period"](../rake_tasks.md#run-rubocop-in-graceful-mode) will not fail the RuboCop CI job. The job will notify Slack in the `#f_rubocop` channel when offenses have been silenced in the scheduled pipeline. However, on merge request pipelines, the RuboCop job will fail.
+
+A grace period can safely be lifted as soon as there are no warnings for 2 weeks in the `#f_rubocop` channel on Slack.
+
+### Enabling a new cop
+
+1. Enable the new cop in `.rubocop.yml` (if not already done via [`gitlab-styles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles)).
+1. [Generate TODOs for the new cop](../rake_tasks.md#generate-initial-rubocop-todo-list).
+1. [Set the new cop to "grace period"](#cop-grace-period).
+1. Create an issue to fix TODOs and encourage Community contributions (via ~"good for new contributors" and/or ~"Seeking community contributions"). [See some examples](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=good%20for%20new%20contributors&label_name%5B%5D=static%20code%20analysis&first_page_size=20).
+1. Create an issue to remove "grace period" after 2 weeks silence in `#f_rubocop` Slack channel. ([See an example](https://gitlab.com/gitlab-org/gitlab/-/issues/374903).)
+
+### Silenced offenses
+
+When offenses are silenced for cops in ["grace period"](#cop-grace-period),
+the `#f_rubocop` Slack channel receives a notification message every two hours.
+
+To fix this issue:
+
+1. Find cops with silenced offenses in the linked CI job.
+1. [Generate TODOs](../rake_tasks.md#generate-initial-rubocop-todo-list) for these cops.
+
#### RuboCop node pattern
When creating [node patterns](https://docs.rubocop.org/rubocop-ast/node_pattern.html) to match
Ruby's AST, you can use [`scripts/rubocop-parse`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/rubocop-parse)
-to display the AST of a Ruby expression, in order to help you create the matcher.
+to display the AST of a Ruby expression, to help you create the matcher.
See also [!97024](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97024).
### Resolving RuboCop exceptions
diff --git a/doc/development/contributing/verify/index.md b/doc/development/contributing/verify/index.md
index 09b206d59aa..e94b7583904 100644
--- a/doc/development/contributing/verify/index.md
+++ b/doc/development/contributing/verify/index.md
@@ -52,7 +52,7 @@ and they serve us and our users well. Some examples of these principles are that
- The feedback delivered by GitLab CI/CD and data produced by the platform should be accurate.
If a job fails and we notify a user that it was successful, it can have severe negative consequences.
-- Feedback needs to be available when a user needs it and data can not disappear unexpectedly when engineers need it.
+- Feedback needs to be available when a user needs it and data cannot disappear unexpectedly when engineers need it.
- It all doesn't matter if the platform is not secure and we
are leaking credentials or secrets.
- When a user provides a set of preconditions in a form of CI/CD configuration, the result should be deterministic each time a pipeline runs, because otherwise the platform might not be trustworthy.
@@ -62,7 +62,7 @@ are leaking credentials or secrets.
### Measure before you optimize, and make data-informed decisions
-It is very difficult to optimize something that you can not measure. How would you
+It is very difficult to optimize something that you cannot measure. How would you
know if you succeeded, or how significant the success was? If you are working on
a performance or reliability improvement, make sure that you measure things before
you optimize them.
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index d2b231ebc7c..52503f2d9c8 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Danger bot
@@ -13,7 +13,7 @@ Danger is a gem that runs in the CI environment, like any other analysis tool.
What sets it apart from (for example, RuboCop) is that it's designed to allow you to
easily write arbitrary code to test properties of your code or changes. To this
end, it provides a set of common helpers and access to information about what
-has actually changed in your environment, then simply runs your code!
+has actually changed in your environment, then runs your code!
If Danger is asking you to change something about your merge request, it's best
just to make the change. If you want to learn how Danger works, or make changes
diff --git a/doc/development/database/add_foreign_key_to_existing_column.md b/doc/development/database/add_foreign_key_to_existing_column.md
index 4be3296b2bb..1609e00531e 100644
--- a/doc/development/database/add_foreign_key_to_existing_column.md
+++ b/doc/development/database/add_foreign_key_to_existing_column.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Add a foreign key constraint to an existing column
@@ -126,7 +126,7 @@ Validating the foreign key scans the whole table and makes sure that each relati
Fortunately, this does not lock the source table (`users`) while running.
NOTE:
-When using [background migrations](background_migrations.md), foreign key validation should happen in the next GitLab release.
+When using [batched background migrations](batched_background_migrations.md), foreign key validation should happen in the next GitLab release.
Migration file for validating the foreign key:
diff --git a/doc/development/database/adding_database_indexes.md b/doc/development/database/adding_database_indexes.md
index 774703bd54f..040c6780316 100644
--- a/doc/development/database/adding_database_indexes.md
+++ b/doc/development/database/adding_database_indexes.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Adding Database Indexes
diff --git a/doc/development/database/avoiding_downtime_in_migrations.md b/doc/development/database/avoiding_downtime_in_migrations.md
index 79c76b351c8..57f5a66a9ee 100644
--- a/doc/development/database/avoiding_downtime_in_migrations.md
+++ b/doc/development/database/avoiding_downtime_in_migrations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Avoiding downtime in migrations
@@ -296,7 +296,7 @@ when migrating a column in a large table (for example, `issues`). Background
migrations spread the work / load over a longer time period, without slowing
down deployments.
-For more information, see [the documentation on cleaning up background migrations](background_migrations.md#cleaning-up).
+For more information, see [the documentation on cleaning up batched background migrations](batched_background_migrations.md#cleaning-up).
## Adding Indexes
diff --git a/doc/development/database/background_migrations.md b/doc/development/database/background_migrations.md
index 9b596eb7379..8e6f29b9eb8 100644
--- a/doc/development/database/background_migrations.md
+++ b/doc/development/database/background_migrations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Background migrations
@@ -44,7 +44,7 @@ into this category.
## Isolation
-Background migrations must be isolated and can not use application code (for example,
+Background migrations must be isolated and cannot use application code (for example,
models defined in `app/models` except the `ApplicationRecord` classes). Since these migrations
can take a long time to run it's possible for new versions to be deployed while they are still running.
@@ -86,7 +86,7 @@ migration classes must be defined in the namespace
Scheduling a background migration should be done in a post-deployment
migration that includes `Gitlab::Database::MigrationHelpers`
-To do so, simply use the following code while
+To do so, use the following code while
replacing the class name and arguments with whatever values are necessary for
your migration:
@@ -110,7 +110,7 @@ You also need to make sure that newly created data is either migrated, or
saved in both the old and new version upon creation. For complex and time
consuming migrations it's best to schedule a background job using an
`after_create` hook so this doesn't affect response timings. The same applies to
-updates. Removals in turn can be handled by simply defining foreign keys with
+updates. Removals in turn can be handled by defining foreign keys with
cascading deletes.
### Rescheduling background migrations
diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md
index 192cd0d3e49..a48a9c42e27 100644
--- a/doc/development/database/batched_background_migrations.md
+++ b/doc/development/database/batched_background_migrations.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: Data Stores
group: Database
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Batched background migrations
@@ -41,7 +41,7 @@ into this category.
## Isolation
-Batched background migrations must be isolated and can not use application code (for example,
+Batched background migrations must be isolated and cannot use application code (for example,
models defined in `app/models` except the `ApplicationRecord` classes).
Because these migrations can take a long time to run, it's possible
for new versions to deploy while the migrations are still running.
@@ -532,6 +532,119 @@ for more details.
## Additional tips and strategies
+### ChatOps integration
+
+The batched background migrations framework has ChatOps support. Using ChatOps, GitLab engineers can interact with the batched background migrations present in the system.
+
+#### List batched background migrations
+
+To list the batched background migrations in the system, run this command:
+
+`/chatops run batched_background_migrations list`
+
+This command supports the following options:
+
+- Database selection:
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
+- Environment selection:
+ - `--dev`: Uses the `dev` environment.
+ - `--staging`: Uses the `staging` environment.
+ - `--staging_ref`: Uses the `staging_ref` environment.
+ - `--production` : Uses the `production` environment (default).
+
+Output example:
+
+![List command](img/list_v15_4.png)
+
+NOTE:
+ChatOps returns 20 batched background migrations order by `created_at` (DESC).
+
+#### Monitor the progress and status of a batched background migration
+
+To see the status and progress of a specific batched background migration, run this command:
+
+`/chatops run batched_background_migrations status MIGRATION_ID`
+
+This command supports the following options:
+
+- Database selection:
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default)
+ - `ci`: Uses the CI database
+- Environment selection:
+ - `--dev`: Uses the `dev` environment.
+ - `--staging`: Uses the `staging` environment.
+ - `--staging_ref`: Uses the `staging_ref` environment.
+ - `--production` : Uses the `production` environment (default).
+
+Output example:
+
+![Status command](img/status_v15_4.png)
+
+`Progress` represents the percentage of the background migration that has been completed.
+
+Definitions of the batched background migration states:
+
+- **Active:** Either:
+ - Ready to be picked by the runner.
+ - Running batched jobs.
+- **Finalizing:** Running batched jobs.
+- **Failed:** Failed batched background migration.
+- **Finished:** Completed batched background migration.
+- **Paused:** Not visible to the runner.
+
+#### Pause a batched background migration
+
+If you want to pause a batched background migration, you need to run the following command:
+
+`/chatops run batched_background_migrations pause MIGRATION_ID`
+
+This command supports the following options:
+
+- Database selection:
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
+- Environment selection:
+ - `--dev`: Uses the `dev` environment.
+ - `--staging`: Uses the `staging` environment.
+ - `--staging_ref`: Uses the `staging_ref` environment.
+ - `--production` : Uses the `production` environment (default).
+
+Output example:
+
+![Pause command](img/pause_v15_4.png)
+
+NOTE:
+You can pause only `active` batched background migrations.
+
+#### Resume a batched background migration
+
+If you want to resume a batched background migration, you need to run the following command:
+
+`/chatops run batched_background_migrations resume MIGRATION_ID`
+
+This command supports the following options:
+
+- Database selection:
+ - `--database DATABASE_NAME`: Connects to the given database:
+ - `main`: Uses the main database (default).
+ - `ci`: Uses the CI database.
+- Environment selection:
+ - `--dev`: Uses the `dev` environment.
+ - `--staging`: Uses the `staging` environment.
+ - `--staging_ref`: Uses the `staging_ref` environment.
+ - `--production` : Uses the `production` environment (default).
+
+Output example:
+
+![Resume command](img/resume_v15_4.png)
+
+NOTE:
+You can resume only `active` batched background migrations
+
### Viewing failure error logs
You can view failures in two ways:
@@ -565,3 +678,8 @@ You can view failures in two ways:
ON transition_logs.batched_background_migration_job_id = jobs.id
WHERE transition_logs.next_status = '2' AND migration.job_class_name = "CLASS_NAME";
```
+
+## Legacy background migrations
+
+Batched background migrations replaced the [legacy background migrations framework](background_migrations.md).
+Check that documentation in reference to any changes involving that framework.
diff --git a/doc/development/database/ci_mirrored_tables.md b/doc/development/database/ci_mirrored_tables.md
index 1d285e607fa..bf3a744b936 100644
--- a/doc/development/database/ci_mirrored_tables.md
+++ b/doc/development/database/ci_mirrored_tables.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# CI mirrored tables
diff --git a/doc/development/database/client_side_connection_pool.md b/doc/development/database/client_side_connection_pool.md
index 3143391a553..3c9f8e76d89 100644
--- a/doc/development/database/client_side_connection_pool.md
+++ b/doc/development/database/client_side_connection_pool.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Client-side connection-pool
diff --git a/doc/development/database/constraint_naming_convention.md b/doc/development/database/constraint_naming_convention.md
index 2f0b8bf0463..e9e130495e6 100644
--- a/doc/development/database/constraint_naming_convention.md
+++ b/doc/development/database/constraint_naming_convention.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Constraints naming conventions
diff --git a/doc/development/database/creating_enums.md b/doc/development/database/creating_enums.md
index 450cb97d978..73c3f546728 100644
--- a/doc/development/database/creating_enums.md
+++ b/doc/development/database/creating_enums.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Creating enums
@@ -103,7 +103,7 @@ This looks working as a workaround, however, this approach has some downsides th
Therefore, you need to be careful of that the offset doesn't exceed the maximum value of 2 bytes integer.
As a conclusion, you should define all of the key/value pairs in FOSS.
-For example, you can simply write the following code in the above case:
+For example, you can write the following code in the above case:
```ruby
class Pipeline < ApplicationRecord
diff --git a/doc/development/database/database_debugging.md b/doc/development/database/database_debugging.md
index 591e526cc96..4dc6a3bdcfa 100644
--- a/doc/development/database/database_debugging.md
+++ b/doc/development/database/database_debugging.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting and debugging the database
diff --git a/doc/development/database/database_dictionary.md b/doc/development/database/database_dictionary.md
index c330c5e67bd..bd6dbc54316 100644
--- a/doc/development/database/database_dictionary.md
+++ b/doc/development/database/database_dictionary.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database Dictionary
diff --git a/doc/development/database/database_lab.md b/doc/development/database/database_lab.md
index 1d584a4ec6f..b60091fa37c 100644
--- a/doc/development/database/database_lab.md
+++ b/doc/development/database/database_lab.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database Lab and Postgres.ai
diff --git a/doc/development/database/database_migration_pipeline.md b/doc/development/database/database_migration_pipeline.md
index 496bd09bf1d..148dc1e94a0 100644
--- a/doc/development/database/database_migration_pipeline.md
+++ b/doc/development/database/database_migration_pipeline.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database migration pipeline
diff --git a/doc/development/database/database_query_comments.md b/doc/development/database/database_query_comments.md
index 2798071bc06..946947db502 100644
--- a/doc/development/database/database_query_comments.md
+++ b/doc/development/database/database_query_comments.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database query comments with Marginalia
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index a85f399a447..aa92134018d 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database Reviewer Guidelines
diff --git a/doc/development/database/db_dump.md b/doc/development/database/db_dump.md
index f2076cbc410..b09c601537c 100644
--- a/doc/development/database/db_dump.md
+++ b/doc/development/database/db_dump.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Importing a database dump into a staging environment
diff --git a/doc/development/database/dbcheck-migrations-job.md b/doc/development/database/dbcheck-migrations-job.md
index 49f8b183272..4ebfb40cd03 100644
--- a/doc/development/database/dbcheck-migrations-job.md
+++ b/doc/development/database/dbcheck-migrations-job.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# db:check-migrations job
diff --git a/doc/development/database/deleting_migrations.md b/doc/development/database/deleting_migrations.md
index 8354cb62d0c..bd03e6c11ae 100644
--- a/doc/development/database/deleting_migrations.md
+++ b/doc/development/database/deleting_migrations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Delete existing migrations
diff --git a/doc/development/database/efficient_in_operator_queries.md b/doc/development/database/efficient_in_operator_queries.md
index a2481577e8c..fb7ff3c1cc2 100644
--- a/doc/development/database/efficient_in_operator_queries.md
+++ b/doc/development/database/efficient_in_operator_queries.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Efficient `IN` operator queries
@@ -670,6 +670,64 @@ records_by_id.each do |id, _|
end
```
+#### Ordering by `JOIN` columns
+
+Ordering records by mixed columns where one or more columns are coming from `JOIN` tables
+works with limitations. It requires extra configuration (CTE). The trick is to use a
+non-materialized CTE to act as a "fake" table which exposes all required columns.
+
+NOTE:
+The query performance might not improve compared to the standard `IN` query. Always
+check the query plan.
+
+Example: order issues by `projects.name, issues.id` within the group hierarchy
+
+The first step is to create a CTE, where all required columns are collected in the `SELECT`
+clause.
+
+```ruby
+cte_query = Issue
+ .select('issues.id AS id', 'issues.project_id AS project_id', 'projects.name AS projects_name')
+ .joins(:project)
+
+cte = Gitlab::SQL::CTE.new(:issue_with_projects, cte_query, materialized: false)
+```
+
+Custom order object configuration:
+
+```ruby
+order = Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_name',
+ order_expression: Issue.arel_table[:projects_name].asc,
+ sql_type: 'character varying',
+ nullable: :nulls_last,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
+```
+
+Generate the query:
+
+```ruby
+scope = cte.apply_to(Issue.where({}).reorder(order))
+
+opts = {
+ scope: scope,
+ array_scope: Project.where(namespace_id: top_level_group.self_and_descendants.select(:id)).select(:id),
+ array_mapping_scope: -> (id_expression) { Issue.where(Issue.arel_table[:project_id].eq(id_expression)) }
+}
+
+records = Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder
+ .new(**opts)
+ .execute
+ .limit(20)
+```
+
#### Batch iteration
Batch iteration over the records is possible via the keyset `Iterator` class.
@@ -1052,6 +1110,6 @@ Performance comparison for the `gitlab-org` group:
| Optimized `IN` query | 9783 | 450ms | 22ms |
NOTE:
-Before taking measurements, the group lookup query was executed separately in order to make
+Before taking measurements, the group lookup query was executed separately to make
the group data available in the buffer cache. Since it's a frequently called query, it
hits many shared buffers during the query execution in the production environment.
diff --git a/doc/development/database/filtering_by_label.md b/doc/development/database/filtering_by_label.md
index 29b0c75298e..a30322176ba 100644
--- a/doc/development/database/filtering_by_label.md
+++ b/doc/development/database/filtering_by_label.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Filtering by label
diff --git a/doc/development/database/foreign_keys.md b/doc/development/database/foreign_keys.md
index 7834e7d53c3..d9506ae614a 100644
--- a/doc/development/database/foreign_keys.md
+++ b/doc/development/database/foreign_keys.md
@@ -1,10 +1,10 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Foreign Keys & Associations
+# Foreign keys and associations
When adding an association to a model you must also add a foreign key. For
example, say you have the following model:
@@ -20,7 +20,7 @@ that data consistency is enforced on database level. Foreign keys also mean that
the database can very quickly remove associated data (for example, when removing a
user), instead of Rails having to do this.
-## Adding Foreign Keys In Migrations
+## Adding foreign keys in migrations
Foreign keys can be added concurrently using `add_concurrent_foreign_key` as
defined in `Gitlab::Database::MigrationHelpers`. See the
@@ -31,7 +31,7 @@ you have removed any orphaned rows. The method `add_concurrent_foreign_key`
does not take care of this so you must do so manually. See
[adding foreign key constraint to an existing column](add_foreign_key_to_existing_column.md).
-## Updating Foreign Keys In Migrations
+## Updating foreign keys in migrations
Sometimes a foreign key constraint must be changed, preserving the column
but updating the constraint condition. For example, moving from
@@ -45,64 +45,64 @@ To replace a foreign key:
1. [Add the new foreign key without validation](add_foreign_key_to_existing_column.md#prevent-invalid-records)
- The name of the foreign key constraint must be changed to add a new
- foreign key before removing the old one.
+ The name of the foreign key constraint must be changed to add a new
+ foreign key before removing the old one.
- ```ruby
- class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
- disable_ddl_transaction!
+ ```ruby
+ class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
- NEW_CONSTRAINT_NAME = 'fk_new'
+ NEW_CONSTRAINT_NAME = 'fk_new'
- def up
- add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :nullify, validate: false, name: NEW_CONSTRAINT_NAME)
- end
+ def up
+ add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :nullify, validate: false, name: NEW_CONSTRAINT_NAME)
+ end
- def down
- with_lock_retries do
- remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :nullify, name: NEW_CONSTRAINT_NAME)
- end
- end
- end
- ```
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :nullify, name: NEW_CONSTRAINT_NAME)
+ end
+ end
+ end
+ ```
1. [Validate the new foreign key](add_foreign_key_to_existing_column.md#validate-the-foreign-key)
- ```ruby
- class ValidateFkNew < Gitlab::Database::Migration[2.0]
- NEW_CONSTRAINT_NAME = 'fk_new'
+ ```ruby
+ class ValidateFkNew < Gitlab::Database::Migration[2.0]
+ NEW_CONSTRAINT_NAME = 'fk_new'
- # foreign key added in <link to MR or path to migration adding new FK>
- def up
- validate_foreign_key(:packages_packages, name: NEW_CONSTRAINT_NAME)
- end
+ # foreign key added in <link to MR or path to migration adding new FK>
+ def up
+ validate_foreign_key(:packages_packages, name: NEW_CONSTRAINT_NAME)
+ end
- def down
- # no-op
- end
- end
- ```
+ def down
+ # no-op
+ end
+ end
+ ```
1. Remove the old foreign key:
- ```ruby
- class RemoveFkOld < Gitlab::Database::Migration[2.0]
- OLD_CONSTRAINT_NAME = 'fk_old'
+ ```ruby
+ class RemoveFkOld < Gitlab::Database::Migration[2.0]
+ OLD_CONSTRAINT_NAME = 'fk_old'
- # new foreign key added in <link to MR or path to migration adding new FK>
- # and validated in <link to MR or path to migration validating new FK>
- def up
- remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :cascade, name: OLD_CONSTRAINT_NAME)
- end
+ # new foreign key added in <link to MR or path to migration adding new FK>
+ # and validated in <link to MR or path to migration validating new FK>
+ def up
+ remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :cascade, name: OLD_CONSTRAINT_NAME)
+ end
- def down
- # Validation is skipped here, so if rolled back, this will need to be revalidated in a separate migration
- add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :cascade, validate: false, name: OLD_CONSTRAINT_NAME)
- end
- end
- ```
+ def down
+ # Validation is skipped here, so if rolled back, this will need to be revalidated in a separate migration
+ add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :cascade, validate: false, name: OLD_CONSTRAINT_NAME)
+ end
+ end
+ ```
-## Cascading Deletes
+## Cascading deletes
Every foreign key must define an `ON DELETE` clause, and in 99% of the cases
this should be set to `CASCADE`.
@@ -124,7 +124,7 @@ have a foreign key constraint. So if that spec fails, don't add the column to
`IGNORED_FK_COLUMNS`, but instead add the FK constraint, or consider naming it
differently.
-## Dependent Removals
+## Dependent removals
Don't define options such as `dependent: :destroy` or `dependent: :delete` when
defining an association. Defining these options means Rails handles the
@@ -182,9 +182,9 @@ create_table :user_configs, id: false do |t|
end
```
-Setting `default: nil` ensures a primary key sequence is not created, and since the primary key
+Setting `default: nil` ensures a primary key sequence is not created, and because the primary key
automatically gets an index, we set `index: false` to avoid creating a duplicate.
-You also need to add the new primary key to the model:
+You must also add the new primary key to the model:
```ruby
class UserConfig < ActiveRecord::Base
diff --git a/doc/development/database/hash_indexes.md b/doc/development/database/hash_indexes.md
index 731639b6f06..aba23dbea70 100644
--- a/doc/development/database/hash_indexes.md
+++ b/doc/development/database/hash_indexes.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Hash Indexes
diff --git a/doc/development/database/img/list_v15_4.png b/doc/development/database/img/list_v15_4.png
new file mode 100644
index 00000000000..f5c478321c1
--- /dev/null
+++ b/doc/development/database/img/list_v15_4.png
Binary files differ
diff --git a/doc/development/database/img/pause_v15_4.png b/doc/development/database/img/pause_v15_4.png
new file mode 100644
index 00000000000..744a2f13243
--- /dev/null
+++ b/doc/development/database/img/pause_v15_4.png
Binary files differ
diff --git a/doc/development/database/img/resume_v15_4.png b/doc/development/database/img/resume_v15_4.png
new file mode 100644
index 00000000000..919fd337595
--- /dev/null
+++ b/doc/development/database/img/resume_v15_4.png
Binary files differ
diff --git a/doc/development/database/img/status_v15_4.png b/doc/development/database/img/status_v15_4.png
new file mode 100644
index 00000000000..01396649094
--- /dev/null
+++ b/doc/development/database/img/status_v15_4.png
Binary files differ
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index 8cf9a2eec04..87b1b4a9d87 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database guides
@@ -26,7 +26,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Different types of migrations](../migration_style_guide.md#choose-an-appropriate-migration-type)
- [Create a regular migration](../migration_style_guide.md#create-a-regular-schema-migration), including creating new models
- [Post-deployment migrations guidelines](post_deployment_migrations.md) and [how to create one](post_deployment_migrations.md#creating-migrations)
-- [Background migrations guidelines](background_migrations.md)
+- [Legacy Background migrations guidelines](background_migrations.md)
- [Batched background migrations guidelines](batched_background_migrations.md)
- [Deleting migrations](deleting_migrations.md)
- [Running database migrations](database_debugging.md#migration-wrangling)
@@ -36,7 +36,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Migrations style guide](../migration_style_guide.md) for creating safe SQL migrations
- [Testing Rails migrations](../testing_guide/testing_migrations_guide.md) guide
- [Post deployment migrations](post_deployment_migrations.md)
-- [Background migrations](background_migrations.md)
- [Swapping tables](swapping_tables.md)
- [Deleting migrations](deleting_migrations.md)
- [SQL guidelines](../sql.md) for working with SQL queries
diff --git a/doc/development/database/insert_into_tables_in_batches.md b/doc/development/database/insert_into_tables_in_batches.md
index ebed3d16319..78aa793f28b 100644
--- a/doc/development/database/insert_into_tables_in_batches.md
+++ b/doc/development/database/insert_into_tables_in_batches.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Sometimes it is necessary to store large amounts of records at once, which can be inefficient
when iterating collections and performing individual `save`s. With the arrival of `insert_all`
in Rails 6, which operates at the row level (that is, using `Hash`es), GitLab has added a set
@@ -181,7 +181,7 @@ end
```
You can still save relations that are not `BulkInsertSafe` in this block; they
-simply are treated as if you had invoked `save` from outside the block.
+are treated as if you had invoked `save` from outside the block.
## Known limitations
diff --git a/doc/development/database/iterating_tables_in_batches.md b/doc/development/database/iterating_tables_in_batches.md
index 6d7a57ecacb..6357bed8b00 100644
--- a/doc/development/database/iterating_tables_in_batches.md
+++ b/doc/development/database/iterating_tables_in_batches.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Iterating tables in batches
@@ -114,7 +114,7 @@ falling into an endless loop as described in following
When dealing with data migrations the preferred way to iterate over a large volume of data is using
`EachBatch`.
-A special case of data migration is a [background migration](background_migrations.md#scheduling)
+A special case of data migration is a [batched background migration](batched_background_migrations.md)
where the actual data modification is executed in a background job. The migration code that
determines the data ranges (slices) and schedules the background jobs uses `each_batch`.
@@ -196,7 +196,7 @@ value is "excluded". The query looks at the index to get the location of the fiv
rows on the disk and read the rows from the table. The returned array is processed in Ruby.
The first iteration is done. For the next iteration, the last `id` value is reused from the
-previous iteration in order to find out the next end `id` value.
+previous iteration to find out the next end `id` value.
```sql
SELECT "users"."id" FROM "users" WHERE "users"."id" >= 302 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
diff --git a/doc/development/database/keyset_pagination.md b/doc/development/database/keyset_pagination.md
index 4aec64b8cce..21bce41012e 100644
--- a/doc/development/database/keyset_pagination.md
+++ b/doc/development/database/keyset_pagination.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Keyset pagination
diff --git a/doc/development/database/layout_and_access_patterns.md b/doc/development/database/layout_and_access_patterns.md
index 99a50b503aa..06ac24c284c 100644
--- a/doc/development/database/layout_and_access_patterns.md
+++ b/doc/development/database/layout_and_access_patterns.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Best practices for data layout and access patterns
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
index 0af12939629..abf66368548 100644
--- a/doc/development/database/loose_foreign_keys.md
+++ b/doc/development/database/loose_foreign_keys.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Loose foreign keys
@@ -311,7 +311,7 @@ end
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:
+Add to the model test file:
```ruby
it_behaves_like 'it has loose foreign keys' do
diff --git a/doc/development/database/maintenance_operations.md b/doc/development/database/maintenance_operations.md
index 85df185c024..bfe18068aab 100644
--- a/doc/development/database/maintenance_operations.md
+++ b/doc/development/database/maintenance_operations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Maintenance operations
diff --git a/doc/development/database/migrations_for_multiple_databases.md b/doc/development/database/migrations_for_multiple_databases.md
index df9607f5672..b4d2656121b 100644
--- a/doc/development/database/migrations_for_multiple_databases.md
+++ b/doc/development/database/migrations_for_multiple_databases.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrations for Multiple databases
diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md
index 034a2c2e438..e5b6cfb8866 100644
--- a/doc/development/database/multiple_databases.md
+++ b/doc/development/database/multiple_databases.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Pods
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Multiple Databases
diff --git a/doc/development/database/namespaces_storage_statistics.md b/doc/development/database/namespaces_storage_statistics.md
index 702129b9ddb..c653cfb145d 100644
--- a/doc/development/database/namespaces_storage_statistics.md
+++ b/doc/development/database/namespaces_storage_statistics.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database case study: Namespaces storage statistics
diff --git a/doc/development/database/not_null_constraints.md b/doc/development/database/not_null_constraints.md
index cd2adc3ca28..dccaff2df00 100644
--- a/doc/development/database/not_null_constraints.md
+++ b/doc/development/database/not_null_constraints.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# `NOT NULL` constraints
@@ -93,7 +93,7 @@ We only want to enforce the `NOT NULL` constraint without setting a default, as
that all epics should have a user-generated description.
After checking our production database, we know that there are `epics` with `NULL` descriptions,
-so we can not add and validate the constraint in one step.
+so we cannot add and validate the constraint in one step.
NOTE:
Even if we did not have any epic with a `NULL` description, another instance of GitLab could have
@@ -202,7 +202,7 @@ end
If you have to clean up a nullable column for a [high-traffic table](../migration_style_guide.md#high-traffic-tables)
(for example, the `artifacts` in `ci_builds`), your background migration goes on for a while and
-it needs an additional [background migration cleaning up](background_migrations.md#cleaning-up)
+it needs an additional [batched background migration cleaning up](batched_background_migrations.md#cleaning-up)
in the release after adding the data migration.
In that rare case you need 3 releases end-to-end:
diff --git a/doc/development/database/ordering_table_columns.md b/doc/development/database/ordering_table_columns.md
index a16df6a4499..286313fb3ce 100644
--- a/doc/development/database/ordering_table_columns.md
+++ b/doc/development/database/ordering_table_columns.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ordering Table Columns in PostgreSQL
diff --git a/doc/development/database/pagination_guidelines.md b/doc/development/database/pagination_guidelines.md
index fe2e3b46939..54b315b9dd9 100644
--- a/doc/development/database/pagination_guidelines.md
+++ b/doc/development/database/pagination_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pagination guidelines
@@ -50,9 +50,9 @@ When we list records on the page we often provide additional filters and differe
For the MVC version, consider the following:
- Reduce the number of sort options to the minimum.
-- Reduce the number of filters (dropdown, search bar) to the minimum.
+- Reduce the number of filters (dropdown list, search bar) to the minimum.
-To make sorting and pagination efficient, for each sort option we need at least two database indexes (ascending, descending order). If we add filter options (by state or by author), we might need more indexes to maintain good performance. Note that indexes are not free, they can significantly affect the `UPDATE` query timings.
+To make sorting and pagination efficient, for each sort option we need at least two database indexes (ascending, descending order). If we add filter options (by state or by author), we might need more indexes to maintain good performance. Indexes are not free, they can significantly affect the `UPDATE` query timings.
It's not possible to make all filter and sort combinations performant, so we should try optimizing the performance by usage patterns.
@@ -154,7 +154,7 @@ Here we're leveraging the ordered property of the b-tree database index. Values
##### `COUNT(*)` on a large dataset
-Kaminari by default executes a count query to determine the number of pages for rendering the page links. Count queries can be quite expensive for a large table. In an unfortunate scenario the queries simply time out.
+Kaminari by default executes a count query to determine the number of pages for rendering the page links. Count queries can be quite expensive for a large table. In an unfortunate scenario the queries time out.
To work around this, we can run Kaminari without invoking the count SQL query.
@@ -264,7 +264,7 @@ Looking at the query execution plan, we can see that this query read only 5 rows
##### No page numbers
-Offset pagination provides an easy way to request a specific page. We can simply edit the URL and modify the `page=` URL parameter. Keyset pagination cannot provide page numbers because the paging logic might depend on different columns.
+Offset pagination provides an easy way to request a specific page. We can edit the URL and modify the `page=` URL parameter. Keyset pagination cannot provide page numbers because the paging logic might depend on different columns.
In the previous example, the column is the `id`, so we might see something like this in the `URL`:
diff --git a/doc/development/database/pagination_performance_guidelines.md b/doc/development/database/pagination_performance_guidelines.md
index 0fef246f133..0f98b50d95c 100644
--- a/doc/development/database/pagination_performance_guidelines.md
+++ b/doc/development/database/pagination_performance_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pagination performance guidelines
diff --git a/doc/development/database/polymorphic_associations.md b/doc/development/database/polymorphic_associations.md
index ac4dc7720a5..f3c9bf1276f 100644
--- a/doc/development/database/polymorphic_associations.md
+++ b/doc/development/database/polymorphic_associations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Polymorphic Associations
diff --git a/doc/development/database/post_deployment_migrations.md b/doc/development/database/post_deployment_migrations.md
index 8166fcc8905..0d0047531f9 100644
--- a/doc/development/database/post_deployment_migrations.md
+++ b/doc/development/database/post_deployment_migrations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Post Deployment Migrations
diff --git a/doc/development/database/query_count_limits.md b/doc/development/database/query_count_limits.md
index a888bbfc6e7..b5fd4395b36 100644
--- a/doc/development/database/query_count_limits.md
+++ b/doc/development/database/query_count_limits.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Query Count Limits
diff --git a/doc/development/database/query_performance.md b/doc/development/database/query_performance.md
index 41dbd08d726..61fd80338fe 100644
--- a/doc/development/database/query_performance.md
+++ b/doc/development/database/query_performance.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Query performance guidelines
diff --git a/doc/development/database/query_recorder.md b/doc/development/database/query_recorder.md
index da5c6c8e6cb..3fc38c10d68 100644
--- a/doc/development/database/query_recorder.md
+++ b/doc/development/database/query_recorder.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# QueryRecorder
diff --git a/doc/development/database/rename_database_tables.md b/doc/development/database/rename_database_tables.md
index d6827cb9e03..641bba1f131 100644
--- a/doc/development/database/rename_database_tables.md
+++ b/doc/development/database/rename_database_tables.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rename table without downtime
diff --git a/doc/development/database/serializing_data.md b/doc/development/database/serializing_data.md
index 97e6f665484..b25c8d49b64 100644
--- a/doc/development/database/serializing_data.md
+++ b/doc/development/database/serializing_data.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Serializing Data
diff --git a/doc/development/database/setting_multiple_values.md b/doc/development/database/setting_multiple_values.md
index cba15a73430..fb85386785d 100644
--- a/doc/development/database/setting_multiple_values.md
+++ b/doc/development/database/setting_multiple_values.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Update multiple database objects
diff --git a/doc/development/database/sha1_as_binary.md b/doc/development/database/sha1_as_binary.md
index dab9b0fe72e..5ad9d106086 100644
--- a/doc/development/database/sha1_as_binary.md
+++ b/doc/development/database/sha1_as_binary.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Storing SHA1 Hashes As Binary
diff --git a/doc/development/database/single_table_inheritance.md b/doc/development/database/single_table_inheritance.md
index c8d082e8a67..ad0101e1594 100644
--- a/doc/development/database/single_table_inheritance.md
+++ b/doc/development/database/single_table_inheritance.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Single Table Inheritance
diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md
index 4b5d1fc8f72..fb005e51902 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Strings and the Text data type
@@ -15,7 +15,7 @@ When adding new columns to store strings or other textual information:
the `#text ... limit: 100` helper (see below) when creating a table, or by using the `add_text_limit`
when altering an existing table.
-The standard Rails `text` column type can not be defined with a limit, but we extend `create_table` to
+The standard Rails `text` column type cannot be defined with a limit, but we extend `create_table` to
add a `limit: 255` option. Outside of `create_table`, `add_text_limit` can be used to add a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html)
to an already existing column.
@@ -50,7 +50,7 @@ For example, consider a migration that creates a table with two text columns,
`db/migrate/20200401000001_create_db_guides.rb`:
```ruby
-class CreateDbGuides < Gitlab::Database::Migration[1.0]
+class CreateDbGuides < Gitlab::Database::Migration[2.0]
def change
create_table :db_guides do |t|
t.bigint :stars, default: 0, null: false
@@ -74,7 +74,7 @@ For example, consider a migration that adds a new text column `extended_title` t
`db/migrate/20200501000001_add_extended_title_to_sprints.rb`:
```ruby
-class AddExtendedTitleToSprints < Gitlab::Database::Migration[1.0]
+class AddExtendedTitleToSprints < Gitlab::Database::Migration[2.0]
# rubocop:disable Migration/AddLimitToTextColumns
# limit is added in 20200501000002_add_text_limit_to_sprints_extended_title
@@ -89,7 +89,7 @@ A second migration should follow the first one with a limit added to `extended_t
`db/migrate/20200501000002_add_text_limit_to_sprints_extended_title.rb`:
```ruby
-class AddTextLimitToSprintsExtendedTitle < Gitlab::Database::Migration[1.0]
+class AddTextLimitToSprintsExtendedTitle < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -131,7 +131,7 @@ Issues is a pretty busy and large table with more than 25 million rows, so we do
other processes that try to access it while running the update.
Also, after checking our production database, we know that there are `issues` with more characters in
-their title than the 1024 character limit, so we can not add and validate the constraint in one step.
+their title than the 1024 character limit, so we cannot add and validate the constraint in one step.
NOTE:
Even if we did not have any record with a title larger than the provided limit, another
@@ -165,7 +165,7 @@ in a post-deployment migration,
`db/post_migrate/20200501000001_add_text_limit_migration.rb`:
```ruby
-class AddTextLimitMigration < Gitlab::Database::Migration[1.0]
+class AddTextLimitMigration < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -196,7 +196,7 @@ to add a background migration for the 13.0 milestone (current),
`db/post_migrate/20200501000002_schedule_cap_title_length_on_issues.rb`:
```ruby
-class ScheduleCapTitleLengthOnIssues < Gitlab::Database::Migration[1.0]
+class ScheduleCapTitleLengthOnIssues < Gitlab::Database::Migration[2.0]
# Info on how many records will be affected on GitLab.com
# time each batch needs to run on average, etc ...
BATCH_SIZE = 5000
@@ -207,30 +207,25 @@ class ScheduleCapTitleLengthOnIssues < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
- class Issue < ::ApplicationRecord
- include EachBatch
-
- self.table_name = 'issues'
- end
-
def up
- queue_background_migration_jobs_by_range_at_intervals(
- Issue.where('char_length(title_html) > 1024'),
- ISSUES_MIGRATION,
- DELAY_INTERVAL,
+ queue_batched_background_migration(
+ ISSUES_BACKGROUND_MIGRATION,
+ :issues,
+ :id,
+ job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE
)
end
def down
- # no-op : the part of the title_html after the limit is lost forever
+ delete_batched_background_migration(ISSUES_BACKGROUND_MIGRATION, :issues, :id, [])
end
end
```
To keep this guide short, we skipped the definition of the background migration and only
provided a high level example of the post-deployment migration that is used to schedule the batches.
-You can find more information on the guide about [background migrations](background_migrations.md)
+You can find more information on the guide about [batched background migrations](batched_background_migrations.md)
#### Validate the text limit (next release)
@@ -241,7 +236,7 @@ helper in a final post-deployment migration,
`db/post_migrate/20200601000001_validate_text_limit_migration.rb`:
```ruby
-class ValidateTextLimitMigration < Gitlab::Database::Migration[1.0]
+class ValidateTextLimitMigration < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -260,7 +255,7 @@ Increasing text limits on existing database columns can be safely achieved by fi
and then dropping the previous limit:
```ruby
-class ChangeMaintainerNoteLimitInCiRunner < Gitlab::Database::Migration[1.0]
+class ChangeMaintainerNoteLimitInCiRunner < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -278,7 +273,7 @@ end
If you have to clean up a text column for a really [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)
(for example, the `artifacts` in `ci_builds`), your background migration goes on for a while and
-it needs an additional [background migration cleaning up](background_migrations.md#cleaning-up)
+it needs an additional [batched background migration cleaning up](batched_background_migrations.md#cleaning-up)
in the release after adding the data migration.
In that rare case you need 3 releases end-to-end:
diff --git a/doc/development/database/swapping_tables.md b/doc/development/database/swapping_tables.md
index efb481ccf35..f659d1408d3 100644
--- a/doc/development/database/swapping_tables.md
+++ b/doc/development/database/swapping_tables.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Swapping Tables
diff --git a/doc/development/database/table_partitioning.md b/doc/development/database/table_partitioning.md
index 582c988bef9..bf12329473d 100644
--- a/doc/development/database/table_partitioning.md
+++ b/doc/development/database/table_partitioning.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database table partitioning
@@ -142,7 +142,7 @@ substantial. Partitioning should only be leveraged if the access patterns
of the data support the partitioning strategy, otherwise performance
suffers.
-## Partitioning a table
+## Partitioning a table (Range)
Unfortunately, tables can only be partitioned at their creation, making
it nontrivial to apply to a busy database. A suite of migration
@@ -256,3 +256,217 @@ The final step of the migration makes the partitioned table ready
for use by the application. This section will be updated when the
migration helper is ready, for now development can be followed in the
[Tracking Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/241267).
+
+## Partitioning a table (List)
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96815) in GitLab 15.4.
+
+Add the partitioning key column to the table you are partitioning.
+Include the partitioning key in the following constraints:
+
+- The primary key.
+- All foreign keys referencing the table to be partitioned.
+- All unique constraints.
+
+### Step 1 - Add partition key
+
+Add the partitioning key column. For example, in a rails migration:
+
+```ruby
+class AddPartitionNumberForPartitioning < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ TABLE_NAME = :table_name
+ COLUMN_NAME = :partition_id
+ DEFAULT_VALUE = 100
+
+ def change
+ add_column(TABLE_NAME, COLUMN_NAME, :bigint, default: 100)
+ end
+end
+```
+
+### Step 2 - Create required indexes
+
+Add indexes including the partitioning key column. For example, in a rails migration:
+
+```ruby
+class PrepareIndexesForPartitioning < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ INDEX_NAME = :index_name
+
+ def up
+ add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+end
+```
+
+### Step 3 - Swap primary key
+
+Swap the primary key including the partitioning key column. For example, in a rails migration:
+
+```ruby
+class PreparePrimaryKeyForPartitioning < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ PRIMARY_KEY = :primary_key
+ OLD_INDEX_NAME = :old_index_name
+ NEW_INDEX_NAME = :new_index_name
+
+ def up
+ swap_primary_key(TABLE_NAME, PRIMARY_KEY, NEW_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_INDEX_NAME)
+ add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_INDEX_NAME)
+
+ unswap_primary_key(TABLE_NAME, PRIMARY_KEY, OLD_INDEX_NAME)
+ end
+end
+```
+
+NOTE:
+Do not forget to set the primary key explicitly in your model as `ActiveRecord` does not support composite primary keys.
+
+```ruby
+class Model < ApplicationRecord
+ self.primary_key = :id
+end
+```
+
+### Step 4 - Enforce unique constraint
+
+Enforce unique indexes including the partitioning key column. For example, in a rails migration:
+
+```ruby
+class PrepareUniqueContraintForPartitioning < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ OLD_UNIQUE_INDEX_NAME = :index_name_unique
+ NEW_UNIQUE_INDEX_NAME = :new_index_name
+
+ def up
+ add_concurrent_index(TABLE_NAME, [:some_column, :partition_id], unique: true, name: NEW_UNIQUE_INDEX_NAME)
+
+ remove_concurrent_index_by_name(TABLE_NAME, OLD_UNIQUE_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, :some_column, unique: true, name: OLD_UNIQUE_INDEX_NAME)
+
+ remove_concurrent_index_by_name(TABLE_NAME, NEW_UNIQUE_INDEX_NAME)
+ end
+end
+```
+
+### Step 5 - Enforce foreign key constraint
+
+Enforce foreign keys including the partitioning key column. For example, in a rails migration:
+
+```ruby
+class PrepareForeignKeyForPartitioning < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ SOURCE_TABLE_NAME = :source_table_name
+ TARGET_TABLE_NAME = :target_table_name
+ COLUMN = :foreign_key_id
+ TARGET_COLUMN = :id
+ CONSTRAINT_NAME = :fk_365d1db505_p
+ PARTITION_COLUMN = :partition_id
+
+ def up
+ add_concurrent_foreign_key(
+ SOURCE_TABLE_NAME,
+ TARGET_TABLE_NAME,
+ column: [PARTITION_COLUMN, COLUMN],
+ target_column: [PARTITION_COLUMN, TARGET_COLUMN],
+ validate: false
+ name: CONSTRAINT_NAME
+ )
+
+ validate_foreign_key(TARGET_TABLE_NAME, CONSTRAINT_NAME)
+ end
+
+ def down
+ drop_constraint(TARGET_TABLE_NAME, CONSTRAINT_NAME)
+ end
+end
+```
+
+### Step 6 - Create parent table and attach existing table as the initial partition
+
+You can now create the parent table attaching the existing table as the initial
+partition by using the following helpers provided by the database team.
+
+For example, using list partitioning in Rails post migrations:
+
+```ruby
+class PrepareTableConstraintsForListPartitioning < Gitlab::Database::Migration[2.0]
+ include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ PARENT_TABLE_NAME = :p_table_name
+ FIRST_PARTITION = 100
+ PARTITION_COLUMN = :partition_id
+
+ def up
+ prepare_constraint_for_list_partitioning(
+ table_name: TABLE_NAME,
+ partitioning_column: PARTITION_COLUMN,
+ parent_table_name: PARENT_TABLE_NAME,
+ initial_partitioning_value: FIRST_PARTITION
+ )
+ end
+
+ def down
+ revert_preparing_constraint_for_list_partitioning(
+ table_name: TABLE_NAME,
+ partitioning_column: PARTITION_COLUMN,
+ parent_table_name: PARENT_TABLE_NAME,
+ initial_partitioning_value: FIRST_PARTITION
+ )
+ end
+end
+```
+
+```ruby
+class ConvertTableToListPartitioning < Gitlab::Database::Migration[2.0]
+ include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ PARENT_TABLE_NAME = :p_table_name
+ FIRST_PARTITION = 100
+ PARTITION_COLUMN = :partition_id
+
+ def up
+ convert_table_to_first_list_partition(
+ table_name: TABLE_NAME,
+ partitioning_column: PARTITION_COLUMN,
+ parent_table_name: PARENT_TABLE_NAME,
+ initial_partitioning_value: FIRST_PARTITION
+ )
+ end
+
+ def down
+ revert_converting_table_to_first_list_partition(
+ table_name: TABLE_NAME,
+ partitioning_column: PARTITION_COLUMN,
+ parent_table_name: PARENT_TABLE_NAME,
+ initial_partitioning_value: FIRST_PARTITION
+ )
+ end
+end
+```
diff --git a/doc/development/database/transaction_guidelines.md b/doc/development/database/transaction_guidelines.md
index 1583bbc02c2..26bb6c2ce8f 100644
--- a/doc/development/database/transaction_guidelines.md
+++ b/doc/development/database/transaction_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Transaction guidelines
@@ -139,5 +139,5 @@ end
```
The `ApplicationRecord` class uses a different database connection than the `Ci::Build` records.
-The two statements in the transaction block are not part of the transaction and are
-rolled back in case something goes wrong. They act as 3rd part calls.
+The two statements in the transaction block are not part of the transaction and are not
+rolled back in case something goes wrong. They act as third-party calls.
diff --git a/doc/development/database/understanding_explain_plans.md b/doc/development/database/understanding_explain_plans.md
index c3cb408b35f..fff9d755e9a 100644
--- a/doc/development/database/understanding_explain_plans.md
+++ b/doc/development/database/understanding_explain_plans.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Understanding EXPLAIN plans
@@ -546,7 +546,7 @@ improve this query, other than _not_ running it at all.
What is important here is that while some may recommend to straight up add an
index the moment you see a sequential scan, it is _much more important_ to first
understand what your query does, how much data it retrieves, and so on. After
-all, you can not optimize something you do not understand.
+all, you cannot optimize something you do not understand.
### Cardinality and selectivity
@@ -719,7 +719,7 @@ and through its [web interface](https://console.postgres.ai/gitlab/joe-instances
With Joe Bot you can execute DDL statements (like creating indexes, tables, and columns) and get query plans for `SELECT`, `UPDATE`, and `DELETE` statements.
-For example, in order to test new index on a column that is not existing on production yet, you can do the following:
+For example, to test new index on a column that is not existing on production yet, you can do the following:
Create the column:
diff --git a/doc/development/database/verifying_database_capabilities.md b/doc/development/database/verifying_database_capabilities.md
index 55347edf4ec..c1dd29082ba 100644
--- a/doc/development/database/verifying_database_capabilities.md
+++ b/doc/development/database/verifying_database_capabilities.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Verifying Database Capabilities
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 14d73437c36..58776c5330c 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Database Review Guidelines
@@ -240,9 +240,11 @@ Include in the MR description:
- Check queries timing (If any): In a single transaction, cumulative query time executed in a migration
needs to fit comfortably in `15s` - preferably much less than that - on GitLab.com.
- For column removals, make sure the column has been [ignored in a previous release](database/avoiding_downtime_in_migrations.md#dropping-columns)
-- Check [background migrations](database/background_migrations.md):
+- Check [batched background migrations](database/batched_background_migrations.md):
- Establish a time estimate for execution on GitLab.com. For historical purposes,
it's highly recommended to include this estimation on the merge request description.
+ This can be the number of expected batches times the delay interval.
+ - Manually trigger the [database testing](database/database_migration_pipeline.md) job (`db:gitlabcom-database-testing`) in the `test` stage.
- If a single `update` is below than `1s` the query can be placed
directly in a regular migration (inside `db/migrate`).
- Background migrations are normally used, but not limited to:
@@ -253,8 +255,6 @@ Include in the MR description:
it's suggested to treat background migrations as
[post migrations](migration_style_guide.md#choose-an-appropriate-migration-type):
place them in `db/post_migrate` instead of `db/migrate`.
- - If a migration [has tracking enabled](database/background_migrations.md#background-jobs-tracking),
- ensure `mark_all_as_succeeded` is called even if no work is done.
- Check [timing guidelines for migrations](migration_style_guide.md#how-long-a-migration-should-take)
- Check migrations are reversible and implement a `#down` method
- Check new table migrations:
diff --git a/doc/development/deleting_migrations.md b/doc/development/deleting_migrations.md
deleted file mode 100644
index 5d5ca431598..00000000000
--- a/doc/development/deleting_migrations.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'database/deleting_migrations.md'
-remove_date: '2022-07-08'
----
-
-This document was moved to [another location](database/deleting_migrations.md).
-
-<!-- This redirect file can be deleted after <2022-07-08>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/dependencies.md b/doc/development/dependencies.md
index 329539f0cc2..3b935ceba22 100644
--- a/doc/development/dependencies.md
+++ b/doc/development/dependencies.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependencies
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index 1e9d3ebda77..a940cd9404c 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deprecating GitLab features
diff --git a/doc/development/developing_with_solargraph.md b/doc/development/developing_with_solargraph.md
index d7e41187ace..7b9912a865e 100644
--- a/doc/development/developing_with_solargraph.md
+++ b/doc/development/developing_with_solargraph.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using Solargraph
diff --git a/doc/development/development_processes.md b/doc/development/development_processes.md
index 27ebe98bc63..10818b749ab 100644
--- a/doc/development/development_processes.md
+++ b/doc/development/development_processes.md
@@ -1,7 +1,7 @@
---
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Development processes
@@ -22,7 +22,7 @@ Must-reads:
Complementary reads:
-- [GitLab core team & GitLab Inc. contribution process](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md)
+- [Contribute to GitLab](contributing/index.md)
- [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer)
- [Patch release process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/process.md#process-for-developers)
- [Guidelines for implementing Enterprise Edition features](ee_features.md)
@@ -56,10 +56,10 @@ group. For example, if you're documenting a new internal API used exclusively by
a given group, request an engineering review from one of the group's members.
After the engineering review is complete, assign the MR to the
-[Technical Writer associated with the stage and group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+[Technical Writer associated with the stage and group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments)
in the modified documentation page's metadata.
If the page is not assigned to a specific group, follow the
-[Technical Writing review process for development guidelines](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines).
+[Technical Writing review process for development guidelines](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines).
#### Broader changes
@@ -79,12 +79,12 @@ In these cases, use the following workflow:
- [Frontend](https://about.gitlab.com/handbook/engineering/frontend/)
- [Backend](https://about.gitlab.com/handbook/engineering/)
- [Database](https://about.gitlab.com/handbook/engineering/development/database/)
- - [User Experience (UX)](https://about.gitlab.com/handbook/engineering/ux/)
+ - [User Experience (UX)](https://about.gitlab.com/handbook/product/ux/)
- [Security](https://about.gitlab.com/handbook/engineering/security/)
- [Quality](https://about.gitlab.com/handbook/engineering/quality/)
- [Engineering Productivity](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity/)
- [Infrastructure](https://about.gitlab.com/handbook/engineering/infrastructure/)
- - [Technical Writing](https://about.gitlab.com/handbook/engineering/ux/technical-writing/)
+ - [Technical Writing](https://about.gitlab.com/handbook/product/ux/technical-writing/)
You can skip this step for MRs authored by EMs or Staff Engineers responsible
for their area.
@@ -100,10 +100,10 @@ In these cases, use the following workflow:
@clefelhocz1.
1. After all approvals are complete, assign the MR to the
- [Technical Writer associated with the stage and group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+ [Technical Writer associated with the stage and group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments)
in the modified documentation page's metadata.
If the page is not assigned to a specific group, follow the
- [Technical Writing review process for development guidelines](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines).
+ [Technical Writing review process for development guidelines](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines).
The Technical Writer may ask for additional approvals as previously suggested before merging the MR.
### Reviewer values
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index 5f03ba93a4d..b38fcea4f00 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with diffs
@@ -148,7 +148,7 @@ This limit is hardcoded and only applied on GitLab.
Diff Viewers, which can be found on `models/diff_viewer/*` are classes used to map metadata about each type of Diff File. It has information
whether it's a binary, which partial should be used to render it or which File extensions this class accounts for.
-`DiffViewer::Base` validates _blobs_ (old and new versions) content, extension and file type in order to check if it can be rendered.
+`DiffViewer::Base` validates _blobs_ (old and new versions) content, extension and file type to check if it can be rendered.
## Merge request diffs against the `HEAD` of the target branch
@@ -169,7 +169,7 @@ In order to display an up-to-date diff, in GitLab 12.9 we
[introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27008) merge request
diffs compared against `HEAD` of the target branch: the
target branch is artificially merged into the source branch, then the resulting
-merge ref is compared to the source branch in order to calculate an accurate
+merge ref is compared to the source branch to calculate an accurate
diff.
Until we complete the epics ["use merge refs for diffs"](https://gitlab.com/groups/gitlab-org/-/epics/854)
diff --git a/doc/development/directory_structure.md b/doc/development/directory_structure.md
index f909fda897f..27384fa559f 100644
--- a/doc/development/directory_structure.md
+++ b/doc/development/directory_structure.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Backend directory structure
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 9d62f2061ca..0ca10bc93dd 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Distributed Tracing - development guidelines **(FREE)**
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 87d2930dcb5..dae62fea603 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -1,5 +1,5 @@
---
-info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
stage: none
group: unassigned
description: "GitLab development - how to document features deployed behind feature flags"
@@ -34,7 +34,7 @@ Possible version history entries are:
> - [Enabled on GitLab.com](issue-link) in GitLab X.X.
> - [Enabled on GitLab.com](issue-link) in GitLab X.X. Available to GitLab.com administrators only.
> - [Enabled on self-managed](issue-link) in GitLab X.X.
-> - [Generally available](issue-link) in GitLab X.Y. [Feature flag `flag_name`](issue-link) removed.
+> - [Generally available](issue-link) in GitLab X.Y. Feature flag `flag_name` removed.
```
You can combine entries if they happened in the same release:
@@ -115,5 +115,5 @@ And, when the feature is done and fully available to all users:
> - 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) 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 `forti_token_cloud`](issue-link) removed.
+> - [Generally available](issue-link) in GitLab 14.0. Feature flag `forti_token_cloud` removed.
```
diff --git a/doc/development/documentation/graphql_styleguide.md b/doc/development/documentation/graphql_styleguide.md
index ad19a40a3f5..1bd8b37ff5f 100644
--- a/doc/development/documentation/graphql_styleguide.md
+++ b/doc/development/documentation/graphql_styleguide.md
@@ -2,7 +2,7 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
description: "Writing styles, markup, formatting, and other standards for GraphQL API's GitLab Documentation."
---
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 73c1874f09e..c52b3b5adae 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: Documentation Guidelines
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how to contribute to GitLab Documentation.
---
@@ -94,7 +94,7 @@ belongs to, as well as an information block as described below:
```plaintext
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
+ https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
```
For example:
@@ -103,7 +103,7 @@ For example:
---
stage: Example Stage
group: Example Group
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
```
@@ -171,7 +171,7 @@ contains an array of groups and their assigned technical writer. This task:
To prepare an update to the `CODEOWNERS` file:
-1. Update `lib/tasks/gitlab/tw/codeowners.rake` with the latest [TW team assignments](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+1. Update `lib/tasks/gitlab/tw/codeowners.rake` with the latest [TW team assignments](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
Make this update in a standalone merge request, as it runs a long pipeline and
requires backend maintainer review. Make sure this is merged before you update
`CODEOWNERS` in another merge request.
@@ -465,7 +465,7 @@ RSpec.describe '<What I am taking screenshots of>', :js do
#### Full page screenshots
-To take a full page screenshot simply `visit the page` and perform any expectation on real content (to have capybara wait till the page is ready and not take a white screenshot).
+To take a full page screenshot, `visit the page` and perform any expectation on real content (to have capybara wait till the page is ready and not take a white screenshot).
#### Element screenshot
diff --git a/doc/development/documentation/redirects.md b/doc/development/documentation/redirects.md
index 1bc697f2878..1118dc97926 100644
--- a/doc/development/documentation/redirects.md
+++ b/doc/development/documentation/redirects.md
@@ -1,7 +1,7 @@
---
stage: none
group: Documentation Guidelines
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how to contribute to GitLab Documentation.
---
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index 2991c1b3224..dc84f3a08dd 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -1,5 +1,5 @@
---
-info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
stage: none
group: unassigned
description: 'Writing styles, markup, formatting, and other standards for the GitLab RESTful APIs.'
diff --git a/doc/development/documentation/review_apps.md b/doc/development/documentation/review_apps.md
index a50efceb307..cb04f0909c1 100644
--- a/doc/development/documentation/review_apps.md
+++ b/doc/development/documentation/review_apps.md
@@ -1,7 +1,7 @@
---
stage: none
group: Documentation Guidelines
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how documentation review apps work.
---
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index 8a9c2e1e8d7..b5c3a59b0eb 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Documentation deployments
diff --git a/doc/development/documentation/site_architecture/folder_structure.md b/doc/development/documentation/site_architecture/folder_structure.md
index 7f29d3fba9e..8a1d9b9fee3 100644
--- a/doc/development/documentation/site_architecture/folder_structure.md
+++ b/doc/development/documentation/site_architecture/folder_structure.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Folder structure for documentation
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index 05e697869b9..37d10b16fcd 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Learn how GitLab docs' global navigation works and how to add new items."
---
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 44e4aac2756..d4553614fad 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Documentation site architecture
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index bc79bf0fbe2..d629bc0b87e 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -1,5 +1,5 @@
---
-info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
stage: none
group: unassigned
description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
@@ -17,9 +17,9 @@ In addition to this page, the following resources can help you craft and contrib
- [Doc contribution guidelines](../index.md)
- [Recommended word list](word_list.md)
- [Doc style and consistency testing](../testing.md)
-- [UI text guidelines](https://design.gitlab.com/content/error-messages/)
+- [Guidelines for UI error messages](https://design.gitlab.com/content/error-messages/)
- [GitLab Handbook style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
-- [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/)
+- [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/)
- [Google Developer Documentation Style Guide](https://developers.google.com/style)
- [Recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix)
@@ -115,7 +115,7 @@ 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](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+mentioning [the writer for](https://about.gitlab.com/handbook/product/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
@@ -333,7 +333,7 @@ When possible, try to avoid acronyms in headings.
### Numbers
-When using numbers in text, spell out zero through nine, and use numbers for 10 and greater. For details, see the [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/numbers).
+When using numbers in text, spell out zero through nine, and use numbers for 10 and greater. For details, see the [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/numbers).
## Text
@@ -465,10 +465,18 @@ When using code block style:
## Lists
-- Always start list items with a capital letter, unless they're parameters or
- commands that are in backticks, or similar.
-- Always leave a blank line before and after a list.
-- Begin a line with spaces (not tabs) to denote a [nested sub-item](#nesting-inside-a-list-item).
+- Use a period after every sentence, including those that complete an introductory phrase.
+ Do not use semicolons or commas.
+- Majority rules. Use either full sentences or all fragments. Avoid a mix.
+- Always start list items with a capital letter.
+- Separate the introductory phrase from explanatory text with a colon (`:`). For example:
+
+ ```markdown
+ You can:
+
+ - Do this thing.
+ - Do this other thing.
+ ```
### Choose between an ordered or unordered list
@@ -492,40 +500,27 @@ These things are imported:
- Thing 3
```
-You can choose to introduce either list with a colon, but you do not have to.
-
-### Markup
+### List markup
- Use dashes (`-`) for unordered lists instead of asterisks (`*`).
-- Prefix `1.` to every item in an ordered list. When rendered, the list items
- display with sequential numbering.
-
-### Punctuation
-
-- Don't add commas (`,`) or semicolons (`;`) to the ends of list items.
-- If a list item is a complete sentence (with a subject and a verb), add a period at the end.
-- Majority rules. If the majority of items do not end in a period, do not end any of the items in a period.
-- Separate list items from explanatory text with a colon (`:`). For example:
-
- ```markdown
- The list is as follows:
-
- - First item: this explains the first item.
- - Second item: this explains the second item.
- ```
+- Start every item in an ordered list with `1.`. When rendered, the list items
+ are sequential.
+- Leave a blank line before and after a list.
+- Begin a line with spaces (not tabs) to denote a [nested sub-item](#nesting-inside-a-list-item).
### Nesting inside a list item
-It's possible to nest items under a list item, so that they render with the same
-indentation as the list item. This can be done with:
+You can nest items under a list item, so they render with the same
+indentation as the list item. You can do this with:
- [Code blocks](#code-blocks)
- [Blockquotes](#blockquotes)
- [Alert boxes](#alert-boxes)
- [Images](#images)
+- [Tabs](#tabs)
-Items nested in lists should always align with the first character of the list
-item. In unordered lists (using `-`), this means two spaces for each level of
+Nested items should always align with the first character of the list
+item. For unordered lists (using `-`), use two spaces for each level of
indentation:
````markdown
@@ -555,26 +550,9 @@ For ordered lists, use three spaces for each level of indentation:
1. Ordered list item 1
A line nested using 3 spaces to align with the `O` above.
-
-1. Ordered list item 2
-
- > A quote block that will nest
- > inside list item 2.
-
-1. Ordered list item 3
-
- ```plaintext
- a code block that nests inside list item 3
- ```
-
-1. Ordered list item 4
-
- ![an image that will nest inside list item 4](image.png)
````
-You can nest full lists inside other lists using the same rules as above. If you
-want to mix types, that's also possible, if you don't mix items at the same
-level:
+You can nest lists in other lists.
```markdown
1. Ordered list item one.
@@ -676,125 +654,66 @@ For other punctuation rules, refer to the
[Pajamas Design System Punctuation section](https://design.gitlab.com/content/punctuation/).
This is overridden by the [documentation-specific punctuation rules](#punctuation).
-### Anchor links
+## Links
-Headings generate anchor links when rendered. `## This is an example` generates
-the anchor `#this-is-an-example`.
+Links help the docs adhere to the
+[single source of truth](#documentation-is-the-single-source-of-truth-ssot) principle.
-NOTE:
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39717) in
-GitLab 13.4, [product badges](#product-tier-badges) used in headings aren't
-included in the generated anchor links. For example, when you link to
-`## This is an example **(FREE)**`, use the anchor `#this-is-an-example`.
+### Links within the same repository
-Keep in mind that the GitLab user interface links to many documentation pages
-and anchor links to take the user to the right spot. When you change
-a heading, search `doc/*`, `app/views/*`, and `ee/app/views/*` for the old
-anchor. If you do not fix these links, the [`ui-docs-lint` job](../testing.md#ui-link-tests)
-in your merge request fails.
-
-Important:
+To link to another page in the same repository,
+use a relative file path. For example, `../user/gitlab_com/index.md`.
-- Avoid crosslinking documentation to headings unless you need to link to a
- specific section of the document. This avoids breaking anchors in the
- future in case the heading is changed.
-- If possible, avoid changing headings, because they're not only linked internally.
- There are various links to GitLab documentation on the internet, such as
- tutorials, presentations, StackOverflow posts, and other sources.
-- Do not link to `h1` headings.
+Use inline link Markdown markup `[Text](https://example.com)`,
+rather than reference-style links, like `[Text][identifier]`.
-Note that with Kramdown, it's possible to add a custom ID to an HTML element
-with Markdown markup, but they don't work in `/help`. Because of this, don't use
-this option.
+Put the entire link on a single line so that [linters](../testing.md) can find it.
-## Links
+### Links in separate repositories
-Links are important in GitLab documentation. Use links instead of
-summarizing to help preserve a [single source of truth](#documentation-is-the-single-source-of-truth-ssot)
-in GitLab documentation.
-
-We include guidance for links in these categories:
-
-- How to set up [anchor links](#anchor-links) for headings.
-- How to set up [criteria](#basic-link-criteria) for configuring a link.
-- What to set up when [linking to a `help`](../../documentation/index.md#linking-to-help)
- page.
-- How to set up [links to internal documentation](#links-to-internal-documentation)
- for cross-references.
-- How to set up [links to external documentation](#links-to-external-documentation)
- for authoritative sources.
-- When to use [links requiring permissions](#links-requiring-permissions).
-- How to set up a [link to a video](#link-to-video).
-- How to [link to specific lines of code](#link-to-specific-lines-of-code)
-
-### Basic link criteria
-
-- Use inline link Markdown markup `[Text](https://example.com)`.
- It's easier to read, review, and maintain. Do not use `[Text][identifier]` reference-style links.
-- Use meaningful anchor text.
- For example, instead of writing something like `Read more about merge requests [here](LINK)`,
- write `Read more about [merge requests](LINK)`.
-- Put the entire link on a single line. Some of our [linters](../testing.md) do not
- validate links when split over multiple lines, and incorrect or broken links could
- slip through.
-
-### Links to internal documentation
+To link to a page in a different repository, use an absolute URL.
+For example, to link from a page in the GitLab repo to the Charts repo,
+use a URL like `https://docs.gitlab.com/charts/`.
-NOTE:
-**Internal** refers to documentation in the same project. When linking to
-documentation in separate projects (for example, linking to Omnibus documentation
-from GitLab documentation), you must use absolute URLs.
+### Anchor links
-Do not use absolute URLs like `https://docs.gitlab.com/ee/index.html` to
-cross-link to other documentation in the same project. Use relative links to
-the file, like `../index.md`. (These are converted to HTML when the site is
-rendered.)
+Each heading has an anchor link. For example, a topic with the title
+`## This is an example` has the anchor `#this-is-an-example`.
-Relative linking enables crosslinks to work:
+The first topic on a page (the `h1`) has an anchor link,
+but do not use it. Link to the page instead.
-- in Review Apps, local previews, and `/help`.
-- when working on the documentation locally, so you can verify that they work as
- early as possible in the process.
-- in the GitLab user interface when browsing doc files in their respective
- repositories. For example, the links displayed at
- `https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md`.
+If a heading has a [product tier badge](#product-tier-badges),
+do not include it in the anchor link. For example, for the heading
+`## This is an example **(FREE)**`, use the anchor `#this-is-an-example`.
-To link to internal documentation:
+With Kramdown, you can add a custom ID to an HTML element, but these IDs
+don't work in `/help`, so you should not use them.
-- Use relative links to Markdown files in the same repository.
-- Do not use absolute URLs or URLs from `docs.gitlab.com`.
-- Use `../` to navigate to higher-level directories.
-- Don't prepend `./` to links to files or directories. To link to a file in the
- same directory or one of its sub-directories, use the syntax `path/to/file.md`.
-- Don't link relative to root. For example, `/ee/user/gitlab_com/index.md`.
+#### Changing links and titles
- Don't:
+When you change a heading, the anchor link changes. To ensure you update
+any related links, search these directories:
- - `https://docs.gitlab.com/ee/administration/geo/replication/troubleshooting.html`
- - `/ee/administration/geo/replication/troubleshooting.md`
- - `./troubleshooting.md`
+- `doc/*`
+- `app/views/*`
+- `ee/app/views/*`
- Do: `../../geo/replication/troubleshooting.md`
+If you do not fix these links, the [`ui-docs-lint` job](../testing.md#ui-link-tests)
+in your merge request fails.
-- Always add the filename `file.md` at the end of the link with the `.md`
- extension, not `.html`.
+### Text for links
- Don't:
+Use descriptive text for links, rather than words like `here` or `this page.`
- - `../../merge_requests/`
- - `../../issues/tags.html`
- - `../../issues/tags.html#stages`
+For example, instead of:
- Do:
+- `For more information, see [this page](LINK).`
+- `For more information, go [here](LINK).`
- - `../../merge_requests/index.md`
- - `../../issues/tags.md`
- - `../../issues/tags.md#stages`
- - `issues/tags.md`
+Use:
-NOTE:
-Using the Markdown extension is necessary for the [`/help`](../index.md#gitlab-help)
-section of GitLab.
+- `For more information, see [merge requests](LINK)`.
### Links to external documentation
@@ -900,6 +819,28 @@ To open group settings:
1. Expand **General pipelines**.
```
+To open either project or group settings:
+
+```markdown
+1. On the top bar, select **Main menu**, and:
+ - For a project, select ***Projects** and find your project.
+ - For a group, select **Groups** and find your group.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **General pipelines**.
+```
+
+To create a project:
+
+```markdown
+1. On the top bar, select **Create new... > New project**.
+```
+
+To create a group:
+
+```markdown
+1. On the top bar, select **Create new... > New group**.
+```
+
To open the Admin Area:
```markdown
@@ -1127,6 +1068,14 @@ Do not use words to describe the icon:
- Avoid: `Select **Erase job log** (the trash icon).`
- Use instead: `Select **Erase job log** (**{remove}**).` This generates as: Select **Erase job log** (**{remove}**).
+When the button doesn't have any hover text, you can describe the icon.
+Follow up by creating a
+[UX bug issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Bug)
+to add hover text to the button to improve accessibility.
+
+- Avoid: `Select **{ellipsis_v}**.`
+- Use instead: `Select the vertical ellipsis (**{ellipsis_v}**).` This generates as: Select the vertical ellipsis (**{ellipsis_v}**).
+
## Videos
Adding GitLab YouTube video tutorials to the documentation is highly
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index 029c7389290..65ad8dea688 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
---
@@ -17,7 +17,7 @@ recommends these word choices. In addition:
For guidance not on this page, we defer to these style guides:
-- [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/)
+- [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/)
- [Google Developer Documentation Style Guide](https://developers.google.com/style)
<!-- vale off -->
@@ -125,7 +125,7 @@ Instead of:
- 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).
+[View details in the Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows).
## Alpha
@@ -141,7 +141,7 @@ Instead of **and/or**, use **or** or rewrite the sentence to spell out both opti
## and so on
Do not use **and so on**. Instead, be more specific. For details, see
-[the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/and-so-on).
+[the Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/and-so-on).
## area
@@ -218,7 +218,7 @@ Instead of:
## cannot, can not
-Use **cannot** instead of **can not**. You can also use **can't**.
+Use **cannot** instead of **can not**.
See also [contractions](index.md#contractions).
@@ -316,7 +316,7 @@ Do not use **Developer permissions**. A user who is assigned the Developer role
## disable
-See [the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/d/disable-disabled) for guidance on **disable**.
+See [the Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/d/disable-disabled) for guidance on **disable**.
Use **inactive** or **off** instead. ([Vale](../testing.md#vale) rule: [`InclusionAbleism.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionAbleism.yml))
## disallow
@@ -363,9 +363,13 @@ Do not use Latin abbreviations. Use **for example**, **such as**, **for instance
Do not use **e-mail** with a hyphen. When plural, use **emails** or **email messages**. ([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+## emojis
+
+Use **emojis** to refer to the plural form of **emoji**.
+
## enable
-See [the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/e/enable-enables) for guidance on **enable**.
+See [the Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/e/enable-enables) for guidance on **enable**.
Use **active** or **on** instead. ([Vale](../testing.md#vale) rule: [`InclusionAbleism.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionAbleism.yml))
## enter
@@ -509,13 +513,16 @@ For example, **Snowplow Guide**. Instead, speak about the feature itself, and ho
When writing about the Guest role:
- Use a capital **G**.
-- Do not use bold.
-- 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:
+- Write it out:
+ - Use: if you are assigned the Guest role
+ - Instead of: if you are a guest
+
+- When the Guest role is the minimum required role:
- Use: at least the Guest role
- Instead of: the Guest role or higher
+Do not use bold.
+
Do not use **Guest permissions**. A user who is assigned the Guest role has a set of associated permissions.
## handy
@@ -656,13 +663,16 @@ Instead of:
When writing about the Maintainer role:
- Use a capital **M**.
-- Do not use bold.
-- 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:
+- Write it out.
+ - Use: if you are assigned the Maintainer role
+ - Instead of: if you are a maintainer
+
+- When the Maintainer role is the minimum required role:
- Use: at least the Maintainer role
- Instead of: the Maintainer role or higher
+Do not use bold.
+
Do not use **Maintainer permissions**. A user who is assigned the Maintainer role has a set of associated permissions.
## mankind
@@ -796,11 +806,14 @@ For example, a log file might overwrite a log file of the same name.
When writing about the Owner role:
- Use a capital **O**.
-- Do not use bold.
-- Do not use the phrase, **if you are an owner** to mean someone who is assigned the Owner
- role. Instead, write it out. For example, **if you are assigned the Owner role**.
+- Write it out.
+ - Use: if you are assigned the Owner role
+ - Instead of: if you are an owner
+Do not use bold.
+
Do not use **Owner permissions**. A user who is assigned the Owner role has a set of associated permissions.
+An Owner is the highest role a user can have.
## Package Registry
@@ -818,7 +831,7 @@ Use lowercase for **personal access token**.
## please
-Do not use **please**. For details, see the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please).
+Do not use **please**. For details, see the [Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please).
## press
@@ -851,13 +864,16 @@ Use **register** instead of **sign up** when talking about creating an account.
When writing about the Reporter role:
- Use a capital **R**.
-- Do not use bold.
-- 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:
+- Write it out.
+ - Use: if you are assigned the Reporter role
+ - Instead of: if you are a reporter
+
+- When the Reporter role is the minimum required role:
- Use: at least the Reporter role
- Instead of: the Reporter role or higher
+Do not use bold.
+
Do not use **Reporter permissions**. A user who is assigned the Reporter role has a set of associated permissions.
## Repository Mirroring
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 59a078bdec0..c801bb9f877 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -1,7 +1,7 @@
---
stage: none
group: Documentation Guidelines
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how to contribute to GitLab Documentation.
---
diff --git a/doc/development/documentation/topic_types/concept.md b/doc/development/documentation/topic_types/concept.md
index a20bb93a97f..dfd003b642d 100644
--- a/doc/development/documentation/topic_types/concept.md
+++ b/doc/development/documentation/topic_types/concept.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Concept topic type
diff --git a/doc/development/documentation/topic_types/index.md b/doc/development/documentation/topic_types/index.md
index af3e66fe87a..8403fd26517 100644
--- a/doc/development/documentation/topic_types/index.md
+++ b/doc/development/documentation/topic_types/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Documentation topic types (CTRT)
diff --git a/doc/development/documentation/topic_types/reference.md b/doc/development/documentation/topic_types/reference.md
index 42f4f5f6f94..e7ee8b20925 100644
--- a/doc/development/documentation/topic_types/reference.md
+++ b/doc/development/documentation/topic_types/reference.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reference topic type
diff --git a/doc/development/documentation/topic_types/task.md b/doc/development/documentation/topic_types/task.md
index 3488cb90cf9..60508fbf6ee 100644
--- a/doc/development/documentation/topic_types/task.md
+++ b/doc/development/documentation/topic_types/task.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Task topic type
diff --git a/doc/development/documentation/topic_types/troubleshooting.md b/doc/development/documentation/topic_types/troubleshooting.md
index 35187bd892e..e2136de2e06 100644
--- a/doc/development/documentation/topic_types/troubleshooting.md
+++ b/doc/development/documentation/topic_types/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: none
group: Style Guide
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting topic type
diff --git a/doc/development/documentation/versions.md b/doc/development/documentation/versions.md
index 85733603cfe..12381b84c2c 100644
--- a/doc/development/documentation/versions.md
+++ b/doc/development/documentation/versions.md
@@ -1,5 +1,5 @@
---
-info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
stage: none
group: unassigned
description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
@@ -139,7 +139,7 @@ To remove a page:
---
stage: Data Stores
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
+ info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
remove_date: '2022-08-02'
redirect_to: '../newpath/to/file/index.md'
---
@@ -154,7 +154,7 @@ To remove a page:
1. Remove the page's entry from the global navigation by editing [`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/content/_data/navigation.yaml) in `gitlab-docs`.
This content is removed from the documentation as part of the Technical Writing team's
-[regularly scheduled tasks](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#regularly-scheduled-tasks).
+[regularly scheduled tasks](https://about.gitlab.com/handbook/product/ux/technical-writing/#regularly-scheduled-tasks).
### Remove a topic
@@ -179,7 +179,7 @@ To remove a topic:
```
This content is removed from the documentation as part of the Technical Writing team's
-[regularly scheduled tasks](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#regularly-scheduled-tasks).
+[regularly scheduled tasks](https://about.gitlab.com/handbook/product/ux/technical-writing/#regularly-scheduled-tasks).
## Which versions are removed
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index fb43a2e995a..85d3d5e9cfc 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# How to update GitLab documentation
@@ -13,7 +13,7 @@ Anyone can contribute to the GitLab documentation! You can create a merge reques
accomplish their work with GitLab.
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).
+[feature workflow process described in the GitLab Handbook](https://about.gitlab.com/handbook/product/ux/technical-writing/workflow/#for-a-product-change).
## How to update the docs
@@ -54,7 +54,7 @@ Ask for help from the Technical Writing team if you:
To identify someone who can help you:
1. Locate the Technical Writer for the relevant
- [DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+ [DevOps stage group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
1. Either:
- If urgent help is required, directly assign the Technical Writer in the issue or in the merge request.
- If non-urgent help is required, ping the Technical Writer in the issue or merge request.
@@ -86,7 +86,7 @@ merge documentation changes. Maintainers must make a good-faith effort to ensure
- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide/index.md).
If the author or reviewer has any questions, they can mention the writer who is assigned to the relevant
-[DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+[DevOps stage group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
The process involves the following:
@@ -96,7 +96,7 @@ The process involves the following:
- Technical Writer (Optional). If not completed for a merge request before merging, must be scheduled
post-merge. Schedule post-merge reviews only if an urgent merge is required. To request a:
- Pre-merge review, assign the Technical Writer listed for the applicable
- [DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
+ [DevOps stage group](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments).
- Post-merge review, see [Post-merge reviews](#post-merge-reviews).
- Maintainer. For merge requests, Maintainers:
- Can always request any of the above reviews.
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 869cb0bab0a..2516196d2e0 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Guidelines for implementing Enterprise Edition features
@@ -72,7 +72,7 @@ To guard your licensed feature:
```
1. Optional. If your global feature is also available to namespaces with a paid plan, combine two
-feature identifiers to allow both admins and group users. For example:
+feature identifiers to allow both administrators and group users. For example:
```ruby
License.feature_available?(:my_feature_name) || group.licensed_feature_available?(:my_feature_name_for_namespace) # Both admins and group members can see this EE feature
@@ -176,12 +176,19 @@ This works because for every path that is present in CE's eager-load/auto-load
paths, we add the same `ee/`-prepended path in [`config/application.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/925d3d4ebc7a2c72964ce97623ae41b8af12538d/config/application.rb#L42-52).
This also applies to views.
-#### Testing EE-only features
+#### Testing EE-only backend features
To test an EE class that doesn't exist in CE, create the spec file as you normally
would in the `ee/spec` directory, but without the second `ee/` subdirectory.
For example, a class `ee/app/models/vulnerability.rb` would have its tests in `ee/spec/models/vulnerability_spec.rb`.
+By default, licensed features are disabled while specs are running. To effectively test your feature
+you must explicitly enable the feature using the `stub_licensed_features` helper, for example:
+
+```ruby
+ stub_licensed_features(my_awesome_feature_name: true)
+```
+
### Extend CE features with EE backend code
For features that build on existing CE features, write a module in the `EE`
@@ -817,7 +824,7 @@ end
Sometimes we need EE-specific behavior in some of the APIs. Normally we could
use EE methods to override CE methods, however API routes are not methods and
-therefore can't be simply overridden. We need to extract them into a standalone
+therefore cannot be overridden. We need to extract them into a standalone
method, or introduce some "hooks" where we could inject behavior in the CE
route. Something like this:
@@ -868,8 +875,8 @@ end
#### EE `route_setting`
-It's very hard to extend this in an EE module, and this is simply storing
-some meta-data for a particular route. Given that, we could simply leave the
+It's very hard to extend this in an EE module, and this is storing
+some meta-data for a particular route. Given that, we could leave the
EE `route_setting` in CE as it doesn't hurt and we don't use
those meta-data in CE.
@@ -1047,7 +1054,7 @@ FactoryBot.define do
end
```
-## Separate of EE code in the frontend
+## Separation of EE code in the frontend
To separate EE-specific JS-files, move the files into an `ee` folder.
@@ -1089,10 +1096,13 @@ ee/app/assets/javascripts/ee_only_feature/index.js
Feature guarding `licensed_feature_available?` and `License.feature_available?` typical
occurs in the controller, as described in the [backend guide](#ee-only-features).
-#### Test EE-only features
+#### Testing EE-only frontend features
Add your EE tests to `ee/spec/frontend/` following the same directory structure you use for CE.
+Check the note under [Testing EE-only backend features](#testing-ee-only-backend-features) regarding
+enabling licensed features.
+
### Extend CE features with EE frontend code
Use the [`push_licensed_feature`](#guard-your-ee-feature) to guard frontend features that extend
@@ -1406,5 +1416,5 @@ to avoid conflicts during CE to EE merge.
### GitLab-svgs
Conflicts in `app/assets/images/icons.json` or `app/assets/images/icons.svg` can
-be resolved simply by regenerating those assets with
+be resolved by regenerating those assets with
[`yarn run svg`](https://gitlab.com/gitlab-org/gitlab-svgs).
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index b3996e16fa1..ab2d241a781 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Elasticsearch knowledge **(PREMIUM SELF)**
@@ -64,7 +64,7 @@ Please see the `sha_tokenizer` explanation later below for an example.
Used when indexing a blob's filename and content. Uses the `whitespace` tokenizer and the filters: [`code`](#code), `lowercase`, and `asciifolding`
-The `whitespace` tokenizer was selected in order to have more control over how tokens are split. For example the string `Foo::bar(4)` needs to generate tokens like `Foo` and `bar(4)` in order to be properly searched.
+The `whitespace` tokenizer was selected to have more control over how tokens are split. For example the string `Foo::bar(4)` needs to generate tokens like `Foo` and `bar(4)` to be properly searched.
Please see the `code` filter for an explanation on how tokens are split.
@@ -94,7 +94,7 @@ Example:
#### `path_tokenizer`
-This is a custom tokenizer that uses the [`path_hierarchy` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pathhierarchy-tokenizer.html) with `reverse: true` in order to allow searches to find paths no matter how much or how little of the path is given as input.
+This is a custom tokenizer that uses the [`path_hierarchy` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pathhierarchy-tokenizer.html) with `reverse: true` to allow searches to find paths no matter how much or how little of the path is given as input.
Example:
@@ -461,8 +461,8 @@ _from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.
The use of Elasticsearch in GitLab is only ever as a secondary data store.
This means that all of the data stored in Elasticsearch can always be derived
again from other data sources, specifically PostgreSQL and Gitaly. Therefore if
-the Elasticsearch data store is ever corrupted for whatever reason you can
-simply reindex everything from scratch.
+the Elasticsearch data store is ever corrupted for whatever reason you can reindex
+everything from scratch.
If your Elasticsearch index is incredibly large it may be too time consuming or
cause too much downtime to reindex from scratch. There aren't any built in
diff --git a/doc/development/emails.md b/doc/development/emails.md
index c997916aa21..2d03d8bca2f 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with email in development
@@ -176,7 +176,7 @@ in the Helm Chart configuration rather than the `Gemfile`.
#### Preserving backwards compatibility
-Removing the `Gemfile` would break incoming e-mail processing for source
+Removing the `Gemfile` would break incoming email processing for source
installs. For now, source installs are advised to upgrade manually to
the version specified in Omnibus and run `bin/mail_room` directly as
done with Omnibus.
diff --git a/doc/development/event_store.md b/doc/development/event_store.md
index 37035083e23..b9200d3be25 100644
--- a/doc/development/event_store.md
+++ b/doc/development/event_store.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab EventStore
diff --git a/doc/development/experiment_guide/experiment_code_reviews.md b/doc/development/experiment_guide/experiment_code_reviews.md
index 07bc0f59463..7242acfbdcf 100644
--- a/doc/development/experiment_guide/experiment_code_reviews.md
+++ b/doc/development/experiment_guide/experiment_code_reviews.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Experiment code reviews
diff --git a/doc/development/experiment_guide/experiment_rollout.md b/doc/development/experiment_guide/experiment_rollout.md
index e68520f7812..b2e1b1168d3 100644
--- a/doc/development/experiment_guide/experiment_rollout.md
+++ b/doc/development/experiment_guide/experiment_rollout.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Experiment rollouts and feature flags
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
deleted file mode 100644
index 5ddbe9b3de9..00000000000
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'index.md'
-remove_date: '2022-08-05'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after 2022-08-05. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/experiment_guide/implementing_experiments.md b/doc/development/experiment_guide/implementing_experiments.md
index 19200d48637..e1407473731 100644
--- a/doc/development/experiment_guide/implementing_experiments.md
+++ b/doc/development/experiment_guide/implementing_experiments.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Implementing an A/B/n experiment
@@ -136,7 +136,7 @@ somewhat abstract and hard to understand initially, but this approach enables us
communicate about experiments as something that's wider than just user behavior.
NOTE:
-Using `actor:` utilizes cookies if the `current_user` is nil. If you don't need
+Using `actor:` uses cookies if the `current_user` is nil. If you don't need
cookies though - meaning that the exposed functionality would only be visible to
signed in users - `{ user: current_user }` would be just as effective.
@@ -318,7 +318,7 @@ Given that we've defined a class for our experiment, and have defined the varian
The first way is by running the experiment. Assuming the experiment has been run, it surfaces in the client layer without having to do anything special.
-The second way doesn't run the experiment and is intended to be used if the experiment must only surface in the client layer. To accomplish this we can `.publish` the experiment. This does not run any logic, but does surface the experiment details in the client layer so they can be utilized there.
+The second way doesn't run the experiment and is intended to be used if the experiment must only surface in the client layer. To accomplish this we can `.publish` the experiment. This does not run any logic, but does surface the experiment details in the client layer so they can be used there.
An example might be to publish an experiment in a `before_action` in a controller. Assuming we've defined the `PillColorExperiment` class, like we have above, we can surface it to the client by publishing it instead of running it:
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 500a19fe1ad..e185cd702a4 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Experiment Guide
diff --git a/doc/development/experiment_guide/testing_experiments.md b/doc/development/experiment_guide/testing_experiments.md
index 78a5d606490..2e88029a27f 100644
--- a/doc/development/experiment_guide/testing_experiments.md
+++ b/doc/development/experiment_guide/testing_experiments.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Testing experiments
diff --git a/doc/development/export_csv.md b/doc/development/export_csv.md
index 29e80f676da..5d35c880ffd 100644
--- a/doc/development/export_csv.md
+++ b/doc/development/export_csv.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Export to CSV
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index bdd6c5d6e84..67166a93cb4 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Accessibility
@@ -68,9 +68,9 @@ We should ensure that:
To provide markup with accessible names, ensure every:
-- `input` has an associated `label`.
-- `button` and `a` have child text, or `aria-label` when child text isn't present, such as for an icon button with no content.
-- `img` has an `alt` attribute.
+- input has an [associated `label`](#examples-of-providing-accessible-names).
+- button and link have [visible text](#buttons-and-links-with-descriptive-accessible-names), or `aria-label` when there is no visible text, such as for an icon button with no content.
+- image has an [`alt` attribute](#images-with-accessible-names).
- `fieldset` has `legend` as its first child.
- `figure` has `figcaption` as its first child.
- `table` has `caption` as its first child.
@@ -100,12 +100,12 @@ Text input examples:
```html
<!-- Input with label -->
<gl-form-group :label="__('Issue title')" label-for="issue-title">
- <gl-form-input id="issue-title" v-model="title" name="title" />
+ <gl-form-input id="issue-title" v-model="title" />
</gl-form-group>
<!-- Input with hidden label -->
-<gl-form-group :label="__('Issue title')" label-for="issue-title" :label-sr-only="true">
- <gl-form-input id="issue-title" v-model="title" name="title" />
+<gl-form-group :label="__('Issue title')" label-for="issue-title" label-sr-only>
+ <gl-form-input id="issue-title" v-model="title" />
</gl-form-group>
```
@@ -114,12 +114,12 @@ Textarea examples:
```html
<!-- Textarea with label -->
<gl-form-group :label="__('Issue description')" label-for="issue-description">
- <gl-form-textarea id="issue-description" v-model="description" name="description" />
+ <gl-form-textarea id="issue-description" v-model="description" />
</gl-form-group>
<!-- Textarea with hidden label -->
-<gl-form-group :label="__('Issue description')" label-for="issue-description" :label-sr-only="true">
- <gl-form-textarea id="issue-description" v-model="description" name="description" />
+<gl-form-group :label="__('Issue description')" label-for="issue-description" label-sr-only>
+ <gl-form-textarea id="issue-description" v-model="description" />
</gl-form-group>
```
@@ -128,11 +128,11 @@ Alternatively, you can use a plain `label` element:
```html
<!-- Input with label using `label` -->
<label for="issue-title">{{ __('Issue title') }}</label>
-<gl-form-input id="issue-title" v-model="title" name="title" />
+<gl-form-input id="issue-title" v-model="title" />
<!-- Input with hidden label using `label` -->
<label for="issue-title" class="gl-sr-only">{{ __('Issue title') }}</label>
-<gl-form-input id="issue-title" v-model="title" name="title" />
+<gl-form-input id="issue-title" v-model="title" />
```
#### Select inputs with accessible names
@@ -142,12 +142,12 @@ Select input examples:
```html
<!-- Select input with label -->
<gl-form-group :label="__('Issue status')" label-for="issue-status">
- <gl-form-select id="issue-status" v-model="status" name="status" :options="options" />
+ <gl-form-select id="issue-status" v-model="status" :options="options" />
</gl-form-group>
<!-- Select input with hidden label -->
-<gl-form-group :label="__('Issue status')" label-for="issue-status" :label-sr-only="true">
- <gl-form-select id="issue-status" v-model="status" name="status" :options="options" />
+<gl-form-group :label="__('Issue status')" label-for="issue-status" label-sr-only>
+ <gl-form-select id="issue-status" v-model="status" :options="options" />
</gl-form-group>
```
@@ -157,12 +157,12 @@ Single checkbox:
```html
<!-- Single checkbox with label -->
-<gl-form-checkbox v-model="status" name="status" value="task-complete">
+<gl-form-checkbox v-model="status" value="task-complete">
{{ __('Task complete') }}
</gl-form-checkbox>
<!-- Single checkbox with hidden label -->
-<gl-form-checkbox v-model="status" name="status" value="task-complete">
+<gl-form-checkbox v-model="status" value="task-complete">
<span class="gl-sr-only">{{ __('Task complete') }}</span>
</gl-form-checkbox>
```
@@ -172,24 +172,24 @@ Multiple checkboxes:
```html
<!-- Multiple labeled checkboxes grouped within a fieldset -->
<gl-form-group :label="__('Task list')">
- <gl-form-checkbox name="task-list" value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
- <gl-form-checkbox name="task-list" value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
+ <gl-form-checkbox value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
+ <gl-form-checkbox value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
</gl-form-group>
<!-- Or -->
<gl-form-group :label="__('Task list')">
- <gl-form-checkbox-group v-model="selected" :options="options" name="task-list" />
+ <gl-form-checkbox-group v-model="selected" :options="options" />
</gl-form-group>
<!-- Multiple labeled checkboxes grouped within a fieldset with hidden legend -->
-<gl-form-group :label="__('Task list')" :label-sr-only="true">
- <gl-form-checkbox name="task-list" value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
- <gl-form-checkbox name="task-list" value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
+<gl-form-group :label="__('Task list')" label-sr-only>
+ <gl-form-checkbox value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
+ <gl-form-checkbox value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
</gl-form-group>
<!-- Or -->
-<gl-form-group :label="__('Task list')" :label-sr-only="true">
- <gl-form-checkbox-group v-model="selected" :options="options" name="task-list" />
+<gl-form-group :label="__('Task list')" label-sr-only>
+ <gl-form-checkbox-group v-model="selected" :options="options" />
</gl-form-group>
```
@@ -199,12 +199,12 @@ Single radio input:
```html
<!-- Single radio with a label -->
-<gl-form-radio v-model="status" name="status" value="opened">
+<gl-form-radio v-model="status" value="opened">
{{ __('Opened') }}
</gl-form-radio>
<!-- Single radio with a hidden label -->
-<gl-form-radio v-model="status" name="status" value="opened">
+<gl-form-radio v-model="status" value="opened">
<span class="gl-sr-only">{{ __('Opened') }}</span>
</gl-form-radio>
```
@@ -214,24 +214,24 @@ Multiple radio inputs:
```html
<!-- Multiple labeled radio inputs grouped within a fieldset -->
<gl-form-group :label="__('Issue status')">
- <gl-form-radio name="status" value="opened">{{ __('Opened') }}</gl-form-radio>
- <gl-form-radio name="status" value="closed">{{ __('Closed') }}</gl-form-radio>
+ <gl-form-radio value="opened">{{ __('Opened') }}</gl-form-radio>
+ <gl-form-radio value="closed">{{ __('Closed') }}</gl-form-radio>
</gl-form-group>
<!-- Or -->
<gl-form-group :label="__('Issue status')">
- <gl-form-radio-group v-model="selected" :options="options" name="status" />
+ <gl-form-radio-group v-model="selected" :options="options" />
</gl-form-group>
<!-- Multiple labeled radio inputs grouped within a fieldset with hidden legend -->
-<gl-form-group :label="__('Issue status')" :label-sr-only="true">
- <gl-form-radio name="status" value="opened">{{ __('Opened') }}</gl-form-radio>
- <gl-form-radio name="status" value="closed">{{ __('Closed') }}</gl-form-radio>
+<gl-form-group :label="__('Issue status')" label-sr-only>
+ <gl-form-radio value="opened">{{ __('Opened') }}</gl-form-radio>
+ <gl-form-radio value="closed">{{ __('Closed') }}</gl-form-radio>
</gl-form-group>
<!-- Or -->
-<gl-form-group :label="__('Issue status')" :label-sr-only="true">
- <gl-form-radio-group v-model="selected" :options="options" name="status" />
+<gl-form-group :label="__('Issue status')" label-sr-only>
+ <gl-form-radio-group v-model="selected" :options="options" />
</gl-form-group>
```
@@ -242,11 +242,11 @@ File input examples:
```html
<!-- File input with a label -->
<label for="attach-file">{{ __('Attach a file') }}</label>
-<input id="attach-file" type="file" name="attach-file" />
+<input id="attach-file" type="file" />
<!-- File input with a hidden label -->
<label for="attach-file" class="gl-sr-only">{{ __('Attach a file') }}</label>
-<input id="attach-file" type="file" name="attach-file" />
+<input id="attach-file" type="file" />
```
#### GlToggle components with an accessible names
@@ -337,7 +337,7 @@ element is interactive you must ensure:
- It can receive keyboard focus.
- It has a visible focus state.
-Use semantic HTML, such as `a` and `button`, which provides these behaviours by default.
+Use semantic HTML, such as `a` (`GlLink`) and `button` (`GlButton`), which provides these behaviours by default.
Keep in mind that:
@@ -351,7 +351,7 @@ See the [Pajamas Keyboard-only page](https://design.gitlab.com/accessibility-aud
Prefer **no** `tabindex` to using `tabindex`, since:
-- Using semantic HTML such as `button` implicitly provides `tabindex="0"`.
+- Using semantic HTML such as `button` (`GlButton`) implicitly provides `tabindex="0"`.
- Tabbing order should match the visual reading order and positive `tabindex`s interfere with this.
### Avoid using `tabindex="0"` to make an element interactive
@@ -359,8 +359,8 @@ Prefer **no** `tabindex` to using `tabindex`, since:
Use interactive elements instead of `div` and `span` tags.
For example:
-- If the element should be clickable, use a `button`.
-- If the element should be text editable, use an `input` or `textarea`.
+- If the element should be clickable, use a `button` (`GlButton`).
+- If the element should be text editable, use an [`input` or `textarea`](#text-inputs-with-accessible-names).
Once the markup is semantically complete, use CSS to update it to its desired visual state.
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index 1d08296eafc..0c85a21fdf4 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Architecture
diff --git a/doc/development/fe_guide/axios.md b/doc/development/fe_guide/axios.md
index b42a17d7870..f90a2b37a1c 100644
--- a/doc/development/fe_guide/axios.md
+++ b/doc/development/fe_guide/axios.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Axios
diff --git a/doc/development/fe_guide/content_editor.md b/doc/development/fe_guide/content_editor.md
index f262e48b6da..8cc274c732e 100644
--- a/doc/development/fe_guide/content_editor.md
+++ b/doc/development/fe_guide/content_editor.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Content Editor development guidelines **(FREE)**
diff --git a/doc/development/fe_guide/customizable_dashboards.md b/doc/development/fe_guide/customizable_dashboards.md
new file mode 100644
index 00000000000..38ee750d421
--- /dev/null
+++ b/doc/development/fe_guide/customizable_dashboards.md
@@ -0,0 +1,99 @@
+---
+stage: Analytics
+group: Product Analytics
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Customizable dashboards **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98610) in GitLab 15.5 as an [Alpha feature](../../policy/alpha-beta-support.md#alpha-features).
+
+Customizable dashboards provide a dashboard structure that allows users to create
+their own dashboards and commit the structure to a repository.
+
+## Usage
+
+To use customizable dashboards:
+
+1. Create your dashboard component.
+1. Render an instance of `CustomizableDashboard`.
+1. Pass a list of widgets to render.
+
+For example, a customizable dashboard for users over time:
+
+```vue
+<script>
+import CustomizableDashboard from 'ee/vue_shared/components/customizable_dashboard/customizable_dashboard.vue';
+import { s__ } from '~/locale';
+
+export default {
+ name: 'AnalyticsDashboard',
+ components: {
+ CustomizableDashboard,
+ },
+ data() {
+ return {
+ widgets: [
+ {
+ component: 'CubeLineChart', // The name of the widget component.
+ title: s__('ProductAnalytics|Users / Time'), // The title shown on the widget component.
+ // Gridstack settings based upon https://github.com/gridstack/gridstack.js/tree/master/doc#item-options.
+ // All values are grid row/column numbers up to 12.
+ // We use the default 12 column grid https://github.com/gridstack/gridstack.js#change-grid-columns.
+ gridAttributes: {
+ size: {
+ height: 4,
+ width: 6,
+ minHeight: 4,
+ minWidth: 6,
+ },
+ position: {
+ xPos: 0,
+ yPos: 0,
+ },
+ },
+ // Options that are used to set bespoke values for each widget.
+ // Available customizations are determined by the widget itself.
+ customizations: {},
+ // Chart options defined by the charting library being used by the widget.
+ chartOptions: {
+ xAxis: { name: __('Time'), type: 'time' },
+ yAxis: { name: __('Counts') },
+ },
+ // The data for the widget.
+ // This could be imported or in this case, a query passed to be used by the widgets API.
+ // Each widget type determines how it handles this property.
+ data: {
+ query: {
+ users: {
+ measures: ['Jitsu.count'],
+ dimensions: ['Jitsu.eventType'],
+ },
+ },
+ },
+ },
+ ]
+ };
+ },
+};
+</script>
+
+<template>
+ <h1>{{ s__('ProductAnalytics|Analytics dashboard') }}</h1>
+ <customizable-dashboard :widgets="widgets" />
+</template>
+```
+
+The widgets data can be retrieved from a file or API request, or imported through HTML data attributes.
+
+For each widget, a `component` is defined. Each `component` is a component declaration and should be included in
+[`vue_shared/components/customizable_dashboard/widgets_base.vue`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/assets/javascripts/vue_shared/components/customizable_dashboard/widgets_base.vue)
+as a dynamic import, to keep the memory usage down until it is used.
+
+For example:
+
+```javascript
+components: {
+ CubeLineChart: () => import('ee/product_analytics/dashboards/components/widgets/cube_line_chart.vue')
+}
+```
diff --git a/doc/development/fe_guide/dark_mode.md b/doc/development/fe_guide/dark_mode.md
index 34901bbb1e6..d687d9740c9 100644
--- a/doc/development/fe_guide/dark_mode.md
+++ b/doc/development/fe_guide/dark_mode.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
This page is about developing dark mode for GitLab. We also have documentation on how
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index c4f30fd36c9..b9bacada499 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Frontend dependencies
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index 580f488bd33..07de86f5810 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Design Anti-patterns
@@ -146,7 +146,7 @@ Even in these scenarios, consider avoiding the Singleton pattern.
#### Utility Functions
-When no state needs to be managed, we can simply export utility functions from a module without
+When no state needs to be managed, we can export utility functions from a module without
messing with any class instantiation.
```javascript
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
index 03575f7e7f9..3c273ab18e9 100644
--- a/doc/development/fe_guide/design_patterns.md
+++ b/doc/development/fe_guide/design_patterns.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Design Patterns
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index 3273263de3b..fc91ff55b24 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Frontend Development Process
@@ -26,7 +26,7 @@ Use your best judgment when to use it and contribute new points through merge re
- [ ] Check the current set weight of the issue, does it fit your estimate?
- [ ] Are all [departments](https://about.gitlab.com/handbook/engineering/#engineering-teams) that are needed from your perspective already involved in the issue? (For example is UX missing?)
- [ ] Is the specification complete? Are you missing decisions? How about error handling/defaults/edge cases? Take your time to understand the needed implementation and go through its flow.
-- [ ] Are all necessary UX specifications available that you will need in order to implement? Are there new UX components/patterns in the designs? Then contact the UI component team early on. How should error messages or validation be handled?
+- [ ] Are all necessary UX specifications available that you will need to implement? Are there new UX components/patterns in the designs? Then contact the UI component team early on. How should error messages or validation be handled?
- [ ] **Library usage** Use Vuex as soon as you have even a medium state to manage, use Vue router if you need to have different views internally and want to link from the outside. Check what libraries we already have for which occasions.
- [ ] **Plan your implementation:**
- [ ] **Architecture plan:** Create a plan aligned with GitLab's architecture, how you are going to do the implementation, for example Vue application setup and its components (through [onion skinning](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35873#note_39994091)), Store structure and data flow, which existing Vue components can you reuse. It's a good idea to go through your plan with another engineer to refine it.
diff --git a/doc/development/fe_guide/emojis.md b/doc/development/fe_guide/emojis.md
index 3c7fc20440b..3296783a616 100644
--- a/doc/development/fe_guide/emojis.md
+++ b/doc/development/fe_guide/emojis.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Emojis
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index 6a645416c0a..3b349d880c0 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Frontend FAQ
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 6dcc57b0ff5..9ed3e551ff2 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -2,7 +2,7 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# GraphQL
@@ -330,7 +330,7 @@ Along with creating local data, we can also extend existing GraphQL types with `
##### Mocking API response with local Apollo cache
-Using local Apollo Cache is helpful when we have a need to mock some GraphQL API responses, queries, or mutations locally (such as when they're still not added to our actual API).
+Using local Apollo Cache is helpful when we have a reason to mock some GraphQL API responses, queries, or mutations locally (such as when they're still not added to our actual API).
For example, we have a [fragment](#fragments) on `DesignVersion` used in our queries:
@@ -341,7 +341,7 @@ fragment VersionListItem on DesignVersion {
}
```
-We also need to fetch the version author and the `created at` property to display in the versions dropdown. But, these changes are still not implemented in our API. We can change the existing fragment to get a mocked response for these new fields:
+We also must fetch the version author and the `created at` property to display in the versions dropdown list. But, these changes are still not implemented in our API. We can change the existing fragment to get a mocked response for these new fields:
```javascript
fragment VersionListItem on DesignVersion {
@@ -627,7 +627,7 @@ GraphQL entities are not yet part of the schema, or if they are feature-flagged
### Manually triggering queries
Queries on a component's `apollo` property are made automatically when the component is created.
-Some components instead want the network request made on-demand, for example a dropdown with lazy-loaded items.
+Some components instead want the network request made on-demand, for example a dropdown list with lazy-loaded items.
There are two ways to do this:
@@ -1318,7 +1318,7 @@ automatically find and index the schema.
#### Testing Apollo components
-If we use `ApolloQuery` or `ApolloMutation` in our components, in order to test their functionality we need to add a stub first:
+If we use `ApolloQuery` or `ApolloMutation` in our components, to test their functionality we need to add a stub first:
```javascript
import { ApolloMutation } from 'vue-apollo';
diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md
index 7e72570454e..d76d718e8e5 100644
--- a/doc/development/fe_guide/haml.md
+++ b/doc/development/fe_guide/haml.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# HAML
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 73f196ef51f..df296f13f48 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Icons and SVG Illustrations
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index d90c270153e..6403cff549f 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Frontend Development Guidelines
diff --git a/doc/development/fe_guide/keyboard_shortcuts.md b/doc/development/fe_guide/keyboard_shortcuts.md
index aab252da305..aeeee72e6be 100644
--- a/doc/development/fe_guide/keyboard_shortcuts.md
+++ b/doc/development/fe_guide/keyboard_shortcuts.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Implementing keyboard shortcuts
diff --git a/doc/development/fe_guide/logging.md b/doc/development/fe_guide/logging.md
index 26633eade43..30cf290fbe8 100644
--- a/doc/development/fe_guide/logging.md
+++ b/doc/development/fe_guide/logging.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Client-side logging for frontend development
diff --git a/doc/development/fe_guide/merge_request_widget_extensions.md b/doc/development/fe_guide/merge_request_widget_extensions.md
index a2ff10cc57f..e5e813bf921 100644
--- a/doc/development/fe_guide/merge_request_widget_extensions.md
+++ b/doc/development/fe_guide/merge_request_widget_extensions.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request widget extensions **(FREE)**
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index 2e1fabd739c..3aa901093f0 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Performance
diff --git a/doc/development/fe_guide/principles.md b/doc/development/fe_guide/principles.md
index 1bf37c8d008..6d1a3238b73 100644
--- a/doc/development/fe_guide/principles.md
+++ b/doc/development/fe_guide/principles.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Principles
diff --git a/doc/development/fe_guide/registry_architecture.md b/doc/development/fe_guide/registry_architecture.md
index be14d5d920c..a87d38634d5 100644
--- a/doc/development/fe_guide/registry_architecture.md
+++ b/doc/development/fe_guide/registry_architecture.md
@@ -1,7 +1,7 @@
---
stage: Package
group: unassigned
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Registry architecture
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
index 6f500c8f0fa..4b7ce6d11e3 100644
--- a/doc/development/fe_guide/security.md
+++ b/doc/development/fe_guide/security.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Security
diff --git a/doc/development/fe_guide/source_editor.md b/doc/development/fe_guide/source_editor.md
index 88508e94380..b7cd903485e 100644
--- a/doc/development/fe_guide/source_editor.md
+++ b/doc/development/fe_guide/source_editor.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Source Editor **(FREE)**
diff --git a/doc/development/fe_guide/storybook.md b/doc/development/fe_guide/storybook.md
index a3a1fa2160f..e57c117bc39 100644
--- a/doc/development/fe_guide/storybook.md
+++ b/doc/development/fe_guide/storybook.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Storybook
diff --git a/doc/development/fe_guide/style/html.md b/doc/development/fe_guide/style/html.md
index 90ff88bc975..b1cce29bc61 100644
--- a/doc/development/fe_guide/style/html.md
+++ b/doc/development/fe_guide/style/html.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# HTML style guide
diff --git a/doc/development/fe_guide/style/index.md b/doc/development/fe_guide/style/index.md
index f3da78647be..94ed9544cf5 100644
--- a/doc/development/fe_guide/style/index.md
+++ b/doc/development/fe_guide/style/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab development style guides
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index b86bdfafa21..38fb926197b 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_js.html'
---
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index 17e80762a38..aacf07fda92 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_scss.html'
---
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index 39dc9cc9c4e..a21d7c4577b 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vue.js style guide
diff --git a/doc/development/fe_guide/tooling.md b/doc/development/fe_guide/tooling.md
index 4b55580c33c..c9efb8e939d 100644
--- a/doc/development/fe_guide/tooling.md
+++ b/doc/development/fe_guide/tooling.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tooling
diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md
index ab10c5bf988..873a14b8f14 100644
--- a/doc/development/fe_guide/troubleshooting.md
+++ b/doc/development/fe_guide/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting frontend development issues
diff --git a/doc/development/fe_guide/view_component.md b/doc/development/fe_guide/view_component.md
index 7ddce609ee7..662d1ad32fc 100644
--- a/doc/development/fe_guide/view_component.md
+++ b/doc/development/fe_guide/view_component.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
group: Foundations
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# ViewComponent
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 5cb461c8ca0..00d9588d087 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vue
@@ -408,11 +408,11 @@ export function useCount(initialValue) {
const count = ref(initialValue)
function incrementCount() {
- ref.value += 1
+ count.value += 1
}
function decrementCount() {
- ref.value -= 1
+ count.value -= 1
}
return { count, incrementCount, decrementCount }
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index 068b0c5b475..c3ce42a80a5 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migration to Vue 3
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 2d1569b7812..5047f1b7f89 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vuex
diff --git a/doc/development/fe_guide/widgets.md b/doc/development/fe_guide/widgets.md
index c6bb89d1fe8..3364c778d76 100644
--- a/doc/development/fe_guide/widgets.md
+++ b/doc/development/fe_guide/widgets.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Widgets
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
index a93ed58336d..0bf506b53ba 100644
--- a/doc/development/feature_categorization/index.md
+++ b/doc/development/feature_categorization/index.md
@@ -1,7 +1,7 @@
---
stage: Enablement
group: Infrastructure
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Feature Categorization
diff --git a/doc/development/feature_development.md b/doc/development/feature_development.md
index fd1c7f4afa5..760ba033633 100644
--- a/doc/development/feature_development.md
+++ b/doc/development/feature_development.md
@@ -1,7 +1,7 @@
---
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Feature development
@@ -114,6 +114,7 @@ Consult these topics for information on contributing to specific GitLab features
- [Cached queries guidelines](cached_queries.md), for tracking down N+1 queries
masked by query caching, memory profiling and why should we avoid cached
queries.
+- [JSON guidelines](json.md) for how to handle JSON in a performant manner.
## Database guides
@@ -128,6 +129,12 @@ See [database guidelines](database/index.md).
- [How to run Jenkins in development environment](integrations/jenkins.md)
- [How to run local `Codesandbox` integration for Web IDE Live Preview](integrations/codesandbox.md)
+The following integration guides are internal. Some integrations require access to administrative accounts of third-party services and are available only for GitLab team members to contribute to:
+
+- [Jira app development](https://gitlab.com/gitlab-org/manage/integrations/team/-/blob/main/integrations/jira.md)
+- [Slack app development](https://gitlab.com/gitlab-org/manage/integrations/team/-/blob/main/integrations/slack.md)
+- [ZenTao development](https://gitlab.com/gitlab-org/manage/integrations/team/-/blob/main/integrations/zentao.md)
+
## Testing guides
- [Testing standards and style guidelines](testing_guide/index.md)
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 63dad3070c7..e6c3c20d50b 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -2,15 +2,18 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
-# Feature flag controls
+# Use ChatOps to enable and disable feature flags
-## Access
+NOTE:
+This document explains how to contribute to the development of the GitLab product.
+If you want to use feature flags to show and hide functionality in your own applications,
+view [this feature flags information](../../operations/feature_flags.md) instead.
-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
+To turn on/off features behind feature flags in any of the
+GitLab-provided environments, like 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
[GitLab.com](https://gitlab.com) or [`dev.gitlab.org`](https://dev.gitlab.org).
@@ -47,12 +50,12 @@ Note that all the examples in that file must be preceded by
If you get an error "Whoops! This action is not allowed. This incident
will be reported." that means your Slack account is not allowed to
-change feature flags or you do not [have access](#access).
+change feature flags or you do not have access.
### Enabling a feature for pre-production testing
As a first step in a feature rollout, you should enable the feature on
-[`about.staging.gitlab.com`](https://about.staging.gitlab.com)
+[`staging.gitlab.com`](https://staging.gitlab.com)
and [`dev.gitlab.org`](https://dev.gitlab.org).
These two environments have different scopes.
@@ -173,7 +176,7 @@ For project level features:
Feature.enabled?(:feature_ice_cold_projects, project)
```
-If you are not certain what percentages to use, simply use the following steps:
+If you are not certain what percentages to use, use the following steps:
1. 25%
1. 50%
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 444b53f9c8d..f1cde4ae1ea 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -2,24 +2,20 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Feature flags in the development of GitLab
NOTE:
-The documentation below covers feature flags used by GitLab to deploy its own features, which **is not** the same
-as the [feature flags offered as part of the product](../../operations/feature_flags.md).
-
-This document provides guidelines on how to use feature flags
-for the development of GitLab to conditionally and/or incrementally enable features
-and test them in production/staging.
+This document explains how to contribute to the development of the GitLab product.
+If you want to use feature flags to show and hide functionality in your own applications,
+view [this feature flags information](../../operations/feature_flags.md) instead.
WARNING:
All newly-introduced feature flags should be [disabled by default](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#feature-flags-in-gitlab-development).
-NOTE:
-This document is the subject of continued work as part of an epic to [improve internal usage of Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). Raise any suggestions as new issues and attach them to the epic.
+This document is the subject of continued work as part of an epic to [improve internal usage of feature flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). Raise any suggestions as new issues and attach them to the epic.
For an [overview of the feature flag lifecycle](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#feature-flag-lifecycle), or if you need help deciding [if you should use a feature flag](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags) or not, please see the [feature flag lifecycle](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/) handbook page.
@@ -56,7 +52,7 @@ When the feature implementation is delivered among multiple merge requests:
1. When the feature is ready to be announced, create a merge request that adds
documentation about the feature, including [documentation for the feature flag itself](../documentation/feature_flags.md),
and a [changelog entry](#changelog). In the same merge request either flip the feature flag to
- be **on by default** or remove it entirely in order to enable the new behavior.
+ be **on by default** or remove it entirely to enable the new behavior.
One might be tempted to think that feature flags will delay the release of a
feature by at least one month (= one release). This is not the case. A feature
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index f30a041931e..7a46cd40da1 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Features inside the `.gitlab/` directory
@@ -16,6 +16,6 @@ When implementing new features, please refer to these existing features to avoid
- [CODEOWNERS](../user/project/code_owners.md#set-up-code-owners): `.gitlab/CODEOWNERS`.
- [Route Maps](../ci/review_apps/index.md#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`.
-- [Insights](../user/project/insights/index.md#configure-your-insights): `.gitlab/insights.yml`.
+- [Insights](../user/project/insights/index.md#configure-project-insights): `.gitlab/insights.yml`.
- [Service Desk Templates](../user/project/service_desk.md#using-customized-email-templates): `.gitlab/service_desk_templates/`.
- [Web IDE](../user/project/web_ide/index.md#web-ide-configuration-file): `.gitlab/.gitlab-webide.yml`.
diff --git a/doc/development/file_storage.md b/doc/development/file_storage.md
index 04e2f381c97..11acb8a2161 100644
--- a/doc/development/file_storage.md
+++ b/doc/development/file_storage.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# File Storage in GitLab
diff --git a/doc/development/fips_compliance.md b/doc/development/fips_compliance.md
index 1029ed88eac..475c1a49000 100644
--- a/doc/development/fips_compliance.md
+++ b/doc/development/fips_compliance.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# FIPS compliance
@@ -67,7 +67,7 @@ listed here that also do not work properly in FIPS mode:
- [Static Application Security Testing (SAST)](../user/application_security/sast/index.md)
supports a reduced set of [analyzers](../user/application_security/sast/index.md#fips-enabled-images)
when operating in FIPS-compliant mode.
-- Advanced Search is currently not included in FIPS mode. It must not be enabled in order to be FIPS-compliant.
+- Advanced Search is currently not included in FIPS mode. It must not be enabled to be FIPS-compliant.
- [Gravatar or Libravatar-based profile images](../administration/libravatar.md) are not FIPS-compliant.
Additionally, these package repositories are disabled in FIPS mode:
@@ -417,7 +417,7 @@ In this environment, OpenSSL refuses to perform cryptographic operations
forbidden by the FIPS standards. This enables you to reproduce FIPS-related bugs,
and validate fixes.
-You should be able to open a web browser inside the virtual machine and log in
+You should be able to open a web browser inside the virtual machine and sign in
to the GitLab instance.
You can disable FIPS mode again by running this command, then restarting the
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
index 87304a761ea..7d3531afb49 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -1,20 +1,67 @@
---
stage: none
group: unassigned
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gemfile guidelines
-When adding a new entry to `Gemfile` or upgrading an existing dependency pay
+When adding a new entry to `Gemfile`, or upgrading an existing dependency pay
attention to the following rules.
+## Bundler checksum verification
+
+In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98508), gem
+checksums are checked before installation. This verification is still
+experimental so it is only active for CI.
+
+If the downloaded gem's checksum does not match the checksum record in
+`Gemfile.checksum`, you will see an error saying that Bundler cannot continue
+installing a gem because there is a potential security issue.
+
+You will see this error as well if you updated, or added a new gem without
+updating `Gemfile.checksum`. To fix this error,
+[update the Gemfile.checksum](#updating-the-checksum-file).
+
+You can opt-in to this verification locally by setting the
+`BUNDLER_CHECKSUM_VERIFICATION_OPT_IN` environment variable:
+
+```shell
+export BUNDLER_CHECKSUM_VERIFICATION_OPT_IN=1
+bundle install
+```
+
+### Updating the checksum file
+
+This needs to be done for any new, or updated gems.
+
+1. When updating `Gemfile.lock`, make sure to also update `Gemfile.checksum` with:
+
+ ```shell
+ bundle exec bundler-checksum init
+ ```
+
+1. Check and commit the changes for `Gemfile.checksum`.
+
## No gems fetched from Git repositories
We do not allow gems that are fetched from Git repositories. All gems have
to be available in the RubyGems index. We want to minimize external build
dependencies and build times.
+## Review the new dependency for quality
+
+We should not add 3rd-party dependencies to GitLab that would not pass our own quality standards.
+This means that new dependencies should, at a minimum, meet the following criteria:
+
+- They have an active developer community. At the minimum a maintainer should still be active
+ to merge change requests in case of emergencies.
+- There are no issues open that we know may impact the availablity or performance of GitLab.
+- The project is tested using some form of test automation. The test suite must be passing
+ using the Ruby version currently used by GitLab.
+- If the project uses a C extension, consider requesting an additional review from a C or MRI
+ domain expert. C extensions can greatly impact GitLab stability and performance.
+
## Request an Appsec review
When adding a new gem to our `Gemfile` or even changing versions in
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 1ae9d9ee32b..884c09cc174 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo (development) **(PREMIUM SELF)**
@@ -69,8 +69,8 @@ the lock, it switches to standby mode.
Geo uses [streaming replication](#streaming-replication) to replicate
the database from the **primary** to the **secondary** sites. This
replication gives the **secondary** sites access to all the data saved
-in the database. So users can log in on the **secondary** and read all
-the issues, merge requests, and so on, on the **secondary** site.
+in the database, so users can sign in to the **secondary** site and read,
+for example, all the issues and merge requests.
### Repository replication
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 18774b9b3fd..3624d280f86 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo self-service framework
diff --git a/doc/development/geo/proxying.md b/doc/development/geo/proxying.md
index d4cb611e965..67d4129a9d0 100644
--- a/doc/development/geo/proxying.md
+++ b/doc/development/geo/proxying.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo proxying
diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md
index a20bdf633cd..dcfcd2e864a 100644
--- a/doc/development/git_object_deduplication.md
+++ b/doc/development/git_object_deduplication.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# How Git object deduplication works in GitLab
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 66b535682f5..a570b5dd7eb 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gitaly developers guide
@@ -219,7 +219,7 @@ as a [CI/CD variable](../ci/variables/index.md).
If you are making changes to the RPC client, such as adding a new endpoint or adding a new
parameter to an existing endpoint, follow the guide for
-[Gitaly protobuf specifications](https://gitlab.com/gitlab-org/gitaly/blob/master/proto/README.md). After pushing
+[Gitaly protobuf specifications](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/protobuf.md). After pushing
the branch with the changes (`new-feature-branch`, for example):
1. Change the `gitaly` line in the Rails' `Gemfile` to:
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 9740ae04553..9ba375439f4 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with the GitHub importer
@@ -114,6 +114,9 @@ GitHub are stored in a single table. Therefore, they have globally-unique IDs an
Therefore, both issues and pull requests have a common API for most related things.
+NOTE:
+This stage is optional and can consume significant extra import time (controlled by `Gitlab::GithubImport::Settings`).
+
### 9. Stage::ImportNotesWorker
This worker imports regular comments for both issues and pull requests. For
@@ -127,16 +130,23 @@ comments.
### 10. Stage::ImportAttachmentsWorker
-This worker imports release notes attachments that are linked inside Markdown.
-For every release of the project, we schedule a job of
-`Gitlab::GithubImport::ImportReleaseAttachmentsWorker` for every comment.
+This worker imports note attachments that are linked inside Markdown.
+For each entity with Markdown text in the project, we schedule a job of:
+
+- `Gitlab::GithubImport::ImportReleaseAttachmentsWorker` for every release.
+- `Gitlab::GithubImport::ImportNoteAttachmentsWorker` for every note.
+- `Gitlab::GithubImport::ImportIssueAttachmentsWorker` for every issue.
+- `Gitlab::GithubImport::ImportMergeRequestAttachmentsWorker` for every merge request.
Each job:
-1. Iterates over all attachment links inside of a specific release note.
+1. Iterates over all attachment links inside of a specific record.
1. Downloads the attachment.
1. Replaces the old link with a newly-generated link to GitLab.
+NOTE:
+It's an optional stage that could consume significant extra import time (controlled by `Gitlab::GithubImport::Settings`).
+
### 11. Stage::ImportProtectedBranchesWorker
This worker imports protected branch rules.
@@ -197,7 +207,7 @@ GitHub has a rate limit of 5,000 API calls per hour. The number of requests
necessary to import a project is largely dominated by the number of unique users
involved in a project (for example, issue authors). Other data such as issue pages
and comments typically only requires a few dozen requests to import. This is
-because we need the Email address of users in order to map them to GitLab users.
+because we need the Email address of users to map them to GitLab users.
We handle this by doing the following:
diff --git a/doc/development/gitlab_flavored_markdown/index.md b/doc/development/gitlab_flavored_markdown/index.md
index 7f7781cbc62..0af31892726 100644
--- a/doc/development/gitlab_flavored_markdown/index.md
+++ b/doc/development/gitlab_flavored_markdown/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Flavored Markdown (GLFM) developer documentation **(FREE)**
diff --git a/doc/development/gitlab_flavored_markdown/specification_guide/index.md b/doc/development/gitlab_flavored_markdown/specification_guide/index.md
index c1227e5d33f..95d06907aa6 100644
--- a/doc/development/gitlab_flavored_markdown/specification_guide/index.md
+++ b/doc/development/gitlab_flavored_markdown/specification_guide/index.md
@@ -1,34 +1,67 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Flavored Markdown (GLFM) Specification Guide **(FREE)**
+## Summary
+
+- _GitLab_ Flavored Markdown (GLFM) is based on
+ [_GitHub_ Flavored Markdown](https://github.github.com/gfm/) (GFM),
+ which is based on [CommonMark](https://spec.commonmark.org/current/).
+- GLFM is divided into two "sets" of Markdown syntax:
+ - An "[official specification](#official-specifications)",
+ which is not dependent upon any specific
+ implementation or environment, and can be supported in any editor.
+ - "[Internal extensions](#internal-extensions)", which may be
+ dependent upon the GitLab environment and metadata.
+- Everything in each of these sets of syntax is specified by
+ [special Markdown files](#input-specification-files)
+ based on the [CommonMark specification syntax](https://spec.commonmark.org/0.30/#about-this-document),
+ which contain side-by-side "examples" of Markdown and the corresponding
+ generated HTML, and associated documentation describing each example.
+- There are also [YAML metadata files](#input-specification-files), which
+ may contain additional information on how individual Markdown/HTML examples
+ should be processed and rendered.
+- These Markdown/YAML files and the examples they contain serve multiple goals:
+ - They are the canonical "source of truth" for how GLFM should be rendered.
+ - They support rendering a [formatted HTML document](#spechtml) containing all
+ of the examples and associated documentation, as the
+ [GFM and CommonMark specs](#various-markdown-specifications) also do.
+ - They support running standard CommonMark [conformance testing](#markdown-conformance-testing)
+ against the official specification.
+ - They support [snapshot testing](#markdown-snapshot-testing) of GitLab
+ internal GLFM processing logic. This is accomplished by automatically
+ generating YAML ["example snapshot files"](#example-snapshot-files)
+ which are used as fixtures to drive automated testing within the GitLab app.
+- There are [various scripts and logic](#scripts)
+ which are used to accomplish the above goals.
+
+## Introduction
+
GitLab supports Markdown in various places. The Markdown dialect we use is called
-GitLab Flavored Markdown, or GLFM.
+GitLab Flavored Markdown (GLFM).
+
+NOTE:
+In this document, _GFM_ refers to _GitHub_ Flavored Markdown, not _GitLab_ Flavored Markdown.
+Refer to the [section on acronyms](#acronyms-glfm-ghfm-gfm-commonmark)
+for a detailed explanation of the various acronyms used in this document.
The specification for the GLFM dialect is based on the
[GitHub Flavored Markdown (GFM) specification](https://github.github.com/gfm/),
which is in turn based on the [CommonMark specification](https://spec.commonmark.org/current/).
The GLFM specification includes
-[several extensions](../../../user/markdown.md#differences-between-gitlab-flavored-markdown-and-standard-markdown)
-to the GFM specification.
+[many additions](../../../user/markdown.md#differences-between-gitlab-flavored-markdown-and-standard-markdown)
+compared to the GFM specification.
-See the [section on acronyms](#acronyms-glfm-ghfm-gfm-commonmark) for a
-detailed explanation of the various acronyms used in this document.
This guide is a developer-facing document that describes the various terms and
definitions, goals, tools, and implementations related to the GLFM specification.
It is intended to support and augment the [user-facing documentation](../../../user/markdown.md)
for GitLab Flavored Markdown.
NOTE:
-In this document, _GFM_ refers to _GitHub_ Flavored Markdown, not _GitLab_ Flavored Markdown.
-Refer to the [section on acronyms](#acronyms-glfm-ghfm-gfm-commonmark)
-for a detailed explanation of the various acronyms used in this document.
-
-NOTE:
This guide and the implementation and files described in it are still a work in
progress. As the work progresses, rewrites and consolidation
between this guide and the [user-facing documentation](../../../user/markdown.md)
@@ -43,7 +76,7 @@ to by the acronym GFM, and this document follows that convention as well.
_GitLab_ Flavored Markdown is referred to as GLFM in this document,
to distinguish it from GitHub Flavored Markdown.
-Unfortunately, this convention is not followed consistently in the rest
+Unfortunately, this convention is not yet followed consistently in the rest
of the documentation or GitLab codebase. In many places, the GFM
acronym is used to refer to _GitLab_ Flavored Markdown. An
[open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24592) exists to resolve
@@ -53,7 +86,7 @@ Some places in the code refer to both the GitLab and GitHub specifications
simultaneous in the same areas of logic. In these situations,
_GitHub_ Flavored Markdown may be referred to with variable or constant names like
`ghfm_` to avoid confusion. For example, we use the `ghfm` acronym for the
-[`ghfm_spec_v_0.29.txt` GitHub Flavored Markdown specification file](#github-flavored-markdown-specification)
+[`ghfm_spec_v_0.29.md` GitHub Flavored Markdown specification file](#github-flavored-markdown-specification),
which is committed to the `gitlab` repository and used as input to the
[`update_specification.rb` script](#update-specificationrb-script).
@@ -77,7 +110,7 @@ Here are the HTML-rendered versions of the specifications:
NOTE:
The creation of the
-[GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html)
+[HTML-rendered version of the GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html)
file is still pending.
However, GLFM has more complex parsing, rendering, and testing requirements than
@@ -134,7 +167,8 @@ Markdown for issues, pull requests, or merge requests within the editor or IDE.
### Markdown examples
Everywhere in the context of the specification and this guide, the term
-_examples_ is specifically used to refer to the Markdown + HTML pairs used
+_examples_ is specifically used to refer to the convention of using
+backtick-delimited Markdown + HTML pairs
to illustrate the canonical parsing (or rendering) behavior of various Markdown source
strings in the standard
[CommonMark specification format](https://spec.commonmark.org/0.30/#example-1).
@@ -143,6 +177,9 @@ In this context, it should not be confused with other similar or related meaning
_example_, such as
[RSpec examples](https://relishapp.com/rspec/rspec-core/docs/example-groups/basic-structure-describe-it).
+See the section on the [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) file
+for more details on the backtick-delimited Markdown+HTML example syntax.
+
### Parsers and renderers
To understand the various ways in which a specification is used, and how it related
@@ -169,11 +206,20 @@ of specification-driven testing referred to in this documentation and elsewhere.
#### Markdown conformance testing
+NOTE:
+Markdown conformance testing for GLFM is not yet implemented.
+
_Markdown conformance testing_ refers to the standard testing method used by
all CommonMark Markdown dialects to verify that a specific implementation conforms
to the CommonMark Markdown specification. It is enforced by running the standard
CommonMark tool [`spec_tests.py`](https://github.com/github/cmark-gfm/blob/master/test/spec_tests.py)
-against a given `spec.txt` specification and the implementation.
+against a given `spec.txt` specification and the implementation, as
+[described in the specification itself](https://github.github.com/gfm/#about-this-document)
+
+Conformance testing is _only_ to be run against GLFM [official specification](#official-specifications)
+examples, and is _not_ to be run against [internal extension](#internal-extensions) examples.
+This is because the internal extension examples may have dependencies on the GitLab environment
+or metadata, but the standard CommonMark conformance testing tool does not support this.
NOTE:
`spec_tests.py` may eventually be re-implemented in Ruby, to not have a dependency on Python.
@@ -187,7 +233,14 @@ tests which use the fixture data. This fixture data is contained in YAML files.
are generated and updated based on the Markdown examples in the specification,
and the existing GLFM parser and render implementations. They may also be
manually updated as necessary to test-drive incomplete implementations.
-Regarding the terminology used here:
+
+Snapshot testing is intended to be comprehensive, so it is run against _all_ examples - both the GLFM
+[official specification](#official-specifications) and [internal extension](#internal-extensions) examples.
+This means that it uses configuration files to support providing GitLab-specific environment or metadata
+which is required by internal extension examples, such
+as [`glfm_example_metadata.yml`](#glfm_example_metadatayml).
+
+Regarding the terminology used for Markdown snapshot testing:
<!-- vale gitlab.InclusionCultural = NO -->
@@ -270,13 +323,14 @@ implementations:
### Multiple versions of rendered HTML
Both of these GLFM renderer implementations (static and WYSIWYG) produce
-HTML which differs from the canonical HTML examples from the specification.
-For every Markdown example in the GLFM specification, three
+HTML which may differ from the canonical HTML examples in the
+<abbr title="GitLab Flavored Markdown">GLFM</abbr> [official specification](#official-specifications).
+Therefore, for every Markdown example in the GLFM specification, three
versions of HTML can potentially be rendered from the example:
-- Static HTML.
-- WYSIWYG HTML.
-- Canonical HTML.
+- Static HTML
+- WYSIWYG HTML
+- Canonical HTML
#### Static HTML
@@ -286,22 +340,57 @@ added for dynamically creating an issue from a task list item.
The GitLab [Markdown API](../../../api/markdown.md) generates HTML
for a given Markdown string using this method.
+The Markdown specified in the [Markdown examples](#markdown-examples) is used to automatically generate HTML in
+[`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) via
+[`update-example-snapshots.rb`](#update-example-snapshotsrb-script). These examples are
+used when running [Markdown snapshot testing](#markdown-snapshot-testing).
+
#### WYSIWYG HTML
**WYSIWYG HTML** is HTML produced by the frontend (JavaScript) Content Editor,
which includes parsing and rendering logic. It is used to present an editable document
in the ProseMirror WYSIWYG editor.
+Just like static HTML,
+the Markdown specified in the [Markdown examples](#markdown-examples) is used to automatically generate HTML in
+[`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) via
+[`update-example-snapshots.rb`](#update-example-snapshotsrb-script). These examples are
+used when running [Markdown snapshot testing](#markdown-snapshot-testing).
+
#### Canonical HTML
-**Canonical HTML** is the clean, basic version of HTML rendered from Markdown.
+**Canonical HTML** is the clean, basic version of HTML rendered from Markdown, with no
+unnecessary classes/elements related to styling or any other implementation-specific behavior.
+
+Its purpose is to support [Markdown conformance testing](#markdown-conformance-testing) against the
+GLFM [`spec.txt`](#spectxt).
+
+Always hardcoded and manually curated, the HTML is never automatically generated.
+The [Markdown examples](#markdown-examples) specifying it are contained
+in different files depending on which [Markdown specification](#various-markdown-specifications)
+a given example originally comes from.
+
+Canonical HTML is **_always specified_** for all [Markdown examples](#markdown-examples)
+in the CommonMark, <abbr title="GitHub Flavored Markdown">GFM</abbr>, and <abbr title="GitLab Flavored Markdown">GLFM</abbr>
+[official specifications](#official-specifications).
+
+However, it is **_never specified_** for GLFM [internal extensions](#internal-extensions) in the [Markdown examples](#markdown-examples).
+**This is because the internal extensions are never tested via [Markdown conformance testing](#markdown-conformance-testing).
+Therefore, canonical HTML for internal extension examples is never used by any scripts or automated testing.**
+
+Here are more details on the sources of canonical HTML examples:
-1. For the examples which come from the CommonMark specification and
+1. For the examples which are part of the CommonMark specification and
GFM extensions specification, the canonical HTML is the exact identical HTML found in the
- GFM `spec.txt` example blocks.
-1. For GLFM extensions to the <abbr title="GitHub Flavored Markdown">GFM</abbr> / CommonMark
- specification, a `glfm_canonical_examples.txt` [input specification file](#input-specification-files)
- contains the Markdown examples and corresponding canonical HTML examples.
+ [GFM `spec.txt`](https://github.com/github/cmark-gfm/blob/master/test/spec.txt) [Markdown example](#markdown-examples) blocks.
+ These examples are copied verbatim from the GFM `spec.txt` into the GLFM
+ version of [`spec.txt`](#spectxt).
+1. For the examples which are part of the GLFM [_official specification_](#official-specifications),
+ the canonical HTML is manually maintained and curated via the examples contained in the
+ [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) [input specification file](#input-specification-files).
+1. For the examples which are part of the GLFM [_internal extensions_](#internal-extensions),
+ the canonical HTML **is never specified**, and **must be left empty in all examples** contained in
+ the [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd) [input specification file](#input-specification-files).
### Canonicalization of HTML
@@ -309,7 +398,11 @@ The rendered [static HTML](#static-html) and [WYSIWYG HTML](#wysiwyg-html)
from the backend (Ruby) and frontend (JavaScript) renderers usually contains extra styling
or HTML elements, to support specific appearance and behavioral requirements.
-Neither the backend nor the frontend rendering logic can directly render the clean, basic canonical HTML.
+Neither the backend nor the frontend rendering logic can directly render the clean, basic HTML
+which is necessary to perform comparison to the [canonical HTML](#canonical-html)
+when running [Markdown conformance testing](#markdown-conformance-testing)
+for the [GLFM official specification examples](#glfm_official_specification_examplesmd).
+
Nor should they be able to, because:
- It's not a direct requirement to support any GitLab application feature.
@@ -318,16 +411,9 @@ Nor should they be able to, because:
Instead, the rendered static or WYSIWYG HTML is converted to canonical HTML by a
_canonicalization_ process. This process can strip all the extra styling and behavioral
HTML from the static or WYSIWYG HTML, resulting in canonical HTML which exactly
-matches the Markdown + HTML examples in a standard `spec.txt` specification.
+matches the canonical HTML examples in a standard `spec.txt` specification.
Use the [`canonicalize-html.rb` script](#canonicalize-htmlrb-script) for this process.
-More explanation about this canonicalization process in the sections below.
-
-NOTE:
-Some of the static or WYSIWYG HTML examples may not be representable as canonical
-HTML. (For example, when they are represented as an image.) In these cases, the Markdown
-conformance test for the example can be skipped by setting `skip_update_example_snapshots: true`
-for the example in `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml`.
### Normalization
@@ -416,7 +502,7 @@ of how the normalizations are specified.
## Goals
-Given the constraints above, we have a few goals related to the GLFM
+Given all the constraints above, we can summarize the various goals related to the GLFM
specification and testing infrastructure:
1. A canonical `spec.txt` exists, and represents the official specification for
@@ -425,17 +511,18 @@ specification and testing infrastructure:
(GFM) specification, just as
<abbr title="GitHub Flavored Markdown">GFM</abbr> is a strict superset
[of the CommonMark specification](https://github.github.com/gfm/#what-is-github-flavored-markdown-).
- Therefore, it contains the superset of all canonical Markdown + HTML examples
- for CommonMark, GFM, and GLFM.
+ 1. Therefore, it contains the superset of all [Markdown examples](#markdown-examples)
+ for CommonMark and GFM, as well as the GLFM
+ [official specification](#official-specifications) and [internal extensions](#internal-extensions).
1. It contains a prose introduction section which is specific to GitLab and GLFM.
1. It contains all other non-introduction sections verbatim from the
- GFM
- `spec.txt`.
- 1. It contains a new extra section for the GLFM GitLab-specific extensions,
- with both prose and examples describing the extensions.
- 1. It should be in the standard format which can processed by the standard
- CommonMark tools [`spec_tests.py`](https://github.com/github/cmark-gfm/blob/master/test/spec_tests.py),
- which is a [script used to run the Markdown conformance tests](https://github.github.com/gfm/#about-this-document)
+ [GFM specification](#github-flavored-markdown-specification).
+ 1. It contains new, extra sections for all the additional Markdown contained in the GLFM
+ [official specification](#official-specifications) and [internal extensions](#internal-extensions),
+ with [Markdown examples](#markdown-examples) and accompanying prose, just like the CommonMark and GFM examples.
+ 1. All its headers and [Markdown examples](#markdown-examples) should be in the standard format which can be processed by the standard
+ CommonMark tool [`spec_tests.py`](https://github.com/github/cmark-gfm/blob/master/test/spec_tests.py) used to perform
+ [Markdown conformance testing](#markdown-conformance-testing)
against all examples contained in a `spec.txt`.
1. The GLFM parsers and HTML renderers for
both the static backend (Ruby) and WYSIWYG frontend (JavaScript) implementations
@@ -445,9 +532,9 @@ specification and testing infrastructure:
NOTE:
Consistent does not mean that both of these implementations render
to the identical HTML. They each have different implementation-specific additions
- to the HTML they render, so therefore their rendered HTML is
- ["canonicalized"](#canonicalization-of-html) to canonical HTML prior running
- the Markdown conformance tests.
+ to the HTML they render, so their rendered HTML is
+ ["canonicalized"](#canonicalization-of-html) to canonical HTML prior to running
+ [Markdown conformance testing](#markdown-conformance-testing).
1. For _both_ the static backend (Ruby) and WYSIWYG frontend (JavaScript) implementations,
a set of example snapshots exists in the form of YAML files, which
correspond to every Markdown example in the GLFM `spec.txt`. These example snapshots
@@ -519,7 +606,7 @@ them from the corresponding implementation class entry point files under
#### `update-specification.rb` script
-The `scripts/glfm/update-specification.rb` script uses specification input files to
+The `scripts/glfm/update-specification.rb` script uses [input specification files](#input-specification-files) to
generate and update `spec.txt` (Markdown) and `spec.html` (HTML). The `spec.html` is
generated by passing the generated (or updated) `spec.txt` Markdown to the backend API
for rendering to static HTML:
@@ -531,14 +618,15 @@ subgraph script:
A --> B{Backend Markdown API}
end
subgraph input:<br/>input specification files
- C[ghfm_spec_v_0.29.txt] --> A
- D[glfm_intro.txt] --> A
- E[glfm_canonical_examples.txt] --> A
+ C[ghfm_spec_v_0.29.md] --> A
+ D[glfm_intro.md] --> A
+ E[glfm_official_specification_examples.md] --> A
+ F[glfm_internal_extension_examples.md] --> A
end
subgraph output:<br/>GLFM specification files
- A --> F[spec.txt]
- F --> B
- B --> G[spec.html]
+ A --> G[spec.txt]
+ G --> B
+ B --> H[spec.html]
end
```
@@ -650,38 +738,65 @@ subgraph output:<br/>test results/output
end
```
+#### `verify-all-generated-files-are-up-to-date.rb` script
+
+The `scripts/glfm/verify-all-generated-files-are-up-to-date.rb` script
+runs the [`update-specification.rb`](#update-specificationrb-script).
+[`update-example-snapshots.rb`](#update-example-snapshotsrb-script) scripts,
+It fails with an exception and non-zero return code if running these scripts
+results in any diffs to the generated and committed
+[output specification files](#output-specification-files) or
+[example snapshot files](#example-snapshot-files).
+
+This script is run via the `glfm-verify` CI job to ensure that all changes to the
+[input specification files](#input-specification-files)
+are reflected in the generated output specification and example snapshot files.
+
### Specification files
These files represent the GLFM specification itself. They are all
-located under the root `glfm_specification`, and are further divided into two
-subfolders:
-
-- `input`: Contains files which are imported or manually edited.
-- `output`: Contains files which are automatically generated.
+located under the root `glfm_specification` and are further divided into
+subcategories based on their usage and purpose:
+
+- `glfm_specification`
+ - `input`: Contains files that are downloaded or manually edited.
+ These are the original input to drive all other automated GLFM
+ specification scripts, processes, or tests.
+ - `github_flavored_markdown`: Contains only the downloaded and committed
+ [`ghfm_spec_v_0.29.md`](#github-flavored-markdown-specification) specification.
+ - `gitlab_flavored_markdown`: Contains all `glfm_*` files.
+ - `*.md` [input specification files](#input-specification-files),
+ which represent the GLFM specification itself.
+ - `*.yml` [input specification configuration files](#input-specification-configuration-files),
+ which control various aspects of the automated GLFM scripts and processes.
+ - `output`: Contains [output specification files](#output-specification-files),
+ which are automatically generated from the
+ input files by running the [`update-specification.rb`](#update-specificationrb-script) script.
#### Input specification files
-The `glfm_specification/input` directory contains files which are the original
-input to drive all other automated GLFM specification scripts/processes/tests.
-They are either downloaded, as in the case of the
-GFM `spec.txt` file, or manually
-updated, as in the case of all GFM files.
+Input specification files are manually curated Markdown files that represent the specification itself.
+They are located at `glfm_specification/input/github_flavored_markdown/*.md` and
+`glfm_specification/input/gitlab_flavored_markdown/*.md`.
+
+See the main [specification files](#specification-files) section for more context and details.
##### GitHub Flavored Markdown specification
-[`glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt)
-is the official latest [GFM `spec.txt`](https://github.com/github/cmark-gfm/blob/master/test/spec.txt).
+[`glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md)
+is a copy of the official latest [GFM `spec.txt`](https://github.com/github/cmark-gfm/blob/master/test/spec.txt).
-- It is automatically downloaded and updated by `update-specification.rb` script.
+- It is automatically downloaded and updated by the `update-specification.rb` script.
- When it is downloaded, the version number is added to the filename.
+- The extension is changed from `*.txt` to `*.md` so that it can be handled better by Markdown editors.
NOTE:
-This file uses the `ghfm` acronym instead of `gfm`, as
+For extra clarity, this file uses the `ghfm` acronym in its name instead of `gfm`, as
explained in the [Acronyms section](#acronyms-glfm-ghfm-gfm-commonmark).
-##### `glfm_intro.txt`
+##### `glfm_intro.md`
-[`glfm_specification/input/gitlab_flavored_markdown/glfm_intro.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.txt)
+[`glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md)
is the GitLab-specific version of the prose in the introduction section of the GLFM specification.
- It is manually updated.
@@ -690,13 +805,24 @@ is the GitLab-specific version of the prose in the introduction section of the G
##### `glfm_canonical_examples.txt`
-[`glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt)
-is the manually updated canonical Markdown+HTML examples for GLFM extensions.
+The `glfm_canonical_examples.txt` file is deprecated and no longer exists. It has been replaced by two files:
-- It contains examples in the [standard backtick-delimited `spec.txt` format](#various-markdown-specifications),
- each of which contain a Markdown example and the corresponding canonical HTML.
+- [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd)
+ which contains the [GLFM official specification](#official-specifications) examples.
+- [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd)
+ which contains the [GLFM internal extension](#internal-extensions) examples.
+
+##### `glfm_official_specification_examples.md`
+
+[`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md)
+consists of the manually updated Markdown+HTML examples for the
+[GLFM official specification](#official-specifications), and their associated documentation and descriptions.
+
+- It contains [Markdown examples](#markdown-examples) in the
+ [standard backtick-delimited `spec.txt` format](#various-markdown-specifications),
+ each of which contains Markdown and the corresponding canonical HTML that should be rendered.
- For all GitLab examples, the "extension" annotation after the backticks should consist of only
- `example gitlab`. It does not currently include any additional extension annotations describing
+ `example`. It does not currently include any additional extension annotations describing
the specific Markdown, unlike the GitHub Flavored Markdown examples, which do include
these additional annotations (such as `example strikethrough`).
- The `update-specification.rb` script inserts it as new sections before the appendix
@@ -706,7 +832,53 @@ is the manually updated canonical Markdown+HTML examples for GLFM extensions.
- `H3` header sections must be nested within `H2` header sections. They cannot be
nested directly within `H1` header sections.
-`glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt` sample entries:
+`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md` sample entries:
+
+<!-- markdownlint-disable MD048 -->
+
+~~~plaintext
+# Section with GLFM official specification examples
+
+## Strong
+
+### Strong with two asterisks
+
+```````````````````````````````` example
+**bold**
+.
+<p><strong>bold</strong></p>
+````````````````````````````````
+
+### Strong with HTML
+
+```````````````````````````````` example
+<strong>
+bold
+</strong>
+.
+<p><strong>
+bold
+</strong></p>
+````````````````````````````````
+~~~
+
+<!-- markdownlint-enable MD048 -->
+
+##### `glfm_internal_extension_examples.md`
+
+[`glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md)
+consists of the manually updated Markdown examples for the
+[GLFM internal extensions](#internal-extensions), and their associated documentation and descriptions.
+
+Its general format is identical to [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd),
+consisting of `H1`, `H2`, or `H3` sections containing [Markdown examples](#markdown-examples) in the
+[standard backtick-delimited `spec.txt` format](#various-markdown-specifications).
+
+However, as described in the [canonical HTML section](#canonical-html), only the Markdown portion of each
+example is specified, and the HTML portion is left empty, because internal extension examples are
+never used for [Markdown conformance testing](#markdown-conformance-testing).
+
+`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md` sample entries:
NOTE:
All lines in this example are prefixed with a `|` character. This prefix helps avoid false
@@ -714,31 +886,40 @@ errors when this file is checked by `markdownlint`, and possible errors in other
The actual file should not have these prefixed `|` characters.
```plaintext
-|# First GitLab-Specific Section with Examples
+|# Section with GLFM Internal Extension Examples
|
-|## Strong but with two asterisks
+|## Video
|
-|```````````````````````````````` example gitlab
-|**bold**
+|```````````````````````````````` example
+|![video](video.m4v "video title")
|.
-|<p><strong>bold</strong></p>
-|````````````````````````````````
-|
-|# Second GitLab-Specific Section with Examples
-|
-|## Strong but with HTML
-|
-|```````````````````````````````` example gitlab
-|<strong>
-|bold
-|</strong>
-|.
-|<p><strong>
-|bold
-|</strong></p>
|````````````````````````````````
```
+#### Input specification configuration files
+
+Input specification configuration files are manually curated YAML files that control various
+aspects of the automated GLFM scripts and processes. They are located at
+`glfm_specification/input/gitlab_flavored_markdown/*.yml`.
+
+See the main [specification files](#specification-files) section for more context and details.
+
+##### Configuration file validation
+
+All of the manually curated example names in the configuration files must correspond to
+an existing [Markdown example](#markdown-examples) name found in
+[`example_snapshots/examples_index.yml`](#glfm_specificationexample_snapshotsexamples_indexyml),
+which is automatically generated based on the [input specification files](#input-specification-files).
+
+If there is an invalid reference to an example name that does not exist, the
+[`scripts/glfm/update-example-snapshots.rb`](#update-example-snapshotsrb-script)
+script fails with a descriptive error.
+
+The only exceptions to this validation are example names beginning with `00_`, which are reserved
+for [YAML aliases](https://yaml.org/spec/1.2.2/#692-node-anchors).
+See the section on [`glfm_example_normalizations.yml`](#glfm_example_normalizationsyml)
+for more details and examples.
+
##### `glfm_example_status.yml`
[`glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml)
@@ -801,8 +982,8 @@ The following optional entries are supported for each example. They all default
##### `glfm_example_normalizations.yml`
[`glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml)
-controls the [normalization](#normalization) process. It allows one or more `regex`/`replacement` pairs
-to be specified for a Markdown example.
+is used to control the [fixture-based normalization](#fixture-based-normalization) process.
+It allows one or more `regex`/`replacement` pairs to be specified for a Markdown example.
- It is manually updated.
- It has a nested structure corresponding to the example and type of entry it refers to.
@@ -811,6 +992,11 @@ to be specified for a Markdown example.
- The YAML anchors use a naming convention based on the index number of the example, to
ensure unique anchor names and avoid naming conflicts.
+NOTE:
+Other approaches to [normalization](#normalization) such as [fixture-based normalization](#fixture-based-normalization)
+or [environment-variable-based normalization](#environment-variable-based-normalization) are always preferable to
+[fixture-based normalization](#fixture-based-normalization).
+
`glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml` sample entries:
```yaml
@@ -891,11 +1077,11 @@ allows control over other aspects of the snapshot example generation process.
#### Output specification files
The `glfm_specification/output` directory contains the CommonMark standard format
-`spec.txt` file which represents the canonical GLFM specification which is generated
+`spec.txt` file which represents the GLFM specification which is generated
by the `update-specification.rb` script. It also contains the rendered `spec.html`
which is generated based on the `spec.txt` as input.
-These output `spec.*` files, which represent the official, canonical GLFM specification,
+These output `spec.*` files, which represent the GLFM specification,
are colocated under the same parent folder `glfm_specification` with the other
`input` specification files. They're located here both for convenience, and because they are all
a mix of manually edited and generated files.
@@ -909,12 +1095,16 @@ move or copy a hosted version of the rendered HTML `spec.html` version to anothe
[`glfm_specification/output/spec.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.txt)
is a Markdown specification file, in the standard format
-with prose and Markdown + canonical HTML examples. It is generated or updated by the
-`update-specification.rb` script.
+with prose and Markdown + canonical HTML examples.
It also serves as input for other scripts such as `update-example-snapshots.rb`
and `run-spec-tests.sh`.
+It is generated or updated by the `update-specification.rb` script, using the
+[input specification files](#input-specification-files) as input.
+See the [`update-specification.rb` script section](#update-specificationrb-script)
+for a diagram and more description on this process.
+
##### spec.html
[`glfm_specification/output/spec.html`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html)
@@ -945,14 +1135,14 @@ be manually edited as necessary to help drive the implementations.
[`glfm_specification/example_snapshots/examples_index.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/example_snapshots/examples_index.yml)
is the main list of all
-CommonMark, GFM, and GLFM example names, each with a unique canonical name.
+CommonMark, GFM, and GLFM example names, each with a uniquely identifying name.
- It is generated from the hierarchical sections and examples in the
GFM `spec.txt` specification.
- For CommonMark and GFM examples,
these sections originally came from the GFM `spec.txt`.
-- For GLFM examples, it is generated from `glfm_canonical_examples.txt`, which is
- the additional Section 7 in the GLFM `spec.txt`.
+- For GLFM examples, it is generated from
+ [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) and [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd).
- It also contains extra metadata about each example, such as:
1. `spec_txt_example_position` - The position of the example in the generated GLFM `spec.txt` file.
- This value is the index order of each individual Markdown + HTML5 example in the file. It is _not_
@@ -998,8 +1188,8 @@ for each entry in `glfm_specification/example_snapshots/examples_index.yml`
it is generated (or updated) from the standard GFM
`spec.txt` using the `update-example-snapshots.rb` script.
- For GLFM, it is generated (or updated) from the
- `glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`
- input specification file.
+ [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) and [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd)
+ input specification files.
`glfm_specification/example_snapshots/markdown.yml` sample entry:
@@ -1018,8 +1208,8 @@ Three types of entries exist, with different HTML for each:
- **Canonical**
- The ["Canonical"](#canonicalization-of-html) HTML.
- For CommonMark and GFM examples, the HTML comes from the examples in `spec.txt`.
- - For GLFM examples, it is generated/updated from
- `glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`.
+ - For [GLFM official specification](#official-specifications) examples, it is generated/updated from
+ [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd).
- **Static**
- This is the static (backend (Ruby)-generated) HTML for each entry in
`glfm_specification/example_snapshots/examples_index.yml`.
@@ -1094,13 +1284,14 @@ This section describes how the scripts can be used to manage the GLFM specificat
1. Run [`update-specification.rb`](#update-specificationrb-script) to update the GLFM specification [output specification files](#output-specification-files).
1. Visually inspect and confirm any resulting changes to the [output specification files](#output-specification-files).
-1. Run [`run-spec-tests.sh`](http://gdk.test:3005/ee/development/gitlab_flavored_markdown/specification_guide/index.html#run-spec-testssh-script) to run the conformance tests against the canonicalized GLFM specification.
+1. Run [`run-spec-tests.sh`](#run-spec-testssh-script) to run the conformance tests against the canonicalized GLFM specification.
1. Commit any changes to the [output specification files](#output-specification-files).
### Update the example snapshots and run snapshot tests
1. If you are working on an in-progress feature or bug, make any necessary manual updates to the [input specification files](#input-specification-files). This may include:
- 1. Updating the canonical Markdown or HTML examples in `glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`.
+ 1. Updating the canonical Markdown or HTML examples in
+ [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) or [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd).
1. Updating `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml` to reflect the current status of the examples or tests.
1. Run [`update-specification.rb`](#update-specificationrb-script) to update the `spec.txt` to reflect any changes which were made to the [input specification files](#input-specification-files).
1. Visually inspect and confirm any resulting changes to the [output specification files](#output-specification-files).
diff --git a/doc/development/go_guide/dependencies.md b/doc/development/go_guide/dependencies.md
index 7cad5bbf417..f2b1ae9e7b8 100644
--- a/doc/development/go_guide/dependencies.md
+++ b/doc/development/go_guide/dependencies.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency Management in Go
diff --git a/doc/development/go_guide/go_upgrade.md b/doc/development/go_guide/go_upgrade.md
index 4e2a0d95910..d931140d9da 100644
--- a/doc/development/go_guide/go_upgrade.md
+++ b/doc/development/go_guide/go_upgrade.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Managing Go versions
@@ -158,6 +158,8 @@ if you need help finding the correct person or labels:
| 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) |
| GitLab Workhorse | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) |
+| GitLab Browser-based DAST | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) |
+| GitLab Coverage Fuzzer | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) |
| LabKit | [Issue Tracker](https://gitlab.com/gitlab-org/labkit/-/issues) |
| [Node Exporter](https://github.com/prometheus/node_exporter) | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) |
| [PgBouncer Exporter](https://github.com/prometheus-community/pgbouncer_exporter) | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) |
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 3adafa8750f..197c7616d82 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Go standards and style guidelines
@@ -357,7 +357,7 @@ Every binary ideally must have structured (JSON) logging in place as it helps
with searching and filtering the logs. At GitLab we use structured logging in
JSON format, as all our infrastructure assumes that. When using
[Logrus](https://github.com/sirupsen/logrus) you can turn on structured
-logging simply by using the build in [JSON formatter](https://github.com/sirupsen/logrus#formatters). This follows the
+logging by using the build in [JSON formatter](https://github.com/sirupsen/logrus#formatters). This follows the
same logging type we use in our [Ruby applications](../logging.md#use-structured-json-logging).
#### How to use Logrus
@@ -436,6 +436,25 @@ of the Code Review Comments page on the Go wiki for more details.
Most editors/IDEs allow you to run commands before/after saving a file, you can set it
up to run `goimports -local gitlab.com/gitlab-org` so that it's applied to every file when saving.
+### Naming branches
+
+Only use the characters `a-z`, `0-9` or `-` in branch names. This restriction is due to the fact that `go get` doesn't work as expected when a branch name contains certain characters, such as a slash `/`:
+
+```shell
+$ go get -u gitlab.com/gitlab-org/security-products/analyzers/report/v3@some-user/some-feature
+
+go get: gitlab.com/gitlab-org/security-products/analyzers/report/v3@some-user/some-feature: invalid version: version "some-user/some-feature" invalid: disallowed version string
+```
+
+If a branch name contains a slash, it forces us to refer to the commit SHA instead, which is less flexible. For example:
+
+```shell
+$ go get -u gitlab.com/gitlab-org/security-products/analyzers/report/v3@5c9a4279fa1263755718cf069d54ba8051287954
+
+go: downloading gitlab.com/gitlab-org/security-products/analyzers/report/v3 v3.15.3-0.20221012172609-5c9a4279fa12
+...
+```
+
### Initializing slices
If initializing a slice, provide a capacity where possible to avoid extra
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index af11340737f..25651639170 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gotchas
diff --git a/doc/development/graphql_guide/authorization.md b/doc/development/graphql_guide/authorization.md
index 717a6d29fbc..7b69ce36071 100644
--- a/doc/development/graphql_guide/authorization.md
+++ b/doc/development/graphql_guide/authorization.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL Authorization
diff --git a/doc/development/graphql_guide/batchloader.md b/doc/development/graphql_guide/batchloader.md
index 492d3bc9007..ef0b97f4f62 100644
--- a/doc/development/graphql_guide/batchloader.md
+++ b/doc/development/graphql_guide/batchloader.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL BatchLoader
@@ -134,7 +134,7 @@ z.sync
```
NOTE:
-There is no dependency analysis in the use of batch-loading. There is simply
+There is no dependency analysis in the use of batch-loading. There is
a pending queue of requests, and as soon as any one result is needed, all pending
requests are evaluated.
@@ -146,7 +146,7 @@ def publisher
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Publisher, object.publisher_id).find
end
-# Here we need the publisher in order to generate the catalog URL
+# Here we need the publisher to generate the catalog URL
def catalog_url
::Gitlab::Graphql::Lazy.with_value(publisher) do |p|
UrlHelpers.book_catalog_url(publisher, object.isbn)
diff --git a/doc/development/graphql_guide/graphql_pro.md b/doc/development/graphql_guide/graphql_pro.md
index 3170f0cfdc2..ec28ceb4f20 100644
--- a/doc/development/graphql_guide/graphql_pro.md
+++ b/doc/development/graphql_guide/graphql_pro.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL Pro
@@ -16,6 +16,6 @@ The main purpose is for support. Per the website:
> creator and maintainer. Get prioritized support for issues and requests.
Note that we **cannot** use the Pro version directly in our product, since we are
-an Open Core product - we can not require customers to purchase the Pro version, nor can we ship it.
+an Open Core product - we cannot require customers to purchase the Pro version, nor can we ship it.
Details on the billing account and gem licensing can be found in the Engineering 1Password vault.
diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md
index 412825e06d3..9c6a2559e5c 100644
--- a/doc/development/graphql_guide/index.md
+++ b/doc/development/graphql_guide/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL development guidelines
diff --git a/doc/development/graphql_guide/monitoring.md b/doc/development/graphql_guide/monitoring.md
index 28d1a4a9046..1e4c083653e 100644
--- a/doc/development/graphql_guide/monitoring.md
+++ b/doc/development/graphql_guide/monitoring.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring GraphQL
diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md
index 72f321a1fd2..7b9d2158c60 100644
--- a/doc/development/graphql_guide/pagination.md
+++ b/doc/development/graphql_guide/pagination.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL pagination
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index ea22b33f1bc..158eb19764b 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Internationalization for GitLab
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index 0870a0e6750..757bcc0ebf1 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Translate GitLab to your language
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 43f19f8a9d6..2a086c796c9 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merging translations from Crowdin
@@ -79,7 +79,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
-this information in the language selection dropdown. Therefore, the translation
+this information in the language selection dropdown list. 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/proofreader.md b/doc/development/i18n/proofreader.md
index f986a852567..b5d57f9912b 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Proofread Translations
@@ -65,6 +65,7 @@ are very appreciative of the work done by translators and proofreaders!
- Michael Hahnle - [GitLab](https://gitlab.com/mhah), [Crowdin](https://crowdin.com/profile/mhah)
- Katrin Leinweber - [GitLab](https://gitlab.com/katrinleinweber), [Crowdin](https://crowdin.com/profile/katrinleinweber)
- Vladislav Wanner - [GitLab](https://gitlab.com/RumBugen), [Crowdin](https://crowdin.com/profile/RumBugen)
+ - Daniel Ziegenberg - [GitLab](https://gitlab.com/ziegenberg), [Crowdin](https://crowdin.com/profile/ziegenberg)
- Greek
- Proofreaders needed.
- Hebrew
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index 61f9d7a25c3..2c8d7eac2a6 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Translating GitLab
diff --git a/doc/development/image_scaling.md b/doc/development/image_scaling.md
index 2078db8294c..4b19c21a457 100644
--- a/doc/development/image_scaling.md
+++ b/doc/development/image_scaling.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
group: Application Performance
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Image scaling guide
@@ -13,7 +13,7 @@ For a general introduction to the history of image scaling at GitLab, you might
## Why image scaling?
-Since version 13.6, GitLab scales down images on demand in order to reduce the page data footprint.
+Since version 13.6, GitLab scales down images on demand to reduce the page data footprint.
This both reduces the amount of data "on the wire", but also helps with rendering performance,
since the browser has less work to do.
@@ -68,7 +68,7 @@ controller mixin. Upon receiving a request coming from a client through Workhors
it should trigger the image scaler as per the criteria mentioned above, and if so, render a special response
header field (`Gitlab-Workhorse-Send-Data`) with the necessary parameters for Workhorse to carry
out the scaling request. If Rails decides the request does not constitute a valid image scaling request,
-we simply follow the path we take to serve any ordinary upload.
+we follow the path we take to serve any ordinary upload.
### Workhorse
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index c66ac0418ac..f864dd3b678 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import/Export development documentation
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index 1f3bf860257..b879d635350 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Test Import Project
@@ -16,7 +16,7 @@ There are several ways to import a project.
### Importing via UI
-The first option is to simply [import the Project tarball file via the GitLab UI](../user/project/settings/import_export.md#import-a-project-and-its-data):
+The first option is to [import the Project tarball file via the GitLab UI](../user/project/settings/import_export.md#import-a-project-and-its-data):
1. Create the group `qa-perf-testing`
1. Import the [GitLab FOSS project tarball](https://gitlab.com/gitlab-org/quality/performance-data/-/blob/master/projects_export/gitlabhq_export.tar.gz) into the Group.
@@ -59,7 +59,7 @@ This script was introduced in GitLab 12.6 for importing large GitLab project exp
As part of this script we also disable direct and background upload to avoid situations where a huge archive is being uploaded to GCS (while being inside a transaction, which can cause idle transaction timeouts).
-We can simply run this script from the terminal:
+We can run this script from the terminal:
Parameters:
@@ -111,7 +111,7 @@ The specified project export file in `archive_path` is missing.
##### `Exception: Permission denied @ rb_sysopen - (filename)`
-The specified project export file can not be accessed by the `git` user.
+The specified project export file cannot be accessed by the `git` user.
Setting the file owner to `git:git`, changing the file permissions to `0400`, and moving it to a
public folder (for example `/tmp/`) fixes the issue.
diff --git a/doc/development/index.md b/doc/development/index.md
index 34e6f466664..d4a34051bc8 100644
--- a/doc/development/index.md
+++ b/doc/development/index.md
@@ -3,7 +3,7 @@ comments: false
type: index, dev
stage: none
group: Development
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
description: "Development Guidelines: learn how to contribute to GitLab."
---
diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md
index 8fd1f0e331d..d7d0ea48db0 100644
--- a/doc/development/integrations/codesandbox.md
+++ b/doc/development/integrations/codesandbox.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up local CodeSandbox development environment
diff --git a/doc/development/integrations/index.md b/doc/development/integrations/index.md
index 0387ba2e4dd..a0a81775391 100644
--- a/doc/development/integrations/index.md
+++ b/doc/development/integrations/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "GitLab's development guidelines for Integrations"
---
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index bb541d26df2..f314f4536e2 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# How to run Jenkins in development environment (on macOS) **(FREE)**
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
index ade81e29ffb..fb0d239db46 100644
--- a/doc/development/integrations/jira_connect.md
+++ b/doc/development/integrations/jira_connect.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up a development environment **(FREE)**
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 2c5dd1c0500..f40caf29cfa 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Security scanner integration
@@ -180,7 +180,7 @@ Here are some examples to get you started:
As documented in the [Docker Official Images](https://github.com/docker-library/official-images#tags-and-aliases) project,
it is strongly encouraged that version number tags be given aliases which allows the user to easily refer to the "most recent" release of a particular series.
-See also [Docker Tagging: Best practices for tagging and versioning Docker images](https://docs.microsoft.com/en-us/archive/blogs/stevelasker/docker-tagging-best-practices-for-tagging-and-versioning-docker-images).
+See also [Docker Tagging: Best practices for tagging and versioning Docker images](https://learn.microsoft.com/en-us/archive/blogs/stevelasker/docker-tagging-best-practices-for-tagging-and-versioning-docker-images).
## Command line
@@ -358,6 +358,10 @@ analyzer to use the latest available schemas.
After the deprecation period for a schema version, the file is removed from GitLab. Reports that
declare removed versions are rejected, and an error message displays on the corresponding pipeline.
+If a report uses a `PATCH` version that doesn't match any vendored schema version, it is validated against
+the latest vendored `PATCH` version. For example, if a report version is 14.0.23 and the latest vendored
+version is 14.0.6, the report is validated against version 14.0.6.
+
GitLab uses the
[`json_schemer`](https://www.rubydoc.info/gems/json_schemer) gem to perform validation.
@@ -430,10 +434,29 @@ The value of the `category` field matches the report type:
- `sast`
- `dast`
-##### Scanner
+##### Scan
+
+The `scan` field is an object that embeds meta information about the scan itself: the `analyzer`
+and `scanner` that performed the scan, the `start_time` and `end_time` the scan executed,
+and `status` of the scan (either "success" or "failure").
+
+Both the `analyzer` and `scanner` fields are objects that embeds a human-readable `name` and a technical `id`.
+The `id` should not collide with any other analyzers or scanners another integrator would provide.
+
+##### Scan Primary Identifiers
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368284) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `sec_mark_dropped_findings_as_resolved`. Disabled by default.
+
+The `scan.primary_identifiers` field is an optional field containing an array of
+[primary identifiers](../../user/application_security/terminology/index.md#primary-identifier)).
+This is an exhaustive list of all rulesets for which the analyzer performed the scan.
+
+Even when the [`Vulnerabilities`](#vulnerabilities) array for a given scan may be empty, this optional field
+should contain the complete list of potential identifiers to inform the Rails application of which
+rules were executed.
-The `scanner` field is an object that embeds a human-readable `name` and a technical `id`.
-The `id` should not collide with any other scanner another integrator would provide.
+When populated, the Rails application will automatically resolve previously detected vulnerabilities as no
+longer relevant when their primary identifier is not included.
##### Name, message, and description
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index 63f86a3f95d..ba0654971d3 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Secure Partner Integration - Onboarding Process
diff --git a/doc/development/interacting_components.md b/doc/development/interacting_components.md
index c137faf464c..f4becd06245 100644
--- a/doc/development/interacting_components.md
+++ b/doc/development/interacting_components.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Developing against interacting components or features
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index c35d40a7b7f..9b77a20a0d6 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -1,13 +1,13 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
# Internal API **(FREE)**
-The internal API is used by different GitLab components, it can not be
+The internal API is used by different GitLab components, it cannot be
used by other consumers. This documentation is intended for people
working on the GitLab codebase.
@@ -21,7 +21,7 @@ Before adding a new internal endpoint, consider if the API would potentially be
useful to the wider GitLab community and can be made externally accessible.
One reason we might favor internal API endpoints sometimes is when using such an endpoint requires
-internal data that external actors can not have. For example, in the internal Pages API we might use
+internal data that external actors cannot have. For example, in the internal Pages API we might use
a secret token that identifies a request as internal or sign a request with a public key that is
not available to a wider community.
@@ -665,8 +665,7 @@ Example response:
## Subscriptions
-The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
-in order to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com.
+The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`) to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com.
### Creating a subscription
@@ -966,3 +965,253 @@ Example response:
### Known consumers
- CustomersDot
+
+## SCIM API **(PREMIUM SAAS)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10.
+
+The SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for
+**system** use for SCIM provider integration, it is subject to change without notice.
+
+To use this API, [Group SSO](../../user/group/saml_sso/index.md) must be enabled for the group.
+This API is only in use where [SCIM for Group SSO](../../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities.
+
+Not to be confused with the [main SCIM API](../../api/scim.md).
+
+### Get a list of SCIM provisioned users
+
+This endpoint is used as part of the SCIM syncing mechanism. It only returns
+a single user based on a unique ID which should match the `extern_uid` of the user.
+
+```plaintext
+GET /api/scim/v2/groups/:group_path/Users
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `filter` | string | no | A [filter](#available-filters) expression. |
+| `group_path` | string | yes | Full path to the group. |
+| `startIndex` | integer | no | The 1-based index indicating where to start returning results from. A value of less than one will be interpreted as 1. |
+| `count` | integer | no | Desired maximum number of query results. |
+
+NOTE:
+Pagination follows the [SCIM spec](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.4) rather than GitLab pagination as used elsewhere. If records change between requests it is possible for a page to either be missing records that have moved to a different page or repeat records from a previous request.
+
+Example request:
+
+```shell
+curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" \
+ --header "Authorization: Bearer <your_scim_token>" \
+ --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:api:messages:2.0:ListResponse"
+ ],
+ "totalResults": 1,
+ "itemsPerPage": 20,
+ "startIndex": 1,
+ "Resources": [
+ {
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+ }
+ ]
+}
+```
+
+### Get a single SCIM provisioned user
+
+```plaintext
+GET /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+
+Example request:
+
+```shell
+curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+}
+```
+
+### Create a SCIM provisioned user
+
+```plaintext
+POST /api/scim/v2/groups/:group_path/Users/
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:---------------|:----------|:----|:--------------------------|
+| `externalId` | string | yes | External UID of the user. |
+| `userName` | string | yes | Username of the user. |
+| `emails` | JSON string | yes | Work email. |
+| `name` | JSON string | yes | Name of the user. |
+| `meta` | string | no | Resource type (`User`). |
+
+Example request:
+
+```shell
+curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" \
+ --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+}
+```
+
+Returns a `201` status code if successful.
+
+### Update a single SCIM provisioned user
+
+Fields that can be updated are:
+
+| SCIM/IdP field | GitLab field |
+|:---------------------------------|:-----------------------------------------------------------------------------|
+| `id/externalId` | `extern_uid` |
+| `name.formatted` | `name` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
+| `emails\[type eq "work"\].value` | `email` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
+| `active` | Identity removal if `active` = `false` |
+| `userName` | `username` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
+
+```plaintext
+PATCH /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+| `Operations` | JSON string | yes | An [operations](#available-operations) expression. |
+
+Example request:
+
+```shell
+curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Returns an empty response with a `204` status code if successful.
+
+### Remove a single SCIM provisioned user
+
+Removes the user's SSO identity and group membership.
+
+```plaintext
+DELETE /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ------------ | ------ | -------- | ------------------------- |
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+
+Example request:
+
+```shell
+curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Returns an empty response with a `204` status code if successful.
+
+### Available filters
+
+They match an expression as specified in [the RFC7644 filtering section](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.2).
+
+| Filter | Description |
+| ----- | ----------- |
+| `eq` | The attribute matches exactly the specified value. |
+
+Example:
+
+```plaintext
+id eq a-b-c-d
+```
+
+### Available operations
+
+They perform an operation as specified in [the RFC7644 update section](https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2).
+
+| Operator | Description |
+| ----- | ----------- |
+| `Replace` | The attribute's value is updated. |
+| `Add` | The attribute has a new value. |
+
+Example:
+
+```json
+{ "op": "Add", "path": "name.formatted", "value": "New Name" }
+```
diff --git a/doc/development/internal_api/internal_api_allowed.md b/doc/development/internal_api/internal_api_allowed.md
index 83dbb54babd..89c76c88df4 100644
--- a/doc/development/internal_api/internal_api_allowed.md
+++ b/doc/development/internal_api/internal_api_allowed.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, api
---
diff --git a/doc/development/internal_users.md b/doc/development/internal_users.md
index 24785c0cf48..67000d969af 100644
--- a/doc/development/internal_users.md
+++ b/doc/development/internal_users.md
@@ -3,7 +3,7 @@ description: "Internal users documentation."
type: concepts, reference, dev
stage: none
group: Development
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Internal users
diff --git a/doc/development/issuable-like-models.md b/doc/development/issuable-like-models.md
index 42dfe2e0f2f..0b48883fe58 100644
--- a/doc/development/issuable-like-models.md
+++ b/doc/development/issuable-like-models.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issuable-like Rails models utilities
diff --git a/doc/development/issue_types.md b/doc/development/issue_types.md
index 820c37aeb14..465f539e026 100644
--- a/doc/development/issue_types.md
+++ b/doc/development/issue_types.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue Types (DEPRECATED)
@@ -42,7 +42,7 @@ issues or when linking objects of the type from Epics. It should use the same
- You can't close it from a commit or a merge request.
- You can't mark it as related to another issue.
-If an Issue type can not be used you can still define a first-class type and
+If an Issue type cannot be used you can still define a first-class type and
then include concerns such as `Issuable` or `Noteable` to reuse functionality
which is common for all our issue-related resources. But you still need to
define the interface for working with the new resource and update some other
diff --git a/doc/development/json.md b/doc/development/json.md
new file mode 100644
index 00000000000..8a2575401fb
--- /dev/null
+++ b/doc/development/json.md
@@ -0,0 +1,46 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# JSON Guidelines
+
+At GitLab we handle a lot of JSON data. To best ensure we remain performant
+when handling large JSON encodes or decodes, we use our own JSON class
+instead of the default methods.
+
+## `Gitlab::Json`
+
+This class should be used in place of any calls to the default `JSON` class,
+`.to_json` calls, and the like. It implements the majority of the public
+methods provided by `JSON`, such as `.parse`, `.generate`, `.dump`, etc, and
+should be entirely identical in its response.
+
+The difference being that by sending all JSON handling through `Gitlab::Json`
+we can change the gem being used in the background. We use `oj`
+instead of the `json` gem, which uses C extensions and is therefore notably
+faster.
+
+This class came into existence because, due to the age of the GitLab application,
+it was proving impossible to just replace the `json` gem with `oj` by default because:
+
+- The number of tests with exact expectations of the responses.
+- The subtle variances between different JSON processors, particularly
+ around formatting.
+
+The `Gitlab::Json` class takes this into account and can
+vary the adapter based on the use case, and account for outdated formatting
+expectations.
+
+## `Gitlab::Json::PrecompiledJson`
+
+This class is used by our hooks into the Grape framework to ensure that
+already-generated JSON is not then run through JSON generation
+a second time when returning the response.
+
+## `Gitlab::Json::LimitedEncoder`
+
+This class can be used to generate JSON but fail with an error if the
+resulting JSON would be too large. The default limit for the `.encode`
+method is 25 MB, but this can be customized when using the method.
diff --git a/doc/development/kubernetes.md b/doc/development/kubernetes.md
index 1c83bef5620..e7764326db3 100644
--- a/doc/development/kubernetes.md
+++ b/doc/development/kubernetes.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Kubernetes integration - development guidelines **(FREE)**
diff --git a/doc/development/lfs.md b/doc/development/lfs.md
index 20157e9e805..4d3371af1d4 100644
--- a/doc/development/lfs.md
+++ b/doc/development/lfs.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Git LFS **(FREE)**
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index a50c514733e..d7dfdb7357d 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Licensing and Compatibility
@@ -18,7 +18,7 @@ Some gems may not include their license information in their `gemspec` file, and
### License Finder commands
-There are a few basic commands License Finder provides that you need in order to manage license detection.
+There are a few basic commands License Finder provides that you need to manage license detection.
To verify that the checks are passing, and/or to see what dependencies are causing the checks to fail:
diff --git a/doc/development/logging.md b/doc/development/logging.md
index 467fb68f3ae..44a47f96de1 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Developers Guide to Logging **(FREE)**
diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md
index f70cca1040e..b61b7472385 100644
--- a/doc/development/maintenance_mode.md
+++ b/doc/development/maintenance_mode.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Internal workings of GitLab Maintenance Mode **(PREMIUM SELF)**
diff --git a/doc/development/mass_insert.md b/doc/development/mass_insert.md
index 4b1716ff00a..24f6127a3de 100644
--- a/doc/development/mass_insert.md
+++ b/doc/development/mass_insert.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Mass inserting Rails models
diff --git a/doc/development/merge_request_application_and_rate_limit_guidelines.md b/doc/development/merge_request_application_and_rate_limit_guidelines.md
index 62bf62f6275..07a48ad7723 100644
--- a/doc/development/merge_request_application_and_rate_limit_guidelines.md
+++ b/doc/development/merge_request_application_and_rate_limit_guidelines.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Application and rate limit guidelines
diff --git a/doc/development/merge_request_concepts/index.md b/doc/development/merge_request_concepts/index.md
index d463f6ba290..14d9582ad84 100644
--- a/doc/development/merge_request_concepts/index.md
+++ b/doc/development/merge_request_concepts/index.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: Create
group: Code Review
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Merge request concepts
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 895fc6f92a4..9d1489836fb 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge Request Performance Guidelines
@@ -44,7 +44,7 @@ and running.
Can the queries used potentially take down any critical services and result in
engineers being woken up in the night? Can a malicious user abuse the code to
-take down a GitLab instance? Do my changes simply make loading a certain page
+take down a GitLab instance? Do my changes make loading a certain page
slower? Does execution time grow exponentially given enough load or data in the
database?
@@ -281,7 +281,7 @@ be clearly mentioned in the merge request description.
## Batch process
**Summary:** Iterating a single process to external services (for example, PostgreSQL, Redis, Object Storage)
-should be executed in a **batch-style** in order to reduce connection overheads.
+should be executed in a **batch-style** to reduce connection overheads.
For fetching rows from various tables in a batch-style, please see [Eager Loading](#eager-loading) section.
@@ -488,7 +488,7 @@ We can consider the following types of storages:
- **Object-based persistent storage** (long term storage) this type of storage uses external
services like [AWS S3](https://en.wikipedia.org/wiki/Amazon_S3). The Object Storage
can be treated as infinitely scalable and redundant. Accessing this storage usually requires
- downloading the file in order to manipulate it. The Object Storage can be considered as an ultimate
+ downloading the file to manipulate it. The Object Storage can be considered as an ultimate
solution, as by definition it can be assumed that it can handle unlimited concurrent uploads
and downloads of files. This is also ultimate solution required to ensure that application can
run in containerized deployments (Kubernetes) at ease.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 4e569579f37..f59c1fd8368 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migration Style Guide
@@ -175,6 +175,14 @@ git checkout origin/master db/structure.sql
VERSION=<migration ID> bundle exec rails db:migrate:main
```
+### Adding new tables to GitLab Schema
+
+GitLab connects to two different Postgres databases: `main` and `ci`. New tables should be defined in [`lib/gitlab/database/gitlab_schemas.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/gitlab_schemas.yml) with the databases they need to be added to.
+
+ ```yaml
+ <TABLE_NAME>: :gitlab_main
+ ```
+
## Avoiding downtime
The document ["Avoiding downtime in migrations"](database/avoiding_downtime_in_migrations.md) specifies
@@ -267,7 +275,7 @@ in that limit. Singular query timings should fit within the [standard limit](dat
In case you need to insert, update, or delete a significant amount of data, you:
- Must disable the single transaction with `disable_ddl_transaction!`.
-- Should consider doing it in a [Background Migration](database/background_migrations.md).
+- Should consider doing it in a [batched background migration](database/batched_background_migrations.md).
## Migration helpers and versioning
@@ -604,7 +612,7 @@ Note that it is not necessary to check if the index exists prior to
removing it, however it is required to specify the name of the
index that is being removed. This can be done either by passing the name
as an option to the appropriate form of `remove_index` or `remove_concurrent_index`,
-or more simply by using the `remove_concurrent_index_by_name` method. Explicitly
+or by using the `remove_concurrent_index_by_name` method. Explicitly
specifying the name is important to ensure the correct index is removed.
For a small table (such as an empty one or one with less than `1,000` records),
@@ -982,6 +990,43 @@ NOTE:
`add_sequence` should be avoided for columns with foreign keys.
Adding sequence to these columns is **only allowed** in the down method (restore previous schema state).
+## Swapping primary key
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98645) in GitLab 15.5.
+
+Swapping the primary key is required to partition a table as the **partition key must be included in the primary key**.
+
+You can use the `swap_primary_key` method provided by the database team.
+
+Under the hood, it works like this:
+
+- Drop the primary key constraint.
+- Add the primary key using the index defined beforehand.
+
+```ruby
+class SwapPrimaryKey < Gitlab::Database::Migration[2.0]
+ TABLE_NAME = :table_name
+ PRIMARY_KEY = :table_name_pkey
+ OLD_INDEX_NAME = :old_index_name
+ NEW_INDEX_NAME = :new_index_name
+
+ def up
+ swap_primary_key(TABLE_NAME, PRIMARY_KEY, NEW_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_INDEX_NAME)
+ add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_INDEX_NAME)
+
+ unswap_primary_key(TABLE_NAME, PRIMARY_KEY, OLD_INDEX_NAME)
+ end
+end
+```
+
+NOTE:
+Make sure to introduce the new index beforehand in a separate migration in order
+to swap the primary key.
+
## Integer column type
By default, an integer column can hold up to a 4-byte (32-bit) number. That is
@@ -1221,7 +1266,7 @@ by an integer. For example: `users` would turn into `users0`
## Using models in migrations (discouraged)
The use of models in migrations is generally discouraged. As such models are
-[contraindicated for background migrations](database/background_migrations.md#isolation),
+[contraindicated for batched background migrations](database/batched_background_migrations.md#isolation),
the model needs to be declared in the migration.
If using a model in the migrations, you should first
@@ -1236,7 +1281,7 @@ in a previous migration.
### Example: Add a column `my_column` to the users table
-It is important not to leave out the `User.reset_column_information` command, in order to ensure that the old schema is dropped from the cache and ActiveRecord loads the updated schema information.
+It is important not to leave out the `User.reset_column_information` command, to ensure that the old schema is dropped from the cache and ActiveRecord loads the updated schema information.
```ruby
class AddAndSeedMyColumn < Gitlab::Database::Migration[2.0]
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 8e39186d396..733823d7f6e 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Modules with instance variables could be considered harmful
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index 0f3531cf5dd..808554d6027 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Backwards compatibility across updates
diff --git a/doc/development/omnibus.md b/doc/development/omnibus.md
index 4e2f2b0c763..a0ba2751a06 100644
--- a/doc/development/omnibus.md
+++ b/doc/development/omnibus.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# What you should know about Omnibus packages
diff --git a/doc/development/packages.md b/doc/development/packages.md
deleted file mode 100644
index a79f5f09677..00000000000
--- a/doc/development/packages.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'packages/index.md'
-remove_date: '2022-08-19'
----
-
-This document was moved to [another location](packages/index.md).
-
-<!-- This redirect file can be deleted after <2022-08-19>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/packages/debian_repository.md b/doc/development/packages/debian_repository.md
index a417ced2e65..71f6c916652 100644
--- a/doc/development/packages/debian_repository.md
+++ b/doc/development/packages/debian_repository.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Debian Repository
diff --git a/doc/development/packages/dependency_proxy.md b/doc/development/packages/dependency_proxy.md
new file mode 100644
index 00000000000..f3e323fb9fa
--- /dev/null
+++ b/doc/development/packages/dependency_proxy.md
@@ -0,0 +1,197 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Dependency Proxy
+
+The Dependency Proxy is a pull-through-cache for registry images from DockerHub. This document describes how this
+feature is constructed in GitLab.
+
+## Container registry
+
+The Dependency Proxy for the container registry acts a stand-in for a remote container registry. In our case,
+the remote registry is the public DockerHub registry.
+
+```mermaid
+flowchart TD
+ id1([$ docker]) --> id2([GitLab Dependency Proxy])
+ id2 --> id3([DockerHub])
+```
+
+From the user's perspective, the GitLab instance is just a container registry that they are interacting with to
+pull images by using `docker login gitlab.com`
+
+When you use `docker login gitlab.com`, the Docker client uses the [v2 API](https://docs.docker.com/registry/spec/api/)
+to make requests.
+
+To support authentication, we must include one route:
+
+- [API Version Check](https://docs.docker.com/registry/spec/api/#api-version-check)
+
+To support `docker pull` requests, we must include two additional routes:
+
+- [Pulling an image manifest](https://docs.docker.com/registry/spec/api/#pulling-an-image-manifest)
+- [Pulling an image layer (blob)](https://docs.docker.com/registry/spec/api/#pulling-a-layer)
+
+These routes are defined in [`gitlab-org/gitlab/config/routes/group.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/3f76455ac9cf90a927767e55c837d6b07af818df/config/routes/group.rb#L164-175).
+
+In its simplest form, the Dependency Proxy manages three requests:
+
+- Logging in / returning a JWT
+- Fetching a manifest
+- Fetching a blob
+
+Here is what the general request sequence looks like for the Dependency Proxy:
+
+```mermaid
+sequenceDiagram
+ Client->>+GitLab: Login? / request token
+ GitLab->>+Client: JWT
+ Client->>+GitLab: request a manifest for an image
+ GitLab->>+ExternalRegistry: request JWT
+ ExternalRegistry->>+GitLab : JWT
+ GitLab->>+ExternalRegistry : request manifest
+ ExternalRegistry->>+GitLab : return manifest
+ GitLab->>+GitLab : store manifest
+ GitLab->>+Client : return manifest
+ loop request image layers
+ Client->>+GitLab: request a blob from the manifest
+ GitLab->>+ExternalRegistry: request JWT
+ ExternalRegistry->>+GitLab : JWT
+ GitLab->>+ExternalRegistry : request blob
+ ExternalRegistry->>+GitLab : return blob
+ GitLab->>+GitLab : store blob
+ GitLab->>+Client : return blob
+ end
+```
+
+### Authentication and authorization
+
+When a Docker client authenticates with a registry, the registry tells the client where to get a JSON Web Token
+(JWT) and to use it for all subsequent requests. This allows the authentication service to live in a separate
+application from the registry. For example, the GitLab container registry directs Docker clients to get a token
+from `https://gitlab.com/jwt/auth`. This endpoint is part of the `gitlab-org/gitlab` project, also known as the
+rails project or web service.
+
+When a user tries to sign in to the dependency proxy with a Docker client, we must tell it where to get a JWT. We
+can use the same endpoint we use with the container registry: `https://gitlab.com/jwt/auth`. But in our case,
+we tell the Docker client to specify `service=dependency_proxy` in the parameters so can use a separate underlying
+service to generate the token.
+
+This sequence diagram shows the request flow for logging into the Dependency Proxy.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant C as Docker CLI
+ participant R as GitLab (Dependency Proxy)
+
+ Note right of C: User tries `docker login gitlab.com` and enters username/password
+ C->>R: GET /v2/
+ Note left of R: Check for Authorization header, return 401 if none, return 200 if token exists and is valid
+ R->>C: 401 Unauthorized with header "WWW-Authenticate": "Bearer realm=\"http://gitlab.com/jwt/auth\",service=\"registry.docker.io\""
+ Note right of C: Request Oauth token using HTTP Basic Auth
+ C->>R: GET /jwt/auth
+ Note left of R: Token is returned
+ R->>C: 200 OK (with Bearer token included)
+ Note right of C: original request is tested again
+ C->>R: GET /v2/ (this time with `Authorization: Bearer [token]` header)
+ Note right of C: Login Succeeded
+ R->>C: 200 OK
+```
+
+The dependency proxy uses its own authentication service, separate from the authentication managed by the UI
+(`ApplicationController`) and API (`ApiGuard`). Once the service has created a JWT, the `DependencyProxy::ApplicationController`
+manages authentication and authorization for the rest of the requests. It manages the user by using `GitLab::Auth::Result` and
+is similar to the authentication implemented by the Git client requests in `GitHttpClientController`.
+
+### Caching
+
+Blobs are cached artifacts with no logic around them. We cache them by digest. When we receive a request for a new blob,
+we check to see if we have a blob with the requested digest, and return it. Otherwise we fetch it from the external
+registry and cache it.
+
+Manifests are more complicated, partially due to [rate limiting on DockerHub](https://www.docker.com/increase-rate-limits/).
+A manifest is essentially a recipe for creating an image. It has a list of blobs to create a certain image. So
+`alpine:latest` has a manifest associated with it that specifies the blobs needed to create the `alpine:latest`
+image. The interesting part is that `alpine:latest` can change over time, so we can't just cache the manifest and
+assume it is OK to use forever. Instead, we must check the digest of the manifest, which is an Etag. This gets
+interesting because the requests for manifests often don't include the digest. So how do we know if the manifest
+we have cached is still the most up-to-date `alpine:latest`? DockerHub allows free HEAD requests that don't count
+toward their rate limit. The HEAD request returns the manifest digest so we can tell whether or not the one we
+have is stale.
+
+With this knowledge, we have built the following logic to manage manifest requests:
+
+```mermaid
+graph TD
+ A[Receive manifest request] --> | We have the manifest cached.| B{Docker manifest HEAD request}
+ A --> | We do not have manifest cached.| C{Docker manifest GET request}
+ B --> | Digest matches the one in the DB | D[Fetch manifest from cache]
+ B --> | Network failure, cannot reach DockerHub | D[Fetch manifest from cache]
+ B --> | Digest does not match the one in DB | C
+ C --> E[Save manifest to cache, save digest to database]
+ D --> F
+ E --> F[Return manifest]
+```
+
+### Workhorse for file handling
+
+Management of file uploads and caching happens in [Workhorse](../workhorse/index.md). This explains the additional
+[`POST` routes](https://gitlab.com/gitlab-org/gitlab/-/blob/3f76455ac9cf90a927767e55c837d6b07af818df/config/routes/group.rb#L170-173)
+that we have for the Dependency Proxy.
+
+The [send_dependency](https://gitlab.com/gitlab-org/gitlab/-/blob/7359d23f4e078479969c872924150219c6f1665f/app/helpers/workhorse_helper.rb#L46-53)
+method makes a request to Workhorse including the previously fetched JWT from the external registry. Workhorse then
+can use that token to request the manifest or blob the user originally requested. The Workhorse code lives in
+[`workhorse/internal/dependencyproxy/dependencyproxy.go`](https://gitlab.com/gitlab-org/gitlab/-/blob/b8f44a8f3c26efe9932c2ada2df75ef7acb8417b/workhorse/internal/dependencyproxy/dependencyproxy.go#L4).
+
+Once we put it all together, the sequence for requesting an image file looks like this:
+
+```mermaid
+sequenceDiagram
+ Client->>Workhorse: GET /v2/*group_id/dependency_proxy/containers/*image/manifests/*tag
+ Workhorse->>Rails: GET /v2/*group_id/dependency_proxy/containers/*image/manifests/*tag
+ Rails->>Rails: Check DB. Is manifest persisted in cache?
+
+ alt In Cache
+ Rails->>Workhorse: Respond with send-url injector
+ Workhorse->>Client: Send the file to the client
+ else Not In Cache
+ Rails->>Rails: Generate auth token and download URL for the manifest in upstream registry
+ Rails->>Workhorse: Respond with send-dependency injector
+ Workhorse->>External Registry: Request the manifest
+ External Registry->>Workhorse: Download the manifest
+ Workhorse->>Rails: GET /v2/*group_id/dependency_proxy/containers/*image/manifest/*tag/authorize
+ Rails->>Workhorse: Respond with upload instructions
+ Workhorse->>Client: Send the manifest file to the client with original headers
+ Workhorse->>Object Storage: Save the manifest file with some of it's header values
+ Workhorse->>Rails: Finalize the upload
+ end
+```
+
+### Cleanup policies
+
+The cleanup policies for the Dependency Proxy work as time-to-live policies. They allow users to set the number
+of days a file is allowed to remain cached if it has been unread. Since there is no way to associate the blobs
+with the images they belong to (to do this, we would need to build the metadata database that the container registry
+folks built), we can set up rules like "if this blob has not been pulled in 90 days, delete it". This means that
+any files that are continuously getting pulled will not be removed from the cache, but if, for example,
+`alpine:latest` changes and one of the underlying blobs is no longer used, it will eventually get cleaned up
+because it has stopped getting pulled. We use the `read_at` attribute to track the last time a given
+`dependency_proxy_blob` or `dependency_proxy_manifest` was pulled.
+
+These work using a cron worker, [DependencyProxy::CleanupDependencyProxyWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/7359d23f4e078479969c872924150219c6f1665f/app/workers/dependency_proxy/cleanup_dependency_proxy_worker.rb#L4),
+that will kick off two [limited capacity](../sidekiq/limited_capacity_worker.md) workers: one to delete blobs,
+and one to delete manifests. The capacity is set in an [application setting](settings.md#container-registry).
+
+### Historic reference links
+
+- [Dependency proxy for private groups](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46042) - initial authentication implementation
+- [Manifest caching](https://gitlab.com/gitlab-org/gitlab/-/issues/241639) - initial manifest caching implementation
+- [Workhorse for blobs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71890) - initial workhorse implementation
+- [Workhorse for manifest](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73033) - moving manifest cache logic to Workhorse
+- [Deploy token support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64363) - authorization largely updated
+- [SSO support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67373) - changes how policies are checked
diff --git a/doc/development/packages/index.md b/doc/development/packages/index.md
index 55deaa229ba..41d6e1b84fd 100644
--- a/doc/development/packages/index.md
+++ b/doc/development/packages/index.md
@@ -1,13 +1,15 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Registry Development
Development and Architectural documentation for the package registry
+- [Debian repository structure](debian_repository.md)
+- [Dependency proxy structure](dependency_proxy.md)
- [Developing a new format](new_format_development.md)
- [Settings](settings.md)
- [Structure / Schema](structure.md)
diff --git a/doc/development/packages/new_format_development.md b/doc/development/packages/new_format_development.md
index 73a2b2f1f81..e9decea3094 100644
--- a/doc/development/packages/new_format_development.md
+++ b/doc/development/packages/new_format_development.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Developing support for a new package format
diff --git a/doc/development/packages/settings.md b/doc/development/packages/settings.md
index 37961c0504c..d591f708954 100644
--- a/doc/development/packages/settings.md
+++ b/doc/development/packages/settings.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Settings
diff --git a/doc/development/packages/structure.md b/doc/development/packages/structure.md
index f8d9da2cc73..e5426f8e2b8 100644
--- a/doc/development/packages/structure.md
+++ b/doc/development/packages/structure.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Structure
diff --git a/doc/development/pages/index.md b/doc/development/pages/index.md
index af9d4d33683..6ee8a9ac433 100644
--- a/doc/development/pages/index.md
+++ b/doc/development/pages/index.md
@@ -2,7 +2,7 @@
type: reference, dev
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "GitLab's development guidelines for GitLab Pages"
---
diff --git a/doc/development/performance.md b/doc/development/performance.md
index 479782e0ccf..4f22d9ceb03 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Performance Guidelines
@@ -79,7 +79,7 @@ GitLab provides built-in tools to help improve performance and availability:
- [Service measurement](service_measurement.md) for measuring and logging service execution.
GitLab team members can use [GitLab.com's performance monitoring systems](https://about.gitlab.com/handbook/engineering/monitoring/) located at
-[`dashboards.gitlab.net`](https://dashboards.gitlab.net), this requires you to log in using your
+[`dashboards.gitlab.net`](https://dashboards.gitlab.net), this requires you to sign in using your
`@gitlab.com` email address. Non-GitLab team-members are advised to set up their
own Prometheus and Grafana stack.
@@ -391,7 +391,7 @@ We store these results also when running nightly scheduled CI jobs on the
default branch on `gitlab.com`. Statistics of these profiling data are
[available online](https://gitlab-org.gitlab.io/rspec_profiling_stats/). For
example, you can find which tests take longest to run or which execute the most
-queries. This can be handy for optimizing our tests or identifying performance
+queries. Use this to optimize our tests or identify performance
issues in our code.
## Memory optimization
@@ -925,7 +925,7 @@ SOME_CONSTANT = 'bar'
## How to seed a database with millions of rows
You might want millions of project rows in your local database, for example,
-in order to compare relative query performance, or to reproduce a bug. You could
+to compare relative query performance, or to reproduce a bug. You could
do this by hand with SQL commands or using [Mass Inserting Rails Models](mass_insert.md) functionality.
Assuming you are working with ActiveRecord models, you might also find these links helpful:
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index d348d659cad..cc7c1229e50 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Implementing permissions
@@ -37,7 +37,7 @@ Groups and projects can have the following visibility levels:
- private (`0`) - an entity is visible only to the approved members of the entity
By default, subgroups can **not** have higher visibility levels.
-For example, if you create a new private group, it can not include a public subgroup.
+For example, if you create a new private group, it cannot include a public subgroup.
The visibility level of a group can be changed only if all subgroups and
sub-projects have the same or lower visibility level. For example, a group can be set
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 648a2aac339..01e42fda2c9 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -1,7 +1,7 @@
---
stage: none
group: Engineering Productivity
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipelines for the GitLab project
@@ -62,11 +62,14 @@ The test mappings contain a map of each source files to a list of test files whi
In the `detect-tests` job, we use this mapping to identify the minimal tests needed for the current merge request.
+Later on in [the `rspec fail-fast` job](#fail-fast-job-in-merge-request-pipelines), we run the minimal tests needed for the current merge request.
+
#### Exceptional cases
In addition, there are a few circumstances where we would always run the full RSpec tests:
- when the `pipeline:run-all-rspec` label is set on the merge request
+- when the `pipeline:run-full-rspec` label is set on the merge request, this label is assigned by triage automation when the merge request is approved by any reviewer
- when the merge request is created by an automation (for example, Gitaly update or MR targeting a stable branch)
- when the merge request is created in a security mirror
- when any CI configuration file is changed (for example, `.gitlab-ci.yml` or `.gitlab/ci/**/*`)
@@ -92,23 +95,11 @@ In addition, there are a few circumstances where we would always run the full Je
### Fork pipelines
-We only run the minimal RSpec & Jest jobs for fork pipelines unless the `pipeline:run-all-rspec`
+We run only the minimal RSpec & Jest jobs for fork pipelines, unless the `pipeline:run-all-rspec`
label is set on the MR. The goal is to reduce the CI/CD minutes consumed by fork pipelines.
See the [experiment issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1170).
-## Faster feedback when reverting merge requests
-
-When you need to revert a merge request, to get accelerated feedback, you can add the `~pipeline:revert` label to your merge request.
-
-When this label is assigned, the following steps of the CI/CD pipeline are skipped:
-
-- The `e2e:package-and-test` job.
-- The `rspec:undercoverage` job.
-- The entire [Review Apps process](testing_guide/review_apps.md).
-
-Apply the label to the merge request, and run a new pipeline for the MR.
-
## Fail-fast job in merge request pipelines
To provide faster feedback when a merge request breaks existing tests, we are experimenting with a
@@ -155,6 +146,18 @@ merge request. This prevents `rspec fail-fast` duration from exceeding the avera
This number can be overridden by setting a CI/CD variable named `RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD`.
+## Faster feedback when reverting merge requests
+
+When you need to revert a merge request, to get accelerated feedback, you can add the `~pipeline:revert` label to your merge request.
+
+When this label is assigned, the following steps of the CI/CD pipeline are skipped:
+
+- The `e2e:package-and-test` job.
+- The `rspec:undercoverage` job.
+- The entire [Review Apps process](testing_guide/review_apps.md).
+
+Apply the label to the merge request, and run a new pipeline for the MR.
+
## Test jobs
We have dedicated jobs for each [testing level](testing_guide/testing_levels.md) and each job runs depending on the
@@ -356,6 +359,11 @@ with latest `master`, and then it triggers a regular branch pipeline for
never be merged back to `master`. Any other Ruby 3 changes should go into
`master` directly, which should be compatible with Ruby 2.7.
+Previously, `ruby3-sync` was using a project token stored in `RUBY3_SYNC_TOKEN`
+(now backed up in `RUBY3_SYNC_TOKEN_NOT_USED`), however due to various
+permissions issues, we ended up using an access token from `gitlab-bot` so now
+`RUBY3_SYNC_TOKEN` is actually an access token from `gitlab-bot`.
+
### Long-term plan
We follow the [PostgreSQL versions shipped with Omnibus GitLab](../administration/package_information/postgresql_versions.md):
@@ -392,8 +400,7 @@ In general, pipelines for an MR fall into one of the following types (from short
A "pipeline type" is an abstract term that mostly describes the "critical path" (for example, the chain of jobs for which the sum
of individual duration equals the pipeline's duration).
-We use these "pipeline types" in [metrics dashboards](https://app.periscopedata.com/app/gitlab/858266/GitLab-Pipeline-Durations)
-in order to detect what types and jobs need to be optimized first.
+We use these "pipeline types" in [metrics dashboards](https://app.periscopedata.com/app/gitlab/858266/GitLab-Pipeline-Durations) to detect what types and jobs need to be optimized first.
An MR that touches multiple areas would be associated with the longest type applicable. For instance, an MR that touches backend
and frontend would fall into the "Frontend" pipeline type since this type takes longer to finish than the "Backend" pipeline type.
@@ -581,8 +588,9 @@ The current stages are:
### Dependency Proxy
Some of the jobs are using images from Docker Hub, where we also use
-`${GITLAB_DEPENDENCY_PROXY}` as a prefix to the image path, so that we pull
+`${GITLAB_DEPENDENCY_PROXY_ADDRESS}` as a prefix to the image path, so that we pull
images from our [Dependency Proxy](../user/packages/dependency_proxy/index.md).
+By default, this variable is set from the value of `${GITLAB_DEPENDENCY_PROXY}`.
`${GITLAB_DEPENDENCY_PROXY}` is a group CI/CD variable defined in
[`gitlab-org`](https://gitlab.com/gitlab-org) as
@@ -590,13 +598,32 @@ images from our [Dependency Proxy](../user/packages/dependency_proxy/index.md).
defined as:
```yaml
-image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
+image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge
```
Projects in the `gitlab-org` group pull from the Dependency Proxy, while
forks that reside on any other personal namespaces or groups fall back to
Docker Hub unless `${GITLAB_DEPENDENCY_PROXY}` is also defined there.
+#### Work around for when a pipeline is started by a Project access token user
+
+When a pipeline is started by a Project access token user (e.g. the `release-tools approver bot` user which
+automatically updates the Gitaly version used in the main project),
+[the Dependency proxy isn't accessible](https://gitlab.com/gitlab-org/gitlab/-/issues/332411#note_1130388163)
+and the job fails at the `Preparing the "docker+machine" executor` step.
+To work around that, we have a special workflow rule, that overrides the
+`${GITLAB_DEPENDENCY_PROXY_ADDRESS}` variable so that Depdendency proxy isn't used in that case:
+
+```yaml
+- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/'
+ variables:
+ GITLAB_DEPENDENCY_PROXY_ADDRESS: ""
+```
+
+NOTE:
+We don't directly override the `${GITLAB_DEPENDENCY_PROXY}` variable because group-level
+variables have higher precedence over `.gitlab-ci.yml` variables.
+
### Common job definitions
Most of the jobs [extend from a few CI definitions](../ci/yaml/index.md#extends)
@@ -731,7 +758,7 @@ This works well for the following reasons:
- `.static-analysis-cache`
- `.rubocop-cache`
- `.coverage-cache`
- - `.danger-review-cache`
+ - `.ruby-node-cache`
- `.qa-cache`
- `.yarn-cache`
- `.assets-compile-cache` (the key includes `${NODE_ENV}` so it's actually two different caches).
@@ -749,34 +776,87 @@ This works well for the following reasons:
### Artifacts strategy
-We limit the artifacts that are saved and retrieved by jobs to the minimum in order to reduce the upload/download time and costs, as well as the artifacts storage.
+We limit the artifacts that are saved and retrieved by jobs to the minimum to reduce the upload/download time and costs, as well as the artifacts storage.
### Components caching
-Some external components (currently only GitLab Workhorse) of GitLab need to be built from source as a preliminary step for running tests.
+Some external components (GitLab Workhorse and frontend assets) of GitLab need to be built from source as a preliminary step for running tests.
+
+#### `cache-workhorse`
-In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), we introduced a new `build-components` job that:
+In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), and then
+[this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297),
+we introduced a new `cache-workhorse` job that:
- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines
- runs automatically for any `master` commit that touches the `workhorse/` folder
-- is manual for GitLab.com's `gitlab-org`'s MRs
+- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files
This job tries to download a generic package that contains GitLab Workhorse binaries needed in the GitLab test suite (under `tmp/tests/gitlab-workhorse`).
- If the package URL returns a 404:
1. It runs `scripts/setup-test-env`, so that the GitLab Workhorse binaries are built.
1. It then creates an archive which contains the binaries and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/).
-- Otherwise, if the package already exists, it exit the job successfully.
+- Otherwise, if the package already exists, it exits the job successfully.
We also changed the `setup-test-env` job to:
-1. First download the GitLab Workhorse generic package build and uploaded by `build-components`.
+1. First download the GitLab Workhorse generic package build and uploaded by `cache-workhorse`.
1. If the package is retrieved successfully, its content is placed in the right folder (for example, `tmp/tests/gitlab-workhorse`), preventing the building of the binaries when `scripts/setup-test-env` is run later on.
1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab Workhorse binaries are built as part of `scripts/setup-test-env`.
NOTE:
The version of the package is the workhorse tree SHA (for example, `git rev-parse HEAD:workhorse`).
+#### `cache-assets`
+
+In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297),
+we introduced three new `cache-assets:test`, `cache-assets:test as-if-foss`,
+and `cache-assets:production` jobs that:
+
+- never run unless `$CACHE_ASSETS_AS_PACKAGE == "true"`
+- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines
+- runs automatically for any `master` commit that touches the assets-related folders
+- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files
+
+This job tries to download a generic package that contains GitLab compiled assets
+needed in the GitLab test suite (under `app/assets/javascripts/locale/**/app.js`,
+and `public/assets`).
+
+- If the package URL returns a 404:
+ 1. It runs `bin/rake gitlab:assets:compile`, so that the GitLab assets are compiled.
+ 1. It then creates an archive which contains the assets and uploads it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/).
+ The package version is set to the assets folders' hash sum.
+- Otherwise, if the package already exists, it exits the job successfully.
+
+#### `compile-*-assets`
+
+We also changed the `compile-test-assets`, `compile-test-assets as-if-foss`,
+and `compile-production-assets` jobs to:
+
+1. First download the "native" cache assets, which contain:
+ - The [compiled assets](https://gitlab.com/gitlab-org/gitlab/-/blob/a6910c9086bb28e553f5e747ec2dd50af6da3c6b/.gitlab/ci/global.gitlab-ci.yml#L86-87).
+ - A [`cached-assets-hash.txt` file](https://gitlab.com/gitlab-org/gitlab/-/blob/a6910c9086bb28e553f5e747ec2dd50af6da3c6b/.gitlab/ci/global.gitlab-ci.yml#L85)
+ containing the `SHA256` hexdigest of all the source files on which the assets depend on.
+ This list of files is a pessimistic list and the assets might not depend on
+ some of these files. At worst we compile the assets more often, which is better than
+ using outdated assets.
+
+ The file is [created after assets are compiled](https://gitlab.com/gitlab-org/gitlab/-/blob/a6910c9086bb28e553f5e747ec2dd50af6da3c6b/.gitlab/ci/frontend.gitlab-ci.yml#L83).
+1. We then we compute the `SHA256` hexdigest of all the source files the assets depend on, **for the current checked out branch**. We [store the hexdigest in the `GITLAB_ASSETS_HASH` variable](https://gitlab.com/gitlab-org/gitlab/-/blob/a6910c9086bb28e553f5e747ec2dd50af6da3c6b/.gitlab/ci/frontend.gitlab-ci.yml#L27).
+1. If `$CACHE_ASSETS_AS_PACKAGE == "true"`, we download the generic package built and uploaded by [`cache-assets:*`](#cache-assets).
+ - If the cache is up-to-date for the checked out branch, we download the native cache
+ **and** the cache package. We could optimize that by not downloading
+ the genetic package but the native cache is actually very often outdated because it's
+ rebuilt only every 2 hours.
+1. We [run the `assets_compile_script` function](https://gitlab.com/gitlab-org/gitlab/-/blob/a6910c9086bb28e553f5e747ec2dd50af6da3c6b/.gitlab/ci/frontend.gitlab-ci.yml#L35),
+ which [itself runs](https://gitlab.com/gitlab-org/gitlab/-/blob/c023191ef412e868ae957f3341208a41ca678403/scripts/utils.sh#L76)
+ the [`assets:compile` Rake task](https://gitlab.com/gitlab-org/gitlab/-/blob/c023191ef412e868ae957f3341208a41ca678403/lib/tasks/gitlab/assets.rake#L80-109).
+
+ This task is responsible for deciding if assets need to be compiled or not.
+ It [compares the `HEAD` `SHA256` hexdigest from `$GITLAB_ASSETS_HASH` with the `master` hexdigest from `cached-assets-hash.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/c023191ef412e868ae957f3341208a41ca678403/lib/tasks/gitlab/assets.rake#L86).
+1. If the hashes are the same, we don't compile anything. If they're different, we compile the assets.
+
### Pre-clone step
NOTE:
diff --git a/doc/development/policies.md b/doc/development/policies.md
index ddd6b8e9bce..b50d654ed28 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# `DeclarativePolicy` framework
diff --git a/doc/development/polling.md b/doc/development/polling.md
index f854891a528..ff239effb80 100644
--- a/doc/development/polling.md
+++ b/doc/development/polling.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Polling with ETag caching
@@ -61,5 +61,5 @@ route matching easier.
For more information see:
- [`Poll-Interval` header](fe_guide/performance.md#real-time-components)
-- [RFC 7232](https://tools.ietf.org/html/rfc7232)
+- [RFC 7232](https://www.rfc-editor.org/rfc/rfc7232)
- [ETag proposal](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26926)
diff --git a/doc/development/post_deployment_migrations.md b/doc/development/post_deployment_migrations.md
deleted file mode 100644
index c3922718e77..00000000000
--- a/doc/development/post_deployment_migrations.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'database/post_deployment_migrations.md'
-remove_date: '2022-07-08'
----
-
-This document was moved to [another location](database/post_deployment_migrations.md).
-
-<!-- This redirect file can be deleted after <2022-07-08>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/product_qualified_lead_guide/index.md b/doc/development/product_qualified_lead_guide/index.md
index 90b8d905264..89a05d59fc9 100644
--- a/doc/development/product_qualified_lead_guide/index.md
+++ b/doc/development/product_qualified_lead_guide/index.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Product Qualified Lead (PQL) development guide
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index a3142b06e12..3eb2c7c9144 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Profiling
@@ -20,6 +20,9 @@ The first argument to the profiler is either a full URL
(including the instance hostname) or an absolute path, including the
leading slash.
+By default the report dump will be stored in a temporary file, which can be
+interacted with using the [stackprof API](#reading-a-gitlabprofiler-report).
+
When using the script, command-line documentation is available by passing no
arguments.
@@ -31,10 +34,11 @@ For example:
```ruby
Gitlab::Profiler.profile('/my-user')
-# Returns a RubyProf::Profile for the regular operation of this request
+# Returns the location of the temp file where the report dump is stored
class UsersController; def show; sleep 100; end; end
Gitlab::Profiler.profile('/my-user')
-# Returns a RubyProf::Profile where 100 seconds is spent in UsersController#show
+# Returns the location of the temp file where the report dump is stored
+# where 100 seconds is spent in UsersController#show
```
For routes that require authorization you must provide a user to
@@ -52,57 +56,14 @@ documented with the method source.
Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first, logger: Logger.new($stdout))
```
-There is also a RubyProf printer available:
-`Gitlab::Profiler::TotalTimeFlatPrinter`. This acts like
-`RubyProf::FlatPrinter`, but its `min_percent` option works on the method's
-total time, not its self time. (This is because we often spend most of our time
-in library code, but this comes from calls in our application.) It also offers a
-`max_percent` option to help filter out outer calls that aren't useful (like
-`ActionDispatch::Integration::Session#process`).
-
-There is a convenience method for using this,
-`Gitlab::Profiler.print_by_total_time`:
-
-```ruby
-result = Gitlab::Profiler.profile('/my-user')
-Gitlab::Profiler.print_by_total_time(result, max_percent: 60, min_percent: 2)
-# Measure Mode: wall_time
-# Thread ID: 70005223698240
-# Fiber ID: 70004894952580
-# Total: 1.768912
-# Sort by: total_time
-#
-# %self total self wait child calls name
-# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::Helpers::RenderingHelper#render
-# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::Renderer#render_partial
-# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::PartialRenderer#render
-# 0.00 1.007 0.000 0.000 1.007 14 *ActionView::PartialRenderer#render_partial
-# 0.00 0.930 0.000 0.000 0.930 14 Hamlit::TemplateHandler#call
-# 0.00 0.928 0.000 0.000 0.928 14 Temple::Engine#call
-# 0.02 0.865 0.000 0.000 0.864 638 *Enumerable#inject
-```
-
-To print the profile in HTML format, use the following example:
-
-```ruby
-result = Gitlab::Profiler.profile('/my-user')
-
-printer = RubyProf::CallStackPrinter.new(result)
-printer.print(File.open('/tmp/profile.html', 'w'))
-```
-
-### Stackprof support
-
-By default, `Gitlab::Profiler.profile` uses a tracing profiler called [`ruby-prof`](https://ruby-prof.github.io/). However, sampling profilers
-[run faster and use less memory](https://jvns.ca/blog/2017/12/17/how-do-ruby---python-profilers-work-/), so they might be preferred.
-
-You can switch to [Stackprof](https://github.com/tmm1/stackprof) (a sampling profiler) to generate a profile by passing `sampling_mode: true`.
Pass in a `profiler_options` hash to configure the output file (`out`) of the sampling data. For example:
```ruby
-Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first, sampling_mode: true, profiler_options: { out: 'tmp/profile.dump' })
+Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first, profiler_options: { out: 'tmp/profile.dump' })
```
+## Reading a GitLab::Profiler report
+
You can get a summary of where time was spent by running Stackprof against the sampling data. For example:
```shell
@@ -244,7 +205,7 @@ Example output:
```
NOTE:
-This endpoint is only available for Rails web workers. Sidekiq workers can not be inspected this way.
+This endpoint is only available for Rails web workers. Sidekiq workers cannot be inspected this way.
## Settings that impact performance
@@ -286,7 +247,7 @@ The following table lists these variables along with their default values.
([Source](https://github.com/ruby/ruby/blob/45b29754cfba8435bc4980a87cd0d32c648f8a2e/gc.c#L254-L308))
-GitLab may decide to change these settings in order to speed up application performance, lower memory requirements, or both.
+GitLab may decide to change these settings to speed up application performance, lower memory requirements, or both.
You can see how each of these settings affect GC performance, memory use and application start-up time for an idle instance of
GitLab by running the `scripts/perf/gc/collect_gc_stats.rb` script. It will output GC stats and general timing data to standard
diff --git a/doc/development/project_templates.md b/doc/development/project_templates.md
index f688d54ad4f..2f1ded23e38 100644
--- a/doc/development/project_templates.md
+++ b/doc/development/project_templates.md
@@ -1,7 +1,7 @@
---
stage: Manage
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Contribute a built-in project template
@@ -50,7 +50,7 @@ Before GitLab can implement the project template, you must [create a merge reque
1. [Export the project](../user/project/settings/import_export.md#export-a-project-and-its-data)
and save the file as `<name>.tar.gz`, where `<name>` is the short name of the project.
Move this file to the root directory of `gitlab-org/gitlab`.
-1. In `gitlab-org/gitlab`, create and checkout a new branch.
+1. In `gitlab-org/gitlab`, create and check out a new branch.
1. Edit the following files to include the project template:
- For **non-Enterprise** project templates:
- In `lib/gitlab/project_template.rb`, add details about the template
diff --git a/doc/development/projections.md b/doc/development/projections.md
index e1dc37a7ce8..e45a16c267d 100644
--- a/doc/development/projections.md
+++ b/doc/development/projections.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Projections
diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md
index b3f259efc3d..c2caa354567 100644
--- a/doc/development/prometheus_metrics.md
+++ b/doc/development/prometheus_metrics.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with Prometheus Metrics **(FREE)**
diff --git a/doc/development/pry_debugging.md b/doc/development/pry_debugging.md
index 6751559b2ef..8ad584a8edc 100644
--- a/doc/development/pry_debugging.md
+++ b/doc/development/pry_debugging.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pry debugging
diff --git a/doc/development/python_guide/index.md b/doc/development/python_guide/index.md
index 77dd328b513..08d2f46c1cd 100644
--- a/doc/development/python_guide/index.md
+++ b/doc/development/python_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Python Development Guidelines
diff --git a/doc/development/rails_initializers.md b/doc/development/rails_initializers.md
index fca24cf8c01..24647429a57 100644
--- a/doc/development/rails_initializers.md
+++ b/doc/development/rails_initializers.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rails initializers
diff --git a/doc/development/rails_update.md b/doc/development/rails_update.md
index bda21860eae..a541de020fb 100644
--- a/doc/development/rails_update.md
+++ b/doc/development/rails_update.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rails update guidelines
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index f300904fc19..505f480c410 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rake tasks for developers
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index b4deffe162a..3239748193f 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# `ReactiveCaching`
diff --git a/doc/development/real_time.md b/doc/development/real_time.md
index f113d4dd3b7..2aa48fed8eb 100644
--- a/doc/development/real_time.md
+++ b/doc/development/real_time.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Real-Time Features
@@ -19,7 +19,7 @@ out using the instructions below.
## Reuse an existing WebSocket connection
Features reusing an existing connection incur minimal risk. Feature flag rollout
-is recommended in order to give more control to self-hosting customers. However,
+is recommended to give more control to self-hosting customers. However,
it is not necessary to roll out in percentages, or to estimate new connections for
GitLab.com.
diff --git a/doc/development/redis.md b/doc/development/redis.md
index e48048be624..75c7df0737b 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Redis guidelines
diff --git a/doc/development/redis/new_redis_instance.md b/doc/development/redis/new_redis_instance.md
index 24885b40eb9..d9d4bb6a9f8 100644
--- a/doc/development/redis/new_redis_instance.md
+++ b/doc/development/redis/new_redis_instance.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Add a new Redis instance
diff --git a/doc/development/refactoring_guide/index.md b/doc/development/refactoring_guide/index.md
index 9793db3bb85..5dd505ff5c6 100644
--- a/doc/development/refactoring_guide/index.md
+++ b/doc/development/refactoring_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Refactoring guide
@@ -18,14 +18,14 @@ Pinning tests help you ensure that you don't unintentionally change the output o
1. For each possible input, identify the significant possible values.
1. Create a test to save a full detailed snapshot for each helpful combination values per input. This should guarantee that we have "pinned down" the current behavior. The snapshot could be literally a screenshot, a dump of HTML, or even an ordered list of debugging statements.
1. Run all the pinning tests against the code, before you start refactoring (Oracle)
-1. Perform the refactor (or checkout the commit with the work done)
+1. Perform the refactor (or check out the commit with the work done)
1. Run again all the pinning test against the post refactor code (Pin)
1. Compare the Oracle with the Pin. If the Pin is different, you know the refactoring doesn't preserve existing behavior.
1. Repeat the previous three steps as necessary until the refactoring is complete.
### Example commit history
-Leaving in the commits for adding and removing pins helps others checkout and verify the result of the test.
+Leaving in the commits for adding and removing pins helps others check out and verify the result of the test.
```shell
AAAAAA Add pinning tests to funky_foo
@@ -77,7 +77,7 @@ expect(cleanForSnapshot(wrapper.element)).toMatchSnapshot();
- [Pinning test in a Haml to Vue refactor](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27691#pinning-tests)
- [Pinning test in isolating a bug](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/32198#note_212736225)
-- [Pinning test in refactoring dropdown](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28173)
+- [Pinning test in refactoring dropdown list](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28173)
- [Pinning test in refactoring vulnerability_details.vue](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25830/commits)
- [Pinning test in refactoring notes_award_list.vue](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29528#pinning-test)
- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Video of pair programming session on pinning tests](https://youtu.be/LrakPcspBK4)
diff --git a/doc/development/reference_processing.md b/doc/development/reference_processing.md
index 1dfe6496e79..5a026e0a2a0 100644
--- a/doc/development/reference_processing.md
+++ b/doc/development/reference_processing.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'An introduction to reference parsers and reference filters, and a guide to their implementation.'
---
diff --git a/doc/development/renaming_features.md b/doc/development/renaming_features.md
index bd25fa1377e..ee759efd7e2 100644
--- a/doc/development/renaming_features.md
+++ b/doc/development/renaming_features.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Renaming features
diff --git a/doc/development/repository_mirroring.md b/doc/development/repository_mirroring.md
index 573ffaccaf9..a9164398afb 100644
--- a/doc/development/repository_mirroring.md
+++ b/doc/development/repository_mirroring.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository mirroring
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 826782d7036..2701192137c 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Guidelines for reusing abstractions
@@ -63,7 +63,7 @@ do so, but then we'd need as many options as we have features. Every option adds
two code paths, which means that for four features we have to cover 8 different
code paths.
-A much more reliable (and pleasant) way of dealing with this, is to simply use
+A much more reliable (and pleasant) way of dealing with this, is to use
the underlying bits that make up `GroupProjectsFinder` directly. This means we
may need a little bit more code in `IssuableFinder`, but it also gives us much
more control and certainty. This means we might end up with something like this:
@@ -96,7 +96,7 @@ This is just a sketch, but it shows the general idea: we would use whatever the
## End goal
The guidelines in this document are meant to foster _better_ code reuse, by
-clearly defining what can be reused where, and what to do when you can not reuse
+clearly defining what can be reused where, and what to do when you cannot reuse
something. Clearly separating abstractions makes it harder to use the wrong one,
makes it easier to debug the code, and (hopefully) results in fewer performance
problems.
@@ -122,7 +122,7 @@ the various abstractions and what they can (not) reuse:
Everything in `app/controllers`.
-Controllers should not do much work on their own, instead they simply pass input
+Controllers should not do much work on their own, instead they pass input
to other classes and present the results.
### API endpoints
@@ -135,40 +135,70 @@ API endpoints have the same abstraction level as controllers.
Everything that resides in `app/services`.
-Services should consider inheriting from:
-
-- `BaseContainerService` for services scoped by container (project or group)
-- `BaseProjectService` for services scoped to projects
-- `BaseGroupService` for services scoped to groups
-
-or, create a new base class and update the list above.
-
-Legacy classes inherited from `BaseService` for historical reasons.
-
-In Service classes the use of `execute` and `#execute` is preferred over `call` and `#call`.
-
-Model properties should be passed to the constructor in a `params` hash, and will be assigned directly.
-
-To pass extra parameters (which need to be processed, and are not model properties),
-include an `options` hash in the constructor and store it in an instance variable:
-
-```ruby
-# container: Project, or Group
-# current_user: Current user
-# params: Model properties from the controller, already allowlisted with strong parameters
-# options: Configuration for this service, can be any of the following:
-# notify: Whether to send a notifcation to the current user
-# cc: Email address to copy when sending a notification
-def initialize(container:, current_user: nil, params: {}, options: {})
- super(container, current_user, params)
- @options = options
-end
-```
-
-View the [initial discussion](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90008#note_988744060)
-and [further discussion](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90853#note_1053425083).
-
-Classes that are not service objects should be [created elsewhere](directory_structure.md#use-namespaces-to-define-bounded-contexts), such as in `lib`.
+Service classes represent operations that coordinates changes between models
+(such as entities and value objects). Changes impact the state of the application.
+
+1. When an object makes no changes to the state of the application, then it's not a service.
+ It may be a [finder](#finders) or a value object.
+1. When there is no operation, there is no need to execute a service. The class would
+ probably be better designed as an entity, a value object, or a policy.
+
+When implementing a service class, consider:
+
+1. A service class initializer should contain in its arguments:
+ 1. A [model](#models) instance that is being acted upon. Should be first positional
+ argument of the initializer. The argument name of the argument is left to the
+ developer's discretion, such as: `issue`, `project`, `merge_request`.
+ 1. When service represents an action initiated by a user or executed in the
+ context of a user, the initializer must have the `current_user:` keyword argument.
+ Services with `current_user:` argument run high-level business logic.
+ 1. When service does not have a user context and it's not directly initiated
+ by a user (like background service or side-effects), the `current_user:`
+ argument is not needed. This describes low-level domain logic or instance-wide logic.
+ 1. For all additional data required by a service, the explicit keyword arguments are recommended.
+ When a service requires too long of a list of arguments, consider splitting them into:
+ - `params`: A hash with model properties that will be assigned directly.
+ - `options`: A hash with extra parameters (which need to be processed,
+ and are not model properties). The `options` hash should be stored in an instance variable.
+
+ ```ruby
+ # merge_request: A model instance that is being acted upon.
+ # assignee: new MR assignee that will be assigned to the MR
+ # after the service is executed.
+ def initialize(merge_request, assignee:)
+ @merge_request = merge_request
+ @assignee = assignee
+ end
+ ```
+
+ ```ruby
+ # issue: A model instance that is being acted upon.
+ # current_user: Current user.
+ # params: Model properties.
+ # options: Configuration for this service. Can be any of the following:
+ # - notify: Whether to send a notification to the current user.
+ # - cc: Email address to copy when sending a notification.
+ def initialize(issue:, current_user:, params: {}, options: {})
+ @issue = issue
+ @current_user = current_user
+ @params = params
+ @options = options
+ end
+ ```
+
+1. It implements a single public instance method `#execute`, which invokes service class behavior:
+ - The `#execute` method takes no arguments. All required data is passed into initializer.
+ - Optional. If needed, the `#execute` method returns its result via [`ServiceResponse`](#serviceresponse).
+
+Several base classes implement the service classes convention. You may consider inheriting from:
+
+- `BaseContainerService` for services scoped by container (project or group).
+- `BaseProjectService` for services scoped to projects.
+- `BaseGroupService` for services scoped to groups.
+
+Classes that are not service objects should be
+[created elsewhere](directory_structure.md#use-namespaces-to-define-bounded-contexts),
+such as in `lib`.
#### ServiceResponse
@@ -235,7 +265,7 @@ For example: `:job_not_retriable`, `:duplicate_package`, `:merge_request_not_mer
Everything in `app/finders`, typically used for retrieving data from a database.
-Finders can not reuse other finders in an attempt to better control the SQL
+Finders cannot reuse other finders in an attempt to better control the SQL
queries they produce.
Finders' `execute` method should return `ActiveRecord::Relation`. Exceptions
diff --git a/doc/development/routing.md b/doc/development/routing.md
index 54a531730f9..16ed15fdcc6 100644
--- a/doc/development/routing.md
+++ b/doc/development/routing.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Routing
diff --git a/doc/development/ruby3_gotchas.md b/doc/development/ruby3_gotchas.md
index db328b0b1a5..4768d6e1182 100644
--- a/doc/development/ruby3_gotchas.md
+++ b/doc/development/ruby3_gotchas.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ruby 3 gotchas
diff --git a/doc/development/ruby_upgrade.md b/doc/development/ruby_upgrade.md
index 3b89a6fd1ea..ccd65b4e7e9 100644
--- a/doc/development/ruby_upgrade.md
+++ b/doc/development/ruby_upgrade.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ruby upgrade guidelines
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 66f436bd391..671086f33b2 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab scalability
@@ -216,7 +216,7 @@ core. It does not support multi-threading.
Dumb secondaries: Redis secondaries (also known as replicas) don't actually
handle any load. Unlike PostgreSQL secondaries, they don't even serve
-read queries. They simply replicate data from the primary and take over
+read queries. They replicate data from the primary and take over
only when the primary fails.
### Redis Sentinels
diff --git a/doc/development/sec/analyzer_development_guide.md b/doc/development/sec/analyzer_development_guide.md
new file mode 100644
index 00000000000..a35bc2b7237
--- /dev/null
+++ b/doc/development/sec/analyzer_development_guide.md
@@ -0,0 +1,185 @@
+---
+stage: Secure
+group: Static Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Sec section analyzer development
+
+Analyzers are shipped as Docker images to execute within a CI pipeline context. This guide describes development and testing
+practices across analyzers.
+
+## Shared modules
+
+There are a number of shared Go modules shared across analyzers for common behavior and interfaces:
+
+- The [`command`](https://gitlab.com/gitlab-org/security-products/analyzers/command#how-to-use-the-library) Go package implements a CLI interface.
+- The [`common`](https://gitlab.com/gitlab-org/security-products/analyzers/common) project provides miscellaneous shared modules for logging, certificate handling, and directory search capabilities.
+- The [`report`](https://gitlab.com/gitlab-org/security-products/analyzers/report) Go package's `Report` and `Finding` structs marshal JSON reports.
+- The [`template`](https://gitlab.com/gitlab-org/security-products/analyzers/template) project scaffolds new analyzers.
+
+## How to use the analyzers
+
+Analyzers are shipped as Docker images. For example, to run the
+[semgrep](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep) Docker image to scan the working directory:
+
+1. `cd` into the directory of the source code you want to scan.
+1. Run `docker login registry.gitlab.com` and provide username plus
+ [personal](../../user/profile/personal_access_tokens.md#create-a-personal-access-token)
+ or [project](../../user/project/settings/project_access_tokens.md#create-a-project-access-token)
+ access token with at least the `read_registry` scope.
+1. Run the Docker image:
+
+ ```shell
+ docker run \
+ --interactive --tty --rm \
+ --volume "$PWD":/tmp/app \
+ --env CI_PROJECT_DIR=/tmp/app \
+ -w /tmp/app \
+ registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:latest /analyzer run
+ ```
+
+1. The Docker container generates a report in the mounted project directory with a report filename corresponding to the analyzer category. For example, [SAST](../../user/application_security/sast) generates a file named `gl-sast-report.json`.
+
+## Analyzers development
+
+To update the analyzer:
+
+1. Modify the Go source code.
+1. Build a new Docker image.
+1. Run the analyzer against its test project.
+1. Compare the generated report with what's expected.
+
+Here's how to create a Docker image named `analyzer`:
+
+```shell
+docker build -t analyzer .
+```
+
+For example, to test Secret Detection run the following:
+
+```shell
+wget https://gitlab.com/gitlab-org/security-products/ci-templates/-/raw/master/scripts/compare_reports.sh
+sh ./compare_reports.sh sd test/fixtures/gl-secret-detection-report.json test/expect/gl-secret-detection-report.json \
+| patch -Np1 test/expect/gl-secret-detection-report.json && Git commit -m 'Update expectation' test/expect/gl-secret-detection-report.json
+rm compare_reports.sh
+```
+
+You can also compile the binary for your own environment and run it locally
+but `analyze` and `run` probably won't work
+since the runtime dependencies of the analyzer are missing.
+
+Here's an example based on
+[SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs):
+
+```shell
+go build -o analyzer
+./analyzer search test/fixtures
+./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json
+```
+
+## How to test the analyzers
+
+Video walkthrough of how Dependency Scanning analyzers are using [downstream pipeline](../../ci/pipelines/downstream_pipelines.md) feature to test analyzers using test projects:
+
+[![How Sec leverages the downstream pipeline feature of GitLab to test analyzers end to end](http://img.youtube.com/vi/KauRBlfUbDE/0.jpg)](http://www.youtube.com/watch?v=KauRBlfUbDE)
+
+### Testing local changes
+
+To test local changes in the shared modules (such as `command` or `report`) for an analyzer
+you can use the
+[`go mod replace`](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive)
+directive to load `command` with your local changes instead of using the version of command that has been
+tagged remotely. For example:
+
+```shell
+go mod edit -replace gitlab.com/gitlab-org/security-products/analyzers/command/v3=/local/path/to/command
+```
+
+Alternatively you can achieve the same result by manually updating the `go.mod` file:
+
+```plaintext
+module gitlab.com/gitlab-org/security-products/analyzers/awesome-analyzer/v2
+
+replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /path/to/command
+
+require (
+ ...
+ gitlab.com/gitlab-org/security-products/analyzers/command/v3 v2.19.0
+)
+```
+
+#### Testing local changes in Docker
+
+To use Docker with `replace` in the `go.mod` file:
+
+1. Copy the contents of `command` into the directory of the analyzer. `cp -r /path/to/command path/to/analyzer/command`.
+1. Add a copy statement in the analyzer's `Dockerfile`: `COPY command /command`.
+1. Update the `replace` statement to make sure it matches the destination of the `COPY` statement in the step above:
+`replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command`
+
+## Versioning and release process
+
+Analyzers are independent projects that follow their own versioning. `Patch` version bumps tend to correspond to a `Minor` version bump of the underlying tools (i.e. [`bandit`](https://wiki.openstack.org/wiki/Security/Projects/Bandit)), allowing us greater flexibility in reserving `Minor` bumps for more significant changes to our scanners. In case of breaking changes imposed by the wrapped scanner, creating a new analyzer on a separate repository must be considered.
+
+The analyzers are released as Docker images following this scheme:
+
+- each push to the `master` branch will override the `edge` image tag
+- each push to any `awesome-feature` branch will generate a matching `awesome-feature` image tag
+- each Git tag will generate the corresponding `Major.Minor.Patch` image tag. A manual job allows to override the corresponding `Major` and the `latest` image tags to point to this `Major.Minor.Patch`.
+
+To release a new analyzer Docker image, there are two different options:
+
+- Manual release process
+- Automatic release process
+
+### Manual release process
+
+1. Ensure that the `CHANGELOG.md` entry for the new analyzer is correct.
+1. Ensure that the release source (typically the `master` or `main` branch) has a passing pipeline.
+1. Create a new release for the analyzer project by selecting the **Deployments** menu on the left-hand side of the project window, then selecting the **Releases** sub-menu.
+1. Select **New release** to open the **New Release** page.
+ 1. In the **Tag name** drop down, enter the same version used in the `CHANGELOG.md`, for example `v2.4.2`, and select the option to create the tag (`Create tag v2.4.2` here).
+ 1. In the **Release title** text box enter the same version used above, for example `v2.4.2`.
+ 1. In the `Release notes` text box, copy and paste the notes from the corresponding version in the `CHANGELOG.md`.
+ 1. Leave all other settings as the default values.
+ 1. Select **Create release**.
+
+After following the above process and creating a new release, a new Git tag is created with the `Tag name` provided above. This triggers a new pipeline with the given tag version and a new analyzer Docker image is built.
+
+If the analyzer uses the [`analyzer.yml` template](https://gitlab.com/gitlab-org/security-products/ci-templates/blob/b446fd3/includes-dev/analyzer.yml#L209-217), then the pipeline triggered as part of the **New release** process above automatically tags and deploys a new version of the analyzer Docker image.
+
+If the analyzer does not use the `analyzer.yml` template, you'll need to manually tag and deploy a new version of the analyzer Docker image:
+
+1. Select the **CI/CD** menu on the left-hand side of the project window, then select the **Pipelines** sub-menu.
+1. A new pipeline should currently be running with the same tag used previously, for example `v2.4.2`.
+1. After the pipeline has completed, it will be in a `blocked` state.
+1. Select the `Manual job` play button on the right hand side of the window and select `tag version` to tag and deploy a new version of the analyzer Docker image.
+
+Use your best judgment to decide when to create a Git tag, which will then trigger the release job. If you
+can't decide, then ask for other's input.
+
+### Automatic release process
+
+The following must be performed before the automatic release process can be used:
+
+1. Configure `CREATE_GIT_TAG: true` as a [`CI/CD` environment variable](../../ci/variables/index.md).
+1. Check the `Variables` in the CI/CD project settings. Unless the project already inherits the `GITLAB_TOKEN` environment variable from the project group, create a [project access token](../../user/project/settings/project_access_tokens.md) with `complete read/write access to the API` and configure `GITLAB_TOKEN` as a [`CI/CD` environment variable](../../ci/variables/index.md) which refers to this token.
+
+After the above steps have been completed, the automatic release process executes as follows:
+
+1. A project maintainer merges an MR into the default branch.
+1. The default pipeline is triggered, and the `upsert git tag` job is executed.
+ - If the most recent version in the `CHANGELOG.md` matches one of the Git tags, the job is a no-op.
+ - Else, this job automatically creates a new release and Git tag using the [releases API](../../api/releases/index.md#create-a-release). The version and message is obtained from the most recent entry in the `CHANGELOG.md` file for the project.
+1. A pipeline is automatically triggered for the new Git tag. This pipeline releases the `latest`, `major`, `minor` and `patch` Docker images of the analyzer.
+
+### Steps to perform after releasing an analyzer
+
+1. After a new version of the analyzer Docker image has been tagged and deployed, please test it with the corresponding test project.
+1. Announce the release on the relevant group Slack channel. Example message:
+
+ > FYI I've just released `ANALYZER_NAME` `ANALYZER_VERSION`. `LINK_TO_RELEASE`
+
+**Never delete a Git tag that has been pushed** as there is a good
+chance that the tag will be used and/or cached by the Go package registry.
diff --git a/doc/development/sec/index.md b/doc/development/sec/index.md
index 06c20cee0bb..c9805044e58 100644
--- a/doc/development/sec/index.md
+++ b/doc/development/sec/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, concepts, howto
---
@@ -18,6 +18,7 @@ See [Terminology](../../user/application_security/terminology) for an overview o
- [Scanning](#scanning)
- [Processing, visualization, and management](#processing-visualization-and-management)
- [Severity Levels](../../user/application_security/vulnerabilities/severities.md)
+- [Analyzer Development](analyzer_development_guide.md)
## Overview
@@ -45,7 +46,7 @@ flowchart LR
### Scanning
The scanning part is responsible for finding vulnerabilities in given resources, and exporting results.
-The scans are executed in CI/CD jobs via several small projects called [Analyzers](../../user/application_security/terminology/index.md#analyzer), which can be found in our [Analyzers sub-group](https://gitlab.com/gitlab-org/security-products/analyzers).
+The scans are executed in CI/CD jobs via several small projects called [Analyzers](../../user/application_security/terminology/index.md#analyzer), which can be found in our [Analyzers subgroup](https://gitlab.com/gitlab-org/security-products/analyzers).
The Analyzers are wrappers around security tools called [Scanners](../../user/application_security/terminology/index.md#scanner), developed internally or externally, to integrate them into GitLab.
The Analyzers are mainly written in Go.
@@ -65,5 +66,5 @@ Depending on the context, the security reports may be stored either in the datab
## CI/CD template development
-While CI/CD templates are the responsibiility of the Verify section, many are critical to the Sec Section's feature usage.
+While CI/CD templates are the responsibility of the Verify section, many are critical to the Sec Section's feature usage.
If you are working with CI/CD templates, please read the [development guide for GitLab CI/CD templates](../cicd/templates.md).
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 4c2f3118366..67f7c556055 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -2,7 +2,7 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Secure Coding Guidelines
@@ -53,6 +53,10 @@ Each time you implement a new feature/endpoint, whether it is at UI, API or Grap
Be careful to **also test [visibility levels](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/doc/development/permissions.md#feature-specific-permissions)** and not only project access rights.
+The HTTP status code returned when an authorization check fails should generally be `404 Not Found` to avoid revealing information
+about whether or not the requested resource exists. `403 Forbidden` may be appropriate if you need to display a specific message to the user
+about why they cannot access the resource. If you are displaying a generic message such as "access denied", consider returning `404 Not Found` instead.
+
Some example of well implemented access controls and tests:
1. [example1](https://dev.gitlab.org/gitlab/gitlab-ee/-/merge_requests/710/diffs?diff_id=13750#af40ef0eaae3c1e018809e1d88086e32bccaca40_43_43)
@@ -1067,7 +1071,7 @@ Symlink attacks makes it possible for an attacker to read the contents of arbitr
#### Ruby
-For zip files, the [`rubyzip`](https://rubygems.org/gems/rubyzip) Ruby gem is already patched against symlink attacks as it simply ignores symbolic links, so for this vulnerable example we will extract a `tar.gz` file with `Gem::Package::TarReader`:
+For zip files, the [`rubyzip`](https://rubygems.org/gems/rubyzip) Ruby gem is already patched against symlink attacks as it ignores symbolic links, so for this vulnerable example we will extract a `tar.gz` file with `Gem::Package::TarReader`:
```ruby
# Vulnerable tar.gz extraction example!
diff --git a/doc/development/service_measurement.md b/doc/development/service_measurement.md
index 17e509672f2..9d22e9c376c 100644
--- a/doc/development/service_measurement.md
+++ b/doc/development/service_measurement.md
@@ -1,12 +1,12 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Developers Guide to service measurement
-You can enable service measurement in order to debug any slow service's execution time, number of SQL calls, garbage collection stats, memory usage, etc.
+You can enable service measurement to debug any slow service's execution time, number of SQL calls, garbage collection stats, memory usage, etc.
## Measuring module
@@ -43,7 +43,7 @@ DummyService.prepend(Measurable)
In case when you are prepending a module from the `EE` namespace with EE features, you need to prepend Measurable after prepending the `EE` module.
-This way, `Measurable` is at the bottom of the ancestor chain, in order to measure execution of `EE` features as well:
+This way, `Measurable` is at the bottom of the ancestor chain, to measure execution of `EE` features as well:
```ruby
class DummyService
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index 5448bbb4293..88a1454393f 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Implement Service Ping
@@ -179,7 +179,7 @@ As the HyperLogLog algorithm is probabilistic, the **results always include erro
The highest encountered error rate is 4.9%.
When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over
-columns that contain non-unique values, which can not be assured by other counters.
+columns that contain non-unique values, which cannot be assured by other counters.
##### estimate_batch_distinct_count method
@@ -605,7 +605,7 @@ alt_usage_data(value = nil, fallback: -1, &block)
Arguments:
-- `value`: a simple static value in which case the value is simply returned.
+- `value`: a static value in which case the value is returned.
- or a `block`: which is evaluated
- `fallback: -1`: the common value used for any metrics that are failing.
@@ -712,10 +712,10 @@ We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/
- Use specialized indexes. For examples, see these merge requests:
- [Example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871)
- [Example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445)
-- Use defined `start` and `finish`, and simple queries.
- These values can be memoized and reused, as in this [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155).
-- Avoid joins and write the queries as simply as possible,
- as in this [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316).
+- Use defined `start` and `finish`. These values can be memoized and reused, as in this
+ [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155).
+- Avoid joins and unnecessary complexity in your queries. See this
+ [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316) as an example.
- Set a custom `batch_size` for `distinct_count`, as in this [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000).
## Add the metric definition
@@ -839,6 +839,22 @@ However, it has the following limitations:
WARNING:
This feature is intended solely for internal GitLab use.
+The aggregated metrics feature provides insight into the data attributes in a collection of Service Ping metrics.
+This aggregation allows you to count data attributes in events without counting each occurrence of the same data attribute in multiple events.
+For example, you can aggregate the number of users who perform several actions, such as creating a new issue and opening a new merge request.
+You can then count each user that performed any combination of these actions.
+
+### Defining aggregated metric via metric YAML definition
+
+To add data for aggregated metrics to the Service Ping payload,
+create metric YAML definition file following [Aggregated metric instrumentation guide](metrics_instrumentation.md#aggregated-metrics).
+
+### (DEPRECATED) Defining aggregated metric via aggregated metric YAML config file
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98206) in GitLab 15.5
+and is planned for removal in 15.5. Use [metrics definition YAMLs](https://gitlab.com/gitlab-org/gitlab/-/issues/370963) instead.
+
To add data for aggregated metrics to the Service Ping payload, add a corresponding definition to:
- [`config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/) for metrics available in the Community Edition.
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index f252eb967aa..0a4e5998345 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Service Ping Guide **(FREE SELF)**
diff --git a/doc/development/service_ping/metrics_dictionary.md b/doc/development/service_ping/metrics_dictionary.md
index d063c4c7601..3439f581e7f 100644
--- a/doc/development/service_ping/metrics_dictionary.md
+++ b/doc/development/service_ping/metrics_dictionary.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Metrics Dictionary Guide
@@ -136,6 +136,9 @@ We use the following categories to classify a metric:
- `subscription`: Data related to licensing.
- `standard`: Standard set of identifiers that are included when collecting data.
+An aggregate metric is a metric that is the sum of two or more child metrics. Service Ping uses the data category of
+the aggregate metric to determine whether or not the data is included in the reported Service Ping payload.
+
### Metric name suggestion examples
#### Metric with `data_source: database`
diff --git a/doc/development/service_ping/metrics_instrumentation.md b/doc/development/service_ping/metrics_instrumentation.md
index debb3a68c04..7a3f291460c 100644
--- a/doc/development/service_ping/metrics_instrumentation.md
+++ b/doc/development/service_ping/metrics_instrumentation.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Metrics instrumentation guide
@@ -254,6 +254,86 @@ options:
- i_quickactions_approve
```
+## Aggregated metrics
+
+The aggregated metrics feature provides insight into the number of data attributes, for example `pseudonymized_user_ids`, that occurred in a collection of events. For example, you can aggregate the number of users who perform multiple actions such as creating a new issue and opening
+a new merge request.
+
+You can use a YAML file to define your aggregated metrics. The following arguments are required:
+
+- `options.events`: List of event names to aggregate into metric data. All events in this list must
+ use the same data source. Additional data source requirements are described in
+ [Database sourced aggregated metrics](implement.md#database-sourced-aggregated-metrics) and
+ [Redis sourced aggregated metrics](implement.md#redis-sourced-aggregated-metrics).
+- `options.aggregate.operator`: Operator that defines how the aggregated metric data is counted. Available operators are:
+ - `OR`: Removes duplicates and counts all entries that triggered any of the listed events.
+ - `AND`: Removes duplicates and counts all elements that were observed triggering all of the following events.
+- `options.aggregate.attribute`: Information pointing to the attribute that is being aggregated across events.
+- `time_frame`: One or more valid time frames. Use these to limit the data included in aggregated metrics to events within a specific date-range. Valid time frames are:
+ - `7d`: The last 7 days of data.
+ - `28d`: The last 28 days of data.
+ - `all`: All historical data, only available for `database` sourced aggregated metrics.
+- `data_source`: Data source used to collect all events data included in the aggregated metrics. Valid data sources are:
+ - [`database`](implement.md#database-sourced-aggregated-metrics)
+ - [`redis_hll`](implement.md#redis-sourced-aggregated-metrics)
+
+Refer to merge request [98206](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98206) for an example of a merge request that adds an `AggregatedMetric` metric.
+
+Count unique `user_ids` that occurred in at least one of the events: `incident_management_alert_status_changed`,
+`incident_management_alert_assigned`, `incident_management_alert_todo`, `incident_management_alert_create_incident`.
+
+```yaml
+time_frame: 28d
+instrumentation_class: AggregatedMetric
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - `incident_management_alert_status_changed`
+ - `incident_management_alert_assigned`
+ - `incident_management_alert_todo`
+ - `incident_management_alert_create_incident`
+```
+
+### Availability-restrained Aggregated metrics
+
+If the Aggregated metric should only be available in the report under specific conditions, then you must specify these conditions in a new class that is a child of the `AggregatedMetric` class.
+
+```ruby
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class MergeUsageCountAggregatedMetric < AggregatedMetric
+ available? { Feature.enabled?(:merge_usage_data_missing_key_paths) }
+ end
+ end
+ end
+ end
+end
+```
+
+You must also use the class's name in the YAML setup.
+
+```yaml
+time_frame: 28d
+instrumentation_class: MergeUsageCountAggregatedMetric
+data_source: redis_hll
+options:
+ aggregate:
+ operator: OR
+ attribute: user_id
+ events:
+ - `incident_management_alert_status_changed`
+ - `incident_management_alert_assigned`
+ - `incident_management_alert_todo`
+ - `incident_management_alert_create_incident`
+```
+
## Numbers metrics
- `operation`: Operations for the given `data` block. Currently we only support `add` operation.
diff --git a/doc/development/service_ping/metrics_lifecycle.md b/doc/development/service_ping/metrics_lifecycle.md
index 28f77b6f587..f13aebeb16e 100644
--- a/doc/development/service_ping/metrics_lifecycle.md
+++ b/doc/development/service_ping/metrics_lifecycle.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Service Ping metric lifecycle
@@ -120,7 +120,7 @@ To remove a metric:
Do not remove the metric's YAML definition altogether. Some self-managed
instances might not immediately update to the latest version of GitLab, and
therefore continue to report the removed metric. The Product Intelligence team
- requires a record of all removed metrics in order to identify and filter them.
+ requires a record of all removed metrics to identify and filter them.
For example please take a look at this [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60149/diffs#b01f429a54843feb22265100c0e4fec1b7da1240_10_10).
diff --git a/doc/development/service_ping/performance_indicator_metrics.md b/doc/development/service_ping/performance_indicator_metrics.md
index d2abc597a22..4c1c61aa05b 100644
--- a/doc/development/service_ping/performance_indicator_metrics.md
+++ b/doc/development/service_ping/performance_indicator_metrics.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Performance Indicator Metrics guide
diff --git a/doc/development/service_ping/review_guidelines.md b/doc/development/service_ping/review_guidelines.md
index 1b00858be7e..a1806551303 100644
--- a/doc/development/service_ping/review_guidelines.md
+++ b/doc/development/service_ping/review_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Service Ping review guidelines
diff --git a/doc/development/service_ping/troubleshooting.md b/doc/development/service_ping/troubleshooting.md
index 4431d5df3ff..201d6a385eb 100644
--- a/doc/development/service_ping/troubleshooting.md
+++ b/doc/development/service_ping/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Service Ping
diff --git a/doc/development/service_ping/usage_data.md b/doc/development/service_ping/usage_data.md
index 4181bd90a02..2f2df14f56d 100644
--- a/doc/development/service_ping/usage_data.md
+++ b/doc/development/service_ping/usage_data.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Usage Data Metrics guide
diff --git a/doc/development/session.md b/doc/development/session.md
index 61a130e3a53..c30364c27f8 100644
--- a/doc/development/session.md
+++ b/doc/development/session.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Accessing session data
diff --git a/doc/development/shared_files.md b/doc/development/shared_files.md
index 4f13bb80761..3bf18a4d410 100644
--- a/doc/development/shared_files.md
+++ b/doc/development/shared_files.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Shared files
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index d8a3f86685e..3935e98199a 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Guidelines for shell commands in the GitLab codebase
diff --git a/doc/development/shell_scripting_guide/index.md b/doc/development/shell_scripting_guide/index.md
index 0591d2c64d0..d3d9304446e 100644
--- a/doc/development/shell_scripting_guide/index.md
+++ b/doc/development/shell_scripting_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Shell scripting standards and style guidelines
diff --git a/doc/development/sidekiq/compatibility_across_updates.md b/doc/development/sidekiq/compatibility_across_updates.md
index ac34d099202..cfb709d9110 100644
--- a/doc/development/sidekiq/compatibility_across_updates.md
+++ b/doc/development/sidekiq/compatibility_across_updates.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq Compatibility across Updates
diff --git a/doc/development/sidekiq/idempotent_jobs.md b/doc/development/sidekiq/idempotent_jobs.md
index da36cdc72aa..80c6c403549 100644
--- a/doc/development/sidekiq/idempotent_jobs.md
+++ b/doc/development/sidekiq/idempotent_jobs.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq idempotent jobs
diff --git a/doc/development/sidekiq/index.md b/doc/development/sidekiq/index.md
index 003f54d48b5..e8c939571cf 100644
--- a/doc/development/sidekiq/index.md
+++ b/doc/development/sidekiq/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq guides
@@ -186,3 +186,9 @@ default weight, which is 1.
Each Sidekiq worker must be tested using RSpec, just like any other class. These
tests should be placed in `spec/workers`.
+
+## Interacting with Sidekiq Redis and APIs
+
+The application should minimise interaction with of any `Sidekiq.redis` and Sidekiq [APIs](https://github.com/mperham/sidekiq/blob/main/lib/sidekiq/api.rb). Such interactions in generic application logic should be abstracted to a [Sidekiq middleware](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/sidekiq_middleware) for re-use across teams. By decoupling application logic from Sidekiq's datastore, it allows for greater freedom when horizontally scaling the GitLab background processing setup.
+
+Some exceptions to this rule would be migration-related logic or administration operations.
diff --git a/doc/development/sidekiq/limited_capacity_worker.md b/doc/development/sidekiq/limited_capacity_worker.md
index 5b86e01781c..5efb9b16725 100644
--- a/doc/development/sidekiq/limited_capacity_worker.md
+++ b/doc/development/sidekiq/limited_capacity_worker.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq limited capacity worker
diff --git a/doc/development/sidekiq/logging.md b/doc/development/sidekiq/logging.md
index b461047ea47..8a2a77b5226 100644
--- a/doc/development/sidekiq/logging.md
+++ b/doc/development/sidekiq/logging.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq logging
diff --git a/doc/development/sidekiq/worker_attributes.md b/doc/development/sidekiq/worker_attributes.md
index a1d24d0c392..48a222d65a0 100644
--- a/doc/development/sidekiq/worker_attributes.md
+++ b/doc/development/sidekiq/worker_attributes.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sidekiq worker attributes
@@ -60,7 +60,7 @@ that branch, but be told in the UI that the branch does not exist. We deem these
jobs to be `urgency :high`.
Extra effort is made to ensure that these jobs are started within a very short
-period of time after being scheduled. However, in order to ensure throughput,
+period of time after being scheduled. However, to ensure throughput,
these jobs also have very strict execution duration requirements:
1. The median job execution time should be less than 1 second.
@@ -117,7 +117,7 @@ Most background jobs in the GitLab application communicate with other GitLab
services. For example, PostgreSQL, Redis, Gitaly, and Object Storage. These are considered
to be "internal" dependencies for a job.
-However, some jobs are dependent on external services in order to complete
+However, some jobs are dependent on external services to complete
successfully. Some examples include:
1. Jobs which call web-hooks configured by a user.
diff --git a/doc/development/snowplow/event_dictionary_guide.md b/doc/development/snowplow/event_dictionary_guide.md
index 7980395b1a9..c5a21f5a081 100644
--- a/doc/development/snowplow/event_dictionary_guide.md
+++ b/doc/development/snowplow/event_dictionary_guide.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Event dictionary guide
diff --git a/doc/development/snowplow/implementation.md b/doc/development/snowplow/implementation.md
index 9a923b115a2..26016eeba84 100644
--- a/doc/development/snowplow/implementation.md
+++ b/doc/development/snowplow/implementation.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Implement Snowplow tracking
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index 42a968b9df0..7327f18fcaf 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Snowplow
@@ -90,7 +90,7 @@ Each click event provides attributes that describe the event.
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | ----------- |
| category | text | true | The page or backend section of the application. Unless infeasible, use the Rails page attribute by default in the frontend, and namespace + class name on the backend, for example, `Notes::CreateService`. |
-| 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`. |
+| 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 list 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. For Service Ping metrics adapted to Snowplow events, this should be the full metric [key path](../service_ping/metrics_dictionary.md#metric-key_path) taken from its definition file. |
| property | text | false | Any additional property of the element, or object being acted on. For Service Ping metrics adapted to Snowplow events, this should be additional information or context that can help analyze the event. For example, in the case of `usage_activity_by_stage_monthly.create.merge_requests_users`, there are four different possible merge request actions: "create", "merge", "comment", and "close". Each of these would be a possible property value. |
| 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. |
diff --git a/doc/development/snowplow/infrastructure.md b/doc/development/snowplow/infrastructure.md
index ea4653dc91d..ae416f40c98 100644
--- a/doc/development/snowplow/infrastructure.md
+++ b/doc/development/snowplow/infrastructure.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Snowplow infrastructure
diff --git a/doc/development/snowplow/review_guidelines.md b/doc/development/snowplow/review_guidelines.md
index 44de849792c..756dbd0ca92 100644
--- a/doc/development/snowplow/review_guidelines.md
+++ b/doc/development/snowplow/review_guidelines.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Snowplow review guidelines
diff --git a/doc/development/snowplow/schemas.md b/doc/development/snowplow/schemas.md
index 799f8335000..482c0e0105b 100644
--- a/doc/development/snowplow/schemas.md
+++ b/doc/development/snowplow/schemas.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Snowplow schemas
diff --git a/doc/development/snowplow/troubleshooting.md b/doc/development/snowplow/troubleshooting.md
index 3ad4c6c9549..306040f8c9c 100644
--- a/doc/development/snowplow/troubleshooting.md
+++ b/doc/development/snowplow/troubleshooting.md
@@ -1,16 +1,16 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Snowplow
## Monitoring
-This page covers dashboards and alerts coming from a number of internal tools.
+This page covers dashboards and alerts coming from a number of internal tools.
-For a brief video overview of the tools used to monitor Snowplow usage, please check out [this internal video](https://www.youtube.com/watch?v=NxPS0aKa_oU) (you must be logged into GitLab Unfiltered to view).
+For a brief video overview of the tools used to monitor Snowplow usage, please check out [this internal video](https://www.youtube.com/watch?v=NxPS0aKa_oU) (you must be logged into GitLab Unfiltered to view).
## Good events drop
@@ -74,7 +74,7 @@ Enrichers are not scalling well for the amount of events we receive.
See the [dashboard](https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#dashboards:name=SnowPlow).
-Could we get assistance in order to fix the delay?
+Could we get assistance to fix the delay?
Thank you!
```
diff --git a/doc/development/spam_protection_and_captcha/exploratory_testing.md b/doc/development/spam_protection_and_captcha/exploratory_testing.md
index e508265cf83..e17d25acb9d 100644
--- a/doc/development/spam_protection_and_captcha/exploratory_testing.md
+++ b/doc/development/spam_protection_and_captcha/exploratory_testing.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exploratory testing of CAPTCHAs
diff --git a/doc/development/spam_protection_and_captcha/graphql_api.md b/doc/development/spam_protection_and_captcha/graphql_api.md
index e3f4e9069e5..846165d35f1 100644
--- a/doc/development/spam_protection_and_captcha/graphql_api.md
+++ b/doc/development/spam_protection_and_captcha/graphql_api.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GraphQL API spam protection and CAPTCHA support
diff --git a/doc/development/spam_protection_and_captcha/index.md b/doc/development/spam_protection_and_captcha/index.md
index dbe8c4aa4e9..1ba1c1678c4 100644
--- a/doc/development/spam_protection_and_captcha/index.md
+++ b/doc/development/spam_protection_and_captcha/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Spam protection and CAPTCHA
diff --git a/doc/development/spam_protection_and_captcha/model_and_services.md b/doc/development/spam_protection_and_captcha/model_and_services.md
index d0519cba68f..d0ca6d350dc 100644
--- a/doc/development/spam_protection_and_captcha/model_and_services.md
+++ b/doc/development/spam_protection_and_captcha/model_and_services.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Model and services spam protection and CAPTCHA support
diff --git a/doc/development/spam_protection_and_captcha/rest_api.md b/doc/development/spam_protection_and_captcha/rest_api.md
index ad74977eb67..7a9f8b5def1 100644
--- a/doc/development/spam_protection_and_captcha/rest_api.md
+++ b/doc/development/spam_protection_and_captcha/rest_api.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# REST API spam protection and CAPTCHA support
diff --git a/doc/development/spam_protection_and_captcha/web_ui.md b/doc/development/spam_protection_and_captcha/web_ui.md
index 9aeb9e96d44..ff7049dd29f 100644
--- a/doc/development/spam_protection_and_captcha/web_ui.md
+++ b/doc/development/spam_protection_and_captcha/web_ui.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Web UI spam protection and CAPTCHA support
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 029874011c4..5829d27b8ee 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SQL Query Guidelines
diff --git a/doc/development/stage_group_observability/dashboards/error_budget_detail.md b/doc/development/stage_group_observability/dashboards/error_budget_detail.md
index 19f98d404e7..a8f932b78c0 100644
--- a/doc/development/stage_group_observability/dashboards/error_budget_detail.md
+++ b/doc/development/stage_group_observability/dashboards/error_budget_detail.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Error budget detail dashboard
diff --git a/doc/development/stage_group_observability/dashboards/index.md b/doc/development/stage_group_observability/dashboards/index.md
index f4e646c8634..9f9ba609271 100644
--- a/doc/development/stage_group_observability/dashboards/index.md
+++ b/doc/development/stage_group_observability/dashboards/index.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dashboards for stage groups
diff --git a/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md b/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
index c8c18b93a8f..fb5d5bbe379 100644
--- a/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
+++ b/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Stage group dashboard
@@ -54,8 +54,8 @@ description, note the following:
precision is 2. In some extremely low panels, you can see `0.00`, even though there is still some
real traffic.
-To inspect the raw data of the panel for further calculation, select **Inspect** from the dropdown
-list of a panel. Queries, raw data, and panel JSON structure are available.
+To inspect the raw data of the panel for further calculation, select **Inspect** from the dropdown list of a panel.
+Queries, raw data, and panel JSON structure are available.
Read more at [Grafana panel inspection](http://grafana.com/docs/grafana/next/panels/query-a-data-source/).
All the dashboards are powered by [Grafana](https://grafana.com/), a frontend for displaying metrics.
diff --git a/doc/development/stage_group_observability/index.md b/doc/development/stage_group_observability/index.md
index 868e55735e8..08f751c508e 100644
--- a/doc/development/stage_group_observability/index.md
+++ b/doc/development/stage_group_observability/index.md
@@ -1,7 +1,7 @@
---
stage: Platforms
group: Scalability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Observability for stage groups
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 221d6b89b20..f1a23f06699 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -2,7 +2,7 @@
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
description: "GitLab development guidelines - testing best practices."
---
diff --git a/doc/development/testing_guide/contract/consumer_tests.md b/doc/development/testing_guide/contract/consumer_tests.md
index 46f4f446ad9..67bb7160749 100644
--- a/doc/development/testing_guide/contract/consumer_tests.md
+++ b/doc/development/testing_guide/contract/consumer_tests.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Writing consumer tests
diff --git a/doc/development/testing_guide/contract/index.md b/doc/development/testing_guide/contract/index.md
index 30a4adaca44..8412a260c7d 100644
--- a/doc/development/testing_guide/contract/index.md
+++ b/doc/development/testing_guide/contract/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Contract testing
@@ -66,7 +66,7 @@ As mentioned in the [folder structure section](#consumer-tests), consumer tests
#### Provider naming
-These are the API endpoints that provides the data to the consumer so they are simply named according to the API endpoint they pertain to. Be mindful that this name is as descriptive as possible. For example, if we're writing a test for the `GET /groups/:id/projects` endpoint, we don't want to simply name it "Projects endpoint" as there is a `GET /projects` endpoint as well that also fetches a list of projects the user has access to across all of GitLab. An easy way to name them is by checking out our [API documentation](../../../api/api_resources.md) and naming it the same way it is named in there. So the [`GET /groups/:id/projects`](../../../api/groups.md#list-a-groups-projects) would be called `List a group’s projects` and [`GET /projects`](../../../api/projects.md#list-all-projects) would be called `List all projects`. Subsequently, the test files are named `list_a_groups_projects_helper.rb` and `list_all_projects_helper.rb` respectively.
+These are the API endpoints that provides the data to the consumer so they are named according to the API endpoint they pertain to. Be mindful that this name is as descriptive as possible. For example, if we're writing a test for the `GET /groups/:id/projects` endpoint, we don't want to name it "Projects endpoint" as there is a `GET /projects` endpoint as well that also fetches a list of projects the user has access to across all of GitLab. An easy way to name them is by checking out our [API documentation](../../../api/api_resources.md) and naming it the same way it is named in there. So the [`GET /groups/:id/projects`](../../../api/groups.md#list-a-groups-projects) would be called `List a group’s projects` and [`GET /projects`](../../../api/projects.md#list-all-projects) would be called `List all projects`. Subsequently, the test files are named `list_a_groups_projects_helper.rb` and `list_all_projects_helper.rb` respectively.
There are some cases where the provider being tested may not be documented so, in those cases, fall back to choosing a name that is as descriptive as possible to ensure it's easy to tell what the provider is for.
diff --git a/doc/development/testing_guide/contract/provider_tests.md b/doc/development/testing_guide/contract/provider_tests.md
index 92ac4c4ed71..1772ed9384e 100644
--- a/doc/development/testing_guide/contract/provider_tests.md
+++ b/doc/development/testing_guide/contract/provider_tests.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Writing provider tests
diff --git a/doc/development/testing_guide/end_to_end/beginners_guide.md b/doc/development/testing_guide/end_to_end/beginners_guide.md
index a13011d0101..b81379d89b2 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Beginner's guide to writing end-to-end tests
@@ -120,6 +120,22 @@ module QA
end
```
+### The `product_group` metadata
+
+Assign `product_group` metadata and specify what product group this test belongs to. In this case, `authentication_and_authorization`.
+
+```ruby
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Login', product_group: :authentication_and_authorization do
+
+ end
+ end
+end
+```
+
### The `it` blocks (examples)
Every test suite contains at least one `it` block (example). A good way to start
@@ -128,7 +144,7 @@ writing end-to-end tests is to write test case descriptions as `it` blocks:
```ruby
module QA
RSpec.describe 'Manage' do
- describe 'Login' do
+ describe 'Login', product_group: :authentication_and_authorization do
it 'can login' do
end
@@ -152,7 +168,7 @@ Begin by logging in.
module QA
RSpec.describe 'Manage' do
- describe 'Login' do
+ describe 'Login', product_group: :authentication_and_authorization do
it 'can login' do
Flow::Login.sign_in
@@ -175,7 +191,7 @@ should answer the question "What do we test?"
module QA
RSpec.describe 'Manage' do
- describe 'Login' do
+ describe 'Login', product_group: :authentication_and_authorization do
it 'can login' do
Flow::Login.sign_in
@@ -222,7 +238,7 @@ a call to `sign_in`.
module QA
RSpec.describe 'Manage' do
- describe 'Login' do
+ describe 'Login', product_group: :authentication_and_authorization do
before do
Flow::Login.sign_in
end
@@ -246,12 +262,12 @@ end
```
The `before` block is essentially a `before(:each)` and is run before each example,
-ensuring we now log in at the beginning of each test.
+ensuring we now sign in at the beginning of each test.
## Test setup using resources and page objects
Next, let's test something other than Login. Let's test Issues, which are owned by the Plan
-stage, so [create a file](#identify-the-devops-stage) in
+stage and the Project Management Group, so [create a file](#identify-the-devops-stage) in
`qa/specs/features/browser_ui/3_create/issues` called `issues_spec.rb`.
```ruby
@@ -259,7 +275,7 @@ stage, so [create a file](#identify-the-devops-stage) in
module QA
RSpec.describe 'Plan' do
- describe 'Issues' do
+ describe 'Issues', product_group: :project_management do
let(:issue) do
Resource::Issue.fabricate_via_api! do |issue|
issue.title = 'My issue'
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 b17ca9e6f8f..37eda7f76f5 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -1,7 +1,7 @@
---
stage: none
group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# End-to-end testing Best Practices
@@ -10,7 +10,7 @@ This is a tailored extension of the Best Practices [found in the testing guide](
## Class and module naming
-The QA framework uses [Zeitwerk](https://github.com/fxn/zeitwerk) for class and module autoloading. The default Zeitwerk [inflector](https://github.com/fxn/zeitwerk#zeitwerkinflector) simply converts snake_cased file names to PascalCased module or class names. It is advised to stick to this pattern to avoid manual maintenance of inflections.
+The QA framework uses [Zeitwerk](https://github.com/fxn/zeitwerk) for class and module autoloading. The default Zeitwerk [inflector](https://github.com/fxn/zeitwerk#zeitwerkinflector) converts snake_cased file names to PascalCased module or class names. It is advised to stick to this pattern to avoid manual maintenance of inflections.
In case custom inflection logic is needed, custom inflectors are added in the [qa.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa.rb) file in the `loader.inflector.inflect` method invocation.
@@ -299,7 +299,7 @@ point of failure and so the screenshot would not be captured at the right moment
## Ensure tests do not leave the browser logged in
-All tests expect to be able to log in at the start of the test.
+All tests expect to be able to sign in at the start of the test.
For an example see [issue #34736](https://gitlab.com/gitlab-org/gitlab/-/issues/34736).
@@ -358,7 +358,7 @@ using the Git CLI.
## Preferred method to blur elements
-To blur an element, the preferred method is to click another element that does not alter the test state.
+To blur an element, the preferred method is to select another element that does not alter the test state.
If there's a mask that blocks the page elements, such as may occur with some dropdowns,
use WebDriver's native mouse events to simulate a click event on the coordinates of an element. Use the following method: `click_element_coordinates`.
diff --git a/doc/development/testing_guide/end_to_end/capybara_to_chemlab_migration_guide.md b/doc/development/testing_guide/end_to_end/capybara_to_chemlab_migration_guide.md
index a71e076b57f..f3911176263 100644
--- a/doc/development/testing_guide/end_to_end/capybara_to_chemlab_migration_guide.md
+++ b/doc/development/testing_guide/end_to_end/capybara_to_chemlab_migration_guide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migration Guide Capybara → Chemlab
diff --git a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
index 8770a5d33cd..5cc82916cdd 100644
--- a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
+++ b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dynamic Element Validation
@@ -48,7 +48,7 @@ click_element(:my_element, Some::Page)
First it is important to define what a "required element" is.
-Simply put, a required element is a visible HTML element that appears on a UI component without any user input.
+A required element is a visible HTML element that appears on a UI component without any user input.
"Visible" can be defined as
diff --git a/doc/development/testing_guide/end_to_end/execution_context_selection.md b/doc/development/testing_guide/end_to_end/execution_context_selection.md
index 0a4c5fcf451..23b8ab7287b 100644
--- a/doc/development/testing_guide/end_to_end/execution_context_selection.md
+++ b/doc/development/testing_guide/end_to_end/execution_context_selection.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Execution context selection
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 9a39161f1ad..8e25c817938 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Testing with feature flags
diff --git a/doc/development/testing_guide/end_to_end/flows.md b/doc/development/testing_guide/end_to_end/flows.md
index b99a1f9deb7..58702ceb861 100644
--- a/doc/development/testing_guide/end_to_end/flows.md
+++ b/doc/development/testing_guide/end_to_end/flows.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Flows in GitLab QA
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index cc9c02a65ce..1853ad47779 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# End-to-end Testing
@@ -125,7 +125,7 @@ For example, when we [dequarantine](https://about.gitlab.com/handbook/engineerin
a flaky test we first want to make sure that it's no longer flaky.
We can do that using the `ce:custom-parallel` and `ee:custom-parallel` jobs.
Both are manual jobs that you can configure using custom variables.
-When clicking the name (not the play icon) of one of the parallel jobs,
+When selecting the name (not the play icon) of one of the parallel jobs,
you are prompted to enter variables. You can use any of
[the variables that can be used with `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)
as well as these:
diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md
index c93e8c9d13f..5fbf2ffbcde 100644
--- a/doc/development/testing_guide/end_to_end/page_objects.md
+++ b/doc/development/testing_guide/end_to_end/page_objects.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Page objects in GitLab QA
@@ -10,7 +10,7 @@ In GitLab QA we are using a known pattern, called _Page Objects_.
This means that we have built an abstraction for all pages in GitLab that we use
to drive GitLab QA scenarios. Whenever we do something on a page, like filling
-in a form or clicking a button, we do that only through a page object
+in a form or selecting a button, we do that only through a page object
associated with this area of GitLab.
For example, when GitLab QA test harness signs in into GitLab, it needs to fill
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
index a519d1ecb47..6e29e9b9dff 100644
--- a/doc/development/testing_guide/end_to_end/resources.md
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Resource classes in GitLab QA
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 1abaf3ef323..b12c6bd443a 100644
--- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
+++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# RSpec metadata for end-to-end tests
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 322f108783f..81e1c7d5dc0 100644
--- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
+++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Running tests that require special setup
diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md
index a9571df1188..f380b24d7a5 100644
--- a/doc/development/testing_guide/end_to_end/style_guide.md
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Style guide for writing end-to-end tests
diff --git a/doc/development/testing_guide/end_to_end/troubleshooting.md b/doc/development/testing_guide/end_to_end/troubleshooting.md
index 76d19dc0159..e0925cb71f4 100644
--- a/doc/development/testing_guide/end_to_end/troubleshooting.md
+++ b/doc/development/testing_guide/end_to_end/troubleshooting.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting end-to-end tests
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 7409f15969d..45f1d0ddf7e 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Flaky tests
@@ -45,15 +45,27 @@ Once a test is in quarantine, there are 3 choices:
On our CI, we use [RSpec::Retry](https://github.com/NoRedInk/rspec-retry) to automatically retry a failing example a few
times (see [`spec/spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/spec_helper.rb) for the precise retries count).
-We also use a home-made `RspecFlaky::Listener` listener which records flaky
-examples in a JSON report file on `main` (`retrieve-tests-metadata` and
-`update-tests-metadata` jobs).
+We also use a custom [`RspecFlaky::Listener`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/tooling/rspec_flaky/listener.rb).
+This listener runs in the `update-tests-metadata` job in `maintenance` scheduled pipelines
+on the `master` branch, and saves flaky examples to `rspec/flaky/report-suite.json`.
+The report file is then retrieved by the `retrieve-tests-metadata` job in all pipelines.
This was originally implemented in: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021>.
If you want to enable retries locally, you can use the `RETRIES` environment variable.
For instance `RETRIES=1 bin/rspec ...` would retry the failing examples once.
+To generate the reports locally, use the `FLAKY_RSPEC_GENERATE_REPORT` environment variable.
+For example, `FLAKY_RSPEC_GENERATE_REPORT=1 bin/rspec ...`.
+
+### Usage of the `rspec/flaky/report-suite.json` report
+
+The `rspec/flaky/report-suite.json` report is:
+
+- Used for [automatically skipping known flaky tests](../pipelines.md#automatic-skipping-of-flaky-tests).
+- [Imported into Snowflake](https://gitlab.com/gitlab-data/analytics/-/blob/master/extract/gitlab_flaky_tests/upload.py)
+ once per day, for monitoring with the [internal dashboard](https://app.periscopedata.com/app/gitlab/888968/EP---Flaky-tests).
+
## Problems we had in the past at GitLab
- [`rspec-retry` is biting us when some API specs fail](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29242): <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9825>
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 22a8792bac6..d7627e2064f 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Frontend testing standards and style guidelines
@@ -200,7 +200,6 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'
const wrapper = shallowMountExtended(ExampleComponent);
-// In this example, `wrapper` is a `@vue/test-utils` wrapper returned from `mount` or `shallowMount`.
it('exists', () => {
// Best (especially for integration tests)
wrapper.findByRole('link', { name: /Click Me/i })
@@ -291,7 +290,7 @@ it('tests a promise rejection', async () => {
});
```
-You can also simply return a promise from the test function.
+You can also return a promise from the test function.
Using the `done` and `done.fail` callbacks is discouraged when working with
promises. They should not be used.
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index e50902c4995..753089fa673 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Testing standards and style guidelines
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index b272d23522e..d86d1c3c7b4 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Review Apps
@@ -84,7 +84,7 @@ the GitLab handbook information for the [shared 1Password account](https://about
### Enable a feature flag for my Review App
-1. Open your Review App and log in as documented above.
+1. Open your Review App and sign in as documented above.
1. Create a personal access token.
1. Enable the feature flag using the [Feature flag API](../../api/features.md).
@@ -101,7 +101,7 @@ the GitLab handbook information for the [shared 1Password account](https://about
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. Select the Pod in the "Managed pods" section. For example, `review-qa-raise-e-12chm0-toolbox-d5455cc8-2lsvz`.
-1. Select the `KUBECTL` dropdown, then `Exec` -> `toolbox`.
+1. Select the `KUBECTL` dropdown list, 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-toolbox-d5455cc8-2lsvz -it -- gitlab-rails console` and
diff --git a/doc/development/testing_guide/smoke.md b/doc/development/testing_guide/smoke.md
index 4fd2729a4d3..62a09ca864b 100644
--- a/doc/development/testing_guide/smoke.md
+++ b/doc/development/testing_guide/smoke.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Smoke Tests
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index c1bf3609b53..c93a5fd539b 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Testing levels
diff --git a/doc/development/testing_guide/testing_migrations_guide.md b/doc/development/testing_guide/testing_migrations_guide.md
index 3006a2230ac..b276a7e2a3a 100644
--- a/doc/development/testing_guide/testing_migrations_guide.md
+++ b/doc/development/testing_guide/testing_migrations_guide.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -22,7 +22,8 @@ a database schema.
Adding a `:migration` tag to a test signature enables some custom RSpec
`before` and `after` hooks in our
[`spec/support/migration.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/f81fa6ab1dd788b70ef44b85aaba1f31ffafae7d/spec/support/migration.rb)
-to run.
+to run. If performing a migration against a database schema other than
+`:gitlab_main` (for example `:gitlab_ci`), then you must specify it as well: `migration: :gitlab_ci`. See [spec/migrations/change_public_projects_cost_factor_spec.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/migrations/change_public_projects_cost_factor_spec.rb#L6-6) for an example.
A `before` hook reverts all migrations to the point that a migration
under test is not yet migrated.
diff --git a/doc/development/testing_guide/testing_rake_tasks.md b/doc/development/testing_guide/testing_rake_tasks.md
index 30d193de2f2..3dfe1f9b725 100644
--- a/doc/development/testing_guide/testing_rake_tasks.md
+++ b/doc/development/testing_guide/testing_rake_tasks.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Testing Rake tasks
diff --git a/doc/development/transient/prevention-patterns.md b/doc/development/transient/prevention-patterns.md
index 93712b104e6..98634df22e9 100644
--- a/doc/development/transient/prevention-patterns.md
+++ b/doc/development/transient/prevention-patterns.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Preventing Transient Bugs
diff --git a/doc/development/uploads/background.md b/doc/development/uploads/background.md
deleted file mode 100644
index 1ad1aec23f2..00000000000
--- a/doc/development/uploads/background.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'index.md'
-remove_date: '2022-07-25'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after <2022-07-25>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/uploads/implementation.md b/doc/development/uploads/implementation.md
deleted file mode 100644
index 1ad1aec23f2..00000000000
--- a/doc/development/uploads/implementation.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'index.md'
-remove_date: '2022-07-25'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after <2022-07-25>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/uploads/index.md b/doc/development/uploads/index.md
index b8326489d40..41ec71451fb 100644
--- a/doc/development/uploads/index.md
+++ b/doc/development/uploads/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Uploads development guide
diff --git a/doc/development/uploads/working_with_uploads.md b/doc/development/uploads/working_with_uploads.md
index 5a5f987c37c..c88762e6bd5 100644
--- a/doc/development/uploads/working_with_uploads.md
+++ b/doc/development/uploads/working_with_uploads.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Uploads guide: Adding new uploads
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 3f6187a4c2e..45a6b74f33a 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab utilities
diff --git a/doc/development/value_stream_analytics.md b/doc/development/value_stream_analytics.md
index bbea89d5645..0d321133705 100644
--- a/doc/development/value_stream_analytics.md
+++ b/doc/development/value_stream_analytics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Value stream analytics development guide
@@ -326,3 +326,25 @@ in your rails console (`rails c`):
```ruby
Analytics::CycleAnalytics::ReaggregationWorker.new.perform
```
+
+### Seed data
+
+#### Value stream analytics
+
+Seed issues and merge requests for value stream analytics:
+
+ ```shell
+ // Seed 10 issues for the project specified by <project-id>
+ $ VSA_SEED_PROJECT_ID=<project-id> VSA_ISSUE_COUNT=10 SEED_VSA=true FILTER=cycle_analytics rake db:seed_fu
+ ```
+
+#### DORA metrics
+
+Seed DORA daily metrics for value stream, insights and CI/CD analytics:
+
+1. [Create an environment from the UI](../ci/environments/index.md#create-a-static-environment) named `production`.
+1. Open the rails console:
+
+ ```shell
+ rails c
+ ```
diff --git a/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md b/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md
index 6087d4bd8f7..a07998550bf 100644
--- a/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md
+++ b/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Aggregated Value Stream Analytics
@@ -43,7 +43,7 @@ Benefits of the aggregated VSA backend:
- Simpler database queries (fewer JOINs).
- Faster aggregations, only a single table is accessed.
- Possibility to introduce further aggregations for improving the first page load time.
-- Better performance for large groups (with many sub-groups, projects, issues and, merge requests).
+- Better performance for large groups (with many subgroups, projects, issues and, merge requests).
- Ready for database decomposition. The VSA related database tables could live in a separate
database with a minimal development effort.
- Ready for keyset pagination which can be useful for exporting the data.
@@ -165,7 +165,7 @@ Creation time always happens first, so this stage always reports negative durati
The data collection scans and processes all issues and merge requests records in the group
hierarchy, starting from the top-level group. This means that if a group only has one value stream
-in a sub-group, we nevertheless collect data of all issues and merge requests in the hierarchy of
+in a subgroup, we nevertheless collect data of all issues and merge requests in the hierarchy of
this group. This aims to simplify the data collection mechanism. Moreover, data research shows
that most group hierarchies have their stages configured on the top level.
@@ -278,7 +278,7 @@ attributes.
- `summary`, `time_summary` - Top-level aggregations, most of the metrics are using different APIs/
finders and not invoking the aggregated backend.
-When clicking on a specific stage, the `records` endpoint is invoked, which returns the related
+When selecting a specific stage, the `records` endpoint is invoked, which returns the related
records (paginated) for the chosen stage in a specific order.
### Database decomposition
diff --git a/doc/development/wikis.md b/doc/development/wikis.md
index deea3d38470..67dc567cc5f 100644
--- a/doc/development/wikis.md
+++ b/doc/development/wikis.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "GitLab's development guidelines for Wikis"
---
diff --git a/doc/development/windows.md b/doc/development/windows.md
index 17dfaddef36..5f32848da79 100644
--- a/doc/development/windows.md
+++ b/doc/development/windows.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -76,7 +76,7 @@ Build a Google Cloud image with the above shared runners repository by doing the
1. Copy and save the password as it is not shown again.
1. Select **RDP** down arrow.
1. Select **Download the RDP file**.
-1. Open the downloaded RDP file with the Windows remote desktop app (<https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-clients>).
+1. Open the downloaded RDP file with the Windows remote desktop app (<https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-clients>).
1. Select **Continue** to accept the certificate.
1. Enter the password and select **Next**.
diff --git a/doc/development/work_items.md b/doc/development/work_items.md
index f15c66ae847..eabad175bf7 100644
--- a/doc/development/work_items.md
+++ b/doc/development/work_items.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Work items and work item types
@@ -88,8 +88,8 @@ so that in future we can allow users to define custom WITs, we will move the
to `work_item_types` will involve creating the set of WITs for all root-level groups.
NOTE:
-At first, defining a WIT will only be possible at the root-level group, which would then be inherited by sub-groups.
-We will investigate the possibility of defining new WITs at sub-group levels at a later iteration.
+At first, defining a WIT will only be possible at the root-level group, which would then be inherited by subgroups.
+We will investigate the possibility of defining new WITs at subgroup levels at a later iteration.
### Introducing work_item_types table
@@ -150,8 +150,27 @@ of widgets.
In order to customize each WIT with corresponding active widgets we will need a data
structure to map each WIT to specific widgets.
+The intent is for work item types to be highly configurable, both by GitLab for
+implementing various work item schemes for customers (an opinionated GitLab
+workflow, or SAFe 5, etc), and eventually for customers to customize their own
+workflows.
+
+In this case, a work item scheme would be defined as a set of types with
+certain characteristics (some widgets enabled, others not), such as an Epic,
+Story, Bug, and Task, etc.
+
+As we're building a new work item architecture, we want to build the ability to
+define these various types in a very flexible manner. Having GitLab use
+this system first (without introducing customer customization) allows us to
+better build out the initial system.
+
NOTE:
-The exact structure of the WITs widgets metadata is still to be defined.
+Currently work item's `base_type` is used to define static mapping of what
+widgets are available for each type (current status), this definition should be
+rather stored in database table. The exact structure of the WIT widgets
+metadata is still to be defined. `base_type` was added to help converting other
+types of resources (requirements and incidents) into work items. Eventually (when
+these resources become regular work items), `base_type` will be removed.
### Custom work item types
diff --git a/doc/development/work_items_widgets.md b/doc/development/work_items_widgets.md
index 92919c10a9f..89602d969e6 100644
--- a/doc/development/work_items_widgets.md
+++ b/doc/development/work_items_widgets.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Work items widgets
@@ -88,7 +88,7 @@ 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.
+attribute or work item details, such as input field, date selector, or dropdown list.
Widgets must be configurable to support various use cases, depending on work items.
When building widgets, use slots to provide extra context while minimizing
@@ -96,18 +96,18 @@ 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)
+We have a [dropdown list 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
+Any work item widget can wrap the dropdown list. 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.
+- Labels, milestones, and assignees selectors use the dropdown list.
-Some frontend widgets already use the dropdown component. Use them as a reference
+Some frontend widgets already use the dropdown list. Use them as a reference
for work items widgets development:
- `ee/app/assets/javascripts/boards/components/assignee_select.vue`
diff --git a/doc/development/workhorse/channel.md b/doc/development/workhorse/channel.md
index 33d7cc63f00..f5693b57f7a 100644
--- a/doc/development/workhorse/channel.md
+++ b/doc/development/workhorse/channel.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Websocket channel support for Workhorse
diff --git a/doc/development/workhorse/configuration.md b/doc/development/workhorse/configuration.md
index a94ba2b4fc6..82e44a6f995 100644
--- a/doc/development/workhorse/configuration.md
+++ b/doc/development/workhorse/configuration.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Workhorse configuration
diff --git a/doc/development/workhorse/gitlab_features.md b/doc/development/workhorse/gitlab_features.md
index 3b240d4cbc6..8b899242935 100644
--- a/doc/development/workhorse/gitlab_features.md
+++ b/doc/development/workhorse/gitlab_features.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Features that rely on Workhorse
diff --git a/doc/development/workhorse/index.md b/doc/development/workhorse/index.md
index f210f511954..0f4e55a002a 100644
--- a/doc/development/workhorse/index.md
+++ b/doc/development/workhorse/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Workhorse
diff --git a/doc/development/workhorse/new_features.md b/doc/development/workhorse/new_features.md
index 5c00903497a..dbde06ddee4 100644
--- a/doc/development/workhorse/new_features.md
+++ b/doc/development/workhorse/new_features.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Adding new features to Workhorse
diff --git a/doc/development/workspace/index.md b/doc/development/workspace/index.md
index b01a7826b3d..f4738e3fc31 100644
--- a/doc/development/workspace/index.md
+++ b/doc/development/workspace/index.md
@@ -3,7 +3,7 @@ comments: false
type: index, dev
stage: none
group: Development
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
description: "Development Guidelines: learn about workspace when developing GitLab."
---
diff --git a/doc/downgrade_ee_to_ce/index.md b/doc/downgrade_ee_to_ce/index.md
index 2aa99eae084..6a3fcab8bde 100644
--- a/doc/downgrade_ee_to_ce/index.md
+++ b/doc/downgrade_ee_to_ce/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Downgrading from EE to CE
diff --git a/doc/drawers/advanced_search_syntax.md b/doc/drawers/advanced_search_syntax.md
index c48efbc120a..3c2ce212b99 100644
--- a/doc/drawers/advanced_search_syntax.md
+++ b/doc/drawers/advanced_search_syntax.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: drawer
source: /doc/user/search/global_search/advanced_search_syntax.md
---
diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md
index af736c11d59..64384372a44 100644
--- a/doc/gitlab-basics/add-file.md
+++ b/doc/gitlab-basics/add-file.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: howto
---
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index 02e9117fa3a..4b53535a711 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Edit files through the command line **(FREE)**
diff --git a/doc/gitlab-basics/feature_branch_workflow.md b/doc/gitlab-basics/feature_branch_workflow.md
index 989a1557ef2..de051c67bc2 100644
--- a/doc/gitlab-basics/feature_branch_workflow.md
+++ b/doc/gitlab-basics/feature_branch_workflow.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html'
---
diff --git a/doc/gitlab-basics/index.md b/doc/gitlab-basics/index.md
deleted file mode 100644
index 3cd5dfe7d18..00000000000
--- a/doc/gitlab-basics/index.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../user/index.md'
-remove_date: '2022-07-08'
----
-
-This document was moved to [another location](../user/index.md).
-
-<!-- This redirect file can be deleted after 2022-07-08. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 875bd00ee55..056fad4061b 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto, tutorial
description: "Introduction to using Git through the command line."
---
@@ -37,7 +37,7 @@ prompt, command shell, and command line). Here are some options:
- [iTerm2](https://iterm2.com/). You can integrate it with [Zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [Oh My Zsh](https://ohmyz.sh/) for color highlighting and other advanced features.
- For Windows users:
- Built-in command line. On the Windows taskbar, select the search icon and type `cmd`.
- - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7).
+ - [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7).
- Git Bash. It is built into [Git for Windows](https://gitforwindows.org/).
- For Linux users:
- Built-in [Linux Terminal](https://ubuntu.com/tutorials/command-line-for-beginners#3-opening-a-terminal).
@@ -147,10 +147,14 @@ between your computer and GitLab.
git clone https://gitlab.com/gitlab-tests/sample-project.git
```
-1. GitLab requests your username and password:
- - If you have 2FA enabled for your account, you must [clone using a token](#clone-using-a-token)
- with `read_repository` or `write_repository` permissions instead of your account's password.
- - If you don't have 2FA enabled, use your account's password.
+1. GitLab requests your username and password.
+
+ If you have enabled two-factor authentication (2FA) on your account, you cannot use your account password. Instead, you can do one of the following:
+
+ - [Clone using a token](#clone-using-a-token) with `read_repository` or `write_repository` permissions.
+ - Install [Git Credential Manager](../user/profile/account/two_factor_authentication.md#git-credential-manager).
+
+ If you have not enabled 2FA, use your account password.
1. To view the files, go to the new directory:
diff --git a/doc/index.md b/doc/index.md
index 1ac8cdb19ce..c359ec7b639 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: 'Learn how to use and administer GitLab, the most scalable Git-based fully integrated platform for software development.'
---
diff --git a/doc/install/aws/eks_clusters_aws.md b/doc/install/aws/eks_clusters_aws.md
index c939bac888c..03f7cd19ed5 100644
--- a/doc/install/aws/eks_clusters_aws.md
+++ b/doc/install/aws/eks_clusters_aws.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# EKS cluster provisioning best practices **(FREE SELF)**
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index b7a01cf61f4..ad3d28d15e3 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
{::options parse_block_html="true" /}
diff --git a/doc/install/aws/gitlab_sre_for_aws.md b/doc/install/aws/gitlab_sre_for_aws.md
index 2e7de6cf2d4..c55ce993cfc 100644
--- a/doc/install/aws/gitlab_sre_for_aws.md
+++ b/doc/install/aws/gitlab_sre_for_aws.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: Doing SRE for GitLab instances and runners on AWS.
---
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 1227dd43369..93a966b69fb 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: Read through the GitLab installation methods.
type: index
@@ -65,7 +65,7 @@ Instances running on Community Edition (CE) require a migration to Enterprise Ed
NOTE:
Because any given GitLab upgrade might involve data disk updates or database schema upgrades, swapping out the AMI is not sufficient 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. Log in to the AWS Web Console, so that selecting 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.
diff --git a/doc/install/aws/manual_install_aws.md b/doc/install/aws/manual_install_aws.md
index 2aa2aa0c3f7..7dbb245dd99 100644
--- a/doc/install/aws/manual_install_aws.md
+++ b/doc/install/aws/manual_install_aws.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
{::options parse_block_html="true" /}
@@ -268,7 +268,7 @@ On the EC2 dashboard, look for Load Balancer in the left navigation bar:
1. Select **Configure Health Check** and set up a health check for your EC2 instances.
1. For **Ping Protocol**, select HTTP.
1. For **Ping Port**, enter 80.
- 1. For **Ping Path** - we recommend that you [use the Readiness check endpoint](../../administration/load_balancer.md#readiness-check). You must add [the VPC IP Address Range (CIDR)](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl) to the [IP allowlist](../../administration/monitoring/ip_whitelist.md) for the [Health Check endpoints](../../user/admin_area/monitoring/health_check.md)
+ 1. For **Ping Path** - we recommend that you [use the Readiness check endpoint](../../administration/load_balancer.md#readiness-check). You must add [the VPC IP Address Range (CIDR)](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl) to the [IP allowlist](../../administration/monitoring/ip_allowlist.md) for the [Health Check endpoints](../../user/admin_area/monitoring/health_check.md)
1. Keep the default **Advanced Details** or adjust them according to your needs.
1. Select **Add EC2 Instances** - don't add anything as we create an Auto Scaling Group later to manage instances for us.
1. Select **Add Tags** and add any tags you need.
@@ -465,7 +465,7 @@ We need a preconfigured, custom GitLab AMI to use in our launch configuration la
From the EC2 dashboard:
1. Use the section below titled "[Find official GitLab-created AMI IDs on AWS](#find-official-gitlab-created-ami-ids-on-aws)" to find the correct AMI to launch.
-1. After clicking **Launch** on the desired AMI, select an instance type based on your workload. Consult the [hardware requirements](../../install/requirements.md#hardware-requirements) to choose one that fits your needs (at least `c5.xlarge`, which is sufficient to accommodate 100 users).
+1. After selecting **Launch** on the desired AMI, select an instance type based on your workload. Consult the [hardware requirements](../../install/requirements.md#hardware-requirements) to choose one that fits your needs (at least `c5.xlarge`, which is sufficient to accommodate 100 users).
1. Select **Configure Instance Details**:
1. In the **Network** dropdown list, select `gitlab-vpc`, the VPC we created earlier.
1. In the **Subnet** dropdown list, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
@@ -670,9 +670,9 @@ Depending on how you installed GitLab and if you did not change the password by
- Your instance ID if you used the official GitLab AMI.
- A randomly generated password stored for 24 hours in `/etc/gitlab/initial_root_password`.
-To change the default password, log in as the `root` user with the default password and [change it in the user profile](../../user/profile#change-your-password).
+To change the default password, log in as the `root` user with the default password and [change it in the user profile](../../user/profile/user_passwords.md#change-your-password).
-When our [auto scaling group](#create-an-auto-scaling-group) spins up new instances, we are able to log in with username `root` and the newly created password.
+When our [auto scaling group](#create-an-auto-scaling-group) spins up new instances, we are able to sign in with username `root` and the newly created password.
### Create custom AMI
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index dd2e7d678e8..9d825bbadcd 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Learn how to spin up a pre-configured GitLab VM on Microsoft Azure.'
type: howto
---
@@ -61,7 +61,7 @@ The first items you need to configure are the basic settings of the underlying v
1. Enter a name for the VM, for example `GitLab`.
1. Select a region.
1. In **Availability options**, select **Availability zone** and set it to `1`.
- Read more about the [availability zones](https://docs.microsoft.com/en-us/azure/virtual-machines/availability).
+ Read more about the [availability zones](https://learn.microsoft.com/en-us/azure/virtual-machines/availability).
1. Ensure the selected image is set to **GitLab - Gen1**.
1. Select the VM size based on the [hardware requirements](../requirements.md#hardware-requirements).
Because the minimum system requirements to run a GitLab environment for up to 500 users
@@ -83,7 +83,7 @@ For the disks:
1. For the OS disk type, select **Premium SSD**.
1. Select the default encryption.
-[Read more about the types of disks](https://docs.microsoft.com/en-us/azure/virtual-machines/managed-disks-overview) that Azure provides.
+[Read more about the types of disks](https://learn.microsoft.com/en-us/azure/virtual-machines/managed-disks-overview) that Azure provides.
Review your settings, and then proceed to the Networking tab.
@@ -159,7 +159,7 @@ to assign a descriptive DNS name to the VM:
Eventually, most users want to use their own domain name. For you to do this, you need to add a DNS `A` record
with your domain registrar that points to the public IP address of your Azure VM.
-You can use [Azure's DNS](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns)
+You can use [Azure's DNS](https://learn.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns)
or some [other registrar](https://docs.gitlab.com/omnibus/settings/dns.html).
### Change the GitLab external URL
@@ -185,7 +185,7 @@ To set up the GitLab external URL:
NOTE:
If you need to reset your credentials, read
- [how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection#reset-ssh-credentials-for-a-user).
+ [how to reset SSH credentials for a user on an Azure VM](https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection#reset-ssh-credentials-for-a-user).
1. Open `/etc/gitlab/gitlab.rb` with your editor.
1. Find `external_url` and replace it with your own domain name. For the sake
@@ -236,7 +236,7 @@ The credentials are:
- Password: the password is automatically created, and there are
[two ways to find it](https://docs.bitnami.com/azure/faq/get-started/find-credentials/).
-After signing in, be sure to immediately [change the password](../../user/profile/index.md#change-your-password).
+After signing in, be sure to immediately [change the password](../../user/profile/user_passwords.md#change-your-password).
## Maintain your GitLab instance
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
deleted file mode 100644
index 86ccf194786..00000000000
--- a/doc/install/digitaloceandocker.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'docker.md'
-remove_date: '2022-08-29'
----
-
-This document was moved to [another location](docker.md).
-
-<!-- This redirect file can be deleted after <2022-08-29>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/install/docker.md b/doc/install/docker.md
index bf08fecc9ca..93988454a27 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Docker images **(FREE SELF)**
@@ -122,7 +122,7 @@ After starting a container you can visit `gitlab.example.com` (or
`http://192.168.59.103` if you used boot2docker on macOS). It might take a while
before the Docker container starts to respond to queries.
-Visit the GitLab URL, and log in with username `root`
+Visit the GitLab URL, and sign in with the username `root`
and the password from the following command:
```shell
@@ -298,13 +298,12 @@ sudo docker exec -it gitlab editor /etc/gitlab/gitlab.rb
Once you open `/etc/gitlab/gitlab.rb` make sure to set the `external_url` to
point to a valid URL.
-To receive e-mails from GitLab you have to configure the
+To receive emails from GitLab you have to configure the
[SMTP settings](https://docs.gitlab.com/omnibus/settings/smtp.html) because the GitLab Docker image doesn't
have an SMTP server installed. You may also be interested in
[enabling HTTPS](https://docs.gitlab.com/omnibus/settings/ssl.html).
-After you make all the changes you want, you will need to restart the container
-in order to reconfigure GitLab:
+After you make all the changes you want, you will need to restart the container to reconfigure GitLab:
```shell
sudo docker restart gitlab
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index e924b6f7c41..7ba1fbad5ea 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Learn how to install a GitLab instance on Google Cloud Platform.'
---
@@ -31,7 +31,7 @@ After you have performed those two steps, you can [create a VM](#creating-the-vm
To deploy GitLab on GCP you must create a virtual machine:
-1. Go to <https://console.cloud.google.com/compute/instances> and log in with your Google credentials.
+1. Go to <https://console.cloud.google.com/compute/instances> and sign in with your Google credentials.
1. Select **Create**
![Search for GitLab](img/launch_vm.png)
@@ -49,7 +49,7 @@ To deploy GitLab on GCP you must create a virtual machine:
## Installing GitLab
-After a few seconds, the instance is created and available to log in. The next step is to install GitLab onto the instance.
+After a few seconds, the instance is created and available to sign in. The next step is to install GitLab onto the instance.
![Deploy settings](img/vm_created.png)
diff --git a/doc/install/index.md b/doc/install/index.md
index 89203c652d1..4aef471ad5c 100644
--- a/doc/install/index.md
+++ b/doc/install/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: Read through the GitLab installation methods.
type: index
diff --git a/doc/install/install_methods.md b/doc/install/install_methods.md
index 6c62deba6fa..a872941dfaf 100644
--- a/doc/install/install_methods.md
+++ b/doc/install/install_methods.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
description: Read through the GitLab installation methods.
type: index
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 5982e354ae5..6108ec8d0e0 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Installation from source **(FREE SELF)**
@@ -49,7 +49,7 @@ If the highest number stable branch is unclear, check the [GitLab blog](https://
| Software | Minimum version | Notes |
| -------- | --------------- | ----- |
| [Ruby](#2-ruby) | `2.7` | From GitLab 13.6, Ruby 2.7 is required. Ruby 3.0 is not supported yet (see [the relevant epic](https://gitlab.com/groups/gitlab-org/-/epics/5149) for the current status). You must use the standard MRI implementation of Ruby. We love [JRuby](https://www.jruby.org/) and [Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform), but GitLab needs several Gems that have native extensions. |
-| [Go](#3-go) | `1.16` | |
+| [Go](#3-go) | `1.17` | From GitLab 15.2, Go 1.17 or later is required. |
| [Git](#git) | `2.33.x` | From GitLab 14.4, Git 2.33.x and later is required. It's highly recommended that you use the [Git version provided by Gitaly](#git). |
| [Node.js](#4-node) | `14.15.0` | GitLab uses [webpack](https://webpack.js.org/) to compile frontend assets. Node.js 16.x is recommended, as it's faster. You can check which version you're running with `node -v`. You must update it to a newer version if needed. |
@@ -120,6 +120,10 @@ sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdb
libcurl4-openssl-dev libicu-dev logrotate rsync python3-docutils pkg-config cmake runit-systemd
```
+NOTE:
+GitLab requires OpenSSL version 1.1. If your Linux distribution includes a different version of OpenSSL,
+you might have to install 1.1 manually.
+
If you want to use Kerberos for user authentication, install `libkrb5-dev`
(if you don't know what Kerberos is, you can assume you don't need it):
diff --git a/doc/install/migrate/compare_sm_to_saas.md b/doc/install/migrate/compare_sm_to_saas.md
index df79987a2fa..e12861632b8 100644
--- a/doc/install/migrate/compare_sm_to_saas.md
+++ b/doc/install/migrate/compare_sm_to_saas.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Comparison of GitLab self-managed with GitLab SaaS
diff --git a/doc/install/next_steps.md b/doc/install/next_steps.md
index 4df2da875a6..c718d895c8a 100644
--- a/doc/install/next_steps.md
+++ b/doc/install/next_steps.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Steps after installing GitLab **(FREE SELF)**
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 6bce71e84c1..a620540369f 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# OpenShift support
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 8d1cf9afc5c..2d6a9411f25 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Managing PostgreSQL extensions **(FREE SELF)**
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 6c60ee09d78..3fe34f6a9b0 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install GitLab under a relative URL **(FREE SELF)**
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 03870897417..8a1533dc268 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Installation system requirements **(FREE SELF)**
diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md
index 755dc5230e9..87b812f3f9b 100644
--- a/doc/integration/advanced_search/elasticsearch.md
+++ b/doc/integration/advanced_search/elasticsearch.md
@@ -2,7 +2,7 @@
type: reference
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Elasticsearch integration **(PREMIUM SELF)**
@@ -742,7 +742,7 @@ Make sure to prepare for this task by having a
### Deleted documents
-Whenever a change or deletion is made to an indexed GitLab object (a merge request description is changed, a file is deleted from the default branch in a repository, a project is deleted, etc), a document in the index is deleted. However, since these are "soft" deletes, the overall number of "deleted documents", and therefore wasted space, increases. Elasticsearch does intelligent merging of segments in order to remove these deleted documents. However, depending on the amount and type of activity in your GitLab installation, it's possible to see as much as 50% wasted space in the index.
+Whenever a change or deletion is made to an indexed GitLab object (a merge request description is changed, a file is deleted from the default branch in a repository, a project is deleted, etc), a document in the index is deleted. However, since these are "soft" deletes, the overall number of "deleted documents", and therefore wasted space, increases. Elasticsearch does intelligent merging of segments to remove these deleted documents. However, depending on the amount and type of activity in your GitLab installation, it's possible to see as much as 50% wasted space in the index.
In general, we recommend letting Elasticsearch merge and reclaim space automatically, with the default settings. From [Lucene's Handling of Deleted Documents](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene's Handling of Deleted Documents"), _"Overall, besides perhaps decreasing the maximum segment size, it is best to leave Lucene's defaults as-is and not fret too much about when deletes are reclaimed."_
diff --git a/doc/integration/advanced_search/elasticsearch_troubleshooting.md b/doc/integration/advanced_search/elasticsearch_troubleshooting.md
index e1a566541c2..7136c273a2a 100644
--- a/doc/integration/advanced_search/elasticsearch_troubleshooting.md
+++ b/doc/integration/advanced_search/elasticsearch_troubleshooting.md
@@ -2,7 +2,7 @@
type: reference
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Elasticsearch **(PREMIUM SELF)**
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index a2b70d42bb6..09f16c76765 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -1,7 +1,7 @@
---
stage: Anti-Abuse
group: Anti-Abuse
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Akismet **(FREE)**
diff --git a/doc/integration/alicloud.md b/doc/integration/alicloud.md
index 1619bdc9504..263b3837d1d 100644
--- a/doc/integration/alicloud.md
+++ b/doc/integration/alicloud.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use AliCloud as an OmniAuth authentication provider **(FREE)**
diff --git a/doc/integration/arkose.md b/doc/integration/arkose.md
index 0135785dc11..aa27e3ba4a4 100644
--- a/doc/integration/arkose.md
+++ b/doc/integration/arkose.md
@@ -1,7 +1,7 @@
---
stage: Anti-Abuse
group: Anti-Abuse
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Arkose Protect
@@ -29,7 +29,7 @@ user doesn't need to take any additional action and can sign in as usual.
## How do we treat malicious sign-in attempts?
Users are not denied access if Arkose Protect considers they are malicious. However,
-their risk score is exposed in the admin console so that we can make more informed decisions when it
+their risk score is exposed in the administrator console so that we can make more informed decisions when it
comes to manually blocking users. When we decide to block a user, feedback is sent to ArkoseLabs to
improve their risk prediction model.
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index 71c71bd8b5c..448807e91fc 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Auth0 OmniAuth Provider **(FREE SELF)**
@@ -11,28 +11,22 @@ application.
1. Sign in to the [Auth0 Console](https://auth0.com/auth/login). You can also
create an account using the same link.
-
1. Select **New App/API**.
-
-1. Provide the Application Name ('GitLab' works fine).
-
-1. After creating, you should see the **Quick Start** options. Disregard them and
- select **Settings** above the **Quick Start** options.
-
+1. Enter the **Application Name**. For example, 'GitLab'.
+1. After creating the application, you should see the **Quick Start** options.
+ Disregard these options and select **Settings** instead.
1. At the top of the Settings screen, you should see your **Domain**, **Client ID**, and
- **Client Secret**. These values are needed in the configuration file. For example:
+ **Client Secret** in the Auth0 Console. Note these settings to complete the configuration
+ file later. For example:
- Domain: `test1234.auth0.com`
- Client ID: `t6X8L2465bNePWLOvt9yi41i`
- Client Secret: `KbveM3nqfjwCbrhaUy_gDu2dss8TIlHIdzlyf33pB7dEK5u_NyQdp65O_o02hXs2`
-
1. Fill in the **Allowed Callback URLs**:
- - `http://YOUR_GITLAB_URL/users/auth/auth0/callback` (or)
- - `https://YOUR_GITLAB_URL/users/auth/auth0/callback`
-
+ - `http://<your_gitlab_url>/users/auth/auth0/callback` (or)
+ - `https://<your_gitlab_url>/users/auth/auth0/callback`
1. Fill in the **Allowed Origins (CORS)**:
- - `http://YOUR_GITLAB_URL` (or)
- - `https://YOUR_GITLAB_URL`
-
+ - `http://<your_gitlab_url>` (or)
+ - `https://<your_gitlab_url>`
1. On your GitLab server, open the configuration file.
For Omnibus GitLab:
@@ -61,9 +55,9 @@ application.
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",
+ client_id: "<your_auth0_client_id>",
+ client_secret: "<your_auth0_client_secret>",
+ domain: "<your_auth0_domain>",
scope: "openid profile email"
}
}
@@ -76,21 +70,17 @@ application.
- { 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',
+ client_id: '<your_auth0_client_id>',
+ client_secret: '<your_auth0_client_secret>',
+ domain: '<your_auth0_domain>',
scope: 'openid profile email' }
}
```
-1. Change `YOUR_AUTH0_CLIENT_ID` to the client ID from the Auth0 Console page
- from step 5.
-
-1. Change `YOUR_AUTH0_CLIENT_SECRET` to the client secret from the Auth0 Console
- page from step 5.
-
+1. Replace `<your_auth0_client_id>` with the client ID from the Auth0 Console page.
+1. Replace `<your_auth0_client_secret>` with the client secret from the Auth0 Console page.
+1. Replace `<your_auth0_client_secret>` with the domain from the Auth0 Console page.
1. Reconfigure or restart GitLab, depending on your installation method:
-
- *If you installed from Omnibus GitLab,*
[Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
- *If you installed from source,*
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index da1aa574bd6..8c30a0cef77 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -1,19 +1,19 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use Microsoft Azure as an authentication provider **(FREE SELF)**
You can enable the Microsoft Azure OAuth 2.0 OmniAuth provider and sign in to
GitLab with your Microsoft Azure credentials. You can configure the provider that uses
-[the earlier Azure Active Directory v1.0 endpoint](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code),
+[the earlier Azure Active Directory v1.0 endpoint](https://learn.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code),
or the provider that uses the v2.0 endpoint.
NOTE:
For new projects, Microsoft suggests you use the
-[OpenID Connect protocol](../administration/auth/oidc.md#microsoft-azure),
+[OpenID Connect protocol](../administration/auth/oidc.md#configure-microsoft-azure),
which uses the Microsoft identity platform (v2.0) endpoint.
## Register an Azure application
@@ -22,8 +22,8 @@ To enable the Microsoft Azure OAuth 2.0 OmniAuth provider, you must register
an Azure application and get a client ID and secret key.
1. Sign in to the [Azure portal](https://portal.azure.com).
-1. If you have multiple Azure Active Directory tenants, switch to the desired tenant.
-1. [Register an application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
+1. If you have multiple Azure Active Directory tenants, switch to the desired tenant. Note the tenant ID.
+1. [Register an application](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
and provide the following information:
- The redirect URI, which requires the URL of the Azure OAuth callback of your GitLab
installation. For example:
@@ -33,7 +33,7 @@ an Azure application and get a client ID and secret key.
1. Save the client ID and client secret. The client secret is only
displayed once.
- If required, you can [create a new application secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).
+ If required, you can [create a new application secret](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).
`client ID` and `client secret` are terms associated with OAuth 2.0.
In some Microsoft documentation, the terms are named `Application ID` and
@@ -41,7 +41,7 @@ In some Microsoft documentation, the terms are named `Application ID` and
## Add API permissions (scopes)
-If you're using the v2.0 endpoint, after you create the application, [configure it to expose a web API](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis).
+If you're using the v2.0 endpoint, after you create the application, [configure it to expose a web API](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis).
Add the following delegated permissions under the Microsoft Graph API:
- `email`
@@ -70,7 +70,7 @@ Alternatively, add the `User.Read.All` application permission.
1. [Configure the initial settings](omniauth.md#configure-initial-settings).
-1. Add the provider configuration. Replace `CLIENT ID`, `CLIENT SECRET`, and `TENANT ID`
+1. Add the provider configuration. Replace `<client_id>`, `<client_secret>`, and `<tenant_id>`
with the values you got when you registered the Azure application.
- **For Omnibus installations**
@@ -83,9 +83,9 @@ Alternatively, add the `User.Read.All` application permission.
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",
+ client_id: "<client_id>",
+ client_secret: "<client_secret>",
+ tenant_id: "<tenant_id>",
}
}
]
@@ -99,15 +99,15 @@ Alternatively, add the `User.Read.All` application permission.
"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",
- "tenant_id" => "TENANT ID",
+ "client_id" => "<client_id>",
+ "client_secret" => "<client_secret>",
+ "tenant_id" => "<tenant_id>",
}
}
]
```
- For [alternative Azure clouds](https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-national-cloud),
+ For [alternative Azure clouds](https://learn.microsoft.com/en-us/azure/active-directory/develop/authentication-national-cloud),
configure `base_azure_url` under the `args` section. For example, for Azure Government Community Cloud (GCC):
```ruby
@@ -116,9 +116,9 @@ Alternatively, add the `User.Read.All` application permission.
"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",
- "tenant_id" => "TENANT ID",
+ "client_id" => "<client_id>",
+ "client_secret" => "<client_secret>",
+ "tenant_id" => "<tenant_id>",
"base_azure_url" => "https://login.microsoftonline.us"
}
}
@@ -132,9 +132,9 @@ Alternatively, add the `User.Read.All` application permission.
```yaml
- { 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' } }
+ args: { client_id: '<client_id>',
+ client_secret: '<client_secret>',
+ tenant_id: '<tenant_id>' } }
```
For the v2.0 endpoint:
@@ -142,26 +142,24 @@ Alternatively, add the `User.Read.All` application permission.
```yaml
- { 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",
- tenant_id: "TENANT ID" } }
+ args: { client_id: "<client_id>",
+ client_secret: "<client_secret>",
+ tenant_id: "<tenant_id>" } }
```
- For [alternative Azure clouds](https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-national-cloud),
+ For [alternative Azure clouds](https://learn.microsoft.com/en-us/azure/active-directory/develop/authentication-national-cloud),
configure `base_azure_url` under the `args` section. For example, for Azure Government Community Cloud (GCC):
```yaml
- { 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",
- tenant_id: "TENANT ID",
+ args: { client_id: "<client_id>",
+ client_secret: "<client_secret>",
+ tenant_id: "<tenant_id>",
base_azure_url: "https://login.microsoftonline.us" } }
```
- In addition, you can optionally add the following parameters to the `args` section:
-
- - `scope` for [OAuth2 scopes](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow). The default is `openid profile email`.
+ You can also optionally add the `scope` for [OAuth 2.0 scopes](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) parameter to the `args` section. The default is `openid profile email`.
1. Save the configuration file.
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index 43032902a21..38d8f0049db 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrate your GitLab server with Bitbucket Cloud **(FREE SELF)**
@@ -22,14 +22,9 @@ To enable the Bitbucket OmniAuth provider you must register your application
with Bitbucket.org. Bitbucket generates an application ID and secret key for
you to use.
-WARNING:
-To help prevent an [OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/)
-vulnerability in which users' GitLab accounts could be compromised, append `/users/auth`
-to the end of the Bitbucket authorization callback URL.
-
1. Sign in to [Bitbucket.org](https://bitbucket.org).
-1. Navigate to your individual user settings (**Bitbucket settings**) or a team's
- settings (**Manage team**), depending on how you want the application registered.
+1. Go to your individual user settings (**Bitbucket settings**) or a team's
+ settings (**Manage team**), depending on how you want to register the application.
It does not matter if the application is registered as an individual or a
team, that is entirely up to you.
1. In the left menu under **Access Management**, select **OAuth**.
@@ -44,6 +39,12 @@ to the end of the Bitbucket authorization callback URL.
`https://gitlab.example.com/users/auth`.
Leaving this field empty
[results in an `Invalid redirect_uri` message](https://confluence.atlassian.com/bitbucket/oauth-faq-338365710.html).
+
+ WARNING:
+ To help prevent an [OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/)
+ vulnerability in which users' GitLab accounts could be compromised, append `/users/auth`
+ to the end of the Bitbucket authorization callback URL.
+
- **URL:** The URL to your GitLab installation, such as `https://gitlab.example.com`.
1. Grant at least the following permissions:
@@ -85,8 +86,8 @@ to the end of the Bitbucket authorization callback URL.
{
name: "bitbucket",
# label: "Provider name", # optional label for login button, defaults to "Bitbucket"
- app_id: "BITBUCKET_APP_KEY",
- app_secret: "BITBUCKET_APP_SECRET",
+ app_id: "<bitbucket_app_key>",
+ app_secret: "<bitbucket_app_secret>",
url: "https://bitbucket.org/"
}
]
@@ -100,12 +101,12 @@ to the end of the Bitbucket authorization callback URL.
providers:
- { name: 'bitbucket',
# label: 'Provider name', # optional label for login button, defaults to "Bitbucket"
- app_id: 'BITBUCKET_APP_KEY',
- app_secret: 'BITBUCKET_APP_SECRET',
+ app_id: '<bitbucket_app_key>',
+ app_secret: '<bitbucket_app_secret>',
url: 'https://bitbucket.org/' }
```
- Where `BITBUCKET_APP_KEY` is the Key and `BITBUCKET_APP_SECRET` the Secret
+ Where `<bitbucket_app_key>` is the **Key** and `<bitbucket_app_secret>` the **Secret**
from the Bitbucket application page.
1. Save the configuration file.
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 45c79cd9726..35c5a6db4a7 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# CAS OmniAuth provider (deprecated) **(FREE SELF)**
diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md
index 42337006189..31e254658c1 100644
--- a/doc/integration/datadog.md
+++ b/doc/integration/datadog.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Datadog integration **(FREE)**
diff --git a/doc/integration/ding_talk.md b/doc/integration/ding_talk.md
index 71dadd766b2..18423fa1607 100644
--- a/doc/integration/ding_talk.md
+++ b/doc/integration/ding_talk.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# DingTalk OAuth 2.0 OmniAuth provider **(FREE SELF)**
@@ -19,7 +19,7 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
1. Fill in the application details:
- - **Application Name**: This can be anything. Consider something like `<Organization>'s GitLab`, or `<Your Name>'s GitLab`, or something else descriptive.
+ - **Application Name**: This can be anything. Consider something like `<Organization>'s GitLab`, `<Your Name>'s GitLab`, or something else descriptive.
- **Application Description**: Create a description.
- **Application icon**: Upload qualified icons if needed.
@@ -31,7 +31,7 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
![DingTalk your application](img/ding_talk_your_application.png)
-1. Under the **Application Credentials** section, there should be an AppKey and AppSecret (see the screenshot). Keep this page open as you continue the configuration.
+1. In the **Application Credentials** section, note the **AppKey** and **AppSecret** as you use these values later.
![DingTalk credentials](img/ding_talk_credentials.png)
@@ -62,8 +62,8 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
{
name: "dingtalk",
# label: "Provider name", # optional label for login button, defaults to "Ding Talk"
- app_id: "YOUR_APP_ID",
- app_secret: "YOUR_APP_SECRET"
+ app_id: "<your_appkey>",
+ app_secret: "<your_appsecret>"
}
]
```
@@ -73,16 +73,16 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
```yaml
- { name: 'dingtalk',
# label: 'Provider name', # optional label for login button, defaults to "Ding Talk"
- app_id: 'YOUR_APP_ID',
- app_secret: 'YOUR_APP_SECRET' }
+ app_id: '<your_appkey>',
+ app_secret: '<your_appsecret>' }
```
-1. Change `YOUR_APP_ID` to the AppKey from the application information page in step 6.
+1. Replace `<your_appkey>` with the AppKey from the **Application Credentials** in step 6.
-1. Change `YOUR_APP_SECRET` to the AppSecret from the application information page in step 6.
+1. Replace `<your_appsecret>` with the AppSecret from the **Application Credentials** in step 6.
1. Save the configuration file.
-1. For the changes to take effect:
- - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
- - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
+1. For the changes to take effect, if you installed:
+ - Using Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - From source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
deleted file mode 100644
index 0b34f7018da..00000000000
--- a/doc/integration/elasticsearch.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'advanced_search/elasticsearch.md'
-remove_date: '2022-09-13'
----
-
-This document was moved to [another location](advanced_search/elasticsearch.md).
-
-<!-- This redirect file can be deleted after <2022-09-13>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> \ No newline at end of file
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index ac470291c27..a3c206176b9 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# External issue tracker **(FREE)**
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index ea5a3cc6d38..7c6afffc847 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Facebook OAuth 2.0 OmniAuth Provider **(FREE)**
diff --git a/doc/integration/github.md b/doc/integration/github.md
index ad90c714dac..6b59128966a 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use GitHub as an authentication provider **(FREE SELF)**
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index fee1e573384..0658c921610 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrate your server with GitLab.com **(FREE SELF)**
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index c2b27e79d6e..26d0da4b49d 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -2,7 +2,7 @@
type: reference, how-to
stage: Create
group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Gitpod integration **(FREE)**
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 8b984122c8b..42b89670a68 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gmail actions buttons for GitLab **(FREE)**
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 80176fac41b..3d174e56bf3 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Google OAuth 2.0 OmniAuth Provider **(FREE SELF)**
diff --git a/doc/integration/index.md b/doc/integration/index.md
index f5b088b47f7..147edcc9e0f 100644
--- a/doc/integration/index.md
+++ b/doc/integration/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
@@ -9,6 +9,10 @@ comments: false
GitLab can be integrated with external services for enhanced functionality.
+## Services
+
+Services such as Campfire, Flowdock, Jira, Pivotal Tracker, and Slack are available as [integrations](../user/project/integrations/index.md).
+
## Issue trackers
You can use an [external issue tracker](external-issue-tracker.md) at the same time as the GitLab
@@ -61,10 +65,6 @@ or [Kroki](../administration/integration/kroki.md) to use diagrams in AsciiDoc a
- Enable integrated code intelligence powered by [Sourcegraph](sourcegraph.md).
- Add [Elasticsearch](advanced_search/elasticsearch.md) for [Advanced Search](../user/search/advanced_search.md).
-## Integrations
-
-Integration with services such as Campfire, Flowdock, Jira, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/index.md).
-
## Troubleshooting
### SSL certificate errors
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 0a4c2c27c31..8a438dde52e 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jenkins integration **(FREE)**
@@ -222,15 +222,7 @@ Or check for duplicate messages in `/var/log/gitlab/gitlab-rail`, like:
2019-10-25_04:22:41.25630 2019-10-25T04:22:41.256Z 1584 TID-ovowh4tek WebHookWorker JID-941fb7f40b69dff3d833c99b INFO: start
```
-To fix this issue:
-
-1. Increase the `gitlab_rails['webhook_timeout']` value in the `gitlab.rb`
- configuration file.
-1. [Restart](../administration/restart_gitlab.md) GitLab:
-
- ```shell
- gitlab-ctl reconfigure
- ```
+On self-managed GitLab instances, you can fix this issue by [increasing the webhook timeout value](../administration/instance_limits.md#webhook-timeout).
### Enable job logs in Jenkins
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index 5010545b73a..53f7162402b 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
remove_date: '2022-10-29'
redirect_to: 'jenkins.md'
---
diff --git a/doc/integration/jira/configure.md b/doc/integration/jira/configure.md
index 58789afff46..66339d5ec27 100644
--- a/doc/integration/jira/configure.md
+++ b/doc/integration/jira/configure.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure the Jira integration in GitLab **(FREE)**
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index 5c8f78a94b1..171c1cbe484 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab.com for Jira Cloud app **(FREE)**
diff --git a/doc/integration/jira/development_panel.md b/doc/integration/jira/development_panel.md
index d52d86c5658..bdb79d65d5e 100644
--- a/doc/integration/jira/development_panel.md
+++ b/doc/integration/jira/development_panel.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Jira development panel integration **(FREE)**
@@ -70,7 +70,7 @@ To simplify administration, we recommend that a GitLab group maintainer or group
| Jira usage | GitLab.com customers need | GitLab self-managed customers need |
|------------|---------------------------|------------------------------------|
| [Atlassian cloud](https://www.atlassian.com/migration/assess/why-cloud) | The [GitLab.com for Jira Cloud app](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). This offers real-time sync between GitLab.com and Jira. For more information, see the documentation for the [GitLab.com for Jira Cloud app](connect-app.md). | The [GitLab.com for Jira Cloud app](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See the documentation for [installing the GitLab.com for Jira Cloud app for self-managed instances](connect-app.md#install-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances) for more information. |
-| Your own server | The [Jira DVCS (distributed version control system) connector](dvcs.md). This syncs data hourly. | The [Jira DVCS Connector](dvcs.md). |
+| Your own server | The [Jira DVCS (distributed version control system) connector](dvcs.md). This syncs data hourly. | The [Jira DVCS (distributed version control system) connector](dvcs.md). This syncs data hourly. |
Each GitLab project can be configured to connect to an entire Jira instance. That means after
configuration, one GitLab project can interact with all Jira projects in that instance. For:
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index ce097a4db23..f33536b7b91 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jira DVCS connector **(FREE)**
diff --git a/doc/integration/jira/index.md b/doc/integration/jira/index.md
index 2f694094940..5daad4094f4 100644
--- a/doc/integration/jira/index.md
+++ b/doc/integration/jira/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jira integrations **(FREE)**
@@ -122,3 +122,59 @@ and complete the CAPTCHA.
There is a [known bug](https://gitlab.com/gitlab-org/gitlab/-/issues/341571)
where the Jira integration sometimes does not work for a project that has been imported.
As a workaround, disable the integration and then re-enable it.
+
+### Bulk change all Jira integrations to Jira instance-level values
+
+To change all Jira projects to use instance-level integration settings:
+
+1. In a [Rails console](../../administration/operations/rails_console.md#starting-a-rails-console-session), run the following:
+
+ ```ruby
+ jira_integration_instance_id = Integrations::Jira.find_by(instance: true).id
+ Integrations::Jira.where(active: true, instance: false, template: false, inherit_from_id: nil).find_each do |integration|
+ integration.update_attribute(:inherit_from_id, jira_integration_instance_id)
+ end
+ ```
+
+1. Modify and save the instance-level integration from the UI to propagate the changes to all group-level and project-level integrations.
+
+### Check if Jira Cloud is linked
+
+You can use the [Rails console](../../administration/operations/rails_console.md#starting-a-rails-console-session) to check if Jira Cloud is linked to:
+
+A specified namespace:
+
+```ruby
+JiraConnectSubscription.where(namespace: Namespace.by_path('group/subgroup'))
+```
+
+A specified project:
+
+```ruby
+Project.find_by_full_path('path/to/project').jira_subscription_exists?
+```
+
+Any namespace:
+
+```ruby
+installation = JiraConnectInstallation.find_by_base_url("https://customer_name.atlassian.net")
+installation.subscriptions
+```
+
+### Bulk update the service integration password for all projects
+
+To reset the Jira user's password for all projects with active Jira integrations,
+run the following in a [Rails console](../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN services s ON p.id = s.project_id WHERE s.type = 'JiraService' AND s.active = true")
+
+p.each do |project|
+ project.jira_integration.update_attribute(:password, '<your-new-password>')
+end
+```
+
+### `500 Whoops` when accessing a Jira issue in GitLab
+
+When accessing a Jira issue in GitLab, you might get a `500 Whoops, something went wrong on our end` error.
+Check [`production.log`](../../administration/logs/index.md#productionlog) to see if it contains a `:NoMethodError (undefined method 'duedate' for #<JIRA::Resource::Issue:0x00007f406d7b3180>)` exception. If that's the case, ensure the **Due date** field is visible for issues in the integrated Jira project.
diff --git a/doc/integration/jira/issues.md b/doc/integration/jira/issues.md
index 98dd4526fd9..3a5d8e66b2d 100644
--- a/doc/integration/jira/issues.md
+++ b/doc/integration/jira/issues.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jira integration issue management **(FREE)**
diff --git a/doc/integration/jira/jira_cloud_configuration.md b/doc/integration/jira/jira_cloud_configuration.md
index 08cd34860ff..d47c84df5e5 100644
--- a/doc/integration/jira/jira_cloud_configuration.md
+++ b/doc/integration/jira/jira_cloud_configuration.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create an API token for Jira in Atlassian cloud **(FREE)**
diff --git a/doc/integration/jira/jira_server_configuration.md b/doc/integration/jira/jira_server_configuration.md
index 63625dd5065..42de883753c 100644
--- a/doc/integration/jira/jira_server_configuration.md
+++ b/doc/integration/jira/jira_server_configuration.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Jira Server credentials **(FREE)**
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 5c9af96ebe8..c7cbc4389f5 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: "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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Kerberos integration **(PREMIUM SELF)**
@@ -295,7 +295,7 @@ this can happen in GitLab CI/CD jobs that [authenticate with the CI/CD job token
1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
After this change, Git remote URLs have to be updated to
-`https://gitlab.example.com:8443/mygroup/myproject.git` in order to use
+`https://gitlab.example.com:8443/mygroup/myproject.git` to use
Kerberos ticket-based authentication.
## Upgrading from password-based to ticket-based Kerberos sign-ins
diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 1e57e45aef3..04b0157b737 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Mattermost
@@ -272,7 +272,7 @@ There are 4 users on local instance
### Use `mmctl` through a remote connection
For remote connections or local connections where the socket cannot be used,
-create a non SSO user and give that user admin privileges. Those credentials
+create a non SSO user and give that user administrator privileges. Those credentials
can then be used to authenticate `mmctl`:
```shell
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index e3ec1aa16a1..a337873a67e 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -1,42 +1,42 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Generic OAuth2 provider **(FREE SELF)**
+# Generic OAuth 2.0 provider **(FREE SELF)**
The `omniauth-oauth2-generic` gem allows single sign-on (SSO) between GitLab
-and your OAuth2 provider (or any OAuth2 provider compatible with this gem).
+and your OAuth 2.0 provider, or any OAuth 2.0 provider compatible with this gem).
This strategy allows for the configuration of this OmniAuth SSO process:
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. The OAuth 2.0 provider handles authentication of the request, user, and (optionally)
+ authorization to access the user's profile.
+1. The OAuth 2.0 provider directs the client back to GitLab where Strategy
+ retrieves 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**
+ 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
+This strategy:
-- 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.
+- Can only be used for single sign-on, and does not provide any other access
+ granted by any OAuth 2.0 provider. For example, importing projects or users.
+- Only supports the Authorization Grant flow, which is most common for client-server
+ applications like GitLab.
+- Cannot fetch user information from more than one URL.
+- Has not been tested with user information formats, except JSON.
-## Configure the OAuth2 provider
+## Configure the OAuth 2.0 provider
To configure the provider:
-1. Register your application in the OAuth2 provider you want to authenticate with.
+1. Register your application in the OAuth 2.0 provider you want to authenticate with.
The redirect URI you provide when registering the application should be:
@@ -44,9 +44,9 @@ To configure the provider:
http://your-gitlab.host.com/users/auth/oauth2_generic/callback
```
- 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.
+ You should now be able to get a client ID and client secret. Where these
+ appear is different for each provider. This may also be called application ID
+ and application secret.
1. On your GitLab server, open the appropriate configuration file.
@@ -99,15 +99,14 @@ To configure the provider:
]
```
- For more information about these settings, see [the gem's README](https://gitlab.com/satorix/omniauth-oauth2-generic#gitlab-config-example).
+ 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. [Restart](../administration/restart_gitlab.md#installations-from-source)
- GitLab for the changes to take effect.
+1. For the changes to take effect, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
-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
+On the sign-in page there should now be a new icon below the regular sign-in
+form. Select that icon to begin your provider's authentication process. This
+directs the browser to your OAuth 2.0 provider's authentication page. If
+everything goes well, you are returned to your GitLab instance and
signed in.
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 21184f7b678..964c5edcbc1 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure GitLab as an OAuth 2.0 authentication identity provider
@@ -126,7 +126,7 @@ application can perform. Available scopes are depicted in the following table.
| `profile` | Grants read-only access to the user's profile data using [OpenID Connect](openid_connect_provider.md). |
| `email` | Grants read-only access to the user's primary email address using [OpenID Connect](openid_connect_provider.md). |
-At any time you can revoke any access by clicking **Revoke**.
+At any time you can revoke any access by selecting **Revoke**.
## Hashed OAuth application secrets
@@ -137,3 +137,17 @@ On self-managed GitLab, by default, this feature is not available. To make it av
On GitLab.com, this feature is not available.
By default, OAuth application secrets are stored as plain text in the database. When enabled, OAuth application secrets are stored in the database in hashed format and are only available to users immediately after creating OAuth applications.
+
+## Hashed OAuth tokens
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364110) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `hash_oauth_tokens`. Enabled on GitLab.com. Disabled by default for self-managed.
+> - [Enabled by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 15.5.
+
+FLAG:
+On self-managed GitLab, by default, this feature is enabled. If you detect a problem, ask an administrator to
+[disable the feature flag](../administration/feature_flags.md) named `hash_oauth_tokens`. If the feature flag is disabled, any tokens that were stored
+in encrypted format are inaccessible. Users must reauthorize applications.
+On GitLab.com, this feature is enabled.
+
+By default, OAuth access tokens are stored in the database in PBKDF2+SHA512 format. GitLab administrators can disable this and OAuth access tokens are
+then stored in plaintext in the database.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 0dfc78b508b..55d1d1bcbb8 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# OmniAuth **(FREE SELF)**
@@ -439,8 +439,9 @@ then override the icon in one of two ways:
## Change apps or configuration
-Because GitLab doesn't support having multiple providers in OAuth, GitLab configuration and user identification must be
-updated at the same time if the provider or app is changed.
+Because OAuth in GitLab doesn't support setting the same external authentication and authorization provider as multiple providers, GitLab configuration and
+user identification must be updated at the same time if the provider or app is changed.
+For example, you can set up `saml` and `azure_activedirectory_v2` but cannot add a second `azure_activedirectory_v2` to the same configuration.
These instructions apply to all methods of authentication where GitLab stores an `extern_uid` and it is the only data used
for user authentication.
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index cc9c8ffd012..ad4cf195d7b 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab as OpenID Connect identity provider **(FREE)**
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index a5fd8db63bd..93d859dd183 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# reCAPTCHA **(FREE SELF)**
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 70d6e0aa0d8..d4d2bfacb4f 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -1,12 +1,12 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Salesforce OmniAuth Provider **(FREE SELF)**
-You can integrate your GitLab instance with [Salesforce](https://www.salesforce.com/) to enable users to log in to your GitLab instance with their Salesforce account.
+You can integrate your GitLab instance with [Salesforce](https://www.salesforce.com/) to enable users to sign in to your GitLab instance with their Salesforce account.
## Create a Salesforce Connected App
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index ef31f276025..0f7f3e336ef 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -795,7 +795,7 @@ documentation on how to use SAML to sign in to GitLab.
Examples:
-- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
+- [ADFS (Active Directory Federation Services)](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider)
GitLab provides the following setup notes for guidance only.
diff --git a/doc/integration/security_partners/index.md b/doc/integration/security_partners/index.md
index 507157f9326..a337ed7757b 100644
--- a/doc/integration/security_partners/index.md
+++ b/doc/integration/security_partners/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index
---
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index db1d5a8cce4..ff892f006a5 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Slash commands in Mattermost and Slack **(FREE)**
diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md
index 731c21c17fa..39efccb7c50 100644
--- a/doc/integration/sourcegraph.md
+++ b/doc/integration/sourcegraph.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, how-to
---
diff --git a/doc/integration/trello_power_up.md b/doc/integration/trello_power_up.md
index 8a8952cb594..df3755dbf31 100644
--- a/doc/integration/trello_power_up.md
+++ b/doc/integration/trello_power_up.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Trello Power-Up **(FREE)**
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index aa9014adc49..90fb63ff40a 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -1,45 +1,51 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Twitter OAuth 1.0a OmniAuth Provider **(FREE SELF)**
NOTE:
-Twitter OAuth 2.0 support is [not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/366213).
+Twitter OAuth 2.0 support is [not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/366213).
To enable the Twitter OmniAuth provider you must register your application with
Twitter. Twitter generates a client ID and secret key for you to use.
+## Create a new Twitter application
+
1. Sign in to [Twitter Application Management](https://developer.twitter.com/apps).
-1. Select "Create new app".
+1. Select **Create new app**.
1. Fill in the application details.
- - Name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or
+ - **Name**: This can be anything. Consider something like `<Organization>'s GitLab`, `<Your Name>'s GitLab` or
something else descriptive.
- - Description: Create a description.
- - Website: The URL to your GitLab installation. `https://gitlab.example.com`
- - Callback URL: `https://gitlab.example.com/users/auth/twitter/callback`
- - Agree to the "Developer Agreement".
+ - **Description**: Create a description.
+ - **Website**: The URL to your GitLab installation. For example, `https://gitlab.example.com`
+ - **Callback URL**: `https://gitlab.example.com/users/auth/twitter/callback`
+ - **Developer Agreement**: Select **Yes, I agree**.
![Twitter App Details](img/twitter_app_details.png)
-1. Select "Create your Twitter application."
+1. Select **Create your Twitter application**.
+
+## Configure the application settings
-1. Select the "Settings" tab.
+1. Select the **Settings** tab.
-1. Underneath the Callback URL check the box next to "Allow this application to be used to Sign in with Twitter."
+1. Underneath the **Callback URL**, select the **Allow this application to be used to Sign in with Twitter** checkbox.
-1. Select "Update settings" at the bottom to save changes.
+1. Select **Update settings** to save the changes.
-1. Select the "Keys and Access Tokens" tab.
+1. Select the **Keys and Access Tokens** tab.
-1. You should now see an API key and API secret (see screenshot). Keep this page open as you continue configuration.
+1. Find your **API key** and **API secret**. Keep this tab open as you continue configuration.
![Twitter app](img/twitter_app_api_keys.png)
+## Configure your application on the GitLab server
+
1. On your GitLab server, open the configuration file.
For Omnibus package:
@@ -58,7 +64,7 @@ Twitter. Twitter generates a client ID and secret key for you to use.
1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
-1. Add the provider configuration:
+1. Add the provider configuration.
For Omnibus package:
@@ -67,8 +73,8 @@ Twitter. Twitter generates a client ID and secret key for you to use.
{
name: "twitter",
# label: "Provider name", # optional label for login button, defaults to "Twitter"
- app_id: "YOUR_APP_ID",
- app_secret: "YOUR_APP_SECRET"
+ app_id: "<your_api_key>",
+ app_secret: "<your_api_secret>"
}
]
```
@@ -78,18 +84,20 @@ 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' }
+ app_id: '<your_api_key>',
+ app_secret: '<your_api_secret>' }
```
-1. Change 'YOUR_APP_ID' to the API key from Twitter page in step 11.
+1. Change `<your_api_key>` to the API key from the Twitter **Keys and Access Tokens** tab.
-1. Change 'YOUR_APP_SECRET' to the API secret from the Twitter page in step 11.
+1. Change `<your_api_secret>` to the API secret from the Twitter **Keys and Access Tokens** tab.
1. Save the configuration file.
-1. For the changes to take effect:
- - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
- - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
+1. For the changes to take effect, if you installed:
+
+ - Using Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - From source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
-On the sign in page there should now be a Twitter icon below the regular sign in form. Select the icon to begin the authentication process. Twitter asks the user to sign in and authorize the GitLab application. If everything goes well the user is returned to GitLab and signed in.
+On the sign-in page, find the Twitter option below the regular sign-in form. Select the option to begin the authentication process. Twitter asks you to sign in and authorize the GitLab application. After authorization,
+you are returned to GitLab and signed in.
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index f85c71a5bb3..ad807f9eb7a 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -1,137 +1,157 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vault Authentication with GitLab OpenID Connect **(FREE)**
[Vault](https://www.vaultproject.io/) is a secrets management application offered by HashiCorp.
-It allows you to store and manage sensitive information such as secret environment variables, encryption keys, and authentication tokens.
-Vault offers Identity-based Access, which means Vault users can authenticate through several of their preferred cloud providers.
+It allows you to store and manage sensitive information such as secret environment
+variables, encryption keys, and authentication tokens.
-This document explains how Vault users can authenticate themselves through GitLab by utilizing our OpenID authentication feature.
-The following assumes you already have Vault installed and running.
+Vault offers Identity-based Access, which means Vault users can authenticate
+through several of their preferred cloud providers.
-1. **Get the OpenID Connect client ID and secret from GitLab:**
+The following content explains how Vault users can authenticate themselves through
+GitLab by using our OpenID authentication feature.
- First you must create a GitLab application to obtain an application ID and secret for authenticating into Vault.
- To do this, sign in to GitLab and follow these steps:
+## Prerequisites
- 1. In the top-right corner, select your avatar.
- 1. Select **Edit profile**.
- 1. On the left sidebar, select **Applications**.
- 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
- 1. Select the **OpenID** scope.
- 1. Select **Save application**.
- 1. Copy client ID and secret, or keep the page open for reference.
+1. [Install Vault](https://www.vaultproject.io/docs/install).
+1. Run Vault.
- ![GitLab OAuth provider](img/gitlab_oauth_vault_v12_6.png)
+## Get the OpenID Connect client ID and secret from GitLab
-1. **Enable OIDC auth on Vault:**
+First you must create a GitLab application to obtain an application ID and secret
+for authenticating into Vault. To do this, sign in to GitLab and follow these steps:
- OpenID Connect is not enabled in Vault by default. This needs to be enabled in the terminal.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. On the left sidebar, select **Applications**.
+1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
+1. Select the **OpenID** scope.
+1. Select **Save application**.
+1. Copy the **Client ID** and **Client Secret**, or keep the page open for reference.
- Open a terminal session and run the following command to enable the OpenID Connect authentication provider in Vault:
+![GitLab OAuth provider](img/gitlab_oauth_vault_v12_6.png)
- ```shell
- vault auth enable oidc
- ```
+## Enable OpenID Connect on Vault
- You should see the following output in the terminal:
+OpenID Connect (OIDC) is not enabled in Vault by default.
- ```plaintext
- Success! Enabled oidc auth method at: oidc/
- ```
+To enable the OIDC authentication provider in Vault, open a terminal session
+and run the following command:
-1. **Write the OIDC configuration:**
+```shell
+vault auth enable oidc
+```
- Next, Vault needs to be given the application ID and secret generated by GitLab.
+You should see the following output in the terminal:
- In the terminal session, run the following command to give Vault access to the GitLab application you've just created with an OpenID scope. This allows Vault to authenticate through GitLab.
+```plaintext
+Success! Enabled oidc auth method at: oidc/
+```
- Replace `your_application_id` and `your_secret` in the example below with the application ID and secret generated for your app:
+## Write the OIDC configuration
- ```shell
- $ vault write auth/oidc/config \
- oidc_discovery_url="https://gitlab.com" \
- oidc_client_id="your_application_id" \
- oidc_client_secret="your_secret" \
- default_role="demo" \
- bound_issuer="localhost"
- ```
+To give Vault the application ID and secret generated by GitLab and allow
+Vault to authenticate through GitLab, run the following command in the terminal:
- You should see the following output in the terminal:
+```shell
+vault write auth/oidc/config \
+ oidc_discovery_url="https://gitlab.com" \
+ oidc_client_id="<your_application_id>" \
+ oidc_client_secret="<your_secret>" \
+ default_role="demo" \
+ bound_issuer="localhost"
+```
- ```shell
- Success! Data written to: auth/oidc/config
- ```
+Replace `<your_application_id>` and `<your_secret>` with the application ID
+and secret generated for your app.
-1. **Write the OIDC Role Configuration:**
+You should see the following output in the terminal:
- Now that Vault has a GitLab application ID and secret, it needs to know the [**Redirect URIs**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris) and scopes given to GitLab during the application creation process. The redirect URIs need to match where your Vault instance is running. The `oidc_scopes` field needs to include the `openid`. Similarly to the previous step, replace `your_application_id` with the generated application ID from GitLab:
+```shell
+Success! Data written to: auth/oidc/config
+```
- This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we show how you can access this role through the Vault CLI.
+## Write the OIDC role configuration
- WARNING:
- If you're using a public GitLab instance (GitLab.com or any other instance publicly
- accessible), it's paramount to specify the `bound_claims` to allow access only to
- members of your group/project. Otherwise, anyone with a public account can access
- your Vault instance.
+You must tell Vault the [**Redirect URIs**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris)
+and scopes given to GitLab when you created the application.
- ```shell
- vault write auth/oidc/role/demo -<<EOF
- {
- "user_claim": "sub",
- "allowed_redirect_uris": "your_vault_instance_redirect_uris",
- "bound_audiences": "your_application_id",
- "oidc_scopes": "openid",
- "role_type": "oidc",
- "policies": "demo",
- "ttl": "1h",
- "bound_claims": { "groups": ["yourGroup/yourSubgrup"] }
- }
- EOF
- ```
+Run the following command in the terminal:
+
+```shell
+vault write auth/oidc/role/demo -<<EOF
+{
+ "user_claim": "sub",
+ "allowed_redirect_uris": "<your_vault_instance_redirect_uris>",
+ "bound_audiences": "<your_application_id>",
+ "oidc_scopes": "<openid>",
+ "role_type": "oidc",
+ "policies": "demo",
+ "ttl": "1h",
+ "bound_claims": { "groups": ["<yourGroup/yourSubgrup>"] }
+}
+EOF
+```
+
+Replace:
+
+- `<your_vault_instance_redirect_uris>` with redirect URIs that match where your
+ Vault instance is running.
+- `<your_application_id>` with the application ID generated for your app.
-1. **Sign in to Vault:**
+The `oidc_scopes` field must include `openid`.
- 1. Go to your Vault UI (example: [http://127.0.0.1:8200/ui/vault/auth?with=oidc](http://127.0.0.1:8200/ui/vault/auth?with=oidc)).
- 1. If the `OIDC` method is not currently selected, open the dropdown and select it.
- 1. Select **Sign in With GitLab**, which opens a modal window:
+This configuration is saved under the name of the role you are creating. In this
+example, we are creating a `demo` role.
- ![Sign into Vault with GitLab](img/sign_into_vault_with_gitlab_v12_6.png)
+WARNING:
+If you're using a public GitLab instance, such as GitLab.com, you must specify
+the `bound_claims` to allow access only to members of your group or project.
+Otherwise, anyone with a public account can access your Vault instance.
- 1. Select **Authorize** to allow Vault to sign in through GitLab. This redirects you back to your Vault UI as a signed-in user.
+## Sign in to Vault
- ![Authorize Vault to connect with GitLab](img/authorize_vault_with_gitlab_v12_6.png)
+1. Go to your Vault UI. For example: [http://127.0.0.1:8200/ui/vault/auth?with=oidc](http://127.0.0.1:8200/ui/vault/auth?with=oidc).
+1. If the `OIDC` method is not selected, open the dropdown list and select it.
+1. Select **Sign in With GitLab**, which opens a modal window:
-1. **Sign in using the Vault CLI** (optional):
+ ![Sign into Vault with GitLab](img/sign_into_vault_with_gitlab_v12_6.png)
- Vault also allows you to sign in via their CLI.
+1. To allow Vault to sign in through GitLab, select **Authorize**. This redirects you back to your Vault UI as a signed-in user.
- After writing the same configurations from above, you can run the command below in your terminal to sign in with the role configuration created in step 4 above:
+ ![Authorize Vault to connect with GitLab](img/authorize_vault_with_gitlab_v12_6.png)
+
+## Sign in using the Vault CLI (optional)
+
+You can also sign into Vault using the [Vault CLI](https://www.vaultproject.io/docs/commands).
+
+1. To sign in with the role configuration you created in the previous example,
+ run the following command in your terminal:
```shell
vault login -method=oidc port=8250 role=demo
```
- Here's a short explanation of what this command does:
+ This command sets:
+
+ - `role=demo` so Vault knows which configuration we'd like to sign in with.
+ - `-method=oidc` to set Vault to use the `OIDC` sign-in method.
+ - `port=8250` to set the port that GitLab should redirect to. This port
+ number must match the port given to GitLab when listing
+ [Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
- 1. In the **Write the OIDC Role Configuration** (step 4), we created a role called
- `demo`. We set `role=demo` so Vault knows which configuration we'd like to
- sign in with.
- 1. To set Vault to use the `OIDC` sign-in method, we set `-method=oidc`.
- 1. To set the port that GitLab should redirect to, we set `port=8250` or
- another port number that matches the port given to GitLab when listing
- [Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
+ After running this command, you should see a link in the terminal.
- After running the command, it presents a link in the terminal.
- Select the link in the terminal and a browser tab opens that confirms you're signed into Vault via OIDC:
+1. Open this link in a web browser:
![Signed into Vault via OIDC](img/signed_into_vault_via_oidc_v12_6.png)
- The terminal outputs:
+ You should see in the terminal:
```plaintext
Success! You are now authenticated. The token information displayed below
diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md
index 19f86ae41bc..257b26dd7c4 100644
--- a/doc/legal/corporate_contributor_license_agreement.md
+++ b/doc/legal/corporate_contributor_license_agreement.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Corporate contributor license agreement
diff --git a/doc/legal/developer_certificate_of_origin.md b/doc/legal/developer_certificate_of_origin.md
index 87185284e58..5c9f7f1fed7 100644
--- a/doc/legal/developer_certificate_of_origin.md
+++ b/doc/legal/developer_certificate_of_origin.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Developer Certificate of Origin Version 1.1
diff --git a/doc/legal/index.md b/doc/legal/index.md
index 9d7b799335c..ea0301284ea 100644
--- a/doc/legal/index.md
+++ b/doc/legal/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md
index 573f535fd84..125ab1e6a8e 100644
--- a/doc/legal/individual_contributor_license_agreement.md
+++ b/doc/legal/individual_contributor_license_agreement.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Individual contributor license agreement
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 22e21c01fbd..3717eb46184 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Observability
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Error Tracking **(FREE)**
@@ -88,7 +88,7 @@ Here, you can filter errors by title or by status (one of Ignored , Resolved, or
## Error Details
-From error list, users can navigate to the error details page by clicking the title of any error.
+From error list, users can navigate to the error details page by selecting the title of any error.
This page has:
@@ -112,7 +112,7 @@ You can take action on Sentry Errors from within the GitLab UI. Marking errors i
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39665) in GitLab 12.7.
-From within the [Error Details](#error-details) page you can ignore a Sentry error by clicking the **Ignore** button near the top of the page.
+From within the [Error Details](#error-details) page you can ignore a Sentry error by selecting the **Ignore** button near the top of the page.
Ignoring an error prevents it from appearing in the [Error Tracking List](#error-tracking-list), and silences notifications that were set up within Sentry.
@@ -121,7 +121,7 @@ Ignoring an error prevents it from appearing in the [Error Tracking List](#error
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39825) in GitLab 12.7.
From within the [Error Details](#error-details) page you can resolve a Sentry error by
-clicking the **Resolve** button near the top of the page.
+selecting the **Resolve** button near the top of the page.
Marking an error as resolved indicates that the error has stopped firing events. If a GitLab issue is linked to the error, then the issue closes.
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 0dccaa6bfe9..0afba821363 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -1,24 +1,24 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Feature Flags **(FREE)**
+# Feature flags **(FREE)**
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) from GitLab Premium to GitLab Free in 13.5.
-With Feature Flags, you can deploy your application's new features to production in smaller batches.
+With feature flags, you can deploy your application's new features to production in smaller batches.
You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery.
Feature flags help reduce risk, allowing you to do controlled testing, and separate feature
delivery from customer launch.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an example of feature flags in action, see [GitLab for Deploys, Feature Flags, and Error Tracking](https://www.youtube.com/embed/5tw2p6lwXxo).
+For an example of feature flags in action, see [GitLab for deploys, feature flags, and error tracking](https://www.youtube.com/embed/5tw2p6lwXxo).
NOTE:
-The Feature Flags GitLab offer as a feature (described in this document) is not the same method
-used for the [development of GitLab](../development/feature_flags/index.md).
+To contribute to the development of the GitLab product, view
+[this feature flag content](../development/feature_flags/index.md) instead.
## How it works
@@ -43,7 +43,7 @@ To create and enable a feature flag:
1. Enter a name that starts with a letter and contains only lowercase letters, digits, underscores (`_`),
or dashes (`-`), and does not end with a dash (`-`) or underscore (`_`).
1. Optional. Enter a description (255 characters maximum).
-1. Add Feature Flag [**Strategies**](#feature-flag-strategies) to define how the flag should be applied. For each strategy, include the **Type** (defaults to [**All users**](#all-users))
+1. Add feature flag [**Strategies**](#feature-flag-strategies) to define how the flag should be applied. For each strategy, include the **Type** (defaults to [**All users**](#all-users))
and **Environments** (defaults to all environments).
1. Select **Create feature flag**.
@@ -74,9 +74,9 @@ is 200. For GitLab SaaS, the maximum number is determined by [tier](https://abou
You can apply a feature flag strategy across multiple environments, without defining
the strategy multiple times.
-GitLab Feature Flags use [Unleash](https://docs.getunleash.io/) as the feature flag
+GitLab feature flags use [Unleash](https://docs.getunleash.io/) as the feature flag
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,
+for granular feature flag controls. GitLab feature flags can have multiple strategies,
and the supported strategies are:
- [All users](#all-users)
@@ -162,7 +162,7 @@ target users. See the [Ruby example](#ruby-application-example) below.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) in GitLab 13.1.
-Enables the feature for lists of users created [in the Feature Flags UI](#create-a-user-list), or with the [Feature Flag User List API](../api/feature_flag_user_lists.md).
+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 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
@@ -294,9 +294,9 @@ Unleash currently [offers many SDKs for various languages and frameworks](https:
For API content, see:
-- [Feature Flags API](../api/feature_flags.md)
-- [Feature Flag Specs API](../api/feature_flag_specs.md) (Deprecated and [scheduled for removal](https://gitlab.com/gitlab-org/gitlab/-/issues/213369) in GitLab 14.0.)
-- [Feature Flag User Lists API](../api/feature_flag_user_lists.md)
+- [Feature flags API](../api/feature_flags.md)
+- [Feature flag specs API](../api/feature_flag_specs.md) (Deprecated and [scheduled for removal](https://gitlab.com/gitlab-org/gitlab/-/issues/213369) in GitLab 14.0.)
+- [Feature flag user lists API](../api/feature_flag_user_lists.md)
### Golang application example
@@ -395,13 +395,13 @@ docker run \
| `UNLEASH_APP_NAME` | The name of the environment the application runs in. For more details, read [Get access credentials](#get-access-credentials). |
| `UNLEASH_API_TOKEN` | Required to start the Unleash Proxy, but not used to connect to GitLab. Can be set to any value. |
-## Feature Flag Related Issues **(PREMIUM)**
+## Feature flag related issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/251234) in GitLab 13.5.
> - Showing related feature flags in issues [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220333) in GitLab 14.1.
-You can link related issues to a feature flag. In the Feature Flag **Linked issues** section,
+You can link related issues to a feature flag. In the feature flag **Linked issues** section,
select the `+` button and input the issue reference number or the full URL of the issue.
The issues then appear in the related feature flag and the other way round.
@@ -409,7 +409,7 @@ This feature is similar to the [linked issues](../user/project/issues/related_is
## Performance factors
-In general, GitLab Feature Flags can be used in any applications,
+In general, GitLab feature flags can be used in any applications,
however, if it's a large application, it could require an additional configuration in advance.
This section explains the performance factors to help your organization to identify
what's needed to be done before using the feature.
@@ -418,7 +418,7 @@ Please read [How it works](#how-it-works) section before diving into the details
### Maximum supported clients in application nodes
GitLab accepts client requests as much as possible until it hits the [rate limiting](../security/rate_limits.md).
-At the moment, the Feature Flag API falls into **Unauthenticated traffic (from a given IP address)**
+At the moment, the feature flag API falls into **Unauthenticated traffic (from a given IP address)**
in the [GitLab.com specific limits](../user/gitlab_com/index.md),
so it's **500 requests per minute**.
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index 7e4223c0820..32603aa3753 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Alerts **(FREE)**
@@ -13,7 +13,7 @@ Alerts are a critical entity in your incident management workflow. They represen
Users with at least the Developer role can
access the Alert list at **Monitor > Alerts** in your project's
sidebar. The Alert list displays alerts sorted by start time, but
-you can change the sort order by clicking the headers in the Alert list.
+you can change the sort order by selecting the headers in the Alert list.
The alert list displays the following information:
diff --git a/doc/operations/incident_management/escalation_policies.md b/doc/operations/incident_management/escalation_policies.md
index 56ff733e395..87455906b26 100644
--- a/doc/operations/incident_management/escalation_policies.md
+++ b/doc/operations/incident_management/escalation_policies.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Escalation Policies **(PREMIUM)**
diff --git a/doc/operations/incident_management/incident_timeline_events.md b/doc/operations/incident_management/incident_timeline_events.md
index 743f9b429d6..5f98335d7aa 100644
--- a/doc/operations/incident_management/incident_timeline_events.md
+++ b/doc/operations/incident_management/incident_timeline_events.md
@@ -1,16 +1,14 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Timeline events
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344059) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `incident_timeline`. Enabled by default.
-
-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 `incident_timeline`.
-On GitLab.com, this feature is available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344059) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `incident_timeline`. Enabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.3.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.5. [Feature flag 'incident_timeline'](https://gitlab.com/gitlab-org/gitlab/-/issues/343386) removed.
Incident timelines are an important part of record keeping for incidents.
Timelines can show executives and external viewers what happened during an incident,
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 2cb2e5f8045..edbe07f166c 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Incidents **(FREE)**
@@ -10,9 +10,6 @@ Incidents are critical entities in incident management workflows. They represent
a service disruption or outage that needs to be restored urgently. GitLab provides
tools for the triage, response, and remediation of incidents.
-Users with at least Guest [permissions](../../user/permissions.md) can access
-incidents [on public projects](../../user/permissions.md#project-members-permissions).
-
## Incident creation
You can create an incident manually or automatically.
@@ -86,8 +83,14 @@ confirm that a GitLab incident is created from the incident.
## Incident list
-For users with at least Guest [permissions](../../user/permissions.md), the
-Incident list is available at **Monitor > Incidents**
+Whether you can view an incident depends on the [project visibility level](../../user/public_access.md) and
+the incident's confidentiality status:
+
+- Public project and a non-confidential incident: You don't have to be a member of the project.
+- Private project and non-confidential incident: You must have at least the Guest role for the project.
+- Confidential incident (regardless of project visibility): You must have at least the Reporter.
+
+The Incident list is available at **Monitor > Incidents**
in your project's sidebar. The list contains the following metrics:
![Incident List](img/incident_list_v14_9.png)
@@ -138,10 +141,9 @@ For a live example of the incident list in action, visit this
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230847) in GitLab 13.4.
-Users with at least Guest [permissions](../../user/permissions.md) can view
-the Incident Details page. Navigate to **Monitor > Incidents** in your project's
-sidebar, and select an incident from the list.
-
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Monitor > Incidents**.
+1. Select an incident from the list.
When you take any of these actions on an incident, GitLab logs a system note and
displays it in the Incident Details view:
@@ -192,7 +194,7 @@ When you upload an image, you can associate the image with text or a link to the
![Text link modal](img/incident_metrics_tab_text_link_modal_v14_9.png)
-If you add a link, you can access the original graph by clicking the hyperlink above the uploaded image.
+If you add a link, you can access the original graph by selecting the hyperlink above the uploaded image.
### Alert details
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index 3b38d4ab427..9e66ab46692 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Incident management **(FREE)**
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 6e65fe875c5..ae6ffe549d5 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Integrations **(FREE)**
diff --git a/doc/operations/incident_management/linked_resources.md b/doc/operations/incident_management/linked_resources.md
index 3fe4a325cdb..4c3ef34f634 100644
--- a/doc/operations/incident_management/linked_resources.md
+++ b/doc/operations/incident_management/linked_resources.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Linked resources in incidents **(PREMIUM)**
@@ -50,6 +50,24 @@ To add a linked resource:
1. Complete the required fields.
1. Select **Add**.
+### Using a quick action **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/374964) in GitLab 15.5.
+
+To add multiple links to an incident, use the `/link`
+[quick action](../../user/project/quick_actions.md):
+
+```plaintext
+/link https://example.link.us/j/123456789
+```
+
+You can also submit a short description with the link.
+The description shows instead of the URL in the **Linked resources** section of the incident:
+
+```plaintext
+/link https://example.link.us/j/123456789, multiple alerts firing
+```
+
### Link Zoom meetings from an incident **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230853) in GitLab 15.4.
@@ -63,7 +81,7 @@ Use the `/zoom` [quick action](../../user/project/quick_actions.md) to add multi
You can also submit a short optional description with the link. The description shows instead of the URL in the **Linked resources** section of the incident issue:
```plaintext
-/zoom https://example.zoom.us/j/123456789, Low on memory incident
+/zoom https://example.zoom.us/j/123456789 Low on memory incident
```
## Remove a linked resource
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
index f1fb3503195..9dfac56f0ba 100644
--- a/doc/operations/incident_management/oncall_schedules.md
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# On-call Schedule Management **(PREMIUM)**
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
index 837fc9c72f5..55e1c9dfbcc 100644
--- a/doc/operations/incident_management/paging.md
+++ b/doc/operations/incident_management/paging.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Paging and notifications **(FREE)**
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index ae4d75396ae..5dd690a1c9f 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Status Page **(ULTIMATE)**
@@ -14,7 +14,7 @@ overview of recent incidents:
![Status Page landing page](img/status_page_incidents_v12_10.png)
-Clicking an incident displays a detail page with more information about a particular incident:
+Selecting an incident displays a detail page with more information about a particular incident:
![Status Page detail](img/status_page_detail_v12_10.png)
@@ -140,7 +140,7 @@ you provided during setup. As part of publication, GitLab:
- Publishes any files attached to incident issue descriptions, up to 5000 per issue.
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) in GitLab 13.1.)
-After publication, you can access the incident's details page by clicking the
+After publication, you can access the incident's details page by selecting the
**Published on status page** button displayed under the Incident's title.
![Status Page detail link](img/status_page_detail_link_v13_1.png)
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 05ce1c5d876..4f0d843f66e 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitor application performance **(FREE)**
diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 6017e2ee16c..ffd304c8897 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up alerts for Prometheus metrics **(FREE)**
diff --git a/doc/operations/metrics/dashboards/default.md b/doc/operations/metrics/dashboards/default.md
index 5c7d6440a7e..7a68e8bf3b3 100644
--- a/doc/operations/metrics/dashboards/default.md
+++ b/doc/operations/metrics/dashboards/default.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab-defined metrics dashboards (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/develop.md b/doc/operations/metrics/dashboards/develop.md
index e09f56e27cf..da5a26fbffd 100644
--- a/doc/operations/metrics/dashboards/develop.md
+++ b/doc/operations/metrics/dashboards/develop.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Developing templates for custom dashboards (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index bd1f75b7b42..4e0b50d1e04 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Custom dashboards (DEPRECATED) **(FREE)**
@@ -124,7 +124,7 @@ can manage [the settings](settings.md) for your metrics dashboard.
## Chart Context Menu
-You can take action related to a chart's data by clicking the
+You can take action related to a chart's data by selecting the
**{ellipsis_v}** **More actions** dropdown box above the upper right corner of
any chart on a dashboard:
diff --git a/doc/operations/metrics/dashboards/panel_types.md b/doc/operations/metrics/dashboards/panel_types.md
index a4cdfc5b9a0..95e8bd82475 100644
--- a/doc/operations/metrics/dashboards/panel_types.md
+++ b/doc/operations/metrics/dashboards/panel_types.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Panel types for dashboards (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index 45f0e906e9c..3fae4af9cd5 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dashboard settings (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/templating_variables.md b/doc/operations/metrics/dashboards/templating_variables.md
index 7d1754f79f5..aac22236dc7 100644
--- a/doc/operations/metrics/dashboards/templating_variables.md
+++ b/doc/operations/metrics/dashboards/templating_variables.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Templating variables for metrics dashboards (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index b796cf4cef5..5cd4dcdfa17 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using variables (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/yaml.md b/doc/operations/metrics/dashboards/yaml.md
index 62389fa01ee..399a8ecb615 100644
--- a/doc/operations/metrics/dashboards/yaml.md
+++ b/doc/operations/metrics/dashboards/yaml.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dashboard YAML properties (DEPRECATED) **(FREE)**
diff --git a/doc/operations/metrics/dashboards/yaml_number_format.md b/doc/operations/metrics/dashboards/yaml_number_format.md
index fd83bff3c08..cd597ea8783 100644
--- a/doc/operations/metrics/dashboards/yaml_number_format.md
+++ b/doc/operations/metrics/dashboards/yaml_number_format.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Unit formats reference **(FREE)**
diff --git a/doc/operations/metrics/embed.md b/doc/operations/metrics/embed.md
index 3fd5daba4fb..f622780530a 100644
--- a/doc/operations/metrics/embed.md
+++ b/doc/operations/metrics/embed.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Embedding metric charts within GitLab Flavored Markdown **(FREE)**
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 1a1ac77ce23..b307aa5fa32 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Embed Grafana panels in Markdown **(FREE)**
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 82f093cf432..3e5ea688fde 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitor your environment's metrics **(FREE)**
@@ -43,7 +43,7 @@ your Prometheus integration depends on where your apps are running:
- **For a cluster integrated Prometheus** - GitLab can query
[an in-cluster Prometheus](../../user/clusters/integrations.md#prometheus-cluster-integration).
You must also complete a code deployment to your cluster for the **Monitor > Metrics**
- page to contain data. You can do this using [Auto DevOps](../../topics/autodevops/quick_start_guide.md).
+ page to contain data. You can do this using [Auto DevOps](../../topics/autodevops/cloud_deployments/auto_devops_with_gke.md).
![Monitoring Dashboard](img/prometheus_monitoring_dashboard_v13_3.png)
@@ -147,7 +147,7 @@ suggested if this feature is used.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) in GitLab 12.9.
-You can edit existing additional custom metrics for your dashboard by clicking the
+You can edit existing additional custom metrics for your dashboard by selecting the
**{ellipsis_v}** **More actions** dropdown and selecting **Edit metric**.
![Edit metric](img/prometheus_dashboard_edit_metric_link_v_12_9.png)
diff --git a/doc/operations/product_analytics.md b/doc/operations/product_analytics.md
index e21770bc579..f9b92f61fd2 100644
--- a/doc/operations/product_analytics.md
+++ b/doc/operations/product_analytics.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Analytics
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Product Analytics **(FREE)**
diff --git a/doc/operations/tracing.md b/doc/operations/tracing.md
index 45f2febd73e..64d8f8a8707 100644
--- a/doc/operations/tracing.md
+++ b/doc/operations/tracing.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tracing (DEPRECATED) **(FREE SELF)**
diff --git a/doc/policy/alpha-beta-support.md b/doc/policy/alpha-beta-support.md
index 6b0bd66041e..8d9b1f270f3 100644
--- a/doc/policy/alpha-beta-support.md
+++ b/doc/policy/alpha-beta-support.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
<!-- any changes made to this page should be reflected in https://about.gitlab.com/support/statement-of-support/#alpha-beta-features and https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga -->
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 02a1c5a53dc..2bfc7f0243a 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts
---
@@ -107,8 +107,7 @@ In some cases, however, we may need to backport *a bug fix* to more than one sta
release, depending on the severity of the bug.
The decision on whether backporting a change is performed is done at the discretion of the
-[current release managers](https://about.gitlab.com/community/release-managers/), similar to what is
-described in the [managing bugs](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md#managing-bugs) process,
+[current release managers](https://about.gitlab.com/community/release-managers/),
based on *all* of the following:
1. Estimated [severity](../development/contributing/issue_workflow.md#severity-labels) of the bug:
diff --git a/doc/raketasks/backup_gitlab.md b/doc/raketasks/backup_gitlab.md
index 0a38416825a..da004a1b774 100644
--- a/doc/raketasks/backup_gitlab.md
+++ b/doc/raketasks/backup_gitlab.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Back up GitLab
@@ -352,8 +352,6 @@ To create an [untarred](#skipping-tar-creation) incremental backup from a tarred
sudo gitlab-backup create INCREMENTAL=yes SKIP=tar
```
-You can't create an incremental backup from an [untarred](#skipping-tar-creation) backup.
-
### Back up specific repository storages
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86896) in GitLab 15.0.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 03413aca2af..2ac79a913f3 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Back up and restore GitLab **(FREE SELF)**
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index 59d8046c8db..2fa6fc2e564 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Clean up **(FREE SELF)**
diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md
index cdc95c1f3cc..ec7f54a41c2 100644
--- a/doc/raketasks/generate_sample_prometheus_data.md
+++ b/doc/raketasks/generate_sample_prometheus_data.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Generate sample Prometheus data **(FREE SELF)**
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index 5c95fe2eca1..6e7ba45167c 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import bare repositories **(FREE SELF)**
@@ -19,7 +19,8 @@ Note that:
- Existing projects are skipped.
- Projects in hashed storage may be skipped. For more information, see
[Importing bare repositories from hashed storage](#importing-bare-repositories-from-hashed-storage).
-- The existing Git repositories ware moved from disk (removed from the original path).
+- The existing Git repositories are moved from disk (removed from the original path).
+- You must manually [push Git LFS objects](#push-git-lfs-objects).
To import bare repositories into a GitLab instance:
@@ -152,3 +153,12 @@ projects (this may take a while if there are 1000s of projects in a namespace):
namespace = Namespace.find_by_full_path('gitlab-org')
namespace.send(:write_projects_repository_config)
```
+
+## Push Git LFS objects
+
+The import task doesn't import Git LFS objects. You must manually push the LFS objects to the newly
+created GitLab repository using the following command:
+
+```shell
+git lfs push --all
+```
diff --git a/doc/raketasks/index.md b/doc/raketasks/index.md
index c2580e26ff0..12d2d8b101a 100644
--- a/doc/raketasks/index.md
+++ b/doc/raketasks/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/raketasks/list_repos.md b/doc/raketasks/list_repos.md
index 4b971c3608f..57d24a2942d 100644
--- a/doc/raketasks/list_repos.md
+++ b/doc/raketasks/list_repos.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Listing repository directories **(FREE SELF)**
diff --git a/doc/raketasks/migrate_snippets.md b/doc/raketasks/migrate_snippets.md
index c36009e69d0..62d2866e499 100644
--- a/doc/raketasks/migrate_snippets.md
+++ b/doc/raketasks/migrate_snippets.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migration to versioned snippets **(FREE SELF)**
diff --git a/doc/raketasks/restore_gitlab.md b/doc/raketasks/restore_gitlab.md
index 7b3a60b436c..61198a3d9ca 100644
--- a/doc/raketasks/restore_gitlab.md
+++ b/doc/raketasks/restore_gitlab.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Restore GitLab
@@ -17,7 +17,7 @@ You can restore a backup only to _the exact same version and type (CE/EE)_ of
GitLab that you created it on (for example CE 9.1.0).
If your backup is a different version than the current installation, you must
-[downgrade your GitLab installation](../update/package/downgrade.md)
+[downgrade](../update/package/downgrade.md) or [upgrade](../update/package/index.md#upgrade-to-a-specific-version-using-the-official-repositories) your GitLab installation
before restoring the backup.
## Restore prerequisites
diff --git a/doc/raketasks/spdx.md b/doc/raketasks/spdx.md
index 81da52bc327..31f860f45de 100644
--- a/doc/raketasks/spdx.md
+++ b/doc/raketasks/spdx.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SPDX license list import **(ULTIMATE SELF)**
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 02c76af1e69..84d943e2c21 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# User management **(FREE SELF)**
@@ -87,7 +87,7 @@ block_auto_created_users: false
This task disables two-factor authentication (2FA) for all users that have it enabled. This can be
useful if the GitLab `config/secrets.yml` file has been lost and users are unable
-to log in, for example.
+to sign in, for example.
To disable two-factor authentication for all users, run:
diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
index 44ca4a3f47e..b4d01d21dc7 100644
--- a/doc/raketasks/web_hooks.md
+++ b/doc/raketasks/web_hooks.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Webhooks administration **(FREE SELF)**
diff --git a/doc/raketasks/x509_signatures.md b/doc/raketasks/x509_signatures.md
index 5090fc285cc..3404f6ae9cf 100644
--- a/doc/raketasks/x509_signatures.md
+++ b/doc/raketasks/x509_signatures.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# X.509 signatures **(FREE SELF)**
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index 1ccc9bfd9be..cde377cbb73 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Proxying assets **(FREE SELF)**
@@ -11,7 +11,7 @@ the ability to steal a user's IP address by referencing images in issues and com
For example, adding `![Example image](http://example.com/example.png)` to
an issue description causes the image to be loaded from the external
-server in order to be displayed. However, this also allows the external server
+server to be displayed. However, this also allows the external server
to log the IP address of the user.
One way to mitigate this is by proxying any external images to a server you
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 5a6578f218b..e2aa4b5d4ab 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/security/index.md b/doc/security/index.md
index 9e05621333b..ff0769e0d93 100644
--- a/doc/security/index.md
+++ b/doc/security/index.md
@@ -1,14 +1,14 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
type: index
---
# Security **(FREE)**
-- [Password storage](password_storage.md)
+- [Passwords and OAuth tokens storage](password_storage.md)
- [Password length limits](password_length_limits.md)
- [Generated passwords for users created through integrated authentication](passwords_for_integrated_authentication_methods.md)
- [Restrict SSH key technologies and minimum length](ssh_keys_restrictions.md)
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 2eeb436316f..37a9fdfdd81 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts
---
diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md
index 57466d1ed5d..fe51022eea7 100644
--- a/doc/security/password_length_limits.md
+++ b/doc/security/password_length_limits.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/security/password_storage.md b/doc/security/password_storage.md
index d3db8cbe4f6..6b20f8619ae 100644
--- a/doc/security/password_storage.md
+++ b/doc/security/password_storage.md
@@ -1,11 +1,15 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
-# Password storage **(FREE)**
+# Password and OAuth token storage **(FREE)**
+
+GitLab administrators can configure how passwords and OAuth tokens are stored.
+
+## Password storage
> PBKDF2 and SHA512 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/360658) in GitLab 15.2 [with flags](../administration/feature_flags.md) named `pbkdf2_password_encryption` and `pbkdf2_password_encryption_write`. Disabled by default.
@@ -17,8 +21,8 @@ library to hash user passwords. Created password hashes have these attributes:
- **Hashing**:
- **BCrypt**: By default, the [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt) hashing
- function is used to generate the hash of the provided password. This is a
- strong, industry-standard cryptographic hashing function.
+ function is used to generate the hash of the provided password. This cryptographic hashing function is
+ strong and industry-standard.
- **PBKDF2 and SHA512**: Starting in GitLab 15.2, PBKDF2 and SHA512 are supported
behind the following feature flags (disabled by default):
- `pbkdf2_password_encryption` - Enables reading and comparison of PBKDF2 + SHA512
@@ -37,3 +41,13 @@ library to hash user passwords. Created password hashes have these attributes:
is added to each password to harden against pre-computed hash and dictionary
attacks. To increase security, each salt is randomly generated for each
password, with no two passwords sharing a salt.
+
+## OAuth access token storage
+
+> - PBKDF2+SHA512 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364110) in GitLab 15.3 [with flag](../administration/feature_flags.md) named `hash_oauth_tokens`.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98242) in GitLab 15.5.
+
+Depending on your version of GitLab and configuration, OAuth access tokens are stored in the database in PBKDF2+SHA512 format. For version information, see
+the relevant [OAuth provider documentation](../integration/oauth_provider.md#hashed-oauth-tokens).
+
+As with PBKDF2+SHA512 password storage, access token values are [stretched](https://en.wikipedia.org/wiki/Key_stretching) 20,000 times to harden against brute-force attacks.
diff --git a/doc/security/passwords_for_integrated_authentication_methods.md b/doc/security/passwords_for_integrated_authentication_methods.md
index d4eb16c07e7..961d147871e 100644
--- a/doc/security/passwords_for_integrated_authentication_methods.md
+++ b/doc/security/passwords_for_integrated_authentication_methods.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/security/project_import_decompressed_archive_size_limits.md b/doc/security/project_import_decompressed_archive_size_limits.md
index 5082d917748..4358e0a5566 100644
--- a/doc/security/project_import_decompressed_archive_size_limits.md
+++ b/doc/security/project_import_decompressed_archive_size_limits.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index e48a9999a06..20a81ed0c30 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index 992a8585a47..248737fc908 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -14,6 +14,8 @@ You can reset user passwords by using a Rake task, a Rails console, or the
To reset a user password, you must be an administrator of a self-managed GitLab instance.
+The user's new password must meet all [password requirements](../user/profile/user_passwords.md#password-requirements).
+
## Use a Rake task
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52347) in GitLab 13.9.
@@ -120,6 +122,11 @@ To reset the root password, follow the steps listed previously.
## Troubleshooting
+Use the following information to troubleshoot issues when resetting a
+user's password.
+
+### Email confirmation issues
+
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:
@@ -132,3 +139,9 @@ attempt to fix this issue in a Rails console. For example, if a new `root` passw
```
1. Attempt to sign in again.
+
+### Unmet password requirements
+
+The password might be too short, too weak, or not meet complexity
+requirements. Ensure the password you are attempting to set meets all
+[password requirements](../user/profile/user_passwords.md#password-requirements).
diff --git a/doc/security/responding_to_security_incidents.md b/doc/security/responding_to_security_incidents.md
index b3bce785695..fb35c389583 100644
--- a/doc/security/responding_to_security_incidents.md
+++ b/doc/security/responding_to_security_incidents.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index 138ebb9858a..5a8450bb8e7 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Restrict allowed SSH key technologies and minimum length **(FREE SELF)**
diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md
index e585f2caeca..0c9734cad36 100644
--- a/doc/security/token_overview.md
+++ b/doc/security/token_overview.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -129,7 +129,7 @@ This table shows available scopes per token. Scopes can be limited further on to
also generally logged by proxies and application servers, which makes those credentials visible to system administrators. Instead, pass API calls an access token using
headers like [the `Private-Token` header](../api/index.md#personalprojectgroup-access-tokens).
- Tokens can also be stored using a [Git credential storage](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
-- Tokens should not be committed to your source code. Instead, consider an approach such as [using external secrets in CI](../ci/secrets/index.md).
+- Tokens must not be committed to your source code. Instead, consider an approach such as [using external secrets in CI](../ci/secrets/index.md).
- When creating a scoped token, consider using the most limited scope possible to reduce the impact of accidentally leaking the token.
- When creating a token, consider setting a token that expires when your task is complete. For example, if performing a one-off import, set the
token to expire after a few hours or a day. This reduces the impact of a token that is accidentally leaked because it is useless when it expires.
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index c808cf4e321..cc06e824d14 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Enforce two-factor authentication **(FREE)**
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index 041527f18af..4eded22ddaa 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -56,7 +56,7 @@ To unlock a locked user:
1. Exit the console with <kbd>Control</kbd>+<kbd>d</kbd>
-The user should now be able to log in.
+The user should now be able to sign in.
<!-- ## Troubleshooting
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index 172e26db618..3f7c66b311b 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# User email confirmation at sign-up **(FREE SELF)**
diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md
index ddb8392d2be..63a5e51e3b5 100644
--- a/doc/security/user_file_uploads.md
+++ b/doc/security/user_file_uploads.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# User file uploads **(FREE)**
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index e1daa705355..49ab4215ea5 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, reference, howto
---
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index 62e045a7593..ec932f2384b 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Purchase
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Features available to Starter and Bronze subscribers
@@ -82,8 +82,7 @@ the tiers are no longer mentioned in GitLab documentation:
- Rake tasks:
- [Displaying GitLab license information](../administration/raketasks/maintenance.md#show-gitlab-license-information)
- Reference Architecture information:
- - [Traffic load balancers](../administration/reference_architectures/index.md#traffic-load-balancer)
- - [Zero downtime updates](../administration/reference_architectures/index.md#zero-downtime-updates)
+ - [Zero downtime upgrades](../administration/reference_architectures/index.md#zero-downtime-upgrades)
- Repositories:
- [Repository size limit](../user/admin_area/settings/account_and_limit_settings.md#repository-size-limit)
- Repository mirroring:
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index aed8bafb780..c9b066144f3 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Purchase
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -259,12 +259,12 @@ generated for the renewal and available for viewing or download on the
#### Enable or disable automatic subscription renewal
To view or change automatic subscription renewal (at the same tier as the
-previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
+previous period), sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
- If a **Resume subscription** button is displayed, your subscription was canceled
- previously. Click it to resume automatic renewal.
+ previously. Select it to resume automatic renewal.
- If a **Cancel subscription** button is displayed, your subscription is set to automatically
- renew at the end of the subscription period. Click it to cancel automatic renewal.
+ renew at the end of the subscription period. Select it to cancel automatic renewal.
If you have difficulty during the renewal process, contact the
[Support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md
index e5f75fd5a7a..441a4d2aa30 100644
--- a/doc/subscriptions/gitlab_dedicated/index.md
+++ b/doc/subscriptions/gitlab_dedicated/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Dedicated
@@ -18,7 +18,8 @@ GitLab Dedicated enables you to offload the operational overhead of managing the
## Available features
-- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#general-setup) in order for GitLab to communicate with your IdP. This is provided during onboarding. SAML [request signing](../../integration/saml.md#request-signing-optional) is supported.
+- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#general-setup) in order for GitLab to communicate with your IdP. This is provided during onboarding.
+ - SAML [request signing](../../integration/saml.md#request-signing-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#saml-groups) are supported.
- Networking:
- Public connectivity with support for IP Allowlists. During onboarding, you can optionally specify a list of IP addresses that can access your Dedicated instance. Subsequently, when an IP not on the allowlist tries to access your instance the connection will be refused.
- Optional. Private connectivity via [AWS PrivateLink](https://aws.amazon.com/privatelink/).
@@ -26,41 +27,59 @@ GitLab Dedicated enables you to offload the operational overhead of managing the
- Upgrades:
- Monthly upgrades tracking one release behind the latest (n-1), with the latest security release.
- Out of band security patches provided for high severity releases.
-- Backups: regular backups taken and tested.
-- Choice of cloud region: upon onboarding, choose the cloud region where you want to deploy your instance. Some AWS regions have limited features and as a result, we are not able to deploy production instances to those regions. See below for the [full list of regions](#aws-regions-not-supported) not currently supported.
+- Backups: Regular backups taken and tested.
+- Choice of cloud region: Upon onboarding, choose the cloud region where you want to deploy your instance. Some AWS regions have limited features and as a result, we are not able to deploy production instances to those regions. See below for the [full list of regions](#aws-regions-not-supported) not currently supported.
- Security: Data encrypted at rest and in transit using latest encryption standards.
-- Application: Self-managed [Ultimate feature set](https://about.gitlab.com/pricing/self-managed/feature-comparison/) with the exception of the unsupported features [listed below](#features-not-available-at-launch).
+- Application: Self-managed [Ultimate feature set](https://about.gitlab.com/pricing/self-managed/feature-comparison/) with the exception of the unsupported features [listed below](#features-that-are-not-available).
-## Features not available at launch
+## Features that are not available
-Features that are not available but we plan to support in the future:
+### GitLab application features
-- LDAP, Smartcard, Kerberos authentication
-- Custom domain
+The following GitLab application features are not available:
+
+- LDAP, Smartcard, or Kerberos authentication
+- Multiple login providers
- Advanced Search
-- Pages
-- GitLab-managed runners
-- FortiAuthenticator/FortiToken 2FA
+- GitLab Pages
+- FortiAuthenticator, or FortiToken 2FA
- Reply-by email
- Service Desk
+- GitLab-managed runners
+- Any feature [not listed above](#available-features) which must be configured outside of the GitLab user interface.
-Features that we do not plan to offer at all:
+The following features will not be supported:
- Mattermost
-- Server-side Git Hooks
+- Server-side Git hooks
+
+### Dedicated service features
+
+The following operational features are not available:
+
+- Custom domains
+- Bring Your Own Key (BYOK) encryption
+- Multiple Geo secondaries (Geo replicas) beyond the secondary site included by default
+- Self-serve purchasing and configuration
+- Multiple login providers
+- Non-AWS cloud providers, such as GCP or Azure
### AWS regions not supported
-The following AWS regions are not available at launch:
+The following AWS regions are not available:
-- Jakarta (ap-southeast-3)
-- Bahrain (me-south-1)
-- Hong Kong (ap-east-1)
-- Cape Town (af-south-1)
-- Milan (eu-south-1)
-- Paris (eu-west-3)
+- Jakarta (`ap-southeast-3`)
+- Bahrain (`me-south-1`)
+- Hong Kong (`ap-east-1`)
+- Cape Town (`af-south-1`)
+- Milan (`eu-south-1`)
+- Paris (`eu-west-3`)
- GovCloud
+## Planned features
+
+Learn more about the planned improvements to Dedicated on the public [direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/).
+
## Contact us
Fill in the following form to contact us and learn more about this offering.
diff --git a/doc/subscriptions/img/support_diagram_c.png b/doc/subscriptions/img/support_diagram_c.png
deleted file mode 100644
index e98baed8605..00000000000
--- a/doc/subscriptions/img/support_diagram_c.png
+++ /dev/null
Binary files differ
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index e71954f1968..1df222ac349 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Purchase
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -46,10 +46,7 @@ A new subscription must be purchased and applied as needed.
Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
the features which fit your budget. For information on what features are available
-at each tier for each product, see:
-
-- [GitLab SaaS feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)
-- [GitLab self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/)
+at each tier for each product, see: [GitLab self-managed feature comparison](https://about.gitlab.com/pricing/feature-comparison/)
## Find your subscription
@@ -73,26 +70,30 @@ click E "./self_managed/index.html#view-your-subscription"
With the [Customers Portal](https://customers.gitlab.com/) you can:
-- [Change your personal details](#change-your-personal-details)
+- [Change account owner information](#change-account-owner-information)
- [Change your company details](#change-your-company-details)
- [Change your payment method](#change-your-payment-method)
- [Change the linked account](#change-the-linked-account)
- [Change the namespace the subscription is linked to](#change-the-linked-namespace)
- [Change customers portal account password](#change-customers-portal-account-password)
-### Change your personal details
+### Change account owner information
-Your personal details are used on invoices. Your email address is used for the Customers Portal
-login and license-related email.
+Account owner personal details are used on invoices. The account owner email
+address is used for the Customers Portal login and license-related email.
-To change your personal details, including name, billing address, and email address:
+To change account owner information, including name, billing address, and email address:
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
1. Select **My account > Account details**.
1. Expand the **Personal details** section.
-1. Edit your personal details.
+1. Edit the personal details.
1. Select **Save changes**.
+If you want to transfer ownership of the Customers Portal account
+to another person, after you enter that person's personal details, you must also
+[change the Customers Portal account password](#change-customers-portal-account-password).
+
### Change your company details
To change your company details, including company name and VAT number:
@@ -138,7 +139,7 @@ To change the GitLab.com account linked to your Customers Portal account:
1. In a separate browser tab, go to [GitLab SaaS](https://gitlab.com) and ensure you
are not logged in.
1. On the Customers Portal page, select **My account > Account details**.
-1. Under **Your GitLab.com account**, select **Change linked account**.
+1. Under **Your GitLab.com account**, select **Change linked account**. If the account is not yet linked, select **Link my GitLab.com account**.
1. Log in to the [GitLab SaaS](https://gitlab.com) account you want to link to the Customers Portal
account.
@@ -164,7 +165,7 @@ Only one namespace can be linked to a subscription.
To change the password for this customers portal account:
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
-1. Select the **My account** drop-down and select **Account details**.
+1. Select the **My account** dropdown list and select **Account details**.
1. Make the required changes to the **Your password** section.
1. Select **Save changes**.
@@ -172,42 +173,36 @@ To change the password for this customers portal account:
### GitLab for Education
-For qualifying non-profit educational institutions, the [GitLab for Education](https://about.gitlab.com/solutions/education/) program provides
-the top GitLab tier, plus 50,000 CI/CD minutes per month.
-
-The GitLab for Education license can only be used for instructional-use or
-non-commercial academic research.
-
-Find more information on how to apply and renew at
-[GitLab for Education](https://about.gitlab.com/solutions/education/).
+For qualifying non-profit educational institutions, the [GitLab for Education Program](https://about.gitlab.com/solutions/education/) provides GitLab Ultimate, plus 50,000 CI/CD minutes per month. The subscription granted under GitLab for Education can only be used for instructional use or non-commercial academic research. For more information—including instructions for applying to the program and renewing program membership—see the [GitLab for Education Program page](https://about.gitlab.com/solutions/education/) and the [GitLab handbook](https://about.gitlab.com/handbook/marketing/community-relations/community-programs/education-program/).
### GitLab for Open Source
-For qualifying open source projects, the [GitLab for Open Source Program](https://about.gitlab.com/solutions/open-source/) provides
-GitLab Ultimate, plus 50,000 CI/CD minutes per month. For more information, see [program requirements](https://about.gitlab.com/solutions/open-source/join/#requirements), [renewals](https://about.gitlab.com/solutions/open-source/join/#renewals), and [program benefits](https://about.gitlab.com/solutions/open-source/join/).
+For qualifying open source projects, the [GitLab for Open Source Program](https://about.gitlab.com/solutions/open-source/) provides GitLab Ultimate, plus 50,000 CI/CD minutes per month. For more information—including instructions for applying to the program and renewing program membership—see the [GitLab for Open Source Program page](https://about.gitlab.com/solutions/open-source/) and the [GitLab handbook](https://about.gitlab.com/handbook/marketing/community-relations/opensource-program/).
-If you have any questions, send an email to `opensource@gitlab.com` for assistance.
+#### Meeting GitLab for Open Source Program requirements
-#### License requirements for GitLab for Open Source Program members
+NOTE:
+GitLab for Open Source Program benefits apply to an entire GitLab namespace. To qualify for the GitLab for Open Source Program, all projects in an applicant's namespace must meet program requirements. Applicants submit materials related to one project in the applying namespace, and the open source program team uses that project to verify eligibility of the entire namespace.
-GitLab for Open Source Program benefits apply to an entire GitLab namespace. To qualify for the GitLab for Open Source Program, **all projects in an applicant's namespace** must carry an [OSI-approved license](https://opensource.org/licenses/).
+To meet GitLab for Open Source Program requirements, first add an OSI-approved open source license to all projects in your namespace.
-To add a license:
+To add a license to a project:
1. On the top bar, select **Main menu > Projects** and find your project.
1. On the overview page, select **Add LICENSE**. If the license you want is not available as a license template, manually copy the entire, unaltered [text of your chosen license](https://opensource.org/licenses/alphabetical) into the `LICENSE` file. Note that GitLab defaults to **All rights reserved** if users do not perform this action.
-Applicants must add the correct license to each project in their respective groups or namespaces When you're sure you're using OSI-approved licenses for your projects, you can take your screenshots.
+Applicants must add the correct license to each project in their respective groups or namespaces. When you're sure you're using OSI-approved licenses for your projects, you can take your screenshots.
#### Verification for Open Source Program
-As part of the [application verification process](https://about.gitlab.com/solutions/open-source/join/), you must upload **three screenshots**:
+Next, take screenshots of your project to confirm that project's eligibility. You must upload three screenshots:
- [OSI-approved license overview](#screenshot-1-license-overview)
- [OSI-approved license contents](#screenshot-2-license-contents)
- [Publicly visible settings](#screenshot-3-publicly-visible-settings)
-Benefits of the GitLab Open Source Program apply to all projects in a GitLab namespace. All projects in an eligible namespace must meet program requirements. However, if you submit materials for **one project** in your namespace, the open source program team uses that project to verify the contents of the entire namespace you use when applying to the program.
+NOTE:
+Benefits of the GitLab Open Source Program apply to all projects in a GitLab namespace. All projects in an eligible namespace must meet program requirements.
##### Screenshot 1: License overview
@@ -239,24 +234,11 @@ To be eligible for the GitLab Open Source Program, projects must be publicly vis
![Publicly visible setting](img/publicly-visible.png)
NOTE:
-Exceptions to this public visibility requirement apply in select circumstances (for example, in cases where a project may hold sensitive data). Email `opensource@gitlab.com` with details of your use case to request written permission for exceptions.
+Exceptions to this public visibility requirement apply in select circumstances (for example, in cases where a project in an applicant's namespace may hold sensitive data). Email `opensource@gitlab.com` with details of your use case to request written permission for exceptions.
### GitLab for Startups
-For qualifying startups, the [GitLab for Startups](https://about.gitlab.com/solutions/startups/) program provides
-the top GitLab tier, plus 50,000 CI/CD minutes per month for 12 months.
-
-For more information, including program requirements, see the [Startup program's landing page](https://about.gitlab.com/solutions/startups/).
-
-Send all questions and requests related to the GitLab for Startups program to `startups@gitlab.com`.
-
-### Support for Community Programs
-
-Because these Community Programs are free of cost, regular Priority Support is not included.
-
-As a community member, you can follow this diagram to find support:
-
-![Support diagram](img/support_diagram_c.png)
+For qualifying startups, the [GitLab for Startups](https://about.gitlab.com/solutions/startups/) program provides GitLab Ultimate, plus 50,000 CI/CD minutes per month for 12 months. For more information—including instructions for applying to the program and renewing program membership—see the [GitLab for Startups Program page](https://about.gitlab.com/solutions/startups/) and the [GitLab handbook](https://about.gitlab.com/handbook/marketing/community-relations/startups-program/).
## Contact Support
@@ -265,12 +247,9 @@ Learn more about:
- The tiers of [GitLab Support](https://about.gitlab.com/support/).
- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
-We also encourage all users to search our project trackers for known issues and
-existing feature requests in the
-[GitLab project](https://gitlab.com/gitlab-org/gitlab/-/issues/).
+We also encourage all users to search our project trackers for known issues and existing feature requests in the [GitLab project](https://gitlab.com/gitlab-org/gitlab/-/issues/).
-These issues are the best avenue for getting updates on specific product plans
-and for communicating directly with the relevant GitLab team members.
+These issues are the best avenue for getting updates on specific product plans and for communicating directly with the relevant GitLab team members.
<!-- ## Troubleshooting
diff --git a/doc/subscriptions/quarterly_reconciliation.md b/doc/subscriptions/quarterly_reconciliation.md
index 78c844b897c..508dd2924e3 100644
--- a/doc/subscriptions/quarterly_reconciliation.md
+++ b/doc/subscriptions/quarterly_reconciliation.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Purchase
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Quarterly reconciliation and annual true-ups **(PREMIUM)**
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 4ae38de54bc..4538e8587c9 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Purchase
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -261,7 +261,7 @@ It also displays the following information:
## Export your license usage
-> Introduced in GitLab 14.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66826) in GitLab 14.2.
If you are an administrator, you can export your license usage into a CSV:
@@ -300,7 +300,7 @@ then [renew your GitLab self-managed subscription](#renew-a-subscription).
The [Customers Portal](https://customers.gitlab.com/customers/sign_in) is your
tool for renewing and modifying your subscription. Before going ahead with renewal,
-log in and verify or update:
+sign in and verify or update:
- The invoice contact details on the **Account details** page.
- The credit card on file on the **Payment Methods** page.
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index ef7598248fe..12ff5cb50b8 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Authentication **(FREE)**
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_ec2.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_ec2.md
index 653fe11c59d..6bebe9eb9e3 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_ec2.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_ec2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use Auto DevOps to deploy to EC2
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_ecs.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_ecs.md
index 4c084f405cd..76fd6ad82d8 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_ecs.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_ecs.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use Auto DevOps to deploy to Amazon ECS
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
index 5f37ca30604..56f3de528b8 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use Auto DevOps to deploy an application to Google Kubernetes Engine **(FREE)**
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 4d97f012a92..0d4afc3c464 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customizing Auto DevOps **(FREE)**
@@ -190,7 +190,7 @@ You can override the default values in the `values.yaml` file in the
`HELM_UPGRADE_VALUES_FILE` [CI/CD variable](#cicd-variables) with
the path and name.
-Some values can not be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
+Some values cannot be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
[build and deployment](#build-and-deployment) CI/CD variable. Follow [this issue](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/31) for more information.
NOTE:
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index c21ed5ed444..73e87aa190f 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Auto DevOps **(FREE)**
@@ -26,36 +26,24 @@ For an introduction to Auto DevOps, watch [Auto DevOps in GitLab 11.0](https://y
## Auto DevOps features
-Based on the DevOps [stages](stages.md), use Auto DevOps to:
-
-**Build your app:**
-
-- [Auto Build](stages.md#auto-build)
-- [Auto Dependency Scanning](stages.md#auto-dependency-scanning)
-
-**Test your app:**
-
-- [Auto Test](stages.md#auto-test)
-- [Auto Browser Performance Testing](stages.md#auto-browser-performance-testing)
-- [Auto Code Intelligence](stages.md#auto-code-intelligence)
-- [Auto Code Quality](stages.md#auto-code-quality)
-- [Auto Container Scanning](stages.md#auto-container-scanning)
-- [Auto License Compliance](stages.md#auto-license-compliance)
-
-**Deploy your app:**
-
-- [Auto Review Apps](stages.md#auto-review-apps)
-- [Auto Deploy](stages.md#auto-deploy)
-
-**Monitor your app:**
-
-- [Auto Monitoring](stages.md#auto-monitoring)
-
-**Secure your app:**
-
-- [Auto Dynamic Application Security Testing (DAST)](stages.md#auto-dast)
-- [Auto Static Application Security Testing (SAST)](stages.md#auto-sast)
-- [Auto Secret Detection](stages.md#auto-secret-detection)
+Auto DevOps supports development during each of the [DevOps stages](stages.md).
+
+| Stage | Auto DevOps feature |
+|---------|-------------|
+| Build | [Auto Build](stages.md#auto-build) |
+| Build | [Auto Dependency Scanning](stages.md#auto-dependency-scanning) |
+| Test | [Auto Test](stages.md#auto-test) |
+| Test | [Auto Browser Performance Testing](stages.md#auto-browser-performance-testing) |
+| Test | [Auto Code Intelligence](stages.md#auto-code-intelligence) |
+| Test | [Auto Code Quality](stages.md#auto-code-quality) |
+| Test | [Auto Container Scanning](stages.md#auto-container-scanning) |
+| Test | [Auto License Compliance](stages.md#auto-license-compliance) |
+| Deploy | [Auto Review Apps](stages.md#auto-review-apps) |
+| Deploy | [Auto Deploy](stages.md#auto-deploy) |
+| Monitor | [Auto Monitoring](stages.md#auto-monitoring) |
+| Secure | [Auto Dynamic Application Security Testing (DAST)](stages.md#auto-dast) |
+| Secure | [Auto Static Application Security Testing (SAST)](stages.md#auto-sast) |
+| Secure | [Auto Secret Detection](stages.md#auto-secret-detection) |
### Comparison to application platforms and PaaS
@@ -80,24 +68,12 @@ If you want to build, test, and deploy your app:
1. View the [requirements for deployment](requirements.md).
1. [Enable Auto DevOps](#enable-or-disable-auto-devops).
-1. Follow the [quick start guide](#quick-start).
-
-As Auto DevOps relies on many components, be familiar with:
-
-- [Continuous methodologies](../../ci/introduction/index.md)
-- [Docker](https://docs.docker.com)
-- [GitLab Runner](https://docs.gitlab.com/runner/)
-
-When deploying to a Kubernetes cluster make sure you're also familiar with:
-
-- [Kubernetes](https://kubernetes.io/docs/home/)
-- [Helm](https://helm.sh/docs/)
-- [Prometheus](https://prometheus.io/docs/introduction/overview/)
+1. [Deploy your app to a cloud provider](#deploy-your-app-to-a-cloud-provider).
### Enable or disable Auto DevOps
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41729) in GitLab 11.3, Auto DevOps is enabled by default.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26655) GitLab 12.7, Auto DevOps runs pipelines automatically only if a [`Dockerfile` or matching buildpack](stages.md#auto-build) exists.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26655) in GitLab 12.7, Auto DevOps runs pipelines automatically only if a [`Dockerfile` or matching buildpack](stages.md#auto-build) exists.
Depending on your instance type, you can enable or disable Auto DevOps at the
following levels:
@@ -116,7 +92,7 @@ To use Auto DevOps for individual projects, you can enable it in a
project-by-project basis. If you intend to use it for more projects,
you can enable it for a [group](#at-the-group-level) or an
[instance](#at-the-instance-level). This can save you the time of
-enabling it one by one.
+enabling it in each project.
Prerequisites:
@@ -143,9 +119,10 @@ To disable it, follow the same process and clear the
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52447) in GitLab 11.10.
-When you enable Auto DevOps at group level, the subgroups and projects in that
-group inherit the configuration. This saves you some time by batch-enabling it
-rather than enabling individually for each subgroup or project.
+When you enable Auto DevOps at the group level, the subgroups and
+projects in that group inherit the configuration. You can save time by
+enabling Auto DevOps for a group instead of enabling it for each
+subgroup or project.
When enabled for a group, you can still disable Auto DevOps
for the subgroups and projects where you don't want to use it.
@@ -162,7 +139,7 @@ To enable Auto DevOps for a group:
1. Select the **Default to Auto DevOps pipeline** checkbox.
1. Select **Save changes**.
-To disable Auto DevOps on the group level, follow the same process and
+To disable Auto DevOps at the group level, follow the same process and
clear the **Default to Auto DevOps pipeline** checkbox.
After enabling Auto DevOps at the group level, you can trigger the
@@ -175,10 +152,9 @@ Auto DevOps pipeline for any project that belongs to that group:
#### At the instance level **(FREE SELF)**
-By enabling Auto DevOps in the instance level, all projects created in that
-instance become enabled. This is convenient when you want to run Auto DevOps by
-default for all projects. You can still disable Auto DevOps individually for
-the groups and projects where you don't want to run it.
+To enable Auto DevOps by default for all projects, you can enable it at the instance level.
+You can still disable Auto DevOps for each group and project
+where you don't want to run it.
Even when disabled for an instance, group Owners and project Maintainers
can still enable Auto DevOps at the group and project levels.
@@ -196,24 +172,17 @@ To enable Auto DevOps for your instance:
1. Optional. Add the Auto DevOps [base domain](requirements.md#auto-devops-base-domain).
1. Select **Save changes**.
-When enabled, it attempts to run Auto DevOps pipelines in every project. If the
+When enabled, Auto DevOps attempts to run pipelines in every project. If the
pipeline fails in a particular project, it disables itself.
GitLab administrators can change this in the [Auto DevOps settings](../../user/admin_area/settings/continuous_integration.md#auto-devops).
If a [CI/CD configuration file](../../ci/yaml/index.md) is present,
-it remains unchanged and Auto DevOps doesn't affect it.
+it remains unchanged and Auto DevOps does not affect it.
To disable Auto DevOps in the instance level, follow the same process
and clear the **Default to Auto DevOps pipeline** checkbox.
-### Private registry support
-
-There is no guarantee that you can use a private container registry with Auto DevOps.
-
-Instead, use the [GitLab Container Registry](../../user/packages/container_registry/index.md) with Auto DevOps to
-simplify configuration and prevent any unforeseen issues.
-
-### Quick start
+### Deploy your app to a cloud provider
- [Use Auto DevOps to deploy to a Kubernetes cluster on Google Kubernetes Engine (GKE)](cloud_deployments/auto_devops_with_gke.md)
- [Use Auto DevOps to deploy to EC2](cloud_deployments/auto_devops_with_ec2.md)
@@ -221,7 +190,7 @@ simplify configuration and prevent any unforeseen issues.
## Upgrade Auto DevOps dependencies when updating GitLab
-When updating GitLab, you may need to upgrade Auto DevOps dependencies to
+When updating GitLab, you might need to upgrade Auto DevOps dependencies to
match your new GitLab version:
- [Upgrading Auto DevOps resources](upgrading_auto_deploy_dependencies.md):
@@ -233,30 +202,29 @@ match your new GitLab version:
- Environment variables.
- [Upgrading PostgreSQL](upgrading_postgresql.md).
+## Private registry support
+
+There is no guarantee that you can use a private container registry with Auto DevOps.
+
+Instead, use the [GitLab Container Registry](../../user/packages/container_registry/index.md) with Auto DevOps to
+simplify configuration and prevent any unforeseen issues.
+
## Install applications behind a proxy
The GitLab integration with Helm does not support installing applications when
behind a proxy.
-To do so, inject proxy settings into the installation pods at runtime.
-For example, you can use a `PodPreset`:
-
-NOTE:
-[PodPreset was removed in Kubernetes v1.20](https://github.com/kubernetes/kubernetes/pull/94090).
-
-```yaml
-apiVersion: settings.k8s.io/v1alpha1
-kind: PodPreset
-metadata:
- name: gitlab-managed-apps-default-proxy
- namespace: gitlab-managed-apps
-spec:
- env:
- - name: http_proxy
- value: "PUT_YOUR_HTTP_PROXY_HERE"
- - name: https_proxy
- value: "PUT_YOUR_HTTPS_PROXY_HERE"
-```
+If you want to do so, you must inject proxy settings into the
+installation pods at runtime.
+
+## Related topics
+
+- [Continuous methodologies](../../ci/introduction/index.md)
+- [Docker](https://docs.docker.com)
+- [GitLab Runner](https://docs.gitlab.com/runner/)
+- [Helm](https://helm.sh/docs/)
+- [Kubernetes](https://kubernetes.io/docs/home/)
+- [Prometheus](https://prometheus.io/docs/introduction/overview/)
## Troubleshooting
diff --git a/doc/topics/autodevops/multiple_clusters_auto_devops.md b/doc/topics/autodevops/multiple_clusters_auto_devops.md
index 9c766385e66..49ded4bfb9a 100644
--- a/doc/topics/autodevops/multiple_clusters_auto_devops.md
+++ b/doc/topics/autodevops/multiple_clusters_auto_devops.md
@@ -1,54 +1,55 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Multiple Kubernetes clusters for Auto DevOps **(FREE)**
-When using Auto DevOps, you can deploy different environments to
-different Kubernetes clusters, due to the 1:1 connection
-[existing between them](../../user/project/clusters/multiple_kubernetes_clusters.md).
+When using Auto DevOps, you can deploy different environments to different Kubernetes clusters.
-The [Deploy Job template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
-used by Auto DevOps defines 3 environment names:
+The [Deploy Job template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml) used by Auto DevOps defines three environment names:
- `review/` (every environment starting with `review/`)
- `staging`
- `production`
-Those environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so
-except for the environment scope, they must have a different deployment domain.
-You must define a separate `KUBE_INGRESS_BASE_DOMAIN` variable for each of the above
-[based on the environment](../../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable).
+These environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so they must have different deployment domains. You must define separate [`KUBE_CONTEXT`](../../user/clusters/agent/ci_cd_workflow.md#using-the-agent-with-auto-devops) and [`KUBE_INGRESS_BASE_DOMAIN`](requirements.md#auto-devops-base-domain) variables for each of the three environments.
-The following table is an example of how to configure the three different clusters:
+## Deploy to different clusters
-| 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 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 deploy your environments to different Kubernetes clusters:
-To add a different cluster for each environment:
+1. [Create Kubernetes clusters](../../user/infrastructure/clusters/connect/new_gke_cluster.md).
+1. Associate the clusters to your project:
+ 1. [Install a GitLab Agent on each cluster](../../user/clusters/agent/index.md).
+ 1. [Configure each agent to access your project](../../user/clusters/agent/install/index.md#configure-your-agent).
+1. [Install NGINX Ingress Controller](cloud_deployments/auto_devops_with_gke.md#install-ingress) in each cluster. Save the IP address and Kubernetes namespace for the next step.
+1. [Configure the Auto DevOps CI/CD Pipeline variables](customize.md#build-and-deployment)
+ - Set up a `KUBE_CONTEXT` variable [for each environment](../../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable). The value must point to the agent of the relevant cluster.
+ - Set up a `KUBE_INGRESS_BASE_DOMAIN`. You must [configure the base domain](requirements.md#auto-devops-base-domain) for each environment to point to the Ingress of the relevant cluster.
+ - Add a `KUBE_NAMESPACE` variable with a value of the Kubernetes namespace you want your deployments to target. You can scope the variable to multiple environments.
-1. Navigate to your project's **Infrastructure > Kubernetes clusters**.
-1. Create the Kubernetes clusters with their respective environment scope, as
- described from the table above.
-1. After creating the clusters, navigate to each cluster and
- [install Ingress](cloud_deployments/auto_devops_with_gke.md#install-ingress).
- Wait for the Ingress IP address to be assigned.
-1. Make sure you've [configured your DNS](requirements.md#auto-devops-base-domain) with the
- specified Auto DevOps domains.
-1. Navigate to each cluster's page, through **Infrastructure > Kubernetes clusters**,
- and add the domain based on its Ingress IP address.
+For deprecated, [certificate-based clusters](../../user/infrastructure/clusters/index.md#certificate-based-kubernetes-integration-deprecated):
+
+1. Go to the project and select **Infrastructure > Kubernetes clusters** from the left sidebar.
+1. [Set the environment scope of each cluster](../../user/project/clusters/multiple_kubernetes_clusters.md#setting-the-environment-scope).
+1. For each cluster, [add a domain based on its Ingress IP address](../../user/project/clusters/gitlab_managed_clusters.md#base-domain).
+
+NOTE:
+[Cluster environment scope is not respected when checking for active Kubernetes clusters](https://gitlab.com/gitlab-org/gitlab/-/issues/20351). For a multi-cluster setup to work with Auto DevOps, you must create a fallback cluster with **Cluster environment scope** set to `*`. You can set any of the clusters you've already added as a fallback cluster.
+
+### Example configurations
+
+| Cluster name | Cluster environment scope | `KUBE_INGRESS_BASE_DOMAIN` value | `KUBE CONTEXT` value | Variable environment scope | Notes |
+| :------------| :-------------------------| :------------------------------- | :--------------------------------- | :--------------------------|:--|
+| review | `review/*` | `review.example.com` | `path/to/project:review-agent` | `review/*` | A review cluster that runs all [Review Apps](../../ci/review_apps/index.md).|
+| staging | `staging` | `staging.example.com` | `path/to/project:staging-agent` | `staging` | Optional. A 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` | `path/to/project:production-agent` | `production` | A production cluster that runs the production environment deployments. You can use [incremental rollouts](customize.md#incremental-rollout-to-production). |
+
+## Test your configuration
After completing configuration, test your setup by creating a merge request.
Verify whether your application deployed as a Review App in the Kubernetes
cluster with the `review/*` environment scope. Similarly, check the
other environments.
-
-[Cluster environment scope isn't respected](https://gitlab.com/gitlab-org/gitlab/-/issues/20351)
-when checking for active Kubernetes clusters. For multi-cluster setup to work with Auto DevOps,
-create a fallback cluster with **Cluster environment scope** set to `*`. A new cluster isn't
-required. You can use any of the clusters already added.
diff --git a/doc/topics/autodevops/prepare_deployment.md b/doc/topics/autodevops/prepare_deployment.md
index c16a6c837cd..7805f9cd9c6 100644
--- a/doc/topics/autodevops/prepare_deployment.md
+++ b/doc/topics/autodevops/prepare_deployment.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Prepare Auto DevOps for deployment **(FREE)**
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
deleted file mode 100644
index a524b6e6451..00000000000
--- a/doc/topics/autodevops/quick_start_guide.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../autodevops/cloud_deployments/auto_devops_with_gke.md'
-remove_date: '2022-09-18'
----
-
-This document was moved to [another location](../autodevops/cloud_deployments/auto_devops_with_gke.md).
-
-<!-- This redirect file can be deleted after <2022-09-18>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> \ No newline at end of file
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index 9dffb490807..7c69e0327c8 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Requirements for Auto DevOps **(FREE)**
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 62356807854..9458d1cc6f9 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Stages of Auto DevOps **(FREE)**
diff --git a/doc/topics/autodevops/troubleshooting.md b/doc/topics/autodevops/troubleshooting.md
index bf3dc27c0e8..ae3cc42223f 100644
--- a/doc/topics/autodevops/troubleshooting.md
+++ b/doc/topics/autodevops/troubleshooting.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting Auto DevOps **(FREE)**
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index 5772a891b41..602bdec6140 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md
index 0d8d8cd6579..d43b1cae9e9 100644
--- a/doc/topics/autodevops/upgrading_postgresql.md
+++ b/doc/topics/autodevops/upgrading_postgresql.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Upgrading PostgreSQL for Auto DevOps **(FREE)**
diff --git a/doc/topics/awesome_co.md b/doc/topics/awesome_co.md
new file mode 100644
index 00000000000..0d725f64f3a
--- /dev/null
+++ b/doc/topics/awesome_co.md
@@ -0,0 +1,143 @@
+---
+stage: Ecosystem
+group: Foundations
+info: 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: AwesomeCo test data harness created by the Test Data Working Group https://about.gitlab.com/company/team/structure/working-groups/demo-test-data/
+comments: false
+---
+
+# AwesomeCo
+
+AwesomeCo is a test data seeding harness, that can seed test data into a user or group namespace.
+
+AwesomeCo uses FactoryBot in the backend which makes maintenance extremely easy. When a Model is changed,
+FactoryBot will already be reflected to account for the change.
+
+## Docker Setup
+
+See [AwesomeCo Docker Demo](https://gitlab.com/-/snippets/2390362)
+
+## GDK Setup
+
+```shell
+$ gdk start db
+ok: run: services/postgresql: (pid n) 0s, normally down
+ok: run: services/redis: (pid n) 74s, normally down
+$ bundle install
+Bundle complete!
+$ bundle exec rake db:migrate
+main: migrated
+ci: migrated
+```
+
+### Run
+
+The `gitlab:seed:awesome_co` Rake task takes two arguments. `:name` and `:namespace_id`.
+
+```shell
+$ bundle exec rake "gitlab:seed:awesome_co[awesome_co,1]"
+Seeding AwesomeCo for Administrator
+```
+
+#### `:name`
+
+Where `:name` is the name of the AwesomeCo. (This will reflect .rb files located in db/seeds/awesome_co/*.rb)
+
+#### `:namespace_id`
+
+Where `:namespace_id` is the ID of the User or Group Namespace
+
+## List of Awesome Companies
+
+Each company (i.e. test data template) is represented as a Ruby file (.rb) in `db/seeds/awesome_co`.
+
+### AwesomeCo (db/seeds/awesome_co/awesome_co.rb)
+
+```shell
+$ bundle exec rake "gitlab:seed:awesome_co[awesome_co,:namespace_id]"
+Seeding AwesomeCo for :namespace_id
+```
+
+AwesomeCo is an automated seeding of [this demo repository](https://gitlab.com/tech-marketing/demos/gitlab-agile-demo/awesome-co).
+
+## Develop
+
+AwesomeCo seeding uses FactoryBot definitions from `spec/factories` which ...
+
+1. Saves time on development
+1. Are easy-to-read
+1. Are easy to maintain
+1. Do not rely on an API that may change in the future
+1. Are always up-to-date
+1. Execute on the lowest-level (`ActiveRecord`) possible to create data as quickly as possible
+
+> _from the [FactoryBot README](https://github.com/thoughtbot/factory_bot#readme_) : factory_bot is a fixtures replacement with a straightforward definition syntax, support for multiple build
+> strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class, including factory
+> inheritance
+
+Factories reside in `spec/factories/*` and are fixtures for Rails models found in `app/models/*`. For example, For a model named `app/models/issue.rb`, the factory will
+be named `spec/factories/issues.rb`. For a model named `app/models/project.rb`, the factory will be named `app/models/projects.rb`.
+
+### Taxonomy of a Factory
+
+Factories consist of three main parts - the **Name** of the factory, the **Traits** and the **Attributes**.
+
+Given: `create(:iteration, :with_title, :current, title: 'My Iteration')`
+
+|||
+|:-|:-|
+| **:iteration** | This is the **Name** of the factory. The file name will be the plural form of this **Name** and reside under either `spec/factories/iterations.rb` or `ee/spec/factories/iterations.rb`. |
+| **:with_title** | This is a **Trait** of the factory. [See how it's defined](https://gitlab.com/gitlab-org/gitlab/-/blob/9c2a1f98483921dd006d70fdaed316e21fc5652f/ee/spec/factories/iterations.rb#L21-23). |
+| **:current** | This is a **Trait** of the factory. [See how it's defined](https://gitlab.com/gitlab-org/gitlab/-/blob/9c2a1f98483921dd006d70fdaed316e21fc5652f/ee/spec/factories/iterations.rb#L29-31). |
+| **title: 'My Iteration'** | This is an **Attribute** of the factory that will be passed to the Model for creation. |
+
+### Examples
+
+In these examples, you will see an instance variable `@owner`. This is the `root` user (`User.first`).
+
+#### Create a Group
+
+```ruby
+my_group = create(:group, name: 'My Group', path: 'my-group-path')
+```
+
+#### Create a Project
+
+```ruby
+# create a Project belonging to a Group
+my_project = create(:project, :public, name: 'My Project', namespace: my_group, creator: @owner)
+```
+
+#### Create an Issue
+
+```ruby
+# create an Issue belonging to a Project
+my_issue = create(:issue, title: 'My Issue', project: my_project, weight: 2)
+```
+
+#### Create an Iteration
+
+```ruby
+# create an Iteration under a Group
+my_iteration = create(:iteration, :with_title, :current, title: 'My Iteration', group: my_group)
+```
+
+### Frequently encountered issues
+
+#### ActiveRecord::RecordInvalid: Validation failed: Email has already been taken, Username has already been taken
+
+This is because, by default, our factories are written to backfill any data that is missing. For instance, when a project
+is created, the project must have somebody that created it. If the owner is not specified, the factory attempts to create it.
+
+**How to fix**
+
+Check the respective Factory to find out what key is required. Usually `:author` or `:owner`.
+
+```ruby
+# This throws ActiveRecord::RecordInvalid
+create(:project, name: 'Throws Error', namespace: create(:group, name: 'Some Group'))
+
+# Specify the user where @owner is a [User] record
+create(:project, name: 'No longer throws error', owner: @owner, namespace: create(:group, name: 'Some Group'))
+create(:epic, group: create(:group), author: @owner)
+```
diff --git a/doc/topics/build_your_application.md b/doc/topics/build_your_application.md
index d48b8383271..35f9db4d087 100644
--- a/doc/topics/build_your_application.md
+++ b/doc/topics/build_your_application.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Build your application **(FREE)**
diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md
index 34a51d3d535..b437541e0ea 100644
--- a/doc/topics/cron/index.md
+++ b/doc/topics/cron/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cron
diff --git a/doc/topics/git/bisect.md b/doc/topics/git/bisect.md
index e587a51ba17..a7f8b2a846c 100644
--- a/doc/topics/git/bisect.md
+++ b/doc/topics/git/bisect.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/cherry_picking.md b/doc/topics/git/cherry_picking.md
index d9314c3becc..ce2a1d4b954 100644
--- a/doc/topics/git/cherry_picking.md
+++ b/doc/topics/git/cherry_picking.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md
index b205cedbdaa..de9f9980811 100644
--- a/doc/topics/git/feature_branch_development.md
+++ b/doc/topics/git/feature_branch_development.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: how-tos
---
diff --git a/doc/topics/git/feature_branching.md b/doc/topics/git/feature_branching.md
index 4e9b43d66f8..73de351fde2 100644
--- a/doc/topics/git/feature_branching.md
+++ b/doc/topics/git/feature_branching.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/getting_started.md b/doc/topics/git/getting_started.md
index 7a836e5b659..a843d44aa8c 100644
--- a/doc/topics/git/getting_started.md
+++ b/doc/topics/git/getting_started.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/git_add.md b/doc/topics/git/git_add.md
index e15a1e9a60d..71f695d1657 100644
--- a/doc/topics/git/git_add.md
+++ b/doc/topics/git/git_add.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/git_log.md b/doc/topics/git/git_log.md
index 3988d7f7ac9..e2e9c0e8804 100644
--- a/doc/topics/git/git_log.md
+++ b/doc/topics/git/git_log.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/git_rebase.md b/doc/topics/git/git_rebase.md
index 1e118f98ca5..2f12201fb45 100644
--- a/doc/topics/git/git_rebase.md
+++ b/doc/topics/git/git_rebase.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: concepts, howto
description: "Introduction to Git rebase and force-push, methods to resolve merge conflicts through the command line."
---
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index 1d1264fecf3..7d753374473 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'This article describes how to install Git on macOS, Ubuntu Linux and Windows.'
---
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index 3e78e366e00..f5dd458f625 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: index
---
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 6fd7f4a5207..1ab4a8a8acc 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs/index.html'
---
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index dda15845088..6e634cde8f0 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "How to migrate an existing Git repository to Git LFS with BFG."
---
@@ -15,7 +15,7 @@ instead of the method documented below.
Using Git LFS can help you to reduce the size of your Git
repository and improve its performance.
-However, simply adding the large files that are already in your repository to Git LFS
+However, adding the large files that are already in your repository to Git LFS
doesn't actually reduce the size of your repository because
the files are still referenced by previous commits.
diff --git a/doc/topics/git/merge_conflicts.md b/doc/topics/git/merge_conflicts.md
index 03b7c03c02a..91b608ab705 100644
--- a/doc/topics/git/merge_conflicts.md
+++ b/doc/topics/git/merge_conflicts.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index 0ed7b2b5e03..e1e4300f42c 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index eeae0d78638..ed80ab71c53 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
---
diff --git a/doc/topics/git/rollback_commits.md b/doc/topics/git/rollback_commits.md
index 478dce179d2..65c4f1e5007 100644
--- a/doc/topics/git/rollback_commits.md
+++ b/doc/topics/git/rollback_commits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/stash.md b/doc/topics/git/stash.md
index 638ab559bd3..6ef72e300ed 100644
--- a/doc/topics/git/stash.md
+++ b/doc/topics/git/stash.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/subtree.md b/doc/topics/git/subtree.md
index 0bf89668405..1d624b45348 100644
--- a/doc/topics/git/subtree.md
+++ b/doc/topics/git/subtree.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/tags.md b/doc/topics/git/tags.md
index d3237fda968..ab196f409f7 100644
--- a/doc/topics/git/tags.md
+++ b/doc/topics/git/tags.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tags **(FREE)**
diff --git a/doc/topics/git/terminology.md b/doc/topics/git/terminology.md
index f64e614c253..ac097396bef 100644
--- a/doc/topics/git/terminology.md
+++ b/doc/topics/git/terminology.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Git terminology
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index 484f3a100bf..e585b860b16 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: howto
---
diff --git a/doc/topics/git/unstage.md b/doc/topics/git/unstage.md
index b5f7c01de24..142a80a9ad9 100644
--- a/doc/topics/git/unstage.md
+++ b/doc/topics/git/unstage.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 13a40dd58ca..26ad155054b 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 034c822671d..ffd9f36b369 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/gitlab_flow.html'
---
diff --git a/doc/topics/offline/index.md b/doc/topics/offline/index.md
index 13207c8c612..56b523c9c6f 100644
--- a/doc/topics/offline/index.md
+++ b/doc/topics/offline/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Offline GitLab **(FREE SELF)**
diff --git a/doc/topics/offline/quick_start_guide.md b/doc/topics/offline/quick_start_guide.md
index c00c9621756..bb2f651786c 100644
--- a/doc/topics/offline/quick_start_guide.md
+++ b/doc/topics/offline/quick_start_guide.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Getting started with an offline GitLab Installation **(FREE SELF)**
diff --git a/doc/topics/plan_and_track.md b/doc/topics/plan_and_track.md
index 13cb3f8923b..cf5dfe488db 100644
--- a/doc/topics/plan_and_track.md
+++ b/doc/topics/plan_and_track.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Plan and track work **(FREE)**
diff --git a/doc/topics/release_your_application.md b/doc/topics/release_your_application.md
index 31fc9b4dbb9..6f1c7bb4a40 100644
--- a/doc/topics/release_your_application.md
+++ b/doc/topics/release_your_application.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy and release your application **(FREE)**
diff --git a/doc/topics/set_up_organization.md b/doc/topics/set_up_organization.md
index b6cacf0b14e..526e36b9ce0 100644
--- a/doc/topics/set_up_organization.md
+++ b/doc/topics/set_up_organization.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up your organization **(FREE)**
diff --git a/doc/tutorials/index.md b/doc/tutorials/index.md
index 1b4762052c0..92e96a059dc 100644
--- a/doc/tutorials/index.md
+++ b/doc/tutorials/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: For assistance with this tutorials page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this tutorials page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
---
# Learn GitLab with tutorials
@@ -16,10 +16,10 @@ and running quickly.
| Topic | Description | Good for beginners |
|-------|-------------|--------------------|
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Introduction to GitLab](https://youtu.be/_4SmIyQ5eis?t=90) (59m 51s) | Walk through recommended processes and example workflows for using GitLab. | **{star}** |
-| [GitLab 101](https://gitlab.edcast.com/pathways/ECL-ce65e759-d9e7-459f-83d0-1765459395d2) | Learn the basics of GitLab in this certification course. | **{star}** |
+| [GitLab 101](https://levelup.gitlab.com/learn/course/gitlab101) | Learn the basics of GitLab in this certification course. | **{star}** |
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Use GitLab for DevOps](https://www.youtube.com/watch?v=7q9Y1Cv-ib0) (12m 34s) | Use GitLab through the entire DevOps lifecycle, from planning to monitoring. | **{star}** |
| [Use Markdown at GitLab](../user/markdown.md) | GitLab Flavored Markdown (GLFM) is used in many areas of GitLab, for example, in merge requests. | **{star}** |
-| [GitLab 201](https://gitlab.edcast.com/pathways/ECL-44010cf6-7a9c-4b9b-b684-fa08508a3252) | Go beyond the basics to learn more about using GitLab for your work. | |
+| [GitLab 201](https://levelup.gitlab.com/learn/course/gitlab-201-certification) | Go beyond the basics to learn more about using GitLab for your work. | |
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Learn GitLab project walkthrough](https://www.youtube.com/watch?v=-oaI2WEKdI4&list=PL05JrBw4t0KofkHq4GZJ05FnNGa11PQ4d) (59m 2s) | Step through the tutorial-style issues in the **Learn GitLab** project. If you don't have this project, download [the export file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/project_templates/learn_gitlab_ultimate.tar.gz) and [import it to a new project](../user/project/settings/import_export.md#import-a-project-and-its-data). | |
| [Productivity tips](https://about.gitlab.com/blog/2021/02/18/improve-your-gitlab-productivity-with-these-10-tips/) | Get tips to help make you a productive GitLab user. | |
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Structure a multi-team organization](https://www.youtube.com/watch?v=KmASFwSap7c) (37m 37s) | Learn to use issues, milestones, epics, labels, and more to plan and manage your work. | |
@@ -67,7 +67,7 @@ configure the infrastructure for your application.
| Topic | Description | Good for beginners |
|-------|-------------|--------------------|
| [Use GitOps with GitLab](https://about.gitlab.com/blog/2022/04/07/the-ultimate-guide-to-gitops-with-gitlab/) | Learn how to provision and manage a base infrastructure, connect to a Kubernetes cluster, deploy third-party applications, and carry out other infrastructure automation tasks. | |
-| [Use Auto DevOps to deploy an application](../topics/autodevops/quick_start_guide.md) | Deploy an application to Google Kubernetes Engine (GKE). | |
+| [Use Auto DevOps to deploy an application](../topics/autodevops/cloud_deployments/auto_devops_with_gke.md) | Deploy an application to Google Kubernetes Engine (GKE). | |
## Publish a static website
diff --git a/doc/tutorials/make_your_first_git_commit.md b/doc/tutorials/make_your_first_git_commit.md
index 879257fc3b8..cb6f41bff6c 100644
--- a/doc/tutorials/make_your_first_git_commit.md
+++ b/doc/tutorials/make_your_first_git_commit.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: For assistance with this tutorial, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this tutorial, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
---
# Make your first Git commit
diff --git a/doc/tutorials/move_personal_project_to_a_group.md b/doc/tutorials/move_personal_project_to_a_group.md
index 49ce09a2ed4..2106f6ec1c9 100644
--- a/doc/tutorials/move_personal_project_to_a_group.md
+++ b/doc/tutorials/move_personal_project_to_a_group.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: For assistance with this tutorial, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+info: For assistance with this tutorial, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
---
# Move your personal project to a group **(FREE SAAS)**
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 44a7137f698..ed9b812525e 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -1,7 +1,7 @@
---
stage: none
group: none
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Deprecations by version
@@ -45,6 +45,39 @@ sole discretion of GitLab Inc.
<div class="announcement-milestone">
+## Announced in 15.5
+
+<div class="deprecation removal-160 breaking-change">
+
+### GraphQL field `confidential` changed to `internal` on notes
+
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
+
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
+The `confidential` field for a `Note` will be deprecated and renamed to `internal`.
+
+</div>
+
+<div class="deprecation removal-160 breaking-change">
+
+### vulnerabilityFindingDismiss GraphQL mutation
+
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
+
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
+The `VulnerabilityFindingDismiss` GraphQL mutation is being deprecated and will be removed in GitLab 16.0. This mutation was not used often as the Vulnerability Finding ID was not available to users (this field was [deprecated in 15.3](https://docs.gitlab.com/ee/update/deprecations.html#use-of-id-field-in-vulnerabilityfindingdismiss-mutation)). Users should instead use `VulnerabilityDismiss` to dismiss vulnerabilities in the Vulnerability Report or `SecurityFindingDismiss` for security findings in the CI Pipeline Security tab.
+
+</div>
+</div>
+
+<div class="announcement-milestone">
+
## Announced in 15.4
<div class="deprecation removal-160 breaking-change">
@@ -809,6 +842,29 @@ To align with this change, API calls to list external status checks will also re
</div>
+<div class="deprecation removal-160 breaking-change">
+
+### GraphQL API Runner will not accept `status` filter values of `active` or `paused`
+
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
+
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
+The GitLab Runner GraphQL endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
+
+A runner's status will only relate to runner contact status, such as: `online`, `offline`.
+Status values `paused` or `active` will no longer be accepted and will be replaced by the `paused` query parameter.
+
+When checking for paused runners, API users are advised to specify `paused: true` as the query parameter.
+When checking for active runners, specify `paused: false`.
+
+The REST API endpoints will follow in the same direction in a future REST v5 API, however the new `paused`
+status value can be used in place of `active` since GitLab 14.8.
+
+</div>
+
<div class="deprecation removal-150 breaking-change">
### GraphQL ID and GlobalID compatibility
@@ -968,40 +1024,6 @@ The `instanceStatisticsMeasurements` GraphQL node has been renamed to `usageTren
<div class="deprecation removal-160 breaking-change">
-### REST API Runner will not accept `status` filter values of `active` or `paused`
-
-Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
-
-WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
-Review the details carefully before upgrading.
-
-The GitLab Runner REST endpoints will stop accepting `paused` or `active` as a status value in GitLab 16.0.
-
-A runner's status will only relate to runner contact status, such as: `online`, `offline`.
-Status values `paused` or `active` will no longer be accepted and will be replaced by the `paused` query parameter.
-
-When checking for paused runners, API users are advised to specify `paused=true` as the query parameter.
-When checking for active runners, specify `paused=false`.
-
-</div>
-
-<div class="deprecation removal-160 breaking-change">
-
-### REST API endpoint to list group runners no longer accepts `project_type` value for `type` argument
-
-Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
-
-WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
-Review the details carefully before upgrading.
-
-The `GET /groups/:id/runners?type=project_type` endpoint will be removed in GitLab 16.0. The endpoint always returned an empty collection.
-
-</div>
-
-<div class="deprecation removal-160 breaking-change">
-
### REST and GraphQL API Runner usage of `active` replaced by `paused`
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
@@ -1010,15 +1032,16 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
-Occurrences of the `active` identifier in the GitLab Runner REST and GraphQL API endpoints will be
-renamed to `paused` in GitLab 16.0, namely:
+Occurrences of the `active` identifier in the GitLab Runner GraphQL API endpoints will be
+renamed to `paused` in GitLab 16.0.
-- GraphQL API:
- - the `CiRunner` property;
- - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation;
- - the `runners` and `Group.runners` queries.
-- REST API:
- - endpoints taking or returning `active` properties, such as:
+- For the GraphQL API, this change affects:
+ - the `CiRunner` property
+ - the `RunnerUpdateInput` input type for the `runnerUpdate` mutation
+ - the `runners` and `Group.runners` queries
+- In v4 of the REST API, starting in GitLab 14.8, you can use the `paused` property in place of `active`
+- In v5 of the REST API, this change will affect:
+ - endpoints taking or returning `active` property, such as:
- `GET /runners`
- `GET /runners/all`
- `GET /runners/:id` / `PUT /runners/:id`
@@ -1026,9 +1049,7 @@ renamed to `paused` in GitLab 16.0, namely:
- `GET /projects/:id/runners` / `POST /projects/:id/runners`
- `GET /groups/:id/runners`
-The 16.0 release of the GitLab Runner will start using the `paused` property when registering runners, and therefore
-will only be compatible with GitLab 16.0 and later. Until 16.0, GitLab will accept the deprecated `active` flag from
-existing runners.
+The 16.0 release of GitLab Runner will start using the `paused` property when registering runners.
</div>
@@ -1788,55 +1809,56 @@ Administrators who need to add runners for multiple projects can register a runn
</div>
-<div class="deprecation removal-150 breaking-change">
+<div class="deprecation removal-160 breaking-change">
-### Known host required for GitLab Runner SSH executor
+### GraphQL API Runner status will not return `paused`
-Planned removal: GitLab <span class="removal-milestone">15.0</span> (2022-05-22)
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
-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.
+The GitLab Runner GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 16.0.
+In a future v5 of the REST API, the endpoints for GitLab Runner will also not return `paused` or `active`.
-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.
+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
+`paused` to be `true` instead. When checking if a runner is `active`, check if `paused` is `false`.
</div>
-<div class="deprecation removal-160 breaking-change">
+<div class="deprecation removal-150 breaking-change">
-### Package pipelines in API payload is paginated
+### Known host required for GitLab Runner SSH executor
-Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
+Planned removal: GitLab <span class="removal-milestone">15.0</span> (2022-05-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
-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.
+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.
-In milestone 16.0, we will remove the `pipelines` attribute from the API response.
+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.
</div>
<div class="deprecation removal-160 breaking-change">
-### REST and GraphQL API Runner status will not return `paused`
+### Package pipelines in API payload is paginated
-Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-04-22)
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
-The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 16.0.
-
-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.
+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.
-When checking if a runner is `paused`, API users are advised to check the boolean attribute
-`paused` to be `true` instead. When checking if a runner is `active`, check if `paused` is `false`.
+In milestone 16.0, we will remove the `pipelines` attribute from the API response.
</div>
diff --git a/doc/update/index.md b/doc/update/index.md
index bffecf58304..06609f03952 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Upgrading GitLab **(FREE SELF)**
@@ -392,6 +392,8 @@ 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.
+For a dynamic view of examples of supported upgrade paths, try the [Upgrade Path tool](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/). The Upgrade Path tool is maintained by the [GitLab Support team](https://about.gitlab.com/handbook/support/#about-the-support-team). Share feedback and help improve the tool by raising an issue or MR in the [upgrade-path project](https://gitlab.com/gitlab-com/support/toolbox/upgrade-path).
+
| Target version | Your version | Supported upgrade path | Note |
| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `15.1.0` | `14.6.2` | `14.6.2` -> `14.9.5` -> `14.10.5` -> `15.0.2` -> `15.1.0` | Three intermediate versions are required: `14.9` and `14.10`, `15.0`, then `15.1.0`. |
@@ -477,7 +479,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
### 15.3.0
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.2.0
@@ -498,7 +500,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
1. Add `gitaly['runtime_dir'] = '<PATH_WITH_EXEC_PERM>'` to `/etc/gitlab/gitlab.rb` and specify a location without `noexec` set.
1. Run `sudo gitlab-ctl reconfigure`.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.1.0
@@ -518,7 +520,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
- Unauthenticated requests to the [`ciConfig` GraphQL field](../api/graphql/reference/index.md#queryciconfig) are no longer supported.
Before you upgrade to GitLab 15.1, add an [access token](../api/index.md#authentication) to your requests.
The user creating the token must have [permission](../user/permissions.md) to create pipelines in the project.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.0.0
@@ -534,7 +536,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
Gitaly. The previous implementation in GitLab Shell was removed in GitLab 15.0. With this change, global server hooks are stored only inside a subdirectory named after the
hook type. Global server hooks can no longer be a single hook file in the root of the custom hooks directory. For example, you must use `<custom_hooks_dir>/<hook_name>.d/*` rather
than `<custom_hooks_dir>/<hook_name>`.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- The `FF_GITLAB_REGISTRY_HELPER_IMAGE` [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) is removed and helper images are always pulled from GitLab Registry.
### 14.10.0
@@ -1183,7 +1185,7 @@ Read more [in the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/364763).
### Geo: Incorrect object storage LFS file deletion on secondary sites in GitLab 15.0.0 to 15.3.2
-[Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397))
+[Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397)
can occur in GitLab 15.0.0 to 15.3.2 in the following situations:
- GitLab-managed object storage replication is disabled, and LFS objects are created while importing a project with object storage enabled.
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 8ac2791c82b..14914eee27c 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating from MySQL to PostgreSQL **(FREE SELF)**
diff --git a/doc/update/package/convert_to_ee.md b/doc/update/package/convert_to_ee.md
index 2bf6d2c580b..7ebb860746b 100644
--- a/doc/update/package/convert_to_ee.md
+++ b/doc/update/package/convert_to_ee.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Convert Community Edition to Enterprise Edition **(FREE SELF)**
diff --git a/doc/update/package/downgrade.md b/doc/update/package/downgrade.md
index f48ba31568f..7b48f1f4045 100644
--- a/doc/update/package/downgrade.md
+++ b/doc/update/package/downgrade.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Downgrade **(FREE SELF)**
diff --git a/doc/update/package/index.md b/doc/update/package/index.md
index 06a56f49cc1..e0a4a388f56 100644
--- a/doc/update/package/index.md
+++ b/doc/update/package/index.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Upgrade GitLab by using the GitLab package **(FREE SELF)**
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index b7c148045bd..6e153d5132d 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/update/plan_your_upgrade.md b/doc/update/plan_your_upgrade.md
index 03bdf161756..8169645e278 100644
--- a/doc/update/plan_your_upgrade.md
+++ b/doc/update/plan_your_upgrade.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a GitLab upgrade plan **(FREE SELF)**
@@ -42,7 +42,7 @@ to ensure the major components of GitLab are working:
```
1. In GitLab UI, check that:
- - Users can log in.
+ - Users can sign in.
- The project list is visible.
- Project issues and merge requests are accessible.
- Users can clone repositories from GitLab.
@@ -122,7 +122,7 @@ to your instance and then upgrade it for any relevant features you're using.
- [Convert from GitLab Community Edition to Enterprise Edition](package/convert_to_ee.md)
- What version should you upgrade to:
- [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 update instructions](index.md#version-specific-upgrading-instructions) for both the current version and the destination version.
- Account for any [version-specific changes](package/index.md#version-specific-changes).
- Check the [OS compatibility with the target GitLab version](../administration/package_information/supported_os.md).
- Due to background migrations, plan to pause before any further upgrades.
diff --git a/doc/update/removals.md b/doc/update/removals.md
index 9b5596d67f2..392259176bb 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -1,7 +1,7 @@
---
stage: none
group: none
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
---
# Removals by version
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 06da66088eb..cc0b188a0f8 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Restoring from backup after a failed upgrade **(FREE SELF)**
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 55561abc009..9bb88755686 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 4f54e69d8c9..bb9199560f9 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
comments: false
---
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index d3102ca4591..a645eb220ad 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Upgrading PostgreSQL Using Slony **(FREE SELF)**
diff --git a/doc/update/with_downtime.md b/doc/update/with_downtime.md
index c6ad854fd0f..dfe64a3c2a9 100644
--- a/doc/update/with_downtime.md
+++ b/doc/update/with_downtime.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Multi-node upgrades with downtime **(FREE SELF)**
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index 29bb1c4bcb4..aebd27f84a9 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Zero downtime upgrades **(FREE SELF)**
@@ -313,7 +313,7 @@ node throughout the process.
- If you're using PgBouncer:
- You must bypass PgBouncer and connect directly to the database leader
+ You must [bypass PgBouncer](../administration/postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer) and connect directly to the database leader
before running migrations.
Rails uses an advisory lock when attempting to run a migration to prevent
@@ -699,7 +699,7 @@ sudo touch /etc/gitlab/skip-auto-reconfigure
1. If you're using PgBouncer:
- You must bypass PgBouncer and connect directly to the database leader
+ You must [bypass PgBouncer](../administration/postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer) and connect directly to the database leader
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_reports.md b/doc/user/admin_area/analytics/dev_ops_reports.md
index b4471a4602a..2d19c0a0058 100644
--- a/doc/user/admin_area/analytics/dev_ops_reports.md
+++ b/doc/user/admin_area/analytics/dev_ops_reports.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# DevOps Reports **(FREE SELF)**
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
index 9147a48aa8e..4304e612e4a 100644
--- a/doc/user/admin_area/analytics/index.md
+++ b/doc/user/admin_area/analytics/index.md
@@ -1,19 +1,25 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Instance-level analytics **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41416) in GitLab 11.2.
-Administrators have access to instance-wide analytics:
+Instance-level analytics provide insights into the feature and data usage of your entire instance.
-1. On the top bar, select **Main menu > Admin**.
-1. On the left sidebar, select **Analytics**.
+## View instance-level analytics
+
+Prerequisite:
+
+- You must have administrator access for your instance.
-There are several kinds of statistics:
+To view instance-level analytics:
+
+1. On the top bar, select **Main menu > Admin**.
+1. On the left sidebar, select **Analytics**, then one of the available analytics:
-- [DevOps Reports](dev_ops_reports.md): Provides an overview of your entire instance's feature usage.
-- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing.
+ - [DevOps Reports](dev_ops_reports.md): Provides an overview of your entire instance's feature usage.
+ - [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how the data is changing.
diff --git a/doc/user/admin_area/analytics/usage_trends.md b/doc/user/admin_area/analytics/usage_trends.md
index f21ee627f7f..a240a1ff524 100644
--- a/doc/user/admin_area/analytics/usage_trends.md
+++ b/doc/user/admin_area/analytics/usage_trends.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Usage Trends **(FREE SELF)**
diff --git a/doc/user/admin_area/appearance.md b/doc/user/admin_area/appearance.md
index fbc2f8d1827..5513fa3585d 100644
--- a/doc/user/admin_area/appearance.md
+++ b/doc/user/admin_area/appearance.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/customization/branded_login_page.html'
---
@@ -30,7 +30,7 @@ supported by many email clients.
## Favicon
By default, the favicon (used by the browser as the tab icon, as well as the CI status icon)
-uses the GitLab logo, but this can be customized with any icon desired. It must be a
+uses the GitLab logo. This can be customized with any icon desired. It must be a
32x32 `.png` or `.ico` image.
After you select and upload an icon, select **Update appearance settings** at the bottom
@@ -41,13 +41,13 @@ of the page to activate it in the GitLab instance.
You can add a small header message, a small footer message, or both, to the interface
of your GitLab instance. These messages appear on all projects and pages of the
instance, including the sign in / sign up page. The default color is white text on
-an orange background, but this can be customized by clicking on **Customize colors**.
+an orange background, but this can be customized by selecting **Customize colors**.
Limited [Markdown](../markdown.md) is supported, such as bold, italics, and links, for
example. Other Markdown features, including lists, images, and quotes are not supported
as the header and footer messages can only be a single line.
-If desired, you can select **Enable header and footer in emails** to have the text of
+You can select **Enable header and footer in emails** to have the text of
the header and footer added to all emails sent by the GitLab instance.
After you add a message, select **Update appearance settings** at the bottom of the page
@@ -71,7 +71,7 @@ You can add also add a [customized help message](settings/help_page.md) below th
## New project pages
-You can add a new project guidelines message to the **New project page** within GitLab.
+You can add a new project guidelines message to the **New project page** in GitLab.
You can make full use of [Markdown](../markdown.md) in the description:
The message is displayed below the **New Project** message, on the left side
@@ -84,8 +84,7 @@ which brings you to the new project page so you can review the change.
## Libravatar
[Libravatar](https://www.libravatar.org) is supported by GitLab for avatar images, but you must
-[manually enable Libravatar support on the GitLab instance](../../administration/libravatar.md)
-in order to use the service.
+[manually enable Libravatar support on the GitLab instance](../../administration/libravatar.md) to use the service.
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
index b508b71ddac..e5d0a6e297e 100644
--- a/doc/user/admin_area/broadcast_messages.md
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -1,7 +1,7 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index 02c4cd05b23..df53ef0696f 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
index 0c03652bfb5..551ed667250 100644
--- a/doc/user/admin_area/custom_project_templates.md
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/diff_limits.md b/doc/user/admin_area/diff_limits.md
index f646d9f95fd..3a1ecac6ee6 100644
--- a/doc/user/admin_area/diff_limits.md
+++ b/doc/user/admin_area/diff_limits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/email_from_gitlab.md b/doc/user/admin_area/email_from_gitlab.md
index 09643fc290e..c1d3521d60c 100644
--- a/doc/user/admin_area/email_from_gitlab.md
+++ b/doc/user/admin_area/email_from_gitlab.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto, reference
---
diff --git a/doc/user/admin_area/geo_sites.md b/doc/user/admin_area/geo_sites.md
index fecc0e7c541..093ed84f41a 100644
--- a/doc/user/admin_area/geo_sites.md
+++ b/doc/user/admin_area/geo_sites.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo sites Admin Area **(PREMIUM SELF)**
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 207b7e6f2d8..e6ddb810933 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -270,10 +270,12 @@ To [Create a new group](../group/manage.md#create-a-group) select **New group**.
### Administering Topics
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
+- > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
+- > Merging topics [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366884) in GitLab 15.5.
-You can administer all [topics](../project/working_with_projects.md#explore-topics) in the
-GitLab instance from the Admin Area's Topics page.
+[Topics](../project/working_with_projects.md#explore-topics) are used to categorize and find similar projects.
+
+You can administer all topics in the GitLab instance from the Admin Area's Topics page.
To access the Topics page:
@@ -295,7 +297,7 @@ insensitive and applies partial matching.
NOTE:
The assigned topics are visible only to everyone with access to the project,
-but everyone can see which topics exist at all on the GitLab instance.
+but everyone can see which topics exist on the GitLab instance.
Do not include sensitive information in the name of a topic.
### Administering Jobs
@@ -351,10 +353,8 @@ You can also filter runners by status, type, and tag. To filter:
#### Bulk delete runners
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/370241) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `admin_runners_bulk_delete`. 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 `admin_runners_bulk_delete`. On GitLab.com, this feature is not available but can be enabled by GitLab.com administrators.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/370241) in GitLab 15.4.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/353981) in GitLab 15.5.
You can delete multiple runners at the same time.
diff --git a/doc/user/admin_area/labels.md b/doc/user/admin_area/labels.md
index 93114186e75..524546d447c 100644
--- a/doc/user/admin_area/labels.md
+++ b/doc/user/admin_area/labels.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index a5338aa35b8..5211a18201b 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Provision
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Activate GitLab Enterprise Edition (EE) **(PREMIUM SELF)**
diff --git a/doc/user/admin_area/license_file.md b/doc/user/admin_area/license_file.md
index 352d79ee381..e6186fb9805 100644
--- a/doc/user/admin_area/license_file.md
+++ b/doc/user/admin_area/license_file.md
@@ -1,7 +1,7 @@
---
stage: Fulfillment
group: Provision
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
<!-- To promote the workflow described in license.md, this page is not included in global left nav. -->
@@ -24,6 +24,9 @@ Otherwise, to add your license:
1. Select the **Terms of Service** checkbox.
1. Select **Add license**.
+NOTE:
+For GitLab versions 14.1.x or newer, you can access the **Add License** page directly from the URL, `<YourGitLabURL>/admin/license/new`.
+
## Add your license file during installation
You can import a license file when you install GitLab.
@@ -71,7 +74,9 @@ and issue creation. Your instance becomes read-only and
an expiration message displays to all administrators. You have a 14-day grace period
before this occurs.
-To resume functionality, activate a new subscription.
+To resume functionality, [renew your subscription](../../subscriptions/self_managed/index.md#renew-a-subscription).
+
+If the license has been expired for more than 30 days, you must purchase a [new subscription](../../subscriptions/self_managed/index.md) to resume functionality.
To go back to Free features, [delete all expired licenses](#remove-a-license).
@@ -138,3 +143,7 @@ rules apply:
For example, if you purchase a license for 100 users, you can have 110 users when you add
your license. However, if you have 111 users, you must purchase more users before you can add
the license.
+
+### `Start GitLab Ultimate trial` still displays after adding license
+
+To fix this issue, restart [Puma or your entire GitLab instance](../../administration/restart_gitlab.md).
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index 38b177766cf..b2f24091d7c 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md
index 6d632a6bdb6..ace1c6be5f8 100644
--- a/doc/user/admin_area/moderate_users.md
+++ b/doc/user/admin_area/moderate_users.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
@@ -83,7 +83,7 @@ by removing them in LDAP, or directly from the Admin Area. To do this:
A blocked user:
-- Cannot log in.
+- Cannot sign in.
- Cannot access Git repositories or the API.
- Does not receive any notifications from GitLab.
- Cannot use [slash commands](../../integration/slash_commands.md).
@@ -171,19 +171,20 @@ Users can also be deactivated using the [GitLab API](../../api/users.md#deactiva
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320875) in GitLab 14.0.
> - Customizable time period [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336747) in GitLab 15.4
+> - The lower limit for inactive period set to 90 days [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100793) in GitLab 15.5
Administrators can enable automatic deactivation of users who either:
- Were created more than a week ago and have not signed in.
-- Have no activity for a specified period of time (defaults to 90 days).
+- Have no activity for a specified period of time (default and minimum is 90 days).
To do this:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
-1. Under **Dormant users**, check **Deactivate dormant users after 90 days of inactivity**.
-1. Under **Period of inactivity (days)**, enter a period of time before deactivation.
+1. Under **Dormant users**, check **Deactivate dormant users after a period of inactivity**.
+1. Under **Days of inactivity before deactivation**, enter the number of days before deactivation. Minimum value is 90 days.
1. Select **Save changes**.
When this feature is enabled, GitLab runs a job once a day to deactivate the dormant users.
diff --git a/doc/user/admin_area/monitoring/background_migrations.md b/doc/user/admin_area/monitoring/background_migrations.md
index 092a49dc7e9..f16cb219f2b 100644
--- a/doc/user/admin_area/monitoring/background_migrations.md
+++ b/doc/user/admin_area/monitoring/background_migrations.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Batched background migrations **(FREE SELF)**
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 84c7fa3c419..e6f9c045329 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Health Check **(FREE SELF)**
@@ -15,7 +15,7 @@ traffic until the system is ready or restart the container as needed.
## IP allowlist
To access monitoring resources, the requesting client IP needs to be included in the allowlist.
-For details, see [how to add IPs to the allowlist for the monitoring endpoints](../../../administration/monitoring/ip_whitelist.md).
+For details, see [how to add IPs to the allowlist for the monitoring endpoints](../../../administration/monitoring/ip_allowlist.md).
## Using the endpoints locally
diff --git a/doc/user/admin_area/reporting/git_abuse_rate_limit.md b/doc/user/admin_area/reporting/git_abuse_rate_limit.md
index 11b0e2403aa..432205d8fa2 100644
--- a/doc/user/admin_area/reporting/git_abuse_rate_limit.md
+++ b/doc/user/admin_area/reporting/git_abuse_rate_limit.md
@@ -1,7 +1,7 @@
---
stage: Anti-Abuse
group: Anti-Abuse
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Git abuse rate limit **(ULTIMATE SELF)**
diff --git a/doc/user/admin_area/reporting/spamcheck.md b/doc/user/admin_area/reporting/spamcheck.md
index 670b0521732..5c305eff4fa 100644
--- a/doc/user/admin_area/reporting/spamcheck.md
+++ b/doc/user/admin_area/reporting/spamcheck.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Spamcheck anti-spam service **(FREE SELF)**
@@ -61,7 +61,7 @@ token as the API key.
## Running Spamcheck over TLS
-Spamcheck service on its own can not communicate directly over TLS with GitLab.
+Spamcheck service on its own cannot communicate directly over TLS with GitLab.
However, Spamcheck can be deployed behind a reverse proxy which performs TLS
termination. In such a scenario, GitLab can be made to communicate with
Spamcheck over TLS by specifying `tls://` scheme for the external Spamcheck URL
diff --git a/doc/user/admin_area/review_abuse_reports.md b/doc/user/admin_area/review_abuse_reports.md
index 16295f340d8..af2f6640f8e 100644
--- a/doc/user/admin_area/review_abuse_reports.md
+++ b/doc/user/admin_area/review_abuse_reports.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -53,7 +53,7 @@ The following is an example of the **Abuse Reports** page:
### Blocking users
-A blocked user cannot log in or access any repositories, but all of their data
+A blocked user cannot sign in or access any repositories, but all of their data
remains.
Blocking a 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 e8f80cfb40f..cd1f20a2f4e 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
@@ -288,6 +288,21 @@ When this ability is disabled, GitLab administrators can still use the
[Admin Area](../index.md#administering-users) or the
[API](../../../api/users.md#user-modification) to update usernames.
+## Prevent users from creating top-level groups
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367754) in GitLab 15.5.
+
+By default, new users can create top-level groups. GitLab administrators can prevent users from creating top-level groups:
+
+- In GitLab 15.5 and later, using either:
+ - The GitLab UI using the steps in this section.
+ - The [application setting API](../../../api/settings.md#change-application-settings).
+- In GitLab 15.4 and earlier, a [configuration file](../../../administration/user_settings.md#use-configuration-files-to-prevent-new-users-from-creating-top-level-groups).
+
+1. On the top bar, select **Main menu > Admin**.
+1. On the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Clear the **Allow users to create top-level groups** checkbox.
+
## Troubleshooting
### 413 Request Entity Too Large
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index dab3c78d9d1..afc9a006b39 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -1,7 +1,7 @@
---
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -70,7 +70,9 @@ runner settings:
To view the rendered details:
-1. On the top bar, select **Main menu > Projects** or **Main menu > Groups** and find your project or group.
+1. On the top bar, select **Main menu**, and:
+ - For a project, select ***Projects** and find your project.
+ - For a group, select **Groups** and find your group.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Runners**.
@@ -242,7 +244,7 @@ To enable or disable the banner:
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/352316) from GitLab Premium to GitLab Ultimate in 15.0.
NOTE:
-An alternative [compliance solution](../../project/settings/index.md#compliance-pipeline-configuration)
+An alternative [compliance solution](../../group/manage.md#configure-a-compliance-pipeline)
is available. We recommend this alternative solution because it provides greater flexibility,
allowing required pipelines to be assigned to specific compliance framework labels.
@@ -326,10 +328,8 @@ To set the maximum file size:
## Prevent users from registering runners
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22225) in GitLab 14.1.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../feature_flags.md) named `runner_registration_control`. On GitLab.com, this feature is not available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22225) in GitLab 14.1.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/368008) in GitLab 15.5.
GitLab administrators can adjust who is allowed to register runners, by showing and hiding areas of the UI.
diff --git a/doc/user/admin_area/settings/deprecated_api_rate_limits.md b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
index 7298d55b051..279cac95fc9 100644
--- a/doc/user/admin_area/settings/deprecated_api_rate_limits.md
+++ b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -37,7 +37,7 @@ To override the general user and IP rate limits for requests to deprecated API e
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > Network**.
1. Expand **Deprecated API Rate Limits**.
-1. Select the check boxes for the types of rate limits you want to enable:
+1. Select the checkboxes for the types of rate limits you want to enable:
- **Unauthenticated API request rate limit**
- **Authenticated API request rate limit**
1. _If you enabled unauthenticated API request rate limits:_
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 96fab153e85..6a7c01ff98b 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Email **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index 9db85eb6ea8..62d3d713616 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# External authorization control **(FREE SELF)**
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 963bca096a4..e5f5064304c 100644
--- a/doc/user/admin_area/settings/files_api_rate_limits.md
+++ b/doc/user/admin_area/settings/files_api_rate_limits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -33,7 +33,7 @@ To override the general user and IP rate limits for requests to the Repository f
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > Network**.
1. Expand **Files API Rate Limits**.
-1. Select the check boxes for the types of rate limits you want to enable:
+1. Select the checkboxes for the types of rate limits you want to enable:
- **Unauthenticated API request rate limit**
- **Authenticated API request rate limit**
1. _If you enabled unauthenticated API request rate limits:_
diff --git a/doc/user/admin_area/settings/floc.md b/doc/user/admin_area/settings/floc.md
index b7d3d8bfa20..08f3e8c09b2 100644
--- a/doc/user/admin_area/settings/floc.md
+++ b/doc/user/admin_area/settings/floc.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Federated Learning of Cohorts (FLoC) **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/git_lfs_rate_limits.md b/doc/user/admin_area/settings/git_lfs_rate_limits.md
index 519bbbef4e4..e0476f1e333 100644
--- a/doc/user/admin_area/settings/git_lfs_rate_limits.md
+++ b/doc/user/admin_area/settings/git_lfs_rate_limits.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/gitaly_timeouts.md b/doc/user/admin_area/settings/gitaly_timeouts.md
index dcf7574136a..d18fe0d74cd 100644
--- a/doc/user/admin_area/settings/gitaly_timeouts.md
+++ b/doc/user/admin_area/settings/gitaly_timeouts.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Gitaly timeouts **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/help_page.md b/doc/user/admin_area/settings/help_page.md
index 38161d0607c..a4072f8680b 100644
--- a/doc/user/admin_area/settings/help_page.md
+++ b/doc/user/admin_area/settings/help_page.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/user/admin_area/settings/import_export_rate_limits.md b/doc/user/admin_area/settings/import_export_rate_limits.md
index cfe4f49388e..acf82360042 100644
--- a/doc/user/admin_area/settings/import_export_rate_limits.md
+++ b/doc/user/admin_area/settings/import_export_rate_limits.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits for imports and exports of project and groups **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/incident_management_rate_limits.md b/doc/user/admin_area/settings/incident_management_rate_limits.md
index f9e91d26db5..295569dafee 100644
--- a/doc/user/admin_area/settings/incident_management_rate_limits.md
+++ b/doc/user/admin_area/settings/incident_management_rate_limits.md
@@ -2,7 +2,7 @@
type: reference
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Incident management rate limits **(ULTIMATE SELF)**
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 7a63f2059ba..1bdacf486a2 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index
---
diff --git a/doc/user/admin_area/settings/instance_template_repository.md b/doc/user/admin_area/settings/instance_template_repository.md
index 0d63fe5db7f..b74f4f68230 100644
--- a/doc/user/admin_area/settings/instance_template_repository.md
+++ b/doc/user/admin_area/settings/instance_template_repository.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/admin_area/settings/package_registry_rate_limits.md b/doc/user/admin_area/settings/package_registry_rate_limits.md
index 62cddd2781c..7e0c3482e3e 100644
--- a/doc/user/admin_area/settings/package_registry_rate_limits.md
+++ b/doc/user/admin_area/settings/package_registry_rate_limits.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index 58afc6a104c..5be9081d9b2 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project integration management **(FREE)**
@@ -122,7 +122,7 @@ Resetting a group-level default setting removes integrations that use default se
1. Navigate to **Project > Settings > Integrations**.
1. Choose the integration you want to enable or update.
-1. From the drop-down, select **Use default settings**.
+1. From the dropdown list, select **Use default settings**.
1. Ensure the toggle is set to **Enable integration**.
1. Select **Save changes**.
@@ -130,6 +130,6 @@ Resetting a group-level default setting removes integrations that use default se
1. Navigate to project or group's **Settings > Integrations**.
1. Choose the integration you want to enable or update.
-1. From the drop-down, select **Use custom settings**.
+1. From the dropdown list, select **Use custom settings**.
1. Ensure the toggle is set to **Enable integration** and enter all required settings.
1. Select **Save changes**.
diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md
index e686c65fe9a..4080ee6a540 100644
--- a/doc/user/admin_area/settings/protected_paths.md
+++ b/doc/user/admin_area/settings/protected_paths.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/push_event_activities_limit.md b/doc/user/admin_area/settings/push_event_activities_limit.md
index cd982bb4aa3..0c3f299e9ec 100644
--- a/doc/user/admin_area/settings/push_event_activities_limit.md
+++ b/doc/user/admin_area/settings/push_event_activities_limit.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
index 8d08da8246a..3c6fd4b1e45 100644
--- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits on issue creation **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
index f55c2f3bd4a..8465dccdbf3 100644
--- a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits on note creation **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md
index ba383d74701..820f7eaf854 100644
--- a/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md
@@ -2,7 +2,7 @@
type: reference
stage: Verify
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits on pipeline creation **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/rate_limit_on_users_api.md b/doc/user/admin_area/settings/rate_limit_on_users_api.md
index 9792fd1000d..f61c381a4fb 100644
--- a/doc/user/admin_area/settings/rate_limit_on_users_api.md
+++ b/doc/user/admin_area/settings/rate_limit_on_users_api.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits on Users API **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
index cb3ca0fe756..7e262c45f48 100644
--- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/sidekiq_job_limits.md b/doc/user/admin_area/settings/sidekiq_job_limits.md
index c1990572aee..7a437d877ca 100644
--- a/doc/user/admin_area/settings/sidekiq_job_limits.md
+++ b/doc/user/admin_area/settings/sidekiq_job_limits.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index bdffe87b75c..320768e6e5a 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sign-in restrictions **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index a0ec964e8db..28fb188731b 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index d26ace161bb..28fe352c684 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 59c100dc016..fbd282ed5ad 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index ad018abf809..fb027b462df 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -1,7 +1,7 @@
---
stage: Analytics
group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Usage statistics **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
index 86676e4a63e..7431fc329d1 100644
--- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md
+++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -109,7 +109,7 @@ attached into the response headers.
| `RateLimit-Observed` | `67` | Number of requests associated to the client in the time window. |
| `RateLimit-Remaining` | `0` | Remaining quota in the time window. The result of `RateLimit-Limit` - `RateLimit-Observed`. |
| `RateLimit-Reset` | `1609844400` | [Unix time](https://en.wikipedia.org/wiki/Unix_time)-formatted time when the request quota is reset. |
-| `RateLimit-ResetTime` | `Tue, 05 Jan 2021 11:00:00 GMT` | [RFC2616](https://tools.ietf.org/html/rfc2616#section-3.3.1)-formatted date and time when the request quota is reset. |
+| `RateLimit-ResetTime` | `Tue, 05 Jan 2021 11:00:00 GMT` | [RFC2616](https://www.rfc-editor.org/rfc/rfc2616#section-3.3.1)-formatted date and time when the request quota is reset. |
| `Retry-After` | `30` | Remaining duration **in seconds** until the quota is reset. This is a [standard HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After). |
## Use an HTTP header to bypass rate limiting
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 87c24f04a1c..d3132ae03c6 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md
index 816e629f496..c6d4f0b8e00 100644
--- a/doc/user/admin_area/user_cohorts.md
+++ b/doc/user/admin_area/user_cohorts.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cohorts **(FREE SELF)**
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index b92d68222f5..de9275b8599 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# CI/CD analytics **(FREE)**
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index dd985b6b090..86f1e24429b 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -1,8 +1,8 @@
---
description: "Learn how long your open merge requests have spent in code review, and what distinguishes the longest-running." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index 41547430e88..56adbff9f59 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Analyze GitLab usage **(FREE)**
@@ -77,8 +77,13 @@ To retrieve metrics for deployment frequency, use the [GraphQL](../../api/graphq
### Lead time for changes
-Lead time for changes measures the time to deliver a feature once it has been developed,
-as described in [Measuring DevOps Performance](https://devops.com/measuring-devops-performance/).
+DORA Lead time for changes measures the time to successfully deliver a feature into production.
+This metric reflects the efficiency of CI/CD pipelines.
+
+In GitLab, Lead time for changes calculates the median time it takes for a merge request to get merged into production.
+We measure "FROM code committed TO code successfully running in production" without adding the "coding_time" to the calculation.
+
+Over time, the lead time for changes should decrease, while your team's performance should increase.
Lead time for changes displays in several charts:
@@ -88,6 +93,9 @@ Lead time for changes displays in several charts:
To retrieve metrics for lead time for changes, use the [GraphQL](../../api/graphql/reference/index.md) or the [REST](../../api/dora/metrics.md) APIs.
+- The definition of lead time for change can vary widely, which often creates confusion within the industry.
+- "Lead time for changes" is not the same as "Lead time". In the value stream, "Lead time" measures the time it takes for work on issue to move from the moment it's requested (Issue created) to the time it's fulfilled and delivered (Issue closed).
+
### Time to restore service
Time to restore service measures how long it takes an organization to recover from a failure in production.
diff --git a/doc/user/analytics/issue_analytics.md b/doc/user/analytics/issue_analytics.md
index 86ae45a02b8..71ce13a725e 100644
--- a/doc/user/analytics/issue_analytics.md
+++ b/doc/user/analytics/issue_analytics.md
@@ -1,8 +1,8 @@
---
type: reference
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue analytics for projects **(PREMIUM)**
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 4f40575a4ef..1d1127c3d9f 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -1,8 +1,8 @@
---
description: "Merge request analytics help you understand the efficiency of your code review process, and the productivity of your team." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request analytics **(PREMIUM)**
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index f0841dc979b..08bb579fd0a 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Productivity analytics **(PREMIUM)**
diff --git a/doc/user/analytics/repository_analytics.md b/doc/user/analytics/repository_analytics.md
index 7723da7397d..b434221b887 100644
--- a/doc/user/analytics/repository_analytics.md
+++ b/doc/user/analytics/repository_analytics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository analytics for projects **(FREE)**
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index d5756c5f822..ab68c897da8 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Value stream analytics for projects **(FREE)**
diff --git a/doc/user/application_security/api_fuzzing/create_har_files.md b/doc/user/application_security/api_fuzzing/create_har_files.md
index bc987c56fe8..445bcfb0444 100644
--- a/doc/user/application_security/api_fuzzing/create_har_files.md
+++ b/doc/user/application_security/api_fuzzing/create_har_files.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 8e371ed4dc6..d542c2d4be5 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -1093,6 +1093,7 @@ profile increases as the number of tests increases.
| `SECURE_ANALYZERS_PREFIX` | Specify the Docker registry base address from which to download the analyzer. |
| `FUZZAPI_VERSION` | Specify API Fuzzing container version. Defaults to `2`. |
| `FUZZAPI_IMAGE_SUFFIX` | Specify a container image suffix. Defaults to none. |
+| `FUZZAPI_API_PORT` | Specify the communication port number used by API Fuzzing engine. Defaults to `5500`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367734) in GitLab 15.5. |
| `FUZZAPI_TARGET_URL` | Base URL of API testing target. |
| `FUZZAPI_CONFIG` | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/276395) in GitLab 13.12, replaced with default `.gitlab/gitlab-api-fuzzing-config.yml`. API Fuzzing configuration file. |
|[`FUZZAPI_PROFILE`](#api-fuzzing-profiles) | Configuration profile to use during testing. Defaults to `Quick-10`. |
@@ -1109,7 +1110,6 @@ profile increases as the number of tests increases.
|[`FUZZAPI_GRAPHQL_SCHEMA`](#graphql-schema) | A URL or filename for a GraphQL schema in JSON format. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352780) in GitLab 15.4. |
|[`FUZZAPI_POSTMAN_COLLECTION`](#postman-collection) | Postman Collection file. |
|[`FUZZAPI_POSTMAN_COLLECTION_VARIABLES`](#postman-variables) | Path to a JSON file to extract Postman variable values. The support for comma-separated (`,`) files was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356312) in GitLab 15.1. |
-|[`FUZZAPI_POSTMAN_COLLECTION_VARIABLES`](#postman-variables) | Path to a JSON file to extract Postman variable values. |
|[`FUZZAPI_OVERRIDES_FILE`](#overrides) | Path to a JSON file containing overrides. |
|[`FUZZAPI_OVERRIDES_ENV`](#overrides) | JSON string containing headers to override. |
|[`FUZZAPI_OVERRIDES_CMD`](#overrides) | Overrides command. |
@@ -1386,7 +1386,7 @@ variables:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.8.
-By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `FUZZAPI_OVERRIDES_CMD_VERBOSE` to any value in order to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
+By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `FUZZAPI_OVERRIDES_CMD_VERBOSE` to any value to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
It is also possible to write messages from your script to a log file that is collected when the job completes or fails. The log file must be created in a specific location and follow a naming convention.
@@ -2226,6 +2226,43 @@ If the issue is occurring with versions v1.6.196 or greater, contact Support and
1. The `gl-api-security-scanner.log` file available as a job artifact. In the right-hand panel of the job details page, select the **Browse** button.
1. The `apifuzzer_fuzz` job definition from your `.gitlab-ci.yml` file.
+### `Failed to start session with scanner. Please retry, and if the problem persists reach out to support.`
+
+The API Fuzzing engine outputs an error message when it cannot establish a connection with the scanner application component. The error message is shown in the job output window of the `apifuzzer_fuzz` job. A common cause for this issue is that the background component cannot use the selected port as it's already in use. This error can occur intermittently if timing plays a part (race condition). This issue occurs most often with Kubernetes environments when other services are mapped into the container causing port conflicts.
+
+Before proceeding with a solution, it is important to confirm that the error message was produced because the port was already taken. To confirm this was the cause:
+
+1. Go to the job console.
+
+1. Look for the artifact `gl-api-security-scanner.log`. You can either download all artifacts by selecting **Download** and then search for the file, or directly start searching by selecting **Browse**.
+
+1. Open the file `gl-api-security-scanner.log` in a text editor.
+
+1. If the error message was produced because the port was already taken, you should see in the file a message like the following:
+
+- In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/367734):
+
+ ```log
+ Failed to bind to address http://127.0.0.1:5500: address already in use.
+ ```
+
+- In GitLab 15.4 and earlier:
+
+ ```log
+ Failed to bind to address http://[::]:5000: address already in use.
+ ```
+
+The text `http://[::]:5000` in the previous message could be different in your case, for instance it could be `http://[::]:5500` or `http://127.0.0.1:5500`. As long as the remaining parts of the error message are the same, it is safe to assume the port was already taken.
+
+If you did not find evidence that the port was already taken, check other troubleshooting sections which also address the same error message shown in the job console output. If there are no more options, feel free to [get support or request an improvement](#get-support-or-request-an-improvement) through the proper channels.
+
+Once you have confirmed the issue was produced because the port was already taken. Then, [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/367734) introduced the configuration variable `FUZZAPI_API_PORT`. This configuration variable allows setting a fixed port number for the scanner background component.
+
+**Solution**
+
+1. Ensure your `.gitlab-ci.yml` file defines the configuration variable `FUZZAPI_API_PORT`.
+1. Update the value of `FUZZAPI_API_PORT` to any available port number greater than 1024. We recommend checking that the new value is not in used by GitLab. See the full list of ports used by GitLab in [Package defaults](../../../administration/package_information/defaults.md#ports)
+
### `Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema`
At the start of an API Fuzzing job the OpenAPI Specification is validated against the [published schema](https://github.com/OAI/OpenAPI-Specification/tree/master/schemas). This error is shown when the provided OpenAPI Specification has validation errors. Errors can be introduced when creating an OpenAPI Specification manually, and also when the schema is generated.
diff --git a/doc/user/application_security/cluster_image_scanning/index.md b/doc/user/application_security/cluster_image_scanning/index.md
deleted file mode 100644
index e7a59d70b25..00000000000
--- a/doc/user/application_security/cluster_image_scanning/index.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../clusters/agent/vulnerabilities.md'
-remove_date: '2022-08-19'
----
-
-This document was moved to [another location](../../clusters/agent/vulnerabilities.md).
-
-<!-- This redirect file can be deleted after <2022-08-19>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index 32a523a1871..5eb1b93eb76 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Security Configuration **(FREE)**
@@ -19,12 +19,23 @@ The Security Configuration page lists the following for the security testing and
- Whether or not it is available.
- A configuration button or a link to its configuration guide.
-The status of each security control is determined by the project's latest default branch
-[CI pipeline](../../../ci/pipelines/index.md).
-If a job with the expected security report artifact exists in the pipeline, the feature's status is
-_enabled_.
+To determine the status of each security control, GitLab checks for a [CI/CD pipeline](../../../ci/pipelines/index.md)
+in the most recent commit on the default branch.
-If the latest pipeline used [Auto DevOps](../../../topics/autodevops/index.md),
+If GitLab finds a CI/CD pipeline, then it inspects each job in the `.gitlab-ci.yml` file.
+
+- If a job defines an [`artifacts:reports` keyword](../../../ci/yaml/artifacts_reports.md)
+ for a security scanner, then GitLab considers the security scanner enabled and shows the **Enabled** status.
+- If no jobs define an `artifacts:reports` keyword for a security scanner, then GitLab considers
+ the security scanner disabled and shows the **Not enabled** status.
+
+If GitLab does not find a CI/CD pipeline, then it considers all security scanners disabled and shows the **Not enabled** status.
+
+Failed pipelines and jobs are included in this process. If a scanner is configured but the job fails,
+that scanner is still considered enabled. This process also determines the scanners and statuses
+returned through the [API](../../../api/graphql/reference/index.md#securityscanners).
+
+If the latest pipeline uses [Auto DevOps](../../../topics/autodevops/index.md),
all security features are configured by default.
To view a project's security configuration:
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 961ccf6b563..f6bd6157a28 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Container Scanning **(FREE)**
@@ -446,7 +446,7 @@ 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:
+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://www.rfc-editor.org/rfc/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
```yaml
container_scanning:
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index bec242a0426..c04c07f561d 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Coverage-guided fuzz testing **(ULTIMATE)**
@@ -337,14 +337,14 @@ To use coverage fuzzing in an offline environment:
After a vulnerability is found, you can [address it](../vulnerabilities/index.md).
The merge request widget lists the vulnerability and contains a button for downloading the fuzzing
-artifacts. By clicking one of the detected vulnerabilities, you can see its details.
+artifacts. By selecting one of the detected vulnerabilities, you can see its details.
![Coverage Fuzzing Security Report](img/coverage_fuzzing_report_v13_6.png)
You can also view the vulnerability from the [Security Dashboard](../security_dashboard/index.md),
which shows an overview of all the security vulnerabilities in your groups, projects, and pipelines.
-Clicking the vulnerability opens a modal that provides additional information about the
+Selecting the vulnerability opens a modal that provides additional information about the
vulnerability:
<!-- vale gitlab.Acronyms = NO -->
diff --git a/doc/user/application_security/cve_id_request.md b/doc/user/application_security/cve_id_request.md
index 6f076bbe3f9..bbe97081a55 100644
--- a/doc/user/application_security/cve_id_request.md
+++ b/doc/user/application_security/cve_id_request.md
@@ -2,7 +2,7 @@
type: tutorial
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# CVE ID request **(FREE SAAS)**
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index e8373b0c0b7..5a4acc78728 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -19,7 +19,7 @@ ensuring DAST coverage.
The browser-based scanner works by loading the target application into a specially-instrumented
Chromium browser. A snapshot of the page is taken before a search to find any actions that a user
-might perform, such as clicking on a link or filling in a form. For each action found, the
+might perform, such as selecting on a link or filling in a form. For each action found, the
browser-based scanner executes it, takes a new snapshot, and determines what in the page changed
from the previous snapshot. Crawling continues by taking more snapshots and finding subsequent
actions. The benefit of scanning by following user actions in a browser is that the crawler can
@@ -64,7 +64,7 @@ The browser-based crawler can be configured using CI/CD variables.
| `DAST_BROWSER_EXCLUDED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. |
| `DAST_BROWSER_EXCLUDED_ELEMENTS` | selector | `a[href='2.html'],css:.no-follow` | Comma-separated list of selectors that are ignored when scanning. |
| `DAST_BROWSER_IGNORED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed but not reported against. |
-| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, clicking a link, or filling a form. |
+| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, selecting a link, or filling a form. |
| `DAST_BROWSER_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. |
| `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. |
@@ -193,3 +193,14 @@ The modules that can be configured for logging are as follows:
| `NAVDB` | Used for persistence mechanisms to store navigation entries. |
| `REPT` | Used for generating reports. |
| `STAT` | Used for general statistics while running the scan. |
+
+### Artifacts
+
+DAST's browser-based analyzer generates artifacts that can help you understand how the scanner works.
+Using the latest version of the DAST [template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml) these artifacts are exposed for download by default.
+
+The list of artifacts includes the following files:
+
+- `gl-dast-debug-auth-report.html`
+- `gl-dast-debug-crawl-report.html`
+- `gl-dast-crawl-graph.svg`
diff --git a/doc/user/application_security/dast/checks/1004.1.md b/doc/user/application_security/dast/checks/1004.1.md
index 40139f2aa8a..737e9dcfd62 100644
--- a/doc/user/application_security/dast/checks/1004.1.md
+++ b/doc/user/application_security/dast/checks/1004.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sensitive cookie without HttpOnly attribute
diff --git a/doc/user/application_security/dast/checks/16.1.md b/doc/user/application_security/dast/checks/16.1.md
index 157b2b96ed4..c225e3ce368 100644
--- a/doc/user/application_security/dast/checks/16.1.md
+++ b/doc/user/application_security/dast/checks/16.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Missing Content-Type header
diff --git a/doc/user/application_security/dast/checks/16.10.md b/doc/user/application_security/dast/checks/16.10.md
index 67368d80022..9d6a7f85e20 100644
--- a/doc/user/application_security/dast/checks/16.10.md
+++ b/doc/user/application_security/dast/checks/16.10.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Content-Security-Policy violations
diff --git a/doc/user/application_security/dast/checks/16.2.md b/doc/user/application_security/dast/checks/16.2.md
index 484460b6642..a317b9418a1 100644
--- a/doc/user/application_security/dast/checks/16.2.md
+++ b/doc/user/application_security/dast/checks/16.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Server header exposes version information
@@ -41,4 +41,4 @@ the `Server` header.
- [CWE](https://cwe.mitre.org/data/definitions/16.html)
- [Apache ServerTokens](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
- [NGINX server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens)
-- [IIS 10 Remove Server Header](https://docs.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/#attributes)
+- [IIS 10 Remove Server Header](https://learn.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/#attributes)
diff --git a/doc/user/application_security/dast/checks/16.3.md b/doc/user/application_security/dast/checks/16.3.md
index e4fc2468dae..d9e6f6f8d92 100644
--- a/doc/user/application_security/dast/checks/16.3.md
+++ b/doc/user/application_security/dast/checks/16.3.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# X-Powered-By header exposes version information
diff --git a/doc/user/application_security/dast/checks/16.4.md b/doc/user/application_security/dast/checks/16.4.md
index 1f72a80cb29..e6b4ba8627f 100644
--- a/doc/user/application_security/dast/checks/16.4.md
+++ b/doc/user/application_security/dast/checks/16.4.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# X-Backend-Server header exposes server information
diff --git a/doc/user/application_security/dast/checks/16.5.md b/doc/user/application_security/dast/checks/16.5.md
index 28bb9f7ee4b..285cc753523 100644
--- a/doc/user/application_security/dast/checks/16.5.md
+++ b/doc/user/application_security/dast/checks/16.5.md
@@ -1,14 +1,14 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# AspNet header exposes version information
## Description
-The target website returns AspNet header(s) and version information of this website. By
+The target website returns AspNet headers and 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.
diff --git a/doc/user/application_security/dast/checks/16.6.md b/doc/user/application_security/dast/checks/16.6.md
index ddd3a10c5f8..c6705b2ec7f 100644
--- a/doc/user/application_security/dast/checks/16.6.md
+++ b/doc/user/application_security/dast/checks/16.6.md
@@ -1,14 +1,14 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/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
+The target website returns AspNet headers 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.
diff --git a/doc/user/application_security/dast/checks/16.7.md b/doc/user/application_security/dast/checks/16.7.md
index a052149ee4d..cef13c9663f 100644
--- a/doc/user/application_security/dast/checks/16.7.md
+++ b/doc/user/application_security/dast/checks/16.7.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Strict-Transport-Security header missing or invalid
diff --git a/doc/user/application_security/dast/checks/16.8.md b/doc/user/application_security/dast/checks/16.8.md
index c9beba4544e..07bd2a6842f 100644
--- a/doc/user/application_security/dast/checks/16.8.md
+++ b/doc/user/application_security/dast/checks/16.8.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Content-Security-Policy analysis
diff --git a/doc/user/application_security/dast/checks/16.9.md b/doc/user/application_security/dast/checks/16.9.md
index c3e4431e415..b0ba502b578 100644
--- a/doc/user/application_security/dast/checks/16.9.md
+++ b/doc/user/application_security/dast/checks/16.9.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Content-Security-Policy-Report-Only analysis
diff --git a/doc/user/application_security/dast/checks/200.1.md b/doc/user/application_security/dast/checks/200.1.md
index fcd329c3f2b..c7c1e938678 100644
--- a/doc/user/application_security/dast/checks/200.1.md
+++ b/doc/user/application_security/dast/checks/200.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of sensitive information to an unauthorized actor (private IP address)
diff --git a/doc/user/application_security/dast/checks/209.1.md b/doc/user/application_security/dast/checks/209.1.md
index f2713a70afd..181595a279e 100644
--- a/doc/user/application_security/dast/checks/209.1.md
+++ b/doc/user/application_security/dast/checks/209.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Generation of error message containing sensitive information
diff --git a/doc/user/application_security/dast/checks/209.2.md b/doc/user/application_security/dast/checks/209.2.md
index 2060bb1802b..9906347f7b9 100644
--- a/doc/user/application_security/dast/checks/209.2.md
+++ b/doc/user/application_security/dast/checks/209.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Generation of database error message containing sensitive information
diff --git a/doc/user/application_security/dast/checks/287.1.md b/doc/user/application_security/dast/checks/287.1.md
index 06b7e7b4b2e..d3d16d47677 100644
--- a/doc/user/application_security/dast/checks/287.1.md
+++ b/doc/user/application_security/dast/checks/287.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Insecure authentication over HTTP (Basic Authentication)
diff --git a/doc/user/application_security/dast/checks/287.2.md b/doc/user/application_security/dast/checks/287.2.md
index 2215b72f47a..9da22c66f84 100644
--- a/doc/user/application_security/dast/checks/287.2.md
+++ b/doc/user/application_security/dast/checks/287.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Insecure authentication over HTTP (Digest Authentication)
diff --git a/doc/user/application_security/dast/checks/319.1.md b/doc/user/application_security/dast/checks/319.1.md
index d598fb70ce3..6c68344505a 100644
--- a/doc/user/application_security/dast/checks/319.1.md
+++ b/doc/user/application_security/dast/checks/319.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Mixed Content
diff --git a/doc/user/application_security/dast/checks/352.1.md b/doc/user/application_security/dast/checks/352.1.md
index 4daba908331..46e3bb32ebe 100644
--- a/doc/user/application_security/dast/checks/352.1.md
+++ b/doc/user/application_security/dast/checks/352.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Absence of anti-CSRF tokens
diff --git a/doc/user/application_security/dast/checks/359.1.md b/doc/user/application_security/dast/checks/359.1.md
index 076ab2da0d5..f7d9069731c 100644
--- a/doc/user/application_security/dast/checks/359.1.md
+++ b/doc/user/application_security/dast/checks/359.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of Private Personal Information (PII) to an unauthorized actor (credit card)
diff --git a/doc/user/application_security/dast/checks/359.2.md b/doc/user/application_security/dast/checks/359.2.md
index 2c59b5e321f..d5428718171 100644
--- a/doc/user/application_security/dast/checks/359.2.md
+++ b/doc/user/application_security/dast/checks/359.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of Private Personal Information (PII) to an unauthorized actor (United States social security number)
diff --git a/doc/user/application_security/dast/checks/548.1.md b/doc/user/application_security/dast/checks/548.1.md
index 1da2ce58247..b6907db5928 100644
--- a/doc/user/application_security/dast/checks/548.1.md
+++ b/doc/user/application_security/dast/checks/548.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of information through directory listing
@@ -42,4 +42,4 @@ indexing.
- [CWE](https://cwe.mitre.org/data/definitions/548.html)
- [Apache Options](https://httpd.apache.org/docs/2.4/mod/core.html#options)
- [NGINX autoindex](https://nginx.org/en/docs/http/ngx_http_autoindex_module.html)
-- [IIS directoryBrowse element](https://docs.microsoft.com/en-us/iis/configuration/system.webserver/directorybrowse)
+- [IIS directoryBrowse element](https://learn.microsoft.com/en-us/iis/configuration/system.webserver/directorybrowse)
diff --git a/doc/user/application_security/dast/checks/598.1.md b/doc/user/application_security/dast/checks/598.1.md
index 817e20ec413..21a28705c4e 100644
--- a/doc/user/application_security/dast/checks/598.1.md
+++ b/doc/user/application_security/dast/checks/598.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use of GET request method with sensitive query strings (session ID)
diff --git a/doc/user/application_security/dast/checks/598.2.md b/doc/user/application_security/dast/checks/598.2.md
index 05d04b71cf0..2b7204b58df 100644
--- a/doc/user/application_security/dast/checks/598.2.md
+++ b/doc/user/application_security/dast/checks/598.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use of GET request method with sensitive query strings (password)
diff --git a/doc/user/application_security/dast/checks/598.3.md b/doc/user/application_security/dast/checks/598.3.md
index be17fdcaef6..9a2e507af18 100644
--- a/doc/user/application_security/dast/checks/598.3.md
+++ b/doc/user/application_security/dast/checks/598.3.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use of GET request method with sensitive query strings (Authorization header details)
diff --git a/doc/user/application_security/dast/checks/601.1.md b/doc/user/application_security/dast/checks/601.1.md
index c51b00cdd36..f9ca304dea8 100644
--- a/doc/user/application_security/dast/checks/601.1.md
+++ b/doc/user/application_security/dast/checks/601.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# URL redirection to untrusted site ('open redirect')
diff --git a/doc/user/application_security/dast/checks/614.1.md b/doc/user/application_security/dast/checks/614.1.md
index d5c7476716f..00f51ceea06 100644
--- a/doc/user/application_security/dast/checks/614.1.md
+++ b/doc/user/application_security/dast/checks/614.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sensitive cookie without Secure attribute
diff --git a/doc/user/application_security/dast/checks/693.1.md b/doc/user/application_security/dast/checks/693.1.md
index d3f4c72c676..7dc09d3f2d7 100644
--- a/doc/user/application_security/dast/checks/693.1.md
+++ b/doc/user/application_security/dast/checks/693.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Missing X-Content-Type-Options: nosniff
diff --git a/doc/user/application_security/dast/checks/798.1.md b/doc/user/application_security/dast/checks/798.1.md
index 819ae92cfdc..2697cd1b1ec 100644
--- a/doc/user/application_security/dast/checks/798.1.md
+++ b/doc/user/application_security/dast/checks/798.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Adafruit API Key
diff --git a/doc/user/application_security/dast/checks/798.10.md b/doc/user/application_security/dast/checks/798.10.md
index 14723c81f17..ceee9c28fd1 100644
--- a/doc/user/application_security/dast/checks/798.10.md
+++ b/doc/user/application_security/dast/checks/798.10.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Asana Client Secret
diff --git a/doc/user/application_security/dast/checks/798.100.md b/doc/user/application_security/dast/checks/798.100.md
index 07bd24211c7..2c14dab9f30 100644
--- a/doc/user/application_security/dast/checks/798.100.md
+++ b/doc/user/application_security/dast/checks/798.100.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Sendbird Access Token
diff --git a/doc/user/application_security/dast/checks/798.101.md b/doc/user/application_security/dast/checks/798.101.md
index ea102147100..e4c277c1bb5 100644
--- a/doc/user/application_security/dast/checks/798.101.md
+++ b/doc/user/application_security/dast/checks/798.101.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token SendGrid API token
diff --git a/doc/user/application_security/dast/checks/798.102.md b/doc/user/application_security/dast/checks/798.102.md
index 8a40475190a..303010d4bc5 100644
--- a/doc/user/application_security/dast/checks/798.102.md
+++ b/doc/user/application_security/dast/checks/798.102.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Sendinblue API token
diff --git a/doc/user/application_security/dast/checks/798.103.md b/doc/user/application_security/dast/checks/798.103.md
index 3d91f7f3b80..0524a50be7b 100644
--- a/doc/user/application_security/dast/checks/798.103.md
+++ b/doc/user/application_security/dast/checks/798.103.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Sentry Access Token
diff --git a/doc/user/application_security/dast/checks/798.104.md b/doc/user/application_security/dast/checks/798.104.md
index 316998615ff..6e806e8cf6e 100644
--- a/doc/user/application_security/dast/checks/798.104.md
+++ b/doc/user/application_security/dast/checks/798.104.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Shippo API token
diff --git a/doc/user/application_security/dast/checks/798.105.md b/doc/user/application_security/dast/checks/798.105.md
index 20618a9d555..162d8533320 100644
--- a/doc/user/application_security/dast/checks/798.105.md
+++ b/doc/user/application_security/dast/checks/798.105.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Shopify access token
diff --git a/doc/user/application_security/dast/checks/798.106.md b/doc/user/application_security/dast/checks/798.106.md
index 4f552302e85..177803b9196 100644
--- a/doc/user/application_security/dast/checks/798.106.md
+++ b/doc/user/application_security/dast/checks/798.106.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Shopify custom access token
diff --git a/doc/user/application_security/dast/checks/798.107.md b/doc/user/application_security/dast/checks/798.107.md
index 2a5961b3905..5241a6e9d09 100644
--- a/doc/user/application_security/dast/checks/798.107.md
+++ b/doc/user/application_security/dast/checks/798.107.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Shopify private app access token
diff --git a/doc/user/application_security/dast/checks/798.108.md b/doc/user/application_security/dast/checks/798.108.md
index 23968bcf660..c6863ac4757 100644
--- a/doc/user/application_security/dast/checks/798.108.md
+++ b/doc/user/application_security/dast/checks/798.108.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Shopify shared secret
diff --git a/doc/user/application_security/dast/checks/798.109.md b/doc/user/application_security/dast/checks/798.109.md
index 57d6823d8a9..bfb82e6640f 100644
--- a/doc/user/application_security/dast/checks/798.109.md
+++ b/doc/user/application_security/dast/checks/798.109.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Slack token
diff --git a/doc/user/application_security/dast/checks/798.11.md b/doc/user/application_security/dast/checks/798.11.md
index b12f86ba800..fd54560db79 100644
--- a/doc/user/application_security/dast/checks/798.11.md
+++ b/doc/user/application_security/dast/checks/798.11.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Atlassian API token
diff --git a/doc/user/application_security/dast/checks/798.110.md b/doc/user/application_security/dast/checks/798.110.md
index 8ac7a8a4be2..7a68284fae4 100644
--- a/doc/user/application_security/dast/checks/798.110.md
+++ b/doc/user/application_security/dast/checks/798.110.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Slack Webhook
diff --git a/doc/user/application_security/dast/checks/798.111.md b/doc/user/application_security/dast/checks/798.111.md
index ff05dcfe55b..0804613ee48 100644
--- a/doc/user/application_security/dast/checks/798.111.md
+++ b/doc/user/application_security/dast/checks/798.111.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Stripe
diff --git a/doc/user/application_security/dast/checks/798.112.md b/doc/user/application_security/dast/checks/798.112.md
index 4f5f89dab9c..2570e39357a 100644
--- a/doc/user/application_security/dast/checks/798.112.md
+++ b/doc/user/application_security/dast/checks/798.112.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Square Access Token
diff --git a/doc/user/application_security/dast/checks/798.113.md b/doc/user/application_security/dast/checks/798.113.md
index 3f8d1a88ec0..c445a9f48b0 100644
--- a/doc/user/application_security/dast/checks/798.113.md
+++ b/doc/user/application_security/dast/checks/798.113.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Squarespace Access Token
diff --git a/doc/user/application_security/dast/checks/798.114.md b/doc/user/application_security/dast/checks/798.114.md
index 0b8235af8c7..7afe862231d 100644
--- a/doc/user/application_security/dast/checks/798.114.md
+++ b/doc/user/application_security/dast/checks/798.114.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token SumoLogic Access ID
diff --git a/doc/user/application_security/dast/checks/798.115.md b/doc/user/application_security/dast/checks/798.115.md
index 052502ea962..dc305c61c30 100644
--- a/doc/user/application_security/dast/checks/798.115.md
+++ b/doc/user/application_security/dast/checks/798.115.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token SumoLogic Access Token
diff --git a/doc/user/application_security/dast/checks/798.116.md b/doc/user/application_security/dast/checks/798.116.md
index 7b1f0eb907d..54d97f90b47 100644
--- a/doc/user/application_security/dast/checks/798.116.md
+++ b/doc/user/application_security/dast/checks/798.116.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Travis CI Access Token
diff --git a/doc/user/application_security/dast/checks/798.117.md b/doc/user/application_security/dast/checks/798.117.md
index 5cd9817795a..ff4b1299d32 100644
--- a/doc/user/application_security/dast/checks/798.117.md
+++ b/doc/user/application_security/dast/checks/798.117.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twilio API Key
diff --git a/doc/user/application_security/dast/checks/798.118.md b/doc/user/application_security/dast/checks/798.118.md
index a74233429df..dc4121e23ba 100644
--- a/doc/user/application_security/dast/checks/798.118.md
+++ b/doc/user/application_security/dast/checks/798.118.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitch API token
diff --git a/doc/user/application_security/dast/checks/798.119.md b/doc/user/application_security/dast/checks/798.119.md
index 80fada87b1c..df470195454 100644
--- a/doc/user/application_security/dast/checks/798.119.md
+++ b/doc/user/application_security/dast/checks/798.119.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitter API Key
diff --git a/doc/user/application_security/dast/checks/798.12.md b/doc/user/application_security/dast/checks/798.12.md
index 6f8d0c83a94..8cfe5f1cf2f 100644
--- a/doc/user/application_security/dast/checks/798.12.md
+++ b/doc/user/application_security/dast/checks/798.12.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token AWS
diff --git a/doc/user/application_security/dast/checks/798.120.md b/doc/user/application_security/dast/checks/798.120.md
index 639b5c6ffc2..986af1901a4 100644
--- a/doc/user/application_security/dast/checks/798.120.md
+++ b/doc/user/application_security/dast/checks/798.120.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitter API Secret
diff --git a/doc/user/application_security/dast/checks/798.121.md b/doc/user/application_security/dast/checks/798.121.md
index e574760baa2..c2301d49bbb 100644
--- a/doc/user/application_security/dast/checks/798.121.md
+++ b/doc/user/application_security/dast/checks/798.121.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitter Access Token
diff --git a/doc/user/application_security/dast/checks/798.122.md b/doc/user/application_security/dast/checks/798.122.md
index 9acb82a6062..442c1bd09ba 100644
--- a/doc/user/application_security/dast/checks/798.122.md
+++ b/doc/user/application_security/dast/checks/798.122.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitter Access Secret
diff --git a/doc/user/application_security/dast/checks/798.123.md b/doc/user/application_security/dast/checks/798.123.md
index 5d5c9df5f40..b21c00fb547 100644
--- a/doc/user/application_security/dast/checks/798.123.md
+++ b/doc/user/application_security/dast/checks/798.123.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Twitter Bearer Token
diff --git a/doc/user/application_security/dast/checks/798.124.md b/doc/user/application_security/dast/checks/798.124.md
index 4900ca44ba4..3d1e7875848 100644
--- a/doc/user/application_security/dast/checks/798.124.md
+++ b/doc/user/application_security/dast/checks/798.124.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Typeform API token
diff --git a/doc/user/application_security/dast/checks/798.125.md b/doc/user/application_security/dast/checks/798.125.md
index 1111ef91491..41217655721 100644
--- a/doc/user/application_security/dast/checks/798.125.md
+++ b/doc/user/application_security/dast/checks/798.125.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Yandex API Key
diff --git a/doc/user/application_security/dast/checks/798.126.md b/doc/user/application_security/dast/checks/798.126.md
index 6253f9a4a92..bfb48d4e3eb 100644
--- a/doc/user/application_security/dast/checks/798.126.md
+++ b/doc/user/application_security/dast/checks/798.126.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Yandex AWS Access Token
diff --git a/doc/user/application_security/dast/checks/798.127.md b/doc/user/application_security/dast/checks/798.127.md
index 86bb9613f16..8df930ffb07 100644
--- a/doc/user/application_security/dast/checks/798.127.md
+++ b/doc/user/application_security/dast/checks/798.127.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Yandex Access Token
diff --git a/doc/user/application_security/dast/checks/798.128.md b/doc/user/application_security/dast/checks/798.128.md
index 0db8cdd8005..2bee2604870 100644
--- a/doc/user/application_security/dast/checks/798.128.md
+++ b/doc/user/application_security/dast/checks/798.128.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Zendesk Secret Key
diff --git a/doc/user/application_security/dast/checks/798.13.md b/doc/user/application_security/dast/checks/798.13.md
index 8cf2f7c2895..83e45dedecb 100644
--- a/doc/user/application_security/dast/checks/798.13.md
+++ b/doc/user/application_security/dast/checks/798.13.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Bitbucket Client ID
diff --git a/doc/user/application_security/dast/checks/798.14.md b/doc/user/application_security/dast/checks/798.14.md
index 85b88660b5a..eb800c510c8 100644
--- a/doc/user/application_security/dast/checks/798.14.md
+++ b/doc/user/application_security/dast/checks/798.14.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Bitbucket Client Secret
diff --git a/doc/user/application_security/dast/checks/798.15.md b/doc/user/application_security/dast/checks/798.15.md
index 51f2fae0021..f9e01799b63 100644
--- a/doc/user/application_security/dast/checks/798.15.md
+++ b/doc/user/application_security/dast/checks/798.15.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Bittrex Access Key
diff --git a/doc/user/application_security/dast/checks/798.16.md b/doc/user/application_security/dast/checks/798.16.md
index 872a97e70ea..92fbb490d12 100644
--- a/doc/user/application_security/dast/checks/798.16.md
+++ b/doc/user/application_security/dast/checks/798.16.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Bittrex Secret Key
diff --git a/doc/user/application_security/dast/checks/798.17.md b/doc/user/application_security/dast/checks/798.17.md
index 9e11af3bfe8..a020c55d2be 100644
--- a/doc/user/application_security/dast/checks/798.17.md
+++ b/doc/user/application_security/dast/checks/798.17.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Beamer API token
diff --git a/doc/user/application_security/dast/checks/798.18.md b/doc/user/application_security/dast/checks/798.18.md
index 71caa0a53ba..16b7e384462 100644
--- a/doc/user/application_security/dast/checks/798.18.md
+++ b/doc/user/application_security/dast/checks/798.18.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Codecov Access Token
diff --git a/doc/user/application_security/dast/checks/798.19.md b/doc/user/application_security/dast/checks/798.19.md
index 6cfbab0e9d1..6ec04f2a011 100644
--- a/doc/user/application_security/dast/checks/798.19.md
+++ b/doc/user/application_security/dast/checks/798.19.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Coinbase Access Token
diff --git a/doc/user/application_security/dast/checks/798.2.md b/doc/user/application_security/dast/checks/798.2.md
index 766f4c75973..18fe524cb08 100644
--- a/doc/user/application_security/dast/checks/798.2.md
+++ b/doc/user/application_security/dast/checks/798.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Adobe Client ID (OAuth Web)
diff --git a/doc/user/application_security/dast/checks/798.20.md b/doc/user/application_security/dast/checks/798.20.md
index 83651142912..22d750dfdfb 100644
--- a/doc/user/application_security/dast/checks/798.20.md
+++ b/doc/user/application_security/dast/checks/798.20.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Clojars API token
diff --git a/doc/user/application_security/dast/checks/798.21.md b/doc/user/application_security/dast/checks/798.21.md
index 93bf588c84b..e38a540a253 100644
--- a/doc/user/application_security/dast/checks/798.21.md
+++ b/doc/user/application_security/dast/checks/798.21.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Confluent Access Token
diff --git a/doc/user/application_security/dast/checks/798.22.md b/doc/user/application_security/dast/checks/798.22.md
index 7a8abbce7ba..55d39c47428 100644
--- a/doc/user/application_security/dast/checks/798.22.md
+++ b/doc/user/application_security/dast/checks/798.22.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Confluent Secret Key
diff --git a/doc/user/application_security/dast/checks/798.23.md b/doc/user/application_security/dast/checks/798.23.md
index f5460e98079..967e41d656d 100644
--- a/doc/user/application_security/dast/checks/798.23.md
+++ b/doc/user/application_security/dast/checks/798.23.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Contentful delivery API token
diff --git a/doc/user/application_security/dast/checks/798.24.md b/doc/user/application_security/dast/checks/798.24.md
index 7a01197a6b8..65db9b1f5d7 100644
--- a/doc/user/application_security/dast/checks/798.24.md
+++ b/doc/user/application_security/dast/checks/798.24.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Databricks API token
diff --git a/doc/user/application_security/dast/checks/798.25.md b/doc/user/application_security/dast/checks/798.25.md
index c5dcee20f61..db7a22c31e2 100644
--- a/doc/user/application_security/dast/checks/798.25.md
+++ b/doc/user/application_security/dast/checks/798.25.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Datadog Access Token
diff --git a/doc/user/application_security/dast/checks/798.26.md b/doc/user/application_security/dast/checks/798.26.md
index bfa5cb0588e..989a9787c04 100644
--- a/doc/user/application_security/dast/checks/798.26.md
+++ b/doc/user/application_security/dast/checks/798.26.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Discord API key
diff --git a/doc/user/application_security/dast/checks/798.27.md b/doc/user/application_security/dast/checks/798.27.md
index 1210d91e741..f17f6bf1c56 100644
--- a/doc/user/application_security/dast/checks/798.27.md
+++ b/doc/user/application_security/dast/checks/798.27.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Discord client ID
diff --git a/doc/user/application_security/dast/checks/798.28.md b/doc/user/application_security/dast/checks/798.28.md
index 5f4718d8eb7..6d063c39d2b 100644
--- a/doc/user/application_security/dast/checks/798.28.md
+++ b/doc/user/application_security/dast/checks/798.28.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Discord client secret
diff --git a/doc/user/application_security/dast/checks/798.29.md b/doc/user/application_security/dast/checks/798.29.md
index 90371a157a0..5c082b2aac0 100644
--- a/doc/user/application_security/dast/checks/798.29.md
+++ b/doc/user/application_security/dast/checks/798.29.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Doppler API token
diff --git a/doc/user/application_security/dast/checks/798.3.md b/doc/user/application_security/dast/checks/798.3.md
index 43d69b77337..e6cfb13d114 100644
--- a/doc/user/application_security/dast/checks/798.3.md
+++ b/doc/user/application_security/dast/checks/798.3.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Adobe Client Secret
diff --git a/doc/user/application_security/dast/checks/798.30.md b/doc/user/application_security/dast/checks/798.30.md
index db62b30b84b..618d2cdafdd 100644
--- a/doc/user/application_security/dast/checks/798.30.md
+++ b/doc/user/application_security/dast/checks/798.30.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Dropbox API secret
diff --git a/doc/user/application_security/dast/checks/798.31.md b/doc/user/application_security/dast/checks/798.31.md
index 8f03ba780e4..d35e9c91f0f 100644
--- a/doc/user/application_security/dast/checks/798.31.md
+++ b/doc/user/application_security/dast/checks/798.31.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Dropbox long lived API token
diff --git a/doc/user/application_security/dast/checks/798.32.md b/doc/user/application_security/dast/checks/798.32.md
index d2ed4af9177..30e38c36959 100644
--- a/doc/user/application_security/dast/checks/798.32.md
+++ b/doc/user/application_security/dast/checks/798.32.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Dropbox short lived API token
diff --git a/doc/user/application_security/dast/checks/798.33.md b/doc/user/application_security/dast/checks/798.33.md
index 5a264cf4286..536faefdb51 100644
--- a/doc/user/application_security/dast/checks/798.33.md
+++ b/doc/user/application_security/dast/checks/798.33.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Droneci Access Token
diff --git a/doc/user/application_security/dast/checks/798.34.md b/doc/user/application_security/dast/checks/798.34.md
index a9b02b75230..5323a026257 100644
--- a/doc/user/application_security/dast/checks/798.34.md
+++ b/doc/user/application_security/dast/checks/798.34.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Duffel API token
diff --git a/doc/user/application_security/dast/checks/798.35.md b/doc/user/application_security/dast/checks/798.35.md
index 5d35baec9bb..16aa601674e 100644
--- a/doc/user/application_security/dast/checks/798.35.md
+++ b/doc/user/application_security/dast/checks/798.35.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Dynatrace API token
diff --git a/doc/user/application_security/dast/checks/798.36.md b/doc/user/application_security/dast/checks/798.36.md
index e2e0f10f842..24827bc66fa 100644
--- a/doc/user/application_security/dast/checks/798.36.md
+++ b/doc/user/application_security/dast/checks/798.36.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token EasyPost API token
diff --git a/doc/user/application_security/dast/checks/798.37.md b/doc/user/application_security/dast/checks/798.37.md
index 089dc8b3ecc..4f3ca41e0ea 100644
--- a/doc/user/application_security/dast/checks/798.37.md
+++ b/doc/user/application_security/dast/checks/798.37.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token EasyPost test API token
diff --git a/doc/user/application_security/dast/checks/798.38.md b/doc/user/application_security/dast/checks/798.38.md
index 886cfcc701b..b8a6ea5b237 100644
--- a/doc/user/application_security/dast/checks/798.38.md
+++ b/doc/user/application_security/dast/checks/798.38.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Etsy Access Token
diff --git a/doc/user/application_security/dast/checks/798.39.md b/doc/user/application_security/dast/checks/798.39.md
index 78a66d15b89..1cad4237cfe 100644
--- a/doc/user/application_security/dast/checks/798.39.md
+++ b/doc/user/application_security/dast/checks/798.39.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Facebook
diff --git a/doc/user/application_security/dast/checks/798.4.md b/doc/user/application_security/dast/checks/798.4.md
index 2ff5db46d83..30e0c34c960 100644
--- a/doc/user/application_security/dast/checks/798.4.md
+++ b/doc/user/application_security/dast/checks/798.4.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Age secret key
diff --git a/doc/user/application_security/dast/checks/798.40.md b/doc/user/application_security/dast/checks/798.40.md
index e6691bb7b3a..7ea8df02055 100644
--- a/doc/user/application_security/dast/checks/798.40.md
+++ b/doc/user/application_security/dast/checks/798.40.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Fastly API key
diff --git a/doc/user/application_security/dast/checks/798.41.md b/doc/user/application_security/dast/checks/798.41.md
index b4d097a9014..8e5eb3e8f43 100644
--- a/doc/user/application_security/dast/checks/798.41.md
+++ b/doc/user/application_security/dast/checks/798.41.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Finicity Client Secret
diff --git a/doc/user/application_security/dast/checks/798.42.md b/doc/user/application_security/dast/checks/798.42.md
index 30c380d13a5..5ff876021ef 100644
--- a/doc/user/application_security/dast/checks/798.42.md
+++ b/doc/user/application_security/dast/checks/798.42.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Finicity API token
diff --git a/doc/user/application_security/dast/checks/798.43.md b/doc/user/application_security/dast/checks/798.43.md
index be984f7119a..44a8e5d44b1 100644
--- a/doc/user/application_security/dast/checks/798.43.md
+++ b/doc/user/application_security/dast/checks/798.43.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Flickr Access Token
diff --git a/doc/user/application_security/dast/checks/798.44.md b/doc/user/application_security/dast/checks/798.44.md
index 183cb49b2e7..5cebcb5c93d 100644
--- a/doc/user/application_security/dast/checks/798.44.md
+++ b/doc/user/application_security/dast/checks/798.44.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Finnhub Access Token
diff --git a/doc/user/application_security/dast/checks/798.46.md b/doc/user/application_security/dast/checks/798.46.md
index 5bf658ff610..c71eacbee34 100644
--- a/doc/user/application_security/dast/checks/798.46.md
+++ b/doc/user/application_security/dast/checks/798.46.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Flutterwave Secret Key
diff --git a/doc/user/application_security/dast/checks/798.47.md b/doc/user/application_security/dast/checks/798.47.md
index a6c7b974b7f..24cf3a02121 100644
--- a/doc/user/application_security/dast/checks/798.47.md
+++ b/doc/user/application_security/dast/checks/798.47.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Flutterwave Encryption Key
diff --git a/doc/user/application_security/dast/checks/798.48.md b/doc/user/application_security/dast/checks/798.48.md
index 523232cb00c..f8778c2b0ba 100644
--- a/doc/user/application_security/dast/checks/798.48.md
+++ b/doc/user/application_security/dast/checks/798.48.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Frame.io API token
diff --git a/doc/user/application_security/dast/checks/798.49.md b/doc/user/application_security/dast/checks/798.49.md
index ab7f39c2376..7ea3a65fbfa 100644
--- a/doc/user/application_security/dast/checks/798.49.md
+++ b/doc/user/application_security/dast/checks/798.49.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Freshbooks Access Token
diff --git a/doc/user/application_security/dast/checks/798.5.md b/doc/user/application_security/dast/checks/798.5.md
index 6d55dcf54df..03afbecb820 100644
--- a/doc/user/application_security/dast/checks/798.5.md
+++ b/doc/user/application_security/dast/checks/798.5.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Airtable API Key
diff --git a/doc/user/application_security/dast/checks/798.50.md b/doc/user/application_security/dast/checks/798.50.md
index f0d864db119..0542a00ff71 100644
--- a/doc/user/application_security/dast/checks/798.50.md
+++ b/doc/user/application_security/dast/checks/798.50.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GoCardless API token
diff --git a/doc/user/application_security/dast/checks/798.52.md b/doc/user/application_security/dast/checks/798.52.md
index 0c4ea4a540b..78864a51172 100644
--- a/doc/user/application_security/dast/checks/798.52.md
+++ b/doc/user/application_security/dast/checks/798.52.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GitHub Personal Access Token
diff --git a/doc/user/application_security/dast/checks/798.53.md b/doc/user/application_security/dast/checks/798.53.md
index 62a548be627..37ef66ec726 100644
--- a/doc/user/application_security/dast/checks/798.53.md
+++ b/doc/user/application_security/dast/checks/798.53.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GitHub OAuth Access Token
diff --git a/doc/user/application_security/dast/checks/798.54.md b/doc/user/application_security/dast/checks/798.54.md
index d29677899a5..bf8ab699f9d 100644
--- a/doc/user/application_security/dast/checks/798.54.md
+++ b/doc/user/application_security/dast/checks/798.54.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GitHub App Token
diff --git a/doc/user/application_security/dast/checks/798.55.md b/doc/user/application_security/dast/checks/798.55.md
index 4c3bd9147c0..0e7528ba008 100644
--- a/doc/user/application_security/dast/checks/798.55.md
+++ b/doc/user/application_security/dast/checks/798.55.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GitHub Refresh Token
diff --git a/doc/user/application_security/dast/checks/798.56.md b/doc/user/application_security/dast/checks/798.56.md
index 563ea1f91a8..6c9e4bbfd9a 100644
--- a/doc/user/application_security/dast/checks/798.56.md
+++ b/doc/user/application_security/dast/checks/798.56.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token GitLab Personal Access Token
diff --git a/doc/user/application_security/dast/checks/798.57.md b/doc/user/application_security/dast/checks/798.57.md
index 25b32953ebd..d0c700c8662 100644
--- a/doc/user/application_security/dast/checks/798.57.md
+++ b/doc/user/application_security/dast/checks/798.57.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Gitter Access Token
diff --git a/doc/user/application_security/dast/checks/798.58.md b/doc/user/application_security/dast/checks/798.58.md
index 056bcb0820a..86396d00ba1 100644
--- a/doc/user/application_security/dast/checks/798.58.md
+++ b/doc/user/application_security/dast/checks/798.58.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token HashiCorp Terraform user/org API token
diff --git a/doc/user/application_security/dast/checks/798.59.md b/doc/user/application_security/dast/checks/798.59.md
index b7e6b4fa32b..471ece22913 100644
--- a/doc/user/application_security/dast/checks/798.59.md
+++ b/doc/user/application_security/dast/checks/798.59.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Heroku API Key
diff --git a/doc/user/application_security/dast/checks/798.6.md b/doc/user/application_security/dast/checks/798.6.md
index ce6ee95bede..cfdfa706c15 100644
--- a/doc/user/application_security/dast/checks/798.6.md
+++ b/doc/user/application_security/dast/checks/798.6.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Algolia API Key
diff --git a/doc/user/application_security/dast/checks/798.60.md b/doc/user/application_security/dast/checks/798.60.md
index f471411440b..bdfe162e615 100644
--- a/doc/user/application_security/dast/checks/798.60.md
+++ b/doc/user/application_security/dast/checks/798.60.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token HubSpot API Token
diff --git a/doc/user/application_security/dast/checks/798.61.md b/doc/user/application_security/dast/checks/798.61.md
index 061bf8f7360..c359dd9cc90 100644
--- a/doc/user/application_security/dast/checks/798.61.md
+++ b/doc/user/application_security/dast/checks/798.61.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Intercom API Token
diff --git a/doc/user/application_security/dast/checks/798.62.md b/doc/user/application_security/dast/checks/798.62.md
index 9c0f312b161..0d34ab89508 100644
--- a/doc/user/application_security/dast/checks/798.62.md
+++ b/doc/user/application_security/dast/checks/798.62.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Kraken Access Token
diff --git a/doc/user/application_security/dast/checks/798.63.md b/doc/user/application_security/dast/checks/798.63.md
index 51668619025..e065750150d 100644
--- a/doc/user/application_security/dast/checks/798.63.md
+++ b/doc/user/application_security/dast/checks/798.63.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Kucoin Access Token
diff --git a/doc/user/application_security/dast/checks/798.64.md b/doc/user/application_security/dast/checks/798.64.md
index 12d20f96a42..12cd11d8d79 100644
--- a/doc/user/application_security/dast/checks/798.64.md
+++ b/doc/user/application_security/dast/checks/798.64.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Kucoin Secret Key
diff --git a/doc/user/application_security/dast/checks/798.65.md b/doc/user/application_security/dast/checks/798.65.md
index eb1dac62037..f2ebfb988b2 100644
--- a/doc/user/application_security/dast/checks/798.65.md
+++ b/doc/user/application_security/dast/checks/798.65.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Launchdarkly Access Token
diff --git a/doc/user/application_security/dast/checks/798.66.md b/doc/user/application_security/dast/checks/798.66.md
index 8f20f9fa339..c83eaba8d29 100644
--- a/doc/user/application_security/dast/checks/798.66.md
+++ b/doc/user/application_security/dast/checks/798.66.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Linear API Token
diff --git a/doc/user/application_security/dast/checks/798.67.md b/doc/user/application_security/dast/checks/798.67.md
index 7554c077376..8b39f42d090 100644
--- a/doc/user/application_security/dast/checks/798.67.md
+++ b/doc/user/application_security/dast/checks/798.67.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Linear Client Secret
diff --git a/doc/user/application_security/dast/checks/798.68.md b/doc/user/application_security/dast/checks/798.68.md
index c633b949185..54a2e418cd2 100644
--- a/doc/user/application_security/dast/checks/798.68.md
+++ b/doc/user/application_security/dast/checks/798.68.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token LinkedIn Client ID
diff --git a/doc/user/application_security/dast/checks/798.69.md b/doc/user/application_security/dast/checks/798.69.md
index b34c2f01be6..0a341f494fc 100644
--- a/doc/user/application_security/dast/checks/798.69.md
+++ b/doc/user/application_security/dast/checks/798.69.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token LinkedIn Client secret
diff --git a/doc/user/application_security/dast/checks/798.7.md b/doc/user/application_security/dast/checks/798.7.md
index 43aba566471..2989c68a311 100644
--- a/doc/user/application_security/dast/checks/798.7.md
+++ b/doc/user/application_security/dast/checks/798.7.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Alibaba AccessKey ID
diff --git a/doc/user/application_security/dast/checks/798.70.md b/doc/user/application_security/dast/checks/798.70.md
index b7c1816481b..cfd1660bd7f 100644
--- a/doc/user/application_security/dast/checks/798.70.md
+++ b/doc/user/application_security/dast/checks/798.70.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Lob API Key
diff --git a/doc/user/application_security/dast/checks/798.72.md b/doc/user/application_security/dast/checks/798.72.md
index 48b2cffbbda..c89fb2bf8c6 100644
--- a/doc/user/application_security/dast/checks/798.72.md
+++ b/doc/user/application_security/dast/checks/798.72.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Mailchimp API key
diff --git a/doc/user/application_security/dast/checks/798.74.md b/doc/user/application_security/dast/checks/798.74.md
index 9a4b909bf4b..94d17b2c1be 100644
--- a/doc/user/application_security/dast/checks/798.74.md
+++ b/doc/user/application_security/dast/checks/798.74.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Mailgun private API token
diff --git a/doc/user/application_security/dast/checks/798.75.md b/doc/user/application_security/dast/checks/798.75.md
index 4c1cfd78003..e2a764bf826 100644
--- a/doc/user/application_security/dast/checks/798.75.md
+++ b/doc/user/application_security/dast/checks/798.75.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Mailgun webhook signing key
diff --git a/doc/user/application_security/dast/checks/798.77.md b/doc/user/application_security/dast/checks/798.77.md
index 7b1becf4c19..f79b6645b26 100644
--- a/doc/user/application_security/dast/checks/798.77.md
+++ b/doc/user/application_security/dast/checks/798.77.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Mattermost Access Token
diff --git a/doc/user/application_security/dast/checks/798.78.md b/doc/user/application_security/dast/checks/798.78.md
index 8d366d44c9d..b2c73b54562 100644
--- a/doc/user/application_security/dast/checks/798.78.md
+++ b/doc/user/application_security/dast/checks/798.78.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token MessageBird API token
diff --git a/doc/user/application_security/dast/checks/798.8.md b/doc/user/application_security/dast/checks/798.8.md
index e6dfe1aa1cc..3b99bae1f4e 100644
--- a/doc/user/application_security/dast/checks/798.8.md
+++ b/doc/user/application_security/dast/checks/798.8.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Alibaba Secret Key
diff --git a/doc/user/application_security/dast/checks/798.80.md b/doc/user/application_security/dast/checks/798.80.md
index c0a893264b0..9a18a21d5d1 100644
--- a/doc/user/application_security/dast/checks/798.80.md
+++ b/doc/user/application_security/dast/checks/798.80.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Netlify Access Token
diff --git a/doc/user/application_security/dast/checks/798.81.md b/doc/user/application_security/dast/checks/798.81.md
index abf40705e7f..fef989c0bbf 100644
--- a/doc/user/application_security/dast/checks/798.81.md
+++ b/doc/user/application_security/dast/checks/798.81.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token New Relic user API Key
diff --git a/doc/user/application_security/dast/checks/798.82.md b/doc/user/application_security/dast/checks/798.82.md
index 519555546b6..23ebba1641e 100644
--- a/doc/user/application_security/dast/checks/798.82.md
+++ b/doc/user/application_security/dast/checks/798.82.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token New Relic user API ID
diff --git a/doc/user/application_security/dast/checks/798.83.md b/doc/user/application_security/dast/checks/798.83.md
index 85bdd534390..3f36e78cfda 100644
--- a/doc/user/application_security/dast/checks/798.83.md
+++ b/doc/user/application_security/dast/checks/798.83.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token New Relic ingest browser API token
diff --git a/doc/user/application_security/dast/checks/798.84.md b/doc/user/application_security/dast/checks/798.84.md
index 74ebb4fcaf1..69f4c1249b4 100644
--- a/doc/user/application_security/dast/checks/798.84.md
+++ b/doc/user/application_security/dast/checks/798.84.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token npm access token
diff --git a/doc/user/application_security/dast/checks/798.86.md b/doc/user/application_security/dast/checks/798.86.md
index 940a46b7658..700ed99ebc5 100644
--- a/doc/user/application_security/dast/checks/798.86.md
+++ b/doc/user/application_security/dast/checks/798.86.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Okta Access Token
diff --git a/doc/user/application_security/dast/checks/798.87.md b/doc/user/application_security/dast/checks/798.87.md
index 8246bafc993..3fb1fe4a857 100644
--- a/doc/user/application_security/dast/checks/798.87.md
+++ b/doc/user/application_security/dast/checks/798.87.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Plaid Client ID
diff --git a/doc/user/application_security/dast/checks/798.88.md b/doc/user/application_security/dast/checks/798.88.md
index 57b029857ba..6d143dce5fa 100644
--- a/doc/user/application_security/dast/checks/798.88.md
+++ b/doc/user/application_security/dast/checks/798.88.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Plaid Secret key
diff --git a/doc/user/application_security/dast/checks/798.89.md b/doc/user/application_security/dast/checks/798.89.md
index 466044834dd..123f2730b30 100644
--- a/doc/user/application_security/dast/checks/798.89.md
+++ b/doc/user/application_security/dast/checks/798.89.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Plaid API Token
diff --git a/doc/user/application_security/dast/checks/798.9.md b/doc/user/application_security/dast/checks/798.9.md
index 12c725cfd08..a86f8241bf7 100644
--- a/doc/user/application_security/dast/checks/798.9.md
+++ b/doc/user/application_security/dast/checks/798.9.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Asana Client ID
diff --git a/doc/user/application_security/dast/checks/798.90.md b/doc/user/application_security/dast/checks/798.90.md
index e0008af4918..884fca83dd3 100644
--- a/doc/user/application_security/dast/checks/798.90.md
+++ b/doc/user/application_security/dast/checks/798.90.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token PlanetScale password
diff --git a/doc/user/application_security/dast/checks/798.91.md b/doc/user/application_security/dast/checks/798.91.md
index be54e99360f..bfccaf3262d 100644
--- a/doc/user/application_security/dast/checks/798.91.md
+++ b/doc/user/application_security/dast/checks/798.91.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token PlanetScale API token
diff --git a/doc/user/application_security/dast/checks/798.92.md b/doc/user/application_security/dast/checks/798.92.md
index 07ae24151f5..ceec84a3fe8 100644
--- a/doc/user/application_security/dast/checks/798.92.md
+++ b/doc/user/application_security/dast/checks/798.92.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token PlanetScale OAuth token
diff --git a/doc/user/application_security/dast/checks/798.93.md b/doc/user/application_security/dast/checks/798.93.md
index 661f460bf27..1d67a889d1a 100644
--- a/doc/user/application_security/dast/checks/798.93.md
+++ b/doc/user/application_security/dast/checks/798.93.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Postman API token
diff --git a/doc/user/application_security/dast/checks/798.94.md b/doc/user/application_security/dast/checks/798.94.md
index 4aeb15fee23..aedeabce11c 100644
--- a/doc/user/application_security/dast/checks/798.94.md
+++ b/doc/user/application_security/dast/checks/798.94.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Private Key
diff --git a/doc/user/application_security/dast/checks/798.95.md b/doc/user/application_security/dast/checks/798.95.md
index 13374aa67e0..fa34f58a48e 100644
--- a/doc/user/application_security/dast/checks/798.95.md
+++ b/doc/user/application_security/dast/checks/798.95.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Pulumi API token
diff --git a/doc/user/application_security/dast/checks/798.96.md b/doc/user/application_security/dast/checks/798.96.md
index cb61bd38950..de93a54ec63 100644
--- a/doc/user/application_security/dast/checks/798.96.md
+++ b/doc/user/application_security/dast/checks/798.96.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token PyPI upload token
diff --git a/doc/user/application_security/dast/checks/798.97.md b/doc/user/application_security/dast/checks/798.97.md
index 93f03a692d7..d3035b05bbb 100644
--- a/doc/user/application_security/dast/checks/798.97.md
+++ b/doc/user/application_security/dast/checks/798.97.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Rubygem API token
diff --git a/doc/user/application_security/dast/checks/798.98.md b/doc/user/application_security/dast/checks/798.98.md
index aab4cb9c5ed..08460c09520 100644
--- a/doc/user/application_security/dast/checks/798.98.md
+++ b/doc/user/application_security/dast/checks/798.98.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token RapidAPI Access Token
diff --git a/doc/user/application_security/dast/checks/798.99.md b/doc/user/application_security/dast/checks/798.99.md
index 90c8aeda7ab..b43bf291cc0 100644
--- a/doc/user/application_security/dast/checks/798.99.md
+++ b/doc/user/application_security/dast/checks/798.99.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exposure of confidential secret or token Sendbird Access ID
diff --git a/doc/user/application_security/dast/checks/829.1.md b/doc/user/application_security/dast/checks/829.1.md
index ca3d99c2bc9..f18634b72d9 100644
--- a/doc/user/application_security/dast/checks/829.1.md
+++ b/doc/user/application_security/dast/checks/829.1.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Inclusion of Functionality from Untrusted Control Sphere
diff --git a/doc/user/application_security/dast/checks/829.2.md b/doc/user/application_security/dast/checks/829.2.md
index e6fada117f8..19490afe676 100644
--- a/doc/user/application_security/dast/checks/829.2.md
+++ b/doc/user/application_security/dast/checks/829.2.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Invalid Sub-Resource Integrity values detected
diff --git a/doc/user/application_security/dast/checks/index.md b/doc/user/application_security/dast/checks/index.md
index 387682318e6..9466734f9cf 100644
--- a/doc/user/application_security/dast/checks/index.md
+++ b/doc/user/application_security/dast/checks/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# DAST browser-based crawler vulnerability checks **(ULTIMATE)**
diff --git a/doc/user/application_security/dast/dast_troubleshooting.md b/doc/user/application_security/dast/dast_troubleshooting.md
index 4e87f1898cc..194761797de 100644
--- a/doc/user/application_security/dast/dast_troubleshooting.md
+++ b/doc/user/application_security/dast/dast_troubleshooting.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 0f446ddee3e..6d1b7beefc7 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -71,7 +71,7 @@ on how to configure Review Apps for DAST.
#### Docker Services
-If your application utilizes Docker containers you have another option for deploying and scanning with DAST.
+If your application uses Docker containers you have another option for deploying and scanning with DAST.
After your Docker build job completes and your image is added to your container registry, you can use the image as a
[service](../../../ci/services/index.md).
@@ -480,7 +480,7 @@ When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
- `DAST_WEBSITE` must be defined when using either `DAST_PATHS_FILE` or `DAST_PATHS`. The paths listed in either use `DAST_WEBSITE` to build the URLs to scan
- Spidering is disabled when `DAST_PATHS` or `DAST_PATHS_FILE` are defined
-- `DAST_PATHS_FILE` and `DAST_PATHS` can not be used together
+- `DAST_PATHS_FILE` and `DAST_PATHS` cannot be used together
- The `DAST_PATHS` variable has a limit of about 130kb. If you have a list or paths
greater than this, use `DAST_PATHS_FILE`.
@@ -637,11 +637,11 @@ including a large number of false positives.
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
-| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that are clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
+| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that are selected prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
-| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when selected submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293595)** in GitLab 14.0. Set to `true` to require domain validation when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_FULL_SCAN_ENABLED` <sup>1</sup> | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
@@ -660,7 +660,7 @@ including a large number of false positives.
| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
| `DAST_SPIDER_MINS` <sup>1</sup> | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
-| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when selected submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_TARGET_AVAILABILITY_TIMEOUT` <sup>1</sup> | number | Time limit in seconds to wait for target availability. |
| `DAST_USE_AJAX_SPIDER` <sup>1</sup> | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USERNAME` <sup>1,2</sup> | string | The username to authenticate to in the website. Example: `admin` |
@@ -744,6 +744,17 @@ scan is run, it may perform *any* function that the authenticated user can. This
includes actions like modifying and deleting data, submitting forms, and following links.
Only run an authenticated scan against a test server.
+### SSO
+
+DAST can authenticate to websites making use of SSO, with the following restrictions:
+
+- DAST cannot bypass a CAPTCHA if the authentication flow includes one.
+- DAST cannot handle multi-factor authentication like one-time passwords (OTP) by using SMS or authenticator apps.
+- DAST must get a cookie, or a local or session storage, with a sufficiently random value.
+
+The [authentication debug output](index.md#configure-the-authentication-debug-output) can be helpful for troubleshooting SSO authentication
+with DAST.
+
### Log in using automatic detection of the login form
By providing a `DAST_USERNAME`, `DAST_PASSWORD`, and `DAST_AUTH_URL`, DAST attempts to authenticate to the
@@ -754,10 +765,10 @@ Automatic detection is "best-effort", and depending on the application being sca
Login process:
1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
- 1. If a form contains a username and password field, `DAST_USERNAME` and `DAST_PASSWORD` is inputted into the respective fields, the form submit button is clicked and the user is logged in.
+ 1. If a form contains a username and password field, `DAST_USERNAME` and `DAST_PASSWORD` is inputted into the respective fields, the form submit button is selected and the user is logged in.
1. If a form contains only a username field, it is assumed that the login form is multi-step.
- 1. The `DAST_USERNAME` is inputted into the username field and the form submit button is clicked.
- 1. The subsequent pages loads where it is expected that a form exists and contains a password field. If found, `DAST_PASSWORD` is inputted, form submit button is clicked and the user is logged in.
+ 1. The `DAST_USERNAME` is inputted into the username field and the form submit button is selected.
+ 1. The subsequent pages loads where it is expected that a form exists and contains a password field. If found, `DAST_PASSWORD` is inputted, form submit button is selected and the user is logged in.
### Log in using explicit selection of the login form
@@ -768,10 +779,10 @@ Most applications benefit from this approach to authentication.
Login process:
1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
- 1. If the `DAST_FIRST_SUBMIT_FIELD` is not defined, then `DAST_USERNAME` is inputted into `DAST_USERNAME_FIELD`, `DAST_PASSWORD` is inputted into `DAST_PASSWORD_FIELD`, `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
+ 1. If the `DAST_FIRST_SUBMIT_FIELD` is not defined, then `DAST_USERNAME` is inputted into `DAST_USERNAME_FIELD`, `DAST_PASSWORD` is inputted into `DAST_PASSWORD_FIELD`, `DAST_SUBMIT_FIELD` is selected and the user is logged in.
1. If the `DAST_FIRST_SUBMIT_FIELD` is defined, then it is assumed that the login form is multi-step.
- 1. The `DAST_USERNAME` is inputted into the `DAST_USERNAME_FIELD` field and the `DAST_FIRST_SUBMIT_FIELD` is clicked.
- 1. The subsequent pages loads where the `DAST_PASSWORD` is inputted into the `DAST_PASSWORD_FIELD` field, the `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
+ 1. The `DAST_USERNAME` is inputted into the `DAST_USERNAME_FIELD` field and the `DAST_FIRST_SUBMIT_FIELD` is selected.
+ 1. The subsequent pages loads where the `DAST_PASSWORD` is inputted into the `DAST_PASSWORD_FIELD` field, the `DAST_SUBMIT_FIELD` is selected and the user is logged in.
### Verifying successful login
@@ -1159,7 +1170,7 @@ A site profile contains:
- **Password**: The password used to authenticate to the website.
- **Username form field**: The name of username field at the sign-in HTML form.
- **Password form field**: The name of password field at the sign-in HTML form.
- - **Submit form field**: The `id` or `name` of the element that when clicked submits the sign-in HTML form.
+ - **Submit form field**: The `id` or `name` of the element that when selected submits the sign-in HTML form.
When an API site type is selected, a [host override](#host-override) is used to ensure the API being scanned is on the same host as the target. This is done to reduce the risk of running an active scan against the wrong API.
diff --git a/doc/user/application_security/dast/run_dast_offline.md b/doc/user/application_security/dast/run_dast_offline.md
index 63163167a6c..05c6b74fbcd 100644
--- a/doc/user/application_security/dast/run_dast_offline.md
+++ b/doc/user/application_security/dast/run_dast_offline.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index f15dce37123..eae32f789b8 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
@@ -1039,6 +1039,7 @@ can be added, removed, and modified by creating a custom configuration.
| `SECURE_ANALYZERS_PREFIX` | Specify the Docker registry base address from which to download the analyzer. |
| `DAST_API_VERSION` | Specify DAST API container version. Defaults to `2`. |
| `DAST_API_IMAGE_SUFFIX` | Specify a container image suffix. Defaults to none. |
+| `DAST_API_API_PORT` | Specify the communication port number used by DAST API engine. Defaults to `5500`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367734) in GitLab 15.5. |
| `DAST_API_TARGET_URL` | Base URL of API testing target. |
|[`DAST_API_CONFIG`](#configuration-files) | DAST API configuration file. Defaults to `.gitlab-dast-api.yml`. |
|[`DAST_API_PROFILE`](#configuration-files) | Configuration profile to use during testing. Defaults to `Quick`. |
@@ -1333,13 +1334,13 @@ variables:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334578) in GitLab 14.8.
-By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `DAST_API_OVERRIDES_CMD_VERBOSE` to any value in order to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
+By default the output of the overrides command is hidden. If the overrides command returns a non zero exit code, the command is displayed as part of your job output. Optionally, you can set the variable `DAST_API_OVERRIDES_CMD_VERBOSE` to any value to display overrides command output as it is generated. This is useful when testing your overrides script, but should be disabled afterwards as it slows down testing.
It is also possible to write messages from your script to a log file that is collected when the job completes or fails. The log file must be created in a specific location and following a naming convention.
Adding some basic logging to your overrides script is useful in case the script fails unexpectedly during normal running of the job. The log file is automatically included as an artifact of the job, allowing you to download it after the job has finished.
-Following our example, we provided `renew_token.py` in the environment variable `DAST_API_OVERRIDES_CMD`. Please notice two things in the script:
+Following our example, we provided `renew_token.py` in the environment variable `DAST_API_OVERRIDES_CMD`. Notice two things in the script:
- Log file is saved in the location indicated by the environmental variable `CI_PROJECT_DIR`.
- Log filename should match `gl-*.log`.
@@ -2064,7 +2065,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 occurring 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, 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.
@@ -2085,13 +2086,50 @@ The DAST API engine outputs an error message when it cannot establish a connecti
- Remove the `DAST_API_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the DAST API CI/CD template. We recommend this method instead of manually setting a value.
- If removing the variable is not possible, check to see if this value has changed in the latest version of the [DAST API CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
+### `Failed to start session with scanner. Please retry, and if the problem persists reach out to support.`
+
+The DAST API engine outputs an error message when it cannot establish a connection with the scanner application component. The error message is shown in the job output window of the `dast_api` job. A common cause for this issue is that the background component cannot use the selected port as it's already in use. This error can occur intermittently if timing plays a part (race condition). This issue occurs most often with Kubernetes environments when other services are mapped into the container causing port conflicts.
+
+Before proceeding with a solution, it is important to confirm that the error message was produced because the port was already taken. To confirm this was the cause:
+
+1. Go to the job console.
+
+1. Look for the artifact `gl-api-security-scanner.log`. You can either download all artifacts by selecting **Download** and then search for the file, or directly start searching by selecting **Browse**.
+
+1. Open the file `gl-api-security-scanner.log` in a text editor.
+
+1. If the error message was produced because the port was already taken, you should see in the file a message like the following:
+
+- In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/367734):
+
+ ```log
+ Failed to bind to address http://127.0.0.1:5500: address already in use.
+ ```
+
+- In GitLab 15.4 and earlier:
+
+ ```log
+ Failed to bind to address http://[::]:5000: address already in use.
+ ```
+
+The text `http://[::]:5000` in the previous message could be different in your case, for instance it could be `http://[::]:5500` or `http://127.0.0.1:5500`. As long as the remaining parts of the error message are the same, it is safe to assume the port was already taken.
+
+If you did not find evidence that the port was already taken, check other troubleshooting sections which also address the same error message shown in the job console output. If there are no more options, feel free to [get support or request an improvement](#get-support-or-request-an-improvement) through the proper channels.
+
+Once you have confirmed the issue was produced because the port was already taken. Then, [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/367734) introduced the configuration variable `DAST_API_API_PORT`. This configuration variable allows setting a fixed port number for the scanner background component.
+
+**Solution**
+
+1. Ensure your `.gitlab-ci.yml` file defines the configuration variable `DAST_API_API_PORT`.
+1. Update the value of `DAST_API_API_PORT` to any available port number greater than 1024. We recommend checking that the new value is not in used by GitLab. See the full list of ports used by GitLab in [Package defaults](../../../administration/package_information/defaults.md#ports)
+
### `Application cannot determine the base URL for the target API`
The DAST API engine outputs an error message when it cannot determine the target API after inspecting the OpenAPI document. This error message is shown when the target API has not been set in the `.gitlab-ci.yml` file, it is not available in the `environment_url.txt` file, and it could not be computed using the OpenAPI document.
There is a order of precedence in which the DAST API engine tries to get the target API when checking the different sources. First, it will try to use the `DAST_API_TARGET_URL`. If the environment variable has not been set, then the DAST API engine will attempt to use the `environment_url.txt` file. If there is no file `environment_url.txt`, then the DAST API engine will use the OpenAPI document contents and the URL provided in `DAST_API_OPENAPI` (if a URL is provided) to try to compute the target API.
-The best-suited solution will depend on whether or not your target API changes for each deployment. In static environments, the target API is the same for each deployment, in this case please refer to the [static environment solution](#static-environment-solution). If the target API changes for each deployment a [dynamic environment solution](#dynamic-environment-solutions) should be applied.
+The best-suited solution will depend on whether or not your target API changes for each deployment. In static environments, the target API is the same for each deployment, in this case refer to the [static environment solution](#static-environment-solution). If the target API changes for each deployment a [dynamic environment solution](#dynamic-environment-solutions) should be applied.
#### Static environment solution
@@ -2188,10 +2226,10 @@ DAST API uses the specified media types in the OpenAPI document to generate requ
## 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/).
+To get support for your particular problem, 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](https://about.gitlab.com/handbook/engineering/workflow/code-review/#review-response-slo) to understand when you should receive a response.
+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. Refer to our [review response SLO](https://about.gitlab.com/handbook/engineering/workflow/code-review/#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.
@@ -2203,7 +2241,7 @@ When experiencing a behavior not working as expected, consider providing context
- 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.
+**Sanitize data attached to a support issue**. Remove sensitive information, including: credentials, passwords, tokens, keys, and secrets.
## Glossary
diff --git a/doc/user/application_security/dependency_list/index.md b/doc/user/application_security/dependency_list/index.md
index 03c97c85dbc..9fffdec2612 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency list **(ULTIMATE)**
@@ -48,7 +48,7 @@ can also be sorted by name or by the packager that installed them.
### Vulnerabilities
-If a dependency has known vulnerabilities, view them by clicking the arrow next to the
+If a dependency has known vulnerabilities, view them by selecting the arrow next to the
dependency's name or the badge that indicates how many known vulnerabilities exist. For each
vulnerability, its severity and description appears below it. To view more details of a vulnerability,
select the vulnerability's description. The [vulnerability's details](../vulnerabilities) page is opened.
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index a59399f7e8d..e4466dffd56 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency Scanning Analyzers **(ULTIMATE)**
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 7aabbdd3194..a3c6c46b081 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency Scanning **(ULTIMATE)**
@@ -48,7 +48,7 @@ possible, we encourage you to use all of our security scanning tools:
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
+ Dependency Scanning cannot detect software dependencies that are pre-bundled
into the container's base image. To identify pre-bundled dependencies, enable
[Container Scanning](../container_scanning/index.md) language scanning using the
[`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/index.md#report-language-specific-findings).
@@ -94,7 +94,7 @@ is **not** `19.03.0`. See [troubleshooting information](#error-response-from-dae
WARNING:
Dependency Scanning does not support run-time installation of compilers and interpreters.
-If you need it, please explain why by filling out [the survey](https://docs.google.com/forms/d/e/1FAIpQLScKo7xEYA65rOjPTGIufAyfjPGnCALSJZoTxBlvskfFMEOZMw/viewform).
+If you need it, explain why by filling out [the survey](https://docs.google.com/forms/d/e/1FAIpQLScKo7xEYA65rOjPTGIufAyfjPGnCALSJZoTxBlvskfFMEOZMw/viewform).
## Supported languages and package managers
@@ -187,7 +187,12 @@ table.supported-languages ul {
<td>Go</td>
<td>All versions</td>
<td><a href="https://go.dev/">Go</a></td>
- <td><code>go.sum</code></td>
+ <td>
+ <ul>
+ <li><code>go.mod</code></li>
+ <li><code>go.sum</code></li>
+ </ul>
+ </td>
<td>Y</td>
</tr>
<tr>
@@ -237,7 +242,7 @@ table.supported-languages ul {
<td>.NET</td>
<td rowspan="2">All versions</td>
<td rowspan="2"><a href="https://www.nuget.org/">NuGet</a></td>
- <td rowspan="2"><a href="https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file"><code>packages.lock.json</code></a></td>
+ <td rowspan="2"><a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file"><code>packages.lock.json</code></a></td>
<td rowspan="2">Y</td>
</tr>
<tr>
@@ -297,7 +302,7 @@ table.supported-languages ul {
<a id="notes-regarding-supported-languages-and-package-managers-2"></a>
<p>
Although Gradle with Java 8 is supported, there are other issues such that Android project builds are not supported at this time.
- Please see the backlog issue <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/336866">Android support for Dependency
+ See the backlog issue <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/336866">Android support for Dependency
Scanning (gemnasium-maven)</a> for more details. Also, Gradle is not supported when <a href="https://docs.gitlab.com/ee/development/fips_compliance.html#enable-fips-mode">FIPS mode</a> is enabled.
</p>
</li>
@@ -353,12 +358,24 @@ The following package managers use lockfiles that GitLab analyzers are capable o
| Bundler | Not applicable | [1.17.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/ruby-bundler/default/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
| Composer | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/php-composer/default/composer.lock) |
| Conan | 0.4 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/c-conan/default/conan.lock) |
-| Go | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/default/go.sum) |
+| Go | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/default/go.sum) <sup><strong><a href="#notes-regarding-parsing-lockfiles-1">1</a></strong></sup> |
| NuGet | v1 | [4.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/default/src/web.api/packages.lock.json#L2) |
| npm | v1, v2 | [6.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/default/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4) |
| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/default/yarn.lock#L2) |
| Poetry | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v3/qa/fixtures/python-poetry/default/poetry.lock) |
+<!-- markdownlint-disable MD044 -->
+<ol>
+ <li>
+ <a id="notes-regarding-parsing-lockfiles-1"></a>
+ <p>
+ Dependency Scanning will only parse <code>go.sum</code> if it's unable to generate the build list
+ used by the Go project.
+ </p>
+ </li>
+</ol>
+<!-- markdownlint-enable MD044 -->
+
#### 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:
@@ -374,6 +391,7 @@ To support the following package managers, the GitLab analyzers proceed in two s
| 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/analyzers/gemnasium-python/-/blob/v2.22.0/spec/image_spec.rb#L224-247) |
| 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/analyzers/gemnasium-python/-/blob/v2.22.0/spec/image_spec.rb#L77-91) |
| 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/analyzers/gemnasium-python/-/blob/v2.22.0/spec/image_spec.rb#L168-191)<sup><b><a href="#exported-dependency-information-notes-3">3</a></b></sup>, [2018.11.26](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v2.22.0/spec/image_spec.rb#L143-166) |
+| Go | [1.17](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/7dc7a892b564abfcb160189f46b2ae6415e0dffa/build/gemnasium/alpine/Dockerfile#L88-91) | [1.17](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/7dc7a892b564abfcb160189f46b2ae6415e0dffa/build/gemnasium/alpine/Dockerfile#L88-91)<sup><strong><a href="#exported-dependency-information-notes-4">4</a></strong></sup> |
<!-- markdownlint-disable MD044 -->
<ol>
@@ -416,6 +434,13 @@ To support the following package managers, the GitLab analyzers proceed in two s
This test confirms that if a <code>Pipfile.lock</code> file is found, it will be used by <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a> to scan the exact package versions listed in this file.
</p>
</li>
+ <li>
+ <a id="exported-dependency-information-notes-4"></a>
+ <p>
+ Because of the implementation of <code>go build</code>, the Go build process requires network access, a pre-loaded modcache via <code>go mod download</code>, or vendored dependencies. For more information,
+ refer to the Go documentation on <a href="https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies">compiling packages and dependencies</a>.
+ </p>
+ </li>
</ol>
<!-- markdownlint-enable MD044 -->
@@ -432,7 +457,7 @@ When a supported dependency file is detected, all dependencies, including transi
### How multiple files are processed
NOTE:
-If you've run into problems while scanning multiple files, please contribute a comment to
+If you've run into problems while scanning multiple files, contribute a comment to
[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/337056).
#### Python
@@ -474,6 +499,12 @@ The following analyzers are executed, each of which have different behavior when
From GitLab 14.8 the `gemnasium` analyzer scans supported JavaScript projects for vendored libraries
(that is, those checked into the project but not managed by the package manager).
+#### Go
+
+When scanning a Go project, gemnasium invokes a builder and attempts to generate a [build list](https://go.dev/ref/mod#glos-build-list) using
+[Minimal Version Selection](https://go.dev/ref/mod#glos-minimal-version-selection). If a non-fatal error is encountered, the build process signals
+that the execution should proceed and falls back to parsing the available `go.sum` file.
+
#### PHP, Go, C, C++, .NET, C&#35;, Ruby, JavaScript
The analyzer for these languages supports multiple lockfiles.
@@ -616,11 +647,15 @@ The following variables are used for configuring specific analyzers (used for a
| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
| `SBT_CLI_OPTS` | `gemnasium-maven` | | List of command-line arguments that the analyzer passes to `sbt`. |
| `PIP_INDEX_URL` | `gemnasium-python` | `https://pypi.org/simple` | Base URL of Python Package Index. |
-| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` | | Array of [extra URLs](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url) of package indexes to use in addition to `PIP_INDEX_URL`. Comma-separated. **Warning:** Please read [the following security consideration](#python-projects) when using this environment variable. |
+| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` | | Array of [extra URLs](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url) of package indexes to use in addition to `PIP_INDEX_URL`. Comma-separated. **Warning:** Read [the following security consideration](#python-projects) when using this environment variable. |
| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` | | Pip requirements file to be scanned. |
| `DS_PIP_VERSION` | `gemnasium-python` | | Force the install of a specific pip version (example: `"19.3"`), otherwise the pip installed in the Docker image is used. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) in GitLab 12.7) |
| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` | | Path to load Python pip dependencies from. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) in GitLab 12.2) |
| `DS_INCLUDE_DEV_DEPENDENCIES` | `gemnasium` | `"true"` | When set to `"false"`, development dependencies and their vulnerabilities are not reported. Only NPM and Poetry projects are supported. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227861) in GitLab 15.1. |
+| `GOOS` | `gemnasium` | `"linux"` | The operating system for which to compile Go code. |
+| `GOARCH` | `gemnasium` | `"amd64"` | The architecture of the processor for which to compile Go code. |
+| `GOFLAGS` | `gemansium` | | The flags passed to the `go build` tool. |
+| `GOPRIVATE` | `gemnasium` | | A list of glob patterns and prefixes to be fetched from source. Read the Go private modules [documentation](https://go.dev/ref/mod#private-modules) for more information. |
#### Other variables
@@ -650,7 +685,7 @@ or [contributing to the code](../../../development/index.md) to enable it to be
### 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. 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:
+You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://www.rfc-editor.org/rfc/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
```yaml
variables:
@@ -895,12 +930,11 @@ include:
merge cyclonedx sboms:
stage: merge-cyclonedx-sboms
- image: alpine:latest
+ image:
+ name: cyclonedx/cyclonedx-cli:0.24.0
+ entrypoint: [""]
script:
- - wget https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.22.0/cyclonedx-linux-musl-x64 -O /usr/local/bin/cyclonedx-cli
- - chmod 755 /usr/local/bin/cyclonedx-cli
- - apk --update add --no-cache icu-dev libstdc++
- - find * -name "gl-sbom-*.cdx.json" -exec cyclonedx-cli merge --input-files {} --output-file gl-sbom-all.cdx.json +
+ - find . -name "gl-sbom-*.cdx.json" -exec /cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" +
artifacts:
paths:
- gl-sbom-all.cdx.json
@@ -913,7 +947,7 @@ this information is removed from the resulting merged file.
## Versioning and release process
-Please check the [Release Process documentation](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md).
+Check the [Release Process documentation](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md).
## Contributing to the vulnerability database
@@ -957,7 +991,7 @@ registry.gitlab.com/security-products/gemnasium-python:3
```
The process for importing Docker images into a local offline Docker registry depends on
-**your network security policy**. Please consult your IT staff to find an accepted and approved
+**your network security policy**. Consult your IT staff to find an accepted and approved
process by which external resources can be imported or temporarily accessed.
These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
@@ -1039,7 +1073,7 @@ ensure that it can reach your private repository. Here is an example configurati
1. Fetch the certificate from your repository URL and add it to the project:
```shell
- echo -n | openssl s_client -connect pypi.example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
+ printf "\n" | openssl s_client -connect pypi.example.com:443 -servername pypi.example.com | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
```
1. Point `setup.py` at the newly downloaded certificate:
@@ -1109,6 +1143,13 @@ version number).
## Troubleshooting
+### Increase log verbosity
+
+When a [job log](../../../ci/jobs/index.md#expand-and-collapse-job-log-sections)
+doesn't contain enough information about a dependency-scanning failure,
+[set `SECURE_LOG_LEVEL` to `debug`](#configuring-dependency-scanning)
+and check the resulting, more verbose log.
+
### Working around missing support for certain languages or package managers
As noted in the ["Supported languages" section](#supported-languages-and-package-managers)
@@ -1269,3 +1310,44 @@ gemnasium-python-dependency_scanning:
before_script:
- apt-get update && apt-get install -y libpq-dev
```
+
+### Error: Project has `<number>` unresolved dependencies
+
+The error message `Project has <number> unresolved dependencies` indicates a dependency resolution problem caused by your `gradle.build` or `gradle.build.kts` file. In the current release, `gemnasium-maven` cannot continue processing when an unresolved dependency is encountered. However, There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/337083) to allow `gemnasium-maven` to recover from unresolved dependency errors and produce a dependency graph. Until this issue has been resolved, you'll need to consult the [Gradle dependency resolution docs](https://docs.gradle.org/current/userguide/dependency_resolution.html) for details on how to fix your `gradle.build` file.
+
+### Setting build constraints when scanning Go projects
+
+Dependency scanning runs within a `linux/amd64` container. As a result, the build list generated
+for a Go project will contain dependencies that are compatible with this environment. If your deployment environment is not
+`linux/amd64`, the final list of dependencies might contain additional incompatible
+modules. The dependency list might also omit modules that are only compatible with your deployment environment. To prevent
+this issue, you can configure the build process to target the operating system and architecture of the deployment
+environment by setting the `GOOS` and `GOARCH` [environment variables](https://go.dev/ref/mod#minimal-version-selection)
+of your `.gitlab-ci.yml` file.
+
+For example:
+
+```yaml
+variables:
+ GOOS: "darwin"
+ GOARCH: "arm64"
+```
+
+You can also supply build tag constraints by using the `GOFLAGS` variable:
+
+```yaml
+variables:
+ GOFLAGS: "-tags=test_feature"
+```
+
+### Dependency Scanning of Go projects returns false positives
+
+The `go.sum` file contains an entry of every module that was considered while generating the project's [build list](https://go.dev/ref/mod#glos-build-list).
+Multiple versions of a module are included in the `go.sum` file, but the [MVS](https://go.dev/ref/mod#minimal-version-selection)
+algorithm used by `go build` only selects one. As a result, when dependency scanning uses `go.sum`, it might report false positives.
+
+To prevent false positives, gemnasium only uses `go.sum` if it is unable to generate the build list for the Go project. If `go.sum` is selected, a warning occurs:
+
+```shell
+[WARN] [Gemnasium] [2022-09-14T20:59:38Z] â–¶ Selecting "go.sum" parser for "/test-projects/gitlab-shell/go.sum". False positives may occur. See https://gitlab.com/gitlab-org/gitlab/-/issues/321081.
+```
diff --git a/doc/user/application_security/generate_test_vulnerabilities/index.md b/doc/user/application_security/generate_test_vulnerabilities/index.md
index 4d424acf9c3..76d2227b86b 100644
--- a/doc/user/application_security/generate_test_vulnerabilities/index.md
+++ b/doc/user/application_security/generate_test_vulnerabilities/index.md
@@ -2,27 +2,31 @@
type: reference, howto
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Generate test vulnerabilities
-You can generate test vulnerabilities when you work on the [Vulnerability Report](../vulnerability_report/index.md).
+You can generate test vulnerabilities for the [Vulnerability Report](../vulnerability_report/index.md) to test GitLab
+vulnerability management features without running a pipeline.
+1. Login in to GitLab.
1. Go to `/-/profile/personal_access_tokens` and generate a personal access token with `api` permissions.
1. Go to your project page and find the project ID. You can find the project ID below the project title.
-1. Open a terminal and go to the `gitlab/qa` directory.
+1. [Clone the GitLab repository](../../../gitlab-basics/start-using-git.md#clone-a-repository) to your local machine.
+1. Open a terminal and go to `gitlab/qa` directory.
+1. Run `bundle install`
1. Run the following command:
```shell
-GITLAB_QA_ACCESS_TOKEN=<your_personal_access_token> GITLAB_URL="http://localhost:3000" bundle exec rake vulnerabilities:setup\[<your_project_id>,<vulnerability_count>\] --trace
+GITLAB_QA_ACCESS_TOKEN=<your_personal_access_token> GITLAB_URL="<address:port>" bundle exec rake vulnerabilities:setup\[<your_project_id>,<vulnerability_count>\] --trace
```
Make sure you do the following:
- Replace `<your_personal_access_token>` with the token you generated in step one.
-- Double check the `GITLAB_URL`. It should point to the running local instance.
-- Replace `<your_project_id>` with the ID you obtained in step two.
+- Double check the `GITLAB_URL`. It should point to address and port of your GitLab instance, for example `http://localhost:3000` if you are running GDK
+- Replace `<your_project_id>` with the ID you obtained in step three above.
- Replace `<vulnerability_count>` with the number of vulnerabilities you'd like to generate.
-The script creates the specified amount of vulnerabilities in the project.
+The script creates the specified number of placeholder vulnerabilities in the project.
diff --git a/doc/user/application_security/get-started-security.md b/doc/user/application_security/get-started-security.md
index ee7864b5ce9..b6213a98f91 100644
--- a/doc/user/application_security/get-started-security.md
+++ b/doc/user/application_security/get-started-security.md
@@ -1,7 +1,7 @@
---
stage: DevSecOps
group: Technical writing
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Get started with GitLab application security **(ULTIMATE)**
@@ -14,7 +14,7 @@ The following steps will help you get the most from GitLab application security
1. Enable [Secret Detection](secret_detection/index.md) and [Dependency Scanning](dependency_scanning/index.md)
to identify any leaked secrets and vulnerable packages in your codebase.
- - For all security scanners, enable them by updating your `[.gitlab-ci.yml](../../ci/yaml/gitlab_ci_yaml.md)` directly on your `default` branch. This creates a baseline scan of your `default` branch, which is necessary for
+ - For all security scanners, enable them by updating your [`.gitlab-ci.yml`](../../ci/yaml/gitlab_ci_yaml.md) directly on your `default` branch. This creates a baseline scan of your `default` branch, which is necessary for
feature branch scans to be compared against. This allows [merge requests](../project/merge_requests/index.md)
to display only newly-introduced vulnerabilities. Otherwise, merge requests will display every
vulnerability in the branch, regardless of whether it was introduced by a change in the branch.
@@ -36,7 +36,7 @@ The following steps will help you get the most from GitLab application security
remediating existing vulnerabilities and preventing the introduction of new ones.
1. Enable other scan types such as [SAST](sast/index.md), [DAST](dast/index.md),
[Fuzz testing](coverage_fuzzing/index.md), or [Container Scanning](container_scanning/index.md).
-1. Use [Compliance Pipelines](../../user/project/settings/index.md#compliance-pipeline-configuration)
+1. Use [Compliance Pipelines](../group/manage.md#configure-a-compliance-pipeline)
or [Scan Execution Policies](policies/scan-execution-policies.md) to enforce required scan types
and ensure separation of duties between security and engineering.
1. Consider enabling [Review Apps](../../development/testing_guide/review_apps.md) to allow for DAST
diff --git a/doc/user/application_security/iac_scanning/index.md b/doc/user/application_security/iac_scanning/index.md
index 1b9cdb11ea3..150c2b732d8 100644
--- a/doc/user/application_security/iac_scanning/index.md
+++ b/doc/user/application_security/iac_scanning/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Infrastructure as Code (IaC) Scanning
@@ -43,7 +43,7 @@ GitLab IaC scanning supports a variety of IaC configuration files. Our IaC secur
| OpenAPI | [KICS](https://kics.io/) | 14.5 |
| Terraform <sup>2</sup> | [KICS](https://kics.io/) | 14.5 |
-1. IaC scanning can analyze Azure Resource Manager templates in JSON format. If you write templates in the [Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) language, you must use [the bicep CLI](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-cli) to convert your Bicep files into JSON before GitLab IaC scanning can analyze them.
+1. IaC scanning can analyze Azure Resource Manager templates in JSON format. If you write templates in the [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview) language, you must use [the bicep CLI](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-cli) to convert your Bicep files into JSON before GitLab IaC scanning can analyze them.
1. Terraform modules in a custom registry are not scanned for vulnerabilities. You can follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/357004) for the proposed feature.
### Supported distributions
diff --git a/doc/user/application_security/img/secure_tools_and_cicd_stages.png b/doc/user/application_security/img/secure_tools_and_cicd_stages.png
new file mode 100644
index 00000000000..3dbfd835baf
--- /dev/null
+++ b/doc/user/application_security/img/secure_tools_and_cicd_stages.png
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index fbd617351da..809fa5f3764 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Secure your application **(ULTIMATE)**
@@ -32,6 +32,25 @@ schedule. Coverage includes:
- Vulnerabilities in a running web application.
- Infrastructure as code configuration.
+Each of the GitLab application security tools is relevant to specific stages of the feature development workflow.
+
+- Commit
+ - SAST
+ - Secret Detection
+ - IaC Scanning
+ - Dependency Scanning
+ - License Scanning
+ - Coverage-guided Fuzz Testing
+- Build
+ - Container Scanning
+- Test
+ - API Security
+ - DAST
+- Deploy
+ - Operational Container Scanning
+
+![CI/CD stages and matching GitLab application security tools](img/secure_tools_and_cicd_stages.png)
+
### Source code analysis
Source code analysis occurs on every code commit. Details of vulnerabilities detected are provided
@@ -48,7 +67,7 @@ Analysis of the web application occurs on every code commit. As part of the CI/C
application is built, deployed to a test environment, and subjected to the following tests:
- Test for known application vectors - [Dynamic Application Security Testing (DAST)](dast/index.md).
-- Analysis of APIs for known attack vectors - [DAST API](dast_api/index.md).
+- Analysis of APIs for known attack vectors - [API Security](dast_api/index.md).
- Analysis of web APIs for unknown bugs and vulnerabilities - [API fuzzing](api_fuzzing/index.md).
### Dependency analysis
@@ -66,7 +85,7 @@ For more details, see
[Dependency Scanning compared to Container Scanning](dependency_scanning/index.md#dependency-scanning-compared-to-container-scanning).
Additionally, dependencies in operational container images can be analyzed for vulnerabilities
-on a regular schedule or cadence. For more details, see [Cluster Image Scanning](cluster_image_scanning/index.md).
+on a regular schedule or cadence. For more details, see [Operational Container Scanning](../../user/clusters/agent/vulnerabilities.md).
### Infrastructure analysis
@@ -152,6 +171,28 @@ does not use the `SECURE_ANALYZERS_PREFIX` variable. To override its Docker imag
the instructions for
[Running container scanning in an offline environment](container_scanning/index.md#running-container-scanning-in-an-offline-environment).
+### Use security scanning tools with merge request pipelines
+
+By default, the application security jobs are configured to run for branch pipelines only.
+To use them with [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md),
+you must reference the [`latest` templates](../../development/cicd/templates.md).
+
+All `latest` security templates support merge request pipelines.
+
+For example, to run both SAST and Dependency Scanning:
+
+```yaml
+include:
+ - template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
+ - template: Jobs/SAST.latest.gitlab-ci.yml
+```
+
+NOTE:
+Mixing `latest` and `stable` security templates can cause both MR and branch pipelines to run. We recommend choosing `latest` or `stable` for all security scanners.
+
+NOTE:
+Latest templates can receive breaking changes in any release.
+
## Default behavior of GitLab security scanning tools
### Secure jobs in your pipeline
@@ -446,7 +487,7 @@ Security and compliance teams must ensure that security scans:
GitLab provides two methods of accomplishing this, each with advantages and disadvantages.
-- [Compliance framework pipelines](../project/settings/index.md#compliance-pipeline-configuration)
+- [Compliance framework pipelines](../group/manage.md#configure-a-compliance-pipeline)
are recommended when:
- Scan execution enforcement is required for any scanner that uses a GitLab template, such as SAST IaC, DAST, Dependency Scanning,
@@ -486,6 +527,7 @@ Feedback is welcome on our vision for [unifying the user experience for these tw
<!-- NOTE: The below subsection(`### Secure job failing with exit code 1`) documentation URL is referred in the [/gitlab-org/security-products/analyzers/command](https://gitlab.com/gitlab-org/security-products/analyzers/command/-/blob/main/command.go#L19) repository. If this section/subsection changes, please ensure to update the corresponding URL in the mentioned repository.
-->
+
### Secure job failing with exit code 1
WARNING:
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index 7344695886a..2db8e9522db 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Offline environments **(ULTIMATE SELF)**
@@ -131,7 +131,7 @@ to be able to use the `docker` command inside the jobs. This runner can be insta
a bastion, and used only for this specific project.
WARNING:
-This template does not include updates for the container scanning analyzer. Please see
+This template does not include updates for the container scanning analyzer. See
[Container scanning offline directions](../container_scanning/index.md#running-container-scanning-in-an-offline-environment).
#### Scheduling the updates
diff --git a/doc/user/application_security/policies/img/scan_execution_policy_rule_mode_v15_5.png b/doc/user/application_security/policies/img/scan_execution_policy_rule_mode_v15_5.png
new file mode 100644
index 00000000000..5ae7c2e065a
--- /dev/null
+++ b/doc/user/application_security/policies/img/scan_execution_policy_rule_mode_v15_5.png
Binary files differ
diff --git a/doc/user/application_security/policies/img/scan_execution_policy_yaml_mode_v14_7.png b/doc/user/application_security/policies/img/scan_execution_policy_yaml_mode_v14_7.png
deleted file mode 100644
index 04768d2e18a..00000000000
--- a/doc/user/application_security/policies/img/scan_execution_policy_yaml_mode_v14_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 9b86ef7316a..b1315329071 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Security Policies
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Policies **(ULTIMATE)**
@@ -135,7 +135,7 @@ See [Scan result policies](scan-result-policies.md).
## Roadmap
-See the [Category Direction page](https://about.gitlab.com/direction/protect/security_orchestration/)
+See the [Category Direction page](https://about.gitlab.com/direction/govern/security_policies/security_policy_management/)
for more information on the product direction of security policies within GitLab.
## Troubleshooting
diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md
index f2fc52a2de8..41d25dfa8c8 100644
--- a/doc/user/application_security/policies/scan-execution-policies.md
+++ b/doc/user/application_security/policies/scan-execution-policies.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Security Policies
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Scan execution policies **(ULTIMATE)**
@@ -9,13 +9,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Group-level security policies were [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4425) in GitLab 15.2.
> - Group-level security policies were [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/356258) in GitLab 15.4.
-Group, sub-group, or project owners can use scan execution policies to require that security scans run on a specified
-schedule or with the project (or multiple projects if the policy is defined at a group or sub-group level) pipeline. Required scans are injected into the CI pipeline as new jobs
+Group, subgroup, or project owners can use scan execution policies to require that security scans run on a specified
+schedule or with the project (or multiple projects if the policy is defined at a group or subgroup level) pipeline. Required scans are injected into the CI pipeline as new jobs
with a long, random job name. In the unlikely event of a job name collision, the security policy job overwrites
any pre-existing job in the pipeline. If a policy is created at the group-level, it will apply to every child
-project or sub-group. A group-level policy cannot be edited from a child project or sub-group.
+project or subgroup. A group-level policy cannot be edited from a child project or subgroup.
-This feature has some overlap with [compliance framework pipelines](../../project/settings/index.md#compliance-pipeline-configuration),
+This feature has some overlap with [compliance framework pipelines](../../group/manage.md#configure-a-compliance-pipeline),
as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
For details on the similarities and differences between these features, see
[Enforce scan execution](../index.md#enforce-scan-execution).
@@ -29,7 +29,7 @@ an error appears that states `chosen stage does not exist`.
## Scan execution policy editor
NOTE:
-Only group, sub-group, or project Owners have the [permissions](../../permissions.md#project-members-permissions)
+Only group, subgroup, or project Owners have the [permissions](../../permissions.md#project-members-permissions)
to select Security Policy Project.
Once your policy is complete, save it by selecting **Create via merge request**
@@ -43,9 +43,7 @@ Most policy changes take effect as soon as the merge request is merged. Any chan
do not go through a merge request and are committed directly to the default branch may require up to 10 minutes
before the policy changes take effect.
-![Scan Execution Policy Editor YAML Mode](img/scan_execution_policy_yaml_mode_v14_7.png)
-
-The policy editor currently only supports the YAML mode. The Rule mode is tracked in the [Allow Users to Edit Rule-mode Scan Execution Policies in the Policy UI](https://gitlab.com/groups/gitlab-org/-/epics/5363) epic.
+![Scan Execution Policy Editor Rule Mode](img/scan_execution_policy_rule_mode_v15_5.png)
## Scan execution policies schema
@@ -90,13 +88,39 @@ 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. |
+| `agents` | `object` | | The name of the [GitLab agents](../../clusters/agent/index.md) where [cluster image scanning](../../clusters/agent/vulnerabilities.md) will run. The object key is the name of the Kubernetes cluster configured for your project in GitLab. You can use the optional value of the object to select and scan specific Kubernetes resources. |
GitLab supports the following types of CRON syntax for the `cadence` field:
- A daily cadence of once per hour at a specified hour, for example: `0 18 * * *`
- A weekly cadence of once per week on a specified day and at a specified hour, for example: `0 13 * * 0`
-It is possible that other elements of the CRON syntax will work in the cadence field, however, GitLab does not officially test or support them.
+Other elements of the CRON syntax may work in the cadence field, however, GitLab does not officially test or support them. The CRON expression is evaluated in UTC by default. If you have a self-managed GitLab instance and have [changed the server timezone](../../../administration/timezone.md), the CRON expression is evaluated with the new timezone.
+
+### `agent` schema
+
+Use this schema to define `agents` objects in the [`schedule` rule type](#schedule-rule-type).
+
+| Field | Type | Possible values | Description |
+|--------------|---------------------|--------------------------|-------------|
+| `namespaces` | `array` of `string` | | The namespace that is scanned. If empty, all namespaces will be scanned. |
+
+#### Policy example
+
+```yaml
+- name: Enforce Container Scanning in cluster connected through gitlab-agent for production and staging namespaces
+ enabled: true
+ rules:
+ - type: schedule
+ cadence: '0 10 * * *'
+ agents:
+ gitlab-agent:
+ namespaces:
+ - 'production'
+ - 'staging'
+ actions:
+ - scan: container_scanning
+```
## `scan` action type
@@ -105,7 +129,7 @@ rule in the defined policy are met.
| Field | Type | Possible values | Description |
|-------|------|-----------------|-------------|
-| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_scanning`, `cluster_image_scanning` | The action's type. |
+| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_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` | | A set of CI variables, supplied as an array of `key: value` pairs, to apply and enforce for the selected scan. The `key` is the variable name, with its `value` provided as a string. This parameter supports any variable that the GitLab CI job supports for the specified scan. |
@@ -126,9 +150,8 @@ 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 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.
- A cluster with a name provided in the `clusters` object must be created and configured for the project.
+- A container scanning scan that is configured for the `pipeline` rule type ignores the agent defined in the `agents` object. The `agents` object is only considered for `schedule` rule types.
+ An agent with a name provided in the `agents` object must be created and configured for the project.
- The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines).
## Example security policies project
@@ -186,8 +209,6 @@ In this example:
and `Site Profile D`.
- 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.
## Example for scan execution policy editor
diff --git a/doc/user/application_security/policies/scan-result-policies.md b/doc/user/application_security/policies/scan-result-policies.md
index 78a97b36e92..45b715a52b8 100644
--- a/doc/user/application_security/policies/scan-result-policies.md
+++ b/doc/user/application_security/policies/scan-result-policies.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Security Policies
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Scan result policies **(ULTIMATE)**
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index ec8e8e6fd93..b7932aae35c 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SAST analyzers **(FREE)**
diff --git a/doc/user/application_security/sast/customize_rulesets.md b/doc/user/application_security/sast/customize_rulesets.md
index 919a3565d88..a0742eb79a7 100644
--- a/doc/user/application_security/sast/customize_rulesets.md
+++ b/doc/user/application_security/sast/customize_rulesets.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customize rulesets **(ULTIMATE)**
@@ -166,7 +166,7 @@ Configure a passthrough these parameters:
| `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. |
+| `ref` | This option only applies to the `git` passthrough type and contains the name of the branch or the SHA to be used. When using a branch name, specify it in the form `refs/heads/<branch>`, not `refs/remotes/<remote_name>/<branch>`. |
| `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. |
@@ -237,7 +237,7 @@ 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
+ `refs/heads/test` from the `myrules` Git repository, and revision
`97f7686` from the `sast-rules` Git repository. 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
@@ -262,7 +262,7 @@ Afterwards, Semgrep is invoked with the final configuration located under
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/user/myrules.git"
- ref = "refs/remotes/origin/test"
+ ref = "refs/heads/test"
[[semgrep.passthrough]]
type = "git"
@@ -309,7 +309,7 @@ It does not explicitly store credentials in the configuration file. To reduce th
[[semgrep.passthrough]]
type = "git"
value = "$GITURL"
- ref = "refs/remotes/origin/main"
+ ref = "refs/heads/main"
```
### Configure the append mode for passthroughs
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index c9bfecffecc..6b8bc1933a3 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Static Application Security Testing (SAST) **(FREE)**
@@ -138,7 +138,7 @@ The following analyzers have multi-project support:
#### Enable multi-project support for Security Code Scan
Multi-project support in the Security Code Scan requires a Solution (`.sln`) file in the root of
-the repository. For details on the Solution format, see the Microsoft reference [Solution (`.sln`) file](https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2019).
+the repository. For details on the Solution format, see the Microsoft reference [Solution (`.sln`) file](https://learn.microsoft.com/en-us/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2019).
### Supported distributions
@@ -357,7 +357,7 @@ Support for more languages and analyzers is tracked in [this epic](https://gitla
### Using CI/CD variables to pass credentials for private repositories
-Some analyzers require downloading the project's dependencies in order to
+Some analyzers require downloading the project's dependencies to
perform the analysis. In turn, such dependencies may live in private Git
repositories and thus require credentials like username and password to download them.
Depending on the analyzer, such credentials can be provided to
@@ -503,7 +503,7 @@ From highest to lowest severity, the logging levels are:
#### Custom Certificate Authority
To trust a custom Certificate Authority, set the `ADDITIONAL_CA_CERT_BUNDLE` variable to the bundle
-of CA certs that you want to trust in the SAST environment. 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:
+of CA certs that you want to trust in the SAST environment. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://www.rfc-editor.org/rfc/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
```yaml
variables:
@@ -680,7 +680,7 @@ registry.gitlab.com/security-products/spotbugs:2
```
The process for importing Docker images into a local offline Docker registry depends on
-**your network security policy**. Please consult your IT staff to find an accepted and approved
+**your network security policy**. Consult your IT staff to find an accepted and approved
process by which external resources can be imported or temporarily accessed. These scanners are [periodically updated](../index.md#vulnerability-scanner-maintenance)
with new definitions, and you may be able to make occasional updates on your own.
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index fe029b26ce5..df6bb19ac25 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Secret Detection **(FREE)**
@@ -120,6 +120,10 @@ To enable Secret Detection using a merge request:
Pipelines now include a Secret Detection job, and the results are included in the merge request
widget.
+## Responding to a leaked secret
+
+If the scanner detects a secret we recommend you rotate it immediately. [Purging a file from the repository's history](../../project/repository/reducing_the_repo_size_using_git.md#purge-files-from-repository-history) may not be effective in removing all references to the file. Also, the secret remains in any forks of the repository.
+
## Configure scan settings
The Secret Detection scan settings can be changed through [CI/CD variables](#available-cicd-variables)
@@ -150,6 +154,18 @@ secret_detection:
SECRET_DETECTION_HISTORIC_SCAN: "true"
```
+### Ignoring Secrets
+
+You might want to add a fake secret to your code base. For instance, you can use a fake secret as an example in your documentation or test suite.
+
+In these cases, Secret Detection can ignore the fake secret and not report it as a vulnerability. To ignore a secret, add `gitleaks:allow` as a comment to the line that contains the secret.
+
+For example:
+
+```ruby
+ "A personal token for GitLab will look like glpat-JUST20LETTERSANDNUMB" #gitleaks:allow
+```
+
### Available CI/CD variables
Secret Detection can be customized by defining available CI/CD variables:
@@ -294,6 +310,11 @@ To create a custom configuration, you can use passthrough chains. Passthroughs c
to build more complex configurations. For more details, see
[SAST Customize ruleset](../sast/customize_rulesets.md).
+Only the following passthrough types are supported by the `secrets` analyzer:
+
+- `file`
+- `raw`
+
In the `secret-detection-ruleset.toml` file, do one of the following:
- Define a custom ruleset, for example:
@@ -384,7 +405,7 @@ of CA certificates that you trust. Do this either in the `.gitlab-ci.yml` file,
variable, or as a CI/CD variable.
- In the `.gitlab-ci.yml` file, the `ADDITIONAL_CA_CERT_BUNDLE` value must contain the
- [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1).
+ [text representation of the X.509 PEM public-key certificate](https://www.rfc-editor.org/rfc/rfc7468#section-5.1).
For example:
diff --git a/doc/user/application_security/secret_detection/post_processing.md b/doc/user/application_security/secret_detection/post_processing.md
index 9771658da4e..8dbe459d4af 100644
--- a/doc/user/application_security/secret_detection/post_processing.md
+++ b/doc/user/application_security/secret_detection/post_processing.md
@@ -1,7 +1,7 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Secret Detection post-processing and revocation **(FREE SAAS)**
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 967e8da58a9..af98fc783e7 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Security Dashboards and Security Center **(ULTIMATE)**
diff --git a/doc/user/application_security/terminology/index.md b/doc/user/application_security/terminology/index.md
index d50cce3b4e8..085a762fffa 100644
--- a/doc/user/application_security/terminology/index.md
+++ b/doc/user/application_security/terminology/index.md
@@ -1,20 +1,21 @@
---
stage: Secure
group: Static Analysis
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
-# Secure and Protect terminology **(FREE)**
+# Secure and Govern terminology **(FREE)**
-This terminology list for GitLab Secure and Protect aims to:
+The glossary of terms aims to achieve the following:
-- Promote a ubiquitous language for discussing application security.
-- Improve the effectiveness of communication regarding GitLab application security features.
-- Get new contributors up to speed faster.
+- Promote a ubiquitous language that can be used everywhere - with customers, on issues, in Slack, in code.
+- Improve the effectiveness of communication between team members.
+- Reduce the potential for miscommunication.
+- Bring new team members and community contributors up to speed faster, reducing the time to productivity.
-This document defines application security terms in the specific context of GitLab Secure and
-Protect features. Terms may therefore have different meanings outside that context.
+The definitions of the terms outlined in this document are in the context of the GitLab
+products. Therefore, a term may have a different meaning to users outside of GitLab.
## Terms
@@ -28,9 +29,7 @@ an artifact after the job is complete. GitLab ingests this report, allowing user
manage found vulnerabilities. For more information, see [Security Scanner Integration](../../../development/integrations/secure.md).
Many GitLab analyzers follow a standard approach using Docker to run a wrapped scanner. For example,
-the Docker image `bandit-sast` is an analyzer that wraps the scanner `Bandit`. You can optionally
-use the [Common library](https://gitlab.com/gitlab-org/security-products/analyzers/common)
-to assist in building an Analyzer.
+the image `semgrep` is an analyzer that wraps the scanner `Semgrep`.
### Attack surface
@@ -44,6 +43,12 @@ The set of meaningful test cases that are generated while the fuzzer is running.
test case produces new coverage in the tested program. It's advised to re-use the corpus and pass it
to subsequent runs.
+### CNA
+
+[CVE](#cve) Numbering Authorities (CNAs) are organizations from around the world that are authorized by
+the [Mitre Corporation](https://cve.mitre.org/) to assign [CVE](#cve)s to vulnerabilities in products or
+services within their respective scope. [GitLab is a CNA](https://about.gitlab.com/security/cve/).
+
### CVE
Common Vulnerabilities and Exposures (CVE®) is a list of common identifiers for publicly known
@@ -63,6 +68,11 @@ architecture. If left unaddressed, weaknesses could result in systems, networks,
vulnerable to attack. The CWE List and associated classification taxonomy serve as a language that
you can use to identify and describe these weaknesses in terms of CWEs.
+### Deduplication
+
+When a category's process deems findings to be the same, or if they are similar enough that a noise reduction is
+required, only one finding is kept and the others are eliminated. Read more about the [deduplication process](../vulnerability_report/pipeline.md#deduplication-process).
+
### Duplicate finding
A legitimate finding that is reported multiple times. This can occur when different scanners
@@ -86,6 +96,13 @@ applications, and infrastructure.
Findings are all potential vulnerability items scanners identify in MRs/feature branches. Only after merging to default does a finding become a [vulnerability](#vulnerability).
+### Grouping
+
+A flexible and non-destructive way to visually organize vulnerabilities in groups when there are multiple findings
+that are likely related but do not qualify for deduplication. For example, you can include findings that should be
+evaluated together, would be fixed by the same action, or come from the same source. Grouping behavior for vulnerabilities is
+under development and tracked in issue [267588](https://gitlab.com/gitlab-org/gitlab/-/issues/267588).
+
### Insignificant finding
A legitimate finding that a particular customer doesn't care about.
@@ -93,16 +110,18 @@ A legitimate finding that a particular customer doesn't care about.
### Location fingerprint
A finding's location fingerprint is a text value that's unique for each location on the attack
-surface. Each Secure product defines this according to its type of attack surface. For example, SAST
+surface. Each security product defines this according to its type of attack surface. For example, SAST
incorporates file path and line number.
-### Package managers
+### Package managers and package types
+
+#### Package managers
-A Package manager is a system that manages your project dependencies.
+A package manager is a system that manages your project dependencies.
The package manager provides a method to install new dependencies (also referred to as "packages"), manage where packages are stored on your file system, and offer capabilities for you to publish your own packages.
-### Package types
+#### Package types
Each package manager, platform, type, or ecosystem has its own conventions and protocols to identify, locate, and provision software packages.
@@ -200,9 +219,26 @@ table.package-managers-and-types ul {
A page that displays findings discovered in the associated CI pipeline.
+### Post-filter
+
+Post-filters help reduce noise in the scanner results and automate manual tasks. You can specify criteria that updates
+or modifies vulnerability data based on scanner results. For example, you can flag findings as likely False Positives
+and automatically resolve vulnerabilities that are no longer detected. These are not permanent actions and can be changed.
+
+Support for automatically resolving findings is tracked in epic [7478](https://gitlab.com/groups/gitlab-org/-/epics/7478) and
+support for cheap scan is proposed in issue [349926](https://gitlab.com/gitlab-org/gitlab/-/issues/349926).
+
+### Pre-filter
+
+An irreversible action that is done to filter out target(s) before analysis occurs. This is usually provided to allow
+the user to reduce scope and noise as well as speed up the analysis. This should not be done if a record is needed as
+we currently do not store anything related to the skipped/excluded code or assets.
+
+Examples: `DS_EXCLUDED_PATHS` should `Exclude files and directories from the scan based on the paths provided.`
+
### Primary identifier
-A finding's primary identifier is a value unique to that finding. The external type and external ID
+A finding's primary identifier is a value that is unique to each finding. The external type and external ID
of the finding's [first identifier](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/v2.4.0-rc1/dist/sast-report-format.json#L228)
combine to create the value.
@@ -218,15 +254,19 @@ once it's imported into the database.
### Scan type (report type)
-The type of scan. This must be one of the following:
+Describes the type of scan. This must be one of the following:
+- `api_fuzzing`
- `cluster_image_scanning`
- `container_scanning`
+- `coverage_fuzzing`
- `dast`
- `dependency_scanning`
- `sast`
- `secret_detection`
+This list is subject to change as scanners are added.
+
### Scanner
Software that can scan for vulnerabilities. The resulting scan report is typically not in the
@@ -235,9 +275,12 @@ Software that can scan for vulnerabilities. The resulting scan report is typical
### Secure product
A group of features related to a specific area of application security with first-class support by
-GitLab. Products include Container Scanning, Dependency Scanning, Dynamic Application Security
-Testing (DAST), Secret Detection, Static Application Security Testing (SAST), and Fuzz Testing. Each
-of these products typically include one or more analyzers.
+GitLab.
+
+Products include Container Scanning, Dependency Scanning, Dynamic Application Security
+Testing (DAST), Secret Detection, Static Application Security Testing (SAST), and Fuzz Testing.
+
+Each of these products typically include one or more analyzers.
### Secure report format
@@ -267,6 +310,7 @@ is listed as GitLab.
A flaw that has a negative impact on the security of its environment. Vulnerabilities describe the
error or weakness, and don't describe where the error is located (see [finding](#finding)).
+
Each vulnerability maps to a unique finding.
Vulnerabilities exist in the default branch. Findings (see [finding](#finding)) are all potential vulnerability items scanners identify in MRs/feature branches. Only after merging to default does a finding become a vulnerability.
@@ -280,8 +324,9 @@ When a [report finding](#report-finding) is stored to the database, it becomes a
Deals with the responsibility of matching findings across scans so that a finding's life cycle can
be understood. Engineers and security teams use this information to decide whether to merge code
-changes, and to see unresolved findings and when they were introduced. Vulnerabilities are tracked
-by comparing the location fingerprint, primary identifier, and report type.
+changes, and to see unresolved findings and when they were introduced.
+
+Vulnerabilities are tracked by comparing the location fingerprint, primary identifier, and report type.
### Vulnerability occurrence
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 91793272cce..9ddb1bb51e2 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerability Page **(ULTIMATE)**
@@ -103,7 +103,7 @@ To create a Jira issue for a vulnerability:
1. On the left sidebar, select **Security & Compliance > Vulnerability report**.
1. Select the vulnerability's description.
1. Select **Create Jira issue**.
-1. If you're not already logged in to Jira, log in.
+1. If you're not already logged in to Jira, sign in.
The Jira issue is created and opened in a new browser tab. The **Summary** and **Description**
fields are pre-populated from the vulnerability's details.
diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md
index aed86cd93aa..36f9578f999 100644
--- a/doc/user/application_security/vulnerabilities/severities.md
+++ b/doc/user/application_security/vulnerabilities/severities.md
@@ -2,7 +2,7 @@
type: reference
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerability severity levels **(ULTIMATE)**
@@ -56,7 +56,9 @@ the following tables:
| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
|------------------------------------------------------------------------------------------|------------------------------|----------------------------|-------------------------------------|
-| [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | **{check-circle}** Yes | CVSS v2.0 Rating and CVSS v3.1 Qualitative Severity Rating | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)`, `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
+| [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | **{check-circle}** Yes | CVSS v2.0 Rating and CVSS v3.1 Qualitative Severity Rating <sup>1</sup> | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)`, `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
+
+1. The CVSS v3.1 rating is used to calculate the severity level. If it's not available, the CVSS v2.0 rating is used instead.
## Container Scanning
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index ba448d410ea..59851fd192c 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Vulnerability Report **(ULTIMATE)**
@@ -174,7 +174,7 @@ To change the status of vulnerabilities in the table:
## Dismissing a vulnerability
When you evaluate a vulnerability and decide it requires no more action, you can mark it
-as **Dismissed**. Dismissed vulnerabilities don't appear in the merge request security widget
+as **Dismissed**. Dismissed vulnerabilities do not appear in the merge request security widget
when detected in future scans.
When a vulnerability is dismissed, a record is made of:
@@ -191,7 +191,7 @@ If a vulnerability is dismissed in error, reverse the dismissal by changing its
By default, vulnerabilities are sorted by severity level, with the highest-severity vulnerabilities listed at the top.
-To sort vulnerabilities by the date each vulnerability was detected, click the "Detected" column header.
+To sort vulnerabilities by the date each vulnerability was detected, select the "Detected" column header.
## Export vulnerability details
@@ -199,7 +199,7 @@ To sort vulnerabilities by the date each vulnerability was detected, click the "
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/213013) to the group-level Vulnerability Report in GitLab 13.1.
You can export details of the vulnerabilities listed in the Vulnerability Report. The export format
-is CSV (comma separated values). Note that all vulnerabilities are included because filters don't
+is CSV (comma separated values). Note that all vulnerabilities are included because filters do not
apply to the export.
Fields included are:
@@ -232,7 +232,7 @@ computer.
NOTE:
It may take several minutes for the download to start if your project contains
-thousands of vulnerabilities. Don't close the page until the download finishes.
+thousands of vulnerabilities. Do not close the page until the download finishes.
## Dismiss a vulnerability
diff --git a/doc/user/application_security/vulnerability_report/pipeline.md b/doc/user/application_security/vulnerability_report/pipeline.md
index 7faf273515c..9e20e4f6f78 100644
--- a/doc/user/application_security/vulnerability_report/pipeline.md
+++ b/doc/user/application_security/vulnerability_report/pipeline.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Govern
group: Threat Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# View vulnerabilities in a pipeline
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index 8de777672ff..3ceecf88c5e 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# AsciiDoc **(FREE)**
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
index e4fcdcd4653..d0aa9fa6119 100644
--- a/doc/user/award_emojis.md
+++ b/doc/user/award_emojis.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Award emoji **(FREE)**
diff --git a/doc/user/clusters/agent/ci_cd_tunnel.md b/doc/user/clusters/agent/ci_cd_tunnel.md
deleted file mode 100644
index 1b99fcf9739..00000000000
--- a/doc/user/clusters/agent/ci_cd_tunnel.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'ci_cd_workflow.md'
-remove_date: '2022-07-20'
----
-
-This document was moved to [another location](ci_cd_workflow.md).
-
-<!-- This redirect file can be deleted after <2022-07-20>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> \ No newline at end of file
diff --git a/doc/user/clusters/agent/ci_cd_workflow.md b/doc/user/clusters/agent/ci_cd_workflow.md
index 7a6c6dc8cd6..7a3c09687a5 100644
--- a/doc/user/clusters/agent/ci_cd_workflow.md
+++ b/doc/user/clusters/agent/ci_cd_workflow.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using GitLab CI/CD with a Kubernetes cluster **(FREE)**
@@ -156,9 +156,24 @@ deploy:
# ... rest of your job configuration
```
+### Using the agent with Auto DevOps
+
+If Auto DevOps is enabled, you must define the `KUBE_CONTEXT` CI/CD variable. Set the value of `KUBE_CONTEXT` to the context of the agent you want to use in your Auto DevOps pipeline jobs (`<PATH_TO_AGENT_CONFIG_REPOSITORY>:<AGENT_NAME>`).
+
+You can also use different agents for different Auto DevOps jobs. For instance, you can use one agent for `staging` jobs and a different agent for `production` jobs. To use multiple agents, define a unique CI/CD variable for each agent.
+
+For example:
+
+1. Add two [environment-scoped CI/CD variables](../../../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable) and name both `KUBE_CONTEXT`.
+1. Set the `environment` of the first variable to `staging`. Set the value of the variable to `<PATH_TO_AGENT_CONFIGURATION_PROJECT>:<STAGING_AGENT_NAME>`.
+1. Set the `environment` of the second variable to `production`. Set the value of the variable to `<PATH_TO_AGENT_CONFIGURATION_PROJECT>:<PRODUCTION_AGENT_NAME>`.
+
+When the `staging` job runs, it will connect to the cluster via the agent named `<STAGING_AGENT_NAME>`, and when the `production` job runs it will connect to the cluster via the agent named `<PRODUCTION_AGENT_NAME>`.
+
## Restrict project and group access by using impersonation **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/357934) in GitLab 15.5 to add impersonation support for environment tiers.
By default, your CI/CD job inherits all the permissions from the service account used to install the
agent in the cluster.
@@ -191,16 +206,17 @@ impersonation credentials in the following way:
- `gitlab:ci_job` to identify all requests coming from CI jobs.
- The list of IDs of groups the project is in.
- The project ID.
- - The slug of the environment this job belongs to.
+ - The slug and tier of the environment this job belongs to.
Example: for a CI job in `group1/group1-1/project1` where:
- Group `group1` has ID 23.
- Group `group1/group1-1` has ID 25.
- Project `group1/group1-1/project1` has ID 150.
- - Job running in a prod environment.
+ - Job running in the `prod` environment, which has the `production` environment tier.
- Group list would be `[gitlab:ci_job, gitlab:group:23, gitlab:group:25, gitlab:project:150, gitlab:project_env:150:prod]`.
+ Group list would be `[gitlab:ci_job, gitlab:group:23, gitlab:group_env_tier:23:production, gitlab:group:25,
+ gitlab:group_env_tier:25:production, gitlab:project:150, gitlab:project_env:150:prod, gitlab:project_env_tier:150:production]`.
- `Extra` carries extra information about the request. The following properties are set on the impersonated identity:
@@ -213,6 +229,7 @@ impersonation credentials in the following way:
| `agent.gitlab.com/ci_job_id` | Contains the CI job ID. |
| `agent.gitlab.com/username` | Contains the username of the user the CI job is running as. |
| `agent.gitlab.com/environment_slug` | Contains the slug of the environment. Only set if running in an environment. |
+| `agent.gitlab.com/environment_tier` | Contains the tier of the environment. Only set if running in an environment. |
Example `config.yaml` to restrict access by the CI/CD job's identity:
@@ -260,6 +277,7 @@ See the [official Kubernetes documentation for details](https://kubernetes.io/do
## Related topics
- [Self-paced classroom workshop](https://gitlab-for-eks.awsworkshop.io) (Uses AWS EKS, but you can use for other Kubernetes clusters)
+- [Configure Auto DevOps](../../../topics/autodevops/cloud_deployments/auto_devops_with_gke.md#configure-auto-devops)
## Troubleshooting
diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md
index 67439788ef7..c0d4a5e088f 100644
--- a/doc/user/clusters/agent/gitops.md
+++ b/doc/user/clusters/agent/gitops.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using GitOps with a Kubernetes cluster **(FREE)**
diff --git a/doc/user/clusters/agent/gitops/helm.md b/doc/user/clusters/agent/gitops/helm.md
index bdc2664e7ba..af9f80618b5 100644
--- a/doc/user/clusters/agent/gitops/helm.md
+++ b/doc/user/clusters/agent/gitops/helm.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using Helm charts to update a Kubernetes cluster (Alpha) **(FREE)**
@@ -13,7 +13,7 @@ with your charts and values. To do this, you use the pull-based GitOps features
Kubernetes.
This feature is in Alpha and [an epic exists](https://gitlab.com/groups/gitlab-org/-/epics/7938)
-to track future work. Please tell us about your use cases by leaving comments in the epic.
+to track future work. Tell us about your use cases by leaving comments in the epic.
NOTE:
This feature is Alpha. In future releases, to accommodate new features, the configuration format might change without notice.
@@ -58,7 +58,7 @@ gitops:
| Keyword | Description |
|--|--|
-| `charts` | List of charts you want to be applied in your cluster. Charts are applied concurrently. All charts must be in the same directory. |
+| `charts` | List of charts you want to be applied in your cluster. Charts are applied concurrently. |
| `release_name` | Required. Name of the release to use when applying the chart. |
| `id` | Required. ID of the project where Helm chart is committed. No authentication mechanisms are currently supported. |
| `path` | Optional. Path of the chart in the project repository. Root of the repository is used by default. This is the directory with the `Chart.yaml` file. |
@@ -69,7 +69,6 @@ gitops:
Drift happens when the current configuration of an infrastructure resource differs from its desired configuration.
Typically, drift is caused by manually editing resources directly, rather than by editing the code that describes the desired state. Minimizing the risk of drift helps to ensure configuration consistency and successful operations.
-mechanism. Minimizing the risk of drift helps to ensure configuration consistency and successful operations.
In GitLab, the agent for Kubernetes regularly compares the desired state from the chart source with
the actual state from the Kubernetes cluster. Deviations from the desired state are fixed at every check. These checks
diff --git a/doc/user/clusters/agent/gitops/secrets_management.md b/doc/user/clusters/agent/gitops/secrets_management.md
index cf520c881bf..dc1cbe3009d 100644
--- a/doc/user/clusters/agent/gitops/secrets_management.md
+++ b/doc/user/clusters/agent/gitops/secrets_management.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Managing Kubernetes secrets in a GitOps workflow
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index eb62a733d36..7fdf0bb2bf0 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connecting a Kubernetes cluster with GitLab
@@ -91,7 +91,7 @@ Read about how to [migrate to the agent for Kubernetes](../../infrastructure/clu
- [GitOps examples and learning materials](gitops.md#related-topics)
- [GitLab CI/CD workflow](ci_cd_workflow.md)
- [Install the agent](install/index.md)
-- [Work with the agent](repository.md)
+- [Work with the agent](work_with_agent.md)
- [Troubleshooting](troubleshooting.md)
- [Guided explorations for a production ready GitOps setup](https://gitlab.com/groups/guided-explorations/gl-k8s-agent/gitops/-/wikis/home#gitlab-agent-for-kubernetes-gitops-working-examples)
- [CI/CD for Kubernetes examples and learning materials](ci_cd_workflow.md#related-topics)
diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md
index 0240fbb45f0..19628419784 100644
--- a/doc/user/clusters/agent/install/index.md
+++ b/doc/user/clusters/agent/install/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Installing the agent for Kubernetes **(FREE)**
@@ -48,7 +48,7 @@ For configuration settings, the agent uses a YAML file in the GitLab project. Yo
To create an agent configuration file:
1. Choose a name for your agent. The agent name follows the
- [DNS label standard from RFC 1123](https://tools.ietf.org/html/rfc1123). The name must:
+ [DNS label standard from RFC 1123](https://www.rfc-editor.org/rfc/rfc1123). The name must:
- Be unique in the project.
- Contain at most 63 characters.
@@ -110,6 +110,9 @@ in your cluster. You can either:
If you do not know which one to choose, we recommend starting with Helm.
+NOTE:
+To connect to multiple clusters, you must configure, register, and install an agent in each cluster. Make sure to give each agent a unique name.
+
#### Install the agent with Helm
To install the agent on your cluster using Helm:
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
deleted file mode 100644
index 8f3a8830202..00000000000
--- a/doc/user/clusters/agent/repository.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'work_with_agent.md'
-remove_date: '2022-07-19'
----
-
-This document was moved to [another location](work_with_agent.md).
-
-<!-- This redirect file can be deleted after <2022-07-19>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/clusters/agent/troubleshooting.md b/doc/user/clusters/agent/troubleshooting.md
index 0596755ec74..0c26c533cc3 100644
--- a/doc/user/clusters/agent/troubleshooting.md
+++ b/doc/user/clusters/agent/troubleshooting.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting the GitLab agent for Kubernetes
diff --git a/doc/user/clusters/agent/vulnerabilities.md b/doc/user/clusters/agent/vulnerabilities.md
index 2d20675b68b..dcb3276deb5 100644
--- a/doc/user/clusters/agent/vulnerabilities.md
+++ b/doc/user/clusters/agent/vulnerabilities.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Operational Container Scanning **(ULTIMATE)**
diff --git a/doc/user/clusters/agent/work_with_agent.md b/doc/user/clusters/agent/work_with_agent.md
index b28f7546379..566eae8e24e 100644
--- a/doc/user/clusters/agent/work_with_agent.md
+++ b/doc/user/clusters/agent/work_with_agent.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with the agent for Kubernetes **(FREE)**
@@ -67,13 +67,13 @@ The agent has two loggers:
- A general purpose logger, which defaults to `info`.
- A gRPC logger, which defaults to `error`.
-One can change their log levels by using a top-level `observability` section in the [agent configuration file](install/index.md#configure-your-agent), for example setting the levels to `debug` and `warning`:
+You can change your log levels by using a top-level `observability` section in the [agent configuration file](install/index.md#configure-your-agent), for example setting the levels to `debug` and `warn`:
```yaml
observability:
logging:
level: debug
- grpc_level: warning
+ grpc_level: warn
```
When `grpc_level` is set to `info` or below, there will be a lot of gRPC logs.
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
deleted file mode 100644
index 7b5ea7d12fd..00000000000
--- a/doc/user/clusters/applications.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-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
-remove_date: '2022-08-22'
-redirect_to: '../../update/removals.md#managed-cluster-applicationsgitlab-ciyml'
----
-
-# GitLab Managed Apps (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 13.12.
-and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/333610) in GitLab 15.0.
-Use the [cluster management project template](management_project_template.md) instead.
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 3dcec32b90c..75bc9e23c0f 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cluster cost management (DEPRECATED) **(ULTIMATE)**
diff --git a/doc/user/clusters/create/index.md b/doc/user/clusters/create/index.md
index b3d2b9f23fa..0721cea965a 100644
--- a/doc/user/clusters/create/index.md
+++ b/doc/user/clusters/create/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create Kubernetes clusters
diff --git a/doc/user/clusters/crossplane.md b/doc/user/clusters/crossplane.md
deleted file mode 100644
index 16615f88e25..00000000000
--- a/doc/user/clusters/crossplane.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-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
-remove_date: '2022-08-22'
-redirect_to: '../../update/removals.md#managed-cluster-applicationsgitlab-ciyml'
----
-
-# Crossplane configuration (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
-in GitLab 14.5. and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/333610)
-in GitLab 15.0. Use [crossplane](https://crossplane.io/) directly instead.
diff --git a/doc/user/clusters/environments.md b/doc/user/clusters/environments.md
index 96f41531576..98292cf9103 100644
--- a/doc/user/clusters/environments.md
+++ b/doc/user/clusters/environments.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cluster Environments (DEPRECATED) **(PREMIUM)**
diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md
index c7597896575..c5e56fcd3a7 100644
--- a/doc/user/clusters/integrations.md
+++ b/doc/user/clusters/integrations.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cluster integrations (DEPRECATED) **(FREE)**
@@ -88,11 +88,11 @@ Prometheus as long as you meet the requirements above.
To enable the Prometheus integration for your cluster:
1. Go to the cluster's page:
- - For a [project-level cluster](../project/clusters/index.md), navigate to your project's
+ - For a [project-level cluster](../project/clusters/index.md), go to your project's
**Infrastructure > Kubernetes clusters**.
- - For a [group-level cluster](../group/clusters/index.md), navigate to your group's
+ - For a [group-level cluster](../group/clusters/index.md), go to your group's
**Kubernetes** page.
- - For an [instance-level cluster](../instance/clusters/index.md), navigate to your instance's
+ - For an [instance-level cluster](../instance/clusters/index.md), go to your instance's
**Kubernetes** page.
1. Select the **Integrations** tab.
1. Check the **Enable Prometheus integration** checkbox.
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index 62f70faa630..df338e8fcee 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cluster management project (DEPRECATED) **(FREE)**
diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md
index cd71be321cc..bdd11f11f9c 100644
--- a/doc/user/clusters/management_project_template.md
+++ b/doc/user/clusters/management_project_template.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Manage cluster applications **(FREE)**
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 ce39e13d928..a86a84fe9ae 100644
--- a/doc/user/clusters/migrating_from_gma_to_project_template.md
+++ b/doc/user/clusters/migrating_from_gma_to_project_template.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrate from GitLab Managed Apps to Cluster Management Projects (DEPRECATED) **(FREE)**
diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md
index 96cb3f3ef38..ac4b20b5166 100644
--- a/doc/user/compliance/compliance_report/index.md
+++ b/doc/user/compliance/compliance_report/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Compliance report **(ULTIMATE)**
@@ -72,7 +72,7 @@ The following is a list of violations that are either:
When you select a row, a drawer is shown that provides further details about the merge
request:
-- Project name and [compliance framework label](../../project/settings/index.md#compliance-frameworks),
+- Project name and [compliance framework label](../../project/settings/index.md#add-a-compliance-framework-to-a-project),
if the project has one assigned.
- Link to the merge request.
- The merge request's branch path in the format `[source] into [target]`.
diff --git a/doc/user/compliance/index.md b/doc/user/compliance/index.md
index c6c4834228b..7981ab44bf9 100644
--- a/doc/user/compliance/index.md
+++ b/doc/user/compliance/index.md
@@ -2,7 +2,7 @@
type: reference
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Compliance **(ULTIMATE)**
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 19b01e4d854..fb5ce37c563 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Secure
group: Composition 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# License compliance **(ULTIMATE)**
@@ -100,7 +100,7 @@ To enable License Compliance in your project's pipeline, either:
(provided by [Auto DevOps](../../../topics/autodevops/index.md)).
- Include the [`License-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml) in your `.gitlab-ci.yml` file.
-Please note that License Compliance is not supported when GitLab is run with FIPS mode enabled.
+License Compliance is not supported when GitLab is run with FIPS mode enabled.
### Include the License Scanning template
@@ -556,8 +556,8 @@ license_scanning:
#### Using private NuGet registries
If you have a private NuGet registry you can add it as a source
-by adding it to the [`packageSources`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections)
-section of a [`nuget.config`](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file) file.
+by adding it to the [`packageSources`](https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections)
+section of a [`nuget.config`](https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file) file.
For example:
@@ -656,7 +656,7 @@ registry.gitlab.com/security-products/license-finder:latest
```
The process for importing Docker images into a local offline Docker registry depends on
-**your network security policy**. Please consult your IT staff to find an accepted and approved
+**your network security policy**. Consult your IT staff to find an accepted and approved
process by which external resources can be imported or temporarily accessed. Note that these scanners are [updated periodically](../../application_security/index.md#vulnerability-scanner-maintenance)
with new definitions, so consider if you are able to make periodic updates yourself.
@@ -869,30 +869,61 @@ A full list of variables can be found in [CI/CD variables](#available-cicd-varia
To find out what tools are pre-installed in the `license_scanning` Docker image use the following command:
```shell
-$ docker run --entrypoint='' registry.gitlab.com/security-products/license-finder:4 /bin/bash -lc 'asdf list'
+$ docker run --entrypoint='' -ti --rm registry.gitlab.com/security-products/license-finder:4 \
+ /bin/bash -c 'dpkg -i /opt/toolcache/*.deb && asdf list'
+...
+dotnet-core
+ 3.1.302
+elixir
+ 1.10.4
golang
- 1.14
+ 1.15.5
+ 1.16.2
gradle
- 6.3
+No versions installed
java
- adopt-openjdk-11.0.7+10
- adopt-openjdk-8u242-b08
+ 11
+ 14
+ 15
+ 8
maven
- 3.6.3
+No versions installed
nodejs
- 10.20.1
- 12.16.3
+ 10.21.0
+ 12.18.2
+ 14.17.1
php
- 7.4.5
+ 7.4.8
python
2.7.18
- 3.8.2
+ 3.3.7
+ 3.4.10
+ 3.5.9
+ 3.6.11
+ 3.7.7
+ 3.8.5
ruby
+ 2.4.10
+ 2.4.5
+ 2.4.9
+ 2.5.8
+ 2.6.0
+ 2.6.1
+ 2.6.2
+ 2.6.3
+ 2.6.4
+ 2.6.5
2.6.6
-sbt
- 1.3.8
+ 2.7.0
+ 2.7.1
+ 2.7.2
+rust
+ 1.45.0
```
+It might take more than 10 minutes to run the command above.
+This is because it installs every single tool version available in the Docker image.
+
To interact with the `license_scanning` runtime environment use the following command:
```shell
diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md
index 79f18e3abf1..d7ab2195e2d 100644
--- a/doc/user/crm/index.md
+++ b/doc/user/crm/index.md
@@ -1,7 +1,7 @@
---
stage: Plan
group: Certify
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customer relations management (CRM) **(FREE)**
@@ -186,7 +186,7 @@ When you use the `/add_contacts` or `/remove_contacts` quick actions, follow the
The root group is the topmost group in the group hierarchy.
-When you move an issue, project, or group **within the same group hierarchy**,
+When you move an issue, project, or group **in the same group hierarchy**,
issues retain their contacts.
When you move an issue or project and the **root group changes**,
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index ed0bcec9f49..13d5b27ad41 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -1,7 +1,7 @@
---
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
---
@@ -177,7 +177,7 @@ You can add an internal note **to an issue or an epic**. It's then visible only
Keep in mind:
- Replies to internal notes are also internal.
-- You can not turn an internal note into a regular comment.
+- You cannot turn an internal note into a regular comment.
Prerequisites:
@@ -315,7 +315,7 @@ At the top of the page, the number of unresolved threads is updated:
If you have multiple unresolved threads in a merge request, you can
create an issue to resolve them separately. In the merge request, at the top of the page,
-click the ellipsis icon button (**{ellipsis_v}**) in the threads control and then select **Create issue to resolve all threads**:
+select the ellipsis icon button (**{ellipsis_v}**) in the threads control and then select **Create issue to resolve all threads**:
![Open new issue for all unresolved threads](img/create_new_issue_v15_4.png)
diff --git a/doc/user/feature_flags.md b/doc/user/feature_flags.md
index e288be87474..cc4bfdb01de 100644
--- a/doc/user/feature_flags.md
+++ b/doc/user/feature_flags.md
@@ -1,7 +1,7 @@
---
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"
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-development-guidelines"
description: "Understand what 'GitLab features deployed behind flags' means."
layout: 'feature_flags'
---
diff --git a/doc/user/free_user_limit.md b/doc/user/free_user_limit.md
index 60091449256..3fbfb2e1aa7 100644
--- a/doc/user/free_user_limit.md
+++ b/doc/user/free_user_limit.md
@@ -1,31 +1,14 @@
---
stage: Growth
group: Acquisition
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Free user limit **(FREE SAAS)**
-From October 19, 2022, namespaces in GitLab.com on the Free tier
-will be limited to five (5) members per [namespace](namespace/index.md).
-This limit applies to top-level private groups.
+From October 19, 2022, a five-user limit will apply to top-level [namespaces](namespace/index.md) with private visibility on GitLab SaaS. These limits will roll out gradually, and impacted users will be notified in GitLab.com at least 60 days before the limit is applied.
-On the transition date, if your namespace has six or more unique members:
-
-- Five members will keep a status of `Active`.
-- Remaining members will get a status of `Over limit` and lose access to the
- group.
-- Members invited through a group or project invitation outside of the namespace
- will be removed. You can add these members back by inviting them through their
- username or email address on the **Members** page for your group or project.
-
-## How active members are determined
-
-On the transition date, we'll automatically select the members who keep their `Active` status
-in the following order, until we reach a total of five:
-
-1. Members with the Owner or Maintainer role.
-1. The most recently active members.
+When the five-user limit is applied, top-level private namespaces exceeding the user limit are placed in a read-only state. These namespaces cannot write new data to repositories, Git Large File Storage (LFS), packages, or registries.
## Manage members in your namespace
@@ -43,7 +26,7 @@ Prerequisite:
1. To remove a member, select **Remove user**.
If you need more time to manage your members, or to try GitLab features
-with a team of more than five members, you can [start a trial](https://about.gitlab.com/free-trial/).
+with a team of more than five members, you can [start a trial](https://gitlab.com/-/trial_registrations/new?glm_source=docs.gitlab.com&glm_content=free-user-limit).
A trial lasts for 30 days and includes an unlimited number of members.
## Related topics
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 62b685ea4f4..d3d50ee1a8f 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab.com settings **(FREE SAAS)**
@@ -146,22 +146,22 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/index.md).
Any settings or feature limits not listed here are using the defaults listed in
the related documentation.
-| Setting | GitLab.com | Default (self-managed) |
-|:-------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Artifacts maximum size (compressed) | 1 GB | See [Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size) |
-| Artifacts [expiry time](../../ci/yaml/index.md#artifactsexpire_in) | From June 22, 2020, deleted after 30 days unless otherwise specified (artifacts created before that date have no expiry). | See [Default artifacts expiration](../admin_area/settings/continuous_integration.md#default-artifacts-expiration) |
-| Scheduled Pipeline Cron | `*/5 * * * *` | See [Pipeline schedules advanced configuration](../../administration/cicd.md#change-maximum-scheduled-pipeline-frequency) |
-| Maximum jobs in active pipelines | `500` for Free tier, `1000` for all trial tiers, and unlimited otherwise. | See [Number of jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines) |
-| Maximum CI/CD subscriptions to a project | `2` | See [Number of CI/CD subscriptions to a project](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) |
-| Maximum number of pipeline triggers in a project | `25000` for Free tier, Unlimited for all paid tiers | See [Limit the number of pipeline triggers](../../administration/instance_limits.md#limit-the-number-of-pipeline-triggers) |
-| Maximum pipeline schedules in projects | `10` for Free tier, `50` for all paid tiers | See [Number of pipeline schedules](../../administration/instance_limits.md#number-of-pipeline-schedules) |
-| Maximum pipelines per schedule | `24` for Free tier, `288` for all paid tiers | See [Limit the number of pipelines created by a pipeline schedule per day](../../administration/instance_limits.md#limit-the-number-of-pipelines-created-by-a-pipeline-schedule-per-day) |
-| Maximum number of schedule rules defined for each security policy project | Unlimited for all paid tiers | See [Number of schedule rules defined for each security policy project](../../administration/instance_limits.md#limit-the-number-of-schedule-rules-defined-for-security-policy-project) |
-| Scheduled job archiving | 3 months (from June 22, 2020). Jobs created before that date were archived after September 22, 2020. | Never |
-| Maximum test cases per [unit test report](../../ci/testing/unit_test_reports.md) | `500000` | Unlimited |
-| Maximum registered runners | Free tier: `50` per-group / `50` per-project<br/>All paid tiers: `1000` per-group / `1000` per-project | See [Number of registered runners per scope](../../administration/instance_limits.md#number-of-registered-runners-per-scope) |
-| Limit of dotenv variables | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | See [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables) |
-| Authorization token duration (minutes) | `15` | To set a custom value, in the Rails console, run `ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)`, where `<integer>` is the desired number of minutes. |
+| Setting | GitLab.com | Default (self-managed) |
+|----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|------------------------|
+| Artifacts maximum size (compressed) | 1 GB | See [Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size). |
+| Artifacts [expiry time](../../ci/yaml/index.md#artifactsexpire_in) | From June 22, 2020, deleted after 30 days unless otherwise specified (artifacts created before that date have no expiry). | See [Default artifacts expiration](../admin_area/settings/continuous_integration.md#default-artifacts-expiration). |
+| Scheduled Pipeline Cron | `*/5 * * * *` | See [Pipeline schedules advanced configuration](../../administration/cicd.md#change-maximum-scheduled-pipeline-frequency). |
+| Maximum jobs in active pipelines | `500` for Free tier, `1000` for all trial tiers, and unlimited otherwise. | See [Number of jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines). |
+| Maximum CI/CD subscriptions to a project | `2` | See [Number of CI/CD subscriptions to a project](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project). |
+| Maximum number of pipeline triggers in a project | `25000` for Free tier, Unlimited for all paid tiers | See [Limit the number of pipeline triggers](../../administration/instance_limits.md#limit-the-number-of-pipeline-triggers). |
+| Maximum pipeline schedules in projects | `10` for Free tier, `50` for all paid tiers | See [Number of pipeline schedules](../../administration/instance_limits.md#number-of-pipeline-schedules). |
+| Maximum pipelines per schedule | `24` for Free tier, `288` for all paid tiers | See [Limit the number of pipelines created by a pipeline schedule per day](../../administration/instance_limits.md#limit-the-number-of-pipelines-created-by-a-pipeline-schedule-per-day). |
+| Maximum number of schedule rules defined for each security policy project | Unlimited for all paid tiers | See [Number of schedule rules defined for each security policy project](../../administration/instance_limits.md#limit-the-number-of-schedule-rules-defined-for-security-policy-project). |
+| Scheduled job archiving | 3 months (from June 22, 2020). Jobs created before that date were archived after September 22, 2020. | Never. |
+| Maximum test cases per [unit test report](../../ci/testing/unit_test_reports.md) | `500000` | Unlimited. |
+| Maximum registered runners | Free tier: `50` per-group / `50` per-project<br/>All paid tiers: `1000` per-group / `1000` per-project | See [Number of registered runners per scope](../../administration/instance_limits.md#number-of-registered-runners-per-scope). |
+| Limit of dotenv variables | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | See [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables). |
+| Authorization token duration (minutes) | `15` | To set a custom value, in the Rails console, run `ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)`, where `<integer>` is the desired number of minutes. |
## Package registry limits
@@ -249,10 +249,13 @@ The limit varies depending on your plan and the number of seats in your subscrip
|----------------------|-------------------------|
| Number of webhooks | `100` per project, `50` per group |
| Maximum payload size | 25 MB |
+| Timeout | 10 seconds |
-For self-managed instance limits, see
-[Webhook rate limit](../../administration/instance_limits.md#webhook-rate-limit)
-and [Number of webhooks](../../administration/instance_limits.md#number-of-webhooks).
+For self-managed instance limits, see:
+
+- [Webhook rate limit](../../administration/instance_limits.md#webhook-rate-limit).
+- [Number of webhooks](../../administration/instance_limits.md#number-of-webhooks).
+- [Webhook timeout](../../administration/instance_limits.md#webhook-timeout).
## Runner SaaS
diff --git a/doc/user/group/access_and_permissions.md b/doc/user/group/access_and_permissions.md
index bdef13af3f9..395ed3c91c7 100644
--- a/doc/user/group/access_and_permissions.md
+++ b/doc/user/group/access_and_permissions.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group access and permissions
@@ -19,14 +19,14 @@ Group push rules allow group maintainers to set
In GitLab 15.4 and later, to configure push rules for a group:
-1. On the left sidebar, select **Push rules**.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand the **Pre-defined push rules** section.
1. Select the settings you want.
1. Select **Save Push Rules**.
In GitLab 15.3 and earlier, to configure push rules for a group:
-1. On the left sidebar, select **Settings > Repository** page.
-1. Expand the **Pre-defined push rules** section.
+1. On the left sidebar, select **Push rules**.
1. Select the settings you want.
1. Select **Save Push Rules**.
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 17a5551adbf..c6cc828302f 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE)**
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index 7750782a623..280781a4cad 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -1,8 +1,8 @@
---
type: reference
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Contribution Analytics **(PREMIUM)**
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 43587dd54ef..7f77c2147e1 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Custom group-level project templates **(PREMIUM)**
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index bb18c69f7ae..67263f15f06 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -1,7 +1,7 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group DevOps Adoption **(ULTIMATE)**
diff --git a/doc/user/group/epics/epic_boards.md b/doc/user/group/epics/epic_boards.md
index a8bbb0575b3..78cc65f1923 100644
--- a/doc/user/group/epics/epic_boards.md
+++ b/doc/user/group/epics/epic_boards.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Epic boards **(PREMIUM)**
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index f2cb437ffda..da6e675f0eb 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -1,18 +1,16 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Epics **(PREMIUM)**
-> Single-level epics were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
+When [issues](../../project/issues/index.md) share a theme across projects and
+milestones, you can manage them by using epics.
-When [issues](../../project/issues/index.md) share a theme across projects and milestones,
-you can manage them by using epics.
-
-You can also create child epics, and assign start and end dates,
-which creates a visual roadmap for you to view progress.
+You can also create child epics and assign start and end dates, which creates
+a visual roadmap for you to view progress.
Use epics:
@@ -37,6 +35,22 @@ graph TD
Also, read more about possible [planning hierarchies](../planning_hierarchy/index.md).
+### Child issues from different group hierarchies
+
+<!-- When feature flag is removed, integrate this info as a sentence in
+https://docs.gitlab.com/ee/user/group/epics/manage_epics.html#add-an-existing-issue-to-an-epic -->
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371081) in GitLab 15.5 [with a flag](../../../administration/feature_flags.md) named `epic_issues_from_different_hierarchies`. Disabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/373304) in GitLab 15.5.
+
+FLAG:
+On self-managed GitLab, by default this feature is unavailable. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `epic_issues_from_different_hierarchies`.
+On GitLab.com, this feature is available.
+
+You can add issues from a different group hierarchy to an epic.
+To do it, paste the issue URL when
+[adding an existing issue](manage_epics.md#add-an-existing-issue-to-an-epic).
+
## Roadmap in epics **(ULTIMATE)**
If your epic contains one or more [child epics](manage_epics.md#multi-level-child-epics) that
diff --git a/doc/user/group/epics/linked_epics.md b/doc/user/group/epics/linked_epics.md
index 89699661efa..4049ac2e9a1 100644
--- a/doc/user/group/epics/linked_epics.md
+++ b/doc/user/group/epics/linked_epics.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Linked epics **(ULTIMATE)**
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 26826ec5832..0a12f551588 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -2,7 +2,7 @@
type: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Manage epics **(PREMIUM)**
@@ -213,6 +213,16 @@ To view epics in a group:
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Epics**.
+### Who can view an epic
+
+Whether you can view an epic depends on the [group visibility level](../../public_access.md) and
+the epic's [confidentiality status](#make-an-epic-confidential):
+
+- Public group and a non-confidential epic: You don't have to be a member of the group.
+- Private group and non-confidential epic: You must have at least the Guest role for the group.
+- Confidential epic (regardless of group visibility): You must have at least the Reporter
+ role for the group.
+
### Cached epic count
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299540) in GitLab 13.11 [with a flag](../../../administration/feature_flags.md) named `cached_sidebar_open_epics_count`. Enabled by default.
@@ -329,8 +339,8 @@ automatically added to the epic.
#### Add an existing issue to an epic
-Existing issues that belong to a project in an epic's group, or any of the epic's
-subgroups, are eligible to be added to the epic. Newly added issues appear at the top of the list of
+You can add existing issues to an epic, including issues in a project in an epic's group, or any of
+the epic's subgroups. Newly added issues appear at the top of the list of
issues in the **Epics and Issues** tab.
An epic contains a list of issues and an issue can be associated with at most one epic.
@@ -339,7 +349,7 @@ current parent.
Prerequisites:
-- You must have at least the Reporter role for the epic's group.
+- You must be able to [view the epic](#who-can-view-an-epic).
- You must be able to [edit the issue](../../project/issues/managing_issues.md#edit-an-issue).
To add an existing issue to an epic:
@@ -356,14 +366,13 @@ To add an existing issue to an epic:
#### Create an issue from an epic
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5419) in GitLab 12.7.
-
Creating an issue from an epic enables you to maintain focus on the broader context of the epic
while dividing work into smaller parts.
Prerequisites:
-- You must have at least the Reporter role for the epic's group.
+- You must be able to [view the epic](#who-can-view-an-epic).
+- You must have at least the Reporter role for the project.
To create an issue from an epic:
@@ -479,6 +488,8 @@ When you add an epic that's already linked to a parent epic, the link to its cur
Epics can contain multiple nested child epics, up to a total of seven levels deep.
+Maximum number of direct child epics is 100.
+
### Add a child epic to an epic
Prerequisites:
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 21b389581ae..ee50cfcf182 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -1,19 +1,19 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating groups **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7 for group resources [with a flag](../../feature_flags.md) named `bulk_import`. Disabled by default.
-> - Group resources [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338985) in GitLab 14.3.
+> - Group items [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338985) in GitLab 14.3.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267945) in GitLab 14.4 for project resources [with a flag](../../feature_flags.md) named `bulk_import_projects`. Disabled by default.
FLAG:
-On self-managed GitLab, by default [migrating group resources](#migrated-group-resources) is available. To hide the
+On self-managed GitLab, by default [migrating group items](#migrated-group-items) is available. To hide the
feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `bulk_import`.
-On self-managed GitLab, by default [migrating project resources](#migrated-project-resources) is not available. To show
+On self-managed GitLab, by default [migrating project items](#migrated-project-items) is not available. To show
this feature, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named
`bulk_import_projects`. On GitLab.com, migrating group resources is available but migrating project resources is not
available.
@@ -33,8 +33,8 @@ another GitLab instance. Migrating groups using the method documented here autom
When you migrate a group, you connect to your GitLab instance and then choose
groups to import. Not all the data is migrated. See:
-- [Migrated group resources](#migrated-group-resources).
-- [Migrated project resources](#migrated-project-resources).
+- [Migrated group items](#migrated-group-items).
+- [Migrated project items](#migrated-project-items).
Leave feedback about group migration in [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495).
@@ -79,10 +79,17 @@ Migration importer page. The remote groups you have the Owner role for are liste
For information on automating user, group, and project import API calls, see
[Automate group and project import](../../project/import/index.md#automate-group-and-project-import).
-## Migrated group resources
+## Migrated group items
-Only the following resources are migrated to the target instance. Any other items are **not**
-migrated:
+The [`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/group/import_export.yml)
+file for groups lists many of the items migrated when migrating groups using group migration. View this file in the branch
+for your version of GitLab to see the list of items relevant to you. For example,
+[`import_export.yml` on the `14-10-stable-ee` branch](https://gitlab.com/gitlab-org/gitlab/-/blob/14-10-stable-ee/lib/gitlab/import_export/group/import_export.yml).
+
+Migrating projects with file exports uses the same export and import mechanisms as creating projects from templates at the [group](../custom_project_templates.md) and
+[instance](../../admin_area/custom_project_templates.md) levels. Therefore, the list of exported items is the same.
+
+Items that are migrated to the target instance include:
- Badges ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292431) in 13.11)
- Board Lists
@@ -92,6 +99,7 @@ migrated:
- Finisher
- Group Labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) in 13.9)
- Iterations ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292428) in 13.10)
+- Iterations cadences ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96570) in 15.4)
- Members ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) in 13.9)
Group members are associated with the imported group if:
- The user already exists in the target GitLab instance and
@@ -101,24 +109,36 @@ migrated:
- Namespace Settings
- Releases
- Milestones ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339422) in GitLab 15.0).
-- Sub-Groups
+- Subgroups
- Uploads
-## Migrated project resources
+Any other items are **not** migrated.
+
+## Migrated project items
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267945) in GitLab 14.4 [with a flag](../../feature_flags.md) named `bulk_import_projects`. Disabled by default.
FLAG:
On self-managed GitLab, migrating project resources are not available by default. To make them available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `bulk_import_projects`. On GitLab.com, migrating project resources are not available.
+The [`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/project/import_export.yml)
+file for projects lists many of the items migrated when migrating projects using group migration. View this file in the branch
+for your version of GitLab to see the list of items relevant to you. For example,
+[`import_export.yml` on the `14-10-stable-ee` branch](https://gitlab.com/gitlab-org/gitlab/-/blob/14-10-stable-ee/lib/gitlab/import_export/project/import_export.yml).
+
+Migrating projects with file exports uses the same export and import mechanisms as creating projects from templates at the [group](../../group/custom_project_templates.md) and
+[instance](../../admin_area/custom_project_templates.md) levels. Therefore, the list of exported items is the same.
+
- Projects ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267945) in GitLab 14.4)
- Auto DevOps ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339410) in GitLab 14.6)
- Branches (including protected branches) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339414) in GitLab 14.7)
- CI Pipelines ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339407) in GitLab 14.6)
- Designs ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339421) in GitLab 15.1)
- Issues ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267946) in GitLab 14.4)
+ - Issue iteration ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96184) in 15.4)
- Issue resource state events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
- Issue resource milestone events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
+ - Issue resource iteration events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
- Labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339419) in GitLab 14.4)
- LFS Objects ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339405) in GitLab 14.8)
- Members ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341886) in GitLab 14.8)
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index c7d92af8ee8..62659938d91 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Groups **(FREE)**
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png
deleted file mode 100644
index ff18a3e86a5..00000000000
--- a/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart_v15_4.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart_v15_4.png
new file mode 100644
index 00000000000..f7963c170e1
--- /dev/null
+++ b/doc/user/group/insights/img/insights_example_stacked_bar_chart_v15_4.png
Binary files differ
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index 0cde0f1f133..b4bca919498 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -1,18 +1,19 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Insights for groups **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 12.0.
-Configure Insights to explore data about you group's activity, such as
+Configure insights to explore data about you group's activity, such as
triage hygiene, issues created or closed in a given period, and average time for merge
requests to be merged.
+You can also create custom insights reports that are relevant for your group.
-## View your group's Insights
+## View group insights
Prerequisites:
@@ -20,22 +21,49 @@ Prerequisites:
- You must have access to a project to view information about its merge requests and issues,
and permission to view them if they are confidential.
-To access your group's Insights:
+To access your group's insights:
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Insights**.
-![Insights example stacked bar chart](img/insights_example_stacked_bar_chart_v13_11.png)
+## Interact with insights charts
-## Configure your Insights
+You can interact with the insights charts to view details about your group's activity.
-GitLab reads Insights from the
+![Insights example stacked bar chart](img/insights_example_stacked_bar_chart_v15_4.png)
+
+### Display different reports
+
+To display one of the available reports on the insights page, from the **Select report** dropdown list,
+select the report you want to display.
+
+### View bar chart annotations
+
+To view annotations, hover over each bar in the chart.
+
+### Zoom in on chart
+
+Insights display data from the last 90 days. You can zoom in to display data only from a subset of the 90-day range.
+
+To do this, select the pause icons (**{status-paused}**) and slide them along the horizontal axis:
+
+- To select a later start date, slide the left pause icon to the right.
+- To select an earlier end date, slide the right pause icon to the left.
+
+### Exclude dimensions from charts
+
+By default, insights display all available dimensions on the chart.
+
+To exclude a dimension, from the legend below the chart, select the name of the dimension.
+
+## Configure group insights
+
+GitLab reads insights from the
[default configuration file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/fixtures/insights/default.yml).
-You can also create custom Insights charts that are more relevant for your group.
-To customize your Insights:
+To configure group insights:
-1. Create a new file [`.gitlab/insights.yml`](../../project/insights/index.md#writing-your-gitlabinsightsyml)
+1. Create a new file [`.gitlab/insights.yml`](../../project/insights/index.md#configure-project-insights)
in a project that belongs to your group.
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
index 26d77edd89b..4764625ff83 100644
--- a/doc/user/group/issues_analytics/index.md
+++ b/doc/user/group/issues_analytics/index.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue analytics for groups **(PREMIUM)**
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 4cc879ef32d..a6435ae2aa3 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Iterations **(PREMIUM)**
@@ -13,8 +13,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [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)
-for tracking over different time periods.
+to track velocity and volatility metrics. For tracking over different time periods, you can use iterations [milestones](../../project/milestones/index.md).
+You can create and manage various [iteration cadences](#iteration-cadences).
For example, you can use:
@@ -24,15 +24,51 @@ For example, you can use:
In GitLab, iterations are similar to milestones, with a few differences:
- Iterations are only available to groups.
-- A group can only have one active iteration at a time.
+- Iterations are grouped into iteration cadences.
- Iterations require both a start and an end date.
-- Iteration date ranges cannot overlap.
+- Iteration date ranges cannot overlap within an iteration cadence.
-## View the iterations list
+## Iteration cadences
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5077) in GitLab 14.1 [with a flag](../../../administration/feature_flags.md), named `iteration_cadences`. Disabled by default.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/354977) in GitLab 15.0: All scheduled iterations must start on the same day of the week as the cadence start day. Start date of cadence cannot be edited after the first iteration starts.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/354878) in GitLab 15.0.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/367493) in GitLab 15.4: A new automation start date can be selected for cadence. Upcoming iterations will be scheduled to start on the same day of the week as the changed start date. Iteration cadences can be manually managed by turning off the automatic scheduling feature.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/354878) in GitLab 15.5. Feature flag `iteration_cadences` removed.
+
+Iteration cadences are containers for iterations and can be used to automate iteration scheduling.
+You can use them to automate creating iterations every 1, 2, 3, or 4 weeks. You can also
+configure iteration cadences to automatically roll over incomplete issues to the next iteration.
+
+### Create an iteration cadence
+
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
+
+Prerequisites:
+
+- You must have at least the Reporter role for a group.
+
+To create an iteration cadence:
+
+1. On the top bar, select **Main menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Iterations**.
+1. Select **New iteration cadence**.
+1. Enter the title and description of the iteration cadence.
+1. To manually manage the iteration cadence, clear the **Enable automatic scheduling** checkbox and skip the next step.
+1. Complete the required fields to use automatic scheduling.
+ - Select the automation start date of the iteration cadence. Iterations will be scheduled to
+ begin on the same day of the week as the day of the week of the start date.
+ - From the **Duration** dropdown list, select how many weeks each iteration should last.
+ - From the **Upcoming iterations** dropdown list, select how many upcoming iterations should be
+ created and maintained by GitLab.
+ - Optional. To move incomplete issues to the next iteration, select **Roll over issues**.
+1. Select **Create cadence**. The cadence list page opens.
+
+If you want to manually manage the created cadence, read [Manual Iteration Management](#manual-iteration-management).
-To view the iterations list:
+### View the iterations list
-1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the top bar, select **Main menu > Groups** and find your group.
1. Select **Issues > Iterations**.
To view all the iterations in a cadence, ordered by descending date, select that iteration cadence.
@@ -46,61 +82,132 @@ by going to its URL. To do so, add: `/-/cadences` to your project or group URL.
For example `https://gitlab.com/gitlab-org/sample-data-templates/sample-gitlab-project/-/cadences`.
This is tracked in [issue 339009](https://gitlab.com/gitlab-org/gitlab/-/issues/339009).
-## Create an iteration
+### Edit an iteration cadence
-> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069) in GitLab 14.10.
-> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
+Prerequisites:
+
+- You must have at least the Developer role for a group.
+
+To edit an iteration cadence:
+
+1. On the top bar, select **Main menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Iterations**.
+1. Select **Edit iteration cadence**.
+
+When you use automatic scheduling and edit the **Automation start date** field,
+you must set a new start date that doesn't overlap with the existing
+current or past iterations.
+
+Editing **Upcoming iterations** is a non-destructive action.
+If ten upcoming iterations already exist, changing the number under **Upcoming iterations** to `2`
+doesn't delete the eight existing upcoming iterations.
-WARNING:
-Manual iteration management is in its end-of-life process. Creating an iteration is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069)
-in GitLab 14.10, and is planned for removal in GitLab 16.0.
+#### Turn on and off automatic scheduling for an iteration cadence
+
+1. On the top bar, select **Main menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Iterations**.
+1. Next to the cadence for which you want to turn on or off automatic scheduling, select the
+ three-dot menu (**{ellipsis_v}**) **> Edit cadence**.
+1. Select or clear the **Enable automatic scheduling** checkbox.
+1. If you're turning on automatic scheduling,
+ complete the required fields **Duration**, **Upcoming iterations**, and **Automation start date**.
+
+ For **Automation start date**, you can select any date that doesn't overlap with the existing open iterations.
+ If you have upcoming iterations, the automatic scheduling adjusts them appropriately to fit
+ your chosen duration.
+1. Select **Save changes**.
+
+#### Example of turning on automatic scheduling for a manual iteration cadence
+
+Suppose it's Friday, April 15, and you have three iteration in a manual iteration cadence:
+
+- Monday, April 4 - Friday, April 8 (closed)
+- Tuesday, April 12 - Friday, April 15 (ongoing)
+- Tuesday, May 3 - Friday, May 6 (upcoming)
+
+The earliest possible **Automation start date** you can choose
+is Saturday, April 16 in this scenario, because April 15 overlaps with
+the ongoing iteration.
+
+If you select Monday, April 18 as the automation start date to
+automate scheduling iterations every week up to two upcoming iterations,
+after the conversion you have the following iterations:
+
+- Monday, April 4 - Friday, April 8 (closed)
+- Tuesday, April 12 - Friday, April 15 (ongoing)
+- Monday, April 18 - Sunday, April 24 (upcoming)
+- Monday, April 25 - Sunday, May 1 (upcoming)
+
+Your existing upcoming iteration "Tuesday, April 12 - Friday, April 15"
+is changed to "April 18 - Sunday, April 24".
+
+An additional upcoming iteration "April 25 - Sunday, May 1" is scheduled
+to satisfy the requirement that there are at least two upcoming iterations scheduled.
+
+### Delete an iteration cadence
+
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
Prerequisites:
- You must have at least the Reporter role for a group.
-To create an iteration:
+Deleting an iteration cadence also deletes all iterations within that cadence.
+
+To delete an iteration cadence:
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Issues > Iterations**.
+1. Select the three-dot menu (**{ellipsis_v}**) > **Delete cadence** for the cadence you want to delete.
+1. Select **Delete cadence**.
+
+## Manual iteration management
+
+If you don't want your iterations to be scheduled by iteration cadences,
+you can also create and manage them manually.
+
+### Create an iteration
+
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
+
+Prerequisites:
+
+- You must have at least the Reporter role for a group.
+- [Automatic scheduling must be disabled](#turn-on-and-off-automatic-scheduling-for-an-iteration-cadence) for the iteration cadence.
+
+To create an iteration:
+
+1. On the top bar, select **Main menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Iterations** and select an iteration cadence.
1. Select **New iteration**.
1. Enter the title, a description (optional), a start date, and a due date.
1. Select **Create iteration**. The iteration details page opens.
-## Edit an iteration
+### Edit an iteration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) in GitLab 13.2.
-> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069) in GitLab 14.10.
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
-WARNING:
-Editing all attributes, with the exception of `description` is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069)
-in GitLab 14.10, and is planned for removal in GitLab 16.0.
-In the future only editing an iteration's `description` will be allowed.
-
Prerequisites:
- You must have at least the Reporter role for a group.
+- [Automatic scheduling must be disabled](#turn-on-and-off-automatic-scheduling-for-an-iteration-cadence) for the iteration cadence.
To edit an iteration, select the three-dot menu (**{ellipsis_v}**) > **Edit**.
-## Delete an iteration
+### Delete an iteration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292268) in GitLab 14.3.
-> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069) in GitLab 14.10.
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
-WARNING:
-Manual iteration management is in its end-of-life process. Deleting an iteration is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069)
-in GitLab 14.10, and is planned for removal in GitLab 16.0.
-
Prerequisites:
- You must have at least the Reporter role for a group.
+- [Automatic scheduling must be disabled](#turn-on-and-off-automatic-scheduling-for-an-iteration-cadence) for the iteration cadence.
To delete an iteration, select the three-dot menu (**{ellipsis_v}**) > **Delete**.
-## Add an issue to an iteration
+### Add an issue to an iteration
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in GitLab 13.2.
@@ -176,116 +283,3 @@ To group issues by label:
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 any area outside the label dropdown list. The page is now grouped by the selected labels.
-
-## Iteration cadences
-
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5077) in GitLab 14.1 [with a flag](../../../administration/feature_flags.md), named `iteration_cadences`. Disabled by default.
-> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/354977) in GitLab 15.0: All scheduled iterations must start on the same day of the week as the cadence start day. Start date of cadence cannot be edited after the first iteration starts.
-> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/354878) in GitLab 15.0.
-> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/367493) in GitLab 15.4: A new automation start date can be selected for cadence. Upcoming iterations will be scheduled to start on the same day of the week as the changed start date. Iteration cadences can be manually managed by turning off the automatic scheduling feature.
-
-Iteration cadences automate iteration scheduling. You can use them to
-automate creating iterations every 1, 2, 3, or 4 weeks. You can also
-configure iteration cadences to automatically roll over incomplete issues to the next iteration.
-
-### Create an iteration cadence
-
-> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
-
-Prerequisites:
-
-- You must have at least the Reporter role for a group.
-
-To create an iteration cadence:
-
-1. On the top bar, select **Main menu > Groups** and find your group.
-1. On the left sidebar, select **Issues > Iterations**.
-1. Select **New iteration cadence**.
-1. Enter the title and description of the iteration cadence.
-1. To manually manage the iteration cadence, clear the **Enable automatic scheduling** checkbox and skip the next step.
-1. Complete the required fields to use automatic scheduling.
- - Select the automation start date of the iteration cadence. Iterations will be scheduled to
- begin on the same day of the week as the day of the week of the start date.
- - From the **Duration** dropdown list, select how many weeks each iteration should last.
- - From the **Upcoming iterations** dropdown list, select how many upcoming iterations should be
- created and maintained by GitLab.
- - Optional. To move incomplete issues to the next iteration, select **Roll over issues**.
-1. Select **Create cadence**. The cadence list page opens.
-
-### Edit an iteration cadence
-
-Prerequisites:
-
-- You must have at least the Developer role for a group.
-
-To edit an iteration cadence:
-
-1. On the top bar, select **Main menu > Groups** and find your group.
-1. On the left sidebar, select **Issues > Iterations**.
-1. Select **Edit iteration cadence**.
-
-When you are using automatic scheduling and edit the **Automation start date** field,
-you must set a new start date that doesn't overlap with the existing
-current or past iterations.
-
-Editing **Upcoming iterations** is a non-destructive action.
-If ten upcoming iterations already exist, changing the number under **Upcoming iterations** to `2`
-doesn't delete the eight existing upcoming iterations.
-
-#### Turn on automatic scheduling for manual iterations cadence
-
-1. On the top bar, select **Main menu > Groups** and find your group.
-1. On the left sidebar, select **Issues > Iterations**.
-1. Select the three-dot menu (**{ellipsis_v}**) > **Edit cadence** for the cadence for which you want to enable automatic scheduling.
-1. Check the **Enable automatic scheduling** checkbox.
-1. Complete the required fields **Duration**, **Upcoming iterations**, and **Automation start date**.
-For **Automation start date**, you can select any date that doesn't overlap with the existing open iterations.
-If you have upcoming iterations, the automatic scheduling adjusts them appropriately to fit
-your chosen duration.
-1. Select **Save changes**.
-
-When you want to manage your iterations cadence manually again, edit your cadence and uncheck the **Enable automatic scheduling** checkbox.
-
-#### Example of turning on automatic scheduling for manual iterations cadence
-
-Suppose it's Friday, April 15, and you have three iteration in a manual iterations cadence:
-
-- Monday, April 4 - Friday, April 8 (closed)
-- Tuesday, April 12 - Friday, April 15 (ongoing)
-- Tuesday, May 3 - Friday, May 6 (upcoming)
-
-The earliest possible **Automation start date** you can choose
-is Saturday, April 16 in this scenario, because April 15 overlaps with
-the ongoing iteration.
-
-If you select Monday, April 18 as the automation start date to
-automate scheduling iterations every week up to two upcoming iterations,
-after the conversion you have the following iterations:
-
-- Monday, April 4 - Friday, April 8 (closed)
-- Tuesday, April 12 - Friday, April 15 (ongoing)
-- Monday, April 18 - Sunday, April 24 (upcoming)
-- Monday, April 25 - Sunday, May 1 (upcoming)
-
-Your existing upcoming iteration "Tuesday, April 12 - Friday, April 15"
-is changed to "April 18 - Sunday, April 24".
-
-An additional upcoming iteration "April 25 - Sunday, May 1" is scheduled
-to satisfy the requirement that there are at least two upcoming iterations scheduled.
-
-### Delete an iteration cadence
-
-> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
-
-Prerequisites:
-
-- You must have at least the Reporter role for a group.
-
-Deleting an iteration cadence also deletes all iterations within that cadence.
-
-To delete an iteration cadence:
-
-1. On the top bar, select **Main menu > Groups** and find your group.
-1. On the left sidebar, select **Issues > Iterations**.
-1. Select the three-dot menu (**{ellipsis_v}**) > **Delete cadence** for the cadence you want to delete.
-1. Select **Delete cadence**.
diff --git a/doc/user/group/manage.md b/doc/user/group/manage.md
index ca9ff0d7b3e..f11d9035a52 100644
--- a/doc/user/group/manage.md
+++ b/doc/user/group/manage.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Manage groups
@@ -127,6 +127,11 @@ To find members in a group, you can sort, filter, or search.
Filter a group to find members. By default, all members in the group and subgroups are displayed.
+In lists of group members, entries can display the following badges:
+
+- **SAML**, to indicate the member has a [SAML account](saml_sso/index.md) connected to them.
+- **Enterprise**, to indicate that [SCIM created the account](saml_sso/scim_setup.md).
+
1. On the top bar, select **Main menu > Groups** and find your group.
1. Above the list of members, in the **Filter members** box, enter filter criteria.
- To view members in the group only, select **Membership = Direct**.
@@ -158,6 +163,10 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
You can give a user access to all projects in a group.
+Prerequisite:
+
+- You must have the Owner role.
+
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Group information > Members**.
1. Select **Invite members**.
@@ -376,6 +385,214 @@ To enable delayed deletion of projects in a group:
NOTE:
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.
+## Compliance frameworks **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/287779) in GitLab 13.12.
+
+You can create a compliance framework that is a label to identify that your project has certain compliance
+requirements or needs additional oversight. The label can optionally enforce
+[compliance pipeline configuration](#configure-a-compliance-pipeline) to the projects on which it is
+[applied](../project/settings/index.md#add-a-compliance-framework-to-a-project).
+
+Group owners can create, edit, and delete compliance frameworks:
+
+1. On the top bar, select **Main menu > Groups > View all groups** and find your group.
+1. On the left sidebar, select **Settings** > **General**.
+1. Expand the **Compliance frameworks** section.
+1. Create, edit, or delete compliance frameworks.
+
+### Configure a compliance pipeline **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3156) in GitLab 13.9, disabled behind `ff_evaluate_group_level_compliance_pipeline` [feature flag](../../administration/feature_flags.md).
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/300324) in GitLab 13.11.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/331231) in GitLab 14.2.
+
+Group owners can configure a compliance pipeline in a project separate to other projects. By default, the compliance
+pipeline configuration (`.gitlab-ci.yml` file) is run instead of the pipeline configuration of labeled projects.
+
+However, the compliance pipeline configuration can reference the `.gitlab-ci.yml` file of the labeled projects so that:
+
+- The compliance pipeline can also run jobs of labeled project pipelines. This allows for centralized control of
+ pipeline configuration.
+- Jobs and variables defined in the compliance pipeline can't be changed by variables in the labeled project's
+ `.gitlab-ci.yml` file.
+
+See [example configuration](#example-configuration) for help configuring a compliance pipeline that runs jobs from
+labeled project pipeline configuration.
+
+To configure a compliance pipeline:
+
+1. On the top bar, select **Main menu > Groups > View all groups** and find your group.
+1. On the left sidebar, select **Settings** > **General**.
+1. Expand the **Compliance frameworks** section.
+1. In **Compliance pipeline configuration (optional)**, add the path to the compliance framework configuration. Use the
+ `path/file.y[a]ml@group-name/project-name` format. For example:
+
+ - `.compliance-ci.yml@gitlab-org/gitlab`.
+ - `.compliance-ci.yaml@gitlab-org/gitlab`.
+
+This configuration is inherited by projects where the compliance framework label is
+[applied](../project/settings/index.md#add-a-compliance-framework-to-a-project). In projects with the applied compliance
+framework label, the compliance pipeline configuration is run instead of the labeled project's own pipeline configuration.
+
+The user running the pipeline in the labeled project must at least have the Reporter role on the compliance project.
+
+When used to enforce scan execution, this feature has some overlap with
+[scan execution policies](../application_security/policies/scan-execution-policies.md). We have not
+[unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312). For details on
+the similarities and differences between these features, see [Enforce scan execution](../application_security/index.md#enforce-scan-execution).
+
+#### Example configuration
+
+The following example `.compliance-gitlab-ci.yml` includes the `include` keyword to ensure labeled project pipeline
+configuration is also executed.
+
+```yaml
+# Allows compliance team to control the ordering and interweaving of stages/jobs.
+# Stages without jobs defined will remain hidden.
+stages:
+ - pre-compliance
+ - build
+ - test
+ - pre-deploy-compliance
+ - deploy
+ - post-compliance
+
+variables: # Can be overridden by setting a job-specific variable in project's local .gitlab-ci.yml
+ FOO: sast
+
+sast: # None of these attributes can be overridden by a project's local .gitlab-ci.yml
+ variables:
+ FOO: sast
+ image: ruby:2.6
+ stage: pre-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+
+sanity check:
+ image: ruby:2.6
+ stage: pre-deploy-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+
+audit trail:
+ image: ruby:2.7
+ stage: post-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+
+include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
+ project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_REF_NAME' # Must be defined or MR pipelines always use the use default branch
+```
+
+##### CF pipelines in Merge Requests originating in project forks
+
+When an MR originates in a fork, the branch to be merged usually only exists in the fork.
+When creating such an MR against a project with CF pipelines, the above snippet will fail with a
+`Project <project-name> reference <branch-name> does not exist!` error message.
+This is because in the context of the target project, `$CI_COMMIT_REF_NAME` evaluates to a non-existing branch name.
+
+To get the correct context, use `$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` instead of `$CI_PROJECT_PATH`.
+This variable is only availabe in
+[merge request pipelines](../../ci/pipelines/merge_request_pipelines.md).
+
+For example, for a configuration that supports both branch pipelines, as well as merge request pipelines originating in project forks,
+you need to [combine both `include` directives with `rules:if`](../../ci/yaml/includes.md#use-rules-with-include):
+
+```yaml
+include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
+ - project: '$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_REF_NAME'
+ rules:
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_REF_NAME'
+ rules:
+ - if: $CI_PIPELINE_SOURCE != 'merge_request_event'
+```
+
+### Ensure compliance jobs are always run
+
+Compliance pipelines [use GitLab CI/CD](../../ci/index.md) to give you an incredible amount of flexibility
+for defining any sort of compliance jobs you like. Depending on your goals, these jobs
+can be configured to be:
+
+- Modified by users.
+- Non-modifiable.
+
+Generally, if a value in a compliance job:
+
+- Is set, it cannot be changed or overridden by project-level configurations.
+- Is not set, a project-level configuration may set.
+
+Either might be wanted or not depending on your use case.
+
+There are a few best practices for ensuring that these jobs are always run exactly
+as you define them and that downstream, project-level pipeline configurations
+cannot change them:
+
+- Add [a `rules:when:always` block](../../ci/yaml/index.md#when) to each of your compliance jobs. This ensures they are
+ non-modifiable and are always run.
+- Explicitly set any [variables](../../ci/yaml/index.md#variables) the job references. This:
+ - Ensures that project-level pipeline configurations do not set them and alter their
+ behavior.
+ - Includes any jobs that drive the logic of your job.
+- Explicitly set the [container image](../../ci/yaml/index.md#image) to run the job in. This ensures that your script
+ steps execute in the correct environment.
+- Explicitly set any relevant GitLab pre-defined [job keywords](../../ci/yaml/index.md#job-keywords).
+ This ensures that your job uses the settings you intend and that they are not overridden by
+ project-level pipelines.
+
+### Avoid parent and child pipelines in GitLab 14.7 and earlier
+
+NOTE:
+This advice does not apply to GitLab 14.8 and later because [a fix](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78878) added
+compatibility for combining compliance pipelines, and parent and child pipelines.
+
+Compliance pipelines start on the run of _every_ pipeline in a labeled project. This means that if a pipeline in the labeled project
+triggers a child pipeline, the compliance pipeline runs first. This can trigger the parent pipeline, instead of the child pipeline.
+
+Therefore, in projects with compliance frameworks, we recommend replacing
+[parent-child pipelines](../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines) with the following:
+
+- Direct [`include`](../../ci/yaml/index.md#include) statements that provide the parent pipeline with child pipeline configuration.
+- Child pipelines placed in another project that are run using the [trigger API](../../ci/triggers/index.md) rather than the parent-child
+ pipeline feature.
+
+This alternative ensures the compliance pipeline does not re-start the parent pipeline.
+
## Disable email notifications
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23585) in GitLab 12.2.
@@ -560,9 +777,7 @@ Changes to [group wikis](../project/wiki/group.md) do not appear in group activi
You can view the most recent actions taken in a group, either in your browser or in an RSS feed:
-1. On the top bar, select **Main menu > Groups > View all groups**.
-1. Select **Your Groups**.
-1. Find the group and select it.
+1. On the top bar, select **Main menu > Groups > View all groups** and find your group.
1. On the left sidebar, select **Group information > Activity**.
To view the activity feed in Atom format, select the
@@ -590,3 +805,45 @@ To find and store an array of groups based on an SQL query in the [rails console
Group.find_by_sql("SELECT * FROM namespaces WHERE name LIKE '%oup'")
=> [#<Group id:3 @test-group>, #<Group id:4 @template-group/template-subgroup>]
```
+
+### Transfer subgroup to another location using Rails console
+
+If transferring a group doesn't work through the UI or API, you may want to attempt the transfer in a [Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+user = User.find_by_username('<username>')
+group = Group.find_by_name("<group_name>")
+## Set parent_group = nil to make the subgroup a top-level group
+parent_group = Group.find_by(id: "<group_id>")
+service = ::Groups::TransferService.new(group, user)
+service.execute(parent_group)
+```
+
+### Find groups pending deletion using Rails console
+
+If you need to find all the groups that are pending deletion, you can use the following command in a [Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+Group.all.each do |g|
+ if g.marked_for_deletion?
+ puts "Group ID: #{g.id}"
+ puts "Group name: #{g.name}"
+ puts "Group path: #{g.full_path}"
+ end
+end
+```
+
+### Delete a group using Rails console
+
+At times, a group deletion may get stuck. If needed, in a [Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session),
+you can attempt to delete a group using the following command:
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+GroupDestroyWorker.new.perform(group_id, user_id)
+```
diff --git a/doc/user/group/planning_hierarchy/index.md b/doc/user/group/planning_hierarchy/index.md
index 6ffc47923f2..baa2a4d6046 100644
--- a/doc/user/group/planning_hierarchy/index.md
+++ b/doc/user/group/planning_hierarchy/index.md
@@ -2,7 +2,7 @@
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Planning hierarchies **(PREMIUM)**
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index f130ecb61dc..0a4d7f5eae4 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -1,7 +1,7 @@
---
stage: Verify
group: Pipeline Insights
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repositories analytics for groups **(PREMIUM)**
diff --git a/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png b/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png
new file mode 100644
index 00000000000..52130672e5a
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png
Binary files differ
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 10ca6d139ad..28431cb6b9a 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Roadmap **(PREMIUM)**
@@ -146,6 +146,16 @@ the timeline header represent the days of the week.
The timeline bar indicates the approximate position of an epic or milestone based on its start and
due dates.
+## Blocked epics **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33587) in GitLab 15.5: View blocking epics when hovering over the “blocked†icon.
+
+If an epic is [blocked by another epic](../epics/linked_epics.md#blocking-epics), an icon appears next to its title to indicate its blocked status.
+
+When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
+
+![Blocked epics](img/roadmap_blocked_icon_v15_5.png)
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/group/saml_sso/example_saml_config.md b/doc/user/group/saml_sso/example_saml_config.md
index d09a8524247..aef39f587ef 100644
--- a/doc/user/group/saml_sso/example_saml_config.md
+++ b/doc/user/group/saml_sso/example_saml_config.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
@@ -9,7 +9,7 @@ type: reference
These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team's collected knowledge.
-Please refer to the GitLab [Group SAML](index.md) docs for information on the feature and how to set it up.
+Refer to the GitLab [Group SAML](index.md) documentation for information on the feature and how to set it up.
When troubleshooting a SAML configuration, GitLab team members will frequently start with the [SAML troubleshooting section](index.md#troubleshooting).
diff --git a/doc/user/group/saml_sso/group_sync.md b/doc/user/group/saml_sso/group_sync.md
index 322b417d466..3a50470ce50 100644
--- a/doc/user/group/saml_sso/group_sync.md
+++ b/doc/user/group/saml_sso/group_sync.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SAML Group Sync **(PREMIUM)**
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index d33cde0a6b1..fa6f378e811 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -1,8 +1,7 @@
---
-type: reference, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SAML SSO for GitLab.com groups **(PREMIUM SAAS)**
@@ -32,8 +31,8 @@ If required, you can find [a glossary of common terms](../../../integration/saml
See [specific identity provider documentation](#providers) for more details.
1. Configure the SAML response to include a [NameID](#nameid) that uniquely identifies each user.
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. While the default is enabled for most SAML providers, ensure the app is set to have service provider
+ initiated calls to link existing GitLab accounts.
1. Once the identity provider is set up, move on to [configuring GitLab](#configure-gitlab).
![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png)
@@ -122,12 +121,22 @@ It can also help to compare the XML response from your provider with our [exampl
> - [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.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/339888) in GitLab 14.7 to not enforce SSO checks for Git activity originating from CI/CD jobs.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/215155) in GitLab 15.5 [with a flag](../../../administration/feature_flags.md) named `transparent_sso_enforcement` to include transparent enforcement even when SSO enforcement is not enabled. Enabled on GitLab.com.
-With this option enabled, users must access GitLab using your group GitLab single sign-on URL to access group resources.
-Users can't be added as new members manually.
-Users with the Owner role can use the standard sign in process to make necessary changes to top-level group settings.
+SSO is enforced when users access groups and projects in the organization's group hierarchy. Users can view other groups and projects without SSO sign in.
+
+When SAML SSO is enabled, SSO is enforced for each user with an existing SAML identity.
+A user has a SAML identity if one or both of the following are true:
+
+- They have signed in to GitLab by using their GitLab group's single sign-on URL.
+- They were provisioned by SCIM.
-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.
+Users without SAML identities are not required to use SSO unless explicit enforcement is enabled.
+
+When the **Enforce SSO-only authentication for web activity for this group** option is enabled, all users must access GitLab by using their GitLab group's single sign-on URL to access group resources,
+regardless of whether they have an existing SAML identity.
+Users also cannot be added as new members manually.
+Users with the Owner role can use the standard sign in process to make necessary changes to top-level group settings.
However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user
has authenticated through SSO. If it's been more than 1 day since the last sign-in, GitLab
@@ -157,17 +166,17 @@ When SSO is enforced, users are not immediately revoked. If the user:
The SAML standard means that you can use a wide range of identity providers with GitLab. Your identity provider might have relevant documentation. It can be generic SAML documentation or specifically targeted for GitLab.
-When [configuring your identity provider](#configure-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
+When [configuring your identity provider](#configure-your-identity-provider), consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#notes-on-configuring-your-identity-provider)
for additional guidance on information your identity provider may require.
GitLab provides the following information for guidance only.
-If you have any questions on configuring the SAML app, please contact your provider's support.
+If you have any questions on configuring the SAML app, contact your provider's support.
### Azure setup notes
-Follow the Azure documentation on [configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) with the notes below for consideration.
+Follow the Azure documentation on [configuring single sign-on to applications](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) with the notes below for consideration.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU).
@@ -225,7 +234,7 @@ See our [example configuration page](example_saml_config.md#google-workspace).
### Okta setup notes
-Please follow the Okta documentation on [setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/main/) with the notes below for consideration.
+Follow the Okta documentation on [setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/main/) with the notes below for consideration.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of the Okta SAML setup including SCIM, see [Demo: Okta Group SAML & SCIM setup](https://youtu.be/0ES9HsZq0AQ).
@@ -237,13 +246,16 @@ For a demo of the Okta SAML setup including SCIM, see [Demo: Okta Group SAML & S
| GitLab single sign-on URL | Login page URL (under **Application Login Page** settings) |
| Identity provider single sign-on URL | Identity Provider Single Sign-On URL |
-Under Okta's **Single sign-on URL** field, check the option **Use this for Recipient URL and Destination URL**.
+Under the Okta **Single sign-on URL** field, check the option **Use this for Recipient URL and Destination URL**.
For NameID, the following settings are recommended; for SCIM, the following settings are required:
- **Application username** (NameID) set to **Custom** `user.getInternalProperty("id")`.
- **Name ID Format** set to **Persistent**.
+The Okta GitLab application available in the App Catalog only supports [SCIM](scim_setup.md). Support
+for SAML is proposed in issue [216173](https://gitlab.com/gitlab-org/gitlab/-/issues/216173).
+
### OneLogin setup notes
OneLogin supports their own [GitLab (SaaS)](https://onelogin.service-now.com/support?id=kb_article&sys_id=92e4160adbf16cd0ca1c400e0b961923&kb_category=50984e84db738300d5505eea4b961913)
@@ -296,7 +308,7 @@ To migrate users to a new email domain, users must:
> SAML user provisioning [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268142) in GitLab 13.7.
-Once Group SSO is configured and enabled, users can access the GitLab.com group through the identity provider's dashboard. If [SCIM](scim_setup.md) is configured, please see the [user access and linking setup section on the SCIM page](scim_setup.md#user-access-and-linking-setup).
+Once Group SSO is configured and enabled, users can access the GitLab.com group through the identity provider's dashboard. If [SCIM](scim_setup.md) is configured, see the [user access and linking setup section on the SCIM page](scim_setup.md#user-access-and-linking-setup).
When a user tries to sign in with Group SSO, GitLab attempts to find or create a user based on the following:
@@ -383,8 +395,8 @@ convert the information to XML. An example SAML response is shown here.
By default, users provisioned with SAML or SCIM are sent a verification email to verify their identity. Instead, you can
[configure GitLab with a custom domain](../../project/pages/custom_domains_ssl_tls_certification/index.md) and GitLab
-will automatically confirm user accounts. Users will still receive an enterprise user welcome email.
-Confirmation is bypassed for users:
+automatically confirms user accounts. Users still receive an enterprise user welcome email. Confirmation is bypassed for
+users:
- That are provisioned with SAML or SCIM.
- That have an email address that belongs to the verified domain.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index a67b2fbe02e..55990336a50 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -1,14 +1,11 @@
---
-type: howto, reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure SCIM for GitLab.com groups **(PREMIUM SAAS)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10.
-
You can use the open standard System for Cross-domain Identity Management (SCIM) to automatically:
- Create users.
@@ -18,7 +15,7 @@ GitLab SAML SSO SCIM doesn't support updating users.
When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider.
-The GitLab [SCIM API](../../../api/scim.md) implements part of [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644).
+The [internal GitLab SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644).
## Configure GitLab
@@ -48,8 +45,12 @@ Other providers can work with GitLab but they have not been tested and are not s
### Configure Azure Active Directory
+Prerequisites:
+
+- [GitLab is configured](#configure-gitlab).
+
The SAML application created during [single sign-on](index.md) set up for
-[Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal)
+[Azure Active Directory](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal)
must be set up for SCIM. For an example, see [example configuration](example_saml_config.md#scim-mapping).
To configure Azure Active Directory for SCIM:
@@ -60,7 +61,7 @@ To configure Azure Active Directory for SCIM:
- **SCIM API endpoint URL** in GitLab for the **Tenant URL** field.
- **Your SCIM token** in GitLab for the **Secret Token** field.
1. Select **Test Connection**. If the test is successful, save your configuration before continuing, or see the
- [troubleshooting](#troubleshooting) information.
+ [troubleshooting](troubleshooting.md) information.
1. Select **Save**.
After saving, **Settings** and **Mappings** sections appear.
@@ -120,49 +121,52 @@ attributes and modify them accordingly. In particular, the `objectId` source att
target attribute.
If a mapping is not listed in the table, use the Azure Active Directory defaults. For a list of required attributes,
-refer to the [SCIM API documentation](../../../api/scim.md).
+refer to the [internal SCIM API](../../../development/internal_api/index.md#scim-api) documentation.
### Configure Okta
-Before you start this section:
+The SAML application created during [single sign-on](index.md) set up for Okta must be set up for SCIM.
-- Check that you are using Okta [Lifecycle Management](https://www.okta.com/products/lifecycle-management/) product. This product tier is required to use SCIM on Okta. To check which Okta product you are using, check your signed Okta contract, contact your Okta AE, CSM, or Okta support.
-- Complete the [GitLab configuration](#configure-gitlab) process.
-- Complete the setup for SAML application for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/main/), as described in the [Okta setup notes](index.md#okta-setup-notes).
-- Check that your Okta SAML setup matches our documentation exactly, especially the NameID configuration. Otherwise, the Okta SCIM app may not work properly.
+Prerequisites:
+
+- You must use the Okta [Lifecycle Management](https://www.okta.com/products/lifecycle-management/) product. This
+ product tier is required to use SCIM on Okta.
+- [GitLab is configured](#configure-gitlab).
+- SAML application for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/main/) set up as
+ described in the [Okta setup notes](index.md#okta-setup-notes).
+- Your Okta SAML setup matches the [configuration steps exactly](index.md), especially the NameID configuration.
-After the above steps are complete:
+To configure Okta for SCIM:
1. Sign in to Okta.
1. Ensure you are in the Admin Area by selecting the **Admin** button located in the top right. The button is not visible from the Admin Area.
1. In the **Application** tab, select **Browse App Catalog**.
-1. Search for **GitLab**, find and select the 'GitLab' application.
+1. Search for **GitLab**, find and select 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.
+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.
1. Select **Done** to finish adding the application.
1. In the **Provisioning** tab, select **Configure API integration**.
1. Select **Enable API integration**.
- - For **Base URL** enter the URL obtained from the GitLab SCIM configuration page
- - For **API Token** enter the SCIM token obtained from the GitLab SCIM configuration page
-1. Select 'Test API Credentials' to verify configuration.
-1. Select **Save** to apply the settings.
+ - For **Base URL**, paste the URL you copied from **SCIM API endpoint URL** on the GitLab SCIM configuration page.
+ - For **API Token**, paste the SCIM token you copied from **Your SCIM token** on the GitLab SCIM
+ configuration page.
+1. To verify the configuration, select **Test API Credentials**.
+1. Select **Save**.
1. After saving the API integration details, new settings tabs appear on the left. Select **To App**.
1. Select **Edit**.
1. Select the **Enable** checkbox for both **Create Users** and **Deactivate Users**.
1. Select **Save**.
-1. Assign users in the **Assignments** tab. Assigned users are created and
- managed in your GitLab group.
+1. Assign users in the **Assignments** tab. Assigned users are created and managed in your GitLab group.
-#### Okta Known Issues
+### Configure OneLogin
-The Okta GitLab application currently only supports SCIM. Continue
-using the separate Okta [SAML SSO](index.md) configuration along with the new SCIM
-application described above. An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/216173) to add SAML support to the Okta GitLab application.
+Prerequisites:
-### Configure OneLogin
+- [GitLab is configured](#configure-gitlab).
-As the developers of this app, OneLogin provides a "GitLab (SaaS)" app in their catalog, which includes a SCIM integration.
-Please reach out to OneLogin if you encounter issues.
+OneLogin provides a **GitLab (SaaS)** app in their catalog, which includes a SCIM integration. Contact OneLogin if you
+encounter issues.
## User access and linking setup
@@ -199,11 +203,11 @@ New users and existing users on subsequent visits can access the group through t
![Enterprise badge for users created with a SCIM identity](img/member_enterprise_badge_v14_0.png)
-For role information, please see the [Group SAML page](index.md#user-access-and-management)
+For role information, see the [Group SAML page](index.md#user-access-and-management)
### Blocking access
-To rescind access to the top-level group, all sub-groups, and projects, remove or deactivate the user
+To rescind access to the top-level group, all subgroups, and projects, remove or deactivate the user
on the identity provider. After the identity provider performs a sync, based on its configured schedule, the user's membership is revoked and they lose access.
NOTE:
@@ -215,125 +219,3 @@ graph TD
B -->|No| C[Nothing to do]
B -->|Yes| D[GitLab removes user from GitLab group]
```
-
-## Troubleshooting
-
-This section contains possible solutions for problems you might encounter.
-
-### How come I can't add a user after I removed them?
-
-As outlined in the [Blocking access section](#blocking-access), when you remove a user, they are removed from the group. However, their account is not deleted.
-
-When the user is added back to the SCIM app, GitLab cannot create a new user because the user already exists.
-
-Solution: Have a user sign in directly to GitLab, then [manually link](#user-access-and-linking-setup) their account.
-
-### How do I diagnose why a user is unable to sign in
-
-Ensure that the user has been added to the SCIM app.
-
-If you receive "User is not linked to a SAML account", then most likely the user already exists in GitLab. Have the user follow the [User access and linking setup](#user-access-and-linking-setup) instructions.
-
-The **Identity** (`extern_uid`) value stored by GitLab is updated by SCIM whenever `id` or `externalId` changes. Users cannot sign in unless the GitLab Identity (`extern_uid`) value matches the `NameId` sent by SAML.
-
-This value is also used by SCIM to match users on the `id`, and is updated by SCIM whenever the `id` or `externalId` values change.
-
-It is important that this SCIM `id` and SCIM `externalId` are configured to the same value as the SAML `NameId`. SAML responses can be traced using [debugging tools](troubleshooting.md#saml-debugging-tools), and any errors can be checked against our [SAML troubleshooting docs](troubleshooting.md).
-
-### How do I verify user's SAML NameId matches the SCIM externalId
-
-Admins can use the Admin Area to [list SCIM identities for a user](../../admin_area/index.md#user-identities).
-
-Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page.
-
-A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`.
-
-To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](troubleshooting.md#saml-debugging-tools).
-
-### Update or fix mismatched SCIM externalId and SAML NameId
-
-Whether the value was changed or you need to map to a different field, ensure `id`, `externalId`, and `NameId` all map to the same field.
-
-If the GitLab `externalId` doesn't match the SAML NameId, it needs to be updated in order for the user to sign in. Ideally your identity provider is configured to do such an update, but in some cases it may be unable to do so, such as when looking up a user fails due to an ID change.
-
-Be cautious if you revise the fields used by your SCIM identity provider, typically `id` and `externalId`.
-We use these IDs to look up users. If the identity provider does not know the current values for these fields,
-that provider may create duplicate users.
-
-If the `externalId` for a user is not correct, and also doesn't match the SAML NameID,
-you can address the problem in the following ways:
-
-- You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken) section.
-- You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on.
-- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`.
- To look up a user, you need to know the desired value that matches the `NameId` as well as the current `externalId`.
-
-It is important not to update these to incorrect values, since this causes users to be unable to sign in. It is also important not to assign a value to the wrong user, as this causes users to get signed into the wrong account.
-
-### I need to change my SCIM app
-
-Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#change-the-saml-app) section.
-
-Alternatively, users can be removed from the SCIM app which de-links all removed users. Sync can then be turned on for the new SCIM app to [link existing users](#user-access-and-linking-setup).
-
-### The SCIM app is throwing `"User has already been taken","status":409` error message
-
-Changing the SAML or SCIM configuration or provider can cause the following problems:
-
-| Problem | Solution |
-| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). |
-| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. |
-
-### Search Rails logs for SCIM requests
-
-GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the [SCIM API](../../../api/scim.md):
-
-- `json.path`: `/scim/v2/groups/<group-path>`
-- `json.params.value`: `<externalId>`
-
-In a relevant log entry, the `json.params.value` shows the values of SCIM parameters GitLab receives. These values can be used to verify if SCIM parameters configured in an
-identity provider's SCIM app are communicated to GitLab as intended. For example, we can use these values as a definitive source on why an account was provisioned with a certain
-set of details. This information can help where an account was SCIM provisioned with details that appear to be incongruent with what might have been configured within an identity
-provider's SCIM app.
-
-### Azure
-
-#### How do I verify my SCIM configuration is correct?
-
-Review the following:
-
-- Ensure that the SCIM value for `id` matches the SAML value for `NameId`.
-- Ensure that the SCIM value for `externalId` matches the SAML value for `NameId`.
-
-Review the following SCIM parameters for sensible values:
-
-- `userName`
-- `displayName`
-- `emails[type eq "work"].value`
-
-#### Testing Azure connection: invalid credentials
-
-When testing the connection, you may encounter an error: **You appear to have entered invalid credentials. Please confirm you are using the correct information for an administrative account**. If `Tenant URL` and `secret token` are correct, check whether your group path contains characters that may be considered invalid JSON primitives (such as `.`). Removing such characters from the group path typically resolves the error.
-
-#### (Field) can't be blank sync error
-
-When checking the Audit Events for the Provisioning, you can sometimes see the
-error `Namespace can't be blank, Name can't be blank, and User can't be blank.`
-
-This is likely caused because not all required fields (such as first name and last name) are present for all users being mapped.
-
-As a workaround, try an alternate mapping:
-
-1. Follow the Azure mapping instructions from above.
-1. Delete the `name.formatted` target attribute entry.
-1. Change the `displayName` source attribute to have `name.formatted` target attribute.
-
-#### 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`](#configure-azure-active-directory).
diff --git a/doc/user/group/saml_sso/troubleshooting.md b/doc/user/group/saml_sso/troubleshooting.md
index 177f33228c0..bde5ed1762a 100644
--- a/doc/user/group/saml_sso/troubleshooting.md
+++ b/doc/user/group/saml_sso/troubleshooting.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting SAML **(FREE)**
@@ -39,7 +39,7 @@ To generate a SAML Response:
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
+1. Select **Authorize** or attempt to sign in. A SAML response is displayed in the tracer console that resembles this
[example SAML response](index.md#example-saml-response).
1. Within the SAML tracer, select the **Export** icon to save the response in JSON format.
@@ -76,6 +76,19 @@ In a relevant log entry, the `json.params` should provide a valid response with:
- `"key": "RelayState"` with `"value": "/group-path"`, and
- `"key": "group_id"` with `"value": "group-path"`.
+You should also check the decoded SAML response with the following filters
+in case the customer has [configured SAML Group Sync](group_sync.md):
+
+- `json.class`: `GroupSamlGroupSyncWorker`
+- `json.args`: `<user ID> or <group ID>`
+
+In the relevant log entry, the:
+
+- `json.args` are in the form `<userID>, <group ID>,
+ [group link ID 1, group link ID 2, ..., group link ID N]`.
+- `json.extra.group_saml_group_sync_worker.stats.*` fields show how many times
+ this run of group sync `added`, `removed` or `changed` the user's membership.
+
In some cases, if the SAML response is lengthy, you may receive a `"key": "truncated"` with `"value":"..."`.
In these cases, use one of the [SAML debugging tools](#saml-debugging-tools), or for SAML SSO for groups,
a group owner can get a copy of the SAML response from when they select
@@ -175,7 +188,7 @@ initiated by the service provider and not only the identity provider.
A user can see this message when they are trying to [manually link SAML to their existing GitLab.com account](index.md#linking-saml-to-your-existing-gitlabcom-account).
-To resolve this problem, the user should check they are using the correct GitLab password to log in. The user first needs
+To resolve this problem, the user should check they are using the correct GitLab password to sign in. The user first needs
to [reset their password](https://gitlab.com/users/password/new) if both:
- The account was provisioned by SCIM.
@@ -191,7 +204,7 @@ For self-managed, administrators can use the [users API](../../../api/users.md)
When using SAML for groups, group members of a role with the appropriate permissions can make use of the [members API](../../../api/members.md) to view group SAML identity information for members of the group.
-This can then be compared to the NameID being sent by the identity provider by decoding the message with a [SAML debugging tool](#saml-debugging-tools). We require that these match in order to identify users.
+This can then be compared to the NameID being sent by the identity provider by decoding the message with a [SAML debugging tool](#saml-debugging-tools). We require that these match to identify users.
### Stuck in a login "loop"
@@ -202,7 +215,7 @@ For GitLab.com, alternatively, when users need to [link SAML to their existing G
### Users receive a 404 **(PREMIUM SAAS)**
Because SAML SSO for groups is a paid feature, your subscription expiring can result in a `404` error when you're signing in using SAML SSO on GitLab.com.
-If all users are receiving a `404` when attempting to log in using SAML, confirm
+If all users are receiving a `404` when attempting to sign in using SAML, confirm
[there is an active subscription](../../../subscriptions/gitlab_com/index.md#view-your-gitlab-saas-subscription) being used in this SAML SSO namespace.
If you receive a `404` during setup when using "verify configuration", make sure you have used the correct
diff --git a/doc/user/group/saml_sso/troubleshooting_scim.md b/doc/user/group/saml_sso/troubleshooting_scim.md
new file mode 100644
index 00000000000..6f8aed4b386
--- /dev/null
+++ b/doc/user/group/saml_sso/troubleshooting_scim.md
@@ -0,0 +1,129 @@
+---
+stage: Manage
+group: Authentication and Authorization
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Troubleshooting SCIM **(PREMIUM SAAS)**
+
+This section contains possible solutions for problems you might encounter.
+
+## How come I can't add a user after I removed them?
+
+As outlined in the [Blocking access section](scim_setup.md#blocking-access), when you remove a user, they are removed from the group. However, their account is not deleted.
+
+When the user is added back to the SCIM app, GitLab cannot create a new user because the user already exists.
+
+Solution: Have a user sign in directly to GitLab, then [manually link](scim_setup.md#user-access-and-linking-setup) their account.
+
+## How do I diagnose why a user is unable to sign in
+
+Ensure that the user has been added to the SCIM app.
+
+If you receive "User is not linked to a SAML account", then most likely the user already exists in GitLab. Have the user follow the [User access and linking setup](scim_setup.md#user-access-and-linking-setup) instructions.
+
+The **Identity** (`extern_uid`) value stored by GitLab is updated by SCIM whenever `id` or `externalId` changes. Users cannot sign in unless the GitLab Identity (`extern_uid`) value matches the `NameId` sent by SAML.
+
+This value is also used by SCIM to match users on the `id`, and is updated by SCIM whenever the `id` or `externalId` values change.
+
+It is important that this SCIM `id` and SCIM `externalId` are configured to the same value as the SAML `NameId`. SAML responses can be traced using [debugging tools](troubleshooting.md#saml-debugging-tools), and any errors can be checked against our [SAML troubleshooting docs](troubleshooting.md).
+
+## How do I verify user's SAML NameId matches the SCIM externalId
+
+Administrators can use the Admin Area to [list SCIM identities for a user](../../admin_area/index.md#user-identities).
+
+Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page.
+
+A possible alternative is to use the [SCIM API](../../../api/scim.md) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`.
+
+To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](troubleshooting.md#saml-debugging-tools).
+
+## Update or fix mismatched SCIM externalId and SAML NameId
+
+Whether the value was changed or you need to map to a different field, ensure `id`, `externalId`, and `NameId` all map to the same field.
+
+If the GitLab `externalId` doesn't match the SAML NameId, it needs to be updated in order for the user to sign in. Ideally your identity provider is configured to do such an update, but in some cases it may be unable to do so, such as when looking up a user fails due to an ID change.
+
+Be cautious if you revise the fields used by your SCIM identity provider, typically `id` and `externalId`.
+We use these IDs to look up users. If the identity provider does not know the current values for these fields,
+that provider may create duplicate users.
+
+If the `externalId` for a user is not correct, and also doesn't match the SAML NameID,
+you can address the problem in the following ways:
+
+- You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken) section.
+- You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on.
+- Use the [SCIM API](../../../api/scim.md) to manually correct the `externalId` stored for users to match the SAML `NameId`.
+ To look up a user, you need to know the desired value that matches the `NameId` as well as the current `externalId`.
+
+It is important not to update these to incorrect values, since this causes users to be unable to sign in. It is also important not to assign a value to the wrong user, as this causes users to get signed into the wrong account.
+
+## I need to change my SCIM app
+
+Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#change-the-saml-app) section.
+
+Alternatively, users can be removed from the SCIM app which de-links all removed users. Sync can then be turned on for the new SCIM app to [link existing users](scim_setup.md#user-access-and-linking-setup).
+
+## The SCIM app is throwing `"User has already been taken","status":409` error message
+
+Changing the SAML or SCIM configuration or provider can cause the following problems:
+
+| Problem | Solution |
+| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). |
+| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using the [SCIM API](../../../api/scim.md) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md) to update the SCIM `id` for the user on GitLab.com. |
+
+## Search Rails logs for SCIM requests
+
+GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in
+[Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the internal
+[SCIM API](../../../development/internal_api/index.md#scim-api):
+
+- `json.path`: `/scim/v2/groups/<group-path>`
+- `json.params.value`: `<externalId>`
+
+In a relevant log entry, the `json.params.value` shows the values of SCIM parameters GitLab receives. These values can be used to verify if SCIM parameters configured in an
+identity provider's SCIM app are communicated to GitLab as intended. For example, we can use these values as a definitive source on why an account was provisioned with a certain
+set of details. This information can help where an account was SCIM provisioned with details that appear to be incongruent with what might have been configured within an identity
+provider's SCIM app.
+
+## Azure
+
+### How do I verify my SCIM configuration is correct?
+
+Review the following:
+
+- Ensure that the SCIM value for `id` matches the SAML value for `NameId`.
+- Ensure that the SCIM value for `externalId` matches the SAML value for `NameId`.
+
+Review the following SCIM parameters for sensible values:
+
+- `userName`
+- `displayName`
+- `emails[type eq "work"].value`
+
+### Testing Azure connection: invalid credentials
+
+When testing the connection, you may encounter an error: **You appear to have entered invalid credentials. Please confirm you are using the correct information for an administrative account**. If `Tenant URL` and `secret token` are correct, check whether your group path contains characters that may be considered invalid JSON primitives (such as `.`). Removing such characters from the group path typically resolves the error.
+
+### (Field) can't be blank sync error
+
+When checking the Audit Events for the Provisioning, you can sometimes see the
+error `Namespace can't be blank, Name can't be blank, and User can't be blank.`
+
+This is likely caused because not all required fields (such as first name and last name) are present for all users being mapped.
+
+As a workaround, try an alternate mapping:
+
+1. Follow the Azure mapping instructions from above.
+1. Delete the `name.formatted` target attribute entry.
+1. Change the `displayName` source attribute to have `name.formatted` target attribute.
+
+### 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`](scim_setup.md#configure-azure-active-directory).
diff --git a/doc/user/group/settings/group_access_tokens.md b/doc/user/group/settings/group_access_tokens.md
index eb9c6af9edf..158e1654c6e 100644
--- a/doc/user/group/settings/group_access_tokens.md
+++ b/doc/user/group/settings/group_access_tokens.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: "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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
---
@@ -48,6 +48,9 @@ You cannot use group access tokens to create other group, project, or personal a
Group 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:
+Group access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../../development/fips_compliance.md) is enabled.
+
## Create a group access token using UI
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214045) in GitLab 14.7.
@@ -137,14 +140,14 @@ The scope determines the actions you can perform when you authenticate with a gr
|:-------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api` | Grants complete read and write access to the scoped group and related project API, including the [Package Registry](../../packages/package_registry/index.md). |
| `read_api` | Grants read access to the scoped group and related 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 any project within a group 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 all repositories within a group. |
-| `write_repository` | Allows read and write access (pull and push) to all repositories within a group. |
+| `read_registry` | Grants read access (pull) to the [Container Registry](../../packages/container_registry/index.md) images if any project within a group is private and authorization is required. |
+| `write_registry` | Grants write access (push) to the [Container Registry](../../packages/container_registry/index.md). |
+| `read_repository` | Grants read access (pull) to all repositories within a group. |
+| `write_repository` | Grants read and write access (pull and push) to all repositories within a group. |
## Enable or disable group access token creation
-To enable or disable group access token creation for all sub-groups in a top-level group:
+To enable or disable group access token creation for all subgroups in a top-level group:
1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 7a398c7d086..cec17688902 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating groups using file exports (deprecated) **(FREE)**
@@ -48,7 +48,15 @@ sure these users exist before importing the desired groups.
### Exported contents
-The following items are exported:
+The [`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/group/import_export.yml)
+file for groups lists many of the items exported and imported when migrating groups using file exports. View this file in the branch
+for your version of GitLab to see the list of items relevant to you. For example,
+[`import_export.yml` on the `14-10-stable-ee` branch](https://gitlab.com/gitlab-org/gitlab/-/blob/14-10-stable-ee/lib/gitlab/import_export/group/import_export.yml).
+
+Migrating projects with file exports uses the same export and import mechanisms as creating projects from templates at the [group](../custom_project_templates.md) and
+[instance](../../admin_area/custom_project_templates.md) levels. Therefore, the list of exported items is the same.
+
+Items that are exported include:
- Milestones
- Labels
@@ -60,8 +68,9 @@ The following items are exported:
- Events
- [Wikis](../../project/wiki/group.md)
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247) in GitLab 13.9)
+- Iterations cadences ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95372) in 15.4)
-The following items are **not** exported:
+Items that are **not** exported include:
- Projects
- Runner tokens
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 657ef361bd5..58f5e476f26 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Subgroups **(FREE)**
@@ -201,7 +201,7 @@ role on an ancestor group, add the user to the subgroup again with a higher role
## Mention subgroups
Mentioning subgroups ([`@<subgroup_name>`](../../discussions/index.md#mentions)) in issues, commits, and merge requests
-notifies all direct members of that group. Inherited members of a sub-group are not notified by mentions. Mentioning works the same as for projects and groups, and you can choose the group
+notifies all direct members of that group. Inherited members of a subgroup are not notified by mentions. Mentioning works the same as for projects and groups, and you can choose the group
of people to be notified.
<!-- ## Troubleshooting
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 9078874d32c..fcf4189aa32 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -1,8 +1,8 @@
---
type: reference
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Value stream analytics for groups **(PREMIUM)**
@@ -28,7 +28,7 @@ Value stream analytics is also available for [projects](../../analytics/value_st
> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 13.3
> - Horizontal stage path [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12196) in 13.0 and [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323982) in 13.12
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role to view value stream analytics for groups.
- You must create a [custom value stream](#create-a-value-stream-with-gitlab-default-stages). Value stream analytics only shows custom value streams created for your group.
@@ -68,7 +68,9 @@ The table shows a list of related workflow items for the selected stage. Based o
The **Overview** dashboard in value stream analytics shows key metrics and DORA metrics of group performance. Based on the filter you select,
the dashboard automatically aggregates DORA metrics and displays the current status of the value stream. Select a DORA metric to view its chart.
-To view deployment metrics, you must have a
+Prerequisite:
+
+- To view deployment metrics, you must have a
[production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
To view the DORA metrics and key metrics:
@@ -248,7 +250,7 @@ You can change the name of a project environment in your GitLab CI/CD configurat
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221202) in GitLab 13.3
-When you create a value stream, you can use GitLab default stages and hide or re-order them to customize. You can also
+When you create a value stream, you can use GitLab default stages and hide or re-order them. You can also
create custom stages in addition to those provided in the default template.
1. On the top bar, select **Main menu > Groups** and find your group.
diff --git a/doc/user/index.md b/doc/user/index.md
index af106b85ce9..81561d23c7b 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use GitLab **(FREE)**
diff --git a/doc/user/infrastructure/clusters/connect/index.md b/doc/user/infrastructure/clusters/connect/index.md
index af728cb5c21..9325f11b0c7 100644
--- a/doc/user/infrastructure/clusters/connect/index.md
+++ b/doc/user/infrastructure/clusters/connect/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connect a cluster to GitLab **(FREE)**
diff --git a/doc/user/infrastructure/clusters/connect/new_civo_cluster.md b/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
index f9feef6329c..998548e3a5e 100644
--- a/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a Civo Kubernetes cluster
diff --git a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
index 126968baee7..164b426fd24 100644
--- a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create an Amazon EKS cluster
diff --git a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
index a23a9e7a6e5..d04b14bf80f 100644
--- a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a Google GKE cluster
diff --git a/doc/user/infrastructure/clusters/deploy/inventory_object.md b/doc/user/infrastructure/clusters/deploy/inventory_object.md
index fc3b86776f0..6bd44c7a0f7 100644
--- a/doc/user/infrastructure/clusters/deploy/inventory_object.md
+++ b/doc/user/infrastructure/clusters/deploy/inventory_object.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tracking cluster resources managed by GitLab **(FREE)**
diff --git a/doc/user/infrastructure/clusters/index.md b/doc/user/infrastructure/clusters/index.md
index 9c8bcd9289c..14fd4917141 100644
--- a/doc/user/infrastructure/clusters/index.md
+++ b/doc/user/infrastructure/clusters/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Kubernetes clusters **(FREE)**
diff --git a/doc/user/infrastructure/clusters/manage/clusters_health.md b/doc/user/infrastructure/clusters/manage/clusters_health.md
index 0eefae3f550..4f63f3e4e2a 100644
--- a/doc/user/infrastructure/clusters/manage/clusters_health.md
+++ b/doc/user/infrastructure/clusters/manage/clusters_health.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Clusters health (DEPRECATED) **(FREE)**
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
index 5f77b7e402a..8b75d54d352 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install cert-manager with a cluster management project **(FREE)**
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md b/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
deleted file mode 100644
index 7ab99ab3875..00000000000
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-stage: Monitor
-group: Respond
-info: 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
-remove_date: '2022-08-22'
-redirect_to: '../../index.md'
----
-
-# Install Elastic Stack with a cluster management project (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) in GitLab 14.8
-and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/360182) in 15.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md b/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
index 7983a640577..bf86fdb5a8f 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install Ingress with a cluster management project **(FREE)**
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md b/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md
index ef7c4637607..4c68ec42712 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install GitLab Runner with a cluster management project **(FREE)**
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
index 31a22a240d9..72a44ef2a21 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Install Vault with a cluster management project **(FREE)**
@@ -88,7 +88,7 @@ server:
After you have successfully installed Vault, you must
[initialize the Vault](https://learn.hashicorp.com/tutorials/vault/getting-started-deploy#initializing-the-vault)
and obtain the initial root token. You need access to your Kubernetes cluster that
-Vault has been deployed into in order to do this. To initialize the Vault, get a
+Vault has been deployed into to do this. To initialize the Vault, get a
shell to one of the Vault pods running inside Kubernetes (typically this is done
by using the `kubectl` command line tool). After you have a shell into the pod,
run the `vault operator init` command:
diff --git a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
index abdb7c58d82..b2b5da61a81 100644
--- a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
+++ b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrate to the GitLab agent for Kubernetes **(FREE)**
@@ -26,7 +26,7 @@ you can use the [CI/CD workflow](../../clusters/agent/ci_cd_workflow.md).
This workflow uses an agent to connect to your cluster. The agent:
- Is not exposed to the internet.
-- Does not require full cluster-admin access to GitLab.
+- Does not require full [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) access to GitLab.
NOTE:
The certificate-based integration was used for popular GitLab features like
diff --git a/doc/user/infrastructure/iac/index.md b/doc/user/infrastructure/iac/index.md
index d5eabb9ba46..c2285ecc773 100644
--- a/doc/user/infrastructure/iac/index.md
+++ b/doc/user/infrastructure/iac/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Infrastructure as Code with Terraform and GitLab **(FREE)**
@@ -19,7 +19,7 @@ Terraform to define resources that you can version, reuse, and share:
## Integrate your project with Terraform
-> SAST test was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.6.
+> IaC Scanning was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.6.
The integration with GitLab and Terraform happens through GitLab CI/CD.
Use an `include` attribute to add the Terraform template to your project and
@@ -35,7 +35,7 @@ All templates:
- Use the [GitLab-managed Terraform state](terraform_state.md) as the Terraform state storage backend.
- Trigger four pipeline stages: `test`, `validate`, `build`, and `deploy`.
- Run Terraform commands: `test`, `validate`, `plan`, and `plan-json`. It also runs the `apply` only on the default branch.
-- Run the [Terraform SAST scanner](../../application_security/iac_scanning/index.md#configure-iac-scanning-manually).
+- Check for security problems using [IaC Scanning](../../application_security/iac_scanning/index.md#configure-iac-scanning-manually).
### Latest Terraform template
diff --git a/doc/user/infrastructure/iac/mr_integration.md b/doc/user/infrastructure/iac/mr_integration.md
index 0fea05a3f03..7b4a7cd6b95 100644
--- a/doc/user/infrastructure/iac/mr_integration.md
+++ b/doc/user/infrastructure/iac/mr_integration.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Terraform integration in merge requests **(FREE)**
@@ -85,7 +85,7 @@ To manually configure a GitLab Terraform Report artifact:
![merge request Terraform widget](img/terraform_plan_widget_v13_2.png)
-1. Clicking the **View Full Log** button in the widget takes you directly to the
+1. Selecting the **View Full Log** button in the widget takes you directly to the
plan output present in the pipeline logs:
![Terraform plan logs](img/terraform_plan_log_v13_0.png)
diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index d4fea6b7dba..9cb3fdd7aaf 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab-managed Terraform state **(FREE)**
diff --git a/doc/user/infrastructure/iac/troubleshooting.md b/doc/user/infrastructure/iac/troubleshooting.md
index 3286b550507..a1eecb909fb 100644
--- a/doc/user/infrastructure/iac/troubleshooting.md
+++ b/doc/user/infrastructure/iac/troubleshooting.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting the Terraform integration with GitLab
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 73e57ea3d59..811e4ad6ad6 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Infrastructure management **(FREE)**
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index 27aa3479b88..eb703328270 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Instance-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE SELF)**
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index d61190fbd31..1a743ae99bb 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Flavored Markdown (GLFM) **(FREE)**
@@ -1764,6 +1764,7 @@ If JSON is invalid, an error occurs.
## References
+- The [GitLab Flavored Markdown (GLFM) Specification Guide](../development/gitlab_flavored_markdown/index.md) is a developer-facing document that describes in detail the various goals, tools, implementations, and terms related to the GLFM specification.
- This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
- The original [Markdown Syntax Guide](https://daringfireball.net/projects/markdown/syntax)
at Daring Fireball is an excellent resource for a detailed explanation of standard Markdown.
diff --git a/doc/user/namespace/index.md b/doc/user/namespace/index.md
index 138b0a355ad..36e048868ad 100644
--- a/doc/user/namespace/index.md
+++ b/doc/user/namespace/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Namespaces
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index 0a7e9d6395b..0a65ea0f64d 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Operations Dashboard **(PREMIUM)**
@@ -13,11 +13,6 @@ To access the dashboard, on the top bar, select **Main menu > Operations**.
## Adding a project to the dashboard
-NOTE:
-For GitLab.com, you can add your project to the Operations Dashboard for free if
-your project is public. If your project is private, the group it belongs to must
-have a [GitLab Premium](https://about.gitlab.com/pricing/) plan.
-
To add a project to the dashboard:
1. Ensure your alerts populate the `gitlab_environment_name` label on the alerts you set up in Prometheus.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 84f544ec4ad..5eafb74a144 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Composer packages in the Package Registry **(FREE)**
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index ed106685b62..cd5ce9a1135 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Conan packages in the Package Registry **(FREE)**
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index bfbc400f4dd..1ac38979950 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Container Registry **(FREE)**
@@ -101,12 +101,14 @@ registry.example.com/mynamespace/myproject/my/image:rc1
## Authenticate with the Container Registry
-To authenticate with the Container Registry, you can use:
+To authenticate with the Container Registry, you can use a:
-- A [personal access token](../../profile/personal_access_tokens.md).
-- A [deploy token](../../project/deploy_tokens/index.md).
+- [Personal access token](../../profile/personal_access_tokens.md).
+- [Deploy token](../../project/deploy_tokens/index.md).
+- [Project access token](../../project/settings/project_access_tokens.md).
+- [Group access token](../../group/settings/group_access_tokens.md).
-Both of these require the minimum scope to be:
+All of these require the minimum scope to be:
- For read (pull) access, `read_registry`.
- For write (push) access, `write_registry` & `read_registry`.
@@ -397,10 +399,10 @@ To delete images from within GitLab:
1. From the **Container Registry** page, you can select what you want to delete,
by either:
- - Deleting the entire repository, and all the tags it contains, by clicking
+ - Deleting the entire repository, and all the tags it contains, by selecting
the red **{remove}** **Trash** icon.
- Navigating to the repository, and deleting tags individually or in bulk
- by clicking the red **{remove}** **Trash** icon next to the tag you want
+ by selecting the red **{remove}** **Trash** icon next to the tag you want
to delete.
1. In the dialog box, select **Remove tag**.
@@ -601,7 +603,7 @@ You can then tag the manifest list with `mygroup/myapp:1.0.0`.
### Troubleshoot as a GitLab server administrator
Troubleshooting the GitLab Container Registry, most of the times, requires
-you to log in to GitLab server with administrator access.
+you to sign in to GitLab server with administrator access.
[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.md#troubleshooting).
@@ -711,7 +713,7 @@ Follow [this issue](https://gitlab.com/gitlab-org/container-registry/-/issues/55
GitLab is [migrating to the next generation of the Container Registry](https://gitlab.com/groups/gitlab-org/-/epics/5523).
During the migration, you may encounter difficulty deleting tags.
If you encounter an error, it's likely that your image repository is in the process of being migrated.
-Please wait a few minutes and try again.
+Wait a few minutes and try again.
### `unauthorized: authentication required` when pushing large images
diff --git a/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md b/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md
index 76e3da9538f..ff89e5f361f 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_data_transfer.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reduce Container Registry data transfers **(FREE)**
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index b3dd8da9b41..9c981aeac53 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reduce Container Registry Storage **(FREE)**
@@ -11,27 +11,26 @@ Container registries become large over time without cleanup. When a large number
- Fetching the list of available tags or images becomes slower.
- They take up a large amount of storage space on the server.
-We recommend deleting unnecessary images and tags, and setting up a [cleanup policy](#cleanup-policy)
+We recommend deleting unnecessary images and tags and setting up a [cleanup policy](#cleanup-policy)
to automatically manage your container registry usage.
## Check Container Registry Storage Use
The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages.
-This page includes the Container Registry usage but is currently only available on GitLab.com.
+This page includes the Container Registry usage, which is only available on GitLab.com.
Measuring usage is only possible on the new version of the GitLab Container Registry backed by a
-metadata database. We are completing the [upgrade and migration of the GitLab.com Container Registry](https://gitlab.com/groups/gitlab-org/-/epics/5523)
-first and only then will work on [making this available to self-managed installs](https://gitlab.com/groups/gitlab-org/-/epics/5521).
+metadata database. Support for improvements is proposed in epic [5523](https://gitlab.com/groups/gitlab-org/-/epics/5523).
+You cannot use the Container Registry in self-managed instances, but epic [5521](https://gitlab.com/groups/gitlab-org/-/epics/5521) proposes to change this behavior.
Image layers stored in the Container Registry are deduplicated at the root namespace level.
-Therefore, if you tag the same 500MB image twice (either in the same repository or across distinct
-repositories under the same root namespace), it will only count towards the root namespace usage
-once. Similarly, if a given image layer is shared across multiple images, be those under the same
-container repository, project, group, or across different ones, that layer will count only once
-towards the root namespace usage.
+If you tag the same image more than once in the same repository or across distinct
+repositories under the same root namespace, it is only counted once.
+If an image layer is shared across multiple images, in the same
+container repository, project, group, or across different repositories, it is only counted once.
Only layers that are referenced by tagged images are accounted for. Untagged images and any layers
-referenced exclusively by them are subject to [online garbage collection](index.md#delete-images)
-and automatically deleted after 24 hours if they remain unreferenced during that period.
+referenced exclusively by them are subject to [online garbage collection](index.md#delete-images).
+Untagged images are automatically deleted after 24 hours if they remain unreferenced during that period.
Image layers are stored on the storage backend in the original (usually compressed) format. This
means that the measured size for any given image layer should match the size displayed on the
@@ -39,7 +38,6 @@ corresponding [image manifest](https://github.com/opencontainers/image-spec/blob
## Cleanup policy
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15398) in GitLab 12.8.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/218737) from "expiration policy" to "cleanup policy" in GitLab 13.2.
> - [Required permissions](https://gitlab.com/gitlab-org/gitlab/-/issues/350682) changed from developer to maintainer in GitLab 15.0.
@@ -56,7 +54,7 @@ Cleanup policies can be run on all projects, with these exceptions:
- For self-managed GitLab instances, the project must have been created
in GitLab 12.8 or later. However, an administrator can enable the cleanup policy
- for all projects (even those created before 12.8) in
+ for all projects (even those created before GitLab 12.8) in
[GitLab application settings](../../../api/settings.md#change-application-settings)
by setting `container_expiration_policies_enable_historic_entries` to true.
Alternatively, you can execute the following command in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
@@ -65,7 +63,7 @@ Cleanup policies can be run on all projects, with these exceptions:
ApplicationSetting.last.update(container_expiration_policies_enable_historic_entries: true)
```
- There are performance risks with enabling it for all projects, especially if you
+ Enabling cleanup policies on all project can impact performance, especially if you
are using an [external registry](#use-with-external-container-registries).
WARNING:
@@ -77,7 +75,7 @@ GitLab.com that don't have a container image.
The cleanup policy collects all tags in the Container Registry and excludes tags
until only the tags to be deleted remain.
-The cleanup policy searches for images based on the tag name. Support for the full path [has not yet been implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/281071), but would allow you to clean up dynamically-named tags.
+The cleanup policy searches for images based on the tag name. Support for full path matching is tracked in issue [281071](https://gitlab.com/gitlab-org/gitlab/-/issues/281071).
The cleanup policy:
@@ -92,9 +90,9 @@ The cleanup policy:
1. Finally, the remaining tags in the list are deleted from the Container Registry.
WARNING:
-On GitLab.com, the execution time for the cleanup policy is limited, and some of the tags may remain in
-the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included,
-so it may take multiple runs for all tags to be deleted.
+On GitLab.com, the execution time for the cleanup policy is limited. Some tags may remain in
+the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included.
+It may take multiple runs for all tags to be deleted.
WARNING:
GitLab self-managed installations support third-party container registries that comply with the
@@ -139,7 +137,7 @@ Cleanup policies use regex patterns to determine which tags should be preserved
Regex patterns are automatically surrounded with `\A` and `\Z` anchors. Do not include any `\A`, `\Z`, `^` or `$` token in the regex patterns as they are not necessary.
-Here are examples of regex patterns you may want to use:
+Here are some examples of regex patterns you can use:
- Match all tags:
@@ -147,7 +145,7 @@ Here are examples of regex patterns you may want to use:
.*
```
- This is the default value for the expiration regex.
+ This pattern is the default value for the expiration regex.
- Match tags that start with `v`:
@@ -255,9 +253,8 @@ When using an [external container registry](../../../administration/packages/con
running a cleanup policy on a project may have some performance risks.
If a project runs a policy to remove thousands of tags
the GitLab background jobs may get backed up or fail completely.
-It is recommended you only enable container cleanup
-policies for projects that were created before GitLab 12.8 if you are confident the number of tags
-being cleaned up is minimal.
+For projects created before GitLab 12.8, we recommend you enable container cleanup policies
+only if the number of tags being cleaned up is minimal.
## More Container Registry storage reduction options
@@ -302,17 +299,16 @@ There can be different reasons behind this:
- Extend the expiration delay of the Container Registry authentication tokens. This defaults to 5
minutes. You can set a custom value by running
`ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)` in the Rails
- console, where `<integer>` is the desired number of minutes. For reference, 15 minutes is the
- value currently in use for GitLab.com. Be aware that by extending this value you increase the
+ console, where `<integer>` is the desired number of minutes. For reference, the expiration delay
+ is set to 15 minutes on GitLab.com. If you increase this value you increase the
time required to revoke permissions.
-If the previous fixes didn't work or you are on earlier versions of GitLab, you can generate a list
-of the tags that you want to delete, and then use that list to delete the tags. To do this, follow
-these steps:
+Alternatively, you can generate a list of tags to delete, and use that list to delete
+the tags. To create the list and delete the tags:
1. Run the following shell script. The command just before the `for` loop ensures that
`list_o_tags.out` is always reinitialized when starting the loop. After running this command, all
- the tags' names will be in the `list_o_tags.out` file:
+ the tags' names are written to the `list_o_tags.out` file:
```shell
# Get a list of all tags in a certain container repository while considering [pagination](../../../api/index.md#pagination)
@@ -331,9 +327,8 @@ these steps:
This set of commands creates a `/tmp/list_o_tags.out` file listing all tags with a `created_at` date of older than one month.
-1. Remove from the `list_o_tags.out` file any tags that you want to keep. Here are some example
- `sed` commands for this. Note that these commands are simply examples. You may change them to
- best suit your needs:
+1. Remove any tags that you want to keep from the `list_o_tags.out` file. For example, you can use `sed` to
+ parse the file and remove the tags.
```shell
# Remove the `latest` tag from the file
diff --git a/doc/user/packages/debian_repository/index.md b/doc/user/packages/debian_repository/index.md
index 4143ab0881f..90fc0bc3bb1 100644
--- a/doc/user/packages/debian_repository/index.md
+++ b/doc/user/packages/debian_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Debian packages in the Package Registry **(FREE)**
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 1310f8eedaa..3fb22437eb0 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Dependency Proxy **(FREE)**
@@ -74,7 +74,7 @@ you must authenticate against the Dependency Proxy.
Follow the [instructions for using images from a private registry](../../../ci/docker/using_docker_images.md#access-an-image-from-a-private-container-registry),
but instead of using `registry.example.com:5000`, use your GitLab domain with no port `gitlab.example.com`.
-For example, to manually log in:
+For example, to manually sign in:
```shell
docker login gitlab.example.com --username my_username --password my_password
@@ -84,7 +84,7 @@ You can authenticate using:
- Your GitLab username and password.
- 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`.
+- A [group deploy token](../../../user/project/deploy_tokens/index.md) with the scope set to `read_registry` and `write_registry`.
Users accessing the Dependency Proxy with a personal access token or username and password must
have at least the Guest role for the group they pull images from.
@@ -109,7 +109,7 @@ Proxy.
> - Automatic runner authentication, when using the Dependency Proxy to pull the image for the job, was [added](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27302) in GitLab 13.9.
> - The prefix for group names containing uppercase letters was [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54559) in GitLab 13.10.
-Runners log in to the Dependency Proxy automatically. To pull through
+Runners sign in to the Dependency Proxy automatically. To pull through
the Dependency Proxy, use one of the [predefined variables](../../../ci/variables/predefined_variables.md):
- `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` pulls through the top-level group.
diff --git a/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md b/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md
index fecf60feeef..1239d1a97ae 100644
--- a/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md
+++ b/doc/user/packages/dependency_proxy/reduce_dependency_proxy_storage.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reduce Dependency Proxy Storage **(FREE)**
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 312a2c119d6..930e0760eb3 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Generic Packages Repository **(FREE)**
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index 733fd383a04..6f6dc084720 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Go proxy for GitLab **(FREE)**
diff --git a/doc/user/packages/harbor_container_registry/index.md b/doc/user/packages/harbor_container_registry/index.md
index 720e274aee5..217d3d57416 100644
--- a/doc/user/packages/harbor_container_registry/index.md
+++ b/doc/user/packages/harbor_container_registry/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Harbor Registry **(FREE)**
@@ -19,7 +19,7 @@ You can view the Harbor Registry for a project or group.
You can search, sort, and filter images on this page. You can share a filtered view by copying the URL from your browser.
At the project level, you can see **CLI Commands** in the upper right corner, where you can copy
-corresponding commands to log in, build images, and push images. **CLI Commands** is not shown at
+corresponding commands to sign in, build images, and push images. **CLI Commands** is not shown at
the group level.
NOTE:
@@ -31,7 +31,7 @@ To download and run a Harbor image hosted in the GitLab Harbor Registry:
1. Copy the link to your container image:
1. Go to your project or group's **Packages and registries > Harbor Registry** and find the image you want.
- 1. Click the **Copy** icon next to the image name.
+ 1. Select the **Copy** icon next to the image name.
1. Use the command to run the container image you want.
@@ -41,7 +41,7 @@ To view the list of tags associated with a specific artifact:
1. Go to your project or group.
1. Go to **Packages and registries > Harbor Registry**.
-1. Click the image name to view its artifacts.
+1. Select the image name to view its artifacts.
1. Select the artifact you want.
This brings up the list of tags. You can view the tag count and the time published.
@@ -62,7 +62,7 @@ To view these commands, go to your project's **Packages and registries > Harbor
To remove the Harbor Registry for a project:
1. Go to your project/group's **Settings > Integrations** page.
-1. Click **Harbor** under **Active integrations**.
+1. Select **Harbor** under **Active integrations**.
1. Clear the **Active** checkbox under **Enable integration**.
1. Select **Save changes**.
diff --git a/doc/user/packages/helm_repository/index.md b/doc/user/packages/helm_repository/index.md
index f64a269938f..521f04226df 100644
--- a/doc/user/packages/helm_repository/index.md
+++ b/doc/user/packages/helm_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Helm charts in the Package Registry **(FREE)**
@@ -100,7 +100,7 @@ upload:
## Install a package
NOTE:
-When requesting a package, GitLab considers only the 300 most recent packages created.
+When requesting a package, GitLab considers only the 1000 most recent packages created.
For each package, only the most recent package file is returned.
To install the latest version of a chart, use the following command:
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index 86cfa8986bb..84a10943879 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Packages and Registries **(FREE)**
diff --git a/doc/user/packages/infrastructure_registry/index.md b/doc/user/packages/infrastructure_registry/index.md
index 48cc7b9dea9..8129b42905a 100644
--- a/doc/user/packages/infrastructure_registry/index.md
+++ b/doc/user/packages/infrastructure_registry/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Infrastructure Registry **(FREE)**
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 957374245d2..ec56255999a 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Maven packages in the Package Repository **(FREE)**
@@ -168,7 +168,7 @@ published to the GitLab Package Registry.
Enter selection (default: Groovy) [1..2]
```
-1. Enter `1` to create a new Java Library project that is described in Groovy DSL. The output should be:
+1. Enter `1` to create a new Java Library project that is described in Groovy DSL, or `2` to create one that is described in Kotlin DSL. The output should be:
```plaintext
Select test framework:
@@ -286,7 +286,7 @@ To authenticate to the Package Registry, you need either a personal access token
In [your `GRADLE_USER_HOME` directory](https://docs.gradle.org/current/userguide/directory_layout.html#dir:gradle_user_home),
create a file `gradle.properties` with the following content:
-```groovy
+```properties
gitLabPrivateToken=REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN
```
@@ -310,6 +310,24 @@ repositories {
}
```
+Or add it to your `build.gradle.kts` file if you are using Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
+ name = "GitLab"
+ credentials(HttpHeaderCredentials::class) {
+ name = "Private-Token"
+ value = findProperty("gitLabPrivateToken") as String?
+ }
+ authentication {
+ create("header", HttpHeaderAuthentication::class)
+ }
+ }
+}
+```
+
### Authenticate with a deploy token in Gradle
To authenticate with a deploy token, add a `repositories` section to your
@@ -332,6 +350,24 @@ repositories {
}
```
+Or add it to your `build.gradle.kts` file if you are using Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
+ name = "GitLab"
+ credentials(HttpHeaderCredentials::class) {
+ name = "Deploy-Token"
+ value = "<deploy-token>"
+ }
+ authentication {
+ create("header", HttpHeaderAuthentication::class)
+ }
+ }
+}
+```
+
### Authenticate with a CI job token in Gradle
To authenticate with a CI job token, add a `repositories` section to your
@@ -354,6 +390,24 @@ repositories {
}
```
+Or add it to your `build.gradle.kts` file if you are using Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("$CI_API_V4_URL/groups/<group>/-/packages/maven")
+ name = "GitLab"
+ credentials(HttpHeaderCredentials::class) {
+ name = "Job-Token"
+ value = System.getenv("CI_JOB_TOKEN")
+ }
+ authentication {
+ create("header", HttpHeaderAuthentication::class)
+ }
+ }
+}
+```
+
## Use the GitLab endpoint for Maven packages
To use the GitLab endpoint for Maven packages, choose an option:
@@ -397,7 +451,7 @@ in Maven should look like this:
</distributionManagement>
```
-The corresponding section in Gradle would be:
+The corresponding section in Gradle Groovy DSL would be:
```groovy
repositories {
@@ -408,6 +462,17 @@ repositories {
}
```
+In Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven")
+ name = "GitLab"
+ }
+}
+```
+
- The `id` is what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
- The `PROJECT_ID` is your project ID, which you can view on your project's home page.
- Replace `gitlab.example.com` with your domain name.
@@ -454,7 +519,7 @@ the `distributionManagement` section:
</distributionManagement>
```
-For Gradle, the corresponding `repositories` section would look like:
+For Gradle, the corresponding `repositories` section in Groovy DSL would look like:
```groovy
repositories {
@@ -465,6 +530,17 @@ repositories {
}
```
+In Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/groups/GROUP_ID/-/packages/maven")
+ name = "GitLab"
+ }
+}
+```
+
- For the `id`, use what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
- For `GROUP_ID`, use your group ID, which you can view on your group's home page.
- For `PROJECT_ID`, use your project ID, which you can view on your project's home page.
@@ -513,7 +589,7 @@ You still need a project-specific URL in the `distributionManagement` section.
</distributionManagement>
```
-The corresponding repositories section in Gradle would look like:
+The corresponding repositories section in Gradle Groovy DSL would look like:
```groovy
repositories {
@@ -524,6 +600,17 @@ repositories {
}
```
+In Kotlin DSL:
+
+```kotlin
+repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/packages/maven")
+ name = "GitLab"
+ }
+}
+```
+
- The `id` is what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
- The `PROJECT_ID` is your project ID, which you can view on your project's home page.
- Replace `gitlab.example.com` with your domain name.
@@ -566,6 +653,8 @@ To publish a package by using Gradle:
1. Add the Gradle plugin [`maven-publish`](https://docs.gradle.org/current/userguide/publishing_maven.html) to the plugins section:
+ In Groovy DSL:
+
```groovy
plugins {
id 'java'
@@ -573,8 +662,19 @@ To publish a package by using Gradle:
}
```
+ In Kotlin DSL:
+
+ ```kotlin
+ plugins {
+ java
+ `maven-publish`
+ }
+ ```
+
1. Add a `publishing` section:
+ In Groovy DSL:
+
```groovy
publishing {
publications {
@@ -597,6 +697,31 @@ To publish a package by using Gradle:
}
```
+ In Kotlin DSL:
+
+ ```kotlin
+ publishing {
+ publications {
+ create<MavenPublication>("library") {
+ from(components["java"])
+ }
+ }
+ repositories {
+ maven {
+ url = uri("https://gitlab.example.com/api/v4/projects/<PROJECT_ID>/packages/maven")
+ credentials(HttpHeaderCredentials::class) {
+ name = "Private-Token"
+ value =
+ findProperty("gitLabPrivateToken") as String? // the variable resides in $GRADLE_USER_HOME/gradle.properties
+ }
+ authentication {
+ create("header", HttpHeaderAuthentication::class)
+ }
+ }
+ }
+ }
+ ```
+
1. Replace `PROJECT_ID` with your project ID, which can be found on your project's home page.
1. Run the publish task:
@@ -703,6 +828,14 @@ dependencies {
}
```
+Or to `build.gradle.kts` if you are using Kotlin DSL:
+
+```kotlin
+dependencies {
+ implementation("com.mycompany.mydepartment:my-project:1.0-SNAPSHOT")
+}
+```
+
### Request forwarding to Maven Central
> [Introduced](<https://gitlab.com/gitlab-org/gitlab/-/issues/362657>) behind a [feature flag](../../feature_flags.md), disabled by default in GitLab 15.4
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 678f5681890..44266559999 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# npm packages in the Package Registry **(FREE)**
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 5b1e5bbd304..d4b87d70447 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# NuGet packages in the Package Registry **(FREE)**
@@ -15,8 +15,8 @@ packages whenever you need to use them as a dependency.
The Package Registry works with:
-- [NuGet CLI](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)
-- [.NET Core CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/)
+- [NuGet CLI](https://learn.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)
+- [.NET Core CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/)
- [Visual Studio](https://visualstudio.microsoft.com/vs/)
For documentation of the specific API endpoints that these
@@ -342,7 +342,7 @@ When publishing packages:
Prerequisites:
-- [A NuGet package created with NuGet CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package).
+- [A NuGet package created with NuGet CLI](https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package).
- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
Publish a package by running this command:
@@ -358,7 +358,7 @@ nuget push <package_file> -Source <source_name>
Prerequisites:
-- [A NuGet package created with .NET CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli).
+- [A NuGet package created with .NET CLI](https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli).
- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
Publish a package by running this command:
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index fe19c549536..2d8cb46f933 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Package Registry **(FREE)**
@@ -53,7 +53,7 @@ For most package types, the following credential types are valid:
- [Project deploy token](../../project/deploy_tokens/index.md):
allows access to all packages in a project. Good for granting and revoking project access to many
users.
-- [Group deploy token](../../project/deploy_tokens/index.md#group-deploy-token):
+- [Group deploy token](../../project/deploy_tokens/index.md):
allows access to all packages in a group and its subgroups. Good for granting and revoking access
to a large number of packages to sets of users.
- [Job token](../../../ci/jobs/ci_job_token.md):
diff --git a/doc/user/packages/package_registry/reduce_package_registry_storage.md b/doc/user/packages/package_registry/reduce_package_registry_storage.md
index d85992fe05d..e6996d9dc3e 100644
--- a/doc/user/packages/package_registry/reduce_package_registry_storage.md
+++ b/doc/user/packages/package_registry/reduce_package_registry_storage.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reduce Package Registry Storage **(FREE)**
@@ -71,9 +71,9 @@ To access these project settings, you must be at least a maintainer on the relat
### Available rules
-- `Number of duplicated assets to keep`. The number of duplicated assets to keep. Some package formats allow you
+- `Number of duplicated assets to keep`: The number of duplicated assets to keep. Some package formats allow you
to upload more than one copy of an asset. You can limit the number of duplicated assets to keep and automatically
- delete the oldest assets once the limit is reached.
+ delete the oldest assets once the limit is reached. Unique filenames, such as those produced by Maven snapshots, are not considered when evaluating the number of duplicated assets to keep.
### Set cleanup limits to conserve resources
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 302c88bf46f..fb1b9ce78ab 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# PyPI packages in the Package Registry **(FREE)**
@@ -426,7 +426,7 @@ the three characters, such as `my-package`, `my_package`, and `my....package`.
## Troubleshooting
-To improve performance, PyPI caches files related to a package. Note that PyPI doesn't remove data by
+To improve performance, the pip command caches files related to a package. Note that pip doesn't remove data by
itself. The cache grows as new packages are installed. If you encounter issues, clear the cache with
this command:
diff --git a/doc/user/packages/rubygems_registry/index.md b/doc/user/packages/rubygems_registry/index.md
index 682a3e2ecf1..f21b210f4f5 100644
--- a/doc/user/packages/rubygems_registry/index.md
+++ b/doc/user/packages/rubygems_registry/index.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Ruby gems in the Package Registry **(FREE)**
@@ -76,7 +76,7 @@ https://gitlab.example.com/api/v4/projects/<project_id>/packages/rubygems: '<you
### Authenticate with a CI job token
To work with RubyGems commands within [GitLab CI/CD](../../../ci/index.md),
-you can use `CI_JOB_TOKEN` instead of a personal access token or deploy token.
+you can use the [`CI_JOB_TOKEN`](../../../ci/jobs/ci_job_token.md) predefined environment variable instead of a personal access token or deploy token.
For example:
diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md
index 0a3de25bf7d..6dd118c39b4 100644
--- a/doc/user/packages/terraform_module_registry/index.md
+++ b/doc/user/packages/terraform_module_registry/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Terraform module registry **(FREE)**
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index 12978ad72a5..25c64c93b73 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Store all of your packages in one GitLab project **(FREE)**
diff --git a/doc/user/packages/workflows/working_with_monorepos.md b/doc/user/packages/workflows/working_with_monorepos.md
index ab10e746302..5606e257ea8 100644
--- a/doc/user/packages/workflows/working_with_monorepos.md
+++ b/doc/user/packages/workflows/working_with_monorepos.md
@@ -1,7 +1,7 @@
---
stage: Package
group: Package
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monorepo package management workflows **(FREE)**
@@ -40,7 +40,7 @@ and by doing one of the following:
If you follow the instructions, you can publish `MyProject` by running `npm publish` from the root
directory.
-Publishing `Foo` is almost exactly the same. Simply follow the same steps while in the `Foo`
+Publishing `Foo` is almost exactly the same. Follow the same steps while in the `Foo`
directory. `Foo` needs its own `package.json` file, which you can add manually by using `npm init`.
`Foo` also needs its own configuration settings. Since you are publishing to the same place, if you
used `npm config set` to set the registry for the parent project, then no additional setup is
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 9a4590d9478..102abf2b427 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Permissions and roles **(FREE)**
@@ -91,6 +91,7 @@ The following table lists project permissions available for each role:
| [Issue boards](project/issue_board.md):<br>Create or delete lists | | ✓ | ✓ | ✓ | ✓ |
| [Issue boards](project/issue_board.md):<br>Move issues between lists | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Add to epic | | ✓ (*23*) | ✓ (*23*) | ✓ (*23*) | ✓ (*23*) |
| [Issues](project/issues/index.md):<br>Assign | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Create (*18*) | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Create [confidential issues](project/issues/confidential_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -165,7 +166,7 @@ The following table lists project permissions available for each role:
| [Projects](project/index.md):<br>Rename project | | | | ✓ | ✓ |
| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*7*) | ✓ (*7*) |
| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Assign project to a [compliance framework](project/settings/index.md#compliance-frameworks) | | | | | ✓ |
+| [Projects](project/index.md):<br>Assign project to a [compliance framework](project/settings/index.md#add-a-compliance-framework-to-a-project) | | | | | ✓ |
| [Projects](project/index.md):<br>Archive project | | | | | ✓ |
| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ |
| [Projects](project/index.md):<br>Delete project | | | | | ✓ |
@@ -246,6 +247,7 @@ The following table lists project permissions available for each role:
20. The ability to view the Container Registry and pull images is controlled by the [Container Registry's visibility permissions](packages/container_registry/index.md#container-registry-visibility-permissions).
21. Maintainers cannot create, demote, or remove Owners, and they cannot promote users to the Owner role. They also cannot approve Owner role access requests.
22. Authors of tasks can delete them even if they don't have the Owner role, but they have to have at least the Guest role for the project.
+23. You must have permission to [view the epic](group/epics/manage_epics.md#who-can-view-an-epic).
<!-- markdownlint-enable MD029 -->
@@ -379,6 +381,7 @@ The following table lists group permissions available for each role:
| Action | Guest | Reporter | Developer | Maintainer | Owner |
|-----------------------------------------------------------------------------------------|-------|----------|-----------|------------|-------|
+| Add an issue to an [epic](group/epics/index.md) | ✓ (7) | ✓ (7) | ✓ (7) | ✓ (7) | ✓ (7) |
| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
| Pull a container image using the dependency proxy | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -445,6 +448,7 @@ The following table lists group permissions available for each role:
4. Developers can push commits to the default branch of a new project only if the [default branch protection](group/manage.md#change-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected".
5. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages.
6. Users can only view events based on their individual actions.
+7. You must have permission to [view the epic](group/epics/manage_epics.md#who-can-view-an-epic) and edit the issue.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index e3f7d47038d..f2636fdaa68 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -2,7 +2,7 @@
type: reference
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Creating users **(FREE SELF)**
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index d2e0c1ad834..5e2908a26e1 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deleting a user account **(FREE)**
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 02567958356..3dc768f6606 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Two-factor authentication **(FREE)**
@@ -452,11 +452,10 @@ This error occurs in the following scenarios:
[enforce 2FA for all users](../../../security/two_factor_authentication.md#enforce-2fa-for-all-users) setting.
- You do not have 2FA enabled, but an administrator has disabled the
[password authentication enabled for Git over HTTP(S)](../../admin_area/settings/sign_in_restrictions.md#password-authentication-enabled)
- setting. If LDAP is:
- - Configured, an [LDAP password](../../../administration/auth/ldap/index.md)
- or a [personal access token](../personal_access_tokens.md)
- must be used to authenticate Git requests over HTTP(S).
- - Not configured, you must use a [personal access token](../personal_access_tokens.md).
+ setting. You can authenticate Git requests:
+ - Over HTTP(S) using a [personal access token](../personal_access_tokens.md).
+ - In your browser using [Git Credential Manager](#git-credential-manager).
+ - If you have configured LDAP, over HTTP(S) using an [LDAP password](../../../administration/auth/ldap/index.md).
### Error: "invalid pin code"
diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md
index b30ee002758..d0600e5e80d 100644
--- a/doc/user/profile/active_sessions.md
+++ b/doc/user/profile/active_sessions.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto
---
diff --git a/doc/user/profile/img/unknown_sign_in_email_v14_0.png b/doc/user/profile/img/unknown_sign_in_email_v14_0.png
deleted file mode 100644
index 62634739b78..00000000000
--- a/doc/user/profile/img/unknown_sign_in_email_v14_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index e4cf905bbce..66f6b4b52de 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -2,7 +2,7 @@
type: index, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# User account **(FREE)**
@@ -25,19 +25,6 @@ To access your user settings:
1. On the top bar, in the top-right corner, select your avatar.
1. Select **Edit profile**.
-## Change your password
-
-To change your password:
-
-1. On the top bar, in the top-right corner, select your avatar.
-1. Select **Edit profile**.
-1. On the left sidebar, select **Password**.
-1. In the **Current password** text box, enter your current password.
-1. In the **New password** and **Password confirmation** text box, enter your new password.
-1. Select **Save password**.
-
-If you don't know your current password, select the **I forgot my password** link. A password reset email is sent to the account's **primary** email address.
-
## Change your username
Your username has a unique [namespace](../namespace/index.md),
@@ -223,12 +210,12 @@ To set the busy status indicator, either:
- Set it directly:
1. On the top bar, in the top-right corner, select your avatar.
1. Select **Set status** or, if you have already set a status, **Edit status**.
- 1. Select the **Busy** checkbox.
+ 1. Select the **Set yourself as busy** checkbox.
- Set it on your profile:
1. On the top bar, in the top-right corner, select your avatar.
1. Select **Edit profile**.
- 1. In the **Current status** section, select the **Busy** checkbox.
+ 1. In the **Current status** section, select the **Set yourself as busy** checkbox.
The busy status is displayed in the user interface.
@@ -330,6 +317,9 @@ GitLab tracks user contribution activity. You can follow or unfollow other users
- The small popover that appears when you hover over a user's name ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76050)
in GitLab 15.0).
+In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/360755),
+the maximum number of users you can follow is 300.
+
To view a user's activity in a top-level Activity view:
1. From a user's profile, select **Follow**.
@@ -472,7 +462,10 @@ Without the `config.extend_remember_period` flag, you would be forced to sign in
- [Create users](account/create_accounts.md)
- [Sign in to your GitLab account](../../topics/authentication/index.md)
-- [Receive emails for sign-ins from unknown IP addresses or devices](unknown_sign_in_notification.md)
+- [Change your password](user_passwords.md)
+- Receive emails for:
+ - [Sign-ins from unknown IP addresses or devices](notifications.md#notifications-for-unknown-sign-ins)
+ - [Attempted sign-ins using wrong two-factor authentication codes](notifications.md#notifications-for-attempted-sign-in-using-wrong-two-factor-authentication-codes)
- Manage applications that can [use GitLab as an OAuth provider](../../integration/oauth_provider.md#introduction-to-oauth)
- Manage [personal access tokens](personal_access_tokens.md) to access your account via API and authorized applications
- Manage [SSH keys](../ssh.md) to access your account via SSH
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 1b737f14f68..7942ee38be9 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -2,7 +2,7 @@
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/notifications.html'
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Notification emails **(FREE)**
@@ -286,6 +286,36 @@ By default, you don't receive notifications for issues, merge requests, or epics
To always receive notifications on your own issues, merge requests, and so on, turn on
[notifications about your own activity](#global-notification-settings).
+## Notifications for unknown sign-ins
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27211) in GitLab 13.0.
+
+NOTE:
+This feature is enabled by default for self-managed instances. Administrators may disable this feature
+through the [Sign-in restrictions](../admin_area/settings/sign_in_restrictions.md#email-notification-for-unknown-sign-ins) section of the UI.
+The feature is always enabled on GitLab.com.
+
+When a user successfully signs in from a previously unknown IP address or device,
+GitLab notifies the user by email. In this way, GitLab proactively alerts users of potentially
+malicious or unauthorized sign-ins.
+
+GitLab uses several methods to identify a known sign-in. All methods must fail for a notification email to be sent.
+
+- Last sign-in IP: The current sign-in IP address is checked against the last sign-in
+ IP address.
+- Current active sessions: If the user has an existing active session from the
+ same IP address. See [Active Sessions](active_sessions.md).
+- Cookie: After successful sign in, an encrypted cookie is stored in the browser.
+ This cookie is set to expire 14 days after the last successful sign in.
+
+## Notifications for attempted sign-in using wrong two-factor authentication codes
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/374740) in GitLab 15.5.
+
+GitLab sends you an email notification if it detects an attempt to sign in to your account using a wrong two-factor
+authentication (2FA) code. This can help you detect that a bad actor gained access to your username and password, and is trying
+to brute force 2FA.
+
## Notifications on designs
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217095) in GitLab 13.6.
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 2fd18f583a4..c7fe68c0609 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -2,7 +2,7 @@
type: concepts, howto
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Personal access tokens **(FREE)**
@@ -45,6 +45,9 @@ For examples of how you can use a personal access token to authenticate with the
Alternately, GitLab administrators can use the API to create [impersonation tokens](../../api/index.md#impersonation-tokens).
Use impersonation tokens to automate authentication as a specific user.
+NOTE:
+Personal access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../development/fips_compliance.md) is enabled.
+
## Create a personal access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) in GitLab 15.3, default expiration of 30 days is populated in the UI.
@@ -102,14 +105,14 @@ A personal access token can perform actions based on the assigned scopes.
| Scope | Access |
|--------------------|--------|
-| `api` | Read-write for the complete API, including all groups and projects, the Container Registry, and the Package Registry. |
-| `read_user` | Read-only for endpoints under `/users`. Essentially, access to any of the `GET` requests in the [Users API](../../api/users.md). |
-| `read_api` | Read-only for the complete API, including all groups and projects, the Container Registry, and the Package Registry. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28944) in GitLab 12.10.) |
-| `read_repository` | Read-only (pull) for the repository through `git clone`. |
-| `write_repository` | Read-write (pull, push) for the repository through `git clone`. |
-| `read_registry` | Read-only (pull) for [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. Available only when the Container Registry is enabled. |
-| `write_registry` | Read-write (push) for [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. Available only when the Container Registry is enabled. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28958) in GitLab 12.10.) |
-| `sudo` | API actions as any user in the system (if the authenticated user is an administrator). |
+| `api` | Grants complete read/write access to the API, including all groups and projects, the container registry, and the package registry. |
+| `read_user` | Grants read-only access to the authenticated user's profile through the `/user` API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under [`/users`](../../api/users.md). |
+| `read_api` | Grants read access to the API, including all groups and projects, the container registry, and the package registry. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28944) in GitLab 12.10.) |
+| `read_repository` | Grants read-only access to repositories on private projects using Git-over-HTTP or the Repository Files API. |
+| `write_repository` | Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API). |
+| `read_registry` | Grants read-only (pull) access to a [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. Available only when the Container Registry is enabled. |
+| `write_registry` | Grants read-write (push) access to a [Container Registry](../packages/container_registry/index.md) images if a project is private and authorization is required. Available only when the Container Registry is enabled. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28958) in GitLab 12.10.) |
+| `sudo` | Grants permission to perform API actions as any user in the system, when authenticated as an administrator. |
## When personal access tokens expire
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index 31ab802a8b8..6849918886a 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---
@@ -51,7 +51,7 @@ See the epic for:
- A list of known issues.
- Our planned direction and next steps.
-If you find an issue that isn't listed, please leave a comment on the epic or create a
+If you find an issue that isn't listed, leave a comment on the epic or create a
new issue.
Dark mode is available as a navigation theme, for MVC and compatibility reasons.
@@ -201,7 +201,7 @@ To set your time preference:
NOTE:
This feature is experimental, and choosing absolute times might break certain layouts.
-Please open an issue if you notice that using absolute times breaks a layout.
+Open an issue if you notice that using absolute times breaks a layout.
## Integrations
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index 37bde3ce846..3bdcd36a34e 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -1,32 +1,11 @@
---
-stage: Manage
-group: Authentication and Authorization
-info: 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: 'notifications.md'
+remove_date: '2023-01-15'
---
-# Email notification for unknown sign-ins **(FREE)**
+This document was moved to [another location](notifications.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27211) in GitLab 13.0.
-
-NOTE:
-This feature is enabled by default for self-managed instances. Administrators may disable this feature
-through the [Sign-in restrictions](../admin_area/settings/sign_in_restrictions.md#email-notification-for-unknown-sign-ins) section of the UI.
-The feature is always enabled on GitLab.com.
-
-When a user successfully signs in from a previously unknown IP address or device,
-GitLab notifies the user by email. In this way, GitLab proactively alerts users of potentially
-malicious or unauthorized sign-ins.
-
-There are several methods used to identify a known sign-in. All methods must fail
-for a notification email to be sent.
-
-- Last sign-in IP: The current sign-in IP address is checked against the last sign-in
- IP address.
-- Current active sessions: If the user has an existing active session from the
- same IP address. See [Active Sessions](active_sessions.md).
-- Cookie: After successful sign in, an encrypted cookie is stored in the browser.
- This cookie is set to expire 14 days after the last successful sign in.
-
-## Example email
-
-![Unknown sign in email](img/unknown_sign_in_email_v14_0.png)
+<!-- This redirect file can be deleted after <2023-01-15>. -->
+<!-- Redirects that point to other docs in the same project expire in three months. -->
+<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/profile/user_passwords.md b/doc/user/profile/user_passwords.md
new file mode 100644
index 00000000000..04d149c9709
--- /dev/null
+++ b/doc/user/profile/user_passwords.md
@@ -0,0 +1,76 @@
+---
+stage: Manage
+group: Authentication and Authorization
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# User passwords **(FREE)**
+
+If you use a password to sign in to GitLab, a strong password is very important. A weak or guessable password makes it
+easier for unauthorized people to log into your account.
+
+Some organizations require you to meet certain requirements when choosing a password.
+
+Improve the security of your account with [two-factor authentication](account/two_factor_authentication.md)
+
+## Choose your password
+
+You can choose a password when you [create a user account](account/create_accounts.md).
+
+If you register your account using an external authentication and
+authorization provider, you do not need to choose a password. GitLab
+[sets a random, unique, and secure password for you](../../security/passwords_for_integrated_authentication_methods.md).
+
+## Change your password
+
+You can change your password. GitLab enforces [password requirements](#password-requirements) when you choose your new
+password.
+
+1. On the top bar, in the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. On the left sidebar, select **Password**.
+1. In the **Current password** text box, enter your current password.
+1. In the **New password** and **Password confirmation** text box, enter your new password.
+1. Select **Save password**.
+
+If you don't know your current password, select the **I forgot my password** link. A password reset email is sent to the
+account's **primary** email address.
+
+## Password requirements
+
+Your passwords must meet a set of requirements when:
+
+- You choose a password during registration.
+- You choose a new password using the forgotten password reset flow.
+- You change your password proactively.
+- You change your password after it expires.
+- An an administrator creates your account.
+- An administrator updates your account.
+
+By default GitLab enforces the following password requirements:
+
+- Minimum and maximum password lengths. For example,
+ see [the settings for GitLab.com](../gitlab_com/index.md#password-requirements).
+- Disallowing [weak passwords](#block-weak-passwords).
+
+Self-managed installations can configure the following additional password requirements:
+
+- [Password minimum and maximum length limits](../../security/password_length_limits.md).
+- [Password complexity requirements](../admin_area/settings/sign_up_restrictions.md#password-complexity-requirements).
+
+## Block weak passwords
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23610) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `block_weak_passwords`, weak passwords aren't accepted. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default blocking weak passwords is not available. To make it available, ask an administrator
+to [enable the feature flag](../../administration/feature_flags.md) named `block_weak_passwords`. On GitLab.com, this
+feature is available but can be configured by GitLab.com administrators only.
+
+GitLab disallows weak passwords. Your password is considered weak when it:
+
+- Matches one of 4500+ known, breached passwords.
+- Contains part of your name, username, or email address.
+- Contains a predictable word (for example, `gitlab` or `devops`).
+
+Weak passwords are rejected with the error message: **Password must not contain commonly used combinations of words and letters**.
diff --git a/doc/user/project/autocomplete_characters.md b/doc/user/project/autocomplete_characters.md
index aa8c21fc781..e0c1ceb7ec5 100644
--- a/doc/user/project/autocomplete_characters.md
+++ b/doc/user/project/autocomplete_characters.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
description: "Autocomplete characters in Markdown fields."
---
diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md
index cf0ff4ed8b9..d43af92e9c6 100644
--- a/doc/user/project/badges.md
+++ b/doc/user/project/badges.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Badges **(FREE)**
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index aac704e2cdd..3e6a9acc304 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Canary Deployments **(FREE)**
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index d9339291328..b3d381c3148 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connect EKS clusters through cluster certificates (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md
index d7137c18a03..363197107f9 100644
--- a/doc/user/project/clusters/add_existing_cluster.md
+++ b/doc/user/project/clusters/add_existing_cluster.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connect existing clusters through cluster certificates (DEPRECATED) **(FREE)**
@@ -244,8 +244,8 @@ You may also experience this error if your certificate is not valid. To check th
subject alternative names contain the correct domain for your cluster's API, run this command:
```shell
-echo | openssl s_client -showcerts -connect kubernetes.example.com:443 2>/dev/null |
+echo | openssl s_client -showcerts -connect kubernetes.example.com:443 -servername kubernetes.example.com 2>/dev/null |
openssl x509 -inform pem -noout -text
```
-The `-connect` argument expects a `host:port` combination. For example, `https://kubernetes.example.com` would be `kubernetes.example.com:443`.
+The `-connect` argument expects a `host:port` combination. For example, `https://kubernetes.example.com` would be `kubernetes.example.com:443`. The `-servername` argument expects a domain without any URI, for example `kubernetes.example.com`.
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index 6ed02838e9b..7b010bf4478 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Connect GKE clusters through cluster certificates (DEPRECATED) **(FREE)**
@@ -66,7 +66,7 @@ cluster certificates:
- **Main menu > Admin > Kubernetes** page, for an instance-level cluster.
1. Select **Integrate with a cluster certificate**.
1. Under the **Create new cluster** tab, select **Google GKE**.
-1. Connect your Google account if you haven't done already by clicking the
+1. Connect your Google account if you haven't done already by selecting the
**Sign in with Google** button.
1. Choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 2fba00ae940..523a6fd65f6 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Add a cluster using cluster certificates (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/cluster_access.md b/doc/user/project/clusters/cluster_access.md
index 43ceb3673d8..c9b3596d92f 100644
--- a/doc/user/project/clusters/cluster_access.md
+++ b/doc/user/project/clusters/cluster_access.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Access controls with cluster certificates (RBAC or ABAC) (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md
index 0a574b9afe2..e8acf5a2727 100644
--- a/doc/user/project/clusters/deploy_to_cluster.md
+++ b/doc/user/project/clusters/deploy_to_cluster.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy to a Kubernetes cluster with cluster certificates (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/gitlab_managed_clusters.md b/doc/user/project/clusters/gitlab_managed_clusters.md
index 3b85d29fb4a..b2a4bd85de4 100644
--- a/doc/user/project/clusters/gitlab_managed_clusters.md
+++ b/doc/user/project/clusters/gitlab_managed_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab-managed clusters (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 940b58103f5..94513fc7124 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index bd87ab1024d..51e4f1c2db2 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -1,8 +1,8 @@
---
stage: Monitor
group: Respond
-info: 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
-remove_date: '2022-18-10'
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+remove_date: '2022-10-18'
redirect_to: '../../clusters/agent/index.md'
---
diff --git a/doc/user/project/clusters/multiple_kubernetes_clusters.md b/doc/user/project/clusters/multiple_kubernetes_clusters.md
index 149df5248c8..95d3bf6e121 100644
--- a/doc/user/project/clusters/multiple_kubernetes_clusters.md
+++ b/doc/user/project/clusters/multiple_kubernetes_clusters.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Multiple clusters per project with cluster certificates (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 94b5f6f52b9..c4ca82f7db4 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Runbooks **(FREE)**
@@ -153,7 +153,7 @@ the components outlined above and the pre-loaded demo runbook.
```
1. After JupyterHub has been installed successfully, open the **Jupyter Hostname**
- in your browser. Select **Sign in with GitLab** button to log in to
+ in your browser. Select **Sign in with GitLab** button to sign in to
JupyterHub and start the server. Authentication is enabled for any user of the
GitLab instance with OAuth2. This button redirects you to a page at GitLab
requesting authorization for JupyterHub to use your GitLab account.
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
deleted file mode 100644
index 93bc41dc24c..00000000000
--- a/doc/user/project/clusters/serverless/aws.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-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
-remove_date: '2022-08-22'
-redirect_to: '../../../../update/removals.md#gitlab-serverless'
----
-
-# Deploying AWS Lambda function using GitLab CI/CD (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/6) in GitLab 14.3 and [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86267) in GitLab 15.0.
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
deleted file mode 100644
index 432caa8476f..00000000000
--- a/doc/user/project/clusters/serverless/index.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-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
-remove_date: '2022-08-22'
-redirect_to: '../../../../update/removals.md#gitlab-serverless'
----
-
-# Serverless (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/6) in GitLab 14.3 and [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86267) in GitLab 15.0.
diff --git a/doc/user/project/code_intelligence.md b/doc/user/project/code_intelligence.md
index 860ebfbed14..d5f9c225cde 100644
--- a/doc/user/project/code_intelligence.md
+++ b/doc/user/project/code_intelligence.md
@@ -1,7 +1,7 @@
---
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index fd2df96308c..aeeacd495a7 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code Owners **(PREMIUM)**
@@ -335,8 +335,10 @@ If you update the `CODEOWNERS` file, close the merge request and create a new on
### User not shown as possible approver
-A user might not show as an approver on the Code Owner merge request approval rules.
+A user might not show as an approver on the Code Owner merge request approval rules
+if any of these conditions are true:
-This result occurs when a rule prevents the specific user from approving the merge request.
-Check the project
-[merge request approval setting](merge_requests/approvals/settings.md#edit-merge-request-approval-settings).
+- A rule prevents the specific user from approving the merge request.
+ Check the project [merge request approval](merge_requests/approvals/settings.md#edit-merge-request-approval-settings) settings.
+- A Code Owner group has a visibility of **private**, and the current user is not a
+ member of the Code Owner group.
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 63010610605..a68f9550ebf 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: howto, reference
---
@@ -118,7 +118,7 @@ To display the deploy boards for a specific [environment](../../ci/environments/
NOTE:
Matching based on the Kubernetes `app` label was removed in
[GitLab 12.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14020).
- To migrate, please apply the required annotations (see above) and
+ To migrate, apply the required annotations (see above) and
re-deploy your application. If you are using Auto DevOps, this will
be done automatically and no action is necessary.
@@ -130,7 +130,7 @@ Once all of the above are set up and the pipeline has run at least once,
navigate to the environments page under **Deployments > Environments**.
Deploy boards are visible by default. You can explicitly select
-the triangle next to their respective environment name in order to hide them.
+the triangle next to their respective environment name to hide them.
### Example manifest file
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index f424ec529b2..58f7d3198b2 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy keys **(FREE)**
@@ -156,3 +156,38 @@ There are a few scenarios where a deploy key will fail to push to a
All deploy keys are associated to an account. Since the permissions for an account can change, this might lead to scenarios where a deploy key that was working is suddenly unable to push to a protected branch.
We recommend you create a service account, and associate a deploy key to the service account, for projects using deploy keys.
+
+#### Identify deploy keys associated with non-member and blocked users
+
+If you need to find the keys that belong to a non-member or blocked user,
+you can use [the Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session) to identify unusable deploy keys using a script similar to the following:
+
+```ruby
+ghost_user_id = User.ghost.id
+
+DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
+ project = deploy_key_mapping.project
+ deploy_key = deploy_key_mapping.deploy_key
+ user = deploy_key.user
+
+ access_checker = Gitlab::DeployKeyAccess.new(deploy_key, container: project)
+
+ # can_push_for_ref? tests if deploy_key can push to default branch, which is likely to be protected
+ can_push = access_checker.can_do_action?(:push_code)
+ can_push_to_default = access_checker.can_push_for_ref?(project.repository.root_ref)
+
+ next if access_checker.allowed? && can_push && can_push_to_default
+
+ if user.nil? || user.id == ghost_user_id
+ username = 'none'
+ state = '-'
+ else
+ username = user.username
+ user_state = user.state
+ end
+
+ puts "Deploy key: #{deploy_key.id}, Project: #{project.full_path}, Can push?: " + (can_push ? 'YES' : 'NO') +
+ ", Can push to default branch #{project.repository.root_ref}?: " + (can_push_to_default ? 'YES' : 'NO') +
+ ", User: #{username}, User state: #{user_state}"
+end
+```
diff --git a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png b/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png
deleted file mode 100644
index 4ab6a45aee1..00000000000
--- a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 04a2eeacffb..aab72d4859e 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Deploy tokens **(FREE)**
@@ -11,217 +11,222 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29280) from **Settings > CI/CD** to **Settings > Repository** in GitLab 12.10.1.
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) package registry scopes in GitLab 13.0.
-Deploy tokens allow you to download (`git clone`) or push and pull packages and
-container registry images of a project without having a user and a password.
+You can use a deploy token to enable authentication of deployment tasks, independent of a user
+account. In most cases you use a deploy token from an external host, like a build server or CI/CD
+server.
-Deploy tokens can be managed only by users with the Maintainer role.
+With a deploy token, automated tasks can:
-Deploy tokens can't be used with the GitLab public API. However, you can use deploy tokens with some
-endpoints, such as those from the Package Registry. For details, see
-[Authenticate with the registry](../../packages/package_registry/index.md#authenticate-with-the-registry).
+- Clone Git repositories.
+- Pull from and push to a GitLab container registry.
+- Pull from and push to a GitLab package registry.
-Deploy tokens are tied to the project and stay enabled even when the user who created the token is removed from the project.
+A deploy token is a pair of values:
-If you have a key pair, you might want to use [deploy keys](../../project/deploy_keys/index.md)
-instead.
+- **username**: `username` in the HTTP authentication framework. The default username format is
+ `gitlab+deploy-token-{n}`. You can specify a custom username when you create the deploy token.
+- **token**: `password` in the HTTP authentication framework.
-## Creating a Deploy token
+You can use a deploy token for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)
+to the following endpoints:
-You can create as many deploy tokens as you need from the settings of your
-project. Alternatively, you can also create [group-scoped deploy tokens](#group-deploy-token).
+- GitLab Package Registry public API.
+- [Git commands](https://git-scm.com/docs/gitcredentials#_description).
-1. Sign in to your GitLab account.
-1. On the top bar, select **Main menu > Projects** or **Main menu > Groups** to find your project or group.
-1. On the left sidebar, select **Settings > Repository**.
-1. Expand **Deploy tokens**.
-1. Choose a name, and optionally, an expiration date and username for the token.
-1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token).
-1. Select **Create deploy token**.
+You can create deploy tokens at either the project or group level:
-Save the deploy token somewhere safe. After you leave or refresh
-the page, **you can't access it again**.
+- **Project deploy token**: Permissions apply only to the project.
+- **Group deploy token**: Permissions apply to all projects in the group.
-![Personal access tokens page](img/deploy_tokens_ui.png)
+By default, a deploy token does not expire. You can optionally set an expiry date when you create
+it. Expiry occurs at midnight UTC on that date.
-## Deploy token expiration
+## Scope
-Deploy tokens expire at midnight UTC on the date you define.
+A deploy token's scope determines the actions it can perform.
-## Revoking a deploy token
+| Scope | Description |
+|--------------------------|--------------------------------------------------------------------------------------------------------------|
+| `read_repository` | Read-only access to the repository using `git clone`. |
+| `read_registry` | Read-only access to the images in the project's [container registry](../../packages/container_registry/index.md). |
+| `write_registry` | Write access (push) to the project's [container registry](../../packages/container_registry/index.md). |
+| `read_package_registry` | Read-only access to the project's package registry. |
+| `write_package_registry` | Write access to the project's package registry. |
-To revoke a deploy token:
+## GitLab deploy token
-1. On the top bar, select **Main menu > Projects** or **Main menu > Groups** to find your project or group.
-1. On the left sidebar, select **Settings > Repository**.
-1. Expand **Deploy tokens**.
-1. In the **Active Deploy Tokens** section, by the token you want to revoke, select **Revoke**.
+> - Support for `gitlab-deploy-token` at the group level [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) in GitLab 15.1 [with a flag](../../../administration/feature_flags.md) named `ci_variable_for_group_gitlab_deploy_token`. Enabled by default.
+> - [Feature flag `ci_variable_for_group_gitlab_deploy_token`](https://gitlab.com/gitlab-org/gitlab/-/issues/363621) removed in GitLab 15.4.
-## Limiting scopes of a deploy token
+A GitLab deploy token is a special type of deploy token. If you create a deploy token named
+`gitlab-deploy-token`, the deploy token is automatically exposed to the CI/CD jobs as variables, for
+use in a CI/CD pipeline:
-Deploy tokens can be created with different scopes that allow various actions
-that a given token can perform. The available scopes are depicted in the
-following table along with GitLab version it was introduced in:
+- `CI_DEPLOY_USER`: Username
+- `CI_DEPLOY_PASSWORD`: Token
-| Scope | Description | Introduced in GitLab Version |
-|--------------------------|-------------|------------------------------|
-| `read_repository` | Allows read-access to the repository through `git clone` | -- |
-| `read_registry` | Allows read-access 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). | 12.10 |
-| `read_package_registry` | Allows read access to the package registry. | 13.0 |
-| `write_package_registry` | Allows write access to the package registry. | 13.0 |
+For example, to use a GitLab token to log in to your GitLab container registry:
-## Deploy token custom username
+```shell
+docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+```
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29639) in GitLab 12.1.
+NOTE:
+In GitLab 15.0 and earlier, the special handling for the `gitlab-deploy-token` deploy token does not
+work for group deploy tokens. To make a group deploy token available for CI/CD jobs, set the
+`CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD` CI/CD variables in **Settings > CI/CD > Variables** to the
+name and token of the group deploy token.
-The default username format is `gitlab+deploy-token-{n}`. Some tools or
-platforms may not support this format; in this case you can specify a custom
-username to be used when creating the deploy token.
+### GitLab public API
-## Usage
+Deploy tokens can't be used with the GitLab public API. However, you can use deploy tokens with some
+endpoints, such as those from the Package Registry. For more information, see
+[Authenticate with the registry](../../packages/package_registry/index.md#authenticate-with-the-registry).
-### Git clone a repository
+## Create a deploy token
-To download a repository using a deploy token:
+Create a deploy token to automate deployment tasks that can run independently of a user account.
-1. Create a deploy token with `read_repository` as a scope.
-1. Take note of your `username` and `token`.
-1. `git clone` the project using the deploy token:
+Prerequisites:
- ```shell
- git clone https://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
- ```
+- You must have at least the Maintainer role for the project or group.
-Replace `<username>` and `<deploy_token>` with the proper values.
+1. On the top bar, select **Main menu**, and:
+ - For a project deploy token, select **Projects** and find your project.
+ - For a group deploy token, select **Groups** and find your group.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy tokens**.
+1. Complete the fields, and select the desired [scopes](#scope).
+1. Select **Create deploy token**.
-### Read Container Registry images
+Record the deploy token's values. After you leave or refresh the page, **you cannot access it
+again**.
-To read the container registry images, you must:
+## Revoke a deploy token
-1. Create a deploy token with `read_registry` as a scope.
-1. Take note of your `username` and `token`.
-1. Sign in to the GitLab Container Registry using the deploy token:
+Revoke a token when it's no longer required.
-```shell
-docker login -u <username> -p <deploy_token> registry.example.com
-```
+Prerequisites:
-Replace `<username>` and `<deploy_token>` with the proper values. You can now
-pull images from your Container Registry.
+- You must have at least the Maintainer role for the project or group.
-### Push Container Registry images
+To revoke a deploy token:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) in GitLab 12.10.
+1. On the top bar, select **Main menu**, and:
+ - For a project deploy token, select **Projects** and find your project.
+ - For a group deploy token, select **Groups** and find your group.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy tokens**.
+1. In the **Active Deploy Tokens** section, by the token you want to revoke, select **Revoke**.
-To push the container registry images, you must:
+## Clone a repository
-1. Create a deploy token with `write_registry` as a scope.
-1. Take note of your `username` and `token`.
-1. Sign in to the GitLab Container Registry using the deploy token:
+You can use a deploy token to clone a repository.
- ```shell
- docker login -u <username> -p <deploy_token> registry.example.com
- ```
+Prerequisites:
-Replace `<username>` and `<deploy_token>` with the proper values. You can now
-push images to your Container Registry.
+- A deploy token with the `read_repository` scope.
-### Read or pull packages
+Example of using a deploy token to clone a repository:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
+```shell
+git clone https://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
+```
-To pull packages in the GitLab package registry, you must:
+## Pull images from a container registry
-1. Create a deploy token with `read_package_registry` as a scope.
-1. Take note of your `username` and `token`.
-1. For the [package type of your choice](../../packages/index.md), follow the
- authentication instructions for deploy tokens.
+You can use a deploy token to pull images from a container registry.
-Example request publishing a NuGet package using a deploy token:
+Prerequisites:
-```shell
-nuget source Add -Name GitLab -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName deploy-token-username -Password 12345678asdf
+- A deploy token with the `read_registry` scope.
-nuget push mypkg.nupkg -Source GitLab
+Example of using a deploy token to pull images from a container registry:
+
+```shell
+docker login -u <username> -p <deploy_token> registry.example.com
+docker pull $CONTAINER_TEST_IMAGE
```
-### Push or upload packages
+## Push images to a container registry
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
+You can use a deploy token to push images to a container registry.
-To upload packages in the GitLab package registry, you must:
+Prerequisites:
-1. Create a deploy token with `write_package_registry` as a scope.
-1. Take note of your `username` and `token`.
-1. For the [package type of your choice](../../packages/index.md), follow the
- authentication instructions for deploy tokens.
+- A deploy token with the `write_registry` scope.
-### Group deploy token
+Example of using a deploy token to push an image to a container registry:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21765) in GitLab 12.9.
+```shell
+docker login -u <username> -p <deploy_token> registry.example.com
+docker push $CONTAINER_TEST_IMAGE
+```
-A deploy token created at the group level can be used across all projects that
-belong either to the specific group or to one of its subgroups.
+## Pull packages from a package registry
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Group Deploy Tokens](https://youtu.be/8kxTJvaD9ks).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
-The Group deploy tokens UI is now accessible under **Settings > Repository**,
-not **Settings > CI/CD** as indicated in the video.
+You can use a deploy token to pull packages from a package registry.
-To use a group deploy token:
+Prerequisites:
-1. [Create](#creating-a-deploy-token) a deploy token for a group.
-1. Use it the same way you use a project deploy token when
- [cloning a repository](#git-clone-a-repository).
+- A deploy token with the `read_package_registry` scope.
-The scopes applied to a group deploy token (such as `read_repository`)
-apply consistently when cloning the repository of related projects.
+For the [package type of your choice](../../packages/index.md), follow the authentication
+instructions for deploy tokens.
-### Pull images from the Dependency Proxy
+Example of installing a NuGet package from a GitLab registry:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/280586) in GitLab 14.2.
+```shell
+nuget source Add -Name GitLab -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName <username> -Password <deploy_token>
+nuget install mypkg.nupkg
+```
-To pull images from the Dependency Proxy, you must:
+## Push packages to a package repository
-1. Create a group deploy token with both `read_registry` and `write_registry` scopes.
-1. Take note of your `username` and `token`.
-1. Follow the Dependency Proxy [authentication instructions](../../packages/dependency_proxy/index.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0.
-### GitLab deploy token
+You can use a deploy token to push packages to a GitLab package registry.
-> - Support for `gitlab-deploy-token` at the group level [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) in GitLab 15.1 [with a flag](../../../administration/feature_flags.md) named `ci_variable_for_group_gitlab_deploy_token`. Enabled by default.
-> - [Feature flag `ci_variable_for_group_gitlab_deploy_token`](https://gitlab.com/gitlab-org/gitlab/-/issues/363621) removed in GitLab 15.4.
+Prerequisites:
+
+- A deploy token with the `write_package_registry` scope.
-There's a special case when it comes to deploy tokens. If a user creates one
-named `gitlab-deploy-token`, the username and token of the deploy token is
-automatically exposed to the CI/CD jobs as CI/CD variables: `CI_DEPLOY_USER`
-and `CI_DEPLOY_PASSWORD`, respectively.
+For the [package type of your choice](../../packages/index.md), follow the authentication
+instructions for deploy tokens.
-After you create the token, you can sign in to the Container Registry by using
-those variables:
+Example of publishing a NuGet package to a package registry:
```shell
-docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+nuget source Add -Name GitLab -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName <username> -Password <deploy_token>
+nuget push mypkg.nupkg -Source GitLab
```
-NOTE:
-In GitLab 15.0 and earlier, the special handling for the `gitlab-deploy-token` deploy token
-does not work for group deploy tokens. To make the group-level deploy token available
-for CI/CD jobs, the `CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD` CI/CD variables must be
-set in **Settings > CI/CD > Variables** to the name and token of the group deploy token.
+## Pull images from the dependency proxy
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/280586) in GitLab 14.2.
+
+You can use a deploy token to pull images from the dependency proxy.
+
+Prerequisites:
+
+- A deploy token with `read_registry` and `write_registry` scopes.
+
+Follow the dependency proxy [authentication instructions](../../packages/dependency_proxy/index.md).
## Troubleshooting
-### Group deploy tokens and LFS
+### Error: `api error: Repository or object not found:`
-A bug
-[prevents Group Deploy Tokens from cloning LFS objects](https://gitlab.com/gitlab-org/gitlab/-/issues/235398).
-If you receive `404 Not Found` errors and this error,
-use a Project Deploy Token to work around the bug:
+When using a group deploy token to clone from LFS objects, you might get `404 Not Found` responses
+and this error message. This occurs because of a bug, documented in
+[issue 235398](https://gitlab.com/gitlab-org/gitlab/-/issues/235398).
```plaintext
api error: Repository or object not found:
https://<URL-with-token>.git/info/lfs/objects/batch
Check that it exists and that you have proper access to it
```
+
+The workaround is to use a project deploy token.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 4050fa34026..40c36236932 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Description templates **(FREE)**
@@ -192,7 +192,7 @@ Here is an example of a bug report template:
## Example Project
-(If possible, please create an example project here on GitLab.com that exhibits the problematic
+(If possible, create an example project here on GitLab.com that exhibits the problematic
behavior, and link to it here in the bug report.
If you are using an older version of GitLab, this will also determine whether the bug has been fixed
in a more recent version)
@@ -207,7 +207,7 @@ in a more recent version)
## Relevant logs and/or screenshots
-(Paste any relevant logs - please use code blocks (```) to format console output, logs, and code, as
+(Paste any relevant logs - use code blocks (```) to format console output, logs, and code, as
it's very hard to read otherwise.)
## Possible fixes
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index f1b9bde6cd0..6d0d444497e 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# File Locking **(FREE)**
diff --git a/doc/user/project/git_attributes.md b/doc/user/project/git_attributes.md
index f2e4b65e3d4..1feb17b19c8 100644
--- a/doc/user/project/git_attributes.md
+++ b/doc/user/project/git_attributes.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/project/highlighting.md b/doc/user/project/highlighting.md
index 1d62cd00b31..22ff234ac81 100644
--- a/doc/user/project/highlighting.md
+++ b/doc/user/project/highlighting.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index dff5a602e8a..3f1a2dcfe2b 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your project from Bitbucket Cloud to GitLab **(FREE)**
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index b6241dbbdb0..1f34c6d4ad9 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your project from Bitbucket Server **(FREE)**
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
index 2d9f92c38e4..1dc62cbbe35 100644
--- a/doc/user/project/import/clearcase.md
+++ b/doc/user/project/import/clearcase.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating from ClearCase **(FREE)**
diff --git a/doc/user/project/import/cvs.md b/doc/user/project/import/cvs.md
index c150e124ac8..f8bbb2354fe 100644
--- a/doc/user/project/import/cvs.md
+++ b/doc/user/project/import/cvs.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating from CVS **(FREE)**
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 3458c7fe4a7..f6395fd9234 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your project from FogBugz to GitLab **(FREE)**
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index db55330f806..46e6b6d377d 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your project from Gitea to GitLab **(FREE)**
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index c04f734e8bb..03f6fd20b0a 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your project from GitHub to GitLab **(FREE)**
@@ -118,6 +118,23 @@ If you are not using the GitHub integration, you can still perform an authorizat
To use a newer personal access token in imports after previously performing these steps, sign out of
your GitLab account and sign in again, or revoke the older personal access token in GitHub.
+### Select additional items to import
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/373705) in GitLab 15.5.
+
+To make imports as fast as possible, the following items aren't imported from GitHub by default:
+
+- Issue and pull request events. For example, _opened_ or _closed_, _renamed_, and _labeled_ or _unlabeled_.
+- All comments. In regular import of large repositories some comments might get skipped due to limitation of GitHub API.
+- Markdown attachments from repository comments, release posts, issue descriptions, and pull request descriptions. These can include
+ images, text, or binary attachments. If not imported, links in Markdown to attachments break after you remove the attachments from GitHub.
+
+You can choose to import these items, but this could significantly increase import time. To import these items, select the appropriate fields in the UI:
+
+- **Import issue and pull request events**.
+- **Use alternative comments import method**.
+- **Import Markdown attachments**.
+
### Select which repositories to import
After you have authorized access to your GitHub repositories, you are redirected to the GitHub importer page and
@@ -178,8 +195,15 @@ The following items of a project are imported:
- Milestones.
- Labels.
- Release note descriptions.
-- Release note attachments. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15620) in GitLab 15.4 with `github_importer_attachments_import`
- [feature flag](../../../administration/feature_flags.md) disabled by default.
+- Attachments for:
+ - Release notes. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15620) in GitLab 15.4.
+ - Comments and notes. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18052) in GitLab 15.5.
+ - Issue description. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18052) in GitLab 15.5.
+ - Merge Request description. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18052) in GitLab 15.5.
+
+ All attachment imports are disabled by default behind
+ `github_importer_attachments_import` [feature flag](../../../administration/feature_flags.md). From GitLab 15.5, can be imported
+ [as an additional item](#select-additional-items-to-import). The feature flag was removed.
- Pull request review comments.
- Regular issue and pull request comments.
- [Git Large File Storage (LFS) Objects](../../../topics/git/lfs/index.md).
@@ -189,35 +213,32 @@ The following items of a project are imported:
- Diff Notes suggestions ([GitLab.com and GitLab 14.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/340624)).
- Issue events and pull requests events. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7673) in GitLab 15.4 with `github_importer_issue_events_import`
[feature flag](../../../administration/feature_flags.md) disabled by default.
+ From GitLab 15.5, can be imported [as an additional item](#select-additional-items-to-import). The feature flag was removed.
References to pull requests and issues are preserved. Each imported repository maintains visibility level unless that
[visibility level is restricted](../../public_access.md#restrict-use-of-public-or-internal-projects), in which case it
defaults to the default project visibility.
+### Branch protection rules
+
+Supported GitHub branch protection rules are mapped to GitLab branch protection rules or project-wide GitLab settings when they are imported:
+
+- GitHub rule **Require conversation resolution before merging** for the project's default branch is mapped to the [**All threads must be resolved** GitLab setting](../../discussions/index.md#prevent-merge-unless-all-threads-are-resolved). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371110) in GitLab 15.5.
+- GitHub rule **Require a pull request before merging** is mapped to the **No one** option in the **Allowed to push** list of the branch protection rule. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/370951) in GitLab 15.5.
+- GitHub rule **Require signed commits** for the project's default branch is mapped to the **Reject unsigned commits** GitLab setting. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/370949) in GitLab 15.5.
+- Support for GitHub rule **Require status checks to pass before merging** was proposed in issue [370948](https://gitlab.com/gitlab-org/gitlab/-/issues/370948). However, this rule cannot be translated during project import into GitLab due to technical difficulties.
+You can still create [status checks](../merge_requests/status_checks.md) in GitLab yourself.
+
## Alternative way to import notes and diff notes
When GitHub Importer runs on extremely large projects not all notes & diff notes can be imported due to GitHub API `issues_comments` & `pull_requests_comments` endpoints limitation.
Not all pages can be fetched due to the following error coming from GitHub API: `In order to keep the API fast for everyone, pagination is limited for this resource. Check the rel=last link relation in the Link response header to see how far back you can traverse.`.
-An alternative approach for importing notes and diff notes is available behind a feature flag.
+An [alternative approach](#select-additional-items-to-import) for importing comments is available.
Instead of using `issues_comments` and `pull_requests_comments`, use individual resources `issue_comments` and `pull_request_comments` instead to pull notes from one object at a time.
This allows us to carry over any missing comments, however it increases the number of network requests required to perform the import, which means its execution takes a longer time.
-To use the alternative way of importing notes, the `github_importer_single_endpoint_notes_import` feature flag must be enabled on the group project is being imported into.
-
-Start a [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
-
-```ruby
-group = Group.find_by_full_path('my/group/fullpath')
-
-# Enable
-Feature.enable(:github_importer_single_endpoint_notes_import, group)
-
-# Disable
-Feature.disable(:github_importer_single_endpoint_notes_import, group)
-```
-
## Reduce GitHub API request objects per page
Some GitHub API endpoints may return a 500 or 502 error for project imports from large repositories.
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
index 8d30a9c7f52..795cb964423 100644
--- a/doc/user/project/import/gitlab_com.md
+++ b/doc/user/project/import/gitlab_com.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import a project from GitLab.com to your private GitLab instance **(FREE)**
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 72d533efd1b..1b5a658d209 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrate projects to a GitLab instance **(FREE)**
diff --git a/doc/user/project/import/jira.md b/doc/user/project/import/jira.md
index 8fb495cd0db..c8b717d0421 100644
--- a/doc/user/project/import/jira.md
+++ b/doc/user/project/import/jira.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import your Jira project issues to GitLab **(FREE)**
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index f04048980e7..ea26613639d 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import multiple repositories by uploading a manifest file **(FREE)**
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab allows you to import all the required Git repositories
based on a manifest file like the one used by the
[Android repository](https://android.googlesource.com/platform/manifest/+/2d6f081a3b05d8ef7a2b1b52b0d536b2b74feab4/default.xml).
-This feature can be very handy when you need to import a project with many
+Use the manifest to import a project with many
repositories like the Android Open Source Project (AOSP).
## Requirements
diff --git a/doc/user/project/import/perforce.md b/doc/user/project/import/perforce.md
index aa256e07b30..ca50a32836e 100644
--- a/doc/user/project/import/perforce.md
+++ b/doc/user/project/import/perforce.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrating from Perforce Helix **(FREE)**
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index 96b38b49960..49f12ca2ba6 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import Phabricator tasks into a GitLab project **(FREE SELF)**
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index d64bea2bb41..d6f4f862b95 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Import project from repository by URL **(FREE)**
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index d6bcb0a2018..1687d621e2e 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -2,7 +2,7 @@
type: howto
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Migrate from Subversion to GitLab **(FREE)**
diff --git a/doc/user/project/import/tfvc.md b/doc/user/project/import/tfvc.md
index 910be690d0b..3625355340b 100644
--- a/doc/user/project/import/tfvc.md
+++ b/doc/user/project/import/tfvc.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts
---
@@ -9,7 +9,7 @@ type: concepts
Team Foundation Server (TFS), renamed [Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/)
in 2019, is a set of tools developed by Microsoft which also includes
-[Team Foundation Version Control](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/what-is-tfvc?view=azure-devops)
+[Team Foundation Version Control](https://learn.microsoft.com/en-us/azure/devops/repos/tfvc/what-is-tfvc?view=azure-devops)
(TFVC), a centralized version control system similar to Git.
In this document, we focus on the TFVC to Git migration.
@@ -28,7 +28,7 @@ The main differences between TFVC and Git are:
For more information, see:
-- Microsoft's [comparison of Git and TFVC](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/comparison-git-tfvc?view=azure-devops).
+- Microsoft's [comparison of Git and TFVC](https://learn.microsoft.com/en-us/azure/devops/repos/tfvc/comparison-git-tfvc?view=azure-devops).
- The Wikipedia [comparison of version control software](https://en.wikipedia.org/wiki/Comparison_of_version_control_software).
## Why migrate
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index e4ae0c4b29b..78a6e8d565f 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Organize work with projects **(FREE)**
diff --git a/doc/user/project/insights/img/project_insights.png b/doc/user/project/insights/img/project_insights.png
deleted file mode 100644
index 83674c94110..00000000000
--- a/doc/user/project/insights/img/project_insights.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 81293fb1645..2874bf98736 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -1,64 +1,68 @@
---
-stage: Manage
+stage: Plan
group: Optimize
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Insights **(ULTIMATE)**
+# Insights for projects **(ULTIMATE)**
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 12.0.
+Configure project insights to explore data such as:
-Configure the Insights that matter for your projects to explore data such as
-triage hygiene, issues created/closed per a given period, average time for merge
-requests to be merged and much more.
+- Issues created and closed during a specified period.
+- Average time for merge requests to be merged.
+- Triage hygiene.
-![Insights example bar chart](img/project_insights.png)
+Insights are also available for [groups](../../group/insights/index.md).
-NOTE:
-This feature is [also available at the group level](../../group/insights/index.md).
+## View project insights
-## View your project's Insights
+Prerequisites:
-You can access your project's Insights by clicking the **Analytics > Insights**
-link in the left sidebar.
+- You must have:
+ - Access to a project to view information about its merge requests and issues.
+ - Permission to view confidential merge requests and issues in the project.
-## Configure your Insights
+To view project insights:
-Insights are configured using a YAML file called `.gitlab/insights.yml` within
-a project. That file is used in the project's Insights page.
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Analytics > Insights**.
+1. To view a report, select the **Select report** dropdown list.
-See [Writing your `.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) below
-for details about the content of this file.
+## Configure project insights
-NOTE:
-After the configuration file is created, you can also
-[use it for your project's group](../../group/insights/index.md#configure-your-insights).
+Prerequisites:
-NOTE:
-If the project doesn't have any configuration file, it attempts to use
-the group configuration if possible. If the group doesn't have any
-configuration, the default configuration is used.
+- Depending on your project configuration, you must have at least the Developer role.
-## Permissions
+Project insights are configured with the [`.gitlab/insights.yml`](#insights-configuration-file) file in the project. If a project doesn't have a configuration file, it uses the [group configuration](../../group/insights/index.md#configure-group-insights).
-If you have access to view a project, then you have access to view their
-Insights.
+The `.gitlab/insights.yml` file is a YAML file where you define:
-NOTE:
-Issues or merge requests that you don't have access to (because you don't have
-access to the project they belong to, or because they are confidential) are
-filtered out of the Insights charts.
+- The structure and order of charts in a report.
+- The style of charts displayed in the report of your project or group.
+
+To configure project insights, either:
+
+- Create a `.gitlab/insights.yml` file locally in the root directory of your project, and push your changes.
+- Create a `.gitlab/insights.yml` file in the UI:
+ 1. On the top bar, select **Main menu > Projects** and find your project.
+ 1. Above the file list, select the branch you want to commit to, select the plus icon, then select **New file**.
+ 1. In the **File name** text box, enter `.gitlab/insights.yml`.
+ 1. In the large text box, update the file contents.
+ 1. Select **Commit changes**.
-You may also consult the [group permissions table](../../permissions.md#group-members-permissions).
+After you create the configuration file, you can also
+[use it for the project's group](../../group/insights/index.md#configure-group-insights).
-## Writing your `.gitlab/insights.yml`
+## Insights configuration file
-The `.gitlab/insights.yml` file defines the structure and order of the Insights
-charts displayed in each Insights page of your project or group.
+In the `.gitlab/insights.yml` file:
-Each page has a unique key and a collection of charts to fetch and display.
+- [Configuration parameters](#insights-configuration-parameters) define the chart behavior.
+- Each report has a unique key and a collection of charts to fetch and display.
+- Each chart definition is made up of a hash composed of key-value pairs.
-For example, here's a single definition for Insights that displays one page with one chart:
+The following example shows a single definition that displays one report with one chart.
```yaml
bugsCharts:
@@ -78,30 +82,9 @@ bugsCharts:
period_limit: 24
```
-Each chart definition is made up of a hash composed of key-value pairs.
+## Insights configuration parameters
-For example, here's single chart definition:
-
-```yaml
-- title: "Monthly bugs created"
- description: "Open bugs created per month"
- type: bar
- query:
- data_source: issuables
- params:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- group_by: month
- period_limit: 24
-```
-
-## Configuration parameters
-
-A chart is defined as a list of parameters that define the chart's behavior.
-
-The following table lists available parameters for charts:
+The following table lists the chart parameters:
| Keyword | Description |
|:---------------------------------------------------|:------------|
@@ -110,15 +93,11 @@ The following table lists available parameters for charts:
| [`type`](#type) | The type of chart: `bar`, `line` or `stacked-bar`. |
| [`query`](#query) | A hash that defines the data source and filtering conditions for the chart. |
-## Parameter details
-
-The following are detailed explanations for parameters used to configure
-Insights charts.
-
### `title`
-`title` is the title of the chart as it displays on the Insights page.
-For example:
+Use `title` to update the chart title. The title displays on the insights report.
+
+**Example:**
```yaml
monthlyBugsCreated:
@@ -127,8 +106,9 @@ monthlyBugsCreated:
### `description`
-The `description` text is displayed above the chart, but below the title. It's used
-to give extra details regarding the chart, for example:
+Use `description` to add a description of the chart. The description displays above the chart, below the title.
+
+**Example:**
```yaml
monthlyBugsCreated:
@@ -138,33 +118,32 @@ monthlyBugsCreated:
### `type`
-`type` is the chart type.
-
-For example:
-
-```yaml
-monthlyBugsCreated:
- title: "Monthly bugs created"
- type: bar
-```
+Use `type` to define the chart type.
-Supported values are:
+**Supported values:**
-| Name | Example |
+| Name | Example: |
| ----- | ------- |
| `bar` | ![Insights example bar chart](img/insights_example_bar_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) |
-NOTE:
-The `dora` data source supports the `bar` and `line` chart types.
+The `dora` data source supports the `bar` and `line` [chart types](#type).
+
+**Example:**
+
+```yaml
+monthlyBugsCreated:
+ title: "Monthly bugs created"
+ type: bar
+```
### `query`
-`query` allows to define the data source and various filtering conditions for the chart.
+Use `query` to define the data source and filtering conditions for the chart.
-Example:
+**Example:**
```yaml
monthlyBugsCreated:
@@ -212,46 +191,46 @@ monthlyBugsCreated:
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 15.3.
-The `data_source` parameter was introduced to allow visualizing data from different data sources.
+Use `data_source` to define the data source that exposes the data.
-Supported values are:
+**Supported values:**
- `issuables`: Exposes merge request or issue data.
-- `dora`: Exposes DORA metrics data.
+- `dora`: Exposes DORA metrics.
-#### `Issuable` query parameters
+#### `issuable` query parameters
##### `query.params.issuable_type`
-Defines the type of "issuable" you want to create a chart for.
+Use `query.params.issuable_type` to define the type of issuable to create a chart for.
-Supported values are:
+**Supported values:**
- `issue`: The chart displays issues' data.
- `merge_request`: The chart displays merge requests' data.
##### `query.params.issuable_state`
-Filter by the current state of the queried "issuable".
+Use `query.params.issuable_state` to filter by the current state of the queried issuable.
By default, the `opened` state filter is applied.
-Supported values are:
+**Supported values:**
-- `opened`: Open issues / merge requests.
-- `closed`: Closed Open issues / merge requests.
-- `locked`: Issues / merge requests that have their discussion locked.
+- `opened`: Open issues or merge requests.
+- `closed`: Closed issues or merge requests.
+- `locked`: Issues or merge requests that have their discussion locked.
- `merged`: Merged merge requests.
-- `all`: Issues / merge requests in all states
+- `all`: Issues or merge requests in all states.
##### `query.params.filter_labels`
-Filter by labels currently applied to the queried "issuable".
+Use `query.params.filter_labels` to filter by labels applied to the queried issuable.
-By default, no labels filter is applied. All the defined labels must be
-currently applied to the "issuable" in order for it to be selected.
+By default, no label filter is applied. All defined labels must
+be applied to the issuable for it to be selected.
-Example:
+**Example:**:
```yaml
monthlyBugsCreated:
@@ -269,12 +248,13 @@ monthlyBugsCreated:
##### `query.params.collection_labels`
-Group "issuable" by the configured labels.
+Use `query.params.collection_labels` to group issuables by the configured labels.
+Grouping is not applied by default.
-By default, no grouping is done. When using this keyword, you need to
-set `type` to either `line` or `stacked-bar`.
+When using this parameter, you must
+set `type` to `line` or `stacked-bar`.
-Example:
+**Example:**
```yaml
weeklyBugsBySeverity:
@@ -296,9 +276,9 @@ weeklyBugsBySeverity:
##### `query.group_by`
-Define the X-axis of your chart.
+Use `query.group_by` to define the X-axis of the chart.
-Supported values are:
+**Supported values:**
- `day`: Group data per day.
- `week`: Group data per week.
@@ -306,11 +286,10 @@ Supported values are:
##### `query.period_limit`
-Define how far "issuables" are queried in the past (using the `query.period_field`).
+Use `query.period_limit` to define how far back in time to query issuables (using the `query.period_field`).
-The unit is related to the `query.group_by` you defined. For instance if you
-defined `query.group_by: 'day'` then `query.period_limit: 365` would mean
-"Gather and display data for the last 365 days".
+The unit is related to the value defined in `query.group_by`. For example, if you
+defined `query.group_by: 'day'`, and `query.period_limit: 365`, the chart displays data from the last 365 days.
By default, default values are applied depending on the `query.group_by`
you defined.
@@ -323,9 +302,9 @@ you defined.
#### `query.period_field`
-Define the timestamp field used to group "issuables".
+Use `query.period_field` to define the timestamp field by which to group issuables.
-Supported values are:
+**Supported values:**
- `created_at` (default): Group data using the `created_at` field.
- `closed_at`: Group data using the `closed_at` field (for issues only).
@@ -345,7 +324,9 @@ you may see `created_at` in place of `merged_at`. `created_at` is used instead.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367248) in GitLab 15.3.
-An example DORA chart definition:
+Use DORA-specific queries with the `dora` data source to create a DORA chart definition.
+
+**Example:**
```yaml
dora:
@@ -377,55 +358,59 @@ dora:
##### `query.metric`
-Defines which DORA metric to query. The available values are:
+Use `query.metric` to define the [DORA metrics](../../../api/dora/metrics.md#the-value-field) to query.
+
+**Supported values:**
- `deployment_frequency` (default)
- `lead_time_for_changes`
- `time_to_restore_service`
- `change_failure_rate`
-The metrics are described on the [DORA API](../../../api/dora/metrics.md#the-value-field) page.
-
##### `query.group_by`
-Define the X-axis of your chart.
+Use `query.group_by` to define the X-axis of your chart.
-Supported values are:
+**Supported values:**
- `day` (default): Group data per day.
- `month`: Group data per month.
##### `query.period_limit`
-Define how far the metrics are queried in the past (default: 15). Maximum lookback period is 180 days or 6 months.
+Use `query.period_limit` to define how far the metrics are queried in the past (default: 15). The maximum period is 180 days or 6 months.
##### `query.environment_tiers`
-An array of environments to include into the calculation (default: production). Available options: `production`, `staging`, `testing`, `development`, `other`.
+Use `query.environment_tiers` to define an array of environments to include the calculation.
-### `projects`
+**Supported values:**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10904) in GitLab 12.4.
+- `production`(default)
+- `staging`
+- `testing`
+- `development`
+- `other`
+
+### `projects`
-You can limit where the "issuables" can be queried from:
+Use `projects` to limit where issuables are queried from:
-- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-your-insights), with `projects`, you can limit the projects to be queried. By default, all projects currently under the group are used.
-- If `.gitlab/insights.yml` is used for a project's insights, specifying any other projects yields no results. By default, the project itself is used.
+- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-group-insights), use `projects` to define the projects from which to query issuables. By default, all projects under the group are used.
+- If `.gitlab/insights.yml` is used for a project's insights, specifying other projects does not yield results. By default, the project is used.
#### `projects.only`
-The `projects.only` option specifies the projects which the "issuables"
-should be queried from.
+Use `projects.only` to specify the projects from which issuables
+are queried.
-Projects listed here are ignored when:
+Projects listed in this parameter are ignored when:
- They don't exist.
- The current user doesn't have sufficient permissions to read them.
-- They are outside of the group.
+- They are outside the group.
-In the following `insights.yml` example, we specify the projects
-the queries are used on. This example is useful when setting
-a group's insights:
+**Example:**
```yaml
monthlyBugsCreated:
@@ -447,7 +432,7 @@ monthlyBugsCreated:
- groupB/project # Projects outside the group will be ignored
```
-## Complete example
+## Complete insights configuration example
```yaml
.projectsOnly: &projectsOnly
diff --git a/doc/user/project/integrations/asana.md b/doc/user/project/integrations/asana.md
index 07b37b5be43..97fb4e7c463 100644
--- a/doc/user/project/integrations/asana.md
+++ b/doc/user/project/integrations/asana.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Asana integration **(FREE)**
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 7b39f6c7162..fceec006a1a 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Atlassian Bamboo integration **(FREE)**
diff --git a/doc/user/project/integrations/bugzilla.md b/doc/user/project/integrations/bugzilla.md
index f058950e0f4..9221250e17f 100644
--- a/doc/user/project/integrations/bugzilla.md
+++ b/doc/user/project/integrations/bugzilla.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Bugzilla service **(FREE)**
diff --git a/doc/user/project/integrations/custom_issue_tracker.md b/doc/user/project/integrations/custom_issue_tracker.md
index c3794aa1a2b..24a2e3d1ebc 100644
--- a/doc/user/project/integrations/custom_issue_tracker.md
+++ b/doc/user/project/integrations/custom_issue_tracker.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Custom issue tracker **(FREE)**
diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md
index dffcc780206..9439e480484 100644
--- a/doc/user/project/integrations/discord_notifications.md
+++ b/doc/user/project/integrations/discord_notifications.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Discord Notifications service **(FREE)**
diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md
index 37d9a86f8fa..ff255cbba51 100644
--- a/doc/user/project/integrations/emails_on_push.md
+++ b/doc/user/project/integrations/emails_on_push.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Enabling emails on push **(FREE)**
diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md
index 45f3653757d..d972509c0f6 100644
--- a/doc/user/project/integrations/ewm.md
+++ b/doc/user/project/integrations/ewm.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# IBM Engineering Workflow Management (EWM) Integration **(FREE)**
diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md
index 4be541d99cb..603ed8b4c05 100644
--- a/doc/user/project/integrations/github.md
+++ b/doc/user/project/integrations/github.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitHub project integration **(PREMIUM)**
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index afc379e7a07..07c99653a0e 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Slack application **(FREE SAAS)**
@@ -22,7 +22,7 @@ The simplest way to enable the GitLab Slack application for your workspace is to
install the [GitLab application](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) from
the [Slack App Directory](https://slack.com/apps).
-Clicking install takes you to the [GitLab Slack application landing page](https://gitlab.com/-/profile/slack/edit)
+Selecting install takes you to the [GitLab Slack application landing page](https://gitlab.com/-/profile/slack/edit)
where you can select a project to enable the GitLab Slack application for.
## Configuration
@@ -89,3 +89,17 @@ project, you would do:
In GitLab 15.0 the Slack app is updated to [Slack's new granular permissions app model](https://medium.com/slack-developer-blog/more-precision-less-restrictions-a3550006f9c3).
There is no change in functionality. A reinstall is not required but recommended.
+
+## Troubleshooting
+
+When you work with the Slack app, the
+[App Home](https://api.slack.com/start/overview#app_home) might not display properly.
+As a workaround, ensure your app is up to date.
+
+To update an existing Slack integration:
+
+1. Go to your [chat settings](https://gitlab.com/-/profile/chat_names).
+1. Next to your project, select **Slack application**.
+1. Select **Reinstall Slack app**.
+
+Alternatively, you can [configure a new Slack integration](https://about.gitlab.com/solutions/slack/).
diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md
index b2586383b43..1be0db223ac 100644
--- a/doc/user/project/integrations/hangouts_chat.md
+++ b/doc/user/project/integrations/hangouts_chat.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Google Chat integration **(FREE)**
diff --git a/doc/user/project/integrations/harbor.md b/doc/user/project/integrations/harbor.md
index 535703ff59e..259b91fc1c7 100644
--- a/doc/user/project/integrations/harbor.md
+++ b/doc/user/project/integrations/harbor.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Harbor container registry integration **(FREE)**
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Use Harbor as the container registry for your GitLab project.
-[Harbor](https://goharbor.io/) is an open source registry that can help you manage artifacts across cloud native compute platforms, like Kubernetes and Docker.
+[Harbor](https://goharbor.io/) is an open source registry that can help you manage artifacts across cloud-native compute platforms, like Kubernetes and Docker.
This integration can help you if you need GitLab CI/CD and a container image repository.
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index 18e827f8df8..77444570499 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Project integrations **(FREE)**
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index 5f7de09cc9d..70f48e4647a 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# irker IRC Gateway **(FREE)**
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 12575e34058..39b89cd87a9 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Mattermost notifications service **(FREE)**
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index 28a5f2eec18..192360f5440 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Mattermost slash commands **(FREE)**
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
index 2e6954390fb..cedb5af144f 100644
--- a/doc/user/project/integrations/microsoft_teams.md
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Microsoft Teams service **(FREE)**
@@ -58,4 +58,4 @@ GitLab to send the notifications:
## Related topics
-- [Setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
+- [Setting up an incoming webhook on Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
diff --git a/doc/user/project/integrations/mock_ci.md b/doc/user/project/integrations/mock_ci.md
index 5cde17dbd83..64ee4521ce4 100644
--- a/doc/user/project/integrations/mock_ci.md
+++ b/doc/user/project/integrations/mock_ci.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Mock CI Service **(FREE)**
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
deleted file mode 100644
index 9625edcd8f9..00000000000
--- a/doc/user/project/integrations/overview.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'index.md'
-remove_date: '2022-07-20'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after 2022-07-20. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/integrations/pipeline_status_emails.md b/doc/user/project/integrations/pipeline_status_emails.md
index c58f5a13613..009bb6662ff 100644
--- a/doc/user/project/integrations/pipeline_status_emails.md
+++ b/doc/user/project/integrations/pipeline_status_emails.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pipeline status emails **(FREE)**
diff --git a/doc/user/project/integrations/pivotal_tracker.md b/doc/user/project/integrations/pivotal_tracker.md
index a0798da21f0..79a00725470 100644
--- a/doc/user/project/integrations/pivotal_tracker.md
+++ b/doc/user/project/integrations/pivotal_tracker.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pivotal Tracker service **(FREE)**
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index c1181169261..9bafa9734e2 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Prometheus integration **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/cloudwatch.md b/doc/user/project/integrations/prometheus_library/cloudwatch.md
index 08488c33ac7..1e9319fa7c7 100644
--- a/doc/user/project/integrations/prometheus_library/cloudwatch.md
+++ b/doc/user/project/integrations/prometheus_library/cloudwatch.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring AWS resources (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md
index ad2cb2681b9..b4533d83acd 100644
--- a/doc/user/project/integrations/prometheus_library/haproxy.md
+++ b/doc/user/project/integrations/prometheus_library/haproxy.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring HAProxy (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index aba14e1f3e9..4ef3a847ef1 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Prometheus Metrics library (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 9a9880a0cb6..0795c110deb 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring Kubernetes (DEPRECATED) **(FREE)**
@@ -35,7 +35,7 @@ integration services must be enabled.
## Configuring Prometheus to monitor for Kubernetes metrics
-Prometheus needs to be deployed into the cluster and configured properly in order to gather Kubernetes metrics. GitLab supports two methods for doing so:
+Prometheus needs to be deployed into the cluster and configured properly to gather Kubernetes metrics. GitLab supports two methods for doing so:
- GitLab [integrates with Kubernetes](../../clusters/index.md), and can [query a Prometheus in a connected cluster](../../../clusters/integrations.md#prometheus-cluster-integration). The in-cluster Prometheus can be configured to automatically collect application metrics from your cluster.
- To configure your own Prometheus server, you can follow the [Prometheus documentation](https://prometheus.io/docs/introduction/overview/).
diff --git a/doc/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index 2825066b8b0..f0a3b25f11a 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring NGINX (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 4c8e648537c..99466a67417 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring NGINX Ingress Controller (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
index e1eee649f0a..e26f93351a1 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -1,7 +1,7 @@
---
stage: Monitor
group: Respond
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Monitoring NGINX Ingress Controller with VTS metrics (DEPRECATED) **(FREE)**
diff --git a/doc/user/project/integrations/pumble.md b/doc/user/project/integrations/pumble.md
index 0eb3a38bb86..f9c0c79be1b 100644
--- a/doc/user/project/integrations/pumble.md
+++ b/doc/user/project/integrations/pumble.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Pumble **(FREE)**
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
index bc1d299dccf..e9752d7ce6c 100644
--- a/doc/user/project/integrations/redmine.md
+++ b/doc/user/project/integrations/redmine.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Redmine service **(FREE)**
diff --git a/doc/user/project/integrations/servicenow.md b/doc/user/project/integrations/servicenow.md
index dc6c2da0d91..d528d1a5547 100644
--- a/doc/user/project/integrations/servicenow.md
+++ b/doc/user/project/integrations/servicenow.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# ServiceNow integration **(FREE)**
diff --git a/doc/user/project/integrations/shimo.md b/doc/user/project/integrations/shimo.md
index ea92b8b3f0b..28cb53f8bf6 100644
--- a/doc/user/project/integrations/shimo.md
+++ b/doc/user/project/integrations/shimo.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Shimo Workspace integration **(FREE)**
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index ae2e57a6d7f..9fe0c76ec4f 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Slack notifications service **(FREE)**
@@ -127,3 +127,21 @@ the GitLab OpenSSL trust store is incorrect. Typical causes are:
- Overriding the trust store with `gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}`.
- Accidentally modifying the default CA bundle `/opt/gitlab/embedded/ssl/certs/cacert.pem`.
+
+### Bulk update to disable the Slack Notification service
+
+To disable notifications for all projects that have Slack integration enabled,
+[start a rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session) and use a script similar to the following:
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+# Grab all projects that have the Slack notifications enabled
+p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN integrations s ON p.id = s.project_id WHERE s.type_new = 'Slack' AND s.active = true")
+
+# Disable the service on each of the projects that were found.
+p.each do |project|
+ project.slack_service.update!(:active, false)
+end
+```
diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md
index 67d6befb5fc..cb698ac0ee0 100644
--- a/doc/user/project/integrations/slack_slash_commands.md
+++ b/doc/user/project/integrations/slack_slash_commands.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Slack slash commands **(FREE SELF)**
diff --git a/doc/user/project/integrations/unify_circuit.md b/doc/user/project/integrations/unify_circuit.md
index 91beefd30ab..c13f642d9e9 100644
--- a/doc/user/project/integrations/unify_circuit.md
+++ b/doc/user/project/integrations/unify_circuit.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Unify Circuit service **(FREE)**
diff --git a/doc/user/project/integrations/webex_teams.md b/doc/user/project/integrations/webex_teams.md
index 0b487e29d26..930ca8e99b8 100644
--- a/doc/user/project/integrations/webex_teams.md
+++ b/doc/user/project/integrations/webex_teams.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Webex Teams service **(FREE)**
@@ -14,7 +14,7 @@ You can configure GitLab to send notifications to a Webex Teams space:
## Create a webhook for the space
1. Go to the [Incoming Webhooks app page](https://apphub.webex.com/applications/incoming-webhooks-cisco-systems-38054-23307).
-1. Select **Connect** and log in to Webex Teams, if required.
+1. Select **Connect**, and sign in to Webex Teams if required.
1. Enter a name for the webhook and select the space to receive the notifications.
1. Select **ADD**.
1. Copy the **Webhook URL**.
diff --git a/doc/user/project/integrations/webhook_events.md b/doc/user/project/integrations/webhook_events.md
index 51049f156b8..c0f0f5a0cd4 100644
--- a/doc/user/project/integrations/webhook_events.md
+++ b/doc/user/project/integrations/webhook_events.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Webhook events **(FREE)**
@@ -1100,6 +1100,7 @@ Payload example:
"object_kind": "pipeline",
"object_attributes":{
"id": 31,
+ "iid": 3,
"ref": "master",
"tag": false,
"sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 1de7440a15d..9fc9d6e2eda 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Webhooks **(FREE)**
@@ -64,54 +64,34 @@ You can configure a webhook for a group or a project.
## Configure your webhook receiver endpoint
-Webhook receivers should be *fast* and *stable*.
-Slow and unstable receivers may be disabled temporarily to ensure system reliability.
-If you are writing your own endpoint (web server) to receive GitLab webhooks, keep in mind the following:
-
-- Your endpoint should send its HTTP response as fast as possible.
- You should aim for sub-second response times in all circumstances.
- If the response takes longer than the configured timeout, GitLab assumes the
- hook failed, which can lead to retries and potentially cause duplicate
- events.
- To customize the timeout, see
- [Webhook fails or multiple webhook requests are triggered](#webhook-fails-or-multiple-webhook-requests-are-triggered).
-- Your endpoint should ALWAYS return a valid HTTP response. If not,
- GitLab assumes the hook failed and retries it.
- Most HTTP libraries take care of the response for you automatically but if
- you are writing a low-level hook, this is important to remember.
-- GitLab usually ignores the HTTP status code returned by your endpoint,
- unless the [`web_hooks_disable_failed` feature flag is set](#failing-webhooks).
-
-Best practices for a webhook receiver:
-
-- Prefer to return `200` or `201` status responses.
- Only return error statuses (in the `4xx` range) to
- indicate that the webhook has been misconfigured. For example, if your receiver
- only supports push events, it is acceptable to return `400` if sent an issue
- payload, since that is an indication that the hook has been set up
- incorrectly. Alternatively, it is acceptable to ignore unrecognized event
- payloads. Never return `500` status responses if the event has been handled.
-- Your service should be idempotent. In some circumstances (including
- timeouts), the same event may be sent twice. Be prepared to handle duplicate
- events. You can reduce the chances of this by ensuring that your endpoint is
+Webhook receiver endpoints should be fast and stable.
+Slow and unstable receivers can be [disabled automatically](#failing-webhooks) to ensure system reliability. Webhooks that fail can lead to retries, [which cause duplicate events](#webhook-fails-or-multiple-webhook-requests-are-triggered).
+
+Endpoints should follow these best practices:
+
+- **Respond quickly with a `200` or `201` status response.** Avoid any significant processing of webhooks in the same request.
+ Instead, implement a queue to handle webhooks after they are received. The timeout limit for webhooks is [10 seconds on GitLab.com](../../../user/gitlab_com/index.md#other-limits).
+- **Be prepared to handle duplicate events.** In [some circumstances](#webhook-fails-or-multiple-webhook-requests-are-triggered), the same event may be sent twice. To mitigate this issue, ensure your endpoint is
reliably fast and stable.
-- Keep response payloads as short as possible. Empty responses are
- fine. GitLab does not examine the response body, and it is only
- stored so you can examine it later in the logs.
-- Limit the number and size of response headers. Only send headers that would
- help you diagnose problems when examining the web hook logs.
-- To support fast response times, perform I/O or computationally intensive
- operations asynchronously. You may indicate that the webhook is
- asynchronous by returning `201`.
+- **Keep the response headers and body minimal.**
+ GitLab does not examine the response headers or body. GitLab stores them so you can examine them later in the logs to help diagnose problems. You should limit the number and size of headers returned. You can also respond to the webhook request with an empty body.
+- Only return client error status responses (in the `4xx` range) to
+ indicate that the webhook has been misconfigured. Responses in this range can lead to your webhooks being [automatically disabled](#failing-webhooks). For example, if your receiver
+ only supports push events, you can return `400` if sent an issue
+ payload, as that is an indication that the hook has been set up
+ incorrectly. Alternatively, you can ignore unrecognized event
+ payloads.
+- Never return `500` server error status responses if the event has been handled as this can cause the webhook to be [temporarily disabled](#failing-webhooks).
+- Invalid HTTP responses are treated as failed requests.
### Failing webhooks
-> - Introduced in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `web_hooks_disable_failed`. Disabled by default.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/329849) in GitLab 14.9.
+> Introduced in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `web_hooks_disable_failed`. 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 `web_hooks_disable_failed`.
+On GitLab.com, this feature is not available.
The feature is not ready for production use.
If a webhook fails repeatedly, it may be disabled automatically.
@@ -234,6 +214,18 @@ Image URLs are not rewritten if:
For more information about supported events for Webhooks, go to [Webhook events](webhook_events.md).
+## Delivery headers
+
+> `X-Gitlab-Instance` header [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31333) in GitLab 15.5.
+
+Webhook requests to your endpoint include the following headers:
+
+| Header | Description | Example |
+| ------ | ------ | ------ |
+| `User-Agent` | In the format `"Gitlab/<VERSION>"`. | `"GitLab/15.5.0-pre"` |
+| `X-Gitlab-Event` | Name of the webhook type. Corresponds to [event types](webhook_events.md) but in the format `"<EVENT> Hook"`. | `"Push Hook"` |
+| `X-Gitlab-Instance` | Hostname of the GitLab instance that sent the webhook. | `"https://gitlab.com"` |
+
## Troubleshoot webhooks
> **Recent events** for group webhooks [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325642) in GitLab 15.3.
@@ -271,20 +263,6 @@ To repeat the delivery with the same data, select **Resend Request**.
NOTE:
If you update the URL or secret token of the webhook, data is delivered to the new address.
-### Webhook fails or multiple webhook requests are triggered
-
-When GitLab sends a webhook, it expects a response in 10 seconds by default.
-If the endpoint doesn't send an HTTP response in those 10 seconds,
-GitLab may assume the webhook failed and retry it.
-
-If your webhooks are failing or you are receiving multiple requests,
-an administrator can try changing the default timeout value
-by uncommenting or adding the following setting in `/etc/gitlab/gitlab.rb`:
-
-```ruby
-gitlab_rails['webhook_timeout'] = 10
-```
-
### Unable to get local issuer certificate
When SSL verification is enabled, you might get an error that GitLab cannot
@@ -296,8 +274,24 @@ determined by [CAcert.org](http://www.cacert.org/).
If that is not the case, consider using [SSL Checker](https://www.sslshopper.com/ssl-checker.html) to identify faults.
Missing intermediate certificates are common causes of verification failure.
+### Webhook fails or multiple webhook requests are triggered
+
+If you are receiving multiple webhook requests, the webhook might have timed out and
+been retried.
+
+GitLab expects a response in [10 seconds](../../../user/gitlab_com/index.md#other-limits). On self-managed GitLab instances, you can [change the webhook timeout limit](../../../administration/instance_limits.md#webhook-timeout).
+
### Re-enable disabled webhooks
+> - Introduced in GitLab 15.2 [with a flag](../../../administration/feature_flags.md) named `webhooks_failed_callout`. Disabled by default.
+> - The [`web_hooks_disable_failed` flag](#failing-webhooks) must also be enabled for this feature to work. 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 flags](../../../administration/feature_flags.md) named `webhooks_failed_callout` and `web_hooks_disable_failed`.
+On GitLab.com, this feature is not available.
+The feature is not ready for production use.
+
If a webhook is failing, a banner displays at the top of the edit page explaining
why it is disabled, and when it will be automatically re-enabled. For example:
diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md
index e6071e7517d..fb6807aeeb0 100644
--- a/doc/user/project/integrations/youtrack.md
+++ b/doc/user/project/integrations/youtrack.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# YouTrack service **(FREE)**
diff --git a/doc/user/project/integrations/zentao.md b/doc/user/project/integrations/zentao.md
index 0256c52e4a3..17727ba22b1 100644
--- a/doc/user/project/integrations/zentao.md
+++ b/doc/user/project/integrations/zentao.md
@@ -1,7 +1,7 @@
---
-stage: Ecosystem
+stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# ZenTao product integration **(PREMIUM)**
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 916d566bb20..1cf902d2290 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue boards **(FREE)**
@@ -161,7 +161,7 @@ Cards finished by the UX team automatically appear in the **Frontend** column wh
for them.
NOTE:
-For a broader use case, please see the blog post
+For a broader use case, see the blog post
[What is GitLab Flow?](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/).
For a real use case example, you can read why
[Codepen decided to adopt issue boards](https://about.gitlab.com/blog/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)
@@ -243,13 +243,13 @@ This allows you to create unique boards according to your team's need.
![Create scoped board](img/issue_board_creation_v13_6.png)
-You can define the scope of your board when creating it or by clicking the **Edit board** button.
+You can define the scope of your board when creating it or by selecting the **Edit board** button.
After a milestone, iteration, assignee, or weight is assigned to an issue board, you can no longer
filter through these in the search bar. In order to do that, you need to remove the desired scope
(for example, milestone, assignee, or weight) from the issue board.
If you don't have editing permission in a board, you're still able to see the configuration by
-clicking **View scope**.
+selecting **View scope**.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch a [video presentation](https://youtu.be/m5UTNCSqaDk) of
@@ -474,7 +474,7 @@ Additionally, you can also see the time tracking value.
### Create a new list
-Create a new list by clicking the **Create** button in the upper right corner of the issue board.
+Create a new list by selecting the **Create** button in the upper right corner of the issue board.
![creating a new list in an issue board](img/issue_board_add_list_v14_1.png)
@@ -698,8 +698,8 @@ A few things to remember:
and adds the label from the list it goes to.
- An issue can exist in multiple lists if it has more than one label.
- Lists are populated with issues automatically if the issues are labeled.
-- Clicking the issue title inside a card takes you to that issue.
-- Clicking a label inside a card quickly filters the entire issue board
+- Selecting the issue title inside a card takes you to that issue.
+- Selecting a label inside a card quickly filters the entire issue board
and show only the issues from all lists that have that label.
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues, start scrolling down and the next
diff --git a/doc/user/project/issues/associate_zoom_meeting.md b/doc/user/project/issues/associate_zoom_meeting.md
index ef864dc2743..c7187323850 100644
--- a/doc/user/project/issues/associate_zoom_meeting.md
+++ b/doc/user/project/issues/associate_zoom_meeting.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Associate a Zoom meeting with an issue **(FREE)**
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index 5a1e66c8f7d..b1bb3f0dbf8 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Confidential issues **(FREE)**
diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md
index ed6c07f2c6d..0b5605bb767 100644
--- a/doc/user/project/issues/crosslinking_issues.md
+++ b/doc/user/project/issues/crosslinking_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Crosslinking issues **(FREE)**
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index e5d698fa97a..83265d3e954 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Export issues to CSV **(FREE)**
@@ -15,7 +15,7 @@ notification email address as an attachment.
collected from issues into a **[comma-separated values](https://en.wikipedia.org/wiki/Comma-separated_values)** (CSV)
file, which stores tabular data in plain text.
-> _CSVs are a handy way of getting data from one program to another where one
+> _CSVs are a way of getting data from one program to another where one
program cannot read the other ones normal output._ [Ref](https://www.quora.com/What-is-a-CSV-file-and-its-uses)
<!-- vale gitlab.Spelling = NO -->
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 1ae57c9a883..d01f22d03c9 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Importing issues from CSV **(FREE)**
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index bf3cd13f3f0..593557967ed 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Design Management **(FREE)**
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 2630052d806..6293fe981de 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Due dates **(FREE)**
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index a2dbc8581d9..09067b69696 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issues **(FREE)**
diff --git a/doc/user/project/issues/issue_weight.md b/doc/user/project/issues/issue_weight.md
index 21d7fb0a764..1ba5a4415e0 100644
--- a/doc/user/project/issues/issue_weight.md
+++ b/doc/user/project/issues/issue_weight.md
@@ -2,7 +2,7 @@
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/issue_weight.html'
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Issue weight **(PREMIUM)**
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index b4edb238479..213c615326f 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Manage issues **(FREE)**
@@ -68,7 +68,7 @@ To create an issue from a group:
The newly created issue opens.
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.
+This can save you a lot of time, if you mostly create issues for the same project.
### From another issue or incident
@@ -577,6 +577,7 @@ Or:
> - Filtering by type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 13.10 [with a flag](../../../administration/feature_flags.md) named `vue_issues_list`. Disabled by default.
> - Filtering by type was [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/322755) in GitLab 14.10.
> - Filtering by type is generally available in GitLab 15.1. [Feature flag `vue_issues_list`](https://gitlab.com/gitlab-org/gitlab/-/issues/359966) removed.
+> - Filtering by health status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218711) in GitLab 15.5.
To filter the list of issues:
diff --git a/doc/user/project/issues/multiple_assignees_for_issues.md b/doc/user/project/issues/multiple_assignees_for_issues.md
index db160b6cfe8..59555e1f675 100644
--- a/doc/user/project/issues/multiple_assignees_for_issues.md
+++ b/doc/user/project/issues/multiple_assignees_for_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Multiple assignees for issues **(PREMIUM)**
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index d1e62a76103..53ad7196920 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Linked issues **(FREE)**
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index 95a7e9387e8..6a1a791645e 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sorting and ordering issue lists **(FREE)**
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 13c93fadf6e..826e0b21ea7 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Labels **(FREE)**
@@ -448,10 +448,10 @@ To learn what happens when you sort by priority or label priority, see
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241538) in GitLab 14.10 with a [feature flag](../../administration/feature_flags.md) named `realtime_labels`, disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/357370#note_991987201) in GitLab 15.1.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/357370) in GitLab 15.5.
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 `realtime_labels`.
+On self-managed GitLab, to prevent updating labels in real-time, you can ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `realtime_labels`.
On GitLab.com, this feature is available.
Changed labels are immediately visible to other users, without refreshing the page, on the following:
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 8d8169e8454..a8f1b634127 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Members of a project **(FREE)**
@@ -234,8 +234,8 @@ GitLab users can request to become a member of a project.
![Request access button](img/request_access_button.png)
-An email is sent to the most recently active project maintainers.
-Up to ten project maintainers are notified.
+An email is sent to the most recently active project maintainers or owners.
+Up to ten project maintainers or owners are notified.
Any project owner or maintainer can approve or decline the request.
Project maintainers cannot approve Owner role access requests.
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index ee161deaabb..52cc9fc4f9b 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Share projects with other groups **(FREE)**
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
deleted file mode 100644
index c1a87f7a5d4..00000000000
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/accessibility_testing.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/accessibility_testing.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index d06c8182e22..d3d95a5bf61 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Collaborate on merge requests across forks **(FREE)**
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index 9f33ed6807b..ea03427161e 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, concepts
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/approvals/index.html'
---
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index 32548215054..e09a1318981 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request approval rules **(PREMIUM)**
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 4fdf6d46b8b..a2a12b22c3b 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request approval settings **(PREMIUM)**
@@ -125,7 +125,7 @@ when more changes are added to it:
1. On the left sidebar, select **Settings > Merge requests**.
1. In the **Merge request approvals** section, scroll to **Approval settings** and
- select **Remove all approvals when commits are added to the source branch**.
+ select **Remove all approvals**.
1. Select **Save changes**.
Approvals aren't removed when a merge request is [rebased from the UI](../methods/index.md#rebasing-in-semi-linear-merge-methods)
diff --git a/doc/user/project/merge_requests/authorization_for_merge_requests.md b/doc/user/project/merge_requests/authorization_for_merge_requests.md
index 37ecc1b8d06..ba28432e90a 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts
---
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
deleted file mode 100644
index 95f749210c4..00000000000
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/browser_performance_testing.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/browser_performance_testing.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/changes.md b/doc/user/project/merge_requests/changes.md
index 5016a33ed28..6703cbf8b03 100644
--- a/doc/user/project/merge_requests/changes.md
+++ b/doc/user/project/merge_requests/changes.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 2040995280e..388c6fb55ac 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
deleted file mode 100644
index 79e590cb905..00000000000
--- a/doc/user/project/merge_requests/code_quality.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/code_quality.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/code_quality.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/commit_templates.md b/doc/user/project/merge_requests/commit_templates.md
index 99a1739b1a4..75c2bdffae8 100644
--- a/doc/user/project/merge_requests/commit_templates.md
+++ b/doc/user/project/merge_requests/commit_templates.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
diff --git a/doc/user/project/merge_requests/commits.md b/doc/user/project/merge_requests/commits.md
index 20e0d3a1f5b..a6ae3ac80a5 100644
--- a/doc/user/project/merge_requests/commits.md
+++ b/doc/user/project/merge_requests/commits.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
diff --git a/doc/user/project/merge_requests/confidential.md b/doc/user/project/merge_requests/confidential.md
index 5b17ec009e4..307998f697d 100644
--- a/doc/user/project/merge_requests/confidential.md
+++ b/doc/user/project/merge_requests/confidential.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge requests for confidential issues **(FREE)**
diff --git a/doc/user/project/merge_requests/conflicts.md b/doc/user/project/merge_requests/conflicts.md
index dc128f89fcd..902095bcbce 100644
--- a/doc/user/project/merge_requests/conflicts.md
+++ b/doc/user/project/merge_requests/conflicts.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md
index 1a44126f7ff..df11d5a1d8d 100644
--- a/doc/user/project/merge_requests/creating_merge_requests.md
+++ b/doc/user/project/merge_requests/creating_merge_requests.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "How to create merge requests in GitLab."
disqus_identifier: 'https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html'
---
@@ -10,6 +10,9 @@ disqus_identifier: 'https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.h
There are many different ways to create a merge request.
+NOTE:
+Use [branch naming patterns](../repository/branches/index.md#naming) to streamline merge request creation.
+
## From the merge request list
You can create a merge request from the list of merge requests.
@@ -93,8 +96,8 @@ You can create a merge request from your fork to contribute back to the main pro
1. On the top bar, select **Main menu > Projects** and find your project.
1. Select your fork of the repository.
1. On the left menu, go to **Merge requests**, and select **New merge request**.
-1. In the **Source branch** drop-down list box, select the branch in your forked repository as the source branch.
-1. In the **Target branch** drop-down list box, select the branch from the upstream repository as the target branch.
+1. In the **Source branch** dropdown list box, select the branch in your forked repository as the source branch.
+1. In the **Target branch** dropdown list box, select the branch from the upstream repository as the target branch.
You can set a [default target project](#set-the-default-target-project) to
change the default target branch (which can be useful if you are working in a
forked project).
diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md
index f997898f5a5..662189c5e40 100644
--- a/doc/user/project/merge_requests/csv_export.md
+++ b/doc/user/project/merge_requests/csv_export.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Export merge requests to CSV **(FREE)**
diff --git a/doc/user/project/merge_requests/dependencies.md b/doc/user/project/merge_requests/dependencies.md
index 5b88e69357c..d0b0ead6b87 100644
--- a/doc/user/project/merge_requests/dependencies.md
+++ b/doc/user/project/merge_requests/dependencies.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/drafts.md b/doc/user/project/merge_requests/drafts.md
index 695c6d7e612..2beb7406518 100644
--- a/doc/user/project/merge_requests/drafts.md
+++ b/doc/user/project/merge_requests/drafts.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html'
---
diff --git a/doc/user/project/merge_requests/fail_fast_testing.md b/doc/user/project/merge_requests/fail_fast_testing.md
deleted file mode 100644
index c09a7c14c06..00000000000
--- a/doc/user/project/merge_requests/fail_fast_testing.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/fail_fast_testing.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/fail_fast_testing.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/fast_forward_merge.md b/doc/user/project/merge_requests/fast_forward_merge.md
deleted file mode 100644
index 048421a3a5b..00000000000
--- a/doc/user/project/merge_requests/fast_forward_merge.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: 'methods/index.md'
-remove_date: '2022-08-09'
----
-
-This document was moved to [another location](methods/index.md).
-
-<!-- This redirect file can be deleted after <2022-08-09>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index 9475c0d60ab..427ab9606e8 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Getting started with merge requests."
---
diff --git a/doc/user/project/merge_requests/img/dependencies_edit_inaccessible_v12_4.png b/doc/user/project/merge_requests/img/dependencies_edit_inaccessible_v12_4.png
deleted file mode 100644
index 5ced2fa812f..00000000000
--- a/doc/user/project/merge_requests/img/dependencies_edit_inaccessible_v12_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/dependencies_view_v12_2.png b/doc/user/project/merge_requests/img/dependencies_view_v12_2.png
deleted file mode 100644
index 3dde15292c4..00000000000
--- a/doc/user/project/merge_requests/img/dependencies_view_v12_2.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 500fb95c193..e73c339e000 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -254,7 +254,7 @@ after merging does not retarget open merge requests. This improvement is
For a software developer working in a team:
-1. You checkout a new branch, and submit your changes through a merge request.
+1. You check out a new branch, and submit your changes through a merge request.
1. You gather feedback from your team.
1. You work on the implementation optimizing code with [Code Quality reports](../../../ci/testing/code_quality.md).
1. You verify your changes with [Unit test reports](../../../ci/testing/unit_test_reports.md) in GitLab CI/CD.
@@ -269,7 +269,7 @@ For a software developer working in a team:
For a web developer writing a webpage for your company's website:
-1. You checkout a new branch and submit a new page through a merge request.
+1. You check out a new branch and submit a new page through a merge request.
1. You gather feedback from your reviewers.
1. You preview your changes with [Review Apps](../../../ci/review_apps/index.md).
1. You request your web designers for their implementation.
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
deleted file mode 100644
index 04b62c5d8fe..00000000000
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/load_performance_testing.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/load_performance_testing.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index 57c4ff455cb..f0359446b06 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/methods/index.md b/doc/user/project/merge_requests/methods/index.md
index 68dd6477408..e72c927198e 100644
--- a/doc/user/project/merge_requests/methods/index.md
+++ b/doc/user/project/merge_requests/methods/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, concepts
---
diff --git a/doc/user/project/merge_requests/revert_changes.md b/doc/user/project/merge_requests/revert_changes.md
index a6e0740ff78..3b07f75a3a7 100644
--- a/doc/user/project/merge_requests/revert_changes.md
+++ b/doc/user/project/merge_requests/revert_changes.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Revert changes **(FREE)**
diff --git a/doc/user/project/merge_requests/reviews/data_usage.md b/doc/user/project/merge_requests/reviews/data_usage.md
index 0988e3f0042..56fb84c8085 100644
--- a/doc/user/project/merge_requests/reviews/data_usage.md
+++ b/doc/user/project/merge_requests/reviews/data_usage.md
@@ -1,7 +1,7 @@
---
stage: ModelOps
group: Applied ML
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -9,36 +9,36 @@ type: index, reference
## How it works
-Suggested Reviewers is the first user-facing GitLab machine learning (ML) powered feature. It leverages a project's contribution graph to generate suggestions. This data already exists within GitLab including merge request metadata, source code files, and GitLab user account metadata.
+Suggested Reviewers is the first user-facing GitLab machine learning (ML) powered feature. It leverages a project's contribution graph to generate suggestions. This data already exists within GitLab including merge request metadata, source code files, and GitLab user account metadata.
### Enabling the feature
When a Project Maintainer or Owner enables Suggested Reviewers in project settings GitLab kicks off a data extraction job for the project which leverages the Merge Request API to understand pattern of review including recency, domain experience, and frequency to suggest an appropriate reviewer.
-This data extraction job can take a few hours to complete (possibly up to a day), which is largely dependent on the size of the project. The process is automated and no action is needed during this process. Once data extraction is complete, you will start getting suggestions in merge requests.
+This data extraction job can take a few hours to complete (possibly up to a day), which is largely dependent on the size of the project. The process is automated and no action is needed during this process. Once data extraction is complete, you will start getting suggestions in merge requests.
### Generating suggestions
-Once Suggested Reviewers is enabled and the data extraction is complete, new merge requests or new commits to existing merge requests will automatically trigger a Suggested Reviewers ML model inference and generate up to 5 suggested reviewers. These suggestions are contextual to the changes in the merge request. Additional commits to merge requests may change the reviewer suggestions which will automatically update in the reviewer dropdown.
+Once Suggested Reviewers is enabled and the data extraction is complete, new merge requests or new commits to existing merge requests will automatically trigger a Suggested Reviewers ML model inference and generate up to 5 suggested reviewers. These suggestions are contextual to the changes in the merge request. Additional commits to merge requests may change the reviewer suggestions which will automatically update in the reviewer dropdown.
## Progressive enhancement
-This feature is designed as a progressive enhancement to the existing GitLab Reviewers functionality. The GitLab Reviewer UI will only offer suggestions if the ML engine is able to provide a recommendation. In the event of an issue or model inference failure, the feature will gracefully degrade. At no point with the usage of Suggested Reviewers prevent a user from being able to manually set a reviewer.
+This feature is designed as a progressive enhancement to the existing GitLab Reviewers functionality. The GitLab Reviewer UI will only offer suggestions if the ML engine is able to provide a recommendation. In the event of an issue or model inference failure, the feature will gracefully degrade. At no point with the usage of Suggested Reviewers prevent a user from being able to manually set a reviewer.
## Model Accuracy
-Organizations use many different processes for code review. Some focus on senior engineers reviewing junior engineer's code, others have hierarchical organizational structure based reviews. Suggested Reviewers is focused on contextual reviewers based on historical merge request activity by users. While we will continue evolving the underlying ML model to better serve various code review use cases and processes Suggested Reviewers does not replace the usage of other code review features like Code Owners and [Approval Rules](../approvals/rules.md). Reviewer selection is highly subjective therefore, we do not expect Suggested Reviewers to provide perfect suggestions everytime.
+Organizations use many different processes for code review. Some focus on senior engineers reviewing junior engineer's code, others have hierarchical organizational structure based reviews. Suggested Reviewers is focused on contextual reviewers based on historical merge request activity by users. While we will continue evolving the underlying ML model to better serve various code review use cases and processes Suggested Reviewers does not replace the usage of other code review features like Code Owners and [Approval Rules](../approvals/rules.md). Reviewer selection is highly subjective therefore, we do not expect Suggested Reviewers to provide perfect suggestions everytime.
Through analysis of beta customer usage, we find that the Suggested Reviewers ML model provides suggestions that are adopted in 60% of cases. We will be introducing a feedback mechanism into the Suggested Reviewers feature in the future to allow users to flag bad reviewer suggestions to help improve the model. Additionally we will be offering an opt-in feature in the future which will allow the model to use your project's data for training the underlying model.
## Off by default
-Suggested Reviewers is off by default and requires a Project Owner or Admin to enable the feature.
+Suggested Reviewers is off by default and requires a Project Owner or Admin to enable the feature.
## Data privacy
-Suggested Reviewers operates completely within the GitLab.com infrastructure providing the same level of [privacy](https://about.gitlab.com/privacy/) and [security](https://about.gitlab.com/security/) of any other feature of GitLab.com.
+Suggested Reviewers operates completely within the GitLab.com infrastructure providing the same level of [privacy](https://about.gitlab.com/privacy/) and [security](https://about.gitlab.com/security/) of any other feature of GitLab.com.
-No new additional data is collected to enable this feature, simply GitLab is inferencing your merge request against a trained machine learning model. The content of your source code is not used as training data. Your data also never leaves GitLab.com, all training and inference is done within GitLab.com infrastructure.
+No new additional data is collected to enable this feature. GitLab is inferencing your merge request against a trained machine learning model. The content of your source code is not used as training data. Your data also never leaves GitLab.com, all training and inference is done within GitLab.com infrastructure.
[Read more about the security of GitLab.com](https://about.gitlab.com/security/faq/)
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index 227f38ad472..ce1fc94395c 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -25,21 +25,21 @@ review merge requests in Visual Studio Code.
> [Introduced](https://gitlab.com/groups/gitlab-org/modelops/applied-ml/review-recommender/-/epics/3) in GitLab 15.4.
-GitLab can recommend reviewers with Suggested Reviewers. Using the changes in a merge request and a project's contribution graph, machine learning powered suggestions appear in the reviewer section of the right merge request sidebar.
+GitLab can recommend reviewers with Suggested Reviewers. Using the changes in a merge request and a project's contribution graph, machine learning powered suggestions appear in the reviewer section of the right merge request sidebar.
![Suggested Reviewers](img/suggested_reviewers_v15_4.png)
This feature is currently in [Open Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#open-beta) behind a [feature flag](https://gitlab.com/gitlab-org/gitlab/-/issues/368356).
-Learn more about [how suggested reviewers works and data privacy](data_usage.md).
+Learn more about [how suggested reviewers works and data privacy](data_usage.md).
### Enable suggested reviewers
-Project Maintainers or Owners can enable suggested reviewers by visiting the [project settings](../../settings/index.md).
+Project Maintainers or Owners can enable suggested reviewers by visiting the [project settings](../../settings/index.md).
Enabling suggested reviewers will trigger GitLab to create an ML model for your project that will be used to generate reviewers. The larger your project, the longer this can take, but usually, the model will be ready to generate suggestions within a few hours.
-No action is required once the feature is enabled. Once the model is ready, recommendations will populate the Reviewer dropdown in the right-hand sidebar of a merge request with new commits.
+No action is required once the feature is enabled. Once the model is ready, recommendations will populate the Reviewer dropdown in the right-hand sidebar of a merge request with new commits.
## Review a merge request
@@ -238,7 +238,7 @@ This can occur if Sidekiq doesn't pick up the changes fast enough.
#### Sidekiq
-Sidekiq didn't process the CI state change fast enough. Please wait a few
+Sidekiq didn't process the CI state change fast enough. Wait a few
seconds and the status should update automatically.
#### Bug
@@ -266,7 +266,7 @@ The merge request sidebar contains the branch reference for the source branch
used to contribute changes for this merge request.
To copy the branch reference into your clipboard, select the **Copy branch name** button
-(**{copy-to-clipboard}**) in the right sidebar. Use it to checkout the branch locally
+(**{copy-to-clipboard}**) in the right sidebar. Use it to check out the branch locally
from the command line by running `git checkout <branch-name>`.
### Checkout merge requests locally through the `head` ref
diff --git a/doc/user/project/merge_requests/reviews/suggestions.md b/doc/user/project/merge_requests/reviews/suggestions.md
index 2ff65571c8b..2d3682c62d4 100644
--- a/doc/user/project/merge_requests/reviews/suggestions.md
+++ b/doc/user/project/merge_requests/reviews/suggestions.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 066149afbb5..e83e17072d6 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Squash and merge **(FREE)**
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index da705a53153..d330ccdefb6 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -1,7 +1,7 @@
---
stage: Govern
group: Compliance
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, concepts
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html'
---
@@ -29,6 +29,18 @@ You can configure merge request status checks for each individual project. These
To learn more about use cases, feature discovery, and development timelines,
see the [external status checks epic](https://gitlab.com/groups/gitlab-org/-/epics/3869).
+## Block merges of merge requests unless all status checks have passed
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369859) in GitLab 15.5 [with a flag](../../../administration/feature_flags.md) named `only_allow_merge_if_all_status_checks_passed`. Disabled by default.
+
+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 `only_allow_merge_if_all_status_checks_passed`. On GitLab.com, this feature is not available.
+
+By default, merge requests in projects can be merged even if external status checks fail. To block the merging of merge requests when external checks fail, enable this feature
+using the [project API](../../../api/projects.md#edit-project). You must also [enable the feature flag](../../../administration/feature_flags.md) named
+`only_allow_merge_if_all_status_checks_passed`.
+
## Lifecycle
External status checks have an **asynchronous** workflow. Merge requests emit a merge request webhook payload to an external service whenever:
@@ -188,7 +200,7 @@ Unable to fetch branches list, please close the form and try again
An unexpected response was received from the branches retrieval API.
As suggested, you should close the form and reopen again or refresh the page. This error should be temporary, although
-if it persists please check the [GitLab status page](https://status.gitlab.com/) to see if there is a wider outage.
+if it persists, check the [GitLab status page](https://status.gitlab.com/) to see if there is a wider outage.
### Failed to load status checks
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
deleted file mode 100644
index 53d45e6940d..00000000000
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/test_coverage_visualization.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/test_coverage_visualization.md).
-
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
deleted file mode 100644
index 6c0086bc429..00000000000
--- a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-redirect_to: '../../../ci/testing/index.md'
-remove_date: '2022-08-31'
----
-
-This document was moved to [another location](../../../ci/testing/index.md).
-
-<!-- This redirect file can be deleted after <2022-08-31>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 236ec64a4dc..6f29272f003 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge requests versions **(FREE)**
diff --git a/doc/user/project/merge_requests/widgets.md b/doc/user/project/merge_requests/widgets.md
index 0e179415192..a7aa86a16d4 100644
--- a/doc/user/project/merge_requests/widgets.md
+++ b/doc/user/project/merge_requests/widgets.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -54,7 +54,7 @@ Set a merge request that looks ready to merge to
If you configured [Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) for your project,
you can preview the changes submitted to a feature branch through a merge request
-on a per-branch basis. You don't need to checkout the branch, install, and preview locally.
+on a per-branch basis. You don't need to check out the branch, install, and preview locally.
All your changes are available to preview by anyone with the Review Apps link.
With GitLab [Route Maps](../../../ci/review_apps/index.md#route-maps) set, the
diff --git a/doc/user/project/milestones/burndown_and_burnup_charts.md b/doc/user/project/milestones/burndown_and_burnup_charts.md
index 0f36747a547..01eeee9d3b9 100644
--- a/doc/user/project/milestones/burndown_and_burnup_charts.md
+++ b/doc/user/project/milestones/burndown_and_burnup_charts.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Burndown and burnup charts **(PREMIUM)**
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 723ca17ee56..76c5e32eb2b 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -2,7 +2,7 @@
type: index, reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Milestones **(FREE)**
@@ -180,8 +180,9 @@ Prerequisites:
To promote a project milestone:
1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Issues > Milestones**.
1. Either:
- - Select **Promote to Group Milestone** (**{level-up}**).
+ - Select **Promote to Group Milestone** (**{level-up}**) next to the milestone you want to promote.
- Select the milestone title, and then select **Promote**.
1. Select **Promote Milestone**.
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 c4c30dbdab4..1d32091b294 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
@@ -2,7 +2,7 @@
type: concepts
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# DNS records overview **(FREE)**
@@ -44,7 +44,7 @@ for the most popular hosting services:
- [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))
+- [Microsoft](https://learn.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 03f8ecac77f..5ee1fa103a4 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
@@ -2,7 +2,7 @@
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html'
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Custom domains and SSL/TLS certificates **(FREE)**
@@ -96,7 +96,7 @@ Root domains (`example.com`) require:
| `_gitlab-pages-verification-code.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
For projects on GitLab.com, this IP is `35.185.44.232`.
-For projects living in other GitLab instances (CE or EE), please contact
+For projects living in other GitLab instances (CE or EE), contact
your sysadmin asking for this information (which IP address is Pages
server running on your instance).
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 b5487f7a465..e9e6e5a9a3c 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
@@ -3,7 +3,7 @@ type: reference
description: "Automatic Let's Encrypt SSL certificates for GitLab Pages."
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Pages integration with Let's Encrypt **(FREE)**
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
index b080bee85aa..b9d2f8cb9a6 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
@@ -2,7 +2,7 @@
type: concepts
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# SSL/TLS certificates **(FREE)**
@@ -39,7 +39,7 @@ Now we have a different picture. [According to Josh Aas](https://letsencrypt.org
<!-- vale gitlab.rulename = YES -->
-> _We've since come to realize that HTTPS is important for almost all websites. It's important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn't want its content altered](https://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We've also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
+> _We've since come to realize that HTTPS is important for almost all websites. It's important for any website that allows people to sign in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn't want its content altered](https://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We've also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
Therefore, the reason why certificates are so important is that they encrypt
the connection between the **client** (you, your visitors)
diff --git a/doc/user/project/pages/getting_started/pages_ci_cd_template.md b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
index 58e15104815..01583dbe45d 100644
--- a/doc/user/project/pages/getting_started/pages_ci_cd_template.md
+++ b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a Pages website by using a CI/CD template **(FREE)**
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 71ed3134c1e..33cf677e1be 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
@@ -2,7 +2,7 @@
type: reference, howto
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a Pages website from a forked sample **(FREE)**
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 1c3d5d722cb..e34544c96f8 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tutorial: Create a GitLab Pages website from scratch **(FREE)**
diff --git a/doc/user/project/pages/getting_started/pages_new_project_template.md b/doc/user/project/pages/getting_started/pages_new_project_template.md
index 92baba6b9c6..d7e304dc6f8 100644
--- a/doc/user/project/pages/getting_started/pages_new_project_template.md
+++ b/doc/user/project/pages/getting_started/pages_new_project_template.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create a Pages website from a template **(FREE)**
diff --git a/doc/user/project/pages/getting_started/pages_ui.md b/doc/user/project/pages/getting_started/pages_ui.md
index 7e618fbaec8..064255c094f 100644
--- a/doc/user/project/pages/getting_started/pages_ui.md
+++ b/doc/user/project/pages/getting_started/pages_ui.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Incubation
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tutorial: Use the GitLab UI to deploy your static site **(FREE)**
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 29712a82be1..588d94729e2 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Pages domain names, URLs, and base URLs **(FREE)**
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 1f3628b74ec..47c0885c26b 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -2,7 +2,7 @@
description: 'Learn how to use GitLab Pages to deploy a static website at no additional cost.'
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Pages **(FREE)**
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index da024881ed6..ed154c0dfca 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Exploring GitLab Pages **(FREE)**
@@ -82,7 +82,7 @@ When using Pages under the top-level domain of a GitLab instance (`*.example.io`
of subdomains. If your namespace or group name contains a dot (for example, `foo.bar`) the domain
`https://foo.bar.example.io` does _not_ work.
-This limitation is because of the [HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1). HTTP pages
+This limitation is because of the [HTTP Over TLS protocol](https://www.rfc-editor.org/rfc/rfc2818#section-3.1). HTTP pages
work as long as you don't redirect HTTP to HTTPS.
## GitLab Pages and subgroups
@@ -108,7 +108,7 @@ Supposed your repository contained the following files:
└── main.js
```
-Then the `.gitlab-ci.yml` example below simply moves all files from the root
+Then the `.gitlab-ci.yml` example below moves all files from the root
directory of the project to the `public/` directory. The `.public` workaround
is so `cp` doesn't also copy `public/` to itself in an infinite loop:
@@ -299,8 +299,7 @@ To fix this, verify that the user is a member of the project.
### Cannot play media content on Safari
-Safari requires the web server to support the [Range request header](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP40006514-SW6)
-in order to play your media content. For GitLab Pages to serve
+Safari requires the web server to support the [Range request header](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP40006514-SW6) to play your media content. For GitLab Pages to serve
HTTP Range requests, you should use the following two variables in your `.gitlab-ci.yml` file:
```yaml
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index e6446c34bf0..be1ea236c87 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Pages access control **(FREE)**
diff --git a/doc/user/project/pages/public_folder.md b/doc/user/project/pages/public_folder.md
index f9c80875cc9..b5d498402d5 100644
--- a/doc/user/project/pages/public_folder.md
+++ b/doc/user/project/pages/public_folder.md
@@ -3,7 +3,7 @@ description: 'Learn how to configure the build output folder for the most
common static site generators'
stage: Create
group: Incubation
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure the public files folder **(FREE)**
@@ -51,16 +51,18 @@ rename that folder to a collision-free alternative first:
```javascript
// astro.config.mjs
- export default {
+ import { defineConfig } from 'astro/config';
+
+ export default defineConfig({
// GitLab Pages requires exposed files to be located in a folder called "public".
// So we're instructing Astro to put the static build output in a folder of that name.
- dist: 'public',
+ outDir: 'public',
// The folder name Astro uses for static files (`public`) is already reserved
// for the build output. So in deviation from the defaults we're using a folder
// called `static` instead.
- public: 'static',
- };
+ publicDir: 'static',
+ });
```
### SvelteKit
diff --git a/doc/user/project/pages/redirects.md b/doc/user/project/pages/redirects.md
index 5d03db4bf00..96de457c7f7 100644
--- a/doc/user/project/pages/redirects.md
+++ b/doc/user/project/pages/redirects.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Create redirects for GitLab Pages **(FREE)**
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 9b685592c9d..f9dcf838c33 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Protected branches **(FREE)**
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index 9b1e862af58..22ce81409a3 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Protected tags **(FREE)**
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index 3eb333f5785..b31ef858d59 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Push Options **(FREE)**
@@ -67,8 +67,8 @@ time as pushing changes:
| `merge_request.milestone="<milestone>"` | Set the milestone of the merge request. Ex: `git push -o merge_request.milestone="3.0"`. | [14.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63960) |
| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
-| `merge_request.assign="<user>"` | Assign users to the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
-| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. Accepts username or user ID.For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
+| `merge_request.assign="<user>"` | Assign users to the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904), support for usernames added in [15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276) |
+| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. Accepts username or user ID.For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904), support for usernames added in [15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276) |
If you use a push option that requires text with spaces in it, you need to enclose it
in quotes (`"`). You can omit the quotes if there are no spaces. Some examples:
@@ -115,13 +115,3 @@ pipeline succeeds:
```shell
git mwps origin <local-branch-name>
```
-
-## Troubleshooting
-
-## Push options for merge request assignment ignored
-
-When you push a branch to GitLab, you can use push options to assign to (`merge_request.assign="<USERNAME>"`)
-or unassign from (`merge_request.unassign="<USERNAME>"`) a user. If GitLab creates
-the merge request successfully, but fails to assign or unassign the merge request
-correctly, you can use the user ID instead. For more information, read the issue
-[Push option `merge_request.(un)assign` seems to be ignored](https://gitlab.com/gitlab-org/gitlab/-/issues/325169).
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 8b8eba62cce..3471123f8b5 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -2,7 +2,7 @@
type: reference
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab quick actions **(FREE)**
@@ -20,6 +20,9 @@ by selecting buttons or dropdowns in the GitLab user interface. You can enter
these commands in the descriptions or comments of issues, epics, merge requests,
and commits.
+Many quick actions are context-aware, requiring certain conditions be met. For example, to remove
+an issue due date with `/remove_due_date`, the issue must have a due date set.
+
Be sure to enter each quick action on a separate line to allow GitLab to
properly detect and execute the commands.
@@ -77,6 +80,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/iteration *iteration:"iteration name"` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set iteration. For example, to set the `Late in July` iteration: `/iteration *iteration:"Late in July"` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) in GitLab 13.1). |
| `/label ~label1 ~label2` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add one or more labels. Label names can also start without a tilde (`~`), but mixed syntax is not supported. |
| `/lock` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Lock the discussions. |
+| `/link` | **{check-circle}** Yes | ****{dotted-circle}** No | **{dotted-circle}** No | Add a link and description to [linked resources](../../operations/incident_management/linked_resources.md) in an incident ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/374964) in GitLab 15.5). |
| `/merge` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Merge changes. Depending on the project setting, this may be [when the pipeline succeeds](merge_requests/merge_when_pipeline_succeeds.md), or adding to a [Merge Train](../../ci/pipelines/merge_trains.md). |
| `/milestone %milestone` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set milestone. |
| `/move <path/to/project>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Move this issue to another project. Be careful when moving an issue to a project with different access rules. Before moving the issue, make sure it does not contain sensitive data. |
@@ -102,7 +106,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/remove_time_spent` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time spent. |
| `/remove_zoom` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove Zoom meeting from this issue. |
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
-| `/severity <severity>` | **{check-circle}** Yes | **{check-circle}** No | **{check-circle}** No | Set the severity. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334045) in GitLab 14.2. |
+| `/severity <severity>` | **{check-circle}** Yes | **{check-circle}** No | **{check-circle}** No | Set the severity. Issue type must be `Incident`. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334045) in GitLab 14.2. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
| `/spend <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. Learn more about [time tracking](time_tracking.md). |
| `/submit_review` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Submit a pending review ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8041) in GitLab 12.7). |
@@ -115,7 +119,8 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/unapprove` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Unapprove the merge request. ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8103) in GitLab 14.3 |
| `/unassign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove specific assignees. |
| `/unassign` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Remove all assignees. |
-| `/unassign_reviewer @user1 @user2` or `/remove_reviewer @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Remove specific reviewers. |
+| `/unassign_reviewer @user1 @user2` or `/remove_reviewer @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Remove specific reviewers.
+| `/unassign_reviewer me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Remove yourself as a reviewer. |
| `/unassign_reviewer` or `/remove_reviewer` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Remove all reviewers. |
| `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Remove specified labels. |
| `/unlabel` or `/remove_label` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Remove all labels. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 87ea95524fe..fd01dd451c2 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Releases **(FREE)**
@@ -61,7 +61,6 @@ You can create a release:
- [Using a job in your CI/CD pipeline](#creating-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.
@@ -77,12 +76,14 @@ To create a release in the Releases page:
1. On the top bar, select **Main menu > Projects** and find your project.
1. On the left sidebar, select **Deployments > Releases** and select **New release**.
-1. From the [**Tag name**](release_fields.md#tag-name) dropdown, either:
+1. From the [**Tag name**](release_fields.md#tag-name) dropdown list, 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. From the **Create from** dropdown list, select a branch or commit SHA to use when
+ creating the new tag.
+ 1. Optional. In the **Set tag message** text box, enter a message to create an
+ [annotated tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#_annotated_tags).
1. Optional. Enter additional information about the release, including:
- [Title](release_fields.md#title).
- [Milestones](#associate-milestones-with-a-release).
@@ -91,29 +92,6 @@ To create a release in the Releases page:
- [Asset links](release_fields.md#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 **Main 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 **Main 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**.
-
### Creating a release by using a CI/CD job
You can create a release directly as part of the GitLab CI/CD pipeline by using the
@@ -133,7 +111,7 @@ Methods for creating a release using a CI/CD job include:
You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority,
which is used to verify the peer when the `release-cli` creates a release through the API using HTTPS with custom certificates.
The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the
-[text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1)
+[text representation of the X.509 PEM public-key certificate](https://www.rfc-editor.org/rfc/rfc7468#section-5.1)
or the `path/to/file` containing the certificate authority.
For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
diff --git a/doc/user/project/releases/release_cicd_examples.md b/doc/user/project/releases/release_cicd_examples.md
index bfd83a20caf..1ec82d6702e 100644
--- a/doc/user/project/releases/release_cicd_examples.md
+++ b/doc/user/project/releases/release_cicd_examples.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Release CI/CD examples
diff --git a/doc/user/project/releases/release_cli.md b/doc/user/project/releases/release_cli.md
index 90363fca8b0..5af19c7cced 100644
--- a/doc/user/project/releases/release_cli.md
+++ b/doc/user/project/releases/release_cli.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/releases/release_fields.md b/doc/user/project/releases/release_fields.md
index 647cac9c38e..5ae1c69847d 100644
--- a/doc/user/project/releases/release_fields.md
+++ b/doc/user/project/releases/release_fields.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Release fields
diff --git a/doc/user/project/remote_development/index.md b/doc/user/project/remote_development/index.md
new file mode 100644
index 00000000000..879978f550a
--- /dev/null
+++ b/doc/user/project/remote_development/index.md
@@ -0,0 +1,139 @@
+---
+stage: Create
+group: Editor
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Remote Development **(FREE)**
+
+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.
+
+You can use the [Web IDE](../web_ide/index.md) to commit changes to a project directly from your web browser without installing any dependencies or cloning any repositories. The Web IDE, however, lacks a native runtime environment on which you would compile code, run tests, or generate real-time feedback in the IDE. For a more complete IDE experience, you can pair the Web IDE with a Remote Development environment that has been properly configured to run as a host.
+
+## Connect a remote machine to the Web IDE
+
+Prerequisites:
+
+- A remote virtual machine with root access
+- A domain address resolving to that machine
+- Docker installation
+
+To connect a remote machine to the Web IDE, you must:
+
+1. [Generate Let's Encrypt certificates](#generate-lets-encrypt-certificates).
+1. [Connect a development environment to the Web IDE](#connect-a-development-environment-to-the-web-ide).
+
+### Generate Let's Encrypt certificates
+
+To generate Let's Encrypt certificates:
+
+1. [Point a domain to your remote machine](#point-a-domain-to-your-remote-machine).
+1. [Install Certbot](#install-certbot).
+1. [Generate the certificates](#generate-the-certificates).
+
+#### Point a domain to your remote machine
+
+To point a domain to your remote machine, create an `A` record from `example.remote.gitlab.dev` to `1.2.3.4`.
+
+#### Install Certbot
+
+[Certbot](https://certbot.eff.org/) is a free and open-source software tool that automatically uses Let's Encrypt certificates on manually administrated websites to enable HTTPS.
+
+To install Certbot, run the following command:
+
+```shell
+sudo apt-get update
+sudo apt-get install certbot
+```
+
+#### Generate the certificates
+
+```shell
+export EMAIL="YOUR_EMAIL@example.com"
+export DOMAIN="example.remote.gitlab.dev"
+
+certbot -d "${DOMAIN}" \
+ -m "${EMAIL}" \
+ --config-dir ~/.certbot/config \
+ --logs-dir ~/.certbot/logs \
+ --work-dir ~/.certbot/work \
+ --manual \
+ --preferred-challenges dns certonly
+```
+
+### Connect a development environment to the Web IDE
+
+To connect a development environment to the Web IDE:
+
+1. [Create a development environment](#manage-a-development-environment).
+1. [Fetch a token](#fetch-a-token).
+1. [Connect to the Web IDE](#connect-to-the-web-ide).
+
+#### Manage a development environment
+
+**Create a development environment**
+
+```shell
+export CERTS_DIR="/home/ubuntu/.certbot/config/live/${DOMAIN}"
+export PROJECTS_DIR="/home/ubuntu"
+
+docker run -d \
+ --name my-environment \
+ -p 3443:3443 \
+ -v "${CERTS_DIR}/fullchain.pem:/gitlab-rd-web-ide/certs/fullchain.pem" \
+ -v "${CERTS_DIR}/privkey.pem:/gitlab-rd-web-ide/certs/privkey.pem" \
+ -v "${PROJECTS_DIR}:/projects" \
+ registry.gitlab.com/gitlab-com/create-stage/editor-poc/remote-development/gitlab-rd-web-ide-docker:0.1 \
+ --log-level warn --domain "${DOMAIN}" --ignore-version-mismatch
+```
+
+The new development environment starts automatically.
+
+**Stop a development environment**
+
+```shell
+docker container stop my-environment
+```
+
+**Start a development environment**
+
+```shell
+docker container start my-environment
+```
+
+The token changes every time you restart the development environment.
+
+**Remove a development environment**
+
+To remove a development environment:
+
+1. Stop the development environment.
+1. Run the following command:
+
+ ```shell
+ docker container rm my-environment
+ ```
+
+#### Fetch a token
+
+```shell
+docker exec my-environment cat TOKEN
+```
+
+#### Connect to the Web IDE
+
+To connect to the Web IDE:
+
+1. Run the following command:
+
+ ```shell
+ echo "https://gitlab-org.gitlab.io/gitlab-web-ide?remoteHost=${DOMAIN}:3443&hostPath=/projects"
+ ```
+
+1. Go to that URL and enter the [token you fetched](#fetch-a-token).
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index d31c64f4640..6801899160d 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: concepts, howto
---
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 5e5a42a061b..9755b5cb944 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Branches **(FREE)**
@@ -13,9 +13,10 @@ other.
After pushing your changes to a new branch, you can:
-- Create a [merge request](../../merge_requests/index.md)
-- Perform inline code review
-- [Discuss](../../../discussions/index.md) your implementation with your team
+- Create a [merge request](../../merge_requests/index.md). You can streamline this process
+ by following [branch naming patterns](#naming).
+- Perform inline code review.
+- [Discuss](../../../discussions/index.md) your implementation with your team.
- Preview changes submitted to a new branch with [Review Apps](../../../../ci/review_apps/index.md).
You can also request [approval](../../merge_requests/approvals/index.md)
@@ -42,6 +43,18 @@ See also:
- [GitLab Flow](../../../../topics/gitlab_flow.md) documentation.
- [Getting started with Git](../../../../topics/git/index.md) and GitLab.
+## Naming
+
+Prefix a branch name with an issue number to streamline merge request creation.
+When you create a merge request for a branch with a name beginning with an issue
+number, GitLab:
+
+- Marks the issue as related. If your project is configured with a
+ [default closing pattern](../../issues/managing_issues.md#default-closing-pattern),
+ merging this merge request [also closes](../../issues/managing_issues.md#closing-issues-automatically)
+ the related issue.
+- Copies label and milestone metadata from the issue.
+
## Compare
To compare branches in a repository:
@@ -99,7 +112,7 @@ Sometimes when you have hundreds of branches you may want a more flexible matchi
![Before swap revisions](img/swap_revisions_before_v13_12.png)
-The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is clicked, the selected revisions for Source and Target is swapped.
+The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is selected, the selected revisions for Source and Target is swapped.
![After swap revisions](img/swap_revisions_after_v13_12.png)
diff --git a/doc/user/project/repository/csv.md b/doc/user/project/repository/csv.md
index 27424268d2b..101878ee4b4 100644
--- a/doc/user/project/repository/csv.md
+++ b/doc/user/project/repository/csv.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/project/repository/file_finder.md b/doc/user/project/repository/file_finder.md
index 42b82f2c360..f9a5d4e3aa7 100644
--- a/doc/user/project/repository/file_finder.md
+++ b/doc/user/project/repository/file_finder.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/file_finder.html'
---
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index df75f19ea6c..fae6e210a6c 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/forking_workflow.html'
---
diff --git a/doc/user/project/repository/git_blame.md b/doc/user/project/repository/git_blame.md
index 0026834ae83..78fcdec2a0b 100644
--- a/doc/user/project/repository/git_blame.md
+++ b/doc/user/project/repository/git_blame.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
description: "Documentation on Git file blame."
---
diff --git a/doc/user/project/repository/git_history.md b/doc/user/project/repository/git_history.md
index 356f02a4902..08fe767f9c9 100644
--- a/doc/user/project/repository/git_history.md
+++ b/doc/user/project/repository/git_history.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
description: "Documentation on Git file history."
---
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index d307a6a8580..910b09449d8 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Signing commits with GPG **(FREE)**
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 4926cf3812e..bcdb626d0f2 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Repository **(FREE)**
@@ -306,3 +306,33 @@ 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.
+
+### Search sequence of pushes to a repository
+
+If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
+[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
+describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../../../administration/server_hooks.md) that changes a HEAD ref in a `git reset` operation.
+
+If you look at the output from the sample code below for the target branch, you
+see a discontinuity in the from/to commits as you step through the output.
+The `commit_from` of each new push should equal the `commit_to` of the previous push.
+A break in that sequence indicates one or more commits have been "lost" from the repository history.
+
+Using the [rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session), the following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
+
+```ruby
+p = Project.find_by_full_path('project/path')
+p.events.pushed_action.last(100).each do |e|
+ puts "%-20.20s %8s...%8s (%s)", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
+end ; nil
+```
+
+Example output showing break in sequence at line 4:
+
+```plaintext
+master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de root
+master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b root
+master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 root
+master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce root
+master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 root
+```
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index 1ed6dbd3348..4f6cff576ea 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
# Jupyter Notebook files **(FREE)**
diff --git a/doc/user/project/repository/managing_large_repositories.md b/doc/user/project/repository/managing_large_repositories.md
index d2ca49c118c..e5c1e4a6614 100644
--- a/doc/user/project/repository/managing_large_repositories.md
+++ b/doc/user/project/repository/managing_large_repositories.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: "Documentation on large repositories."
---
@@ -14,11 +14,11 @@ In the following sections, we detail several best practices for improving perfor
## Large File System (LFS)
-It's *strongly* recommended in any Git system that binary or blob files (for example, packages, audio, video, or graphics) are stored as Large File Storage (LFS) objects. In such setup, the Objects are stored elsewhere, such as in Object Storage, and this can reduce the repository size significantly, thus improving performance.
+It's *strongly* recommended in any Git system that binary or blob files (for example, packages, audio, video, or graphics) are stored as Large File Storage (LFS) objects. With LFS, the objects are stored externally, such as in Object Storage, which reduces the number and size of objects in the repository. Storing objects in external Object Storage can improve performance.
-To analyze if the repository has these sorts of objects, it's recommended to run a tool like [`git-sizer`](https://github.com/github/git-sizer) to get a detailed analysis. These tools can show in detail what makes up the repository as well as highlights any areas of concern. If any large objects are found, it's then recommended removing them with tools such as [`git filter-repo`](reducing_the_repo_size_using_git.md).
+To analyze if a repository has large objects, you can use a tool like [`git-sizer`](https://github.com/github/git-sizer) for detailed analysis. This tool shows details about what makes up the repository, and highlights any areas of concern. If any large objects are found, you can then remove them with a tool such as [`git filter-repo`](reducing_the_repo_size_using_git.md).
-Refer to the [Git LFS documentation for more information](../../../topics/git/lfs/index.md).
+For more information, refer to the [Git LFS documentation](../../../topics/git/lfs/index.md).
## Gitaly Pack Objects Cache
diff --git a/doc/user/project/repository/mirror/bidirectional.md b/doc/user/project/repository/mirror/bidirectional.md
index 793ca2a5f1f..9942469dd5c 100644
--- a/doc/user/project/repository/mirror/bidirectional.md
+++ b/doc/user/project/repository/mirror/bidirectional.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
---
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index 176461aeba7..fa6d8d82559 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
---
@@ -316,3 +316,38 @@ Mirroring does not support the short version of SSH clone URLs (`git@gitlab.com:
and requires the full version including the protocol (`ssh://git@gitlab.com/gitlab-org/gitlab.git`).
Make sure that host and project path are separated using `/` instead of `:`.
+
+### Transfer mirror users and tokens to a single service account in Rails console
+
+This requires access to the [GitLab Rails console](../../../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
+Use case: If you have multiple users using their own GitHub credentials to set up
+repository mirroring, mirroring breaks when people leave the company. Use this
+script to migrate disparate mirroring users and tokens into a single service account:
+
+```ruby
+svc_user = User.find_by(username: 'ourServiceUser')
+token = 'githubAccessToken'
+
+Project.where(mirror: true).each do |project|
+ import_url = project.import_url
+
+ # The url we want is https://token@project/path.git
+ repo_url = if import_url.include?('@')
+ # Case 1: The url is something like https://23423432@project/path.git
+ import_url.split('@').last
+ elsif import_url.include?('//')
+ # Case 2: The url is something like https://project/path.git
+ import_url.split('//').last
+ end
+
+ next unless repo_url
+
+ final_url = "https://#{token}@#{repo_url}"
+
+ project.mirror_user = svc_user
+ project.import_url = final_url
+ project.username_only_import_url = final_url
+ project.save
+end
+```
diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md
index 159580dcfa5..1923d8e2ae7 100644
--- a/doc/user/project/repository/mirror/pull.md
+++ b/doc/user/project/repository/mirror/pull.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
---
diff --git a/doc/user/project/repository/mirror/push.md b/doc/user/project/repository/mirror/push.md
index 10bdc54ecee..11d53b0c1d1 100644
--- a/doc/user/project/repository/mirror/push.md
+++ b/doc/user/project/repository/mirror/push.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
---
diff --git a/doc/user/project/repository/push_rules.md b/doc/user/project/repository/push_rules.md
index 90d2fdb89d0..917fca03967 100644
--- a/doc/user/project/repository/push_rules.md
+++ b/doc/user/project/repository/push_rules.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Push rules **(PREMIUM)**
@@ -78,6 +78,15 @@ Use these rules for your commit messages.
the expression. To allow any commit message, leave empty.
Uses multiline mode, which can be disabled by using `(?-m)`.
+## Reject commits that aren't DCO certified
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98810) in GitLab 15.5.
+
+Commits signed with the [Developer Certificate of Origin](https://developercertificate.org/) (DCO)
+certify the contributor wrote, or has the right to submit, the code contributed in that commit.
+You can require all commits to your project to comply with the DCO. This push rule requires a
+`Signed-off-by:` trailer in every commit message, and rejects any commits that lack it.
+
## Validate branch names
To validate your branch names, enter a regular expression for **Branch name**.
@@ -284,3 +293,28 @@ enabled, unsigned commits may still appear in the commit history if a commit was
created in GitLab itself. As expected, commits created outside GitLab and
pushed to the repository are rejected. For more information about this issue,
read [issue #19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
+
+### Bulk update push rules for _all_ projects
+
+To update the push rules to be the same for all projects,
+you need to use [the rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session),
+or write a script to update each project using the [Push Rules API endpoint](../../../api/projects.md#push-rules).
+
+For example, to enable **Check whether the commit author is a GitLab user** and **Do not allow users to remove Git tags with `git push`** checkboxes,
+and create a filter for allowing commits from a specific email domain only through rails console:
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+``` ruby
+Project.find_each do |p|
+ pr = p.push_rule || PushRule.new(project: p)
+ # Check whether the commit author is a GitLab user
+ pr.member_check = true
+ # Do not allow users to remove Git tags with `git push`
+ pr.deny_delete_tag = true
+ # Commit author's email
+ pr.author_email_regex = '@domain\.com$'
+ pr.save!
+end
+```
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index f209c7ef137..c85dd4555ca 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -1,7 +1,7 @@
---
stage: Systems
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reduce repository size **(FREE)**
@@ -257,4 +257,28 @@ increased, your only option is to:
### Incorrect repository statistics shown in the GUI
If the displayed size or commit number is different from the exported `.tar.gz` or local repository,
-you can ask a GitLab administrator to [force an update](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#incorrect-repository-statistics-shown-in-the-gui).
+you can ask a GitLab administrator to force an update.
+
+Using [the rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+p = Project.find_by_full_path('<namespace>/<project>')
+pp p.statistics
+p.statistics.refresh!
+pp p.statistics
+# compare with earlier values
+
+# An alternate method to clear project statistics
+p.repository.expire_all_method_caches
+UpdateProjectStatisticsWorker.perform_async(p.id, ["commit_count","repository_size","storage_size","lfs_objects_size"])
+
+# check the total artifact storage space separately
+builds_with_artifacts = p.builds.with_downloadable_artifacts.all
+
+artifact_storage = 0
+builds_with_artifacts.find_each do |build|
+ artifact_storage += build.artifacts_size
+end
+
+puts "#{artifact_storage} bytes"
+```
diff --git a/doc/user/project/repository/vscode.md b/doc/user/project/repository/vscode.md
index bbf14a71653..4afdb3be0bd 100644
--- a/doc/user/project/repository/vscode.md
+++ b/doc/user/project/repository/vscode.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Workflow extension for VS Code **(FREE)**
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 4ca341f0535..e1f05cd5501 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Web Editor **(FREE)**
@@ -40,7 +40,7 @@ might need. GitLab displays a message to help you:
![First file for your project](img/web_editor_template_dropdown_first_file_v14_1.png)
-When clicking on either `LICENSE` or `.gitignore` and so on, a dropdown displays
+When selecting either `LICENSE` or `.gitignore` and so on, a dropdown displays
to provide you a template that may be suitable for your project:
![MIT license selected](img/web_editor_template_dropdown_mit_license_v14_1.png)
@@ -115,6 +115,9 @@ the target branch. Select **Create directory** to finish.
There are multiple ways to create a branch from the GitLab web interface.
+NOTE:
+Use [branch naming patterns](branches/index.md#naming) to streamline merge request creation.
+
### Create a new branch from an issue
> The **Create merge request** button [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/349566) to open the merge request creation form in GitLab 14.8.
@@ -122,7 +125,7 @@ There are multiple ways to create a branch from the GitLab web interface.
If your development workflow requires an issue for every merge
request, you can create a branch directly from the issue to speed the process up.
The new branch, and later its merge request, are marked as related to this issue.
-Once merged, the merge request closes the issue.
+After merging the merge request, the issue is closed automatically, unless [automatic issue closing is disabled](../issues/managing_issues.md#disable-automatic-issue-closing).
You can see a **Create merge request** dropdown below the issue description.
NOTE:
diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md
index 0259ff6ce30..4a17b2ab84c 100644
--- a/doc/user/project/repository/x509_signed_commits/index.md
+++ b/doc/user/project/repository/x509_signed_commits/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Sign commits and tags with X.509 certificates **(FREE)**
@@ -48,7 +48,7 @@ GitLab checks certificate revocation lists on a daily basis with a background wo
- Self-signed certificates without `authorityKeyIdentifier`,
`subjectKeyIdentifier`, and `crlDistributionPoints` are not supported. We
recommend using certificates from a PKI that are in line with
- [RFC 5280](https://tools.ietf.org/html/rfc5280).
+ [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280).
- If you have more than one email in the Subject Alternative Name list in
your signing certificate,
[only the first one is used to verify commits](https://gitlab.com/gitlab-org/gitlab/-/issues/336677).
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index 8b80c494e2f..3b1af1f688c 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -2,7 +2,7 @@
type: reference, howto
stage: Plan
group: Certify
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Requirements Management **(ULTIMATE)**
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index bafa2005fdf..199f25f1122 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -1,7 +1,7 @@
---
stage: Plan
group: Certify
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Service Desk **(FREE)**
@@ -264,7 +264,7 @@ Graph API instead of IMAP. Follow the [documentation in the incoming email secti
}
```
-For Microsoft Cloud for US Government or [other Azure deployments](https://docs.microsoft.com/en-us/graph/deployments), configure the `azure_ad_endpoint` and `graph_endpoint` settings.
+For Microsoft Cloud for US Government or [other Azure deployments](https://learn.microsoft.com/en-us/graph/deployments), configure the `azure_ad_endpoint` and `graph_endpoint` settings.
- Example for Microsoft Cloud for US Government:
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 375e4a62b86..a47873f5179 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Import
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Migrating projects using file exports **(FREE)**
@@ -58,7 +58,7 @@ moved to your configured `uploads_directory`. Every 24 hours, a worker deletes t
### Items that are exported
The [`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/project/import_export.yml)
-file lists the items exported and imported when migrating projects using file exports. View this file in the branch
+file for projects lists many of the items exported and imported when migrating projects using file exports. View this file in the branch
for your version of GitLab to see the list of items relevant to you. For example,
[`import_export.yml` on the `14-10-stable-ee` branch](https://gitlab.com/gitlab-org/gitlab/-/blob/14-10-stable-ee/lib/gitlab/import_export/project/import_export.yml).
@@ -72,8 +72,10 @@ Items that are exported include:
- Project configuration, excluding integrations
- Issues
- Issue comments
+ - Issue iteration ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96184) in 15.4)
- Issue resource state events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
- Issue resource milestone events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
+ - Issue resource iteration events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291983) in GitLab 15.4)
- Merge requests
- Merge request diffs
- Merge request comments
@@ -135,16 +137,15 @@ To import a project:
To get the status of an import, you can query it through the [Project import/export API](../../../api/project_import_export.md#import-status).
As described in the API documentation, the query may return an import error or exceptions.
-### Items that are imported
+### Changes to imported items
-The following items are imported but changed slightly:
+Exported items are imported with the following changes:
-- Project members with the Owner role are imported as Maintainers.
-- If an imported project contains merge requests originating from forks, then new branches
- associated with such merge requests are created in a project during the import/export. Thus, the
- number of branches in the exported project might be bigger than in the original project.
-- If use of the `Internal` visibility level
- [is restricted](../../public_access.md#restrict-use-of-public-or-internal-projects),
+- Project members with the Owner role are imported with the Maintainer role.
+- If an imported project contains merge requests originating from forks, new branches associated with these merge
+ requests are created in the project. Therefore, the number of branches in the new project can be more than in the
+ source project.
+- If the `Internal` visibility level [is restricted](../../public_access.md#restrict-use-of-public-or-internal-projects),
all imported projects are given `Private` visibility.
Deploy keys aren't imported. To use deploy keys, you must enable them in your imported project and update protected branches.
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 5c2118e02cf..4407986f354 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, index, howto
---
@@ -40,187 +40,24 @@ To assign topics to a project:
1. In the **Topics** text box, enter the project topics. Popular topics are suggested as you type.
1. Select **Save changes**.
-## Compliance frameworks **(PREMIUM)**
+If you're an instance administrator, you can administer all project topics from the
+[Admin Area's Topics page](../../admin_area/index.md#administering-topics).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/287779) in GitLab 13.12.
+## Add a compliance framework to a project **(PREMIUM)**
-You can create a compliance framework label to identify that your project has certain compliance
-requirements or needs additional oversight. The label can optionally apply
-[compliance pipeline configuration](#compliance-pipeline-configuration).
+[Compliance frameworks](../../group/manage.md#compliance-frameworks) can be assigned to projects within group that has a
+compliance framework using either:
-Group owners can create, edit, and delete compliance frameworks:
-
-1. On the top bar, select **Main menu > Groups** and find your group.
-1. On the left sidebar, select **Settings** > **General**.
-1. Expand the **Compliance frameworks** section.
-
-Compliance frameworks created can then be assigned to projects within the group using:
-
-- The GitLab UI, using the project settings page.
+- The GitLab UI:
+ 1. On the top bar, select **Main menu > Projects > View all projects** and find your project.
+ 1. On the left sidebar, select **Settings** > **General**.
+ 1. Expand the **Compliance frameworks** section.
+ 1. Select a compliance framework.
+ 1. Select **Save changes**.
- In [GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/333249) and later, using the
- [GraphQL API](../../../api/graphql/reference/index.md#mutationprojectsetcomplianceframework).
-
-NOTE:
-Creating compliance frameworks on subgroups with GraphQL causes the framework to be
-created on the root ancestor if the user has the correct permissions. The GitLab UI presents a
-read-only view to discourage this behavior.
-
-### Compliance pipeline configuration **(ULTIMATE)**
-
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3156) in GitLab 13.9, disabled behind `ff_evaluate_group_level_compliance_pipeline` [feature flag](../../../administration/feature_flags.md).
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/300324) in GitLab 13.11.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/331231) in GitLab 14.2.
-
-Compliance framework pipelines allow group owners to define
-a compliance pipeline in a separate repository that gets
-executed in place of the local project's `.gitlab-ci.yml` file. As part of this pipeline, an
-`include` statement can reference the local project's `.gitlab-ci.yml` file. This way, the compliance
-pipeline jobs can run alongside the project-specific jobs any time the pipeline runs.
-Jobs and variables defined in the compliance
-pipeline can't be changed by variables in the local project's `.gitlab-ci.yml` file.
-
-When you set up the compliance framework, use the **Compliance pipeline configuration** box to link
-the compliance framework to specific CI/CD configuration. Use the
-`path/file.y[a]ml@group-name/project-name` format. For example:
-
-- `.compliance-ci.yml@gitlab-org/gitlab`.
-- `.compliance-ci.yaml@gitlab-org/gitlab`.
-
-This configuration is inherited by projects where the compliance framework label is applied. The
-result forces projects with the label to run the compliance CI/CD configuration in addition to
-the project's own CI/CD configuration. When a project with a compliance framework label executes a
-pipeline, it evaluates configuration in the following order:
-
-1. Compliance pipeline configuration.
-1. Project-specific pipeline configuration.
-
-The user running the pipeline in the project must at least have the Reporter role on the compliance
-project.
-
-Example `.compliance-gitlab-ci.yml`:
-
-```yaml
-# Allows compliance team to control the ordering and interweaving of stages/jobs.
-# Stages without jobs defined will remain hidden.
-stages:
- - pre-compliance
- - build
- - test
- - pre-deploy-compliance
- - deploy
- - post-compliance
-
-variables: # Can be overridden by setting a job-specific variable in project's local .gitlab-ci.yml
- FOO: sast
-
-sast: # None of these attributes can be overridden by a project's local .gitlab-ci.yml
- variables:
- FOO: sast
- image: ruby:2.6
- stage: pre-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-
-sanity check:
- image: ruby:2.6
- stage: pre-deploy-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-
-audit trail:
- image: ruby:2.6
- stage: post-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-
-include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
- project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_REF_NAME' # Must be defined or MR pipelines always use the use default branch
-```
-
-When used to enforce scan execution, this feature has some overlap with [scan execution policies](../../application_security/policies/scan-execution-policies.md),
-as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
-For details on the similarities and differences between these features, see
-[Enforce scan execution](../../application_security/index.md#enforce-scan-execution).
-
-### Ensure compliance jobs are always run
-
-Compliance pipelines use GitLab CI/CD to give you an incredible amount of flexibility
-for defining any sort of compliance jobs you like. Depending on your goals, these jobs
-can be configured to be:
-
-- Modified by users.
-- Non-modifiable.
-
-At a high-level, if a value in a compliance job:
-
-- Is set, it cannot be changed or overridden by project-level configurations.
-- Is not set, a project-level configuration may set.
-
-Either might be wanted or not depending on your use case.
-
-There are a few best practices for ensuring that these jobs are always run exactly
-as you define them and that downstream, project-level pipeline configurations
-cannot change them:
-
-- Add a `rules:when:always` block to each of your compliance jobs. This ensures they are
- non-modifiable and are always run.
-- Explicitly set any variables the job references. This:
- - Ensures that project-level pipeline configurations do not set them and alter their
- behavior.
- - Includes any jobs that drive the logic of your job.
-- Explicitly set the container image file to run the job in. This ensures that your script
- steps execute in the correct environment.
-- Explicitly set any relevant GitLab pre-defined [job keywords](../../../ci/yaml/index.md#job-keywords).
- This ensures that your job uses the settings you intend and that they are not overridden by
- project-level pipelines.
-
-### Avoid parent and child pipelines in GitLab 14.7 and earlier
-
-NOTE:
-This advice does not apply to GitLab 14.8 and later because [a fix](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78878) added
-compatibility for combining compliance pipelines, and parent and child pipelines.
-
-Compliance pipelines start on the run of _every_ pipeline in a relevant project. This means that if a pipeline in the relevant project
-triggers a child pipeline, the compliance pipeline runs first. This can trigger the parent pipeline, instead of the child pipeline.
-
-Therefore, in projects with compliance frameworks, we recommend replacing
-[parent-child pipelines](../../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines) with the following:
-
-- Direct [`include`](../../../ci/yaml/index.md#include) statements that provide the parent pipeline with child pipeline configuration.
-- Child pipelines placed in another project that are run using the [trigger API](../../../ci/triggers/index.md) rather than the parent-child
- pipeline feature.
-
-This alternative ensures the compliance pipeline does not re-start the parent pipeline.
+ [GraphQL API](../../../api/graphql/reference/index.md#mutationprojectsetcomplianceframework). If you create
+ compliance frameworks on subgroups with GraphQL, the framework is created on the root ancestor if the user has the
+ correct permissions. The GitLab UI presents a read-only view to discourage this behavior.
## Configure project visibility, features, and permissions
@@ -255,7 +92,8 @@ Use the toggles to enable or disable features in the project.
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md). |
| **Pages** | ✓ | Allows you to [publish static websites](../pages/index.md). |
| **Operations** | ✓ | Control access to Operations-related features, including [Operations Dashboard](../../../operations/index.md), [Environments and Deployments](../../../ci/environments/index.md), [Feature Flags](../../../operations/feature_flags.md). |
-| **Metrics Dashboard** | ✓ | Control access to [metrics dashboard](../integrations/prometheus.md). |
+| **Metrics Dashboard** | ✓ | Control access to [metrics dashboard](../integrations/prometheus.md). |
+| **Releases** | ✓ | Control access to [Releases](../releases/index.md). |
When you disable a feature, the following additional features are also disabled:
@@ -372,7 +210,7 @@ where GitLab is installed.
Prerequisites:
-You must be a project maintainer or administrator to rename a repository.
+You must be a project maintainer, owner, or administrator to rename a repository.
NOTE:
When you change the repository path, users may experience issues if they push to, or pull from, the old URL. For more information, see
@@ -538,3 +376,33 @@ Configure Error Tracking to discover and view [Sentry errors within GitLab](../.
[Add Storage credentials](../../../operations/incident_management/status_page.md#sync-incidents-to-the-status-page)
to enable the syncing of public Issues to a [deployed status page](../../../operations/incident_management/status_page.md#create-a-status-page-project).
+
+## Troubleshooting
+
+When working with project settings, you might encounter the following issues, or require alternate methods to complete specific tasks.
+
+### Remove a fork relationship through console
+
+If removing the fork through the UI or API is not working, you can attempt the fork relationship removal in a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
+```ruby
+p = Project.find_by_full_path('<project_path>')
+u = User.find_by_username('<username>')
+Projects::UnlinkForkService.new(p, u).execute
+```
+
+### Transfer a project through console
+
+If transferring a project through the UI or API is not working, you can attempt the transfer in a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
+```ruby
+p = Project.find_by_full_path('<project_path>')
+
+# To set the owner of the project
+current_user = p.creator
+
+# Namespace where you want this to be moved
+namespace = Namespace.find_by_full_path("<new_namespace>")
+
+Projects::TransferService.new(p, current_user).execute(namespace)
+```
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index c9c5efce9b1..f27672a1b07 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: "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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference, howto
---
@@ -48,6 +48,9 @@ You cannot use project access tokens to create other group, project, or personal
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:
+Project access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../../development/fips_compliance.md) is enabled.
+
## Create a project access token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89114) in GitLab 15.1, Owners can select Owner role for project access tokens.
@@ -82,10 +85,10 @@ The scope determines the actions you can perform when you authenticate with a pr
|:-------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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. |
+| `read_registry` | Grants read access (pull) to the [Container Registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. |
+| `write_registry` | Grants write access (push) to the [Container Registry](../../packages/container_registry/index.md). |
+| `read_repository` | Grants read access (pull) to the repository. |
+| `write_repository` | Grants read and write access (pull and push) to the repository. |
## Enable or disable project access token creation
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
deleted file mode 100644
index 343482757f5..00000000000
--- a/doc/user/project/static_site_editor/index.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-stage: Create
-group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
-remove_date: '2022-08-03'
-redirect_to: '../web_ide/index.md'
----
-
-# Static Site Editor (removed) **(FREE)**
-
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77246) in GitLab 14.7
-and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/352505) in 15.0.
-Use the [Web Editor](../repository/web_editor.md) or [Web IDE](../web_ide/index.md) instead.
-
-## Remove the Static Site Editor
-
-The Static Site Editor itself isn't part of your project. To remove the Static Site Editor
-from an existing project, remove links that point back to the editor:
-
-1. Remove any links that use `edit_page_url` in your project. If you used the
- **Middleman - Static Site Editor** project template, the only instance of this
- helper is located in `/source/layouts/layout.erb`. Remove this line entirely:
-
- ```ruby
- <%= link_to('Edit this page', edit_page_url(data.config.repository, current_page.file_descriptor.relative_path), id: 'edit-page-link') %>
- ```
-
-1. In `/data/config.yml`, delete the `repository` key / value pair:
-
- ```yaml
- repository: https://gitlab.com/<username>/<myproject>
- ```
-
- - If `repository` is the only value stored in `/data/config.yml`, you can delete the entire file.
-1. In `/helpers/custom_helpers.rb`, delete `edit_page_url()` and `endcode_path()`:
-
- ```ruby
- def edit_page_url(base_url, relative_path)
- "#{base_url}/-/sse/#{encode_path(relative_path)}/"
- end
-
- def encode_path(relative_path)
- ERB::Util.url_encode("master/source/#{relative_path}")
- end
- ```
-
- - If `edit_page_url()` and `encode_path()` are the only helpers, you may delete
- `/helpers/custom_helpers.rb` entirely.
-1. Clean up any extraneous configuration files.
-1. Commit and push your changes.
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index 522ec962e53..71b8c911839 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -3,7 +3,7 @@ type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/time_tracking.html'
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Time tracking **(FREE)**
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 2a197c733cf..a0eac9376f2 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Web IDE **(FREE)**
@@ -134,10 +134,10 @@ schemas:
Each schema entry supports two properties:
-- `uri`: please provide an absolute URL for the schema definition file here.
+- `uri`: Provide an absolute URL for the schema definition file here.
The schema from this URL is loaded when a matching file is open.
-- `match`: a list of matching paths or glob expressions. If a schema matches a
- particular path pattern, it is applied to that file. Please enclose the pattern
+- `match`: A list of matching paths or glob expressions. If a schema matches a
+ particular path pattern, it is applied to that file. Enclose the pattern
in quotes if it begins with an asterisk (`*`), it's be applied to that file.
If a pattern begins with an asterisk (`*`), enclose it in quotation marks.
Otherwise, the configuration file is not valid YAML.
@@ -193,7 +193,7 @@ shows you a preview of the merge request diff if you commit your changes.
You can use the Web IDE to quickly fix failing tests by opening
the branch or merge request in the Web IDE and opening the logs of the failed
job. You can access the status of all jobs for the most recent pipeline and job
-traces for the current commit by clicking the **Pipelines** button in the top
+traces for the current commit by selecting the **Pipelines** button in the top
right.
The pipeline status is also shown at all times in the status bar in the bottom
@@ -375,7 +375,7 @@ may be disabled:
- `.gitlab/.gitlab-webide.yml` does not exist or is set up incorrectly.
- No active private runners are available for the project.
-If active, clicking the **Start Web Terminal** button loads the terminal view
+If active, selecting the **Start Web Terminal** button loads the terminal view
and start connecting to the runner's terminal. At any time, the **Terminal** tab
can be closed and reopened and the state of the terminal is not affected.
@@ -384,7 +384,7 @@ runner's shell prompt appears in the terminal. From here, you can enter
commands executed in the runner's environment. This is similar
to running commands in a local terminal or through SSH.
-While the terminal is running, it can be stopped by clicking **Stop Terminal**.
+While the terminal is running, it can be stopped by selecting **Stop Terminal**.
This disconnects the terminal and stops the runner's terminal job. From here,
select **Restart Terminal** to start a new terminal session.
@@ -454,8 +454,8 @@ The Web IDE has a few limitations:
### Troubleshooting
- If the terminal's text is gray and unresponsive, then the terminal has stopped
- and it can no longer be used. A stopped terminal can be restarted by clicking
+ and it can no longer be used. A stopped terminal can be restarted by selecting
**Restart Terminal**.
- If the terminal displays **Connection Failure**, then the terminal could not
- connect to the runner. Please try to stop and restart the terminal. If the
+ connect to the runner. Try to stop and restart the terminal. If the
problem persists, double check your runner configuration.
diff --git a/doc/user/project/wiki/group.md b/doc/user/project/wiki/group.md
index 03838a62d59..0e9b76e943d 100644
--- a/doc/user/project/wiki/group.md
+++ b/doc/user/project/wiki/group.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Group wikis **(PREMIUM)**
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index b8924c33b13..eedc44be3f9 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Wiki **(FREE)**
@@ -152,6 +152,8 @@ You need at least the Developer role to edit a wiki page:
1. Edit the content.
1. Select **Save changes**.
+Unsaved changes to a wiki page are preserved in local browser storage to prevent accidental data loss.
+
### Create a table of contents
To generate a table of contents from a wiki page's subheadings, use the `[[_TOC_]]` tag.
@@ -388,6 +390,11 @@ line of your Apache configuration to ensure your page slugs render correctly.
WARNING:
This operation deletes all data in the wiki.
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the
+right conditions. We highly recommend running them in a test environment with a backup of the
+instance ready to be restored, just in case.
+
To clear all data from a project wiki and recreate it in a blank state:
1. [Start a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index e58bf5aa557..705e49df039 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -1,7 +1,7 @@
---
stage: Manage
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---
# Manage projects **(FREE)**
@@ -13,6 +13,11 @@ code are saved in projects, and most features are in the scope of projects.
To view projects, on the top bar, select **Main menu > Projects > View all projects**.
+NOTE:
+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. 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.
@@ -46,11 +51,6 @@ To explore project topics:
The **Explore topics** tab shows a list of topics sorted by the number of associated projects.
-NOTE:
-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. Then the tab is visible only to signed-in users.
-
You can assign topics to a project on the [Project Settings page](settings/index.md#assign-topics-to-a-project).
If you're an instance administrator, you can administer all project topics from the
@@ -90,8 +90,7 @@ To create a blank project:
- 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.
- - In the **Project target (optional)** field, select your project's deployment target.
+ - In the **Project deployment target (optional)** field, select your project's deployment target.
This information helps GitLab better understand its users and their deployment requirements.
- To modify the project's [viewing and access rights](../public_access.md) for
users, change the **Visibility Level**.
@@ -496,3 +495,97 @@ download starts, the `insteadOf` configuration sends the traffic to the secondar
- [Fork a project](repository/forking_workflow.md#creating-a-fork).
- [Adjust project visibility and access levels](settings/index.md#configure-project-visibility-features-and-permissions).
- [Limitations on project and group names](../../user/reserved_names.md#limitations-on-project-and-group-names)
+
+## Troubleshooting
+
+When working with projects, you might encounter the following issues, or require alternate methods to complete specific tasks.
+
+### Find projects using an SQL query
+
+While in [a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session), you can find and store an array of projects based on a SQL query:
+
+```ruby
+# Finds projects that end with '%ject'
+projects = Project.find_by_sql("SELECT * FROM projects WHERE name LIKE '%ject'")
+=> [#<Project id:12 root/my-first-project>>, #<Project id:13 root/my-second-project>>]
+```
+
+### Clear a project's or repository's cache
+
+If a project or repository has been updated but the state is not reflected in the UI, you may need to clear the project's or repository's cache.
+You can do so through [a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session) and one of the following:
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+## Clear project cache
+ProjectCacheWorker.perform_async(project.id)
+
+## Clear repository .exists? cache
+project.repository.expire_exists_cache
+```
+
+### Find projects that are pending deletion
+
+If you need to find all projects marked for deletion but that have not yet been deleted,
+[start a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session) and run the following:
+
+```ruby
+projects = Project.where(pending_delete: true)
+projects.each do |p|
+ puts "Project ID: #{p.id}"
+ puts "Project name: #{p.name}"
+ puts "Repository path: #{p.repository.full_path}"
+end
+```
+
+### Delete a project using console
+
+If a project cannot be deleted, you can attempt to delete it through [Rails console](../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+project = Project.find_by_full_path('<project_path>')
+user = User.find_by_username('<username>')
+ProjectDestroyWorker.new.perform(project.id, user.id, {})
+```
+
+If this fails, display why it doesn't work with:
+
+```ruby
+project = Project.find_by_full_path('<project_path>')
+project.delete_error
+```
+
+### Toggle a feature for all projects within a group
+
+While toggling a feature in a project can be done through the [projects API](../../api/projects.md),
+you may need to do this for a large number of projects.
+
+To toggle a specific feature, you can [start a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session)
+and run the following function:
+
+WARNING:
+Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
+
+```ruby
+projects = Group.find_by_name('_group_name').projects
+projects.each do |p|
+ ## replace <feature-name> with the appropriate feature name in all instances
+ state = p.<feature-name>
+
+ if state != 0
+ puts "#{p.name} has <feature-name> already enabled. Skipping..."
+ else
+ puts "#{p.name} didn't have <feature-name> enabled. Enabling..."
+ p.project_feature.update!(<feature-name>: ProjectFeature::PRIVATE)
+ end
+end
+```
+
+To find features that can be toggled, run `pp p.project_feature`.
+Available permission levels are listed in
+[concerns/featurable.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/featurable.rb).
diff --git a/doc/user/public_access.md b/doc/user/public_access.md
index 3accb0f5e3d..703932e50f6 100644
--- a/doc/user/public_access.md
+++ b/doc/user/public_access.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/user/report_abuse.md b/doc/user/report_abuse.md
index 93d9a1e773e..fab01973104 100644
--- a/doc/user/report_abuse.md
+++ b/doc/user/report_abuse.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Report abuse **(FREE)**
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 3cf379243e3..f8c735eaea8 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Reserved project and group names **(FREE)**
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index bec1a8f3d4c..86b59572e77 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
@@ -43,42 +43,3 @@ See [Advanced Search syntax](global_search/advanced_search_syntax.md) for more i
- To search by issue ID, use the `#` prefix followed by the issue ID (for example, [`#23456`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=%2323456&group_id=9970&project_id=278964)).
- To search by merge request ID, use the `!` prefix followed by the merge request ID (for example, [`!23456`](https://gitlab.com/search?snippets=&scope=merge_requests&repository_ref=&search=%2123456&group_id=9970&project_id=278964)).
-
-## Global search scopes **(FREE SELF)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68640) in GitLab 14.3.
-
-To improve the performance of your instance's global search, you can limit
-the scope of the search. To do so, you can exclude global search scopes by disabling
-[`ops` feature flags](../../development/feature_flags/index.md#ops-type).
-
-Global search has all its scopes **enabled** by default in GitLab SaaS and
-self-managed instances. A GitLab administrator can disable the following `ops`
-feature flags to limit the scope of your instance's global search and optimize
-its performance:
-
-| Scope | Feature flag | Description |
-|--|--|--|
-| Code | `global_search_code_tab` | When enabled, the global search includes code as part of the search. |
-| Commits | `global_search_commits_tab` | When enabled, the global search includes commits as part of the search. |
-| Issues | `global_search_issues_tab` | When enabled, the global search includes issues as part of the search. |
-| Merge Requests | `global_search_merge_requests_tab` | When enabled, the global search includes merge requests as part of the search. |
-| Users | `global_search_users_tab` | When enabled, the global search includes users as part of the search. |
-| Wiki | `global_search_wiki_tab` | When enabled, the global search includes wiki as part of the search. [Group wikis](../project/wiki/group.md) are not included. |
-
-## Global Search validation
-
-To prevent abusive searches, such as searches that may result in a Distributed Denial of Service (DDoS), Global Search ignores, logs, and
-doesn't return any results for searches considered abusive according to the following criteria:
-
-- Searches with less than 2 characters.
-- Searches with any term greater than 100 characters. URL search terms have a maximum of 200 characters.
-- Searches with a stop word as the only term (for example, "the", "and", "if", etc.).
-- Searches with a `group_id` or `project_id` parameter that is not completely numeric.
-- Searches with a `repository_ref` or `project_ref` parameter that has special characters not allowed by [Git refname](https://git-scm.com/docs/git-check-ref-format).
-- Searches with a `scope` that is unknown.
-
-Searches that don't comply with the criteria described below aren't logged as abusive but are flagged with an error:
-
-- Searches with more than 4096 characters.
-- Searches with more than 64 terms.
diff --git a/doc/user/search/global_search/advanced_search_syntax.md b/doc/user/search/global_search/advanced_search_syntax.md
index 9daa7afd6de..cd4bff0a20e 100644
--- a/doc/user/search/global_search/advanced_search_syntax.md
+++ b/doc/user/search/global_search/advanced_search_syntax.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Advanced Search syntax **(PREMIUM)**
@@ -47,5 +47,6 @@ Advanced Search searches default project branches only.
| [`rails -filename:gemfile.lock`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=rails+-filename%3Agemfile.lock&snippets=) | Show _rails_ in all files except the _`gemfile.lock`_ file. |
| [`RSpec.describe Resolvers -*builder`](https://gitlab.com/search?group_id=9970&project_id=278964&scope=blobs&search=RSpec.describe+Resolvers+-*builder) | Show all _RSpec.describe Resolvers_ that don't start with _builder_. |
| [<code>bug &#124; (display +banner)</code>](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+%7C+%28display+%2Bbanner%29&group_id=9970&project_id=278964) | Show _bug_ **or** _display_ **and** _banner_. |
+| [<code>helper -extension:yml -extension:js</code>](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=helper+-extension%3Ayml+-extension%3Ajs&snippets=) | Show _helper_ in all files, except for files with _`.yml`_ **or** _`.js`_ extensions. |
<!-- markdownlint-enable -->
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 41eff28b088..9bff2a91ec8 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -1,7 +1,7 @@
---
stage: Data Stores
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Searching in GitLab **(FREE)**
@@ -13,20 +13,40 @@ Both types of search are the same, except when you are searching through code.
- When you use basic search to search code, your search includes one project at a time.
- When you use [advanced search](advanced_search.md) to search code, your search includes all projects at once.
-## Basic search
+## Global search scopes **(FREE SELF)**
-Use basic search to find:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68640) in GitLab 14.3.
-- Projects
-- Issues
-- Merge requests
-- Milestones
-- Users
-- Epics (when searching in a group only)
-- Code
-- Comments
-- Commits
-- Wiki
+To improve the performance of your instance's global search, a GitLab administrator
+can limit the search scope by disabling the following [`ops` feature flags](../../development/feature_flags/index.md#ops-type).
+
+| Scope | Feature flag | Description |
+|--|--|--|
+| Code | `global_search_code_tab` | When enabled, global search includes code. |
+| Commits | `global_search_commits_tab` | When enabled, global search includes commits. |
+| Issues | `global_search_issues_tab` | When enabled, global search includes issues. |
+| Merge requests | `global_search_merge_requests_tab` | When enabled, global search includes merge requests. |
+| Users | `global_search_users_tab` | When enabled, global search includes users. |
+| Wiki | `global_search_wiki_tab` | When enabled, global search includes project wikis (not [group wikis](../project/wiki/group.md)). |
+
+All global search scopes are enabled by default on GitLab.com
+and self-managed instances.
+
+## Global search validation
+
+Global search ignores and logs as abusive any search with:
+
+- Fewer than 2 characters
+- A term longer than 100 characters (URL search terms must not exceed 200 characters)
+- A stop word only (for example, `the`, `and`, or `if`)
+- An unknown `scope`
+- `group_id` or `project_id` that is not completely numeric
+- `repository_ref` or `project_ref` with special characters not allowed by [Git refname](https://git-scm.com/docs/git-check-ref-format)
+
+Global search only flags with an error any search that includes more than:
+
+- 4096 characters
+- 64 terms
## Perform a search
@@ -78,6 +98,10 @@ and gives you the option to return to the search results page.
## Searching for specific terms
+> - [Removed support for partial matches in issue searches](https://gitlab.com/gitlab-org/gitlab/-/issues/273784) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `issues_full_text_search`. Disabled by default.
+> - Feature flag [`issues_full_text_search` enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/273784) in GitLab 14.10.
+> - Feature flag [`issues_full_text_search` enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/273784) in GitLab 15.2.
+
You can filter issues and merge requests by specific terms included in titles or descriptions.
- Syntax
@@ -88,6 +112,9 @@ You can filter issues and merge requests by specific terms included in titles or
- For performance reasons, terms shorter than 3 chars are ignored. For example: searching
issues for `included in titles` is same as `included titles`
- Search is limited to 4096 characters and 64 terms per query.
+ - When searching issues, partial matches are not allowed. For example: searching for `play` will
+ not return issues that have the word `display`. But variations of words will still match, so searching
+ for `displays` also returns issues that have the word `display`.
## Retrieve search results as feed
@@ -114,7 +141,7 @@ in your browser. To run a search from history:
## Removing search filters
-Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button or via <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd>.
+Individual filters can be removed by selecting the filter's (x) button or backspacing. The entire search filter can be cleared by selecting the search box's (x) button or via <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd>.
To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Control</kbd> + <kbd>⌫</kbd> keyboard combination can be used.
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index 2d753fa042a..bf233bef6a2 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html'
---
@@ -55,6 +55,8 @@ descriptions):
| <kbd>Command</kbd> + <kbd>i</kbd> | <kbd>Control</kbd> + <kbd>i</kbd> | Italicize the selected text (surround it with `_`). |
| <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>x</kbd> | <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>x</kbd> | Strike through the selected text (surround it with `~~`). |
| <kbd>Command</kbd> + <kbd>k</kbd> | <kbd>Control</kbd> + <kbd>k</kbd> | Add a link (surround the selected text with `[]()`). |
+| <kbd>Command</kbd> + <kbd>&#93;</kbd> | <kbd>Control</kbd> + <kbd>&#93;</kbd> | Indent list item. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/351924) in GitLab 15.3. |
+| <kbd>Command</kbd> + <kbd>&#91;</kbd> | <kbd>Control</kbd> + <kbd>&#91;</kbd> | Outdent list item. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/351924) in GitLab 15.3. |
The shortcuts for editing in text fields are always enabled, even if other
keyboard shortcuts are disabled.
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index f4683414dea..6a8184e9ca1 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Editor
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
type: reference
---
diff --git a/doc/user/ssh.md b/doc/user/ssh.md
index 913140d2a01..be76ce487b6 100644
--- a/doc/user/ssh.md
+++ b/doc/user/ssh.md
@@ -1,7 +1,7 @@
---
stage: Manage
group: Authentication and Authorization
-info: 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Use SSH keys to communicate with GitLab **(FREE)**
@@ -408,8 +408,8 @@ If you are using [EGit](https://www.eclipse.org/egit/), you can [add your SSH ke
## Use SSH on Microsoft Windows
-If you're running Windows 10, you can either use the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install)
-with [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install#update-to-wsl-2) which
+If you're running Windows 10, you can either use the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install)
+with [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install#update-to-wsl-2) which
has both `git` and `ssh` preinstalled, or install [Git for Windows](https://gitforwindows.org) to
use SSH through PowerShell.
@@ -421,7 +421,7 @@ as both have a different home directory:
You can either copy over the `.ssh/` directory to use the same key, or generate a key in each environment.
-If you're running Windows 11 and using [OpenSSH for Windows](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview), ensure the `HOME`
+If you're running Windows 11 and using [OpenSSH for Windows](https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview), ensure the `HOME`
environment variable is set correctly. Otherwise, your private SSH key might not be found.
Alternative tools include:
diff --git a/doc/user/tasks.md b/doc/user/tasks.md
index fce16b012d1..59453d27572 100644
--- a/doc/user/tasks.md
+++ b/doc/user/tasks.md
@@ -1,7 +1,7 @@
---
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tasks **(FREE)**
@@ -115,17 +115,24 @@ To change the assignee on a task:
1. In the issue description, in the **Tasks** section, select the title of the task you want to edit.
The task window opens.
1. Next to **Assignees**, select **Add assignees**.
-1. From the dropdown list, select the user(s) to add as an assignee.
+1. From the dropdown list, select the users to add as an assignee.
1. Select any area outside the dropdown list.
-## Set a start and due date
+## Assign labels to a task
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/365399) in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `work_items_mvc_2`. Disabled by default.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339756) in GitLab 15.5.
-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_mvc_2`.
-On GitLab.com, this feature is not available.
-This feature is not ready for production use.
+To add [labels](project/labels.md) to a task:
+
+1. In the issue description, in the **Tasks** section, select the title of the task you want to edit. The task window opens.
+1. Next to **Labels**, select **Add labels**.
+1. From the dropdown list, select the labels to add.
+1. Select any area outside the dropdown list.
+
+## Set a start and due date
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/365399) in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `work_items_mvc_2`. Disabled by default.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/365399) in GitLab 15.5.
You can set a [start and due date](project/issues/due_dates.md) on a task.
@@ -169,3 +176,21 @@ To set issue weight of a task:
The task window opens.
1. Next to **Weight**, enter a whole, positive number.
1. Select the close icon (**{close}**).
+
+## Add a task to an iteration **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362550) in GitLab 15.5.
+
+You can add a task to an [iteration](group/iterations/index.md).
+You can see the iteration title and period only when you view a task.
+
+Prerequisites:
+
+- You must have at least the Reporter role for the project.
+
+To add a task to an iteration:
+
+1. In the issue description, in the **Tasks** section, select the title of the task you want to edit.
+ The task window opens.
+1. Next to **Iteration**, select **Add to iteration**.
+1. From the dropdown list, select the iteration to be associated with the task.
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 0a120100c57..d7deda33a65 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -2,7 +2,7 @@
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/todos.html'
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# To-Do List **(FREE)**
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index 1b267a0569b..ef58d8aec66 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -1,7 +1,7 @@
---
stage: none
group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Updating to GitLab 13.2: Email confirmation issues
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 828c9a3c4b0..1b265e86dd4 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -2,7 +2,7 @@
type: howto
stage: Fulfillment
group: Utilization
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Storage usage quota **(FREE)**
@@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Namespace storage limit
Namespaces on GitLab SaaS have a storage limit. For more information, see our [pricing page](https://about.gitlab.com/pricing/).
-This limit is not visible on the Usage quotas page, but will be prior to [enforcement](#namespace-storage-limit-enforcement-schedule). Self-managed deployments are not affected.
+This limit is not visible on the Usage quotas page, but will be prior to the limit being [applied](#namespace-storage-limit-application-schedule). Self-managed deployments are not affected.
Storage types that add to the total namespace storage are:
@@ -26,30 +26,30 @@ Storage types that add to the total namespace storage are:
- Wiki
- Snippets
-If your total namespace storage exceeds the available namespace storage quota, all projects under the namespace are locked. A locked project will not be able to push to the repository, run pipelines and jobs, or build and push packages.
+If your total namespace storage exceeds the available namespace storage quota, all projects under the namespace are locked.
+A locked project cannot push to the repository, run pipelines and jobs, or build and push packages.
To prevent exceeding the namespace storage quota, you can:
-1. Reduce storage consumption by following the suggestions in the [Manage Your Storage Usage](#manage-your-storage-usage) section of this page.
-1. Apply for [GitLab for Education](https://about.gitlab.com/solutions/education/join/), [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/join/), or [GitLab for Startups](https://about.gitlab.com/solutions/startups/) if you meet the eligibility requirements.
-1. Consider using a [self-managed instance](../subscriptions/self_managed/index.md) of GitLab which does not have these limits on the free tier.
-1. [Purchase additional storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer) units at $60/year for 10GB of storage.
-1. [Start a trial](https://about.gitlab.com/free-trial/) or [upgrade to GitLab Premium or Ultimate](https://about.gitlab.com/pricing) which include higher limits and features that enable growing teams to ship faster without sacrificing on quality.
-1. [Talk to an expert](https://page.gitlab.com/usage_limits_help.html) to learn more about your options and ask questions.
+- Reduce storage consumption by following the suggestions in the [Manage Your Storage Usage](#manage-your-storage-usage) section of this page.
+- Apply for [GitLab for Education](https://about.gitlab.com/solutions/education/join/), [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/join/), or [GitLab for Startups](https://about.gitlab.com/solutions/startups/) if you meet the eligibility requirements.
+- Consider using a [self-managed instance](../subscriptions/self_managed/index.md) of GitLab which does not have these limits on the free tier.
+- [Purchase additional storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer) units at $60/year for 10GB of storage.
+- [Start a trial](https://about.gitlab.com/free-trial/) or [upgrade to GitLab Premium or Ultimate](https://about.gitlab.com/pricing) which include higher limits and features that enable growing teams to ship faster without sacrificing on quality.
+- [Talk to an expert](https://page.gitlab.com/usage_limits_help.html) to learn more about your options and ask questions.
-### Namespace storage limit enforcement schedule
+### Namespace storage limit application schedule
-Storage limits for GitLab SaaS Free tier namespaces will not be enforced prior to 2022-10-19. Storage limits for GitLab SaaS Paid tier namespaces will not be enforced for prior to 2023-02-15. Enforcement will not occur until all storage types are accurately measured, including deduplication of forks for [Git](https://gitlab.com/gitlab-org/gitlab/-/issues/371671) and [LFS](https://gitlab.com/gitlab-org/gitlab/-/issues/370242).
+Information on when namespace-level storage limits will be applied is available on these FAQ pages for the [Free](https://about.gitlab.com/pricing/faq-efficient-free-tier/#storage-limits-on-gitlab-saas-free-tier) and [Paid](https://about.gitlab.com/pricing/faq-paid-storage-transfer/) tier.
-Impacted users are notified via email and in-app notifications at least 60 days prior to enforcement.
-
-### Project storage limit
+## Project storage limit
Projects on GitLab SaaS have a 10GB storage limit on their Git repository and LFS storage.
-Once namespace-level storage limits are enforced, the project limit will be removed. A namespace has either a namespace-level storage limit or a project-level storage limit, but not both.
+After namespace-level storage limits are applied, the project limit will be removed. A namespace has either a namespace-level storage limit or a project-level storage limit, but not both.
-When a project's repository and LFS reaches the quota, the project is locked. You cannot push changes to a locked project. To monitor the size of each
-repository in a namespace, including a breakdown for each project, you can
+When a project's repository and LFS reaches the quota, the project is locked.
+You cannot push changes to a locked project. To monitor the size of each
+repository in a namespace, including a breakdown for each project,
[view storage usage](#view-storage-usage). To allow a project's repository and LFS to exceed the free quota
you must purchase additional storage. For more details, see [Excess storage usage](#excess-storage-usage).
@@ -66,7 +66,7 @@ Prerequisites:
1. From the left sidebar, select **Settings > Usage Quotas**.
1. Select the **Storage** tab.
-The statistics are displayed. Select any title to view details. The information on this page
+Select any title to view details. The information on this page
is updated every 90 minutes.
If your namespace shows `'Not applicable.'`, push a commit to any project in the
@@ -95,12 +95,11 @@ Depending on your role, you can also use the following methods to manage or redu
- [Reduce dependency proxy storage](packages/dependency_proxy/reduce_dependency_proxy_storage.md).
- [Reduce repository size](project/repository/reducing_the_repo_size_using_git.md).
- [Reduce container registry storage](packages/container_registry/reduce_container_registry_storage.md).
-- [Reduce container registry data transfers](packages/container_registry/reduce_container_registry_data_transfer.md).
- [Reduce wiki repository size](../administration/wikis/index.md#reduce-wiki-repository-size).
## Excess storage usage
-Excess storage usage is the amount that a project's repository and LFS exceeds the free storage quota. If no
+Excess storage usage is the amount that a project's repository and LFS exceeds the [project storage limit](#project-storage-limit). If no
purchased storage is available the project is locked. You cannot push changes to a locked project.
To unlock a project you must [purchase more storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer)
for the namespace. When the purchase is completed, locked projects are automatically unlocked. The
@@ -141,3 +140,9 @@ available decreases. All projects remain unlocked because 40 GB purchased storag
| Green | 11 GB | 1 GB | 10 GB | Not locked |
| Yellow | 5 GB | 0 GB | 10 GB | Not locked |
| **Totals** | **45 GB** | **10 GB** | - | - |
+
+## Manage your transfer usage
+
+Depending on your role, you can use the following methods to manage or reduce your transfer:
+
+- [Reduce Container Registry data transfers](packages/container_registry/reduce_container_registry_data_transfer.md).
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index 1c5a77c1f0c..d7e014672aa 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -1,7 +1,7 @@
---
stage: Manage
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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Workspace
@@ -26,7 +26,7 @@ everything you do as a GitLab administrator, including:
Our goal is to reach feature parity between SaaS and self-managed installations, with all
[Admin Area settings](/ee/user/admin_area/settings/index.md) moving to either:
-- Groups. Available in the Workspace, top-level group namespaces, and sub-groups.
+- Groups. Available in the Workspace, top-level group namespaces, and subgroups.
- Hardware Controls. For functionality that does not apply to groups, Hardware Controls are only
applicable to self-managed installations. There is one Hardware Controls section per installation.
diff --git a/glfm_specification/example_snapshots/examples_index.yml b/glfm_specification/example_snapshots/examples_index.yml
index fd3e350f58a..c0739912399 100644
--- a/glfm_specification/example_snapshots/examples_index.yml
+++ b/glfm_specification/example_snapshots/examples_index.yml
@@ -2012,75 +2012,75 @@
06_15_00__inlines__textual_content__003:
spec_txt_example_position: 673
source_specification: commonmark
-07_01_00__gitlab_specific_markdown__footnotes__001:
+07_01_00__gitlab_official_specification_markdown__footnotes__001:
spec_txt_example_position: 674
source_specification: gitlab
-07_02_00__gitlab_specific_markdown__task_list_items__001:
+07_02_00__gitlab_official_specification_markdown__task_list_items__001:
spec_txt_example_position: 675
source_specification: gitlab
-07_02_00__gitlab_specific_markdown__task_list_items__002:
+07_02_00__gitlab_official_specification_markdown__task_list_items__002:
spec_txt_example_position: 676
source_specification: gitlab
-07_02_00__gitlab_specific_markdown__task_list_items__003:
+07_02_00__gitlab_official_specification_markdown__task_list_items__003:
spec_txt_example_position: 677
source_specification: gitlab
-07_02_00__gitlab_specific_markdown__task_list_items__004:
+07_02_00__gitlab_official_specification_markdown__task_list_items__004:
spec_txt_example_position: 678
source_specification: gitlab
-07_03_00__gitlab_specific_markdown__front_matter__001:
+07_03_00__gitlab_official_specification_markdown__front_matter__001:
spec_txt_example_position: 679
source_specification: gitlab
-07_03_00__gitlab_specific_markdown__front_matter__002:
+07_03_00__gitlab_official_specification_markdown__front_matter__002:
spec_txt_example_position: 680
source_specification: gitlab
-07_03_00__gitlab_specific_markdown__front_matter__003:
+07_03_00__gitlab_official_specification_markdown__front_matter__003:
spec_txt_example_position: 681
source_specification: gitlab
-07_03_00__gitlab_specific_markdown__front_matter__004:
+07_03_00__gitlab_official_specification_markdown__front_matter__004:
spec_txt_example_position: 682
source_specification: gitlab
-07_03_00__gitlab_specific_markdown__front_matter__005:
+07_03_00__gitlab_official_specification_markdown__front_matter__005:
spec_txt_example_position: 683
source_specification: gitlab
-07_04_00__gitlab_specific_markdown__audio__001:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__001:
spec_txt_example_position: 684
source_specification: gitlab
-07_04_00__gitlab_specific_markdown__audio__002:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__002:
spec_txt_example_position: 685
source_specification: gitlab
-07_05_00__gitlab_specific_markdown__video__001:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__003:
spec_txt_example_position: 686
source_specification: gitlab
-07_05_00__gitlab_specific_markdown__video__002:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__004:
spec_txt_example_position: 687
source_specification: gitlab
-07_06_00__gitlab_specific_markdown__table_of_contents__001:
+08_01_00__gitlab_internal_extension_markdown__audio__001:
spec_txt_example_position: 688
source_specification: gitlab
-07_06_00__gitlab_specific_markdown__table_of_contents__002:
+08_01_00__gitlab_internal_extension_markdown__audio__002:
spec_txt_example_position: 689
source_specification: gitlab
-07_06_00__gitlab_specific_markdown__table_of_contents__003:
+08_02_00__gitlab_internal_extension_markdown__video__001:
spec_txt_example_position: 690
source_specification: gitlab
-07_06_00__gitlab_specific_markdown__table_of_contents__004:
+08_02_00__gitlab_internal_extension_markdown__video__002:
spec_txt_example_position: 691
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__001:
spec_txt_example_position: 692
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__002:
spec_txt_example_position: 693
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__003:
spec_txt_example_position: 694
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__004:
spec_txt_example_position: 695
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__005:
spec_txt_example_position: 696
source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__006:
spec_txt_example_position: 697
source_specification: gitlab
diff --git a/glfm_specification/example_snapshots/html.yml b/glfm_specification/example_snapshots/html.yml
index e683c37a7ac..ef2ba39f925 100644
--- a/glfm_specification/example_snapshots/html.yml
+++ b/glfm_specification/example_snapshots/html.yml
@@ -7638,7 +7638,7 @@
<p data-sourcepos="1:1-1:19" dir="auto">Multiple spaces</p>
wysiwyg: |-
<p>Multiple spaces</p>
-07_01_00__gitlab_specific_markdown__footnotes__001:
+07_01_00__gitlab_official_specification_markdown__footnotes__001:
canonical: |
<p>
footnote reference tag
@@ -7671,7 +7671,7 @@
wysiwyg: |-
<p>footnote reference tag <sup identifier="fortytwo">fortytwo</sup></p>
<div node="footnoteDefinition(paragraph(&quot;footnote text&quot;))" htmlattributes="[object Object]"><p>footnote text</p></div>
-07_02_00__gitlab_specific_markdown__task_list_items__001:
+07_02_00__gitlab_official_specification_markdown__task_list_items__001:
canonical: |
<ul>
<li>
@@ -7687,7 +7687,7 @@
</ul>
wysiwyg: |-
<ul start="1" parens="false" data-type="taskList"><li data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p>incomplete</p></div></li></ul>
-07_02_00__gitlab_specific_markdown__task_list_items__002:
+07_02_00__gitlab_official_specification_markdown__task_list_items__002:
canonical: |
<ul>
<li>
@@ -7703,7 +7703,7 @@
</ul>
wysiwyg: |-
<ul start="1" parens="false" data-type="taskList"><li data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p>completed</p></div></li></ul>
-07_02_00__gitlab_specific_markdown__task_list_items__003:
+07_02_00__gitlab_official_specification_markdown__task_list_items__003:
canonical: |
<ul>
<li>
@@ -7720,9 +7720,7 @@
<task-button></task-button><input type="checkbox" class="task-list-item-checkbox" data-inapplicable disabled> <s>inapplicable</s>
</li>
</ul>
- wysiwyg: |-
- <ul bullet="*"><li><p>[~] inapplicable</p></li></ul>
-07_02_00__gitlab_specific_markdown__task_list_items__004:
+07_02_00__gitlab_official_specification_markdown__task_list_items__004:
canonical: |
<ul>
<li>
@@ -7745,9 +7743,7 @@
<p data-sourcepos="3:3-3:20">text in loose list</p>
</li>
</ul>
- wysiwyg: |-
- Inapplicable task list items not yet implemented for WYSYWIG
-07_03_00__gitlab_specific_markdown__front_matter__001:
+07_03_00__gitlab_official_specification_markdown__front_matter__001:
canonical: |
<pre>
<code>
@@ -7761,7 +7757,7 @@
</div>
wysiwyg: |-
<pre language="yaml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>title: YAML front matter</code></pre>
-07_03_00__gitlab_specific_markdown__front_matter__002:
+07_03_00__gitlab_official_specification_markdown__front_matter__002:
canonical: |
<pre>
<code>
@@ -7775,7 +7771,7 @@
</div>
wysiwyg: |-
<pre language="toml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>title: TOML front matter</code></pre>
-07_03_00__gitlab_specific_markdown__front_matter__003:
+07_03_00__gitlab_official_specification_markdown__front_matter__003:
canonical: |
<pre>
<code>
@@ -7795,7 +7791,7 @@
<pre language="json" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>{
"title": "JSON front matter"
}</code></pre>
-07_03_00__gitlab_specific_markdown__front_matter__004:
+07_03_00__gitlab_official_specification_markdown__front_matter__004:
canonical: |
<p>text</p>
<hr>
@@ -7809,7 +7805,7 @@
<p>text</p>
<hr>
<h2>title: YAML front matter</h2>
-07_03_00__gitlab_specific_markdown__front_matter__005:
+07_03_00__gitlab_official_specification_markdown__front_matter__005:
canonical: |
<hr>
<h2>title: YAML front matter</h2>
@@ -7820,37 +7816,7 @@
wysiwyg: |-
<hr>
<h2>title: YAML front matter</h2>
-07_04_00__gitlab_specific_markdown__audio__001:
- canonical: |
- <p><audio src="audio.oga" title="audio title"></audio></p>
- static: |-
- <p data-sourcepos="1:1-1:33" dir="auto"><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio title"></audio><a href="audio.oga" target="_blank" rel="noopener noreferrer" title="Download 'audio title'">audio title</a></span></p>
- wysiwyg: |-
- <p><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio"></audio><a href="audio.oga">audio</a></span></p>
-07_04_00__gitlab_specific_markdown__audio__002:
- canonical: |
- <p><audio src="audio.oga" title="audio title"></audio></p>
- static: |-
- <p data-sourcepos="3:1-3:15" dir="auto"><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio title"></audio><a href="audio.oga" target="_blank" rel="noopener noreferrer" title="Download 'audio title'">audio title</a></span></p>
- wysiwyg: |-
- <pre>[audio]: audio.oga "audio title"</pre>
- <p><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio"></audio><a href="audio.oga">audio</a></span></p>
-07_05_00__gitlab_specific_markdown__video__001:
- canonical: |
- <p><video src="video.m4v" title="video title"></video></p>
- static: |-
- <p data-sourcepos="1:1-1:33" dir="auto"><span class="media-container video-container"><video src="video.m4v" controls="true" data-setup="{}" data-title="video title" width="400" preload="metadata"></video><a href="video.m4v" target="_blank" rel="noopener noreferrer" title="Download 'video title'">video title</a></span></p>
- wysiwyg: |-
- <p><span class="media-container video-container"><video src="video.m4v" controls="true" data-setup="{}" data-title="video"></video><a href="video.m4v">video</a></span></p>
-07_05_00__gitlab_specific_markdown__video__002:
- canonical: |
- <p><video src="video.mov" title="video title"></video></p>
- static: |-
- <p data-sourcepos="3:1-3:15" dir="auto"><span class="media-container video-container"><video src="video.mov" controls="true" data-setup="{}" data-title="video title" width="400" preload="metadata"></video><a href="video.mov" target="_blank" rel="noopener noreferrer" title="Download 'video title'">video title</a></span></p>
- wysiwyg: |-
- <pre>[video]: video.mov "video title"</pre>
- <p><span class="media-container video-container"><video src="video.mov" controls="true" data-setup="{}" data-title="video"></video><a href="video.mov">video</a></span></p>
-07_06_00__gitlab_specific_markdown__table_of_contents__001:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__001:
canonical: |
<nav>
<ul>
@@ -7874,7 +7840,7 @@
<div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
-07_06_00__gitlab_specific_markdown__table_of_contents__002:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__002:
canonical: |
<nav>
<ul>
@@ -7898,7 +7864,7 @@
<div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
-07_06_00__gitlab_specific_markdown__table_of_contents__003:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__003:
canonical: |
<p>[[<em>TOC</em>]]text</p>
<p>text[TOC]</p>
@@ -7912,7 +7878,7 @@
text</p>
<p>text
[TOC]</p>
-07_06_00__gitlab_specific_markdown__table_of_contents__004:
+07_04_00__gitlab_official_specification_markdown__table_of_contents__004:
canonical: |
<nav>
<ul>
@@ -7927,45 +7893,63 @@
wysiwyg: |-
<div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
<h1>Heading 1</h1>
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
+08_01_00__gitlab_internal_extension_markdown__audio__001:
+ canonical: |
+ <p><audio src="audio.oga" title="audio title"></audio></p>
+ static: |-
+ <p data-sourcepos="1:1-1:33" dir="auto"><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio title"></audio><a href="audio.oga" target="_blank" rel="noopener noreferrer" title="Download 'audio title'">audio title</a></span></p>
+ wysiwyg: |-
+ <p><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio"></audio><a href="audio.oga">audio</a></span></p>
+08_01_00__gitlab_internal_extension_markdown__audio__002:
+ canonical: |
+ <p><audio src="audio.oga" title="audio title"></audio></p>
+ static: |-
+ <p data-sourcepos="3:1-3:15" dir="auto"><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio title"></audio><a href="audio.oga" target="_blank" rel="noopener noreferrer" title="Download 'audio title'">audio title</a></span></p>
+ wysiwyg: |-
+ <pre>[audio]: audio.oga "audio title"</pre>
+ <p><span class="media-container audio-container"><audio src="audio.oga" controls="true" data-setup="{}" data-title="audio"></audio><a href="audio.oga">audio</a></span></p>
+08_02_00__gitlab_internal_extension_markdown__video__001:
+ canonical: |
+ <p><video src="video.m4v" title="video title"></video></p>
+ static: |-
+ <p data-sourcepos="1:1-1:33" dir="auto"><span class="media-container video-container"><video src="video.m4v" controls="true" data-setup="{}" data-title="video title" width="400" preload="metadata"></video><a href="video.m4v" target="_blank" rel="noopener noreferrer" title="Download 'video title'">video title</a></span></p>
+ wysiwyg: |-
+ <p><span class="media-container video-container"><video src="video.m4v" controls="true" data-setup="{}" data-title="video"></video><a href="video.m4v">video</a></span></p>
+08_02_00__gitlab_internal_extension_markdown__video__002:
+ canonical: |
+ <p><video src="video.mov" title="video title"></video></p>
+ static: |-
+ <p data-sourcepos="3:1-3:15" dir="auto"><span class="media-container video-container"><video src="video.mov" controls="true" data-setup="{}" data-title="video title" width="400" preload="metadata"></video><a href="video.mov" target="_blank" rel="noopener noreferrer" title="Download 'video title'">video title</a></span></p>
+ wysiwyg: |-
+ <pre>[video]: video.mov "video title"</pre>
+ <p><span class="media-container video-container"><video src="video.mov" controls="true" data-setup="{}" data-title="video"></video><a href="video.mov">video</a></span></p>
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__001:
canonical: |
<p><a href="groups-test-file">groups-test-file</a></p>
static: |-
<p data-sourcepos="1:1-1:45" dir="auto"><a href="/groups/glfm_group/-/uploads/groups-test-file" data-canonical-src="/uploads/groups-test-file" data-link="true" class="gfm">groups-test-file</a></p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__002:
canonical: |
<p><a href="projects-test-file">projects-test-file</a></p>
static: |-
<p data-sourcepos="1:1-1:40" dir="auto"><a href="/glfm_group/glfm_project/-/blob/master/projects-test-file">projects-test-file</a></p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__003:
canonical: |
<p>This project snippet ID reference IS filtered: $88888</p>
static: |-
<p data-sourcepos="1:1-1:53" dir="auto">This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888" data-reference-type="snippet" data-original="$88888" data-link="false" data-link-reference="false" data-project="77777" data-snippet="88888" data-container="body" data-placement="top" title="glfm_project_snippet" class="gfm gfm-snippet has-tooltip">$88888</a></p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__004:
canonical: |
<p>This personal snippet ID reference is not filtered: $99999</p>
static: |-
<p data-sourcepos="1:1-1:58" dir="auto">This personal snippet ID reference is not filtered: $99999</p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__005:
canonical: |
<p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
static: |-
<p data-sourcepos="1:1-1:50" dir="auto"><a href="/glfm_group/glfm_project/-/wikis/project-wikis-test-file" data-canonical-src="project-wikis-test-file">project-wikis-test-file</a></p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__006:
canonical: |
<p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
static: |-
<p data-sourcepos="1:1-1:46" dir="auto"><a href="/groups/glfm_group/-/wikis/group-wikis-test-file" data-canonical-src="group-wikis-test-file">group-wikis-test-file</a></p>
- wysiwyg: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
diff --git a/glfm_specification/example_snapshots/markdown.yml b/glfm_specification/example_snapshots/markdown.yml
index 9af824e120f..867108a6cc5 100644
--- a/glfm_specification/example_snapshots/markdown.yml
+++ b/glfm_specification/example_snapshots/markdown.yml
@@ -2189,87 +2189,87 @@
Foo χÏῆν
06_15_00__inlines__textual_content__003: |
Multiple spaces
-07_01_00__gitlab_specific_markdown__footnotes__001: |
+07_01_00__gitlab_official_specification_markdown__footnotes__001: |
footnote reference tag [^fortytwo]
[^fortytwo]: footnote text
-07_02_00__gitlab_specific_markdown__task_list_items__001: |
+07_02_00__gitlab_official_specification_markdown__task_list_items__001: |
- [ ] incomplete
-07_02_00__gitlab_specific_markdown__task_list_items__002: |
+07_02_00__gitlab_official_specification_markdown__task_list_items__002: |
- [x] completed
-07_02_00__gitlab_specific_markdown__task_list_items__003: |
+07_02_00__gitlab_official_specification_markdown__task_list_items__003: |
- [~] inapplicable
-07_02_00__gitlab_specific_markdown__task_list_items__004: |
+07_02_00__gitlab_official_specification_markdown__task_list_items__004: |
- [~] inapplicable
text in loose list
-07_03_00__gitlab_specific_markdown__front_matter__001: |
+07_03_00__gitlab_official_specification_markdown__front_matter__001: |
---
title: YAML front matter
---
-07_03_00__gitlab_specific_markdown__front_matter__002: |
+07_03_00__gitlab_official_specification_markdown__front_matter__002: |
+++
title: TOML front matter
+++
-07_03_00__gitlab_specific_markdown__front_matter__003: |
+07_03_00__gitlab_official_specification_markdown__front_matter__003: |
;;;
{
"title": "JSON front matter"
}
;;;
-07_03_00__gitlab_specific_markdown__front_matter__004: |
+07_03_00__gitlab_official_specification_markdown__front_matter__004: |
text
---
title: YAML front matter
---
-07_03_00__gitlab_specific_markdown__front_matter__005: |2
+07_03_00__gitlab_official_specification_markdown__front_matter__005: |2
---
title: YAML front matter
---
-07_04_00__gitlab_specific_markdown__audio__001: |
- ![audio](audio.oga "audio title")
-07_04_00__gitlab_specific_markdown__audio__002: |
- [audio]: audio.oga "audio title"
-
- ![audio][audio]
-07_05_00__gitlab_specific_markdown__video__001: |
- ![video](video.m4v "video title")
-07_05_00__gitlab_specific_markdown__video__002: |
- [video]: video.mov "video title"
-
- ![video][video]
-07_06_00__gitlab_specific_markdown__table_of_contents__001: |
+07_04_00__gitlab_official_specification_markdown__table_of_contents__001: |
[TOC]
# Heading 1
## Heading 2
-07_06_00__gitlab_specific_markdown__table_of_contents__002: |
+07_04_00__gitlab_official_specification_markdown__table_of_contents__002: |
[[_TOC_]]
# Heading 1
## Heading 2
-07_06_00__gitlab_specific_markdown__table_of_contents__003: |
+07_04_00__gitlab_official_specification_markdown__table_of_contents__003: |
[[_TOC_]]
text
text
[TOC]
-07_06_00__gitlab_specific_markdown__table_of_contents__004: |2
+07_04_00__gitlab_official_specification_markdown__table_of_contents__004: |2
[[_TOC_]]
# Heading 1
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001: |
+08_01_00__gitlab_internal_extension_markdown__audio__001: |
+ ![audio](audio.oga "audio title")
+08_01_00__gitlab_internal_extension_markdown__audio__002: |
+ [audio]: audio.oga "audio title"
+
+ ![audio][audio]
+08_02_00__gitlab_internal_extension_markdown__video__001: |
+ ![video](video.m4v "video title")
+08_02_00__gitlab_internal_extension_markdown__video__002: |
+ [video]: video.mov "video title"
+
+ ![video][video]
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__001: |
[groups-test-file](/uploads/groups-test-file)
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002: |
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__002: |
[projects-test-file](projects-test-file)
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003: |
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__003: |
This project snippet ID reference IS filtered: $88888
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004: |
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__004: |
This personal snippet ID reference is not filtered: $99999
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005: |
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__005: |
[project-wikis-test-file](project-wikis-test-file)
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006: |
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__006: |
[group-wikis-test-file](group-wikis-test-file)
diff --git a/glfm_specification/example_snapshots/prosemirror_json.yml b/glfm_specification/example_snapshots/prosemirror_json.yml
index 1051b5ccdd7..de54518a574 100644
--- a/glfm_specification/example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/example_snapshots/prosemirror_json.yml
@@ -20561,7 +20561,7 @@
}
]
}
-07_01_00__gitlab_specific_markdown__footnotes__001: |-
+07_01_00__gitlab_official_specification_markdown__footnotes__001: |-
{
"type": "doc",
"content": [
@@ -20601,7 +20601,7 @@
}
]
}
-07_02_00__gitlab_specific_markdown__task_list_items__001: |-
+07_02_00__gitlab_official_specification_markdown__task_list_items__001: |-
{
"type": "doc",
"content": [
@@ -20634,7 +20634,7 @@
}
]
}
-07_02_00__gitlab_specific_markdown__task_list_items__002: |-
+07_02_00__gitlab_official_specification_markdown__task_list_items__002: |-
{
"type": "doc",
"content": [
@@ -20667,11 +20667,7 @@
}
]
}
-07_02_00__gitlab_specific_markdown__task_list_items__003: |-
- Inapplicable task list items not yet implemented for WYSYWIG
-07_02_00__gitlab_specific_markdown__task_list_items__004: |-
- Inapplicable task list items not yet implemented for WYSYWIG
-07_03_00__gitlab_specific_markdown__front_matter__001: |-
+07_03_00__gitlab_official_specification_markdown__front_matter__001: |-
{
"type": "doc",
"content": [
@@ -20691,7 +20687,7 @@
}
]
}
-07_03_00__gitlab_specific_markdown__front_matter__002: |-
+07_03_00__gitlab_official_specification_markdown__front_matter__002: |-
{
"type": "doc",
"content": [
@@ -20711,7 +20707,7 @@
}
]
}
-07_03_00__gitlab_specific_markdown__front_matter__003: |-
+07_03_00__gitlab_official_specification_markdown__front_matter__003: |-
{
"type": "doc",
"content": [
@@ -20731,7 +20727,7 @@
}
]
}
-07_03_00__gitlab_specific_markdown__front_matter__004: |-
+07_03_00__gitlab_official_specification_markdown__front_matter__004: |-
{
"type": "doc",
"content": [
@@ -20761,7 +20757,7 @@
}
]
}
-07_03_00__gitlab_specific_markdown__front_matter__005: |-
+07_03_00__gitlab_official_specification_markdown__front_matter__005: |-
{
"type": "doc",
"content": [
@@ -20782,61 +20778,73 @@
}
]
}
-07_04_00__gitlab_specific_markdown__audio__001: |-
+07_04_00__gitlab_official_specification_markdown__table_of_contents__001: |-
{
"type": "doc",
"content": [
{
- "type": "paragraph",
+ "type": "tableOfContents"
+ },
+ {
+ "type": "heading",
+ "attrs": {
+ "level": 1
+ },
"content": [
{
- "type": "audio",
- "attrs": {
- "uploading": false,
- "src": "audio.oga",
- "canonicalSrc": "audio.oga",
- "alt": "audio"
- }
+ "type": "text",
+ "text": "Heading 1"
+ }
+ ]
+ },
+ {
+ "type": "heading",
+ "attrs": {
+ "level": 2
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "Heading 2"
}
]
}
]
}
-07_04_00__gitlab_specific_markdown__audio__002: |-
+07_04_00__gitlab_official_specification_markdown__table_of_contents__002: |-
{
"type": "doc",
"content": [
{
- "type": "referenceDefinition",
+ "type": "tableOfContents"
+ },
+ {
+ "type": "heading",
"attrs": {
- "identifier": "audio",
- "url": "audio.oga",
- "title": "audio title"
+ "level": 1
},
"content": [
{
"type": "text",
- "text": "[audio]: audio.oga \"audio title\""
+ "text": "Heading 1"
}
]
},
{
- "type": "paragraph",
+ "type": "heading",
+ "attrs": {
+ "level": 2
+ },
"content": [
{
- "type": "audio",
- "attrs": {
- "uploading": false,
- "src": "audio.oga",
- "canonicalSrc": "audio",
- "alt": "audio"
- }
+ "type": "text",
+ "text": "Heading 2"
}
]
}
]
}
-07_05_00__gitlab_specific_markdown__video__001: |-
+07_04_00__gitlab_official_specification_markdown__table_of_contents__003: |-
{
"type": "doc",
"content": [
@@ -20844,33 +20852,21 @@
"type": "paragraph",
"content": [
{
- "type": "video",
- "attrs": {
- "uploading": false,
- "src": "video.m4v",
- "canonicalSrc": "video.m4v",
- "alt": "video"
- }
- }
- ]
- }
- ]
- }
-07_05_00__gitlab_specific_markdown__video__002: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "referenceDefinition",
- "attrs": {
- "identifier": "video",
- "url": "video.mov",
- "title": "video title"
- },
- "content": [
+ "type": "text",
+ "text": "[["
+ },
{
"type": "text",
- "text": "[video]: video.mov \"video title\""
+ "marks": [
+ {
+ "type": "italic"
+ }
+ ],
+ "text": "TOC"
+ },
+ {
+ "type": "text",
+ "text": "]]\ntext"
}
]
},
@@ -20878,19 +20874,14 @@
"type": "paragraph",
"content": [
{
- "type": "video",
- "attrs": {
- "uploading": false,
- "src": "video.mov",
- "canonicalSrc": "video",
- "alt": "video"
- }
+ "type": "text",
+ "text": "text\n[TOC]"
}
]
}
]
}
-07_06_00__gitlab_specific_markdown__table_of_contents__001: |-
+07_04_00__gitlab_official_specification_markdown__table_of_contents__004: |-
{
"type": "doc",
"content": [
@@ -20908,55 +20899,64 @@
"text": "Heading 1"
}
]
- },
+ }
+ ]
+ }
+08_01_00__gitlab_internal_extension_markdown__audio__001: |-
+ {
+ "type": "doc",
+ "content": [
{
- "type": "heading",
- "attrs": {
- "level": 2
- },
+ "type": "paragraph",
"content": [
{
- "type": "text",
- "text": "Heading 2"
+ "type": "audio",
+ "attrs": {
+ "uploading": false,
+ "src": "audio.oga",
+ "canonicalSrc": "audio.oga",
+ "alt": "audio"
+ }
}
]
}
]
}
-07_06_00__gitlab_specific_markdown__table_of_contents__002: |-
+08_01_00__gitlab_internal_extension_markdown__audio__002: |-
{
"type": "doc",
"content": [
{
- "type": "tableOfContents"
- },
- {
- "type": "heading",
+ "type": "referenceDefinition",
"attrs": {
- "level": 1
+ "identifier": "audio",
+ "url": "audio.oga",
+ "title": "audio title"
},
"content": [
{
"type": "text",
- "text": "Heading 1"
+ "text": "[audio]: audio.oga \"audio title\""
}
]
},
{
- "type": "heading",
- "attrs": {
- "level": 2
- },
+ "type": "paragraph",
"content": [
{
- "type": "text",
- "text": "Heading 2"
+ "type": "audio",
+ "attrs": {
+ "uploading": false,
+ "src": "audio.oga",
+ "canonicalSrc": "audio",
+ "alt": "audio"
+ }
}
]
}
]
}
-07_06_00__gitlab_specific_markdown__table_of_contents__003: |-
+08_02_00__gitlab_internal_extension_markdown__video__001: |-
{
"type": "doc",
"content": [
@@ -20964,65 +20964,49 @@
"type": "paragraph",
"content": [
{
- "type": "text",
- "text": "[["
- },
- {
- "type": "text",
- "marks": [
- {
- "type": "italic"
- }
- ],
- "text": "TOC"
- },
- {
- "type": "text",
- "text": "]]\ntext"
- }
- ]
- },
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "text": "text\n[TOC]"
+ "type": "video",
+ "attrs": {
+ "uploading": false,
+ "src": "video.m4v",
+ "canonicalSrc": "video.m4v",
+ "alt": "video"
+ }
}
]
}
]
}
-07_06_00__gitlab_specific_markdown__table_of_contents__004: |-
+08_02_00__gitlab_internal_extension_markdown__video__002: |-
{
"type": "doc",
"content": [
{
- "type": "tableOfContents"
- },
- {
- "type": "heading",
+ "type": "referenceDefinition",
"attrs": {
- "level": 1
+ "identifier": "video",
+ "url": "video.mov",
+ "title": "video title"
},
"content": [
{
"type": "text",
- "text": "Heading 1"
+ "text": "[video]: video.mov \"video title\""
+ }
+ ]
+ },
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "video",
+ "attrs": {
+ "uploading": false,
+ "src": "video.mov",
+ "canonicalSrc": "video",
+ "alt": "video"
+ }
}
]
}
]
}
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006: |-
- Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
diff --git a/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md b/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md
new file mode 100644
index 00000000000..1702761563e
--- /dev/null
+++ b/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.md
@@ -0,0 +1,10226 @@
+---
+title: GitHub Flavored Markdown Spec
+version: 0.29
+date: '2019-04-06'
+license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
+...
+
+# Introduction
+
+## What is GitHub Flavored Markdown?
+
+GitHub Flavored Markdown, often shortened as GFM, is the dialect of Markdown
+that is currently supported for user content on GitHub.com and GitHub
+Enterprise.
+
+This formal specification, based on the CommonMark Spec, defines the syntax and
+semantics of this dialect.
+
+GFM is a strict superset of CommonMark. All the features which are supported in
+GitHub user content and that are not specified on the original CommonMark Spec
+are hence known as **extensions**, and highlighted as such.
+
+While GFM supports a wide range of inputs, it's worth noting that GitHub.com
+and GitHub Enterprise perform additional post-processing and sanitization after
+GFM is converted to HTML to ensure security and consistency of the website.
+
+## What is Markdown?
+
+Markdown is a plain text format for writing structured documents,
+based on conventions for indicating formatting in email
+and usenet posts. It was developed by John Gruber (with
+help from Aaron Swartz) and released in 2004 in the form of a
+[syntax description](http://daringfireball.net/projects/markdown/syntax)
+and a Perl script (`Markdown.pl`) for converting Markdown to
+HTML. In the next decade, dozens of implementations were
+developed in many languages. Some extended the original
+Markdown syntax with conventions for footnotes, tables, and
+other document elements. Some allowed Markdown documents to be
+rendered in formats other than HTML. Websites like Reddit,
+StackOverflow, and GitHub had millions of people using Markdown.
+And Markdown started to be used beyond the web, to author books,
+articles, slide shows, letters, and lecture notes.
+
+What distinguishes Markdown from many other lightweight markup
+syntaxes, which are often easier to write, is its readability.
+As Gruber writes:
+
+> The overriding design goal for Markdown's formatting syntax is
+> to make it as readable as possible. The idea is that a
+> Markdown-formatted document should be publishable as-is, as
+> plain text, without looking like it's been marked up with tags
+> or formatting instructions.
+> (<http://daringfireball.net/projects/markdown/>)
+
+The point can be illustrated by comparing a sample of
+[AsciiDoc](http://www.methods.co.nz/asciidoc/) with
+an equivalent sample of Markdown. Here is a sample of
+AsciiDoc from the AsciiDoc manual:
+
+```
+1. List item one.
++
+List item one continued with a second paragraph followed by an
+Indented block.
++
+.................
+$ ls *.sh
+$ mv *.sh ~/tmp
+.................
++
+List item continued with a third paragraph.
+
+2. List item two continued with an open block.
++
+--
+This paragraph is part of the preceding list item.
+
+a. This list is nested and does not require explicit item
+continuation.
++
+This paragraph is part of the preceding list item.
+
+b. List item b.
+
+This paragraph belongs to item two of the outer list.
+--
+```
+
+And here is the equivalent in Markdown:
+```
+1. List item one.
+
+ List item one continued with a second paragraph followed by an
+ Indented block.
+
+ $ ls *.sh
+ $ mv *.sh ~/tmp
+
+ List item continued with a third paragraph.
+
+2. List item two continued with an open block.
+
+ This paragraph is part of the preceding list item.
+
+ 1. This list is nested and does not require explicit item continuation.
+
+ This paragraph is part of the preceding list item.
+
+ 2. List item b.
+
+ This paragraph belongs to item two of the outer list.
+```
+
+The AsciiDoc version is, arguably, easier to write. You don't need
+to worry about indentation. But the Markdown version is much easier
+to read. The nesting of list items is apparent to the eye in the
+source, not just in the processed document.
+
+## Why is a spec needed?
+
+John Gruber's [canonical description of Markdown's
+syntax](http://daringfireball.net/projects/markdown/syntax)
+does not specify the syntax unambiguously. Here are some examples of
+questions it does not answer:
+
+1. How much indentation is needed for a sublist? The spec says that
+ continuation paragraphs need to be indented four spaces, but is
+ not fully explicit about sublists. It is natural to think that
+ they, too, must be indented four spaces, but `Markdown.pl` does
+ not require that. This is hardly a "corner case," and divergences
+ between implementations on this issue often lead to surprises for
+ users in real documents. (See [this comment by John
+ Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).)
+
+2. Is a blank line needed before a block quote or heading?
+ Most implementations do not require the blank line. However,
+ this can lead to unexpected results in hard-wrapped text, and
+ also to ambiguities in parsing (note that some implementations
+ put the heading inside the blockquote, while others do not).
+ (John Gruber has also spoken [in favor of requiring the blank
+ lines](http://article.gmane.org/gmane.text.markdown.general/2146).)
+
+3. Is a blank line needed before an indented code block?
+ (`Markdown.pl` requires it, but this is not mentioned in the
+ documentation, and some implementations do not require it.)
+
+ ``` markdown
+ paragraph
+ code?
+ ```
+
+4. What is the exact rule for determining when list items get
+ wrapped in `<p>` tags? Can a list be partially "loose" and partially
+ "tight"? What should we do with a list like this?
+
+ ``` markdown
+ 1. one
+
+ 2. two
+ 3. three
+ ```
+
+ Or this?
+
+ ``` markdown
+ 1. one
+ - a
+
+ - b
+ 2. two
+ ```
+
+ (There are some relevant comments by John Gruber
+ [here](http://article.gmane.org/gmane.text.markdown.general/2554).)
+
+5. Can list markers be indented? Can ordered list markers be right-aligned?
+
+ ``` markdown
+ 8. item 1
+ 9. item 2
+ 10. item 2a
+ ```
+
+6. Is this one list with a thematic break in its second item,
+ or two lists separated by a thematic break?
+
+ ``` markdown
+ * a
+ * * * * *
+ * b
+ ```
+
+7. When list markers change from numbers to bullets, do we have
+ two lists or one? (The Markdown syntax description suggests two,
+ but the perl scripts and many other implementations produce one.)
+
+ ``` markdown
+ 1. fee
+ 2. fie
+ - foe
+ - fum
+ ```
+
+8. What are the precedence rules for the markers of inline structure?
+ For example, is the following a valid link, or does the code span
+ take precedence ?
+
+ ``` markdown
+ [a backtick (`)](/url) and [another backtick (`)](/url).
+ ```
+
+9. What are the precedence rules for markers of emphasis and strong
+ emphasis? For example, how should the following be parsed?
+
+ ``` markdown
+ *foo *bar* baz*
+ ```
+
+10. What are the precedence rules between block-level and inline-level
+ structure? For example, how should the following be parsed?
+
+ ``` markdown
+ - `a long code span can contain a hyphen like this
+ - and it can screw things up`
+ ```
+
+11. Can list items include section headings? (`Markdown.pl` does not
+ allow this, but does allow blockquotes to include headings.)
+
+ ``` markdown
+ - # Heading
+ ```
+
+12. Can list items be empty?
+
+ ``` markdown
+ * a
+ *
+ * b
+ ```
+
+13. Can link references be defined inside block quotes or list items?
+
+ ``` markdown
+ > Blockquote [foo].
+ >
+ > [foo]: /url
+ ```
+
+14. If there are multiple definitions for the same reference, which takes
+ precedence?
+
+ ``` markdown
+ [foo]: /url1
+ [foo]: /url2
+
+ [foo][]
+ ```
+
+In the absence of a spec, early implementers consulted `Markdown.pl`
+to resolve these ambiguities. But `Markdown.pl` was quite buggy, and
+gave manifestly bad results in many cases, so it was not a
+satisfactory replacement for a spec.
+
+Because there is no unambiguous spec, implementations have diverged
+considerably. As a result, users are often surprised to find that
+a document that renders one way on one system (say, a GitHub wiki)
+renders differently on another (say, converting to docbook using
+pandoc). To make matters worse, because nothing in Markdown counts
+as a "syntax error," the divergence often isn't discovered right away.
+
+## About this document
+
+This document attempts to specify Markdown syntax unambiguously.
+It contains many examples with side-by-side Markdown and
+HTML. These are intended to double as conformance tests. An
+accompanying script `spec_tests.py` can be used to run the tests
+against any Markdown program:
+
+ python test/spec_tests.py --spec spec.txt --program PROGRAM
+
+Since this document describes how Markdown is to be parsed into
+an abstract syntax tree, it would have made sense to use an abstract
+representation of the syntax tree instead of HTML. But HTML is capable
+of representing the structural distinctions we need to make, and the
+choice of HTML for the tests makes it possible to run the tests against
+an implementation without writing an abstract syntax tree renderer.
+
+This document is generated from a text file, `spec.txt`, written
+in Markdown with a small extension for the side-by-side tests.
+The script `tools/makespec.py` can be used to convert `spec.txt` into
+HTML or CommonMark (which can then be converted into other formats).
+
+In the examples, the `→` character is used to represent tabs.
+
+# Preliminaries
+
+## Characters and lines
+
+Any sequence of [characters] is a valid CommonMark
+document.
+
+A [character](@) is a Unicode code point. Although some
+code points (for example, combining accents) do not correspond to
+characters in an intuitive sense, all code points count as characters
+for purposes of this spec.
+
+This spec does not specify an encoding; it thinks of lines as composed
+of [characters] rather than bytes. A conforming parser may be limited
+to a certain encoding.
+
+A [line](@) is a sequence of zero or more [characters]
+other than newline (`U+000A`) or carriage return (`U+000D`),
+followed by a [line ending] or by the end of file.
+
+A [line ending](@) is a newline (`U+000A`), a carriage return
+(`U+000D`) not followed by a newline, or a carriage return and a
+following newline.
+
+A line containing no characters, or a line containing only spaces
+(`U+0020`) or tabs (`U+0009`), is called a [blank line](@).
+
+The following definitions of character classes will be used in this spec:
+
+A [whitespace character](@) is a space
+(`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`),
+form feed (`U+000C`), or carriage return (`U+000D`).
+
+[Whitespace](@) is a sequence of one or more [whitespace
+characters].
+
+A [Unicode whitespace character](@) is
+any code point in the Unicode `Zs` general category, or a tab (`U+0009`),
+carriage return (`U+000D`), newline (`U+000A`), or form feed
+(`U+000C`).
+
+[Unicode whitespace](@) is a sequence of one
+or more [Unicode whitespace characters].
+
+A [space](@) is `U+0020`.
+
+A [non-whitespace character](@) is any character
+that is not a [whitespace character].
+
+An [ASCII punctuation character](@)
+is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`,
+`*`, `+`, `,`, `-`, `.`, `/` (U+0021–2F),
+`:`, `;`, `<`, `=`, `>`, `?`, `@` (U+003A–0040),
+`[`, `\`, `]`, `^`, `_`, `` ` `` (U+005B–0060),
+`{`, `|`, `}`, or `~` (U+007B–007E).
+
+A [punctuation character](@) is an [ASCII
+punctuation character] or anything in
+the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
+
+## Tabs
+
+Tabs in lines are not expanded to [spaces]. However,
+in contexts where whitespace helps to define block structure,
+tabs behave as if they were replaced by spaces with a tab stop
+of 4 characters.
+
+Thus, for example, a tab can be used instead of four spaces
+in an indented code block. (Note, however, that internal
+tabs are passed through as literal tabs, not expanded to
+spaces.)
+
+```````````````````````````````` example
+→foo→baz→→bim
+.
+<pre><code>foo→baz→→bim
+</code></pre>
+````````````````````````````````
+
+```````````````````````````````` example
+ →foo→baz→→bim
+.
+<pre><code>foo→baz→→bim
+</code></pre>
+````````````````````````````````
+
+```````````````````````````````` example
+ a→a
+ á½â†’a
+.
+<pre><code>a→a
+á½â†’a
+</code></pre>
+````````````````````````````````
+
+In the following example, a continuation paragraph of a list
+item is indented with a tab; this has exactly the same effect
+as indentation with four spaces would:
+
+```````````````````````````````` example
+ - foo
+
+→bar
+.
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+````````````````````````````````
+
+```````````````````````````````` example
+- foo
+
+→→bar
+.
+<ul>
+<li>
+<p>foo</p>
+<pre><code> bar
+</code></pre>
+</li>
+</ul>
+````````````````````````````````
+
+Normally the `>` that begins a block quote may be followed
+optionally by a space, which is not considered part of the
+content. In the following case `>` is followed by a tab,
+which is treated as if it were expanded into three spaces.
+Since one of these spaces is considered part of the
+delimiter, `foo` is considered to be indented six spaces
+inside the block quote context, so we get an indented
+code block starting with two spaces.
+
+```````````````````````````````` example
+>→→foo
+.
+<blockquote>
+<pre><code> foo
+</code></pre>
+</blockquote>
+````````````````````````````````
+
+```````````````````````````````` example
+-→→foo
+.
+<ul>
+<li>
+<pre><code> foo
+</code></pre>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ foo
+→bar
+.
+<pre><code>foo
+bar
+</code></pre>
+````````````````````````````````
+
+```````````````````````````````` example
+ - foo
+ - bar
+→ - baz
+.
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+```````````````````````````````` example
+#→Foo
+.
+<h1>Foo</h1>
+````````````````````````````````
+
+```````````````````````````````` example
+*→*→*→
+.
+<hr />
+````````````````````````````````
+
+
+## Insecure characters
+
+For security reasons, the Unicode character `U+0000` must be replaced
+with the REPLACEMENT CHARACTER (`U+FFFD`).
+
+# Blocks and inlines
+
+We can think of a document as a sequence of
+[blocks](@)---structural elements like paragraphs, block
+quotations, lists, headings, rules, and code blocks. Some blocks (like
+block quotes and list items) contain other blocks; others (like
+headings and paragraphs) contain [inline](@) content---text,
+links, emphasized text, images, code spans, and so on.
+
+## Precedence
+
+Indicators of block structure always take precedence over indicators
+of inline structure. So, for example, the following is a list with
+two items, not a list with one item containing a code span:
+
+```````````````````````````````` example
+- `one
+- two`
+.
+<ul>
+<li>`one</li>
+<li>two`</li>
+</ul>
+````````````````````````````````
+
+
+This means that parsing can proceed in two steps: first, the block
+structure of the document can be discerned; second, text lines inside
+paragraphs, headings, and other block constructs can be parsed for inline
+structure. The second step requires information about link reference
+definitions that will be available only at the end of the first
+step. Note that the first step requires processing lines in sequence,
+but the second can be parallelized, since the inline parsing of
+one block element does not affect the inline parsing of any other.
+
+## Container blocks and leaf blocks
+
+We can divide blocks into two types:
+[container blocks](@),
+which can contain other blocks, and [leaf blocks](@),
+which cannot.
+
+# Leaf blocks
+
+This section describes the different kinds of leaf block that make up a
+Markdown document.
+
+## Thematic breaks
+
+A line consisting of 0-3 spaces of indentation, followed by a sequence
+of three or more matching `-`, `_`, or `*` characters, each followed
+optionally by any number of spaces or tabs, forms a
+[thematic break](@).
+
+```````````````````````````````` example
+***
+---
+___
+.
+<hr />
+<hr />
+<hr />
+````````````````````````````````
+
+
+Wrong characters:
+
+```````````````````````````````` example
++++
+.
+<p>+++</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+===
+.
+<p>===</p>
+````````````````````````````````
+
+
+Not enough characters:
+
+```````````````````````````````` example
+--
+**
+__
+.
+<p>--
+**
+__</p>
+````````````````````````````````
+
+
+One to three spaces indent are allowed:
+
+```````````````````````````````` example
+ ***
+ ***
+ ***
+.
+<hr />
+<hr />
+<hr />
+````````````````````````````````
+
+
+Four spaces is too many:
+
+```````````````````````````````` example
+ ***
+.
+<pre><code>***
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+Foo
+ ***
+.
+<p>Foo
+***</p>
+````````````````````````````````
+
+
+More than three characters may be used:
+
+```````````````````````````````` example
+_____________________________________
+.
+<hr />
+````````````````````````````````
+
+
+Spaces are allowed between the characters:
+
+```````````````````````````````` example
+ - - -
+.
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ** * ** * ** * **
+.
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+- - - -
+.
+<hr />
+````````````````````````````````
+
+
+Spaces are allowed at the end:
+
+```````````````````````````````` example
+- - - -
+.
+<hr />
+````````````````````````````````
+
+
+However, no other characters may occur in the line:
+
+```````````````````````````````` example
+_ _ _ _ a
+
+a------
+
+---a---
+.
+<p>_ _ _ _ a</p>
+<p>a------</p>
+<p>---a---</p>
+````````````````````````````````
+
+
+It is required that all of the [non-whitespace characters] be the same.
+So, this is not a thematic break:
+
+```````````````````````````````` example
+ *-*
+.
+<p><em>-</em></p>
+````````````````````````````````
+
+
+Thematic breaks do not need blank lines before or after:
+
+```````````````````````````````` example
+- foo
+***
+- bar
+.
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+<ul>
+<li>bar</li>
+</ul>
+````````````````````````````````
+
+
+Thematic breaks can interrupt a paragraph:
+
+```````````````````````````````` example
+Foo
+***
+bar
+.
+<p>Foo</p>
+<hr />
+<p>bar</p>
+````````````````````````````````
+
+
+If a line of dashes that meets the above conditions for being a
+thematic break could also be interpreted as the underline of a [setext
+heading], the interpretation as a
+[setext heading] takes precedence. Thus, for example,
+this is a setext heading, not a paragraph followed by a thematic break:
+
+```````````````````````````````` example
+Foo
+---
+bar
+.
+<h2>Foo</h2>
+<p>bar</p>
+````````````````````````````````
+
+
+When both a thematic break and a list item are possible
+interpretations of a line, the thematic break takes precedence:
+
+```````````````````````````````` example
+* Foo
+* * *
+* Bar
+.
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+<ul>
+<li>Bar</li>
+</ul>
+````````````````````````````````
+
+
+If you want a thematic break in a list item, use a different bullet:
+
+```````````````````````````````` example
+- Foo
+- * * *
+.
+<ul>
+<li>Foo</li>
+<li>
+<hr />
+</li>
+</ul>
+````````````````````````````````
+
+
+## ATX headings
+
+An [ATX heading](@)
+consists of a string of characters, parsed as inline content, between an
+opening sequence of 1--6 unescaped `#` characters and an optional
+closing sequence of any number of unescaped `#` characters.
+The opening sequence of `#` characters must be followed by a
+[space] or by the end of line. The optional closing sequence of `#`s must be
+preceded by a [space] and may be followed by spaces only. The opening
+`#` character may be indented 0-3 spaces. The raw contents of the
+heading are stripped of leading and trailing spaces before being parsed
+as inline content. The heading level is equal to the number of `#`
+characters in the opening sequence.
+
+Simple headings:
+
+```````````````````````````````` example
+# foo
+## foo
+### foo
+#### foo
+##### foo
+###### foo
+.
+<h1>foo</h1>
+<h2>foo</h2>
+<h3>foo</h3>
+<h4>foo</h4>
+<h5>foo</h5>
+<h6>foo</h6>
+````````````````````````````````
+
+
+More than six `#` characters is not a heading:
+
+```````````````````````````````` example
+####### foo
+.
+<p>####### foo</p>
+````````````````````````````````
+
+
+At least one space is required between the `#` characters and the
+heading's contents, unless the heading is empty. Note that many
+implementations currently do not require the space. However, the
+space was required by the
+[original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py),
+and it helps prevent things like the following from being parsed as
+headings:
+
+```````````````````````````````` example
+#5 bolt
+
+#hashtag
+.
+<p>#5 bolt</p>
+<p>#hashtag</p>
+````````````````````````````````
+
+
+This is not a heading, because the first `#` is escaped:
+
+```````````````````````````````` example
+\## foo
+.
+<p>## foo</p>
+````````````````````````````````
+
+
+Contents are parsed as inlines:
+
+```````````````````````````````` example
+# foo *bar* \*baz\*
+.
+<h1>foo <em>bar</em> *baz*</h1>
+````````````````````````````````
+
+
+Leading and trailing [whitespace] is ignored in parsing inline content:
+
+```````````````````````````````` example
+# foo
+.
+<h1>foo</h1>
+````````````````````````````````
+
+
+One to three spaces indentation are allowed:
+
+```````````````````````````````` example
+ ### foo
+ ## foo
+ # foo
+.
+<h3>foo</h3>
+<h2>foo</h2>
+<h1>foo</h1>
+````````````````````````````````
+
+
+Four spaces are too much:
+
+```````````````````````````````` example
+ # foo
+.
+<pre><code># foo
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo
+ # bar
+.
+<p>foo
+# bar</p>
+````````````````````````````````
+
+
+A closing sequence of `#` characters is optional:
+
+```````````````````````````````` example
+## foo ##
+ ### bar ###
+.
+<h2>foo</h2>
+<h3>bar</h3>
+````````````````````````````````
+
+
+It need not be the same length as the opening sequence:
+
+```````````````````````````````` example
+# foo ##################################
+##### foo ##
+.
+<h1>foo</h1>
+<h5>foo</h5>
+````````````````````````````````
+
+
+Spaces are allowed after the closing sequence:
+
+```````````````````````````````` example
+### foo ###
+.
+<h3>foo</h3>
+````````````````````````````````
+
+
+A sequence of `#` characters with anything but [spaces] following it
+is not a closing sequence, but counts as part of the contents of the
+heading:
+
+```````````````````````````````` example
+### foo ### b
+.
+<h3>foo ### b</h3>
+````````````````````````````````
+
+
+The closing sequence must be preceded by a space:
+
+```````````````````````````````` example
+# foo#
+.
+<h1>foo#</h1>
+````````````````````````````````
+
+
+Backslash-escaped `#` characters do not count as part
+of the closing sequence:
+
+```````````````````````````````` example
+### foo \###
+## foo #\##
+# foo \#
+.
+<h3>foo ###</h3>
+<h2>foo ###</h2>
+<h1>foo #</h1>
+````````````````````````````````
+
+
+ATX headings need not be separated from surrounding content by blank
+lines, and they can interrupt paragraphs:
+
+```````````````````````````````` example
+****
+## foo
+****
+.
+<hr />
+<h2>foo</h2>
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+Foo bar
+# baz
+Bar foo
+.
+<p>Foo bar</p>
+<h1>baz</h1>
+<p>Bar foo</p>
+````````````````````````````````
+
+
+ATX headings can be empty:
+
+```````````````````````````````` example
+##
+#
+### ###
+.
+<h2></h2>
+<h1></h1>
+<h3></h3>
+````````````````````````````````
+
+
+## Setext headings
+
+A [setext heading](@) consists of one or more
+lines of text, each containing at least one [non-whitespace
+character], with no more than 3 spaces indentation, followed by
+a [setext heading underline]. The lines of text must be such
+that, were they not followed by the setext heading underline,
+they would be interpreted as a paragraph: they cannot be
+interpretable as a [code fence], [ATX heading][ATX headings],
+[block quote][block quotes], [thematic break][thematic breaks],
+[list item][list items], or [HTML block][HTML blocks].
+
+A [setext heading underline](@) is a sequence of
+`=` characters or a sequence of `-` characters, with no more than 3
+spaces indentation and any number of trailing spaces. If a line
+containing a single `-` can be interpreted as an
+empty [list items], it should be interpreted this way
+and not as a [setext heading underline].
+
+The heading is a level 1 heading if `=` characters are used in
+the [setext heading underline], and a level 2 heading if `-`
+characters are used. The contents of the heading are the result
+of parsing the preceding lines of text as CommonMark inline
+content.
+
+In general, a setext heading need not be preceded or followed by a
+blank line. However, it cannot interrupt a paragraph, so when a
+setext heading comes after a paragraph, a blank line is needed between
+them.
+
+Simple examples:
+
+```````````````````````````````` example
+Foo *bar*
+=========
+
+Foo *bar*
+---------
+.
+<h1>Foo <em>bar</em></h1>
+<h2>Foo <em>bar</em></h2>
+````````````````````````````````
+
+
+The content of the header may span more than one line:
+
+```````````````````````````````` example
+Foo *bar
+baz*
+====
+.
+<h1>Foo <em>bar
+baz</em></h1>
+````````````````````````````````
+
+The contents are the result of parsing the headings's raw
+content as inlines. The heading's raw content is formed by
+concatenating the lines and removing initial and final
+[whitespace].
+
+```````````````````````````````` example
+ Foo *bar
+baz*→
+====
+.
+<h1>Foo <em>bar
+baz</em></h1>
+````````````````````````````````
+
+
+The underlining can be any length:
+
+```````````````````````````````` example
+Foo
+-------------------------
+
+Foo
+=
+.
+<h2>Foo</h2>
+<h1>Foo</h1>
+````````````````````````````````
+
+
+The heading content can be indented up to three spaces, and need
+not line up with the underlining:
+
+```````````````````````````````` example
+ Foo
+---
+
+ Foo
+-----
+
+ Foo
+ ===
+.
+<h2>Foo</h2>
+<h2>Foo</h2>
+<h1>Foo</h1>
+````````````````````````````````
+
+
+Four spaces indent is too much:
+
+```````````````````````````````` example
+ Foo
+ ---
+
+ Foo
+---
+.
+<pre><code>Foo
+---
+
+Foo
+</code></pre>
+<hr />
+````````````````````````````````
+
+
+The setext heading underline can be indented up to three spaces, and
+may have trailing spaces:
+
+```````````````````````````````` example
+Foo
+ ----
+.
+<h2>Foo</h2>
+````````````````````````````````
+
+
+Four spaces is too much:
+
+```````````````````````````````` example
+Foo
+ ---
+.
+<p>Foo
+---</p>
+````````````````````````````````
+
+
+The setext heading underline cannot contain internal spaces:
+
+```````````````````````````````` example
+Foo
+= =
+
+Foo
+--- -
+.
+<p>Foo
+= =</p>
+<p>Foo</p>
+<hr />
+````````````````````````````````
+
+
+Trailing spaces in the content line do not cause a line break:
+
+```````````````````````````````` example
+Foo
+-----
+.
+<h2>Foo</h2>
+````````````````````````````````
+
+
+Nor does a backslash at the end:
+
+```````````````````````````````` example
+Foo\
+----
+.
+<h2>Foo\</h2>
+````````````````````````````````
+
+
+Since indicators of block structure take precedence over
+indicators of inline structure, the following are setext headings:
+
+```````````````````````````````` example
+`Foo
+----
+`
+
+<a title="a lot
+---
+of dashes"/>
+.
+<h2>`Foo</h2>
+<p>`</p>
+<h2>&lt;a title=&quot;a lot</h2>
+<p>of dashes&quot;/&gt;</p>
+````````````````````````````````
+
+
+The setext heading underline cannot be a [lazy continuation
+line] in a list item or block quote:
+
+```````````````````````````````` example
+> Foo
+---
+.
+<blockquote>
+<p>Foo</p>
+</blockquote>
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+> foo
+bar
+===
+.
+<blockquote>
+<p>foo
+bar
+===</p>
+</blockquote>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- Foo
+---
+.
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+````````````````````````````````
+
+
+A blank line is needed between a paragraph and a following
+setext heading, since otherwise the paragraph becomes part
+of the heading's content:
+
+```````````````````````````````` example
+Foo
+Bar
+---
+.
+<h2>Foo
+Bar</h2>
+````````````````````````````````
+
+
+But in general a blank line is not required before or after
+setext headings:
+
+```````````````````````````````` example
+---
+Foo
+---
+Bar
+---
+Baz
+.
+<hr />
+<h2>Foo</h2>
+<h2>Bar</h2>
+<p>Baz</p>
+````````````````````````````````
+
+
+Setext headings cannot be empty:
+
+```````````````````````````````` example
+
+====
+.
+<p>====</p>
+````````````````````````````````
+
+
+Setext heading text lines must not be interpretable as block
+constructs other than paragraphs. So, the line of dashes
+in these examples gets interpreted as a thematic break:
+
+```````````````````````````````` example
+---
+---
+.
+<hr />
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+- foo
+-----
+.
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+ foo
+---
+.
+<pre><code>foo
+</code></pre>
+<hr />
+````````````````````````````````
+
+
+```````````````````````````````` example
+> foo
+-----
+.
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+````````````````````````````````
+
+
+If you want a heading with `> foo` as its literal text, you can
+use backslash escapes:
+
+```````````````````````````````` example
+\> foo
+------
+.
+<h2>&gt; foo</h2>
+````````````````````````````````
+
+
+**Compatibility note:** Most existing Markdown implementations
+do not allow the text of setext headings to span multiple lines.
+But there is no consensus about how to interpret
+
+``` markdown
+Foo
+bar
+---
+baz
+```
+
+One can find four different interpretations:
+
+1. paragraph "Foo", heading "bar", paragraph "baz"
+2. paragraph "Foo bar", thematic break, paragraph "baz"
+3. paragraph "Foo bar --- baz"
+4. heading "Foo bar", paragraph "baz"
+
+We find interpretation 4 most natural, and interpretation 4
+increases the expressive power of CommonMark, by allowing
+multiline headings. Authors who want interpretation 1 can
+put a blank line after the first paragraph:
+
+```````````````````````````````` example
+Foo
+
+bar
+---
+baz
+.
+<p>Foo</p>
+<h2>bar</h2>
+<p>baz</p>
+````````````````````````````````
+
+
+Authors who want interpretation 2 can put blank lines around
+the thematic break,
+
+```````````````````````````````` example
+Foo
+bar
+
+---
+
+baz
+.
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+````````````````````````````````
+
+
+or use a thematic break that cannot count as a [setext heading
+underline], such as
+
+```````````````````````````````` example
+Foo
+bar
+* * *
+baz
+.
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+````````````````````````````````
+
+
+Authors who want interpretation 3 can use backslash escapes:
+
+```````````````````````````````` example
+Foo
+bar
+\---
+baz
+.
+<p>Foo
+bar
+---
+baz</p>
+````````````````````````````````
+
+
+## Indented code blocks
+
+An [indented code block](@) is composed of one or more
+[indented chunks] separated by blank lines.
+An [indented chunk](@) is a sequence of non-blank lines,
+each indented four or more spaces. The contents of the code block are
+the literal contents of the lines, including trailing
+[line endings], minus four spaces of indentation.
+An indented code block has no [info string].
+
+An indented code block cannot interrupt a paragraph, so there must be
+a blank line between a paragraph and a following indented code block.
+(A blank line is not needed, however, between a code block and a following
+paragraph.)
+
+```````````````````````````````` example
+ a simple
+ indented code block
+.
+<pre><code>a simple
+ indented code block
+</code></pre>
+````````````````````````````````
+
+
+If there is any ambiguity between an interpretation of indentation
+as a code block and as indicating that material belongs to a [list
+item][list items], the list item interpretation takes precedence:
+
+```````````````````````````````` example
+ - foo
+
+ bar
+.
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. foo
+
+ - bar
+.
+<ol>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+````````````````````````````````
+
+
+
+The contents of a code block are literal text, and do not get parsed
+as Markdown:
+
+```````````````````````````````` example
+ <a/>
+ *hi*
+
+ - one
+.
+<pre><code>&lt;a/&gt;
+*hi*
+
+- one
+</code></pre>
+````````````````````````````````
+
+
+Here we have three chunks separated by blank lines:
+
+```````````````````````````````` example
+ chunk1
+
+ chunk2
+
+
+
+ chunk3
+.
+<pre><code>chunk1
+
+chunk2
+
+
+
+chunk3
+</code></pre>
+````````````````````````````````
+
+
+Any initial spaces beyond four will be included in the content, even
+in interior blank lines:
+
+```````````````````````````````` example
+ chunk1
+
+ chunk2
+.
+<pre><code>chunk1
+
+ chunk2
+</code></pre>
+````````````````````````````````
+
+
+An indented code block cannot interrupt a paragraph. (This
+allows hanging indents and the like.)
+
+```````````````````````````````` example
+Foo
+ bar
+
+.
+<p>Foo
+bar</p>
+````````````````````````````````
+
+
+However, any non-blank line with fewer than four leading spaces ends
+the code block immediately. So a paragraph may occur immediately
+after indented code:
+
+```````````````````````````````` example
+ foo
+bar
+.
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+````````````````````````````````
+
+
+And indented code can occur immediately before and after other kinds of
+blocks:
+
+```````````````````````````````` example
+# Heading
+ foo
+Heading
+------
+ foo
+----
+.
+<h1>Heading</h1>
+<pre><code>foo
+</code></pre>
+<h2>Heading</h2>
+<pre><code>foo
+</code></pre>
+<hr />
+````````````````````````````````
+
+
+The first line can be indented more than four spaces:
+
+```````````````````````````````` example
+ foo
+ bar
+.
+<pre><code> foo
+bar
+</code></pre>
+````````````````````````````````
+
+
+Blank lines preceding or following an indented code block
+are not included in it:
+
+```````````````````````````````` example
+
+
+ foo
+
+
+.
+<pre><code>foo
+</code></pre>
+````````````````````````````````
+
+
+Trailing spaces are included in the code block's content:
+
+```````````````````````````````` example
+ foo
+.
+<pre><code>foo
+</code></pre>
+````````````````````````````````
+
+
+
+## Fenced code blocks
+
+A [code fence](@) is a sequence
+of at least three consecutive backtick characters (`` ` ``) or
+tildes (`~`). (Tildes and backticks cannot be mixed.)
+A [fenced code block](@)
+begins with a code fence, indented no more than three spaces.
+
+The line with the opening code fence may optionally contain some text
+following the code fence; this is trimmed of leading and trailing
+whitespace and called the [info string](@). If the [info string] comes
+after a backtick fence, it may not contain any backtick
+characters. (The reason for this restriction is that otherwise
+some inline code would be incorrectly interpreted as the
+beginning of a fenced code block.)
+
+The content of the code block consists of all subsequent lines, until
+a closing [code fence] of the same type as the code block
+began with (backticks or tildes), and with at least as many backticks
+or tildes as the opening code fence. If the leading code fence is
+indented N spaces, then up to N spaces of indentation are removed from
+each line of the content (if present). (If a content line is not
+indented, it is preserved unchanged. If it is indented less than N
+spaces, all of the indentation is removed.)
+
+The closing code fence may be indented up to three spaces, and may be
+followed only by spaces, which are ignored. If the end of the
+containing block (or document) is reached and no closing code fence
+has been found, the code block contains all of the lines after the
+opening code fence until the end of the containing block (or
+document). (An alternative spec would require backtracking in the
+event that a closing code fence is not found. But this makes parsing
+much less efficient, and there seems to be no real down side to the
+behavior described here.)
+
+A fenced code block may interrupt a paragraph, and does not require
+a blank line either before or after.
+
+The content of a code fence is treated as literal text, not parsed
+as inlines. The first word of the [info string] is typically used to
+specify the language of the code sample, and rendered in the `class`
+attribute of the `code` tag. However, this spec does not mandate any
+particular treatment of the [info string].
+
+Here is a simple example with backticks:
+
+```````````````````````````````` example
+```
+<
+ >
+```
+.
+<pre><code>&lt;
+ &gt;
+</code></pre>
+````````````````````````````````
+
+
+With tildes:
+
+```````````````````````````````` example
+~~~
+<
+ >
+~~~
+.
+<pre><code>&lt;
+ &gt;
+</code></pre>
+````````````````````````````````
+
+Fewer than three backticks is not enough:
+
+```````````````````````````````` example
+``
+foo
+``
+.
+<p><code>foo</code></p>
+````````````````````````````````
+
+The closing code fence must use the same character as the opening
+fence:
+
+```````````````````````````````` example
+```
+aaa
+~~~
+```
+.
+<pre><code>aaa
+~~~
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~
+aaa
+```
+~~~
+.
+<pre><code>aaa
+```
+</code></pre>
+````````````````````````````````
+
+
+The closing code fence must be at least as long as the opening fence:
+
+```````````````````````````````` example
+````
+aaa
+```
+``````
+.
+<pre><code>aaa
+```
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~
+aaa
+~~~
+~~~~
+.
+<pre><code>aaa
+~~~
+</code></pre>
+````````````````````````````````
+
+
+Unclosed code blocks are closed by the end of the document
+(or the enclosing [block quote][block quotes] or [list item][list items]):
+
+```````````````````````````````` example
+```
+.
+<pre><code></code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+`````
+
+```
+aaa
+.
+<pre><code>
+```
+aaa
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+> ```
+> aaa
+
+bbb
+.
+<blockquote>
+<pre><code>aaa
+</code></pre>
+</blockquote>
+<p>bbb</p>
+````````````````````````````````
+
+
+A code block can have all empty lines as its content:
+
+```````````````````````````````` example
+```
+
+
+```
+.
+<pre><code>
+
+</code></pre>
+````````````````````````````````
+
+
+A code block can be empty:
+
+```````````````````````````````` example
+```
+```
+.
+<pre><code></code></pre>
+````````````````````````````````
+
+
+Fences can be indented. If the opening fence is indented,
+content lines will have equivalent opening indentation removed,
+if present:
+
+```````````````````````````````` example
+ ```
+ aaa
+aaa
+```
+.
+<pre><code>aaa
+aaa
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+aaa
+ aaa
+aaa
+ ```
+.
+<pre><code>aaa
+aaa
+aaa
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+ aaa
+ aaa
+ aaa
+ ```
+.
+<pre><code>aaa
+ aaa
+aaa
+</code></pre>
+````````````````````````````````
+
+
+Four spaces indentation produces an indented code block:
+
+```````````````````````````````` example
+ ```
+ aaa
+ ```
+.
+<pre><code>```
+aaa
+```
+</code></pre>
+````````````````````````````````
+
+
+Closing fences may be indented by 0-3 spaces, and their indentation
+need not match that of the opening fence:
+
+```````````````````````````````` example
+```
+aaa
+ ```
+.
+<pre><code>aaa
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+aaa
+ ```
+.
+<pre><code>aaa
+</code></pre>
+````````````````````````````````
+
+
+This is not a closing fence, because it is indented 4 spaces:
+
+```````````````````````````````` example
+```
+aaa
+ ```
+.
+<pre><code>aaa
+ ```
+</code></pre>
+````````````````````````````````
+
+
+
+Code fences (opening and closing) cannot contain internal spaces:
+
+```````````````````````````````` example
+``` ```
+aaa
+.
+<p><code> </code>
+aaa</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~~~
+aaa
+~~~ ~~
+.
+<pre><code>aaa
+~~~ ~~
+</code></pre>
+````````````````````````````````
+
+
+Fenced code blocks can interrupt paragraphs, and can be followed
+directly by paragraphs, without a blank line between:
+
+```````````````````````````````` example
+foo
+```
+bar
+```
+baz
+.
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+````````````````````````````````
+
+
+Other blocks can also occur before and after fenced code blocks
+without an intervening blank line:
+
+```````````````````````````````` example
+foo
+---
+~~~
+bar
+~~~
+# baz
+.
+<h2>foo</h2>
+<pre><code>bar
+</code></pre>
+<h1>baz</h1>
+````````````````````````````````
+
+
+An [info string] can be provided after the opening code fence.
+Although this spec doesn't mandate any particular treatment of
+the info string, the first word is typically used to specify
+the language of the code block. In HTML output, the language is
+normally indicated by adding a class to the `code` element consisting
+of `language-` followed by the language name.
+
+```````````````````````````````` example
+```ruby
+def foo(x)
+ return 3
+end
+```
+.
+<pre><code class="language-ruby">def foo(x)
+ return 3
+end
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~ ruby startline=3 $%@#$
+def foo(x)
+ return 3
+end
+~~~~~~~
+.
+<pre><code class="language-ruby">def foo(x)
+ return 3
+end
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+````;
+````
+.
+<pre><code class="language-;"></code></pre>
+````````````````````````````````
+
+
+[Info strings] for backtick code blocks cannot contain backticks:
+
+```````````````````````````````` example
+``` aa ```
+foo
+.
+<p><code>aa</code>
+foo</p>
+````````````````````````````````
+
+
+[Info strings] for tilde code blocks can contain backticks and tildes:
+
+```````````````````````````````` example
+~~~ aa ``` ~~~
+foo
+~~~
+.
+<pre><code class="language-aa">foo
+</code></pre>
+````````````````````````````````
+
+
+Closing code fences cannot have [info strings]:
+
+```````````````````````````````` example
+```
+``` aaa
+```
+.
+<pre><code>``` aaa
+</code></pre>
+````````````````````````````````
+
+
+
+## HTML blocks
+
+An [HTML block](@) is a group of lines that is treated
+as raw HTML (and will not be escaped in HTML output).
+
+There are seven kinds of [HTML block], which can be defined by their
+start and end conditions. The block begins with a line that meets a
+[start condition](@) (after up to three spaces optional indentation).
+It ends with the first subsequent line that meets a matching [end
+condition](@), or the last line of the document, or the last line of
+the [container block](#container-blocks) containing the current HTML
+block, if no line is encountered that meets the [end condition]. If
+the first line meets both the [start condition] and the [end
+condition], the block will contain just that line.
+
+1. **Start condition:** line begins with the string `<script`,
+`<pre`, or `<style` (case-insensitive), followed by whitespace,
+the string `>`, or the end of the line.\
+**End condition:** line contains an end tag
+`</script>`, `</pre>`, or `</style>` (case-insensitive; it
+need not match the start tag).
+
+2. **Start condition:** line begins with the string `<!--`.\
+**End condition:** line contains the string `-->`.
+
+3. **Start condition:** line begins with the string `<?`.\
+**End condition:** line contains the string `?>`.
+
+4. **Start condition:** line begins with the string `<!`
+followed by an uppercase ASCII letter.\
+**End condition:** line contains the character `>`.
+
+5. **Start condition:** line begins with the string
+`<![CDATA[`.\
+**End condition:** line contains the string `]]>`.
+
+6. **Start condition:** line begins the string `<` or `</`
+followed by one of the strings (case-insensitive) `address`,
+`article`, `aside`, `base`, `basefont`, `blockquote`, `body`,
+`caption`, `center`, `col`, `colgroup`, `dd`, `details`, `dialog`,
+`dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`,
+`footer`, `form`, `frame`, `frameset`,
+`h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `head`, `header`, `hr`,
+`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
+`nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
+`section`, `summary`, `table`, `tbody`, `td`,
+`tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed
+by [whitespace], the end of the line, the string `>`, or
+the string `/>`.\
+**End condition:** line is followed by a [blank line].
+
+7. **Start condition:** line begins with a complete [open tag]
+(with any [tag name] other than `script`,
+`style`, or `pre`) or a complete [closing tag],
+followed only by [whitespace] or the end of the line.\
+**End condition:** line is followed by a [blank line].
+
+HTML blocks continue until they are closed by their appropriate
+[end condition], or the last line of the document or other [container
+block](#container-blocks). This means any HTML **within an HTML
+block** that might otherwise be recognised as a start condition will
+be ignored by the parser and passed through as-is, without changing
+the parser's state.
+
+For instance, `<pre>` within a HTML block started by `<table>` will not affect
+the parser state; as the HTML block was started in by start condition 6, it
+will end at any blank line. This can be surprising:
+
+```````````````````````````````` example
+<table><tr><td>
+<pre>
+**Hello**,
+
+_world_.
+</pre>
+</td></tr></table>
+.
+<table><tr><td>
+<pre>
+**Hello**,
+<p><em>world</em>.
+</pre></p>
+</td></tr></table>
+````````````````````````````````
+
+In this case, the HTML block is terminated by the newline — the `**Hello**`
+text remains verbatim — and regular parsing resumes, with a paragraph,
+emphasised `world` and inline and block HTML following.
+
+All types of [HTML blocks] except type 7 may interrupt
+a paragraph. Blocks of type 7 may not interrupt a paragraph.
+(This restriction is intended to prevent unwanted interpretation
+of long tags inside a wrapped paragraph as starting HTML blocks.)
+
+Some simple examples follow. Here are some basic HTML blocks
+of type 6:
+
+```````````````````````````````` example
+<table>
+ <tr>
+ <td>
+ hi
+ </td>
+ </tr>
+</table>
+
+okay.
+.
+<table>
+ <tr>
+ <td>
+ hi
+ </td>
+ </tr>
+</table>
+<p>okay.</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ <div>
+ *hello*
+ <foo><a>
+.
+ <div>
+ *hello*
+ <foo><a>
+````````````````````````````````
+
+
+A block can also start with a closing tag:
+
+```````````````````````````````` example
+</div>
+*foo*
+.
+</div>
+*foo*
+````````````````````````````````
+
+
+Here we have two HTML blocks with a Markdown paragraph between them:
+
+```````````````````````````````` example
+<DIV CLASS="foo">
+
+*Markdown*
+
+</DIV>
+.
+<DIV CLASS="foo">
+<p><em>Markdown</em></p>
+</DIV>
+````````````````````````````````
+
+
+The tag on the first line can be partial, as long
+as it is split where there would be whitespace:
+
+```````````````````````````````` example
+<div id="foo"
+ class="bar">
+</div>
+.
+<div id="foo"
+ class="bar">
+</div>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<div id="foo" class="bar
+ baz">
+</div>
+.
+<div id="foo" class="bar
+ baz">
+</div>
+````````````````````````````````
+
+
+An open tag need not be closed:
+```````````````````````````````` example
+<div>
+*foo*
+
+*bar*
+.
+<div>
+*foo*
+<p><em>bar</em></p>
+````````````````````````````````
+
+
+
+A partial tag need not even be completed (garbage
+in, garbage out):
+
+```````````````````````````````` example
+<div id="foo"
+*hi*
+.
+<div id="foo"
+*hi*
+````````````````````````````````
+
+
+```````````````````````````````` example
+<div class
+foo
+.
+<div class
+foo
+````````````````````````````````
+
+
+The initial tag doesn't even need to be a valid
+tag, as long as it starts like one:
+
+```````````````````````````````` example
+<div *???-&&&-<---
+*foo*
+.
+<div *???-&&&-<---
+*foo*
+````````````````````````````````
+
+
+In type 6 blocks, the initial tag need not be on a line by
+itself:
+
+```````````````````````````````` example
+<div><a href="bar">*foo*</a></div>
+.
+<div><a href="bar">*foo*</a></div>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<table><tr><td>
+foo
+</td></tr></table>
+.
+<table><tr><td>
+foo
+</td></tr></table>
+````````````````````````````````
+
+
+Everything until the next blank line or end of document
+gets included in the HTML block. So, in the following
+example, what looks like a Markdown code block
+is actually part of the HTML block, which continues until a blank
+line or the end of the document is reached:
+
+```````````````````````````````` example
+<div></div>
+``` c
+int x = 33;
+```
+.
+<div></div>
+``` c
+int x = 33;
+```
+````````````````````````````````
+
+
+To start an [HTML block] with a tag that is *not* in the
+list of block-level tags in (6), you must put the tag by
+itself on the first line (and it must be complete):
+
+```````````````````````````````` example
+<a href="foo">
+*bar*
+</a>
+.
+<a href="foo">
+*bar*
+</a>
+````````````````````````````````
+
+
+In type 7 blocks, the [tag name] can be anything:
+
+```````````````````````````````` example
+<Warning>
+*bar*
+</Warning>
+.
+<Warning>
+*bar*
+</Warning>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<i class="foo">
+*bar*
+</i>
+.
+<i class="foo">
+*bar*
+</i>
+````````````````````````````````
+
+
+```````````````````````````````` example
+</ins>
+*bar*
+.
+</ins>
+*bar*
+````````````````````````````````
+
+
+These rules are designed to allow us to work with tags that
+can function as either block-level or inline-level tags.
+The `<del>` tag is a nice example. We can surround content with
+`<del>` tags in three different ways. In this case, we get a raw
+HTML block, because the `<del>` tag is on a line by itself:
+
+```````````````````````````````` example
+<del>
+*foo*
+</del>
+.
+<del>
+*foo*
+</del>
+````````````````````````````````
+
+
+In this case, we get a raw HTML block that just includes
+the `<del>` tag (because it ends with the following blank
+line). So the contents get interpreted as CommonMark:
+
+```````````````````````````````` example
+<del>
+
+*foo*
+
+</del>
+.
+<del>
+<p><em>foo</em></p>
+</del>
+````````````````````````````````
+
+
+Finally, in this case, the `<del>` tags are interpreted
+as [raw HTML] *inside* the CommonMark paragraph. (Because
+the tag is not on a line by itself, we get inline HTML
+rather than an [HTML block].)
+
+```````````````````````````````` example
+<del>*foo*</del>
+.
+<p><del><em>foo</em></del></p>
+````````````````````````````````
+
+
+HTML tags designed to contain literal content
+(`script`, `style`, `pre`), comments, processing instructions,
+and declarations are treated somewhat differently.
+Instead of ending at the first blank line, these blocks
+end at the first line containing a corresponding end tag.
+As a result, these blocks can contain blank lines:
+
+A pre tag (type 1):
+
+```````````````````````````````` example
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+okay
+.
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+<p>okay</p>
+````````````````````````````````
+
+
+A script tag (type 1):
+
+```````````````````````````````` example
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+okay
+.
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+<p>okay</p>
+````````````````````````````````
+
+
+A style tag (type 1):
+
+```````````````````````````````` example
+<style
+ type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+okay
+.
+<style
+ type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+<p>okay</p>
+````````````````````````````````
+
+
+If there is no matching end tag, the block will end at the
+end of the document (or the enclosing [block quote][block quotes]
+or [list item][list items]):
+
+```````````````````````````````` example
+<style
+ type="text/css">
+
+foo
+.
+<style
+ type="text/css">
+
+foo
+````````````````````````````````
+
+
+```````````````````````````````` example
+> <div>
+> foo
+
+bar
+.
+<blockquote>
+<div>
+foo
+</blockquote>
+<p>bar</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- <div>
+- foo
+.
+<ul>
+<li>
+<div>
+</li>
+<li>foo</li>
+</ul>
+````````````````````````````````
+
+
+The end tag can occur on the same line as the start tag:
+
+```````````````````````````````` example
+<style>p{color:red;}</style>
+*foo*
+.
+<style>p{color:red;}</style>
+<p><em>foo</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<!-- foo -->*bar*
+*baz*
+.
+<!-- foo -->*bar*
+<p><em>baz</em></p>
+````````````````````````````````
+
+
+Note that anything on the last line after the
+end tag will be included in the [HTML block]:
+
+```````````````````````````````` example
+<script>
+foo
+</script>1. *bar*
+.
+<script>
+foo
+</script>1. *bar*
+````````````````````````````````
+
+
+A comment (type 2):
+
+```````````````````````````````` example
+<!-- Foo
+
+bar
+ baz -->
+okay
+.
+<!-- Foo
+
+bar
+ baz -->
+<p>okay</p>
+````````````````````````````````
+
+
+
+A processing instruction (type 3):
+
+```````````````````````````````` example
+<?php
+
+ echo '>';
+
+?>
+okay
+.
+<?php
+
+ echo '>';
+
+?>
+<p>okay</p>
+````````````````````````````````
+
+
+A declaration (type 4):
+
+```````````````````````````````` example
+<!DOCTYPE html>
+.
+<!DOCTYPE html>
+````````````````````````````````
+
+
+CDATA (type 5):
+
+```````````````````````````````` example
+<![CDATA[
+function matchwo(a,b)
+{
+ if (a < b && a < 0) then {
+ return 1;
+
+ } else {
+
+ return 0;
+ }
+}
+]]>
+okay
+.
+<![CDATA[
+function matchwo(a,b)
+{
+ if (a < b && a < 0) then {
+ return 1;
+
+ } else {
+
+ return 0;
+ }
+}
+]]>
+<p>okay</p>
+````````````````````````````````
+
+
+The opening tag can be indented 1-3 spaces, but not 4:
+
+```````````````````````````````` example
+ <!-- foo -->
+
+ <!-- foo -->
+.
+ <!-- foo -->
+<pre><code>&lt;!-- foo --&gt;
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ <div>
+
+ <div>
+.
+ <div>
+<pre><code>&lt;div&gt;
+</code></pre>
+````````````````````````````````
+
+
+An HTML block of types 1--6 can interrupt a paragraph, and need not be
+preceded by a blank line.
+
+```````````````````````````````` example
+Foo
+<div>
+bar
+</div>
+.
+<p>Foo</p>
+<div>
+bar
+</div>
+````````````````````````````````
+
+
+However, a following blank line is needed, except at the end of
+a document, and except for blocks of types 1--5, [above][HTML
+block]:
+
+```````````````````````````````` example
+<div>
+bar
+</div>
+*foo*
+.
+<div>
+bar
+</div>
+*foo*
+````````````````````````````````
+
+
+HTML blocks of type 7 cannot interrupt a paragraph:
+
+```````````````````````````````` example
+Foo
+<a href="bar">
+baz
+.
+<p>Foo
+<a href="bar">
+baz</p>
+````````````````````````````````
+
+
+This rule differs from John Gruber's original Markdown syntax
+specification, which says:
+
+> The only restrictions are that block-level HTML elements —
+> e.g. `<div>`, `<table>`, `<pre>`, `<p>`, etc. — must be separated from
+> surrounding content by blank lines, and the start and end tags of the
+> block should not be indented with tabs or spaces.
+
+In some ways Gruber's rule is more restrictive than the one given
+here:
+
+- It requires that an HTML block be preceded by a blank line.
+- It does not allow the start tag to be indented.
+- It requires a matching end tag, which it also does not allow to
+ be indented.
+
+Most Markdown implementations (including some of Gruber's own) do not
+respect all of these restrictions.
+
+There is one respect, however, in which Gruber's rule is more liberal
+than the one given here, since it allows blank lines to occur inside
+an HTML block. There are two reasons for disallowing them here.
+First, it removes the need to parse balanced tags, which is
+expensive and can require backtracking from the end of the document
+if no matching end tag is found. Second, it provides a very simple
+and flexible way of including Markdown content inside HTML tags:
+simply separate the Markdown from the HTML using blank lines:
+
+Compare:
+
+```````````````````````````````` example
+<div>
+
+*Emphasized* text.
+
+</div>
+.
+<div>
+<p><em>Emphasized</em> text.</p>
+</div>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<div>
+*Emphasized* text.
+</div>
+.
+<div>
+*Emphasized* text.
+</div>
+````````````````````````````````
+
+
+Some Markdown implementations have adopted a convention of
+interpreting content inside tags as text if the open tag has
+the attribute `markdown=1`. The rule given above seems a simpler and
+more elegant way of achieving the same expressive power, which is also
+much simpler to parse.
+
+The main potential drawback is that one can no longer paste HTML
+blocks into Markdown documents with 100% reliability. However,
+*in most cases* this will work fine, because the blank lines in
+HTML are usually followed by HTML block tags. For example:
+
+```````````````````````````````` example
+<table>
+
+<tr>
+
+<td>
+Hi
+</td>
+
+</tr>
+
+</table>
+.
+<table>
+<tr>
+<td>
+Hi
+</td>
+</tr>
+</table>
+````````````````````````````````
+
+
+There are problems, however, if the inner tags are indented
+*and* separated by spaces, as then they will be interpreted as
+an indented code block:
+
+```````````````````````````````` example
+<table>
+
+ <tr>
+
+ <td>
+ Hi
+ </td>
+
+ </tr>
+
+</table>
+.
+<table>
+ <tr>
+<pre><code>&lt;td&gt;
+ Hi
+&lt;/td&gt;
+</code></pre>
+ </tr>
+</table>
+````````````````````````````````
+
+
+Fortunately, blank lines are usually not necessary and can be
+deleted. The exception is inside `<pre>` tags, but as described
+[above][HTML blocks], raw HTML blocks starting with `<pre>`
+*can* contain blank lines.
+
+## Link reference definitions
+
+A [link reference definition](@)
+consists of a [link label], indented up to three spaces, followed
+by a colon (`:`), optional [whitespace] (including up to one
+[line ending]), a [link destination],
+optional [whitespace] (including up to one
+[line ending]), and an optional [link
+title], which if it is present must be separated
+from the [link destination] by [whitespace].
+No further [non-whitespace characters] may occur on the line.
+
+A [link reference definition]
+does not correspond to a structural element of a document. Instead, it
+defines a label which can be used in [reference links]
+and reference-style [images] elsewhere in the document. [Link
+reference definitions] can come either before or after the links that use
+them.
+
+```````````````````````````````` example
+[foo]: /url "title"
+
+[foo]
+.
+<p><a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ [foo]:
+ /url
+ 'the title'
+
+[foo]
+.
+<p><a href="/url" title="the title">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[Foo*bar\]]:my_(url) 'title (with parens)'
+
+[Foo*bar\]]
+.
+<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[Foo bar]:
+<my url>
+'title'
+
+[Foo bar]
+.
+<p><a href="my%20url" title="title">Foo bar</a></p>
+````````````````````````````````
+
+
+The title may extend over multiple lines:
+
+```````````````````````````````` example
+[foo]: /url '
+title
+line1
+line2
+'
+
+[foo]
+.
+<p><a href="/url" title="
+title
+line1
+line2
+">foo</a></p>
+````````````````````````````````
+
+
+However, it may not contain a [blank line]:
+
+```````````````````````````````` example
+[foo]: /url 'title
+
+with blank line'
+
+[foo]
+.
+<p>[foo]: /url 'title</p>
+<p>with blank line'</p>
+<p>[foo]</p>
+````````````````````````````````
+
+
+The title may be omitted:
+
+```````````````````````````````` example
+[foo]:
+/url
+
+[foo]
+.
+<p><a href="/url">foo</a></p>
+````````````````````````````````
+
+
+The link destination may not be omitted:
+
+```````````````````````````````` example
+[foo]:
+
+[foo]
+.
+<p>[foo]:</p>
+<p>[foo]</p>
+````````````````````````````````
+
+ However, an empty link destination may be specified using
+ angle brackets:
+
+```````````````````````````````` example
+[foo]: <>
+
+[foo]
+.
+<p><a href="">foo</a></p>
+````````````````````````````````
+
+The title must be separated from the link destination by
+whitespace:
+
+```````````````````````````````` example
+[foo]: <bar>(baz)
+
+[foo]
+.
+<p>[foo]: <bar>(baz)</p>
+<p>[foo]</p>
+````````````````````````````````
+
+
+Both title and destination can contain backslash escapes
+and literal backslashes:
+
+```````````````````````````````` example
+[foo]: /url\bar\*baz "foo\"bar\baz"
+
+[foo]
+.
+<p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
+````````````````````````````````
+
+
+A link can come before its corresponding definition:
+
+```````````````````````````````` example
+[foo]
+
+[foo]: url
+.
+<p><a href="url">foo</a></p>
+````````````````````````````````
+
+
+If there are several matching definitions, the first one takes
+precedence:
+
+```````````````````````````````` example
+[foo]
+
+[foo]: first
+[foo]: second
+.
+<p><a href="first">foo</a></p>
+````````````````````````````````
+
+
+As noted in the section on [Links], matching of labels is
+case-insensitive (see [matches]).
+
+```````````````````````````````` example
+[FOO]: /url
+
+[Foo]
+.
+<p><a href="/url">Foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[ΑΓΩ]: /φου
+
+[αγω]
+.
+<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
+````````````````````````````````
+
+
+Here is a link reference definition with no corresponding link.
+It contributes nothing to the document.
+
+```````````````````````````````` example
+[foo]: /url
+.
+````````````````````````````````
+
+
+Here is another one:
+
+```````````````````````````````` example
+[
+foo
+]: /url
+bar
+.
+<p>bar</p>
+````````````````````````````````
+
+
+This is not a link reference definition, because there are
+[non-whitespace characters] after the title:
+
+```````````````````````````````` example
+[foo]: /url "title" ok
+.
+<p>[foo]: /url &quot;title&quot; ok</p>
+````````````````````````````````
+
+
+This is a link reference definition, but it has no title:
+
+```````````````````````````````` example
+[foo]: /url
+"title" ok
+.
+<p>&quot;title&quot; ok</p>
+````````````````````````````````
+
+
+This is not a link reference definition, because it is indented
+four spaces:
+
+```````````````````````````````` example
+ [foo]: /url "title"
+
+[foo]
+.
+<pre><code>[foo]: /url &quot;title&quot;
+</code></pre>
+<p>[foo]</p>
+````````````````````````````````
+
+
+This is not a link reference definition, because it occurs inside
+a code block:
+
+```````````````````````````````` example
+```
+[foo]: /url
+```
+
+[foo]
+.
+<pre><code>[foo]: /url
+</code></pre>
+<p>[foo]</p>
+````````````````````````````````
+
+
+A [link reference definition] cannot interrupt a paragraph.
+
+```````````````````````````````` example
+Foo
+[bar]: /baz
+
+[bar]
+.
+<p>Foo
+[bar]: /baz</p>
+<p>[bar]</p>
+````````````````````````````````
+
+
+However, it can directly follow other block elements, such as headings
+and thematic breaks, and it need not be followed by a blank line.
+
+```````````````````````````````` example
+# [Foo]
+[foo]: /url
+> bar
+.
+<h1><a href="/url">Foo</a></h1>
+<blockquote>
+<p>bar</p>
+</blockquote>
+````````````````````````````````
+
+```````````````````````````````` example
+[foo]: /url
+bar
+===
+[foo]
+.
+<h1>bar</h1>
+<p><a href="/url">foo</a></p>
+````````````````````````````````
+
+```````````````````````````````` example
+[foo]: /url
+===
+[foo]
+.
+<p>===
+<a href="/url">foo</a></p>
+````````````````````````````````
+
+
+Several [link reference definitions]
+can occur one after another, without intervening blank lines.
+
+```````````````````````````````` example
+[foo]: /foo-url "foo"
+[bar]: /bar-url
+ "bar"
+[baz]: /baz-url
+
+[foo],
+[bar],
+[baz]
+.
+<p><a href="/foo-url" title="foo">foo</a>,
+<a href="/bar-url" title="bar">bar</a>,
+<a href="/baz-url">baz</a></p>
+````````````````````````````````
+
+
+[Link reference definitions] can occur
+inside block containers, like lists and block quotations. They
+affect the entire document, not just the container in which they
+are defined:
+
+```````````````````````````````` example
+[foo]
+
+> [foo]: /url
+.
+<p><a href="/url">foo</a></p>
+<blockquote>
+</blockquote>
+````````````````````````````````
+
+
+Whether something is a [link reference definition] is
+independent of whether the link reference it defines is
+used in the document. Thus, for example, the following
+document contains just a link reference definition, and
+no visible content:
+
+```````````````````````````````` example
+[foo]: /url
+.
+````````````````````````````````
+
+
+## Paragraphs
+
+A sequence of non-blank lines that cannot be interpreted as other
+kinds of blocks forms a [paragraph](@).
+The contents of the paragraph are the result of parsing the
+paragraph's raw content as inlines. The paragraph's raw content
+is formed by concatenating the lines and removing initial and final
+[whitespace].
+
+A simple example with two paragraphs:
+
+```````````````````````````````` example
+aaa
+
+bbb
+.
+<p>aaa</p>
+<p>bbb</p>
+````````````````````````````````
+
+
+Paragraphs can contain multiple lines, but no blank lines:
+
+```````````````````````````````` example
+aaa
+bbb
+
+ccc
+ddd
+.
+<p>aaa
+bbb</p>
+<p>ccc
+ddd</p>
+````````````````````````````````
+
+
+Multiple blank lines between paragraph have no effect:
+
+```````````````````````````````` example
+aaa
+
+
+bbb
+.
+<p>aaa</p>
+<p>bbb</p>
+````````````````````````````````
+
+
+Leading spaces are skipped:
+
+```````````````````````````````` example
+ aaa
+ bbb
+.
+<p>aaa
+bbb</p>
+````````````````````````````````
+
+
+Lines after the first may be indented any amount, since indented
+code blocks cannot interrupt paragraphs.
+
+```````````````````````````````` example
+aaa
+ bbb
+ ccc
+.
+<p>aaa
+bbb
+ccc</p>
+````````````````````````````````
+
+
+However, the first line may be indented at most three spaces,
+or an indented code block will be triggered:
+
+```````````````````````````````` example
+ aaa
+bbb
+.
+<p>aaa
+bbb</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ aaa
+bbb
+.
+<pre><code>aaa
+</code></pre>
+<p>bbb</p>
+````````````````````````````````
+
+
+Final spaces are stripped before inline parsing, so a paragraph
+that ends with two or more spaces will not end with a [hard line
+break]:
+
+```````````````````````````````` example
+aaa
+bbb
+.
+<p>aaa<br />
+bbb</p>
+````````````````````````````````
+
+
+## Blank lines
+
+[Blank lines] between block-level elements are ignored,
+except for the role they play in determining whether a [list]
+is [tight] or [loose].
+
+Blank lines at the beginning and end of the document are also ignored.
+
+```````````````````````````````` example
+
+
+aaa
+
+
+# aaa
+
+
+.
+<p>aaa</p>
+<h1>aaa</h1>
+````````````````````````````````
+
+<div class="extension">
+
+## Tables (extension)
+
+GFM enables the `table` extension, where an additional leaf block type is
+available.
+
+A [table](@) is an arrangement of data with rows and columns, consisting of a
+single header row, a [delimiter row] separating the header from the data, and
+zero or more data rows.
+
+Each row consists of cells containing arbitrary text, in which [inlines] are
+parsed, separated by pipes (`|`). A leading and trailing pipe is also
+recommended for clarity of reading, and if there's otherwise parsing ambiguity.
+Spaces between pipes and cell content are trimmed. Block-level elements cannot
+be inserted in a table.
+
+The [delimiter row](@) consists of cells whose only content are hyphens (`-`),
+and optionally, a leading or trailing colon (`:`), or both, to indicate left,
+right, or center alignment respectively.
+
+```````````````````````````````` example table
+| foo | bar |
+| --- | --- |
+| baz | bim |
+.
+<table>
+<thead>
+<tr>
+<th>foo</th>
+<th>bar</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>baz</td>
+<td>bim</td>
+</tr>
+</tbody>
+</table>
+````````````````````````````````
+
+Cells in one column don't need to match length, though it's easier to read if
+they are. Likewise, use of leading and trailing pipes may be inconsistent:
+
+```````````````````````````````` example table
+| abc | defghi |
+:-: | -----------:
+bar | baz
+.
+<table>
+<thead>
+<tr>
+<th align="center">abc</th>
+<th align="right">defghi</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">bar</td>
+<td align="right">baz</td>
+</tr>
+</tbody>
+</table>
+````````````````````````````````
+
+Include a pipe in a cell's content by escaping it, including inside other
+inline spans:
+
+```````````````````````````````` example table
+| f\|oo |
+| ------ |
+| b `\|` az |
+| b **\|** im |
+.
+<table>
+<thead>
+<tr>
+<th>f|oo</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>b <code>|</code> az</td>
+</tr>
+<tr>
+<td>b <strong>|</strong> im</td>
+</tr>
+</tbody>
+</table>
+````````````````````````````````
+
+The table is broken at the first empty line, or beginning of another
+block-level structure:
+
+```````````````````````````````` example table
+| abc | def |
+| --- | --- |
+| bar | baz |
+> bar
+.
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+</tbody>
+</table>
+<blockquote>
+<p>bar</p>
+</blockquote>
+````````````````````````````````
+
+```````````````````````````````` example table
+| abc | def |
+| --- | --- |
+| bar | baz |
+bar
+
+bar
+.
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+<tr>
+<td>bar</td>
+<td></td>
+</tr>
+</tbody>
+</table>
+<p>bar</p>
+````````````````````````````````
+
+The header row must match the [delimiter row] in the number of cells. If not,
+a table will not be recognized:
+
+```````````````````````````````` example table
+| abc | def |
+| --- |
+| bar |
+.
+<p>| abc | def |
+| --- |
+| bar |</p>
+````````````````````````````````
+
+The remainder of the table's rows may vary in the number of cells. If there
+are a number of cells fewer than the number of cells in the header row, empty
+cells are inserted. If there are greater, the excess is ignored:
+
+```````````````````````````````` example table
+| abc | def |
+| --- | --- |
+| bar |
+| bar | baz | boo |
+.
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td></td>
+</tr>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+</tbody>
+</table>
+````````````````````````````````
+
+If there are no rows in the body, no `<tbody>` is generated in HTML output:
+
+```````````````````````````````` example table
+| abc | def |
+| --- | --- |
+.
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+</table>
+````````````````````````````````
+
+</div>
+
+# Container blocks
+
+A [container block](#container-blocks) is a block that has other
+blocks as its contents. There are two basic kinds of container blocks:
+[block quotes] and [list items].
+[Lists] are meta-containers for [list items].
+
+We define the syntax for container blocks recursively. The general
+form of the definition is:
+
+> If X is a sequence of blocks, then the result of
+> transforming X in such-and-such a way is a container of type Y
+> with these blocks as its content.
+
+So, we explain what counts as a block quote or list item by explaining
+how these can be *generated* from their contents. This should suffice
+to define the syntax, although it does not give a recipe for *parsing*
+these constructions. (A recipe is provided below in the section entitled
+[A parsing strategy](#appendix-a-parsing-strategy).)
+
+## Block quotes
+
+A [block quote marker](@)
+consists of 0-3 spaces of initial indent, plus (a) the character `>` together
+with a following space, or (b) a single character `>` not followed by a space.
+
+The following rules define [block quotes]:
+
+1. **Basic case.** If a string of lines *Ls* constitute a sequence
+ of blocks *Bs*, then the result of prepending a [block quote
+ marker] to the beginning of each line in *Ls*
+ is a [block quote](#block-quotes) containing *Bs*.
+
+2. **Laziness.** If a string of lines *Ls* constitute a [block
+ quote](#block-quotes) with contents *Bs*, then the result of deleting
+ the initial [block quote marker] from one or
+ more lines in which the next [non-whitespace character] after the [block
+ quote marker] is [paragraph continuation
+ text] is a block quote with *Bs* as its content.
+ [Paragraph continuation text](@) is text
+ that will be parsed as part of the content of a paragraph, but does
+ not occur at the beginning of the paragraph.
+
+3. **Consecutiveness.** A document cannot contain two [block
+ quotes] in a row unless there is a [blank line] between them.
+
+Nothing else counts as a [block quote](#block-quotes).
+
+Here is a simple example:
+
+```````````````````````````````` example
+> # Foo
+> bar
+> baz
+.
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+````````````````````````````````
+
+
+The spaces after the `>` characters can be omitted:
+
+```````````````````````````````` example
+># Foo
+>bar
+> baz
+.
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+````````````````````````````````
+
+
+The `>` characters can be indented 1-3 spaces:
+
+```````````````````````````````` example
+ > # Foo
+ > bar
+ > baz
+.
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+````````````````````````````````
+
+
+Four spaces gives us a code block:
+
+```````````````````````````````` example
+ > # Foo
+ > bar
+ > baz
+.
+<pre><code>&gt; # Foo
+&gt; bar
+&gt; baz
+</code></pre>
+````````````````````````````````
+
+
+The Laziness clause allows us to omit the `>` before
+[paragraph continuation text]:
+
+```````````````````````````````` example
+> # Foo
+> bar
+baz
+.
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+````````````````````````````````
+
+
+A block quote can contain some lazy and some non-lazy
+continuation lines:
+
+```````````````````````````````` example
+> bar
+baz
+> foo
+.
+<blockquote>
+<p>bar
+baz
+foo</p>
+</blockquote>
+````````````````````````````````
+
+
+Laziness only applies to lines that would have been continuations of
+paragraphs had they been prepended with [block quote markers].
+For example, the `> ` cannot be omitted in the second line of
+
+``` markdown
+> foo
+> ---
+```
+
+without changing the meaning:
+
+```````````````````````````````` example
+> foo
+---
+.
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+````````````````````````````````
+
+
+Similarly, if we omit the `> ` in the second line of
+
+``` markdown
+> - foo
+> - bar
+```
+
+then the block quote ends after the first line:
+
+```````````````````````````````` example
+> - foo
+- bar
+.
+<blockquote>
+<ul>
+<li>foo</li>
+</ul>
+</blockquote>
+<ul>
+<li>bar</li>
+</ul>
+````````````````````````````````
+
+
+For the same reason, we can't omit the `> ` in front of
+subsequent lines of an indented or fenced code block:
+
+```````````````````````````````` example
+> foo
+ bar
+.
+<blockquote>
+<pre><code>foo
+</code></pre>
+</blockquote>
+<pre><code>bar
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+> ```
+foo
+```
+.
+<blockquote>
+<pre><code></code></pre>
+</blockquote>
+<p>foo</p>
+<pre><code></code></pre>
+````````````````````````````````
+
+
+Note that in the following case, we have a [lazy
+continuation line]:
+
+```````````````````````````````` example
+> foo
+ - bar
+.
+<blockquote>
+<p>foo
+- bar</p>
+</blockquote>
+````````````````````````````````
+
+
+To see why, note that in
+
+```markdown
+> foo
+> - bar
+```
+
+the `- bar` is indented too far to start a list, and can't
+be an indented code block because indented code blocks cannot
+interrupt paragraphs, so it is [paragraph continuation text].
+
+A block quote can be empty:
+
+```````````````````````````````` example
+>
+.
+<blockquote>
+</blockquote>
+````````````````````````````````
+
+
+```````````````````````````````` example
+>
+>
+>
+.
+<blockquote>
+</blockquote>
+````````````````````````````````
+
+
+A block quote can have initial or final blank lines:
+
+```````````````````````````````` example
+>
+> foo
+>
+.
+<blockquote>
+<p>foo</p>
+</blockquote>
+````````````````````````````````
+
+
+A blank line always separates block quotes:
+
+```````````````````````````````` example
+> foo
+
+> bar
+.
+<blockquote>
+<p>foo</p>
+</blockquote>
+<blockquote>
+<p>bar</p>
+</blockquote>
+````````````````````````````````
+
+
+(Most current Markdown implementations, including John Gruber's
+original `Markdown.pl`, will parse this example as a single block quote
+with two paragraphs. But it seems better to allow the author to decide
+whether two block quotes or one are wanted.)
+
+Consecutiveness means that if we put these block quotes together,
+we get a single block quote:
+
+```````````````````````````````` example
+> foo
+> bar
+.
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+````````````````````````````````
+
+
+To get a block quote with two paragraphs, use:
+
+```````````````````````````````` example
+> foo
+>
+> bar
+.
+<blockquote>
+<p>foo</p>
+<p>bar</p>
+</blockquote>
+````````````````````````````````
+
+
+Block quotes can interrupt paragraphs:
+
+```````````````````````````````` example
+foo
+> bar
+.
+<p>foo</p>
+<blockquote>
+<p>bar</p>
+</blockquote>
+````````````````````````````````
+
+
+In general, blank lines are not needed before or after block
+quotes:
+
+```````````````````````````````` example
+> aaa
+***
+> bbb
+.
+<blockquote>
+<p>aaa</p>
+</blockquote>
+<hr />
+<blockquote>
+<p>bbb</p>
+</blockquote>
+````````````````````````````````
+
+
+However, because of laziness, a blank line is needed between
+a block quote and a following paragraph:
+
+```````````````````````````````` example
+> bar
+baz
+.
+<blockquote>
+<p>bar
+baz</p>
+</blockquote>
+````````````````````````````````
+
+
+```````````````````````````````` example
+> bar
+
+baz
+.
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+> bar
+>
+baz
+.
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+````````````````````````````````
+
+
+It is a consequence of the Laziness rule that any number
+of initial `>`s may be omitted on a continuation line of a
+nested block quote:
+
+```````````````````````````````` example
+> > > foo
+bar
+.
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+</blockquote>
+</blockquote>
+````````````````````````````````
+
+
+```````````````````````````````` example
+>>> foo
+> bar
+>>baz
+.
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar
+baz</p>
+</blockquote>
+</blockquote>
+</blockquote>
+````````````````````````````````
+
+
+When including an indented code block in a block quote,
+remember that the [block quote marker] includes
+both the `>` and a following space. So *five spaces* are needed after
+the `>`:
+
+```````````````````````````````` example
+> code
+
+> not code
+.
+<blockquote>
+<pre><code>code
+</code></pre>
+</blockquote>
+<blockquote>
+<p>not code</p>
+</blockquote>
+````````````````````````````````
+
+
+
+## List items
+
+A [list marker](@) is a
+[bullet list marker] or an [ordered list marker].
+
+A [bullet list marker](@)
+is a `-`, `+`, or `*` character.
+
+An [ordered list marker](@)
+is a sequence of 1--9 arabic digits (`0-9`), followed by either a
+`.` character or a `)` character. (The reason for the length
+limit is that with 10 digits we start seeing integer overflows
+in some browsers.)
+
+The following rules define [list items]:
+
+1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of
+ blocks *Bs* starting with a [non-whitespace character], and *M* is a
+ list marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result
+ of prepending *M* and the following spaces to the first line of
+ *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a
+ list item with *Bs* as its contents. The type of the list item
+ (bullet or ordered) is determined by the type of its list marker.
+ If the list item is ordered, then it is also assigned a start
+ number, based on the ordered list marker.
+
+ Exceptions:
+
+ 1. When the first list item in a [list] interrupts
+ a paragraph---that is, when it starts on a line that would
+ otherwise count as [paragraph continuation text]---then (a)
+ the lines *Ls* must not begin with a blank line, and (b) if
+ the list item is ordered, the start number must be 1.
+ 2. If any line is a [thematic break][thematic breaks] then
+ that line is not a list item.
+
+For example, let *Ls* be the lines
+
+```````````````````````````````` example
+A paragraph
+with two lines.
+
+ indented code
+
+> A block quote.
+.
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+````````````````````````````````
+
+
+And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says
+that the following is an ordered list item with start number 1,
+and the same contents as *Ls*:
+
+```````````````````````````````` example
+1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+The most important thing to notice is that the position of
+the text after the list marker determines how much indentation
+is needed in subsequent blocks in the list item. If the list
+marker takes up two spaces, and there are three spaces between
+the list marker and the next [non-whitespace character], then blocks
+must be indented five spaces in order to fall under the list
+item.
+
+Here are some examples showing how far content must be indented to be
+put under the list item:
+
+```````````````````````````````` example
+- one
+
+ two
+.
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- one
+
+ two
+.
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ - one
+
+ two
+.
+<ul>
+<li>one</li>
+</ul>
+<pre><code> two
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ - one
+
+ two
+.
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+It is tempting to think of this in terms of columns: the continuation
+blocks must be indented at least to the column of the first
+[non-whitespace character] after the list marker. However, that is not quite right.
+The spaces after the list marker determine how much relative indentation
+is needed. Which column this indentation reaches will depend on
+how the list item is embedded in other constructions, as shown by
+this example:
+
+```````````````````````````````` example
+ > > 1. one
+>>
+>> two
+.
+<blockquote>
+<blockquote>
+<ol>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ol>
+</blockquote>
+</blockquote>
+````````````````````````````````
+
+
+Here `two` occurs in the same column as the list marker `1.`,
+but is actually contained in the list item, because there is
+sufficient indentation after the last containing blockquote marker.
+
+The converse is also possible. In the following example, the word `two`
+occurs far to the right of the initial text of the list item, `one`, but
+it is not considered part of the list item, because it is not indented
+far enough past the blockquote marker:
+
+```````````````````````````````` example
+>>- one
+>>
+ > > two
+.
+<blockquote>
+<blockquote>
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+</blockquote>
+</blockquote>
+````````````````````````````````
+
+
+Note that at least one space is needed between the list marker and
+any following content, so these are not list items:
+
+```````````````````````````````` example
+-one
+
+2.two
+.
+<p>-one</p>
+<p>2.two</p>
+````````````````````````````````
+
+
+A list item may contain blocks that are separated by more than
+one blank line.
+
+```````````````````````````````` example
+- foo
+
+
+ bar
+.
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+A list item may contain any kind of block:
+
+```````````````````````````````` example
+1. foo
+
+ ```
+ bar
+ ```
+
+ baz
+
+ > bam
+.
+<ol>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+<blockquote>
+<p>bam</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+A list item that contains an indented code block will preserve
+empty lines within the code block verbatim.
+
+```````````````````````````````` example
+- Foo
+
+ bar
+
+
+ baz
+.
+<ul>
+<li>
+<p>Foo</p>
+<pre><code>bar
+
+
+baz
+</code></pre>
+</li>
+</ul>
+````````````````````````````````
+
+Note that ordered list start numbers must be nine digits or less:
+
+```````````````````````````````` example
+123456789. ok
+.
+<ol start="123456789">
+<li>ok</li>
+</ol>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1234567890. not ok
+.
+<p>1234567890. not ok</p>
+````````````````````````````````
+
+
+A start number may begin with 0s:
+
+```````````````````````````````` example
+0. ok
+.
+<ol start="0">
+<li>ok</li>
+</ol>
+````````````````````````````````
+
+
+```````````````````````````````` example
+003. ok
+.
+<ol start="3">
+<li>ok</li>
+</ol>
+````````````````````````````````
+
+
+A start number may not be negative:
+
+```````````````````````````````` example
+-1. not ok
+.
+<p>-1. not ok</p>
+````````````````````````````````
+
+
+
+2. **Item starting with indented code.** If a sequence of lines *Ls*
+ constitute a sequence of blocks *Bs* starting with an indented code
+ block, and *M* is a list marker of width *W* followed by
+ one space, then the result of prepending *M* and the following
+ space to the first line of *Ls*, and indenting subsequent lines of
+ *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents.
+ If a line is empty, then it need not be indented. The type of the
+ list item (bullet or ordered) is determined by the type of its list
+ marker. If the list item is ordered, then it is also assigned a
+ start number, based on the ordered list marker.
+
+An indented code block will have to be indented four spaces beyond
+the edge of the region where text will be included in the list item.
+In the following case that is 6 spaces:
+
+```````````````````````````````` example
+- foo
+
+ bar
+.
+<ul>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ul>
+````````````````````````````````
+
+
+And in this case it is 11 spaces:
+
+```````````````````````````````` example
+ 10. foo
+
+ bar
+.
+<ol start="10">
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ol>
+````````````````````````````````
+
+
+If the *first* block in the list item is an indented code block,
+then by rule #2, the contents must be indented *one* space after the
+list marker:
+
+```````````````````````````````` example
+ indented code
+
+paragraph
+
+ more code
+.
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. indented code
+
+ paragraph
+
+ more code
+.
+<ol>
+<li>
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+````````````````````````````````
+
+
+Note that an additional space indent is interpreted as space
+inside the code block:
+
+```````````````````````````````` example
+1. indented code
+
+ paragraph
+
+ more code
+.
+<ol>
+<li>
+<pre><code> indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+````````````````````````````````
+
+
+Note that rules #1 and #2 only apply to two cases: (a) cases
+in which the lines to be included in a list item begin with a
+[non-whitespace character], and (b) cases in which
+they begin with an indented code
+block. In a case like the following, where the first block begins with
+a three-space indent, the rules do not allow us to form a list item by
+indenting the whole thing and prepending a list marker:
+
+```````````````````````````````` example
+ foo
+
+bar
+.
+<p>foo</p>
+<p>bar</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- foo
+
+ bar
+.
+<ul>
+<li>foo</li>
+</ul>
+<p>bar</p>
+````````````````````````````````
+
+
+This is not a significant restriction, because when a block begins
+with 1-3 spaces indent, the indentation can always be removed without
+a change in interpretation, allowing rule #1 to be applied. So, in
+the above case:
+
+```````````````````````````````` example
+- foo
+
+ bar
+.
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+3. **Item starting with a blank line.** If a sequence of lines *Ls*
+ starting with a single [blank line] constitute a (possibly empty)
+ sequence of blocks *Bs*, not separated from each other by more than
+ one blank line, and *M* is a list marker of width *W*,
+ then the result of prepending *M* to the first line of *Ls*, and
+ indenting subsequent lines of *Ls* by *W + 1* spaces, is a list
+ item with *Bs* as its contents.
+ If a line is empty, then it need not be indented. The type of the
+ list item (bullet or ordered) is determined by the type of its list
+ marker. If the list item is ordered, then it is also assigned a
+ start number, based on the ordered list marker.
+
+Here are some list items that start with a blank line but are not empty:
+
+```````````````````````````````` example
+-
+ foo
+-
+ ```
+ bar
+ ```
+-
+ baz
+.
+<ul>
+<li>foo</li>
+<li>
+<pre><code>bar
+</code></pre>
+</li>
+<li>
+<pre><code>baz
+</code></pre>
+</li>
+</ul>
+````````````````````````````````
+
+When the list item starts with a blank line, the number of spaces
+following the list marker doesn't change the required indentation:
+
+```````````````````````````````` example
+-
+ foo
+.
+<ul>
+<li>foo</li>
+</ul>
+````````````````````````````````
+
+
+A list item can begin with at most one blank line.
+In the following example, `foo` is not part of the list
+item:
+
+```````````````````````````````` example
+-
+
+ foo
+.
+<ul>
+<li></li>
+</ul>
+<p>foo</p>
+````````````````````````````````
+
+
+Here is an empty bullet list item:
+
+```````````````````````````````` example
+- foo
+-
+- bar
+.
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+````````````````````````````````
+
+
+It does not matter whether there are spaces following the [list marker]:
+
+```````````````````````````````` example
+- foo
+-
+- bar
+.
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+````````````````````````````````
+
+
+Here is an empty ordered list item:
+
+```````````````````````````````` example
+1. foo
+2.
+3. bar
+.
+<ol>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ol>
+````````````````````````````````
+
+
+A list may start or end with an empty list item:
+
+```````````````````````````````` example
+*
+.
+<ul>
+<li></li>
+</ul>
+````````````````````````````````
+
+However, an empty list item cannot interrupt a paragraph:
+
+```````````````````````````````` example
+foo
+*
+
+foo
+1.
+.
+<p>foo
+*</p>
+<p>foo
+1.</p>
+````````````````````````````````
+
+
+4. **Indentation.** If a sequence of lines *Ls* constitutes a list item
+ according to rule #1, #2, or #3, then the result of indenting each line
+ of *Ls* by 1-3 spaces (the same for each line) also constitutes a
+ list item with the same contents and attributes. If a line is
+ empty, then it need not be indented.
+
+Indented one space:
+
+```````````````````````````````` example
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+Indented two spaces:
+
+```````````````````````````````` example
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+Indented three spaces:
+
+```````````````````````````````` example
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+Four spaces indent gives a code block:
+
+```````````````````````````````` example
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<pre><code>1. A paragraph
+ with two lines.
+
+ indented code
+
+ &gt; A block quote.
+</code></pre>
+````````````````````````````````
+
+
+
+5. **Laziness.** If a string of lines *Ls* constitute a [list
+ item](#list-items) with contents *Bs*, then the result of deleting
+ some or all of the indentation from one or more lines in which the
+ next [non-whitespace character] after the indentation is
+ [paragraph continuation text] is a
+ list item with the same contents and attributes. The unindented
+ lines are called
+ [lazy continuation line](@)s.
+
+Here is an example with [lazy continuation lines]:
+
+```````````````````````````````` example
+ 1. A paragraph
+with two lines.
+
+ indented code
+
+ > A block quote.
+.
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+````````````````````````````````
+
+
+Indentation can be partially deleted:
+
+```````````````````````````````` example
+ 1. A paragraph
+ with two lines.
+.
+<ol>
+<li>A paragraph
+with two lines.</li>
+</ol>
+````````````````````````````````
+
+
+These examples show how laziness can work in nested structures:
+
+```````````````````````````````` example
+> 1. > Blockquote
+continued here.
+.
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+````````````````````````````````
+
+
+```````````````````````````````` example
+> 1. > Blockquote
+> continued here.
+.
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+````````````````````````````````
+
+
+
+6. **That's all.** Nothing that is not counted as a list item by rules
+ #1--5 counts as a [list item](#list-items).
+
+The rules for sublists follow from the general rules
+[above][List items]. A sublist must be indented the same number
+of spaces a paragraph would need to be in order to be included
+in the list item.
+
+So, in this case we need two spaces indent:
+
+```````````````````````````````` example
+- foo
+ - bar
+ - baz
+ - boo
+.
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz
+<ul>
+<li>boo</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+
+One is not enough:
+
+```````````````````````````````` example
+- foo
+ - bar
+ - baz
+ - boo
+.
+<ul>
+<li>foo</li>
+<li>bar</li>
+<li>baz</li>
+<li>boo</li>
+</ul>
+````````````````````````````````
+
+
+Here we need four, because the list marker is wider:
+
+```````````````````````````````` example
+10) foo
+ - bar
+.
+<ol start="10">
+<li>foo
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+````````````````````````````````
+
+
+Three is not enough:
+
+```````````````````````````````` example
+10) foo
+ - bar
+.
+<ol start="10">
+<li>foo</li>
+</ol>
+<ul>
+<li>bar</li>
+</ul>
+````````````````````````````````
+
+
+A list may be the first block in a list item:
+
+```````````````````````````````` example
+- - foo
+.
+<ul>
+<li>
+<ul>
+<li>foo</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. - 2. foo
+.
+<ol>
+<li>
+<ul>
+<li>
+<ol start="2">
+<li>foo</li>
+</ol>
+</li>
+</ul>
+</li>
+</ol>
+````````````````````````````````
+
+
+A list item can contain a heading:
+
+```````````````````````````````` example
+- # Foo
+- Bar
+ ---
+ baz
+.
+<ul>
+<li>
+<h1>Foo</h1>
+</li>
+<li>
+<h2>Bar</h2>
+baz</li>
+</ul>
+````````````````````````````````
+
+
+### Motivation
+
+John Gruber's Markdown spec says the following about list items:
+
+1. "List markers typically start at the left margin, but may be indented
+ by up to three spaces. List markers must be followed by one or more
+ spaces or a tab."
+
+2. "To make lists look nice, you can wrap items with hanging indents....
+ But if you don't want to, you don't have to."
+
+3. "List items may consist of multiple paragraphs. Each subsequent
+ paragraph in a list item must be indented by either 4 spaces or one
+ tab."
+
+4. "It looks nice if you indent every line of the subsequent paragraphs,
+ but here again, Markdown will allow you to be lazy."
+
+5. "To put a blockquote within a list item, the blockquote's `>`
+ delimiters need to be indented."
+
+6. "To put a code block within a list item, the code block needs to be
+ indented twice — 8 spaces or two tabs."
+
+These rules specify that a paragraph under a list item must be indented
+four spaces (presumably, from the left margin, rather than the start of
+the list marker, but this is not said), and that code under a list item
+must be indented eight spaces instead of the usual four. They also say
+that a block quote must be indented, but not by how much; however, the
+example given has four spaces indentation. Although nothing is said
+about other kinds of block-level content, it is certainly reasonable to
+infer that *all* block elements under a list item, including other
+lists, must be indented four spaces. This principle has been called the
+*four-space rule*.
+
+The four-space rule is clear and principled, and if the reference
+implementation `Markdown.pl` had followed it, it probably would have
+become the standard. However, `Markdown.pl` allowed paragraphs and
+sublists to start with only two spaces indentation, at least on the
+outer level. Worse, its behavior was inconsistent: a sublist of an
+outer-level list needed two spaces indentation, but a sublist of this
+sublist needed three spaces. It is not surprising, then, that different
+implementations of Markdown have developed very different rules for
+determining what comes under a list item. (Pandoc and python-Markdown,
+for example, stuck with Gruber's syntax description and the four-space
+rule, while discount, redcarpet, marked, PHP Markdown, and others
+followed `Markdown.pl`'s behavior more closely.)
+
+Unfortunately, given the divergences between implementations, there
+is no way to give a spec for list items that will be guaranteed not
+to break any existing documents. However, the spec given here should
+correctly handle lists formatted with either the four-space rule or
+the more forgiving `Markdown.pl` behavior, provided they are laid out
+in a way that is natural for a human to read.
+
+The strategy here is to let the width and indentation of the list marker
+determine the indentation necessary for blocks to fall under the list
+item, rather than having a fixed and arbitrary number. The writer can
+think of the body of the list item as a unit which gets indented to the
+right enough to fit the list marker (and any indentation on the list
+marker). (The laziness rule, #5, then allows continuation lines to be
+unindented if needed.)
+
+This rule is superior, we claim, to any rule requiring a fixed level of
+indentation from the margin. The four-space rule is clear but
+unnatural. It is quite unintuitive that
+
+``` markdown
+- foo
+
+ bar
+
+ - baz
+```
+
+should be parsed as two lists with an intervening paragraph,
+
+``` html
+<ul>
+<li>foo</li>
+</ul>
+<p>bar</p>
+<ul>
+<li>baz</li>
+</ul>
+```
+
+as the four-space rule demands, rather than a single list,
+
+``` html
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+<ul>
+<li>baz</li>
+</ul>
+</li>
+</ul>
+```
+
+The choice of four spaces is arbitrary. It can be learned, but it is
+not likely to be guessed, and it trips up beginners regularly.
+
+Would it help to adopt a two-space rule? The problem is that such
+a rule, together with the rule allowing 1--3 spaces indentation of the
+initial list marker, allows text that is indented *less than* the
+original list marker to be included in the list item. For example,
+`Markdown.pl` parses
+
+``` markdown
+ - one
+
+ two
+```
+
+as a single list item, with `two` a continuation paragraph:
+
+``` html
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+```
+
+and similarly
+
+``` markdown
+> - one
+>
+> two
+```
+
+as
+
+``` html
+<blockquote>
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+</blockquote>
+```
+
+This is extremely unintuitive.
+
+Rather than requiring a fixed indent from the margin, we could require
+a fixed indent (say, two spaces, or even one space) from the list marker (which
+may itself be indented). This proposal would remove the last anomaly
+discussed. Unlike the spec presented above, it would count the following
+as a list item with a subparagraph, even though the paragraph `bar`
+is not indented as far as the first paragraph `foo`:
+
+``` markdown
+ 10. foo
+
+ bar
+```
+
+Arguably this text does read like a list item with `bar` as a subparagraph,
+which may count in favor of the proposal. However, on this proposal indented
+code would have to be indented six spaces after the list marker. And this
+would break a lot of existing Markdown, which has the pattern:
+
+``` markdown
+1. foo
+
+ indented code
+```
+
+where the code is indented eight spaces. The spec above, by contrast, will
+parse this text as expected, since the code block's indentation is measured
+from the beginning of `foo`.
+
+The one case that needs special treatment is a list item that *starts*
+with indented code. How much indentation is required in that case, since
+we don't have a "first paragraph" to measure from? Rule #2 simply stipulates
+that in such cases, we require one space indentation from the list marker
+(and then the normal four spaces for the indented code). This will match the
+four-space rule in cases where the list marker plus its initial indentation
+takes four spaces (a common case), but diverge in other cases.
+
+<div class="extension">
+
+## Task list items (extension)
+
+GFM enables the `tasklist` extension, where an additional processing step is
+performed on [list items].
+
+A [task list item](@) is a [list item][list items] where the first block in it
+is a paragraph which begins with a [task list item marker] and at least one
+whitespace character before any other content.
+
+A [task list item marker](@) consists of an optional number of spaces, a left
+bracket (`[`), either a whitespace character or the letter `x` in either
+lowercase or uppercase, and then a right bracket (`]`).
+
+When rendered, the [task list item marker] is replaced with a semantic checkbox element;
+in an HTML output, this would be an `<input type="checkbox">` element.
+
+If the character between the brackets is a whitespace character, the checkbox
+is unchecked. Otherwise, the checkbox is checked.
+
+This spec does not define how the checkbox elements are interacted with: in practice,
+implementors are free to render the checkboxes as disabled or inmutable elements,
+or they may dynamically handle dynamic interactions (i.e. checking, unchecking) in
+the final rendered document.
+
+```````````````````````````````` example disabled
+- [ ] foo
+- [x] bar
+.
+<ul>
+<li><input disabled="" type="checkbox"> foo</li>
+<li><input checked="" disabled="" type="checkbox"> bar</li>
+</ul>
+````````````````````````````````
+
+Task lists can be arbitrarily nested:
+
+```````````````````````````````` example disabled
+- [x] foo
+ - [ ] bar
+ - [x] baz
+- [ ] bim
+.
+<ul>
+<li><input checked="" disabled="" type="checkbox"> foo
+<ul>
+<li><input disabled="" type="checkbox"> bar</li>
+<li><input checked="" disabled="" type="checkbox"> baz</li>
+</ul>
+</li>
+<li><input disabled="" type="checkbox"> bim</li>
+</ul>
+````````````````````````````````
+
+</div>
+
+## Lists
+
+A [list](@) is a sequence of one or more
+list items [of the same type]. The list items
+may be separated by any number of blank lines.
+
+Two list items are [of the same type](@)
+if they begin with a [list marker] of the same type.
+Two list markers are of the
+same type if (a) they are bullet list markers using the same character
+(`-`, `+`, or `*`) or (b) they are ordered list numbers with the same
+delimiter (either `.` or `)`).
+
+A list is an [ordered list](@)
+if its constituent list items begin with
+[ordered list markers], and a
+[bullet list](@) if its constituent list
+items begin with [bullet list markers].
+
+The [start number](@)
+of an [ordered list] is determined by the list number of
+its initial list item. The numbers of subsequent list items are
+disregarded.
+
+A list is [loose](@) if any of its constituent
+list items are separated by blank lines, or if any of its constituent
+list items directly contain two block-level elements with a blank line
+between them. Otherwise a list is [tight](@).
+(The difference in HTML output is that paragraphs in a loose list are
+wrapped in `<p>` tags, while paragraphs in a tight list are not.)
+
+Changing the bullet or ordered list delimiter starts a new list:
+
+```````````````````````````````` example
+- foo
+- bar
++ baz
+.
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<ul>
+<li>baz</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. foo
+2. bar
+3) baz
+.
+<ol>
+<li>foo</li>
+<li>bar</li>
+</ol>
+<ol start="3">
+<li>baz</li>
+</ol>
+````````````````````````````````
+
+
+In CommonMark, a list can interrupt a paragraph. That is,
+no blank line is needed to separate a paragraph from a following
+list:
+
+```````````````````````````````` example
+Foo
+- bar
+- baz
+.
+<p>Foo</p>
+<ul>
+<li>bar</li>
+<li>baz</li>
+</ul>
+````````````````````````````````
+
+`Markdown.pl` does not allow this, through fear of triggering a list
+via a numeral in a hard-wrapped line:
+
+``` markdown
+The number of windows in my house is
+14. The number of doors is 6.
+```
+
+Oddly, though, `Markdown.pl` *does* allow a blockquote to
+interrupt a paragraph, even though the same considerations might
+apply.
+
+In CommonMark, we do allow lists to interrupt paragraphs, for
+two reasons. First, it is natural and not uncommon for people
+to start lists without blank lines:
+
+``` markdown
+I need to buy
+- new shoes
+- a coat
+- a plane ticket
+```
+
+Second, we are attracted to a
+
+> [principle of uniformity](@):
+> if a chunk of text has a certain
+> meaning, it will continue to have the same meaning when put into a
+> container block (such as a list item or blockquote).
+
+(Indeed, the spec for [list items] and [block quotes] presupposes
+this principle.) This principle implies that if
+
+``` markdown
+ * I need to buy
+ - new shoes
+ - a coat
+ - a plane ticket
+```
+
+is a list item containing a paragraph followed by a nested sublist,
+as all Markdown implementations agree it is (though the paragraph
+may be rendered without `<p>` tags, since the list is "tight"),
+then
+
+``` markdown
+I need to buy
+- new shoes
+- a coat
+- a plane ticket
+```
+
+by itself should be a paragraph followed by a nested sublist.
+
+Since it is well established Markdown practice to allow lists to
+interrupt paragraphs inside list items, the [principle of
+uniformity] requires us to allow this outside list items as
+well. ([reStructuredText](http://docutils.sourceforge.net/rst.html)
+takes a different approach, requiring blank lines before lists
+even inside other list items.)
+
+In order to solve of unwanted lists in paragraphs with
+hard-wrapped numerals, we allow only lists starting with `1` to
+interrupt paragraphs. Thus,
+
+```````````````````````````````` example
+The number of windows in my house is
+14. The number of doors is 6.
+.
+<p>The number of windows in my house is
+14. The number of doors is 6.</p>
+````````````````````````````````
+
+We may still get an unintended result in cases like
+
+```````````````````````````````` example
+The number of windows in my house is
+1. The number of doors is 6.
+.
+<p>The number of windows in my house is</p>
+<ol>
+<li>The number of doors is 6.</li>
+</ol>
+````````````````````````````````
+
+but this rule should prevent most spurious list captures.
+
+There can be any number of blank lines between items:
+
+```````````````````````````````` example
+- foo
+
+- bar
+
+
+- baz
+.
+<ul>
+<li>
+<p>foo</p>
+</li>
+<li>
+<p>bar</p>
+</li>
+<li>
+<p>baz</p>
+</li>
+</ul>
+````````````````````````````````
+
+```````````````````````````````` example
+- foo
+ - bar
+ - baz
+
+
+ bim
+.
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>
+<p>baz</p>
+<p>bim</p>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+
+To separate consecutive lists of the same type, or to separate a
+list from an indented code block that would otherwise be parsed
+as a subparagraph of the final list item, you can insert a blank HTML
+comment:
+
+```````````````````````````````` example
+- foo
+- bar
+
+<!-- -->
+
+- baz
+- bim
+.
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<!-- -->
+<ul>
+<li>baz</li>
+<li>bim</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- foo
+
+ notcode
+
+- foo
+
+<!-- -->
+
+ code
+.
+<ul>
+<li>
+<p>foo</p>
+<p>notcode</p>
+</li>
+<li>
+<p>foo</p>
+</li>
+</ul>
+<!-- -->
+<pre><code>code
+</code></pre>
+````````````````````````````````
+
+
+List items need not be indented to the same level. The following
+list items will be treated as items at the same list level,
+since none is indented enough to belong to the previous list
+item:
+
+```````````````````````````````` example
+- a
+ - b
+ - c
+ - d
+ - e
+ - f
+- g
+.
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d</li>
+<li>e</li>
+<li>f</li>
+<li>g</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. a
+
+ 2. b
+
+ 3. c
+.
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ol>
+````````````````````````````````
+
+Note, however, that list items may not be indented more than
+three spaces. Here `- e` is treated as a paragraph continuation
+line, because it is indented more than three spaces:
+
+```````````````````````````````` example
+- a
+ - b
+ - c
+ - d
+ - e
+.
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d
+- e</li>
+</ul>
+````````````````````````````````
+
+And here, `3. c` is treated as in indented code block,
+because it is indented four spaces and preceded by a
+blank line.
+
+```````````````````````````````` example
+1. a
+
+ 2. b
+
+ 3. c
+.
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+</ol>
+<pre><code>3. c
+</code></pre>
+````````````````````````````````
+
+
+This is a loose list, because there is a blank line between
+two of the list items:
+
+```````````````````````````````` example
+- a
+- b
+
+- c
+.
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+So is this, with a empty second item:
+
+```````````````````````````````` example
+* a
+*
+
+* c
+.
+<ul>
+<li>
+<p>a</p>
+</li>
+<li></li>
+<li>
+<p>c</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+These are loose lists, even though there is no space between the items,
+because one of the items directly contains two block-level elements
+with a blank line between them:
+
+```````````````````````````````` example
+- a
+- b
+
+ c
+- d
+.
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- a
+- b
+
+ [ref]: /url
+- d
+.
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+This is a tight list, because the blank lines are in a code block:
+
+```````````````````````````````` example
+- a
+- ```
+ b
+
+
+ ```
+- c
+.
+<ul>
+<li>a</li>
+<li>
+<pre><code>b
+
+
+</code></pre>
+</li>
+<li>c</li>
+</ul>
+````````````````````````````````
+
+
+This is a tight list, because the blank line is between two
+paragraphs of a sublist. So the sublist is loose while
+the outer list is tight:
+
+```````````````````````````````` example
+- a
+ - b
+
+ c
+- d
+.
+<ul>
+<li>a
+<ul>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+</ul>
+</li>
+<li>d</li>
+</ul>
+````````````````````````````````
+
+
+This is a tight list, because the blank line is inside the
+block quote:
+
+```````````````````````````````` example
+* a
+ > b
+ >
+* c
+.
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+</li>
+<li>c</li>
+</ul>
+````````````````````````````````
+
+
+This list is tight, because the consecutive block elements
+are not separated by blank lines:
+
+```````````````````````````````` example
+- a
+ > b
+ ```
+ c
+ ```
+- d
+.
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+<pre><code>c
+</code></pre>
+</li>
+<li>d</li>
+</ul>
+````````````````````````````````
+
+
+A single-paragraph list is tight:
+
+```````````````````````````````` example
+- a
+.
+<ul>
+<li>a</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- a
+ - b
+.
+<ul>
+<li>a
+<ul>
+<li>b</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+
+This list is loose, because of the blank line between the
+two block elements in the list item:
+
+```````````````````````````````` example
+1. ```
+ foo
+ ```
+
+ bar
+.
+<ol>
+<li>
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+</li>
+</ol>
+````````````````````````````````
+
+
+Here the outer list is loose, the inner list tight:
+
+```````````````````````````````` example
+* foo
+ * bar
+
+ baz
+.
+<ul>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+<p>baz</p>
+</li>
+</ul>
+````````````````````````````````
+
+
+```````````````````````````````` example
+- a
+ - b
+ - c
+
+- d
+ - e
+ - f
+.
+<ul>
+<li>
+<p>a</p>
+<ul>
+<li>b</li>
+<li>c</li>
+</ul>
+</li>
+<li>
+<p>d</p>
+<ul>
+<li>e</li>
+<li>f</li>
+</ul>
+</li>
+</ul>
+````````````````````````````````
+
+
+# Inlines
+
+Inlines are parsed sequentially from the beginning of the character
+stream to the end (left to right, in left-to-right languages).
+Thus, for example, in
+
+```````````````````````````````` example
+`hi`lo`
+.
+<p><code>hi</code>lo`</p>
+````````````````````````````````
+
+`hi` is parsed as code, leaving the backtick at the end as a literal
+backtick.
+
+
+## Backslash escapes
+
+Any ASCII punctuation character may be backslash-escaped:
+
+```````````````````````````````` example
+\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+.
+<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
+````````````````````````````````
+
+
+Backslashes before other characters are treated as literal
+backslashes:
+
+```````````````````````````````` example
+\→\A\a\ \3\φ\«
+.
+<p>\→\A\a\ \3\φ\«</p>
+````````````````````````````````
+
+
+Escaped characters are treated as regular characters and do
+not have their usual Markdown meanings:
+
+```````````````````````````````` example
+\*not emphasized*
+\<br/> not a tag
+\[not a link](/foo)
+\`not code`
+1\. not a list
+\* not a list
+\# not a heading
+\[foo]: /url "not a reference"
+\&ouml; not a character entity
+.
+<p>*not emphasized*
+&lt;br/&gt; not a tag
+[not a link](/foo)
+`not code`
+1. not a list
+* not a list
+# not a heading
+[foo]: /url &quot;not a reference&quot;
+&amp;ouml; not a character entity</p>
+````````````````````````````````
+
+
+If a backslash is itself escaped, the following character is not:
+
+```````````````````````````````` example
+\\*emphasis*
+.
+<p>\<em>emphasis</em></p>
+````````````````````````````````
+
+
+A backslash at the end of the line is a [hard line break]:
+
+```````````````````````````````` example
+foo\
+bar
+.
+<p>foo<br />
+bar</p>
+````````````````````````````````
+
+
+Backslash escapes do not work in code blocks, code spans, autolinks, or
+raw HTML:
+
+```````````````````````````````` example
+`` \[\` ``
+.
+<p><code>\[\`</code></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ \[\]
+.
+<pre><code>\[\]
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~
+\[\]
+~~~
+.
+<pre><code>\[\]
+</code></pre>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<http://example.com?find=\*>
+.
+<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<a href="/bar\/)">
+.
+<a href="/bar\/)">
+````````````````````````````````
+
+
+But they work in all other contexts, including URLs and link titles,
+link references, and [info strings] in [fenced code blocks]:
+
+```````````````````````````````` example
+[foo](/bar\* "ti\*tle")
+.
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo]
+
+[foo]: /bar\* "ti\*tle"
+.
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+``` foo\+bar
+foo
+```
+.
+<pre><code class="language-foo+bar">foo
+</code></pre>
+````````````````````````````````
+
+
+
+## Entity and numeric character references
+
+Valid HTML entity references and numeric character references
+can be used in place of the corresponding Unicode character,
+with the following exceptions:
+
+- Entity and character references are not recognized in code
+ blocks and code spans.
+
+- Entity and character references cannot stand in place of
+ special characters that define structural elements in
+ CommonMark. For example, although `&#42;` can be used
+ in place of a literal `*` character, `&#42;` cannot replace
+ `*` in emphasis delimiters, bullet list markers, or thematic
+ breaks.
+
+Conforming CommonMark parsers need not store information about
+whether a particular character was represented in the source
+using a Unicode character or an entity reference.
+
+[Entity references](@) consist of `&` + any of the valid
+HTML5 entity names + `;`. The
+document <https://html.spec.whatwg.org/multipage/entities.json>
+is used as an authoritative source for the valid entity
+references and their corresponding code points.
+
+```````````````````````````````` example
+&nbsp; &amp; &copy; &AElig; &Dcaron;
+&frac34; &HilbertSpace; &DifferentialD;
+&ClockwiseContourIntegral; &ngE;
+.
+<p>  &amp; © Æ Ď
+¾ ℋ ⅆ
+∲ ≧̸</p>
+````````````````````````````````
+
+
+[Decimal numeric character
+references](@)
+consist of `&#` + a string of 1--7 arabic digits + `;`. A
+numeric character reference is parsed as the corresponding
+Unicode character. Invalid Unicode code points will be replaced by
+the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons,
+the code point `U+0000` will also be replaced by `U+FFFD`.
+
+```````````````````````````````` example
+&#35; &#1234; &#992; &#0;
+.
+<p># Ӓ Ϡ �</p>
+````````````````````````````````
+
+
+[Hexadecimal numeric character
+references](@) consist of `&#` +
+either `X` or `x` + a string of 1-6 hexadecimal digits + `;`.
+They too are parsed as the corresponding Unicode character (this
+time specified with a hexadecimal numeral instead of decimal).
+
+```````````````````````````````` example
+&#X22; &#XD06; &#xcab;
+.
+<p>&quot; ആ ಫ</p>
+````````````````````````````````
+
+
+Here are some nonentities:
+
+```````````````````````````````` example
+&nbsp &x; &#; &#x;
+&#987654321;
+&#abcdef0;
+&ThisIsNotDefined; &hi?;
+.
+<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
+&amp;#987654321;
+&amp;#abcdef0;
+&amp;ThisIsNotDefined; &amp;hi?;</p>
+````````````````````````````````
+
+
+Although HTML5 does accept some entity references
+without a trailing semicolon (such as `&copy`), these are not
+recognized here, because it makes the grammar too ambiguous:
+
+```````````````````````````````` example
+&copy
+.
+<p>&amp;copy</p>
+````````````````````````````````
+
+
+Strings that are not on the list of HTML5 named entities are not
+recognized as entity references either:
+
+```````````````````````````````` example
+&MadeUpEntity;
+.
+<p>&amp;MadeUpEntity;</p>
+````````````````````````````````
+
+
+Entity and numeric character references are recognized in any
+context besides code spans or code blocks, including
+URLs, [link titles], and [fenced code block][] [info strings]:
+
+```````````````````````````````` example
+<a href="&ouml;&ouml;.html">
+.
+<a href="&ouml;&ouml;.html">
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
+.
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo]
+
+[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
+.
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+``` f&ouml;&ouml;
+foo
+```
+.
+<pre><code class="language-föö">foo
+</code></pre>
+````````````````````````````````
+
+
+Entity and numeric character references are treated as literal
+text in code spans and code blocks:
+
+```````````````````````````````` example
+`f&ouml;&ouml;`
+.
+<p><code>f&amp;ouml;&amp;ouml;</code></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+ f&ouml;f&ouml;
+.
+<pre><code>f&amp;ouml;f&amp;ouml;
+</code></pre>
+````````````````````````````````
+
+
+Entity and numeric character references cannot be used
+in place of symbols indicating structure in CommonMark
+documents.
+
+```````````````````````````````` example
+&#42;foo&#42;
+*foo*
+.
+<p>*foo*
+<em>foo</em></p>
+````````````````````````````````
+
+```````````````````````````````` example
+&#42; foo
+
+* foo
+.
+<p>* foo</p>
+<ul>
+<li>foo</li>
+</ul>
+````````````````````````````````
+
+```````````````````````````````` example
+foo&#10;&#10;bar
+.
+<p>foo
+
+bar</p>
+````````````````````````````````
+
+```````````````````````````````` example
+&#9;foo
+.
+<p>→foo</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[a](url &quot;tit&quot;)
+.
+<p>[a](url &quot;tit&quot;)</p>
+````````````````````````````````
+
+
+## Code spans
+
+A [backtick string](@)
+is a string of one or more backtick characters (`` ` ``) that is neither
+preceded nor followed by a backtick.
+
+A [code span](@) begins with a backtick string and ends with
+a backtick string of equal length. The contents of the code span are
+the characters between the two backtick strings, normalized in the
+following ways:
+
+- First, [line endings] are converted to [spaces].
+- If the resulting string both begins *and* ends with a [space]
+ character, but does not consist entirely of [space]
+ characters, a single [space] character is removed from the
+ front and back. This allows you to include code that begins
+ or ends with backtick characters, which must be separated by
+ whitespace from the opening or closing backtick strings.
+
+This is a simple code span:
+
+```````````````````````````````` example
+`foo`
+.
+<p><code>foo</code></p>
+````````````````````````````````
+
+
+Here two backticks are used, because the code contains a backtick.
+This example also illustrates stripping of a single leading and
+trailing space:
+
+```````````````````````````````` example
+`` foo ` bar ``
+.
+<p><code>foo ` bar</code></p>
+````````````````````````````````
+
+
+This example shows the motivation for stripping leading and trailing
+spaces:
+
+```````````````````````````````` example
+` `` `
+.
+<p><code>``</code></p>
+````````````````````````````````
+
+Note that only *one* space is stripped:
+
+```````````````````````````````` example
+` `` `
+.
+<p><code> `` </code></p>
+````````````````````````````````
+
+The stripping only happens if the space is on both
+sides of the string:
+
+```````````````````````````````` example
+` a`
+.
+<p><code> a</code></p>
+````````````````````````````````
+
+Only [spaces], and not [unicode whitespace] in general, are
+stripped in this way:
+
+```````````````````````````````` example
+` b `
+.
+<p><code> b </code></p>
+````````````````````````````````
+
+No stripping occurs if the code span contains only spaces:
+
+```````````````````````````````` example
+` `
+` `
+.
+<p><code> </code>
+<code> </code></p>
+````````````````````````````````
+
+
+[Line endings] are treated like spaces:
+
+```````````````````````````````` example
+``
+foo
+bar
+baz
+``
+.
+<p><code>foo bar baz</code></p>
+````````````````````````````````
+
+```````````````````````````````` example
+``
+foo
+``
+.
+<p><code>foo </code></p>
+````````````````````````````````
+
+
+Interior spaces are not collapsed:
+
+```````````````````````````````` example
+`foo bar
+baz`
+.
+<p><code>foo bar baz</code></p>
+````````````````````````````````
+
+Note that browsers will typically collapse consecutive spaces
+when rendering `<code>` elements, so it is recommended that
+the following CSS be used:
+
+ code{white-space: pre-wrap;}
+
+
+Note that backslash escapes do not work in code spans. All backslashes
+are treated literally:
+
+```````````````````````````````` example
+`foo\`bar`
+.
+<p><code>foo\</code>bar`</p>
+````````````````````````````````
+
+
+Backslash escapes are never needed, because one can always choose a
+string of *n* backtick characters as delimiters, where the code does
+not contain any strings of exactly *n* backtick characters.
+
+```````````````````````````````` example
+``foo`bar``
+.
+<p><code>foo`bar</code></p>
+````````````````````````````````
+
+```````````````````````````````` example
+` foo `` bar `
+.
+<p><code>foo `` bar</code></p>
+````````````````````````````````
+
+
+Code span backticks have higher precedence than any other inline
+constructs except HTML tags and autolinks. Thus, for example, this is
+not parsed as emphasized text, since the second `*` is part of a code
+span:
+
+```````````````````````````````` example
+*foo`*`
+.
+<p>*foo<code>*</code></p>
+````````````````````````````````
+
+
+And this is not parsed as a link:
+
+```````````````````````````````` example
+[not a `link](/foo`)
+.
+<p>[not a <code>link](/foo</code>)</p>
+````````````````````````````````
+
+
+Code spans, HTML tags, and autolinks have the same precedence.
+Thus, this is code:
+
+```````````````````````````````` example
+`<a href="`">`
+.
+<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
+````````````````````````````````
+
+
+But this is an HTML tag:
+
+```````````````````````````````` example
+<a href="`">`
+.
+<p><a href="`">`</p>
+````````````````````````````````
+
+
+And this is code:
+
+```````````````````````````````` example
+`<http://foo.bar.`baz>`
+.
+<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
+````````````````````````````````
+
+
+But this is an autolink:
+
+```````````````````````````````` example
+<http://foo.bar.`baz>`
+.
+<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
+````````````````````````````````
+
+
+When a backtick string is not closed by a matching backtick string,
+we just have literal backticks:
+
+```````````````````````````````` example
+```foo``
+.
+<p>```foo``</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+`foo
+.
+<p>`foo</p>
+````````````````````````````````
+
+The following case also illustrates the need for opening and
+closing backtick strings to be equal in length:
+
+```````````````````````````````` example
+`foo``bar``
+.
+<p>`foo<code>bar</code></p>
+````````````````````````````````
+
+
+## Emphasis and strong emphasis
+
+John Gruber's original [Markdown syntax
+description](http://daringfireball.net/projects/markdown/syntax#em) says:
+
+> Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
+> emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML
+> `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML `<strong>`
+> tag.
+
+This is enough for most users, but these rules leave much undecided,
+especially when it comes to nested emphasis. The original
+`Markdown.pl` test suite makes it clear that triple `***` and
+`___` delimiters can be used for strong emphasis, and most
+implementations have also allowed the following patterns:
+
+``` markdown
+***strong emph***
+***strong** in emph*
+***emph* in strong**
+**in strong *emph***
+*in emph **strong***
+```
+
+The following patterns are less widely supported, but the intent
+is clear and they are useful (especially in contexts like bibliography
+entries):
+
+``` markdown
+*emph *with emph* in it*
+**strong **with strong** in it**
+```
+
+Many implementations have also restricted intraword emphasis to
+the `*` forms, to avoid unwanted emphasis in words containing
+internal underscores. (It is best practice to put these in code
+spans, but users often do not.)
+
+``` markdown
+internal emphasis: foo*bar*baz
+no emphasis: foo_bar_baz
+```
+
+The rules given below capture all of these patterns, while allowing
+for efficient parsing strategies that do not backtrack.
+
+First, some definitions. A [delimiter run](@) is either
+a sequence of one or more `*` characters that is not preceded or
+followed by a non-backslash-escaped `*` character, or a sequence
+of one or more `_` characters that is not preceded or followed by
+a non-backslash-escaped `_` character.
+
+A [left-flanking delimiter run](@) is
+a [delimiter run] that is (1) not followed by [Unicode whitespace],
+and either (2a) not followed by a [punctuation character], or
+(2b) followed by a [punctuation character] and
+preceded by [Unicode whitespace] or a [punctuation character].
+For purposes of this definition, the beginning and the end of
+the line count as Unicode whitespace.
+
+A [right-flanking delimiter run](@) is
+a [delimiter run] that is (1) not preceded by [Unicode whitespace],
+and either (2a) not preceded by a [punctuation character], or
+(2b) preceded by a [punctuation character] and
+followed by [Unicode whitespace] or a [punctuation character].
+For purposes of this definition, the beginning and the end of
+the line count as Unicode whitespace.
+
+Here are some examples of delimiter runs.
+
+ - left-flanking but not right-flanking:
+
+ ```
+ ***abc
+ _abc
+ **"abc"
+ _"abc"
+ ```
+
+ - right-flanking but not left-flanking:
+
+ ```
+ abc***
+ abc_
+ "abc"**
+ "abc"_
+ ```
+
+ - Both left and right-flanking:
+
+ ```
+ abc***def
+ "abc"_"def"
+ ```
+
+ - Neither left nor right-flanking:
+
+ ```
+ abc *** def
+ a _ b
+ ```
+
+(The idea of distinguishing left-flanking and right-flanking
+delimiter runs based on the character before and the character
+after comes from Roopesh Chander's
+[vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags).
+vfmd uses the terminology "emphasis indicator string" instead of "delimiter
+run," and its rules for distinguishing left- and right-flanking runs
+are a bit more complex than the ones given here.)
+
+The following rules define emphasis and strong emphasis:
+
+1. A single `*` character [can open emphasis](@)
+ iff (if and only if) it is part of a [left-flanking delimiter run].
+
+2. A single `_` character [can open emphasis] iff
+ it is part of a [left-flanking delimiter run]
+ and either (a) not part of a [right-flanking delimiter run]
+ or (b) part of a [right-flanking delimiter run]
+ preceded by punctuation.
+
+3. A single `*` character [can close emphasis](@)
+ iff it is part of a [right-flanking delimiter run].
+
+4. A single `_` character [can close emphasis] iff
+ it is part of a [right-flanking delimiter run]
+ and either (a) not part of a [left-flanking delimiter run]
+ or (b) part of a [left-flanking delimiter run]
+ followed by punctuation.
+
+5. A double `**` [can open strong emphasis](@)
+ iff it is part of a [left-flanking delimiter run].
+
+6. A double `__` [can open strong emphasis] iff
+ it is part of a [left-flanking delimiter run]
+ and either (a) not part of a [right-flanking delimiter run]
+ or (b) part of a [right-flanking delimiter run]
+ preceded by punctuation.
+
+7. A double `**` [can close strong emphasis](@)
+ iff it is part of a [right-flanking delimiter run].
+
+8. A double `__` [can close strong emphasis] iff
+ it is part of a [right-flanking delimiter run]
+ and either (a) not part of a [left-flanking delimiter run]
+ or (b) part of a [left-flanking delimiter run]
+ followed by punctuation.
+
+9. Emphasis begins with a delimiter that [can open emphasis] and ends
+ with a delimiter that [can close emphasis], and that uses the same
+ character (`_` or `*`) as the opening delimiter. The
+ opening and closing delimiters must belong to separate
+ [delimiter runs]. If one of the delimiters can both
+ open and close emphasis, then the sum of the lengths of the
+ delimiter runs containing the opening and closing delimiters
+ must not be a multiple of 3 unless both lengths are
+ multiples of 3.
+
+10. Strong emphasis begins with a delimiter that
+ [can open strong emphasis] and ends with a delimiter that
+ [can close strong emphasis], and that uses the same character
+ (`_` or `*`) as the opening delimiter. The
+ opening and closing delimiters must belong to separate
+ [delimiter runs]. If one of the delimiters can both open
+ and close strong emphasis, then the sum of the lengths of
+ the delimiter runs containing the opening and closing
+ delimiters must not be a multiple of 3 unless both lengths
+ are multiples of 3.
+
+11. A literal `*` character cannot occur at the beginning or end of
+ `*`-delimited emphasis or `**`-delimited strong emphasis, unless it
+ is backslash-escaped.
+
+12. A literal `_` character cannot occur at the beginning or end of
+ `_`-delimited emphasis or `__`-delimited strong emphasis, unless it
+ is backslash-escaped.
+
+Where rules 1--12 above are compatible with multiple parsings,
+the following principles resolve ambiguity:
+
+13. The number of nestings should be minimized. Thus, for example,
+ an interpretation `<strong>...</strong>` is always preferred to
+ `<em><em>...</em></em>`.
+
+14. An interpretation `<em><strong>...</strong></em>` is always
+ preferred to `<strong><em>...</em></strong>`.
+
+15. When two potential emphasis or strong emphasis spans overlap,
+ so that the second begins before the first ends and ends after
+ the first ends, the first takes precedence. Thus, for example,
+ `*foo _bar* baz_` is parsed as `<em>foo _bar</em> baz_` rather
+ than `*foo <em>bar* baz</em>`.
+
+16. When there are two potential emphasis or strong emphasis spans
+ with the same closing delimiter, the shorter one (the one that
+ opens later) takes precedence. Thus, for example,
+ `**foo **bar baz**` is parsed as `**foo <strong>bar baz</strong>`
+ rather than `<strong>foo **bar baz</strong>`.
+
+17. Inline code spans, links, images, and HTML tags group more tightly
+ than emphasis. So, when there is a choice between an interpretation
+ that contains one of these elements and one that does not, the
+ former always wins. Thus, for example, `*[foo*](bar)` is
+ parsed as `*<a href="bar">foo*</a>` rather than as
+ `<em>[foo</em>](bar)`.
+
+These rules can be illustrated through a series of examples.
+
+Rule 1:
+
+```````````````````````````````` example
+*foo bar*
+.
+<p><em>foo bar</em></p>
+````````````````````````````````
+
+
+This is not emphasis, because the opening `*` is followed by
+whitespace, and hence not part of a [left-flanking delimiter run]:
+
+```````````````````````````````` example
+a * foo bar*
+.
+<p>a * foo bar*</p>
+````````````````````````````````
+
+
+This is not emphasis, because the opening `*` is preceded
+by an alphanumeric and followed by punctuation, and hence
+not part of a [left-flanking delimiter run]:
+
+```````````````````````````````` example
+a*"foo"*
+.
+<p>a*&quot;foo&quot;*</p>
+````````````````````````````````
+
+
+Unicode nonbreaking spaces count as whitespace, too:
+
+```````````````````````````````` example
+* a *
+.
+<p>* a *</p>
+````````````````````````````````
+
+
+Intraword emphasis with `*` is permitted:
+
+```````````````````````````````` example
+foo*bar*
+.
+<p>foo<em>bar</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+5*6*78
+.
+<p>5<em>6</em>78</p>
+````````````````````````````````
+
+
+Rule 2:
+
+```````````````````````````````` example
+_foo bar_
+.
+<p><em>foo bar</em></p>
+````````````````````````````````
+
+
+This is not emphasis, because the opening `_` is followed by
+whitespace:
+
+```````````````````````````````` example
+_ foo bar_
+.
+<p>_ foo bar_</p>
+````````````````````````````````
+
+
+This is not emphasis, because the opening `_` is preceded
+by an alphanumeric and followed by punctuation:
+
+```````````````````````````````` example
+a_"foo"_
+.
+<p>a_&quot;foo&quot;_</p>
+````````````````````````````````
+
+
+Emphasis with `_` is not allowed inside words:
+
+```````````````````````````````` example
+foo_bar_
+.
+<p>foo_bar_</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+5_6_78
+.
+<p>5_6_78</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+приÑтанÑм_ÑтремÑÑ‚ÑÑ_
+.
+<p>приÑтанÑм_ÑтремÑÑ‚ÑÑ_</p>
+````````````````````````````````
+
+
+Here `_` does not generate emphasis, because the first delimiter run
+is right-flanking and the second left-flanking:
+
+```````````````````````````````` example
+aa_"bb"_cc
+.
+<p>aa_&quot;bb&quot;_cc</p>
+````````````````````````````````
+
+
+This is emphasis, even though the opening delimiter is
+both left- and right-flanking, because it is preceded by
+punctuation:
+
+```````````````````````````````` example
+foo-_(bar)_
+.
+<p>foo-<em>(bar)</em></p>
+````````````````````````````````
+
+
+Rule 3:
+
+This is not emphasis, because the closing delimiter does
+not match the opening delimiter:
+
+```````````````````````````````` example
+_foo*
+.
+<p>_foo*</p>
+````````````````````````````````
+
+
+This is not emphasis, because the closing `*` is preceded by
+whitespace:
+
+```````````````````````````````` example
+*foo bar *
+.
+<p>*foo bar *</p>
+````````````````````````````````
+
+
+A newline also counts as whitespace:
+
+```````````````````````````````` example
+*foo bar
+*
+.
+<p>*foo bar
+*</p>
+````````````````````````````````
+
+
+This is not emphasis, because the second `*` is
+preceded by punctuation and followed by an alphanumeric
+(hence it is not part of a [right-flanking delimiter run]:
+
+```````````````````````````````` example
+*(*foo)
+.
+<p>*(*foo)</p>
+````````````````````````````````
+
+
+The point of this restriction is more easily appreciated
+with this example:
+
+```````````````````````````````` example
+*(*foo*)*
+.
+<p><em>(<em>foo</em>)</em></p>
+````````````````````````````````
+
+
+Intraword emphasis with `*` is allowed:
+
+```````````````````````````````` example
+*foo*bar
+.
+<p><em>foo</em>bar</p>
+````````````````````````````````
+
+
+
+Rule 4:
+
+This is not emphasis, because the closing `_` is preceded by
+whitespace:
+
+```````````````````````````````` example
+_foo bar _
+.
+<p>_foo bar _</p>
+````````````````````````````````
+
+
+This is not emphasis, because the second `_` is
+preceded by punctuation and followed by an alphanumeric:
+
+```````````````````````````````` example
+_(_foo)
+.
+<p>_(_foo)</p>
+````````````````````````````````
+
+
+This is emphasis within emphasis:
+
+```````````````````````````````` example
+_(_foo_)_
+.
+<p><em>(<em>foo</em>)</em></p>
+````````````````````````````````
+
+
+Intraword emphasis is disallowed for `_`:
+
+```````````````````````````````` example
+_foo_bar
+.
+<p>_foo_bar</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_приÑтанÑм_ÑтремÑÑ‚ÑÑ
+.
+<p>_приÑтанÑм_ÑтремÑÑ‚ÑÑ</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_foo_bar_baz_
+.
+<p><em>foo_bar_baz</em></p>
+````````````````````````````````
+
+
+This is emphasis, even though the closing delimiter is
+both left- and right-flanking, because it is followed by
+punctuation:
+
+```````````````````````````````` example
+_(bar)_.
+.
+<p><em>(bar)</em>.</p>
+````````````````````````````````
+
+
+Rule 5:
+
+```````````````````````````````` example
+**foo bar**
+.
+<p><strong>foo bar</strong></p>
+````````````````````````````````
+
+
+This is not strong emphasis, because the opening delimiter is
+followed by whitespace:
+
+```````````````````````````````` example
+** foo bar**
+.
+<p>** foo bar**</p>
+````````````````````````````````
+
+
+This is not strong emphasis, because the opening `**` is preceded
+by an alphanumeric and followed by punctuation, and hence
+not part of a [left-flanking delimiter run]:
+
+```````````````````````````````` example
+a**"foo"**
+.
+<p>a**&quot;foo&quot;**</p>
+````````````````````````````````
+
+
+Intraword strong emphasis with `**` is permitted:
+
+```````````````````````````````` example
+foo**bar**
+.
+<p>foo<strong>bar</strong></p>
+````````````````````````````````
+
+
+Rule 6:
+
+```````````````````````````````` example
+__foo bar__
+.
+<p><strong>foo bar</strong></p>
+````````````````````````````````
+
+
+This is not strong emphasis, because the opening delimiter is
+followed by whitespace:
+
+```````````````````````````````` example
+__ foo bar__
+.
+<p>__ foo bar__</p>
+````````````````````````````````
+
+
+A newline counts as whitespace:
+```````````````````````````````` example
+__
+foo bar__
+.
+<p>__
+foo bar__</p>
+````````````````````````````````
+
+
+This is not strong emphasis, because the opening `__` is preceded
+by an alphanumeric and followed by punctuation:
+
+```````````````````````````````` example
+a__"foo"__
+.
+<p>a__&quot;foo&quot;__</p>
+````````````````````````````````
+
+
+Intraword strong emphasis is forbidden with `__`:
+
+```````````````````````````````` example
+foo__bar__
+.
+<p>foo__bar__</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+5__6__78
+.
+<p>5__6__78</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+приÑтанÑм__ÑтремÑÑ‚ÑÑ__
+.
+<p>приÑтанÑм__ÑтремÑÑ‚ÑÑ__</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo, __bar__, baz__
+.
+<p><strong>foo, <strong>bar</strong>, baz</strong></p>
+````````````````````````````````
+
+
+This is strong emphasis, even though the opening delimiter is
+both left- and right-flanking, because it is preceded by
+punctuation:
+
+```````````````````````````````` example
+foo-__(bar)__
+.
+<p>foo-<strong>(bar)</strong></p>
+````````````````````````````````
+
+
+
+Rule 7:
+
+This is not strong emphasis, because the closing delimiter is preceded
+by whitespace:
+
+```````````````````````````````` example
+**foo bar **
+.
+<p>**foo bar **</p>
+````````````````````````````````
+
+
+(Nor can it be interpreted as an emphasized `*foo bar *`, because of
+Rule 11.)
+
+This is not strong emphasis, because the second `**` is
+preceded by punctuation and followed by an alphanumeric:
+
+```````````````````````````````` example
+**(**foo)
+.
+<p>**(**foo)</p>
+````````````````````````````````
+
+
+The point of this restriction is more easily appreciated
+with these examples:
+
+```````````````````````````````` example
+*(**foo**)*
+.
+<p><em>(<strong>foo</strong>)</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
+*Asclepias physocarpa*)**
+.
+<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
+<em>Asclepias physocarpa</em>)</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo "*bar*" foo**
+.
+<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
+````````````````````````````````
+
+
+Intraword emphasis:
+
+```````````````````````````````` example
+**foo**bar
+.
+<p><strong>foo</strong>bar</p>
+````````````````````````````````
+
+
+Rule 8:
+
+This is not strong emphasis, because the closing delimiter is
+preceded by whitespace:
+
+```````````````````````````````` example
+__foo bar __
+.
+<p>__foo bar __</p>
+````````````````````````````````
+
+
+This is not strong emphasis, because the second `__` is
+preceded by punctuation and followed by an alphanumeric:
+
+```````````````````````````````` example
+__(__foo)
+.
+<p>__(__foo)</p>
+````````````````````````````````
+
+
+The point of this restriction is more easily appreciated
+with this example:
+
+```````````````````````````````` example
+_(__foo__)_
+.
+<p><em>(<strong>foo</strong>)</em></p>
+````````````````````````````````
+
+
+Intraword strong emphasis is forbidden with `__`:
+
+```````````````````````````````` example
+__foo__bar
+.
+<p>__foo__bar</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__приÑтанÑм__ÑтремÑÑ‚ÑÑ
+.
+<p>__приÑтанÑм__ÑтремÑÑ‚ÑÑ</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo__bar__baz__
+.
+<p><strong>foo__bar__baz</strong></p>
+````````````````````````````````
+
+
+This is strong emphasis, even though the closing delimiter is
+both left- and right-flanking, because it is followed by
+punctuation:
+
+```````````````````````````````` example
+__(bar)__.
+.
+<p><strong>(bar)</strong>.</p>
+````````````````````````````````
+
+
+Rule 9:
+
+Any nonempty sequence of inline elements can be the contents of an
+emphasized span.
+
+```````````````````````````````` example
+*foo [bar](/url)*
+.
+<p><em>foo <a href="/url">bar</a></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo
+bar*
+.
+<p><em>foo
+bar</em></p>
+````````````````````````````````
+
+
+In particular, emphasis and strong emphasis can be nested
+inside emphasis:
+
+```````````````````````````````` example
+_foo __bar__ baz_
+.
+<p><em>foo <strong>bar</strong> baz</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_foo _bar_ baz_
+.
+<p><em>foo <em>bar</em> baz</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo_ bar_
+.
+<p><em><em>foo</em> bar</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo *bar**
+.
+<p><em>foo <em>bar</em></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo **bar** baz*
+.
+<p><em>foo <strong>bar</strong> baz</em></p>
+````````````````````````````````
+
+```````````````````````````````` example
+*foo**bar**baz*
+.
+<p><em>foo<strong>bar</strong>baz</em></p>
+````````````````````````````````
+
+Note that in the preceding case, the interpretation
+
+``` markdown
+<p><em>foo</em><em>bar<em></em>baz</em></p>
+```
+
+
+is precluded by the condition that a delimiter that
+can both open and close (like the `*` after `foo`)
+cannot form emphasis if the sum of the lengths of
+the delimiter runs containing the opening and
+closing delimiters is a multiple of 3 unless
+both lengths are multiples of 3.
+
+
+For the same reason, we don't get two consecutive
+emphasis sections in this example:
+
+```````````````````````````````` example
+*foo**bar*
+.
+<p><em>foo**bar</em></p>
+````````````````````````````````
+
+
+The same condition ensures that the following
+cases are all strong emphasis nested inside
+emphasis, even when the interior spaces are
+omitted:
+
+
+```````````````````````````````` example
+***foo** bar*
+.
+<p><em><strong>foo</strong> bar</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo **bar***
+.
+<p><em>foo <strong>bar</strong></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo**bar***
+.
+<p><em>foo<strong>bar</strong></em></p>
+````````````````````````````````
+
+
+When the lengths of the interior closing and opening
+delimiter runs are *both* multiples of 3, though,
+they can match to create emphasis:
+
+```````````````````````````````` example
+foo***bar***baz
+.
+<p>foo<em><strong>bar</strong></em>baz</p>
+````````````````````````````````
+
+```````````````````````````````` example
+foo******bar*********baz
+.
+<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
+````````````````````````````````
+
+
+Indefinite levels of nesting are possible:
+
+```````````````````````````````` example
+*foo **bar *baz* bim** bop*
+.
+<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo [*bar*](/url)*
+.
+<p><em>foo <a href="/url"><em>bar</em></a></em></p>
+````````````````````````````````
+
+
+There can be no empty emphasis or strong emphasis:
+
+```````````````````````````````` example
+** is not an empty emphasis
+.
+<p>** is not an empty emphasis</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**** is not an empty strong emphasis
+.
+<p>**** is not an empty strong emphasis</p>
+````````````````````````````````
+
+
+
+Rule 10:
+
+Any nonempty sequence of inline elements can be the contents of an
+strongly emphasized span.
+
+```````````````````````````````` example
+**foo [bar](/url)**
+.
+<p><strong>foo <a href="/url">bar</a></strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo
+bar**
+.
+<p><strong>foo
+bar</strong></p>
+````````````````````````````````
+
+
+In particular, emphasis and strong emphasis can be nested
+inside strong emphasis:
+
+```````````````````````````````` example
+__foo _bar_ baz__
+.
+<p><strong>foo <em>bar</em> baz</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo __bar__ baz__
+.
+<p><strong>foo <strong>bar</strong> baz</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+____foo__ bar__
+.
+<p><strong><strong>foo</strong> bar</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo **bar****
+.
+<p><strong>foo <strong>bar</strong></strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo *bar* baz**
+.
+<p><strong>foo <em>bar</em> baz</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo*bar*baz**
+.
+<p><strong>foo<em>bar</em>baz</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+***foo* bar**
+.
+<p><strong><em>foo</em> bar</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo *bar***
+.
+<p><strong>foo <em>bar</em></strong></p>
+````````````````````````````````
+
+
+Indefinite levels of nesting are possible:
+
+```````````````````````````````` example
+**foo *bar **baz**
+bim* bop**
+.
+<p><strong>foo <em>bar <strong>baz</strong>
+bim</em> bop</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo [*bar*](/url)**
+.
+<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
+````````````````````````````````
+
+
+There can be no empty emphasis or strong emphasis:
+
+```````````````````````````````` example
+__ is not an empty emphasis
+.
+<p>__ is not an empty emphasis</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+____ is not an empty strong emphasis
+.
+<p>____ is not an empty strong emphasis</p>
+````````````````````````````````
+
+
+
+Rule 11:
+
+```````````````````````````````` example
+foo ***
+.
+<p>foo ***</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo *\**
+.
+<p>foo <em>*</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo *_*
+.
+<p>foo <em>_</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo *****
+.
+<p>foo *****</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo **\***
+.
+<p>foo <strong>*</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo **_**
+.
+<p>foo <strong>_</strong></p>
+````````````````````````````````
+
+
+Note that when delimiters do not match evenly, Rule 11 determines
+that the excess literal `*` characters will appear outside of the
+emphasis, rather than inside it:
+
+```````````````````````````````` example
+**foo*
+.
+<p>*<em>foo</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo**
+.
+<p><em>foo</em>*</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+***foo**
+.
+<p>*<strong>foo</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+****foo*
+.
+<p>***<em>foo</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**foo***
+.
+<p><strong>foo</strong>*</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo****
+.
+<p><em>foo</em>***</p>
+````````````````````````````````
+
+
+
+Rule 12:
+
+```````````````````````````````` example
+foo ___
+.
+<p>foo ___</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo _\__
+.
+<p>foo <em>_</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo _*_
+.
+<p>foo <em>*</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo _____
+.
+<p>foo _____</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo __\___
+.
+<p>foo <strong>_</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo __*__
+.
+<p>foo <strong>*</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo_
+.
+<p>_<em>foo</em></p>
+````````````````````````````````
+
+
+Note that when delimiters do not match evenly, Rule 12 determines
+that the excess literal `_` characters will appear outside of the
+emphasis, rather than inside it:
+
+```````````````````````````````` example
+_foo__
+.
+<p><em>foo</em>_</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+___foo__
+.
+<p>_<strong>foo</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+____foo_
+.
+<p>___<em>foo</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo___
+.
+<p><strong>foo</strong>_</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_foo____
+.
+<p><em>foo</em>___</p>
+````````````````````````````````
+
+
+Rule 13 implies that if you want emphasis nested directly inside
+emphasis, you must use different delimiters:
+
+```````````````````````````````` example
+**foo**
+.
+<p><strong>foo</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*_foo_*
+.
+<p><em><em>foo</em></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__foo__
+.
+<p><strong>foo</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_*foo*_
+.
+<p><em><em>foo</em></em></p>
+````````````````````````````````
+
+
+However, strong emphasis within strong emphasis is possible without
+switching delimiters:
+
+```````````````````````````````` example
+****foo****
+.
+<p><strong><strong>foo</strong></strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+____foo____
+.
+<p><strong><strong>foo</strong></strong></p>
+````````````````````````````````
+
+
+
+Rule 13 can be applied to arbitrarily long sequences of
+delimiters:
+
+```````````````````````````````` example
+******foo******
+.
+<p><strong><strong><strong>foo</strong></strong></strong></p>
+````````````````````````````````
+
+
+Rule 14:
+
+```````````````````````````````` example
+***foo***
+.
+<p><em><strong>foo</strong></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_____foo_____
+.
+<p><em><strong><strong>foo</strong></strong></em></p>
+````````````````````````````````
+
+
+Rule 15:
+
+```````````````````````````````` example
+*foo _bar* baz_
+.
+<p><em>foo _bar</em> baz_</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo __bar *baz bim__ bam*
+.
+<p><em>foo <strong>bar *baz bim</strong> bam</em></p>
+````````````````````````````````
+
+
+Rule 16:
+
+```````````````````````````````` example
+**foo **bar baz**
+.
+<p>**foo <strong>bar baz</strong></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo *bar baz*
+.
+<p>*foo <em>bar baz</em></p>
+````````````````````````````````
+
+
+Rule 17:
+
+```````````````````````````````` example
+*[bar*](/url)
+.
+<p>*<a href="/url">bar*</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_foo [bar_](/url)
+.
+<p>_foo <a href="/url">bar_</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*<img src="foo" title="*"/>
+.
+<p>*<img src="foo" title="*"/></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**<a href="**">
+.
+<p>**<a href="**"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__<a href="__">
+.
+<p>__<a href="__"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*a `*`*
+.
+<p><em>a <code>*</code></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+_a `_`_
+.
+<p><em>a <code>_</code></em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+**a<http://foo.bar/?q=**>
+.
+<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+__a<http://foo.bar/?q=__>
+.
+<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
+````````````````````````````````
+
+
+<div class="extension">
+
+## Strikethrough (extension)
+
+GFM enables the `strikethrough` extension, where an additional emphasis type is
+available.
+
+Strikethrough text is any text wrapped in two tildes (`~`).
+
+```````````````````````````````` example strikethrough
+~~Hi~~ Hello, world!
+.
+<p><del>Hi</del> Hello, world!</p>
+````````````````````````````````
+
+As with regular emphasis delimiters, a new paragraph will cause strikethrough
+parsing to cease:
+
+```````````````````````````````` example strikethrough
+This ~~has a
+
+new paragraph~~.
+.
+<p>This ~~has a</p>
+<p>new paragraph~~.</p>
+````````````````````````````````
+
+</div>
+
+## Links
+
+A link contains [link text] (the visible text), a [link destination]
+(the URI that is the link destination), and optionally a [link title].
+There are two basic kinds of links in Markdown. In [inline links] the
+destination and title are given immediately after the link text. In
+[reference links] the destination and title are defined elsewhere in
+the document.
+
+A [link text](@) consists of a sequence of zero or more
+inline elements enclosed by square brackets (`[` and `]`). The
+following rules apply:
+
+- Links may not contain other links, at any level of nesting. If
+ multiple otherwise valid link definitions appear nested inside each
+ other, the inner-most definition is used.
+
+- Brackets are allowed in the [link text] only if (a) they
+ are backslash-escaped or (b) they appear as a matched pair of brackets,
+ with an open bracket `[`, a sequence of zero or more inlines, and
+ a close bracket `]`.
+
+- Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly
+ than the brackets in link text. Thus, for example,
+ `` [foo`]` `` could not be a link text, since the second `]`
+ is part of a code span.
+
+- The brackets in link text bind more tightly than markers for
+ [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link.
+
+A [link destination](@) consists of either
+
+- a sequence of zero or more characters between an opening `<` and a
+ closing `>` that contains no line breaks or unescaped
+ `<` or `>` characters, or
+
+- a nonempty sequence of characters that does not start with
+ `<`, does not include ASCII space or control characters, and
+ includes parentheses only if (a) they are backslash-escaped or
+ (b) they are part of a balanced pair of unescaped parentheses.
+ (Implementations may impose limits on parentheses nesting to
+ avoid performance issues, but at least three levels of nesting
+ should be supported.)
+
+A [link title](@) consists of either
+
+- a sequence of zero or more characters between straight double-quote
+ characters (`"`), including a `"` character only if it is
+ backslash-escaped, or
+
+- a sequence of zero or more characters between straight single-quote
+ characters (`'`), including a `'` character only if it is
+ backslash-escaped, or
+
+- a sequence of zero or more characters between matching parentheses
+ (`(...)`), including a `(` or `)` character only if it is
+ backslash-escaped.
+
+Although [link titles] may span multiple lines, they may not contain
+a [blank line].
+
+An [inline link](@) consists of a [link text] followed immediately
+by a left parenthesis `(`, optional [whitespace], an optional
+[link destination], an optional [link title] separated from the link
+destination by [whitespace], optional [whitespace], and a right
+parenthesis `)`. The link's text consists of the inlines contained
+in the [link text] (excluding the enclosing square brackets).
+The link's URI consists of the link destination, excluding enclosing
+`<...>` if present, with backslash-escapes in effect as described
+above. The link's title consists of the link title, excluding its
+enclosing delimiters, with backslash-escapes in effect as described
+above.
+
+Here is a simple inline link:
+
+```````````````````````````````` example
+[link](/uri "title")
+.
+<p><a href="/uri" title="title">link</a></p>
+````````````````````````````````
+
+
+The title may be omitted:
+
+```````````````````````````````` example
+[link](/uri)
+.
+<p><a href="/uri">link</a></p>
+````````````````````````````````
+
+
+Both the title and the destination may be omitted:
+
+```````````````````````````````` example
+[link]()
+.
+<p><a href="">link</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link](<>)
+.
+<p><a href="">link</a></p>
+````````````````````````````````
+
+The destination can only contain spaces if it is
+enclosed in pointy brackets:
+
+```````````````````````````````` example
+[link](/my uri)
+.
+<p>[link](/my uri)</p>
+````````````````````````````````
+
+```````````````````````````````` example
+[link](</my uri>)
+.
+<p><a href="/my%20uri">link</a></p>
+````````````````````````````````
+
+The destination cannot contain line breaks,
+even if enclosed in pointy brackets:
+
+```````````````````````````````` example
+[link](foo
+bar)
+.
+<p>[link](foo
+bar)</p>
+````````````````````````````````
+
+```````````````````````````````` example
+[link](<foo
+bar>)
+.
+<p>[link](<foo
+bar>)</p>
+````````````````````````````````
+
+The destination can contain `)` if it is enclosed
+in pointy brackets:
+
+```````````````````````````````` example
+[a](<b)c>)
+.
+<p><a href="b)c">a</a></p>
+````````````````````````````````
+
+Pointy brackets that enclose links must be unescaped:
+
+```````````````````````````````` example
+[link](<foo\>)
+.
+<p>[link](&lt;foo&gt;)</p>
+````````````````````````````````
+
+These are not links, because the opening pointy bracket
+is not matched properly:
+
+```````````````````````````````` example
+[a](<b)c
+[a](<b)c>
+[a](<b>c)
+.
+<p>[a](&lt;b)c
+[a](&lt;b)c&gt;
+[a](<b>c)</p>
+````````````````````````````````
+
+Parentheses inside the link destination may be escaped:
+
+```````````````````````````````` example
+[link](\(foo\))
+.
+<p><a href="(foo)">link</a></p>
+````````````````````````````````
+
+Any number of parentheses are allowed without escaping, as long as they are
+balanced:
+
+```````````````````````````````` example
+[link](foo(and(bar)))
+.
+<p><a href="foo(and(bar))">link</a></p>
+````````````````````````````````
+
+However, if you have unbalanced parentheses, you need to escape or use the
+`<...>` form:
+
+```````````````````````````````` example
+[link](foo\(and\(bar\))
+.
+<p><a href="foo(and(bar)">link</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link](<foo(and(bar)>)
+.
+<p><a href="foo(and(bar)">link</a></p>
+````````````````````````````````
+
+
+Parentheses and other symbols can also be escaped, as usual
+in Markdown:
+
+```````````````````````````````` example
+[link](foo\)\:)
+.
+<p><a href="foo):">link</a></p>
+````````````````````````````````
+
+
+A link can contain fragment identifiers and queries:
+
+```````````````````````````````` example
+[link](#fragment)
+
+[link](http://example.com#fragment)
+
+[link](http://example.com?foo=3#frag)
+.
+<p><a href="#fragment">link</a></p>
+<p><a href="http://example.com#fragment">link</a></p>
+<p><a href="http://example.com?foo=3#frag">link</a></p>
+````````````````````````````````
+
+
+Note that a backslash before a non-escapable character is
+just a backslash:
+
+```````````````````````````````` example
+[link](foo\bar)
+.
+<p><a href="foo%5Cbar">link</a></p>
+````````````````````````````````
+
+
+URL-escaping should be left alone inside the destination, as all
+URL-escaped characters are also valid URL characters. Entity and
+numerical character references in the destination will be parsed
+into the corresponding Unicode code points, as usual. These may
+be optionally URL-escaped when written as HTML, but this spec
+does not enforce any particular policy for rendering URLs in
+HTML or other formats. Renderers may make different decisions
+about how to escape or normalize URLs in the output.
+
+```````````````````````````````` example
+[link](foo%20b&auml;)
+.
+<p><a href="foo%20b%C3%A4">link</a></p>
+````````````````````````````````
+
+
+Note that, because titles can often be parsed as destinations,
+if you try to omit the destination and keep the title, you'll
+get unexpected results:
+
+```````````````````````````````` example
+[link]("title")
+.
+<p><a href="%22title%22">link</a></p>
+````````````````````````````````
+
+
+Titles may be in single quotes, double quotes, or parentheses:
+
+```````````````````````````````` example
+[link](/url "title")
+[link](/url 'title')
+[link](/url (title))
+.
+<p><a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a></p>
+````````````````````````````````
+
+
+Backslash escapes and entity and numeric character references
+may be used in titles:
+
+```````````````````````````````` example
+[link](/url "title \"&quot;")
+.
+<p><a href="/url" title="title &quot;&quot;">link</a></p>
+````````````````````````````````
+
+
+Titles must be separated from the link using a [whitespace].
+Other [Unicode whitespace] like non-breaking space doesn't work.
+
+```````````````````````````````` example
+[link](/url "title")
+.
+<p><a href="/url%C2%A0%22title%22">link</a></p>
+````````````````````````````````
+
+
+Nested balanced quotes are not allowed without escaping:
+
+```````````````````````````````` example
+[link](/url "title "and" title")
+.
+<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
+````````````````````````````````
+
+
+But it is easy to work around this by using a different quote type:
+
+```````````````````````````````` example
+[link](/url 'title "and" title')
+.
+<p><a href="/url" title="title &quot;and&quot; title">link</a></p>
+````````````````````````````````
+
+
+(Note: `Markdown.pl` did allow double quotes inside a double-quoted
+title, and its test suite included a test demonstrating this.
+But it is hard to see a good rationale for the extra complexity this
+brings, since there are already many ways---backslash escaping,
+entity and numeric character references, or using a different
+quote type for the enclosing title---to write titles containing
+double quotes. `Markdown.pl`'s handling of titles has a number
+of other strange features. For example, it allows single-quoted
+titles in inline links, but not reference links. And, in
+reference links but not inline links, it allows a title to begin
+with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows
+titles with no closing quotation mark, though 1.0.2b8 does not.
+It seems preferable to adopt a simple, rational rule that works
+the same way in inline links and link reference definitions.)
+
+[Whitespace] is allowed around the destination and title:
+
+```````````````````````````````` example
+[link]( /uri
+ "title" )
+.
+<p><a href="/uri" title="title">link</a></p>
+````````````````````````````````
+
+
+But it is not allowed between the link text and the
+following parenthesis:
+
+```````````````````````````````` example
+[link] (/uri)
+.
+<p>[link] (/uri)</p>
+````````````````````````````````
+
+
+The link text may contain balanced brackets, but not unbalanced ones,
+unless they are escaped:
+
+```````````````````````````````` example
+[link [foo [bar]]](/uri)
+.
+<p><a href="/uri">link [foo [bar]]</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link] bar](/uri)
+.
+<p>[link] bar](/uri)</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link [bar](/uri)
+.
+<p>[link <a href="/uri">bar</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link \[bar](/uri)
+.
+<p><a href="/uri">link [bar</a></p>
+````````````````````````````````
+
+
+The link text may contain inline content:
+
+```````````````````````````````` example
+[link *foo **bar** `#`*](/uri)
+.
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[![moon](moon.jpg)](/uri)
+.
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+````````````````````````````````
+
+
+However, links may not contain other links, at any level of nesting.
+
+```````````````````````````````` example
+[foo [bar](/uri)](/uri)
+.
+<p>[foo <a href="/uri">bar</a>](/uri)</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo *[bar [baz](/uri)](/uri)*](/uri)
+.
+<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![[[foo](uri1)](uri2)](uri3)
+.
+<p><img src="uri3" alt="[foo](uri2)" /></p>
+````````````````````````````````
+
+
+These cases illustrate the precedence of link text grouping over
+emphasis grouping:
+
+```````````````````````````````` example
+*[foo*](/uri)
+.
+<p>*<a href="/uri">foo*</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo *bar](baz*)
+.
+<p><a href="baz*">foo *bar</a></p>
+````````````````````````````````
+
+
+Note that brackets that *aren't* part of links do not take
+precedence:
+
+```````````````````````````````` example
+*foo [bar* baz]
+.
+<p><em>foo [bar</em> baz]</p>
+````````````````````````````````
+
+
+These cases illustrate the precedence of HTML tags, code spans,
+and autolinks over link grouping:
+
+```````````````````````````````` example
+[foo <bar attr="](baz)">
+.
+<p>[foo <bar attr="](baz)"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo`](/uri)`
+.
+<p>[foo<code>](/uri)</code></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo<http://example.com/?search=](uri)>
+.
+<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
+````````````````````````````````
+
+
+There are three kinds of [reference link](@)s:
+[full](#full-reference-link), [collapsed](#collapsed-reference-link),
+and [shortcut](#shortcut-reference-link).
+
+A [full reference link](@)
+consists of a [link text] immediately followed by a [link label]
+that [matches] a [link reference definition] elsewhere in the document.
+
+A [link label](@) begins with a left bracket (`[`) and ends
+with the first right bracket (`]`) that is not backslash-escaped.
+Between these brackets there must be at least one [non-whitespace character].
+Unescaped square bracket characters are not allowed inside the
+opening and closing square brackets of [link labels]. A link
+label can have at most 999 characters inside the square
+brackets.
+
+One label [matches](@)
+another just in case their normalized forms are equal. To normalize a
+label, strip off the opening and closing brackets,
+perform the *Unicode case fold*, strip leading and trailing
+[whitespace] and collapse consecutive internal
+[whitespace] to a single space. If there are multiple
+matching reference link definitions, the one that comes first in the
+document is used. (It is desirable in such cases to emit a warning.)
+
+The contents of the first link label are parsed as inlines, which are
+used as the link's text. The link's URI and title are provided by the
+matching [link reference definition].
+
+Here is a simple example:
+
+```````````````````````````````` example
+[foo][bar]
+
+[bar]: /url "title"
+.
+<p><a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+The rules for the [link text] are the same as with
+[inline links]. Thus:
+
+The link text may contain balanced brackets, but not unbalanced ones,
+unless they are escaped:
+
+```````````````````````````````` example
+[link [foo [bar]]][ref]
+
+[ref]: /uri
+.
+<p><a href="/uri">link [foo [bar]]</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[link \[bar][ref]
+
+[ref]: /uri
+.
+<p><a href="/uri">link [bar</a></p>
+````````````````````````````````
+
+
+The link text may contain inline content:
+
+```````````````````````````````` example
+[link *foo **bar** `#`*][ref]
+
+[ref]: /uri
+.
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[![moon](moon.jpg)][ref]
+
+[ref]: /uri
+.
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+````````````````````````````````
+
+
+However, links may not contain other links, at any level of nesting.
+
+```````````````````````````````` example
+[foo [bar](/uri)][ref]
+
+[ref]: /uri
+.
+<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo *bar [baz][ref]*][ref]
+
+[ref]: /uri
+.
+<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
+````````````````````````````````
+
+
+(In the examples above, we have two [shortcut reference links]
+instead of one [full reference link].)
+
+The following cases illustrate the precedence of link text grouping over
+emphasis grouping:
+
+```````````````````````````````` example
+*[foo*][ref]
+
+[ref]: /uri
+.
+<p>*<a href="/uri">foo*</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo *bar][ref]
+
+[ref]: /uri
+.
+<p><a href="/uri">foo *bar</a></p>
+````````````````````````````````
+
+
+These cases illustrate the precedence of HTML tags, code spans,
+and autolinks over link grouping:
+
+```````````````````````````````` example
+[foo <bar attr="][ref]">
+
+[ref]: /uri
+.
+<p>[foo <bar attr="][ref]"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo`][ref]`
+
+[ref]: /uri
+.
+<p>[foo<code>][ref]</code></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo<http://example.com/?search=][ref]>
+
+[ref]: /uri
+.
+<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
+````````````````````````````````
+
+
+Matching is case-insensitive:
+
+```````````````````````````````` example
+[foo][BaR]
+
+[bar]: /url "title"
+.
+<p><a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+Unicode case fold is used:
+
+```````````````````````````````` example
+[Толпой][Толпой] is a Russian word.
+
+[ТОЛПОЙ]: /url
+.
+<p><a href="/url">Толпой</a> is a Russian word.</p>
+````````````````````````````````
+
+
+Consecutive internal [whitespace] is treated as one space for
+purposes of determining matching:
+
+```````````````````````````````` example
+[Foo
+ bar]: /url
+
+[Baz][Foo bar]
+.
+<p><a href="/url">Baz</a></p>
+````````````````````````````````
+
+
+No [whitespace] is allowed between the [link text] and the
+[link label]:
+
+```````````````````````````````` example
+[foo] [bar]
+
+[bar]: /url "title"
+.
+<p>[foo] <a href="/url" title="title">bar</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo]
+[bar]
+
+[bar]: /url "title"
+.
+<p>[foo]
+<a href="/url" title="title">bar</a></p>
+````````````````````````````````
+
+
+This is a departure from John Gruber's original Markdown syntax
+description, which explicitly allows whitespace between the link
+text and the link label. It brings reference links in line with
+[inline links], which (according to both original Markdown and
+this spec) cannot have whitespace after the link text. More
+importantly, it prevents inadvertent capture of consecutive
+[shortcut reference links]. If whitespace is allowed between the
+link text and the link label, then in the following we will have
+a single reference link, not two shortcut reference links, as
+intended:
+
+``` markdown
+[foo]
+[bar]
+
+[foo]: /url1
+[bar]: /url2
+```
+
+(Note that [shortcut reference links] were introduced by Gruber
+himself in a beta version of `Markdown.pl`, but never included
+in the official syntax description. Without shortcut reference
+links, it is harmless to allow space between the link text and
+link label; but once shortcut references are introduced, it is
+too dangerous to allow this, as it frequently leads to
+unintended results.)
+
+When there are multiple matching [link reference definitions],
+the first is used:
+
+```````````````````````````````` example
+[foo]: /url1
+
+[foo]: /url2
+
+[bar][foo]
+.
+<p><a href="/url1">bar</a></p>
+````````````````````````````````
+
+
+Note that matching is performed on normalized strings, not parsed
+inline content. So the following does not match, even though the
+labels define equivalent inline content:
+
+```````````````````````````````` example
+[bar][foo\!]
+
+[foo!]: /url
+.
+<p>[bar][foo!]</p>
+````````````````````````````````
+
+
+[Link labels] cannot contain brackets, unless they are
+backslash-escaped:
+
+```````````````````````````````` example
+[foo][ref[]
+
+[ref[]: /uri
+.
+<p>[foo][ref[]</p>
+<p>[ref[]: /uri</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo][ref[bar]]
+
+[ref[bar]]: /uri
+.
+<p>[foo][ref[bar]]</p>
+<p>[ref[bar]]: /uri</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[[[foo]]]
+
+[[[foo]]]: /url
+.
+<p>[[[foo]]]</p>
+<p>[[[foo]]]: /url</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[foo][ref\[]
+
+[ref\[]: /uri
+.
+<p><a href="/uri">foo</a></p>
+````````````````````````````````
+
+
+Note that in this example `]` is not backslash-escaped:
+
+```````````````````````````````` example
+[bar\\]: /uri
+
+[bar\\]
+.
+<p><a href="/uri">bar\</a></p>
+````````````````````````````````
+
+
+A [link label] must contain at least one [non-whitespace character]:
+
+```````````````````````````````` example
+[]
+
+[]: /uri
+.
+<p>[]</p>
+<p>[]: /uri</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[
+ ]
+
+[
+ ]: /uri
+.
+<p>[
+]</p>
+<p>[
+]: /uri</p>
+````````````````````````````````
+
+
+A [collapsed reference link](@)
+consists of a [link label] that [matches] a
+[link reference definition] elsewhere in the
+document, followed by the string `[]`.
+The contents of the first link label are parsed as inlines,
+which are used as the link's text. The link's URI and title are
+provided by the matching reference link definition. Thus,
+`[foo][]` is equivalent to `[foo][foo]`.
+
+```````````````````````````````` example
+[foo][]
+
+[foo]: /url "title"
+.
+<p><a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[*foo* bar][]
+
+[*foo* bar]: /url "title"
+.
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+````````````````````````````````
+
+
+The link labels are case-insensitive:
+
+```````````````````````````````` example
+[Foo][]
+
+[foo]: /url "title"
+.
+<p><a href="/url" title="title">Foo</a></p>
+````````````````````````````````
+
+
+
+As with full reference links, [whitespace] is not
+allowed between the two sets of brackets:
+
+```````````````````````````````` example
+[foo]
+[]
+
+[foo]: /url "title"
+.
+<p><a href="/url" title="title">foo</a>
+[]</p>
+````````````````````````````````
+
+
+A [shortcut reference link](@)
+consists of a [link label] that [matches] a
+[link reference definition] elsewhere in the
+document and is not followed by `[]` or a link label.
+The contents of the first link label are parsed as inlines,
+which are used as the link's text. The link's URI and title
+are provided by the matching link reference definition.
+Thus, `[foo]` is equivalent to `[foo][]`.
+
+```````````````````````````````` example
+[foo]
+
+[foo]: /url "title"
+.
+<p><a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[*foo* bar]
+
+[*foo* bar]: /url "title"
+.
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[[*foo* bar]]
+
+[*foo* bar]: /url "title"
+.
+<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+[[bar [foo]
+
+[foo]: /url
+.
+<p>[[bar <a href="/url">foo</a></p>
+````````````````````````````````
+
+
+The link labels are case-insensitive:
+
+```````````````````````````````` example
+[Foo]
+
+[foo]: /url "title"
+.
+<p><a href="/url" title="title">Foo</a></p>
+````````````````````````````````
+
+
+A space after the link text should be preserved:
+
+```````````````````````````````` example
+[foo] bar
+
+[foo]: /url
+.
+<p><a href="/url">foo</a> bar</p>
+````````````````````````````````
+
+
+If you just want bracketed text, you can backslash-escape the
+opening bracket to avoid links:
+
+```````````````````````````````` example
+\[foo]
+
+[foo]: /url "title"
+.
+<p>[foo]</p>
+````````````````````````````````
+
+
+Note that this is a link, because a link label ends with the first
+following closing bracket:
+
+```````````````````````````````` example
+[foo*]: /url
+
+*[foo*]
+.
+<p>*<a href="/url">foo*</a></p>
+````````````````````````````````
+
+
+Full and compact references take precedence over shortcut
+references:
+
+```````````````````````````````` example
+[foo][bar]
+
+[foo]: /url1
+[bar]: /url2
+.
+<p><a href="/url2">foo</a></p>
+````````````````````````````````
+
+```````````````````````````````` example
+[foo][]
+
+[foo]: /url1
+.
+<p><a href="/url1">foo</a></p>
+````````````````````````````````
+
+Inline links also take precedence:
+
+```````````````````````````````` example
+[foo]()
+
+[foo]: /url1
+.
+<p><a href="">foo</a></p>
+````````````````````````````````
+
+```````````````````````````````` example
+[foo](not a link)
+
+[foo]: /url1
+.
+<p><a href="/url1">foo</a>(not a link)</p>
+````````````````````````````````
+
+In the following case `[bar][baz]` is parsed as a reference,
+`[foo]` as normal text:
+
+```````````````````````````````` example
+[foo][bar][baz]
+
+[baz]: /url
+.
+<p>[foo]<a href="/url">bar</a></p>
+````````````````````````````````
+
+
+Here, though, `[foo][bar]` is parsed as a reference, since
+`[bar]` is defined:
+
+```````````````````````````````` example
+[foo][bar][baz]
+
+[baz]: /url1
+[bar]: /url2
+.
+<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
+````````````````````````````````
+
+
+Here `[foo]` is not parsed as a shortcut reference, because it
+is followed by a link label (even though `[bar]` is not defined):
+
+```````````````````````````````` example
+[foo][bar][baz]
+
+[baz]: /url1
+[foo]: /url2
+.
+<p>[foo]<a href="/url1">bar</a></p>
+````````````````````````````````
+
+
+
+## Images
+
+Syntax for images is like the syntax for links, with one
+difference. Instead of [link text], we have an
+[image description](@). The rules for this are the
+same as for [link text], except that (a) an
+image description starts with `![` rather than `[`, and
+(b) an image description may contain links.
+An image description has inline elements
+as its contents. When an image is rendered to HTML,
+this is standardly used as the image's `alt` attribute.
+
+```````````````````````````````` example
+![foo](/url "title")
+.
+<p><img src="/url" alt="foo" title="title" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo *bar*]
+
+[foo *bar*]: train.jpg "train & tracks"
+.
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo ![bar](/url)](/url2)
+.
+<p><img src="/url2" alt="foo bar" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo [bar](/url)](/url2)
+.
+<p><img src="/url2" alt="foo bar" /></p>
+````````````````````````````````
+
+
+Though this spec is concerned with parsing, not rendering, it is
+recommended that in rendering to HTML, only the plain string content
+of the [image description] be used. Note that in
+the above example, the alt attribute's value is `foo bar`, not `foo
+[bar](/url)` or `foo <a href="/url">bar</a>`. Only the plain string
+content is rendered, without formatting.
+
+```````````````````````````````` example
+![foo *bar*][]
+
+[foo *bar*]: train.jpg "train & tracks"
+.
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo *bar*][foobar]
+
+[FOOBAR]: train.jpg "train & tracks"
+.
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo](train.jpg)
+.
+<p><img src="train.jpg" alt="foo" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+My ![foo bar](/path/to/train.jpg "title" )
+.
+<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo](<url>)
+.
+<p><img src="url" alt="foo" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![](/url)
+.
+<p><img src="/url" alt="" /></p>
+````````````````````````````````
+
+
+Reference-style:
+
+```````````````````````````````` example
+![foo][bar]
+
+[bar]: /url
+.
+<p><img src="/url" alt="foo" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![foo][bar]
+
+[BAR]: /url
+.
+<p><img src="/url" alt="foo" /></p>
+````````````````````````````````
+
+
+Collapsed:
+
+```````````````````````````````` example
+![foo][]
+
+[foo]: /url "title"
+.
+<p><img src="/url" alt="foo" title="title" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![*foo* bar][]
+
+[*foo* bar]: /url "title"
+.
+<p><img src="/url" alt="foo bar" title="title" /></p>
+````````````````````````````````
+
+
+The labels are case-insensitive:
+
+```````````````````````````````` example
+![Foo][]
+
+[foo]: /url "title"
+.
+<p><img src="/url" alt="Foo" title="title" /></p>
+````````````````````````````````
+
+
+As with reference links, [whitespace] is not allowed
+between the two sets of brackets:
+
+```````````````````````````````` example
+![foo]
+[]
+
+[foo]: /url "title"
+.
+<p><img src="/url" alt="foo" title="title" />
+[]</p>
+````````````````````````````````
+
+
+Shortcut:
+
+```````````````````````````````` example
+![foo]
+
+[foo]: /url "title"
+.
+<p><img src="/url" alt="foo" title="title" /></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+![*foo* bar]
+
+[*foo* bar]: /url "title"
+.
+<p><img src="/url" alt="foo bar" title="title" /></p>
+````````````````````````````````
+
+
+Note that link labels cannot contain unescaped brackets:
+
+```````````````````````````````` example
+![[foo]]
+
+[[foo]]: /url "title"
+.
+<p>![[foo]]</p>
+<p>[[foo]]: /url &quot;title&quot;</p>
+````````````````````````````````
+
+
+The link labels are case-insensitive:
+
+```````````````````````````````` example
+![Foo]
+
+[foo]: /url "title"
+.
+<p><img src="/url" alt="Foo" title="title" /></p>
+````````````````````````````````
+
+
+If you just want a literal `!` followed by bracketed text, you can
+backslash-escape the opening `[`:
+
+```````````````````````````````` example
+!\[foo]
+
+[foo]: /url "title"
+.
+<p>![foo]</p>
+````````````````````````````````
+
+
+If you want a link after a literal `!`, backslash-escape the
+`!`:
+
+```````````````````````````````` example
+\![foo]
+
+[foo]: /url "title"
+.
+<p>!<a href="/url" title="title">foo</a></p>
+````````````````````````````````
+
+
+## Autolinks
+
+[Autolink](@)s are absolute URIs and email addresses inside
+`<` and `>`. They are parsed as links, with the URL or email address
+as the link label.
+
+A [URI autolink](@) consists of `<`, followed by an
+[absolute URI] followed by `>`. It is parsed as
+a link to the URI, with the URI as the link's label.
+
+An [absolute URI](@),
+for these purposes, consists of a [scheme] followed by a colon (`:`)
+followed by zero or more characters other than ASCII
+[whitespace] and control characters, `<`, and `>`. If
+the URI includes these characters, they must be percent-encoded
+(e.g. `%20` for a space).
+
+For purposes of this spec, a [scheme](@) is any sequence
+of 2--32 characters beginning with an ASCII letter and followed
+by any combination of ASCII letters, digits, or the symbols plus
+("+"), period ("."), or hyphen ("-").
+
+Here are some valid autolinks:
+
+```````````````````````````````` example
+<http://foo.bar.baz>
+.
+<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<http://foo.bar.baz/test?q=hello&id=22&boolean>
+.
+<p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<irc://foo.bar:2233/baz>
+.
+<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
+````````````````````````````````
+
+
+Uppercase is also fine:
+
+```````````````````````````````` example
+<MAILTO:FOO@BAR.BAZ>
+.
+<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
+````````````````````````````````
+
+
+Note that many strings that count as [absolute URIs] for
+purposes of this spec are not valid URIs, because their
+schemes are not registered or because of other problems
+with their syntax:
+
+```````````````````````````````` example
+<a+b+c:d>
+.
+<p><a href="a+b+c:d">a+b+c:d</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<made-up-scheme://foo,bar>
+.
+<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<http://../>
+.
+<p><a href="http://../">http://../</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<localhost:5001/foo>
+.
+<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
+````````````````````````````````
+
+
+Spaces are not allowed in autolinks:
+
+```````````````````````````````` example
+<http://foo.bar/baz bim>
+.
+<p>&lt;http://foo.bar/baz bim&gt;</p>
+````````````````````````````````
+
+
+Backslash-escapes do not work inside autolinks:
+
+```````````````````````````````` example
+<http://example.com/\[\>
+.
+<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
+````````````````````````````````
+
+
+An [email autolink](@)
+consists of `<`, followed by an [email address],
+followed by `>`. The link's label is the email address,
+and the URL is `mailto:` followed by the email address.
+
+An [email address](@),
+for these purposes, is anything that matches
+the [non-normative regex from the HTML5
+spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)):
+
+ /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
+ (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
+
+Examples of email autolinks:
+
+```````````````````````````````` example
+<foo@bar.example.com>
+.
+<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<foo+special@Bar.baz-bar0.com>
+.
+<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
+````````````````````````````````
+
+
+Backslash-escapes do not work inside email autolinks:
+
+```````````````````````````````` example
+<foo\+@bar.example.com>
+.
+<p>&lt;foo+@bar.example.com&gt;</p>
+````````````````````````````````
+
+
+These are not autolinks:
+
+```````````````````````````````` example
+<>
+.
+<p>&lt;&gt;</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+< http://foo.bar >
+.
+<p>&lt; http://foo.bar &gt;</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<m:abc>
+.
+<p>&lt;m:abc&gt;</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<foo.bar.baz>
+.
+<p>&lt;foo.bar.baz&gt;</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+http://example.com
+.
+<p>http://example.com</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo@bar.example.com
+.
+<p>foo@bar.example.com</p>
+````````````````````````````````
+
+<div class="extension">
+
+## Autolinks (extension)
+
+GFM enables the `autolink` extension, where autolinks will be recognised in a
+greater number of conditions.
+
+[Autolink]s can also be constructed without requiring the use of `<` and to `>`
+to delimit them, although they will be recognized under a smaller set of
+circumstances. All such recognized autolinks can only come at the beginning of
+a line, after whitespace, or any of the delimiting characters `*`, `_`, `~`,
+and `(`.
+
+An [extended www autolink](@) will be recognized
+when the text `www.` is found followed by a [valid domain].
+A [valid domain](@) consists of segments
+of alphanumeric characters, underscores (`_`) and hyphens (`-`)
+separated by periods (`.`).
+There must be at least one period,
+and no underscores may be present in the last two segments of the domain.
+
+The scheme `http` will be inserted automatically:
+
+```````````````````````````````` example autolink
+www.commonmark.org
+.
+<p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
+````````````````````````````````
+
+After a [valid domain], zero or more non-space non-`<` characters may follow:
+
+```````````````````````````````` example autolink
+Visit www.commonmark.org/help for more information.
+.
+<p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
+````````````````````````````````
+
+We then apply [extended autolink path validation](@) as follows:
+
+Trailing punctuation (specifically, `?`, `!`, `.`, `,`, `:`, `*`, `_`, and `~`)
+will not be considered part of the autolink, though they may be included in the
+interior of the link:
+
+```````````````````````````````` example autolink
+Visit www.commonmark.org.
+
+Visit www.commonmark.org/a.b.
+.
+<p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
+<p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
+````````````````````````````````
+
+When an autolink ends in `)`, we scan the entire autolink for the total number
+of parentheses. If there is a greater number of closing parentheses than
+opening ones, we don't consider the unmatched trailing parentheses part of the
+autolink, in order to facilitate including an autolink inside a parenthesis:
+
+```````````````````````````````` example autolink
+www.google.com/search?q=Markup+(business)
+
+www.google.com/search?q=Markup+(business)))
+
+(www.google.com/search?q=Markup+(business))
+
+(www.google.com/search?q=Markup+(business)
+.
+<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
+<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
+<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+````````````````````````````````
+
+This check is only done when the link ends in a closing parentheses `)`, so if
+the only parentheses are in the interior of the autolink, no special rules are
+applied:
+
+```````````````````````````````` example autolink
+www.google.com/search?q=(business))+ok
+.
+<p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
+````````````````````````````````
+
+If an autolink ends in a semicolon (`;`), we check to see if it appears to
+resemble an [entity reference][entity references]; if the preceding text is `&`
+followed by one or more alphanumeric characters. If so, it is excluded from
+the autolink:
+
+```````````````````````````````` example autolink
+www.google.com/search?q=commonmark&hl=en
+
+www.google.com/search?q=commonmark&hl;
+.
+<p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
+<p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
+````````````````````````````````
+
+`<` immediately ends an autolink.
+
+```````````````````````````````` example autolink
+www.commonmark.org/he<lp
+.
+<p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
+````````````````````````````````
+
+An [extended url autolink](@) will be recognised when one of the schemes
+`http://`, `https://`, or `ftp://`, followed by a [valid domain], then zero or
+more non-space non-`<` characters according to
+[extended autolink path validation]:
+
+```````````````````````````````` example autolink
+http://commonmark.org
+
+(Visit https://encrypted.google.com/search?q=Markup+(business))
+
+Anonymous FTP is available at ftp://foo.bar.baz.
+.
+<p><a href="http://commonmark.org">http://commonmark.org</a></p>
+<p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
+<p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
+````````````````````````````````
+
+
+An [extended email autolink](@) will be recognised when an email address is
+recognised within any text node. Email addresses are recognised according to
+the following rules:
+
+* One ore more characters which are alphanumeric, or `.`, `-`, `_`, or `+`.
+* An `@` symbol.
+* One or more characters which are alphanumeric, or `-` or `_`,
+ separated by periods (`.`).
+ There must be at least one period.
+ The last character must not be one of `-` or `_`.
+
+The scheme `mailto:` will automatically be added to the generated link:
+
+```````````````````````````````` example autolink
+foo@bar.baz
+.
+<p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
+````````````````````````````````
+
+`+` can occur before the `@`, but not after.
+
+```````````````````````````````` example autolink
+hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
+.
+<p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
+````````````````````````````````
+
+`.`, `-`, and `_` can occur on both sides of the `@`, but only `.` may occur at
+the end of the email address, in which case it will not be considered part of
+the address:
+
+```````````````````````````````` example autolink
+a.b-c_d@a.b
+
+a.b-c_d@a.b.
+
+a.b-c_d@a.b-
+
+a.b-c_d@a.b_
+.
+<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
+<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
+<p>a.b-c_d@a.b-</p>
+<p>a.b-c_d@a.b_</p>
+````````````````````````````````
+
+</div>
+
+## Raw HTML
+
+Text between `<` and `>` that looks like an HTML tag is parsed as a
+raw HTML tag and will be rendered in HTML without escaping.
+Tag and attribute names are not limited to current HTML tags,
+so custom tags (and even, say, DocBook tags) may be used.
+
+Here is the grammar for tags:
+
+A [tag name](@) consists of an ASCII letter
+followed by zero or more ASCII letters, digits, or
+hyphens (`-`).
+
+An [attribute](@) consists of [whitespace],
+an [attribute name], and an optional
+[attribute value specification].
+
+An [attribute name](@)
+consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII
+letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML
+specification restricted to ASCII. HTML5 is laxer.)
+
+An [attribute value specification](@)
+consists of optional [whitespace],
+a `=` character, optional [whitespace], and an [attribute
+value].
+
+An [attribute value](@)
+consists of an [unquoted attribute value],
+a [single-quoted attribute value], or a [double-quoted attribute value].
+
+An [unquoted attribute value](@)
+is a nonempty string of characters not
+including [whitespace], `"`, `'`, `=`, `<`, `>`, or `` ` ``.
+
+A [single-quoted attribute value](@)
+consists of `'`, zero or more
+characters not including `'`, and a final `'`.
+
+A [double-quoted attribute value](@)
+consists of `"`, zero or more
+characters not including `"`, and a final `"`.
+
+An [open tag](@) consists of a `<` character, a [tag name],
+zero or more [attributes], optional [whitespace], an optional `/`
+character, and a `>` character.
+
+A [closing tag](@) consists of the string `</`, a
+[tag name], optional [whitespace], and the character `>`.
+
+An [HTML comment](@) consists of `<!--` + *text* + `-->`,
+where *text* does not start with `>` or `->`, does not end with `-`,
+and does not contain `--`. (See the
+[HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).)
+
+A [processing instruction](@)
+consists of the string `<?`, a string
+of characters not including the string `?>`, and the string
+`?>`.
+
+A [declaration](@) consists of the
+string `<!`, a name consisting of one or more uppercase ASCII letters,
+[whitespace], a string of characters not including the
+character `>`, and the character `>`.
+
+A [CDATA section](@) consists of
+the string `<![CDATA[`, a string of characters not including the string
+`]]>`, and the string `]]>`.
+
+An [HTML tag](@) consists of an [open tag], a [closing tag],
+an [HTML comment], a [processing instruction], a [declaration],
+or a [CDATA section].
+
+Here are some simple open tags:
+
+```````````````````````````````` example
+<a><bab><c2c>
+.
+<p><a><bab><c2c></p>
+````````````````````````````````
+
+
+Empty elements:
+
+```````````````````````````````` example
+<a/><b2/>
+.
+<p><a/><b2/></p>
+````````````````````````````````
+
+
+[Whitespace] is allowed:
+
+```````````````````````````````` example
+<a /><b2
+data="foo" >
+.
+<p><a /><b2
+data="foo" ></p>
+````````````````````````````````
+
+
+With attributes:
+
+```````````````````````````````` example
+<a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 />
+.
+<p><a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 /></p>
+````````````````````````````````
+
+
+Custom tag names can be used:
+
+```````````````````````````````` example
+Foo <responsive-image src="foo.jpg" />
+.
+<p>Foo <responsive-image src="foo.jpg" /></p>
+````````````````````````````````
+
+
+Illegal tag names, not parsed as HTML:
+
+```````````````````````````````` example
+<33> <__>
+.
+<p>&lt;33&gt; &lt;__&gt;</p>
+````````````````````````````````
+
+
+Illegal attribute names:
+
+```````````````````````````````` example
+<a h*#ref="hi">
+.
+<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
+````````````````````````````````
+
+
+Illegal attribute values:
+
+```````````````````````````````` example
+<a href="hi'> <a href=hi'>
+.
+<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
+````````````````````````````````
+
+
+Illegal [whitespace]:
+
+```````````````````````````````` example
+< a><
+foo><bar/ >
+<foo bar=baz
+bim!bop />
+.
+<p>&lt; a&gt;&lt;
+foo&gt;&lt;bar/ &gt;
+&lt;foo bar=baz
+bim!bop /&gt;</p>
+````````````````````````````````
+
+
+Missing [whitespace]:
+
+```````````````````````````````` example
+<a href='bar'title=title>
+.
+<p>&lt;a href='bar'title=title&gt;</p>
+````````````````````````````````
+
+
+Closing tags:
+
+```````````````````````````````` example
+</a></foo >
+.
+<p></a></foo ></p>
+````````````````````````````````
+
+
+Illegal attributes in closing tag:
+
+```````````````````````````````` example
+</a href="foo">
+.
+<p>&lt;/a href=&quot;foo&quot;&gt;</p>
+````````````````````````````````
+
+
+Comments:
+
+```````````````````````````````` example
+foo <!-- this is a
+comment - with hyphen -->
+.
+<p>foo <!-- this is a
+comment - with hyphen --></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo <!-- not a comment -- two hyphens -->
+.
+<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
+````````````````````````````````
+
+
+Not comments:
+
+```````````````````````````````` example
+foo <!--> foo -->
+
+foo <!-- foo--->
+.
+<p>foo &lt;!--&gt; foo --&gt;</p>
+<p>foo &lt;!-- foo---&gt;</p>
+````````````````````````````````
+
+
+Processing instructions:
+
+```````````````````````````````` example
+foo <?php echo $a; ?>
+.
+<p>foo <?php echo $a; ?></p>
+````````````````````````````````
+
+
+Declarations:
+
+```````````````````````````````` example
+foo <!ELEMENT br EMPTY>
+.
+<p>foo <!ELEMENT br EMPTY></p>
+````````````````````````````````
+
+
+CDATA sections:
+
+```````````````````````````````` example
+foo <![CDATA[>&<]]>
+.
+<p>foo <![CDATA[>&<]]></p>
+````````````````````````````````
+
+
+Entity and numeric character references are preserved in HTML
+attributes:
+
+```````````````````````````````` example
+foo <a href="&ouml;">
+.
+<p>foo <a href="&ouml;"></p>
+````````````````````````````````
+
+
+Backslash escapes do not work in HTML attributes:
+
+```````````````````````````````` example
+foo <a href="\*">
+.
+<p>foo <a href="\*"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<a href="\"">
+.
+<p>&lt;a href=&quot;&quot;&quot;&gt;</p>
+````````````````````````````````
+
+
+<div class="extension">
+
+## Disallowed Raw HTML (extension)
+
+GFM enables the `tagfilter` extension, where the following HTML tags will be
+filtered when rendering HTML output:
+
+* `<title>`
+* `<textarea>`
+* `<style>`
+* `<xmp>`
+* `<iframe>`
+* `<noembed>`
+* `<noframes>`
+* `<script>`
+* `<plaintext>`
+
+Filtering is done by replacing the leading `<` with the entity `&lt;`. These
+tags are chosen in particular as they change how HTML is interpreted in a way
+unique to them (i.e. nested HTML is interpreted differently), and this is
+usually undesireable in the context of other rendered Markdown content.
+
+All other HTML tags are left untouched.
+
+```````````````````````````````` example tagfilter
+<strong> <title> <style> <em>
+
+<blockquote>
+ <xmp> is disallowed. <XMP> is also disallowed.
+</blockquote>
+.
+<p><strong> &lt;title> &lt;style> <em></p>
+<blockquote>
+ &lt;xmp> is disallowed. &lt;XMP> is also disallowed.
+</blockquote>
+````````````````````````````````
+
+</div>
+
+## Hard line breaks
+
+A line break (not in a code span or HTML tag) that is preceded
+by two or more spaces and does not occur at the end of a block
+is parsed as a [hard line break](@) (rendered
+in HTML as a `<br />` tag):
+
+```````````````````````````````` example
+foo
+baz
+.
+<p>foo<br />
+baz</p>
+````````````````````````````````
+
+
+For a more visible alternative, a backslash before the
+[line ending] may be used instead of two spaces:
+
+```````````````````````````````` example
+foo\
+baz
+.
+<p>foo<br />
+baz</p>
+````````````````````````````````
+
+
+More than two spaces can be used:
+
+```````````````````````````````` example
+foo
+baz
+.
+<p>foo<br />
+baz</p>
+````````````````````````````````
+
+
+Leading spaces at the beginning of the next line are ignored:
+
+```````````````````````````````` example
+foo
+ bar
+.
+<p>foo<br />
+bar</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo\
+ bar
+.
+<p>foo<br />
+bar</p>
+````````````````````````````````
+
+
+Line breaks can occur inside emphasis, links, and other constructs
+that allow inline content:
+
+```````````````````````````````` example
+*foo
+bar*
+.
+<p><em>foo<br />
+bar</em></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+*foo\
+bar*
+.
+<p><em>foo<br />
+bar</em></p>
+````````````````````````````````
+
+
+Line breaks do not occur inside code spans
+
+```````````````````````````````` example
+`code
+span`
+.
+<p><code>code span</code></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+`code\
+span`
+.
+<p><code>code\ span</code></p>
+````````````````````````````````
+
+
+or HTML tags:
+
+```````````````````````````````` example
+<a href="foo
+bar">
+.
+<p><a href="foo
+bar"></p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+<a href="foo\
+bar">
+.
+<p><a href="foo\
+bar"></p>
+````````````````````````````````
+
+
+Hard line breaks are for separating inline content within a block.
+Neither syntax for hard line breaks works at the end of a paragraph or
+other block element:
+
+```````````````````````````````` example
+foo\
+.
+<p>foo\</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo
+.
+<p>foo</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+### foo\
+.
+<h3>foo\</h3>
+````````````````````````````````
+
+
+```````````````````````````````` example
+### foo
+.
+<h3>foo</h3>
+````````````````````````````````
+
+
+## Soft line breaks
+
+A regular line break (not in a code span or HTML tag) that is not
+preceded by two or more spaces or a backslash is parsed as a
+[softbreak](@). (A softbreak may be rendered in HTML either as a
+[line ending] or as a space. The result will be the same in
+browsers. In the examples here, a [line ending] will be used.)
+
+```````````````````````````````` example
+foo
+baz
+.
+<p>foo
+baz</p>
+````````````````````````````````
+
+
+Spaces at the end of the line and beginning of the next line are
+removed:
+
+```````````````````````````````` example
+foo
+ baz
+.
+<p>foo
+baz</p>
+````````````````````````````````
+
+
+A conforming parser may render a soft line break in HTML either as a
+line break or as a space.
+
+A renderer may also provide an option to render soft line breaks
+as hard line breaks.
+
+## Textual content
+
+Any characters not given an interpretation by the above rules will
+be parsed as plain textual content.
+
+```````````````````````````````` example
+hello $.;'there
+.
+<p>hello $.;'there</p>
+````````````````````````````````
+
+
+```````````````````````````````` example
+Foo χÏῆν
+.
+<p>Foo χÏῆν</p>
+````````````````````````````````
+
+
+Internal spaces are preserved verbatim:
+
+```````````````````````````````` example
+Multiple spaces
+.
+<p>Multiple spaces</p>
+````````````````````````````````
+
+
+<!-- END TESTS -->
+
+# Appendix: A parsing strategy
+
+In this appendix we describe some features of the parsing strategy
+used in the CommonMark reference implementations.
+
+## Overview
+
+Parsing has two phases:
+
+1. In the first phase, lines of input are consumed and the block
+structure of the document---its division into paragraphs, block quotes,
+list items, and so on---is constructed. Text is assigned to these
+blocks but not parsed. Link reference definitions are parsed and a
+map of links is constructed.
+
+2. In the second phase, the raw text contents of paragraphs and headings
+are parsed into sequences of Markdown inline elements (strings,
+code spans, links, emphasis, and so on), using the map of link
+references constructed in phase 1.
+
+At each point in processing, the document is represented as a tree of
+**blocks**. The root of the tree is a `document` block. The `document`
+may have any number of other blocks as **children**. These children
+may, in turn, have other blocks as children. The last child of a block
+is normally considered **open**, meaning that subsequent lines of input
+can alter its contents. (Blocks that are not open are **closed**.)
+Here, for example, is a possible document tree, with the open blocks
+marked by arrows:
+
+``` tree
+-> document
+ -> block_quote
+ paragraph
+ "Lorem ipsum dolor\nsit amet."
+ -> list (type=bullet tight=true bullet_char=-)
+ list_item
+ paragraph
+ "Qui *quodsi iracundia*"
+ -> list_item
+ -> paragraph
+ "aliquando id"
+```
+
+## Phase 1: block structure
+
+Each line that is processed has an effect on this tree. The line is
+analyzed and, depending on its contents, the document may be altered
+in one or more of the following ways:
+
+1. One or more open blocks may be closed.
+2. One or more new blocks may be created as children of the
+ last open block.
+3. Text may be added to the last (deepest) open block remaining
+ on the tree.
+
+Once a line has been incorporated into the tree in this way,
+it can be discarded, so input can be read in a stream.
+
+For each line, we follow this procedure:
+
+1. First we iterate through the open blocks, starting with the
+root document, and descending through last children down to the last
+open block. Each block imposes a condition that the line must satisfy
+if the block is to remain open. For example, a block quote requires a
+`>` character. A paragraph requires a non-blank line.
+In this phase we may match all or just some of the open
+blocks. But we cannot close unmatched blocks yet, because we may have a
+[lazy continuation line].
+
+2. Next, after consuming the continuation markers for existing
+blocks, we look for new block starts (e.g. `>` for a block quote).
+If we encounter a new block start, we close any blocks unmatched
+in step 1 before creating the new block as a child of the last
+matched block.
+
+3. Finally, we look at the remainder of the line (after block
+markers like `>`, list markers, and indentation have been consumed).
+This is text that can be incorporated into the last open
+block (a paragraph, code block, heading, or raw HTML).
+
+Setext headings are formed when we see a line of a paragraph
+that is a [setext heading underline].
+
+Reference link definitions are detected when a paragraph is closed;
+the accumulated text lines are parsed to see if they begin with
+one or more reference link definitions. Any remainder becomes a
+normal paragraph.
+
+We can see how this works by considering how the tree above is
+generated by four lines of Markdown:
+
+``` markdown
+> Lorem ipsum dolor
+sit amet.
+> - Qui *quodsi iracundia*
+> - aliquando id
+```
+
+At the outset, our document model is just
+
+``` tree
+-> document
+```
+
+The first line of our text,
+
+``` markdown
+> Lorem ipsum dolor
+```
+
+causes a `block_quote` block to be created as a child of our
+open `document` block, and a `paragraph` block as a child of
+the `block_quote`. Then the text is added to the last open
+block, the `paragraph`:
+
+``` tree
+-> document
+ -> block_quote
+ -> paragraph
+ "Lorem ipsum dolor"
+```
+
+The next line,
+
+``` markdown
+sit amet.
+```
+
+is a "lazy continuation" of the open `paragraph`, so it gets added
+to the paragraph's text:
+
+``` tree
+-> document
+ -> block_quote
+ -> paragraph
+ "Lorem ipsum dolor\nsit amet."
+```
+
+The third line,
+
+``` markdown
+> - Qui *quodsi iracundia*
+```
+
+causes the `paragraph` block to be closed, and a new `list` block
+opened as a child of the `block_quote`. A `list_item` is also
+added as a child of the `list`, and a `paragraph` as a child of
+the `list_item`. The text is then added to the new `paragraph`:
+
+``` tree
+-> document
+ -> block_quote
+ paragraph
+ "Lorem ipsum dolor\nsit amet."
+ -> list (type=bullet tight=true bullet_char=-)
+ -> list_item
+ -> paragraph
+ "Qui *quodsi iracundia*"
+```
+
+The fourth line,
+
+``` markdown
+> - aliquando id
+```
+
+causes the `list_item` (and its child the `paragraph`) to be closed,
+and a new `list_item` opened up as child of the `list`. A `paragraph`
+is added as a child of the new `list_item`, to contain the text.
+We thus obtain the final tree:
+
+``` tree
+-> document
+ -> block_quote
+ paragraph
+ "Lorem ipsum dolor\nsit amet."
+ -> list (type=bullet tight=true bullet_char=-)
+ list_item
+ paragraph
+ "Qui *quodsi iracundia*"
+ -> list_item
+ -> paragraph
+ "aliquando id"
+```
+
+## Phase 2: inline structure
+
+Once all of the input has been parsed, all open blocks are closed.
+
+We then "walk the tree," visiting every node, and parse raw
+string contents of paragraphs and headings as inlines. At this
+point we have seen all the link reference definitions, so we can
+resolve reference links as we go.
+
+``` tree
+document
+ block_quote
+ paragraph
+ str "Lorem ipsum dolor"
+ softbreak
+ str "sit amet."
+ list (type=bullet tight=true bullet_char=-)
+ list_item
+ paragraph
+ str "Qui "
+ emph
+ str "quodsi iracundia"
+ list_item
+ paragraph
+ str "aliquando id"
+```
+
+Notice how the [line ending] in the first paragraph has
+been parsed as a `softbreak`, and the asterisks in the first list item
+have become an `emph`.
+
+### An algorithm for parsing nested emphasis and links
+
+By far the trickiest part of inline parsing is handling emphasis,
+strong emphasis, links, and images. This is done using the following
+algorithm.
+
+When we're parsing inlines and we hit either
+
+- a run of `*` or `_` characters, or
+- a `[` or `![`
+
+we insert a text node with these symbols as its literal content, and we
+add a pointer to this text node to the [delimiter stack](@).
+
+The [delimiter stack] is a doubly linked list. Each
+element contains a pointer to a text node, plus information about
+
+- the type of delimiter (`[`, `![`, `*`, `_`)
+- the number of delimiters,
+- whether the delimiter is "active" (all are active to start), and
+- whether the delimiter is a potential opener, a potential closer,
+ or both (which depends on what sort of characters precede
+ and follow the delimiters).
+
+When we hit a `]` character, we call the *look for link or image*
+procedure (see below).
+
+When we hit the end of the input, we call the *process emphasis*
+procedure (see below), with `stack_bottom` = NULL.
+
+#### *look for link or image*
+
+Starting at the top of the delimiter stack, we look backwards
+through the stack for an opening `[` or `![` delimiter.
+
+- If we don't find one, we return a literal text node `]`.
+
+- If we do find one, but it's not *active*, we remove the inactive
+ delimiter from the stack, and return a literal text node `]`.
+
+- If we find one and it's active, then we parse ahead to see if
+ we have an inline link/image, reference link/image, compact reference
+ link/image, or shortcut reference link/image.
+
+ + If we don't, then we remove the opening delimiter from the
+ delimiter stack and return a literal text node `]`.
+
+ + If we do, then
+
+ * We return a link or image node whose children are the inlines
+ after the text node pointed to by the opening delimiter.
+
+ * We run *process emphasis* on these inlines, with the `[` opener
+ as `stack_bottom`.
+
+ * We remove the opening delimiter.
+
+ * If we have a link (and not an image), we also set all
+ `[` delimiters before the opening delimiter to *inactive*. (This
+ will prevent us from getting links within links.)
+
+#### *process emphasis*
+
+Parameter `stack_bottom` sets a lower bound to how far we
+descend in the [delimiter stack]. If it is NULL, we can
+go all the way to the bottom. Otherwise, we stop before
+visiting `stack_bottom`.
+
+Let `current_position` point to the element on the [delimiter stack]
+just above `stack_bottom` (or the first element if `stack_bottom`
+is NULL).
+
+We keep track of the `openers_bottom` for each delimiter
+type (`*`, `_`) and each length of the closing delimiter run
+(modulo 3). Initialize this to `stack_bottom`.
+
+Then we repeat the following until we run out of potential
+closers:
+
+- Move `current_position` forward in the delimiter stack (if needed)
+ until we find the first potential closer with delimiter `*` or `_`.
+ (This will be the potential closer closest
+ to the beginning of the input -- the first one in parse order.)
+
+- Now, look back in the stack (staying above `stack_bottom` and
+ the `openers_bottom` for this delimiter type) for the
+ first matching potential opener ("matching" means same delimiter).
+
+- If one is found:
+
+ + Figure out whether we have emphasis or strong emphasis:
+ if both closer and opener spans have length >= 2, we have
+ strong, otherwise regular.
+
+ + Insert an emph or strong emph node accordingly, after
+ the text node corresponding to the opener.
+
+ + Remove any delimiters between the opener and closer from
+ the delimiter stack.
+
+ + Remove 1 (for regular emph) or 2 (for strong emph) delimiters
+ from the opening and closing text nodes. If they become empty
+ as a result, remove them and remove the corresponding element
+ of the delimiter stack. If the closing node is removed, reset
+ `current_position` to the next element in the stack.
+
+- If none is found:
+
+ + Set `openers_bottom` to the element before `current_position`.
+ (We know that there are no openers for this kind of closer up to and
+ including this point, so this puts a lower bound on future searches.)
+
+ + If the closer at `current_position` is not a potential opener,
+ remove it from the delimiter stack (since we know it can't
+ be a closer either).
+
+ + Advance `current_position` to the next element in the stack.
+
+After we're done, we remove all delimiters above `stack_bottom` from the
+delimiter stack.
diff --git a/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt b/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt
deleted file mode 100644
index 582131d700a..00000000000
--- a/glfm_specification/input/github_flavored_markdown/ghfm_spec_v_0.29.txt
+++ /dev/null
@@ -1,10227 +0,0 @@
----
-title: GitHub Flavored Markdown Spec
-version: 0.29
-date: '2019-04-06'
-license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
-...
-
-# Introduction
-
-## What is GitHub Flavored Markdown?
-
-GitHub Flavored Markdown, often shortened as GFM, is the dialect of Markdown
-that is currently supported for user content on GitHub.com and GitHub
-Enterprise.
-
-This formal specification, based on the CommonMark Spec, defines the syntax and
-semantics of this dialect.
-
-GFM is a strict superset of CommonMark. All the features which are supported in
-GitHub user content and that are not specified on the original CommonMark Spec
-are hence known as **extensions**, and highlighted as such.
-
-While GFM supports a wide range of inputs, it's worth noting that GitHub.com
-and GitHub Enterprise perform additional post-processing and sanitization after
-GFM is converted to HTML to ensure security and consistency of the website.
-
-## What is Markdown?
-
-Markdown is a plain text format for writing structured documents,
-based on conventions for indicating formatting in email
-and usenet posts. It was developed by John Gruber (with
-help from Aaron Swartz) and released in 2004 in the form of a
-[syntax description](http://daringfireball.net/projects/markdown/syntax)
-and a Perl script (`Markdown.pl`) for converting Markdown to
-HTML. In the next decade, dozens of implementations were
-developed in many languages. Some extended the original
-Markdown syntax with conventions for footnotes, tables, and
-other document elements. Some allowed Markdown documents to be
-rendered in formats other than HTML. Websites like Reddit,
-StackOverflow, and GitHub had millions of people using Markdown.
-And Markdown started to be used beyond the web, to author books,
-articles, slide shows, letters, and lecture notes.
-
-What distinguishes Markdown from many other lightweight markup
-syntaxes, which are often easier to write, is its readability.
-As Gruber writes:
-
-> The overriding design goal for Markdown's formatting syntax is
-> to make it as readable as possible. The idea is that a
-> Markdown-formatted document should be publishable as-is, as
-> plain text, without looking like it's been marked up with tags
-> or formatting instructions.
-> (<http://daringfireball.net/projects/markdown/>)
-
-The point can be illustrated by comparing a sample of
-[AsciiDoc](http://www.methods.co.nz/asciidoc/) with
-an equivalent sample of Markdown. Here is a sample of
-AsciiDoc from the AsciiDoc manual:
-
-```
-1. List item one.
-+
-List item one continued with a second paragraph followed by an
-Indented block.
-+
-.................
-$ ls *.sh
-$ mv *.sh ~/tmp
-.................
-+
-List item continued with a third paragraph.
-
-2. List item two continued with an open block.
-+
---
-This paragraph is part of the preceding list item.
-
-a. This list is nested and does not require explicit item
-continuation.
-+
-This paragraph is part of the preceding list item.
-
-b. List item b.
-
-This paragraph belongs to item two of the outer list.
---
-```
-
-And here is the equivalent in Markdown:
-```
-1. List item one.
-
- List item one continued with a second paragraph followed by an
- Indented block.
-
- $ ls *.sh
- $ mv *.sh ~/tmp
-
- List item continued with a third paragraph.
-
-2. List item two continued with an open block.
-
- This paragraph is part of the preceding list item.
-
- 1. This list is nested and does not require explicit item continuation.
-
- This paragraph is part of the preceding list item.
-
- 2. List item b.
-
- This paragraph belongs to item two of the outer list.
-```
-
-The AsciiDoc version is, arguably, easier to write. You don't need
-to worry about indentation. But the Markdown version is much easier
-to read. The nesting of list items is apparent to the eye in the
-source, not just in the processed document.
-
-## Why is a spec needed?
-
-John Gruber's [canonical description of Markdown's
-syntax](http://daringfireball.net/projects/markdown/syntax)
-does not specify the syntax unambiguously. Here are some examples of
-questions it does not answer:
-
-1. How much indentation is needed for a sublist? The spec says that
- continuation paragraphs need to be indented four spaces, but is
- not fully explicit about sublists. It is natural to think that
- they, too, must be indented four spaces, but `Markdown.pl` does
- not require that. This is hardly a "corner case," and divergences
- between implementations on this issue often lead to surprises for
- users in real documents. (See [this comment by John
- Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).)
-
-2. Is a blank line needed before a block quote or heading?
- Most implementations do not require the blank line. However,
- this can lead to unexpected results in hard-wrapped text, and
- also to ambiguities in parsing (note that some implementations
- put the heading inside the blockquote, while others do not).
- (John Gruber has also spoken [in favor of requiring the blank
- lines](http://article.gmane.org/gmane.text.markdown.general/2146).)
-
-3. Is a blank line needed before an indented code block?
- (`Markdown.pl` requires it, but this is not mentioned in the
- documentation, and some implementations do not require it.)
-
- ``` markdown
- paragraph
- code?
- ```
-
-4. What is the exact rule for determining when list items get
- wrapped in `<p>` tags? Can a list be partially "loose" and partially
- "tight"? What should we do with a list like this?
-
- ``` markdown
- 1. one
-
- 2. two
- 3. three
- ```
-
- Or this?
-
- ``` markdown
- 1. one
- - a
-
- - b
- 2. two
- ```
-
- (There are some relevant comments by John Gruber
- [here](http://article.gmane.org/gmane.text.markdown.general/2554).)
-
-5. Can list markers be indented? Can ordered list markers be right-aligned?
-
- ``` markdown
- 8. item 1
- 9. item 2
- 10. item 2a
- ```
-
-6. Is this one list with a thematic break in its second item,
- or two lists separated by a thematic break?
-
- ``` markdown
- * a
- * * * * *
- * b
- ```
-
-7. When list markers change from numbers to bullets, do we have
- two lists or one? (The Markdown syntax description suggests two,
- but the perl scripts and many other implementations produce one.)
-
- ``` markdown
- 1. fee
- 2. fie
- - foe
- - fum
- ```
-
-8. What are the precedence rules for the markers of inline structure?
- For example, is the following a valid link, or does the code span
- take precedence ?
-
- ``` markdown
- [a backtick (`)](/url) and [another backtick (`)](/url).
- ```
-
-9. What are the precedence rules for markers of emphasis and strong
- emphasis? For example, how should the following be parsed?
-
- ``` markdown
- *foo *bar* baz*
- ```
-
-10. What are the precedence rules between block-level and inline-level
- structure? For example, how should the following be parsed?
-
- ``` markdown
- - `a long code span can contain a hyphen like this
- - and it can screw things up`
- ```
-
-11. Can list items include section headings? (`Markdown.pl` does not
- allow this, but does allow blockquotes to include headings.)
-
- ``` markdown
- - # Heading
- ```
-
-12. Can list items be empty?
-
- ``` markdown
- * a
- *
- * b
- ```
-
-13. Can link references be defined inside block quotes or list items?
-
- ``` markdown
- > Blockquote [foo].
- >
- > [foo]: /url
- ```
-
-14. If there are multiple definitions for the same reference, which takes
- precedence?
-
- ``` markdown
- [foo]: /url1
- [foo]: /url2
-
- [foo][]
- ```
-
-In the absence of a spec, early implementers consulted `Markdown.pl`
-to resolve these ambiguities. But `Markdown.pl` was quite buggy, and
-gave manifestly bad results in many cases, so it was not a
-satisfactory replacement for a spec.
-
-Because there is no unambiguous spec, implementations have diverged
-considerably. As a result, users are often surprised to find that
-a document that renders one way on one system (say, a GitHub wiki)
-renders differently on another (say, converting to docbook using
-pandoc). To make matters worse, because nothing in Markdown counts
-as a "syntax error," the divergence often isn't discovered right away.
-
-## About this document
-
-This document attempts to specify Markdown syntax unambiguously.
-It contains many examples with side-by-side Markdown and
-HTML. These are intended to double as conformance tests. An
-accompanying script `spec_tests.py` can be used to run the tests
-against any Markdown program:
-
- python test/spec_tests.py --spec spec.txt --program PROGRAM
-
-Since this document describes how Markdown is to be parsed into
-an abstract syntax tree, it would have made sense to use an abstract
-representation of the syntax tree instead of HTML. But HTML is capable
-of representing the structural distinctions we need to make, and the
-choice of HTML for the tests makes it possible to run the tests against
-an implementation without writing an abstract syntax tree renderer.
-
-This document is generated from a text file, `spec.txt`, written
-in Markdown with a small extension for the side-by-side tests.
-The script `tools/makespec.py` can be used to convert `spec.txt` into
-HTML or CommonMark (which can then be converted into other formats).
-
-In the examples, the `→` character is used to represent tabs.
-
-# Preliminaries
-
-## Characters and lines
-
-Any sequence of [characters] is a valid CommonMark
-document.
-
-A [character](@) is a Unicode code point. Although some
-code points (for example, combining accents) do not correspond to
-characters in an intuitive sense, all code points count as characters
-for purposes of this spec.
-
-This spec does not specify an encoding; it thinks of lines as composed
-of [characters] rather than bytes. A conforming parser may be limited
-to a certain encoding.
-
-A [line](@) is a sequence of zero or more [characters]
-other than newline (`U+000A`) or carriage return (`U+000D`),
-followed by a [line ending] or by the end of file.
-
-A [line ending](@) is a newline (`U+000A`), a carriage return
-(`U+000D`) not followed by a newline, or a carriage return and a
-following newline.
-
-A line containing no characters, or a line containing only spaces
-(`U+0020`) or tabs (`U+0009`), is called a [blank line](@).
-
-The following definitions of character classes will be used in this spec:
-
-A [whitespace character](@) is a space
-(`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`),
-form feed (`U+000C`), or carriage return (`U+000D`).
-
-[Whitespace](@) is a sequence of one or more [whitespace
-characters].
-
-A [Unicode whitespace character](@) is
-any code point in the Unicode `Zs` general category, or a tab (`U+0009`),
-carriage return (`U+000D`), newline (`U+000A`), or form feed
-(`U+000C`).
-
-[Unicode whitespace](@) is a sequence of one
-or more [Unicode whitespace characters].
-
-A [space](@) is `U+0020`.
-
-A [non-whitespace character](@) is any character
-that is not a [whitespace character].
-
-An [ASCII punctuation character](@)
-is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`,
-`*`, `+`, `,`, `-`, `.`, `/` (U+0021–2F),
-`:`, `;`, `<`, `=`, `>`, `?`, `@` (U+003A–0040),
-`[`, `\`, `]`, `^`, `_`, `` ` `` (U+005B–0060),
-`{`, `|`, `}`, or `~` (U+007B–007E).
-
-A [punctuation character](@) is an [ASCII
-punctuation character] or anything in
-the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
-
-## Tabs
-
-Tabs in lines are not expanded to [spaces]. However,
-in contexts where whitespace helps to define block structure,
-tabs behave as if they were replaced by spaces with a tab stop
-of 4 characters.
-
-Thus, for example, a tab can be used instead of four spaces
-in an indented code block. (Note, however, that internal
-tabs are passed through as literal tabs, not expanded to
-spaces.)
-
-```````````````````````````````` example
-→foo→baz→→bim
-.
-<pre><code>foo→baz→→bim
-</code></pre>
-````````````````````````````````
-
-```````````````````````````````` example
- →foo→baz→→bim
-.
-<pre><code>foo→baz→→bim
-</code></pre>
-````````````````````````````````
-
-```````````````````````````````` example
- a→a
- á½â†’a
-.
-<pre><code>a→a
-á½â†’a
-</code></pre>
-````````````````````````````````
-
-In the following example, a continuation paragraph of a list
-item is indented with a tab; this has exactly the same effect
-as indentation with four spaces would:
-
-```````````````````````````````` example
- - foo
-
-→bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-- foo
-
-→→bar
-.
-<ul>
-<li>
-<p>foo</p>
-<pre><code> bar
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-Normally the `>` that begins a block quote may be followed
-optionally by a space, which is not considered part of the
-content. In the following case `>` is followed by a tab,
-which is treated as if it were expanded into three spaces.
-Since one of these spaces is considered part of the
-delimiter, `foo` is considered to be indented six spaces
-inside the block quote context, so we get an indented
-code block starting with two spaces.
-
-```````````````````````````````` example
->→→foo
-.
-<blockquote>
-<pre><code> foo
-</code></pre>
-</blockquote>
-````````````````````````````````
-
-```````````````````````````````` example
--→→foo
-.
-<ul>
-<li>
-<pre><code> foo
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
- foo
-→bar
-.
-<pre><code>foo
-bar
-</code></pre>
-````````````````````````````````
-
-```````````````````````````````` example
- - foo
- - bar
-→ - baz
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-#→Foo
-.
-<h1>Foo</h1>
-````````````````````````````````
-
-```````````````````````````````` example
-*→*→*→
-.
-<hr />
-````````````````````````````````
-
-
-## Insecure characters
-
-For security reasons, the Unicode character `U+0000` must be replaced
-with the REPLACEMENT CHARACTER (`U+FFFD`).
-
-# Blocks and inlines
-
-We can think of a document as a sequence of
-[blocks](@)---structural elements like paragraphs, block
-quotations, lists, headings, rules, and code blocks. Some blocks (like
-block quotes and list items) contain other blocks; others (like
-headings and paragraphs) contain [inline](@) content---text,
-links, emphasized text, images, code spans, and so on.
-
-## Precedence
-
-Indicators of block structure always take precedence over indicators
-of inline structure. So, for example, the following is a list with
-two items, not a list with one item containing a code span:
-
-```````````````````````````````` example
-- `one
-- two`
-.
-<ul>
-<li>`one</li>
-<li>two`</li>
-</ul>
-````````````````````````````````
-
-
-This means that parsing can proceed in two steps: first, the block
-structure of the document can be discerned; second, text lines inside
-paragraphs, headings, and other block constructs can be parsed for inline
-structure. The second step requires information about link reference
-definitions that will be available only at the end of the first
-step. Note that the first step requires processing lines in sequence,
-but the second can be parallelized, since the inline parsing of
-one block element does not affect the inline parsing of any other.
-
-## Container blocks and leaf blocks
-
-We can divide blocks into two types:
-[container blocks](@),
-which can contain other blocks, and [leaf blocks](@),
-which cannot.
-
-# Leaf blocks
-
-This section describes the different kinds of leaf block that make up a
-Markdown document.
-
-## Thematic breaks
-
-A line consisting of 0-3 spaces of indentation, followed by a sequence
-of three or more matching `-`, `_`, or `*` characters, each followed
-optionally by any number of spaces or tabs, forms a
-[thematic break](@).
-
-```````````````````````````````` example
-***
----
-___
-.
-<hr />
-<hr />
-<hr />
-````````````````````````````````
-
-
-Wrong characters:
-
-```````````````````````````````` example
-+++
-.
-<p>+++</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-===
-.
-<p>===</p>
-````````````````````````````````
-
-
-Not enough characters:
-
-```````````````````````````````` example
---
-**
-__
-.
-<p>--
-**
-__</p>
-````````````````````````````````
-
-
-One to three spaces indent are allowed:
-
-```````````````````````````````` example
- ***
- ***
- ***
-.
-<hr />
-<hr />
-<hr />
-````````````````````````````````
-
-
-Four spaces is too many:
-
-```````````````````````````````` example
- ***
-.
-<pre><code>***
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo
- ***
-.
-<p>Foo
-***</p>
-````````````````````````````````
-
-
-More than three characters may be used:
-
-```````````````````````````````` example
-_____________________________________
-.
-<hr />
-````````````````````````````````
-
-
-Spaces are allowed between the characters:
-
-```````````````````````````````` example
- - - -
-.
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
- ** * ** * ** * **
-.
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-- - - -
-.
-<hr />
-````````````````````````````````
-
-
-Spaces are allowed at the end:
-
-```````````````````````````````` example
-- - - -
-.
-<hr />
-````````````````````````````````
-
-
-However, no other characters may occur in the line:
-
-```````````````````````````````` example
-_ _ _ _ a
-
-a------
-
----a---
-.
-<p>_ _ _ _ a</p>
-<p>a------</p>
-<p>---a---</p>
-````````````````````````````````
-
-
-It is required that all of the [non-whitespace characters] be the same.
-So, this is not a thematic break:
-
-```````````````````````````````` example
- *-*
-.
-<p><em>-</em></p>
-````````````````````````````````
-
-
-Thematic breaks do not need blank lines before or after:
-
-```````````````````````````````` example
-- foo
-***
-- bar
-.
-<ul>
-<li>foo</li>
-</ul>
-<hr />
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-Thematic breaks can interrupt a paragraph:
-
-```````````````````````````````` example
-Foo
-***
-bar
-.
-<p>Foo</p>
-<hr />
-<p>bar</p>
-````````````````````````````````
-
-
-If a line of dashes that meets the above conditions for being a
-thematic break could also be interpreted as the underline of a [setext
-heading], the interpretation as a
-[setext heading] takes precedence. Thus, for example,
-this is a setext heading, not a paragraph followed by a thematic break:
-
-```````````````````````````````` example
-Foo
----
-bar
-.
-<h2>Foo</h2>
-<p>bar</p>
-````````````````````````````````
-
-
-When both a thematic break and a list item are possible
-interpretations of a line, the thematic break takes precedence:
-
-```````````````````````````````` example
-* Foo
-* * *
-* Bar
-.
-<ul>
-<li>Foo</li>
-</ul>
-<hr />
-<ul>
-<li>Bar</li>
-</ul>
-````````````````````````````````
-
-
-If you want a thematic break in a list item, use a different bullet:
-
-```````````````````````````````` example
-- Foo
-- * * *
-.
-<ul>
-<li>Foo</li>
-<li>
-<hr />
-</li>
-</ul>
-````````````````````````````````
-
-
-## ATX headings
-
-An [ATX heading](@)
-consists of a string of characters, parsed as inline content, between an
-opening sequence of 1--6 unescaped `#` characters and an optional
-closing sequence of any number of unescaped `#` characters.
-The opening sequence of `#` characters must be followed by a
-[space] or by the end of line. The optional closing sequence of `#`s must be
-preceded by a [space] and may be followed by spaces only. The opening
-`#` character may be indented 0-3 spaces. The raw contents of the
-heading are stripped of leading and trailing spaces before being parsed
-as inline content. The heading level is equal to the number of `#`
-characters in the opening sequence.
-
-Simple headings:
-
-```````````````````````````````` example
-# foo
-## foo
-### foo
-#### foo
-##### foo
-###### foo
-.
-<h1>foo</h1>
-<h2>foo</h2>
-<h3>foo</h3>
-<h4>foo</h4>
-<h5>foo</h5>
-<h6>foo</h6>
-````````````````````````````````
-
-
-More than six `#` characters is not a heading:
-
-```````````````````````````````` example
-####### foo
-.
-<p>####### foo</p>
-````````````````````````````````
-
-
-At least one space is required between the `#` characters and the
-heading's contents, unless the heading is empty. Note that many
-implementations currently do not require the space. However, the
-space was required by the
-[original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py),
-and it helps prevent things like the following from being parsed as
-headings:
-
-```````````````````````````````` example
-#5 bolt
-
-#hashtag
-.
-<p>#5 bolt</p>
-<p>#hashtag</p>
-````````````````````````````````
-
-
-This is not a heading, because the first `#` is escaped:
-
-```````````````````````````````` example
-\## foo
-.
-<p>## foo</p>
-````````````````````````````````
-
-
-Contents are parsed as inlines:
-
-```````````````````````````````` example
-# foo *bar* \*baz\*
-.
-<h1>foo <em>bar</em> *baz*</h1>
-````````````````````````````````
-
-
-Leading and trailing [whitespace] is ignored in parsing inline content:
-
-```````````````````````````````` example
-# foo
-.
-<h1>foo</h1>
-````````````````````````````````
-
-
-One to three spaces indentation are allowed:
-
-```````````````````````````````` example
- ### foo
- ## foo
- # foo
-.
-<h3>foo</h3>
-<h2>foo</h2>
-<h1>foo</h1>
-````````````````````````````````
-
-
-Four spaces are too much:
-
-```````````````````````````````` example
- # foo
-.
-<pre><code># foo
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo
- # bar
-.
-<p>foo
-# bar</p>
-````````````````````````````````
-
-
-A closing sequence of `#` characters is optional:
-
-```````````````````````````````` example
-## foo ##
- ### bar ###
-.
-<h2>foo</h2>
-<h3>bar</h3>
-````````````````````````````````
-
-
-It need not be the same length as the opening sequence:
-
-```````````````````````````````` example
-# foo ##################################
-##### foo ##
-.
-<h1>foo</h1>
-<h5>foo</h5>
-````````````````````````````````
-
-
-Spaces are allowed after the closing sequence:
-
-```````````````````````````````` example
-### foo ###
-.
-<h3>foo</h3>
-````````````````````````````````
-
-
-A sequence of `#` characters with anything but [spaces] following it
-is not a closing sequence, but counts as part of the contents of the
-heading:
-
-```````````````````````````````` example
-### foo ### b
-.
-<h3>foo ### b</h3>
-````````````````````````````````
-
-
-The closing sequence must be preceded by a space:
-
-```````````````````````````````` example
-# foo#
-.
-<h1>foo#</h1>
-````````````````````````````````
-
-
-Backslash-escaped `#` characters do not count as part
-of the closing sequence:
-
-```````````````````````````````` example
-### foo \###
-## foo #\##
-# foo \#
-.
-<h3>foo ###</h3>
-<h2>foo ###</h2>
-<h1>foo #</h1>
-````````````````````````````````
-
-
-ATX headings need not be separated from surrounding content by blank
-lines, and they can interrupt paragraphs:
-
-```````````````````````````````` example
-****
-## foo
-****
-.
-<hr />
-<h2>foo</h2>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo bar
-# baz
-Bar foo
-.
-<p>Foo bar</p>
-<h1>baz</h1>
-<p>Bar foo</p>
-````````````````````````````````
-
-
-ATX headings can be empty:
-
-```````````````````````````````` example
-##
-#
-### ###
-.
-<h2></h2>
-<h1></h1>
-<h3></h3>
-````````````````````````````````
-
-
-## Setext headings
-
-A [setext heading](@) consists of one or more
-lines of text, each containing at least one [non-whitespace
-character], with no more than 3 spaces indentation, followed by
-a [setext heading underline]. The lines of text must be such
-that, were they not followed by the setext heading underline,
-they would be interpreted as a paragraph: they cannot be
-interpretable as a [code fence], [ATX heading][ATX headings],
-[block quote][block quotes], [thematic break][thematic breaks],
-[list item][list items], or [HTML block][HTML blocks].
-
-A [setext heading underline](@) is a sequence of
-`=` characters or a sequence of `-` characters, with no more than 3
-spaces indentation and any number of trailing spaces. If a line
-containing a single `-` can be interpreted as an
-empty [list items], it should be interpreted this way
-and not as a [setext heading underline].
-
-The heading is a level 1 heading if `=` characters are used in
-the [setext heading underline], and a level 2 heading if `-`
-characters are used. The contents of the heading are the result
-of parsing the preceding lines of text as CommonMark inline
-content.
-
-In general, a setext heading need not be preceded or followed by a
-blank line. However, it cannot interrupt a paragraph, so when a
-setext heading comes after a paragraph, a blank line is needed between
-them.
-
-Simple examples:
-
-```````````````````````````````` example
-Foo *bar*
-=========
-
-Foo *bar*
----------
-.
-<h1>Foo <em>bar</em></h1>
-<h2>Foo <em>bar</em></h2>
-````````````````````````````````
-
-
-The content of the header may span more than one line:
-
-```````````````````````````````` example
-Foo *bar
-baz*
-====
-.
-<h1>Foo <em>bar
-baz</em></h1>
-````````````````````````````````
-
-The contents are the result of parsing the headings's raw
-content as inlines. The heading's raw content is formed by
-concatenating the lines and removing initial and final
-[whitespace].
-
-```````````````````````````````` example
- Foo *bar
-baz*→
-====
-.
-<h1>Foo <em>bar
-baz</em></h1>
-````````````````````````````````
-
-
-The underlining can be any length:
-
-```````````````````````````````` example
-Foo
--------------------------
-
-Foo
-=
-.
-<h2>Foo</h2>
-<h1>Foo</h1>
-````````````````````````````````
-
-
-The heading content can be indented up to three spaces, and need
-not line up with the underlining:
-
-```````````````````````````````` example
- Foo
----
-
- Foo
------
-
- Foo
- ===
-.
-<h2>Foo</h2>
-<h2>Foo</h2>
-<h1>Foo</h1>
-````````````````````````````````
-
-
-Four spaces indent is too much:
-
-```````````````````````````````` example
- Foo
- ---
-
- Foo
----
-.
-<pre><code>Foo
----
-
-Foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-The setext heading underline can be indented up to three spaces, and
-may have trailing spaces:
-
-```````````````````````````````` example
-Foo
- ----
-.
-<h2>Foo</h2>
-````````````````````````````````
-
-
-Four spaces is too much:
-
-```````````````````````````````` example
-Foo
- ---
-.
-<p>Foo
----</p>
-````````````````````````````````
-
-
-The setext heading underline cannot contain internal spaces:
-
-```````````````````````````````` example
-Foo
-= =
-
-Foo
---- -
-.
-<p>Foo
-= =</p>
-<p>Foo</p>
-<hr />
-````````````````````````````````
-
-
-Trailing spaces in the content line do not cause a line break:
-
-```````````````````````````````` example
-Foo
------
-.
-<h2>Foo</h2>
-````````````````````````````````
-
-
-Nor does a backslash at the end:
-
-```````````````````````````````` example
-Foo\
-----
-.
-<h2>Foo\</h2>
-````````````````````````````````
-
-
-Since indicators of block structure take precedence over
-indicators of inline structure, the following are setext headings:
-
-```````````````````````````````` example
-`Foo
-----
-`
-
-<a title="a lot
----
-of dashes"/>
-.
-<h2>`Foo</h2>
-<p>`</p>
-<h2>&lt;a title=&quot;a lot</h2>
-<p>of dashes&quot;/&gt;</p>
-````````````````````````````````
-
-
-The setext heading underline cannot be a [lazy continuation
-line] in a list item or block quote:
-
-```````````````````````````````` example
-> Foo
----
-.
-<blockquote>
-<p>Foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-> foo
-bar
-===
-.
-<blockquote>
-<p>foo
-bar
-===</p>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- Foo
----
-.
-<ul>
-<li>Foo</li>
-</ul>
-<hr />
-````````````````````````````````
-
-
-A blank line is needed between a paragraph and a following
-setext heading, since otherwise the paragraph becomes part
-of the heading's content:
-
-```````````````````````````````` example
-Foo
-Bar
----
-.
-<h2>Foo
-Bar</h2>
-````````````````````````````````
-
-
-But in general a blank line is not required before or after
-setext headings:
-
-```````````````````````````````` example
----
-Foo
----
-Bar
----
-Baz
-.
-<hr />
-<h2>Foo</h2>
-<h2>Bar</h2>
-<p>Baz</p>
-````````````````````````````````
-
-
-Setext headings cannot be empty:
-
-```````````````````````````````` example
-
-====
-.
-<p>====</p>
-````````````````````````````````
-
-
-Setext heading text lines must not be interpretable as block
-constructs other than paragraphs. So, the line of dashes
-in these examples gets interpreted as a thematic break:
-
-```````````````````````````````` example
----
----
-.
-<hr />
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
------
-.
-<ul>
-<li>foo</li>
-</ul>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
- foo
----
-.
-<pre><code>foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-> foo
------
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-If you want a heading with `> foo` as its literal text, you can
-use backslash escapes:
-
-```````````````````````````````` example
-\> foo
-------
-.
-<h2>&gt; foo</h2>
-````````````````````````````````
-
-
-**Compatibility note:** Most existing Markdown implementations
-do not allow the text of setext headings to span multiple lines.
-But there is no consensus about how to interpret
-
-``` markdown
-Foo
-bar
----
-baz
-```
-
-One can find four different interpretations:
-
-1. paragraph "Foo", heading "bar", paragraph "baz"
-2. paragraph "Foo bar", thematic break, paragraph "baz"
-3. paragraph "Foo bar --- baz"
-4. heading "Foo bar", paragraph "baz"
-
-We find interpretation 4 most natural, and interpretation 4
-increases the expressive power of CommonMark, by allowing
-multiline headings. Authors who want interpretation 1 can
-put a blank line after the first paragraph:
-
-```````````````````````````````` example
-Foo
-
-bar
----
-baz
-.
-<p>Foo</p>
-<h2>bar</h2>
-<p>baz</p>
-````````````````````````````````
-
-
-Authors who want interpretation 2 can put blank lines around
-the thematic break,
-
-```````````````````````````````` example
-Foo
-bar
-
----
-
-baz
-.
-<p>Foo
-bar</p>
-<hr />
-<p>baz</p>
-````````````````````````````````
-
-
-or use a thematic break that cannot count as a [setext heading
-underline], such as
-
-```````````````````````````````` example
-Foo
-bar
-* * *
-baz
-.
-<p>Foo
-bar</p>
-<hr />
-<p>baz</p>
-````````````````````````````````
-
-
-Authors who want interpretation 3 can use backslash escapes:
-
-```````````````````````````````` example
-Foo
-bar
-\---
-baz
-.
-<p>Foo
-bar
----
-baz</p>
-````````````````````````````````
-
-
-## Indented code blocks
-
-An [indented code block](@) is composed of one or more
-[indented chunks] separated by blank lines.
-An [indented chunk](@) is a sequence of non-blank lines,
-each indented four or more spaces. The contents of the code block are
-the literal contents of the lines, including trailing
-[line endings], minus four spaces of indentation.
-An indented code block has no [info string].
-
-An indented code block cannot interrupt a paragraph, so there must be
-a blank line between a paragraph and a following indented code block.
-(A blank line is not needed, however, between a code block and a following
-paragraph.)
-
-```````````````````````````````` example
- a simple
- indented code block
-.
-<pre><code>a simple
- indented code block
-</code></pre>
-````````````````````````````````
-
-
-If there is any ambiguity between an interpretation of indentation
-as a code block and as indicating that material belongs to a [list
-item][list items], the list item interpretation takes precedence:
-
-```````````````````````````````` example
- - foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. foo
-
- - bar
-.
-<ol>
-<li>
-<p>foo</p>
-<ul>
-<li>bar</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-
-The contents of a code block are literal text, and do not get parsed
-as Markdown:
-
-```````````````````````````````` example
- <a/>
- *hi*
-
- - one
-.
-<pre><code>&lt;a/&gt;
-*hi*
-
-- one
-</code></pre>
-````````````````````````````````
-
-
-Here we have three chunks separated by blank lines:
-
-```````````````````````````````` example
- chunk1
-
- chunk2
-
-
-
- chunk3
-.
-<pre><code>chunk1
-
-chunk2
-
-
-
-chunk3
-</code></pre>
-````````````````````````````````
-
-
-Any initial spaces beyond four will be included in the content, even
-in interior blank lines:
-
-```````````````````````````````` example
- chunk1
-
- chunk2
-.
-<pre><code>chunk1
-
- chunk2
-</code></pre>
-````````````````````````````````
-
-
-An indented code block cannot interrupt a paragraph. (This
-allows hanging indents and the like.)
-
-```````````````````````````````` example
-Foo
- bar
-
-.
-<p>Foo
-bar</p>
-````````````````````````````````
-
-
-However, any non-blank line with fewer than four leading spaces ends
-the code block immediately. So a paragraph may occur immediately
-after indented code:
-
-```````````````````````````````` example
- foo
-bar
-.
-<pre><code>foo
-</code></pre>
-<p>bar</p>
-````````````````````````````````
-
-
-And indented code can occur immediately before and after other kinds of
-blocks:
-
-```````````````````````````````` example
-# Heading
- foo
-Heading
-------
- foo
-----
-.
-<h1>Heading</h1>
-<pre><code>foo
-</code></pre>
-<h2>Heading</h2>
-<pre><code>foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-The first line can be indented more than four spaces:
-
-```````````````````````````````` example
- foo
- bar
-.
-<pre><code> foo
-bar
-</code></pre>
-````````````````````````````````
-
-
-Blank lines preceding or following an indented code block
-are not included in it:
-
-```````````````````````````````` example
-
-
- foo
-
-
-.
-<pre><code>foo
-</code></pre>
-````````````````````````````````
-
-
-Trailing spaces are included in the code block's content:
-
-```````````````````````````````` example
- foo
-.
-<pre><code>foo
-</code></pre>
-````````````````````````````````
-
-
-
-## Fenced code blocks
-
-A [code fence](@) is a sequence
-of at least three consecutive backtick characters (`` ` ``) or
-tildes (`~`). (Tildes and backticks cannot be mixed.)
-A [fenced code block](@)
-begins with a code fence, indented no more than three spaces.
-
-The line with the opening code fence may optionally contain some text
-following the code fence; this is trimmed of leading and trailing
-whitespace and called the [info string](@). If the [info string] comes
-after a backtick fence, it may not contain any backtick
-characters. (The reason for this restriction is that otherwise
-some inline code would be incorrectly interpreted as the
-beginning of a fenced code block.)
-
-The content of the code block consists of all subsequent lines, until
-a closing [code fence] of the same type as the code block
-began with (backticks or tildes), and with at least as many backticks
-or tildes as the opening code fence. If the leading code fence is
-indented N spaces, then up to N spaces of indentation are removed from
-each line of the content (if present). (If a content line is not
-indented, it is preserved unchanged. If it is indented less than N
-spaces, all of the indentation is removed.)
-
-The closing code fence may be indented up to three spaces, and may be
-followed only by spaces, which are ignored. If the end of the
-containing block (or document) is reached and no closing code fence
-has been found, the code block contains all of the lines after the
-opening code fence until the end of the containing block (or
-document). (An alternative spec would require backtracking in the
-event that a closing code fence is not found. But this makes parsing
-much less efficient, and there seems to be no real down side to the
-behavior described here.)
-
-A fenced code block may interrupt a paragraph, and does not require
-a blank line either before or after.
-
-The content of a code fence is treated as literal text, not parsed
-as inlines. The first word of the [info string] is typically used to
-specify the language of the code sample, and rendered in the `class`
-attribute of the `code` tag. However, this spec does not mandate any
-particular treatment of the [info string].
-
-Here is a simple example with backticks:
-
-```````````````````````````````` example
-```
-<
- >
-```
-.
-<pre><code>&lt;
- &gt;
-</code></pre>
-````````````````````````````````
-
-
-With tildes:
-
-```````````````````````````````` example
-~~~
-<
- >
-~~~
-.
-<pre><code>&lt;
- &gt;
-</code></pre>
-````````````````````````````````
-
-Fewer than three backticks is not enough:
-
-```````````````````````````````` example
-``
-foo
-``
-.
-<p><code>foo</code></p>
-````````````````````````````````
-
-The closing code fence must use the same character as the opening
-fence:
-
-```````````````````````````````` example
-```
-aaa
-~~~
-```
-.
-<pre><code>aaa
-~~~
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~
-aaa
-```
-~~~
-.
-<pre><code>aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-The closing code fence must be at least as long as the opening fence:
-
-```````````````````````````````` example
-````
-aaa
-```
-``````
-.
-<pre><code>aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~
-aaa
-~~~
-~~~~
-.
-<pre><code>aaa
-~~~
-</code></pre>
-````````````````````````````````
-
-
-Unclosed code blocks are closed by the end of the document
-(or the enclosing [block quote][block quotes] or [list item][list items]):
-
-```````````````````````````````` example
-```
-.
-<pre><code></code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`````
-
-```
-aaa
-.
-<pre><code>
-```
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> ```
-> aaa
-
-bbb
-.
-<blockquote>
-<pre><code>aaa
-</code></pre>
-</blockquote>
-<p>bbb</p>
-````````````````````````````````
-
-
-A code block can have all empty lines as its content:
-
-```````````````````````````````` example
-```
-
-
-```
-.
-<pre><code>
-
-</code></pre>
-````````````````````````````````
-
-
-A code block can be empty:
-
-```````````````````````````````` example
-```
-```
-.
-<pre><code></code></pre>
-````````````````````````````````
-
-
-Fences can be indented. If the opening fence is indented,
-content lines will have equivalent opening indentation removed,
-if present:
-
-```````````````````````````````` example
- ```
- aaa
-aaa
-```
-.
-<pre><code>aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
-aaa
- aaa
-aaa
- ```
-.
-<pre><code>aaa
-aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
- aaa
- aaa
- aaa
- ```
-.
-<pre><code>aaa
- aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-Four spaces indentation produces an indented code block:
-
-```````````````````````````````` example
- ```
- aaa
- ```
-.
-<pre><code>```
-aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-Closing fences may be indented by 0-3 spaces, and their indentation
-need not match that of the opening fence:
-
-```````````````````````````````` example
-```
-aaa
- ```
-.
-<pre><code>aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
-aaa
- ```
-.
-<pre><code>aaa
-</code></pre>
-````````````````````````````````
-
-
-This is not a closing fence, because it is indented 4 spaces:
-
-```````````````````````````````` example
-```
-aaa
- ```
-.
-<pre><code>aaa
- ```
-</code></pre>
-````````````````````````````````
-
-
-
-Code fences (opening and closing) cannot contain internal spaces:
-
-```````````````````````````````` example
-``` ```
-aaa
-.
-<p><code> </code>
-aaa</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~~~
-aaa
-~~~ ~~
-.
-<pre><code>aaa
-~~~ ~~
-</code></pre>
-````````````````````````````````
-
-
-Fenced code blocks can interrupt paragraphs, and can be followed
-directly by paragraphs, without a blank line between:
-
-```````````````````````````````` example
-foo
-```
-bar
-```
-baz
-.
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-<p>baz</p>
-````````````````````````````````
-
-
-Other blocks can also occur before and after fenced code blocks
-without an intervening blank line:
-
-```````````````````````````````` example
-foo
----
-~~~
-bar
-~~~
-# baz
-.
-<h2>foo</h2>
-<pre><code>bar
-</code></pre>
-<h1>baz</h1>
-````````````````````````````````
-
-
-An [info string] can be provided after the opening code fence.
-Although this spec doesn't mandate any particular treatment of
-the info string, the first word is typically used to specify
-the language of the code block. In HTML output, the language is
-normally indicated by adding a class to the `code` element consisting
-of `language-` followed by the language name.
-
-```````````````````````````````` example
-```ruby
-def foo(x)
- return 3
-end
-```
-.
-<pre><code class="language-ruby">def foo(x)
- return 3
-end
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~ ruby startline=3 $%@#$
-def foo(x)
- return 3
-end
-~~~~~~~
-.
-<pre><code class="language-ruby">def foo(x)
- return 3
-end
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-````;
-````
-.
-<pre><code class="language-;"></code></pre>
-````````````````````````````````
-
-
-[Info strings] for backtick code blocks cannot contain backticks:
-
-```````````````````````````````` example
-``` aa ```
-foo
-.
-<p><code>aa</code>
-foo</p>
-````````````````````````````````
-
-
-[Info strings] for tilde code blocks can contain backticks and tildes:
-
-```````````````````````````````` example
-~~~ aa ``` ~~~
-foo
-~~~
-.
-<pre><code class="language-aa">foo
-</code></pre>
-````````````````````````````````
-
-
-Closing code fences cannot have [info strings]:
-
-```````````````````````````````` example
-```
-``` aaa
-```
-.
-<pre><code>``` aaa
-</code></pre>
-````````````````````````````````
-
-
-
-## HTML blocks
-
-An [HTML block](@) is a group of lines that is treated
-as raw HTML (and will not be escaped in HTML output).
-
-There are seven kinds of [HTML block], which can be defined by their
-start and end conditions. The block begins with a line that meets a
-[start condition](@) (after up to three spaces optional indentation).
-It ends with the first subsequent line that meets a matching [end
-condition](@), or the last line of the document, or the last line of
-the [container block](#container-blocks) containing the current HTML
-block, if no line is encountered that meets the [end condition]. If
-the first line meets both the [start condition] and the [end
-condition], the block will contain just that line.
-
-1. **Start condition:** line begins with the string `<script`,
-`<pre`, or `<style` (case-insensitive), followed by whitespace,
-the string `>`, or the end of the line.\
-**End condition:** line contains an end tag
-`</script>`, `</pre>`, or `</style>` (case-insensitive; it
-need not match the start tag).
-
-2. **Start condition:** line begins with the string `<!--`.\
-**End condition:** line contains the string `-->`.
-
-3. **Start condition:** line begins with the string `<?`.\
-**End condition:** line contains the string `?>`.
-
-4. **Start condition:** line begins with the string `<!`
-followed by an uppercase ASCII letter.\
-**End condition:** line contains the character `>`.
-
-5. **Start condition:** line begins with the string
-`<![CDATA[`.\
-**End condition:** line contains the string `]]>`.
-
-6. **Start condition:** line begins the string `<` or `</`
-followed by one of the strings (case-insensitive) `address`,
-`article`, `aside`, `base`, `basefont`, `blockquote`, `body`,
-`caption`, `center`, `col`, `colgroup`, `dd`, `details`, `dialog`,
-`dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`,
-`footer`, `form`, `frame`, `frameset`,
-`h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `head`, `header`, `hr`,
-`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
-`nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
-`section`, `source`, `summary`, `table`, `tbody`, `td`,
-`tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed
-by [whitespace], the end of the line, the string `>`, or
-the string `/>`.\
-**End condition:** line is followed by a [blank line].
-
-7. **Start condition:** line begins with a complete [open tag]
-(with any [tag name] other than `script`,
-`style`, or `pre`) or a complete [closing tag],
-followed only by [whitespace] or the end of the line.\
-**End condition:** line is followed by a [blank line].
-
-HTML blocks continue until they are closed by their appropriate
-[end condition], or the last line of the document or other [container
-block](#container-blocks). This means any HTML **within an HTML
-block** that might otherwise be recognised as a start condition will
-be ignored by the parser and passed through as-is, without changing
-the parser's state.
-
-For instance, `<pre>` within a HTML block started by `<table>` will not affect
-the parser state; as the HTML block was started in by start condition 6, it
-will end at any blank line. This can be surprising:
-
-```````````````````````````````` example
-<table><tr><td>
-<pre>
-**Hello**,
-
-_world_.
-</pre>
-</td></tr></table>
-.
-<table><tr><td>
-<pre>
-**Hello**,
-<p><em>world</em>.
-</pre></p>
-</td></tr></table>
-````````````````````````````````
-
-In this case, the HTML block is terminated by the newline — the `**Hello**`
-text remains verbatim — and regular parsing resumes, with a paragraph,
-emphasised `world` and inline and block HTML following.
-
-All types of [HTML blocks] except type 7 may interrupt
-a paragraph. Blocks of type 7 may not interrupt a paragraph.
-(This restriction is intended to prevent unwanted interpretation
-of long tags inside a wrapped paragraph as starting HTML blocks.)
-
-Some simple examples follow. Here are some basic HTML blocks
-of type 6:
-
-```````````````````````````````` example
-<table>
- <tr>
- <td>
- hi
- </td>
- </tr>
-</table>
-
-okay.
-.
-<table>
- <tr>
- <td>
- hi
- </td>
- </tr>
-</table>
-<p>okay.</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- <div>
- *hello*
- <foo><a>
-.
- <div>
- *hello*
- <foo><a>
-````````````````````````````````
-
-
-A block can also start with a closing tag:
-
-```````````````````````````````` example
-</div>
-*foo*
-.
-</div>
-*foo*
-````````````````````````````````
-
-
-Here we have two HTML blocks with a Markdown paragraph between them:
-
-```````````````````````````````` example
-<DIV CLASS="foo">
-
-*Markdown*
-
-</DIV>
-.
-<DIV CLASS="foo">
-<p><em>Markdown</em></p>
-</DIV>
-````````````````````````````````
-
-
-The tag on the first line can be partial, as long
-as it is split where there would be whitespace:
-
-```````````````````````````````` example
-<div id="foo"
- class="bar">
-</div>
-.
-<div id="foo"
- class="bar">
-</div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div id="foo" class="bar
- baz">
-</div>
-.
-<div id="foo" class="bar
- baz">
-</div>
-````````````````````````````````
-
-
-An open tag need not be closed:
-```````````````````````````````` example
-<div>
-*foo*
-
-*bar*
-.
-<div>
-*foo*
-<p><em>bar</em></p>
-````````````````````````````````
-
-
-
-A partial tag need not even be completed (garbage
-in, garbage out):
-
-```````````````````````````````` example
-<div id="foo"
-*hi*
-.
-<div id="foo"
-*hi*
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div class
-foo
-.
-<div class
-foo
-````````````````````````````````
-
-
-The initial tag doesn't even need to be a valid
-tag, as long as it starts like one:
-
-```````````````````````````````` example
-<div *???-&&&-<---
-*foo*
-.
-<div *???-&&&-<---
-*foo*
-````````````````````````````````
-
-
-In type 6 blocks, the initial tag need not be on a line by
-itself:
-
-```````````````````````````````` example
-<div><a href="bar">*foo*</a></div>
-.
-<div><a href="bar">*foo*</a></div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<table><tr><td>
-foo
-</td></tr></table>
-.
-<table><tr><td>
-foo
-</td></tr></table>
-````````````````````````````````
-
-
-Everything until the next blank line or end of document
-gets included in the HTML block. So, in the following
-example, what looks like a Markdown code block
-is actually part of the HTML block, which continues until a blank
-line or the end of the document is reached:
-
-```````````````````````````````` example
-<div></div>
-``` c
-int x = 33;
-```
-.
-<div></div>
-``` c
-int x = 33;
-```
-````````````````````````````````
-
-
-To start an [HTML block] with a tag that is *not* in the
-list of block-level tags in (6), you must put the tag by
-itself on the first line (and it must be complete):
-
-```````````````````````````````` example
-<a href="foo">
-*bar*
-</a>
-.
-<a href="foo">
-*bar*
-</a>
-````````````````````````````````
-
-
-In type 7 blocks, the [tag name] can be anything:
-
-```````````````````````````````` example
-<Warning>
-*bar*
-</Warning>
-.
-<Warning>
-*bar*
-</Warning>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<i class="foo">
-*bar*
-</i>
-.
-<i class="foo">
-*bar*
-</i>
-````````````````````````````````
-
-
-```````````````````````````````` example
-</ins>
-*bar*
-.
-</ins>
-*bar*
-````````````````````````````````
-
-
-These rules are designed to allow us to work with tags that
-can function as either block-level or inline-level tags.
-The `<del>` tag is a nice example. We can surround content with
-`<del>` tags in three different ways. In this case, we get a raw
-HTML block, because the `<del>` tag is on a line by itself:
-
-```````````````````````````````` example
-<del>
-*foo*
-</del>
-.
-<del>
-*foo*
-</del>
-````````````````````````````````
-
-
-In this case, we get a raw HTML block that just includes
-the `<del>` tag (because it ends with the following blank
-line). So the contents get interpreted as CommonMark:
-
-```````````````````````````````` example
-<del>
-
-*foo*
-
-</del>
-.
-<del>
-<p><em>foo</em></p>
-</del>
-````````````````````````````````
-
-
-Finally, in this case, the `<del>` tags are interpreted
-as [raw HTML] *inside* the CommonMark paragraph. (Because
-the tag is not on a line by itself, we get inline HTML
-rather than an [HTML block].)
-
-```````````````````````````````` example
-<del>*foo*</del>
-.
-<p><del><em>foo</em></del></p>
-````````````````````````````````
-
-
-HTML tags designed to contain literal content
-(`script`, `style`, `pre`), comments, processing instructions,
-and declarations are treated somewhat differently.
-Instead of ending at the first blank line, these blocks
-end at the first line containing a corresponding end tag.
-As a result, these blocks can contain blank lines:
-
-A pre tag (type 1):
-
-```````````````````````````````` example
-<pre language="haskell"><code>
-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-</code></pre>
-okay
-.
-<pre language="haskell"><code>
-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-</code></pre>
-<p>okay</p>
-````````````````````````````````
-
-
-A script tag (type 1):
-
-```````````````````````````````` example
-<script type="text/javascript">
-// JavaScript example
-
-document.getElementById("demo").innerHTML = "Hello JavaScript!";
-</script>
-okay
-.
-<script type="text/javascript">
-// JavaScript example
-
-document.getElementById("demo").innerHTML = "Hello JavaScript!";
-</script>
-<p>okay</p>
-````````````````````````````````
-
-
-A style tag (type 1):
-
-```````````````````````````````` example
-<style
- type="text/css">
-h1 {color:red;}
-
-p {color:blue;}
-</style>
-okay
-.
-<style
- type="text/css">
-h1 {color:red;}
-
-p {color:blue;}
-</style>
-<p>okay</p>
-````````````````````````````````
-
-
-If there is no matching end tag, the block will end at the
-end of the document (or the enclosing [block quote][block quotes]
-or [list item][list items]):
-
-```````````````````````````````` example
-<style
- type="text/css">
-
-foo
-.
-<style
- type="text/css">
-
-foo
-````````````````````````````````
-
-
-```````````````````````````````` example
-> <div>
-> foo
-
-bar
-.
-<blockquote>
-<div>
-foo
-</blockquote>
-<p>bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- <div>
-- foo
-.
-<ul>
-<li>
-<div>
-</li>
-<li>foo</li>
-</ul>
-````````````````````````````````
-
-
-The end tag can occur on the same line as the start tag:
-
-```````````````````````````````` example
-<style>p{color:red;}</style>
-*foo*
-.
-<style>p{color:red;}</style>
-<p><em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<!-- foo -->*bar*
-*baz*
-.
-<!-- foo -->*bar*
-<p><em>baz</em></p>
-````````````````````````````````
-
-
-Note that anything on the last line after the
-end tag will be included in the [HTML block]:
-
-```````````````````````````````` example
-<script>
-foo
-</script>1. *bar*
-.
-<script>
-foo
-</script>1. *bar*
-````````````````````````````````
-
-
-A comment (type 2):
-
-```````````````````````````````` example
-<!-- Foo
-
-bar
- baz -->
-okay
-.
-<!-- Foo
-
-bar
- baz -->
-<p>okay</p>
-````````````````````````````````
-
-
-
-A processing instruction (type 3):
-
-```````````````````````````````` example
-<?php
-
- echo '>';
-
-?>
-okay
-.
-<?php
-
- echo '>';
-
-?>
-<p>okay</p>
-````````````````````````````````
-
-
-A declaration (type 4):
-
-```````````````````````````````` example
-<!DOCTYPE html>
-.
-<!DOCTYPE html>
-````````````````````````````````
-
-
-CDATA (type 5):
-
-```````````````````````````````` example
-<![CDATA[
-function matchwo(a,b)
-{
- if (a < b && a < 0) then {
- return 1;
-
- } else {
-
- return 0;
- }
-}
-]]>
-okay
-.
-<![CDATA[
-function matchwo(a,b)
-{
- if (a < b && a < 0) then {
- return 1;
-
- } else {
-
- return 0;
- }
-}
-]]>
-<p>okay</p>
-````````````````````````````````
-
-
-The opening tag can be indented 1-3 spaces, but not 4:
-
-```````````````````````````````` example
- <!-- foo -->
-
- <!-- foo -->
-.
- <!-- foo -->
-<pre><code>&lt;!-- foo --&gt;
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- <div>
-
- <div>
-.
- <div>
-<pre><code>&lt;div&gt;
-</code></pre>
-````````````````````````````````
-
-
-An HTML block of types 1--6 can interrupt a paragraph, and need not be
-preceded by a blank line.
-
-```````````````````````````````` example
-Foo
-<div>
-bar
-</div>
-.
-<p>Foo</p>
-<div>
-bar
-</div>
-````````````````````````````````
-
-
-However, a following blank line is needed, except at the end of
-a document, and except for blocks of types 1--5, [above][HTML
-block]:
-
-```````````````````````````````` example
-<div>
-bar
-</div>
-*foo*
-.
-<div>
-bar
-</div>
-*foo*
-````````````````````````````````
-
-
-HTML blocks of type 7 cannot interrupt a paragraph:
-
-```````````````````````````````` example
-Foo
-<a href="bar">
-baz
-.
-<p>Foo
-<a href="bar">
-baz</p>
-````````````````````````````````
-
-
-This rule differs from John Gruber's original Markdown syntax
-specification, which says:
-
-> The only restrictions are that block-level HTML elements —
-> e.g. `<div>`, `<table>`, `<pre>`, `<p>`, etc. — must be separated from
-> surrounding content by blank lines, and the start and end tags of the
-> block should not be indented with tabs or spaces.
-
-In some ways Gruber's rule is more restrictive than the one given
-here:
-
-- It requires that an HTML block be preceded by a blank line.
-- It does not allow the start tag to be indented.
-- It requires a matching end tag, which it also does not allow to
- be indented.
-
-Most Markdown implementations (including some of Gruber's own) do not
-respect all of these restrictions.
-
-There is one respect, however, in which Gruber's rule is more liberal
-than the one given here, since it allows blank lines to occur inside
-an HTML block. There are two reasons for disallowing them here.
-First, it removes the need to parse balanced tags, which is
-expensive and can require backtracking from the end of the document
-if no matching end tag is found. Second, it provides a very simple
-and flexible way of including Markdown content inside HTML tags:
-simply separate the Markdown from the HTML using blank lines:
-
-Compare:
-
-```````````````````````````````` example
-<div>
-
-*Emphasized* text.
-
-</div>
-.
-<div>
-<p><em>Emphasized</em> text.</p>
-</div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div>
-*Emphasized* text.
-</div>
-.
-<div>
-*Emphasized* text.
-</div>
-````````````````````````````````
-
-
-Some Markdown implementations have adopted a convention of
-interpreting content inside tags as text if the open tag has
-the attribute `markdown=1`. The rule given above seems a simpler and
-more elegant way of achieving the same expressive power, which is also
-much simpler to parse.
-
-The main potential drawback is that one can no longer paste HTML
-blocks into Markdown documents with 100% reliability. However,
-*in most cases* this will work fine, because the blank lines in
-HTML are usually followed by HTML block tags. For example:
-
-```````````````````````````````` example
-<table>
-
-<tr>
-
-<td>
-Hi
-</td>
-
-</tr>
-
-</table>
-.
-<table>
-<tr>
-<td>
-Hi
-</td>
-</tr>
-</table>
-````````````````````````````````
-
-
-There are problems, however, if the inner tags are indented
-*and* separated by spaces, as then they will be interpreted as
-an indented code block:
-
-```````````````````````````````` example
-<table>
-
- <tr>
-
- <td>
- Hi
- </td>
-
- </tr>
-
-</table>
-.
-<table>
- <tr>
-<pre><code>&lt;td&gt;
- Hi
-&lt;/td&gt;
-</code></pre>
- </tr>
-</table>
-````````````````````````````````
-
-
-Fortunately, blank lines are usually not necessary and can be
-deleted. The exception is inside `<pre>` tags, but as described
-[above][HTML blocks], raw HTML blocks starting with `<pre>`
-*can* contain blank lines.
-
-## Link reference definitions
-
-A [link reference definition](@)
-consists of a [link label], indented up to three spaces, followed
-by a colon (`:`), optional [whitespace] (including up to one
-[line ending]), a [link destination],
-optional [whitespace] (including up to one
-[line ending]), and an optional [link
-title], which if it is present must be separated
-from the [link destination] by [whitespace].
-No further [non-whitespace characters] may occur on the line.
-
-A [link reference definition]
-does not correspond to a structural element of a document. Instead, it
-defines a label which can be used in [reference links]
-and reference-style [images] elsewhere in the document. [Link
-reference definitions] can come either before or after the links that use
-them.
-
-```````````````````````````````` example
-[foo]: /url "title"
-
-[foo]
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- [foo]:
- /url
- 'the title'
-
-[foo]
-.
-<p><a href="/url" title="the title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[Foo*bar\]]:my_(url) 'title (with parens)'
-
-[Foo*bar\]]
-.
-<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[Foo bar]:
-<my url>
-'title'
-
-[Foo bar]
-.
-<p><a href="my%20url" title="title">Foo bar</a></p>
-````````````````````````````````
-
-
-The title may extend over multiple lines:
-
-```````````````````````````````` example
-[foo]: /url '
-title
-line1
-line2
-'
-
-[foo]
-.
-<p><a href="/url" title="
-title
-line1
-line2
-">foo</a></p>
-````````````````````````````````
-
-
-However, it may not contain a [blank line]:
-
-```````````````````````````````` example
-[foo]: /url 'title
-
-with blank line'
-
-[foo]
-.
-<p>[foo]: /url 'title</p>
-<p>with blank line'</p>
-<p>[foo]</p>
-````````````````````````````````
-
-
-The title may be omitted:
-
-```````````````````````````````` example
-[foo]:
-/url
-
-[foo]
-.
-<p><a href="/url">foo</a></p>
-````````````````````````````````
-
-
-The link destination may not be omitted:
-
-```````````````````````````````` example
-[foo]:
-
-[foo]
-.
-<p>[foo]:</p>
-<p>[foo]</p>
-````````````````````````````````
-
- However, an empty link destination may be specified using
- angle brackets:
-
-```````````````````````````````` example
-[foo]: <>
-
-[foo]
-.
-<p><a href="">foo</a></p>
-````````````````````````````````
-
-The title must be separated from the link destination by
-whitespace:
-
-```````````````````````````````` example
-[foo]: <bar>(baz)
-
-[foo]
-.
-<p>[foo]: <bar>(baz)</p>
-<p>[foo]</p>
-````````````````````````````````
-
-
-Both title and destination can contain backslash escapes
-and literal backslashes:
-
-```````````````````````````````` example
-[foo]: /url\bar\*baz "foo\"bar\baz"
-
-[foo]
-.
-<p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
-````````````````````````````````
-
-
-A link can come before its corresponding definition:
-
-```````````````````````````````` example
-[foo]
-
-[foo]: url
-.
-<p><a href="url">foo</a></p>
-````````````````````````````````
-
-
-If there are several matching definitions, the first one takes
-precedence:
-
-```````````````````````````````` example
-[foo]
-
-[foo]: first
-[foo]: second
-.
-<p><a href="first">foo</a></p>
-````````````````````````````````
-
-
-As noted in the section on [Links], matching of labels is
-case-insensitive (see [matches]).
-
-```````````````````````````````` example
-[FOO]: /url
-
-[Foo]
-.
-<p><a href="/url">Foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[ΑΓΩ]: /φου
-
-[αγω]
-.
-<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
-````````````````````````````````
-
-
-Here is a link reference definition with no corresponding link.
-It contributes nothing to the document.
-
-```````````````````````````````` example
-[foo]: /url
-.
-````````````````````````````````
-
-
-Here is another one:
-
-```````````````````````````````` example
-[
-foo
-]: /url
-bar
-.
-<p>bar</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because there are
-[non-whitespace characters] after the title:
-
-```````````````````````````````` example
-[foo]: /url "title" ok
-.
-<p>[foo]: /url &quot;title&quot; ok</p>
-````````````````````````````````
-
-
-This is a link reference definition, but it has no title:
-
-```````````````````````````````` example
-[foo]: /url
-"title" ok
-.
-<p>&quot;title&quot; ok</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because it is indented
-four spaces:
-
-```````````````````````````````` example
- [foo]: /url "title"
-
-[foo]
-.
-<pre><code>[foo]: /url &quot;title&quot;
-</code></pre>
-<p>[foo]</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because it occurs inside
-a code block:
-
-```````````````````````````````` example
-```
-[foo]: /url
-```
-
-[foo]
-.
-<pre><code>[foo]: /url
-</code></pre>
-<p>[foo]</p>
-````````````````````````````````
-
-
-A [link reference definition] cannot interrupt a paragraph.
-
-```````````````````````````````` example
-Foo
-[bar]: /baz
-
-[bar]
-.
-<p>Foo
-[bar]: /baz</p>
-<p>[bar]</p>
-````````````````````````````````
-
-
-However, it can directly follow other block elements, such as headings
-and thematic breaks, and it need not be followed by a blank line.
-
-```````````````````````````````` example
-# [Foo]
-[foo]: /url
-> bar
-.
-<h1><a href="/url">Foo</a></h1>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-```````````````````````````````` example
-[foo]: /url
-bar
-===
-[foo]
-.
-<h1>bar</h1>
-<p><a href="/url">foo</a></p>
-````````````````````````````````
-
-```````````````````````````````` example
-[foo]: /url
-===
-[foo]
-.
-<p>===
-<a href="/url">foo</a></p>
-````````````````````````````````
-
-
-Several [link reference definitions]
-can occur one after another, without intervening blank lines.
-
-```````````````````````````````` example
-[foo]: /foo-url "foo"
-[bar]: /bar-url
- "bar"
-[baz]: /baz-url
-
-[foo],
-[bar],
-[baz]
-.
-<p><a href="/foo-url" title="foo">foo</a>,
-<a href="/bar-url" title="bar">bar</a>,
-<a href="/baz-url">baz</a></p>
-````````````````````````````````
-
-
-[Link reference definitions] can occur
-inside block containers, like lists and block quotations. They
-affect the entire document, not just the container in which they
-are defined:
-
-```````````````````````````````` example
-[foo]
-
-> [foo]: /url
-.
-<p><a href="/url">foo</a></p>
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-Whether something is a [link reference definition] is
-independent of whether the link reference it defines is
-used in the document. Thus, for example, the following
-document contains just a link reference definition, and
-no visible content:
-
-```````````````````````````````` example
-[foo]: /url
-.
-````````````````````````````````
-
-
-## Paragraphs
-
-A sequence of non-blank lines that cannot be interpreted as other
-kinds of blocks forms a [paragraph](@).
-The contents of the paragraph are the result of parsing the
-paragraph's raw content as inlines. The paragraph's raw content
-is formed by concatenating the lines and removing initial and final
-[whitespace].
-
-A simple example with two paragraphs:
-
-```````````````````````````````` example
-aaa
-
-bbb
-.
-<p>aaa</p>
-<p>bbb</p>
-````````````````````````````````
-
-
-Paragraphs can contain multiple lines, but no blank lines:
-
-```````````````````````````````` example
-aaa
-bbb
-
-ccc
-ddd
-.
-<p>aaa
-bbb</p>
-<p>ccc
-ddd</p>
-````````````````````````````````
-
-
-Multiple blank lines between paragraph have no effect:
-
-```````````````````````````````` example
-aaa
-
-
-bbb
-.
-<p>aaa</p>
-<p>bbb</p>
-````````````````````````````````
-
-
-Leading spaces are skipped:
-
-```````````````````````````````` example
- aaa
- bbb
-.
-<p>aaa
-bbb</p>
-````````````````````````````````
-
-
-Lines after the first may be indented any amount, since indented
-code blocks cannot interrupt paragraphs.
-
-```````````````````````````````` example
-aaa
- bbb
- ccc
-.
-<p>aaa
-bbb
-ccc</p>
-````````````````````````````````
-
-
-However, the first line may be indented at most three spaces,
-or an indented code block will be triggered:
-
-```````````````````````````````` example
- aaa
-bbb
-.
-<p>aaa
-bbb</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- aaa
-bbb
-.
-<pre><code>aaa
-</code></pre>
-<p>bbb</p>
-````````````````````````````````
-
-
-Final spaces are stripped before inline parsing, so a paragraph
-that ends with two or more spaces will not end with a [hard line
-break]:
-
-```````````````````````````````` example
-aaa
-bbb
-.
-<p>aaa<br />
-bbb</p>
-````````````````````````````````
-
-
-## Blank lines
-
-[Blank lines] between block-level elements are ignored,
-except for the role they play in determining whether a [list]
-is [tight] or [loose].
-
-Blank lines at the beginning and end of the document are also ignored.
-
-```````````````````````````````` example
-
-
-aaa
-
-
-# aaa
-
-
-.
-<p>aaa</p>
-<h1>aaa</h1>
-````````````````````````````````
-
-<div class="extension">
-
-## Tables (extension)
-
-GFM enables the `table` extension, where an additional leaf block type is
-available.
-
-A [table](@) is an arrangement of data with rows and columns, consisting of a
-single header row, a [delimiter row] separating the header from the data, and
-zero or more data rows.
-
-Each row consists of cells containing arbitrary text, in which [inlines] are
-parsed, separated by pipes (`|`). A leading and trailing pipe is also
-recommended for clarity of reading, and if there's otherwise parsing ambiguity.
-Spaces between pipes and cell content are trimmed. Block-level elements cannot
-be inserted in a table.
-
-The [delimiter row](@) consists of cells whose only content are hyphens (`-`),
-and optionally, a leading or trailing colon (`:`), or both, to indicate left,
-right, or center alignment respectively.
-
-```````````````````````````````` example table
-| foo | bar |
-| --- | --- |
-| baz | bim |
-.
-<table>
-<thead>
-<tr>
-<th>foo</th>
-<th>bar</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>baz</td>
-<td>bim</td>
-</tr>
-</tbody>
-</table>
-````````````````````````````````
-
-Cells in one column don't need to match length, though it's easier to read if
-they are. Likewise, use of leading and trailing pipes may be inconsistent:
-
-```````````````````````````````` example table
-| abc | defghi |
-:-: | -----------:
-bar | baz
-.
-<table>
-<thead>
-<tr>
-<th align="center">abc</th>
-<th align="right">defghi</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td align="center">bar</td>
-<td align="right">baz</td>
-</tr>
-</tbody>
-</table>
-````````````````````````````````
-
-Include a pipe in a cell's content by escaping it, including inside other
-inline spans:
-
-```````````````````````````````` example table
-| f\|oo |
-| ------ |
-| b `\|` az |
-| b **\|** im |
-.
-<table>
-<thead>
-<tr>
-<th>f|oo</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>b <code>|</code> az</td>
-</tr>
-<tr>
-<td>b <strong>|</strong> im</td>
-</tr>
-</tbody>
-</table>
-````````````````````````````````
-
-The table is broken at the first empty line, or beginning of another
-block-level structure:
-
-```````````````````````````````` example table
-| abc | def |
-| --- | --- |
-| bar | baz |
-> bar
-.
-<table>
-<thead>
-<tr>
-<th>abc</th>
-<th>def</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>bar</td>
-<td>baz</td>
-</tr>
-</tbody>
-</table>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-```````````````````````````````` example table
-| abc | def |
-| --- | --- |
-| bar | baz |
-bar
-
-bar
-.
-<table>
-<thead>
-<tr>
-<th>abc</th>
-<th>def</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>bar</td>
-<td>baz</td>
-</tr>
-<tr>
-<td>bar</td>
-<td></td>
-</tr>
-</tbody>
-</table>
-<p>bar</p>
-````````````````````````````````
-
-The header row must match the [delimiter row] in the number of cells. If not,
-a table will not be recognized:
-
-```````````````````````````````` example table
-| abc | def |
-| --- |
-| bar |
-.
-<p>| abc | def |
-| --- |
-| bar |</p>
-````````````````````````````````
-
-The remainder of the table's rows may vary in the number of cells. If there
-are a number of cells fewer than the number of cells in the header row, empty
-cells are inserted. If there are greater, the excess is ignored:
-
-```````````````````````````````` example table
-| abc | def |
-| --- | --- |
-| bar |
-| bar | baz | boo |
-.
-<table>
-<thead>
-<tr>
-<th>abc</th>
-<th>def</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>bar</td>
-<td></td>
-</tr>
-<tr>
-<td>bar</td>
-<td>baz</td>
-</tr>
-</tbody>
-</table>
-````````````````````````````````
-
-If there are no rows in the body, no `<tbody>` is generated in HTML output:
-
-```````````````````````````````` example table
-| abc | def |
-| --- | --- |
-.
-<table>
-<thead>
-<tr>
-<th>abc</th>
-<th>def</th>
-</tr>
-</thead>
-</table>
-````````````````````````````````
-
-</div>
-
-# Container blocks
-
-A [container block](#container-blocks) is a block that has other
-blocks as its contents. There are two basic kinds of container blocks:
-[block quotes] and [list items].
-[Lists] are meta-containers for [list items].
-
-We define the syntax for container blocks recursively. The general
-form of the definition is:
-
-> If X is a sequence of blocks, then the result of
-> transforming X in such-and-such a way is a container of type Y
-> with these blocks as its content.
-
-So, we explain what counts as a block quote or list item by explaining
-how these can be *generated* from their contents. This should suffice
-to define the syntax, although it does not give a recipe for *parsing*
-these constructions. (A recipe is provided below in the section entitled
-[A parsing strategy](#appendix-a-parsing-strategy).)
-
-## Block quotes
-
-A [block quote marker](@)
-consists of 0-3 spaces of initial indent, plus (a) the character `>` together
-with a following space, or (b) a single character `>` not followed by a space.
-
-The following rules define [block quotes]:
-
-1. **Basic case.** If a string of lines *Ls* constitute a sequence
- of blocks *Bs*, then the result of prepending a [block quote
- marker] to the beginning of each line in *Ls*
- is a [block quote](#block-quotes) containing *Bs*.
-
-2. **Laziness.** If a string of lines *Ls* constitute a [block
- quote](#block-quotes) with contents *Bs*, then the result of deleting
- the initial [block quote marker] from one or
- more lines in which the next [non-whitespace character] after the [block
- quote marker] is [paragraph continuation
- text] is a block quote with *Bs* as its content.
- [Paragraph continuation text](@) is text
- that will be parsed as part of the content of a paragraph, but does
- not occur at the beginning of the paragraph.
-
-3. **Consecutiveness.** A document cannot contain two [block
- quotes] in a row unless there is a [blank line] between them.
-
-Nothing else counts as a [block quote](#block-quotes).
-
-Here is a simple example:
-
-```````````````````````````````` example
-> # Foo
-> bar
-> baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-The spaces after the `>` characters can be omitted:
-
-```````````````````````````````` example
-># Foo
->bar
-> baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-The `>` characters can be indented 1-3 spaces:
-
-```````````````````````````````` example
- > # Foo
- > bar
- > baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-Four spaces gives us a code block:
-
-```````````````````````````````` example
- > # Foo
- > bar
- > baz
-.
-<pre><code>&gt; # Foo
-&gt; bar
-&gt; baz
-</code></pre>
-````````````````````````````````
-
-
-The Laziness clause allows us to omit the `>` before
-[paragraph continuation text]:
-
-```````````````````````````````` example
-> # Foo
-> bar
-baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-A block quote can contain some lazy and some non-lazy
-continuation lines:
-
-```````````````````````````````` example
-> bar
-baz
-> foo
-.
-<blockquote>
-<p>bar
-baz
-foo</p>
-</blockquote>
-````````````````````````````````
-
-
-Laziness only applies to lines that would have been continuations of
-paragraphs had they been prepended with [block quote markers].
-For example, the `> ` cannot be omitted in the second line of
-
-``` markdown
-> foo
-> ---
-```
-
-without changing the meaning:
-
-```````````````````````````````` example
-> foo
----
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-Similarly, if we omit the `> ` in the second line of
-
-``` markdown
-> - foo
-> - bar
-```
-
-then the block quote ends after the first line:
-
-```````````````````````````````` example
-> - foo
-- bar
-.
-<blockquote>
-<ul>
-<li>foo</li>
-</ul>
-</blockquote>
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-For the same reason, we can't omit the `> ` in front of
-subsequent lines of an indented or fenced code block:
-
-```````````````````````````````` example
-> foo
- bar
-.
-<blockquote>
-<pre><code>foo
-</code></pre>
-</blockquote>
-<pre><code>bar
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> ```
-foo
-```
-.
-<blockquote>
-<pre><code></code></pre>
-</blockquote>
-<p>foo</p>
-<pre><code></code></pre>
-````````````````````````````````
-
-
-Note that in the following case, we have a [lazy
-continuation line]:
-
-```````````````````````````````` example
-> foo
- - bar
-.
-<blockquote>
-<p>foo
-- bar</p>
-</blockquote>
-````````````````````````````````
-
-
-To see why, note that in
-
-```markdown
-> foo
-> - bar
-```
-
-the `- bar` is indented too far to start a list, and can't
-be an indented code block because indented code blocks cannot
-interrupt paragraphs, so it is [paragraph continuation text].
-
-A block quote can be empty:
-
-```````````````````````````````` example
->
-.
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
->
->
->
-.
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-A block quote can have initial or final blank lines:
-
-```````````````````````````````` example
->
-> foo
->
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-````````````````````````````````
-
-
-A blank line always separates block quotes:
-
-```````````````````````````````` example
-> foo
-
-> bar
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-(Most current Markdown implementations, including John Gruber's
-original `Markdown.pl`, will parse this example as a single block quote
-with two paragraphs. But it seems better to allow the author to decide
-whether two block quotes or one are wanted.)
-
-Consecutiveness means that if we put these block quotes together,
-we get a single block quote:
-
-```````````````````````````````` example
-> foo
-> bar
-.
-<blockquote>
-<p>foo
-bar</p>
-</blockquote>
-````````````````````````````````
-
-
-To get a block quote with two paragraphs, use:
-
-```````````````````````````````` example
-> foo
->
-> bar
-.
-<blockquote>
-<p>foo</p>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-Block quotes can interrupt paragraphs:
-
-```````````````````````````````` example
-foo
-> bar
-.
-<p>foo</p>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-In general, blank lines are not needed before or after block
-quotes:
-
-```````````````````````````````` example
-> aaa
-***
-> bbb
-.
-<blockquote>
-<p>aaa</p>
-</blockquote>
-<hr />
-<blockquote>
-<p>bbb</p>
-</blockquote>
-````````````````````````````````
-
-
-However, because of laziness, a blank line is needed between
-a block quote and a following paragraph:
-
-```````````````````````````````` example
-> bar
-baz
-.
-<blockquote>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> bar
-
-baz
-.
-<blockquote>
-<p>bar</p>
-</blockquote>
-<p>baz</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> bar
->
-baz
-.
-<blockquote>
-<p>bar</p>
-</blockquote>
-<p>baz</p>
-````````````````````````````````
-
-
-It is a consequence of the Laziness rule that any number
-of initial `>`s may be omitted on a continuation line of a
-nested block quote:
-
-```````````````````````````````` example
-> > > foo
-bar
-.
-<blockquote>
-<blockquote>
-<blockquote>
-<p>foo
-bar</p>
-</blockquote>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
->>> foo
-> bar
->>baz
-.
-<blockquote>
-<blockquote>
-<blockquote>
-<p>foo
-bar
-baz</p>
-</blockquote>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-When including an indented code block in a block quote,
-remember that the [block quote marker] includes
-both the `>` and a following space. So *five spaces* are needed after
-the `>`:
-
-```````````````````````````````` example
-> code
-
-> not code
-.
-<blockquote>
-<pre><code>code
-</code></pre>
-</blockquote>
-<blockquote>
-<p>not code</p>
-</blockquote>
-````````````````````````````````
-
-
-
-## List items
-
-A [list marker](@) is a
-[bullet list marker] or an [ordered list marker].
-
-A [bullet list marker](@)
-is a `-`, `+`, or `*` character.
-
-An [ordered list marker](@)
-is a sequence of 1--9 arabic digits (`0-9`), followed by either a
-`.` character or a `)` character. (The reason for the length
-limit is that with 10 digits we start seeing integer overflows
-in some browsers.)
-
-The following rules define [list items]:
-
-1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of
- blocks *Bs* starting with a [non-whitespace character], and *M* is a
- list marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result
- of prepending *M* and the following spaces to the first line of
- *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a
- list item with *Bs* as its contents. The type of the list item
- (bullet or ordered) is determined by the type of its list marker.
- If the list item is ordered, then it is also assigned a start
- number, based on the ordered list marker.
-
- Exceptions:
-
- 1. When the first list item in a [list] interrupts
- a paragraph---that is, when it starts on a line that would
- otherwise count as [paragraph continuation text]---then (a)
- the lines *Ls* must not begin with a blank line, and (b) if
- the list item is ordered, the start number must be 1.
- 2. If any line is a [thematic break][thematic breaks] then
- that line is not a list item.
-
-For example, let *Ls* be the lines
-
-```````````````````````````````` example
-A paragraph
-with two lines.
-
- indented code
-
-> A block quote.
-.
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-````````````````````````````````
-
-
-And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says
-that the following is an ordered list item with start number 1,
-and the same contents as *Ls*:
-
-```````````````````````````````` example
-1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-The most important thing to notice is that the position of
-the text after the list marker determines how much indentation
-is needed in subsequent blocks in the list item. If the list
-marker takes up two spaces, and there are three spaces between
-the list marker and the next [non-whitespace character], then blocks
-must be indented five spaces in order to fall under the list
-item.
-
-Here are some examples showing how far content must be indented to be
-put under the list item:
-
-```````````````````````````````` example
-- one
-
- two
-.
-<ul>
-<li>one</li>
-</ul>
-<p>two</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- one
-
- two
-.
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
- - one
-
- two
-.
-<ul>
-<li>one</li>
-</ul>
-<pre><code> two
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- - one
-
- two
-.
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-It is tempting to think of this in terms of columns: the continuation
-blocks must be indented at least to the column of the first
-[non-whitespace character] after the list marker. However, that is not quite right.
-The spaces after the list marker determine how much relative indentation
-is needed. Which column this indentation reaches will depend on
-how the list item is embedded in other constructions, as shown by
-this example:
-
-```````````````````````````````` example
- > > 1. one
->>
->> two
-.
-<blockquote>
-<blockquote>
-<ol>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ol>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-Here `two` occurs in the same column as the list marker `1.`,
-but is actually contained in the list item, because there is
-sufficient indentation after the last containing blockquote marker.
-
-The converse is also possible. In the following example, the word `two`
-occurs far to the right of the initial text of the list item, `one`, but
-it is not considered part of the list item, because it is not indented
-far enough past the blockquote marker:
-
-```````````````````````````````` example
->>- one
->>
- > > two
-.
-<blockquote>
-<blockquote>
-<ul>
-<li>one</li>
-</ul>
-<p>two</p>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-Note that at least one space is needed between the list marker and
-any following content, so these are not list items:
-
-```````````````````````````````` example
--one
-
-2.two
-.
-<p>-one</p>
-<p>2.two</p>
-````````````````````````````````
-
-
-A list item may contain blocks that are separated by more than
-one blank line.
-
-```````````````````````````````` example
-- foo
-
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-A list item may contain any kind of block:
-
-```````````````````````````````` example
-1. foo
-
- ```
- bar
- ```
-
- baz
-
- > bam
-.
-<ol>
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-<p>baz</p>
-<blockquote>
-<p>bam</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-A list item that contains an indented code block will preserve
-empty lines within the code block verbatim.
-
-```````````````````````````````` example
-- Foo
-
- bar
-
-
- baz
-.
-<ul>
-<li>
-<p>Foo</p>
-<pre><code>bar
-
-
-baz
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-Note that ordered list start numbers must be nine digits or less:
-
-```````````````````````````````` example
-123456789. ok
-.
-<ol start="123456789">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1234567890. not ok
-.
-<p>1234567890. not ok</p>
-````````````````````````````````
-
-
-A start number may begin with 0s:
-
-```````````````````````````````` example
-0. ok
-.
-<ol start="0">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-```````````````````````````````` example
-003. ok
-.
-<ol start="3">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-A start number may not be negative:
-
-```````````````````````````````` example
--1. not ok
-.
-<p>-1. not ok</p>
-````````````````````````````````
-
-
-
-2. **Item starting with indented code.** If a sequence of lines *Ls*
- constitute a sequence of blocks *Bs* starting with an indented code
- block, and *M* is a list marker of width *W* followed by
- one space, then the result of prepending *M* and the following
- space to the first line of *Ls*, and indenting subsequent lines of
- *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents.
- If a line is empty, then it need not be indented. The type of the
- list item (bullet or ordered) is determined by the type of its list
- marker. If the list item is ordered, then it is also assigned a
- start number, based on the ordered list marker.
-
-An indented code block will have to be indented four spaces beyond
-the edge of the region where text will be included in the list item.
-In the following case that is 6 spaces:
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-
-And in this case it is 11 spaces:
-
-```````````````````````````````` example
- 10. foo
-
- bar
-.
-<ol start="10">
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-If the *first* block in the list item is an indented code block,
-then by rule #2, the contents must be indented *one* space after the
-list marker:
-
-```````````````````````````````` example
- indented code
-
-paragraph
-
- more code
-.
-<pre><code>indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. indented code
-
- paragraph
-
- more code
-.
-<ol>
-<li>
-<pre><code>indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-Note that an additional space indent is interpreted as space
-inside the code block:
-
-```````````````````````````````` example
-1. indented code
-
- paragraph
-
- more code
-.
-<ol>
-<li>
-<pre><code> indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-Note that rules #1 and #2 only apply to two cases: (a) cases
-in which the lines to be included in a list item begin with a
-[non-whitespace character], and (b) cases in which
-they begin with an indented code
-block. In a case like the following, where the first block begins with
-a three-space indent, the rules do not allow us to form a list item by
-indenting the whole thing and prepending a list marker:
-
-```````````````````````````````` example
- foo
-
-bar
-.
-<p>foo</p>
-<p>bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-````````````````````````````````
-
-
-This is not a significant restriction, because when a block begins
-with 1-3 spaces indent, the indentation can always be removed without
-a change in interpretation, allowing rule #1 to be applied. So, in
-the above case:
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-3. **Item starting with a blank line.** If a sequence of lines *Ls*
- starting with a single [blank line] constitute a (possibly empty)
- sequence of blocks *Bs*, not separated from each other by more than
- one blank line, and *M* is a list marker of width *W*,
- then the result of prepending *M* to the first line of *Ls*, and
- indenting subsequent lines of *Ls* by *W + 1* spaces, is a list
- item with *Bs* as its contents.
- If a line is empty, then it need not be indented. The type of the
- list item (bullet or ordered) is determined by the type of its list
- marker. If the list item is ordered, then it is also assigned a
- start number, based on the ordered list marker.
-
-Here are some list items that start with a blank line but are not empty:
-
-```````````````````````````````` example
--
- foo
--
- ```
- bar
- ```
--
- baz
-.
-<ul>
-<li>foo</li>
-<li>
-<pre><code>bar
-</code></pre>
-</li>
-<li>
-<pre><code>baz
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-When the list item starts with a blank line, the number of spaces
-following the list marker doesn't change the required indentation:
-
-```````````````````````````````` example
--
- foo
-.
-<ul>
-<li>foo</li>
-</ul>
-````````````````````````````````
-
-
-A list item can begin with at most one blank line.
-In the following example, `foo` is not part of the list
-item:
-
-```````````````````````````````` example
--
-
- foo
-.
-<ul>
-<li></li>
-</ul>
-<p>foo</p>
-````````````````````````````````
-
-
-Here is an empty bullet list item:
-
-```````````````````````````````` example
-- foo
--
-- bar
-.
-<ul>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-It does not matter whether there are spaces following the [list marker]:
-
-```````````````````````````````` example
-- foo
--
-- bar
-.
-<ul>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-Here is an empty ordered list item:
-
-```````````````````````````````` example
-1. foo
-2.
-3. bar
-.
-<ol>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ol>
-````````````````````````````````
-
-
-A list may start or end with an empty list item:
-
-```````````````````````````````` example
-*
-.
-<ul>
-<li></li>
-</ul>
-````````````````````````````````
-
-However, an empty list item cannot interrupt a paragraph:
-
-```````````````````````````````` example
-foo
-*
-
-foo
-1.
-.
-<p>foo
-*</p>
-<p>foo
-1.</p>
-````````````````````````````````
-
-
-4. **Indentation.** If a sequence of lines *Ls* constitutes a list item
- according to rule #1, #2, or #3, then the result of indenting each line
- of *Ls* by 1-3 spaces (the same for each line) also constitutes a
- list item with the same contents and attributes. If a line is
- empty, then it need not be indented.
-
-Indented one space:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indented two spaces:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indented three spaces:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Four spaces indent gives a code block:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<pre><code>1. A paragraph
- with two lines.
-
- indented code
-
- &gt; A block quote.
-</code></pre>
-````````````````````````````````
-
-
-
-5. **Laziness.** If a string of lines *Ls* constitute a [list
- item](#list-items) with contents *Bs*, then the result of deleting
- some or all of the indentation from one or more lines in which the
- next [non-whitespace character] after the indentation is
- [paragraph continuation text] is a
- list item with the same contents and attributes. The unindented
- lines are called
- [lazy continuation line](@)s.
-
-Here is an example with [lazy continuation lines]:
-
-```````````````````````````````` example
- 1. A paragraph
-with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indentation can be partially deleted:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-.
-<ol>
-<li>A paragraph
-with two lines.</li>
-</ol>
-````````````````````````````````
-
-
-These examples show how laziness can work in nested structures:
-
-```````````````````````````````` example
-> 1. > Blockquote
-continued here.
-.
-<blockquote>
-<ol>
-<li>
-<blockquote>
-<p>Blockquote
-continued here.</p>
-</blockquote>
-</li>
-</ol>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> 1. > Blockquote
-> continued here.
-.
-<blockquote>
-<ol>
-<li>
-<blockquote>
-<p>Blockquote
-continued here.</p>
-</blockquote>
-</li>
-</ol>
-</blockquote>
-````````````````````````````````
-
-
-
-6. **That's all.** Nothing that is not counted as a list item by rules
- #1--5 counts as a [list item](#list-items).
-
-The rules for sublists follow from the general rules
-[above][List items]. A sublist must be indented the same number
-of spaces a paragraph would need to be in order to be included
-in the list item.
-
-So, in this case we need two spaces indent:
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
- - boo
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>baz
-<ul>
-<li>boo</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-One is not enough:
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
- - boo
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-<li>baz</li>
-<li>boo</li>
-</ul>
-````````````````````````````````
-
-
-Here we need four, because the list marker is wider:
-
-```````````````````````````````` example
-10) foo
- - bar
-.
-<ol start="10">
-<li>foo
-<ul>
-<li>bar</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-Three is not enough:
-
-```````````````````````````````` example
-10) foo
- - bar
-.
-<ol start="10">
-<li>foo</li>
-</ol>
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-A list may be the first block in a list item:
-
-```````````````````````````````` example
-- - foo
-.
-<ul>
-<li>
-<ul>
-<li>foo</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. - 2. foo
-.
-<ol>
-<li>
-<ul>
-<li>
-<ol start="2">
-<li>foo</li>
-</ol>
-</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-A list item can contain a heading:
-
-```````````````````````````````` example
-- # Foo
-- Bar
- ---
- baz
-.
-<ul>
-<li>
-<h1>Foo</h1>
-</li>
-<li>
-<h2>Bar</h2>
-baz</li>
-</ul>
-````````````````````````````````
-
-
-### Motivation
-
-John Gruber's Markdown spec says the following about list items:
-
-1. "List markers typically start at the left margin, but may be indented
- by up to three spaces. List markers must be followed by one or more
- spaces or a tab."
-
-2. "To make lists look nice, you can wrap items with hanging indents....
- But if you don't want to, you don't have to."
-
-3. "List items may consist of multiple paragraphs. Each subsequent
- paragraph in a list item must be indented by either 4 spaces or one
- tab."
-
-4. "It looks nice if you indent every line of the subsequent paragraphs,
- but here again, Markdown will allow you to be lazy."
-
-5. "To put a blockquote within a list item, the blockquote's `>`
- delimiters need to be indented."
-
-6. "To put a code block within a list item, the code block needs to be
- indented twice — 8 spaces or two tabs."
-
-These rules specify that a paragraph under a list item must be indented
-four spaces (presumably, from the left margin, rather than the start of
-the list marker, but this is not said), and that code under a list item
-must be indented eight spaces instead of the usual four. They also say
-that a block quote must be indented, but not by how much; however, the
-example given has four spaces indentation. Although nothing is said
-about other kinds of block-level content, it is certainly reasonable to
-infer that *all* block elements under a list item, including other
-lists, must be indented four spaces. This principle has been called the
-*four-space rule*.
-
-The four-space rule is clear and principled, and if the reference
-implementation `Markdown.pl` had followed it, it probably would have
-become the standard. However, `Markdown.pl` allowed paragraphs and
-sublists to start with only two spaces indentation, at least on the
-outer level. Worse, its behavior was inconsistent: a sublist of an
-outer-level list needed two spaces indentation, but a sublist of this
-sublist needed three spaces. It is not surprising, then, that different
-implementations of Markdown have developed very different rules for
-determining what comes under a list item. (Pandoc and python-Markdown,
-for example, stuck with Gruber's syntax description and the four-space
-rule, while discount, redcarpet, marked, PHP Markdown, and others
-followed `Markdown.pl`'s behavior more closely.)
-
-Unfortunately, given the divergences between implementations, there
-is no way to give a spec for list items that will be guaranteed not
-to break any existing documents. However, the spec given here should
-correctly handle lists formatted with either the four-space rule or
-the more forgiving `Markdown.pl` behavior, provided they are laid out
-in a way that is natural for a human to read.
-
-The strategy here is to let the width and indentation of the list marker
-determine the indentation necessary for blocks to fall under the list
-item, rather than having a fixed and arbitrary number. The writer can
-think of the body of the list item as a unit which gets indented to the
-right enough to fit the list marker (and any indentation on the list
-marker). (The laziness rule, #5, then allows continuation lines to be
-unindented if needed.)
-
-This rule is superior, we claim, to any rule requiring a fixed level of
-indentation from the margin. The four-space rule is clear but
-unnatural. It is quite unintuitive that
-
-``` markdown
-- foo
-
- bar
-
- - baz
-```
-
-should be parsed as two lists with an intervening paragraph,
-
-``` html
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>baz</li>
-</ul>
-```
-
-as the four-space rule demands, rather than a single list,
-
-``` html
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-```
-
-The choice of four spaces is arbitrary. It can be learned, but it is
-not likely to be guessed, and it trips up beginners regularly.
-
-Would it help to adopt a two-space rule? The problem is that such
-a rule, together with the rule allowing 1--3 spaces indentation of the
-initial list marker, allows text that is indented *less than* the
-original list marker to be included in the list item. For example,
-`Markdown.pl` parses
-
-``` markdown
- - one
-
- two
-```
-
-as a single list item, with `two` a continuation paragraph:
-
-``` html
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-```
-
-and similarly
-
-``` markdown
-> - one
->
-> two
-```
-
-as
-
-``` html
-<blockquote>
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-</blockquote>
-```
-
-This is extremely unintuitive.
-
-Rather than requiring a fixed indent from the margin, we could require
-a fixed indent (say, two spaces, or even one space) from the list marker (which
-may itself be indented). This proposal would remove the last anomaly
-discussed. Unlike the spec presented above, it would count the following
-as a list item with a subparagraph, even though the paragraph `bar`
-is not indented as far as the first paragraph `foo`:
-
-``` markdown
- 10. foo
-
- bar
-```
-
-Arguably this text does read like a list item with `bar` as a subparagraph,
-which may count in favor of the proposal. However, on this proposal indented
-code would have to be indented six spaces after the list marker. And this
-would break a lot of existing Markdown, which has the pattern:
-
-``` markdown
-1. foo
-
- indented code
-```
-
-where the code is indented eight spaces. The spec above, by contrast, will
-parse this text as expected, since the code block's indentation is measured
-from the beginning of `foo`.
-
-The one case that needs special treatment is a list item that *starts*
-with indented code. How much indentation is required in that case, since
-we don't have a "first paragraph" to measure from? Rule #2 simply stipulates
-that in such cases, we require one space indentation from the list marker
-(and then the normal four spaces for the indented code). This will match the
-four-space rule in cases where the list marker plus its initial indentation
-takes four spaces (a common case), but diverge in other cases.
-
-<div class="extension">
-
-## Task list items (extension)
-
-GFM enables the `tasklist` extension, where an additional processing step is
-performed on [list items].
-
-A [task list item](@) is a [list item][list items] where the first block in it
-is a paragraph which begins with a [task list item marker] and at least one
-whitespace character before any other content.
-
-A [task list item marker](@) consists of an optional number of spaces, a left
-bracket (`[`), either a whitespace character or the letter `x` in either
-lowercase or uppercase, and then a right bracket (`]`).
-
-When rendered, the [task list item marker] is replaced with a semantic checkbox element;
-in an HTML output, this would be an `<input type="checkbox">` element.
-
-If the character between the brackets is a whitespace character, the checkbox
-is unchecked. Otherwise, the checkbox is checked.
-
-This spec does not define how the checkbox elements are interacted with: in practice,
-implementors are free to render the checkboxes as disabled or inmutable elements,
-or they may dynamically handle dynamic interactions (i.e. checking, unchecking) in
-the final rendered document.
-
-```````````````````````````````` example disabled
-- [ ] foo
-- [x] bar
-.
-<ul>
-<li><input disabled="" type="checkbox"> foo</li>
-<li><input checked="" disabled="" type="checkbox"> bar</li>
-</ul>
-````````````````````````````````
-
-Task lists can be arbitrarily nested:
-
-```````````````````````````````` example disabled
-- [x] foo
- - [ ] bar
- - [x] baz
-- [ ] bim
-.
-<ul>
-<li><input checked="" disabled="" type="checkbox"> foo
-<ul>
-<li><input disabled="" type="checkbox"> bar</li>
-<li><input checked="" disabled="" type="checkbox"> baz</li>
-</ul>
-</li>
-<li><input disabled="" type="checkbox"> bim</li>
-</ul>
-````````````````````````````````
-
-</div>
-
-## Lists
-
-A [list](@) is a sequence of one or more
-list items [of the same type]. The list items
-may be separated by any number of blank lines.
-
-Two list items are [of the same type](@)
-if they begin with a [list marker] of the same type.
-Two list markers are of the
-same type if (a) they are bullet list markers using the same character
-(`-`, `+`, or `*`) or (b) they are ordered list numbers with the same
-delimiter (either `.` or `)`).
-
-A list is an [ordered list](@)
-if its constituent list items begin with
-[ordered list markers], and a
-[bullet list](@) if its constituent list
-items begin with [bullet list markers].
-
-The [start number](@)
-of an [ordered list] is determined by the list number of
-its initial list item. The numbers of subsequent list items are
-disregarded.
-
-A list is [loose](@) if any of its constituent
-list items are separated by blank lines, or if any of its constituent
-list items directly contain two block-level elements with a blank line
-between them. Otherwise a list is [tight](@).
-(The difference in HTML output is that paragraphs in a loose list are
-wrapped in `<p>` tags, while paragraphs in a tight list are not.)
-
-Changing the bullet or ordered list delimiter starts a new list:
-
-```````````````````````````````` example
-- foo
-- bar
-+ baz
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-</ul>
-<ul>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. foo
-2. bar
-3) baz
-.
-<ol>
-<li>foo</li>
-<li>bar</li>
-</ol>
-<ol start="3">
-<li>baz</li>
-</ol>
-````````````````````````````````
-
-
-In CommonMark, a list can interrupt a paragraph. That is,
-no blank line is needed to separate a paragraph from a following
-list:
-
-```````````````````````````````` example
-Foo
-- bar
-- baz
-.
-<p>Foo</p>
-<ul>
-<li>bar</li>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-`Markdown.pl` does not allow this, through fear of triggering a list
-via a numeral in a hard-wrapped line:
-
-``` markdown
-The number of windows in my house is
-14. The number of doors is 6.
-```
-
-Oddly, though, `Markdown.pl` *does* allow a blockquote to
-interrupt a paragraph, even though the same considerations might
-apply.
-
-In CommonMark, we do allow lists to interrupt paragraphs, for
-two reasons. First, it is natural and not uncommon for people
-to start lists without blank lines:
-
-``` markdown
-I need to buy
-- new shoes
-- a coat
-- a plane ticket
-```
-
-Second, we are attracted to a
-
-> [principle of uniformity](@):
-> if a chunk of text has a certain
-> meaning, it will continue to have the same meaning when put into a
-> container block (such as a list item or blockquote).
-
-(Indeed, the spec for [list items] and [block quotes] presupposes
-this principle.) This principle implies that if
-
-``` markdown
- * I need to buy
- - new shoes
- - a coat
- - a plane ticket
-```
-
-is a list item containing a paragraph followed by a nested sublist,
-as all Markdown implementations agree it is (though the paragraph
-may be rendered without `<p>` tags, since the list is "tight"),
-then
-
-``` markdown
-I need to buy
-- new shoes
-- a coat
-- a plane ticket
-```
-
-by itself should be a paragraph followed by a nested sublist.
-
-Since it is well established Markdown practice to allow lists to
-interrupt paragraphs inside list items, the [principle of
-uniformity] requires us to allow this outside list items as
-well. ([reStructuredText](http://docutils.sourceforge.net/rst.html)
-takes a different approach, requiring blank lines before lists
-even inside other list items.)
-
-In order to solve of unwanted lists in paragraphs with
-hard-wrapped numerals, we allow only lists starting with `1` to
-interrupt paragraphs. Thus,
-
-```````````````````````````````` example
-The number of windows in my house is
-14. The number of doors is 6.
-.
-<p>The number of windows in my house is
-14. The number of doors is 6.</p>
-````````````````````````````````
-
-We may still get an unintended result in cases like
-
-```````````````````````````````` example
-The number of windows in my house is
-1. The number of doors is 6.
-.
-<p>The number of windows in my house is</p>
-<ol>
-<li>The number of doors is 6.</li>
-</ol>
-````````````````````````````````
-
-but this rule should prevent most spurious list captures.
-
-There can be any number of blank lines between items:
-
-```````````````````````````````` example
-- foo
-
-- bar
-
-
-- baz
-.
-<ul>
-<li>
-<p>foo</p>
-</li>
-<li>
-<p>bar</p>
-</li>
-<li>
-<p>baz</p>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
-
-
- bim
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>
-<p>baz</p>
-<p>bim</p>
-</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-To separate consecutive lists of the same type, or to separate a
-list from an indented code block that would otherwise be parsed
-as a subparagraph of the final list item, you can insert a blank HTML
-comment:
-
-```````````````````````````````` example
-- foo
-- bar
-
-<!-- -->
-
-- baz
-- bim
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-</ul>
-<!-- -->
-<ul>
-<li>baz</li>
-<li>bim</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
-
- notcode
-
-- foo
-
-<!-- -->
-
- code
-.
-<ul>
-<li>
-<p>foo</p>
-<p>notcode</p>
-</li>
-<li>
-<p>foo</p>
-</li>
-</ul>
-<!-- -->
-<pre><code>code
-</code></pre>
-````````````````````````````````
-
-
-List items need not be indented to the same level. The following
-list items will be treated as items at the same list level,
-since none is indented enough to belong to the previous list
-item:
-
-```````````````````````````````` example
-- a
- - b
- - c
- - d
- - e
- - f
-- g
-.
-<ul>
-<li>a</li>
-<li>b</li>
-<li>c</li>
-<li>d</li>
-<li>e</li>
-<li>f</li>
-<li>g</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. a
-
- 2. b
-
- 3. c
-.
-<ol>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>c</p>
-</li>
-</ol>
-````````````````````````````````
-
-Note, however, that list items may not be indented more than
-three spaces. Here `- e` is treated as a paragraph continuation
-line, because it is indented more than three spaces:
-
-```````````````````````````````` example
-- a
- - b
- - c
- - d
- - e
-.
-<ul>
-<li>a</li>
-<li>b</li>
-<li>c</li>
-<li>d
-- e</li>
-</ul>
-````````````````````````````````
-
-And here, `3. c` is treated as in indented code block,
-because it is indented four spaces and preceded by a
-blank line.
-
-```````````````````````````````` example
-1. a
-
- 2. b
-
- 3. c
-.
-<ol>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-</ol>
-<pre><code>3. c
-</code></pre>
-````````````````````````````````
-
-
-This is a loose list, because there is a blank line between
-two of the list items:
-
-```````````````````````````````` example
-- a
-- b
-
-- c
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>c</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-So is this, with a empty second item:
-
-```````````````````````````````` example
-* a
-*
-
-* c
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li></li>
-<li>
-<p>c</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-These are loose lists, even though there is no space between the items,
-because one of the items directly contains two block-level elements
-with a blank line between them:
-
-```````````````````````````````` example
-- a
-- b
-
- c
-- d
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-<p>c</p>
-</li>
-<li>
-<p>d</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
-- b
-
- [ref]: /url
-- d
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>d</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank lines are in a code block:
-
-```````````````````````````````` example
-- a
-- ```
- b
-
-
- ```
-- c
-.
-<ul>
-<li>a</li>
-<li>
-<pre><code>b
-
-
-</code></pre>
-</li>
-<li>c</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank line is between two
-paragraphs of a sublist. So the sublist is loose while
-the outer list is tight:
-
-```````````````````````````````` example
-- a
- - b
-
- c
-- d
-.
-<ul>
-<li>a
-<ul>
-<li>
-<p>b</p>
-<p>c</p>
-</li>
-</ul>
-</li>
-<li>d</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank line is inside the
-block quote:
-
-```````````````````````````````` example
-* a
- > b
- >
-* c
-.
-<ul>
-<li>a
-<blockquote>
-<p>b</p>
-</blockquote>
-</li>
-<li>c</li>
-</ul>
-````````````````````````````````
-
-
-This list is tight, because the consecutive block elements
-are not separated by blank lines:
-
-```````````````````````````````` example
-- a
- > b
- ```
- c
- ```
-- d
-.
-<ul>
-<li>a
-<blockquote>
-<p>b</p>
-</blockquote>
-<pre><code>c
-</code></pre>
-</li>
-<li>d</li>
-</ul>
-````````````````````````````````
-
-
-A single-paragraph list is tight:
-
-```````````````````````````````` example
-- a
-.
-<ul>
-<li>a</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
- - b
-.
-<ul>
-<li>a
-<ul>
-<li>b</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-This list is loose, because of the blank line between the
-two block elements in the list item:
-
-```````````````````````````````` example
-1. ```
- foo
- ```
-
- bar
-.
-<ol>
-<li>
-<pre><code>foo
-</code></pre>
-<p>bar</p>
-</li>
-</ol>
-````````````````````````````````
-
-
-Here the outer list is loose, the inner list tight:
-
-```````````````````````````````` example
-* foo
- * bar
-
- baz
-.
-<ul>
-<li>
-<p>foo</p>
-<ul>
-<li>bar</li>
-</ul>
-<p>baz</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
- - b
- - c
-
-- d
- - e
- - f
-.
-<ul>
-<li>
-<p>a</p>
-<ul>
-<li>b</li>
-<li>c</li>
-</ul>
-</li>
-<li>
-<p>d</p>
-<ul>
-<li>e</li>
-<li>f</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-# Inlines
-
-Inlines are parsed sequentially from the beginning of the character
-stream to the end (left to right, in left-to-right languages).
-Thus, for example, in
-
-```````````````````````````````` example
-`hi`lo`
-.
-<p><code>hi</code>lo`</p>
-````````````````````````````````
-
-`hi` is parsed as code, leaving the backtick at the end as a literal
-backtick.
-
-
-## Backslash escapes
-
-Any ASCII punctuation character may be backslash-escaped:
-
-```````````````````````````````` example
-\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
-.
-<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
-````````````````````````````````
-
-
-Backslashes before other characters are treated as literal
-backslashes:
-
-```````````````````````````````` example
-\→\A\a\ \3\φ\«
-.
-<p>\→\A\a\ \3\φ\«</p>
-````````````````````````````````
-
-
-Escaped characters are treated as regular characters and do
-not have their usual Markdown meanings:
-
-```````````````````````````````` example
-\*not emphasized*
-\<br/> not a tag
-\[not a link](/foo)
-\`not code`
-1\. not a list
-\* not a list
-\# not a heading
-\[foo]: /url "not a reference"
-\&ouml; not a character entity
-.
-<p>*not emphasized*
-&lt;br/&gt; not a tag
-[not a link](/foo)
-`not code`
-1. not a list
-* not a list
-# not a heading
-[foo]: /url &quot;not a reference&quot;
-&amp;ouml; not a character entity</p>
-````````````````````````````````
-
-
-If a backslash is itself escaped, the following character is not:
-
-```````````````````````````````` example
-\\*emphasis*
-.
-<p>\<em>emphasis</em></p>
-````````````````````````````````
-
-
-A backslash at the end of the line is a [hard line break]:
-
-```````````````````````````````` example
-foo\
-bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-Backslash escapes do not work in code blocks, code spans, autolinks, or
-raw HTML:
-
-```````````````````````````````` example
-`` \[\` ``
-.
-<p><code>\[\`</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- \[\]
-.
-<pre><code>\[\]
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~
-\[\]
-~~~
-.
-<pre><code>\[\]
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://example.com?find=\*>
-.
-<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="/bar\/)">
-.
-<a href="/bar\/)">
-````````````````````````````````
-
-
-But they work in all other contexts, including URLs and link titles,
-link references, and [info strings] in [fenced code blocks]:
-
-```````````````````````````````` example
-[foo](/bar\* "ti\*tle")
-.
-<p><a href="/bar*" title="ti*tle">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /bar\* "ti\*tle"
-.
-<p><a href="/bar*" title="ti*tle">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-``` foo\+bar
-foo
-```
-.
-<pre><code class="language-foo+bar">foo
-</code></pre>
-````````````````````````````````
-
-
-
-## Entity and numeric character references
-
-Valid HTML entity references and numeric character references
-can be used in place of the corresponding Unicode character,
-with the following exceptions:
-
-- Entity and character references are not recognized in code
- blocks and code spans.
-
-- Entity and character references cannot stand in place of
- special characters that define structural elements in
- CommonMark. For example, although `&#42;` can be used
- in place of a literal `*` character, `&#42;` cannot replace
- `*` in emphasis delimiters, bullet list markers, or thematic
- breaks.
-
-Conforming CommonMark parsers need not store information about
-whether a particular character was represented in the source
-using a Unicode character or an entity reference.
-
-[Entity references](@) consist of `&` + any of the valid
-HTML5 entity names + `;`. The
-document <https://html.spec.whatwg.org/multipage/entities.json>
-is used as an authoritative source for the valid entity
-references and their corresponding code points.
-
-```````````````````````````````` example
-&nbsp; &amp; &copy; &AElig; &Dcaron;
-&frac34; &HilbertSpace; &DifferentialD;
-&ClockwiseContourIntegral; &ngE;
-.
-<p>  &amp; © Æ Ď
-¾ ℋ ⅆ
-∲ ≧̸</p>
-````````````````````````````````
-
-
-[Decimal numeric character
-references](@)
-consist of `&#` + a string of 1--7 arabic digits + `;`. A
-numeric character reference is parsed as the corresponding
-Unicode character. Invalid Unicode code points will be replaced by
-the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons,
-the code point `U+0000` will also be replaced by `U+FFFD`.
-
-```````````````````````````````` example
-&#35; &#1234; &#992; &#0;
-.
-<p># Ӓ Ϡ �</p>
-````````````````````````````````
-
-
-[Hexadecimal numeric character
-references](@) consist of `&#` +
-either `X` or `x` + a string of 1-6 hexadecimal digits + `;`.
-They too are parsed as the corresponding Unicode character (this
-time specified with a hexadecimal numeral instead of decimal).
-
-```````````````````````````````` example
-&#X22; &#XD06; &#xcab;
-.
-<p>&quot; ആ ಫ</p>
-````````````````````````````````
-
-
-Here are some nonentities:
-
-```````````````````````````````` example
-&nbsp &x; &#; &#x;
-&#987654321;
-&#abcdef0;
-&ThisIsNotDefined; &hi?;
-.
-<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
-&amp;#987654321;
-&amp;#abcdef0;
-&amp;ThisIsNotDefined; &amp;hi?;</p>
-````````````````````````````````
-
-
-Although HTML5 does accept some entity references
-without a trailing semicolon (such as `&copy`), these are not
-recognized here, because it makes the grammar too ambiguous:
-
-```````````````````````````````` example
-&copy
-.
-<p>&amp;copy</p>
-````````````````````````````````
-
-
-Strings that are not on the list of HTML5 named entities are not
-recognized as entity references either:
-
-```````````````````````````````` example
-&MadeUpEntity;
-.
-<p>&amp;MadeUpEntity;</p>
-````````````````````````````````
-
-
-Entity and numeric character references are recognized in any
-context besides code spans or code blocks, including
-URLs, [link titles], and [fenced code block][] [info strings]:
-
-```````````````````````````````` example
-<a href="&ouml;&ouml;.html">
-.
-<a href="&ouml;&ouml;.html">
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
-.
-<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
-.
-<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-``` f&ouml;&ouml;
-foo
-```
-.
-<pre><code class="language-föö">foo
-</code></pre>
-````````````````````````````````
-
-
-Entity and numeric character references are treated as literal
-text in code spans and code blocks:
-
-```````````````````````````````` example
-`f&ouml;&ouml;`
-.
-<p><code>f&amp;ouml;&amp;ouml;</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- f&ouml;f&ouml;
-.
-<pre><code>f&amp;ouml;f&amp;ouml;
-</code></pre>
-````````````````````````````````
-
-
-Entity and numeric character references cannot be used
-in place of symbols indicating structure in CommonMark
-documents.
-
-```````````````````````````````` example
-&#42;foo&#42;
-*foo*
-.
-<p>*foo*
-<em>foo</em></p>
-````````````````````````````````
-
-```````````````````````````````` example
-&#42; foo
-
-* foo
-.
-<p>* foo</p>
-<ul>
-<li>foo</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-foo&#10;&#10;bar
-.
-<p>foo
-
-bar</p>
-````````````````````````````````
-
-```````````````````````````````` example
-&#9;foo
-.
-<p>→foo</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[a](url &quot;tit&quot;)
-.
-<p>[a](url &quot;tit&quot;)</p>
-````````````````````````````````
-
-
-## Code spans
-
-A [backtick string](@)
-is a string of one or more backtick characters (`` ` ``) that is neither
-preceded nor followed by a backtick.
-
-A [code span](@) begins with a backtick string and ends with
-a backtick string of equal length. The contents of the code span are
-the characters between the two backtick strings, normalized in the
-following ways:
-
-- First, [line endings] are converted to [spaces].
-- If the resulting string both begins *and* ends with a [space]
- character, but does not consist entirely of [space]
- characters, a single [space] character is removed from the
- front and back. This allows you to include code that begins
- or ends with backtick characters, which must be separated by
- whitespace from the opening or closing backtick strings.
-
-This is a simple code span:
-
-```````````````````````````````` example
-`foo`
-.
-<p><code>foo</code></p>
-````````````````````````````````
-
-
-Here two backticks are used, because the code contains a backtick.
-This example also illustrates stripping of a single leading and
-trailing space:
-
-```````````````````````````````` example
-`` foo ` bar ``
-.
-<p><code>foo ` bar</code></p>
-````````````````````````````````
-
-
-This example shows the motivation for stripping leading and trailing
-spaces:
-
-```````````````````````````````` example
-` `` `
-.
-<p><code>``</code></p>
-````````````````````````````````
-
-Note that only *one* space is stripped:
-
-```````````````````````````````` example
-` `` `
-.
-<p><code> `` </code></p>
-````````````````````````````````
-
-The stripping only happens if the space is on both
-sides of the string:
-
-```````````````````````````````` example
-` a`
-.
-<p><code> a</code></p>
-````````````````````````````````
-
-Only [spaces], and not [unicode whitespace] in general, are
-stripped in this way:
-
-```````````````````````````````` example
-` b `
-.
-<p><code> b </code></p>
-````````````````````````````````
-
-No stripping occurs if the code span contains only spaces:
-
-```````````````````````````````` example
-` `
-` `
-.
-<p><code> </code>
-<code> </code></p>
-````````````````````````````````
-
-
-[Line endings] are treated like spaces:
-
-```````````````````````````````` example
-``
-foo
-bar
-baz
-``
-.
-<p><code>foo bar baz</code></p>
-````````````````````````````````
-
-```````````````````````````````` example
-``
-foo
-``
-.
-<p><code>foo </code></p>
-````````````````````````````````
-
-
-Interior spaces are not collapsed:
-
-```````````````````````````````` example
-`foo bar
-baz`
-.
-<p><code>foo bar baz</code></p>
-````````````````````````````````
-
-Note that browsers will typically collapse consecutive spaces
-when rendering `<code>` elements, so it is recommended that
-the following CSS be used:
-
- code{white-space: pre-wrap;}
-
-
-Note that backslash escapes do not work in code spans. All backslashes
-are treated literally:
-
-```````````````````````````````` example
-`foo\`bar`
-.
-<p><code>foo\</code>bar`</p>
-````````````````````````````````
-
-
-Backslash escapes are never needed, because one can always choose a
-string of *n* backtick characters as delimiters, where the code does
-not contain any strings of exactly *n* backtick characters.
-
-```````````````````````````````` example
-``foo`bar``
-.
-<p><code>foo`bar</code></p>
-````````````````````````````````
-
-```````````````````````````````` example
-` foo `` bar `
-.
-<p><code>foo `` bar</code></p>
-````````````````````````````````
-
-
-Code span backticks have higher precedence than any other inline
-constructs except HTML tags and autolinks. Thus, for example, this is
-not parsed as emphasized text, since the second `*` is part of a code
-span:
-
-```````````````````````````````` example
-*foo`*`
-.
-<p>*foo<code>*</code></p>
-````````````````````````````````
-
-
-And this is not parsed as a link:
-
-```````````````````````````````` example
-[not a `link](/foo`)
-.
-<p>[not a <code>link](/foo</code>)</p>
-````````````````````````````````
-
-
-Code spans, HTML tags, and autolinks have the same precedence.
-Thus, this is code:
-
-```````````````````````````````` example
-`<a href="`">`
-.
-<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
-````````````````````````````````
-
-
-But this is an HTML tag:
-
-```````````````````````````````` example
-<a href="`">`
-.
-<p><a href="`">`</p>
-````````````````````````````````
-
-
-And this is code:
-
-```````````````````````````````` example
-`<http://foo.bar.`baz>`
-.
-<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
-````````````````````````````````
-
-
-But this is an autolink:
-
-```````````````````````````````` example
-<http://foo.bar.`baz>`
-.
-<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
-````````````````````````````````
-
-
-When a backtick string is not closed by a matching backtick string,
-we just have literal backticks:
-
-```````````````````````````````` example
-```foo``
-.
-<p>```foo``</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`foo
-.
-<p>`foo</p>
-````````````````````````````````
-
-The following case also illustrates the need for opening and
-closing backtick strings to be equal in length:
-
-```````````````````````````````` example
-`foo``bar``
-.
-<p>`foo<code>bar</code></p>
-````````````````````````````````
-
-
-## Emphasis and strong emphasis
-
-John Gruber's original [Markdown syntax
-description](http://daringfireball.net/projects/markdown/syntax#em) says:
-
-> Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
-> emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML
-> `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML `<strong>`
-> tag.
-
-This is enough for most users, but these rules leave much undecided,
-especially when it comes to nested emphasis. The original
-`Markdown.pl` test suite makes it clear that triple `***` and
-`___` delimiters can be used for strong emphasis, and most
-implementations have also allowed the following patterns:
-
-``` markdown
-***strong emph***
-***strong** in emph*
-***emph* in strong**
-**in strong *emph***
-*in emph **strong***
-```
-
-The following patterns are less widely supported, but the intent
-is clear and they are useful (especially in contexts like bibliography
-entries):
-
-``` markdown
-*emph *with emph* in it*
-**strong **with strong** in it**
-```
-
-Many implementations have also restricted intraword emphasis to
-the `*` forms, to avoid unwanted emphasis in words containing
-internal underscores. (It is best practice to put these in code
-spans, but users often do not.)
-
-``` markdown
-internal emphasis: foo*bar*baz
-no emphasis: foo_bar_baz
-```
-
-The rules given below capture all of these patterns, while allowing
-for efficient parsing strategies that do not backtrack.
-
-First, some definitions. A [delimiter run](@) is either
-a sequence of one or more `*` characters that is not preceded or
-followed by a non-backslash-escaped `*` character, or a sequence
-of one or more `_` characters that is not preceded or followed by
-a non-backslash-escaped `_` character.
-
-A [left-flanking delimiter run](@) is
-a [delimiter run] that is (1) not followed by [Unicode whitespace],
-and either (2a) not followed by a [punctuation character], or
-(2b) followed by a [punctuation character] and
-preceded by [Unicode whitespace] or a [punctuation character].
-For purposes of this definition, the beginning and the end of
-the line count as Unicode whitespace.
-
-A [right-flanking delimiter run](@) is
-a [delimiter run] that is (1) not preceded by [Unicode whitespace],
-and either (2a) not preceded by a [punctuation character], or
-(2b) preceded by a [punctuation character] and
-followed by [Unicode whitespace] or a [punctuation character].
-For purposes of this definition, the beginning and the end of
-the line count as Unicode whitespace.
-
-Here are some examples of delimiter runs.
-
- - left-flanking but not right-flanking:
-
- ```
- ***abc
- _abc
- **"abc"
- _"abc"
- ```
-
- - right-flanking but not left-flanking:
-
- ```
- abc***
- abc_
- "abc"**
- "abc"_
- ```
-
- - Both left and right-flanking:
-
- ```
- abc***def
- "abc"_"def"
- ```
-
- - Neither left nor right-flanking:
-
- ```
- abc *** def
- a _ b
- ```
-
-(The idea of distinguishing left-flanking and right-flanking
-delimiter runs based on the character before and the character
-after comes from Roopesh Chander's
-[vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags).
-vfmd uses the terminology "emphasis indicator string" instead of "delimiter
-run," and its rules for distinguishing left- and right-flanking runs
-are a bit more complex than the ones given here.)
-
-The following rules define emphasis and strong emphasis:
-
-1. A single `*` character [can open emphasis](@)
- iff (if and only if) it is part of a [left-flanking delimiter run].
-
-2. A single `_` character [can open emphasis] iff
- it is part of a [left-flanking delimiter run]
- and either (a) not part of a [right-flanking delimiter run]
- or (b) part of a [right-flanking delimiter run]
- preceded by punctuation.
-
-3. A single `*` character [can close emphasis](@)
- iff it is part of a [right-flanking delimiter run].
-
-4. A single `_` character [can close emphasis] iff
- it is part of a [right-flanking delimiter run]
- and either (a) not part of a [left-flanking delimiter run]
- or (b) part of a [left-flanking delimiter run]
- followed by punctuation.
-
-5. A double `**` [can open strong emphasis](@)
- iff it is part of a [left-flanking delimiter run].
-
-6. A double `__` [can open strong emphasis] iff
- it is part of a [left-flanking delimiter run]
- and either (a) not part of a [right-flanking delimiter run]
- or (b) part of a [right-flanking delimiter run]
- preceded by punctuation.
-
-7. A double `**` [can close strong emphasis](@)
- iff it is part of a [right-flanking delimiter run].
-
-8. A double `__` [can close strong emphasis] iff
- it is part of a [right-flanking delimiter run]
- and either (a) not part of a [left-flanking delimiter run]
- or (b) part of a [left-flanking delimiter run]
- followed by punctuation.
-
-9. Emphasis begins with a delimiter that [can open emphasis] and ends
- with a delimiter that [can close emphasis], and that uses the same
- character (`_` or `*`) as the opening delimiter. The
- opening and closing delimiters must belong to separate
- [delimiter runs]. If one of the delimiters can both
- open and close emphasis, then the sum of the lengths of the
- delimiter runs containing the opening and closing delimiters
- must not be a multiple of 3 unless both lengths are
- multiples of 3.
-
-10. Strong emphasis begins with a delimiter that
- [can open strong emphasis] and ends with a delimiter that
- [can close strong emphasis], and that uses the same character
- (`_` or `*`) as the opening delimiter. The
- opening and closing delimiters must belong to separate
- [delimiter runs]. If one of the delimiters can both open
- and close strong emphasis, then the sum of the lengths of
- the delimiter runs containing the opening and closing
- delimiters must not be a multiple of 3 unless both lengths
- are multiples of 3.
-
-11. A literal `*` character cannot occur at the beginning or end of
- `*`-delimited emphasis or `**`-delimited strong emphasis, unless it
- is backslash-escaped.
-
-12. A literal `_` character cannot occur at the beginning or end of
- `_`-delimited emphasis or `__`-delimited strong emphasis, unless it
- is backslash-escaped.
-
-Where rules 1--12 above are compatible with multiple parsings,
-the following principles resolve ambiguity:
-
-13. The number of nestings should be minimized. Thus, for example,
- an interpretation `<strong>...</strong>` is always preferred to
- `<em><em>...</em></em>`.
-
-14. An interpretation `<em><strong>...</strong></em>` is always
- preferred to `<strong><em>...</em></strong>`.
-
-15. When two potential emphasis or strong emphasis spans overlap,
- so that the second begins before the first ends and ends after
- the first ends, the first takes precedence. Thus, for example,
- `*foo _bar* baz_` is parsed as `<em>foo _bar</em> baz_` rather
- than `*foo <em>bar* baz</em>`.
-
-16. When there are two potential emphasis or strong emphasis spans
- with the same closing delimiter, the shorter one (the one that
- opens later) takes precedence. Thus, for example,
- `**foo **bar baz**` is parsed as `**foo <strong>bar baz</strong>`
- rather than `<strong>foo **bar baz</strong>`.
-
-17. Inline code spans, links, images, and HTML tags group more tightly
- than emphasis. So, when there is a choice between an interpretation
- that contains one of these elements and one that does not, the
- former always wins. Thus, for example, `*[foo*](bar)` is
- parsed as `*<a href="bar">foo*</a>` rather than as
- `<em>[foo</em>](bar)`.
-
-These rules can be illustrated through a series of examples.
-
-Rule 1:
-
-```````````````````````````````` example
-*foo bar*
-.
-<p><em>foo bar</em></p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `*` is followed by
-whitespace, and hence not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a * foo bar*
-.
-<p>a * foo bar*</p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `*` is preceded
-by an alphanumeric and followed by punctuation, and hence
-not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a*"foo"*
-.
-<p>a*&quot;foo&quot;*</p>
-````````````````````````````````
-
-
-Unicode nonbreaking spaces count as whitespace, too:
-
-```````````````````````````````` example
-* a *
-.
-<p>* a *</p>
-````````````````````````````````
-
-
-Intraword emphasis with `*` is permitted:
-
-```````````````````````````````` example
-foo*bar*
-.
-<p>foo<em>bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5*6*78
-.
-<p>5<em>6</em>78</p>
-````````````````````````````````
-
-
-Rule 2:
-
-```````````````````````````````` example
-_foo bar_
-.
-<p><em>foo bar</em></p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `_` is followed by
-whitespace:
-
-```````````````````````````````` example
-_ foo bar_
-.
-<p>_ foo bar_</p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `_` is preceded
-by an alphanumeric and followed by punctuation:
-
-```````````````````````````````` example
-a_"foo"_
-.
-<p>a_&quot;foo&quot;_</p>
-````````````````````````````````
-
-
-Emphasis with `_` is not allowed inside words:
-
-```````````````````````````````` example
-foo_bar_
-.
-<p>foo_bar_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5_6_78
-.
-<p>5_6_78</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-приÑтанÑм_ÑтремÑÑ‚ÑÑ_
-.
-<p>приÑтанÑм_ÑтремÑÑ‚ÑÑ_</p>
-````````````````````````````````
-
-
-Here `_` does not generate emphasis, because the first delimiter run
-is right-flanking and the second left-flanking:
-
-```````````````````````````````` example
-aa_"bb"_cc
-.
-<p>aa_&quot;bb&quot;_cc</p>
-````````````````````````````````
-
-
-This is emphasis, even though the opening delimiter is
-both left- and right-flanking, because it is preceded by
-punctuation:
-
-```````````````````````````````` example
-foo-_(bar)_
-.
-<p>foo-<em>(bar)</em></p>
-````````````````````````````````
-
-
-Rule 3:
-
-This is not emphasis, because the closing delimiter does
-not match the opening delimiter:
-
-```````````````````````````````` example
-_foo*
-.
-<p>_foo*</p>
-````````````````````````````````
-
-
-This is not emphasis, because the closing `*` is preceded by
-whitespace:
-
-```````````````````````````````` example
-*foo bar *
-.
-<p>*foo bar *</p>
-````````````````````````````````
-
-
-A newline also counts as whitespace:
-
-```````````````````````````````` example
-*foo bar
-*
-.
-<p>*foo bar
-*</p>
-````````````````````````````````
-
-
-This is not emphasis, because the second `*` is
-preceded by punctuation and followed by an alphanumeric
-(hence it is not part of a [right-flanking delimiter run]:
-
-```````````````````````````````` example
-*(*foo)
-.
-<p>*(*foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with this example:
-
-```````````````````````````````` example
-*(*foo*)*
-.
-<p><em>(<em>foo</em>)</em></p>
-````````````````````````````````
-
-
-Intraword emphasis with `*` is allowed:
-
-```````````````````````````````` example
-*foo*bar
-.
-<p><em>foo</em>bar</p>
-````````````````````````````````
-
-
-
-Rule 4:
-
-This is not emphasis, because the closing `_` is preceded by
-whitespace:
-
-```````````````````````````````` example
-_foo bar _
-.
-<p>_foo bar _</p>
-````````````````````````````````
-
-
-This is not emphasis, because the second `_` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-_(_foo)
-.
-<p>_(_foo)</p>
-````````````````````````````````
-
-
-This is emphasis within emphasis:
-
-```````````````````````````````` example
-_(_foo_)_
-.
-<p><em>(<em>foo</em>)</em></p>
-````````````````````````````````
-
-
-Intraword emphasis is disallowed for `_`:
-
-```````````````````````````````` example
-_foo_bar
-.
-<p>_foo_bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_приÑтанÑм_ÑтремÑÑ‚ÑÑ
-.
-<p>_приÑтанÑм_ÑтремÑÑ‚ÑÑ</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo_bar_baz_
-.
-<p><em>foo_bar_baz</em></p>
-````````````````````````````````
-
-
-This is emphasis, even though the closing delimiter is
-both left- and right-flanking, because it is followed by
-punctuation:
-
-```````````````````````````````` example
-_(bar)_.
-.
-<p><em>(bar)</em>.</p>
-````````````````````````````````
-
-
-Rule 5:
-
-```````````````````````````````` example
-**foo bar**
-.
-<p><strong>foo bar</strong></p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening delimiter is
-followed by whitespace:
-
-```````````````````````````````` example
-** foo bar**
-.
-<p>** foo bar**</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening `**` is preceded
-by an alphanumeric and followed by punctuation, and hence
-not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a**"foo"**
-.
-<p>a**&quot;foo&quot;**</p>
-````````````````````````````````
-
-
-Intraword strong emphasis with `**` is permitted:
-
-```````````````````````````````` example
-foo**bar**
-.
-<p>foo<strong>bar</strong></p>
-````````````````````````````````
-
-
-Rule 6:
-
-```````````````````````````````` example
-__foo bar__
-.
-<p><strong>foo bar</strong></p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening delimiter is
-followed by whitespace:
-
-```````````````````````````````` example
-__ foo bar__
-.
-<p>__ foo bar__</p>
-````````````````````````````````
-
-
-A newline counts as whitespace:
-```````````````````````````````` example
-__
-foo bar__
-.
-<p>__
-foo bar__</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening `__` is preceded
-by an alphanumeric and followed by punctuation:
-
-```````````````````````````````` example
-a__"foo"__
-.
-<p>a__&quot;foo&quot;__</p>
-````````````````````````````````
-
-
-Intraword strong emphasis is forbidden with `__`:
-
-```````````````````````````````` example
-foo__bar__
-.
-<p>foo__bar__</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5__6__78
-.
-<p>5__6__78</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-приÑтанÑм__ÑтремÑÑ‚ÑÑ__
-.
-<p>приÑтанÑм__ÑтремÑÑ‚ÑÑ__</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo, __bar__, baz__
-.
-<p><strong>foo, <strong>bar</strong>, baz</strong></p>
-````````````````````````````````
-
-
-This is strong emphasis, even though the opening delimiter is
-both left- and right-flanking, because it is preceded by
-punctuation:
-
-```````````````````````````````` example
-foo-__(bar)__
-.
-<p>foo-<strong>(bar)</strong></p>
-````````````````````````````````
-
-
-
-Rule 7:
-
-This is not strong emphasis, because the closing delimiter is preceded
-by whitespace:
-
-```````````````````````````````` example
-**foo bar **
-.
-<p>**foo bar **</p>
-````````````````````````````````
-
-
-(Nor can it be interpreted as an emphasized `*foo bar *`, because of
-Rule 11.)
-
-This is not strong emphasis, because the second `**` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-**(**foo)
-.
-<p>**(**foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with these examples:
-
-```````````````````````````````` example
-*(**foo**)*
-.
-<p><em>(<strong>foo</strong>)</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
-*Asclepias physocarpa*)**
-.
-<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
-<em>Asclepias physocarpa</em>)</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo "*bar*" foo**
-.
-<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
-````````````````````````````````
-
-
-Intraword emphasis:
-
-```````````````````````````````` example
-**foo**bar
-.
-<p><strong>foo</strong>bar</p>
-````````````````````````````````
-
-
-Rule 8:
-
-This is not strong emphasis, because the closing delimiter is
-preceded by whitespace:
-
-```````````````````````````````` example
-__foo bar __
-.
-<p>__foo bar __</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the second `__` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-__(__foo)
-.
-<p>__(__foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with this example:
-
-```````````````````````````````` example
-_(__foo__)_
-.
-<p><em>(<strong>foo</strong>)</em></p>
-````````````````````````````````
-
-
-Intraword strong emphasis is forbidden with `__`:
-
-```````````````````````````````` example
-__foo__bar
-.
-<p>__foo__bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__приÑтанÑм__ÑтремÑÑ‚ÑÑ
-.
-<p>__приÑтанÑм__ÑтремÑÑ‚ÑÑ</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo__bar__baz__
-.
-<p><strong>foo__bar__baz</strong></p>
-````````````````````````````````
-
-
-This is strong emphasis, even though the closing delimiter is
-both left- and right-flanking, because it is followed by
-punctuation:
-
-```````````````````````````````` example
-__(bar)__.
-.
-<p><strong>(bar)</strong>.</p>
-````````````````````````````````
-
-
-Rule 9:
-
-Any nonempty sequence of inline elements can be the contents of an
-emphasized span.
-
-```````````````````````````````` example
-*foo [bar](/url)*
-.
-<p><em>foo <a href="/url">bar</a></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo
-bar*
-.
-<p><em>foo
-bar</em></p>
-````````````````````````````````
-
-
-In particular, emphasis and strong emphasis can be nested
-inside emphasis:
-
-```````````````````````````````` example
-_foo __bar__ baz_
-.
-<p><em>foo <strong>bar</strong> baz</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo _bar_ baz_
-.
-<p><em>foo <em>bar</em> baz</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo_ bar_
-.
-<p><em><em>foo</em> bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo *bar**
-.
-<p><em>foo <em>bar</em></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo **bar** baz*
-.
-<p><em>foo <strong>bar</strong> baz</em></p>
-````````````````````````````````
-
-```````````````````````````````` example
-*foo**bar**baz*
-.
-<p><em>foo<strong>bar</strong>baz</em></p>
-````````````````````````````````
-
-Note that in the preceding case, the interpretation
-
-``` markdown
-<p><em>foo</em><em>bar<em></em>baz</em></p>
-```
-
-
-is precluded by the condition that a delimiter that
-can both open and close (like the `*` after `foo`)
-cannot form emphasis if the sum of the lengths of
-the delimiter runs containing the opening and
-closing delimiters is a multiple of 3 unless
-both lengths are multiples of 3.
-
-
-For the same reason, we don't get two consecutive
-emphasis sections in this example:
-
-```````````````````````````````` example
-*foo**bar*
-.
-<p><em>foo**bar</em></p>
-````````````````````````````````
-
-
-The same condition ensures that the following
-cases are all strong emphasis nested inside
-emphasis, even when the interior spaces are
-omitted:
-
-
-```````````````````````````````` example
-***foo** bar*
-.
-<p><em><strong>foo</strong> bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo **bar***
-.
-<p><em>foo <strong>bar</strong></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo**bar***
-.
-<p><em>foo<strong>bar</strong></em></p>
-````````````````````````````````
-
-
-When the lengths of the interior closing and opening
-delimiter runs are *both* multiples of 3, though,
-they can match to create emphasis:
-
-```````````````````````````````` example
-foo***bar***baz
-.
-<p>foo<em><strong>bar</strong></em>baz</p>
-````````````````````````````````
-
-```````````````````````````````` example
-foo******bar*********baz
-.
-<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
-````````````````````````````````
-
-
-Indefinite levels of nesting are possible:
-
-```````````````````````````````` example
-*foo **bar *baz* bim** bop*
-.
-<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo [*bar*](/url)*
-.
-<p><em>foo <a href="/url"><em>bar</em></a></em></p>
-````````````````````````````````
-
-
-There can be no empty emphasis or strong emphasis:
-
-```````````````````````````````` example
-** is not an empty emphasis
-.
-<p>** is not an empty emphasis</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**** is not an empty strong emphasis
-.
-<p>**** is not an empty strong emphasis</p>
-````````````````````````````````
-
-
-
-Rule 10:
-
-Any nonempty sequence of inline elements can be the contents of an
-strongly emphasized span.
-
-```````````````````````````````` example
-**foo [bar](/url)**
-.
-<p><strong>foo <a href="/url">bar</a></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo
-bar**
-.
-<p><strong>foo
-bar</strong></p>
-````````````````````````````````
-
-
-In particular, emphasis and strong emphasis can be nested
-inside strong emphasis:
-
-```````````````````````````````` example
-__foo _bar_ baz__
-.
-<p><strong>foo <em>bar</em> baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo __bar__ baz__
-.
-<p><strong>foo <strong>bar</strong> baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo__ bar__
-.
-<p><strong><strong>foo</strong> bar</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo **bar****
-.
-<p><strong>foo <strong>bar</strong></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo *bar* baz**
-.
-<p><strong>foo <em>bar</em> baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo*bar*baz**
-.
-<p><strong>foo<em>bar</em>baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-***foo* bar**
-.
-<p><strong><em>foo</em> bar</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo *bar***
-.
-<p><strong>foo <em>bar</em></strong></p>
-````````````````````````````````
-
-
-Indefinite levels of nesting are possible:
-
-```````````````````````````````` example
-**foo *bar **baz**
-bim* bop**
-.
-<p><strong>foo <em>bar <strong>baz</strong>
-bim</em> bop</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo [*bar*](/url)**
-.
-<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
-````````````````````````````````
-
-
-There can be no empty emphasis or strong emphasis:
-
-```````````````````````````````` example
-__ is not an empty emphasis
-.
-<p>__ is not an empty emphasis</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____ is not an empty strong emphasis
-.
-<p>____ is not an empty strong emphasis</p>
-````````````````````````````````
-
-
-
-Rule 11:
-
-```````````````````````````````` example
-foo ***
-.
-<p>foo ***</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *\**
-.
-<p>foo <em>*</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *_*
-.
-<p>foo <em>_</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *****
-.
-<p>foo *****</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo **\***
-.
-<p>foo <strong>*</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo **_**
-.
-<p>foo <strong>_</strong></p>
-````````````````````````````````
-
-
-Note that when delimiters do not match evenly, Rule 11 determines
-that the excess literal `*` characters will appear outside of the
-emphasis, rather than inside it:
-
-```````````````````````````````` example
-**foo*
-.
-<p>*<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo**
-.
-<p><em>foo</em>*</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-***foo**
-.
-<p>*<strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-****foo*
-.
-<p>***<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo***
-.
-<p><strong>foo</strong>*</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo****
-.
-<p><em>foo</em>***</p>
-````````````````````````````````
-
-
-
-Rule 12:
-
-```````````````````````````````` example
-foo ___
-.
-<p>foo ___</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _\__
-.
-<p>foo <em>_</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _*_
-.
-<p>foo <em>*</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _____
-.
-<p>foo _____</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo __\___
-.
-<p>foo <strong>_</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo __*__
-.
-<p>foo <strong>*</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo_
-.
-<p>_<em>foo</em></p>
-````````````````````````````````
-
-
-Note that when delimiters do not match evenly, Rule 12 determines
-that the excess literal `_` characters will appear outside of the
-emphasis, rather than inside it:
-
-```````````````````````````````` example
-_foo__
-.
-<p><em>foo</em>_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-___foo__
-.
-<p>_<strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo_
-.
-<p>___<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo___
-.
-<p><strong>foo</strong>_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo____
-.
-<p><em>foo</em>___</p>
-````````````````````````````````
-
-
-Rule 13 implies that if you want emphasis nested directly inside
-emphasis, you must use different delimiters:
-
-```````````````````````````````` example
-**foo**
-.
-<p><strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*_foo_*
-.
-<p><em><em>foo</em></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo__
-.
-<p><strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_*foo*_
-.
-<p><em><em>foo</em></em></p>
-````````````````````````````````
-
-
-However, strong emphasis within strong emphasis is possible without
-switching delimiters:
-
-```````````````````````````````` example
-****foo****
-.
-<p><strong><strong>foo</strong></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo____
-.
-<p><strong><strong>foo</strong></strong></p>
-````````````````````````````````
-
-
-
-Rule 13 can be applied to arbitrarily long sequences of
-delimiters:
-
-```````````````````````````````` example
-******foo******
-.
-<p><strong><strong><strong>foo</strong></strong></strong></p>
-````````````````````````````````
-
-
-Rule 14:
-
-```````````````````````````````` example
-***foo***
-.
-<p><em><strong>foo</strong></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_____foo_____
-.
-<p><em><strong><strong>foo</strong></strong></em></p>
-````````````````````````````````
-
-
-Rule 15:
-
-```````````````````````````````` example
-*foo _bar* baz_
-.
-<p><em>foo _bar</em> baz_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo __bar *baz bim__ bam*
-.
-<p><em>foo <strong>bar *baz bim</strong> bam</em></p>
-````````````````````````````````
-
-
-Rule 16:
-
-```````````````````````````````` example
-**foo **bar baz**
-.
-<p>**foo <strong>bar baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo *bar baz*
-.
-<p>*foo <em>bar baz</em></p>
-````````````````````````````````
-
-
-Rule 17:
-
-```````````````````````````````` example
-*[bar*](/url)
-.
-<p>*<a href="/url">bar*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo [bar_](/url)
-.
-<p>_foo <a href="/url">bar_</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*<img src="foo" title="*"/>
-.
-<p>*<img src="foo" title="*"/></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**<a href="**">
-.
-<p>**<a href="**"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__<a href="__">
-.
-<p>__<a href="__"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*a `*`*
-.
-<p><em>a <code>*</code></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_a `_`_
-.
-<p><em>a <code>_</code></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**a<http://foo.bar/?q=**>
-.
-<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__a<http://foo.bar/?q=__>
-.
-<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
-````````````````````````````````
-
-
-<div class="extension">
-
-## Strikethrough (extension)
-
-GFM enables the `strikethrough` extension, where an additional emphasis type is
-available.
-
-Strikethrough text is any text wrapped in two tildes (`~`).
-
-```````````````````````````````` example strikethrough
-~~Hi~~ Hello, world!
-.
-<p><del>Hi</del> Hello, world!</p>
-````````````````````````````````
-
-As with regular emphasis delimiters, a new paragraph will cause strikethrough
-parsing to cease:
-
-```````````````````````````````` example strikethrough
-This ~~has a
-
-new paragraph~~.
-.
-<p>This ~~has a</p>
-<p>new paragraph~~.</p>
-````````````````````````````````
-
-</div>
-
-## Links
-
-A link contains [link text] (the visible text), a [link destination]
-(the URI that is the link destination), and optionally a [link title].
-There are two basic kinds of links in Markdown. In [inline links] the
-destination and title are given immediately after the link text. In
-[reference links] the destination and title are defined elsewhere in
-the document.
-
-A [link text](@) consists of a sequence of zero or more
-inline elements enclosed by square brackets (`[` and `]`). The
-following rules apply:
-
-- Links may not contain other links, at any level of nesting. If
- multiple otherwise valid link definitions appear nested inside each
- other, the inner-most definition is used.
-
-- Brackets are allowed in the [link text] only if (a) they
- are backslash-escaped or (b) they appear as a matched pair of brackets,
- with an open bracket `[`, a sequence of zero or more inlines, and
- a close bracket `]`.
-
-- Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly
- than the brackets in link text. Thus, for example,
- `` [foo`]` `` could not be a link text, since the second `]`
- is part of a code span.
-
-- The brackets in link text bind more tightly than markers for
- [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link.
-
-A [link destination](@) consists of either
-
-- a sequence of zero or more characters between an opening `<` and a
- closing `>` that contains no line breaks or unescaped
- `<` or `>` characters, or
-
-- a nonempty sequence of characters that does not start with
- `<`, does not include ASCII space or control characters, and
- includes parentheses only if (a) they are backslash-escaped or
- (b) they are part of a balanced pair of unescaped parentheses.
- (Implementations may impose limits on parentheses nesting to
- avoid performance issues, but at least three levels of nesting
- should be supported.)
-
-A [link title](@) consists of either
-
-- a sequence of zero or more characters between straight double-quote
- characters (`"`), including a `"` character only if it is
- backslash-escaped, or
-
-- a sequence of zero or more characters between straight single-quote
- characters (`'`), including a `'` character only if it is
- backslash-escaped, or
-
-- a sequence of zero or more characters between matching parentheses
- (`(...)`), including a `(` or `)` character only if it is
- backslash-escaped.
-
-Although [link titles] may span multiple lines, they may not contain
-a [blank line].
-
-An [inline link](@) consists of a [link text] followed immediately
-by a left parenthesis `(`, optional [whitespace], an optional
-[link destination], an optional [link title] separated from the link
-destination by [whitespace], optional [whitespace], and a right
-parenthesis `)`. The link's text consists of the inlines contained
-in the [link text] (excluding the enclosing square brackets).
-The link's URI consists of the link destination, excluding enclosing
-`<...>` if present, with backslash-escapes in effect as described
-above. The link's title consists of the link title, excluding its
-enclosing delimiters, with backslash-escapes in effect as described
-above.
-
-Here is a simple inline link:
-
-```````````````````````````````` example
-[link](/uri "title")
-.
-<p><a href="/uri" title="title">link</a></p>
-````````````````````````````````
-
-
-The title may be omitted:
-
-```````````````````````````````` example
-[link](/uri)
-.
-<p><a href="/uri">link</a></p>
-````````````````````````````````
-
-
-Both the title and the destination may be omitted:
-
-```````````````````````````````` example
-[link]()
-.
-<p><a href="">link</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](<>)
-.
-<p><a href="">link</a></p>
-````````````````````````````````
-
-The destination can only contain spaces if it is
-enclosed in pointy brackets:
-
-```````````````````````````````` example
-[link](/my uri)
-.
-<p>[link](/my uri)</p>
-````````````````````````````````
-
-```````````````````````````````` example
-[link](</my uri>)
-.
-<p><a href="/my%20uri">link</a></p>
-````````````````````````````````
-
-The destination cannot contain line breaks,
-even if enclosed in pointy brackets:
-
-```````````````````````````````` example
-[link](foo
-bar)
-.
-<p>[link](foo
-bar)</p>
-````````````````````````````````
-
-```````````````````````````````` example
-[link](<foo
-bar>)
-.
-<p>[link](<foo
-bar>)</p>
-````````````````````````````````
-
-The destination can contain `)` if it is enclosed
-in pointy brackets:
-
-```````````````````````````````` example
-[a](<b)c>)
-.
-<p><a href="b)c">a</a></p>
-````````````````````````````````
-
-Pointy brackets that enclose links must be unescaped:
-
-```````````````````````````````` example
-[link](<foo\>)
-.
-<p>[link](&lt;foo&gt;)</p>
-````````````````````````````````
-
-These are not links, because the opening pointy bracket
-is not matched properly:
-
-```````````````````````````````` example
-[a](<b)c
-[a](<b)c>
-[a](<b>c)
-.
-<p>[a](&lt;b)c
-[a](&lt;b)c&gt;
-[a](<b>c)</p>
-````````````````````````````````
-
-Parentheses inside the link destination may be escaped:
-
-```````````````````````````````` example
-[link](\(foo\))
-.
-<p><a href="(foo)">link</a></p>
-````````````````````````````````
-
-Any number of parentheses are allowed without escaping, as long as they are
-balanced:
-
-```````````````````````````````` example
-[link](foo(and(bar)))
-.
-<p><a href="foo(and(bar))">link</a></p>
-````````````````````````````````
-
-However, if you have unbalanced parentheses, you need to escape or use the
-`<...>` form:
-
-```````````````````````````````` example
-[link](foo\(and\(bar\))
-.
-<p><a href="foo(and(bar)">link</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](<foo(and(bar)>)
-.
-<p><a href="foo(and(bar)">link</a></p>
-````````````````````````````````
-
-
-Parentheses and other symbols can also be escaped, as usual
-in Markdown:
-
-```````````````````````````````` example
-[link](foo\)\:)
-.
-<p><a href="foo):">link</a></p>
-````````````````````````````````
-
-
-A link can contain fragment identifiers and queries:
-
-```````````````````````````````` example
-[link](#fragment)
-
-[link](http://example.com#fragment)
-
-[link](http://example.com?foo=3#frag)
-.
-<p><a href="#fragment">link</a></p>
-<p><a href="http://example.com#fragment">link</a></p>
-<p><a href="http://example.com?foo=3#frag">link</a></p>
-````````````````````````````````
-
-
-Note that a backslash before a non-escapable character is
-just a backslash:
-
-```````````````````````````````` example
-[link](foo\bar)
-.
-<p><a href="foo%5Cbar">link</a></p>
-````````````````````````````````
-
-
-URL-escaping should be left alone inside the destination, as all
-URL-escaped characters are also valid URL characters. Entity and
-numerical character references in the destination will be parsed
-into the corresponding Unicode code points, as usual. These may
-be optionally URL-escaped when written as HTML, but this spec
-does not enforce any particular policy for rendering URLs in
-HTML or other formats. Renderers may make different decisions
-about how to escape or normalize URLs in the output.
-
-```````````````````````````````` example
-[link](foo%20b&auml;)
-.
-<p><a href="foo%20b%C3%A4">link</a></p>
-````````````````````````````````
-
-
-Note that, because titles can often be parsed as destinations,
-if you try to omit the destination and keep the title, you'll
-get unexpected results:
-
-```````````````````````````````` example
-[link]("title")
-.
-<p><a href="%22title%22">link</a></p>
-````````````````````````````````
-
-
-Titles may be in single quotes, double quotes, or parentheses:
-
-```````````````````````````````` example
-[link](/url "title")
-[link](/url 'title')
-[link](/url (title))
-.
-<p><a href="/url" title="title">link</a>
-<a href="/url" title="title">link</a>
-<a href="/url" title="title">link</a></p>
-````````````````````````````````
-
-
-Backslash escapes and entity and numeric character references
-may be used in titles:
-
-```````````````````````````````` example
-[link](/url "title \"&quot;")
-.
-<p><a href="/url" title="title &quot;&quot;">link</a></p>
-````````````````````````````````
-
-
-Titles must be separated from the link using a [whitespace].
-Other [Unicode whitespace] like non-breaking space doesn't work.
-
-```````````````````````````````` example
-[link](/url "title")
-.
-<p><a href="/url%C2%A0%22title%22">link</a></p>
-````````````````````````````````
-
-
-Nested balanced quotes are not allowed without escaping:
-
-```````````````````````````````` example
-[link](/url "title "and" title")
-.
-<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
-````````````````````````````````
-
-
-But it is easy to work around this by using a different quote type:
-
-```````````````````````````````` example
-[link](/url 'title "and" title')
-.
-<p><a href="/url" title="title &quot;and&quot; title">link</a></p>
-````````````````````````````````
-
-
-(Note: `Markdown.pl` did allow double quotes inside a double-quoted
-title, and its test suite included a test demonstrating this.
-But it is hard to see a good rationale for the extra complexity this
-brings, since there are already many ways---backslash escaping,
-entity and numeric character references, or using a different
-quote type for the enclosing title---to write titles containing
-double quotes. `Markdown.pl`'s handling of titles has a number
-of other strange features. For example, it allows single-quoted
-titles in inline links, but not reference links. And, in
-reference links but not inline links, it allows a title to begin
-with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows
-titles with no closing quotation mark, though 1.0.2b8 does not.
-It seems preferable to adopt a simple, rational rule that works
-the same way in inline links and link reference definitions.)
-
-[Whitespace] is allowed around the destination and title:
-
-```````````````````````````````` example
-[link]( /uri
- "title" )
-.
-<p><a href="/uri" title="title">link</a></p>
-````````````````````````````````
-
-
-But it is not allowed between the link text and the
-following parenthesis:
-
-```````````````````````````````` example
-[link] (/uri)
-.
-<p>[link] (/uri)</p>
-````````````````````````````````
-
-
-The link text may contain balanced brackets, but not unbalanced ones,
-unless they are escaped:
-
-```````````````````````````````` example
-[link [foo [bar]]](/uri)
-.
-<p><a href="/uri">link [foo [bar]]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link] bar](/uri)
-.
-<p>[link] bar](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link [bar](/uri)
-.
-<p>[link <a href="/uri">bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link \[bar](/uri)
-.
-<p><a href="/uri">link [bar</a></p>
-````````````````````````````````
-
-
-The link text may contain inline content:
-
-```````````````````````````````` example
-[link *foo **bar** `#`*](/uri)
-.
-<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[![moon](moon.jpg)](/uri)
-.
-<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
-````````````````````````````````
-
-
-However, links may not contain other links, at any level of nesting.
-
-```````````````````````````````` example
-[foo [bar](/uri)](/uri)
-.
-<p>[foo <a href="/uri">bar</a>](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *[bar [baz](/uri)](/uri)*](/uri)
-.
-<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![[[foo](uri1)](uri2)](uri3)
-.
-<p><img src="uri3" alt="[foo](uri2)" /></p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of link text grouping over
-emphasis grouping:
-
-```````````````````````````````` example
-*[foo*](/uri)
-.
-<p>*<a href="/uri">foo*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar](baz*)
-.
-<p><a href="baz*">foo *bar</a></p>
-````````````````````````````````
-
-
-Note that brackets that *aren't* part of links do not take
-precedence:
-
-```````````````````````````````` example
-*foo [bar* baz]
-.
-<p><em>foo [bar</em> baz]</p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of HTML tags, code spans,
-and autolinks over link grouping:
-
-```````````````````````````````` example
-[foo <bar attr="](baz)">
-.
-<p>[foo <bar attr="](baz)"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo`](/uri)`
-.
-<p>[foo<code>](/uri)</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo<http://example.com/?search=](uri)>
-.
-<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
-````````````````````````````````
-
-
-There are three kinds of [reference link](@)s:
-[full](#full-reference-link), [collapsed](#collapsed-reference-link),
-and [shortcut](#shortcut-reference-link).
-
-A [full reference link](@)
-consists of a [link text] immediately followed by a [link label]
-that [matches] a [link reference definition] elsewhere in the document.
-
-A [link label](@) begins with a left bracket (`[`) and ends
-with the first right bracket (`]`) that is not backslash-escaped.
-Between these brackets there must be at least one [non-whitespace character].
-Unescaped square bracket characters are not allowed inside the
-opening and closing square brackets of [link labels]. A link
-label can have at most 999 characters inside the square
-brackets.
-
-One label [matches](@)
-another just in case their normalized forms are equal. To normalize a
-label, strip off the opening and closing brackets,
-perform the *Unicode case fold*, strip leading and trailing
-[whitespace] and collapse consecutive internal
-[whitespace] to a single space. If there are multiple
-matching reference link definitions, the one that comes first in the
-document is used. (It is desirable in such cases to emit a warning.)
-
-The contents of the first link label are parsed as inlines, which are
-used as the link's text. The link's URI and title are provided by the
-matching [link reference definition].
-
-Here is a simple example:
-
-```````````````````````````````` example
-[foo][bar]
-
-[bar]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-The rules for the [link text] are the same as with
-[inline links]. Thus:
-
-The link text may contain balanced brackets, but not unbalanced ones,
-unless they are escaped:
-
-```````````````````````````````` example
-[link [foo [bar]]][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link [foo [bar]]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link \[bar][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link [bar</a></p>
-````````````````````````````````
-
-
-The link text may contain inline content:
-
-```````````````````````````````` example
-[link *foo **bar** `#`*][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[![moon](moon.jpg)][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
-````````````````````````````````
-
-
-However, links may not contain other links, at any level of nesting.
-
-```````````````````````````````` example
-[foo [bar](/uri)][ref]
-
-[ref]: /uri
-.
-<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar [baz][ref]*][ref]
-
-[ref]: /uri
-.
-<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
-````````````````````````````````
-
-
-(In the examples above, we have two [shortcut reference links]
-instead of one [full reference link].)
-
-The following cases illustrate the precedence of link text grouping over
-emphasis grouping:
-
-```````````````````````````````` example
-*[foo*][ref]
-
-[ref]: /uri
-.
-<p>*<a href="/uri">foo*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">foo *bar</a></p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of HTML tags, code spans,
-and autolinks over link grouping:
-
-```````````````````````````````` example
-[foo <bar attr="][ref]">
-
-[ref]: /uri
-.
-<p>[foo <bar attr="][ref]"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo`][ref]`
-
-[ref]: /uri
-.
-<p>[foo<code>][ref]</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo<http://example.com/?search=][ref]>
-
-[ref]: /uri
-.
-<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
-````````````````````````````````
-
-
-Matching is case-insensitive:
-
-```````````````````````````````` example
-[foo][BaR]
-
-[bar]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-Unicode case fold is used:
-
-```````````````````````````````` example
-[Толпой][Толпой] is a Russian word.
-
-[ТОЛПОЙ]: /url
-.
-<p><a href="/url">Толпой</a> is a Russian word.</p>
-````````````````````````````````
-
-
-Consecutive internal [whitespace] is treated as one space for
-purposes of determining matching:
-
-```````````````````````````````` example
-[Foo
- bar]: /url
-
-[Baz][Foo bar]
-.
-<p><a href="/url">Baz</a></p>
-````````````````````````````````
-
-
-No [whitespace] is allowed between the [link text] and the
-[link label]:
-
-```````````````````````````````` example
-[foo] [bar]
-
-[bar]: /url "title"
-.
-<p>[foo] <a href="/url" title="title">bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-[bar]
-
-[bar]: /url "title"
-.
-<p>[foo]
-<a href="/url" title="title">bar</a></p>
-````````````````````````````````
-
-
-This is a departure from John Gruber's original Markdown syntax
-description, which explicitly allows whitespace between the link
-text and the link label. It brings reference links in line with
-[inline links], which (according to both original Markdown and
-this spec) cannot have whitespace after the link text. More
-importantly, it prevents inadvertent capture of consecutive
-[shortcut reference links]. If whitespace is allowed between the
-link text and the link label, then in the following we will have
-a single reference link, not two shortcut reference links, as
-intended:
-
-``` markdown
-[foo]
-[bar]
-
-[foo]: /url1
-[bar]: /url2
-```
-
-(Note that [shortcut reference links] were introduced by Gruber
-himself in a beta version of `Markdown.pl`, but never included
-in the official syntax description. Without shortcut reference
-links, it is harmless to allow space between the link text and
-link label; but once shortcut references are introduced, it is
-too dangerous to allow this, as it frequently leads to
-unintended results.)
-
-When there are multiple matching [link reference definitions],
-the first is used:
-
-```````````````````````````````` example
-[foo]: /url1
-
-[foo]: /url2
-
-[bar][foo]
-.
-<p><a href="/url1">bar</a></p>
-````````````````````````````````
-
-
-Note that matching is performed on normalized strings, not parsed
-inline content. So the following does not match, even though the
-labels define equivalent inline content:
-
-```````````````````````````````` example
-[bar][foo\!]
-
-[foo!]: /url
-.
-<p>[bar][foo!]</p>
-````````````````````````````````
-
-
-[Link labels] cannot contain brackets, unless they are
-backslash-escaped:
-
-```````````````````````````````` example
-[foo][ref[]
-
-[ref[]: /uri
-.
-<p>[foo][ref[]</p>
-<p>[ref[]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo][ref[bar]]
-
-[ref[bar]]: /uri
-.
-<p>[foo][ref[bar]]</p>
-<p>[ref[bar]]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[[foo]]]
-
-[[[foo]]]: /url
-.
-<p>[[[foo]]]</p>
-<p>[[[foo]]]: /url</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo][ref\[]
-
-[ref\[]: /uri
-.
-<p><a href="/uri">foo</a></p>
-````````````````````````````````
-
-
-Note that in this example `]` is not backslash-escaped:
-
-```````````````````````````````` example
-[bar\\]: /uri
-
-[bar\\]
-.
-<p><a href="/uri">bar\</a></p>
-````````````````````````````````
-
-
-A [link label] must contain at least one [non-whitespace character]:
-
-```````````````````````````````` example
-[]
-
-[]: /uri
-.
-<p>[]</p>
-<p>[]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[
- ]
-
-[
- ]: /uri
-.
-<p>[
-]</p>
-<p>[
-]: /uri</p>
-````````````````````````````````
-
-
-A [collapsed reference link](@)
-consists of a [link label] that [matches] a
-[link reference definition] elsewhere in the
-document, followed by the string `[]`.
-The contents of the first link label are parsed as inlines,
-which are used as the link's text. The link's URI and title are
-provided by the matching reference link definition. Thus,
-`[foo][]` is equivalent to `[foo][foo]`.
-
-```````````````````````````````` example
-[foo][]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[*foo* bar][]
-
-[*foo* bar]: /url "title"
-.
-<p><a href="/url" title="title"><em>foo</em> bar</a></p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-[Foo][]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">Foo</a></p>
-````````````````````````````````
-
-
-
-As with full reference links, [whitespace] is not
-allowed between the two sets of brackets:
-
-```````````````````````````````` example
-[foo]
-[]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a>
-[]</p>
-````````````````````````````````
-
-
-A [shortcut reference link](@)
-consists of a [link label] that [matches] a
-[link reference definition] elsewhere in the
-document and is not followed by `[]` or a link label.
-The contents of the first link label are parsed as inlines,
-which are used as the link's text. The link's URI and title
-are provided by the matching link reference definition.
-Thus, `[foo]` is equivalent to `[foo][]`.
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[*foo* bar]
-
-[*foo* bar]: /url "title"
-.
-<p><a href="/url" title="title"><em>foo</em> bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[*foo* bar]]
-
-[*foo* bar]: /url "title"
-.
-<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[bar [foo]
-
-[foo]: /url
-.
-<p>[[bar <a href="/url">foo</a></p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-[Foo]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">Foo</a></p>
-````````````````````````````````
-
-
-A space after the link text should be preserved:
-
-```````````````````````````````` example
-[foo] bar
-
-[foo]: /url
-.
-<p><a href="/url">foo</a> bar</p>
-````````````````````````````````
-
-
-If you just want bracketed text, you can backslash-escape the
-opening bracket to avoid links:
-
-```````````````````````````````` example
-\[foo]
-
-[foo]: /url "title"
-.
-<p>[foo]</p>
-````````````````````````````````
-
-
-Note that this is a link, because a link label ends with the first
-following closing bracket:
-
-```````````````````````````````` example
-[foo*]: /url
-
-*[foo*]
-.
-<p>*<a href="/url">foo*</a></p>
-````````````````````````````````
-
-
-Full and compact references take precedence over shortcut
-references:
-
-```````````````````````````````` example
-[foo][bar]
-
-[foo]: /url1
-[bar]: /url2
-.
-<p><a href="/url2">foo</a></p>
-````````````````````````````````
-
-```````````````````````````````` example
-[foo][]
-
-[foo]: /url1
-.
-<p><a href="/url1">foo</a></p>
-````````````````````````````````
-
-Inline links also take precedence:
-
-```````````````````````````````` example
-[foo]()
-
-[foo]: /url1
-.
-<p><a href="">foo</a></p>
-````````````````````````````````
-
-```````````````````````````````` example
-[foo](not a link)
-
-[foo]: /url1
-.
-<p><a href="/url1">foo</a>(not a link)</p>
-````````````````````````````````
-
-In the following case `[bar][baz]` is parsed as a reference,
-`[foo]` as normal text:
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url
-.
-<p>[foo]<a href="/url">bar</a></p>
-````````````````````````````````
-
-
-Here, though, `[foo][bar]` is parsed as a reference, since
-`[bar]` is defined:
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url1
-[bar]: /url2
-.
-<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
-````````````````````````````````
-
-
-Here `[foo]` is not parsed as a shortcut reference, because it
-is followed by a link label (even though `[bar]` is not defined):
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url1
-[foo]: /url2
-.
-<p>[foo]<a href="/url1">bar</a></p>
-````````````````````````````````
-
-
-
-## Images
-
-Syntax for images is like the syntax for links, with one
-difference. Instead of [link text], we have an
-[image description](@). The rules for this are the
-same as for [link text], except that (a) an
-image description starts with `![` rather than `[`, and
-(b) an image description may contain links.
-An image description has inline elements
-as its contents. When an image is rendered to HTML,
-this is standardly used as the image's `alt` attribute.
-
-```````````````````````````````` example
-![foo](/url "title")
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo *bar*]
-
-[foo *bar*]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo ![bar](/url)](/url2)
-.
-<p><img src="/url2" alt="foo bar" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo [bar](/url)](/url2)
-.
-<p><img src="/url2" alt="foo bar" /></p>
-````````````````````````````````
-
-
-Though this spec is concerned with parsing, not rendering, it is
-recommended that in rendering to HTML, only the plain string content
-of the [image description] be used. Note that in
-the above example, the alt attribute's value is `foo bar`, not `foo
-[bar](/url)` or `foo <a href="/url">bar</a>`. Only the plain string
-content is rendered, without formatting.
-
-```````````````````````````````` example
-![foo *bar*][]
-
-[foo *bar*]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo *bar*][foobar]
-
-[FOOBAR]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo](train.jpg)
-.
-<p><img src="train.jpg" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-My ![foo bar](/path/to/train.jpg "title" )
-.
-<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo](<url>)
-.
-<p><img src="url" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![](/url)
-.
-<p><img src="/url" alt="" /></p>
-````````````````````````````````
-
-
-Reference-style:
-
-```````````````````````````````` example
-![foo][bar]
-
-[bar]: /url
-.
-<p><img src="/url" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo][bar]
-
-[BAR]: /url
-.
-<p><img src="/url" alt="foo" /></p>
-````````````````````````````````
-
-
-Collapsed:
-
-```````````````````````````````` example
-![foo][]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![*foo* bar][]
-
-[*foo* bar]: /url "title"
-.
-<p><img src="/url" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-The labels are case-insensitive:
-
-```````````````````````````````` example
-![Foo][]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="Foo" title="title" /></p>
-````````````````````````````````
-
-
-As with reference links, [whitespace] is not allowed
-between the two sets of brackets:
-
-```````````````````````````````` example
-![foo]
-[]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" />
-[]</p>
-````````````````````````````````
-
-
-Shortcut:
-
-```````````````````````````````` example
-![foo]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![*foo* bar]
-
-[*foo* bar]: /url "title"
-.
-<p><img src="/url" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-Note that link labels cannot contain unescaped brackets:
-
-```````````````````````````````` example
-![[foo]]
-
-[[foo]]: /url "title"
-.
-<p>![[foo]]</p>
-<p>[[foo]]: /url &quot;title&quot;</p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-![Foo]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="Foo" title="title" /></p>
-````````````````````````````````
-
-
-If you just want a literal `!` followed by bracketed text, you can
-backslash-escape the opening `[`:
-
-```````````````````````````````` example
-!\[foo]
-
-[foo]: /url "title"
-.
-<p>![foo]</p>
-````````````````````````````````
-
-
-If you want a link after a literal `!`, backslash-escape the
-`!`:
-
-```````````````````````````````` example
-\![foo]
-
-[foo]: /url "title"
-.
-<p>!<a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-## Autolinks
-
-[Autolink](@)s are absolute URIs and email addresses inside
-`<` and `>`. They are parsed as links, with the URL or email address
-as the link label.
-
-A [URI autolink](@) consists of `<`, followed by an
-[absolute URI] followed by `>`. It is parsed as
-a link to the URI, with the URI as the link's label.
-
-An [absolute URI](@),
-for these purposes, consists of a [scheme] followed by a colon (`:`)
-followed by zero or more characters other than ASCII
-[whitespace] and control characters, `<`, and `>`. If
-the URI includes these characters, they must be percent-encoded
-(e.g. `%20` for a space).
-
-For purposes of this spec, a [scheme](@) is any sequence
-of 2--32 characters beginning with an ASCII letter and followed
-by any combination of ASCII letters, digits, or the symbols plus
-("+"), period ("."), or hyphen ("-").
-
-Here are some valid autolinks:
-
-```````````````````````````````` example
-<http://foo.bar.baz>
-.
-<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://foo.bar.baz/test?q=hello&id=22&boolean>
-.
-<p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<irc://foo.bar:2233/baz>
-.
-<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
-````````````````````````````````
-
-
-Uppercase is also fine:
-
-```````````````````````````````` example
-<MAILTO:FOO@BAR.BAZ>
-.
-<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
-````````````````````````````````
-
-
-Note that many strings that count as [absolute URIs] for
-purposes of this spec are not valid URIs, because their
-schemes are not registered or because of other problems
-with their syntax:
-
-```````````````````````````````` example
-<a+b+c:d>
-.
-<p><a href="a+b+c:d">a+b+c:d</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<made-up-scheme://foo,bar>
-.
-<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://../>
-.
-<p><a href="http://../">http://../</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<localhost:5001/foo>
-.
-<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
-````````````````````````````````
-
-
-Spaces are not allowed in autolinks:
-
-```````````````````````````````` example
-<http://foo.bar/baz bim>
-.
-<p>&lt;http://foo.bar/baz bim&gt;</p>
-````````````````````````````````
-
-
-Backslash-escapes do not work inside autolinks:
-
-```````````````````````````````` example
-<http://example.com/\[\>
-.
-<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
-````````````````````````````````
-
-
-An [email autolink](@)
-consists of `<`, followed by an [email address],
-followed by `>`. The link's label is the email address,
-and the URL is `mailto:` followed by the email address.
-
-An [email address](@),
-for these purposes, is anything that matches
-the [non-normative regex from the HTML5
-spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)):
-
- /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
- (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
-
-Examples of email autolinks:
-
-```````````````````````````````` example
-<foo@bar.example.com>
-.
-<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<foo+special@Bar.baz-bar0.com>
-.
-<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
-````````````````````````````````
-
-
-Backslash-escapes do not work inside email autolinks:
-
-```````````````````````````````` example
-<foo\+@bar.example.com>
-.
-<p>&lt;foo+@bar.example.com&gt;</p>
-````````````````````````````````
-
-
-These are not autolinks:
-
-```````````````````````````````` example
-<>
-.
-<p>&lt;&gt;</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-< http://foo.bar >
-.
-<p>&lt; http://foo.bar &gt;</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<m:abc>
-.
-<p>&lt;m:abc&gt;</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<foo.bar.baz>
-.
-<p>&lt;foo.bar.baz&gt;</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-http://example.com
-.
-<p>http://example.com</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo@bar.example.com
-.
-<p>foo@bar.example.com</p>
-````````````````````````````````
-
-<div class="extension">
-
-## Autolinks (extension)
-
-GFM enables the `autolink` extension, where autolinks will be recognised in a
-greater number of conditions.
-
-[Autolink]s can also be constructed without requiring the use of `<` and to `>`
-to delimit them, although they will be recognized under a smaller set of
-circumstances. All such recognized autolinks can only come at the beginning of
-a line, after whitespace, or any of the delimiting characters `*`, `_`, `~`,
-and `(`.
-
-An [extended www autolink](@) will be recognized
-when the text `www.` is found followed by a [valid domain].
-A [valid domain](@) consists of segments
-of alphanumeric characters, underscores (`_`) and hyphens (`-`)
-separated by periods (`.`).
-There must be at least one period,
-and no underscores may be present in the last two segments of the domain.
-
-The scheme `http` will be inserted automatically:
-
-```````````````````````````````` example autolink
-www.commonmark.org
-.
-<p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
-````````````````````````````````
-
-After a [valid domain], zero or more non-space non-`<` characters may follow:
-
-```````````````````````````````` example autolink
-Visit www.commonmark.org/help for more information.
-.
-<p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
-````````````````````````````````
-
-We then apply [extended autolink path validation](@) as follows:
-
-Trailing punctuation (specifically, `?`, `!`, `.`, `,`, `:`, `*`, `_`, and `~`)
-will not be considered part of the autolink, though they may be included in the
-interior of the link:
-
-```````````````````````````````` example autolink
-Visit www.commonmark.org.
-
-Visit www.commonmark.org/a.b.
-.
-<p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
-<p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
-````````````````````````````````
-
-When an autolink ends in `)`, we scan the entire autolink for the total number
-of parentheses. If there is a greater number of closing parentheses than
-opening ones, we don't consider the unmatched trailing parentheses part of the
-autolink, in order to facilitate including an autolink inside a parenthesis:
-
-```````````````````````````````` example autolink
-www.google.com/search?q=Markup+(business)
-
-www.google.com/search?q=Markup+(business)))
-
-(www.google.com/search?q=Markup+(business))
-
-(www.google.com/search?q=Markup+(business)
-.
-<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
-<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
-<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
-<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
-````````````````````````````````
-
-This check is only done when the link ends in a closing parentheses `)`, so if
-the only parentheses are in the interior of the autolink, no special rules are
-applied:
-
-```````````````````````````````` example autolink
-www.google.com/search?q=(business))+ok
-.
-<p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
-````````````````````````````````
-
-If an autolink ends in a semicolon (`;`), we check to see if it appears to
-resemble an [entity reference][entity references]; if the preceding text is `&`
-followed by one or more alphanumeric characters. If so, it is excluded from
-the autolink:
-
-```````````````````````````````` example autolink
-www.google.com/search?q=commonmark&hl=en
-
-www.google.com/search?q=commonmark&hl;
-.
-<p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
-<p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
-````````````````````````````````
-
-`<` immediately ends an autolink.
-
-```````````````````````````````` example autolink
-www.commonmark.org/he<lp
-.
-<p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
-````````````````````````````````
-
-An [extended url autolink](@) will be recognised when one of the schemes
-`http://`, `https://`, or `ftp://`, followed by a [valid domain], then zero or
-more non-space non-`<` characters according to
-[extended autolink path validation]:
-
-```````````````````````````````` example autolink
-http://commonmark.org
-
-(Visit https://encrypted.google.com/search?q=Markup+(business))
-
-Anonymous FTP is available at ftp://foo.bar.baz.
-.
-<p><a href="http://commonmark.org">http://commonmark.org</a></p>
-<p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
-<p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
-````````````````````````````````
-
-
-An [extended email autolink](@) will be recognised when an email address is
-recognised within any text node. Email addresses are recognised according to
-the following rules:
-
-* One ore more characters which are alphanumeric, or `.`, `-`, `_`, or `+`.
-* An `@` symbol.
-* One or more characters which are alphanumeric, or `-` or `_`,
- separated by periods (`.`).
- There must be at least one period.
- The last character must not be one of `-` or `_`.
-
-The scheme `mailto:` will automatically be added to the generated link:
-
-```````````````````````````````` example autolink
-foo@bar.baz
-.
-<p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
-````````````````````````````````
-
-`+` can occur before the `@`, but not after.
-
-```````````````````````````````` example autolink
-hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
-.
-<p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
-````````````````````````````````
-
-`.`, `-`, and `_` can occur on both sides of the `@`, but only `.` may occur at
-the end of the email address, in which case it will not be considered part of
-the address:
-
-```````````````````````````````` example autolink
-a.b-c_d@a.b
-
-a.b-c_d@a.b.
-
-a.b-c_d@a.b-
-
-a.b-c_d@a.b_
-.
-<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
-<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
-<p>a.b-c_d@a.b-</p>
-<p>a.b-c_d@a.b_</p>
-````````````````````````````````
-
-</div>
-
-## Raw HTML
-
-Text between `<` and `>` that looks like an HTML tag is parsed as a
-raw HTML tag and will be rendered in HTML without escaping.
-Tag and attribute names are not limited to current HTML tags,
-so custom tags (and even, say, DocBook tags) may be used.
-
-Here is the grammar for tags:
-
-A [tag name](@) consists of an ASCII letter
-followed by zero or more ASCII letters, digits, or
-hyphens (`-`).
-
-An [attribute](@) consists of [whitespace],
-an [attribute name], and an optional
-[attribute value specification].
-
-An [attribute name](@)
-consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII
-letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML
-specification restricted to ASCII. HTML5 is laxer.)
-
-An [attribute value specification](@)
-consists of optional [whitespace],
-a `=` character, optional [whitespace], and an [attribute
-value].
-
-An [attribute value](@)
-consists of an [unquoted attribute value],
-a [single-quoted attribute value], or a [double-quoted attribute value].
-
-An [unquoted attribute value](@)
-is a nonempty string of characters not
-including [whitespace], `"`, `'`, `=`, `<`, `>`, or `` ` ``.
-
-A [single-quoted attribute value](@)
-consists of `'`, zero or more
-characters not including `'`, and a final `'`.
-
-A [double-quoted attribute value](@)
-consists of `"`, zero or more
-characters not including `"`, and a final `"`.
-
-An [open tag](@) consists of a `<` character, a [tag name],
-zero or more [attributes], optional [whitespace], an optional `/`
-character, and a `>` character.
-
-A [closing tag](@) consists of the string `</`, a
-[tag name], optional [whitespace], and the character `>`.
-
-An [HTML comment](@) consists of `<!--` + *text* + `-->`,
-where *text* does not start with `>` or `->`, does not end with `-`,
-and does not contain `--`. (See the
-[HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).)
-
-A [processing instruction](@)
-consists of the string `<?`, a string
-of characters not including the string `?>`, and the string
-`?>`.
-
-A [declaration](@) consists of the
-string `<!`, a name consisting of one or more uppercase ASCII letters,
-[whitespace], a string of characters not including the
-character `>`, and the character `>`.
-
-A [CDATA section](@) consists of
-the string `<![CDATA[`, a string of characters not including the string
-`]]>`, and the string `]]>`.
-
-An [HTML tag](@) consists of an [open tag], a [closing tag],
-an [HTML comment], a [processing instruction], a [declaration],
-or a [CDATA section].
-
-Here are some simple open tags:
-
-```````````````````````````````` example
-<a><bab><c2c>
-.
-<p><a><bab><c2c></p>
-````````````````````````````````
-
-
-Empty elements:
-
-```````````````````````````````` example
-<a/><b2/>
-.
-<p><a/><b2/></p>
-````````````````````````````````
-
-
-[Whitespace] is allowed:
-
-```````````````````````````````` example
-<a /><b2
-data="foo" >
-.
-<p><a /><b2
-data="foo" ></p>
-````````````````````````````````
-
-
-With attributes:
-
-```````````````````````````````` example
-<a foo="bar" bam = 'baz <em>"</em>'
-_boolean zoop:33=zoop:33 />
-.
-<p><a foo="bar" bam = 'baz <em>"</em>'
-_boolean zoop:33=zoop:33 /></p>
-````````````````````````````````
-
-
-Custom tag names can be used:
-
-```````````````````````````````` example
-Foo <responsive-image src="foo.jpg" />
-.
-<p>Foo <responsive-image src="foo.jpg" /></p>
-````````````````````````````````
-
-
-Illegal tag names, not parsed as HTML:
-
-```````````````````````````````` example
-<33> <__>
-.
-<p>&lt;33&gt; &lt;__&gt;</p>
-````````````````````````````````
-
-
-Illegal attribute names:
-
-```````````````````````````````` example
-<a h*#ref="hi">
-.
-<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
-````````````````````````````````
-
-
-Illegal attribute values:
-
-```````````````````````````````` example
-<a href="hi'> <a href=hi'>
-.
-<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
-````````````````````````````````
-
-
-Illegal [whitespace]:
-
-```````````````````````````````` example
-< a><
-foo><bar/ >
-<foo bar=baz
-bim!bop />
-.
-<p>&lt; a&gt;&lt;
-foo&gt;&lt;bar/ &gt;
-&lt;foo bar=baz
-bim!bop /&gt;</p>
-````````````````````````````````
-
-
-Missing [whitespace]:
-
-```````````````````````````````` example
-<a href='bar'title=title>
-.
-<p>&lt;a href='bar'title=title&gt;</p>
-````````````````````````````````
-
-
-Closing tags:
-
-```````````````````````````````` example
-</a></foo >
-.
-<p></a></foo ></p>
-````````````````````````````````
-
-
-Illegal attributes in closing tag:
-
-```````````````````````````````` example
-</a href="foo">
-.
-<p>&lt;/a href=&quot;foo&quot;&gt;</p>
-````````````````````````````````
-
-
-Comments:
-
-```````````````````````````````` example
-foo <!-- this is a
-comment - with hyphen -->
-.
-<p>foo <!-- this is a
-comment - with hyphen --></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo <!-- not a comment -- two hyphens -->
-.
-<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
-````````````````````````````````
-
-
-Not comments:
-
-```````````````````````````````` example
-foo <!--> foo -->
-
-foo <!-- foo--->
-.
-<p>foo &lt;!--&gt; foo --&gt;</p>
-<p>foo &lt;!-- foo---&gt;</p>
-````````````````````````````````
-
-
-Processing instructions:
-
-```````````````````````````````` example
-foo <?php echo $a; ?>
-.
-<p>foo <?php echo $a; ?></p>
-````````````````````````````````
-
-
-Declarations:
-
-```````````````````````````````` example
-foo <!ELEMENT br EMPTY>
-.
-<p>foo <!ELEMENT br EMPTY></p>
-````````````````````````````````
-
-
-CDATA sections:
-
-```````````````````````````````` example
-foo <![CDATA[>&<]]>
-.
-<p>foo <![CDATA[>&<]]></p>
-````````````````````````````````
-
-
-Entity and numeric character references are preserved in HTML
-attributes:
-
-```````````````````````````````` example
-foo <a href="&ouml;">
-.
-<p>foo <a href="&ouml;"></p>
-````````````````````````````````
-
-
-Backslash escapes do not work in HTML attributes:
-
-```````````````````````````````` example
-foo <a href="\*">
-.
-<p>foo <a href="\*"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="\"">
-.
-<p>&lt;a href=&quot;&quot;&quot;&gt;</p>
-````````````````````````````````
-
-
-<div class="extension">
-
-## Disallowed Raw HTML (extension)
-
-GFM enables the `tagfilter` extension, where the following HTML tags will be
-filtered when rendering HTML output:
-
-* `<title>`
-* `<textarea>`
-* `<style>`
-* `<xmp>`
-* `<iframe>`
-* `<noembed>`
-* `<noframes>`
-* `<script>`
-* `<plaintext>`
-
-Filtering is done by replacing the leading `<` with the entity `&lt;`. These
-tags are chosen in particular as they change how HTML is interpreted in a way
-unique to them (i.e. nested HTML is interpreted differently), and this is
-usually undesireable in the context of other rendered Markdown content.
-
-All other HTML tags are left untouched.
-
-```````````````````````````````` example tagfilter
-<strong> <title> <style> <em>
-
-<blockquote>
- <xmp> is disallowed. <XMP> is also disallowed.
-</blockquote>
-.
-<p><strong> &lt;title> &lt;style> <em></p>
-<blockquote>
- &lt;xmp> is disallowed. &lt;XMP> is also disallowed.
-</blockquote>
-````````````````````````````````
-
-</div>
-
-## Hard line breaks
-
-A line break (not in a code span or HTML tag) that is preceded
-by two or more spaces and does not occur at the end of a block
-is parsed as a [hard line break](@) (rendered
-in HTML as a `<br />` tag):
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-For a more visible alternative, a backslash before the
-[line ending] may be used instead of two spaces:
-
-```````````````````````````````` example
-foo\
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-More than two spaces can be used:
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-Leading spaces at the beginning of the next line are ignored:
-
-```````````````````````````````` example
-foo
- bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo\
- bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-Line breaks can occur inside emphasis, links, and other constructs
-that allow inline content:
-
-```````````````````````````````` example
-*foo
-bar*
-.
-<p><em>foo<br />
-bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo\
-bar*
-.
-<p><em>foo<br />
-bar</em></p>
-````````````````````````````````
-
-
-Line breaks do not occur inside code spans
-
-```````````````````````````````` example
-`code
-span`
-.
-<p><code>code span</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`code\
-span`
-.
-<p><code>code\ span</code></p>
-````````````````````````````````
-
-
-or HTML tags:
-
-```````````````````````````````` example
-<a href="foo
-bar">
-.
-<p><a href="foo
-bar"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="foo\
-bar">
-.
-<p><a href="foo\
-bar"></p>
-````````````````````````````````
-
-
-Hard line breaks are for separating inline content within a block.
-Neither syntax for hard line breaks works at the end of a paragraph or
-other block element:
-
-```````````````````````````````` example
-foo\
-.
-<p>foo\</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo
-.
-<p>foo</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-### foo\
-.
-<h3>foo\</h3>
-````````````````````````````````
-
-
-```````````````````````````````` example
-### foo
-.
-<h3>foo</h3>
-````````````````````````````````
-
-
-## Soft line breaks
-
-A regular line break (not in a code span or HTML tag) that is not
-preceded by two or more spaces or a backslash is parsed as a
-[softbreak](@). (A softbreak may be rendered in HTML either as a
-[line ending] or as a space. The result will be the same in
-browsers. In the examples here, a [line ending] will be used.)
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo
-baz</p>
-````````````````````````````````
-
-
-Spaces at the end of the line and beginning of the next line are
-removed:
-
-```````````````````````````````` example
-foo
- baz
-.
-<p>foo
-baz</p>
-````````````````````````````````
-
-
-A conforming parser may render a soft line break in HTML either as a
-line break or as a space.
-
-A renderer may also provide an option to render soft line breaks
-as hard line breaks.
-
-## Textual content
-
-Any characters not given an interpretation by the above rules will
-be parsed as plain textual content.
-
-```````````````````````````````` example
-hello $.;'there
-.
-<p>hello $.;'there</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo χÏῆν
-.
-<p>Foo χÏῆν</p>
-````````````````````````````````
-
-
-Internal spaces are preserved verbatim:
-
-```````````````````````````````` example
-Multiple spaces
-.
-<p>Multiple spaces</p>
-````````````````````````````````
-
-
-<!-- END TESTS -->
-
-# Appendix: A parsing strategy
-
-In this appendix we describe some features of the parsing strategy
-used in the CommonMark reference implementations.
-
-## Overview
-
-Parsing has two phases:
-
-1. In the first phase, lines of input are consumed and the block
-structure of the document---its division into paragraphs, block quotes,
-list items, and so on---is constructed. Text is assigned to these
-blocks but not parsed. Link reference definitions are parsed and a
-map of links is constructed.
-
-2. In the second phase, the raw text contents of paragraphs and headings
-are parsed into sequences of Markdown inline elements (strings,
-code spans, links, emphasis, and so on), using the map of link
-references constructed in phase 1.
-
-At each point in processing, the document is represented as a tree of
-**blocks**. The root of the tree is a `document` block. The `document`
-may have any number of other blocks as **children**. These children
-may, in turn, have other blocks as children. The last child of a block
-is normally considered **open**, meaning that subsequent lines of input
-can alter its contents. (Blocks that are not open are **closed**.)
-Here, for example, is a possible document tree, with the open blocks
-marked by arrows:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- "Qui *quodsi iracundia*"
- -> list_item
- -> paragraph
- "aliquando id"
-```
-
-## Phase 1: block structure
-
-Each line that is processed has an effect on this tree. The line is
-analyzed and, depending on its contents, the document may be altered
-in one or more of the following ways:
-
-1. One or more open blocks may be closed.
-2. One or more new blocks may be created as children of the
- last open block.
-3. Text may be added to the last (deepest) open block remaining
- on the tree.
-
-Once a line has been incorporated into the tree in this way,
-it can be discarded, so input can be read in a stream.
-
-For each line, we follow this procedure:
-
-1. First we iterate through the open blocks, starting with the
-root document, and descending through last children down to the last
-open block. Each block imposes a condition that the line must satisfy
-if the block is to remain open. For example, a block quote requires a
-`>` character. A paragraph requires a non-blank line.
-In this phase we may match all or just some of the open
-blocks. But we cannot close unmatched blocks yet, because we may have a
-[lazy continuation line].
-
-2. Next, after consuming the continuation markers for existing
-blocks, we look for new block starts (e.g. `>` for a block quote).
-If we encounter a new block start, we close any blocks unmatched
-in step 1 before creating the new block as a child of the last
-matched block.
-
-3. Finally, we look at the remainder of the line (after block
-markers like `>`, list markers, and indentation have been consumed).
-This is text that can be incorporated into the last open
-block (a paragraph, code block, heading, or raw HTML).
-
-Setext headings are formed when we see a line of a paragraph
-that is a [setext heading underline].
-
-Reference link definitions are detected when a paragraph is closed;
-the accumulated text lines are parsed to see if they begin with
-one or more reference link definitions. Any remainder becomes a
-normal paragraph.
-
-We can see how this works by considering how the tree above is
-generated by four lines of Markdown:
-
-``` markdown
-> Lorem ipsum dolor
-sit amet.
-> - Qui *quodsi iracundia*
-> - aliquando id
-```
-
-At the outset, our document model is just
-
-``` tree
--> document
-```
-
-The first line of our text,
-
-``` markdown
-> Lorem ipsum dolor
-```
-
-causes a `block_quote` block to be created as a child of our
-open `document` block, and a `paragraph` block as a child of
-the `block_quote`. Then the text is added to the last open
-block, the `paragraph`:
-
-``` tree
--> document
- -> block_quote
- -> paragraph
- "Lorem ipsum dolor"
-```
-
-The next line,
-
-``` markdown
-sit amet.
-```
-
-is a "lazy continuation" of the open `paragraph`, so it gets added
-to the paragraph's text:
-
-``` tree
--> document
- -> block_quote
- -> paragraph
- "Lorem ipsum dolor\nsit amet."
-```
-
-The third line,
-
-``` markdown
-> - Qui *quodsi iracundia*
-```
-
-causes the `paragraph` block to be closed, and a new `list` block
-opened as a child of the `block_quote`. A `list_item` is also
-added as a child of the `list`, and a `paragraph` as a child of
-the `list_item`. The text is then added to the new `paragraph`:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- -> list_item
- -> paragraph
- "Qui *quodsi iracundia*"
-```
-
-The fourth line,
-
-``` markdown
-> - aliquando id
-```
-
-causes the `list_item` (and its child the `paragraph`) to be closed,
-and a new `list_item` opened up as child of the `list`. A `paragraph`
-is added as a child of the new `list_item`, to contain the text.
-We thus obtain the final tree:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- "Qui *quodsi iracundia*"
- -> list_item
- -> paragraph
- "aliquando id"
-```
-
-## Phase 2: inline structure
-
-Once all of the input has been parsed, all open blocks are closed.
-
-We then "walk the tree," visiting every node, and parse raw
-string contents of paragraphs and headings as inlines. At this
-point we have seen all the link reference definitions, so we can
-resolve reference links as we go.
-
-``` tree
-document
- block_quote
- paragraph
- str "Lorem ipsum dolor"
- softbreak
- str "sit amet."
- list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- str "Qui "
- emph
- str "quodsi iracundia"
- list_item
- paragraph
- str "aliquando id"
-```
-
-Notice how the [line ending] in the first paragraph has
-been parsed as a `softbreak`, and the asterisks in the first list item
-have become an `emph`.
-
-### An algorithm for parsing nested emphasis and links
-
-By far the trickiest part of inline parsing is handling emphasis,
-strong emphasis, links, and images. This is done using the following
-algorithm.
-
-When we're parsing inlines and we hit either
-
-- a run of `*` or `_` characters, or
-- a `[` or `![`
-
-we insert a text node with these symbols as its literal content, and we
-add a pointer to this text node to the [delimiter stack](@).
-
-The [delimiter stack] is a doubly linked list. Each
-element contains a pointer to a text node, plus information about
-
-- the type of delimiter (`[`, `![`, `*`, `_`)
-- the number of delimiters,
-- whether the delimiter is "active" (all are active to start), and
-- whether the delimiter is a potential opener, a potential closer,
- or both (which depends on what sort of characters precede
- and follow the delimiters).
-
-When we hit a `]` character, we call the *look for link or image*
-procedure (see below).
-
-When we hit the end of the input, we call the *process emphasis*
-procedure (see below), with `stack_bottom` = NULL.
-
-#### *look for link or image*
-
-Starting at the top of the delimiter stack, we look backwards
-through the stack for an opening `[` or `![` delimiter.
-
-- If we don't find one, we return a literal text node `]`.
-
-- If we do find one, but it's not *active*, we remove the inactive
- delimiter from the stack, and return a literal text node `]`.
-
-- If we find one and it's active, then we parse ahead to see if
- we have an inline link/image, reference link/image, compact reference
- link/image, or shortcut reference link/image.
-
- + If we don't, then we remove the opening delimiter from the
- delimiter stack and return a literal text node `]`.
-
- + If we do, then
-
- * We return a link or image node whose children are the inlines
- after the text node pointed to by the opening delimiter.
-
- * We run *process emphasis* on these inlines, with the `[` opener
- as `stack_bottom`.
-
- * We remove the opening delimiter.
-
- * If we have a link (and not an image), we also set all
- `[` delimiters before the opening delimiter to *inactive*. (This
- will prevent us from getting links within links.)
-
-#### *process emphasis*
-
-Parameter `stack_bottom` sets a lower bound to how far we
-descend in the [delimiter stack]. If it is NULL, we can
-go all the way to the bottom. Otherwise, we stop before
-visiting `stack_bottom`.
-
-Let `current_position` point to the element on the [delimiter stack]
-just above `stack_bottom` (or the first element if `stack_bottom`
-is NULL).
-
-We keep track of the `openers_bottom` for each delimiter
-type (`*`, `_`) and each length of the closing delimiter run
-(modulo 3). Initialize this to `stack_bottom`.
-
-Then we repeat the following until we run out of potential
-closers:
-
-- Move `current_position` forward in the delimiter stack (if needed)
- until we find the first potential closer with delimiter `*` or `_`.
- (This will be the potential closer closest
- to the beginning of the input -- the first one in parse order.)
-
-- Now, look back in the stack (staying above `stack_bottom` and
- the `openers_bottom` for this delimiter type) for the
- first matching potential opener ("matching" means same delimiter).
-
-- If one is found:
-
- + Figure out whether we have emphasis or strong emphasis:
- if both closer and opener spans have length >= 2, we have
- strong, otherwise regular.
-
- + Insert an emph or strong emph node accordingly, after
- the text node corresponding to the opener.
-
- + Remove any delimiters between the opener and closer from
- the delimiter stack.
-
- + Remove 1 (for regular emph) or 2 (for strong emph) delimiters
- from the opening and closing text nodes. If they become empty
- as a result, remove them and remove the corresponding element
- of the delimiter stack. If the closing node is removed, reset
- `current_position` to the next element in the stack.
-
-- If none is found:
-
- + Set `openers_bottom` to the element before `current_position`.
- (We know that there are no openers for this kind of closer up to and
- including this point, so this puts a lower bound on future searches.)
-
- + If the closer at `current_position` is not a potential opener,
- remove it from the delimiter stack (since we know it can't
- be a closer either).
-
- + Advance `current_position` to the next element in the stack.
-
-After we're done, we remove all delimiters above `stack_bottom` from the
-delimiter stack.
-
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt b/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
deleted file mode 100644
index 10a46dcca6b..00000000000
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
+++ /dev/null
@@ -1,389 +0,0 @@
-# GitLab-Specific Markdown
-
-Currently, only some of the GitLab-specific markdown features are
-listed in this section. We will eventually add all
-GitLab-specific features currently listed as supported in the
-[user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).
-
-There is currently only this single top-level heading, but the
-examples may be split into multiple top-level headings in the future.
-
-## Footnotes
-
-See
-[the footnotes section of the user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html#footnotes).
-
-```````````````````````````````` example gitlab
-footnote reference tag [^fortytwo]
-
-[^fortytwo]: footnote text
-.
-<p>
-footnote reference tag
-<sup>
-<a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref>
-1
-</a>
-</sup>
-</p>
-<section data-footnotes>
-<ol>
-<li id="fn-fortytwo-42">
-<p>
-footnote text
-<a href="#fnref-fortytwo-42" data-footnote-backref>
-</a>
-</p>
-</li>
-</ol>
-</section>
-````````````````````````````````
-
-## Task list items
-
-See
-[Task lists](https://docs.gitlab.com/ee/user/markdown.html#task-lists) in the GitLab Flavored Markdown documentation.
-
-Task list items (checkboxes) are defined as a GitHub Flavored Markdown extension in a section above.
-GitLab extends the behavior of task list items to support additional features.
-Some of these features are in-progress, and should not yet be considered part of the official
-GitLab Flavored Markdown specification.
-
-Some of the behavior of task list items is implemented as client-side JavaScript/CSS.
-
-The following are some basic examples; more examples may be added in the future.
-
-Incomplete task:
-
-```````````````````````````````` example gitlab
-- [ ] incomplete
-.
-<ul>
-<li>
-<task-button/>
-<input type="checkbox" disabled/>
-incomplete
-</li>
-</ul>
-````````````````````````````````
-
-Completed task:
-
-```````````````````````````````` example gitlab
-- [x] completed
-.
-<ul>
-<li>
-<task-button/>
-<input type="checkbox" checked disabled/>
-completed
-</li>
-</ul>
-````````````````````````````````
-
-Inapplicable task:
-
-```````````````````````````````` example gitlab
-- [~] inapplicable
-.
-<ul>
-<li>
-<task-button/>
-<input type="checkbox" data-inapplicable disabled>
-<s>
-inapplicable
-</s>
-</li>
-</ul>
-````````````````````````````````
-
-Inapplicable task in a "loose" list. Note that the `<del>` tag is not applied to the
-loose text; it has strikethrough applied with CSS.
-
-```````````````````````````````` example gitlab
-- [~] inapplicable
-
- text in loose list
-.
-<ul>
-<li>
-<p>
-<task-button/>
-<input type="checkbox" data-inapplicable disabled>
-<s>
-inapplicable
-</s>
-</p>
-<p>
-text in loose list
-</p>
-</li>
-</ul>
-````````````````````````````````
-
-## Front matter
-
-See
-[Front matter](https://docs.gitlab.com/ee/user/markdown.html#front-matter) in the GitLab Flavored Markdown documentation.
-
-Front matter is metadata included at the beginning of a Markdown document, preceding the content.
-This data can be used by static site generators like Jekyll, Hugo, and many other applications.
-
-YAML front matter:
-
-```````````````````````````````` example gitlab
----
-title: YAML front matter
----
-.
-<pre>
-<code>
-title: YAML front matter
-</code>
-</pre>
-````````````````````````````````
-
-TOML front matter:
-
-```````````````````````````````` example gitlab
-+++
-title: TOML front matter
-+++
-.
-<pre>
-<code>
-title: TOML front matter
-</code>
-</pre>
-````````````````````````````````
-
-JSON front matter:
-
-```````````````````````````````` example gitlab
-;;;
-{
- "title": "JSON front matter"
-}
-;;;
-.
-<pre>
-<code>
-{
- "title": "JSON front matter"
-}
-</code>
-</pre>
-````````````````````````````````
-
-Front matter blocks should be inserted at the top of the document:
-
-```````````````````````````````` example gitlab
-text
-
----
-title: YAML front matter
----
-.
-<p>text</p>
-<hr>
-<h2>title: YAML front matter</h2>
-````````````````````````````````
-
-Front matter block delimiters shouldn’t be preceded by space characters:
-
-```````````````````````````````` example gitlab
- ---
-title: YAML front matter
----
-.
-<hr>
-<h2>title: YAML front matter</h2>
-````````````````````````````````
-
-## Audio
-
-See
-[audio](https://docs.gitlab.com/ee/user/markdown.html#audio) in the GitLab Flavored Markdown documentation.
-
-GLFM renders image elements as an audio player as long as the resource’s file extension is
-one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
-Audio ignore the alternative text part of an image declaration.
-
-```````````````````````````````` example gitlab
-![audio](audio.oga "audio title")
-.
-<p><audio src="audio.oga" title="audio title"></audio></p>
-````````````````````````````````
-
-Reference definitions work audio as well:
-
-```````````````````````````````` example gitlab
-[audio]: audio.oga "audio title"
-
-![audio][audio]
-.
-<p><audio src="audio.oga" title="audio title"></audio></p>
-````````````````````````````````
-
-## Video
-
-See
-[videos](https://docs.gitlab.com/ee/user/markdown.html#videos) in the GitLab Flavored Markdown documentation.
-
-GLFM renders image elements as a video player as long as the resource’s file extension is
-one of the following supported video extensions `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`.
-Videos ignore the alternative text part of an image declaration.
-
-
-```````````````````````````````` example gitlab
-![video](video.m4v "video title")
-.
-<p><video src="video.m4v" title="video title"></video></p>
-````````````````````````````````
-
-Reference definitions work video as well:
-
-```````````````````````````````` example gitlab
-[video]: video.mov "video title"
-
-![video][video]
-.
-<p><video src="video.mov" title="video title"></video></p>
-````````````````````````````````
-
-## Table of contents
-
-See
-[table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
-in the GitLab Flavored Markdown documentation.
-
-A table of contents is an unordered list that links to subheadings in the document.
-Add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
-
-```````````````````````````````` example gitlab
-[TOC]
-
-# Heading 1
-
-## Heading 2
-.
-<nav>
- <ul>
- <li><a href="#heading-1">Heading 1</a></li>
- <ul>
- <li><a href="#heading-2">Heading 2</a></li>
- </ul>
- </ul>
-</nav>
-<h1>Heading 1</h1>
-<h2>Heading 2</h2>
-````````````````````````````````
-
-```````````````````````````````` example gitlab
-[[_TOC_]]
-
-# Heading 1
-
-## Heading 2
-.
-<nav>
- <ul>
- <li><a href="#heading-1">Heading 1</a></li>
- <ul>
- <li><a href="#heading-2">Heading 2</a></li>
- </ul>
- </ul>
-</nav>
-<h1>Heading 1</h1>
-<h2>Heading 2</h2>
-````````````````````````````````
-
-A table of contents is a block element. It should preceded and followed by a blank
-line.
-
-```````````````````````````````` example gitlab
-[[_TOC_]]
-text
-
-text
-[TOC]
-.
-<p>[[<em>TOC</em>]]text</p>
-<p>text[TOC]</p>
-````````````````````````````````
-
-A table of contents can be indented with up to three spaces.
-
-```````````````````````````````` example gitlab
- [[_TOC_]]
-
-# Heading 1
-.
-<nav>
- <ul>
- <li><a href="#heading-1">Heading 1</a></li>
- </ul>
-</nav>
-<h1>Heading 1</h1>
-````````````````````````````````
-
-# Examples Using Internal Extensions
-
-## Markdown Preview API Request Overrides
-
-This section contains examples of all controllers which use `PreviewMarkdown` module
-and use different `markdown_context_params`. They exercise the various `preview_markdown`
-endpoints via `glfm_example_metadata.yml`.
-
-
-`preview_markdown` exercising `groups` API endpoint and `UploadLinkFilter`:
-
-```````````````````````````````` example gitlab
-[groups-test-file](/uploads/groups-test-file)
-.
-<p><a href="groups-test-file">groups-test-file</a></p>
-````````````````````````````````
-
-`preview_markdown` exercising `projects` API endpoint and `RepositoryLinkFilter`:
-
-```````````````````````````````` example gitlab
-[projects-test-file](projects-test-file)
-.
-<p><a href="projects-test-file">projects-test-file</a></p>
-````````````````````````````````
-
-`preview_markdown` exercising `projects` API endpoint and `SnippetReferenceFilter`:
-
-```````````````````````````````` example gitlab
-This project snippet ID reference IS filtered: $88888
-.
-<p>This project snippet ID reference IS filtered: $88888</p>
-````````````````````````````````
-
-`preview_markdown` exercising personal (non-project) `snippets` API endpoint. This is
-only used by the comment field on personal snippets. It has no unique custom markdown
-extension behavior, and specifically does not render snippet references via
-`SnippetReferenceFilter`, even if the ID is valid.
-
-```````````````````````````````` example gitlab
-This personal snippet ID reference is not filtered: $99999
-.
-<p>This personal snippet ID reference is not filtered: $99999</p>
-````````````````````````````````
-
-`preview_markdown` exercising project `wikis` API endpoint and `WikiLinkFilter`:
-
-```````````````````````````````` example gitlab
-[project-wikis-test-file](project-wikis-test-file)
-.
-<p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
-````````````````````````````````
-
-`preview_markdown` exercising group `wikis` API endpoint and `WikiLinkFilter`. This example
-also requires an EE license enabling the `group_wikis` feature:
-
-```````````````````````````````` example gitlab
-[group-wikis-test-file](group-wikis-test-file)
-.
-<p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
-````````````````````````````````
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml
index 3c043f5fba1..7fc1f9d9be0 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_metadata.yml
@@ -1,14 +1,14 @@
---
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__001:
api_request_override_path: /groups/glfm_group/preview_markdown
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__002:
api_request_override_path: /glfm_group/glfm_project/preview_markdown
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__003:
api_request_override_path: /glfm_group/glfm_project/preview_markdown
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__004:
api_request_override_path: /-/snippets/preview_markdown
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__005:
api_request_override_path: /glfm_group/glfm_project/-/wikis/new_page/preview_markdown
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__006:
ee: true
api_request_override_path: /groups/glfm_group/-/wikis/new_page/preview_markdown
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
index d576a8ddb51..06de4e687af 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
@@ -5,6 +5,7 @@
# - https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#glfm_example_normalizationsyml
#
# NOTE: All YAML anchors which are shared across one or more entries are defined in the `00_shared` section.
+# They must all start with `00_` in order to be skipped during example name validation.
00_shared:
00_uri: &00_uri
- regex: '(href|data-src)(=")(.*?)(test-file\.(png|zip)")'
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml
index a74c3492324..a0ce7f44a3c 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml
@@ -12,49 +12,49 @@
skip_running_snapshot_static_html_tests: false # NOT YET SUPPORTED
skip_running_snapshot_wysiwyg_html_tests: false
skip_running_snapshot_prosemirror_json_tests: false
-07_02_00__gitlab_specific_markdown__task_list_items__003:
+07_02_00__gitlab_official_specification_markdown__task_list_items__003:
skip_update_example_snapshot_html_wysiwyg: Inapplicable task list items not yet implemented for WYSYWIG
skip_update_example_snapshot_prosemirror_json: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_conformance_wysiwyg_tests: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_snapshot_wysiwyg_html_tests: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_snapshot_prosemirror_json_tests: Inapplicable task list items not yet implemented for WYSYWIG
-07_02_00__gitlab_specific_markdown__task_list_items__004:
+07_02_00__gitlab_official_specification_markdown__task_list_items__004:
skip_update_example_snapshot_html_wysiwyg: Inapplicable task list items not yet implemented for WYSYWIG
skip_update_example_snapshot_prosemirror_json: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_conformance_wysiwyg_tests: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_snapshot_wysiwyg_html_tests: Inapplicable task list items not yet implemented for WYSYWIG
skip_running_snapshot_prosemirror_json_tests: Inapplicable task list items not yet implemented for WYSYWIG
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__001:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_wysiwyg_html_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_prosemirror_json_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__002:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_wysiwyg_html_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_prosemirror_json_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__003:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_wysiwyg_html_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_prosemirror_json_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__004:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_wysiwyg_html_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_prosemirror_json_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__005:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_wysiwyg_html_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_snapshot_prosemirror_json_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+08_03_00__gitlab_internal_extension_markdown__markdown_preview_api_request_overrides__006:
skip_update_example_snapshot_html_wysiwyg: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_update_example_snapshot_prosemirror_json: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
skip_running_conformance_wysiwyg_tests: Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md b/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md
new file mode 100644
index 00000000000..171a8e430d3
--- /dev/null
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md
@@ -0,0 +1,111 @@
+# GitLab Internal Extension Markdown
+
+## Audio
+
+See
+[audio](https://docs.gitlab.com/ee/user/markdown.html#audio) in the GitLab Flavored Markdown documentation.
+
+GLFM renders image elements as an audio player as long as the resource’s file extension is
+one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
+Audio ignore the alternative text part of an image declaration.
+
+```````````````````````````````` example gitlab
+![audio](audio.oga "audio title")
+.
+<p><audio src="audio.oga" title="audio title"></audio></p>
+````````````````````````````````
+
+Reference definitions work audio as well:
+
+```````````````````````````````` example gitlab
+[audio]: audio.oga "audio title"
+
+![audio][audio]
+.
+<p><audio src="audio.oga" title="audio title"></audio></p>
+````````````````````````````````
+
+## Video
+
+See
+[videos](https://docs.gitlab.com/ee/user/markdown.html#videos) in the GitLab Flavored Markdown documentation.
+
+GLFM renders image elements as a video player as long as the resource’s file extension is
+one of the following supported video extensions `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`.
+Videos ignore the alternative text part of an image declaration.
+
+
+```````````````````````````````` example gitlab
+![video](video.m4v "video title")
+.
+<p><video src="video.m4v" title="video title"></video></p>
+````````````````````````````````
+
+Reference definitions work video as well:
+
+```````````````````````````````` example gitlab
+[video]: video.mov "video title"
+
+![video][video]
+.
+<p><video src="video.mov" title="video title"></video></p>
+````````````````````````````````
+
+## Markdown Preview API Request Overrides
+
+This section contains examples of all controllers which use `PreviewMarkdown` module
+and use different `markdown_context_params`. They exercise the various `preview_markdown`
+endpoints via `glfm_example_metadata.yml`.
+
+
+`preview_markdown` exercising `groups` API endpoint and `UploadLinkFilter`:
+
+```````````````````````````````` example gitlab
+[groups-test-file](/uploads/groups-test-file)
+.
+<p><a href="groups-test-file">groups-test-file</a></p>
+````````````````````````````````
+
+`preview_markdown` exercising `projects` API endpoint and `RepositoryLinkFilter`:
+
+```````````````````````````````` example gitlab
+[projects-test-file](projects-test-file)
+.
+<p><a href="projects-test-file">projects-test-file</a></p>
+````````````````````````````````
+
+`preview_markdown` exercising `projects` API endpoint and `SnippetReferenceFilter`:
+
+```````````````````````````````` example gitlab
+This project snippet ID reference IS filtered: $88888
+.
+<p>This project snippet ID reference IS filtered: $88888</p>
+````````````````````````````````
+
+`preview_markdown` exercising personal (non-project) `snippets` API endpoint. This is
+only used by the comment field on personal snippets. It has no unique custom markdown
+extension behavior, and specifically does not render snippet references via
+`SnippetReferenceFilter`, even if the ID is valid.
+
+```````````````````````````````` example gitlab
+This personal snippet ID reference is not filtered: $99999
+.
+<p>This personal snippet ID reference is not filtered: $99999</p>
+````````````````````````````````
+
+`preview_markdown` exercising project `wikis` API endpoint and `WikiLinkFilter`:
+
+```````````````````````````````` example gitlab
+[project-wikis-test-file](project-wikis-test-file)
+.
+<p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
+````````````````````````````````
+
+`preview_markdown` exercising group `wikis` API endpoint and `WikiLinkFilter`. This example
+also requires an EE license enabling the `group_wikis` feature:
+
+```````````````````````````````` example gitlab
+[group-wikis-test-file](group-wikis-test-file)
+.
+<p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
+````````````````````````````````
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.txt b/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md
index b5351bf37de..b5351bf37de 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.txt
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md b/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md
new file mode 100644
index 00000000000..f2b62b1a4ac
--- /dev/null
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md
@@ -0,0 +1,277 @@
+# GitLab Official Specification Markdown
+
+Currently, only some of the GitLab-specific markdown features are
+listed in this section. We will eventually add all
+GitLab-specific features currently listed as supported in the
+[user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).
+
+There is currently only this single top-level heading, but the
+examples may be split into multiple top-level headings in the future.
+
+## Footnotes
+
+See
+[the footnotes section of the user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html#footnotes).
+
+```````````````````````````````` example gitlab
+footnote reference tag [^fortytwo]
+
+[^fortytwo]: footnote text
+.
+<p>
+footnote reference tag
+<sup>
+<a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref>
+1
+</a>
+</sup>
+</p>
+<section data-footnotes>
+<ol>
+<li id="fn-fortytwo-42">
+<p>
+footnote text
+<a href="#fnref-fortytwo-42" data-footnote-backref>
+</a>
+</p>
+</li>
+</ol>
+</section>
+````````````````````````````````
+
+## Task list items
+
+See
+[Task lists](https://docs.gitlab.com/ee/user/markdown.html#task-lists) in the GitLab Flavored Markdown documentation.
+
+Task list items (checkboxes) are defined as a GitHub Flavored Markdown extension in a section above.
+GitLab extends the behavior of task list items to support additional features.
+Some of these features are in-progress, and should not yet be considered part of the official
+GitLab Flavored Markdown specification.
+
+Some of the behavior of task list items is implemented as client-side JavaScript/CSS.
+
+The following are some basic examples; more examples may be added in the future.
+
+Incomplete task:
+
+```````````````````````````````` example gitlab
+- [ ] incomplete
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" disabled/>
+incomplete
+</li>
+</ul>
+````````````````````````````````
+
+Completed task:
+
+```````````````````````````````` example gitlab
+- [x] completed
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" checked disabled/>
+completed
+</li>
+</ul>
+````````````````````````````````
+
+Inapplicable task:
+
+```````````````````````````````` example gitlab
+- [~] inapplicable
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" data-inapplicable disabled>
+<s>
+inapplicable
+</s>
+</li>
+</ul>
+````````````````````````````````
+
+Inapplicable task in a "loose" list. Note that the `<del>` tag is not applied to the
+loose text; it has strikethrough applied with CSS.
+
+```````````````````````````````` example gitlab
+- [~] inapplicable
+
+ text in loose list
+.
+<ul>
+<li>
+<p>
+<task-button/>
+<input type="checkbox" data-inapplicable disabled>
+<s>
+inapplicable
+</s>
+</p>
+<p>
+text in loose list
+</p>
+</li>
+</ul>
+````````````````````````````````
+
+## Front matter
+
+See
+[Front matter](https://docs.gitlab.com/ee/user/markdown.html#front-matter) in the GitLab Flavored Markdown documentation.
+
+Front matter is metadata included at the beginning of a Markdown document, preceding the content.
+This data can be used by static site generators like Jekyll, Hugo, and many other applications.
+
+YAML front matter:
+
+```````````````````````````````` example gitlab
+---
+title: YAML front matter
+---
+.
+<pre>
+<code>
+title: YAML front matter
+</code>
+</pre>
+````````````````````````````````
+
+TOML front matter:
+
+```````````````````````````````` example gitlab
++++
+title: TOML front matter
++++
+.
+<pre>
+<code>
+title: TOML front matter
+</code>
+</pre>
+````````````````````````````````
+
+JSON front matter:
+
+```````````````````````````````` example gitlab
+;;;
+{
+ "title": "JSON front matter"
+}
+;;;
+.
+<pre>
+<code>
+{
+ "title": "JSON front matter"
+}
+</code>
+</pre>
+````````````````````````````````
+
+Front matter blocks should be inserted at the top of the document:
+
+```````````````````````````````` example gitlab
+text
+
+---
+title: YAML front matter
+---
+.
+<p>text</p>
+<hr>
+<h2>title: YAML front matter</h2>
+````````````````````````````````
+
+Front matter block delimiters shouldn’t be preceded by space characters:
+
+```````````````````````````````` example gitlab
+ ---
+title: YAML front matter
+---
+.
+<hr>
+<h2>title: YAML front matter</h2>
+````````````````````````````````
+
+## Table of contents
+
+See
+[table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
+in the GitLab Flavored Markdown documentation.
+
+A table of contents is an unordered list that links to subheadings in the document.
+Add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
+
+```````````````````````````````` example gitlab
+[TOC]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+ <ul>
+ <li><a href="#heading-1">Heading 1</a></li>
+ <ul>
+ <li><a href="#heading-2">Heading 2</a></li>
+ </ul>
+ </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+ <ul>
+ <li><a href="#heading-1">Heading 1</a></li>
+ <ul>
+ <li><a href="#heading-2">Heading 2</a></li>
+ </ul>
+ </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+A table of contents is a block element. It should preceded and followed by a blank
+line.
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+text
+
+text
+[TOC]
+.
+<p>[[<em>TOC</em>]]text</p>
+<p>text[TOC]</p>
+````````````````````````````````
+
+A table of contents can be indented with up to three spaces.
+
+```````````````````````````````` example gitlab
+ [[_TOC_]]
+
+# Heading 1
+.
+<nav>
+ <ul>
+ <li><a href="#heading-1">Heading 1</a></li>
+ </ul>
+</nav>
+<h1>Heading 1</h1>
+````````````````````````````````
diff --git a/glfm_specification/output/spec.html b/glfm_specification/output/spec.html
index b8315390200..e57cd344618 100644
--- a/glfm_specification/output/spec.html
+++ b/glfm_specification/output/spec.html
@@ -1 +1,9219 @@
-PLACEHOLDER FILE. Actual contents will be added in a future MR.
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1:1-4: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">GitLab Flavored Markdown (GLFM) Spec</span></span>
+<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<h1 data-sourcepos="6:1-6:14" dir="auto">
+<a id="user-content-introduction" class="anchor" href="#introduction" aria-hidden="true"></a>Introduction</h1>
+<p data-sourcepos="8:1-8:84" dir="auto">TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.</p>
+<h1 data-sourcepos="10:1-10:15" dir="auto">
+<a id="user-content-preliminaries" class="anchor" href="#preliminaries" aria-hidden="true"></a>Preliminaries</h1>
+<h2 data-sourcepos="12:1-12:23" dir="auto">
+<a id="user-content-characters-and-lines" class="anchor" href="#characters-and-lines" aria-hidden="true"></a>Characters and lines</h2>
+<p data-sourcepos="14:1-15:9" dir="auto">Any sequence of [characters] is a valid CommonMark
+document.</p>
+<p data-sourcepos="17:1-20:26" dir="auto">A <a href="@">character</a> is a Unicode code point. Although some
+code points (for example, combining accents) do not correspond to
+characters in an intuitive sense, all code points count as characters
+for purposes of this spec.</p>
+<p data-sourcepos="22:1-24:22" dir="auto">This spec does not specify an encoding; it thinks of lines as composed
+of [characters] rather than bytes. A conforming parser may be limited
+to a certain encoding.</p>
+<p data-sourcepos="26:1-28:50" dir="auto">A <a href="@">line</a> is a sequence of zero or more [characters]
+other than newline (<code>U+000A</code>) or carriage return (<code>U+000D</code>),
+followed by a [line ending] or by the end of file.</p>
+<p data-sourcepos="30:1-32:18" dir="auto">A <a href="@">line ending</a> is a newline (<code>U+000A</code>), a carriage return
+(<code>U+000D</code>) not followed by a newline, or a carriage return and a
+following newline.</p>
+<p data-sourcepos="34:1-35:59" dir="auto">A line containing no characters, or a line containing only spaces
+(<code>U+0020</code>) or tabs (<code>U+0009</code>), is called a <a href="@">blank line</a>.</p>
+<p data-sourcepos="37:1-37:73" dir="auto">The following definitions of character classes will be used in this spec:</p>
+<p data-sourcepos="39:1-41:52" dir="auto">A <a href="@">whitespace character</a> is a space
+(<code>U+0020</code>), tab (<code>U+0009</code>), newline (<code>U+000A</code>), line tabulation (<code>U+000B</code>),
+form feed (<code>U+000C</code>), or carriage return (<code>U+000D</code>).</p>
+<p data-sourcepos="43:1-44:12" dir="auto"><a href="@">Whitespace</a> is a sequence of one or more [whitespace
+characters].</p>
+<p data-sourcepos="46:1-49:11" dir="auto">A <a href="@">Unicode whitespace character</a> is
+any code point in the Unicode <code>Zs</code> general category, or a tab (<code>U+0009</code>),
+carriage return (<code>U+000D</code>), newline (<code>U+000A</code>), or form feed
+(<code>U+000C</code>).</p>
+<p data-sourcepos="51:1-52:40" dir="auto"><a href="@">Unicode whitespace</a> is a sequence of one
+or more [Unicode whitespace characters].</p>
+<p data-sourcepos="54:1-54:25" dir="auto">A <a href="@">space</a> is <code>U+0020</code>.</p>
+<p data-sourcepos="56:1-57:37" dir="auto">A <a href="@">non-whitespace character</a> is any character
+that is not a [whitespace character].</p>
+<p data-sourcepos="59:1-64:38" dir="auto">An <a href="@">ASCII punctuation character</a>
+is <code>!</code>, <code>"</code>, <code>#</code>, <code>$</code>, <code>%</code>, <code>&amp;</code>, <code>'</code>, <code>(</code>, <code>)</code>,
+<code>*</code>, <code>+</code>, <code>,</code>, <code>-</code>, <code>.</code>, <code>/</code> (U+0021–2F),
+<code>:</code>, <code>;</code>, <code>&lt;</code>, <code>=</code>, <code>&gt;</code>, <code>?</code>, <code>@</code> (U+003A–0040),
+<code>[</code>, <code>\</code>, <code>]</code>, <code>^</code>, <code>_</code>, <code>`</code> (U+005B–0060),
+<code>{</code>, <code>|</code>, <code>}</code>, or <code>~</code> (U+007B–007E).</p>
+<p data-sourcepos="66:1-68:76" dir="auto">A <a href="@">punctuation character</a> is an [ASCII
+punctuation character] or anything in
+the general Unicode categories <code>Pc</code>, <code>Pd</code>, <code>Pe</code>, <code>Pf</code>, <code>Pi</code>, <code>Po</code>, or <code>Ps</code>.</p>
+<h2 data-sourcepos="70:1-70:7" dir="auto">
+<a id="user-content-tabs" class="anchor" href="#tabs" aria-hidden="true"></a>Tabs</h2>
+<p data-sourcepos="72:1-75:16" dir="auto">Tabs in lines are not expanded to [spaces]. However,
+in contexts where whitespace helps to define block structure,
+tabs behave as if they were replaced by spaces with a tab stop
+of 4 characters.</p>
+<p data-sourcepos="77:1-80:8" dir="auto">Thus, for example, a tab can be used instead of four spaces
+in an indented code block. (Note, however, that internal
+tabs are passed through as literal tabs, not expanded to
+spaces.)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="82:1-87:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">→foo→baz→→bim</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo→baz→→bim</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="89:1-94:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> →foo→baz→→bim</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo→baz→→bim</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="96:1-103:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> a→a</span>
+<span id="LC2" class="line" lang="plaintext"> á½â†’a</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;a→a</span>
+<span id="LC5" class="line" lang="plaintext">á½â†’a</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="105:1-107:38" dir="auto">In the following example, a continuation paragraph of a list
+item is indented with a tab; this has exactly the same effect
+as indentation with four spaces would:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="109:1-120:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">→bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="122:1-134:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">→→bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="136:1-143:36" dir="auto">Normally the <code>&gt;</code> that begins a block quote may be followed
+optionally by a space, which is not considered part of the
+content. In the following case <code>&gt;</code> is followed by a tab,
+which is treated as if it were expanded into three spaces.
+Since one of these spaces is considered part of the
+delimiter, <code>foo</code> is considered to be indented six spaces
+inside the block quote context, so we get an indented
+code block starting with two spaces.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="145:1-152:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;→→foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; foo</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="154:1-163:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-→→foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="166:1-173:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
+<span id="LC2" class="line" lang="plaintext">→bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">bar</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="175:1-191:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext">→ - baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="193:1-197:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">#→Foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="199:1-203:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*→*→*→</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="206:1-206:22" dir="auto">
+<a id="user-content-insecure-characters" class="anchor" href="#insecure-characters" aria-hidden="true"></a>Insecure characters</h2>
+<p data-sourcepos="208:1-209:42" dir="auto">For security reasons, the Unicode character <code>U+0000</code> must be replaced
+with the REPLACEMENT CHARACTER (<code>U+FFFD</code>).</p>
+<h1 data-sourcepos="211:1-211:20" dir="auto">
+<a id="user-content-blocks-and-inlines" class="anchor" href="#blocks-and-inlines" aria-hidden="true"></a>Blocks and inlines</h1>
+<p data-sourcepos="213:1-218:54" dir="auto">We can think of a document as a sequence of
+<a href="@">blocks</a>---structural elements like paragraphs, block
+quotations, lists, headings, rules, and code blocks. Some blocks (like
+block quotes and list items) contain other blocks; others (like
+headings and paragraphs) contain <a href="@">inline</a> content---text,
+links, emphasized text, images, code spans, and so on.</p>
+<h2 data-sourcepos="220:1-220:13" dir="auto">
+<a id="user-content-precedence" class="anchor" href="#precedence" aria-hidden="true"></a>Precedence</h2>
+<p data-sourcepos="222:1-224:59" dir="auto">Indicators of block structure always take precedence over indicators
+of inline structure. So, for example, the following is a list with
+two items, not a list with one item containing a code span:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="226:1-234:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- `one</span>
+<span id="LC2" class="line" lang="plaintext">- two`</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;`one&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;two`&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="237:1-244:66" dir="auto">This means that parsing can proceed in two steps: first, the block
+structure of the document can be discerned; second, text lines inside
+paragraphs, headings, and other block constructs can be parsed for inline
+structure. The second step requires information about link reference
+definitions that will be available only at the end of the first
+step. Note that the first step requires processing lines in sequence,
+but the second can be parallelized, since the inline parsing of
+one block element does not affect the inline parsing of any other.</p>
+<h2 data-sourcepos="246:1-246:35" dir="auto">
+<a id="user-content-container-blocks-and-leaf-blocks" class="anchor" href="#container-blocks-and-leaf-blocks" aria-hidden="true"></a>Container blocks and leaf blocks</h2>
+<p data-sourcepos="248:1-251:13" dir="auto">We can divide blocks into two types:
+<a href="@">container blocks</a>,
+which can contain other blocks, and <a href="@">leaf blocks</a>,
+which cannot.</p>
+<h1 data-sourcepos="253:1-253:13" dir="auto">
+<a id="user-content-leaf-blocks" class="anchor" href="#leaf-blocks" aria-hidden="true"></a>Leaf blocks</h1>
+<p data-sourcepos="255:1-256:18" dir="auto">This section describes the different kinds of leaf block that make up a
+Markdown document.</p>
+<h2 data-sourcepos="258:1-258:18" dir="auto">
+<a id="user-content-thematic-breaks" class="anchor" href="#thematic-breaks" aria-hidden="true"></a>Thematic breaks</h2>
+<p data-sourcepos="260:1-263:20" dir="auto">A line consisting of 0-3 spaces of indentation, followed by a sequence
+of three or more matching <code>-</code>, <code>_</code>, or <code>*</code> characters, each followed
+optionally by any number of spaces or tabs, forms a
+<a href="@">thematic break</a>.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="265:1-273:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">___</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="276:1-276:17" dir="auto">Wrong characters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="278:1-282:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;+++&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="285:1-289:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">===</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;===&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="292:1-292:22" dir="auto">Not enough characters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="294:1-302:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">--</span>
+<span id="LC2" class="line" lang="plaintext">**</span>
+<span id="LC3" class="line" lang="plaintext">__</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;--</span>
+<span id="LC6" class="line" lang="plaintext">**</span>
+<span id="LC7" class="line" lang="plaintext">__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="305:1-305:39" dir="auto">One to three spaces indent are allowed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="307:1-315:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ***</span>
+<span id="LC2" class="line" lang="plaintext"> ***</span>
+<span id="LC3" class="line" lang="plaintext"> ***</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="318:1-318:24" dir="auto">Four spaces is too many:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="320:1-325:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;***</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="328:1-334:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext"> ***</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC5" class="line" lang="plaintext">***&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="337:1-337:39" dir="auto">More than three characters may be used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="339:1-343:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_____________________________________</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="346:1-346:42" dir="auto">Spaces are allowed between the characters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="348:1-352:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - - -</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="355:1-359:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ** * ** * ** * **</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="362:1-366:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- - - -</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="369:1-369:30" dir="auto">Spaces are allowed at the end:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="371:1-375:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- - - - </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="378:1-378:51" dir="auto">However, no other characters may occur in the line:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="380:1-390:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_ _ _ _ a</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">a------</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">---a---</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;_ _ _ _ a&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;a------&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;---a---&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="393:1-394:33" dir="auto">It is required that all of the [non-whitespace characters] be the same.
+So, this is not a thematic break:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="396:1-400:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> *-*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;-&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="403:1-403:56" dir="auto">Thematic breaks do not need blank lines before or after:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="405:1-417:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">***</span>
+<span id="LC3" class="line" lang="plaintext">- bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="420:1-420:42" dir="auto">Thematic breaks can interrupt a paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="422:1-430:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">***</span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="433:1-437:71" dir="auto">If a line of dashes that meets the above conditions for being a
+thematic break could also be interpreted as the underline of a [setext
+heading], the interpretation as a
+[setext heading] takes precedence. Thus, for example,
+this is a setext heading, not a paragraph followed by a thematic break:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="439:1-446:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="449:1-450:63" dir="auto">When both a thematic break and a list item are possible
+interpretations of a line, the thematic break takes precedence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="452:1-464:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">* Foo</span>
+<span id="LC2" class="line" lang="plaintext">* * *</span>
+<span id="LC3" class="line" lang="plaintext">* Bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;Foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;Bar&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="467:1-467:68" dir="auto">If you want a thematic break in a list item, use a different bullet:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="469:1-479:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- Foo</span>
+<span id="LC2" class="line" lang="plaintext">- * * *</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;Foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="482:1-482:15" dir="auto">
+<a id="user-content-atx-headings" class="anchor" href="#atx-headings" aria-hidden="true"></a>ATX headings</h2>
+<p data-sourcepos="484:1-494:35" dir="auto">An <a href="@">ATX heading</a>
+consists of a string of characters, parsed as inline content, between an
+opening sequence of 1--6 unescaped <code>#</code> characters and an optional
+closing sequence of any number of unescaped <code>#</code> characters.
+The opening sequence of <code>#</code> characters must be followed by a
+[space] or by the end of line. The optional closing sequence of <code>#</code>s must be
+preceded by a [space] and may be followed by spaces only. The opening
+<code>#</code> character may be indented 0-3 spaces. The raw contents of the
+heading are stripped of leading and trailing spaces before being parsed
+as inline content. The heading level is equal to the number of <code>#</code>
+characters in the opening sequence.</p>
+<p data-sourcepos="496:1-496:16" dir="auto">Simple headings:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="498:1-512:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo</span>
+<span id="LC2" class="line" lang="plaintext">## foo</span>
+<span id="LC3" class="line" lang="plaintext">### foo</span>
+<span id="LC4" class="line" lang="plaintext">#### foo</span>
+<span id="LC5" class="line" lang="plaintext">##### foo</span>
+<span id="LC6" class="line" lang="plaintext">###### foo</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h1&gt;foo&lt;/h1&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;h2&gt;foo&lt;/h2&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;h3&gt;foo&lt;/h3&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h4&gt;foo&lt;/h4&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;h5&gt;foo&lt;/h5&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;h6&gt;foo&lt;/h6&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="515:1-515:46" dir="auto">More than six <code>#</code> characters is not a heading:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="517:1-521:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">####### foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;####### foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="524:1-530:9" dir="auto">At least one space is required between the <code>#</code> characters and the
+heading's contents, unless the heading is empty. Note that many
+implementations currently do not require the space. However, the
+space was required by the
+<a href="http://www.aaronsw.com/2002/atx/atx.py" rel="nofollow noreferrer noopener" target="_blank">original ATX implementation</a>,
+and it helps prevent things like the following from being parsed as
+headings:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="532:1-539:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">#5 bolt</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">#hashtag</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;#5 bolt&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;#hashtag&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="542:1-542:56" dir="auto">This is not a heading, because the first <code>#</code> is escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="544:1-548:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\## foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;## foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="551:1-551:31" dir="auto">Contents are parsed as inlines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="553:1-557:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo *bar* \*baz\*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h1&gt;foo &lt;em&gt;bar&lt;/em&gt; *baz*&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="560:1-560:71" dir="auto">Leading and trailing [whitespace] is ignored in parsing inline content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="562:1-566:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h1&gt;foo&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="569:1-569:44" dir="auto">One to three spaces indentation are allowed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="571:1-579:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ### foo</span>
+<span id="LC2" class="line" lang="plaintext"> ## foo</span>
+<span id="LC3" class="line" lang="plaintext"> # foo</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h3&gt;foo&lt;/h3&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h2&gt;foo&lt;/h2&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;h1&gt;foo&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="582:1-582:25" dir="auto">Four spaces are too much:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="584:1-589:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> # foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;# foo</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="592:1-598:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext"> # bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext"># bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="601:1-601:49" dir="auto">A closing sequence of <code>#</code> characters is optional:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="603:1-609:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">## foo ##</span>
+<span id="LC2" class="line" lang="plaintext"> ### bar ###</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h2&gt;foo&lt;/h2&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h3&gt;bar&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="612:1-612:55" dir="auto">It need not be the same length as the opening sequence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="614:1-620:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo ##################################</span>
+<span id="LC2" class="line" lang="plaintext">##### foo ##</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h1&gt;foo&lt;/h1&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h5&gt;foo&lt;/h5&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="623:1-623:46" dir="auto">Spaces are allowed after the closing sequence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="625:1-629:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">### foo ### </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h3&gt;foo&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="632:1-634:8" dir="auto">A sequence of <code>#</code> characters with anything but [spaces] following it
+is not a closing sequence, but counts as part of the contents of the
+heading:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="636:1-640:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">### foo ### b</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h3&gt;foo ### b&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="643:1-643:49" dir="auto">The closing sequence must be preceded by a space:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="645:1-649:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo#</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h1&gt;foo#&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="652:1-653:24" dir="auto">Backslash-escaped <code>#</code> characters do not count as part
+of the closing sequence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="655:1-663:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">### foo \###</span>
+<span id="LC2" class="line" lang="plaintext">## foo #\##</span>
+<span id="LC3" class="line" lang="plaintext"># foo \#</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h3&gt;foo ###&lt;/h3&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h2&gt;foo ###&lt;/h2&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;h1&gt;foo #&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="666:1-667:41" dir="auto">ATX headings need not be separated from surrounding content by blank
+lines, and they can interrupt paragraphs:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="669:1-677:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">****</span>
+<span id="LC2" class="line" lang="plaintext">## foo</span>
+<span id="LC3" class="line" lang="plaintext">****</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h2&gt;foo&lt;/h2&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="680:1-688:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo bar</span>
+<span id="LC2" class="line" lang="plaintext"># baz</span>
+<span id="LC3" class="line" lang="plaintext">Bar foo</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo bar&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;baz&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;Bar foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="691:1-691:26" dir="auto">ATX headings can be empty:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="693:1-701:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">## </span>
+<span id="LC2" class="line" lang="plaintext">#</span>
+<span id="LC3" class="line" lang="plaintext">### ###</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h2&gt;&lt;/h2&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;h3&gt;&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="704:1-704:18" dir="auto">
+<a id="user-content-setext-headings" class="anchor" href="#setext-headings" aria-hidden="true"></a>Setext headings</h2>
+<p data-sourcepos="706:1-714:54" dir="auto">A <a href="@">setext heading</a> consists of one or more
+lines of text, each containing at least one [non-whitespace
+character], with no more than 3 spaces indentation, followed by
+a [setext heading underline]. The lines of text must be such
+that, were they not followed by the setext heading underline,
+they would be interpreted as a paragraph: they cannot be
+interpretable as a [code fence], [ATX heading][ATX headings],
+[block quote][block quotes], [thematic break][thematic breaks],
+[list item][list items], or [HTML block][HTML blocks].</p>
+<p data-sourcepos="716:1-721:40" dir="auto">A <a href="@">setext heading underline</a> is a sequence of
+<code>=</code> characters or a sequence of <code>-</code> characters, with no more than 3
+spaces indentation and any number of trailing spaces. If a line
+containing a single <code>-</code> can be interpreted as an
+empty [list items], it should be interpreted this way
+and not as a [setext heading underline].</p>
+<p data-sourcepos="723:1-727:8" dir="auto">The heading is a level 1 heading if <code>=</code> characters are used in
+the [setext heading underline], and a level 2 heading if <code>-</code>
+characters are used. The contents of the heading are the result
+of parsing the preceding lines of text as CommonMark inline
+content.</p>
+<p data-sourcepos="729:1-732:5" dir="auto">In general, a setext heading need not be preceded or followed by a
+blank line. However, it cannot interrupt a paragraph, so when a
+setext heading comes after a paragraph, a blank line is needed between
+them.</p>
+<p data-sourcepos="734:1-734:16" dir="auto">Simple examples:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="736:1-745:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo *bar*</span>
+<span id="LC2" class="line" lang="plaintext">=========</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">Foo *bar*</span>
+<span id="LC5" class="line" lang="plaintext">---------</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;h1&gt;Foo &lt;em&gt;bar&lt;/em&gt;&lt;/h1&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h2&gt;Foo &lt;em&gt;bar&lt;/em&gt;&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="748:1-748:54" dir="auto">The content of the header may span more than one line:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="750:1-757:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo *bar</span>
+<span id="LC2" class="line" lang="plaintext">baz*</span>
+<span id="LC3" class="line" lang="plaintext">====</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h1&gt;Foo &lt;em&gt;bar</span>
+<span id="LC6" class="line" lang="plaintext">baz&lt;/em&gt;&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="759:1-762:13" dir="auto">The contents are the result of parsing the headings's raw
+content as inlines. The heading's raw content is formed by
+concatenating the lines and removing initial and final
+[whitespace].</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="764:1-771:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> Foo *bar</span>
+<span id="LC2" class="line" lang="plaintext">baz*→</span>
+<span id="LC3" class="line" lang="plaintext">====</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h1&gt;Foo &lt;em&gt;bar</span>
+<span id="LC6" class="line" lang="plaintext">baz&lt;/em&gt;&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="774:1-774:34" dir="auto">The underlining can be any length:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="776:1-785:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">-------------------------</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">Foo</span>
+<span id="LC5" class="line" lang="plaintext">=</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="788:1-789:33" dir="auto">The heading content can be indented up to three spaces, and need
+not line up with the underlining:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="791:1-804:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> Foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> Foo</span>
+<span id="LC5" class="line" lang="plaintext">-----</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext"> Foo</span>
+<span id="LC8" class="line" lang="plaintext"> ===</span>
+<span id="LC9" class="line" lang="plaintext">.</span>
+<span id="LC10" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="807:1-807:31" dir="auto">Four spaces indent is too much:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="809:1-822:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> Foo</span>
+<span id="LC2" class="line" lang="plaintext"> ---</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> Foo</span>
+<span id="LC5" class="line" lang="plaintext">---</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;Foo</span>
+<span id="LC8" class="line" lang="plaintext">---</span>
+<span id="LC9" class="line" lang="plaintext"></span>
+<span id="LC10" class="line" lang="plaintext">Foo</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="825:1-826:25" dir="auto">The setext heading underline can be indented up to three spaces, and
+may have trailing spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="828:1-833:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext"> ---- </span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="836:1-836:24" dir="auto">Four spaces is too much:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="838:1-844:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext"> ---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC5" class="line" lang="plaintext">---&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="847:1-847:60" dir="auto">The setext heading underline cannot contain internal spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="849:1-860:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">= =</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">Foo</span>
+<span id="LC5" class="line" lang="plaintext">--- -</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC8" class="line" lang="plaintext">= =&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="863:1-863:62" dir="auto">Trailing spaces in the content line do not cause a line break:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="865:1-870:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo </span>
+<span id="LC2" class="line" lang="plaintext">-----</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="873:1-873:32" dir="auto">Nor does a backslash at the end:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="875:1-880:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo\</span>
+<span id="LC2" class="line" lang="plaintext">----</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h2&gt;Foo\&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="883:1-884:66" dir="auto">Since indicators of block structure take precedence over
+indicators of inline structure, the following are setext headings:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="886:1-899:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`Foo</span>
+<span id="LC2" class="line" lang="plaintext">----</span>
+<span id="LC3" class="line" lang="plaintext">`</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">&lt;a title="a lot</span>
+<span id="LC6" class="line" lang="plaintext">---</span>
+<span id="LC7" class="line" lang="plaintext">of dashes"/&gt;</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;h2&gt;`Foo&lt;/h2&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;`&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h2&gt;&amp;lt;a title=&amp;quot;a lot&lt;/h2&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;of dashes&amp;quot;/&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="902:1-903:36" dir="auto">The setext heading underline cannot be a [lazy continuation
+line] in a list item or block quote:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="905:1-913:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; Foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="916:1-926:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">===</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC7" class="line" lang="plaintext">bar</span>
+<span id="LC8" class="line" lang="plaintext">===&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="929:1-937:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- Foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;Foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="940:1-942:25" dir="auto">A blank line is needed between a paragraph and a following
+setext heading, since otherwise the paragraph becomes part
+of the heading's content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="944:1-951:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">Bar</span>
+<span id="LC3" class="line" lang="plaintext">---</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h2&gt;Foo</span>
+<span id="LC6" class="line" lang="plaintext">Bar&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="954:1-955:16" dir="auto">But in general a blank line is not required before or after
+setext headings:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="957:1-969:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
+<span id="LC2" class="line" lang="plaintext">Foo</span>
+<span id="LC3" class="line" lang="plaintext">---</span>
+<span id="LC4" class="line" lang="plaintext">Bar</span>
+<span id="LC5" class="line" lang="plaintext">---</span>
+<span id="LC6" class="line" lang="plaintext">Baz</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;h2&gt;Foo&lt;/h2&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;h2&gt;Bar&lt;/h2&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;Baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="972:1-972:32" dir="auto">Setext headings cannot be empty:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="974:1-979:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
+<span id="LC2" class="line" lang="plaintext">====</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;====&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="982:1-984:55" dir="auto">Setext heading text lines must not be interpretable as block
+constructs other than paragraphs. So, the line of dashes
+in these examples gets interpreted as a thematic break:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="986:1-992:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="995:1-1003:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">-----</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1006:1-1013:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1016:1-1024:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">-----</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1027:1-1028:22" dir="auto">If you want a heading with <code>&gt; foo</code> as its literal text, you can
+use backslash escapes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1030:1-1035:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">------</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;h2&gt;&amp;gt; foo&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1038:1-1040:48" dir="auto"><strong>Compatibility note:</strong> Most existing Markdown implementations
+do not allow the text of setext headings to span multiple lines.
+But there is no consensus about how to interpret</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1042:1-1047:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">Foo</span>
+<span id="LC2" class="line" lang="markdown"><span class="gh">bar</span></span>
+<span id="LC3" class="line" lang="markdown"><span class="gh">---</span></span>
+<span id="LC4" class="line" lang="markdown">baz</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1049:1-1049:44" dir="auto">One can find four different interpretations:</p>
+<ol data-sourcepos="1051:1-1055:0" dir="auto">
+<li data-sourcepos="1051:1-1051:50">paragraph "Foo", heading "bar", paragraph "baz"</li>
+<li data-sourcepos="1052:1-1052:55">paragraph "Foo bar", thematic break, paragraph "baz"</li>
+<li data-sourcepos="1053:1-1053:30">paragraph "Foo bar --- baz"</li>
+<li data-sourcepos="1054:1-1055:0">heading "Foo bar", paragraph "baz"</li>
+</ol>
+<p data-sourcepos="1056:1-1059:43" dir="auto">We find interpretation 4 most natural, and interpretation 4
+increases the expressive power of CommonMark, by allowing
+multiline headings. Authors who want interpretation 1 can
+put a blank line after the first paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1061:1-1071:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">---</span>
+<span id="LC5" class="line" lang="plaintext">baz</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h2&gt;bar&lt;/h2&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1074:1-1075:19" dir="auto">Authors who want interpretation 2 can put blank lines around
+the thematic break,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1077:1-1089:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">---</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">baz</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC9" class="line" lang="plaintext">bar&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1092:1-1093:19" dir="auto">or use a thematic break that cannot count as a [setext heading
+underline], such as</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1095:1-1105:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">* * *</span>
+<span id="LC4" class="line" lang="plaintext">baz</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC7" class="line" lang="plaintext">bar&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1108:1-1108:60" dir="auto">Authors who want interpretation 3 can use backslash escapes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1110:1-1120:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">\---</span>
+<span id="LC4" class="line" lang="plaintext">baz</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC7" class="line" lang="plaintext">bar</span>
+<span id="LC8" class="line" lang="plaintext">---</span>
+<span id="LC9" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="1123:1-1123:23" dir="auto">
+<a id="user-content-indented-code-blocks" class="anchor" href="#indented-code-blocks" aria-hidden="true"></a>Indented code blocks</h2>
+<p data-sourcepos="1125:1-1131:44" dir="auto">An <a href="@">indented code block</a> is composed of one or more
+[indented chunks] separated by blank lines.
+An <a href="@">indented chunk</a> is a sequence of non-blank lines,
+each indented four or more spaces. The contents of the code block are
+the literal contents of the lines, including trailing
+[line endings], minus four spaces of indentation.
+An indented code block has no [info string].</p>
+<p data-sourcepos="1133:1-1136:11" dir="auto">An indented code block cannot interrupt a paragraph, so there must be
+a blank line between a paragraph and a following indented code block.
+(A blank line is not needed, however, between a code block and a following
+paragraph.)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1138:1-1145:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> a simple</span>
+<span id="LC2" class="line" lang="plaintext"> indented code block</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;a simple</span>
+<span id="LC5" class="line" lang="plaintext"> indented code block</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1148:1-1150:65" dir="auto">If there is any ambiguity between an interpretation of indentation
+as a code block and as indicating that material belongs to a [list
+item][list items], the list item interpretation takes precedence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1152:1-1163:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1166:1-1179:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> - bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1183:1-1184:12" dir="auto">The contents of a code block are literal text, and do not get parsed
+as Markdown:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1186:1-1197:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &lt;a/&gt;</span>
+<span id="LC2" class="line" lang="plaintext"> *hi*</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> - one</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;a/&amp;gt;</span>
+<span id="LC7" class="line" lang="plaintext">*hi*</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext">- one</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1200:1-1200:51" dir="auto">Here we have three chunks separated by blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1202:1-1219:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> chunk1</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> chunk2</span>
+<span id="LC4" class="line" lang="plaintext"> </span>
+<span id="LC5" class="line" lang="plaintext"> </span>
+<span id="LC6" class="line" lang="plaintext"> </span>
+<span id="LC7" class="line" lang="plaintext"> chunk3</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;chunk1</span>
+<span id="LC10" class="line" lang="plaintext"></span>
+<span id="LC11" class="line" lang="plaintext">chunk2</span>
+<span id="LC12" class="line" lang="plaintext"></span>
+<span id="LC13" class="line" lang="plaintext"></span>
+<span id="LC14" class="line" lang="plaintext"></span>
+<span id="LC15" class="line" lang="plaintext">chunk3</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1222:1-1223:24" dir="auto">Any initial spaces beyond four will be included in the content, even
+in interior blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1225:1-1234:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> chunk1</span>
+<span id="LC2" class="line" lang="plaintext"> </span>
+<span id="LC3" class="line" lang="plaintext"> chunk2</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;chunk1</span>
+<span id="LC6" class="line" lang="plaintext"> </span>
+<span id="LC7" class="line" lang="plaintext"> chunk2</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1237:1-1238:37" dir="auto">An indented code block cannot interrupt a paragraph. (This
+allows hanging indents and the like.)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1240:1-1247:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext"> bar</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC6" class="line" lang="plaintext">bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1250:1-1252:20" dir="auto">However, any non-blank line with fewer than four leading spaces ends
+the code block immediately. So a paragraph may occur immediately
+after indented code:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1254:1-1261:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1264:1-1265:7" dir="auto">And indented code can occur immediately before and after other kinds of
+blocks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1267:1-1282:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># Heading</span>
+<span id="LC2" class="line" lang="plaintext"> foo</span>
+<span id="LC3" class="line" lang="plaintext">Heading</span>
+<span id="LC4" class="line" lang="plaintext">------</span>
+<span id="LC5" class="line" lang="plaintext"> foo</span>
+<span id="LC6" class="line" lang="plaintext">----</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h1&gt;Heading&lt;/h1&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h2&gt;Heading&lt;/h2&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1285:1-1285:53" dir="auto">The first line can be indented more than four spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1287:1-1294:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
+<span id="LC2" class="line" lang="plaintext"> bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; foo</span>
+<span id="LC5" class="line" lang="plaintext">bar</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1297:1-1298:23" dir="auto">Blank lines preceding or following an indented code block
+are not included in it:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1300:1-1309:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
+<span id="LC2" class="line" lang="plaintext"> </span>
+<span id="LC3" class="line" lang="plaintext"> foo</span>
+<span id="LC4" class="line" lang="plaintext"> </span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1312:1-1312:57" dir="auto">Trailing spaces are included in the code block's content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1314:1-1319:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo </span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="1323:1-1323:21" dir="auto">
+<a id="user-content-fenced-code-blocks" class="anchor" href="#fenced-code-blocks" aria-hidden="true"></a>Fenced code blocks</h2>
+<p data-sourcepos="1325:1-1329:61" dir="auto">A <a href="@">code fence</a> is a sequence
+of at least three consecutive backtick characters (<code>`</code>) or
+tildes (<code>~</code>). (Tildes and backticks cannot be mixed.)
+A <a href="@">fenced code block</a>
+begins with a code fence, indented no more than three spaces.</p>
+<p data-sourcepos="1331:1-1337:34" dir="auto">The line with the opening code fence may optionally contain some text
+following the code fence; this is trimmed of leading and trailing
+whitespace and called the <a href="@">info string</a>. If the [info string] comes
+after a backtick fence, it may not contain any backtick
+characters. (The reason for this restriction is that otherwise
+some inline code would be incorrectly interpreted as the
+beginning of a fenced code block.)</p>
+<p data-sourcepos="1339:1-1346:43" dir="auto">The content of the code block consists of all subsequent lines, until
+a closing [code fence] of the same type as the code block
+began with (backticks or tildes), and with at least as many backticks
+or tildes as the opening code fence. If the leading code fence is
+indented N spaces, then up to N spaces of indentation are removed from
+each line of the content (if present). (If a content line is not
+indented, it is preserved unchanged. If it is indented less than N
+spaces, all of the indentation is removed.)</p>
+<p data-sourcepos="1348:1-1356:25" dir="auto">The closing code fence may be indented up to three spaces, and may be
+followed only by spaces, which are ignored. If the end of the
+containing block (or document) is reached and no closing code fence
+has been found, the code block contains all of the lines after the
+opening code fence until the end of the containing block (or
+document). (An alternative spec would require backtracking in the
+event that a closing code fence is not found. But this makes parsing
+much less efficient, and there seems to be no real down side to the
+behavior described here.)</p>
+<p data-sourcepos="1358:1-1359:36" dir="auto">A fenced code block may interrupt a paragraph, and does not require
+a blank line either before or after.</p>
+<p data-sourcepos="1361:1-1365:42" dir="auto">The content of a code fence is treated as literal text, not parsed
+as inlines. The first word of the [info string] is typically used to
+specify the language of the code sample, and rendered in the <code>class</code>
+attribute of the <code>code</code> tag. However, this spec does not mandate any
+particular treatment of the [info string].</p>
+<p data-sourcepos="1367:1-1367:40" dir="auto">Here is a simple example with backticks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1369:1-1378:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">&lt;</span>
+<span id="LC3" class="line" lang="plaintext"> &gt;</span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;</span>
+<span id="LC7" class="line" lang="plaintext"> &amp;gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1381:1-1381:12" dir="auto">With tildes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1383:1-1392:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~</span>
+<span id="LC2" class="line" lang="plaintext">&lt;</span>
+<span id="LC3" class="line" lang="plaintext"> &gt;</span>
+<span id="LC4" class="line" lang="plaintext">~~~</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;</span>
+<span id="LC7" class="line" lang="plaintext"> &amp;gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1394:1-1394:41" dir="auto">Fewer than three backticks is not enough:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1396:1-1402:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">``</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1404:1-1405:6" dir="auto">The closing code fence must use the same character as the opening
+fence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1407:1-1416:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">~~~</span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC7" class="line" lang="plaintext">~~~</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1419:1-1428:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">~~~</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC7" class="line" lang="plaintext">```</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1431:1-1431:69" dir="auto">The closing code fence must be at least as long as the opening fence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1433:1-1442:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">````</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">``````</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC7" class="line" lang="plaintext">```</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1445:1-1454:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~~</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">~~~</span>
+<span id="LC4" class="line" lang="plaintext">~~~~</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC7" class="line" lang="plaintext">~~~</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1457:1-1458:74" dir="auto">Unclosed code blocks are closed by the end of the document
+(or the enclosing [block quote][block quotes] or [list item][list items]):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1460:1-1464:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1467:1-1477:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`````</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">aaa</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;</span>
+<span id="LC7" class="line" lang="plaintext">```</span>
+<span id="LC8" class="line" lang="plaintext">aaa</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1480:1-1491:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; ```</span>
+<span id="LC2" class="line" lang="plaintext">&gt; aaa</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">bbb</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1494:1-1494:53" dir="auto">A code block can have all empty lines as its content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1496:1-1505:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> </span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;</span>
+<span id="LC7" class="line" lang="plaintext"> </span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1508:1-1508:26" dir="auto">A code block can be empty:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1510:1-1515:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">```</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1518:1-1520:11" dir="auto">Fences can be indented. If the opening fence is indented,
+content lines will have equivalent opening indentation removed,
+if present:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1522:1-1531:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ```</span>
+<span id="LC2" class="line" lang="plaintext"> aaa</span>
+<span id="LC3" class="line" lang="plaintext">aaa</span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC7" class="line" lang="plaintext">aaa</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1534:1-1545:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext"> aaa</span>
+<span id="LC4" class="line" lang="plaintext">aaa</span>
+<span id="LC5" class="line" lang="plaintext"> ```</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC8" class="line" lang="plaintext">aaa</span>
+<span id="LC9" class="line" lang="plaintext">aaa</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1548:1-1559:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ```</span>
+<span id="LC2" class="line" lang="plaintext"> aaa</span>
+<span id="LC3" class="line" lang="plaintext"> aaa</span>
+<span id="LC4" class="line" lang="plaintext"> aaa</span>
+<span id="LC5" class="line" lang="plaintext"> ```</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC8" class="line" lang="plaintext"> aaa</span>
+<span id="LC9" class="line" lang="plaintext">aaa</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1562:1-1562:56" dir="auto">Four spaces indentation produces an indented code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1564:1-1573:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ```</span>
+<span id="LC2" class="line" lang="plaintext"> aaa</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;```</span>
+<span id="LC6" class="line" lang="plaintext">aaa</span>
+<span id="LC7" class="line" lang="plaintext">```</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1576:1-1577:41" dir="auto">Closing fences may be indented by 0-3 spaces, and their indentation
+need not match that of the opening fence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1579:1-1586:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1589:1-1596:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1599:1-1599:61" dir="auto">This is not a closing fence, because it is indented 4 spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1601:1-1609:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC6" class="line" lang="plaintext"> ```</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1613:1-1613:65" dir="auto">Code fences (opening and closing) cannot contain internal spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1615:1-1621:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` ```</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt; &lt;/code&gt;</span>
+<span id="LC5" class="line" lang="plaintext">aaa&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1624:1-1632:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~~~~</span>
+<span id="LC2" class="line" lang="plaintext">aaa</span>
+<span id="LC3" class="line" lang="plaintext">~~~ ~~</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC6" class="line" lang="plaintext">~~~ ~~</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1635:1-1636:53" dir="auto">Fenced code blocks can interrupt paragraphs, and can be followed
+directly by paragraphs, without a blank line between:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1638:1-1649:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext">```</span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">baz</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1652:1-1653:34" dir="auto">Other blocks can also occur before and after fenced code blocks
+without an intervening blank line:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1655:1-1667:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">~~~</span>
+<span id="LC4" class="line" lang="plaintext">bar</span>
+<span id="LC5" class="line" lang="plaintext">~~~</span>
+<span id="LC6" class="line" lang="plaintext"># baz</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h2&gt;foo&lt;/h2&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h1&gt;baz&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1670:1-1675:45" dir="auto">An [info string] can be provided after the opening code fence.
+Although this spec doesn't mandate any particular treatment of
+the info string, the first word is typically used to specify
+the language of the code block. In HTML output, the language is
+normally indicated by adding a class to the <code>code</code> element consisting
+of <code>language-</code> followed by the language name.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1677:1-1688:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```ruby</span>
+<span id="LC2" class="line" lang="plaintext">def foo(x)</span>
+<span id="LC3" class="line" lang="plaintext"> return 3</span>
+<span id="LC4" class="line" lang="plaintext">end</span>
+<span id="LC5" class="line" lang="plaintext">```</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-ruby"&gt;def foo(x)</span>
+<span id="LC8" class="line" lang="plaintext"> return 3</span>
+<span id="LC9" class="line" lang="plaintext">end</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1691:1-1702:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~~ ruby startline=3 $%@#$</span>
+<span id="LC2" class="line" lang="plaintext">def foo(x)</span>
+<span id="LC3" class="line" lang="plaintext"> return 3</span>
+<span id="LC4" class="line" lang="plaintext">end</span>
+<span id="LC5" class="line" lang="plaintext">~~~~~~~</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-ruby"&gt;def foo(x)</span>
+<span id="LC8" class="line" lang="plaintext"> return 3</span>
+<span id="LC9" class="line" lang="plaintext">end</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1705:1-1710:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">````;</span>
+<span id="LC2" class="line" lang="plaintext">````</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-;"&gt;&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1713:1-1713:65" dir="auto">[Info strings] for backtick code blocks cannot contain backticks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1715:1-1721:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` aa ```</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;aa&lt;/code&gt;</span>
+<span id="LC5" class="line" lang="plaintext">foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1724:1-1724:70" dir="auto">[Info strings] for tilde code blocks can contain backticks and tildes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1726:1-1733:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~ aa ``` ~~~</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">~~~</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-aa"&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1736:1-1736:47" dir="auto">Closing code fences cannot have [info strings]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1738:1-1745:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">``` aaa</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;``` aaa</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="1749:1-1749:14" dir="auto">
+<a id="user-content-html-blocks" class="anchor" href="#html-blocks" aria-hidden="true"></a>HTML blocks</h2>
+<p data-sourcepos="1751:1-1752:53" dir="auto">An <a href="@">HTML block</a> is a group of lines that is treated
+as raw HTML (and will not be escaped in HTML output).</p>
+<p data-sourcepos="1754:1-1762:50" dir="auto">There are seven kinds of [HTML block], which can be defined by their
+start and end conditions. The block begins with a line that meets a
+<a href="@">start condition</a> (after up to three spaces optional indentation).
+It ends with the first subsequent line that meets a matching <a href="@">end
+condition</a>, or the last line of the document, or the last line of
+the <a href="#container-blocks">container block</a> containing the current HTML
+block, if no line is encountered that meets the [end condition]. If
+the first line meets both the [start condition] and the [end
+condition], the block will contain just that line.</p>
+<ol data-sourcepos="1764:1-1805:0" dir="auto">
+<li data-sourcepos="1764:1-1770:0">
+<p data-sourcepos="1764:5-1769:30"><strong>Start condition:</strong> line begins with the string <code>&lt;script</code>,
+<code>&lt;pre</code>, or <code>&lt;style</code> (case-insensitive), followed by whitespace,
+the string <code>&gt;</code>, or the end of the line.<br>
+<strong>End condition:</strong> line contains an end tag
+<code>&lt;/script&gt;</code>, <code>&lt;/pre&gt;</code>, or <code>&lt;/style&gt;</code> (case-insensitive; it
+need not match the start tag).</p>
+</li>
+<li data-sourcepos="1771:1-1773:0">
+<p data-sourcepos="1771:5-1772:51"><strong>Start condition:</strong> line begins with the string <code>&lt;!--</code>.<br>
+<strong>End condition:</strong> line contains the string <code>--&gt;</code>.</p>
+</li>
+<li data-sourcepos="1774:1-1776:0">
+<p data-sourcepos="1774:5-1775:49"><strong>Start condition:</strong> line begins with the string <code>&lt;?</code>.<br>
+<strong>End condition:</strong> line contains the string <code>?&gt;</code>.</p>
+</li>
+<li data-sourcepos="1777:1-1780:0">
+<p data-sourcepos="1777:5-1779:51"><strong>Start condition:</strong> line begins with the string <code>&lt;!</code>
+followed by an uppercase ASCII letter.<br>
+<strong>End condition:</strong> line contains the character <code>&gt;</code>.</p>
+</li>
+<li data-sourcepos="1781:1-1784:0">
+<p data-sourcepos="1781:5-1783:50"><strong>Start condition:</strong> line begins with the string
+<code>&lt;![CDATA[</code>.<br>
+<strong>End condition:</strong> line contains the string <code>]]&gt;</code>.</p>
+</li>
+<li data-sourcepos="1785:1-1799:0">
+<p data-sourcepos="1785:5-1798:54"><strong>Start condition:</strong> line begins the string <code>&lt;</code> or <code>&lt;/</code>
+followed by one of the strings (case-insensitive) <code>address</code>,
+<code>article</code>, <code>aside</code>, <code>base</code>, <code>basefont</code>, <code>blockquote</code>, <code>body</code>,
+<code>caption</code>, <code>center</code>, <code>col</code>, <code>colgroup</code>, <code>dd</code>, <code>details</code>, <code>dialog</code>,
+<code>dir</code>, <code>div</code>, <code>dl</code>, <code>dt</code>, <code>fieldset</code>, <code>figcaption</code>, <code>figure</code>,
+<code>footer</code>, <code>form</code>, <code>frame</code>, <code>frameset</code>,
+<code>h1</code>, <code>h2</code>, <code>h3</code>, <code>h4</code>, <code>h5</code>, <code>h6</code>, <code>head</code>, <code>header</code>, <code>hr</code>,
+<code>html</code>, <code>iframe</code>, <code>legend</code>, <code>li</code>, <code>link</code>, <code>main</code>, <code>menu</code>, <code>menuitem</code>,
+<code>nav</code>, <code>noframes</code>, <code>ol</code>, <code>optgroup</code>, <code>option</code>, <code>p</code>, <code>param</code>,
+<code>section</code>, <code>summary</code>, <code>table</code>, <code>tbody</code>, <code>td</code>,
+<code>tfoot</code>, <code>th</code>, <code>thead</code>, <code>title</code>, <code>tr</code>, <code>track</code>, <code>ul</code>, followed
+by [whitespace], the end of the line, the string <code>&gt;</code>, or
+the string <code>/&gt;</code>.<br>
+<strong>End condition:</strong> line is followed by a [blank line].</p>
+</li>
+<li data-sourcepos="1800:1-1805:0">
+<p data-sourcepos="1800:5-1804:54"><strong>Start condition:</strong> line begins with a complete [open tag]
+(with any [tag name] other than <code>script</code>,
+<code>style</code>, or <code>pre</code>) or a complete [closing tag],
+followed only by [whitespace] or the end of the line.<br>
+<strong>End condition:</strong> line is followed by a [blank line].</p>
+</li>
+</ol>
+<p data-sourcepos="1806:1-1811:19" dir="auto">HTML blocks continue until they are closed by their appropriate
+[end condition], or the last line of the document or other <a href="#container-blocks">container
+block</a>. This means any HTML <strong>within an HTML
+block</strong> that might otherwise be recognised as a start condition will
+be ignored by the parser and passed through as-is, without changing
+the parser's state.</p>
+<p data-sourcepos="1813:1-1815:51" dir="auto">For instance, <code>&lt;pre&gt;</code> within a HTML block started by <code>&lt;table&gt;</code> will not affect
+the parser state; as the HTML block was started in by start condition 6, it
+will end at any blank line. This can be surprising:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1817:1-1832:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;table&gt;&lt;tr&gt;&lt;td&gt;</span>
+<span id="LC2" class="line" lang="plaintext">&lt;pre&gt;</span>
+<span id="LC3" class="line" lang="plaintext">**Hello**,</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">_world_.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;table&gt;&lt;tr&gt;&lt;td&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">**Hello**,</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;world&lt;/em&gt;.</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/pre&gt;&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1834:1-1836:55" dir="auto">In this case, the HTML block is terminated by the newline — the <code>**Hello**</code>
+text remains verbatim — and regular parsing resumes, with a paragraph,
+emphasised <code>world</code> and inline and block HTML following.</p>
+<p data-sourcepos="1838:1-1841:65" dir="auto">All types of [HTML blocks] except type 7 may interrupt
+a paragraph. Blocks of type 7 may not interrupt a paragraph.
+(This restriction is intended to prevent unwanted interpretation
+of long tags inside a wrapped paragraph as starting HTML blocks.)</p>
+<p data-sourcepos="1843:1-1844:10" dir="auto">Some simple examples follow. Here are some basic HTML blocks
+of type 6:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1846:1-1865:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC2" class="line" lang="plaintext"> &lt;tr&gt;</span>
+<span id="LC3" class="line" lang="plaintext"> &lt;td&gt;</span>
+<span id="LC4" class="line" lang="plaintext"> hi</span>
+<span id="LC5" class="line" lang="plaintext"> &lt;/td&gt;</span>
+<span id="LC6" class="line" lang="plaintext"> &lt;/tr&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext">okay.</span>
+<span id="LC10" class="line" lang="plaintext">.</span>
+<span id="LC11" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC12" class="line" lang="plaintext"> &lt;tr&gt;</span>
+<span id="LC13" class="line" lang="plaintext"> &lt;td&gt;</span>
+<span id="LC14" class="line" lang="plaintext"> hi</span>
+<span id="LC15" class="line" lang="plaintext"> &lt;/td&gt;</span>
+<span id="LC16" class="line" lang="plaintext"> &lt;/tr&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;p&gt;okay.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1868:1-1876:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext"> *hello*</span>
+<span id="LC3" class="line" lang="plaintext"> &lt;foo&gt;&lt;a&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext"> &lt;div&gt;</span>
+<span id="LC6" class="line" lang="plaintext"> *hello*</span>
+<span id="LC7" class="line" lang="plaintext"> &lt;foo&gt;&lt;a&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1879:1-1879:42" dir="auto">A block can also start with a closing tag:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1881:1-1887:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC5" class="line" lang="plaintext">*foo*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1890:1-1890:68" dir="auto">Here we have two HTML blocks with a Markdown paragraph between them:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1892:1-1902:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;DIV CLASS="foo"&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">*Markdown*</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">&lt;/DIV&gt;</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;DIV CLASS="foo"&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;Markdown&lt;/em&gt;&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/DIV&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1905:1-1906:47" dir="auto">The tag on the first line can be partial, as long
+as it is split where there would be whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1908:1-1916:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div id="foo"</span>
+<span id="LC2" class="line" lang="plaintext"> class="bar"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;div id="foo"</span>
+<span id="LC6" class="line" lang="plaintext"> class="bar"&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1919:1-1927:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div id="foo" class="bar</span>
+<span id="LC2" class="line" lang="plaintext"> baz"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;div id="foo" class="bar</span>
+<span id="LC6" class="line" lang="plaintext"> baz"&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1930:1-1930:31" dir="auto">An open tag need not be closed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1931:1-1940:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">*bar*</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC7" class="line" lang="plaintext">*foo*</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1944:1-1945:17" dir="auto">A partial tag need not even be completed (garbage
+in, garbage out):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1947:1-1953:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div id="foo"</span>
+<span id="LC2" class="line" lang="plaintext">*hi*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;div id="foo"</span>
+<span id="LC5" class="line" lang="plaintext">*hi*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1956:1-1962:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div class</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;div class</span>
+<span id="LC5" class="line" lang="plaintext">foo</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1965:1-1966:35" dir="auto">The initial tag doesn't even need to be a valid
+tag, as long as it starts like one:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1968:1-1974:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div *???-&amp;&amp;&amp;-&lt;---</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;div *???-&amp;&amp;&amp;-&lt;---</span>
+<span id="LC5" class="line" lang="plaintext">*foo*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1977:1-1978:7" dir="auto">In type 6 blocks, the initial tag need not be on a line by
+itself:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1980:1-1984:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;&lt;a href="bar"&gt;*foo*&lt;/a&gt;&lt;/div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;div&gt;&lt;a href="bar"&gt;*foo*&lt;/a&gt;&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="1987:1-1995:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;table&gt;&lt;tr&gt;&lt;td&gt;</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;table&gt;&lt;tr&gt;&lt;td&gt;</span>
+<span id="LC6" class="line" lang="plaintext">foo</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="1998:1-2002:43" dir="auto">Everything until the next blank line or end of document
+gets included in the HTML block. So, in the following
+example, what looks like a Markdown code block
+is actually part of the HTML block, which continues until a blank
+line or the end of the document is reached:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2004:1-2014:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;&lt;/div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">``` c</span>
+<span id="LC3" class="line" lang="plaintext">int x = 33;</span>
+<span id="LC4" class="line" lang="plaintext">```</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;div&gt;&lt;/div&gt;</span>
+<span id="LC7" class="line" lang="plaintext">``` c</span>
+<span id="LC8" class="line" lang="plaintext">int x = 33;</span>
+<span id="LC9" class="line" lang="plaintext">```</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2017:1-2019:51" dir="auto">To start an [HTML block] with a tag that is <em>not</em> in the
+list of block-level tags in (6), you must put the tag by
+itself on the first line (and it must be complete):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2021:1-2029:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="foo"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*bar*</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/a&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;a href="foo"&gt;</span>
+<span id="LC6" class="line" lang="plaintext">*bar*</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/a&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2032:1-2032:49" dir="auto">In type 7 blocks, the [tag name] can be anything:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2034:1-2042:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;Warning&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*bar*</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/Warning&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;Warning&gt;</span>
+<span id="LC6" class="line" lang="plaintext">*bar*</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/Warning&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2045:1-2053:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;i class="foo"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*bar*</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/i&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;i class="foo"&gt;</span>
+<span id="LC6" class="line" lang="plaintext">*bar*</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/i&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2056:1-2062:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;/ins&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*bar*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/ins&gt;</span>
+<span id="LC5" class="line" lang="plaintext">*bar*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2065:1-2069:59" dir="auto">These rules are designed to allow us to work with tags that
+can function as either block-level or inline-level tags.
+The <code>&lt;del&gt;</code> tag is a nice example. We can surround content with
+<code>&lt;del&gt;</code> tags in three different ways. In this case, we get a raw
+HTML block, because the <code>&lt;del&gt;</code> tag is on a line by itself:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2071:1-2079:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;del&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/del&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;del&gt;</span>
+<span id="LC6" class="line" lang="plaintext">*foo*</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/del&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2082:1-2084:54" dir="auto">In this case, we get a raw HTML block that just includes
+the <code>&lt;del&gt;</code> tag (because it ends with the following blank
+line). So the contents get interpreted as CommonMark:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2086:1-2096:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;del&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">*foo*</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">&lt;/del&gt;</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;del&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/del&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2099:1-2102:29" dir="auto">Finally, in this case, the <code>&lt;del&gt;</code> tags are interpreted
+as [raw HTML] <em>inside</em> the CommonMark paragraph. (Because
+the tag is not on a line by itself, we get inline HTML
+rather than an [HTML block].)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2104:1-2108:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;del&gt;*foo*&lt;/del&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;del&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2111:1-2116:50" dir="auto">HTML tags designed to contain literal content
+(<code>script</code>, <code>style</code>, <code>pre</code>), comments, processing instructions,
+and declarations are treated somewhat differently.
+Instead of ending at the first blank line, these blocks
+end at the first line containing a corresponding end tag.
+As a result, these blocks can contain blank lines:</p>
+<p data-sourcepos="2118:1-2118:19" dir="auto">A pre tag (type 1):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2120:1-2136:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;pre language="haskell"&gt;&lt;code&gt;</span>
+<span id="LC2" class="line" lang="plaintext">import Text.HTML.TagSoup</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">main :: IO ()</span>
+<span id="LC5" class="line" lang="plaintext">main = print $ parseTags tags</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">okay</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre language="haskell"&gt;&lt;code&gt;</span>
+<span id="LC10" class="line" lang="plaintext">import Text.HTML.TagSoup</span>
+<span id="LC11" class="line" lang="plaintext"></span>
+<span id="LC12" class="line" lang="plaintext">main :: IO ()</span>
+<span id="LC13" class="line" lang="plaintext">main = print $ parseTags tags</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2139:1-2139:22" dir="auto">A script tag (type 1):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2141:1-2155:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;script type="text/javascript"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">// JavaScript example</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">document.getElementById("demo").innerHTML = "Hello JavaScript!";</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/script&gt;</span>
+<span id="LC6" class="line" lang="plaintext">okay</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;script type="text/javascript"&gt;</span>
+<span id="LC9" class="line" lang="plaintext">// JavaScript example</span>
+<span id="LC10" class="line" lang="plaintext"></span>
+<span id="LC11" class="line" lang="plaintext">document.getElementById("demo").innerHTML = "Hello JavaScript!";</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/script&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2158:1-2158:21" dir="auto">A style tag (type 1):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2160:1-2176:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;style</span>
+<span id="LC2" class="line" lang="plaintext"> type="text/css"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">h1 {color:red;}</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">p {color:blue;}</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/style&gt;</span>
+<span id="LC7" class="line" lang="plaintext">okay</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;style</span>
+<span id="LC10" class="line" lang="plaintext"> type="text/css"&gt;</span>
+<span id="LC11" class="line" lang="plaintext">h1 {color:red;}</span>
+<span id="LC12" class="line" lang="plaintext"></span>
+<span id="LC13" class="line" lang="plaintext">p {color:blue;}</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/style&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2179:1-2181:28" dir="auto">If there is no matching end tag, the block will end at the
+end of the document (or the enclosing [block quote][block quotes]
+or [list item][list items]):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2183:1-2193:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;style</span>
+<span id="LC2" class="line" lang="plaintext"> type="text/css"&gt;</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">foo</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;style</span>
+<span id="LC7" class="line" lang="plaintext"> type="text/css"&gt;</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext">foo</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2196:1-2207:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; &lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">bar</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC8" class="line" lang="plaintext">foo</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2210:1-2220:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- &lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">- foo</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2223:1-2223:56" dir="auto">The end tag can occur on the same line as the start tag:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2225:1-2231:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;style&gt;p{color:red;}&lt;/style&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;style&gt;p{color:red;}&lt;/style&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2234:1-2240:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;!-- foo --&gt;*bar*</span>
+<span id="LC2" class="line" lang="plaintext">*baz*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;!-- foo --&gt;*bar*</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2243:1-2244:45" dir="auto">Note that anything on the last line after the
+end tag will be included in the [HTML block]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2246:1-2254:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;script&gt;</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/script&gt;1. *bar*</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;script&gt;</span>
+<span id="LC6" class="line" lang="plaintext">foo</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/script&gt;1. *bar*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2257:1-2257:19" dir="auto">A comment (type 2):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2259:1-2271:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;!-- Foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext"> baz --&gt;</span>
+<span id="LC5" class="line" lang="plaintext">okay</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;!-- Foo</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext">bar</span>
+<span id="LC10" class="line" lang="plaintext"> baz --&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2275:1-2275:34" dir="auto">A processing instruction (type 3):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2277:1-2291:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;?php</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> echo '&gt;';</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">?&gt;</span>
+<span id="LC6" class="line" lang="plaintext">okay</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;?php</span>
+<span id="LC9" class="line" lang="plaintext"></span>
+<span id="LC10" class="line" lang="plaintext"> echo '&gt;';</span>
+<span id="LC11" class="line" lang="plaintext"></span>
+<span id="LC12" class="line" lang="plaintext">?&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2294:1-2294:23" dir="auto">A declaration (type 4):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2296:1-2300:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;!DOCTYPE html&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;!DOCTYPE html&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2303:1-2303:15" dir="auto">CDATA (type 5):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2305:1-2333:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;![CDATA[</span>
+<span id="LC2" class="line" lang="plaintext">function matchwo(a,b)</span>
+<span id="LC3" class="line" lang="plaintext">{</span>
+<span id="LC4" class="line" lang="plaintext"> if (a &lt; b &amp;&amp; a &lt; 0) then {</span>
+<span id="LC5" class="line" lang="plaintext"> return 1;</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext"> } else {</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext"> return 0;</span>
+<span id="LC10" class="line" lang="plaintext"> }</span>
+<span id="LC11" class="line" lang="plaintext">}</span>
+<span id="LC12" class="line" lang="plaintext">]]&gt;</span>
+<span id="LC13" class="line" lang="plaintext">okay</span>
+<span id="LC14" class="line" lang="plaintext">.</span>
+<span id="LC15" class="line" lang="plaintext">&lt;![CDATA[</span>
+<span id="LC16" class="line" lang="plaintext">function matchwo(a,b)</span>
+<span id="LC17" class="line" lang="plaintext">{</span>
+<span id="LC18" class="line" lang="plaintext"> if (a &lt; b &amp;&amp; a &lt; 0) then {</span>
+<span id="LC19" class="line" lang="plaintext"> return 1;</span>
+<span id="LC20" class="line" lang="plaintext"></span>
+<span id="LC21" class="line" lang="plaintext"> } else {</span>
+<span id="LC22" class="line" lang="plaintext"></span>
+<span id="LC23" class="line" lang="plaintext"> return 0;</span>
+<span id="LC24" class="line" lang="plaintext"> }</span>
+<span id="LC25" class="line" lang="plaintext">}</span>
+<span id="LC26" class="line" lang="plaintext">]]&gt;</span>
+<span id="LC27" class="line" lang="plaintext">&lt;p&gt;okay&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2336:1-2336:54" dir="auto">The opening tag can be indented 1-3 spaces, but not 4:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2338:1-2346:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &lt;!-- foo --&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> &lt;!-- foo --&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext"> &lt;!-- foo --&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;!-- foo --&amp;gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2349:1-2357:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> &lt;div&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext"> &lt;div&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;div&amp;gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2360:1-2361:25" dir="auto">An HTML block of types 1--6 can interrupt a paragraph, and need not be
+preceded by a blank line.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2363:1-2373:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC8" class="line" lang="plaintext">bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2376:1-2378:7" dir="auto">However, a following blank line is needed, except at the end of
+a document, and except for blocks of types 1--5, [above][HTML
+block]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2380:1-2390:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC4" class="line" lang="plaintext">*foo*</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC7" class="line" lang="plaintext">bar</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC9" class="line" lang="plaintext">*foo*</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2393:1-2393:51" dir="auto">HTML blocks of type 7 cannot interrupt a paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2395:1-2403:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">&lt;a href="bar"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;a href="bar"&gt;</span>
+<span id="LC7" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2406:1-2407:26" dir="auto">This rule differs from John Gruber's original Markdown syntax
+specification, which says:</p>
+<blockquote data-sourcepos="2409:1-2412:51" dir="auto">
+<p data-sourcepos="2409:3-2412:51">The only restrictions are that block-level HTML elements —
+e.g. <code>&lt;div&gt;</code>, <code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. — must be separated from
+surrounding content by blank lines, and the start and end tags of the
+block should not be indented with tabs or spaces.</p>
+</blockquote>
+<p data-sourcepos="2414:1-2415:5" dir="auto">In some ways Gruber's rule is more restrictive than the one given
+here:</p>
+<ul data-sourcepos="2417:1-2421:0" dir="auto">
+<li data-sourcepos="2417:1-2417:61">It requires that an HTML block be preceded by a blank line.</li>
+<li data-sourcepos="2418:1-2418:49">It does not allow the start tag to be indented.</li>
+<li data-sourcepos="2419:1-2421:0">It requires a matching end tag, which it also does not allow to
+be indented.</li>
+</ul>
+<p data-sourcepos="2422:1-2423:34" dir="auto">Most Markdown implementations (including some of Gruber's own) do not
+respect all of these restrictions.</p>
+<p data-sourcepos="2425:1-2432:61" dir="auto">There is one respect, however, in which Gruber's rule is more liberal
+than the one given here, since it allows blank lines to occur inside
+an HTML block. There are two reasons for disallowing them here.
+First, it removes the need to parse balanced tags, which is
+expensive and can require backtracking from the end of the document
+if no matching end tag is found. Second, it provides a very simple
+and flexible way of including Markdown content inside HTML tags:
+simply separate the Markdown from the HTML using blank lines:</p>
+<p data-sourcepos="2434:1-2434:8" dir="auto">Compare:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2436:1-2446:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">*Emphasized* text.</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;Emphasized&lt;/em&gt; text.&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2449:1-2457:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC2" class="line" lang="plaintext">*Emphasized* text.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;/div&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;div&gt;</span>
+<span id="LC6" class="line" lang="plaintext">*Emphasized* text.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/div&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2460:1-2464:22" dir="auto">Some Markdown implementations have adopted a convention of
+interpreting content inside tags as text if the open tag has
+the attribute <code>markdown=1</code>. The rule given above seems a simpler and
+more elegant way of achieving the same expressive power, which is also
+much simpler to parse.</p>
+<p data-sourcepos="2466:1-2469:59" dir="auto">The main potential drawback is that one can no longer paste HTML
+blocks into Markdown documents with 100% reliability. However,
+<em>in most cases</em> this will work fine, because the blank lines in
+HTML are usually followed by HTML block tags. For example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2471:1-2491:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">&lt;td&gt;</span>
+<span id="LC6" class="line" lang="plaintext">Hi</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/td&gt;</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC10" class="line" lang="plaintext"></span>
+<span id="LC11" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC12" class="line" lang="plaintext">.</span>
+<span id="LC13" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;td&gt;</span>
+<span id="LC16" class="line" lang="plaintext">Hi</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/td&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2494:1-2496:23" dir="auto">There are problems, however, if the inner tags are indented
+<em>and</em> separated by spaces, as then they will be interpreted as
+an indented code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2498:1-2519:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> &lt;tr&gt;</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> &lt;td&gt;</span>
+<span id="LC6" class="line" lang="plaintext"> Hi</span>
+<span id="LC7" class="line" lang="plaintext"> &lt;/td&gt;</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext"> &lt;/tr&gt;</span>
+<span id="LC10" class="line" lang="plaintext"></span>
+<span id="LC11" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC12" class="line" lang="plaintext">.</span>
+<span id="LC13" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC14" class="line" lang="plaintext"> &lt;tr&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;lt;td&amp;gt;</span>
+<span id="LC16" class="line" lang="plaintext"> Hi</span>
+<span id="LC17" class="line" lang="plaintext">&amp;lt;/td&amp;gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC19" class="line" lang="plaintext"> &lt;/tr&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2522:1-2525:26" dir="auto">Fortunately, blank lines are usually not necessary and can be
+deleted. The exception is inside <code>&lt;pre&gt;</code> tags, but as described
+[above][HTML blocks], raw HTML blocks starting with <code>&lt;pre&gt;</code>
+<em>can</em> contain blank lines.</p>
+<h2 data-sourcepos="2527:1-2527:29" dir="auto">
+<a id="user-content-link-reference-definitions" class="anchor" href="#link-reference-definitions" aria-hidden="true"></a>Link reference definitions</h2>
+<p data-sourcepos="2529:1-2537:61" dir="auto">A <a href="@">link reference definition</a>
+consists of a [link label], indented up to three spaces, followed
+by a colon (<code>:</code>), optional [whitespace] (including up to one
+[line ending]), a [link destination],
+optional [whitespace] (including up to one
+[line ending]), and an optional [link
+title], which if it is present must be separated
+from the [link destination] by [whitespace].
+No further [non-whitespace characters] may occur on the line.</p>
+<p data-sourcepos="2539:1-2544:5" dir="auto">A [link reference definition]
+does not correspond to a structural element of a document. Instead, it
+defines a label which can be used in [reference links]
+and reference-style [images] elsewhere in the document. [Link
+reference definitions] can come either before or after the links that use
+them.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2546:1-2552:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2555:1-2563:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [foo]: </span>
+<span id="LC2" class="line" lang="plaintext"> /url </span>
+<span id="LC3" class="line" lang="plaintext"> 'the title' </span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[foo]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="the title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2566:1-2572:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Foo*bar\]]:my_(url) 'title (with parens)'</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[Foo*bar\]]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="my_(url)" title="title (with parens)"&gt;Foo*bar]&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2575:1-2583:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Foo bar]:</span>
+<span id="LC2" class="line" lang="plaintext">&lt;my url&gt;</span>
+<span id="LC3" class="line" lang="plaintext">'title'</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[Foo bar]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="my%20url" title="title"&gt;Foo bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2586:1-2586:41" dir="auto">The title may extend over multiple lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2588:1-2602:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url '</span>
+<span id="LC2" class="line" lang="plaintext">title</span>
+<span id="LC3" class="line" lang="plaintext">line1</span>
+<span id="LC4" class="line" lang="plaintext">line2</span>
+<span id="LC5" class="line" lang="plaintext">'</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext">[foo]</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="</span>
+<span id="LC10" class="line" lang="plaintext">title</span>
+<span id="LC11" class="line" lang="plaintext">line1</span>
+<span id="LC12" class="line" lang="plaintext">line2</span>
+<span id="LC13" class="line" lang="plaintext">"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2605:1-2605:43" dir="auto">However, it may not contain a [blank line]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2607:1-2617:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url 'title</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">with blank line'</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[foo]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;[foo]: /url 'title&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;with blank line'&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2620:1-2620:25" dir="auto">The title may be omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2622:1-2629:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]:</span>
+<span id="LC2" class="line" lang="plaintext">/url</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[foo]</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2632:1-2632:40" dir="auto">The link destination may not be omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2634:1-2641:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]:</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo]:&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2643:2-2644:16" dir="auto">However, an empty link destination may be specified using
+angle brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2646:1-2652:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: &lt;&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href=""&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2654:1-2655:11" dir="auto">The title must be separated from the link destination by
+whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2657:1-2664:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: &lt;bar&gt;(baz)</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo]: &lt;bar&gt;(baz)&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2667:1-2668:24" dir="auto">Both title and destination can contain backslash escapes
+and literal backslashes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2670:1-2676:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url\bar\*baz "foo\"bar\baz"</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url%5Cbar*baz" title="foo&amp;quot;bar\baz"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2679:1-2679:52" dir="auto">A link can come before its corresponding definition:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2681:1-2687:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2690:1-2691:11" dir="auto">If there are several matching definitions, the first one takes
+precedence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2693:1-2700:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: first</span>
+<span id="LC4" class="line" lang="plaintext">[foo]: second</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="first"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2703:1-2704:33" dir="auto">As noted in the section on [Links], matching of labels is
+case-insensitive (see [matches]).</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2706:1-2712:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[FOO]: /url</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[Foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;Foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2715:1-2721:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[ΑΓΩ]: /φου</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[αγω]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/%CF%86%CE%BF%CF%85"&gt;αγω&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2724:1-2725:39" dir="auto">Here is a link reference definition with no corresponding link.
+It contributes nothing to the document.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2727:1-2730:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC2" class="line" lang="plaintext">.</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2733:1-2733:20" dir="auto">Here is another one:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2735:1-2742:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">]: /url</span>
+<span id="LC4" class="line" lang="plaintext">bar</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2745:1-2746:44" dir="auto">This is not a link reference definition, because there are
+[non-whitespace characters] after the title:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2748:1-2752:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title" ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo]: /url &amp;quot;title&amp;quot; ok&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2755:1-2755:57" dir="auto">This is a link reference definition, but it has no title:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2757:1-2762:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC2" class="line" lang="plaintext">"title" ok</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&amp;quot;title&amp;quot; ok&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2765:1-2766:12" dir="auto">This is not a link reference definition, because it is indented
+four spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2768:1-2776:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [foo]: /url "title"</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;[foo]: /url &amp;quot;title&amp;quot;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2779:1-2780:13" dir="auto">This is not a link reference definition, because it occurs inside
+a code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2782:1-2792:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
+<span id="LC2" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[foo]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;[foo]: /url</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2795:1-2795:59" dir="auto">A [link reference definition] cannot interrupt a paragraph.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2797:1-2806:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">[bar]: /baz</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[bar]</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;Foo</span>
+<span id="LC7" class="line" lang="plaintext">[bar]: /baz&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;[bar]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2809:1-2810:65" dir="auto">However, it can directly follow other block elements, such as headings
+and thematic breaks, and it need not be followed by a blank line.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2812:1-2821:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># [Foo]</span>
+<span id="LC2" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC3" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;h1&gt;&lt;a href="/url"&gt;Foo&lt;/a&gt;&lt;/h1&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2823:1-2831:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">===</span>
+<span id="LC4" class="line" lang="plaintext">[foo]</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;bar&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2833:1-2840:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC2" class="line" lang="plaintext">===</span>
+<span id="LC3" class="line" lang="plaintext">[foo]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;===</span>
+<span id="LC6" class="line" lang="plaintext">&lt;a href="/url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2843:1-2844:61" dir="auto">Several [link reference definitions]
+can occur one after another, without intervening blank lines.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2846:1-2859:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /foo-url "foo"</span>
+<span id="LC2" class="line" lang="plaintext">[bar]: /bar-url</span>
+<span id="LC3" class="line" lang="plaintext"> "bar"</span>
+<span id="LC4" class="line" lang="plaintext">[baz]: /baz-url</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">[foo],</span>
+<span id="LC7" class="line" lang="plaintext">[bar],</span>
+<span id="LC8" class="line" lang="plaintext">[baz]</span>
+<span id="LC9" class="line" lang="plaintext">.</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/foo-url" title="foo"&gt;foo&lt;/a&gt;,</span>
+<span id="LC11" class="line" lang="plaintext">&lt;a href="/bar-url" title="bar"&gt;bar&lt;/a&gt;,</span>
+<span id="LC12" class="line" lang="plaintext">&lt;a href="/baz-url"&gt;baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2862:1-2865:12" dir="auto">[Link reference definitions] can occur
+inside block containers, like lists and block quotations. They
+affect the entire document, not just the container in which they
+are defined:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2867:1-2875:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">&gt; [foo]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2878:1-2882:19" dir="auto">Whether something is a [link reference definition] is
+independent of whether the link reference it defines is
+used in the document. Thus, for example, the following
+document contains just a link reference definition, and
+no visible content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2884:1-2887:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC2" class="line" lang="plaintext">.</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="2890:1-2890:13" dir="auto">
+<a id="user-content-paragraphs" class="anchor" href="#paragraphs" aria-hidden="true"></a>Paragraphs</h2>
+<p data-sourcepos="2892:1-2897:13" dir="auto">A sequence of non-blank lines that cannot be interpreted as other
+kinds of blocks forms a <a href="@">paragraph</a>.
+The contents of the paragraph are the result of parsing the
+paragraph's raw content as inlines. The paragraph's raw content
+is formed by concatenating the lines and removing initial and final
+[whitespace].</p>
+<p data-sourcepos="2899:1-2899:37" dir="auto">A simple example with two paragraphs:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2901:1-2908:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">bbb</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;aaa&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2911:1-2911:58" dir="auto">Paragraphs can contain multiple lines, but no blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2913:1-2924:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
+<span id="LC2" class="line" lang="plaintext">bbb</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">ccc</span>
+<span id="LC5" class="line" lang="plaintext">ddd</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;aaa</span>
+<span id="LC8" class="line" lang="plaintext">bbb&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;ccc</span>
+<span id="LC10" class="line" lang="plaintext">ddd&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2927:1-2927:54" dir="auto">Multiple blank lines between paragraph have no effect:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2929:1-2937:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">bbb</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;aaa&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2940:1-2940:27" dir="auto">Leading spaces are skipped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2942:1-2948:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> aaa</span>
+<span id="LC2" class="line" lang="plaintext"> bbb</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;aaa</span>
+<span id="LC5" class="line" lang="plaintext">bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2951:1-2952:40" dir="auto">Lines after the first may be indented any amount, since indented
+code blocks cannot interrupt paragraphs.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2954:1-2962:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
+<span id="LC2" class="line" lang="plaintext"> bbb</span>
+<span id="LC3" class="line" lang="plaintext"> ccc</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;aaa</span>
+<span id="LC6" class="line" lang="plaintext">bbb</span>
+<span id="LC7" class="line" lang="plaintext">ccc&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2965:1-2966:44" dir="auto">However, the first line may be indented at most three spaces,
+or an indented code block will be triggered:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2968:1-2974:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> aaa</span>
+<span id="LC2" class="line" lang="plaintext">bbb</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;aaa</span>
+<span id="LC5" class="line" lang="plaintext">bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2977:1-2984:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> aaa</span>
+<span id="LC2" class="line" lang="plaintext">bbb</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;aaa</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="2987:1-2989:7" dir="auto">Final spaces are stripped before inline parsing, so a paragraph
+that ends with two or more spaces will not end with a [hard line
+break]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="2991:1-2997:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa </span>
+<span id="LC2" class="line" lang="plaintext">bbb </span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;aaa&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bbb&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="3000:1-3000:14" dir="auto">
+<a id="user-content-blank-lines" class="anchor" href="#blank-lines" aria-hidden="true"></a>Blank lines</h2>
+<p data-sourcepos="3002:1-3004:22" dir="auto">[Blank lines] between block-level elements are ignored,
+except for the role they play in determining whether a [list]
+is [tight] or [loose].</p>
+<p data-sourcepos="3006:1-3006:70" dir="auto">Blank lines at the beginning and end of the document are also ignored.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3008:1-3020:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> </span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">aaa</span>
+<span id="LC4" class="line" lang="plaintext"> </span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"># aaa</span>
+<span id="LC7" class="line" lang="plaintext"></span>
+<span id="LC8" class="line" lang="plaintext"> </span>
+<span id="LC9" class="line" lang="plaintext">.</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;aaa&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h1&gt;aaa&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div>
+<h2 data-sourcepos="3024:1-3024:21">
+<a id="user-content-tables-extension" class="anchor" href="#tables-extension" aria-hidden="true"></a>Tables (extension)</h2>
+<p data-sourcepos="3026:1-3027:10">GFM enables the <code>table</code> extension, where an additional leaf block type is
+available.</p>
+<p data-sourcepos="3029:1-3031:23">A <a href="@">table</a> is an arrangement of data with rows and columns, consisting of a
+single header row, a [delimiter row] separating the header from the data, and
+zero or more data rows.</p>
+<p data-sourcepos="3033:1-3037:23">Each row consists of cells containing arbitrary text, in which [inlines] are
+parsed, separated by pipes (<code>|</code>). A leading and trailing pipe is also
+recommended for clarity of reading, and if there's otherwise parsing ambiguity.
+Spaces between pipes and cell content are trimmed. Block-level elements cannot
+be inserted in a table.</p>
+<p data-sourcepos="3039:1-3041:40">The <a href="@">delimiter row</a> consists of cells whose only content are hyphens (<code>-</code>),
+and optionally, a leading or trailing colon (<code>:</code>), or both, to indicate left,
+right, or center alignment respectively.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3043:1-3062:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| foo | bar |</span>
+<span id="LC2" class="line" lang="plaintext">| --- | --- |</span>
+<span id="LC3" class="line" lang="plaintext">| baz | bim |</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;th&gt;foo&lt;/th&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;th&gt;bar&lt;/th&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;td&gt;baz&lt;/td&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;td&gt;bim&lt;/td&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3064:1-3065:74">Cells in one column don't need to match length, though it's easier to read if
+they are. Likewise, use of leading and trailing pipes may be inconsistent:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3067:1-3086:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | defghi |</span>
+<span id="LC2" class="line" lang="plaintext">:-: | -----------:</span>
+<span id="LC3" class="line" lang="plaintext">bar | baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;th align="center"&gt;abc&lt;/th&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;th align="right"&gt;defghi&lt;/th&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;td align="center"&gt;bar&lt;/td&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;td align="right"&gt;baz&lt;/td&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3088:1-3089:13">Include a pipe in a cell's content by escaping it, including inside other
+inline spans:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3091:1-3112:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| f\|oo |</span>
+<span id="LC2" class="line" lang="plaintext">| ------ |</span>
+<span id="LC3" class="line" lang="plaintext">| b `\|` az |</span>
+<span id="LC4" class="line" lang="plaintext">| b **\|** im |</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;th&gt;f|oo&lt;/th&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;td&gt;b &lt;code&gt;|&lt;/code&gt; az&lt;/td&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;td&gt;b &lt;strong&gt;|&lt;/strong&gt; im&lt;/td&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3114:1-3115:22">The table is broken at the first empty line, or beginning of another
+block-level structure:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3117:1-3140:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | def |</span>
+<span id="LC2" class="line" lang="plaintext">| --- | --- |</span>
+<span id="LC3" class="line" lang="plaintext">| bar | baz |</span>
+<span id="LC4" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;th&gt;abc&lt;/th&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;th&gt;def&lt;/th&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;td&gt;bar&lt;/td&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;td&gt;baz&lt;/td&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC22" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3142:1-3169:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | def |</span>
+<span id="LC2" class="line" lang="plaintext">| --- | --- |</span>
+<span id="LC3" class="line" lang="plaintext">| bar | baz |</span>
+<span id="LC4" class="line" lang="plaintext">bar</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">bar</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;th&gt;abc&lt;/th&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;th&gt;def&lt;/th&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;td&gt;bar&lt;/td&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;td&gt;baz&lt;/td&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;td&gt;bar&lt;/td&gt;</span>
+<span id="LC22" class="line" lang="plaintext">&lt;td&gt;&lt;/td&gt;</span>
+<span id="LC23" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC24" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC25" class="line" lang="plaintext">&lt;/table&gt;</span>
+<span id="LC26" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3171:1-3172:31">The header row must match the [delimiter row] in the number of cells. If not,
+a table will not be recognized:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3174:1-3182:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | def |</span>
+<span id="LC2" class="line" lang="plaintext">| --- |</span>
+<span id="LC3" class="line" lang="plaintext">| bar |</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;| abc | def |</span>
+<span id="LC6" class="line" lang="plaintext">| --- |</span>
+<span id="LC7" class="line" lang="plaintext">| bar |&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3184:1-3186:65">The remainder of the table's rows may vary in the number of cells. If there
+are a number of cells fewer than the number of cells in the header row, empty
+cells are inserted. If there are greater, the excess is ignored:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3188:1-3212:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | def |</span>
+<span id="LC2" class="line" lang="plaintext">| --- | --- |</span>
+<span id="LC3" class="line" lang="plaintext">| bar |</span>
+<span id="LC4" class="line" lang="plaintext">| bar | baz | boo |</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;th&gt;abc&lt;/th&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;th&gt;def&lt;/th&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;tbody&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;td&gt;bar&lt;/td&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;td&gt;&lt;/td&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;td&gt;bar&lt;/td&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;td&gt;baz&lt;/td&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC22" class="line" lang="plaintext">&lt;/tbody&gt;</span>
+<span id="LC23" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3214:1-3214:75">If there are no rows in the body, no <code>&lt;tbody&gt;</code> is generated in HTML output:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3216:1-3228:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">| abc | def |</span>
+<span id="LC2" class="line" lang="plaintext">| --- | --- |</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;table&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;thead&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;tr&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;th&gt;abc&lt;/th&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;th&gt;def&lt;/th&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/tr&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/thead&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/table&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+</div>
+<h1 data-sourcepos="3232:1-3232:18" dir="auto">
+<a id="user-content-container-blocks" class="anchor" href="#container-blocks" aria-hidden="true"></a>Container blocks</h1>
+<p data-sourcepos="3234:1-3237:45" dir="auto">A <a href="#container-blocks">container block</a> is a block that has other
+blocks as its contents. There are two basic kinds of container blocks:
+[block quotes] and [list items].
+[Lists] are meta-containers for [list items].</p>
+<p data-sourcepos="3239:1-3240:26" dir="auto">We define the syntax for container blocks recursively. The general
+form of the definition is:</p>
+<blockquote data-sourcepos="3242:1-3244:35" dir="auto">
+<p data-sourcepos="3242:3-3244:35">If X is a sequence of blocks, then the result of
+transforming X in such-and-such a way is a container of type Y
+with these blocks as its content.</p>
+</blockquote>
+<p data-sourcepos="3246:1-3250:52" dir="auto">So, we explain what counts as a block quote or list item by explaining
+how these can be <em>generated</em> from their contents. This should suffice
+to define the syntax, although it does not give a recipe for <em>parsing</em>
+these constructions. (A recipe is provided below in the section entitled
+<a href="#appendix-a-parsing-strategy">A parsing strategy</a>.)</p>
+<h2 data-sourcepos="3252:1-3252:15" dir="auto">
+<a id="user-content-block-quotes" class="anchor" href="#block-quotes" aria-hidden="true"></a>Block quotes</h2>
+<p data-sourcepos="3254:1-3256:78" dir="auto">A <a href="@">block quote marker</a>
+consists of 0-3 spaces of initial indent, plus (a) the character <code>&gt;</code> together
+with a following space, or (b) a single character <code>&gt;</code> not followed by a space.</p>
+<p data-sourcepos="3258:1-3258:42" dir="auto">The following rules define [block quotes]:</p>
+<ol data-sourcepos="3260:1-3277:0" dir="auto">
+<li data-sourcepos="3260:1-3264:0">
+<p data-sourcepos="3260:5-3263:54"><strong>Basic case.</strong> If a string of lines <em>Ls</em> constitute a sequence
+of blocks <em>Bs</em>, then the result of prepending a [block quote
+marker] to the beginning of each line in <em>Ls</em>
+is a <a href="#block-quotes">block quote</a> containing <em>Bs</em>.</p>
+</li>
+<li data-sourcepos="3265:1-3274:0">
+<p data-sourcepos="3265:5-3273:48"><strong>Laziness.</strong> If a string of lines <em>Ls</em> constitute a <a href="#block-quotes">block
+quote</a> with contents <em>Bs</em>, then the result of deleting
+the initial [block quote marker] from one or
+more lines in which the next [non-whitespace character] after the [block
+quote marker] is [paragraph continuation
+text] is a block quote with <em>Bs</em> as its content.
+<a href="@">Paragraph continuation text</a> is text
+that will be parsed as part of the content of a paragraph, but does
+not occur at the beginning of the paragraph.</p>
+</li>
+<li data-sourcepos="3275:1-3277:0">
+<p data-sourcepos="3275:5-3276:65"><strong>Consecutiveness.</strong> A document cannot contain two [block
+quotes] in a row unless there is a [blank line] between them.</p>
+</li>
+</ol>
+<p data-sourcepos="3278:1-3278:54" dir="auto">Nothing else counts as a <a href="#block-quotes">block quote</a>.</p>
+<p data-sourcepos="3280:1-3280:25" dir="auto">Here is a simple example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3282:1-3292:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC3" class="line" lang="plaintext">&gt; baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC8" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3295:1-3295:51" dir="auto">The spaces after the <code>&gt;</code> characters can be omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3297:1-3307:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;# Foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt;bar</span>
+<span id="LC3" class="line" lang="plaintext">&gt; baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC8" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3310:1-3310:46" dir="auto">The <code>&gt;</code> characters can be indented 1-3 spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3312:1-3322:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &gt; # Foo</span>
+<span id="LC2" class="line" lang="plaintext"> &gt; bar</span>
+<span id="LC3" class="line" lang="plaintext"> &gt; baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC8" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3325:1-3325:34" dir="auto">Four spaces gives us a code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3327:1-3336:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &gt; # Foo</span>
+<span id="LC2" class="line" lang="plaintext"> &gt; bar</span>
+<span id="LC3" class="line" lang="plaintext"> &gt; baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&amp;gt; # Foo</span>
+<span id="LC6" class="line" lang="plaintext">&amp;gt; bar</span>
+<span id="LC7" class="line" lang="plaintext">&amp;gt; baz</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3339:1-3340:30" dir="auto">The Laziness clause allows us to omit the <code>&gt;</code> before
+[paragraph continuation text]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3342:1-3352:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC3" class="line" lang="plaintext">baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC8" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3355:1-3356:19" dir="auto">A block quote can contain some lazy and some non-lazy
+continuation lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3358:1-3368:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC7" class="line" lang="plaintext">baz</span>
+<span id="LC8" class="line" lang="plaintext">foo&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3371:1-3373:61" dir="auto">Laziness only applies to lines that would have been continuations of
+paragraphs had they been prepended with [block quote markers].
+For example, the <code>&gt; </code> cannot be omitted in the second line of</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3375:1-3378:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; foo</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gt">&gt; ---</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3380:1-3380:29" dir="auto">without changing the meaning:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3382:1-3390:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">---</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;hr /&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3393:1-3393:52" dir="auto">Similarly, if we omit the <code>&gt; </code> in the second line of</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3395:1-3398:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; - foo</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gt">&gt; - bar</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3400:1-3400:47" dir="auto">then the block quote ends after the first line:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3402:1-3414:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; - foo</span>
+<span id="LC2" class="line" lang="plaintext">- bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3417:1-3418:53" dir="auto">For the same reason, we can't omit the <code>&gt; </code> in front of
+subsequent lines of an indented or fenced code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3420:1-3430:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext"> bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3433:1-3443:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; ```</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3446:1-3447:19" dir="auto">Note that in the following case, we have a [lazy
+continuation line]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3449:1-3457:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">- bar&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3460:1-3460:24" dir="auto">To see why, note that in</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3462:1-3465:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; foo</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gt">&gt; - bar</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3467:1-3469:61" dir="auto">the <code>- bar</code> is indented too far to start a list, and can't
+be an indented code block because indented code blocks cannot
+interrupt paragraphs, so it is [paragraph continuation text].</p>
+<p data-sourcepos="3471:1-3471:27" dir="auto">A block quote can be empty:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3473:1-3478:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3481:1-3488:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;</span>
+<span id="LC2" class="line" lang="plaintext">&gt; </span>
+<span id="LC3" class="line" lang="plaintext">&gt; </span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3491:1-3491:52" dir="auto">A block quote can have initial or final blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3493:1-3501:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;</span>
+<span id="LC2" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC3" class="line" lang="plaintext">&gt; </span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3504:1-3504:43" dir="auto">A blank line always separates block quotes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3506:1-3517:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3520:1-3523:44" dir="auto">(Most current Markdown implementations, including John Gruber's
+original <code>Markdown.pl</code>, will parse this example as a single block quote
+with two paragraphs. But it seems better to allow the author to decide
+whether two block quotes or one are wanted.)</p>
+<p data-sourcepos="3525:1-3526:28" dir="auto">Consecutiveness means that if we put these block quotes together,
+we get a single block quote:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3528:1-3536:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">bar&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3539:1-3539:46" dir="auto">To get a block quote with two paragraphs, use:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3541:1-3550:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt;</span>
+<span id="LC3" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3553:1-3553:38" dir="auto">Block quotes can interrupt paragraphs:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3555:1-3563:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3566:1-3567:7" dir="auto">In general, blank lines are not needed before or after block
+quotes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3569:1-3581:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; aaa</span>
+<span id="LC2" class="line" lang="plaintext">***</span>
+<span id="LC3" class="line" lang="plaintext">&gt; bbb</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;aaa&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr /&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;bbb&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3584:1-3585:40" dir="auto">However, because of laziness, a blank line is needed between
+a block quote and a following paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3587:1-3595:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;bar</span>
+<span id="LC6" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3598:1-3607:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3610:1-3619:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC2" class="line" lang="plaintext">&gt;</span>
+<span id="LC3" class="line" lang="plaintext">baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3622:1-3624:19" dir="auto">It is a consequence of the Laziness rule that any number
+of initial <code>&gt;</code>s may be omitted on a continuation line of a
+nested block quote:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3626:1-3638:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; &gt; &gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC8" class="line" lang="plaintext">bar&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3641:1-3655:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;&gt;&gt; foo</span>
+<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
+<span id="LC3" class="line" lang="plaintext">&gt;&gt;baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC9" class="line" lang="plaintext">bar</span>
+<span id="LC10" class="line" lang="plaintext">baz&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3658:1-3661:8" dir="auto">When including an indented code block in a block quote,
+remember that the [block quote marker] includes
+both the <code>&gt;</code> and a following space. So <em>five spaces</em> are needed after
+the <code>&gt;</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3663:1-3675:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; code</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">&gt; not code</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;code</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;not code&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="3679:1-3679:13" dir="auto">
+<a id="user-content-list-items" class="anchor" href="#list-items" aria-hidden="true"></a>List items</h2>
+<p data-sourcepos="3681:1-3682:49" dir="auto">A <a href="@">list marker</a> is a
+[bullet list marker] or an [ordered list marker].</p>
+<p data-sourcepos="3684:1-3685:32" dir="auto">A <a href="@">bullet list marker</a>
+is a <code>-</code>, <code>+</code>, or <code>*</code> character.</p>
+<p data-sourcepos="3687:1-3691:18" dir="auto">An <a href="@">ordered list marker</a>
+is a sequence of 1--9 arabic digits (<code>0-9</code>), followed by either a
+<code>.</code> character or a <code>)</code> character. (The reason for the length
+limit is that with 10 digits we start seeing integer overflows
+in some browsers.)</p>
+<p data-sourcepos="3693:1-3693:40" dir="auto">The following rules define [list items]:</p>
+<ol data-sourcepos="3695:1-3714:0" dir="auto">
+<li data-sourcepos="3695:1-3714:0">
+<p data-sourcepos="3695:5-3703:45"><strong>Basic case.</strong> If a sequence of lines <em>Ls</em> constitute a sequence of
+blocks <em>Bs</em> starting with a [non-whitespace character], and <em>M</em> is a
+list marker of width <em>W</em> followed by 1 ≤ <em>N</em> ≤ 4 spaces, then the result
+of prepending <em>M</em> and the following spaces to the first line of
+<em>Ls</em>, and indenting subsequent lines of <em>Ls</em> by <em>W + N</em> spaces, is a
+list item with <em>Bs</em> as its contents. The type of the list item
+(bullet or ordered) is determined by the type of its list marker.
+If the list item is ordered, then it is also assigned a start
+number, based on the ordered list marker.</p>
+<p data-sourcepos="3705:5-3705:15">Exceptions:</p>
+<ol data-sourcepos="3707:5-3714:0">
+<li data-sourcepos="3707:5-3711:57">When the first list item in a [list] interrupts
+a paragraph---that is, when it starts on a line that would
+otherwise count as [paragraph continuation text]---then (a)
+the lines <em>Ls</em> must not begin with a blank line, and (b) if
+the list item is ordered, the start number must be 1.</li>
+<li data-sourcepos="3712:5-3714:0">If any line is a [thematic break][thematic breaks] then
+that line is not a list item.</li>
+</ol>
+</li>
+</ol>
+<p data-sourcepos="3715:1-3715:34" dir="auto">For example, let <em>Ls</em> be the lines</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3717:1-3732:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">A paragraph</span>
+<span id="LC2" class="line" lang="plaintext">with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">&gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC9" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3735:1-3737:30" dir="auto">And let <em>M</em> be the marker <code>1.</code>, and <em>N</em> = 2. Then rule #1 says
+that the following is an ordered list item with start number 1,
+and the same contents as <em>Ls</em>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3739:1-3758:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC11" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3761:1-3767:5" dir="auto">The most important thing to notice is that the position of
+the text after the list marker determines how much indentation
+is needed in subsequent blocks in the list item. If the list
+marker takes up two spaces, and there are three spaces between
+the list marker and the next [non-whitespace character], then blocks
+must be indented five spaces in order to fall under the list
+item.</p>
+<p data-sourcepos="3769:1-3770:24" dir="auto">Here are some examples showing how far content must be indented to be
+put under the list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3772:1-3781:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- one</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;one&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;two&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3784:1-3795:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- one</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;one&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;two&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3798:1-3808:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - one</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;one&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; two</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3811:1-3822:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> - one</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;one&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;two&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3825:1-3831:13" dir="auto">It is tempting to think of this in terms of columns: the continuation
+blocks must be indented at least to the column of the first
+[non-whitespace character] after the list marker. However, that is not quite right.
+The spaces after the list marker determine how much relative indentation
+is needed. Which column this indentation reaches will depend on
+how the list item is embedded in other constructions, as shown by
+this example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3833:1-3848:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> &gt; &gt; 1. one</span>
+<span id="LC2" class="line" lang="plaintext">&gt;&gt;</span>
+<span id="LC3" class="line" lang="plaintext">&gt;&gt; two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;one&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;two&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3851:1-3853:67" dir="auto">Here <code>two</code> occurs in the same column as the list marker <code>1.</code>,
+but is actually contained in the list item, because there is
+sufficient indentation after the last containing blockquote marker.</p>
+<p data-sourcepos="3855:1-3858:38" dir="auto">The converse is also possible. In the following example, the word <code>two</code>
+occurs far to the right of the initial text of the list item, <code>one</code>, but
+it is not considered part of the list item, because it is not indented
+far enough past the blockquote marker:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3860:1-3873:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt;&gt;- one</span>
+<span id="LC2" class="line" lang="plaintext">&gt;&gt;</span>
+<span id="LC3" class="line" lang="plaintext"> &gt; &gt; two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;one&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;two&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3876:1-3877:51" dir="auto">Note that at least one space is needed between the list marker and
+any following content, so these are not list items:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3879:1-3886:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-one</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">2.two</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;-one&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;2.two&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3889:1-3890:15" dir="auto">A list item may contain blocks that are separated by more than
+one blank line.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3892:1-3904:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> bar</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3907:1-3907:42" dir="auto">A list item may contain any kind of block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3909:1-3931:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext"> bar</span>
+<span id="LC5" class="line" lang="plaintext"> ```</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext"> baz</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext"> &gt; bam</span>
+<span id="LC10" class="line" lang="plaintext">.</span>
+<span id="LC11" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;p&gt;bam&lt;/p&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3934:1-3935:43" dir="auto">A list item that contains an indented code block will preserve
+empty lines within the code block verbatim.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3937:1-3955:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- Foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> baz</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC12" class="line" lang="plaintext"></span>
+<span id="LC13" class="line" lang="plaintext"></span>
+<span id="LC14" class="line" lang="plaintext">baz</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3957:1-3957:65" dir="auto">Note that ordered list start numbers must be nine digits or less:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3959:1-3965:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">123456789. ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ol start="123456789"&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;ok&lt;/li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3968:1-3972:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1234567890. not ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;1234567890. not ok&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3975:1-3975:33" dir="auto">A start number may begin with 0s:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3977:1-3983:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">0. ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ol start="0"&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;ok&lt;/li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3986:1-3992:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">003. ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ol start="3"&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;ok&lt;/li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="3995:1-3995:35" dir="auto">A start number may not be negative:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="3997:1-4001:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-1. not ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;-1. not ok&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<ol start="2" data-sourcepos="4005:1-4015:0" dir="auto">
+<li data-sourcepos="4005:1-4015:0">
+<strong>Item starting with indented code.</strong> If a sequence of lines <em>Ls</em>
+constitute a sequence of blocks <em>Bs</em> starting with an indented code
+block, and <em>M</em> is a list marker of width <em>W</em> followed by
+one space, then the result of prepending <em>M</em> and the following
+space to the first line of <em>Ls</em>, and indenting subsequent lines of
+<em>Ls</em> by <em>W + 1</em> spaces, is a list item with <em>Bs</em> as its contents.
+If a line is empty, then it need not be indented. The type of the
+list item (bullet or ordered) is determined by the type of its list
+marker. If the list item is ordered, then it is also assigned a
+start number, based on the ordered list marker.</li>
+</ol>
+<p data-sourcepos="4016:1-4018:39" dir="auto">An indented code block will have to be indented four spaces beyond
+the edge of the region where text will be included in the list item.
+In the following case that is 6 spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4020:1-4032:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4035:1-4035:33" dir="auto">And in this case it is 11 spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4037:1-4049:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 10. foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol start="10"&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4052:1-4054:12" dir="auto">If the <em>first</em> block in the list item is an indented code block,
+then by rule #2, the contents must be indented <em>one</em> space after the
+list marker:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4056:1-4068:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> indented code</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">paragraph</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> more code</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;paragraph&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;more code</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4071:1-4087:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. indented code</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> more code</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;paragraph&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;more code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4090:1-4091:22" dir="auto">Note that an additional space indent is interpreted as space
+inside the code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4093:1-4109:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. indented code</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> more code</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt; indented code</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;paragraph&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;more code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4112:1-4118:55" dir="auto">Note that rules #1 and #2 only apply to two cases: (a) cases
+in which the lines to be included in a list item begin with a
+[non-whitespace character], and (b) cases in which
+they begin with an indented code
+block. In a case like the following, where the first block begins with
+a three-space indent, the rules do not allow us to form a list item by
+indenting the whole thing and prepending a list marker:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4120:1-4127:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4130:1-4139:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4142:1-4145:15" dir="auto">This is not a significant restriction, because when a block begins
+with 1-3 spaces indent, the indentation can always be removed without
+a change in interpretation, allowing rule #1 to be applied. So, in
+the above case:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4147:1-4158:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<ol start="3" data-sourcepos="4161:1-4172:0" dir="auto">
+<li data-sourcepos="4161:1-4172:0">
+<strong>Item starting with a blank line.</strong> If a sequence of lines <em>Ls</em>
+starting with a single [blank line] constitute a (possibly empty)
+sequence of blocks <em>Bs</em>, not separated from each other by more than
+one blank line, and <em>M</em> is a list marker of width <em>W</em>,
+then the result of prepending <em>M</em> to the first line of <em>Ls</em>, and
+indenting subsequent lines of <em>Ls</em> by <em>W + 1</em> spaces, is a list
+item with <em>Bs</em> as its contents.
+If a line is empty, then it need not be indented. The type of the
+list item (bullet or ordered) is determined by the type of its list
+marker. If the list item is ordered, then it is also assigned a
+start number, based on the ordered list marker.</li>
+</ol>
+<p data-sourcepos="4173:1-4173:72" dir="auto">Here are some list items that start with a blank line but are not empty:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4175:1-4196:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-</span>
+<span id="LC2" class="line" lang="plaintext"> foo</span>
+<span id="LC3" class="line" lang="plaintext">-</span>
+<span id="LC4" class="line" lang="plaintext"> ```</span>
+<span id="LC5" class="line" lang="plaintext"> bar</span>
+<span id="LC6" class="line" lang="plaintext"> ```</span>
+<span id="LC7" class="line" lang="plaintext">-</span>
+<span id="LC8" class="line" lang="plaintext"> baz</span>
+<span id="LC9" class="line" lang="plaintext">.</span>
+<span id="LC10" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;bar</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;baz</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4198:1-4199:66" dir="auto">When the list item starts with a blank line, the number of spaces
+following the list marker doesn't change the required indentation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4201:1-4208:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- </span>
+<span id="LC2" class="line" lang="plaintext"> foo</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4211:1-4213:5" dir="auto">A list item can begin with at most one blank line.
+In the following example, <code>foo</code> is not part of the list
+item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4215:1-4224:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> foo</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4227:1-4227:34" dir="auto">Here is an empty bullet list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4229:1-4239:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">-</span>
+<span id="LC3" class="line" lang="plaintext">- bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4242:1-4242:72" dir="auto">It does not matter whether there are spaces following the [list marker]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4244:1-4254:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">- </span>
+<span id="LC3" class="line" lang="plaintext">- bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4257:1-4257:35" dir="auto">Here is an empty ordered list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4259:1-4269:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. foo</span>
+<span id="LC2" class="line" lang="plaintext">2.</span>
+<span id="LC3" class="line" lang="plaintext">3. bar</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4272:1-4272:48" dir="auto">A list may start or end with an empty list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4274:1-4280:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4282:1-4282:57" dir="auto">However, an empty list item cannot interrupt a paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4284:1-4295:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext">*</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">foo</span>
+<span id="LC5" class="line" lang="plaintext">1.</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC8" class="line" lang="plaintext">*&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC10" class="line" lang="plaintext">1.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<ol start="4" data-sourcepos="4298:1-4303:0" dir="auto">
+<li data-sourcepos="4298:1-4303:0">
+<strong>Indentation.</strong> If a sequence of lines <em>Ls</em> constitutes a list item
+according to rule #1, #2, or #3, then the result of indenting each line
+of <em>Ls</em> by 1-3 spaces (the same for each line) also constitutes a
+list item with the same contents and attributes. If a line is
+empty, then it need not be indented.</li>
+</ol>
+<p data-sourcepos="4304:1-4304:19" dir="auto">Indented one space:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4306:1-4325:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC11" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4328:1-4328:20" dir="auto">Indented two spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4330:1-4349:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC11" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4352:1-4352:22" dir="auto">Indented three spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4354:1-4373:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC11" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4376:1-4376:38" dir="auto">Four spaces indent gives a code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4378:1-4393:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;1. A paragraph</span>
+<span id="LC9" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC10" class="line" lang="plaintext"></span>
+<span id="LC11" class="line" lang="plaintext"> indented code</span>
+<span id="LC12" class="line" lang="plaintext"></span>
+<span id="LC13" class="line" lang="plaintext"> &amp;gt; A block quote.</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<ol start="5" data-sourcepos="4397:1-4405:0" dir="auto">
+<li data-sourcepos="4397:1-4405:0">
+<strong>Laziness.</strong> If a string of lines <em>Ls</em> constitute a <a href="#list-items">list
+item</a> with contents <em>Bs</em>, then the result of deleting
+some or all of the indentation from one or more lines in which the
+next [non-whitespace character] after the indentation is
+[paragraph continuation text] is a
+list item with the same contents and attributes. The unindented
+lines are called
+<a href="@">lazy continuation line</a>s.</li>
+</ol>
+<p data-sourcepos="4406:1-4406:50" dir="auto">Here is an example with [lazy continuation lines]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4408:1-4427:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext">with two lines.</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> indented code</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> &gt; A block quote.</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;A paragraph</span>
+<span id="LC11" class="line" lang="plaintext">with two lines.&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;indented code</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;A block quote.&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4430:1-4430:37" dir="auto">Indentation can be partially deleted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4432:1-4440:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> 1. A paragraph</span>
+<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;A paragraph</span>
+<span id="LC6" class="line" lang="plaintext">with two lines.&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4443:1-4443:63" dir="auto">These examples show how laziness can work in nested structures:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4445:1-4459:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; 1. &gt; Blockquote</span>
+<span id="LC2" class="line" lang="plaintext">continued here.</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;Blockquote</span>
+<span id="LC9" class="line" lang="plaintext">continued here.&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4462:1-4476:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; 1. &gt; Blockquote</span>
+<span id="LC2" class="line" lang="plaintext">&gt; continued here.</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;Blockquote</span>
+<span id="LC9" class="line" lang="plaintext">continued here.&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<ol start="6" data-sourcepos="4480:1-4482:0" dir="auto">
+<li data-sourcepos="4480:1-4482:0">
+<strong>That's all.</strong> Nothing that is not counted as a list item by rules
+#1--5 counts as a <a href="#list-items">list item</a>.</li>
+</ol>
+<p data-sourcepos="4483:1-4486:17" dir="auto">The rules for sublists follow from the general rules
+[above][List items]. A sublist must be indented the same number
+of spaces a paragraph would need to be in order to be included
+in the list item.</p>
+<p data-sourcepos="4488:1-4488:43" dir="auto">So, in this case we need two spaces indent:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4490:1-4511:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext"> - baz</span>
+<span id="LC4" class="line" lang="plaintext"> - boo</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;foo</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;bar</span>
+<span id="LC10" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;baz</span>
+<span id="LC12" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;boo&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4514:1-4514:18" dir="auto">One is not enough:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4516:1-4528:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext"> - baz</span>
+<span id="LC4" class="line" lang="plaintext"> - boo</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;boo&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4531:1-4531:52" dir="auto">Here we need four, because the list marker is wider:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4533:1-4544:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">10) foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ol start="10"&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4547:1-4547:20" dir="auto">Three is not enough:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4549:1-4559:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">10) foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ol start="10"&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4562:1-4562:45" dir="auto">A list may be the first block in a list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4564:1-4574:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- - foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4577:1-4591:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. - 2. foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol start="2"&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4594:1-4594:34" dir="auto">A list item can contain a heading:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4596:1-4610:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- # Foo</span>
+<span id="LC2" class="line" lang="plaintext">- Bar</span>
+<span id="LC3" class="line" lang="plaintext"> ---</span>
+<span id="LC4" class="line" lang="plaintext"> baz</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;h1&gt;Foo&lt;/h1&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;h2&gt;Bar&lt;/h2&gt;</span>
+<span id="LC12" class="line" lang="plaintext">baz&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h3 data-sourcepos="4613:1-4613:14" dir="auto">
+<a id="user-content-motivation" class="anchor" href="#motivation" aria-hidden="true"></a>Motivation</h3>
+<p data-sourcepos="4615:1-4615:64" dir="auto">John Gruber's Markdown spec says the following about list items:</p>
+<ol data-sourcepos="4617:1-4636:0" dir="auto">
+<li data-sourcepos="4617:1-4620:0">
+<p data-sourcepos="4617:4-4619:20">"List markers typically start at the left margin, but may be indented
+by up to three spaces. List markers must be followed by one or more
+spaces or a tab."</p>
+</li>
+<li data-sourcepos="4621:1-4623:0">
+<p data-sourcepos="4621:4-4622:48">"To make lists look nice, you can wrap items with hanging indents....
+But if you don't want to, you don't have to."</p>
+</li>
+<li data-sourcepos="4624:1-4627:0">
+<p data-sourcepos="4624:4-4626:8">"List items may consist of multiple paragraphs. Each subsequent
+paragraph in a list item must be indented by either 4 spaces or one
+tab."</p>
+</li>
+<li data-sourcepos="4628:1-4630:0">
+<p data-sourcepos="4628:4-4629:55">"It looks nice if you indent every line of the subsequent paragraphs,
+but here again, Markdown will allow you to be lazy."</p>
+</li>
+<li data-sourcepos="4631:1-4633:0">
+<p data-sourcepos="4631:4-4632:35">"To put a blockquote within a list item, the blockquote's <code>&gt;</code>
+delimiters need to be indented."</p>
+</li>
+<li data-sourcepos="4634:1-4636:0">
+<p data-sourcepos="4634:4-4635:44">"To put a code block within a list item, the code block needs to be
+indented twice — 8 spaces or two tabs."</p>
+</li>
+</ol>
+<p data-sourcepos="4637:1-4646:18" dir="auto">These rules specify that a paragraph under a list item must be indented
+four spaces (presumably, from the left margin, rather than the start of
+the list marker, but this is not said), and that code under a list item
+must be indented eight spaces instead of the usual four. They also say
+that a block quote must be indented, but not by how much; however, the
+example given has four spaces indentation. Although nothing is said
+about other kinds of block-level content, it is certainly reasonable to
+infer that <em>all</em> block elements under a list item, including other
+lists, must be indented four spaces. This principle has been called the
+<em>four-space rule</em>.</p>
+<p data-sourcepos="4648:1-4659:48" dir="auto">The four-space rule is clear and principled, and if the reference
+implementation <code>Markdown.pl</code> had followed it, it probably would have
+become the standard. However, <code>Markdown.pl</code> allowed paragraphs and
+sublists to start with only two spaces indentation, at least on the
+outer level. Worse, its behavior was inconsistent: a sublist of an
+outer-level list needed two spaces indentation, but a sublist of this
+sublist needed three spaces. It is not surprising, then, that different
+implementations of Markdown have developed very different rules for
+determining what comes under a list item. (Pandoc and python-Markdown,
+for example, stuck with Gruber's syntax description and the four-space
+rule, while discount, redcarpet, marked, PHP Markdown, and others
+followed <code>Markdown.pl</code>'s behavior more closely.)</p>
+<p data-sourcepos="4661:1-4666:45" dir="auto">Unfortunately, given the divergences between implementations, there
+is no way to give a spec for list items that will be guaranteed not
+to break any existing documents. However, the spec given here should
+correctly handle lists formatted with either the four-space rule or
+the more forgiving <code>Markdown.pl</code> behavior, provided they are laid out
+in a way that is natural for a human to read.</p>
+<p data-sourcepos="4668:1-4674:22" dir="auto">The strategy here is to let the width and indentation of the list marker
+determine the indentation necessary for blocks to fall under the list
+item, rather than having a fixed and arbitrary number. The writer can
+think of the body of the list item as a unit which gets indented to the
+right enough to fit the list marker (and any indentation on the list
+marker). (The laziness rule, #5, then allows continuation lines to be
+unindented if needed.)</p>
+<p data-sourcepos="4676:1-4678:39" dir="auto">This rule is superior, we claim, to any rule requiring a fixed level of
+indentation from the margin. The four-space rule is clear but
+unnatural. It is quite unintuitive that</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4680:1-4686:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="p">-</span> foo</span>
+<span id="LC2" class="line" lang="markdown"></span>
+<span id="LC3" class="line" lang="markdown"> bar</span>
+<span id="LC4" class="line" lang="markdown"></span>
+<span id="LC5" class="line" lang="markdown"><span class="p"> -</span> baz</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4688:1-4688:60" dir="auto">should be parsed as two lists with an intervening paragraph,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4690:1-4698:3" class="code highlight js-syntax-highlight language-html" lang="html" v-pre="true"><code><span id="LC1" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC2" class="line" lang="html"><span class="nt">&lt;li&gt;</span>foo<span class="nt">&lt;/li&gt;</span></span>
+<span id="LC3" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span>
+<span id="LC4" class="line" lang="html"><span class="nt">&lt;p&gt;</span>bar<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC5" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC6" class="line" lang="html"><span class="nt">&lt;li&gt;</span>baz<span class="nt">&lt;/li&gt;</span></span>
+<span id="LC7" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4700:1-4700:58" dir="auto">as the four-space rule demands, rather than a single list,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4702:1-4712:3" class="code highlight js-syntax-highlight language-html" lang="html" v-pre="true"><code><span id="LC1" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC2" class="line" lang="html"><span class="nt">&lt;li&gt;</span></span>
+<span id="LC3" class="line" lang="html"><span class="nt">&lt;p&gt;</span>foo<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC4" class="line" lang="html"><span class="nt">&lt;p&gt;</span>bar<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC5" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC6" class="line" lang="html"><span class="nt">&lt;li&gt;</span>baz<span class="nt">&lt;/li&gt;</span></span>
+<span id="LC7" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span>
+<span id="LC8" class="line" lang="html"><span class="nt">&lt;/li&gt;</span></span>
+<span id="LC9" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4714:1-4715:62" dir="auto">The choice of four spaces is arbitrary. It can be learned, but it is
+not likely to be guessed, and it trips up beginners regularly.</p>
+<p data-sourcepos="4717:1-4721:20" dir="auto">Would it help to adopt a two-space rule? The problem is that such
+a rule, together with the rule allowing 1--3 spaces indentation of the
+initial list marker, allows text that is indented <em>less than</em> the
+original list marker to be included in the list item. For example,
+<code>Markdown.pl</code> parses</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4723:1-4727:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="p"> -</span> one</span>
+<span id="LC2" class="line" lang="markdown"></span>
+<span id="LC3" class="line" lang="markdown"> two</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4729:1-4729:59" dir="auto">as a single list item, with <code>two</code> a continuation paragraph:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4731:1-4738:3" class="code highlight js-syntax-highlight language-html" lang="html" v-pre="true"><code><span id="LC1" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC2" class="line" lang="html"><span class="nt">&lt;li&gt;</span></span>
+<span id="LC3" class="line" lang="html"><span class="nt">&lt;p&gt;</span>one<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC4" class="line" lang="html"><span class="nt">&lt;p&gt;</span>two<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC5" class="line" lang="html"><span class="nt">&lt;/li&gt;</span></span>
+<span id="LC6" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4740:1-4740:13" dir="auto">and similarly</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4742:1-4746:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; - one</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gt">&gt;</span></span>
+<span id="LC3" class="line" lang="markdown"><span class="gt">&gt; two</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4748:1-4748:2" dir="auto">as</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4750:1-4759:3" class="code highlight js-syntax-highlight language-html" lang="html" v-pre="true"><code><span id="LC1" class="line" lang="html"><span class="nt">&lt;blockquote&gt;</span></span>
+<span id="LC2" class="line" lang="html"><span class="nt">&lt;ul&gt;</span></span>
+<span id="LC3" class="line" lang="html"><span class="nt">&lt;li&gt;</span></span>
+<span id="LC4" class="line" lang="html"><span class="nt">&lt;p&gt;</span>one<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC5" class="line" lang="html"><span class="nt">&lt;p&gt;</span>two<span class="nt">&lt;/p&gt;</span></span>
+<span id="LC6" class="line" lang="html"><span class="nt">&lt;/li&gt;</span></span>
+<span id="LC7" class="line" lang="html"><span class="nt">&lt;/ul&gt;</span></span>
+<span id="LC8" class="line" lang="html"><span class="nt">&lt;/blockquote&gt;</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4761:1-4761:30" dir="auto">This is extremely unintuitive.</p>
+<p data-sourcepos="4763:1-4768:52" dir="auto">Rather than requiring a fixed indent from the margin, we could require
+a fixed indent (say, two spaces, or even one space) from the list marker (which
+may itself be indented). This proposal would remove the last anomaly
+discussed. Unlike the spec presented above, it would count the following
+as a list item with a subparagraph, even though the paragraph <code>bar</code>
+is not indented as far as the first paragraph <code>foo</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4770:1-4774:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="p"> 10.</span> foo</span>
+<span id="LC2" class="line" lang="markdown"></span>
+<span id="LC3" class="line" lang="markdown"> bar </span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4776:1-4779:62" dir="auto">Arguably this text does read like a list item with <code>bar</code> as a subparagraph,
+which may count in favor of the proposal. However, on this proposal indented
+code would have to be indented six spaces after the list marker. And this
+would break a lot of existing Markdown, which has the pattern:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4781:1-4785:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="p">1.</span> foo</span>
+<span id="LC2" class="line" lang="markdown"></span>
+<span id="LC3" class="line" lang="markdown"><span class="sb"> indented code</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4787:1-4789:28" dir="auto">where the code is indented eight spaces. The spec above, by contrast, will
+parse this text as expected, since the code block's indentation is measured
+from the beginning of <code>foo</code>.</p>
+<p data-sourcepos="4791:1-4797:62" dir="auto">The one case that needs special treatment is a list item that <em>starts</em>
+with indented code. How much indentation is required in that case, since
+we don't have a "first paragraph" to measure from? Rule #2 simply stipulates
+that in such cases, we require one space indentation from the list marker
+(and then the normal four spaces for the indented code). This will match the
+four-space rule in cases where the list marker plus its initial indentation
+takes four spaces (a common case), but diverge in other cases.</p>
+<div>
+<h2 data-sourcepos="4801:1-4801:30">
+<a id="user-content-task-list-items-extension" class="anchor" href="#task-list-items-extension" aria-hidden="true"></a>Task list items (extension)</h2>
+<p data-sourcepos="4803:1-4804:26">GFM enables the <code>tasklist</code> extension, where an additional processing step is
+performed on [list items].</p>
+<p data-sourcepos="4806:1-4808:46">A <a href="@">task list item</a> is a [list item][list items] where the first block in it
+is a paragraph which begins with a [task list item marker] and at least one
+whitespace character before any other content.</p>
+<p data-sourcepos="4810:1-4812:55">A <a href="@">task list item marker</a> consists of an optional number of spaces, a left
+bracket (<code>[</code>), either a whitespace character or the letter <code>x</code> in either
+lowercase or uppercase, and then a right bracket (<code>]</code>).</p>
+<p data-sourcepos="4814:1-4815:70">When rendered, the [task list item marker] is replaced with a semantic checkbox element;
+in an HTML output, this would be an <code>&lt;input type="checkbox"&gt;</code> element.</p>
+<p data-sourcepos="4817:1-4818:50">If the character between the brackets is a whitespace character, the checkbox
+is unchecked. Otherwise, the checkbox is checked.</p>
+<p data-sourcepos="4820:1-4823:28">This spec does not define how the checkbox elements are interacted with: in practice,
+implementors are free to render the checkboxes as disabled or inmutable elements,
+or they may dynamically handle dynamic interactions (i.e. checking, unchecking) in
+the final rendered document.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4825:1-4833:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] foo</span>
+<span id="LC2" class="line" lang="plaintext">- [x] bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; foo&lt;/li&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; bar&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4835:1-4835:37">Task lists can be arbitrarily nested:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4837:1-4852:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] foo</span>
+<span id="LC2" class="line" lang="plaintext"> - [ ] bar</span>
+<span id="LC3" class="line" lang="plaintext"> - [x] baz</span>
+<span id="LC4" class="line" lang="plaintext">- [ ] bim</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; foo</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; bar&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; baz&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; bim&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+</div>
+<h2 data-sourcepos="4856:1-4856:8" dir="auto">
+<a id="user-content-lists" class="anchor" href="#lists" aria-hidden="true"></a>Lists</h2>
+<p data-sourcepos="4858:1-4860:46" dir="auto">A <a href="@">list</a> is a sequence of one or more
+list items [of the same type]. The list items
+may be separated by any number of blank lines.</p>
+<p data-sourcepos="4862:1-4867:30" dir="auto">Two list items are <a href="@">of the same type</a>
+if they begin with a [list marker] of the same type.
+Two list markers are of the
+same type if (a) they are bullet list markers using the same character
+(<code>-</code>, <code>+</code>, or <code>*</code>) or (b) they are ordered list numbers with the same
+delimiter (either <code>.</code> or <code>)</code>).</p>
+<p data-sourcepos="4869:1-4873:39" dir="auto">A list is an <a href="@">ordered list</a>
+if its constituent list items begin with
+[ordered list markers], and a
+<a href="@">bullet list</a> if its constituent list
+items begin with [bullet list markers].</p>
+<p data-sourcepos="4875:1-4878:12" dir="auto">The <a href="@">start number</a>
+of an [ordered list] is determined by the list number of
+its initial list item. The numbers of subsequent list items are
+disregarded.</p>
+<p data-sourcepos="4880:1-4885:65" dir="auto">A list is <a href="@">loose</a> if any of its constituent
+list items are separated by blank lines, or if any of its constituent
+list items directly contain two block-level elements with a blank line
+between them. Otherwise a list is <a href="@">tight</a>.
+(The difference in HTML output is that paragraphs in a loose list are
+wrapped in <code>&lt;p&gt;</code> tags, while paragraphs in a tight list are not.)</p>
+<p data-sourcepos="4887:1-4887:64" dir="auto">Changing the bullet or ordered list delimiter starts a new list:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4889:1-4901:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">- bar</span>
+<span id="LC3" class="line" lang="plaintext">+ baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4904:1-4916:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. foo</span>
+<span id="LC2" class="line" lang="plaintext">2. bar</span>
+<span id="LC3" class="line" lang="plaintext">3) baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ol start="3"&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4919:1-4921:5" dir="auto">In CommonMark, a list can interrupt a paragraph. That is,
+no blank line is needed to separate a paragraph from a following
+list:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4923:1-4933:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
+<span id="LC2" class="line" lang="plaintext">- bar</span>
+<span id="LC3" class="line" lang="plaintext">- baz</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4935:1-4936:37" dir="auto"><code>Markdown.pl</code> does not allow this, through fear of triggering a list
+via a numeral in a hard-wrapped line:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4938:1-4941:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">The number of windows in my house is</span>
+<span id="LC2" class="line" lang="markdown"><span class="p">14.</span> The number of doors is 6.</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4943:1-4945:6" dir="auto">Oddly, though, <code>Markdown.pl</code> <em>does</em> allow a blockquote to
+interrupt a paragraph, even though the same considerations might
+apply.</p>
+<p data-sourcepos="4947:1-4949:35" dir="auto">In CommonMark, we do allow lists to interrupt paragraphs, for
+two reasons. First, it is natural and not uncommon for people
+to start lists without blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4951:1-4956:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">I need to buy</span>
+<span id="LC2" class="line" lang="markdown"><span class="p">-</span> new shoes</span>
+<span id="LC3" class="line" lang="markdown"><span class="p">-</span> a coat</span>
+<span id="LC4" class="line" lang="markdown"><span class="p">-</span> a plane ticket</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4958:1-4958:29" dir="auto">Second, we are attracted to a</p>
+<blockquote data-sourcepos="4960:1-4963:54" dir="auto">
+<p data-sourcepos="4960:3-4963:54"><a href="@">principle of uniformity</a>:
+if a chunk of text has a certain
+meaning, it will continue to have the same meaning when put into a
+container block (such as a list item or blockquote).</p>
+</blockquote>
+<p data-sourcepos="4965:1-4966:47" dir="auto">(Indeed, the spec for [list items] and [block quotes] presupposes
+this principle.) This principle implies that if</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4968:1-4973:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="p"> *</span> I need to buy</span>
+<span id="LC2" class="line" lang="markdown"><span class="p"> -</span> new shoes</span>
+<span id="LC3" class="line" lang="markdown"><span class="p"> -</span> a coat</span>
+<span id="LC4" class="line" lang="markdown"><span class="p"> -</span> a plane ticket</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4975:1-4978:4" dir="auto">is a list item containing a paragraph followed by a nested sublist,
+as all Markdown implementations agree it is (though the paragraph
+may be rendered without <code>&lt;p&gt;</code> tags, since the list is "tight"),
+then</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="4980:1-4985:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">I need to buy</span>
+<span id="LC2" class="line" lang="markdown"><span class="p">-</span> new shoes</span>
+<span id="LC3" class="line" lang="markdown"><span class="p">-</span> a coat</span>
+<span id="LC4" class="line" lang="markdown"><span class="p">-</span> a plane ticket</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="4987:1-4987:61" dir="auto">by itself should be a paragraph followed by a nested sublist.</p>
+<p data-sourcepos="4989:1-4994:30" dir="auto">Since it is well established Markdown practice to allow lists to
+interrupt paragraphs inside list items, the [principle of
+uniformity] requires us to allow this outside list items as
+well. (<a href="http://docutils.sourceforge.net/rst.html" rel="nofollow noreferrer noopener" target="_blank">reStructuredText</a>
+takes a different approach, requiring blank lines before lists
+even inside other list items.)</p>
+<p data-sourcepos="4996:1-4998:28" dir="auto">In order to solve of unwanted lists in paragraphs with
+hard-wrapped numerals, we allow only lists starting with <code>1</code> to
+interrupt paragraphs. Thus,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5000:1-5006:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">The number of windows in my house is</span>
+<span id="LC2" class="line" lang="plaintext">14. The number of doors is 6.</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;The number of windows in my house is</span>
+<span id="LC5" class="line" lang="plaintext">14. The number of doors is 6.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5008:1-5008:51" dir="auto">We may still get an unintended result in cases like</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5010:1-5018:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">The number of windows in my house is</span>
+<span id="LC2" class="line" lang="plaintext">1. The number of doors is 6.</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;The number of windows in my house is&lt;/p&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;The number of doors is 6.&lt;/li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5020:1-5020:57" dir="auto">but this rule should prevent most spurious list captures.</p>
+<p data-sourcepos="5022:1-5022:53" dir="auto">There can be any number of blank lines between items:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5024:1-5043:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">- bar</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">- baz</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5045:1-5067:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"> - bar</span>
+<span id="LC3" class="line" lang="plaintext"> - baz</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> bim</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;foo</span>
+<span id="LC10" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;bar</span>
+<span id="LC12" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;bim&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5070:1-5073:8" dir="auto">To separate consecutive lists of the same type, or to separate a
+list from an indented code block that would otherwise be parsed
+as a subparagraph of the final list item, you can insert a blank HTML
+comment:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5075:1-5093:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext">- bar</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">&lt;!-- --&gt;</span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext">- baz</span>
+<span id="LC7" class="line" lang="plaintext">- bim</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;!-- --&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;li&gt;baz&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;bim&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5096:1-5119:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> notcode</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">- foo</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext">&lt;!-- --&gt;</span>
+<span id="LC8" class="line" lang="plaintext"></span>
+<span id="LC9" class="line" lang="plaintext"> code</span>
+<span id="LC10" class="line" lang="plaintext">.</span>
+<span id="LC11" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;p&gt;notcode&lt;/p&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;!-- --&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;code</span>
+<span id="LC22" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5122:1-5125:5" dir="auto">List items need not be indented to the same level. The following
+list items will be treated as items at the same list level,
+since none is indented enough to belong to the previous list
+item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5127:1-5145:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> - b</span>
+<span id="LC3" class="line" lang="plaintext"> - c</span>
+<span id="LC4" class="line" lang="plaintext"> - d</span>
+<span id="LC5" class="line" lang="plaintext"> - e</span>
+<span id="LC6" class="line" lang="plaintext"> - f</span>
+<span id="LC7" class="line" lang="plaintext">- g</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;a&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;b&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;c&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;d&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;li&gt;e&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;li&gt;f&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;g&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5148:1-5166:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. a</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> 2. b</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> 3. c</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;c&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5168:1-5170:52" dir="auto">Note, however, that list items may not be indented more than
+three spaces. Here <code>- e</code> is treated as a paragraph continuation
+line, because it is indented more than three spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5172:1-5186:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> - b</span>
+<span id="LC3" class="line" lang="plaintext"> - c</span>
+<span id="LC4" class="line" lang="plaintext"> - d</span>
+<span id="LC5" class="line" lang="plaintext"> - e</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;a&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;b&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;c&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;d</span>
+<span id="LC12" class="line" lang="plaintext">- e&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5188:1-5190:11" dir="auto">And here, <code>3. c</code> is treated as in indented code block,
+because it is indented four spaces and preceded by a
+blank line.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5192:1-5209:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. a</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> 2. b</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> 3. c</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;3. c</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5212:1-5213:22" dir="auto">This is a loose list, because there is a blank line between
+two of the list items:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5215:1-5232:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext">- b</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">- c</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;p&gt;c&lt;/p&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5235:1-5235:37" dir="auto">So is this, with a empty second item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5237:1-5252:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">* a</span>
+<span id="LC2" class="line" lang="plaintext">*</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">* c</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;c&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5255:1-5257:31" dir="auto">These are loose lists, even though there is no space between the items,
+because one of the items directly contains two block-level elements
+with a blank line between them:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5259:1-5278:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext">- b</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> c</span>
+<span id="LC5" class="line" lang="plaintext">- d</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;p&gt;c&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;p&gt;d&lt;/p&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5281:1-5299:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext">- b</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> [ref]: /url</span>
+<span id="LC5" class="line" lang="plaintext">- d</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;p&gt;d&lt;/p&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5302:1-5302:66" dir="auto">This is a tight list, because the blank lines are in a code block:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5304:1-5323:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext">- ```</span>
+<span id="LC3" class="line" lang="plaintext"> b</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"></span>
+<span id="LC6" class="line" lang="plaintext"> ```</span>
+<span id="LC7" class="line" lang="plaintext">- c</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;a&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;b</span>
+<span id="LC13" class="line" lang="plaintext"></span>
+<span id="LC14" class="line" lang="plaintext"></span>
+<span id="LC15" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;li&gt;c&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5326:1-5328:24" dir="auto">This is a tight list, because the blank line is between two
+paragraphs of a sublist. So the sublist is loose while
+the outer list is tight:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5330:1-5348:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> - b</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> c</span>
+<span id="LC5" class="line" lang="plaintext">- d</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;a</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;c&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;d&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5351:1-5352:12" dir="auto">This is a tight list, because the blank line is inside the
+block quote:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5354:1-5368:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">* a</span>
+<span id="LC2" class="line" lang="plaintext"> &gt; b</span>
+<span id="LC3" class="line" lang="plaintext"> &gt;</span>
+<span id="LC4" class="line" lang="plaintext">* c</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;a</span>
+<span id="LC8" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;li&gt;c&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5371:1-5372:33" dir="auto">This list is tight, because the consecutive block elements
+are not separated by blank lines:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5374:1-5392:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> &gt; b</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext"> c</span>
+<span id="LC5" class="line" lang="plaintext"> ```</span>
+<span id="LC6" class="line" lang="plaintext">- d</span>
+<span id="LC7" class="line" lang="plaintext">.</span>
+<span id="LC8" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;li&gt;a</span>
+<span id="LC10" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;b&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;c</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;li&gt;d&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5395:1-5395:33" dir="auto">A single-paragraph list is tight:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5397:1-5403:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;a&lt;/li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5406:1-5417:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> - b</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;li&gt;a</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;b&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5420:1-5421:36" dir="auto">This list is loose, because of the blank line between the
+two block elements in the list item:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5423:1-5437:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. ```</span>
+<span id="LC2" class="line" lang="plaintext"> foo</span>
+<span id="LC3" class="line" lang="plaintext"> ```</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext"> bar</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;foo</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;bar&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/ol&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5440:1-5440:51" dir="auto">Here the outer list is loose, the inner list tight:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5442:1-5457:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">* foo</span>
+<span id="LC2" class="line" lang="plaintext"> * bar</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext"> baz</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;bar&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;baz&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5460:1-5485:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- a</span>
+<span id="LC2" class="line" lang="plaintext"> - b</span>
+<span id="LC3" class="line" lang="plaintext"> - c</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">- d</span>
+<span id="LC6" class="line" lang="plaintext"> - e</span>
+<span id="LC7" class="line" lang="plaintext"> - f</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;a&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;li&gt;b&lt;/li&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;li&gt;c&lt;/li&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;p&gt;d&lt;/p&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;li&gt;e&lt;/li&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;li&gt;f&lt;/li&gt;</span>
+<span id="LC22" class="line" lang="plaintext">&lt;/ul&gt;</span>
+<span id="LC23" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC24" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h1 data-sourcepos="5488:1-5488:9" dir="auto">
+<a id="user-content-inlines" class="anchor" href="#inlines" aria-hidden="true"></a>Inlines</h1>
+<p data-sourcepos="5490:1-5492:21" dir="auto">Inlines are parsed sequentially from the beginning of the character
+stream to the end (left to right, in left-to-right languages).
+Thus, for example, in</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5494:1-5498:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`hi`lo`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;hi&lt;/code&gt;lo`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5500:1-5501:9" dir="auto"><code>hi</code> is parsed as code, leaving the backtick at the end as a literal
+backtick.</p>
+<h2 data-sourcepos="5504:1-5504:20" dir="auto">
+<a id="user-content-backslash-escapes" class="anchor" href="#backslash-escapes" aria-hidden="true"></a>Backslash escapes</h2>
+<p data-sourcepos="5506:1-5506:57" dir="auto">Any ASCII punctuation character may be backslash-escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5508:1-5512:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\!\"\#\$\%\&amp;\'\(\)\*\+\,\-\.\/\:\;\&lt;\=\&gt;\?\@\[\\\]\^\_\`\{\|\}\~</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;!&amp;quot;#$%&amp;amp;'()*+,-./:;&amp;lt;=&amp;gt;?@[\]^_`{|}~&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5515:1-5516:12" dir="auto">Backslashes before other characters are treated as literal
+backslashes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5518:1-5522:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\→\A\a\ \3\φ\«</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;\→\A\a\ \3\φ\«&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5525:1-5526:39" dir="auto">Escaped characters are treated as regular characters and do
+not have their usual Markdown meanings:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5528:1-5548:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\*not emphasized*</span>
+<span id="LC2" class="line" lang="plaintext">\&lt;br/&gt; not a tag</span>
+<span id="LC3" class="line" lang="plaintext">\[not a link](/foo)</span>
+<span id="LC4" class="line" lang="plaintext">\`not code`</span>
+<span id="LC5" class="line" lang="plaintext">1\. not a list</span>
+<span id="LC6" class="line" lang="plaintext">\* not a list</span>
+<span id="LC7" class="line" lang="plaintext">\# not a heading</span>
+<span id="LC8" class="line" lang="plaintext">\[foo]: /url "not a reference"</span>
+<span id="LC9" class="line" lang="plaintext">\&amp;ouml; not a character entity</span>
+<span id="LC10" class="line" lang="plaintext">.</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;*not emphasized*</span>
+<span id="LC12" class="line" lang="plaintext">&amp;lt;br/&amp;gt; not a tag</span>
+<span id="LC13" class="line" lang="plaintext">[not a link](/foo)</span>
+<span id="LC14" class="line" lang="plaintext">`not code`</span>
+<span id="LC15" class="line" lang="plaintext">1. not a list</span>
+<span id="LC16" class="line" lang="plaintext">* not a list</span>
+<span id="LC17" class="line" lang="plaintext"># not a heading</span>
+<span id="LC18" class="line" lang="plaintext">[foo]: /url &amp;quot;not a reference&amp;quot;</span>
+<span id="LC19" class="line" lang="plaintext">&amp;amp;ouml; not a character entity&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5551:1-5551:65" dir="auto">If a backslash is itself escaped, the following character is not:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5553:1-5557:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\\*emphasis*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;\&lt;em&gt;emphasis&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5560:1-5560:58" dir="auto">A backslash at the end of the line is a [hard line break]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5562:1-5568:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo\</span>
+<span id="LC2" class="line" lang="plaintext">bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5571:1-5572:9" dir="auto">Backslash escapes do not work in code blocks, code spans, autolinks, or
+raw HTML:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5574:1-5578:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`` \[\` ``</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;\[\`&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5581:1-5586:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> \[\]</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;\[\]</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5589:1-5596:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~~</span>
+<span id="LC2" class="line" lang="plaintext">\[\]</span>
+<span id="LC3" class="line" lang="plaintext">~~~</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;\[\]</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5599:1-5603:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://example.com?find=\*&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://example.com?find=%5C*"&gt;http://example.com?find=\*&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5606:1-5610:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="/bar\/)"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;a href="/bar\/)"&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5613:1-5614:60" dir="auto">But they work in all other contexts, including URLs and link titles,
+link references, and [info strings] in [fenced code blocks]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5616:1-5620:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo](/bar\* "ti\*tle")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/bar*" title="ti*tle"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5623:1-5629:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /bar\* "ti\*tle"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/bar*" title="ti*tle"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5632:1-5639:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` foo\+bar</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-foo+bar"&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="5643:1-5643:42" dir="auto">
+<a id="user-content-entity-and-numeric-character-references" class="anchor" href="#entity-and-numeric-character-references" aria-hidden="true"></a>Entity and numeric character references</h2>
+<p data-sourcepos="5645:1-5647:30" dir="auto">Valid HTML entity references and numeric character references
+can be used in place of the corresponding Unicode character,
+with the following exceptions:</p>
+<ul data-sourcepos="5649:1-5658:0" dir="auto">
+<li data-sourcepos="5649:1-5651:0">
+<p data-sourcepos="5649:3-5650:24">Entity and character references are not recognized in code
+blocks and code spans.</p>
+</li>
+<li data-sourcepos="5652:1-5658:0">
+<p data-sourcepos="5652:3-5657:9">Entity and character references cannot stand in place of
+special characters that define structural elements in
+CommonMark. For example, although <code>&amp;#42;</code> can be used
+in place of a literal <code>*</code> character, <code>&amp;#42;</code> cannot replace
+<code>*</code> in emphasis delimiters, bullet list markers, or thematic
+breaks.</p>
+</li>
+</ul>
+<p data-sourcepos="5659:1-5661:49" dir="auto">Conforming CommonMark parsers need not store information about
+whether a particular character was represented in the source
+using a Unicode character or an entity reference.</p>
+<p data-sourcepos="5663:1-5667:47" dir="auto"><a href="@">Entity references</a> consist of <code>&amp;</code> + any of the valid
+HTML5 entity names + <code>;</code>. The
+document <a href="https://html.spec.whatwg.org/multipage/entities.json" rel="nofollow noreferrer noopener" target="_blank">https://html.spec.whatwg.org/multipage/entities.json</a>
+is used as an authoritative source for the valid entity
+references and their corresponding code points.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5669:1-5677:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;nbsp; &amp;amp; &amp;copy; &amp;AElig; &amp;Dcaron;</span>
+<span id="LC2" class="line" lang="plaintext">&amp;frac34; &amp;HilbertSpace; &amp;DifferentialD;</span>
+<span id="LC3" class="line" lang="plaintext">&amp;ClockwiseContourIntegral; &amp;ngE;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;  &amp;amp; © Æ Ď</span>
+<span id="LC6" class="line" lang="plaintext">¾ ℋ ⅆ</span>
+<span id="LC7" class="line" lang="plaintext">∲ ≧̸&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5680:1-5686:58" dir="auto"><a href="@">Decimal numeric character
+references</a>
+consist of <code>&amp;#</code> + a string of 1--7 arabic digits + <code>;</code>. A
+numeric character reference is parsed as the corresponding
+Unicode character. Invalid Unicode code points will be replaced by
+the REPLACEMENT CHARACTER (<code>U+FFFD</code>). For security reasons,
+the code point <code>U+0000</code> will also be replaced by <code>U+FFFD</code>.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5688:1-5692:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;#35; &amp;#1234; &amp;#992; &amp;#0;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;# Ӓ Ϡ �&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5695:1-5699:62" dir="auto"><a href="@">Hexadecimal numeric character
+references</a> consist of <code>&amp;#</code> +
+either <code>X</code> or <code>x</code> + a string of 1-6 hexadecimal digits + <code>;</code>.
+They too are parsed as the corresponding Unicode character (this
+time specified with a hexadecimal numeral instead of decimal).</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5701:1-5705:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;#X22; &amp;#XD06; &amp;#xcab;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;quot; ആ ಫ&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5708:1-5708:26" dir="auto">Here are some nonentities:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5710:1-5720:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;nbsp &amp;x; &amp;#; &amp;#x;</span>
+<span id="LC2" class="line" lang="plaintext">&amp;#987654321;</span>
+<span id="LC3" class="line" lang="plaintext">&amp;#abcdef0;</span>
+<span id="LC4" class="line" lang="plaintext">&amp;ThisIsNotDefined; &amp;hi?;</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&amp;amp;nbsp &amp;amp;x; &amp;amp;#; &amp;amp;#x;</span>
+<span id="LC7" class="line" lang="plaintext">&amp;amp;#987654321;</span>
+<span id="LC8" class="line" lang="plaintext">&amp;amp;#abcdef0;</span>
+<span id="LC9" class="line" lang="plaintext">&amp;amp;ThisIsNotDefined; &amp;amp;hi?;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5723:1-5725:60" dir="auto">Although HTML5 does accept some entity references
+without a trailing semicolon (such as <code>&amp;copy</code>), these are not
+recognized here, because it makes the grammar too ambiguous:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5727:1-5731:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;copy</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;amp;copy&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5734:1-5735:39" dir="auto">Strings that are not on the list of HTML5 named entities are not
+recognized as entity references either:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5737:1-5741:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;MadeUpEntity;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;amp;MadeUpEntity;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5744:1-5746:62" dir="auto">Entity and numeric character references are recognized in any
+context besides code spans or code blocks, including
+URLs, [link titles], and [fenced code block][] [info strings]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5748:1-5752:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="&amp;ouml;&amp;ouml;.html"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;a href="&amp;ouml;&amp;ouml;.html"&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5755:1-5759:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo](/f&amp;ouml;&amp;ouml; "f&amp;ouml;&amp;ouml;")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/f%C3%B6%C3%B6" title="föö"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5762:1-5768:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /f&amp;ouml;&amp;ouml; "f&amp;ouml;&amp;ouml;"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/f%C3%B6%C3%B6" title="föö"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5771:1-5778:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` f&amp;ouml;&amp;ouml;</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">```</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;&lt;code class="language-föö"&gt;foo</span>
+<span id="LC6" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5781:1-5782:35" dir="auto">Entity and numeric character references are treated as literal
+text in code spans and code blocks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5784:1-5788:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`f&amp;ouml;&amp;ouml;`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;f&amp;amp;ouml;&amp;amp;ouml;&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5791:1-5796:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> f&amp;ouml;f&amp;ouml;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;pre&gt;&lt;code&gt;f&amp;amp;ouml;f&amp;amp;ouml;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;/code&gt;&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5799:1-5801:10" dir="auto">Entity and numeric character references cannot be used
+in place of symbols indicating structure in CommonMark
+documents.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5803:1-5809:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;#42;foo&amp;#42;</span>
+<span id="LC2" class="line" lang="plaintext">*foo*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;*foo*</span>
+<span id="LC5" class="line" lang="plaintext">&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5811:1-5820:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;#42; foo</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">* foo</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;* foo&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;li&gt;foo&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5822:1-5828:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo&amp;#10;&amp;#10;bar</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5830:1-5834:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&amp;#9;foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;→foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5837:1-5841:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[a](url &amp;quot;tit&amp;quot;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[a](url &amp;quot;tit&amp;quot;)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="5844:1-5844:13" dir="auto">
+<a id="user-content-code-spans" class="anchor" href="#code-spans" aria-hidden="true"></a>Code spans</h2>
+<p data-sourcepos="5846:1-5848:36" dir="auto">A <a href="@">backtick string</a>
+is a string of one or more backtick characters (<code>`</code>) that is neither
+preceded nor followed by a backtick.</p>
+<p data-sourcepos="5850:1-5853:15" dir="auto">A <a href="@">code span</a> begins with a backtick string and ends with
+a backtick string of equal length. The contents of the code span are
+the characters between the two backtick strings, normalized in the
+following ways:</p>
+<ul data-sourcepos="5855:1-5862:0" dir="auto">
+<li data-sourcepos="5855:1-5855:50">First, [line endings] are converted to [spaces].</li>
+<li data-sourcepos="5856:1-5862:0">If the resulting string both begins <em>and</em> ends with a [space]
+character, but does not consist entirely of [space]
+characters, a single [space] character is removed from the
+front and back. This allows you to include code that begins
+or ends with backtick characters, which must be separated by
+whitespace from the opening or closing backtick strings.</li>
+</ul>
+<p data-sourcepos="5863:1-5863:27" dir="auto">This is a simple code span:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5865:1-5869:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`foo`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5872:1-5874:15" dir="auto">Here two backticks are used, because the code contains a backtick.
+This example also illustrates stripping of a single leading and
+trailing space:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5876:1-5880:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`` foo ` bar ``</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo ` bar&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5883:1-5884:7" dir="auto">This example shows the motivation for stripping leading and trailing
+spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5886:1-5890:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` `` `</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;``&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5892:1-5892:39" dir="auto">Note that only <em>one</em> space is stripped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5894:1-5898:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` `` `</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt; `` &lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5900:1-5901:20" dir="auto">The stripping only happens if the space is on both
+sides of the string:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5903:1-5907:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` a`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt; a&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5909:1-5910:21" dir="auto">Only [spaces], and not [unicode whitespace] in general, are
+stripped in this way:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5912:1-5916:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` b `</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt; b &lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5918:1-5918:58" dir="auto">No stripping occurs if the code span contains only spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5920:1-5926:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` `</span>
+<span id="LC2" class="line" lang="plaintext">` `</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt; &lt;/code&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;code&gt; &lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5929:1-5929:39" dir="auto">[Line endings] are treated like spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5931:1-5939:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``</span>
+<span id="LC2" class="line" lang="plaintext">foo</span>
+<span id="LC3" class="line" lang="plaintext">bar </span>
+<span id="LC4" class="line" lang="plaintext">baz</span>
+<span id="LC5" class="line" lang="plaintext">``</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo bar baz&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5941:1-5947:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``</span>
+<span id="LC2" class="line" lang="plaintext">foo </span>
+<span id="LC3" class="line" lang="plaintext">``</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo &lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5950:1-5950:34" dir="auto">Interior spaces are not collapsed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5952:1-5957:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`foo bar </span>
+<span id="LC2" class="line" lang="plaintext">baz`</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo bar baz&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5959:1-5961:26" dir="auto">Note that browsers will typically collapse consecutive spaces
+when rendering <code>&lt;code&gt;</code> elements, so it is recommended that
+the following CSS be used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5963:5-5965:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code{white-space: pre-wrap;}</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5966:1-5967:22" dir="auto">Note that backslash escapes do not work in code spans. All backslashes
+are treated literally:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5969:1-5973:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`foo\`bar`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo\&lt;/code&gt;bar`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5976:1-5978:59" dir="auto">Backslash escapes are never needed, because one can always choose a
+string of <em>n</em> backtick characters as delimiters, where the code does
+not contain any strings of exactly <em>n</em> backtick characters.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5980:1-5984:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``foo`bar``</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo`bar&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5986:1-5990:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">` foo `` bar `</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;foo `` bar&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="5993:1-5996:5" dir="auto">Code span backticks have higher precedence than any other inline
+constructs except HTML tags and autolinks. Thus, for example, this is
+not parsed as emphasized text, since the second <code>*</code> is part of a code
+span:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="5998:1-6002:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo`*`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*foo&lt;code&gt;*&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6005:1-6005:33" dir="auto">And this is not parsed as a link:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6007:1-6011:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[not a `link](/foo`)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[not a &lt;code&gt;link](/foo&lt;/code&gt;)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6014:1-6015:19" dir="auto">Code spans, HTML tags, and autolinks have the same precedence.
+Thus, this is code:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6017:1-6021:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`&lt;a href="`"&gt;`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;&lt;/code&gt;&amp;quot;&amp;gt;`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6024:1-6024:24" dir="auto">But this is an HTML tag:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6026:1-6030:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="`"&gt;`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="`"&gt;`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6033:1-6033:17" dir="auto">And this is code:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6035:1-6039:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`&lt;http://foo.bar.`baz&gt;`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;&amp;lt;http://foo.bar.&lt;/code&gt;baz&amp;gt;`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6042:1-6042:24" dir="auto">But this is an autolink:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6044:1-6048:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://foo.bar.`baz&gt;`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://foo.bar.%60baz"&gt;http://foo.bar.`baz&lt;/a&gt;`&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6051:1-6052:31" dir="auto">When a backtick string is not closed by a matching backtick string,
+we just have literal backticks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6054:1-6058:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```foo``</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;```foo``&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6061:1-6065:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`foo</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;`foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6067:1-6068:47" dir="auto">The following case also illustrates the need for opening and
+closing backtick strings to be equal in length:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6070:1-6074:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`foo``bar``</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;`foo&lt;code&gt;bar&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="6077:1-6077:31" dir="auto">
+<a id="user-content-emphasis-and-strong-emphasis" class="anchor" href="#emphasis-and-strong-emphasis" aria-hidden="true"></a>Emphasis and strong emphasis</h2>
+<p data-sourcepos="6079:1-6080:73" dir="auto">John Gruber's original <a href="http://daringfireball.net/projects/markdown/syntax#em" rel="nofollow noreferrer noopener" target="_blank">Markdown syntax
+description</a> says:</p>
+<blockquote data-sourcepos="6082:1-6085:6" dir="auto">
+<p data-sourcepos="6082:3-6085:6">Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of
+emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an HTML
+<code>&lt;em&gt;</code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML <code>&lt;strong&gt;</code>
+tag.</p>
+</blockquote>
+<p data-sourcepos="6087:1-6091:57" dir="auto">This is enough for most users, but these rules leave much undecided,
+especially when it comes to nested emphasis. The original
+<code>Markdown.pl</code> test suite makes it clear that triple <code>***</code> and
+<code>___</code> delimiters can be used for strong emphasis, and most
+implementations have also allowed the following patterns:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6093:1-6099:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gs">***strong emph**</span><span class="err">*</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gs">***strong**</span> in emph<span class="err">*</span></span>
+<span id="LC3" class="line" lang="markdown"><span class="gs">***emph* in strong**</span></span>
+<span id="LC4" class="line" lang="markdown"><span class="gs">**in strong *emph**</span><span class="err">*</span></span>
+<span id="LC5" class="line" lang="markdown"><span class="ge">*in emph **strong***</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6101:1-6103:9" dir="auto">The following patterns are less widely supported, but the intent
+is clear and they are useful (especially in contexts like bibliography
+entries):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6105:1-6108:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="ge">*emph *</span>with emph<span class="ge">* in it*</span></span>
+<span id="LC2" class="line" lang="markdown"><span class="gs">**strong **</span>with strong<span class="gs">** in it**</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6110:1-6113:31" dir="auto">Many implementations have also restricted intraword emphasis to
+the <code>*</code> forms, to avoid unwanted emphasis in words containing
+internal underscores. (It is best practice to put these in code
+spans, but users often do not.)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6115:1-6118:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">internal emphasis: foo<span class="ge">*bar*</span>baz</span>
+<span id="LC2" class="line" lang="markdown">no emphasis: foo_bar_baz</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6120:1-6121:55" dir="auto">The rules given below capture all of these patterns, while allowing
+for efficient parsing strategies that do not backtrack.</p>
+<p data-sourcepos="6123:1-6127:38" dir="auto">First, some definitions. A <a href="@">delimiter run</a> is either
+a sequence of one or more <code>*</code> characters that is not preceded or
+followed by a non-backslash-escaped <code>*</code> character, or a sequence
+of one or more <code>_</code> characters that is not preceded or followed by
+a non-backslash-escaped <code>_</code> character.</p>
+<p data-sourcepos="6129:1-6135:37" dir="auto">A <a href="@">left-flanking delimiter run</a> is
+a [delimiter run] that is (1) not followed by [Unicode whitespace],
+and either (2a) not followed by a [punctuation character], or
+(2b) followed by a [punctuation character] and
+preceded by [Unicode whitespace] or a [punctuation character].
+For purposes of this definition, the beginning and the end of
+the line count as Unicode whitespace.</p>
+<p data-sourcepos="6137:1-6143:37" dir="auto">A <a href="@">right-flanking delimiter run</a> is
+a [delimiter run] that is (1) not preceded by [Unicode whitespace],
+and either (2a) not preceded by a [punctuation character], or
+(2b) preceded by a [punctuation character] and
+followed by [Unicode whitespace] or a [punctuation character].
+For purposes of this definition, the beginning and the end of
+the line count as Unicode whitespace.</p>
+<p data-sourcepos="6145:1-6145:41" dir="auto">Here are some examples of delimiter runs.</p>
+<ul data-sourcepos="6147:3-6178:0" dir="auto">
+<li data-sourcepos="6147:3-6155:0">
+<p data-sourcepos="6147:5-6147:41">left-flanking but not right-flanking:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6149:5-6154:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***abc</span>
+<span id="LC2" class="line" lang="plaintext"> _abc</span>
+<span id="LC3" class="line" lang="plaintext">**"abc"</span>
+<span id="LC4" class="line" lang="plaintext"> _"abc"</span></code></pre>
+<copy-code></copy-code>
+</div>
+</li>
+<li data-sourcepos="6156:3-6164:0">
+<p data-sourcepos="6156:5-6156:41">right-flanking but not left-flanking:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6158:5-6163:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> abc***</span>
+<span id="LC2" class="line" lang="plaintext"> abc_</span>
+<span id="LC3" class="line" lang="plaintext">"abc"**</span>
+<span id="LC4" class="line" lang="plaintext">"abc"_</span></code></pre>
+<copy-code></copy-code>
+</div>
+</li>
+<li data-sourcepos="6165:3-6171:0">
+<p data-sourcepos="6165:5-6165:33">Both left and right-flanking:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6167:5-6170:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> abc***def</span>
+<span id="LC2" class="line" lang="plaintext">"abc"_"def"</span></code></pre>
+<copy-code></copy-code>
+</div>
+</li>
+<li data-sourcepos="6172:3-6178:0">
+<p data-sourcepos="6172:5-6172:36">Neither left nor right-flanking:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6174:5-6177:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">abc *** def</span>
+<span id="LC2" class="line" lang="plaintext">a _ b</span></code></pre>
+<copy-code></copy-code>
+</div>
+</li>
+</ul>
+<p data-sourcepos="6179:1-6185:49" dir="auto">(The idea of distinguishing left-flanking and right-flanking
+delimiter runs based on the character before and the character
+after comes from Roopesh Chander's
+<a href="http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags" rel="nofollow noreferrer noopener" target="_blank">vfmd</a>.
+vfmd uses the terminology "emphasis indicator string" instead of "delimiter
+run," and its rules for distinguishing left- and right-flanking runs
+are a bit more complex than the ones given here.)</p>
+<p data-sourcepos="6187:1-6187:56" dir="auto">The following rules define emphasis and strong emphasis:</p>
+<ol data-sourcepos="6189:1-6253:0" dir="auto">
+<li data-sourcepos="6189:1-6191:0">
+<p data-sourcepos="6189:5-6190:71">A single <code>*</code> character <a href="@">can open emphasis</a>
+iff (if and only if) it is part of a [left-flanking delimiter run].</p>
+</li>
+<li data-sourcepos="6192:1-6197:0">
+<p data-sourcepos="6192:5-6196:28">A single <code>_</code> character [can open emphasis] iff
+it is part of a [left-flanking delimiter run]
+and either (a) not part of a [right-flanking delimiter run]
+or (b) part of a [right-flanking delimiter run]
+preceded by punctuation.</p>
+</li>
+<li data-sourcepos="6198:1-6200:0">
+<p data-sourcepos="6198:5-6199:55">A single <code>*</code> character <a href="@">can close emphasis</a>
+iff it is part of a [right-flanking delimiter run].</p>
+</li>
+<li data-sourcepos="6201:1-6206:0">
+<p data-sourcepos="6201:5-6205:28">A single <code>_</code> character [can close emphasis] iff
+it is part of a [right-flanking delimiter run]
+and either (a) not part of a [left-flanking delimiter run]
+or (b) part of a [left-flanking delimiter run]
+followed by punctuation.</p>
+</li>
+<li data-sourcepos="6207:1-6209:0">
+<p data-sourcepos="6207:5-6208:54">A double <code>**</code> <a href="@">can open strong emphasis</a>
+iff it is part of a [left-flanking delimiter run].</p>
+</li>
+<li data-sourcepos="6210:1-6215:0">
+<p data-sourcepos="6210:5-6214:28">A double <code>__</code> [can open strong emphasis] iff
+it is part of a [left-flanking delimiter run]
+and either (a) not part of a [right-flanking delimiter run]
+or (b) part of a [right-flanking delimiter run]
+preceded by punctuation.</p>
+</li>
+<li data-sourcepos="6216:1-6218:0">
+<p data-sourcepos="6216:5-6217:55">A double <code>**</code> <a href="@">can close strong emphasis</a>
+iff it is part of a [right-flanking delimiter run].</p>
+</li>
+<li data-sourcepos="6219:1-6224:0">
+<p data-sourcepos="6219:5-6223:28">A double <code>__</code> [can close strong emphasis] iff
+it is part of a [right-flanking delimiter run]
+and either (a) not part of a [left-flanking delimiter run]
+or (b) part of a [left-flanking delimiter run]
+followed by punctuation.</p>
+</li>
+<li data-sourcepos="6225:1-6234:0">
+<p data-sourcepos="6225:5-6233:19">Emphasis begins with a delimiter that [can open emphasis] and ends
+with a delimiter that [can close emphasis], and that uses the same
+character (<code>_</code> or <code>*</code>) as the opening delimiter. The
+opening and closing delimiters must belong to separate
+[delimiter runs]. If one of the delimiters can both
+open and close emphasis, then the sum of the lengths of the
+delimiter runs containing the opening and closing delimiters
+must not be a multiple of 3 unless both lengths are
+multiples of 3.</p>
+</li>
+<li data-sourcepos="6235:1-6245:0">
+<p data-sourcepos="6235:5-6244:23">Strong emphasis begins with a delimiter that
+[can open strong emphasis] and ends with a delimiter that
+[can close strong emphasis], and that uses the same character
+(<code>_</code> or <code>*</code>) as the opening delimiter. The
+opening and closing delimiters must belong to separate
+[delimiter runs]. If one of the delimiters can both open
+and close strong emphasis, then the sum of the lengths of
+the delimiter runs containing the opening and closing
+delimiters must not be a multiple of 3 unless both lengths
+are multiples of 3.</p>
+</li>
+<li data-sourcepos="6246:1-6249:0">
+<p data-sourcepos="6246:5-6248:25">A literal <code>*</code> character cannot occur at the beginning or end of
+<code>*</code>-delimited emphasis or <code>**</code>-delimited strong emphasis, unless it
+is backslash-escaped.</p>
+</li>
+<li data-sourcepos="6250:1-6253:0">
+<p data-sourcepos="6250:5-6252:25">A literal <code>_</code> character cannot occur at the beginning or end of
+<code>_</code>-delimited emphasis or <code>__</code>-delimited strong emphasis, unless it
+is backslash-escaped.</p>
+</li>
+</ol>
+<p data-sourcepos="6254:1-6255:43" dir="auto">Where rules 1--12 above are compatible with multiple parsings,
+the following principles resolve ambiguity:</p>
+<ol start="13" data-sourcepos="6257:1-6282:0" dir="auto">
+<li data-sourcepos="6257:1-6260:0">
+<p data-sourcepos="6257:5-6259:28">The number of nestings should be minimized. Thus, for example,
+an interpretation <code>&lt;strong&gt;...&lt;/strong&gt;</code> is always preferred to
+<code>&lt;em&gt;&lt;em&gt;...&lt;/em&gt;&lt;/em&gt;</code>.</p>
+</li>
+<li data-sourcepos="6261:1-6263:0">
+<p data-sourcepos="6261:5-6262:49">An interpretation <code>&lt;em&gt;&lt;strong&gt;...&lt;/strong&gt;&lt;/em&gt;</code> is always
+preferred to <code>&lt;strong&gt;&lt;em&gt;...&lt;/em&gt;&lt;/strong&gt;</code>.</p>
+</li>
+<li data-sourcepos="6264:1-6269:0">
+<p data-sourcepos="6264:5-6268:34">When two potential emphasis or strong emphasis spans overlap,
+so that the second begins before the first ends and ends after
+the first ends, the first takes precedence. Thus, for example,
+<code>*foo _bar* baz_</code> is parsed as <code>&lt;em&gt;foo _bar&lt;/em&gt; baz_</code> rather
+than <code>*foo &lt;em&gt;bar* baz&lt;/em&gt;</code>.</p>
+</li>
+<li data-sourcepos="6270:1-6275:0">
+<p data-sourcepos="6270:5-6274:49">When there are two potential emphasis or strong emphasis spans
+with the same closing delimiter, the shorter one (the one that
+opens later) takes precedence. Thus, for example,
+<code>**foo **bar baz**</code> is parsed as <code>**foo &lt;strong&gt;bar baz&lt;/strong&gt;</code>
+rather than <code>&lt;strong&gt;foo **bar baz&lt;/strong&gt;</code>.</p>
+</li>
+<li data-sourcepos="6276:1-6282:0">
+<p data-sourcepos="6276:5-6281:26">Inline code spans, links, images, and HTML tags group more tightly
+than emphasis. So, when there is a choice between an interpretation
+that contains one of these elements and one that does not, the
+former always wins. Thus, for example, <code>*[foo*](bar)</code> is
+parsed as <code>*&lt;a href="bar"&gt;foo*&lt;/a&gt;</code> rather than as
+<code>&lt;em&gt;[foo&lt;/em&gt;](bar)</code>.</p>
+</li>
+</ol>
+<p data-sourcepos="6283:1-6283:60" dir="auto">These rules can be illustrated through a series of examples.</p>
+<p data-sourcepos="6285:1-6285:7" dir="auto">Rule 1:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6287:1-6291:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo bar*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6294:1-6295:66" dir="auto">This is not emphasis, because the opening <code>*</code> is followed by
+whitespace, and hence not part of a [left-flanking delimiter run]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6297:1-6301:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a * foo bar*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;a * foo bar*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6304:1-6306:44" dir="auto">This is not emphasis, because the opening <code>*</code> is preceded
+by an alphanumeric and followed by punctuation, and hence
+not part of a [left-flanking delimiter run]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6308:1-6312:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a*"foo"*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;a*&amp;quot;foo&amp;quot;*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6315:1-6315:52" dir="auto">Unicode nonbreaking spaces count as whitespace, too:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6317:1-6321:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">* a *</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;* a *&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6324:1-6324:41" dir="auto">Intraword emphasis with <code>*</code> is permitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6326:1-6330:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo*bar*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo&lt;em&gt;bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6333:1-6337:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">5*6*78</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;5&lt;em&gt;6&lt;/em&gt;78&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6340:1-6340:7" dir="auto">Rule 2:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6342:1-6346:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo bar_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6349:1-6350:11" dir="auto">This is not emphasis, because the opening <code>_</code> is followed by
+whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6352:1-6356:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_ foo bar_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_ foo bar_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6359:1-6360:47" dir="auto">This is not emphasis, because the opening <code>_</code> is preceded
+by an alphanumeric and followed by punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6362:1-6366:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a_"foo"_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;a_&amp;quot;foo&amp;quot;_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6369:1-6369:46" dir="auto">Emphasis with <code>_</code> is not allowed inside words:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6371:1-6375:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo_bar_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo_bar_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6378:1-6382:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">5_6_78</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;5_6_78&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6385:1-6389:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">приÑтанÑм_ÑтремÑÑ‚ÑÑ_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;приÑтанÑм_ÑтремÑÑ‚ÑÑ_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6392:1-6393:47" dir="auto">Here <code>_</code> does not generate emphasis, because the first delimiter run
+is right-flanking and the second left-flanking:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6395:1-6399:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aa_"bb"_cc</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;aa_&amp;quot;bb&amp;quot;_cc&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6402:1-6404:12" dir="auto">This is emphasis, even though the opening delimiter is
+both left- and right-flanking, because it is preceded by
+punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6406:1-6410:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo-_(bar)_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo-&lt;em&gt;(bar)&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6413:1-6413:7" dir="auto">Rule 3:</p>
+<p data-sourcepos="6415:1-6416:32" dir="auto">This is not emphasis, because the closing delimiter does
+not match the opening delimiter:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6418:1-6422:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_foo*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6425:1-6426:11" dir="auto">This is not emphasis, because the closing <code>*</code> is preceded by
+whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6428:1-6432:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo bar *</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*foo bar *&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6435:1-6435:36" dir="auto">A newline also counts as whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6437:1-6443:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo bar</span>
+<span id="LC2" class="line" lang="plaintext">*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;*foo bar</span>
+<span id="LC5" class="line" lang="plaintext">*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6446:1-6448:58" dir="auto">This is not emphasis, because the second <code>*</code> is
+preceded by punctuation and followed by an alphanumeric
+(hence it is not part of a [right-flanking delimiter run]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6450:1-6454:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*(*foo)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*(*foo)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6457:1-6458:18" dir="auto">The point of this restriction is more easily appreciated
+with this example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6460:1-6464:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*(*foo*)*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;(&lt;em&gt;foo&lt;/em&gt;)&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6467:1-6467:39" dir="auto">Intraword emphasis with <code>*</code> is allowed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6469:1-6473:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo*bar</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6477:1-6477:7" dir="auto">Rule 4:</p>
+<p data-sourcepos="6479:1-6480:11" dir="auto">This is not emphasis, because the closing <code>_</code> is preceded by
+whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6482:1-6486:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo bar _</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_foo bar _&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6489:1-6490:56" dir="auto">This is not emphasis, because the second <code>_</code> is
+preceded by punctuation and followed by an alphanumeric:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6492:1-6496:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_(_foo)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_(_foo)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6499:1-6499:33" dir="auto">This is emphasis within emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6501:1-6505:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_(_foo_)_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;(&lt;em&gt;foo&lt;/em&gt;)&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6508:1-6508:41" dir="auto">Intraword emphasis is disallowed for <code>_</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6510:1-6514:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo_bar</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_foo_bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6517:1-6521:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_приÑтанÑм_ÑтремÑÑ‚ÑÑ</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_приÑтанÑм_ÑтремÑÑ‚ÑÑ&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6524:1-6528:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo_bar_baz_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo_bar_baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6531:1-6533:12" dir="auto">This is emphasis, even though the closing delimiter is
+both left- and right-flanking, because it is followed by
+punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6535:1-6539:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_(bar)_.</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;(bar)&lt;/em&gt;.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6542:1-6542:7" dir="auto">Rule 5:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6544:1-6548:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo bar**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6551:1-6552:23" dir="auto">This is not strong emphasis, because the opening delimiter is
+followed by whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6554:1-6558:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">** foo bar**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;** foo bar**&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6561:1-6563:44" dir="auto">This is not strong emphasis, because the opening <code>**</code> is preceded
+by an alphanumeric and followed by punctuation, and hence
+not part of a [left-flanking delimiter run]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6565:1-6569:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a**"foo"**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;a**&amp;quot;foo&amp;quot;**&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6572:1-6572:49" dir="auto">Intraword strong emphasis with <code>**</code> is permitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6574:1-6578:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo**bar**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo&lt;strong&gt;bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6581:1-6581:7" dir="auto">Rule 6:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6583:1-6587:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo bar__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6590:1-6591:23" dir="auto">This is not strong emphasis, because the opening delimiter is
+followed by whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6593:1-6597:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__ foo bar__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__ foo bar__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6600:1-6600:31" dir="auto">A newline counts as whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6601:1-6607:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__</span>
+<span id="LC2" class="line" lang="plaintext">foo bar__</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;__</span>
+<span id="LC5" class="line" lang="plaintext">foo bar__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6610:1-6611:47" dir="auto">This is not strong emphasis, because the opening <code>__</code> is preceded
+by an alphanumeric and followed by punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6613:1-6617:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a__"foo"__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;a__&amp;quot;foo&amp;quot;__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6620:1-6620:49" dir="auto">Intraword strong emphasis is forbidden with <code>__</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6622:1-6626:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo__bar__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo__bar__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6629:1-6633:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">5__6__78</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;5__6__78&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6636:1-6640:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">приÑтанÑм__ÑтремÑÑ‚ÑÑ__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;приÑтанÑм__ÑтремÑÑ‚ÑÑ__&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6643:1-6647:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo, __bar__, baz__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo, &lt;strong&gt;bar&lt;/strong&gt;, baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6650:1-6652:12" dir="auto">This is strong emphasis, even though the opening delimiter is
+both left- and right-flanking, because it is preceded by
+punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6654:1-6658:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo-__(bar)__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo-&lt;strong&gt;(bar)&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6662:1-6662:7" dir="auto">Rule 7:</p>
+<p data-sourcepos="6664:1-6665:14" dir="auto">This is not strong emphasis, because the closing delimiter is preceded
+by whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6667:1-6671:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo bar **</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**foo bar **&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6674:1-6675:9" dir="auto">(Nor can it be interpreted as an emphasized <code>*foo bar *</code>, because of
+Rule 11.)</p>
+<p data-sourcepos="6677:1-6678:56" dir="auto">This is not strong emphasis, because the second <code>**</code> is
+preceded by punctuation and followed by an alphanumeric:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6680:1-6684:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**(**foo)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**(**foo)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6687:1-6688:20" dir="auto">The point of this restriction is more easily appreciated
+with these examples:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6690:1-6694:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*(**foo**)*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;(&lt;strong&gt;foo&lt;/strong&gt;)&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6697:1-6703:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**Gomphocarpus (*Gomphocarpus physocarpus*, syn.</span>
+<span id="LC2" class="line" lang="plaintext">*Asclepias physocarpa*)**</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;Gomphocarpus (&lt;em&gt;Gomphocarpus physocarpus&lt;/em&gt;, syn.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;em&gt;Asclepias physocarpa&lt;/em&gt;)&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6706:1-6710:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo "*bar*" foo**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &amp;quot;&lt;em&gt;bar&lt;/em&gt;&amp;quot; foo&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6713:1-6713:19" dir="auto">Intraword emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6715:1-6719:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo**bar</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;/strong&gt;bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6722:1-6722:7" dir="auto">Rule 8:</p>
+<p data-sourcepos="6724:1-6725:23" dir="auto">This is not strong emphasis, because the closing delimiter is
+preceded by whitespace:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6727:1-6731:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo bar __</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__foo bar __&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6734:1-6735:56" dir="auto">This is not strong emphasis, because the second <code>__</code> is
+preceded by punctuation and followed by an alphanumeric:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6737:1-6741:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__(__foo)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__(__foo)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6744:1-6745:18" dir="auto">The point of this restriction is more easily appreciated
+with this example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6747:1-6751:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_(__foo__)_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;(&lt;strong&gt;foo&lt;/strong&gt;)&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6754:1-6754:49" dir="auto">Intraword strong emphasis is forbidden with <code>__</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6756:1-6760:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo__bar</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__foo__bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6763:1-6767:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__приÑтанÑм__ÑтремÑÑ‚ÑÑ</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__приÑтанÑм__ÑтремÑÑ‚ÑÑ&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6770:1-6774:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo__bar__baz__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo__bar__baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6777:1-6779:12" dir="auto">This is strong emphasis, even though the closing delimiter is
+both left- and right-flanking, because it is followed by
+punctuation:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6781:1-6785:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__(bar)__.</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;(bar)&lt;/strong&gt;.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6788:1-6788:7" dir="auto">Rule 9:</p>
+<p data-sourcepos="6790:1-6791:16" dir="auto">Any nonempty sequence of inline elements can be the contents of an
+emphasized span.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6793:1-6797:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo [bar](/url)*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;a href="/url"&gt;bar&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6800:1-6806:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo</span>
+<span id="LC2" class="line" lang="plaintext">bar*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6809:1-6810:16" dir="auto">In particular, emphasis and strong emphasis can be nested
+inside emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6812:1-6816:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo __bar__ baz_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;strong&gt;bar&lt;/strong&gt; baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6819:1-6823:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo _bar_ baz_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;em&gt;bar&lt;/em&gt; baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6826:1-6830:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo_ bar_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;em&gt;foo&lt;/em&gt; bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6833:1-6837:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo *bar**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;em&gt;bar&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6840:1-6844:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo **bar** baz*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;strong&gt;bar&lt;/strong&gt; baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6846:1-6850:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo**bar**baz*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;strong&gt;bar&lt;/strong&gt;baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6852:1-6852:51" dir="auto">Note that in the preceding case, the interpretation</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6854:1-6856:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="nt">&lt;p&gt;&lt;em&gt;</span>foo<span class="nt">&lt;/em&gt;&lt;em&gt;</span>bar<span class="nt">&lt;em&gt;&lt;/em&gt;</span>baz<span class="nt">&lt;/em&gt;&lt;/p&gt;</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6859:1-6864:32" dir="auto">is precluded by the condition that a delimiter that
+can both open and close (like the <code>*</code> after <code>foo</code>)
+cannot form emphasis if the sum of the lengths of
+the delimiter runs containing the opening and
+closing delimiters is a multiple of 3 unless
+both lengths are multiples of 3.</p>
+<p data-sourcepos="6867:1-6868:34" dir="auto">For the same reason, we don't get two consecutive
+emphasis sections in this example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6870:1-6874:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo**bar*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo**bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6877:1-6880:8" dir="auto">The same condition ensures that the following
+cases are all strong emphasis nested inside
+emphasis, even when the interior spaces are
+omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6883:1-6887:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***foo** bar*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;strong&gt;foo&lt;/strong&gt; bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6890:1-6894:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo **bar***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;strong&gt;bar&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6897:1-6901:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo**bar***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;strong&gt;bar&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6904:1-6906:34" dir="auto">When the lengths of the interior closing and opening
+delimiter runs are <em>both</em> multiples of 3, though,
+they can match to create emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6908:1-6912:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo***bar***baz</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo&lt;em&gt;&lt;strong&gt;bar&lt;/strong&gt;&lt;/em&gt;baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6914:1-6918:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo******bar*********baz</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;bar&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;***baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6921:1-6921:42" dir="auto">Indefinite levels of nesting are possible:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6923:1-6927:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo **bar *baz* bim** bop*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;strong&gt;bar &lt;em&gt;baz&lt;/em&gt; bim&lt;/strong&gt; bop&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6930:1-6934:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo [*bar*](/url)*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;a href="/url"&gt;&lt;em&gt;bar&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6937:1-6937:50" dir="auto">There can be no empty emphasis or strong emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6939:1-6943:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">** is not an empty emphasis</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;** is not an empty emphasis&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6946:1-6950:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**** is not an empty strong emphasis</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**** is not an empty strong emphasis&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6954:1-6954:8" dir="auto">Rule 10:</p>
+<p data-sourcepos="6956:1-6957:25" dir="auto">Any nonempty sequence of inline elements can be the contents of an
+strongly emphasized span.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6959:1-6963:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo [bar](/url)**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;a href="/url"&gt;bar&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6966:1-6972:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo</span>
+<span id="LC2" class="line" lang="plaintext">bar**</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="6975:1-6976:23" dir="auto">In particular, emphasis and strong emphasis can be nested
+inside strong emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6978:1-6982:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo _bar_ baz__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;em&gt;bar&lt;/em&gt; baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6985:1-6989:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo __bar__ baz__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;strong&gt;bar&lt;/strong&gt; baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6992:1-6996:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">____foo__ bar__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;&lt;strong&gt;foo&lt;/strong&gt; bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="6999:1-7003:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo **bar****</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;strong&gt;bar&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7006:1-7010:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo *bar* baz**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;em&gt;bar&lt;/em&gt; baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7013:1-7017:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo*bar*baz**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;em&gt;bar&lt;/em&gt;baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7020:1-7024:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***foo* bar**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;&lt;em&gt;foo&lt;/em&gt; bar&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7027:1-7031:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo *bar***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;em&gt;bar&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7034:1-7034:42" dir="auto">Indefinite levels of nesting are possible:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7036:1-7042:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo *bar **baz**</span>
+<span id="LC2" class="line" lang="plaintext">bim* bop**</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;em&gt;bar &lt;strong&gt;baz&lt;/strong&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bim&lt;/em&gt; bop&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7045:1-7049:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo [*bar*](/url)**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo &lt;a href="/url"&gt;&lt;em&gt;bar&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7052:1-7052:50" dir="auto">There can be no empty emphasis or strong emphasis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7054:1-7058:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__ is not an empty emphasis</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__ is not an empty emphasis&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7061:1-7065:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">____ is not an empty strong emphasis</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;____ is not an empty strong emphasis&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7069:1-7069:8" dir="auto">Rule 11:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7071:1-7075:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo ***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo ***&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7078:1-7082:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo *\**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;em&gt;*&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7085:1-7089:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo *_*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;em&gt;_&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7092:1-7096:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo *****</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo *****&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7099:1-7103:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo **\***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;strong&gt;*&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7106:1-7110:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo **_**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;strong&gt;_&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7113:1-7115:32" dir="auto">Note that when delimiters do not match evenly, Rule 11 determines
+that the excess literal <code>*</code> characters will appear outside of the
+emphasis, rather than inside it:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7117:1-7121:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7124:1-7128:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7131:1-7135:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***foo**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*&lt;strong&gt;foo&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7138:1-7142:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">****foo*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;***&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7145:1-7149:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;/strong&gt;*&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7152:1-7156:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo****</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;***&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7160:1-7160:8" dir="auto">Rule 12:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7162:1-7166:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo ___</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo ___&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7169:1-7173:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo _\__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;em&gt;_&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7176:1-7180:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo _*_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;em&gt;*&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7183:1-7187:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo _____</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo _____&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7190:1-7194:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo __\___</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;strong&gt;_&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7197:1-7201:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo __*__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;strong&gt;*&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7204:1-7208:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7211:1-7213:32" dir="auto">Note that when delimiters do not match evenly, Rule 12 determines
+that the excess literal <code>_</code> characters will appear outside of the
+emphasis, rather than inside it:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7215:1-7219:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7222:1-7226:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">___foo__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_&lt;strong&gt;foo&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7229:1-7233:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">____foo_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;___&lt;em&gt;foo&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7236:1-7240:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo___</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;/strong&gt;_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7243:1-7247:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo____</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;/em&gt;___&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7250:1-7251:44" dir="auto">Rule 13 implies that if you want emphasis nested directly inside
+emphasis, you must use different delimiters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7253:1-7257:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7260:1-7264:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*_foo_*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7267:1-7271:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__foo__</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7274:1-7278:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_*foo*_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7281:1-7282:21" dir="auto">However, strong emphasis within strong emphasis is possible without
+switching delimiters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7284:1-7288:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">****foo****</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7291:1-7295:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">____foo____</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7299:1-7300:11" dir="auto">Rule 13 can be applied to arbitrarily long sequences of
+delimiters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7302:1-7306:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">******foo******</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7309:1-7309:8" dir="auto">Rule 14:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7311:1-7315:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***foo***</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7318:1-7322:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_____foo_____</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;strong&gt;foo&lt;/strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7325:1-7325:8" dir="auto">Rule 15:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7327:1-7331:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo _bar* baz_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo _bar&lt;/em&gt; baz_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7334:1-7338:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo __bar *baz bim__ bam*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo &lt;strong&gt;bar *baz bim&lt;/strong&gt; bam&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7341:1-7341:8" dir="auto">Rule 16:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7343:1-7347:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**foo **bar baz**</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**foo &lt;strong&gt;bar baz&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7350:1-7354:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo *bar baz*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*foo &lt;em&gt;bar baz&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7357:1-7357:8" dir="auto">Rule 17:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7359:1-7363:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*[bar*](/url)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*&lt;a href="/url"&gt;bar*&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7366:1-7370:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_foo [bar_](/url)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;_foo &lt;a href="/url"&gt;bar_&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7373:1-7377:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*&lt;img src="foo" title="*"/&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*&lt;img src="foo" title="*"/&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7380:1-7384:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**&lt;a href="**"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**&lt;a href="**"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7387:1-7391:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__&lt;a href="__"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__&lt;a href="__"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7394:1-7398:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*a `*`*</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;a &lt;code&gt;*&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7401:1-7405:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">_a `_`_</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;a &lt;code&gt;_&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7408:1-7412:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">**a&lt;http://foo.bar/?q=**&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;**a&lt;a href="http://foo.bar/?q=**"&gt;http://foo.bar/?q=**&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7415:1-7419:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__a&lt;http://foo.bar/?q=__&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;__a&lt;a href="http://foo.bar/?q=__"&gt;http://foo.bar/?q=__&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div>
+<h2 data-sourcepos="7424:1-7424:28">
+<a id="user-content-strikethrough-extension" class="anchor" href="#strikethrough-extension" aria-hidden="true"></a>Strikethrough (extension)</h2>
+<p data-sourcepos="7426:1-7427:10">GFM enables the <code>strikethrough</code> extension, where an additional emphasis type is
+available.</p>
+<p data-sourcepos="7429:1-7429:59">Strikethrough text is any text wrapped in two tildes (<code>~</code>).</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7431:1-7435:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">~~Hi~~ Hello, world!</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;del&gt;Hi&lt;/del&gt; Hello, world!&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7437:1-7438:17">As with regular emphasis delimiters, a new paragraph will cause strikethrough
+parsing to cease:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7440:1-7447:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This ~~has a</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">new paragraph~~.</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;This ~~has a&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;new paragraph~~.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+</div>
+<h2 data-sourcepos="7451:1-7451:8" dir="auto">
+<a id="user-content-links" class="anchor" href="#links" aria-hidden="true"></a>Links</h2>
+<p data-sourcepos="7453:1-7458:13" dir="auto">A link contains [link text] (the visible text), a [link destination]
+(the URI that is the link destination), and optionally a [link title].
+There are two basic kinds of links in Markdown. In [inline links] the
+destination and title are given immediately after the link text. In
+[reference links] the destination and title are defined elsewhere in
+the document.</p>
+<p data-sourcepos="7460:1-7462:22" dir="auto">A <a href="@">link text</a> consists of a sequence of zero or more
+inline elements enclosed by square brackets (<code>[</code> and <code>]</code>). The
+following rules apply:</p>
+<ul data-sourcepos="7464:1-7480:0" dir="auto">
+<li data-sourcepos="7464:1-7467:0">
+<p data-sourcepos="7464:3-7466:43">Links may not contain other links, at any level of nesting. If
+multiple otherwise valid link definitions appear nested inside each
+other, the inner-most definition is used.</p>
+</li>
+<li data-sourcepos="7468:1-7472:0">
+<p data-sourcepos="7468:3-7471:22">Brackets are allowed in the [link text] only if (a) they
+are backslash-escaped or (b) they appear as a matched pair of brackets,
+with an open bracket <code>[</code>, a sequence of zero or more inlines, and
+a close bracket <code>]</code>.</p>
+</li>
+<li data-sourcepos="7473:1-7477:0">
+<p data-sourcepos="7473:3-7476:25">Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly
+than the brackets in link text. Thus, for example,
+<code>[foo`]`</code> could not be a link text, since the second <code>]</code>
+is part of a code span.</p>
+</li>
+<li data-sourcepos="7478:1-7480:0">
+<p data-sourcepos="7478:3-7479:78">The brackets in link text bind more tightly than markers for
+[emphasis and strong emphasis]. Thus, for example, <code>*[foo*](url)</code> is a link.</p>
+</li>
+</ul>
+<p data-sourcepos="7481:1-7481:42" dir="auto">A <a href="@">link destination</a> consists of either</p>
+<ul data-sourcepos="7483:1-7494:0" dir="auto">
+<li data-sourcepos="7483:1-7486:0">
+<p data-sourcepos="7483:3-7485:27">a sequence of zero or more characters between an opening <code>&lt;</code> and a
+closing <code>&gt;</code> that contains no line breaks or unescaped
+<code>&lt;</code> or <code>&gt;</code> characters, or</p>
+</li>
+<li data-sourcepos="7487:1-7494:0">
+<p data-sourcepos="7487:3-7493:23">a nonempty sequence of characters that does not start with
+<code>&lt;</code>, does not include ASCII space or control characters, and
+includes parentheses only if (a) they are backslash-escaped or
+(b) they are part of a balanced pair of unescaped parentheses.
+(Implementations may impose limits on parentheses nesting to
+avoid performance issues, but at least three levels of nesting
+should be supported.)</p>
+</li>
+</ul>
+<p data-sourcepos="7495:1-7495:37" dir="auto">A <a href="@">link title</a> consists of either</p>
+<ul data-sourcepos="7497:1-7508:0" dir="auto">
+<li data-sourcepos="7497:1-7500:0">
+<p data-sourcepos="7497:3-7499:23">a sequence of zero or more characters between straight double-quote
+characters (<code>"</code>), including a <code>"</code> character only if it is
+backslash-escaped, or</p>
+</li>
+<li data-sourcepos="7501:1-7504:0">
+<p data-sourcepos="7501:3-7503:23">a sequence of zero or more characters between straight single-quote
+characters (<code>'</code>), including a <code>'</code> character only if it is
+backslash-escaped, or</p>
+</li>
+<li data-sourcepos="7505:1-7508:0">
+<p data-sourcepos="7505:3-7507:20">a sequence of zero or more characters between matching parentheses
+(<code>(...)</code>), including a <code>(</code> or <code>)</code> character only if it is
+backslash-escaped.</p>
+</li>
+</ul>
+<p data-sourcepos="7509:1-7510:15" dir="auto">Although [link titles] may span multiple lines, they may not contain
+a [blank line].</p>
+<p data-sourcepos="7512:1-7522:6" dir="auto">An <a href="@">inline link</a> consists of a [link text] followed immediately
+by a left parenthesis <code>(</code>, optional [whitespace], an optional
+[link destination], an optional [link title] separated from the link
+destination by [whitespace], optional [whitespace], and a right
+parenthesis <code>)</code>. The link's text consists of the inlines contained
+in the [link text] (excluding the enclosing square brackets).
+The link's URI consists of the link destination, excluding enclosing
+<code>&lt;...&gt;</code> if present, with backslash-escapes in effect as described
+above. The link's title consists of the link title, excluding its
+enclosing delimiters, with backslash-escapes in effect as described
+above.</p>
+<p data-sourcepos="7524:1-7524:29" dir="auto">Here is a simple inline link:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7526:1-7530:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/uri "title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri" title="title"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7533:1-7533:25" dir="auto">The title may be omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7535:1-7539:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7542:1-7542:50" dir="auto">Both the title and the destination may be omitted:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7544:1-7548:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link]()</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href=""&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7551:1-7555:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](&lt;&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href=""&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7557:1-7558:28" dir="auto">The destination can only contain spaces if it is
+enclosed in pointy brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7560:1-7564:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/my uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link](/my uri)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7566:1-7570:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](&lt;/my uri&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/my%20uri"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7572:1-7573:36" dir="auto">The destination cannot contain line breaks,
+even if enclosed in pointy brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7575:1-7581:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo</span>
+<span id="LC2" class="line" lang="plaintext">bar)</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;[link](foo</span>
+<span id="LC5" class="line" lang="plaintext">bar)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7583:1-7589:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](&lt;foo</span>
+<span id="LC2" class="line" lang="plaintext">bar&gt;)</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;[link](&lt;foo</span>
+<span id="LC5" class="line" lang="plaintext">bar&gt;)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7591:1-7592:19" dir="auto">The destination can contain <code>)</code> if it is enclosed
+in pointy brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7594:1-7598:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[a](&lt;b)c&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="b)c"&gt;a&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7600:1-7600:53" dir="auto">Pointy brackets that enclose links must be unescaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7602:1-7606:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](&lt;foo\&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link](&amp;lt;foo&amp;gt;)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7608:1-7609:24" dir="auto">These are not links, because the opening pointy bracket
+is not matched properly:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7611:1-7619:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[a](&lt;b)c</span>
+<span id="LC2" class="line" lang="plaintext">[a](&lt;b)c&gt;</span>
+<span id="LC3" class="line" lang="plaintext">[a](&lt;b&gt;c)</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[a](&amp;lt;b)c</span>
+<span id="LC6" class="line" lang="plaintext">[a](&amp;lt;b)c&amp;gt;</span>
+<span id="LC7" class="line" lang="plaintext">[a](&lt;b&gt;c)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7621:1-7621:55" dir="auto">Parentheses inside the link destination may be escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7623:1-7627:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](\(foo\))</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="(foo)"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7629:1-7630:9" dir="auto">Any number of parentheses are allowed without escaping, as long as they are
+balanced:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7632:1-7636:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo(and(bar)))</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo(and(bar))"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7638:1-7639:13" dir="auto">However, if you have unbalanced parentheses, you need to escape or use the
+<code>&lt;...&gt;</code> form:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7641:1-7645:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo\(and\(bar\))</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo(and(bar)"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7648:1-7652:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](&lt;foo(and(bar)&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo(and(bar)"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7655:1-7656:12" dir="auto">Parentheses and other symbols can also be escaped, as usual
+in Markdown:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7658:1-7662:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo\)\:)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo):"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7665:1-7665:52" dir="auto">A link can contain fragment identifiers and queries:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7667:1-7677:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](#fragment)</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[link](http://example.com#fragment)</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[link](http://example.com?foo=3#frag)</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="#fragment"&gt;link&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://example.com#fragment"&gt;link&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://example.com?foo=3#frag"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7680:1-7681:17" dir="auto">Note that a backslash before a non-escapable character is
+just a backslash:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7683:1-7687:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo\bar)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo%5Cbar"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7690:1-7697:52" dir="auto">URL-escaping should be left alone inside the destination, as all
+URL-escaped characters are also valid URL characters. Entity and
+numerical character references in the destination will be parsed
+into the corresponding Unicode code points, as usual. These may
+be optionally URL-escaped when written as HTML, but this spec
+does not enforce any particular policy for rendering URLs in
+HTML or other formats. Renderers may make different decisions
+about how to escape or normalize URLs in the output.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7699:1-7703:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](foo%20b&amp;auml;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo%20b%C3%A4"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7706:1-7708:23" dir="auto">Note that, because titles can often be parsed as destinations,
+if you try to omit the destination and keep the title, you'll
+get unexpected results:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7710:1-7714:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link]("title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="%22title%22"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7717:1-7717:62" dir="auto">Titles may be in single quotes, double quotes, or parentheses:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7719:1-7727:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/url "title")</span>
+<span id="LC2" class="line" lang="plaintext">[link](/url 'title')</span>
+<span id="LC3" class="line" lang="plaintext">[link](/url (title))</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;link&lt;/a&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;a href="/url" title="title"&gt;link&lt;/a&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;a href="/url" title="title"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7730:1-7731:22" dir="auto">Backslash escapes and entity and numeric character references
+may be used in titles:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7733:1-7737:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/url "title \"&amp;quot;")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title &amp;quot;&amp;quot;"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7740:1-7741:64" dir="auto">Titles must be separated from the link using a [whitespace].
+Other [Unicode whitespace] like non-breaking space doesn't work.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7743:1-7747:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/url "title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url%C2%A0%22title%22"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7750:1-7750:56" dir="auto">Nested balanced quotes are not allowed without escaping:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7752:1-7756:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/url "title "and" title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link](/url &amp;quot;title &amp;quot;and&amp;quot; title&amp;quot;)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7759:1-7759:67" dir="auto">But it is easy to work around this by using a different quote type:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7761:1-7765:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link](/url 'title "and" title')</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title &amp;quot;and&amp;quot; title"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7768:1-7781:61" dir="auto">(Note: <code>Markdown.pl</code> did allow double quotes inside a double-quoted
+title, and its test suite included a test demonstrating this.
+But it is hard to see a good rationale for the extra complexity this
+brings, since there are already many ways---backslash escaping,
+entity and numeric character references, or using a different
+quote type for the enclosing title---to write titles containing
+double quotes. <code>Markdown.pl</code>'s handling of titles has a number
+of other strange features. For example, it allows single-quoted
+titles in inline links, but not reference links. And, in
+reference links but not inline links, it allows a title to begin
+with <code>"</code> and end with <code>)</code>. <code>Markdown.pl</code> 1.0.1 even allows
+titles with no closing quotation mark, though 1.0.2b8 does not.
+It seems preferable to adopt a simple, rational rule that works
+the same way in inline links and link reference definitions.)</p>
+<p data-sourcepos="7783:1-7783:57" dir="auto">[Whitespace] is allowed around the destination and title:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7785:1-7790:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link]( /uri</span>
+<span id="LC2" class="line" lang="plaintext"> "title" )</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri" title="title"&gt;link&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7793:1-7794:22" dir="auto">But it is not allowed between the link text and the
+following parenthesis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7796:1-7800:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link] (/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link] (/uri)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7803:1-7804:24" dir="auto">The link text may contain balanced brackets, but not unbalanced ones,
+unless they are escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7806:1-7810:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link [foo [bar]]](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link [foo [bar]]&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7813:1-7817:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link] bar](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link] bar](/uri)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7820:1-7824:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link [bar](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[link &lt;a href="/uri"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7827:1-7831:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link \[bar](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link [bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7834:1-7834:41" dir="auto">The link text may contain inline content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7836:1-7840:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link *foo **bar** `#`*](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link &lt;em&gt;foo &lt;strong&gt;bar&lt;/strong&gt; &lt;code&gt;#&lt;/code&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7843:1-7847:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[![moon](moon.jpg)](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;&lt;img src="moon.jpg" alt="moon" /&gt;&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7850:1-7850:68" dir="auto">However, links may not contain other links, at any level of nesting.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7852:1-7856:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo [bar](/uri)](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo &lt;a href="/uri"&gt;bar&lt;/a&gt;](/uri)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7859:1-7863:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo *[bar [baz](/uri)](/uri)*](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo &lt;em&gt;[bar &lt;a href="/uri"&gt;baz&lt;/a&gt;](/uri)&lt;/em&gt;](/uri)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7866:1-7870:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![[[foo](uri1)](uri2)](uri3)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="uri3" alt="[foo](uri2)" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7873:1-7874:18" dir="auto">These cases illustrate the precedence of link text grouping over
+emphasis grouping:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7876:1-7880:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*[foo*](/uri)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;*&lt;a href="/uri"&gt;foo*&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7883:1-7887:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo *bar](baz*)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="baz*"&gt;foo *bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7890:1-7891:11" dir="auto">Note that brackets that <em>aren't</em> part of links do not take
+precedence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7893:1-7897:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo [bar* baz]</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo [bar&lt;/em&gt; baz]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7900:1-7901:33" dir="auto">These cases illustrate the precedence of HTML tags, code spans,
+and autolinks over link grouping:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7903:1-7907:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo &lt;bar attr="](baz)"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo &lt;bar attr="](baz)"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7910:1-7914:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo`](/uri)`</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo&lt;code&gt;](/uri)&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7917:1-7921:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo&lt;http://example.com/?search=](uri)&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;[foo&lt;a href="http://example.com/?search=%5D(uri)"&gt;http://example.com/?search=](uri)&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7924:1-7926:41" dir="auto">There are three kinds of <a href="@">reference link</a>s:
+<a href="#full-reference-link">full</a>, <a href="#collapsed-reference-link">collapsed</a>,
+and <a href="#shortcut-reference-link">shortcut</a>.</p>
+<p data-sourcepos="7928:1-7930:71" dir="auto">A <a href="@">full reference link</a>
+consists of a [link text] immediately followed by a [link label]
+that [matches] a [link reference definition] elsewhere in the document.</p>
+<p data-sourcepos="7932:1-7938:9" dir="auto">A <a href="@">link label</a> begins with a left bracket (<code>[</code>) and ends
+with the first right bracket (<code>]</code>) that is not backslash-escaped.
+Between these brackets there must be at least one [non-whitespace character].
+Unescaped square bracket characters are not allowed inside the
+opening and closing square brackets of [link labels]. A link
+label can have at most 999 characters inside the square
+brackets.</p>
+<p data-sourcepos="7940:1-7947:69" dir="auto">One label <a href="@">matches</a>
+another just in case their normalized forms are equal. To normalize a
+label, strip off the opening and closing brackets,
+perform the <em>Unicode case fold</em>, strip leading and trailing
+[whitespace] and collapse consecutive internal
+[whitespace] to a single space. If there are multiple
+matching reference link definitions, the one that comes first in the
+document is used. (It is desirable in such cases to emit a warning.)</p>
+<p data-sourcepos="7949:1-7951:37" dir="auto">The contents of the first link label are parsed as inlines, which are
+used as the link's text. The link's URI and title are provided by the
+matching [link reference definition].</p>
+<p data-sourcepos="7953:1-7953:25" dir="auto">Here is a simple example:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7955:1-7961:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7964:1-7965:22" dir="auto">The rules for the [link text] are the same as with
+[inline links]. Thus:</p>
+<p data-sourcepos="7967:1-7968:24" dir="auto">The link text may contain balanced brackets, but not unbalanced ones,
+unless they are escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7970:1-7976:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link [foo [bar]]][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link [foo [bar]]&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7979:1-7985:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link \[bar][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link [bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="7988:1-7988:41" dir="auto">The link text may contain inline content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7990:1-7996:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[link *foo **bar** `#`*][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;link &lt;em&gt;foo &lt;strong&gt;bar&lt;/strong&gt; &lt;code&gt;#&lt;/code&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="7999:1-8005:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[![moon](moon.jpg)][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;&lt;img src="moon.jpg" alt="moon" /&gt;&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8008:1-8008:68" dir="auto">However, links may not contain other links, at any level of nesting.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8010:1-8016:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo [bar](/uri)][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo &lt;a href="/uri"&gt;bar&lt;/a&gt;]&lt;a href="/uri"&gt;ref&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8019:1-8025:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo *bar [baz][ref]*][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo &lt;em&gt;bar &lt;a href="/uri"&gt;baz&lt;/a&gt;&lt;/em&gt;]&lt;a href="/uri"&gt;ref&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8028:1-8029:38" dir="auto">(In the examples above, we have two [shortcut reference links]
+instead of one [full reference link].)</p>
+<p data-sourcepos="8031:1-8032:18" dir="auto">The following cases illustrate the precedence of link text grouping over
+emphasis grouping:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8034:1-8040:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*[foo*][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;*&lt;a href="/uri"&gt;foo*&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8043:1-8049:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo *bar][ref]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;foo *bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8052:1-8053:33" dir="auto">These cases illustrate the precedence of HTML tags, code spans,
+and autolinks over link grouping:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8055:1-8061:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo &lt;bar attr="][ref]"&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo &lt;bar attr="][ref]"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8064:1-8070:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo`][ref]`</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo&lt;code&gt;][ref]&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8073:1-8079:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo&lt;http://example.com/?search=][ref]&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo&lt;a href="http://example.com/?search=%5D%5Bref%5D"&gt;http://example.com/?search=][ref]&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8082:1-8082:29" dir="auto">Matching is case-insensitive:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8084:1-8090:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][BaR]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8093:1-8093:26" dir="auto">Unicode case fold is used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8095:1-8101:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Толпой][Толпой] is a Russian word.</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ТОЛПОЙ]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;Толпой&lt;/a&gt; is a Russian word.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8104:1-8105:33" dir="auto">Consecutive internal [whitespace] is treated as one space for
+purposes of determining matching:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8107:1-8114:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Foo</span>
+<span id="LC2" class="line" lang="plaintext"> bar]: /url</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[Baz][Foo bar]</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;Baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8117:1-8118:13" dir="auto">No [whitespace] is allowed between the [link text] and the
+[link label]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8120:1-8126:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo] [bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo] &lt;a href="/url" title="title"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8129:1-8137:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext">[bar]</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[bar]: /url "title"</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[foo]</span>
+<span id="LC7" class="line" lang="plaintext">&lt;a href="/url" title="title"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8140:1-8149:9" dir="auto">This is a departure from John Gruber's original Markdown syntax
+description, which explicitly allows whitespace between the link
+text and the link label. It brings reference links in line with
+[inline links], which (according to both original Markdown and
+this spec) cannot have whitespace after the link text. More
+importantly, it prevents inadvertent capture of consecutive
+[shortcut reference links]. If whitespace is allowed between the
+link text and the link label, then in the following we will have
+a single reference link, not two shortcut reference links, as
+intended:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8151:1-8157:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">[foo]</span>
+<span id="LC2" class="line" lang="markdown">[bar]</span>
+<span id="LC3" class="line" lang="markdown"></span>
+<span id="LC4" class="line" lang="markdown"><span class="p">[</span><span class="ss">foo</span><span class="p">]:</span> <span class="sx">/url1</span></span>
+<span id="LC5" class="line" lang="markdown"><span class="p">[</span><span class="ss">bar</span><span class="p">]:</span> <span class="sx">/url2</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8159:1-8165:20" dir="auto">(Note that [shortcut reference links] were introduced by Gruber
+himself in a beta version of <code>Markdown.pl</code>, but never included
+in the official syntax description. Without shortcut reference
+links, it is harmless to allow space between the link text and
+link label; but once shortcut references are introduced, it is
+too dangerous to allow this, as it frequently leads to
+unintended results.)</p>
+<p data-sourcepos="8167:1-8168:18" dir="auto">When there are multiple matching [link reference definitions],
+the first is used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8170:1-8178:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url1</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url2</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">[bar][foo]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url1"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8181:1-8183:40" dir="auto">Note that matching is performed on normalized strings, not parsed
+inline content. So the following does not match, even though the
+labels define equivalent inline content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8185:1-8191:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[bar][foo\!]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo!]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[bar][foo!]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8194:1-8195:18" dir="auto">[Link labels] cannot contain brackets, unless they are
+backslash-escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8197:1-8204:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][ref[]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref[]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo][ref[]&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[ref[]: /uri&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8207:1-8214:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][ref[bar]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref[bar]]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo][ref[bar]]&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[ref[bar]]: /uri&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8217:1-8224:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[[foo]]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[[[foo]]]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[[[foo]]]&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[[[foo]]]: /url&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8227:1-8233:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][ref\[]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[ref\[]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8236:1-8236:55" dir="auto">Note that in this example <code>]</code> is not backslash-escaped:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8238:1-8244:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[bar\\]: /uri</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[bar\\]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/uri"&gt;bar\&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8247:1-8247:68" dir="auto">A [link label] must contain at least one [non-whitespace character]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8249:1-8256:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[]: /uri</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[]&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[]: /uri&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8259:1-8270:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[</span>
+<span id="LC2" class="line" lang="plaintext"> ]</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[</span>
+<span id="LC5" class="line" lang="plaintext"> ]: /uri</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;[</span>
+<span id="LC8" class="line" lang="plaintext">]&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;[</span>
+<span id="LC10" class="line" lang="plaintext">]: /uri&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8273:1-8280:40" dir="auto">A <a href="@">collapsed reference link</a>
+consists of a [link label] that [matches] a
+[link reference definition] elsewhere in the
+document, followed by the string <code>[]</code>.
+The contents of the first link label are parsed as inlines,
+which are used as the link's text. The link's URI and title are
+provided by the matching reference link definition. Thus,
+<code>[foo][]</code> is equivalent to <code>[foo][foo]</code>.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8282:1-8288:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8291:1-8297:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[*foo* bar][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[*foo* bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;&lt;em&gt;foo&lt;/em&gt; bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8300:1-8300:37" dir="auto">The link labels are case-insensitive:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8302:1-8308:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Foo][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;Foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8312:1-8313:41" dir="auto">As with full reference links, [whitespace] is not
+allowed between the two sets of brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8315:1-8323:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo] </span>
+<span id="LC2" class="line" lang="plaintext">[]</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;</span>
+<span id="LC7" class="line" lang="plaintext">[]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8326:1-8333:41" dir="auto">A <a href="@">shortcut reference link</a>
+consists of a [link label] that [matches] a
+[link reference definition] elsewhere in the
+document and is not followed by <code>[]</code> or a link label.
+The contents of the first link label are parsed as inlines,
+which are used as the link's text. The link's URI and title
+are provided by the matching link reference definition.
+Thus, <code>[foo]</code> is equivalent to <code>[foo][]</code>.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8335:1-8341:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8344:1-8350:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[*foo* bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[*foo* bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;&lt;em&gt;foo&lt;/em&gt; bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8353:1-8359:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[*foo* bar]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[*foo* bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[&lt;a href="/url" title="title"&gt;&lt;em&gt;foo&lt;/em&gt; bar&lt;/a&gt;]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8362:1-8368:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[bar [foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[[bar &lt;a href="/url"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8371:1-8371:37" dir="auto">The link labels are case-insensitive:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8373:1-8379:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[Foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url" title="title"&gt;Foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8382:1-8382:48" dir="auto">A space after the link text should be preserved:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8384:1-8390:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo] bar</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url"&gt;foo&lt;/a&gt; bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8393:1-8394:31" dir="auto">If you just want bracketed text, you can backslash-escape the
+opening bracket to avoid links:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8396:1-8402:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8405:1-8406:26" dir="auto">Note that this is a link, because a link label ends with the first
+following closing bracket:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8408:1-8414:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo*]: /url</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">*[foo*]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;*&lt;a href="/url"&gt;foo*&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8417:1-8418:11" dir="auto">Full and compact references take precedence over shortcut
+references:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8420:1-8427:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">[bar]: /url2</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url2"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8429:1-8435:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url1"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8437:1-8437:34" dir="auto">Inline links also take precedence:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8439:1-8445:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]()</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href=""&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8447:1-8453:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo](not a link)</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url1"&gt;foo&lt;/a&gt;(not a link)&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8455:1-8456:23" dir="auto">In the following case <code>[bar][baz]</code> is parsed as a reference,
+<code>[foo]</code> as normal text:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8458:1-8464:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][bar][baz]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[baz]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;a href="/url"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8467:1-8468:19" dir="auto">Here, though, <code>[foo][bar]</code> is parsed as a reference, since
+<code>[bar]</code> is defined:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8470:1-8477:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][bar][baz]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[baz]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">[bar]: /url2</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="/url2"&gt;foo&lt;/a&gt;&lt;a href="/url1"&gt;baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8480:1-8481:65" dir="auto">Here <code>[foo]</code> is not parsed as a shortcut reference, because it
+is followed by a link label (even though <code>[bar]</code> is not defined):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8483:1-8490:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo][bar][baz]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[baz]: /url1</span>
+<span id="LC4" class="line" lang="plaintext">[foo]: /url2</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[foo]&lt;a href="/url1"&gt;bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="8494:1-8494:9" dir="auto">
+<a id="user-content-images" class="anchor" href="#images" aria-hidden="true"></a>Images</h2>
+<p data-sourcepos="8496:1-8504:55" dir="auto">Syntax for images is like the syntax for links, with one
+difference. Instead of [link text], we have an
+<a href="@">image description</a>. The rules for this are the
+same as for [link text], except that (a) an
+image description starts with <code>![</code> rather than <code>[</code>, and
+(b) an image description may contain links.
+An image description has inline elements
+as its contents. When an image is rendered to HTML,
+this is standardly used as the image's <code>alt</code> attribute.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8506:1-8510:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo](/url "title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8513:1-8519:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo *bar*]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo *bar*]: train.jpg "train &amp; tracks"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="train.jpg" alt="foo bar" title="train &amp;amp; tracks" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8522:1-8526:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo ![bar](/url)](/url2)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url2" alt="foo bar" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8529:1-8533:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo [bar](/url)](/url2)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url2" alt="foo bar" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8536:1-8541:40" dir="auto">Though this spec is concerned with parsing, not rendering, it is
+recommended that in rendering to HTML, only the plain string content
+of the [image description] be used. Note that in
+the above example, the alt attribute's value is <code>foo bar</code>, not <code>foo [bar](/url)</code> or <code>foo &lt;a href="/url"&gt;bar&lt;/a&gt;</code>. Only the plain string
+content is rendered, without formatting.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8543:1-8549:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo *bar*][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo *bar*]: train.jpg "train &amp; tracks"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="train.jpg" alt="foo bar" title="train &amp;amp; tracks" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8552:1-8558:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo *bar*][foobar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[FOOBAR]: train.jpg "train &amp; tracks"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="train.jpg" alt="foo bar" title="train &amp;amp; tracks" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8561:1-8565:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo](train.jpg)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="train.jpg" alt="foo" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8568:1-8572:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">My ![foo bar](/path/to/train.jpg "title" )</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;My &lt;img src="/path/to/train.jpg" alt="foo bar" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8575:1-8579:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo](&lt;url&gt;)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="url" alt="foo" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8582:1-8586:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![](/url)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8589:1-8589:16" dir="auto">Reference-style:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8591:1-8597:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo][bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[bar]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8600:1-8606:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo][bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[BAR]: /url</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8609:1-8609:10" dir="auto">Collapsed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8611:1-8617:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8620:1-8626:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![*foo* bar][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[*foo* bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo bar" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8629:1-8629:32" dir="auto">The labels are case-insensitive:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8631:1-8637:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![Foo][]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="Foo" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8640:1-8641:33" dir="auto">As with reference links, [whitespace] is not allowed
+between the two sets of brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8643:1-8651:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo] </span>
+<span id="LC2" class="line" lang="plaintext">[]</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" title="title" /&gt;</span>
+<span id="LC7" class="line" lang="plaintext">[]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8654:1-8654:9" dir="auto">Shortcut:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8656:1-8662:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8665:1-8671:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![*foo* bar]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[*foo* bar]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="foo bar" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8674:1-8674:56" dir="auto">Note that link labels cannot contain unescaped brackets:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8676:1-8683:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![[foo]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[[foo]]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;![[foo]]&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;[[foo]]: /url &amp;quot;title&amp;quot;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8686:1-8686:37" dir="auto">The link labels are case-insensitive:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8688:1-8694:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![Foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;img src="/url" alt="Foo" title="title" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8697:1-8698:33" dir="auto">If you just want a literal <code>!</code> followed by bracketed text, you can
+backslash-escape the opening <code>[</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8700:1-8706:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">!\[foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;![foo]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8709:1-8710:4" dir="auto">If you want a link after a literal <code>!</code>, backslash-escape the
+<code>!</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8712:1-8718:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\![foo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[foo]: /url "title"</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;!&lt;a href="/url" title="title"&gt;foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="8721:1-8721:12" dir="auto">
+<a id="user-content-autolinks" class="anchor" href="#autolinks" aria-hidden="true"></a>Autolinks</h2>
+<p data-sourcepos="8723:1-8725:18" dir="auto"><a href="@">Autolink</a>s are absolute URIs and email addresses inside
+<code>&lt;</code> and <code>&gt;</code>. They are parsed as links, with the URL or email address
+as the link label.</p>
+<p data-sourcepos="8727:1-8729:52" dir="auto">A <a href="@">URI autolink</a> consists of <code>&lt;</code>, followed by an
+[absolute URI] followed by <code>&gt;</code>. It is parsed as
+a link to the URI, with the URI as the link's label.</p>
+<p data-sourcepos="8731:1-8736:25" dir="auto">An <a href="@">absolute URI</a>,
+for these purposes, consists of a [scheme] followed by a colon (<code>:</code>)
+followed by zero or more characters other than ASCII
+[whitespace] and control characters, <code>&lt;</code>, and <code>&gt;</code>. If
+the URI includes these characters, they must be percent-encoded
+(e.g. <code>%20</code> for a space).</p>
+<p data-sourcepos="8738:1-8741:37" dir="auto">For purposes of this spec, a <a href="@">scheme</a> is any sequence
+of 2--32 characters beginning with an ASCII letter and followed
+by any combination of ASCII letters, digits, or the symbols plus
+("+"), period ("."), or hyphen ("-").</p>
+<p data-sourcepos="8743:1-8743:30" dir="auto">Here are some valid autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8745:1-8749:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://foo.bar.baz&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://foo.bar.baz"&gt;http://foo.bar.baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8752:1-8756:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://foo.bar.baz/test?q=hello&amp;amp;id=22&amp;amp;boolean"&gt;http://foo.bar.baz/test?q=hello&amp;amp;id=22&amp;amp;boolean&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8759:1-8763:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;irc://foo.bar:2233/baz&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="irc://foo.bar:2233/baz"&gt;irc://foo.bar:2233/baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8766:1-8766:23" dir="auto">Uppercase is also fine:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8768:1-8772:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;MAILTO:FOO@BAR.BAZ&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="MAILTO:FOO@BAR.BAZ"&gt;MAILTO:FOO@BAR.BAZ&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8775:1-8778:18" dir="auto">Note that many strings that count as [absolute URIs] for
+purposes of this spec are not valid URIs, because their
+schemes are not registered or because of other problems
+with their syntax:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8780:1-8784:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a+b+c:d&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="a+b+c:d"&gt;a+b+c:d&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8787:1-8791:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;made-up-scheme://foo,bar&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="made-up-scheme://foo,bar"&gt;made-up-scheme://foo,bar&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8794:1-8798:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://../&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://../"&gt;http://../&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8801:1-8805:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;localhost:5001/foo&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="localhost:5001/foo"&gt;localhost:5001/foo&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8808:1-8808:36" dir="auto">Spaces are not allowed in autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8810:1-8814:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://foo.bar/baz bim&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;http://foo.bar/baz bim&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8817:1-8817:47" dir="auto">Backslash-escapes do not work inside autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8819:1-8823:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;http://example.com/\[\&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://example.com/%5C%5B%5C"&gt;http://example.com/\[\&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8826:1-8829:55" dir="auto">An <a href="@">email autolink</a>
+consists of <code>&lt;</code>, followed by an [email address],
+followed by <code>&gt;</code>. The link's label is the email address,
+and the URL is <code>mailto:</code> followed by the email address.</p>
+<p data-sourcepos="8831:1-8834:83" dir="auto">An <a href="@">email address</a>,
+for these purposes, is anything that matches
+the <a href="https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)" rel="nofollow noreferrer noopener" target="_blank">non-normative regex from the HTML5
+spec</a>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8836:5-8838:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">/^[a-zA-Z0-9.!#$%&amp;'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?</span>
+<span id="LC2" class="line" lang="plaintext">(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8839:1-8839:28" dir="auto">Examples of email autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8841:1-8845:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;foo@bar.example.com&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="mailto:foo@bar.example.com"&gt;foo@bar.example.com&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8848:1-8852:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;foo+special@Bar.baz-bar0.com&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="mailto:foo+special@Bar.baz-bar0.com"&gt;foo+special@Bar.baz-bar0.com&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8855:1-8855:53" dir="auto">Backslash-escapes do not work inside email autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8857:1-8861:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;foo\+@bar.example.com&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;foo+@bar.example.com&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8864:1-8864:24" dir="auto">These are not autolinks:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8866:1-8870:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8873:1-8877:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt; http://foo.bar &gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt; http://foo.bar &amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8880:1-8884:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;m:abc&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;m:abc&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8887:1-8891:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;foo.bar.baz&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;foo.bar.baz&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8894:1-8898:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">http://example.com</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;http://example.com&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8901:1-8905:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo@bar.example.com</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo@bar.example.com&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div>
+<h2 data-sourcepos="8909:1-8909:24">
+<a id="user-content-autolinks-extension" class="anchor" href="#autolinks-extension" aria-hidden="true"></a>Autolinks (extension)</h2>
+<p data-sourcepos="8911:1-8912:29">GFM enables the <code>autolink</code> extension, where autolinks will be recognised in a
+greater number of conditions.</p>
+<p data-sourcepos="8914:1-8918:8">[Autolink]s can also be constructed without requiring the use of <code>&lt;</code> and to <code>&gt;</code>
+to delimit them, although they will be recognized under a smaller set of
+circumstances. All such recognized autolinks can only come at the beginning of
+a line, after whitespace, or any of the delimiting characters <code>*</code>, <code>_</code>, <code>~</code>,
+and <code>(</code>.</p>
+<p data-sourcepos="8920:1-8926:73">An <a href="@">extended www autolink</a> will be recognized
+when the text <code>www.</code> is found followed by a [valid domain].
+A <a href="@">valid domain</a> consists of segments
+of alphanumeric characters, underscores (<code>_</code>) and hyphens (<code>-</code>)
+separated by periods (<code>.</code>).
+There must be at least one period,
+and no underscores may be present in the last two segments of the domain.</p>
+<p data-sourcepos="8928:1-8928:49">The scheme <code>http</code> will be inserted automatically:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8930:1-8934:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">www.commonmark.org</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.commonmark.org"&gt;www.commonmark.org&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8936:1-8936:77">After a [valid domain], zero or more non-space non-<code>&lt;</code> characters may follow:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8938:1-8942:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Visit www.commonmark.org/help for more information.</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;Visit &lt;a href="http://www.commonmark.org/help"&gt;www.commonmark.org/help&lt;/a&gt; for more information.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8944:1-8944:64">We then apply <a href="@">extended autolink path validation</a> as follows:</p>
+<p data-sourcepos="8946:1-8948:21">Trailing punctuation (specifically, <code>?</code>, <code>!</code>, <code>.</code>, <code>,</code>, <code>:</code>, <code>*</code>, <code>_</code>, and <code>~</code>)
+will not be considered part of the autolink, though they may be included in the
+interior of the link:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8950:1-8957:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Visit www.commonmark.org.</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">Visit www.commonmark.org/a.b.</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;Visit &lt;a href="http://www.commonmark.org"&gt;www.commonmark.org&lt;/a&gt;.&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;Visit &lt;a href="http://www.commonmark.org/a.b"&gt;www.commonmark.org/a.b&lt;/a&gt;.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8959:1-8962:76">When an autolink ends in <code>)</code>, we scan the entire autolink for the total number
+of parentheses. If there is a greater number of closing parentheses than
+opening ones, we don't consider the unmatched trailing parentheses part of the
+autolink, in order to facilitate including an autolink inside a parenthesis:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8964:1-8977:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">www.google.com/search?q=Markup+(business)</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">www.google.com/search?q=Markup+(business)))</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">(www.google.com/search?q=Markup+(business))</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext">(www.google.com/search?q=Markup+(business)</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.google.com/search?q=Markup+(business)"&gt;www.google.com/search?q=Markup+(business)&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.google.com/search?q=Markup+(business)"&gt;www.google.com/search?q=Markup+(business)&lt;/a&gt;))&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;(&lt;a href="http://www.google.com/search?q=Markup+(business)"&gt;www.google.com/search?q=Markup+(business)&lt;/a&gt;)&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;(&lt;a href="http://www.google.com/search?q=Markup+(business)"&gt;www.google.com/search?q=Markup+(business)&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8979:1-8981:8">This check is only done when the link ends in a closing parentheses <code>)</code>, so if
+the only parentheses are in the interior of the autolink, no special rules are
+applied:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8983:1-8987:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">www.google.com/search?q=(business))+ok</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.google.com/search?q=(business))+ok"&gt;www.google.com/search?q=(business))+ok&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="8989:1-8992:13">If an autolink ends in a semicolon (<code>;</code>), we check to see if it appears to
+resemble an [entity reference][entity references]; if the preceding text is <code>&amp;</code>
+followed by one or more alphanumeric characters. If so, it is excluded from
+the autolink:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="8994:1-9001:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">www.google.com/search?q=commonmark&amp;hl=en</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">www.google.com/search?q=commonmark&amp;hl;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.google.com/search?q=commonmark&amp;amp;hl=en"&gt;www.google.com/search?q=commonmark&amp;amp;hl=en&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.google.com/search?q=commonmark"&gt;www.google.com/search?q=commonmark&lt;/a&gt;&amp;amp;hl;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9003:1-9003:33"><code>&lt;</code> immediately ends an autolink.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9005:1-9009:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">www.commonmark.org/he&lt;lp</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://www.commonmark.org/he"&gt;www.commonmark.org/he&lt;/a&gt;&amp;lt;lp&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9011:1-9014:36">An <a href="@">extended url autolink</a> will be recognised when one of the schemes
+<code>http://</code>, <code>https://</code>, or <code>ftp://</code>, followed by a [valid domain], then zero or
+more non-space non-<code>&lt;</code> characters according to
+[extended autolink path validation]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9016:1-9026:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">http://commonmark.org</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">(Visit https://encrypted.google.com/search?q=Markup+(business))</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">Anonymous FTP is available at ftp://foo.bar.baz.</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;a href="http://commonmark.org"&gt;http://commonmark.org&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;(Visit &lt;a href="https://encrypted.google.com/search?q=Markup+(business)"&gt;https://encrypted.google.com/search?q=Markup+(business)&lt;/a&gt;)&lt;/p&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;Anonymous FTP is available at &lt;a href="ftp://foo.bar.baz"&gt;ftp://foo.bar.baz&lt;/a&gt;.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9029:1-9031:20">An <a href="@">extended email autolink</a> will be recognised when an email address is
+recognised within any text node. Email addresses are recognised according to
+the following rules:</p>
+<ul data-sourcepos="9033:1-9039:0">
+<li data-sourcepos="9033:1-9033:75">One ore more characters which are alphanumeric, or <code>.</code>, <code>-</code>, <code>_</code>, or <code>+</code>.</li>
+<li data-sourcepos="9034:1-9034:16">An <code>@</code> symbol.</li>
+<li data-sourcepos="9035:1-9039:0">One or more characters which are alphanumeric, or <code>-</code> or <code>_</code>,
+separated by periods (<code>.</code>).
+There must be at least one period.
+The last character must not be one of <code>-</code> or <code>_</code>.</li>
+</ul>
+<p data-sourcepos="9040:1-9040:71">The scheme <code>mailto:</code> will automatically be added to the generated link:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9042:1-9046:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo@bar.baz</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="mailto:foo@bar.baz"&gt;foo@bar.baz&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9048:1-9048:44"><code>+</code> can occur before the <code>@</code>, but not after.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9050:1-9054:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;hello@mail+xyz.example isn't valid, but &lt;a href="mailto:hello+xyz@mail.example"&gt;hello+xyz@mail.example&lt;/a&gt; is.&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9056:1-9058:12"><code>.</code>, <code>-</code>, and <code>_</code> can occur on both sides of the <code>@</code>, but only <code>.</code> may occur at
+the end of the email address, in which case it will not be considered part of
+the address:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9060:1-9073:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a.b-c_d@a.b</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">a.b-c_d@a.b.</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">a.b-c_d@a.b-</span>
+<span id="LC6" class="line" lang="plaintext"></span>
+<span id="LC7" class="line" lang="plaintext">a.b-c_d@a.b_</span>
+<span id="LC8" class="line" lang="plaintext">.</span>
+<span id="LC9" class="line" lang="plaintext">&lt;p&gt;&lt;a href="mailto:a.b-c_d@a.b"&gt;a.b-c_d@a.b&lt;/a&gt;&lt;/p&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;p&gt;&lt;a href="mailto:a.b-c_d@a.b"&gt;a.b-c_d@a.b&lt;/a&gt;.&lt;/p&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;p&gt;a.b-c_d@a.b-&lt;/p&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;p&gt;a.b-c_d@a.b_&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+</div>
+<h2 data-sourcepos="9077:1-9077:11" dir="auto">
+<a id="user-content-raw-html" class="anchor" href="#raw-html" aria-hidden="true"></a>Raw HTML</h2>
+<p data-sourcepos="9079:1-9082:57" dir="auto">Text between <code>&lt;</code> and <code>&gt;</code> that looks like an HTML tag is parsed as a
+raw HTML tag and will be rendered in HTML without escaping.
+Tag and attribute names are not limited to current HTML tags,
+so custom tags (and even, say, DocBook tags) may be used.</p>
+<p data-sourcepos="9084:1-9084:29" dir="auto">Here is the grammar for tags:</p>
+<p data-sourcepos="9086:1-9088:14" dir="auto">A <a href="@">tag name</a> consists of an ASCII letter
+followed by zero or more ASCII letters, digits, or
+hyphens (<code>-</code>).</p>
+<p data-sourcepos="9090:1-9092:32" dir="auto">An <a href="@">attribute</a> consists of [whitespace],
+an [attribute name], and an optional
+[attribute value specification].</p>
+<p data-sourcepos="9094:1-9097:52" dir="auto">An <a href="@">attribute name</a>
+consists of an ASCII letter, <code>_</code>, or <code>:</code>, followed by zero or more ASCII
+letters, digits, <code>_</code>, <code>.</code>, <code>:</code>, or <code>-</code>. (Note: This is the XML
+specification restricted to ASCII. HTML5 is laxer.)</p>
+<p data-sourcepos="9099:1-9102:7" dir="auto">An <a href="@">attribute value specification</a>
+consists of optional [whitespace],
+a <code>=</code> character, optional [whitespace], and an [attribute
+value].</p>
+<p data-sourcepos="9104:1-9106:72" dir="auto">An <a href="@">attribute value</a>
+consists of an [unquoted attribute value],
+a [single-quoted attribute value], or a [double-quoted attribute value].</p>
+<p data-sourcepos="9108:1-9110:60" dir="auto">An <a href="@">unquoted attribute value</a>
+is a nonempty string of characters not
+including [whitespace], <code>"</code>, <code>'</code>, <code>=</code>, <code>&lt;</code>, <code>&gt;</code>, or <code>`</code>.</p>
+<p data-sourcepos="9112:1-9114:46" dir="auto">A <a href="@">single-quoted attribute value</a>
+consists of <code>'</code>, zero or more
+characters not including <code>'</code>, and a final <code>'</code>.</p>
+<p data-sourcepos="9116:1-9118:46" dir="auto">A <a href="@">double-quoted attribute value</a>
+consists of <code>"</code>, zero or more
+characters not including <code>"</code>, and a final <code>"</code>.</p>
+<p data-sourcepos="9120:1-9122:31" dir="auto">An <a href="@">open tag</a> consists of a <code>&lt;</code> character, a [tag name],
+zero or more [attributes], optional [whitespace], an optional <code>/</code>
+character, and a <code>&gt;</code> character.</p>
+<p data-sourcepos="9124:1-9125:57" dir="auto">A <a href="@">closing tag</a> consists of the string <code>&lt;/</code>, a
+[tag name], optional [whitespace], and the character <code>&gt;</code>.</p>
+<p data-sourcepos="9127:1-9130:63" dir="auto">An <a href="@">HTML comment</a> consists of <code>&lt;!--</code> + <em>text</em> + <code>--&gt;</code>,
+where <em>text</em> does not start with <code>&gt;</code> or <code>-&gt;</code>, does not end with <code>-</code>,
+and does not contain <code>--</code>. (See the
+<a href="http://www.w3.org/TR/html5/syntax.html#comments" rel="nofollow noreferrer noopener" target="_blank">HTML5 spec</a>.)</p>
+<p data-sourcepos="9132:1-9135:5" dir="auto">A <a href="@">processing instruction</a>
+consists of the string <code>&lt;?</code>, a string
+of characters not including the string <code>?&gt;</code>, and the string
+<code>?&gt;</code>.</p>
+<p data-sourcepos="9137:1-9140:37" dir="auto">A <a href="@">declaration</a> consists of the
+string <code>&lt;!</code>, a name consisting of one or more uppercase ASCII letters,
+[whitespace], a string of characters not including the
+character <code>&gt;</code>, and the character <code>&gt;</code>.</p>
+<p data-sourcepos="9142:1-9144:28" dir="auto">A <a href="@">CDATA section</a> consists of
+the string <code>&lt;![CDATA[</code>, a string of characters not including the string
+<code>]]&gt;</code>, and the string <code>]]&gt;</code>.</p>
+<p data-sourcepos="9146:1-9148:21" dir="auto">An <a href="@">HTML tag</a> consists of an [open tag], a [closing tag],
+an [HTML comment], a [processing instruction], a [declaration],
+or a [CDATA section].</p>
+<p data-sourcepos="9150:1-9150:31" dir="auto">Here are some simple open tags:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9152:1-9156:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a&gt;&lt;bab&gt;&lt;c2c&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a&gt;&lt;bab&gt;&lt;c2c&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9159:1-9159:15" dir="auto">Empty elements:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9161:1-9165:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a/&gt;&lt;b2/&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a/&gt;&lt;b2/&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9168:1-9168:24" dir="auto">[Whitespace] is allowed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9170:1-9176:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a /&gt;&lt;b2</span>
+<span id="LC2" class="line" lang="plaintext">data="foo" &gt;</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;a /&gt;&lt;b2</span>
+<span id="LC5" class="line" lang="plaintext">data="foo" &gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9179:1-9179:16" dir="auto">With attributes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9181:1-9187:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a foo="bar" bam = 'baz &lt;em&gt;"&lt;/em&gt;'</span>
+<span id="LC2" class="line" lang="plaintext">_boolean zoop:33=zoop:33 /&gt;</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;a foo="bar" bam = 'baz &lt;em&gt;"&lt;/em&gt;'</span>
+<span id="LC5" class="line" lang="plaintext">_boolean zoop:33=zoop:33 /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9190:1-9190:29" dir="auto">Custom tag names can be used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9192:1-9196:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo &lt;responsive-image src="foo.jpg" /&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;Foo &lt;responsive-image src="foo.jpg" /&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9199:1-9199:38" dir="auto">Illegal tag names, not parsed as HTML:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9201:1-9205:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;33&gt; &lt;__&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;33&amp;gt; &amp;lt;__&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9208:1-9208:24" dir="auto">Illegal attribute names:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9210:1-9214:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a h*#ref="hi"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;a h*#ref=&amp;quot;hi&amp;quot;&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9217:1-9217:25" dir="auto">Illegal attribute values:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9219:1-9223:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="hi'&gt; &lt;a href=hi'&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;a href=&amp;quot;hi'&amp;gt; &amp;lt;a href=hi'&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9226:1-9226:21" dir="auto">Illegal [whitespace]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9228:1-9238:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt; a&gt;&lt;</span>
+<span id="LC2" class="line" lang="plaintext">foo&gt;&lt;bar/ &gt;</span>
+<span id="LC3" class="line" lang="plaintext">&lt;foo bar=baz</span>
+<span id="LC4" class="line" lang="plaintext">bim!bop /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">.</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;&amp;lt; a&amp;gt;&amp;lt;</span>
+<span id="LC7" class="line" lang="plaintext">foo&amp;gt;&amp;lt;bar/ &amp;gt;</span>
+<span id="LC8" class="line" lang="plaintext">&amp;lt;foo bar=baz</span>
+<span id="LC9" class="line" lang="plaintext">bim!bop /&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9241:1-9241:21" dir="auto">Missing [whitespace]:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9243:1-9247:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href='bar'title=title&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;a href='bar'title=title&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9250:1-9250:13" dir="auto">Closing tags:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9252:1-9256:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;/a&gt;&lt;/foo &gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;/a&gt;&lt;/foo &gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9259:1-9259:34" dir="auto">Illegal attributes in closing tag:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9261:1-9265:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;/a href="foo"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;/a href=&amp;quot;foo&amp;quot;&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9268:1-9268:9" dir="auto">Comments:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9270:1-9276:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;!-- this is a</span>
+<span id="LC2" class="line" lang="plaintext">comment - with hyphen --&gt;</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo &lt;!-- this is a</span>
+<span id="LC5" class="line" lang="plaintext">comment - with hyphen --&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9279:1-9283:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;!-- not a comment -- two hyphens --&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &amp;lt;!-- not a comment -- two hyphens --&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9286:1-9286:13" dir="auto">Not comments:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9288:1-9295:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;!--&gt; foo --&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">foo &lt;!-- foo---&gt;</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;foo &amp;lt;!--&amp;gt; foo --&amp;gt;&lt;/p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;p&gt;foo &amp;lt;!-- foo---&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9298:1-9298:24" dir="auto">Processing instructions:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9300:1-9304:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;?php echo $a; ?&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;?php echo $a; ?&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9307:1-9307:13" dir="auto">Declarations:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9309:1-9313:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;!ELEMENT br EMPTY&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;!ELEMENT br EMPTY&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9316:1-9316:15" dir="auto">CDATA sections:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9318:1-9322:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;![CDATA[&gt;&amp;&lt;]]&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;![CDATA[&gt;&amp;&lt;]]&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9325:1-9326:11" dir="auto">Entity and numeric character references are preserved in HTML
+attributes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9328:1-9332:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;a href="&amp;ouml;"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;a href="&amp;ouml;"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9335:1-9335:49" dir="auto">Backslash escapes do not work in HTML attributes:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9337:1-9341:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo &lt;a href="\*"&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo &lt;a href="\*"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9344:1-9348:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="\""&gt;</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;quot;&amp;gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div>
+<h2 data-sourcepos="9353:1-9353:34">
+<a id="user-content-disallowed-raw-html-extension" class="anchor" href="#disallowed-raw-html-extension" aria-hidden="true"></a>Disallowed Raw HTML (extension)</h2>
+<p data-sourcepos="9355:1-9356:36">GFM enables the <code>tagfilter</code> extension, where the following HTML tags will be
+filtered when rendering HTML output:</p>
+<ul data-sourcepos="9358:1-9367:0">
+<li data-sourcepos="9358:1-9358:11"><code>&lt;title&gt;</code></li>
+<li data-sourcepos="9359:1-9359:14"><code>&lt;textarea&gt;</code></li>
+<li data-sourcepos="9360:1-9360:11"><code>&lt;style&gt;</code></li>
+<li data-sourcepos="9361:1-9361:9"><code>&lt;xmp&gt;</code></li>
+<li data-sourcepos="9362:1-9362:12"><code>&lt;iframe&gt;</code></li>
+<li data-sourcepos="9363:1-9363:13"><code>&lt;noembed&gt;</code></li>
+<li data-sourcepos="9364:1-9364:14"><code>&lt;noframes&gt;</code></li>
+<li data-sourcepos="9365:1-9365:12"><code>&lt;script&gt;</code></li>
+<li data-sourcepos="9366:1-9367:0"><code>&lt;plaintext&gt;</code></li>
+</ul>
+<p data-sourcepos="9368:1-9371:71">Filtering is done by replacing the leading <code>&lt;</code> with the entity <code>&amp;lt;</code>. These
+tags are chosen in particular as they change how HTML is interpreted in a way
+unique to them (i.e. nested HTML is interpreted differently), and this is
+usually undesireable in the context of other rendered Markdown content.</p>
+<p data-sourcepos="9373:1-9373:39">All other HTML tags are left untouched.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9375:1-9386:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;strong&gt; &lt;title&gt; &lt;style&gt; &lt;em&gt;</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC4" class="line" lang="plaintext"> &lt;xmp&gt; is disallowed. &lt;XMP&gt; is also disallowed.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;/blockquote&gt;</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt; &amp;lt;title&gt; &amp;lt;style&gt; &lt;em&gt;&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;blockquote&gt;</span>
+<span id="LC9" class="line" lang="plaintext"> &amp;lt;xmp&gt; is disallowed. &amp;lt;XMP&gt; is also disallowed.</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/blockquote&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+</div>
+<h2 data-sourcepos="9390:1-9390:19" dir="auto">
+<a id="user-content-hard-line-breaks" class="anchor" href="#hard-line-breaks" aria-hidden="true"></a>Hard line breaks</h2>
+<p data-sourcepos="9392:1-9395:27" dir="auto">A line break (not in a code span or HTML tag) that is preceded
+by two or more spaces and does not occur at the end of a block
+is parsed as a <a href="@">hard line break</a> (rendered
+in HTML as a <code>&lt;br /&gt;</code> tag):</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9397:1-9403:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9406:1-9407:48" dir="auto">For a more visible alternative, a backslash before the
+[line ending] may be used instead of two spaces:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9409:1-9415:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo\</span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9418:1-9418:33" dir="auto">More than two spaces can be used:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9420:1-9426:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9429:1-9429:61" dir="auto">Leading spaces at the beginning of the next line are ignored:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9431:1-9437:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span>
+<span id="LC2" class="line" lang="plaintext"> bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9440:1-9446:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo\</span>
+<span id="LC2" class="line" lang="plaintext"> bar</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9449:1-9450:26" dir="auto">Line breaks can occur inside emphasis, links, and other constructs
+that allow inline content:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9452:1-9458:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo </span>
+<span id="LC2" class="line" lang="plaintext">bar*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9461:1-9467:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">*foo\</span>
+<span id="LC2" class="line" lang="plaintext">bar*</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;em&gt;foo&lt;br /&gt;</span>
+<span id="LC5" class="line" lang="plaintext">bar&lt;/em&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9470:1-9470:42" dir="auto">Line breaks do not occur inside code spans</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9472:1-9477:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`code </span>
+<span id="LC2" class="line" lang="plaintext">span`</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;code span&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9480:1-9485:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">`code\</span>
+<span id="LC2" class="line" lang="plaintext">span`</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;code&gt;code\ span&lt;/code&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9488:1-9488:13" dir="auto">or HTML tags:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9490:1-9496:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="foo </span>
+<span id="LC2" class="line" lang="plaintext">bar"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo </span>
+<span id="LC5" class="line" lang="plaintext">bar"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9499:1-9505:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a href="foo\</span>
+<span id="LC2" class="line" lang="plaintext">bar"&gt;</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;&lt;a href="foo\</span>
+<span id="LC5" class="line" lang="plaintext">bar"&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9508:1-9510:20" dir="auto">Hard line breaks are for separating inline content within a block.
+Neither syntax for hard line breaks works at the end of a paragraph or
+other block element:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9512:1-9516:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo\</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo\&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9519:1-9523:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;foo&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9526:1-9530:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">### foo\</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h3&gt;foo\&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9533:1-9537:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">### foo </span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;h3&gt;foo&lt;/h3&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9540:1-9540:19" dir="auto">
+<a id="user-content-soft-line-breaks" class="anchor" href="#soft-line-breaks" aria-hidden="true"></a>Soft line breaks</h2>
+<p data-sourcepos="9542:1-9546:62" dir="auto">A regular line break (not in a code span or HTML tag) that is not
+preceded by two or more spaces or a backslash is parsed as a
+<a href="@">softbreak</a>. (A softbreak may be rendered in HTML either as a
+[line ending] or as a space. The result will be the same in
+browsers. In the examples here, a [line ending] will be used.)</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9548:1-9554:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
+<span id="LC2" class="line" lang="plaintext">baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9557:1-9558:8" dir="auto">Spaces at the end of the line and beginning of the next line are
+removed:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9560:1-9566:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span>
+<span id="LC2" class="line" lang="plaintext"> baz</span>
+<span id="LC3" class="line" lang="plaintext">.</span>
+<span id="LC4" class="line" lang="plaintext">&lt;p&gt;foo</span>
+<span id="LC5" class="line" lang="plaintext">baz&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9569:1-9570:25" dir="auto">A conforming parser may render a soft line break in HTML either as a
+line break or as a space.</p>
+<p data-sourcepos="9572:1-9573:20" dir="auto">A renderer may also provide an option to render soft line breaks
+as hard line breaks.</p>
+<h2 data-sourcepos="9575:1-9575:18" dir="auto">
+<a id="user-content-textual-content" class="anchor" href="#textual-content" aria-hidden="true"></a>Textual content</h2>
+<p data-sourcepos="9577:1-9578:35" dir="auto">Any characters not given an interpretation by the above rules will
+be parsed as plain textual content.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9580:1-9584:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">hello $.;'there</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;hello $.;'there&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9587:1-9591:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo χÏῆν</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;Foo χÏῆν&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9594:1-9594:39" dir="auto">Internal spaces are preserved verbatim:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9596:1-9600:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Multiple spaces</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;Multiple spaces&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h1 data-sourcepos="9603:1-9603:40" dir="auto">
+<a id="user-content-gitlab-official-specification-markdown" class="anchor" href="#gitlab-official-specification-markdown" aria-hidden="true"></a>GitLab Official Specification Markdown</h1>
+<p data-sourcepos="9605:1-9608:104" dir="auto">Currently, only some of the GitLab-specific markdown features are
+listed in this section. We will eventually add all
+GitLab-specific features currently listed as supported in the
+<a href="https://docs.gitlab.com/ee/user/markdown.html" rel="nofollow noreferrer noopener" target="_blank">user-facing documentation for GitLab Flavored Markdown</a>.</p>
+<p data-sourcepos="9610:1-9611:69" dir="auto">There is currently only this single top-level heading, but the
+examples may be split into multiple top-level headings in the future.</p>
+<h2 data-sourcepos="9613:1-9613:12" dir="auto">
+<a id="user-content-footnotes" class="anchor" href="#footnotes" aria-hidden="true"></a>Footnotes</h2>
+<p data-sourcepos="9615:1-9616:143" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#footnotes" rel="nofollow noreferrer noopener" target="_blank">the footnotes section of the user-facing documentation for GitLab Flavored Markdown</a>.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9618:1-9642:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">footnote reference tag [^fortytwo]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">[^fortytwo]: footnote text</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;</span>
+<span id="LC6" class="line" lang="plaintext">footnote reference tag</span>
+<span id="LC7" class="line" lang="plaintext">&lt;sup&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref&gt;</span>
+<span id="LC9" class="line" lang="plaintext">1</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/a&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/sup&gt;</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/p&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;section data-footnotes&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;ol&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;li id="fn-fortytwo-42"&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;p&gt;</span>
+<span id="LC17" class="line" lang="plaintext">footnote text</span>
+<span id="LC18" class="line" lang="plaintext">&lt;a href="#fnref-fortytwo-42" data-footnote-backref&gt;</span>
+<span id="LC19" class="line" lang="plaintext">&lt;/a&gt;</span>
+<span id="LC20" class="line" lang="plaintext">&lt;/p&gt;</span>
+<span id="LC21" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC22" class="line" lang="plaintext">&lt;/ol&gt;</span>
+<span id="LC23" class="line" lang="plaintext">&lt;/section&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9644:1-9644:18" dir="auto">
+<a id="user-content-task-list-items" class="anchor" href="#task-list-items" aria-hidden="true"></a>Task list items</h2>
+<p data-sourcepos="9646:1-9647:117" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#task-lists" rel="nofollow noreferrer noopener" target="_blank">Task lists</a> in the GitLab Flavored Markdown documentation.</p>
+<p data-sourcepos="9649:1-9652:39" dir="auto">Task list items (checkboxes) are defined as a GitHub Flavored Markdown extension in a section above.
+GitLab extends the behavior of task list items to support additional features.
+Some of these features are in-progress, and should not yet be considered part of the official
+GitLab Flavored Markdown specification.</p>
+<p data-sourcepos="9654:1-9654:85" dir="auto">Some of the behavior of task list items is implemented as client-side JavaScript/CSS.</p>
+<p data-sourcepos="9656:1-9656:80" dir="auto">The following are some basic examples; more examples may be added in the future.</p>
+<p data-sourcepos="9658:1-9658:16" dir="auto">Incomplete task:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9660:1-9670:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;task-button/&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;input type="checkbox" disabled/&gt;</span>
+<span id="LC7" class="line" lang="plaintext">incomplete</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9672:1-9672:15" dir="auto">Completed task:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9674:1-9684:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;task-button/&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;input type="checkbox" checked disabled/&gt;</span>
+<span id="LC7" class="line" lang="plaintext">completed</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9686:1-9686:18" dir="auto">Inapplicable task:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9688:1-9700:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC5" class="line" lang="plaintext">&lt;task-button/&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;input type="checkbox" data-inapplicable disabled&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;s&gt;</span>
+<span id="LC8" class="line" lang="plaintext">inapplicable</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/s&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC11" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9702:1-9703:50" dir="auto">Inapplicable task in a "loose" list. Note that the <code>&lt;del&gt;</code> tag is not applied to the
+loose text; it has strikethrough applied with CSS.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9705:1-9724:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"> text in loose list</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;ul&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;li&gt;</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;task-button/&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;input type="checkbox" data-inapplicable disabled&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;s&gt;</span>
+<span id="LC11" class="line" lang="plaintext">inapplicable</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/s&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/p&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;p&gt;</span>
+<span id="LC15" class="line" lang="plaintext">text in loose list</span>
+<span id="LC16" class="line" lang="plaintext">&lt;/p&gt;</span>
+<span id="LC17" class="line" lang="plaintext">&lt;/li&gt;</span>
+<span id="LC18" class="line" lang="plaintext">&lt;/ul&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9726:1-9726:15" dir="auto">
+<a id="user-content-front-matter" class="anchor" href="#front-matter" aria-hidden="true"></a>Front matter</h2>
+<p data-sourcepos="9728:1-9729:121" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#front-matter" rel="nofollow noreferrer noopener" target="_blank">Front matter</a> in the GitLab Flavored Markdown documentation.</p>
+<p data-sourcepos="9731:1-9732:95" dir="auto">Front matter is metadata included at the beginning of a Markdown document, preceding the content.
+This data can be used by static site generators like Jekyll, Hugo, and many other applications.</p>
+<p data-sourcepos="9734:1-9734:18" dir="auto">YAML front matter:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9736:1-9746:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
+<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
+<span id="LC3" class="line" lang="plaintext">---</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;code&gt;</span>
+<span id="LC7" class="line" lang="plaintext">title: YAML front matter</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9748:1-9748:18" dir="auto">TOML front matter:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9750:1-9760:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
+<span id="LC2" class="line" lang="plaintext">title: TOML front matter</span>
+<span id="LC3" class="line" lang="plaintext">+++</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;pre&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;code&gt;</span>
+<span id="LC7" class="line" lang="plaintext">title: TOML front matter</span>
+<span id="LC8" class="line" lang="plaintext">&lt;/code&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9762:1-9762:18" dir="auto">JSON front matter:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9764:1-9778:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
+<span id="LC2" class="line" lang="plaintext">{</span>
+<span id="LC3" class="line" lang="plaintext"> "title": "JSON front matter"</span>
+<span id="LC4" class="line" lang="plaintext">}</span>
+<span id="LC5" class="line" lang="plaintext">;;;</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;pre&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;code&gt;</span>
+<span id="LC9" class="line" lang="plaintext">{</span>
+<span id="LC10" class="line" lang="plaintext"> "title": "JSON front matter"</span>
+<span id="LC11" class="line" lang="plaintext">}</span>
+<span id="LC12" class="line" lang="plaintext">&lt;/code&gt;</span>
+<span id="LC13" class="line" lang="plaintext">&lt;/pre&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9780:1-9780:66" dir="auto">Front matter blocks should be inserted at the top of the document:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9782:1-9792:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">---</span>
+<span id="LC4" class="line" lang="plaintext">title: YAML front matter</span>
+<span id="LC5" class="line" lang="plaintext">---</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;text&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;hr&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;h2&gt;title: YAML front matter&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9794:1-9794:74" dir="auto">Front matter block delimiters shouldn’t be preceded by space characters:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9796:1-9803:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
+<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
+<span id="LC3" class="line" lang="plaintext">---</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;hr&gt;</span>
+<span id="LC6" class="line" lang="plaintext">&lt;h2&gt;title: YAML front matter&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9805:1-9805:20" dir="auto">
+<a id="user-content-table-of-contents" class="anchor" href="#table-of-contents" aria-hidden="true"></a>Table of contents</h2>
+<p data-sourcepos="9807:1-9809:46" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#table-of-contents" rel="nofollow noreferrer noopener" target="_blank">table of contents</a>
+in the GitLab Flavored Markdown documentation.</p>
+<p data-sourcepos="9811:1-9812:58" dir="auto">A table of contents is an unordered list that links to subheadings in the document.
+Add either the <code>[[_TOC_]]</code> or </p><ul class="section-nav">
+<li><a href="#introduction">Introduction</a></li>
+<li>
+<a href="#preliminaries">Preliminaries</a><ul>
+<li><a href="#characters-and-lines">Characters and lines</a></li>
+<li><a href="#tabs">Tabs</a></li>
+<li><a href="#insecure-characters">Insecure characters</a></li>
+</ul>
+</li>
+<li>
+<a href="#blocks-and-inlines">Blocks and inlines</a><ul>
+<li><a href="#precedence">Precedence</a></li>
+<li><a href="#container-blocks-and-leaf-blocks">Container blocks and leaf blocks</a></li>
+</ul>
+</li>
+<li>
+<a href="#leaf-blocks">Leaf blocks</a><ul>
+<li><a href="#thematic-breaks">Thematic breaks</a></li>
+<li><a href="#atx-headings">ATX headings</a></li>
+<li><a href="#setext-headings">Setext headings</a></li>
+<li><a href="#indented-code-blocks">Indented code blocks</a></li>
+<li><a href="#fenced-code-blocks">Fenced code blocks</a></li>
+<li><a href="#html-blocks">HTML blocks</a></li>
+<li><a href="#link-reference-definitions">Link reference definitions</a></li>
+<li><a href="#paragraphs">Paragraphs</a></li>
+<li><a href="#blank-lines">Blank lines</a></li>
+<li><a href="#tables-extension">Tables (extension)</a></li>
+</ul>
+</li>
+<li>
+<a href="#container-blocks">Container blocks</a><ul>
+<li><a href="#block-quotes">Block quotes</a></li>
+<li>
+<a href="#list-items">List items</a><ul><li><a href="#motivation">Motivation</a></li></ul>
+</li>
+<li><a href="#task-list-items-extension">Task list items (extension)</a></li>
+<li><a href="#lists">Lists</a></li>
+</ul>
+</li>
+<li>
+<a href="#inlines">Inlines</a><ul>
+<li><a href="#backslash-escapes">Backslash escapes</a></li>
+<li><a href="#entity-and-numeric-character-references">Entity and numeric character references</a></li>
+<li><a href="#code-spans">Code spans</a></li>
+<li><a href="#emphasis-and-strong-emphasis">Emphasis and strong emphasis</a></li>
+<li><a href="#strikethrough-extension">Strikethrough (extension)</a></li>
+<li><a href="#links">Links</a></li>
+<li><a href="#images">Images</a></li>
+<li><a href="#autolinks">Autolinks</a></li>
+<li><a href="#autolinks-extension">Autolinks (extension)</a></li>
+<li><a href="#raw-html">Raw HTML</a></li>
+<li><a href="#disallowed-raw-html-extension">Disallowed Raw HTML (extension)</a></li>
+<li><a href="#hard-line-breaks">Hard line breaks</a></li>
+<li><a href="#soft-line-breaks">Soft line breaks</a></li>
+<li><a href="#textual-content">Textual content</a></li>
+</ul>
+</li>
+<li>
+<a href="#gitlab-official-specification-markdown">GitLab Official Specification Markdown</a><ul>
+<li><a href="#footnotes">Footnotes</a></li>
+<li><a href="#task-list-items">Task list items</a></li>
+<li><a href="#front-matter">Front matter</a></li>
+<li><a href="#table-of-contents">Table of contents</a></li>
+</ul>
+</li>
+<li>
+<a href="#gitlab-internal-extension-markdown">GitLab Internal Extension Markdown</a><ul>
+<li><a href="#audio">Audio</a></li>
+<li><a href="#video">Video</a></li>
+<li><a href="#markdown-preview-api-request-overrides">Markdown Preview API Request Overrides</a></li>
+</ul>
+</li>
+<li>
+<a href="#appendix-a-parsing-strategy">Appendix: A parsing strategy</a><ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#phase-1-block-structure">Phase 1: block structure</a></li>
+<li>
+<a href="#phase-2-inline-structure">Phase 2: inline structure</a><ul><li>
+<a href="#an-algorithm-for-parsing-nested-emphasis-and-links">An algorithm for parsing nested emphasis and links</a><ul>
+<li><a href="#look-for-link-or-image">look for link or image</a></li>
+<li><a href="#process-emphasis">process emphasis</a></li>
+</ul>
+</li></ul>
+</li>
+</ul>
+</li>
+</ul> tag on its own line.
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9814:1-9831:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">## Heading 2</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;nav&gt;</span>
+<span id="LC8" class="line" lang="plaintext"> &lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext"> &lt;ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-2"&gt;Heading 2&lt;/a&gt;&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext"> &lt;/ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext"> &lt;/ul&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/nav&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;h1&gt;Heading 1&lt;/h1&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;h2&gt;Heading 2&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9833:1-9850:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
+<span id="LC4" class="line" lang="plaintext"></span>
+<span id="LC5" class="line" lang="plaintext">## Heading 2</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;nav&gt;</span>
+<span id="LC8" class="line" lang="plaintext"> &lt;ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
+<span id="LC10" class="line" lang="plaintext"> &lt;ul&gt;</span>
+<span id="LC11" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-2"&gt;Heading 2&lt;/a&gt;&lt;/li&gt;</span>
+<span id="LC12" class="line" lang="plaintext"> &lt;/ul&gt;</span>
+<span id="LC13" class="line" lang="plaintext"> &lt;/ul&gt;</span>
+<span id="LC14" class="line" lang="plaintext">&lt;/nav&gt;</span>
+<span id="LC15" class="line" lang="plaintext">&lt;h1&gt;Heading 1&lt;/h1&gt;</span>
+<span id="LC16" class="line" lang="plaintext">&lt;h2&gt;Heading 2&lt;/h2&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9852:1-9853:5" dir="auto">A table of contents is a block element. It should preceded and followed by a blank
+line.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9855:1-9864:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
+<span id="LC2" class="line" lang="plaintext">text</span>
+<span id="LC3" class="line" lang="plaintext"></span>
+<span id="LC4" class="line" lang="plaintext">text</span>
+<span id="LC5" class="line" lang="plaintext">[TOC]</span>
+<span id="LC6" class="line" lang="plaintext">.</span>
+<span id="LC7" class="line" lang="plaintext">&lt;p&gt;[[&lt;em&gt;TOC&lt;/em&gt;]]text&lt;/p&gt;</span>
+<span id="LC8" class="line" lang="plaintext">&lt;p&gt;text[TOC]&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9866:1-9866:60" dir="auto">A table of contents can be indented with up to three spaces.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9868:1-9879:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;nav&gt;</span>
+<span id="LC6" class="line" lang="plaintext"> &lt;ul&gt;</span>
+<span id="LC7" class="line" lang="plaintext"> &lt;li&gt;&lt;a href="#heading-1"&gt;Heading 1&lt;/a&gt;&lt;/li&gt;</span>
+<span id="LC8" class="line" lang="plaintext"> &lt;/ul&gt;</span>
+<span id="LC9" class="line" lang="plaintext">&lt;/nav&gt;</span>
+<span id="LC10" class="line" lang="plaintext">&lt;h1&gt;Heading 1&lt;/h1&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h1 data-sourcepos="9881:1-9881:36" dir="auto">
+<a id="user-content-gitlab-internal-extension-markdown" class="anchor" href="#gitlab-internal-extension-markdown" aria-hidden="true"></a>GitLab Internal Extension Markdown</h1>
+<h2 data-sourcepos="9883:1-9883:8" dir="auto">
+<a id="user-content-audio" class="anchor" href="#audio" aria-hidden="true"></a>Audio</h2>
+<p data-sourcepos="9885:1-9886:107" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#audio" rel="nofollow noreferrer noopener" target="_blank">audio</a> in the GitLab Flavored Markdown documentation.</p>
+<p data-sourcepos="9888:1-9890:63" dir="auto">GLFM renders image elements as an audio player as long as the resource’s file extension is
+one of the following supported audio extensions <code>.mp3</code>, <code>.oga</code>, <code>.ogg</code>, <code>.spx</code>, and <code>.wav</code>.
+Audio ignore the alternative text part of an image declaration.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9892:1-9896:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![audio](audio.oga "audio title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;audio src="audio.oga" title="audio title"&gt;&lt;/audio&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9898:1-9898:41" dir="auto">Reference definitions work audio as well:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9900:1-9906:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[audio]: audio.oga "audio title"</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">![audio][audio]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;audio src="audio.oga" title="audio title"&gt;&lt;/audio&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9908:1-9908:8" dir="auto">
+<a id="user-content-video" class="anchor" href="#video" aria-hidden="true"></a>Video</h2>
+<p data-sourcepos="9910:1-9911:109" dir="auto">See
+<a href="https://docs.gitlab.com/ee/user/markdown.html#videos" rel="nofollow noreferrer noopener" target="_blank">videos</a> in the GitLab Flavored Markdown documentation.</p>
+<p data-sourcepos="9913:1-9915:64" dir="auto">GLFM renders image elements as a video player as long as the resource’s file extension is
+one of the following supported video extensions <code>.mp4</code>, <code>.m4v</code>, <code>.mov</code>, <code>.webm</code>, and <code>.ogv</code>.
+Videos ignore the alternative text part of an image declaration.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9918:1-9922:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">![video](video.m4v "video title")</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;video src="video.m4v" title="video title"&gt;&lt;/video&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9924:1-9924:41" dir="auto">Reference definitions work video as well:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9926:1-9932:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[video]: video.mov "video title"</span>
+<span id="LC2" class="line" lang="plaintext"></span>
+<span id="LC3" class="line" lang="plaintext">![video][video]</span>
+<span id="LC4" class="line" lang="plaintext">.</span>
+<span id="LC5" class="line" lang="plaintext">&lt;p&gt;&lt;video src="video.mov" title="video title"&gt;&lt;/video&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="9934:1-9934:41" dir="auto">
+<a id="user-content-markdown-preview-api-request-overrides" class="anchor" href="#markdown-preview-api-request-overrides" aria-hidden="true"></a>Markdown Preview API Request Overrides</h2>
+<p data-sourcepos="9936:1-9938:42" dir="auto">This section contains examples of all controllers which use <code>PreviewMarkdown</code> module
+and use different <code>markdown_context_params</code>. They exercise the various <code>preview_markdown</code>
+endpoints via <code>glfm_example_metadata.yml</code>.</p>
+<p data-sourcepos="9941:1-9941:75" dir="auto"><code>preview_markdown</code> exercising <code>groups</code> API endpoint and <code>UploadLinkFilter</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9943:1-9947:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[groups-test-file](/uploads/groups-test-file)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="groups-test-file"&gt;groups-test-file&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9949:1-9949:81" dir="auto"><code>preview_markdown</code> exercising <code>projects</code> API endpoint and <code>RepositoryLinkFilter</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9951:1-9955:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[projects-test-file](projects-test-file)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="projects-test-file"&gt;projects-test-file&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9957:1-9957:83" dir="auto"><code>preview_markdown</code> exercising <code>projects</code> API endpoint and <code>SnippetReferenceFilter</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9959:1-9963:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This project snippet ID reference IS filtered: $88888</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;This project snippet ID reference IS filtered: $88888&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9965:1-9968:50" dir="auto"><code>preview_markdown</code> exercising personal (non-project) <code>snippets</code> API endpoint. This is
+only used by the comment field on personal snippets. It has no unique custom markdown
+extension behavior, and specifically does not render snippet references via
+<code>SnippetReferenceFilter</code>, even if the ID is valid.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9970:1-9974:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This personal snippet ID reference is not filtered: $99999</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;This personal snippet ID reference is not filtered: $99999&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9976:1-9976:80" dir="auto"><code>preview_markdown</code> exercising project <code>wikis</code> API endpoint and <code>WikiLinkFilter</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9978:1-9982:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[project-wikis-test-file](project-wikis-test-file)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="project-wikis-test-file"&gt;project-wikis-test-file&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="9984:1-9985:63" dir="auto"><code>preview_markdown</code> exercising group <code>wikis</code> API endpoint and <code>WikiLinkFilter</code>. This example
+also requires an EE license enabling the <code>group_wikis</code> feature:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="9987:1-9991:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[group-wikis-test-file](group-wikis-test-file)</span>
+<span id="LC2" class="line" lang="plaintext">.</span>
+<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;a href="group-wikis-test-file"&gt;group-wikis-test-file&lt;/a&gt;&lt;/p&gt;</span></code></pre>
+<copy-code></copy-code>
+</div>
+
+<h1 data-sourcepos="9995:1-9995:30" dir="auto">
+<a id="user-content-appendix-a-parsing-strategy" class="anchor" href="#appendix-a-parsing-strategy" aria-hidden="true"></a>Appendix: A parsing strategy</h1>
+<p data-sourcepos="9997:1-9998:49" dir="auto">In this appendix we describe some features of the parsing strategy
+used in the CommonMark reference implementations.</p>
+<h2 data-sourcepos="10000:1-10000:11" dir="auto">
+<a id="user-content-overview" class="anchor" href="#overview" aria-hidden="true"></a>Overview</h2>
+<p data-sourcepos="10002:1-10002:23" dir="auto">Parsing has two phases:</p>
+<ol data-sourcepos="10004:1-10014:0" dir="auto">
+<li data-sourcepos="10004:1-10009:0">
+<p data-sourcepos="10004:4-10008:28">In the first phase, lines of input are consumed and the block
+structure of the document---its division into paragraphs, block quotes,
+list items, and so on---is constructed. Text is assigned to these
+blocks but not parsed. Link reference definitions are parsed and a
+map of links is constructed.</p>
+</li>
+<li data-sourcepos="10010:1-10014:0">
+<p data-sourcepos="10010:4-10013:34">In the second phase, the raw text contents of paragraphs and headings
+are parsed into sequences of Markdown inline elements (strings,
+code spans, links, emphasis, and so on), using the map of link
+references constructed in phase 1.</p>
+</li>
+</ol>
+<p data-sourcepos="10015:1-10022:17" dir="auto">At each point in processing, the document is represented as a tree of
+<strong>blocks</strong>. The root of the tree is a <code>document</code> block. The <code>document</code>
+may have any number of other blocks as <strong>children</strong>. These children
+may, in turn, have other blocks as children. The last child of a block
+is normally considered <strong>open</strong>, meaning that subsequent lines of input
+can alter its contents. (Blocks that are not open are <strong>closed</strong>.)
+Here, for example, is a possible document tree, with the open blocks
+marked by arrows:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10024:1-10036:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span>
+<span id="LC2" class="line" lang="plaintext"> -&gt; block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> "Lorem ipsum dolor\nsit amet."</span>
+<span id="LC5" class="line" lang="plaintext"> -&gt; list (type=bullet tight=true bullet_char=-)</span>
+<span id="LC6" class="line" lang="plaintext"> list_item</span>
+<span id="LC7" class="line" lang="plaintext"> paragraph</span>
+<span id="LC8" class="line" lang="plaintext"> "Qui *quodsi iracundia*"</span>
+<span id="LC9" class="line" lang="plaintext"> -&gt; list_item</span>
+<span id="LC10" class="line" lang="plaintext"> -&gt; paragraph</span>
+<span id="LC11" class="line" lang="plaintext"> "aliquando id"</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="10038:1-10038:27" dir="auto">
+<a id="user-content-phase-1-block-structure" class="anchor" href="#phase-1-block-structure" aria-hidden="true"></a>Phase 1: block structure</h2>
+<p data-sourcepos="10040:1-10042:37" dir="auto">Each line that is processed has an effect on this tree. The line is
+analyzed and, depending on its contents, the document may be altered
+in one or more of the following ways:</p>
+<ol data-sourcepos="10044:1-10049:0" dir="auto">
+<li data-sourcepos="10044:1-10044:41">One or more open blocks may be closed.</li>
+<li data-sourcepos="10045:1-10046:19">One or more new blocks may be created as children of the
+last open block.</li>
+<li data-sourcepos="10047:1-10049:0">Text may be added to the last (deepest) open block remaining
+on the tree.</li>
+</ol>
+<p data-sourcepos="10050:1-10051:54" dir="auto">Once a line has been incorporated into the tree in this way,
+it can be discarded, so input can be read in a stream.</p>
+<p data-sourcepos="10053:1-10053:40" dir="auto">For each line, we follow this procedure:</p>
+<ol data-sourcepos="10055:1-10074:0" dir="auto">
+<li data-sourcepos="10055:1-10063:0">
+<p data-sourcepos="10055:4-10062:25">First we iterate through the open blocks, starting with the
+root document, and descending through last children down to the last
+open block. Each block imposes a condition that the line must satisfy
+if the block is to remain open. For example, a block quote requires a
+<code>&gt;</code> character. A paragraph requires a non-blank line.
+In this phase we may match all or just some of the open
+blocks. But we cannot close unmatched blocks yet, because we may have a
+[lazy continuation line].</p>
+</li>
+<li data-sourcepos="10064:1-10069:0">
+<p data-sourcepos="10064:5-10068:14">Next, after consuming the continuation markers for existing
+blocks, we look for new block starts (e.g. <code>&gt;</code> for a block quote).
+If we encounter a new block start, we close any blocks unmatched
+in step 1 before creating the new block as a child of the last
+matched block.</p>
+</li>
+<li data-sourcepos="10070:1-10074:0">
+<p data-sourcepos="10070:5-10073:54">Finally, we look at the remainder of the line (after block
+markers like <code>&gt;</code>, list markers, and indentation have been consumed).
+This is text that can be incorporated into the last open
+block (a paragraph, code block, heading, or raw HTML).</p>
+</li>
+</ol>
+<p data-sourcepos="10075:1-10076:37" dir="auto">Setext headings are formed when we see a line of a paragraph
+that is a [setext heading underline].</p>
+<p data-sourcepos="10078:1-10081:17" dir="auto">Reference link definitions are detected when a paragraph is closed;
+the accumulated text lines are parsed to see if they begin with
+one or more reference link definitions. Any remainder becomes a
+normal paragraph.</p>
+<p data-sourcepos="10083:1-10084:36" dir="auto">We can see how this works by considering how the tree above is
+generated by four lines of Markdown:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10086:1-10091:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; Lorem ipsum dolor</span></span>
+<span id="LC2" class="line" lang="markdown">sit amet.</span>
+<span id="LC3" class="line" lang="markdown"><span class="gt">&gt; - Qui *quodsi iracundia*</span></span>
+<span id="LC4" class="line" lang="markdown"><span class="gt">&gt; - aliquando id</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10093:1-10093:41" dir="auto">At the outset, our document model is just</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10095:1-10097:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10099:1-10099:27" dir="auto">The first line of our text,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10101:1-10103:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; Lorem ipsum dolor</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10105:1-10108:23" dir="auto">causes a <code>block_quote</code> block to be created as a child of our
+open <code>document</code> block, and a <code>paragraph</code> block as a child of
+the <code>block_quote</code>. Then the text is added to the last open
+block, the <code>paragraph</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10110:1-10115:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span>
+<span id="LC2" class="line" lang="plaintext"> -&gt; block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> -&gt; paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> "Lorem ipsum dolor"</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10117:1-10117:14" dir="auto">The next line,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10119:1-10121:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown">sit amet.</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10123:1-10124:24" dir="auto">is a "lazy continuation" of the open <code>paragraph</code>, so it gets added
+to the paragraph's text:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10126:1-10131:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span>
+<span id="LC2" class="line" lang="plaintext"> -&gt; block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> -&gt; paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> "Lorem ipsum dolor\nsit amet."</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10133:1-10133:15" dir="auto">The third line,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10135:1-10137:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; - Qui *quodsi iracundia*</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10139:1-10142:64" dir="auto">causes the <code>paragraph</code> block to be closed, and a new <code>list</code> block
+opened as a child of the <code>block_quote</code>. A <code>list_item</code> is also
+added as a child of the <code>list</code>, and a <code>paragraph</code> as a child of
+the <code>list_item</code>. The text is then added to the new <code>paragraph</code>:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10144:1-10153:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span>
+<span id="LC2" class="line" lang="plaintext"> -&gt; block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> "Lorem ipsum dolor\nsit amet."</span>
+<span id="LC5" class="line" lang="plaintext"> -&gt; list (type=bullet tight=true bullet_char=-)</span>
+<span id="LC6" class="line" lang="plaintext"> -&gt; list_item</span>
+<span id="LC7" class="line" lang="plaintext"> -&gt; paragraph</span>
+<span id="LC8" class="line" lang="plaintext"> "Qui *quodsi iracundia*"</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10155:1-10155:16" dir="auto">The fourth line,</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10157:1-10159:3" class="code highlight js-syntax-highlight language-markdown" lang="markdown" v-pre="true"><code><span id="LC1" class="line" lang="markdown"><span class="gt">&gt; - aliquando id</span></span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10161:1-10164:30" dir="auto">causes the <code>list_item</code> (and its child the <code>paragraph</code>) to be closed,
+and a new <code>list_item</code> opened up as child of the <code>list</code>. A <code>paragraph</code>
+is added as a child of the new <code>list_item</code>, to contain the text.
+We thus obtain the final tree:</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10166:1-10178:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">-&gt; document</span>
+<span id="LC2" class="line" lang="plaintext"> -&gt; block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> "Lorem ipsum dolor\nsit amet."</span>
+<span id="LC5" class="line" lang="plaintext"> -&gt; list (type=bullet tight=true bullet_char=-)</span>
+<span id="LC6" class="line" lang="plaintext"> list_item</span>
+<span id="LC7" class="line" lang="plaintext"> paragraph</span>
+<span id="LC8" class="line" lang="plaintext"> "Qui *quodsi iracundia*"</span>
+<span id="LC9" class="line" lang="plaintext"> -&gt; list_item</span>
+<span id="LC10" class="line" lang="plaintext"> -&gt; paragraph</span>
+<span id="LC11" class="line" lang="plaintext"> "aliquando id"</span></code></pre>
+<copy-code></copy-code>
+</div>
+<h2 data-sourcepos="10180:1-10180:28" dir="auto">
+<a id="user-content-phase-2-inline-structure" class="anchor" href="#phase-2-inline-structure" aria-hidden="true"></a>Phase 2: inline structure</h2>
+<p data-sourcepos="10182:1-10182:66" dir="auto">Once all of the input has been parsed, all open blocks are closed.</p>
+<p data-sourcepos="10184:1-10187:33" dir="auto">We then "walk the tree," visiting every node, and parse raw
+string contents of paragraphs and headings as inlines. At this
+point we have seen all the link reference definitions, so we can
+resolve reference links as we go.</p>
+<div class="gl-relative markdown-code-block js-markdown-code">
+<pre data-sourcepos="10189:1-10205:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="tree" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">document</span>
+<span id="LC2" class="line" lang="plaintext"> block_quote</span>
+<span id="LC3" class="line" lang="plaintext"> paragraph</span>
+<span id="LC4" class="line" lang="plaintext"> str "Lorem ipsum dolor"</span>
+<span id="LC5" class="line" lang="plaintext"> softbreak</span>
+<span id="LC6" class="line" lang="plaintext"> str "sit amet."</span>
+<span id="LC7" class="line" lang="plaintext"> list (type=bullet tight=true bullet_char=-)</span>
+<span id="LC8" class="line" lang="plaintext"> list_item</span>
+<span id="LC9" class="line" lang="plaintext"> paragraph</span>
+<span id="LC10" class="line" lang="plaintext"> str "Qui "</span>
+<span id="LC11" class="line" lang="plaintext"> emph</span>
+<span id="LC12" class="line" lang="plaintext"> str "quodsi iracundia"</span>
+<span id="LC13" class="line" lang="plaintext"> list_item</span>
+<span id="LC14" class="line" lang="plaintext"> paragraph</span>
+<span id="LC15" class="line" lang="plaintext"> str "aliquando id"</span></code></pre>
+<copy-code></copy-code>
+</div>
+<p data-sourcepos="10207:1-10209:22" dir="auto">Notice how the [line ending] in the first paragraph has
+been parsed as a <code>softbreak</code>, and the asterisks in the first list item
+have become an <code>emph</code>.</p>
+<h3 data-sourcepos="10211:1-10211:54" dir="auto">
+<a id="user-content-an-algorithm-for-parsing-nested-emphasis-and-links" class="anchor" href="#an-algorithm-for-parsing-nested-emphasis-and-links" aria-hidden="true"></a>An algorithm for parsing nested emphasis and links</h3>
+<p data-sourcepos="10213:1-10215:10" dir="auto">By far the trickiest part of inline parsing is handling emphasis,
+strong emphasis, links, and images. This is done using the following
+algorithm.</p>
+<p data-sourcepos="10217:1-10217:44" dir="auto">When we're parsing inlines and we hit either</p>
+<ul data-sourcepos="10219:1-10221:0" dir="auto">
+<li data-sourcepos="10219:1-10219:36">a run of <code>*</code> or <code>_</code> characters, or</li>
+<li data-sourcepos="10220:1-10221:0">a <code>[</code> or <code>![</code>
+</li>
+</ul>
+<p data-sourcepos="10222:1-10223:60" dir="auto">we insert a text node with these symbols as its literal content, and we
+add a pointer to this text node to the <a href="@">delimiter stack</a>.</p>
+<p data-sourcepos="10225:1-10226:65" dir="auto">The [delimiter stack] is a doubly linked list. Each
+element contains a pointer to a text node, plus information about</p>
+<ul data-sourcepos="10228:1-10234:0" dir="auto">
+<li data-sourcepos="10228:1-10228:45">the type of delimiter (<code>[</code>, <code>![</code>, <code>*</code>, <code>_</code>)</li>
+<li data-sourcepos="10229:1-10229:27">the number of delimiters,</li>
+<li data-sourcepos="10230:1-10230:66">whether the delimiter is "active" (all are active to start), and</li>
+<li data-sourcepos="10231:1-10234:0">whether the delimiter is a potential opener, a potential closer,
+or both (which depends on what sort of characters precede
+and follow the delimiters).</li>
+</ul>
+<p data-sourcepos="10235:1-10236:22" dir="auto">When we hit a <code>]</code> character, we call the <em>look for link or image</em>
+procedure (see below).</p>
+<p data-sourcepos="10238:1-10239:50" dir="auto">When we hit the end of the input, we call the <em>process emphasis</em>
+procedure (see below), with <code>stack_bottom</code> = NULL.</p>
+<h4 data-sourcepos="10241:1-10241:29" dir="auto">
+<a id="user-content-look-for-link-or-image" class="anchor" href="#look-for-link-or-image" aria-hidden="true"></a><em>look for link or image</em>
+</h4>
+<p data-sourcepos="10243:1-10244:55" dir="auto">Starting at the top of the delimiter stack, we look backwards
+through the stack for an opening <code>[</code> or <code>![</code> delimiter.</p>
+<ul data-sourcepos="10246:1-10271:0" dir="auto">
+<li data-sourcepos="10246:1-10247:0">
+<p data-sourcepos="10246:3-10246:58">If we don't find one, we return a literal text node <code>]</code>.</p>
+</li>
+<li data-sourcepos="10248:1-10250:0">
+<p data-sourcepos="10248:3-10249:63">If we do find one, but it's not <em>active</em>, we remove the inactive
+delimiter from the stack, and return a literal text node <code>]</code>.</p>
+</li>
+<li data-sourcepos="10251:1-10271:0">
+<p data-sourcepos="10251:3-10253:47">If we find one and it's active, then we parse ahead to see if
+we have an inline link/image, reference link/image, compact reference
+link/image, or shortcut reference link/image.</p>
+<ul data-sourcepos="10255:3-10271:0">
+<li data-sourcepos="10255:3-10257:0">
+<p data-sourcepos="10255:5-10256:55">If we don't, then we remove the opening delimiter from the
+delimiter stack and return a literal text node <code>]</code>.</p>
+</li>
+<li data-sourcepos="10258:3-10271:0">
+<p data-sourcepos="10258:5-10258:18">If we do, then</p>
+<ul data-sourcepos="10260:5-10271:0">
+<li data-sourcepos="10260:5-10262:0">
+<p data-sourcepos="10260:7-10261:62">We return a link or image node whose children are the inlines
+after the text node pointed to by the opening delimiter.</p>
+</li>
+<li data-sourcepos="10263:5-10265:0">
+<p data-sourcepos="10263:7-10264:24">We run <em>process emphasis</em> on these inlines, with the <code>[</code> opener
+as <code>stack_bottom</code>.</p>
+</li>
+<li data-sourcepos="10266:5-10267:0">
+<p data-sourcepos="10266:7-10266:38">We remove the opening delimiter.</p>
+</li>
+<li data-sourcepos="10268:5-10271:0">
+<p data-sourcepos="10268:7-10270:55">If we have a link (and not an image), we also set all
+<code>[</code> delimiters before the opening delimiter to <em>inactive</em>. (This
+will prevent us from getting links within links.)</p>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<h4 data-sourcepos="10272:1-10272:23" dir="auto">
+<a id="user-content-process-emphasis" class="anchor" href="#process-emphasis" aria-hidden="true"></a><em>process emphasis</em>
+</h4>
+<p data-sourcepos="10274:1-10277:24" dir="auto">Parameter <code>stack_bottom</code> sets a lower bound to how far we
+descend in the [delimiter stack]. If it is NULL, we can
+go all the way to the bottom. Otherwise, we stop before
+visiting <code>stack_bottom</code>.</p>
+<p data-sourcepos="10279:1-10281:9" dir="auto">Let <code>current_position</code> point to the element on the [delimiter stack]
+just above <code>stack_bottom</code> (or the first element if <code>stack_bottom</code>
+is NULL).</p>
+<p data-sourcepos="10283:1-10285:47" dir="auto">We keep track of the <code>openers_bottom</code> for each delimiter
+type (<code>*</code>, <code>_</code>) and each length of the closing delimiter run
+(modulo 3). Initialize this to <code>stack_bottom</code>.</p>
+<p data-sourcepos="10287:1-10288:8" dir="auto">Then we repeat the following until we run out of potential
+closers:</p>
+<ul data-sourcepos="10290:1-10328:0" dir="auto">
+<li data-sourcepos="10290:1-10294:0">
+<p data-sourcepos="10290:3-10293:65">Move <code>current_position</code> forward in the delimiter stack (if needed)
+until we find the first potential closer with delimiter <code>*</code> or <code>_</code>.
+(This will be the potential closer closest
+to the beginning of the input -- the first one in parse order.)</p>
+</li>
+<li data-sourcepos="10295:1-10298:0">
+<p data-sourcepos="10295:3-10297:68">Now, look back in the stack (staying above <code>stack_bottom</code> and
+the <code>openers_bottom</code> for this delimiter type) for the
+first matching potential opener ("matching" means same delimiter).</p>
+</li>
+<li data-sourcepos="10299:1-10316:0">
+<p data-sourcepos="10299:3-10299:18">If one is found:</p>
+<ul data-sourcepos="10301:3-10316:0">
+<li data-sourcepos="10301:3-10304:0">
+<p data-sourcepos="10301:5-10303:30">Figure out whether we have emphasis or strong emphasis:
+if both closer and opener spans have length &gt;= 2, we have
+strong, otherwise regular.</p>
+</li>
+<li data-sourcepos="10305:3-10307:0">
+<p data-sourcepos="10305:5-10306:46">Insert an emph or strong emph node accordingly, after
+the text node corresponding to the opener.</p>
+</li>
+<li data-sourcepos="10308:3-10310:0">
+<p data-sourcepos="10308:5-10309:24">Remove any delimiters between the opener and closer from
+the delimiter stack.</p>
+</li>
+<li data-sourcepos="10311:3-10316:0">
+<p data-sourcepos="10311:5-10315:56">Remove 1 (for regular emph) or 2 (for strong emph) delimiters
+from the opening and closing text nodes. If they become empty
+as a result, remove them and remove the corresponding element
+of the delimiter stack. If the closing node is removed, reset
+<code>current_position</code> to the next element in the stack.</p>
+</li>
+</ul>
+</li>
+<li data-sourcepos="10317:1-10328:0">
+<p data-sourcepos="10317:3-10317:19">If none is found:</p>
+<ul data-sourcepos="10319:3-10328:0">
+<li data-sourcepos="10319:3-10322:0">
+<p data-sourcepos="10319:5-10321:73">Set <code>openers_bottom</code> to the element before <code>current_position</code>.
+(We know that there are no openers for this kind of closer up to and
+including this point, so this puts a lower bound on future searches.)</p>
+</li>
+<li data-sourcepos="10323:3-10326:0">
+<p data-sourcepos="10323:5-10325:24">If the closer at <code>current_position</code> is not a potential opener,
+remove it from the delimiter stack (since we know it can't
+be a closer either).</p>
+</li>
+<li data-sourcepos="10327:3-10328:0">
+<p data-sourcepos="10327:5-10327:64">Advance <code>current_position</code> to the next element in the stack.</p>
+</li>
+</ul>
+</li>
+</ul>
+<p data-sourcepos="10329:1-10330:16" dir="auto">After we're done, we remove all delimiters above <code>stack_bottom</code> from the
+delimiter stack.</p>
diff --git a/glfm_specification/output/spec.txt b/glfm_specification/output/spec.txt
index af4eba06758..a8565b15bc3 100644
--- a/glfm_specification/output/spec.txt
+++ b/glfm_specification/output/spec.txt
@@ -1791,7 +1791,7 @@ followed by one of the strings (case-insensitive) `address`,
`h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `head`, `header`, `hr`,
`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
`nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
-`section`, `source`, `summary`, `table`, `tbody`, `td`,
+`section`, `summary`, `table`, `tbody`, `td`,
`tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed
by [whitespace], the end of the line, the string `>`, or
the string `/>`.\
@@ -9600,7 +9600,7 @@ Multiple spaces
````````````````````````````````
-# GitLab-Specific Markdown
+# GitLab Official Specification Markdown
Currently, only some of the GitLab-specific markdown features are
listed in this section. We will eventually add all
@@ -9802,57 +9802,6 @@ title: YAML front matter
<h2>title: YAML front matter</h2>
````````````````````````````````
-## Audio
-
-See
-[audio](https://docs.gitlab.com/ee/user/markdown.html#audio) in the GitLab Flavored Markdown documentation.
-
-GLFM renders image elements as an audio player as long as the resource’s file extension is
-one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
-Audio ignore the alternative text part of an image declaration.
-
-```````````````````````````````` example gitlab
-![audio](audio.oga "audio title")
-.
-<p><audio src="audio.oga" title="audio title"></audio></p>
-````````````````````````````````
-
-Reference definitions work audio as well:
-
-```````````````````````````````` example gitlab
-[audio]: audio.oga "audio title"
-
-![audio][audio]
-.
-<p><audio src="audio.oga" title="audio title"></audio></p>
-````````````````````````````````
-
-## Video
-
-See
-[videos](https://docs.gitlab.com/ee/user/markdown.html#videos) in the GitLab Flavored Markdown documentation.
-
-GLFM renders image elements as a video player as long as the resource’s file extension is
-one of the following supported video extensions `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`.
-Videos ignore the alternative text part of an image declaration.
-
-
-```````````````````````````````` example gitlab
-![video](video.m4v "video title")
-.
-<p><video src="video.m4v" title="video title"></video></p>
-````````````````````````````````
-
-Reference definitions work video as well:
-
-```````````````````````````````` example gitlab
-[video]: video.mov "video title"
-
-![video][video]
-.
-<p><video src="video.mov" title="video title"></video></p>
-````````````````````````````````
-
## Table of contents
See
@@ -9929,7 +9878,58 @@ A table of contents can be indented with up to three spaces.
<h1>Heading 1</h1>
````````````````````````````````
-# Examples Using Internal Extensions
+# GitLab Internal Extension Markdown
+
+## Audio
+
+See
+[audio](https://docs.gitlab.com/ee/user/markdown.html#audio) in the GitLab Flavored Markdown documentation.
+
+GLFM renders image elements as an audio player as long as the resource’s file extension is
+one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
+Audio ignore the alternative text part of an image declaration.
+
+```````````````````````````````` example gitlab
+![audio](audio.oga "audio title")
+.
+<p><audio src="audio.oga" title="audio title"></audio></p>
+````````````````````````````````
+
+Reference definitions work audio as well:
+
+```````````````````````````````` example gitlab
+[audio]: audio.oga "audio title"
+
+![audio][audio]
+.
+<p><audio src="audio.oga" title="audio title"></audio></p>
+````````````````````````````````
+
+## Video
+
+See
+[videos](https://docs.gitlab.com/ee/user/markdown.html#videos) in the GitLab Flavored Markdown documentation.
+
+GLFM renders image elements as a video player as long as the resource’s file extension is
+one of the following supported video extensions `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`.
+Videos ignore the alternative text part of an image declaration.
+
+
+```````````````````````````````` example gitlab
+![video](video.m4v "video title")
+.
+<p><video src="video.m4v" title="video title"></video></p>
+````````````````````````````````
+
+Reference definitions work video as well:
+
+```````````````````````````````` example gitlab
+[video]: video.mov "video title"
+
+![video][video]
+.
+<p><video src="video.mov" title="video title"></video></p>
+````````````````````````````````
## Markdown Preview API Request Overrides
@@ -10328,4 +10328,3 @@ closers:
After we're done, we remove all delimiters above `stack_bottom` from the
delimiter stack.
-
diff --git a/jest.config.base.js b/jest.config.base.js
index d90a3b9825e..a6c22a8877c 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -144,6 +144,8 @@ module.exports = (path, options = {}) => {
'three',
'monaco-editor',
'monaco-yaml',
+ 'monaco-marker-data-provider',
+ 'monaco-worker-manager',
'fast-mersenne-twister',
'prosemirror-markdown',
'marked',
@@ -172,7 +174,7 @@ module.exports = (path, options = {}) => {
restoreMocks: true,
slowTestThreshold: process.env.CI ? 6000 : 500,
transform: {
- '^.+\\.(gql|graphql)$': 'jest-transform-graphql',
+ '^.+\\.(gql|graphql)$': './spec/frontend/__helpers__/graphql_transformer.js',
'^.+_worker\\.js$': './spec/frontend/__helpers__/web_worker_transformer.js',
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': '@vue/vue2-jest',
diff --git a/lefthook.yml b/lefthook.yml
index 8a3a0d8c2cb..a2819358bdf 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -8,6 +8,11 @@ pre-push:
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
glob: '*.{js,vue}'
run: yarn run lint:eslint {files}
+ jsonlint:
+ tags: style
+ files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
+ glob: '*.{json}'
+ run: scripts/lint-json.sh {files}
haml-lint:
tags: view haml style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
diff --git a/lib/api/access_requests.rb b/lib/api/access_requests.rb
index e6ce62a1c6e..74f6515f07f 100644
--- a/lib/api/access_requests.rb
+++ b/lib/api/access_requests.rb
@@ -12,7 +12,8 @@ module API
%w[group project].each do |source_type|
params do
- requires :id, type: String, desc: "The #{source_type} ID"
+ requires :id, type: String,
+ desc: "The ID or URL-encoded path of the #{source_type} owned by the authenticated user"
end
resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Gets a list of access requests for a #{source_type}." do
@@ -54,7 +55,8 @@ module API
end
params do
requires :user_id, type: Integer, desc: 'The user ID of the access requester'
- optional :access_level, type: Integer, desc: 'A valid access level (defaults: `30`, developer access level)'
+ optional :access_level, type: Integer, desc: 'A valid access level (defaults: `30`, the Developer role)',
+ default: 30
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/access_requests/:user_id/approve' do
diff --git a/lib/api/admin/batched_background_migrations.rb b/lib/api/admin/batched_background_migrations.rb
index 675f3365bd3..e8cc08a23be 100644
--- a/lib/api/admin/batched_background_migrations.rb
+++ b/lib/api/admin/batched_background_migrations.rb
@@ -61,6 +61,11 @@ module API
end
put do
Gitlab::Database::SharedModel.using_connection(base_model.connection) do
+ unless batched_background_migration.paused?
+ msg = 'You can resume only `paused` batched background migrations.'
+ render_api_error!(msg, 422)
+ end
+
batched_background_migration.execute!
present_entity(batched_background_migration)
end
@@ -81,6 +86,11 @@ module API
end
put do
Gitlab::Database::SharedModel.using_connection(base_model.connection) do
+ unless batched_background_migration.active?
+ msg = 'You can pause only `active` batched background migrations.'
+ render_api_error!(msg, 422)
+ end
+
batched_background_migration.pause!
present_entity(batched_background_migration)
end
diff --git a/lib/api/alert_management_alerts.rb b/lib/api/alert_management_alerts.rb
index bbb7e7280c9..f03f133f6f7 100644
--- a/lib/api/alert_management_alerts.rb
+++ b/lib/api/alert_management_alerts.rb
@@ -32,7 +32,8 @@ module API
success Entities::MetricImage
end
params do
- requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The image file to be uploaded'
+ requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The image file to be uploaded',
+ documentation: { type: 'file' }
optional :url, type: String, desc: 'The url to view more metric info'
optional :url_text, type: String, desc: 'A description of the image or URL'
end
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 443bf1d649a..933c3f69075 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -3,6 +3,7 @@
module API
class API < ::API::Base
include APIGuard
+ include Helpers::OpenApi
LOG_FILENAME = Rails.root.join("log", "api_json.log")
@@ -165,6 +166,13 @@ module API
::Users::ActivityService.new(@current_user).execute
end
+ # Mount endpoints to include in the OpenAPI V2 documentation here
+ namespace do
+ mount ::API::Metadata
+
+ add_open_api_documentation!
+ end
+
# Keep in alphabetical order
mount ::API::AccessRequests
mount ::API::Admin::BatchedBackgroundMigrations
@@ -250,7 +258,6 @@ module API
mount ::API::MergeRequestApprovals
mount ::API::MergeRequestDiffs
mount ::API::MergeRequests
- mount ::API::Metadata
mount ::API::Metrics::Dashboard::Annotations
mount ::API::Metrics::UserStarredDashboards
mount ::API::Namespaces
@@ -263,7 +270,7 @@ module API
mount ::API::PackageFiles
mount ::API::Pages
mount ::API::PagesDomains
- mount ::API::PersonalAccessTokens::SelfRevocation
+ mount ::API::PersonalAccessTokens::SelfInformation
mount ::API::PersonalAccessTokens
mount ::API::ProjectClusters
mount ::API::ProjectContainerRepositories
@@ -316,7 +323,6 @@ module API
mount ::API::UsageDataQueries
mount ::API::UserCounts
mount ::API::Users
- mount ::API::Version
mount ::API::Wikis
mount ::API::Ml::Mlflow
end
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 70488621f33..4048215160f 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -41,6 +41,9 @@ module API
end
desc 'Delete an application'
+ params do
+ requires :id, type: Integer, desc: 'The ID of the application (not the application_id)'
+ end
delete ':id' do
application = ApplicationsFinder.new(params).execute
break not_found!('Application') unless application
diff --git a/lib/api/badges.rb b/lib/api/badges.rb
index f969eec8431..0a3f247ffd6 100644
--- a/lib/api/badges.rb
+++ b/lib/api/badges.rb
@@ -31,6 +31,7 @@ module API
end
params do
use :pagination
+ optional :name, type: String, desc: 'Name for the badge'
end
get ":id/badges", urgency: :low do
source = find_source(source_type, params[:id])
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 5588818cbaf..7e6b0214c03 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -52,19 +52,13 @@ module API
merged_branch_names = repository.merged_branch_names(branches.map(&:name))
- expiry_time = if Feature.enabled?(:increase_branch_cache_expiry, type: :ops)
- 60.minutes
- else
- 10.minutes
- end
-
present_cached(
branches,
with: Entities::Branch,
current_user: current_user,
project: user_project,
merged_branch_names: merged_branch_names,
- expires_in: expiry_time,
+ expires_in: 60.minutes,
cache_context: -> (branch) { [current_user&.cache_key, merged_branch_names.include?(branch.name)] }
)
end
diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb
index 2c6adc0f37b..c54632919be 100644
--- a/lib/api/bulk_imports.rb
+++ b/lib/api/bulk_imports.rb
@@ -32,11 +32,16 @@ module API
end
end
- before { authenticate! }
+ before do
+ not_found! unless ::BulkImports::Features.enabled?
+
+ authenticate!
+ end
resource :bulk_imports do
desc 'Start a new GitLab Migration' do
detail 'This feature was introduced in GitLab 14.2.'
+ success Entities::BulkImport
end
params do
requires :configuration, type: Hash, desc: 'The source GitLab instance configuration' do
@@ -83,6 +88,7 @@ module API
desc 'List all GitLab Migrations' do
detail 'This feature was introduced in GitLab 14.1.'
+ success Entities::BulkImport
end
params do
use :pagination
@@ -97,6 +103,7 @@ module API
desc "List all GitLab Migrations' entities" do
detail 'This feature was introduced in GitLab 14.1.'
+ success Entities::BulkImports::Entity
end
params do
use :pagination
@@ -116,6 +123,7 @@ module API
desc 'Get GitLab Migration details' do
detail 'This feature was introduced in GitLab 14.1.'
+ success Entities::BulkImport
end
params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
@@ -126,6 +134,7 @@ module API
desc "List GitLab Migration entities" do
detail 'This feature was introduced in GitLab 14.1.'
+ success Entities::BulkImports::Entity
end
params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
@@ -139,6 +148,7 @@ module API
desc 'Get GitLab Migration entity details' do
detail 'This feature was introduced in GitLab 14.1.'
+ success Entities::BulkImports::Entity
end
params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb
index b3a0a9ef54a..37c7cc73c46 100644
--- a/lib/api/ci/job_artifacts.rb
+++ b/lib/api/ci/job_artifacts.rb
@@ -38,7 +38,7 @@ module API
latest_build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
authorize_read_job_artifacts!(latest_build)
- present_artifacts_file!(latest_build.artifacts_file)
+ present_artifacts_file!(latest_build.artifacts_file, project: latest_build.project)
end
desc 'Download a specific file from artifacts archive from a ref' do
@@ -80,7 +80,7 @@ module API
build = find_build!(params[:job_id])
authorize_read_job_artifacts!(build)
- present_artifacts_file!(build.artifacts_file)
+ present_artifacts_file!(build.artifacts_file, project: build.project)
end
desc 'Download a specific file from artifacts archive' do
diff --git a/lib/api/ci/resource_groups.rb b/lib/api/ci/resource_groups.rb
index e3fd887475a..ea6d3cc8fd4 100644
--- a/lib/api/ci/resource_groups.rb
+++ b/lib/api/ci/resource_groups.rb
@@ -38,6 +38,25 @@ module API
present resource_group, with: Entities::Ci::ResourceGroup
end
+ desc 'List upcoming jobs of a resource group' do
+ success Entities::Ci::JobBasic
+ end
+ params do
+ requires :key, type: String, desc: 'The key of the resource group'
+
+ use :pagination
+ end
+ get ':id/resource_groups/:key/upcoming_jobs' do
+ authorize! :read_resource_group, resource_group
+ authorize! :read_build, user_project
+
+ upcoming_processables = resource_group
+ .upcoming_processables
+ .preload(:user, pipeline: :project) # rubocop:disable CodeReuse/ActiveRecord
+
+ present paginate(upcoming_processables), with: Entities::Ci::JobBasic
+ end
+
desc 'Edit a resource group' do
success Entities::Ci::ResourceGroup
end
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 9e4a700d0f3..2d2dcc544f9 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -332,7 +332,7 @@ module API
authenticate_job!(require_running: false)
end
- present_artifacts_file!(current_job.artifacts_file, supports_direct_download: params[:direct_download])
+ present_artifacts_file!(current_job.artifacts_file, project: current_job.project, supports_direct_download: params[:direct_download])
end
end
end
diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb
index c1f47dd67ce..68431df203b 100644
--- a/lib/api/ci/secure_files.rb
+++ b/lib/api/ci/secure_files.rb
@@ -74,6 +74,10 @@ module API
file_too_large! unless secure_file.file.size < ::Ci::SecureFile::FILE_SIZE_LIMIT.to_i
if secure_file.save
+ if Feature.enabled?(:secure_files_metadata_parsers, user_project)
+ ::Ci::ParseSecureFileMetadataWorker.perform_async(secure_file.id) # rubocop:disable CodeReuse/Worker
+ end
+
present secure_file, with: Entities::Ci::SecureFile
else
render_validation_error!(secure_file)
diff --git a/lib/api/ci/variables.rb b/lib/api/ci/variables.rb
index f9707960b9d..c9e1d115d03 100644
--- a/lib/api/ci/variables.rb
+++ b/lib/api/ci/variables.rb
@@ -33,6 +33,9 @@ module API
end
params do
requires :key, type: String, desc: 'The key of the variable'
+ optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
+ optional :environment_scope, type: String, desc: 'The environment scope of the variable'
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/variables/:key', urgency: :low do
@@ -78,7 +81,9 @@ module API
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
- optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production'
+ optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
+ optional :environment_scope, type: String, desc: 'The environment scope of the variable'
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
@@ -104,7 +109,9 @@ module API
end
params do
requires :key, type: String, desc: 'The key of the variable'
- optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production'
+ optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
+ optional :environment_scope, type: String, desc: 'The environment scope of the variable'
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
delete ':id/variables/:key' do
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 5a6d06dcdd9..7d8b58fd7b6 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -52,8 +52,8 @@ module API
optional :ref, type: String, desc: 'The ref'
optional :target_url, type: String, desc: 'The target URL to associate with this status'
optional :description, type: String, desc: 'A short description of the status'
- optional :name, type: String, desc: 'A string label to differentiate this status from the status of other systems. Default: "default"'
- optional :context, type: String, desc: 'A string label to differentiate this status from the status of other systems. Default: "default"'
+ optional :name, type: String, desc: 'A string label to differentiate this status from the status of other systems. Default: "default"', documentation: { default: 'default' }
+ optional :context, type: String, desc: 'A string label to differentiate this status from the status of other systems. Default: "default"', documentation: { default: 'default' }
optional :coverage, type: Float, desc: 'The total code coverage'
optional :pipeline_id, type: Integer, desc: 'An existing pipeline ID, when multiple pipelines on the same commit SHA have been triggered'
end
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
index d6e006df976..4cc680068b6 100644
--- a/lib/api/concerns/packages/npm_endpoints.rb
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -116,7 +116,12 @@ module API
redirect_request = project_or_nil.blank? || packages.empty?
- redirect_registry_request(redirect_request, :npm, package_name: package_name) do
+ redirect_registry_request(
+ forward_to_registry: redirect_request,
+ package_type: :npm,
+ target: project_or_nil,
+ package_name: package_name
+ ) do
authorize_read_package!(project)
not_found!('Packages') if packages.empty?
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index 9dedc4390f7..03f0f97b805 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -81,11 +81,7 @@ module API
package = ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute
- package_file = ::Packages::Debian::CreatePackageFileService.new(package, file_params).execute
-
- if params['file_name'].end_with? '.changes'
- ::Packages::Debian::ProcessChangesWorker.perform_async(package_file.id, current_user.id) # rubocop:disable CodeReuse/Worker
- end
+ ::Packages::Debian::CreatePackageFileService.new(package: package, current_user: current_user, params: file_params).execute
created!
rescue ObjectStorage::RemoteStoreError => e
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index ca13db8701e..c53f4bca5a7 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -161,9 +161,7 @@ module API
end
end
- desc 'Delete deploy key for a project' do
- success Key
- end
+ desc 'Delete deploy key for a project'
params do
requires :key_id, type: Integer, desc: 'The ID of the deploy key'
end
diff --git a/lib/api/entities/bulk_imports/entity_failure.rb b/lib/api/entities/bulk_imports/entity_failure.rb
index a3dbe3280ee..56312745868 100644
--- a/lib/api/entities/bulk_imports/entity_failure.rb
+++ b/lib/api/entities/bulk_imports/entity_failure.rb
@@ -4,11 +4,16 @@ module API
module Entities
module BulkImports
class EntityFailure < Grape::Entity
- expose :pipeline_class
- expose :pipeline_step
+ expose :relation
+ expose :pipeline_step, as: :step
+ expose :exception_message do |failure|
+ ::Projects::ImportErrorFilter.filter_message(failure.exception_message.truncate(72))
+ end
expose :exception_class
expose :correlation_id_value
expose :created_at
+ expose :pipeline_class
+ expose :pipeline_step
end
end
end
diff --git a/lib/api/entities/ci/job_basic.rb b/lib/api/entities/ci/job_basic.rb
index 3d9318ec428..fb975475cf5 100644
--- a/lib/api/entities/ci/job_basic.rb
+++ b/lib/api/entities/ci/job_basic.rb
@@ -21,7 +21,7 @@ module API
expose :project do
expose :ci_job_token_scope_enabled do |job|
- job.project.ci_job_token_scope_enabled?
+ job.project.ci_outbound_job_token_scope_enabled?
end
end
end
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index e29d55771f2..f034eb5c94c 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -7,7 +7,7 @@ module API
expose :id
expose :description
expose :ip_address
- expose :active # TODO Remove in %16.0 in favor of `paused` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/351109
+ expose :active # TODO Remove in v5 in favor of `paused` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/375709
expose :paused do |runner|
!runner.active
end
@@ -16,7 +16,7 @@ module API
expose :name
expose :online?, as: :online
# DEPRECATED
- # TODO Remove in %16.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ # TODO Remove in v5 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/375709
expose :deprecated_rest_status, as: :status
end
end
diff --git a/lib/api/entities/license.rb b/lib/api/entities/license.rb
index d7a414344c1..8ecf8a430fe 100644
--- a/lib/api/entities/license.rb
+++ b/lib/api/entities/license.rb
@@ -2,6 +2,7 @@
module API
module Entities
+ # Serializes a Licensee::License
class License < Entities::LicenseBasic
expose :popular?, as: :popular
expose(:description) { |license| license.meta['description'] }
diff --git a/lib/api/entities/license_basic.rb b/lib/api/entities/license_basic.rb
index 08af68785a9..0916738d21d 100644
--- a/lib/api/entities/license_basic.rb
+++ b/lib/api/entities/license_basic.rb
@@ -2,10 +2,16 @@
module API
module Entities
+ # Serializes a Gitlab::Git::DeclaredLicense
class LicenseBasic < Grape::Entity
expose :key, :name, :nickname
expose :url, as: :html_url
- expose(:source_url) { |license| license.meta['source'] }
+
+ # This was dropped:
+ # https://github.com/github/choosealicense.com/commit/325806b42aa3d5b78e84120327ec877bc936dbdd#diff-66df8f1997786f7052d29010f2cbb4c66391d60d24ca624c356acc0ab986f139
+ expose :source_url do |_|
+ nil
+ end
end
end
end
diff --git a/lib/api/entities/merge_request_approvals.rb b/lib/api/entities/merge_request_approvals.rb
index 0c464844ae7..6810952b2fc 100644
--- a/lib/api/entities/merge_request_approvals.rb
+++ b/lib/api/entities/merge_request_approvals.rb
@@ -8,7 +8,7 @@ module API
end
expose :user_can_approve do |merge_request, options|
- merge_request.can_be_approved_by?(options[:current_user])
+ merge_request.eligible_for_approval_by?(options[:current_user])
end
expose :approved do |merge_request|
diff --git a/lib/api/entities/metadata.rb b/lib/api/entities/metadata.rb
new file mode 100644
index 00000000000..daa491ec42a
--- /dev/null
+++ b/lib/api/entities/metadata.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class Metadata < Grape::Entity
+ expose :version
+ expose :revision
+ expose :kas do
+ expose :enabled, documentation: { type: 'boolean' }
+ expose :externalUrl
+ expose :version
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ml/mlflow/experiment.rb b/lib/api/entities/ml/mlflow/experiment.rb
index cfe366feaab..54e0fe63985 100644
--- a/lib/api/entities/ml/mlflow/experiment.rb
+++ b/lib/api/entities/ml/mlflow/experiment.rb
@@ -5,22 +5,10 @@ module API
module Ml
module Mlflow
class Experiment < Grape::Entity
- expose :experiment do
- expose :experiment_id
- expose :name
- expose :lifecycle_stage
- expose :artifact_location
- end
-
- private
-
- def lifecycle_stage
- object.deleted_on? ? 'deleted' : 'active'
- end
-
- def experiment_id
- object.iid.to_s
- end
+ expose(:experiment_id) { |experiment| experiment.iid.to_s }
+ expose :name
+ expose(:lifecycle_stage) { |experiment| experiment.deleted_on? ? 'deleted' : 'active' }
+ expose(:artifact_location) { |experiment| 'not_implemented' }
end
end
end
diff --git a/lib/api/entities/ml/mlflow/get_experiment.rb b/lib/api/entities/ml/mlflow/get_experiment.rb
new file mode 100644
index 00000000000..f28d2ce76f6
--- /dev/null
+++ b/lib/api/entities/ml/mlflow/get_experiment.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ml
+ module Mlflow
+ class GetExperiment < Grape::Entity
+ expose :itself, using: Experiment, as: :experiment
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ml/mlflow/list_experiment.rb b/lib/api/entities/ml/mlflow/list_experiment.rb
new file mode 100644
index 00000000000..515015bf4b7
--- /dev/null
+++ b/lib/api/entities/ml/mlflow/list_experiment.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ml
+ module Mlflow
+ class ListExperiment < Grape::Entity
+ expose :experiments, with: Experiment
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ml/mlflow/metric.rb b/lib/api/entities/ml/mlflow/metric.rb
new file mode 100644
index 00000000000..963aaa5f144
--- /dev/null
+++ b/lib/api/entities/ml/mlflow/metric.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ml
+ module Mlflow
+ class Metric < Grape::Entity
+ expose :name, as: :key
+ expose :value
+ expose :tracked_at, as: :timestamp
+ expose :step, expose_nil: false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ml/mlflow/run.rb b/lib/api/entities/ml/mlflow/run.rb
index c679330206e..a8e1cfe08dd 100644
--- a/lib/api/entities/ml/mlflow/run.rb
+++ b/lib/api/entities/ml/mlflow/run.rb
@@ -7,7 +7,10 @@ module API
class Run < Grape::Entity
expose :run do
expose(:info) { |candidate| RunInfo.represent(candidate) }
- expose(:data) { |candidate| {} }
+ expose :data do
+ expose :metrics, using: Metric
+ expose :params, using: RunParam
+ end
end
end
end
diff --git a/lib/api/entities/ml/mlflow/run_param.rb b/lib/api/entities/ml/mlflow/run_param.rb
new file mode 100644
index 00000000000..75fee738f8b
--- /dev/null
+++ b/lib/api/entities/ml/mlflow/run_param.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ml
+ module Mlflow
+ class RunParam < Grape::Entity
+ expose :name, as: :key
+ expose :value
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ml/mlflow/update_run.rb b/lib/api/entities/ml/mlflow/update_run.rb
index 5acdaab0e33..090d69b8895 100644
--- a/lib/api/entities/ml/mlflow/update_run.rb
+++ b/lib/api/entities/ml/mlflow/update_run.rb
@@ -10,7 +10,7 @@ module API
private
def run_info
- ::API::Entities::Ml::Mlflow::RunInfo.represent object
+ RunInfo.represent object
end
end
end
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 1739bdd639e..f158695f605 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -80,6 +80,7 @@ module API
expose(:analytics_access_level) { |project, options| project_feature_string_access_level(project, :analytics) }
expose(:container_registry_access_level) { |project, options| project_feature_string_access_level(project, :container_registry) }
expose(:security_and_compliance_access_level) { |project, options| project_feature_string_access_level(project, :security_and_compliance) }
+ expose(:releases_access_level) { |project, options| project_feature_string_access_level(project, :releases) }
expose :emails_disabled
expose :shared_runners_enabled
@@ -103,7 +104,7 @@ module API
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :ci_default_git_depth
expose :ci_forward_deployment_enabled
- expose :ci_job_token_scope_enabled
+ expose(:ci_job_token_scope_enabled) { |p, _| p.ci_outbound_job_token_scope_enabled? }
expose :ci_separated_caches
expose :ci_opt_in_jwt
expose :ci_allow_fork_pipelines_to_run_in_parent_project
diff --git a/lib/api/entities/user_with_admin.rb b/lib/api/entities/user_with_admin.rb
index f9c1a646a4f..53fef7a46e2 100644
--- a/lib/api/entities/user_with_admin.rb
+++ b/lib/api/entities/user_with_admin.rb
@@ -6,6 +6,7 @@ module API
expose :admin?, as: :is_admin
expose :note
expose :namespace_id
+ expose :created_by, with: UserBasic
end
end
end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index c4b67f83941..42d5e6a73b3 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -40,7 +40,7 @@ module API
params do
requires :name, type: String, desc: 'The name of the environment to be created'
optional :external_url, type: String, desc: 'URL on which this deployment is viewable'
- optional :slug, absence: { message: "is automatically generated and cannot be changed" }
+ optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
end
post ':id/environments' do
@@ -64,7 +64,7 @@ module API
# TODO: disallow renaming via the API https://gitlab.com/gitlab-org/gitlab/-/issues/338897
optional :name, type: String, desc: 'DEPRECATED: Renaming environment can lead to errors, this will be removed in 15.0'
optional :external_url, type: String, desc: 'The new URL on which this deployment is viewable'
- optional :slug, absence: { message: "is automatically generated and cannot be changed" }
+ optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
end
put ':id/environments/:environment_id' do
diff --git a/lib/api/features.rb b/lib/api/features.rb
index f89da48acea..9d4e6eee82c 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -7,6 +7,7 @@ module API
feature_category :feature_flags
urgency :low
+ # TODO: remove these helpers with feature flag set_feature_flag_service
helpers do
def gate_value(params)
case params[:value]
@@ -87,35 +88,49 @@ module API
mutually_exclusive :key, :project
end
post ':name' do
- validate_feature_flag_name!(params[:name]) unless params[:force]
-
- targets = gate_targets(params)
- value = gate_value(params)
- key = gate_key(params)
-
- case value
- when true
- if gate_specified?(params)
- targets.each { |target| Feature.enable(params[:name], target) }
- else
- Feature.enable(params[:name])
- end
- when false
- if gate_specified?(params)
- targets.each { |target| Feature.disable(params[:name], target) }
+ if Feature.enabled?(:set_feature_flag_service)
+ flag_params = declared_params(include_missing: false)
+ response = ::Admin::SetFeatureFlagService
+ .new(feature_flag_name: params[:name], params: flag_params)
+ .execute
+
+ if response.success?
+ present response.payload[:feature_flag],
+ with: Entities::Feature, current_user: current_user
else
- Feature.disable(params[:name])
+ bad_request!(response.message)
end
else
- if key == :percentage_of_actors
- Feature.enable_percentage_of_actors(params[:name], value)
+ validate_feature_flag_name!(params[:name]) unless params[:force]
+
+ targets = gate_targets(params)
+ value = gate_value(params)
+ key = gate_key(params)
+
+ case value
+ when true
+ if gate_specified?(params)
+ targets.each { |target| Feature.enable(params[:name], target) }
+ else
+ Feature.enable(params[:name])
+ end
+ when false
+ if gate_specified?(params)
+ targets.each { |target| Feature.disable(params[:name], target) }
+ else
+ Feature.disable(params[:name])
+ end
else
- Feature.enable_percentage_of_time(params[:name], value)
+ if key == :percentage_of_actors
+ Feature.enable_percentage_of_actors(params[:name], value)
+ else
+ Feature.enable_percentage_of_time(params[:name], value)
+ end
end
- end
- present Feature.get(params[:name]), # rubocop:disable Gitlab/AvoidFeatureGet
- with: Entities::Feature, current_user: current_user
+ present Feature.get(params[:name]), # rubocop:disable Gitlab/AvoidFeatureGet
+ with: Entities::Feature, current_user: current_user
+ end
rescue Feature::Target::UnknowTargetError => e
bad_request!(e.message)
end
@@ -128,6 +143,7 @@ module API
end
end
+ # TODO: remove this helper with feature flag set_feature_flag_service
helpers do
def validate_feature_flag_name!(name)
# no-op
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index ad5455c5de6..0098b074f05 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -40,6 +40,8 @@ module API
end
put 'authorize' do
+ project = authorized_user_project
+
authorize_workhorse!(subject: project, maximum_size: project.actual_limits.generic_packages_max_file_size)
end
@@ -59,6 +61,8 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
put do
+ project = authorized_user_project
+
authorize_upload!(project)
bad_request!('File is too large') if max_file_size_exceeded?
@@ -95,6 +99,8 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get do
+ project = authorized_user_project(action: :read_package)
+
authorize_read_package!(project)
package = ::Packages::Generic::PackageFinder.new(project).execute!(params[:package_name], params[:package_version])
@@ -112,12 +118,8 @@ module API
include ::API::Helpers::PackagesHelpers
include ::API::Helpers::Packages::BasicAuthHelpers
- def project
- authorized_user_project
- end
-
def max_file_size_exceeded?
- project.actual_limits.exceeded?(:generic_packages_max_file_size, params[:file].size)
+ authorized_user_project.actual_limits.exceeded?(:generic_packages_max_file_size, params[:file].size)
end
end
end
diff --git a/lib/api/group_import.rb b/lib/api/group_import.rb
index abb8c10efc6..cef9b542c9e 100644
--- a/lib/api/group_import.rb
+++ b/lib/api/group_import.rb
@@ -54,7 +54,7 @@ module API
params do
requires :path, type: String, desc: 'Group path'
requires :name, type: String, desc: 'Group name'
- requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The group export file to be imported'
+ requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The group export file to be imported', documentation: { type: 'file' }
optional :parent_id, type: Integer, desc: "The ID of the parent group that the group will be imported into. Defaults to the current user's namespace."
end
post 'import' do
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 6b1fc0d4279..ca99e30fbf7 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -123,6 +123,12 @@ module API
end
def present_groups_with_pagination_strategies(params, groups)
+ # Prevent Rails from optimizing the count query and inadvertadly creating a poor performing databse query.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/368969
+ if Feature.enabled?(:present_groups_select_all)
+ groups = groups.select(groups.arel_table[Arel.star])
+ end
+
return present_groups(params, groups) if current_user.present?
options = {
diff --git a/lib/api/helm_packages.rb b/lib/api/helm_packages.rb
index f90084a7e57..fa2537bcfc4 100644
--- a/lib/api/helm_packages.rb
+++ b/lib/api/helm_packages.rb
@@ -44,9 +44,10 @@ module API
end
get ":channel/index.yaml" do
- authorize_read_package!(authorized_user_project)
+ project = authorized_user_project(action: :read_package)
+ authorize_read_package!(project)
- packages = Packages::Helm::PackagesFinder.new(authorized_user_project, params[:channel]).execute
+ packages = Packages::Helm::PackagesFinder.new(project, params[:channel]).execute
env['api.format'] = :yaml
present ::Packages::Helm::IndexPresenter.new(params[:id], params[:channel], packages),
@@ -61,11 +62,12 @@ module API
requires :file_name, type: String, desc: 'Helm package file name'
end
get ":channel/charts/:file_name.tgz" do
- authorize_read_package!(authorized_user_project)
+ project = authorized_user_project(action: :read_package)
+ authorize_read_package!(project)
- package_file = Packages::Helm::PackageFilesFinder.new(authorized_user_project, params[:channel], file_name: "#{params[:file_name]}.tgz").most_recent!
+ package_file = Packages::Helm::PackageFilesFinder.new(project, params[:channel], file_name: "#{params[:file_name]}.tgz").most_recent!
- track_package_event('pull_package', :helm, project: authorized_user_project, namespace: authorized_user_project.namespace)
+ track_package_event('pull_package', :helm, project: project, namespace: project.namespace)
present_package_file!(package_file)
end
@@ -89,7 +91,7 @@ module API
end
params do
requires :channel, type: String, desc: 'Helm channel', regexp: Gitlab::Regex.helm_channel_regex
- requires :chart, type: ::API::Validations::Types::WorkhorseFile, desc: 'The chart file to be published (generated by Multipart middleware)'
+ requires :chart, type: ::API::Validations::Types::WorkhorseFile, desc: 'The chart file to be published (generated by Multipart middleware)', documentation: { type: 'file' }
end
post "api/:channel/charts" do
authorize_upload!(authorized_user_project)
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index e29d76a5950..0eb4fbb196c 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -18,6 +18,7 @@ module API
API_TOKEN_ENV = 'gitlab.api.token'
API_EXCEPTION_ENV = 'gitlab.api.exception'
API_RESPONSE_STATUS_CODE = 'gitlab.api.response_status_code'
+ INTEGER_ID_REGEX = /^-?\d+$/.freeze
def declared_params(options = {})
options = { include_parent_namespaces: false }.merge(options)
@@ -139,7 +140,7 @@ module API
projects = Project.without_deleted.not_hidden
- if id.is_a?(Integer) || id =~ /^\d+$/
+ if id.is_a?(Integer) || id =~ INTEGER_ID_REGEX
projects.find_by(id: id)
elsif id.include?("/")
projects.find_by_full_path(id)
@@ -168,7 +169,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_group(id)
- if id.to_s =~ /^\d+$/
+ if id.to_s =~ INTEGER_ID_REGEX
Group.find_by(id: id)
else
Group.find_by_full_path(id)
@@ -203,7 +204,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_namespace(id)
- if id.to_s =~ /^\d+$/
+ if id.to_s =~ INTEGER_ID_REGEX
Namespace.without_project_namespaces.find_by(id: id)
else
find_namespace_by_path(id)
@@ -286,22 +287,11 @@ module API
end
def authenticate_by_gitlab_shell_token!
- if Feature.enabled?(:gitlab_shell_jwt_token)
- begin
- payload, _ = JSONWebToken::HMACToken.decode(headers[GITLAB_SHELL_API_HEADER], secret_token)
- unauthorized! unless payload['iss'] == GITLAB_SHELL_JWT_ISSUER
- rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature => ex
- Gitlab::ErrorTracking.track_exception(ex)
- unauthorized!
- end
- else
- input = params['secret_token']
- input ||= Base64.decode64(headers[GITLAB_SHARED_SECRET_HEADER]) if headers.key?(GITLAB_SHARED_SECRET_HEADER)
-
- input&.chomp!
-
- unauthorized! unless Devise.secure_compare(secret_token, input)
- end
+ payload, _ = JSONWebToken::HMACToken.decode(headers[GITLAB_SHELL_API_HEADER], secret_token)
+ unauthorized! unless payload['iss'] == GITLAB_SHELL_JWT_ISSUER
+ rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature => ex
+ Gitlab::ErrorTracking.track_exception(ex)
+ unauthorized!
end
def authenticated_with_can_read_all_resources!
@@ -602,19 +592,19 @@ module API
end
end
- def present_artifacts_file!(file, **args)
+ def present_artifacts_file!(file, project:, **args)
log_artifacts_filesize(file&.model)
- present_carrierwave_file!(file, **args)
+ present_carrierwave_file!(file, project: project, **args)
end
- def present_carrierwave_file!(file, supports_direct_download: true)
+ def present_carrierwave_file!(file, project: nil, supports_direct_download: true)
return not_found! unless file&.exists?
if file.file_storage?
present_disk_file!(file.path, file.filename)
elsif supports_direct_download && file.class.direct_download_enabled?
- redirect(file.url)
+ redirect(cdn_fronted_url(file, project))
else
header(*Gitlab::Workhorse.send_url(file.url))
status :ok
@@ -622,6 +612,16 @@ module API
end
end
+ def cdn_fronted_url(file, project)
+ if file.respond_to?(:cdn_enabled_url)
+ result = file.cdn_enabled_url(project, ip_address)
+ Gitlab::ApplicationContext.push(artifact_used_cdn: result.used_cdn)
+ result.url
+ else
+ file.url
+ end
+ end
+
def increment_counter(event_name)
Gitlab::UsageDataCounters.count(event_name)
rescue StandardError => error
@@ -732,13 +732,7 @@ module API
end
def secret_token
- if Feature.enabled?(:gitlab_shell_jwt_token)
- strong_memoize(:secret_token) do
- File.read(Gitlab.config.gitlab_shell.secret_file)
- end
- else
- Gitlab::Shell.secret_token
- end
+ Gitlab::Shell.secret_token
end
def authenticate_non_public?
diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb
index e9af50b80be..74c8b582fde 100644
--- a/lib/api/helpers/groups_helpers.rb
+++ b/lib/api/helpers/groups_helpers.rb
@@ -11,7 +11,7 @@ module API
optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the group'
- optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for the group'
+ optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for the group', documentation: { type: 'file' }
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users in this group to setup Two-factor authentication'
optional :two_factor_grace_period, type: Integer, desc: 'Time before Two-factor authentication is enforced'
diff --git a/lib/api/helpers/open_api.rb b/lib/api/helpers/open_api.rb
new file mode 100644
index 00000000000..11602244b57
--- /dev/null
+++ b/lib/api/helpers/open_api.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module OpenApi
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def add_open_api_documentation!
+ return if Rails.env.production?
+
+ open_api_config = YAML.load_file(Rails.root.join('config/open_api.yml'))['metadata'].deep_symbolize_keys
+
+ add_swagger_documentation(open_api_config)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/packages/basic_auth_helpers.rb b/lib/api/helpers/packages/basic_auth_helpers.rb
index ebedb3b7563..a62bb1d4991 100644
--- a/lib/api/helpers/packages/basic_auth_helpers.rb
+++ b/lib/api/helpers/packages/basic_auth_helpers.rb
@@ -14,15 +14,27 @@ module API
include Constants
include Gitlab::Utils::StrongMemoize
- def authorized_user_project
- @authorized_user_project ||= authorized_project_find!
+ def authorized_user_project(action: :read_project)
+ strong_memoize("authorized_user_project_#{action}") do
+ authorized_project_find!(action: action)
+ end
end
- def authorized_project_find!
+ def authorized_project_find!(action: :read_project)
project = find_project(params[:id])
- unless project && can?(current_user, :read_project, project)
- return unauthorized_or! { not_found! }
+ return unauthorized_or! { not_found! } unless project
+
+ case action
+ when :read_package
+ unless can?(current_user, :read_package, project&.packages_policy_subject)
+ # guest users can have :read_project but not :read_package
+ return forbidden! if can?(current_user, :read_project, project)
+
+ return unauthorized_or! { not_found! }
+ end
+ else
+ return unauthorized_or! { not_found! } unless can?(current_user, action, project)
end
project
diff --git a/lib/api/helpers/packages/dependency_proxy_helpers.rb b/lib/api/helpers/packages/dependency_proxy_helpers.rb
index a09499e00d7..dc81e5e1b51 100644
--- a/lib/api/helpers/packages/dependency_proxy_helpers.rb
+++ b/lib/api/helpers/packages/dependency_proxy_helpers.rb
@@ -16,8 +16,8 @@ module API
maven: 'maven_package_requests_forwarding'
}.freeze
- def redirect_registry_request(forward_to_registry, package_type, options)
- if forward_to_registry && redirect_registry_request_available?(package_type) && maven_forwarding_ff_enabled?(package_type, options[:target])
+ def redirect_registry_request(forward_to_registry: false, package_type: nil, target: nil, **options)
+ if forward_to_registry && redirect_registry_request_available?(package_type, target) && maven_forwarding_ff_enabled?(package_type, target)
::Gitlab::Tracking.event(self.options[:for].name, "#{package_type}_request_forward")
redirect(registry_url(package_type, options))
else
@@ -40,15 +40,19 @@ module API
end
end
- def redirect_registry_request_available?(package_type)
+ def redirect_registry_request_available?(package_type, target)
application_setting_name = APPLICATION_SETTING_NAMES[package_type]
raise ArgumentError, "Can't find application setting for package_type #{package_type}" unless application_setting_name
- ::Gitlab::CurrentSettings
- .current_application_settings
- .attributes
- .fetch(application_setting_name, false)
+ if target.present? && Feature.enabled?(:cascade_package_forwarding_settings, target)
+ target.public_send(application_setting_name) # rubocop:disable GitlabSecurity/PublicSend
+ else
+ ::Gitlab::CurrentSettings
+ .current_application_settings
+ .attributes
+ .fetch(application_setting_name, false)
+ end
end
private
diff --git a/lib/api/helpers/personal_access_tokens_helpers.rb b/lib/api/helpers/personal_access_tokens_helpers.rb
index db28daa5396..4fd72d89f4c 100644
--- a/lib/api/helpers/personal_access_tokens_helpers.rb
+++ b/lib/api/helpers/personal_access_tokens_helpers.rb
@@ -4,11 +4,14 @@ module API
module Helpers
module PersonalAccessTokensHelpers
def finder_params(current_user)
- if current_user.can_admin_all_resources?
- { user: user(params[:user_id]) }
- else
- { user: current_user, impersonation: false }
- end
+ user_param =
+ if current_user.can_admin_all_resources?
+ { user: user(params[:user_id]) }
+ else
+ { user: current_user, impersonation: false }
+ end
+
+ declared(params, include_missing: false).merge(user_param)
end
def user(user_id)
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 7ca3f55b5a2..9839828a5b4 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -36,6 +36,7 @@ module API
optional :analytics_access_level, type: String, values: %w(disabled private enabled), desc: 'Analytics access level. One of `disabled`, `private` or `enabled`'
optional :container_registry_access_level, type: String, values: %w(disabled private enabled), desc: 'Controls visibility of the container registry. One of `disabled`, `private` or `enabled`. `private` will make the container registry accessible only to project members (reporter role and above). `enabled` will make the container registry accessible to everyone who has access to the project. `disabled` will disable the container registry'
optional :security_and_compliance_access_level, type: String, values: %w(disabled private enabled), desc: 'Security and compliance access level. One of `disabled`, `private` or `enabled`'
+ optional :releases_access_level, type: String, values: %w(disabled private enabled), desc: 'Releases access level. One of `disabled`, `private` or `enabled`'
optional :emails_disabled, type: Boolean, desc: 'Disable email notifications'
optional :show_default_award_emojis, type: Boolean, desc: 'Show default award emojis'
@@ -58,7 +59,7 @@ module API
optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all threads are resolved'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :topics instead'
optional :topics, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of topics for a project'
- optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for project'
+ optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for project', documentation: { type: 'file' }
optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
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'
@@ -72,7 +73,7 @@ module API
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature'
optional :squash_option, type: String, values: %w(never always default_on default_off), desc: 'Squash default for project. One of `never`, `always`, `default_on`, or `default_off`.'
- optional :mr_default_target_self, Boolean, desc: 'Merge requests of this forked project targets itself by default'
+ optional :mr_default_target_self, type: Boolean, desc: 'Merge requests of this forked project targets itself by default'
end
params :optional_project_params_ee do
@@ -179,6 +180,7 @@ module API
:keep_latest_artifact,
:mr_default_target_self,
:enforce_auth_checks_on_uploads,
+ :releases_access_level,
# TODO: remove in API v5, replaced by *_access_level
:issues_enabled,
diff --git a/lib/api/import_github.rb b/lib/api/import_github.rb
index 46ca8e4c428..493cc038f46 100644
--- a/lib/api/import_github.rb
+++ b/lib/api/import_github.rb
@@ -43,6 +43,7 @@ module API
optional :new_name, type: String, desc: 'New repo name'
requires :target_namespace, type: String, desc: 'Namespace to import repo into'
optional :github_hostname, type: String, desc: 'Custom GitHub enterprise hostname'
+ optional :optional_stages, type: Hash, desc: 'Optional stages of import to be performed'
end
post 'import/github' do
result = Import::GithubService.new(client, current_user, params).execute(access_params, provider)
@@ -54,5 +55,20 @@ module API
{ errors: result[:message] }
end
end
+
+ params do
+ requires :project_id, type: Integer, desc: 'ID of importing project to be canceled'
+ end
+ post 'import/github/cancel' do
+ project = Project.imported_from(provider.to_s).find(params[:project_id])
+ result = Import::Github::CancelProjectImportService.new(project, current_user).execute
+
+ if result[:status] == :success
+ status :ok
+ present ProjectSerializer.new.represent(project, serializer: :import)
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
end
end
diff --git a/lib/api/internal/pages.rb b/lib/api/internal/pages.rb
index 20ca7038471..6be2679af14 100644
--- a/lib/api/internal/pages.rb
+++ b/lib/api/internal/pages.rb
@@ -59,7 +59,8 @@ module API
# Gitlab::Pages::CacheControl
present_cached virtual_domain,
cache_context: nil,
- with: Entities::Internal::Pages::VirtualDomain
+ with: Entities::Internal::Pages::VirtualDomain,
+ expires_in: ::Gitlab::Pages::CacheControl::EXPIRE
else
present virtual_domain, with: Entities::Internal::Pages::VirtualDomain
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index b6ad34424a6..b8b4019765d 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -272,17 +272,21 @@ module API
begin
spam_params = ::Spam::SpamParams.new_from_request(request: request)
- issue = ::Issues::CreateService.new(project: user_project,
- current_user: current_user,
- params: issue_params,
- spam_params: spam_params).execute
+ result = ::Issues::CreateService.new(project: user_project,
+ current_user: current_user,
+ params: issue_params,
+ spam_params: spam_params).execute
+
+ if result.success?
+ present result[:issue], with: Entities::Issue, current_user: current_user, project: user_project
+ elsif result[:issue]
+ issue = result[:issue]
- if issue.valid?
- present issue, with: Entities::Issue, current_user: current_user, project: user_project
- else
with_captcha_check_rest_api(spammable: issue) do
render_validation_error!(issue)
end
+ else
+ render_api_error!(result.errors.join(', '), result.http_status || 422)
end
rescue ::ActiveRecord::RecordNotUnique
render_api_error!('Duplicated issue', 409)
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index a3a25ec1696..72313d6a588 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -125,7 +125,13 @@ module API
no_package_found = package_file ? false : true
- redirect_registry_request(no_package_found, :maven, path: params[:path], file_name: params[:file_name], target: params[:target]) do
+ redirect_registry_request(
+ forward_to_registry: no_package_found,
+ package_type: :maven,
+ target: params[:target],
+ path: params[:path],
+ file_name: params[:file_name]
+ ) do
not_found!('Package') if no_package_found
case format
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 1dc0e1f0d22..a0e7d0b10cd 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -218,6 +218,7 @@ module API
[
current_user&.cache_key,
mr.merge_status,
+ mr.labels.map(&:cache_key),
mr.merge_request_assignees.map(&:cache_key),
mr.merge_request_reviewers.map(&:cache_key)
].join(":")
@@ -560,7 +561,7 @@ module API
put ':id/merge_requests/:merge_request_iid/reset_approvals', feature_category: :code_review, urgency: :low do
merge_request = find_project_merge_request(params[:merge_request_iid])
- unauthorized! unless current_user.bot? && merge_request.can_be_approved_by?(current_user)
+ unauthorized! unless current_user.bot? && merge_request.eligible_for_approval_by?(current_user)
merge_request.approvals.delete_all
diff --git a/lib/api/metadata.rb b/lib/api/metadata.rb
index c4984f0e7f0..3e42ffe336a 100644
--- a/lib/api/metadata.rb
+++ b/lib/api/metadata.rb
@@ -25,15 +25,76 @@ module API
}
EOF
- desc 'Get the metadata information of the GitLab instance.' do
+ helpers do
+ def run_metadata_query
+ run_graphql!(
+ query: METADATA_QUERY,
+ context: { current_user: current_user },
+ transform: ->(result) { result.dig('data', 'metadata') }
+ )
+ end
+ end
+
+ desc 'Retrieve metadata information for this GitLab instance.' do
detail 'This feature was introduced in GitLab 15.2.'
+ success [
+ {
+ code: 200,
+ model: Entities::Metadata,
+ message: 'successful operation',
+ examples: {
+ successful_response: {
+ 'value' => {
+ version: "15.0-pre",
+ revision: "c401a659d0c",
+ kas: {
+ enabled: true,
+ externalUrl: "grpc://gitlab.example.com:8150",
+ version: "15.0.0"
+ }
+ }
+ }
+ }
+ }
+ ]
+ failure [{ code: 401, message: 'unauthorized operation' }]
+ tags %w[metadata]
end
get '/metadata' do
- run_graphql!(
- query: METADATA_QUERY,
- context: { current_user: current_user },
- transform: ->(result) { result.dig('data', 'metadata') }
- )
+ run_metadata_query
+ end
+
+ # Support the deprecated `/version` route.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/366287
+ desc 'Get the version information of the GitLab instance.' do
+ detail 'This feature was introduced in GitLab 8.13 and deprecated in 15.5. ' \
+ 'We recommend you instead use the Metadata API.'
+ success [
+ {
+ code: 200,
+ model: Entities::Metadata,
+ message: 'successful operation',
+ examples: {
+ 'Example' => {
+ 'value' => {
+ version: "15.0-pre",
+ revision: "c401a659d0c",
+ kas: {
+ enabled: true,
+ externalUrl: "grpc://gitlab.example.com:8150",
+ version: "15.0.0"
+ }
+ }
+ }
+ }
+ }
+ ]
+ failure [{ code: 401, message: 'unauthorized operation' }]
+ tags %w[metadata]
+ end
+
+ get '/version' do
+ run_metadata_query
end
end
end
diff --git a/lib/api/ml/mlflow.rb b/lib/api/ml/mlflow.rb
index 4f5bd42f8f9..2ffb04ebcbd 100644
--- a/lib/api/ml/mlflow.rb
+++ b/lib/api/ml/mlflow.rb
@@ -9,20 +9,28 @@ module API
include APIGuard
# The first part of the url is the namespace, the second part of the URL is what the MLFlow client calls
- MLFLOW_API_PREFIX = ':id/ml/mflow/api/2.0/mlflow/'
+ MLFLOW_API_PREFIX = ':id/ml/mlflow/api/2.0/mlflow/'
allow_access_with_scope :api
allow_access_with_scope :read_api, if: -> (request) { request.get? || request.head? }
+ feature_category :mlops
+
+ content_type :json, 'application/json'
+ default_format :json
+
before do
+ # MLFlow Client considers any status code different than 200 an error, even 201
+ status 200
+
authenticate!
+
not_found! unless Feature.enabled?(:ml_experiment_tracking, user_project)
end
- feature_category :mlops
-
- content_type :json, 'application/json'
- default_format :json
+ rescue_from ActiveRecord::ActiveRecordError do |e|
+ invalid_parameter!(e.message)
+ end
helpers do
def resource_not_found!
@@ -32,6 +40,34 @@ module API
def resource_already_exists!
render_structured_api_error!({ error_code: 'RESOURCE_ALREADY_EXISTS' }, 400)
end
+
+ def invalid_parameter!(message = nil)
+ render_structured_api_error!({ error_code: 'INVALID_PARAMETER_VALUE', message: message }, 400)
+ end
+
+ def experiment_repository
+ ::Ml::ExperimentTracking::ExperimentRepository.new(user_project, current_user)
+ end
+
+ def candidate_repository
+ ::Ml::ExperimentTracking::CandidateRepository.new(user_project, current_user)
+ end
+
+ def experiment
+ @experiment ||= find_experiment!(params[:experiment_id], params[:experiment_name])
+ end
+
+ def candidate
+ @candidate ||= find_candidate!(params[:run_id])
+ end
+
+ def find_experiment!(iid, name)
+ experiment_repository.by_iid_or_name(iid: iid, name: name) || resource_not_found!
+ end
+
+ def find_candidate!(iid)
+ candidate_repository.by_iid(iid) || resource_not_found!
+ end
end
params do
@@ -44,33 +80,35 @@ module API
namespace MLFLOW_API_PREFIX do
resource :experiments do
desc 'Fetch experiment by experiment_id' do
- success Entities::Ml::Mlflow::Experiment
+ success Entities::Ml::Mlflow::GetExperiment
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#get-experiment'
end
params do
optional :experiment_id, type: String, default: '', desc: 'Experiment ID, in reference to the project'
end
get 'get', urgency: :low do
- experiment = ::Ml::Experiment.by_project_id_and_iid(user_project.id, params[:experiment_id])
-
- resource_not_found! unless experiment
-
- present experiment, with: Entities::Ml::Mlflow::Experiment
+ present experiment, with: Entities::Ml::Mlflow::GetExperiment
end
desc 'Fetch experiment by experiment_name' do
- success Entities::Ml::Mlflow::Experiment
+ success Entities::Ml::Mlflow::GetExperiment
detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#get-experiment-by-name'
end
params do
optional :experiment_name, type: String, default: '', desc: 'Experiment name'
end
get 'get-by-name', urgency: :low do
- experiment = ::Ml::Experiment.by_project_id_and_name(user_project, params[:experiment_name])
+ present experiment, with: Entities::Ml::Mlflow::GetExperiment
+ end
- resource_not_found! unless experiment
+ desc 'List experiments' do
+ success Entities::Ml::Mlflow::ListExperiment
+ detail 'https://www.mlflow.org/docs/latest/rest-api.html#list-experiments'
+ end
+ get 'list', urgency: :low do
+ response = { experiments: experiment_repository.all }
- present experiment, with: Entities::Ml::Mlflow::Experiment
+ present response, with: Entities::Ml::Mlflow::ListExperiment
end
desc 'Create experiment' do
@@ -83,33 +121,13 @@ module API
optional :tags, type: Array, desc: 'This will be ignored'
end
post 'create', urgency: :low do
- resource_already_exists! if ::Ml::Experiment.has_record?(user_project.id, params[:name])
-
- experiment = ::Ml::Experiment.create!(name: params[:name],
- user: current_user,
- project: user_project)
-
- present experiment, with: Entities::Ml::Mlflow::NewExperiment
+ present experiment_repository.create!(params[:name]), with: Entities::Ml::Mlflow::NewExperiment
+ rescue ActiveRecord::RecordInvalid
+ resource_already_exists!
end
end
resource :runs do
- desc 'Gets an MLFlow Run, which maps to GitLab Candidates' do
- success Entities::Ml::Mlflow::Run
- detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#get-run'
- end
- params do
- optional :run_id, type: String, desc: 'UUID of the candidate.'
- optional :run_uuid, type: String, desc: 'This parameter is ignored'
- end
- get 'get', urgency: :low do
- candidate = ::Ml::Candidate.with_project_id_and_iid(user_project.id, params[:run_id])
-
- resource_not_found! unless candidate
-
- present candidate, with: Entities::Ml::Mlflow::Run
- end
-
desc 'Creates a Run.' do
success Entities::Ml::Mlflow::Run
detail ['https://www.mlflow.org/docs/1.28.0/rest-api.html#create-run',
@@ -125,16 +143,18 @@ module API
optional :tags, type: Array, desc: 'This will be ignored'
end
post 'create', urgency: :low do
- experiment = ::Ml::Experiment.by_project_id_and_iid(user_project.id, params[:experiment_id].to_i)
-
- resource_not_found! unless experiment
-
- candidate = ::Ml::Candidate.create!(
- experiment: experiment,
- user: current_user,
- start_time: params[:start_time] || 0
- )
+ present candidate_repository.create!(experiment, params[:start_time]), with: Entities::Ml::Mlflow::Run
+ end
+ desc 'Gets an MLFlow Run, which maps to GitLab Candidates' do
+ success Entities::Ml::Mlflow::Run
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#get-run'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the candidate.'
+ optional :run_uuid, type: String, desc: 'This parameter is ignored'
+ end
+ get 'get', urgency: :low do
present candidate, with: Entities::Ml::Mlflow::Run
end
@@ -144,7 +164,7 @@ module API
'MLFlow Runs map to GitLab Candidates']
end
params do
- optional :run_id, type: String, desc: 'UUID of the candidate.'
+ requires :run_id, type: String, desc: 'UUID of the candidate.'
optional :status, type: String,
values: ::Ml::Candidate.statuses.keys.map(&:upcase),
desc: "Status of the run. Accepts: " \
@@ -152,16 +172,79 @@ module API
optional :end_time, type: Integer, desc: 'Ending time of the run'
end
post 'update', urgency: :low do
- candidate = ::Ml::Candidate.with_project_id_and_iid(user_project.id, params[:run_id])
+ candidate_repository.update(candidate, params[:status], params[:end_time])
- resource_not_found! unless candidate
+ present candidate, with: Entities::Ml::Mlflow::UpdateRun
+ end
- candidate.status = params[:status].downcase if params[:status]
- candidate.end_time = params[:end_time] if params[:end_time]
+ desc 'Logs a metric to a run.' do
+ summary 'Log a metric for a run. A metric is a key-value pair (string key, float value) with an '\
+ 'associated timestamp. Examples include the various metrics that represent ML model accuracy. '\
+ 'A metric can be logged multiple times.'
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-metric'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the run.'
+ requires :key, type: String, desc: 'Name for the metric.'
+ requires :value, type: Float, desc: 'Value of the metric.'
+ requires :timestamp, type: Integer, desc: 'Unix timestamp in milliseconds when metric was recorded'
+ optional :step, type: Integer, desc: 'Step at which the metric was recorded'
+ end
+ post 'log-metric', urgency: :low do
+ candidate_repository.add_metric!(
+ candidate,
+ params[:key],
+ params[:value],
+ params[:timestamp],
+ params[:step]
+ )
+
+ {}
+ end
- candidate.save if candidate.valid?
+ desc 'Logs a parameter to a run.' do
+ summary 'Log a param used for a run. A param is a key-value pair (string key, string value). '\
+ 'Examples include hyperparameters used for ML model training and constant dates and values '\
+ 'used in an ETL pipeline. A param can be logged only once for a run, duplicate will be .'\
+ 'ignored'
- present candidate, with: Entities::Ml::Mlflow::UpdateRun
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the run.'
+ requires :key, type: String, desc: 'Name for the parameter.'
+ requires :value, type: String, desc: 'Value for the parameter.'
+ end
+ post 'log-parameter', urgency: :low do
+ bad_request! unless candidate_repository.add_param!(candidate, params[:key], params[:value])
+
+ {}
+ end
+
+ desc 'Logs multiple parameters and metrics.' do
+ summary 'Log a batch of metrics and params for a run. Validation errors will block the entire batch, '\
+ 'duplicate errors will be ignored.'
+
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the run.'
+ optional :metrics, type: Array, default: [] do
+ requires :key, type: String, desc: 'Name for the metric.'
+ requires :value, type: Float, desc: 'Value of the metric.'
+ requires :timestamp, type: Integer, desc: 'Unix timestamp in milliseconds when metric was recorded'
+ optional :step, type: Integer, desc: 'Step at which the metric was recorded'
+ end
+ optional :params, type: Array, default: [] do
+ requires :key, type: String, desc: 'Name for the metric.'
+ requires :value, type: String, desc: 'Value of the metric.'
+ end
+ end
+ post 'log-batch', urgency: :low do
+ candidate_repository.add_metrics(candidate, params[:metrics])
+ candidate_repository.add_params(candidate, params[:params])
+
+ {}
end
end
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 77c479c529a..8ce875cdc03 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -73,7 +73,7 @@ module API
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
requires :body, type: String, desc: 'The content of a note'
- optional :confidential, type: Boolean, desc: '[Deprecated in 15.3] Renamed to internal'
+ optional :confidential, type: Boolean, desc: '[Deprecated in 15.5] Renamed to internal'
optional :internal, type: Boolean, desc: 'Internal note flag, default is false'
optional :created_at, type: String, desc: 'The creation date of the note'
optional :merge_request_diff_head_sha, type: String, desc: 'The SHA of the head commit'
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 34d3a5150da..9cf61967ba4 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -106,7 +106,9 @@ module API
pages_domain_params = declared(params, include_parent_namespaces: false)
- pages_domain = user_project.pages_domains.create(pages_domain_params)
+ pages_domain = ::PagesDomains::CreateService
+ .new(user_project, current_user, pages_domain_params)
+ .execute
if pages_domain.persisted?
present pages_domain, with: Entities::PagesDomain
@@ -136,7 +138,9 @@ module API
pages_domain_params.delete(:user_provided_key)
end
- if pages_domain.update(pages_domain_params)
+ service = ::PagesDomains::UpdateService.new(user_project, current_user, pages_domain_params)
+
+ if service.execute(pages_domain)
present pages_domain, with: Entities::PagesDomain
else
render_validation_error!(pages_domain)
@@ -150,7 +154,9 @@ module API
delete ":id/pages/domains/:domain", requirements: PAGES_DOMAINS_ENDPOINT_REQUIREMENTS do
authorize! :update_pages, user_project
- pages_domain.destroy
+ ::PagesDomains::DeleteService
+ .new(user_project, current_user)
+ .execute(pages_domain)
no_content!
end
diff --git a/lib/api/personal_access_tokens.rb b/lib/api/personal_access_tokens.rb
index 1c00569bba2..a2903faa4ad 100644
--- a/lib/api/personal_access_tokens.rb
+++ b/lib/api/personal_access_tokens.rb
@@ -11,7 +11,15 @@ module API
success Entities::PersonalAccessToken
end
params do
- optional :user_id, type: Integer, desc: 'User ID'
+ optional :user_id, type: Integer, desc: 'Filter PATs by User ID'
+ optional :revoked, type: Boolean, desc: 'Filter PATs where revoked state matches parameter'
+ optional :state, type: String, desc: 'Filter PATs which are either active or not',
+ values: %w[active inactive]
+ optional :created_before, type: DateTime, desc: 'Filter PATs which were created before given datetime'
+ optional :created_after, type: DateTime, desc: 'Filter PATs which were created after given datetime'
+ optional :last_used_before, type: DateTime, desc: 'Filter PATs which were used before given datetime'
+ optional :last_used_after, type: DateTime, desc: 'Filter PATs which were used after given datetime'
+ optional :search, type: String, desc: 'Filters PATs by its name'
use :pagination
end
diff --git a/lib/api/personal_access_tokens/self_information.rb b/lib/api/personal_access_tokens/self_information.rb
new file mode 100644
index 00000000000..89850614f94
--- /dev/null
+++ b/lib/api/personal_access_tokens/self_information.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module API
+ class PersonalAccessTokens
+ class SelfInformation < ::API::Base
+ include APIGuard
+
+ feature_category :authentication_and_authorization
+
+ helpers ::API::Helpers::PersonalAccessTokensHelpers
+
+ # As any token regardless of `scope` should be able to view/revoke itself
+ # all available scopes are allowed for this API class.
+ # Please be aware of the permissive scope when adding new endpoints to this class.
+ allow_access_with_scope(Gitlab::Auth.all_available_scopes)
+
+ before { authenticate! }
+
+ resource :personal_access_tokens do
+ get 'self' do
+ present access_token, with: Entities::PersonalAccessToken
+ end
+
+ delete 'self' do
+ revoke_token(access_token)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/personal_access_tokens/self_revocation.rb b/lib/api/personal_access_tokens/self_revocation.rb
deleted file mode 100644
index 22e07f4cc7b..00000000000
--- a/lib/api/personal_access_tokens/self_revocation.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module API
- class PersonalAccessTokens
- class SelfRevocation < ::API::Base
- include APIGuard
-
- feature_category :authentication_and_authorization
-
- helpers ::API::Helpers::PersonalAccessTokensHelpers
-
- # As any token regardless of `scope` should be able to revoke itself
- # all availabe scopes are allowed for this API class.
- # Please be aware of the permissive scope when adding new endpoints to this class.
- allow_access_with_scope(Gitlab::Auth.all_available_scopes)
-
- before { authenticate! }
-
- resource :personal_access_tokens do
- delete 'self' do
- revoke_token(access_token)
- end
- end
- end
- end
-end
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index d610b5e4f95..29fdfe45566 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -46,7 +46,8 @@ module API
optional :description, type: String, desc: 'Override the project description'
optional :upload, type: Hash do
optional :url, type: String, desc: 'The URL to upload the project'
- optional :http_method, type: String, default: 'PUT', desc: 'HTTP method to upload the exported project'
+ optional :http_method, type: String, default: 'PUT', values: %w[PUT POST],
+ desc: 'HTTP method to upload the exported project'
end
end
post ':id/export' do
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 7a66044c5b6..0da8c1ecedd 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -55,7 +55,7 @@ module API
params do
requires :path, type: String, desc: 'The new project path and name'
- requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The project export file to be imported'
+ requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The project export file to be imported', documentation: { type: 'file' }
optional :name, type: String, desc: 'The name of the project to be imported. Defaults to the path of the project if not provided.'
optional :namespace, type: String, desc: "The ID or name of the namespace that the project will be imported into. Defaults to the current user's namespace."
optional :overwrite, type: Boolean, default: false, desc: 'If there is a project in the same namespace and with the same name overwrite it'
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 8c58cc585d8..bb97f4fa7ce 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -375,7 +375,7 @@ module API
optional :name, type: String, desc: 'The name that will be assigned to the fork'
optional :description, type: String, desc: 'The description that will be assigned to the fork'
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the fork'
- optional :mr_default_target_self, Boolean, desc: 'Merge requests of this forked project targets itself by default'
+ optional :mr_default_target_self, type: Boolean, desc: 'Merge requests of this forked project targets itself by default'
end
post ':id/fork', feature_category: :source_code_management do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20759')
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index ae583ca968a..1f27fcce879 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -56,7 +56,12 @@ module API
packages = Packages::Pypi::PackagesFinder.new(current_user, group_or_project, { package_name: params[:package_name] }).execute
empty_packages = packages.empty?
- redirect_registry_request(empty_packages, :pypi, package_name: params[:package_name]) do
+ redirect_registry_request(
+ forward_to_registry: empty_packages,
+ package_type: :pypi,
+ target: group_or_project,
+ package_name: params[:package_name]
+ ) do
not_found!('Package') if empty_packages
presenter = ::Packages::Pypi::SimplePackageVersionsPresenter.new(packages, group_or_project)
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 44bb4228786..ff17696ed3e 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -63,7 +63,7 @@ module API
@results = search_service(additional_params).search_objects(preload_method)
end
- set_global_search_log_information
+ set_global_search_log_information(additional_params)
Gitlab::Metrics::GlobalSearchSlis.record_apdex(
elapsed: @search_duration_s,
@@ -105,7 +105,7 @@ module API
# EE, without having to modify this file directly.
end
- def search_type
+ def search_type(additional_params = {})
'basic'
end
@@ -113,10 +113,10 @@ module API
params[:scope]
end
- def set_global_search_log_information
+ def set_global_search_log_information(additional_params)
Gitlab::Instrumentation::GlobalSearchApi.set_information(
- type: search_type,
- level: search_service.level,
+ type: search_type(additional_params),
+ level: search_service(additional_params).level,
scope: search_scope,
search_duration_s: @search_duration_s
)
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index f393f862f55..8c8b6c0a1ba 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -132,7 +132,7 @@ module API
requires :recaptcha_private_key, type: String, desc: 'Generate private key at http://www.google.com/recaptcha'
end
optional :repository_checks_enabled, type: Boolean, desc: "GitLab will periodically run 'git fsck' in all project and wiki repositories to look for silent disk corruption issues."
- optional :repository_storages_weighted, type: Hash, coerce_with: Validations::Types::HashOfIntegerValues.coerce, desc: 'Storage paths for new projects with a weighted value ranging from 0 to 100'
+ optional :repository_storages_weighted, type: Hash, coerce_with: Validations::Types::HashOfIntegerValues.coerce, desc: 'Storage paths for new projects with a weighted value ranging from 0 to 100', documentation: { type: 'Object', additional_properties: Integer }
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to set up Two-factor authentication'
given require_two_factor_authentication: ->(val) { val } do
requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication'
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 4e70ebddf94..5f8e6c806cb 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -6,6 +6,7 @@ module API
include PaginationParams
feature_category :snippets
+ urgency :low
resource :snippets do
helpers Helpers::SnippetsHelpers
@@ -51,7 +52,7 @@ module API
use :pagination
end
- get 'public', urgency: :low do
+ get 'public' do
authenticate!
filter_params = declared_params(include_missing: false).merge(only_personal: true)
@@ -192,7 +193,7 @@ module API
params do
use :raw_file_params
end
- get ":id/files/:ref/:file_path/raw", urgency: :low, requirements: { file_path: API::NO_SLASH_URL_PART_REGEX } do
+ get ":id/files/:ref/:file_path/raw", requirements: { file_path: API::NO_SLASH_URL_PART_REGEX } do
snippet = snippets.find_by_id(params.delete(:id))
not_found!('Snippet') unless snippet&.repo_exists?
diff --git a/lib/api/support/git_access_actor.rb b/lib/api/support/git_access_actor.rb
index f450630afdd..16861a146ae 100644
--- a/lib/api/support/git_access_actor.rb
+++ b/lib/api/support/git_access_actor.rb
@@ -57,3 +57,5 @@ module API
end
end
end
+
+API::Support::GitAccessActor.prepend_mod_with('API::Support::GitAccessActor')
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index 85a299c5673..a80ef514943 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -7,15 +7,18 @@ module API
GLOBAL_TEMPLATE_TYPES = {
gitignores: {
gitlab_version: 8.8,
- feature_category: :source_code_management
+ feature_category: :source_code_management,
+ file_type: '.gitignore'
},
gitlab_ci_ymls: {
gitlab_version: 8.9,
- feature_category: :pipeline_authoring
+ feature_category: :pipeline_authoring,
+ file_type: 'GitLab CI/CD YAML'
},
dockerfiles: {
gitlab_version: 8.15,
- feature_category: :source_code_management
+ feature_category: :source_code_management,
+ file_type: 'Dockerfile'
}
}.freeze
@@ -26,7 +29,7 @@ module API
end
end
- desc 'Get the list of the available license template' do
+ desc 'Get all license templates' do
detail 'This feature was introduced in GitLab 8.7.'
success ::API::Entities::License
end
@@ -43,12 +46,14 @@ module API
present paginate(::Kaminari.paginate_array(templates)), with: ::API::Entities::License
end
- desc 'Get the text for a specific license' do
+ desc 'Get a single license template' do
detail 'This feature was introduced in GitLab 8.7.'
success ::API::Entities::License
end
params do
- requires :name, type: String, desc: 'The name of the template'
+ requires :name, type: String, desc: 'The name of the license template'
+ optional :project, type: String, desc: 'The copyrighted project name'
+ optional :fullname, type: String, desc: 'The full-name of the copyright holder'
end
get "templates/licenses/:name", requirements: { name: /[\w\.-]+/ }, feature_category: :source_code_management do
template = TemplateFinder.build(:licenses, nil, name: params[:name]).execute
@@ -65,8 +70,9 @@ module API
GLOBAL_TEMPLATE_TYPES.each do |template_type, properties|
gitlab_version = properties[:gitlab_version]
+ file_type = properties[:file_type]
- desc 'Get the list of the available template' do
+ desc "Get all #{file_type} templates" do
detail "This feature was introduced in GitLab #{gitlab_version}."
success Entities::TemplatesList
end
@@ -78,12 +84,12 @@ module API
present paginate(templates), with: Entities::TemplatesList
end
- desc 'Get the text for a specific template present in local filesystem' do
+ desc "Get a single #{file_type} template" do
detail "This feature was introduced in GitLab #{gitlab_version}."
success Entities::Template
end
params do
- requires :name, type: String, desc: 'The name of the template'
+ requires :name, type: String, desc: "The name of the #{file_type} template"
end
get "templates/#{template_type}/:name", requirements: { name: /[\w\.-]+/ }, feature_category: properties[:feature_category] do
finder = TemplateFinder.build(template_type, nil, name: declared(params)[:name])
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index f1779df7cc6..57745ee8802 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -15,17 +15,17 @@ module API
}.freeze
params do
- requires :id, type: String, desc: 'The ID of a project'
+ requires :id, type: String, desc: 'The ID or URL-encoded path of the project owned by the authenticated user'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
ISSUABLE_TYPES.each do |type, finder|
type_id_str = "#{type.singularize}_iid".to_sym
- desc 'Create a todo on an issuable' do
+ desc 'Create a to-do item on an issuable' do
success Entities::Todo
end
params do
- requires type_id_str, type: Integer, desc: 'The IID of an issuable'
+ requires type_id_str, type: Integer, desc: 'The internal ID of an issuable'
end
post ":id/#{type}/:#{type_id_str}/todo" do
issuable = instance_exec(params[type_id_str], &finder)
@@ -44,12 +44,12 @@ module API
resource :todos do
helpers do
params :todo_filters do
- optional :action, String, values: Todo::ACTION_NAMES.values.map(&:to_s)
- optional :author_id, Integer
- optional :state, String, values: Todo.state_machine.states.map(&:name).map(&:to_s)
- optional :type, String, values: TodosFinder.todo_types
- optional :project_id, Integer
- optional :group_id, Integer
+ optional :action, type: String, values: Todo::ACTION_NAMES.values.map(&:to_s), desc: 'The action to be filtered'
+ optional :author_id, type: Integer, desc: 'The ID of an author'
+ optional :project_id, type: Integer, desc: 'The ID of a project'
+ optional :group_id, type: Integer, desc: 'The ID of a group'
+ optional :state, type: String, values: Todo.state_machine.states.map(&:name).map(&:to_s), desc: 'The state of the to-do item'
+ optional :type, type: String, values: TodosFinder.todo_types.map(&:to_s), desc: 'The type of to-do item'
end
def find_todos
@@ -81,7 +81,7 @@ module API
end
end
- desc 'Get a todo list' do
+ desc 'Get a list of to-do items' do
success Entities::Todo
end
params do
@@ -96,11 +96,11 @@ module API
present todos, options
end
- desc 'Mark a todo as done' do
+ desc 'Mark a to-do item as done' do
success Entities::Todo
end
params do
- requires :id, type: Integer, desc: 'The ID of the todo being marked as done'
+ requires :id, type: Integer, desc: 'The ID of to-do item'
end
post ':id/mark_as_done' do
todo = current_user.todos.find(params[:id])
@@ -110,7 +110,7 @@ module API
present todo, with: Entities::Todo, current_user: current_user
end
- desc 'Mark all todos as done'
+ desc 'Mark all to-do items as done'
post '/mark_as_done' do
todos = find_todos
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 1d1c633824e..7f44e46f1ca 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -50,11 +50,13 @@ module API
optional :provider, type: String, desc: 'The external provider'
optional :bio, type: String, desc: 'The biography of the user'
optional :location, type: String, desc: 'The location of the user'
+ optional :pronouns, type: String, desc: 'The pronouns of the user'
optional :public_email, type: String, desc: 'The public email of the user'
+ optional :commit_email, type: String, desc: 'The commit email, _private for private commit email'
optional :admin, type: Boolean, desc: 'Flag indicating the user is an administrator'
optional :can_create_group, type: Boolean, desc: 'Flag indicating the user can create groups'
optional :external, type: Boolean, desc: 'Flag indicating the user is an external user'
- optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for user'
+ optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for user', documentation: { type: 'file' }
optional :theme_id, type: Integer, desc: 'The GitLab theme for the user'
optional :color_scheme_id, type: Integer, desc: 'The color scheme for the file viewer'
optional :private_profile, type: Boolean, desc: 'Flag indicating the user has a private profile'
@@ -187,7 +189,10 @@ module API
user = find_user(params[:id])
not_found!('User') unless user
- if current_user.follow(user)
+ followee = current_user.follow(user)
+ if followee&.errors&.any?
+ render_api_error!(followee.errors.full_messages.join(', '), 400)
+ elsif followee&.persisted?
present user, with: Entities::UserBasic
else
not_modified!
@@ -885,7 +890,7 @@ module API
params do
requires :name, type: String, desc: 'The name of the impersonation token'
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the impersonation token'
- optional :scopes, type: Array, desc: 'The array of scopes of the impersonation token'
+ optional :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The array of scopes of the impersonation token'
end
post feature_category: :authentication_and_authorization do
impersonation_token = finder.build(declared_params(include_missing: false))
diff --git a/lib/api/version.rb b/lib/api/version.rb
deleted file mode 100644
index bdce88ab827..00000000000
--- a/lib/api/version.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module API
- class Version < ::API::Base
- helpers ::API::Helpers::GraphqlHelpers
- include APIGuard
-
- allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
-
- before { authenticate! }
-
- feature_category :not_owned # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned
-
- METADATA_QUERY = <<~EOF
- {
- metadata {
- version
- revision
- }
- }
- EOF
-
- desc 'Get the version information of the GitLab instance.' do
- detail 'This feature was introduced in GitLab 8.13.'
- end
- get '/version' do
- run_graphql!(
- query: METADATA_QUERY,
- context: { current_user: current_user },
- transform: ->(result) { result.dig('data', 'metadata') }
- )
- end
- end
-end
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 082be1f7e11..bb8ad5c4285 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -133,7 +133,7 @@ module API
success Entities::WikiAttachment
end
params do
- requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded'
+ requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded', documentation: { type: 'file' }
optional :branch, type: String, desc: 'The name of the branch'
end
post ":id/wikis/attachments" do
diff --git a/lib/banzai/filter/markdown_engines/common_mark.rb b/lib/banzai/filter/markdown_engines/common_mark.rb
index cf368e28beb..7abfadc612b 100644
--- a/lib/banzai/filter/markdown_engines/common_mark.rb
+++ b/lib/banzai/filter/markdown_engines/common_mark.rb
@@ -56,3 +56,5 @@ module Banzai
end
end
end
+
+Banzai::Filter::MarkdownEngines::CommonMark.prepend_mod
diff --git a/lib/banzai/filter/pathological_markdown_filter.rb b/lib/banzai/filter/pathological_markdown_filter.rb
deleted file mode 100644
index 0f94150c7a1..00000000000
--- a/lib/banzai/filter/pathological_markdown_filter.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- class PathologicalMarkdownFilter < HTML::Pipeline::TextFilter
- # It's not necessary for this to be precise - we just need to detect
- # when there are a non-trivial number of unclosed image links.
- # So we don't really care about code blocks, etc.
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/370428
- REGEX = /!\[(?:[^\]])+?!\[/.freeze
- DETECTION_MAX = 10
-
- def call
- count = 0
-
- @text.scan(REGEX) do |_match|
- count += 1
- break if count > DETECTION_MAX
- end
-
- return @text if count <= DETECTION_MAX
-
- "_Unable to render markdown - too many unclosed markdown image links detected._"
- end
- end
- end
-end
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index 179afd840a5..1c794a81d9d 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'cgi/util'
+
# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
module Banzai
module Filter
@@ -93,7 +95,7 @@ module Banzai
def text
return '' unless node
- @text ||= EscapeUtils.escape_html(node.text)
+ @text ||= CGI.escapeHTML(node.text)
end
private
diff --git a/lib/banzai/filter/truncate_visible_filter.rb b/lib/banzai/filter/truncate_visible_filter.rb
new file mode 100644
index 00000000000..edd6efd4706
--- /dev/null
+++ b/lib/banzai/filter/truncate_visible_filter.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class TruncateVisibleFilter < HTML::Pipeline::Filter
+ # Truncates the document to `truncate_visible_max_chars` characters,
+ # excluding any HTML tags.
+
+ MATCH_CODE = 'pre > code > .line'
+
+ def call
+ return doc unless context[:truncate_visible_max_chars].present?
+
+ max_chars = context[:truncate_visible_max_chars]
+ content_length = 0
+ @truncated = false
+
+ doc.traverse do |node|
+ if node.text? || node.content.empty?
+ if truncated
+ node.remove
+ next
+ end
+
+ handle_line_breaks(node)
+ truncate_content(content_length, max_chars, node)
+
+ content_length += node.content.length
+ end
+
+ truncate_if_block(node)
+ end
+
+ doc
+ end
+
+ private
+
+ attr_reader :truncated
+
+ def truncate_content(content_length, max_chars, node)
+ num_remaining = max_chars - content_length
+ return unless node.content.length > num_remaining
+
+ node.content = node.content.truncate(num_remaining)
+ @truncated = true
+ end
+
+ # Handle line breaks within a node
+ def handle_line_breaks(node)
+ return unless node.content.strip.lines.length > 1
+
+ node.content = "#{node.content.lines.first.chomp}..."
+ @truncated = true
+ end
+
+ # If `node` is the first block element, and the
+ # text hasn't already been truncated, then append "..." to the node contents
+ # and return true. Otherwise return false.
+ def truncate_if_block(node)
+ return if truncated
+ return unless node.element? && (node.description&.block? || node.matches?(MATCH_CODE))
+
+ node.inner_html = "#{node.inner_html}..." if node.next_sibling
+ @truncated = true
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index b4c2e7efae3..455cac98841 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -42,7 +42,7 @@ module Banzai
def apply_relative_link_rules!
if @uri.relative? && @uri.path.present?
link = @uri.path
- link = ::File.join(@wiki_base_path, link) unless link.starts_with?(@wiki_base_path)
+ link = ::File.join(@wiki_base_path, link) unless prefixed_with_base_path?(link)
link = "#{link}##{@uri.fragment}" if @uri.fragment
@uri = Addressable::URI.parse(link)
end
@@ -55,6 +55,15 @@ module Banzai
def repository_upload?
@uri.relative? && @uri.path.starts_with?(Wikis::CreateAttachmentService::ATTACHMENT_PATH)
end
+
+ def prefixed_with_base_path?(link)
+ link.starts_with?(@wiki_base_path) || link.starts_with?(old_wiki_base_path)
+ end
+
+ # before we added `/-/` to all our paths
+ def old_wiki_base_path
+ @wiki_base_path.sub('/-/', '/')
+ end
end
end
end
diff --git a/lib/banzai/pipeline/ascii_doc_pipeline.rb b/lib/banzai/pipeline/ascii_doc_pipeline.rb
index 90edc7010f4..b652d8d89cf 100644
--- a/lib/banzai/pipeline/ascii_doc_pipeline.rb
+++ b/lib/banzai/pipeline/ascii_doc_pipeline.rb
@@ -13,6 +13,7 @@ module Banzai
Filter::ColorFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
+ Filter::WikiLinkFilter,
Filter::AsciiDocPostProcessingFilter
]
end
diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb
index fb6f6e9077d..1da0f72996b 100644
--- a/lib/banzai/pipeline/plain_markdown_pipeline.rb
+++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb
@@ -5,7 +5,6 @@ module Banzai
class PlainMarkdownPipeline < BasePipeline
def self.filters
FilterArray[
- Filter::PathologicalMarkdownFilter,
Filter::MarkdownPreEscapeFilter,
Filter::MarkdownFilter,
Filter::MarkdownPostEscapeFilter
diff --git a/lib/banzai/pipeline/post_process_pipeline.rb b/lib/banzai/pipeline/post_process_pipeline.rb
index da2262cdf83..f8035698b9b 100644
--- a/lib/banzai/pipeline/post_process_pipeline.rb
+++ b/lib/banzai/pipeline/post_process_pipeline.rb
@@ -5,6 +5,7 @@ module Banzai
class PostProcessPipeline < BasePipeline
def self.filters
@filters ||= FilterArray[
+ Filter::TruncateVisibleFilter,
*internal_link_filters,
Filter::AbsoluteLinkFilter,
Filter::BroadcastMessagePlaceholdersFilter
diff --git a/lib/bitbucket/client.rb b/lib/bitbucket/client.rb
index 92894575ec2..887f13b0358 100644
--- a/lib/bitbucket/client.rb
+++ b/lib/bitbucket/client.rb
@@ -8,6 +8,11 @@ module Bitbucket
@connection = Connection.new(options)
end
+ def last_issue(repo)
+ parsed_response = connection.get("/repositories/#{repo}/issues?pagelen=1&sort=-created_on&state=ALL")
+ Bitbucket::Representation::Issue.new(parsed_response['values'].first)
+ end
+
def issues(repo)
path = "/repositories/#{repo}/issues"
get_collection(path, :issue)
diff --git a/lib/bulk_imports/common/pipelines/entity_finisher.rb b/lib/bulk_imports/common/pipelines/entity_finisher.rb
index 915dcf1b455..5066f622d57 100644
--- a/lib/bulk_imports/common/pipelines/entity_finisher.rb
+++ b/lib/bulk_imports/common/pipelines/entity_finisher.rb
@@ -24,11 +24,12 @@ module BulkImports
end
logger.info(
- bulk_import_id: context.bulk_import.id,
+ bulk_import_id: context.bulk_import_id,
bulk_import_entity_id: context.entity.id,
bulk_import_entity_type: context.entity.source_type,
pipeline_class: self.class.name,
- message: "Entity #{entity.status_name}"
+ message: "Entity #{entity.status_name}",
+ importer: 'gitlab_migration'
)
context.portable.try(:after_import)
diff --git a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
index 0f92c1f1210..fea550b9f9d 100644
--- a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
+++ b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
@@ -44,6 +44,11 @@ module BulkImports
wikis = client.get(context.entity.wikis_url_path).parsed_response
wikis.any?
+ rescue BulkImports::NetworkError => e
+ # 403 is returned when wiki is disabled in settings
+ return if e.response&.forbidden? || e.response&.not_found?
+
+ raise
end
def client
diff --git a/lib/bulk_imports/common/rest/get_badges_query.rb b/lib/bulk_imports/common/rest/get_badges_query.rb
index 60b2ebcc552..6e7cb7504ba 100644
--- a/lib/bulk_imports/common/rest/get_badges_query.rb
+++ b/lib/bulk_imports/common/rest/get_badges_query.rb
@@ -7,11 +7,8 @@ module BulkImports
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('/'),
+ resource: [context.entity.base_resource_path, 'badges'].join('/'),
query: {
page: context.tracker.next_page
}
diff --git a/lib/bulk_imports/features.rb b/lib/bulk_imports/features.rb
new file mode 100644
index 00000000000..952e8e62d71
--- /dev/null
+++ b/lib/bulk_imports/features.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Features
+ def self.enabled?
+ ::Feature.enabled?(:bulk_import)
+ end
+
+ def self.project_migration_enabled?(destination_namespace = nil)
+ if destination_namespace.present?
+ root_ancestor = Namespace.find_by_full_path(destination_namespace)&.root_ancestor
+
+ ::Feature.enabled?(:bulk_import_projects, root_ancestor)
+ else
+ ::Feature.enabled?(:bulk_import_projects)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
index 1140beef48c..029b6f0f729 100644
--- a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
+++ b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
@@ -5,10 +5,8 @@ module BulkImports
module Extractors
class SubgroupsExtractor
def extract(context)
- encoded_parent_path = ERB::Util.url_encode(context.entity.source_full_path)
-
response = http_client(context.configuration)
- .each_page(:get, "groups/#{encoded_parent_path}/subgroups")
+ .each_page(:get, "#{context.entity.base_resource_path}/subgroups")
.flat_map(&:itself)
BulkImports::Pipeline::ExtractedData.new(data: response)
diff --git a/lib/bulk_imports/groups/graphql/get_group_query.rb b/lib/bulk_imports/groups/graphql/get_group_query.rb
index 911b2b67d8c..0e73a7fb4b9 100644
--- a/lib/bulk_imports/groups/graphql/get_group_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_group_query.rb
@@ -14,9 +14,9 @@ module BulkImports
<<-'GRAPHQL'
query($full_path: ID!) {
group(fullPath: $full_path) {
+ id
name
path
- full_path: fullPath
description
visibility
emails_disabled: emailsDisabled
diff --git a/lib/bulk_imports/groups/graphql/get_projects_query.rb b/lib/bulk_imports/groups/graphql/get_projects_query.rb
index 3f74bbb8cce..4784baf225c 100644
--- a/lib/bulk_imports/groups/graphql/get_projects_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_projects_query.rb
@@ -20,6 +20,7 @@ module BulkImports
has_next_page: hasNextPage
}
nodes {
+ id
name
full_path: fullPath
}
diff --git a/lib/bulk_imports/groups/pipelines/project_entities_pipeline.rb b/lib/bulk_imports/groups/pipelines/project_entities_pipeline.rb
index c318675e649..026b2e55713 100644
--- a/lib/bulk_imports/groups/pipelines/project_entities_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/project_entities_pipeline.rb
@@ -15,7 +15,8 @@ module BulkImports
source_full_path: data['full_path'],
destination_name: data['name'],
destination_namespace: context.entity.group.full_path,
- parent_id: context.entity.id
+ parent_id: context.entity.id,
+ source_xid: GlobalID.parse(data['id']).model_id
}
end
diff --git a/lib/bulk_imports/groups/stage.rb b/lib/bulk_imports/groups/stage.rb
index 0378a9c605d..6928ce43191 100644
--- a/lib/bulk_imports/groups/stage.rb
+++ b/lib/bulk_imports/groups/stage.rb
@@ -90,13 +90,7 @@ module BulkImports
def feature_flag_enabled?
destination_namespace = @bulk_import_entity.destination_namespace
- if destination_namespace.present?
- root_ancestor = Namespace.find_by_full_path(destination_namespace)&.root_ancestor
-
- ::Feature.enabled?(:bulk_import_projects, root_ancestor)
- else
- ::Feature.enabled?(:bulk_import_projects)
- end
+ BulkImports::Features.project_migration_enabled?(destination_namespace)
end
end
end
diff --git a/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
index d9efcdb1ba5..83b442458dc 100644
--- a/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
+++ b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
@@ -4,6 +4,7 @@ module BulkImports
module Groups
module Transformers
class GroupAttributesTransformer
+ # rubocop: disable Style/IfUnlessModifier
def transform(context, data)
import_entity = context.entity
@@ -11,74 +12,64 @@ module BulkImports
namespace = Namespace.find_by_full_path(import_entity.destination_namespace)
end
- data
- .then { |data| transform_name(import_entity, namespace, data) }
- .then { |data| transform_path(import_entity, data) }
- .then { |data| transform_full_path(data) }
- .then { |data| transform_parent(context, import_entity, namespace, data) }
- .then { |data| transform_visibility_level(data) }
- .then { |data| transform_project_creation_level(data) }
- .then { |data| transform_subgroup_creation_level(data) }
- end
-
- private
+ params = {
+ 'name' => group_name(namespace, data),
+ 'path' => import_entity.destination_slug.parameterize,
+ 'description' => data['description'],
+ 'lfs_enabled' => data['lfs_enabled'],
+ 'emails_disabled' => data['emails_disabled'],
+ 'mentions_disabled' => data['mentions_disabled'],
+ 'share_with_group_lock' => data['share_with_group_lock']
+ }
- def transform_name(import_entity, namespace, data)
if namespace.present?
- namespace_children_names = namespace.children.pluck(:name) # rubocop: disable CodeReuse/ActiveRecord
-
- if namespace_children_names.include?(data['name'])
- data['name'] = Uniquify.new(1).string(-> (counter) { "#{data['name']}(#{counter})" }) do |base|
- namespace_children_names.include?(base)
- end
- end
+ params['parent_id'] = namespace.id
end
- data
- end
-
- def transform_path(import_entity, data)
- data['path'] = import_entity.destination_slug.parameterize
- data
- end
+ if data.has_key?('two_factor_grace_period')
+ params['two_factor_grace_period'] = data['two_factor_grace_period']
+ end
- def transform_full_path(data)
- data.delete('full_path')
- data
- end
+ if data.has_key?('request_access_enabled')
+ params['request_access_enabled'] = data['request_access_enabled']
+ end
- def transform_parent(context, import_entity, namespace, data)
- data['parent_id'] = namespace.id if namespace.present?
+ if data.has_key?('require_two_factor_authentication')
+ params['require_two_factor_authentication'] = data['require_two_factor_authentication']
+ end
- data
- end
+ if data.has_key?('project_creation_level')
+ params['project_creation_level'] =
+ Gitlab::Access.project_creation_string_options[data['project_creation_level']]
+ end
- def transform_visibility_level(data)
- visibility = data['visibility']
+ if data.has_key?('subgroup_creation_level')
+ params['subgroup_creation_level'] =
+ Gitlab::Access.subgroup_creation_string_options[data['subgroup_creation_level']]
+ end
- return data unless visibility.present?
+ if data.has_key?('visibility')
+ params['visibility_level'] = Gitlab::VisibilityLevel.string_options[data['visibility']]
+ end
- data['visibility_level'] = Gitlab::VisibilityLevel.string_options[visibility]
- data.delete('visibility')
- data
+ params
end
+ # rubocop: enable Style/IfUnlessModifier
- def transform_project_creation_level(data)
- project_creation_level = data['project_creation_level']
-
- return data unless project_creation_level.present?
-
- data['project_creation_level'] = Gitlab::Access.project_creation_string_options[project_creation_level]
- data
- end
+ private
- def transform_subgroup_creation_level(data)
- subgroup_creation_level = data['subgroup_creation_level']
+ def group_name(namespace, data)
+ if namespace.present?
+ namespace_children_names = namespace.children.pluck(:name) # rubocop: disable CodeReuse/ActiveRecord
- return data unless subgroup_creation_level.present?
+ if namespace_children_names.include?(data['name'])
+ data['name'] = Uniquify.new(1).string(-> (counter) { "#{data['name']}(#{counter})" }) do |base|
+ namespace_children_names.include?(base)
+ end
+ end
+ end
- data['subgroup_creation_level'] = Gitlab::Access.subgroup_creation_string_options[subgroup_creation_level]
- data
+ data['name']
end
end
end
diff --git a/lib/bulk_imports/network_error.rb b/lib/bulk_imports/network_error.rb
index 3514291a75d..fda4bb74a30 100644
--- a/lib/bulk_imports/network_error.rb
+++ b/lib/bulk_imports/network_error.rb
@@ -2,15 +2,21 @@
module BulkImports
class NetworkError < Error
- COUNTER_KEY = 'bulk_imports/%{entity_id}/%{stage}/%{tracker_id}/network_error/%{error}'
+ TRACKER_COUNTER_KEY = 'bulk_imports/%{entity_id}/%{stage}/%{tracker_id}/network_error/%{error}'
+ ENTITY_COUNTER_KEY = 'bulk_imports/%{entity_id}/network_error/%{error}'
- RETRIABLE_EXCEPTIONS = Gitlab::HTTP::HTTP_TIMEOUT_ERRORS
+ RETRIABLE_EXCEPTIONS = Gitlab::HTTP::HTTP_TIMEOUT_ERRORS + [
+ EOFError, SocketError, OpenSSL::SSL::SSLError, OpenSSL::OpenSSLError,
+ Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH
+ ].freeze
RETRIABLE_HTTP_CODES = [429].freeze
DEFAULT_RETRY_DELAY_SECONDS = 30
MAX_RETRIABLE_COUNT = 10
+ attr_reader :response
+
def initialize(message = nil, response: nil)
raise ArgumentError, 'message or response required' if message.blank? && response.blank?
@@ -19,9 +25,9 @@ module BulkImports
@response = response
end
- def retriable?(tracker)
+ def retriable?(object)
if retriable_exception? || retriable_http_code?
- increment(tracker) <= MAX_RETRIABLE_COUNT
+ increment(object) <= MAX_RETRIABLE_COUNT
else
false
end
@@ -37,8 +43,6 @@ module BulkImports
private
- attr_reader :response
-
def retriable_exception?
RETRIABLE_EXCEPTIONS.include?(cause&.class)
end
@@ -47,15 +51,27 @@ module BulkImports
RETRIABLE_HTTP_CODES.include?(response&.code)
end
- def increment(tracker)
- key = COUNTER_KEY % {
+ def increment(object)
+ key = object.is_a?(BulkImports::Entity) ? entity_cache_key(object) : tracker_cache_key(object)
+
+ Gitlab::Cache::Import::Caching.increment(key)
+ end
+
+ def tracker_cache_key(tracker)
+ TRACKER_COUNTER_KEY % {
stage: tracker.stage,
tracker_id: tracker.id,
entity_id: tracker.entity.id,
error: cause.class.name
}
+ end
- Gitlab::Cache::Import::Caching.increment(key)
+ def entity_cache_key(entity)
+ ENTITY_COUNTER_KEY % {
+ import_id: entity.bulk_import_id,
+ entity_id: entity.id,
+ error: cause.class.name
+ }
end
end
end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index 68b86c68619..54d5d3209f8 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -183,7 +183,11 @@ module BulkImports
end
def relation
- class_attributes[:relation_name]
+ class_attributes[:relation_name] || default_relation
+ end
+
+ def default_relation
+ self.name.demodulize.chomp('Pipeline').underscore
end
private
diff --git a/lib/bulk_imports/pipeline/context.rb b/lib/bulk_imports/pipeline/context.rb
index d753f888671..fde24cf3646 100644
--- a/lib/bulk_imports/pipeline/context.rb
+++ b/lib/bulk_imports/pipeline/context.rb
@@ -32,6 +32,10 @@ module BulkImports
@bulk_import ||= entity.bulk_import
end
+ def bulk_import_id
+ @bulk_import_id ||= bulk_import.id
+ end
+
def current_user
@current_user ||= bulk_import.user
end
diff --git a/lib/bulk_imports/pipeline/runner.rb b/lib/bulk_imports/pipeline/runner.rb
index c03da7d8d01..ef9575d1e96 100644
--- a/lib/bulk_imports/pipeline/runner.rb
+++ b/lib/bulk_imports/pipeline/runner.rb
@@ -54,7 +54,8 @@ module BulkImports
skip!(
'Skipping pipeline due to failed entity',
pipeline_step: step,
- step_class: class_name
+ step_class: class_name,
+ importer: 'gitlab_migration'
)
rescue BulkImports::NetworkError => e
if e.retriable?(context.tracker)
@@ -108,9 +109,12 @@ module BulkImports
}
error(
+ bulk_import_id: context.bulk_import_id,
pipeline_step: step,
exception_class: exception.class.to_s,
- exception_message: exception.message
+ exception_message: exception.message,
+ message: "Pipeline failed",
+ importer: 'gitlab_migration'
)
BulkImports::Failure.create(attributes)
@@ -130,11 +134,12 @@ module BulkImports
def log_params(extra)
defaults = {
- bulk_import_id: context.bulk_import.id,
+ bulk_import_id: context.bulk_import_id,
bulk_import_entity_id: context.entity.id,
bulk_import_entity_type: context.entity.source_type,
pipeline_class: pipeline,
- context_extra: context.extra
+ context_extra: context.extra,
+ importer: 'gitlab_migration'
}
defaults
diff --git a/lib/bulk_imports/projects/graphql/get_project_query.rb b/lib/bulk_imports/projects/graphql/get_project_query.rb
index 76475893ac1..a2d7094d570 100644
--- a/lib/bulk_imports/projects/graphql/get_project_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_project_query.rb
@@ -10,6 +10,7 @@ module BulkImports
<<-'GRAPHQL'
query($full_path: ID!) {
project(fullPath: $full_path) {
+ id
visibility
created_at: createdAt
}
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 498bc11b168..723935f8aaf 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -10,6 +10,8 @@ module ContainerRegistry
REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features'
REGISTRY_TAG_DELETE_FEATURE = 'tag_delete'
+ DEFAULT_TAGS_PAGE_SIZE = 10000
+
ALLOWED_REDIRECT_SCHEMES = %w[http https].freeze
REDIRECT_OPTIONS = {
clear_authorization_header: true,
@@ -52,8 +54,11 @@ module ContainerRegistry
}
end
- def repository_tags(name)
- response_body faraday.get("/v2/#{name}/tags/list")
+ def repository_tags(name, page_size: DEFAULT_TAGS_PAGE_SIZE)
+ response = faraday.get("/v2/#{name}/tags/list") do |req|
+ req.params['n'] = page_size
+ end
+ response_body(response)
end
def repository_manifest(name, reference)
diff --git a/lib/container_registry/gitlab_api_client.rb b/lib/container_registry/gitlab_api_client.rb
index 2947dcb4b40..5dddd421223 100644
--- a/lib/container_registry/gitlab_api_client.rb
+++ b/lib/container_registry/gitlab_api_client.rb
@@ -23,6 +23,8 @@ module ContainerRegistry
MAX_TAGS_PAGE_SIZE = 1000
+ UnsuccessfulResponseError = Class.new(StandardError)
+
def self.supports_gitlab_api?
with_dummy_client(return_value_if_disabled: false) do |client|
client.supports_gitlab_api?
@@ -105,12 +107,22 @@ module ContainerRegistry
def tags(path, page_size: 100, last: nil)
limited_page_size = [page_size, MAX_TAGS_PAGE_SIZE].min
with_token_faraday do |faraday_client|
- response = faraday_client.get("/gitlab/v1/repositories/#{path}/tags/list/") do |req|
+ url = "/gitlab/v1/repositories/#{path}/tags/list/"
+ response = faraday_client.get(url) do |req|
req.params['n'] = limited_page_size
req.params['last'] = last if last
end
- break {} unless response.success?
+ unless response.success?
+ Gitlab::ErrorTracking.log_exception(
+ UnsuccessfulResponseError.new,
+ class: self.class.name,
+ url: url,
+ status_code: response.status
+ )
+
+ break {}
+ end
link_parser = Gitlab::Utils::LinkHeaderParser.new(response.headers['link'])
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index edfc39aea0c..6af24451322 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -53,8 +53,6 @@ module Feature
default_enabled: false,
example: <<-EOS
experiment(:my_experiment, project: project, actor: current_user) { ...variant code... }
- # or
- Gitlab::Experimentation.in_experiment_group?(:my_experiment, subject: current_user)
EOS
}
}.freeze
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index 0f0ecd82a32..1920e1443da 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -21,6 +21,7 @@ module Gitlab
:related_class,
:feature_category,
:artifact_size,
+ :artifact_used_cdn,
:artifacts_dependencies_size,
:artifacts_dependencies_count,
:root_caller_id
@@ -38,6 +39,7 @@ module Gitlab
Attribute.new(:related_class, String),
Attribute.new(:feature_category, String),
Attribute.new(:artifact, ::Ci::JobArtifact),
+ Attribute.new(:artifact_used_cdn, Object),
Attribute.new(:artifacts_dependencies_size, Integer),
Attribute.new(:artifacts_dependencies_count, Integer),
Attribute.new(:root_caller_id, String)
@@ -91,6 +93,7 @@ module Gitlab
assign_hash_if_value(hash, :remote_ip)
assign_hash_if_value(hash, :related_class)
assign_hash_if_value(hash, :feature_category)
+ assign_hash_if_value(hash, :artifact_used_cdn)
assign_hash_if_value(hash, :artifacts_dependencies_size)
assign_hash_if_value(hash, :artifacts_dependencies_count)
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 6213dd203c4..c567df8e133 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -221,6 +221,8 @@ module Gitlab
end
if token.user.can_log_in_with_non_expired_password? || token.user.project_bot?
+ ::PersonalAccessTokens::LastUsedService.new(token).execute
+
Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes))
end
end
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index 1fed2b263da..26be7c8aa60 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -217,11 +217,7 @@ module Gitlab
def build_new_user(skip_confirmation: true)
user_params = user_attributes.merge(skip_confirmation: skip_confirmation)
- new_user = Users::AuthorizedBuildService.new(nil, user_params).execute
-
- persist_accepted_terms_if_required(new_user)
-
- new_user
+ Users::AuthorizedBuildService.new(nil, user_params).execute
end
def user_attributes
@@ -249,15 +245,6 @@ module Gitlab
}
end
- def persist_accepted_terms_if_required(new_user)
- if Feature.enabled?(:update_oauth_registration_flow) &&
- Gitlab::CurrentSettings.current_application_settings.enforce_terms?
-
- terms = ApplicationSetting::Term.latest
- Users::RespondToTermsService.new(new_user, terms).execute(accepted: true)
- end
- end
-
def sync_profile_from_provider?
Gitlab::Auth::OAuth::Provider.sync_profile_from_provider?(auth_hash.provider)
end
diff --git a/lib/gitlab/auth_logger.rb b/lib/gitlab/auth_logger.rb
index 6d3edba02b0..763430df335 100644
--- a/lib/gitlab/auth_logger.rb
+++ b/lib/gitlab/auth_logger.rb
@@ -7,3 +7,5 @@ module Gitlab
end
end
end
+
+Gitlab::AuthLogger.prepend_mod
diff --git a/lib/gitlab/background_migration/backfill_epic_cache_counts.rb b/lib/gitlab/background_migration/backfill_epic_cache_counts.rb
new file mode 100644
index 00000000000..bd61d1a0f07
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_epic_cache_counts.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class BackfillEpicCacheCounts < Gitlab::BackgroundMigration::BatchedMigrationJob
+ def perform; end
+ end
+ # rubocop: enable Style/Documentation
+ end
+end
+
+# rubocop: disable Layout/LineLength
+Gitlab::BackgroundMigration::BackfillEpicCacheCounts.prepend_mod_with('Gitlab::BackgroundMigration::BackfillEpicCacheCounts')
+# rubocop: enable Layout/LineLength
diff --git a/lib/gitlab/background_migration/backfill_internal_on_notes.rb b/lib/gitlab/background_migration/backfill_internal_on_notes.rb
new file mode 100644
index 00000000000..300f2cff6ca
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_internal_on_notes.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This syncs the data to `internal` from `confidential` as we rename the column.
+ class BackfillInternalOnNotes < BatchedMigrationJob
+ scope_to -> (relation) { relation.where(confidential: true) }
+
+ def perform
+ each_sub_batch(operation_name: :update_all) do |sub_batch|
+ sub_batch.update_all(internal: true)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_namespace_details.rb b/lib/gitlab/background_migration/backfill_namespace_details.rb
new file mode 100644
index 00000000000..b8a51b576b6
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_namespace_details.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill namespace_details for a range of namespaces
+ class BackfillNamespaceDetails < ::Gitlab::BackgroundMigration::BatchedMigrationJob
+ def perform
+ each_sub_batch(operation_name: :backfill_namespace_details) do |sub_batch|
+ upsert_namespace_details(sub_batch)
+ end
+ end
+
+ def upsert_namespace_details(relation)
+ connection.execute(
+ <<~SQL
+ INSERT INTO namespace_details (description, description_html, cached_markdown_version, created_at, updated_at, namespace_id)
+ SELECT namespaces.description, namespaces.description_html, namespaces.cached_markdown_version, now(), now(), namespaces.id
+ FROM namespaces
+ WHERE namespaces.id IN(#{relation.select(:id).to_sql})
+ AND namespaces.type <> 'Project'
+ ON CONFLICT (namespace_id) DO NOTHING;
+ SQL
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities.rb b/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities.rb
new file mode 100644
index 00000000000..c3e1019b72f
--- /dev/null
+++ b/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Background migration for deleting orphaned operational vulnerabilities (without findings)
+ class DeleteOrphanedOperationalVulnerabilities < ::Gitlab::BackgroundMigration::BatchedMigrationJob
+ REPORT_TYPES = {
+ cluster_image_scanning: 7,
+ custom: 99
+ }.freeze
+
+ NOT_EXISTS_SQL = <<-SQL
+ NOT EXISTS (
+ SELECT FROM vulnerability_occurrences
+ WHERE "vulnerability_occurrences"."vulnerability_id" = "vulnerabilities"."id"
+ )
+ SQL
+
+ scope_to ->(relation) do
+ relation
+ .where(report_type: [REPORT_TYPES[:cluster_image_scanning], REPORT_TYPES[:custom]])
+ end
+
+ def perform
+ each_sub_batch(operation_name: :delete_orphaned_operational_vulnerabilities) do |sub_batch|
+ sub_batch
+ .where(NOT_EXISTS_SQL)
+ .delete_all
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/destroy_invalid_members.rb b/lib/gitlab/background_migration/destroy_invalid_members.rb
new file mode 100644
index 00000000000..7d78795bea9
--- /dev/null
+++ b/lib/gitlab/background_migration/destroy_invalid_members.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ class DestroyInvalidMembers < Gitlab::BackgroundMigration::BatchedMigrationJob # rubocop:disable Style/Documentation
+ scope_to ->(relation) { relation.where(member_namespace_id: nil) }
+
+ def perform
+ each_sub_batch(operation_name: :delete_all) do |sub_batch|
+ deleted_members_data = sub_batch.map do |m|
+ { id: m.id, source_id: m.source_id, source_type: m.source_type }
+ end
+
+ deleted_count = sub_batch.delete_all
+
+ Gitlab::AppLogger.info({ message: 'Removing invalid member records',
+ deleted_count: deleted_count,
+ deleted_member_data: deleted_members_data })
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_approval_merge_request_rules_with_security_orchestration.rb b/lib/gitlab/background_migration/populate_approval_merge_request_rules_with_security_orchestration.rb
new file mode 100644
index 00000000000..2257dc016be
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_approval_merge_request_rules_with_security_orchestration.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class doesn't delete merge request level rules
+ # as this feature exists only in EE
+ class PopulateApprovalMergeRequestRulesWithSecurityOrchestration < BatchedMigrationJob
+ def perform; end
+ end
+ end
+end
+
+# rubocop:disable Layout/LineLength
+Gitlab::BackgroundMigration::PopulateApprovalMergeRequestRulesWithSecurityOrchestration.prepend_mod_with('Gitlab::BackgroundMigration::PopulateApprovalMergeRequestRulesWithSecurityOrchestration')
+# rubocop:enable Layout/LineLength
diff --git a/lib/gitlab/background_migration/populate_approval_project_rules_with_security_orchestration.rb b/lib/gitlab/background_migration/populate_approval_project_rules_with_security_orchestration.rb
new file mode 100644
index 00000000000..1d0c0010551
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_approval_project_rules_with_security_orchestration.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class doesn't delete merge request level rules
+ # as this feature exists only in EE
+ class PopulateApprovalProjectRulesWithSecurityOrchestration < BatchedMigrationJob
+ def perform; end
+ end
+ end
+end
+
+# rubocop:disable Layout/LineLength
+Gitlab::BackgroundMigration::PopulateApprovalProjectRulesWithSecurityOrchestration.prepend_mod_with('Gitlab::BackgroundMigration::PopulateApprovalProjectRulesWithSecurityOrchestration')
+# rubocop:enable Layout/LineLength
diff --git a/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values.rb b/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values.rb
new file mode 100644
index 00000000000..952f3b0e3c3
--- /dev/null
+++ b/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # A job to nullify duplicate token_encrypted values in ci_runners table in batches
+ class ResetDuplicateCiRunnersTokenEncryptedValues < BatchedMigrationJob
+ def perform
+ each_sub_batch(operation_name: :nullify_duplicate_ci_runner_token_encrypted_values) do |sub_batch|
+ # Reset duplicate runner encrypted tokens that would prevent creating an unique index.
+ nullify_duplicate_ci_runner_token_encrypted_values(sub_batch)
+ end
+ end
+
+ private
+
+ def nullify_duplicate_ci_runner_token_encrypted_values(sub_batch)
+ batchable_model = define_batchable_model(batch_table, connection: connection)
+
+ duplicate_tokens = batchable_model
+ .where(token_encrypted: sub_batch.select(:token_encrypted).distinct)
+ .group(:token_encrypted)
+ .having('COUNT(*) > 1')
+ .pluck(:token_encrypted)
+
+ return if duplicate_tokens.empty?
+
+ batchable_model.where(token_encrypted: duplicate_tokens).update_all(token_encrypted: nil)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values.rb b/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values.rb
new file mode 100644
index 00000000000..cfd6a4e4091
--- /dev/null
+++ b/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # A job to nullify duplicate token values in ci_runners table in batches
+ class ResetDuplicateCiRunnersTokenValues < BatchedMigrationJob
+ def perform
+ each_sub_batch(operation_name: :nullify_duplicate_ci_runner_token_values) do |sub_batch|
+ # Reset duplicate runner tokens that would prevent creating an unique index.
+ nullify_duplicate_ci_runner_token_values(sub_batch)
+ end
+ end
+
+ private
+
+ def nullify_duplicate_ci_runner_token_values(sub_batch)
+ batchable_model = define_batchable_model(batch_table, connection: connection)
+
+ duplicate_tokens = batchable_model
+ .where(token: sub_batch.select(:token).distinct)
+ .group(:token)
+ .having('COUNT(*) > 1')
+ .pluck(:token)
+
+ batchable_model.where(token: duplicate_tokens).update_all(token: nil) if duplicate_tokens.any?
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status.rb b/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status.rb
new file mode 100644
index 00000000000..84183753158
--- /dev/null
+++ b/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # The `ci_pipeline_artifacts.locked` column was added in
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97194 to
+ # speed up the finding of expired, pipeline artifacts. By default,
+ # the value is "unknown" (2), but the correct value should be the
+ # value of the associated `ci_pipelines.locked` value. This class
+ # does an UPDATE join to make the values match.
+ class UpdateCiPipelineArtifactsUnknownLockedStatus < BatchedMigrationJob
+ def perform
+ connection.exec_query(<<~SQL)
+ UPDATE ci_pipeline_artifacts
+ SET locked = ci_pipelines.locked
+ FROM ci_pipelines
+ WHERE ci_pipeline_artifacts.id BETWEEN #{start_id} AND #{end_id}
+ AND ci_pipeline_artifacts.locked = 2
+ AND ci_pipelines.id = ci_pipeline_artifacts.pipeline_id;
+ SQL
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/batch_pop_queueing.rb b/lib/gitlab/batch_pop_queueing.rb
deleted file mode 100644
index 103ce644f2b..00000000000
--- a/lib/gitlab/batch_pop_queueing.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- ##
- # This class is a queuing system for processing expensive tasks in an atomic manner
- # with batch poping to let you optimize the total processing time.
- #
- # In usual queuing system, the first item started being processed immediately
- # and the following items wait until the next items have been popped from the queue.
- # On the other hand, this queueing system, the former part is same, however,
- # it pops the enqueued items as batch. This is especially useful when you want to
- # drop redundant items from the queue in order to process important items only,
- # thus it's more efficient than the traditional queueing system.
- #
- # Caveats:
- # - The order of the items are not guaranteed because of `sadd` (Redis Sets).
- #
- # Example:
- # ```
- # class TheWorker
- # def perform
- # result = Gitlab::BatchPopQueueing.new('feature', 'queue').safe_execute([item]) do |items_in_queue|
- # item = extract_the_most_important_item_from(items_in_queue)
- # expensive_process(item)
- # end
- #
- # if result[:status] == :finished && result[:new_items].present?
- # item = extract_the_most_important_item_from(items_in_queue)
- # TheWorker.perform_async(item.id)
- # end
- # end
- # end
- # ```
- #
- class BatchPopQueueing
- attr_reader :namespace, :queue_id
-
- EXTRA_QUEUE_EXPIRE_WINDOW = 1.hour
- MAX_COUNTS_OF_POP_ALL = 1000
-
- # Initialize queue
- #
- # @param [String] namespace The namespace of the exclusive lock and queue key. Typically, it's a feature name.
- # @param [String] queue_id The identifier of the queue.
- # @return [Boolean]
- def initialize(namespace, queue_id)
- raise ArgumentError if namespace.empty? || queue_id.empty?
-
- @namespace = namespace
- @queue_id = queue_id
- end
-
- ##
- # Execute the given block in an exclusive lock.
- # If there is the other thread has already working on the block,
- # it enqueues the items without processing the block.
- #
- # @param [Array<String>] new_items New items to be added to the queue.
- # @param [Time] lock_timeout The timeout of the exclusive lock. Generally, this value should be longer than the maximum prosess timing of the given block.
- # @return [Hash]
- # - status => One of the `:enqueued` or `:finished`.
- # - new_items => Newly enqueued items during the given block had been processed.
- #
- # NOTE: If an exception is raised in the block, the poppped items will not be recovered.
- # We should NOT re-enqueue the items in this case because it could end up in an infinite loop.
- def safe_execute(new_items, lock_timeout: 10.minutes, &block)
- enqueue(new_items, lock_timeout + EXTRA_QUEUE_EXPIRE_WINDOW)
-
- lease = Gitlab::ExclusiveLease.new(lock_key, timeout: lock_timeout)
-
- return { status: :enqueued } unless uuid = lease.try_obtain
-
- begin
- all_args = pop_all
-
- yield all_args if block
-
- { status: :finished, new_items: peek_all }
- ensure
- Gitlab::ExclusiveLease.cancel(lock_key, uuid)
- end
- end
-
- private
-
- def lock_key
- @lock_key ||= "batch_pop_queueing:lock:#{namespace}:#{queue_id}"
- end
-
- def queue_key
- @queue_key ||= "batch_pop_queueing:queue:#{namespace}:#{queue_id}"
- end
-
- def enqueue(items, expire_time)
- Gitlab::Redis::Queues.with do |redis|
- redis.sadd(queue_key, items)
- redis.expire(queue_key, expire_time.to_i)
- end
- end
-
- def pop_all
- Gitlab::Redis::Queues.with do |redis|
- redis.spop(queue_key, MAX_COUNTS_OF_POP_ALL)
- end
- end
-
- def peek_all
- Gitlab::Redis::Queues.with do |redis|
- redis.smembers(queue_key)
- end
- end
- end
-end
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index d58de7eb211..7de6be45349 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -67,6 +67,14 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ def allocate_issues_internal_id!(project, client)
+ last_bitbucket_issue = client.last_issue(repo)
+
+ return unless last_bitbucket_issue
+
+ Issue.track_project_iid!(project, last_bitbucket_issue.iid)
+ end
+
def repo
@repo ||= client.repo(project.import_source)
end
@@ -84,6 +92,10 @@ module Gitlab
def import_issues
return unless repo.issues_enabled?
+ # If a user creates an issue while the import is in progress, this can lead to an import failure.
+ # The workaround is to allocate IIDs before starting the importer.
+ allocate_issues_internal_id!(project, client)
+
create_labels
issue_type_id = WorkItems::Type.default_issue_type.id
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
index 99ce1119c17..9209c9b4927 100644
--- a/lib/gitlab/cache/ci/project_pipeline_status.rb
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -108,7 +108,7 @@ module Gitlab
return self.loaded unless self.loaded.nil?
Gitlab::Redis::Cache.with do |redis|
- redis.exists(cache_key)
+ redis.exists?(cache_key) # rubocop:disable CodeReuse/ActiveRecord
end
end
diff --git a/lib/gitlab/cache/helpers.rb b/lib/gitlab/cache/helpers.rb
index 48b6ca59367..024fa48c066 100644
--- a/lib/gitlab/cache/helpers.rb
+++ b/lib/gitlab/cache/helpers.rb
@@ -126,7 +126,6 @@ module Gitlab
end
def increment_cache_metric(render_type:, total_count:, miss_count:)
- return unless Feature.enabled?(:add_timing_to_certain_cache_actions)
return unless caller_id
metric_name = :cached_object_operations_total
@@ -146,17 +145,13 @@ module Gitlab
end
def time_action(render_type:, &block)
- if Feature.enabled?(:add_timing_to_certain_cache_actions)
- real_start = Gitlab::Metrics::System.monotonic_time
+ real_start = Gitlab::Metrics::System.monotonic_time
- presented_object = yield
+ presented_object = yield
- real_duration_histogram(render_type).observe({}, Gitlab::Metrics::System.monotonic_time - real_start)
+ real_duration_histogram(render_type).observe({}, Gitlab::Metrics::System.monotonic_time - real_start)
- presented_object
- else
- yield
- end
+ presented_object
end
def real_duration_histogram(render_type)
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 1034f5eacef..4069a683ceb 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -41,7 +41,6 @@ module Gitlab
def find_modified_paths(pipeline)
return unless pipeline
- return pipeline.modified_paths unless ::Feature.enabled?(:ci_rules_changes_compare, pipeline.project)
compare_to_sha = find_compare_to_sha(pipeline)
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 438fa1cb3b2..661c6fb87e3 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -85,6 +85,10 @@ module Gitlab
root.workflow_entry.rules_value
end
+ def workflow_name
+ root.workflow_entry.name
+ end
+
def normalized_jobs
@normalized_jobs ||= Ci::Config::Normalizer.new(jobs).normalize_jobs
end
diff --git a/lib/gitlab/ci/config/entry/current_variables.rb b/lib/gitlab/ci/config/entry/current_variables.rb
deleted file mode 100644
index 3b6721ec92d..00000000000
--- a/lib/gitlab/ci/config/entry/current_variables.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Entry that represents CI/CD variables.
- # The class will be renamed to `Variables` when removing the FF `ci_variables_refactoring_to_variable`.
- #
- class CurrentVariables < ::Gitlab::Config::Entry::ComposableHash
- include ::Gitlab::Config::Entry::Validatable
-
- validations do
- validates :config, type: Hash
- end
-
- # Enable these lines when removing the FF `ci_variables_refactoring_to_variable`
- # and renaming this class to `Variables`.
- # def self.default(**)
- # {}
- # end
-
- def value
- @entries.to_h do |key, entry|
- [key.to_s, entry.value]
- end
- end
-
- def value_with_data
- @entries.to_h do |key, entry|
- [key.to_s, entry.value_with_data]
- end
- end
-
- private
-
- def composable_class(_name, _config)
- Entry::Variable
- end
-
- def composable_metadata
- { allowed_value_data: opt(:allowed_value_data) }
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/legacy_variables.rb b/lib/gitlab/ci/config/entry/legacy_variables.rb
deleted file mode 100644
index 5379f707537..00000000000
--- a/lib/gitlab/ci/config/entry/legacy_variables.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Entry that represents environment variables.
- # This is legacy implementation and will be removed with the FF `ci_variables_refactoring_to_variable`.
- #
- class LegacyVariables < ::Gitlab::Config::Entry::Node
- include ::Gitlab::Config::Entry::Validatable
-
- ALLOWED_VALUE_DATA = %i[value description].freeze
-
- validations do
- validates :config, variables: { allowed_value_data: ALLOWED_VALUE_DATA }, if: :use_value_data?
- validates :config, variables: true, unless: :use_value_data?
- end
-
- def value
- @config.to_h { |key, value| [key.to_s, expand_value(value)[:value]] }
- end
-
- def value_with_data
- @config.to_h { |key, value| [key.to_s, expand_value(value)] }
- end
-
- def use_value_data?
- opt(:use_value_data)
- end
-
- private
-
- def expand_value(value)
- if value.is_a?(Hash)
- { value: value[:value].to_s, description: value[:description] }.compact
- else
- { value: value.to_s }
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/root.rb b/lib/gitlab/ci/config/entry/root.rb
index 57e89bd7bc5..1d7d8617c74 100644
--- a/lib/gitlab/ci/config/entry/root.rb
+++ b/lib/gitlab/ci/config/entry/root.rb
@@ -48,10 +48,9 @@ module Gitlab
description: 'Script that will be executed after each job.',
reserved: true
- # use_value_data will be removed with the FF ci_variables_refactoring_to_variable
entry :variables, Entry::Variables,
description: 'Environment variables that will be used.',
- metadata: { use_value_data: true, allowed_value_data: %i[value description] },
+ metadata: { allowed_value_data: %i[value description], allow_array_value: true },
reserved: true
entry :stages, Entry::Stages,
diff --git a/lib/gitlab/ci/config/entry/timeout.rb b/lib/gitlab/ci/config/entry/timeout.rb
index 0bffa9340de..5769ea22b06 100644
--- a/lib/gitlab/ci/config/entry/timeout.rb
+++ b/lib/gitlab/ci/config/entry/timeout.rb
@@ -5,7 +5,7 @@ module Gitlab
class Config
module Entry
##
- # Entry that represents the interrutible value.
+ # Entry that represents the interruptible value.
#
class Timeout < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
diff --git a/lib/gitlab/ci/config/entry/variable.rb b/lib/gitlab/ci/config/entry/variable.rb
index 253888aadeb..54c153c8b07 100644
--- a/lib/gitlab/ci/config/entry/variable.rb
+++ b/lib/gitlab/ci/config/entry/variable.rb
@@ -10,6 +10,7 @@ module Gitlab
class Variable < ::Gitlab::Config::Entry::Simplifiable
strategy :SimpleVariable, if: -> (config) { SimpleVariable.applies_to?(config) }
strategy :ComplexVariable, if: -> (config) { ComplexVariable.applies_to?(config) }
+ strategy :ComplexArrayVariable, if: -> (config) { ComplexArrayVariable.applies_to?(config) }
class SimpleVariable < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
@@ -39,7 +40,7 @@ module Gitlab
class << self
def applies_to?(config)
- config.is_a?(Hash)
+ config.is_a?(Hash) && !config[:value].is_a?(Array)
end
end
@@ -86,6 +87,34 @@ module Gitlab
end
end
+ class ComplexArrayVariable < ComplexVariable
+ include ::Gitlab::Config::Entry::Validatable
+
+ class << self
+ def applies_to?(config)
+ config.is_a?(Hash) && config[:value].is_a?(Array)
+ end
+ end
+
+ validations do
+ validates :config_value, array_of_strings: true, allow_nil: false, if: :config_value_defined?
+
+ validate do
+ next if opt(:allow_array_value)
+
+ errors.add(:config, 'value must be an alphanumeric string')
+ end
+ end
+
+ def value
+ config_value.first
+ end
+
+ def value_with_data
+ super.merge(value_options: config_value).compact
+ end
+ end
+
class UnknownStrategy < ::Gitlab::Config::Entry::Node
def errors
["variable definition must be either a string or a hash"]
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index 0284958d9d4..4430a11dda7 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -6,20 +6,38 @@ module Gitlab
module Entry
##
# Entry that represents CI/CD variables.
- # CurrentVariables will be renamed to this class when removing the FF `ci_variables_refactoring_to_variable`.
- #
- class Variables
- def self.new(...)
- if YamlProcessor::FeatureFlags.enabled?(:ci_variables_refactoring_to_variable)
- CurrentVariables.new(...)
- else
- LegacyVariables.new(...)
- end
+ class Variables < ::Gitlab::Config::Entry::ComposableHash
+ include ::Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, type: Hash
end
def self.default(**)
{}
end
+
+ def value
+ @entries.to_h do |key, entry|
+ [key.to_s, entry.value]
+ end
+ end
+
+ def value_with_data
+ @entries.to_h do |key, entry|
+ [key.to_s, entry.value_with_data]
+ end
+ end
+
+ private
+
+ def composable_class(_name, _config)
+ Entry::Variable
+ end
+
+ def composable_metadata
+ { allowed_value_data: opt(:allowed_value_data), allow_array_value: opt(:allow_array_value) }
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/workflow.rb b/lib/gitlab/ci/config/entry/workflow.rb
index 5bc992a38a0..691d9e2d48b 100644
--- a/lib/gitlab/ci/config/entry/workflow.rb
+++ b/lib/gitlab/ci/config/entry/workflow.rb
@@ -6,12 +6,17 @@ module Gitlab
module Entry
class Workflow < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Configurable
+ include ::Gitlab::Config::Entry::Validatable
+ include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[rules].freeze
+ ALLOWED_KEYS = %i[rules name].freeze
+
+ attributes :name
validations do
validates :config, type: Hash
validates :config, allowed_keys: ALLOWED_KEYS
+ validates :name, allow_nil: true, length: { minimum: 1, maximum: 255 }
end
entry :rules, Entry::Rules,
diff --git a/lib/gitlab/ci/config/external/context.rb b/lib/gitlab/ci/config/external/context.rb
index ec628399785..138e79db331 100644
--- a/lib/gitlab/ci/config/external/context.rb
+++ b/lib/gitlab/ci/config/external/context.rb
@@ -10,7 +10,6 @@ module Gitlab
TimeoutError = Class.new(StandardError)
MAX_INCLUDES = 100
- TRIAL_MAX_INCLUDES = 250
include ::Gitlab::Utils::StrongMemoize
@@ -31,7 +30,7 @@ module Gitlab
@expandset = Set.new
@execution_deadline = 0
@logger = logger || Gitlab::Ci::Pipeline::Logger.new(project: project)
- @max_includes = Feature.enabled?(:ci_increase_includes_to_250, project) ? TRIAL_MAX_INCLUDES : MAX_INCLUDES
+ @max_includes = MAX_INCLUDES
yield self if block_given?
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index d3e7210b820..d82ca875e76 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -12,7 +12,7 @@ module Gitlab
self.new(build, ttl: build.metadata_timeout).encoded
end
- def initialize(build, ttl: nil)
+ def initialize(build, ttl:)
@build = build
@ttl = ttl
end
diff --git a/lib/gitlab/ci/jwt_v2.rb b/lib/gitlab/ci/jwt_v2.rb
index 4e01688a955..cfefa79d9e0 100644
--- a/lib/gitlab/ci/jwt_v2.rb
+++ b/lib/gitlab/ci/jwt_v2.rb
@@ -3,13 +3,27 @@
module Gitlab
module Ci
class JwtV2 < Jwt
+ DEFAULT_AUD = Settings.gitlab.base_url
+
+ def self.for_build(build, aud: DEFAULT_AUD)
+ new(build, ttl: build.metadata_timeout, aud: aud).encoded
+ end
+
+ def initialize(build, ttl:, aud:)
+ super(build, ttl: ttl)
+
+ @aud = aud
+ end
+
private
+ attr_reader :aud
+
def reserved_claims
super.merge(
iss: Settings.gitlab.base_url,
sub: "project_path:#{project.full_path}:ref_type:#{ref_type}:ref:#{source_ref}",
- aud: Settings.gitlab.base_url
+ aud: aud
)
end
end
diff --git a/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb b/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb
index 00ca723b258..c76a4309779 100644
--- a/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb
+++ b/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb
@@ -23,8 +23,7 @@ module Gitlab
::Gitlab::Ci::Reports::Sbom::Source.new(
type: :dependency_scanning,
- data: data,
- fingerprint: fingerprint
+ data: data
)
end
@@ -37,10 +36,6 @@ module Gitlab
data.dig(*keys).present?
end
end
-
- def fingerprint
- Digest::SHA256.hexdigest(data.to_json)
- end
end
end
end
diff --git a/lib/gitlab/ci/parsers/security/common.rb b/lib/gitlab/ci/parsers/security/common.rb
index da7faaab6ff..0c117d5f214 100644
--- a/lib/gitlab/ci/parsers/security/common.rb
+++ b/lib/gitlab/ci/parsers/security/common.rb
@@ -44,31 +44,15 @@ module Gitlab
attr_reader :json_data, :report, :validate
def valid?
- # We want validation to happen regardless of VALIDATE_SCHEMA
- # CI variable.
- #
- # Previously it controlled BOTH validation and enforcement of
- # schema validation result.
- #
- # After 15.0 we will enforce schema validation by default
- # See: https://gitlab.com/groups/gitlab-org/-/epics/6968
- schema_validator.deprecation_warnings.each { |deprecation_warning| report.add_warning('Schema', deprecation_warning) }
-
- if validate
- schema_validation_passed = schema_validator.valid?
+ return true unless validate
- # Validation warnings are errors
- schema_validator.errors.each { |error| report.add_error('Schema', error) }
- schema_validator.warnings.each { |warning| report.add_error('Schema', warning) }
+ schema_validation_passed = schema_validator.valid?
- schema_validation_passed
- else
- # Validation warnings are warnings
- schema_validator.errors.each { |error| report.add_warning('Schema', error) }
- schema_validator.warnings.each { |warning| report.add_warning('Schema', warning) }
+ schema_validator.errors.each { |error| report.add_error('Schema', error) }
+ schema_validator.deprecation_warnings.each { |deprecation_warning| report.add_warning('Schema', deprecation_warning) }
+ schema_validator.warnings.each { |warning| report.add_warning('Schema', warning) }
- true
- end
+ schema_validation_passed
end
def schema_validator
@@ -216,7 +200,22 @@ module Gitlab
external_id: scanner_data['id'],
name: scanner_data['name'],
vendor: scanner_data.dig('vendor', 'name'),
- version: scanner_data.dig('version')))
+ version: scanner_data.dig('version'),
+ primary_identifiers: create_scan_primary_identifiers))
+ end
+
+ # TODO: primary_identifiers should be initialized on the
+ # scan itself but we do not currently parse scans through `MergeReportsService`
+ def create_scan_primary_identifiers
+ return unless scan_data.is_a?(Hash) && scan_data.dig('primary_identifiers')
+
+ scan_data.dig('primary_identifiers').map do |identifier|
+ ::Gitlab::Ci::Reports::Security::Identifier.new(
+ external_type: identifier['type'],
+ external_id: identifier['value'],
+ name: identifier['name'],
+ url: identifier['url'])
+ end
end
def create_identifiers(identifiers)
diff --git a/lib/gitlab/ci/parsers/security/concerns/deprecated_syntax.rb b/lib/gitlab/ci/parsers/security/concerns/deprecated_syntax.rb
deleted file mode 100644
index 24613a441be..00000000000
--- a/lib/gitlab/ci/parsers/security/concerns/deprecated_syntax.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Parsers
- module Security
- module Concerns
- module DeprecatedSyntax
- extend ActiveSupport::Concern
-
- included do
- extend ::Gitlab::Utils::Override
-
- override :parse_report
- end
-
- def report_data
- @report_data ||= begin
- data = super
-
- if data.is_a?(Array)
- data = {
- "version" => self.class::DEPRECATED_REPORT_VERSION,
- "vulnerabilities" => data
- }
- end
-
- data
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/parsers/security/sast.rb b/lib/gitlab/ci/parsers/security/sast.rb
index e3c62614cd8..3d999f20f1e 100644
--- a/lib/gitlab/ci/parsers/security/sast.rb
+++ b/lib/gitlab/ci/parsers/security/sast.rb
@@ -5,10 +5,6 @@ module Gitlab
module Parsers
module Security
class Sast < Common
- include Security::Concerns::DeprecatedSyntax
-
- DEPRECATED_REPORT_VERSION = "1.2"
-
private
def create_location(location_data)
diff --git a/lib/gitlab/ci/parsers/security/secret_detection.rb b/lib/gitlab/ci/parsers/security/secret_detection.rb
index c6d95c1d391..175731b6b64 100644
--- a/lib/gitlab/ci/parsers/security/secret_detection.rb
+++ b/lib/gitlab/ci/parsers/security/secret_detection.rb
@@ -5,10 +5,6 @@ module Gitlab
module Parsers
module Security
class SecretDetection < Common
- include Security::Concerns::DeprecatedSyntax
-
- DEPRECATED_REPORT_VERSION = "1.2"
-
private
def create_location(location_data)
diff --git a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
index 28d6620e5c4..627a1f58715 100644
--- a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
+++ b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
@@ -7,14 +7,14 @@ module Gitlab
module Validators
class SchemaValidator
SUPPORTED_VERSIONS = {
- cluster_image_scanning: %w[14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- container_scanning: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- coverage_fuzzing: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- dast: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- api_fuzzing: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- dependency_scanning: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- sast: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0],
- secret_detection: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0]
+ cluster_image_scanning: %w[14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ container_scanning: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ coverage_fuzzing: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ dast: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ api_fuzzing: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ dependency_scanning: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ sast: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2],
+ secret_detection: %w[14.0.0 14.0.1 14.0.2 14.0.3 14.0.4 14.0.5 14.0.6 14.1.0 14.1.1 14.1.2 14.1.3 15.0.0 15.0.1 15.0.2]
}.freeze
VERSIONS_TO_REMOVE_IN_16_0 = [].freeze
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..0fcab3cd8bb
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/cluster-image-scanning-report-format.json
@@ -0,0 +1,980 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/cluster-image-scanning-report-format.json",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/container-scanning-report-format.json
new file mode 100644
index 00000000000..c08d0b45ced
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/container-scanning-report-format.json
@@ -0,0 +1,914 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/container-scanning-report-format.json",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^[^:]+(:\\d+[^:]*)?:[^:]+(:[^:]+)?$",
+ "description": "The analyzed Docker image."
+ },
+ "default_branch_image": {
+ "type": "string",
+ "maxLength": 255,
+ "pattern": "^[a-zA-Z0-9/_.-]+(:\\d+[a-zA-Z0-9/_.-]*)?:[a-zA-Z0-9_.-]+$",
+ "description": "The name of the image on the default branch."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..e1ee91de23c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/coverage-fuzzing-report-format.json
@@ -0,0 +1,870 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/coverage-fuzzing-report-format.json",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dast-report-format.json
new file mode 100644
index 00000000000..ba2b31cf6aa
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dast-report-format.json
@@ -0,0 +1,1275 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/dast-report-format.json",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..2bf207ce2c2
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/dependency-scanning-report-format.json
@@ -0,0 +1,978 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/dependency-scanning-report-format.json",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "dependency_files",
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/sast-report-format.json
new file mode 100644
index 00000000000..c3f3bf8265f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/sast-report-format.json
@@ -0,0 +1,865 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/sast-report-format.json",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/secret-detection-report-format.json
new file mode 100644
index 00000000000..9f7c4a45466
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.1/secret-detection-report-format.json
@@ -0,0 +1,888 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/secret-detection-report-format.json",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.1"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/cluster-image-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/cluster-image-scanning-report-format.json
new file mode 100644
index 00000000000..b753a44a3d4
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/cluster-image-scanning-report-format.json
@@ -0,0 +1,980 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/cluster-image-scanning-report-format.json",
+ "title": "Report format for GitLab Cluster Image Scanning",
+ "description": "This schema provides the the report format for Cluster Image Scanning (https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "cluster_image_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "image",
+ "kubernetes_resource"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image.",
+ "examples": [
+ "index.docker.io/library/nginx:1.21"
+ ]
+ },
+ "kubernetes_resource": {
+ "type": "object",
+ "description": "The specific Kubernetes resource that was scanned.",
+ "required": [
+ "namespace",
+ "kind",
+ "name",
+ "container_name"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes namespace the resource that had its image scanned.",
+ "examples": [
+ "default",
+ "staging",
+ "production"
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The Kubernetes kind the resource that had its image scanned.",
+ "examples": [
+ "Deployment",
+ "DaemonSet"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the resource that had its image scanned.",
+ "examples": [
+ "nginx-ingress"
+ ]
+ },
+ "container_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The name of the container that had its image scanned.",
+ "examples": [
+ "nginx"
+ ]
+ },
+ "agent_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes Agent which performed the scan.",
+ "examples": [
+ "1234"
+ ]
+ },
+ "cluster_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 255,
+ "description": "The GitLab ID of the Kubernetes cluster when using cluster integration.",
+ "examples": [
+ "1234"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/container-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/container-scanning-report-format.json
new file mode 100644
index 00000000000..85671d03a27
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/container-scanning-report-format.json
@@ -0,0 +1,912 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/container-scanning-report-format.json",
+ "title": "Report format for GitLab Container Scanning",
+ "description": "This schema provides the the report format for Container Scanning (https://docs.gitlab.com/ee/user/application_security/container_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "container_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "dependency",
+ "operating_system",
+ "image"
+ ],
+ "properties": {
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ },
+ "operating_system": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The operating system that contains the vulnerable package."
+ },
+ "image": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The analyzed Docker image."
+ },
+ "default_branch_image": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the image on the default branch."
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/coverage-fuzzing-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/coverage-fuzzing-report-format.json
new file mode 100644
index 00000000000..33568a246fa
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/coverage-fuzzing-report-format.json
@@ -0,0 +1,870 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/coverage-fuzzing-report-format.json",
+ "title": "Report format for GitLab Fuzz Testing",
+ "description": "This schema provides the report format for Coverage Guided Fuzz Testing (https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "coverage_fuzzing"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "description": "The location of the error",
+ "type": "object",
+ "properties": {
+ "crash_address": {
+ "type": "string",
+ "description": "The relative address in memory were the crash occurred.",
+ "examples": [
+ "0xabababab"
+ ]
+ },
+ "stacktrace_snippet": {
+ "type": "string",
+ "description": "The stack trace recorded during fuzzing resulting the crash.",
+ "examples": [
+ "func_a+0xabcd\nfunc_b+0xabcc"
+ ]
+ },
+ "crash_state": {
+ "type": "string",
+ "description": "Minimised and normalized crash stack-trace (called crash_state).",
+ "examples": [
+ "func_a+0xa\nfunc_b+0xb\nfunc_c+0xc"
+ ]
+ },
+ "crash_type": {
+ "type": "string",
+ "description": "Type of the crash.",
+ "examples": [
+ "Heap-Buffer-overflow",
+ "Division-by-zero"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dast-report-format.json
new file mode 100644
index 00000000000..eb141f044d5
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dast-report-format.json
@@ -0,0 +1,1275 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/dast-report-format.json",
+ "title": "Report format for GitLab DAST",
+ "description": "This schema provides the the report format for Dynamic Application Security Testing (https://docs.gitlab.com/ee/user/application_security/dast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanned_resources",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dast",
+ "api_fuzzing"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "scanned_resources": {
+ "type": "array",
+ "description": "The attack surface scanned by DAST.",
+ "items": {
+ "type": "object",
+ "required": [
+ "method",
+ "url",
+ "type"
+ ],
+ "properties": {
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method of the scanned resource.",
+ "examples": [
+ "GET",
+ "POST",
+ "HEAD"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the scanned resource.",
+ "examples": [
+ "http://my.site.com/a-page"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Type of the scanned resource, for DAST, this must be 'url'.",
+ "examples": [
+ "url"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "evidence": {
+ "type": "object",
+ "properties": {
+ "source": {
+ "type": "object",
+ "description": "Source of evidence",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique source identifier",
+ "examples": [
+ "assert:LogAnalysis",
+ "assert:StatusCode"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Source display name",
+ "examples": [
+ "Log Analysis",
+ "Status Code"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "Link to additional information",
+ "examples": [
+ "https://docs.gitlab.com/ee/development/integrations/secure.html"
+ ]
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Human readable string containing evidence of the vulnerability.",
+ "examples": [
+ "Credit card 4111111111111111 found",
+ "Server leaked information nginx/1.17.6"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ },
+ "supporting_messages": {
+ "type": "array",
+ "description": "Array of supporting http messages.",
+ "items": {
+ "type": "object",
+ "description": "A supporting http message.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Message display name.",
+ "examples": [
+ "Unmodified",
+ "Recorded"
+ ]
+ },
+ "request": {
+ "type": "object",
+ "description": "An HTTP request.",
+ "required": [
+ "headers",
+ "method",
+ "url"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "method": {
+ "type": "string",
+ "minLength": 1,
+ "description": "HTTP method used in the request.",
+ "examples": [
+ "GET",
+ "POST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "URL of the request.",
+ "examples": [
+ "http://my.site.com/vulnerable-endpoint?show-credit-card"
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the request for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "user=jsmith&first=%27&last=smith"
+ ]
+ }
+ }
+ },
+ "response": {
+ "type": "object",
+ "description": "An HTTP response.",
+ "required": [
+ "headers",
+ "reason_phrase",
+ "status_code"
+ ],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "HTTP headers present on the request.",
+ "items": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the HTTP header.",
+ "examples": [
+ "Accept",
+ "Content-Length",
+ "Content-Type"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the HTTP header.",
+ "examples": [
+ "*/*",
+ "560",
+ "application/json; charset=utf-8"
+ ]
+ }
+ }
+ }
+ },
+ "reason_phrase": {
+ "type": "string",
+ "description": "HTTP reason phrase of the response.",
+ "examples": [
+ "OK",
+ "Internal Server Error"
+ ]
+ },
+ "status_code": {
+ "type": "integer",
+ "description": "HTTP status code of the response.",
+ "examples": [
+ 200,
+ 500
+ ]
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the response for display purposes. Body must be suitable for display (not binary), and truncated to a reasonable size.",
+ "examples": [
+ "{\"user_id\": 2}"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "hostname": {
+ "type": "string",
+ "description": "The protocol, domain, and port of the application where the vulnerability was found."
+ },
+ "method": {
+ "type": "string",
+ "description": "The HTTP method that was used to request the URL where the vulnerability was found."
+ },
+ "param": {
+ "type": "string",
+ "description": "A value provided by a vulnerability rule related to the found vulnerability. Examples include a header value, or a parameter used in a HTTP POST."
+ },
+ "path": {
+ "type": "string",
+ "description": "The path of the URL where the vulnerability was found. Typically, this would start with a forward slash."
+ }
+ }
+ },
+ "assets": {
+ "type": "array",
+ "description": "Array of build assets associated with vulnerability.",
+ "items": {
+ "type": "object",
+ "description": "Describes an asset associated with vulnerability.",
+ "required": [
+ "type",
+ "name",
+ "url"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of asset",
+ "enum": [
+ "http_session",
+ "postman"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Display name for asset",
+ "examples": [
+ "HTTP Messages",
+ "Postman Collection"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Link to asset in build artifacts",
+ "examples": [
+ "https://gitlab.com/gitlab-org/security-products/dast/-/jobs/626397001/artifacts/file//output/zap_session.data"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dependency-scanning-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dependency-scanning-report-format.json
new file mode 100644
index 00000000000..31905180019
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/dependency-scanning-report-format.json
@@ -0,0 +1,978 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/dependency-scanning-report-format.json",
+ "title": "Report format for GitLab Dependency Scanning",
+ "description": "This schema provides the the report format for Dependency Scanning analyzers (https://docs.gitlab.com/ee/user/application_security/dependency_scanning).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "dependency_files",
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "dependency_scanning"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "required": [
+ "file",
+ "dependency"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Path to the manifest or lock file where the dependency is declared (such as yarn.lock)."
+ },
+ "dependency": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ },
+ "dependency_files": {
+ "type": "array",
+ "description": "List of dependency files identified in the project.",
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "package_manager",
+ "dependencies"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1
+ },
+ "package_manager": {
+ "type": "string",
+ "minLength": 1
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Describes the dependency of a project where the vulnerability is located.",
+ "required": [
+ "package",
+ "version"
+ ],
+ "properties": {
+ "package": {
+ "type": "object",
+ "description": "Provides information on the package where the vulnerability is located.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the package where the vulnerability is located."
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "Version of the vulnerable package."
+ },
+ "iid": {
+ "description": "ID that identifies the dependency in the scope of a dependency file.",
+ "type": "number"
+ },
+ "direct": {
+ "type": "boolean",
+ "description": "Tells whether this is a direct, top-level dependency of the scanned project."
+ },
+ "dependency_path": {
+ "type": "array",
+ "description": "Ancestors of the dependency, starting from a direct project dependency, and ending with an immediate parent of the dependency. The dependency itself is excluded from the path. Direct dependencies have no path.",
+ "items": {
+ "type": "object",
+ "required": [
+ "iid"
+ ],
+ "properties": {
+ "iid": {
+ "type": "number",
+ "description": "ID that is unique in the scope of a parent object, and specific to the resource type."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/sast-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/sast-report-format.json
new file mode 100644
index 00000000000..efc9715aafb
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/sast-report-format.json
@@ -0,0 +1,865 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/sast-report-format.json",
+ "title": "Report format for GitLab SAST",
+ "description": "This schema provides the report format for Static Application Security Testing analyzers (https://docs.gitlab.com/ee/user/application_security/sast).",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "sast"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "type": "object",
+ "description": "Identifies the vulnerability's location.",
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability."
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located."
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located."
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/secret-detection-report-format.json b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/secret-detection-report-format.json
new file mode 100644
index 00000000000..adbd01760d7
--- /dev/null
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/15.0.2/secret-detection-report-format.json
@@ -0,0 +1,888 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/master/dist/secret-detection-report-format.json",
+ "title": "Report format for GitLab Secret Detection",
+ "description": "This schema provides the the report format for the Secret Detection analyzer (https://docs.gitlab.com/ee/user/application_security/secret_detection)",
+ "definitions": {
+ "detail_type": {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/named_list"
+ },
+ {
+ "$ref": "#/definitions/list"
+ },
+ {
+ "$ref": "#/definitions/table"
+ },
+ {
+ "$ref": "#/definitions/text"
+ },
+ {
+ "$ref": "#/definitions/url"
+ },
+ {
+ "$ref": "#/definitions/code"
+ },
+ {
+ "$ref": "#/definitions/value"
+ },
+ {
+ "$ref": "#/definitions/diff"
+ },
+ {
+ "$ref": "#/definitions/markdown"
+ },
+ {
+ "$ref": "#/definitions/commit"
+ },
+ {
+ "$ref": "#/definitions/file_location"
+ },
+ {
+ "$ref": "#/definitions/module_location"
+ }
+ ]
+ },
+ "text_value": {
+ "type": "string"
+ },
+ "named_field": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/text_value",
+ "minLength": 1
+ },
+ "description": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "named_list": {
+ "type": "object",
+ "description": "An object with named and typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "named-list"
+ },
+ "items": {
+ "type": "object",
+ "patternProperties": {
+ "^.*$": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/named_field"
+ },
+ {
+ "$ref": "#/definitions/detail_type"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "list": {
+ "type": "object",
+ "description": "A list of typed fields",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "description": "A table of typed fields",
+ "required": [
+ "type",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "header": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/detail_type"
+ }
+ }
+ }
+ }
+ },
+ "text": {
+ "type": "object",
+ "description": "Raw text",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value"
+ }
+ }
+ },
+ "url": {
+ "type": "object",
+ "description": "A single URL",
+ "required": [
+ "type",
+ "href"
+ ],
+ "properties": {
+ "type": {
+ "const": "url"
+ },
+ "text": {
+ "$ref": "#/definitions/text_value"
+ },
+ "href": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "http://mysite.com"
+ ]
+ }
+ }
+ },
+ "code": {
+ "type": "object",
+ "description": "A codeblock",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "code"
+ },
+ "value": {
+ "type": "string"
+ },
+ "lang": {
+ "type": "string",
+ "description": "A programming language"
+ }
+ }
+ },
+ "value": {
+ "type": "object",
+ "description": "A field that can store a range of types of value",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "value"
+ },
+ "value": {
+ "type": [
+ "number",
+ "string",
+ "boolean"
+ ]
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "description": "A diff",
+ "required": [
+ "type",
+ "before",
+ "after"
+ ],
+ "properties": {
+ "type": {
+ "const": "diff"
+ },
+ "before": {
+ "type": "string"
+ },
+ "after": {
+ "type": "string"
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "markdown"
+ },
+ "value": {
+ "$ref": "#/definitions/text_value",
+ "examples": [
+ "Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"
+ ]
+ }
+ }
+ },
+ "commit": {
+ "type": "object",
+ "description": "A commit/tag/branch within the GitLab project",
+ "required": [
+ "type",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "commit"
+ },
+ "value": {
+ "type": "string",
+ "description": "The commit SHA",
+ "minLength": 1
+ }
+ }
+ },
+ "file_location": {
+ "type": "object",
+ "description": "A location within a file in the project",
+ "required": [
+ "type",
+ "file_name",
+ "line_start"
+ ],
+ "properties": {
+ "type": {
+ "const": "file-location"
+ },
+ "file_name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "line_start": {
+ "type": "integer"
+ },
+ "line_end": {
+ "type": "integer"
+ }
+ }
+ },
+ "module_location": {
+ "type": "object",
+ "description": "A location within a binary module of the form module+relative_offset",
+ "required": [
+ "type",
+ "module_name",
+ "offset"
+ ],
+ "properties": {
+ "type": {
+ "const": "module-location"
+ },
+ "module_name": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "compiled_binary"
+ ]
+ },
+ "offset": {
+ "type": "integer",
+ "examples": [
+ 100
+ ]
+ }
+ }
+ }
+ },
+ "self": {
+ "version": "15.0.2"
+ },
+ "required": [
+ "scan",
+ "version",
+ "vulnerabilities"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "scan": {
+ "type": "object",
+ "required": [
+ "analyzer",
+ "end_time",
+ "scanner",
+ "start_time",
+ "status",
+ "type"
+ ],
+ "properties": {
+ "end_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan finished.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-01-28T03:26:02"
+ ]
+ },
+ "messages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Communication intended for the initiator of a scan.",
+ "required": [
+ "level",
+ "value"
+ ],
+ "properties": {
+ "level": {
+ "type": "string",
+ "description": "Describes the severity of the communication. Use info to communicate normal scan behaviour; warn to communicate a potentially recoverable problem, or a partial error; fatal to communicate an issue that causes the scan to halt.",
+ "enum": [
+ "info",
+ "warn",
+ "fatal"
+ ],
+ "examples": [
+ "info"
+ ]
+ },
+ "value": {
+ "type": "string",
+ "description": "The message to communicate.",
+ "minLength": 1,
+ "examples": [
+ "Permission denied, scanning aborted"
+ ]
+ }
+ }
+ }
+ },
+ "analyzer": {
+ "type": "object",
+ "description": "Object defining the analyzer used to perform the scan. Analyzers typically delegate to an underlying scanner to run the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "gitlab-dast"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the analyzer, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "GitLab DAST"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "pattern": "^https?://.+",
+ "description": "A link to more information about the analyzer.",
+ "examples": [
+ "https://docs.gitlab.com/ee/user/application_security/dast"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the analyzer.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the analyzer.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ }
+ }
+ },
+ "scanner": {
+ "type": "object",
+ "description": "Object defining the scanner used to perform the scan.",
+ "required": [
+ "id",
+ "name",
+ "version",
+ "vendor"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique id that identifies the scanner.",
+ "minLength": 1,
+ "examples": [
+ "my-sast-scanner"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "A human readable value that identifies the scanner, not required to be unique.",
+ "minLength": 1,
+ "examples": [
+ "My SAST Scanner"
+ ]
+ },
+ "url": {
+ "type": "string",
+ "description": "A link to more information about the scanner.",
+ "examples": [
+ "https://scanner.url"
+ ]
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the scanner.",
+ "minLength": 1,
+ "examples": [
+ "1.0.2"
+ ]
+ },
+ "vendor": {
+ "description": "The vendor/maintainer of the scanner.",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the vendor.",
+ "minLength": 1,
+ "examples": [
+ "GitLab"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "start_time": {
+ "type": "string",
+ "description": "ISO8601 UTC value with format yyyy-mm-ddThh:mm:ss, representing when the scan started.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$",
+ "examples": [
+ "2020-02-14T16:01:59"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Result of the scan.",
+ "enum": [
+ "success",
+ "failure"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of the scan.",
+ "enum": [
+ "secret_detection"
+ ]
+ },
+ "primary_identifiers": {
+ "type": "array",
+ "description": "An array containing an exhaustive list of primary identifiers for which the analyzer may return results",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "schema": {
+ "type": "string",
+ "description": "URI pointing to the validating security report schema.",
+ "pattern": "^https?://.+"
+ },
+ "version": {
+ "type": "string",
+ "description": "The version of the schema to which the JSON report conforms.",
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "description": "Array of vulnerability objects.",
+ "items": {
+ "type": "object",
+ "description": "Describes the vulnerability using GitLab Flavored Markdown",
+ "required": [
+ "id",
+ "identifiers",
+ "location"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the vulnerability. This must not include the finding's specific information."
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 1048576,
+ "description": "A long text section describing the vulnerability more fully."
+ },
+ "severity": {
+ "type": "string",
+ "description": "How much the vulnerability impacts the software. Possible values are Info, Unknown, Low, Medium, High, or Critical. Note that some analyzers may not report all these possible values.",
+ "enum": [
+ "Info",
+ "Unknown",
+ "Low",
+ "Medium",
+ "High",
+ "Critical"
+ ]
+ },
+ "solution": {
+ "type": "string",
+ "maxLength": 7000,
+ "description": "Explanation of how to fix the vulnerability."
+ },
+ "identifiers": {
+ "type": "array",
+ "minItems": 1,
+ "description": "An ordered array of references that identify a vulnerability on internal or external databases. The first identifier is the Primary Identifier, which has special meaning.",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "for example, cve, cwe, osvdb, usn, or an analyzer-dependent type such as gemnasium).",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "description": "Human-readable name of the identifier.",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the identifier's documentation.",
+ "pattern": "^https?://.+"
+ },
+ "value": {
+ "type": "string",
+ "description": "Value of the identifier, for matching purpose.",
+ "minLength": 1
+ }
+ }
+ }
+ },
+ "links": {
+ "type": "array",
+ "description": "An array of references to external documentation or articles that describe the vulnerability.",
+ "items": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the vulnerability details link."
+ },
+ "url": {
+ "type": "string",
+ "description": "URL of the vulnerability details document.",
+ "pattern": "^https?://.+"
+ }
+ }
+ }
+ },
+ "details": {
+ "$ref": "#/definitions/named_list/properties/items"
+ },
+ "tracking": {
+ "description": "Describes how this vulnerability should be tracked as the project changes.",
+ "oneOf": [
+ {
+ "description": "Declares that a series of items should be tracked using source-specific tracking methods.",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "source"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "description": "An item that should be tracked using source-specific tracking methods.",
+ "type": "object",
+ "required": [
+ "signatures"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located."
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the file that includes the vulnerability."
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the file that includes the vulnerability."
+ },
+ "signatures": {
+ "type": "array",
+ "description": "An array of calculated tracking signatures for this tracking item.",
+ "minItems": 1,
+ "items": {
+ "description": "A calculated tracking signature value and metadata.",
+ "required": [
+ "algorithm",
+ "value"
+ ],
+ "properties": {
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to generate the signature."
+ },
+ "value": {
+ "type": "string",
+ "description": "The result of this signature algorithm."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Each tracking type must declare its own type."
+ }
+ }
+ },
+ "flags": {
+ "description": "Flags that can be attached to vulnerabilities.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Informational flags identified and assigned to a vulnerability.",
+ "required": [
+ "type",
+ "origin",
+ "description"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Result of the scan.",
+ "enum": [
+ "flagged-as-likely-false-positive"
+ ]
+ },
+ "origin": {
+ "minLength": 1,
+ "description": "Tool that issued the flag.",
+ "type": "string"
+ },
+ "description": {
+ "minLength": 1,
+ "description": "What the flag is about.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "location": {
+ "required": [
+ "commit"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "description": "Path to the file where the vulnerability is located"
+ },
+ "commit": {
+ "type": "object",
+ "description": "Represents the commit in which the vulnerability was detected",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "sha": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "start_line": {
+ "type": "number",
+ "description": "The first line of the code affected by the vulnerability"
+ },
+ "end_line": {
+ "type": "number",
+ "description": "The last line of the code affected by the vulnerability"
+ },
+ "class": {
+ "type": "string",
+ "description": "Provides the name of the class where the vulnerability is located"
+ },
+ "method": {
+ "type": "string",
+ "description": "Provides the name of the method where the vulnerability is located"
+ }
+ }
+ },
+ "raw_source_code_extract": {
+ "type": "string",
+ "description": "Provides an unsanitized excerpt of the affected source code."
+ }
+ }
+ }
+ },
+ "remediations": {
+ "type": "array",
+ "description": "An array of objects containing information on available remediations, along with patch diffs to apply.",
+ "items": {
+ "type": "object",
+ "required": [
+ "fixes",
+ "summary",
+ "diff"
+ ],
+ "properties": {
+ "fixes": {
+ "type": "array",
+ "description": "An array of strings that represent references to vulnerabilities fixed by this remediation.",
+ "items": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique identifier of the vulnerability. This is recommended to be a UUID.",
+ "examples": [
+ "642735a5-1425-428d-8d4e-3c854885a3c9"
+ ]
+ }
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "description": "An overview of how the vulnerabilities were fixed."
+ },
+ "diff": {
+ "type": "string",
+ "minLength": 1,
+ "description": "A base64-encoded remediation code diff, compatible with git apply."
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
index 9c12d46cede..07a3aff1862 100644
--- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
+++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
@@ -11,9 +11,11 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def perform!
+ ff_enabled = Feature.enabled?(:ci_skip_auto_cancelation_on_child_pipelines, project)
+ return if ff_enabled && pipeline.parent_pipeline? # skip if child pipeline
return unless project.auto_cancel_pending_pipelines?
- Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines, name: 'cancel_pending_pipelines') do |cancelables|
+ Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines(ff_enabled), name: 'cancel_pending_pipelines') do |cancelables|
cancelables.select(:id).each_batch(of: BATCH_SIZE) do |cancelables_batch|
auto_cancel_interruptible_pipelines(cancelables_batch.ids)
end
@@ -27,13 +29,19 @@ module Gitlab
private
- def auto_cancelable_pipelines
- project.all_pipelines.created_after(1.week.ago)
+ def auto_cancelable_pipelines(ff_enabled)
+ relation = project.all_pipelines
+ .created_after(1.week.ago)
.ci_and_parent_sources
.for_ref(pipeline.ref)
- .id_not_in(pipeline.same_family_pipeline_ids)
.where_not_sha(project.commit(pipeline.ref).try(:id))
.alive_or_scheduled
+
+ if ff_enabled
+ relation.id_not_in(pipeline.id)
+ else
+ relation.id_not_in(pipeline.same_family_pipeline_ids)
+ end
end
def auto_cancel_interruptible_pipelines(pipeline_ids)
@@ -41,6 +49,14 @@ module Gitlab
.id_in(pipeline_ids)
.with_only_interruptible_builds
.each do |cancelable_pipeline|
+ Gitlab::AppLogger.info(
+ class: self.class.name,
+ message: "Pipeline #{pipeline.id} auto-canceling pipeline #{cancelable_pipeline.id}",
+ canceled_pipeline_id: cancelable_pipeline.id,
+ canceled_by_pipeline_id: pipeline.id,
+ canceled_by_pipeline_source: pipeline.source
+ )
+
# cascade_to_children not needed because we iterate through descendants here
cancelable_pipeline.cancel_running(
auto_canceled_by_pipeline_id: pipeline.id,
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index 14c320f77bf..76d4a05bf30 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -121,11 +121,7 @@ module Gitlab
end
def observe_jobs_count_in_alive_pipelines
- jobs_count = if Feature.enabled?(:ci_limit_active_jobs_early, project)
- project.all_pipelines.jobs_count_in_alive_pipelines
- else
- project.all_pipelines.builds_count_in_alive_pipelines
- end
+ jobs_count = project.all_pipelines.jobs_count_in_alive_pipelines
metrics.active_jobs_histogram
.observe({ plan: project.actual_plan_name }, jobs_count)
diff --git a/lib/gitlab/ci/pipeline/chain/config/content.rb b/lib/gitlab/ci/pipeline/chain/config/content.rb
index a14dec48619..d41213ef6dd 100644
--- a/lib/gitlab/ci/pipeline/chain/config/content.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/content.rb
@@ -9,15 +9,6 @@ module Gitlab
include Chain::Helpers
include ::Gitlab::Utils::StrongMemoize
- SOURCES = [
- Gitlab::Ci::Pipeline::Chain::Config::Content::Parameter,
- Gitlab::Ci::Pipeline::Chain::Config::Content::Bridge,
- Gitlab::Ci::Pipeline::Chain::Config::Content::Repository,
- Gitlab::Ci::Pipeline::Chain::Config::Content::ExternalProject,
- Gitlab::Ci::Pipeline::Chain::Config::Content::Remote,
- Gitlab::Ci::Pipeline::Chain::Config::Content::AutoDevops
- ].freeze
-
def perform!
if pipeline_config&.exists?
@pipeline.build_pipeline_config(content: pipeline_config.content)
@@ -36,8 +27,6 @@ module Gitlab
def pipeline_config
strong_memoize(:pipeline_config) do
- next legacy_find_config if ::Feature.disabled?(:ci_project_pipeline_config_refactoring, project)
-
::Gitlab::Ci::ProjectConfig.new(
project: project, sha: @pipeline.sha,
custom_content: @command.content,
@@ -45,24 +34,9 @@ module Gitlab
)
end
end
-
- def legacy_find_config
- sources.each do |source|
- config = source.new(@pipeline, @command)
- return config if config.exists?
- end
-
- nil
- end
-
- def sources
- SOURCES
- end
end
end
end
end
end
end
-
-Gitlab::Ci::Pipeline::Chain::Config::Content.prepend_mod_with('Gitlab::Ci::Pipeline::Chain::Config::Content')
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb b/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb
deleted file mode 100644
index 4947e2eb879..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class AutoDevops < Source
- def content
- strong_memoize(:content) do
- next unless project&.auto_devops_enabled?
-
- template = Gitlab::Template::GitlabCiYmlTemplate.find(template_name)
- YAML.dump('include' => [{ 'template' => template.full_name }])
- end
- end
-
- def source
- :auto_devops_source
- end
-
- private
-
- def template_name
- 'Auto-DevOps'
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/bridge.rb b/lib/gitlab/ci/pipeline/chain/config/content/bridge.rb
deleted file mode 100644
index 39ffa2d4e25..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/bridge.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class Bridge < Source
- def content
- return unless @command.bridge
-
- @command.bridge.yaml_for_downstream
- end
-
- def source
- :bridge_source
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/external_project.rb b/lib/gitlab/ci/pipeline/chain/config/content/external_project.rb
deleted file mode 100644
index 092e7d43371..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/external_project.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class ExternalProject < Source
- def content
- strong_memoize(:content) do
- next unless external_project_path?
-
- path_file, path_project, ref = extract_location_tokens
-
- config_location = { 'project' => path_project, 'file' => path_file }
- config_location['ref'] = ref if ref.present?
-
- YAML.dump('include' => [config_location])
- end
- end
-
- def source
- :external_project_source
- end
-
- private
-
- # Example: path/to/.gitlab-ci.yml@another-group/another-project
- def external_project_path?
- ci_config_path =~ /\A.+(yml|yaml)@.+\z/
- end
-
- # Example: path/to/.gitlab-ci.yml@another-group/another-project:refname
- def extract_location_tokens
- path_file, path_project = ci_config_path.split('@', 2)
-
- if path_project.include? ":"
- project, ref = path_project.split(':', 2)
- [path_file, project, ref]
- else
- [path_file, path_project]
- end
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/parameter.rb b/lib/gitlab/ci/pipeline/chain/config/content/parameter.rb
deleted file mode 100644
index 9954aedc4b7..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/parameter.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class Parameter < Source
- UnsupportedSourceError = Class.new(StandardError)
-
- def content
- strong_memoize(:content) do
- next unless command.content.present?
-
- command.content
- end
- end
-
- def source
- :parameter_source
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/remote.rb b/lib/gitlab/ci/pipeline/chain/config/content/remote.rb
deleted file mode 100644
index 4990a5a6eb5..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/remote.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class Remote < Source
- def content
- strong_memoize(:content) do
- next unless ci_config_path =~ URI::DEFAULT_PARSER.make_regexp(%w[http https])
-
- YAML.dump('include' => [{ 'remote' => ci_config_path }])
- end
- end
-
- def source
- :remote_source
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/repository.rb b/lib/gitlab/ci/pipeline/chain/config/content/repository.rb
deleted file mode 100644
index 0752b099d3d..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/repository.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- class Repository < Source
- def content
- strong_memoize(:content) do
- next unless file_in_repository?
-
- YAML.dump('include' => [{ 'local' => ci_config_path }])
- end
- end
-
- def source
- :repository_source
- end
-
- private
-
- def file_in_repository?
- return unless project
- return unless @pipeline.sha
-
- project.repository.gitlab_ci_yml_for(@pipeline.sha, ci_config_path).present?
- rescue GRPC::NotFound, GRPC::Internal
- nil
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/source.rb b/lib/gitlab/ci/pipeline/chain/config/content/source.rb
deleted file mode 100644
index 69dca1568b6..00000000000
--- a/lib/gitlab/ci/pipeline/chain/config/content/source.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Config
- class Content
- # When removing ci_project_pipeline_config_refactoring, this and its subclasses will be removed.
- class Source
- include Gitlab::Utils::StrongMemoize
-
- DEFAULT_YAML_FILE = '.gitlab-ci.yml'
-
- attr_reader :command
-
- def initialize(pipeline, command)
- @pipeline = pipeline
- @command = command
- end
-
- def exists?
- strong_memoize(:exists) do
- content.present?
- end
- end
-
- def content
- raise NotImplementedError
- end
-
- def source
- raise NotImplementedError
- end
-
- def project
- @project ||= @pipeline.project
- end
-
- def ci_config_path
- @ci_config_path ||= project.ci_config_path.presence || DEFAULT_YAML_FILE
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/chain/limit/active_jobs.rb b/lib/gitlab/ci/pipeline/chain/limit/active_jobs.rb
new file mode 100644
index 00000000000..8b26416edf7
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/limit/active_jobs.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ module Limit
+ class ActiveJobs < Chain::Base
+ include ::Gitlab::Utils::StrongMemoize
+ include ::Gitlab::Ci::Pipeline::Chain::Helpers
+
+ LIMIT_NAME = :ci_active_jobs
+ MESSAGE = "Project exceeded the allowed number of jobs in active pipelines. Retry later."
+
+ def perform!
+ return unless limits.exceeded?(LIMIT_NAME, count_jobs_in_alive_pipelines)
+
+ error(MESSAGE, drop_reason: :job_activity_limit_exceeded)
+
+ Gitlab::AppLogger.info(
+ class: self.class.name,
+ message: MESSAGE,
+ project_id: project.id,
+ plan: project.actual_plan_name)
+ end
+
+ def break?
+ pipeline.errors.any?
+ end
+
+ private
+
+ def namespace
+ strong_memoize(:namespace) do
+ project.namespace
+ end
+ end
+
+ def limits
+ strong_memoize(:limits) do
+ namespace.actual_limits
+ end
+ end
+
+ def count_jobs_in_alive_pipelines
+ strong_memoize(:count_jobs_in_alive_pipelines) do
+ count_persisted_jobs_in_all_alive_pipelines + count_current_pipeline_jobs
+ end
+ end
+
+ def count_current_pipeline_jobs
+ command.pipeline_seed.size
+ end
+
+ def count_persisted_jobs_in_all_alive_pipelines
+ project.all_pipelines.jobs_count_in_alive_pipelines
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/limit/job_activity.rb b/lib/gitlab/ci/pipeline/chain/limit/job_activity.rb
deleted file mode 100644
index 3706dd0b9f6..00000000000
--- a/lib/gitlab/ci/pipeline/chain/limit/job_activity.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Chain
- module Limit
- class JobActivity < Chain::Base
- def perform!
- # to be overridden in EE
- end
-
- def break?
- false # to be overridden in EE
- end
- end
- end
- end
- end
- end
-end
-
-Gitlab::Ci::Pipeline::Chain::Limit::JobActivity.prepend_mod_with('Gitlab::Ci::Pipeline::Chain::Limit::JobActivity')
diff --git a/lib/gitlab/ci/pipeline/chain/populate.rb b/lib/gitlab/ci/pipeline/chain/populate.rb
index 654e24be8e1..4bec8355732 100644
--- a/lib/gitlab/ci/pipeline/chain/populate.rb
+++ b/lib/gitlab/ci/pipeline/chain/populate.rb
@@ -25,6 +25,8 @@ module Gitlab
return error('Failed to build the pipeline!')
end
+ set_pipeline_name
+
raise Populate::PopulateError if pipeline.persisted?
end
@@ -34,6 +36,15 @@ module Gitlab
private
+ def set_pipeline_name
+ return if Feature.disabled?(:pipeline_name, pipeline.project) ||
+ @command.yaml_processor_result.workflow_name.blank?
+
+ name = @command.yaml_processor_result.workflow_name
+
+ pipeline.build_pipeline_metadata(project: pipeline.project, title: name)
+ end
+
def stage_names
# We filter out `.pre/.post` stages, as they alone are not considered
# a complete pipeline:
diff --git a/lib/gitlab/ci/pipeline/duration.rb b/lib/gitlab/ci/pipeline/duration.rb
index de24bbf688b..e8a991026b5 100644
--- a/lib/gitlab/ci/pipeline/duration.rb
+++ b/lib/gitlab/ci/pipeline/duration.rb
@@ -91,7 +91,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def from_pipeline(pipeline)
status = %w[success failed running canceled]
- builds = pipeline.builds.latest
+ builds = pipeline.processables.latest
.where(status: status).where.not(started_at: nil).order(:started_at)
from_builds(builds)
diff --git a/lib/gitlab/ci/pipeline/logger.rb b/lib/gitlab/ci/pipeline/logger.rb
index 44d905faced..4b7cbae5004 100644
--- a/lib/gitlab/ci/pipeline/logger.rb
+++ b/lib/gitlab/ci/pipeline/logger.rb
@@ -86,6 +86,7 @@ module Gitlab
'count' => values.size,
'min' => values.min,
'max' => values.max,
+ 'sum' => values.sum,
'avg' => values.sum / values.size
}
end.compact
diff --git a/lib/gitlab/ci/processable_object_hierarchy.rb b/lib/gitlab/ci/processable_object_hierarchy.rb
index 1122361e27e..c1531c3f4ab 100644
--- a/lib/gitlab/ci/processable_object_hierarchy.rb
+++ b/lib/gitlab/ci/processable_object_hierarchy.rb
@@ -20,12 +20,16 @@ module Gitlab
def ancestor_conditions(cte)
middle_table[:name].eq(objects_table[:name]).and(
middle_table[:build_id].eq(cte.table[:id])
+ ).and(
+ objects_table[:commit_id].eq(cte.table[:commit_id])
)
end
def descendant_conditions(cte)
middle_table[:build_id].eq(objects_table[:id]).and(
middle_table[:name].eq(cte.table[:name])
+ ).and(
+ objects_table[:commit_id].eq(cte.table[:commit_id])
)
end
end
diff --git a/lib/gitlab/ci/reports/sbom/source.rb b/lib/gitlab/ci/reports/sbom/source.rb
index ea0fb8d4fbb..fbb8644c1b0 100644
--- a/lib/gitlab/ci/reports/sbom/source.rb
+++ b/lib/gitlab/ci/reports/sbom/source.rb
@@ -5,12 +5,11 @@ module Gitlab
module Reports
module Sbom
class Source
- attr_reader :source_type, :data, :fingerprint
+ attr_reader :source_type, :data
- def initialize(type:, data:, fingerprint:)
+ def initialize(type:, data:)
@source_type = type
@data = data
- @fingerprint = fingerprint
end
end
end
diff --git a/lib/gitlab/ci/reports/security/report.rb b/lib/gitlab/ci/reports/security/report.rb
index 70f2919d38d..54b21da5436 100644
--- a/lib/gitlab/ci/reports/security/report.rb
+++ b/lib/gitlab/ci/reports/security/report.rb
@@ -69,6 +69,10 @@ module Gitlab
replace_with!(::Security::MergeReportsService.new(self, other).execute)
end
+ def primary_identifiers
+ scanners.values.flat_map(&:primary_identifiers).compact
+ end
+
def primary_scanner
scanners.first&.second
end
diff --git a/lib/gitlab/ci/reports/security/scanner.rb b/lib/gitlab/ci/reports/security/scanner.rb
index 918df163ede..080ed3f834a 100644
--- a/lib/gitlab/ci/reports/security/scanner.rb
+++ b/lib/gitlab/ci/reports/security/scanner.rb
@@ -16,15 +16,16 @@ module Gitlab
"semgrep" => 2
}.freeze
- attr_accessor :external_id, :name, :vendor, :version
+ attr_accessor :external_id, :name, :vendor, :version, :primary_identifiers
alias_method :key, :external_id
- def initialize(external_id:, name:, vendor:, version:)
+ def initialize(external_id:, name:, vendor:, version:, primary_identifiers: nil)
@external_id = external_id
@name = name
@vendor = vendor
@version = version
+ @primary_identifiers = primary_identifiers
end
def to_hash
diff --git a/lib/gitlab/ci/secure_files/cer.rb b/lib/gitlab/ci/secure_files/cer.rb
new file mode 100644
index 00000000000..45d2898c29b
--- /dev/null
+++ b/lib/gitlab/ci/secure_files/cer.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module SecureFiles
+ class Cer
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :error
+
+ def initialize(filedata)
+ @filedata = filedata
+ @error = nil
+ end
+
+ def certificate_data
+ OpenSSL::X509::Certificate.new(@filedata)
+ rescue OpenSSL::X509::CertificateError => err
+ @error = err.to_s
+ nil
+ end
+ strong_memoize_attr :certificate_data
+
+ def metadata
+ return {} unless certificate_data
+
+ {
+ issuer: issuer,
+ subject: subject,
+ id: id,
+ expires_at: expires_at
+ }
+ end
+ strong_memoize_attr :metadata
+
+ private
+
+ def expires_at
+ certificate_data.not_before
+ end
+
+ def id
+ certificate_data.serial.to_s
+ end
+
+ def issuer
+ X509Name.parse(certificate_data.issuer)
+ end
+
+ def subject
+ X509Name.parse(certificate_data.subject)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/secure_files/mobile_provision.rb b/lib/gitlab/ci/secure_files/mobile_provision.rb
new file mode 100644
index 00000000000..4ea74e20310
--- /dev/null
+++ b/lib/gitlab/ci/secure_files/mobile_provision.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+require 'cfpropertylist'
+
+module Gitlab
+ module Ci
+ module SecureFiles
+ class MobileProvision
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :error
+
+ def initialize(filedata)
+ @filedata = filedata
+ end
+
+ def decoded_plist
+ p7 = OpenSSL::PKCS7.new(@filedata)
+ p7.verify(nil, OpenSSL::X509::Store.new, nil, OpenSSL::PKCS7::NOVERIFY)
+ p7.data
+ rescue ArgumentError, OpenSSL::PKCS7::PKCS7Error => err
+ @error = err.to_s
+ nil
+ end
+ strong_memoize_attr :decoded_plist
+
+ def properties
+ list = CFPropertyList::List.new(data: decoded_plist, format: CFPropertyList::List::FORMAT_XML).value
+ CFPropertyList.native_types(list)
+ rescue CFFormatError, CFPlistError, CFTypeError => err
+ @error = err.to_s
+ nil
+ end
+ strong_memoize_attr :properties
+
+ def metadata
+ return {} unless properties
+
+ {
+ id: id,
+ expires_at: expires_at,
+ platforms: properties["Platform"],
+ team_name: properties['TeamName'],
+ team_id: properties['TeamIdentifier'],
+ app_name: properties['AppIDName'],
+ app_id: properties['Name'],
+ app_id_prefix: properties['ApplicationIdentifierPrefix'],
+ xcode_managed: properties['IsXcodeManaged'],
+ entitlements: properties['Entitlements'],
+ devices: properties['ProvisionedDevices'],
+ certificate_ids: certificate_ids
+ }
+ end
+ strong_memoize_attr :metadata
+
+ private
+
+ def id
+ properties['UUID']
+ end
+
+ def expires_at
+ properties['ExpirationDate']
+ end
+
+ def certificate_ids
+ return [] if developer_certificates.empty?
+
+ developer_certificates.map { |c| c.metadata[:id] }
+ end
+
+ def developer_certificates
+ certificates = properties['DeveloperCertificates']
+ return if certificates.empty?
+
+ certs = []
+ certificates.each_with_object([]) do |cert, obj|
+ certs << Cer.new(cert)
+ end
+
+ certs
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/secure_files/p12.rb b/lib/gitlab/ci/secure_files/p12.rb
new file mode 100644
index 00000000000..1006a4d05b2
--- /dev/null
+++ b/lib/gitlab/ci/secure_files/p12.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module SecureFiles
+ class P12
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :error
+
+ def initialize(filedata, password = nil)
+ @filedata = filedata
+ @password = password
+ end
+
+ def certificate_data
+ OpenSSL::PKCS12.new(@filedata, @password).certificate
+ rescue OpenSSL::PKCS12::PKCS12Error => err
+ @error = err.to_s
+ nil
+ end
+ strong_memoize_attr :certificate_data
+
+ def metadata
+ return {} unless certificate_data
+
+ {
+ issuer: issuer,
+ subject: subject,
+ id: serial,
+ expires_at: expires_at
+ }
+ end
+ strong_memoize_attr :metadata
+
+ private
+
+ def expires_at
+ certificate_data.not_before
+ end
+
+ def serial
+ certificate_data.serial.to_s
+ end
+
+ def issuer
+ X509Name.parse(certificate_data.issuer)
+ end
+
+ def subject
+ X509Name.parse(certificate_data.subject)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/secure_files/x509_name.rb b/lib/gitlab/ci/secure_files/x509_name.rb
new file mode 100644
index 00000000000..659959b8ae5
--- /dev/null
+++ b/lib/gitlab/ci/secure_files/x509_name.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module SecureFiles
+ class X509Name
+ def self.parse(x509_name)
+ x509_name.to_utf8.split(',').to_h { |a| a.split('=') }
+ rescue StandardError
+ {}
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/templates/C++.gitlab-ci.yml b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
index 3096af1b173..fbdaeecca5d 100644
--- a/lib/gitlab/ci/templates/C++.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
@@ -33,3 +33,8 @@ test:
stage: test
script:
- ./runmytests.sh
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
index 4fe37ceaeaa..3379ce2f649 100644
--- a/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
@@ -28,3 +28,8 @@ test:
# If you need to run any migrations or configure the database, this
# would be the point to do it.
- lein test
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
index 68b55b782cd..9584ec5deef 100644
--- a/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
@@ -42,3 +42,8 @@ spec:
minitest:
script:
- crystal test/spec_test.cr # change to the file(s) you execute for tests
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Django.gitlab-ci.yml b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
index acc4a9d2917..21dda92257e 100644
--- a/lib/gitlab/ci/templates/Django.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
@@ -74,3 +74,8 @@ django-tests:
- echo "GRANT ALL on *.* to '${MYSQL_USER}';"| mysql -u root --password="${MYSQL_ROOT_PASSWORD}" -h mysql
# use python3 explicitly. see https://wiki.ubuntu.com/Python/3
- python3 manage.py test
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
index 83ddce936e6..8b20c4cbccc 100644
--- a/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
@@ -24,3 +24,8 @@ before_script:
mix:
script:
- mix test
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
index 021662ab416..7f81755348c 100644
--- a/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml
@@ -35,3 +35,8 @@ test:
- $CI_PROJECT_DIR/coverage
reports:
junit: report.xml
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Go.gitlab-ci.yml b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
index 603aede4d46..8cfea3e236f 100644
--- a/lib/gitlab/ci/templates/Go.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
@@ -28,3 +28,8 @@ compile:
artifacts:
paths:
- mybinaries
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml b/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml
index 08dc10d34b7..671925c5df6 100644
--- a/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml
@@ -1,3 +1,5 @@
+# You can copy and paste this template into a new `.gitlab-ci.yml` file.
+# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
# 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:
@@ -39,3 +41,8 @@ test:
paths:
- build
- .gradle
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Grails.gitlab-ci.yml b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
index 03c8941169f..01697f67b89 100644
--- a/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
@@ -46,3 +46,8 @@ before_script:
build:
script:
- ./gradlew build
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index ce227bad19a..071eccbab0d 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_BUILD_IMAGE_VERSION: 'v1.14.0'
+ AUTO_BUILD_IMAGE_VERSION: 'v1.19.0'
build:
stage: build
diff --git a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
index ce227bad19a..071eccbab0d 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_BUILD_IMAGE_VERSION: 'v1.14.0'
+ AUTO_BUILD_IMAGE_VERSION: 'v1.19.0'
build:
stage: build
diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
index e278539d214..23efed212f8 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -8,7 +8,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/ci-cd/codequality:0.85.29"
+ CODE_QUALITY_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/ci-cd/codequality:0.87.0"
needs: []
script:
- export SOURCE_CODE=$PWD
@@ -26,6 +26,11 @@ code_quality:
echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
done
}
+ - |
+ if [ -n "$CODECLIMATE_REGISTRY_USERNAME" ] && [ -n "$CODECLIMATE_REGISTRY_PASSWORD" ] && [ -n "$CODECLIMATE_PREFIX" ]; then
+ CODECLIMATE_REGISTRY=${CODECLIMATE_PREFIX%%/*}
+ docker login "$CODECLIMATE_REGISTRY" --username "$CODECLIMATE_REGISTRY_USERNAME" --password "$CODECLIMATE_REGISTRY_PASSWORD"
+ fi
- docker pull --quiet "$CODE_QUALITY_IMAGE"
- |
docker run --rm \
@@ -38,6 +43,8 @@ code_quality:
REPORT_FORMAT \
ENGINE_MEMORY_LIMIT_BYTES \
CODECLIMATE_PREFIX \
+ CODECLIMATE_REGISTRY_USERNAME \
+ CODECLIMATE_REGISTRY_PASSWORD \
) \
--volume "$PWD":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 539e1a6385d..d994ed70ea9 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.37.0'
+ DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.39.0'
.dast-auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
index 7cbc8e40b47..222f534387a 100644
--- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
@@ -50,6 +50,8 @@ dependency_scanning:
artifacts:
paths:
- "**/gl-sbom-*.cdx.json"
+ reports:
+ cyclonedx: "**/gl-sbom-*.cdx.json"
.gemnasium-shared-rule:
exists:
diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml
index 70f85382967..67057e916a8 100644
--- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml
@@ -50,6 +50,8 @@ dependency_scanning:
artifacts:
paths:
- "**/gl-sbom-*.cdx.json"
+ reports:
+ cyclonedx: "**/gl-sbom-*.cdx.json"
.gemnasium-shared-rule:
exists:
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 78fe108e8b9..7ad71625436 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.37.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.39.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index bc2e1fed0d4..10c843f60a6 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.37.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.39.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
diff --git a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
index 34084272b29..d39b329c4b6 100644
--- a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
@@ -81,3 +81,8 @@ pages:
# description page.
#
# [3]: https://hub.docker.com/_/julia/
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
index 3a490012f3d..7bb2ea328e7 100644
--- a/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
@@ -78,3 +78,8 @@ test:
# set it in your package.json script
# comment this out if you don't have a frontend test
- npm test
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
index dfa46d7af61..347b811bc5d 100644
--- a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
@@ -14,26 +14,44 @@
# * Deploy built artifacts from master branch only.
variables:
- # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
# `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
- MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
- # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
+ MAVEN_OPTS: >-
+ -Dhttps.protocols=TLSv1.2
+ -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
+ -Dorg.slf4j.simpleLogger.showDateTime=true
+ -Djava.awt.headless=true
+
+ # As of Maven 3.3.0 instead of this you MAY define these options in `.mvn/maven.config` so the same config is used
# when running from the command line.
+ # As of Maven 3.6.1, the use of `--no-tranfer-progress` (or `-ntp`) suppresses download and upload messages. The use
+ # of the `Slf4jMavenTransferListener` is no longer necessary.
# `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
- MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
+ MAVEN_CLI_OPTS: >-
+ --batch-mode
+ --errors
+ --fail-at-end
+ --show-version
+ --no-transfer-progress
+ -DinstallAtEnd=true
+ -DdeployAtEnd=true
-# This template uses jdk8 for verifying and deploying images
-image: maven:3.3.9-jdk-8
+# This template uses the latest Maven 3 release, e.g., 3.8.6, and OpenJDK 8 (LTS)
+# for verifying and deploying images
+# Maven 3.8.x REQUIRES HTTPS repositories.
+# See https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked for more.
+image: maven:3-openjdk-8
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
+# Be aware that `mvn deploy` will install the built jar into this repository. If you notice your cache size
+# increasing, consider adding `-Dmaven.install.skip=true` to `MAVEN_OPTS` or in `.mvn/maven.config`
cache:
paths:
- .m2/repository
# For merge requests do not `deploy` but only run `verify`.
# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
-.verify: &verify
+.verify:
stage: test
script:
- 'mvn $MAVEN_CLI_OPTS verify'
@@ -43,19 +61,20 @@ cache:
# Verify merge requests using JDK8
verify:jdk8:
- <<: *verify
+ extends:
+ - .verify
-# To deploy packages from CI, create a ci_settings.xml file
+# To deploy packages from CI, create a `ci_settings.xml` file
# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for more details.
# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
-# For `master` branch run `mvn deploy` automatically.
+# For `master` or `main` branch run `mvn deploy` automatically.
deploy:jdk8:
stage: deploy
script:
- - if [ ! -f ci_settings.xml ];
- then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for instructions.";
+ - if [ ! -f ci_settings.xml ]; then
+ echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for instructions.";
fi
- - 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
+ - 'mvn $MAVEN_CLI_OPTS deploy --settings ci_settings.xml'
only:
variables:
- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
diff --git a/lib/gitlab/ci/templates/Mono.gitlab-ci.yml b/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
index 65db649e22f..e34bb8307f4 100644
--- a/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
@@ -49,3 +49,8 @@ debug:
- msbuild /p:Configuration="Debug" /p:Platform="Any CPU"
/p:OutputPath="./../../build/debug/" "MyProject.sln"
- mono packages/NUnit.ConsoleRunner.3.6.0/tools/nunit3-console.exe build/debug/MyProject.Test.dll
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
index 7a4f7ed628b..649d525df76 100644
--- a/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
@@ -33,3 +33,8 @@ test_db:
script:
- npm install
- node ./specs/start.js ./specs/db-postgres.spec.js
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/PHP.gitlab-ci.yml b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
index 12640d28d29..0604438e0aa 100644
--- a/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
@@ -42,3 +42,8 @@ variables:
test:
script:
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
index 55cf22b6601..51d2273d41d 100644
--- a/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
@@ -18,3 +18,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
index 2f518d667a5..e577a489c55 100644
--- a/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
@@ -11,6 +11,7 @@ pages:
- apk update && apk add doxygen
- doxygen doxygen/Doxyfile
- mv doxygen/documentation/html/ public/
+ environment: production
artifacts:
paths:
- public
diff --git a/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
index 9da50439be8..88ed73b41e7 100644
--- a/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
@@ -20,3 +20,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
index 85f90984045..9f3ba6d5dd4 100644
--- a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
@@ -6,6 +6,7 @@
# Full project: https://gitlab.com/pages/plain-html
pages:
stage: deploy
+ environment: production
script:
- mkdir .public
- cp -r ./* .public
diff --git a/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
index 9e48ac9fcdc..aa86ad2a6ad 100644
--- a/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
@@ -18,3 +18,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
index a6f94a4d80e..b1617e9239c 100644
--- a/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
@@ -11,6 +11,7 @@ pages:
- npm install hexo-cli -g
- test -e package.json && npm install
- hexo generate
+ environment: production
artifacts:
paths:
- public
diff --git a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
index 591eebf9cd6..d6f6e94526e 100644
--- a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
@@ -27,3 +27,4 @@ pages:
only:
variables:
- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
index 59e55efaee0..fba4afca9ed 100644
--- a/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
@@ -21,6 +21,7 @@ test:
pages:
stage: deploy
+ environment: production
script:
- pip install hyde
- hyde gen -d public
diff --git a/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
index 8e15570fd1a..57e3ced4dc2 100644
--- a/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
@@ -29,6 +29,7 @@ before_script:
# This build job produced the output directory of your site
pages:
+ environment: production
script:
- jbake . public
artifacts:
diff --git a/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
index e0ad2e55f7d..8b07454af24 100644
--- a/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
@@ -36,3 +36,4 @@ pages:
only:
variables:
- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
index 26fac92d0dc..ad083fcc5db 100644
--- a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
@@ -40,3 +40,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
index 9b5c1198c6c..e86337ae23c 100644
--- a/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
@@ -15,3 +15,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
index d97f0b7beb7..a49e95b62c8 100644
--- a/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
@@ -19,3 +19,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
index 17ce0ef3659..d8f036ab4ed 100644
--- a/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
@@ -31,3 +31,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
index a3ce96da244..b0511abd109 100644
--- a/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
@@ -15,3 +15,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
index 4abdf66a21c..c89050eede7 100644
--- a/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
@@ -18,3 +18,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
index 7d52a407848..3721344b21e 100644
--- a/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
@@ -13,3 +13,4 @@ pages:
artifacts:
paths:
- public/
+ environment: production
diff --git a/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml
index 961941ac4d0..00efcfa1b32 100644
--- a/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml
@@ -32,3 +32,4 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
diff --git a/lib/gitlab/ci/templates/Python.gitlab-ci.yml b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
index 191d5b6b11c..febbb36d834 100644
--- a/lib/gitlab/ci/templates/Python.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
@@ -55,3 +55,8 @@ pages:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Rust.gitlab-ci.yml b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
index a83f84da818..b9823444db2 100644
--- a/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
@@ -40,3 +40,8 @@ test:cargo:
# when: always
# reports:
# junit: $CI_PROJECT_DIR/tests/*.xml
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/Scala.gitlab-ci.yml b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
index 26efe7a8908..ce5d5937896 100644
--- a/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
@@ -30,3 +30,8 @@ test:
script:
# Execute your project's tests
- sbt clean test
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
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 8d6c191edc4..f12efa1db34 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
@@ -40,6 +40,19 @@ apifuzzer_fuzz:
- if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
$CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
when: never
+
+ # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
+ $CI_GITLAB_FIPS_MODE == "true"
+ variables:
+ DAST_API_IMAGE_SUFFIX: "-fips"
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+
+ # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
+
+ # Add the job to branch pipelines.
- if: $CI_COMMIT_BRANCH &&
$CI_GITLAB_FIPS_MODE == "true"
variables:
@@ -55,5 +68,3 @@ apifuzzer_fuzz:
- gl-*.log
reports:
api_fuzzing: gl-api-fuzzing-report.json
-
-# end
diff --git a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
index d4b6a252b25..d933007ec61 100644
--- a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
@@ -31,15 +31,15 @@ coverage_fuzzing_unlicensed:
stage: fuzz
allow_failure: true
before_script:
- - export COVFUZZ_JOB_TOKEN=$CI_JOB_TOKEN
- - export COVFUZZ_PRIVATE_TOKEN=$CI_PRIVATE_TOKEN
- - export COVFUZZ_PROJECT_PATH=$CI_PROJECT_PATH
- - export COVFUZZ_PROJECT_ID=$CI_PROJECT_ID
+ - export COVFUZZ_JOB_TOKEN="$CI_JOB_TOKEN"
+ - export COVFUZZ_PRIVATE_TOKEN="$CI_PRIVATE_TOKEN"
+ - export COVFUZZ_PROJECT_PATH="$CI_PROJECT_PATH"
+ - export COVFUZZ_PROJECT_ID="$CI_PROJECT_ID"
- if [ -x "$(command -v apt-get)" ] ; then apt-get update && apt-get install -y wget; fi
- wget -O gitlab-cov-fuzz "${COVFUZZ_URL_PREFIX}"/"${COVFUZZ_VERSION}"/binaries/gitlab-cov-fuzz_Linux_x86_64
- chmod a+x gitlab-cov-fuzz
- export REGRESSION=true
- - if [[ $CI_COMMIT_BRANCH = $COVFUZZ_BRANCH ]]; then REGRESSION=false; fi;
+ - if [[ "$CI_COMMIT_BRANCH" = "$COVFUZZ_BRANCH" ]]; then REGRESSION=false; fi;
artifacts:
paths:
- corpus
diff --git a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..feed4c47157
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.latest.gitlab-ci.yml
@@ -0,0 +1,64 @@
+# 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/Coverage-Fuzzing.gitlab-ci.yml
+
+# Read more about this feature https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing
+#
+# Configure coverage fuzzing 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/coverage_fuzzing/#available-cicd-variables
+
+variables:
+ # Which branch we want to run full fledged long running fuzzing jobs.
+ # All others will run fuzzing regression
+ COVFUZZ_BRANCH: "$CI_DEFAULT_BRANCH"
+ # This is using semantic version and will always download latest v3 gitlab-cov-fuzz release
+ COVFUZZ_VERSION: v3
+ # This is for users who have an offline environment and will have to replicate gitlab-cov-fuzz release binaries
+ # to their own servers
+ COVFUZZ_URL_PREFIX: "https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw"
+
+
+coverage_fuzzing_unlicensed:
+ stage: .pre
+ allow_failure: true
+ rules:
+ - if: $GITLAB_FEATURES !~ /\bcoverage_fuzzing\b/ && $COVFUZZ_DISABLED == null
+ script:
+ - echo "ERROR Your GitLab project is missing licensing for Coverage Fuzzing" && exit 1
+
+.fuzz_base:
+ stage: fuzz
+ allow_failure: true
+ before_script:
+ - export COVFUZZ_JOB_TOKEN="$CI_JOB_TOKEN"
+ - export COVFUZZ_PRIVATE_TOKEN="$CI_PRIVATE_TOKEN"
+ - export COVFUZZ_PROJECT_PATH="$CI_PROJECT_PATH"
+ - export COVFUZZ_PROJECT_ID="$CI_PROJECT_ID"
+ - if [ -x "$(command -v apt-get)" ] ; then apt-get update && apt-get install -y wget; fi
+ - wget -O gitlab-cov-fuzz "${COVFUZZ_URL_PREFIX}"/"${COVFUZZ_VERSION}"/binaries/gitlab-cov-fuzz_Linux_x86_64
+ - chmod a+x gitlab-cov-fuzz
+ - export REGRESSION=true
+ - if [[ "$CI_COMMIT_BRANCH" = "$COVFUZZ_BRANCH" ]]; then REGRESSION=false; fi;
+ artifacts:
+ paths:
+ - corpus
+ - crashes
+ - gl-coverage-fuzzing-report.json
+ reports:
+ coverage_fuzzing: gl-coverage-fuzzing-report.json
+ when: always
+ rules:
+ - if: $COVFUZZ_DISABLED
+ when: never
+
+ # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
+ $GITLAB_FEATURES =~ /\bcoverage_fuzzing\b/
+
+ # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
+
+ # Add the job to branch pipelines.
+ - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bcoverage_fuzzing\b/
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
index 8aabf20c5df..a28914d082f 100644
--- a/lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml
@@ -40,6 +40,19 @@ dast_api:
- if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH &&
$CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
when: never
+
+ # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
+ $CI_GITLAB_FIPS_MODE == "true"
+ variables:
+ DAST_API_IMAGE_SUFFIX: "-fips"
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+
+ # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
+
+ # Add the job to branch pipelines.
- if: $CI_COMMIT_BRANCH &&
$CI_GITLAB_FIPS_MODE == "true"
variables:
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index 9d3b1f4316e..50e9bb5431d 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -52,6 +52,19 @@ dast:
- if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME &&
$REVIEW_DISABLED
when: never
+
+ # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
+ ($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+
+ # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
+
+ # Add the job to branch pipelines.
- if: $CI_COMMIT_BRANCH &&
($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
diff --git a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
index 3c4533d603e..2a5ac539a42 100644
--- a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
@@ -38,3 +38,8 @@ archive_project:
- ios_11-3
- xcode_9-3
- macos_10-13
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml b/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
index b8d284532bd..5fcbb251672 100644
--- a/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
@@ -111,3 +111,8 @@ tests:
# (e.g. integration tests, unit tests etc).
script:
- 'dotnet test --no-restore'
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
index 58e840da713..400226b415d 100644
--- a/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
@@ -36,3 +36,8 @@ build:
artifacts:
paths:
- ./*.ipa
+
+deploy:
+ stage: deploy
+ script: echo "Define your deployment script!"
+ environment: production
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index c5664ef1cfb..2dc7bbc391e 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -140,7 +140,7 @@ module Gitlab
def being_watched?
Gitlab::Redis::SharedState.with do |redis|
- redis.exists(being_watched_cache_key)
+ redis.exists?(being_watched_cache_key) # rubocop:disable CodeReuse/ActiveRecord
end
end
diff --git a/lib/gitlab/ci/variables/builder.rb b/lib/gitlab/ci/variables/builder.rb
index 528d72c9bcc..cf5f04215ad 100644
--- a/lib/gitlab/ci/variables/builder.rb
+++ b/lib/gitlab/ci/variables/builder.rb
@@ -11,6 +11,7 @@ module Gitlab
@instance_variables_builder = Builder::Instance.new
@project_variables_builder = Builder::Project.new(project)
@group_variables_builder = Builder::Group.new(project&.group)
+ @release_variables_builder = Builder::Release.new(release)
end
def scoped_variables(job, environment:, dependencies:)
@@ -28,6 +29,7 @@ module Gitlab
variables.concat(secret_project_variables(environment: environment))
variables.concat(pipeline.variables)
variables.concat(pipeline_schedule_variables)
+ variables.concat(release_variables)
end
end
@@ -106,18 +108,26 @@ module Gitlab
end
end
+ def release_variables
+ strong_memoize(:release_variables) do
+ release_variables_builder.variables
+ end
+ end
+
private
attr_reader :pipeline
attr_reader :instance_variables_builder
attr_reader :project_variables_builder
attr_reader :group_variables_builder
+ attr_reader :release_variables_builder
delegate :project, to: :pipeline
def predefined_variables(job)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_JOB_NAME', value: job.name)
+ variables.append(key: 'CI_JOB_NAME_SLUG', value: job_name_slug(job))
variables.append(key: 'CI_JOB_STAGE', value: job.stage_name)
variables.append(key: 'CI_JOB_MANUAL', value: 'true') if job.action?
variables.append(key: 'CI_PIPELINE_TRIGGERED', value: 'true') if job.trigger_request
@@ -145,6 +155,10 @@ module Gitlab
end
end
+ def job_name_slug(job)
+ job.name && Gitlab::Utils.slugify(job.name)
+ end
+
def ci_node_total_value(job)
parallel = job.options&.dig(:parallel)
parallel = parallel.dig(:total) if parallel.is_a?(Hash)
@@ -166,6 +180,12 @@ module Gitlab
container[args] = yield
end
end
+
+ def release
+ return unless @pipeline.tag?
+
+ project.releases.find_by_tag(@pipeline.ref)
+ end
end
end
end
diff --git a/lib/gitlab/ci/variables/builder/release.rb b/lib/gitlab/ci/variables/builder/release.rb
new file mode 100644
index 00000000000..25f3d8446c5
--- /dev/null
+++ b/lib/gitlab/ci/variables/builder/release.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ class Builder
+ class Release
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :release
+
+ DESCRIPTION_LIMIT = 1024
+
+ def initialize(release)
+ @release = release
+ end
+
+ def variables
+ strong_memoize(:variables) do
+ ::Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ next variables unless release
+
+ if release.description
+ variables.append(
+ key: 'CI_RELEASE_DESCRIPTION',
+ value: release.description.truncate(DESCRIPTION_LIMIT),
+ raw: true)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index 52673d03e69..b6d6e1a3e5f 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -72,7 +72,7 @@ module Gitlab
Collection.new(@variables.reject(&block))
end
- def expand_value(value, keep_undefined: false, expand_file_vars: true)
+ def expand_value(value, keep_undefined: false, expand_file_vars: true, project: nil)
value.gsub(Item::VARIABLES_REGEXP) do
match = Regexp.last_match # it is either a valid variable definition or a ($$ / %%)
full_match = match[0]
@@ -88,6 +88,16 @@ module Gitlab
if variable # VARIABLE_NAME is an existing variable
next variable.value unless variable.file?
+ # Will be cleaned up with https://gitlab.com/gitlab-org/gitlab/-/issues/378266
+ if project
+ # We only log if `project` exists to make sure it is called from `Ci::BuildRunnerPresenter`
+ # when the variables are sent to Runner.
+ Gitlab::AppJsonLogger.info(
+ event: 'file_variable_is_referenced_in_another_variable',
+ project_id: project.id
+ )
+ end
+
expand_file_vars ? variable.value : full_match
elsif keep_undefined
full_match # we do not touch the variable definition
@@ -97,7 +107,7 @@ module Gitlab
end
end
- def sort_and_expand_all(keep_undefined: false, expand_file_vars: true)
+ def sort_and_expand_all(keep_undefined: false, expand_file_vars: true, project: nil)
sorted = Sort.new(self)
return self.class.new(self, sorted.errors) unless sorted.valid?
@@ -112,7 +122,8 @@ module Gitlab
# expand variables as they are added
variable = item.to_runner_variable
variable[:value] = new_collection.expand_value(variable[:value], keep_undefined: keep_undefined,
- expand_file_vars: expand_file_vars)
+ expand_file_vars: expand_file_vars,
+ project: project)
new_collection.append(variable)
end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index f203f88442d..5c3864362da 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -32,18 +32,16 @@ module Gitlab
end
end
- def stage_builds_attributes(stage)
- jobs.values
- .select { |job| job[:stage] == stage }
- .map { |job| build_attributes(job[:name]) }
- end
-
def workflow_rules
@workflow_rules ||= @ci_config.workflow_rules
end
+ def workflow_name
+ @workflow_name ||= @ci_config.workflow_name&.strip
+ end
+
def root_variables
- @root_variables ||= transform_to_array(variables)
+ @root_variables ||= transform_to_array(@ci_config.variables)
end
def jobs
@@ -58,6 +56,38 @@ module Gitlab
@included_templates ||= @ci_config.included_templates
end
+ def variables_with_data
+ @ci_config.variables_with_data
+ end
+
+ def yaml_variables_for(job_name)
+ job = jobs[job_name]
+
+ return [] unless job
+
+ Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
+ from: root_variables,
+ to: job[:job_variables],
+ inheritance: job.fetch(:root_variables_inheritance, true)
+ )
+ end
+
+ def stage_for(job_name)
+ jobs.dig(job_name, :stage)
+ end
+
+ def config_metadata
+ @ci_config&.metadata || {}
+ end
+
+ private
+
+ def stage_builds_attributes(stage)
+ jobs.values
+ .select { |job| job[:stage] == stage }
+ .map { |job| build_attributes(job[:name]) }
+ end
+
def build_attributes(name)
job = jobs.fetch(name.to_sym, {})
@@ -103,36 +133,6 @@ module Gitlab
}.compact }.compact
end
- def variables_with_data
- @ci_config.variables_with_data
- end
-
- def yaml_variables_for(job_name)
- job = jobs[job_name]
-
- return [] unless job
-
- Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
- from: root_variables,
- to: job[:job_variables],
- inheritance: job.fetch(:root_variables_inheritance, true)
- )
- end
-
- def stage_for(job_name)
- jobs.dig(job_name, :stage)
- end
-
- def config_metadata
- @ci_config&.metadata || {}
- end
-
- private
-
- def variables
- @variables ||= @ci_config.variables
- end
-
def release(job)
job[:release]
end
diff --git a/lib/gitlab/config/entry/legacy_validation_helpers.rb b/lib/gitlab/config/entry/legacy_validation_helpers.rb
index be7d26fed4e..415f6f77214 100644
--- a/lib/gitlab/config/entry/legacy_validation_helpers.rb
+++ b/lib/gitlab/config/entry/legacy_validation_helpers.rb
@@ -50,12 +50,6 @@ module Gitlab
variables.values.flatten(1).all?(&method(:validate_alphanumeric))
end
- def validate_string_or_hash_value_variables(variables, allowed_value_data)
- variables.is_a?(Hash) &&
- variables.keys.all?(&method(:validate_alphanumeric)) &&
- variables.values.all? { |value| validate_string_or_hash_value_variable(value, allowed_value_data) }
- end
-
def validate_alphanumeric(value)
validate_string(value) || validate_integer(value)
end
@@ -68,14 +62,6 @@ module Gitlab
value.is_a?(String) || value.is_a?(Symbol)
end
- def validate_string_or_hash_value_variable(value, allowed_value_data)
- if value.is_a?(Hash)
- (value.keys - allowed_value_data).empty? && value.values.all?(&method(:validate_alphanumeric))
- else
- validate_alphanumeric(value)
- end
- end
-
def validate_regexp(value)
Gitlab::UntrustedRegexp::RubySyntax.valid?(value)
end
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
index 337cfbc5287..b88a6766d92 100644
--- a/lib/gitlab/config/entry/validators.rb
+++ b/lib/gitlab/config/entry/validators.rb
@@ -44,7 +44,7 @@ module Gitlab
mutually_exclusive_keys = value.try(:keys).to_a & options[:in]
if mutually_exclusive_keys.length > 1
- record.errors.add(attribute, "please use only one the following keys: " +
+ record.errors.add(attribute, "please use only one of the following keys: " +
mutually_exclusive_keys.join(', '))
end
end
@@ -304,15 +304,12 @@ module Gitlab
end
end
- # This will be removed with the FF `ci_variables_refactoring_to_variable`.
class VariablesValidator < ActiveModel::EachValidator
include LegacyValidationHelpers
def validate_each(record, attribute, value)
if options[:array_values]
validate_key_array_values(record, attribute, value)
- elsif options[:allowed_value_data]
- validate_key_hash_values(record, attribute, value, options[:allowed_value_data])
else
validate_key_values(record, attribute, value)
end
@@ -329,12 +326,6 @@ module Gitlab
record.errors.add(attribute, 'should be a hash of key value pairs, value can be an array')
end
end
-
- def validate_key_hash_values(record, attribute, value, allowed_value_data)
- unless validate_string_or_hash_value_variables(value, allowed_value_data)
- record.errors.add(attribute, 'should be a hash of key value pairs, value can be a hash')
- end
- end
end
class AlphanumericValidator < ActiveModel::EachValidator
diff --git a/lib/gitlab/config_checker/external_database_checker.rb b/lib/gitlab/config_checker/external_database_checker.rb
index 54320b7ff9a..64950fb4eef 100644
--- a/lib/gitlab/config_checker/external_database_checker.rb
+++ b/lib/gitlab/config_checker/external_database_checker.rb
@@ -5,22 +5,29 @@ module Gitlab
module ExternalDatabaseChecker
extend self
+ PG_REQUIREMENTS_LINK =
+ '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
+
def check
- return [] if ApplicationRecord.database.postgresql_minimum_supported_version?
+ unsupported_database = Gitlab::Database
+ .database_base_models
+ .map { |_, model| Gitlab::Database::Reflection.new(model) }
+ .reject(&:postgresql_minimum_supported_version?)
- [
+ unsupported_database.map do |database|
{
type: 'warning',
message: _('You are using PostgreSQL %{pg_version_current}, but PostgreSQL ' \
'%{pg_version_minimum} is required for this version of GitLab. ' \
'Please upgrade your environment to a supported PostgreSQL version, ' \
- 'see %{pg_requirements_url} for details.') % {
- pg_version_current: ApplicationRecord.database.version,
- pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
- pg_requirements_url: '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
- }
+ 'see %{pg_requirements_url} for details.') % \
+ {
+ pg_version_current: database.version,
+ pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
+ pg_requirements_url: PG_REQUIREMENTS_LINK
+ }
}
- ]
+ end
end
end
end
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index 320ebe5e80f..a75c7c539ae 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -63,6 +63,7 @@ module Gitlab
def hook_attrs(pipeline)
{
id: pipeline.id,
+ iid: pipeline.iid,
ref: pipeline.source_ref,
tag: pipeline.tag,
sha: pipeline.sha,
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index 45f52765d0f..92cafd1d00e 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -67,11 +67,11 @@ module Gitlab
end
event :finish do
- transition any => :finished
+ transition [:paused, :finished, :active, :finalizing] => :finished
end
event :failure do
- transition any => :failed
+ transition [:failed, :finalizing, :active] => :failed
end
event :finalize do
diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml
index 5725d7a4503..c4a9cf8b80f 100644
--- a/lib/gitlab/database/gitlab_schemas.yml
+++ b/lib/gitlab/database/gitlab_schemas.yml
@@ -99,6 +99,7 @@ ci_pipeline_messages: :gitlab_ci
ci_pipeline_schedules: :gitlab_ci
ci_pipeline_schedule_variables: :gitlab_ci
ci_pipelines_config: :gitlab_ci
+ci_pipeline_metadata: :gitlab_ci
ci_pipelines: :gitlab_ci
ci_pipeline_variables: :gitlab_ci
ci_platform_metrics: :gitlab_ci
@@ -263,6 +264,8 @@ 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
+incident_management_timeline_event_tags: :gitlab_main
+incident_management_timeline_event_tag_links: :gitlab_main
index_statuses: :gitlab_main
in_product_marketing_emails: :gitlab_main
insights: :gitlab_main
@@ -389,6 +392,7 @@ packages_nuget_dependency_link_metadata: :gitlab_main
packages_nuget_metadata: :gitlab_main
packages_package_file_build_infos: :gitlab_main
packages_package_files: :gitlab_main
+packages_rpm_repository_files: :gitlab_main
packages_packages: :gitlab_main
packages_pypi_metadata: :gitlab_main
packages_rubygems_metadata: :gitlab_main
@@ -447,6 +451,7 @@ projects: :gitlab_main
projects_sync_events: :gitlab_main
project_statistics: :gitlab_main
project_topics: :gitlab_main
+project_wiki_repository_states: :gitlab_main
prometheus_alert_events: :gitlab_main
prometheus_alerts: :gitlab_main
prometheus_metrics: :gitlab_main
@@ -545,6 +550,7 @@ user_group_callouts: :gitlab_main
user_project_callouts: :gitlab_main
user_highest_roles: :gitlab_main
user_interacted_projects: :gitlab_main
+user_phone_number_validations: :gitlab_main
user_permission_export_uploads: :gitlab_main
user_preferences: :gitlab_main
users: :gitlab_main
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
index 40b76a1c028..0881025b425 100644
--- a/lib/gitlab/database/load_balancing/load_balancer.rb
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -105,16 +105,25 @@ module Gitlab
def read_write
connection = nil
transaction_open = nil
+ attempts = 3
+
+ if prevent_load_balancer_retries_in_transaction?
+ attempts = 1 if pool.connection.transaction_open?
+ end
+
# In the event of a failover the primary may be briefly unavailable.
# Instead of immediately grinding to a halt we'll retry the operation
# a few times.
- retry_with_backoff do
+ # It is not possible preserve transaction state during a retry, so we do not retry in that case.
+ retry_with_backoff(attempts: attempts) do |attempt|
connection = pool.connection
transaction_open = connection.transaction_open?
yield connection
rescue StandardError => e
- if transaction_open && connection_error?(e)
+ # No leaking will happen on the final attempt. Leaks are caused by subsequent retries
+ not_final_attempt = attempt && attempt < attempts
+ if transaction_open && connection_error?(e) && not_final_attempt
::Gitlab::Database::LoadBalancing::Logger.warn(
event: :transaction_leak,
message: 'A write transaction has leaked during database fail-over'
@@ -171,7 +180,7 @@ module Gitlab
end
# Yields a block, retrying it upon error using an exponential backoff.
- def retry_with_backoff(retries = 3, time = 2)
+ def retry_with_backoff(attempts: 3, time: 2)
# In CI we only use the primary, but databases may not always be
# available (or take a few seconds to become available). Retrying in
# this case can slow down CI jobs. In addition, retrying with _only_
@@ -183,12 +192,12 @@ module Gitlab
# replicas were configured.
return yield if primary_only?
- retried = 0
+ attempt = 1
last_error = nil
- while retried < retries
+ while attempt <= attempts
begin
- return yield
+ return yield attempt # Yield the current attempt count
rescue StandardError => error
raise error unless connection_error?(error)
@@ -198,7 +207,7 @@ module Gitlab
last_error = error
sleep(time)
- retried += 1
+ attempt += 1
time **= 2
end
end
@@ -332,6 +341,10 @@ module Gitlab
row = ar_connection.select_all(sql).first
row['location'] if row
end
+
+ def prevent_load_balancer_retries_in_transaction?
+ Gitlab::Utils.to_boolean(ENV['PREVENT_LOAD_BALANCER_RETRIES_IN_TRANSACTION'], default: false)
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
index 5d91292b8de..3180289ec69 100644
--- a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
+++ b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
@@ -97,8 +97,14 @@ module Gitlab
end
def databases_in_sync?(wal_locations)
+ locations = if Feature.enabled?(:indifferent_wal_location_keys)
+ wal_locations.with_indifferent_access
+ else
+ wal_locations
+ end
+
::Gitlab::Database::LoadBalancing.each_load_balancer.all? do |lb|
- if (location = wal_locations[lb.name])
+ if (location = locations[lb.name])
lb.select_up_to_date_host(location)
else
# If there's no entry for a load balancer it means the Sidekiq
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index e574422ce11..df40e3b3868 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -296,12 +296,11 @@ module Gitlab
with_lock_retries do
execute("LOCK TABLE #{target}, #{source} IN SHARE ROW EXCLUSIVE MODE") if reverse_lock_order
-
execute <<-EOF.strip_heredoc
ALTER TABLE #{source}
ADD CONSTRAINT #{options[:name]}
- FOREIGN KEY (#{options[:column]})
- REFERENCES #{target} (#{target_column})
+ FOREIGN KEY (#{multiple_columns(options[:column])})
+ REFERENCES #{target} (#{multiple_columns(target_column)})
#{on_delete_statement(options[:on_delete])}
NOT VALID;
EOF
@@ -355,7 +354,7 @@ module Gitlab
# - For standard rails foreign keys the prefix is `fk_rails_`
#
def concurrent_foreign_key_name(table, column, prefix: 'fk_')
- identifier = "#{table}_#{column}_fk"
+ identifier = "#{table}_#{multiple_columns(column, separator: '_')}_fk"
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
"#{prefix}#{hashed_identifier}"
@@ -1503,6 +1502,26 @@ into similar problems in the future (e.g. when new tables are created).
SQL
end
+ def drop_constraint(table_name, constraint_name, cascade: false)
+ execute <<~SQL
+ ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(constraint_name)} #{cascade_statement(cascade)}
+ SQL
+ end
+
+ def add_primary_key_using_index(table_name, pk_name, index_to_use)
+ execute <<~SQL
+ ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_table_name(pk_name)} PRIMARY KEY USING INDEX #{quote_table_name(index_to_use)}
+ SQL
+ end
+
+ def swap_primary_key(table_name, primary_key_name, index_to_use)
+ with_lock_retries(raise_on_exhaustion: true) do
+ drop_constraint(table_name, primary_key_name, cascade: true)
+ add_primary_key_using_index(table_name, primary_key_name, index_to_use)
+ end
+ end
+ alias_method :unswap_primary_key, :swap_primary_key
+
def drop_sequence(table_name, column_name, sequence_name)
execute <<~SQL
ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} DROP DEFAULT;
@@ -1519,6 +1538,14 @@ into similar problems in the future (e.g. when new tables are created).
private
+ def multiple_columns(columns, separator: ', ')
+ Array.wrap(columns).join(separator)
+ end
+
+ def cascade_statement(cascade)
+ cascade ? 'CASCADE' : ''
+ end
+
def create_temporary_columns_and_triggers(table, columns, primary_key: :id, data_type: :bigint)
unless table_exists?(table)
raise "Table #{table} does not exist"
diff --git a/lib/gitlab/database/migrations/base_background_runner.rb b/lib/gitlab/database/migrations/base_background_runner.rb
index 76982a9da9b..dbb85bad95c 100644
--- a/lib/gitlab/database/migrations/base_background_runner.rb
+++ b/lib/gitlab/database/migrations/base_background_runner.rb
@@ -4,10 +4,11 @@ module Gitlab
module Database
module Migrations
class BaseBackgroundRunner
- attr_reader :result_dir
+ attr_reader :result_dir, :connection
- def initialize(result_dir:)
+ def initialize(result_dir:, connection:)
@result_dir = result_dir
+ @connection = connection
end
def jobs_by_migration_name
@@ -45,7 +46,7 @@ module Gitlab
instrumentation.observe(version: nil,
name: batch_names.next,
- connection: ActiveRecord::Migration.connection) do
+ connection: connection) do
run_job(j)
end
end
diff --git a/lib/gitlab/database/migrations/runner.rb b/lib/gitlab/database/migrations/runner.rb
index 4404b5bf961..85dc6051c7c 100644
--- a/lib/gitlab/database/migrations/runner.rb
+++ b/lib/gitlab/database/migrations/runner.rb
@@ -6,40 +6,68 @@ module Gitlab
class Runner
BASE_RESULT_DIR = Rails.root.join('tmp', 'migration-testing').freeze
METADATA_FILENAME = 'metadata.json'
- SCHEMA_VERSION = 3 # Version of the output format produced by the runner
+ SCHEMA_VERSION = 4 # Version of the output format produced by the runner
class << self
- def up
- Runner.new(direction: :up, migrations: migrations_for_up, result_dir: BASE_RESULT_DIR.join('up'))
+ def up(database:, legacy_mode: false)
+ within_context_for_database(database) do
+ Runner.new(direction: :up, database: database, migrations: migrations_for_up(database), legacy_mode: legacy_mode)
+ end
end
- def down
- Runner.new(direction: :down, migrations: migrations_for_down, result_dir: BASE_RESULT_DIR.join('down'))
+ def down(database:, legacy_mode: false)
+ within_context_for_database(database) do
+ Runner.new(direction: :down, database: database, migrations: migrations_for_down(database), legacy_mode: legacy_mode)
+ end
end
def background_migrations
TestBackgroundRunner.new(result_dir: BASE_RESULT_DIR.join('background_migrations'))
end
- def batched_background_migrations(for_database:)
+ def batched_background_migrations(for_database:, legacy_mode: false)
runner = nil
+ result_dir = if legacy_mode
+ BASE_RESULT_DIR.join('background_migrations')
+ else
+ BASE_RESULT_DIR.join(for_database.to_s, 'background_migrations')
+ end
+
# Only one loop iteration since we pass `only:` here
Gitlab::Database::EachDatabase.each_database_connection(only: for_database) do |connection|
runner = Gitlab::Database::Migrations::TestBatchedBackgroundRunner
- .new(result_dir: BASE_RESULT_DIR.join('background_migrations'), connection: connection)
+ .new(result_dir: result_dir, connection: connection)
end
runner
end
def migration_context
- @migration_context ||= ApplicationRecord.connection.migration_context
+ # We're mirroring rails internal migration code, which requires that
+ # ActiveRecord::Base has connected to the current database. The correct database is chosen by
+ # within_context_for_database
+ ActiveRecord::Base.connection.migration_context # rubocop:disable Database/MultipleDatabases
+ end
+
+ # rubocop:disable Database/MultipleDatabases
+ def within_context_for_database(database)
+ original_db_config = ActiveRecord::Base.connection_db_config
+ # The config only works if passed a string
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: database.to_s)
+ raise ArgumentError, "Cannot find a database configuration for #{database}" unless db_config
+
+ ActiveRecord::Base.establish_connection(db_config) # rubocop:disable Database/EstablishConnection
+
+ yield
+ ensure
+ ActiveRecord::Base.establish_connection(original_db_config) # rubocop:disable Database/EstablishConnection
end
+ # rubocop:enable Database/MultipleDatabases
private
- def migrations_for_up
+ def migrations_for_up(database)
existing_versions = migration_context.get_all_versions.to_set
migration_context.migrations.reject do |migration|
@@ -51,7 +79,7 @@ module Gitlab
`git diff --name-only origin/HEAD...HEAD db/post_migrate db/migrate`.split("\n")
end
- def migrations_for_down
+ def migrations_for_down(database)
versions_this_branch = migration_file_names_this_branch.map do |m_name|
m_name.match(%r{^db/(post_)?migrate/(\d+)}) { |m| m.captures[1]&.to_i }
end.to_set
@@ -65,14 +93,21 @@ module Gitlab
attr_reader :direction, :result_dir, :migrations
- delegate :migration_context, to: :class
+ delegate :migration_context, :within_context_for_database, to: :class
- def initialize(direction:, migrations:, result_dir:)
+ def initialize(direction:, database:, migrations:, legacy_mode: false)
raise "Direction must be up or down" unless %i[up down].include?(direction)
@direction = direction
@migrations = migrations
- @result_dir = result_dir
+ @result_dir = if legacy_mode
+ BASE_RESULT_DIR.join(direction.to_s)
+ else
+ BASE_RESULT_DIR.join(database.to_s, direction.to_s)
+ end
+
+ @database = database
+ @legacy_mode = legacy_mode
end
def run
@@ -86,14 +121,22 @@ module Gitlab
instrumentation = Instrumentation.new(result_dir: result_dir)
- sorted_migrations.each do |migration|
- 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
+ within_context_for_database(@database) do
+ sorted_migrations.each do |migration|
+ 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
end
ensure
metadata_filename = File.join(result_dir, METADATA_FILENAME)
- File.write(metadata_filename, { version: SCHEMA_VERSION }.to_json)
+ version = if @legacy_mode
+ 3
+ else
+ SCHEMA_VERSION
+ end
+
+ File.write(metadata_filename, { database: @database.to_s, version: version }.to_json)
# We clear the cache here to mirror the cache clearing that happens at the end of `db:migrate` tasks
# This clearing makes subsequent rake tasks in the same execution pick up database schema changes caused by
diff --git a/lib/gitlab/database/migrations/test_background_runner.rb b/lib/gitlab/database/migrations/test_background_runner.rb
index 6da2e098d43..65db330b1a6 100644
--- a/lib/gitlab/database/migrations/test_background_runner.rb
+++ b/lib/gitlab/database/migrations/test_background_runner.rb
@@ -5,7 +5,7 @@ module Gitlab
module Migrations
class TestBackgroundRunner < BaseBackgroundRunner
def initialize(result_dir:)
- super(result_dir: result_dir)
+ super(result_dir: result_dir, connection: ActiveRecord::Migration.connection)
@job_coordinator = Gitlab::BackgroundMigration.coordinator_for_database(Gitlab::Database::MAIN_DATABASE_NAME)
end
diff --git a/lib/gitlab/database/migrations/test_batched_background_runner.rb b/lib/gitlab/database/migrations/test_batched_background_runner.rb
index c27ae6a2c5d..46855ca1921 100644
--- a/lib/gitlab/database/migrations/test_batched_background_runner.rb
+++ b/lib/gitlab/database/migrations/test_batched_background_runner.rb
@@ -5,65 +5,73 @@ module Gitlab
module Migrations
class TestBatchedBackgroundRunner < BaseBackgroundRunner
include Gitlab::Database::DynamicModelHelpers
- attr_reader :connection
def initialize(result_dir:, connection:)
- super(result_dir: result_dir)
+ super(result_dir: result_dir, connection: connection)
@connection = connection
end
def jobs_by_migration_name
- Gitlab::Database::BackgroundMigration::BatchedMigration
- .executable
- .created_after(3.hours.ago) # Simple way to exclude migrations already running before migration testing
- .to_h do |migration|
- batching_strategy = migration.batch_class.new(connection: connection)
-
- smallest_batch_start = migration.next_min_value
-
- table_max_value = define_batchable_model(migration.table_name, connection: connection)
- .maximum(migration.column_name)
-
- largest_batch_start = table_max_value - migration.batch_size
-
- # variance is the portion of the batch range that we shrink between variance * 0 and variance * 1
- # to pick actual batches to sample.
- variance = largest_batch_start - smallest_batch_start
-
- batch_starts = uniform_fractions
- .lazy # frac varies from 0 to 1, values in smallest_batch_start..largest_batch_start
- .map { |frac| (variance * frac).to_i + smallest_batch_start }
-
- # Track previously run batches so that we stop sampling if a new batch would intersect an older one
- completed_batches = []
-
- jobs_to_sample = batch_starts
- # Stop sampling if a batch would intersect a previous batch
- .take_while { |start| completed_batches.none? { |batch| batch.cover?(start) } }
- .map do |batch_start|
- next_bounds = batching_strategy.next_batch(
- migration.table_name,
- migration.column_name,
- batch_min_value: batch_start,
- batch_size: migration.batch_size,
- job_arguments: migration.job_arguments
- )
-
- batch_min, batch_max = next_bounds
-
- job = migration.create_batched_job!(batch_min, batch_max)
-
- completed_batches << (batch_min..batch_max)
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .executable
+ .created_after(3.hours.ago) # Simple way to exclude migrations already running before migration testing
+ .to_h do |migration|
+ batching_strategy = migration.batch_class.new(connection: connection)
+
+ smallest_batch_start = migration.next_min_value
+
+ table_max_value = define_batchable_model(migration.table_name, connection: connection)
+ .maximum(migration.column_name)
+
+ largest_batch_start = table_max_value - migration.batch_size
+
+ # variance is the portion of the batch range that we shrink between variance * 0 and variance * 1
+ # to pick actual batches to sample.
+ variance = largest_batch_start - smallest_batch_start
+
+ batch_starts = uniform_fractions
+ .lazy # frac varies from 0 to 1, values in smallest_batch_start..largest_batch_start
+ .map { |frac| (variance * frac).to_i + smallest_batch_start }
+
+ # Track previously run batches so that we stop sampling if a new batch would intersect an older one
+ completed_batches = []
+
+ jobs_to_sample = batch_starts
+ # Stop sampling if a batch would intersect a previous batch
+ .take_while { |start| completed_batches.none? { |batch| batch.cover?(start) } }
+ .map do |batch_start|
+ # The current block is lazily evaluated as part of the jobs_to_sample enumerable
+ # so it executes after the enclosing using_connection block has already executed
+ # Therefore we need to re-associate with the explicit connection again
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ next_bounds = batching_strategy.next_batch(
+ migration.table_name,
+ migration.column_name,
+ batch_min_value: batch_start,
+ batch_size: migration.batch_size,
+ job_arguments: migration.job_arguments
+ )
+
+ batch_min, batch_max = next_bounds
+
+ job = migration.create_batched_job!(batch_min, batch_max)
+
+ completed_batches << (batch_min..batch_max)
+
+ job
+ end
+ end
- job
+ [migration.job_class_name, jobs_to_sample]
end
-
- [migration.job_class_name, jobs_to_sample]
end
end
def run_job(job)
- Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper.new(connection: connection).perform(job)
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper.new(connection: connection).perform(job)
+ end
end
def uniform_fractions
diff --git a/lib/gitlab/database/partitioning/convert_table_to_first_list_partition.rb b/lib/gitlab/database/partitioning/convert_table_to_first_list_partition.rb
index f45cf02ec9b..23a8dc0b44f 100644
--- a/lib/gitlab/database/partitioning/convert_table_to_first_list_partition.rb
+++ b/lib/gitlab/database/partitioning/convert_table_to_first_list_partition.rb
@@ -6,8 +6,6 @@ module Gitlab
class ConvertTableToFirstListPartition
UnableToPartition = Class.new(StandardError)
- include Gitlab::Database::MigrationHelpers
-
SQL_STATEMENT_SEPARATOR = ";\n\n"
attr_reader :partitioning_column, :table_name, :parent_table_name, :zero_partition_value
@@ -175,9 +173,21 @@ module Gitlab
def alter_sequence_statements(old_table:, new_table:)
sequences_owned_by(old_table).map do |seq_info|
seq_name, column_name = seq_info.values_at(:name, :column_name)
- <<~SQL.chomp
+
+ statement_parts = []
+
+ # If a different user owns the old table, the conversion process will fail to reassign the sequence
+ # ownership to the new parent table (as it will be owned by the current user).
+ # Force the old table to be owned by the current user in that case.
+ unless current_user_owns_table?(old_table)
+ statement_parts << set_current_user_owns_table_statement(old_table)
+ end
+
+ statement_parts << <<~SQL.chomp
ALTER SEQUENCE #{quote_table_name(seq_name)} OWNED BY #{quote_table_name(new_table)}.#{quote_column_name(column_name)}
SQL
+
+ statement_parts.join(SQL_STATEMENT_SEPARATOR)
end
end
@@ -208,6 +218,23 @@ module Gitlab
{ name: name, column_name: column_name }
end
end
+
+ def table_owner(table_name)
+ connection.select_value(<<~SQL, nil, [table_name])
+ SELECT tableowner FROM pg_tables WHERE tablename = $1
+ SQL
+ end
+
+ def current_user_owns_table?(table_name)
+ current_user = connection.select_value('select current_user')
+ table_owner(table_name) == current_user
+ end
+
+ def set_current_user_owns_table_statement(table_name)
+ <<~SQL.chomp
+ ALTER TABLE #{connection.quote_table_name(table_name)} OWNER TO CURRENT_USER
+ SQL
+ end
end
end
end
diff --git a/lib/gitlab/database/query_analyzers/base.rb b/lib/gitlab/database/query_analyzers/base.rb
index 5f321ece962..9a52a4f6e23 100644
--- a/lib/gitlab/database/query_analyzers/base.rb
+++ b/lib/gitlab/database/query_analyzers/base.rb
@@ -8,7 +8,7 @@ module Gitlab
QueryAnalyzerError = Class.new(Exception) # rubocop:disable Lint/InheritException
def self.suppressed?
- Thread.current[self.suppress_key]
+ Thread.current[self.suppress_key] || @suppress_in_rspec
end
def self.requires_tracking?(parsed)
@@ -19,6 +19,20 @@ module Gitlab
Thread.current[self.suppress_key] = value
end
+ # The other suppress= method stores the
+ # value in Thread.current because it is
+ # meant to work in a multi-threaded puma
+ # environment but this does not work
+ # correctly in capybara tests where we
+ # suppress in the rspec runner context but
+ # this does not take effect in the puma
+ # thread. As such we just suppress
+ # globally in RSpec since we don't run
+ # different tests concurrently.
+ class << self
+ attr_writer :suppress_in_rspec
+ end
+
def self.with_suppressed(value = true, &blk)
previous = self.suppressed?
self.suppress = value
diff --git a/lib/gitlab/database/reflection.rb b/lib/gitlab/database/reflection.rb
index 33c965cb150..6c4e46728d4 100644
--- a/lib/gitlab/database/reflection.rb
+++ b/lib/gitlab/database/reflection.rb
@@ -124,7 +124,11 @@ module Gitlab
# - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-servers
# - https://docs.microsoft.com/en-us/azure/postgresql/concepts-servers#managing-your-server
# this database is present on both Flexible and Single server, so we should check the former first.
- 'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" }
+ 'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" },
+ # Based on
+ # - https://cloud.google.com/sql/docs/postgres/flags
+ # running a query to detect flag names that begin with 'alloydb
+ 'AlloyDB for PostgreSQL' => { statement: "SELECT name FROM pg_settings WHERE name LIKE 'alloydb%'" }
}.each do |flavor, conditions|
return flavor if connection.execute(conditions[:statement]).to_a.present?
rescue ActiveRecord::StatementInvalid => e
diff --git a/lib/gitlab/database/schema_helpers.rb b/lib/gitlab/database/schema_helpers.rb
index f96de13006f..2c7ca28942e 100644
--- a/lib/gitlab/database/schema_helpers.rb
+++ b/lib/gitlab/database/schema_helpers.rb
@@ -71,12 +71,17 @@ module Gitlab
"#{type}_#{hashed_identifier}"
end
- def with_lock_retries(&block)
- Gitlab::Database::WithLockRetries.new(
+ def with_lock_retries(*args, **kwargs, &block)
+ raise_on_exhaustion = !!kwargs.delete(:raise_on_exhaustion)
+ merged_args = {
connection: connection,
klass: self.class,
- logger: Gitlab::BackgroundMigration::Logger
- ).run(&block)
+ logger: Gitlab::BackgroundMigration::Logger,
+ allow_savepoints: true
+ }.merge(kwargs)
+
+ Gitlab::Database::WithLockRetries.new(**merged_args)
+ .run(raise_on_exhaustion: raise_on_exhaustion, &block)
end
def assert_not_in_transaction_block(scope:)
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 084ce63e36a..d6f5e45c034 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -82,16 +82,6 @@ module Gitlab
private
- def expiration
- return 1.day unless Feature.enabled?(:highlight_diffs_renewable_expiration, diffable.project)
-
- if Feature.enabled?(:highlight_diffs_short_renewable_expiration, diffable.project)
- EXPIRATION
- else
- 8.hours
- end
- end
-
def set_highlighted_diff_lines(diff_file, content)
diff_file.highlighted_diff_lines = content.map do |line|
Gitlab::Diff::Line.safe_init_from_hash(line)
@@ -147,7 +137,7 @@ module Gitlab
end
# HSETs have to have their expiration date manually updated
- pipeline.expire(key, expiration)
+ pipeline.expire(key, EXPIRATION)
end
record_memory_usage(fetch_memory_usage(redis, key))
@@ -197,14 +187,12 @@ module Gitlab
return {} unless file_paths.any?
results = []
- cache_key = key
- highlight_diffs_renewable_expiration_enabled = Feature.enabled?(:highlight_diffs_renewable_expiration, diffable.project)
- expiration_period = expiration
+ cache_key = key # Moving out redis calls for feature flags out of redis.pipelined
Gitlab::Redis::Cache.with do |redis|
redis.pipelined do |pipeline|
results = pipeline.hmget(cache_key, file_paths)
- pipeline.expire(key, expiration_period) if highlight_diffs_renewable_expiration_enabled
+ pipeline.expire(key, EXPIRATION)
end
end
diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb
index 7b31dd9926b..434893eab82 100644
--- a/lib/gitlab/email/handler/create_issue_handler.rb
+++ b/lib/gitlab/email/handler/create_issue_handler.rb
@@ -36,8 +36,14 @@ module Gitlab
validate_permission!(:create_issue)
+ result = create_issue
+ issue = result[:issue]
+
+ # issue won't be present only on unrecoverable errors
+ raise InvalidIssueError, result.errors.join(', ') if result.error? && issue.blank?
+
verify_record!(
- record: create_issue,
+ record: issue,
invalid_exception: InvalidIssueError,
record_name: 'issue')
end
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index 8e2c7559bc1..06365296a76 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -91,7 +91,7 @@ module Gitlab
end
def create_issue!
- @issue = ::Issues::CreateService.new(
+ result = ::Issues::CreateService.new(
project: project,
current_user: User.support_bot,
params: {
@@ -106,7 +106,9 @@ module Gitlab
spam_params: nil
).execute
- raise InvalidIssueError unless @issue.persisted?
+ raise InvalidIssueError if result.error?
+
+ @issue = result[:issue]
begin
::Issue::Email.create!(issue: @issue, email_message_id: mail.message_id)
diff --git a/lib/gitlab/email/message/in_product_marketing/trial.rb b/lib/gitlab/email/message/in_product_marketing/trial.rb
index 11a799886ab..720262816b4 100644
--- a/lib/gitlab/email/message/in_product_marketing/trial.rb
+++ b/lib/gitlab/email/message/in_product_marketing/trial.rb
@@ -42,11 +42,11 @@ module Gitlab
[
s_("InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"),
list([
- s_('InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels').html_safe % strong_options,
- s_('InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals').html_safe % strong_options,
- s_('InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection').html_safe % strong_options,
- s_('InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream').html_safe % strong_options
- ])
+ s_('InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels').html_safe % strong_options,
+ s_('InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals').html_safe % strong_options,
+ s_('InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection').html_safe % strong_options,
+ s_('InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream').html_safe % strong_options
+ ])
].join("\n"),
s_('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.'),
s_('InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process.')
diff --git a/lib/gitlab/email/message/in_product_marketing/verify.rb b/lib/gitlab/email/message/in_product_marketing/verify.rb
index d2a78b53e1f..3982a8b87fd 100644
--- a/lib/gitlab/email/message/in_product_marketing/verify.rb
+++ b/lib/gitlab/email/message/in_product_marketing/verify.rb
@@ -49,10 +49,10 @@ module Gitlab
[
nil,
list([
- s_('InProductMarketing|Start by %{performance_link}').html_safe % { performance_link: performance_link },
- s_('InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}').html_safe % { ci_template_link: ci_template_link },
- s_('InProductMarketing|And finally %{deploy_link} a Python application.').html_safe % { deploy_link: deploy_link }
- ]),
+ s_('InProductMarketing|Start by %{performance_link}').html_safe % { performance_link: performance_link },
+ s_('InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}').html_safe % { ci_template_link: ci_template_link },
+ s_('InProductMarketing|And finally %{deploy_link} a Python application.').html_safe % { deploy_link: deploy_link }
+ ]),
nil
][series]
end
diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb
index 34c674c3003..b1fd35184ac 100644
--- a/lib/gitlab/encoding_helper.rb
+++ b/lib/gitlab/encoding_helper.rb
@@ -73,8 +73,6 @@ module Gitlab
# This method escapes unsupported UTF-8 characters instead of deleting them
def encode_utf8_with_escaping!(message)
- return encode!(message) if Feature.disabled?(:escape_gitaly_refs)
-
message = force_encode_utf8(message)
return message if message.valid_encoding?
diff --git a/lib/gitlab/environment.rb b/lib/gitlab/environment.rb
index b1a9603d3a5..3c6ed696b9d 100644
--- a/lib/gitlab/environment.rb
+++ b/lib/gitlab/environment.rb
@@ -5,5 +5,9 @@ module Gitlab
def self.hostname
@hostname ||= ENV['HOSTNAME'] || Socket.gethostname
end
+
+ def self.qa_user_agent
+ ENV['GITLAB_QA_USER_AGENT']
+ end
end
end
diff --git a/lib/gitlab/event_store.rb b/lib/gitlab/event_store.rb
index b45970cb45a..023c8ace4d9 100644
--- a/lib/gitlab/event_store.rb
+++ b/lib/gitlab/event_store.rb
@@ -43,9 +43,18 @@ module Gitlab
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectPathChangedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectArchivedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectTransferedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker,
+ to: ::Projects::ProjectAttributesChangedEvent,
+ if: -> (event) { event.pages_related? }
+ store.subscribe ::Pages::InvalidateDomainCacheWorker,
+ to: ::Projects::ProjectFeaturesChangedEvent,
+ if: -> (event) { event.pages_related? }
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupTransferedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupPathChangedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupDeletedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainDeletedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainUpdatedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainCreatedEvent
store.subscribe ::MergeRequests::CreateApprovalEventWorker, to: ::MergeRequests::ApprovedEvent
store.subscribe ::MergeRequests::CreateApprovalNoteWorker, to: ::MergeRequests::ApprovedEvent
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index 75d07a36dcd..0b18a337707 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -118,7 +118,7 @@ module Gitlab
# Returns true if the key for this lease is set.
def exists?
Gitlab::Redis::SharedState.with do |redis|
- redis.exists(@redis_shared_state_key)
+ redis.exists?(@redis_shared_state_key) # rubocop:disable CodeReuse/ActiveRecord
end
end
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
deleted file mode 100644
index 142d0e55593..00000000000
--- a/lib/gitlab/experimentation.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: true
-
-# == Experimentation
-#
-# Utility module for A/B testing experimental features. Define your experiments in the `EXPERIMENTS` constant.
-# Experiment options:
-# - tracking_category (optional, used to set the category when tracking an experiment event)
-# - rollout_strategy: default is `:cookie` based rollout. We may also set it to `:user` based rollout
-#
-# The experiment is controlled by a Feature Flag (https://docs.gitlab.com/ee/development/feature_flags/controls.html),
-# which is named "#{experiment_key}_experiment_percentage" and *must* be set with a percentage and not be used for other purposes.
-#
-# To enable the experiment for 10% of the time:
-#
-# chatops: `/chatops run feature set experiment_key_experiment_percentage 10 --random`
-# console: `Feature.enable_percentage_of_time(:experiment_key_experiment_percentage, 10)`
-#
-# To disable the experiment:
-#
-# chatops: `/chatops run feature delete experiment_key_experiment_percentage`
-# console: `Feature.remove(:experiment_key_experiment_percentage)`
-#
-# To check the current rollout percentage:
-#
-# chatops: `/chatops run feature get experiment_key_experiment_percentage`
-# console: `Feature.get(:experiment_key_experiment_percentage).percentage_of_time_value`
-#
-
-# TODO: see https://gitlab.com/gitlab-org/gitlab/-/issues/217490
-module Gitlab
- module Experimentation
- EXPERIMENTS = {
- }.freeze
-
- class << self
- def get_experiment(experiment_key)
- return unless EXPERIMENTS.key?(experiment_key)
-
- ::Gitlab::Experimentation::Experiment.new(experiment_key, **EXPERIMENTS[experiment_key])
- end
-
- def active?(experiment_key)
- experiment = get_experiment(experiment_key)
- return false unless experiment
-
- experiment.active?
- end
-
- def in_experiment_group?(experiment_key, subject:)
- return false if subject.blank?
- return false unless active?(experiment_key)
-
- log_invalid_rollout(experiment_key, subject)
-
- experiment = get_experiment(experiment_key)
- return false unless experiment
-
- experiment.enabled_for_index?(index_for_subject(experiment, subject))
- end
-
- def rollout_strategy(experiment_key)
- experiment = get_experiment(experiment_key)
- return unless experiment
-
- experiment.rollout_strategy
- end
-
- def log_invalid_rollout(experiment_key, subject)
- return if valid_subject_for_rollout_strategy?(experiment_key, subject)
-
- logger = Gitlab::ExperimentationLogger.build
- logger.warn message: 'Subject must conform to the rollout strategy',
- experiment_key: experiment_key,
- subject: subject.class.to_s,
- rollout_strategy: rollout_strategy(experiment_key)
- end
-
- def valid_subject_for_rollout_strategy?(experiment_key, subject)
- case rollout_strategy(experiment_key)
- when :user
- subject.is_a?(User)
- when :group
- subject.is_a?(Group)
- when :cookie
- subject.nil? || subject.is_a?(String)
- else
- false
- end
- end
-
- private
-
- def index_for_subject(experiment, subject)
- index = Zlib.crc32("#{experiment.key}#{subject_id(subject)}")
-
- index % 100
- end
-
- def subject_id(subject)
- if subject.respond_to?(:to_global_id)
- subject.to_global_id.to_s
- elsif subject.respond_to?(:to_s)
- subject.to_s
- else
- raise ArgumentError, 'Subject must respond to `to_global_id` or `to_s`'
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
deleted file mode 100644
index b09d67b8d5f..00000000000
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-# frozen_string_literal: true
-
-require 'zlib'
-
-# Controller concern that checks if an `experimentation_subject_id cookie` is present and sets it if absent.
-# Used for A/B testing of experimental features. Exposes the `experiment_enabled?(experiment_name, subject: nil)` method
-# to controllers and views. It returns true when the experiment is enabled and the user is selected as part
-# of the experimental group.
-#
-module Gitlab
- module Experimentation
- module ControllerConcern
- include ::Gitlab::Experimentation::GroupTypes
- include Gitlab::Tracking::Helpers
- extend ActiveSupport::Concern
-
- included do
- before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?, :experiment_tracking_category_and_group, :record_experiment_group
- end
-
- def set_experimentation_subject_id_cookie
- if Gitlab.com?
- return if cookies[:experimentation_subject_id].present?
-
- cookies.permanent.signed[:experimentation_subject_id] = {
- value: SecureRandom.uuid,
- secure: ::Gitlab.config.gitlab.https,
- httponly: true
- }
- else
- # We set the cookie before, although experiments are not conducted on self managed instances.
- cookies.delete(:experimentation_subject_id)
- end
- end
-
- def push_frontend_experiment(experiment_key, subject: nil)
- var_name = experiment_key.to_s.camelize(:lower)
-
- enabled = experiment_enabled?(experiment_key, subject: subject)
-
- gon.push({ experiments: { var_name => enabled } }, true)
- end
-
- def experiment_enabled?(experiment_key, subject: nil)
- return true if forced_enabled?(experiment_key)
- return false if dnt_enabled?
-
- Experimentation.log_invalid_rollout(experiment_key, subject)
-
- subject ||= experimentation_subject_id
-
- Experimentation.in_experiment_group?(experiment_key, subject: subject)
- end
-
- def track_experiment_event(experiment_key, action, value = nil, subject: nil)
- return if dnt_enabled?
-
- track_experiment_event_for(experiment_key, action, value, subject: subject) do |tracking_data|
- ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data.merge!(user: current_user))
- end
- end
-
- def frontend_experimentation_tracking_data(experiment_key, action, value = nil, subject: nil)
- return if dnt_enabled?
-
- track_experiment_event_for(experiment_key, action, value, subject: subject) do |tracking_data|
- gon.push(tracking_data: tracking_data)
- end
- end
-
- def record_experiment_user(experiment_key, context = {})
- return if dnt_enabled?
- return unless Experimentation.active?(experiment_key) && current_user
-
- subject = Experimentation.rollout_strategy(experiment_key) == :cookie ? nil : current_user
-
- ::Experiment.add_user(experiment_key, tracking_group(experiment_key, nil, subject: subject), current_user, context)
- end
-
- def record_experiment_group(experiment_key, group)
- return if dnt_enabled?
- return unless Experimentation.active?(experiment_key) && group
-
- variant_subject = Experimentation.rollout_strategy(experiment_key) == :cookie ? nil : group
- variant = tracking_group(experiment_key, nil, subject: variant_subject)
-
- ::Experiment.add_group(experiment_key, group: group, variant: variant)
- end
-
- def record_experiment_conversion_event(experiment_key, context = {})
- return if dnt_enabled?
- return unless current_user
- return unless Experimentation.active?(experiment_key)
-
- ::Experiment.record_conversion_event(experiment_key, current_user, context)
- end
-
- def experiment_tracking_category_and_group(experiment_key, subject: nil)
- "#{tracking_category(experiment_key)}:#{tracking_group(experiment_key, '_group', subject: subject)}"
- end
-
- private
-
- def experimentation_subject_id
- cookies.signed[:experimentation_subject_id]
- end
-
- def track_experiment_event_for(experiment_key, action, value, subject: nil)
- return unless Experimentation.active?(experiment_key)
-
- yield experimentation_tracking_data(experiment_key, action, value, subject: subject)
- end
-
- def experimentation_tracking_data(experiment_key, action, value, subject: nil)
- {
- category: tracking_category(experiment_key),
- action: action,
- property: tracking_group(experiment_key, "_group", subject: subject),
- label: tracking_label(subject),
- value: value
- }.compact
- end
-
- def tracking_category(experiment_key)
- Experimentation.get_experiment(experiment_key).tracking_category
- end
-
- def tracking_group(experiment_key, suffix = nil, subject: nil)
- return unless Experimentation.active?(experiment_key)
-
- subject ||= experimentation_subject_id
- group = experiment_enabled?(experiment_key, subject: subject) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
-
- suffix ? "#{group}#{suffix}" : group
- end
-
- def forced_enabled?(experiment_key)
- return true if params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
- return false if cookies[:force_experiment].blank?
-
- cookies[:force_experiment].to_s.split(',').any? { |experiment| experiment.strip == experiment_key.to_s }
- end
-
- def tracking_label(subject = nil)
- return experimentation_subject_id if subject.blank?
-
- if subject.respond_to?(:to_global_id)
- Digest::SHA256.hexdigest(subject.to_global_id.to_s)
- else
- Digest::SHA256.hexdigest(subject.to_s)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/experimentation/experiment.rb b/lib/gitlab/experimentation/experiment.rb
deleted file mode 100644
index 0c7091d19e3..00000000000
--- a/lib/gitlab/experimentation/experiment.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Experimentation
- class Experiment
- FEATURE_FLAG_SUFFIX = "_experiment_percentage"
-
- attr_reader :key, :tracking_category, :rollout_strategy
-
- def initialize(key, **params)
- @key = key
- @tracking_category = params[:tracking_category]
- @rollout_strategy = params[:rollout_strategy] || :cookie
- end
-
- def active?
- # TODO: just touch a feature flag
- # Temporary change, we will change `experiment_percentage` in future to `Feature.enabled?
- Feature.enabled?(feature_flag_name, type: :experiment)
-
- ::Gitlab.com? && experiment_percentage > 0
- end
-
- def enabled_for_index?(index)
- return false if index.blank?
-
- index <= experiment_percentage
- end
-
- private
-
- def experiment_percentage
- feature_flag.percentage_of_time_value
- end
-
- def feature_flag
- Feature.get(feature_flag_name) # rubocop:disable Gitlab/AvoidFeatureGet
- end
-
- def feature_flag_name
- :"#{key}#{FEATURE_FLAG_SUFFIX}"
- end
- end
- end
-end
diff --git a/lib/gitlab/experimentation_logger.rb b/lib/gitlab/experimentation_logger.rb
deleted file mode 100644
index ba1b60d6b4c..00000000000
--- a/lib/gitlab/experimentation_logger.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class ExperimentationLogger < ::Gitlab::JsonLogger
- def self.file_name_noext
- 'experimentation_json'
- end
- end
-end
diff --git a/lib/gitlab/git/declared_license.rb b/lib/gitlab/git/declared_license.rb
new file mode 100644
index 00000000000..bc12b1918ea
--- /dev/null
+++ b/lib/gitlab/git/declared_license.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ # DeclaredLicense is the software license declared in a LICENSE or COPYING
+ # file in the git repository.
+ class DeclaredLicense
+ # SPDX Identifier for the license
+ attr_reader :key
+
+ # Full name of the license
+ attr_reader :name
+
+ # Nickname of the license (optional, a shorter user-friendly name)
+ attr_reader :nickname
+
+ # Filename of the file containing license
+ attr_accessor :path
+
+ # URL that points to the LICENSE
+ attr_reader :url
+
+ def initialize(key: nil, name: nil, nickname: nil, url: nil, path: nil)
+ @key = key
+ @name = name
+ @nickname = nickname
+ @url = url
+ @path = path
+ end
+
+ def ==(other)
+ return unless other.is_a?(self.class)
+
+ key == other.key
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index f1cd75258be..9bbe17dcad1 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -783,10 +783,31 @@ module Gitlab
end
end
- def license_short_name
+ def license(from_gitaly)
wrapped_gitaly_errors do
- gitaly_repository_client.license_short_name
+ response = gitaly_repository_client.find_license
+
+ break nil if response.license_short_name.empty?
+
+ if from_gitaly
+ break ::Gitlab::Git::DeclaredLicense.new(key: response.license_short_name,
+ name: response.license_name,
+ nickname: response.license_nickname.presence,
+ url: response.license_url.presence,
+ path: response.license_path)
+ end
+
+ licensee_object = Licensee::License.new(response.license_short_name)
+
+ break nil if licensee_object.name.blank?
+
+ licensee_object.meta.nickname = "LICENSE" if licensee_object.key == "other"
+
+ licensee_object
end
+ rescue Licensee::InvalidLicense => e
+ Gitlab::ErrorTracking.track_exception(e)
+ nil
end
def fetch_source_branch!(source_repository, source_branch, local_ref)
@@ -1008,8 +1029,8 @@ module Gitlab
@praefect_info_client ||= Gitlab::GitalyClient::PraefectInfoService.new(self)
end
- def branch_names_contains_sha(sha)
- gitaly_ref_client.branch_names_contains_sha(sha)
+ def branch_names_contains_sha(sha, limit: 0)
+ gitaly_ref_client.branch_names_contains_sha(sha, limit: limit)
end
def tag_names_contains_sha(sha, limit: 0)
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
deleted file mode 100644
index 2228fcb886e..00000000000
--- a/lib/gitlab/git/wiki.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Git
- class Wiki
- include Gitlab::Git::WrapsGitalyErrors
-
- DuplicatePageError = Class.new(StandardError)
-
- DEFAULT_PAGINATION = Kaminari.config.default_per_page
-
- CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do
- def to_h
- { user_id: user_id, username: username, name: name, email: email, message: message }
- end
- end
-
- # GollumSlug inlines just enough knowledge from Gollum::Page to generate a
- # slug, which is used when previewing pages that haven't been persisted
- class GollumSlug
- class << self
- def cname(name, char_white_sub = '-', char_other_sub = '-')
- if name.respond_to?(:gsub)
- name.gsub(/\s/, char_white_sub).gsub(/[<>+]/, char_other_sub)
- else
- ''
- end
- end
-
- def format_to_ext(format)
- format == :markdown ? "md" : format.to_s
- end
-
- def canonicalize_filename(filename)
- ::File.basename(filename, ::File.extname(filename)).tr('-', ' ')
- end
-
- def generate(title, format)
- ext = format_to_ext(format.to_sym)
- name = cname(title) + '.' + ext
- canonical_name = canonicalize_filename(name)
-
- path =
- if name.include?('/')
- name.sub(%r{/[^/]+$}, '/')
- else
- ''
- end
-
- path + cname(canonical_name, '-', '-')
- end
- end
- end
-
- attr_reader :repository
-
- # TODO remove argument when issue
- # https://gitlab.com/gitlab-org/gitlab/-/issues/329190
- # is closed.
- def self.default_ref(container = nil)
- Gitlab::DefaultBranch.value(object: container)
- end
-
- # Initialize with a Gitlab::Git::Repository instance
- def initialize(repository)
- @repository = repository
- end
-
- def repository_exists?
- @repository.exists?
- end
-
- def list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
- wrapped_gitaly_errors do
- gitaly_list_pages(
- limit: limit,
- sort: sort,
- direction_desc: direction_desc,
- load_content: load_content
- )
- end
- end
-
- def page(title:, version: nil, dir: nil, load_content: true)
- wrapped_gitaly_errors do
- gitaly_find_page(title: title, version: version, dir: dir, load_content: load_content)
- end
- end
-
- def count_page_versions(page_path)
- @repository.count_commits(ref: 'HEAD', path: page_path)
- end
-
- def preview_slug(title, format)
- GollumSlug.generate(title, format)
- end
-
- private
-
- def gitaly_wiki_client
- @gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository)
- end
-
- def gitaly_find_page(title:, version: nil, dir: nil, load_content: true)
- return unless title.present?
-
- wiki_page, version = gitaly_wiki_client.find_page(title: title, version: version, dir: dir, load_content: load_content)
- return unless wiki_page
-
- Gitlab::Git::WikiPage.from_gitaly_wiki_page(wiki_page, version)
- rescue GRPC::InvalidArgument
- nil
- end
-
- def gitaly_list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
- params = { limit: limit, sort: sort, direction_desc: direction_desc }
-
- gitaly_pages =
- if load_content
- gitaly_wiki_client.load_all_pages(**params)
- else
- gitaly_wiki_client.list_all_pages(**params)
- end
-
- gitaly_pages.map do |wiki_page, version|
- Gitlab::Git::WikiPage.from_gitaly_wiki_page(wiki_page, version)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/wiki_page.rb b/lib/gitlab/git/wiki_page.rb
index 57b7e7d53dd..26d15daf093 100644
--- a/lib/gitlab/git/wiki_page.rb
+++ b/lib/gitlab/git/wiki_page.rb
@@ -5,22 +5,6 @@ module Gitlab
class WikiPage
attr_reader :url_path, :title, :format, :path, :version, :raw_data, :name, :historical, :formatted_data
- class << self
- # Abstracts away Gitlab::GitalyClient::WikiPage
- def from_gitaly_wiki_page(gitaly_page, version)
- new(
- url_path: gitaly_page.url_path,
- title: gitaly_page.title,
- format: gitaly_page.format,
- path: gitaly_page.path,
- raw_data: gitaly_page.raw_data,
- name: gitaly_page.name,
- historical: gitaly_page.historical?,
- version: version
- )
- end
- end
-
def initialize(hash)
@url_path = hash[:url_path]
@title = hash[:title]
@@ -41,6 +25,11 @@ module Gitlab
@text_data = @raw_data && Gitlab::EncodingHelper.encode!(@raw_data.dup)
end
+
+ def raw_data=(data)
+ @raw_data = data
+ @text_data = @raw_data && Gitlab::EncodingHelper.encode!(@raw_data.dup)
+ end
end
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 1c5ad650678..9a3f5fb844b 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -394,7 +394,7 @@ module Gitlab
elsif user
user.can?(:read_project, project)
elsif ci?
- true # allow CI (build without a user) for backwards compatibility
+ false
end || Guest.can?(:read_project, project)
end
@@ -445,9 +445,6 @@ module Gitlab
nil
when Key
actor.user
- when :ci
- Gitlab::AppJsonLogger.info(message: 'Actor was :ci', project_id: project.id)
- nil
end
end
end
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index bb6bc3121bd..d2b702f3a6d 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -270,15 +270,13 @@ module Gitlab
end
def consume_find_local_branches_response(response)
- if Feature.enabled?(:gitaly_simplify_find_local_branches_response, type: :undefined)
- response.flat_map do |message|
+ response.flat_map do |message|
+ if message.local_branches.present?
message.local_branches.map do |branch|
target_commit = Gitlab::Git::Commit.decorate(@repository, branch.target_commit)
Gitlab::Git::Branch.new(@repository, branch.name, branch.target_commit.id, target_commit)
end
- end
- else
- response.flat_map do |message|
+ else
message.branches.map do |gitaly_branch|
Gitlab::Git::Branch.new(
@repository,
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 04d6f92e8d8..f11437552e1 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -283,12 +283,10 @@ module Gitlab
response.path.presence
end
- def license_short_name
+ def find_license
request = Gitaly::FindLicenseRequest.new(repository: @gitaly_repo)
- response = GitalyClient.call(@storage, :repository_service, :find_license, request, timeout: GitalyClient.fast_timeout)
-
- response.license_short_name.presence
+ GitalyClient.call(@storage, :repository_service, :find_license, request, timeout: GitalyClient.medium_timeout)
end
def calculate_checksum
diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb
deleted file mode 100644
index ca839b232cf..00000000000
--- a/lib/gitlab/gitaly_client/wiki_service.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-# frozen_string_literal: true
-
-require 'stringio'
-
-module Gitlab
- module GitalyClient
- class WikiService
- include Gitlab::EncodingHelper
-
- MAX_MSG_SIZE = 128.kilobytes.freeze
-
- def initialize(repository)
- @gitaly_repo = repository.gitaly_repository
- @repository = repository
- end
-
- def write_page(name, format, content, commit_details)
- request = Gitaly::WikiWritePageRequest.new(
- repository: @gitaly_repo,
- name: encode_binary(name),
- format: format.to_s,
- commit_details: gitaly_commit_details(commit_details)
- )
-
- strio = binary_io(content)
-
- enum = Enumerator.new do |y|
- until strio.eof?
- request.content = strio.read(MAX_MSG_SIZE)
-
- y.yield request
-
- request = Gitaly::WikiWritePageRequest.new
- end
- end
-
- response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_write_page, enum, timeout: GitalyClient.medium_timeout)
- if error = response.duplicate_error.presence
- raise Gitlab::Git::Wiki::DuplicatePageError, error
- end
- end
-
- def update_page(page_path, title, format, content, commit_details)
- request = Gitaly::WikiUpdatePageRequest.new(
- repository: @gitaly_repo,
- page_path: encode_binary(page_path),
- title: encode_binary(title),
- format: format.to_s,
- commit_details: gitaly_commit_details(commit_details)
- )
-
- strio = binary_io(content)
-
- enum = Enumerator.new do |y|
- until strio.eof?
- request.content = strio.read(MAX_MSG_SIZE)
-
- y.yield request
-
- request = Gitaly::WikiUpdatePageRequest.new
- end
- end
-
- GitalyClient.call(@repository.storage, :wiki_service, :wiki_update_page, enum, timeout: GitalyClient.medium_timeout)
- end
-
- def find_page(title:, version: nil, dir: nil, load_content: true)
- request = Gitaly::WikiFindPageRequest.new(
- repository: @gitaly_repo,
- title: encode_binary(title),
- revision: encode_binary(version),
- directory: encode_binary(dir),
- skip_content: !load_content
- )
-
- response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_find_page, request, timeout: GitalyClient.fast_timeout)
-
- wiki_page_from_iterator(response)
- end
-
- def list_all_pages(limit: 0, sort: nil, direction_desc: false)
- sort_value = Gitaly::WikiListPagesRequest::SortBy.resolve(sort.to_s.upcase.to_sym)
-
- params = { repository: @gitaly_repo, limit: limit, direction_desc: direction_desc }
- params[:sort] = sort_value if sort_value
-
- request = Gitaly::WikiListPagesRequest.new(params)
- stream = GitalyClient.call(@repository.storage, :wiki_service, :wiki_list_pages, request, timeout: GitalyClient.medium_timeout)
- stream.each_with_object([]) do |message, pages|
- page = message.page
-
- next unless page
-
- wiki_page = GitalyClient::WikiPage.new(page.to_h)
- version = new_wiki_page_version(page.version)
-
- pages << [wiki_page, version]
- end
- end
-
- def load_all_pages(limit: 0, sort: nil, direction_desc: false)
- sort_value = Gitaly::WikiGetAllPagesRequest::SortBy.resolve(sort.to_s.upcase.to_sym)
-
- params = { repository: @gitaly_repo, limit: limit, direction_desc: direction_desc }
- params[:sort] = sort_value if sort_value
-
- request = Gitaly::WikiGetAllPagesRequest.new(params)
- response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_get_all_pages, request, timeout: GitalyClient.medium_timeout)
-
- pages = []
-
- loop do
- page, version = wiki_page_from_iterator(response) { |message| message.end_of_page }
-
- break unless page && version
-
- pages << [page, version]
- end
-
- pages
- end
-
- private
-
- # If a block is given and the yielded value is truthy, iteration will be
- # stopped early at that point; else the iterator is consumed entirely.
- # The iterator is traversed with `next` to allow resuming the iteration.
- def wiki_page_from_iterator(iterator)
- wiki_page = version = nil
-
- while message = iterator.next
- break if block_given? && yield(message)
-
- page = message.page
- next unless page
-
- if wiki_page
- wiki_page.raw_data << page.raw_data
- else
- wiki_page = GitalyClient::WikiPage.new(page.to_h)
-
- version = new_wiki_page_version(page.version)
- end
- end
-
- [wiki_page, version]
- rescue StopIteration
- [wiki_page, version]
- end
-
- def new_wiki_page_version(version)
- Gitlab::Git::WikiPageVersion.new(
- Gitlab::Git::Commit.decorate(@repository, version.commit),
- version.format
- )
- end
-
- def gitaly_commit_details(commit_details)
- Gitaly::WikiCommitDetails.new(
- user_id: commit_details.user_id,
- user_name: encode_binary(commit_details.username),
- name: encode_binary(commit_details.name),
- email: encode_binary(commit_details.email),
- message: encode_binary(commit_details.message)
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index 6cff15a204f..0f89a7b6575 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -69,7 +69,7 @@ module Gitlab
#
# username - The username of the user.
def user(username)
- with_rate_limit { octokit.user(username) }
+ with_rate_limit { octokit.user(username).to_h }
end
def pull_request_reviews(repo_name, iid)
@@ -88,7 +88,7 @@ module Gitlab
end
def pull_request(repo_name, iid)
- with_rate_limit { octokit.pull_request(repo_name, iid) }
+ with_rate_limit { octokit.pull_request(repo_name, iid).to_h }
end
def labels(*args)
@@ -108,7 +108,7 @@ module Gitlab
end
def branch_protection(repo_name, branch_name)
- with_rate_limit { octokit.branch_protection(repo_name, branch_name) }
+ with_rate_limit { octokit.branch_protection(repo_name, branch_name).to_h }
end
# Fetches data from the GitHub API and yields a Page object for every page
@@ -150,7 +150,7 @@ module Gitlab
each_page(method, *args) do |page|
page.objects.each do |object|
- yield object
+ yield object.to_h
end
end
end
@@ -183,7 +183,7 @@ module Gitlab
end
def search_query(str:, type:, include_collaborations: true, include_orgs: true)
- query = "#{str} in:#{type} is:public,private user:#{octokit.user.login}"
+ query = "#{str} in:#{type} is:public,private user:#{octokit.user.to_h[:login]}"
query = [query, collaborations_subquery].join(' ') if include_collaborations
query = [query, organizations_subquery].join(' ') if include_orgs
@@ -274,13 +274,13 @@ module Gitlab
def collaborations_subquery
each_object(:repos, nil, { affiliation: 'collaborator' })
- .map { |repo| "repo:#{repo.full_name}" }
+ .map { |repo| "repo:#{repo[:full_name]}" }
.join(' ')
end
def organizations_subquery
each_object(:organizations)
- .map { |org| "org:#{org.login}" }
+ .map { |org| "org:#{org[:login]}" }
.join(' ')
end
diff --git a/lib/gitlab/github_import/exceptions.rb b/lib/gitlab/github_import/exceptions.rb
new file mode 100644
index 00000000000..3a36b64a11b
--- /dev/null
+++ b/lib/gitlab/github_import/exceptions.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Exceptions
+ # Sometimes it's not clear which of not implemented interfaces caused this error.
+ # We need custom exception to be able to add text that gives extra context.
+ NotImplementedError = Class.new(StandardError)
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/attachments/base_importer.rb b/lib/gitlab/github_import/importer/attachments/base_importer.rb
new file mode 100644
index 00000000000..eaff99aed43
--- /dev/null
+++ b/lib/gitlab/github_import/importer/attachments/base_importer.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Attachments
+ class BaseImporter
+ include ParallelScheduling
+
+ BATCH_SIZE = 100
+
+ # The method that will be called for traversing through all the objects to
+ # import, yielding them to the supplied block.
+ def each_object_to_import
+ collection.each_batch(of: BATCH_SIZE, column: ordering_column) do |batch|
+ batch.each do |record|
+ next if already_imported?(record)
+
+ Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
+
+ yield record
+
+ # We mark the object as imported immediately so we don't end up
+ # scheduling it multiple times.
+ mark_as_imported(record)
+ end
+ end
+ end
+
+ def representation_class
+ Representation::NoteText
+ end
+
+ def importer_class
+ NoteAttachmentsImporter
+ end
+
+ private
+
+ def collection
+ raise Gitlab::GithubImport::Exceptions::NotImplementedError, '#collection'
+ end
+
+ def ordering_column
+ :id
+ end
+
+ def object_representation(object)
+ representation_class.from_db_record(object)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/attachments/issues_importer.rb b/lib/gitlab/github_import/importer/attachments/issues_importer.rb
new file mode 100644
index 00000000000..090bfb4a098
--- /dev/null
+++ b/lib/gitlab/github_import/importer/attachments/issues_importer.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Attachments
+ class IssuesImporter < ::Gitlab::GithubImport::Importer::Attachments::BaseImporter
+ def sidekiq_worker_class
+ ::Gitlab::GithubImport::Attachments::ImportIssueWorker
+ end
+
+ def collection_method
+ :issue_attachments
+ end
+
+ def object_type
+ :issue_attachment
+ end
+
+ def id_for_already_imported_cache(issue)
+ issue.id
+ end
+
+ private
+
+ def collection
+ project.issues.select(:id, :description)
+ end
+
+ def ordering_column
+ :iid
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/attachments/merge_requests_importer.rb b/lib/gitlab/github_import/importer/attachments/merge_requests_importer.rb
new file mode 100644
index 00000000000..f41071b1785
--- /dev/null
+++ b/lib/gitlab/github_import/importer/attachments/merge_requests_importer.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Attachments
+ class MergeRequestsImporter < ::Gitlab::GithubImport::Importer::Attachments::BaseImporter
+ def sidekiq_worker_class
+ ::Gitlab::GithubImport::Attachments::ImportMergeRequestWorker
+ end
+
+ def collection_method
+ :merge_request_attachments
+ end
+
+ def object_type
+ :merge_request_attachment
+ end
+
+ def id_for_already_imported_cache(merge_request)
+ merge_request.id
+ end
+
+ private
+
+ def collection
+ project.merge_requests.select(:id, :description)
+ end
+
+ def ordering_column
+ :iid
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/attachments/notes_importer.rb b/lib/gitlab/github_import/importer/attachments/notes_importer.rb
new file mode 100644
index 00000000000..aa38a7a3a3f
--- /dev/null
+++ b/lib/gitlab/github_import/importer/attachments/notes_importer.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Attachments
+ class NotesImporter < ::Gitlab::GithubImport::Importer::Attachments::BaseImporter
+ def sidekiq_worker_class
+ ::Gitlab::GithubImport::Attachments::ImportNoteWorker
+ end
+
+ def collection_method
+ :note_attachments
+ end
+
+ def object_type
+ :note_attachment
+ end
+
+ def id_for_already_imported_cache(note)
+ note.id
+ end
+
+ private
+
+ # TODO: exclude :system, :noteable_type from select after removing override Note#note method
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/369923
+ def collection
+ project.notes.user.select(:id, :note, :system, :noteable_type)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/attachments/releases_importer.rb b/lib/gitlab/github_import/importer/attachments/releases_importer.rb
new file mode 100644
index 00000000000..feaa69eff71
--- /dev/null
+++ b/lib/gitlab/github_import/importer/attachments/releases_importer.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Attachments
+ class ReleasesImporter < ::Gitlab::GithubImport::Importer::Attachments::BaseImporter
+ def sidekiq_worker_class
+ ::Gitlab::GithubImport::Attachments::ImportReleaseWorker
+ end
+
+ def collection_method
+ :release_attachments
+ end
+
+ def object_type
+ :release_attachment
+ end
+
+ def id_for_already_imported_cache(release)
+ release.id
+ end
+
+ private
+
+ def collection
+ project.releases.select(:id, :description)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/diff_notes_importer.rb b/lib/gitlab/github_import/importer/diff_notes_importer.rb
index 49cbc8f7a42..92f26692a05 100644
--- a/lib/gitlab/github_import/importer/diff_notes_importer.rb
+++ b/lib/gitlab/github_import/importer/diff_notes_importer.rb
@@ -27,7 +27,7 @@ module Gitlab
end
def id_for_already_imported_cache(note)
- note.id
+ note[:id]
end
end
end
diff --git a/lib/gitlab/github_import/importer/issue_events_importer.rb b/lib/gitlab/github_import/importer/issue_events_importer.rb
index 71dd99f91f9..a1c706c5d78 100644
--- a/lib/gitlab/github_import/importer/issue_events_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_events_importer.rb
@@ -27,7 +27,7 @@ module Gitlab
end
def id_for_already_imported_cache(event)
- event.id
+ event[:id]
end
end
end
diff --git a/lib/gitlab/github_import/importer/issues_importer.rb b/lib/gitlab/github_import/importer/issues_importer.rb
index 21d9ce8cd2d..3d6f15fc2bc 100644
--- a/lib/gitlab/github_import/importer/issues_importer.rb
+++ b/lib/gitlab/github_import/importer/issues_importer.rb
@@ -33,13 +33,17 @@ module Gitlab
end
def id_for_already_imported_cache(issue)
- issue.number
+ issue[:number]
end
def collection_options
{ state: 'all', sort: 'created', direction: 'asc' }
end
+ def increment_object_counter?(object)
+ object[:pull_request].nil?
+ end
+
private
def additional_object_data
diff --git a/lib/gitlab/github_import/importer/labels_importer.rb b/lib/gitlab/github_import/importer/labels_importer.rb
index 7293de56a9a..9a011f17a18 100644
--- a/lib/gitlab/github_import/importer/labels_importer.rb
+++ b/lib/gitlab/github_import/importer/labels_importer.rb
@@ -22,7 +22,7 @@ module Gitlab
end
def already_imported?(label)
- existing_labels.include?(label.name)
+ existing_labels.include?(label[:name])
end
def build_labels_cache
@@ -33,8 +33,8 @@ module Gitlab
time = Time.zone.now
{
- title: label.name,
- color: '#' + label.color,
+ title: label[:name],
+ color: '#' + label[:color],
project_id: project.id,
type: 'ProjectLabel',
created_at: time,
diff --git a/lib/gitlab/github_import/importer/milestones_importer.rb b/lib/gitlab/github_import/importer/milestones_importer.rb
index d11b151bbe2..1a3a54d0053 100644
--- a/lib/gitlab/github_import/importer/milestones_importer.rb
+++ b/lib/gitlab/github_import/importer/milestones_importer.rb
@@ -22,7 +22,7 @@ module Gitlab
end
def already_imported?(milestone)
- existing_milestones.include?(milestone.number)
+ existing_milestones.include?(milestone[:number])
end
def build_milestones_cache
@@ -31,19 +31,19 @@ module Gitlab
def build(milestone)
{
- iid: milestone.number,
- title: milestone.title,
- description: milestone.description,
+ iid: milestone[:number],
+ title: milestone[:title],
+ description: milestone[:description],
project_id: project.id,
state: state_for(milestone),
- due_date: milestone.due_on&.to_date,
- created_at: milestone.created_at,
- updated_at: milestone.updated_at
+ due_date: milestone[:due_on]&.to_date,
+ created_at: milestone[:created_at],
+ updated_at: milestone[:updated_at]
}
end
def state_for(milestone)
- milestone.state == 'open' ? :active : :closed
+ milestone[:state] == 'open' ? :active : :closed
end
def each_milestone
diff --git a/lib/gitlab/github_import/importer/note_attachments_importer.rb b/lib/gitlab/github_import/importer/note_attachments_importer.rb
new file mode 100644
index 00000000000..9901c9e76f5
--- /dev/null
+++ b/lib/gitlab/github_import/importer/note_attachments_importer.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ class NoteAttachmentsImporter
+ attr_reader :note_text, :project
+
+ # note_text - An instance of `NoteText`.
+ # project - An instance of `Project`.
+ # client - An instance of `Gitlab::GithubImport::Client`.
+ def initialize(note_text, project, _client = nil)
+ @note_text = note_text
+ @project = project
+ end
+
+ def execute
+ attachments = MarkdownText.fetch_attachments(note_text.text)
+ return if attachments.blank?
+
+ new_text = attachments.reduce(note_text.text) do |text, attachment|
+ new_url = download_attachment(attachment)
+ text.gsub(attachment.url, new_url)
+ end
+
+ update_note_record(new_text)
+ end
+
+ private
+
+ # in: an instance of Gitlab::GithubImport::Markdown::Attachment
+ # out: gitlab attachment markdown url
+ def download_attachment(attachment)
+ downloader = ::Gitlab::GithubImport::AttachmentsDownloader.new(attachment.url)
+ file = downloader.perform
+ uploader = UploadService.new(project, file, FileUploader).execute
+ uploader.to_h[:url]
+ ensure
+ downloader&.delete
+ end
+
+ def update_note_record(text)
+ case note_text.record_type
+ when ::Release.name
+ ::Release.find(note_text.record_db_id).update_column(:description, text)
+ when ::Issue.name
+ ::Issue.find(note_text.record_db_id).update_column(:description, text)
+ when ::MergeRequest.name
+ ::MergeRequest.find(note_text.record_db_id).update_column(:description, text)
+ when ::Note.name
+ ::Note.find(note_text.record_db_id).update_column(:note, text)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/note_importer.rb b/lib/gitlab/github_import/importer/note_importer.rb
index 1410006af26..69b7b2c2a38 100644
--- a/lib/gitlab/github_import/importer/note_importer.rb
+++ b/lib/gitlab/github_import/importer/note_importer.rb
@@ -36,6 +36,9 @@ module Gitlab
# We're using bulk_insert here so we can bypass any validations and
# callbacks. Running these would result in a lot of unnecessary SQL
# queries being executed when importing large projects.
+ # Note: if you're going to replace `legacy_bulk_insert` with something that trigger callback
+ # to generate HTML version - you also need to regenerate it in
+ # Gitlab::GithubImport::Importer::NoteAttachmentsImporter.
ApplicationRecord.legacy_bulk_insert(Note.table_name, [attributes]) # rubocop:disable Gitlab/BulkInsert
rescue ActiveRecord::InvalidForeignKey
# It's possible the project and the issue have been deleted since
diff --git a/lib/gitlab/github_import/importer/notes_importer.rb b/lib/gitlab/github_import/importer/notes_importer.rb
index ca1d7d60515..4c2b87a8c5e 100644
--- a/lib/gitlab/github_import/importer/notes_importer.rb
+++ b/lib/gitlab/github_import/importer/notes_importer.rb
@@ -27,7 +27,7 @@ module Gitlab
end
def id_for_already_imported_cache(note)
- note.id
+ note[:id]
end
end
end
diff --git a/lib/gitlab/github_import/importer/protected_branch_importer.rb b/lib/gitlab/github_import/importer/protected_branch_importer.rb
index 16215fdce8e..21075e21e1d 100644
--- a/lib/gitlab/github_import/importer/protected_branch_importer.rb
+++ b/lib/gitlab/github_import/importer/protected_branch_importer.rb
@@ -6,6 +6,10 @@ module Gitlab
class ProtectedBranchImporter
attr_reader :protected_branch, :project, :client
+ # By default on GitHub, both developers and maintainers can merge
+ # a PR into the protected branch
+ GITHUB_DEFAULT_MERGE_ACCESS_LEVEL = Gitlab::Access::DEVELOPER
+
# protected_branch - An instance of
# `Gitlab::GithubImport::Representation::ProtectedBranch`.
# project - An instance of `Project`
@@ -22,6 +26,8 @@ module Gitlab
ProtectedBranches::CreateService
.new(project, project.creator, params)
.execute(skip_authorization: true)
+
+ update_project_settings if default_branch?
end
private
@@ -29,8 +35,8 @@ module Gitlab
def params
{
name: protected_branch.id,
- push_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }],
- merge_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }],
+ push_access_levels_attributes: [{ access_level: push_access_level }],
+ merge_access_levels_attributes: [{ access_level: merge_access_level }],
allow_force_push: allow_force_push?
}
end
@@ -42,6 +48,95 @@ module Gitlab
protected_branch.allow_force_pushes
end
end
+
+ def default_branch?
+ protected_branch.id == project.default_branch
+ end
+
+ def update_project_settings
+ update_setting_for_only_allow_merge_if_all_discussions_are_resolved
+ update_project_push_rule
+ end
+
+ def update_setting_for_only_allow_merge_if_all_discussions_are_resolved
+ return unless protected_branch.required_conversation_resolution
+
+ project.update(only_allow_merge_if_all_discussions_are_resolved: true)
+ end
+
+ def update_project_push_rule
+ return unless project.licensed_feature_available?(:push_rules)
+ return unless protected_branch.required_signatures
+
+ push_rule = project.push_rule || project.build_push_rule
+ push_rule.update!(reject_unsigned_commits: true)
+ project.project_setting.update!(push_rule_id: push_rule.id)
+ end
+
+ def push_access_level
+ if protected_branch.required_pull_request_reviews
+ Gitlab::Access::NO_ACCESS
+ else
+ gitlab_access_level_for(:push)
+ end
+ end
+
+ # Gets the strictest merge_access_level between GitHub and GitLab
+ def merge_access_level
+ gitlab_access = gitlab_access_level_for(:merge)
+
+ return gitlab_access if gitlab_access == Gitlab::Access::NO_ACCESS
+
+ [gitlab_access, GITHUB_DEFAULT_MERGE_ACCESS_LEVEL].max
+ end
+
+ # action - :push/:merge
+ def gitlab_access_level_for(action)
+ if default_branch?
+ action == :push ? default_branch_push_access_level : default_branch_merge_access_level
+ elsif protected_on_gitlab?
+ non_default_branch_access_level_for(action)
+ else
+ gitlab_default_access_level_for(action)
+ end
+ end
+
+ def default_branch_push_access_level
+ if default_branch_protection.developer_can_push?
+ Gitlab::Access::DEVELOPER
+ else
+ gitlab_default_access_level_for(:push)
+ end
+ end
+
+ def default_branch_merge_access_level
+ if default_branch_protection.developer_can_merge?
+ Gitlab::Access::DEVELOPER
+ else
+ gitlab_default_access_level_for(:merge)
+ end
+ end
+
+ def default_branch_protection
+ Gitlab::Access::BranchProtection.new(project.namespace.default_branch_protection)
+ end
+
+ def protected_on_gitlab?
+ ProtectedBranch.protected?(project, protected_branch.id)
+ end
+
+ def non_default_branch_access_level_for(action)
+ access_level = ProtectedBranch.access_levels_for_ref(protected_branch.id, action: action)
+ .find(&:role?)&.access_level
+
+ access_level || gitlab_default_access_level_for(action)
+ end
+
+ def gitlab_default_access_level_for(action)
+ return ProtectedBranch::PushAccessLevel::GITLAB_DEFAULT_ACCESS_LEVEL if action == :push
+
+ ProtectedBranch::MergeAccessLevel::GITLAB_DEFAULT_ACCESS_LEVEL
+ end
end
end
end
diff --git a/lib/gitlab/github_import/importer/protected_branches_importer.rb b/lib/gitlab/github_import/importer/protected_branches_importer.rb
index b5be823d5ab..4372477f55d 100644
--- a/lib/gitlab/github_import/importer/protected_branches_importer.rb
+++ b/lib/gitlab/github_import/importer/protected_branches_importer.rb
@@ -11,9 +11,9 @@ module Gitlab
def each_object_to_import
repo = project.import_source
- protected_branches = client.branches(repo).select { |branch| branch.protection&.enabled }
+ protected_branches = client.branches(repo).select { |branch| branch.dig(:protection, :enabled) }
protected_branches.each do |protected_branch|
- object = client.branch_protection(repo, protected_branch.name)
+ object = client.branch_protection(repo, protected_branch[:name])
next if object.nil? || already_imported?(object)
yield object
@@ -44,7 +44,7 @@ module Gitlab
end
def id_for_already_imported_cache(protected_branch)
- protected_branch.name
+ protected_branch[:name]
end
end
end
diff --git a/lib/gitlab/github_import/importer/pull_requests_importer.rb b/lib/gitlab/github_import/importer/pull_requests_importer.rb
index 5d291d9d723..16541c90002 100644
--- a/lib/gitlab/github_import/importer/pull_requests_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_importer.rb
@@ -19,7 +19,7 @@ module Gitlab
end
def id_for_already_imported_cache(pr)
- pr.number
+ pr[:number]
end
def object_type
@@ -55,11 +55,11 @@ module Gitlab
def update_repository?(pr)
last_update = project.last_repository_updated_at || project.created_at
- return false if pr.updated_at < last_update
+ return false if pr[:updated_at] < last_update
# PRs may be updated without there actually being new commits, thus we
# check to make sure we only re-fetch if truly necessary.
- !(commit_exists?(pr.head.sha) && commit_exists?(pr.base.sha))
+ !(commit_exists?(pr.dig(:head, :sha)) && commit_exists?(pr.dig(:base, :sha)))
end
def commit_exists?(sha)
diff --git a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
index 5e55d09fe3d..543c29a21a0 100644
--- a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
@@ -34,7 +34,7 @@ module Gitlab
end
def id_for_already_imported_cache(review)
- review.id
+ review[:id]
end
# The worker can be interrupted, by rate limit for instance,
@@ -48,11 +48,13 @@ module Gitlab
def each_object_to_import(&block)
each_review_page do |page, merge_request|
page.objects.each do |review|
+ review = review.to_h
+
next if already_imported?(review)
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
- review.merge_request_id = merge_request.id
+ review[:merge_request_id] = merge_request.id
yield(review)
mark_as_imported(review)
diff --git a/lib/gitlab/github_import/importer/release_attachments_importer.rb b/lib/gitlab/github_import/importer/release_attachments_importer.rb
deleted file mode 100644
index 6419851623c..00000000000
--- a/lib/gitlab/github_import/importer/release_attachments_importer.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module GithubImport
- module Importer
- class ReleaseAttachmentsImporter
- attr_reader :release_db_id, :release_description, :project
-
- # release - An instance of `ReleaseAttachments`.
- # project - An instance of `Project`.
- # client - An instance of `Gitlab::GithubImport::Client`.
- def initialize(release_attachments, project, _client = nil)
- @release_db_id = release_attachments.release_db_id
- @release_description = release_attachments.description
- @project = project
- end
-
- def execute
- attachment_urls = MarkdownText.fetch_attachment_urls(release_description)
- new_description = attachment_urls.reduce(release_description) do |description, url|
- new_url = download_attachment(url)
- description.gsub(url, new_url)
- end
-
- Release.find(release_db_id).update_column(:description, new_description)
- end
-
- private
-
- # in: github attachment markdown url
- # out: gitlab attachment markdown url
- def download_attachment(markdown_url)
- url = extract_url_from_markdown(markdown_url)
- name_prefix = extract_name_from_markdown(markdown_url)
-
- downloader = ::Gitlab::GithubImport::AttachmentsDownloader.new(url)
- file = downloader.perform
- uploader = UploadService.new(project, file, FileUploader).execute
- "#{name_prefix}(#{uploader.to_h[:url]})"
- ensure
- downloader&.delete
- end
-
- # in: "![image-icon](https://user-images.githubusercontent.com/..)"
- # out: https://user-images.githubusercontent.com/..
- def extract_url_from_markdown(text)
- text.match(%r{https://.*\)$}).to_a[0].chop
- end
-
- # in: "![image-icon](https://user-images.githubusercontent.com/..)"
- # out: ![image-icon]
- def extract_name_from_markdown(text)
- text.match(%r{^!?\[.*\]}).to_a[0]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/github_import/importer/releases_attachments_importer.rb b/lib/gitlab/github_import/importer/releases_attachments_importer.rb
deleted file mode 100644
index 7221c802d83..00000000000
--- a/lib/gitlab/github_import/importer/releases_attachments_importer.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module GithubImport
- module Importer
- class ReleasesAttachmentsImporter
- include ParallelScheduling
-
- BATCH_SIZE = 100
-
- # The method that will be called for traversing through all the objects to
- # import, yielding them to the supplied block.
- def each_object_to_import
- project.releases.select(:id, :description).each_batch(of: BATCH_SIZE, column: :id) do |batch|
- batch.each do |release|
- next if already_imported?(release)
-
- Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
-
- yield release
-
- # We mark the object as imported immediately so we don't end up
- # scheduling it multiple times.
- mark_as_imported(release)
- end
- end
- end
-
- def representation_class
- Representation::ReleaseAttachments
- end
-
- def importer_class
- ReleaseAttachmentsImporter
- end
-
- def sidekiq_worker_class
- ImportReleaseAttachmentsWorker
- end
-
- def collection_method
- :release_attachments
- end
-
- def object_type
- :release_attachment
- end
-
- def id_for_already_imported_cache(release)
- release.id
- end
-
- def object_representation(object)
- representation_class.from_db_record(object)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/github_import/importer/releases_importer.rb b/lib/gitlab/github_import/importer/releases_importer.rb
index 51d364772d2..fe6da30bbf8 100644
--- a/lib/gitlab/github_import/importer/releases_importer.rb
+++ b/lib/gitlab/github_import/importer/releases_importer.rb
@@ -12,6 +12,9 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ # Note: if you're going to replace `legacy_bulk_insert` with something that triggers callback
+ # to generate HTML version - you also need to regenerate it in
+ # Gitlab::GithubImport::Importer::NoteAttachmentsImporter.
def execute
bulk_insert(Release, build_releases)
end
@@ -21,21 +24,21 @@ module Gitlab
end
def already_imported?(release)
- existing_tags.include?(release.tag_name) || release.tag_name.nil?
+ existing_tags.include?(release[:tag_name]) || release[:tag_name].nil?
end
def build(release)
- existing_tags.add(release.tag_name)
+ existing_tags.add(release[:tag_name])
{
- name: release.name,
- tag: release.tag_name,
+ name: release[:name],
+ tag: release[:tag_name],
author_id: fetch_author_id(release),
description: description_for(release),
- created_at: release.created_at,
- updated_at: release.created_at,
+ created_at: release[:created_at],
+ updated_at: release[:created_at],
# Draft releases will have a null published_at
- released_at: release.published_at || Time.current,
+ released_at: release[:published_at] || Time.current,
project_id: project.id
}
end
@@ -45,7 +48,7 @@ module Gitlab
end
def description_for(release)
- release.body.presence || "Release for tag #{release.tag_name}"
+ release[:body].presence || "Release for tag #{release[:tag_name]}"
end
def object_type
diff --git a/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb b/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb
index 8a9ddfc6ec0..4090555c85e 100644
--- a/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb
+++ b/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb
@@ -22,13 +22,15 @@ module Gitlab
# To make it possible to identify issue in separated worker we need to patch
# Sawyer instances here with issue number
def each_associated(parent_record, associated)
+ associated = associated.to_h
+
compose_associated_id!(parent_record, associated)
return if already_imported?(associated)
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
pull_request = parent_record.is_a? MergeRequest
- associated.issue = { 'number' => parent_record.iid, 'pull_request' => pull_request }
+ associated[:issue] = { number: parent_record.iid, pull_request: pull_request }
yield(associated)
mark_as_imported(associated)
@@ -78,7 +80,7 @@ module Gitlab
end
def id_for_already_imported_cache(event)
- event.id
+ event[:id]
end
def collection_options
@@ -87,9 +89,9 @@ module Gitlab
# Cross-referenced events on Github doesn't have id.
def compose_associated_id!(issuable, event)
- return if event.event != 'cross-referenced'
+ return if event[:event] != 'cross-referenced'
- event.id = "cross-reference##{issuable.iid}-in-#{event.source.issue.id}"
+ event[:id] = "cross-reference##{issuable.iid}-in-#{event.dig(:source, :issue, :id)}"
end
end
end
diff --git a/lib/gitlab/github_import/issuable_finder.rb b/lib/gitlab/github_import/issuable_finder.rb
index e7a1b7b3368..b960df581e4 100644
--- a/lib/gitlab/github_import/issuable_finder.rb
+++ b/lib/gitlab/github_import/issuable_finder.rb
@@ -80,12 +80,16 @@ module Gitlab
end
def timeout
- if project.group.present? && ::Feature.enabled?(:github_importer_single_endpoint_notes_import, project.group, type: :ops)
+ if import_settings.enabled?(:single_endpoint_notes_import)
Gitlab::Cache::Import::Caching::LONGER_TIMEOUT
else
Gitlab::Cache::Import::Caching::TIMEOUT
end
end
+
+ def import_settings
+ ::Gitlab::GithubImport::Settings.new(project)
+ end
end
end
end
diff --git a/lib/gitlab/github_import/markdown/attachment.rb b/lib/gitlab/github_import/markdown/attachment.rb
new file mode 100644
index 00000000000..a5cf5ffa60e
--- /dev/null
+++ b/lib/gitlab/github_import/markdown/attachment.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Markdown
+ class Attachment
+ MEDIA_TYPES = %w[gif jpeg jpg mov mp4 png svg webm].freeze
+ DOC_TYPES = %w[
+ csv docx fodg fodp fods fodt gz log md odf odg odp ods
+ odt pdf pptx tgz txt xls xlsx zip
+ ].freeze
+
+ class << self
+ # markdown_node - CommonMarker::Node
+ def from_markdown(markdown_node)
+ case markdown_node.type
+ when :html, :inline_html
+ from_inline_html(markdown_node)
+ when :image
+ from_markdown_image(markdown_node)
+ when :link
+ from_markdown_link(markdown_node)
+ end
+ end
+
+ private
+
+ def from_markdown_image(markdown_node)
+ url = markdown_node.url
+
+ return unless github_url?(url, media: true)
+ return unless whitelisted_type?(url, media: true)
+
+ new(markdown_node.to_plaintext.strip, url)
+ end
+
+ def from_markdown_link(markdown_node)
+ url = markdown_node.url
+
+ return unless github_url?(url, docs: true)
+ return unless whitelisted_type?(url, docs: true)
+
+ new(markdown_node.to_plaintext.strip, url)
+ end
+
+ def from_inline_html(markdown_node)
+ img = Nokogiri::HTML.parse(markdown_node.string_content).xpath('//img')[0]
+
+ return unless img
+ return unless github_url?(img[:src], media: true)
+ return unless whitelisted_type?(img[:src], media: true)
+
+ new(img[:alt], img[:src])
+ end
+
+ def github_url?(url, docs: false, media: false)
+ if media
+ url.start_with?(::Gitlab::GithubImport::MarkdownText::GITHUB_MEDIA_CDN)
+ elsif docs
+ url.start_with?(::Gitlab::GithubImport::MarkdownText.github_url)
+ end
+ end
+
+ def whitelisted_type?(url, docs: false, media: false)
+ if media
+ MEDIA_TYPES.any? { |type| url.end_with?(type) }
+ elsif docs
+ DOC_TYPES.any? { |type| url.end_with?(type) }
+ end
+ end
+ end
+
+ attr_reader :name, :url
+
+ def initialize(name, url)
+ @name = name
+ @url = url
+ end
+
+ def inspect
+ "<#{self.class.name}: { name: #{name}, url: #{url} }>"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/markdown_text.rb b/lib/gitlab/github_import/markdown_text.rb
index bf2856bc77f..2424b3e8c1f 100644
--- a/lib/gitlab/github_import/markdown_text.rb
+++ b/lib/gitlab/github_import/markdown_text.rb
@@ -8,23 +8,12 @@ module Gitlab
class MarkdownText
include Gitlab::EncodingHelper
- ISSUE_REF_MATCHER = '%{github_url}/%{import_source}/issues'
- PULL_REF_MATCHER = '%{github_url}/%{import_source}/pull'
-
- MEDIA_TYPES = %w[gif jpeg jpg mov mp4 png svg webm].freeze
- DOC_TYPES = %w[
- csv docx fodg fodp fods fodt gz log md odf odg odp ods
- odt pdf pptx tgz txt xls xlsx zip
- ].freeze
- ALL_TYPES = (MEDIA_TYPES + DOC_TYPES).freeze
-
# On github.com we have base url for docs and CDN url for media.
# On github EE as far as we can know there is no CDN urls and media is placed on base url.
- # To no escape the escaping symbol we use single quotes instead of double with interpolation.
- # rubocop:disable Style/StringConcatenation
- CDN_URL_MATCHER = '(!\[.+\]\(%{github_media_cdn}/\d+/(\w|-)+\.(' + MEDIA_TYPES.join('|') + ')\))'
- BASE_URL_MATCHER = '(\[.+\]\(%{github_url}/.+/.+/files/\d+/.+\.(' + ALL_TYPES.join('|') + ')\))'
- # rubocop:enable Style/StringConcatenation
+ GITHUB_MEDIA_CDN = 'https://user-images.githubusercontent.com'
+
+ ISSUE_REF_MATCHER = '%{github_url}/%{import_source}/issues'
+ PULL_REF_MATCHER = '%{github_url}/%{import_source}/pull'
class << self
def format(*args)
@@ -42,20 +31,6 @@ module Gitlab
.gsub(pull_ref_matcher, url_helpers.project_merge_requests_url(project))
end
- def fetch_attachment_urls(text)
- cdn_url_matcher = CDN_URL_MATCHER % { github_media_cdn: Regexp.escape(github_media_cdn) }
- doc_url_matcher = BASE_URL_MATCHER % { github_url: Regexp.escape(github_url) }
-
- text.scan(Regexp.new(cdn_url_matcher)).map(&:first) +
- text.scan(Regexp.new(doc_url_matcher)).map(&:first)
- end
-
- private
-
- def github_media_cdn
- 'https://user-images.githubusercontent.com'
- end
-
# Returns github domain without slash in the end
def github_url
oauth_config = Gitlab::Auth::OAuth::Provider.config_for('github') || {}
@@ -63,6 +38,23 @@ module Gitlab
url = url.chop if url.end_with?('/')
url
end
+
+ def fetch_attachments(text)
+ attachments = []
+ doc = CommonMarker.render_doc(text)
+
+ doc.walk do |node|
+ attachment = extract_attachment(node)
+ attachments << attachment if attachment
+ end
+ attachments
+ end
+
+ private
+
+ def extract_attachment(node)
+ ::Gitlab::GithubImport::Markdown::Attachment.from_markdown(node)
+ end
end
# text - The Markdown text as a String.
diff --git a/lib/gitlab/github_import/parallel_scheduling.rb b/lib/gitlab/github_import/parallel_scheduling.rb
index bf5046de36c..03aa02fb659 100644
--- a/lib/gitlab/github_import/parallel_scheduling.rb
+++ b/lib/gitlab/github_import/parallel_scheduling.rb
@@ -125,9 +125,13 @@ module Gitlab
next unless page_counter.set(page.number)
page.objects.each do |object|
+ object = object.to_h
+
next if already_imported?(object)
- Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
+ if increment_object_counter?(object)
+ Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
+ end
yield object
@@ -138,6 +142,10 @@ module Gitlab
end
end
+ def increment_object_counter?(_object)
+ true
+ end
+
# Returns true if the given object has already been imported, false
# otherwise.
#
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index 64aa6ea5cb4..f3be90834c7 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -19,33 +19,33 @@ module Gitlab
# Builds a diff note from a GitHub API response.
#
- # note - An instance of `Sawyer::Resource` containing the note details.
+ # note - An instance of `Hash` containing the note details.
def self.from_api_response(note, additional_data = {})
- matches = note.html_url.match(NOTEABLE_ID_REGEX)
+ matches = note[:html_url].match(NOTEABLE_ID_REGEX)
unless matches
raise(
ArgumentError,
- "The note URL #{note.html_url.inspect} is not supported"
+ "The note URL #{note[:html_url].inspect} is not supported"
)
end
- user = Representation::User.from_api_response(note.user) if note.user
+ user = Representation::User.from_api_response(note[:user]) if note[:user]
hash = {
noteable_id: matches[:iid].to_i,
- file_path: note.path,
- commit_id: note.commit_id,
- original_commit_id: note.original_commit_id,
- diff_hunk: note.diff_hunk,
+ file_path: note[:path],
+ commit_id: note[:commit_id],
+ original_commit_id: note[:original_commit_id],
+ diff_hunk: note[:diff_hunk],
author: user,
- note: note.body,
- created_at: note.created_at,
- updated_at: note.updated_at,
- note_id: note.id,
- end_line: note.line,
- start_line: note.start_line,
- side: note.side,
- in_reply_to_id: note.in_reply_to_id
+ note: note[:body],
+ created_at: note[:created_at],
+ updated_at: note[:updated_at],
+ note_id: note[:id],
+ end_line: note[:line],
+ start_line: note[:start_line],
+ side: note[:side],
+ in_reply_to_id: note[:in_reply_to_id]
}
new(hash)
diff --git a/lib/gitlab/github_import/representation/issue.rb b/lib/gitlab/github_import/representation/issue.rb
index 9d457ec1c2f..e878aeaf3b9 100644
--- a/lib/gitlab/github_import/representation/issue.rb
+++ b/lib/gitlab/github_import/representation/issue.rb
@@ -15,28 +15,28 @@ module Gitlab
# Builds an issue from a GitHub API response.
#
- # issue - An instance of `Sawyer::Resource` containing the issue
+ # issue - An instance of `Hash` containing the issue
# details.
def self.from_api_response(issue, additional_data = {})
user =
- if issue.user
- Representation::User.from_api_response(issue.user)
+ if issue[:user]
+ Representation::User.from_api_response(issue[:user])
end
hash = {
- iid: issue.number,
- title: issue.title,
- description: issue.body,
- milestone_number: issue.milestone&.number,
- state: issue.state == 'open' ? :opened : :closed,
- assignees: issue.assignees.map do |u|
+ iid: issue[:number],
+ title: issue[:title],
+ description: issue[:body],
+ milestone_number: issue.dig(:milestone, :number),
+ state: issue[:state] == 'open' ? :opened : :closed,
+ assignees: issue[:assignees].map do |u|
Representation::User.from_api_response(u)
end,
- label_names: issue.labels.map(&:name),
+ label_names: issue[:labels].map { _1[:name] },
author: user,
- created_at: issue.created_at,
- updated_at: issue.updated_at,
- pull_request: issue.pull_request ? true : false,
+ created_at: issue[:created_at],
+ updated_at: issue[:updated_at],
+ pull_request: issue[:pull_request] ? true : false,
work_item_type_id: additional_data[:work_item_type_id]
}
diff --git a/lib/gitlab/github_import/representation/issue_event.rb b/lib/gitlab/github_import/representation/issue_event.rb
index 89271a7dcd6..39a23c016ce 100644
--- a/lib/gitlab/github_import/representation/issue_event.rb
+++ b/lib/gitlab/github_import/representation/issue_event.rb
@@ -34,23 +34,23 @@ module Gitlab
class << self
# Builds an event from a GitHub API response.
#
- # event - An instance of `Sawyer::Resource` containing the event details.
+ # event - An instance of `Hash` containing the event details.
def from_api_response(event, additional_data = {})
new(
- id: event.id,
- actor: user_representation(event.actor),
- event: event.event,
- commit_id: event.commit_id,
- label_title: event.label && event.label[:name],
- old_title: event.rename && event.rename[:from],
- new_title: event.rename && event.rename[:to],
- milestone_title: event.milestone && event.milestone[:title],
- issue: event.issue&.to_h&.symbolize_keys,
- source: event.source,
- assignee: user_representation(event.assignee),
- requested_reviewer: user_representation(event.requested_reviewer),
- review_requester: user_representation(event.review_requester),
- created_at: event.created_at
+ id: event[:id],
+ actor: user_representation(event[:actor]),
+ event: event[:event],
+ commit_id: event[:commit_id],
+ label_title: event.dig(:label, :name),
+ old_title: event.dig(:rename, :from),
+ new_title: event.dig(:rename, :to),
+ milestone_title: event.dig(:milestone, :title),
+ issue: event[:issue],
+ source: event[:source],
+ assignee: user_representation(event[:assignee]),
+ requested_reviewer: user_representation(event[:requested_reviewer]),
+ review_requester: user_representation(event[:review_requester]),
+ created_at: event[:created_at]
)
end
diff --git a/lib/gitlab/github_import/representation/note.rb b/lib/gitlab/github_import/representation/note.rb
index ae56c370b19..14379e8a4e9 100644
--- a/lib/gitlab/github_import/representation/note.rb
+++ b/lib/gitlab/github_import/representation/note.rb
@@ -16,14 +16,14 @@ module Gitlab
# Builds a note from a GitHub API response.
#
- # note - An instance of `Sawyer::Resource` containing the note details.
+ # note - An instance of `Hash` containing the note details.
def self.from_api_response(note, additional_data = {})
- matches = note.html_url.match(NOTEABLE_TYPE_REGEX)
+ matches = note[:html_url].match(NOTEABLE_TYPE_REGEX)
if !matches || !matches[:type]
raise(
ArgumentError,
- "The note URL #{note.html_url.inspect} is not supported"
+ "The note URL #{note[:html_url].inspect} is not supported"
)
end
@@ -34,15 +34,15 @@ module Gitlab
'Issue'
end
- user = Representation::User.from_api_response(note.user) if note.user
+ user = Representation::User.from_api_response(note[:user]) if note[:user]
hash = {
noteable_type: noteable_type,
noteable_id: matches[:iid].to_i,
author: user,
- note: note.body,
- created_at: note.created_at,
- updated_at: note.updated_at,
- note_id: note.id
+ note: note[:body],
+ created_at: note[:created_at],
+ updated_at: note[:updated_at],
+ note_id: note[:id]
}
new(hash)
diff --git a/lib/gitlab/github_import/representation/note_text.rb b/lib/gitlab/github_import/representation/note_text.rb
new file mode 100644
index 00000000000..505d7d805d3
--- /dev/null
+++ b/lib/gitlab/github_import/representation/note_text.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+# This class only partly represents MODELS_ALLOWLIST records from DB and
+# is used to connect ReleasesAttachmentsImporter, NotesAttachmentsImporter etc.
+# with NoteAttachmentsImporter without modifying ObjectImporter a lot.
+# Attachments are inside release's `description`.
+module Gitlab
+ module GithubImport
+ module Representation
+ class NoteText
+ include ToHash
+ include ExposeAttribute
+
+ MODELS_ALLOWLIST = [::Release, ::Note, ::Issue, ::MergeRequest].freeze
+ ModelNotSupported = Class.new(StandardError)
+
+ attr_reader :attributes
+
+ expose_attribute :record_db_id, :record_type, :text
+
+ class << self
+ # Builds a note text representation from DB record of Note or Release.
+ #
+ # record - An instance of `Note`, `Release`, `Issue`, `MergeRequest` model
+ def from_db_record(record)
+ check_record_class!(record)
+
+ record_type = record.class.name
+ # only column for note is different along MODELS_ALLOWLIST
+ text = record.is_a?(::Note) ? record.note : record.description
+ new(
+ record_db_id: record.id,
+ record_type: record_type,
+ text: text
+ )
+ end
+
+ def from_json_hash(raw_hash)
+ new Representation.symbolize_hash(raw_hash)
+ end
+
+ private
+
+ def check_record_class!(record)
+ raise ModelNotSupported, record.class.name if MODELS_ALLOWLIST.exclude?(record.class)
+ end
+ end
+
+ # attributes - A Hash containing the event details. The keys of this
+ # Hash (and any nested hashes) must be symbols.
+ def initialize(attributes)
+ @attributes = attributes
+ end
+
+ def github_identifiers
+ { db_id: record_db_id }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/representation/protected_branch.rb b/lib/gitlab/github_import/representation/protected_branch.rb
index b80b7cf1076..07a607ae70d 100644
--- a/lib/gitlab/github_import/representation/protected_branch.rb
+++ b/lib/gitlab/github_import/representation/protected_branch.rb
@@ -9,18 +9,22 @@ module Gitlab
attr_reader :attributes
- expose_attribute :id, :allow_force_pushes
+ expose_attribute :id, :allow_force_pushes, :required_conversation_resolution, :required_signatures,
+ :required_pull_request_reviews
# Builds a Branch Protection info from a GitHub API response.
# Resource structure details:
# https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection
- # branch_protection - An instance of `Sawyer::Resource` containing the protection details.
+ # branch_protection - An instance of `Hash` containing the protection details.
def self.from_api_response(branch_protection, _additional_object_data = {})
- branch_name = branch_protection.url.match(%r{/branches/(\S{1,255})/protection$})[1]
+ branch_name = branch_protection[:url].match(%r{/branches/(\S{1,255})/protection$})[1]
hash = {
id: branch_name,
- allow_force_pushes: branch_protection.allow_force_pushes.enabled
+ allow_force_pushes: branch_protection.dig(:allow_force_pushes, :enabled),
+ required_conversation_resolution: branch_protection.dig(:required_conversation_resolution, :enabled),
+ required_signatures: branch_protection.dig(:required_signatures, :enabled),
+ required_pull_request_reviews: branch_protection[:required_pull_request_reviews].present?
}
new(hash)
diff --git a/lib/gitlab/github_import/representation/pull_request.rb b/lib/gitlab/github_import/representation/pull_request.rb
index 2adac2af502..4b8ae1f8eab 100644
--- a/lib/gitlab/github_import/representation/pull_request.rb
+++ b/lib/gitlab/github_import/representation/pull_request.rb
@@ -17,30 +17,30 @@ module Gitlab
# Builds a PR from a GitHub API response.
#
- # issue - An instance of `Sawyer::Resource` containing the PR details.
+ # issue - An instance of `Hash` containing the PR details.
def self.from_api_response(pr, additional_data = {})
- assignee = Representation::User.from_api_response(pr.assignee) if pr.assignee
- user = Representation::User.from_api_response(pr.user) if pr.user
- merged_by = Representation::User.from_api_response(pr.merged_by) if pr.merged_by
+ assignee = Representation::User.from_api_response(pr[:assignee]) if pr[:assignee]
+ user = Representation::User.from_api_response(pr[:user]) if pr[:user]
+ merged_by = Representation::User.from_api_response(pr[:merged_by]) if pr[:merged_by]
hash = {
- iid: pr.number,
- title: pr.title,
- description: pr.body,
- source_branch: pr.head.ref,
- target_branch: pr.base.ref,
- source_branch_sha: pr.head.sha,
- target_branch_sha: pr.base.sha,
- source_repository_id: pr.head&.repo&.id,
- target_repository_id: pr.base&.repo&.id,
- source_repository_owner: pr.head&.user&.login,
- state: pr.state == 'open' ? :opened : :closed,
- milestone_number: pr.milestone&.number,
+ iid: pr[:number],
+ title: pr[:title],
+ description: pr[:body],
+ source_branch: pr.dig(:head, :ref),
+ target_branch: pr.dig(:base, :ref),
+ source_branch_sha: pr.dig(:head, :sha),
+ target_branch_sha: pr.dig(:base, :sha),
+ source_repository_id: pr.dig(:head, :repo, :id),
+ target_repository_id: pr.dig(:base, :repo, :id),
+ source_repository_owner: pr.dig(:head, :user, :login),
+ state: pr[:state] == 'open' ? :opened : :closed,
+ milestone_number: pr.dig(:milestone, :number),
author: user,
assignee: assignee,
- created_at: pr.created_at,
- updated_at: pr.updated_at,
- merged_at: pr.merged_at,
+ created_at: pr[:created_at],
+ updated_at: pr[:updated_at],
+ merged_at: pr[:merged_at],
merged_by: merged_by
}
diff --git a/lib/gitlab/github_import/representation/pull_request_review.rb b/lib/gitlab/github_import/representation/pull_request_review.rb
index 8a7ecf0c588..8fb57ae89a4 100644
--- a/lib/gitlab/github_import/representation/pull_request_review.rb
+++ b/lib/gitlab/github_import/representation/pull_request_review.rb
@@ -11,16 +11,19 @@ module Gitlab
expose_attribute :author, :note, :review_type, :submitted_at, :merge_request_id, :review_id
+ # Builds a PullRequestReview from a GitHub API response.
+ #
+ # review - An instance of `Hash` containing the note details.
def self.from_api_response(review, additional_data = {})
- user = Representation::User.from_api_response(review.user) if review.user
+ user = Representation::User.from_api_response(review[:user]) if review[:user]
new(
- merge_request_id: review.merge_request_id,
+ merge_request_id: review[:merge_request_id],
author: user,
- note: review.body,
- review_type: review.state,
- submitted_at: review.submitted_at,
- review_id: review.id
+ note: review[:body],
+ review_type: review[:state],
+ submitted_at: review[:submitted_at],
+ review_id: review[:id]
)
end
diff --git a/lib/gitlab/github_import/representation/release_attachments.rb b/lib/gitlab/github_import/representation/release_attachments.rb
deleted file mode 100644
index fd272be2405..00000000000
--- a/lib/gitlab/github_import/representation/release_attachments.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-# This class only partly represents Release record from DB and
-# is used to connect ReleasesAttachmentsImporter with ReleaseAttachmentsImporter
-# without modifying ObjectImporter a lot.
-# Attachments are inside release's `description`.
-module Gitlab
- module GithubImport
- module Representation
- class ReleaseAttachments
- include ToHash
- include ExposeAttribute
-
- attr_reader :attributes
-
- expose_attribute :release_db_id, :description
-
- # Builds a event from a GitHub API response.
- #
- # release - An instance of `Release` model.
- def self.from_db_record(release)
- new(
- release_db_id: release.id,
- description: release.description
- )
- end
-
- def self.from_json_hash(raw_hash)
- new Representation.symbolize_hash(raw_hash)
- end
-
- # attributes - A Hash containing the event details. The keys of this
- # Hash (and any nested hashes) must be symbols.
- def initialize(attributes)
- @attributes = attributes
- end
-
- def github_identifiers
- { db_id: release_db_id }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/github_import/representation/user.rb b/lib/gitlab/github_import/representation/user.rb
index 4ef916cc41c..02cbe037384 100644
--- a/lib/gitlab/github_import/representation/user.rb
+++ b/lib/gitlab/github_import/representation/user.rb
@@ -13,11 +13,11 @@ module Gitlab
# Builds a user from a GitHub API response.
#
- # user - An instance of `Sawyer::Resource` containing the user details.
+ # user - An instance of `Hash` containing the user details.
def self.from_api_response(user, additional_data = {})
new(
- id: user.id,
- login: user.login
+ id: user[:id],
+ login: user[:login]
)
end
diff --git a/lib/gitlab/github_import/settings.rb b/lib/gitlab/github_import/settings.rb
new file mode 100644
index 00000000000..77288b9fb98
--- /dev/null
+++ b/lib/gitlab/github_import/settings.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ class Settings
+ OPTIONAL_STAGES = {
+ single_endpoint_issue_events_import: {
+ label: 'Import issue and pull request events',
+ details: <<-TEXT.split("\n").map(&:strip).join(' ')
+ For example, opened or closed, renamed, and labeled or unlabeled.
+ Time required to import these events depends on how many issues or pull requests your project has.
+ TEXT
+ },
+ single_endpoint_notes_import: {
+ label: 'Use alternative comments import method',
+ details: <<-TEXT.split("\n").map(&:strip).join(' ')
+ The default method can skip some comments in large projects because of limitations of the GitHub API.
+ TEXT
+ },
+ attachments_import: {
+ label: 'Import Markdown attachments',
+ details: <<-TEXT.split("\n").map(&:strip).join(' ')
+ Import Markdown attachments from repository comments, release posts, issue descriptions,
+ and pull request descriptions. These can include images, text, or binary attachments.
+ If not imported, links in Markdown to attachments break after you remove the attachments from GitHub.
+ TEXT
+ }
+ }.freeze
+
+ def self.stages_array
+ OPTIONAL_STAGES.map do |stage_name, data|
+ {
+ name: stage_name.to_s,
+ label: s_(format("GitHubImport|%{text}", text: data[:label])),
+ details: s_(format("GitHubImport|%{text}", text: data[:details]))
+ }
+ end
+ end
+
+ def initialize(project)
+ @project = project
+ end
+
+ def write(user_settings)
+ user_settings = user_settings.to_h.with_indifferent_access
+
+ optional_stages = fetch_stages_from_params(user_settings)
+ import_data = project.create_or_update_import_data(data: { optional_stages: optional_stages })
+ import_data.save!
+ end
+
+ def enabled?(stage_name)
+ project.import_data&.data&.dig('optional_stages', stage_name.to_s) || false
+ end
+
+ def disabled?(stage_name)
+ !enabled?(stage_name)
+ end
+
+ private
+
+ attr_reader :project
+
+ def fetch_stages_from_params(user_settings)
+ OPTIONAL_STAGES.keys.to_h do |stage_name|
+ enabled = Gitlab::Utils.to_boolean(user_settings[stage_name], default: false)
+ [stage_name, enabled]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/single_endpoint_notes_importing.rb b/lib/gitlab/github_import/single_endpoint_notes_importing.rb
index aea4059dfbc..3584288da57 100644
--- a/lib/gitlab/github_import/single_endpoint_notes_importing.rb
+++ b/lib/gitlab/github_import/single_endpoint_notes_importing.rb
@@ -4,10 +4,10 @@
# - SingleEndpointDiffNotesImporter
# - SingleEndpointIssueNotesImporter
# - SingleEndpointMergeRequestNotesImporter
-# if `github_importer_single_endpoint_notes_import` feature flag is on.
+# if enabled by Gitlab::GithubImport::Settings
#
# - SingleEndpointIssueEventsImporter
-# if `github_importer_issue_events_import` feature flag is on.
+# if enabled by Gitlab::GithubImport::Settings
#
# Fetches associated objects page by page to each item of parent collection.
# Currently `associated` is note or event.
@@ -32,7 +32,7 @@ module Gitlab
end
def id_for_already_imported_cache(associated)
- associated.id
+ associated[:id]
end
def parent_collection
@@ -54,6 +54,8 @@ module Gitlab
# in Github API response object. For example:
# lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb:26
def each_associated(_parent_record, associated)
+ associated = associated.to_h
+
return if already_imported?(associated)
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
diff --git a/lib/gitlab/github_import/user_finder.rb b/lib/gitlab/github_import/user_finder.rb
index 1feb0d450f0..b8751def08f 100644
--- a/lib/gitlab/github_import/user_finder.rb
+++ b/lib/gitlab/github_import/user_finder.rb
@@ -39,18 +39,19 @@ module Gitlab
#
# If the object has no author ID we'll use the ID of the GitLab ghost
# user.
+ # object - An instance of `Hash` or a `Github::Representer`
def author_id_for(object, author_key: :author)
user_info = case author_key
when :actor
- object&.actor
+ object[:actor]
when :assignee
- object&.assignee
+ object[:assignee]
when :requested_reviewer
- object&.requested_reviewer
+ object[:requested_reviewer]
when :review_requester
- object&.review_requester
+ object[:review_requester]
else
- object&.author
+ object ? object[:author] : nil
end
id = user_info ? user_id_for(user_info) : GithubImport.ghost_user_id
@@ -64,14 +65,14 @@ module Gitlab
# Returns the GitLab user ID of an issuable's assignee.
def assignee_id_for(issuable)
- user_id_for(issuable.assignee) if issuable.assignee
+ user_id_for(issuable[:assignee]) if issuable[:assignee]
end
# Returns the GitLab user ID for a GitHub user.
#
- # user - An instance of `Gitlab::GithubImport::Representation::User`.
+ # user - An instance of `Gitlab::GithubImport::Representation::User` or `Hash`.
def user_id_for(user)
- find(user.id, user.login) if user.present?
+ find(user[:id], user[:login]) if user.present?
end
# Returns the GitLab ID for the given GitHub ID or username.
@@ -114,7 +115,7 @@ module Gitlab
unless email
user = client.user(username)
- email = Gitlab::Cache::Import::Caching.write(cache_key, user.email, timeout: timeout(user.email)) if user
+ email = Gitlab::Cache::Import::Caching.write(cache_key, user[:email], timeout: timeout(user[:email])) if user
end
email
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 08a614edb4b..bdb7484f3d6 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -15,6 +15,7 @@ module Gitlab
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
gon.markdown_surround_selection = current_user&.markdown_surround_selection
+ gon.markdown_automatic_lists = current_user&.markdown_automatic_lists
if Gitlab.config.sentry.enabled
gon.sentry_dsn = Gitlab.config.sentry.clientside_dsn
@@ -32,6 +33,7 @@ module Gitlab
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
gon.select2_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/select2.css')
+ gon.gridstack_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/gridstack.css')
gon.test_env = Rails.env.test?
gon.disable_animations = Gitlab.config.gitlab['disable_animations']
gon.suggested_label_colors = LabelsHelper.suggested_colors
@@ -55,7 +57,7 @@ module Gitlab
push_frontend_feature_flag(:security_auto_fix)
push_frontend_feature_flag(:new_header_search)
push_frontend_feature_flag(:source_editor_toolbar)
- push_frontend_feature_flag(:gl_avatar_for_all_user_avatars)
+ push_frontend_feature_flag(:integration_slack_app_notifications)
end
# Exposes the state of a feature flag to the frontend code.
diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb
index 987a5e7b74b..eca4d42fb9a 100644
--- a/lib/gitlab/graphql/pagination/keyset/connection.rb
+++ b/lib/gitlab/graphql/pagination/keyset/connection.rb
@@ -151,7 +151,7 @@ module Gitlab
def limit_value
# note: only first _or_ last can be specified, not both
- @limit_value ||= [first, last, max_page_size, GitlabSchema.default_max_page_size].compact.min
+ @limit_value ||= [first, last, max_page_size || GitlabSchema.default_max_page_size].compact.min
end
def loaded?(items)
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index 5b9216c0914..a2d06b7f5b3 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -44,28 +44,28 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 0,
'cs_CZ' => 0,
- 'da_DK' => 38,
+ 'da_DK' => 37,
'de' => 17,
'en' => 100,
'eo' => 0,
- 'es' => 37,
+ 'es' => 36,
'fil_PH' => 0,
- 'fr' => 11,
+ 'fr' => 72,
'gl_ES' => 0,
'id_ID' => 0,
'it' => 1,
'ja' => 31,
- 'ko' => 17,
- 'nb_NO' => 26,
+ 'ko' => 20,
+ 'nb_NO' => 25,
'nl_NL' => 0,
- 'pl_PL' => 4,
- 'pt_BR' => 56,
+ 'pl_PL' => 3,
+ 'pt_BR' => 57,
'ro_RO' => 99,
- 'ru' => 27,
- 'si_LK' => 10,
+ 'ru' => 26,
+ 'si_LK' => 11,
'tr_TR' => 11,
- 'uk' => 50,
- 'zh_CN' => 97,
+ 'uk' => 49,
+ 'zh_CN' => 98,
'zh_HK' => 1,
'zh_TW' => 99
}.freeze
diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
index 6c5fba37d7b..fe0ab01e4fd 100644
--- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
@@ -26,10 +26,10 @@ module Gitlab
log_info(message: "Started uploading project", export_size: export_size)
upload_duration = Benchmark.realtime do
- if Feature.enabled?(:import_export_web_upload_stream) && !project.export_file.file_storage?
- upload_project_as_remote_stream
- else
+ if project.export_file.file_storage?
handle_response_error(send_file)
+ else
+ upload_project_as_remote_stream
end
end
diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb
index bbec473d29d..b05d9cb2489 100644
--- a/lib/gitlab/import_export/base/relation_factory.rb
+++ b/lib/gitlab/import_export/base/relation_factory.rb
@@ -15,19 +15,19 @@ module Gitlab
UNIQUE_RELATIONS = %i[].freeze
USER_REFERENCES = %w[
- author_id
- assignee_id
- updated_by_id
- merged_by_id
- latest_closed_by_id
- user_id
- created_by_id
- last_edited_by_id
- merge_user_id
- resolved_by_id
- closed_by_id
- owner_id
- ].freeze
+ author_id
+ assignee_id
+ updated_by_id
+ merged_by_id
+ latest_closed_by_id
+ user_id
+ created_by_id
+ last_edited_by_id
+ merge_user_id
+ resolved_by_id
+ closed_by_id
+ owner_id
+ ].freeze
TOKEN_RESET_MODELS = %i[Project Namespace Group Ci::Trigger Ci::Build Ci::Runner ProjectHook ErrorTracking::ProjectErrorTrackingSetting].freeze
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index 99396d64779..cf62f181366 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -175,21 +175,22 @@ module Gitlab
order_expression = arel_table[column].public_send(direction).public_send(nulls_position) # rubocop:disable GitlabSecurity/PublicSend
reverse_order_expression = arel_table[column].public_send(reverse_direction).public_send(reverse_nulls_position) # rubocop:disable GitlabSecurity/PublicSend
- ::Gitlab::Pagination::Keyset::Order.build([
- ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: column,
- column_expression: arel_table[column],
- order_expression: order_expression,
- reversed_order_expression: reverse_order_expression,
- order_direction: direction,
- nullable: nulls_position,
- distinct: false
- ),
- ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: klass.primary_key,
- order_expression: arel_order_classes[direction].new(arel_table[klass.primary_key.to_sym])
- )
- ])
+ ::Gitlab::Pagination::Keyset::Order.build(
+ [
+ ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: column,
+ column_expression: arel_table[column],
+ order_expression: order_expression,
+ reversed_order_expression: reverse_order_expression,
+ order_direction: direction,
+ nullable: nulls_position,
+ distinct: false
+ ),
+ ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: klass.primary_key,
+ order_expression: arel_order_classes[direction].new(arel_table[klass.primary_key.to_sym])
+ )
+ ])
end
def read_from_replica_if_available(&block)
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index 33e4823f192..fb44aaf094e 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -98,6 +98,7 @@ tree:
- :statuses
- :external_pull_request
- :merge_request
+ - :pipeline_metadata
- :auto_devops
- :pipeline_schedules
- :container_expiration_policy
@@ -582,6 +583,9 @@ included_attributes:
- :iid
- :source_sha
- :target_sha
+ pipeline_metadata:
+ - :project_id
+ - :title
stages:
- :name
- :status
@@ -971,6 +975,8 @@ excluded_attributes:
- :external_pull_request_id
- :ci_ref_id
- :locked
+ pipeline_metadata:
+ - :pipeline_id
stages:
- :pipeline_id
merge_access_levels:
diff --git a/lib/gitlab/import_export/project/import_task.rb b/lib/gitlab/import_export/project/import_task.rb
index 89f2b36ea58..4ea47a5624a 100644
--- a/lib/gitlab/import_export/project/import_task.rb
+++ b/lib/gitlab/import_export/project/import_task.rb
@@ -64,7 +64,7 @@ module Gitlab
end
def execute_sidekiq_job
- Sidekiq::Worker.drain_all
+ Sidekiq::Worker.drain_all # rubocop:disable Cop/SidekiqApiUsage
end
def full_path
diff --git a/lib/gitlab/import_export/project/relation_factory.rb b/lib/gitlab/import_export/project/relation_factory.rb
index c4b0e24e34a..568315930d8 100644
--- a/lib/gitlab/import_export/project/relation_factory.rb
+++ b/lib/gitlab/import_export/project/relation_factory.rb
@@ -13,6 +13,7 @@ module Gitlab
pipeline_schedules: 'Ci::PipelineSchedule',
builds: 'Ci::Build',
runners: 'Ci::Runner',
+ pipeline_metadata: 'Ci::PipelineMetadata',
hooks: 'ProjectHook',
merge_access_levels: 'ProtectedBranch::MergeAccessLevel',
push_access_levels: 'ProtectedBranch::PushAccessLevel',
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index ad19508fb99..bc0563729a7 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -86,8 +86,9 @@ module Gitlab
mkdir_p(File.join(uploads_export_path, secret))
download_or_copy_upload(upload, upload_path)
- rescue Errno::ENAMETOOLONG => e
- # Do not fail entire project export if downloaded file has filename that exceeds 255 characters.
+ rescue StandardError => e
+ # Do not fail entire project export if something goes wrong during file download
+ # (e.g. downloaded file has filename that exceeds 255 characters).
# Ignore raised exception, skip such upload, log the error and keep going with the export instead.
Gitlab::ErrorTracking.log_exception(e, project_id: @project.id)
end
diff --git a/lib/gitlab/jira_import/handle_labels_service.rb b/lib/gitlab/jira_import/handle_labels_service.rb
index 1b00515cced..60d7f9e93d9 100644
--- a/lib/gitlab/jira_import/handle_labels_service.rb
+++ b/lib/gitlab/jira_import/handle_labels_service.rb
@@ -12,7 +12,7 @@ module Gitlab
return if jira_labels.blank?
existing_labels = LabelsFinder.new(nil, project: project, title: jira_labels)
- .execute(skip_authorization: true).select(:id, :name)
+ .execute(skip_authorization: true).select(:id, :project_id, :group_id, :type, :name)
new_labels = create_missing_labels(existing_labels)
label_ids = existing_labels.map(&:id)
diff --git a/lib/gitlab/jira_import/issues_importer.rb b/lib/gitlab/jira_import/issues_importer.rb
index 25dffcbe0ee..5057317ae01 100644
--- a/lib/gitlab/jira_import/issues_importer.rb
+++ b/lib/gitlab/jira_import/issues_importer.rb
@@ -7,10 +7,6 @@ module Gitlab
# see https://jira.atlassian.com/browse/JRACLOUD-67570
# We set it to 1000 in case they change their mind.
BATCH_SIZE = 1000
- JIRA_IMPORT_THRESHOLD = 100_000
- JIRA_IMPORT_PAUSE_LIMIT = 50_000
-
- RetriesExceededError = Class.new(RuntimeError)
attr_reader :imported_items_cache_key, :start_at, :job_waiter
@@ -52,7 +48,7 @@ module Gitlab
end
def schedule_issue_import_workers(issues)
- next_iid = project.issues.maximum(:iid).to_i + 1
+ next_iid = Issue.with_project_iid_supply(project, &:next_value)
issues.each do |jira_issue|
# Technically it's possible that the same work is performed multiple
@@ -71,13 +67,11 @@ module Gitlab
{ iid: next_iid }
).execute
- # Pause the importer to allow the import to catch up and cache to drain
- pause_jira_issue_importer if jira_import_issue_worker.queue_size > JIRA_IMPORT_THRESHOLD
-
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
job_waiter.jobs_remaining += 1
- next_iid += 1
+
+ next_iid = Issue.with_project_iid_supply(project, &:next_value)
# Mark the issue as imported immediately so we don't end up
# importing it multiple times within same import.
@@ -97,27 +91,6 @@ module Gitlab
job_waiter
end
- def jira_import_issue_worker
- @_jira_import_issue_worker ||= Gitlab::JiraImport::ImportIssueWorker
- end
-
- def pause_jira_issue_importer
- # Wait for import workers to drop below 50K in the iterations of the timeout
- # timeout - Set to 5 seconds.
- # Time to process 100K jobs is currently ~14 seconds.
- # Source: https://github.com/mperham/sidekiq#performance
- # retries - Set to 10 times to avoid indefinitely pause.
- # Raises an error if the queue does not reduce below the limit after 10 tries.
-
- retries = 10
- while retries > 0 && jira_import_issue_worker.queue_size >= JIRA_IMPORT_PAUSE_LIMIT
- job_waiter.wait(5)
- retries -= 1
- end
-
- raise RetriesExceededError, 'Retry failed after 10 attempts' if retries == 0
- end
-
def fetch_issues(start_at)
client.Issue.jql("PROJECT='#{jira_project_key}' ORDER BY created ASC", { max_results: BATCH_SIZE, start_at: start_at })
end
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index ce07752f88c..823d6202b1e 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -34,6 +34,7 @@ module Gitlab
alias_method :parse!, :parse
alias_method :load, :parse
+ alias_method :decode, :parse
# Restricted method for converting a Ruby object to JSON. If you
# need to pass options to this, you should use `.generate` instead,
@@ -56,6 +57,8 @@ module Gitlab
adapter_generate(object, opts)
end
+ alias_method :encode, :generate
+
# Generates JSON for an object and makes it look purdy
#
# The Oj variant in this looks seriously weird but these are the settings
diff --git a/lib/gitlab/kroki.rb b/lib/gitlab/kroki.rb
index fa10e922c80..6799be8e279 100644
--- a/lib/gitlab/kroki.rb
+++ b/lib/gitlab/kroki.rb
@@ -6,13 +6,13 @@ module Gitlab
# Helper methods for Kroki
module Kroki
BLOCKDIAG_FORMATS = %w[
- blockdiag
- seqdiag
- actdiag
- nwdiag
- packetdiag
- rackdiag
- ].freeze
+ blockdiag
+ seqdiag
+ actdiag
+ nwdiag
+ packetdiag
+ rackdiag
+ ].freeze
DIAGRAMS_FORMATS = (::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES - %w(mermaid)).freeze
DIAGRAMS_FORMATS_WO_PLANTUML = (DIAGRAMS_FORMATS - %w(plantuml)).freeze
diff --git a/lib/gitlab/legacy_github_import/base_formatter.rb b/lib/gitlab/legacy_github_import/base_formatter.rb
index 0b19cf742ed..7bb33cd474b 100644
--- a/lib/gitlab/legacy_github_import/base_formatter.rb
+++ b/lib/gitlab/legacy_github_import/base_formatter.rb
@@ -23,7 +23,7 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def url
- raw_data.url || ''
+ raw_data[:url] || ''
end
end
end
diff --git a/lib/gitlab/legacy_github_import/branch_formatter.rb b/lib/gitlab/legacy_github_import/branch_formatter.rb
index 1177751457f..372c6b2e8a0 100644
--- a/lib/gitlab/legacy_github_import/branch_formatter.rb
+++ b/lib/gitlab/legacy_github_import/branch_formatter.rb
@@ -3,7 +3,17 @@
module Gitlab
module LegacyGithubImport
class BranchFormatter < BaseFormatter
- delegate :repo, :sha, :ref, to: :raw_data
+ def repo
+ raw_data[:repo]
+ end
+
+ def sha
+ raw_data[:sha]
+ end
+
+ def ref
+ raw_data[:ref]
+ end
def exists?
branch_exists? && commit_exists?
@@ -14,7 +24,7 @@ module Gitlab
end
def user
- raw_data.user&.login || 'unknown'
+ raw_data.dig(:user, :login) || 'unknown'
end
def short_sha
diff --git a/lib/gitlab/legacy_github_import/comment_formatter.rb b/lib/gitlab/legacy_github_import/comment_formatter.rb
index d83cc4f6b3c..ffd9da604ca 100644
--- a/lib/gitlab/legacy_github_import/comment_formatter.rb
+++ b/lib/gitlab/legacy_github_import/comment_formatter.rb
@@ -9,19 +9,19 @@ module Gitlab
{
project: project,
note: note,
- commit_id: raw_data.commit_id,
+ commit_id: raw_data[:commit_id],
line_code: line_code,
author_id: author_id,
type: type,
- created_at: raw_data.created_at,
- updated_at: raw_data.updated_at
+ created_at: raw_data[:created_at],
+ updated_at: raw_data[:updated_at]
}
end
private
def author
- @author ||= UserFormatter.new(client, raw_data.user)
+ @author ||= UserFormatter.new(client, raw_data[:user])
end
def author_id
@@ -29,7 +29,7 @@ module Gitlab
end
def body
- raw_data.body || ""
+ raw_data[:body] || ""
end
def line_code
@@ -48,11 +48,11 @@ module Gitlab
end
def diff_hunk
- raw_data.diff_hunk
+ raw_data[:diff_hunk]
end
def file_path
- raw_data.path
+ raw_data[:path]
end
def note
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index 4ddafbac4c6..331eab7b62a 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -96,7 +96,7 @@ module Gitlab
def import_labels
fetch_resources(:labels, repo, per_page: 100) do |labels|
labels.each do |raw|
- gh_label = LabelFormatter.new(project, raw)
+ gh_label = LabelFormatter.new(project, raw.to_h)
gh_label.create!
rescue StandardError => e
errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(gh_label.url), errors: e.message }
@@ -109,7 +109,7 @@ module Gitlab
def import_milestones
fetch_resources(:milestones, repo, state: :all, per_page: 100) do |milestones|
milestones.each do |raw|
- gh_milestone = MilestoneFormatter.new(project, raw)
+ gh_milestone = MilestoneFormatter.new(project, raw.to_h)
gh_milestone.create!
rescue StandardError => e
errors << { type: :milestone, url: Gitlab::UrlSanitizer.sanitize(gh_milestone.url), errors: e.message }
@@ -121,6 +121,7 @@ module Gitlab
def import_issues
fetch_resources(:issues, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |issues|
issues.each do |raw|
+ raw = raw.to_h
gh_issue = IssueFormatter.new(project, raw, client)
begin
@@ -143,6 +144,7 @@ module Gitlab
def import_pull_requests
fetch_resources(:pull_requests, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |pull_requests|
pull_requests.each do |raw|
+ raw = raw.to_h
gh_pull_request = PullRequestFormatter.new(project, raw, client)
next unless gh_pull_request.valid?
@@ -190,10 +192,12 @@ module Gitlab
end
def apply_labels(issuable, raw)
- return unless raw.labels.count > 0
+ raw = raw.to_h
- label_ids = raw.labels
- .map { |attrs| @labels[attrs.name] }
+ return unless raw[:labels].count > 0
+
+ label_ids = raw[:labels]
+ .map { |attrs| @labels[attrs[:name]] }
.compact
issuable.update_attribute(:label_ids, label_ids)
@@ -226,10 +230,12 @@ module Gitlab
def create_comments(comments)
ActiveRecord::Base.no_touching do
comments.each do |raw|
+ raw = raw.to_h
+
comment = CommentFormatter.new(project, raw, client)
# GH does not return info about comment's parent, so we guess it by checking its URL!
- *_, parent, iid = URI(raw.html_url).path.split('/')
+ *_, parent, iid = URI(raw[:html_url]).path.split('/')
issuable = if parent == 'issues'
Issue.find_by(project_id: project.id, iid: iid)
@@ -241,7 +247,7 @@ module Gitlab
issuable.notes.create!(comment.attributes)
rescue StandardError => e
- errors << { type: :comment, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message }
+ errors << { type: :comment, url: Gitlab::UrlSanitizer.sanitize(raw[:url]), errors: e.message }
end
end
end
@@ -251,7 +257,7 @@ module Gitlab
last_note_attrs = nil
cut_off_index = comments.find_index do |raw|
- comment = CommentFormatter.new(project, raw)
+ comment = CommentFormatter.new(project, raw.to_h)
comment_attrs = comment.attributes
last_note_attrs ||= last_note.slice(*comment_attrs.keys)
@@ -282,7 +288,7 @@ module Gitlab
def import_releases
fetch_resources(:releases, repo, per_page: 100) do |releases|
releases.each do |raw|
- gh_release = ReleaseFormatter.new(project, raw)
+ gh_release = ReleaseFormatter.new(project, raw.to_h)
gh_release.create! if gh_release.valid?
rescue StandardError => e
errors << { type: :release, url: Gitlab::UrlSanitizer.sanitize(gh_release.url), errors: e.message }
diff --git a/lib/gitlab/legacy_github_import/issuable_formatter.rb b/lib/gitlab/legacy_github_import/issuable_formatter.rb
index 1a0aefbbd62..e4e333735be 100644
--- a/lib/gitlab/legacy_github_import/issuable_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issuable_formatter.rb
@@ -9,7 +9,9 @@ module Gitlab
raise NotImplementedError
end
- delegate :number, to: :raw_data
+ def number
+ raw_data[:number]
+ end
def find_condition
{ iid: number }
@@ -18,15 +20,15 @@ module Gitlab
private
def state
- raw_data.state == 'closed' ? 'closed' : 'opened'
+ raw_data[:state] == 'closed' ? 'closed' : 'opened'
end
def assigned?
- raw_data.assignee.present?
+ raw_data[:assignee].present?
end
def author
- @author ||= UserFormatter.new(client, raw_data.user)
+ @author ||= UserFormatter.new(client, raw_data[:user])
end
def author_id
@@ -35,7 +37,7 @@ module Gitlab
def assignee
if assigned?
- @assignee ||= UserFormatter.new(client, raw_data.assignee)
+ @assignee ||= UserFormatter.new(client, raw_data[:assignee])
end
end
@@ -46,7 +48,7 @@ module Gitlab
end
def body
- raw_data.body || ""
+ raw_data[:body] || ""
end
def description
@@ -59,8 +61,8 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def milestone
- if raw_data.milestone.present?
- milestone = MilestoneFormatter.new(project, raw_data.milestone)
+ if raw_data[:milestone].present?
+ milestone = MilestoneFormatter.new(project, raw_data[:milestone])
project.milestones.find_by(milestone.find_condition)
end
end
diff --git a/lib/gitlab/legacy_github_import/issue_formatter.rb b/lib/gitlab/legacy_github_import/issue_formatter.rb
index 2f46e2e30d1..e5c568207e3 100644
--- a/lib/gitlab/legacy_github_import/issue_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issue_formatter.rb
@@ -8,18 +8,18 @@ module Gitlab
iid: number,
project: project,
milestone: milestone,
- title: raw_data.title,
+ title: raw_data[:title],
description: description,
state: state,
author_id: author_id,
assignee_ids: Array(assignee_id),
- created_at: raw_data.created_at,
- updated_at: raw_data.updated_at
+ created_at: raw_data[:created_at],
+ updated_at: raw_data[:updated_at]
}
end
def has_comments?
- raw_data.comments > 0
+ raw_data[:comments] > 0
end
def project_association
@@ -27,7 +27,7 @@ module Gitlab
end
def pull_request?
- raw_data.pull_request.present?
+ raw_data[:pull_request].present?
end
end
end
diff --git a/lib/gitlab/legacy_github_import/label_formatter.rb b/lib/gitlab/legacy_github_import/label_formatter.rb
index 415b1b8878f..e3b767f41fa 100644
--- a/lib/gitlab/legacy_github_import/label_formatter.rb
+++ b/lib/gitlab/legacy_github_import/label_formatter.rb
@@ -28,11 +28,11 @@ module Gitlab
private
def color
- "##{raw_data.color}"
+ "##{raw_data[:color]}"
end
def title
- raw_data.name
+ raw_data[:name]
end
end
end
diff --git a/lib/gitlab/legacy_github_import/milestone_formatter.rb b/lib/gitlab/legacy_github_import/milestone_formatter.rb
index 2fe1b4258d3..60d5bcbf44a 100644
--- a/lib/gitlab/legacy_github_import/milestone_formatter.rb
+++ b/lib/gitlab/legacy_github_import/milestone_formatter.rb
@@ -7,12 +7,12 @@ module Gitlab
{
iid: number,
project: project,
- title: raw_data.title,
- description: raw_data.description,
- due_date: raw_data.due_on,
+ title: raw_data[:title],
+ description: raw_data[:description],
+ due_date: raw_data[:due_on],
state: state,
- created_at: raw_data.created_at,
- updated_at: raw_data.updated_at
+ created_at: raw_data[:created_at],
+ updated_at: raw_data[:updated_at]
}
end
@@ -26,16 +26,16 @@ module Gitlab
def number
if project.gitea_import?
- raw_data.id
+ raw_data[:id]
else
- raw_data.number
+ raw_data[:number]
end
end
private
def state
- raw_data.state == 'closed' ? 'closed' : 'active'
+ raw_data[:state] == 'closed' ? 'closed' : 'active'
end
end
end
diff --git a/lib/gitlab/legacy_github_import/pull_request_formatter.rb b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
index 5b847f13d4a..72adba30093 100644
--- a/lib/gitlab/legacy_github_import/pull_request_formatter.rb
+++ b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
@@ -9,7 +9,7 @@ module Gitlab
def attributes
{
iid: number,
- title: raw_data.title,
+ title: raw_data[:title],
description: description,
source_project: source_branch_project,
source_branch: source_branch_name,
@@ -21,8 +21,8 @@ module Gitlab
milestone: milestone,
author_id: author_id,
assignee_id: assignee_id,
- created_at: raw_data.created_at,
- updated_at: raw_data.updated_at,
+ created_at: raw_data[:created_at],
+ updated_at: raw_data[:updated_at],
imported: true
}
end
@@ -36,7 +36,7 @@ module Gitlab
end
def source_branch
- @source_branch ||= BranchFormatter.new(project, raw_data.head)
+ @source_branch ||= BranchFormatter.new(project, raw_data[:head])
end
def source_branch_name
@@ -57,7 +57,7 @@ module Gitlab
end
def target_branch
- @target_branch ||= BranchFormatter.new(project, raw_data.base)
+ @target_branch ||= BranchFormatter.new(project, raw_data[:base])
end
def target_branch_name
@@ -71,7 +71,7 @@ module Gitlab
def cross_project?
return true if source_branch_repo.nil?
- source_branch_repo.id != target_branch_repo.id
+ source_branch_repo[:id] != target_branch_repo[:id]
end
def opened?
@@ -81,7 +81,7 @@ module Gitlab
private
def state
- if raw_data.state == 'closed' && raw_data.merged_at.present?
+ if raw_data[:state] == 'closed' && raw_data[:merged_at].present?
'merged'
else
super
diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb
index 0fb7e376f5b..2a54a15429b 100644
--- a/lib/gitlab/legacy_github_import/release_formatter.rb
+++ b/lib/gitlab/legacy_github_import/release_formatter.rb
@@ -6,13 +6,13 @@ module Gitlab
def attributes
{
project: project,
- tag: raw_data.tag_name,
- name: raw_data.name,
- description: raw_data.body,
- created_at: raw_data.created_at,
+ tag: raw_data[:tag_name],
+ name: raw_data[:name],
+ description: raw_data[:body],
+ created_at: raw_data[:created_at],
# Draft releases will have a null published_at
- released_at: raw_data.published_at || Time.current,
- updated_at: raw_data.created_at
+ released_at: raw_data[:published_at] || Time.current,
+ updated_at: raw_data[:created_at]
}
end
@@ -21,11 +21,11 @@ module Gitlab
end
def find_condition
- { tag: raw_data.tag_name }
+ { tag: raw_data[:tag_name] }
end
def valid?
- !raw_data.draft && raw_data.tag_name.present?
+ !raw_data[:draft] && raw_data[:tag_name].present?
end
end
end
diff --git a/lib/gitlab/legacy_github_import/user_formatter.rb b/lib/gitlab/legacy_github_import/user_formatter.rb
index 7ae1b195ec6..d45a166d2b7 100644
--- a/lib/gitlab/legacy_github_import/user_formatter.rb
+++ b/lib/gitlab/legacy_github_import/user_formatter.rb
@@ -5,13 +5,19 @@ module Gitlab
class UserFormatter
attr_reader :client, :raw
- delegate :id, :login, to: :raw, allow_nil: true
-
def initialize(client, raw)
@client = client
@raw = raw
end
+ def id
+ raw[:id]
+ end
+
+ def login
+ raw[:login]
+ end
+
def gitlab_id
return @gitlab_id if defined?(@gitlab_id)
@@ -21,7 +27,7 @@ module Gitlab
private
def email
- @email ||= client.user(raw.login).try(:email)
+ @email ||= client.user(raw[:login]).to_h[:email]
end
def find_by_email
diff --git a/lib/gitlab/memory/diagnostic_reports_logger.rb b/lib/gitlab/memory/diagnostic_reports_logger.rb
new file mode 100644
index 00000000000..cc5b719fa19
--- /dev/null
+++ b/lib/gitlab/memory/diagnostic_reports_logger.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+module Gitlab
+ module Memory
+ class DiagnosticReportsLogger < ::Logger
+ def format_message(severity, timestamp, progname, message)
+ data = {}
+ data[:severity] = severity
+ data[:time] = timestamp.utc.iso8601(3)
+
+ data.merge!(message)
+
+ "#{JSON.generate(data)}\n" # rubocop:disable Gitlab/Json
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/reports_daemon.rb b/lib/gitlab/memory/reports_daemon.rb
index ed1da8baab5..0dfc31235e7 100644
--- a/lib/gitlab/memory/reports_daemon.rb
+++ b/lib/gitlab/memory/reports_daemon.rb
@@ -7,7 +7,7 @@ module Gitlab
DEFAULT_SLEEP_MAX_DELTA_S = 600 # 0..10 minutes
DEFAULT_SLEEP_BETWEEN_REPORTS_S = 120 # 2 minutes
- DEFAULT_REPORTS_PATH = '/tmp'
+ DEFAULT_REPORTS_PATH = Dir.tmpdir
def initialize(**options)
super
diff --git a/lib/gitlab/memory/reports_uploader.rb b/lib/gitlab/memory/reports_uploader.rb
new file mode 100644
index 00000000000..76c3e0862e2
--- /dev/null
+++ b/lib/gitlab/memory/reports_uploader.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require_relative '../metrics/system'
+
+module Gitlab
+ module Memory
+ class ReportsUploader
+ def initialize(gcs_key:, gcs_project:, gcs_bucket:, logger:)
+ @gcs_bucket = gcs_bucket
+ @fog = Fog::Storage::Google.new(google_project: gcs_project, google_json_key_location: gcs_key)
+ @logger = logger
+ end
+
+ def upload(path)
+ log_upload_requested(path)
+ start_monotonic_time = Gitlab::Metrics::System.monotonic_time
+
+ File.open(path.to_s) { |file| fog.put_object(gcs_bucket, File.basename(path), file) }
+
+ duration_s = Gitlab::Metrics::System.monotonic_time - start_monotonic_time
+ log_upload_success(path, duration_s)
+ rescue StandardError, Errno::ENOENT => error
+ log_exception(error)
+ end
+
+ private
+
+ attr_reader :gcs_bucket, :fog, :logger
+
+ def log_upload_requested(path)
+ logger.info(log_labels.merge(perf_report_status: 'upload requested', perf_report_path: path))
+ end
+
+ def log_upload_success(path, duration_s)
+ logger.info(log_labels.merge(perf_report_status: 'upload success', perf_report_path: path,
+ duration_s: duration_s))
+ end
+
+ def log_exception(error)
+ logger.error(log_labels.merge(perf_report_status: "error", error: error.message))
+ end
+
+ def log_labels
+ {
+ message: "Diagnostic reports",
+ class: self.class.name,
+ pid: $$
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/upload_and_cleanup_reports.rb b/lib/gitlab/memory/upload_and_cleanup_reports.rb
new file mode 100644
index 00000000000..27d94df478c
--- /dev/null
+++ b/lib/gitlab/memory/upload_and_cleanup_reports.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class UploadAndCleanupReports
+ DEFAULT_SLEEP_TIME_SECONDS = 900 # 15 minutes
+
+ def initialize(
+ uploader:,
+ reports_path:,
+ logger:,
+ sleep_time_seconds: ENV['GITLAB_DIAGNOSTIC_REPORTS_UPLOADER_SLEEP_S']&.to_i || DEFAULT_SLEEP_TIME_SECONDS)
+
+ @uploader = uploader
+ @reports_path = reports_path
+ @sleep_time_seconds = sleep_time_seconds
+ @alive = true
+ @logger = logger
+ end
+
+ attr_reader :uploader, :reports_path, :sleep_time_seconds, :logger
+
+ def call
+ log_started
+
+ loop do
+ sleep(sleep_time_seconds)
+
+ files_to_process.each { |path| upload_and_cleanup!(path) }
+ end
+ end
+
+ private
+
+ def upload_and_cleanup!(path)
+ uploader.upload(path)
+ rescue StandardError, Errno::ENOENT => error
+ log_exception(error)
+ ensure
+ cleanup!(path)
+ end
+
+ def cleanup!(path)
+ File.unlink(path) if File.exist?(path)
+ rescue Errno::ENOENT
+ # Path does not exist: Ignore. We already check `File.exist?`. Rescue to be extra safe.
+ end
+
+ def files_to_process
+ Dir.entries(reports_path)
+ .map { |path| File.join(reports_path, path) }
+ .select { |path| File.file?(path) }
+ end
+
+ def log_started
+ logger.info(log_labels.merge(perf_report_status: "started"))
+ end
+
+ def log_exception(error)
+ logger.error(log_labels.merge(perf_report_status: "error", error: error.message))
+ end
+
+ def log_labels
+ {
+ message: "Diagnostic reports",
+ class: self.class.name,
+ pid: $$
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog.rb b/lib/gitlab/memory/watchdog.rb
index 38231fa933b..7007fdfe386 100644
--- a/lib/gitlab/memory/watchdog.rb
+++ b/lib/gitlab/memory/watchdog.rb
@@ -2,25 +2,10 @@
module Gitlab
module Memory
- # A background thread that observes Ruby heap fragmentation and calls
- # into a handler when the Ruby heap has been fragmented for an extended
- # period of time.
- #
- # See Gitlab::Metrics::Memory for how heap fragmentation is defined.
- #
- # To decide whether a given fragmentation level is being exceeded,
- # the watchdog regularly polls the GC. Whenever a violation occurs
- # a strike is issued. If the maximum number of strikes are reached,
- # a handler is invoked to deal with the situation.
- #
- # The duration for which a process may be above a given fragmentation
- # threshold is computed as `max_strikes * sleep_time_seconds`.
+ # A background thread that monitors Ruby memory and calls
+ # into a handler when the Ruby process violates defined limits
+ # for an extended period of time.
class Watchdog
- DEFAULT_SLEEP_TIME_SECONDS = 60 * 5
- DEFAULT_MAX_HEAP_FRAG = 0.5
- DEFAULT_MAX_MEM_GROWTH = 3.0
- DEFAULT_MAX_STRIKES = 5
-
# This handler does nothing. It returns `false` to indicate to the
# caller that the situation has not been dealt with so it will
# receive calls repeatedly if fragmentation remains high.
@@ -62,73 +47,27 @@ module Gitlab
end
end
- # max_heap_fragmentation:
- # The degree to which the Ruby heap is allowed to be fragmented. Range [0,1].
- # max_mem_growth:
- # A multiplier for how much excess private memory a worker can map compared to a reference process
- # (itself or the primary in a pre-fork server.)
- # max_strikes:
- # How many times the process is allowed to be above max_heap_fragmentation before
- # a handler is invoked.
- # sleep_time_seconds:
- # Used to control the frequency with which the watchdog will wake up and poll the GC.
- def initialize(
- handler: NullHandler.instance,
- logger: Logger.new($stdout),
- max_heap_fragmentation: ENV['GITLAB_MEMWD_MAX_HEAP_FRAG']&.to_f || DEFAULT_MAX_HEAP_FRAG,
- max_mem_growth: ENV['GITLAB_MEMWD_MAX_MEM_GROWTH']&.to_f || DEFAULT_MAX_MEM_GROWTH,
- max_strikes: ENV['GITLAB_MEMWD_MAX_STRIKES']&.to_i || DEFAULT_MAX_STRIKES,
- sleep_time_seconds: ENV['GITLAB_MEMWD_SLEEP_TIME_SEC']&.to_i || DEFAULT_SLEEP_TIME_SECONDS,
- **options)
- super(**options)
-
- @handler = handler
- @logger = logger
- @sleep_time_seconds = sleep_time_seconds
- @max_strikes = max_strikes
- @stats = {
- heap_frag: {
- max: max_heap_fragmentation,
- strikes: 0
- },
- mem_growth: {
- max: max_mem_growth,
- strikes: 0
- }
- }
-
+ def initialize
+ @configuration = Configuration.new
@alive = true
- init_prometheus_metrics(max_heap_fragmentation)
- end
-
- attr_reader :max_strikes, :sleep_time_seconds
-
- def max_heap_fragmentation
- @stats[:heap_frag][:max]
- end
-
- def max_mem_growth
- @stats[:mem_growth][:max]
+ init_prometheus_metrics
end
- def strikes(stat)
- @stats[stat][:strikes]
+ def configure
+ yield @configuration
end
def call
- @logger.info(log_labels.merge(message: 'started'))
+ logger.info(log_labels.merge(message: 'started'))
while @alive
- sleep(@sleep_time_seconds)
-
- next unless Feature.enabled?(:gitlab_memory_watchdog, type: :ops)
+ sleep(sleep_time_seconds)
- monitor_heap_fragmentation
- monitor_memory_growth
+ monitor if Feature.enabled?(:gitlab_memory_watchdog, type: :ops)
end
- @logger.info(log_labels.merge(message: 'stopped'))
+ logger.info(log_labels.merge(message: 'stopped'))
end
def stop
@@ -137,71 +76,24 @@ module Gitlab
private
- def monitor_memory_condition(stat_key)
- return unless @alive
-
- stat = @stats[stat_key]
-
- ok, labels = yield(stat)
+ def monitor
+ @configuration.monitors.call_each do |result|
+ break unless @alive
- if ok
- stat[:strikes] = 0
- else
- stat[:strikes] += 1
- @counter_violations.increment(reason: stat_key.to_s)
- end
+ next unless result.threshold_violated?
- if stat[:strikes] > @max_strikes
- @alive = !memory_limit_exceeded_callback(stat_key, labels)
- stat[:strikes] = 0
- end
- end
+ @counter_violations.increment(reason: result.monitor_name)
- def monitor_heap_fragmentation
- monitor_memory_condition(:heap_frag) do |stat|
- heap_fragmentation = Gitlab::Metrics::Memory.gc_heap_fragmentation
- [
- heap_fragmentation <= stat[:max],
- {
- message: 'heap fragmentation limit exceeded',
- memwd_cur_heap_frag: heap_fragmentation,
- memwd_max_heap_frag: stat[:max]
- }
- ]
- end
- end
+ next unless result.strikes_exceeded?
- def monitor_memory_growth
- monitor_memory_condition(:mem_growth) do |stat|
- worker_uss = Gitlab::Metrics::System.memory_usage_uss_pss[:uss]
- reference_uss = reference_mem[:uss]
- memory_limit = stat[:max] * reference_uss
- [
- worker_uss <= memory_limit,
- {
- message: 'memory limit exceeded',
- memwd_uss_bytes: worker_uss,
- memwd_ref_uss_bytes: reference_uss,
- memwd_max_uss_bytes: memory_limit
- }
- ]
+ @alive = !memory_limit_exceeded_callback(result.monitor_name, result.payload)
end
end
- # On pre-fork systems this would be the primary process memory from which workers fork.
- # Otherwise it is the current process' memory.
- #
- # We initialize this lazily because in the initializer the application may not have
- # finished booting yet, which would yield an incorrect baseline.
- def reference_mem
- @reference_mem ||= Gitlab::Metrics::System.memory_usage_uss_pss(pid: Gitlab::Cluster::PRIMARY_PID)
- end
-
- def memory_limit_exceeded_callback(stat_key, handler_labels)
- all_labels = log_labels.merge(handler_labels)
- .merge(memwd_cur_strikes: strikes(stat_key))
- @logger.warn(all_labels)
- @counter_violations_handled.increment(reason: stat_key.to_s)
+ def memory_limit_exceeded_callback(monitor_name, monitor_payload)
+ all_labels = log_labels.merge(monitor_payload)
+ logger.warn(all_labels)
+ @counter_violations_handled.increment(reason: monitor_name)
handler.call
end
@@ -211,7 +103,15 @@ module Gitlab
# all that happens is we collect logs and Prometheus events for fragmentation violations.
return NullHandler.instance unless Feature.enabled?(:enforce_memory_watchdog, type: :ops)
- @handler
+ @configuration.handler
+ end
+
+ def logger
+ @configuration.logger
+ end
+
+ def sleep_time_seconds
+ @configuration.sleep_time_seconds
end
def log_labels
@@ -219,27 +119,20 @@ module Gitlab
pid: $$,
worker_id: worker_id,
memwd_handler_class: handler.class.name,
- memwd_sleep_time_s: @sleep_time_seconds,
- memwd_max_strikes: @max_strikes,
+ memwd_sleep_time_s: sleep_time_seconds,
memwd_rss_bytes: process_rss_bytes
}
end
- def worker_id
- ::Prometheus::PidProvider.worker_id
- end
-
def process_rss_bytes
Gitlab::Metrics::System.memory_usage_rss
end
- def init_prometheus_metrics(max_heap_fragmentation)
- @heap_frag_limit = Gitlab::Metrics.gauge(
- :gitlab_memwd_heap_frag_limit,
- 'The configured limit for how fragmented the Ruby heap is allowed to be'
- )
- @heap_frag_limit.set({}, max_heap_fragmentation)
+ def worker_id
+ ::Prometheus::PidProvider.worker_id
+ end
+ def init_prometheus_metrics
default_labels = { pid: worker_id }
@counter_violations = Gitlab::Metrics.counter(
:gitlab_memwd_violations_total,
diff --git a/lib/gitlab/memory/watchdog/configuration.rb b/lib/gitlab/memory/watchdog/configuration.rb
new file mode 100644
index 00000000000..2d84b083f55
--- /dev/null
+++ b/lib/gitlab/memory/watchdog/configuration.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class Watchdog
+ class Configuration
+ class MonitorStack
+ def initialize
+ @monitors = []
+ end
+
+ def use(monitor_class, *args, **kwargs, &block)
+ remove(monitor_class)
+ @monitors.push(build_monitor_state(monitor_class, *args, **kwargs, &block))
+ end
+
+ def call_each
+ @monitors.each do |monitor|
+ yield monitor.call
+ end
+ end
+
+ private
+
+ def remove(monitor_class)
+ @monitors.delete_if { |monitor| monitor.monitor_class == monitor_class }
+ end
+
+ def build_monitor_state(monitor_class, *args, max_strikes:, **kwargs, &block)
+ monitor = build_monitor(monitor_class, *args, **kwargs, &block)
+
+ Gitlab::Memory::Watchdog::MonitorState.new(monitor, max_strikes: max_strikes)
+ end
+
+ def build_monitor(monitor_class, *args, **kwargs, &block)
+ monitor_class.new(*args, **kwargs, &block)
+ end
+ end
+
+ DEFAULT_SLEEP_TIME_SECONDS = 60
+
+ attr_reader :monitors
+ attr_writer :logger, :handler, :sleep_time_seconds
+
+ def initialize
+ @monitors = MonitorStack.new
+ end
+
+ def handler
+ @handler ||= NullHandler.instance
+ end
+
+ def logger
+ @logger ||= Gitlab::Logger.new($stdout)
+ end
+
+ # Used to control the frequency with which the watchdog will wake up and poll the GC.
+ def sleep_time_seconds
+ @sleep_time_seconds ||= DEFAULT_SLEEP_TIME_SECONDS
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb b/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb
new file mode 100644
index 00000000000..7748c19c6d8
--- /dev/null
+++ b/lib/gitlab/memory/watchdog/monitor/heap_fragmentation.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class Watchdog
+ module Monitor
+ # A monitor that observes Ruby heap fragmentation and calls
+ # memory_violation_callback when the Ruby heap has been fragmented for an extended
+ # period of time.
+ #
+ # See Gitlab::Metrics::Memory for how heap fragmentation is defined.
+ class HeapFragmentation
+ attr_reader :max_heap_fragmentation
+
+ # max_heap_fragmentation:
+ # The degree to which the Ruby heap is allowed to be fragmented. Range [0,1].
+ def initialize(max_heap_fragmentation:)
+ @max_heap_fragmentation = max_heap_fragmentation
+ init_frag_limit_metrics
+ end
+
+ def call
+ heap_fragmentation = Gitlab::Metrics::Memory.gc_heap_fragmentation
+
+ return { threshold_violated: false, payload: {} } unless heap_fragmentation > max_heap_fragmentation
+
+ { threshold_violated: true, payload: payload(heap_fragmentation) }
+ end
+
+ private
+
+ def payload(heap_fragmentation)
+ {
+ message: 'heap fragmentation limit exceeded',
+ memwd_cur_heap_frag: heap_fragmentation,
+ memwd_max_heap_frag: max_heap_fragmentation
+ }
+ end
+
+ def init_frag_limit_metrics
+ heap_frag_limit = Gitlab::Metrics.gauge(
+ :gitlab_memwd_heap_frag_limit,
+ 'The configured limit for how fragmented the Ruby heap is allowed to be'
+ )
+ heap_frag_limit.set({}, max_heap_fragmentation)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog/monitor/unique_memory_growth.rb b/lib/gitlab/memory/watchdog/monitor/unique_memory_growth.rb
new file mode 100644
index 00000000000..2a1512c4cff
--- /dev/null
+++ b/lib/gitlab/memory/watchdog/monitor/unique_memory_growth.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class Watchdog
+ module Monitor
+ class UniqueMemoryGrowth
+ attr_reader :max_mem_growth
+
+ def initialize(max_mem_growth:)
+ @max_mem_growth = max_mem_growth
+ end
+
+ def call
+ worker_uss = Gitlab::Metrics::System.memory_usage_uss_pss[:uss]
+ reference_uss = reference_mem[:uss]
+ memory_limit = max_mem_growth * reference_uss
+
+ return { threshold_violated: false, payload: {} } unless worker_uss > memory_limit
+
+ { threshold_violated: true, payload: payload(worker_uss, reference_uss, memory_limit) }
+ end
+
+ private
+
+ def payload(worker_uss, reference_uss, memory_limit)
+ {
+ message: 'memory limit exceeded',
+ memwd_uss_bytes: worker_uss,
+ memwd_ref_uss_bytes: reference_uss,
+ memwd_max_uss_bytes: memory_limit
+ }
+ end
+
+ # On pre-fork systems this would be the primary process memory from which workers fork.
+ # Otherwise it is the current process' memory.
+ #
+ # We initialize this lazily because in the initializer the application may not have
+ # finished booting yet, which would yield an incorrect baseline.
+ def reference_mem
+ @reference_mem ||= Gitlab::Metrics::System.memory_usage_uss_pss(pid: Gitlab::Cluster::PRIMARY_PID)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog/monitor_state.rb b/lib/gitlab/memory/watchdog/monitor_state.rb
new file mode 100644
index 00000000000..73be5de3e45
--- /dev/null
+++ b/lib/gitlab/memory/watchdog/monitor_state.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class Watchdog
+ class MonitorState
+ class Result
+ attr_reader :payload
+
+ def initialize(strikes_exceeded:, threshold_violated:, monitor_class:, payload: )
+ @strikes_exceeded = strikes_exceeded
+ @threshold_violated = threshold_violated
+ @monitor_class = monitor_class
+ @payload = payload
+ end
+
+ def strikes_exceeded?
+ @strikes_exceeded
+ end
+
+ def threshold_violated?
+ @threshold_violated
+ end
+
+ def monitor_name
+ @monitor_class.name.demodulize.underscore.to_sym
+ end
+ end
+
+ def initialize(monitor, max_strikes:)
+ @monitor = monitor
+ @max_strikes = max_strikes
+ @strikes = 0
+ end
+
+ def call
+ reset_strikes if strikes_exceeded?
+
+ monitor_result = @monitor.call
+
+ if monitor_result[:threshold_violated]
+ issue_strike
+ else
+ reset_strikes
+ end
+
+ build_result(monitor_result)
+ end
+
+ def monitor_class
+ @monitor.class
+ end
+
+ private
+
+ def build_result(monitor_result)
+ Result.new(
+ strikes_exceeded: strikes_exceeded?,
+ monitor_class: monitor_class,
+ threshold_violated: monitor_result[:threshold_violated],
+ payload: payload.merge(monitor_result[:payload]))
+ end
+
+ def payload
+ {
+ memwd_max_strikes: @max_strikes,
+ memwd_cur_strikes: @strikes
+ }
+ end
+
+ def strikes_exceeded?
+ @strikes > @max_strikes
+ end
+
+ def issue_strike
+ @strikes += 1
+ end
+
+ def reset_strikes
+ @strikes = 0
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/global_search_slis.rb b/lib/gitlab/metrics/global_search_slis.rb
index e37129fed38..3400a6c78ef 100644
--- a/lib/gitlab/metrics/global_search_slis.rb
+++ b/lib/gitlab/metrics/global_search_slis.rb
@@ -13,9 +13,7 @@ module Gitlab
ADVANCED_CODE_TARGET_S = 13.546
def initialize_slis!
- if Feature.enabled?(:global_search_custom_slis)
- Gitlab::Metrics::Sli::Apdex.initialize_sli(:global_search, possible_labels)
- end
+ Gitlab::Metrics::Sli::Apdex.initialize_sli(:global_search, possible_labels)
return unless Feature.enabled?(:global_search_error_rate_sli)
@@ -23,8 +21,6 @@ module Gitlab
end
def record_apdex(elapsed:, search_type:, search_level:, search_scope:)
- return unless Feature.enabled?(:global_search_custom_slis)
-
Gitlab::Metrics::Sli::Apdex[:global_search].increment(
labels: labels(search_type: search_type, search_level: search_level, search_scope: search_scope),
success: elapsed < duration_target(search_type, search_scope)
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index d7eef722d6e..affadc4274c 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -14,11 +14,13 @@ module Gitlab
PROC_SMAPS_ROLLUP_PATH = '/proc/%s/smaps_rollup'
PROC_LIMITS_PATH = '/proc/self/limits'
PROC_FD_GLOB = '/proc/self/fd/*'
+ PROC_MEM_INFO = '/proc/meminfo'
PRIVATE_PAGES_PATTERN = /^(Private_Clean|Private_Dirty|Private_Hugetlb):\s+(?<value>\d+)/.freeze
PSS_PATTERN = /^Pss:\s+(?<value>\d+)/.freeze
RSS_PATTERN = /VmRSS:\s+(?<value>\d+)/.freeze
MAX_OPEN_FILES_PATTERN = /Max open files\s*(?<value>\d+)/.freeze
+ MEM_TOTAL_PATTERN = /^MemTotal:\s+(?<value>\d+) (.+)/.freeze
def summary
proportional_mem = memory_usage_uss_pss
@@ -45,6 +47,10 @@ module Gitlab
.transform_values(&:kilobytes)
end
+ def memory_total
+ sum_matches(PROC_MEM_INFO, memory_total: MEM_TOTAL_PATTERN)[:memory_total].kilobytes
+ end
+
def file_descriptor_count
Dir.glob(PROC_FD_GLOB).length
end
diff --git a/lib/gitlab/object_hierarchy.rb b/lib/gitlab/object_hierarchy.rb
index 0576aed811c..12d4d9d8928 100644
--- a/lib/gitlab/object_hierarchy.rb
+++ b/lib/gitlab/object_hierarchy.rb
@@ -138,9 +138,9 @@ module Gitlab
.with
.recursive(ancestors.to_arel, descendants.to_arel)
.from_union([
- ancestors_scope,
- descendants_scope
- ])
+ ancestors_scope,
+ descendants_scope
+ ])
read_only(relation)
end
diff --git a/lib/gitlab/pages/cache_control.rb b/lib/gitlab/pages/cache_control.rb
index 991a1297d03..187d5f907e4 100644
--- a/lib/gitlab/pages/cache_control.rb
+++ b/lib/gitlab/pages/cache_control.rb
@@ -3,9 +3,13 @@
module Gitlab
module Pages
class CacheControl
- CACHE_KEY_FORMAT = 'pages_domain_for_%{type}_%{id}'
+ include Gitlab::Utils::StrongMemoize
- attr_reader :cache_key
+ EXPIRE = 12.hours
+ # To avoid delivering expired deployment URL in the cached payload,
+ # use a longer expiration time in the deployment URL
+ DEPLOYMENT_EXPIRATION = (EXPIRE + 12.hours)
+ CACHE_KEY_FORMAT = 'pages_domain_for_%{type}_%{id}_%{settings}'
class << self
def for_project(project_id)
@@ -20,12 +24,35 @@ module Gitlab
def initialize(type:, id:)
raise(ArgumentError, "type must be :namespace or :project") unless %i[namespace project].include?(type)
- @cache_key = CACHE_KEY_FORMAT % { type: type, id: id }
+ @type = type
+ @id = id
+ end
+
+ def cache_key
+ strong_memoize(:cache_key) do
+ CACHE_KEY_FORMAT % {
+ type: @type,
+ id: @id,
+ settings: settings
+ }
+ end
end
def clear_cache
Rails.cache.delete(cache_key)
end
+
+ private
+
+ def settings
+ values = ::Gitlab.config.pages.dup
+
+ values['app_settings'] = ::Gitlab::CurrentSettings.attributes.slice(
+ 'force_pages_access_control'
+ )
+
+ ::Digest::SHA256.hexdigest(values.inspect)
+ end
end
end
end
diff --git a/lib/gitlab/pagination/keyset/simple_order_builder.rb b/lib/gitlab/pagination/keyset/simple_order_builder.rb
index c36bd497aa3..318720c77d1 100644
--- a/lib/gitlab/pagination/keyset/simple_order_builder.rb
+++ b/lib/gitlab/pagination/keyset/simple_order_builder.rb
@@ -129,28 +129,31 @@ module Gitlab
end
def primary_key_descending_order
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: model_class.primary_key,
- order_expression: arel_table[primary_key].desc
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: model_class.primary_key,
+ order_expression: arel_table[primary_key].desc
+ )
+ ])
end
def primary_key_order
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: model_class.primary_key,
- order_expression: order_values.first
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: model_class.primary_key,
+ order_expression: order_values.first
+ )
+ ])
end
def column_with_tie_breaker_order(tie_breaker_column_order = default_tie_breaker_column_order)
- Gitlab::Pagination::Keyset::Order.build([
- column(order_values.first),
- tie_breaker_column_order
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ column(order_values.first),
+ tie_breaker_column_order
+ ])
end
def column(order_value)
diff --git a/lib/gitlab/patch/sidekiq_cron_poller.rb b/lib/gitlab/patch/sidekiq_cron_poller.rb
deleted file mode 100644
index 630c364d455..00000000000
--- a/lib/gitlab/patch/sidekiq_cron_poller.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-# Patch to address https://github.com/ondrejbartas/sidekiq-cron/issues/361
-# This restores the poll interval to v1.2.0 behavior
-# https://github.com/ondrejbartas/sidekiq-cron/blob/v1.2.0/lib/sidekiq/cron/poller.rb#L36-L38
-# This patch only applies to v1.4.0
-require 'sidekiq/cron/version'
-
-if Gem::Version.new(Sidekiq::Cron::VERSION) != Gem::Version.new('1.4.0')
- raise 'New version of sidekiq-cron detected, please remove or update this patch'
-end
-
-module Gitlab
- module Patch
- module SidekiqCronPoller
- def poll_interval_average
- Sidekiq.options[:poll_interval] || Sidekiq::Cron::POLL_INTERVAL
- end
- end
- end
-end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index fd9f73d18c1..f8a85f693bc 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -43,12 +43,9 @@ module Gitlab
# - private_token: instead of providing a user instance, the token can be
# given as a string. Takes precedence over the user option.
#
- # - sampling_mode: When true, uses a sampling profiler (StackProf) instead of a tracing profiler (RubyProf).
- #
- # - profiler_options: A keyword Hash of arguments passed to the profiler. Defaults by profiler type:
- # RubyProf - {}
- # StackProf - { mode: :wall, out: <some temporary file>, interval: 1000, raw: true }
- def self.profile(url, logger: nil, post_data: nil, user: nil, private_token: nil, sampling_mode: false, profiler_options: {})
+ # - profiler_options: A keyword Hash of arguments passed to the profiler. Defaults:
+ # { mode: :wall, out: <some temporary file>, interval: 1000, raw: true }
+ def self.profile(url, logger: nil, post_data: nil, user: nil, private_token: nil, profiler_options: {})
app = ActionDispatch::Integration::Session.new(Rails.application)
verb = :get
headers = {}
@@ -80,7 +77,7 @@ module Gitlab
with_custom_logger(logger) do
with_user(user) do
- with_profiler(sampling_mode, profiler_options) do
+ with_profiler(profiler_options) do
app.public_send(verb, url, params: post_data, headers: headers) # rubocop:disable GitlabSecurity/PublicSend
end
end
@@ -174,21 +171,11 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- def self.print_by_total_time(result, options = {})
- default_options = { sort_method: :total_time, filter_by: :total_time }
-
- RubyProf::FlatPrinter.new(result).print($stdout, default_options.merge(options))
- end
-
- def self.with_profiler(sampling_mode, profiler_options)
- if sampling_mode
- require 'stackprof'
- args = { mode: :wall, interval: 1000, raw: true }.merge!(profiler_options)
- args[:out] ||= ::Tempfile.new(["profile-#{Time.now.to_i}-", ".dump"]).path
- ::StackProf.run(**args) { yield }
- else
- RubyProf.profile(**profiler_options) { yield }
- end
+ def self.with_profiler(profiler_options)
+ require 'stackprof'
+ args = { mode: :wall, interval: 1000, raw: true }.merge!(profiler_options)
+ args[:out] ||= ::Tempfile.new(["profile-#{Time.now.to_i}-", ".dump"]).path
+ ::StackProf.run(**args) { yield }
end
end
end
diff --git a/lib/gitlab/project_authorizations.rb b/lib/gitlab/project_authorizations.rb
index 1d7b179baf0..da3f67dde51 100644
--- a/lib/gitlab/project_authorizations.rb
+++ b/lib/gitlab/project_authorizations.rb
@@ -37,9 +37,9 @@ module Gitlab
Namespace
.unscoped
.select([
- links[:project_id],
- least(cte_alias[:access_level], links[:group_access], 'access_level')
- ])
+ links[:project_id],
+ least(cte_alias[:access_level], links[:group_access], 'access_level')
+ ])
.from(cte_alias)
.joins('INNER JOIN project_group_links ON project_group_links.group_id = namespaces.id')
.joins('INNER JOIN projects ON projects.id = project_group_links.project_id')
@@ -79,9 +79,9 @@ module Gitlab
# Sub groups of any groups the user is a member of.
cte << Group.select([
- namespaces[:id],
- greatest(members[:access_level], cte.table[:access_level], 'access_level')
- ])
+ namespaces[:id],
+ greatest(members[:access_level], cte.table[:access_level], 'access_level')
+ ])
.joins(join_cte(cte))
.joins(join_members_on_namespaces)
.except(:order)
diff --git a/lib/gitlab/query_limiting/transaction.rb b/lib/gitlab/query_limiting/transaction.rb
index 2e31849caaa..46c0a0ddf7a 100644
--- a/lib/gitlab/query_limiting/transaction.rb
+++ b/lib/gitlab/query_limiting/transaction.rb
@@ -14,8 +14,13 @@ module Gitlab
# The maximum number of SQL queries that can be executed in a request. For
# the sake of keeping things simple we hardcode this value here, it's not
# supposed to be changed very often anyway.
- THRESHOLD = 100
- LOG_THRESHOLD = THRESHOLD * 1.5
+ def self.threshold
+ 100
+ end
+
+ def self.log_threshold
+ threshold * 1.5
+ end
# Error that is raised whenever exceeding the maximum number of queries.
ThresholdExceededError = Class.new(StandardError)
@@ -76,7 +81,7 @@ module Gitlab
end
def executed_sql(sql)
- return if @count > LOG_THRESHOLD || ignorable?(sql)
+ return if @count > self.class.log_threshold || ignorable?(sql)
@sql_executed << sql
end
@@ -86,15 +91,15 @@ module Gitlab
end
def threshold_exceeded?
- count > THRESHOLD
+ count > self.class.threshold
end
def error_message
header = 'Too many SQL queries were executed'
header = "#{header} in #{action}" if action
- msg = "a maximum of #{THRESHOLD} is allowed but #{count} SQL queries were executed"
+ msg = "a maximum of #{self.class.threshold} is allowed but #{count} SQL queries were executed"
log = @sql_executed.each_with_index.map { |sql, i| "#{i}: #{sql}" }.join("\n").presence
- ellipsis = '...' if @count > LOG_THRESHOLD
+ ellipsis = '...' if @count > self.class.log_threshold
["#{header}: #{msg}", log, ellipsis].compact.join("\n")
end
@@ -105,3 +110,5 @@ module Gitlab
end
end
end
+
+Gitlab::QueryLimiting::Transaction.prepend_mod
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index d38b81bff0b..f0ad6653c5e 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -176,7 +176,7 @@ module Gitlab
explanation { _('Approve the current merge request.') }
types MergeRequest
condition do
- quick_action_target.persisted? && quick_action_target.can_be_approved_by?(current_user)
+ quick_action_target.persisted? && quick_action_target.eligible_for_approval_by?(current_user)
end
command :approve do
success = ::MergeRequests::ApprovalService.new(project: quick_action_target.project, current_user: current_user).execute(quick_action_target)
@@ -190,7 +190,7 @@ module Gitlab
explanation { _('Unapprove the current merge request.') }
types MergeRequest
condition do
- quick_action_target.persisted? && quick_action_target.can_be_unapproved_by?(current_user)
+ quick_action_target.persisted? && quick_action_target.eligible_for_unapproval_by?(current_user)
end
command :unapprove do
success = ::MergeRequests::RemoveApprovalService.new(project: quick_action_target.project, current_user: current_user).execute(quick_action_target)
diff --git a/lib/gitlab/redis/duplicate_jobs.rb b/lib/gitlab/redis/duplicate_jobs.rb
index beb3ba1abee..c76d298da18 100644
--- a/lib/gitlab/redis/duplicate_jobs.rb
+++ b/lib/gitlab/redis/duplicate_jobs.rb
@@ -18,9 +18,11 @@ module Gitlab
# `Sidekiq.redis` is a namespaced redis connection. This means keys are actually being stored under
# "resque:gitlab:resque:gitlab:duplicate:". For backwards compatibility, we make the secondary store
# namespaced in the same way, but omit it from the primary so keys have proper format there.
+ # rubocop:disable Cop/RedisQueueUsage
secondary_store = ::Redis::Namespace.new(
Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE, redis: ::Redis.new(Gitlab::Redis::Queues.params)
)
+ # rubocop:enable Cop/RedisQueueUsage
MultiStore.new(primary_store, secondary_store, name.demodulize)
end
diff --git a/lib/gitlab/redis/sidekiq_status.rb b/lib/gitlab/redis/sidekiq_status.rb
index d4362c7cad8..9b8bbf5a0ad 100644
--- a/lib/gitlab/redis/sidekiq_status.rb
+++ b/lib/gitlab/redis/sidekiq_status.rb
@@ -14,7 +14,7 @@ module Gitlab
def redis
primary_store = ::Redis.new(Gitlab::Redis::SharedState.params)
- secondary_store = ::Redis.new(Gitlab::Redis::Queues.params)
+ secondary_store = ::Redis.new(Gitlab::Redis::Queues.params) # rubocop:disable Cop/RedisQueueUsage
MultiStore.new(primary_store, secondary_store, name.demodulize)
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 10c03103899..4f76cce2c7d 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -414,8 +414,10 @@ module Gitlab
# Based on Jira's project key format
# https://confluence.atlassian.com/adminjiraserver073/changing-the-project-key-format-861253229.html
+ # Avoids linking CVE IDs (https://cve.mitre.org/cve/identifiers/syntaxchange.html#new) as Jira issues.
+ # CVE IDs use the format of CVE-YYYY-NNNNNNN
def jira_issue_key_regex
- @jira_issue_key_regex ||= /[A-Z][A-Z_0-9]+-\d+/
+ @jira_issue_key_regex ||= /(?!CVE-\d+-\d+)[A-Z][A-Z_0-9]+-\d+/
end
def jira_issue_key_project_key_extraction_regex
diff --git a/lib/gitlab/repository_set_cache.rb b/lib/gitlab/repository_set_cache.rb
index 33c7d96c45b..baf48fd0dc1 100644
--- a/lib/gitlab/repository_set_cache.rb
+++ b/lib/gitlab/repository_set_cache.rb
@@ -41,7 +41,7 @@ module Gitlab
smembers, exists = with do |redis|
redis.multi do |multi|
multi.smembers(full_key)
- multi.exists(full_key)
+ multi.exists?(full_key) # rubocop:disable CodeReuse/ActiveRecord
end
end
@@ -58,7 +58,7 @@ module Gitlab
full_key = cache_key(key)
with do |redis|
- exists = redis.exists(full_key)
+ exists = redis.exists?(full_key) # rubocop:disable CodeReuse/ActiveRecord
write(key, yield) unless exists
redis.sscan_each(full_key, match: pattern)
diff --git a/lib/gitlab/request_endpoints.rb b/lib/gitlab/request_endpoints.rb
index 157c0f91e65..4efafaa0ac2 100644
--- a/lib/gitlab/request_endpoints.rb
+++ b/lib/gitlab/request_endpoints.rb
@@ -8,6 +8,7 @@ module Gitlab
# but if they weren't, the routes will be drawn and available for the rest of
# application.
API::API.compile!
+ API::API.reset_routes!
API::API.routes.select { |route| route.app.options[:for] < API::Base }
end
diff --git a/lib/gitlab/runtime.rb b/lib/gitlab/runtime.rb
index 5b1341207fd..6d95cb9a87b 100644
--- a/lib/gitlab/runtime.rb
+++ b/lib/gitlab/runtime.rb
@@ -25,9 +25,9 @@ module Gitlab
if matches.one?
matches.first
elsif matches.none?
- raise UnknownProcessError, "Failed to identify runtime for process #{Process.pid} (#{$0})"
+ raise UnknownProcessError, "Failed to identify runtime for process #{Process.pid} (#{$PROGRAM_NAME})"
else
- raise AmbiguousProcessError, "Ambiguous runtime #{matches} for process #{Process.pid} (#{$0})"
+ raise AmbiguousProcessError, "Ambiguous runtime #{matches} for process #{Process.pid} (#{$PROGRAM_NAME})"
end
end
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb
index 4c5fae87420..360bbc073c5 100644
--- a/lib/gitlab/search/query.rb
+++ b/lib/gitlab/search/query.rb
@@ -40,19 +40,24 @@ module Gitlab
query_tokens = parse_raw_query
filters = @filters.each_with_object([]) do |filter, parsed_filters|
- match = query_tokens.find { |part| part =~ /\A-?#{filter[:name]}:/ }
+ matches = query_tokens.select { |part| part =~ /\A-?#{filter[:name]}:/ }
- next unless match
+ next unless matches.any?
- input = match.split(':')[1..].join
- next if input.empty?
+ matches.each do |match|
+ query_filter = filter.dup
- filter[:negated] = match.start_with?("-")
- filter[:value] = parse_filter(filter, input.gsub(QUOTES_REGEXP, ''))
- filter[:regex_value] = Regexp.escape(filter[:value]).gsub('\*', '.*?')
- fragments << match
+ input = match.split(':')[1..].join
- parsed_filters << filter
+ next if input.empty?
+
+ query_filter[:negated] = match.start_with?("-")
+ query_filter[:value] = parse_filter(query_filter, input.gsub(QUOTES_REGEXP, ''))
+ query_filter[:regex_value] = Regexp.escape(query_filter[:value]).gsub('\*', '.*?')
+
+ fragments << match
+ parsed_filters << query_filter
+ end
end
query = (query_tokens - fragments).join(' ')
diff --git a/lib/gitlab/set_cache.rb b/lib/gitlab/set_cache.rb
index 23c23393bc8..c7818cb3418 100644
--- a/lib/gitlab/set_cache.rb
+++ b/lib/gitlab/set_cache.rb
@@ -28,7 +28,7 @@ module Gitlab
end
def exist?(key)
- with { |redis| redis.exists(cache_key(key)) }
+ with { |redis| redis.exists?(cache_key(key)) } # rubocop:disable CodeReuse/ActiveRecord
end
def write(key, value)
@@ -59,7 +59,7 @@ module Gitlab
with do |redis|
redis.multi do |multi|
multi.sismember(full_key, value)
- multi.exists(full_key)
+ multi.exists?(full_key) # rubocop:disable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index ac9a7d25fc2..3e7bdfbe89a 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -53,8 +53,33 @@ module Gitlab
end
end
+ def cron_jobs
+ @cron_jobs ||= begin
+ Gitlab.config.load_dynamic_cron_schedules!
+
+ # Load recurring jobs from gitlab.yml
+ # UGLY Hack to get nested hash from settingslogic
+ jobs = Gitlab::Json.parse(Gitlab.config.cron_jobs.to_json)
+
+ jobs.delete('poll_interval') # Would be interpreted as a job otherwise
+
+ # UGLY hack: Settingslogic doesn't allow 'class' key
+ required_keys = %w[job_class cron]
+ jobs.each do |k, v|
+ if jobs[k] && required_keys.all? { |s| jobs[k].key?(s) }
+ jobs[k]['class'] = jobs[k].delete('job_class')
+ else
+ jobs.delete(k)
+ Gitlab::AppLogger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
+ end
+ end
+
+ jobs
+ end
+ end
+
def cron_workers
- @cron_workers ||= Settings.cron_jobs.map { |job_name, options| options['job_class'].constantize }
+ @cron_workers ||= cron_jobs.map { |job_name, options| options['class'].constantize }
end
def workers
diff --git a/lib/gitlab/sidekiq_daemon/memory_killer.rb b/lib/gitlab/sidekiq_daemon/memory_killer.rb
index 24e2eca420e..b8f86b92844 100644
--- a/lib/gitlab/sidekiq_daemon/memory_killer.rb
+++ b/lib/gitlab/sidekiq_daemon/memory_killer.rb
@@ -51,9 +51,10 @@ module Gitlab
def refresh_state(phase)
@phase = PHASE.fetch(phase)
- @current_rss = get_rss
- @soft_limit_rss = get_soft_limit_rss
- @hard_limit_rss = get_hard_limit_rss
+ @current_rss = get_rss_kb
+ @soft_limit_rss = get_soft_limit_rss_kb
+ @hard_limit_rss = get_hard_limit_rss_kb
+ @memory_total = get_memory_total_kb
# track the current state as prometheus gauges
@metrics[:sidekiq_memory_killer_phase].set({}, @phase)
@@ -107,6 +108,8 @@ module Gitlab
end
def restart_sidekiq
+ return if Feature.enabled?(:sidekiq_memory_killer_read_only_mode, type: :ops)
+
# Tell Sidekiq to stop fetching new jobs
# We first SIGNAL and then wait given time
# We also monitor a number of running jobs and allow to restart early
@@ -176,6 +179,7 @@ module Gitlab
current_rss: @current_rss,
soft_limit_rss: @soft_limit_rss,
hard_limit_rss: @hard_limit_rss,
+ memory_total_kb: @memory_total,
reason: reason,
running_jobs: running_jobs)
@@ -212,18 +216,19 @@ module Gitlab
end
end
- def get_rss
- output, status = Gitlab::Popen.popen(%W(ps -o rss= -p #{pid}), Rails.root.to_s)
- return 0 unless status&.zero?
+ def get_memory_total_kb
+ Gitlab::Metrics::System.memory_total / 1.kilobytes
+ end
- output.to_i
+ def get_rss_kb
+ Gitlab::Metrics::System.memory_usage_rss / 1.kilobytes
end
- def get_soft_limit_rss
+ def get_soft_limit_rss_kb
SOFT_LIMIT_RSS_KB + rss_increase_by_jobs
end
- def get_hard_limit_rss
+ def get_hard_limit_rss_kb
HARD_LIMIT_RSS_KB
end
diff --git a/lib/gitlab/sidekiq_daemon/monitor.rb b/lib/gitlab/sidekiq_daemon/monitor.rb
index 1f1d63877b5..655e95c82d3 100644
--- a/lib/gitlab/sidekiq_daemon/monitor.rb
+++ b/lib/gitlab/sidekiq_daemon/monitor.rb
@@ -182,7 +182,7 @@ module Gitlab
def cancelled?(jid)
::Gitlab::Redis::SharedState.with do |redis|
- redis.exists(self.class.cancel_job_key(jid))
+ redis.exists?(self.class.cancel_job_key(jid)) # rubocop:disable CodeReuse/ActiveRecord
end
end
diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb
index fd3a5f715e8..b20f639ce85 100644
--- a/lib/gitlab/sidekiq_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware.rb
@@ -7,7 +7,7 @@ module Gitlab
# The result of this method should be passed to
# Sidekiq's `config.server_middleware` method
# eg: `config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator)`
- def self.server_configurator(metrics: true, arguments_logger: true, memory_killer: true)
+ def self.server_configurator(metrics: true, arguments_logger: true)
lambda do |chain|
# Size limiter should be placed at the top
chain.add ::Gitlab::SidekiqMiddleware::SizeLimiter::Server
@@ -27,7 +27,6 @@ module Gitlab
end
chain.add ::Gitlab::SidekiqMiddleware::ArgumentsLogger if arguments_logger
- chain.add ::Gitlab::SidekiqMiddleware::MemoryKiller if memory_killer
chain.add ::Gitlab::SidekiqMiddleware::RequestStoreMiddleware
chain.add ::Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata
chain.add ::Gitlab::SidekiqMiddleware::BatchLoader
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
index ab126ea4749..d42bd672bac 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
@@ -282,7 +282,7 @@ module Gitlab
Gitlab::Redis::DuplicateJobs.with { |redis| yield redis }
else
# Keep the old behavior intact if neither feature flag is turned on
- Sidekiq.redis { |redis| yield redis }
+ Sidekiq.redis { |redis| yield redis } # rubocop:disable Cop/SidekiqRedisCall
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/memory_killer.rb b/lib/gitlab/sidekiq_middleware/memory_killer.rb
deleted file mode 100644
index 0b38c98f710..00000000000
--- a/lib/gitlab/sidekiq_middleware/memory_killer.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module SidekiqMiddleware
- class MemoryKiller
- # Default the RSS limit to 0, meaning the MemoryKiller is disabled
- MAX_RSS = (ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] || 0).to_s.to_i
- # Give Sidekiq 15 minutes of grace time after exceeding the RSS limit
- GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i
- # Wait 30 seconds for running jobs to finish during graceful shutdown
- SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i
-
- # Create a mutex used to ensure there will be only one thread waiting to
- # shut Sidekiq down
- MUTEX = Mutex.new
-
- attr_reader :worker
-
- def call(worker, job, queue)
- yield
-
- @worker = worker
- current_rss = get_rss
-
- return unless MAX_RSS > 0 && current_rss > MAX_RSS
-
- Thread.new do
- # Return if another thread is already waiting to shut Sidekiq down
- next unless MUTEX.try_lock
-
- warn("Sidekiq worker PID-#{pid} current RSS #{current_rss}"\
- " exceeds maximum RSS #{MAX_RSS} after finishing job #{worker.class} JID-#{job['jid']}")
-
- warn("Sidekiq worker PID-#{pid} will stop fetching new jobs"\
- " in #{GRACE_TIME} seconds, and will be shut down #{SHUTDOWN_WAIT} seconds later")
-
- # Wait `GRACE_TIME` to give the memory intensive job time to finish.
- # Then, tell Sidekiq to stop fetching new jobs.
- wait_and_signal(GRACE_TIME, 'SIGTSTP', 'stop fetching new jobs')
-
- # Wait `SHUTDOWN_WAIT` to give already fetched jobs time to finish.
- # Then, tell Sidekiq to gracefully shut down by giving jobs a few more
- # moments to finish, killing and requeuing them if they didn't, and
- # then terminating itself. Sidekiq will replicate the TERM to all its
- # children if it can.
- wait_and_signal(SHUTDOWN_WAIT, 'SIGTERM', 'gracefully shut down')
-
- # Wait for Sidekiq to shutdown gracefully, and kill it if it didn't.
- # Kill the whole pgroup, so we can be sure no children are left behind
- wait_and_signal_pgroup(Sidekiq.options[:timeout] + 2, 'SIGKILL', 'die')
- end
- end
-
- private
-
- def get_rss
- output, status = Gitlab::Popen.popen(%W(ps -o rss= -p #{pid}), Rails.root.to_s)
- return 0 unless status == 0
-
- output.to_i
- end
-
- # If this sidekiq process is pgroup leader, signal to the whole pgroup
- def wait_and_signal_pgroup(time, signal, explanation)
- return wait_and_signal(time, signal, explanation) unless Process.getpgrp == pid
-
- warn("waiting #{time} seconds before sending Sidekiq worker PGRP-#{pid} #{signal} (#{explanation})", signal: signal)
- sleep(time)
-
- warn("sending Sidekiq worker PGRP-#{pid} #{signal} (#{explanation})", signal: signal)
- Process.kill(signal, 0)
- end
-
- def wait_and_signal(time, signal, explanation)
- warn("waiting #{time} seconds before sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})", signal: signal)
- sleep(time)
-
- warn("sending Sidekiq worker PID-#{pid} #{signal} (#{explanation})", signal: signal)
- Process.kill(signal, pid)
- end
-
- def pid
- Process.pid
- end
-
- def warn(message, signal: nil)
- Sidekiq.logger.warn(class: worker.class.name, pid: pid, signal: signal, message: message)
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index 9d08d236720..17234bdf519 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -126,7 +126,7 @@ module Gitlab
Gitlab::Redis::SidekiqStatus.with { |redis| yield redis }
else
# Keep the old behavior intact if neither feature flag is turned on
- Sidekiq.redis { |redis| yield redis }
+ Sidekiq.redis { |redis| yield redis } # rubocop:disable Cop/SidekiqRedisCall
end
end
private_class_method :with_redis
diff --git a/lib/gitlab/slash_commands/issue_new.rb b/lib/gitlab/slash_commands/issue_new.rb
index ef368767689..1527fd263e0 100644
--- a/lib/gitlab/slash_commands/issue_new.rb
+++ b/lib/gitlab/slash_commands/issue_new.rb
@@ -21,12 +21,16 @@ module Gitlab
title = match[:title]
description = match[:description].to_s.rstrip
- issue = create_issue(title: title, description: description)
+ result = create_issue(title: title, description: description)
- if issue.persisted?
- presenter(issue).present
+ if result.success?
+ presenter(result[:issue]).present
+ elsif result[:issue]
+ presenter(result[:issue]).display_errors
else
- presenter(issue).display_errors
+ Gitlab::SlashCommands::Presenters::Error.new(
+ result.errors.join(', ')
+ ).message
end
end
diff --git a/lib/gitlab/tracking/service_ping_context.rb b/lib/gitlab/tracking/service_ping_context.rb
new file mode 100644
index 00000000000..393cd647e7f
--- /dev/null
+++ b/lib/gitlab/tracking/service_ping_context.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracking
+ class ServicePingContext
+ SCHEMA_URL = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0'
+ ALLOWED_SOURCES = %i[redis_hll].freeze
+
+ def initialize(data_source:, event:)
+ unless ALLOWED_SOURCES.include?(data_source)
+ raise ArgumentError, "#{data_source} is not acceptable data source for ServicePingContext"
+ end
+
+ @payload = {
+ data_source: data_source,
+ event_name: event
+ }
+ end
+
+ def to_context
+ SnowplowTracker::SelfDescribingJson.new(SCHEMA_URL, @payload)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb
index cf48aa49938..30f2efc8638 100644
--- a/lib/gitlab/usage/metric.rb
+++ b/lib/gitlab/usage/metric.rb
@@ -46,10 +46,7 @@ module Gitlab
end
def instrumentation_object
- @instrumentation_object ||= instrumentation_class.constantize.new(
- time_frame: definition.time_frame,
- options: definition.attributes[:options]
- )
+ @instrumentation_object ||= instrumentation_class.constantize.new(definition.attributes)
end
end
end
diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb
index 2c50678c6bf..d6b1e62c84f 100644
--- a/lib/gitlab/usage/metric_definition.rb
+++ b/lib/gitlab/usage/metric_definition.rb
@@ -5,7 +5,7 @@ module Gitlab
class MetricDefinition
METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json')
SKIP_VALIDATION_STATUSES = %w[deprecated removed].to_set.freeze
- AVAILABLE_STATUSES = %w[active data_available implemented deprecated].to_set.freeze
+ AVAILABLE_STATUSES = %w[active data_available implemented deprecated broken].to_set.freeze
VALID_SERVICE_PING_STATUSES = %w[active data_available implemented deprecated broken].to_set.freeze
InvalidError = Class.new(RuntimeError)
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
index 11e2fd22638..cd72f16d46d 100644
--- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -13,62 +13,72 @@ module Gitlab
end
def all_time_data
- aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
- aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME)
end
def weekly_data
- aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME)
+ end
+
+ def calculate_count_for_aggregation(aggregation:, time_frame:)
+ with_validate_configuration(aggregation, time_frame) do
+ source = SOURCES[aggregation[:source]]
+
+ if aggregation[:operator] == UNION_OF_AGGREGATED_METRICS
+ source.calculate_metrics_union(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
+ else
+ source.calculate_metrics_intersections(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
+ end
+ end
+ rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
+ failure(error)
end
private
attr_accessor :aggregated_metrics, :recorded_at
- def aggregated_metrics_data(start_date:, end_date:, time_frame:)
+ def aggregated_metrics_data(time_frame)
aggregated_metrics.each_with_object({}) do |aggregation, data|
next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], type: :development)
next unless aggregation[:time_frame].include?(time_frame)
- case aggregation[:source]
- when REDIS_SOURCE
- if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
- data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(
- DisallowedAggregationTimeFrame.new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
- )
- else
- data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
- end
- when DATABASE_SOURCE
- data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
- else
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(UnknownAggregationSource.new("Aggregation source: '#{aggregation[:source]}' must be included in #{SOURCES.keys}"))
-
- data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
- end
+ data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, time_frame: time_frame)
end
end
- def calculate_count_for_aggregation(aggregation:, start_date:, end_date:)
- source = SOURCES[aggregation[:source]]
-
- case aggregation[:operator]
- when UNION_OF_AGGREGATED_METRICS
- source.calculate_metrics_union(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
- when INTERSECTION_OF_AGGREGATED_METRICS
- source.calculate_metrics_intersections(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
- else
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"))
- Gitlab::Utils::UsageData::FALLBACK
+ def with_validate_configuration(aggregation, time_frame)
+ source = aggregation[:source]
+
+ unless ALLOWED_METRICS_AGGREGATIONS.include?(aggregation[:operator])
+ return failure(
+ UnknownAggregationOperator
+ .new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}")
+ )
end
- rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
+
+ unless SOURCES[source]
+ return failure(
+ UnknownAggregationSource
+ .new("Aggregation source: '#{source}' must be included in #{SOURCES.keys}")
+ )
+ end
+
+ if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME && source == REDIS_SOURCE
+ return failure(
+ DisallowedAggregationTimeFrame
+ .new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
+ )
+ end
+
+ yield
+ end
+
+ def failure(error)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
Gitlab::Utils::UsageData::FALLBACK
end
@@ -82,6 +92,17 @@ module Gitlab
def load_yaml_from_path(path)
YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
end
+
+ def time_constraints(time_frame)
+ case time_frame
+ when Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
+ monthly_time_range
+ when Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
+ weekly_time_range
+ when Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
+ { start_date: nil, end_date: nil }
+ end
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb b/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb
new file mode 100644
index 00000000000..63ead5a8cb0
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ # Usage example
+ #
+ # In metric YAML definition:
+ #
+ # instrumentation_class: AggregatedMetric
+ # data_source: redis_hll
+ # options:
+ # aggregate:
+ # operator: OR
+ # attribute: user_id
+ # events:
+ # - 'incident_management_alert_status_changed'
+ # - 'incident_management_alert_assigned'
+ # - 'incident_management_alert_todo'
+ # - 'incident_management_alert_create_incident'
+
+ class AggregatedMetric < BaseMetric
+ FALLBACK = -1
+
+ def initialize(metric_definition)
+ super
+ @source = parse_data_source_to_legacy_value(metric_definition)
+ @aggregate = options.fetch(:aggregate, {})
+ end
+
+ def value
+ alt_usage_data(fallback: FALLBACK) do
+ Aggregates::Aggregate
+ .new(Time.current)
+ .calculate_count_for_aggregation(
+ aggregation: aggregate_config,
+ time_frame: time_frame
+ )
+ end
+ end
+
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(:alt)
+ end
+
+ private
+
+ attr_accessor :source, :aggregate
+
+ # TODO: This method is a temporary measure that
+ # handles backwards compatibility until
+ # point 5 from is resolved https://gitlab.com/gitlab-org/gitlab/-/issues/370963#implementation
+ def parse_data_source_to_legacy_value(metric_definition)
+ return 'redis' if metric_definition[:data_source] == 'redis_hll'
+
+ metric_definition[:data_source]
+ end
+
+ def aggregate_config
+ {
+ source: source,
+ events: options[:events],
+ operator: aggregate[:operator]
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index 5e20766b1b4..55da2315e45 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -23,9 +23,9 @@ module Gitlab
attr_reader :metric_available
end
- def initialize(time_frame:, options: {})
- @time_frame = time_frame
- @options = options
+ def initialize(metric_definition)
+ @time_frame = metric_definition.fetch(:time_frame)
+ @options = metric_definition.fetch(:options, {})
end
def instrumentation
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
index 67dc1455b23..642b67a3b02 100644
--- a/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
@@ -7,7 +7,7 @@ module Gitlab
class CountBulkImportsEntitiesMetric < DatabaseMetric
operation :count
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
if source_type.present? && !source_type.in?(allowed_source_types)
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
index c5498ce530f..d485e8b4f72 100644
--- a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
@@ -7,7 +7,7 @@ module Gitlab
class CountImportedProjectsMetric < DatabaseMetric
operation :count
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
raise ArgumentError, "import_type options attribute is required" unless import_type.present?
diff --git a/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb
new file mode 100644
index 00000000000..0c421dc3311
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class DistinctCountProjectsWithExpirationPolicyDisabledMetric < DatabaseMetric
+ operation :distinct_count, column: :project_id
+
+ start { Project.minimum(:id) }
+ finish { Project.maximum(:id) }
+
+ cache_start_and_finish_as :project_id
+
+ relation { ::ContainerExpirationPolicy.where(enabled: false) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
index 0f4b903b99c..7c646281598 100644
--- a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
@@ -28,9 +28,8 @@ module Gitlab
end
end
- def initialize(time_frame: 'none', options: {})
- @time_frame = time_frame
- @options = options
+ def initialize(metric_definition)
+ super(metric_definition.reverse_merge(time_frame: 'none'))
end
def value
diff --git a/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb
new file mode 100644
index 00000000000..f22ee2aa3f5
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class GitlabForJiraAppDirectInstallationsCountMetric < DatabaseMetric
+ operation :count
+
+ relation { JiraConnectInstallation.direct_installations }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb
new file mode 100644
index 00000000000..222a69faf8b
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class GitlabForJiraAppProxyInstallationsCountMetric < DatabaseMetric
+ operation :count
+
+ relation { JiraConnectInstallation.proxy_installations }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb b/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb
new file mode 100644
index 00000000000..e2fdb3462c5
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ # Usage example
+ #
+ # In metric YAML definition:
+ #
+ # instrumentation_class: MergeRequestWidgetExtensionMetric
+ # options:
+ # event: expand
+ # widget: terraform
+ #
+ class MergeRequestWidgetExtensionMetric < RedisMetric
+ extend ::Gitlab::Utils::Override
+
+ def validate_options!
+ raise ArgumentError, "'event' option is required" unless metric_event.present?
+ raise ArgumentError, "'widget' option is required" unless widget_name.present?
+ end
+
+ def widget_name
+ options[:widget]
+ end
+
+ override :prefix
+ def prefix
+ 'i_code_review_merge_request_widget'
+ end
+
+ private
+
+ override :redis_key
+ def redis_key
+ "#{USAGE_PREFIX}#{prefix}_#{widget_name}_count_#{metric_event}".upcase
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
index bb27cca1bb9..17009f7638e 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
@@ -12,7 +12,7 @@ module Gitlab
# events:
# - g_analytics_valuestream
# end
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
raise ArgumentError, "options events are required" unless metric_events.present?
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
index 26d963e2407..ae3326fa845 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
@@ -17,12 +17,17 @@ module Gitlab
include Gitlab::UsageDataCounters::RedisCounter
USAGE_PREFIX = "USAGE_"
+ OPTIONS_PREFIX_KEY = :prefix
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
+ validate_options!
+ end
+
+ def validate_options!
raise ArgumentError, "'event' option is required" unless metric_event.present?
- raise ArgumentError, "'prefix' option is required" unless prefix.present?
+ raise ArgumentError, "'prefix' option is required" unless options.has_key?(OPTIONS_PREFIX_KEY)
end
def metric_event
@@ -30,7 +35,7 @@ module Gitlab
end
def prefix
- options[:prefix]
+ options[OPTIONS_PREFIX_KEY]
end
def include_usage_prefix?
@@ -50,9 +55,10 @@ module Gitlab
private
def redis_key
- key = "#{prefix}_#{metric_event}".upcase
+ key = metric_event.dup
+ key.prepend("#{prefix}_") if prefix
key.prepend(USAGE_PREFIX) if include_usage_prefix?
- key
+ key.upcase
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb b/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb
new file mode 100644
index 00000000000..d045265495a
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class WorkItemsActivityAggregatedMetric < AggregatedMetric
+ available? { Feature.enabled?(:track_work_items_activity) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index e2232dc5e2a..87ccb9a31da 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -21,18 +21,18 @@ module Gitlab
MAX_GENERATION_TIME_FOR_SAAS = 40.hours
CE_MEMOIZED_VALUES = %i(
- issue_minimum_id
- issue_maximum_id
- project_minimum_id
- project_maximum_id
- user_minimum_id
- user_maximum_id
- deployment_minimum_id
- deployment_maximum_id
- auth_providers
- aggregated_metrics
- recorded_at
- ).freeze
+ issue_minimum_id
+ issue_maximum_id
+ project_minimum_id
+ project_maximum_id
+ user_minimum_id
+ user_maximum_id
+ deployment_minimum_id
+ deployment_maximum_id
+ auth_providers
+ aggregated_metrics
+ recorded_at
+ ).freeze
class << self
include Gitlab::Utils::UsageData
@@ -346,7 +346,6 @@ module Gitlab
start = minimum_id(Project)
finish = maximum_id(Project)
- results[:projects_with_expiration_policy_disabled] = distinct_count(::ContainerExpirationPolicy.where(enabled: false), :project_id, start: start, finish: finish)
# rubocop: disable UsageData/LargeTable
base = ::ContainerExpirationPolicy.active
# rubocop: enable UsageData/LargeTable
diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb
index eae1c593a8f..37c6e1af7c0 100644
--- a/lib/gitlab/usage_data_counters.rb
+++ b/lib/gitlab/usage_data_counters.rb
@@ -2,25 +2,24 @@
module Gitlab
module UsageDataCounters
- COUNTERS = [
- WikiPageCounter,
- NoteCounter,
- SnippetCounter,
- SearchCounter,
- CycleAnalyticsCounter,
- ProductivityAnalyticsCounter,
- SourceCodeCounter,
- KubernetesAgentCounter,
- MergeRequestWidgetExtensionCounter
- ].freeze
+ COUNTERS = [].freeze
COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES = [
PackageEventCounter,
MergeRequestCounter,
DesignsCounter,
DiffsCounter,
+ KubernetesAgentCounter,
+ NoteCounter,
+ SearchCounter,
ServiceUsageDataCounter,
- WebIdeCounter
+ WebIdeCounter,
+ WikiPageCounter,
+ SnippetCounter,
+ CycleAnalyticsCounter,
+ ProductivityAnalyticsCounter,
+ SourceCodeCounter,
+ MergeRequestWidgetExtensionCounter
].freeze
UsageDataCounterError = Class.new(StandardError)
@@ -28,13 +27,11 @@ module Gitlab
class << self
def unmigrated_counters
- # we are using the #counters method instead of the COUNTERS const
- # to make sure it's working correctly for `ee` version of UsageDataCounters
- counters - self::COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES
+ self::COUNTERS
end
def counters
- self::COUNTERS + self::COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES
+ unmigrated_counters + migrated_counters
end
def count(event_name)
@@ -46,6 +43,12 @@ module Gitlab
raise UnknownEvent, "Cannot find counter for event #{event_name}"
end
+
+ private
+
+ def migrated_counters
+ COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES
+ end
end
end
end
diff --git a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
index 61c071c8738..1e8918c7c96 100644
--- a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
@@ -34,6 +34,21 @@ module Gitlab::UsageDataCounters
Gitlab::Template::GitlabCiYmlTemplate.find(template_name.chomp('.gitlab-ci.yml'))&.full_name
end
+ def all_included_templates(template_name)
+ expanded_template_name = expand_template_name(template_name)
+ results = [expanded_template_name].tap do |result|
+ template = Gitlab::Template::GitlabCiYmlTemplate.find(template_name.chomp('.gitlab-ci.yml'))
+ data = YAML.safe_load(template.content, aliases: true)
+ [data['include']].compact.flatten.each do |ci_include|
+ if ci_include_template = ci_include['template']
+ result.concat(all_included_templates(ci_include_template))
+ end
+ end
+ end
+
+ results.uniq.sort_by { _1['name'] }
+ end
+
private
def template_to_event_name(template)
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index f0cb9bcbe94..24a87ae01f4 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -19,18 +19,14 @@ module Gitlab
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
CATEGORIES_FOR_TOTALS = %w[
- analytics
compliance
- epics_usage
error_tracking
ide_edit
- incident_management
- issues_edit
pipeline_authoring
- quickactions
].freeze
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
+ analytics
ci_users
deploy_token_packages
code_review
@@ -38,9 +34,13 @@ module Gitlab
error_tracking
ide_edit
importer
+ incident_management
incident_management_alerts
+ issues_edit
kubernetes_agent
+ manage
pipeline_authoring
+ quickactions
search
secure
snippets
diff --git a/lib/gitlab/usage_data_counters/known_events/analytics.yml b/lib/gitlab/usage_data_counters/known_events/analytics.yml
index 76c97a974d7..85524c766ca 100644
--- a/lib/gitlab/usage_data_counters/known_events/analytics.yml
+++ b/lib/gitlab/usage_data_counters/known_events/analytics.yml
@@ -10,54 +10,18 @@
category: analytics
redis_slot: analytics
aggregation: weekly
-- name: p_analytics_merge_request
- category: analytics
- redis_slot: analytics
- aggregation: weekly
- name: i_analytics_instance_statistics
category: analytics
redis_slot: analytics
aggregation: weekly
-- name: g_analytics_contribution
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_insights
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_issues
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_productivity
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_valuestream
- category: analytics
- redis_slot: analytics
- aggregation: weekly
- name: p_analytics_pipelines
category: analytics
redis_slot: analytics
aggregation: weekly
-- name: p_analytics_code_reviews
- category: analytics
- redis_slot: analytics
- aggregation: weekly
- name: p_analytics_valuestream
category: analytics
redis_slot: analytics
aggregation: weekly
-- name: p_analytics_insights
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: p_analytics_issues
- category: analytics
- redis_slot: analytics
- aggregation: weekly
- name: p_analytics_repo
category: analytics
redis_slot: analytics
@@ -86,23 +50,3 @@
category: analytics
redis_slot: analytics
aggregation: weekly
-- name: g_analytics_ci_cd_release_statistics
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_ci_cd_deployment_frequency
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_ci_cd_lead_time
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_ci_cd_time_to_restore_service
- category: analytics
- redis_slot: analytics
- aggregation: weekly
-- name: g_analytics_ci_cd_change_failure_rate
- 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 10e36a75a3a..5b80f6c6c0d 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -99,6 +99,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_coverage_fuzzing_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_dast_on_demand_api_scan
category: ci_templates
redis_slot: ci_templates
@@ -499,27 +503,11 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_dast_default_branch_deploy
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_load_performance_testing
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_helm_2to3
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_sast
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_secret_detection
+- name: p_ci_templates_implicit_jobs_browser_performance_testing
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_license_scanning
+- name: p_ci_templates_implicit_jobs_build
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -531,47 +519,7 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_deploy_ecs
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_deploy_ec2
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_license_scanning_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_deploy
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_build
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_browser_performance_testing
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_dependency_scanning_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_test
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_sast_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_sast_iac
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_secret_detection_latest
+- name: p_ci_templates_implicit_jobs_dast_default_branch_deploy
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -579,63 +527,35 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_jobs_deploy_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_browser_performance_testing_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_cf_provision
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_build_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_jobs_sast_iac_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_sast
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_runner_validation
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_on_demand_scan
+- name: p_ci_templates_implicit_jobs_deploy
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_secret_detection
+- name: p_ci_templates_implicit_jobs_deploy_ec2
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_license_scanning
+- name: p_ci_templates_implicit_jobs_deploy_ecs
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_on_demand_api_scan
+- name: p_ci_templates_implicit_jobs_helm_2to3
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_coverage_fuzzing
+- name: p_ci_templates_implicit_jobs_license_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_api_fuzzing_latest
+- name: p_ci_templates_implicit_jobs_sast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_secure_binaries
+- name: p_ci_templates_implicit_jobs_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_api
+- name: p_ci_templates_implicit_jobs_test
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -643,11 +563,7 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_dast_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_sast_iac
+- name: p_ci_templates_implicit_security_dast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
@@ -655,27 +571,15 @@
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_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_api_fuzzing
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
-- name: p_ci_templates_implicit_security_dast
+- name: p_ci_templates_implicit_security_license_scanning
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_fortify_fod_sast
+- name: p_ci_templates_implicit_security_sast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
-- name: p_ci_templates_implicit_security_sast_iac_latest
+- name: p_ci_templates_implicit_security_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index 29b231f88f8..c13c7657576 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -84,11 +84,6 @@
redis_slot: incident_management
category: incident_management
aggregation: weekly
-- name: incident_management_incident_published
- redis_slot: incident_management
- category: incident_management
- aggregation: weekly
- feature_flag: usage_data_incident_management_incident_published
- name: incident_management_incident_relate
redis_slot: incident_management
category: incident_management
@@ -114,29 +109,11 @@
redis_slot: incident_management
category: incident_management
aggregation: weekly
-# Incident management linked resources
-- name: incident_management_issuable_resource_link_created
- redis_slot: incident_management
- category: incident_management
- aggregation: weekly
-- name: incident_management_issuable_resource_link_deleted
- redis_slot: incident_management
- category: incident_management
- aggregation: weekly
-- name: incident_management_issuable_resource_link_visited
- redis_slot: incident_management
- category: incident_management
- aggregation: weekly
# Incident management alerts
- name: incident_management_alert_create_incident
redis_slot: incident_management
category: incident_management_alerts
aggregation: weekly
-# Incident management on-call
-- name: i_incident_management_oncall_notification_sent
- redis_slot: incident_management
- category: incident_management_oncall
- aggregation: weekly
# Testing category
- name: i_testing_test_case_parsed
category: testing
@@ -150,7 +127,6 @@
category: testing
redis_slot: testing
aggregation: weekly
- feature_flag: usage_data_ci_i_testing_test_report_uploaded
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
@@ -192,14 +168,6 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
-- name: g_project_management_issue_iteration_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_weight_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
- name: g_project_management_issue_cross_referenced
category: issues_edit
redis_slot: project_management
@@ -228,18 +196,6 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
-- name: g_project_management_issue_added_to_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_removed_from_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
-- name: g_project_management_issue_changed_epic
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
- name: g_project_management_issue_designs_added
category: issues_edit
redis_slot: project_management
@@ -276,20 +232,11 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
-- name: g_project_management_issue_health_status_changed
- category: issues_edit
- redis_slot: project_management
- aggregation: daily
- name: g_project_management_issue_cloned
category: issues_edit
redis_slot: project_management
aggregation: daily
# Secrets Management
-- name: i_ci_secrets_management_vault_build_created
- category: ci_secrets_management
- redis_slot: ci_secrets_management
- aggregation: weekly
- feature_flag: usage_data_i_ci_secrets_management_vault_build_created
- name: i_snippets_show
category: snippets
redis_slot: snippets
@@ -342,11 +289,6 @@
category: geo
redis_slot: geo
aggregation: daily
-# Growth
-- name: users_clicking_registration_features_offer
- category: growth
- redis_slot: users
- aggregation: weekly
# Manage
- name: unique_active_user
category: manage
diff --git a/lib/gitlab/usage_data_counters/known_events/epic_events.yml b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
deleted file mode 100644
index dd6625a9cc9..00000000000
--- a/lib/gitlab/usage_data_counters/known_events/epic_events.yml
+++ /dev/null
@@ -1,227 +0,0 @@
-# Epic events
-#
-# We are using the same slot of issue events 'project_management' for
-# epic events to allow data aggregation.
-# More information in: https://gitlab.com/gitlab-org/gitlab/-/issues/322405
-- name: g_project_management_epic_created
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# content change events
-
-- name: project_management_users_unchecking_epic_task
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: project_management_users_checking_epic_task
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_epic_titles
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_epic_descriptions
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# epic notes
-
-- name: g_project_management_users_creating_epic_notes
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_epic_notes
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_destroying_epic_notes
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# emoji
-
-- name: g_project_management_users_awarding_epic_emoji
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_removing_epic_emoji
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# start date events
-
-- name: g_project_management_users_setting_epic_start_date_as_fixed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_fixed_epic_start_date
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_setting_epic_start_date_as_inherited
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# due date events
-
-- name: g_project_management_users_setting_epic_due_date_as_fixed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_fixed_epic_due_date
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_setting_epic_due_date_as_inherited
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-# relationships
-
-- name: g_project_management_epic_issue_added
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_issue_removed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_issue_moved_from_project
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_updating_epic_parent
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_closed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_reopened
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: 'g_project_management_issue_promoted_to_epic'
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_setting_epic_confidential
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_setting_epic_visible
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_users_changing_labels
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_destroyed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_cross_referenced
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_users_epic_issue_added_from_epic
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_related_added
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_related_removed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_blocking_added
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_blocking_removed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_blocked_added
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
-- name: g_project_management_epic_blocked_removed
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
-
diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
index 58a0c0695af..69b348b9a22 100644
--- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml
+++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
@@ -1,17 +1,17 @@
---
-- name: i_quickactions_approve
+- name: i_quickactions_assign_multiple
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_unapprove
+- name: i_quickactions_approve
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_assign_single
+- name: i_quickactions_unapprove
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_assign_multiple
+- name: i_quickactions_assign_single
category: quickactions
redis_slot: quickactions
aggregation: weekly
@@ -31,18 +31,6 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_child_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
-- name: i_quickactions_clear_weight
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
-- name: i_quickactions_clear_health_status
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_clone
category: quickactions
redis_slot: quickactions
@@ -83,18 +71,10 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_estimate
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_iteration
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_label
category: quickactions
redis_slot: quickactions
@@ -115,14 +95,6 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_parent_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
-- name: i_quickactions_promote
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_promote_to_incident
category: quickactions
redis_slot: quickactions
@@ -131,14 +103,6 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_page
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
-- name: i_quickactions_publish
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_ready
category: quickactions
redis_slot: quickactions
@@ -163,34 +127,18 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_remove_child_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_remove_due_date
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_remove_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_remove_estimate
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_remove_iteration
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_remove_milestone
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_remove_parent_epic
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
- name: i_quickactions_remove_time_spent
category: quickactions
redis_slot: quickactions
@@ -275,19 +223,15 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_weight
- category: quickactions
- redis_slot: quickactions
- aggregation: weekly
-- name: i_quickactions_health_status
+- name: i_quickactions_wip
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_wip
+- name: i_quickactions_zoom
category: quickactions
redis_slot: quickactions
aggregation: weekly
-- name: i_quickactions_zoom
+- name: i_quickactions_link
category: quickactions
redis_slot: quickactions
aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/work_items.yml b/lib/gitlab/usage_data_counters/known_events/work_items.yml
index 6cd7836ea94..ee828fc0f72 100644
--- a/lib/gitlab/usage_data_counters/known_events/work_items.yml
+++ b/lib/gitlab/usage_data_counters/known_events/work_items.yml
@@ -14,3 +14,16 @@
redis_slot: users
aggregation: weekly
feature_flag: track_work_items_activity
+- name: users_updating_work_item_labels
+ category: work_items
+ redis_slot: users
+ aggregation: weekly
+ feature_flag: track_work_items_activity
+- name: users_updating_work_item_iteration
+ # The event tracks an EE feature.
+ # It's added here so it can be aggregated into the CE/EE 'OR' aggregate metrics.
+ # It will report 0 for CE instances and should not be used with 'AND' aggregators.
+ category: work_items
+ redis_slot: users
+ aggregation: weekly
+ feature_flag: track_work_items_activity
diff --git a/lib/gitlab/usage_data_counters/work_item_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/work_item_activity_unique_counter.rb
index 99b4c082310..a0fd04596fc 100644
--- a/lib/gitlab/usage_data_counters/work_item_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/work_item_activity_unique_counter.rb
@@ -6,6 +6,7 @@ module Gitlab
WORK_ITEM_CREATED = 'users_creating_work_items'
WORK_ITEM_TITLE_CHANGED = 'users_updating_work_item_title'
WORK_ITEM_DATE_CHANGED = 'users_updating_work_item_dates'
+ WORK_ITEM_LABELS_CHANGED = 'users_updating_work_item_labels'
class << self
def track_work_item_created_action(author:)
@@ -20,6 +21,10 @@ module Gitlab
track_unique_action(WORK_ITEM_DATE_CHANGED, author)
end
+ def track_work_item_labels_changed_action(author:)
+ track_unique_action(WORK_ITEM_LABELS_CHANGED, author)
+ end
+
private
def track_unique_action(action, author)
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
index c2983779603..4486ca53966 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -75,10 +75,6 @@ module Gitlab
}
end
- def epics_deepest_relationship_level
- { epics_deepest_relationship_level: 0 }
- end
-
def topology_usage_data
{
duration_s: 0,
diff --git a/lib/gitlab/utils/execution_tracker.rb b/lib/gitlab/utils/execution_tracker.rb
index 6d48658853c..92398926e1b 100644
--- a/lib/gitlab/utils/execution_tracker.rb
+++ b/lib/gitlab/utils/execution_tracker.rb
@@ -3,7 +3,7 @@
module Gitlab
module Utils
class ExecutionTracker
- MAX_RUNTIME = 30.seconds
+ MAX_RUNTIME = 60.seconds
ExecutionTimeOutError = Class.new(StandardError)
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 19bdeefed7e..0b818b99ac7 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -291,14 +291,6 @@ module Gitlab
end
end
- def epics_deepest_relationship_level
- with_duration do
- # rubocop: disable UsageData/LargeTable
- { epics_deepest_relationship_level: ::Epic.deepest_relationship_level.to_i }
- # rubocop: enable UsageData/LargeTable
- end
- end
-
private
def prometheus_client(verify:)
diff --git a/lib/gitlab/web_hooks.rb b/lib/gitlab/web_hooks.rb
index 349c7a020cc..8c6de56292a 100644
--- a/lib/gitlab/web_hooks.rb
+++ b/lib/gitlab/web_hooks.rb
@@ -3,5 +3,6 @@
module Gitlab
module WebHooks
GITLAB_EVENT_HEADER = 'X-Gitlab-Event'
+ GITLAB_INSTANCE_HEADER = 'X-Gitlab-Instance'
end
end
diff --git a/lib/gitlab/x509/signature.rb b/lib/gitlab/x509/signature.rb
index 8acbfc144e9..f8a6980f208 100644
--- a/lib/gitlab/x509/signature.rb
+++ b/lib/gitlab/x509/signature.rb
@@ -37,7 +37,7 @@ module Gitlab
!verified_signature ||
user.nil?
- if user.verified_emails.include?(@email) && certificate_email == @email
+ if user.verified_emails.include?(@email.downcase) && certificate_email.casecmp?(@email)
:verified
else
:unverified
diff --git a/lib/prometheus/pid_provider.rb b/lib/prometheus/pid_provider.rb
index d2563b4c806..05a2d3bd0c9 100644
--- a/lib/prometheus/pid_provider.rb
+++ b/lib/prometheus/pid_provider.rb
@@ -39,7 +39,7 @@ module Prometheus
end
def process_name
- $0
+ $PROGRAM_NAME
end
end
end
diff --git a/lib/quality/seeders/issues.rb b/lib/quality/seeders/issues.rb
index 5d345dd30a1..bf42913e043 100644
--- a/lib/quality/seeders/issues.rb
+++ b/lib/quality/seeders/issues.rb
@@ -31,9 +31,9 @@ module Quality
}
params[:closed_at] = params[:created_at] + rand(35).days if params[:state] == 'closed'
- issue = ::Issues::CreateService.new(project: project, current_user: team.sample, params: params, spam_params: nil).execute_without_rate_limiting
+ create_result = ::Issues::CreateService.new(project: project, current_user: team.sample, params: params, spam_params: nil).execute_without_rate_limiting
- if issue.persisted?
+ if create_result.success?
created_issues_count += 1
print '.' # rubocop:disable Rails/Output
end
diff --git a/lib/sidebars/groups/menus/packages_registries_menu.rb b/lib/sidebars/groups/menus/packages_registries_menu.rb
index 61cd81711f8..873f11f8a5b 100644
--- a/lib/sidebars/groups/menus/packages_registries_menu.rb
+++ b/lib/sidebars/groups/menus/packages_registries_menu.rb
@@ -8,7 +8,7 @@ module Sidebars
def configure_menu_items
add_item(packages_registry_menu_item)
add_item(container_registry_menu_item)
- add_item(harbor_registry__menu_item)
+ add_item(harbor_registry_menu_item)
add_item(dependency_proxy_menu_item)
true
end
@@ -49,8 +49,10 @@ module Sidebars
)
end
- def harbor_registry__menu_item
- if Feature.disabled?(:harbor_registry_integration) || context.group.harbor_integration.nil?
+ def harbor_registry_menu_item
+ if Feature.disabled?(:harbor_registry_integration) ||
+ context.group.harbor_integration.nil? ||
+ !context.group.harbor_integration.activated?
return nil_menu_item(:harbor_registry)
end
diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb
index 63eea0ea500..2181d89262b 100644
--- a/lib/sidebars/projects/menus/infrastructure_menu.rb
+++ b/lib/sidebars/projects/menus/infrastructure_menu.rb
@@ -89,12 +89,12 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Google Cloud'),
link: project_google_cloud_configuration_path(context.project),
- active_routes: { controller: [
- :configuration,
- :service_accounts,
- :databases,
- :deployments,
- :gcp_regions
+ active_routes: { controller: %w[
+ projects/google_cloud/configuration
+ projects/google_cloud/service_accounts
+ projects/google_cloud/databases
+ projects/google_cloud/deployments
+ projects/google_cloud/gcp_regions
] },
item_id: :google_cloud
)
diff --git a/lib/sidebars/projects/menus/packages_registries_menu.rb b/lib/sidebars/projects/menus/packages_registries_menu.rb
index 2ddffe42899..fc7c564574a 100644
--- a/lib/sidebars/projects/menus/packages_registries_menu.rb
+++ b/lib/sidebars/projects/menus/packages_registries_menu.rb
@@ -9,7 +9,7 @@ module Sidebars
add_item(packages_registry_menu_item)
add_item(container_registry_menu_item)
add_item(infrastructure_registry_menu_item)
- add_item(harbor_registry__menu_item)
+ add_item(harbor_registry_menu_item)
true
end
@@ -65,8 +65,10 @@ module Sidebars
)
end
- def harbor_registry__menu_item
- if Feature.disabled?(:harbor_registry_integration, context.project) || context.project.harbor_integration.nil?
+ def harbor_registry_menu_item
+ if Feature.disabled?(:harbor_registry_integration, context.project) ||
+ context.project.harbor_integration.nil? ||
+ !context.project.harbor_integration.activated?
return ::Sidebars::NilMenuItem.new(item_id: :harbor_registry)
end
diff --git a/lib/sidebars/projects/menus/repository_menu.rb b/lib/sidebars/projects/menus/repository_menu.rb
index 0a295f0f618..1b46323089c 100644
--- a/lib/sidebars/projects/menus/repository_menu.rb
+++ b/lib/sidebars/projects/menus/repository_menu.rb
@@ -85,6 +85,8 @@ module Sidebars
end
def contributors_menu_item
+ return false unless context.project.analytics_enabled?
+
::Sidebars::MenuItem.new(
title: _('Contributors'),
link: project_graph_path(context.project, context.current_ref),
diff --git a/lib/system_check/app/authorized_keys_permission_check.rb b/lib/system_check/app/authorized_keys_permission_check.rb
index 1246a6875a3..9b81812de74 100644
--- a/lib/system_check/app/authorized_keys_permission_check.rb
+++ b/lib/system_check/app/authorized_keys_permission_check.rb
@@ -19,11 +19,12 @@ module SystemCheck
end
def show_error
- try_fixing_it([
- "sudo chmod 700 #{File.dirname(authorized_keys.file)}",
- "touch #{authorized_keys.file}",
- "sudo chmod 600 #{authorized_keys.file}"
- ])
+ try_fixing_it(
+ [
+ "sudo chmod 700 #{File.dirname(authorized_keys.file)}",
+ "touch #{authorized_keys.file}",
+ "sudo chmod 600 #{authorized_keys.file}"
+ ])
fix_and_rerun
end
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index 76ee5379213..b58d9473794 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -5,28 +5,52 @@ require 'fileutils'
module Tasks
module Gitlab
module Assets
- FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets/javascripts].freeze
+ FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets].freeze
EE_ASSET_FOLDERS = %w[ee/app/assets].freeze
JH_ASSET_FOLDERS = %w[jh/app/assets].freeze
- JS_ASSET_PATTERNS = %w[*.js config/**/*.js].freeze
- JS_ASSET_FILES = %w[package.json yarn.lock].freeze
- MASTER_SHA256_HASH_FILE = 'master-assets-hash.txt'
- HEAD_SHA256_HASH_FILE = 'assets-hash.txt'
- PUBLIC_ASSETS_WEBPACK_DIR = 'public/assets/webpack'
+ # In the new caching strategy, we check the assets hash sum *before* compiling
+ # the app/assets/javascripts/locale/**/app.js files. That means the hash sum
+ # must depend on locale/**/gitlab.po.
+ JS_ASSET_PATTERNS = %w[*.js config/**/*.js locale/**/gitlab.po].freeze
+ JS_ASSET_FILES = %w[
+ package.json
+ yarn.lock
+ babel.config.js
+ config/webpack.config.js
+ ].freeze
+ EXCLUDE_PATTERNS = %w[
+ app/assets/javascripts/locale/**/app.js
+ ].freeze
+ PUBLIC_ASSETS_DIR = 'public/assets'
+ HEAD_ASSETS_SHA256_HASH_ENV = 'GITLAB_ASSETS_HASH'
+ CACHED_ASSETS_SHA256_HASH_FILE = 'cached-assets-hash.txt'
+
+ def self.master_assets_sha256
+ @master_assets_sha256 ||=
+ if File.exist?(Tasks::Gitlab::Assets::CACHED_ASSETS_SHA256_HASH_FILE)
+ File.read(Tasks::Gitlab::Assets::CACHED_ASSETS_SHA256_HASH_FILE)
+ else
+ 'missing!'
+ end
+ end
+
+ def self.head_assets_sha256
+ @head_assets_sha256 ||= ENV.fetch(Tasks::Gitlab::Assets::HEAD_ASSETS_SHA256_HASH_ENV) do
+ Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation(verbose: false)
+ end
+ end
- def self.sha256_of_assets_impacting_webpack_compilation
+ def self.sha256_of_assets_impacting_compilation(verbose: true)
start_time = Time.now
- asset_files = assets_impacting_webpack_compilation
- puts "Generating the SHA256 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..."
+ asset_files = assets_impacting_compilation
+ puts "Generating the SHA256 hash for #{asset_files.size} Webpack-related assets..." if verbose
- asset_file_sha256s = asset_files.map do |asset_file|
- Digest::SHA256.file(asset_file).hexdigest
- end
+ assets_sha256 = asset_files.map { |asset_file| Digest::SHA256.file(asset_file).hexdigest }.join
- Digest::SHA256.hexdigest(asset_file_sha256s.join).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" }
+ Digest::SHA256.hexdigest(assets_sha256).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" if verbose }
end
- def self.assets_impacting_webpack_compilation
+ def self.assets_impacting_compilation
assets_folders = FOSS_ASSET_FOLDERS
assets_folders += EE_ASSET_FOLDERS if ::Gitlab.ee?
assets_folders += JH_ASSET_FOLDERS if ::Gitlab.jh?
@@ -38,52 +62,34 @@ module Tasks
asset_files.concat(Dir.glob(["#{folder}/**/*.*"]))
end
- asset_files
+ asset_files - Dir.glob(EXCLUDE_PATTERNS)
end
-
- private_class_method :assets_impacting_webpack_compilation
+ private_class_method :assets_impacting_compilation
end
end
end
namespace :gitlab do
namespace :assets do
+ desc 'GitLab | Assets | Return the hash sum of all frontend assets'
+ task :hash_sum do
+ print Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation(verbose: false)
+ end
+
desc 'GitLab | Assets | Compile all frontend assets'
task :compile do
require_dependency 'gitlab/task_helpers'
- %w[
- yarn:check
- gettext:po_to_json
- rake:assets:precompile
- gitlab:assets:compile_webpack_if_needed
- gitlab:assets:fix_urls
- gitlab:assets:check_page_bundle_mixins_css_for_sideeffects
- ].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task))
- end
-
- desc 'GitLab | Assets | Compile all Webpack assets'
- task :compile_webpack_if_needed do
- FileUtils.mv(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE, force: true)
-
- master_assets_sha256 =
- if File.exist?(Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE)
- File.read(Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE)
- else
- 'missing!'
- end
+ puts "Assets SHA256 for `master`: #{Tasks::Gitlab::Assets.master_assets_sha256.inspect}"
+ puts "Assets SHA256 for `HEAD`: #{Tasks::Gitlab::Assets.head_assets_sha256.inspect}"
- head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_webpack_compilation.tap do |sha256|
- File.write(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, sha256)
- end
-
- puts "Webpack assets SHA256 for `master`: #{master_assets_sha256}"
- puts "Webpack assets SHA256 for `HEAD`: #{head_assets_sha256}"
+ if Tasks::Gitlab::Assets.head_assets_sha256 != Tasks::Gitlab::Assets.master_assets_sha256
+ FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR) if Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR)
- public_assets_webpack_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR)
-
- if head_assets_sha256 != master_assets_sha256 || !public_assets_webpack_dir_exists
- FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists
+ # gettext:po_to_json needs to run before rake:assets:precompile because
+ # app/assets/javascripts/locale/**/app.js are pre-compiled by Sprockets
+ Gitlab::TaskHelpers.invoke_and_time_task('gettext:po_to_json')
+ Gitlab::TaskHelpers.invoke_and_time_task('rake:assets:precompile')
log_path = ENV['WEBPACK_COMPILE_LOG_PATH']
@@ -96,6 +102,9 @@ namespace :gitlab do
puts "Written webpack stdout log to #{log_path}" if log_path
puts "You can inspect the webpack log here: #{ENV['CI_JOB_URL']}/artifacts/file/#{log_path}" if log_path && ENV['CI_JOB_URL']
+
+ Gitlab::TaskHelpers.invoke_and_time_task('gitlab:assets:fix_urls')
+ Gitlab::TaskHelpers.invoke_and_time_task('gitlab:assets:check_page_bundle_mixins_css_for_sideeffects')
end
end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index ff43a36d930..6647a10898f 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -4,121 +4,168 @@ require 'active_record/fixtures'
namespace :gitlab do
namespace :backup do
+ PID = Process.pid.freeze
+ PID_FILE = "#{Rails.application.root}/tmp/backup_restore.pid"
+
# Create backup of GitLab system
desc 'GitLab | Backup | Create a backup of the GitLab system'
task create: :gitlab_environment do
- warn_user_is_not_gitlab
+ lock do
+ warn_user_is_not_gitlab
- Backup::Manager.new(progress).create
+ Backup::Manager.new(progress).create
+ end
end
# Restore backup of GitLab system
desc 'GitLab | Backup | Restore a previously created backup'
task restore: :gitlab_environment do
- warn_user_is_not_gitlab
+ lock do
+ warn_user_is_not_gitlab
- Backup::Manager.new(progress).restore
+ Backup::Manager.new(progress).restore
+ end
end
namespace :repo do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('repositories')
+ lock do
+ Backup::Manager.new(progress).run_create_task('repositories')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('repositories')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('repositories')
+ end
end
end
namespace :db do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('main_db')
- Backup::Manager.new(progress).run_create_task('ci_db')
+ lock do
+ Backup::Manager.new(progress).run_create_task('main_db')
+ Backup::Manager.new(progress).run_create_task('ci_db')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('main_db')
- Backup::Manager.new(progress).run_restore_task('ci_db')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('main_db')
+ Backup::Manager.new(progress).run_restore_task('ci_db')
+ end
end
end
namespace :builds do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('builds')
+ lock do
+ Backup::Manager.new(progress).run_create_task('builds')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('builds')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('builds')
+ end
end
end
namespace :uploads do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('uploads')
+ lock do
+ Backup::Manager.new(progress).run_create_task('uploads')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('uploads')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('uploads')
+ end
end
end
namespace :artifacts do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('artifacts')
+ lock do
+ Backup::Manager.new(progress).run_create_task('artifacts')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('artifacts')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('artifacts')
+ end
end
end
namespace :pages do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('pages')
+ lock do
+ Backup::Manager.new(progress).run_create_task('pages')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('pages')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('pages')
+ end
end
end
namespace :lfs do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('lfs')
+ lock do
+ Backup::Manager.new(progress).run_create_task('lfs')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('lfs')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('lfs')
+ end
end
end
namespace :terraform_state do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('terraform_state')
+ lock do
+ Backup::Manager.new(progress).run_create_task('terraform_state')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('terraform_state')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('terraform_state')
+ end
end
end
namespace :registry do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('registry')
+ lock do
+ Backup::Manager.new(progress).run_create_task('registry')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('registry')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('registry')
+ end
end
end
namespace :packages do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('packages')
+ lock do
+ Backup::Manager.new(progress).run_create_task('packages')
+ end
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('packages')
+ lock do
+ Backup::Manager.new(progress).run_restore_task('packages')
+ end
end
end
@@ -132,6 +179,35 @@ namespace :gitlab do
$stdout
end
end
+
+ def lock
+ File.open(PID_FILE, File::RDWR | File::CREAT, 0644) do |f|
+ f.flock(File::LOCK_EX)
+
+ unless f.read.empty?
+ # There is a PID inside so the process fails
+ progress.puts(<<~HEREDOC.color(:red))
+ Backup and restore in progress:
+ There is a backup and restore task in progress. Please, try to run the current task once the previous one ends.
+ If there is no other process running, please remove the PID file manually: rm #{PID_FILE}
+ HEREDOC
+
+ exit 1
+ end
+
+ f.write(PID)
+ f.flush
+ ensure
+ f.flock(File::LOCK_UN)
+ end
+
+ begin
+ yield
+ ensure
+ progress.puts "#{Time.now} " + "-- Deleting backup and restore lock file".color(:blue)
+ File.delete(PID_FILE)
+ end
+ end
end
# namespace end: backup
end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 30e0e3e72ff..4ef0c396f4a 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -304,14 +304,30 @@ namespace :gitlab do
end
namespace :migration_testing do
- desc 'Run migrations with instrumentation'
+ # Not possible to import Gitlab::Database::DATABASE_NAMES here
+ # Specs verify that a task exists for each entry in that array.
+ all_databases = %i[main ci]
+
task up: :environment do
- Gitlab::Database::Migrations::Runner.up.run
+ Gitlab::Database::Migrations::Runner.up(database: 'main', legacy_mode: true).run
+ end
+
+ namespace :up do
+ all_databases.each do |db|
+ desc "Run migrations on #{db} with instrumentation"
+ task db => :environment do
+ Gitlab::Database::Migrations::Runner.up(database: db).run
+ end
+ end
end
- desc 'Run down migrations in current branch with instrumentation'
- task down: :environment do
- Gitlab::Database::Migrations::Runner.down.run
+ namespace :down do
+ all_databases.each do |db|
+ desc "Run down migrations on #{db} in current branch with instrumentation"
+ task db => :environment do
+ Gitlab::Database::Migrations::Runner.down(database: db).run
+ end
+ end
end
desc 'Sample traditional background migrations with instrumentation'
@@ -321,12 +337,24 @@ namespace :gitlab do
Gitlab::Database::Migrations::Runner.background_migrations.run_jobs(for_duration: duration)
end
- desc 'Sample batched background migrations with instrumentation'
+ namespace :sample_batched_background_migrations do
+ all_databases.each do |db|
+ desc "Sample batched background migrations on #{db} with instrumentation"
+ task db, [:duration_s] => [:environment] do |_t, args|
+ duration = args[:duration_s]&.to_i&.seconds || 30.minutes # Default of 30 minutes
+
+ Gitlab::Database::Migrations::Runner.batched_background_migrations(for_database: db)
+ .run_jobs(for_duration: duration)
+ end
+ end
+ end
+
+ desc "Sample batched background migrations with instrumentation (legacy)"
task :sample_batched_background_migrations, [:database, :duration_s] => [:environment] do |_t, args|
- database_name = args[:database] || 'main'
duration = args[:duration_s]&.to_i&.seconds || 30.minutes # Default of 30 minutes
- Gitlab::Database::Migrations::Runner.batched_background_migrations(for_database: database_name)
+ database = args[:database] || 'main'
+ Gitlab::Database::Migrations::Runner.batched_background_migrations(for_database: database, legacy_mode: true)
.run_jobs(for_duration: duration)
end
end
diff --git a/lib/tasks/gitlab/db/lock_writes.rake b/lib/tasks/gitlab/db/lock_writes.rake
index eb6d257cac5..421c6a90fdd 100644
--- a/lib/tasks/gitlab/db/lock_writes.rake
+++ b/lib/tasks/gitlab/db/lock_writes.rake
@@ -14,7 +14,8 @@ namespace :gitlab do
table_name: table_name,
connection: connection,
database_name: database_name,
- logger: Logger.new($stdout)
+ logger: Logger.new($stdout),
+ dry_run: ENV['DRY_RUN'] == 'true'
)
if schemas_for_connection.include?(schema_name.to_sym)
diff --git a/lib/tasks/gitlab/openapi.rake b/lib/tasks/gitlab/openapi.rake
new file mode 100644
index 00000000000..fd067a1bf0b
--- /dev/null
+++ b/lib/tasks/gitlab/openapi.rake
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+if Rails.env.development?
+ require 'grape-swagger/rake/oapi_tasks'
+ GrapeSwagger::Rake::OapiTasks.new('::API::API')
+end
+
+namespace :gitlab do
+ namespace :openapi do
+ task :generate do
+ raise 'This task can only be run in the development environment' unless Rails.env.development?
+
+ ENV['store'] = 'tmp/openapi.json'
+ Rake::Task["oapi:fetch"].invoke(['openapi.json'])
+
+ yaml_content = Gitlab::Json.parse(File.read('tmp/openapi_swagger_doc.json')).to_yaml
+
+ File.write("doc/api/openapi/openapi_v2.yaml", yaml_content)
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/seed.rake b/lib/tasks/gitlab/seed.rake
index 36761165af5..7b9c57b1876 100644
--- a/lib/tasks/gitlab/seed.rake
+++ b/lib/tasks/gitlab/seed.rake
@@ -35,5 +35,40 @@ namespace :gitlab do
puts "\n#{issues_created} issues created!"
end
end
+
+ task :epics, [:group_full_path, :backfill_weeks, :average_issues_per_week] => :environment do |t, args|
+ args.with_defaults(backfill_weeks: 5, average_issues_per_week: 2)
+
+ groups =
+ if args.group_full_path
+ group = Group.find_by_full_path(args.group_full_path)
+
+ unless group
+ error_message = "Group '#{args.group_full_path}' does not exist!"
+ potential_groups = Group.search(args.group_full_path)
+
+ if potential_groups.present?
+ error_message += " Did you mean '#{potential_groups.first.full_path}'?"
+ end
+
+ puts error_message.color(:red)
+ exit 1
+ end
+
+ [group]
+ else
+ Group.not_mass_generated.find_each
+ end
+
+ groups.each do |group|
+ puts "\nSeeding epics for the '#{group.full_path}' group"
+ seeder = Quality::Seeders::Epics.new(group: group)
+ epics = seeder.seed(
+ backfill_weeks: args.backfill_weeks.to_i,
+ average_issues_per_week: args.average_issues_per_week.to_i
+ )
+ puts "\n#{epics} epics created!"
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/snippets.rake b/lib/tasks/gitlab/snippets.rake
index b55f82480e1..d7f71468102 100644
--- a/lib/tasks/gitlab/snippets.rake
+++ b/lib/tasks/gitlab/snippets.rake
@@ -60,7 +60,7 @@ namespace :gitlab do
end
def migration_running?
- Sidekiq::ScheduledSet.new.any? { |r| r.klass == 'BackgroundMigrationWorker' && r.args[0] == 'BackfillSnippetRepositories' }
+ Sidekiq::ScheduledSet.new.any? { |r| r.klass == 'BackgroundMigrationWorker' && r.args[0] == 'BackfillSnippetRepositories' } # rubocop:disable Cop/SidekiqApiUsage
end
# @example
diff --git a/lib/tasks/gitlab/tw/codeowners.rake b/lib/tasks/gitlab/tw/codeowners.rake
index 148801254bf..fd9c7114979 100644
--- a/lib/tasks/gitlab/tw/codeowners.rake
+++ b/lib/tasks/gitlab/tw/codeowners.rake
@@ -7,10 +7,10 @@ namespace :tw do
task :codeowners do
CodeOwnerRule = Struct.new(:category, :writer)
DocumentOwnerMapping = Struct.new(:path, :writer) do
- def writer_owns_all_pages?(mappings)
- mappings
- .select { |mapping| mapping.directory == directory }
- .all? { |mapping| mapping.writer == writer }
+ def writer_owns_directory?(mappings)
+ dir_mappings = mappings.select { |mapping| mapping.directory == directory }
+
+ dir_mappings.count { |mapping| mapping.writer == writer } / dir_mappings.length.to_f > 0.5
end
def directory
@@ -22,13 +22,12 @@ namespace :tw do
CodeOwnerRule.new('Activation', '@phillipwells'),
CodeOwnerRule.new('Acquisition', '@phillipwells'),
CodeOwnerRule.new('Anti-Abuse', '@phillipwells'),
- CodeOwnerRule.new('Authentication and Authorization', '@eread'),
+ CodeOwnerRule.new('Authentication and Authorization', '@jglassman1'),
CodeOwnerRule.new('Certify', '@msedlakjakubowski'),
CodeOwnerRule.new('Code Review', '@aqualls'),
CodeOwnerRule.new('Compliance', '@eread'),
CodeOwnerRule.new('Composition Analysis', '@rdickenson'),
CodeOwnerRule.new('Configure', '@phillipwells'),
- CodeOwnerRule.new('Container Security', '@claytoncornell'),
CodeOwnerRule.new('Contributor Experience', '@eread'),
CodeOwnerRule.new('Conversion', '@kpaizee'),
CodeOwnerRule.new('Database', '@aqualls'),
@@ -39,7 +38,7 @@ namespace :tw do
CodeOwnerRule.new('Documentation Guidelines', '@sselhorn'),
CodeOwnerRule.new('Dynamic Analysis', '@rdickenson'),
CodeOwnerRule.new('Ecosystem', '@kpaizee'),
- CodeOwnerRule.new('Editor', '@aqualls'),
+ CodeOwnerRule.new('Editor', '@ashrafkhamis'),
CodeOwnerRule.new('Foundations', '@rdickenson'),
CodeOwnerRule.new('Fuzz Testing', '@rdickenson'),
CodeOwnerRule.new('Geo', '@axil'),
@@ -58,6 +57,7 @@ namespace :tw do
CodeOwnerRule.new('Pipeline Execution', '@marcel.amirault'),
CodeOwnerRule.new('Pipeline Insights', '@marcel.amirault'),
CodeOwnerRule.new('Portfolio Management', '@msedlakjakubowski'),
+ CodeOwnerRule.new('Product Analytics', '@lciutacu'),
CodeOwnerRule.new('Product Intelligence', '@claytoncornell'),
CodeOwnerRule.new('Product Planning', '@msedlakjakubowski'),
CodeOwnerRule.new('Project Management', '@msedlakjakubowski'),
@@ -68,6 +68,7 @@ namespace :tw do
CodeOwnerRule.new('Respond', '@msedlakjakubowski'),
CodeOwnerRule.new('Runner', '@sselhorn'),
CodeOwnerRule.new('Pods', '@sselhorn'),
+ CodeOwnerRule.new('Security Policies', '@claytoncornell'),
CodeOwnerRule.new('Source Code', '@aqualls'),
CodeOwnerRule.new('Static Analysis', '@rdickenson'),
CodeOwnerRule.new('Style Guide', '@sselhorn'),
@@ -114,14 +115,14 @@ namespace :tw do
deduplicated_mappings = Set.new
mappings.each do |mapping|
- if mapping.writer_owns_all_pages?(mappings)
+ if mapping.writer_owns_directory?(mappings)
deduplicated_mappings.add("#{mapping.directory}/ #{mapping.writer}")
else
deduplicated_mappings.add("#{mapping.path} #{mapping.writer}")
end
end
- deduplicated_mappings.each { |mapping| puts mapping }
+ deduplicated_mappings.sort.each { |mapping| puts mapping }
if errors.present?
puts "-----"
diff --git a/lib/tasks/gitlab/usage_data.rake b/lib/tasks/gitlab/usage_data.rake
index 73a79427da3..159b70cd673 100644
--- a/lib/tasks/gitlab/usage_data.rake
+++ b/lib/tasks/gitlab/usage_data.rake
@@ -43,17 +43,10 @@ namespace :gitlab do
# Do not edit it manually!
BANNER
- repository_includes = ci_template_includes_hash(:repository_source)
- auto_devops_jobs_includes = ci_template_includes_hash(:auto_devops_source, 'Jobs')
- auto_devops_security_includes = ci_template_includes_hash(:auto_devops_source, 'Security')
- all_includes = [
- *repository_includes,
- ci_template_event('p_ci_templates_implicit_auto_devops'),
- *auto_devops_jobs_includes,
- *auto_devops_security_includes
- ]
-
- File.write(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH, banner + YAML.dump(all_includes).gsub(/ *$/m, ''))
+ all_includes = explicit_template_includes + implicit_auto_devops_includes
+ yaml = banner + YAML.dump(all_includes).gsub(/ *$/m, '')
+
+ File.write(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH, yaml)
end
desc 'GitLab | UsageDataMetrics | Generate raw SQL metrics queries for RSpec'
@@ -65,16 +58,27 @@ namespace :gitlab do
end
FileUtils.mkdir_p(path)
- FileUtils.chdir(path)
- File.write('sql_metrics_queries.json', Gitlab::Json.pretty_generate(queries))
+ File.write(File.join(path, 'sql_metrics_queries.json'), Gitlab::Json.pretty_generate(queries))
+ end
+
+ # Events for templates included via YAML-less Auto-DevOps
+ def implicit_auto_devops_includes
+ Gitlab::UsageDataCounters::CiTemplateUniqueCounter
+ .all_included_templates('Auto-DevOps.gitlab-ci.yml')
+ .map { |template| implicit_auto_devops_event(template) }
+ .uniq
+ .sort_by { _1['name'] }
end
- def ci_template_includes_hash(source, template_directory = nil)
- Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_templates("lib/gitlab/ci/templates/#{template_directory}").map do |template|
- expanded_template_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.expand_template_name("#{template_directory}/#{template}")
- event_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_template_event_name(expanded_template_name, source)
+ # Events for templates included in a .gitlab-ci.yml using include:template
+ def explicit_template_includes
+ Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_templates("lib/gitlab/ci/templates/").each_with_object([]) do |template, result|
+ expanded_template_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.expand_template_name(template)
+ next unless expanded_template_name # guard against templates unavailable on FOSS
- ci_template_event(event_name)
+ event_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_template_event_name(expanded_template_name, :repository_source)
+
+ result << ci_template_event(event_name)
end
end
@@ -86,5 +90,10 @@ namespace :gitlab do
'aggregation' => 'weekly'
}
end
+
+ def implicit_auto_devops_event(expanded_template_name)
+ event_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_template_event_name(expanded_template_name, :auto_devops_source)
+ ci_template_event(event_name)
+ end
end
end
diff --git a/lib/version_check.rb b/lib/version_check.rb
index 2d132001f54..35014f3ddf0 100644
--- a/lib/version_check.rb
+++ b/lib/version_check.rb
@@ -5,6 +5,36 @@ require "base64"
class VersionCheck
include ReactiveCaching
+ ## Version Check Reactive Caching
+ ## This cache stores the external API response from https://version.gitlab.com
+ ##
+ ## Example API Response
+ ## {
+ ## "latest_version": "15.2.2",
+ ## "severity": "success"
+ ## }
+ ##
+ ## This response from this endpoint only changes in 2 scenarios:
+ ## 1. Customer upgrades their GitLab Instance
+ ## 2. GitLab releases a new version
+ ##
+ ## We use GitLab::VERSION as the identifier for the cached information.
+ ## This means if the user upgrades their version we will create a new cache record.
+ ## The old one will be invalidated and cleaned up at the end of the self.reactive_cache_lifetime.
+ ##
+ ## - self.reactive_cache_refresh_interval = 12.hours
+ ## We want to prevent as many external API calls as possible to save on resources.
+ ## Since an EXISTING cache record will only become "invalid" if GitLab releases a new version we
+ ## determined that 12 hour intervals is enough of a window to capture an available upgrade.
+ ##
+ ## - self.reactive_cache_lifetime = 7.days
+ ## We don't want the data to be missing every time a user revisits a page using this info.
+ ## Thus 7 days seems like a fair amount of time before we erase the cache.
+ ## This also will handle cleaning up old cache records as they will no longer be accessed after an upgrade.
+ ##
+
+ self.reactive_cache_refresh_interval = 12.hours
+ self.reactive_cache_lifetime = 7.days
self.reactive_cache_work_type = :external_dependency
self.reactive_cache_worker_finder = ->(_id, *args) { from_cache }
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 3b28edfd3e2..bd2cf29a94d 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 1fa3ac2174f..8801f84e816 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -190,6 +190,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1396,15 +1405,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1465,6 +1465,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1504,9 +1513,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1540,6 +1546,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1561,10 +1570,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as draft"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1588,6 +1600,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -2185,9 +2203,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -2206,6 +2221,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2887,12 +2911,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3286,9 +3304,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3301,6 +3325,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3322,6 +3349,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3358,6 +3388,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3409,9 +3442,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3598,6 +3643,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3937,9 +3985,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4366,6 +4426,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4441,6 +4504,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4729,9 +4795,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4981,6 +5044,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -5212,6 +5278,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5887,6 +5956,9 @@ msgstr[5] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6562,6 +6634,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6883,7 +6958,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6925,6 +7000,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -7255,6 +7333,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -7291,33 +7372,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7327,6 +7453,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7627,6 +7765,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7804,6 +7945,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7813,7 +7957,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -8074,7 +8218,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -8269,6 +8413,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -9295,6 +9442,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9394,6 +9544,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9424,6 +9577,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9433,6 +9589,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9499,6 +9658,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -10171,6 +10333,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -10276,6 +10441,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10345,7 +10513,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10663,6 +10831,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -11131,13 +11302,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11461,6 +11632,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11677,6 +11851,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11689,6 +11866,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12952,6 +13135,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -13138,6 +13327,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -13282,6 +13474,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13645,6 +13840,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13690,6 +13888,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13711,6 +13912,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13726,6 +13930,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13915,18 +14125,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13999,25 +14200,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -14038,7 +14236,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -14059,12 +14257,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14623,6 +14815,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14989,6 +15193,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -15127,9 +15334,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -15247,6 +15451,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15595,6 +15802,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15628,6 +15838,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15652,6 +15865,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16762,9 +16978,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17452,6 +17665,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17581,9 +17797,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17593,6 +17815,33 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17866,6 +18115,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -18205,6 +18457,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18427,9 +18682,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -19294,6 +19546,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -19330,6 +19585,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19546,7 +19804,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19891,6 +20149,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19909,6 +20173,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19930,7 +20197,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19984,6 +20251,9 @@ msgstr[5] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -20029,7 +20299,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20470,24 +20740,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20527,16 +20818,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20548,6 +20845,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20557,10 +20860,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20641,6 +20947,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20650,6 +20962,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20839,6 +21154,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20863,6 +21181,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21772,6 +22093,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21997,6 +22321,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -22057,12 +22384,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -22075,6 +22408,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -22267,9 +22603,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22666,6 +22999,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22765,6 +23104,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -23137,9 +23479,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23995,6 +24334,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -24076,7 +24418,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24889,6 +25231,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24940,10 +25285,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -25027,9 +25372,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -25039,9 +25399,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -25054,7 +25411,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -25291,6 +25648,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26437,6 +26797,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26461,6 +26824,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26725,6 +27091,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26947,6 +27316,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27451,6 +27823,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27754,33 +28129,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27802,12 +28210,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27826,6 +28252,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27850,6 +28279,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27859,15 +28294,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27880,12 +28351,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27946,6 +28438,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -28111,6 +28606,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28675,6 +29173,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28921,15 +29422,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28996,6 +29497,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -29029,13 +29533,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -29053,6 +29557,9 @@ msgstr[5] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -29104,10 +29611,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -29164,7 +29671,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -29383,9 +29890,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29788,9 +30292,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29800,15 +30316,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29923,6 +30451,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30604,6 +31138,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30613,6 +31150,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30673,6 +31213,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30784,6 +31327,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30997,15 +31543,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -31018,9 +31558,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -31036,9 +31573,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -31051,6 +31585,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -31288,9 +31825,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -31336,9 +31870,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31828,6 +32359,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31858,6 +32392,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31981,12 +32518,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -32023,6 +32566,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -32176,7 +32722,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -32266,6 +32812,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32788,6 +33337,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32824,6 +33376,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32848,6 +33403,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -33004,6 +33562,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -33073,18 +33634,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -33235,9 +33826,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -33397,9 +33985,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -34315,6 +34900,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34717,6 +35305,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34738,6 +35329,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34978,6 +35572,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -35011,9 +35608,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -35023,6 +35617,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -35095,6 +35692,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -35122,7 +35722,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -35173,6 +35776,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -35185,6 +35791,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -35215,6 +35824,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -35257,6 +35869,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35476,9 +36091,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35626,6 +36238,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35713,6 +36328,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -36061,13 +36679,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -36124,9 +36742,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36529,6 +37144,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36541,6 +37159,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36571,12 +37192,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36694,6 +37321,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36817,9 +37447,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36865,9 +37492,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36889,9 +37513,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36937,6 +37567,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -37249,6 +37882,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -37324,18 +37960,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -37348,6 +37981,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37957,6 +38593,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -38023,6 +38692,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -38263,6 +38935,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -38305,6 +38980,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -38365,6 +39043,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -39265,7 +39946,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -39289,9 +39970,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -39328,7 +40021,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -39337,7 +40036,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -39457,25 +40156,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40702,6 +41413,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40909,9 +41623,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -41179,9 +41890,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -41245,6 +41953,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -41290,6 +42001,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -41338,6 +42052,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -41434,6 +42169,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41650,6 +42388,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41662,12 +42403,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41755,6 +42502,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -42106,6 +42856,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -42139,6 +42892,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -42358,9 +43114,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -42382,9 +43135,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -42496,6 +43246,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42625,9 +43378,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42643,6 +43393,15 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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 ""
@@ -43324,6 +44083,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -43366,10 +44128,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -43444,9 +44206,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -43480,7 +44239,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43825,6 +44584,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -44146,9 +44908,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -44167,7 +44926,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -44428,6 +45214,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -44455,7 +45244,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44887,6 +45676,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44908,10 +45700,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44923,6 +45715,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44950,6 +45745,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44962,6 +45760,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44974,6 +45775,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -45037,6 +45841,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -45247,6 +46057,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -45262,12 +46075,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -45292,6 +46111,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -45316,6 +46141,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -45502,12 +46330,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45742,6 +46564,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45778,9 +46606,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45847,6 +46681,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -46117,6 +46954,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -46240,6 +47083,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -46444,7 +47290,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -46462,7 +47308,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -47065,6 +47911,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -47167,6 +48016,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -47212,6 +48064,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -47488,6 +48343,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47653,6 +48511,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47698,6 +48559,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -48043,9 +48907,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -48136,6 +48997,15 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "load it anyway"
msgstr ""
@@ -48181,6 +49051,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -48556,6 +49429,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48637,9 +49513,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48799,6 +49672,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48835,6 +49711,15 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48943,6 +49828,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -49009,6 +49897,15 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index e9768c881e3..49882c2db1a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 90da7dcc69b..d5eb7b9dc6c 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 51525dcc90b..10746716218 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28750,15 +29261,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 5463671b026..72f6db364e4 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr "Сътрудници"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон за интервала"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr "Ðов план за Ñхема"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Ðктивно"
msgid "PipelineSchedules|All"
msgstr "Ð’Ñички"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Ðеактивно"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Следващо изпълнение"
@@ -28960,15 +29472,27 @@ msgstr "Ðищо"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Въведете кратко опиÑание за тази Ñхема"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Поемане на ÑобÑтвеноÑтта"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Цел"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Променливи"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Прочетете повече"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Изберете формата на архива"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Изберете чаÑова зона"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 56037de2b5e..6029606ab6a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 97d2549fdfd..56580402a80 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index d31db85434b..6fa207a2359 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -177,6 +177,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1303,14 +1311,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1365,6 +1365,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1402,9 +1410,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1438,6 +1443,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1459,10 +1467,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as draft"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1486,6 +1497,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -2055,9 +2072,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -2076,6 +2090,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2757,12 +2780,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3156,9 +3173,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3171,6 +3194,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3192,6 +3218,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3228,6 +3257,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3279,9 +3311,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3468,6 +3512,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3807,9 +3854,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4236,6 +4295,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4311,6 +4373,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4599,9 +4664,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4850,6 +4912,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -5079,6 +5144,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5746,6 +5814,9 @@ msgstr[4] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6420,6 +6491,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6741,7 +6815,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6782,6 +6856,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -7109,6 +7186,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -7145,33 +7225,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7181,6 +7306,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7481,6 +7618,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7657,6 +7797,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7666,7 +7809,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7927,7 +8070,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -8122,6 +8265,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -9145,6 +9291,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9244,6 +9393,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9273,6 +9425,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9282,6 +9437,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9348,6 +9506,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -10019,6 +10180,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -10124,6 +10288,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10193,7 +10360,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10511,6 +10678,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10976,13 +11146,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11306,6 +11476,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11522,6 +11695,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11534,6 +11710,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12795,6 +12977,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12981,6 +13169,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -13125,6 +13316,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13482,6 +13676,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13527,6 +13724,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13548,6 +13748,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13563,6 +13766,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13751,18 +13960,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13834,25 +14034,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13873,7 +14070,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13894,12 +14091,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14454,6 +14645,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14820,6 +15023,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14958,9 +15164,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -15078,6 +15281,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15426,6 +15632,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15459,6 +15668,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15483,6 +15695,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16590,9 +16805,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17279,6 +17491,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17408,9 +17623,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17419,6 +17640,33 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17689,6 +17937,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -18028,6 +18279,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18250,9 +18504,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -19117,6 +19368,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -19153,6 +19407,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19369,7 +19626,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19714,6 +19971,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19732,6 +19995,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19753,7 +20019,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19805,6 +20071,9 @@ msgstr[4] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19850,7 +20119,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20289,24 +20558,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20346,16 +20636,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20367,6 +20663,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20376,10 +20678,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20460,6 +20765,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20469,6 +20780,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20656,6 +20970,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20680,6 +20997,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21588,6 +21908,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21812,6 +22135,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21872,12 +22198,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21890,6 +22222,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -22082,9 +22417,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22480,6 +22812,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22579,6 +22917,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22951,9 +23292,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23807,6 +24145,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23888,7 +24229,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24695,6 +25036,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24746,10 +25090,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24833,9 +25177,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24845,9 +25204,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24860,7 +25216,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -25097,6 +25453,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26239,6 +26598,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26263,6 +26625,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26527,6 +26892,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26747,6 +27115,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27250,6 +27621,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27549,33 +27923,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27597,12 +28004,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27621,6 +28046,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27645,6 +28073,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27654,15 +28088,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27675,12 +28145,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27741,6 +28232,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27905,6 +28399,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28468,6 +28965,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28713,15 +29213,15 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28788,6 +29288,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28821,13 +29324,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28844,6 +29347,9 @@ msgstr[4] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28895,10 +29401,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28955,7 +29461,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -29173,9 +29679,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29578,9 +30081,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29590,15 +30105,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29713,6 +30240,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30394,6 +30927,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30403,6 +30939,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30463,6 +31002,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30574,6 +31116,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30787,15 +31332,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30808,9 +31347,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30826,9 +31362,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30841,6 +31374,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -31078,9 +31614,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -31126,9 +31659,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31618,6 +32148,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31648,6 +32181,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31771,12 +32307,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31813,6 +32355,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31966,7 +32511,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -32056,6 +32601,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32578,6 +33126,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32614,6 +33165,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32638,6 +33192,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32794,6 +33351,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32863,18 +33423,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -33025,9 +33615,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -33186,9 +33773,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -34096,6 +34680,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34494,6 +35081,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34515,6 +35105,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34751,6 +35344,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34784,9 +35380,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34796,6 +35389,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34867,6 +35463,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34894,7 +35493,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34945,6 +35547,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34957,6 +35562,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34987,6 +35595,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -35028,6 +35639,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35247,9 +35861,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35397,6 +36008,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35484,6 +36098,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35821,13 +36438,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35884,9 +36501,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36289,6 +36903,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36301,6 +36918,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36331,12 +36951,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36454,6 +37080,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36577,9 +37206,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36625,9 +37251,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36649,9 +37272,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36697,6 +37326,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -37009,6 +37641,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -37084,18 +37719,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -37108,6 +37740,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37715,6 +38350,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37781,6 +38449,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -38021,6 +38692,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -38063,6 +38737,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -38123,6 +38800,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -39023,7 +39703,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -39047,9 +39727,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -39086,7 +39778,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -39095,7 +39793,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -39214,25 +39912,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40450,6 +41160,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40657,9 +41370,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40927,9 +41637,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40993,6 +41700,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -41038,6 +41748,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -41086,6 +41799,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -41182,6 +41916,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41398,6 +42135,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41410,12 +42150,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41503,6 +42249,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41852,6 +42601,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41885,6 +42637,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -42104,9 +42859,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -42128,9 +42880,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -42242,6 +42991,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42371,9 +43123,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42389,6 +43138,14 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
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 ""
@@ -43070,6 +43827,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -43112,10 +43872,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -43190,9 +43950,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -43226,7 +43983,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43570,6 +44327,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43891,9 +44651,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43912,7 +44669,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -44173,6 +44957,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -44199,7 +44986,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44629,6 +45416,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44650,10 +45440,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44665,6 +45455,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44692,6 +45485,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44704,6 +45500,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44716,6 +45515,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44779,6 +45581,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44989,6 +45797,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -45004,12 +45815,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -45034,6 +45851,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -45058,6 +45881,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -45242,12 +46068,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45482,6 +46302,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45517,9 +46343,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45586,6 +46418,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45854,6 +46689,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45977,6 +46818,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -46180,7 +47024,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -46198,7 +47042,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46797,6 +47641,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46897,6 +47744,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46942,6 +47792,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -47214,6 +48067,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47377,6 +48233,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47422,6 +48281,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47761,9 +48623,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47854,6 +48713,14 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "load it anyway"
msgstr ""
@@ -47897,6 +48764,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -48270,6 +49140,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48351,9 +49224,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48509,6 +49379,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48544,6 +49417,14 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48652,6 +49533,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48718,6 +49602,14 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index b20cd8353be..337041e880f 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -151,6 +151,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d odobravatelj"
@@ -1117,12 +1123,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1165,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1198,9 +1204,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1234,6 +1237,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1255,10 +1261,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1282,6 +1291,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1795,9 +1810,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1816,6 +1828,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2497,12 +2518,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2896,9 +2911,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2911,6 +2932,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2932,6 +2956,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2968,6 +2995,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3019,9 +3049,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3208,6 +3250,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3547,9 +3592,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3976,6 +4033,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Svi projekti"
@@ -4051,6 +4111,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4339,9 +4402,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4588,6 +4648,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4813,6 +4876,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5464,6 +5530,9 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6136,6 +6205,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6457,7 +6529,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6496,6 +6568,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6817,6 +6892,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6853,33 +6931,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6889,6 +7012,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7189,6 +7324,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7363,6 +7501,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7372,7 +7513,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7633,7 +7774,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7828,6 +7969,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8845,6 +8989,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8944,6 +9091,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8971,6 +9121,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8980,6 +9133,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9046,6 +9202,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9715,6 +9874,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9820,6 +9982,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9889,7 +10054,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10207,6 +10372,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10666,13 +10834,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10996,6 +11164,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11212,6 +11383,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11224,6 +11398,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12481,6 +12661,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Dan u mjesecu"
@@ -12667,6 +12853,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12811,6 +13000,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13156,6 +13348,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13201,6 +13396,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13222,6 +13420,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13237,6 +13438,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13423,18 +13630,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13504,25 +13702,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13543,7 +13738,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13564,12 +13759,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14116,6 +14305,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14482,6 +14683,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14620,9 +14824,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14740,6 +14941,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15088,6 +15292,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15121,6 +15328,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15145,6 +15355,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16246,9 +16459,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16933,6 +17143,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17062,15 +17275,48 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17335,6 +17581,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17674,6 +17923,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17896,9 +18148,6 @@ msgstr "GitLab Zadatak"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18763,6 +19012,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18799,6 +19051,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19015,7 +19270,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19360,6 +19615,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19378,6 +19639,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19399,7 +19663,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19447,6 +19711,9 @@ msgstr[2] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19492,7 +19759,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19927,24 +20194,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19984,16 +20272,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20005,6 +20299,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20014,10 +20314,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20098,6 +20401,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20107,6 +20416,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20290,6 +20602,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20314,6 +20629,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21220,6 +21538,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21442,6 +21763,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21502,12 +21826,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21520,6 +21850,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21712,9 +22045,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22108,6 +22438,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22207,6 +22543,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22579,9 +22918,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23431,6 +23767,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23512,7 +23851,7 @@ msgstr ""
msgid "Learn more"
msgstr "Saznaj više"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24307,6 +24646,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr "OznaÄi zadatak kao povjerljiv."
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24358,10 +24700,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24445,9 +24787,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24457,9 +24814,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24472,7 +24826,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24709,6 +25063,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25843,6 +26200,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25867,6 +26227,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26131,6 +26494,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26347,6 +26713,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26848,6 +27217,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27139,33 +27511,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27187,12 +27592,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27211,6 +27634,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27235,6 +27661,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27244,15 +27676,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27265,12 +27733,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27331,6 +27820,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27493,6 +27985,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28054,6 +28549,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28297,15 +28795,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28372,6 +28870,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28405,13 +28906,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28426,6 +28927,9 @@ msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28477,10 +28981,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28537,7 +29041,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28753,9 +29257,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29158,9 +29659,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29170,15 +29683,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29293,6 +29818,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29974,6 +30505,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29983,6 +30517,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30043,6 +30580,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30154,6 +30694,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30367,15 +30910,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30388,9 +30925,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30406,9 +30940,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30421,6 +30952,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30658,9 +31192,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30706,9 +31237,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31198,6 +31726,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31228,6 +31759,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31351,12 +31885,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31393,6 +31933,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31546,7 +32089,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31636,6 +32179,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32158,6 +32704,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32194,6 +32743,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32218,6 +32770,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32374,6 +32929,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32443,18 +33001,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32605,9 +33193,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32764,9 +33349,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33658,6 +34240,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34048,6 +34633,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34069,6 +34657,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34297,6 +34888,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34330,9 +34924,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34342,6 +34933,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34411,6 +35005,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34438,7 +35035,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34489,6 +35089,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34501,6 +35104,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34531,6 +35137,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34570,6 +35179,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34789,9 +35401,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34939,6 +35548,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35026,6 +35638,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35341,13 +35956,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35404,9 +36019,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35809,6 +36421,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35821,6 +36436,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35851,12 +36469,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35974,6 +36598,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36097,9 +36724,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36145,9 +36769,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36169,9 +36790,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36217,6 +36844,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36529,6 +37159,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36604,18 +37237,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36628,6 +37258,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37231,6 +37864,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37297,6 +37963,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37537,6 +38206,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37579,6 +38251,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37639,6 +38314,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38539,7 +39217,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38563,9 +39241,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38602,7 +39292,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38611,7 +39307,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38728,25 +39424,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39946,6 +40654,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40153,9 +40864,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40423,9 +41131,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40489,6 +41194,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40534,6 +41242,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40582,6 +41293,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40678,6 +41410,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40894,6 +41629,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40906,12 +41644,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40999,6 +41743,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41344,6 +42091,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41377,6 +42127,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41596,9 +42349,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41620,9 +42370,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41734,6 +42481,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41863,9 +42613,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41881,6 +42628,12 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
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 ""
@@ -42562,6 +43315,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42604,10 +43360,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42682,9 +43438,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42718,7 +43471,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43060,6 +43813,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43381,9 +44137,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43402,7 +44155,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43663,6 +44443,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43687,7 +44470,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44113,6 +44896,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44134,10 +44920,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44149,6 +44935,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44176,6 +44965,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44188,6 +44980,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44200,6 +44995,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44263,6 +45061,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44473,6 +45277,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44488,12 +45295,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44518,6 +45331,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44542,6 +45361,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44722,12 +45544,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44962,6 +45778,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44995,9 +45817,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45064,6 +45892,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45328,6 +46159,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45451,6 +46288,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45652,7 +46492,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45670,7 +46510,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46261,6 +47101,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46357,6 +47200,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46402,6 +47248,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46666,6 +47515,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46825,6 +47677,9 @@ msgstr ""
msgid "comment"
msgstr "komentar"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46870,6 +47725,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47197,9 +48055,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47290,6 +48145,12 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "load it anyway"
msgstr ""
@@ -47329,6 +48190,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47698,6 +48562,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47779,9 +48646,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47929,6 +48793,9 @@ msgstr "ukloni težinu"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47962,6 +48829,12 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48070,6 +48943,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48136,6 +49012,12 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 17a3c3c8096..35d5f017595 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprovador"
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr "Afegeix usuaris al grup:"
-
-msgid "Add users to group"
-msgstr "Afegeix usuaris al grup"
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr "Analítiques"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Tasques"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr "Registre de contenidors"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr "Domini"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Mostra-ho tot"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fallit"
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr "Identitats"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Nom:"
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index fe142536833..8de7929c3e9 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1210,13 +1217,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} je k dispozici"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1925,9 +1941,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 65c2c634404..44983b73f0a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -190,6 +190,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1396,15 +1405,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1465,6 +1465,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1504,9 +1513,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1540,6 +1546,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1561,10 +1570,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as draft"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1588,6 +1600,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -2185,9 +2203,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -2206,6 +2221,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2887,12 +2911,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3286,9 +3304,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3301,6 +3325,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3322,6 +3349,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3358,6 +3388,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3409,9 +3442,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3598,6 +3643,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3937,9 +3985,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4366,6 +4426,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4441,6 +4504,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4729,9 +4795,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4981,6 +5044,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -5212,6 +5278,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5887,6 +5956,9 @@ msgstr[5] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6562,6 +6634,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6883,7 +6958,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6925,6 +7000,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -7255,6 +7333,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -7291,33 +7372,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7327,6 +7453,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7627,6 +7765,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7804,6 +7945,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7813,7 +7957,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -8074,7 +8218,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -8269,6 +8413,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -9295,6 +9442,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9394,6 +9544,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9424,6 +9577,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9433,6 +9589,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9499,6 +9658,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -10171,6 +10333,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -10276,6 +10441,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10345,7 +10513,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10663,6 +10831,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -11131,13 +11302,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11461,6 +11632,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11677,6 +11851,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11689,6 +11866,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12952,6 +13135,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -13138,6 +13327,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -13282,6 +13474,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13645,6 +13840,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13690,6 +13888,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13711,6 +13912,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13726,6 +13930,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13915,18 +14125,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13999,25 +14200,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -14038,7 +14236,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -14059,12 +14257,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14623,6 +14815,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14989,6 +15193,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -15127,9 +15334,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -15247,6 +15451,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15595,6 +15802,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15628,6 +15838,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15652,6 +15865,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16762,9 +16978,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17452,6 +17665,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17581,9 +17797,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17593,6 +17815,33 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17866,6 +18115,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -18205,6 +18457,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18427,9 +18682,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -19294,6 +19546,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -19330,6 +19585,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19546,7 +19804,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19891,6 +20149,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19909,6 +20173,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19930,7 +20197,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19984,6 +20251,9 @@ msgstr[5] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -20029,7 +20299,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20470,24 +20740,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20527,16 +20818,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20548,6 +20845,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20557,10 +20860,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20641,6 +20947,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20650,6 +20962,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20839,6 +21154,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20863,6 +21181,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21772,6 +22093,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21997,6 +22321,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -22057,12 +22384,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -22075,6 +22408,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -22267,9 +22603,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22666,6 +22999,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22765,6 +23104,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -23137,9 +23479,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23995,6 +24334,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -24076,7 +24418,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24889,6 +25231,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24940,10 +25285,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -25027,9 +25372,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -25039,9 +25399,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -25054,7 +25411,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -25291,6 +25648,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26437,6 +26797,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26461,6 +26824,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26725,6 +27091,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26947,6 +27316,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27451,6 +27823,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27754,33 +28129,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27802,12 +28210,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27826,6 +28252,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27850,6 +28279,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27859,15 +28294,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27880,12 +28351,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27946,6 +28438,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -28111,6 +28606,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28675,6 +29173,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28921,15 +29422,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28996,6 +29497,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -29029,13 +29533,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -29053,6 +29557,9 @@ msgstr[5] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -29104,10 +29611,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -29164,7 +29671,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -29383,9 +29890,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29788,9 +30292,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29800,15 +30316,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29923,6 +30451,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30604,6 +31138,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30613,6 +31150,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30673,6 +31213,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30784,6 +31327,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30997,15 +31543,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -31018,9 +31558,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -31036,9 +31573,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -31051,6 +31585,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -31288,9 +31825,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -31336,9 +31870,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31828,6 +32359,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31858,6 +32392,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31981,12 +32518,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -32023,6 +32566,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -32176,7 +32722,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -32266,6 +32812,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32788,6 +33337,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32824,6 +33376,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32848,6 +33403,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -33004,6 +33562,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -33073,18 +33634,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -33235,9 +33826,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -33397,9 +33985,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -34315,6 +34900,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34717,6 +35305,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34738,6 +35329,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34978,6 +35572,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -35011,9 +35608,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -35023,6 +35617,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -35095,6 +35692,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -35122,7 +35722,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -35173,6 +35776,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -35185,6 +35791,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -35215,6 +35824,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -35257,6 +35869,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35476,9 +36091,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35626,6 +36238,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35713,6 +36328,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -36061,13 +36679,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -36124,9 +36742,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36529,6 +37144,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36541,6 +37159,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36571,12 +37192,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36694,6 +37321,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36817,9 +37447,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36865,9 +37492,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36889,9 +37513,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36937,6 +37567,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -37249,6 +37882,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -37324,18 +37960,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -37348,6 +37981,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37957,6 +38593,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -38023,6 +38692,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -38263,6 +38935,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -38305,6 +38980,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -38365,6 +39043,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -39265,7 +39946,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -39289,9 +39970,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -39328,7 +40021,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -39337,7 +40036,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -39457,25 +40156,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40702,6 +41413,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40909,9 +41623,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -41179,9 +41890,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -41245,6 +41953,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -41290,6 +42001,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -41338,6 +42052,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -41434,6 +42169,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41650,6 +42388,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41662,12 +42403,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41755,6 +42502,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -42106,6 +42856,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -42139,6 +42892,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -42358,9 +43114,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -42382,9 +43135,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -42496,6 +43246,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42625,9 +43378,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42643,6 +43393,15 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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 ""
@@ -43324,6 +44083,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -43366,10 +44128,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -43444,9 +44206,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -43480,7 +44239,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43825,6 +44584,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -44146,9 +44908,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -44167,7 +44926,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -44428,6 +45214,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -44455,7 +45244,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44887,6 +45676,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44908,10 +45700,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44923,6 +45715,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44950,6 +45745,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44962,6 +45760,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44974,6 +45775,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -45037,6 +45841,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -45247,6 +46057,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -45262,12 +46075,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -45292,6 +46111,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -45316,6 +46141,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -45502,12 +46330,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45742,6 +46564,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45778,9 +46606,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45847,6 +46681,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -46117,6 +46954,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -46240,6 +47083,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -46444,7 +47290,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -46462,7 +47308,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -47065,6 +47911,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -47167,6 +48016,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -47212,6 +48064,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -47488,6 +48343,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47653,6 +48511,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47698,6 +48559,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -48043,9 +48907,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -48136,6 +48997,15 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "load it anyway"
msgstr ""
@@ -48181,6 +49051,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -48556,6 +49429,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48637,9 +49513,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48799,6 +49672,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48835,6 +49711,15 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48943,6 +49828,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -49009,6 +49897,15 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index bf4795ccc80..30a8586c79c 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkender"
@@ -1024,11 +1029,6 @@ msgstr "%{spanStart}i%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} til %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
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."
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] "%{strong_start}%{count} medlem%{strong_end} skal godkende for at sammenlægge. Alle med rollen Udvikler eller højere kan godkende."
msgstr[1] "%{strong_start}%{count} medlemmer%{strong_end} skal godkende for at sammenlægge. Alle med rollen Udvikler eller højere kan godkende."
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} er ukendt eller ugyldigt"
msgid "%{text} is available"
msgstr "%{text} er tilgængelig"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} skal enten tilhøre et projekt eller en gruppe."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} understøtter ikke burnupdiagrammer"
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advarsler fundet: viser første %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,12 +1158,15 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "%{user_name}s profilside"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} ændrede udkaststatussen på sammenlægningsanmodningen %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} har spurgt om en GitLab-konto på din instans %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "%{username}s avatar"
@@ -1180,6 +1188,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} brugt tid."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} gør det muligt for dig at sende underretninger til webprogrammer som svar til begivenheder i en gruppe eller et projekt."
@@ -1665,9 +1679,6 @@ msgstr "En ny udgivelse %{tag} for %{name} blev udgivet. Besøg Udgivelser-siden
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "En ny efterligningstoken er blevet oprettet."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Et ren HTML-websted som bruger Netlify til CI/CD frem for GitLab, men stadigvæk med alle de andre gode GitLab-funktioner"
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Tilføj udløser"
-msgid "Add user(s) to the group:"
-msgstr "Tilføj brugere til gruppen:"
-
-msgid "Add users to group"
-msgstr "Tilføj brugere til gruppe"
-
msgid "Add variable"
msgstr "Tilføj variabel"
@@ -2766,9 +2780,15 @@ msgstr "Feedtoken"
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "Jeg har læst og accepteret Let's Encrypts %{link_start}Vilkår for tjeneste%{link_end} (PDF)."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "Beskyt CI-/CD-variabler som standard"
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Blokeret"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Blokering af brugeren har følgende indvirkninger:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr "Alle sammenlægningsanmodningsafhængigheder er blevet sammenlagt"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Alle projekter"
@@ -3921,6 +3980,9 @@ msgstr "Tillad nøglen at bruge push til depotet"
msgid "Allow use of licensed EE features"
msgstr "Tillad brug af licenserede EE-funktioner"
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Tillad brugere at afskedig broadcastmeddelelsen"
@@ -4209,9 +4271,6 @@ msgstr "Der opstod en fejl under indlæsning af et afsnit på siden."
msgid "An error occurred while loading all the files."
msgstr "Der opstod en fejl under indlæsning af alle filerne."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Der opstod en fejl under indlæsning af diagramdata"
@@ -4457,6 +4516,9 @@ msgstr "Der opstod en ukendt fejl."
msgid "Analytics"
msgstr "Analyse"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analyser dine afhængigheder for kendte sårbarheder."
@@ -4680,6 +4742,9 @@ msgstr "Tilmelding aktiveret"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "Vedhæfter %d filer"
msgid "Attaching the file failed."
msgstr "Kunne ikke vedhæfte filen."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Nedenunder finder du alle de grupper, som er offentlige."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr "Direkte medlemskaber"
msgid "Billing|Enter at least three characters to search."
msgstr "Indtast mindst tre tegn for at søge."
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr "Sædedetaljer til/fra"
msgid "Billing|Type %{username} to confirm"
msgstr "Skriv %{username} for at bekræfte"
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr "Bruger blev fjernet"
@@ -6671,6 +6745,9 @@ msgstr "Indlæser epics"
msgid "Bold text"
msgstr "Fed tekst"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr "forventede en tilknyttet gruppe men har et tilknyttet projekt"
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr "forventede et tilknyttet projekt men har en tilknyttet gruppe"
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr "skal være en gruppe"
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr "Udsendelsesstrategi"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Job"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,8 +7626,8 @@ msgstr "Kan ikke forfremme problemstilling fordi de ikke tilhører en gruppe."
msgid "Cannot promote issue due to insufficient permissions."
msgstr "Kan ikke forfremme problemstilling pga. utilstrækkelige tilladelser."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr "Kan ikke referere til en gruppe %{timebox_type} med et internt id!"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr ""
@@ -7681,6 +7821,9 @@ msgstr "Ændrer titlen til \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Ukendt bruger"
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr "Commits til"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "Her vises commits du vælger. Gå til det første faneblad og vælg commits for at tilføje til sammenlægningsanmodningen."
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Der opstod en fejl under hentning af data for sammenlægningsanmodninger."
@@ -9668,6 +9829,9 @@ msgstr "Fuldført"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr "Fuldført"
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr "Kontakter"
msgid "Container Registry"
msgstr "Beholderregister"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Beholderskanning"
@@ -10511,13 +10678,13 @@ msgstr "Bidragsydere"
msgid "Control emails linked to your account"
msgstr "Styr e-mails som er linket til din konto"
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr "Land"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Dækning"
@@ -11057,6 +11227,9 @@ msgstr "Opret emne"
msgid "Create user"
msgstr "Opret bruger"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Opret jokertegn: %{searchTerm}"
@@ -11069,6 +11242,12 @@ msgstr "Opret din gruppe"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "Du har ikke tilladelse til at oprette en undergruppe i gruppen."
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Dag i måneden"
@@ -12510,6 +12695,9 @@ msgstr "Slet konto"
msgid "Delete artifacts"
msgstr "Slet artefakter"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr "Slettet"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Slettede chatkaldenavn: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr "Slettede projekter kan ikke gendannes!"
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "Tillader læse- og skriveadgang til pakkeregisteret."
@@ -13038,6 +13232,9 @@ msgstr "Indtast et brugernavn til din token. Er som standard %{code_start}gitlab
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "Udløber"
@@ -13059,6 +13256,9 @@ msgstr "Tilbagekald %{name}"
msgid "DeployTokens|Scopes"
msgstr "Omfang"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Brugernavn"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr "lykkedes"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,20 +13536,11 @@ msgstr "Arkiverede designs vil stadigvæk være tilgængelige i forrige versione
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr "Er du sikker på, at du vil arkivere de valgte designs?"
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "Er du sikker på, at du vil annullere ændringer til kommentaren?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Er du sikker på, at du vil annullere oprettelse af kommentaren?"
-msgid "DesignManagement|Cancel changes"
-msgstr "Annuller ændringer"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Annuller bekræftelse af kommentar"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "Annuller bekræftelse om opdatering af kommentar"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
@@ -13360,6 +13548,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr ""
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Kunne ikke tilføje en ny kommentar. Prøv venligst igen."
@@ -13378,8 +13572,8 @@ msgstr "Fravælg alle"
msgid "DesignManagement|Designs"
msgstr "Designs"
-msgid "DesignManagement|Discard comment"
-msgstr "Forkast kommentar"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr "Gå til næste design"
msgid "DesignManagement|Go to previous design"
msgstr "GÃ¥ til forrige design"
-msgid "DesignManagement|Keep changes"
-msgstr "Behold ændringer"
-
-msgid "DesignManagement|Keep comment"
-msgstr "Behold kommentar"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr "Domæne"
msgid "Domain Name"
msgstr "Domænenavn"
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Rediger wikiside"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr "og %{moreCount} mere"
msgid "Emails"
msgstr "E-mails"
-msgid "Emails sent from Service Desk have this name."
-msgstr "E-mails som sendes fra serviceskranken har dette navn."
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "Aktivér e-mail-underretning"
@@ -14919,6 +15122,9 @@ msgstr "Udsendelse"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr "Tilbagerul miljø"
msgid "Environments|Rollback environment %{name}?"
msgstr "Tilbagerul miljøet %{name}?"
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Vis alle"
@@ -16074,9 +16286,6 @@ msgstr "Kunne ikke indlæse grene. Prøv venligst igen."
msgid "Failed to load deploy keys."
msgstr "Kunne ikke indlæse udsendelsesnøgler."
-msgid "Failed to load emoji list."
-msgstr "Kunne ikke indlæse emojiliste."
-
msgid "Failed to load error details from Sentry."
msgstr "Kunne ikke indlæse fejldetaljer fra Sentry."
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr "Fandt fejl i din .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr "Framework slettet"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Gratis prøveperiode af GitLab.com Ultimate"
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "Det vil synkronisere alle %{replicableType} igen. Det kan tage noget tid af fuldføre. Er du sikker på, at du vil fortsætte?"
@@ -17719,9 +17970,6 @@ msgstr "GitLab-problemstilling"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -18586,6 +18834,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Indlæser epics"
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr "Ingen start- eller slutdato"
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr "Inden for 3 år"
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr "Overholdelsesframeworks"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "Retningslinje"
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr "Identiteter"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr "Hvis du ikke loggede ind for nyligt, så skal du straks %{password_link_
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "Hvis du ikke loggede ind for nyligt, så skal du straks ændre din adgangskode: %{password_link}."
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "Hvis du for nyligt har logget ind og genkender IP-adressen, så kan du se bort fra e-mailen."
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr "Indeks"
@@ -21257,6 +21577,9 @@ msgstr "Tilføj en integrering"
msgid "Integrations|Add namespace"
msgstr "Tilføj navnerum"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Alle detaljer"
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Aktivér kommentarer"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "Kunne ikke linke navnerum. Prøv venligst igen."
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr "Kunne ikke indlæse navnerum. Prøv venligst igen."
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr "Kunne ikke aflinke navnerum. Prøv venligst igen."
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr "GitLab-administratorere kan opsætte integreringer som alle grupper og projekter nedarver og bruger som standard. Integreringerne gælder alle grupper og projekter som ikke allerede bruger tilpassede indstillinger. Du kan tilsidesætte tilpassede indstillinger for en gruppe eller projekt hvis indstillingerne er nødvendige på det niveau. Lær mere om %{integrations_link_start}håndtering af integrering på instansniveau%{link_end}."
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervalmønster"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr "Bruger licenssæde:"
msgid "Is using seat"
msgstr "Bruger sæde"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr "Kunne ikke indlæse problemstillinger. Prøv venligst igen."
msgid "IssueAnalytics|Issue"
msgstr "Problemstilling"
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr "Milepæl"
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr "Datoer kan ikke overlappe andre eksisterende gennemløb i gennemløbskadencen"
@@ -23243,6 +23578,9 @@ msgstr "Sidste indlogning kl.:"
msgid "Last successful update"
msgstr "Sidste opdatering som lykkedes"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,8 +23662,8 @@ msgstr ""
msgid "Learn more"
msgstr "Lær mere"
-msgid "Learn more about %{username}"
-msgstr "Lær mere om %{username}"
+msgid "Learn more about %{name}"
+msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Lær mere om Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr "Gør problemstilling fortrolig"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,12 +24505,12 @@ msgstr "HÃ¥ndter projekter."
msgid "Manage two-factor authentication"
msgstr "HÃ¥ndter totrinsgodkendelse"
-msgid "Manage your license"
-msgstr "HÃ¥ndter din licens"
-
msgid "Manage your project's triggers"
msgstr "Håndter dit projekts udløsere"
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "HÃ¥ndteret konto"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr "Mærkede problemstillingen som relateret til %{issue_ref}."
msgid "Marked to do as done."
msgstr "Mærkede gøremål som færdig."
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr "Problemstillinger som har fået fjernet deres stjerne (åbne og utildelt
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr "Navnet er allerede taget."
msgid "Name new label"
msgstr "Navngiv ny etiket"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Navn:"
@@ -26147,6 +26512,9 @@ msgstr "Ny pipelineplanlægning"
msgid "New Project"
msgstr "Nyt projekt"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Nyt krav"
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "Antal commits"
@@ -26934,33 +27305,66 @@ msgstr "Underret brugere med e-mail når indlogningsplacering ikke genkendes."
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Okt."
@@ -27287,6 +27778,9 @@ msgstr "Rotationer"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr "Led alertbeskeder direkte til bestemte medlemmer i dit team"
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr "Vælg deltager"
@@ -27847,6 +28341,9 @@ msgstr "GitLab virker måske ikke ordentligt fordi du bruger en forældet webbro
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "Installer venligst en %{browser_link_start}understøttede webbrowser%{browser_link_end} for at få en bedre oplevelse."
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr "Tilsidesat"
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr "Slet pakkefil"
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Slet pakkeversion"
msgid "PackageRegistry|Delete package"
msgstr "Slet pakke"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr "Instansniveau"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Lær at %{noPackagesLinkStart}udgive og dele dine pakker%{noPackagesLinkEnd} med GitLab."
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,11 +28771,11 @@ msgstr "Vis PyPi-kommandoer"
msgid "PackageRegistry|Show Yarn commands"
msgstr "Vis Yarn-kommandoer"
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr "Noget gik galt under sletning af pakkefilen."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr "Noget gik galt under sletning af pakken."
@@ -28328,8 +28831,8 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr "Du er ved at slette %{filename}. Det er en destruktiv handling der kan gøre din pakke ubrugelig. Er du sikker?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "Du er ved at slette %{name}. Handlingen kan ikke gøres om. Er du sikker?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr "Pause"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Aktiv"
msgid "PipelineSchedules|All"
msgstr "Alle"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inaktiv"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Næste kørsel"
@@ -28960,15 +29472,27 @@ msgstr "Ingen"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Angiv en kort beskrivelse til pipelinen"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Tag ejerskab"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "MÃ¥l"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variabler"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Vent venligst et øjeblik. Siden opdateres automatisk når den er klar."
@@ -29773,6 +30306,9 @@ msgstr "Vent venligst mens vi opretter forbindelse til dit depot. Opdater efter
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Vent venligst mens vi importerer depotet for dig. Opdater efter ønske."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "Pods i brug"
@@ -29833,6 +30369,9 @@ msgstr "Præferencer"
msgid "Preferences saved."
msgstr "Præferencer gemt."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Opførsel"
@@ -29944,6 +30483,9 @@ msgstr "Præferencer for tid"
msgid "Preferences|Use relative times"
msgstr "Brug relative tidspunkter"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr "Aktiv"
msgid "Profiles|Add key"
msgstr "Tilføj nøgle"
-msgid "Profiles|Add status emoji"
-msgstr "Tilføj statusemoji"
-
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 ""
-
msgid "Profiles|Avatar cropper"
msgstr "Beskæring af avatar"
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr "Optaget"
-
msgid "Profiles|Change username"
msgstr "Ændr brugernavn"
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "By, land"
-msgid "Profiles|Clear status"
-msgstr "Ryd status"
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Forbundne kontoer"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Nuværende sti: %{path}"
@@ -30448,9 +30981,6 @@ msgstr "Det kan være sjovt at bruge emojier i navne men prøv venligst at indst
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "Hvad er din status?"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Din status"
-
msgid "Profiles|https://website.com"
msgstr "https://website.com"
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "Konfigurer dine projektressourcer og overvåg deres helbred."
@@ -31018,6 +31548,9 @@ msgstr "Aktivér sammenlægningstog"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr "Ingen sammenlægningscommits er oprettet."
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr "Offentlig"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Depot"
@@ -31336,7 +31878,7 @@ msgstr "Når der er en sammenlægningskonflikt, så får brugeren mulighed for a
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Gren"
@@ -31984,6 +32532,9 @@ msgstr "Beskyttet gren (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "Beskyttede grene"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr "Hvad er beskyttede grene?"
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr "Udgiver problemstillingen til den tilknyttede statusside."
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr "Pull-anmodninger fra forgrening understøttes ikke"
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Læs mere"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr "Læs mere om GitLab på %{link_to_promo}."
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr "Læs mere om projekttilladelser %{help_link_open}her%{help_link_close}"
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr "Tilmeld U2F-enhed (Universal Two-Factor)"
msgid "Register WebAuthn Device"
msgstr "Tilmeld WebAuthn-enhed"
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr "Tilbagekaldt efterligningstoken %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr "Kopiér e-mailadresse"
@@ -33846,6 +34433,9 @@ msgstr "Rolle"
msgid "Rollback"
msgstr "Tilbagerul"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr "Maksimum timeout for job"
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr "Navn"
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Runnere"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr "Stop runneren i at acceptere nye job."
msgid "Runners|Tags"
msgstr "Mærkater"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr "Gemmer projekt."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr "Søg efter tildelere"
msgid "Search authors"
msgstr "Søg efter forfattere"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Søg efter grene"
@@ -34797,6 +35408,9 @@ msgstr "Søg efter projekter"
msgid "Search projects..."
msgstr "Søg efter projekter ..."
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "Ikke aktiveret"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr "Opret Jira-problemstilling"
msgid "SecurityReports|Create issue"
msgstr "Opret problemstilling"
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr "Download %{artifactName}"
@@ -35611,12 +36228,18 @@ msgstr "Fejl ved fortolkning af sikkerhedsrapporter"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr "Kunne ikke hente sikkerhedsrapportinformation. Genindlæs venligst siden og prøv igen senere."
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Problemstilling oprettet"
@@ -35734,6 +36357,9 @@ msgstr "Beklager, dit filter gav ingen resultater"
msgid "SecurityReports|Status"
msgstr "Status"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Vælg arkivformat"
msgid "Select Git revision"
msgstr "Vælg Git-revision"
-msgid "Select Page"
-msgstr "Vælg side"
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr "Vælg et skabelondepot"
msgid "Select a template type"
msgstr "Vælg en skabelontype"
-msgid "Select a time zone"
-msgstr "Vælg en tidszone"
-
msgid "Select a timezone"
msgstr "Vælg en tidszone"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr "Vælg gren"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Vælg forfaldsdato"
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr "Vælg projekter"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Vælg kontrollanter"
@@ -36289,6 +36918,9 @@ msgstr "Indstil målgren"
msgid "Set target branch to %{branch_name}."
msgstr "Indstil målgren til %{branch_name}."
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr "Indstil vægt"
msgid "Set weight to %{weight}."
msgstr "Indstil vægt til %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "Der vises en indikator ved siden af dit navn og din avatar"
-
-msgid "SetStatusModal|Busy"
-msgstr "Optaget"
-
msgid "SetStatusModal|Clear status"
msgstr "Ryd status"
msgid "SetStatusModal|Clear status after"
msgstr "Ryd status efter"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Rediger status"
@@ -36388,6 +37017,9 @@ msgstr "Indstil en status"
msgid "SetStatusModal|Set status"
msgstr "Indstil status"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Beklager, vi var ikke i stand til at indstille din status. Prøv venligst igen senere."
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr "Sorteringsretning: stigende"
msgid "Sort direction: Descending"
msgstr "Sorteringsretning: faldende"
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr "Blokerende"
@@ -37337,6 +38008,9 @@ msgstr "Sidste kontakt"
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Mindst populær"
@@ -37397,6 +38071,9 @@ msgstr "Ældste med stjerne"
msgid "SortOptions|Oldest updated"
msgstr "Ældste opdateret"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "Popularitet"
@@ -38297,8 +38974,8 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr "Grøn-cyan"
-msgid "SuggestedColors|Lavendar"
-msgstr "Lavendel"
+msgid "SuggestedColors|Lavender"
+msgstr ""
msgid "SuggestedColors|Magenta-pink"
msgstr "Magentapink"
@@ -38321,9 +38998,21 @@ msgstr "Rosenrød"
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr "Aktivér abonnement"
msgid "SuperSonics|Activation code"
msgstr "Aktiveringskode"
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr "Køb abonnement"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "Dit abonnement"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr "Udklippet kan ikke tilgås uden godkendelse."
@@ -39901,9 +40611,6 @@ msgstr "Der er ingen tilgængelige data."
msgid "There is no data available. Please change your selection."
msgstr "Der er ingen data tilgængelig. Ændr venligst din markering."
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr "Der er ingen tabeldata tilgængelige."
@@ -40171,9 +40878,6 @@ msgstr "Cron-mønsteret er ugyldigt"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Epicen findes ikke eller du har ikke tilstrækkelig tilladelse."
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Dette er din nuværende session"
@@ -40642,6 +41376,9 @@ msgstr "Projektet er arkiveret og kan ikke kommenteres på."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Projektet er licenseret under %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr "Projektet håndterer sine afhængigheder med %{strong_start}%{manager_na
msgid "This project path either does not exist or you do not have access."
msgstr "Enten findes projektstien ikke eller også har du ikke adgang."
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr "Projektet slettes %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr "Projektet vil blive slettet %{date} eftersom dets forældergruppe '%{parent_group_name}' er blevet planlagt til sletning."
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr "Det vil fjerne forgreningsrelationen mellem projektet og %{fork_source}.
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr "Det vil fjerne forgreningsrelationen mellem projektet og andre projekter i forgreningsnetværket."
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr "Kan ikke finde tråden som skal besvares"
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr "Commit-liste til/fra"
-msgid "Toggle dropdown"
-msgstr "Rullegardin til/fra"
-
msgid "Toggle emoji award"
msgstr "Emojibelønning til/fra"
@@ -41366,9 +42115,6 @@ msgstr "Genveje til/fra"
msgid "Toggle sidebar"
msgstr "Sidebjælke til/fra"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "Ydelseslinje til/fra"
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr "Kerner i alt (CPU'er)"
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr "Hukommelse i alt (GB)"
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "GÃ¥ tilbage til GitLab"
-msgid "Trials|Hey there"
-msgstr "Hej med dig"
-
msgid "Trials|Skip Trial"
msgstr "Spring prøveperiode over"
@@ -41627,6 +42373,11 @@ msgstr "Du kan anvende din prøveperiode på en ny gruppe eller en eksisterende
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artefakter"
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr "Sæder"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr "Delte stykker med kode og tekst."
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr "Brugeridentiteten blev fjernet."
msgid "User identity was successfully updated."
msgstr "Brugeridentiteten blev opdateret."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr "Utildelt"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Vis diagram"
@@ -43431,8 +44212,8 @@ msgstr "Vis dokumentation"
msgid "View eligible approvers"
msgstr "Vis kvalificerede godkendere"
-msgid "View epics list"
-msgstr "Vis epicliste"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Fil"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,12 +44660,12 @@ msgstr "Billede"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "Links"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr "Metode"
@@ -43891,6 +44675,9 @@ msgstr "Navnerum"
msgid "Vulnerability|Project"
msgstr "Projekt"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Alvorlighed"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "Status"
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Værktøj"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr "Vi oprettede et sandkasseprojekt som vil hjælpe dig med at lære det grundlæggende i GitLab. Du vil blive vejledt på en problemstillingstavle. Du kan gennemgå problemstillingerne i dit eget tempo."
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Vi registererede potentiel spam i %{humanized_resource_name}. Løs venligst reCAPTCHA'en for at fortsætte."
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr "Hændelser for udsendelse"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr "Hændelser for funktionsflag"
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "Hændelser for problemstillinger"
msgid "Webhooks|Job events"
msgstr "Hændelser for job"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "Hændelser for medlem"
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr "Hemmelig token"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "Hændelser for undergruppe"
@@ -44284,6 +45101,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr "Du kan oprette en ny %{link}."
@@ -45188,6 +46023,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 add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr "Du har opsat 2FA til din konto! Hvis du mister adgang til din 2FA-enhed,
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr "tilføjet"
msgid "added %{emails}"
msgstr "tilføjede %{emails}"
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr "tilføjede et Zoom-opkald til problemstillingen"
@@ -46087,6 +46928,9 @@ msgstr "af"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "må ikke ændres"
@@ -46392,6 +47239,9 @@ msgstr "Fandt %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr "kommentar"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "kommenterede på %{link_to_project}"
@@ -46594,6 +47447,9 @@ msgstr "oprettet %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "oprettet %{timeAgo} af %{author}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr "oprettet af"
@@ -46915,9 +47771,6 @@ msgstr "er ikke tilladt eftersom gruppen ikke er topniveaugruppe."
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr "indlæs det alligevel"
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "mangler"
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "min-fantastiske-gruppe"
@@ -47493,9 +48357,6 @@ msgstr "eller"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "ud af %d test i alt"
@@ -47639,6 +48500,9 @@ msgstr "fjern vægt"
msgid "removed"
msgstr "fjernet"
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "fjernede et Zoom-opkald fra problemstillingen"
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "Der opstod en fejl ved oprettelse af sammenlægningsanmodningen"
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "mærkatnavn"
@@ -47845,6 +48717,11 @@ msgstr "opdateret %{time_ago}"
msgid "uploads"
msgstr "uploads"
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "brugeravatar"
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 98c63b4cf46..ecdde1d6852 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -24,8 +24,8 @@ msgstr " (von %{timeoutSource})"
msgid " (squashes %{strongStart}%{count}%{strongEnd} commit)"
msgid_plural " (squashes %{strongStart}%{count}%{strongEnd} commits)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " (Squasht %{strongStart}%{count}%{strongEnd} Commit)"
+msgstr[1] " (Squasht %{strongStart}%{count}%{strongEnd} Commits)"
msgid " Collected %{time}"
msgstr " Gesammelt %{time}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] "%d zusätzlicher Verfasser"
msgstr[1] "%d zusätzliche Verfasser"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d zusätzlicher Benutzer"
+msgstr[1] "%d zusätzliche Benutzer"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d Genehmigende(r)"
@@ -150,8 +155,8 @@ msgstr[1] "%d Genehmigende (von dir genehmigt)"
msgid "%d artifact"
msgid_plural "%d artifacts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Artefakt"
+msgstr[1] "%d Artefakte"
msgid "%d assigned issue"
msgid_plural "%d assigned issues"
@@ -225,8 +230,8 @@ msgstr[1] "%d Beiträge"
msgid "%d contributor"
msgid_plural "%d contributors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Mitwirkende(r)"
+msgstr[1] "%d Mitwirkende"
msgid "%d day"
msgid_plural "%d days"
@@ -380,8 +385,8 @@ msgstr[1] "%d Projekte ausgewählt"
msgid "%d push"
msgid_plural "%d pushes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Push"
+msgstr[1] "%d Pushes"
msgid "%d remaining"
msgid_plural "%d remaining"
@@ -707,7 +712,7 @@ msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wird entfernt! Bist du sicher?"
msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
-msgstr ""
+msgstr "%{issuable_class_name} existiert nicht oder Berechtigungen zum Hinzufügen eines Zeiteintrages fehlt."
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(s) bereits zugewiesen"
@@ -743,7 +748,7 @@ msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}Absturzzustand:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
-msgstr ""
+msgstr "%{labelStart}Absturztyp:%{labelEnd} %{crash_type}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}Beweis:%{labelEnd} %{evidence}"
@@ -761,7 +766,7 @@ msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Namensraum:%{labelEnd} %{namespace}"
msgid "%{labelStart}Project:%{labelEnd} %{project}"
-msgstr ""
+msgstr "%{labelStart}Projekt:%{labelEnd} %{project}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Scanner:%{labelEnd} %{scanner}"
@@ -800,7 +805,7 @@ msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title
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 draft from merging before it's ready."
-msgstr "%{link_start}Beginnen Sie den Titel mit %{draft_snippet}%{link_end} , um zu verhindern, dass ein Merge-Request-Entwurf vorzeitig gemerged wird."
+msgstr "%{link_start}Beginne den Titel mit %{draft_snippet}%{link_end}, um zu verhindern, dass ein Merge-Request-Entwurf vorzeitig gemerged wird."
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow} und %{awardsListLength} weitere"
@@ -988,8 +993,8 @@ msgstr[1] ""
msgid "%{selectedProjectsCount} project"
msgid_plural "%{selectedProjectsCount} projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{selectedProjectsCount} Projekt"
+msgstr[1] "%{selectedProjectsCount} Projekte"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1024,11 +1029,6 @@ msgstr "%{spanStart}in%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} bis %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}Warnung:%{strongClose} SAML Gruppen-Links können GitLab dazu veranlassen, automatisch Mitglieder aus Gruppen zu entfernen."
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] "%{strong_start}%{count} Mitglied%{strong_end} muss die Zusammenführung genehmigen. Jede(r) mit der Entwickler(innen)rolle oder höher darf genehmigen."
msgstr[1] "%{strong_start}%{count} Mitglieder%{strong_end} müssen die Zusammenführung genehmigen. Jede(r) mit der Entwickler(innen)rolle oder höher darf genehmigen."
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} Punkt"
+msgstr[1] "%{strong_start}%{errors}%{strong_end} Punkte"
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} ist unbekannt oder ungültig"
msgid "%{text} is available"
msgstr "%{text} ist verfügbar"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} sollte zu einem Projekt oder einer Gruppe gehören."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} Warnungen gefunden: Zeige erste %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} unterstützt nur den Namen %{name}"
@@ -1153,10 +1158,13 @@ msgstr "%{user_name} (%{user_username}) wurde aus den folgenden Eskalationsricht
msgid "%{user_name} profile page"
msgstr "Profileseite von %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as draft"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} verbrachte Zeit."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} ermöglichen das Senden von Benachrichtigungen an Web-Anwendungen als Reaktion auf Ereignisse in einer Gruppe oder einem Projekt."
@@ -1558,10 +1572,10 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), wenn du denkst, dass dies ein Fehler ist."
msgid "409|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), wenn du denkst, dass dies ein Fehler ist."
msgid "409|There was a conflict with your request."
-msgstr ""
+msgstr "Es gab einen Konflikt bei deiner Anfrage."
msgid "8 hours"
msgstr "8 Stunden"
@@ -1665,9 +1679,6 @@ msgstr "Ein neues Release %{tag} für %{name} wurde veröffentlicht. Besuche die
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "Eine neuer Identitätswechsel-Token wurde erstellt."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr "Ein persönlicher Zugangstoken wurde widerrufen"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr "Ein persönliches Zugangstoken, namens %{code_start}%{token_name}%{code_end}, wurde widerrufen."
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr "Ein persönliches Zugangstoken, namens %{token_name}, wurde widerrufen."
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Eine einfache HTML-Seite, welche Netlify anstatt GitLab für CI/CD nutzt, aber trotzdem von den nützlichen GitLab-Funktionen profitiert"
@@ -1750,10 +1770,10 @@ msgid "API?"
msgstr "API?"
msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
-msgstr ""
+msgstr "$VARIABLE_WITH_PASSWORD"
msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
-msgstr ""
+msgstr "$VARIABLE_WITH_USERNAME"
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1978,7 +1998,7 @@ msgid "AccessTokens|Keep this token secret. Anyone who has it can access reposit
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 ""
+msgstr "Halte diesen Token geheim. Jeder der den Token besitzt, kann Tickets erstellen, als wären sie von dir erstellt. Sollte dies jemals geschehen, %{linkStart}setze diesen Token zurück%{linkEnd}."
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 ""
@@ -2170,7 +2190,7 @@ msgid "Add a confidential internal note to this %{noteableDisplayName}."
msgstr ""
msgid "Add a custom message with details about the instance's shared runners. The message is visible when you view runners for projects and groups. Markdown is supported."
-msgstr ""
+msgstr "Füge eine benutzerdefinierte Nachricht mit Details zu den gemeinsamen Runnern der Instanz hinzu. Die Nachricht ist sichtbar, wenn du Runner für Projekte und Gruppen ansiehst. Markdown wird unterstützt."
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Füge einen allgemeinen Kommentar zu %{noteableDisplayName} hinzu."
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr "Benutzer(innen) zur Gruppe hinzufügen:"
-
-msgid "Add users to group"
-msgstr "Füge Benutzer(innen) zur Gruppe hinzu"
-
msgid "Add variable"
msgstr "Variable hinzufügen"
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "Lege die Ablaufzeit der Authentifizierungstoken neu registrierter Instance-Runner fest. Authentifizierungstoken werden in diesen Intervallen automatisch zurückgesetzt."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Blockiert"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Benutzer(in) zu blockieren hat folgende Auswirkungen:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "Kann Gruppe erstellen"
@@ -3154,7 +3198,7 @@ msgid "AdminUsers|It's you!"
msgstr "Das bist du!"
msgid "AdminUsers|LDAP Blocked"
-msgstr ""
+msgstr "LDAP blockiert"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr "Alle Projektmitglieder"
+
msgid "All projects"
msgstr "Alle Projekte"
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr "Benutzern das Erstellen von Gruppen auf oberster Ebene erlauben"
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Beim Laden der Diagrammdaten ist ein Fehler aufgetreten"
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr "Analysen"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "%d Dateien anhängen"
msgid "Attaching the file failed."
msgstr "Die Datei konnte nicht angehängt werden."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr "Es wurde versucht, sich mit einem falschen Zwei-Faktor-Authentifizierungscode bei %{host} anzumelden"
+
msgid "Audit Events"
msgstr "Audit-Ereignisse"
@@ -5473,7 +5541,7 @@ msgid "AuditStreams|This is great for keeping everything one place."
msgstr ""
msgid "AuditStreams|Value"
-msgstr ""
+msgstr "Wert"
msgid "AuditStreams|Verification token"
msgstr "Bestätigungstoken"
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Unten findest du alle Gruppen, die öffentlich sind."
+msgid "Beta"
+msgstr "Beta"
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6609,13 +6683,13 @@ msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
msgid "Boards|Move card"
-msgstr ""
+msgstr "Karte verschieben"
msgid "Boards|Move to end of list"
-msgstr ""
+msgstr "An das Ende der Liste verschieben"
msgid "Boards|Move to start of list"
-msgstr ""
+msgstr "An den Anfang der Liste verschieben"
msgid "Boards|New board"
msgstr "Neues Board"
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "Sowohl SSH als auch HTTP(S)"
@@ -6707,33 +6784,78 @@ msgstr "Branch nicht geladen - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
+msgstr "Pushen erlaubt"
+
+msgid "BranchRules|Allowed to push (%{total})"
msgstr ""
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
+msgstr "Branch"
+
+msgid "BranchRules|Branch name or pattern"
msgstr ""
+msgid "BranchRules|Branch rules details"
+msgstr "Details zu den Branch-Regeln"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "Gruppen"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr "Rollen"
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr "Zielbranch"
+
+msgid "BranchRules|Users"
+msgstr "Benutzer"
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr "Ungültiger Quelltyp der Entität"
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr "Bereitstellungsstrategie"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Jobs"
@@ -7225,8 +7365,8 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
-msgstr ""
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Wähle die Projekte aus, auf die über API-Anfragen zugegriffen werden kann, die mit der CI/CD-Variable CI_JOB_TOKEN dieses Projekts authentifiziert wurden. Es stellt ein Sicherheitsrisiko dar, diese Funktion zu deaktivieren, da nicht autorisierte Projekte versuchen könnten, ein aktives Token abzurufen und auf die API zuzugreifen. %{linkStart}Mehr erfahren.%{linkEnd}"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr ""
@@ -7486,8 +7626,8 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "Ãœber eine interne ID kann nicht auf einen Gruppen-Milestone verwiesen werden!"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr ""
@@ -7681,6 +7821,9 @@ msgstr "Ändert den Titel in \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8438,7 +8581,7 @@ msgid "Cloud Run"
msgstr ""
msgid "Cloud SQL instances are fully managed, relational MySQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Cloud SQL-Instanzen sind vollständig verwaltete, relationale MySQL-Datenbanken. Google kümmert sich um die Replikation, das Patch-Management und die Datenbankverwaltung, um Verfügbarkeit und Leistung zu gewährleisten."
msgid "Cloud SQL instances are fully managed, relational SQL Server databases. Google handles replication, patch management, and database management to ensure availability and performance."
msgstr ""
@@ -8447,28 +8590,28 @@ msgid "Cloud Storage"
msgstr ""
msgid "CloudSeed|All"
-msgstr ""
+msgstr "Alle"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "AlloyDB für Postgres"
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "Verfügbare Datenbankdienste mit denen Instanzen erstellt werden können"
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "Abbrechen"
msgid "CloudSeed|Cloud Firestore"
msgstr ""
msgid "CloudSeed|Cloud SQL for MySQL"
-msgstr ""
+msgstr "Cloud SQL für MySQL"
msgid "CloudSeed|Cloud SQL for Postgres"
-msgstr ""
+msgstr "Cloud SQL für Postgres"
msgid "CloudSeed|Cloud SQL for SQL Server"
-msgstr ""
+msgstr "Cloud SQL für SQL Server"
msgid "CloudSeed|Cloud SQL instance creation request successful. Expected resolution time is ~5 minutes."
msgstr ""
@@ -8567,16 +8710,16 @@ msgid "CloudSeed|Memorystore for Redis"
msgstr ""
msgid "CloudSeed|No instances"
-msgstr ""
+msgstr "Keine Instanzen"
msgid "CloudSeed|Refs"
-msgstr ""
+msgstr "Referenzen"
msgid "CloudSeed|Regions"
msgstr "Regionen"
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
-msgstr ""
+msgstr "Skalierbarer, sicherer und hochverfügbarer In-Memory-Dienst für Redis"
msgid "CloudSeed|Service"
msgstr ""
@@ -8585,13 +8728,13 @@ msgid "CloudSeed|Service Account"
msgstr "Dienstkonto"
msgid "CloudSeed|Services"
-msgstr ""
+msgstr "Dienste"
msgid "CloudSeed|There are no instances to display."
msgstr ""
msgid "CloudSeed|Version"
-msgstr ""
+msgstr "Version"
msgid "Cluster"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9427,7 +9585,7 @@ msgid "Collector hostname"
msgstr ""
msgid "Color"
-msgstr ""
+msgstr "Farbe"
msgid "ColorWidget|An error occurred while updating color."
msgstr "Es gab einen Fehler beim Aktualisieren der Farbe."
@@ -9563,6 +9721,9 @@ msgstr "Commits zu"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Beim Abrufen der Daten des Merge-Requests ist ein Fehler aufgetreten."
@@ -9668,6 +9829,9 @@ msgstr "Abgeschlossen"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr "Container-Registry"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Container Scanning"
@@ -10511,13 +10678,13 @@ msgstr "Mitwirkende"
msgid "Control emails linked to your account"
msgstr "Lege mit deinem Konto verknüpfte E-Mails fest"
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Abdeckung"
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Wildcard erstellen: %{searchTerm}"
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr "Tag-Nachricht festlegen"
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr "Gelöscht"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr "Nur Lesezugriff"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Aktive Bereitstellungstoken (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "Ermöglicht Lese- und Schreibzugriff auf Registry-Images."
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "Ablaufdatum (optional)"
+
msgid "DeployTokens|Expires"
msgstr "Verfällt"
@@ -13059,6 +13256,9 @@ msgstr "Widerrufe %{name}"
msgid "DeployTokens|Scopes"
msgstr "Gültigkeitsbereiche"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Benutzername"
+msgid "DeployTokens|Username (optional)"
+msgstr "Benutzername (optional)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "Dein neuer Bereitstellungs-Token"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr "Für Informationen zu einem möglichen Ersatz %{epicStart} erfahre mehr über Opstrace %{epicEnd}."
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr "Für Informationen zu einem möglichen Ersatz %{opstrace_link_start} erfahre mehr über Opstrace %{link_end}."
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr "Die Metrikfunktion wurde in GitLab 14.7 eingestellt."
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,8 +13572,8 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
-msgstr "Kommentar verwerfen"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr "Domäne"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "Die folgenden Domains sind für Projekte in dieser Gruppe konfiguriert. Benutzer(innen) mit E-Mail-Adressen, die zu einer verifizierten Domain passen, müssen ihr Konto nicht bestätigen."
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Wiki-Seite bearbeiten"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr "E-Mails"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr "An %{email} gesendete E-Mails werden ebenfalls unterstützt."
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr "Bereitstellung"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr "Noch keine Bereitstellungen"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Beachte, dass diese Aktion die Umgebung stoppen wird, es aber %{emphasisStart}keine%{emphasisEnd} Auswirkungen auf bestehende Bereitstellung haben wird, da keine \"stop environment action\" in der Datei %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} definiert ist."
@@ -14976,6 +15185,9 @@ msgstr "Umgebung wiederherstellen"
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Alle anzeigen"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "Fehler beim Laden der Emoji-Liste."
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "Alternativ kannst Du auf GitLab Premium oder GitLab Ultimate upgraden."
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "Kostenpflichtige Tarife erkunden"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "Kostenpflichtige Tarife erkunden:"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr "Es scheint so, als hättest Du die Grenze von %{free_user_limit} Mitgliedern für %{namespace_name} erreicht. Du kannst keine Weiteren hinzufügen, aber Du kannst deine bestehenden Mitglieder verwalten, indem Du beispielsweise inaktive Mitglieder entfernst und durch neue Mitglieder ersetzt."
+
+msgid "FreeUserCap|Manage members"
+msgstr "Mitglieder verwalten"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "Mitglieder verwalten:"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "Um mehr Mitglieder zu erhalten, %{trial_link_start}probiere die Testversion%{trial_link_end}, oder %{upgrade_link_start}upgrade%{upgrade_link_end} auf GitLab Premium oder GitLab Ultimate."
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "Um mehr Mitglieder zu erhalten, probiere die Testversion:"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "Du hast die Mitgliederlimit erreicht!"
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr "Fehler:"
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fehlgeschlagen"
@@ -17264,10 +17512,10 @@ msgid "Geo|Next sync scheduled at"
msgstr "Nächste Synchronisierung geplant um"
msgid "Geo|No %{replicable_type} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "Es wurden keine %{replicable_type} gefunden. Wenn du der Meinung bist, dass dies ein Fehler ist, findest du weitere Informationen in der Dokumentation zur %{linkStart}Geo Fehlersuche%{linkEnd}."
msgid "Geo|No %{replicable} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "Es wurden keine %{replicable} gefunden. Wenn du der Meinung bist, dass dies ein Fehler ist, findest du weitere Informationen in der Dokumentation zur %{linkStart}Geo Fehlersuche%{linkEnd}."
msgid "Geo|No Geo site found"
msgstr "Keine Geo-Seite gefunden"
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr "Erfahre mehr über Untergruppen"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "Muss mit einem Buchstaben, einer Ziffer, einem Emoji oder einem Unterstrich beginnen. Kann auch Punkte, Bindestriche, Leerzeichen und Klammern enthalten."
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr "Identitäten"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr "Wenn Du nicht kürzlich versucht hast, Dich anzumelden, dann solltest Du umgehend %{password_link_start}Dein Passwort ändern%{password_link_end}."
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr "Wenn Du nicht kürzlich versucht hast, Dich anzumelden, dann solltest Du umgehend Dein Passwort ändern: %{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 ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "Wenn du dich kürzlich angemeldet hast und die IP-Adresse erkennst, kannst du diese E-Mail ignorieren."
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr "Wenn Du vor kurzem versucht hast, Dich anzumelden, aber versehentlich einen falschen Code für die Zwei-Faktor-Authentifizierung eingegeben hast, kannst Du diese E-Mail ignorieren."
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr "Verbinde Repositories von"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr "Zeile einrücken"
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallmuster"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr "Verwendet eine Lizenz"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr "Iteration"
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr "Mehr Informationen"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr "Mache alle in deinem Team unabhängig von ihrem Standort produktiver. Gi
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr "Zwei-Faktor-Authentifizierung verwalten"
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr "Durchgestrichenen Text hinzufügen (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Durchgestrichenen Text hinzufügen (%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr "Zeile einrücken (%{modifierKey}])"
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr "Zeile einrücken (%{modifier_key}])"
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "Zeile ausrücken (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "Zeile ausrücken (%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "Unterstützt %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} abgeschlossen"
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr "Benutzer(in) spiegeln"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Gespiegelte Repositories"
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr "Neues Label benennen"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Name:"
@@ -26147,6 +26512,9 @@ msgstr "Neuer Pipeline Zeitplan"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Neue Anforderung"
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,25 +27305,52 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email}, jetzt bekannt als %{user_name}, hat deine Einladung angenommen, dem %{target_name} %{target_model_name} beizutreten."
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} hat %{member_role} Zugriff auf %{target_source_link} %{target_type} angefordert."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
msgstr ""
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr "%{p_start}Um die Remote-URL in deinem lokalen Repository zu aktualisieren, führe (für ssh):%{p_end} %{ssh_url_to_repo} %{p_start}oder für http(s):%{p_end} %{http_url_to_repo} aus"
+
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
+msgstr "%{paragraph_start}Hallo %{name}!%{paragraph_end} %{paragraph_start}Ein neuer öffentlicher Schlüssel wurde zu Deinem Konto hinzugefügt:%{paragraph_end} %{paragraph_start}Bezeichnung: %{key_title}%{paragraph_end} %{paragraph_start}Wenn dieser Schlüssel irrtümlich hinzugefügt wurde, kannst Du ihn unter %{removal_link} entfernen.%{paragraph_end}"
+
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
msgstr ""
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
@@ -26961,6 +27359,12 @@ msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr "Die automatische DevOps-Pipeline wurde für %{project} deaktiviert"
msgid "Notify|CI/CD project settings"
msgstr "CI/CD-Projekteinstellungen"
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr "Mehr über Auto-DevOps erfahren"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr "Projekt %{old_path_with_namespace} wurde an einen anderen Ort verschoben."
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "Die Auto DevOps-Pipeline ist für die Pipeline %{pipeline_link} fehlgeschlagen und wurde für %{project_link} deaktiviert. Um die Auto-DevOps-Pipeline mit deinem Projekt zu verwenden, überprüfe bitte %{supported_langs_link}, passe dein Projekt entsprechend an und aktiviere die Auto-DevOps-Pipeline in deinen %{settings_link}."
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr "Das Projekt befindet sich jetzt unter %{project_full_name_link_start}%{project_full_name}%{link_end}."
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "Deine Anfrage, dem %{target_to_join} %{target_type} beizutreten, wurde %{denied_tag}."
msgid "Notify|currently supported languages"
msgstr "Aktuell unterstützte Sprachen"
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Okt"
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr "Leite Alarme direkt an bestimmte Mitglieder deines Teams weiter. Um auf diese Funktion zuzugreifen, bitte %{linkStart}einen Projekteigentümer%{linkEnd} dir mindestens die Betreuerrolle zuzuweisen."
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr "Zeile ausrücken"
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr "Anzahl der zu behaltenden doppelten Assets"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr "Wenn ein Paket mit dem gleichen Namen und der gleichen Version zum Regis
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr "Pausieren"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Aktiv"
msgid "PipelineSchedules|All"
msgstr "Alle"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inaktiv"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Nächste Durchführung"
@@ -28960,15 +29472,27 @@ msgstr "Nichts"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Gib eine kurze Beschreibung für diese Pipeline ein"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Eigentümer(in) werden"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Ziel"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variablen"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr "Bitte warte, während wir uns mit deinem Repository verbinden. Nach Beli
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Warte bitte, während wir das Repository für dich importieren. Aktualisiere nach Belieben."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "Pods im Einsatz"
@@ -29833,6 +30369,9 @@ msgstr "Einstellungen"
msgid "Preferences saved."
msgstr "Einstellungen gespeichert."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Verhalten"
@@ -29944,6 +30483,9 @@ msgstr "Zeiteinstellungen"
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr "Aktiv"
msgid "Profiles|Add key"
msgstr "Schlüssel hinzufügen"
-msgid "Profiles|Add status emoji"
-msgstr "Füge Status-Emoji hinzu"
-
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 "Neben deinem Namen und Avatar erscheint ein Indikator."
-
msgid "Profiles|Avatar cropper"
msgstr "Avatar zuschneiden"
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr "Benutzernamen ändern"
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "Stadt, Land"
-msgid "Profiles|Clear status"
-msgstr "Status löschen"
-
msgid "Profiles|Commit email"
msgstr "Commit-E-Mail"
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Verbundene Konten"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Aktueller Pfad: %{path}"
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr "Webadresse"
-msgid "Profiles|What's your status?"
-msgstr "Was ist dein Status?"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Dein Status"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Nur signierte Commits können zu diesem Repository gepusht werden."
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr "Beim Abrufen der Ãœbertragungsorte ist ein Fehler aufgetreten. Bitte aktualisiere die Seite und versuche es erneut."
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Mehr lesen"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "Das Repository muss mindestens eine Datei enthalten."
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr "Rich Text"
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr "Rolle"
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr "Aktuell"
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Branches durchsuchen"
@@ -34797,6 +35408,9 @@ msgstr "Projekte suchen"
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ", und %{count} mehr"
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr "Leider hat dein Filter keine Ergebnisse geliefert"
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Archivierungsformat auswählen"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr "Wähle ein Vorlagen-Repository aus"
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr "Zeitzone auswählen"
-
msgid "Select a timezone"
msgstr "Zeitzone auswählen"
@@ -35929,9 +36549,15 @@ msgstr "Beauftragte(n)"
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr "Ziel-Branch setzen"
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "Status löschen"
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "Zeigt an, dass du beschäftigt bist oder nicht antworten kannst"
+
msgid "SetStatusModal|Edit status"
msgstr "Status bearbeiten"
@@ -36388,6 +37017,9 @@ msgstr "Einen Status setzen"
msgid "SetStatusModal|Set status"
msgstr "Status setzen"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "Setze dich als beschäftigt"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Leider konnten wir deinen Status nicht festlegen. Bitte versuche es später erneut."
@@ -36828,7 +37460,7 @@ msgid "SignUp|By clicking %{button_text} or registering through a third party yo
msgstr ""
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "Indem du auf %{button_text} klickst oder dich über einen Drittanbieter registrierst, akzeptierst du %{link_start}die Nutzungsbedingungen und erkennst die Datenschutz- und Cookie-Richtlinien%{link_end} an."
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr "GitLab-Inhalte anzeigen und kontrollieren, während du in Slack arbeitest. Gib den Befehl als Nachricht in deinen Chat-Client ein, um ihn zu aktivieren. %{startMarkup}Erfahre mehr%{endMarkup}."
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr "Zuletzt gesehen"
msgid "SortOptions|Last created"
msgstr "Zuletzt erstellt"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Am unbeliebtesten"
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr "Älteste Aktualisierung"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "Beliebtheit"
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,8 +39064,8 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr "Die Instanz kann aufgrund eines Verbindungsproblems nicht aktiviert werden."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr ""
msgid "SuperSonics|Cloud licensing"
msgstr ""
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,9 +40941,12 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr "Der Umfang dieses Boards ist reduziert"
-msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
+msgid "This branch has diverged from upstream."
msgstr ""
+msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
+msgstr "Diese Änderung entfernt %{strongOpen}ALL%{strongClose} Premium- und Ultimate-Funktionen für %{strongOpen}ALL%{strongClose} SaaS-Kunden und führt dazu, dass Tests nicht mehr funktionieren."
+
msgid "This chart could not be displayed"
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Dies ist deine aktuelle Sitzung"
@@ -40642,6 +41376,9 @@ msgstr "Dieses Projekt ist archiviert und kann nicht kommentiert werden."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr "Diese Version wurde mit einem Datum in der Vergangenheit erstellt. Eine Beweissammlung zum Zeitpunkt der Veröffentlichung ist nicht verfügbar."
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr "Thread zum Antworten kann nicht gefunden werden"
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr "Um interne Benutzer(innen) zu definieren, musst du zunächst externe Benutzer(innen) aktivieren"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr "Beschreibung des Commits ein-/ausklappen"
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Seitenleiste ein-/ausblenden"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr "Nutzeridentität wurde erfolgreich aktualisiert."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "Benutzer:innen erfolgreich hinzugefügt."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43361,7 +44139,7 @@ msgid "Version %{report_version} for report type %{report_type} has been depreca
msgstr ""
msgid "Version %{report_version} for report type %{report_type} is unsupported, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
-msgstr ""
+msgstr "Die Version %{report_version} für den Berichtstyp %{report_type} wird nicht unterstützt, folgende Versionen werden für diesen Berichtstyp unterstützt: %{supported_schema_versions}. GitLab versucht, diesen Bericht anhand der frühesten unterstützten Versionen dieses Berichtstyps zu validieren, um alle Fehler anzuzeigen, übernimmt den Bericht jedoch nicht"
msgid "Version %{versionNumber}"
msgstr ""
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,8 +44212,8 @@ msgstr ""
msgid "View eligible approvers"
msgstr "Geeignete Genehmigungsberechtigte anzeigen"
-msgid "View epics list"
-msgstr "Epic-Liste anzeigen"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Datei"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,12 +44660,12 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "Links"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr ""
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projekt"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Schweregrad"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitte löse den reCAPTCHA um fortzufahren."
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr "Beauftragte(n) hinzufügen"
msgid "WorkItem|Add assignees"
msgstr "Beauftragte hinzufügen"
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr "Aufgabe hinzufügen"
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr "Du kannst keine weiteren Epics mehr hinzufügen. Dieses Epic hat bereits die maximale Anzahl an untergeordneten Epics."
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr "von"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr "Limit von %{project_limit} erreicht"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr "Meilenstein sollte entweder zu einem Projekt oder eine Gruppe gehören."
+
msgid "missing"
msgstr "fehlt"
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "meine-tolle-gruppe"
@@ -47493,9 +48357,6 @@ msgstr "oder"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "von insgesamt %d Test"
@@ -47639,6 +48500,9 @@ msgstr "Gewichtung entfernen"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "Zoom Anruf von diesem Ticket entfernt"
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "Fehler während der Merge-Request-Erstellung"
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "Tag-Name"
@@ -47845,6 +48717,11 @@ msgstr "aktualisiert %{time_ago}"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "Benutzeravatar"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 2b4d8d5cec7..8c7c7be8114 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/en_GB/gitlab.po b/locale/en_GB/gitlab.po
index ba3aa1d928d..b55d8cfb28a 100644
--- a/locale/en_GB/gitlab.po
+++ b/locale/en_GB/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: en-GB\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr " %{start} to %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] "%d additional committer"
msgstr[1] "%d additional committers"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d approver"
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr "Git abuse rate limit"
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "Can create group"
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "Both SSH and HTTP(S)"
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr "Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr "For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,17 +20090,23 @@ msgstr "Please enter a valid code"
msgid "IdentityVerification|Resend code"
msgstr "Resend code"
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr "The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr "The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr ""
msgid "IdentityVerification|Verification code"
msgstr "Verification code"
@@ -19824,6 +20117,12 @@ msgstr "Verification successful"
msgid "IdentityVerification|Verify code"
msgstr "Verify code"
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,11 +20132,14 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr "You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr "Marked this %{noun} as ready."
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} in %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr "Auto DevOps pipeline was disabled for %{project}"
msgid "Notify|CI/CD project settings"
msgstr "CI/CD project settings"
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr "Learn more about Auto DevOps"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr "Milestone changed to %{milestone}"
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline %{pipeline_link} triggered by"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr "Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgid "Notify|currently supported languages"
msgstr "currently supported languages"
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "successfully completed %{jobs} in %{stages}."
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr "An indicator appears next to your name and avatar."
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr "Choose to show contributions of private projects on your public profile
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr "Connect a service for sign-in."
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr "Who you represent or work for."
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "Your name was automatically set based on your %{provider_label} account, so people you know can recognise you."
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr "Get started with runners"
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr "How do we upgrade GitLab runner?"
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} more"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ", and %{count} more"
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr "Set the Ready status"
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr "Solid"
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,8 +38974,8 @@ msgstr "Green screen"
msgid "SuggestedColors|Green-cyan"
msgstr "Green-cyan"
-msgid "SuggestedColors|Lavendar"
-msgstr "Lavender"
+msgid "SuggestedColors|Lavender"
+msgstr ""
msgid "SuggestedColors|Magenta-pink"
msgstr "Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr "Rose red"
msgid "SuggestedColors|Titanium yellow"
msgstr "Titanium yellow"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr "Toggle the Draft status"
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr "Add assignee"
msgid "WorkItem|Add assignees"
msgstr "Add assignees"
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr "Create task"
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr "organisations can only be added to root groups"
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 6075d6b3320..e233156e745 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr "Kontribuantoj"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervala Åablono"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr "Nova ĉenstabla plano"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Åœaltitaj"
msgid "PipelineSchedules|All"
msgstr "Ĉiuj"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "MalÅaltitaj"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Sekvanta plenumo"
@@ -28960,15 +29472,27 @@ msgstr "Nenio"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Akiri posedon"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Celo"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variabloj"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Legu pli"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Elektu formaton de arkivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Elektu horzonon"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 4b43727c308..6ba80989cc7 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprobador"
@@ -1024,11 +1029,6 @@ msgstr "%{spanStart}en%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} hasta %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] "%{strongOpen}%{errors}%{strongClose} punto"
-msgstr[1] "%{strongOpen}%{errors}%{strongClose} puntos"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} es desconocido o no es válido"
msgid "%{text} is available"
msgstr "%{text} esta disponible"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advertencias encontradas: mostrando las primeras %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} solo admite %{name} nombre"
@@ -1153,12 +1158,15 @@ msgstr "%{user_name} (%{user_username}) fue eliminado de las siguientes polític
msgid "%{user_name} profile page"
msgstr "%{user_name} página de perfil"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} ha solicitado una cuenta de GitLab en su instancia %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "Avatar de %{username}"
@@ -1180,6 +1188,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} tiempo gastado."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar notificaciones a aplicaciones web en respuesta a los eventos generados en un grupo o en un proyecto."
@@ -1665,9 +1679,6 @@ msgstr "Se publicó una nueva versión %{tag} para %{name}. Visite la página de
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "Se ha creado un nuevo token de impersonación."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Un sitio HTML simple que utiliza Netlify para CI/CD en lugar de GitLab, pero que mantiene todas las otras excelentes características de GitLab"
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Añadir disparador"
-msgid "Add user(s) to the group:"
-msgstr "Añadir usuario(s) al grupo:"
-
-msgid "Add users to group"
-msgstr "Añadir usuarios al grupo"
-
msgid "Add variable"
msgstr "Añadir variable"
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "He leído y acepto los %{link_start}términos de servicio%{link_end}(PDF) de Let's Encrypt."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "Mantener los últimos artefactos para todos los trabajos en los últimos pipelines ejecutados correctamente"
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr "Exportar proyecto"
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "Proteger las variables de CI/CD de forma predeterminada"
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "Establezca el límite a 0 para desactivarlo."
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Bloqueado"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Bloquear usuario tiene los siguientes efectos:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "Puede crear grupo"
@@ -3417,9 +3461,21 @@ msgstr "Opciones de exportación avanzadas"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "Reindexación requerida"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr "Todas las dependencias de las peticiones de fusión han sido fusionadas"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Todos los proyectos"
@@ -3921,6 +3980,9 @@ msgstr "Permitir a esta clave hacer push a este repositorio"
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr "Se ha producido un error al cargar una sección de esta página."
msgid "An error occurred while loading all the files."
msgstr "Se ha producido un error al cargar todos los archivos."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Se ha producido un error al cargar los datos del gráfico."
@@ -4457,6 +4516,9 @@ msgstr "Se ha producido un error desconocido."
msgid "Analytics"
msgstr "Analíticas"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analizar sus dependencias en busca de vulnerabilidades conocidas."
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "Adjuntar %d archivos"
msgid "Attaching the file failed."
msgstr "Se ha producido un error al adjuntar el archivo."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Eventos de auditoría"
@@ -5994,6 +6062,9 @@ msgstr "A continuación se muestran los ajustes relativos a %{link_to_gitlab_pag
msgid "Below you will find all the groups that are public."
msgstr "A continuación encontrará todos los grupos públicos."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Cobertura de código quincenal"
@@ -6315,8 +6386,8 @@ msgstr "Membresías directas"
msgid "Billing|Enter at least three characters to search."
msgstr "Introduzca al menos tres caracteres para buscar."
-msgid "Billing|Explore all plans"
-msgstr "Explorar todos los planes"
+msgid "Billing|Explore paid plans"
+msgstr ""
msgid "Billing|Export list"
msgstr "Exportar lista"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr "Escriba el %{username} para confirmar"
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr "Se ha eliminado correctamente a este usuario"
@@ -6671,6 +6745,9 @@ msgstr "Cargando épicas"
msgid "Bold text"
msgstr "Negrita"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "Tanto SSH como HTTP(S)"
@@ -6707,33 +6784,78 @@ msgstr "Branch no cargada - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr "Protecciones"
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr "Por defecto al pipeline de Auto DevOps para todos los proyectos"
msgid "CICD|Deployment strategy"
msgstr "Estrategia de despliegue"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Trabajos"
@@ -7225,7 +7365,7 @@ msgstr "Límite"
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr "No se puede promocionar la incidencia porque no pertenece a un grupo."
msgid "Cannot promote issue due to insufficient permissions."
msgstr "No se puede promocionar la incidencia debido a la falta de permisos."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,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 "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr "¿Está seguro de que desea eliminar este agente? Esta acción no se pue
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr "Certificado"
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Última conexión %{timeAgo}"
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr "No está conectado"
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr "Recomendado"
@@ -8895,6 +9050,9 @@ msgstr "Token revocado por %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Usuario desconocido"
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "Ver todos los agentes %{number}"
@@ -9563,6 +9721,9 @@ msgstr "Commits a"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Se ha producido un error al obtener los datos de los merge requests."
@@ -9668,6 +9829,9 @@ msgstr "Completado"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr "Completado"
@@ -9737,7 +9901,7 @@ msgstr "El nombre es obligatorio"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr "Contactos"
msgid "Container Registry"
msgstr "Registro de contenedores"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Análisis de contenedores"
@@ -10511,13 +10678,13 @@ msgstr "Contribuidores"
msgid "Control emails linked to your account"
msgstr "Controle los correos electrónicos vinculados a su cuenta"
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr "País"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Cobertura"
@@ -11057,6 +11227,9 @@ msgstr "Crear tema"
msgid "Create user"
msgstr "Crear usuario"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Crear comodín: %{searchTerm}"
@@ -11069,6 +11242,12 @@ msgstr "Cree su grupo"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "No tiene permiso para crear un subgrupo en este grupo."
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Día del mes"
@@ -12510,6 +12695,9 @@ msgstr "Eliminar cuenta"
msgid "Delete artifacts"
msgstr "Eliminar artefactos"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr "Eliminado"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "¡Eliminado el nick del chat %{chat_name}!"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr "¡Los proyectos eliminados no se pueden recuperar!"
@@ -12993,6 +13184,9 @@ msgstr "Acceso de sólo lectura"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Claves de despliegue activas (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "Expira"
@@ -13059,6 +13256,9 @@ msgstr "Revocar %{name}"
msgid "DeployTokens|Scopes"
msgstr "Ãmbitos"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Nombre de usuario"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr "exitoso"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,20 +13536,11 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "¿Está seguro de que desea cancelar los cambios realizados en este comentario?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "¿Está seguro de que desea cancelar la creación de este comentario?"
-msgid "DesignManagement|Cancel changes"
-msgstr "Cancelar los cambios"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Cancelar la confirmación de comentario"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "Cancelar la confirmación de actualización de los comentarios"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
@@ -13360,6 +13548,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "Comentario"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Se ha producido un error al crear el comentario. Por favor, inténtelo de nuevo."
@@ -13378,8 +13572,8 @@ msgstr "Deseleccionar todo"
msgid "DesignManagement|Designs"
msgstr "Diseños"
-msgid "DesignManagement|Discard comment"
-msgstr "Descartar comentario"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr "Ir al siguiente diseño"
msgid "DesignManagement|Go to previous design"
msgstr "Ir al diseño anterior"
-msgid "DesignManagement|Keep changes"
-msgstr "Mantener los cambios"
-
-msgid "DesignManagement|Keep comment"
-msgstr "Mantener comentario"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "La versión del diseño solicitada no existe. Mostrando la última versión en su lugar"
@@ -13947,6 +14135,18 @@ msgstr "Dominio"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Editar página wiki"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Edite su comentario más reciente en un hilo (desde un cuadro de texto vacío)"
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr "Correos electrónicos"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "Habilitar notificaciones por correo electrónico"
@@ -14919,6 +15122,9 @@ msgstr "Despliegue"
msgid "Environments|Deployment %{status}"
msgstr "Despliegue %{status}"
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr "No hay entornos desplegados"
msgid "Environments|No deployments yet"
msgstr "Todavía no hay despliegues"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Note que esta acción detendrá el entorno, pero %{emphasisStart}no%{emphasisEnd} tendrá ningún efecto sobre cualquier instancia debido a que no hay una \"acción para detener el entorno\" definida en el archivo %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}."
@@ -14976,6 +15185,9 @@ msgstr "Deshacer entorno"
msgid "Environments|Rollback environment %{name}?"
msgstr "¿Desea restaurar el entorno %{name}?"
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Mostrar todo"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "Se ha producido un error al cargar la lista de emojis."
-
msgid "Failed to load error details from Sentry."
msgstr "Se ha producido un error al cargar los detalles de error desde Sentry."
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr "Se han encontrado errores en su fichero .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fallido"
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr "Incidencia de GitLab"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr "Cargando tareas épicas"
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr "Sin fecha de inicio y sin fecha de finalización"
@@ -18622,6 +18873,9 @@ msgstr "Para ver la hoja de ruta, agregue la fecha de inicio o la de vencimiento
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para ampliar su búsqueda, cambie o elimine los filtros; desde %{startDate} a %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr "Dentro de 3 años"
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr "Nombre del subgrupo"
msgid "Groups|Subgroup slug"
msgstr "Slug del subgrupo"
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "Guía"
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr "Antes de iniciar sesión, necesitamos verificar su identidad. Introduzca el siguiente código en la página de inicio de sesión."
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr "Crear un proyecto"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,17 +20090,23 @@ msgstr "Por favor, introduzca un código válido"
msgid "IdentityVerification|Resend code"
msgstr "IdentityVerification|Reenviar código"
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr "IdentityVerification|El código ha caducado. Vuelve a enviar un nuevo código e inténtalo de nuevo."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr "IdentityVerification|El código es incorrecto. Introdúzcalo de nuevo, o vuelva a enviar un nuevo código."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr ""
msgid "IdentityVerification|Verification code"
msgstr "IdentityVerification|Código de verificación"
@@ -19824,6 +20117,12 @@ msgstr "IdentityVerification|Verificación correcta"
msgid "IdentityVerification|Verify code"
msgstr "IdentityVerification|Verificar código"
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr "Verifique su identidad"
@@ -19833,11 +20132,14 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr "Ha alcanzado la cantidad máxima de intentos. Espere %{interval} o reenvíe un nuevo código e inténtelo de nuevo."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "Su cuenta ha sido verificada correctamente. Será redirigido a su cuenta en un momento o %{redirect_url_start}haga clic aquí%{redirect_url_end} para actualizar."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "Suu código de verificación caduca después de %{expires_in_minutes} minutos."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr "Si pierde los códigos de recuperación, puede generar otros nuevos, inv
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr "Conectar repositorios desde"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "URL de importación bloqueada: %{message}"
@@ -20131,6 +20445,9 @@ msgstr "Solicitando a su %{provider} los repositorios fallados"
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "No se pudieron importar los datos remotos."
@@ -21036,6 +21353,9 @@ msgstr "Incompleto"
msgid "Increase"
msgstr "Incrementar"
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr "Ãndice"
@@ -21257,6 +21577,9 @@ msgstr "Añadir una integración"
msgid "Integrations|Add namespace"
msgstr "Añadir espacio de nombres"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Todos los detalles"
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Habilitar comentarios"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr "Introduzca su alias"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Patrón de intervalo"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr "Está usando el asiento de licencia:"
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr "Se ha producido un error al cargar las incidencias. Por favor, inténtel
msgid "IssueAnalytics|Issue"
msgstr "Incidencia"
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr "Hito"
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr "Última actualización con éxito"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr "Verficado por última vez"
@@ -23324,7 +23662,7 @@ msgstr "Aprenda como %{no_packages_link_start}publicar y compartir sus paquetes%
msgid "Learn more"
msgstr "Conozca más"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr "Haga que todos en su equipo sean más productivos, independientemente de
msgid "Make issue confidential"
msgstr "Convertir este problema en confidencial"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,12 +24505,12 @@ msgstr "Administrar proyectos"
msgid "Manage two-factor authentication"
msgstr "Administrar autenticación de dos factores"
-msgid "Manage your license"
-msgstr "Administrar su licencia"
-
msgid "Manage your project's triggers"
msgstr ""
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "Cuenta gestionada"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr "Marcado este %{noun} como listo."
@@ -24278,7 +24631,7 @@ msgstr "Marcar esta incidencia como incidencia relacionada con %{issue_ref}."
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr "Incidencias no iniciadas (abiertas y no asignadas)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr "Replicar usuario"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Repositorios replicados"
@@ -25933,6 +26295,9 @@ msgstr "El nombre ya está en uso."
msgid "Name new label"
msgstr "Nombre de la nueva etiqueta"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Nombre:"
@@ -26147,6 +26512,9 @@ msgstr "Nueva Programación del Pipeline"
msgid "New Project"
msgstr "Nuevo proyecto"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Nuevo requisito"
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "Número de commits"
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} en %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr "Más información sobre Auto DevOps"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr "Hito cambiado a %{milestone}"
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline %{pipeline_link} activado por"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr "lenguajes soportados actualmente"
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "%{jobs} completado con éxito en %{stages}."
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "El objeto no existe en el servidor o no tiene permisos para acceder a él"
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Oct"
@@ -27287,6 +27778,9 @@ msgstr "Rotaciones"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr "Seleccionar participante"
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr "Reemplazado"
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Eliminar la versión del paquete"
msgid "PackageRegistry|Delete package"
msgstr "Eliminar paquete"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr "Nivel de instancia"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr "Paquete no válido: se ha producido un error en la extracción de metadatos"
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Aprenda a %{noPackagesLinkStart}publicar y compartir sus paquetes%{noPackagesLinkEnd} con GitLab."
@@ -28197,15 +28697,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr "Registro de paquetes"
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
msgid "PackageRegistry|Package deleted successfully"
msgstr "Paquete eliminado correctamente"
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr "Archivo de paquete eliminado correctamente"
-
msgid "PackageRegistry|Package formats"
msgstr ""
@@ -28217,6 +28717,9 @@ msgstr[1] "El paquete tiene %{updatesCount} actualizaciones archivadas"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr "Paquete actualizado por el commit %{link} en la rama %{branch}, construido por pipeline %{pipeline}, y publicado en el registro %{datetime}"
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr "Mostrar comandos de PyPi"
msgid "PackageRegistry|Show Yarn commands"
msgstr "Mostrar comandos de Yarn"
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,8 +28831,8 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr "Está a punto de eliminar %{filename}. Esta es una acción destructiva que puede hacer que su paquete sea inutilizable. ¿Está seguro?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "Está a punto de eliminar %{name}, esta operación es irreversible, ¿está seguro?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr "Pausar"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Activos"
msgid "PipelineSchedules|All"
msgstr "Todos"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inactivos"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Próxima Ejecución"
@@ -28960,15 +29472,27 @@ msgstr "Ninguno"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Proporcione una descripción breve para este pipeline"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Tomar posesión"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Destino"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variables"
@@ -29083,6 +29607,12 @@ msgstr "La configuración de los pipelines para '%{project_name}' se actualizó
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr "Por favor, escriba %{phrase_code} para continuar o cierre esta ventana m
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "Utilice este formulario para informar a los administradores sobre los usuarios que crean spam en las incidencias, en los comentarios o se comportan de una manera inadecuada."
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Espere un momento; esta página se actualizará automáticamente cuando esté lista."
@@ -29773,6 +30306,9 @@ msgstr "Por favor espere mientras nos conectamos a su repositorio."
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Por favor espere mientras importamos el repositorio por usted."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "Pods en uso"
@@ -29833,6 +30369,9 @@ msgstr "Preferencias"
msgid "Preferences saved."
msgstr "Preferencias guardadas."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Comportamiento"
@@ -29944,6 +30483,9 @@ msgstr "Preferencias de hora"
msgid "Preferences|Use relative times"
msgstr "Utilizar tiempos relativos"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr "Activo"
msgid "Profiles|Add key"
msgstr "Añadir clave"
-msgid "Profiles|Add status emoji"
-msgstr "Añadir emoji de estado"
-
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 "Se muestra un indicador junto a su nombre y su avatar."
-
msgid "Profiles|Avatar cropper"
msgstr "Redimensionador de avatar"
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "Bio"
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr "Cambiar el nombre de usuario"
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "Ciudad, país"
-msgid "Profiles|Clear status"
-msgstr "Borrar estado"
-
msgid "Profiles|Commit email"
msgstr "Dirección de correo electrónico para los commits"
@@ -30211,6 +30741,9 @@ msgstr "Conectar un servicio para iniciar sesión."
msgid "Profiles|Connected Accounts"
msgstr "Cuentas conectadas"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Ruta actual: %{path}"
@@ -30448,9 +30981,6 @@ msgstr "El uso de emojis en los nombres parece divertido, pero por favor, intent
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "¿Cuál es su estado?"
-
msgid "Profiles|Who you represent or work for."
msgstr "A quién representa o para quien trabaja."
@@ -30496,9 +31026,6 @@ msgstr "Su nombre se configuró automáticamente en función de su cuenta %{prov
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Su estado"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Solo se pueden enviar commits firmados a este repositorio."
@@ -31183,6 +31722,9 @@ msgstr "Visibilidad del proyecto"
msgid "ProjectSettings|Public"
msgstr "Público"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Repositorio"
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "IOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr "Actividad"
@@ -31948,6 +32493,9 @@ msgstr "Permitido push"
msgid "ProtectedBranch|Allowed to push:"
msgstr "Permitido push:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Rama"
@@ -31984,6 +32532,9 @@ msgstr "Ramas protegidas (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr "Por defecto"
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Leer más"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr "Registrar un dispositivo universal de autenticación de dos factores (U2
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "El repositorio debe contener al menos 1 archivo."
@@ -33825,6 +34409,9 @@ msgstr "¡Token de suplantación revocado %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Se ha revocado el token de acceso personal %{personal_access_token_name}!"
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr "Rol"
msgid "Rollback"
msgstr "Restaurar"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -34070,6 +34660,9 @@ msgstr "Runners|Empezar con los ejecutores"
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr "¿Cómo actualizamos el ejecutor de GitLab?"
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "Token de registro"
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "Los ejecutores son los agentes de GitLab que ejecutan sus trabajos de CI/CD. Siga las %{linkStart}instrucciones de instalación y registro%{linkEnd} para configurar un ejecutor."
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr "Hasta la fecha"
@@ -34560,9 +35171,6 @@ msgstr "Guardar proyecto."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr "Buscar autores"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Buscar ramas"
@@ -34797,6 +35408,9 @@ msgstr "Buscar proyectos"
msgid "Search projects..."
msgstr "Buscar proyectos..."
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "No habilitado"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} más"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ", y %{count} más"
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Crear incidencia"
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr "vulnerabilidades de desarrollo"
@@ -35581,6 +36195,9 @@ msgstr "Descartada '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar descartados"
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Incidencia creada"
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "Estado"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Seleccionar formato de archivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr "Seleccionar página"
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr "Seleccione una plantilla de repositorio"
msgid "Select a template type"
msgstr "Seleccione un tipo de plantilla"
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Selecciona una zona horaria"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr "Seleccione la rama"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr "Seleccione los proyectos"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Seleccionar revisor(es)"
@@ -36289,6 +36918,9 @@ msgstr "Establecer la rama de destino a"
msgid "Set target branch to %{branch_name}."
msgstr "Establecer la rama de destino a %{branch_name}."
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr "Establecer el estado a Preparado"
@@ -36364,18 +36996,15 @@ msgstr "Establecer el peso"
msgid "Set weight to %{weight}."
msgstr "Establecer el peso a %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "Aparece un indicador junto a su nombre y su avatar"
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "Borrar estado"
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Editar estado"
@@ -36388,6 +37017,9 @@ msgstr "Establecer un estado"
msgid "SetStatusModal|Set status"
msgstr "Establecer estado"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Lo sentimos, no hemos podido establecer su estado. Por favor, inténtelo de nuevo más tarde."
@@ -36989,6 +37621,39 @@ msgstr "Escriba la palabra que mejor describa a su equipo."
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr "Sólido"
@@ -37295,6 +37963,9 @@ msgstr "Dirección de ordenación: Ascendente"
msgid "Sort direction: Descending"
msgstr "Dirección de ordenación: Descendente"
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr "Último Contacto"
msgid "SortOptions|Last created"
msgstr "Fecha de creación"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Menos popular"
@@ -37397,6 +38071,9 @@ msgstr "Destacados más antiguos"
msgid "SortOptions|Oldest updated"
msgstr "Actualizado más antiguo"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "Popularidad"
@@ -38297,8 +38974,8 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
-msgstr "Lavanda"
+msgid "SuggestedColors|Lavender"
+msgstr ""
msgid "SuggestedColors|Magenta-pink"
msgstr "Magenta-rosa"
@@ -38321,9 +38998,21 @@ msgstr "Rojo rosado"
msgid "SuggestedColors|Titanium yellow"
msgstr "Amarillo titanio"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,8 +39049,14 @@ msgstr "Activar suscripción"
msgid "SuperSonics|Activation code"
msgstr "Código de activación"
-msgid "SuperSonics|An error occurred while adding your subscription."
-msgstr "Se ha producido un error al añadir su suscripción."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr ""
msgid "SuperSonics|Billable users"
msgstr "Usuarios facturables"
@@ -38369,8 +39064,8 @@ msgstr "Usuarios facturables"
msgid "SuperSonics|Buy subscription"
msgstr "Comprar suscripción"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr "Se ha producido un error al activar la instancia debido a un problema de conectividad."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr ""
msgid "SuperSonics|Cloud licensing"
msgstr "Licencias en la nube"
@@ -38485,26 +39180,38 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr "No se puede mostrar tu %{subscriptionEntryName} en este momento. Por favor, actualice la página para volver a intentarlo."
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "Su suscripción"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr "Los detalles de su suscripción se sincronizarán en breve."
-msgid "SuperSonics|Your subscription is expired."
-msgstr "Su suscripción ha caducado."
+msgid "SuperSonics|Your subscription is expired"
+msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr "Se puede acceder al fragmento de código sin necesidad ningún tipo de autenticación."
@@ -39901,9 +40611,6 @@ msgstr "No hay datos disponibles."
msgid "There is no data available. Please change your selection."
msgstr "No hay datos disponibles. Por favor, cambie su selección."
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr "Este bloque es auto-referencial"
msgid "This board's scope is reduced"
msgstr "El alcance de este tablero es limitado"
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Esta tarea épica no existe o no tiene permisos suficientes."
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Esta es su sesión actual"
@@ -40642,6 +41376,9 @@ msgstr "Este proyecto está archivado y no se puede comentar en el."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr "Este proyecto será eliminado el %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr "Este proyecto se eliminará el %{date} , ya que se programó la eliminación de su grupo principal '%{parent_group_name}'."
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Para añadir la entrada manualmente, proporcione los siguientes detalles a la aplicación en su teléfono."
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir los usuarios internos, primero habilite nuevos usuarios externos"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr "Cambiar la descripción del commit"
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Ocultar/mostrar barra lateral"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr "Tamaño total de los artefactos: %{total_size}"
msgid "Total cores (CPUs)"
msgstr "Núcleos totales (CPUs)"
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr "Memoria total (GB)"
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "Volver a GitLab"
-msgid "Trials|Hey there"
-msgstr "Hola"
-
msgid "Trials|Skip Trial"
msgstr "Saltar periodo de prueba"
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 "Su prueba termina el %{boldStart}%{trialEndDate}%{boldEnd}. Esperamos que estés disfrutando de las características de GitLab %{planName}. Para mantener esas funciones después de que termine tu prueba, tendrás que comprar una suscripción. (También puedes elegir GitLab Premium si se ajusta a tus necesidades)"
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft} de almacenamiento comprado está disponible"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artefactos"
@@ -42350,10 +43104,10 @@ msgstr "Periodo actual de uso"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr "Repositorio"
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr "La identidad de usuario se ha eliminado correctamente."
msgid "User identity was successfully updated."
msgstr "La identidad de usuario se ha actualizado correctamente."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr "El usuario no está autorizado a resolver el hilo"
@@ -43126,9 +43880,6 @@ msgstr "Usuarios que solicitan acceso a"
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "Usuarios añadidos con éxito."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr "Ningún asignado - %{openingTag} asignarse a usted mismo %{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr "Sin asignar"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Ver gráfico"
@@ -43431,8 +44212,8 @@ msgstr "Ver documentación"
msgid "View eligible approvers"
msgstr "Ver aprobadores elegibles"
-msgid "View epics list"
-msgstr "Ver lista de tareas épicas"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Archivo"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,12 +44660,12 @@ msgstr "Imagen"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "Enlaces"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr "Método"
@@ -43891,6 +44675,9 @@ msgstr "Espacio de nombres"
msgid "Vulnerability|Project"
msgstr "Proyecto"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Severidad"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "Estado"
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr "No ha sido posible conectar al servidor de Prometheus. O el servidor ya
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Hemos detectado spam potencial en %{humanized_resource_name}. Por favor resuelva el reCAPTCHA para poder continuar."
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr "Eventos de despliegue"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "Activar la verificación SSL"
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "Eventos de las incidencias"
msgid "Webhooks|Job events"
msgstr "Eventos de los trabajos"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "Eventos de los miembros"
@@ -44260,6 +45071,12 @@ msgstr "Verificación SSL"
msgid "Webhooks|Secret token"
msgstr "Token secreto"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr "Agregar asignado"
msgid "WorkItem|Add assignees"
msgstr "Agregar asignados"
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr "Añadir tarea"
@@ -44734,9 +45554,15 @@ msgstr "Crear tarea"
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr "Puede crear un nuevo %{link}."
@@ -45188,6 +46023,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 add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr "Debe estar conectado para buscar en todo GitLab"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr "añadido"
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr "añadió una llamada de Zoom a esta incidencia"
@@ -46087,6 +46928,9 @@ msgstr "por"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr "Encontrado %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr "Informe completo"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr "comentario"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "comentado en %{link_to_project}"
@@ -46594,6 +47447,9 @@ msgstr "creado el %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr "límite de %{project_limit} alcanzado"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "falta"
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "mi-asombroso-grupo"
@@ -47493,9 +48357,6 @@ msgstr "o"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "total de %d prueba"
@@ -47639,6 +48500,9 @@ msgstr "eliminar el peso"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "eliminó una llamada de Zoom de esta incidencia"
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "Se ha producido un error al crear el merge request"
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "nombre de la etiqueta"
@@ -47845,6 +48717,11 @@ msgstr "actualizado %{time_ago}"
msgid "uploads"
msgstr "subidos"
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "avatar del usuario"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 1daa290c56b..8ba2aa55b63 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index bd627e90002..d1dcab0c699 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index c0ba0e81cc9..d0dadef061f 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 89b966c88fb..1f520e7303e 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 609bb34fc8b..e650c9c1beb 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr " %{start} à %{end}"
@@ -24,8 +24,8 @@ msgstr " (depuis %{timeoutSource})"
msgid " (squashes %{strongStart}%{count}%{strongEnd} commit)"
msgid_plural " (squashes %{strongStart}%{count}%{strongEnd} commits)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " (combiné avec %{strongStart}%{count}%{strongEnd} commit)"
+msgstr[1] " (combiné avec %{strongStart}%{count}%{strongEnd} commits)"
msgid " Collected %{time}"
msgstr " Collecté %{time}"
@@ -52,7 +52,7 @@ msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr " ou %{emphasisStart}!id demande de fusion%{emphasisEnd}"
msgid " or %{emphasisStart}#id%{emphasisEnd}"
-msgstr ""
+msgstr " ou %{emphasisStart}#id%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr " ou %{emphasisStart}#id ticket%{emphasisEnd}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] "%d contributeur supplémentaire"
msgstr[1] "%d contributeurs supplémentaires"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d utilisateur supplémentaire"
+msgstr[1] "%d utilisateurs supplémentaires"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d approbateur"
@@ -150,8 +155,8 @@ msgstr[1] "%d approbateurs (vous avez approuvé)"
msgid "%d artifact"
msgid_plural "%d artifacts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d artéfact"
+msgstr[1] "%d artéfacts"
msgid "%d assigned issue"
msgid_plural "%d assigned issues"
@@ -225,8 +230,8 @@ msgstr[1] "%d contributions"
msgid "%d contributor"
msgid_plural "%d contributors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d contributeur"
+msgstr[1] "%d contributeurs"
msgid "%d day"
msgid_plural "%d days"
@@ -305,8 +310,8 @@ msgstr[1] "%d tickets importés avec succès avec l'étiquette"
msgid "%d job"
msgid_plural "%d jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tâche"
+msgstr[1] "%d tâches"
msgid "%d layer"
msgid_plural "%d layers"
@@ -380,8 +385,8 @@ msgstr[1] "%d projets sélectionnés"
msgid "%d push"
msgid_plural "%d pushes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d poussée"
+msgstr[1] "%d poussées"
msgid "%d remaining"
msgid_plural "%d remaining"
@@ -390,8 +395,8 @@ msgstr[1] "%d restants"
msgid "%d reply"
msgid_plural "%d replies"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d réponse"
+msgstr[1] "%d réponses"
msgid "%d second"
msgid_plural "%d seconds"
@@ -400,8 +405,8 @@ msgstr[1] "%d secondes"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d étape"
+msgstr[1] "%d étapes"
msgid "%d star"
msgid_plural "%d stars"
@@ -525,8 +530,8 @@ msgstr "%{completedCount} poids complété"
msgid "%{completedCount} of %{count} checklist item completed"
msgid_plural "%{completedCount} of %{count} checklist items completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{completedCount} élément de la liste de contrôle sur %{count} terminé"
+msgstr[1] "%{completedCount} éléments de la liste de contrôle sur %{count} terminés"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} sur %{totalWeight} du poids complété"
@@ -535,7 +540,7 @@ msgid "%{completed} of %{total} issues closed"
msgstr "%{completed} sur %{total} tickets fermés"
msgid "%{completed} of %{total} weight completed"
-msgstr ""
+msgstr "%{completed} poids sur %{total} complété"
msgid "%{cores} cores"
msgstr "%{cores} cœurs"
@@ -707,7 +712,7 @@ msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sera supprimé ! Êtesâ€vous sûr ?"
msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
-msgstr ""
+msgstr "%{issuable_class_name} n'existe pas ou vous n'avez pas la permission d'y ajouter une entrée de temps passé."
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(s) déjà assigné(s)"
@@ -761,7 +766,7 @@ msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Espace de noms :%{labelEnd} %{namespace}"
msgid "%{labelStart}Project:%{labelEnd} %{project}"
-msgstr ""
+msgstr "%{labelStart}Projet :%{labelEnd} %{project}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Scanner :%{labelEnd} %{scanner}"
@@ -776,7 +781,7 @@ msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Outil :%{labelEnd} %{reportType}"
msgid "%{labelStart}URL:%{labelEnd} %{url}"
-msgstr ""
+msgstr "%{labelStart}URL :%{labelEnd} %{url}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Réponse non modifiée :%{labelEnd} %{headers}"
@@ -898,10 +903,10 @@ msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} ouverts, %{closedIssues} fermés"
msgid "%{over_limit_message} To get more members, an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "%{over_limit_message} Pour pouvoir disposer de plus de membres, un propriétaire du groupe peut commencer une période d'essai ou faire une mise à niveau vers une édition payante."
msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
-msgstr ""
+msgstr "%{over_limit_message} Pour obtenir plus de sièges, %{link_start}passez à une édition payante%{link_end}."
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed} %% utilisé(s)"
@@ -983,13 +988,13 @@ msgstr[1] "Les résultats de %{securityScanner} ne sont pas disponibles, car auc
msgid "%{selectedLabelsCount} label"
msgid_plural "%{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{selectedLabelsCount} étiquette"
+msgstr[1] "%{selectedLabelsCount} étiquettes"
msgid "%{selectedProjectsCount} project"
msgid_plural "%{selectedProjectsCount} projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{selectedProjectsCount} projet"
+msgstr[1] "%{selectedProjectsCount} projets"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1007,35 +1012,30 @@ msgid "%{size} bytes"
msgstr "%{size} octets"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch} dans %{targetBranch}"
msgid "%{source} %{copyButton} into %{target}"
msgstr ""
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} a été soumis à Akismet avec succès."
msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
-msgstr ""
+msgstr "%{spanStart}à la ligne%{spanEnd} %{errorLine}%{errorColumn}"
msgid "%{spanStart}in%{spanEnd} %{errorFn}"
-msgstr ""
+msgstr "%{spanStart}dans%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
-msgstr ""
-
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr "%{start} à %{end}"
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
msgid "%{strongStart}%{count}%{strongEnd} commit"
msgid_plural "%{strongStart}%{count}%{strongEnd} commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strongStart}%{count}%{strongEnd} commit"
+msgstr[1] "%{strongStart}%{count}%{strongEnd} commits"
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1052,26 +1052,31 @@ msgstr[1] "%{strong_start}%{commit_count}%{strong_end} commits"
msgid "%{strong_start}%{count} approval rule%{strong_end} requires eligible members to approve before merging."
msgid_plural "%{strong_start}%{count} approval rules%{strong_end} require eligible members to approve before merging."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{count} règle d'approbation%{strong_end} exige que des membres éligibles donnent leur approbation avant la fusion."
+msgstr[1] "%{strong_start}%{count} règles d'approbation%{strong_end} exigent que des membres éligibles donnent leur approbation avant la fusion."
msgid "%{strong_start}%{count} eligible member%{strong_end} must approve to merge."
msgid_plural "%{strong_start}%{count} eligible members%{strong_end} must approve to merge."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{count} membre éligible%{strong_end} doit approuver la fusion."
+msgstr[1] "%{strong_start}%{count} membres éligibles%{strong_end} doivent approuver la fusion."
msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{count} membre%{strong_end} doit approuver la fusion. Toute personne ayant au minimum le rôle de Développeur peut donner son approbation."
+msgstr[1] "%{strong_start}%{count} membres%{strong_end} doivent approuver la fusion. Toute personne ayant au minimum le rôle de Développeur peut donner son approbation."
+
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} point"
+msgstr[1] "%{strong_start}%{errors}%{strong_end} points"
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
msgid "%{strong_start}%{release_count}%{strong_end} Release"
msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{release_count}%{strong_end} Version"
+msgstr[1] "%{strong_start}%{release_count}%{strong_end} Versions"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
@@ -1079,26 +1084,23 @@ msgstr[0] "%{strong_start}%{tag_count}%{strong_end} étiquette"
msgstr[1] "%{strong_start}%{tag_count}%{strong_end} étiquettes"
msgid "%{tabname} changed"
-msgstr ""
+msgstr "%{tabname} modifié"
msgid "%{tags} tag per image name"
-msgstr ""
+msgstr "%{tags} étiquette par nom d'image"
msgid "%{tags} tags per image name"
-msgstr ""
+msgstr "%{tags} étiquettes par nom d'image"
msgid "%{tag}-%{evidence}-%{filename}"
msgstr ""
msgid "%{template_project_id} is unknown or invalid"
-msgstr ""
+msgstr "%{template_project_id} est inconnu ou invalide"
msgid "%{text} is available"
msgstr "%{text} est disponible"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1106,7 +1108,7 @@ msgid "%{timebox_type} must have a start and due date"
msgstr ""
msgid "%{time} UTC"
-msgstr ""
+msgstr "%{time} UTC"
msgid "%{title} %{operator} %{threshold}"
msgstr ""
@@ -1115,82 +1117,94 @@ msgid "%{title} changes"
msgstr "Changements %{title}"
msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} libre)"
msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} libre)"
msgid "%{totalWeight} total weight"
-msgstr ""
+msgstr "%{totalWeight} poids total"
msgid "%{total_warnings} warning(s) found:"
-msgstr ""
+msgstr "%{total_warnings} avertissement(s) trouvé(s) :"
msgid "%{total} remaining issue weight"
msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
+msgstr "%{total} avertissements trouvés : affichage des %{warningsDisplayed} premiers"
+
+msgid "%{type} must be a %{help_link}"
msgstr ""
msgid "%{type} only supports %{name} name"
msgstr ""
msgid "%{userName} (cannot merge)"
-msgstr ""
+msgstr "%{userName} (ne peut pas fusionner)"
msgid "%{userName}'s avatar"
-msgstr ""
+msgstr "Avatar de %{userName}"
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) a été retiré de %{rotation} en %{schedule} dans %{project}. "
msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project_link}: "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) a été retiré des politiques d'escalade suivantes de %{project_link} : "
msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project}:"
-msgstr ""
+msgstr "%{user_name} (%{user_username}) a été retiré des politiques d'escalade suivantes de %{project} :"
msgid "%{user_name} profile page"
msgstr "Profil de %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
-msgstr ""
+msgstr "%{username} a fait la demande d'un compte GitLab sur votre instance %{host} :"
+
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr "%{username} a marqué la demande de fusion %{mr_link} comme brouillon"
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr "%{username} a marqué la demande de fusion %{mr_link} comme étant prête"
msgid "%{username}'s avatar"
-msgstr ""
+msgstr "Avatar de %{username}"
msgid "%{user} created a merge request: %{mr_link}"
msgstr "%{user} a créé une demande de fusion : %{mr_link}"
msgid "%{user} created an epic: %{epic_link}"
-msgstr ""
+msgstr "%{user} a créé une épopée : %{epic_link}"
msgid "%{user} created an issue: %{issue_link}"
msgstr "%{user} a créé un ticket : %{issue_link}"
msgid "%{value} is not included in the list"
-msgstr ""
+msgstr "%{value} ne fait pas partie de la liste"
msgid "%{value} s"
-msgstr ""
+msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
-msgstr ""
+msgstr "%{verb} %{time_spent_value} temps passé."
+
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} ce(tte) %{noun} comme brouillon."
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} ce(tte) %{noun} comme étant prêt(e)."
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
-msgstr ""
+msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} vous permet d'envoyer des notifications aux applications web en réponse à des événements dans un groupe ou dans un projet."
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
-msgstr ""
+msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} vous permet d'envoyer des notifications aux applications web en réponse aux événements d'un groupe ou d'un projet. Nous recommandons d'utiliser une %{integrations_link_start}intégration%{link_end} plutôt qu'un webhook."
msgid "%{widget} options"
msgstr ""
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
-msgstr ""
+msgstr "Les %{wildcards_link_start}caractères génériques%{wildcards_link_end} tels que %{code_tag_start}v*%{code_tag_end} ou %{code_tag_start}*-release%{code_tag_end} sont pris en charge."
msgid "'%{data}' at %{location} does not match format: %{format}"
msgstr ""
@@ -1202,7 +1216,7 @@ msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
msgstr ""
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "« %{data} » à %{location} n'est pas de type : %{type}"
msgid "'%{data}' at %{location} is not one of: %{enum}"
msgstr ""
@@ -1214,13 +1228,13 @@ msgid "'%{level}' is not a valid visibility level"
msgstr ""
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » créée"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » supprimée"
msgid "'%{name}' Value Stream saved"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » enregistrée"
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1230,62 +1244,62 @@ msgstr ""
msgid "(%d closed)"
msgid_plural "(%d closed)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "(%d fermé)"
+msgstr[1] "(%d fermés)"
msgid "(%{mrCount} merged)"
-msgstr ""
+msgstr "(%{mrCount} fusionnés)"
msgid "(%{value}) has already been taken"
-msgstr ""
+msgstr "(%{value}) a déjà été pris"
msgid "(+%{count}&nbsp;rules)"
-msgstr ""
+msgstr "(+%{count}&nbsp;règles)"
msgid "(Group Managed Account)"
msgstr ""
msgid "(No changes)"
-msgstr ""
+msgstr "(Aucun changement)"
msgid "(UTC %{offset}) %{timezone}"
-msgstr ""
+msgstr "(UTC %{offset}) %{timezone}"
msgid "(check progress)"
-msgstr ""
+msgstr "(suivre la progression)"
msgid "(deleted)"
-msgstr ""
+msgstr "(supprimé)"
msgid "(expired)"
-msgstr ""
+msgstr "(expiré)"
msgid "(leave blank if you don't want to change it)"
-msgstr ""
+msgstr "(laissez vide si vous ne souhaitez pas faire de modification)"
msgid "(max size 15 MB)"
-msgstr ""
+msgstr "(taille max 15 Mo)"
msgid "(optional)"
-msgstr ""
+msgstr "(facultatif)"
msgid "(removed)"
-msgstr ""
+msgstr "(supprimé)"
msgid "(revoked)"
-msgstr ""
+msgstr "(révoqué)"
msgid "(this user)"
-msgstr ""
+msgstr "(cet utilisateur)"
msgid "(we need your current password to confirm your changes)"
-msgstr ""
+msgstr "(nous avons besoin de votre mot de passe actuel pour confirmer vos modifications)"
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* Toutes les heures sont en UTC sauf indication contraire"
msgid "*Required"
-msgstr ""
+msgstr "*Requis"
msgid "+ %{amount} more"
msgstr ""
@@ -1301,8 +1315,8 @@ msgstr ""
msgid "+%d more"
msgid_plural "+%d more"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "+%d en plus"
+msgstr[1] "+%d en plus"
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1329,7 +1343,7 @@ msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status
msgstr ""
msgid "- Add or remove a user."
-msgstr ""
+msgstr "- Ajouter ou supprimer un utilisateur."
msgid "- Available to run jobs."
msgstr ""
@@ -1338,35 +1352,35 @@ msgid "- Create or close an issue."
msgstr "- Créer ou fermer un ticket."
msgid "- Create, update, or delete a merge request."
-msgstr ""
+msgstr "- Créer, mettre à jour ou supprimer une demande de fusion."
msgid "- Event"
msgid_plural "- Events"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "- Événement"
+msgstr[1] "- Événements"
msgid "- Go to the Activity page for %{project_name}."
-msgstr ""
+msgstr "- Allez sur la page Activité de %{project_name}."
msgid "- List the visible events for %{project_name} using the Events API %{events_api_link}."
-msgstr ""
+msgstr "- Lister les événements visibles pour %{project_name} à l'aide de l'API Events %{events_api_link}."
msgid "- Not available to run jobs."
msgstr ""
msgid "- Push code to the repository."
-msgstr ""
+msgstr "- Pousser du code vers le dépôt."
msgid "- Select -"
-msgstr ""
+msgstr "- Sélectionner -"
msgid "- User"
msgid_plural "- Users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "- Utilisateur"
+msgstr[1] "- Utilisateurs"
msgid "- View the last_activity_at attribute for %{project_name} using the Project API %{projects_api_link}."
-msgstr ""
+msgstr "- Afficher l'attribut last_activity_at pour %{project_name} à l'aide de l'API Project %{projects_api_link}."
msgid "- of - issues closed"
msgstr "- de - tickets fermés"
@@ -1378,16 +1392,16 @@ msgid "- show less"
msgstr "- en montrer moins"
msgid "."
-msgstr ""
+msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "/day"
-msgstr ""
+msgstr "/jour"
msgid "0 bytes"
-msgstr ""
+msgstr "0 octets"
msgid "1 Code quality finding"
msgid_plural "%d Code quality findings"
@@ -1401,8 +1415,8 @@ msgstr[1] "%d jours"
msgid "1 Issue"
msgid_plural "%d Issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Ticket"
+msgstr[1] "%d Tickets"
msgid "1 closed issue"
msgid_plural "%{issues} closed issues"
@@ -1416,28 +1430,28 @@ msgstr[1] "%{merge_requests} demandes de fusion fermées"
msgid "1 day"
msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 jour"
+msgstr[1] "%d jours"
msgid "1 day remaining"
msgid_plural "%d days remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 jour restant"
+msgstr[1] "%d jours restant"
msgid "1 day selected"
msgid_plural "%d days selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 jour sélectionné"
+msgstr[1] "%d jours sélectionnés"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 clé de déploiement"
+msgstr[1] "%d clés de déploiement"
msgid "1 follower"
msgid_plural "%{count} followers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 abonné"
+msgstr[1] "%{count} abonnés"
msgid "1 group"
msgid_plural "%d groups"
@@ -1446,33 +1460,33 @@ msgstr[1] "%d groupes"
msgid "1 hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 heure"
+msgstr[1] "%d heures"
msgid "1 issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 demande sélectionnée"
+msgstr[1] "%d demandes sélectionnées"
msgid "1 merge request selected"
msgid_plural "%d merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 demande de fusion sélectionnée"
+msgstr[1] "%d demandes de fusion sélectionnées"
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 demande de fusion fusionnée"
+msgstr[1] "%{merge_requests} demandes de fusion effectuées"
msgid "1 minute"
msgid_plural "%d minutes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 minute"
+msgstr[1] "%d minutes"
msgid "1 month remaining"
msgid_plural "%d months remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 mois restant"
+msgstr[1] "%d mois restant"
msgid "1 open issue"
msgid_plural "%{issues} open issues"
@@ -1501,31 +1515,31 @@ msgstr[1] "%{num} utilisateurs"
msgid "1 week remaining"
msgid_plural "%d weeks remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 semaine restante"
+msgstr[1] "%d semaines restantes"
msgid "1 year remaining"
msgid_plural "%d years remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 an restant"
+msgstr[1] "%d ans restants"
msgid "1-9 contributions"
-msgstr ""
+msgstr "1-9 contributions"
msgid "10-19 contributions"
-msgstr ""
+msgstr "10-19 contributions"
msgid "1000+"
-msgstr ""
+msgstr "1000+"
msgid "192.168.0.0/24 or 2001:0DB8:1234::/48"
-msgstr ""
+msgstr "192.168.0.0/24 ou 2001:0DB8:1234::/48"
msgid "1st contribution!"
msgstr "1ʳᵉ contribution !"
msgid "20-29 contributions"
-msgstr ""
+msgstr "20-29 contributions"
msgid "2FA"
msgstr "Authentification à deux facteurs"
@@ -1534,10 +1548,10 @@ msgid "2FADevice|Registered On"
msgstr ""
msgid "3 hours"
-msgstr ""
+msgstr "3 heures"
msgid "30 minutes"
-msgstr ""
+msgstr "30 minutes"
msgid "30+ contributions"
msgstr ""
@@ -1558,13 +1572,13 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Veuillez contacter votre administrateur GitLab si vous pensez qu’il s’agit d’une erreur."
msgid "409|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "Veuillez contacter votre administrateur GitLab si vous pensez qu’il s’agit d’une erreur."
msgid "409|There was a conflict with your request."
-msgstr ""
+msgstr "Il y a eu un conflit avec votre demande."
msgid "8 hours"
-msgstr ""
+msgstr "8 heures"
msgid ":%{startLine} to %{endLine}"
msgstr ""
@@ -1597,22 +1611,22 @@ msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is
msgstr ""
msgid "A Work Item can be a parent or a child, but not both."
-msgstr ""
+msgstr "Un Élément de Travail peut être un parent ou un enfant, mais pas les deux à la fois."
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
msgid "A basic template for developing Linux programs using Kotlin Native"
-msgstr ""
+msgstr "Un modèle de base pour développer des programmes Linux à l'aide de Kotlin Native"
msgid "A complete DevOps platform"
msgstr ""
msgid "A confidential issue cannot have a parent that already has non-confidential children."
-msgstr ""
+msgstr "Un ticket confidentiel ne peut pas avoir un parent qui a déjà un enfant non confidentiel."
msgid "A confidential work item cannot have a parent that already has non-confidential children."
-msgstr ""
+msgstr "Un élément de travail confidentiel ne peut pas avoir un parent qui a déjà un enfant non confidentiel."
msgid "A default branch cannot be chosen for an empty project."
msgstr "Une branche par défaut ne peut pas être choisie pour un projet vide."
@@ -1624,28 +1638,28 @@ msgid "A different reason"
msgstr ""
msgid "A file has been changed."
-msgstr ""
+msgstr "Un fichier a été modifié."
msgid "A file was not found."
-msgstr ""
+msgstr "Un fichier n'a pas été trouvé."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr ""
msgid "A file with this name already exists."
-msgstr ""
+msgstr "Un fichier portant ce nom existe déjà."
msgid "A group is a collection of several projects"
-msgstr ""
+msgstr "Un groupe est un ensemble de plusieurs projets"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
-msgstr ""
+msgstr "Un groupe représente votre entreprise dans GitLab. Ils vous permettent de gérer les utilisateurs et de collaborer sur plusieurs projets."
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
-msgstr ""
+msgstr "Une limite de %{ci_project_subscriptions_limit} abonnements depuis ou vers un projet est appliquée."
msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
@@ -1654,7 +1668,7 @@ msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
-msgstr ""
+msgstr "Un nouveau pipeline Auto DevOps a été créé, allez à la page Pipelines pour plus de détails"
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 ""
@@ -1663,31 +1677,37 @@ msgid "A new Release %{tag} for %{name} was published. Visit the Releases page t
msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
-msgstr ""
-
-msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Une nouvelle adresse e-mail a été ajoutée à votre compte GitLab: %{email}"
msgid "A new personal access token has been created"
-msgstr ""
+msgstr "Un nouveau jeton d'accès personnel a été créé"
msgid "A new personal access token, named %{token_name}, has been created."
-msgstr ""
+msgstr "Un nouveau jeton d'accès personnel, nommé %{token_name}, a été créé."
msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
+msgstr "Une épopée non-confidentielle ne peut pas être assignée à une épopée parent confidentielle"
msgid "A non-confidential issue cannot have a confidential parent."
-msgstr ""
+msgstr "Un ticket non confidentiel ne peut pas avoir un parent confidentiel."
msgid "A non-confidential work item cannot have a confidential parent."
-msgstr ""
+msgstr "Un élément de travail non confidentiel ne peut pas avoir un parent confidentiel."
msgid "A page with that title already exists"
msgstr "Une page avec ce titre existe déjà"
+msgid "A personal access token has been revoked"
+msgstr "Un jeton d'accès personnel a été révoqué"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr "Un jeton d'accès personnel, nommé %{code_start}%{token_name}%{code_end}, a été révoqué."
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr "Un jeton d'accès personnel, nommé %{token_name}, a été révoqué."
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr ""
+msgstr "Un site en pur HTML utilisant Netlify pour la CI/CD à la place de GitLab, mais tout en proposant toutes les autres fonctionnalités de GitLab"
msgid "A platform value can be web, mob or app."
msgstr ""
@@ -1702,22 +1722,22 @@ msgid "A project containing issues for each audit inquiry in the HIPAA Audit Pro
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 ""
+msgstr "Le nom du dépôt d'un projet définit son URL (celle que vous utilisez pour accéder au projet via un navigateur) ainsi que son emplacement sur le disque de fichiers où GitLab est installé. %{link_start}En savoir plus.%{link_end}"
msgid "A quarterly reconciliation is due on %{date}"
-msgstr ""
+msgstr "Un rapprochement trimestriel a lieu le %{date}"
msgid "A ready-to-go template for use with Android apps"
-msgstr ""
+msgstr "Un modèle prêt à l’emploi à utiliser pour les applications Android"
msgid "A ready-to-go template for use with iOS Swift apps"
-msgstr ""
+msgstr "Un modèle prêt à l’emploi à utiliser pour les applications iOS en Swift"
msgid "A rebase is already in progress."
-msgstr ""
+msgstr "Un rebase est déjà en cours."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
-msgstr ""
+msgstr "Une connexion à votre compte a été faite à partir de l'adresse IP suivante : %{ip}"
msgid "A title is required"
msgstr "Un titre est requis"
@@ -1729,7 +1749,7 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr ""
msgid "API"
-msgstr ""
+msgstr "API"
msgid "API Fuzzing"
msgstr ""
@@ -1744,79 +1764,79 @@ msgid "API Token"
msgstr ""
msgid "API key"
-msgstr ""
+msgstr "Clé de l'API"
msgid "API?"
msgstr ""
msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
-msgstr ""
+msgstr "$VARIABLE_WITH_PASSWORD"
msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
-msgstr ""
+msgstr "$VARIABLE_WITH_USERNAME"
msgid "APIFuzzing|API Fuzzing Configuration"
-msgstr ""
+msgstr "Configuration de l'API Fuzzing"
msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
-msgstr ""
+msgstr "Choisissez une méthode"
msgid "APIFuzzing|Choose a profile"
-msgstr ""
+msgstr "Choisissez un profil"
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Configurez les valeurs pour l'authentification HTTP de base. D'autres méthodes d'authentification sont prises en charge. %{linkStart}En savoir plus%{linkEnd}."
msgid "APIFuzzing|Customize your project's API fuzzing configuration options and copy the code snippet to your .gitlab-ci.yml file to apply any changes. Note that this tool does not reflect or update your .gitlab-ci.yml file automatically. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
msgstr ""
msgid "APIFuzzing|Enable authentication"
-msgstr ""
+msgstr "Activer l'authentification"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
-msgstr ""
+msgstr "Entrez le nom de la variable CI contenant le mot de passe. Par exemple : $VARIABLE_WITH_PASSWORD."
msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
-msgstr ""
+msgstr "Entrez le nom de la variable CI contenant le nom d'utilisateur. Par exemple : $VARIABLE_WITH_USERNAME."
msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
+msgstr "Chemin de fichier ou URL vers les APIs à tester. Par exemple, dossier/exemple_fuzz.har. Les fichiers HAR peuvent contenir des informations sensibles comme des jetons d'authentification, des clés d'API ou des cookies de session. Nous vous conseillons d'examiner le contenu des fichiers HAR avant de les ajouter à un dépôt."
msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
-msgstr ""
+msgstr "Chemin de fichier ou URL vers la spécification OpenAPI. Par exemple, dossier/openapi.json ou http://www.exemple.com/openapi.json."
msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
-msgstr ""
+msgstr "Chemin de fichier ou URL des requêtes à tester. Par exemple, dossier/exemple.collection_postman.json."
msgid "APIFuzzing|Generate code snippet"
-msgstr ""
+msgstr "Générer un extrait de code"
msgid "APIFuzzing|Make sure your credentials are secured"
-msgstr ""
+msgstr "Assurez-vous que vos identifiants sont sécurisés"
msgid "APIFuzzing|Password for basic authentication"
-msgstr ""
+msgstr "Mot de passe pour l'authentification de base"
msgid "APIFuzzing|Predefined profiles"
-msgstr ""
+msgstr "Profils prédéfinis"
msgid "APIFuzzing|Scan mode"
-msgstr ""
+msgstr "Mode d'analyse"
msgid "APIFuzzing|Scan profile"
-msgstr ""
+msgstr "Profil d'analyse"
msgid "APIFuzzing|Show code snippet for the profile"
-msgstr ""
+msgstr "Afficher l'extrait de code du profil"
msgid "APIFuzzing|Target URL"
-msgstr ""
+msgstr "URL cible"
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr ""
+msgstr "Il existe trois façons d'effectuer des analyses."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr ""
@@ -1828,25 +1848,25 @@ msgid "APIFuzzing|Tip: Insert this part below all stages"
msgstr ""
msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
-msgstr ""
+msgstr "Pour éviter une faille de sécurité, les infos d'authentification doivent être ajoutées sous la forme d'une %{ciVariablesLinkStart}variable CI%{ciVariablesLinkEnd}. Un utilisateur disposant de droits d'accès mainteneur peut gérer les variables CI dans la section %{ciSettingsLinkStart}Paramètres%{ciSettingsLinkEnd}. Nous avons identifié que nous n'êtes pas un mainteneur. Soumettez vos modifications puis assignez-les à un mainteneur pour mettre à jour les identifiants avant la fusion."
msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
-msgstr ""
+msgstr "Pour éviter une faille de sécurité, les infos d'authentification doivent être ajoutées sous la forme d'une %{ciVariablesLinkStart}variable CI%{ciVariablesLinkEnd}. En tant qu'utilisateur disposant de droits d'accès mainteneur, vous pouvez gérer les variables CI dans la section %{ciSettingsLinkStart}Paramètres%{ciSettingsLinkEnd}."
msgid "APIFuzzing|Username for basic authentication"
-msgstr ""
+msgstr "Nom d'utilisateur pour l'authentification de base"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
-msgstr ""
+msgstr "Vous pouvez avoir besoin de l’aide d’un mainteneur pour sécuriser vos identifiants."
msgid "APIFuzzing|folder/example.postman_collection.json"
-msgstr ""
+msgstr "dossier/exemple.collection_postman.json"
msgid "APIFuzzing|folder/example_fuzz.har"
-msgstr ""
+msgstr "dossier/exemple_fuzz.har"
msgid "APIFuzzing|folder/openapi.json"
-msgstr ""
+msgstr "dossier/openapi.json"
msgid "AWS Access Key"
msgstr ""
@@ -1858,16 +1878,16 @@ msgid "AWS Secret Access Key"
msgstr ""
msgid "AWS access key ID (Optional)"
-msgstr ""
+msgstr "ID de la clé d'accès AWS (facultatif)"
msgid "AWS secret access key (Optional)"
-msgstr ""
+msgstr "Clé d'accès secrète AWS (Facultatif)"
msgid "AWS service error: %{error}"
-msgstr ""
+msgstr "Erreur de service AWS : %{error}"
msgid "Abort"
-msgstr ""
+msgstr "Annuler"
msgid "About GitLab"
msgstr "À propos de GitLab"
@@ -1879,7 +1899,7 @@ msgid "About this feature"
msgstr "À propos de cette fonctionnalité"
msgid "About your company"
-msgstr ""
+msgstr "À propos de votre entreprise"
msgid "Abuse Reports"
msgstr "Rapports d’abus"
@@ -1900,10 +1920,10 @@ msgid "Acceptable for use in this project"
msgstr ""
msgid "Access Git repositories or the API."
-msgstr ""
+msgstr "Accéder aux dépôts Git ou à l'API."
msgid "Access Token"
-msgstr ""
+msgstr "Jeton d'Accès"
msgid "Access Tokens"
msgstr "Jetons d’accès"
@@ -1912,7 +1932,7 @@ msgid "Access denied for your LDAP account."
msgstr ""
msgid "Access denied: %{error}"
-msgstr ""
+msgstr "Accès refusé : %{error}"
msgid "Access expires"
msgstr ""
@@ -1924,22 +1944,22 @@ msgid "Access granted"
msgstr ""
msgid "Access requests"
-msgstr ""
+msgstr "Demandes d'accès"
msgid "Access to '%{classification_label}' not allowed"
msgstr "Accès à « %{classification_label} » non autorisé"
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "Clés de Déploiement"
msgid "AccessDropdown|Groups"
-msgstr ""
+msgstr "Groupes"
msgid "AccessDropdown|Roles"
-msgstr ""
+msgstr "Rôles"
msgid "AccessDropdown|Users"
-msgstr ""
+msgstr "Utilisateurs"
msgid "AccessTokens|Access Tokens"
msgstr ""
@@ -1954,13 +1974,13 @@ msgid "AccessTokens|Are you sure? Any issue email addresses currently in use wil
msgstr ""
msgid "AccessTokens|Copy feed token"
-msgstr ""
+msgstr "Copier le jeton de flux"
msgid "AccessTokens|Copy incoming email token"
-msgstr ""
+msgstr "Copier le jeton de courriel entrant"
msgid "AccessTokens|Copy static object token"
-msgstr ""
+msgstr "Copier le jeton d'objet statique"
msgid "AccessTokens|Created"
msgstr "Créé"
@@ -1975,13 +1995,13 @@ 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 ""
+msgstr "Gardez ce jeton secret. Quiconque s’en empare peut accéder aux objets statiques du dépôt à votre place. Si jamais cela arrivait, %{linkStart}réinitialisez ce jeton%{linkEnd}."
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 ""
+msgstr "Gardez ce jeton secret. Quiconque s’en empare peut créer des tickets à votre place. Si cela arrive, %{linkStart}réinitialisez-le%{linkEnd}."
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 ""
+msgstr "Gardez ce jeton secret. Quiconque s’en empare peut lire les flux RSS de l'activité et des tickets, ou celui de votre agenda, comme s'il s'agissait de vous. Si cela arrive, %{linkStart}réinitialisez-le%{linkEnd}."
msgid "AccessTokens|Personal Access Tokens"
msgstr ""
@@ -1990,7 +2010,7 @@ msgid "AccessTokens|Static object token"
msgstr ""
msgid "AccessTokens|The last time a token was used"
-msgstr ""
+msgstr "La dernière fois qu'un jeton a été utilisé"
msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
msgstr ""
@@ -2002,19 +2022,19 @@ msgid "AccessTokens|You can generate a personal access token for each applicatio
msgstr ""
msgid "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."
-msgstr ""
+msgstr "Votre jeton de flux vous authentifie lorsque votre lecteur RSS charge un flux RSS personnalisé ou lorsque votre application de calendrier charge un calendrier personnalisé. Il est visible dans les URL de ces flux."
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 "Votre jeton de courriel entrant vous authentifie lorsque vous créez un nouveau ticket par courriel et est inclus dans les adresses de courriel spécifiques de chaque projet personnel."
msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
-msgstr ""
+msgstr "Votre jeton d'objet statique vous authentifie lorsque des objets statiques du dépôt (tels que des archives ou des blobs) sont servis depuis un stockage externe."
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "En savoir plus"
msgid "AccessibilityReport|Message: %{message}"
-msgstr ""
+msgstr "Message : %{message}"
msgid "AccessibilityReport|New"
msgstr ""
@@ -2023,10 +2043,10 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr ""
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "Accessible à tout utilisateur connecté."
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "Accessible à tous, quelle que soit l'authentification."
msgid "Account"
msgstr "Compte"
@@ -2038,7 +2058,7 @@ msgid "Account and limit"
msgstr "Limitations du compte"
msgid "Account:"
-msgstr ""
+msgstr "Compte :"
msgid "Account: %{account}"
msgstr ""
@@ -2047,31 +2067,31 @@ msgid "AccountValidation|Fix your pipelines by validating your account"
msgstr ""
msgid "AccountValidation|I'll bring my own runners"
-msgstr ""
+msgstr "J'apporterai mes propres exécuteurs"
msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, you'll need to validate your account using one of our verification options. If you prefer not to, you can run pipelines by bringing your own runners and disabling shared runners for your project."
-msgstr ""
+msgstr "Afin d'utiliser des minutes CI/CD gratuites sur les exécuteurs partagés, vous devrez valider votre compte en utilisant une de nos options de vérification. Si vous préférez ne pas le faire, vous pouvez exécuter des pipelines en apportant vos propres exécuteurs et en désactivant les exécuteurs partagés de votre projet."
msgid "AccountValidation|Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
-msgstr ""
+msgstr "Il semblerait que vous devez valider votre compte pour utiliser des minutes CI/CD gratuites"
msgid "AccountValidation|Validate your account"
-msgstr ""
+msgstr "Valider votre compte"
msgid "AccountValidation|Verification is required to discourage and reduce the abuse on GitLab infrastructure. If you verify with a credit or debit card, %{strong_start}GitLab will not charge your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
-msgstr ""
+msgstr "La vérification est nécessaire pour décourager et réduire les abus sur l'infrastructure de GitLab. Si vous l'effectuez avec une carte de débit ou de crédit, %{strong_start}GitLab ne fera aucun prélèvement, celle-ci ne sera utilisée que pour la validation.%{strong_end} %{learn_more_link}"
msgid "Acknowledge"
msgstr ""
msgid "Action"
-msgstr ""
+msgstr "Action"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "Action à prendre lors de la réception d'une alerte. %{docsLink}"
msgid "Actions"
msgstr ""
@@ -2086,7 +2106,7 @@ msgid "Active"
msgstr "Actif"
msgid "Active %{accessTokenTypePlural} (%{totalAccessTokens})"
-msgstr ""
+msgstr "%{accessTokenTypePlural} actifs (%{totalAccessTokens})"
msgid "Active %{type} (%{token_length})"
msgstr ""
@@ -2095,19 +2115,19 @@ msgid "Active Sessions"
msgstr "Sessions actives"
msgid "Active chat names (%{count})"
-msgstr ""
+msgstr "Noms des discussions actives (%{count})"
msgid "Activity"
msgstr "Activité"
msgid "Activity|An error occurred while retrieving activity. Reload the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de l'activité. Rechargez la page pour réessayer."
msgid "Add"
msgstr "Ajouter"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "Ajouter « %{value} »"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -2125,10 +2145,10 @@ msgid "Add LICENSE"
msgstr ""
msgid "Add License"
-msgstr ""
+msgstr "Ajouter une licence"
msgid "Add New Site"
-msgstr ""
+msgstr "Ajouter un Nouveau Site"
msgid "Add README"
msgstr "Ajouter un README"
@@ -2143,22 +2163,22 @@ msgid "Add a GCP region"
msgstr ""
msgid "Add a GPG key"
-msgstr ""
+msgstr "Ajouter une clé GPG"
msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
-msgstr ""
+msgstr "Ajouter des Conditions Générales d'Utilisation et une Politique de Confidentialité pour les utilisateurs de cette instance GitLab."
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
msgid "Add a checklist"
-msgstr ""
+msgstr "Ajouter une liste de contrôle"
msgid "Add a collapsible section"
-msgstr ""
+msgstr "Ajouter une section rétractable"
msgid "Add a comment to this line"
msgstr ""
@@ -2167,10 +2187,10 @@ msgid "Add a comment to this line or drag for multiple lines"
msgstr ""
msgid "Add a confidential internal note to this %{noteableDisplayName}."
-msgstr ""
+msgstr "Ajouter une note interne confidentielle à ce %{noteableDisplayName}."
msgid "Add a custom message with details about the instance's shared runners. The message is visible when you view runners for projects and groups. Markdown is supported."
-msgstr ""
+msgstr "Ajoutez un message personnalisé avec les détails concernant les exécuteurs partagés de l'instance. Il sera visible quand vous afficherez les exécuteurs des projets et des groupes. Markdown est pris en charge."
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2179,16 +2199,16 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "Ajoutez une page d’accueil à votre wiki contenant des informations sur votre projet. GitLab l’affichera ici à la place de ce message."
msgid "Add a new issue"
-msgstr ""
+msgstr "Ajouter un nouveau ticket"
msgid "Add a numbered list"
msgstr "Ajouter une liste numérotée"
msgid "Add a related epic"
-msgstr ""
+msgstr "Ajouter une épopée associée"
msgid "Add a related issue"
-msgstr ""
+msgstr "Ajouter un ticket lié"
msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -2197,7 +2217,7 @@ msgid "Add a table"
msgstr "Ajouter un tableau"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "Ajouter un événement de la chronologie à l'incident"
msgid "Add a title..."
msgstr "Ajouter un titre..."
@@ -2206,13 +2226,13 @@ msgid "Add a to do"
msgstr "Ajouter une tâche"
msgid "Add an SSH key"
-msgstr ""
+msgstr "Ajouter une clé SSH"
msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
msgstr ""
msgid "Add an existing issue"
-msgstr ""
+msgstr "Ajouter un ticket existant"
msgid "Add an impersonation token"
msgstr ""
@@ -2236,19 +2256,19 @@ msgid "Add comment now"
msgstr "Ajouter un commentaire"
msgid "Add comment to design"
-msgstr ""
+msgstr "Ajouter un commentaire au design"
msgid "Add comment to incident timeline"
-msgstr ""
+msgstr "Ajouter un commentaire à la chronologie des incidents"
msgid "Add comment..."
-msgstr ""
+msgstr "Ajouter un commentaire..."
msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
-msgstr ""
+msgstr "Ajouter les messages de commit en tant que commentaires sur les tâches Asana. %{docs_link}"
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
-msgstr ""
+msgstr "Ajouter les messages de validation en tant que commentaires sur les histoires de Pivotal Tracker. %{docs_link}"
msgid "Add customer relation contact(s)."
msgstr ""
@@ -2257,13 +2277,13 @@ msgid "Add customer relation contacts"
msgstr ""
msgid "Add deploy freeze"
-msgstr ""
+msgstr "Ajouter un gel de déploiement"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
-msgstr ""
+msgstr "Ajouter des clés de déploiement pour accorder un accès en lecture/écriture à ce dépôt. %{link_start}Que sont les clés de déploiement ?%{link_end}"
msgid "Add email address"
-msgstr ""
+msgstr "Ajouter une adresse électronique"
msgid "Add email participant(s)"
msgstr ""
@@ -2272,10 +2292,10 @@ msgid "Add environment"
msgstr ""
msgid "Add existing confidential %{issuableType}"
-msgstr ""
+msgstr "Ajouter un(e) %{issuableType} confidentiel(le) existant(e)"
msgid "Add existing issue"
-msgstr ""
+msgstr "Ajouter un ticket existant"
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Ajouter un enâ€tête et un pied de page aux courriels. Veuillez noter que les paramètres de couleur seront appliqués uniquement à l’intérieur de l’interface de l’application"
@@ -2284,19 +2304,19 @@ msgid "Add image comment"
msgstr "Ajouter un commentaire à l’image"
msgid "Add internal note"
-msgstr ""
+msgstr "Ajouter une note interne"
msgid "Add key"
-msgstr ""
+msgstr "Ajouter une clé"
msgid "Add label(s)"
msgstr "Ajouter des étiquettes"
msgid "Add labels"
-msgstr ""
+msgstr "Ajouter des étiquettes"
msgid "Add license"
-msgstr ""
+msgstr "Ajouter une licence"
msgid "Add list"
msgstr ""
@@ -2317,16 +2337,16 @@ msgid "Add or subtract spent time"
msgstr ""
msgid "Add people"
-msgstr ""
+msgstr "Ajouter des personnes"
msgid "Add previously merged commits"
msgstr ""
msgid "Add project"
-msgstr ""
+msgstr "Ajouter un projet"
msgid "Add projects"
-msgstr ""
+msgstr "Ajouter des projets"
msgid "Add reaction"
msgstr "Ajouter une réaction"
@@ -2344,10 +2364,10 @@ msgid "Add text to the sign-in page. Markdown enabled."
msgstr ""
msgid "Add to board"
-msgstr ""
+msgstr "Ajouter au tableau"
msgid "Add to epic"
-msgstr ""
+msgstr "Ajouter à l'épopée"
msgid "Add to merge train"
msgstr ""
@@ -2365,13 +2385,7 @@ msgid "Add topics to projects to help users find them."
msgstr "Ajouter des sujets aux projets pour aider les utilisateurs à les trouver."
msgid "Add trigger"
-msgstr ""
-
-msgid "Add user(s) to the group:"
-msgstr "Ajouter un ou des utilisateurs au groupe :"
-
-msgid "Add users to group"
-msgstr "Ajouter des utilisateurs au groupe"
+msgstr "Ajouter un déclencheur"
msgid "Add variable"
msgstr ""
@@ -2386,34 +2400,34 @@ msgid "Add your team members and others to GitLab."
msgstr ""
msgid "Add/remove"
-msgstr ""
+msgstr "Ajouter/supprimer"
msgid "AddContextCommits|Add previously merged commits"
-msgstr ""
+msgstr "Ajouter des commits précédemment fusionnés"
msgid "AddContextCommits|Add/remove"
-msgstr ""
+msgstr "Ajouter/supprimer"
msgid "AddMember|Invite email is invalid"
msgstr ""
msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
-msgstr ""
+msgstr "Limite de %{daily_invites} invitation(s) par jour dépassée"
msgid "AddMember|Invites cannot be blank"
-msgstr ""
+msgstr "Les invitations ne peuvent pas être vides"
msgid "AddMember|No invite source provided."
-msgstr ""
+msgstr "Aucune source d'invitation fournie."
msgid "AddMember|No users specified."
-msgstr ""
+msgstr "Aucun utilisateur spécifié."
msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr "Trop d'utilisateurs spécifiés (la limite est %{user_limit})"
msgid "Added"
-msgstr ""
+msgstr "Ajouté"
msgid "Added %{epic_ref} as a child epic."
msgstr ""
@@ -2425,7 +2439,7 @@ msgid "Added a to do."
msgstr ""
msgid "Added an issue to an epic."
-msgstr ""
+msgstr "A ajouté un ticket à une épopée."
msgid "Added for this merge request"
msgstr ""
@@ -2440,25 +2454,25 @@ msgid "Additional minutes"
msgstr ""
msgid "Additional minutes:"
-msgstr ""
+msgstr "Minutes supplémentaires :"
msgid "Additional text"
msgstr "Texte supplémentaire"
msgid "Additional text for the sign-in and Help page."
-msgstr ""
+msgstr "Texte supplémentaire pour les pages d'aide et de connexion."
msgid "Additional text to show on the Help page"
msgstr ""
msgid "Additional text to show on the sign-in page"
-msgstr ""
+msgstr "Texte supplémentaire à afficher sur la page de connexion"
msgid "Address"
-msgstr ""
+msgstr "Adresse"
msgid "Adds"
-msgstr ""
+msgstr "Ajoute"
msgid "Adds %{epic_ref} as child epic."
msgstr ""
@@ -2470,25 +2484,25 @@ msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "Ajoute un événement de la chronologie à l'incident."
msgid "Adds a to do."
-msgstr ""
+msgstr "Ajoute une tâche."
msgid "Adds an issue to an epic."
-msgstr ""
+msgstr "Ajoute un ticket à une épopée."
msgid "Adds email participant(s)."
msgstr ""
msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
-msgstr ""
+msgstr "Ajoute ce %{issuable_type} en relation avec le %{issuable_type} depuis lequel il a été créé"
msgid "Adjust how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "Ajuster la fréquence à laquelle l'interface utilisateur de GitLab recherche les mises à jour."
msgid "Admin"
-msgstr ""
+msgstr "Admin"
msgid "Admin Area"
msgstr "Espace d’administration"
@@ -2506,7 +2520,7 @@ msgid "Admin Overview"
msgstr "Vue administrateur"
msgid "Admin Section"
-msgstr ""
+msgstr "Section Admin"
msgid "Admin mode already enabled"
msgstr ""
@@ -2521,40 +2535,40 @@ msgid "Admin navigation"
msgstr ""
msgid "Admin notes"
-msgstr ""
+msgstr "Notes de l'administrateur"
msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
-msgstr ""
+msgstr "%{billable_users_link_start}En savoir plus%{billable_users_link_end} sur ce qui définit un utilisateur facturable"
msgid "AdminArea|Active users"
-msgstr ""
+msgstr "Utilisateurs actifs"
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
-msgstr ""
+msgstr "Tous les utilisateurs créés sur cette instance, y compris ceux qui ne sont pas des %{billable_users_link_start}utilisateurs facturables%{billable_users_link_end}."
msgid "AdminArea|Billable users"
-msgstr ""
+msgstr "Utilisateurs facturables"
msgid "AdminArea|Blocked users"
-msgstr ""
+msgstr "Utilisateurs bloqués"
msgid "AdminArea|Bots"
-msgstr ""
+msgstr "Bots"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "Composants"
msgid "AdminArea|Developer"
-msgstr ""
+msgstr "Développeur"
msgid "AdminArea|Features"
-msgstr ""
+msgstr "Fonctionnalités"
msgid "AdminArea|Get security updates from GitLab and stay up to date"
-msgstr ""
+msgstr "Obtenez des mises à jour de sécurité depuis GitLab et restez à jour"
msgid "AdminArea|Groups"
-msgstr ""
+msgstr "Groupes"
msgid "AdminArea|Guest"
msgstr "Invité"
@@ -2566,49 +2580,49 @@ msgid "AdminArea|Instance OAuth applications"
msgstr ""
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "Derniers groupes"
msgid "AdminArea|Latest projects"
-msgstr ""
+msgstr "Derniers projets"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "Derniers utilisateurs"
msgid "AdminArea|Maintainer"
-msgstr ""
+msgstr "Mainteneur"
msgid "AdminArea|Manage applications for your instance that can use GitLab as an %{docs_link_start}OAuth provider%{docs_link_end}."
msgstr ""
msgid "AdminArea|Minimal access"
-msgstr ""
+msgstr "Accès minimal"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "Nouveau groupe"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "Nouveau projet"
msgid "AdminArea|New user"
-msgstr ""
+msgstr "Nouvel utilisateur"
msgid "AdminArea|No applications found"
msgstr ""
msgid "AdminArea|Owner"
-msgstr ""
+msgstr "Propriétaire"
msgid "AdminArea|Projects"
-msgstr ""
+msgstr "Projets"
msgid "AdminArea|Reporter"
msgstr ""
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "Inscrivez-vous à la lettre d'information sur la sécurité de GitLab pour être informé des mises à jour de sécurité."
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "S'inscrire à la lettre d'information de GitLab"
msgid "AdminArea|Stop all jobs"
msgstr "Arrêter toutes les tâches"
@@ -2626,7 +2640,7 @@ msgid "AdminArea|Total users"
msgstr ""
msgid "AdminArea|Users"
-msgstr ""
+msgstr "Utilisateurs"
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2635,7 +2649,7 @@ msgid "AdminArea|Users with highest role"
msgstr ""
msgid "AdminArea|Users without a Group and Project"
-msgstr ""
+msgstr "Utilisateurs sans Groupe ni Projet"
msgid "AdminArea|View latest groups"
msgstr ""
@@ -2647,19 +2661,19 @@ msgid "AdminArea|View latest users"
msgstr ""
msgid "AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running."
-msgstr ""
+msgstr "Vous êtes sur le point d'arrêter toutes les tâches. Toutes les tâches actuelles qui sont en cours d'exécution seront interrompues."
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erreur lors du chargement des statistiques. Veuillez réessayer"
msgid "AdminLabels|Define your default set of project labels"
-msgstr ""
+msgstr "Définissez votre propre ensemble d'étiquettes de projet"
msgid "AdminLabels|Labels created here will be automatically added to new projects."
-msgstr ""
+msgstr "Les étiquettes créées ici seront automatiquement ajoutées aux nouveaux projets."
msgid "AdminLabels|They can be used to categorize issues and merge requests."
-msgstr ""
+msgstr "Elles peuvent servir à classifier les tickets et les demandes de fusion."
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 ""
@@ -2671,16 +2685,16 @@ msgid "AdminProjects|Delete Project %{projectName}?"
msgstr "Supprimer le projet %{projectName} ?"
msgid "AdminSettings|%{strongStart}WARNING:%{strongEnd} Environment variable %{environment_variable} does not exist or is not pointing to a valid directory. %{icon_link}"
-msgstr ""
+msgstr "%{strongStart}ATTENTION :%{strongEnd} La variable d'environment %{environment_variable} n'existe pas ou ne pointe pas sur un répertoire valide. %{icon_link}"
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 "Un compte Let's Encrypt sera configuré pour cette instance GitLab à l'aide de cette adresse de messagerie. Vous recevrez des courriels pour vous avertir de l'expiration des certificats. %{link_start}En savoir plus.%{link_end}"
msgid "AdminSettings|Affects all new and existing groups."
msgstr ""
msgid "AdminSettings|All new projects can use the instance's shared runners by default."
-msgstr ""
+msgstr "Tous les nouveaux projets peuvent utiliser les exécuteurs partagés de l'instance par défaut."
msgid "AdminSettings|Auto DevOps domain"
msgstr "Domaine de DevOps automatique"
@@ -2689,121 +2703,133 @@ msgid "AdminSettings|CI/CD limits"
msgstr ""
msgid "AdminSettings|Configure Let's Encrypt"
-msgstr ""
+msgstr "Configurer Let's Encrypt"
msgid "AdminSettings|Configure limits on the number of repositories users can download in a given time."
msgstr ""
msgid "AdminSettings|Configure when inactive projects should be automatically deleted. %{linkStart}What are inactive projects?%{linkEnd}"
-msgstr ""
+msgstr "Définir quand les projets inactifs doivent être automatiquement supprimés. %{linkStart}Qu'est-ce-qu'un projet inactif ?%{linkEnd}"
msgid "AdminSettings|Delete inactive projects"
-msgstr ""
+msgstr "Supprimer les projets inactifs"
msgid "AdminSettings|Delete inactive projects that exceed"
-msgstr ""
+msgstr "Supprimer les projets inactifs qui dépassent"
msgid "AdminSettings|Delete project after"
-msgstr ""
+msgstr "Supprimer le projet après"
msgid "AdminSettings|Disable Elasticsearch until indexing completes."
-msgstr ""
+msgstr "Désactiver Elasticsearch jusqu'à ce que l'indexation soit terminée."
msgid "AdminSettings|Disable feed token"
-msgstr ""
+msgstr "Désactiver le jeton de flux"
msgid "AdminSettings|Disable public access to Pages sites"
-msgstr ""
+msgstr "Désactiver l'accès public aux sites Pages"
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 "Afficher une bannière sur les demandes de fusion des projets sans pipeline afin d'entamer la procédure d'ajout d'un fichier .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 ""
+msgstr "La vérification de domaine est une mesure de sécurité essentielle pour les sites GitLab publics. Les utilisateurs doivent démontrer qu'ils contrôlent un domaine avant qu'il ne soit activé. %{link_start}En savoir plus.%{link_end}"
msgid "AdminSettings|Elasticsearch indexing"
-msgstr ""
+msgstr "Indexation Elasticsearch"
msgid "AdminSettings|Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "Courriel depuis GitLab - envoi de courriel aux utilisateurs directement depuis l'Espace d'Administration. %{link_start}En savoir plus%{link_end}."
msgid "AdminSettings|Enable Registration Features"
-msgstr ""
+msgstr "Activer les fonctionnalités d'inscription"
msgid "AdminSettings|Enable Service Ping"
msgstr ""
msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
-msgstr ""
+msgstr "Activer la collecte des métriques de l'application. Un redémarrage est requis. %{link_start}En savoir plus sur l'export des métriques vers Prometheus%{link_end}. "
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
-msgstr ""
+msgstr "Activer l'analyseur personnalisé kuromoji : Indexation"
msgid "AdminSettings|Enable kuromoji custom analyzer: Search"
-msgstr ""
+msgstr "Activer l'analyseur personnalisé kuromoji : Recherche"
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "Activer la bannière de suggestion de pipeline"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr ""
+msgstr "Activer les exécuteurs partagés pour les nouveaux projets"
msgid "AdminSettings|Enable smartcn custom analyzer: Indexing"
-msgstr ""
+msgstr "Activer l'analyseur personnalisé smartcn : Indexation"
msgid "AdminSettings|Enable smartcn custom analyzer: Search"
-msgstr ""
+msgstr "Activer l'analyseur personnalisé smartcn : Recherche"
msgid "AdminSettings|Enabled"
msgstr ""
msgid "AdminSettings|Enforce invitation flow for groups and projects"
-msgstr ""
+msgstr "Imposer le flux d'invitation pour les groupes et les projets"
msgid "AdminSettings|Feed token"
-msgstr ""
+msgstr "Jeton de flux"
msgid "AdminSettings|Git abuse rate limit"
-msgstr ""
+msgstr "Taux limite avant abus de Git"
+
+msgid "AdminSettings|Group runners expiration"
+msgstr "Expiration des exécuteurs de groupe"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
-msgstr ""
+msgstr "J'ai lu et j'accepte les %{link_start}Conditions d'Utilisation%{link_end} (PDF) de Let's Encrypt."
+
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Si aucune unité n'est spécifiée, ce sera la seconde par défaut. Par exemple, sont équivalents : %{oneDayInSeconds}, %{oneDayInHoursHumanReadable} et %{oneDayHumanReadable}. La valeur minimale est de deux heures. %{linkStart}En savoir plus.%{linkEnd}"
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
-msgstr ""
+msgstr "Si non spécifiée au niveau du groupe ou de l'instance, la valeur par défaut est %{default_initial_branch_name}. N'affecte pas les dépôts existants."
msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
-msgstr ""
+msgstr "Si aucun index n'existe, GitLab en crée un."
msgid "AdminSettings|Import sources"
msgstr ""
msgid "AdminSettings|Inactive project deletion"
-msgstr ""
+msgstr "Suppression de projet inactif"
+
+msgid "AdminSettings|Instance runners expiration"
+msgstr "Expiration des exécuteurs d'instance"
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
-msgstr ""
+msgstr "Conserver les derniers artéfacts de toutes les tâches des pipelines réussis le plus récemment"
msgid "AdminSettings|Let's Encrypt email"
-msgstr ""
+msgstr "Adresse de courriel Let's Encrypt"
msgid "AdminSettings|Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "Limiter la taille du projet au niveau global, groupe et projet. %{link_start}En savoir plus%{link_end}."
msgid "AdminSettings|Limit the number of namespaces and projects that can be indexed."
-msgstr ""
+msgstr "Limiter le nombre d'espaces de noms et de projets pouvant être indexés."
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr ""
+msgstr "Durée maximale d'une session pour les opérations Git lorsque l'A2F est activée."
msgid "AdminSettings|Maximum number of DAG dependencies that a job can have"
msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
-msgstr ""
+msgstr "Nombre maximum de pipelines actifs par projet"
+
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "Nombre maximum de domaines personnalisés par projet"
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
-msgstr ""
+msgstr "Nombre maximum de tâches dans un pipeline unique"
msgid "AdminSettings|Maximum number of pipeline schedules"
msgstr ""
@@ -2818,130 +2844,145 @@ msgid "AdminSettings|Maximum number of runners registered per project"
msgstr ""
msgid "AdminSettings|Minimum size must be at least 0."
-msgstr ""
+msgstr "La taille minimale doit être d'au moins 0."
msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
-msgstr ""
+msgstr "Nouvelles variables CI/CD des projets et des groupes protégées par défaut."
msgid "AdminSettings|No required pipeline"
msgstr ""
msgid "AdminSettings|Only enable search after installing the plugin, enabling indexing, and recreating the index."
-msgstr ""
+msgstr "N'activer la recherche qu'après l'installation du plugin, l'activation de l'indexation et la régénération de l'index."
msgid "AdminSettings|Pause Elasticsearch indexing"
-msgstr ""
+msgstr "Suspendre l'indexation Elasticsearch"
msgid "AdminSettings|Preview payload"
-msgstr ""
+msgstr "Aperçu de la charge utile"
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr "Expiration des exécuteurs de projet"
+
msgid "AdminSettings|Protect CI/CD variables by default"
-msgstr ""
+msgstr "Protéger les variables CI/CD par défaut"
msgid "AdminSettings|Registration Features include:"
-msgstr ""
+msgstr "Les fonctionnalités payantes incluent :"
msgid "AdminSettings|Require users to prove ownership of custom domains"
-msgstr ""
+msgstr "Exiger des utilisateurs qu'ils prouvent qu'ils sont propriétaires de domaines personnalisés"
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
msgid "AdminSettings|Requires %{linkStart}email notifications%{linkEnd}"
-msgstr ""
+msgstr "Nécessite les %{linkStart}notifications par courriel%{linkEnd}"
msgid "AdminSettings|Restrict group access by IP address. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "Restreindre l'accès au groupe selon l'adresse IP. %{link_start}En savoir plus%{link_end}."
msgid "AdminSettings|Save %{name} limits"
msgstr ""
msgid "AdminSettings|Search with Elasticsearch enabled"
-msgstr ""
+msgstr "Recherche avec Elasticsearch activée"
msgid "AdminSettings|Select a CI/CD template"
msgstr ""
msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
-msgstr ""
+msgstr "Sélectionnez un groupe à utiliser comme source pour les modèles de projet de niveau instance."
msgid "AdminSettings|Select to disable public access for Pages sites, which requires users to sign in for access to the Pages sites in your instance. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Sélectionnez pour désactiver l'accès public aux sites Pages, ce qui oblige les utilisateurs à se connecter pour accéder aux sites Pages de votre instance. %{link_start}En savoir plus%{link_end}"
msgid "AdminSettings|Send email to maintainers after project is inactive for"
-msgstr ""
+msgstr "Envoyer un courriel aux mainteneurs après que le projet soit inactif depuis"
msgid "AdminSettings|Send warning email"
-msgstr ""
+msgstr "Envoyer un courriel d'avertissement"
msgid "AdminSettings|Service ping is disabled in your configuration file, and cannot be enabled through this form. For more information, see the documentation on %{link_start}deactivating service ping%{link_end}."
-msgstr ""
+msgstr "Le partage de données d'usage est désactivé dans votre fichier de configuration et ne peut être activé par le biais de ce formulaire. Pour plus d'informations, référez-vous à la documentation au sujet de la %{link_start}désactivation du partage de données%{link_end}"
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr ""
+msgstr "Durée de session pour les opérations Git lorsque l'A2F est activée (minutes)"
msgid "AdminSettings|Set a CI/CD template as the required pipeline configuration for all projects in the instance. Project CI/CD configuration merges into the required pipeline configuration when the pipeline runs. %{link_start}What is a required pipeline configuration?%{link_end}"
-msgstr ""
+msgstr "Définir un modèle CI/CD comme configuration requise de pipeline pour tous les projets de l'instance. La configuration CI/CD du projet fusionne avec la configuration requise de pipeline lorsque le pipeline est exécuté. %{link_start}Qu'est-ce-qu'une configuration requise de pipeline ?%{link_end}"
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "Définit la durée avant expiration des jetons d'authentification des exécuteurs de groupe nouvellement enregistrés."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "Définit la durée avant expiration des jetons d'authentification des exécuteurs d'instance nouvellement enregistrés. Les jetons d'authentification sont automatiquement réinitialisés à ces intervalles."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "Définit la durée avant expiration des jetons d'authentification des exécuteurs de projet nouvellement enregistrés."
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "Définir le nombre maximal de domaines Pages GitLab personnalisés par projet (0 pour illimité). %{link_start}En savoir plus.%{link_end}"
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Définir la taille maximale des Pages GitLab par projet (0 pour illimitée). %{link_start}En savoir plus.%{link_end}"
msgid "AdminSettings|Setting must be greater than 0."
-msgstr ""
+msgstr "Le paramètre doit être supérieur à 0."
msgid "AdminSettings|Size and domain settings for Pages static sites."
-msgstr ""
+msgstr "Paramètres de taille et de domaine pour les sites statiques Pages."
msgid "AdminSettings|The default domain to use for Auto Review Apps and Auto Deploy stages in all projects."
msgstr ""
msgid "AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
-msgstr ""
+msgstr "Les derniers artéfacts de toutes les tâches des pipelines qui ont réussi le plus récemment dans chaque projet sont enregistrés et n'expirent pas."
msgid "AdminSettings|The projects in this group can be selected as templates for new projects created on the instance. %{link_start}Learn more.%{link_end} "
-msgstr ""
+msgstr "Les projets de ce groupe peuvent être sélectionnés comme modèles pour les nouveaux projets créés sur l'instance. %{link_start}En savoir plus.%{link_end} "
msgid "AdminSettings|The template for the required pipeline configuration can be one of the GitLab-provided templates, or a custom template added to an instance template repository. %{link_start}How do I create an instance template repository?%{link_end}"
-msgstr ""
+msgstr "Le modèle pour la configuration requise du pipeline peut être un de ceux fournis par GitLab, ou un modèle personnalisé ajouté à un dépôt de modèles d'instance. %{link_start}Comment puis-je créer un dépôt de modèles d'instance ?%{link_end}"
msgid "AdminSettings|There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
-msgstr ""
+msgstr "Il y a des migrations de Recherche Avancée en attente qui nécessitent une mise en pause de l'indexation. Elle doit rester en pause jusqu'à ce que GitLab termine les migrations."
msgid "AdminSettings|To enable Registration Features, first enable Service Ping."
-msgstr ""
+msgstr "Pour activer les fonctionnalités payantes, activez d'abord le partage de données d'usage."
msgid "AdminSettings|To help improve GitLab and its user experience, GitLab periodically collects usage information. %{link_start}What information is shared with GitLab Inc.?%{link_end}"
-msgstr ""
+msgstr "Pour contribuer à améliorer GitLab et son expérience utilisateur, GitLab collecte périodiquement des informations d’utilisation. %{link_start}Quelles sont les informations partagées avec GitLab Inc. ?%{link_end}"
msgid "AdminSettings|Total number of jobs in currently active pipelines"
-msgstr ""
+msgstr "Nombre total de tâches dans les pipelines actuellement actifs"
msgid "AdminSettings|Use AWS OpenSearch Service with IAM credentials"
msgstr ""
msgid "AdminSettings|Users and groups must accept the invitation before they're added to a group or project."
-msgstr ""
+msgstr "Les utilisateurs et les groupes doivent accepter l’invitation avant de pouvoir être ajoutés à un groupe ou à un projet."
msgid "AdminSettings|When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
-msgstr ""
+msgstr "En pause, GitLab fait toujours le suivi des modifications. Ceci est utile pour les migrations d'index/grappes de serveurs."
msgid "AdminSettings|When to delete inactive projects"
-msgstr ""
+msgstr "Quand supprimer les projets inactifs"
msgid "AdminSettings|You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
-msgstr ""
+msgstr "Vous pouvez activer les fonctionnalités payantes car le partage de données d'usage est activé. Pour continuer à profiter des fonctionnalités payantes à l'avenir, vous devrez aussi vous enregistrer auprès de GitLab via un nouveau service de licence Cloud."
msgid "AdminSettings|You can't delete projects before the warning email is sent."
-msgstr ""
+msgstr "Vous ne pouvez pas supprimer de projets tant que le courriel d'avertissement n'est pas envoyé."
msgid "AdminStatistics|Active Users"
msgstr ""
@@ -2950,13 +2991,13 @@ msgid "AdminStatistics|Forks"
msgstr ""
msgid "AdminStatistics|Issues"
-msgstr ""
+msgstr "Tickets"
msgid "AdminStatistics|Merge requests"
-msgstr ""
+msgstr "Demandes de fusion"
msgid "AdminStatistics|Milestones"
-msgstr ""
+msgstr "Jalons"
msgid "AdminStatistics|Notes"
msgstr ""
@@ -2968,25 +3009,25 @@ msgid "AdminStatistics|Snippets"
msgstr ""
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "(Admin)"
msgid "AdminUsers|(Banned)"
-msgstr ""
+msgstr "(Banni)"
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(Bloqué)"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "(désactivé)"
msgid "AdminUsers|(Internal)"
-msgstr ""
+msgstr "(Interne)"
msgid "AdminUsers|(Locked)"
-msgstr ""
+msgstr "(Verrouillé)"
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "(En attente d'approbation)"
msgid "AdminUsers|2FA Disabled"
msgstr ""
@@ -2995,82 +3036,82 @@ msgid "AdminUsers|2FA Enabled"
msgstr ""
msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user. Validated users can use free CI minutes on shared runners."
-msgstr ""
+msgstr "Un utilisateur peut se valider lui-même en entrant une carte de crédit/débit, ou alors il peut être validé manuellement par un administrateur. Les utilisateurs validés peuvent utiliser des minutes CI gratuites sur les exécuteurs partagés."
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "Accès"
msgid "AdminUsers|Access Git repositories"
msgstr ""
msgid "AdminUsers|Access level"
-msgstr ""
+msgstr "Niveau d'accès"
msgid "AdminUsers|Access the API"
msgstr ""
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "Activer"
msgid "AdminUsers|Activate user %{username}?"
-msgstr ""
+msgstr "Activer l'utilisateur %{username} ?"
msgid "AdminUsers|Active"
-msgstr ""
+msgstr "Actif"
msgid "AdminUsers|Adjust the user cap setting on your instance"
msgstr ""
msgid "AdminUsers|Admin"
-msgstr ""
+msgstr "Admin"
msgid "AdminUsers|Administrator"
-msgstr ""
+msgstr "Administrateur"
msgid "AdminUsers|Admins"
-msgstr ""
+msgstr "Admins"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "Approuver"
msgid "AdminUsers|Approve user %{username}?"
-msgstr ""
+msgstr "Activer l'utilisateur %{username} ?"
msgid "AdminUsers|Approved users can:"
-msgstr ""
+msgstr "Les utilisateurs approuvés peuvent:"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "Auditeur"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr "Les auditeurs ont un accès en lecture seule à tous les groupes, projets et utilisateurs."
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "Marqué automatiquement comme utilisateur interne par défaut"
msgid "AdminUsers|Avatar"
-msgstr ""
+msgstr "Avatar"
msgid "AdminUsers|Ban user"
-msgstr ""
+msgstr "Bannir un utilisateur"
msgid "AdminUsers|Ban user %{username}?"
msgstr ""
msgid "AdminUsers|Banned"
-msgstr ""
+msgstr "Banni"
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
msgid "AdminUsers|Block"
-msgstr ""
+msgstr "Bloquer"
msgid "AdminUsers|Block user"
msgstr "Bloquer ce compte"
msgid "AdminUsers|Block user %{username}?"
-msgstr ""
+msgstr "Bloquer l'utilisateur %{username} ?"
msgid "AdminUsers|Blocked"
msgstr ""
@@ -3078,20 +3119,23 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr "Bot"
+
msgid "AdminUsers|Can create group"
-msgstr ""
+msgstr "Peuvent créer des groupes"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "Impossible de se connecter ou d'accéder aux informations de l'instance"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
msgid "AdminUsers|Cohorts"
-msgstr ""
+msgstr "Cohortes"
msgid "AdminUsers|Confirm user"
-msgstr ""
+msgstr "Confirmer l'utilisateur"
msgid "AdminUsers|Confirm user %{username}?"
msgstr ""
@@ -3103,7 +3147,7 @@ msgid "AdminUsers|Deactivate"
msgstr ""
msgid "AdminUsers|Deactivate user %{username}?"
-msgstr ""
+msgstr "Désactiver l'utilisateur %{username} ?"
msgid "AdminUsers|Deactivated"
msgstr ""
@@ -3127,52 +3171,52 @@ msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
msgstr "Exporter les permissions en CSV (100000 utilisateurs maximum)"
msgid "AdminUsers|External"
-msgstr ""
+msgstr "Externe"
msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
-msgstr ""
+msgstr "Les utilisateurs externes ne peuvent pas voir les projets internes ou privés à moins que l'accès ne leur soit explicitement accordé. De plus, ils ne peuvent pas créer des projets ou des groupes, ni des extraits personnels."
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "Pour plus d'informations, veuillez vous référer à la %{link_start}documentation sur la suppression de compte utilisateur.%{link_end}"
msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
-msgstr ""
+msgstr "Voici quelques liens utiles pour vous aider à gérer votre instance :"
msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
msgstr ""
msgid "AdminUsers|Important information about usage on your GitLab instance"
-msgstr ""
+msgstr "Informations importantes sur l’utilisation de votre instance GitLab"
msgid "AdminUsers|Is using seat"
msgstr ""
msgid "AdminUsers|Issues authored by this user are hidden from other users."
-msgstr ""
+msgstr "Les tickets rédigés par cet utilisateur sont cachés aux autres utilisateurs."
msgid "AdminUsers|It's you!"
msgstr ""
msgid "AdminUsers|LDAP Blocked"
-msgstr ""
+msgstr "Bloqué par LDAP"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
msgid "AdminUsers|Limits"
-msgstr ""
+msgstr "Limites"
msgid "AdminUsers|Linkedin"
-msgstr ""
+msgstr "Linkedin"
msgid "AdminUsers|Locked"
-msgstr ""
+msgstr "Verrouillé"
msgid "AdminUsers|Log in"
-msgstr ""
+msgstr "Connexion"
msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
-msgstr ""
+msgstr "Gérer (accepter/refuser) les inscriptions des utilisateurs en attente"
msgid "AdminUsers|New user"
msgstr ""
@@ -3193,28 +3237,28 @@ msgid "AdminUsers|Personal projects, group and user history will be left intact"
msgstr ""
msgid "AdminUsers|Quota of CI/CD minutes"
-msgstr ""
+msgstr "Quota de minutes CI/CD"
msgid "AdminUsers|Reactivating a user will:"
msgstr ""
msgid "AdminUsers|Regular"
-msgstr ""
+msgstr "Normal"
msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
-msgstr ""
+msgstr "Rejeter"
msgid "AdminUsers|Reject user %{username}?"
-msgstr ""
+msgstr "Rejeter l'utilisateur %{username}?"
msgid "AdminUsers|Rejected users:"
-msgstr ""
+msgstr "Utilisateurs rejetés :"
msgid "AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in."
-msgstr ""
+msgstr "Le lien de réinitialisation sera généré et envoyé à l'utilisateur. Celui-ci sera forcé de définir un mot de passe lors de sa première connexion."
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
@@ -3229,22 +3273,22 @@ msgid "AdminUsers|Send email to users"
msgstr ""
msgid "AdminUsers|Skype"
-msgstr ""
+msgstr "Skype"
msgid "AdminUsers|Sort by"
msgstr ""
msgid "AdminUsers|The maximum number of CI/CD minutes on shared runners that a group can use each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
-msgstr ""
+msgstr "Le nombre maximum de minutes CI/CD sur les exécuteurs partagés qu'un groupe peut utiliser chaque mois. Définir à 0 pour illimité. Laisser vide pour hériter du paramètre global fixé à %{minutes}"
msgid "AdminUsers|The user can't access git repositories."
-msgstr ""
+msgstr "L’utilisateur ne peut pas accéder aux dépôts git."
msgid "AdminUsers|The user can't log in."
-msgstr ""
+msgstr "L'utilisateur ne peut pas se connecter."
msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
-msgstr ""
+msgstr "L'utilisateur dispose d'un accès illimité à tous les groupes, projets, utilisateurs et fonctionnalités."
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3274,16 +3318,16 @@ msgid "AdminUsers|Unban user %{username}?"
msgstr ""
msgid "AdminUsers|Unblock"
-msgstr ""
+msgstr "Débloquer"
msgid "AdminUsers|Unblock user %{username}?"
-msgstr ""
+msgstr "Débloquer l'utilisateur %{username} ?"
msgid "AdminUsers|Unlock user %{username}?"
-msgstr ""
+msgstr "Déverrouiller l'utilisateur %{username} ?"
msgid "AdminUsers|User administration"
-msgstr ""
+msgstr "Administration des utilisateurs"
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -3292,25 +3336,25 @@ msgid "AdminUsers|User will not be able to login"
msgstr ""
msgid "AdminUsers|Users"
-msgstr ""
+msgstr "Utilisateurs"
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
-msgstr ""
+msgstr "Des utilisateurs peuvent toujours être invités à rejoindre votre instance et/ou s'ajouter eux-mêmes s'ils y sont autorisés en fonction de vos paramètres. Ils n'auront pas accès à votre instance et ne seront pas comptabilisés dans votre nombre de sièges souscrits jusqu'à ce que vous %{approve_link}."
msgid "AdminUsers|Validate user account"
-msgstr ""
+msgstr "Valider le compte utilisateur"
msgid "AdminUsers|View pending member requests"
-msgstr ""
+msgstr "Voir les demandes de membres en attente"
msgid "AdminUsers|Website URL"
-msgstr ""
+msgstr "URL du site web"
msgid "AdminUsers|What can I do?"
-msgstr ""
+msgstr "Que puis-je faire ?"
msgid "AdminUsers|What does this mean?"
-msgstr ""
+msgstr "Qu'est-ce que cela signifie?"
msgid "AdminUsers|When banned:"
msgstr ""
@@ -3325,10 +3369,10 @@ msgid "AdminUsers|Without projects"
msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement l’utilisateur %{username}. Les tickets, les demandes de fusion et les groupes qui lui sont liés seront transférés à un « utilisateur fantôme » global au système. Pour éviter la perte de données, pensez à utiliser à la place la fonctionnalité %{strongStart}bloquer l'utilisateur%{strongEnd}. L'action %{strongStart}Supprimer l'utilisateur%{strongEnd} terminée, elle ne pourra pas être annulée ni récupérée."
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement l’utilisateur %{username}. Cela supprimera tous les tickets, demandes de fusion et groupes qui lui sont liés. Pour éviter la perte de données, pensez à utiliser à la place la fonctionnalité %{strongStart}bloquer l'utilisateur%{strongEnd} . L'action %{strongStart}Supprimer l'utilisateur%{strongEnd} terminée, elle ne pourra pas être annulée ni récupérée."
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -3343,16 +3387,16 @@ msgid "AdminUsers|You can always unblock their account, their data will remain i
msgstr ""
msgid "AdminUsers|You can ban their account in the future if necessary."
-msgstr ""
+msgstr "Vous pouvez bannir leur compte dans le futur si nécessaire."
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr ""
msgid "AdminUsers|You cannot remove your own administrator access."
-msgstr ""
+msgstr "Vous ne pouvez pas supprimer votre propre accès administrateur."
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
-msgstr ""
+msgstr "Vous devez faire un transfert de propriété ou supprimer les groupes appartenant à cet utilisateur avant de pouvoir supprimer son compte"
msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
msgstr ""
@@ -3361,46 +3405,46 @@ msgid "AdminUsers|approve them"
msgstr ""
msgid "AdminUsers|contact our support team"
-msgstr ""
+msgstr "Contactez notre équipe d'assistance"
msgid "AdminUsers|docs"
-msgstr ""
+msgstr "docs"
msgid "AdminUsers|user cap"
msgstr ""
msgid "Administration"
-msgstr ""
+msgstr "Administration"
msgid "Administrators"
-msgstr ""
+msgstr "Administrateurs"
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 "Les utilisateurs supplémentaires doivent être examinés et approuvés par un administrateur système. En savoir plus sur les %{help_link_start}limites d'utilisation%{help_link_end}."
msgid "Admin|Admin notes"
-msgstr ""
+msgstr "Notes administrateur"
msgid "Admin|Learn more about quarterly reconciliation"
-msgstr ""
+msgstr "En savoir plus sur le rapprochement trimestriel"
msgid "Admin|Note"
msgstr ""
msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
-msgstr ""
+msgstr "Le rapprochement trimestriel aura lieu le %{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 ""
+msgstr "Le nombre maximum de sièges de votre espace de noms dépasse le nombre de sièges de votre abonnement. Le %{qrtlyDate}, un rapprochement trimestriel aura lieu et vous serez facturé automatiquement au prorata pour le surplus. Aucune action de votre part n'est nécessaire. Si une carte de crédit est enregistrée, elle sera utilisée. Sinon, vous recevrez une facture. Pour plus d'informations sur le calendrier du processus de facturation, consultez la documentation."
msgid "Admin|The number of max users in your instance exceeds the number of users in your license. 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 ""
+msgstr "Le nombre maximum d'utilisateurs de votre instance dépasse le nombre d'utilisateurs de votre licence. Le %{qrtlyDate}, un rapprochement trimestriel aura lieu et vous serez facturé automatiquement au prorata pour le surplus. Aucune action de votre part n'est nécessaire. Si une carte de crédit est enregistrée, elle sera utilisée. Sinon, vous recevrez une facture. Pour plus d'informations sur le calendrier du processus de facturation, consultez la documentation."
msgid "Admin|View pending user approvals"
-msgstr ""
+msgstr "Afficher les approbations d'utilisateurs en attente"
msgid "Admin|Your instance has reached its user cap"
-msgstr ""
+msgstr "Votre instance a atteint sa limite d'utilisateurs"
msgid "Advanced"
msgstr ""
@@ -3409,15 +3453,27 @@ msgid "Advanced Search"
msgstr "Recherche avancée"
msgid "Advanced Settings"
-msgstr ""
+msgstr "Paramètres avancés"
msgid "Advanced export options"
msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
+msgstr "Version d'Elasticsearch non compatible"
+
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
msgstr ""
msgid "AdvancedSearch|Reindex required"
+msgstr "Réindexation requise"
+
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
msgstr ""
msgid "After a successful password update you will be redirected to login screen."
@@ -3427,43 +3483,43 @@ msgid "After a successful password update, you will be redirected to the login p
msgstr ""
msgid "After it expires, you can't use merge approvals, code quality, or many other features."
-msgstr ""
+msgstr "Après son expiration, vous ne pouvez pas utiliser les approbations de fusion, la qualité de code ou de nombreuses autres fonctionnalités."
msgid "After it expires, you can't use merge approvals, epics, or many other features."
-msgstr ""
+msgstr "Après son expiration, vous ne pouvez pas utiliser les approbations de fusion, les épopées ou de nombreuses autres fonctionnalités."
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 ""
+msgstr "Une fois l'exportation terminée, téléchargez le fichier de données depuis le courriel de notification ou depuis cette page. Vous pourrez ensuite l'importer sur la page %{strong_text_start}Créer un nouveau groupe%{strong_text_end} d'une autre instance GitLab."
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 ""
msgid "Akismet helps prevent the creation of spam issues in public projects."
-msgstr ""
+msgstr "Akismet contribue à empêcher la création de tickets indésirables dans les projets publics."
msgid "Alert"
-msgstr ""
+msgstr "Alerte"
msgid "AlertManagement|Acknowledged"
msgstr ""
msgid "AlertManagement|Activity feed"
-msgstr ""
+msgstr "Flux d'activité"
msgid "AlertManagement|Alert"
-msgstr ""
+msgstr "Alerte"
msgid "AlertManagement|Alert assignee(s): %{assignees}"
-msgstr ""
+msgstr "Destinataire(s) des alertes : %{assignees}"
msgid "AlertManagement|Alert detail"
msgstr ""
@@ -3475,10 +3531,10 @@ msgid "AlertManagement|Alert status: %{status}"
msgstr ""
msgid "AlertManagement|Alerts"
-msgstr ""
+msgstr "Alertes"
msgid "AlertManagement|All alerts"
-msgstr ""
+msgstr "Toutes les alertes"
msgid "AlertManagement|Assign status"
msgstr ""
@@ -3490,7 +3546,7 @@ msgid "AlertManagement|Authorize external service"
msgstr ""
msgid "AlertManagement|Create incident"
-msgstr ""
+msgstr "Créer un incident"
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 ""
@@ -3499,31 +3555,31 @@ msgid "AlertManagement|Edit"
msgstr ""
msgid "AlertManagement|Environment"
-msgstr ""
+msgstr "Environnement"
msgid "AlertManagement|Events"
-msgstr ""
+msgstr "Événements"
msgid "AlertManagement|Incident"
-msgstr ""
+msgstr "Incident"
msgid "AlertManagement|Key"
-msgstr ""
+msgstr "Clé"
msgid "AlertManagement|Metrics"
-msgstr ""
+msgstr "Métriques"
msgid "AlertManagement|Metrics weren't available in the alerts payload."
-msgstr ""
+msgstr "Les métriques n'étaient pas disponibles dans la charge utile des alertes."
msgid "AlertManagement|More information"
-msgstr ""
+msgstr "Plus d'informations"
msgid "AlertManagement|No alert data to display."
-msgstr ""
+msgstr "Aucune donnée d'alerte à afficher."
msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
-msgstr ""
+msgstr "Aucune alerte n'est disponible pour affichage. Voir l'%{linkStart}activation de la gestion des alertes%{linkEnd} pour plus d’informations sur l’ajout d’alertes à la liste."
msgid "AlertManagement|No alerts to display."
msgstr ""
@@ -3535,7 +3591,7 @@ msgid "AlertManagement|Open"
msgstr ""
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "Veuillez réessayer."
msgid "AlertManagement|Reported %{when}"
msgstr ""
@@ -3547,7 +3603,7 @@ msgid "AlertManagement|Resolved"
msgstr ""
msgid "AlertManagement|Runbook"
-msgstr ""
+msgstr "Dossier d'exploitation"
msgid "AlertManagement|Service"
msgstr ""
@@ -3559,70 +3615,70 @@ msgid "AlertManagement|Start time"
msgstr ""
msgid "AlertManagement|Status"
-msgstr ""
+msgstr "État"
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 "Une erreur s’est produite lors de l’affichage de l’alerte. Veuillez actualiser la page pour réessayer."
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de la liste des assigné(e)s. Veuillez réessayer."
msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour des assigné(e)s à l’alerte. Veuillez réessayer."
msgid "AlertManagement|There was an error while updating the status of the alert."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de l'état de l’alerte."
msgid "AlertManagement|There was an error while updating the to-do item of the alert."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de l'élément « À faire » de l'alerte."
msgid "AlertManagement|This assignee cannot be assigned to this alert."
-msgstr ""
+msgstr "Ce destinataire ne peut pas être assigné à cette alerte."
msgid "AlertManagement|Tool"
-msgstr ""
+msgstr "Outil"
msgid "AlertManagement|Triggered"
-msgstr ""
+msgstr "Déclenché"
msgid "AlertManagement|Value"
-msgstr ""
+msgstr "Valeur"
msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertMappingBuilder|Define fallback"
-msgstr ""
+msgstr "Définir une solution par défaut"
msgid "AlertMappingBuilder|GitLab alert key"
-msgstr ""
+msgstr "Clé d’alerte GitLab"
msgid "AlertMappingBuilder|Make selection"
-msgstr ""
+msgstr "Faire la sélection"
msgid "AlertMappingBuilder|Payload alert key"
-msgstr ""
+msgstr "Clé d'alerte de la charge utile"
msgid "AlertMappingBuilder|Select key"
-msgstr ""
+msgstr "Sélectionner la clé"
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 "Le titre est un champ requis pour les alertes de GitLab. Dans l'hypothèse où le champ dans lequel vous avez spécifié la charge utile ne serait pas disponible, indiquez quel champ devra être utilisé à la place. "
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 "Une URL de crochet web et une clé d'autorisation sont générées pour l'intégration. Après avoir enregistré cette dernière, les deux sont visibles dans l'onglet « Afficher les identifiants »."
msgid "AlertSettings|Add new integration"
-msgstr ""
+msgstr "Ajouter une nouvelle intégration"
msgid "AlertSettings|Alert settings"
-msgstr ""
+msgstr "Paramètres d’alerte"
msgid "AlertSettings|Authorization key"
msgstr ""
@@ -3631,25 +3687,25 @@ msgid "AlertSettings|Configure details"
msgstr ""
msgid "AlertSettings|Current integrations"
-msgstr ""
+msgstr "Intégrations actuelles"
msgid "AlertSettings|Customize alert payload mapping (optional)"
-msgstr ""
+msgstr "Personnaliser l'association de charge utile d'alerte (facultatif)"
msgid "AlertSettings|Delete integration"
-msgstr ""
+msgstr "Supprimer l’intégration"
msgid "AlertSettings|Edit integration"
-msgstr ""
+msgstr "Modifier l’intégration"
msgid "AlertSettings|Edit payload"
-msgstr ""
+msgstr "Modifier la charge utile"
msgid "AlertSettings|Enable integration"
-msgstr ""
+msgstr "Activer l'intégration"
msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
-msgstr ""
+msgstr "Entrez un exemple de charge utile issu de votre outil de supervision sélectionné. Cela prend en charge l'envoi d'alertes vers un point de terminaison GitLab."
msgid "AlertSettings|Enter integration name"
msgstr ""
@@ -3658,43 +3714,43 @@ 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 "GitLab a créé une URL et une clé d'autorisation pour votre intégration. Vous pouvez les utiliser pour mettre en place un crochet web et pour autoriser votre point de terminaison à envoyer des alertes vers GitLab."
msgid "AlertSettings|HTTP Endpoint"
msgstr ""
msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
-msgstr ""
+msgstr "Si vous modifiez la charge utile, vous devrez refaire l'association avec les champs."
msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
-msgstr ""
+msgstr "Si vous réinitialisez la clé d'autorisation de ce projet, vous devrez la mettre à jour dans chacune des sources d'alerte activées."
msgid "AlertSettings|Integration successfully saved"
-msgstr ""
+msgstr "Intégration enregistrée avec succès"
msgid "AlertSettings|Name integration"
msgstr ""
msgid "AlertSettings|Parse payload fields"
-msgstr ""
+msgstr "Analyser les champs de la charge utile"
msgid "AlertSettings|Proceed with editing"
-msgstr ""
+msgstr "Procéder à l'édition"
msgid "AlertSettings|Prometheus"
msgstr ""
msgid "AlertSettings|Prometheus API base URL"
-msgstr ""
+msgstr "URL de base de l'API Prometheus"
msgid "AlertSettings|Reset Key"
-msgstr ""
+msgstr "Réinitialiser la Clé"
msgid "AlertSettings|Reset the mapping"
msgstr ""
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
-msgstr ""
+msgstr "L'exemple de charge utile a été analysé. Vous pouvez à présent faire l'association des champs."
msgid "AlertSettings|Save & create test alert"
msgstr ""
@@ -3703,28 +3759,28 @@ msgid "AlertSettings|Save integration"
msgstr ""
msgid "AlertSettings|Save integration & send"
-msgstr ""
+msgstr "Enregistrer l’intégration et envoyer"
msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
-msgstr ""
+msgstr "Envoyer une alerte de test"
msgid "AlertSettings|Send without saving"
msgstr ""
msgid "AlertSettings|The form has unsaved changes"
-msgstr ""
+msgstr "Le formulaire comporte des modifications non enregistrées"
msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
-msgstr ""
+msgstr "Le formulaire contient des modifications non enregistrées. Comment voudriez-vous procéder ?"
msgid "AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the \"Parse payload fields\" button to continue."
-msgstr ""
+msgstr "Pour créer une association personnalisée, entrez un exemple de charge utile issue de votre outil de supervision au format JSON. Sélectionnez le bouton « Analyser les champs de la charge utile » pour continuer."
msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
-msgstr ""
+msgstr "L'URL ne peut pas être vide et doit commencer par 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 ""
@@ -3733,64 +3789,64 @@ msgid "AlertSettings|Use the URL and authorization key below to configure how an
msgstr ""
msgid "AlertSettings|View URL and authorization key"
-msgstr ""
+msgstr "Afficher l'URL et la clé d'autorisation"
msgid "AlertSettings|View credentials"
-msgstr ""
+msgstr "Afficher les identifiants"
msgid "AlertSettings|Webhook URL"
-msgstr ""
+msgstr "URL de Webhook"
msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
-msgstr ""
+msgstr "Vous pouvez associer les champs par défaut des alertes GitLab aux clés de votre charge utile grâce aux listes déroulantes ci-dessous."
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
-msgstr ""
+msgstr "{ \"events\": [{ \"application\": \"Nom de l'application\" }] }"
msgid "Alerts"
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
-msgstr ""
+msgstr "Les alertes seront créées via cette intégration"
msgid "AlertsIntegrations|Alerts will not be created through this integration"
-msgstr ""
+msgstr "Les alertes ne seront pas créées via cette intégration"
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
-msgstr ""
+msgstr "Si vous supprimez l'intégration %{integrationName}, les alertes ne seront plus envoyées depuis ce point de terminaison. Cette action ne peut pas être annulée."
msgid "AlertsIntegrations|Integration Name"
msgstr ""
msgid "AlertsIntegrations|Integration payload is invalid."
-msgstr ""
+msgstr "La charge utile de l’intégration n’est pas valide."
msgid "AlertsIntegrations|No integrations have been added yet."
-msgstr ""
+msgstr "Aucune intégration n’a encore été ajoutée."
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
msgstr "L'intégration actuelle n'a pas pu être mise à jour. Veuillez réessayer."
msgid "AlertsIntegrations|The integration could not be added. Please try again."
-msgstr ""
+msgstr "L’intégration n’a pas pu être ajoutée. Veuillez réessayer."
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
-msgstr ""
+msgstr "L’intégration n’a pas pu être supprimée. Veuillez réessayer."
msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
-msgstr ""
+msgstr "L'intégration n'est pas active actuellement. Activez-la pour envoyer l'alerte de test."
msgid "AlertsIntegrations|The integration is deleted."
-msgstr ""
+msgstr "L’intégration est supprimée."
msgid "AlertsIntegrations|The integration is saved."
-msgstr ""
+msgstr "L'intégration est enregistrée."
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
-msgstr ""
+msgstr "Le jeton de l’intégration n’a pas pu être réinitialisé. Veuillez réessayer."
msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
-msgstr ""
+msgstr "L'alerte de test devrait maintenant être visible dans votre liste d'alertes."
msgid "Algorithm"
msgstr ""
@@ -3817,7 +3873,7 @@ msgid "All changes are committed"
msgstr "Toutes les modifications sont validées"
msgid "All eligible users"
-msgstr ""
+msgstr "Tous les utilisateurs éligibles"
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3829,13 +3885,13 @@ msgid "All groups and projects"
msgstr ""
msgid "All issues"
-msgstr ""
+msgstr "Tous les tickets"
msgid "All issues for this milestone are closed."
msgstr "Tous les tickets de ce jalon sont fermés"
msgid "All issues for this milestone are closed. You may close this milestone now."
-msgstr ""
+msgstr "Tous les tickets liés à ce jalon sont fermés. Vous pouvez désormais fermer ce jalon."
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
@@ -3846,23 +3902,26 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr "Tous les membres du projet"
+
msgid "All projects"
msgstr ""
msgid "All projects selected"
-msgstr ""
+msgstr "Tous les projets sélectionnés"
msgid "All protected branches"
msgstr ""
msgid "All threads resolved!"
-msgstr ""
+msgstr "Tous les sujets ont été résolus !"
msgid "All users in this group must set up two-factor authentication"
-msgstr ""
+msgstr "Tous les utilisateurs de ce groupe doivent configurer une authentification à deux facteurs"
msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
-msgstr ""
+msgstr "Tous les utilisateurs doivent accepter les Conditions Générales d'Utilisation et la Politique de Confidentialité pour accéder à GitLab"
msgid "All users must have a name."
msgstr ""
@@ -3874,10 +3933,10 @@ msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
msgid "Allow access to members of the following group"
-msgstr ""
+msgstr "Autoriser l'accès aux membres du groupe suivant"
msgid "Allow access to the following IP addresses"
-msgstr ""
+msgstr "Autoriser l'accès aux adresses IP suivantes"
msgid "Allow commits from members who can merge to the target branch. %{link_start}About this feature.%{link_end}"
msgstr ""
@@ -3886,7 +3945,7 @@ msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "Autoriser les non-administrateurs à accéder à la barre de performance"
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
@@ -3904,7 +3963,7 @@ msgid "Allow password authentication for the web interface"
msgstr ""
msgid "Allow project maintainers to configure repository mirroring"
-msgstr ""
+msgstr "Autoriser les mainteneurs de projet à configurer la mise en miroir de dépôts"
msgid "Allow projects and subgroups to override the group setting"
msgstr ""
@@ -3913,7 +3972,7 @@ msgid "Allow projects within this group to use Git LFS"
msgstr "Autoriser les projets de ce groupe à utiliser le stockage Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
-msgstr ""
+msgstr "Autoriser l’accès public aux pipelines et aux détails des tâches, dont les journaux de sortie et les artéfacts."
msgid "Allow this key to push to this repository"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr "Autoriser les utilisateurs à créer des groupes de niveau supérieur"
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -3937,7 +3999,7 @@ msgid "Allowed to create:"
msgstr ""
msgid "Allowed to delete projects"
-msgstr ""
+msgstr "Autorisé à supprimer des projets"
msgid "Allowed to fail"
msgstr ""
@@ -3946,7 +4008,7 @@ msgid "Allows projects or subgroups in this group to override the global setting
msgstr ""
msgid "Allows projects to track errors using an Opstrace integration."
-msgstr ""
+msgstr "Permet aux projets de faire un suivi des erreurs grâce à une intégration de Opstrace."
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Vous permet d’ajouter et de gérer des grappes de serveurs Kubernetes."
@@ -3958,10 +4020,10 @@ msgid "Almost there..."
msgstr ""
msgid "Already blocked"
-msgstr ""
+msgstr "Déjà bloqué"
msgid "Already have login and password?"
-msgstr ""
+msgstr "Vous avez déjà un identifiant et un mot de passe ?"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "Également appelé « émetteur » ou « identifiant du tiers de confiance »"
@@ -4000,7 +4062,7 @@ msgid "An Enterprise User GitLab account has been created for you by your organi
msgstr ""
msgid "An administrator changed the password for your GitLab account on %{link_to}."
-msgstr ""
+msgstr "Un administrateur a modifié le mot de passe de votre compte GitLab sur %{link_to}."
msgid "An alert has been resolved in %{project_path}."
msgstr ""
@@ -4012,7 +4074,7 @@ msgid "An application called %{link_to_client} is requesting access to your GitL
msgstr "Une application appelée %{link_to_client} demande l’accès à votre compte 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 "Une notification par courriel a récemment été envoyée depuis le panneau d'administration. Veuillez patienter %{wait_time_in_words} avant de tenter l'envoi d'un autre message."
msgid "An email will be sent with the report attached after it is generated."
msgstr ""
@@ -4057,28 +4119,28 @@ msgid "An error occurred when loading the user verification challenge. Refresh t
msgstr ""
msgid "An error occurred when updating the title"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du titre"
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
msgstr ""
msgid "An error occurred while adding approvers"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'ajout des approbateurs"
msgid "An error occurred while adding formatted title for epic"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'ajout à l'épopée d'un titre formaté"
msgid "An error occurred while approving, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'approbation, veuillez réessayer."
msgid "An error occurred while authorizing your role"
msgstr ""
msgid "An error occurred while checking group path. Please refresh and try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la vérification du chemin d'accès au groupe. Veuillez actualiser et réessayer."
msgid "An error occurred while decoding the file."
-msgstr ""
+msgstr "Une erreur s'est produite lors du décodage du fichier."
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -4111,19 +4173,19 @@ msgid "An error occurred while fetching Markdown preview"
msgstr ""
msgid "An error occurred while fetching ancestors"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des prédécesseurs"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des branches. Réessayez la recherche."
msgid "An error occurred while fetching codequality mr diff reports."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des rapports sur la qualité de code des diffs de MR."
msgid "An error occurred while fetching commit data."
msgstr ""
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des commits. Réessayez la recherche."
msgid "An error occurred while fetching coverage reports."
msgstr ""
@@ -4144,10 +4206,10 @@ msgid "An error occurred while fetching label colors."
msgstr ""
msgid "An error occurred while fetching participants"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des participants"
msgid "An error occurred while fetching participants."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des participants."
msgid "An error occurred while fetching pending comments"
msgstr "Une erreur est survenue lors de la récupération des commentaires en attente"
@@ -4156,13 +4218,13 @@ msgid "An error occurred while fetching projects autocomplete."
msgstr ""
msgid "An error occurred while fetching reference"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la référence"
msgid "An error occurred while fetching reviewers."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des relecteurs."
msgid "An error occurred while fetching tags. Retry the search."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étiquettes. Réessayez la recherche."
msgid "An error occurred while fetching terraform reports."
msgstr ""
@@ -4171,7 +4233,7 @@ msgid "An error occurred while fetching the job log."
msgstr "Une erreur est survenue pendant la récupération du journal de la tâche."
msgid "An error occurred while fetching the job logs."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des journaux de la tâche."
msgid "An error occurred while fetching the job."
msgstr "Une erreur est survenue pendant la récupération de la tâche."
@@ -4183,7 +4245,7 @@ msgid "An error occurred while fetching the latest pipeline."
msgstr ""
msgid "An error occurred while fetching the pipelines jobs."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tâches des pipelines."
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
@@ -4195,7 +4257,7 @@ msgid "An error occurred while getting files for - %{branchId}"
msgstr ""
msgid "An error occurred while getting issue counts"
-msgstr ""
+msgstr "Une erreur est survenue lors de l'obtention du nombre de tickets"
msgid "An error occurred while getting projects"
msgstr "Une erreur s’est produite lors de la récupération des projets"
@@ -4204,14 +4266,11 @@ msgid "An error occurred while initializing path locks"
msgstr "Une erreur est survenue lors de l’initialisation des verrous des chemins d’accès"
msgid "An error occurred while loading a section of this page."
-msgstr ""
+msgstr "Une erreur s’est produite lors du chargement d'une section de cette page."
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Une erreur est survenue lors du chargement des données du graphique"
@@ -4222,7 +4281,7 @@ msgid "An error occurred while loading commit signatures"
msgstr "Une erreur s’est produite lors du chargement des signatures du commit"
msgid "An error occurred while loading designs. Please try again."
-msgstr ""
+msgstr "Une erreur c'est produite pendant le chargement des designs. Veuillez réessayer."
msgid "An error occurred while loading diff"
msgstr "Une erreur s’est produite lors du chargement du diff"
@@ -4240,16 +4299,16 @@ msgid "An error occurred while loading merge requests."
msgstr ""
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "Une erreur s’est produite lors du chargement des projets."
msgid "An error occurred while loading the Jobs tab."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de l'onglet des Tâches."
msgid "An error occurred while loading the Needs tab."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de l'onglet Besoins."
msgid "An error occurred while loading the Test Reports tab."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de l'onglet des Rapports de Tests."
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4267,10 +4326,10 @@ msgid "An error occurred while loading the file."
msgstr ""
msgid "An error occurred while loading the file. Please try again later."
-msgstr ""
+msgstr "Une erreur est survenue lors de chargement du fichier. Veuillez réessayer ultérieurement."
msgid "An error occurred while loading the file. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement du fichier. Veuillez réessayer."
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -4282,10 +4341,10 @@ msgid "An error occurred while loading the merge request."
msgstr ""
msgid "An error occurred while loading the notification settings. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des paramètres de notification. Veuillez réessayer."
msgid "An error occurred while loading the pipeline."
-msgstr ""
+msgstr "Une erreur s’est produite lors du chargement du pipeline."
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
@@ -4294,19 +4353,19 @@ msgid "An error occurred while making the request."
msgstr "Une erreur s’est produite lors de la requête."
msgid "An error occurred while moving the issue."
-msgstr ""
+msgstr "Une erreur est survenue lors du déplacement du ticket."
msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while parsing the file."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'analyse du fichier."
msgid "An error occurred while pasting text in the editor. Please try again."
msgstr ""
msgid "An error occurred while performing this action."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'exécution de cette action."
msgid "An error occurred while removing epics."
msgstr ""
@@ -4318,7 +4377,7 @@ msgid "An error occurred while rendering preview broadcast message"
msgstr "Une erreur s’est produite lors de la prévisualisation de la bannière"
msgid "An error occurred while rendering the editor"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'affichage de l'éditeur"
msgid "An error occurred while reordering issues."
msgstr ""
@@ -4330,16 +4389,16 @@ msgid "An error occurred while retrieving diff"
msgstr "Une erreur s’est produite lors de la récupération du diff"
msgid "An error occurred while retrieving diff files"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des fichiers diff"
msgid "An error occurred while retrieving projects."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets."
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de vos paramètres. Rechargez la page pour réessayer."
msgid "An error occurred while saving changes: %{error}"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'enregistrement des modifications : %{error}"
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
@@ -4347,25 +4406,25 @@ msgstr[0] ""
msgstr[1] ""
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la sauvegarde de vos paramètres. Essayez de les sauvegarder de nouveau."
msgid "An error occurred while triggering the job."
msgstr ""
msgid "An error occurred while trying to follow this user, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative pour suivre cet utilisateur, veuillez réessayer."
msgid "An error occurred while trying to generate the report. Please try again later."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative pour générer le rapport. Veuillez réessayer plus tard."
msgid "An error occurred while trying to render the content editor. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative pour afficher l'éditeur de contenu. Veuillez réessayer."
msgid "An error occurred while trying to run a new pipeline for this merge request."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative d'exécution d'un nouveau pipeline pour cette demande de fusion."
msgid "An error occurred while trying to unfollow this user, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative pour ne plus suivre cet utilisateur, veuillez réessayer."
msgid "An error occurred while updating approvers"
msgstr ""
@@ -4374,19 +4433,19 @@ msgid "An error occurred while updating assignees."
msgstr ""
msgid "An error occurred while updating configuration."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la configuration."
msgid "An error occurred while updating labels."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des labels."
msgid "An error occurred while updating the comment"
msgstr "Une erreur est survenue lors de la mise à jour du commentaire"
msgid "An error occurred while updating the configuration."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la configuration."
msgid "An error occurred while updating the notification settings. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des paramètres de notification. Veuillez réessayer."
msgid "An error occurred while uploading the file. Please try again."
msgstr ""
@@ -4398,37 +4457,37 @@ msgid "An error occurred while validating username"
msgstr "Une erreur s’est produite lors de la validation du nom d’utilisateur"
msgid "An error occurred. Please sign in again."
-msgstr ""
+msgstr "Une erreur s'est produite. Veuillez vous reconnecter."
msgid "An error occurred. Please try again."
msgstr "Une erreur est survenue. Merci de réessayer."
msgid "An example project for managing Kubernetes clusters integrated with GitLab"
-msgstr ""
+msgstr "Un exemple de projet pour gérer des grappes de serveurs Kubernetes intégrées à GitLab"
msgid "An example project that shows off the best practices for setting up GitLab for your own organization, including sample issues, merge requests, and milestones"
-msgstr ""
+msgstr "Un exemple de projet qui présente les bonnes pratiques pour configurer GitLab dans votre propre entreprise, et qui contient des exemples de tickets, demandes de fusion et jalons"
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
-msgstr ""
+msgstr "Un exemple montrant comment utiliser Jsonnet avec les pipelines enfants dynamiques de GitLab"
msgid "An incident has been resolved in %{project_path}."
msgstr ""
msgid "An incident has been triggered in %{project_path}."
-msgstr ""
+msgstr "Un incident a été déclenché dans %{project_path}."
msgid "An integer value is required for seconds"
msgstr ""
msgid "An issue already exists"
-msgstr ""
+msgstr "Un ticket existe déjà"
msgid "An unauthenticated user"
-msgstr ""
+msgstr "Un utilisateur non authentifié"
msgid "An unexpected error occurred"
-msgstr ""
+msgstr "Une erreur inattendue s'est produite"
msgid "An unexpected error occurred while checking the project environment."
msgstr ""
@@ -4440,7 +4499,7 @@ msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr ""
msgid "An unexpected error occurred while loading the code quality diff."
-msgstr ""
+msgstr "Une erreur inattendue s'est produite lors du chargement du diff de qualité de code."
msgid "An unexpected error occurred while starting the Web Terminal."
msgstr ""
@@ -4449,14 +4508,17 @@ msgid "An unexpected error occurred while stopping the Web Terminal."
msgstr ""
msgid "An unknown error occurred while loading this graph."
-msgstr ""
+msgstr "Une erreur inconnue s'est produite lors du chargement de ce graphe."
msgid "An unknown error occurred."
-msgstr ""
+msgstr "Une erreur inconnue s'est produite."
msgid "Analytics"
msgstr "Analyse"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4464,13 +4526,13 @@ msgid "Analyze your infrastructure as code configuration files for known vulnera
msgstr ""
msgid "Analyze your source code and git history for secrets."
-msgstr ""
+msgstr "Analyser votre code source et historique git à la recherche de secrets."
msgid "Analyze your source code for known vulnerabilities."
-msgstr ""
+msgstr "Analysez votre code source à la recherche de vulnérabilités."
msgid "Analyzing file…"
-msgstr ""
+msgstr "Analyse du fichier…"
msgid "Ancestors"
msgstr ""
@@ -4482,10 +4544,10 @@ msgid "Anonymous"
msgstr "Anonyme"
msgid "Another action is currently in progress"
-msgstr ""
+msgstr "Une autre action est actuellement en cours"
msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
-msgstr ""
+msgstr "Un autre outil de suivi de tickets est déjà en cours d'utilisation. Un seul peut être actif à la fois"
msgid "Another third-party wiki is already in use. Only one third-party wiki integration can be active at a time"
msgstr ""
@@ -4512,7 +4574,7 @@ msgid "Any label"
msgstr ""
msgid "Any member with at least Developer permissions on the project."
-msgstr ""
+msgstr "Tout membre ayant au moins les permissions Développeur sur le projet."
msgid "Any milestone"
msgstr "N'importe quel jalon"
@@ -4548,16 +4610,16 @@ msgid "Application ID"
msgstr "Identifiant de l’application"
msgid "Application limits saved successfully"
-msgstr ""
+msgstr "Limites d'application enregistrées avec succès"
msgid "Application settings saved successfully"
msgstr ""
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "Les paramètres de l'application ont été sauvegardés avec succès."
msgid "Application settings update failed"
-msgstr ""
+msgstr "La mise à jour des paramètres de l'application a échoué"
msgid "Application uninstalled but failed to destroy: %{error_message}"
msgstr ""
@@ -4572,143 +4634,146 @@ msgid "Application: %{name}"
msgstr "Application : %{name}"
msgid "ApplicationSettings|A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
-msgstr ""
+msgstr "Un élément de menu Tableau de bord des métriques apparaît dans la section Surveillance de la zone d'administration."
msgid "ApplicationSettings|Add a link to Grafana"
-msgstr ""
+msgstr "Ajouter un lien vers Grafana"
msgid "ApplicationSettings|After sign-up text"
msgstr ""
msgid "ApplicationSettings|After the instance reaches the user cap, any user who is added or requests access must be approved by an administrator. Leave blank for unlimited."
-msgstr ""
+msgstr "Après que l'instance ait atteint le nombre maximal d'utilisateurs, tout utilisateur qui est ajouté ou qui demande un accès devra être approuvé par un administrateur. Laissez vide pour qu'il n'y ait pas de limite."
msgid "ApplicationSettings|Allowed domains for sign-ups"
-msgstr ""
+msgstr "Domaines autorisés pour les inscriptions"
msgid "ApplicationSettings|Any user that visits %{host} and creates an account must be explicitly approved by an administrator before they can sign in. Only effective if sign-ups are enabled."
-msgstr ""
+msgstr "Tout utilisateur qui visite %{host} et crée un compte doit être explicitement approuvé par un administrateur avant de pouvoir se connecter. Actif uniquement si les inscriptions sont activées."
msgid "ApplicationSettings|Any user that visits %{host} can create an account."
-msgstr ""
+msgstr "Tout utilisateur qui visite %{host} peut créer un compte."
msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Approuver %d utilisateur"
+msgstr[1] "Approuver %d utilisateurs"
msgid "ApplicationSettings|Approve users"
-msgstr ""
+msgstr "Approuver des utilisateurs"
msgid "ApplicationSettings|Approve users in the pending approval status?"
-msgstr ""
+msgstr "Approuver les utilisateurs qui sont en attente d'approbation ?"
msgid "ApplicationSettings|Approve users who are pending approval?"
-msgstr ""
+msgstr "Approuver les utilisateurs qui sont en attente d’approbation ?"
msgid "ApplicationSettings|By making this change, you will automatically approve %d user who is pending approval."
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users who are pending approval."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "En faisant cette modification, vous allez automatiquement approuver %d utilisateur dont l'approbation est en attente."
+msgstr[1] "En faisant cette modification, vous allez automatiquement approuver %d utilisateurs dont l'approbation est en attente."
msgid "ApplicationSettings|By making this change, you will automatically approve all users who are pending approval."
-msgstr ""
+msgstr "En faisant cette modification, vous allez automatiquement approuver tous les utilisateurs dont l'approbation est en attente."
msgid "ApplicationSettings|Denied domains for sign-ups"
-msgstr ""
+msgstr "Domaines refusés pour les inscriptions"
msgid "ApplicationSettings|Denylist file"
-msgstr ""
+msgstr "Fichier de liste d'exclusion"
msgid "ApplicationSettings|Domain denylist"
-msgstr ""
+msgstr "Liste d'exclusion de domaines"
msgid "ApplicationSettings|Email restrictions"
-msgstr ""
+msgstr "Restrictions d'adresses de courriel"
msgid "ApplicationSettings|Email restrictions for sign-ups"
-msgstr ""
+msgstr "Restrictions d'adresses de courriel pour les inscriptions"
msgid "ApplicationSettings|Enable Slack application"
-msgstr ""
+msgstr "Activer l'application Slack"
msgid "ApplicationSettings|Enable domain denylist for sign-ups"
-msgstr ""
+msgstr "Activer la liste d'exclusion de domaines pour les inscriptions"
msgid "ApplicationSettings|Enable email restrictions for sign-ups"
-msgstr ""
+msgstr "Activer les restrictions d'adresses de courriel pour les inscriptions"
msgid "ApplicationSettings|Enter denylist manually"
-msgstr ""
+msgstr "Entrez la liste d'exclusion manuellement"
msgid "ApplicationSettings|Minimum password length (number of characters)"
-msgstr ""
+msgstr "Longueur minimale du mot de passe (nombre de caractères)"
msgid "ApplicationSettings|Only users with e-mail addresses that match these domain(s) can sign up. Wildcards allowed. Use separate lines for multiple entries. Example: domain.com, *.domain.com"
-msgstr ""
+msgstr "Seuls les utilisateurs dont les adresses de courriel correspondent à ce(s) domaine(s ) peuvent s'inscrire. Les jokers sont autorisés. Pour plusieurs entrées, utilisez des lignes séparées. Exemple : domaine.com, *.domaine.com"
msgid "ApplicationSettings|Require admin approval for new sign-ups"
-msgstr ""
+msgstr "Exiger l'approbation de l'administrateur pour les nouvelles inscriptions"
msgid "ApplicationSettings|Require lowercase letters"
-msgstr ""
+msgstr "Nécessite des lettres minuscules"
msgid "ApplicationSettings|Require numbers"
-msgstr ""
+msgstr "Nécessite des chiffres"
msgid "ApplicationSettings|Require symbols"
-msgstr ""
+msgstr "Nécessite des symboles"
msgid "ApplicationSettings|Require uppercase letters"
-msgstr ""
+msgstr "Nécessite des lettres majuscules"
msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. %{linkStart}What is the supported syntax?%{linkEnd}"
-msgstr ""
+msgstr "Restreint les inscriptions aux adresses de courriel qui correspondent à l'expression rationnelle spécifiée. %{linkStart}Quelle est la syntaxe supportée ?%{linkEnd}"
msgid "ApplicationSettings|Save changes"
-msgstr ""
+msgstr "Enregistrer les modifications"
msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
-msgstr ""
+msgstr "Voir la %{linkStart}stratégie des mots de passe%{linkEnd}."
msgid "ApplicationSettings|Send confirmation email on sign-up"
-msgstr ""
+msgstr "Envoyer un courriel de confirmation lors de l'inscription"
msgid "ApplicationSettings|Sign-up enabled"
msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
-msgstr ""
+msgstr "Texte affiché après l’inscription d’un utilisateur. Markdown activé."
+
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr "Cette fonctionnalité n'est disponible que sur GitLab.com"
msgid "ApplicationSettings|This option is only available on GitLab.com"
-msgstr ""
+msgstr "Cette option est disponible uniquement sur GitLab.com"
msgid "ApplicationSettings|Upload denylist file"
-msgstr ""
+msgstr "Téléverser le fichier de liste d'exclusion"
msgid "ApplicationSettings|User cap"
-msgstr ""
+msgstr "Plafonnement utilisateur"
msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) cannot sign up. Wildcards allowed. Use separate lines for multiple entries. Example: domain.com, *.domain.com"
msgstr ""
msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) cannot sign up. Wildcards allowed. Use separate lines or commas for multiple entries."
-msgstr ""
+msgstr "Les utilisateurs dont les adresses de courriel correspondent à ce(s) domaine(s) ne peuvent pas s'inscrire. Les jokers sont autorisés. Pour plusieurs entrées, utilisez des lignes séparées ou des virgules."
msgid "ApplicationSettings|When enabled, new passwords must contain at least one lowercase letter (a-z)."
-msgstr ""
+msgstr "Avec cette option activée, les nouveaux mots de passe doivent contenir au minimum une lettre minuscule (de a à z)."
msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
-msgstr ""
+msgstr "Avec cette option activée, les nouveaux mots de passe doivent contenir au minimum un chiffre (de 0 à 9)."
msgid "ApplicationSettings|When enabled, new passwords must contain at least one symbol."
-msgstr ""
+msgstr "Avec cette option activée, les nouveaux mots de passe doivent contenir au minimum un symbole."
msgid "ApplicationSettings|When enabled, new passwords must contain at least one uppercase letter (A-Z)."
-msgstr ""
+msgstr "Avec cette option activée, les nouveaux mots de passe doivent contenir au minimum une lettre majuscule (de A à Z)."
msgid "ApplicationSettings|domain.com"
-msgstr ""
+msgstr "domaine.com"
msgid "Applications"
msgstr "Applications"
@@ -4721,8 +4786,8 @@ msgstr ""
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Appliquer %d suggestion"
+msgstr[1] "Appliquer %d suggestions"
msgid "Apply a label"
msgstr ""
@@ -4737,7 +4802,7 @@ msgid "Apply template"
msgstr ""
msgid "Apply this approval rule to all branches or a specific protected branch."
-msgstr ""
+msgstr "Appliquer cette règle d'approbation à toutes les branches ou à une branche protégée spécifique."
msgid "Applying"
msgstr ""
@@ -4755,19 +4820,19 @@ msgid "Applying multiple commands"
msgstr ""
msgid "Applying suggestion..."
-msgstr ""
+msgstr "Application de la suggestion..."
msgid "Applying suggestions..."
-msgstr ""
+msgstr "Application des suggestions..."
msgid "Approval rules"
msgstr ""
msgid "Approval rules reset to project defaults"
-msgstr ""
+msgstr "Règles d'approbation réinitialisées aux valeurs par défaut du projet"
msgid "Approval settings"
-msgstr ""
+msgstr "Paramètres d'approbation"
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
@@ -4776,13 +4841,13 @@ msgstr[1] ""
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} member%{strongEnd}. Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} members%{strongEnd}. Approvals from these members are not revoked."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Vous êtes sur le point de supprimer le groupe approbateur %{name} qui comporte %{strongStart}%{count} membre%{strongEnd}. Les approbations de ce membre ne sont pas révoquées."
+msgstr[1] "Vous êtes sur le point de supprimer le groupe approbateur %{name} qui comporte %{strongStart}%{count} membres%{strongEnd}. Les approbations de ces membres ne sont pas révoquées."
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d membre"
+msgstr[1] "%d membres"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
@@ -4790,118 +4855,118 @@ msgstr[0] ""
msgstr[1] ""
msgid "ApprovalRule|A merge request author collaborating with a merge request approver"
-msgstr ""
+msgstr "Un auteur de demande de fusion collaborant avec un approbateur de demande de fusion"
msgid "ApprovalRule|Add approvers"
-msgstr ""
+msgstr "Ajouter des approbateurs"
msgid "ApprovalRule|Approval rules"
-msgstr ""
+msgstr "Règles d'approbation"
msgid "ApprovalRule|Approvals required"
-msgstr ""
+msgstr "Approbations requises"
msgid "ApprovalRule|Approver Type"
-msgstr ""
+msgstr "Type d'Approbateur"
msgid "ApprovalRule|Approvers"
-msgstr ""
+msgstr "Approbateurs"
msgid "ApprovalRule|Confirmed"
-msgstr ""
+msgstr "Confirmée"
msgid "ApprovalRule|Dismissed"
-msgstr ""
+msgstr "Rejetée"
msgid "ApprovalRule|Examples: QA, Security."
-msgstr ""
+msgstr "Exemples : QA, Sécurité."
msgid "ApprovalRule|Improve your organization's code review with required approvals."
-msgstr ""
+msgstr "Améliorez la révision du code de votre organisation avec les approbations requises."
msgid "ApprovalRule|Increase quality and maintain standards."
-msgstr ""
+msgstr "Augmenter la qualité et maintenir les normes."
msgid "ApprovalRule|Learn more about merge request approval rules."
-msgstr ""
+msgstr "En savoir plus sur les règles d'approbation des demandes de fusion."
msgid "ApprovalRule|Name"
msgstr ""
msgid "ApprovalRule|Newly detected"
-msgstr ""
+msgstr "Récemment détectée"
msgid "ApprovalRule|Previously detected"
-msgstr ""
+msgstr "Précédemment détectée"
msgid "ApprovalRule|Reduce your time to merge."
msgstr ""
msgid "ApprovalRule|Resolved"
-msgstr ""
+msgstr "Résolue"
msgid "ApprovalRule|Rule name"
msgstr ""
msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
-msgstr ""
+msgstr "Sélectionnez les approbateurs éligibles par expertise ou fichiers modifiés."
msgid "ApprovalRule|Target branch"
msgstr ""
msgid "ApprovalRule|Try for free"
-msgstr ""
+msgstr "Essayer gratuitement"
msgid "ApprovalSettings|Keep approvals"
-msgstr ""
+msgstr "Conserver les approbations"
msgid "ApprovalSettings|Merge request approval settings have been updated."
-msgstr ""
+msgstr "Les paramètres d'approbation des demandes de fusion ont été mis à jour."
msgid "ApprovalSettings|Prevent approval by author"
-msgstr ""
+msgstr "Empêcher l'approbation par l'auteur"
msgid "ApprovalSettings|Prevent approvals by users who add commits"
-msgstr ""
+msgstr "Empêcher les approbations par les utilisateurs qui ajoutent des commits"
msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
-msgstr ""
+msgstr "Empêcher la modification des règles d'approbation dans les demandes de fusion"
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests"
-msgstr ""
+msgstr "Empêcher la modification des règles d'approbation dans les projets et les demandes de fusion"
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgstr "Empêcher la modification des règles d'approbation dans les projets et les demandes de fusion."
msgid "ApprovalSettings|Remove all approvals"
-msgstr ""
+msgstr "Supprimer toutes les approbations"
msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
-msgstr ""
+msgstr "Supprimer les approbations faites par les Propriétaires du Code si leurs fichiers ont été modifiés"
msgid "ApprovalSettings|Require user password to approve"
-msgstr ""
+msgstr "Exiger un mot de passe utilisateur pour approuver"
msgid "ApprovalSettings|There was an error loading merge request approval settings."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des paramètres d'approbation des demandes de fusion."
msgid "ApprovalSettings|There was an error updating merge request approval settings."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des paramètres d'approbation des demandes de fusion."
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 in the group settings by an administrator or group owner."
-msgstr ""
+msgstr "Ce paramètre est configuré dans %{groupName} et ne peut être modifié dans les paramètres du groupe que par un administrateur ou par un propriétaire du groupe."
msgid "ApprovalSettings|When a commit is added:"
-msgstr ""
+msgstr "Lorsqu'un commit est ajouté :"
msgid "Approvals are optional."
-msgstr ""
+msgstr "Les approbations sont facultatives."
msgid "Approvals|Section: %section"
-msgstr ""
+msgstr "Section : %section"
msgid "Approve"
msgstr ""
@@ -4910,7 +4975,7 @@ msgid "Approve a merge request"
msgstr ""
msgid "Approve merge request"
-msgstr ""
+msgstr "Approuver la demande de fusion"
msgid "Approve the current merge request."
msgstr ""
@@ -4943,7 +5008,7 @@ msgid "April"
msgstr "avril"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "Architecture introuvable pour le système d'exploitation"
msgid "Archive"
msgstr ""
@@ -4961,7 +5026,7 @@ msgid "Archived"
msgstr ""
msgid "Archived (%{movedToStart}moved%{movedToEnd})"
-msgstr ""
+msgstr "Archivé (%{movedToStart}déplacé%{movedToEnd})"
msgid "Archived in this version"
msgstr ""
@@ -4973,7 +5038,7 @@ msgid "Archived projects"
msgstr "Projets archivés"
msgid "Archiving the project makes it entirely read-only. It is hidden from the dashboard and doesn't display in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "L'archivage du projet met celui-ci en lecture seule dans sa totalité. Il est masqué sur le tableau de bord et n'est pas affiché dans les recherches. %{strong_start}Aucun commit ne pourra y être fait, et aucun ticket, commentaire ni autre entité ne pourra être créé.%{strong_end} %{link_start}En savoir plus.%{link_end}"
msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
msgstr ""
@@ -4982,7 +5047,7 @@ msgid "Are you absolutely sure?"
msgstr ""
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir archiver ce projet ?"
msgid "Are you sure that you want to destroy %{application}"
msgstr ""
@@ -4997,7 +5062,7 @@ msgid "Are you sure you want to approve %{user}?"
msgstr ""
msgid "Are you sure you want to attempt to merge?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir tenter la fusion ?"
msgid "Are you sure you want to cancel editing this %{commentType}?"
msgstr "Êtes-vous sûr de vouloir annuler la modification de ce %{commentType} ?"
@@ -5012,22 +5077,22 @@ msgid "Are you sure you want to delete these artifacts?"
msgstr ""
msgid "Are you sure you want to delete this %{commentType}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer ce %{commentType} ?"
msgid "Are you sure you want to delete this SSH key?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette clé SSH ?"
msgid "Are you sure you want to delete this comment?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?"
msgid "Are you sure you want to delete this deploy key?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette clé de déploiement ?"
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
msgid "Are you sure you want to delete this label?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette étiquette ?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Êtesâ€vous sûr·e de vouloir supprimer ce pipeline programmé ?"
@@ -5042,18 +5107,18 @@ msgid "Are you sure you want to discard this comment?"
msgstr ""
msgid "Are you sure you want to discard your changes?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir abandonner vos modifications ?"
msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Êtes-vous sûr de vouloir importer %d dépôt ?"
+msgstr[1] "Êtes-vous sûr de vouloir importer %d dépôts ?"
msgid "Are you sure you want to lock %{path}?"
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir verrouiller %{path} ?"
msgid "Are you sure you want to lock this directory?"
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir verrouiller ce répertoire ?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Êtesâ€vous vraiment prêt(e) à perdre les modifications non enregistrées ?"
@@ -5068,7 +5133,7 @@ msgid "Are you sure you want to re-deploy this environment?"
msgstr ""
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir réindexer ?"
msgid "Are you sure you want to remove %{email}?"
msgstr ""
@@ -5077,28 +5142,28 @@ msgid "Are you sure you want to remove %{group_name}?"
msgstr "Voulezâ€vous vraiment supprimer %{group_name} ?"
msgid "Are you sure you want to remove %{topic_name}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer %{topic_name} ?"
msgid "Are you sure you want to remove the attachment?"
msgstr "Êtes-vous sûr de vouloir supprimer la pièce jointe?"
msgid "Are you sure you want to remove the license?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer la licence ?"
msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer cette clé de déploiement ? Si quelque chose fait toujours usage de cette clé, cela va cesser de fonctionner."
msgid "Are you sure you want to remove this identity?"
msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette identité ?"
msgid "Are you sure you want to remove this list?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer cette liste ?"
msgid "Are you sure you want to remove this nickname?"
msgstr ""
msgid "Are you sure you want to reset the error tracking access token?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir réinitialiser le jeton d'accès du suivi des erreurs ?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton de bilan de santé ?"
@@ -5107,19 +5172,19 @@ msgid "Are you sure you want to reset the registration token?"
msgstr ""
msgid "Are you sure you want to retry this migration?"
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir retenter cette migration ?"
msgid "Are you sure you want to revoke this %{accessTokenType}? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir révoquer ce %{accessTokenType} ? Cette action ne peut pas être annulée."
msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
msgstr ""
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir révoquer ce jeton d'accès personnel ? Cette action ne peut pas être annulée."
msgid "Are you sure you want to revoke this project access token? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir révoquer ce jeton d'accès au projet ? Cette action ne peut pas être annulée."
msgid "Are you sure you want to stop this environment?"
msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
@@ -5128,10 +5193,10 @@ msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Êtesâ€vous sûr·e de vouloir déverrouiller %{path_lock_path} ?"
msgid "Are you sure you want to unlock %{path}?"
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir déverrouiller %{path} ?"
msgid "Are you sure you want to unlock this directory?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir déverrouiller ce répertoire ?"
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -5146,7 +5211,7 @@ msgid "Are you sure? Removing this GPG key does not affect already signed commit
msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
-msgstr ""
+msgstr "Êtes-vous sûr(e) ? L'appareil sera déconnecté de GitLab et tous les jetons « se souvenir de moi » seront révoqués."
msgid "Arrange charts"
msgstr ""
@@ -5164,16 +5229,16 @@ msgid "Artifacts"
msgstr "Artéfacts"
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 "Comme nous développons toujours davantage de fonctions pour SAST, nous souhaiterions connaître votre avis sur la fonctionnalité de configuration SAST via %{linkStart}cet ticket%{linkEnd}."
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
msgid "AsanaService|Add commit messages as comments to Asana tasks."
-msgstr ""
+msgstr "Ajouter les messages de commit en tant que commentaires sur les tâches Asana."
msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
-msgstr ""
+msgstr "Liste des branches à inspecter automatiquement, séparées par des virgules. Laissez vide pour inclure toutes les branches."
msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
@@ -5182,13 +5247,13 @@ msgid "Ascending"
msgstr "Croissant"
msgid "Ask again later"
-msgstr ""
+msgstr "Redemander plus tard"
msgid "Ask someone with write access to resolve it."
msgstr ""
msgid "Ask your group owner to set up a group runner."
-msgstr ""
+msgstr "Demandez au propriétaire de votre groupe la mise en place d'un exécuteur de groupe."
msgid "Assertion consumer service URL"
msgstr "URL du service consommateur d’assertion"
@@ -5218,7 +5283,7 @@ msgid "Assign milestone"
msgstr "Attribuer un jalon"
msgid "Assign myself"
-msgstr ""
+msgstr "Me l'attribuer"
msgid "Assign reviewer"
msgstr ""
@@ -5227,7 +5292,7 @@ msgid "Assign reviewer(s)"
msgstr ""
msgid "Assign severity"
-msgstr ""
+msgstr "Attribuer la gravité"
msgid "Assign some issues to this milestone."
msgstr ""
@@ -5242,7 +5307,7 @@ msgid "Assign to me"
msgstr "Me l'assigner"
msgid "Assigned %{assignee_users_sentence}."
-msgstr ""
+msgstr "%{assignee_users_sentence} attribué."
msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
msgstr ""
@@ -5251,10 +5316,10 @@ msgid "Assigned Issues"
msgstr "Tickets assignés"
msgid "Assigned merge requests"
-msgstr ""
+msgstr "Demandes de fusion assignées"
msgid "Assigned projects"
-msgstr ""
+msgstr "Projets assignés"
msgid "Assigned to %{assigneeName}"
msgstr "Assigné à %{assigneeName}"
@@ -5270,11 +5335,11 @@ msgstr "Assigné à vous"
msgid "Assignee"
msgid_plural "%d Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Assigné"
+msgstr[1] "%d Assignés"
msgid "Assignee has no permissions"
-msgstr ""
+msgstr "L'assigné(e) n'a aucune autorisation"
msgid "Assignee lists not available with your current license"
msgstr "La liste des personnes assignées n’est pas disponible avec votre licence actuelle"
@@ -5295,34 +5360,37 @@ msgid "At least one approval from a code owner is required to change files match
msgstr "Au moins une approbation d’un propriétaire de code est requise pour modifier les fichiers correspondant aux règles de propriété du code (CODEOWNER)."
msgid "At least one field of %{one_of_required_fields} must be present"
-msgstr ""
+msgstr "Au moins un champ de %{one_of_required_fields} doit être présent"
msgid "At least one of group_id or project_id must be specified"
msgstr ""
msgid "At least one of your Personal Access Tokens is expired. %{generate_new}"
-msgstr ""
+msgstr "Au moins un de vos Jetons d'Accès Personnel a expiré. %{generate_new}"
msgid "At least one of your Personal Access Tokens will expire soon. %{generate_new}"
-msgstr ""
+msgstr "Au moins un de vos Jetons d'Accès Personnel va bientôt expirer. %{generate_new}"
msgid "At risk"
-msgstr ""
+msgstr "À risque"
msgid "Attach a file or image"
-msgstr ""
+msgstr "Joindre un fichier ou une image"
msgid "Attaching File - %{progress}"
msgstr "Ajout du fichier en pièce-jointe - %{progress}"
msgid "Attaching a file"
msgid_plural "Attaching %d files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Joindre un fichier"
+msgstr[1] "Joindre %d fichiers"
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Événements d’audit"
@@ -5333,13 +5401,13 @@ msgid "AuditLogs|(removed)"
msgstr ""
msgid "AuditLogs|Action"
-msgstr ""
+msgstr "Action"
msgid "AuditLogs|Author"
-msgstr ""
+msgstr "Auteur"
msgid "AuditLogs|Date"
-msgstr ""
+msgstr "Date"
msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
msgstr ""
@@ -5348,42 +5416,42 @@ msgid "AuditLogs|Failed to find %{type}. Please try again."
msgstr ""
msgid "AuditLogs|Group Events"
-msgstr ""
+msgstr "Événements de groupe"
msgid "AuditLogs|IP Address"
-msgstr ""
+msgstr "Adresse IP"
msgid "AuditLogs|Log"
-msgstr ""
+msgstr "Journaux"
msgid "AuditLogs|Member Events"
msgstr ""
msgid "AuditLogs|No matching %{type} found."
-msgstr ""
+msgstr "Pas de %{type} qui corresponde."
msgid "AuditLogs|Object"
-msgstr ""
+msgstr "Objet"
msgid "AuditLogs|Project Events"
-msgstr ""
+msgstr "Événements de projet"
msgid "AuditLogs|Target"
-msgstr ""
+msgstr "Cible"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "Ce mois-ci"
msgid "AuditLogs|User Events"
-msgstr ""
+msgstr "Événements d’utilisateur"
msgid "AuditStreams|%d destination"
msgid_plural "AuditStreams|%d destinations"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d destination"
+msgstr[1] "%d destinations"
msgid "AuditStreams|A header with this name already exists."
-msgstr ""
+msgstr "Un en-tête portant ce nom existe déjà."
msgid "AuditStreams|Active"
msgstr ""
@@ -5398,16 +5466,16 @@ msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party sys
msgstr ""
msgid "AuditStreams|Add another custom header"
-msgstr ""
+msgstr "Ajouter un autre en-tête personnalisé"
msgid "AuditStreams|Add external stream destination"
msgstr ""
msgid "AuditStreams|Add header"
-msgstr ""
+msgstr "Ajouter un en-tête"
msgid "AuditStreams|Add streaming destination"
-msgstr ""
+msgstr "Ajouter une destination de flux"
msgid "AuditStreams|An error occurred when creating external audit event stream destination. Please try it again."
msgstr ""
@@ -5425,43 +5493,43 @@ msgid "AuditStreams|Cancel editing"
msgstr ""
msgid "AuditStreams|Custom HTTP headers (optional)"
-msgstr ""
+msgstr "En-têtes HTTP personnalisés (facultatif)"
msgid "AuditStreams|Delete %{link}"
msgstr ""
msgid "AuditStreams|Destination URL"
-msgstr ""
+msgstr "URL de destination"
msgid "AuditStreams|Destinations receive all audit event data"
msgstr ""
msgid "AuditStreams|Edit %{link}"
-msgstr ""
+msgstr "Modifier %{link}"
msgid "AuditStreams|Header"
-msgstr ""
+msgstr "En-tête"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
-msgstr ""
+msgstr "Le maximum de %{number} en-têtes HTTP a été atteint."
msgid "AuditStreams|Remove custom header"
-msgstr ""
+msgstr "Supprimer l'en-tête personnalisé"
msgid "AuditStreams|Save external stream destination"
-msgstr ""
+msgstr "Sauvegarder la destination du flux externe"
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
msgid "AuditStreams|Stream added successfully"
-msgstr ""
+msgstr "Flux ajouté avec succès"
msgid "AuditStreams|Stream deleted successfully"
-msgstr ""
+msgstr "Flux supprimé avec succès"
msgid "AuditStreams|Stream updated successfully"
-msgstr ""
+msgstr "Flux mis à jour avec succès"
msgid "AuditStreams|Streams"
msgstr ""
@@ -5473,10 +5541,10 @@ msgid "AuditStreams|This is great for keeping everything one place."
msgstr ""
msgid "AuditStreams|Value"
-msgstr ""
+msgstr "Valeur"
msgid "AuditStreams|Verification token"
-msgstr ""
+msgstr "Jeton de vérification"
msgid "Aug"
msgstr "août"
@@ -5494,28 +5562,28 @@ msgid "Authenticate with GitHub"
msgstr ""
msgid "Authenticated API rate limit period in seconds"
-msgstr ""
+msgstr "Limitation de fréquence des requêtes d'API authentifiées en secondes"
msgid "Authenticated API requests"
-msgstr ""
+msgstr "Requêtes D'API authentifiées"
msgid "Authenticated Git LFS rate limit period in seconds"
-msgstr ""
+msgstr "Durée de la limitation des requêtes Git LFS authentifiées en secondes"
msgid "Authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "Limitation des requêtes Git LFS authentifiées"
msgid "Authenticated Git LFS requests"
-msgstr ""
+msgstr "Requêtes Git LFS authentifiées"
msgid "Authenticated web rate limit period in seconds"
-msgstr ""
+msgstr "Limitation de fréquence des requêtes Web authentifiées en secondes"
msgid "Authenticated web requests"
-msgstr ""
+msgstr "Requêtes web authentifiées"
msgid "Authentication"
-msgstr ""
+msgstr "Authentification"
msgid "Authentication Failure"
msgstr ""
@@ -5524,7 +5592,7 @@ msgid "Authentication Log"
msgstr "Journal d’authentification"
msgid "Authentication error: enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}"
-msgstr ""
+msgstr "Erreur d'authentification : activez l'A2F dans les paramètres de votre profil pour continuer à utiliser GitLab : %{mfa_help_page}"
msgid "Authentication failed: %{error_message}"
msgstr ""
@@ -5542,16 +5610,16 @@ msgid "Authentication via U2F device failed."
msgstr ""
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "L'authentification via l'appareil WebAuthn a échoué."
msgid "Author"
msgstr "Auteur·e"
msgid "Author: %{author_name}"
-msgstr ""
+msgstr "Auteur : %{author_name}"
msgid "Authored %{timeago}"
-msgstr ""
+msgstr "Rédigé %{timeago}"
msgid "Authored %{timeago} by %{author}"
msgstr ""
@@ -5560,10 +5628,10 @@ msgid "Authorization code:"
msgstr "Code d’autorisation :"
msgid "Authorization required"
-msgstr ""
+msgstr "Autorisation requise"
msgid "Authorization token duration (minutes)"
-msgstr ""
+msgstr "Durée d'un jeton d'autorisation (minutes)"
msgid "Authorization was granted by entering your username and password in the application."
msgstr "L’autorisation a été accordée via la saisie de vos nom d’utilisateur et mot de passe dans l’application."
@@ -5575,7 +5643,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "Autoriser %{link_to_client} à utiliser votre compte ?"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "Autoriser %{user} à utiliser votre compte ?"
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -5587,10 +5655,10 @@ msgid "Authorized applications (%{size})"
msgstr "Applications autorisées (%{size})"
msgid "AuthorizedApplication|Are you sure you want to revoke this application?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir révoquer cette application ?"
msgid "AuthorizedApplication|Revoke application"
-msgstr ""
+msgstr "Révoquer l'application"
msgid "Authors: %{authors}"
msgstr "Auteur·e·s : %{authors}"
@@ -5605,13 +5673,13 @@ msgid "Auto stop successfully canceled."
msgstr ""
msgid "Auto-cancel redundant pipelines"
-msgstr ""
+msgstr "Annulation auto des pipelines redondants"
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}Automatisez la construction, le test et le déploiement%{auto_devops_end} de vos applications selon votre configuration d'intégration et de livraison continues. %{quickstart_start}Comment commencer ?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -5620,7 +5688,7 @@ msgid "AutoDevOps|Auto DevOps documentation"
msgstr "documentation Auto DevOps"
msgid "AutoDevOps|Dismiss Auto DevOps box"
-msgstr ""
+msgstr "Fermer la boîte Auto DevOps"
msgid "AutoDevOps|Enable in settings"
msgstr "Activer dans les paramètres"
@@ -5635,31 +5703,31 @@ msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if
msgstr ""
msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "Outils de test de sécurité activés avec %{linkStart}Auto DevOps%{linkEnd}"
msgid "AutoRemediation| 1 Merge Request"
-msgstr ""
+msgstr "1 Demande de Fusion"
msgid "AutoRemediation|%{mrsCount} ready for review"
msgstr ""
msgid "AutoRemediation|Auto-fix"
-msgstr ""
+msgstr "Correction auto"
msgid "AutoRemediation|Auto-fix solutions"
-msgstr ""
+msgstr "Solutions de correction automatique"
msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
-msgstr ""
+msgstr "Si vous utilisez une analyse de dépendance et/ou de conteneur, et que la correction automatique est activée, la correction automatique crée automatiquement des demandes de fusion avec des corrections de vulnérabilités."
msgid "AutoRemediation|Introducing GitLab auto-fix"
-msgstr ""
+msgstr "Introduction à la correction automatique de 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 ""
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "Restaurer automatiquement le dernier déploiement réussi lorsqu'un problème critique est détecté."
msgid "AutoRollback|Enable automatic rollbacks"
msgstr ""
@@ -5686,7 +5754,7 @@ msgid "Automatic deployment rollbacks"
msgstr ""
msgid "Automatic event tracking provides a traceable history for audits."
-msgstr ""
+msgstr "Le suivi automatique des événements fournit un historique traçable pour les audits."
msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
@@ -5695,10 +5763,10 @@ msgid "Automatically resolved"
msgstr ""
msgid "Automatically update this project's branches and tags from the upstream repository."
-msgstr ""
+msgstr "Mettre à jour automatiquement les branches et les étiquettes de ce projet à partir du dépôt amont."
msgid "Autosave|Note"
-msgstr ""
+msgstr "Note"
msgid "Available"
msgstr "Disponible"
@@ -5707,13 +5775,13 @@ msgid "Available ID"
msgstr ""
msgid "Available group runners: %{runners}"
-msgstr ""
+msgstr "Exécuteurs de groupe disponibles : %{runners}"
msgid "Available on-demand"
msgstr ""
msgid "Available shared runners:"
-msgstr ""
+msgstr "Exécuteurs partagés disponibles :"
msgid "Available specific runners"
msgstr ""
@@ -5731,16 +5799,16 @@ msgid "Awaiting user signup"
msgstr ""
msgid "Award added"
-msgstr ""
+msgstr "Récompense ajoutée"
msgid "Award removed"
-msgstr ""
+msgstr "Récompense supprimée"
msgid "AwardEmoji|No emojis found."
-msgstr ""
+msgstr "Aucun émoji trouvé."
msgid "Back"
-msgstr ""
+msgstr "Retour"
msgid "Back to page %{number}"
msgstr ""
@@ -5758,19 +5826,19 @@ msgid "Background color"
msgstr "Couleur d’arrièreâ€plan"
msgid "BackgroundMigrations|Background Migrations"
-msgstr ""
+msgstr "Migrations en arrière-plan"
msgid "BackgroundMigrations|Background migrations are used to perform data migrations whenever a migration exceeds the time limits in our guidelines. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Les migrations en arrière-plan sont utilisées pour effectuer des migrations de données chaque fois qu'une migration dépasse les limites de temps de nos directives. %{linkStart}En savoir plus%{linkEnd}"
msgid "BackgroundMigrations|Batch size"
-msgstr ""
+msgstr "Taille du lot"
msgid "BackgroundMigrations|Database"
-msgstr ""
+msgstr "Base de données"
msgid "BackgroundMigrations|Failed jobs:"
-msgstr ""
+msgstr "Tâches en échec :"
msgid "BackgroundMigrations|Finished at"
msgstr ""
@@ -5794,7 +5862,7 @@ msgid "Badges|Badge image preview"
msgstr "Aperçu de l’image du badge"
msgid "Badges|Badge saved."
-msgstr ""
+msgstr "Badge enregistré."
msgid "Badges|Delete badge?"
msgstr "Supprimer le badge ?"
@@ -5839,7 +5907,7 @@ msgid "Badges|Saving the badge failed, please check the entered URLs and try aga
msgstr "L’enregistrement du badge a échoué. Veuillez vérifier les URL entrées et réessayer."
msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
-msgstr ""
+msgstr "%{docsLinkStart}Variables%{docsLinkEnd} prises en charge : %{placeholders}"
msgid "Badges|The badge was deleted."
msgstr "Le badge a été supprimé."
@@ -5851,40 +5919,40 @@ msgid "Badges|This project has no badges"
msgstr "Ce projet n’a pas de badge"
msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer ce badge. Les badges supprimés %{strongStart}ne peuvent pas%{strongEnd} être restaurés."
msgid "Badges|Your badges"
msgstr "Vos badges numériques"
msgid "BambooService|Atlassian Bamboo"
-msgstr ""
+msgstr "Atlassian Bamboo"
msgid "BambooService|Bamboo URL"
-msgstr ""
+msgstr "URL de Bamboo"
msgid "BambooService|Bamboo build plan key."
-msgstr ""
+msgstr "Clé du plan de construction Bamboo."
msgid "BambooService|Bamboo service root URL."
-msgstr ""
+msgstr "URL racine du service Bamboo."
msgid "BambooService|Enter new build key"
-msgstr ""
+msgstr "Entrez une nouvelle clé"
msgid "BambooService|Leave blank to use your current build key."
-msgstr ""
+msgstr "Laissez vide pour utiliser votre clé de build actuelle."
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec 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 "Exécutez des pipelines CI/CD avec Atlassian Bamboo. Vous devez configurer l'étiquetage automatique des révisions et un déclencheur de dépôt dans Bamboo. %{docs_link}"
msgid "BambooService|The user with API access to the Bamboo server."
-msgstr ""
+msgstr "L'utilisateur ayant accès à l'API du serveur Bamboo."
msgid "Banned"
-msgstr ""
+msgstr "Banni"
msgid "Banner message"
msgstr ""
@@ -5896,16 +5964,16 @@ msgid "Batch size"
msgstr ""
msgid "Batched Job|Background Migrations"
-msgstr ""
+msgstr "Migrations en arrière-plan"
msgid "Batched Job|Batched Job (Id: %{id})"
-msgstr ""
+msgstr "Tâche par lots (Id : %{id})"
msgid "BatchedJob|Attempts"
-msgstr ""
+msgstr "Tentatives"
msgid "BatchedJob|Batch size"
-msgstr ""
+msgstr "Taille du lot"
msgid "BatchedJob|Batched Jobs"
msgstr ""
@@ -5932,22 +6000,22 @@ msgid "BatchedJob|Finished at"
msgstr ""
msgid "BatchedJob|Max Value"
-msgstr ""
+msgstr "Valeur Max"
msgid "BatchedJob|Max value"
-msgstr ""
+msgstr "Valeur max"
msgid "BatchedJob|Min Value"
-msgstr ""
+msgstr "Valeur min"
msgid "BatchedJob|Min value"
-msgstr ""
+msgstr "Valeur min"
msgid "BatchedJob|Next Status"
-msgstr ""
+msgstr "Statut suivant"
msgid "BatchedJob|Next status"
-msgstr ""
+msgstr "Statut suivant"
msgid "BatchedJob|Pause ms"
msgstr ""
@@ -5956,13 +6024,13 @@ msgid "BatchedJob|Pause time (ms)"
msgstr ""
msgid "BatchedJob|Previous Status"
-msgstr ""
+msgstr "État précédent"
msgid "BatchedJob|Previous status"
-msgstr ""
+msgstr "État précédent"
msgid "BatchedJob|Started at"
-msgstr ""
+msgstr "Démarré à"
msgid "BatchedJob|Transition logs:"
msgstr ""
@@ -5974,10 +6042,10 @@ msgid "Be careful. Renaming a project's repository can have unintended side effe
msgstr ""
msgid "Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}"
-msgstr ""
+msgstr "Avant d'activer cette intégration, créez un crochet web pour le salon Google Chat dans lequel vous voulez recevoir les notifications de ce projet. %{docs_link}"
msgid "Before inserting code, be sure to read the comment that separated each code group."
-msgstr ""
+msgstr "Avant d'insérer du code, assurez-vous d'avoir lu le commentaire qui sépare chaque groupe de code."
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
msgstr ""
@@ -5989,11 +6057,14 @@ msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr ""
msgid "Below are the settings for %{link_to_gitlab_pages}."
-msgstr ""
+msgstr "Les paramètres de %{link_to_gitlab_pages} figurent ci-après."
msgid "Below you will find all the groups that are public."
msgstr "Vous trouverez ciâ€dessous tous les groupes publics."
+msgid "Beta"
+msgstr "Bêta"
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6004,55 +6075,55 @@ msgid "Billing"
msgstr "Facturation"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}"
-msgstr ""
+msgstr "%{group_name} utilise actuellement le %{plan_name}"
msgid "BillingPlans|10,000 CI/CD minutes per month"
-msgstr ""
+msgstr "10000 minutes CI/CD par mois"
msgid "BillingPlans|10GB transfer per month"
-msgstr ""
+msgstr "10 Go de transfert par mois"
msgid "BillingPlans|400 CI/CD minutes per month"
-msgstr ""
+msgstr "400 minutes CI/CD par mois"
msgid "BillingPlans|5 users per namespace"
-msgstr ""
+msgstr "5 utilisateurs par espace de noms"
msgid "BillingPlans|50,000 CI/CD minutes per month"
-msgstr ""
+msgstr "50000 minutes CI/CD par mois"
msgid "BillingPlans|5GB storage"
-msgstr ""
+msgstr "5 Go de stockage"
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Advanced CI/CD"
-msgstr ""
+msgstr "CI/CD avancé"
msgid "BillingPlans|All plans have unlimited (private) repositories."
-msgstr ""
+msgstr "Tous les forfaits incluent des dépôts (privés) illimités."
msgid "BillingPlans|All the features from Free"
-msgstr ""
+msgstr "Toutes les fonctionnalités de Free"
msgid "BillingPlans|All the features from Premium"
-msgstr ""
+msgstr "Toutes les fonctionnalités de Premium"
msgid "BillingPlans|Billed annually at %{price_per_year} USD"
-msgstr ""
+msgstr "Facturé annuellement à %{price_per_year} USD"
msgid "BillingPlans|Check out all groups"
-msgstr ""
+msgstr "Vérifier tous les groupes"
msgid "BillingPlans|Compliance"
-msgstr ""
+msgstr "Conformité"
msgid "BillingPlans|Congratulations, your free trial is activated."
-msgstr ""
+msgstr "Félicitations, votre essai gratuit est activé."
msgid "BillingPlans|End of availability for the Bronze Plan"
-msgstr ""
+msgstr "Fin de disponibilité pour le Forfait Bronze"
msgid "BillingPlans|Enhance team productivity and collaboration"
msgstr ""
@@ -6061,7 +6132,7 @@ msgid "BillingPlans|Enterprise agile planning"
msgstr ""
msgid "BillingPlans|Faster code reviews"
-msgstr ""
+msgstr "Revues de code plus rapides"
msgid "BillingPlans|Free forever features for individual users"
msgstr ""
@@ -6076,19 +6147,19 @@ msgid "BillingPlans|If you would like to downgrade your plan please contact %{su
msgstr ""
msgid "BillingPlans|Includes free static websites"
-msgstr ""
+msgstr "Inclut les sites Web statiques gratuits"
msgid "BillingPlans|Learn more"
-msgstr ""
+msgstr "En savoir plus"
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 "Renseignez-vous sur nos forfaits en lisant notre %{faq_link} ou essayez gratuitement l’édition Ultimate sur GitLab.com pendant 30 jours."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
-msgstr ""
+msgstr "Vous cherchez à acheter ou gérer un abonnement pour votre groupe ? Accédez à vos %{groups_link} puis allez sur %{strong_open}Paramètres &gt; Facturation%{strong_close}"
msgid "BillingPlans|Loved and trusted by our customers"
msgstr ""
@@ -6097,25 +6168,25 @@ msgid "BillingPlans|Manage plan"
msgstr "Gérer les forfaits"
msgid "BillingPlans|Not the group you're looking for? %{all_groups_link}."
-msgstr ""
+msgstr "Ce n'est pas le groupe que vous recherchez ? %{all_groups_link}."
msgid "BillingPlans|Open Source - MIT License"
msgstr ""
msgid "BillingPlans|Organization wide security, compliance and planning"
-msgstr ""
+msgstr "Sécurité, conformité et planification à l'échelle de l'organisation"
msgid "BillingPlans|Portfolio management"
msgstr ""
msgid "BillingPlans|Premium"
-msgstr ""
+msgstr "Premium"
msgid "BillingPlans|Pricing page"
msgstr ""
msgid "BillingPlans|Ready to explore the value of the paid features today? Start a trial, no credit card required."
-msgstr ""
+msgstr "Prêt à découvrir la valeur des fonctionnalités payantes aujourd'hui ? Commencez une période d'essai, aucune carte de crédit n'est nécessaire."
msgid "BillingPlans|Recommended"
msgstr ""
@@ -6133,16 +6204,16 @@ msgid "BillingPlans|Self-managed reliability"
msgstr ""
msgid "BillingPlans|Spans the DevOps lifecycle"
-msgstr ""
+msgstr "Couvre le cycle de vie DevOps"
msgid "BillingPlans|Start a free Ultimate trial"
msgstr ""
msgid "BillingPlans|Still have questions?"
-msgstr ""
+msgstr "D'autres questions ?"
msgid "BillingPlans|Support"
-msgstr ""
+msgstr "Support"
msgid "BillingPlans|Talk to an expert today."
msgstr ""
@@ -6154,7 +6225,7 @@ msgid "BillingPlans|To manage the plan for this group, visit the billing section
msgstr "Pour gérer le forfait de ce groupe, rendez vous à la section facturation de %{parent_billing_page_link}."
msgid "BillingPlans|Ultimate"
-msgstr ""
+msgstr "Ultimate"
msgid "BillingPlans|Upgrade to Premium"
msgstr ""
@@ -6163,40 +6234,40 @@ msgid "BillingPlans|Upgrade to Ultimate"
msgstr ""
msgid "BillingPlans|Value stream management"
-msgstr ""
+msgstr "Gestion de la chaîne de valeur"
msgid "BillingPlans|We're here to help."
-msgstr ""
+msgstr "Nous sommes là pour vous aider."
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 "Alors que GitLab met fin à la disponibilité du forfait Bronze, il vous est toujours possible de renouveler votre abonnement Bronze une dernière fois avant %{eoa_bronze_plan_end_date}. Nous proposons également pour une durée limitée une mise à niveau gratuite vers notre forfait Premium (jusqu'à 25 utilisateurs) ! En savoir plus sur les modifications et offres sur notre %{announcement_link}."
msgid "BillingPlans|You don't have any groups. You'll need to %{create_group_link_start}create one%{create_group_link_end} and %{move_link_start}move this project to it%{move_link_end}."
msgstr ""
msgid "BillingPlans|You'll have to %{move_link_start}move this project%{move_link_end} to one of your groups."
-msgstr ""
+msgstr "Vous aurez à %{move_link_start}déplacer ce projet%{move_link_end} dans un de vos groupes."
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
-msgstr ""
+msgstr "Votre essai de GitLab.com %{plan} va %{strong_open}expirer après %{expiration_date}%{strong_close}. Vous pouvez conserver l'accès aux fonctionnalités %{plan} en faisant la mise à niveau ci-dessous."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
msgstr ""
msgid "BillingPlans|Your current plan"
-msgstr ""
+msgstr "Votre forfait actuel"
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr ""
msgid "BillingPlans|for the remainder of your subscription"
-msgstr ""
+msgstr "pour le reste de votre abonnement"
msgid "BillingPlans|frequently asked questions"
msgstr "foire aux questions"
msgid "BillingPlans|group"
-msgstr ""
+msgstr "groupe"
msgid "BillingPlans|monthly"
msgstr "mensuel"
@@ -6205,7 +6276,7 @@ msgid "BillingPlans|per user"
msgstr "par utilisateur"
msgid "BillingPlans|per user/month"
-msgstr ""
+msgstr "par utilisateur/mois"
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -6214,37 +6285,37 @@ msgid "BillingPlan|Upgrade for free"
msgstr ""
msgid "Billings|%{planName} plan"
-msgstr ""
+msgstr "Forfait %{planName}"
msgid "Billings|An error occurred while extending your trial."
msgstr ""
msgid "Billings|An error occurred while reactivating your trial."
-msgstr ""
+msgstr "Une erreur est survenue lors de la réactivation de votre essai."
msgid "Billings|By extending your trial, you will receive an additional 30 days of %{planName}. Your trial can be only extended once."
-msgstr ""
+msgstr "En prolongeant votre essai, vous bénéficierez de 30 jours supplémentaires sur %{planName}. Votre essai ne peut être prolongé qu'une seule fois."
msgid "Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once."
-msgstr ""
+msgstr "En réactivant votre essai, vous bénéficierez de 30 jours supplémentaires sur %{planName}. Votre essai ne peut être réactivé qu'une seule fois."
msgid "Billings|Error validating card details"
msgstr ""
msgid "Billings|Extend trial"
-msgstr ""
+msgstr "Prolonger l'essai"
msgid "Billings|Free groups are limited to %{number} seats."
-msgstr ""
+msgstr "Les groupes gratuits sont limités à %{number} sièges."
msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
-msgstr ""
+msgstr "Les groupes dans les éditions Gratuite ou d'essai peuvent inviter au maximum 20 membres par jour."
msgid "Billings|In a seat"
msgstr ""
msgid "Billings|Reactivate trial"
-msgstr ""
+msgstr "Réactiver l'essai"
msgid "Billings|Seats in use / Seats available"
msgstr ""
@@ -6253,117 +6324,120 @@ msgid "Billings|Seats in use / Seats in subscription"
msgstr ""
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr ""
+msgstr "Les exécuteurs partagés ne peuvent pas être activés tant qu'aucune carte de crédit valide n'est enregistrée."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 ""
+msgstr "Pour utiliser des minutes CI/CD gratuites avec les exécuteurs partagés, vous devrez valider votre compte avec une carte de crédit. Si vous préférez ne pas en fournir une, vous pourrez exécuter des pipelines par l'apport de vos propres exécuteurs et la désactivation des exécuteurs partagés de votre projet. Cela est nécessaire pour décourager et réduire les abus sur l'infrastructure de GitLab. %{strongStart}GitLab ne débitera pas votre carte, celle-ci ne sera utilisée que pour la validation.%{strongEnd} %{linkStart}En savoir plus%{linkEnd}."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 ""
+msgstr "Pour utiliser des minutes CI/CD gratuites sur des exécuteurs partagés, vous devrez valider votre compte avec une carte de crédit. Ceci est nécessaire pour décourager et réduire les abus sur l'infrastructure de GitLab. %{strongStart}GitLab ne débitera pas votre carte, elle ne sera utilisée qu'à des fins de validation.%{strongEnd}"
msgid "Billings|User validation required"
msgstr ""
msgid "Billings|Validate account"
-msgstr ""
+msgstr "Valider le compte"
msgid "Billings|Validate user account"
-msgstr ""
+msgstr "Valider le compte utilisateur"
msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "Vous êtes maintenant en mesure de profiter des minutes CI/CD gratuites sur les exécuteurs partagés."
msgid "Billings|Your account has been validated"
-msgstr ""
+msgstr "Votre compte a été validé"
msgid "Billing|%{user} was successfully approved"
msgstr ""
msgid "Billing|Add seats"
-msgstr ""
+msgstr "Ajouter des sièges"
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
msgid "Billing|An error occurred while approving %{user}"
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’approbation de %{user}"
msgid "Billing|An error occurred while getting a billable member details."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des détails d'un membre facturable."
msgid "Billing|An error occurred while loading GitLab subscription details."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des détails de l'abonnement GitLab."
msgid "Billing|An error occurred while loading billable members list."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de la liste des membres facturables."
msgid "Billing|An error occurred while loading pending members list"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de la liste des membres en attente"
msgid "Billing|An error occurred while removing a billable member."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression d'un membre facturable."
msgid "Billing|Awaiting member signup"
msgstr ""
msgid "Billing|Cannot remove user"
-msgstr ""
+msgstr "Impossible de supprimer l'utilisateur"
msgid "Billing|Direct memberships"
-msgstr ""
+msgstr "Adhésions directes"
msgid "Billing|Enter at least three characters to search."
msgstr "Entrez au moins trois caractères pour faire une recherche."
-msgid "Billing|Explore all plans"
-msgstr ""
+msgid "Billing|Explore paid plans"
+msgstr "Découvrez les forfaits payants"
msgid "Billing|Export list"
-msgstr ""
+msgstr "Exporter la liste"
msgid "Billing|Group invite"
msgstr ""
msgid "Billing|Groups in the Free tier are limited to %d seat"
msgid_plural "Billing|Groups in the Free tier are limited to %d seats"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Les groupes de l'édition Gratuite sont limités à %d siège"
+msgstr[1] "Les groupes de l'édition Gratuite sont limités à %d sièges"
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 "Les membres qui ont été invités via une invitation de groupe ne peuvent pas être supprimés. Vous pouvez soit supprimer l'ensemble du groupe, soit demander à un Propriétaire du groupe invité d'en supprimer le membre."
msgid "Billing|No users to display."
msgstr ""
msgid "Billing|Private"
-msgstr ""
+msgstr "Privé"
msgid "Billing|Project invite"
msgstr ""
msgid "Billing|Remove user %{username} from your subscription"
-msgstr ""
+msgstr "Supprimer l'utilisateur %{username} de votre abonnement"
msgid "Billing|To ensure all members can access the group when your trial ends, you can upgrade to a paid tier."
-msgstr ""
+msgstr "Pour vous assurer que tous les membres puissent accéder au groupe à la fin de votre période d'essai, vous pouvez effectuer une mise à niveau vers une édition payante."
msgid "Billing|Toggle seat details"
-msgstr ""
+msgstr "Afficher/masquer les détails du siège"
msgid "Billing|Type %{username} to confirm"
-msgstr ""
+msgstr "Tapez %{username} pour confirmer"
+
+msgid "Billing|Unlimited members during your trial"
+msgstr "Nombre illimité de membres pendant la période d'essai"
msgid "Billing|User was successfully removed"
-msgstr ""
+msgstr "L'utilisateur a été supprimé avec succès"
msgid "Billing|View pending approvals"
-msgstr ""
+msgstr "Afficher les approbations en attente"
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 "Vous êtes sur le point de supprimer l'utilisateur %{username} de votre abonnement. Si vous continuez, l'utilisateur sera supprimé du groupe %{namespace} ainsi que de tous ses sous-groupes et projets. Cette action ne pourra pas être annulée."
msgid "Billing|Your group recently changed to use the Free plan. %{over_limit_message} You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
-msgstr ""
+msgstr "Votre groupe a récemment changé pour utiliser le forfait Gratuit. %{over_limit_message} Vous pouvez libérer de l'espace pour les nouveaux membres en supprimant ceux qui n'ont plus besoin d'accès ou en les basculant au-delà de la limite. Pour que le nombre de membres ne soit plus limité, vous pouvez %{link_start}faire une mise à niveau%{link_end} vers une édition payante."
msgid "Bitbucket Server Import"
msgstr "Importation d’un serveur Bitbucket"
@@ -6375,33 +6449,33 @@ msgid "Bitbucket import"
msgstr "Importation de Bitbucket"
msgid "Blame"
-msgstr ""
+msgstr "Examiner"
msgid "BlobViewer|View on %{environmentName}"
-msgstr ""
+msgstr "Voir sur %{environmentName}"
msgid "Block user"
-msgstr ""
+msgstr "Bloquer l'utilisateur"
msgid "Blocked"
-msgstr ""
+msgstr "Bloqué"
msgid "Blocked by %d issue"
msgid_plural "Blocked by %d issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Bloqué par %d ticket"
+msgstr[1] "Bloqué par %d tickets"
msgid "Blocked issue"
-msgstr ""
+msgstr "Ticket bloqué"
msgid "Blocking"
msgstr ""
msgid "Blocking epics"
-msgstr ""
+msgstr "Épopées bloquantes"
msgid "Blocking issues"
-msgstr ""
+msgstr "Tickets bloquants"
msgid "Blocks"
msgstr ""
@@ -6410,19 +6484,19 @@ msgid "Blog"
msgstr "Blog"
msgid "Board scope affects which epics are displayed for anyone who visits this board"
-msgstr ""
+msgstr "La portée du tableau indique quelles épopées sont affichées pour toute les personnes visitant ce tableau"
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Groupes"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Chargement des groupes"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "BoardNewEpic|Search groups"
msgstr ""
@@ -6431,25 +6505,25 @@ msgid "BoardNewEpic|Select a group"
msgstr ""
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "BoardNewIssue|Projects"
-msgstr ""
+msgstr "Projets"
msgid "BoardNewIssue|Search projects"
msgstr "Rechercher des projets"
msgid "BoardNewIssue|Select a project"
-msgstr ""
+msgstr "Sélectionner un projet"
msgid "BoardScope|%{iterationTitle} iteration in %{iterationCadence}"
-msgstr ""
+msgstr "Itération %{iterationTitle} dans %{iterationCadence}"
msgid "BoardScope|An error occurred while getting iterations. Please try again."
msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des jalons, veuillez réessayer."
msgid "BoardScope|An error occurred while searching for labels, please try again."
msgstr "Une erreur s'est produite lors de la recherche des étiquettes, veuillez réessayer."
@@ -6458,37 +6532,37 @@ msgid "BoardScope|An error occurred while searching for users, please try again.
msgstr "Une erreur s'est produite lors de la recherche d'utilisateurs, veuillez réessayer."
msgid "BoardScope|Any Milestone"
-msgstr ""
+msgstr "N'importe quel Jalon"
msgid "BoardScope|Any assignee"
-msgstr ""
+msgstr "N'importe quel assigné"
msgid "BoardScope|Any iteration"
msgstr ""
msgid "BoardScope|Any label"
-msgstr ""
+msgstr "N'importe quelle étiquette"
msgid "BoardScope|Assignee"
-msgstr ""
+msgstr "Assigné(e)"
msgid "BoardScope|Choose labels"
-msgstr ""
+msgstr "Choisir les étiquettes"
msgid "BoardScope|Current iteration"
msgstr ""
msgid "BoardScope|Don't filter milestone"
-msgstr ""
+msgstr "Ne pas filtrer par jalon"
msgid "BoardScope|Edit"
-msgstr ""
+msgstr "Modifier"
msgid "BoardScope|Iteration"
msgstr ""
msgid "BoardScope|Labels"
-msgstr ""
+msgstr "Étiquettes"
msgid "BoardScope|Milestone"
msgstr "Jalon"
@@ -6518,83 +6592,83 @@ msgid "BoardScope|Select milestone"
msgstr "Sélectionner un jalon"
msgid "BoardScope|Select weight"
-msgstr ""
+msgstr "Sélectionnez le poids"
msgid "BoardScope|Started"
msgstr ""
msgid "BoardScope|Upcoming"
-msgstr ""
+msgstr "À venir"
msgid "BoardScope|Weight"
-msgstr ""
+msgstr "Poids"
msgid "Boards"
msgstr "Tableaux"
msgid "Boards and board lists"
-msgstr ""
+msgstr "Tableaux et listes de tableaux"
msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "+ %{displayedIssuablesCount} %{issuableType} de plus"
+msgstr[1] "+ %{displayedIssuablesCount} %{issuableType}s de plus"
msgid "Boards|An error occurred while creating the epic. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création de l'épopée. Veuillez réessayer."
msgid "Boards|An error occurred while creating the issue. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du ticket. Veuillez réessayer."
msgid "Boards|An error occurred while creating the list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création de la liste. Veuillez réessayer."
msgid "Boards|An error occurred while fetching child groups. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des groupes enfants. Veuillez réessayer."
msgid "Boards|An error occurred while fetching group projects. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets de groupe. Veuillez réessayer."
msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tickets. Veuillez recharger la page."
msgid "Boards|An error occurred while fetching labels. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étiquettes. Veuillez recharger la page."
msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tickets du tableau. Veuillez recharger la page."
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des lignes de séparation des tableaux. Veuillez recharger la page."
msgid "Boards|An error occurred while fetching the board. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération du tableau. Veuillez recharger la page."
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while moving the epic. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du déplacement de l'épopée. Veuillez réessayer."
msgid "Boards|An error occurred while moving the issue. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du déplacement du ticket. Veuillez réessayer."
msgid "Boards|An error occurred while removing the list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de la liste. Veuillez réessayer."
msgid "Boards|An error occurred while updating the board list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la liste des tableaux. Veuillez réessayer."
msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Blocage par %{blockedByCount} %{issuableType}"
+msgstr[1] "Blocage par %{blockedByCount} %{issuableType}s"
msgid "Boards|Collapse"
msgstr ""
@@ -6606,25 +6680,25 @@ msgid "Boards|Expand"
msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
-msgstr ""
+msgstr "Échec de la récupération des %{issuableType}s bloquant(e)s"
msgid "Boards|Move card"
-msgstr ""
+msgstr "Déplacer la carte"
msgid "Boards|Move to end of list"
-msgstr ""
+msgstr "Déplacer en fin de liste"
msgid "Boards|Move to start of list"
-msgstr ""
+msgstr "Déplacer en début de liste"
msgid "Boards|New board"
-msgstr ""
+msgstr "Nouveau tableau"
msgid "Boards|New epic"
-msgstr ""
+msgstr "Nouvelle épopée"
msgid "Boards|Retrieving blocking %{issuableType}s"
-msgstr ""
+msgstr "Récupération des %{issuableType}s bloquant(e)s"
msgid "Boards|View all blocking %{issuableType}s"
msgstr ""
@@ -6633,19 +6707,19 @@ msgid "Boards|View scope"
msgstr ""
msgid "Board|An error occurred while fetching the board, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération du tableau, veuillez réessayer."
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
msgid "Board|Board scope"
-msgstr ""
+msgstr "Portée du tableau"
msgid "Board|Create board"
msgstr ""
msgid "Board|Create new board"
-msgstr ""
+msgstr "Créer un nouveau tableau"
msgid "Board|Delete board"
msgstr ""
@@ -6654,28 +6728,31 @@ msgid "Board|Edit board"
msgstr ""
msgid "Board|Enter board name"
-msgstr ""
+msgstr "Entrer le nom du tableau"
msgid "Board|Failed to delete board. Please try again."
-msgstr ""
+msgstr "Échec de la suppression du tableau. Veuillez réessayer."
msgid "Board|Load more epics"
-msgstr ""
+msgstr "Charger plus d'épopées"
msgid "Board|Load more issues"
msgstr ""
msgid "Board|Loading epics"
-msgstr ""
+msgstr "Chargement des épopées"
msgid "Bold text"
-msgstr ""
+msgstr "Texte en gras"
+
+msgid "Bot"
+msgstr "Bot"
msgid "Both SSH and HTTP(S)"
-msgstr ""
+msgstr "SSH et HTTP(S)"
msgid "Both project and dashboard_path are required"
-msgstr ""
+msgstr "Le projet et dashboard_path sont tous deux requis"
msgid "Branch"
msgstr ""
@@ -6684,13 +6761,13 @@ msgid "Branch %{branchName} was not found in this project's repository."
msgstr "La branche %{branchName} n’a pas été trouvée dans le dépôt de ce projet."
msgid "Branch %{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 "La branche %{branch_name} a été créée. Pour mettre en place le déploiement automatique, choisissez un modèle Yaml GitLab CI puis validez vos modifications. %{link_to_autodeploy_doc}"
msgid "Branch already exists"
msgstr ""
msgid "Branch changed"
-msgstr ""
+msgstr "Branche modifiée"
msgid "Branch has been updated since the merge was requested."
msgstr ""
@@ -6707,56 +6784,113 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+msgstr "Les %{linkStart}caractères génériques%{linkEnd} tels que *-stable ou production/* sont pris en charge."
+
+msgid "BranchRules|All branches"
msgstr ""
-msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgid "BranchRules|All users with push access are allowed to force push."
msgstr ""
+msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr "Autoriser tous les utilisateurs ayant un accès pour pousser à %{linkStart}forcer les poussées%{linkEnd}."
+
msgid "BranchRules|Allowed to merge"
+msgstr "Autorisé à fusionner"
+
+msgid "BranchRules|Allowed to merge (%{total})"
msgstr ""
msgid "BranchRules|Allowed to push"
+msgstr "Autorisé à pousser"
+
+msgid "BranchRules|Allowed to push (%{total})"
msgstr ""
msgid "BranchRules|An error occurred while fetching branches."
+msgstr "Une erreur s'est produite lors de la récupération des branches."
+
+msgid "BranchRules|Approvals"
msgstr ""
msgid "BranchRules|Branch"
+msgstr "Branche"
+
+msgid "BranchRules|Branch name or pattern"
msgstr ""
+msgid "BranchRules|Branch rules details"
+msgstr "Détails des règles de branche"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr "Créer un joker : %{searchTerm}"
+
+msgid "BranchRules|Details"
msgstr ""
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "Groupes"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr "Conservez les branches stables sécurisées et forcez les développeurs à utiliser des demandes de fusion. %{linkStart}Que sont les branches protégées ?%{linkEnd}"
+
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
msgstr ""
msgid "BranchRules|No matching results"
+msgstr "Aucun résultat correspondant"
+
+msgid "BranchRules|Protect branch"
msgstr ""
msgid "BranchRules|Protections"
-msgstr ""
+msgstr "Protections"
msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
-msgstr ""
+msgstr "Rejeter les poussées de code qui modifient les fichiers répertoriés dans le fichier CODEOWNERS."
msgid "BranchRules|Require approval from code owners."
+msgstr "Nécessiter l'approbation des propriétaires du code."
+
+msgid "BranchRules|Roles"
+msgstr "Rôles"
+
+msgid "BranchRules|Status checks"
msgstr ""
+msgid "BranchRules|Target Branch"
+msgstr "Branche cible"
+
+msgid "BranchRules|Users"
+msgstr "Utilisateurs"
+
msgid "BranchRules|default"
-msgstr ""
+msgstr "par défaut"
msgid "BranchRules|protected"
-msgstr ""
+msgstr "protégée"
msgid "Branches"
msgstr "Branches"
msgid "Branches: %{source_branch} to %{target_branch}"
-msgstr ""
+msgstr "Branches : %{source_branch} vers %{target_branch}"
msgid "Branches: %{source_branch} → %{target_branch}"
-msgstr ""
+msgstr "Branches : %{source_branch} → %{target_branch}"
msgid "Branches|Active"
msgstr "Active"
@@ -6765,13 +6899,13 @@ msgid "Branches|Active branches"
msgstr "Branches actives"
msgid "Branches|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this branch."
-msgstr ""
+msgstr "Une fois que vous aurez confirmé et cliqué sur %{strongStart}%{buttonText}%{strongEnd}, vous ne pourrez plus restaurer cette branche."
msgid "Branches|All"
msgstr "Toutes"
msgid "Branches|Cancel, keep branch"
-msgstr ""
+msgstr "Annuler, conserver la branche"
msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
@@ -6786,7 +6920,7 @@ msgid "Branches|Delete branch"
msgstr "Supprimer cette branche"
msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Supprimer la branche. Êtes-vous ABSOLUMENT SÛR(E) ?"
msgid "Branches|Delete merged branches"
msgstr "Supprimer les branches fusionnées"
@@ -6795,10 +6929,10 @@ msgid "Branches|Delete protected branch"
msgstr "Supprimer cette branche protégée"
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Supprimer la branche protégée. Êtes-vous ABSOLUMENT SÛR(E) ?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "La suppression de la branche %{strongStart}%{branchName}%{strongEnd} ne peut être annulée. Êtes-vous sûr ?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "La suppression des branches fusionnées ne peut être annulée. Êtesâ€vous sûr(e) ?"
@@ -6822,7 +6956,7 @@ msgid "Branches|Overview"
msgstr "Vue d’ensemble"
msgid "Branches|Please type the following to confirm:"
-msgstr ""
+msgstr "Veuillez taper ce qui suit pour confirmer :"
msgid "Branches|Show active branches"
msgstr "Afficher les branches actives"
@@ -6855,25 +6989,25 @@ msgid "Branches|The default branch cannot be deleted"
msgstr "La branche par défaut ne peut pas être supprimée"
msgid "Branches|This branch hasn't been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
+msgstr "Cette branche n'a pas été fusionnée dans %{defaultBranchName}. Pour éviter la perte de données, envisagez de la fusionner avant de la supprimer."
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Pour rejeter les changements locaux et écraser la branche avec la version du dépôt en amont, veuillez la supprimer ici et cliquer sur « Mettre à jour maintenant » ciâ€dessus."
msgid "Branches|Unable to load branches"
-msgstr ""
+msgstr "Impossible de charger les branches"
msgid "Branches|Yes, delete branch"
-msgstr ""
+msgstr "Oui, supprimer la branche"
msgid "Branches|Yes, delete protected branch"
-msgstr ""
+msgstr "Oui, supprimer la branche protégée"
msgid "Branches|You're about to permanently delete the branch %{branchName}."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement la branche %{branchName}."
msgid "Branches|You're about to permanently delete the protected branch %{branchName}."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement la branche protégée %{branchName}."
msgid "Branches|diverged from upstream"
msgstr "en divergence du dépôt en amont"
@@ -6894,7 +7028,7 @@ msgid "Broadcast Message was successfully updated."
msgstr "Le message de diffusion a été mis à jour avec succès."
msgid "Broadcast Messages"
-msgstr ""
+msgstr "Messages de diffusion"
msgid "Browse Directory"
msgstr "Parcourir le dossier"
@@ -6912,7 +7046,7 @@ msgid "Browse files"
msgstr "Parcourir les fichiers"
msgid "Browse templates"
-msgstr ""
+msgstr "Parcourir les modèles"
msgid "Build cannot be erased"
msgstr ""
@@ -6924,19 +7058,19 @@ msgid "BuildArtifacts|Loading artifacts"
msgstr ""
msgid "Built-in"
-msgstr ""
+msgstr "Intégré"
msgid "Bulk request concurrency"
-msgstr ""
+msgstr "Concurrence des requêtes en bloc"
msgid "Bulk update"
msgstr ""
msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
-msgstr ""
+msgstr "%{host} fait tourner une ancienne version de GitLab (v%{version})"
msgid "BulkImport|%{feature} (require v%{version})"
-msgstr ""
+msgstr "%{feature} (nécessite la v%{version})"
msgid "BulkImport|Destination"
msgstr ""
@@ -6945,109 +7079,112 @@ msgid "BulkImport|Destination group"
msgstr ""
msgid "BulkImport|Existing groups"
-msgstr ""
+msgstr "Groupes existants"
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 ""
+msgstr "Les données suivantes ne seront pas migrées : %{bullets} Contactez l'administrateur système de %{host} pour mettre à jour GitLab si vous avez besoin d'inclure ces données dans votre migration"
msgid "BulkImport|From source group"
-msgstr ""
+msgstr "Depuis le groupe source"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "Historique d'importation de groupe"
msgid "BulkImport|History"
-msgstr ""
+msgstr "Historique"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
-msgstr ""
+msgstr "L'importation a échoué : La destination ne peut pas être un sous-groupe du groupe source. Modifiez la destination et réessayez."
msgid "BulkImport|Import groups from GitLab"
-msgstr ""
+msgstr "Importer des groupes depuis GitLab"
msgid "BulkImport|Import is finished. Pick another name for re-import"
-msgstr ""
+msgstr "L'importation est terminée. Choisissez un autre nom pour ré-importer"
msgid "BulkImport|Import selected"
-msgstr ""
+msgstr "Importer la sélection"
msgid "BulkImport|Importing the group failed."
-msgstr ""
+msgstr "L'importation du groupe a échoué."
msgid "BulkImport|Last imported to %{link}"
msgstr ""
msgid "BulkImport|Name already exists."
-msgstr ""
+msgstr "Le nom existe déjà."
msgid "BulkImport|Name already used as a target for another group."
-msgstr ""
+msgstr "Le nom est déjà utilisé comme cible pour un autre groupe."
msgid "BulkImport|No additional information provided."
msgstr ""
msgid "BulkImport|No groups found"
-msgstr ""
+msgstr "Aucun groupe trouvé"
msgid "BulkImport|No history is available"
msgstr ""
msgid "BulkImport|No parent"
-msgstr ""
+msgstr "Aucun parent"
msgid "BulkImport|Only groups that you have the %{role} role for are listed as groups you can import."
-msgstr ""
+msgstr "Seuls les groupes pour lesquels vous avez le rôle %{role} sont listés parmi ceux que vous pouvez importer."
msgid "BulkImport|Project import history"
msgstr ""
msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
-msgstr ""
+msgstr "La réimportation crée un nouveau groupe. Elle n'est pas synchronisée avec le groupe existant."
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
-msgstr ""
+msgstr "Affichage de %{start}-%{end} sur %{total}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own from %{link}"
-msgstr ""
+msgstr "Affichage de %{start}-%{end} parmi les %{total} que vous possédez sur %{link}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own matching filter \"%{filter}\" from %{link}"
-msgstr ""
+msgstr "Affichage de %{start}-%{end} parmi les %{total} que vous possédez et qui correspondent au filtre « %{filter} » sur %{link}"
msgid "BulkImport|Source"
msgstr ""
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "Groupe source"
msgid "BulkImport|Template / File-based import / GitLab Migration"
msgstr ""
msgid "BulkImport|To new group"
-msgstr ""
+msgstr "Vers un nouveau groupe"
msgid "BulkImport|Update of import statuses with realtime changes failed"
msgstr ""
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "Vos groupes importés apparaîtront ici."
msgid "BulkImport|Your imported projects will appear here."
-msgstr ""
+msgstr "Vos projets importés apparaîtront ici."
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
-msgstr ""
+msgstr "possède un Groupe associé alors que c'est un Projet qui était attendu"
+
+msgid "BulkImport|invalid entity source type"
+msgstr "type de source d'entité non valide"
msgid "BulkImport|must be a group"
msgstr ""
msgid "Bullet list"
-msgstr ""
+msgstr "Liste à puces"
msgid "Burndown chart"
msgstr ""
@@ -7059,61 +7196,61 @@ msgid "Burnup chart"
msgstr ""
msgid "Burnup chart could not be generated due to too many events"
-msgstr ""
+msgstr "Les graphiques d'avancement ne peuvent pas être générés en raison d'un trop grand nombre d'événements"
msgid "Business"
-msgstr ""
+msgstr "Entreprise"
msgid "Business metrics (Custom)"
msgstr "Métriques commerciales (personnalisées)"
msgid "Busy"
-msgstr ""
+msgstr "Occupé(e)"
msgid "Buy CI Minutes"
msgstr ""
msgid "Buy Storage"
-msgstr ""
+msgstr "Acheter du Stockage"
msgid "Buy more Pipeline minutes"
msgstr ""
msgid "By %{user_name}"
-msgstr ""
+msgstr "Par %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
-msgstr ""
+msgstr "En s'authentifiant avec un compte lié à une adresse électronique d'Entreprise, il est considéré que ce compte est un Utilisateur d'Entreprise. "
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
msgid "By month"
-msgstr ""
+msgstr "Par mois"
msgid "By quarter"
-msgstr ""
+msgstr "Par trimestre"
msgid "By week"
-msgstr ""
+msgstr "Par semaine"
msgid "ByAuthor|by"
msgstr "par"
msgid "CHANGELOG"
-msgstr ""
+msgstr "CHANGELOG"
msgid "CI Lint"
-msgstr ""
+msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}include%{codeEnd} keyword. %{link}"
-msgstr ""
+msgstr "Configuration CI validée, incluant toutes les configurations ajoutées avec le mot-clé %{codeStart}include%{codeEnd}. %{link}"
msgid "CI settings"
-msgstr ""
+msgstr "Paramètres CI"
msgid "CI variables"
-msgstr ""
+msgstr "Variables CI"
msgid "CI/CD"
msgstr "Intégration et livraison continues"
@@ -7128,7 +7265,7 @@ msgid "CI/CD configuration"
msgstr "Configuration de l’intégration et de la livraison continues"
msgid "CI/CD configuration file"
-msgstr ""
+msgstr "Fichier de configuration CI/CD"
msgid "CI/CD limits"
msgstr ""
@@ -7137,48 +7274,48 @@ msgid "CI/CD minutes"
msgstr ""
msgid "CI/CD|No projects have been added to the scope"
-msgstr ""
+msgstr "Aucun projet n'a été ajouté à la portée"
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
-msgstr ""
+msgstr "%{percent}%{percentSymbol}"
msgid "CICDAnalytics|All time"
msgstr ""
msgid "CICDAnalytics|Change failure rate"
-msgstr ""
+msgstr "Taux d’échec des changements"
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "Fréquence de déploiement"
msgid "CICDAnalytics|Lead time"
-msgstr ""
+msgstr "Délai de mise à disposition"
msgid "CICDAnalytics|No shared runner minute usage data available"
-msgstr ""
+msgstr "Aucune donnée d'utilisation des minutes d'exécuteur partagé n'est disponible"
msgid "CICDAnalytics|Projects with releases"
-msgstr ""
+msgstr "Projets avec versions"
msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Version"
+msgstr[1] "Versions"
msgid "CICDAnalytics|Release statistics"
-msgstr ""
+msgstr "Statistiques des versions"
msgid "CICDAnalytics|Releases"
-msgstr ""
+msgstr "Versions"
msgid "CICDAnalytics|Shared runner duration is the total runtime of all jobs that ran on shared runners"
-msgstr ""
+msgstr "La durée prise par les exécuteurs partagés correspond au temps d'exécution total de toutes les tâches qui ont été lancées par les exécuteurs partagés"
msgid "CICDAnalytics|Shared runner pipeline minute duration by month"
msgstr ""
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des statistiques de publication"
msgid "CICDAnalytics|Time to restore service"
msgstr ""
@@ -7187,13 +7324,13 @@ msgid "CICDAnalytics|What is shared runner duration?"
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 "Ajoutez un %{base_domain_link_start}domaine de base%{link_end} à votre %{kubernetes_cluster_link_start}grappe de serveurs Kubernetes%{link_end} pour que votre stratégie de déploiement fonctionne."
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 "Ajoutez une %{kubernetes_cluster_link_start}intégration de grappe de serveurs Kubernetes%{link_end} avec un domaine ou créez une variable CI AUTO_DEVOPS_PLATFORM_TARGET."
msgid "CICD|Add an existing project to the scope"
-msgstr ""
+msgstr "Ajouter un projet existant à la portée"
msgid "CICD|Auto DevOps"
msgstr "Auto DevOps"
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr "Stratégie de déploiement"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Tâches"
@@ -7225,14 +7365,14 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
-msgstr ""
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Sélectionner les projets accessibles par les requêtes API authentifiées avec la variable CI/CD CI_JOB_TOKEN de ce projet. Désactiver cette fonctionnalité constitue un risque pour la sécurité, car des projets non autorisés peuvent tenter de récupérer un jeton actif et accéder à l'API. %{linkStart}En savoir plus.%{linkEnd}"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
-msgstr ""
+msgstr "Le pipeline Auto DevOps s’exécute par défaut dans tous les projets sans fichier de configuration CI/CD. %{link_start}Qu’est-ce que Auto DevOps ?%{link_end}"
msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Le pipeline Auto DevOps s’exécute si aucun autre fichier de configuration CI n’est trouvé."
msgid "CICD|There are several CI/CD limits in place."
msgstr ""
@@ -7241,7 +7381,7 @@ msgid "CICD|Unprotected branches will not have access to the cache from protecte
msgstr ""
msgid "CICD|Use separate caches for protected branches"
-msgstr ""
+msgstr "Utiliser des caches distincts pour les branches protégées"
msgid "CICD|group enabled"
msgstr ""
@@ -7256,7 +7396,7 @@ msgid "CLOSED (MOVED)"
msgstr "FERMÉ (DÉPLACÉ)"
msgid "CODEOWNERS rule violation"
-msgstr ""
+msgstr "Violation de règle CODEOWNERS"
msgid "CONTRIBUTING"
msgstr ""
@@ -7265,58 +7405,58 @@ msgid "CPU"
msgstr ""
msgid "CSV is being generated and will be emailed to you upon completion."
-msgstr ""
+msgstr "Le CSV est en cours de génération et sera envoyé par courriel une fois celle-ci terminée."
msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
-msgstr ""
+msgstr "En tant que mainteneur, demander une CVE pour une vulnérabilité de votre projet contribuera à garder vos utilisateurs informés et en sécurité."
msgid "CVE|CVE ID Request"
-msgstr ""
+msgstr "Demande d'ID de CVE"
msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
-msgstr ""
+msgstr "Les identifiants Common Vulnerability Enumeration (CVE) servent à suivre des vulnérabilités distinctes dans des versions de code spécifiques."
msgid "CVE|Create CVE ID Request"
-msgstr ""
+msgstr "Créer une Demande d'ID de CVE"
msgid "CVE|Enable CVE ID requests in the issue sidebar"
-msgstr ""
+msgstr "Activer les demandes d'ID de CVE dans la barre latérale des tickets"
msgid "CVE|Request CVE ID"
msgstr ""
msgid "CVE|Why Request a CVE ID?"
-msgstr ""
+msgstr "Pourquoi Demander un ID de CVE ?"
msgid "Cadence is not automated"
-msgstr ""
+msgstr "La cadence n'est pas automatisée"
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 ""
+msgstr "Calculer le nombre de tranches lors de la réindexation. Le multiplicateur est appliqué au nombre de fragments par index. En savoir plus sur la %{slice_multiplier_link_start}configuration du multiplicateur de tranches %{slice_multiplier_link_end}."
msgid "Callback URL"
msgstr "URL de retour"
msgid "Campfire room ID (optional)"
-msgstr ""
+msgstr "ID du salon Campfire (facultatif)"
msgid "Campfire subdomain (optional)"
-msgstr ""
+msgstr "Sous-domaine Campfire (facultatif)"
msgid "Campfire token"
-msgstr ""
+msgstr "Jeton Campfire"
msgid "CampfireService|API authentication token from Campfire."
-msgstr ""
+msgstr "Jeton d'authentification d'API de Campfire."
msgid "CampfireService|From the end of the room URL."
-msgstr ""
+msgstr "Depuis la fin de l'URL du salon."
msgid "CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}"
-msgstr ""
+msgstr "Envoyer les notifications concernant les événements de poussées aux salons de discussion Campfire. %{docs_link}"
msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
-msgstr ""
+msgstr "Le sous-domaine %{code_open}.campfirenow.com%{code_close}."
msgid "Can be manually deployed to"
msgstr ""
@@ -7331,25 +7471,25 @@ msgid "Can not delete primary training"
msgstr ""
msgid "Can't apply as the source branch was deleted."
-msgstr ""
+msgstr "Impossible d'appliquer car la branche source a été supprimée."
msgid "Can't apply as these lines were changed in a more recent version."
-msgstr ""
+msgstr "Impossible d'appliquer car ces lignes ont été modifiées dans une version plus récente."
msgid "Can't apply as this line was changed in a more recent version."
-msgstr ""
+msgstr "Impossible d'appliquer car cette ligne a été modifiée dans une version plus récente."
msgid "Can't apply this suggestion."
-msgstr ""
+msgstr "Impossible d'appliquer cette suggestion."
msgid "Can't be empty"
msgstr ""
msgid "Can't create snippet: %{err}"
-msgstr ""
+msgstr "Impossible de créer l'extrait de code : %{err}"
msgid "Can't fetch content for the blob: %{err}"
-msgstr ""
+msgstr "Impossible de récupérer le contenu du blob : %{err}"
msgid "Can't find HEAD commit for this branch"
msgstr "Impossible de trouver le dernier commit (HEAD) pour cette branche"
@@ -7361,46 +7501,46 @@ msgid "Can't scan the code?"
msgstr ""
msgid "Can't update snippet: %{err}"
-msgstr ""
+msgstr "Impossible de mettre à jour l'extrait de code : %{err}"
msgid "Canary"
msgstr ""
msgid "Canary Ingress does not exist in the environment."
-msgstr ""
+msgstr "Le Canari Ingress n'existe pas dans l'environnement."
msgid "Canary weight must be specified and valid range (0..100)."
-msgstr ""
+msgstr "Le poids du Canari doit être spécifié et être dans une plage valide (0..100)."
msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
-msgstr ""
+msgstr "%{boldStart}Canari :%{boldEnd} %{canary}"
msgid "CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}"
-msgstr ""
+msgstr "%{boldStart}Stable :%{boldEnd} %{stable}"
msgid "CanaryIngress|Canary"
-msgstr ""
+msgstr "Canari"
msgid "CanaryIngress|Change ratio"
-msgstr ""
+msgstr "Modifier le ratio"
msgid "CanaryIngress|Change the ratio of canary deployments?"
-msgstr ""
+msgstr "Modifier le ratio des déploiements canari ?"
msgid "CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished."
msgstr ""
msgid "CanaryIngress|Stable"
-msgstr ""
+msgstr "Stable"
msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
-msgstr ""
+msgstr "Pour %{environment}, vous mettez le ratio de publication canari par rapport au déploiement stable à :"
msgid "Cancel"
msgstr "Annuler"
msgid "Cancel and close"
-msgstr ""
+msgstr "Annuler et fermer"
msgid "Cancel downstream pipeline"
msgstr ""
@@ -7409,7 +7549,7 @@ msgid "Cancel editing"
msgstr ""
msgid "Cancel index deletion"
-msgstr ""
+msgstr "Annuler la suppression d'index"
msgid "Cancel running"
msgstr ""
@@ -7418,22 +7558,22 @@ msgid "Cancel this job"
msgstr "Annuler cette tâche"
msgid "Cancel your account"
-msgstr ""
+msgstr "Annuler votre compte"
msgid "Cancel, keep project"
-msgstr ""
+msgstr "Annuler, conserver le projet"
msgid "Canceled deployment to"
msgstr ""
msgid "Cancelled"
-msgstr ""
+msgstr "Annulé"
msgid "Cancelling Preview"
msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
-msgstr ""
+msgstr "Impossible d'assigner une épopée confidentielle à un ticket non confidentiel. Rendez le ticket confidentiel et réessayez"
msgid "Cannot assign an issue that does not belong under the same group (or descendant) as the epic."
msgstr ""
@@ -7451,7 +7591,7 @@ msgid "Cannot create the abuse report. This user has been blocked."
msgstr ""
msgid "Cannot delete %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Impossible de supprimer %{profile_name} référencé dans la stratégie de sécurité"
msgid "Cannot have multiple Jira imports running at the same time"
msgstr ""
@@ -7463,16 +7603,16 @@ 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 "Impossible de rendre l'épopée confidentielle si elle contient des épopées enfants non confidentielles"
msgid "Cannot make the epic confidential if it contains non-confidential issues"
-msgstr ""
+msgstr "Impossible de rendre l'épopée confidentielle si elle contient des tickets non confidentiels"
msgid "Cannot merge"
msgstr ""
msgid "Cannot modify %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Impossible de modifier %{profile_name} référencé dans la stratégie de sécurité"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Impossible de modifier la grappe de serveurs gérée par Kubernetes"
@@ -7486,8 +7626,8 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "Impossible de faire référence à un jalon de groupe avec un id interne !"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr ""
@@ -7502,40 +7642,40 @@ msgid "Card holder name"
msgstr ""
msgid "Card number:"
-msgstr ""
+msgstr "Numéro de carte :"
msgid "CascadingSettings|Enforce deletion protection for all subgroups"
-msgstr ""
+msgstr "Imposer la protection contre la suppression pour tous les sous-groupes"
msgid "CascadingSettings|Enforce for all subgroups"
-msgstr ""
+msgstr "Imposer à tous les sous-groupes"
msgid "CascadingSettings|Setting enforced"
-msgstr ""
+msgstr "Paramètre imposé"
msgid "CascadingSettings|Subgroups cannot change this setting."
-msgstr ""
+msgstr "Les sous-groupes ne peuvent pas modifier ce paramètre."
msgid "CascadingSettings|This setting has been enforced by an instance admin."
-msgstr ""
+msgstr "Ce paramètre a été imposé par un administrateur de l'instance."
msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
-msgstr ""
+msgstr "Ce paramètre a été imposé par un propriétaire de %{link}."
msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
-msgstr ""
+msgstr "ne peut pas être modifié en raison d'un verrouillage en amont"
msgid "CascadingSettings|cannot be nil when locking the attribute"
-msgstr ""
+msgstr "ne peut pas être nul lors du verrouillage de l'attribut"
msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "Certains contenus de l'utilisateur seront déplacés vers un « utilisateur fantôme » global au système afin qu'ils soient toujours conservés. Pour plus d'informations, veuillez vous référer à la %{link_start}documentation sur la suppression de compte utilisateur%{link_end}."
msgid "Certificate"
-msgstr ""
+msgstr "Certificat"
msgid "Certificate (PEM)"
-msgstr ""
+msgstr "Certificat (PEM)"
msgid "Certificate Issuer"
msgstr ""
@@ -7550,10 +7690,10 @@ msgid "Change assignee"
msgstr ""
msgid "Change assignee(s)"
-msgstr ""
+msgstr "Changer le(s) assigné(s)"
msgid "Change assignee(s)."
-msgstr ""
+msgstr "Changer le(s) assigné(s)."
msgid "Change branches"
msgstr ""
@@ -7562,22 +7702,22 @@ msgid "Change label"
msgstr "Modifier l'étiquette"
msgid "Change made by"
-msgstr ""
+msgstr "Modification faite par"
msgid "Change milestone"
msgstr "Changer de jalon"
msgid "Change path"
-msgstr ""
+msgstr "Changer le chemin"
msgid "Change reviewer(s)"
-msgstr ""
+msgstr "Changer de relecteur(s)"
msgid "Change reviewer(s)."
-msgstr ""
+msgstr "Changer les relecteur(s)."
msgid "Change role"
-msgstr ""
+msgstr "Changer le rôle"
msgid "Change status"
msgstr ""
@@ -7598,10 +7738,10 @@ msgid "Change your password or recover your current one"
msgstr ""
msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
-msgstr ""
+msgstr "Le Relecteur est passé de %{old} à %{new}"
msgid "ChangeReviewer|Reviewer changed to %{new}"
-msgstr ""
+msgstr "Le Relecteur est modifié pour %{new}"
msgid "ChangeReviewer|Unassigned"
msgstr "Non assigné(s)"
@@ -7610,10 +7750,10 @@ msgid "ChangeTypeAction|Cherry-pick"
msgstr "Picorer"
msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab créera une branche dans votre projet divergent et lancera une demande de fusion."
msgid "ChangeTypeAction|Pick into branch"
-msgstr ""
+msgstr "Sélectionner dans la branche"
msgid "ChangeTypeAction|Pick into project"
msgstr ""
@@ -7625,16 +7765,16 @@ msgid "ChangeTypeAction|Revert in branch"
msgstr ""
msgid "ChangeTypeAction|Search branches"
-msgstr ""
+msgstr "Rechercher des branches"
msgid "ChangeTypeAction|Search projects"
msgstr ""
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
-msgstr ""
+msgstr "Démarrer une %{newMergeRequest} avec ces modifications"
msgid "ChangeTypeAction|Switch branch"
-msgstr ""
+msgstr "Changer de branche"
msgid "ChangeTypeAction|Switch project"
msgstr ""
@@ -7643,7 +7783,7 @@ msgid "ChangeTypeAction|This will create a new commit in order to revert the exi
msgstr "Cela va créer un nouveau commit afin de défaire les modifications existantes."
msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
-msgstr ""
+msgstr "Vos modifications seront validées sur %{branchName} car une demande de fusion est ouverte."
msgid "Changed"
msgstr ""
@@ -7655,7 +7795,7 @@ msgid "Changed merge method to %{merge_method}"
msgstr ""
msgid "Changed reviewer(s)."
-msgstr ""
+msgstr "Relecteur(s) changé(s)."
msgid "Changed squash option to %{squash_option}"
msgstr ""
@@ -7664,13 +7804,13 @@ msgid "Changed the title to \"%{title_param}\"."
msgstr ""
msgid "Changes"
-msgstr ""
+msgstr "Modifications"
msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
-msgstr ""
+msgstr "Les modifications sont affichées comme si la révision %{b_open}source%{b_close} était en cours de fusion vers la révision %{b_open}cible%{b_close}."
msgid "Changes saved."
-msgstr ""
+msgstr "Modifications enregistrées."
msgid "Changes suppressed. Click to show."
msgstr ""
@@ -7679,13 +7819,16 @@ msgid "Changes the title to \"%{title_param}\"."
msgstr ""
msgid "Changes to the title have not been saved"
-msgstr ""
+msgstr "Les modifications apportées au titre n'ont pas été enregistrées"
+
+msgid "Changes:"
+msgstr "Modifications :"
msgid "Changing any setting here requires an application restart"
-msgstr ""
+msgstr "Toute modification de paramètre nécessitera un redémarrage de l'application"
msgid "Characters left"
-msgstr ""
+msgstr "Caractères restants"
msgid "Characters over limit"
msgstr ""
@@ -7754,19 +7897,19 @@ 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 ""
+msgstr "Vérifiez le fichier %{code_open}elasticsearch.log%{code_close} pour déterminer la raison pour laquelle la migration s'est interrompue puis effectuez des modifications avant de retenter la migration. Une fois la cause de l'échec corrigée, cliquez sur %{strong_open}Retenter la migration%{strong_close} pour qu'une nouvelle tentative en arrière-plan soit planifiée."
msgid "Check the current instance configuration "
-msgstr ""
+msgstr "Vérifier la configuration de l'instance actuelle "
msgid "Check with your administrator."
-msgstr ""
+msgstr "Vérifiez avec votre administrateur."
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
msgid "Check your Kubernetes cluster images for known vulnerabilities."
-msgstr ""
+msgstr "Vérifiez les vulnérabilités connues des images de votre grappe de serveurs Kubernetes."
msgid "Checking %{text} availability…"
msgstr "Vérification de la disponibilité de %{text}…"
@@ -7787,41 +7930,41 @@ msgid "Checkout"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
-msgstr ""
+msgstr "%{selectedPlanPrice}$ par pack de 10 Go de stokage et par année"
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
-msgstr ""
+msgstr "%{selectedPlanPrice}$ par pack de 1000 minutes"
msgid "Checkout|$%{selectedPlanPrice} per user per year"
msgstr ""
msgid "Checkout|%d CI minute pack"
msgid_plural "Checkout|%d CI minute packs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d pack de minutes CI"
+msgstr[1] "%d packs de minutes CI"
msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
msgstr ""
msgid "Checkout|%{name}'s CI minutes"
-msgstr ""
+msgstr "Minutes CI de %{name}"
msgid "Checkout|%{name}'s GitLab subscription"
msgstr ""
msgid "Checkout|%{name}'s storage subscription"
-msgstr ""
+msgstr "Abonnement au stockage de %{name}"
msgid "Checkout|%{quantity} CI minutes"
-msgstr ""
+msgstr "%{quantity} minutes CI"
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} Go de stockage"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{quantity} pack de stockage"
+msgstr[1] "%{quantity} packs de stockage"
msgid "Checkout|%{selectedPlanText} plan"
msgstr ""
@@ -7833,25 +7976,25 @@ msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
msgid "Checkout|(x%{numberOfUsers})"
-msgstr ""
+msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
-msgstr ""
+msgstr "(x%{quantity})"
msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
-msgstr ""
+msgstr "Une erreur inconnue s'est produite. Veuillez réessayer en actualisant cette page."
msgid "Checkout|Billing address"
-msgstr ""
+msgstr "Adresse de facturation"
msgid "Checkout|CI minute pack"
-msgstr ""
+msgstr "pack de minutes CI"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
-msgstr ""
+msgstr "Les packs de minutes CI ne sont utilisés qu'après que vous ayez employé le quota mensuel de votre abonnement. Les minutes supplémentaires seront reportées de mois en mois et sont valables pendant un an."
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "Minutes CI"
msgid "Checkout|Calculating your subscription..."
msgstr ""
@@ -7860,13 +8003,13 @@ msgid "Checkout|Checkout"
msgstr ""
msgid "Checkout|City"
-msgstr ""
+msgstr "Ville"
msgid "Checkout|Confirm purchase"
msgstr ""
msgid "Checkout|Confirming..."
-msgstr ""
+msgstr "Confirmation..."
msgid "Checkout|Continue to billing"
msgstr ""
@@ -7875,10 +8018,10 @@ msgid "Checkout|Continue to payment"
msgstr ""
msgid "Checkout|Country"
-msgstr ""
+msgstr "Pays"
msgid "Checkout|Create a new group"
-msgstr ""
+msgstr "Créer un nouveau groupe"
msgid "Checkout|Credit card form failed to load. Please try again."
msgstr ""
@@ -7890,34 +8033,34 @@ msgid "Checkout|Edit"
msgstr ""
msgid "Checkout|Enter a number greater than 0"
-msgstr ""
+msgstr "Entrez un nombre supérieur à 0"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
-msgstr ""
+msgstr "Exp %{expirationMonth}/%{expirationYear}"
msgid "Checkout|Failed to confirm your order! Please try again."
-msgstr ""
+msgstr "Échec de la confirmation de votre commande ! Veuillez réessayer."
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
-msgstr ""
+msgstr "Échec de la confirmation de votre commande : %{message}. Veuillez réessayer."
msgid "Checkout|Failed to load countries. Please try again."
-msgstr ""
+msgstr "Impossible de charger les pays. Veuillez réessayer."
msgid "Checkout|Failed to load states. Please try again."
msgstr ""
msgid "Checkout|Failed to load the payment form. Please try again."
-msgstr ""
+msgstr "Échec du chargement du formulaire de paiement. Veuillez réessayer."
msgid "Checkout|Failed to register credit card. Please try again."
-msgstr ""
+msgstr "Échec de l'enregistrement de la carte de crédit. Veuillez réessayer."
msgid "Checkout|GB"
-msgstr ""
+msgstr "Go"
msgid "Checkout|GitLab group"
-msgstr ""
+msgstr "Groupe GitLab"
msgid "Checkout|GitLab plan"
msgstr ""
@@ -7926,16 +8069,16 @@ msgid "Checkout|Group"
msgstr ""
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use) or more."
-msgstr ""
+msgstr "Doit valoir %{minimumNumberOfUsers} (votre nombre de sièges en cours d'utilisation) ou plus."
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use, plus all over limit members) or more. To buy fewer seats, remove members from the group."
-msgstr ""
+msgstr "Doit valoir %{minimumNumberOfUsers} (votre nombre de sièges en cours d'utilisation plus tous les membres hors limite) ou plus. Pour acheter moins de sièges, enlevez des membres du groupe."
msgid "Checkout|Name of company or organization using GitLab"
msgstr ""
msgid "Checkout|Name: %{errors}"
-msgstr ""
+msgstr "Nom : %{errors}"
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
msgstr ""
@@ -7944,16 +8087,16 @@ msgid "Checkout|Number of users"
msgstr ""
msgid "Checkout|Payment method"
-msgstr ""
+msgstr "Moyen de paiement"
msgid "Checkout|Please select a country"
-msgstr ""
+msgstr "Veuillez sélectionner un pays"
msgid "Checkout|Please select a state"
msgstr ""
msgid "Checkout|Purchase details"
-msgstr ""
+msgstr "Détails de l'achat"
msgid "Checkout|Select"
msgstr ""
@@ -7962,13 +8105,13 @@ msgid "Checkout|State"
msgstr ""
msgid "Checkout|Storage packs"
-msgstr ""
+msgstr "Packs de stockage"
msgid "Checkout|Street address"
-msgstr ""
+msgstr "Adresse"
msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
-msgstr ""
+msgstr "L'envoi du formulaire de la carte de crédit a échoué avec le code %{errorCode} : %{errorMessage}"
msgid "Checkout|Subscription details"
msgstr ""
@@ -7977,52 +8120,52 @@ msgid "Checkout|Subtotal"
msgstr ""
msgid "Checkout|Success: subscription"
-msgstr ""
+msgstr "Réussite : abonnement"
msgid "Checkout|Tax"
msgstr ""
msgid "Checkout|Total"
-msgstr ""
+msgstr "Total"
msgid "Checkout|Total minutes: %{quantity}"
-msgstr ""
+msgstr "Total des minutes : %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "Stockage total : %{quantity} Go"
msgid "Checkout|Users"
-msgstr ""
+msgstr "Utilisateurs"
msgid "Checkout|You'll create your new group after checkout"
-msgstr ""
+msgstr "Vous créerez votre nouveau groupe après la commande"
msgid "Checkout|Your organization"
msgstr ""
msgid "Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly."
-msgstr ""
+msgstr "Votre abonnement au stockage possède les mêmes termes que votre abonnement principal, et le tarif est calculé au prorata en conséquence."
msgid "Checkout|Your subscription will be applied to this group"
-msgstr ""
+msgstr "Votre abonnement sera appliqué à ce groupe"
msgid "Checkout|Zip code"
-msgstr ""
+msgstr "Code postal"
msgid "Checkout|a storage subscription"
-msgstr ""
+msgstr "un abonnement au stockage"
msgid "Checkout|company or team"
msgstr ""
msgid "Checkout|minutes"
-msgstr ""
+msgstr "minutes"
msgid "Checkout|x %{quantity} %{units} per pack"
-msgstr ""
+msgstr "x %{quantity} %{units} par pack"
msgid "Checkout|x %{quantity} %{units} per pack ="
-msgstr ""
+msgstr "x %{quantity} %{units} par pack ="
msgid "Cherry-pick this commit"
msgstr "Picorer ce commit"
@@ -8034,7 +8177,7 @@ msgid "Child"
msgstr ""
msgid "Child epic"
-msgstr ""
+msgstr "Épopée enfant"
msgid "Child epic does not exist."
msgstr ""
@@ -8043,7 +8186,7 @@ msgid "Child epic doesn't exist."
msgstr ""
msgid "Child issues and epics"
-msgstr ""
+msgstr "Épopées et tickets enfants"
msgid "Chinese language support using"
msgstr ""
@@ -8052,7 +8195,7 @@ msgid "Choose File..."
msgstr ""
msgid "Choose a file"
-msgstr ""
+msgstr "Choisir un fichier"
msgid "Choose a group"
msgstr ""
@@ -8073,7 +8216,7 @@ msgid "Choose file…"
msgstr ""
msgid "Choose the preferred Runner and populate the AWS CFT."
-msgstr ""
+msgstr "Choisissez l'Exécuteur préféré et remplissez le CFT AWS."
msgid "Choose the top-level group for your repository imports."
msgstr "Choisissez le groupe de premier niveau pour vos importations dans le dépôt."
@@ -8082,10 +8225,10 @@ 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 "Choisissez le contenu que vous souhaitez voir sur la page d'aperçu de groupe."
msgid "Choose which Git strategy to use when fetching the project."
-msgstr ""
+msgstr "Choisissez la stratégie Git à utiliser lors de la récupération du projet."
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Choisissez quels dépôts vous voulez connecter pour exécuter des pipelines d’intégration et de livraison continues (CI/CD)."
@@ -8094,7 +8237,7 @@ msgid "Choose your framework"
msgstr ""
msgid "CiCdAnalytics|Date range: %{range}"
-msgstr ""
+msgstr "Plage de dates : %{range}"
msgid "CiStatusLabel|canceled"
msgstr "annulé"
@@ -8193,7 +8336,7 @@ msgid "CiVariables|Protected"
msgstr ""
msgid "CiVariables|Remove variable"
-msgstr ""
+msgstr "Supprimer la variable"
msgid "CiVariables|Remove variable row"
msgstr "Supprimer cette variable"
@@ -8208,7 +8351,7 @@ msgid "CiVariables|State"
msgstr ""
msgid "CiVariables|Type"
-msgstr ""
+msgstr "Type"
msgid "CiVariables|Value"
msgstr ""
@@ -8238,27 +8381,27 @@ msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "est indisponible : %{reason}"
msgid "Clean up after running %{link_start}git filter-repo%{link_end} on the repository."
-msgstr ""
+msgstr "Nettoyer après avoir exécuté %{link_start}git filter-repo%{link_end} sur le dépôt."
msgid "Cleanup policies are executed by background workers. This setting defines the maximum number of workers that can run concurrently. Set it to 0 to remove all workers and not execute the cleanup policies."
-msgstr ""
+msgstr "Les politiques de nettoyage sont exécutées par des workers en arrière-plan. Ce paramètre définit le nombre maximal de workers qui peuvent s'exécuter en même temps. Définissez-le à 0 pour supprimer tous les workers et ne plus exécuter les politiques de nettoyage."
msgid "Cleanup policy maximum number of tags to be deleted"
-msgstr ""
+msgstr "Nombre maximal d'étiquettes à supprimer par la politique de nettoyage"
msgid "Cleanup policy maximum processing time (seconds)"
-msgstr ""
+msgstr "Durée de traitement maximale de la stratégie de nettoyage (secondes)"
msgid "Cleanup policy maximum workers running concurrently"
-msgstr ""
+msgstr "Nombre maximal de workers de la politique de nettoyage s'exécutant simultanément"
msgid "Clear"
msgstr ""
msgid "Clear %{count} image from cache?"
msgid_plural "Clear %{count} images from cache?"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Supprimer %{count} image du cache ?"
+msgstr[1] "Supprimer %{count} images du cache ?"
msgid "Clear all repository checks"
msgstr ""
@@ -8270,7 +8413,7 @@ msgid "Clear due date"
msgstr ""
msgid "Clear health status"
-msgstr ""
+msgstr "Effacer l'état de santé"
msgid "Clear recent searches"
msgstr "Effacer les recherches récentes"
@@ -8291,34 +8434,34 @@ msgid "Clear templates search input"
msgstr ""
msgid "Clear this checkbox to use a personal access token instead."
-msgstr ""
+msgstr "Décocher cette case pour utiliser un jeton d'accès personnel à la place."
msgid "Clear this checkbox to use a personal access token or LDAP password instead."
-msgstr ""
+msgstr "Décocher cette case pour utiliser un jeton d'accès personnel ou un mot de passe LDAP à la place."
msgid "Clear this checkbox to use an external authentication provider instead."
-msgstr ""
+msgstr "Décochez cette case pour utiliser un fournisseur d'authentification externe à la place."
msgid "Clear weight"
msgstr ""
msgid "Cleared health status."
-msgstr ""
+msgstr "État de santé effacé."
msgid "Cleared weight."
msgstr ""
msgid "Clears health status."
-msgstr ""
+msgstr "Efface l'état de santé."
msgid "Clears weight."
msgstr ""
msgid "Click %{link_start}here%{link_end} to view the request."
-msgstr ""
+msgstr "Cliquez %{link_start}ici%{link_end} pour voir la requête."
msgid "Click %{link_to} to view the request."
-msgstr ""
+msgstr "Cliquez %{link_to} pour voir la requête."
msgid "Click the link below to confirm your email address (%{email})"
msgstr ""
@@ -8339,13 +8482,13 @@ msgid "Click to reveal"
msgstr ""
msgid "Client request timeout"
-msgstr ""
+msgstr "Délai d'expiration des requêtes client"
msgid "Clients"
msgstr "Clients"
msgid "Clientside DSN"
-msgstr ""
+msgstr "DSN côté client"
msgid "Clone"
msgstr ""
@@ -8366,19 +8509,19 @@ msgid "Clone with KRB5"
msgstr ""
msgid "Clone with SSH"
-msgstr ""
+msgstr "Cloner avec SSH"
msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
-msgstr ""
+msgstr "Impossible de cloner le ticket car les permissions sont insuffisantes !"
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
-msgstr ""
+msgstr "Impossible de cloner le ticket vers le projet cible car il est en attente de suppression."
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
-msgstr ""
+msgstr "Impossible de cloner les tickets de type « %{issue_type} »."
msgid "Cloned this issue to %{path_to_project}."
-msgstr ""
+msgstr "Ce ticket a été cloné vers %{path_to_project}."
msgid "Clones this issue, without comments, to %{project}."
msgstr ""
@@ -8396,7 +8539,7 @@ msgid "Close %{tabname}"
msgstr ""
msgid "Close design"
-msgstr ""
+msgstr "Fermer le design"
msgid "Close epic"
msgstr "Clore l’épopée"
@@ -8411,13 +8554,13 @@ msgid "Close this %{quick_action_target}"
msgstr ""
msgid "Closed"
-msgstr "Fermé(e)"
+msgstr "Fermé"
msgid "Closed %{epicTimeagoDate}"
-msgstr ""
+msgstr "Fermée(s) %{epicTimeagoDate}"
msgid "Closed MRs"
-msgstr ""
+msgstr "MR fermées"
msgid "Closed date"
msgstr "Date de fermeture"
@@ -8438,160 +8581,160 @@ msgid "Cloud Run"
msgstr ""
msgid "Cloud SQL instances are fully managed, relational MySQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Les instances Cloud SQL sont des bases de données MySQL relationnelles entièrement gérées. Google prend en charge la réplication, la gestion des correctifs et l'administration de la base de données pour garantir performance et disponibilité."
msgid "Cloud SQL instances are fully managed, relational SQL Server databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Les instances Cloud SQL sont des bases de données relationnelles SQL Server entièrement gérées. Google prend en charge la réplication, la gestion des correctifs et l'administration de la base de données pour garantir performance et disponibilité."
msgid "Cloud Storage"
msgstr ""
msgid "CloudSeed|All"
-msgstr ""
+msgstr "Tous"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "AlloyDB pour Postgres"
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "Services de base de données disponibles grâce auxquels des instances peuvent être créées"
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "CloudSeed|Cloud Firestore"
-msgstr ""
+msgstr "Cloud Firestore"
msgid "CloudSeed|Cloud SQL for MySQL"
-msgstr ""
+msgstr "Cloud SQL pour MySQL"
msgid "CloudSeed|Cloud SQL for Postgres"
-msgstr ""
+msgstr "Cloud SQL pour Postgres"
msgid "CloudSeed|Cloud SQL for SQL Server"
-msgstr ""
+msgstr "Cloud SQL pour SQL Server"
msgid "CloudSeed|Cloud SQL instance creation request successful. Expected resolution time is ~5 minutes."
-msgstr ""
+msgstr "La demande de création d'instance Cloud SQL a réussi. La durée de résolution prévue est d'environ 5 minutes."
msgid "CloudSeed|Cloud SQL instances are fully managed, relational PostgreSQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Les instances Cloud SQL sont des bases de données relationnelles PostgreSQL entièrement gérées. Google prend en charge la réplication, la gestion des correctifs et l'administration de la base de données pour garantir performance et disponibilité."
msgid "CloudSeed|CloudSQL Instance"
-msgstr ""
+msgstr "Instance CloudSQL"
msgid "CloudSeed|Configuration"
-msgstr ""
+msgstr "Configuration"
msgid "CloudSeed|Create MySQL Instance"
-msgstr ""
+msgstr "Créer une instance MySQL"
msgid "CloudSeed|Create Postgres Instance"
-msgstr ""
+msgstr "Créer une instance Postgres"
msgid "CloudSeed|Create cluster"
-msgstr ""
+msgstr "Créer une grappe de serveurs"
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "Créer une base de données"
msgid "CloudSeed|Create instance"
-msgstr ""
+msgstr "Créer une instance"
msgid "CloudSeed|Database instance is generated within the selected Google Cloud project"
-msgstr ""
+msgstr "L'instance de la base de données est générée dans le projet Google Cloud sélectionné"
msgid "CloudSeed|Database instances associated with this project"
-msgstr ""
+msgstr "Instances de bases de données associées à ce projet"
msgid "CloudSeed|Database version"
-msgstr ""
+msgstr "Version de la base de données"
msgid "CloudSeed|Databases"
-msgstr ""
+msgstr "Bases de données"
msgid "CloudSeed|Deployments"
-msgstr ""
+msgstr "Déploiements"
msgid "CloudSeed|Description"
-msgstr ""
+msgstr "Description"
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
-msgstr ""
+msgstr "Détermine la quantité de mémoire et de cœurs virtuels disponibles pour votre instance"
msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "Améliorer la sécurité en stockant les variables de la base de données dans des gestionnaires de secrets - en savoir plus sur la %{docLinkStart}gestion de secrets avec GitLab%{docLinkEnd}"
msgid "CloudSeed|Environment"
-msgstr ""
+msgstr "Environnement"
msgid "CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development"
-msgstr ""
+msgstr "Base de données NoSQL en nuage, flexible et extensible, pour le développement côtés client et serveur"
msgid "CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads"
-msgstr ""
+msgstr "Service compatible PostgreSQL entièrement géré pour des charges de travail à forte demande"
msgid "CloudSeed|Fully managed relational database service for MySQL"
-msgstr ""
+msgstr "Service de base de données relationnelle entièrement géré pour MySQL"
msgid "CloudSeed|Fully managed relational database service for PostgreSQL"
-msgstr ""
+msgstr "Service de base de données relationnelle entièrement géré pour PostgreSQL"
msgid "CloudSeed|Fully managed relational database service for SQL Server"
-msgstr ""
+msgstr "Service de base de données relationnelle entièrement géré pour SQL Server"
msgid "CloudSeed|Generated database instance is linked to the selected branch or tag"
-msgstr ""
+msgstr "L'instance de base de données générée est reliée à la branche ou à l'étiquette sélectionnée"
msgid "CloudSeed|Google Cloud Error - %{message}"
-msgstr ""
+msgstr "Erreur Google Cloud - %{message}"
msgid "CloudSeed|Google Cloud Project"
-msgstr ""
+msgstr "Projet Google Cloud"
msgid "CloudSeed|Google Cloud project"
-msgstr ""
+msgstr "Projet Google Cloud"
msgid "CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances"
-msgstr ""
+msgstr "J'accepte la tarification Google Cloud et les responsabilités impliquées par la gestion d'instances de bases de données"
msgid "CloudSeed|Instances"
-msgstr ""
+msgstr "Instances"
msgid "CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}."
-msgstr ""
+msgstr "En savoir plus sur les tarifications de %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} et %{firestorePricingStart}Firestore%{firestorePricingEnd}."
msgid "CloudSeed|Machine type"
-msgstr ""
+msgstr "Type de machine"
msgid "CloudSeed|Memorystore for Redis"
-msgstr ""
+msgstr "Memorystore pour Redis"
msgid "CloudSeed|No instances"
-msgstr ""
+msgstr "Aucune instance"
msgid "CloudSeed|Refs"
-msgstr ""
+msgstr "Réfs"
msgid "CloudSeed|Regions"
-msgstr ""
+msgstr "Régions"
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
-msgstr ""
+msgstr "Service en mémoire sécurisé, extensible et à haute disponibilité pour Redis"
msgid "CloudSeed|Service"
-msgstr ""
+msgstr "Service"
msgid "CloudSeed|Service Account"
-msgstr ""
+msgstr "Compte de Service"
msgid "CloudSeed|Services"
-msgstr ""
+msgstr "Services"
msgid "CloudSeed|There are no instances to display."
-msgstr ""
+msgstr "Il n'y a aucune instance à afficher."
msgid "CloudSeed|Version"
-msgstr ""
+msgstr "Version"
msgid "Cluster"
msgstr ""
@@ -8603,58 +8746,58 @@ msgid "Cluster cache cleared."
msgstr ""
msgid "Cluster is required for Stages::ClusterEndpointInserter"
-msgstr ""
+msgstr "Une grappe de serveurs est requise pour Stages::ClusterEndpointInserter"
msgid "Cluster level"
msgstr ""
msgid "Cluster type must be specified for Stages::ClusterEndpointInserter"
-msgstr ""
+msgstr "Le type de grappe de serveurs doit être spécifié pour Stages::ClusterEndpointInserter"
msgid "ClusterAgents|%{linkStart}View the documentation%{linkEnd} for advanced installation. Ensure you have your access token available."
-msgstr ""
+msgstr "%{linkStart}Voir la documentation%{linkEnd} de l'installation avancée. Assurez-vous d'être en possession de votre jeton d'accès."
msgid "ClusterAgents|%{name} successfully deleted"
-msgstr ""
+msgstr "%{name} supprimé avec succès"
msgid "ClusterAgents|%{name} successfully revoked"
msgstr ""
msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr ""
+msgstr "%{number} agents sur %{total}"
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
-msgstr ""
+msgstr "%{number} grappes de serveurs sur %{total} connectées via des certificats de grappes de serveurs"
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon}Connecté"
msgid "ClusterAgents|%{titleIcon}Not connected"
-msgstr ""
+msgstr "%{titleIcon}Non connecté"
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} créé"
msgid "ClusterAgents|%{tokenName} revoked"
-msgstr ""
+msgstr "%{tokenName} révoqué"
msgid "ClusterAgents|Access tokens"
-msgstr ""
+msgstr "Jetons d'accès"
msgid "ClusterAgents|Add an agent configuration file to %{linkStart}this repository%{linkEnd} and select it, or create a new one to register with GitLab:"
-msgstr ""
+msgstr "Ajoutez le fichier de configuration d'un agent à %{linkStart}ce dépôt%{linkEnd} et sélectionnez-le, ou créez-en un nouveau pour l'enregistrer avec GitLab :"
msgid "ClusterAgents|Advanced installation methods"
-msgstr ""
+msgstr "Méthodes d’installation avancées"
msgid "ClusterAgents|Agent"
-msgstr ""
+msgstr "Agent"
msgid "ClusterAgents|Agent %{strongStart}connected%{strongEnd}"
-msgstr ""
+msgstr "Agent %{strongStart}connecté%{strongEnd}"
msgid "ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}"
-msgstr ""
+msgstr "Agent %{strongStart}déconnecté%{strongEnd}"
msgid "ClusterAgents|Agent access token:"
msgstr ""
@@ -8663,7 +8806,7 @@ msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
-msgstr ""
+msgstr "Agent jamais connecté à GitLab"
msgid "ClusterAgents|Agent version mismatch"
msgstr ""
@@ -8672,34 +8815,37 @@ msgid "ClusterAgents|Agent version mismatch and update"
msgstr ""
msgid "ClusterAgents|Agent version update required"
-msgstr ""
+msgstr "Mise à jour de la version de l'agent requise"
msgid "ClusterAgents|All"
-msgstr ""
+msgstr "Tout"
msgid "ClusterAgents|An error occurred while loading your agent"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de votre agent"
msgid "ClusterAgents|An error occurred while loading your agents"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de vos agents"
msgid "ClusterAgents|An error occurred while retrieving agent activity. Reload the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de l'activité de l'agent. Rechargez la page pour réessayer."
msgid "ClusterAgents|An unknown error occurred. Please try again."
-msgstr ""
+msgstr "Une erreur inconnue s'est produite. Veuillez réessayer."
msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cet agent ? Vous ne pouvez pas annuler cette action."
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
+msgstr "Êtes-vous sûr de vouloir révoquer ce jeton ? Vous ne pouvez pas annuler cette action."
+
+msgid "ClusterAgents|CI/CD workflow with restricted access"
msgstr ""
msgid "ClusterAgents|Certificate"
-msgstr ""
+msgstr "Certificat"
msgid "ClusterAgents|Configuration"
-msgstr ""
+msgstr "Configuration"
msgid "ClusterAgents|Connect a Kubernetes cluster"
msgstr ""
@@ -8717,19 +8863,19 @@ msgid "ClusterAgents|Connect a cluster (deprecated)"
msgstr ""
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "Connectés"
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "État de la connexion"
msgid "ClusterAgents|Copy command"
msgstr ""
msgid "ClusterAgents|Copy token"
-msgstr ""
+msgstr "Copier le jeton"
msgid "ClusterAgents|Create a cluster"
-msgstr ""
+msgstr "Créer une grappe de serveurs"
msgid "ClusterAgents|Create agent access token"
msgstr ""
@@ -8738,7 +8884,7 @@ msgid "ClusterAgents|Create agent: %{searchTerm}"
msgstr ""
msgid "ClusterAgents|Create token"
-msgstr ""
+msgstr "Créer un jeton"
msgid "ClusterAgents|Created by"
msgstr "Créé par"
@@ -8750,22 +8896,22 @@ msgid "ClusterAgents|Date created"
msgstr ""
msgid "ClusterAgents|Default configuration"
-msgstr ""
+msgstr "Configuration par défaut"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "Supprimer"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "Supprimer l'agent"
msgid "ClusterAgents|Deprecated"
msgstr ""
msgid "ClusterAgents|Description"
-msgstr ""
+msgstr "Description"
msgid "ClusterAgents|Event occurred"
-msgstr ""
+msgstr "Un événement s’est produit"
msgid "ClusterAgents|Failed to create a token"
msgstr ""
@@ -8774,84 +8920,93 @@ msgid "ClusterAgents|Failed to register an agent"
msgstr ""
msgid "ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included in the command."
-msgstr ""
+msgstr "Depuis un terminal, connectez-vous à votre grappe de serveurs puis exécutez cette commande. Cette dernière contient le jeton."
msgid "ClusterAgents|GitLab agent"
-msgstr ""
+msgstr "Agent GitLab"
msgid "ClusterAgents|GitLab agent for Kubernetes"
-msgstr ""
+msgstr "Agent GitLab pour Kubernetes"
msgid "ClusterAgents|Give feedback"
msgstr ""
msgid "ClusterAgents|How do I register an agent?"
-msgstr ""
+msgstr "Comment enregistrer un agent ?"
msgid "ClusterAgents|How to update an agent?"
-msgstr ""
+msgstr "Comment mettre à jour un agent ?"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
-msgid "ClusterAgents|Last connected %{timeAgo}."
+msgid "ClusterAgents|Integration Status"
msgstr ""
+msgid "ClusterAgents|Last connected %{timeAgo}."
+msgstr "Dernière connexion %{timeAgo}."
+
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "Dernier contact"
msgid "ClusterAgents|Learn how to troubleshoot"
msgstr ""
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "Assurez-vous d'utiliser un jeton valide."
msgid "ClusterAgents|Name"
-msgstr ""
+msgstr "Nom"
msgid "ClusterAgents|Never"
msgstr ""
msgid "ClusterAgents|Never connected"
-msgstr ""
+msgstr "Jamais connectés"
msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Il n'y a eu aucune activité au cours du dernier jour"
+msgstr[1] "Il n'y a eu aucune activité au cours des %d derniers jours"
-msgid "ClusterAgents|No agents"
+msgid "ClusterAgents|No agent access token"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr "Aucun agent"
+
msgid "ClusterAgents|No clusters connected through cluster certificates"
-msgstr ""
+msgstr "Aucune grappe de serveurs connectée via les certificats de grappes de serveurs"
msgid "ClusterAgents|Not connected"
-msgstr ""
+msgstr "Non connectés"
+
+msgid "ClusterAgents|Premium"
+msgstr "Premium"
msgid "ClusterAgents|Recommended"
-msgstr ""
+msgstr "Recommandée"
msgid "ClusterAgents|Register"
-msgstr ""
+msgstr "Enregistrer"
msgid "ClusterAgents|Registering agent"
msgstr ""
msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
-msgstr ""
+msgstr "Nécessite un rôle Mainteneur ou supérieur pour supprimer des agents"
msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
-msgstr ""
+msgstr "Nécessite un rôle Mainteneur ou supérieur pour effectuer ces actions"
msgid "ClusterAgents|Requires a Maintainer or greater role to perform this action"
msgstr ""
msgid "ClusterAgents|Revoke access token?"
-msgstr ""
+msgstr "Révoquer le jeton d’accès ?"
msgid "ClusterAgents|Revoke token"
-msgstr ""
+msgstr "Révoquer le jeton"
msgid "ClusterAgents|Security"
msgstr ""
@@ -8860,82 +9015,85 @@ msgid "ClusterAgents|See agent activity updates, like tokens created or revoked
msgstr ""
msgid "ClusterAgents|Select an agent or enter a name to create new"
-msgstr ""
+msgstr "Sélectionnez un agent ou entrez un nom pour en créer un nouveau"
msgid "ClusterAgents|Tell us what you think"
-msgstr ""
+msgstr "Dites-nous ce que vous pensez"
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 ""
+msgstr "L’agent GitLab fournit un niveau de sécurité accru lors de la connexion des grappes de serveurs Kubernetes à GitLab. %{linkStart}En savoir plus sur l’agent GitLab.%{linkEnd}"
msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
-msgstr ""
+msgstr "Cela fait longtemps que l'agent n'est pas connecté. Il pourrait s'agir d'un problème de connectivité. Le dernier contact a eu lieu %{timeAgo}."
msgid "ClusterAgents|The agent uses the token to connect with GitLab."
-msgstr ""
+msgstr "L'agent utilise le jeton pour se connecter à GitLab."
msgid "ClusterAgents|The agent version do not match each other across your cluster's pods. This can happen when a new agent version was just deployed and Kubernetes is shutting down the old pods."
-msgstr ""
+msgstr "La version de l’agent ne correspond pas à celle des pods de votre grappe de serveurs. Cela peut arriver si une nouvelle version d'agent vient juste d'être déployée et que Kubernetes est en train d'arrêter les anciens pods."
msgid "ClusterAgents|This agent has no tokens"
-msgstr ""
+msgstr "Cet agent n’a aucun jeton"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
-msgstr ""
+msgstr "Pour supprimer l’agent, tapez %{name} pour confirmer :"
msgid "ClusterAgents|To revoke the token, type %{name} to confirm:"
-msgstr ""
+msgstr "Pour révoquer le jeton, tapez %{name} pour confirmer :"
msgid "ClusterAgents|Token created by %{userName}"
-msgstr ""
+msgstr "Jeton créé par %{userName}"
msgid "ClusterAgents|Token revoked by %{userName}"
-msgstr ""
+msgstr "Jeton révoqué par %{userName}"
msgid "ClusterAgents|Unknown user"
-msgstr ""
+msgstr "Utilisateur inconnu"
+
+msgid "ClusterAgents|Valid access token"
+msgstr "Jeton d’accès valide"
msgid "ClusterAgents|View all %{number} agents"
-msgstr ""
+msgstr "Voir tous les %{number} agents"
msgid "ClusterAgents|View all %{number} clusters"
-msgstr ""
+msgstr "Voir toutes les %{number} grappes de serveurs"
msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
-msgstr ""
+msgstr "Nous aimerions en savoir plus sur votre expérience avec l'Agent GitLab."
msgid "ClusterAgents|What is agent activity?"
-msgstr ""
+msgstr "Qu’est-ce que l’activité de l’agent ?"
msgid "ClusterAgents|What is default configuration?"
-msgstr ""
+msgstr "Quelle est la configuration par défaut ?"
msgid "ClusterAgents|You cannot see this token again after you close this window."
-msgstr ""
+msgstr "Vous ne pourrez plus revoir ce jeton après avoir fermé cette fenêtre."
msgid "ClusterAgents|You will need to create a token to connect to your agent"
-msgstr ""
+msgstr "Vous devrez créer un jeton pour vous connecter à votre agent"
msgid "ClusterAgents|Your agent version is out of sync with your GitLab version (v%{version}), which might cause compatibility problems. Update the agent installed on your cluster to the most recent version."
-msgstr ""
+msgstr "La version de votre agent n'est pas synchronisée avec votre version de GitLab (v%{version}), ce qui pourrait causer des problèmes de compatibilité. Mettez à jour l'agent installé sur votre grappe de serveurs vers la version la plus récente."
msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
-msgstr ""
+msgstr "Le %{linkStart}Serveur d'Agent GitLab (KAS)%{linkEnd} n'est pas mis en œuvre sur votre instance. Demandez à un administrateur GitLab de l'installer."
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
-msgstr ""
+msgstr "L’utilisateur n’a pas les permissions suffisantes pour créer un jeton pour ce projet"
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour créer un agent de grappe de serveurs pour ce projet"
msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer cet agent de grappe de serveurs"
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Plus d’informations%{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 "Un projet de gestion de grappe de serveurs peut être utilisé pour exécuter des tâches de déploiement avec les privilèges %{code_open}cluster-admin%{code_close} de Kubernetes."
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
@@ -8962,10 +9120,10 @@ msgid "ClusterIntegration|Adding an integration will share the cluster across al
msgstr ""
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
-msgstr ""
+msgstr "Options avancées de l’intégration de cette grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
-msgstr ""
+msgstr "Permettre à GitLab de gérer les espaces de noms et les comptes de service de cette grappe de serveurs."
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
msgstr ""
@@ -8974,16 +9132,16 @@ msgid "ClusterIntegration|Amazon EKS"
msgstr ""
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
-msgstr ""
+msgstr "Une erreur inconnue s’est produite lors de la tentative de connexion à Kubernetes."
msgid "ClusterIntegration|Any project namespaces"
-msgstr ""
+msgstr "Tout espace de noms de projet"
msgid "ClusterIntegration|Apply for credit"
msgstr ""
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "Erreur d'authentification"
msgid "ClusterIntegration|Base domain"
msgstr ""
@@ -8995,28 +9153,28 @@ msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ensemble de certificats des autorités de certification (format PEM)"
msgid "ClusterIntegration|Check your CA certificate"
-msgstr ""
+msgstr "Vérifiez votre certificat CA"
msgid "ClusterIntegration|Check your cluster status"
-msgstr ""
+msgstr "Vérifiez l’état de votre grappe de serveurs"
msgid "ClusterIntegration|Check your token"
-msgstr ""
+msgstr "Vérifiez votre jeton"
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Choisissez lequel de vos environnements utilisera cette grappe de serveurs."
msgid "ClusterIntegration|Civo Kubernetes"
-msgstr ""
+msgstr "Civo Kubernetes"
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
-msgstr ""
+msgstr "Vider le cache local de l’espace de noms et des comptes de service."
msgid "ClusterIntegration|Cluster management project"
-msgstr ""
+msgstr "Projet de gestion de grappe de serveurs"
msgid "ClusterIntegration|Cluster name is required."
msgstr ""
@@ -9028,10 +9186,10 @@ msgid "ClusterIntegration|Connect a Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
-msgstr ""
+msgstr "Connectez votre grappe de serveurs à GitLab via des %{linkStart}certificats de grappes de serveurs%{linkEnd}."
msgid "ClusterIntegration|Connection Error"
-msgstr ""
+msgstr "Erreur de connexion"
msgid "ClusterIntegration|Copy API URL"
msgstr "Copier l’URL de l’API"
@@ -9043,10 +9201,10 @@ msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copier le nom de la grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Create a Kubernetes cluster"
-msgstr ""
+msgstr "Créer une grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
-msgstr ""
+msgstr "Déployez chaque environnement dans son propre espace de noms. Sinon, les environnements inclus dans un projet utiliseront le même espace de noms à l'échelle du projet. Notez que toute personne qui peut déclencher un déploiement d'un espace de noms peut lire ses secrets. S'ils sont modifiés, les environnements existants utiliseront leurs espaces de noms actuels jusqu'à ce que le cache de la grappe de serveurs soit effacé."
msgid "ClusterIntegration|Did you know?"
msgstr "Le saviezâ€vous ?"
@@ -9055,7 +9213,7 @@ msgid "ClusterIntegration|Elastic Kubernetes Service"
msgstr ""
msgid "ClusterIntegration|Enable Prometheus integration"
-msgstr ""
+msgstr "Activer l'intégration Prometheus"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr "Activez ou désactivez la connexion de GitLab à votre grappe de serveurs Kubernetes."
@@ -9067,16 +9225,16 @@ msgid "ClusterIntegration|Enter details about your cluster. %{linkStart}How do I
msgstr ""
msgid "ClusterIntegration|Enter new Service Token"
-msgstr ""
+msgstr "Entrez un nouveau Jeton de Service"
msgid "ClusterIntegration|Enter your Kubernetes cluster certificate details"
-msgstr ""
+msgstr "Entrez les détails du certificat de votre grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Environment scope"
msgstr "Portée de l’environnement"
msgid "ClusterIntegration|Environment scope is required."
-msgstr ""
+msgstr "La portée de l’environnement est requise."
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr "Chaque nouveau compte Google Cloud Platform (GCP) reçoit un crédit de 300 US$ sur %{sign_up_link}. En partenariat avec Google, GitLab est en mesure de vous offrir 200 US$ supplémentaires, à la fois pour les nouveaux et les anciens comptes GCP, afin de vous permettre de commencer l’intégration de Google Kubernetes Engine sur GitLab."
@@ -9103,7 +9261,7 @@ msgid "ClusterIntegration|GitLab failed to authenticate."
msgstr ""
msgid "ClusterIntegration|GitLab failed to connect to the cluster."
-msgstr ""
+msgstr "GitLab n’a pas pu se connecter à la grappe de serveurs."
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
@@ -9118,22 +9276,22 @@ msgid "ClusterIntegration|Group cluster"
msgstr "Groupe de la grappe de serveurs"
msgid "ClusterIntegration|HTTP Error"
-msgstr ""
+msgstr "Erreur HTTP"
msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
msgstr ""
msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
-msgstr ""
+msgstr "Afin de visualiser la santé de votre grappe de serveurs, vous devez d’abord activer Prometheus dans l’onglet Intégrations."
msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integration disabled"
-msgstr ""
+msgstr "Intégration désactivée"
msgid "ClusterIntegration|Integration enabled"
-msgstr ""
+msgstr "Intégration activée"
msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
@@ -9148,7 +9306,7 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr ""
msgid "ClusterIntegration|Learn more about Kubernetes."
-msgstr ""
+msgstr "En savoir plus sur Kubernetes."
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "En savoir plus sur les grappes de serveurs Kubernetes de groupe"
@@ -9157,16 +9315,16 @@ msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Make sure your API endpoint is correct"
-msgstr ""
+msgstr "Assurez-vous que votre point de terminaison de l'API est correct"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
msgid "ClusterIntegration|Namespace per environment"
-msgstr ""
+msgstr "Espace de noms par environnement"
msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
-msgstr ""
+msgstr "Les calculs réalisés par le nœud utilisent l'API Metrics de Kubernetes. Assurez-vous que les métriques sont installées sur votre grappe de serveurs"
msgid "ClusterIntegration|Project cluster"
msgstr "Grappe de serveurs du projet"
@@ -9178,7 +9336,7 @@ msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
msgstr ""
msgid "ClusterIntegration|Provider details"
-msgstr ""
+msgstr "Détails du fournisseur"
msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr "Grappe de serveurs avec contrôle d’accès par rôle"
@@ -9223,7 +9381,7 @@ msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cl
msgstr ""
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
-msgstr ""
+msgstr "Spécifier un domaine vous permettra d'utiliser les Applications de Revue Auto et les étapes de Déploiement Auto pour %{linkStart}Auto DevOps.%{linkEnd} Le domaine doit avoir un wildcard DNS configuré correspondant au domaine. "
msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
@@ -9232,37 +9390,37 @@ msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "L'intégration Kubernetes basée sur un certificat est désormais obsolète et sera désactivée à la fin du mois de février 2023. Veuillez %{linkStart}migrer vers l'agent GitLab pour Kubernetes%{linkEnd} ou contacter le support GitLab."
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "L’intégration Kubernetes basée sur un certificat est désormais obsolète et sera désactivée à la fin du mois de février 2023. Veuillez %{linkStart}migrer vers l'agent GitLab pour Kubernetes%{linkEnd}."
msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
-msgstr ""
+msgstr "La méthode à base de certificat pour connecter les grappes de serveurs à GitLab a été %{linkStart} dépréciée%{linkEnd} dans GitLab 14.5."
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, and Web terminals."
-msgstr ""
+msgstr "L’espace de noms associé à votre projet. Il sera utilisé pour déployer les tableaux de bord et les terminaux Web."
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
-msgstr ""
+msgstr "Une erreur HTTP s'est produite lors de la connexion à votre grappe de serveurs."
msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
-msgstr ""
+msgstr "Cela est nécessaire si votre intégration n'est plus synchronisée. Le cache sera repeuplé lors de la prochaine tâche CI qui nécessite un espace de noms et des comptes de services."
msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
-msgstr ""
+msgstr "Ceci est nécessaire pour que les associations environnement-espace de noms existantes soient supprimées des grappes de serveurs précédemment gérées par GitLab."
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Cette option vous permettra d’installer des applications sur des grappes de serveurs avec contrôle d’accès basé sur le rôle (RBAC)."
msgid "ClusterIntegration|This process is %{issue_link_start}deprecated%{issue_link_end}. Use the %{docs_link_start}the GitLab agent for Kubernetes%{docs_link_end} instead."
-msgstr ""
+msgstr "Ce processus est %{issue_link_start}obsolète%{issue_link_end}. Utilisez l'%{docs_link_start}agent GitLab pour Kubernetes%{docs_link_end} à la place."
msgid "ClusterIntegration|This will permanently delete the following resources:"
-msgstr ""
+msgstr "Cela supprimera définitivement les ressources suivantes :"
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
@@ -9271,25 +9429,25 @@ msgid "ClusterIntegration|To remove your integration, type %{clusterName} to con
msgstr ""
msgid "ClusterIntegration|Troubleshooting tips:"
-msgstr ""
+msgstr "Conseils de dépannage :"
msgid "ClusterIntegration|Unable to Authenticate"
-msgstr ""
+msgstr "Impossible d’Authentifier"
msgid "ClusterIntegration|Unable to Connect"
-msgstr ""
+msgstr "Impossible de Connecter"
msgid "ClusterIntegration|Unknown Error"
-msgstr ""
+msgstr "Erreur inconnue"
msgid "ClusterIntegration|Use GitLab to deploy to your cluster, run jobs, use review apps, and more."
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 ""
+msgstr "Utilisez l'%{linkStart}agent GitLab%{linkEnd} pour connecter en toute sécurité vos grappes de serveurs Kubernetes à GitLab. Vous pouvez déployer vos applications, exécuter vos pipelines, utiliser des Applications de Revue et bien plus encore."
msgid "ClusterIntegration|Using AutoDevOps with multiple clusters? %{help_link_start}Read this first.%{help_link_end}"
-msgstr ""
+msgstr "Utiliser AutoDevOps avec plusieurs grappes de serveurs ? %{help_link_start}Lisez d'abord ceci.%{help_link_end}"
msgid "ClusterIntegration|Where do you want to create a cluster?"
msgstr ""
@@ -9307,19 +9465,19 @@ msgid "ClusterIntegration|sign up"
msgstr "s’inscrire"
msgid "Clusters|An error occurred while loading clusters"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des grappes de serveurs"
msgid "Code"
msgstr ""
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
-msgstr ""
+msgstr "Couverture de code : %{coveragePercentage}%{percentSymbol}"
msgid "Code Coverage| Empty code coverage data"
-msgstr ""
+msgstr "Données de couverture de code vides"
msgid "Code Coverage|Couldn't fetch the code coverage data"
-msgstr ""
+msgstr "Impossible de récupérer les données de couverture de code"
msgid "Code Owner"
msgstr ""
@@ -9334,16 +9492,16 @@ 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 "Les données analytiques de Revue de Code affichent un tableau des demandes de fusion ouvertes considérées comme étant en revue de code. Il n'y a actuellement aucune demande de fusion en cours de revue pour ce projet et/ou pour ces filtres."
msgid "Code block"
msgstr ""
msgid "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
-msgstr ""
+msgstr "Le code peut être importé depuis des sources activées pendant la création du projet. OmniAuth doit être configuré pour GitHub"
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
-msgstr ""
+msgstr "Statistiques de la couverture de code pour %{ref} de %{start_date} à %{end_date}"
msgid "Code owner approval is required"
msgstr ""
@@ -9355,22 +9513,22 @@ msgid "Code review"
msgstr ""
msgid "Code snippet"
-msgstr ""
+msgstr "Extrait de code"
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
-msgstr ""
+msgstr "Extrait de code copié. Insérez-le au bon endroit dans le fichier YAML."
msgid "CodeIntelligence|This is the definition"
msgstr ""
msgid "CodeNavigation|No references found"
-msgstr ""
+msgstr "Aucune référence trouvée"
msgid "CodeOwner|Pattern"
msgstr ""
msgid "CodeQuality|New code quality degradations on this line"
-msgstr ""
+msgstr "Nouvelles dégradations de la qualité de code sur cette ligne"
msgid "Cohorts|Inactive users"
msgstr ""
@@ -9379,7 +9537,7 @@ msgid "Cohorts|Month %{month_index}"
msgstr ""
msgid "Cohorts|New users"
-msgstr ""
+msgstr "Nouveaux utilisateurs"
msgid "Cohorts|Registration month"
msgstr ""
@@ -9394,52 +9552,52 @@ msgid "Collapse"
msgstr "Réduire"
msgid "Collapse all threads"
-msgstr ""
+msgstr "Réduire tous les fils de conversation"
msgid "Collapse approvers"
msgstr ""
msgid "Collapse issues"
-msgstr ""
+msgstr "Réduire les tickets"
msgid "Collapse jobs"
msgstr ""
msgid "Collapse merge details"
-msgstr ""
+msgstr "Réduire les détails de fusion"
msgid "Collapse milestones"
-msgstr ""
+msgstr "Réduire les jalons"
msgid "Collapse replies"
-msgstr ""
+msgstr "Réduire les réponses"
msgid "Collapse settings section"
-msgstr ""
+msgstr "Réduire la section des paramètres"
msgid "Collapse sidebar"
msgstr "Masquer la barre latérale"
msgid "Collapses this file (only for you) until it’s changed again."
-msgstr ""
+msgstr "Replier ce fichier (pour vous uniquement) jusqu'à ce qu'il soit de nouveau modifié."
msgid "Collector hostname"
msgstr ""
msgid "Color"
-msgstr ""
+msgstr "Couleur"
msgid "ColorWidget|An error occurred while updating color."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la couleur."
msgid "ColorWidget|Assign epic color"
-msgstr ""
+msgstr "Définir la couleur des épopées"
msgid "ColorWidget|Color"
-msgstr ""
+msgstr "Couleur"
msgid "ColorWidget|Error fetching epic color."
-msgstr ""
+msgstr "Erreur lors de la récupération de la couleur de l'épopée."
msgid "Colorize messages"
msgstr ""
@@ -9448,7 +9606,7 @@ msgid "ComboSearch is not defined"
msgstr ""
msgid "Comma-separated list of email addresses."
-msgstr ""
+msgstr "Liste d'adresses de courriel, séparées par des virgules."
msgid "Command"
msgstr ""
@@ -9475,7 +9633,7 @@ msgid "Comment '%{label}' position"
msgstr ""
msgid "Comment added to the timeline."
-msgstr ""
+msgstr "Commentaire ajouté à la chronologie."
msgid "Comment form position"
msgstr "Position du formulaire de commentaire"
@@ -9487,13 +9645,13 @@ msgid "Comment on lines %{startLine} to %{endLine}"
msgstr ""
msgid "Comment/Reply (quoting selected text)"
-msgstr ""
+msgstr "Commenter/Répondre (en citant le texte sélectionné)"
msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
-msgstr ""
+msgstr "Mettre des commentaires sur des fichiers qui remplacent, ou sont remplacés par des liens symboliques n'est pas pris en charge."
msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
-msgstr ""
+msgstr "Mettre des commentaires sur des liens symboliques qui remplacent, ou sont remplacés par des fichiers n'est pas pris en charge."
msgid "Comments"
msgstr "Commentaires"
@@ -9516,7 +9674,7 @@ msgid "Commit SHA"
msgstr ""
msgid "Commit changes"
-msgstr ""
+msgstr "Valider les modifications"
msgid "Commit deleted"
msgstr ""
@@ -9561,7 +9719,10 @@ 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 "Les commits que vous sélectionnez apparaissent ici. Allez sur le premier onglet et sélectionnez les commits à ajouter à cette demande de fusion."
+
+msgid "Commits:"
+msgstr "Commits :"
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Une erreur s’est produite lors de la récupération des données de demandes de fusion."
@@ -9579,7 +9740,7 @@ msgid "Community forum"
msgstr "Forum de la communauté"
msgid "Company"
-msgstr ""
+msgstr "Entreprise"
msgid "Company Name"
msgstr ""
@@ -9588,19 +9749,19 @@ msgid "Compare"
msgstr "Comparer"
msgid "Compare %{oldCommitId}...%{newCommitId}"
-msgstr ""
+msgstr "Comparer %{oldCommitId}...%{newCommitId}"
msgid "Compare Git revisions"
msgstr "Comparer les révisions Git"
msgid "Compare GitLab editions"
-msgstr ""
+msgstr "Comparer les éditions de GitLab"
msgid "Compare Revisions"
msgstr "Comparer les révisions"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "Comparer les branches et continuer"
msgid "Compare changes"
msgstr ""
@@ -9612,7 +9773,7 @@ msgid "Compare changes with the merge request target branch"
msgstr "Comparer les modifications avec la branche cible de la demande de fusion"
msgid "Compare submodule commit revisions"
-msgstr ""
+msgstr "Comparer les révisions des commits de sous-modules"
msgid "Compare with previous version"
msgstr ""
@@ -9624,40 +9785,40 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr "Il n’y a rien à comparer."
msgid "CompareRevisions|Branches"
-msgstr ""
+msgstr "Branches"
msgid "CompareRevisions|Compare"
-msgstr ""
+msgstr "Comparer"
msgid "CompareRevisions|Create merge request"
-msgstr ""
+msgstr "Créer une demande de fusion"
msgid "CompareRevisions|Filter by Git revision"
-msgstr ""
+msgstr "Filtrer par révision Git"
msgid "CompareRevisions|Select Git revision"
-msgstr ""
+msgstr "Sélectionnez une révision Git"
msgid "CompareRevisions|Select branch/tag"
-msgstr ""
+msgstr "Sélectionnez une branche/étiquette"
msgid "CompareRevisions|Select target project"
-msgstr ""
+msgstr "Sélectionnez le projet cible"
msgid "CompareRevisions|Swap revisions"
-msgstr ""
+msgstr "Échanger les révisions"
msgid "CompareRevisions|Tags"
-msgstr ""
+msgstr "Étiquettes"
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de la liste des branches/étiquettes. Veuillez réessayer."
msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la recherche de la liste des branches/étiquettes. Veuillez réessayer."
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la liste des branches/étiquettes. Veuillez réessayer."
msgid "CompareRevisions|View open merge request"
msgstr ""
@@ -9668,86 +9829,89 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr "Terminez la vérification pour vous inscrire."
+
msgid "Completed"
msgstr ""
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
-msgstr ""
+msgstr "Terminé en %{duration_seconds} secondes (%{relative_time})"
msgid "Compliance framework"
-msgstr ""
+msgstr "Cadre de conformité"
msgid "Compliance report"
-msgstr ""
+msgstr "Rapport de conformité"
msgid "ComplianceFrameworks|Add framework"
-msgstr ""
+msgstr "Ajouter un cadre"
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "Couleur d'arrière-plan"
msgid "ComplianceFrameworks|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
-msgstr ""
+msgstr "Cadre de conformité supprimé avec succès"
msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
-msgstr ""
+msgstr "Configuration du pipeline de conformité (facultatif)"
msgid "ComplianceFrameworks|Configuration not found"
-msgstr ""
+msgstr "Configuration introuvable"
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
-msgstr ""
+msgstr "Supprimer le cadre de conformité %{framework}"
msgid "ComplianceFrameworks|Delete framework"
-msgstr ""
+msgstr "Supprimer le cadre"
msgid "ComplianceFrameworks|Description"
-msgstr ""
+msgstr "Description"
msgid "ComplianceFrameworks|Description is required"
-msgstr ""
+msgstr "La description est requise"
msgid "ComplianceFrameworks|Edit framework"
-msgstr ""
+msgstr "Modifier le cadre"
msgid "ComplianceFrameworks|Error deleting the compliance framework. Please try again"
-msgstr ""
+msgstr "Erreur lors de la suppression du cadre de conformité. Veuillez réessayer"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
-msgstr ""
+msgstr "Erreur lors de la récupération des données des cadres de conformité. Veuillez actualiser la page"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
-msgstr ""
+msgstr "Erreur lors de la récupération des données des cadres de conformité. Veuillez actualiser la page ou essayer un autre cadre"
msgid "ComplianceFrameworks|Frameworks that have been added will appear here."
msgstr ""
msgid "ComplianceFrameworks|Invalid format"
-msgstr ""
+msgstr "Format non valide"
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "Nom"
msgid "ComplianceFrameworks|Name is required"
-msgstr ""
+msgstr "Le nom est requis"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
-msgstr ""
+msgstr "Impossible d'enregistrer ce cadre de conformité. Veuillez réessayer"
msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement le cadre de conformité %{framework} de tous les projets sur lesquels il est appliqué, ce qui pourrait supprimer d'autres fonctionnalités. Cela ne pourra pas être annulé."
msgid "ComplianceFramework|Add a framework to %{linkStart}%{groupName}%{linkEnd} and it will appear here."
-msgstr ""
+msgstr "Ajouter un framework à %{linkStart}%{groupName}%{linkEnd} et il apparaîtra ici."
msgid "ComplianceFramework|Add framework in %{groupName}"
msgstr ""
@@ -9756,10 +9920,10 @@ msgid "ComplianceFramework|After a framework is added to %{linkStart}%{groupName
msgstr ""
msgid "ComplianceFramework|Edit compliance framework"
-msgstr ""
+msgstr "Modifier le cadre de conformité"
msgid "ComplianceFramework|New compliance framework"
-msgstr ""
+msgstr "Nouveau cadre de conformité"
msgid "ComplianceFramework|No compliance frameworks are set up yet"
msgstr ""
@@ -9771,22 +9935,22 @@ msgid "ComplianceReport|Approved by committer"
msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
-msgstr ""
+msgstr "Moins de 2 approbateurs"
msgid "ComplianceReport|No violations found"
msgstr ""
msgid "Component"
-msgstr ""
+msgstr "Composant"
msgid "Confidence"
-msgstr ""
+msgstr "Confiance"
msgid "Confidential"
msgstr "Confidentiel"
msgid "Confidential issue"
-msgstr ""
+msgstr "Ticket confidentiel"
msgid "Confidential note"
msgstr "Note confidentielle"
@@ -9801,34 +9965,34 @@ msgid "Configuration help"
msgstr ""
msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
-msgstr ""
+msgstr "Configurer l'affichage et le contenu des %{italic_start}Nouveautés%{italic_end}."
msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Configurez %{link} pour suivre les événements. %{link_start}En savoir plus.%{link_end}"
msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and %{housekeeping_link_start}housekeeping%{link_end} on repositories."
-msgstr ""
+msgstr "Configurez des %{repository_checks_link_start}vérifications de dépôt%{link_end} et la %{housekeeping_link_start}maintenance%{link_end} sur les dépôts."
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
-msgstr ""
+msgstr "Configurer les CAPTCHAs, limitations d'adresse IP et autres mesures anti-pourriel."
msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
-msgstr ""
+msgstr "Paramétrez l'Analyse de Conteneurs dans `.gitlab-ci.yml` en utilisant le modèle géré de GitLab. Vous pouvez [modifier des variables](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) pour personnaliser les paramètres de l'Analyse de Conteneurs."
msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "Configurer l'Analyse de Conteneurs dans `.gitlab-ci.yml`, en créant ce fichier s'il n'existe pas déjà"
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 "Paramétrez l'Analyse de Dépendances dans `.gitlab-ci.yml` en utilisant le modèle géré de GitLab. Vous pouvez [modifier des variables](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) pour personnaliser les paramètres de l'Analyse de Dépendances."
msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "Configurer l'Analyse de Dépendances dans `.gitlab-ci.yml`, en créant ce fichier s'il n'existe pas déjà"
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "Configurer le Suivi des Erreurs"
msgid "Configure GitLab"
-msgstr ""
+msgstr "Configurer GitLab"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -9837,37 +10001,37 @@ msgid "Configure Gitaly timeouts."
msgstr "Configurer les délais d’expiration de Gitaly."
msgid "Configure Integrations"
-msgstr ""
+msgstr "Configurer les intégrations"
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 ""
+msgstr "Paramétrez SAST pour IaC dans `.gitlab-ci.yml` en utilisant le modèle géré de GitLab. Vous pouvez [modifier des variables](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) pour personnaliser les paramètres SAST pour IaC."
msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "Configurez SAST pour IaC dans `.gitlab-ci.yml`, en créant ce fichier s'il n'existe pas déjà"
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 ""
+msgstr "Paramétrez SAST dans `.gitlab-ci.yml` en utilisant le modèle géré de GitLab. Vous pouvez [modifier des variables](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) pour personnaliser les paramètres SAST."
msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "Configurez SAST dans `.gitlab-ci.yml`, en créant ce fichier s'il n'existe pas déjà"
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 "Paramétrez la Détection de Secrets dans `.gitlab-ci.yml` en utilisant le modèle géré de GitLab. Vous pouvez [modifier des variables](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) pour personnaliser les paramètres de la Détection de Secrets."
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "Configurer la Détection de Secrets dans `.gitlab-ci.yml`, en créant ce fichier s'il n'existe pas déjà"
msgid "Configure Sentry integration for error tracking"
-msgstr ""
+msgstr "Configurer l'intégration de Sentry pour le suivi des erreurs"
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 "Configurez un fichier %{codeStart}.gitlab-webide.yml%{codeEnd} dans le répertoire %{codeStart}.gitlab%{codeEnd} pour commencer à utiliser le Terminal Web. %{helpStart}En savoir plus.%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
-msgstr ""
+msgstr "Configurer les autorisations avancées, le Stockage de Fichiers Volumineux (LFS), les paramètres d'authentification à deux facteurs et de CI/CD."
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
@@ -9876,7 +10040,7 @@ msgid "Configure existing installation"
msgstr ""
msgid "Configure pipeline"
-msgstr ""
+msgstr "Configurer le pipeline"
msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
msgstr ""
@@ -9894,19 +10058,19 @@ msgid "Configure repository mirroring."
msgstr ""
msgid "Configure repository storage."
-msgstr ""
+msgstr "Configurer le stockage du dépôt."
msgid "Configure settings for Advanced Search with Elasticsearch."
-msgstr ""
+msgstr "Configurer les paramètres de Recherche Avancée avec Elasticsearch."
msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
msgstr ""
msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "Configurer des limitations spécifiques pour les requêtes Git LFS pour remplacer celles générales aux IP et utilisateurs."
msgid "Configure specific limits for deprecated API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "Configurer des limitations spécifiques pour les requêtes d'API obsolètes pour remplacer celles générales aux IP et utilisateurs."
msgid "Configure the %{link} integration."
msgstr "Configurez l’intégration de %{link}."
@@ -9921,10 +10085,10 @@ msgid "Configure via Merge Request"
msgstr ""
msgid "Configure which lists are shown for anyone who visits this board"
-msgstr ""
+msgstr "Configurer les listes qui sont affichées pour toute personne visitant ce tableau"
msgid "Configure with a merge request"
-msgstr ""
+msgstr "Configurer avec une demande de fusion"
msgid "Configure your environments to be deployed to specific geographical regions"
msgstr ""
@@ -9984,25 +10148,25 @@ msgid "Conflict: This file was renamed in the source branch, but removed in the
msgstr ""
msgid "Confluence"
-msgstr ""
+msgstr "Confluence"
msgid "Confluence Cloud Workspace URL"
-msgstr ""
+msgstr "URL de l'espace de travail Confluence Cloud"
msgid "ConfluenceService|Confluence Workspace"
-msgstr ""
+msgstr "Espace de travail Confluence"
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
-msgstr ""
+msgstr "Lier un espace de travail Confluence à la barre latérale."
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 "Lier un espace de travail Confluence à la barre latérale. L'activation de cette intégration remplace le lien « Wiki » de la barre latérale par un lien vers un espace de travail Confluence. Le wiki GitLab reste toujours disponible sur l'URL d'origine."
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 "Votre wiki GitLab est toujours disponible sur %{wiki_link}. Pour réactiver le lien vers votre wiki GitLab, désactivez cette intégration."
msgid "Congratulations, your free trial is activated."
-msgstr ""
+msgstr "Félicitations, votre essai gratuit est activé."
msgid "Connect"
msgstr "Connecter"
@@ -10050,16 +10214,19 @@ msgid "Contact support"
msgstr ""
msgid "Contacts"
-msgstr ""
+msgstr "Contacts"
msgid "Container Registry"
msgstr "Registre de conteneur"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
msgid "Container must be a project or a group."
-msgstr ""
+msgstr "Le conteneur doit être un projet ou un groupe."
msgid "Container registry images"
msgstr ""
@@ -10068,18 +10235,18 @@ msgid "Container registry is not enabled on this GitLab instance. Ask an adminis
msgstr ""
msgid "Container repositories"
-msgstr ""
+msgstr "Dépôts de conteneurs"
msgid "Container repository"
-msgstr ""
+msgstr "Dépôt de conteneurs"
msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
-msgstr ""
+msgstr "Veuillez aller dans les %{linkStart}paramètres d'administration%{linkEnd} pour activer cette fonction."
msgid "ContainerRegistry|%{count} Image repository"
msgid_plural "ContainerRegistry|%{count} Image repositories"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} dépôt d'images"
+msgstr[1] "%{count} dépôts d'images"
msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
@@ -10087,64 +10254,64 @@ msgstr[0] ""
msgstr[1] ""
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
-msgstr ""
+msgstr "%{strongStart}Désactivé%{strongEnd} - Les étiquettes ne seront pas supprimées automatiquement."
msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
-msgstr ""
+msgstr "%{strongStart}Activé%{strongEnd} - Les étiquettes qui correspondent aux règles de cette page seront automatiquement planifiées pour suppression."
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
-msgstr ""
+msgstr "La suppression de %{title} a été planifiée avec succès"
msgid "ContainerRegistry|-- tags"
msgstr ""
msgid "ContainerRegistry|Build an image"
-msgstr ""
+msgstr "Construire une image"
msgid "ContainerRegistry|CLI Commands"
-msgstr ""
+msgstr "Commandes CLI"
msgid "ContainerRegistry|Clean up image tags"
-msgstr ""
+msgstr "Nettoyer les étiquettes d'image"
msgid "ContainerRegistry|Cleanup disabled"
-msgstr ""
+msgstr "Nettoyage désactivé"
msgid "ContainerRegistry|Cleanup in progress"
-msgstr ""
+msgstr "Nettoyage en cours"
msgid "ContainerRegistry|Cleanup incomplete"
-msgstr ""
+msgstr "Nettoyage incomplet"
msgid "ContainerRegistry|Cleanup is currently removing tags"
-msgstr ""
+msgstr "Le nettoyage est actuellement en train de supprimer des étiquettes"
msgid "ContainerRegistry|Cleanup is disabled for this project"
-msgstr ""
+msgstr "Le nettoyage est désactivé pour ce projet"
msgid "ContainerRegistry|Cleanup is ongoing"
msgstr ""
msgid "ContainerRegistry|Cleanup pending"
-msgstr ""
+msgstr "Nettoyage en attente"
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
-msgstr ""
+msgstr "La stratégie de nettoyage des étiquettes est désactivée."
msgid "ContainerRegistry|Cleanup policy successfully saved."
-msgstr ""
+msgstr "La stratégie de nettoyage a été enregistrée avec succès."
msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
-msgstr ""
+msgstr "Le nettoyage a été exécuté mais certaines étiquettes n'ont pas été supprimées"
msgid "ContainerRegistry|Cleanup will run %{time}"
msgstr ""
msgid "ContainerRegistry|Cleanup will run soon"
-msgstr ""
+msgstr "Le nettoyage sera bientôt exécuté"
msgid "ContainerRegistry|Configuration digest: %{digest}"
-msgstr ""
+msgstr "Code de hachage de configuration : %{digest}"
msgid "ContainerRegistry|Container Registry"
msgstr ""
@@ -10153,7 +10320,7 @@ msgid "ContainerRegistry|Copy build command"
msgstr ""
msgid "ContainerRegistry|Copy image path"
-msgstr ""
+msgstr "Copier le chemin de l'image"
msgid "ContainerRegistry|Copy login command"
msgstr ""
@@ -10162,106 +10329,106 @@ msgid "ContainerRegistry|Copy push command"
msgstr ""
msgid "ContainerRegistry|Delete image repository?"
-msgstr ""
+msgstr "Supprimer le dépôt d’images ?"
msgid "ContainerRegistry|Delete selected tags"
-msgstr ""
+msgstr "Supprimer les étiquettes sélectionnées"
msgid "ContainerRegistry|Delete tag"
-msgstr ""
+msgstr "Supprimer l’étiquette"
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 ""
+msgstr "Supprimer le dépôt d'images supprimera aussi toutes les images et étiquettes qu'il contient. Cette action ne peut pas être annulée. Veuillez taper ce qui suit pour confirmer : %{code}"
msgid "ContainerRegistry|Digest: %{imageId}"
-msgstr ""
+msgstr "Code de hachage : %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr ""
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "Modifier les règles de nettoyage"
msgid "ContainerRegistry|Enable expiration policy"
-msgstr ""
+msgstr "Activer la stratégie d'expiration"
msgid "ContainerRegistry|Expiration policy is disabled."
-msgstr ""
+msgstr "La politique d'expiration est désactivée."
msgid "ContainerRegistry|Expiration policy will run in %{time}"
-msgstr ""
+msgstr "La stratégie d'expiration sera exécutée dans %{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 ""
msgid "ContainerRegistry|Image repository deletion failed"
-msgstr ""
+msgstr "La suppression du dépôt d’images a échoué"
msgid "ContainerRegistry|Image repository not found"
-msgstr ""
+msgstr "Dépôt d'images introuvable"
msgid "ContainerRegistry|Image repository temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}"
-msgstr ""
+msgstr "Le dépôt d'images ne peut temporairement pas être marqué pour suppression. Veuillez réessayer dans quelques minutes. %{docLinkStart}Plus de détails%{docLinkEnd}"
msgid "ContainerRegistry|Image repository will be deleted"
-msgstr ""
+msgstr "Le dépôt d'images sera supprimé"
msgid "ContainerRegistry|Image repository with no name located at the project URL."
-msgstr ""
+msgstr "Dépôt d'image sans nom sur l'URL du projet."
msgid "ContainerRegistry|Image tags"
msgstr ""
msgid "ContainerRegistry|Invalid tag: missing manifest digest"
-msgstr ""
+msgstr "Étiquette non valide : code de hachage de manifeste manquant"
msgid "ContainerRegistry|Keep tags matching:"
-msgstr ""
+msgstr "Conserver les étiquettes correspondant à :"
msgid "ContainerRegistry|Keep the most recent:"
-msgstr ""
+msgstr "Conserver les plus récentes :"
msgid "ContainerRegistry|Keep these tags"
-msgstr ""
+msgstr "Conserver ces étiquettes"
msgid "ContainerRegistry|Last updated %{time}"
-msgstr ""
+msgstr "Dernière mise à jour %{time}"
msgid "ContainerRegistry|Login"
msgstr ""
msgid "ContainerRegistry|Manifest digest: %{digest}"
-msgstr ""
+msgstr "Code de hachage de manifeste : %{digest}"
msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
-msgstr ""
+msgstr "Permission manquante ou insuffisante, bouton de suppression désactivé"
msgid "ContainerRegistry|Next cleanup scheduled to run on:"
-msgstr ""
+msgstr "Le prochain nettoyage est planifié pour s'exécuter le :"
msgid "ContainerRegistry|Not yet scheduled"
-msgstr ""
+msgstr "Pas encore planifié"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
+msgstr "Remarque : toute mise à jour de la stratégie entraînera une modification de la date et de l’heure de l'exécution planifiée"
msgid "ContainerRegistry|Partial cleanup complete"
-msgstr ""
+msgstr "Nettoyage partiel terminé"
msgid "ContainerRegistry|Please try different search criteria"
-msgstr ""
+msgstr "Veuillez essayer des critères de recherche différents"
msgid "ContainerRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "Publication %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "Publié dans le dépôt d'images %{repositoryPath} à %{time} le %{date}"
msgid "ContainerRegistry|Push an image"
-msgstr ""
+msgstr "Pousser une image"
msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
-msgstr ""
+msgstr "N’oubliez pas de lancer %{docLinkStart}le ramasse-miettes%{docLinkEnd} pour supprimer les données périmées du stockage."
msgid "ContainerRegistry|Remove repository"
msgstr "Supprimer le dépôt"
@@ -10272,106 +10439,106 @@ msgstr[0] ""
msgstr[1] ""
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "Supprimer les étiquettes correspondant à :"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "Supprimer les étiquettes antérieures à :"
msgid "ContainerRegistry|Remove these tags"
-msgstr ""
+msgstr "Supprimer ces étiquettes"
msgid "ContainerRegistry|Run cleanup:"
-msgstr ""
+msgstr "Lancer le nettoyage :"
msgid "ContainerRegistry|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 "Économisez de l'espace de stockage en supprimant automatiquement les étiquettes du registre de conteneurs et en ne conservant que celles que vous souhaitez. %{linkStart}Comment le nettoyage fonctionne-t-il ?%{linkEnd}"
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "Configurer les règles de nettoyage"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "Définir des règles pour supprimer automatiquement les paquets inutilisés pour économiser de l'espace de stockage."
msgid "ContainerRegistry|Set up cleanup"
-msgstr ""
+msgstr "Configurer le nettoyage"
msgid "ContainerRegistry|Show full path"
-msgstr ""
+msgstr "Afficher le chemin complet"
msgid "ContainerRegistry|Some tags were not deleted"
-msgstr ""
+msgstr "Certaines étiquettes n'ont pas été supprimées"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la stratégie de nettoyage."
msgid "ContainerRegistry|Something went wrong while fetching the image details."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des détails de l'image."
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération de la liste des dépôts."
msgid "ContainerRegistry|Something went wrong while fetching the tags list."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération de la liste des étiquettes."
msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
-msgstr ""
+msgstr "Une erreur s'est produite lors du marquage de l'étiquette pour suppression."
msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
-msgstr ""
+msgstr "Une erreur s’est produite lors du marquage des étiquettes pour suppression."
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la planification de %{title} pour suppression. Veuillez réessayer."
msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la planification de la suppression de l'image."
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de la stratégie de nettoyage."
msgid "ContainerRegistry|Sorry, your filter produced no results."
msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche."
msgid "ContainerRegistry|Tag successfully marked for deletion."
-msgstr ""
+msgstr "Étiquette marquée avec succès pour suppression."
msgid "ContainerRegistry|Tags successfully marked for deletion."
-msgstr ""
+msgstr "Étiquettes marquées avec succès pour suppression."
msgid "ContainerRegistry|Tags temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}."
-msgstr ""
+msgstr "Les étiquettes ne peuvent temporairement pas être marquées pour suppression. Veuillez réessayer dans quelques minutes. %{docLinkStart}Plus de détails%{docLinkEnd}."
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 "Les étiquettes qui correspondent à ces règles sont %{strongStart}conservées%{strongEnd}, même si elles correspondent à une règle de suppression ci-dessous. L'étiquette %{secondStrongStart}la plus récente%{secondStrongEnd} est toujours conservée."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
+msgstr "Les étiquettes qui correspondent à ces règles sont %{strongStart}supprimées%{strongEnd}, sauf si une règle ci-dessus indique de les conserver."
msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Les étiquettes dont les noms correspondent à cette expression rationnelle sont conservées. %{linkStart}Voir des exemples d'expressions rationnelles.%{linkEnd}"
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Les étiquettes dont les noms correspondent à cette expression rationnelle sont supprimées. %{linkStart}Voir des exemples d'expressions rationnelles.%{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 "La stratégie de nettoyage a expiré avant de pouvoir supprimer toutes les étiquettes. Un administrateur peut %{adminLinkStart}exécuter manuellement le nettoyage maintenant%{adminLinkEnd} ou vous pouvez attendre que la stratégie de nettoyage s'exécute à nouveau automatiquement. %{docLinkStart}Plus d'informations%{docLinkEnd}"
msgid "ContainerRegistry|The cleanup will continue within %{time}. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Le nettoyage se poursuivra dans %{time}. %{linkStart}En savoir plus%{linkEnd}"
msgid "ContainerRegistry|The filter returned no results"
-msgstr ""
+msgstr "Le filtre n'a renvoyé aucun résultat"
msgid "ContainerRegistry|The image repository could not be found."
-msgstr ""
+msgstr "Le dépôt d’images n'a pas pu être trouvé."
msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
msgstr ""
msgid "ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
-msgstr ""
+msgstr "Le dépôt d'images demandé n'existe pas ou a été supprimé. Si vous pensez qu'il s'agit d'une erreur, essayez de rafraîchir la page."
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr ""
+msgstr "La valeur de cette entrée doit contenir moins de 256 caractères"
msgid "ContainerRegistry|There are no container images available in this group"
msgstr ""
@@ -10380,28 +10547,28 @@ msgid "ContainerRegistry|There are no container images stored for this project"
msgstr ""
msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de ce dépôt d'images, veuillez réessayer."
msgid "ContainerRegistry|This image has no active tags"
msgstr ""
msgid "ContainerRegistry|This image repository has failed to be deleted"
-msgstr ""
+msgstr "La suppression de ce dépôt d'images a échoué"
msgid "ContainerRegistry|This image repository is scheduled for deletion"
-msgstr ""
+msgstr "Ce dépôt d'images est programmé pour suppression"
msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Ce dépôt d'images sera supprimé. %{linkStart}En savoir plus.%{linkEnd}"
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
-msgstr ""
+msgstr "La stratégie de nettoyage des étiquettes de ce projet n’est pas activée."
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr "Pour élargir votre recherche, modifiez ou supprimez les filtres ci-dessus."
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 "Nous rencontrons des difficultés pour nous connecter au Registre de Conteneur. Veuillez essayer de rafraîchir la page. Si cette erreur persiste, veuillez consulter %{docLinkStart}la documentation de dépannage%{docLinkEnd}."
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
@@ -10416,16 +10583,16 @@ msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
msgstr ""
msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer le dépôt %{title}. Une fois confirmé, ce dépôt sera définitivement supprimé."
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
msgid "Content parsed with %{link}."
-msgstr ""
+msgstr "Contenu analysé avec %{link}."
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
-msgstr ""
+msgstr "Vous devez fournir une fonction renderMarkdown ou un sérialiseur personnalisé"
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -10461,40 +10628,40 @@ msgid "Contribution Analytics"
msgstr ""
msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
-msgstr ""
+msgstr "%{created_count} créé(e)s, %{closed_count} fermé(e)s."
msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
-msgstr ""
+msgstr "%{created_count} créé(e)s, %{merged_count} fusionné(e)s, %{closed_count} fermé(e)s."
msgid "ContributionAnalytics|%{pushes}, more than %{commits} by %{contributors}."
msgstr ""
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
-msgstr ""
+msgstr "Données analytiques des contributions pour les tickets, demandes de fusion et événements de poussée depuis %{start_date}"
msgid "ContributionAnalytics|Issues"
-msgstr ""
+msgstr "Tickets"
msgid "ContributionAnalytics|Last 3 months"
-msgstr ""
+msgstr "Les 3 derniers mois"
msgid "ContributionAnalytics|Last month"
-msgstr ""
+msgstr "Le mois dernier"
msgid "ContributionAnalytics|Last week"
-msgstr ""
+msgstr "La dernière semaine"
msgid "ContributionAnalytics|Merge requests"
-msgstr ""
+msgstr "Demandes de fusion"
msgid "ContributionAnalytics|No issues for the selected time period."
-msgstr ""
+msgstr "Aucun ticket pour la période sélectionnée."
msgid "ContributionAnalytics|No merge requests for the selected time period."
-msgstr ""
+msgstr "Aucune demande de fusion pour la période sélectionnée."
msgid "ContributionAnalytics|No pushes for the selected time period."
-msgstr ""
+msgstr "Aucune poussée pour la période sélectionnée."
msgid "Contributions for %{calendar_date}"
msgstr ""
@@ -10503,7 +10670,7 @@ msgid "Contributions per group member"
msgstr "Contributions par membre du groupe"
msgid "Contributor"
-msgstr ""
+msgstr "Contributeur"
msgid "Contributors"
msgstr "Contributeurs"
@@ -10511,15 +10678,15 @@ msgstr "Contributeurs"
msgid "Control emails linked to your account"
msgstr ""
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr "Contrôler la façon dont est utilisée la variable CI/CD CI_JOB_TOKEN CI/CD pour l'accès de l'API entre les projets."
+
msgid "Control how the GitLab Package Registry functions."
-msgstr ""
+msgstr "Contrôlez le fonctionnement du Registre de Paquets de GitLab."
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
-msgid "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."
-msgstr ""
-
msgid "Cookie domain"
msgstr ""
@@ -10539,13 +10706,13 @@ msgid "Copy %{http_label} clone URL"
msgstr ""
msgid "Copy %{name}"
-msgstr ""
+msgstr "Copier %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Copier l’URL %{protocol} de clonage"
msgid "Copy %{type}"
-msgstr ""
+msgstr "Copier %{type}"
msgid "Copy ID"
msgstr ""
@@ -10563,7 +10730,7 @@ msgid "Copy URL"
msgstr ""
msgid "Copy audio URL"
-msgstr ""
+msgstr "Copier l'URL de l'audio"
msgid "Copy branch name"
msgstr ""
@@ -10572,7 +10739,7 @@ msgid "Copy code"
msgstr ""
msgid "Copy codes"
-msgstr ""
+msgstr "Copier les codes"
msgid "Copy command"
msgstr ""
@@ -10590,7 +10757,7 @@ msgid "Copy evidence SHA"
msgstr ""
msgid "Copy failed. Please manually copy the value."
-msgstr ""
+msgstr "La copie a échoué. Veuillez copier la valeur manuellement."
msgid "Copy file contents"
msgstr ""
@@ -10599,10 +10766,10 @@ msgid "Copy file path"
msgstr ""
msgid "Copy image URL"
-msgstr ""
+msgstr "Copier l'URL de l'image"
msgid "Copy issue URL to clipboard"
-msgstr ""
+msgstr "Copier l'URL du ticket dans le presse-papiers"
msgid "Copy key"
msgstr ""
@@ -10623,22 +10790,22 @@ msgid "Copy link to chart"
msgstr ""
msgid "Copy reference"
-msgstr ""
+msgstr "Copier la référence"
msgid "Copy secret"
msgstr ""
msgid "Copy source branch name"
-msgstr ""
+msgstr "Copier le nom de la branche source"
msgid "Copy the code below to implement tracking in your application:"
-msgstr ""
+msgstr "Copiez le code ci-dessous pour implémenter le suivi dans votre application :"
msgid "Copy this registration token."
msgstr ""
msgid "Copy to clipboard"
-msgstr ""
+msgstr "Copier dans le presse-papier"
msgid "Copy token"
msgstr ""
@@ -10650,73 +10817,73 @@ msgid "Copy value"
msgstr ""
msgid "Copy video URL"
-msgstr ""
+msgstr "Copier l'URL de la vidéo"
msgid "Corpus Management"
-msgstr ""
+msgstr "Gestion du Corpus"
msgid "Corpus Management|Are you sure you want to delete the corpus?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer le corpus ?"
msgid "CorpusManagement|A corpus is used by fuzz testing to improve coverage. Corpus files can be manually created or auto-generated. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Un corpus est utilisé par les tests à données aléatoires pour améliorer la couverture. Les fichiers de corpus peuvent être créés manuellement ou générés automatiquement. %{linkStart}En savoir plus%{linkEnd}"
msgid "CorpusManagement|Actions"
-msgstr ""
+msgstr "Actions"
msgid "CorpusManagement|Corpus file"
-msgstr ""
+msgstr "Fichier de corpus"
msgid "CorpusManagement|Corpus files are used in coverage-guided fuzz testing as seed inputs to improve testing."
msgstr ""
msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
-msgstr ""
+msgstr "Les fichiers de corpus doivent être au format *.zip. 5 Go maximum"
msgid "CorpusManagement|Corpus name"
-msgstr ""
+msgstr "Nom du corpus"
msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
-msgstr ""
+msgstr "Actuellement, il n'y a aucun corpus téléversé ou généré."
msgid "CorpusManagement|File too large, Maximum 5 GB"
-msgstr ""
+msgstr "Fichier trop volumineux, Maximum 5 Go"
msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
-msgstr ""
+msgstr "Le nom de fichier ne peut contenir que des lettres minuscules (a-z), des lettres majuscules (A-Z), des chiffres (0-9), des points (.), des traits d'union (-) ou des traits de soulignement (_)."
msgid "CorpusManagement|Fuzz testing corpus management"
-msgstr ""
+msgstr "Gestion de corpus pour les tests à données aléatoires"
msgid "CorpusManagement|Last updated"
-msgstr ""
+msgstr "Dernière mise à jour"
msgid "CorpusManagement|Last used"
-msgstr ""
+msgstr "Dernière utilisation"
msgid "CorpusManagement|Latest Job:"
-msgstr ""
+msgstr "Dernière Tâche :"
msgid "CorpusManagement|Manage your fuzz testing corpus files"
msgstr ""
msgid "CorpusManagement|New corpus"
-msgstr ""
+msgstr "Nouveau corpus"
msgid "CorpusManagement|New upload"
-msgstr ""
+msgstr "Nouveau téléversement"
msgid "CorpusManagement|Not Set"
-msgstr ""
+msgstr "Non Défini"
msgid "CorpusManagement|Target"
-msgstr ""
+msgstr "Cible"
msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
-msgstr ""
+msgstr "Pour utiliser ce corpus, éditez le fichier YAML correspondant"
msgid "CorpusManagement|Total Size: %{totalSize}"
-msgstr ""
+msgstr "Taille Totale : %{totalSize}"
msgid "Could not add admins as members"
msgstr ""
@@ -10725,7 +10892,7 @@ msgid "Could not apply %{name} command."
msgstr ""
msgid "Could not apply %{name} command. %{message}."
-msgstr ""
+msgstr "Impossible d'appliquer la commande %{name} . %{message}."
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -10734,13 +10901,13 @@ msgid "Could not change HEAD: branch '%{branch}' does not exist"
msgstr ""
msgid "Could not commit. An unexpected error occurred."
-msgstr ""
+msgstr "Impossible de valider. Une erreur inattendue s'est produite."
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
msgid "Could not connect to Sentry. Refresh the page to try again."
-msgstr ""
+msgstr "Impossible de se connecter à Sentry. Actualisez la page pour réessayer."
msgid "Could not connect to Web IDE file mirror service."
msgstr ""
@@ -10755,19 +10922,19 @@ msgid "Could not create group"
msgstr ""
msgid "Could not create issue"
-msgstr ""
+msgstr "Impossible de créer le ticket"
msgid "Could not create project"
msgstr ""
msgid "Could not create wiki page"
-msgstr ""
+msgstr "Impossible de créer la page wiki"
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
msgid "Could not delete wiki page"
-msgstr ""
+msgstr "Impossible de supprimer la page wiki"
msgid "Could not draw the lines for job relationships"
msgstr ""
@@ -10779,10 +10946,10 @@ msgid "Could not fetch training providers. Please refresh the page, or try again
msgstr ""
msgid "Could not find design."
-msgstr ""
+msgstr "Impossible de trouver le design."
msgid "Could not find iteration"
-msgstr ""
+msgstr "Itération introuvable"
msgid "Could not get the data properly"
msgstr ""
@@ -10791,10 +10958,10 @@ msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
-msgstr ""
+msgstr "Impossible de charger les compteurs d'utilisation. Veuillez actualiser la page pour réessayer."
msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
-msgstr ""
+msgstr "Impossible de supprimer %{user} de %{group}. Il n'est pas possible de supprimer le dernier propriétaire du groupe."
msgid "Could not remove %{user} from %{group}. User is not a group member."
msgstr ""
@@ -10806,7 +10973,7 @@ msgid "Could not restore the group"
msgstr ""
msgid "Could not revoke access token %{access_token_name}."
-msgstr ""
+msgstr "Impossible de révoquer le jeton d'accès %{access_token_name}."
msgid "Could not revoke impersonation token %{token_name}."
msgstr ""
@@ -10827,25 +10994,28 @@ msgid "Could not save prometheus manual configuration"
msgstr ""
msgid "Could not update the LDAP settings"
-msgstr ""
+msgstr "Impossible de mettre à jour les paramètres LDAP"
msgid "Could not update wiki page"
-msgstr ""
+msgstr "Impossible de mettre à jour la page wiki"
msgid "Could not upload your designs as one or more files uploaded are not supported."
-msgstr ""
+msgstr "Impossible de téléverser vos designs car un ou plusieurs fichiers envoyés ne sont pas pris en charge."
msgid "Couldn't assign policy to project or group"
msgstr ""
msgid "Country"
+msgstr "Pays"
+
+msgid "Counts reflect children you may not have access to."
msgstr ""
msgid "Coverage"
msgstr ""
msgid "Coverage Fuzzing"
-msgstr ""
+msgstr "Tests à données aléatoires guidés par la couverture de code"
msgid "Create"
msgstr "Créer"
@@ -10857,7 +11027,7 @@ msgid "Create %{humanized_resource_name}"
msgstr ""
msgid "Create %{type}"
-msgstr ""
+msgstr "Créer %{type}"
msgid "Create %{workspace} label"
msgstr ""
@@ -10872,22 +11042,22 @@ msgid "Create a GitLab account first, and then connect it to your %{label} accou
msgstr ""
msgid "Create a Kubernetes cluster"
-msgstr ""
+msgstr "Créer une grappe de serveurs Kubernetes"
msgid "Create a Mattermost team for this group"
msgstr ""
msgid "Create a cluster"
-msgstr ""
+msgstr "Créer une grappe de serveurs"
msgid "Create a group"
-msgstr ""
+msgstr "Créer un groupe"
msgid "Create a merge request"
msgstr ""
msgid "Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
-msgstr ""
+msgstr "Créez un nouveau fichier %{codeStart}.gitlab-ci.yml%{codeEnd} à la racine du dépôt pour commencer."
msgid "Create a new branch"
msgstr "Créer une nouvelle branche"
@@ -10899,7 +11069,7 @@ msgid "Create a new issue"
msgstr "Créer un nouveau ticket"
msgid "Create a new project"
-msgstr ""
+msgstr "Créer un nouveau projet"
msgid "Create a new repository"
msgstr ""
@@ -10908,16 +11078,16 @@ msgid "Create a personal access token on your account to pull or push via %{prot
msgstr "Créer un jeton d’accès personnel pour votre compte afin de récupérer ou pousser par %{protocol}."
msgid "Create a project"
-msgstr ""
+msgstr "Créer un projet"
msgid "Create an account using:"
msgstr ""
msgid "Create an incident. Incidents are created for each alert triggered."
-msgstr ""
+msgstr "Créer un incident. Les incidents sont créés pour chaque alerte déclenchée."
msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "Créez et fournissez votre %{link_start}Jeton d'Accès Personnel%{link_end} GitHub. Vous devrez sélectionner la portée %{code_open}repo%{code_close} ; nous pourrons ainsi afficher une liste de vos dépôts publics et privés disponibles pour l'importation."
msgid "Create branch"
msgstr "Créer une branche"
@@ -10938,7 +11108,7 @@ msgid "Create confidential merge request and branch"
msgstr ""
msgid "Create custom type"
-msgstr ""
+msgstr "Créer un type personnalisé"
msgid "Create directory"
msgstr "Créer un dossier"
@@ -10962,16 +11132,16 @@ msgid "Create group label"
msgstr "Créer une étiquette de groupe"
msgid "Create issue"
-msgstr ""
+msgstr "Créer un ticket"
msgid "Create issue to resolve all threads"
msgstr ""
msgid "Create iteration"
-msgstr ""
+msgstr "Créer une itération"
msgid "Create label"
-msgstr ""
+msgstr "Créer une étiquette"
msgid "Create list"
msgstr ""
@@ -10989,13 +11159,13 @@ msgid "Create milestone"
msgstr "Créer un jalon"
msgid "Create new"
-msgstr ""
+msgstr "Créer un nouveau"
msgid "Create new %{name} by email"
msgstr ""
msgid "Create new Value Stream"
-msgstr ""
+msgstr "Créer de nouvelles Chaînes de Valeur"
msgid "Create new branch"
msgstr "Créer une nouvelle branche"
@@ -11016,10 +11186,10 @@ msgid "Create new label"
msgstr "Créer une nouvelle étiquette"
msgid "Create new project"
-msgstr ""
+msgstr "Créer un nouveau projet"
msgid "Create new..."
-msgstr ""
+msgstr "Créer un nouveau…"
msgid "Create one"
msgstr ""
@@ -11028,7 +11198,7 @@ msgid "Create or close an issue."
msgstr "Créer ou fermer un ticket."
msgid "Create or import your first project"
-msgstr ""
+msgstr "Créez ou importez votre premier projet"
msgid "Create project"
msgstr ""
@@ -11040,13 +11210,13 @@ msgid "Create release"
msgstr ""
msgid "Create requirement"
-msgstr ""
+msgstr "Créer une exigence"
msgid "Create service account"
msgstr ""
msgid "Create snippet"
-msgstr ""
+msgstr "Créer un extrait de code"
msgid "Create tag %{tagName}"
msgstr ""
@@ -11055,10 +11225,13 @@ msgid "Create topic"
msgstr ""
msgid "Create user"
-msgstr ""
+msgstr "Créer un utilisateur"
+
+msgid "Create wildcard"
+msgstr "Créer un joker"
msgid "Create wildcard: %{searchTerm}"
-msgstr ""
+msgstr "Création de joker : %{searchTerm}"
msgid "Create your first page"
msgstr "Créer votre première page"
@@ -11067,7 +11240,13 @@ msgid "Create your group"
msgstr ""
msgid "Create, update, or delete a merge request."
-msgstr ""
+msgstr "Créer, mettre à jour ou supprimer une demande de fusion."
+
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "Ajoute un message à l'étiquette. Laisser vide crée une %{linkStart}étiquette légère%{linkEnd}."
+
+msgid "CreateGitTag|Set tag message"
+msgstr "Définir le message de l’étiquette"
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -11079,130 +11258,130 @@ msgid "CreateTag|Tag"
msgstr "Étiquette"
msgid "CreateValueStreamForm|%{name} (default)"
-msgstr ""
+msgstr "%{name} (par défaut)"
msgid "CreateValueStreamForm|'%{name}' Value Stream created"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » créée"
msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » enregistrée"
msgid "CreateValueStreamForm|Add another stage"
-msgstr ""
+msgstr "Ajouter une autre étape"
msgid "CreateValueStreamForm|Add stage"
-msgstr ""
+msgstr "Ajouter une étape"
msgid "CreateValueStreamForm|All default stages are currently visible"
-msgstr ""
+msgstr "Toutes les étapes par défaut sont actuellement visibles"
msgid "CreateValueStreamForm|Code stage start"
-msgstr ""
+msgstr "Début de l'étape de code"
msgid "CreateValueStreamForm|Create from default template"
-msgstr ""
+msgstr "Créer à partir du modèle par défaut"
msgid "CreateValueStreamForm|Create from no template"
msgstr ""
msgid "CreateValueStreamForm|Create new Value Stream"
-msgstr ""
+msgstr "Créer une nouvelle Chaîne de Valeur"
msgid "CreateValueStreamForm|Create value stream"
-msgstr ""
+msgstr "Créer une chaîne de valeur"
msgid "CreateValueStreamForm|Default stages"
-msgstr ""
+msgstr "Étapes par défaut"
msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
-msgstr ""
+msgstr "Les étapes par défaut peuvent uniquement être masquées ou réordonnées"
msgid "CreateValueStreamForm|Edit value stream"
-msgstr ""
+msgstr "Modifier la chaîne de valeur"
msgid "CreateValueStreamForm|Editing stage"
-msgstr ""
+msgstr "Modification de l'étape"
msgid "CreateValueStreamForm|End event"
-msgstr ""
+msgstr "Événement de fin"
msgid "CreateValueStreamForm|End event label"
-msgstr ""
+msgstr "Étiquette de l'événement de fin"
msgid "CreateValueStreamForm|End event: "
-msgstr ""
+msgstr "Événement de fin : "
msgid "CreateValueStreamForm|Enter stage name"
-msgstr ""
+msgstr "Entrez un nom pour l'étape"
msgid "CreateValueStreamForm|Enter value stream name"
-msgstr ""
+msgstr "Entrez le nom de la chaîne de valeur"
msgid "CreateValueStreamForm|Issue stage end"
-msgstr ""
+msgstr "Fin de l'étape de ticket"
msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
-msgstr ""
+msgstr "Longueur maximale de %{maxLength} caractères"
msgid "CreateValueStreamForm|Name is required"
-msgstr ""
+msgstr "Le nom est requis"
msgid "CreateValueStreamForm|New stage"
-msgstr ""
+msgstr "Nouvelle étape"
msgid "CreateValueStreamForm|Plan stage start"
-msgstr ""
+msgstr "Début de l'étape de planification"
msgid "CreateValueStreamForm|Please select a start event first"
-msgstr ""
+msgstr "Veuillez d'abord sélectionner un événement de début"
msgid "CreateValueStreamForm|Please select an end event"
-msgstr ""
+msgstr "Veuillez sélectionner un événement de fin"
msgid "CreateValueStreamForm|Recover hidden stage"
-msgstr ""
+msgstr "Récupérer l'étape cachée"
msgid "CreateValueStreamForm|Restore defaults"
-msgstr ""
+msgstr "Restaurer les valeurs par défaut"
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
msgid "CreateValueStreamForm|Save value stream"
-msgstr ""
+msgstr "Enregistrer la chaîne de valeur"
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "Sélectionnez l'événement de fin"
msgid "CreateValueStreamForm|Select start event"
-msgstr ""
+msgstr "Sélectionnez l'événement de début"
msgid "CreateValueStreamForm|Stage %{index}"
-msgstr ""
+msgstr "Étape %{index}"
msgid "CreateValueStreamForm|Stage name already exists"
-msgstr ""
+msgstr "Ce nom d’étape existe déjà"
msgid "CreateValueStreamForm|Stage name is required"
-msgstr ""
+msgstr "Le nom de l'étape est requis"
msgid "CreateValueStreamForm|Start event"
-msgstr ""
+msgstr "Événement de début"
msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
-msgstr ""
+msgstr "L'événement de début a été modifié, veuillez sélectionner un événement de fin valide"
msgid "CreateValueStreamForm|Start event label"
-msgstr ""
+msgstr "Étiquette de l'événement de début"
msgid "CreateValueStreamForm|Start event: "
-msgstr ""
+msgstr "Événement de début : "
msgid "CreateValueStreamForm|Update stage"
-msgstr ""
+msgstr "Mettre à jour l'étape"
msgid "CreateValueStreamForm|Value Stream name"
-msgstr ""
+msgstr "Nom de la Chaîne de Valeur"
msgid "Created"
msgstr "Créé"
@@ -11235,13 +11414,13 @@ msgid "Created by:"
msgstr "Créé par:"
msgid "Created compliance violations if any were found"
-msgstr ""
+msgstr "Infractions de conformité créées s'il en a été trouvées"
msgid "Created date"
msgstr "Date de création"
msgid "Created issue %{issueLink}"
-msgstr ""
+msgstr "Ticket créé %{issueLink}"
msgid "Created issue %{issueLink} at %{projectLink}"
msgstr "Le ticket %{issueLink} a été créé dans %{projectLink}"
@@ -11268,7 +11447,7 @@ msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue
msgstr ""
msgid "Creating"
-msgstr ""
+msgstr "Création en cours"
msgid "Creating epic"
msgstr "Création de l’épopée en cours"
@@ -11280,40 +11459,40 @@ msgid "Creation date"
msgstr ""
msgid "Creator"
-msgstr ""
+msgstr "Créateur"
msgid "Credentials"
msgstr ""
msgid "CredentialsInventory|GPG Keys"
-msgstr ""
+msgstr "Clés GPG"
msgid "CredentialsInventory|No credentials found"
-msgstr ""
+msgstr "Aucun identifiant trouvé"
msgid "CredentialsInventory|Personal Access Tokens"
-msgstr ""
+msgstr "Jetons d'Accès Personnels"
msgid "CredentialsInventory|Project Access Tokens"
-msgstr ""
+msgstr "Jetons d'accès au projet"
msgid "CredentialsInventory|SSH Keys"
-msgstr ""
+msgstr "Clés SSH"
msgid "Credit card required to be on file in order to create a pipeline"
msgstr ""
msgid "Credit card:"
-msgstr ""
+msgstr "Carte de crédit :"
msgid "Critical vulnerabilities present"
msgstr ""
msgid "Crm|Active"
-msgstr ""
+msgstr "Actif"
msgid "Crm|Contact"
-msgstr ""
+msgstr "Contact"
msgid "Crm|Contact has been added."
msgstr ""
@@ -11331,7 +11510,7 @@ msgid "Crm|Default rate"
msgstr ""
msgid "Crm|Edit contact"
-msgstr ""
+msgstr "Modifier le contact"
msgid "Crm|Edit organization"
msgstr ""
@@ -11340,7 +11519,7 @@ msgid "Crm|New contact"
msgstr ""
msgid "Crm|New organization"
-msgstr ""
+msgstr "Nouvelle organisation"
msgid "Crm|No contacts found"
msgstr ""
@@ -11364,28 +11543,28 @@ msgid "Cron Timezone"
msgstr "Fuseau horaire des tâches planifiées cron"
msgid "Cron time zone"
-msgstr ""
+msgstr "Fuseau horaire cron"
msgid "Crowd"
-msgstr ""
+msgstr "Crowd"
msgid "CsvParser|Failed to render the CSV file for the following reasons:"
-msgstr ""
+msgstr "Le rendu du fichier CSV a échoué pour les raisons suivantes :"
msgid "CsvParser|Quoted field unterminated"
-msgstr ""
+msgstr "Champ entre guillemets non terminé"
msgid "CsvParser|Too few fields"
-msgstr ""
+msgstr "Trop peu de champs"
msgid "CsvParser|Too many fields"
-msgstr ""
+msgstr "Trop de champs"
msgid "CsvParser|Trailing quote on quoted field is malformed"
-msgstr ""
+msgstr "Un guillemet d'un champ entre guillemets est malformé"
msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
-msgstr ""
+msgstr "Impossible de détecter automatiquement le délimiteur ; mis par défaut à « , »"
msgid "Current"
msgstr ""
@@ -11397,28 +11576,28 @@ msgid "Current Project"
msgstr ""
msgid "Current forks will keep their visibility level."
-msgstr ""
+msgstr "Les forks actuels conserveront leur niveau de visibilité."
msgid "Current node must be the primary node or you will be locking yourself out"
-msgstr ""
+msgstr "Le nœud actuel doit être le nœud principal sinon vous vous verrouillerez vous-même"
msgid "Current password"
msgstr ""
msgid "Current sign-in IP:"
-msgstr ""
+msgstr "IP de connexion actuelle :"
msgid "Current sign-in at:"
-msgstr ""
+msgstr "Connexion actuelle le :"
msgid "Current sign-in ip"
-msgstr ""
+msgstr "IP de connexion actuelle"
msgid "Current vulnerabilities count"
msgstr ""
msgid "CurrentUser|Buy Pipeline minutes"
-msgstr ""
+msgstr "Acheter des minutes de pipeline"
msgid "CurrentUser|Edit profile"
msgstr "Modifier le profil"
@@ -11451,13 +11630,13 @@ msgid "Custom hostname (for private commit emails)"
msgstr "Nom d’hôte personnalisé (pour les courriels de commit privés)"
msgid "Custom metrics"
-msgstr ""
+msgstr "Métriques personnalisées"
msgid "Custom notification events"
msgstr "Événements de notification personnalisés"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
-msgstr ""
+msgstr "Les niveaux de notification personnalisés sont les mêmes que les niveaux participants. Avec des niveaux de notification personnalisés, vous recevrez également des notifications pour certains événements. Pour en savoir plus, consultez les %{notificationLinkStart}courriels de notification%{notificationLinkEnd}."
msgid "Custom project templates"
msgstr "Modèles de projets personnalisés"
@@ -11469,13 +11648,13 @@ msgid "Custom range"
msgstr ""
msgid "Custom range (UTC)"
-msgstr ""
+msgstr "Plage personnalisée (UTC)"
msgid "Customer experience improvement and third-party offers"
msgstr ""
msgid "Customer relations"
-msgstr ""
+msgstr "Relation Client"
msgid "Customer relations contacts"
msgstr ""
@@ -11484,7 +11663,7 @@ msgid "Customer relations organizations"
msgstr ""
msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
-msgstr ""
+msgstr "Personnalisez les paramètres CI/CD, dont les exécuteurs partagés, les artéfacts des tâches et Auto DevOps."
msgid "Customize colors"
msgstr "Personnaliser les couleurs"
@@ -11496,7 +11675,7 @@ msgid "Customize icon"
msgstr ""
msgid "Customize language and region related settings."
-msgstr ""
+msgstr "Personnaliser les paramètres liés à la langue et à la région."
msgid "Customize name"
msgstr ""
@@ -11514,10 +11693,10 @@ msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge reque
msgstr "L'étiquette %{label_reference} a été ajoutée à la demande de fusion"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
-msgstr ""
+msgstr "L'étiquette %{label_reference} a été supprimée du ticket"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
-msgstr ""
+msgstr "L'étiquette %{label_reference} a été supprimée de la demande de fusion"
msgid "CycleAnalyticsEvent|Issue closed"
msgstr ""
@@ -11550,10 +11729,10 @@ msgid "CycleAnalyticsEvent|Merge request closed"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request created"
-msgstr ""
+msgstr "Demande de fusion créée"
msgid "CycleAnalyticsEvent|Merge request first commit time"
-msgstr ""
+msgstr "Date du premier commit de la demande de fusion"
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
msgstr ""
@@ -11562,7 +11741,7 @@ msgid "CycleAnalyticsEvent|Merge request label was added"
msgstr ""
msgid "CycleAnalyticsEvent|Merge request label was removed"
-msgstr ""
+msgstr "L'étiquette de la demande de fusion a été supprimée"
msgid "CycleAnalyticsEvent|Merge request last build finish time"
msgstr ""
@@ -11595,7 +11774,7 @@ msgid "CycleAnalyticsStage|Test"
msgstr "Test"
msgid "CycleAnalyticsStage|Total"
-msgstr ""
+msgstr "Total"
msgid "CycleAnalyticsStage|is not available for the selected group"
msgstr ""
@@ -11616,13 +11795,13 @@ msgid "CycleAnalytics|Average time to completion (days)"
msgstr ""
msgid "CycleAnalytics|Change Failure Rate"
-msgstr ""
+msgstr "Taux d’échec des changements"
msgid "CycleAnalytics|Create a custom value stream to view metrics about stages specific to your development process. Use your value stream to visualize your DevSecOps lifecycle, determine the velocity of your group, and identify inefficient processes."
msgstr ""
msgid "CycleAnalytics|Create a custom value stream…"
-msgstr ""
+msgstr "Créer une chaîne de valeur personnalisée…"
msgid "CycleAnalytics|Custom value streams to measure your DevSecOps lifecycle"
msgstr ""
@@ -11631,7 +11810,7 @@ msgid "CycleAnalytics|Data is collecting and loading."
msgstr ""
msgid "CycleAnalytics|Date"
-msgstr ""
+msgstr "Date"
msgid "CycleAnalytics|Display chart filters"
msgstr ""
@@ -11640,7 +11819,7 @@ msgid "CycleAnalytics|If you have recently upgraded to GitLab Premium, it can ta
msgstr ""
msgid "CycleAnalytics|Lead Time for Changes"
-msgstr ""
+msgstr "Délai de mise à disposition pour les Modifications"
msgid "CycleAnalytics|Number of tasks"
msgstr ""
@@ -11650,8 +11829,8 @@ msgstr ""
msgid "CycleAnalytics|Project selected"
msgid_plural "CycleAnalytics|%d projects selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Projet sélectionné"
+msgstr[1] "%d projets sélectionnés"
msgid "CycleAnalytics|Select labels"
msgstr "Sélectionner les étiquettes"
@@ -11660,31 +11839,31 @@ msgid "CycleAnalytics|Show"
msgstr ""
msgid "CycleAnalytics|Stage time: %{title}"
-msgstr ""
+msgstr "Durée de l'étape : %{title}"
msgid "CycleAnalytics|Tasks by type"
-msgstr ""
+msgstr "Tâches par type"
msgid "CycleAnalytics|The average time items spent in this stage. Data limited to items completed within this date range."
-msgstr ""
+msgstr "La durée moyenne que les éléments prennent au cours de cette étape. Les données sont limitées aux éléments terminés sur cet intervalle de dates."
msgid "CycleAnalytics|The given date range is larger than 180 days"
-msgstr ""
+msgstr "La plage de dates donnée est supérieure à 180 jours"
msgid "CycleAnalytics|The total time items spent across each value stream stage. Data limited to items completed within this date range."
-msgstr ""
+msgstr "La durée totale que les éléments prennent au cours de toutes les étapes de la chaîne de valeur. Les données sont limitées aux éléments terminés sur cet intervalle de dates."
msgid "CycleAnalytics|There is no data for 'Stage time' available. Adjust the current filters."
-msgstr ""
+msgstr "Il n'y a aucune donnée disponible pour « Durée de l'étape ». Ajustez les filtres actuels."
msgid "CycleAnalytics|There is no data for 'Total time' available. Adjust the current filters."
-msgstr ""
+msgstr "Il n'y a aucune donnée disponible pour « Durée totale ». Ajustez les filtres actuels."
msgid "CycleAnalytics|Time to Restore Service"
-msgstr ""
+msgstr "Temps de restauration du service"
msgid "CycleAnalytics|Total time"
-msgstr ""
+msgstr "Durée totale"
msgid "CycleAnalytics|group dropdown filter"
msgstr ""
@@ -11696,100 +11875,100 @@ msgid "CycleAnalytics|project dropdown filter"
msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
-msgstr ""
+msgstr "La visualisation des DAG nécessite au minimum 3 tâches dépendantes."
msgid "DAST Configuration"
-msgstr ""
+msgstr "Configuration DAST"
msgid "DAST configuration not found"
-msgstr ""
+msgstr "Configuration DAST introuvable"
msgid "DAST profile not found: %{name}"
-msgstr ""
+msgstr "Profil DAST introuvable : %{name}"
msgid "DAST profiles"
-msgstr ""
+msgstr "Profils DAST"
msgid "DNS"
msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "DORA4Metrics|Average (last %{days}d)"
-msgstr ""
+msgstr "Moyenne (%{days} derniers jours)"
msgid "DORA4Metrics|Change failure rate"
-msgstr ""
+msgstr "Taux d’échec des changements"
msgid "DORA4Metrics|Change failure rate (percentage)"
-msgstr ""
+msgstr "Taux d’échec des changements (pourcentage)"
msgid "DORA4Metrics|Date"
-msgstr ""
+msgstr "Date"
msgid "DORA4Metrics|Days for an open incident"
-msgstr ""
+msgstr "Jours pour un incident ouvert"
msgid "DORA4Metrics|Days from merge to deploy"
-msgstr ""
+msgstr "Jours entre la fusion et le déploiement"
msgid "DORA4Metrics|Deployment frequency"
-msgstr ""
+msgstr "Fréquence de déploiement"
msgid "DORA4Metrics|Lead time for changes"
-msgstr ""
+msgstr "Délai d'exécution des modifications"
msgid "DORA4Metrics|Lead time for changes (median days)"
-msgstr ""
+msgstr "Délai d'exécution des changements (jours médians)"
msgid "DORA4Metrics|Median (last %{days}d)"
-msgstr ""
+msgstr "Médiane (%{days} derniers jours)"
msgid "DORA4Metrics|Median time (last %{days}d)"
-msgstr ""
+msgstr "Durée médiane (%{days} derniers jours)"
msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
-msgstr ""
+msgstr "Durée médiane d'ouverture d'un incident dans un environnement de production au cours de la période donnée."
msgid "DORA4Metrics|No incidents during this period"
-msgstr ""
+msgstr "Aucun incident au cours de cette période"
msgid "DORA4Metrics|No merge requests were deployed during this period"
-msgstr ""
+msgstr "Aucune demande de fusion n'a été déployée au cours de cette période"
msgid "DORA4Metrics|Number of deployments"
-msgstr ""
+msgstr "Nombre de déploiements"
msgid "DORA4Metrics|Number of incidents divided by the number of deployments to a production environment in the given time period."
-msgstr ""
+msgstr "Nombre d’incidents divisé par le nombre de déploiements vers un environnement de production au cours de la période donnée."
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr ""
+msgstr "Pourcentage des déploiements qui ont échoué"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des données sur le taux d'échec des changements."
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des données sur la fréquence de déploiement."
msgid "DORA4Metrics|Something went wrong while getting lead time data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des données sur le délai de mise à disposition."
msgid "DORA4Metrics|Something went wrong while getting time to restore service data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des données sur le temps jusqu'à la remise en service."
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 "Le graphique affiche la fréquence des déploiements vers le(s) environnement(s) de production basé(s) sur la valeur %{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 ""
+msgstr "Le graphique affiche le temps médian entre la fusion d'une demande de fusion et son déploiements vers le(s) environnement(s) de production basé(s) sur la valeur %{linkStart}deployment_tier%{linkEnd}."
msgid "DORA4Metrics|Time to restore service"
-msgstr ""
+msgstr "Temps jusqu'à la remise en service"
msgid "DORA4Metrics|Time to restore service (median days)"
-msgstr ""
+msgstr "Temps jusqu'à la remise en service (jours médians)"
msgid "DSN"
msgstr ""
@@ -11819,274 +11998,274 @@ msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available f
msgstr ""
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 "Personnalisez la configuration DAST pour répondre à vos besoins. Les paramètres modifiés ici remplacent ceux fournis par GitLab et sont exclus des mises à jour. Pour les détails sur les options de configuration plus avancées, voir la %{docsLinkStart}documentation de GitLab sur DAST%{docsLinkEnd}."
msgid "DastConfig|DAST CI/CD configuration"
-msgstr ""
+msgstr "Configuration CI/CD pour DAST"
msgid "DastConfig|Enable DAST to automatically test for vulnerabilities in your project's running application, website, or API, in the CI/CD pipeline. Configuration changes must be applied to your .gitlab-ci.yml file to take effect. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
-msgstr ""
+msgstr "Activer DAST pour rechercher automatiquement les vulnérabilités dans l'application en cours, le site web ou l'API de votre projet, via un pipeline CI/CD. Afin de prendre effet, des modifications de configuration doivent être apportées à votre fichier .gitlab-ci.yml. Pour la description de toutes les options de configuration, voir la %{linkStart}documentation de GitLab sur DAST%{linkEnd}."
msgid "DastConfig|Enabled"
-msgstr ""
+msgstr "Activé"
msgid "DastConfig|Generate code snippet"
msgstr ""
msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
-msgstr ""
+msgstr "Dernière analyse déclenchée %{runTimeAgo} dans le pipeline "
msgid "DastConfig|No previous scans found for this project"
-msgstr ""
+msgstr "Aucune analyse antérieure trouvée pour ce projet"
msgid "DastConfig|Not enabled"
-msgstr ""
+msgstr "Non activé"
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 "Une analyse passive surveille tous les messages HTTP (requêtes et réponses) envoyés à la cible. Une analyse active attaque la cible pour trouver des vulnérabilités potentielles."
msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Un profil de scanner définit les détails de la configuration d’un scanner de sécurité. %{linkStart}En savoir plus%{linkEnd}."
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Un profil de site définit les informations sur les attributs et la configuration de vos API, applications et sites Web déployés. %{linkStart}En savoir plus%{linkEnd}."
msgid "DastProfiles|AJAX spider"
msgstr ""
msgid "DastProfiles|API"
-msgstr ""
+msgstr "API"
msgid "DastProfiles|API endpoint URL"
-msgstr ""
+msgstr "URL du point de terminaison de l'API"
msgid "DastProfiles|Active"
msgstr ""
msgid "DastProfiles|Additional request headers (optional)"
-msgstr ""
+msgstr "En-têtes de requête supplémentaires (facultatif)"
msgid "DastProfiles|Are you sure you want to delete this profile?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer ce profil ?"
msgid "DastProfiles|Attacks the target to find potential vulnerabilities. Active scans are potentially harmful to the site being scanned."
-msgstr ""
+msgstr "Attaque la cible pour trouver d'éventuelles vulnérabilités. Les analyses actives sont potentiellement dangereuses pour le site qui est analysé."
msgid "DastProfiles|Authentication"
-msgstr ""
+msgstr "Authentification"
msgid "DastProfiles|Authentication URL"
-msgstr ""
+msgstr "URL d’Authentification"
msgid "DastProfiles|Branch missing"
-msgstr ""
+msgstr "Branche manquante"
msgid "DastProfiles|Change scanner profile"
-msgstr ""
+msgstr "Modifier le profil du scanner"
msgid "DastProfiles|Change site profile"
-msgstr ""
+msgstr "Modifier le profil du site"
msgid "DastProfiles|Choose a scan method"
-msgstr ""
+msgstr "Choisissez une méthode d'analyse"
msgid "DastProfiles|Could not create the scanner profile. Please try again."
-msgstr ""
+msgstr "Impossible de créer le profil du scanner. Veuillez réessayer."
msgid "DastProfiles|Could not create the site profile. Please try again."
-msgstr ""
+msgstr "Impossible de créer le profil de site. Veuillez réessayer."
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de supprimer le profil du scanner. Veuillez actualiser la page ou réessayer plus tard."
msgid "DastProfiles|Could not delete scanner profiles:"
-msgstr ""
+msgstr "Impossible de supprimer les profils de scanner :"
msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de supprimer le profil du site. Veuillez actualiser la page ou réessayer plus tard."
msgid "DastProfiles|Could not delete site profiles:"
-msgstr ""
+msgstr "Impossible de supprimer les profils de site :"
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les profils de scanner. Veuillez actualiser la page ou réessayer plus tard."
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les profils de site. Veuillez actualiser la page ou réessayer plus tard."
msgid "DastProfiles|Could not update the scanner profile. Please try again."
-msgstr ""
+msgstr "Impossible de mettre à jour le profil du scanner. Veuillez réessayer."
msgid "DastProfiles|Could not update the site profile. Please try again."
-msgstr ""
+msgstr "Impossible de mettre à jour le profil de site. Veuillez réessayer."
msgid "DastProfiles|DAST profile library"
msgstr ""
msgid "DastProfiles|Debug messages"
-msgstr ""
+msgstr "Messages de débogage"
msgid "DastProfiles|Delete profile"
-msgstr ""
+msgstr "Supprimer le profil"
msgid "DastProfiles|Edit profile"
msgstr "Modifier le profil"
msgid "DastProfiles|Edit scanner profile"
-msgstr ""
+msgstr "Modifier le profil de scanner"
msgid "DastProfiles|Edit site profile"
msgstr "Modifier le profil de site"
msgid "DastProfiles|Enable Authentication"
-msgstr ""
+msgstr "Activer l'Authentification"
msgid "DastProfiles|Enable Basic Authentication"
-msgstr ""
+msgstr "Activer l'authentification Basic"
msgid "DastProfiles|Enter URLs in a comma-separated list."
-msgstr ""
+msgstr "Entrez les URL dans une liste avec la virgule comme séparateur."
msgid "DastProfiles|Enter headers in a comma-separated list."
-msgstr ""
+msgstr "Entrez les en-têtes dans une liste avec la virgule comme séparateur."
msgid "DastProfiles|Error Details"
-msgstr ""
+msgstr "Détails de l'erreur"
msgid "DastProfiles|Excluded URLs"
-msgstr ""
+msgstr "URLs exclues"
msgid "DastProfiles|Excluded URLs (optional)"
-msgstr ""
+msgstr "URLs exclues (facultatif)"
msgid "DastProfiles|Excluded paths"
-msgstr ""
+msgstr "Chemins exclus"
msgid "DastProfiles|Excluded paths (optional)"
-msgstr ""
+msgstr "Chemins exclus (facultatif)"
msgid "DastProfiles|Hide debug messages"
-msgstr ""
+msgstr "Masquer les messages de débogage"
msgid "DastProfiles|Include debug messages in the DAST console output."
-msgstr ""
+msgstr "Inclure les messages de débogage dans la sortie de la console DAST."
msgid "DastProfiles|Manage %{profileType} profiles"
-msgstr ""
+msgstr "Gérer les profils de %{profileType}"
msgid "DastProfiles|Manage profiles"
-msgstr ""
+msgstr "Gérer les profils"
msgid "DastProfiles|Manage site profiles"
-msgstr ""
+msgstr "Gérer les profils de site"
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
-msgstr ""
+msgstr "Minimum = 0 (délai d'attente non activé), Maximum = 2880 minutes"
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
-msgstr ""
+msgstr "Minimum = 1 seconde, Maximum = 3600 secondes"
msgid "DastProfiles|Monitors all HTTP requests sent to the target to find potential vulnerabilities."
-msgstr ""
+msgstr "Surveille toutes les requêtes HTTP envoyées vers la cible pour trouver des vulnérabilités potentielles."
msgid "DastProfiles|New scanner profile"
-msgstr ""
+msgstr "Nouveau profil de scanner"
msgid "DastProfiles|New site profile"
-msgstr ""
+msgstr "Nouveau profil de site"
msgid "DastProfiles|No scanner profile selected"
-msgstr ""
+msgstr "Aucun profil de scanner sélectionné"
msgid "DastProfiles|No scanner profiles created yet"
-msgstr ""
+msgstr "Aucun profil de scanner n’a encore été créé"
msgid "DastProfiles|No site profile selected"
-msgstr ""
+msgstr "Aucun profil de site sélectionné"
msgid "DastProfiles|No site profiles created yet"
-msgstr ""
+msgstr "Aucun profil de site n’a encore été créé"
msgid "DastProfiles|Not Validated"
-msgstr ""
+msgstr "Non validé"
msgid "DastProfiles|Passive"
msgstr ""
msgid "DastProfiles|Password"
-msgstr ""
+msgstr "Mot de passe"
msgid "DastProfiles|Password form field"
-msgstr ""
+msgstr "Champ de formulaire du mot de passe"
msgid "DastProfiles|Profile in use and cannot be renamed"
-msgstr ""
+msgstr "Le profil est en cours d'utilisation et ne peut pas être renommé"
msgid "DastProfiles|Profile is being used by this on-demand scan"
-msgstr ""
+msgstr "Le profil est utilisé par cette analyse à la demande"
msgid "DastProfiles|Profile name"
-msgstr ""
+msgstr "Nom du profil"
msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
-msgstr ""
+msgstr "Demander des noms et des valeurs d'en-tête. Les en-têtes sont ajoutés à chaque demande effectuée par DAST."
msgid "DastProfiles|Request headers"
-msgstr ""
+msgstr "En-têtes de requête"
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
-msgstr ""
+msgstr "Lancer l'araignée AJAX, en plus de l'araignée traditionnelle, pour explorer le site cible."
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
-msgstr ""
+msgstr "Enregistrez dans des profils les configurations couramment utilisées pour les sites cibles et les spécifications d'analyses. Utilisez-les avec une analyse à la demande."
msgid "DastProfiles|Save profile"
-msgstr ""
+msgstr "Enregistrer le profil"
msgid "DastProfiles|Scan method"
-msgstr ""
+msgstr "Méthode d'analyse"
msgid "DastProfiles|Scan mode"
-msgstr ""
+msgstr "Mode d'analyse"
msgid "DastProfiles|Scanner name"
-msgstr ""
+msgstr "Nom du scanner"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "Profil de scanner"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "Profils de scanner"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
-msgstr ""
+msgstr "Sélectionnez un profil de scanner pour lancer une analyse DAST"
msgid "DastProfiles|Select a site profile to run a DAST scan"
-msgstr ""
+msgstr "Sélectionnez un profil de site pour lancer une analyse DAST"
msgid "DastProfiles|Select branch"
-msgstr ""
+msgstr "Sélectionner une branche"
msgid "DastProfiles|Select scanner profile"
-msgstr ""
+msgstr "Sélectionner le profil du scanner"
msgid "DastProfiles|Select site profile"
-msgstr ""
+msgstr "Sélectionner le profil du site"
msgid "DastProfiles|Show debug messages"
-msgstr ""
+msgstr "Afficher les messages de débogage"
msgid "DastProfiles|Site name"
-msgstr ""
+msgstr "Nom du site"
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "Profil de site"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "Profils de site"
msgid "DastProfiles|Site type"
-msgstr ""
+msgstr "Type de site"
msgid "DastProfiles|Spider timeout"
msgstr ""
@@ -12098,159 +12277,159 @@ msgid "DastProfiles|Submit button (optional)"
msgstr ""
msgid "DastProfiles|Target URL"
-msgstr ""
+msgstr "URL cible"
msgid "DastProfiles|Target timeout"
-msgstr ""
+msgstr "Délai d'expiration pour la cible"
msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
-msgstr ""
+msgstr "Le nombre maximal de secondes autorisé pour le parcours du site par l'araignée."
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
-msgstr ""
+msgstr "Le nombre maximal de secondes autorisé pour que le site en cours de test réponde à une requête."
msgid "DastProfiles|This profile is currently being used in a policy."
-msgstr ""
+msgstr "Ce profil est actuellement utilisé par une stratégie."
msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
-msgstr ""
+msgstr "Ce profil de scanner est actuellement utilisé par une stratégie. Pour effectuer des modifications, vous devez le supprimer de la stratégie active."
msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
-msgstr ""
+msgstr "Ce profil de site est actuellement utilisé par une stratégie. Pour effectuer des modifications, vous devez le supprimer de la stratégie active."
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
-msgstr ""
+msgstr "URL"
msgid "DastProfiles|URLs to skip during the authenticated scan."
-msgstr ""
+msgstr "URLs à ignorer lors de l'analyse authentifiée."
msgid "DastProfiles|Username"
-msgstr ""
+msgstr "Nom d’utilisateur"
msgid "DastProfiles|Username form field"
-msgstr ""
+msgstr "Champ de formulaire du nom d'utilisateur"
msgid "DastProfiles|Validated"
-msgstr ""
+msgstr "Validé"
msgid "DastProfiles|Validation status"
-msgstr ""
+msgstr "État de la validation"
msgid "DastProfiles|Website"
-msgstr ""
+msgstr "Site web"
msgid "DastProfiles|What does each method do?"
-msgstr ""
+msgstr "Que fait chaque méthode ?"
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 ""
+msgstr "Vous pouvez soit choisir une analyse passive ou valider le site ciblé à partir de la page de profil. %%{docsLinkStart}Apprenez plus à propos du site de validation%{docsLinkEnd}"
msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
-msgstr ""
+msgstr "Vous ne pouvez pas exécuter une analyse active sur un site non validé."
msgid "DastProfiles|https://example.com/dast_example.har"
-msgstr ""
+msgstr "https://exemple.com/exemple_dast.har"
msgid "DastProfiles|https://example.com/openapi.json"
-msgstr ""
+msgstr "https://exemple.com/openapi.json"
msgid "DastProfiles|https://example.com/postman_collection.json"
-msgstr ""
+msgstr "https://exemple.com/collection_postman.json"
msgid "DastSiteValidation|Copy HTTP header to clipboard"
-msgstr ""
+msgstr "Copier l'en-tête HTTP dans le presse-papiers"
msgid "DastSiteValidation|Copy Meta tag to clipboard"
msgstr ""
msgid "DastSiteValidation|Could not create validation token. Please try again."
-msgstr ""
+msgstr "Impossible de créer le jeton de validation. Veuillez réessayer."
msgid "DastSiteValidation|Could not revoke validation. Please try again."
-msgstr ""
+msgstr "Impossible de révoquer la validation. Veuillez réessayer."
msgid "DastSiteValidation|Download validation text file"
-msgstr ""
+msgstr "Télécharger le fichier texte de validation"
msgid "DastSiteValidation|Header validation"
-msgstr ""
+msgstr "Validation de l'en-tête"
msgid "DastSiteValidation|Meta tag validation"
msgstr ""
msgid "DastSiteValidation|Not validated"
-msgstr ""
+msgstr "Non validé"
msgid "DastSiteValidation|Retry validation"
-msgstr ""
+msgstr "Retenter la validation"
msgid "DastSiteValidation|Revoke validation"
-msgstr ""
+msgstr "Révoquer la validation"
msgid "DastSiteValidation|Step 1 - Choose site validation method."
-msgstr ""
+msgstr "Étape 1 - Choisissez une méthode de validation de site."
msgid "DastSiteValidation|Step 2 - Add the following HTTP header to your site."
-msgstr ""
+msgstr "Étape 2 - Ajoutez l'en-tête HTTP suivant à votre site."
msgid "DastSiteValidation|Step 2 - Add the following meta tag to your site."
-msgstr ""
+msgstr "Étape 2 - Ajoutez la balise méta suivante à votre site."
msgid "DastSiteValidation|Step 2 - Download the following text file, then upload it to the target site."
-msgstr ""
+msgstr "Étape 2 - Téléchargez le fichier texte suivant, puis téléversez-le sur le site cible."
msgid "DastSiteValidation|Step 3 - Confirm header location."
-msgstr ""
+msgstr "Étape 3 - Confirmez l'emplacement de l'en-tête."
msgid "DastSiteValidation|Step 3 - Confirm meta tag location."
-msgstr ""
+msgstr "Étape 3 - Confirmez l'emplacement de la balise méta."
msgid "DastSiteValidation|Step 3 - Confirm text file location."
-msgstr ""
+msgstr "Étape 3 - Confirmez l'emplacement du fichier texte."
msgid "DastSiteValidation|Text file validation"
-msgstr ""
+msgstr "Validation par fichier texte"
msgid "DastSiteValidation|The validation has failed. Please try again."
-msgstr ""
+msgstr "La validation a échoué. Veuillez réessayer."
msgid "DastSiteValidation|The validation is in progress. Please wait..."
-msgstr ""
+msgstr "La validation est en cours. Veuillez patienter..."
msgid "DastSiteValidation|This will affect %d other profile targeting the same URL."
msgid_plural "DastSiteValidation|This will affect %d other profiles targeting the same URL."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Cela affectera %d autre profil qui a pour cible la même URL."
+msgstr[1] "Cela affectera %d autres profils qui ont pour cible la même URL."
msgid "DastSiteValidation|To run an active scan, validate your site. Site profile validation reduces the risk of running an active scan against the wrong website. All site profiles that share the same base URL share the same validation status."
-msgstr ""
+msgstr "Pour lancer une analyse active, validez votre site. La validation du profil de site réduit le risque de lancer une analyse active sur le mauvais site Web. Tous les profils de site qui partagent la même URL de base partagent le même statut de validation."
msgid "DastSiteValidation|Validate"
-msgstr ""
+msgstr "Valider"
msgid "DastSiteValidation|Validate site"
msgstr ""
msgid "DastSiteValidation|Validated"
-msgstr ""
+msgstr "Validé"
msgid "DastSiteValidation|Validating..."
-msgstr ""
+msgstr "Validation..."
msgid "DastSiteValidation|Validation failed"
-msgstr ""
+msgstr "La validation a échoué"
msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
-msgstr ""
+msgstr "La validation de %{url} a échoué. %{retryButtonStart}Réessayer la validation%{retryButtonEnd}."
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
-msgstr ""
+msgstr "La validation a réussi. Les analyses actives et passives peuvent être exécutées sur le site cible."
msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
-msgstr ""
+msgstr "Vous ne serez pas en mesure d’exécuter des analyses actives à destination de %{url}."
msgid "Data is still calculating..."
msgstr ""
@@ -12259,10 +12438,10 @@ msgid "Data refresh"
msgstr ""
msgid "Data type"
-msgstr ""
+msgstr "Type de données"
msgid "Database update failed"
-msgstr ""
+msgstr "La mise à jour de la base de données a échoué"
msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
msgstr ""
@@ -12274,7 +12453,7 @@ msgid "DatadogIntegration|API URL"
msgstr ""
msgid "DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}"
-msgstr ""
+msgstr "Étiquettes personnalisées dans Datadog. Entrez une étiquette par ligne au format %{codeOpen}clé:valeur%{codeClose}. %{linkOpen}Comment utiliser les étiquettes ?%{linkClose}"
msgid "DatadogIntegration|Environment"
msgstr ""
@@ -12295,7 +12474,7 @@ msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Use
msgstr ""
msgid "DatadogIntegration|Tags"
-msgstr ""
+msgstr "Étiquettes"
msgid "DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}."
msgstr ""
@@ -12316,14 +12495,20 @@ msgid "Date merged"
msgstr ""
msgid "Date range"
-msgstr ""
+msgstr "Intervalle de dates"
msgid "Date range limited to %{number} days"
-msgstr ""
+msgstr "La plage de dates est limitée à %{number} jours"
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr "Date de mise en application sur les espaces de noms nouvellement créés"
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr "%{start_date}–%{end_date}"
+
msgid "Day of month"
msgstr ""
@@ -12346,13 +12531,13 @@ msgid "Days to merge"
msgstr ""
msgid "Deactivate dormant users after a period of inactivity"
-msgstr ""
+msgstr "Désactiver les utilisateurs dormants après une période d'inactivité"
msgid "Dear Administrator,"
-msgstr ""
+msgstr "Cher Administrateur,"
msgid "Debian package already exists in Distribution"
-msgstr ""
+msgstr "Le paquet Debian existe déjà dans la Distribution"
msgid "Debug"
msgstr "Déboguer"
@@ -12370,13 +12555,13 @@ msgid "Decline and sign out"
msgstr "Refuser et se déconnecter"
msgid "Decompressed archive size validation failed."
-msgstr ""
+msgstr "La validation de la taille de l'archive décompressée a échoué."
msgid "Decrease"
msgstr ""
msgid "Default CI/CD configuration file"
-msgstr ""
+msgstr "Fichier de configuration CI/CD par défaut"
msgid "Default artifacts expiration"
msgstr ""
@@ -12412,37 +12597,37 @@ msgid "DefaultBranchLabel|default"
msgstr ""
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
-msgstr ""
+msgstr "Les développeurs et les mainteneurs peuvent pousser de nouveaux commits, mais pas forcer les poussées."
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
-msgstr ""
+msgstr "Les développeurs et les mainteneurs peuvent pousser de nouveaux commits, forcer les poussées ou supprimer la branche."
msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
-msgstr ""
+msgstr "Les développeurs ne peuvent pas pousser de nouveaux commits, mais les mainteneurs le peuvent. Ni les uns ni les autres ne peuvent forcer les poussées."
msgid "DefaultBranchProtection|Fully protected"
-msgstr ""
+msgstr "Entièrement protégée"
msgid "DefaultBranchProtection|Not protected"
-msgstr ""
+msgstr "Non protégée"
msgid "DefaultBranchProtection|Partially protected"
-msgstr ""
+msgstr "Partiellement protégée"
msgid "DefaultBranchProtection|Protected against pushes"
-msgstr ""
+msgstr "Protégée contre les poussées"
msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
-msgstr ""
+msgstr "Définissez un motif personnalisé pour le gel de déploiement avec la %{cronSyntaxStart}syntaxe de cron%{cronSyntaxEnd}"
msgid "Define a custom pattern with cron syntax"
msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
msgid "Define custom rules for what constitutes spam, independent of Akismet"
-msgstr ""
+msgstr "Définir des règles personnalisées pour ce qui constitue du pourriel, indépendamment d'Akismet"
msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
msgstr ""
@@ -12454,22 +12639,22 @@ msgid "Define rules for who can push, merge, and the required approvals for each
msgstr ""
msgid "Definition"
-msgstr ""
+msgstr "Définition"
msgid "Delay 2FA enforcement (hours)"
msgstr ""
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir exécuter %{jobName} immédiatement ? Dans le cas contraire, cette tâche sera automatiquement exécutée à l’heure programmée."
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
msgstr "Êtesâ€vous sûr(e) de vouloir exécuter %{job_name} immédiatement ? Dans le cas contraire, cette tâche sera automatiquement exécutée à l’heure programmée."
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir exécuter %{job_name} immédiatement ? Ce travail s'exécutera automatiquement une fois son minuteur terminé."
msgid "DelayedJobs|Run the delayed job now?"
-msgstr ""
+msgstr "Exécuter le travail différé maintenant ?"
msgid "DelayedJobs|Start now"
msgstr "Commencer maintenant"
@@ -12487,31 +12672,34 @@ msgid "Delete %{issuableType}"
msgstr ""
msgid "Delete %{name}"
-msgstr ""
+msgstr "Supprimer %{name}"
msgid "Delete Comment"
msgstr ""
msgid "Delete File"
-msgstr ""
+msgstr "Supprimer le fichier"
msgid "Delete Key"
-msgstr ""
+msgstr "Supprimer la Clé"
msgid "Delete Selected"
-msgstr ""
+msgstr "Supprimer la Sélection"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "Supprimer les Chaînes de Valeur"
msgid "Delete account"
-msgstr ""
+msgstr "Supprimer le compte"
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr "Supprimer la ressource"
+
msgid "Delete audio"
-msgstr ""
+msgstr "Supprimer l'audio"
msgid "Delete badge"
msgstr ""
@@ -12520,28 +12708,28 @@ msgid "Delete code block"
msgstr ""
msgid "Delete column"
-msgstr ""
+msgstr "Supprimer la colonne"
msgid "Delete comment"
msgstr "Supprimer le commentaire"
msgid "Delete corpus"
-msgstr ""
+msgstr "Supprimer le corpus"
msgid "Delete deploy key"
-msgstr ""
+msgstr "Supprimer la clé de déploiement"
msgid "Delete epic"
-msgstr ""
+msgstr "Supprimer l'épopée"
msgid "Delete file"
-msgstr ""
+msgstr "Supprimer le fichier"
msgid "Delete identity"
-msgstr ""
+msgstr "Supprimer l'identité"
msgid "Delete image"
-msgstr ""
+msgstr "Supprimer l'image"
msgid "Delete image repository"
msgstr ""
@@ -12553,7 +12741,7 @@ msgid "Delete label"
msgstr ""
msgid "Delete label: %{labelName}"
-msgstr ""
+msgstr "Suppression d'étiquette : %{labelName}"
msgid "Delete pipeline"
msgstr ""
@@ -12565,13 +12753,13 @@ msgid "Delete project"
msgstr ""
msgid "Delete release"
-msgstr ""
+msgstr "Supprimer la version"
msgid "Delete release %{release}?"
-msgstr ""
+msgstr "Supprimer la version %{release} ?"
msgid "Delete row"
-msgstr ""
+msgstr "Supprimer la ligne"
msgid "Delete self monitoring project"
msgstr ""
@@ -12586,22 +12774,22 @@ msgid "Delete source branch"
msgstr ""
msgid "Delete source branch when merge request is accepted."
-msgstr ""
+msgstr "Supprimer la branche source lorsque la demande de fusion est acceptée."
msgid "Delete subscription"
msgstr ""
msgid "Delete table"
-msgstr ""
+msgstr "Supprimer le tableau"
msgid "Delete this attachment"
msgstr "Supprimer cette pièce jointe"
msgid "Delete this epic and all descendants?"
-msgstr ""
+msgstr "Supprimer cette épopée et tous ses descendants ?"
msgid "Delete this project"
-msgstr ""
+msgstr "Supprimer ce projet"
msgid "Delete user list"
msgstr ""
@@ -12610,43 +12798,43 @@ msgid "Delete variable"
msgstr ""
msgid "Delete video"
-msgstr ""
+msgstr "Supprimer la vidéo"
msgid "DeleteProject|Failed to remove events. Please try again or contact administrator."
-msgstr ""
+msgstr "Impossible de supprimer les événements. Veuillez réessayer ou contacter l'administrateur."
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
-msgstr ""
+msgstr "Impossible de supprimer les extraits du projet. Veuillez réessayer ou contacter l’administrateur."
msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
msgstr ""
msgid "DeleteProject|Failed to remove webhooks. Please try again or contact administrator."
-msgstr ""
+msgstr "Impossible de supprimer les webhooks. Veuillez réessayer ou contacter l'administrateur."
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr ""
msgid "DeleteRelease|Are you sure you want to delete this release?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette version ?"
msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
-msgstr ""
+msgstr "Pour plus de détails, voir %{docsPathStart}Suppression d'une version%{docsPathEnd}."
msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer la version %{release} et ses ressources. L'étiquette Git %{tag} ne sera pas supprimée."
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "Chaîne de Valeur « %{name} » supprimée"
msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer la Chaîne de Valeur « %{name} » ?"
msgid "DeleteValueStream|Delete %{name}"
-msgstr ""
+msgstr "Supprimer %{name}"
msgid "Deleted"
msgstr "Supprimé"
@@ -12654,53 +12842,56 @@ msgstr "Supprimé"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted projects cannot be restored!"
+msgid "Deleted commits:"
msgstr ""
+msgid "Deleted projects cannot be restored!"
+msgstr "Les projets supprimés ne peuvent pas être restaurés !"
+
msgid "Deleted the source branch."
msgstr ""
msgid "Deletes the source branch"
-msgstr ""
+msgstr "Supprime la branche source"
msgid "Deleting"
msgstr ""
msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "La suppression d'un projet le place dans un état de lecture seule jusqu'au %{date}, moment auquel le projet sera définitivement supprimé. Êtes-vous ABSOLUMENT sûr(e) ?"
msgid "Deleting the project will delete its repository and all related resources, including issues and merge requests."
-msgstr ""
+msgstr "La suppression du projet supprimera son dépôt et toutes ses ressources associées, y compris les tickets et les demandes de fusion."
msgid "Deletion pending. This project will be deleted on %{date}. Repository and other project resources are read-only."
-msgstr ""
+msgstr "Suppression en attente. Ce projet sera supprimé le %{date}. Le dépôt et les autres ressources du projet sont en lecture seule."
msgid "DeletionSettings|All projects are deleted immediately."
-msgstr ""
+msgstr "Tous les projets sont supprimés immédiatement."
msgid "DeletionSettings|Deletion protection"
-msgstr ""
+msgstr "Protection contre la suppression"
msgid "DeletionSettings|Keep deleted"
-msgstr ""
+msgstr "Laisser supprimés les"
msgid "DeletionSettings|Keep deleted projects for %{number} days"
-msgstr ""
+msgstr "Conserver les projets supprimés pendant %{number}  jours"
msgid "DeletionSettings|Keep deleted projects for 1 day"
-msgstr ""
+msgstr "Conserver les projets supprimés pendant 1 journée"
msgid "DeletionSettings|None, delete immediately"
-msgstr ""
+msgstr "Aucune, supprimer immédiatement"
msgid "DeletionSettings|Only administrators can delete projects."
-msgstr ""
+msgstr "Seuls les administrateurs peuvent supprimer des projets."
msgid "DeletionSettings|Owners and administrators can delete projects."
-msgstr ""
+msgstr "Les propriétaires et les administrateurs peuvent supprimer des projets."
msgid "DeletionSettings|Retention period that deleted groups and projects will remain restorable. Personal projects are always deleted immediately. Some groups can opt-out their projects."
-msgstr ""
+msgstr "Durée de conservation pendant laquelle il reste possible de restaurer les groupes et projets supprimés. Les projets personnels sont toujours supprimés immédiatement. Certains groupes peuvent en exclure leurs projets."
msgid "Denied"
msgstr ""
@@ -12727,19 +12918,19 @@ msgstr[1] ""
msgid "Dependencies|%d more"
msgid_plural "Dependencies|%d more"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d de plus"
+msgstr[1] "%d de plus"
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnérabilité détectée"
+msgstr[1] "%d vulnérabilités détectées"
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
msgid "Dependencies|(top level)"
-msgstr ""
+msgstr "(premier niveau)"
msgid "Dependencies|All"
msgstr ""
@@ -12760,7 +12951,7 @@ msgid "Dependencies|Job failed to generate the dependency list"
msgstr ""
msgid "Dependencies|Learn more about dependency paths"
-msgstr ""
+msgstr "En savoir plus sur les chemins de dépendance"
msgid "Dependencies|License"
msgstr ""
@@ -12769,22 +12960,22 @@ msgid "Dependencies|Location"
msgstr ""
msgid "Dependencies|Location and dependency path"
-msgstr ""
+msgstr "Emplacement et chemin de dépendance"
msgid "Dependencies|Packager"
msgstr ""
msgid "Dependencies|Software Bill of Materials (SBOM) based on the %{linkStart}latest successful%{linkEnd} scan"
-msgstr ""
+msgstr "Nomenclature logicielle (SBOM) basée sur l'analyse %{linkStart}réussie la plus récente%{linkEnd}"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
-msgstr ""
+msgstr "Le chemin de dépendance du composant est basé sur le fichier verrou. Il peut y avoir plusieurs chemins. Dans ce cas, c'est le plus long qui est affiché."
msgid "Dependencies|There may be multiple paths"
-msgstr ""
+msgstr "Il peut y avoir plusieurs chemins d'accès"
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -12799,7 +12990,7 @@ msgid "Dependency List"
msgstr ""
msgid "Dependency List has no entries"
-msgstr ""
+msgstr "Aucune entrée dans la liste de dépendances"
msgid "Dependency Proxy"
msgstr ""
@@ -12808,10 +12999,10 @@ msgid "Dependency Scanning"
msgstr ""
msgid "Dependency list"
-msgstr ""
+msgstr "Liste des dépendances"
msgid "DependencyProxy|All items in the cache are scheduled for removal."
-msgstr ""
+msgstr "Tous les éléments du cache sont planifiés pour suppression."
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -12820,40 +13011,40 @@ msgid "DependencyProxy|Clear cache"
msgstr ""
msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
-msgstr ""
+msgstr "Vider automatiquement le cache du Proxy de Dépendance"
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
-msgstr ""
+msgstr "Contient %{count} blobs d'images (%{size})"
msgid "DependencyProxy|Copy prefix"
-msgstr ""
+msgstr "Copier le préfixe"
msgid "DependencyProxy|Dependency Proxy"
-msgstr ""
+msgstr "Proxy de dépendance"
msgid "DependencyProxy|Dependency Proxy image prefix"
-msgstr ""
+msgstr "Préfixe d'image du Proxy de Dépendance"
msgid "DependencyProxy|Enable Dependency Proxy"
-msgstr ""
+msgstr "Activer le proxy de dépendance"
msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
-msgstr ""
+msgstr "Activer le Proxy de Dépendance et les paramètres pour vider le cache."
msgid "DependencyProxy|Image list"
-msgstr ""
+msgstr "Liste d'images"
msgid "DependencyProxy|Scheduled for deletion"
msgstr ""
msgid "DependencyProxy|There are no images in the cache"
-msgstr ""
+msgstr "Il n'y a aucune image dans le cache"
msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
-msgstr ""
+msgstr "Pour voir le préfixe d'image et ce qu'il y a dans le cache, visitez le %{linkStart}Proxy de Dépendance%{linkEnd}"
msgid "DependencyProxy|When enabled, images older than 90 days will be removed from the cache."
-msgstr ""
+msgstr "Cette option activée, les images de plus de 90 jours seront supprimées du cache."
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -12862,8 +13053,8 @@ msgstr[1] ""
msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Dépend de la %{strongStart}fermeture de %{closedCount}%{strongEnd} demande de fusion."
+msgstr[1] "Dépend de la %{strongStart}fermeture de %{closedCount}%{strongEnd} demandes de fusion."
msgid "Deploy"
msgid_plural "Deploys"
@@ -12871,7 +13062,7 @@ msgstr[0] "Déploiement"
msgstr[1] "Déploiements"
msgid "Deploy Key"
-msgstr ""
+msgstr "Clé de Déploiement"
msgid "Deploy Keys"
msgstr "Clefs de déploiement"
@@ -12883,16 +13074,16 @@ msgid "Deploy container based web apps on Google managed clusters"
msgstr ""
msgid "Deploy freezes"
-msgstr ""
+msgstr "Gels de déploiement"
msgid "Deploy key was successfully updated."
msgstr ""
msgid "Deploy keys"
-msgstr ""
+msgstr "Clés de déploiement"
msgid "Deploy keys grant read/write access to all repositories in your instance"
-msgstr ""
+msgstr "Les clés de déploiement accordent un accès en lecture/écriture à tous les dépôts de votre instance"
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr ""
@@ -12907,43 +13098,43 @@ msgid "DeployBoards|To see deployment progress for your environments, make sure
msgstr ""
msgid "DeployBoard|Kubernetes Pods"
-msgstr ""
+msgstr "Pods Kubernetes"
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
-msgstr ""
+msgstr "Ajoutez une période de gel pour empêcher la publication de versions non souhaitées pour une certaine durée et pour un environnement donné. Vous devez actualiser les tâches de déploiement dans %{filename} pour refléter les gels de déploiements ajoutés ici. %{freeze_period_link_start}En savoir plus.%{freeze_period_link_end}"
msgid "DeployFreeze|Add deploy freeze"
-msgstr ""
+msgstr "Ajouter un gel de déploiement"
msgid "DeployFreeze|Delete"
-msgstr ""
+msgstr "Supprimer"
msgid "DeployFreeze|Delete deploy freeze?"
-msgstr ""
+msgstr "Supprimer le gel de déploiement ?"
msgid "DeployFreeze|Delete freeze period"
-msgstr ""
+msgstr "Supprimer la période de gel"
msgid "DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?"
-msgstr ""
+msgstr "Le gel de déploiement du %{start} au %{end} dans %{timezone} sera supprimé. Êtes-vous sûr ?"
msgid "DeployFreeze|Edit"
-msgstr ""
+msgstr "Modifier"
msgid "DeployFreeze|Freeze end"
-msgstr ""
+msgstr "Fin du gel"
msgid "DeployFreeze|Freeze start"
-msgstr ""
+msgstr "Début du gel"
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
-msgstr ""
+msgstr "Il n'existe aucun gel de déploiement pour ce projet. Pour en ajouter un, sélectionnez %{strongStart}Ajouter un gel de déploiement%{strongEnd}"
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
-msgstr ""
+msgstr "Spécifiez les gels de déploiement avec la %{cron_syntax_link_start}syntaxe cron%{cron_syntax_link_end}."
msgid "DeployFreeze|Time zone"
-msgstr ""
+msgstr "Fuseau horaire"
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} autres"
@@ -12970,7 +13161,7 @@ msgid "DeployKeys|Expand %{count} other projects"
msgstr "Afficher %{count} autres projets"
msgid "DeployKeys|Grant write permissions to this key"
-msgstr ""
+msgstr "Accorder des autorisations d'écriture à cette clé"
msgid "DeployKeys|Loading deploy keys"
msgstr "Chargement des clefs de déploiement"
@@ -12993,20 +13184,23 @@ msgstr "Accès en lecture seule"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Jetons de déploiement actifs : (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "Autorise l'accès en lecture et écriture sur les images du registre."
+
msgid "DeployTokens|Allows read and write access to the package registry."
-msgstr ""
+msgstr "Autorise l'accès en lecture et écriture au registre de paquets."
msgid "DeployTokens|Allows read-only access to registry images."
-msgstr ""
+msgstr "Autorise l'accès en lecture seule aux images de registre."
msgid "DeployTokens|Allows read-only access to the package registry."
-msgstr ""
+msgstr "Autorise l'accès en lecture seule au registre de paquets."
msgid "DeployTokens|Allows read-only access to the repository."
-msgstr ""
+msgstr "Autorise l’accès en lecture seule au dépôt."
msgid "DeployTokens|Allows write access to registry images."
-msgstr ""
+msgstr "Autorise l'accès en écriture aux images de registre."
msgid "DeployTokens|Copy deploy token"
msgstr ""
@@ -13015,7 +13209,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 "Créer un nouveau jeton de déploiement pour tous les projets de ce groupe. %{link_start}Que sont les jetons de déploiement ?%{link_end}"
msgid "DeployTokens|Create deploy token"
msgstr "Créer un jeton de déploiement"
@@ -13024,31 +13218,34 @@ msgid "DeployTokens|Created"
msgstr "Créé"
msgid "DeployTokens|Deploy tokens"
-msgstr ""
+msgstr "Jetons de déploiement"
msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
-msgstr ""
+msgstr "Les jetons de déploiement permettent l’accès aux paquets, à votre dépôt et aux images de registre."
msgid "DeployTokens|Enter a unique name for your deploy token."
-msgstr ""
+msgstr "Entrez un nom unique pour votre jeton de déploiement."
msgid "DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}."
-msgstr ""
+msgstr "Entrez un nom d'utilisateur pour votre jeton. Par défaut : %{code_start}gitlab+deploy-token-{n}%{code_end}."
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
-msgstr ""
+msgstr "Entrez une date d’expiration pour votre jeton. Par défaut, n’expire jamais."
+
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "Date d'expiration (facultatif)"
msgid "DeployTokens|Expires"
msgstr "Expire"
msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
-msgstr ""
+msgstr "Les jetons de déploiement de groupe permettent l’accès aux paquets, dépôts et images de registre dans le groupe."
msgid "DeployTokens|Name"
msgstr "Nom"
msgid "DeployTokens|New deploy token"
-msgstr ""
+msgstr "Nouveau jeton de déploiement"
msgid "DeployTokens|Revoke"
msgstr "Révoquer"
@@ -13059,6 +13256,9 @@ msgstr "Révoquer %{name}"
msgid "DeployTokens|Scopes"
msgstr "Champs d’application"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr "Portées (en sélectionner au moins une)"
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13066,19 +13266,25 @@ msgid "DeployTokens|This action cannot be undone."
msgstr "Cette action ne peut pas être annulée."
msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
-msgstr ""
+msgstr "Ce nom d'utilisateur prend en charge des accès. %{link_start}Quels types d'accès ?%{link_end}"
msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
-msgstr ""
+msgstr "Utilisez ce jeton en tant que mot de passe. Enregistrez-le. Ce mot de passe %{i_start}ne peut pas%{i_end} être récupéré."
msgid "DeployTokens|Username"
msgstr "Nom d’utilisateur"
+msgid "DeployTokens|Username (optional)"
+msgstr "Nom d’utilisateur (facultatif)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "Votre Nouveau Jeton de Déploiement"
+
msgid "DeployTokens|Your new Deploy Token username"
-msgstr ""
+msgstr "Le nom d'utilisateur de votre nouveau Jeton de Déploiement"
msgid "DeployTokens|Your new group deploy token has been created."
-msgstr ""
+msgstr "Votre nouveau jeton de déploiement de groupe a été créé."
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Votre nouveau jeton de déploiement pour votre projet a été créé."
@@ -13102,13 +13308,13 @@ msgid "Deploying to AWS is easy with GitLab"
msgstr ""
msgid "Deployment"
-msgstr ""
+msgstr "Déploiement"
msgid "Deployment Frequency"
-msgstr ""
+msgstr "Fréquence de déploiement"
msgid "Deployment Target|%{linkStart}How to provision or deploy to Kubernetes clusters from GitLab?%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Comment provisionner ou déployer vers des grappes de serveurs Kubernetes depuis GitLab ?%{linkEnd}"
msgid "Deployment Target|Project deployment target (optional)"
msgstr ""
@@ -13117,22 +13323,22 @@ msgid "Deployment Target|Select the deployment target"
msgstr ""
msgid "Deployment frequency"
-msgstr ""
+msgstr "Fréquence de déploiement"
msgid "DeploymentApproval| Current approvals: %{current}"
-msgstr ""
+msgstr "Approbations actuelles : %{current}"
msgid "DeploymentApproval|Approval options"
-msgstr ""
+msgstr "Options d'approbation"
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
-msgstr ""
+msgstr "Approuver ou rejeter le déploiement #%{deploymentIid}"
msgid "DeploymentApproval|Approved %{time}"
-msgstr ""
+msgstr "Approuvé %{time}"
msgid "DeploymentApproval|Approved by you %{time}"
-msgstr ""
+msgstr "Approuvé par vous %{time}"
msgid "DeploymentApproval|Approving will run the manual job from deployment #%{deploymentIid}. Rejecting will fail the manual job."
msgstr ""
@@ -13141,28 +13347,28 @@ msgid "DeploymentApproval|Deployment tier: %{tier}"
msgstr ""
msgid "DeploymentApproval|Environment: %{environment}"
-msgstr ""
+msgstr "Environnement : %{environment}"
msgid "DeploymentApproval|Manual job: %{jobName}"
-msgstr ""
+msgstr "Tâche manuelle : %{jobName}"
msgid "DeploymentApproval|Rejected %{time}"
-msgstr ""
+msgstr "Rejeté %{time}"
msgid "DeploymentApproval|Rejected by you %{time}"
-msgstr ""
+msgstr "Rejeté par vous %{time}"
msgid "DeploymentTarget|GitLab Pages"
msgstr ""
msgid "DeploymentTarget|Heroku"
-msgstr ""
+msgstr "Heroku"
msgid "DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)"
-msgstr ""
+msgstr "Fournisseur d'infrastructure (Terraform, Cloudformation, etc.)"
msgid "DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)"
-msgstr ""
+msgstr "Kubernetes (GKE, EKS, OpenShift etc.)"
msgid "DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)"
msgstr ""
@@ -13171,60 +13377,60 @@ msgid "DeploymentTarget|Mobile app store"
msgstr ""
msgid "DeploymentTarget|No deployment planned"
-msgstr ""
+msgstr "Aucun déploiement planifié"
msgid "DeploymentTarget|Other hosting service"
-msgstr ""
+msgstr "Autre service d'hébergement"
msgid "DeploymentTarget|Registry (package or container)"
-msgstr ""
+msgstr "Registre (paquet ou conteneur)"
msgid "DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)"
msgstr ""
msgid "DeploymentTarget|Serverless backend (Lambda, Cloud functions)"
-msgstr ""
+msgstr "Backend Serverless (fonctions Lambda, Cloud)"
msgid "DeploymentTarget|Virtual machine (for example, EC2)"
-msgstr ""
+msgstr "Machine virtuelle (par exemple, EC2)"
msgid "Deployments"
msgstr ""
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{deployments} environnement impacté."
+msgstr[1] "%{deployments} environnements impactés."
msgid "Deployment|API"
msgstr ""
msgid "Deployment|Cancelled"
-msgstr ""
+msgstr "Annulé"
msgid "Deployment|Created"
-msgstr ""
+msgstr "Créé"
msgid "Deployment|Deployment ID"
-msgstr ""
+msgstr "ID de déploiement"
msgid "Deployment|Failed"
-msgstr ""
+msgstr "Échec"
msgid "Deployment|Latest Deployed"
-msgstr ""
+msgstr "Dernier déploiement"
msgid "Deployment|Needs Approval"
-msgstr ""
+msgstr "Nécessite une approbation"
msgid "Deployment|Running"
-msgstr ""
+msgstr "En cours"
msgid "Deployment|Skipped"
-msgstr ""
+msgstr "Ignoré"
msgid "Deployment|Success"
-msgstr ""
+msgstr "Succès"
msgid "Deployment|This deployment was created using the API"
msgstr ""
@@ -13233,10 +13439,10 @@ msgid "Deployment|Triggerer"
msgstr ""
msgid "Deployment|Waiting"
-msgstr ""
+msgstr "En attente"
msgid "Deployment|blocked"
-msgstr ""
+msgstr "bloqué"
msgid "Deployment|canceled"
msgstr ""
@@ -13251,7 +13457,7 @@ msgid "Deployment|running"
msgstr ""
msgid "Deployment|skipped"
-msgstr ""
+msgstr "Ignoré"
msgid "Deployment|success"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13287,16 +13484,16 @@ msgid "Description"
msgstr "Description"
msgid "Description (alt text)"
-msgstr ""
+msgstr "Description (texte alternatif)"
msgid "Description (optional)"
-msgstr ""
+msgstr "Description (facultative)"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr ""
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
-msgstr ""
+msgstr "Description analysée avec %{link_start}GitLab Flavored Markdown%{link_end}."
msgid "Description:"
msgstr "Description :"
@@ -13308,87 +13505,84 @@ msgid "Design Management files and data"
msgstr ""
msgid "Design repositories"
-msgstr ""
+msgstr "Dépôts de design"
msgid "Design repository"
-msgstr ""
+msgstr "Dépôt de design"
msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
msgid_plural "DesignManagement|The designs you tried uploading did not change."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{filename} n'a pas changé."
+msgstr[1] "Les designs que vous avez essayé de téléverser n'ont pas changé."
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
msgid "DesignManagement|Archive design"
-msgstr ""
+msgstr "Archiver le design"
msgid "DesignManagement|Archive designs"
-msgstr ""
+msgstr "Archiver les designs"
msgid "DesignManagement|Archive selected"
-msgstr ""
+msgstr "Archiver la sélection"
msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
-msgstr ""
+msgstr "Les designs archivés resteront disponibles dans les versions précédentes de la collection de designs."
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
-msgstr ""
-
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir archiver les designs sélectionnés ?"
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir annuler la création de ce commentaire ?"
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr ""
+msgid "DesignManagement|Comment"
+msgstr "Commentaire"
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
-msgstr ""
+msgstr "Impossible d'ajouter un nouveau commentaire. Veuillez réessayer."
msgid "DesignManagement|Could not create new discussion. Please try again."
-msgstr ""
+msgstr "Impossible de créer une nouvelle discussion. Veuillez réessayer."
msgid "DesignManagement|Could not update discussion. Please try again."
-msgstr ""
+msgstr "Impossible de mettre à jour la discussion. Veuillez réessayer."
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
msgid "DesignManagement|Deselect all"
-msgstr ""
+msgstr "Tout désélectionner"
msgid "DesignManagement|Designs"
-msgstr ""
+msgstr "Designs"
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "Discussion"
msgid "DesignManagement|Download design"
-msgstr ""
+msgstr "Télécharger le design"
msgid "DesignManagement|Error uploading a new design. Please try again."
-msgstr ""
+msgstr "Erreur lors du téléversement d'un nouveau design. Veuillez réessayer."
msgid "DesignManagement|Go back to designs"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13415,37 +13603,37 @@ msgid "DesignManagement|Resolved Comments"
msgstr ""
msgid "DesignManagement|Save comment"
-msgstr ""
+msgstr "Enregistrer le commentaire"
msgid "DesignManagement|Select all"
-msgstr ""
+msgstr "Tout sélectionner"
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
-msgstr ""
+msgstr "Plusieurs des designs que vous avez essayé de téléverser n'ont pas changé : %{skippedFiles} et %{moreCount} de plus."
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
-msgstr ""
+msgstr "Certains des designs que vous avez essayé de téléverser n'ont pas changé : %{skippedFiles}."
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
-msgstr ""
+msgstr "Une erreur s’est produite lors du déplacement de vos designs. Veuillez téléverser vos designs ci-dessous."
msgid "DesignManagement|To upload designs, you'll need to enable LFS and have an admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
-msgstr ""
+msgstr "Pour téléverser des designs, il est nécessaire d'activer LFS et que l'administrateur ait activé le stockage haché. %{requirements_link_start}Plus d'informations%{requirements_link_end}"
msgid "DesignManagement|Unresolve thread"
msgstr ""
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "Téléverser des designs"
msgid "DesignManagement|Upload skipped. %{reason}"
-msgstr ""
+msgstr "Téléversement ignoré. %{reason}"
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
-msgstr ""
+msgstr "Vos designs sont en cours de copie et sont en route… Veuillez actualiser pour mettre à jour."
msgid "Designs"
msgstr ""
@@ -13463,7 +13651,7 @@ msgid "Details (default)"
msgstr ""
msgid "Details block"
-msgstr ""
+msgstr "Bloc de détails"
msgid "Detect host keys"
msgstr "Détecter les clefs de l’hôte"
@@ -13472,178 +13660,178 @@ msgid "DevOps Adoption"
msgstr ""
msgid "DevOps Reports"
-msgstr ""
+msgstr "Rapports DevOps"
msgid "DevOps adoption"
-msgstr ""
+msgstr "Adoption de DevOps"
msgid "Development"
-msgstr ""
+msgstr "Développement"
msgid "Devices (optional)"
-msgstr ""
+msgstr "Appareils (facultatif)"
msgid "DevopsAdoption|%{adoptedCount}/%{featuresCount} %{title} features adopted"
-msgstr ""
+msgstr "%{adoptedCount} fonctionnalités %{title} adoptées sur %{featuresCount}"
msgid "DevopsAdoption|Add a group to get started"
-msgstr ""
+msgstr "Ajouter un groupe pour commencer"
msgid "DevopsAdoption|Add or remove groups"
-msgstr ""
+msgstr "Ajouter ou supprimer des groupes"
msgid "DevopsAdoption|Add or remove subgroups"
-msgstr ""
+msgstr "Ajouter ou supprimer des sous-groupes"
msgid "DevopsAdoption|Adopted"
-msgstr ""
+msgstr "Adopté"
msgid "DevopsAdoption|Adoption by group"
-msgstr ""
+msgstr "Adoption par groupe"
msgid "DevopsAdoption|Adoption by subgroup"
-msgstr ""
+msgstr "Adoption par sous-groupe"
msgid "DevopsAdoption|Adoption over time"
-msgstr ""
+msgstr "Adoption au cours du temps"
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression du groupe. Veuillez réessayer."
msgid "DevopsAdoption|Approvals"
-msgstr ""
+msgstr "Approbations"
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer %{name} du tableau ?"
msgid "DevopsAdoption|At least one approval on a merge request"
-msgstr ""
+msgstr "Au moins une approbation sur une demande de fusion"
msgid "DevopsAdoption|At least one deploy"
-msgstr ""
+msgstr "Au moins un déploiement"
msgid "DevopsAdoption|At least one issue created"
-msgstr ""
+msgstr "Au moins un ticket créé"
msgid "DevopsAdoption|At least one merge request created"
-msgstr ""
+msgstr "Au moins une demande de fusion créée"
msgid "DevopsAdoption|At least one pipeline successfully run"
-msgstr ""
+msgstr "Au moins un pipeline exécuté avec succès"
msgid "DevopsAdoption|Code owners"
-msgstr ""
+msgstr "Propriétaires de code"
msgid "DevopsAdoption|Code owners enabled for at least one project"
-msgstr ""
+msgstr "Des propriétaires de code sont activés pour au moins un projet"
msgid "DevopsAdoption|Confirm remove Group"
-msgstr ""
+msgstr "Confirmez la suppression du Groupe"
msgid "DevopsAdoption|DAST"
-msgstr ""
+msgstr "DAST"
msgid "DevopsAdoption|DAST enabled for at least one project"
-msgstr ""
+msgstr "DAST activé pour au moins un projet"
msgid "DevopsAdoption|Dependency Scanning"
-msgstr ""
+msgstr "Analyse des Dépendances"
msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
-msgstr ""
+msgstr "Analyse des Dépendances activée pour au moins un projet"
msgid "DevopsAdoption|Deploys"
-msgstr ""
+msgstr "Déploiements"
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 ""
+msgstr "L'adoption DevOps suit l'utilisation des fonctionnalités clés à travers vos groupes préférés. Ajoutez un groupe au tableau pour commencer."
msgid "DevopsAdoption|Edit groups"
-msgstr ""
+msgstr "Modifier les groupes"
msgid "DevopsAdoption|Edit subgroups"
-msgstr ""
+msgstr "Modifier les sous-groupes"
msgid "DevopsAdoption|Feature adoption is based on usage in the previous calendar month. Data is updated at the beginning of each month. Last updated: %{timestamp}."
-msgstr ""
+msgstr "L'adoption de fonctionnalité est basée sur son usage au cours du mois calendaire précédent. Les données sont actualisées au début de chaque mois. Dernière mise à jour : %{timestamp}."
msgid "DevopsAdoption|Fuzz Testing"
-msgstr ""
+msgstr "Tests à données aléatoires"
msgid "DevopsAdoption|Fuzz Testing enabled for at least one project"
-msgstr ""
+msgstr "Tests à données aléatoires activés pour au moins un projet"
msgid "DevopsAdoption|Issues"
-msgstr ""
+msgstr "Tickets"
msgid "DevopsAdoption|MRs"
msgstr ""
msgid "DevopsAdoption|No results…"
-msgstr ""
+msgstr "Aucun résultat…"
msgid "DevopsAdoption|No tracked features"
-msgstr ""
+msgstr "Aucune fonctionnalité suivie"
msgid "DevopsAdoption|Not adopted"
-msgstr ""
+msgstr "Non adopté"
msgid "DevopsAdoption|Ops"
-msgstr ""
+msgstr "Ops"
msgid "DevopsAdoption|Overall adoption"
-msgstr ""
+msgstr "Adoption globale"
msgid "DevopsAdoption|Pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "DevopsAdoption|Remove Group"
-msgstr ""
+msgstr "Supprimer le Groupe"
msgid "DevopsAdoption|Remove Group from the table."
-msgstr ""
+msgstr "Supprimer le Groupe du tableau."
msgid "DevopsAdoption|Runner configured for project/group"
-msgstr ""
+msgstr "Exécuteur configuré pour un projet/groupe"
msgid "DevopsAdoption|Runners"
-msgstr ""
+msgstr "Exécuteurs"
msgid "DevopsAdoption|SAST"
-msgstr ""
+msgstr "SAST"
msgid "DevopsAdoption|SAST enabled for at least one project"
-msgstr ""
+msgstr "SAST activé pour au moins un projet"
msgid "DevopsAdoption|Sec"
-msgstr ""
+msgstr "Sec"
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'activation du groupe actuel. Veuillez actualiser la page."
msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des données d'adoption de Groupe. Veuillez actualiser la page."
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des Groupes. Veuillez actualiser la page."
msgid "DevopsAdoption|This group has no subgroups"
-msgstr ""
+msgstr "Ce groupe n’a pas de sous-groupes"
msgid "DevopsAdoption|Total number of features adopted"
-msgstr ""
+msgstr "Nombre total des fonctionnalités adoptées"
msgid "DevopsAdoption|You cannot remove the group you are currently in."
-msgstr ""
+msgstr "Vous ne pouvez pas supprimer le groupe dans lequel vous êtes actuellement."
msgid "DevopsReport|DevOps Score"
-msgstr ""
+msgstr "Score DevOps"
msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
-msgstr ""
+msgstr "Les métriques du score DevOps sont basées sur l’utilisation au cours des 30 derniers jours. Dernière mise à jour : %{timestamp}."
msgid "DevopsReport|High"
msgstr ""
@@ -13658,34 +13846,34 @@ msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Overview"
-msgstr ""
+msgstr "Vue d'ensemble"
msgid "DevopsReport|Score"
-msgstr ""
+msgstr "Score"
msgid "DevopsReport|Your score"
-msgstr ""
+msgstr "Votre score"
msgid "DevopsReport|Your usage"
-msgstr ""
+msgstr "Votre usage"
msgid "Diagram (%{language})"
-msgstr ""
+msgstr "Diagramme (%{language})"
msgid "Did not delete the source branch."
msgstr ""
msgid "Didn't receive a confirmation email?"
-msgstr ""
+msgstr "Vous n'avez pas reçu de courriel de confirmation ?"
msgid "Didn't receive confirmation instructions?"
-msgstr ""
+msgstr "Vous n'avez pas reçu les instructions de confirmation ?"
msgid "Didn't receive unlock instructions?"
-msgstr ""
+msgstr "Vous n'avez pas reçu les instructions de déverrouillage ?"
msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
-msgstr ""
+msgstr "Les fichiers diff qui dépassent cette limite seront indiqués comme « trop grands » et ne seront pas extensibles."
msgid "Diff limits"
msgstr "Limites du diff"
@@ -13697,52 +13885,52 @@ msgid "Difference between start date and now"
msgstr ""
msgid "DiffsCompareBaseBranch|(HEAD)"
-msgstr ""
+msgstr "(HEAD)"
msgid "DiffsCompareBaseBranch|(base)"
msgstr ""
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ajout"
+msgstr[1] "%d ajouts"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d suppression"
+msgstr[1] "%d suppressions"
msgid "Diffs|Expand all lines"
msgstr ""
msgid "Diffs|Next 20 lines"
-msgstr ""
+msgstr "20 lignes suivantes"
msgid "Diffs|No file name available"
msgstr "Aucun nom de fichier disponible"
msgid "Diffs|Previous 20 lines"
-msgstr ""
+msgstr "20 lignes précédentes"
msgid "Diffs|Show %{unfoldCount} lines"
-msgstr ""
+msgstr "Afficher %{unfoldCount} lignes"
msgid "Diffs|Show all unchanged lines"
-msgstr ""
+msgstr "Afficher toutes les lignes inchangées"
msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Affichage de %{dropdownStart}%{count} fichier modifié%{dropdownEnd}"
+msgstr[1] "Affichage de %{dropdownStart}%{count} fichiers modifiés%{dropdownEnd}"
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Quelque chose s’est mal passé lors de la rapatriement des lignes du diff."
msgid "Diffs|with %{additions} and %{deletions}"
-msgstr ""
+msgstr "avec %{additions} et %{deletions}"
msgid "Direct member"
-msgstr ""
+msgstr "Membre direct"
msgid "Direct members"
msgstr ""
@@ -13763,16 +13951,16 @@ msgid "Disable"
msgstr "Désactiver"
msgid "Disable Two-factor Authentication"
-msgstr ""
+msgstr "Désactiver l'Authentification à deux facteurs"
msgid "Disable What's new"
-msgstr ""
+msgstr "Désactiver les Nouveautés"
msgid "Disable for this project"
msgstr "Désactiver pour ce projet"
msgid "Disable group runners"
-msgstr ""
+msgstr "Désactiver les exécuteurs de groupe"
msgid "Disable two-factor authentication"
msgstr ""
@@ -13787,7 +13975,7 @@ msgid "Disabled mirrors can only be enabled by instance owners. It is recommende
msgstr ""
msgid "Discard"
-msgstr ""
+msgstr "Abandonner"
msgid "Discard all changes"
msgstr "Rejeter tous les changements"
@@ -13808,7 +13996,7 @@ msgid "DiscordService|Discord Notifications"
msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
-msgstr ""
+msgstr "Envoie des notifications sur les événements du projet vers un canal Discord."
msgid "Discover"
msgstr ""
@@ -13820,22 +14008,22 @@ msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Découvrez des projets, des groupes et des extraits de code. Partagez vos projets avec d’autres personnes"
msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
-msgstr ""
+msgstr "Vérifier votre application à la recherche de vulnérabilités susceptibles d'entraîner des accès non autorisés, des fuites de données ou des dénis de services."
msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
msgstr ""
msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
-msgstr ""
+msgstr "GitLab effectuera des tests statiques et dynamiques sur le code de votre application à la recherche de failles connues, puis rapportera celles-ci dans la demande de fusion afin que vous puissiez les corriger avant."
msgid "Discover|Security capabilities, integrated into your development lifecycle"
-msgstr ""
+msgstr "Fonctionnalités de sécurité, intégrées à votre cycle de développement"
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
-msgstr ""
+msgstr "Voir les autres fonctionnalités du %{linkStart}forfait Ultimate%{linkEnd}"
msgid "Discover|Start a free trial"
-msgstr ""
+msgstr "Commencer un essai gratuit"
msgid "Discover|Upgrade now"
msgstr ""
@@ -13863,17 +14051,17 @@ msgstr "Rejeter"
msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Rejeter %d vulnérabilité sélectionnée comme"
+msgstr[1] "Rejeter les %d vulnérabilités sélectionnées comme"
msgid "Dismiss Alert"
-msgstr ""
+msgstr "Rejeter l'Alerte"
msgid "Dismiss merge request promotion"
-msgstr ""
+msgstr "Rejeter la promotion de la demande de fusion"
msgid "Dismiss selected"
-msgstr ""
+msgstr "Rejeter la sélection"
msgid "Dismiss trial promotion"
msgstr "Rejeter l’offre promotionnelle"
@@ -13897,16 +14085,16 @@ msgid "Display"
msgstr ""
msgid "Display alerts from all configured monitoring tools."
-msgstr ""
+msgstr "Affichage des alertes depuis tous les outils de supervision configurés."
msgid "Display milestones"
-msgstr ""
+msgstr "Afficher les jalons"
msgid "Display name"
msgstr ""
msgid "Display progress of child issues"
-msgstr ""
+msgstr "Afficher la progression des tickets enfants"
msgid "Display rendered file"
msgstr ""
@@ -13921,10 +14109,10 @@ msgid "Do not display content for customer experience improvement and offers fro
msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
-msgstr ""
+msgstr "Ne pas forcer les poussées vers des références divergentes. Après la création du miroir, ce paramètre ne peut être modifié que via l'API. %{mirroring_docs_link_start}En savoir plus sur cette option%{link_closing_tag} et %{mirroring_api_docs_link_start}sur l'API.%{link_closing_tag}"
msgid "Do you want to remove this deploy key?"
-msgstr ""
+msgstr "Voulez-vous supprimer cette clé de déploiement ?"
msgid "Dockerfile"
msgstr ""
@@ -13939,13 +14127,25 @@ msgid "Documentation pages URL"
msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
-msgstr ""
+msgstr "Documents réindexés : %{processed_documents} (%{percentage}%%)"
msgid "Domain"
msgstr "Domaine"
msgid "Domain Name"
-msgstr ""
+msgstr "Nom de Domaine"
+
+msgid "Domain Verification"
+msgstr "Vérification de domaine"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "Comment configurer un domaine ?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "Aucun domaine n'est configuré. Créez-en un dans un projet de cette hiérarchie de groupe."
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "Les domaines suivants sont configurés pour les projets de ce groupe. Les utilisateurs dont les adresses de courriel correspondent à un domaine vérifié n'ont pas besoin de confirmer leur compte."
msgid "Don't have a group?"
msgstr ""
@@ -13954,7 +14154,7 @@ msgid "Don't have an account yet?"
msgstr ""
msgid "Don't include description in commit message"
-msgstr ""
+msgstr "Ne pas inclure la description dans le message de commit"
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr ""
@@ -13969,7 +14169,7 @@ msgid "Done"
msgstr "Terminé"
msgid "Dormant users"
-msgstr ""
+msgstr "Utilisateurs inactifs"
msgid "Download"
msgstr "Télécharger"
@@ -13984,13 +14184,13 @@ msgid "Download (%{fileSizeReadable})"
msgstr ""
msgid "Download (%{size})"
-msgstr ""
+msgstr "Télécharger (%{size})"
msgid "Download CSV"
msgstr ""
msgid "Download PDF"
-msgstr ""
+msgstr "Télécharger le PDF"
msgid "Download artifacts"
msgstr ""
@@ -14008,10 +14208,10 @@ msgid "Download image"
msgstr ""
msgid "Download payload"
-msgstr ""
+msgstr "Télécharger la charge utile"
msgid "Download raw data (.csv)"
-msgstr ""
+msgstr "Télécharger les données brutes (.csv)"
msgid "Download source code"
msgstr ""
@@ -14035,37 +14235,37 @@ msgid "Downvotes"
msgstr "Votes négatifs"
msgid "Draft"
-msgstr ""
+msgstr "Brouillon"
msgid "Draft: %{filename}"
-msgstr ""
+msgstr "Brouillon : %{filename}"
msgid "Drag to reorder prioritized labels and change their relative priority."
-msgstr ""
+msgstr "Faites glisser les étiquettes prioritaires pour les classer et modifier leur priorité relative."
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "Faites glisser vos designs ici ou %{linkStart}cliquez pour les téléverser%{linkEnd}."
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
-msgstr ""
+msgstr "Déposez ou %{linkStart}téléversez%{linkEnd} un fichier à joindre"
msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
-msgstr ""
+msgstr "Déposez ou %{linkStart}téléversez%{linkEnd} des fichiers à joindre"
msgid "Drop your designs to start your upload."
-msgstr ""
+msgstr "Déposez vos designs pour démarrer votre téléversement."
msgid "Drop your files to start your upload."
-msgstr ""
+msgstr "Déposez vos fichiers pour commencer le téléversement."
msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
msgstr ""
msgid "DropdownWidget|Assign %{issuableAttribute}"
-msgstr ""
+msgstr "Assigner %{issuableAttribute}"
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "DropdownWidget|Edit %{issuableAttribute}"
msgstr ""
@@ -14074,16 +14274,16 @@ msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuab
msgstr ""
msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
-msgstr ""
+msgstr "%{issuableAttribute} impossible à définir sur ce(tte) %{issuableType}. Veuillez réessayer."
msgid "DropdownWidget|No %{issuableAttribute}"
-msgstr ""
+msgstr "Aucun(e) %{issuableAttribute}"
msgid "DropdownWidget|No %{issuableAttribute} found"
-msgstr ""
+msgstr "%{issuableAttribute} introuvable"
msgid "DropdownWidget|No open %{issuableAttribute} found"
-msgstr ""
+msgstr "Aucun(e) %{issuableAttribute} ouvert(e) trouvé(e)"
msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
msgstr ""
@@ -14098,22 +14298,22 @@ msgid "Due date"
msgstr "Date d’échéance"
msgid "Due to inactivity, the %{project_link} project is scheduled to be deleted on %{b_open}%{deletion_date}%{b_close}. To unschedule the deletion of %{project_link}, perform some activity on it. For example:"
-msgstr ""
+msgstr "Faute d'activité, le projet %{project_link} est planifié pour être supprimé le %{b_open}%{deletion_date}%{b_close}. Pour annuler la planification de la suppression de %{project_link}, effectuez une activité quelconque dessus. Par exemple :"
msgid "Due to inactivity, the %{project_name} (%{project_link}) project is scheduled to be deleted on %{deletion_date}. To unschedule the deletion of %{project_name}, perform some activity on it. For example:"
-msgstr ""
+msgstr "Faute d'activité, le projet %{project_name} (%{project_link}) est planifié pour être supprimé le %{deletion_date}. Pour annuler la planification de la suppression de %{project_name}, effectuez une activité quelconque dessus. Par exemple :"
msgid "Due to inactivity, this project is scheduled to be deleted on %{deletion_date}. %{link_start}Why is this scheduled?%{link_end}"
-msgstr ""
+msgstr "Faute d'activité, ce projet est planifié pour être supprimé le %{deletion_date}. %{link_start}Pourquoi cela est-il planifié ?%{link_end}"
msgid "Duplicate page: %{error_message}"
-msgstr ""
+msgstr "Page dupliquée : %{error_message}"
msgid "Duration"
msgstr ""
msgid "Duration (min)"
-msgstr ""
+msgstr "Durée (min)"
msgid "Duration|%s days"
msgstr ""
@@ -14158,13 +14358,13 @@ msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use
msgstr "Au cours de ce processus, il vous sera demandé les URL de GitLab. Utilisez les URL indiquées ciâ€dessous."
msgid "Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "Test dynamique de la sécurité des applications (DAST)"
msgid "E-mail:"
-msgstr ""
+msgstr "Courriel :"
msgid "Each project can also have an issue tracker and a wiki."
-msgstr ""
+msgstr "Chaque projet peut également avoir un gestionnaire de tickets et un wiki."
msgid "Edit"
msgstr "Éditer"
@@ -14182,13 +14382,13 @@ msgid "Edit Deploy Key"
msgstr ""
msgid "Edit Geo Site"
-msgstr ""
+msgstr "Modifier le Site Geo"
msgid "Edit Group Hook"
-msgstr ""
+msgstr "Modifier le Crochet de Groupe"
msgid "Edit Identity"
-msgstr ""
+msgstr "Modifier l'Identité"
msgid "Edit Label"
msgstr "Modifier l’étiquette"
@@ -14200,22 +14400,22 @@ msgid "Edit Password"
msgstr ""
msgid "Edit Pipeline Schedule"
-msgstr ""
+msgstr "Modifier la Planification de Pipeline"
msgid "Edit Release"
msgstr ""
msgid "Edit Requirement"
-msgstr ""
+msgstr "Modifier l'Exigence"
msgid "Edit Slack integration"
-msgstr ""
+msgstr "Éditer l'intégration de Slack"
msgid "Edit Snippet"
msgstr "Modifier le fragment de code"
msgid "Edit System Hook"
-msgstr ""
+msgstr "Modifier le Crochet Système"
msgid "Edit application"
msgstr "Modifier l’application"
@@ -14230,7 +14430,7 @@ msgid "Edit commit message"
msgstr ""
msgid "Edit deploy freeze"
-msgstr ""
+msgstr "Modifier le gel de déploiement"
msgid "Edit deploy key"
msgstr ""
@@ -14242,16 +14442,16 @@ msgid "Edit environment"
msgstr ""
msgid "Edit epics"
-msgstr ""
+msgstr "Modifier les épopées"
msgid "Edit files in the editor and commit changes here"
msgstr "Modifier les fichiers dans l’éditeur et valider les modifications ici"
msgid "Edit fork in Web IDE"
-msgstr ""
+msgstr "Modifier le fork dans l'EDI Web"
msgid "Edit group application"
-msgstr ""
+msgstr "Modifier l'application de groupe"
msgid "Edit group: %{group_name}"
msgstr "Modifier le groupe : %{group_name}"
@@ -14260,10 +14460,10 @@ msgid "Edit identity for %{user_name}"
msgstr "Modifier l’identité de %{user_name}"
msgid "Edit image description"
-msgstr ""
+msgstr "Modifier la description de l'image"
msgid "Edit in pipeline editor"
-msgstr ""
+msgstr "Modifier dans l'éditeur de pipeline"
msgid "Edit in single-file editor"
msgstr ""
@@ -14275,19 +14475,19 @@ msgid "Edit issues"
msgstr "Modifier les tickets"
msgid "Edit link"
-msgstr ""
+msgstr "Modifier le lien"
msgid "Edit merge requests"
-msgstr ""
+msgstr "Modifier les demandes de fusion"
msgid "Edit public deploy key"
msgstr ""
msgid "Edit sidebar"
-msgstr ""
+msgstr "Modifier la barre latérale"
msgid "Edit table"
-msgstr ""
+msgstr "Modifier le tableau"
msgid "Edit this file only."
msgstr ""
@@ -14299,10 +14499,10 @@ msgid "Edit title and description"
msgstr "Modifier le titre et la description"
msgid "Edit topic: %{topic_name}"
-msgstr ""
+msgstr "Modifier le sujet : %{topic_name}"
msgid "Edit user: %{user_name}"
-msgstr ""
+msgstr "Modification d'utilisateur : %{user_name}"
msgid "Edit video description"
msgstr ""
@@ -14313,8 +14513,11 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr "Modifiez votre recherche et réessayez"
+
msgid "Edit your search filter and try again."
-msgstr ""
+msgstr "Modifiez votre filtre de recherche et réessayez."
msgid "Edit, lint, and visualize your pipeline."
msgstr ""
@@ -14323,16 +14526,16 @@ msgid "Edited"
msgstr "Édité"
msgid "Edited %{timeago}"
-msgstr "Édité il y a %{timeago}"
+msgstr "Modifié %{timeago}"
msgid "Editing"
msgstr ""
msgid "Elapsed time"
-msgstr ""
+msgstr "Temps écoulé"
msgid "Elasticsearch HTTP client timeout value in seconds."
-msgstr ""
+msgstr "Valeur du délai d'expiration du client HTTP Elasticsearch en secondes."
msgid "Elasticsearch indexing restrictions"
msgstr ""
@@ -14344,16 +14547,16 @@ msgid "Elasticsearch migration halted"
msgstr ""
msgid "Elasticsearch reindexing is already in progress"
-msgstr ""
+msgstr "Une réindexation Elasticsearch est déjà en cours"
msgid "Elasticsearch reindexing triggered"
-msgstr ""
+msgstr "Réindexation Elasticsearch déclenchée"
msgid "Elasticsearch reindexing was not started: %{errors}"
-msgstr ""
+msgstr "La réindexation Elasticsearch n'a pas démarré : %{errors}"
msgid "Elasticsearch zero-downtime reindexing"
-msgstr ""
+msgstr "Réindexation Elasticsearch sans temps mort"
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -14377,10 +14580,10 @@ msgid "Email address suffix"
msgstr ""
msgid "Email address to use for Support Desk"
-msgstr ""
+msgstr "Adresse de courriel à utiliser pour le Service d'Assistance"
msgid "Email could not be sent"
-msgstr ""
+msgstr "Le courriel n'a pas pu être envoyé"
msgid "Email display name"
msgstr ""
@@ -14389,7 +14592,7 @@ msgid "Email not verified. Please verify your email in Salesforce."
msgstr ""
msgid "Email notification for unknown sign-ins"
-msgstr ""
+msgstr "Notification par courriel pour les connexions inconnues"
msgid "Email patch"
msgstr "Correctif par courriel"
@@ -14398,31 +14601,31 @@ msgid "Email patches"
msgstr ""
msgid "Email sent"
-msgstr ""
+msgstr "Le courriel a été envoyé"
msgid "Email the pipeline status to a list of recipients."
-msgstr ""
+msgstr "Envoyer l'état du pipeline par courriel à une liste de destinataires."
msgid "Email updates (optional)"
msgstr ""
msgid "Email:"
-msgstr ""
+msgstr "Courriel :"
msgid "Email: %{email}"
-msgstr ""
+msgstr "Courriel : %{email}"
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "Le fil de discussion auquel vous répondez n'existe plus, peut-être a-t-il été supprimé ? Si vous pensez que c'est une erreur, contactez un membre du staff."
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
msgstr ""
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
-msgstr ""
+msgstr "Nous n'avons pas pu déterminer à quoi le courriel répond. Veuillez créer votre commentaire via l'interface Web."
msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
msgstr ""
@@ -14431,7 +14634,7 @@ msgid "EmailError|We couldn't find the project. Please check if there's any typo
msgstr ""
msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
-msgstr ""
+msgstr "Nous n'avons pas pu traiter votre courriel car il est trop volulineux. Veuillez créer votre ticket ou votre commentaire via l'interface Web."
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr ""
@@ -14440,22 +14643,19 @@ msgid "EmailError|Your account has been blocked. If you believe this is in error
msgstr ""
msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
-msgstr ""
+msgstr "%{emails} sera informé de votre commentaire."
msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
-msgstr ""
+msgstr "%{emails}, %{andMore} seront informés de votre commentaire."
msgid "EmailParticipantsWarning|and %{moreCount} more"
-msgstr ""
+msgstr "et %{moreCount} de plus"
msgid "Emails"
msgstr "Courriels"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
-msgstr ""
+msgstr "Les courriels envoyés à %{email} sont également pris en charge."
msgid "EmailsOnPushService|Disable code diffs"
msgstr ""
@@ -14470,16 +14670,16 @@ msgid "EmailsOnPushService|Emails on push"
msgstr ""
msgid "EmailsOnPushService|Emails separated by whitespace."
-msgstr ""
+msgstr "Adresses de courriel séparées par des espaces."
msgid "EmailsOnPushService|Send from committer"
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 ""
+msgstr "Envoyer les notifications depuis l'adresse de courriel du contributeur si le domaine correspond à celui utilisé par votre instance GitLab (tels que %{domains})."
msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
-msgstr ""
+msgstr "tanuki@exemple.com gitlab@exemple.com"
msgid "Embed"
msgstr "Embarquer"
@@ -14491,7 +14691,7 @@ msgid "Enable"
msgstr "Activer"
msgid "Enable Akismet"
-msgstr ""
+msgstr "Activer Akismet"
msgid "Enable Amazon EKS integration"
msgstr ""
@@ -14500,10 +14700,10 @@ msgid "Enable Auto DevOps"
msgstr "Activer Auto DevOps"
msgid "Enable GitLab Error Tracking"
-msgstr ""
+msgstr "Activer le Suivi d'Erreurs de GitLab"
msgid "Enable GitLab Prometheus metrics endpoint"
-msgstr ""
+msgstr "Activer le point d'arrivée des métriques Prometheus de GitLab"
msgid "Enable Gitpod"
msgstr ""
@@ -14515,62 +14715,65 @@ msgid "Enable Invisible Captcha during sign up"
msgstr ""
msgid "Enable Kroki"
-msgstr ""
+msgstr "Activer Kroki"
msgid "Enable Mailgun event receiver"
-msgstr ""
+msgstr "Activer le récepteur d'événements Mailgun"
msgid "Enable PlantUML"
msgstr ""
msgid "Enable SSL verification"
-msgstr ""
+msgstr "Activer la vérification SSL"
msgid "Enable Sentry error tracking"
msgstr ""
msgid "Enable Snowplow tracking"
-msgstr ""
+msgstr "Activer le suivi avec Snowplow"
msgid "Enable Spam Check via external API endpoint"
msgstr ""
msgid "Enable What's new: All tiers"
-msgstr ""
+msgstr "Activer les Nouveautés : Toutes les éditions"
msgid "Enable What's new: Current tier only"
-msgstr ""
+msgstr "Activer les Nouveautés : Édition actuelle seulement"
msgid "Enable access to the performance bar for non-administrators in a given group."
-msgstr ""
+msgstr "Activer l'accès à la barre de performance pour les non-administrateurs d'un groupe donné."
msgid "Enable admin mode"
msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "Activer et désactiver le Service d'Assistance. Une configuration supplémentaire peut se révéler nécessaire. %{link_start}En savoir plus%{link_end}."
msgid "Enable authenticated API request rate limit"
-msgstr ""
+msgstr "Activer la limite de fréquence des requêtes d'API authentifiées"
msgid "Enable authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "Activer la limite de fréquence des requêtes Git LFS authentifiées"
msgid "Enable authenticated web request rate limit"
msgstr ""
msgid "Enable authentication"
-msgstr ""
+msgstr "Activer l'authentification"
msgid "Enable automatic repository housekeeping"
-msgstr ""
+msgstr "Activer la maintenance automatique du dépôt"
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
-msgstr ""
+msgstr "Activer les stratégies d'expiration et de conservation des conteneurs pour les projets créés avec des versions de GitLab antérieures à la 12.7."
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14584,7 +14787,7 @@ msgid "Enable for this project"
msgstr "Activer pour ce projet"
msgid "Enable group runners"
-msgstr ""
+msgstr "Activer les exécuteurs de groupe"
msgid "Enable header and footer in emails"
msgstr ""
@@ -14593,22 +14796,22 @@ msgid "Enable in-product marketing emails"
msgstr ""
msgid "Enable incident management inbound alert limit"
-msgstr ""
+msgstr "Activer la limite d'alerte entrante de la gestion des incidents"
msgid "Enable integration"
-msgstr ""
+msgstr "Activer l'intégration"
msgid "Enable logs collection"
msgstr ""
msgid "Enable maintenance mode"
-msgstr ""
+msgstr "Activer le mode maintenance"
msgid "Enable multipart emails"
-msgstr ""
+msgstr "Activer les courriels 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 ""
+msgstr "Activer uniquement pour les applications confidentielles utilisées exclusivement par un serveur backend de confiance qui peut stocker en toute sécurité le secret du client. Ne pas activer pour les applications mobiles natives, à page unique ou autres applications JavaScript car elles ne peuvent pas garder le secret du client confidentiel."
msgid "Enable or disable version check and Service Ping."
msgstr ""
@@ -14617,13 +14820,13 @@ msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
-msgstr ""
+msgstr "Activer reCAPTCHA"
msgid "Enable reCAPTCHA for login."
msgstr ""
msgid "Enable repository checks"
-msgstr ""
+msgstr "Activer les vérifications de dépôt"
msgid "Enable security training"
msgstr ""
@@ -14632,19 +14835,19 @@ msgid "Enable security training to help your developers learn how to fix vulnera
msgstr ""
msgid "Enable shared runners for all projects and subgroups in this group."
-msgstr ""
+msgstr "Activer les exécuteurs partagés pour tous les projets et sous-groupes de ce groupe."
msgid "Enable shared runners for this group"
-msgstr ""
+msgstr "Activer les exécuteurs partagés pour ce groupe"
msgid "Enable shared runners for this project"
-msgstr ""
+msgstr "Activer les exécuteurs partagés pour ce projet"
msgid "Enable two-factor authentication"
msgstr ""
msgid "Enable unauthenticated API request rate limit"
-msgstr ""
+msgstr "Activer la limite de fréquence des requêtes d'API non authentifiées"
msgid "Enable unauthenticated web request rate limit"
msgstr ""
@@ -14653,25 +14856,25 @@ msgid "Enable user deactivation emails"
msgstr ""
msgid "Enable version check"
-msgstr ""
+msgstr "Activer le contrôle de version"
msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
-msgstr ""
+msgstr "%{stepStart}Étape 1%{stepEnd}. Assurez-vous d'avoir configuré Kubernetes et de disposer d'un domaine de base pour votre %{linkStart}grappe de serveurs%{linkEnd}."
msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
-msgstr ""
+msgstr "%{stepStart}Étape 2%{stepEnd}. Copiez l'extrait suivant :"
msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
-msgstr ""
+msgstr "%{stepStart}Étape 3%{stepEnd}. Ajoutez-le au fichier %{linkStart}gitlab-ci.yml%{linkEnd} du projet."
msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
-msgstr ""
+msgstr "%{stepStart}Étape 4 (facultative)%{stepEnd}. Activez les Revues Visuelles en suivant les %{linkStart}instructions de configuration%{linkEnd}."
msgid "EnableReviewApp|Close"
-msgstr ""
+msgstr "Fermer"
msgid "EnableReviewApp|Copy snippet text"
-msgstr ""
+msgstr "Copier l'extrait de texte"
msgid "Enabled"
msgstr "activé"
@@ -14686,7 +14889,7 @@ msgid "End Time"
msgstr ""
msgid "Ends"
-msgstr ""
+msgstr "Se termine"
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
@@ -14704,7 +14907,7 @@ msgid "Enforce two-factor authentication for all user sign-ins."
msgstr ""
msgid "Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "Améliorez la sécurité en stockant les clés de compte de service dans des gestionnaires de secrets - apprenez-en plus sur la %{docLinkStart}gestion de secrets avec GitLab%{docLinkEnd}"
msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
msgstr ""
@@ -14713,7 +14916,7 @@ msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd}
msgstr ""
msgid "Enter %{weights_link_start}weights%{weights_link_end} for storages for new repositories. Configured storages appear below."
-msgstr ""
+msgstr "Entrez les %{weights_link_start}poids%{weights_link_end} pour les stockages des nouveaux dépôts. Les stockages configurés apparaissent ci-dessous."
msgid "Enter 2FA for Admin Mode"
msgstr ""
@@ -14728,10 +14931,10 @@ msgid "Enter an integer number between 0 and 100"
msgstr ""
msgid "Enter any color or choose one of the suggested colors below."
-msgstr ""
+msgstr "Entrez n'importe quelle couleur ou choisissez-en une parmi celles suggérées ci-dessous."
msgid "Enter any color."
-msgstr ""
+msgstr "Entrez une couleur."
msgid "Enter at least three characters to search"
msgstr ""
@@ -14743,7 +14946,7 @@ msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
msgid "Enter license key"
-msgstr ""
+msgstr "Entrez la clé de licence"
msgid "Enter merge request URLs"
msgstr ""
@@ -14755,7 +14958,7 @@ msgid "Enter number of issues"
msgstr ""
msgid "Enter one or more user ID separated by commas"
-msgstr ""
+msgstr "Entrez un ou plusieurs ID utilisateur séparés par des virgules"
msgid "Enter the %{name} description"
msgstr ""
@@ -14767,28 +14970,28 @@ msgid "Enter the code from the two-factor app on your mobile device. If you've l
msgstr ""
msgid "Enter the following to confirm:"
-msgstr ""
+msgstr "Entrez ce qui suit pour confirmer :"
msgid "Enter the name of your application, and we'll return a unique %{type}."
msgstr ""
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
-msgstr ""
+msgstr "Entrez le nombre de secondes ou toute autre expression lisible telle que « 1 hour ». Ce délai d'expiration a la priorité sur les délais plus courts définis pour le projet."
msgid "Enter the password for password-protected Elasticsearch servers."
-msgstr ""
+msgstr "Entrez le mot de passe pour les serveurs Elasticsearch protégés par mot de passe."
msgid "Enter the username for password-protected Elasticsearch servers."
-msgstr ""
+msgstr "Entrez le nom d'utilisateur pour les serveurs Elasticsearch protégés par mot de passe."
msgid "Enter your Packagist server. Defaults to https://packagist.org."
-msgstr ""
+msgstr "Entrez votre serveur Packagist. https://packagist.org par défaut."
msgid "Enter your Packagist token."
-msgstr ""
+msgstr "Entrez votre jeton Packagist."
msgid "Enter your Packagist username."
-msgstr ""
+msgstr "Entrez votre nom d'utilisateur Packagist."
msgid "Enter your password to approve"
msgstr ""
@@ -14797,22 +15000,22 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgstr "Environnement"
msgid "Environment is required for Stages::MetricEndpointInserter"
-msgstr ""
+msgstr "Un environnement est requis pour Stages::MetricEndpointInserter"
msgid "Environment is required for Stages::VariableEndpointInserter"
-msgstr ""
+msgstr "Un environment est requis pour Stages::VariableEndpointInserter"
msgid "Environment scope"
-msgstr ""
+msgstr "Portée de l'environnement"
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
-msgstr ""
+msgstr "Les variables d'environnement sont configurées par votre administrateur pour être %{link_start}protégées%{link_end} par défaut."
msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
-msgstr ""
+msgstr "Les variables d'environnement de cette instance GitLab sont configurées pour être %{link_start}protégées%{link_end} par défaut."
msgid "Environment:"
msgstr ""
@@ -14824,7 +15027,7 @@ msgid "EnvironmentDashboard|Created through the Deployment API"
msgstr ""
msgid "EnvironmentDashboard|You are looking at the last updated environment"
-msgstr ""
+msgstr "Vous consultez le dernier environnement actualisé"
msgid "Environments"
msgstr "Environnements"
@@ -14833,13 +15036,13 @@ msgid "Environments Dashboard"
msgstr ""
msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
-msgstr ""
+msgstr "Les environnements vous permettent de suivre les déploiements de votre application. %{linkStart}Plus d'informations%{linkEnd}."
msgid "Environments in %{name}"
msgstr ""
msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
-msgstr ""
+msgstr "%{severity} • %{title} %{text}. %{linkStart}Voir les Détails%{linkEnd} · %{startedAt} "
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -14863,13 +15066,13 @@ msgid "EnvironmentsDashboard|The environments dashboard provides a summary of ea
msgstr ""
msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Ce tableau de bord affiche 3 environnements par projet, et est lié au Tableau de bord des Opérations. Lorsque vous ajoutez ou supprimez un projet d'un tableau de bord, GitLab l'ajoute ou le supprime de l’autre. %{linkStart}Plus d'informations%{linkEnd}"
msgid "Environments|An error occurred while canceling the auto stop, please try again"
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’annulation de l’arrêt automatique, veuillez réessayer"
msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la suppression de l’environnement. Vérifiez si l’environnement est arrêté ; si ce n'est pas le cas, arrêtez-le et réessayez."
msgid "Environments|An error occurred while fetching the environments."
msgstr "Une erreur s’est produite lors de la récupération des environnements."
@@ -14890,7 +15093,7 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
msgid "Environments|Auto stop"
-msgstr ""
+msgstr "Arrêt auto"
msgid "Environments|Auto stops %{autoStopAt}"
msgstr ""
@@ -14899,16 +15102,16 @@ msgid "Environments|Commit"
msgstr "Commit"
msgid "Environments|Delete"
-msgstr ""
+msgstr "Supprimer"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "Supprimer « %{environmentName} » ?"
msgid "Environments|Delete environment"
-msgstr ""
+msgstr "Supprimer l'environnement"
msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
-msgstr ""
+msgstr "La suppression de l'environnement '%{environmentName}' ne peut pas être annulée. Voulez-vous le supprimer quand même ?"
msgid "Environments|Deploy to..."
msgstr "Déployer vers…"
@@ -14917,10 +15120,13 @@ msgid "Environments|Deployment"
msgstr "Déploiement"
msgid "Environments|Deployment %{status}"
-msgstr ""
+msgstr "Déploiement %{status}"
+
+msgid "Environments|Edit your search and try again"
+msgstr "Modifiez votre recherche et réessayez"
msgid "Environments|Enable review app"
-msgstr ""
+msgstr "Activer Review App"
msgid "Environments|Environment"
msgstr "Environnement"
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr "Aucun déploiement pour le moment"
+msgid "Environments|No results found"
+msgstr "Aucun résultat trouvé"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Notez que cette action arrêtera l’environnement, mais n’aura %{emphasisStart}aucun%{emphasisEnd} effet sur les déploiements existants en raison de l’absence de directive « arrêter l’action de l’environnement » dans le fichier de configuration %{ciConfigLinkEnd}.gitlab-ci.yml%{ciConfigLinkStart}."
@@ -14962,7 +15171,7 @@ msgid "Environments|Open live environment"
msgstr "Ouvrir l’environnement en cours"
msgid "Environments|Re-deploy environment"
-msgstr ""
+msgstr "Redéployer l'environnement"
msgid "Environments|Re-deploy environment %{name}?"
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr "Restaurer l’environnement"
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr "Rechercher par nom d'environnement"
+
msgid "Environments|Show all"
msgstr "Tout afficher"
@@ -14986,22 +15198,22 @@ msgid "Environments|Stop environment"
msgstr "Arrêter l’environnement"
msgid "Environments|Stopping %{environmentName}"
-msgstr ""
+msgstr "Arrêt de %{environmentName}"
msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
-msgstr ""
+msgstr "Il n'y a pas encore de déploiement pour cet environnement. %{linkStart}En savoir plus sur la mise en place des déploiements.%{linkEnd}"
msgid "Environments|This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?"
-msgstr ""
+msgstr "Cette action va %{docsStart}réessayer le dernier déploiement%{docsEnd} avec le commit %{commitId}, pour cet environnement. Êtes-vous sûr de vouloir continuer ?"
msgid "Environments|This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?"
-msgstr ""
+msgstr "Cette action va %{docsStart}restaurer cet environnement%{docsEnd} en revenant à un déploiement précédemment réussi pour le commit %{commitId}. Êtes-vous sûr de vouloir continuer ?"
msgid "Environments|Upcoming"
-msgstr ""
+msgstr "À venir"
msgid "Environments|Upcoming deployment"
-msgstr ""
+msgstr "Déploiement à venir"
msgid "Environments|Updated"
msgstr "Mis à jour"
@@ -15013,37 +15225,37 @@ msgid "Environments|You don't have any stopped environments."
msgstr ""
msgid "Environments|by %{avatar}"
-msgstr ""
+msgstr "par %{avatar}"
msgid "Environments|protected"
msgstr "protégé"
msgid "Environment|Auto stop %{time}"
-msgstr ""
+msgstr "Arrêt automatique %{time}"
msgid "Environment|Deployment tier"
-msgstr ""
+msgstr "Type de déploiement"
msgid "Epic"
msgstr "Épopée"
msgid "Epic Boards"
-msgstr ""
+msgstr "Tableaux des Épopées"
msgid "Epic actions"
-msgstr ""
+msgstr "Actions des épopées"
msgid "Epic cannot be found."
-msgstr ""
+msgstr "L'épopée est introuvable."
msgid "Epic details"
-msgstr ""
+msgstr "Détails de l'épopée"
msgid "Epic events"
msgstr ""
msgid "Epic not found for given params"
-msgstr ""
+msgstr "Épopée introuvable pour les paramètres donnés"
msgid "Epics"
msgstr "Épopées"
@@ -15055,43 +15267,43 @@ msgid "Epics let you manage your portfolio of projects more efficiently and with
msgstr "Les épopées vous permettent de gérer votre portefeuille de projets plus efficacement et avec moins d’efforts"
msgid "Epics, issues, and merge requests"
-msgstr ""
+msgstr "Épopées, tickets et demandes de fusion"
msgid "Epics|%{startDate} – %{dueDate}"
-msgstr ""
+msgstr "%{startDate} – %{dueDate}"
msgid "Epics|%{startDate} – No due date"
-msgstr ""
+msgstr "%{startDate} – Pas de date d'échéance"
msgid "Epics|Add a new epic"
-msgstr ""
+msgstr "Ajouter une nouvelle épopée"
msgid "Epics|Add an existing epic"
-msgstr ""
+msgstr "Ajouter une épopée existante"
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer %{bStart}%{targetIssueTitle}%{bEnd} de %{bStart}%{parentEpicTitle}%{bEnd} ?"
msgid "Epics|Assign Epic"
-msgstr ""
+msgstr "Assigner une Épopée"
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr "Laisser vide pour hériter des dates du jalon"
msgid "Epics|No start date – %{dueDate}"
-msgstr ""
+msgstr "Pas de date de début – %{dueDate}"
msgid "Epics|Remove epic"
msgstr ""
msgid "Epics|Remove issue"
-msgstr ""
+msgstr "Supprimer le ticket"
msgid "Epics|Search epics"
-msgstr ""
+msgstr "Rechercher des épopées"
msgid "Epics|Select epic"
-msgstr ""
+msgstr "Sélectionner une épopée"
msgid "Epics|Show more"
msgstr ""
@@ -15103,19 +15315,19 @@ msgid "Epics|Something went wrong while creating child epics."
msgstr ""
msgid "Epics|Something went wrong while creating issue."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du ticket."
msgid "Epics|Something went wrong while fetching child epics."
msgstr ""
msgid "Epics|Something went wrong while fetching epics list."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la liste des épopées."
msgid "Epics|Something went wrong while fetching group epics."
msgstr ""
msgid "Epics|Something went wrong while moving item."
-msgstr ""
+msgstr "Une erreur s'est produite lors du déplacement de l'élément."
msgid "Epics|Something went wrong while ordering item."
msgstr ""
@@ -15124,19 +15336,19 @@ msgid "Epics|Something went wrong while removing issue from epic."
msgstr ""
msgid "Epics|Something went wrong while updating epics."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des épopées."
msgid "Epics|The color for the epic when it's visualized, such as on roadmap timeline bars."
-msgstr ""
+msgstr "La couleur de l'épopée lorsqu'elle est visualisée, par exemple sur les barres chronologiques de la feuille de route."
msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
-msgstr ""
+msgstr "Cette épopée et toute épopée enfant qu'elle contiendrait sont confidentielles et ne devraient être visibles que par les membres de l’équipe ayant au moins un accès à Rapporteur."
msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
msgstr ""
msgid "Epics|Unable to save epic. Please try again"
-msgstr ""
+msgstr "Impossible d'enregistrer l'épopée. Veuillez réessayer"
msgid "Erased"
msgstr ""
@@ -15154,31 +15366,31 @@ msgid "Error creating epic"
msgstr "Erreur lors de la création de l’épopée"
msgid "Error creating label."
-msgstr ""
+msgstr "Erreur lors de la création de l'étiquette."
msgid "Error creating new directory. Please try again."
-msgstr ""
+msgstr "Erreur lors de la création du nouveau répertoire. Veuillez réessayer."
msgid "Error creating new iteration"
msgstr ""
msgid "Error creating repository for snippet with id %{snippet_id}"
-msgstr ""
+msgstr "Erreur lors de la création du dépôt pour l'extrait de code dont l'id est %{snippet_id}"
msgid "Error creating the snippet"
-msgstr ""
+msgstr "Erreur lors de la création de l'extrait de code"
msgid "Error creating vulnerability finding: %{errors}"
-msgstr ""
+msgstr "Erreur lors de la création de la découverte de vulnérabilité : %{errors}"
msgid "Error deleting project. Check logs for error details."
msgstr ""
msgid "Error fetching branches"
-msgstr ""
+msgstr "Erreur lors de la récupération des branches"
msgid "Error fetching burnup chart data"
-msgstr ""
+msgstr "Erreur lors de la récupération des données du graphique d'avancement"
msgid "Error fetching diverging counts for branches. Please try again."
msgstr ""
@@ -15193,7 +15405,7 @@ msgid "Error fetching network graph."
msgstr "Erreur lors de la récupération du graphique du réseau."
msgid "Error fetching payload data."
-msgstr ""
+msgstr "Erreur lors de la récupération des données de la charge utile."
msgid "Error fetching refs"
msgstr "Erreur lors de la récupération des refs"
@@ -15214,10 +15426,10 @@ msgid "Error loading file viewer."
msgstr ""
msgid "Error loading issues"
-msgstr ""
+msgstr "Erreur lors du chargement des tickets"
msgid "Error loading iterations"
-msgstr ""
+msgstr "Erreur lors du chargement des itérations"
msgid "Error loading last commit."
msgstr "Erreur lors du chargement du dernier commit."
@@ -15250,13 +15462,13 @@ msgid "Error occurred when saving assignees"
msgstr ""
msgid "Error occurred when saving reviewers"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'enregistrement des relecteurs"
msgid "Error occurred while updating the %{issuableType} status"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de l'état de %{issuableType}"
msgid "Error occurred while updating the issue status"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de l'état du ticket"
msgid "Error occurred. A blocked user cannot be deactivated"
msgstr ""
@@ -15274,7 +15486,7 @@ msgid "Error occurred. User was not confirmed"
msgstr ""
msgid "Error occurred. User was not unbanned"
-msgstr ""
+msgstr "Une erreur s'est produite. L'utilisateur n'a pas été gracié"
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -15283,10 +15495,10 @@ msgid "Error occurred. User was not unlocked"
msgstr ""
msgid "Error parsing CSV file. Please make sure it has"
-msgstr ""
+msgstr "Erreur lors de l'analyse du fichier CSV. Veuillez vous assurer qu'il a"
msgid "Error promoting the note to timeline event: %{error}"
-msgstr ""
+msgstr "Erreur lors de la promotion de la note en événement de chronologie : %{error}"
msgid "Error rendering Markdown preview"
msgstr ""
@@ -15298,7 +15510,7 @@ msgid "Error setting up editor. Please try again."
msgstr ""
msgid "Error tracking"
-msgstr ""
+msgstr "Suivi des erreurs"
msgid "Error updating %{issuableType}"
msgstr ""
@@ -15310,13 +15522,13 @@ msgid "Error updating status of to-do item."
msgstr ""
msgid "Error updating the snippet"
-msgstr ""
+msgstr "Erreur lors de la mise à jour de l'extrait de code"
msgid "Error uploading file"
msgstr ""
msgid "Error uploading file. Please try again."
-msgstr ""
+msgstr "Erreur lors du téléversement du fichier. Veuillez réessayer."
msgid "Error uploading file: %{stripped}"
msgstr ""
@@ -15331,37 +15543,37 @@ msgid "Error with Akismet. Please check the logs for more info."
msgstr ""
msgid "Error: %{error_message}"
-msgstr ""
+msgstr "Erreur : %{error_message}"
msgid "Error: %{error}"
-msgstr ""
+msgstr "Erreur : %{error}"
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
msgid "Error: No AWS credentials were supplied"
-msgstr ""
+msgstr "Erreur : Aucun identifiant AWS n'a été fourni"
msgid "Error: No AWS provision role found for user"
msgstr ""
msgid "Error: Unable to create deploy freeze"
-msgstr ""
+msgstr "Erreur : Impossible de créer le gel de déploiement"
msgid "Error: Unable to delete deploy freeze"
-msgstr ""
+msgstr "Erreur : Impossible de supprimer le gel de déploiement"
msgid "Error: Unable to find AWS role for current user"
-msgstr ""
+msgstr "Erreur: Impossible de trouver le rôle AWS pour l'utilisateur actuel"
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "Le jeton d'accès est %{token_in_code_tag}"
msgid "ErrorTracking|Active"
msgstr ""
msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
-msgstr ""
+msgstr "Après l'ajout de votre Jeton d'Authentification, sélectionnez le bouton Connecter pour charger les projets."
msgid "ErrorTracking|Auth Token"
msgstr ""
@@ -15370,16 +15582,16 @@ msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and a
msgstr ""
msgid "ErrorTracking|Connection failed. Check Auth Token and try again."
-msgstr ""
+msgstr "La connexion a échoué. Vérifiez le Jeton d'Authentification et réessayez."
msgid "ErrorTracking|Enable error tracking"
-msgstr ""
+msgstr "Activer le suivi des erreurs"
msgid "ErrorTracking|Error tracking backend"
msgstr ""
msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
-msgstr ""
+msgstr "Si vous auto-hébergez Sentry, entrez l'URL complète de votre instance Sentry. Si vous utilisez la solution d'hébergement de Sentry, entrez https://sentry.io"
msgid "ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a %{settingsLinkStart}Sentry API URL and Auth Token%{settingsLinkEnd} on your project settings page. However, error tracking is not ready for production use and cannot be enabled on GitLab.com."
msgstr ""
@@ -15394,7 +15606,7 @@ msgid "ErrorTracking|Select project"
msgstr ""
msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
-msgstr ""
+msgstr "Pour activer la sélection de projet, entrez un Jeton d'Authentification valide."
msgid "ErrorTracking|View project settings"
msgstr ""
@@ -15403,121 +15615,121 @@ msgid "Errors"
msgstr ""
msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
-msgstr ""
+msgstr "Erreurs trouvées sur la ligne %{line_number} : %{error_lines}. Veuillez vérifier si ces lignes ont un titre d'exigence."
msgid "Escalate this incident"
-msgstr ""
+msgstr "Escalader cet incident"
msgid "Escalation Policies"
-msgstr ""
+msgstr "Politiques d'Escalade"
msgid "Escalation policies"
-msgstr ""
+msgstr "Politiques d'escalade"
msgid "Escalation policies may not have more than %{rule_count} rules"
-msgstr ""
+msgstr "Les politiques d'escalade ne peuvent pas avoir plus de %{rule_count} règles"
msgid "Escalation policies must have at least one rule"
-msgstr ""
+msgstr "Les politiques d'escalade doivent contenir au moins une règle"
msgid "Escalation policy"
-msgstr ""
+msgstr "Politique d'escalade"
msgid "Escalation policy:"
-msgstr ""
+msgstr "Politique d'escalade :"
msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
-msgstr ""
+msgstr "%{clockIcon} SI l'alerte n'est pas %{alertStatus} sur %{minutes}"
msgid "EscalationPolicies|%{notificationIcon} THEN %{doAction} %{forScheduleOrUser}"
-msgstr ""
+msgstr "%{notificationIcon} PUIS %{doAction} %{forScheduleOrUser}"
msgid "EscalationPolicies|+ Add an additional rule"
-msgstr ""
+msgstr "+ Ajouter une règle supplémentaire"
msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
msgstr ""
msgid "EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first."
-msgstr ""
+msgstr "Un calendrier est indispensable à l'ajout d'une politique d'escalade. Veuillez commencer par créer un calendrier d'astreintes."
msgid "EscalationPolicies|A user is required for adding an escalation policy."
-msgstr ""
+msgstr "Un utilisateur est requis pour ajouter une politique d'escalade."
msgid "EscalationPolicies|Add an escalation policy"
-msgstr ""
+msgstr "Ajouter une politique d'escalade"
msgid "EscalationPolicies|Add escalation policy"
-msgstr ""
+msgstr "Ajouter une politique d'escalade"
msgid "EscalationPolicies|Add policy"
msgstr ""
msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer la politique d'escalade « %{escalationPolicy} » ? Cette action ne peut pas être annulée."
msgid "EscalationPolicies|Create an escalation policy in GitLab"
-msgstr ""
+msgstr "Créer une politique d'escalade dans GitLab"
msgid "EscalationPolicies|Delete escalation policy"
-msgstr ""
+msgstr "Supprimer la politique d'escalade"
msgid "EscalationPolicies|Edit escalation policy"
-msgstr ""
+msgstr "Modifier la politique d'escalade"
msgid "EscalationPolicies|Email on-call user in schedule"
msgstr ""
msgid "EscalationPolicies|Email user"
-msgstr ""
+msgstr "Envoyer un courriel à un utilisateur"
msgid "EscalationPolicies|Escalation policies"
-msgstr ""
+msgstr "Politiques d'escalade"
msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
-msgstr ""
+msgstr "Politique d'escalade %{obstacle} dans le projet %{project}"
msgid "EscalationPolicies|Escalation rules"
-msgstr ""
+msgstr "Règles d'escalade"
msgid "EscalationPolicies|Failed to load oncall-schedules"
-msgstr ""
+msgstr "Échec du chargement des calendriers d'astreintes"
msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
-msgstr ""
+msgstr "SI l'alerte n'est pas %{alertStatus} dans %{minutes} minutes"
msgid "EscalationPolicies|Maximum of 10 rules has been reached."
-msgstr ""
+msgstr "Le maximum de 10 règles a été atteint."
msgid "EscalationPolicies|Minutes must be between 0 and 1440."
-msgstr ""
+msgstr "Les minutes doivent être comprises entre 0 et 1440."
msgid "EscalationPolicies|Remove escalation rule"
-msgstr ""
+msgstr "Supprimer la règle d'escalade"
msgid "EscalationPolicies|Search for user"
-msgstr ""
+msgstr "Rechercher un utilisateur"
msgid "EscalationPolicies|Select schedule"
-msgstr ""
+msgstr "Sélectionner un calendrier"
msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
-msgstr ""
+msgstr "Configurez les politiques d'escalades pour définir qui est bipé, et quand, dans le cas où les premiers utilisateurs bipés ne répondraient pas."
msgid "EscalationPolicies|THEN %{doAction} %{scheduleOrUser}"
-msgstr ""
+msgstr "ALORS %{doAction} %{scheduleOrUser}"
msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
-msgstr ""
+msgstr "La politique d'escalade n'a pas pu être supprimée. Veuillez réessayer."
msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
-msgstr ""
+msgstr "La politique d'escalade n'a pas pu être mise à jour. Veuillez réessayer"
msgid "EscalationPolicies|This policy has no escalation rules."
-msgstr ""
+msgstr "Cette politique n’a aucune règle d’escalade."
msgid "EscalationPolicies|mins"
-msgstr ""
+msgstr "min"
msgid "Estimate"
msgstr ""
@@ -15526,7 +15738,7 @@ msgid "Estimated"
msgstr "Estimé"
msgid "Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
-msgstr ""
+msgstr "Même si vous atteignez le nombre de sièges dans votre abonnement, vous pouvez continuer à ajouter des utilisateurs, et GitLab vous facturera le surplus."
msgid "EventFilterBy|Filter by all"
msgstr "Tout filtrer"
@@ -15535,7 +15747,7 @@ msgid "EventFilterBy|Filter by comments"
msgstr "Filtrer par commentaires"
msgid "EventFilterBy|Filter by designs"
-msgstr ""
+msgstr "Filtrer par design"
msgid "EventFilterBy|Filter by epic events"
msgstr ""
@@ -15553,7 +15765,7 @@ msgid "EventFilterBy|Filter by team"
msgstr "Filtrer par équipe"
msgid "EventFilterBy|Filter by wiki"
-msgstr ""
+msgstr "Filtrer par wiki"
msgid "Events"
msgstr ""
@@ -15565,13 +15777,13 @@ msgid "Every %{action} attempt has failed: %{job_error_message}. Please try agai
msgstr ""
msgid "Every 3 months"
-msgstr ""
+msgstr "Tous les 3 mois"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every 6 months"
-msgstr ""
+msgstr "Tous les 6 mois"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
msgstr ""
@@ -15580,10 +15792,10 @@ msgid "Every day"
msgstr ""
msgid "Every day (at %{time})"
-msgstr ""
+msgstr "Tous les jours (à %{time})"
msgid "Every day at %{time} %{timezone}"
-msgstr ""
+msgstr "Tous les jours à %{time} %{timezone}"
msgid "Every month"
msgstr ""
@@ -15602,8 +15814,8 @@ msgstr ""
msgid "Every week"
msgid_plural "Every %d weeks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Toutes les semaines"
+msgstr[1] "Toutes les %d semaines"
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -15621,7 +15833,7 @@ msgid "Everyone With Access"
msgstr ""
msgid "Everyone can access the wiki."
-msgstr ""
+msgstr "Tout le monde peut accéder au wiki."
msgid "Everyone can contribute"
msgstr "Tout le monde peut contribuer"
@@ -15648,7 +15860,7 @@ msgid "Everything you need to create a GitLab Pages site using Middleman"
msgstr ""
msgid "Everything you need to create a GitLab Pages site using Pelican"
-msgstr ""
+msgstr "Tout ce dont vous avez besoin pour créer un site GitLab Pages avec Pelican"
msgid "Everything you need to create a GitLab Pages site using plain HTML"
msgstr ""
@@ -15669,10 +15881,10 @@ msgid "Except policy:"
msgstr ""
msgid "Exceptions"
-msgstr ""
+msgstr "Exceptions"
msgid "Excluding merge commits. Limited to %{limit} commits."
-msgstr ""
+msgstr "Commits de fusion exclus. Limités à %{limit} commits."
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
@@ -15681,16 +15893,16 @@ msgid "Execution time"
msgstr ""
msgid "Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "Nom de branche, étiquette ou SHA de commit existant"
msgid "Existing projects may be moved into a group"
-msgstr ""
+msgstr "Les projets existants peuvent être déplacés dans un groupe"
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
-msgstr ""
+msgstr "Les projets existants pourront utiliser des stratégies d'expiration. Évitez d'activer cette option si un Registre de Conteneurs externe est utilisé car cela impacte les performances quand il y a de nombreuses images sur un même projet."
msgid "Existing sign in methods may be removed"
-msgstr ""
+msgstr "Les méthodes de connexion existantes peuvent être supprimées"
msgid "Exit."
msgstr ""
@@ -15702,10 +15914,10 @@ msgid "Expand all"
msgstr "Tout étendre"
msgid "Expand all files"
-msgstr ""
+msgstr "Étendre tous les fichiers"
msgid "Expand all threads"
-msgstr ""
+msgstr "Étendre tous les fils de conversation"
msgid "Expand approvers"
msgstr ""
@@ -15714,16 +15926,16 @@ msgid "Expand file"
msgstr ""
msgid "Expand issues"
-msgstr ""
+msgstr "Étendre les tickets"
msgid "Expand jobs"
msgstr ""
msgid "Expand merge details"
-msgstr ""
+msgstr "Étendre les détails de fusion"
msgid "Expand milestones"
-msgstr ""
+msgstr "Étendre les jalons"
msgid "Expand panel"
msgstr ""
@@ -15735,10 +15947,10 @@ msgid "Expand sidebar"
msgstr "Étendre la barre latérale"
msgid "Expected documents: %{expected_documents}"
-msgstr ""
+msgstr "Documents attendus : %{expected_documents}"
msgid "ExperimentSubject|Must have exactly one of User, Namespace, or Project."
-msgstr ""
+msgstr "Doit être un choix unique entre Utilisateur, Espace de noms et Projet."
msgid "Expiration"
msgstr ""
@@ -15747,10 +15959,10 @@ msgid "Expiration date"
msgstr "Date d’expiration"
msgid "Expiration date (optional)"
-msgstr ""
+msgstr "Date d'expiration (facultatif)"
msgid "Expiration date:"
-msgstr ""
+msgstr "Date d’expiration :"
msgid "Expired"
msgstr ""
@@ -15765,10 +15977,10 @@ msgid "Expires"
msgstr ""
msgid "Expires %{preposition} %{expires_at}"
-msgstr ""
+msgstr "Expire %{preposition} %{expires_at}"
msgid "Expires on"
-msgstr ""
+msgstr "Expire le"
msgid "Expires:"
msgstr ""
@@ -15798,7 +16010,7 @@ msgid "Explore public groups"
msgstr "Explorer les groupes publics"
msgid "Explore public projects"
-msgstr ""
+msgstr "Explorer les projets publics"
msgid "Explore snippets"
msgstr ""
@@ -15807,49 +16019,49 @@ msgid "Explore topics"
msgstr "Explorer les sujets"
msgid "Export"
-msgstr ""
+msgstr "Exporter"
msgid "Export %{requirementsCount} requirements?"
-msgstr ""
+msgstr "Exporter %{requirementsCount} exigences ?"
msgid "Export as CSV"
msgstr "Exporter en CSV"
msgid "Export commit custody report"
-msgstr ""
+msgstr "Exporter le rapport des consignations du commit"
msgid "Export group"
msgstr ""
msgid "Export issues"
-msgstr ""
+msgstr "Exporter les tickets"
msgid "Export merge requests"
-msgstr ""
+msgstr "Exporter les demandes de fusion"
msgid "Export project"
msgstr ""
msgid "Export requirements"
-msgstr ""
+msgstr "Exporter les exigences"
msgid "Export this group with all related data."
-msgstr ""
+msgstr "Exporter ce groupe avec toutes les données associées."
msgid "Export this project with all its related data in order to move it to a new GitLab instance. When the exported file is ready, you can download it from this page or from the download link in the email notification you will receive. You can then import it when creating a new project. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Exportez ce projet avec toutes ses données associées afin de le déplacer vers une nouvelle instance de GitLab. Lorsque le fichier exporté est prêt, vous pouvez le télécharger à partir de cette page ou du lien de téléchargement présent dans le courriel de notification que vous recevrez. Vous pouvez ensuite l'importer lors de la création d'un nouveau projet. %{link_start}En savoir plus.%{link_end}"
msgid "Export variable to pipelines running on protected branches and tags only."
msgstr ""
msgid "Exported requirements"
-msgstr ""
+msgstr "Exigences exportées"
msgid "External URL"
msgstr ""
msgid "External User:"
-msgstr ""
+msgstr "Utilisateur Externe :"
msgid "External authorization denied access to this project"
msgstr "L’autorisation externe a refusé l’accès à ce projet"
@@ -15861,7 +16073,7 @@ msgid "External storage authentication token"
msgstr ""
msgid "External storage for repository static objects"
-msgstr ""
+msgstr "Stockage externe pour les objets statiques du dépôt"
msgid "ExternalAuthorizationService|Classification label"
msgstr "Étiquette de classification"
@@ -15870,79 +16082,79 @@ msgid "ExternalAuthorizationService|When no classification label is set the defa
msgstr "Lorsqu’aucune étiquette de classification n’est définie, l’étiquette par défaut « %{default_label} » sera utilisée."
msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
-msgstr ""
+msgstr "L’accès aux projets est validé sur un service externe en utilisant leur étiquette de classification."
msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
-msgstr ""
+msgstr "Certificat utilisé pour l'authentification avec le service d'autorisation externe. Si vide, le certificat du serveur est validé lors de l'accès via HTTPS."
msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
-msgstr ""
+msgstr "Étiquette de classification à utiliser lors de la demande d'autorisation si aucune étiquette spécifique n'est définie sur le projet."
msgid "ExternalAuthorization|Client authorization certificate"
-msgstr ""
+msgstr "Certificat d'autorisation du client"
msgid "ExternalAuthorization|Client authorization key"
-msgstr ""
+msgstr "Clé d'autorisation du client"
msgid "ExternalAuthorization|Client authorization key password (optional)"
-msgstr ""
+msgstr "Mot de passe de la clé d'autorisation du client (facultatif)"
msgid "ExternalAuthorization|Default classification label"
-msgstr ""
+msgstr "Étiquette de classification par défaut"
msgid "ExternalAuthorization|Enable classification control using an external service"
-msgstr ""
+msgstr "Activer le contrôle de classification en utilisant un service externe"
msgid "ExternalAuthorization|External authorization"
-msgstr ""
+msgstr "Autorisation externe"
msgid "ExternalAuthorization|External authorization request timeout (seconds)"
-msgstr ""
+msgstr "Délai d'expiration des demandes d'autorisation externes (secondes)"
msgid "ExternalAuthorization|External classification policy authorization."
-msgstr ""
+msgstr "Autorisation de la politique de classification externe."
msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
-msgstr ""
+msgstr "Phrase secrète requise pour déchiffrer la clé privée. Chiffrée lorsqu'elle est enregistrée."
msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
-msgstr ""
+msgstr "Durée pendant laquelle GitLab attend une réponse du service externe. S'il n'y a pas de réponse, l'accès est refusé. Par défaut : 0,5 seconde."
msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
-msgstr ""
+msgstr "Clé privée du certificat d'authentification client. Chiffrée lorsqu'elle est enregistrée."
msgid "ExternalAuthorization|Service URL"
-msgstr ""
+msgstr "URL du service"
msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
-msgstr ""
+msgstr "URL auprès de laquelle les projets font les requêtes d'autorisation. Si elle est vide, les fonctionnalités inter-projets sont disponibles et peuvent toujours spécifier des étiquettes de classification pour les projets."
msgid "ExternalIssueIntegration|Another issue tracker is already in use"
-msgstr ""
+msgstr "Un autre gestionnaire de suivi de tickets est déjà en cours d'utilisation"
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 ""
+msgstr "Les données peuvent ne pas être toutes affichées ici. Pour voir plus de détails ou apporter des modifications à ce ticket, accédez à %{linkStart}%{trackerName}%{linkEnd}."
msgid "ExternalIssueIntegration|Only one issue tracker integration can be active at a time. Please disable the active tracker first and try again."
-msgstr ""
+msgstr "Une seule intégration de gestionnaire de suivi de tickets peut être active à un moment donné. Veuillez commencer par désactiver le gestionnaire actif puis réessayez."
msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
-msgstr ""
+msgstr "Ce ticket est synchronisé avec %{trackerName}"
msgid "ExternalWikiService|Enter the URL to the external wiki."
-msgstr ""
+msgstr "Entrez l'URL du wiki externe."
msgid "ExternalWikiService|External wiki"
-msgstr ""
+msgstr "Wiki externe"
msgid "ExternalWikiService|External wiki URL"
-msgstr ""
+msgstr "URL du wiki externe"
msgid "ExternalWikiService|Link to an external wiki from the sidebar."
-msgstr ""
+msgstr "Lien vers un wiki externe depuis la barre latérale."
msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
-msgstr ""
+msgstr "https://exemple.com/xxx/wiki/..."
msgid "Facebook"
msgstr "Facebook"
@@ -15955,8 +16167,8 @@ msgstr "Tâches ayant échoué"
msgid "Failed job"
msgid_plural "Failed jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Tâche en échec"
+msgstr[1] "Tâches en échec"
msgid "Failed on"
msgstr ""
@@ -15969,23 +16181,23 @@ msgstr ""
msgid "Failed to archive a design. Please try again."
msgid_plural "Failed to archive designs. Please try again."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Echec de l'archivage du design. Essayez à nouveau."
+msgstr[1] "Echec de l'archivage des designs. Essayez à nouveau."
msgid "Failed to assign a reviewer because no user was specified."
-msgstr ""
+msgstr "Échec de l'attribution d'un relecteur car aucun utilisateur n'a été spécifié."
msgid "Failed to assign a user because no user was found."
msgstr ""
msgid "Failed to cancel auto stop because failed to update the environment."
-msgstr ""
+msgstr "Échec de l'annulation de l'arrêt automatique car la mise à jour de l'environnement a échoué."
msgid "Failed to cancel auto stop because the environment is not set as auto stop."
msgstr ""
msgid "Failed to cancel auto stop because you do not have permission to update the environment."
-msgstr ""
+msgstr "Échec de l'annulation de l'arrêt automatique car vous n'êtes pas autorisé à mettre à jour l'environnement."
msgid "Failed to change the owner"
msgstr "Échec du changement de propriétaire"
@@ -15994,10 +16206,10 @@ msgid "Failed to check related branches."
msgstr "Échec de la vérification des branches liées."
msgid "Failed to clone this issue because target project doesn't exist."
-msgstr ""
+msgstr "Impossible de cloner ce ticket car le projet cible n'existe pas."
msgid "Failed to clone this issue: wrong parameters."
-msgstr ""
+msgstr "Impossible de cloner ce ticket : paramètres incorrects."
msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
@@ -16006,13 +16218,13 @@ msgid "Failed to create a to-do item for the design."
msgstr ""
msgid "Failed to create framework"
-msgstr ""
+msgstr "Échec de la création du framework"
msgid "Failed to create import label for jira import."
msgstr ""
msgid "Failed to create new access token: %{token_response_message}"
-msgstr ""
+msgstr "Échec de la création d'un nouveau jeton d'accès : %{token_response_message}"
msgid "Failed to create repository"
msgstr ""
@@ -16021,7 +16233,7 @@ msgid "Failed to create resources"
msgstr ""
msgid "Failed to create wiki"
-msgstr ""
+msgstr "Échec de la création du wiki"
msgid "Failed to deploy to"
msgstr "Échec du déploiement sur"
@@ -16030,10 +16242,10 @@ msgid "Failed to enqueue the rebase operation, possibly due to a long-lived tran
msgstr ""
msgid "Failed to fetch the iteration for this issue. Please try again."
-msgstr ""
+msgstr "Échec de la récupération de l'itération de ce ticket. Veuillez réessayer."
msgid "Failed to fetch the iterations for the group. Please try again."
-msgstr ""
+msgstr "Échec de la récupération des itérations du groupe. Veuillez réessayer."
msgid "Failed to find import label for Jira import."
msgstr ""
@@ -16057,55 +16269,52 @@ msgid "Failed to load"
msgstr ""
msgid "Failed to load Roadmap"
-msgstr ""
+msgstr "Échec du chargement de la Feuille de route"
msgid "Failed to load assignees."
-msgstr ""
+msgstr "Échec du chargement des assigné(e)s."
msgid "Failed to load assignees. Please try again."
-msgstr ""
+msgstr "Impossible de charger les assigné(e)s. Veuillez réessayer."
msgid "Failed to load authors. Please try again."
msgstr ""
msgid "Failed to load branches. Please try again."
-msgstr ""
+msgstr "Échec du chargement des branches. Veuillez réessayer."
msgid "Failed to load deploy keys."
-msgstr ""
-
-msgid "Failed to load emoji list."
-msgstr "Impossible de charger la liste des émojis."
+msgstr "Échec du chargement des clés de déploiement."
msgid "Failed to load error details from Sentry."
msgstr ""
msgid "Failed to load errors from Sentry."
-msgstr ""
+msgstr "Impossible de charger les erreurs depuis Sentry."
msgid "Failed to load group activity metrics. Please try again."
-msgstr ""
+msgstr "Impossible de charger les métriques d'activité du groupe. Veuillez réessayer."
msgid "Failed to load groups, users and deploy keys."
-msgstr ""
+msgstr "Échec du chargement des groupes, des utilisateurs et des clés de déploiement."
msgid "Failed to load groups."
-msgstr ""
+msgstr "Échec du chargement des groupes."
msgid "Failed to load iteration cadences."
msgstr ""
msgid "Failed to load iterations."
-msgstr ""
+msgstr "Échec du chargement des itérations."
msgid "Failed to load labels. Please try again."
-msgstr ""
+msgstr "Impossible de charger les étiquettes. Veuillez réessayer."
msgid "Failed to load milestones."
-msgstr ""
+msgstr "Échec du chargement des jalons."
msgid "Failed to load milestones. Please try again."
-msgstr ""
+msgstr "Échec du chargement des jalons. Veuillez réessayer."
msgid "Failed to load projects"
msgstr ""
@@ -16117,7 +16326,7 @@ msgid "Failed to load stacktrace."
msgstr ""
msgid "Failed to make repository read-only. %{reason}"
-msgstr ""
+msgstr "Impossible de rendre le dépôt en lecture seule. %{reason}"
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr ""
@@ -16132,7 +16341,7 @@ msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
msgid "Failed to promote issue to incident"
-msgstr ""
+msgstr "La promotion du ticket en incident a échoué"
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -16159,7 +16368,7 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Échec de la suppression du pipeline programmé"
msgid "Failed to remove timelog"
-msgstr ""
+msgstr "Échec de la suppression d'une entrée de temps passé"
msgid "Failed to remove user identity."
msgstr ""
@@ -16168,7 +16377,7 @@ msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
-msgstr ""
+msgstr "Échec de la récupération de la page"
msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr ""
@@ -16183,7 +16392,7 @@ msgid "Failed to save preferences."
msgstr ""
msgid "Failed to save timelog"
-msgstr ""
+msgstr "Échec de la sauvegarde d'une entrée de temps passé"
msgid "Failed to set due date because the date format is invalid."
msgstr ""
@@ -16204,13 +16413,13 @@ msgid "Failed to update environment!"
msgstr ""
msgid "Failed to update framework"
-msgstr ""
+msgstr "Échec de la mise à jour du framework"
msgid "Failed to update issue status"
msgstr ""
msgid "Failed to update the Canary Ingress."
-msgstr ""
+msgstr "Échec de la mise à jour du Canari Ingress."
msgid "Failed to update."
msgstr ""
@@ -16225,22 +16434,22 @@ msgid "Failure"
msgstr "Échec"
msgid "False positive"
-msgstr ""
+msgstr "Faux positif"
msgid "Fast timeout"
-msgstr ""
+msgstr "Délai d'expiration rapide"
msgid "Faster releases. Better code. Less pain."
-msgstr ""
+msgstr "Publications plus rapides. Meilleur code. Moins de frictions."
msgid "Favicon"
-msgstr ""
+msgstr "Favicon"
msgid "Favicon was successfully removed."
msgstr ""
msgid "Favicon will be removed. Are you sure?"
-msgstr ""
+msgstr "La favicon sera supprimée. Êtesâ€vous sûr(e) ?"
msgid "Feature Flags"
msgstr "Indicateurs de fonctionnalités"
@@ -16249,7 +16458,7 @@ msgid "Feature deprecation"
msgstr ""
msgid "Feature flag status"
-msgstr ""
+msgstr "État de l'indicateur de fonctionnalité"
msgid "Feature flag was not removed."
msgstr ""
@@ -16259,8 +16468,8 @@ msgstr ""
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d utilisateur"
+msgstr[1] "%d utilisateurs"
msgid "FeatureFlags|%{percent} by available ID"
msgstr ""
@@ -16284,13 +16493,13 @@ msgid "FeatureFlags|Active"
msgstr "Actif"
msgid "FeatureFlags|Add strategy"
-msgstr ""
+msgstr "Ajouter une stratégie"
msgid "FeatureFlags|All Environments"
-msgstr ""
+msgstr "Tous les environnements"
msgid "FeatureFlags|All Users"
-msgstr ""
+msgstr "Tous les utilisateurs"
msgid "FeatureFlags|All users"
msgstr ""
@@ -16302,7 +16511,7 @@ msgid "FeatureFlags|Configure feature flags"
msgstr "Configurer les indicateurs de fonctionnalité"
msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
-msgstr ""
+msgstr "Envisagez plutôt d'utiliser la stratégie « Pourcentage de déploiement » qui est plus souple."
msgid "FeatureFlags|Create feature flag"
msgstr "Créer un indicateur de fonctionnalité"
@@ -16320,10 +16529,10 @@ msgid "FeatureFlags|Edit Feature Flag"
msgstr "Modifier l’indicateur de fonctionnalité"
msgid "FeatureFlags|Edit User List"
-msgstr ""
+msgstr "Modifier la Liste d'Utilisateurs"
msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
-msgstr ""
+msgstr "Activer des fonctionnalités pour des utilisateurs et des environnements spécifiques en configurant des stratégies d'indicateurs de fonctionnalités."
msgid "FeatureFlags|Environment Specs"
msgstr ""
@@ -16332,16 +16541,16 @@ msgid "FeatureFlags|Feature Flag"
msgstr "Indicateur de fonctionnalité"
msgid "FeatureFlags|Feature Flag User List Details"
-msgstr ""
+msgstr "Détails des Listes d'Utilisateurs des Indicateurs de Fonctionnalités"
msgid "FeatureFlags|Feature Flag User Lists"
-msgstr ""
+msgstr "Listes d'Utilisateurs des Indicateurs de Fonctionnalités"
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
msgid "FeatureFlags|Feature Flag has no strategies"
-msgstr ""
+msgstr "L'indicateur de fonctionnalité ne possède pas de stratégie"
msgid "FeatureFlags|Feature Flags"
msgstr ""
@@ -16368,7 +16577,7 @@ msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
-msgstr ""
+msgstr "Installez une %{docsLinkAnchoredStart}bibliothèque cliente compatible%{docsLinkAnchoredEnd} et spécifiez l'URL de l'API, le nom de l'application et l'ID de l'instance au cours de la configuration. %{docsLinkStart}Plus d'informations%{docsLinkEnd}"
msgid "FeatureFlags|Instance ID"
msgstr "Identifiant d’instance"
@@ -16392,28 +16601,28 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "Nouvel indicateur de fonctionnalité"
msgid "FeatureFlags|New User List"
-msgstr ""
+msgstr "Nouvelle Liste d'Utilisateurs"
msgid "FeatureFlags|New feature flag"
msgstr ""
msgid "FeatureFlags|No user list selected"
-msgstr ""
+msgstr "Aucune liste d'utilisateurs sélectionnée"
msgid "FeatureFlags|Percent of users"
-msgstr ""
+msgstr "Pourcentage d'utilisateurs"
msgid "FeatureFlags|Percent rollout"
-msgstr ""
+msgstr "Pourcentage de déploiement"
msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
-msgstr ""
+msgstr "Le pourcentage de déploiement doit être un nombre entier compris entre 0 et 100"
msgid "FeatureFlags|Remove"
msgstr ""
msgid "FeatureFlags|Search code references"
-msgstr ""
+msgstr "Rechercher des références de code"
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 ""
@@ -16422,13 +16631,13 @@ msgid "FeatureFlags|Status"
msgstr "État"
msgid "FeatureFlags|Strategies"
-msgstr ""
+msgstr "Stratégies"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
-msgstr ""
+msgstr "Pour empêcher des actions accidentelles, nous vous demandons de confirmer votre intention. Veuillez taper %{projectName} pour continuer ou fermer ce dialogue pour annuler."
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -16437,16 +16646,16 @@ msgid "FeatureFlags|User IDs"
msgstr ""
msgid "FeatureFlags|User List"
-msgstr ""
+msgstr "Liste d'Utilisateurs"
msgid "FeatureFlags|User Lists"
-msgstr ""
+msgstr "Listes d'Utilisateurs"
msgid "FeatureFlags|View user lists"
-msgstr ""
+msgstr "Afficher les listes d'utilisateurs"
msgid "FeatureFlag|Percentage"
-msgstr ""
+msgstr "Pourcentage"
msgid "FeatureFlag|Select a user list"
msgstr ""
@@ -16455,16 +16664,16 @@ msgid "FeatureFlag|Select the environment scope for this feature flag"
msgstr ""
msgid "FeatureFlag|There are no configured user lists"
-msgstr ""
+msgstr "Il n’y a pas de liste d’utilisateurs configurée"
msgid "FeatureFlag|Type"
-msgstr ""
+msgstr "Type"
msgid "FeatureFlag|User IDs"
-msgstr ""
+msgstr "IDs utilisateur"
msgid "FeatureFlag|User List"
-msgstr ""
+msgstr "Liste d'Utilisateurs"
msgid "Feb"
msgstr "févr."
@@ -16482,13 +16691,13 @@ msgid "File"
msgstr ""
msgid "File %{current} of %{total}"
-msgstr ""
+msgstr "Fichier %{current} sur %{total}"
msgid "File Hooks"
-msgstr ""
+msgstr "Fichiers « Hooks »"
msgid "File Hooks (%{count})"
-msgstr ""
+msgstr "Fichiers « Hooks » (%{count})"
msgid "File Tree"
msgstr ""
@@ -16503,7 +16712,7 @@ msgid "File deleted"
msgstr ""
msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
-msgstr ""
+msgstr "Les fichiers « hooks » sont similaires aux « hooks » système mais sont exécutés sous forme de fichiers plutôt que par l'envoi de données vers une URL."
msgid "File mode changed from %{a_mode} to %{b_mode}"
msgstr ""
@@ -16515,22 +16724,22 @@ msgid "File name"
msgstr ""
msgid "File renamed with no changes."
-msgstr ""
+msgstr "Fichier renommé sans changement."
msgid "File suppressed by a .gitattributes entry or the file's encoding is unsupported."
-msgstr ""
+msgstr "Le fichier a été supprimé par une entrée .gitattributes, ou son encodage n'est pas pris en charge."
msgid "File templates"
msgstr "Modèles de fichiers"
msgid "File too large. Secure Files must be less than %{limit} MB."
-msgstr ""
+msgstr "Fichier trop volumineux. Les Fichiers Sécurisés doivent faire moins de %{limit} Mo."
msgid "File upload error."
msgstr ""
msgid "Filename"
-msgstr ""
+msgstr "Nom du fichier"
msgid "Files"
msgstr "Fichiers"
@@ -16548,16 +16757,16 @@ msgid "Files, directories, and submodules in the path %{path} for commit referen
msgstr ""
msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
-msgstr ""
+msgstr "Remplissez les champs ci-dessous, activez %{strong_open}Activer l'authentification SAML pour ce groupe%{strong_close} et appuyez sur %{strong_open}Enregistrer les modifications%{strong_close}"
msgid "Filter"
msgstr "Filtrer"
msgid "Filter by"
-msgstr ""
+msgstr "Filtrer par"
msgid "Filter by %{page_context_word} that are currently open."
-msgstr ""
+msgstr "Filtrer sur les %{page_context_word} qui sont actuellement ouvert(e)s."
msgid "Filter by Git revision"
msgstr ""
@@ -16566,13 +16775,13 @@ msgid "Filter by issues that are currently closed."
msgstr ""
msgid "Filter by issues that are currently opened."
-msgstr ""
+msgstr "Filtrer sur les tickets qui sont actuellement ouverts."
msgid "Filter by label"
-msgstr ""
+msgstr "Filtrer par étiquette"
msgid "Filter by merge requests that are currently closed and unmerged."
-msgstr ""
+msgstr "Filtrer par demandes de fusion qui sont actuellement fermées et non fusionnées."
msgid "Filter by merge requests that are currently merged."
msgstr ""
@@ -16587,16 +16796,16 @@ msgid "Filter by name"
msgstr "Filtrer par nom"
msgid "Filter by test cases that are currently archived."
-msgstr ""
+msgstr "Filtrer par cas de test actuellement archivés."
msgid "Filter by test cases that are currently open."
-msgstr ""
+msgstr "Filtrer sur les cas de tests actuellement ouverts."
msgid "Filter by user"
-msgstr ""
+msgstr "Filtrer par utilisateur"
msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
-msgstr ""
+msgstr "Les paramètres du filtre ne sont pas valides. Assurez-vous que la date de fin est postérieure à la date de début."
msgid "Filter pipelines"
msgstr ""
@@ -16620,13 +16829,13 @@ msgid "Filter..."
msgstr "Filtrer…"
msgid "Find File"
-msgstr ""
+msgstr "Rechercher un fichier"
msgid "Find bugs in your code with API fuzzing."
msgstr ""
msgid "Find bugs in your code with coverage-guided fuzzing."
-msgstr ""
+msgstr "Trouvez les bogues de votre code avec des tests à données aléatoires guidés par la couverture."
msgid "Find by path"
msgstr "Rechercher par chemin d’accès"
@@ -16635,10 +16844,10 @@ msgid "Find file"
msgstr "Rechercher un fichier"
msgid "Fingerprint (MD5)"
-msgstr ""
+msgstr "Empreinte (MD5)"
msgid "Fingerprint (SHA256)"
-msgstr ""
+msgstr "Empreinte (SHA256)"
msgid "Fingerprints"
msgstr "Empreintes"
@@ -16650,13 +16859,13 @@ msgid "Finish review"
msgstr ""
msgid "Finish setting up your dedicated account for %{group_name}."
-msgstr ""
+msgstr "Terminer la configuration de votre compte dédié pour %{group_name}."
msgid "Finished"
msgstr "Terminé"
msgid "First Name"
-msgstr ""
+msgstr "Prénom"
msgid "First Seen"
msgstr ""
@@ -16674,7 +16883,7 @@ msgid "Fixed"
msgstr ""
msgid "Fixed burndown chart"
-msgstr ""
+msgstr "Graphique d'avancement corrigé"
msgid "Fixed:"
msgstr "Corrigé :"
@@ -16683,22 +16892,22 @@ msgid "Flags"
msgstr ""
msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
-msgstr ""
+msgstr "Configurez si vous souhaitez participer à FLoC. %{floc_link_start}Qu'est-ce-que FLoC ?%{floc_link_end}"
msgid "FloC|Federated Learning of Cohorts (FLoC)"
-msgstr ""
+msgstr "Federated Learning of Cohorts (FLoC)"
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "Participer à FLoC"
msgid "FlowdockService|Enter your Flowdock token."
-msgstr ""
+msgstr "Entrez votre jeton Flowdock."
msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows."
-msgstr ""
+msgstr "Envoyer des notifications d'événements depuis GitLab vers des flux Flowdock."
msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}"
-msgstr ""
+msgstr "Envoyer des notifications d'événements depuis GitLab vers des flux Flowdock. %{docs_link}"
msgid "Focus filter bar"
msgstr ""
@@ -16719,22 +16928,22 @@ msgid "FogBugz import"
msgstr "Importation de FogBugz"
msgid "Fogbugz|Fogbugz import failed due to an error: %{error}"
-msgstr ""
+msgstr "L’importation Fogbugz a échoué à cause d’une erreur : %{error}"
msgid "Fogbugz|Project %{repo} could not be found"
-msgstr ""
+msgstr "Le projet %{repo} n'a pas pu être trouvé"
msgid "Folder/%{name}"
msgstr ""
msgid "Follow"
-msgstr ""
+msgstr "Suivre"
msgid "Followed Users' Activity"
-msgstr ""
+msgstr "Activité des Utilisateurs suivis"
msgid "Followed users"
-msgstr ""
+msgstr "Utilisateurs suivis"
msgid "Font Color"
msgstr "Couleur de la police"
@@ -16743,46 +16952,49 @@ msgid "Footer message"
msgstr "Message de pied de page"
msgid "For a faster browsing experience, some files are collapsed by default."
-msgstr ""
+msgstr "Pour une navigation plus rapide, certains fichiers ont été repliés par défaut."
msgid "For additional information, review your %{link_to} or contact your group owner."
-msgstr ""
+msgstr "Pour plus d'informations, examinez votre %{link_to} ou contactez le propriétaire de votre groupe."
msgid "For additional information, review your group membership: %{link_to} or contact your group owner."
-msgstr ""
+msgstr "Pour des informations supplémentaires, examinez votre adhésion au groupe : %{link_to} ou contactez le propriétaire de votre groupe."
msgid "For each job, clone the repository."
msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
-msgstr ""
+msgstr "Pour chaque tâche, réutiliser l'espace de travail du projet. S'il n'en existe pas, utiliser %{code_open}git clone%{code_close}."
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
-msgstr ""
+msgstr "Par exemple, l'application utilisant le jeton ou le but du jeton. Ne donnez pas d'informations sensibles pour le nom du jeton, car elles seront visibles pour tous les membres du %{resource_type}."
+
+msgid "For faster browsing, not all history is shown."
+msgstr "Pour une navigation plus rapide, l'historique n'est pas entièrement affiché."
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
+msgstr "Pour les fichiers de taille supérieure à cette limite, n'indexer que le nom. Le contenu du fichier ne sera ni indexé ni accessible aux recherches."
msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
-msgstr ""
+msgstr "Pour une utilisation individuelle, créez un compte distinct avec votre adresse électronique personnelle, non relié à votre groupe ou domaine de messagerie Entreprise."
msgid "For investigating IT service disruptions or outages"
-msgstr ""
+msgstr "Pour enquêter sur les perturbations ou les pannes des services informatiques"
msgid "For more info, read the documentation."
msgstr ""
msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
-msgstr ""
+msgstr "Pour plus d'informations sur la façon dont le nombre d'utilisateurs actifs est calculé, consultez la %{self_managed_subscriptions_doc_link}documentation."
msgid "For more information, go to the "
msgstr "Pour plus d’informations, consultez "
msgid "For more information, see the File Hooks documentation."
-msgstr ""
+msgstr "Pour plus d'informations, reportez-vous à la documentation sur les fichiers « Hooks »."
msgid "Forgot your password?"
msgstr ""
@@ -16803,70 +17015,70 @@ msgid "ForkProject|A fork is a copy of a project."
msgstr ""
msgid "ForkProject|An error occurred while forking the project. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du projet divergent. Veuillez réessayer."
msgid "ForkProject|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "ForkProject|Create a group"
-msgstr ""
+msgstr "Créer un groupe"
msgid "ForkProject|Fork project"
-msgstr ""
+msgstr "Créer un projet divergent"
msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
-msgstr ""
+msgstr "Créer un dépôt divergent vous permet de faire des modifications sans affecter le projet d'origine."
msgid "ForkProject|Internal"
-msgstr ""
+msgstr "Interne"
msgid "ForkProject|Please select a namespace"
-msgstr ""
+msgstr "Veuillez sélectionner un espace de noms"
msgid "ForkProject|Please select a visibility level"
-msgstr ""
+msgstr "Veuillez sélectionner un niveau de visibilité"
msgid "ForkProject|Private"
-msgstr ""
+msgstr "Privé"
msgid "ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
-msgstr ""
+msgstr "L'accès au projet doit être accordé à chaque utilisateur de manière explicite. Si ce projet fait partie d'un groupe, l'accès sera accordé à tous ses membres."
msgid "ForkProject|Public"
-msgstr ""
+msgstr "Public"
msgid "ForkProject|Select a namespace"
-msgstr ""
+msgstr "Sélectionnez un espace de noms"
msgid "ForkProject|Something went wrong while loading data. Please refresh the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des données. Veuillez actualiser la page pour réessayer."
msgid "ForkProject|The project can be accessed by any logged in user."
-msgstr ""
+msgstr "Le projet est accessible à tout utilisateur connecté."
msgid "ForkProject|The project can be accessed without any authentication."
-msgstr ""
+msgstr "Le projet est accessible sans authentification."
msgid "ForkProject|Visibility level"
-msgstr ""
+msgstr "Niveau de visibilité"
msgid "ForkProject|Want to organize several dependent projects under the same namespace?"
-msgstr ""
+msgstr "Vous souhaitez organiser plusieurs projets interdépendants sous un même espace de noms ?"
msgid "ForkSuggestion|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "ForkSuggestion|Fork"
-msgstr ""
+msgstr "Créer un projet divergent"
msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "Vous ne pouvez pas %{edit_start}modifier%{edit_end} des fichiers directement dans ce projet. Créez un projet divergent puis proposez une demande de fusion avec vos modifications."
msgid "ForkedFromProjectPath|Forked from"
msgstr "Divergence issue de"
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
-msgstr ""
+msgstr "Forké depuis un projet inaccessible"
msgid "Forking in progress"
msgstr "Divergence en cours"
@@ -16878,7 +17090,7 @@ msgid "Format: %{dateFormat}"
msgstr ""
msgid "Forward %{package_type} package requests to the %{registry_type} Registry if the packages are not found in the GitLab Package Registry"
-msgstr ""
+msgstr "Transférer les demandes de paquets %{package_type} au Registre %{registry_type} dans le cas où les paquets ne sont pas trouvés dans le Registre de Paquets de GitLab"
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr ""
@@ -16887,21 +17099,54 @@ msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
msgid "Framework successfully deleted"
+msgstr "Framework supprimé avec succès"
+
+msgid "Free"
msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
+msgstr "Essai Gratuit de GitLab.com Ultimate"
+
+msgid "Free User Cap"
msgstr ""
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Les groupes gratuits sont limités à %{free_user_limit} membre et ceux qui restent, obtenant l'état hors limite, perdront l'accès au groupe."
+msgstr[1] "Les groupes gratuits sont limités à %{free_user_limit} membres et ceux qui restent, obtenant l'état hors limite, perdront l'accès au groupe."
+
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "Vous pouvez également faire une mise à niveau vers GitLab Premium ou GitLab Ultimate :"
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "Explorer les forfaits payants"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "Explorer les forfaits payants :"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr "Il semble que vous ayez atteint votre limite de %{free_user_limit} membres pour « %{namespace_name} ». Vous ne pouvez pas en ajouter plus, mais vous pouvez gérer vos membres existants, par exemple, en supprimant ceux qui sont inactifs pour les remplacer par des nouveaux."
+
+msgid "FreeUserCap|Manage members"
+msgstr "Gérer les membres"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "Gérer les membres :"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "Afin d'obtenir plus de membres, %{trial_link_start}commencez un essai%{trial_link_end} ou %{upgrade_link_start}faîtes une mise à niveau%{upgrade_link_end} vers GitLab Premium ou GitLab Ultimate."
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "Afin d'obtenir plus de membres, commencez une période d'essai :"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "Vous avez atteint votre nombre limite de membres !"
msgid "Freeze end"
-msgstr ""
+msgstr "Fin du gel"
msgid "Freeze start"
-msgstr ""
+msgstr "Début du gel"
msgid "Frequency"
msgstr ""
@@ -16910,7 +17155,7 @@ msgid "Frequently searched"
msgstr "Fréquemment recherché"
msgid "Fri"
-msgstr ""
+msgstr "Ven"
msgid "Friday"
msgstr ""
@@ -16919,15 +17164,15 @@ msgid "From"
msgstr ""
msgid "From %{code_open}%{source_title}%{code_close} into"
-msgstr ""
+msgstr "De %{code_open}%{source_title}%{code_close} vers"
msgid "From %{providerTitle}"
msgstr ""
msgid "From October 19, 2022, free private groups will be limited to %d member"
msgid_plural "From October 19, 2022, free private groups will be limited to %d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "À partir du 19 octobre 2022, les groupes gratuits seront limités à %d membre"
+msgstr[1] "À partir du 19 octobre 2022, les groupes gratuits seront limités à %d membres"
msgid "From issue creation until deploy to production"
msgstr "Depuis la création du ticket jusqu’au déploiement en production"
@@ -16939,7 +17184,7 @@ msgid "Full"
msgstr ""
msgid "Full log"
-msgstr ""
+msgstr "Journaux complets"
msgid "Full name"
msgstr ""
@@ -16975,71 +17220,71 @@ msgid "Generate a default set of labels"
msgstr "Générer un jeu d’étiquettes par défaut"
msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
-msgstr ""
+msgstr "Générer des jetons d'accès au groupe, de portée limitée à celui-ci, pour vos applications qui ont besoin de l'API GitLab."
msgid "Generate new export"
msgstr ""
msgid "Generate project access tokens scoped to this project for your applications that need access to the GitLab API."
-msgstr ""
+msgstr "Générer des jetons d'accès au projet, de portée limitée au projet, pour vos applications qui ont besoin de l'API GitLab."
msgid "Generate site and private keys at"
-msgstr ""
+msgstr "Générer le site et les clés privées sur"
msgid "Generated with JSON data"
-msgstr ""
+msgstr "Généré avec les données JSON"
msgid "Generic"
-msgstr ""
+msgstr "Générique"
msgid "Generic package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier de paquet générique en octets"
msgid "GenericReport|After"
-msgstr ""
+msgstr "Après"
msgid "GenericReport|Before"
-msgstr ""
+msgstr "Avant"
msgid "GenericReport|Diff"
-msgstr ""
+msgstr "Diff"
msgid "Geo"
msgstr "Geo"
msgid "Geo Replication"
-msgstr ""
+msgstr "Réplication Geo"
msgid "Geo Settings"
-msgstr ""
+msgstr "Paramètres de Geo"
msgid "Geo Sites"
-msgstr ""
+msgstr "Sites Geo"
msgid "Geo sites"
-msgstr ""
+msgstr "Sites Geo"
msgid "Geo|%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 "Geo|%d shard selected"
msgid_plural "%d shards selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fragment sélectionné"
+msgstr[1] "%d fragments sélectionnés"
msgid "Geo|%{boldStart}Not applicable%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
-msgstr ""
+msgstr "%{boldStart}Non applicable%{boldEnd} : Geo ne vérifie pas ce composant pour le moment. Voir les %{linkStart}types de données que nous prévoyons de prendre en charge%{linkEnd}."
msgid "Geo|%{component} synced"
-msgstr ""
+msgstr "%{component} synchronisé"
msgid "Geo|%{component} verified"
-msgstr ""
+msgstr "%{component} vérifié"
msgid "Geo|%{label} %{timeAgo}"
-msgstr ""
+msgstr "%{label} %{timeAgo}"
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17057,19 +17302,19 @@ msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
msgid "Geo|%{timeAgoStr} (%{pendingEvents} events)"
-msgstr ""
+msgstr "%{timeAgoStr} (%{pendingEvents} événements)"
msgid "Geo|%{title} checksum progress"
msgstr ""
msgid "Geo|Add New Site"
-msgstr ""
+msgstr "Ajouter un nouveau site"
msgid "Geo|Add site"
-msgstr ""
+msgstr "Ajouter un site"
msgid "Geo|All"
-msgstr ""
+msgstr "Tout"
msgid "Geo|All %{replicable_name}"
msgstr ""
@@ -17078,25 +17323,25 @@ msgid "Geo|All projects"
msgstr "Tous les projets"
msgid "Geo|All projects are being scheduled for resync"
-msgstr ""
+msgstr "Tous les projets ont été planifiés pour resynchronisation"
msgid "Geo|All projects are being scheduled for reverify"
-msgstr ""
+msgstr "Tous les projets ont été planifiés pour revérification"
msgid "Geo|Allow this secondary site to replicate content on Object Storage"
-msgstr ""
+msgstr "Autoriser ce site secondaire à répliquer le contenu sur le stockage d'objets"
msgid "Geo|Allowed Geo IP"
-msgstr ""
+msgstr "IP Geo autorisée"
msgid "Geo|Allowed Geo IP can't be blank"
-msgstr ""
+msgstr "L’adresse IP autorisée de Geo ne peut pas être vide"
msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
-msgstr ""
+msgstr "L'adresse IP autorisée de Geo doit contenir entre 1 et 255 caractères"
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
-msgstr ""
+msgstr "L'adresse IP autorisée de Geo doit contenir des adresses IP valides"
msgid "Geo|Checksummed"
msgstr ""
@@ -17105,37 +17350,37 @@ msgid "Geo|Choose specific groups or storage shards"
msgstr ""
msgid "Geo|Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
-msgstr ""
+msgstr "Virgule comme séparateur, p. ex. « 1.1.1.1, 2.2.2.0/24 »"
msgid "Geo|Configure various settings for your %{siteType} site. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Configurez divers paramètres pour votre site %{siteType} . %{linkStart}En savoir plus%{linkEnd}"
msgid "Geo|Connection timeout"
-msgstr ""
+msgstr "Délai de connexion dépassé"
msgid "Geo|Connection timeout can't be blank"
-msgstr ""
+msgstr "Le délai d'expiration de la connexion ne peut pas être vide"
msgid "Geo|Connection timeout must be a number"
-msgstr ""
+msgstr "Le délai d'expiration de la connexion doit être un nombre"
msgid "Geo|Connection timeout should be between 1-120"
-msgstr ""
+msgstr "Le délai d'expiration de la connexion doit être compris entre 1 et 120"
msgid "Geo|Consult Geo troubleshooting information"
-msgstr ""
+msgstr "Consulter les informations de dépannage de Geo"
msgid "Geo|Container repositories synchronization concurrency limit"
-msgstr ""
+msgstr "Limite de synchronisations de dépôts de conteneurs simultanées"
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|Data replication lag"
-msgstr ""
+msgstr "Latence de la réplication des données"
msgid "Geo|Data type"
-msgstr ""
+msgstr "Type de données"
msgid "Geo|Disabled"
msgstr ""
@@ -17147,22 +17392,25 @@ msgid "Geo|Does not match the primary storage configuration"
msgstr ""
msgid "Geo|Edit %{nodeType} site"
-msgstr ""
+msgstr "Modifier le site %{nodeType}"
msgid "Geo|Edit Geo Site"
-msgstr ""
+msgstr "Modifier le Site Geo"
msgid "Geo|Edit your search and try again."
-msgstr ""
+msgstr "Modifiez votre recherche et réessayez."
msgid "Geo|Errors:"
+msgstr "Erreurs :"
+
+msgid "Geo|External URL"
msgstr ""
msgid "Geo|Failed"
msgstr "En échec"
msgid "Geo|File synchronization concurrency limit"
-msgstr ""
+msgstr "Limite de synchronisations de fichiers simultanées"
msgid "Geo|Filter Geo sites"
msgstr ""
@@ -17171,10 +17419,10 @@ msgid "Geo|Filter by name"
msgstr "Filtrer par nom"
msgid "Geo|Filter by status"
-msgstr ""
+msgstr "Filtrer par état"
msgid "Geo|Full details"
-msgstr ""
+msgstr "Détails complets"
msgid "Geo|Geo Settings"
msgstr ""
@@ -17186,37 +17434,37 @@ msgid "Geo|Geo allows you to choose specific groups or storage shards to replica
msgstr ""
msgid "Geo|Geo can replicate objects stored in Object Storage (AWS S3, or other compatible object storage)."
-msgstr ""
+msgstr "Geo peut dupliquer des objets enregistrés dans le Stockage d'Objets (AWS S3 ou autre stockage d'objets compatible)"
msgid "Geo|Geo sites"
-msgstr ""
+msgstr "Sites Geo"
msgid "Geo|Geo sites are paused using a command run on the site"
-msgstr ""
+msgstr "Les sites Geo sont mis en pause en utilisant une commande exécutée sur le site"
msgid "Geo|Go to the primary site"
-msgstr ""
+msgstr "Aller au site principal"
msgid "Geo|Groups to synchronize"
-msgstr ""
+msgstr "Groupes à synchroniser"
msgid "Geo|Healthy"
-msgstr ""
+msgstr "En bonne santé"
msgid "Geo|If enabled, GitLab will handle Object Storage replication using Geo."
msgstr ""
msgid "Geo|If you want to make changes, you must visit the primary site."
-msgstr ""
+msgstr "Si vous souhaitez apporter des modifications, vous devez aller sur le site principal."
msgid "Geo|In progress"
-msgstr ""
+msgstr "En cours"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "URL interne"
msgid "Geo|Internal URL (optional)"
-msgstr ""
+msgstr "URL interne (facultatif)"
msgid "Geo|Last event ID from primary"
msgstr ""
@@ -17237,25 +17485,25 @@ msgid "Geo|Last time verified"
msgstr "Dernière vérification"
msgid "Geo|Learn more about Geo"
-msgstr ""
+msgstr "En savoir plus sur Geo"
msgid "Geo|Learn more about Geo site statuses"
-msgstr ""
+msgstr "En savoir plus sur l'état des sites Geo"
msgid "Geo|Limit the number of concurrent operations this secondary site can run in the background."
-msgstr ""
+msgstr "Limiter le nombre d'opérations simultanées que ce site secondaire peut exécuter en arrière-plan."
msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
-msgstr ""
+msgstr "Augmentez la productivité de chacun des membres de votre équipe quel que soit l'endroit où il se trouve. GitLab Geo crée des miroirs de votre instance GitLab en lecture seule afin de pouvoir réduire le temps pris pour cloner ou récupérer des dépôts volumineux."
msgid "Geo|Minimum interval in days"
-msgstr ""
+msgstr "Intervalle minimum en jours"
msgid "Geo|Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
-msgstr ""
+msgstr "Doit correspondre avec %{codeStart}external_url%{codeEnd} dans %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgid "Geo|Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
-msgstr ""
+msgstr "Doit correspondre à %{codeStart}geo_node_name%{codeEnd} dans %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgid "Geo|Never"
msgstr "Jamais"
@@ -17264,34 +17512,34 @@ msgid "Geo|Next sync scheduled at"
msgstr "Prochaine synchro programmée à"
msgid "Geo|No %{replicable_type} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "%{replicable_type} introuvable. Si vous pensez qu'il s'agit d'une erreur, veuillez vous référer à la documentation de %{linkStart}Dépannage de Geo%{linkEnd} pour plus d'informations."
msgid "Geo|No %{replicable} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "%{replicable} introuvable. Si vous pensez qu'il s'agit d'une erreur, veuillez vous référer à la documentation de %{linkStart}Dépannage de Geo%{linkEnd} pour plus d'informations."
msgid "Geo|No Geo site found"
-msgstr ""
+msgstr "Aucun site Geo trouvé"
msgid "Geo|No available replication slots"
-msgstr ""
+msgstr "Aucun emplacement de réplication disponible"
msgid "Geo|Nothing found…"
-msgstr ""
+msgstr "Rien n'a été trouvé..."
msgid "Geo|Nothing to checksum"
msgstr ""
msgid "Geo|Nothing to synchronize"
-msgstr ""
+msgstr "Rien à synchroniser"
msgid "Geo|Nothing to verify"
-msgstr ""
+msgstr "Rien à vérifier"
msgid "Geo|Object Storage replication"
-msgstr ""
+msgstr "Réplication du Stockage d'Objets"
msgid "Geo|Offline"
-msgstr ""
+msgstr "Hors ligne"
msgid "Geo|Pending synchronization"
msgstr "En attente de synchronisation"
@@ -17300,10 +17548,10 @@ msgid "Geo|Pending verification"
msgstr "En attente de vérification"
msgid "Geo|Primary"
-msgstr ""
+msgstr "Primaire"
msgid "Geo|Primary site"
-msgstr ""
+msgstr "Site principal"
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 "Le projet (identifiant : %{project_id}) n’existe plus sur le primaire. Vous pouvez supprimer cette entrée en toute sécurité, car cela ne supprimera aucune donnée sur le disque."
@@ -17315,10 +17563,10 @@ msgid "Geo|Projects in certain storage shards"
msgstr "Projets dans certains fragments de stockage"
msgid "Geo|Queued"
-msgstr ""
+msgstr "En file d’attente"
msgid "Geo|Re-verification interval"
-msgstr ""
+msgstr "Intervalle de revérification"
msgid "Geo|Redownload"
msgstr "Reâ€télécharger"
@@ -17327,58 +17575,58 @@ msgid "Geo|Remove"
msgstr "Supprimer"
msgid "Geo|Remove %{nodeType} site"
-msgstr ""
+msgstr "Supprimer le site %{nodeType}"
msgid "Geo|Remove entry"
msgstr ""
msgid "Geo|Remove site"
-msgstr ""
+msgstr "Supprimer le site"
msgid "Geo|Remove tracking database entry"
msgstr ""
msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
-msgstr ""
+msgstr "La suppression d'un site Geo arrête la synchronisation depuis et vers ce site. Êtes-vous sûr(e) ?"
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
-msgstr ""
+msgstr "Les données répliquées sont vérifiées par rapport au(x) site(s) secondaire(s) grâce à des sommes de contrôle"
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums."
-msgstr ""
+msgstr "Les données répliquées sont vérifiées par rapport au(x) site(s) secondaire(s) grâce à des sommes de contrôle."
msgid "Geo|Replication Details"
-msgstr ""
+msgstr "Détails de Réplication"
msgid "Geo|Replication slot WAL"
-msgstr ""
+msgstr "Journal à écriture anticipée (WAL) de l’emplacement de réplication"
msgid "Geo|Replication slots"
-msgstr ""
+msgstr "Emplacements de réplication"
msgid "Geo|Replication status"
-msgstr ""
+msgstr "État de réplication"
msgid "Geo|Replication summary"
-msgstr ""
+msgstr "Résumé de réplication"
msgid "Geo|Repository synchronization concurrency limit"
-msgstr ""
+msgstr "Limite de synchronisations de dépôts simultanées"
msgid "Geo|Resync"
msgstr "Reâ€synchroniser"
msgid "Geo|Resync all"
-msgstr ""
+msgstr "Tout resynchroniser"
msgid "Geo|Resync all %{projects_count} projects"
-msgstr ""
+msgstr "Resynchroniser l'ensemble des %{projects_count} projets"
msgid "Geo|Resync all %{total}%{replicableType}"
-msgstr ""
+msgstr "Resynchroniser l'ensemble des %{total} %{replicableType}"
msgid "Geo|Resync project"
-msgstr ""
+msgstr "Resynchroniser le projet"
msgid "Geo|Retry count"
msgstr "Nombre de tentatives"
@@ -17387,124 +17635,127 @@ msgid "Geo|Reverify"
msgstr ""
msgid "Geo|Reverify all"
-msgstr ""
+msgstr "Tout revérifier"
msgid "Geo|Reverify all %{projects_count} projects"
-msgstr ""
+msgstr "Revérifier l'ensemble des %{projects_count} projets"
msgid "Geo|Reverify project"
-msgstr ""
+msgstr "Revérifier le projet"
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary site."
-msgstr ""
+msgstr "Vérifie l'état de la réplication, et revérifie et resynchronise les éléments avec le site principal."
msgid "Geo|Secondary"
-msgstr ""
+msgstr "Secondaire"
msgid "Geo|Secondary site"
-msgstr ""
+msgstr "Site secondaire"
msgid "Geo|Select groups to replicate"
-msgstr ""
+msgstr "Sélectionner les groupes à répliquer"
msgid "Geo|Select shards to replicate"
-msgstr ""
+msgstr "Sélectionnez les fragments à répliquer"
msgid "Geo|Selective (%{syncLabel})"
-msgstr ""
+msgstr "Sélective (%{syncLabel})"
msgid "Geo|Selective synchronization"
-msgstr ""
+msgstr "Synchronisation sélective"
msgid "Geo|Set the timeout in seconds to send a secondary site status to the primary and IPs allowed for the secondary sites."
-msgstr ""
+msgstr "Définir le délai d'attente avant expiration en secondes pour l'envoi de l'état d'un site secondaire vers le site principal et les adresses IP autorisées pour les sites secondaires."
msgid "Geo|Set verification limit and frequency."
-msgstr ""
+msgstr "Définir la limite et la fréquence de vérification."
msgid "Geo|Set what should be replicated by this secondary site."
-msgstr ""
+msgstr "Définir ce qui doit être répliqué par ce site secondaire."
msgid "Geo|Shards to synchronize"
-msgstr ""
+msgstr "Fragments à synchroniser"
msgid "Geo|Show more"
-msgstr ""
+msgstr "Afficher plus"
msgid "Geo|Site name can't be blank"
-msgstr ""
+msgstr "Le nom du site ne peut pas être vide"
msgid "Geo|Site name should be between 1 and 255 characters"
-msgstr ""
+msgstr "Le nom du site doit contenir entre 1 et 255 caractères"
msgid "Geo|Site's status was updated %{timeAgo}."
-msgstr ""
+msgstr "L'état du site a été mis à jour %{timeAgo}."
msgid "Geo|Status"
msgstr "Statut"
msgid "Geo|Storage config"
-msgstr ""
+msgstr "Configuration de stockage"
msgid "Geo|Synced"
msgstr "Synchronisé"
msgid "Geo|Synchronization"
-msgstr ""
+msgstr "Synchronisation"
msgid "Geo|Synchronization failed - %{error}"
msgstr "Synchro en échec — %{error}"
msgid "Geo|Synchronization settings"
-msgstr ""
+msgstr "Paramètres de synchronisation"
msgid "Geo|Synchronization status"
-msgstr ""
+msgstr "État de la synchronisation"
msgid "Geo|The URL of the primary site that is used internally by the secondary sites."
-msgstr ""
+msgstr "L'URL du site principal utilisé en interne par les sites secondaires."
msgid "Geo|The URL of the secondary site that is used internally by the primary site."
-msgstr ""
+msgstr "L'URL du site secondaire utilisé en interne par le site principal."
msgid "Geo|The database is currently %{db_lag} behind the primary site."
-msgstr ""
+msgstr "La base de données est actuellement %{db_lag} derrière le site principal."
msgid "Geo|The site is currently %{minutes_behind} behind the primary site."
-msgstr ""
+msgstr "Le site est actuellement %{minutes_behind} derrière le site principal."
msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
msgid "Geo|There are no %{replicable} to show"
-msgstr ""
+msgstr "Il n'y a pas de %{replicable} à afficher"
msgid "Geo|There was an error deleting the Geo Site"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression du Site Geo"
msgid "Geo|There was an error fetching the Geo Settings"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des Paramètres de Geo"
msgid "Geo|There was an error fetching the Geo Sites"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des Sites Geo"
msgid "Geo|There was an error fetching the Sites's Groups"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des Groupes de Sites"
msgid "Geo|There was an error saving this Geo Site"
-msgstr ""
+msgstr "Une erreur s’est produite lors de l'enregistrement de ce Site Geo"
msgid "Geo|There was an error updating the Geo Settings"
+msgstr "Une erreur s'est produite lors de la mise à jour des paramètres de Geo"
+
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
msgstr ""
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "Cette action resynchronisera la totalité des %{replicableType}. Cela peut prendre un certain temps pour s'exécuter. Êtes-vous sûr(e) de vouloir continuer ?"
msgid "Geo|This will resync all projects. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "Cette action resynchronisera tous les projets. Cela peut prendre un certain temps pour s'exécuter. Êtes-vous sûr(e) de vouloir continuer ?"
msgid "Geo|This will reverify all projects. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "Cette action revérifiera tous les projets. Cela peut prendre un certain temps pour s'exécuter. Êtes-vous sûr(e) de vouloir continuer ?"
msgid "Geo|Time in seconds"
msgstr ""
@@ -17516,19 +17767,19 @@ 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|Tuning settings"
-msgstr ""
+msgstr "Paramètres de réglage"
msgid "Geo|URL can't be blank"
-msgstr ""
+msgstr "L'URL ne peut pas être vide"
msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
-msgstr ""
+msgstr "L'URL doit être une url valide (ex: https://gitlab.com)"
msgid "Geo|Undefined"
-msgstr ""
+msgstr "Non défini"
msgid "Geo|Unhealthy"
-msgstr ""
+msgstr "En mauvaise santé"
msgid "Geo|Unknown"
msgstr ""
@@ -17537,7 +17788,7 @@ msgid "Geo|Updated %{timeAgo}"
msgstr "Mis à jour %{timeAgo}"
msgid "Geo|Verification"
-msgstr ""
+msgstr "Vérification"
msgid "Geo|Verification concurrency limit"
msgstr ""
@@ -17549,7 +17800,7 @@ msgid "Geo|Verification information"
msgstr ""
msgid "Geo|Verification status"
-msgstr ""
+msgstr "État de la vérification"
msgid "Geo|Verified"
msgstr ""
@@ -17561,10 +17812,10 @@ msgid "Geo|With GitLab Geo, you can install a special read-only and replicated i
msgstr ""
msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo site."
-msgstr ""
+msgstr "Vous êtes sur un site Geo secondaire, %{b_open}en lecture seule%{b_close}."
msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Vous pouvez effectuer un nombre limité de modifications ou d’actions sur cette page."
msgid "Geo|misconfigured"
msgstr "mal configuré"
@@ -17582,10 +17833,10 @@ msgid "Get a free trial"
msgstr ""
msgid "Get a support subscription"
-msgstr ""
+msgstr "Obtenir un abonnement au support"
msgid "Get started"
-msgstr ""
+msgstr "Commencer"
msgid "Get started with GitLab"
msgstr ""
@@ -17603,22 +17854,22 @@ msgid "Getting started with releases"
msgstr ""
msgid "Git"
-msgstr ""
+msgstr "Git"
msgid "Git GC period"
-msgstr ""
+msgstr "Période de Git GC"
msgid "Git LFS Rate Limits"
-msgstr ""
+msgstr "Limitations de Fréquence Git LFS"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
-msgstr ""
+msgstr "Les objets Git LFS seront synchronisés si LFS est %{docs_link_start}activé sur le projet%{docs_link_end}. Les miroirs push ne synchroniseront %{strong_open}pas%{strong_close} les objets LFS via SSH."
msgid "Git LFS status:"
-msgstr ""
+msgstr "État de Git LFS :"
msgid "Git global setup"
msgstr ""
@@ -17645,40 +17896,40 @@ msgid "GitAbuse|Automatically ban users from this %{scope} when they exceed the
msgstr ""
msgid "GitAbuse|Excluded users"
-msgstr ""
+msgstr "Utilisateurs exclus"
msgid "GitAbuse|Number of repositories"
-msgstr ""
+msgstr "Nombre de dépôts"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "Le nombre de dépôts ne peut pas être vide. Mettre à 0 pour illimité."
msgid "GitAbuse|Number of repositories must be a number."
-msgstr ""
+msgstr "Le nombre de dépôts doit être un nombre."
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr ""
+msgstr "Le nombre de dépôts doit être compris entre %{minNumRepos} et %{maxNumRepos}."
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "Durée considérée (secondes)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "La durée considérée ne peut pas être vide. Mettre à 0 pour pas de limite."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "La durée considérée doit être un nombre."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "La durée considérée doit être comprise entre %{minTimePeriod} et %{maxTimePeriod} secondes."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr ""
+msgstr "Le nombre maximum de dépôts uniques qu'un utilisateur peut télécharger au cours de la période spécifiée avant d'être banni."
msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
-msgstr ""
+msgstr "Utilisateurs exclus du taux limite d’abus de Git."
msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
-msgstr ""
+msgstr "Vous ne pouvez pas spécifier plus de %{maxExcludedUsers} utilisateurs exclus."
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
msgstr ""
@@ -17687,67 +17938,64 @@ msgid "GitHub import"
msgstr "Importation de GitHub"
msgid "GitHubImporter|*Merged by: %{author} at %{timestamp}*"
-msgstr ""
+msgstr "*Fusion par : %{author} le %{timestamp}*"
msgid "GitLab"
-msgstr ""
+msgstr "GitLab"
msgid "GitLab (self-managed)"
msgstr ""
msgid "GitLab / Unsubscribe"
-msgstr ""
+msgstr "GitLab / Se désabonner"
msgid "GitLab API"
msgstr ""
msgid "GitLab Account Request"
-msgstr ""
+msgstr "Demande de Compte GitLab"
msgid "GitLab Billing Team."
-msgstr ""
+msgstr "Équipe de facturation GitLab."
msgid "GitLab Error Tracking"
-msgstr ""
+msgstr "Suivi d'Erreurs de GitLab"
msgid "GitLab Import"
msgstr "Importation depuis GitLab"
msgid "GitLab Issue"
-msgstr ""
+msgstr "Ticket GitLab"
msgid "GitLab KAS"
-msgstr ""
-
-msgid "GitLab Logo"
-msgstr ""
+msgstr "GitLab KAS"
msgid "GitLab Pages"
msgstr ""
msgid "GitLab Shell"
-msgstr ""
+msgstr "GitLab Shell"
msgid "GitLab Support Bot"
-msgstr ""
+msgstr "Bot de support GitLab"
msgid "GitLab Team Member"
msgstr ""
msgid "GitLab Ultimate trial"
-msgstr ""
+msgstr "Essai GitLab Ultimate"
msgid "GitLab User"
msgstr "Utilisateur GitLab"
msgid "GitLab Workhorse"
-msgstr ""
+msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
-msgstr ""
+msgstr "Demande de compte GitLab rejetée"
msgid "GitLab commit"
-msgstr ""
+msgstr "Validation 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 ""
@@ -17771,22 +18019,22 @@ 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 est une application tout-en-un pour gérer le cycle de développement logiciel dans son intégralité. Depuis la planification du projet et la gestion du code source jusqu'à l'IC/CD, la supervision et la sécurité."
msgid "GitLab is free to use. Many features for larger teams are part of our %{link_start}paid products%{link_end}. You can try Ultimate for free without any obligation or payment details."
-msgstr ""
+msgstr "L'utilisation de GitLab est gratuite. De nombreuses fonctionnalités à destination de grandes équipes font parties de nos %{link_start}produits payants%{link_end}. Vous pouvez essayer Ultimate gratuitement sans aucune obligation ni information de paiement."
msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
msgstr ""
msgid "GitLab is open source software to collaborate on code."
-msgstr ""
+msgstr "GitLab est un logiciel libre pour collaborer sur du code."
msgid "GitLab is undergoing maintenance"
msgstr ""
msgid "GitLab logo"
-msgstr ""
+msgstr "Logo GitLab"
msgid "GitLab metadata URL"
msgstr ""
@@ -17795,37 +18043,37 @@ msgid "GitLab project export"
msgstr "Exportation de projet GitLab"
msgid "GitLab single sign-on URL"
-msgstr ""
+msgstr "URL de l'authentification unique GitLab"
msgid "GitLab username"
-msgstr ""
+msgstr "Nom d'utilisateur GitLab"
msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs"
-msgstr ""
+msgstr "GitLab utilise %{linkStart}Sidekiq%{linkEnd} pour traiter les tâches en arrière-plan"
msgid "GitLab version"
msgstr ""
msgid "GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab va créer une branche dans votre projet divergent et lancer une demande de fusion."
msgid "GitLab.com"
-msgstr ""
+msgstr "GitLab.com"
msgid "GitLab.com (SaaS)"
-msgstr ""
+msgstr "GitLab.com (SaaS)"
msgid "GitLab.com import"
msgstr "Importation depuis GitLab.com"
msgid "GitLabPagesDomains|Retry"
-msgstr ""
+msgstr "Réessayer"
msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
msgstr ""
msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
-msgstr ""
+msgstr "Le Contrôle d’Accès est activé pour ce site web Pages ; seuls les utilisateurs autorisés seront en mesure d’y accéder. Pour rendre votre site web accessible au public, accédez à %{strong_start}Paramètres &gt; Général &gt; Visibilité%{strong_end} dans votre projet et sélectionnez %{strong_start}Tout le monde%{strong_end} dans la section des pages. Lisez la %{link_start}documentation%{link_end} pour plus d'informations."
msgid "GitLabPages|Access pages"
msgstr ""
@@ -17834,13 +18082,13 @@ msgid "GitLabPages|Are you sure?"
msgstr ""
msgid "GitLabPages|Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
-msgstr ""
+msgstr "Peut être outrepassé au niveau du projet. Pour supprimer la limite, entrez 0. Pour hériter de la valeur, laissez vide."
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
msgid "GitLabPages|Check the Pipeline Status"
-msgstr ""
+msgstr "Vérifier l'État du Pipeline"
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17849,7 +18097,7 @@ msgid "GitLabPages|Domains"
msgstr ""
msgid "GitLabPages|Edit"
-msgstr ""
+msgstr "Éditer"
msgid "GitLabPages|Expired"
msgstr ""
@@ -17858,10 +18106,10 @@ msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
-msgstr ""
+msgstr "Les Pages GitLab de ce projet sont désactivées. Vous pouvez les activer sur la page %{strong_start}Paramètres &gt; Général &gt; Visibilité%{strong_end} de votre projet."
msgid "GitLabPages|Maximum size (MB)"
-msgstr ""
+msgstr "Taille maximale (Mo)"
msgid "GitLabPages|New Domain"
msgstr ""
@@ -17876,10 +18124,10 @@ msgid "GitLabPages|Remove"
msgstr ""
msgid "GitLabPages|Remove certificate"
-msgstr ""
+msgstr "Supprimer le certificat"
msgid "GitLabPages|Remove domain"
-msgstr ""
+msgstr "Supprimer le domaine"
msgid "GitLabPages|Remove pages"
msgstr ""
@@ -17888,43 +18136,43 @@ msgid "GitLabPages|Removing pages will prevent them from being exposed to the ou
msgstr ""
msgid "GitLabPages|Save changes"
-msgstr ""
+msgstr "Enregistrer les modifications"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’obtention du certificat Let's Encrypt pour %{domain}. Pour réessayer, consultez les %{link_start}détails de votre domaine%{link_end}."
msgid "GitLabPages|Start over"
-msgstr ""
+msgstr "Recommencer"
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+msgstr "La prise en charge des domaines et des certificats est désactivée. Demandez à l'administrateur de votre système de l'activer."
msgid "GitLabPages|Unverified"
msgstr ""
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "Mise à jour de la configuration de vos Pages..."
msgid "GitLabPages|Verified"
msgstr ""
msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
-msgstr ""
+msgstr "En attente de la fin du Pipeline Pages..."
msgid "GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Lorsque cette option est activée, toutes les tentatives pour se rendre sur votre site Web via HTTP sont automatiquement redirigées vers HTTPS à l'aide d'une réponse avec le code d'état 301. Nécessite un certificat valide pour tous les domaines. %{docs_link_start}En savoir plus.%{link_end}"
msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with subdomains of subdomains. If your namespace or groupname contains a dot, it does not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages work if you don't redirect HTTP to HTTPS. %{docs_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Lors de l'utilisation de Pages sous le domaine générique d'une instance GitLab (%{pages_host}), vous ne pouvez pas utiliser HTTPS avec des sous-domaines de sous-domaines. Si votre espace de noms ou nom de groupe contient un point, il ne fonctionnera pas. Il s'agit d'une limitation du protocole HTTP Over TLS. Les pages HTTP fonctionneront si vous ne redirigez pas HTTP vers HTTPS. %{docs_link_start}En savoir plus.%{link_end}"
msgid "GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Avec GitLab Pages, vous pouvez héberger votre site Web statique directement sur votre dépôt GitLab. %{docs_link_start}En savoir plus.%{link_end}"
msgid "GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}."
-msgstr ""
+msgstr "Votre site Pages n'est pas encore configuré. Consultez la %{docs_link_start}documentation de GitLab Pages%{link_end} pour apprendre comment téléverser votre site statique et le rendre disponible sous GitLab. Vous pouvez également vous inspirer des %{samples_link_start}exemples de projets Pages%{link_end} ."
msgid "GitLabPages|Your Project has been configured for Pages. Now we have to wait for the Pipeline to succeed for the first time."
-msgstr ""
+msgstr "Votre Projet a été configuré pour Pages. Il faut à présent attendre que le Pipeline se termine avec succès pour la première fois."
msgid "GitLabPages|Your pages are served under:"
msgstr ""
@@ -17933,13 +18181,13 @@ msgid "Gitaly Servers"
msgstr "Serveurs Gitaly"
msgid "Gitaly relative path:"
-msgstr ""
+msgstr "Chemin relatif de Gitaly :"
msgid "Gitaly storage name:"
-msgstr ""
+msgstr "Nom du stockage de Gitaly :"
msgid "Gitaly timeouts"
-msgstr ""
+msgstr "Délais d'expiration de Gitaly"
msgid "Gitaly|Address"
msgstr "Adresse"
@@ -17951,70 +18199,70 @@ msgid "Gitea Import"
msgstr "Importation depuis Gitea"
msgid "GithubImporter|PR mergers"
-msgstr ""
+msgstr "Valideurs de PR"
msgid "GithubImporter|PR reviews"
-msgstr ""
+msgstr "Revues de PR"
msgid "GithubImporter|Pull requests"
msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
-msgstr ""
+msgstr "Créez un %{token_link_start}jeton d'accès personnel%{token_link_end} disposant de l'accès %{status_html} puis collez-le ici."
msgid "GithubIntegration|Enable static status check names"
-msgstr ""
+msgstr "Activer les noms de vérification de l'état statique"
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
msgid "GithubIntegration|Repository URL"
-msgstr ""
+msgstr "URL du dépôt"
msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
msgstr ""
msgid "GithubIntegration|Static status check names (optional)"
-msgstr ""
+msgstr "Noms de vérification d'état statiques (facultatif)"
msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
+msgstr "Cela nécessite de faire un miroir de votre dépôt GitHub vers ce projet. %{docs_link}"
msgid "Gitpod"
msgstr ""
msgid "Gitpod|Enable Gitpod integration"
-msgstr ""
+msgstr "Activer l’intégration de Gitpod"
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "URL de Gitpod"
msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
-msgstr ""
+msgstr "L'URL de votre instance Gitpod configurée pour lire vos projets GitLab, comme https://gitpod.exemple.com."
msgid "Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
-msgstr ""
+msgstr "Pour utiliser Gitpod, vous devez au préalable activer la fonctionnalité dans la section intégrations de vos %{linkStart}préférences utilisateur%{linkEnd}."
msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
-msgstr ""
+msgstr "Pour utiliser l'intégration, chaque utilisateur doit également activer Gitpod sur son compte. %{link_start}Comment puis-je l'activer ?%{link_end} "
msgid "Gitpod|https://gitpod.example.com"
-msgstr ""
+msgstr "https://gitpod.exemple.com"
msgid "Given access %{time_ago}"
-msgstr ""
+msgstr "Accès donné %{time_ago}"
msgid "Given epic is already related to this epic."
msgstr ""
msgid "Global Search is disabled for this scope"
-msgstr ""
+msgstr "La Recherche Globale est désactivée pour cette portée"
msgid "Global Shortcuts"
msgstr ""
msgid "Global notification level"
-msgstr ""
+msgstr "Niveau de notification global"
msgid "Global notification settings"
msgstr ""
@@ -18026,13 +18274,13 @@ msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow
msgstr "%{count} résultats par défaut fournis. Utilisez les touches fléchées haut et bas pour parcourir la liste des résultats de la recherche."
msgid "GlobalSearch|Groups"
-msgstr ""
+msgstr "Groupes"
msgid "GlobalSearch|Help"
-msgstr ""
+msgstr "Aide"
msgid "GlobalSearch|In this project"
-msgstr ""
+msgstr "Dans ce projet"
msgid "GlobalSearch|Issues I've created"
msgstr "Tickets que j'ai créés"
@@ -18053,13 +18301,13 @@ msgid "GlobalSearch|Projects"
msgstr "Projets"
msgid "GlobalSearch|Recent epics"
-msgstr ""
+msgstr "Épopées récentes"
msgid "GlobalSearch|Recent issues"
-msgstr ""
+msgstr "Tickets récents"
msgid "GlobalSearch|Recent merge requests"
-msgstr ""
+msgstr "Demandes de fusion récentes"
msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
msgstr "Résultats mis à jour. %{count} résultats disponibles. Utilisez les touches fléchées haut et bas pour parcourir la liste des résultats de la recherche, ou ENTRÉE pour envoyer."
@@ -18074,7 +18322,7 @@ msgid "GlobalSearch|Search results are loading"
msgstr "Les résultats de la recherche sont en cours de chargement"
msgid "GlobalSearch|Settings"
-msgstr ""
+msgstr "Paramètres"
msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
msgstr "Une erreur s'est produite lors de la récupération des suggestions d'autocomplétion de recherche."
@@ -18098,16 +18346,16 @@ msgid "GlobalSearch|group"
msgstr "groupe"
msgid "GlobalSearch|in %{scope}"
-msgstr ""
+msgstr "dans %{scope}"
msgid "GlobalSearch|project"
msgstr "projet"
msgid "GlobalShortcuts|Copied source branch name to clipboard."
-msgstr ""
+msgstr "Nom de la branche source copié dans le presse-papiers."
msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
-msgstr ""
+msgstr "Impossible de copier le nom de la branche source pour le moment."
msgid "Globally-allowed IP ranges"
msgstr ""
@@ -18116,7 +18364,7 @@ msgid "Go Back"
msgstr "Retour"
msgid "Go Micro is a framework for micro service development"
-msgstr ""
+msgstr "Go Micro est un framework pour le développement de microservices"
msgid "Go back"
msgstr "Retour"
@@ -18125,7 +18373,7 @@ msgid "Go back (while searching for files)"
msgstr "Revenir en arrière (lors de la recherche de fichiers)"
msgid "Go back to configuration"
-msgstr ""
+msgstr "Retour à la configuration"
msgid "Go full screen"
msgstr "Plein écran"
@@ -18137,16 +18385,16 @@ msgid "Go to commits"
msgstr ""
msgid "Go to definition"
-msgstr ""
+msgstr "Aller à la définition"
msgid "Go to environments"
msgstr ""
msgid "Go to environments page to approve or reject"
-msgstr ""
+msgstr "Aller à la page des environnements pour approuver ou rejeter"
msgid "Go to epic"
-msgstr ""
+msgstr "Aller à l'épopée"
msgid "Go to file"
msgstr ""
@@ -18161,10 +18409,10 @@ msgid "Go to find file"
msgstr ""
msgid "Go to issue boards"
-msgstr ""
+msgstr "Aller aux tableaux des tickets"
msgid "Go to issues"
-msgstr ""
+msgstr "Aller aux tickets"
msgid "Go to jobs"
msgstr ""
@@ -18185,22 +18433,22 @@ msgid "Go to next unresolved thread"
msgstr "Aller au sujet non résolu suivant"
msgid "Go to page %{page}"
-msgstr ""
+msgstr "Aller à la page %{page}"
msgid "Go to parent"
msgstr ""
msgid "Go to parent directory"
-msgstr ""
+msgstr "Aller au répertoire parent"
msgid "Go to previous page"
msgstr "Aller à la page précédente"
msgid "Go to previous unresolved thread"
-msgstr ""
+msgstr "Aller au fil de conversation non résolu précédent"
msgid "Go to primary site"
-msgstr ""
+msgstr "Aller au site principal"
msgid "Go to project"
msgstr ""
@@ -18218,7 +18466,7 @@ msgid "Go to snippets"
msgstr ""
msgid "Go to the %{b_open}Activity%{b_close} page for %{project_link}."
-msgstr ""
+msgstr "Aller à la page %{b_open}Activité%{b_close} de %{project_link}."
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
msgstr ""
@@ -18257,7 +18505,7 @@ msgid "Go to your groups"
msgstr ""
msgid "Go to your issues"
-msgstr ""
+msgstr "Aller à vos tickets"
msgid "Go to your merge requests"
msgstr ""
@@ -18269,34 +18517,34 @@ msgid "Go to your snippets"
msgstr ""
msgid "Google Cloud"
-msgstr ""
+msgstr "Google Cloud"
msgid "Google Cloud Error - %{error}"
-msgstr ""
+msgstr "Erreur Google Cloud - %{error}"
msgid "Google Cloud Project"
msgstr ""
msgid "Google Cloud authorizations required"
-msgstr ""
+msgstr "Autorisations Google Cloud requises"
msgid "GoogleCloud|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "GoogleCloud|Configured region is linked to the selected branch or tag"
-msgstr ""
+msgstr "La région configurée est liée à l'étiquette ou à la branche sélectionnée"
msgid "GoogleCloud|Create service account"
-msgstr ""
+msgstr "Créer un compte de service"
msgid "GoogleCloud|Generated service account is linked to the selected branch or tag"
-msgstr ""
+msgstr "Le compte de service généré est lié à l'étiquette ou à la branche sélectionnée"
msgid "GoogleCloud|Google Cloud project"
-msgstr ""
+msgstr "Projet Google Cloud"
msgid "GoogleCloud|Google OAuth2 token revocation request failed"
-msgstr ""
+msgstr "La demande de révocation du jeton Google OAuth2 a échoué"
msgid "GoogleCloud|Google OAuth2 token revocation requested"
msgstr ""
@@ -18305,16 +18553,16 @@ msgid "GoogleCloud|I understand the responsibilities involved with managing serv
msgstr ""
msgid "GoogleCloud|New service account is generated for the selected Google Cloud project"
-msgstr ""
+msgstr "Un nouveau compte de service est généré pour le projet Google Cloud sélectionné"
msgid "GoogleCloud|Refs"
msgstr ""
msgid "GoogleCloud|Revoke authorizations"
-msgstr ""
+msgstr "Révoquer les autorisations"
msgid "GoogleCloud|Revoke authorizations granted to GitLab. This does not invalidate service accounts."
-msgstr ""
+msgstr "Révoquer les autorisations accordées à GitLab. Cela n'invalide pas les comptes de service."
msgid "Got it"
msgstr ""
@@ -18329,13 +18577,13 @@ msgid "Grafana response contains invalid json"
msgstr ""
msgid "GrafanaIntegration|API token"
-msgstr ""
+msgstr "Jeton d’API"
msgid "GrafanaIntegration|Active"
msgstr ""
msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
-msgstr ""
+msgstr "Entrez le %{docLinkStart}jeton d'API Grafana%{docLinkEnd}."
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr ""
@@ -18344,31 +18592,31 @@ msgid "GrafanaIntegration|Grafana URL"
msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
-msgstr ""
+msgstr "Authentification Grafana"
msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
-msgstr ""
+msgstr "Configurez l'authentification Grafana pour intégrer des panneaux Grafana dans du GitLab Flavored Markdown."
msgid "Grant access"
msgstr ""
msgid "Grant write permissions to this key"
-msgstr ""
+msgstr "Accorder des autorisations d'écriture à cette clé"
msgid "Graph"
msgstr "Graphique"
msgid "GraphViewType|Job dependencies"
-msgstr ""
+msgstr "Dépendances des tâches"
msgid "GraphViewType|Show dependencies"
-msgstr ""
+msgstr "Afficher les dépendances"
msgid "GraphViewType|Stage"
-msgstr ""
+msgstr "Étape"
msgid "Graphs"
-msgstr ""
+msgstr "graphiques"
msgid "Gravatar"
msgstr ""
@@ -18380,10 +18628,10 @@ msgid "Group"
msgstr "Groupe"
msgid "Group %{group_name} couldn't be exported."
-msgstr ""
+msgstr "Le groupe %{group_name} n'a pas pu être exporté."
msgid "Group %{group_name} was exported successfully."
-msgstr ""
+msgstr "Le groupe %{group_name} a été exporté avec succès."
msgid "Group %{group_name} was scheduled for deletion."
msgstr ""
@@ -18392,13 +18640,13 @@ msgid "Group %{group_name} was successfully created."
msgstr ""
msgid "Group Access Tokens"
-msgstr ""
+msgstr "Jetons d'Accès de Groupe"
msgid "Group Git LFS status:"
msgstr "Statut du stockage LFS Git du groupe :"
msgid "Group Hooks"
-msgstr ""
+msgstr "Crochets de groupe"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
@@ -18410,85 +18658,85 @@ msgid "Group URL"
msgstr "URL du groupe"
msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "La création de jeton d'accès de groupe est désactivée dans ce groupe. Vous pouvez toujours utiliser et gérer les jetons existants. %{link_start}En savoir plus.%{link_end}"
msgid "Group application: %{name}"
-msgstr ""
+msgstr "Application de groupe : %{name}"
msgid "Group applications"
-msgstr ""
+msgstr "Applications de groupe"
msgid "Group audit events"
-msgstr ""
+msgstr "Événements d'audit de groupe"
msgid "Group avatar"
msgstr "Avatar de groupe"
msgid "Group by"
-msgstr ""
+msgstr "Groupé par"
msgid "Group description (optional)"
msgstr "Description du groupe (optionnel)"
msgid "Group export could not be started."
-msgstr ""
+msgstr "L'exportation de groupe n'a pas pu être démarrée."
msgid "Group export download requests"
msgstr ""
msgid "Group export error"
-msgstr ""
+msgstr "Erreur d'exportation de groupe"
msgid "Group export link has expired. Please generate a new export from your group settings."
-msgstr ""
+msgstr "Le lien d'exportation de groupe a expiré. Veuillez générer un nouvel export à partir de vos paramètres de groupe."
msgid "Group export requests"
-msgstr ""
+msgstr "Demandes d'exportation de groupe"
msgid "Group export started. A download link will be sent by email and made available on this page."
-msgstr ""
+msgstr "L'exportation du groupe a commencé. Un lien de téléchargement sera envoyé par courriel et sera disponible sur cette page."
msgid "Group has been already marked for deletion"
-msgstr ""
+msgstr "Le groupe a déjà été marqué pour suppression"
msgid "Group has not been marked for deletion"
msgstr ""
msgid "Group import could not be scheduled"
-msgstr ""
+msgstr "L'importation de groupe n'a pas pu être planifiée"
msgid "Group import requests"
-msgstr ""
+msgstr "Demandes d'importation de groupe"
msgid "Group info:"
msgstr "Informations du groupe :"
msgid "Group information"
-msgstr ""
+msgstr "Information du groupe"
msgid "Group is required when cluster_type is :group"
-msgstr ""
+msgstr "Un groupe est requis lorsque cluster_type est :group"
msgid "Group jobs by"
-msgstr ""
+msgstr "Grouper les tâches par"
msgid "Group members"
msgstr ""
msgid "Group membership expiration date changed"
-msgstr ""
+msgstr "La date d'expiration de l'adhésion au groupe a été modifiée"
msgid "Group membership expiration date removed"
-msgstr ""
+msgstr "La date d'expiration de l'adhésion au groupe a été supprimée"
msgid "Group milestone"
-msgstr ""
+msgstr "Jalon de groupe"
msgid "Group name"
msgstr "Nom du groupe"
msgid "Group name (your organization)"
-msgstr ""
+msgstr "Nom du groupe (votre entreprise)"
msgid "Group navigation"
msgstr ""
@@ -18497,7 +18745,7 @@ msgid "Group overview content"
msgstr ""
msgid "Group path is already taken. We've suggested one that is available."
-msgstr ""
+msgstr "Le chemin du groupe est déjà pris. Nous en avons suggéré un qui est disponible."
msgid "Group path is available."
msgstr ""
@@ -18509,19 +18757,19 @@ msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
msgid "Group requires separate account"
-msgstr ""
+msgstr "Le groupe nécessite un compte séparé"
msgid "Group runners"
-msgstr ""
+msgstr "Exécuteurs de Groupe"
msgid "Group runners can be managed with the %{link}."
-msgstr ""
+msgstr "Les exécuteurs de groupe peuvent être gérés avec l'%{link}."
msgid "Group variables (inherited)"
msgstr ""
msgid "Group was exported"
-msgstr ""
+msgstr "Le groupe a été exporté"
msgid "Group was successfully updated."
msgstr ""
@@ -18530,7 +18778,7 @@ msgid "Group wikis"
msgstr ""
msgid "Group-level wiki is disabled."
-msgstr ""
+msgstr "Le wiki au niveau du groupe est désactivé."
msgid "Group: %{group_name}"
msgstr "Groupe : %{group_name}"
@@ -18539,55 +18787,58 @@ msgid "Group: %{name}"
msgstr ""
msgid "GroupActivityMetrics|Issues created"
-msgstr ""
+msgstr "Tickets créés"
msgid "GroupActivityMetrics|Last 30 days"
-msgstr ""
+msgstr "Les 30 derniers jours"
msgid "GroupActivityMetrics|Members added"
-msgstr ""
+msgstr "Membres ajoutés"
msgid "GroupActivityMetrics|Merge Requests created"
-msgstr ""
+msgstr "Demandes de fusion créées"
msgid "GroupActivityMetrics|Recent activity"
-msgstr ""
+msgstr "Activité récente"
msgid "GroupImport|Failed to import group."
-msgstr ""
+msgstr "L'importation du groupe a échoué."
msgid "GroupImport|Group '%{group_name}' is being imported."
-msgstr ""
+msgstr "Le groupe « %{group_name} » est en cours d'importation."
msgid "GroupImport|Group could not be imported: %{errors}"
-msgstr ""
+msgstr "Le groupe n'a pas pu être importé : %{errors}"
msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
-msgstr ""
+msgstr "Veuillez patienter pendant que nous importons le groupe. Actualisez quand vous voulez."
msgid "GroupImport|The group was successfully imported."
-msgstr ""
+msgstr "Le groupe a été importé avec succès."
msgid "GroupImport|Unable to process group import file"
-msgstr ""
+msgstr "Impossible de traiter le fichier d’importation de groupe"
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "Copier l'ID du groupe"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "ID de groupe : %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
msgstr ""
msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
-msgstr ""
+msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
-msgstr ""
+msgstr "Chargement des épopées"
+
+msgid "GroupRoadmap|New epic"
+msgstr "Nouvelle épopée"
msgid "GroupRoadmap|No start and end date"
-msgstr ""
+msgstr "Pas de date de début ni de fin"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
@@ -18596,7 +18847,7 @@ msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Une erreur s’est produite lors de la récupération des épopées"
msgid "GroupRoadmap|Something went wrong while fetching milestones"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des jalons"
msgid "GroupRoadmap|Sorry, no epics matched your search"
msgstr "Désolé, aucune épopée ne correspond à votre recherche"
@@ -18605,13 +18856,13 @@ msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timelin
msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
msgid "GroupRoadmap|This quarter"
-msgstr ""
+msgstr "Ce trimestre"
msgid "GroupRoadmap|This year"
-msgstr ""
+msgstr "Cette année"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
-msgstr ""
+msgstr "Pour que les épopées apparaissent sur la feuille de route, ajoutez-leur des dates de début ou d'échéance."
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
msgstr ""
@@ -18622,35 +18873,38 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr "Afficher la liste des épopées"
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
-msgstr ""
+msgstr "\"persistant\" recommandé"
msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
-msgstr ""
+msgstr "%{strongOpen}Avertissement%{strongClose} - Activer la %{linkStart}mise en œuvre de SSO%{linkEnd} pour réduire les risques de sécurité."
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
msgid "GroupSAML|An error occurred generating your SCIM token. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la génération de votre jeton SCIM. Veuillez réessayer."
msgid "GroupSAML|An error occurred resetting your SCIM token. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la réinitialisation de votre jeton SCIM. Veuillez réessayer."
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 ""
+msgstr "Êtes-vous sûr de vouloir réinitialiser le jeton SCIM ? Le provisionnement SCIM cessera de fonctionner jusqu'à ce que le nouveau jeton soit mis à jour."
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
-msgstr ""
+msgstr "Avant de mettre en Å“uvre SSO, activez l'authentification SAML."
msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
-msgstr ""
+msgstr "Avant de mettre en œuvre l'authentification unique avec SSO pour l'activité Git de tous les utilisateurs, activez-la pour l'activité web."
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -18659,7 +18913,7 @@ msgid "GroupSAML|Configuration"
msgstr ""
msgid "GroupSAML|Copy SAML Response XML"
-msgstr ""
+msgstr "Copier le XML de la réponse SAML"
msgid "GroupSAML|Could not create SAML group link: %{errors}."
msgstr ""
@@ -18668,16 +18922,16 @@ msgid "GroupSAML|Default membership role"
msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group"
-msgstr ""
+msgstr "Activer l'authentification SAML pour ce groupe"
msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
-msgstr ""
+msgstr "Mettre en œuvre l'authentification unique SSO pour les activités de Git et du Proxy de Dépendance pour ce groupe"
msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
-msgstr ""
+msgstr "Mettre en œuvre l'authentification unique SSO pour l'activité web de ce groupe"
msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
-msgstr ""
+msgstr "Forcer les utilisateurs à avoir des comptes dédiés gérés par le groupe pour ce groupe"
msgid "GroupSAML|Generate a SCIM token"
msgstr ""
@@ -18686,10 +18940,10 @@ msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Id
msgstr ""
msgid "GroupSAML|Identifier"
-msgstr ""
+msgstr "Identifiant"
msgid "GroupSAML|Identity provider single sign-on URL"
-msgstr ""
+msgstr "URL d’authentification unique du fournisseur d’identité"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
msgstr ""
@@ -18698,16 +18952,16 @@ msgid "GroupSAML|Manage your group’s membership while adding another level of
msgstr ""
msgid "GroupSAML|Members"
-msgstr ""
+msgstr "Membres"
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
msgid "GroupSAML|NameID"
-msgstr ""
+msgstr "NameID"
msgid "GroupSAML|NameID Format"
-msgstr ""
+msgstr "Format NameID"
msgid "GroupSAML|New SAML group link saved."
msgstr ""
@@ -18716,10 +18970,10 @@ msgid "GroupSAML|No active SAML group links"
msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group"
-msgstr ""
+msgstr "Interdire les projets divergents externes pour ce groupe"
msgid "GroupSAML|Reset SCIM token"
-msgstr ""
+msgstr "Réinitialiser le jeton SCIM"
msgid "GroupSAML|Role to assign members of this SAML group."
msgstr ""
@@ -18734,10 +18988,10 @@ msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
msgstr ""
msgid "GroupSAML|SAML Response Output"
-msgstr ""
+msgstr "Sortie de la réponse SAML"
msgid "GroupSAML|SAML Response XML"
-msgstr ""
+msgstr "XML de la réponse SAML"
msgid "GroupSAML|SAML Single Sign On"
msgstr ""
@@ -18755,7 +19009,7 @@ msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get thi
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 ""
+msgstr "Le jeton SCIM est maintenant masqué. Pour voir à nouveau sa valeur, vous devez %{linkStart}le réinitialiser%{linkEnd}."
msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
msgstr ""
@@ -18764,19 +19018,19 @@ msgid "GroupSAML|This will be set as the access level of users added to the grou
msgstr ""
msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
-msgstr ""
+msgstr "Afin de pouvoir activer les comptes gérés par le groupe, vous devez d'abord forcer l'authentification SSO."
msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
msgstr ""
msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
-msgstr ""
+msgstr "Utiliser les liens de groupe SAML pour gérer l'appartenance à un groupe à l'aide de SAML."
msgid "GroupSAML|Valid SAML Response"
-msgstr ""
+msgstr "Réponse SAML valide"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
-msgstr ""
+msgstr "Avec l'indicateur activé pour interdire les forks externes, les membres du groupe ne pourront créer un fork du projet que dans votre groupe."
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -18788,25 +19042,25 @@ msgid "GroupSAML|recommend persistent ID instead of email"
msgstr ""
msgid "GroupSaml|Copy SCIM API endpoint URL"
-msgstr ""
+msgstr "Copier l'URL du point de terminaison de l'API SCIM"
msgid "GroupSaml|Copy SCIM token"
-msgstr ""
+msgstr "Copier le jeton SCIM"
msgid "GroupSaml|SCIM API endpoint URL"
-msgstr ""
+msgstr "URL du point de terminaison de l'API SCIM"
msgid "GroupSaml|Your SCIM token"
-msgstr ""
+msgstr "Votre jeton SCIM"
msgid "GroupSelect|No matching results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "Rechercher des groupes"
msgid "GroupSelect|Select a group"
-msgstr ""
+msgstr "Sélectionner un groupe"
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
msgstr ""
@@ -18815,30 +19069,30 @@ msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
msgid "GroupSettings|Available only on the top-level group. Applies to all subgroups. Groups already shared with a group outside %{group} are still shared unless removed manually."
-msgstr ""
+msgstr "Disponible uniquement sur le groupe de niveau supérieur. S'applique à tous les sous-groupes. Les groupes déjà partagés avec un groupe en dehors de %{group} sont toujours partagés à moins de les supprimer manuellement."
msgid "GroupSettings|Badges"
msgstr "Badges numériques"
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 ""
+msgstr "Faites attention. Changer le parent d'un groupe peut avoir des effets secondaires inattendus. %{learn_more_link_start}En savoir plus.%{learn_more_link_end}"
msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
msgstr ""
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "Modifier l'URL du groupe"
msgid "GroupSettings|Changing a group's URL can have unintended side effects."
-msgstr ""
+msgstr "La modification de l’URL d'un groupe peut avoir des effets secondaires imprévus."
msgid "GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores."
-msgstr ""
+msgstr "Choisissez un chemin de groupe qui ne commence pas par un tiret ni se termine par un point. Il peut également contenir des caractères alphanumériques et des traits de soulignement."
msgid "GroupSettings|Compliance frameworks"
-msgstr ""
+msgstr "Cadres de conformité"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -18848,85 +19102,85 @@ msgid "GroupSettings|Custom project templates"
msgstr ""
msgid "GroupSettings|Customer relations is enabled"
-msgstr ""
+msgstr "La relation client est activée"
msgid "GroupSettings|Customize this group's badges."
-msgstr ""
+msgstr "Personnaliser les badges de ce groupe."
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
msgid "GroupSettings|Email notifications are disabled"
-msgstr ""
+msgstr "Les notifications par courriel sont désactivées"
msgid "GroupSettings|Export group"
-msgstr ""
+msgstr "Exportation de groupe"
msgid "GroupSettings|Git abuse rate limit"
-msgstr ""
+msgstr "Taux limite avant abus de Git"
msgid "GroupSettings|Group members are not notified if the group is mentioned."
-msgstr ""
+msgstr "Les membres du groupe ne sont pas informés si le groupe est mentionné."
msgid "GroupSettings|Group mentions are disabled"
-msgstr ""
+msgstr "Les mentions du groupe sont désactivées"
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 "Si non spécifiée au niveau du groupe ou de l'instance, la valeur par défaut est %{default_initial_branch_name}. N'affecte pas les dépôts existants."
msgid "GroupSettings|If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
-msgstr ""
+msgstr "Si la visibilité du groupe parent est inférieure à la visibilité actuelle du groupe, les niveaux de visibilité des sous-groupes et des projets seront modifiés en fonction de la visibilité du nouveau groupe parent."
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
-msgstr ""
+msgstr "Les membres ne peuvent pas inviter des groupes qui sont en-dehors de %{group} ou de ses sous-groupes"
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
-msgstr ""
+msgstr "Des organisations et des contacts peuvent être créés et associés avec des tickets."
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
-msgstr ""
+msgstr "Outrepasse les préférences de notification des utilisateurs pour tous les membres du groupe, sous-groupes et projets."
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
msgid "GroupSettings|Please choose a group URL with no special characters or spaces."
-msgstr ""
+msgstr "Veuillez choisir une URL de groupe sans caractères spéciaux ni espaces."
msgid "GroupSettings|Prevent forking outside of the group"
-msgstr ""
+msgstr "Empêcher le fork en dehors du groupe"
msgid "GroupSettings|Prevent forking setting was not saved"
-msgstr ""
+msgstr "Les paramètres pour empêcher le fork n’ont pas été enregistrés"
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
-msgstr ""
+msgstr "Les projets dans %{group} ne peuvent pas être partagés avec d'autres groupes"
msgid "GroupSettings|Reporting"
-msgstr ""
+msgstr "Rapports"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
-msgstr ""
+msgstr "Sélectionnez un sous-groupe à utiliser en tant que source pour les modèles de projet personnalisé de ce groupe."
msgid "GroupSettings|Select parent group"
-msgstr ""
+msgstr "Sélectionner le groupe parent"
msgid "GroupSettings|Select the project containing the %{code_start}.gitlab/insights.yml%{code_end} file"
-msgstr ""
+msgstr "Sélectionnez le projet contenant le fichier %{code_start}.gitlab/insights.yml%{code_end}"
msgid "GroupSettings|Select the project containing your custom Insights file. %{help_link_start}What is Insights?%{help_link_end}"
-msgstr ""
+msgstr "Sélectionnez le projet contenant votre fichier Insights personnalisé. %{help_link_start}Qu'est-ce que Insights ?%{help_link_end}"
msgid "GroupSettings|Set a size limit for all content in each Pages site in this group. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Définir une limite pour la taille de l'ensemble du contenu de chaque site Pages de ce groupe. %{link_start}En savoir plus.%{link_end}"
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
-msgstr ""
+msgstr "Définit les protections et nom initiaux pour la branche par défaut des nouveaux dépôts créés dans le groupe."
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Le pipeline Auto DevOps s’exécute si aucun autre fichier de configuration CI n’est trouvé."
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 ""
+msgstr "Les projets de ce sous-groupe peuvent être sélectionnés comme modèles pour les nouveaux projets créés dans le groupe. %{link_start}En savoir plus.%{link_end}"
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
msgstr ""
@@ -18947,16 +19201,16 @@ msgid "GroupSettings|Transfer group"
msgstr ""
msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group"
-msgstr ""
+msgstr "Les utilisateurs peuvent créer des %{link_start_project}jetons d'accès au projet%{link_end} et des %{link_start_group}jetons d'accès au groupe%{link_end} dans ce groupe"
msgid "GroupSettings|What are badges?"
-msgstr ""
+msgstr "Que sont les 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 ""
+msgstr "Lorsque le nombre d'utilisateurs actifs dépasse ce nombre, les utilisateurs supplémentaires doivent être %{user_cap_docs_link_start}approuvés par un propriétaire%{user_cap_docs_link_end}. Laissez vide si vous ne voulez pas imposer ces approbations."
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 ""
+msgstr "Lorsque le nombre d'utilisateurs actifs dépasse ce nombre, les utilisateurs supplémentaires doivent être %{user_cap_docs_link_start}approuvés par un propriétaire%{user_cap_docs_link_end}. Laissez vide si vous ne voulez pas imposer ces approbations. Augmenter le nombre maximal d'utilisateurs n'approuvera pas automatiquement les utilisateurs en attente."
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -18983,13 +19237,13 @@ msgid "Groups (%{count})"
msgstr ""
msgid "Groups and projects"
-msgstr ""
+msgstr "Groupes et projets"
msgid "Groups are a great way to organize projects and people."
-msgstr ""
+msgstr "Les groupes sont un excellent moyen d'organiser des projets et des personnes."
msgid "Groups are the best way to manage projects and members."
-msgstr ""
+msgstr "Les groupes sont le meilleur moyen de gérer des projets et des membres."
msgid "GroupsDropdown|Frequently visited"
msgstr "Fréquemment consultés"
@@ -19016,10 +19270,10 @@ msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr "Un groupe est une collection de plusieurs projets."
msgid "GroupsEmptyState|Create new project"
-msgstr ""
+msgstr "Créer un nouveau projet"
msgid "GroupsEmptyState|Create new subgroup"
-msgstr ""
+msgstr "Créer un nouveau sous-groupe"
msgid "GroupsEmptyState|Groups are the best way to manage multiple projects and members."
msgstr ""
@@ -19031,40 +19285,40 @@ msgid "GroupsEmptyState|No groups found"
msgstr "Aucun groupe trouvé"
msgid "GroupsEmptyState|No subgroups or projects."
-msgstr ""
+msgstr "Aucun sous-groupe ni projet."
msgid "GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab."
-msgstr ""
+msgstr "Les projets sont l'endroit où vous pouvez stocker votre code, accéder aux tickets, au wiki et aux autres fonctionnalités de GitLab."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accéder à chacun de ses projets."
msgid "GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project."
-msgstr ""
+msgstr "Vous n’avez pas les permissions nécessaires pour créer un sous-groupe ou un projet dans ce groupe. Veuillez contacter un propriétaire de ce groupe pour créer un nouveau sous-groupe ou projet."
msgid "GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "Les %{groupsLinkStart}groupes%{groupsLinkEnd} et les %{subgroupsLinkStart}sous-groupes%{subgroupsLinkEnd} vous permettent de gérer plusieurs projets et de collaborer dessus. Les membres d'un groupe disposent d'un accès à l'ensemble de ses projets."
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 "Les %{linkStart}groupes%{linkEnd} vous permettent de gérer et collaborer sur plusieurs projets. Les membres d'un groupe disposent d'un accès à l'ensemble de ses projets."
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Réunit des groupes apparentés et accorde aux membres l'accès à plusieurs projets à la fois."
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
-msgstr ""
+msgstr "Contactez un administrateur pour activer les options pour importer votre groupe."
msgid "GroupsNew|Create group"
-msgstr ""
+msgstr "Créer un groupe"
msgid "GroupsNew|Create new group"
-msgstr ""
+msgstr "Créer un nouveau groupe"
msgid "GroupsNew|Create subgroup"
-msgstr ""
+msgstr "Créer un sous-groupe"
msgid "GroupsNew|Create this in the %{pat_link_start}user settings%{pat_link_end} of the source GitLab instance. For %{short_living_link_start}security reasons%{short_living_link_end}, use a short expiration date when creating the token."
msgstr ""
@@ -19073,64 +19327,64 @@ msgid "GroupsNew|GitLab source URL"
msgstr ""
msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
-msgstr ""
+msgstr "Les groupes peuvent également être imbriqués en créant des %{linkStart}sous-groupes%{linkEnd}."
msgid "GroupsNew|Import a group and related data from another GitLab instance."
-msgstr ""
+msgstr "Importer un groupe et ses données associées depuis une autre instance GitLab."
msgid "GroupsNew|Import group"
-msgstr ""
+msgstr "Importer un groupe"
msgid "GroupsNew|Import groups from another instance of GitLab"
-msgstr ""
+msgstr "Importer des groupes depuis une autre instance de GitLab"
msgid "GroupsNew|No import options available"
msgstr ""
msgid "GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}."
-msgstr ""
+msgstr "Tous les objets associés ne sont pas migrés. %{docs_link_start}Plus d'infos%{docs_link_end}."
msgid "GroupsNew|Personal access token"
-msgstr ""
+msgstr "Jeton d'accès personnel"
msgid "GroupsNew|Please fill in GitLab source URL."
-msgstr ""
+msgstr "Veuillez renseigner l'URL source de GitLab."
msgid "GroupsNew|Please fill in your personal access token."
-msgstr ""
+msgstr "Veuillez renseigner votre jeton d’accès personnel."
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
-msgstr ""
+msgstr "Spécifiez les identifiants d'une autre instance de GitLab pour importer vos groupes directement."
msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
-msgstr ""
+msgstr "Cette fonctionnalité est obsolète et remplacée par la %{docs_link_start}migration de groupe%{docs_link_end}."
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 ""
+msgstr "Pour importer un groupe, accédez aux paramètres de groupe de l’instance GitLab source, %{link_start}générez un fichier d’exportation%{link_end} puis téléversez-le ici."
msgid "GroupsNew|Upload file"
-msgstr ""
+msgstr "Téléverser un fichier"
msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
-msgstr ""
+msgstr "Vous pouvez également %{linkStart}importer un groupe existant%{linkEnd}."
msgid "GroupsNew|e.g. h8d3f016698e..."
-msgstr ""
+msgstr "p. ex. h8d3f016698e..."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
msgstr "Êtes-vous sûr·e de vouloir quitter le groupe « %{fullName} » ?"
msgid "GroupsTree|Delete"
-msgstr ""
+msgstr "Supprimer"
msgid "GroupsTree|Edit"
-msgstr ""
+msgstr "Modifier"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "Impossible de quitter le groupe. Veuillez vous assurer que vous n’êtes pas seul·e propriétaire."
msgid "GroupsTree|Leave group"
-msgstr ""
+msgstr "Quitter le groupe"
msgid "GroupsTree|Loading groups"
msgstr "Chargement des groupes"
@@ -19142,230 +19396,242 @@ msgid "GroupsTree|No groups or projects matched your search"
msgstr "Aucun groupe ni projet ne correspond à votre recherche"
msgid "GroupsTree|Options"
-msgstr ""
+msgstr "Options"
msgid "GroupsTree|Search by name"
msgstr "Rechercher par nom"
msgid "Groups|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "L’avatar sera supprimé. Êtes-vous sûr(e) ?"
msgid "Groups|Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "La modification de l’URL du groupe peut avoir des effets secondaires imprévus."
msgid "Groups|Checking group URL availability..."
-msgstr ""
+msgstr "Vérification de la disponibilité de l'URL du groupe..."
msgid "Groups|Enter a descriptive name for your group."
-msgstr ""
+msgstr "Entrez un nom descriptif pour votre groupe."
msgid "Groups|Group ID"
-msgstr ""
+msgstr "ID du groupe"
msgid "Groups|Group URL"
-msgstr ""
+msgstr "URL du groupe"
msgid "Groups|Group avatar"
-msgstr ""
+msgstr "Avatar du groupe"
msgid "Groups|Group description (optional)"
-msgstr ""
+msgstr "Description du groupe (facultatif)"
msgid "Groups|Group name"
-msgstr ""
+msgstr "Nom du groupe"
msgid "Groups|Group path is available."
-msgstr ""
+msgstr "Le chemin du groupe est disponible."
msgid "Groups|Group path is unavailable. Path has been replaced with a suggested available path."
-msgstr ""
+msgstr "Le chemin du groupe n’est pas disponible. Il a été remplacé par une suggestion de chemin qui est disponible."
msgid "Groups|Learn more"
+msgstr "En savoir plus"
+
+msgid "Groups|Learn more about subgroups"
+msgstr "En savoir plus sur les sous-groupes"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
msgstr ""
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
-msgstr ""
+msgstr "Doit commencer par une lettre, un chiffre, un emoji ou un trait de soulignement. Peut également contenir des points, des tirets, des espaces et des parenthèses."
msgid "Groups|Remove avatar"
-msgstr ""
+msgstr "Supprimer l’avatar"
msgid "Groups|Save changes"
-msgstr ""
+msgstr "Enregistrer les modifications"
msgid "Groups|Subgroup URL"
-msgstr ""
+msgstr "URL du sous-groupe"
msgid "Groups|Subgroup name"
-msgstr ""
+msgstr "Nom du sous-groupe"
msgid "Groups|Subgroup slug"
+msgstr "Slug du sous-groupe"
+
+msgid "Groups|You're creating a new top-level group"
msgstr ""
msgid "Guideline"
msgstr ""
msgid "HAR (HTTP Archive)"
-msgstr ""
+msgstr "HAR (HTTP Archive)"
msgid "HAR file URL"
-msgstr ""
+msgstr "URL du fichier HAR"
msgid "HAR file path or URL"
-msgstr ""
+msgstr "Chemin d'accès ou URL du fichier HAR"
msgid "HTTP Archive (HAR)"
-msgstr ""
+msgstr "Archive HTTP (HAR)"
msgid "HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url}"
-msgstr ""
+msgstr "HTTP Basic : Accès refusé. Soit le mot de passe ou jeton fourni est incorrect, soit l'A2F est activée sur votre compte et vous devez utiliser un jeton d'accès personnel au lieu d'un mot de passe. Voir %{help_page_url}"
msgid "Harbor Registry"
-msgstr ""
+msgstr "Registre Harbor"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
-msgstr ""
+msgstr "URL de base de l'instance Harbor."
msgid "HarborIntegration|Enter new Harbor password"
-msgstr ""
+msgstr "Entrez un nouveau mot de passe Harbor"
msgid "HarborIntegration|Harbor URL"
-msgstr ""
+msgstr "URL de Harbor"
msgid "HarborIntegration|Harbor password"
-msgstr ""
+msgstr "Mot de passe de Harbor"
msgid "HarborIntegration|Harbor project name"
-msgstr ""
+msgstr "Nom du projet Harbor"
msgid "HarborIntegration|Harbor username"
-msgstr ""
+msgstr "Nom d'utilisateur Harbor"
msgid "HarborIntegration|Leave blank to use your current password."
-msgstr ""
+msgstr "Laisser vide pour utiliser votre mot de passe actuel."
msgid "HarborIntegration|Password for your Harbor username."
-msgstr ""
+msgstr "Le mot de passe de votre nom d'utilisateur Harbor."
msgid "HarborIntegration|The name of the project in Harbor."
-msgstr ""
+msgstr "Le nom du projet dans Harbor."
msgid "HarborIntegration|Use Harbor as this project's container registry."
-msgstr ""
+msgstr "Utiliser Harbor comme registre de conteneur sur ce projet."
msgid "HarborRegistry|%d artifact"
msgid_plural "HarborRegistry|%d artifacts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d artéfact"
+msgstr[1] "%d artéfacts"
msgid "HarborRegistry|%{count} Image repository"
msgid_plural "HarborRegistry|%{count} Image repositories"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} Dépôt d'images"
+msgstr[1] "%{count} Dépôts d'images"
msgid "HarborRegistry|-- artifacts"
+msgstr "-- artéfacts"
+
+msgid "HarborRegistry|-- tags"
msgstr ""
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
msgid "HarborRegistry|Harbor Registry"
-msgstr ""
+msgstr "Registre Harbor"
msgid "HarborRegistry|Harbor connection error"
-msgstr ""
+msgstr "Erreur de connexion Harbor"
msgid "HarborRegistry|Please try different search criteria"
-msgstr ""
+msgstr "Veuillez essayer des critères de recherche différents"
msgid "HarborRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "Publication %{timeInfo}"
msgid "HarborRegistry|Root image"
-msgstr ""
+msgstr "Image racine"
msgid "HarborRegistry|Something went wrong while fetching the artifact list."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la liste des artéfacts."
msgid "HarborRegistry|Something went wrong while fetching the repository list."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération de la liste des dépôts."
msgid "HarborRegistry|Something went wrong while fetching the tags."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étiquettes."
msgid "HarborRegistry|Sorry, your filter produced no results."
msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche."
msgid "HarborRegistry|Tag"
-msgstr ""
+msgstr " Étiquette"
msgid "HarborRegistry|The filter returned no results"
-msgstr ""
+msgstr "Le filtre n'a renvoyé aucun résultat"
msgid "HarborRegistry|There are no harbor images stored for this project"
-msgstr ""
+msgstr "Il n'y a aucune image de port stockée pour ce projet"
msgid "HarborRegistry|This image has no artifacts"
-msgstr ""
+msgstr "Cette image n'a aucun artéfact"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "Pour élargir votre recherche, modifiez ou supprimez les filtres ci-dessus."
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr ""
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr "Nous rencontrons des difficultés pour nous connecter au Registre Harbor. Veuillez essayer de rafraîchir la page. Si cette erreur persiste, veuillez consulter %{docLinkStart}la documentation%{docLinkEnd}."
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
-msgstr ""
+msgstr "Grâce au Registre Harbor, chaque projet peut se connecter à un espace harbor pour stocker ses images Docker."
msgid "HarborRegistry|With the Harbor Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "Avec le Registre Harbor, chaque projet peut avoir son propre espace pour stocker des images. %{docLinkStart}Plus d’informations%{docLinkEnd}"
msgid "Hashed Storage must be enabled to use Geo"
-msgstr ""
+msgstr "Le Stockage haché doit être activé pour utiliser Geo"
msgid "Hashed repository storage paths"
msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
-msgstr ""
+msgstr "Le stockage haché ne peut plus être désactivé pour les nouveaux projets"
msgid "Header logo"
-msgstr ""
+msgstr "Logo d'en-tête"
msgid "Header logo was successfully removed."
msgstr ""
msgid "Header logo will be removed. Are you sure?"
-msgstr ""
+msgstr "Le logo d'en-tête sera supprimé. Êtesâ€vous sûr(e) ?"
msgid "Header message"
msgstr "Message d’enâ€tête"
msgid "HeaderAction|incident"
-msgstr ""
+msgstr "incident"
msgid "HeaderAction|issue"
-msgstr ""
+msgstr "ticket"
msgid "Headers"
-msgstr ""
+msgstr "En-têtes"
msgid "Heading 1"
-msgstr ""
+msgstr "Titre 1"
msgid "Heading 2"
-msgstr ""
+msgstr "Titre 2"
msgid "Heading 3"
-msgstr ""
+msgstr "Titre 3"
msgid "Heading 4"
-msgstr ""
+msgstr "Titre 4"
msgid "Health"
-msgstr ""
+msgstr "Santé"
msgid "Health Check"
msgstr "État des services"
@@ -19374,10 +19640,10 @@ msgid "Health information can be retrieved from the following endpoints. More in
msgstr "L’état des services peut être récupéré depuis les emplacements suivants. Plus d’information disponible."
msgid "Health status"
-msgstr ""
+msgstr "État de santé"
msgid "Health status cannot be edited because this issue is closed"
-msgstr ""
+msgstr "L'état de santé ne peut pas être modifié car ce ticket est fermé"
msgid "HealthCheck|Access token is"
msgstr "Le jeton d’accès est"
@@ -19392,34 +19658,34 @@ msgid "HealthCheck|Unhealthy"
msgstr "En mauvaise santé"
msgid "Hello %{name},"
-msgstr ""
+msgstr "Bonjour %{name},"
msgid "Hello, %{name}!"
-msgstr ""
+msgstr "Bonjour %{name} !"
msgid "Hello, %{username}!"
-msgstr ""
+msgstr "Bonjour %{username} !"
msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
-msgstr ""
+msgstr "%{handshake_emoji} Contribuez à GitLab : %{contribute_link}"
msgid "HelloMessage|%{magnifier_emoji} Create a new GitLab issue: %{new_issue_link}"
-msgstr ""
+msgstr "%{magnifier_emoji} Créez un nouveau ticket GitLab : %{new_issue_link}"
msgid "HelloMessage|%{rocket_emoji} We like your curiosity! Help us improve GitLab by joining the team: %{jobs_page_link}"
-msgstr ""
+msgstr "%{rocket_emoji} Nous apprécions votre curiosité ! Aidez-nous à améliorer GitLab en rejoignant l'équipe : %{jobs_page_link}"
msgid "HelloMessage|Does this page need fixes or improvements? Open an issue or contribute a merge request to help make GitLab more lovable. At GitLab, everyone can contribute!"
-msgstr ""
+msgstr "Cette page doit-elle être corrigée ou améliorée ? Ouvrez un ticket ou contribuez à une demande de fusion pour rendre GitLab plus agréable. Chez GitLab, tout le monde peut contribuer !"
msgid "HelloMessage|Welcome to GitLab!"
-msgstr ""
+msgstr "Bienvenue sur GitLab !"
msgid "Help"
msgstr "Aide"
msgid "Help translate GitLab into your language"
-msgstr ""
+msgstr "Aidez-nous à traduire GitLab dans votre langue"
msgid "Helps prevent bots from brute-force attacks."
msgstr ""
@@ -19431,28 +19697,28 @@ msgid "Helps prevent bots from creating accounts. %{link_start}How do I configur
msgstr ""
msgid "Helps prevent bots from creating issues."
-msgstr ""
+msgstr "Contribue à empêcher la création de tickets par des bots."
msgid "Helps prevent malicious users hide their activity."
-msgstr ""
+msgstr "Contribue à empêcher des utilisateurs malveillants de cacher leur activité."
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
-msgstr ""
+msgstr "Contribue à réduire le volume de requêtes (celles de robots d'exploration ou de bots abusifs par exemple)"
msgid "Helps reduce request volume for protected paths."
-msgstr ""
+msgstr "Aide à réduire le volume de demandes pour les chemins d'accès protégés."
msgid "Hi %{username}!"
-msgstr ""
+msgstr "Bonjour %{username}!"
msgid "Hi %{username},"
-msgstr ""
+msgstr "Bonjour %{username},"
msgid "Hidden"
msgstr ""
msgid "Hide"
-msgstr ""
+msgstr "Masquer"
msgid "Hide Live Preview"
msgstr ""
@@ -19466,10 +19732,10 @@ msgstr[0] ""
msgstr[1] ""
msgid "Hide comments"
-msgstr ""
+msgstr "Masquer les commentaires"
msgid "Hide comments on this file"
-msgstr ""
+msgstr "Masquer les commentaires de ce fichier"
msgid "Hide details"
msgstr ""
@@ -19487,7 +19753,7 @@ msgid "Hide list"
msgstr ""
msgid "Hide marketing-related entries from the Help page"
-msgstr ""
+msgstr "Masquer les entrées liées au marketing de la page d'Aide"
msgid "Hide payload"
msgstr "Masquer la charge utile"
@@ -19499,7 +19765,7 @@ msgid "Hide thread"
msgstr ""
msgid "Hide tooltips or popovers"
-msgstr ""
+msgstr "Masquer les info-bulles et les boîtes flottantes"
msgid "Hide value"
msgid_plural "Hide values"
@@ -19510,31 +19776,31 @@ msgid "Hide values"
msgstr ""
msgid "Hierarchy|Current structure"
-msgstr ""
+msgstr "Structure actuelle"
msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
-msgstr ""
+msgstr "Apporter de la valeur ajoutée en répartissant les tâches essentielles à travers une structure hiérarchique. Cette structure contribue à aider les équipes à comprendre la portée, les priorités, et la façon dont le travail se répercute sur des objectifs plus larges."
msgid "Hierarchy|Help us improve work items in GitLab!"
-msgstr ""
+msgstr "Aidez-nous à améliorer les éléments de travail dans GitLab !"
msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
-msgstr ""
+msgstr "Y a-t-il un framework ou un type d'élément de travail auquel vous souhaitez avoir accès sur GitLab ? Donnez-nous vos commentaires et aidez-nous à construire les expériences qui vous sont précieuses."
msgid "Hierarchy|Planning hierarchy"
-msgstr ""
+msgstr "Hiérarchie de planification"
msgid "Hierarchy|Take the work items survey"
-msgstr ""
+msgstr "Répondre à l'enquête sur les éléments de travail"
msgid "Hierarchy|These items are unavailable in the current structure."
-msgstr ""
+msgstr "Ces éléments ne sont pas disponibles dans la structure actuelle."
msgid "Hierarchy|Unavailable structure"
-msgstr ""
+msgstr "Structure non disponible"
msgid "Hierarchy|You can start using these items now."
-msgstr ""
+msgstr "Vous pouvez commencer à utiliser ces éléments dès maintenant."
msgid "High or unknown vulnerabilities present"
msgstr ""
@@ -19543,19 +19809,19 @@ msgid "Highest role:"
msgstr ""
msgid "HighlightBar|Alert events:"
-msgstr ""
+msgstr "Événements d’alerte :"
msgid "HighlightBar|Alert start time:"
-msgstr ""
+msgstr "Heure de début de l'alerte :"
msgid "HighlightBar|Original alert:"
-msgstr ""
+msgstr "Alerte originale :"
msgid "HighlightBar|Time to SLA:"
msgstr ""
msgid "Historical release"
-msgstr ""
+msgstr "Version de l'historique"
msgid "History"
msgstr "Historique"
@@ -19564,13 +19830,13 @@ msgid "History of authentications"
msgstr ""
msgid "Holder name:"
-msgstr ""
+msgstr "Nom du titulaire :"
msgid "Home page URL"
-msgstr ""
+msgstr "URL de la page d'accueil"
msgid "Homepage"
-msgstr ""
+msgstr "Page d'accueil"
msgid "Hook execution failed. Ensure the group has a project with commits."
msgstr ""
@@ -19582,13 +19848,13 @@ msgid "Horizontal rule"
msgstr ""
msgid "Hostname"
-msgstr ""
+msgstr "Nom d’hôte"
msgid "Hostname used in private commit emails. %{learn_more}"
-msgstr ""
+msgstr "Nom d'hôte utilisé dans les courriels de validation privés. %{learn_more}"
msgid "Hour (UTC)"
-msgstr ""
+msgstr "Heure (UTC)"
msgid "Housekeeping"
msgstr ""
@@ -19597,7 +19863,7 @@ msgid "Housekeeping successfully started"
msgstr "Maintenance démarrée avec succès"
msgid "How do I configure Akismet?"
-msgstr ""
+msgstr "Comment configurer Akismet ?"
msgid "How do I configure this integration?"
msgstr ""
@@ -19606,34 +19872,34 @@ msgid "How do I generate it?"
msgstr ""
msgid "How do I mirror repositories?"
-msgstr ""
+msgstr "Comment puis-je faire des miroirs de dépôts ?"
msgid "How do I rename an environment?"
-msgstr ""
+msgstr "Comment renommer un environnement ?"
msgid "How do I set up a Google Chat webhook?"
-msgstr ""
+msgstr "Comment configurer un crochet Google Chat ?"
msgid "How do I set up this service?"
-msgstr ""
+msgstr "Comment puis-je mettre en place ce service ?"
msgid "How do I use a web terminal?"
-msgstr ""
+msgstr "Comment utiliser un terminal Web ?"
msgid "How do I use file templates?"
-msgstr ""
+msgstr "Comment utiliser les modèles de fichiers ?"
msgid "How does pull mirroring work?"
-msgstr ""
+msgstr "Comment fonctionne le pull mirroring ?"
msgid "How many seconds an IP counts toward the IP address limit."
msgstr ""
msgid "How the job limiter handles jobs exceeding the thresholds specified below. The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and raises an exception if the compressed size exceeds the limit."
-msgstr ""
+msgstr "Comment le limiteur de tâches gère celles qui dépassent les seuils spécifiés ci-dessous. Le mode « suivi » enregistre uniquement les tâches. Le mode « compression » compresse les tâches et déclenche une exception si la taille compressée dépasse la limite."
msgid "How to track time"
-msgstr ""
+msgstr "Comment suivre le temps"
msgid "I accept the %{terms_link}"
msgstr "J’accepte les %{terms_link}"
@@ -19642,10 +19908,10 @@ msgid "I forgot my password"
msgstr ""
msgid "I want to explore GitLab to see if it’s worth switching to"
-msgstr ""
+msgstr "Je souhaite découvrir GitLab pour voir s'il est intéressant d'y passer"
msgid "I want to learn the basics of Git"
-msgstr ""
+msgstr "Je souhaite apprendre les bases de Git"
msgid "I want to move my repository to GitLab from somewhere else"
msgstr ""
@@ -19660,7 +19926,7 @@ msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "I'm signing up for GitLab because:"
-msgstr ""
+msgstr "Je m'inscris sur GitLab car :"
msgid "ID"
msgstr "Identifiant"
@@ -19669,7 +19935,7 @@ msgid "ID:"
msgstr ""
msgid "IDE"
-msgstr ""
+msgstr "IDE"
msgid "IDE|Back"
msgstr "Retour"
@@ -19678,7 +19944,7 @@ msgid "IDE|Commit"
msgstr "Valider"
msgid "IDE|Commit to %{branchName} branch"
-msgstr ""
+msgstr "Valider sur la branche %{branchName}"
msgid "IDE|Edit"
msgstr "Modifier"
@@ -19702,22 +19968,22 @@ msgid "IDE|Review"
msgstr "Examiner"
msgid "IDE|Start a new merge request"
-msgstr ""
+msgstr "Démarrer une nouvelle demande de fusion"
msgid "IDE|Successful commit"
msgstr ""
msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
-msgstr ""
+msgstr "Cette option est désactivée car vous n'êtes pas autorisé à créer des demandes de fusion sur ce projet."
msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
-msgstr ""
+msgstr "Cette option est désactivée car vous n'avez pas les droits d'écriture sur la branche actuelle."
msgid "INFO: Your SSH key has expired. Please generate a new key."
-msgstr ""
+msgstr "INFO : Votre clé SSH a expiré. Veuillez générer une nouvelle clé."
msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
-msgstr ""
+msgstr "INFO : Votre clé SSH expire bientôt. Veuillez générer une nouvelle clé."
msgid "IP Address"
msgstr "Adresse IP"
@@ -19729,7 +19995,7 @@ msgid "IP address restrictions"
msgstr ""
msgid "IP addresses per user"
-msgstr ""
+msgstr "Adresses IP par utilisateur"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr ""
@@ -19746,86 +20012,119 @@ msgstr ""
msgid "Identities"
msgstr "Identités"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "Un nouveau code a été envoyé."
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
-msgstr ""
+msgstr "Avant de créer votre groupe, nous avons besoin de vérifiiez votre identité avec un mode de paiement valide. Vous ne serez pas débité lors de cette étape. Si jamais nous avons besoin de vous facturer, nous vous le ferons savoir."
+
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "Avant que vous ne terminiez la création de votre compte, nous devons vérifier votre identité. Sur la page de vérification, entrez le code suivant."
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
-msgstr ""
+msgstr "Avant que vous ne vous connectiez, nous devons vérifier votre identité. Entrez le code suivant sur la page de connexion."
+
+msgid "IdentityVerification|Confirm your email address"
+msgstr "Confirmez votre adresse de courriel"
msgid "IdentityVerification|Create a project"
-msgstr ""
+msgstr "Créer un projet"
+
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "Vous n'avez pas reçu de code ?"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "Entrez un code."
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "Entrez un code valide."
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
-msgstr ""
+msgstr "Pour une sécurité accrue, vous devez vérifier votre identité en quelques étapes rapides."
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
-msgstr ""
+msgstr "Pour plus de sécurité, vous devrez vérifier votre identité. Nous avons envoyé un code de vérification à %{email}"
+
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr "GitLab n'effectuera aucun prélèvement ni ne stockera vos informations de paiement, elles ne seront utilisées que pour la vérification."
msgid "IdentityVerification|Help us keep GitLab secure"
-msgstr ""
+msgstr "Aidez-nous à assurer la sécurité de GitLab"
msgid "IdentityVerification|Help us protect your account"
-msgstr ""
+msgstr "Aidez-nous à protéger votre compte"
msgid "IdentityVerification|If you have not recently tried to sign into GitLab, we recommend %{password_link_start}changing your password%{link_end} and %{two_fa_link_start}setting up Two-Factor Authentication%{link_end} to keep your account safe. Your verification code expires after %{expires_in_minutes} minutes."
-msgstr ""
+msgstr "Si vous n'avez pas essayé de vous connecter à GitLab récemment, nous vous conseillons de %{password_link_start}modifier votre mot de passe%{link_end} et de %{two_fa_link_start}configurer l'Authentification à Deux Facteurs%{link_end} afin de garder votre compte sécurisé. Votre code de vérification expire dans %{expires_in_minutes} minutes."
msgid "IdentityVerification|If you have not recently tried to sign into GitLab, we recommend changing your password (%{password_link}) and setting up Two-Factor Authentication (%{two_fa_link}) to keep your account safe."
-msgstr ""
+msgstr "Si vous n'avez pas essayé de vous connecter à GitLab récemment, nous vous conseillons de modifier votre mot de passe (%{password_link}) et de configurer l'Authentification à Deux Facteurs (%{two_fa_link}) afin de garder votre compte sécurisé."
msgid "IdentityVerification|If you've lost access to the email associated to this account or having trouble with the code, %{link_start}here are some other steps you can take.%{link_end}"
-msgstr ""
+msgstr "Si vous avez perdu l'accès à l'adresse de courriel associée à ce compte ou si vous rencontrez des difficultés avec le code, %{link_start}voici quelques autres étapes que vous pouvez suivre.%{link_end}"
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "Indicatif téléphonique international"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
-msgstr ""
+msgstr "Le nombre maximal de tentatives de connexion a été dépassé. Attendez %{interval} et réessayez."
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "Numéro de téléphone"
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "Le numéro de téléphone ne peut pas être vide."
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
-msgstr ""
+msgstr "Le numéro de téléphone doit contenir %{maxLength} chiffres ou moins."
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "Le numéro de téléphone ne doit contenir que des chiffres."
msgid "IdentityVerification|Please enter a valid code"
-msgstr ""
+msgstr "Veuillez entrer un code valide"
msgid "IdentityVerification|Resend code"
-msgstr ""
+msgstr "Renvoyer le code"
+
+msgid "IdentityVerification|Send a new code"
+msgstr "Envoyer un nouveau code"
msgid "IdentityVerification|Send code"
-msgstr ""
+msgstr "Envoyer un code"
+
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr "Une erreur s'est produite. Veuillez réessayer."
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr "Étape 1 : Vérifier le numéro de téléphone"
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr "Le code a expiré. Envoyez un nouveau code et réessayez."
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr "Le code est incorrect. Saisissez-le de nouveau, ou envoyez un nouveau code."
msgid "IdentityVerification|Verification code"
-msgstr ""
+msgstr "Code de vérification"
msgid "IdentityVerification|Verification successful"
-msgstr ""
+msgstr "Vérification réussie"
msgid "IdentityVerification|Verify code"
-msgstr ""
+msgstr "Vérifier le code"
+
+msgid "IdentityVerification|Verify email address"
+msgstr "Vérifier l'adresse de courriel"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "Méthode de vérification de paiement"
msgid "IdentityVerification|Verify your identity"
-msgstr ""
+msgstr "Vérifiez votre identité"
msgid "IdentityVerification|You can always verify your account at a later time to create a group."
msgstr ""
@@ -19833,23 +20132,26 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "Le nombre maximum d'envois a été atteint. Patientez %{interval} et réessayez."
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr "Vous avez atteint le nombre maximal d'essais. Attendez %{interval} ou envoyez un nouveau code et réessayez."
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "Votre compte a été vérifié avec succès. Vous serez redirigé vers votre compte dans quelques instants. Vous pouvez également %{redirect_url_start}rafraîchir la page%{redirect_url_end}."
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
-msgstr ""
+msgstr "Votre code de vérification va expirer dans %{expires_in_minutes} minutes."
msgid "Identity|Provider ID"
-msgstr ""
+msgstr "ID du fournisseur"
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 ""
+msgstr "Si un champ indexé dépasse cette limite, il sera tronqué à ce nombre de caractères. Le contenu restant ne sera ni indexé ni accessible aux recherches. Cela ne s'applique pas à l'indexation du dépôt ou du wiki. Définir cette valeur à 0 signifie qu'il n'y a pas de limite."
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
-msgstr ""
+msgstr "Si vide, %{code_open}Réessayez plus tard%{code_close} par défaut."
msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
msgstr ""
@@ -19864,25 +20166,25 @@ msgid "If disabled, a diverged local branch will not be automatically updated wi
msgstr ""
msgid "If disabled, only administrators can configure repository mirroring."
-msgstr ""
+msgstr "Si cette option est désactivée, seuls les administrateurs peuvent configurer la mise en miroir du dépôt."
msgid "If enabled, only protected branches will be mirrored."
-msgstr ""
+msgstr "Si activé, seules les branches protégées seront mises en miroir."
msgid "If no options are selected, only administrators can register runners."
-msgstr ""
+msgstr "Si aucune option n'est sélectionnée, seuls les administrateurs peuvent enregistrer des exécuteurs."
msgid "If none of the options work, try contacting a GitLab administrator."
-msgstr ""
+msgstr "Si aucune de ces options ne fonctionne, essayez de contacter un administrateur GitLab."
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
-msgstr ""
+msgstr "Si le nombre d'utilisateurs actifs dépasse la limite définie, une quantité de %{users_over_license_link} vous sera facturée lors du prochain rapprochement de votre licence."
msgid "If this email was added in error, you can remove it here:"
-msgstr ""
+msgstr "Si ce courriel a été ajouté par erreur, vous pouvez le supprimer ici :"
msgid "If this email was added in error, you can remove it here: %{profile_emails_url}"
-msgstr ""
+msgstr "Si ce courriel a été ajouté par erreur, vous pouvez le supprimer ici : %{profile_emails_url}"
msgid "If this is a mistake, you can %{link_start}unban them%{link_end}."
msgstr ""
@@ -19900,37 +20202,46 @@ msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commit
msgstr "Si vous utilisez GitHub, vous verrez les statuts des pipelines sur GitHub pour vos commits et demandes d’intégration (pull requests). %{more_info_link}"
msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
-msgstr ""
+msgstr "Si vous ajoutez des %{codeStart}nécessités%{codeEnd} aux tâches de votre pipeline, vous serez en mesure de voir les relations des %{codeStart}nécessités%{codeEnd} entre tâches dans cet onglet en tant que %{linkStart}Graphe orienté acyclique (DAG)%{linkEnd}."
msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
msgstr ""
msgid "If you did not initiate this change, please contact your administrator immediately."
-msgstr ""
+msgstr "Si vous n'êtes pas à l'origine de cette modification, veuillez contacter votre administrateur immédiatement."
msgid "If you did not perform this request, you can safely ignore this email."
-msgstr ""
+msgstr "Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce courriel en toute sécurité."
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
-msgstr ""
+msgstr "Si vous ne vous êtes pas connecté récemment, vous devriez immédiatement %{password_link_start}modifier votre mot de passe%{password_link_end}."
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr "Si vous ne vous êtes pas connecté récemment, vous devriez immédiatement modifier votre mot de passe : %{password_link}."
+
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
msgstr ""
-msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
+msgstr "Si les vérifications de dépôt vous renvoient de nombreuses fausses alertes, vous pouvez supprimer de la base de données toutes les informations de vérification de dépôt."
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr "Si vous vous êtes connecté récemment et que vous reconnaissez l'adresse IP, vous pouvez ignorer ce courriel."
+
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
msgstr ""
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
-msgstr ""
+msgstr "Si vous souhaitez réactiver l'authentification à deux facteurs, consultez %{two_factor_link}"
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
-msgstr ""
+msgstr "Si vous souhaitez réactiver l'authentification à deux facteurs, visitez la page %{settings_link_to}."
msgid "If you want to remove this email address, visit %{profile_link}"
msgstr ""
@@ -19939,7 +20250,7 @@ msgid "If you want to remove this email address, visit the %{settings_link_to} p
msgstr ""
msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
-msgstr ""
+msgstr "Si vous avez acheté ou renouvelé votre abonnement et que vous disposez d'un code d'activation, veuillez le saisir ci-dessous pour lancer le processus d'activation."
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -19948,10 +20259,10 @@ msgid "Ignore"
msgstr ""
msgid "Ignored"
-msgstr ""
+msgstr "Ignoré"
msgid "Image URL"
-msgstr ""
+msgstr "URL de l'image"
msgid "ImageDiffViewer|2-up"
msgstr "côte à côte"
@@ -19969,13 +20280,13 @@ msgid "ImageViewerDimensions|W"
msgstr ""
msgid "Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior."
-msgstr ""
+msgstr "Les images dont les dimensions sont incorrectes ne sont pas redimensionnées automatiquement et peuvent provoquer des effets inattendus."
msgid "Impersonate"
-msgstr ""
+msgstr "Incarner"
msgid "Impersonation Tokens"
-msgstr ""
+msgstr "Jetons d'emprunt d'identité"
msgid "Impersonation has been disabled"
msgstr ""
@@ -19985,8 +20296,8 @@ msgstr "Importer"
msgid "Import %d compatible repository"
msgid_plural "Import %d compatible repositories"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Importer %d dépôt compatible"
+msgstr[1] "Importer %d dépôts compatibles"
msgid "Import %d repository"
msgid_plural "Import %d repositories"
@@ -20012,16 +20323,16 @@ msgid "Import from"
msgstr ""
msgid "Import from Jira"
-msgstr ""
+msgstr "Importer depuis Jira"
msgid "Import group"
msgstr ""
msgid "Import group from file"
-msgstr ""
+msgstr "Importer un groupe depuis un fichier"
msgid "Import groups"
-msgstr ""
+msgstr "Importer des groupes"
msgid "Import history"
msgstr ""
@@ -20030,7 +20341,7 @@ msgid "Import in progress"
msgstr "Importation en cours"
msgid "Import in progress. Refresh page to see newly added issues."
-msgstr ""
+msgstr "Importation en cours. Rafraîchir la page pour voir les tickets nouvellement ajoutés."
msgid "Import issues"
msgstr ""
@@ -20069,7 +20380,7 @@ msgid "Import requirements"
msgstr ""
msgid "Import started by: %{importInitiator}"
-msgstr ""
+msgstr "Importation démarrée par : %{importInitiator}"
msgid "Import tasks"
msgstr ""
@@ -20081,10 +20392,10 @@ msgid "Import timed out. Import took longer than %{import_jobs_expiration} secon
msgstr ""
msgid "ImportAProjectModal|Import from a project"
-msgstr ""
+msgstr "Importer depuis un projet"
msgid "ImportAProjectModal|Import members from another project"
-msgstr ""
+msgstr "Importer des membres depuis un autre projet"
msgid "ImportAProjectModal|Import project members"
msgstr ""
@@ -20096,7 +20407,7 @@ msgid "ImportAProjectModal|Successfully imported"
msgstr ""
msgid "ImportAProjectModal|Unable to import project members"
-msgstr ""
+msgstr "Impossible d’importer les membres du projet"
msgid "ImportAProjectModal|You're importing members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
@@ -20105,6 +20416,9 @@ msgid "ImportButtons|Connect repositories from"
msgstr "Connecter des dépôts provenant de"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
+msgstr "La limite de débit de %{provider} a été dépassée. Réessayez plus tard"
+
+msgid "ImportProjects|Advanced import settings"
msgstr ""
msgid "ImportProjects|Blocked import URL: %{message}"
@@ -20114,21 +20428,24 @@ msgid "ImportProjects|Error importing repository %{project_safe_import_url} into
msgstr ""
msgid "ImportProjects|Import repositories"
-msgstr ""
+msgstr "Importer des dépôts"
msgid "ImportProjects|Importing the project failed"
msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
-msgstr ""
+msgstr "L'importation du projet a échoué : %{reason}"
msgid "ImportProjects|Requesting namespaces failed"
-msgstr ""
+msgstr "L'interrogation des espaces de noms a échoué"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
+msgstr "Sélectionnez les dépôts que vous souhaitez importer"
+
+msgid "ImportProjects|The more information you select, the longer it will take to import"
msgstr ""
msgid "ImportProjects|The remote data could not be imported."
@@ -20141,45 +20458,45 @@ msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
msgid "Imported requirements"
-msgstr ""
+msgstr "Exigences importées"
msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Importation de %d dépôt"
+msgstr[1] "Importation de %d dépôts"
msgid "Importing..."
msgstr ""
msgid "Import|The repository could not be imported."
-msgstr ""
+msgstr "Le dépôt n'a pas pu être importé."
msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
-msgstr ""
+msgstr "Il n'y a pas de dépôt Git valide à cette URL. Si votre dépôt HTTP n'est pas publiquement accessible, vérifiez vos identifiants."
msgid "Improve customer support with Service Desk"
-msgstr ""
+msgstr "Améliorer le support client avec le Service d'Assistance"
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "En cas de miroir « pull », votre utilisateur sera l’auteur de tous les événements du flux d’activité résultant d’une mise à jour, comme la création de nouvelles branches ou les nouveaux commits poussés vers des branches existantes."
msgid "In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
-msgstr ""
+msgstr "Dans chaque exemple, remplacez %{code_start}TOKEN%{code_end} par le jeton de déclenchement que vous avez généré et remplacez %{code_start}REF_NAME%{code_end} par le nom de branche ou d'étiquette."
msgid "In progress"
-msgstr ""
+msgstr "En cours"
msgid "In the background, we're attempting to connect you again."
msgstr ""
msgid "In this page you will find information about the settings that are used in your current instance."
-msgstr ""
+msgstr "Sur cette page, vous trouverez des informations sur les paramètres utilisés par votre instance actuelle."
msgid "In use"
msgstr ""
msgid "InProductMarketing|%{organization_name} logo"
-msgstr ""
+msgstr "Logo de %{organization_name}"
msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
msgstr ""
@@ -20191,16 +20508,16 @@ msgid "InProductMarketing|%{strong_start}Executive level insights%{strong_end} â
msgstr ""
msgid "InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
-msgstr ""
+msgstr "%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
-msgstr ""
+msgstr "*GitLab*, nom : synonyme d'équipes efficaces"
msgid "InProductMarketing|...and you can get a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "...et vous pouvez obtenir un essai gratuit de GitLab Ultimate"
msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
msgstr ""
@@ -20212,52 +20529,52 @@ msgid "InProductMarketing|Access advanced features, build more efficiently, stre
msgstr ""
msgid "InProductMarketing|Access advanced features."
-msgstr ""
+msgstr "Accéder aux fonctionnalités avancées."
msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
msgstr ""
msgid "InProductMarketing|And finally %{deploy_link} a Python application."
-msgstr ""
+msgstr "Et pour terminer %{deploy_link} une application Python."
msgid "InProductMarketing|And many more..."
-msgstr ""
+msgstr "Et bien plus encore..."
msgid "InProductMarketing|Are your runners ready?"
-msgstr ""
+msgstr "Vos exécuteurs sont-ils prêts ?"
msgid "InProductMarketing|Automated security scans directly within GitLab"
-msgstr ""
+msgstr "Analyses de sécurité automatisées directement au sein de GitLab"
msgid "InProductMarketing|Be a DevOps hero"
msgstr ""
msgid "InProductMarketing|Beef up your security"
-msgstr ""
+msgstr "Renforcez votre sécurité"
msgid "InProductMarketing|Better code in less time"
msgstr ""
msgid "InProductMarketing|Blog"
-msgstr ""
+msgstr "Blog"
msgid "InProductMarketing|Break down silos to coordinate seamlessly across development, operations, and security with a consistent experience across the development lifecycle."
msgstr ""
msgid "InProductMarketing|Building for iOS? We've got you covered."
-msgstr ""
+msgstr "Construire pour iOS ? Nous avons ce qu'il vous faut."
msgid "InProductMarketing|Burn up/down charts"
msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
-msgstr ""
+msgstr "En définissant des propriétaires de code et en exigeant des approbations de fusion, la bonne personne examinera la bonne MR. Ceci est gagnant-gagnant : un code plus propre et un processus d'examen plus efficace."
msgid "InProductMarketing|Code owners"
-msgstr ""
+msgstr "Propriétaires du code"
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
-msgstr ""
+msgstr "Les propriétaires de code et les approbations de fusion requises font partie des éditions payantes de GitLab. Vous pouvez commencer une période d'essai de 30 jours de GitLab Ultimate et activer ces fonctionnalités en moins de 5 minutes sans avoir besoin de carte bancaire."
msgid "InProductMarketing|Code review analytics"
msgstr ""
@@ -20269,10 +20586,10 @@ msgid "InProductMarketing|Collaboration made easy"
msgstr ""
msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
-msgstr ""
+msgstr "Créez un exécuteur CI personnalisé en quelques clics"
msgid "InProductMarketing|Create a custom runner"
-msgstr ""
+msgstr "Créer un exécuteur personnalisé"
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
msgstr ""
@@ -20281,19 +20598,19 @@ msgid "InProductMarketing|Create well-defined workflows by using scoped labels o
msgstr ""
msgid "InProductMarketing|Create your first project!"
-msgstr ""
+msgstr "Créez votre premier projet !"
msgid "InProductMarketing|Define who owns specific files or directories, so the right reviewers are suggested when a merge request introduces changes to those files."
msgstr ""
msgid "InProductMarketing|Deliver Better Products Faster"
-msgstr ""
+msgstr "Livrez de Meilleurs Produits plus Rapidement"
msgid "InProductMarketing|Dependency scanning"
-msgstr ""
+msgstr "Analyse des dépendances"
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
-msgstr ""
+msgstr "Saviez-vous que les équipes qui utilisent GitLab sont bien plus efficaces ?"
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20302,19 +20619,19 @@ msgid "InProductMarketing|Discover Premium & Ultimate"
msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
-msgstr ""
+msgstr "Découvrez Premium & Ultimate."
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
-msgstr ""
+msgstr "Avez-vous un coéquipier qui serait parfait pour cette tâche ?"
msgid "InProductMarketing|Dynamic application security testing"
msgstr ""
msgid "InProductMarketing|Epics"
-msgstr ""
+msgstr "Épopées"
msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
-msgstr ""
+msgstr "Développez votre parcours DevOps avec un essai gratuit de GitLab"
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -20326,7 +20643,7 @@ msgid "InProductMarketing|Explore the power of GitLab CI/CD"
msgstr ""
msgid "InProductMarketing|Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20338,28 +20655,28 @@ msgid "InProductMarketing|Find out how your teams are really doing"
msgstr ""
msgid "InProductMarketing|Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
-msgstr ""
+msgstr "Découvrez si vos bibliothèques externes sont sûres. Exécutez des tâches d'analyse de dépendances qui vérifient la présence de vulnérabilités connues dans vos bibliothèques externes."
msgid "InProductMarketing|Follow our steps"
msgstr ""
msgid "InProductMarketing|Free 30-day trial"
-msgstr ""
+msgstr "Essai gratuit de 30 jours"
msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy."
-msgstr ""
+msgstr "Démarrez rapidement avec CI/CD en utilisant notre %{quick_start_link}. Commencez avec un exécuteur disponible puis créez un fichier de CI .yml - c'est vraiment aussi simple que cela."
msgid "InProductMarketing|Get our import guides"
msgstr ""
msgid "InProductMarketing|Get set up to build for iOS"
-msgstr ""
+msgstr "Mettez en place la construction pour iOS"
msgid "InProductMarketing|Get started today"
msgstr ""
msgid "InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required."
-msgstr ""
+msgstr "Débutez dès aujourd'hui avec un essai GitLab Ultimate de 30 jours, aucune carte de crédit n'est requise."
msgid "InProductMarketing|Get started with GitLab CI/CD"
msgstr ""
@@ -20368,25 +20685,25 @@ msgid "InProductMarketing|Get to know GitLab CI/CD"
msgstr ""
msgid "InProductMarketing|Get your team set up on GitLab"
-msgstr ""
+msgstr "Mettez votre équipe en place sur GitLab"
msgid "InProductMarketing|Git basics"
msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
-msgstr ""
+msgstr "des projets GitHub Enterprise vers GitLab"
msgid "InProductMarketing|GitLab is infrastructure agnostic (supporting GCP, AWS, Azure, OpenShift, VMWare, On Prem, Bare Metal, and more), offering a consistent workflow experience – irrespective of the environment."
-msgstr ""
+msgstr "GitLab est indépendant de l’infrastructure (prenant en charge GCP, AWS, Azure, OpenShift, VMWare, On Prem, Bare Metal etc), offrant une expérience de flux de travail cohérente, quel que soit l’environnement."
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 ""
+msgstr "GitLab propose des tests statiques de la sécurité des applications (SAST), des tests dynamiques de la sécurité des applications (DAST), des analyses de conteneurs ainsi que des analyses de dépendances pour contribuer à la livraison d'applications sécurisées et à la conformité des licences."
msgid "InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"
-msgstr ""
+msgstr "La CI/CD facilite le développement logiciel. Vous ne nous croyez pas ? Voici trois façons de l'utiliser pour un essai rapide (et concluant) :"
msgid "InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"
-msgstr ""
+msgstr "Les éditions payantes de GitLab sont conçues pour vous rendre, vous, votre équipe et votre application, plus efficaces et davantage en sécurité grâce à des fonctionnalités, qui, sans s'y limiter, comprennent :"
msgid "InProductMarketing|Give us one minute..."
msgstr ""
@@ -20395,79 +20712,79 @@ msgid "InProductMarketing|Go farther with GitLab"
msgstr ""
msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
-msgstr ""
+msgstr "Goldman Sachs est passé de 1 construction toutes les deux semaines à des milliers par jour"
msgid "InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}."
-msgstr ""
+msgstr "Vous avez une autre instance que vous souhaitez importer ? Voici notre %{import_link}."
msgid "InProductMarketing|Here's what you need to know"
-msgstr ""
+msgstr "Voici ce que vous devez savoir"
msgid "InProductMarketing|How (and why) mirroring makes sense"
-msgstr ""
+msgstr "De quelle manière (et pour quelle raison) la mise en miroir montre sa pertinence"
msgid "InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?"
-msgstr ""
+msgstr "Combien de temps nous faut-il pour clôturer des tickets/MR selon leurs types tels que demandes de fonctionnalités, bogues, dette technique, sécurité ?"
msgid "InProductMarketing|How many days does it take our team to complete various tasks?"
-msgstr ""
+msgstr "Combien de jours faut-il à notre équipe pour effectuer différentes tâches ?"
msgid "InProductMarketing|How to build and test faster"
msgstr ""
msgid "InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}."
-msgstr ""
+msgstr "Si vous ne souhaitez pas recevoir de courriels commerciaux directement de GitLab, %{marketing_preference_link}."
msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
-msgstr ""
+msgstr "Si vous ne souhaitez plus recevoir de courriels commerciaux de notre part,"
msgid "InProductMarketing|Import your project and code from GitHub, Bitbucket and others"
msgstr ""
msgid "InProductMarketing|Improve app security with a 30-day trial"
-msgstr ""
+msgstr "Améliorez la sécurité des applications grâce à un essai de 30 jours"
msgid "InProductMarketing|Improve code quality and streamline reviews"
-msgstr ""
+msgstr "Améliorez la qualité du code et rationalisez sa revue"
msgid "InProductMarketing|Increase Operational Efficiencies"
-msgstr ""
+msgstr "Augmenter l'Efficacité Opérationnelle"
msgid "InProductMarketing|Invite them to help out."
msgstr ""
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
-msgstr ""
+msgstr "Invitez vos collègues et commencez à livrer du code plus rapidement."
msgid "InProductMarketing|Invite your colleagues to join in less than one minute"
-msgstr ""
+msgstr "Invitez vos collègues à vous rejoindre en moins d'une minute"
msgid "InProductMarketing|Invite your colleagues today"
-msgstr ""
+msgstr "Invitez vos collègues aujourd'hui"
msgid "InProductMarketing|Invite your team in less than 60 seconds"
-msgstr ""
+msgstr "Invitez votre équipe en moins de 60 secondes"
msgid "InProductMarketing|Invite your team now"
msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
-msgstr ""
+msgstr "Invitez votre équipe dès aujourd'hui pour créer ensemble du code (et des processus) de meilleure qualité"
msgid "InProductMarketing|It's all in the stats"
msgstr ""
msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
-msgstr ""
+msgstr "Il est également possible de simplement %{external_repo_link} pour tirer profit de la CI/CD de GitLab."
msgid "InProductMarketing|Keep your code quality high by defining who should approve merge requests and how many approvals are required."
-msgstr ""
+msgstr "Maintenez une qualité de code élevée en définissant qui doit approuver les demandes de fusion et combien d'approbations sont requises."
msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
msgstr ""
msgid "InProductMarketing|Learn how to build for iOS"
-msgstr ""
+msgstr "Apprenez à construire pour iOS"
msgid "InProductMarketing|Lower cost of development"
msgstr ""
@@ -20476,7 +20793,7 @@ msgid "InProductMarketing|Make it easier to collaborate on high-level ideas by g
msgstr ""
msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
-msgstr ""
+msgstr "Prêt pour la transition ? Il est plus facile que vous ne le pensiez d'importer vos projets dans GitLab. Migrez %{github_link} or importez quelque chose %{bitbucket_link}."
msgid "InProductMarketing|Master the art of importing!"
msgstr ""
@@ -20491,58 +20808,58 @@ msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you
msgstr ""
msgid "InProductMarketing|Multiple required approvers"
-msgstr ""
+msgstr "Plusieurs approbateurs requis"
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
msgid "InProductMarketing|No credit card required."
-msgstr ""
+msgstr "Aucune carte de crédit requise."
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
msgid "InProductMarketing|Protect your web application by using DAST to examine for vulnerabilities in deployed environments."
-msgstr ""
+msgstr "Protégez votre application Web en utilisant DAST pour rechercher les vulnérabilités dans les environnements déployés."
msgid "InProductMarketing|Rapid development, simplified"
msgstr ""
msgid "InProductMarketing|Reduce Security & Compliance Risk"
-msgstr ""
+msgstr "Réduire les Risques de Sécurité et de Conformité"
msgid "InProductMarketing|Require multiple approvers on a merge request, so you know it's in good shape before it's merged."
msgstr ""
msgid "InProductMarketing|Roadmaps"
-msgstr ""
+msgstr "Feuilles de route"
msgid "InProductMarketing|Scoped labels"
-msgstr ""
+msgstr "Étiquettes à portée limitée"
msgid "InProductMarketing|Security that's integrated into your development lifecycle"
msgstr ""
msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
-msgstr ""
+msgstr "Il se peut que vous ne soyez pas prêt pour une transition complète vers un nouvel outil. Si nous n'êtes pas prêt pour y passer totalement, la %{mirroring_link} vous donne une solution sûre pour toujours utiliser votre outil actuel tout en essayant GitLab en parallèle."
msgid "InProductMarketing|Speed. Efficiency. Trust."
-msgstr ""
+msgstr "Vitesse. Efficacité. Confiance."
msgid "InProductMarketing|Spin up an autoscaling runner in GitLab"
-msgstr ""
+msgstr "Faire tourner un exécuteur à dimensionnement automatique dans GitLab"
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
-msgstr ""
+msgstr "Commencez un essai GitLab Ultimate aujourd'hui en moins d'une minute, sans avoir besoin de carte de crédit."
msgid "InProductMarketing|Start a Self-Managed trial"
-msgstr ""
+msgstr "Commencez un essai Auto-Géré"
msgid "InProductMarketing|Start a free trial"
msgstr ""
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
-msgstr ""
+msgstr "Commencer un essai gratuit de GitLab Ultimate – pas besoin de carte bancaire"
msgid "InProductMarketing|Start a trial"
msgstr ""
@@ -20554,19 +20871,19 @@ msgid "InProductMarketing|Start by importing your projects"
msgstr ""
msgid "InProductMarketing|Start with a GitLab Ultimate free trial"
-msgstr ""
+msgstr "Commencez avec un essai gratuit de GitLab Ultimate"
msgid "InProductMarketing|Start your trial now!"
-msgstr ""
+msgstr "Démarrer votre essai maintenant !"
msgid "InProductMarketing|Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!"
-msgstr ""
+msgstr "Commencez votre essai aujourd'hui pour réussir avec une application unique et découvrir gratuitement toutes les fonctionnalités de GitLab Ultimate !"
msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
-msgstr ""
+msgstr "Rationalisez la revue de code, voyez en un clin d'œil qui n'est pas disponible, communiquez via les commentaires ou par courriel et intégrez Slack afin que tout le monde soit sur la même page."
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20578,40 +20895,40 @@ msgid "InProductMarketing|Team members collaborating"
msgstr ""
msgid "InProductMarketing|Team up in GitLab for greater efficiency"
-msgstr ""
+msgstr "Faites équipe sur GitLab pour une plus grande efficacité"
msgid "InProductMarketing|Team work makes the dream work"
-msgstr ""
+msgstr "Le travail d'équipe fait du rêve une réalité"
msgid "InProductMarketing|Test, create, deploy"
msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
-msgstr ""
+msgstr "C'est tout ce qu'il faut pour démarrer avec GitLab, mais si vous travaillez avec Git pour la première fois, consultez nos %{basics_link} pour des conseils et astuces qui seront utiles pour débuter."
msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
-msgstr ""
+msgstr "Ceci est le courriel %{current_series} sur %{total_series} dans la série %{track}."
msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
-msgstr ""
+msgstr "Il s'agit du courriel %{current_series} sur %{total_series} des séries %{track}. Pour désactiver l'envoi de courriels de notification par votre instance GitLab locale, contactez votre administrateur, ou %{unsubscribe_link}."
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
-msgstr ""
+msgstr "Ticketmaster a réduit son temps de construction CI d'un facteur 15"
msgid "InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}."
msgstr ""
msgid "InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}."
-msgstr ""
+msgstr "Pour ne plus recevoir ces courriels de présentation, %{unsubscribe_link}."
msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
-msgstr ""
+msgstr "Pour comprendre et tirer le meilleur parti de GitLab, commencez par le début et %{project_link}. Dans GitLab, les dépôts font partie d'un projet, donc, après avoir créé votre projet, vous pouvez continuer et %{repo_link}."
msgid "InProductMarketing|Track completed issues in a chart, so you can see how a milestone is progressing at a glance."
msgstr ""
msgid "InProductMarketing|Try GitLab Ultimate for free"
-msgstr ""
+msgstr "Essayez GitLab Ultimate gratuitement"
msgid "InProductMarketing|Try it out"
msgstr ""
@@ -20620,10 +20937,10 @@ msgid "InProductMarketing|Try it yourself"
msgstr ""
msgid "InProductMarketing|Turn coworkers into collaborators"
-msgstr ""
+msgstr "Transformez vos collègues en collaborateurs"
msgid "InProductMarketing|Twitter"
-msgstr ""
+msgstr "Twitter"
msgid "InProductMarketing|Understand repository mirroring"
msgstr ""
@@ -20635,49 +20952,49 @@ msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
msgid "InProductMarketing|Use our AWS cloudformation template to spin up your runners in just a few clicks!"
-msgstr ""
+msgstr "Utilisez notre modèle AWS cloudformation pour faire tourner vos exécuteurs en quelques clics !"
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
-msgstr ""
+msgstr "Utilisé par plus de 100000 entreprises dans le monde entier :"
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
msgid "InProductMarketing|Want to get your iOS app up and running, including publishing all the way to TestFlight? Follow our guide to set up GitLab and fastlane to publish iOS apps to the App Store."
-msgstr ""
+msgstr "Vous voulez rendre votre application iOS opérationnelle et la lancer, en passant par l'étape de sa publication sur TestFlight ? Suivez notre guide pour configurer GitLab et fastlane pour mettre en ligne des applications iOS sur l'App Store."
msgid "InProductMarketing|Want to host GitLab on your servers?"
-msgstr ""
+msgstr "Vous souhaitez héberger GitLab sur vos serveurs ?"
msgid "InProductMarketing|Watch iOS building in action."
-msgstr ""
+msgstr "Voyez la construction iOS à l'œuvre."
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
-msgstr ""
+msgstr "Nous connaissons deux ou trois choses pour être efficace et nous ne pouvons pas les garder pour nous. Inscrivez-vous pour un essai gratuit de GitLab Ultimate et vos équipes seront à pied d'œuvre dès le premier jour."
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
msgid "InProductMarketing|When your team is on GitLab these answers are a click away."
-msgstr ""
+msgstr "Lorsque votre équipe est sur GitLab, ces réponses sont à portée de clic."
msgid "InProductMarketing|Working in GitLab = more efficient"
msgstr ""
msgid "InProductMarketing|YouTube"
-msgstr ""
+msgstr "YouTube"
msgid "InProductMarketing|Your software, deployed your way"
-msgstr ""
+msgstr "Votre logiciel, déployé à votre façon"
msgid "InProductMarketing|Your teams can be more efficient"
msgstr ""
msgid "InProductMarketing|comprehensive guide"
-msgstr ""
+msgstr "guide complet"
msgid "InProductMarketing|connect an external repository"
-msgstr ""
+msgstr "connecter un dépôt externe"
msgid "InProductMarketing|create a project"
msgstr ""
@@ -20698,7 +21015,7 @@ msgid "InProductMarketing|repository mirroring"
msgstr ""
msgid "InProductMarketing|set up a repo"
-msgstr ""
+msgstr "mettre en place un dépôt"
msgid "InProductMarketing|test and deploy"
msgstr ""
@@ -20710,34 +21027,34 @@ msgid "InProductMarketing|unsubscribe"
msgstr ""
msgid "InProductMarketing|update your preferences"
-msgstr ""
+msgstr "mettre à jour vos préférences"
msgid "InProductMarketing|using a CI/CD template"
-msgstr ""
+msgstr "en utilisant un modèle CI/CD"
msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
-msgstr ""
+msgstr "vous pouvez vous %{unsubscribe_link} à tout moment."
msgid "Inactive"
msgstr ""
msgid "Incident"
-msgstr ""
+msgstr "Incident"
msgid "Incident Management Limits"
msgstr ""
msgid "Incident details"
-msgstr ""
+msgstr "Détails de l'incident"
msgid "Incident template (optional)."
msgstr ""
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
-msgstr ""
+msgstr "%{hours} heures, %{minutes} minutes restantes"
msgid "IncidentManagement|%{minutes} minutes remaining"
-msgstr ""
+msgstr "%{minutes} minutes restantes"
msgid "IncidentManagement|Achieved SLA"
msgstr ""
@@ -20746,70 +21063,70 @@ msgid "IncidentManagement|Acknowledged"
msgstr ""
msgid "IncidentManagement|All"
-msgstr ""
+msgstr "Tout"
msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
-msgstr ""
+msgstr "Toutes les alertes promues en incidents sont automatiquement affichées dans la liste."
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 ""
+msgstr "Toutes les alertes promues en incidents sont automatiquement affichées dans la liste. Vous pouvez également créer un nouvel incident en utilisant le bouton ci-dessous."
msgid "IncidentManagement|An error occurred while fetching the incident status. Please reload the page."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de l'état de l'incident. Veuillez recharger la page."
msgid "IncidentManagement|An error occurred while updating the incident status. Please reload the page and try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de l'état de l'incident. Veuillez recharger la page et réessayer."
msgid "IncidentManagement|Assign paging status"
msgstr ""
msgid "IncidentManagement|Assignees"
-msgstr ""
+msgstr "Assigné(e)s"
msgid "IncidentManagement|Closed"
-msgstr ""
+msgstr "Fermé(s)"
msgid "IncidentManagement|Create incident"
-msgstr ""
+msgstr "Créer un incident"
msgid "IncidentManagement|Critical - S1"
-msgstr ""
+msgstr "Critique - S1"
msgid "IncidentManagement|Date created"
msgstr ""
msgid "IncidentManagement|Display your incidents in a dedicated view"
-msgstr ""
+msgstr "Afficher vos incidents dans une vue dédiée"
msgid "IncidentManagement|High - S2"
-msgstr ""
+msgstr "Élevée - S2"
msgid "IncidentManagement|Incident"
-msgstr ""
+msgstr "Incident"
msgid "IncidentManagement|Incidents"
-msgstr ""
+msgstr "Incidents"
msgid "IncidentManagement|Learn more about incident statuses"
-msgstr ""
+msgstr "En savoir plus sur les états des incidents"
msgid "IncidentManagement|Low - S4"
-msgstr ""
+msgstr "Basse - S4"
msgid "IncidentManagement|Medium - S3"
-msgstr ""
+msgstr "Moyenne - S3"
msgid "IncidentManagement|Missed SLA"
msgstr ""
msgid "IncidentManagement|No incidents to display."
-msgstr ""
+msgstr "Aucun incident à afficher."
msgid "IncidentManagement|None"
msgstr ""
msgid "IncidentManagement|Open"
-msgstr ""
+msgstr "Ouvert(s)"
msgid "IncidentManagement|Page your team with escalation policies"
msgstr ""
@@ -20818,10 +21135,10 @@ msgid "IncidentManagement|Paged"
msgstr ""
msgid "IncidentManagement|Published"
-msgstr ""
+msgstr "Publié(s)"
msgid "IncidentManagement|Published to status page"
-msgstr ""
+msgstr "Publié(s) sur la page d'état"
msgid "IncidentManagement|Resolved"
msgstr ""
@@ -20830,19 +21147,19 @@ msgid "IncidentManagement|Setting the status to Acknowledged or Resolved stops p
msgstr ""
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "Gravité"
msgid "IncidentManagement|Status"
msgstr ""
msgid "IncidentManagement|There are no closed incidents"
-msgstr ""
+msgstr "Il n’y a aucun incident fermé"
msgid "IncidentManagement|There was an error displaying the incidents."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’affichage des incidents."
msgid "IncidentManagement|Time to SLA"
-msgstr ""
+msgstr "Durée avant SLA"
msgid "IncidentManagement|Triggered"
msgstr ""
@@ -20851,55 +21168,55 @@ msgid "IncidentManagement|Unassigned"
msgstr "Non assigné(s)"
msgid "IncidentManagement|Unknown"
-msgstr ""
+msgstr "Inconnue"
msgid "IncidentManagement|Unpublished"
-msgstr ""
+msgstr "Non publié(s)"
msgid "IncidentManagement|Use escalation policies to automatically page your team when incidents are created."
-msgstr ""
+msgstr "Utilisez des politiques d'escalade pour notifier automatiquement votre équipe de la création d'incidents."
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
-msgstr ""
+msgstr "Activer le compte à rebours « durée avant SLA »"
msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
-msgstr ""
+msgstr "Ajustez les paramètres d'incident et mettez en place des intégrations d'outils externes pour mieux gérer les incidents."
msgid "IncidentSettings|Grafana integration"
-msgstr ""
+msgstr "Intégration de Grafana"
msgid "IncidentSettings|Incident settings"
-msgstr ""
+msgstr "Paramètres des incidents"
msgid "IncidentSettings|Incidents"
-msgstr ""
+msgstr "Incidents"
msgid "IncidentSettings|Introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer starts automatically when the incident is created, and sets a time limit for resolving the incident. When activated, the time to SLA countdown appears on all new incidents."
-msgstr ""
+msgstr "Introduire un compte à rebours dans les tickets d'incident pour mieux suivre les ententes de niveau de service (SLA). Le minuteur démarre automatiquement lorsque l'incident est créé et fixe une limite de temps pour la résolution de l'incident. Lorsqu'il est activé, le compte à rebours du temps avant SLA apparaît sur tous les nouveaux incidents."
msgid "IncidentSettings|PagerDuty integration"
-msgstr ""
+msgstr "Intégration de PagerDuty"
msgid "IncidentSettings|Time limit"
msgstr ""
msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
-msgstr ""
+msgstr "Le délai doit être un multiple de 15 minutes."
msgid "IncidentSettings|Time limit must be a valid number."
-msgstr ""
+msgstr "Le délai doit être un nombre valide."
msgid "IncidentSettings|Time limit must be greater than 0."
-msgstr ""
+msgstr "Le délai doit être supérieur à 0."
msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
-msgstr ""
+msgstr "Lorsqu'il est activé, cela s'applique à tous les nouveaux incidents du projet."
msgid "IncidentSettings|hours"
-msgstr ""
+msgstr "heures"
msgid "IncidentSettings|minutes"
-msgstr ""
+msgstr "minutes"
msgid "Incidents"
msgstr ""
@@ -20908,115 +21225,115 @@ msgid "Incidents|Add image details"
msgstr ""
msgid "Incidents|Add text or a link to display with your image. If you don't add either, the file name displays instead."
-msgstr ""
+msgstr "Ajouter un texte ou un lien avec votre image. Sans cela, le nom du fichier sera affiché à la place."
msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
-msgstr ""
+msgstr "Déposez ou %{linkStart}téléversez%{linkEnd} une capture d'écran de métriques pour la joindre à l'incident"
msgid "Incidents|Must start with http or https"
-msgstr ""
+msgstr "Doit commencer par http ou https"
msgid "Incident|Add new timeline event"
msgstr ""
msgid "Incident|Alert details"
-msgstr ""
+msgstr "Détails de l'alerte"
msgid "Incident|Are you sure you want to delete this event?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cet événement ?"
msgid "Incident|Are you sure you wish to delete this image?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer cette image ?"
msgid "Incident|Delete event"
-msgstr ""
+msgstr "Supprimer l'événement"
msgid "Incident|Delete image"
-msgstr ""
+msgstr "Supprimer l'image"
msgid "Incident|Deleting %{filename}"
-msgstr ""
+msgstr "Suppression de %{filename}"
msgid "Incident|Edit image text or link"
-msgstr ""
+msgstr "Modifier le lien ou le texte de l'image"
msgid "Incident|Editing %{filename}"
-msgstr ""
+msgstr "Modification de %{filename}"
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr ""
+msgstr "Erreur lors de la création d'un événement sur la chronologie des incidents : %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr ""
+msgstr "Erreur lors de la suppression d'un événement sur la chronologie des incidents : %{error}"
msgid "Incident|Error updating incident timeline event: %{error}"
-msgstr ""
+msgstr "Erreur lors de la mise à jour d'un événement sur la chronologie des incidents : %{error}"
msgid "Incident|Metrics"
-msgstr ""
+msgstr "Métriques"
msgid "Incident|No timeline items have been added yet."
msgstr ""
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "Sauvegarder et ajouter un autre événement"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création de l'événement de la chronologie des incidents."
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de l'événement de la chronologie des incidents."
msgid "Incident|Something went wrong while fetching incident timeline events."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des événements de la chronologie des incidents."
msgid "Incident|Something went wrong while updating the incident timeline event."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de l'événement de la chronologie des incidents."
msgid "Incident|Summary"
-msgstr ""
+msgstr "Résumé"
msgid "Incident|There was an issue loading alert data. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des données de l'alerte. Veuillez réessayer."
msgid "Incident|There was an issue loading incident data. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des données de l'incident. Veuillez réessayer."
msgid "Incident|Timeline"
msgstr ""
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "Texte de la chronologie"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "Texte de la chronologie..."
msgid "Include author name in notification email body"
msgstr ""
msgid "Include description in commit message"
-msgstr ""
+msgstr "Inclure la description dans le message du commit"
msgid "Include new features from all tiers."
-msgstr ""
+msgstr "Inclure les nouvelles fonctionnalités de toutes les éditions."
msgid "Include the name of the author of the issue, merge request or comment in the email body. By default, GitLab overrides the email sender's name. Some email servers don't support that option."
-msgstr ""
+msgstr "Inclure le nom de l'auteur du ticket, de la demande de fusion ou du commentaire dans le corps du courriel. Par défaut, GitLab remplace le nom de l'expéditeur du courriel. Certains serveurs de messagerie ne gèrent pas cette option."
msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
-msgstr ""
+msgstr "Inclure le nom d'utilisateur dans l'URL si nécessaire : %{code_open}https://nomutilisateur@gitlab.societe.fr/groupe/projet.git%{code_close}."
msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
-msgstr ""
+msgstr "Inclut les objets LFS. Chaque groupe ou projet peut outrepasser cette valeur. Définir à 0 pour pas de limite."
msgid "Includes an MVC structure to help you get started"
-msgstr ""
+msgstr "Contient une structure MVC pour vous aider à démarrer"
msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started"
-msgstr ""
+msgstr "Contient une structure MVC, un Gemfile et un Rakefile ainsi que bien d'autres choses pour vous aider à démarrer"
msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
-msgstr ""
+msgstr "Contient une structure MVC et des fichiers mvnw et pom.xml pour vous aider à démarrer"
msgid "Incoming email"
msgstr ""
@@ -21028,22 +21345,25 @@ msgid "Incompatible options set!"
msgstr ""
msgid "Incompatible project"
-msgstr ""
+msgstr "Projet incompatible"
msgid "Incomplete"
msgstr ""
msgid "Increase"
+msgstr "Augmenter"
+
+msgid "Indent line"
msgstr ""
msgid "Index"
-msgstr ""
+msgstr "Indexer"
msgid "Index all projects"
msgstr ""
msgid "Index deletion is canceled"
-msgstr ""
+msgstr "La suppression d'index est annulée"
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indique si l’exécuteur peut choisir des tâches sans étiquettes (tags)"
@@ -21052,43 +21372,43 @@ msgid "Inform users without uploaded SSH keys that they can't push over SSH unti
msgstr ""
msgid "Infrastructure"
-msgstr ""
+msgstr "Infrastructure"
msgid "Infrastructure Registry"
-msgstr ""
+msgstr "Registre d'Infrastructure"
msgid "Infrastructure as Code (IaC) Scanning"
-msgstr ""
+msgstr "Analyse de l'Infrastructure en tant que Code (IaC)"
msgid "InfrastructureRegistry|Copy Terraform Command"
-msgstr ""
+msgstr "Copier la Commande Terraform"
msgid "InfrastructureRegistry|Copy Terraform Setup Command"
-msgstr ""
+msgstr "Copier la Commande de Configuration Terraform"
msgid "InfrastructureRegistry|Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
-msgstr ""
+msgstr "Copiez et collez dans votre configuration Terraform, insérez les variables puis lancez Terraform init :"
msgid "InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour plus d'informations sur le registre Terraform, %{linkStart}consultez notre documentation%{linkEnd}."
msgid "InfrastructureRegistry|Infrastructure Registry"
-msgstr ""
+msgstr "Registre d'Infrastructure"
msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "Publiez et partagez vos modules. %{docLinkStart}Plus d'informations%{docLinkEnd}"
msgid "InfrastructureRegistry|Terraform"
-msgstr ""
+msgstr "Terraform"
msgid "InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab."
-msgstr ""
+msgstr "Les modules Terraform sont le principal moyen d'empaqueter et de réutiliser des configurations de ressources avec Terraform. En savoir plus sur la %{noPackagesLinkStart}création de modules Terraform%{noPackagesLinkEnd} dans GitLab."
msgid "InfrastructureRegistry|To authorize access to the Terraform registry:"
-msgstr ""
+msgstr "Pour autoriser l'accès au registre Terraform :"
msgid "InfrastructureRegistry|You have no Terraform modules in your project"
-msgstr ""
+msgstr "Vous n'avez aucun module Terraform dans votre projet"
msgid "Inherited"
msgstr ""
@@ -21112,43 +21432,43 @@ msgid "Input host keys manually"
msgstr "Entrer les clefs d’hôte manuellement"
msgid "Input the remote repository URL"
-msgstr ""
+msgstr "Entrez l'URL du dépôt distant"
msgid "Insert"
msgstr ""
msgid "Insert a %{rows}x%{cols} table."
-msgstr ""
+msgstr "Insérer un tableau %{rows}x%{cols}."
msgid "Insert a quote"
msgstr ""
msgid "Insert code"
-msgstr ""
+msgstr "Insérer du code"
msgid "Insert column after"
-msgstr ""
+msgstr "Insérer une colonne après"
msgid "Insert column before"
-msgstr ""
+msgstr "Insérer une colonne avant"
msgid "Insert image"
-msgstr ""
+msgstr "Insérer une image"
msgid "Insert link"
msgstr ""
msgid "Insert row after"
-msgstr ""
+msgstr "Insérer une ligne après"
msgid "Insert row before"
-msgstr ""
+msgstr "Insérer une ligne avant"
msgid "Insert suggestion"
msgstr ""
msgid "Insert table"
-msgstr ""
+msgstr "Insérer un tableau"
msgid "Insights"
msgstr ""
@@ -21157,19 +21477,19 @@ msgid "Insights|Configure a custom report for insights into your group processes
msgstr ""
msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr ""
+msgstr "Certains éléments ne sont pas visibles car des filtres ont été appliqués au projet via le fichier insights.yml (voir la configuration projects.only pour plus d'informations)."
msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr ""
+msgstr "Ce projet est masqué par un filtre du fichier insights.yml (voir la configuration projects.only pour plus d'informations)."
msgid "Install GitLab Runner and ensure it's running."
-msgstr ""
+msgstr "Installez GitLab Runner et assurez-vous qu'il est en cours d'exécution."
msgid "Install on clusters"
msgstr ""
msgid "Installation"
-msgstr ""
+msgstr "Installation"
msgid "Instance"
msgid_plural "Instances"
@@ -21180,97 +21500,100 @@ msgid "Instance Configuration"
msgstr ""
msgid "Instance access request"
-msgstr ""
+msgstr "Demande d'accès à l'instance"
msgid "Instance access request approved"
-msgstr ""
+msgstr "Demande d'accès à l'instance approuvée"
msgid "Instance access request rejected"
-msgstr ""
+msgstr "Demande d'accès à l'instance rejetée"
msgid "Instance administrators group already exists"
msgstr ""
msgid "Instance audit events"
-msgstr ""
+msgstr "Événements d'audit d'instance"
msgid "Instance overview"
-msgstr ""
+msgstr "Vue d'ensemble de l'instance"
msgid "Insufficient permissions"
-msgstr ""
+msgstr "Permissions insuffisantes"
msgid "Insufficient permissions for dast_configuration keyword"
-msgstr ""
+msgstr "Permissions insuffisantes pour le mot-clé dast_configuration"
msgid "Integration"
-msgstr ""
+msgstr "Intégration"
msgid "Integration Settings"
-msgstr ""
+msgstr "Paramètres d'intégration"
msgid "IntegrationEvents|A comment is added on a confidential issue"
-msgstr ""
+msgstr "Un commentaire est ajouté à un ticket confidentiel"
msgid "IntegrationEvents|A comment is added on an issue"
-msgstr ""
+msgstr "Un commentaire est ajouté à un ticket"
msgid "IntegrationEvents|A confidential issue is created, updated, or closed"
-msgstr ""
+msgstr "Un ticket confidentiel est créé, mis à jour ou fermé"
msgid "IntegrationEvents|A merge request is created, updated, or merged"
-msgstr ""
+msgstr "Une demande de fusion est créée, mise à jour ou fusionnée"
msgid "IntegrationEvents|A pipeline status changes"
-msgstr ""
+msgstr "L'état d'un pipeline change"
msgid "IntegrationEvents|A push is made to the repository"
-msgstr ""
+msgstr "Une poussée est faite vers le dépôt"
msgid "IntegrationEvents|A tag is pushed to the repository"
-msgstr ""
+msgstr "Une étiquette est poussée vers le dépôt"
msgid "IntegrationEvents|A wiki page is created or updated"
-msgstr ""
+msgstr "Une page wiki est créée ou mise à jour"
msgid "IntegrationEvents|An issue is created, updated, or closed"
-msgstr ""
+msgstr "Un ticket est créé, mis à jour ou fermé"
msgid "Integrations"
msgstr "Intégrations"
msgid "Integrations|%{integrationTitle}: active"
-msgstr ""
+msgstr "%{integrationTitle} : active"
msgid "Integrations|%{integration} settings saved and active."
-msgstr ""
+msgstr "Paramètres %{integration} enregistrés et actifs."
msgid "Integrations|%{integration} settings saved, but not active."
-msgstr ""
+msgstr "Paramètres %{integration} enregistrés mais non actifs."
msgid "Integrations|Active integrations"
-msgstr ""
+msgstr "Intégrations actives"
msgid "Integrations|Add an integration"
-msgstr ""
+msgstr "Ajouter une intégration"
msgid "Integrations|Add namespace"
-msgstr ""
+msgstr "Ajouter un espace de noms"
+
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr "L'ajout d'un espace de noms ne fonctionne que dans les navigateurs qui autorisent les cookies intersites. %{linkStart}En savoir plus%{linkEnd}."
msgid "Integrations|All details"
-msgstr ""
+msgstr "Tous les détails"
msgid "Integrations|All projects inheriting these settings will also be reset."
-msgstr ""
+msgstr "Tous les projets qui héritent de ces paramètres seront également réinitialisés."
msgid "Integrations|An error occurred while loading projects using custom settings."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des projets qui utilisent des paramètres personnalisés."
msgid "Integrations|An event will be triggered when one of the following items happen."
-msgstr ""
+msgstr "Un événement sera déclenché lorsqu'un des éléments suivants se produit."
msgid "Integrations|Branches for which notifications are to be sent"
-msgstr ""
+msgstr "Branches pour lesquelles des notifications doivent être envoyées"
msgid "Integrations|Clear if using a self-signed certificate."
msgstr ""
@@ -21282,220 +21605,229 @@ msgid "Integrations|Comment settings:"
msgstr ""
msgid "Integrations|Configure the scope of notifications."
-msgstr ""
+msgstr "Configurer la portée des notifications."
msgid "Integrations|Connection details"
-msgstr ""
+msgstr "Détails de la connexion"
msgid "Integrations|Connection failed. Check your integration settings."
-msgstr ""
+msgstr "La connexion a échoué. Vérifiez vos paramètres d'intégration."
msgid "Integrations|Connection successful."
-msgstr ""
+msgstr "Connexion réussie."
msgid "Integrations|Create new issue in Jira"
-msgstr ""
+msgstr "Créer un nouveau ticket dans Jira"
msgid "Integrations|Create new issue in ZenTao"
-msgstr ""
+msgstr "Créer un nouveau ticket dans ZenTao"
msgid "Integrations|Default settings are inherited from the group level."
-msgstr ""
+msgstr "Les paramètres par défaut sont hérités de ceux au niveau du groupe."
msgid "Integrations|Default settings are inherited from the instance level."
-msgstr ""
+msgstr "Les paramètres par défaut sont hérités de ceux au niveau de l'instance."
msgid "Integrations|Edit project alias"
-msgstr ""
+msgstr "Modifier l'alias du projet"
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
-msgstr ""
+msgstr "Activer les commandes de barre oblique GitLab.com dans un espace de travail Slack."
msgid "Integrations|Enable SSL verification"
-msgstr ""
+msgstr "Activer la vérification SSL"
msgid "Integrations|Enable comments"
msgstr ""
-msgid "Integrations|Enter your alias"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr "Entrez votre alias"
+
msgid "Integrations|Failed to link namespace. Please try again."
-msgstr ""
+msgstr "Échec de la liaison de l'espace de noms. Veuillez réessayer."
+
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr "Échec du chargement de l'ID de l'Application de Connexion Jira. Veuillez réessayer."
msgid "Integrations|Failed to load namespaces. Please try again."
-msgstr ""
+msgstr "Échec du chargement des espaces de noms. Veuillez réessayer."
msgid "Integrations|Failed to load subscriptions."
-msgstr ""
+msgstr "Échec du chargement des abonnements."
msgid "Integrations|Failed to sign in to GitLab."
-msgstr ""
+msgstr "Échec de la connexion à GitLab."
msgid "Integrations|Failed to unlink namespace. Please try again."
-msgstr ""
+msgstr "Échec de la dissociation de l'espace de noms. Veuillez réessayer."
+
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr "Échec de la mise à jour de la version de GitLab. Veuillez réessayer."
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
-msgstr ""
+msgstr "Les administrateurs de GitLab peuvent configurer des intégrations dont tous les groupes et projets vont hériter et que ceux-ci utiliseront par défaut. Ces intégrations s'appliquent à tous les groupes et projets qui n'ont pas déjà de paramètres personnalisés. Vous pouvez outrepasser les paramètres personnalisés d'un groupe ou d'un projet si les paramètres sont nécessaires à ce niveau. En savoir plus sur la %{integrations_link_start}gestion d'intégration au niveau de l'instance%{link_end}."
msgid "Integrations|GitLab administrators can set up integrations that all projects in a group inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a project if the settings are necessary at that level. Learn more about %{integrations_link_start}group-level integration management%{link_end}."
-msgstr ""
+msgstr "Les administrateurs de GitLab peuvent configurer des intégrations dont tous les groupes et projets vont hériter et que ceux-ci utiliseront par défaut. Ces intégrations s'appliquent à tous les projets qui n'ont pas déjà de paramètres personnalisés. Vous pouvez outrepasser les paramètres personnalisés d'un projet si les paramètres sont nécessaires à ce niveau. En savoir plus sur la %{integrations_link_start}gestion d'intégration au niveau du groupe%{link_end}."
msgid "Integrations|Group-level integration management"
-msgstr ""
+msgstr "Gestion d'intégration au niveau du groupe"
msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
-msgstr ""
+msgstr "Inclus Standard, plus le message de commit, le hash de commit et les IDs des tickets"
msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Instance-level integration management"
-msgstr ""
+msgstr "Gestion d'intégration au niveau de l'instance"
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
-msgstr ""
+msgstr "Les tickets créés dans Jira sont affichés ici une fois que vous avez créé les tickets dans la configuration du projet sur Jira."
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
-msgstr ""
+msgstr "Gardez vos dépendances PHP à jour sur Packagist."
msgid "Integrations|Known limitations"
-msgstr ""
+msgstr "Limitations connues"
msgid "Integrations|Link namespaces"
-msgstr ""
+msgstr "Lier des espaces de noms"
msgid "Integrations|Linked namespaces"
-msgstr ""
+msgstr "Espaces de noms liés"
msgid "Integrations|Namespace successfully linked"
-msgstr ""
+msgstr "Espace de noms lié avec succès"
msgid "Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance."
-msgstr ""
+msgstr "Les espaces de noms sont les groupes et sous-groupes de GitLab que vous reliez à cette instance de Jira."
msgid "Integrations|No available namespaces."
-msgstr ""
+msgstr "Aucun espace de noms disponible."
msgid "Integrations|No linked namespaces"
-msgstr ""
+msgstr "Aucun espace de noms lié"
msgid "Integrations|Notification settings"
-msgstr ""
+msgstr "Paramètres de notification"
msgid "Integrations|Projects using custom settings"
-msgstr ""
+msgstr "Projets utilisant des paramètres personnalisés"
msgid "Integrations|Projects using custom settings will not be affected."
-msgstr ""
+msgstr "Les projets utilisant des paramètres personnalisés ne seront pas affectés."
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
-msgstr ""
+msgstr "Les projets utilisant des paramètres personnalisés ne seront pas impactés à moins que le propriétaire du projet ne choisisse d'utiliser les paramètres par défaut du niveau parent."
msgid "Integrations|Reset integration?"
-msgstr ""
+msgstr "Réinitialiser l’intégration ?"
msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
-msgstr ""
+msgstr "La réinitialisation de cette intégration effacera ses paramètres et la désactivera."
msgid "Integrations|Restrict to branch (optional)"
-msgstr ""
+msgstr "Restreindre à une branche (facultatif)"
msgid "Integrations|Return to GitLab for Jira"
-msgstr ""
+msgstr "Retourner à GitLab pour Jira"
msgid "Integrations|SSL verification"
-msgstr ""
+msgstr "Vérification SSL"
msgid "Integrations|Save settings?"
-msgstr ""
+msgstr "Enregistrer les paramètres ?"
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
-msgstr ""
+msgstr "L'enregistrement mettra à jour les paramètres par défaut pour tous les projets qui n'utilisent pas de paramètres personnalisés."
msgid "Integrations|Search Jira issues"
-msgstr ""
+msgstr "Rechercher des tickets Jira"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "Rechercher des tickets ZenTao"
msgid "Integrations|Send notifications about project events to Unify Circuit."
-msgstr ""
+msgstr "Envoie des notifications sur les événements du projet vers Unify Circuit."
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "Se connecter à %{url}"
msgid "Integrations|Sign in to GitLab"
-msgstr ""
+msgstr "Se connecter à GitLab"
msgid "Integrations|Sign in to add namespaces"
-msgstr ""
+msgstr "Connectez-vous pour ajouter des espaces de noms"
msgid "Integrations|Standard"
msgstr ""
msgid "Integrations|There are no projects using custom settings"
-msgstr ""
+msgstr "Aucun projet n'utilise de paramètres personnalisés"
msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Cette intégration ne fonctionne qu'avec GitLab.com. L'ajout d'un espace de noms ne fonctionne que dans les navigateurs qui autorisent les cookies intersites. %{linkStart}En savoir plus%{linkEnd}."
msgid "Integrations|This integration, and inheriting projects were reset."
-msgstr ""
+msgstr "Cette intégration et les projets qui en héritent ont été réinitialisés."
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
msgid "Integrations|Trigger"
-msgstr ""
+msgstr "Déclencheur"
msgid "Integrations|Use custom settings"
-msgstr ""
+msgstr "Utiliser des paramètres personnalisés"
msgid "Integrations|Use default settings"
-msgstr ""
+msgstr "Utiliser les paramètres par défaut"
msgid "Integrations|You can close this window."
-msgstr ""
+msgstr "Vous pouvez fermer cette fenêtre."
msgid "Integrations|You can use this alias in your Slack commands"
-msgstr ""
+msgstr "Vous pouvez utiliser cet alias dans vos commandes Slack"
msgid "Integrations|You haven't activated any integrations yet."
-msgstr ""
+msgstr "Vous n'avez pas encore activé d'intégration."
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
-msgstr ""
+msgstr "Vous devez disposer des permissions de propriétaire ou de mainteneur pour lier des espaces de noms."
msgid "Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app."
-msgstr ""
+msgstr "Vous devez employer un %{linkStart}navigateur pris en charge%{linkEnd} afin d'utiliser l'application GitLab pour Jira."
msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Vous devriez à présent voir l'activité de GitLab.com dans vos tickets Jira Cloud. %{linkStart}En savoir plus%{linkEnd}"
msgid "Integrations|You've activated every integration 🎉"
-msgstr ""
+msgstr "Vous avez activé chaque intégration 🎉"
msgid "Integrations|Your browser is not supported"
-msgstr ""
+msgstr "Votre navigateur n'est pas pris en charge"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
msgid "Integrations|can't exceed %{recipients_limit}"
-msgstr ""
+msgstr "ne peut pas dépasser %{recipients_limit}"
msgid "IntelliJ IDEA (HTTPS)"
-msgstr ""
+msgstr "IntelliJ IDEA (HTTPS)"
msgid "IntelliJ IDEA (SSH)"
-msgstr ""
+msgstr "IntelliJ IDEA (SSH)"
msgid "Interactive mode"
-msgstr ""
+msgstr "Mode interactif"
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr "Les personnes intéressées peuvent même contribuer en poussant des commits si elles le souhaitent."
@@ -21504,16 +21836,16 @@ msgid "Internal"
msgstr ""
msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
+msgstr "Interne - Le groupe et tous les projets internes peuvent être vus par tout utilisateur connecté, à l'exception des utilisateurs externes."
msgid "Internal - The project can be accessed by any logged in user except external users."
msgstr ""
msgid "Internal error occurred while delivering this webhook."
-msgstr ""
+msgstr "Une erreur interne est survenue lors de l'exécution de ce webhook."
msgid "Internal note"
-msgstr ""
+msgstr "Note interne"
msgid "Internal users"
msgstr "Utilisateurs internes"
@@ -21527,26 +21859,23 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Modèle d’intervalle"
-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 ""
+msgstr "Présentation de Vos Rapports DevOps"
msgid "Invalid"
-msgstr ""
+msgstr "Non valide"
msgid "Invalid Insights config file detected"
msgstr ""
msgid "Invalid OS"
-msgstr ""
+msgstr "OS non valide"
msgid "Invalid URL"
msgstr ""
msgid "Invalid URL: %{url}"
-msgstr ""
+msgstr "URL non valide : %{url}"
msgid "Invalid date"
msgstr ""
@@ -21555,7 +21884,7 @@ msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
msgstr ""
msgid "Invalid date range"
-msgstr ""
+msgstr "Plage de dates non valide"
msgid "Invalid feature"
msgstr ""
@@ -21564,7 +21893,7 @@ msgid "Invalid field"
msgstr ""
msgid "Invalid file format with specified file type"
-msgstr ""
+msgstr "Format de fichier non valide avec le type de fichier spécifié"
msgid "Invalid file."
msgstr ""
@@ -21573,7 +21902,7 @@ msgid "Invalid format selected"
msgstr ""
msgid "Invalid hash"
-msgstr ""
+msgstr "Hash non valide"
msgid "Invalid import params"
msgstr ""
@@ -21585,28 +21914,28 @@ msgid "Invalid login or password"
msgstr ""
msgid "Invalid period"
-msgstr ""
+msgstr "Période non valide"
msgid "Invalid pin code."
-msgstr ""
+msgstr "Code PIN non valide."
msgid "Invalid policy type"
-msgstr ""
+msgstr "Type de politique non valide"
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
-msgstr ""
+msgstr "Bundle de dépôt non valide pour l'extrait d'id %{snippet_id}"
msgid "Invalid repository path"
msgstr ""
msgid "Invalid rule"
-msgstr ""
+msgstr "Règle non valide"
msgid "Invalid server response"
msgstr ""
msgid "Invalid status"
-msgstr ""
+msgstr "État non valide"
msgid "Invalid two-factor code."
msgstr ""
@@ -21615,7 +21944,7 @@ msgid "Invalid yaml"
msgstr ""
msgid "Investigate vulnerability: %{title}"
-msgstr ""
+msgstr "Enquête sur la vulnérabilité : %{title}"
msgid "Invisible Captcha"
msgstr ""
@@ -21627,10 +21956,10 @@ msgid "Invitation"
msgstr ""
msgid "Invitation declined"
-msgstr ""
+msgstr "Invitation refusée"
msgid "Invite \"%{email}\" by email"
-msgstr ""
+msgstr "Inviter « %{email} » par courriel"
msgid "Invite \"%{trimmed}\" by email"
msgstr ""
@@ -21639,7 +21968,7 @@ msgid "Invite Members"
msgstr "Inviter des membres"
msgid "Invite a group"
-msgstr ""
+msgstr "Inviter un groupe"
msgid "Invite members"
msgstr "Inviter des membres"
@@ -21651,79 +21980,79 @@ msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_o
msgstr ""
msgid "InviteEmail|%{project_or_group} details"
-msgstr ""
+msgstr "Détails du %{project_or_group}"
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Les groupes rassemblent des projets apparentés et accordent aux membres des accès à plusieurs projets en même temps."
msgid "InviteEmail|Join now"
-msgstr ""
+msgstr "Rejoindre maintenant"
msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
-msgstr ""
+msgstr "Rejoignez votre équipe sur GitLab ! %{inviter} vous a invité sur %{project_or_group_name}"
msgid "InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}"
msgstr ""
msgid "InviteEmail|Projects are used to host and collaborate on code, track issues, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
-msgstr ""
+msgstr "Les projets sont utilisés pour héberger et collaborer sur du code, suivre les tickets ainsi que construire, tester et déployer en continu votre application grâce à GitLab CI/CD qui est intégré."
msgid "InviteEmail|What's it about?"
-msgstr ""
+msgstr "De quoi s'agit-il ?"
msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "Vous avez été invité(e) à rejoindre le %{project_or_group} %{project_or_group_name} en tant que %{role}"
msgid "InviteEmail|You were assigned the following tasks:"
msgstr ""
msgid "InviteEmail|and has assigned you the following tasks:"
-msgstr ""
+msgstr "et vous a assigné les tâches suivantes :"
msgid "InviteMembersBanner|Collaborate with your team"
-msgstr ""
+msgstr "Collaborer avec votre équipe"
msgid "InviteMembersBanner|Invite your colleagues"
-msgstr ""
+msgstr "Invitez vos collègues"
msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
-msgstr ""
+msgstr "Nous avons remarqué que vous n’avez invité personne dans ce groupe. Invitez vos collègues afin de pouvoir discuter des tickets, collaborer sur les demandes de fusion et partager vos connaissances."
msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "Pour bénéficier de plus de membres et accéder à des fonctionnalités payantes supplémentaires, un propriétaire de ce groupe peut commencer une période d'essai ou faire une mise à niveau vers une offre payante."
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
-msgstr ""
+msgstr "%{linkStart}En savoir plus%{linkEnd} sur les permissions des rôles"
msgid "InviteMembersModal|Access expiration date (optional)"
-msgstr ""
+msgstr "Date d'expiration de l'accès (facultatif)"
msgid "InviteMembersModal|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "InviteMembersModal|Choose a project for the issues"
-msgstr ""
+msgstr "Choisissez un projet pour les tickets"
msgid "InviteMembersModal|Close invite team members"
-msgstr ""
+msgstr "Fermer Inviter des membres de l'équipe"
msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
-msgstr ""
+msgstr "Félicitations pour la création de votre projet, vous y êtes presque !"
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
-msgstr ""
+msgstr "Créer des tickets pour que le nouveau membre de votre équipe travaille dessus (facultatif)"
msgid "InviteMembersModal|Explore paid plans"
-msgstr ""
+msgstr "Découvrir les forfaits payants"
msgid "InviteMembersModal|GitLab is better with colleagues!"
-msgstr ""
+msgstr "GitLab, c'est mieux avec des collègues !"
msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
-msgstr ""
+msgstr "Que diriez-vous d'inviter un ou deux collègues à vous rejoindre ?"
msgid "InviteMembersModal|Invite"
msgstr "Inviter"
@@ -21735,16 +22064,16 @@ msgid "InviteMembersModal|Invite members"
msgstr "Inviter des membres"
msgid "InviteMembersModal|Manage members"
-msgstr ""
+msgstr "Gérer les membres"
msgid "InviteMembersModal|Members were successfully added"
-msgstr ""
+msgstr "Les membres ont été ajoutés avec succès"
msgid "InviteMembersModal|Please select members or type email addresses to invite"
-msgstr ""
+msgstr "Veuillez sélectionner des membres ou saisir des adresses de courriel à inviter"
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "Examinez les erreurs d'invitation et réessayez :"
msgid "InviteMembersModal|Search for a group to invite"
msgstr "Rechercher un groupe à inviter"
@@ -21753,72 +22082,72 @@ msgid "InviteMembersModal|Select a group to invite"
msgstr "Sélectionnez un groupe à inviter"
msgid "InviteMembersModal|Select a role"
-msgstr ""
+msgstr "Sélectionnez un rôle"
msgid "InviteMembersModal|Select members or type email addresses"
-msgstr ""
+msgstr "Sélectionnez des membres ou tapez des adresses de courriel"
msgid "InviteMembersModal|Show less"
-msgstr ""
+msgstr "Afficher moins"
msgid "InviteMembersModal|Show more (%{count})"
-msgstr ""
+msgstr "Afficher plus (%{count})"
msgid "InviteMembersModal|Something went wrong"
-msgstr ""
+msgstr "Une erreur s'est produite"
msgid "InviteMembersModal|The following member couldn't be invited"
msgid_plural "InviteMembersModal|The following %d members couldn't be invited"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le membre suivant n'a pas pu être invité"
+msgstr[1] "Les %d membres suivants n'ont pas pu être invités"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
-msgstr ""
+msgstr "Cette fonctionnalité est désactivée jusqu'à ce que ce groupe ait suffisamment d'espace pour plus de membres."
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 ""
+msgstr "Pour assigner des tickets à un nouveau membre de l'équipe, vous avez besoin d'un projet pour ceux-ci. %{linkStart}Créez un projet pour commencer.%{linkEnd}"
msgid "InviteMembersModal|To get more members an owner of the group can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-msgstr ""
+msgstr "Pour pouvoir avoir davantage de membres, un propriétaire de ce groupe peut %{trialLinkStart}commencer une période d'essai%{trialLinkEnd} ou %{upgradeLinkStart}effectuer une mise à niveau%{upgradeLinkEnd} vers une offre payante."
msgid "InviteMembersModal|Username or email address"
-msgstr ""
+msgstr "Nom d’utilisateur ou adresse de messagerie"
msgid "InviteMembersModal|You cannot add more members, but you can remove members who no longer need access."
-msgstr ""
+msgstr "Vous ne pouvez pas ajouter plus de membres, mais vous pouvez supprimer ceux qui n’ont plus besoin d’accès."
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
-msgstr ""
+msgstr "Vous n'avez de place que pour %{count} %{members} de plus sur %{name}"
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "Vous invitez un groupe dans le groupe %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "Vous invitez un groupe dans le projet %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "Vous invitez des membres au groupe %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "Vous invitez des membres au projet %{strongStart}%{name}%{strongEnd}."
msgid "InviteMembersModal|You've reached your %{count} %{members} limit for %{name}"
-msgstr ""
+msgstr "Vous avez atteint votre limite de %{count} %{members} pour %{name}"
msgid "InviteMembers|Invite a group"
msgstr "Inviter un groupe"
msgid "InviteMembers|Invite team members"
-msgstr ""
+msgstr "Inviter des membres de l'équipe"
msgid "InviteMember|Add members to this project and start collaborating with your team."
-msgstr ""
+msgstr "Ajouter des membres à ce projet et commencer à travailler avec votre équipe."
msgid "InviteMember|Invite Members (optional)"
-msgstr ""
+msgstr "Inviter des membres (facultatif)"
msgid "InviteMember|Invite another member"
-msgstr ""
+msgstr "Inviter un autre membre"
msgid "InviteMember|Invite members"
msgstr "Inviter des membres"
@@ -21827,94 +22156,94 @@ msgid "InviteMember|Invite your team"
msgstr ""
msgid "InviteMember|Invited users will be added with developer level permissions. %{linkStart}View the documentation%{linkEnd} to see how to change this later."
-msgstr ""
+msgstr "Les utilisateurs invités seront ajoutés avec des autorisations de niveau développeur. %{linkStart}Afficher la documentation%{linkEnd} pour voir comment modifier cela ultérieurement."
msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
-msgstr ""
+msgstr "%{inviter} attend toujours que vous rejoigniez GitLab"
msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
msgstr ""
msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
-msgstr ""
+msgstr "%{inviter} attend que vous rejoigniez le %{project_or_group} %{strong_start}%{project_or_group_name}%{strong_end} en tant que %{role}."
msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
-msgstr ""
+msgstr "L'invitation de %{inviter} à GitLab est en attente"
msgid "InviteReminderEmail|Accept invitation"
-msgstr ""
+msgstr "Accepter l'invitation"
msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
-msgstr ""
+msgstr "Accepter l’invitation : %{invite_url}"
msgid "InviteReminderEmail|Decline invitation"
-msgstr ""
+msgstr "Refuser l'invitation"
msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
-msgstr ""
+msgstr "Refuser l'invitation : %{decline_url}"
msgid "InviteReminderEmail|Hey there %{wave_emoji}"
-msgstr ""
+msgstr "Bonjour %{wave_emoji}"
msgid "InviteReminderEmail|Hey there!"
msgstr ""
msgid "InviteReminderEmail|In case you missed it..."
-msgstr ""
+msgstr "Au cas où vous ne l'auriez pas vu..."
msgid "InviteReminderEmail|Invitation pending"
-msgstr ""
+msgstr "Invitation en attente"
msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
-msgstr ""
+msgstr "Cela fait %{invitation_age} jours que %{inviter} vous a invité(e) à rejoindre le %{project_or_group} %{strong_start}%{project_or_group_name}%{strong_end} en tant que %{role}. Que souhaitez-vous faire ?"
msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
-msgstr ""
+msgstr "Ceci est pour vous rappeler que %{inviter} vous a invité à rejoindre le %{project_or_group} %{strong_start}%{project_or_group_name}%{strong_end} en tant que %{role}."
msgid "Invited"
msgstr ""
msgid "Invited group allowed email domains must contain a subset of the allowed email domains of the root ancestor group. Go to the group's 'Settings &gt; General' page and check 'Restrict membership by email domain'."
-msgstr ""
+msgstr "Les domaines de messagerie autorisés du groupe invité doivent contenir un sous-ensemble des domaines de messagerie autorisés du groupe au sommet de la hiérarchie. Allez à la page « Paramètres &gt; Général » du groupe et cochez « Restreindre l'adhésion par domaine de messagerie »."
msgid "IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}"
-msgstr ""
+msgstr "Canaux et utilisateurs séparés par des espaces. %{recipients_docs_link}"
msgid "IrkerService|Default IRC URI (optional)"
-msgstr ""
+msgstr "URI IRC par défaut (facultatif)"
msgid "IrkerService|How to enter channels or users?"
-msgstr ""
+msgstr "Comment saisir des canaux ou des utilisateurs ?"
msgid "IrkerService|Recipients"
-msgstr ""
+msgstr "Destinataires"
msgid "IrkerService|Send update messages to an irker server."
-msgstr ""
+msgstr "Envoyer des messages de mise à jour à un serveur irker."
msgid "IrkerService|Send update messages to an irker server. Before you can use this, you need to set up the irker daemon. %{docs_link}"
-msgstr ""
+msgstr "Envoyer des messages de mise à jour à un serveur irker. Avant de pouvoir l'utiliser, vous devez configurer le daemon irker. %{docs_link}"
msgid "IrkerService|Server host (optional)"
-msgstr ""
+msgstr "Hôte du serveur (facultatif)"
msgid "IrkerService|Server port (optional)"
msgstr ""
msgid "IrkerService|URI to add before each recipient."
-msgstr ""
+msgstr "URI à ajouter avant chaque destinataire."
msgid "IrkerService|irker (IRC gateway)"
-msgstr ""
+msgstr "irker (passerelle IRC)"
msgid "IrkerService|irker daemon hostname (defaults to localhost)."
-msgstr ""
+msgstr "nom d'hôte du daemon irker (localhost par défaut)."
msgid "IrkerService|irker daemon port (defaults to 6659)."
-msgstr ""
+msgstr "port du daemon irker (6659 par défaut)."
msgid "Is blocked by"
-msgstr ""
+msgstr "Est bloqué par"
msgid "Is using license seat:"
msgstr ""
@@ -21922,9 +22251,15 @@ msgstr ""
msgid "Is using seat"
msgstr ""
-msgid "IssuableStatus|%{wi_type} created %{created_at} by "
+msgid "IssuableEvents|removed review request for"
msgstr ""
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
+msgid "IssuableStatus|%{wi_type} created %{created_at} by "
+msgstr "%{wi_type} créé(e) %{created_at} par "
+
msgid "IssuableStatus|Closed"
msgstr "Fermé"
@@ -21947,31 +22282,31 @@ msgid "Issue"
msgstr "Ticket"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
-msgstr ""
+msgstr "Le ticket %{issue_reference} a déjà été ajouté à l'épopée %{epic_reference}."
msgid "Issue Analytics"
-msgstr ""
+msgstr "Analytique des tickets"
msgid "Issue Boards"
msgstr "Tableaux des tickets"
msgid "Issue Type"
-msgstr ""
+msgstr "Type de Ticket"
msgid "Issue already promoted to epic."
-msgstr ""
+msgstr "Le ticket a déjà été promu en épopée."
msgid "Issue cannot be found."
msgstr ""
msgid "Issue created from vulnerability %{vulnerability_link}"
-msgstr ""
+msgstr "Ticket créé à partir de la vulnérabilité %{vulnerability_link}"
msgid "Issue creation requests"
-msgstr ""
+msgstr "Demandes de création de ticket"
msgid "Issue details"
-msgstr ""
+msgstr "Détails du ticket"
msgid "Issue events"
msgstr "Événements du ticket"
@@ -21980,19 +22315,19 @@ msgid "Issue first deployed to production"
msgstr ""
msgid "Issue has been promoted to incident"
-msgstr ""
+msgstr "Le ticket a été promu en incident"
msgid "Issue label"
-msgstr ""
+msgstr "Etiquette du ticket"
msgid "Issue or merge request ID is required"
-msgstr ""
+msgstr "Un ID de ticket ou de demande de fusion est requis"
msgid "Issue published on status page."
-msgstr ""
+msgstr "Ticket publié sur la page d'état."
msgid "Issue types"
-msgstr ""
+msgstr "Types de ticket"
msgid "Issue update failed"
msgstr ""
@@ -22001,34 +22336,37 @@ msgid "Issue was closed by %{name} %{reason}"
msgstr "Le ticket a été fermé par %{name} %{reason}"
msgid "Issue weight"
-msgstr ""
+msgstr "Poids du ticket"
msgid "IssueAnalytics|Age"
-msgstr ""
+msgstr "Âge"
msgid "IssueAnalytics|Assignees"
-msgstr ""
+msgstr "Assigné(e)s"
msgid "IssueAnalytics|Created by"
msgstr "Créé par"
msgid "IssueAnalytics|Due date"
-msgstr ""
+msgstr "Date d'échéance"
msgid "IssueAnalytics|Failed to load issues. Please try again."
-msgstr ""
+msgstr "Impossible de charger les tickets. Veuillez réessayer."
msgid "IssueAnalytics|Issue"
-msgstr ""
+msgstr "Ticket"
+
+msgid "IssueAnalytics|Iteration"
+msgstr "Itération"
msgid "IssueAnalytics|Milestone"
msgstr "Jalon"
msgid "IssueAnalytics|Status"
-msgstr ""
+msgstr "État"
msgid "IssueAnalytics|Weight"
-msgstr ""
+msgstr "Poids"
msgid "IssueBoards|Board"
msgstr "Tableau"
@@ -22037,19 +22375,19 @@ msgid "IssueBoards|Boards"
msgstr "Tableaux"
msgid "IssueBoards|Create new board"
-msgstr ""
+msgstr "Créer un nouveau tableau"
msgid "IssueBoards|Delete board"
-msgstr ""
+msgstr "Supprimer le tableau"
msgid "IssueBoards|No matching boards found"
-msgstr ""
+msgstr "Aucun tableau correspondant trouvé"
msgid "IssueBoards|Some of your boards are hidden, add a license to see them again."
-msgstr ""
+msgstr "Certains de vos tableaux sont cachés, ajoutez une licence pour les voir de nouveau."
msgid "IssueBoards|Switch board"
-msgstr ""
+msgstr "Changer de tableau"
msgid "IssueList|created %{timeAgoString} by %{user}"
msgstr "créé %{timeAgoString} par %{user}"
@@ -22058,61 +22396,61 @@ msgid "IssueTracker|Custom issue tracker"
msgstr ""
msgid "IssueTracker|Issue URL"
-msgstr ""
+msgstr "URL du ticket"
msgid "IssueTracker|New issue URL"
-msgstr ""
+msgstr "URL de nouveau ticket"
msgid "IssueTracker|The URL to create an issue in the external issue tracker."
-msgstr ""
+msgstr "L'URL pour créer un ticket dans le gestionnaire de tickets externe."
msgid "IssueTracker|The URL to the project in the external issue tracker."
-msgstr ""
+msgstr "L’URL du projet dans le gestionnaire de tickets externe."
msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
-msgstr ""
+msgstr "L’URL pour afficher un ticket dans le gestionnaire de tickets externe. Doit contenir %{colon_id}."
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser Bugzilla comme gestionnaire de tickets pour ce projet."
msgid "IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "Utiliser Bugzilla comme gestionnaire de tickets pour ce projet. %{docs_link}"
msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser IBM Engineering Workflow Management comme gestionnaire de tickets pour ce projet."
msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "Utiliser IBM Engineering Workflow Management comme gestionnaire de tickets pour ce projet. %{docs_link}"
msgid "IssueTracker|Use Redmine as the issue tracker. %{docs_link}"
-msgstr ""
+msgstr "Utiliser Redmine comme gestionnaire de tickets. %{docs_link}"
msgid "IssueTracker|Use Redmine as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser Redmine comme gestionnaire de tickets pour ce projet."
msgid "IssueTracker|Use YouTrack as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser YouTrack comme gestionnaire de tickets pour ce projet."
msgid "IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "Utiliser YouTrack comme gestionnaire de tickets pour ce projet. %{docs_link}"
msgid "IssueTracker|Use a custom issue tracker as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser un gestionnaire de tickets personnalisé pour ce projet."
msgid "IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}"
-msgstr ""
+msgstr "Utiliser un gestionnaire de tickets personnalisé qui ne figure pas dans la liste des intégrations. %{docs_link}"
msgid "Issues"
msgstr "Tickets"
msgid "Issues Rate Limits"
-msgstr ""
+msgstr "Limites du Taux de Tickets"
msgid "Issues and merge requests"
-msgstr ""
+msgstr "Tickets et demandes de fusion"
msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
-msgstr ""
+msgstr "Les tickets sont en cours de rééquilibrage, la réorganisation manuelle est donc désactivée."
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discussion. De plus, les tickets sont consultables et filtrables."
@@ -22121,19 +22459,19 @@ msgid "Issues closed"
msgstr "Tickets clos"
msgid "Issues exist in projects, so to create an issue, first create a project."
-msgstr ""
+msgstr "Les tickets se trouvent dans les projets. Par conséquent, afin de créer un ticket, créez au préalable un projet."
msgid "Issues must match this scope to appear in this list."
-msgstr ""
+msgstr "Les tickets doivent être dans cette portée pour apparaître dans cette liste."
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
msgid "Issues with label %{label}"
-msgstr ""
+msgstr "Tickets avec l'étiquette %{label}"
msgid "Issues with no epic assigned"
-msgstr ""
+msgstr "Tickets sans épopée attribuée"
msgid "Issues, merge requests, pushes, and comments."
msgstr ""
@@ -22142,7 +22480,7 @@ msgid "IssuesAnalytics|After you begin creating issues for your projects, we can
msgstr "Une fois que vous aurez commencé à créer des tickets d’incident en relation avec vos projets, nous pourrons commencer à en effectuer le suivi et afficher des statistiques les concernant"
msgid "IssuesAnalytics|Avg/Month:"
-msgstr ""
+msgstr "Moyenne/Mois:"
msgid "IssuesAnalytics|Issues created"
msgstr "Tickets créés"
@@ -22163,118 +22501,118 @@ msgid "IssuesAnalytics|To widen your search, change or remove filters in the fil
msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des critères de recherche dans la barre de filtrage ciâ€dessus"
msgid "IssuesAnalytics|Total:"
-msgstr ""
+msgstr "Total :"
msgid "Issue|Title"
msgstr "Titre"
msgid "It is not possible to %{action} files that are stored in LFS using the web interface"
-msgstr ""
+msgstr "L'interface web ne permet pas de %{action} des fichiers qui sont enregistrés sur LFS"
msgid "It looks like you have some draft commits in this branch."
-msgstr ""
+msgstr "Il semble que vous ayez des brouillons de commits dans cette branche."
msgid "It looks like you're attempting to activate your subscription. Use %{a_start}the Subscription page%{a_end} instead."
msgstr ""
msgid "It may be several days before you see feature usage data."
-msgstr ""
+msgstr "Il peut s'écouler plusieurs jours avant de voir les données d'utilisation des fonctionnalités."
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
-msgstr ""
+msgstr "Il semble que la tâche d'analyse des dépendances ait été exécutée avec succès, mais aucune dépendance n'a été détectée dans votre projet."
msgid "It seems that there is currently no available data for code coverage"
-msgstr ""
+msgstr "Il semble n'y avoir actuellement aucune donnée disponible pour la couverture du code"
msgid "It's you"
msgstr ""
msgid "Italic text"
-msgstr ""
+msgstr "Texte en italique"
msgid "Iteration"
msgstr ""
msgid "Iteration cannot be created for cadence"
-msgstr ""
+msgstr "L'itération ne peut pas être créée pour la cadence"
msgid "Iteration changed to"
msgstr ""
msgid "Iteration lists not available with your current license"
-msgstr ""
+msgstr "Les listes d'itérations ne sont pas disponibles avec votre licence actuelle"
msgid "Iteration removed"
-msgstr ""
+msgstr "Itération supprimée"
msgid "Iteration updated"
msgstr ""
msgid "Iterations"
-msgstr ""
+msgstr "Itérations"
msgid "Iterations cadence not found"
-msgstr ""
+msgstr "Cadence d'itérations introuvable"
msgid "Iterations cannot be manually added to cadences that use automatic scheduling"
-msgstr ""
+msgstr "Des itérations ne peuvent pas être ajoutées manuellement à des cadences qui utilisent la planification automatique"
msgid "IterationsCadence|The automation start date must come after the active iteration %{iteration_dates}."
-msgstr ""
+msgstr "La date de début de l'automatisation doit être postérieure à l'itération active %{iteration_dates}."
msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
-msgstr ""
+msgstr "La date de début de l'automatisation doit être postérieure à l'itération active %{iteration_dates}."
msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
-msgstr ""
+msgstr "La date de début de l'automatisation créerait rétroactivement une itération dans le passé. %{start_date} est la date de début la plus ancienne possible."
msgid "Iterations|Add iteration"
-msgstr ""
+msgstr "Ajouter une itération"
msgid "Iterations|All"
msgstr ""
msgid "Iterations|All scheduled iterations will remain scheduled even if you use a smaller number."
-msgstr ""
+msgstr "Toutes les itérations planifiées resteront planifiées même si vous utilisez un nombre plus petit."
msgid "Iterations|Automatic scheduling"
-msgstr ""
+msgstr "Planification automatique"
msgid "Iterations|Automation start date"
-msgstr ""
+msgstr "Date de début de l'automatisation"
msgid "Iterations|Cadence configuration is invalid."
-msgstr ""
+msgstr "La configuration de cadence n’est pas valide."
msgid "Iterations|Cadence name"
-msgstr ""
+msgstr "Nom de la cadence"
msgid "Iterations|Cancel"
msgstr ""
msgid "Iterations|Couldn't find iteration cadence"
-msgstr ""
+msgstr "Impossible de trouver la cadence d'itération"
msgid "Iterations|Create cadence"
-msgstr ""
+msgstr "Créer une cadence"
msgid "Iterations|Create iteration"
msgstr ""
msgid "Iterations|Create iterations automatically on a regular schedule."
-msgstr ""
+msgstr "Créer automatiquement des itérations selon une planification périodique."
msgid "Iterations|Delete cadence"
-msgstr ""
+msgstr "Supprimer la cadence"
msgid "Iterations|Delete iteration cadence?"
-msgstr ""
+msgstr "Supprimer la cadence d'itération ?"
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "Supprimer l'itération ?"
msgid "Iterations|Description"
msgstr ""
@@ -22286,61 +22624,61 @@ msgid "Iterations|Due date"
msgstr ""
msgid "Iterations|Duration"
-msgstr ""
+msgstr "Durée"
msgid "Iterations|Edit cadence"
-msgstr ""
+msgstr "Modifier la cadence"
msgid "Iterations|Edit iteration"
-msgstr ""
+msgstr "Modifier l'itération"
msgid "Iterations|Edit iteration cadence"
-msgstr ""
+msgstr "Modifier la cadence d'itération"
msgid "Iterations|Enable automatic scheduling"
msgstr ""
msgid "Iterations|Enable roll over"
-msgstr ""
+msgstr "Activer la reconduction"
msgid "Iterations|Error loading iteration cadences."
-msgstr ""
+msgstr "Erreur lors du chargement des cadences d'itération."
msgid "Iterations|Iteration cadences"
-msgstr ""
+msgstr "Cadences d'itération"
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
msgstr ""
msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
-msgstr ""
+msgstr "Les itérations sont planifiées pour commencer les %{weekday}s."
msgid "Iterations|Move incomplete issues to the next iteration."
-msgstr ""
+msgstr "Déplacer les tickets non terminés vers l'itération suivante."
msgid "Iterations|New iteration"
-msgstr ""
+msgstr "Nouvelle itération"
msgid "Iterations|New iteration cadence"
-msgstr ""
+msgstr "Nouvelle cadence d'itération"
msgid "Iterations|No closed iterations."
-msgstr ""
+msgstr "Aucune itération fermée."
msgid "Iterations|No iteration cadences to show."
-msgstr ""
+msgstr "Aucune cadence d'itération à afficher."
msgid "Iterations|No iterations found"
msgstr ""
msgid "Iterations|No iterations in cadence."
-msgstr ""
+msgstr "Aucune itération dans la cadence."
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "Aucune itération ouverte."
msgid "Iterations|Number of upcoming iterations that should be scheduled at a time."
-msgstr ""
+msgstr "Nombre d'itérations à venir qui doivent être planifiées au même moment."
msgid "Iterations|Open"
msgstr ""
@@ -22352,28 +22690,28 @@ msgid "Iterations|Save changes"
msgstr ""
msgid "Iterations|Select duration"
-msgstr ""
+msgstr "Sélectionnez une durée"
msgid "Iterations|Select number"
-msgstr ""
+msgstr "Sélectionnez un nombre"
msgid "Iterations|Select start date"
-msgstr ""
+msgstr "Sélectionnez une date de début"
msgid "Iterations|Start date"
-msgstr ""
+msgstr "Date de début"
msgid "Iterations|The date of the first iteration to schedule. This date determines the day of the week when each iteration starts."
-msgstr ""
+msgstr "La date de la première itération à planifier. Cette date détermine quel jour de la semaine commence chaque itération."
msgid "Iterations|The duration of each iteration (in weeks)."
-msgstr ""
+msgstr "La durée de chaque itération (en semaines)."
msgid "Iterations|The iteration has been deleted."
-msgstr ""
+msgstr "L'itération a été supprimée."
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
-msgstr ""
+msgstr "Cela supprimera la cadence ainsi que toutes les itérations qu'elle contient."
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
msgstr ""
@@ -22382,25 +22720,22 @@ msgid "Iterations|Title"
msgstr "Titre"
msgid "Iterations|Unable to find iteration cadence."
-msgstr ""
+msgstr "Impossible de trouver la cadence d'itération."
msgid "Iterations|Unable to find iteration."
-msgstr ""
+msgstr "Impossible de trouver l'itération."
msgid "Iterations|Unable to save cadence. Please try again."
-msgstr ""
+msgstr "Impossible d'enregistrer la cadence. Veuillez réessayer."
msgid "Iterations|Upcoming iterations"
-msgstr ""
-
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
+msgstr "Itérations à venir"
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
-msgstr ""
+msgstr "Les dates ne peuvent pas chevaucher celles d'autres itérations existantes à l'intérieur de cette cadence d'itérations"
msgid "Iteration|cannot be more than 500 years in the future"
-msgstr ""
+msgstr "ne peut pas être plus de 500 ans dans le futur"
msgid "Jan"
msgstr "janv."
@@ -22415,265 +22750,265 @@ msgid "Jira display name"
msgstr ""
msgid "Jira import is already running."
-msgstr ""
+msgstr "L'importation Jira est déjà en cours d'exécution."
msgid "Jira integration not configured."
-msgstr ""
+msgstr "L'intégration de Jira n'est pas configurée."
msgid "Jira project key is not configured."
-msgstr ""
+msgstr "La clé du projet Jira n'est pas configurée."
msgid "Jira project: %{importProject}"
-msgstr ""
+msgstr "Projet Jira : %{importProject}"
msgid "Jira service not configured."
-msgstr ""
+msgstr "Le service Jira n'est pas configuré."
msgid "Jira user"
-msgstr ""
+msgstr "Utilisateur Jira"
msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
-msgstr ""
+msgstr "Les utilisateurs Jira ont été importés depuis l'instance Jira configurée. Ils peuvent être mappés en sélectionnant un utilisateur GitLab dans la liste déroulante dans la colonne « Nom d’utilisateur GitLab ». Quand le formulaire apparaît, la liste déroulante indique par défaut l'utilisateur qui effectue l'importation."
msgid "Jira-GitLab user mapping template"
-msgstr ""
+msgstr "Modèle d'association d'utilisateurs Jira-GitLab"
msgid "JiraConnect|Cannot find namespace. Make sure you have sufficient permissions."
-msgstr ""
+msgstr "Impossible de trouver l'espace de noms. Assurez-vous d'avoir les permissions suffisantes."
msgid "JiraConnect|Configure your Jira Connect Application ID."
-msgstr ""
+msgstr "Configurez l'ID de votre Application Jira Connect."
msgid "JiraConnect|Could not fetch user information from Jira. Check the permissions in Jira and try again."
-msgstr ""
+msgstr "Impossible de récupérer les informations utilisateur depuis Jira. Vérifiez les permissions dans Jira et réessayez."
msgid "JiraConnect|Create branch for Jira issue %{jiraIssue}"
msgstr ""
msgid "JiraConnect|Failed to create branch."
-msgstr ""
+msgstr "Échec de la création de la branche."
msgid "JiraConnect|Failed to create branch. Please try again."
-msgstr ""
+msgstr "Échec de la création de la branche. Veuillez réessayer."
msgid "JiraConnect|GitLab for Jira App"
msgstr ""
msgid "JiraConnect|Jira Connect Application ID"
-msgstr ""
+msgstr "ID de l'Application Jira Connect"
msgid "JiraConnect|New branch was successfully created."
-msgstr ""
+msgstr "La nouvelle branche a été créée avec succès."
msgid "JiraConnect|The Jira user is not a site administrator. Check the permissions in Jira and try again."
-msgstr ""
+msgstr "L'utilisateur Jira n'est pas un administrateur du site. Vérifiez les permissions dans Jira et réessayez."
msgid "JiraConnect|You can now close this window and return to Jira."
-msgstr ""
+msgstr "Vous pouvez maintenant fermer cette fenêtre et retourner dans Jira."
msgid "JiraConnect|You don't have permission to create branches for this project. Select a different project or contact the project owner for access. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Vous n'avez pas la permission de créer des branches pour ce projet. Sélectionnez un projet différent ou contactez son propriétaire pour y accéder. %{linkStart}En savoir plus.%{linkEnd}"
msgid "JiraRequest|A connection error occurred while connecting to Jira. Try your request again."
-msgstr ""
+msgstr "Une erreur de connexion s'est produite lors de la connexion à Jira. Réessayez votre demande."
msgid "JiraRequest|A timeout error occurred while connecting to Jira. Try your request again."
-msgstr ""
+msgstr "Une erreur de délai d'attente dépassé s'est produite lors de la connexion à Jira. Réessayez votre demande."
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
-msgstr ""
+msgstr "Une erreur SSL s'est produite lors de la connexion à Jira : %{message}. Réessayez votre demande."
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 "Une erreur s'est produite lors de la demande de données depuis Jira. Vérifiez la %{docs_link_start}configuration de votre intégration Jira%{docs_link_end} et réessayez."
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 "Une erreur s'est produite lors de la demande de données depuis Jira : %{messages}. Vérifiez la %{docs_link_start}configuration de votre intégration Jira%{docs_link_end} et réessayez."
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
-msgstr ""
+msgstr "L'URL de l'API Jira pour se connecter à Jira n'est pas valide. Vérifiez l'URL d'API de votre intégration Jira et réessayez."
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 "Les identifiants pour accéder à Jira ne donnent pas l'autorisation d'accéder aux données. Vérifiez les %{docs_link_start}identifiants de votre intégration Jira%{docs_link_end} et réessayez."
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 "Les identifiants pour accéder à Jira ne sont pas valides. Vérifiez les %{docs_link_start}identifiants de votre intégration Jira%{docs_link_end} et réessayez."
msgid "JiraService| on branch %{branch_link}"
msgstr ""
msgid "JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab."
-msgstr ""
+msgstr "%{jiraDocsLinkStart}Activer l'intégration de Jira%{jiraDocsLinkEnd} pour voir vos tickets Jira dans GitLab."
msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
-msgstr ""
+msgstr "%{jira_docs_link_start}Activez l'intégration Jira%{jira_docs_link_end} pour voir vos tickets Jira dans GitLab."
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
-msgstr ""
+msgstr "%{user_link} a mentionné ce ticket dans %{entity_link} de %{project_link}%{branch} : {quote}%{entity_message}{quote}"
msgid "JiraService|An error occurred while fetching issue list"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la liste de tickets"
msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Passer automatiquement les tickets Jira dans la catégorie « Terminé ». %{linkStart}En savoir plus%{linkEnd}"
msgid "JiraService|Base URL of the Jira instance."
-msgstr ""
+msgstr "URL de base de l'instance Jira."
msgid "JiraService|Change GitLab version"
msgstr ""
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
-msgstr ""
+msgstr "Définissez le type des tickets Jira qui seront créés à partir des vulnérabilités."
msgid "JiraService|Displaying Jira issues while leaving GitLab issues also enabled might be confusing. Consider %{gitlab_issues_link_start}disabling GitLab issues%{link_end} if they won't otherwise be used."
-msgstr ""
+msgstr "Afficher les tickets Jira tout en laissant aussi les tickets GitLab activés peut prêter à confusion. Envisagez de %{gitlab_issues_link_start}désactiver les tickets GitLab%{link_end} s'ils n'ont pas à être utilisés autrement."
msgid "JiraService|Enable Jira issue creation from vulnerabilities"
-msgstr ""
+msgstr "Activer la création de tickets Jira à partir de vulnérabilités"
msgid "JiraService|Enable Jira issues"
-msgstr ""
+msgstr "Activer les tickets Jira"
msgid "JiraService|Enable Jira transitions"
-msgstr ""
+msgstr "Activer les transitions Jira"
msgid "JiraService|Enter new password or API token"
-msgstr ""
+msgstr "Entrez un nouveau mot de passe ou un jeton d'API"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
-msgstr ""
+msgstr "Échec du chargement du ticket Jira. Affichez le ticket dans Jira ou rechargez la page."
msgid "JiraService|Fetch issue types for this Jira project"
-msgstr ""
+msgstr "Récupérer les types de tickets de ce projet Jira"
msgid "JiraService|For example, 12, 24"
-msgstr ""
+msgstr "Par exemple, 12, 24"
msgid "JiraService|For example, AB"
-msgstr ""
+msgstr "Par exemple, AB"
msgid "JiraService|For example: https://gitlab.example.com"
-msgstr ""
+msgstr "Par exemple : https://gitlab.exemple.com"
msgid "JiraService|GitLab for Jira Configuration"
-msgstr ""
+msgstr "Configuration de GitLab pour Jira"
msgid "JiraService|GitLab instance URL"
-msgstr ""
+msgstr "URL de l'instance GitLab"
msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
-msgstr ""
+msgstr "Les IDs doivent être une liste de nombres qui peuvent être séparés par , ou ;"
msgid "JiraService|If different from Web URL."
-msgstr ""
+msgstr "Si différent de l'URL Web."
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
-msgstr ""
+msgstr "Les tickets créés à partir des vulnérabilités de ce projet seront des tickets Jira, même si les tickets GitLab sont activés."
msgid "JiraService|Jira API URL"
msgstr ""
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
-msgstr ""
+msgstr "Les commentaires Jira sont créés lorsqu'un ticket est référencé dans un commit."
msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
-msgstr ""
+msgstr "Les commentaires Jira sont créés lorsqu'un ticket est référencé dans une demande de fusion."
msgid "JiraService|Jira issues"
-msgstr ""
+msgstr "Tickets Jira"
msgid "JiraService|Jira project key"
-msgstr ""
+msgstr "Clé de projet Jira"
msgid "JiraService|Leave blank to use your current password or API token."
-msgstr ""
+msgstr "Laissez vide pour utiliser votre mot de passe ou jeton d'API actuel."
msgid "JiraService|Move to Done"
-msgstr ""
+msgstr "Passer à Terminé"
msgid "JiraService|Open Jira"
-msgstr ""
+msgstr "Ouvrir Jira"
msgid "JiraService|Password or API token"
msgstr ""
msgid "JiraService|Project key changed, refresh list"
-msgstr ""
+msgstr "Clé de projet modifiée, actualiser la liste"
msgid "JiraService|Project key is required to generate issue types"
-msgstr ""
+msgstr "Une clé de projet est requise pour générer des types de tickets"
msgid "JiraService|Select issue type"
-msgstr ""
+msgstr "Sélectionner le type de ticket"
msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
-msgstr ""
+msgstr "Définissez un état final personnalisé à l'aide des IDs de transition. %{linkStart}En savoir plus sur les IDs de transition%{linkEnd}"
msgid "JiraService|Sign in to GitLab to link namespaces."
-msgstr ""
+msgstr "Connectez-vous à GitLab pour relier des espaces de noms."
msgid "JiraService|Sign in to GitLab.com to get started."
-msgstr ""
+msgstr "Connectez-vous à GitLab.com pour commencer."
msgid "JiraService|This feature requires a Premium plan."
-msgstr ""
+msgstr "Cette fonctionnalité nécessite un forfait Premium."
msgid "JiraService|Transition Jira issues to their final state:"
-msgstr ""
+msgstr "Passer les tickets Jira à leur état final :"
msgid "JiraService|Use Jira as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser Jira comme gestionnaire de tickets pour ce projet."
msgid "JiraService|Use a password for server version and an API token for cloud version."
-msgstr ""
+msgstr "Utiliser un mot de passe pour la version serveur et un jeton d'API pour la version Cloud."
msgid "JiraService|Use a username for server version and an email for cloud version."
-msgstr ""
+msgstr "Utiliser un nom d'utilisateur pour la version serveur et une adresse de courriel pour la version Cloud."
msgid "JiraService|Use custom transitions"
-msgstr ""
+msgstr "Utiliser des transitions personnalisées"
msgid "JiraService|Username or Email"
-msgstr ""
+msgstr "Nom d'utilisateur ou e-mail"
msgid "JiraService|Using Jira for issue tracking?"
-msgstr ""
+msgstr "Utiliser Jira pour le suivi des tickets ?"
msgid "JiraService|Warning: All GitLab users with access to this GitLab project can view all issues from the Jira project you select."
-msgstr ""
+msgstr "Avertissement : Tous les utilisateurs de GitLab qui ont accès à ce projet GitLab sont en mesure de voir tous les tickets du projet Jira que vous avez sélectionné."
msgid "JiraService|Web URL"
-msgstr ""
+msgstr "URL Web"
msgid "JiraService|Welcome to GitLab for Jira"
msgstr ""
msgid "JiraService|What version of GitLab are you using?"
-msgstr ""
+msgstr "Quelle version de GitLab utilisez-vous ?"
msgid "JiraService|When a Jira issue is mentioned in a commit or merge request, a remote link and comment (if enabled) will be created."
-msgstr ""
+msgstr "Lorsqu'un ticket Jira est mentionné dans un commit ou une demande de fusion, un lien et un commentaire distants (si activé) seront créés."
msgid "JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues."
-msgstr ""
+msgstr "Travailler sur les tickets Jira sans quitter GitLab. Ajoutez un menu Jira pour accéder à une liste en lecture seule de vos tickets Jira."
msgid "JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues. %{jira_issues_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Travailler sur les tickets Jira sans quitter GitLab. Ajoutez un menu Jira pour accéder à une liste en lecture seule de vos tickets Jira. %{jira_issues_link_start}En savoir plus.%{link_end}"
msgid "JiraService|You can now close this window and%{br}return to the GitLab for Jira application."
-msgstr ""
+msgstr "Vous pouvez maintenant fermer cette fenêtre et%{br}revenir à l’application GitLab pour Jira."
msgid "JiraService|You must configure Jira before enabling this integration. %{jira_doc_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Vous devez configurer Jira avant d'activer cette intégration. %{jira_doc_link_start}En savoir plus.%{link_end}"
msgid "Job"
msgstr "Tâche"
msgid "Job %{jobName}"
-msgstr ""
+msgstr "Tâche %{jobName}"
msgid "Job Failed #%{build_id}"
msgstr ""
@@ -22694,10 +23029,10 @@ msgid "Job logs and artifacts"
msgstr ""
msgid "Job to create self-monitoring project is in progress"
-msgstr ""
+msgstr "La tâche de création d'un projet d'auto-surveillance est en cours"
msgid "Job to delete self-monitoring project is in progress"
-msgstr ""
+msgstr "La tâche de suppression du projet d'auto-surveillance est en cours"
msgid "Job was retried"
msgstr ""
@@ -22706,97 +23041,97 @@ msgid "Jobs"
msgstr "Tâches"
msgid "Jobs fail if they run longer than the timeout time. Input value is in seconds by default. Human readable input is also accepted, for example %{code_open}1 hour%{code_close}."
-msgstr ""
+msgstr "Les tâches échouent si elles s'exécutent toujours quand le délai d'attente arrive à expiration. La valeur d'entrée est en secondes par défaut. Une expression lisible est également acceptée, par exemple %{code_open}1 hour%{code_close}."
msgid "Jobs older than the configured time are considered expired and are archived. Archived jobs can no longer be retried. Leave empty to never archive jobs automatically. The default unit is in days, but you can use other units, for example %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}. Minimum value is 1 day."
-msgstr ""
+msgstr "Les tâches antérieures à la durée configurée sont considérées expirées et sont archivées. Les tâches archivées ne peuvent plus être retentées. Laissez vide pour ne jamais archiver les tâches automatiquement. L'unité par défaut est en jours, mais vous pouvez en utiliser d'autres, par exemple %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}. La valeur minimale est de 1 jour."
msgid "Jobs|All"
msgstr ""
msgid "Jobs|An error occurred while loading the Failed Jobs tab."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de l'onglet des Tâches ayant échoué."
msgid "Jobs|Are you sure you want to proceed?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir continuer ?"
msgid "Jobs|Are you sure you want to retry this job?"
-msgstr ""
+msgstr "Êtesâ€vous sûr(e) de vouloir relancer cette tâche ?"
msgid "Jobs|Create CI/CD configuration file"
-msgstr ""
+msgstr "Créer un fichier de configuration CI/CD"
msgid "Jobs|Filter jobs"
-msgstr ""
+msgstr "Filtrer les tâches"
msgid "Jobs|Finished"
msgstr ""
msgid "Jobs|Job is stuck. Check runners."
-msgstr ""
+msgstr "La tâche est bloquée. Vérifiez les exécuteurs."
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
-msgstr ""
+msgstr "Les tâches sont les éléments de base d'un pipeline de GitLab CI/CD. Chaque tâche possède une action spécifique, telle que tester du code. Pour définir des tâches dans un pipeline CI/CD, ajoutez un fichier de configuration CI/CD à votre projet."
msgid "Jobs|No jobs to show"
-msgstr ""
+msgstr "Aucune tâche à afficher"
msgid "Jobs|Raw text search is not currently supported for the jobs filtered search feature. Please use the available search tokens."
-msgstr ""
+msgstr "La recherche de texte brut n’est actuellement pas prise en charge pour la fonction de recherche filtrée. Veuillez utiliser les jetons de recherche disponibles."
msgid "Jobs|Status"
-msgstr ""
+msgstr "État"
msgid "Jobs|There was a problem fetching the failed jobs."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tâches en échec."
msgid "Jobs|Use jobs to automate your tasks"
-msgstr ""
+msgstr "Utiliser des tâches pour automatiser vos actions"
msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
-msgstr ""
+msgstr "Vous êtes sur le point de relancer une tâche qui a échoué car elle a tenté de déployer du code plus ancien que celui du dernier déploiement. Relancer cette tâche pourrait aboutir à l'écrasement de l'environnement avec le code source plus ancien."
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id}"
-msgstr ""
+msgstr "%{boldStart}Pipeline%{boldEnd} %{id}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source}"
-msgstr ""
+msgstr "%{boldStart}Pipeline%{boldEnd} %{id} pour %{mrId} avec %{source}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source} into %{target}"
-msgstr ""
+msgstr "%{boldStart}Pipeline%{boldEnd} %{id} pour %{mrId} avec %{source} vers %{target}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
-msgstr ""
+msgstr "%{boldStart}Pipeline%{boldEnd} %{id} pour %{ref}"
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr ""
+msgstr "%{searchLength} résultats trouvés pour %{searchTerm}"
msgid "Job|Are you sure you want to erase this job log and artifacts?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir effacer le journal de tâche et les artéfacts ?"
msgid "Job|Browse"
msgstr "Parcourir"
msgid "Job|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "Job|Canceled"
-msgstr ""
+msgstr "Annulée"
msgid "Job|Complete Raw"
msgstr "Brut complet"
msgid "Job|Created"
-msgstr ""
+msgstr "Créée"
msgid "Job|Download"
msgstr "Télécharger"
msgid "Job|Erase job log and artifacts"
-msgstr ""
+msgstr "Effacer le journal des tâches et les artéfacts"
msgid "Job|Failed"
-msgstr ""
+msgstr "Échouée"
msgid "Job|Finished at"
msgstr ""
@@ -22811,58 +23146,58 @@ msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Job log search"
-msgstr ""
+msgstr "Recherche dans le journal de tâches"
msgid "Job|Keep"
msgstr "Garder"
msgid "Job|Manual"
-msgstr ""
+msgstr "Manuelle"
msgid "Job|No search results found"
msgstr "Aucun résultat de recherche trouvé"
msgid "Job|Passed"
-msgstr ""
+msgstr "Réussie"
msgid "Job|Pending"
-msgstr ""
+msgstr "En attente"
msgid "Job|Preparing"
-msgstr ""
+msgstr "En préparation"
msgid "Job|Retry"
-msgstr ""
+msgstr "Réessayer"
msgid "Job|Running"
-msgstr ""
+msgstr "En cours"
msgid "Job|Scheduled"
-msgstr ""
+msgstr "Planifiée"
msgid "Job|Scroll to bottom"
msgstr "Faire défiler vers le bas"
msgid "Job|Scroll to next failure"
-msgstr ""
+msgstr "Défiler jusqu'à l’échec suivant"
msgid "Job|Scroll to top"
msgstr "Faire défiler vers le haut"
msgid "Job|Search for substrings in your job log output. Currently search is only supported for the visible job log output, not for any log output that is truncated due to size."
-msgstr ""
+msgstr "Rechercher des sous-chaînes dans la sortie de votre journal de tâches. Actuellement, la recherche n'est possible que pour la sortie visible du journal des tâches, et non pour toute sortie de journal tronquée en raison de la taille."
msgid "Job|Search job log"
-msgstr ""
+msgstr "Rechercher dans le journal des tâches"
msgid "Job|Show complete raw"
msgstr "Afficher la version brute"
msgid "Job|Skipped"
-msgstr ""
+msgstr "Ignorée"
msgid "Job|Status"
-msgstr ""
+msgstr "État"
msgid "Job|The artifacts were removed"
msgstr "Les artefacts ont été supprimés"
@@ -22874,58 +23209,58 @@ msgid "Job|There was a problem retrying the failed job."
msgstr ""
msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
-msgstr ""
+msgstr "Ces artéfacts sont les plus récents. Ils ne seront pas supprimés (même s'ils ont expirés) jusqu'à ce que de nouveaux artéfacts soient disponibles."
msgid "Job|This job failed because the necessary resources were not successfully created."
msgstr ""
msgid "Job|This job is stuck because of one of the following problems. There are no active runners online, no runners for the %{linkStart}protected branch%{linkEnd}, or no runners that match all of the job's tags:"
-msgstr ""
+msgstr "Cette tâche est bloquée en raison de l'un des problèmes suivants. Il n'y a aucun exécuteur actif en ligne, aucun exécuteur pour la %{linkStart}branche protégée%{linkEnd}, ou aucun exécuteur qui corresponde à toutes les étiquettes de la tâche :"
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Job|This job is stuck because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "Cette tâche est bloquée parce que vous n'avez aucun exécuteur actif pouvant exécuter cette tâche."
msgid "Job|Waiting for resource"
-msgstr ""
+msgstr "En attente de ressource"
msgid "Job|We could not find this element"
-msgstr ""
+msgstr "Nous n'avons pas pu trouver cet élément"
msgid "Job|allowed to fail"
-msgstr ""
+msgstr "autorisé à échouer"
msgid "Job|delayed"
-msgstr ""
+msgstr "différée"
msgid "Job|manual"
-msgstr ""
+msgstr "manuelle"
msgid "Job|triggered"
-msgstr ""
+msgstr "déclenchée"
msgid "Join GitLab today! You and your team can plan, build, and ship secure code all in one application. Get started here for free!"
-msgstr ""
+msgstr "Rejoignez GitLab dès aujourd'hui ! Vous et votre équipe pouvez planifier, créer et expédier du code sécurisé dans une seule application. Commencez ici gratuitement !"
msgid "Join Zoom meeting"
msgstr ""
msgid "Join a project"
-msgstr ""
+msgstr "Rejoindre un projet"
msgid "Join your team on GitLab and contribute to an existing project"
-msgstr ""
+msgstr "Rejoignez votre équipe sur GitLab et contribuez à un projet existant"
msgid "Joined %{time_ago}"
-msgstr ""
+msgstr "Rejoint %{time_ago}"
msgid "Joined %{user_created_time}"
msgstr ""
msgid "Joined projects (%{projects_count})"
-msgstr ""
+msgstr "Projets rejoints (%{projects_count})"
msgid "Jul"
msgstr "juill."
@@ -22946,22 +23281,22 @@ msgid "K8s pod health"
msgstr ""
msgid "KEY"
-msgstr ""
+msgstr "CLÉ"
msgid "Keep"
msgstr ""
msgid "Keep artifacts from most recent successful jobs"
-msgstr ""
+msgstr "Conserver les artéfacts des tâches réussies les plus récentes"
msgid "Keep divergent refs"
msgstr ""
msgid "Keeping all SAST analyzers enabled future-proofs the project in case new languages are added later on. Determining which analyzers apply is a process that consumes minimal resources and adds minimal time to the pipeline. Leaving all SAST analyzers enabled ensures maximum coverage."
-msgstr ""
+msgstr "Le fait de garder tous les analyseurs SAST activés couvre le projet dans le cas où de nouveaux langages sont ajoutés après coup. La détermination des analyseurs à appliquer est un processus qui consomme des ressources minimes et qui n'ajoute au pipeline qu'une durée minimale. Laisser tous les analyseurs SAST activés garantit une couverture maximale."
msgid "Kerberos access denied"
-msgstr ""
+msgstr "Accès Kerberos refusé"
msgid "Key"
msgstr ""
@@ -22970,25 +23305,25 @@ msgid "Key (PEM)"
msgstr ""
msgid "Key:"
-msgstr ""
+msgstr "Clé :"
msgid "Keyboard shortcuts"
msgstr "Raccourcis clavier"
msgid "KeyboardKey|Alt"
-msgstr ""
+msgstr "Alt"
msgid "KeyboardKey|Ctrl"
-msgstr ""
+msgstr "Ctrl"
msgid "KeyboardKey|Ctrl+"
-msgstr ""
+msgstr "Ctrl+"
msgid "KeyboardKey|Enter"
-msgstr ""
+msgstr "Entrée"
msgid "KeyboardKey|Esc"
-msgstr ""
+msgstr "Échap"
msgid "KeyboardKey|Shift"
msgstr ""
@@ -23000,13 +23335,13 @@ msgid "KeyboardShortcuts|Search keyboard shortcuts"
msgstr "Rechercher dans les raccourcis clavier"
msgid "Keys"
-msgstr ""
+msgstr "Clés"
msgid "Ki"
msgstr ""
msgid "Kroki"
-msgstr ""
+msgstr "Kroki"
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -23018,7 +23353,7 @@ msgid "Kubernetes Clusters"
msgstr ""
msgid "Kubernetes cluster"
-msgstr ""
+msgstr "Grappe de serveurs Kubernetes"
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Le temps de création de la grappe de serveurs Kubernetes dépasse le délai d’expiration : %{timeout}"
@@ -23033,7 +23368,7 @@ msgid "Kubernetes cluster was successfully updated."
msgstr "La grappe de serveurs Kubernetes a été mise à jour avec succès."
msgid "Kubernetes clusters"
-msgstr ""
+msgstr "Grappes de serveurs Kubernetes"
msgid "Kubernetes deployment not found"
msgstr ""
@@ -23045,25 +23380,25 @@ msgid "LDAP"
msgstr ""
msgid "LDAP Synchronization"
-msgstr ""
+msgstr "Synchronisation LDAP"
msgid "LDAP group settings"
-msgstr ""
+msgstr "Paramètres de groupe LDAP"
msgid "LDAP settings"
msgstr ""
msgid "LDAP settings updated"
-msgstr ""
+msgstr "Paramètres LDAP mis à jour"
msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
msgstr ""
msgid "LDAP synchronizations"
-msgstr ""
+msgstr "Synchronisations LDAP"
msgid "LDAP uid:"
-msgstr ""
+msgstr "Uid LDAP :"
msgid "LFS"
msgstr "LFS"
@@ -23088,8 +23423,8 @@ msgstr "Menu déroulant des actions sur les étiquettes"
msgid "Label added: %{labels}"
msgid_plural "Labels added: %{labels}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Étiquette ajoutée : %{labels}"
+msgstr[1] "Étiquettes ajoutées : %{labels}"
msgid "Label priority"
msgstr "Priorité de l'étiquette"
@@ -23122,22 +23457,22 @@ msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr "Les étiquettes peuvent être appliquées aux tickets et aux demandes de fusion afin de les catégoriser."
msgid "Labels can be applied to issues and merge requests. Star a label to make it a priority label."
-msgstr ""
+msgstr "Des étiquettes peuvent être appliquées aux tickets et aux demandes de fusion. Placer une étoile sur une étiquette rend celle-ci prioritaire."
msgid "Labels with no issues in this iteration:"
-msgstr ""
+msgstr "Étiquettes sans ticket dans cette itération :"
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
-msgstr ""
+msgstr "%{spanStart}Promouvoir l'étiquette%{spanEnd} %{labelTitle} %{spanStart}en Étiquette de Groupe ?%{spanEnd}"
msgid "Labels|Promote Label"
msgstr "Promouvoir l’étiquette"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
-msgstr ""
+msgstr "Promouvoir %{labelTitle} la rendra disponible pour tous les projets situés à l'intérieur de %{groupName}. Les étiquettes de projet existantes ayant le même titre seront fusionnées. Si une étiquette de groupe avec le même titre existe, elle sera également fusionnée. Cette action ne peut pas être annulée."
msgid "Label|Assignee"
-msgstr ""
+msgstr "Assigné"
msgid "Language"
msgstr "Langue"
@@ -23154,28 +23489,28 @@ msgstr[0] "Le dernier %d jour"
msgstr[1] "Les %d derniers jours"
msgid "Last %{days} days"
-msgstr ""
+msgstr "Les %{days} derniers jours"
msgid "Last 2 weeks"
-msgstr ""
+msgstr "Les 2 dernières semaines"
msgid "Last 30 days"
-msgstr ""
+msgstr "Les 30 derniers jours"
msgid "Last 60 days"
-msgstr ""
+msgstr "Les 60 derniers jours"
msgid "Last 90 days"
-msgstr ""
+msgstr "Les 90 derniers jours"
msgid "Last Accessed On"
msgstr ""
msgid "Last Activity"
-msgstr ""
+msgstr "Dernière Activité"
msgid "Last Name"
-msgstr ""
+msgstr "Nom"
msgid "Last Pipeline"
msgstr "Dernier pipeline"
@@ -23184,7 +23519,7 @@ msgid "Last Seen"
msgstr ""
msgid "Last Sync"
-msgstr ""
+msgstr "Dernière Synchro"
msgid "Last Used"
msgstr ""
@@ -23208,16 +23543,16 @@ msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr "Dernière modification par %{link_start}%{avatar} %{name}%{link_end}"
msgid "Last event"
-msgstr ""
+msgstr "Dernier événement"
msgid "Last item before this page loaded in your browser:"
msgstr ""
msgid "Last modified"
-msgstr ""
+msgstr "Dernière modification"
msgid "Last month"
-msgstr ""
+msgstr "Le mois dernier"
msgid "Last name"
msgstr ""
@@ -23226,23 +23561,26 @@ msgid "Last reply by"
msgstr "Dernière réponse de"
msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
-msgstr ""
+msgstr "La dernière vérification du dépôt (%{last_check_timestamp}) a échoué. Voir les messages d'erreur dans le fichier « repocheck.log »."
msgid "Last seen"
msgstr ""
msgid "Last sign-in"
-msgstr ""
+msgstr "Dernière connexion"
msgid "Last sign-in IP:"
-msgstr ""
+msgstr "IP de la dernière connexion :"
msgid "Last sign-in at:"
-msgstr ""
+msgstr "Dernière connexion le :"
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr "Dernière mise à jour réussie %{time}."
+
msgid "Last time verified"
msgstr ""
@@ -23256,7 +23594,7 @@ msgid "Last updated"
msgstr "Dernière mise à jour"
msgid "Last updated %{time} ago"
-msgstr ""
+msgstr "Dernière mise à jour il y a %{time}"
msgid "Last used"
msgstr ""
@@ -23268,10 +23606,10 @@ msgid "Last used on:"
msgstr ""
msgid "Last week"
-msgstr ""
+msgstr "La dernière semaine"
msgid "Last year"
-msgstr ""
+msgstr "L'année dernière"
msgid "LastCommit|authored"
msgstr ""
@@ -23289,7 +23627,7 @@ msgid "Latest pipeline for the most recent commit on this branch"
msgstr ""
msgid "Launch a ready-to-code development environment for your project."
-msgstr ""
+msgstr "Lancer un environnement de développement prêt-à-coder pour votre projet."
msgid "Layout|Fixed"
msgstr ""
@@ -23304,16 +23642,16 @@ msgid "Lead Time for Changes"
msgstr ""
msgid "Lead time"
-msgstr ""
+msgstr "Délai de mise à disposition"
msgid "Learn GitLab"
msgstr ""
msgid "Learn More"
-msgstr ""
+msgstr "En savoir plus"
msgid "Learn More."
-msgstr ""
+msgstr "En savoir plus."
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -23324,17 +23662,17 @@ msgstr ""
msgid "Learn more"
msgstr "En savoir plus"
-msgid "Learn more about %{username}"
-msgstr ""
+msgid "Learn more about %{name}"
+msgstr "En savoir plus sur %{name}"
msgid "Learn more about Auto DevOps"
msgstr ""
msgid "Learn more about GitLab"
-msgstr ""
+msgstr "En savoir plus sur GitLab"
msgid "Learn more about Needs relationships"
-msgstr ""
+msgstr "En savoir plus sur les relations de Besoins"
msgid "Learn more about Web Terminal"
msgstr ""
@@ -23349,7 +23687,7 @@ msgid "Learn more about custom project templates"
msgstr ""
msgid "Learn more about deploying to AWS"
-msgstr ""
+msgstr "En savoir plus sur le déploiement vers AWS"
msgid "Learn more about deploying to a cluster"
msgstr ""
@@ -23358,10 +23696,10 @@ msgid "Learn more about group-level project templates"
msgstr ""
msgid "Learn more about groups."
-msgstr ""
+msgstr "En savoir plus sur les groupes."
msgid "Learn more about issues."
-msgstr ""
+msgstr "En savoir plus sur les tickets."
msgid "Learn more about max seats used"
msgstr ""
@@ -23370,7 +23708,7 @@ msgid "Learn more about seats owed"
msgstr ""
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 ""
+msgstr "En savoir plus sur les fragments et les réplicas grâce à la documentation sur la %{configuration_link_start}configuration de Recherche Avancée%{configuration_link_end}. Les changements ne seront pas effectifs tant que vous n'aurez pas %{recreated_link_start}recréé%{recreated_link_end} l'index."
msgid "Learn more about signing commits"
msgstr ""
@@ -23379,37 +23717,37 @@ msgid "Learn more in the"
msgstr "Apprenezâ€en plus dans la"
msgid "Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "LearnGitLab|%{percentage}%{percentSymbol} completed"
msgstr ""
msgid "LearnGitLab|Add code owners"
-msgstr ""
+msgstr "Ajouter des propriétaires de code"
msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
-msgstr ""
+msgstr "Rechercher des vulnérabilités dans votre application avec DAST"
msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
-msgstr ""
+msgstr "Terminez d'abord ces tâches afin de pouvoir profiter des fonctionnalités de GitLab à leur maximum :"
msgid "LearnGitLab|Create a repository"
-msgstr ""
+msgstr "Créer un dépôt"
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
-msgstr ""
+msgstr "Créez un flux de travail pour votre nouvel environnement et découvrez la façon dont les fonctionnalités de GitLab fonctionnent ensemble :"
msgid "LearnGitLab|Create an issue"
-msgstr ""
+msgstr "Créer un ticket"
msgid "LearnGitLab|Create or import your first repository into your new project."
msgstr "Créez ou importez votre premier dépôt dans votre nouveau projet."
msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work."
-msgstr ""
+msgstr "Créer/importer des tickets pour collaborer sur des idées et planifier le travail."
msgid "LearnGitLab|Deploy"
-msgstr ""
+msgstr "Déployer"
msgid "LearnGitLab|Enable require merge approvals"
msgstr ""
@@ -23418,7 +23756,7 @@ msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy a
msgstr ""
msgid "LearnGitLab|Invite your colleagues"
-msgstr ""
+msgstr "Invitez vos collègues"
msgid "LearnGitLab|Learn GitLab"
msgstr ""
@@ -23433,61 +23771,61 @@ msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set u
msgstr ""
msgid "LearnGitLab|Review and edit proposed changes to source code."
-msgstr ""
+msgstr "Examiner et modifier les modifications proposées au code source."
msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
-msgstr ""
+msgstr "Attribuer les revues de code aux bons relecteurs, à chaque fois."
msgid "LearnGitLab|Run a Security scan using CI/CD"
-msgstr ""
+msgstr "Exécuter une analyse de Sécurité avec CI/CD"
msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
-msgstr ""
+msgstr "Gagnez du temps en automatisant vos tâches d'intégration et de déploiement."
msgid "LearnGitLab|Scan dependencies for licenses"
-msgstr ""
+msgstr "Analyser les dépendances à la recherche de licences"
msgid "LearnGitLab|Scan dependencies for vulnerabilities"
-msgstr ""
+msgstr "Analyser les dépendances à la recherche de vulnérabilités"
msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
-msgstr ""
+msgstr "Analysez votre code pour en découvrir les vulnérabilités avant d'effectuer le déploiement."
msgid "LearnGitLab|Set up CI/CD"
msgstr ""
msgid "LearnGitLab|Set up your first project's CI/CD"
-msgstr ""
+msgstr "Configurez CI/CD pour votre premier projet"
msgid "LearnGitLab|Set up your workspace"
msgstr ""
msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "Commencez un essai gratuit de GitLab Ultimate"
msgid "LearnGitLab|Submit a merge request (MR)"
-msgstr ""
+msgstr "Soumettre une demande de fusion (MR)"
msgid "LearnGitLab|Try GitLab Ultimate for free"
msgstr ""
msgid "LearnGitLab|Try all GitLab features for 30 days, no credit card required."
-msgstr ""
+msgstr "Essayez toutes les fonctionnalités de GitLab pendant 30 jours, aucune carte de crédit n’est requise."
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
-msgstr ""
+msgstr "Utilisez votre nouveau flux de travail GitLab pour déployer votre application, surveiller son état de santé et assurer sa sécurité :"
msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
-msgstr ""
+msgstr "Votre équipe s'étoffe ! Vous avez invité avec succès de nouveaux coéquipiers à se joindre au projet %{projectName}."
msgid "LearnGitlab|- Included in trial"
-msgstr ""
+msgstr "- Inclus dans l'essai"
msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
-msgstr ""
+msgstr "Contactez votre administrateur pour démarrer un essai gratuit d'Ultimate"
msgid "LearnGitlab|Creating your onboarding experience..."
-msgstr ""
+msgstr "Création de votre expérience d'intégration..."
msgid "LearnGitlab|Ok, let's go"
msgstr ""
@@ -23514,19 +23852,19 @@ msgid "Leave zen mode"
msgstr ""
msgid "Leaving this setting enabled is recommended."
-msgstr ""
+msgstr "Laisser ce paramètre activé est recommandé."
msgid "Legacy burndown chart"
-msgstr ""
+msgstr "Ancien graphique d'avancement"
msgid "Legacy license"
msgstr ""
msgid "Less Details"
-msgstr ""
+msgstr "Moins de détails"
msgid "Less restrictive visibility"
-msgstr ""
+msgstr "Visibilité moins restrictive"
msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
@@ -23538,31 +23876,31 @@ msgid "License Compliance"
msgstr ""
msgid "License Compliance| Used by %{dependencies}"
-msgstr ""
+msgstr "Utilisée par %{dependencies}"
msgid "License compliance"
-msgstr ""
+msgstr "Conformité de licence"
msgid "License key"
-msgstr ""
+msgstr "Clé de licence"
msgid "License overview"
-msgstr ""
+msgstr "Aperçu des licences"
msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
-msgstr ""
+msgstr "Les %{docLinkStart}Approbations de licence%{docLinkEnd} sont actives"
msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
-msgstr ""
+msgstr "Les %{docLinkStart}Approbations de licence%{docLinkEnd} sont inactives"
msgid "LicenseCompliance|Acceptable for use in this project"
msgstr ""
msgid "LicenseCompliance|Acceptable license to be used in the project"
-msgstr ""
+msgstr "Licence acceptable pouvant être utilisée dans le projet"
msgid "LicenseCompliance|Add license and related policy"
-msgstr ""
+msgstr "Ajouter une licence et sa stratégie associée"
msgid "LicenseCompliance|Add license policy"
msgstr ""
@@ -23580,10 +23918,10 @@ msgid "LicenseCompliance|Deny"
msgstr ""
msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
-msgstr ""
+msgstr "Interdire la demande de fusion si détectée puis ordonner au développeur de supprimer"
msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
-msgstr ""
+msgstr "En savoir plus sur les %{linkStart}Approbations de licence%{linkEnd}"
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
@@ -23592,8 +23930,8 @@ msgstr[1] ""
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La Conformité de Licence a détecté %d licence et une violation de stratégie pour la branche source uniquement ; une approbation est nécessaire"
+msgstr[1] "La Conformité de Licence a détecté %d licences et des violations de stratégie pour la branche source uniquement ; une approbation est nécessaire"
msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
@@ -23607,13 +23945,13 @@ msgstr[1] ""
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La Conformité de Licence a détecté %d nouvelle licence et une violation de stratégie"
+msgstr[1] "La Conformité de Licence a détecté %d nouvelles licences et des violations de stratégie"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La Conformité de Licence a détecté %d nouvelle licence et une violation de stratégie ; une approbation est nécessaire"
+msgstr[1] "La Conformité de Licence a détecté %d nouvelles licences et des violations de stratégie ; une approbation est nécessaire"
msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
msgstr ""
@@ -23625,10 +23963,10 @@ msgid "LicenseCompliance|License name"
msgstr ""
msgid "LicenseCompliance|No policy matches this license"
-msgstr ""
+msgstr "Aucune politique ne correspond à cette licence"
msgid "LicenseCompliance|Out-of-compliance with the project's policies and should be removed"
-msgstr ""
+msgstr "Non conforme(s) aux stratégies du projet et à supprimer"
msgid "LicenseCompliance|Remove license"
msgstr ""
@@ -23637,7 +23975,7 @@ msgid "LicenseCompliance|Remove license?"
msgstr ""
msgid "LicenseCompliance|There are currently no policies in this project."
-msgstr ""
+msgstr "Il n'y a actuellement aucune stratégie dans ce projet."
msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
@@ -23670,16 +24008,16 @@ msgid "Licensed Features"
msgstr ""
msgid "Licensed to:"
-msgstr ""
+msgstr "Licence accordée à :"
msgid "Licenses"
msgstr "Licences"
msgid "Licenses|%{remainingComponentsCount} more"
-msgstr ""
+msgstr "%{remainingComponentsCount} de plus"
msgid "Licenses|Acceptable license to be used in the project"
-msgstr ""
+msgstr "Licence acceptable pouvant être utilisée dans le projet"
msgid "Licenses|Component"
msgstr ""
@@ -23691,49 +24029,49 @@ msgid "Licenses|Detected in Project"
msgstr ""
msgid "Licenses|Displays licenses detected in the project that are out of compliance with the project's policies, based on the %{linkStart}latest successful%{linkEnd} scan"
-msgstr ""
+msgstr "Affiche les licences détectées dans le projet qui ne sont pas conformes aux stratégies du projet, en se basant sur la%{linkStart}dernière analyse réussie%{linkEnd}"
msgid "Licenses|Drag your license file here or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
+msgstr "Faites glisser votre fichier de licence ici ou %{linkStart}cliquez pour le téléverser%{linkEnd}."
msgid "Licenses|Drop your license file to start the upload."
-msgstr ""
+msgstr "Déposez votre fichier de licence pour démarrer le téléversement."
msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
-msgstr ""
+msgstr "Erreur lors de la récupération de la liste des licences. Veuillez vérifier votre connexion réseau et réessayer."
msgid "Licenses|Error: You are trying to upload something other than a file"
-msgstr ""
+msgstr "Erreur : Vous essayez de téléverser autre chose qu’un fichier"
msgid "Licenses|License Compliance"
-msgstr ""
+msgstr "Conformité de licence"
msgid "Licenses|Name"
-msgstr ""
+msgstr "Nom"
msgid "Licenses|Policies"
-msgstr ""
+msgstr "Stratégies"
msgid "Licenses|Policy"
-msgstr ""
+msgstr "Stratégie"
msgid "Licenses|Policy violation: denied"
-msgstr ""
+msgstr "Violation de stratégie : refus"
msgid "Licenses|Specified policies in this project"
-msgstr ""
+msgstr "Stratégies spécifiées dans ce projet"
msgid "Licenses|The file could not be uploaded."
-msgstr ""
+msgstr "Le fichier n'a pas pu être téléversé."
msgid "Licenses|The license list details information about the licenses used within your project."
-msgstr ""
+msgstr "La liste des licences détaille les informations sur les licences utilisées au sein de votre projet."
msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
-msgstr ""
+msgstr "Licence non acceptable, si elle est détectée, elle interdira toute demande de fusion jusqu'à ce qu'elle soit supprimée"
msgid "Licenses|View license details for your project"
-msgstr ""
+msgstr "Voir les détails de la licence de votre projet"
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -23742,13 +24080,13 @@ msgid "Limit sign in from multiple IP addresses"
msgstr ""
msgid "Limit the number of inbound incident management alerts that can be sent to a project."
-msgstr ""
+msgstr "Limiter le nombre d'alertes entrantes de gestion des incidents qui peuvent être envoyées à un projet."
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
-msgstr ""
+msgstr "Limiter le nombre de tickets et d'épopées par minute qu'un utilisateur peut créer via des requêtes web et API."
msgid "Limit the number of pipeline creation requests per minute. This limit includes pipelines created through the UI, the API, and by background processing."
-msgstr ""
+msgstr "Limiter le nombre de requêtes de création de pipelines par minute. Cette limite inclut les pipelines créés via l'interface utilisateur, l'API et les traitements en arrière-plan."
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -23757,28 +24095,28 @@ msgid "Limiting mode"
msgstr ""
msgid "Line changes"
-msgstr ""
+msgstr "Lignes changées"
msgid "Link"
msgstr ""
msgid "Link (optional)"
-msgstr ""
+msgstr "Lien (facultatif)"
msgid "Link Sentry to GitLab to discover and view the errors your application generates."
-msgstr ""
+msgstr "Associer Sentry à GitLab pour découvrir et afficher les erreurs générées par votre application."
msgid "Link URL"
msgstr ""
msgid "Link an external wiki from the project's sidebar. %{docs_link}"
-msgstr ""
+msgstr "Lier un wiki externe à la barre latérale du projet. %{docs_link}"
msgid "Link copied"
msgstr ""
msgid "Link text"
-msgstr ""
+msgstr "Texte de lien"
msgid "Link title"
msgstr ""
@@ -23787,7 +24125,7 @@ msgid "Link title is required"
msgstr ""
msgid "Link to go to GitLab pipeline documentation"
-msgstr ""
+msgstr "Lien vers la documentation des pipelines GitLab"
msgid "Link to your Grafana instance."
msgstr ""
@@ -23799,7 +24137,7 @@ msgid "Linked epics"
msgstr ""
msgid "Linked incidents or issues"
-msgstr ""
+msgstr "Incidents ou tickets liés"
msgid "Linked items"
msgstr "Tickets liés"
@@ -23808,52 +24146,52 @@ msgid "LinkedIn"
msgstr "LinkedIn"
msgid "LinkedIn:"
-msgstr ""
+msgstr "LinkedIn :"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
msgid "LinkedResources|Add"
-msgstr ""
+msgstr "Ajouter"
msgid "LinkedResources|Add a resource link"
-msgstr ""
+msgstr "Ajouter un lien de ressource"
msgid "LinkedResources|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "LinkedResources|Error creating resource link for the incident: %{error}"
-msgstr ""
+msgstr "Erreur lors de la création du lien de la ressource pour l'incident : %{error}"
msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
-msgstr ""
+msgstr "Erreur lors de la suppression de la ressource liée pour l'incident : %{error}"
msgid "LinkedResources|Fetching linked resources"
-msgstr ""
+msgstr "Récupération des ressources liées"
msgid "LinkedResources|Link"
-msgstr ""
+msgstr "Lien"
msgid "LinkedResources|Linked resources"
-msgstr ""
+msgstr "Ressources liées"
msgid "LinkedResources|Remove"
-msgstr ""
+msgstr "Supprimer"
msgid "LinkedResources|Something went wrong while creating the resource link for the incident."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du lien de la ressource pour l'incident."
msgid "LinkedResources|Something went wrong while deleting the linked resource for the incident."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de la ressource liée de l'incident."
msgid "LinkedResources|Something went wrong while fetching linked resources for the incident."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des ressources liées de l'incident."
msgid "LinkedResources|Text (Optional)"
-msgstr ""
+msgstr "Texte (facultatif)"
msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
-msgstr ""
+msgstr "Utilisez cet espace pour ajouter des liens vers les ressources dont votre équipe a besoin pour travailler à la résolution de l'incident."
msgid "Links"
msgstr ""
@@ -23868,16 +24206,16 @@ msgid "List available repositories"
msgstr "Lister les dépôts disponibles"
msgid "List of all merge commits"
-msgstr ""
+msgstr "Liste de tous les commits de fusion"
msgid "List of suitable GCP locations"
-msgstr ""
+msgstr "Liste des emplacements GCP appropriés"
msgid "List of users who are allowed to exceed the rate limit. Example: username1, username2"
msgstr ""
msgid "List options"
-msgstr ""
+msgstr "Options des listes"
msgid "List settings"
msgstr ""
@@ -23886,7 +24224,7 @@ msgid "List the merge requests that must be merged before this one."
msgstr ""
msgid "List the visible events for %{project_link} using the %{events_api_link}."
-msgstr ""
+msgstr "Lister les évènements visibles de %{project_link} en utilisant l'%{events_api_link}."
msgid "List view"
msgstr "Vue en liste"
@@ -23898,16 +24236,16 @@ msgid "Live preview"
msgstr "Prévisualisation"
msgid "Load more"
-msgstr ""
+msgstr "Charger davantage"
msgid "Load more users"
-msgstr ""
+msgstr "Charger plus d'utilisateurs"
msgid "Loading"
msgstr ""
msgid "Loading %{name}"
-msgstr ""
+msgstr "Chargement de %{name}"
msgid "Loading contribution stats for group members"
msgstr "Chargement des statistiques de contribution des membres du groupe"
@@ -23925,7 +24263,7 @@ msgid "Loading the GitLab IDE..."
msgstr "Chargement de l’EDI de GitLab…"
msgid "Loading, please wait."
-msgstr ""
+msgstr "Chargement en cours, veuillez patienter."
msgid "Loading..."
msgstr "Chargement…"
@@ -23940,7 +24278,7 @@ msgid "Location"
msgstr ""
msgid "Location:"
-msgstr ""
+msgstr "Emplacement :"
msgid "Lock"
msgstr "Verrouiller"
@@ -23949,13 +24287,13 @@ msgid "Lock %{issuableDisplayName}"
msgstr "Verrouiller %{issuableDisplayName}"
msgid "Lock File?"
-msgstr ""
+msgstr "Verrouiller le fichier ?"
msgid "Lock memberships to LDAP synchronization"
msgstr ""
msgid "Lock merge request"
-msgstr ""
+msgstr "Verrouiller la demande de fusion"
msgid "Lock not found"
msgstr "Verrou non trouvé"
@@ -23964,7 +24302,7 @@ msgid "Lock the discussion"
msgstr ""
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "Verrouiller ce(tte) %{issuableDisplayName} ? Seuls les %{strongStart}membres du projet%{strongEnd} peuvent mettre des commentaires."
msgid "Lock to current projects"
msgstr "Verrouiller aux projets en cours"
@@ -23988,34 +24326,34 @@ msgid "Locks the discussion."
msgstr ""
msgid "LoggedOutMarketingHeader|About GitLab"
-msgstr ""
+msgstr "À propos de GitLab"
msgid "LoggedOutMarketingHeader|Explore GitLab"
-msgstr ""
+msgstr "Explorer GitLab"
msgid "LoggedOutMarketingHeader|Get started"
-msgstr ""
+msgstr "Démarrer"
msgid "LoggedOutMarketingHeader|GitLab Learn"
msgstr ""
msgid "LoggedOutMarketingHeader|GitLab docs"
-msgstr ""
+msgstr "Docs GitLab"
msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
-msgstr ""
+msgstr "GitLab : la plateforme DevOps"
msgid "LoggedOutMarketingHeader|How GitLab compares"
-msgstr ""
+msgstr "Comment GitLab se compare"
msgid "LoggedOutMarketingHeader|Install GitLab"
-msgstr ""
+msgstr "Installer GitLab"
msgid "LoggedOutMarketingHeader|Pricing"
-msgstr ""
+msgstr "Tarification"
msgid "LoggedOutMarketingHeader|Talk to an expert"
-msgstr ""
+msgstr "Parlez à un expert"
msgid "Login"
msgstr ""
@@ -24027,7 +24365,7 @@ msgid "Logo was successfully removed."
msgstr ""
msgid "Logo will be removed. Are you sure?"
-msgstr ""
+msgstr "Le logo sera supprimé. Êtesâ€vous sûr(e) ?"
msgid "Logs"
msgstr "Journaux"
@@ -24036,10 +24374,10 @@ msgid "Looks like you've reached your %{free_limit} member limit for %{strong_st
msgstr ""
msgid "Low vulnerabilities present"
-msgstr ""
+msgstr "Vulnérabilités faibles présentes"
msgid "MB"
-msgstr ""
+msgstr "Mo"
msgid "MD5"
msgstr ""
@@ -24048,19 +24386,19 @@ msgid "MERGED"
msgstr ""
msgid "MR widget|Back to the merge request"
-msgstr ""
+msgstr "Revenir à la demande de fusion"
msgid "MR widget|See your pipeline in action"
-msgstr ""
+msgstr "Voir votre pipeline en action"
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
-msgstr ""
+msgstr "Consultez notre ouvrage %{beginnerLinkStart}Beginner's Guide to Continuous Integratio%{beginnerLinkEnd} et à nos %{exampleLinkStart}exemples sur GitLab CI/CD%{exampleLinkEnd} pour en savoir plus."
msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
-msgstr ""
+msgstr "Le pipeline testera votre code à chaque commit. Un %{codeQualityLinkStart}rapport de qualité de code%{codeQualityLinkEnd} apparaîtra dans vos demandes de fusion pour vous avertir de dégradations potentielles du code."
msgid "MRApprovals|Approvals"
-msgstr ""
+msgstr "Approbations"
msgid "MRApprovals|Approved by"
msgstr ""
@@ -24069,13 +24407,13 @@ msgid "MRApprovals|Approvers"
msgstr ""
msgid "MRApprovals|Commented by"
-msgstr ""
+msgstr "Mise en commentaire par"
msgid "MRDiffFile|Changes are too large to be shown."
-msgstr ""
+msgstr "Les modifications sont trop importantes pour être affichées."
msgid "MRDiffFile|View file @ %{commitSha}"
-msgstr ""
+msgstr "Voir le fichier @ %{commitSha}"
msgid "MRDiff|Show changes only"
msgstr ""
@@ -24084,22 +24422,22 @@ msgid "MRDiff|Show full file"
msgstr ""
msgid "Made this issue confidential."
-msgstr ""
+msgstr "Ce ticket est désormais confidentiel."
msgid "Mailgun"
-msgstr ""
+msgstr "Mailgun"
msgid "Mailgun HTTP webhook signing key"
-msgstr ""
+msgstr "Clé de signature pour le crochet web HTTP de Mailgun"
msgid "Mailgun events"
-msgstr ""
+msgstr "Événements Mailgun"
msgid "Main menu"
-msgstr ""
+msgstr "Menu principal"
msgid "Maintenance mode"
-msgstr ""
+msgstr "Mode maintenance"
msgid "Make adjustments to how your GitLab instance is set up."
msgstr ""
@@ -24111,6 +24449,9 @@ msgid "Make everyone on your team more productive regardless of their location.
msgstr "Rendez chaque membre de votre équipe plus productif, quel que soit l’endroit où il se situe. GitLab Geo crée des miroirs en lecture seule de votre instance GitLab afin que vous puissiez réduire le temps nécessaire pour cloner et récupérer de gros dépôts."
msgid "Make issue confidential"
+msgstr "Rendre le ticket confidentiel"
+
+msgid "Make sure you choose a strong, unique password."
msgstr ""
msgid "Make sure you have the correct permissions to link your project."
@@ -24126,7 +24467,7 @@ msgid "Manage %{workspace} labels"
msgstr ""
msgid "Manage Web IDE features."
-msgstr ""
+msgstr "Gérer les fonctionnalités de l'EDI Web."
msgid "Manage access"
msgstr "Gestion des accès"
@@ -24135,13 +24476,13 @@ msgid "Manage applications that can use GitLab as an OAuth provider, and applica
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 use GitLab as an OAuth provider."
-msgstr ""
+msgstr "Gérer les applications qui utilisent GitLab comme fournisseur OAuth."
msgid "Manage applications that you've authorized to use your account."
msgstr "Gérez les applications que vous avez autorisées à utiliser votre compte."
msgid "Manage git repositories with fine-grained access controls that keep your code secure."
-msgstr ""
+msgstr "Gérer les dépôts git avec des contrôles d'accès à granularité fine pour garder votre code sécurisé."
msgid "Manage group labels"
msgstr "Gérer les étiquettes de groupe"
@@ -24159,15 +24500,15 @@ msgid "Manage project labels"
msgstr "Gérer les étiquettes de projet"
msgid "Manage projects."
-msgstr ""
+msgstr "Gérer les projets."
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
-msgstr ""
-
msgid "Manage your project's triggers"
+msgstr "Gérez les déclencheurs de votre projet"
+
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24180,7 +24521,7 @@ msgid "Manifest file import"
msgstr "Importation de fichier manifeste"
msgid "Manifest import"
-msgstr ""
+msgstr "Importation de manifeste"
msgid "Manual"
msgstr "Manuel"
@@ -24189,7 +24530,7 @@ msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
msgid "Manually link this issue by adding it to the linked issue section of the %{linkStart}originating vulnerability%{linkEnd}."
-msgstr ""
+msgstr "Liez manuellement ce ticket en l'ajoutant à la section des tickets liés de la %{linkStart}vulnérabilité d'origine%{linkEnd}."
msgid "Map a FogBugz account ID to a GitLab user"
msgstr "Associer un identifiant de compte FogBugz à un utilisateur GitLab"
@@ -24204,34 +24545,34 @@ msgid "Mark as done"
msgstr "Marquer comme terminé"
msgid "Mark as draft"
-msgstr ""
+msgstr "Marquer comme brouillon"
msgid "Mark as ready"
-msgstr ""
+msgstr "Marquer comme prêt"
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
msgid "Mark this issue as related to another issue"
-msgstr ""
+msgstr "Marquer ce ticket comme lié à un autre ticket"
msgid "Mark to do as done"
msgstr "Marquer une tâche comme terminé"
msgid "Markdown Help"
-msgstr ""
+msgstr "Aide sur Markdown"
msgid "Markdown enabled."
msgstr ""
msgid "Markdown supported."
-msgstr ""
+msgstr "Markdown pris en charge."
msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
-msgstr ""
+msgstr "Ajouter un lien (%{modifierKey}K)"
msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
-msgstr ""
+msgstr "Ajouter un lien (%{modifier_key}K)"
msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
msgstr "Ajouter du texte en gras (%{modifierKey}B)"
@@ -24246,26 +24587,38 @@ msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
msgstr "Ajouter du texte en italique (%{modifier_key}I)"
msgid "MarkdownEditor|Add strikethrough text (%{modifierKey}⇧X)"
-msgstr ""
+msgstr "Ajouter un texte barré (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
+msgstr "Ajouter un texte barré (%{modifier_key}⇧X)"
+
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "Désindenter une ligne (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "Désindenter une ligne (%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "Prend en charge le %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr "Marqué"
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
msgid "Marked as draft. Can only be merged when marked as ready."
-msgstr ""
+msgstr "Marqué comme brouillon. Ne peut être fusionné que si marqué comme étant prêt."
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24273,13 +24626,13 @@ msgid "Marked this issue as a duplicate of %{duplicate_param}."
msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "a lié ce ticket au %{issue_ref}."
msgid "Marked to do as done."
msgstr "Marqué comme terminé."
-msgid "Marks this %{noun} as a draft."
-msgstr ""
+msgid "Marks"
+msgstr "Marque"
msgid "Marks this %{noun} as ready."
msgstr ""
@@ -24288,7 +24641,7 @@ msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "Marque ce ticket comme lié à %{issue_ref}."
msgid "Marks to do as done."
msgstr "Marque comme fait."
@@ -24300,19 +24653,19 @@ msgid "Match not found; try refining your search query."
msgstr ""
msgid "Mattermost"
-msgstr ""
+msgstr "Mattermost"
msgid "Mattermost URL:"
-msgstr ""
+msgstr "URL de Mattermost :"
msgid "Mattermost notifications"
-msgstr ""
+msgstr "Notifications Mattermost"
msgid "MattermostService|Add to Mattermost"
msgstr ""
msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
-msgstr ""
+msgstr "Après avoir configuré l’intégration, affichez vos nouvelles commandes Mattermost en entrant"
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -24336,58 +24689,58 @@ msgid "MattermostService|Suggestions:"
msgstr ""
msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
-msgstr ""
+msgstr "Utilisez ce service pour effectuer des tâches courantes dans votre projet en entrant des commandes barre oblique dans Mattermost."
msgid "Max 100,000 events"
-msgstr ""
+msgstr "100000 événements max"
msgid "Max Value"
msgstr ""
msgid "Max authenticated Git LFS requests per period per user"
-msgstr ""
+msgstr "Nombre maximal de requêtes Git LFS authentifiées par période et par utilisateur"
msgid "Max file size is 200 KB."
-msgstr ""
+msgstr "La taille maximale de fichier est de 200 Ko."
msgid "Max role"
-msgstr ""
+msgstr "Rôle max"
msgid "Max seats used"
msgstr ""
msgid "Max session time"
-msgstr ""
+msgstr "Durée maximale de session"
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "Maximum 20 caractères"
msgid "Maximum Conan package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale du paquet Conan en octets"
msgid "Maximum Helm chart file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale de graphique Helm en octets"
msgid "Maximum Maven package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale du paquet Maven en octets"
msgid "Maximum NuGet package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale du paquet NuGet en octets"
msgid "Maximum PyPI package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale du paquet PyPI en octets"
msgid "Maximum Terraform Module package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale du paquet Module Terraform en octets"
msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for access token (days)"
-msgstr ""
+msgstr "Durée de vie maximale permise pour les jetons d'accès (jours)"
msgid "Maximum allowed lifetime for SSH keys (days)"
-msgstr ""
+msgstr "Durée de vie maximale autorisée pour les clés SSH (jours)"
msgid "Maximum artifacts size"
msgstr ""
@@ -24396,7 +24749,7 @@ msgid "Maximum artifacts size (MB)"
msgstr ""
msgid "Maximum attachment size"
-msgstr ""
+msgstr "Taille maximale des pièces jointes"
msgid "Maximum attachment size (MB)"
msgstr ""
@@ -24408,28 +24761,28 @@ msgid "Maximum authenticated web requests per rate limit period per user"
msgstr ""
msgid "Maximum bulk request size (MiB)"
-msgstr ""
+msgstr "Taille maximale de requête en bloc (Mio)"
msgid "Maximum capacity"
msgstr ""
msgid "Maximum character limit - %{limit}"
-msgstr ""
+msgstr "Limite maximale de caractères - %{limit}"
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
-msgstr ""
+msgstr "Concurrence maximale des requêtes en bloc Elasticsearch par opération d'indexation."
msgid "Maximum delay (Minutes)"
msgstr ""
msgid "Maximum diff patch size"
-msgstr ""
+msgstr "Taille maximale du correctif diff"
msgid "Maximum diff patch size (Bytes)"
-msgstr ""
+msgstr "Taille maximale du correctif diff (octets)"
msgid "Maximum duration of a session."
-msgstr ""
+msgstr "Durée maximale d'une session."
msgid "Maximum export size"
msgstr ""
@@ -24441,19 +24794,19 @@ msgid "Maximum field length"
msgstr ""
msgid "Maximum file size indexed (KiB)"
-msgstr ""
+msgstr "Taille maximale de fichier à indexer (KiB)"
msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
-msgstr ""
+msgstr "La taille maximale du fichier est de 1 Mo. Les dimensions de l'image doivent être de 32×32 pixels. Les formats d'image autorisés sont %{favicon_extension_allowlist}."
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
msgstr ""
msgid "Maximum file size is 1MB. Pages are optimized for a 640x360 px logo."
-msgstr ""
+msgstr "La taille maximale du fichier est de 1 Mo. Les pages sont optimisées pour un logo de 640x360 px."
msgid "Maximum files in a diff"
-msgstr ""
+msgstr "Nombre maximum de fichiers dans un diff"
msgid "Maximum group export download requests per minute"
msgstr ""
@@ -24465,13 +24818,13 @@ msgid "Maximum group import requests per minute"
msgstr ""
msgid "Maximum import size"
-msgstr ""
+msgstr "Taille maximale de l'importation"
msgid "Maximum import size (MB)"
msgstr ""
msgid "Maximum job artifact size"
-msgstr ""
+msgstr "Taille maximale des artéfacts des tâches"
msgid "Maximum job timeout"
msgstr "Durée maximale d’exécution de la tâche"
@@ -24480,10 +24833,10 @@ msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
msgid "Maximum lines in a diff"
-msgstr ""
+msgstr "Nombre maximum de lignes dans un diff"
msgid "Maximum npm package file size in bytes"
-msgstr ""
+msgstr "Taille de fichier maximale des paquets npm en octets"
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
@@ -24513,16 +24866,19 @@ msgid "Maximum number of requests per minute for each raw path (default is 300).
msgstr ""
msgid "Maximum number of unique IP addresses per user."
-msgstr ""
+msgstr "Nombre maximum d'adresses IP uniques par utilisateur."
+
+msgid "Maximum number of variables loaded (2000)"
+msgstr "Nombre maximum de variables chargées (2000)"
msgid "Maximum of 255 characters"
msgstr ""
msgid "Maximum page reached"
-msgstr ""
+msgstr "Page maximale atteinte"
msgid "Maximum page size"
-msgstr ""
+msgstr "Taille maximale de page"
msgid "Maximum project export download requests per minute"
msgstr ""
@@ -24534,7 +24890,7 @@ msgid "Maximum project import requests per minute"
msgstr ""
msgid "Maximum push size"
-msgstr ""
+msgstr "Taille maximale de poussée"
msgid "Maximum push size (MB)"
msgstr ""
@@ -24546,16 +24902,16 @@ msgid "Maximum requests per minute"
msgstr ""
msgid "Maximum running slices"
-msgstr ""
+msgstr "Nombre maximum de tranches en cours d'exécution"
msgid "Maximum size limit for a single commit."
-msgstr ""
+msgstr "Taille maximale pour un commit unique."
msgid "Maximum size limit for each repository."
-msgstr ""
+msgstr "Taille maximale pour chaque dépôt."
msgid "Maximum size of Elasticsearch bulk indexing requests."
-msgstr ""
+msgstr "Taille maximale des requêtes d'indexation en bloc Elasticsearch."
msgid "Maximum size of export files."
msgstr ""
@@ -24564,19 +24920,19 @@ msgid "Maximum size of import files."
msgstr ""
msgid "Maximum size of individual attachments in comments."
-msgstr ""
+msgstr "Taille maximale des pièces jointes individuelles dans les commentaires."
msgid "Maximum size of pages (MB)"
-msgstr ""
+msgstr "Taille maximale des pages (Mo)"
msgid "Maximum snippet size"
-msgstr ""
+msgstr "Taille maximale d'extrait"
msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
msgstr ""
msgid "Maximum time that users are allowed to skip the setup of two-factor authentication (in hours). Set to 0 (zero) to enforce at next sign in."
-msgstr ""
+msgstr "Durée maximale pendant laquelle les utilisateurs sont autorisés à ignorer la configuration de l'authentification à deux facteurs (en heures). Définir sur 0 (zéro) pour l'imposer à la prochaine connexion."
msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited."
msgstr ""
@@ -24591,49 +24947,49 @@ msgid "May"
msgstr "mai"
msgid "Mean time to merge"
-msgstr ""
+msgstr "Temps moyen jusqu'à la fusion"
msgid "Measured in bytes of code. Excludes generated and vendored code."
-msgstr ""
+msgstr "Mesurés en octets de code. Hors code généré ou vendu."
msgid "Medium timeout"
-msgstr ""
+msgstr "Délai d'expiration moyen"
msgid "Medium vulnerabilities present"
-msgstr ""
+msgstr "Vulnérabilités moyennes présentes"
msgid "Member since"
-msgstr ""
+msgstr "Membre depuis"
msgid "Member since %{date}"
msgstr "Membre depuis le %{date}"
msgid "Member since:"
-msgstr ""
+msgstr "Membre depuis :"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
-msgstr ""
+msgstr "%{member_name} vous a invité à rejoindre GitLab"
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
-msgstr ""
+msgstr "Invitation à rejoindre le %{project_or_group} %{project_or_group_name}"
msgid "Members"
msgstr "Membres"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
-msgstr ""
+msgstr "Les membres peuvent être ajoutés par les %{i_open}Mainteneurs%{i_close} ou %{i_open}Propriétaires%{i_close} du projet"
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
msgid "Members of %{group} can also merge into this branch: %{branch}"
-msgstr ""
+msgstr "Les membres de %{group} peuvent aussi fusionner vers cette branche : %{branch}"
msgid "Members of %{group} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "Les membres de %{group} peuvent également pousser vers cette branche : %{branch}"
msgid "Members of a group may only view projects they have permission to access"
-msgstr ""
+msgstr "Les membres d'un groupe ne peuvent voir que les projets auxquels ils ont le droit d'accéder"
msgid "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seat in use and will be billed for the overage."
msgid_plural "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seats in use and will be billed for the overage."
@@ -24645,68 +25001,68 @@ msgstr ""
msgid "MembersOverage|Your subscription includes %d seat."
msgid_plural "MembersOverage|Your subscription includes %d seats."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Votre abonnement comprend %d siège."
+msgstr[1] "Votre abonnement comprend %d sièges."
msgid "Membership"
-msgstr ""
+msgstr "Abonnement"
msgid "Members|%{time} by %{user}"
-msgstr ""
+msgstr "%{time} par %{user}"
msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
-msgstr ""
+msgstr "%{userName} est pour le moment un utilisateur LDAP. Modifier ses permissions prendra le dessus sur les paramètres provenant de la synchronisation du groupe LDAP."
msgid "Members|2FA"
-msgstr ""
+msgstr "A2F"
msgid "Members|An error occurred while trying to enable LDAP override, please try again."
msgstr ""
msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative pour rétablir les paramètres de synchronisation du groupe LDAP, veuillez réessayer."
msgid "Members|An error occurred while updating the member's expiration date, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de la date d'expiration du membre, veuillez réessayer."
msgid "Members|An error occurred while updating the member's role, please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du rôle du membre, veuillez réessayer."
msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir refuser la demande de %{usersName} pour rejoindre « %{source} »"
msgid "Members|Are you sure you want to leave \"%{source}\"?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir quitter « %{source} » ?"
msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer « %{groupName} » ?"
msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\"?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer %{usersName} de « %{source} » ?"
msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\"?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer ce membre orphelin de « %{source} » ?"
msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
msgstr ""
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir retirer votre demande d'accès pour « %{source} »"
msgid "Members|Direct"
-msgstr ""
+msgstr "Direct"
msgid "Members|Disabled"
-msgstr ""
+msgstr "Désactivé"
msgid "Members|Edit permissions"
-msgstr ""
+msgstr "Modifier les permissions"
msgid "Members|Enabled"
-msgstr ""
+msgstr "Activé"
msgid "Members|Expiration date removed successfully."
-msgstr ""
+msgstr "La date d'expiration a été supprimée avec succès."
msgid "Members|Expiration date updated successfully."
msgstr "La date d'expiration a été mise à jour avec succès."
@@ -24715,52 +25071,52 @@ msgid "Members|Filter groups"
msgstr ""
msgid "Members|Filter members"
-msgstr ""
+msgstr "Filtrer les membres"
msgid "Members|Inherited"
-msgstr ""
+msgstr "Hérité"
msgid "Members|LDAP override enabled."
-msgstr ""
+msgstr "Outrepassement de LDAP activé."
msgid "Members|Leave \"%{source}\""
-msgstr ""
+msgstr "Quitter « %{source} »"
msgid "Members|Membership"
-msgstr ""
+msgstr "Appartenance"
msgid "Members|Remove \"%{groupName}\""
-msgstr ""
+msgstr "Supprimer « %{groupName} »"
msgid "Members|Remove group"
-msgstr ""
+msgstr "Supprimer le groupe"
msgid "Members|Revert to LDAP group sync settings"
-msgstr ""
+msgstr "Rétablir les paramètres de synchronisation de groupe LDAP"
msgid "Members|Reverted to LDAP group sync settings."
-msgstr ""
+msgstr "Paramètres de synchronisation de groupe LDAP rétablis."
msgid "Members|Role updated successfully."
-msgstr ""
+msgstr "Rôle mis à jour avec succès."
msgid "Members|Search groups"
-msgstr ""
+msgstr "Rechercher des groupes"
msgid "Members|Search invited"
msgstr "Rechercher les invités"
msgid "Member|Deny access"
-msgstr ""
+msgstr "Refuser l'accès"
msgid "Member|Revoke invite"
-msgstr ""
+msgstr "Révoquer l'invitation"
msgid "Memory Usage"
msgstr ""
msgid "Menu"
-msgstr ""
+msgstr "Menu"
msgid "Merge"
msgstr ""
@@ -24772,7 +25128,7 @@ msgid "Merge Request"
msgstr "Demande de fusion"
msgid "Merge Request Analytics"
-msgstr ""
+msgstr "Données analytiques de Demande de Fusion"
msgid "Merge Requests"
msgstr "Demandes de fusion"
@@ -24781,28 +25137,28 @@ msgid "Merge Requests created"
msgstr "Demandes de fusion créées"
msgid "Merge Requests in Review"
-msgstr ""
+msgstr "Demandes de fusion en Examen"
msgid "Merge Requests merged"
msgstr ""
msgid "Merge automatically (%{strategy})"
-msgstr ""
+msgstr "Fusionner automatiquement (%{strategy})"
msgid "Merge blocked: all merge request dependencies must be merged."
-msgstr ""
+msgstr "Fusion bloquée : toutes les dépendances de demande de fusion doivent être fusionnées."
msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
-msgstr ""
+msgstr "Fusion bloquée : la demande de fusion doit être marquée comme prête. Elle est toujours marquée comme brouillon."
msgid "Merge blocked: new changes were just added."
-msgstr ""
+msgstr "Fusion bloquée : de nouvelles modifications viennent d'être apportées."
msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
-msgstr ""
+msgstr "Fusion bloquée : le pipeline doit réussir. Il est en attente d'une tâche manuelle pour continuer."
msgid "Merge blocked: the source branch must be rebased onto the target branch."
-msgstr ""
+msgstr "Fusion bloquée : la branche source doit être rebasée sur la branche cible."
msgid "Merge commit SHA"
msgstr ""
@@ -24832,46 +25188,46 @@ msgid "Merge request"
msgstr "Demande de fusion"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
-msgstr ""
+msgstr "La demande de fusion %{mr_link} a été examinée par %{mr_author}"
msgid "Merge request actions"
msgstr ""
msgid "Merge request analytics"
-msgstr ""
+msgstr "Données analytiques des demandes de fusion"
msgid "Merge request approvals"
msgstr "Approbations de la demande de fusion"
msgid "Merge request commits"
-msgstr ""
+msgstr "Commits de demande de fusion"
msgid "Merge request dependencies"
msgstr ""
msgid "Merge request events"
-msgstr ""
+msgstr "Événements de demande de fusion"
msgid "Merge request locked."
-msgstr ""
+msgstr "Demande de fusion verrouillée."
msgid "Merge request not merged"
msgstr ""
msgid "Merge request reports"
-msgstr ""
+msgstr "Rapports de demande de fusion"
msgid "Merge request unlocked."
-msgstr ""
+msgstr "Demande de fusion déverrouillée."
msgid "Merge request was scheduled to merge after pipeline succeeds"
-msgstr ""
+msgstr "La fusion de la demande de fusion a été programmée après que le pipeline ait réussi"
msgid "Merge requests"
msgstr "Demandes de fusion"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "Les paramètres des approbations et des demandes de fusion ont changé de place."
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"
@@ -24880,7 +25236,7 @@ msgid "Merge the feature branch into the target branch and fix any conflicts. %{
msgstr ""
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
-msgstr ""
+msgstr "Fusion indisponible : les demandes de fusion dans un nœud Geo secondaire sont en lecture seule."
msgid "Merge unverified changes"
msgstr ""
@@ -24925,16 +25281,16 @@ msgid "MergeRequestAnalytics|Date Merged"
msgstr ""
msgid "MergeRequestAnalytics|Line changes"
-msgstr ""
+msgstr "Lignes modifiées"
msgid "MergeRequestAnalytics|Merge Request"
-msgstr ""
+msgstr "Demande de Fusion"
msgid "MergeRequestAnalytics|Milestone"
-msgstr ""
+msgstr "Jalon"
msgid "MergeRequestAnalytics|Pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
@@ -24949,7 +25305,7 @@ msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%
msgstr ""
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
-msgstr ""
+msgstr "Mise en commentaire des lignes %{selectStart}start%{selectEnd} à %{end}"
msgid "MergeRequestDiffs|Select comment starting line"
msgstr ""
@@ -24961,16 +25317,16 @@ msgid "MergeRequests|Create issue to resolve thread"
msgstr ""
msgid "MergeRequests|Reference copied"
-msgstr ""
+msgstr "Référence copiée"
msgid "MergeRequests|Saving the comment failed"
msgstr "L’enregistrement du commentaire a échoué"
msgid "MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch."
-msgstr ""
+msgstr "L'écrasement a échoué : Écrasez les commits en local, résolvez les éventuels conflits, puis poussez la branche."
msgid "MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging."
-msgstr ""
+msgstr "Écrasement non autorisé : Ce projet ne vous autorise pas à écraser les commits lors de la fusion."
msgid "MergeRequests|Thread stays resolved"
msgstr ""
@@ -25009,22 +25365,22 @@ msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{li
msgstr ""
msgid "MergeRequest|Approved by @%{username}"
-msgstr ""
+msgstr "Approuvée par @%{username}"
msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
-msgstr ""
+msgstr "Impossible d'afficher cette demande de fusion en raison d'une erreur interne. Contactez votre administrateur."
msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
-msgstr ""
+msgstr "Impossible d'afficher cette demande de fusion car le projet divergent a été supprimé."
msgid "MergeRequest|Can't show this merge request because the source branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch."
-msgstr ""
+msgstr "Impossible d’afficher cette demande de fusion car la branche source %{branch_badge} est absente du projet %{path_badge}. Fermez cette demande de fusion ou actualisez la branche source."
msgid "MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch."
-msgstr ""
+msgstr "Impossible d’afficher cette demande de fusion car la branche cible %{branch_badge} est absente du projet %{path_badge}. Fermez cette demande de fusion ou actualisez la branche cible."
msgid "MergeRequest|Compare %{target} and %{source}"
-msgstr ""
+msgstr "Comparer %{target} et %{source}"
msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
msgstr ""
@@ -25036,31 +25392,31 @@ msgid "MergeRequest|No files found"
msgstr "Aucun fichier trouvé"
msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
-msgstr ""
+msgstr "Rechercher (p. ex. *.vue) (%{modifier_key}P)"
msgid "MergeTopics|%{sourceTopic} will be removed"
-msgstr ""
+msgstr "%{sourceTopic} sera supprimé"
msgid "MergeTopics|All assigned projects will be moved to %{targetTopic}"
-msgstr ""
+msgstr "Tous les projets assignés seront déplacés vers %{targetTopic}"
msgid "MergeTopics|Merge topics"
-msgstr ""
+msgstr "Fusionner les sujets"
msgid "MergeTopics|Merging topics will cause the following:"
-msgstr ""
+msgstr "Fusionner les sujets aura les conséquences suivantes :"
msgid "MergeTopics|Move all assigned projects from the source topic to the target topic and remove the source topic."
-msgstr ""
+msgstr "Déplacer tous les projets assignés du sujet source vers le sujet cible et supprimer le sujet source."
msgid "MergeTopics|Source topic"
-msgstr ""
+msgstr "Sujet source"
msgid "MergeTopics|Target topic"
-msgstr ""
+msgstr "Sujet cible"
msgid "MergeTopics|This action cannot be undone."
-msgstr ""
+msgstr "Cette action ne peut pas être annulée."
msgid "Merged"
msgstr "Fusionnée"
@@ -25072,25 +25428,25 @@ msgid "Merged branches are being deleted. This can take some time depending on t
msgstr ""
msgid "Merged by"
-msgstr ""
+msgstr "Fusionné par"
msgid "Merged this merge request."
msgstr ""
msgid "Merged: %{merged}"
-msgstr ""
+msgstr "Fusionné: %{merged}"
msgid "Merges this merge request immediately."
-msgstr ""
+msgstr "Fusionne cette demande de fusion immédiatement."
msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
-msgstr ""
+msgstr "Fusionner immédiatement n'est pas recommandé car cela peut avoir un impact négatif sur le train de fusion existant. Lisez la %{docsLinkStart}documentation%{docsLinkEnd} pour plus d'informations."
msgid "Mermaid diagram"
-msgstr ""
+msgstr "Diagramme Mermaid"
msgid "Message"
-msgstr ""
+msgstr "Message"
msgid "Messages"
msgstr "Messages"
@@ -25099,7 +25455,7 @@ msgid "Method"
msgstr ""
msgid "Method call threshold (ms)"
-msgstr ""
+msgstr "Seuil d'appel de méthode (ms)"
msgid "Metric was successfully added."
msgstr ""
@@ -25108,7 +25464,7 @@ msgid "Metric was successfully updated."
msgstr ""
msgid "Metric:"
-msgstr ""
+msgstr "Métrique :"
msgid "MetricChart|Please select a metric"
msgstr ""
@@ -25117,22 +25473,22 @@ msgid "MetricChart|Selected"
msgstr ""
msgid "MetricChart|There is no data available. Please change your selection."
-msgstr ""
+msgstr "Aucune donnée disponible. Veuillez modifier votre sélection."
msgid "MetricChart|There is too much data to calculate. Please change your selection."
-msgstr ""
+msgstr "Il y a trop de données à calculer. Veuillez modifier votre sélection."
msgid "MetricImages|There was an issue deleting the image."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de l'image."
msgid "MetricImages|There was an issue loading metric images."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des images des métriques."
msgid "MetricImages|There was an issue updating your image."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour de votre image."
msgid "MetricImages|There was an issue uploading your image."
-msgstr ""
+msgstr "Une erreur s'est produite lors du téléversement de votre image."
msgid "Metrics"
msgstr "Métriques"
@@ -25147,79 +25503,79 @@ msgid "Metrics Dashboard"
msgstr ""
msgid "Metrics Dashboard YAML definition"
-msgstr ""
+msgstr "Définition YAML du tableau de bord des métriques"
msgid "Metrics Dashboard YAML definition is invalid:"
-msgstr ""
+msgstr "La définition YAML du tableau de bord des métriques n'est pas valide :"
msgid "Metrics Dashboard YAML definition is valid."
-msgstr ""
+msgstr "La définition YAML du tableau de bord des métriques est valide."
msgid "Metrics and profiling"
msgstr "Statistiques et rapports"
msgid "Metrics:"
-msgstr ""
+msgstr "Métriques :"
msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
+msgstr "Une annotation ne peut pas faire partie d'une grappe de serveurs et d'un environnement en même temps"
msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
-msgstr ""
+msgstr "L'annotation n'a pas été supprimée"
msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
-msgstr ""
+msgstr "L'annotation doit appartenir à une grappe de serveurs ou à un environnement"
msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "Le tableau de bord avec le chemin demandé est introuvable"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à créer une annotation pour la grappe de serveurs sélectionnée"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à créer une annotation pour l'environnement sélectionné"
msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à supprimer cette annotation"
msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
-msgstr ""
+msgstr "Ajouter un bouton au tableau de bord des métriques qui se connecte directement à votre tableau de bord externe existant."
msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
-msgstr ""
+msgstr "Indiquez si vous souhaitez afficher les métriques du tableau de bord en UTC ou dans le fuseau horaire local de l'utilisateur."
msgid "MetricsSettings|Dashboard timezone"
-msgstr ""
+msgstr "Fuseau horaire du tableau de bord"
msgid "MetricsSettings|External dashboard URL"
-msgstr ""
+msgstr "URL du tableau de bord externe"
msgid "MetricsSettings|Manage metrics dashboard settings."
-msgstr ""
+msgstr "Gérer les paramètres du tableau de bord des métriques."
msgid "MetricsSettings|Metrics"
-msgstr ""
+msgstr "Métriques"
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
-msgstr ""
+msgstr "UTC (temps universel coordonné)"
msgid "MetricsSettings|User's local timezone"
-msgstr ""
+msgstr "Fuseau horaire local de l’utilisateur"
msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "Le tableau de bord avec le chemin demandé est introuvable"
msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
-msgstr ""
+msgstr "Vous n'avez pas l'autorisation d'ajouter une étoile à ce tableau de bord"
msgid "Metrics|1. Define and preview panel"
-msgstr ""
+msgstr "1. Définissez et prévisualisez le panneau"
msgid "Metrics|2. Paste panel YAML into dashboard"
-msgstr ""
+msgstr "2. Collez le code YAML du panneau dans le tableau de bord"
msgid "Metrics|Add metric"
msgstr ""
@@ -25231,25 +25587,25 @@ msgid "Metrics|Avg"
msgstr ""
msgid "Metrics|Back to dashboard"
-msgstr ""
+msgstr "Retour au tableau de bord"
msgid "Metrics|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consultez la documentation sur l’intégration et la livraison continues (CI/CD) concernant le déploiement dans un environnement"
msgid "Metrics|Collapse panel"
-msgstr ""
+msgstr "Réduire le panneau"
msgid "Metrics|Collapse panel (Esc)"
-msgstr ""
+msgstr "Réduire le panneau (Échap)"
msgid "Metrics|Copy YAML"
-msgstr ""
+msgstr "Copier YAML"
msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
-msgstr ""
+msgstr "Copiez et collez le YAML du panneau dans votre fichier YAML du tableau de bord."
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
@@ -25258,19 +25614,19 @@ msgid "Metrics|Create metric"
msgstr "Créer une métrique"
msgid "Metrics|Create new dashboard"
-msgstr ""
+msgstr "Créer un nouveau tableau de bord"
msgid "Metrics|Create your dashboard configuration file"
-msgstr ""
+msgstr "Créer votre fichier de configuration de tableau de bord"
msgid "Metrics|Current"
msgstr ""
msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "Les fichiers des tableaux de bord se trouvent à la racine de ce projet dans %{codeStart}.gitlab/dashboards%{codeEnd}."
msgid "Metrics|Define panel YAML below to preview panel."
-msgstr ""
+msgstr "Définissez le YAML du panneau ci-dessous pour prévisualiser le panneau."
msgid "Metrics|Delete metric"
msgstr ""
@@ -25279,10 +25635,10 @@ msgid "Metrics|Delete metric?"
msgstr ""
msgid "Metrics|Duplicate"
-msgstr ""
+msgstr "Dupliquer"
msgid "Metrics|Duplicate current dashboard"
-msgstr ""
+msgstr "Dupliquer le tableau de bord actuel"
msgid "Metrics|Duplicate dashboard"
msgstr ""
@@ -25294,7 +25650,7 @@ msgid "Metrics|Duplicating..."
msgstr ""
msgid "Metrics|Edit dashboard YAML"
-msgstr ""
+msgstr "Modifier le YAML du tableau de bord"
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
@@ -25302,13 +25658,13 @@ msgstr[0] ""
msgstr[1] ""
msgid "Metrics|Expand panel"
-msgstr ""
+msgstr "Étendre le panneau"
msgid "Metrics|For grouping similar metrics"
msgstr "Pour regrouper des métriques similaires"
msgid "Metrics|Invalid time range, please verify."
-msgstr ""
+msgstr "Intervalle de temps invalide, veuillez vérifier."
msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
@@ -25317,10 +25673,10 @@ msgid "Metrics|Legend label (optional)"
msgstr "Libellé de légende (facultatif)"
msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
-msgstr ""
+msgstr "Le lien contient une fenêtre de temps non valide, veuillez vérifier le lien pour voir la période demandée."
msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
-msgstr ""
+msgstr "Le lien contient des informations de graphique non valides, veuillez le vérifier pour voir le panneau étendu."
msgid "Metrics|Manage chart links"
msgstr ""
@@ -25329,13 +25685,13 @@ msgid "Metrics|Max"
msgstr ""
msgid "Metrics|Metrics Settings"
-msgstr ""
+msgstr "Paramètres des métriques"
msgid "Metrics|Min"
msgstr ""
msgid "Metrics|More actions"
-msgstr ""
+msgstr "Plus d'actions"
msgid "Metrics|Must be a valid PromQL query."
msgstr "La requête doit être une requête PromQL valide."
@@ -25347,10 +25703,10 @@ msgid "Metrics|Open repository"
msgstr ""
msgid "Metrics|Panel YAML"
-msgstr ""
+msgstr "YAML du panneau"
msgid "Metrics|Panel YAML copied"
-msgstr ""
+msgstr "YAML du panneau copié"
msgid "Metrics|Preview panel"
msgstr ""
@@ -25362,34 +25718,34 @@ msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentation des requêtes Prometheus"
msgid "Metrics|Refresh Prometheus data"
-msgstr ""
+msgstr "Rafraîchir les données Prometheus"
msgid "Metrics|Refresh dashboard"
-msgstr ""
+msgstr "Actualiser le tableau de bord"
msgid "Metrics|Select a value"
-msgstr ""
+msgstr "Sélectionner une valeur"
msgid "Metrics|Set refresh rate"
-msgstr ""
+msgstr "Définir la fréquence de rafraîchissement"
msgid "Metrics|Star dashboard"
-msgstr ""
+msgstr "Attribuer une étoile au tableau de bord"
msgid "Metrics|There was an error creating the dashboard."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création du tableau de bord."
msgid "Metrics|There was an error creating the dashboard. %{error}"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création du tableau de bord. %{error}"
msgid "Metrics|There was an error fetching annotations. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des annotations. Veuillez réessayer."
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr "Une erreur s’est produite lors de la récupération des données d’environnement. Veuillez réessayer."
msgid "Metrics|There was an error getting annotations information."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’obtention des informations d’annotations."
msgid "Metrics|There was an error getting dashboard validation warnings information."
msgstr ""
@@ -25401,7 +25757,7 @@ msgid "Metrics|There was an error getting environments information."
msgstr "Une erreur s’est produite lors de l’obtention des informations d’environnement."
msgid "Metrics|There was an error getting options for variable \"%{name}\"."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’obtention des options pour la variable « %{name} »."
msgid "Metrics|There was an error trying to validate your query"
msgstr ""
@@ -25410,10 +25766,10 @@ msgid "Metrics|There was an error while retrieving metrics"
msgstr "Une erreur est survenue lors de la récupération des métriques"
msgid "Metrics|There was an error while retrieving metrics. %{message}"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des métriques. %{message}"
msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "Pour créer un nouveau tableau de bord, ajoutez un nouveau fichier YAML dans %{codeStart}.gitlab/dashboards%{codeEnd} à la racine de ce projet."
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Le point de terminaison Prometheus a renvoyé une réponse contenant des données de déploiement inattendues"
@@ -25422,7 +25778,7 @@ msgid "Metrics|Unit label"
msgstr "Libellé de l’unité"
msgid "Metrics|Unstar dashboard"
-msgstr ""
+msgstr "Enlever une étoile au tableau de bord"
msgid "Metrics|Used as a title for the chart"
msgstr "Utilisé comme titre pour le graphique"
@@ -25434,10 +25790,10 @@ msgid "Metrics|Validating query"
msgstr ""
msgid "Metrics|Values"
-msgstr ""
+msgstr "Valeurs"
msgid "Metrics|View documentation"
-msgstr ""
+msgstr "Voir la documentation"
msgid "Metrics|Y-axis label"
msgstr "Libellé de l’axe Y"
@@ -25449,7 +25805,7 @@ msgid "Metrics|You're about to permanently delete this metric. This cannot be un
msgstr ""
msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
-msgstr ""
+msgstr "Le schéma de votre tableau de bord n’est pas valide. Modifiez le tableau de bord pour corriger le schéma YAML."
msgid "Metrics|e.g. HTTP requests"
msgstr ""
@@ -25473,18 +25829,18 @@ msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
msgid "Migration"
-msgstr ""
+msgstr "Migration"
msgid "Migration has been scheduled to be retried"
-msgstr ""
+msgstr "Une nouvelle tentative de migration a été planifiée"
msgid "Migration successful."
msgstr ""
msgid "Milestone"
msgid_plural "Milestones"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Jalon"
+msgstr[1] "Jalons"
msgid "Milestone due date"
msgstr "Date d'échéance du jalon"
@@ -25493,10 +25849,10 @@ msgid "Milestone lists not available with your current license"
msgstr "La liste des jalons n’est pas disponible avec votre licence actuelle"
msgid "MilestoneCombobox|An error occurred while searching for milestones"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la recherche de jalons"
msgid "MilestoneCombobox|Group milestones"
-msgstr ""
+msgstr "Jalons de groupe"
msgid "MilestoneCombobox|Milestone"
msgstr "Jalon"
@@ -25520,25 +25876,25 @@ msgid "MilestoneSidebar|Closed:"
msgstr "Fermé:"
msgid "MilestoneSidebar|Copy reference"
-msgstr ""
+msgstr "Copier la référence"
msgid "MilestoneSidebar|Due date"
msgstr "Date d'échéance"
msgid "MilestoneSidebar|Edit"
-msgstr ""
+msgstr "Editer"
msgid "MilestoneSidebar|From"
-msgstr ""
+msgstr "De"
msgid "MilestoneSidebar|Issues"
msgstr "Tickets"
msgid "MilestoneSidebar|Merge requests"
-msgstr ""
+msgstr "Demandes de fusion"
msgid "MilestoneSidebar|Merged:"
-msgstr ""
+msgstr "Fusionné :"
msgid "MilestoneSidebar|New Issue"
msgstr "Nouveau ticket"
@@ -25550,28 +25906,28 @@ msgid "MilestoneSidebar|No due date"
msgstr "Aucune date d'échéance"
msgid "MilestoneSidebar|No start date"
-msgstr ""
+msgstr "Aucune date de début"
msgid "MilestoneSidebar|None"
msgstr "Aucun"
msgid "MilestoneSidebar|Open:"
-msgstr ""
+msgstr "Ouvrir:"
msgid "MilestoneSidebar|Reference:"
-msgstr ""
+msgstr "Référence :"
msgid "MilestoneSidebar|Start date"
-msgstr ""
+msgstr "Date de début"
msgid "MilestoneSidebar|Toggle sidebar"
msgstr ""
msgid "MilestoneSidebar|Until"
-msgstr ""
+msgstr "Jusqu'à"
msgid "MilestoneSidebar|complete"
-msgstr ""
+msgstr "Terminé"
msgid "Milestones"
msgstr "Jalons"
@@ -25583,10 +25939,10 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
msgstr "Vous êtes sur le point de supprimer définitivement le jalon %{milestoneTitle}. Ce jalon n’est actuellement référencé par aucun ticket ni aucune demande de fusion."
msgid "Milestones|Close Milestone"
-msgstr ""
+msgstr "Fermer le jalon"
msgid "Milestones|Completed Issues (closed)"
-msgstr ""
+msgstr "Tickets terminés (fermés)"
msgid "Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}"
msgstr ""
@@ -25601,13 +25957,13 @@ msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
msgstr "Impossible de supprimer le jalon %{milestoneTitle}"
msgid "Milestones|Group Milestone"
-msgstr ""
+msgstr "Jalon de groupe"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr "Le jalon %{milestoneTitle} est introuvable"
msgid "Milestones|Ongoing Issues (open and assigned)"
-msgstr ""
+msgstr "Tickets en cours (ouverts et attribués)"
msgid "Milestones|Organize issues and merge requests into a cohesive group, and set optional start and due dates. %{learn_more_link}"
msgstr ""
@@ -25622,19 +25978,19 @@ msgid "Milestones|Promote Milestone"
msgstr "Promouvoir le jalon"
msgid "Milestones|Promote to Group Milestone"
-msgstr ""
+msgstr "Promouvoir en jalon de groupe"
msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
-msgstr ""
+msgstr "Promouvoir %{milestoneTitle} le rendra disponible pour tous les projets du groupe %{groupName}. Les jalons des projets portant le même nom seront fusionnés."
msgid "Milestones|Reopen Milestone"
-msgstr ""
+msgstr "Rouvrir le jalon"
msgid "Milestones|There are no closed milestones"
-msgstr ""
+msgstr "Il n’y a aucun jalon fermé"
msgid "Milestones|There are no open milestones"
-msgstr ""
+msgstr "Il n’y a aucun jalon ouvert"
msgid "Milestones|This action cannot be reversed."
msgstr "Cette action ne peut pas être annulée."
@@ -25643,7 +25999,10 @@ msgid "Milestones|Unstarted Issues (open and unassigned)"
msgstr "Tickets non commencés (ouverts et non attribués)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
-msgstr ""
+msgstr "Utiliser des jalons pour suivre les tickets et les demandes de fusion sur une période de temps déterminée"
+
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "terminé à %{percentage}%{percent}"
msgid "Min Value"
msgstr ""
@@ -25658,17 +26017,20 @@ msgid "Mirror direction"
msgstr "Sens du miroir"
msgid "Mirror only protected branches"
-msgstr ""
+msgstr "Mise en miroir des branches protégées uniquement"
msgid "Mirror repository"
-msgstr ""
+msgstr "Dépôt miroir"
msgid "Mirror settings are only available to GitLab administrators."
-msgstr ""
+msgstr "Les paramètres de miroir ne sont disponibles que pour les administrateurs GitLab."
msgid "Mirror user"
msgstr "Utilisateur accédant au miroir"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Dépôts mis en miroir"
@@ -25688,34 +26050,34 @@ msgid "Mirroring will only be available if the feature is included in the plan o
msgstr ""
msgid "Miscellaneous"
-msgstr ""
+msgstr "Divers"
msgid "Missing"
msgstr ""
msgid "Missing OAuth configuration for GitHub."
-msgstr ""
+msgstr "La configuration OAuth pour GitHub est manquante."
msgid "Missing OS"
-msgstr ""
+msgstr "OS manquant"
msgid "Missing arch"
-msgstr ""
+msgstr "Arch manquante"
msgid "Missing commit signatures endpoint!"
msgstr ""
msgid "MissingSSHKeyWarningLink|Add SSH key"
-msgstr ""
+msgstr "Ajouter une clé SSH"
msgid "MissingSSHKeyWarningLink|Don't show again"
-msgstr ""
+msgstr "Ne plus afficher"
msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
-msgstr ""
+msgstr "Vous ne pouvez ni pousser ni récupérer de dépôt tant que vous n'avez pas ajouté une clé SSH à votre profil."
msgid "MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile"
-msgstr ""
+msgstr "Vous ne pourrez ni récupérer ni pousser vers des dépôts via SSH tant que vous n'aurez pas ajouté une clé SSH à votre profil"
msgid "ModalButton|Add projects"
msgstr ""
@@ -25739,19 +26101,19 @@ msgid "Modify merge commit"
msgstr ""
msgid "Mon"
-msgstr ""
+msgstr "Lun"
msgid "Monday"
msgstr ""
msgid "Monitor"
-msgstr ""
+msgstr "Supervision"
msgid "Monitor GitLab with Prometheus."
-msgstr ""
+msgstr "Surveiller GitLab avec Prometheus."
msgid "Monitor Settings"
-msgstr ""
+msgstr "Paramètres de Supervision"
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -25760,16 +26122,16 @@ msgid "Monitoring"
msgstr "Supervision"
msgid "Month"
-msgstr ""
+msgstr "Mois"
msgid "Months"
msgstr "Mois"
msgid "More"
-msgstr ""
+msgstr "Plus"
msgid "More Details"
-msgstr ""
+msgstr "Plus de détails"
msgid "More Information"
msgstr ""
@@ -25790,10 +26152,10 @@ msgid "More information and share feedback"
msgstr ""
msgid "More information is available|here"
-msgstr ""
+msgstr "Plus d’information disponible|ici"
msgid "More information."
-msgstr ""
+msgstr "Plus d'informations."
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
@@ -25814,7 +26176,7 @@ msgid "Move"
msgstr "Déplacer"
msgid "Move down"
-msgstr ""
+msgstr "Déplacer vers le bas"
msgid "Move issue"
msgstr "Déplacer le ticket"
@@ -25829,13 +26191,13 @@ msgid "Move selection up"
msgstr ""
msgid "Move test case"
-msgstr ""
+msgstr "Déplacer le cas de test"
msgid "Move this issue to another project."
msgstr ""
msgid "Move up"
-msgstr ""
+msgstr "Déplacer vers le haut"
msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
msgstr ""
@@ -25844,7 +26206,7 @@ msgid "MoveIssue|Cannot move issue to project it originates from!"
msgstr ""
msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
-msgstr ""
+msgstr "Impossible de déplacer les tickets de type « %{issue_type} »."
msgid "Moved issue to %{label} column in the board."
msgstr ""
@@ -25859,13 +26221,13 @@ msgid "Moves this issue to %{path_to_project}."
msgstr ""
msgid "MrDeploymentActions|Deploy"
-msgstr ""
+msgstr "Déployer"
msgid "MrDeploymentActions|Re-deploy"
-msgstr ""
+msgstr "Redéployer"
msgid "MrDeploymentActions|Stop environment"
-msgstr ""
+msgstr "Arrêter l'environnement"
msgid "MrList|Assigned to %{name}"
msgstr "Assigné à %{name}"
@@ -25874,141 +26236,144 @@ msgid "MrList|Review requested from %{name}"
msgstr ""
msgid "MrSurvey|By continuing, you acknowledge that responses will be used to improve GitLab and in accordance with the %{linkStart}GitLab Privacy Policy%{linkEnd}."
-msgstr ""
+msgstr "En poursuivant, vous reconnaissez être informé que les réponses seront utilisées pour améliorer GitLab et cela dans le respect de la %{linkStart}Politique de Confidentialité de GitLab%{linkEnd}."
msgid "MrSurvey|How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
-msgstr ""
+msgstr "À quel point êtes-vous satisfait des %{strongStart}vitesse/performance%{strongEnd} des demandes de fusion ?"
msgid "MrSurvey|Merge request experience survey"
-msgstr ""
+msgstr "Enquête de satisfaction sur les demandes de fusion"
msgid "MrSurvey|Overall, how satisfied are you with merge requests?"
-msgstr ""
+msgstr "Dans l'ensemble, êtes-vous satisfait des demandes de fusion ?"
msgid "MrSurvey|Thank you for your feedback!"
-msgstr ""
+msgstr "Merci pour vos commentaires !"
msgid "Multi-project"
-msgstr ""
+msgstr "Multi-projet"
msgid "Multiple HTTP integrations are not supported for this project"
-msgstr ""
+msgstr "Ce projet ne peut pas prendre en charge plusieurs intégrations HTTP"
msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
-msgstr ""
+msgstr "Il est possible d'avoir plusieurs plages d'adresses IP. N'affecte pas l'accès aux paramètres du groupe."
msgid "Multiple Prometheus integrations are not supported"
-msgstr ""
+msgstr "Les intégrations multiples de Prometheus ne sont pas prises en charge"
msgid "Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1."
-msgstr ""
+msgstr "Multiplicateur à appliquer aux intervalles d'interrogation. Les valeurs décimales sont prises en charge. La valeur par défaut est 1."
msgid "My awesome group"
msgstr ""
msgid "My company or team"
-msgstr ""
+msgstr "Mon entreprise ou mon équipe"
msgid "My topic"
-msgstr ""
+msgstr "Mon sujet"
msgid "My-Reaction"
msgstr "Ma réaction"
msgid "NEW"
-msgstr ""
+msgstr "NOUVEAU"
msgid "Name"
msgstr "Nom"
msgid "Name can't be blank"
-msgstr ""
+msgstr "Le nom ne peut pas être vide"
msgid "Name has already been taken"
msgstr ""
msgid "Name is already taken."
-msgstr ""
+msgstr "Le nom est déjà pris."
msgid "Name new label"
msgstr "Nommez la nouvelle étiquette"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr "Nom à utiliser comme nom d'expéditeur pour les courriels du Service d’Assistance."
+
msgid "Name:"
msgstr "Nom :"
msgid "Namespace"
-msgstr ""
+msgstr "Espace de noms"
msgid "Namespace ID:"
-msgstr ""
+msgstr "ID espace de noms :"
msgid "Namespace:"
-msgstr ""
+msgstr "Espace de noms :"
msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{namespace_name} contient %{locked_project_count} projet verrouillé"
+msgstr[1] "%{namespace_name} contient %{locked_project_count} projets verrouillés"
msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr ""
+msgstr "%{namespace_name} est maintenant en lecture seule. Vous ne pouvez pas : %{base_message}"
msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
-msgstr ""
+msgstr "Si vous atteignez 100%% de la capacité de stockage, vous ne pourrez pas : %{base_message}"
msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
-msgstr ""
+msgstr "Veuillez acheter du stockage supplémentaire pour déverrouiller vos projets au-delà de la limite de projet gratuite de %{free_size_limit}. Vous ne pouvez pas %{base_message}"
msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
-msgstr ""
+msgstr "Vous avez utilisé la totalité de votre stockage supplémentaire, veuillez en acheter davantage pour déverrouiller vos projets au-delà de la limite gratuite de %{free_size_limit}. Vous ne pouvez pas %{base_message}"
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
+msgstr "Vous avez atteint %{usage_in_percent} de la capacité de stockage de %{namespace_name} (%{used_storage} sur %{storage_limit})"
msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
-msgstr ""
+msgstr "Vous avez atteint la limite de stockage gratuit de %{free_size_limit} sur un ou plusieurs projets."
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
-msgstr ""
+msgstr "pousser vers votre dépôt, créer des pipelines, créer des tickets ou ajouter des commentaires. Pour réduire la quantité de stockage, supprimez les dépôts, artéfacts, wikis, tickets et pipelines inutilisés."
msgid "NamespaceStorage|%{name_with_link} namespace has approximately %{percent} (%{size}) namespace storage space remaining."
-msgstr ""
+msgstr "L'espace de noms %{name_with_link} dispose d'environ %{percent} (%{size}) d'espace de stockage restant."
msgid "NamespaceStorage|%{name_with_link} namespace has exceeded its namespace storage limit."
-msgstr ""
+msgstr "L'espace de noms %{name_with_link} a dépassé sa limite de stockage d'espace de noms."
msgid "NamespaceStorage|%{name}(%{url}) namespace has approximately %{percent} (%{size}) namespace storage space remaining."
-msgstr ""
+msgstr "L'espace de noms %{name}(%{url}) dispose d'environ %{percent} (%{size}) d'espace de stockage restant."
msgid "NamespaceStorage|%{name}(%{url}) namespace has exceeded its namespace storage limit."
-msgstr ""
+msgstr "L'espace de noms %{name}(%{url}) a dépassé sa limite de stockage d'espace de noms."
msgid "NamespaceStorage|Action required: Approximately %{percentage_of_available_storage}%% of namespace storage remains for %{namespace_name}"
-msgstr ""
+msgstr "Action requise : Environ %{percentage_of_available_storage}%% de stockage d'espace de noms restant pour %{namespace_name}"
msgid "NamespaceStorage|Action required: Storage has been exceeded for %{namespace_name}"
-msgstr ""
+msgstr "Action requise : Le stockage a été dépassé pour %{namespace_name}"
msgid "NamespaceStorage|Buy more storage"
-msgstr ""
+msgstr "Acheter plus de stockage"
msgid "NamespaceStorage|We recommend that you buy additional storage to ensure your service is not interrupted."
-msgstr ""
+msgstr "Nous vous recommandons d’acheter du stockage supplémentaire pour vous assurer que votre service ne soit pas interrompu."
msgid "NamespaceStorage|We recommend that you buy additional storage to resume normal service."
-msgstr ""
+msgstr "Nous vous recommandons d’acheter du stockage supplémentaire pour retrouver un service normal."
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 ""
+msgstr "Les utilisateurs en attente doivent être examinés et approuvés par un propriétaire de groupe. En savoir plus sur la %{user_caps_link_start}limitation du nombre d'utilisateurs%{link_end} et sur l'%{users_pending_approval_link_start}approbation d'utilisateurs en attente%{link_end}."
msgid "NamespaceUserCap|View pending approvals"
-msgstr ""
+msgstr "Voir les approbations en attente"
msgid "NamespaceUserCap|Your group has reached its billable member limit"
msgstr ""
msgid "Namespaces"
-msgstr ""
+msgstr "Espaces de noms"
msgid "Namespaces to index"
msgstr ""
@@ -26023,40 +26388,40 @@ msgid "Navigate to the project to close the milestone."
msgstr ""
msgid "Navigation bar"
-msgstr ""
+msgstr "Barre de navigation"
msgid "NavigationTheme|Blue"
-msgstr ""
+msgstr "Bleu"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "Mode Sombre (alpha)"
msgid "NavigationTheme|Gray"
-msgstr ""
+msgstr "Gris"
msgid "NavigationTheme|Green"
-msgstr ""
+msgstr "Vert"
msgid "NavigationTheme|Indigo"
-msgstr ""
+msgstr "Indigo"
msgid "NavigationTheme|Light Blue"
-msgstr ""
+msgstr "Bleu clair"
msgid "NavigationTheme|Light Gray"
-msgstr ""
+msgstr "Gris clair"
msgid "NavigationTheme|Light Green"
-msgstr ""
+msgstr "Vert clair"
msgid "NavigationTheme|Light Indigo"
-msgstr ""
+msgstr "Indigo clair"
msgid "NavigationTheme|Light Red"
-msgstr ""
+msgstr "Rouge clair"
msgid "NavigationTheme|Red"
-msgstr ""
+msgstr "Rouge"
msgid "Nav|Help"
msgstr "Aide"
@@ -26083,7 +26448,7 @@ msgid "Network"
msgstr "Réseau"
msgid "Network:"
-msgstr ""
+msgstr "Réseau :"
msgid "Never"
msgstr "Jamais"
@@ -26098,19 +26463,19 @@ msgid "New Application"
msgstr "Nouvelle application"
msgid "New Branch"
-msgstr ""
+msgstr "Nouvelle Branche"
msgid "New Deploy Key"
-msgstr ""
+msgstr "Nouvelle clé de déploiement"
msgid "New Environment"
msgstr ""
msgid "New Epic"
-msgstr ""
+msgstr "Nouvelle Épopée"
msgid "New File"
-msgstr ""
+msgstr "Nouveau fichier"
msgid "New Group"
msgstr "Nouveau groupe"
@@ -26127,13 +26492,13 @@ msgstr[0] "Nouveau ticket"
msgstr[1] "Nouveaux tickets"
msgid "New Jira import"
-msgstr ""
+msgstr "Nouvelle importation Jira"
msgid "New Label"
msgstr "Nouvelle étiquette"
msgid "New Milestone"
-msgstr ""
+msgstr "Nouveau jalon"
msgid "New Pages Domain"
msgstr ""
@@ -26147,20 +26512,23 @@ msgstr "Nouvelle planification de pipeline"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr "Nouvelle Branche Protégée"
+
msgid "New Requirement"
-msgstr ""
+msgstr "Nouvelle Exigence"
msgid "New Snippet"
msgstr "Nouvel extrait de code"
msgid "New Test Case"
-msgstr ""
+msgstr "Nouveau Cas de Test"
msgid "New User"
-msgstr ""
+msgstr "Nouvel utilisateur"
msgid "New application"
-msgstr ""
+msgstr "Nouvelle application"
msgid "New branch"
msgstr "Nouvelle branche"
@@ -26169,10 +26537,10 @@ msgid "New branch unavailable"
msgstr "Nouvelle branche indisponible"
msgid "New confidential epic title "
-msgstr ""
+msgstr "Nouveau titre d'épopée confidentielle "
msgid "New confidential issue title"
-msgstr ""
+msgstr "Nouveau titre de ticket confidentiel"
msgid "New deploy key"
msgstr ""
@@ -26181,7 +26549,7 @@ msgid "New directory"
msgstr "Nouveau dossier"
msgid "New discussion"
-msgstr ""
+msgstr "Nouvelle discussion"
msgid "New email address added"
msgstr ""
@@ -26196,7 +26564,7 @@ msgid "New epic title"
msgstr ""
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "Le nouveau jeton d'accès du suivi des erreurs a été généré !"
msgid "New file"
msgstr "Nouveau fichier"
@@ -26220,13 +26588,13 @@ msgid "New issue title"
msgstr ""
msgid "New iteration created"
-msgstr ""
+msgstr "Nouvelle itération créée"
msgid "New label"
msgstr "Nouvelle étiquette"
msgid "New list"
-msgstr ""
+msgstr "Nouvelle liste"
msgid "New merge request"
msgstr "Nouvelle demande de fusion"
@@ -26235,28 +26603,28 @@ msgid "New milestone"
msgstr "Nouveau jalon"
msgid "New name"
-msgstr ""
+msgstr "Nouveau Nom"
msgid "New password"
msgstr ""
msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
-msgstr ""
+msgstr "Les nouveaux pipelines entraînent l'annulation de ceux plus anciens qui sont en attente ou en cours d'exécution sur la même branche."
msgid "New project"
msgstr "Nouveau projet"
msgid "New project page"
-msgstr ""
+msgstr "Page de nouveau projet"
msgid "New project pages"
-msgstr ""
+msgstr "Pages de nouveau projet"
msgid "New project/repository"
msgstr "Nouveau projet/dépôt"
msgid "New public deploy key"
-msgstr ""
+msgstr "Nouvelle clé de déploiement publique"
msgid "New related %{issueType}"
msgstr "Nouveau %{issueType} lié"
@@ -26265,10 +26633,10 @@ msgid "New release"
msgstr ""
msgid "New requirement"
-msgstr ""
+msgstr "Nouvelle exigence"
msgid "New response for issue #%{issue_iid}:"
-msgstr ""
+msgstr "Nouvelle réponse pour le ticket #%{issue_iid} :"
msgid "New runners registration token has been generated!"
msgstr ""
@@ -26286,10 +26654,10 @@ msgid "New tag"
msgstr "Nouvelle étiquette"
msgid "New test case"
-msgstr ""
+msgstr "Nouveau cas de test"
msgid "New topic"
-msgstr ""
+msgstr "Nouveau sujet"
msgid "New users set to external"
msgstr ""
@@ -26301,22 +26669,22 @@ msgid "Newest first"
msgstr "Plus récent en premier"
msgid "Newly-registered users are external by default"
-msgstr ""
+msgstr "Les utilisateurs nouvellement enregistrés sont externes par défaut"
msgid "Next"
-msgstr "Suivant"
+msgstr "GitLab Next"
msgid "Next commit"
-msgstr ""
+msgstr "Commit suivant"
msgid "Next design"
-msgstr ""
+msgstr "Design suivant"
msgid "Next file in diff"
-msgstr ""
+msgstr "Fichier suivant du diff"
msgid "Next scan"
-msgstr ""
+msgstr "Analyse suivante"
msgid "Next unresolved discussion"
msgstr ""
@@ -26337,16 +26705,16 @@ msgid "No %{providerTitle} repositories found"
msgstr ""
msgid "No CSV data to display."
-msgstr ""
+msgstr "Pas de données CSV à afficher."
msgid "No Epic"
msgstr ""
msgid "No Google Cloud projects - You need at least one Google Cloud project"
-msgstr ""
+msgstr "Aucun projet Google Cloud - Vous avez besoin d'au moins un projet Google Cloud"
msgid "No Matching Results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "No Milestone"
msgstr "Aucun jalon"
@@ -26355,7 +26723,7 @@ msgid "No Scopes"
msgstr ""
msgid "No Work Item Link found"
-msgstr ""
+msgstr "Aucun Lien d'Élément de Travail trouvé"
msgid "No active admin user found"
msgstr ""
@@ -26370,7 +26738,7 @@ msgid "No approvers"
msgstr ""
msgid "No artifacts found"
-msgstr ""
+msgstr "Aucun artéfact trouvé"
msgid "No assignee"
msgstr "Aucune personne assignée"
@@ -26379,7 +26747,7 @@ msgid "No authentication methods configured."
msgstr ""
msgid "No available branches"
-msgstr ""
+msgstr "Aucune branche disponible"
msgid "No branches found"
msgstr "Aucune branche trouvée"
@@ -26391,22 +26759,22 @@ msgid "No changes"
msgstr "Aucun changement"
msgid "No changes between %{source} and %{target}"
-msgstr ""
+msgstr "Aucune modification entre %{source} et %{target}"
msgid "No child epics match applied filters"
-msgstr ""
+msgstr "Aucune épopée enfant ne correspond aux filtres appliqués"
msgid "No commenters"
msgstr ""
msgid "No commits present here"
-msgstr ""
+msgstr "Aucun commit présent ici"
msgid "No committers"
msgstr ""
msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
-msgstr ""
+msgstr "Aucun courriel de confirmation reçu ? Vérifiez dans le dossier des pourriels ou %{request_link_start}demandez un nouveau courriel de confirmation%{request_link_end}."
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Aucune connexion n’a pu être établie avec un serveur Gitaly, veuillez vérifier votre journal !"
@@ -26424,7 +26792,7 @@ msgid "No credit card required."
msgstr "Aucune carte de crédit n’est nécessaire."
msgid "No data available"
-msgstr ""
+msgstr "Aucune donnée disponible"
msgid "No data found"
msgstr ""
@@ -26433,16 +26801,16 @@ msgid "No data to display"
msgstr ""
msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
-msgstr ""
+msgstr "Aucun déploiement détecté. Utilisez des environnements pour contrôler le déploiement continu de votre logiciel. %{linkStart}En savoir plus sur les tâches de déploiement.%{linkEnd}"
msgid "No deployments found"
msgstr ""
msgid "No email participants were added. Either none were provided, or they already exist."
-msgstr ""
+msgstr "Aucun participant n'a été ajouté par courriel. Soit aucun n'a été fourni, soit ils existent déjà."
msgid "No endpoint provided"
-msgstr ""
+msgstr "Aucun point de terminaison fourni"
msgid "No errors to display."
msgstr ""
@@ -26451,10 +26819,10 @@ msgid "No estimate or time spent"
msgstr "Aucune estimation ou temps passé"
msgid "No file chosen."
-msgstr ""
+msgstr "Aucun fichier choisi."
msgid "No file hooks found."
-msgstr ""
+msgstr "Aucun fichier « Hook » trouvé."
msgid "No file selected"
msgstr ""
@@ -26466,7 +26834,7 @@ msgid "No files found."
msgstr "Aucun fichier trouvé."
msgid "No forks are available to you."
-msgstr ""
+msgstr "Aucun fork ne vous est disponible."
msgid "No group provided"
msgstr ""
@@ -26475,10 +26843,10 @@ msgid "No grouping"
msgstr ""
msgid "No issues found"
-msgstr ""
+msgstr "Aucun ticket trouvé"
msgid "No iteration"
-msgstr ""
+msgstr "Aucune itération"
msgid "No iterations to show"
msgstr ""
@@ -26499,7 +26867,7 @@ msgid "No license. All rights reserved"
msgstr "Aucune licence. Tous droits réservés"
msgid "No matches found"
-msgstr ""
+msgstr "Aucune correspondance trouvée"
msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} ID."
msgstr ""
@@ -26508,19 +26876,19 @@ msgid "No matching %{issuable} found. Make sure that you are adding a valid %{is
msgstr ""
msgid "No matching labels"
-msgstr ""
+msgstr "Aucune étiquette correspondante"
msgid "No matching results"
msgstr ""
msgid "No matching results for \"%{query}\""
-msgstr ""
+msgstr "Aucun résultat correspondant pour « %{query} »"
msgid "No matching results..."
-msgstr ""
+msgstr "Aucun résultat correspondant..."
msgid "No members found"
-msgstr ""
+msgstr "Aucun membre trouvé"
msgid "No memberships found"
msgstr ""
@@ -26535,7 +26903,7 @@ msgid "No milestone"
msgstr "Aucun jalon"
msgid "No namespace"
-msgstr ""
+msgstr "Aucun espace de noms"
msgid "No other labels with such name or description"
msgstr "Aucune autre étiquette avec un tel nom ou une telle description"
@@ -26550,7 +26918,7 @@ msgid "No plan"
msgstr ""
msgid "No policy matches this license"
-msgstr ""
+msgstr "Aucune stratégie ne correspond à cette licence"
msgid "No preview for this file type"
msgstr ""
@@ -26559,13 +26927,13 @@ msgid "No prioritized labels with such name or description"
msgstr ""
msgid "No project subscribes to the pipelines in this project."
-msgstr ""
+msgstr "Aucun projet n'est abonné aux pipelines de ce projet."
msgid "No projects available."
-msgstr ""
+msgstr "Aucun projet disponible."
msgid "No projects found"
-msgstr ""
+msgstr "Aucun projet trouvé"
msgid "No public deploy keys"
msgstr ""
@@ -26574,25 +26942,25 @@ msgid "No public groups"
msgstr "Aucun groupe public"
msgid "No ref selected"
-msgstr ""
+msgstr "Pas de réf sélectionnée"
msgid "No regions configured"
msgstr ""
msgid "No related merge requests found."
-msgstr ""
+msgstr "Aucune demande de fusion associée n'a été trouvée."
msgid "No repository"
msgstr "Aucun dépôt"
msgid "No results"
-msgstr ""
+msgstr "Aucun résultat"
msgid "No results found"
-msgstr ""
+msgstr "Aucun résultat trouvé"
msgid "No runner executable"
-msgstr ""
+msgstr "Aucun Exécuteur exécutable"
msgid "No schedules"
msgstr "Aucune planification"
@@ -26601,43 +26969,43 @@ msgid "No service accounts"
msgstr ""
msgid "No severity matches the provided parameter"
-msgstr ""
+msgstr "Aucune gravité ne correspond au paramètre fourni"
msgid "No source selected"
-msgstr ""
+msgstr "Aucune source sélectionnée"
msgid "No stack trace for this error"
-msgstr ""
+msgstr "Pas de trace de pile pour cette erreur"
msgid "No starrers matched your search"
msgstr ""
msgid "No suggestions found"
-msgstr ""
+msgstr "Aucune suggestion trouvée"
msgid "No tag selected"
-msgstr ""
+msgstr "Aucune étiquette sélectionnée"
msgid "No template"
msgstr ""
msgid "No template selected"
-msgstr ""
+msgstr "Aucun modèle sélectionné"
msgid "No test coverage"
msgstr ""
msgid "No triggers exist yet. Use the form above to create one."
-msgstr ""
+msgstr "Il n'y a pas encore de déclencheur. Utilisez le formulaire ci-dessus pour en créer un."
msgid "No user provided"
-msgstr ""
+msgstr "Aucun utilisateur spécifié"
msgid "No vulnerabilities present"
msgstr ""
msgid "No webhook events"
-msgstr ""
+msgstr "Aucun événement de crochet web"
msgid "No webhooks enabled. Select trigger events above."
msgstr ""
@@ -26647,9 +27015,12 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
-msgid "No. of commits"
+msgid "No wrap"
msgstr ""
+msgid "No. of commits"
+msgstr "Nb de commits"
+
msgid "Nobody has starred this repository yet"
msgstr ""
@@ -26669,22 +27040,22 @@ msgid "None"
msgstr "Aucun"
msgid "None of the group milestones have the same project as the release"
-msgstr ""
+msgstr "Aucun des jalons de groupe n'a le même projet que la version"
msgid "Normal text"
-msgstr ""
+msgstr "Texte normal"
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
-msgstr ""
+msgstr "Tous les navigateurs ne gèrent pas les appareils U2F. Par conséquent, il vous faut d'abord configurer une application d'authentification à deux facteurs. De cette façon, vous serez toujours en mesure de vous connecter - même si vous utilisez un navigateur non pris en charge."
msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
-msgstr ""
+msgstr "Tous les navigateurs ne gèrent pas WebAuthn. Par conséquent, il vous faut d'abord configurer une application d'authentification à deux facteurs. De cette façon, vous serez toujours en mesure de vous connecter - même si vous utilisez un navigateur non pris en charge."
msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
msgstr ""
msgid "Not applicable."
-msgstr ""
+msgstr "Non applicable."
msgid "Not available"
msgstr "Indisponible"
@@ -26699,13 +27070,13 @@ msgid "Not confidential"
msgstr "Non confidentiel"
msgid "Not found"
-msgstr ""
+msgstr "Non trouvé"
msgid "Not found."
msgstr ""
msgid "Not permitted to destroy framework"
-msgstr ""
+msgstr "Pas d'autorisation pour détruire le framework"
msgid "Not ready yet. Try again later."
msgstr ""
@@ -26714,19 +27085,19 @@ msgid "Not started"
msgstr ""
msgid "Not supported"
-msgstr ""
+msgstr "Non pris en charge"
msgid "Note"
msgstr ""
msgid "Note creation requests"
-msgstr ""
+msgstr "Demandes de création de note"
msgid "Note parameters are invalid: %{errors}"
msgstr ""
msgid "Note that pushing to GitLab requires write access to this repository."
-msgstr ""
+msgstr "Remarquez que l'envoi vers GitLab nécessite un accès en écriture sur ce dépôt."
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Remarque : En tant qu’administrateur ou administratrice, vous pouvez configurer %{github_integration_link}, ce qui vous permettra de vous authentifier via GitHub et de connecter des dépôts sans générer de jeton d’accès personnel."
@@ -26741,7 +27112,7 @@ msgid "Note: Consider asking your GitLab administrator to configure %{github_int
msgstr "Remarque : Envisagez de demander à votre administra·teur·trice GitLab de configurer %{github_integration_link}, ce qui vous permettra de vous connecter via GitHub et d’importer des dépôts sans générer de jeton d’accès personnel."
msgid "Note: current forks will keep their visibility level."
-msgstr ""
+msgstr "Remarque : les forks actuels conserveront leur niveau de visibilité."
msgid "NoteForm|Note"
msgstr ""
@@ -26756,7 +27127,7 @@ msgid "Notes rate limit"
msgstr ""
msgid "Notes|Are you sure you want to cancel creating this %{commentType}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir annuler la création de ce %{commentType} ?"
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Souhaitezâ€vous réellement annuler la création de ce commentaire ?"
@@ -26765,7 +27136,7 @@ msgid "Notes|Collapse replies"
msgstr "Réduire les réponses"
msgid "Notes|Expand replies"
-msgstr ""
+msgstr "Afficher les réponses"
msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
msgstr ""
@@ -26792,16 +27163,16 @@ msgid "Notes|This internal note will always remain confidential"
msgstr ""
msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
-msgstr ""
+msgstr "Vous ne voyez que les %{boldStart}autres activités%{boldEnd} dans le flux. Pour ajouter un commentaire, basculez sur l'une des options suivantes."
msgid "Note|The created date provided is too far in the past."
-msgstr ""
+msgstr "La date de création fournie est trop loin dans le passé."
msgid "Nothing to preview."
msgstr "Rien à prévisualiser."
msgid "Notification Email"
-msgstr ""
+msgstr "Courriel de notification"
msgid "Notification events"
msgstr "Événement de notifications"
@@ -26814,23 +27185,23 @@ msgstr ""
msgid "NotificationEmail|Assignee"
msgid_plural "NotificationEmail|Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Assigné(e)"
+msgstr[1] "Assigné(e)s"
msgid "NotificationEmail|Assignee: %{users}"
msgid_plural "NotificationEmail|Assignees: %{users}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Assigné(e) : %{users}"
+msgstr[1] "Assigné(e)s : %{users}"
msgid "NotificationEmail|Reviewer"
msgid_plural "NotificationEmail|Reviewers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Relecteur"
+msgstr[1] "Relecteurs"
msgid "NotificationEmail|Reviewer: %{users}"
msgid_plural "NotificationEmail|Reviewers: %{users}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Relecteur : %{users}"
+msgstr[1] "Relecteurs : %{users}"
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -26848,16 +27219,16 @@ msgid "NotificationEvent|Fixed pipeline"
msgstr ""
msgid "NotificationEvent|Issue due"
-msgstr ""
+msgstr "Ticket arrivé à échéance"
msgid "NotificationEvent|Merge merge request"
msgstr "Fusionner la demande de fusion"
msgid "NotificationEvent|Merge when pipeline succeeds"
-msgstr ""
+msgstr "Fusionner lorsque le pipeline réussit"
msgid "NotificationEvent|Moved project"
-msgstr ""
+msgstr "Projet déplacé"
msgid "NotificationEvent|New epic"
msgstr "Nouvelle épopée"
@@ -26923,10 +27294,10 @@ msgid "Notifications on"
msgstr "Notifications activées"
msgid "Notifications turned off."
-msgstr ""
+msgstr "Notifications désactivées."
msgid "Notifications turned on."
-msgstr ""
+msgstr "Notifications activées."
msgid "Notify users by email when sign-in location is not recognized."
msgstr ""
@@ -26934,38 +27305,71 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr "Le ticket de %{author_link} arrive bientôt à échéance %{issue_reference_link}."
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr "%{author_name} %{action_name} %{ref_type} %{ref_name} sur %{project_link}"
+
+msgid "Notify|%{changed_files}:"
+msgstr "%{changed_files} :"
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} dans %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
-msgstr ""
+msgstr "%{commits_text} depuis la branche « %{target_branch} »"
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr "%{committed_by_start} par %{author_name} %{committed_by_end} %{committed_at_start} le %{committed_date} %{committed_at_end}"
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
-msgstr ""
+msgstr "%{invite_email}, dont le nom est à présent %{user_name}, a accepté votre invitation à rejoindre le %{target_model_name} %{target_name}."
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
+msgstr "%{invited_user} a %{highlight_start}décliné%{highlight_end} votre invitation à rejoindre le %{target_name} %{target_link}."
+
+msgid "Notify|%{issues} imported."
msgstr ""
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
-msgstr ""
+msgstr "%{member_link} a demandé un accès %{member_role} au %{target_type} %{target_source_link}."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "La %{mr_highlight}demande de fusion%{highlight_end} %{mr_link} %{reviewer_highlight}a été approuvée par%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "La %{mr_highlight}demande de fusion%{highlight_end} %{mr_link} %{reviewer_highlight}a été désapprouvée par%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr "%{name} a demandé une nouvelle relecture sur %{mr_link}."
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
-msgstr ""
+msgstr "%{paragraph_start}Bonjour %{name}!%{paragraph_end} %{paragraph_start}Une nouvelle clé publique a été ajoutée à votre compte:%{paragraph_end} %{paragraph_start}titre: %{key_title}%{paragraph_end} %{paragraph_start}Si cette clé a été ajoutée par erreur, vous pouvez la supprimer sous %{removal_link}%{paragraph_end}"
+
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr "%{project_link_start}Téléchargez%{project_link_end} l'exportation du projet."
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr "%{update_at_start} Dernière mise à jour le %{update_at_mid} %{last_update_at} %{update_at_end}"
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
-msgstr ""
+msgstr "%{updated_by_user_name} a poussé de nouveaux commits sur la demande de fusion %{mr_link}"
msgid "Notify|A new GPG key was added to your account:"
-msgstr ""
+msgstr "Une nouvelle clé GPG a été ajoutée sur votre compte :"
+
+msgid "Notify|A remote mirror update has failed."
+msgstr "Une mise à jour du miroir distant a échoué."
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr "Après son expiration, vous pourrez %{a_start} en demander un nouveau %{a_end}."
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
-msgstr ""
+msgstr "Toutes les discussions sur la demande de fusion %{mr_link} ont été résolues par %{name}"
msgid "Notify|And %{total_stripped_new_commits_count} more"
-msgstr ""
+msgstr "Et %{total_stripped_new_commits_count} de plus"
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "L'assignation est passée de %{fromNames} à %{toNames}"
@@ -26977,25 +27381,43 @@ msgid "Notify|Author: %{author_name}"
msgstr "Auteur : %{author_name}"
msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
-msgstr ""
+msgstr "Le pipeline Auto DevOps a été désactivé pour %{project}"
msgid "Notify|CI/CD project settings"
+msgstr "paramètres de projet CI/CD"
+
+msgid "Notify|Click here to set your password"
+msgstr "Cliquez ici pour définir votre mot de passe"
+
+msgid "Notify|Commit Author"
msgstr ""
-msgid "Notify|Don't want to receive updates from GitLab administrators?"
+msgid "Notify|Committed by"
msgstr ""
+msgid "Notify|Don't want to receive updates from GitLab administrators?"
+msgstr "Vous ne souhaitez pas recevoir de mises à jour des administrateurs GitLab ?"
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr "Erreur lors de l'analyse du fichier CSV. Veuillez vous assurer qu'il a le format correct : un fichier texte délimité qui utilise une virgule pour séparer les valeurs."
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "Erreurs trouvées sur %{singular_or_plural_line} : %{error_lines}. Veuillez vérifier si ces lignes ont un titre de ticket."
+
msgid "Notify|Fingerprint: %{fingerprint}"
-msgstr ""
+msgstr "Empreinte : %{fingerprint}"
+
+msgid "Notify|Hi %{username}!"
+msgstr "Bonjour %{username} !"
msgid "Notify|Hi %{user}!"
-msgstr ""
+msgstr "Bonjour %{user} !"
msgid "Notify|If this key was added in error, you can remove it under %{removal_link}"
-msgstr ""
+msgstr "Si cette clé a été ajoutée par erreur, vous pouvez la supprimer sous %{removal_link}"
msgid "Notify|If you no longer wish to use this domain with GitLab Pages, please remove it from your GitLab project and delete any related DNS records."
-msgstr ""
+msgstr "Si vous ne souhaitez plus utiliser ce domaine avec les Pages GitLab, veuillez l'enlever de votre projet GitLab et supprimer tous les enregistrements DNS associés."
msgid "Notify|Issue was %{issue_status} by %{updated_by}"
msgstr "Le ticket a été %{issue_status} par %{updated_by}"
@@ -27004,7 +27426,10 @@ msgid "Notify|Issue was moved to another project."
msgstr "Le ticket a été déplacé vers un autre projet."
msgid "Notify|Learn more about Auto DevOps"
-msgstr ""
+msgstr "En savoir plus sur Auto DevOps"
+
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr "Les journaux peuvent contenir des données sensibles. Veuillez en tenir compte avant de transmettre ce courriel."
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr "La demande de fusion %{merge_request} ne peut plus être fusionnée en raison d'un conflit."
@@ -27025,45 +27450,108 @@ msgid "Notify|Merge request URL: %{merge_request_url}"
msgstr "URL de la demande de fusion : %{merge_request_url}"
msgid "Notify|Merge request was approved"
-msgstr ""
+msgstr "La demande de fusion a été approuvée"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
-msgstr ""
+msgstr "La demande de fusion a été approuvée (%{approvals}/%{required_approvals})"
+
+msgid "Notify|Merge request was unapproved"
+msgstr "La demande de fusion a été désapprouvée"
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr "La demande de fusion a été désapprouvée (%{approvals_count}/%{approvals_required})"
msgid "Notify|Milestone changed to %{milestone}"
msgstr "Le jalon a été changé à %{milestone}"
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "Jalon supprimé"
msgid "Notify|New issue: %{project_issue_url}"
msgstr "Nouveau ticket : %{project_issue_url}"
+msgid "Notify|No preview for this file type"
+msgstr "Aucun aperçu pour ce type de fichier"
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline %{pipeline_link} déclenché par"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "Le pipeline a été corrigé et #%{pipeline_id} est passé !"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr "Le projet %{old_path_with_namespace} a été déplacé vers un autre emplacement."
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr "Le projet %{project_name} a été exporté avec succès."
+
+msgid "Notify|Remote mirror"
+msgstr "Miroir distant"
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr "L'Administrateur vous a créé un compte. Vous êtes à présent membre de l'application GitLab de l'entreprise."
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
+msgstr "Le pipeline Auto DevOps a échoué pour le pipeline %{pipeline_link} et a été désactivé pour %{project_link}. Afin d'utiliser le pipeline Auto DevOps avec votre projet, veuillez examiner les %{supported_langs_link} puis adaptez votre projet en conséquence et activez le pipeline Auto DevOps dans vos %{settings_link}."
+
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr "Le diff pour ce fichier n'a pas été inclus car il est trop volumineux"
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr "Le diff n'a pas été inclus car il est trop volumineux."
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "Le lien de téléchargement expirera dans 24 heures."
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
msgstr ""
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr "Ce ticket arrive à échéance le: %{issue_due_date}"
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "Ce lien est valide pendant %{password_reset_token_valid_time}."
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
-msgstr ""
+msgstr "À moins que vous ne vérifiiez votre domaine avant le %{time_start}%{time}%{time_end} , il sera supprimé de votre projet GitLab."
msgid "Notify|You don't have access to the project."
msgstr "Vous n'avez pas accès au projet."
msgid "Notify|You have been mentioned in an issue."
-msgstr ""
+msgstr "Vous avez été mentionné dans un ticket."
msgid "Notify|You have been mentioned in merge request %{mr_link}"
-msgstr ""
+msgstr "Vous avez été mentionné dans la demande de fusion %{mr_link}"
+
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "Vous avez été désabonné des notifications d’administrateur GitLab."
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr "Votre import CSV pour le projet %{project_link} s'est terminé."
+
+msgid "Notify|Your account has been created successfully."
+msgstr "Votre compte a été créé avec succès."
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
-msgstr ""
+msgstr "Votre demande de rejoindre le %{target_to_join} %{target_type} a été %{denied_tag}."
msgid "Notify|currently supported languages"
+msgstr "langages actuellement pris en charge"
+
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr "connexion.........................................."
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
msgstr ""
msgid "Notify|successfully completed %{jobs} in %{stages}."
@@ -27076,22 +27564,22 @@ msgid "November"
msgstr "novembre"
msgid "Now, personalize your GitLab experience"
-msgstr ""
+msgstr "Maintenant, personnalisez votre expérience GitLab"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
-msgstr ""
+msgstr "Les métadonnées de Nuget doivent au moins avoir license_url, project_url ou icon_url définies."
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 ""
+msgstr "Nombre de poussées Git après lequel %{code_start}git gc%{code_end} est exécuté."
msgid "Number of Git pushes after which a full %{code_start}git repack%{code_end} is run."
-msgstr ""
+msgstr "Nombre de poussées Git après lequel un %{code_start}git repack%{code_end} complet est exécuté."
msgid "Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run."
-msgstr ""
+msgstr "Nombre de poussées Git après lequel un %{code_start}git repack%{code_end} incrémental est exécuté."
msgid "Number of LOCs per commit"
msgstr ""
@@ -27103,22 +27591,22 @@ msgid "Number of commits per MR"
msgstr ""
msgid "Number of employees"
-msgstr ""
+msgstr "Nombre d'employés"
msgid "Number of events"
-msgstr ""
+msgstr "Nombre d'événements"
msgid "Number of events for this project: %{total_count}."
-msgstr ""
+msgstr "Nombre d'événements pour ce projet : %{total_count}."
msgid "Number of files touched"
msgstr ""
msgid "Number of replicas"
-msgstr ""
+msgstr "Nombre de répliques"
msgid "Number of shards"
-msgstr ""
+msgstr "Nombre de fragments"
msgid "OK"
msgstr "OK"
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr "Observabilité"
+
msgid "Oct"
msgstr "oct."
@@ -27142,13 +27633,13 @@ msgid "Offline"
msgstr ""
msgid "Oh no!"
-msgstr ""
+msgstr "Oh non !"
msgid "Ok, let's go"
msgstr ""
msgid "Okay"
-msgstr ""
+msgstr "D'accord"
msgid "Oldest first"
msgstr "Plus ancien en premier"
@@ -27161,92 +27652,92 @@ msgstr ""
msgid "On %{end_date}, your trial will end and %{namespace_name} will be limited to %{free_user_limit} member"
msgid_plural "On %{end_date}, your trial will end and %{namespace_name} will be limited to %{free_user_limit} members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le %{end_date}, votre période d'essai se terminera et %{namespace_name} sera limité à %{free_user_limit} membre"
+msgstr[1] "Le %{end_date}, votre période d'essai se terminera et %{namespace_name} sera limité à %{free_user_limit} membres"
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "Sur la barre latérale de gauche, sélectionnez %{merge_requests_link} pour les voir."
msgid "On track"
msgstr ""
msgid "On-call Schedules"
-msgstr ""
+msgstr "Calendriers des astreintes"
msgid "On-call schedules"
-msgstr ""
+msgstr "Calendriers des astreintes"
msgid "On-demand scans run outside of the DevOps cycle and find vulnerabilities in your projects"
msgstr ""
msgid "OnCallScheduless|Any escalation rules that are using this schedule will also be deleted."
-msgstr ""
+msgstr "Toutes les règles d'escalade faisant usage de ce calendrier seront également supprimées."
msgid "OnCallSchedules|1 day"
-msgstr ""
+msgstr "1 jour"
msgid "OnCallSchedules|2 weeks"
-msgstr ""
+msgstr "2 semaines"
msgid "OnCallSchedules|Add a rotation"
-msgstr ""
+msgstr "Ajouter un cycle"
msgid "OnCallSchedules|Add a schedule"
-msgstr ""
+msgstr "Ajouter un calendrier"
msgid "OnCallSchedules|Add an additional schedule to your project"
-msgstr ""
+msgstr "Ajouter un calendrier supplémentaire à votre projet"
msgid "OnCallSchedules|Add rotation"
-msgstr ""
+msgstr "Ajout de cycle"
msgid "OnCallSchedules|Add schedule"
-msgstr ""
+msgstr "Ajouter un calendrier"
msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteRotation}\" rotation? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer le cycle « %{deleteRotation} » ? Cette action ne peut pas être annulée."
msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\" schedule? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer le calendrier « %{deleteSchedule} » ? Cette action ne peut pas être annulée."
msgid "OnCallSchedules|Collapse schedule"
-msgstr ""
+msgstr "Réduire le calendrier"
msgid "OnCallSchedules|Create on-call schedules in GitLab"
-msgstr ""
+msgstr "Créer des calendriers d'astreintes dans GitLab"
msgid "OnCallSchedules|Currently no rotation."
msgstr ""
msgid "OnCallSchedules|Delete rotation"
-msgstr ""
+msgstr "Supprimer le cycle"
msgid "OnCallSchedules|Delete schedule"
-msgstr ""
+msgstr "Supprimer le calendrier"
msgid "OnCallSchedules|Edit rotation"
-msgstr ""
+msgstr "Modifier le cycle"
msgid "OnCallSchedules|Edit schedule"
-msgstr ""
+msgstr "Modifier le calendrier"
msgid "OnCallSchedules|Enable end date"
-msgstr ""
+msgstr "Activer la date de fin"
msgid "OnCallSchedules|Expand schedule"
-msgstr ""
+msgstr "Étendre le calendrier"
msgid "OnCallSchedules|Failed to add rotation"
-msgstr ""
+msgstr "Échec de l'ajout du cycle"
msgid "OnCallSchedules|Failed to add schedule"
-msgstr ""
+msgstr "Échec de l'ajout du calendrier"
msgid "OnCallSchedules|Failed to edit schedule"
-msgstr ""
+msgstr "Échec de la modification du calendrier"
msgid "OnCallSchedules|For this rotation, on-call will be:"
-msgstr ""
+msgstr "Pour ce cycle, l'astreinte sera :"
msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
@@ -27258,148 +27749,151 @@ msgid "OnCallSchedules|Please note, rotations with shifts that are less than fou
msgstr ""
msgid "OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification."
-msgstr ""
+msgstr "La suppression de cet utilisateur peut exposer son équipe d'astreinte au risque de manquer une notification."
msgid "OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification."
-msgstr ""
+msgstr "Vous supprimer vous-même peut exposer votre équipe d'astreinte au risque de manquer une notification."
msgid "OnCallSchedules|Restrict to time intervals"
-msgstr ""
+msgstr "Restreindre à des intervalles de temps"
msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
-msgstr ""
+msgstr "La date/heure de fin du cycle de travail doit être postérieure celle de début"
msgid "OnCallSchedules|Rotation length"
-msgstr ""
+msgstr "Durée de cycle"
msgid "OnCallSchedules|Rotation name cannot be empty"
-msgstr ""
+msgstr "Le nom du cycle ne peut pas être vide"
msgid "OnCallSchedules|Rotation participants cannot be empty"
-msgstr ""
+msgstr "Le cycle doit contenir des participants"
msgid "OnCallSchedules|Rotation start date cannot be empty"
-msgstr ""
+msgstr "La date de début de cycle ne peut pas être vide"
msgid "OnCallSchedules|Rotations"
-msgstr ""
+msgstr "Cycles"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
-msgstr ""
+msgstr "Acheminer les alertes directement à des membres spécifiques de votre équipe"
+
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr "Dirige les alertes directement vers des membres particuliers de votre équipe. Pour accéder à cette fonctionnalité, demandez à %{linkStart}un Propriétaire du projet%{linkEnd} de vous accorder au minimum le rôle de Mainteneur."
msgid "OnCallSchedules|Select participant"
-msgstr ""
+msgstr "Sélectionner un participant"
msgid "OnCallSchedules|Select timezone"
-msgstr ""
+msgstr "Sélectionnez le fuseau horaire"
msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
-msgstr ""
+msgstr "Définit le fuseau horaire par défaut du calendrier, pour tous les participants"
msgid "OnCallSchedules|Successfully created a new rotation"
-msgstr ""
+msgstr "Un nouveau cycle a été créé avec succès"
msgid "OnCallSchedules|Successfully edited your rotation"
-msgstr ""
+msgstr "Votre cycle a été modifié avec succès"
msgid "OnCallSchedules|The rotation could not be deleted. Please try again."
-msgstr ""
+msgstr "Le cycle n'a pas pu être supprimé. Veuillez réessayer."
msgid "OnCallSchedules|The rotation could not be updated. Please try again."
-msgstr ""
+msgstr "Le cycle n'a pas pu être mis à jour. Veuillez réessayer."
msgid "OnCallSchedules|The schedule could not be deleted. Please try again."
-msgstr ""
+msgstr "Le calendrier n’a pas pu être supprimé. Veuillez réessayer."
msgid "OnCallSchedules|The schedule could not be updated. Please try again."
-msgstr ""
+msgstr "Le calendrier n’a pas pu être mis à jour. Veuillez réessayer."
msgid "OnCallSchedules|Try adding a rotation"
-msgstr ""
+msgstr "Tentative d'ajout d'un cycle"
msgid "OnCallSchedules|User %{name} is currently part of:"
-msgstr ""
+msgstr "L'utilisateur %{name} fait actuellement partie de :"
msgid "OnCallSchedules|View next timeframe"
-msgstr ""
+msgstr "Voir la période suivante"
msgid "OnCallSchedules|View previous timeframe"
-msgstr ""
+msgstr "Voir la période précédente"
msgid "OnCallSchedules|You are currently a part of:"
-msgstr ""
+msgstr "Vous faites actuellement partie de :"
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 ""
+msgstr "Votre calendrier a été créé avec succès. Pour ajouter des utilisateurs individuels à celui-ci, utilisez le bouton Ajouter un cycle. Pour activer les notifications pour ce calendrier, vous devez également créer une %{linkStart}politique d'escalade%{linkEnd}."
msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "%{learnMoreLinkStart}En savoir plus sur les analyses à la demande%{learnMoreLinkEnd}."
msgid "OnDemandScans|%{profileType} profile library"
-msgstr ""
+msgstr "bibliothèque de profil de %{profileType}"
msgid "OnDemandScans|Add a schedule to run this scan at a specified date and time or on a recurring basis. Scheduled scans are automatically saved to scan library."
-msgstr ""
+msgstr "Établir une planification pour exécuter cette analyse à une date et une heure spécifiées ou sur une base récurrente. Les analyses planifiées sont automatiquement enregistrées dans la bibliothèque d'analyses."
msgid "OnDemandScans|Analyze a deployed version of your web application for known vulnerabilities by examining it from the outside in. DAST works by simulating external attacks on your application while it is running."
msgstr ""
msgid "OnDemandScans|Are you sure you want to delete this scan?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette analyse ?"
msgid "OnDemandScans|Cancel"
msgstr ""
msgid "OnDemandScans|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de supprimer l'analyse enregistrée. Veuillez actualiser la page ou réessayer plus tard."
msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les analyses à la demande. Veuillez actualiser la page ou réessayer plus tard."
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les profils de scanner. Veuillez actualiser la page ou réessayer plus tard."
msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les profils de site. Veuillez actualiser la page ou réessayer plus tard."
msgid "OnDemandScans|Could not run the scan. Please try again."
-msgstr ""
+msgstr "Impossible d’exécuter l’analyse. Veuillez réessayer."
msgid "OnDemandScans|Create new scanner profile"
-msgstr ""
+msgstr "Créer un nouveau profil de scanner"
msgid "OnDemandScans|Create new site profile"
-msgstr ""
+msgstr "Créer un nouveau profil de site"
msgid "OnDemandScans|DAST configuration"
-msgstr ""
+msgstr "Configuration DAST"
msgid "OnDemandScans|DAST scans for vulnerabilities in your project's running application, website, or API. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
-msgstr ""
+msgstr "Analyses DAST des vulnérabilités présentes dans l'API, le site web ou l'application en cours d'exécution de votre projet. Pour plus de détails sur toutes les options de configuration, voir la %{linkStart}documentation GitLab sur DAST%{linkEnd}."
msgid "OnDemandScans|Define the fundamental configuration options for your on-demand scan."
-msgstr ""
+msgstr "Définissez les options de configuration essentielles pour votre analyse à la demande."
msgid "OnDemandScans|Delete profile"
-msgstr ""
+msgstr "Supprimer le profil"
msgid "OnDemandScans|Description (optional)"
-msgstr ""
+msgstr "Description (facultatif)"
msgid "OnDemandScans|Discard changes"
-msgstr ""
+msgstr "Abandonner les modifications"
msgid "OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost."
-msgstr ""
+msgstr "Souhaitez-vous abandonner les modifications ou poursuivre la modification de ce profil ? Les modifications non enregistrées seront perdues."
msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "Test dynamique de la sécurité des applications (DAST)"
msgid "OnDemandScans|Edit %{profileType} profile"
msgstr "Modifier %{profileType} profil"
msgid "OnDemandScans|Edit on-demand DAST scan"
-msgstr ""
+msgstr "Modifier l'analyse DAST à la demande"
msgid "OnDemandScans|Edit on-demand scan"
msgstr ""
@@ -27408,151 +27902,151 @@ msgid "OnDemandScans|Edit profile"
msgstr "Modifier le profil"
msgid "OnDemandScans|Enable scan schedule"
-msgstr ""
+msgstr "Activer la planification d'analyse"
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
-msgstr ""
+msgstr "Par exemple : Teste la page de connexion contre les injections SQL"
msgid "OnDemandScans|Keep editing"
-msgstr ""
+msgstr "Poursuivre la modification"
msgid "OnDemandScans|Manage scanner profiles"
-msgstr ""
+msgstr "Gérer les profils de scanner"
msgid "OnDemandScans|Manage site profiles"
-msgstr ""
+msgstr "Gérer les profils de site"
msgid "OnDemandScans|My daily scan"
-msgstr ""
+msgstr "Mon analyse quotidienne"
msgid "OnDemandScans|New %{profileType} profile"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
-msgstr ""
+msgstr "Nouvelle analyse DAST à la demande"
msgid "OnDemandScans|New on-demand scan"
-msgstr ""
+msgstr "Nouvelle analyse à la demande"
msgid "OnDemandScans|New profile"
-msgstr ""
+msgstr "Nouveau profil"
msgid "OnDemandScans|New scan"
-msgstr ""
+msgstr "Nouvelle analyse"
msgid "OnDemandScans|No %{profileType} profiles found for DAST"
msgstr ""
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
-msgstr ""
+msgstr "Actuellement aucun profil . Pour créer une nouvelle analyse, vous devez avoir rempli entièrement au moins un profil de scanner."
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
-msgstr ""
+msgstr "Il n'y a aucun profil pour l'instant. Afin de créer une nouvelle analyse, vous devez avoir terminé au moins un profil de site."
msgid "OnDemandScans|On-demand Scans"
-msgstr ""
+msgstr "Analyses à la demande"
msgid "OnDemandScans|On-demand scans"
-msgstr ""
+msgstr "Analyses à la demande"
msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "Les analyses à la demande s'exécutent en dehors du cycle DevOps et trouvent les vulnérabilités de vos projets. %{learnMoreLinkStart}En savoir plus%{learnMoreLinkEnd}."
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
-msgstr ""
+msgstr "Les analyses à la demande s'exécutent en dehors du cycle DevOps et trouvent les vulnérabilités de vos projets. %{learnMoreLinkStart}En savoir plus%{learnMoreLinkEnd}"
msgid "OnDemandScans|Repeats"
-msgstr ""
+msgstr "Répétitions"
msgid "OnDemandScans|Run scan"
-msgstr ""
+msgstr "Exécuter l'analyse"
msgid "OnDemandScans|Save and run scan"
-msgstr ""
+msgstr "Enregistrer et exécuter l'analyse"
msgid "OnDemandScans|Save scan"
-msgstr ""
+msgstr "Enregistrer l'analyse"
msgid "OnDemandScans|Scan configuration"
-msgstr ""
+msgstr "Configuration de l'analyse"
msgid "OnDemandScans|Scan library"
msgstr "Bibliothèque de numérisation"
msgid "OnDemandScans|Scan name"
-msgstr ""
+msgstr "Nom de l'analyse"
msgid "OnDemandScans|Scan results will be associated with the selected branch."
-msgstr ""
+msgstr "Les résultats de l'analyse seront associés à la branche sélectionnée."
msgid "OnDemandScans|Scan schedule"
-msgstr ""
+msgstr "Planification d'analyse"
msgid "OnDemandScans|Scan type"
-msgstr ""
+msgstr "Type d'analyse"
msgid "OnDemandScans|Scanner profile"
-msgstr ""
+msgstr "Profil de scanner"
msgid "OnDemandScans|Select one of the existing profiles"
-msgstr ""
+msgstr "Sélectionnez l'un des profils existants"
msgid "OnDemandScans|Site profile"
-msgstr ""
+msgstr "Profil de site"
msgid "OnDemandScans|Start by creating a new profile. Profiles make it easy to save and reuse configuration details for GitLab’s security tools."
-msgstr ""
+msgstr "Commencez par la création d'un nouveau profil. Les profils facilitent l'enregistrement et la réutilisation des informations de configuration des outils de sécurité de GitLab."
msgid "OnDemandScans|Start time"
msgstr ""
msgid "OnDemandScans|Target"
-msgstr ""
+msgstr "Cible"
msgid "OnDemandScans|The scan could not be canceled."
-msgstr ""
+msgstr "L'analyse n'a pas pu être annulée."
msgid "OnDemandScans|The scan could not be retried."
-msgstr ""
+msgstr "L'analyse n'a pas pu être retentée."
msgid "OnDemandScans|There are no finished scans."
-msgstr ""
+msgstr "Il n'y a aucune analyse terminée."
msgid "OnDemandScans|There are no running scans."
-msgstr ""
+msgstr "Il n'y a aucune analyse en cours."
msgid "OnDemandScans|There are no saved scans."
-msgstr ""
+msgstr "Il n'y a pas d'analyse enregistrée."
msgid "OnDemandScans|There are no scheduled scans."
-msgstr ""
+msgstr "Il n'y a aucune analyse planifiée."
msgid "OnDemandScans|Timezone"
-msgstr ""
+msgstr "Fuseau horaire"
msgid "OnDemandScans|Use existing scanner profile"
-msgstr ""
+msgstr "Utiliser un profil de scanner existant"
msgid "OnDemandScans|Use existing site profile"
-msgstr ""
+msgstr "Utiliser un profil de site existant"
msgid "OnDemandScans|View results"
-msgstr ""
+msgstr "Voir les résultats"
msgid "OnDemandScans|You have unsaved changes"
-msgstr ""
+msgstr "Vous avez des modifications non enregistrées"
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
-msgstr ""
+msgstr "Vous devez créer un dépôt à l'intérieur de votre projet pour exécuter une analyse à la demande."
msgid "OnDemandScans|at"
-msgstr ""
+msgstr "le"
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
-msgstr ""
+msgstr "Une fois supprimée, la relation du fork ne pourra plus être restaurée. Ce projet ne sera plus en mesure de recevoir ni d'envoyer des demandes de fusion vers le projet source ni vers d'autres forks."
msgid "Once you confirm and press \"Reduce project visibility\":"
msgstr ""
@@ -27563,13 +28057,13 @@ msgstr[0] "Un élément de plus"
msgstr[1] "%d éléments de plus"
msgid "One or more arguments are invalid: %{args}."
-msgstr ""
+msgstr "Un ou plusieurs arguments sont invalides : %{args}."
msgid "One or more contacts were successfully added."
-msgstr ""
+msgstr "Un ou plusieurs contacts ont été ajoutés avec succès."
msgid "One or more contacts were successfully removed."
-msgstr ""
+msgstr "Un ou plusieurs contacts ont été supprimés avec succès."
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -27578,43 +28072,43 @@ msgid "One or more of you personal access tokens were revoked"
msgstr ""
msgid "One or more of your %{provider} projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "Un ou plusieurs de vos projets %{provider} ne peuvent pas être importés directement dans GitLab car ils utilisent Subversion ou Mercurial plutôt que Git pour le contrôle de versions."
msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
msgid "One or more of your personal access tokens has expired."
-msgstr ""
+msgstr "Un ou plusieurs de vos jetons d'accès personnels ont expiré."
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less:"
-msgstr ""
+msgstr "Un ou plusieurs de vos jetons d'accès personnels expireront dans %{days_to_expire} jours ou moins :"
msgid "Only %{workspaceType} members with %{permissions} can view or be notified about this %{issuableType}."
-msgstr ""
+msgstr "Seuls les membres du %{workspaceType} ayant un rôle de %{permissions} peuvent voir ce(tte) %{issuableType} et être notifié à son sujet."
msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
-msgstr ""
+msgstr "Seule 1 ligne d'apparences peut exister"
msgid "Only HTTP(S)"
-msgstr ""
+msgstr "Uniquement HTTP(S)"
msgid "Only Issue ID or merge request ID is required"
-msgstr ""
+msgstr "Seul l'ID du ticket ou celui de la demande de fusion est requis"
msgid "Only Project Members"
msgstr ""
msgid "Only SSH"
-msgstr ""
+msgstr "Uniquement SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
-msgstr ""
+msgstr "Accessible uniquement aux %{membersPageLinkStart}membres du projet%{membersPageLinkEnd}. L'appartenance doit être accordée à chaque utilisateur de manière explicite."
msgid "Only active projects show up in the search and on the dashboard."
-msgstr ""
+msgstr "Seuls les projets actifs remontent dans la recherche et sur le tableau de bord."
msgid "Only allow anyone to register for accounts on GitLab instances that you intend to be used by anyone. Allowing anyone to register makes GitLab instances more vulnerable."
msgstr ""
@@ -27623,13 +28117,13 @@ msgid "Only effective when remote storage is enabled. Set to 0 for no size limit
msgstr ""
msgid "Only group members with at least the Reporter role can view or be notified about this epic"
-msgstr ""
+msgstr "Seuls les membres du groupe ayant au moins le rôle de Rapporteur peuvent voir cette épopée ou recevoir des notifications la concernant"
msgid "Only include features new to your current subscription tier."
-msgstr ""
+msgstr "N'inclure que les fonctionnalités nouvellement apparues dans l'édition correspondant à votre abonnement actuel."
msgid "Only members of this group can access the wiki."
-msgstr ""
+msgstr "Seuls les membres de ce groupe peuvent accéder au wiki."
msgid "Only policy:"
msgstr ""
@@ -27641,19 +28135,19 @@ msgid "Only project members can comment."
msgstr "Seuls les membres du projet peuvent commenter."
msgid "Only projects created under a Ultimate license are available in Security Dashboards."
-msgstr ""
+msgstr "Seuls les projets créés sous une licence Ultimate sont disponibles dans les Tableaux de bord de Sécurité."
msgid "Only reCAPTCHA v2 is supported:"
-msgstr ""
+msgstr "Seul reCAPTCHA v2 est supporté :"
msgid "Only required if not using role instance credentials."
msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
-msgstr ""
+msgstr "N'utiliser que des lettres minuscules, des chiffres et des tirets bas."
msgid "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
-msgstr ""
+msgstr "Seuls les utilisateurs vérifiés avec une adresse de courriel de l'un de ces domaines peuvent être ajoutés au groupe. Plusieurs domaines sont possibles."
msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
@@ -27671,19 +28165,19 @@ msgid "Open errors"
msgstr ""
msgid "Open in Gitpod"
-msgstr ""
+msgstr "Ouvrir dans Gitpod"
msgid "Open in Web IDE"
-msgstr ""
+msgstr "Ouvrir dans l'EDI Web"
msgid "Open in file view"
msgstr ""
msgid "Open in your IDE"
-msgstr ""
+msgstr "Ouvrir dans votre IDE"
msgid "Open new window"
-msgstr ""
+msgstr "Ouvrir une nouvelle fenêtre"
msgid "Open raw"
msgstr ""
@@ -27692,16 +28186,16 @@ msgid "Open sidebar"
msgstr "Ouvrir la barre latérale"
msgid "Open: %{open}"
-msgstr ""
+msgstr "Ouvert: %{open}"
msgid "OpenAPI"
-msgstr ""
+msgstr "OpenAPI"
msgid "OpenAPI Specification file URL"
-msgstr ""
+msgstr "URL du fichier de spécification OpenAPI"
msgid "OpenAPI Specification file path or URL"
-msgstr ""
+msgstr "URL ou chemin du fichier de Spécification OpenAPI"
msgid "OpenSearch's region."
msgstr ""
@@ -27722,19 +28216,19 @@ msgid "Opens in a new window"
msgstr "Ouvrir dans une nouvelle fenêtre"
msgid "Opens new window"
-msgstr ""
+msgstr "Ouvre une nouvelle fenêtre"
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
msgid "Operation not allowed"
-msgstr ""
+msgstr "Opération non autorisée"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
msgid "Operations"
-msgstr ""
+msgstr "Opérations"
msgid "Operations Dashboard"
msgstr "Tableau de bord des opérations"
@@ -27752,13 +28246,13 @@ msgid "OperationsDashboard|Operations Dashboard"
msgstr ""
msgid "OperationsDashboard|The Operations and Environments dashboards share the same list of projects. When you add or remove a project from one, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Le tableau de bord des Opérations et celui des Environnements partagent la même liste de projets. Lorsque vous ajoutez ou supprimez un projet de l'un d'eux, GitLab l'ajoute ou le supprime de l’autre. %{linkStart}Plus d'informations%{linkEnd}"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "Le tableau de bord des opérations fournit un résumé de l’état de santé opérationnel de chaque projet, comprenant les états des pipelines et des alertes."
msgid "Opstrace endpoint for Error Tracking integration"
-msgstr ""
+msgstr "Point d'arrivée Opstrace pour l'intégration du Suivi d'Erreurs"
msgid "Optimize your workflow with CI/CD Pipelines"
msgstr ""
@@ -27767,7 +28261,7 @@ msgid "Optional"
msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
-msgstr ""
+msgstr "Le paramètre optionnel « variables » doit être un hash. Ex. : variables[key1]=valeur1"
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Vous pouvez éventuellement %{link_to_customize} la manière dont les adresses de courriel et les noms d’utilisateur issus de FogBugz sont importés dans GitLab."
@@ -27779,19 +28273,19 @@ msgid "Or you can choose one of the suggested colors below"
msgstr "Ou vous pouvez choisir l’une des couleurs suggérées ciâ€dessous"
msgid "Ordered list"
-msgstr ""
+msgstr "Liste numérotée"
msgid "Organizations"
-msgstr ""
+msgstr "Entreprises"
msgid "Orphaned member"
-msgstr ""
+msgstr "Membre orphelin"
msgid "Other Labels"
msgstr "Autres étiquettes"
msgid "Other available runners"
-msgstr ""
+msgstr "Autres exécuteurs disponibles"
msgid "Other information"
msgstr "Autres informations"
@@ -27800,51 +28294,54 @@ msgid "Other merge requests block this MR"
msgstr ""
msgid "Other versions"
-msgstr ""
+msgstr "Autres versions"
msgid "Other visibility settings have been disabled by the administrator."
msgstr ""
msgid "Otherwise, click the link below to complete the process."
-msgstr ""
+msgstr "Sinon, cliquez sur le lien ci-dessous pour terminer le processus."
msgid "Otherwise, click the link below to complete the process:"
-msgstr ""
+msgstr "Sinon, cliquez sur le lien ci-dessous pour terminer le processus :"
msgid "Our team has been notified. Please try again."
-msgstr ""
+msgstr "Notre équipe a été notifiée. Veuillez réessayer."
msgid "Out-of-compliance with this project's policies and should be removed"
-msgstr ""
+msgstr "Non conforme(s) aux stratégies de ce projet et à supprimer"
msgid "OutboundRequests|Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "Autoriser les requêtes vers le réseau local depuis les hooks et les services."
msgid "OutboundRequests|Allow requests to the local network from system hooks"
-msgstr ""
+msgstr "Autoriser les requêtes vers le réseau local depuis les hooks systèmes"
msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
-msgstr ""
+msgstr "Autoriser les requêtes vers le réseau local depuis les webhooks et les services"
msgid "OutboundRequests|Enforce DNS rebinding attack protection"
-msgstr ""
+msgstr "Imposer la protection contre les attaques par DNS rebinding"
msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
-msgstr ""
+msgstr "Adresses IP locales et noms de domaines auxquels les services et hooks peuvent accéder"
msgid "OutboundRequests|Outbound requests"
-msgstr ""
+msgstr "Requêtes sortantes"
msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
-msgstr ""
+msgstr "Les requêtes vers ces domaines et adresses IP sont accessibles à la fois aux hooks systèmes et aux hooks Web même lorsque les requêtes locales ne sont pas autorisées. Les plages d'IP telles que 1:0:0:0:0:0:0/124 ou 127.0.0/28 sont prises en charge. Les domaines wildcard ne sont pas pris en charge. Pour séparer les entrées, utilisez des virgules, des points-virgules ou des nouvelles lignes. La liste d'autorisation peut contenir un maximum de 1000 entrées. Les domaines doivent utiliser l'encodage IDNA."
msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
-msgstr ""
+msgstr "Résoudre les adresses IP une seule fois et les utiliser pour soumettre des requêtes."
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
-msgstr ""
+msgstr "GitLab peut ne pas fonctionner correctement car vous utilisez un navigateur Web obsolète."
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr "Veuillez installer un %{browser_link_start}navigateur Web pris en charge%{browser_link_end} pour une meilleure expérience."
+
+msgid "Outdent line"
msgstr ""
msgid "Overridden"
@@ -27857,7 +28354,7 @@ msgid "Overwrite diverged branches"
msgstr "Écraser les branches divergentes"
msgid "Owned by %{image_tag}"
-msgstr ""
+msgstr "Appartenant à %{image_tag}"
msgid "Owned by anyone"
msgstr "Appartenant à n'importe qui"
@@ -27866,13 +28363,13 @@ msgid "Owned by me"
msgstr "M'appartenant"
msgid "Owned by:"
-msgstr ""
+msgstr "Appartient à :"
msgid "Owner"
msgstr "Propriétaire"
msgid "Owners and administrators"
-msgstr ""
+msgstr "Propriétaires et administrateurs"
msgid "Owners can modify this selection."
msgstr ""
@@ -27881,115 +28378,115 @@ 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 "En fournissant mes informations de contact, j'accepte que GitLab puisse me contacter par courriel à propos de ses produits, services et événements. Vous pouvez vous rétracter à tout moment en vous désinscrivant depuis les courriels ou en vous rendant dans notre centre de préférence de communication."
msgid "PQL|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "PQL|Contact our Sales team"
-msgstr ""
+msgstr "Contacter notre équipe commerciale"
msgid "PQL|Contact sales"
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 "Bonjour %{userName}. Avant de vous mettre en contact avec notre équipe commerciale, nous souhaiterions vérifier et compléter les informations ci-dessous."
msgid "PQL|Message for the Sales team (optional)"
-msgstr ""
+msgstr "Message pour l'équipe commerciale (facultatif)"
msgid "PQL|Please select a city or state"
-msgstr ""
+msgstr "Veuillez sélectionner une ville ou une région"
msgid "PQL|Submit information"
-msgstr ""
+msgstr "Soumettre les informations"
msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
-msgstr ""
+msgstr "Merci de nous avoir contacté ! Notre équipe commerciale reviendra vers vous bientôt."
msgid "Package Registry"
-msgstr ""
+msgstr "Registre de paquets"
msgid "Package Registry: authenticated API requests"
-msgstr ""
+msgstr "Registre de Paquets : requêtes d'API authentifiées"
msgid "Package Registry: unauthenticated API requests"
-msgstr ""
+msgstr "Registre de Paquets : requêtes d'API non authentifiées"
msgid "Package already exists"
-msgstr ""
+msgstr "Le paquet existe déjà"
msgid "Package and registry settings"
-msgstr ""
+msgstr "Paramètres des paquets et registres"
msgid "Package deleted successfully"
msgstr ""
msgid "Package file size limits"
-msgstr ""
+msgstr "Limites de taille de fichier des paquets"
msgid "Package recipe already exists"
-msgstr ""
+msgstr "La recette du paquet existe déjà"
msgid "Package registry rate limits"
msgstr ""
msgid "Package type"
-msgstr ""
+msgstr "Type de paquet"
msgid "Package type must be Conan"
-msgstr ""
+msgstr "Le type de paquet doit être Conan"
msgid "Package type must be Debian"
-msgstr ""
+msgstr "Le type de paquet doit être Debian"
msgid "Package type must be Helm"
-msgstr ""
+msgstr "Le type de paquet doit être Helm"
msgid "Package type must be Maven"
-msgstr ""
+msgstr "Le type de paquet doit être Maven"
msgid "Package type must be NPM"
msgstr ""
msgid "Package type must be NuGet"
-msgstr ""
+msgstr "Le type de paquet doit être NuGet"
msgid "Package type must be PyPi"
-msgstr ""
+msgstr "Le type de paquet doit être PyPi"
msgid "Package type must be RPM"
-msgstr ""
+msgstr "Le type de paquet doit être RPM"
msgid "Package type must be RubyGems"
-msgstr ""
+msgstr "Le type de paquet doit être RubyGems"
msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
-msgstr ""
+msgstr "%{name} version %{version} été créé pour la première fois %{datetime}"
msgid "PackageRegistry|Add Conan Remote"
-msgstr ""
+msgstr "Ajouter un dépôt distant Conan"
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
-msgstr ""
+msgstr "Ajouter la commande du dépôt de DSL Kotlin pour Gradle"
msgid "PackageRegistry|Add NuGet Source"
-msgstr ""
+msgstr "Ajouter une source NuGet"
msgid "PackageRegistry|Add composer registry"
-msgstr ""
+msgstr "Ajouter un registre composer"
msgid "PackageRegistry|Additional metadata"
-msgstr ""
+msgstr "Métadonnées supplémentaires"
msgid "PackageRegistry|Allow duplicates"
-msgstr ""
+msgstr "Autoriser les doublons"
msgid "PackageRegistry|Allow packages with the same name and version to be uploaded to the registry. The newest version of a package is always used when installing."
-msgstr ""
+msgstr "Autoriser le téléversement vers le registre de paquets qui ont les mêmes nom et version. La dernière version d'un paquet est toujours utilisée lors de l'installation."
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -27998,64 +28495,64 @@ msgid "PackageRegistry|App name: %{name}"
msgstr ""
msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
-msgstr ""
+msgstr "Construction par le pipeline %{link} déclenché %{datetime} par %{author}"
msgid "PackageRegistry|Composer"
-msgstr ""
+msgstr "Composer"
msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
-msgstr ""
+msgstr "Composer.json avec licence : %{license} et version : %{version}"
msgid "PackageRegistry|Conan"
-msgstr ""
+msgstr "Conan"
msgid "PackageRegistry|Conan Command"
-msgstr ""
+msgstr "Commande Conan"
msgid "PackageRegistry|Copy .pypirc content"
-msgstr ""
+msgstr "Copier le contenu de .pypirc"
msgid "PackageRegistry|Copy Conan Command"
-msgstr ""
+msgstr "Copier la commande Conan"
msgid "PackageRegistry|Copy Conan Setup Command"
-msgstr ""
+msgstr "Copier la commande de configuration Conan"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
-msgstr ""
+msgstr "Copier la commande d'installation Gradle Groovy DSL"
msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
-msgstr ""
+msgstr "Copier la commande d'installation du DSL Kotlin pour Gradle"
msgid "PackageRegistry|Copy Maven XML"
-msgstr ""
+msgstr "Copier le XML de Maven"
msgid "PackageRegistry|Copy Maven command"
-msgstr ""
+msgstr "Copier la commande Maven"
msgid "PackageRegistry|Copy Maven registry XML"
-msgstr ""
+msgstr "Copier le XML du registre Maven"
msgid "PackageRegistry|Copy NuGet Command"
-msgstr ""
+msgstr "Copier la commande NuGet"
msgid "PackageRegistry|Copy NuGet Setup Command"
-msgstr ""
+msgstr "Copier la commande de configuration NuGet"
msgid "PackageRegistry|Copy Pip command"
-msgstr ""
+msgstr "Copier la commande Pip"
msgid "PackageRegistry|Copy SHA"
-msgstr ""
+msgstr "Copier le SHA"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
-msgstr ""
+msgstr "Copier ajouter la commande de dépôt Gradle Groovy DSL"
msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
-msgstr ""
+msgstr "Copier la commande pour ajouter le dépôt de DSL Kotlin pour Gradle"
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
-msgstr ""
+msgstr "Copiez et collez ceci à l'intérieur du bloc de %{codeStart}dépendances%{codeEnd} de votre %{codeStart}pom.xml%{codeEnd}."
msgid "PackageRegistry|Copy npm command"
msgstr ""
@@ -28064,7 +28561,7 @@ msgid "PackageRegistry|Copy npm setup command"
msgstr ""
msgid "PackageRegistry|Copy registry include"
-msgstr ""
+msgstr "Copier l'inclusion de registre"
msgid "PackageRegistry|Copy require package include"
msgstr ""
@@ -28079,18 +28576,15 @@ msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
-msgstr ""
+msgstr "Créé par le commit %{link} sur la branche %{branch}"
msgid "PackageRegistry|Debian"
-msgstr ""
+msgstr "Debian"
msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
+msgstr[0] "Supprimer 1 ressource"
+msgstr[1] "Supprimer %d ressources"
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -28098,71 +28592,77 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr "Supprimer la ressource du paquet"
+
msgid "PackageRegistry|Delete selected"
-msgstr ""
+msgstr "Supprimer la sélection"
msgid "PackageRegistry|Delete this package"
msgstr ""
msgid "PackageRegistry|Duplicate packages"
-msgstr ""
+msgstr "Paquets dupliqués"
msgid "PackageRegistry|Error publishing"
-msgstr ""
+msgstr "Erreur de publication"
msgid "PackageRegistry|Examples of assets include .pom & .jar files"
-msgstr ""
+msgstr "Des exemples de ressources incluent les fichiers .pom et .jar"
msgid "PackageRegistry|Failed to load the package data"
-msgstr ""
+msgstr "Échec du chargement des données du paquet"
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
-msgstr ""
+msgstr "Pour plus d'informations sur les paquets Composer dans GitLab, %{linkStart}voir la documentation.%{linkEnd}"
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour plus d'informations sur le registre Conan, %{linkStart}consultez la documentation%{linkEnd}."
msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour plus d'informations sur le registre Maven, %{linkStart}consultez la documentation%{linkEnd}."
msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour plus d'informations sur le registre NuGet , %{linkStart}consultez la documentation%{linkEnd}."
msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour plus d'informations sur le registre PyPi, %{linkStart}consultez la documentation%{linkEnd}."
msgid "PackageRegistry|Generic"
-msgstr ""
+msgstr "Générique"
msgid "PackageRegistry|Gradle Groovy DSL"
-msgstr ""
+msgstr "DSL Groovy pour Gradle"
msgid "PackageRegistry|Gradle Groovy DSL install command"
-msgstr ""
+msgstr "Commande d'installation Gradle Groovy DSL"
msgid "PackageRegistry|Gradle Kotlin DSL"
-msgstr ""
+msgstr "DSL Kotlin pour Gradle"
msgid "PackageRegistry|Gradle Kotlin DSL install command"
-msgstr ""
+msgstr "Commande d'installation du DSL Kotlin pour Gradle"
msgid "PackageRegistry|Helm"
-msgstr ""
+msgstr "Helm"
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
-msgstr ""
+msgstr "Si vous ne l'avez pas déjà fait, vous devrez ajouter ce qui suit à votre fichier %{codeStart}.pypirc%{codeEnd}."
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
-msgstr ""
+msgstr "Si vous ne l'avez pas déjà fait, vous devrez ajouter ce qui suit à votre fichier %{codeStart}pom.xml%{codeEnd}."
msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Instance-level"
-msgstr ""
+msgstr "Niveau instance"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
-msgstr ""
+msgstr "Paquet non valide : l'extraction des méta-données a échoué"
+
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "Dernier téléchargement %{dateTime}"
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28171,129 +28671,132 @@ msgid "PackageRegistry|License information located at %{link}"
msgstr ""
msgid "PackageRegistry|Manage storage used by package assets"
-msgstr ""
+msgstr "Gérer le stockage utilisé par les ressources des paquets"
msgid "PackageRegistry|Manually Published"
-msgstr ""
+msgstr "Publié manuellement"
msgid "PackageRegistry|Maven"
-msgstr ""
+msgstr "Maven"
msgid "PackageRegistry|Maven Command"
-msgstr ""
+msgstr "Commande Maven"
msgid "PackageRegistry|Maven XML"
-msgstr ""
+msgstr "XML Maven"
msgid "PackageRegistry|NuGet"
-msgstr ""
+msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
-msgstr ""
+msgstr "Commande NuGet"
msgid "PackageRegistry|Number of duplicate assets to keep"
-msgstr ""
+msgstr "Nombre de ressources dupliquées à conserver"
msgid "PackageRegistry|Package Registry"
-msgstr ""
+msgstr "Registre de Paquets"
+
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr "Ressource du paquet supprimée avec succès"
msgid "PackageRegistry|Package assets deleted successfully"
-msgstr ""
+msgstr "Ressources de paquet supprimées avec succès"
msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
-
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr ""
+msgstr "Paquet supprimé avec succès"
msgid "PackageRegistry|Package formats"
-msgstr ""
+msgstr "Formats de paquets"
msgid "PackageRegistry|Package has %{updatesCount} archived update"
msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le paquet a %{updatesCount} mise à jour archivée"
+msgstr[1] "Le paquet a %{updatesCount} mises à jour archivées"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
+msgstr "Paquet mis à jour par le commit %{link} sur la branche %{branch}, construit par le pipeline %{pipeline} et publié dans le registre %{datetime}"
+
+msgid "PackageRegistry|Permanently delete"
msgstr ""
msgid "PackageRegistry|Permanently delete assets"
-msgstr ""
+msgstr "Supprimer définitivement les ressources"
msgid "PackageRegistry|Pip Command"
-msgstr ""
+msgstr "Commande Pip"
msgid "PackageRegistry|Project-level"
-msgstr ""
+msgstr "Niveau projet"
msgid "PackageRegistry|Publish packages if their name or version matches this regex."
-msgstr ""
+msgstr "Publier les paquets si leur nom ou leur version correspond à cette expression rationnelle."
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
msgid "PackageRegistry|PyPI"
-msgstr ""
+msgstr "PyPI"
msgid "PackageRegistry|Recipe: %{recipe}"
-msgstr ""
+msgstr "Recette : %{recipe}"
msgid "PackageRegistry|Registry setup"
-msgstr ""
+msgstr "Configuration du Registre"
msgid "PackageRegistry|Remove package"
msgstr ""
msgid "PackageRegistry|Required Python: %{pythonVersion}"
-msgstr ""
+msgstr "Python requis : %{pythonVersion}"
msgid "PackageRegistry|RubyGems"
-msgstr ""
+msgstr "RubyGems"
msgid "PackageRegistry|Show Composer commands"
-msgstr ""
+msgstr "Afficher les commandes Composer"
msgid "PackageRegistry|Show Conan commands"
-msgstr ""
+msgstr "Afficher les commandes Conan"
msgid "PackageRegistry|Show NPM commands"
-msgstr ""
+msgstr "Afficher les commandes NPM"
msgid "PackageRegistry|Show Nuget commands"
-msgstr ""
+msgstr "Afficher les commandes Nuget"
msgid "PackageRegistry|Show PyPi commands"
-msgstr ""
+msgstr "Afficher les commandes PyPi"
msgid "PackageRegistry|Show Yarn commands"
-msgstr ""
+msgstr "Afficher les commandes Yarn"
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
-msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
+msgstr "Une erreur s’est produite lors de la suppression de la ressource du paquet."
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr "Une erreur s’est produite lors de la suppression des ressources du paquet."
msgid "PackageRegistry|Something went wrong while deleting the package."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la suppression du paquet."
msgid "PackageRegistry|Something went wrong while fetching the package history."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération de l'historique du paquet."
msgid "PackageRegistry|Something went wrong while fetching the package metadata."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des métadonnées du paquet."
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche."
msgid "PackageRegistry|Source project located at %{link}"
-msgstr ""
+msgstr "Projet source situé à %{link}"
msgid "PackageRegistry|Target SHA: %{sha}"
-msgstr ""
+msgstr "SHA cible : %{sha}"
msgid "PackageRegistry|There are no other versions of this package."
-msgstr ""
+msgstr "Il n’y a pas d'autre version de ce paquet."
msgid "PackageRegistry|There are no packages yet"
msgstr ""
@@ -28302,57 +28805,57 @@ msgid "PackageRegistry|There was a problem fetching the details for this package
msgstr ""
msgid "PackageRegistry|There was a timeout and the package was not published. Delete this package and try again."
-msgstr ""
+msgstr "Un délai d'attente a expiré et le paquet n'a pas été publié. Supprimez ce paquet et réessayez."
msgid "PackageRegistry|There was an error publishing a %{packageName} package"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la publication d'un paquet %{packageName}"
msgid "PackageRegistry|This NuGet package has no dependencies."
-msgstr ""
+msgstr "Ce paquet NuGet n'a aucune dépendance."
msgid "PackageRegistry|To widen your search, change or remove the filters above."
msgstr "Pour élargir votre recherche, modifiez ou supprimez les filtres ci-dessus."
msgid "PackageRegistry|Type"
-msgstr ""
+msgstr "Type"
msgid "PackageRegistry|Unable to fetch package version information."
-msgstr ""
+msgstr "Impossible de récupérer les informations de version du paquet."
msgid "PackageRegistry|Unable to load package"
msgstr ""
msgid "PackageRegistry|When a package with same name and version is uploaded to the registry, more assets are added to the package. To save storage space, keep only the most recent assets."
-msgstr ""
+msgstr "Lorsqu’un paquet ayant le même nom et la même version est téléversé dans le registre, des ressources supplémentaires sont ajoutées au paquet. Pour économiser de l'espace de stockage, ne conservez que les ressources les plus récentes."
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer %{filename}. Il s'agit d'une action destructrice qui peut rendre votre paquet inutilisable. Êtes-vous sûr(e) ?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Vous êtes sur le point de supprimer 1 ressource. Cette opération est irréversible."
+msgstr[1] "Vous êtes sur le point de supprimer %d ressources. Cette opération est irréversible."
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer la version %{version} de %{name}. Êtes-vous sûr(e) ?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
-msgstr ""
+msgstr "Vous pouvez également avoir besoin de configurer l’authentification à l’aide d’un jeton d’authentification. %{linkStart}Voir la documentation%{linkEnd} pour en savoir plus."
msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
-msgstr ""
+msgstr "Vous aurez besoin d'un %{linkStart}jeton d'accès personnel%{linkEnd}."
msgid "PackageRegistry|npm"
-msgstr ""
+msgstr "npm"
msgid "PackageRegistry|published by %{author}"
-msgstr ""
+msgstr "publié par %{author}"
msgid "Packages and registries"
-msgstr ""
+msgstr "Paquets & registres"
msgid "Page not found"
msgstr ""
@@ -28361,22 +28864,22 @@ msgid "PagerDutySettings|Active"
msgstr ""
msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
-msgstr ""
+msgstr "Créer un incident GitLab pour chaque incident PagerDuty en %{linkStart}configurant un webhook dans PagerDuty%{linkEnd}"
msgid "PagerDutySettings|Failed to update Webhook URL"
-msgstr ""
+msgstr "Échec de la mise à jour de l’URL du Webhook"
msgid "PagerDutySettings|Reset webhook URL"
-msgstr ""
+msgstr "Réinitialiser l’URL du webhook"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
-msgstr ""
+msgstr "La réinitialisation de l’URL du webhook de ce projet nécessitera la mise à jour des paramètres de cette intégration dans PagerDuty."
msgid "PagerDutySettings|Webhook URL"
-msgstr ""
+msgstr "URL du Webhook"
msgid "PagerDutySettings|Webhook URL update was successful"
-msgstr ""
+msgstr "La mise à jour de l'URL du Webhook a réussi"
msgid "Pages"
msgstr "Pages"
@@ -28430,7 +28933,7 @@ msgid "Parent epic is not present."
msgstr ""
msgid "Parsing error for param :embed_json. %{message}"
-msgstr ""
+msgstr "Erreur d'analyse pour le param :embed_json. %{message}"
msgid "Part of merge request changes"
msgstr "Partie des modifications de la demande de fusion"
@@ -28442,7 +28945,7 @@ msgid "Participants"
msgstr ""
msgid "Pass job variables"
-msgstr ""
+msgstr "Transmettre des variables de tâche"
msgid "Passed"
msgstr ""
@@ -28466,49 +28969,49 @@ msgid "Password successfully changed"
msgstr ""
msgid "Password was successfully updated. Please sign in again."
-msgstr ""
+msgstr "Le mot de passe a été mis à jour avec succès. Veuillez vous reconnecter."
msgid "PasswordPrompt|Confirm password"
msgstr ""
msgid "PasswordPrompt|Confirm password to continue"
-msgstr ""
+msgstr "Confirmez le mot de passe pour continuer"
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "Le mot de passe est requis"
msgid "PasswordPrompt|Please enter your password to confirm"
-msgstr ""
+msgstr "Veuillez entrer votre mot de passe pour confirmer"
msgid "Passwords should be unique and not used for any other sites or services."
-msgstr ""
+msgstr "Les mots de passe doivent être uniques et ne pas être utilisés pour d'autres sites ou services."
msgid "Password|requires at least one lowercase letter"
-msgstr ""
+msgstr "nécessite au moins une lettre minuscule"
msgid "Password|requires at least one number"
-msgstr ""
+msgstr "nécessite au moins un nombre"
msgid "Password|requires at least one symbol character"
-msgstr ""
+msgstr "nécessite au moins un symbole"
msgid "Password|requires at least one uppercase letter"
-msgstr ""
+msgstr "nécessite au moins une lettre majuscule"
msgid "Past due"
msgstr ""
msgid "Paste a public key here."
-msgstr ""
+msgstr "Collez une clé publique ici."
msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
-msgstr ""
+msgstr "Coller une clé publique ici. %{link_start}Comment la générer ?%{link_end}"
msgid "Paste confidential epic link"
-msgstr ""
+msgstr "Coller le lien de l'épopée confidentielle"
msgid "Paste confidential issue link"
-msgstr ""
+msgstr "Coller le lien du ticket confidentiel"
msgid "Paste epic link"
msgstr ""
@@ -28517,16 +29020,16 @@ msgid "Paste issue link"
msgstr ""
msgid "Paste link"
-msgstr ""
+msgstr "Coller le lien"
msgid "Paste project path (i.e. gitlab-org/gitlab)"
-msgstr ""
+msgstr "Coller le chemin du projet (c.-à-d. gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
-msgstr ""
+msgstr "Collez ce DSN dans votre SDK Sentry"
msgid "Patch to apply"
-msgstr ""
+msgstr "Correctif à appliquer"
msgid "Path"
msgstr ""
@@ -28535,46 +29038,43 @@ msgid "Path:"
msgstr "Chemin d’accès :"
msgid "Paths can contain wildcards, like */welcome"
-msgstr ""
+msgstr "Les chemins d'accès peuvent contenir des jokers , p.ex. */bienvenue"
msgid "Paths to protect with rate limiting"
-msgstr ""
+msgstr "Chemins à protéger avec une limitation de fréquence"
msgid "Pause"
msgstr "Pause"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
msgid "Paused"
-msgstr ""
+msgstr "En pause"
msgid "Paused runners don't accept new jobs"
-msgstr ""
+msgstr "Les exécuteurs en pause n'acceptent pas de nouvelles tâches"
msgid "Peer review by"
-msgstr ""
+msgstr "Revue des pairs par"
msgid "Pending"
msgstr "En attente"
msgid "Pending Deletion"
-msgstr ""
+msgstr "Suppression en attente"
msgid "Pending comments"
-msgstr ""
+msgstr "Commentaires en attente"
msgid "Pending deletion"
-msgstr ""
+msgstr "Suppression en attente"
msgid "Pending owner action"
msgstr ""
msgid "Pending sync…"
-msgstr ""
+msgstr "Synchro en attente…"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Les personnes sans autorisation ne recevront jamais de notifications et ne pourront pas commenter."
@@ -28586,13 +29086,13 @@ msgid "Per your subscription agreement with GitLab, you must report your license
msgstr "Conformément aux termes de votre contrat d'abonnement avec GitLab, vous devez communiquer vos données d'utilisation de licences à une fréquence mensuelle. GitLab utilise ces données pour maintenir votre abonnement à jour. Pour ce faire, exportez votre fichier d'utilisation de licence et envoyez-le par courriel à %{renewal_service_email}. Si une mise à jour de la licence est nécessaire, GitLab vous enverra celle-ci à l'adresse de courriel enregistrée dans le %{customers_dot} et vous pourrez la téléverser sur votre instance."
msgid "Percent rollout must be an integer number between 0 and 100"
-msgstr ""
+msgstr "Le pourcentage de déploiement doit être un nombre entier compris entre 0 et 100"
msgid "Percentage"
-msgstr ""
+msgstr "Pourcentage"
msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
-msgstr ""
+msgstr "Effectuer des opérations avancées telles que changer de chemin, transférer, exporter ou supprimer le groupe."
msgid "Perform code reviews and enhance collaboration with merge requests."
msgstr ""
@@ -28604,28 +29104,28 @@ msgid "Performance optimization"
msgstr "Optimisation des performances"
msgid "PerformanceBar|Backend"
-msgstr ""
+msgstr "Backend"
msgid "PerformanceBar|Bullet notifications"
-msgstr ""
+msgstr "Notifications Bullet"
msgid "PerformanceBar|DOM Content Loaded"
-msgstr ""
+msgstr "DOM Content Loaded"
msgid "PerformanceBar|Download"
msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
-msgstr ""
+msgstr "Appels Elasticsearch"
msgid "PerformanceBar|External Http calls"
-msgstr ""
+msgstr "Appels Http externes"
msgid "PerformanceBar|First Contentful Paint"
-msgstr ""
+msgstr "First Contentful Paint"
msgid "PerformanceBar|Flamegraph with mode:"
-msgstr ""
+msgstr "Flamegraph avec le mode :"
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -28634,7 +29134,7 @@ msgid "PerformanceBar|Gitaly calls"
msgstr ""
msgid "PerformanceBar|Memory"
-msgstr ""
+msgstr "Mémoire"
msgid "PerformanceBar|Memory report"
msgstr ""
@@ -28649,40 +29149,40 @@ msgid "PerformanceBar|SQL queries"
msgstr ""
msgid "PerformanceBar|Sort by duration"
-msgstr ""
+msgstr "Trier par durée"
msgid "PerformanceBar|Sort chronologically"
-msgstr ""
+msgstr "Trier chronologiquement"
msgid "PerformanceBar|Stats"
-msgstr ""
+msgstr "Stats"
msgid "PerformanceBar|Total duration"
-msgstr ""
+msgstr "Durée totale"
msgid "PerformanceBar|Trace"
msgstr ""
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "objet"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "mur"
msgid "Period in seconds"
-msgstr ""
+msgstr "Période en secondes"
msgid "Period of inactivity (days)"
-msgstr ""
+msgstr "Période d'inactivité (jours)"
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "Période d'inactivité avant désactivation."
msgid "Permalink"
-msgstr ""
+msgstr "Lien permanent"
msgid "Permanently remove group"
msgstr ""
@@ -28691,7 +29191,7 @@ msgid "Permissions"
msgstr "Droits d’accès"
msgid "Permissions Help"
-msgstr ""
+msgstr "Aide sur les Autorisations"
msgid "Permissions and group features"
msgstr ""
@@ -28700,28 +29200,28 @@ msgid "Personal Access Token"
msgstr "Jeton d’accès personnel"
msgid "Personal Access Token prefix"
-msgstr ""
+msgstr "Préfixe du Jeton d'Accès Personnel"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
msgid "Personal projects"
-msgstr ""
+msgstr "Projets personnels"
msgid "Personal projects limit:"
-msgstr ""
+msgstr "Limite de projets personnels :"
msgid "PersonalProject|Learn to move a project to a group"
-msgstr ""
+msgstr "En savoir plus sur le déplacement d'un projet vers un groupe"
msgid "PersonalProject|Some GitLab features, including the ability to upgrade to a paid plan or start a free trial, are only available for groups and projects inside groups. %{projectName} is a personal project, so none of this is available. We recommend you move your project to a group to unlock GitLab's full potential."
-msgstr ""
+msgstr "Certaines fonctionnalités de GitLab, dont la possibilité de faire une mise à niveau vers un forfait payant ou de démarrer une période d'essai gratuite, ne sont disponibles que pour les groupes et les projets à l'intérieur de groupes. %{projectName} étant un projet personnel, aucune de ces possibilités n'est donc disponible. Nous vous recommandons de déplacer votre projet dans un groupe pour déverrouiller tout le potentiel de GitLab."
msgid "PersonalProject|We have some instructions to help you create a group and move your project into it."
-msgstr ""
+msgstr "Nous disposons de quelques instructions pour vous aider à créer un groupe et y déplacer votre projet."
msgid "PersonalProject|Your project %{projectName} is not in a group"
-msgstr ""
+msgstr "Votre projet %{projectName} n'est pas dans un groupe"
msgid "Phabricator Server Import"
msgstr ""
@@ -28751,13 +29251,13 @@ msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir réinitialiser le fichier à sa dernière version validée ?"
msgid "Pipeline ID"
msgstr ""
msgid "Pipeline IID"
-msgstr ""
+msgstr "IID de pipeline"
msgid "Pipeline Schedule"
msgstr "Planification de pipeline"
@@ -28766,7 +29266,7 @@ msgid "Pipeline Schedules"
msgstr "Planifications de pipelines"
msgid "Pipeline URL"
-msgstr ""
+msgstr "URL du pipeline"
msgid "Pipeline creation rate limits"
msgstr ""
@@ -28775,7 +29275,7 @@ msgid "Pipeline durations for the last 30 commits"
msgstr ""
msgid "Pipeline ran in fork of project"
-msgstr ""
+msgstr "Pipeline exécuté dans un fork du projet"
msgid "Pipeline status emails"
msgstr ""
@@ -28784,7 +29284,7 @@ msgid "Pipeline subscriptions"
msgstr ""
msgid "Pipeline subscriptions trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
-msgstr ""
+msgstr "Les abonnements de pipeline déclenchent un nouveau pipeline sur la branche par défaut de ce projet quand un pipeline se termine avec succès pour une nouvelle étiquette de la %{default_branch_docs} du projet souscrit."
msgid "Pipeline triggers"
msgstr "Déclencheurs de pipeline"
@@ -28793,16 +29293,16 @@ msgid "Pipeline: %{status}"
msgstr ""
msgid "PipelineCharts|An error has occurred when retrieving the analytics data"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des données analytiques"
msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des données des pipelines"
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
-msgstr ""
+msgstr "Une erreur inconnue s'est produite lors du traitement des analyses CI/CD."
msgid "PipelineCharts|CI/CD Analytics"
-msgstr ""
+msgstr "Analyses CI/CD"
msgid "PipelineCharts|Failed:"
msgstr "Échecs :"
@@ -28817,58 +29317,58 @@ msgid "PipelineCharts|Successful:"
msgstr "Réussites :"
msgid "PipelineCharts|There was an error parsing the data for the charts."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’analyse des données pour les graphiques."
msgid "PipelineCharts|Total:"
msgstr "Total :"
msgid "PipelineEditorFileTree|Configuration files added with the include keyword"
-msgstr ""
+msgstr "Fichiers de configuration ajoutés avec le mot-clé include"
msgid "PipelineEditorFileTree|When you use the include keyword to add pipeline configuration from files in the project, those files will be listed here."
msgstr ""
msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
-msgstr ""
+msgstr "Parcourir des %{linkStart}exemples et des modèles de CI/CD%{linkEnd}"
msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
-msgstr ""
+msgstr "Validez le fichier sur votre dépôt. Le pipeline sera alors exécuté automatiquement."
msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
-msgstr ""
+msgstr "Premiers pas avec GitLab CI / CD"
msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
-msgstr ""
+msgstr "GitLab CI/CD peut automatiquement construire, tester et déployer votre application."
msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
-msgstr ""
+msgstr "Si vous utilisez une instance auto-gérée de GitLab, %{linkStart}assurez-vous que votre instance dispose d'exécuteurs disponibles.%{linkEnd}"
msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
-msgstr ""
+msgstr "En savoir plus sur les %{linkStart}concepts de GitLab CI/CD%{linkEnd}"
msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
-msgstr ""
+msgstr "Rendez votre pipeline plus efficace avec le %{linkStart}mot-clé Needs%{linkEnd}"
msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
msgstr ""
msgid "PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run."
-msgstr ""
+msgstr "Sélectionnez l'ID du pipeline pour afficher les détails complets de votre première exécution de pipeline."
msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
-msgstr ""
+msgstr "Les tâches et les étapes du pipeline sont définies dans un fichier %{codeStart}.gitlab-ci.yml%{codeEnd}. Vous pouvez modifier, visualiser et valider la syntaxe de ce fichier en utilisant l'Éditeur de Pipeline."
msgid "PipelineEditorTutorial|The pipeline status is at the top of the page."
-msgstr ""
+msgstr "L'état du pipeline figure en haut de la page."
msgid "PipelineEditorTutorial|This template creates a simple test pipeline. To use it:"
-msgstr ""
+msgstr "Ce modèle crée un pipeline de test simple. Pour l'utiliser :"
msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
-msgstr ""
+msgstr "Utilisez les onglets Visualisation et Lint de l'Éditeur de Pipeline pour visualiser votre pipeline et vérifier la présence d'erreurs ou d'avertissements avant de valider vos modifications."
msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
-msgstr ""
+msgstr "Voir la %{linkStart}référence de la syntaxe de .gitlab-ci.yml%{linkEnd}"
msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
msgstr ""
@@ -28880,64 +29380,64 @@ msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr ""
msgid "PipelineEditor|Configuration content has changed. Re-run validation for updated results."
-msgstr ""
+msgstr "Le contenu de la configuration a changé. Relancez la validation pour des résultats actualisés."
msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
-msgstr ""
+msgstr "Le contenu actuel de l’onglet Modification sera utilisé pour la simulation."
msgid "PipelineEditor|Git push event to the default branch"
-msgstr ""
+msgstr "Événement de poussée Git vers la branche par défaut"
msgid "PipelineEditor|Other pipeline sources are not available yet."
-msgstr ""
+msgstr "D'autres sources de pipeline ne sont pas encore disponibles."
msgid "PipelineEditor|Pipeline Source"
-msgstr ""
+msgstr "Source du pipeline"
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies."
-msgstr ""
+msgstr "Le comportement du pipeline sera simulé en intégrant les dépendances des tâches %{codeStart}rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd} et %{codeStart}needs%{codeEnd}."
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Le comportement du pipeline sera simulé en intégrant les dépendances des tâches %{codeStart}rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd} et %{codeStart}needs%{codeEnd}. %{linkStart}En savoir plus%{linkEnd}"
msgid "PipelineEditor|Pipeline simulation completed with errors"
-msgstr ""
+msgstr "La simulation de pipeline s'est terminée avec des erreurs"
msgid "PipelineEditor|Simulated a %{codeStart}git push%{codeEnd} event for a default branch. %{codeStart}Rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd}, and %{codeStart}needs%{codeEnd} job dependencies logic have been evaluated. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Évènement %{codeStart}git push%{codeEnd} pour la branche par défaut simulé. Les dépendances logiques %{codeStart}rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd} et %{codeStart}needs%{codeEnd} ont été évaluées. %{linkStart}En savoir plus%{linkEnd} "
msgid "PipelineEditor|Simulation completed successfully"
-msgstr ""
+msgstr "Simulation terminée avec succès"
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
-msgstr ""
+msgstr "La configuration CI/CD est validée en continu. Les erreurs et les avertissements sont affichés du moment que le fichier de configuration CI/CD n'est pas vide."
msgid "PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax."
-msgstr ""
+msgstr "La vue du YAML à fusionner est montrée lorsque le fichier de configuration CI/CD a une syntaxe valide."
msgid "PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax."
-msgstr ""
+msgstr "La visualisation du pipeline est affichée lorsque le fichier de configuration CI/CD a une syntaxe valide."
msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax."
-msgstr ""
+msgstr "Cet onglet sera utilisable lorsque le fichier de configuration CI/CD aura un contenu avec une syntaxe valide."
msgid "PipelineEditor|Validate pipeline"
-msgstr ""
+msgstr "Valider le pipeline"
msgid "PipelineEditor|Validate pipeline under selected conditions"
-msgstr ""
+msgstr "Valider le pipeline sous les conditions sélectionnées"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
-msgstr ""
+msgstr "Valider le pipeline sous les conditions simulées"
msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
-msgstr ""
+msgstr "Validation du pipeline... Cela peut prendre jusqu'à une minute."
msgid "PipelineEditor|Waiting for CI content to load..."
-msgstr ""
+msgstr "En attente du chargement du contenu CI..."
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
-msgstr ""
+msgstr "Personnalisé (%{linkStart}syntaxe Cron%{linkEnd})"
msgid "PipelineSchedules|Activated"
msgstr "Activé"
@@ -28948,9 +29448,21 @@ msgstr "Actif"
msgid "PipelineSchedules|All"
msgstr "Tous"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inactif"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Prochaine exécution"
@@ -28958,64 +29470,76 @@ msgid "PipelineSchedules|None"
msgstr "Aucun"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
+msgstr "Seul le propriétaire d’une planification de pipeline peut y apporter des modifications. Voulez-vous prendre possession de cette planification ?"
+
+msgid "PipelineSchedules|Owner"
msgstr ""
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Indiquez une courte description"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "S’approprier"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Cible"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variables"
msgid "PipelineSchedule|Take ownership to edit"
-msgstr ""
+msgstr "Prendre possession pour modifier"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Discussion"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "Externe"
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "Demande de Tirage Externe"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "Demande de Fusion"
msgid "PipelineSource|On-Demand DAST Scan"
-msgstr ""
+msgstr "Analyse DAST à la demande"
msgid "PipelineSource|On-Demand DAST Validation"
-msgstr ""
+msgstr "Validation DAST à la demande"
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "Pipeline Parent"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "PipelineSource|Push"
-msgstr ""
+msgstr "Poussée"
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "Planification"
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "Déclencheur"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "EDI Web"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr ""
@@ -29024,25 +29548,25 @@ msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
msgstr ""
msgid "PipelineWizardDefaultCommitMessage|Add %{filename}"
-msgstr ""
+msgstr "Ajouter %{filename}"
msgid "PipelineWizardDefaultCommitMessage|Update %{filename}"
-msgstr ""
+msgstr "Mettre à jour %{filename}"
msgid "PipelineWizardInputValidation|At least one entry is required"
-msgstr ""
+msgstr "Au moins une entrée est requise"
msgid "PipelineWizardInputValidation|This field is required"
-msgstr ""
+msgstr "Ce champ est requis"
msgid "PipelineWizardInputValidation|This value is not valid"
-msgstr ""
+msgstr "Cette valeur n'est pas valide"
msgid "PipelineWizardListWidget|add another step"
-msgstr ""
+msgstr "ajouter une autre étape"
msgid "PipelineWizardListWidget|remove step"
-msgstr ""
+msgstr "supprimer l'étape"
msgid "PipelineWizard|Commit"
msgstr ""
@@ -29051,22 +29575,22 @@ msgid "PipelineWizard|Commit Message"
msgstr ""
msgid "PipelineWizard|Commit changes to your file"
-msgstr ""
+msgstr "Valider les modifications sur votre fichier"
msgid "PipelineWizard|Commit file to Branch"
msgstr ""
msgid "PipelineWizard|Commit your new file"
-msgstr ""
+msgstr "Validez votre nouveau fichier"
msgid "PipelineWizard|The file has been committed."
-msgstr ""
+msgstr "Le fichier a été validé."
msgid "PipelineWizard|There was a problem committing the changes."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la validation des modifications."
msgid "PipelineWizard|There was a problem while checking whether your file already exists in the specified branch."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la vérification de l'existence de votre fichier dans la branche spécifiée."
msgid "PipelineWizard|There was an unexpected error trying to set up the template. The error has been logged."
msgstr ""
@@ -29083,8 +29607,14 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr "%{jobs} %{ref_text} en %{duration}"
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr "(mis en file d'attente pendant %{queued_duration})"
+
msgid "Pipelines|1. Set up a runner"
-msgstr ""
+msgstr "1. Configurez un exécuteur"
msgid "Pipelines|2. Configure deployment pipeline"
msgstr ""
@@ -29096,13 +29626,13 @@ msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Are you sure you want to run this pipeline?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir exécuter ce pipeline ?"
msgid "Pipelines|Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "Pipelines|Based on your project, we recommend this template:"
-msgstr ""
+msgstr "Sur la base de votre projet, nous recommandons ce modèle :"
msgid "Pipelines|Build with confidence"
msgstr "Construire en toute confiance"
@@ -29111,49 +29641,49 @@ msgid "Pipelines|Building for iOS?"
msgstr ""
msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
-msgstr ""
+msgstr "En révoquant un déclencheur, vous casserez tous les processus qui l'utilisent. Êtes-vous sûr ?"
msgid "Pipelines|CI lint"
-msgstr ""
+msgstr "CI lint"
msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
-msgstr ""
+msgstr "Pipeline enfant (%{link_start}parent%{link_end})"
msgid "Pipelines|Clear runner caches"
-msgstr ""
+msgstr "Vider les caches des exécuteurs"
msgid "Pipelines|Configuration validation currently not available."
-msgstr ""
+msgstr "La validation de la configuration n'est pas disponible actuellement."
msgid "Pipelines|Configure pipeline"
-msgstr ""
+msgstr "Configurer le pipeline"
msgid "Pipelines|Continuous integration and deployment template to test and deploy your %{name} project."
-msgstr ""
+msgstr "Modèle d'intégration et de déploiement continus pour tester et déployer votre projet %{name}."
msgid "Pipelines|Copy trigger token"
-msgstr ""
+msgstr "Copier le jeton de déclenchement"
msgid "Pipelines|Could not load artifacts."
-msgstr ""
+msgstr "Impossible de charger les artéfacts."
msgid "Pipelines|Could not load merged YAML content"
-msgstr ""
+msgstr "Impossible de charger le contenu du YAML à fusionner"
msgid "Pipelines|Description"
-msgstr ""
+msgstr "Description"
msgid "Pipelines|Don't need a guide? Jump in right away with a template."
-msgstr ""
+msgstr "Pas besoin de guide ? Commencez directement avec un modèle."
msgid "Pipelines|Edit"
-msgstr ""
+msgstr "Modifier"
msgid "Pipelines|Editor"
-msgstr ""
+msgstr "Éditeur"
msgid "Pipelines|Follow these instructions to install GitLab Runner on macOS."
-msgstr ""
+msgstr "Suivez ces instructions pour installer GitLab Runner sur macOS."
msgid "Pipelines|Get familiar with GitLab CI syntax by setting up a simple pipeline running a \"Hello world\" script to see how it runs, explore how CI/CD works."
msgstr ""
@@ -29162,67 +29692,67 @@ msgid "Pipelines|Get started with GitLab CI/CD"
msgstr ""
msgid "Pipelines|GitLab CI/CD can automatically build, test, and deploy your code. Let GitLab take care of time consuming tasks, so you can spend more time creating."
-msgstr ""
+msgstr "GitLab CI/CD peut automatiquement construire, tester et déployer votre code. Laissez GitLab se charger des tâches chronophages afin de pouvoir consacrer davantage de temps à la création."
msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline."
-msgstr ""
+msgstr "GitLab Runner est une application qui fonctionne avec GitLab CI/CD pour exécuter des tâches dans un pipeline."
msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. There are active runners available to run your jobs right now. If you prefer, you can %{settingsLinkStart}configure your runners%{settingsLinkEnd} or %{docsLinkStart}learn more%{docsLinkEnd} about runners."
msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
-msgstr ""
+msgstr "En cas de doute, veuillez demander à un mainteneur du projet de l'examiner pour vous."
msgid "Pipelines|Install GitLab Runner"
msgstr ""
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
-msgstr ""
+msgstr "Il est recommandé que le code soit examiné minutieusement avant d’exécuter ce pipeline avec la ressource CI du projet parent."
msgid "Pipelines|Last Used"
-msgstr ""
+msgstr "Dernière utilisation"
msgid "Pipelines|Learn the basics of pipelines and .yml files"
msgstr ""
msgid "Pipelines|Let's get that runner set up! %{emojiStart}tada%{emojiEnd}"
-msgstr ""
+msgstr "Configurons cet exécuteur ! %{emojiStart}tada%{emojiEnd}"
msgid "Pipelines|Lint"
-msgstr ""
+msgstr "Lint"
msgid "Pipelines|Loading Pipelines"
msgstr "Chargement des pipelines"
msgid "Pipelines|Loading pipelines"
-msgstr ""
+msgstr "Chargement des pipelines"
msgid "Pipelines|Merged YAML is view only"
-msgstr ""
+msgstr "Le YAML à fusionner est en visualisation uniquement"
msgid "Pipelines|More Information"
-msgstr ""
+msgstr "Plus d'informations"
msgid "Pipelines|Need more information to set up your runner? %{linkStart}Check out our documentation%{linkEnd}."
-msgstr ""
+msgstr "Besoin de plus d'informations pour configurer votre exécuteur ? %{linkStart}Consultez notre documentation%{linkEnd}."
msgid "Pipelines|No runners detected"
-msgstr ""
+msgstr "Aucun exécuteur détecté"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
-msgstr ""
+msgstr "Aucun déclencheur n'a encore été créé. Ajoutez-en un en utilisant le formulaire ci-dessus."
msgid "Pipelines|Not building for iOS or not what you're looking for? %{linkStart}See what else%{linkEnd} GitLab CI/CD has to offer."
-msgstr ""
+msgstr "Vous ne construisez pas pour iOS, ou cela ne correspond pas à ce que vous cherchez ? %{linkStart}Découvrez les autres possibilités%{linkEnd} offertes par GitLab CI/CD."
msgid "Pipelines|Owner"
-msgstr ""
+msgstr "Propriétaire"
msgid "Pipelines|Pipeline Editor"
-msgstr ""
+msgstr "Éditeur de Pipeline"
msgid "Pipelines|Pipeline syntax is correct."
-msgstr ""
+msgstr "La syntaxe du pipeline est correcte."
msgid "Pipelines|Project cache successfully reset."
msgstr "Réinitialisation du cache de projet réussie."
@@ -29237,55 +29767,55 @@ msgid "Pipelines|Runners are available to run your jobs now"
msgstr ""
msgid "Pipelines|Set up a runner"
-msgstr ""
+msgstr "Configurer un exécuteur"
msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "Une erreur s’est produite lors du nettoyage du cache des exécuteurs."
msgid "Pipelines|The %{namespace_name} namespace has %{percentage}%% 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 %{namespace_name} dispose de %{percentage}%% ou moins de minutes restantes de Pipeline d'Exécuteur Partagé. Une fois qu’elles seront épuisées, aucune nouvelle tâche ni pipeline de ses projets ne sera lancé."
msgid "Pipelines|The %{namespace_name} namespace has exceeded its pipeline minutes quota. Buy additional pipeline minutes, or no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "L' %{namespace_name} a dépassé son quota de minutes de pipeline. Achetez des minutes de pipeline supplémentaires, sinon aucun nouveau travail ou pipeline dans ses projets ne sera exécuté. Achetez des minutes de pipeline supplémentaires, sinon aucune nouvelle tâche ni pipeline de ses projets ne sera exécuté."
msgid "Pipelines|The CI configuration was not loaded, please try again."
-msgstr ""
+msgstr "La configuration CI n'a pas été chargée, veuillez réessayer."
msgid "Pipelines|The GitLab CI configuration could not be updated."
-msgstr ""
+msgstr "La configuration de GitLab CI n'a pas pu être mise à jour."
msgid "Pipelines|There are currently no finished pipelines."
-msgstr ""
+msgstr "Il n’y a actuellement aucun pipeline terminé."
msgid "Pipelines|There are currently no pipelines."
msgstr "Il n’y a actuellement aucun pipeline."
msgid "Pipelines|There was a problem with loading the pipeline data."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des données du pipeline."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Une erreur est survenue lors de la récupération des pipelines. Réessayez dans quelques instants ou contactez votre équipe d’assistance."
msgid "Pipelines|This GitLab CI configuration is invalid."
-msgstr ""
+msgstr "Cette configuration de GitLab CI n’est pas valide."
msgid "Pipelines|This GitLab CI configuration is invalid:"
-msgstr ""
+msgstr "Cette configuration de GitLab CI n’est pas valide :"
msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
-msgstr ""
+msgstr "Cette configuration de GitLab CI n’est pas valide : %{reason}."
msgid "Pipelines|This GitLab CI configuration is valid."
-msgstr ""
+msgstr "Cette configuration de GitLab CI est valide."
msgid "Pipelines|This is a child pipeline within the parent pipeline"
msgstr ""
msgid "Pipelines|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
-msgstr ""
+msgstr "Ce pipeline s'est exécuté sur le contenu de cette demande de fusion combiné avec le contenu de toutes les autres demandes de fusion qui étaient en attente de fusion vers la branche cible."
msgid "Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+msgstr "Ce pipeline s'est exécuté sur le contenu de la branche source de cette demande de fusion, pas sur celui de la branche cible."
msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
msgstr ""
@@ -29294,163 +29824,163 @@ msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Ce projet n’est actuellement pas configuré pour exécuter des pipelines."
msgid "Pipelines|Token"
-msgstr ""
+msgstr "Jeton"
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
msgid "Pipelines|Try test template"
-msgstr ""
+msgstr "Essayer le modèle de test"
msgid "Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works."
-msgstr ""
+msgstr "Utiliser un fichier modèle d'exemple %{codeStart}.gitlab-ci.yml%{codeEnd} pour découvrir le fonctionnement de CI/CD."
msgid "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD."
-msgstr ""
+msgstr "Utiliser un modèle basé sur le langage ou sur le framework de votre projet pour débuter avec GitLab CI/CD."
msgid "Pipelines|Use template"
-msgstr ""
+msgstr "Utiliser un modèle"
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "Valider"
msgid "Pipelines|Validating GitLab CI configuration…"
-msgstr ""
+msgstr "Validation de la configuration de GitLab CI en cours…"
msgid "Pipelines|View merged YAML"
-msgstr ""
+msgstr "Afficher le YAML à fusionner"
msgid "Pipelines|Visualize"
-msgstr ""
+msgstr "Visualiser"
msgid "Pipelines|We'll guide you through a simple pipeline set-up."
-msgstr ""
+msgstr "Nous allons vous guider à travers la configuration d'un pipeline simple."
msgid "Pipelines|We'll walk you through how to deploy to iOS in two easy steps."
msgstr ""
msgid "Pipelines|You have runners available to run your job now. No need to do anything else."
-msgstr ""
+msgstr "Vous avez des exécuteurs disponibles pour lancer votre tâche maintenant. Pas besoin de faire quoi que ce soit d'autre."
msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
-msgstr ""
+msgstr "Vos modifications ont été validées avec succès. Redirection vers la page de nouvelle demande de fusion."
msgid "Pipelines|error"
-msgstr ""
+msgstr "erreur"
msgid "Pipelines|invalid"
-msgstr ""
+msgstr "invalide"
msgid "Pipelines|latest"
-msgstr ""
+msgstr "dernier"
msgid "Pipelines|merge request"
-msgstr ""
+msgstr "demande de fusion"
msgid "Pipelines|merge train"
-msgstr ""
+msgstr "train de fusion"
msgid "Pipelines|stuck"
msgstr ""
msgid "Pipelines|yaml invalid"
-msgstr ""
+msgstr "yaml non valide"
msgid "Pipeline|Actions"
-msgstr ""
+msgstr "Actions"
msgid "Pipeline|Branch name"
-msgstr ""
+msgstr "Nom de la branche"
msgid "Pipeline|Branches or tags could not be loaded."
-msgstr ""
+msgstr "Les branches ou les étiquettes n’ont pas pu être chargées."
msgid "Pipeline|Canceled"
-msgstr ""
+msgstr "Annulé"
msgid "Pipeline|Checking pipeline status"
msgstr ""
msgid "Pipeline|Checking pipeline status."
-msgstr ""
+msgstr "Vérification de l'état du pipeline."
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
-msgstr ""
+msgstr "Impossible de récupérer l'état du pipeline. Pour les étapes de dépannage, lire la %{linkStart}documentation%{linkEnd}."
msgid "Pipeline|Created"
-msgstr ""
+msgstr "Créé"
msgid "Pipeline|Creating pipeline."
-msgstr ""
+msgstr "Création du pipeline."
msgid "Pipeline|Date"
-msgstr ""
+msgstr "Date"
msgid "Pipeline|Failed"
-msgstr ""
+msgstr "Échoué"
msgid "Pipeline|In progress"
-msgstr ""
+msgstr "En cours"
msgid "Pipeline|Manual"
-msgstr ""
+msgstr "Manuel"
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "Pipeline de demande de fusion"
msgid "Pipeline|Merge train pipeline"
msgstr ""
msgid "Pipeline|Merge train pipeline jobs can not be retried"
-msgstr ""
+msgstr "Les tâches du pipeline de train de fusion ne peuvent pas être retentées"
msgid "Pipeline|Merged result pipeline"
msgstr ""
msgid "Pipeline|Passed"
-msgstr ""
+msgstr "Passé"
msgid "Pipeline|Pending"
-msgstr ""
+msgstr "En attente"
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
-msgstr ""
+msgstr "Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} pour %{commitStart}%{commitEnd}"
msgid "Pipeline|Pipeline cannot be run."
-msgstr ""
+msgstr "Le pipeline ne peut pas être exécuté."
msgid "Pipeline|Pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
-msgstr ""
+msgstr "La recherche de texte brut n’est pas prise en charge actuellement. Veuillez utiliser les jetons de recherche disponibles."
msgid "Pipeline|Run for branch name or tag"
-msgstr ""
+msgstr "Exécuter pour un nom de branche ou une étiquette"
msgid "Pipeline|Run merge request pipeline"
-msgstr ""
+msgstr "Exécuter le pipeline de la demande de fusion"
msgid "Pipeline|Run pipeline"
-msgstr ""
+msgstr "Exécuter le pipeline"
msgid "Pipeline|Running"
-msgstr ""
+msgstr "En cours"
msgid "Pipeline|Skipped"
-msgstr ""
+msgstr "Ignoré"
msgid "Pipeline|Source"
-msgstr ""
+msgstr "Source"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "Politique de Sécurité"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
-msgstr ""
+msgstr "Spécifiez les valeurs des variables à utiliser lors de cette exécution. Celles spécifiées dans les %{linkStart}paramètres CI/CD%{linkEnd} seront utilisées par défaut."
msgid "Pipeline|Stages"
msgstr "Étapes"
@@ -29465,31 +29995,31 @@ msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "Arrêter le pipeline numéro %{pipelineId} ?"
msgid "Pipeline|Tag name"
-msgstr ""
+msgstr "Nom de l'étiquette"
msgid "Pipeline|Test coverage"
msgstr ""
msgid "Pipeline|This change will decrease the overall test coverage if merged."
-msgstr ""
+msgstr "Cette modification diminuera la couverture de test globale si elle est fusionnée."
msgid "Pipeline|This change will increase the overall test coverage if merged."
-msgstr ""
+msgstr "Cette modification augmentera la couverture de test globale si elle est fusionnée."
msgid "Pipeline|This change will not change the overall test coverage if merged."
-msgstr ""
+msgstr "Cette modification ne modifiera pas la couverture de test globale si elle est fusionnée."
msgid "Pipeline|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
-msgstr ""
+msgstr "Ce pipeline s'est exécuté sur le contenu de cette demande de fusion combiné avec le contenu de toutes les autres demandes de fusion qui étaient en attente de fusion vers la branche cible."
msgid "Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+msgstr "Ce pipeline s'est exécuté sur le contenu de la branche source de cette demande de fusion, pas sur celui de la branche cible."
msgid "Pipeline|To run a merge request pipeline, the jobs in the CI/CD configuration file %{linkStart}must be configured%{linkEnd} to run in merge request pipelines."
-msgstr ""
+msgstr "Pour exécuter un pipeline de demande de fusion, les tâches dans le fichier de configuration CI/CD %{linkStart}doivent être configurées%{linkEnd} pour s'exécuter dans les pipelines de demande de fusion."
msgid "Pipeline|Trigger author"
-msgstr ""
+msgstr "Auteur du déclencheur"
msgid "Pipeline|Triggerer"
msgstr ""
@@ -29498,25 +30028,25 @@ msgid "Pipeline|Variables"
msgstr "Variables"
msgid "Pipeline|View commit"
-msgstr ""
+msgstr "Afficher le commit"
msgid "Pipeline|View pipeline"
msgstr ""
msgid "Pipeline|We are currently unable to fetch pipeline data"
-msgstr ""
+msgstr "Il n'est pas possible actuellement de récupérer les données de pipeline"
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "Vous êtes sur le point d’arrêter le pipeline n°%{pipelineId}."
msgid "Pipeline|for"
msgstr ""
msgid "Pipeline|merge request"
-msgstr ""
+msgstr "demande de fusion"
msgid "Pipeline|merge train"
-msgstr ""
+msgstr "train de fusion"
msgid "Pipeline|on"
msgstr ""
@@ -29528,25 +30058,25 @@ msgid "Pipeline|with stages"
msgstr "avec les étapes"
msgid "PivotalTrackerService|Add commit messages as comments to Pivotal Tracker stories."
-msgstr ""
+msgstr "Ajouter les messages de validation en tant que commentaires sur les histoires de Pivotal Tracker."
msgid "PivotalTrackerService|Comma-separated list of branches to automatically inspect. Leave blank to include all branches."
-msgstr ""
+msgstr "Liste des branches, séparées par des virgules, qui seront inspectées automatiquement. Laisser vide pour inclure toutes les branches."
msgid "PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user."
-msgstr ""
+msgstr "Jeton d'API Pivotal Tracker. L'utilisateur doit posséder un accès à l'histoire. Tous les commentaires sont attribués à cet utilisateur."
msgid "Plain diff"
msgstr "Diff brut"
msgid "Plain-text response to send to clients that hit a rate limit"
-msgstr ""
+msgstr "Réponse en texte brut à envoyer aux clients qui atteignent une limitation de fréquence"
msgid "Plan"
-msgstr ""
+msgstr "Forfait"
msgid "Plan:"
-msgstr ""
+msgstr "Forfait :"
msgid "Planning hierarchy"
msgstr ""
@@ -29555,10 +30085,10 @@ msgid "PlantUML"
msgstr "PlantUML"
msgid "PlantUML URL"
-msgstr ""
+msgstr "URL de PlantUML"
msgid "PlantUML diagram"
-msgstr ""
+msgstr "Diagramme PlantUML"
msgid "Play"
msgstr "Lancer"
@@ -29573,7 +30103,7 @@ msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStar
msgstr ""
msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
-msgstr ""
+msgstr "Veuillez vous %{registerLinkStart}inscrire%{registerLinkEnd} ou vous %{signInLinkStart}connecter%{signInLinkEnd} pour démarrer un nouvelle discussion."
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
msgstr ""
@@ -29594,37 +30124,37 @@ msgid "Please check the configuration file to ensure that it is available and th
msgstr ""
msgid "Please check your email %{email} to confirm your account"
-msgstr ""
+msgstr "Veuillez vérifier votre courriel %{email} pour valider votre compte"
msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
msgstr ""
msgid "Please click the link in the confirmation email before continuing. It was sent to %{html_tag_strong_start}%{email}%{html_tag_strong_end}."
-msgstr ""
+msgstr "Veuillez cliquer sur le lien présent dans le courriel de confirmation avant de continuer. Il a été envoyé à %{html_tag_strong_start}%{email}%{html_tag_strong_end}."
msgid "Please complete your profile with email address"
msgstr ""
msgid "Please confirm your email address"
-msgstr ""
+msgstr "Veuillez confirmer votre adresse de courriel"
msgid "Please contact an admin to register runners."
-msgstr ""
+msgstr "Veuillez contacter un administrateur pour enregistrer des exécuteurs."
msgid "Please contact your GitLab administrator if you think this is an error."
-msgstr ""
+msgstr "Veuillez contacter votre administrateur GitLab si vous pensez qu’il s’agit d’une erreur."
msgid "Please contact your administrator with any questions."
-msgstr ""
+msgstr "Veuillez contacter votre administrateur pour toute question."
msgid "Please contact your administrator."
-msgstr ""
+msgstr "Veuillez contacter votre administrateur."
msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
-msgstr ""
+msgstr "Veuillez les convertir %{linkStart}vers Git%{linkEnd} puis retourner sur le %{linkToImportFlow}."
msgid "Please copy, download, or print your recovery codes before proceeding."
-msgstr ""
+msgstr "Veuillez copier, télécharger ou imprimer vos codes de récupération avant de poursuivre."
msgid "Please create a password for your new account."
msgstr ""
@@ -29633,10 +30163,10 @@ msgid "Please create a username with only alphanumeric characters."
msgstr ""
msgid "Please create an index before enabling indexing"
-msgstr ""
+msgstr "Veuillez créer un index avant d'activer l'indexation"
msgid "Please delete your current license if you want to downgrade to the free plan."
-msgstr ""
+msgstr "Veuillez supprimer votre licence actuelle si vous souhaitez revenir au forfait gratuit."
msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
@@ -29648,37 +30178,37 @@ msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
msgid "Please enter a valid URL format, ex: http://www.example.com/home"
-msgstr ""
+msgstr "Veuillez entrer un format d'URL valide, ex. : http://www.exemple.com/accueil"
msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
-msgstr ""
+msgstr "Veuillez entrer une valeur de couleur hexadécimale valide (#RRVVBB ou #RVB)"
msgid "Please enter a valid number"
msgstr ""
msgid "Please enter a valid time interval"
-msgstr ""
+msgstr "Veuillez entrer un intervalle de temps valide"
msgid "Please enter your current password."
-msgstr ""
+msgstr "Veuillez entrer votre mot de passe actuel."
msgid "Please fill in a descriptive name for your group."
msgstr "Veuillez saisir un nom descriptif pour votre groupe."
msgid "Please fill in a name for your topic."
-msgstr ""
+msgstr "Veuillez saisir un nom pour votre sujet."
msgid "Please fill in a title for your topic."
-msgstr ""
+msgstr "Veuillez saisir un titre pour votre sujet."
msgid "Please fill out this field."
msgstr ""
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
-msgstr ""
+msgstr "Veuillez suivre les %{link_start}instructions de dépannage de Let's Encrypt%{link_end} pour obtenir à nouveau votre certificat Let's Encrypt."
msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
-msgstr ""
+msgstr "Veuillez suivre les instructions de dépannage de Let's Encrypt pour obtenir de nouveau votre certificat Let's Encrypt : %{docs_url}."
msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
@@ -29690,10 +30220,10 @@ msgid "Please provide a name"
msgstr ""
msgid "Please provide a name."
-msgstr ""
+msgstr "Veuillez fournir un nom."
msgid "Please provide a valid URL."
-msgstr ""
+msgstr "Veuillez fournir une URL valide."
msgid "Please provide a valid email address."
msgstr ""
@@ -29702,10 +30232,10 @@ msgid "Please provide attributes to update"
msgstr ""
msgid "Please reach out if you have any questions and we'll be happy to assist."
-msgstr ""
+msgstr "N'hésitez pas à nous contacter si vous avez des questions et nous serons heureux de vous accompagner."
msgid "Please review the %{linkStart}contribution guidelines%{linkEnd} for this project."
-msgstr ""
+msgstr "Veuillez consulter les %{linkStart}directives de contribution%{linkEnd} de ce projet."
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 ""
@@ -29717,7 +30247,7 @@ msgid "Please select"
msgstr ""
msgid "Please select a Jira project"
-msgstr ""
+msgstr "Veuillez sélectionner un projet Jira"
msgid "Please select a country"
msgstr ""
@@ -29726,13 +30256,13 @@ msgid "Please select a file"
msgstr ""
msgid "Please select a group"
-msgstr ""
+msgstr "Veuillez sélectionner un groupe"
msgid "Please select a valid target branch"
-msgstr ""
+msgstr "Veuillez sélectionner une branche cible valide"
msgid "Please select a valid target branch."
-msgstr ""
+msgstr "Veuillez sélectionner une branche cible valide."
msgid "Please select and add a member"
msgstr ""
@@ -29741,7 +30271,7 @@ msgid "Please select at least one filter to see results"
msgstr "Veuillez sélectionner au moins un filtre pour voir les résultats"
msgid "Please select what should be included in each exported requirement."
-msgstr ""
+msgstr "Veuillez sélectionner ce qui doit être inclus dans chaque exigence exportée."
msgid "Please select..."
msgstr ""
@@ -29750,13 +30280,13 @@ msgid "Please set a new password before proceeding."
msgstr ""
msgid "Please solve the captcha"
-msgstr ""
+msgstr "Veuillez résoudre le captcha"
msgid "Please try again"
msgstr "Veuillez réessayer"
msgid "Please try and refresh the page. If the problem persists please contact support."
-msgstr ""
+msgstr "Veuillez essayer et actualiser la page. Si le problème persiste, veuillez contacter le support."
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr "Veuillez patienter pendant la connexion à votre dépôt. Actualisez à
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Veuillez patienter pendant l’importation de votre dépôt. Actualisez à votre guise."
+msgid "Please wait while we prepare for verification."
+msgstr "Veuillez patienter pendant que nous nous préparons pour la vérification."
+
msgid "Pods in use"
msgstr ""
@@ -29780,19 +30316,19 @@ msgid "Point to any links you like: documentation, built binaries, or other rela
msgstr ""
msgid "Policies"
-msgstr ""
+msgstr "Politiques"
msgid "Policy '%{escalation_policy_name}' does not exist."
-msgstr ""
+msgstr "La politique « %{escalation_policy_name} » n'existe pas."
msgid "Policy management project does not have any policies in %{policy_path}"
-msgstr ""
+msgstr "Le projet de gestion des stratégies ne contient aucune stratégie dans %{policy_path}"
msgid "Policy project doesn't exist"
msgstr ""
msgid "PolicyRuleMultiSelect|%{firstLabel} +%{numberOfAdditionalLabels} more"
-msgstr ""
+msgstr "%{firstLabel} +%{numberOfAdditionalLabels} de plus"
msgid "PolicyRuleMultiSelect|All %{itemTypeName}"
msgstr ""
@@ -29801,31 +30337,31 @@ msgid "PolicyRuleMultiSelect|Select %{itemTypeName}"
msgstr ""
msgid "PolicyRuleMultiSelect|Select all"
-msgstr ""
+msgstr "Tout sélectionner"
msgid "Polling interval multiplier"
-msgstr ""
+msgstr "Multiplicateur de la fréquence de scrutation"
msgid "Popularity"
msgstr "Popularité"
msgid "Port"
-msgstr ""
+msgstr "Port"
msgid "Postman collection"
-msgstr ""
+msgstr "Collection Postman"
msgid "Postman collection file URL"
-msgstr ""
+msgstr "URL du fichier de collection Postman"
msgid "Postman collection file path or URL"
-msgstr ""
+msgstr "URL ou chemin du fichier de la collection Postman"
msgid "Potentially unwanted character detected: Unicode BiDi Control"
-msgstr ""
+msgstr "Caractère potentiellement indésirable détecté : Contrôle Unicode BiDi"
msgid "Pre-defined push rules"
-msgstr ""
+msgstr "Règles de poussée prédéfinies"
msgid "Preferences"
msgstr "Préférences"
@@ -29833,32 +30369,35 @@ msgstr "Préférences"
msgid "Preferences saved."
msgstr "Préférences enregistrées."
-msgid "Preferences|Behavior"
+msgid "Preferences|Automatically add new list items"
msgstr ""
+msgid "Preferences|Behavior"
+msgstr "Comportement"
+
msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
msgstr ""
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "Choisissez le contenu par défaut que vous souhaitez voir sur votre tableau de bord."
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
msgid "Preferences|Color for added lines"
-msgstr ""
+msgstr "Couleur des lignes ajoutées"
msgid "Preferences|Color for removed lines"
-msgstr ""
+msgstr "Couleur des lignes supprimées"
msgid "Preferences|Color theme"
msgstr "Couleurs du thème"
msgid "Preferences|Configure how dates and times display for you."
-msgstr ""
+msgstr "Configurer comment vous sont présentées les dates et les heures."
msgid "Preferences|Customize integrations with third party services."
-msgstr ""
+msgstr "Personnalisez les intégrations avec des services tiers."
msgid "Preferences|Customize the color of GitLab."
msgstr "Personnaliser les couleurs de GitLab."
@@ -29867,7 +30406,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr "Personnaliser les couleurs de l'affichage des diffs."
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "Tableau de bord"
msgid "Preferences|Diff colors"
msgstr "Couleurs des diff"
@@ -29876,31 +30415,31 @@ msgid "Preferences|Display time in 24-hour format"
msgstr "Afficher l'heure au format 24 heures"
msgid "Preferences|Enable Gitpod integration"
-msgstr ""
+msgstr "Activer l’intégration de Gitpod"
msgid "Preferences|Enable integrated code intelligence on code views"
-msgstr ""
+msgstr "Activer l'intelligence de code intégrée sur les vues de code"
msgid "Preferences|Failed to save preferences."
-msgstr ""
+msgstr "Échec de l'enregistrement des préférences."
msgid "Preferences|For example: 30 minutes ago."
msgstr "Par exemple : il y a 30 minutes."
msgid "Preferences|Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
-msgstr ""
+msgstr "Afficher un seul fichier à la fois au lieu de tous les fichiers modifiés. Pour basculer entre les fichiers, utilisez le navigateur de fichiers."
msgid "Preferences|Integrations"
-msgstr ""
+msgstr "Intégrations"
msgid "Preferences|Layout width"
-msgstr ""
+msgstr "Largeur de la mise en page"
msgid "Preferences|Must be a number between %{min} and %{max}"
-msgstr ""
+msgstr "Doit être un nombre compris entre %{min} et %{max}"
msgid "Preferences|Preview"
msgstr "Aperçu"
@@ -29909,16 +30448,16 @@ msgid "Preferences|Project overview content"
msgstr ""
msgid "Preferences|Render whitespace characters in the Web IDE"
-msgstr ""
+msgstr "Afficher les caractères non imprimables dans l'EDI Web"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
-msgstr ""
+msgstr "Afficher un fichier à la fois sur l'onglet Modifications de la demande de fusion"
msgid "Preferences|Show whitespace changes in diffs"
-msgstr ""
+msgstr "Afficher les modifications des caractères non imprimables dans les diffs"
msgid "Preferences|Sourcegraph"
-msgstr ""
+msgstr "Sourcegraph"
msgid "Preferences|Surround text selection when typing quotes or brackets"
msgstr ""
@@ -29927,10 +30466,10 @@ msgid "Preferences|Syntax highlighting theme"
msgstr "Thème de coloration syntaxique"
msgid "Preferences|Tab width"
-msgstr ""
+msgstr "Largeur de tabulation"
msgid "Preferences|This feature is experimental and translations are not yet complete."
-msgstr ""
+msgstr "Cette fonctionnalité est expérimentale et les traductions ne sont pas encore terminées."
msgid "Preferences|This setting allows you to customize the appearance of the syntax."
msgstr "Ce paramètre vous permet de personnaliser l'apparence de la syntaxe."
@@ -29944,38 +30483,41 @@ msgstr "Préférences de l’heure"
msgid "Preferences|Use relative times"
msgstr ""
-msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
msgstr ""
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr "Lorsque vous saisissez du texte dans un champ de commentaire ou de description, la sélection est encadrée par le caractère correspondant après avoir tapé l'un des caractères suivants : %{supported_characters}."
+
msgid "Preparing the report for the scan."
-msgstr ""
+msgstr "Préparation du rapport pour l'analyse."
msgid "Prev"
msgstr ""
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "Empêcher l'arrêt automatique"
msgid "Prevent editing approval rules in projects and merge requests"
-msgstr ""
+msgstr "Empêcher la modification des règles d'approbation dans les projets et les demandes de fusion"
msgid "Prevent environment from auto-stopping"
-msgstr ""
+msgstr "Empêcher l'environnement de s'arrêter automatiquement"
msgid "Prevent project forking outside current group"
-msgstr ""
+msgstr "Empêcher le fork de projet en dehors du groupe actuel"
msgid "Prevent users from changing their profile name"
-msgstr ""
+msgstr "Empêcher les utilisateurs de changer leur nom de profil"
msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
-msgstr ""
+msgstr "Empêcher les utilisateurs d'effectuer des opérations en écriture quand GitLab est en cours de maintenance."
msgid "Preview"
msgstr "Aperçu"
msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
-msgstr ""
+msgstr "Prévisualisez les projets JavaScript dans l'EDI Web avec CodeSandbox Live Preview. %{link_start}En savoir plus.%{link_end} "
msgid "Preview Markdown"
msgstr ""
@@ -29984,7 +30526,7 @@ msgid "Preview changes"
msgstr ""
msgid "Preview diagram"
-msgstr ""
+msgstr "Aperçu du diagramme"
msgid "Preview payload"
msgstr "Aperçu de la charge utile"
@@ -29993,22 +30535,22 @@ msgid "Previous Artifacts"
msgstr ""
msgid "Previous commit"
-msgstr ""
+msgstr "Commit précédent"
msgid "Previous design"
-msgstr ""
+msgstr "Design précédent"
msgid "Previous file in diff"
-msgstr ""
+msgstr "Fichier précédent du diff"
msgid "Previous unresolved discussion"
-msgstr ""
+msgstr "Discussion précédente non résolue"
msgid "Primary Action"
-msgstr ""
+msgstr "Action principale"
msgid "Print codes"
-msgstr ""
+msgstr "Imprimer les codes"
msgid "Prioritize"
msgstr "Prioriser"
@@ -30032,7 +30574,7 @@ msgid "Private - Guest users are not allowed to view detailed release informatio
msgstr "Privé - Les utilisateurs invités ne sont pas autorisés à voir les informations de version détaillées telles que la version ou le code source."
msgid "Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
-msgstr ""
+msgstr "Privé - L'accès au projet doit être explicitement accordé à chaque utilisateur. Si ce projet fait partie d'un groupe, l'accès sera accordé aux membres du groupe."
msgid "Private - The group and its projects can only be viewed by members."
msgstr "Privé — le groupe ainsi que ses projets ne sont accessibles qu’à ses membres."
@@ -30050,19 +30592,19 @@ msgid "Private projects can be created in your personal namespace with:"
msgstr "Des projets privés peuvent être créés dans votre espace de noms personnel avec :"
msgid "Problem with %{name} command: %{message}."
-msgstr ""
+msgstr "Problème avec la commande %{name} : %{message}."
msgid "Proceed"
msgstr ""
msgid "Product Analytics"
-msgstr ""
+msgstr "Données analytiques de produit"
msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
-msgstr ""
+msgstr "Il n’y a pas de données pour ce type de graphique actuellement. Veuillez consulter l’onglet Configuration si vous n’avez pas déjà configuré l’outil des données analytiques de produit."
msgid "Productivity"
-msgstr ""
+msgstr "Productivité"
msgid "Productivity Analytics"
msgstr ""
@@ -30074,7 +30616,7 @@ msgid "ProductivityAanalytics|Merge requests"
msgstr ""
msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
-msgstr ""
+msgstr "est plus tôt que la date minimale autorisée"
msgid "ProductivityAnalytics|Ascending"
msgstr ""
@@ -30110,7 +30652,7 @@ msgid "ProductivityAnalytics|Trendline"
msgstr ""
msgid "ProductivityAnalytics|is earlier than the given merged at after date"
-msgstr ""
+msgstr "est antérieur à la date d'après la fusion spécifiée"
msgid "Profile"
msgstr "Profil"
@@ -30125,10 +30667,10 @@ msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
-msgstr ""
+msgstr "Page du profil :"
msgid "Profile parameter missing"
-msgstr ""
+msgstr "Paramètre de profil manquant"
msgid "ProfileSession|on"
msgstr ""
@@ -30146,7 +30688,7 @@ msgid "Profiles|@username"
msgstr ""
msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
-msgstr ""
+msgstr "Le compte n'a pas pu être supprimé. GitLab n'a pas réussi à vérifier votre identité."
msgid "Profiles|Account scheduled for removal."
msgstr "Compte programmé pour suppression."
@@ -30157,14 +30699,8 @@ msgstr ""
msgid "Profiles|Add key"
msgstr "Ajouter une clef"
-msgid "Profiles|Add status emoji"
-msgstr "Ajouter un émoji de statut"
-
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 "Une erreur s'est produite lors de la mise à jour de votre nom d'utilisateur, veuillez réessayer."
msgid "Profiles|Avatar cropper"
msgstr "Rogneur d’avatar"
@@ -30173,14 +30709,11 @@ msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
msgid "Profiles|Begins with %{ssh_key_algorithms}."
-msgstr ""
+msgstr "Commence par %{ssh_key_algorithms}."
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr "Changer le nom d’utilisateur·rice"
@@ -30191,26 +30724,26 @@ msgid "Profiles|Choose file..."
msgstr "Choisir un fichier…"
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr ""
+msgstr "Choisir d'afficher les contributions des projets privés sur votre profil public mais sans les informations relatives aux projet, dépôt ni organisation."
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr "Effacer le statut"
-
msgid "Profiles|Commit email"
msgstr ""
msgid "Profiles|Connect %{provider}"
-msgstr ""
+msgstr "Connecter %{provider}"
msgid "Profiles|Connect a service for sign-in."
-msgstr ""
+msgstr "Sélectionner un service avec lequel vous connecter."
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr "Crée %{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "Chemin d’accès actuel : %{path}"
@@ -30230,40 +30763,40 @@ msgid "Profiles|Disconnect"
msgstr ""
msgid "Profiles|Disconnect %{provider}"
-msgstr ""
+msgstr "Déconnecter %{provider}"
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 profile."
-msgstr ""
+msgstr "Ne pas afficher les informations personnelles liées à l’activité sur votre profil."
msgid "Profiles|Edit Profile"
msgstr "Modifier le profil"
msgid "Profiles|Ensure you have two-factor authentication recovery codes stored in a safe place."
-msgstr ""
+msgstr "Assurez-vous que les codes de récupération d'authentification à deux facteurs sont stockés dans un endroit sûr."
msgid "Profiles|Enter how your name is pronounced to help people address you correctly."
-msgstr ""
+msgstr "Indiquez la façon dont votre nom se prononce pour aider les gens à s'adresser correctement à vous."
msgid "Profiles|Enter your name, so people you know can recognize you."
-msgstr ""
+msgstr "Entrez votre nom afin que les personnes que vous connaissez puissent vous reconnaître."
msgid "Profiles|Enter your password to confirm the email change"
-msgstr ""
+msgstr "Entrez votre mot de passe pour confirmer la modification de l'adresse électronique"
msgid "Profiles|Enter your pronouns to let people know how to refer to you."
-msgstr ""
+msgstr "Entrez les pronoms qui vous correspondent pour que l'on sache comment faire référence à vous."
msgid "Profiles|Example: MacBook key"
msgstr ""
msgid "Profiles|Expiration date"
-msgstr ""
+msgstr "Date d'expiration"
msgid "Profiles|Expired:"
-msgstr ""
+msgstr "Expiré :"
msgid "Profiles|Expires:"
msgstr ""
@@ -30275,10 +30808,10 @@ msgid "Profiles|Full name"
msgstr ""
msgid "Profiles|GitLab is unable to verify your identity automatically. For security purposes, you must set a password by %{openingTag}resetting your password%{closingTag} to delete your account."
-msgstr ""
+msgstr "GitLab ne peut pas vérifier votre identité automatiquement. Pour des raisons de sécurité, vous devez définir un mot de passe en %{openingTag}réinitialisant votre mot de passe%{closingTag} pour supprimer votre compte."
msgid "Profiles|If after setting a password, the option to delete your account is still not available, please %{link_start}submit a request%{link_end} to begin the account deletion process."
-msgstr ""
+msgstr "Si, après avoir défini un mot de passe, l'option pour supprimer votre compte n'est toujours pas disponible, veuillez %{link_start}soumettre une requête%{link_end} pour commencer le processus de suppression."
msgid "Profiles|Include private contributions on my profile"
msgstr ""
@@ -30287,7 +30820,7 @@ msgid "Profiles|Incoming email token was successfully reset"
msgstr ""
msgid "Profiles|Increase your account's security by enabling two-factor authentication (2FA)."
-msgstr ""
+msgstr "Augmenter la sécurité de votre compte en activant l'authentification à deux facteurs (A2F)."
msgid "Profiles|Invalid password"
msgstr "Mot de passe incorrect"
@@ -30296,13 +30829,13 @@ msgid "Profiles|Invalid username"
msgstr "Nom d’utilisateur incorrect"
msgid "Profiles|Job title"
-msgstr ""
+msgstr "Intitulé de poste"
msgid "Profiles|Key"
msgstr ""
msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
-msgstr ""
+msgstr "La clé devient invalide à cette date. La durée de vie maximale des clés SSH est de %{max_ssh_key_lifetime} jours"
msgid "Profiles|Key titles are publicly visible."
msgstr ""
@@ -30323,16 +30856,16 @@ msgid "Profiles|Main settings"
msgstr "Paramètres principaux"
msgid "Profiles|Manage two-factor authentication"
-msgstr ""
+msgstr "Gérer l'authentification à deux facteurs"
msgid "Profiles|No file chosen."
-msgstr ""
+msgstr "Aucun fichier choisi."
msgid "Profiles|Notification email"
msgstr ""
msgid "Profiles|Optional but recommended. If set, key becomes invalid on the specified date."
-msgstr ""
+msgstr "Facultatif mais recommandé. Si définie, la clé devient invalide à la date spécifiée."
msgid "Profiles|Organization"
msgstr ""
@@ -30353,10 +30886,10 @@ msgid "Profiles|Profile was successfully updated"
msgstr "Profil mis à jour avec succès"
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "Pronoms"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "Prononciation"
msgid "Profiles|Public avatar"
msgstr "Avatar public"
@@ -30365,22 +30898,22 @@ msgid "Profiles|Public email"
msgstr ""
msgid "Profiles|Publicly visible private SSH keys can compromise your system."
-msgstr ""
+msgstr "Les clés SSH privées visibles publiquement peuvent compromettre votre système."
msgid "Profiles|Remove avatar"
msgstr "Supprimer l’avatar"
msgid "Profiles|Select a service to sign in with."
-msgstr ""
+msgstr "Sélectionnez un service avec lequel vous connecter."
msgid "Profiles|Service sign-in"
-msgstr ""
+msgstr "Se connecter au service"
msgid "Profiles|Set new profile picture"
msgstr "Définir une nouvelle photo de profil"
msgid "Profiles|Set your local time zone."
-msgstr ""
+msgstr "Définissez votre fuseau horaire local."
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "Certaines options ne sont pas disponibles pour les comptes LDAP"
@@ -30389,25 +30922,25 @@ msgid "Profiles|Static object token was successfully reset"
msgstr ""
msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr ""
+msgstr "Parlez-nous de vous en moins de 250 caractères."
msgid "Profiles|The ability to update your name has been disabled by your administrator."
-msgstr ""
+msgstr "La possibilité de mettre à jour votre nom a été désactivée par votre administrateur."
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "La taille de fichier maximale autorisée est de 200 Kio."
msgid "Profiles|This email will be displayed on your public profile."
-msgstr ""
+msgstr "Cette adresse de messagerie sera affichée sur votre profil public."
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more.%{commit_email_link_end}"
-msgstr ""
+msgstr "Cette adresse de courriel sera utilisée pour les opérations Web telles que les modifications et les fusions. %{commit_email_link_start}En savoir plus.%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Cet émoji et ce message apparaîtront sur votre profil et partout dans l’interface."
msgid "Profiles|This information will appear on your profile."
-msgstr ""
+msgstr "Cette information apparaîtra sur votre profil."
msgid "Profiles|Time settings"
msgstr ""
@@ -30416,7 +30949,7 @@ msgid "Profiles|Title"
msgstr "Titre"
msgid "Profiles|Two-factor authentication"
-msgstr ""
+msgstr "Authentification à Deux Facteurs"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
@@ -30446,13 +30979,10 @@ msgid "Profiles|Using emojis in names seems fun, but please try to set a status
msgstr ""
msgid "Profiles|Website url"
-msgstr ""
-
-msgid "Profiles|What's your status?"
-msgstr "Quel est votre statut ?"
+msgstr "URL du site Web"
msgid "Profiles|Who you represent or work for."
-msgstr ""
+msgstr "Qui vous représentez ou pour qui vous travaillez."
msgid "Profiles|You can change your avatar here"
msgstr "Vous pouvez changer votre avatar ici"
@@ -30470,10 +31000,10 @@ msgid "Profiles|You don't have access to delete this user."
msgstr "Vous n’avez pas les autorisations suffisantes pour supprimer cet utilisateur ou cette utilisatrice."
msgid "Profiles|You must accept the Terms of Service in order to perform this action."
-msgstr ""
+msgstr "Vous devez accepter les Conditions Générales d'Utilisation pour effectuer cette action."
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
-msgstr ""
+msgstr "Vous devez faire un transfert de propriété ou supprimer les groupes dont vous êtes le propriétaire avant de pouvoir supprimer votre compte"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Vous devez transférer la propriété ou supprimer ces groupes avant de pouvoir supprimer votre compte."
@@ -30494,13 +31024,10 @@ msgid "Profiles|Your name was automatically set based on your %{provider_label}
msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr ""
-
-msgid "Profiles|Your status"
-msgstr "Votre statut"
+msgstr "Votre nom sera automatiquement défini d'après votre compte %{provider_label} afin qu'il soit possible de vous reconnaître."
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://siteweb.com"
msgid "Profiles|username"
msgstr ""
@@ -30509,7 +31036,7 @@ msgid "Profiles|your account"
msgstr "votre compte"
msgid "Profile|%{job_title} at %{organization}"
-msgstr ""
+msgstr "%{job_title} chez %{organization}"
msgid "Profiling - Performance bar"
msgstr "Profilage — barre de performance"
@@ -30533,7 +31060,7 @@ msgid "Project %{project_repo} could not be found"
msgstr ""
msgid "Project & Group can not be assigned at the same time"
-msgstr ""
+msgstr "Le projet et le groupe ne peuvent pas être assignés en même temps"
msgid "Project '%{project_name}' is being imported."
msgstr ""
@@ -30542,7 +31069,7 @@ msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "Le projet « %{project_name} » est en cours de suppression."
msgid "Project '%{project_name}' is restored."
-msgstr ""
+msgstr "Le projet '%{project_name}' a été restauré."
msgid "Project '%{project_name}' queued for deletion."
msgstr "Projet « %{project_name} » en attente de suppression."
@@ -30554,10 +31081,10 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "Mise à jour du projet « %{project_name} » effectuée."
msgid "Project '%{project_name}' will be deleted on %{date}"
-msgstr ""
+msgstr "Le projet « %{project_name} » sera supprimé le %{date}"
msgid "Project Access Tokens"
-msgstr ""
+msgstr "Jetons d'accès au projet"
msgid "Project Badges"
msgstr "Badges numériques du projet"
@@ -30569,25 +31096,25 @@ msgid "Project ID"
msgstr ""
msgid "Project Templates"
-msgstr ""
+msgstr "Modèles de Projet"
msgid "Project URL"
msgstr "URL du projet"
msgid "Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
-msgstr ""
+msgstr "L'accès au projet doit être explicitement accordé à chaque utilisateur. Si ce projet fait partie d'un groupe, l'accès est accordé aux membres du groupe."
msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "La création de jetons d'accès au projet est désactivée dans ce groupe. Vous pouvez toujours utiliser et gérer les jetons existants. %{link_start}En savoir plus.%{link_end}"
msgid "Project already deleted"
-msgstr ""
+msgstr "Projet déjà supprimé"
msgid "Project and wiki repositories"
msgstr ""
msgid "Project audit events"
-msgstr ""
+msgstr "Événements d'audit de projet"
msgid "Project avatar"
msgstr "Avatar du projet"
@@ -30596,7 +31123,7 @@ msgid "Project cannot be shared with the group it is in or one of its ancestors.
msgstr ""
msgid "Project configuration, excluding integrations"
-msgstr ""
+msgstr "La configuration du projet, à l'exclusion des intégrations"
msgid "Project description (optional)"
msgstr ""
@@ -30605,7 +31132,7 @@ msgid "Project does not exist or you don't have permission to perform this actio
msgstr ""
msgid "Project does not have a policy configuration"
-msgstr ""
+msgstr "Le projet ne dispose d'aucune configuration de politique"
msgid "Project export could not be deleted."
msgstr "L’exportation du projet n’a pas pu être supprimée."
@@ -30620,25 +31147,25 @@ msgid "Project export link has expired. Please generate a new export from your p
msgstr "Le lien de l’exportation du projet a expiré. Merci de générer une nouvelle exportation depuis les paramètres du projet."
msgid "Project export requests"
-msgstr ""
+msgstr "Demandes d'exportation de projet"
msgid "Project export started. A download link will be sent by email and made available on this page."
-msgstr ""
+msgstr "L'exportation du projet a commencé. Un lien de téléchargement sera envoyé par courriel et sera disponible sur cette page."
msgid "Project has too many %{label_for_message} to search"
msgstr ""
msgid "Project import requests"
-msgstr ""
+msgstr "Demandes d'importation de projet"
msgid "Project info:"
-msgstr ""
+msgstr "Infos du projet :"
msgid "Project information"
msgstr "Informations du projet"
msgid "Project is required when cluster_type is :project"
-msgstr ""
+msgstr "Le projet est requis lorsque cluster_type vaut :project"
msgid "Project members"
msgstr ""
@@ -30662,7 +31189,7 @@ msgid "Project security status"
msgstr ""
msgid "Project security status help page"
-msgstr ""
+msgstr "Page d'aide sur l'état de la sécurité du projet"
msgid "Project slug"
msgstr "Identifiant « slug » du projet"
@@ -30671,22 +31198,22 @@ msgid "Project uploads"
msgstr ""
msgid "Project visibility level is less restrictive than the group settings."
-msgstr ""
+msgstr "Le niveau de visibilité du projet est moins restrictif que celui défini par les paramètres du groupe."
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "Le projet n'a pas été trouvé ou vous n'avez pas la permission de l'ajouter aux Tableaux de bord de Sécurité."
msgid "Project: %{name}"
msgstr ""
msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
-msgstr ""
+msgstr "Projet:Branches : %{source_project_path}:%{source_branch} vers %{target_project_path}:%{target_branch}"
msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
-msgstr ""
+msgstr "Projet:Branches : %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
msgid "ProjectActivityRSS|Subscribe"
msgstr "S’abonner"
@@ -30707,13 +31234,13 @@ msgid "ProjectCreationLevel|No one"
msgstr "Personne"
msgid "ProjectCreationLevel|Roles allowed to create projects"
-msgstr ""
+msgstr "Rôles autorisés à créer des projets"
msgid "ProjectFileTree|Name"
msgstr "Nom"
msgid "ProjectFileTree|Show more"
-msgstr ""
+msgstr "Afficher plus"
msgid "ProjectLastActivity|Never"
msgstr "Jamais"
@@ -30740,7 +31267,7 @@ msgid "ProjectOverview|Unstar"
msgstr "Supprimer l’étoile"
msgid "ProjectOverview|You don't have permission to fork this project"
-msgstr ""
+msgstr "Vous n'avez pas la permission de créer une divergence de ce projet"
msgid "ProjectOverview|You have reached your project limit"
msgstr "Vous avez atteint la limite de votre projet"
@@ -30749,46 +31276,46 @@ msgid "ProjectOverview|You must sign in to star a project"
msgstr "Vous devez vous authentifier afin de pouvoir ajouter une étoile à un projet"
msgid "ProjectPage|Copy project ID"
-msgstr ""
+msgstr "Copier l'ID du projet"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Identifiant de projet : %{project_id}"
msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative de récupération des statistiques de qualité du projet"
msgid "ProjectQualitySummary|Coverage"
-msgstr ""
+msgstr "Couverture"
msgid "ProjectQualitySummary|Failure"
-msgstr ""
+msgstr "Échec"
msgid "ProjectQualitySummary|Get insight into the overall percentage of tests in your project that succeed, fail and are skipped."
msgstr ""
msgid "ProjectQualitySummary|Help us improve this page"
-msgstr ""
+msgstr "Aidez-nous à améliorer cette page"
msgid "ProjectQualitySummary|Latest pipeline results"
-msgstr ""
+msgstr "Derniers résultats du pipeline"
msgid "ProjectQualitySummary|Learn more about test coverage"
-msgstr ""
+msgstr "En savoir plus sur la couverture des tests"
msgid "ProjectQualitySummary|Learn more about test reports"
-msgstr ""
+msgstr "En savoir plus sur les rapports des tests"
msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
-msgstr ""
+msgstr "Mesure de la quantité de votre code couverte par les tests."
msgid "ProjectQualitySummary|Provide feedback"
-msgstr ""
+msgstr "Donnez votre avis"
msgid "ProjectQualitySummary|See full report"
-msgstr ""
+msgstr "Voir le rapport complet"
msgid "ProjectQualitySummary|See project Code Coverage Statistics"
-msgstr ""
+msgstr "Voir les Statistiques de Couverture du Code du projet"
msgid "ProjectQualitySummary|Set up test runs"
msgstr ""
@@ -30797,199 +31324,202 @@ msgid "ProjectQualitySummary|Set up test runs (opens in a new tab)"
msgstr ""
msgid "ProjectQualitySummary|Skipped"
-msgstr ""
+msgstr "Ignorés"
msgid "ProjectQualitySummary|Success"
-msgstr ""
+msgstr "Réussite"
msgid "ProjectQualitySummary|Test coverage"
-msgstr ""
+msgstr "Couverture des tests"
msgid "ProjectQualitySummary|Test runs"
msgstr ""
msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
-msgstr ""
+msgstr "Le pourcentage des tests qui ont réussi, échoué ou été ignorés."
msgid "ProjectQualitySummary|This page helps you understand the code testing trends for your project. Let us know how we can improve it!"
-msgstr ""
+msgstr "Cette page vous aide à comprendre les tendances des tests de code de votre projet. Faites-nous savoir comment nous pouvons l'améliorer !"
msgid "ProjectSelect| or group"
msgstr ""
msgid "ProjectSelect|No matching results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "ProjectSelect|Search for project"
msgstr ""
msgid "ProjectSelect|Search projects"
-msgstr ""
+msgstr "Rechercher des projets"
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "Sélectionnez un projet"
msgid "ProjectSelect|Something went wrong while fetching projects"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets. Veuillez réessayer."
msgid "ProjectService|Drone server URL"
-msgstr ""
+msgstr "URL du serveur Drone"
msgid "ProjectService|Enter new API key"
-msgstr ""
+msgstr "Entrez une nouvelle clé d'API"
msgid "ProjectService|Enter new password"
-msgstr ""
+msgstr "Entrez un nouveau mot de passe"
msgid "ProjectService|Enter new password."
-msgstr ""
+msgstr "Entrez un nouveau mot de passe."
msgid "ProjectService|Enter new token"
-msgstr ""
+msgstr "Entrez un nouveau jeton"
msgid "ProjectService|Jenkins server URL"
-msgstr ""
+msgstr "URL du serveur Jenkins"
msgid "ProjectService|Leave blank to use your current API key"
-msgstr ""
+msgstr "Laisser vide pour utiliser votre clé d'API actuelle"
msgid "ProjectService|Leave blank to use your current API key."
-msgstr ""
+msgstr "Laisser vide pour utiliser votre clé d'API actuelle."
msgid "ProjectService|Leave blank to use your current password"
-msgstr ""
+msgstr "Laisser vide pour utiliser votre mot de passe actuel"
msgid "ProjectService|Leave blank to use your current password."
-msgstr ""
+msgstr "Laissez vide pour utiliser votre mot de passe actuel."
msgid "ProjectService|Leave blank to use your current token."
-msgstr ""
+msgstr "Laissez vide pour utiliser votre jeton actuel."
msgid "ProjectService|Mock service URL"
-msgstr ""
+msgstr "URL du service de mocking"
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
-msgstr ""
+msgstr "Doit avoir l'autorisation de déclencher une construction manuelle dans TeamCity."
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
msgid "ProjectService|Run CI/CD pipelines with Buildkite."
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec Buildkite."
msgid "ProjectService|Run CI/CD pipelines with Drone."
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec Drone."
msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec JetBrains TeamCity."
msgid "ProjectService|TeamCity server URL"
-msgstr ""
+msgstr "URL du serveur TeamCity"
msgid "ProjectService|The build configuration ID of the TeamCity project."
-msgstr ""
+msgstr "L'ID de configuration de la construction du projet TeamCity."
msgid "ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository."
-msgstr ""
+msgstr "Le jeton que vous obtenez après avoir créé un pipeline Buildkite avec un dépôt GitLab."
msgid "ProjectService|To configure this integration, you should:"
-msgstr ""
+msgstr "Pour configurer cette intégration, vous devez :"
msgid "ProjectService|Token for the Drone project."
-msgstr ""
+msgstr "Jeton pour le projet Drone."
msgid "ProjectService|Trigger event for new comments on confidential issues."
-msgstr ""
+msgstr "Déclencher un événement pour les nouveaux commentaires sur les tickets confidentiels."
msgid "ProjectService|Trigger event for new comments."
-msgstr ""
+msgstr "Déclencher un événement pour les nouveaux commentaires."
msgid "ProjectService|Trigger event for new tags pushed to the repository."
-msgstr ""
+msgstr "Déclencher un événement pour les nouvelles étiquettes poussées vers le dépôt."
msgid "ProjectService|Trigger event for pushes to the repository."
-msgstr ""
+msgstr "Déclencher un événement pour les poussées vers le dépôt."
msgid "ProjectService|Trigger event when a commit is created or updated."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'un commit est créé ou mis à jour."
msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'un ticket confidentiel est créé, mis à jour ou fermé."
msgid "ProjectService|Trigger event when a deployment starts or finishes."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'un déploiement commence ou finit."
msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'une demande de fusion est créée, mise à jour ou fusionnée."
msgid "ProjectService|Trigger event when a new, unique alert is recorded."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'une nouvelle alerte unique est enregistrée."
msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
-msgstr ""
+msgstr "Déclencher un évènement quand une nouvelle vulnérabilité, unique, est enregistrée. (Remarque : Cette fonctionnalité nécessite un forfait Ultimate.)"
msgid "ProjectService|Trigger event when a pipeline status changes."
-msgstr ""
+msgstr "Déclencher un événement lorsque l'état d'un pipeline change."
msgid "ProjectService|Trigger event when a wiki page is created or updated."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'une page de wiki est créée ou mise à jour."
msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
-msgstr ""
+msgstr "Déclencher un événement lorsqu'un ticket est créé, mis à jour ou fermé."
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Que sont les modèles de description ?%{link_end}"
msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Quelles variables puis-je utiliser ?%{link_end}"
msgid "ProjectSettings|Additional options"
-msgstr ""
+msgstr "Options supplémentaires"
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
-msgstr ""
+msgstr "Paramètres supplémentaires qui agissent sur comment et quand les fusions sont effectuées."
msgid "ProjectSettings|All threads must be resolved"
-msgstr ""
+msgstr "Tous les fil de conversation doivent être résolus"
msgid "ProjectSettings|Allow"
-msgstr ""
+msgstr "Autoriser"
msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
-msgstr ""
+msgstr "Toujours afficher les boutons des émojis de récompense « pouce vers le haut » et « pouce vers le bas » sur les tickets, les demandes de fusion et les extraits."
msgid "ProjectSettings|Analytics"
-msgstr ""
+msgstr "Analytiques"
msgid "ProjectSettings|Automatically resolve merge request diff threads when they become outdated"
-msgstr ""
+msgstr "Résoudre automatiquement les discussions des diff de demande de fusion lorsqu'elles ne sont plus d'actualité"
msgid "ProjectSettings|Badges"
msgstr "Badges numériques"
msgid "ProjectSettings|Build, test, and deploy your changes."
-msgstr ""
+msgstr "Construisez, testez et déployez vos modifications."
msgid "ProjectSettings|Checkbox is visible and selected by default."
-msgstr ""
+msgstr "La case à cocher est visible et cochée par défaut."
msgid "ProjectSettings|Checkbox is visible and unselected by default."
-msgstr ""
+msgstr "La case à cocher est visible et décochée par défaut."
msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
-msgstr ""
+msgstr "Choisir la méthode, les options, les vérifications et les options d'écrasement pour les demandes de fusion. Vous pouvez également configurer des modèles de demande de fusion pour différentes actions."
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr "Choisissez votre méthode de fusion, vos options, vos vérifications et vos options d'écrasement."
+
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
msgstr ""
msgid "ProjectSettings|Configure your project resources and monitor their health."
-msgstr ""
+msgstr "Configurer les ressources de votre projet et surveiller leur état de santé."
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "Contactez un administrateur pour modifier ce paramètre."
@@ -31001,49 +31531,52 @@ msgid "ProjectSettings|Customize this project's badges."
msgstr ""
msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
-msgstr ""
+msgstr "Déterminer ce qu'il advient de l'historique des commits lors de la fusion d'une demande de fusion."
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
-msgstr ""
+msgstr "Ne pas autoriser"
msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
-msgstr ""
+msgstr "Activer par défaut l'option « Supprimer la branche source »"
msgid "ProjectSettings|Enable merge trains"
-msgstr ""
+msgstr "Activer les trains de fusion"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "Activer les relecteurs suggérés"
+
msgid "ProjectSettings|Encourage"
msgstr ""
msgid "ProjectSettings|Environments"
-msgstr ""
+msgstr "Environnements"
msgid "ProjectSettings|Every merge creates a merge commit."
-msgstr ""
+msgstr "Chaque fusion crée un commit de fusion."
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its packages."
-msgstr ""
+msgstr "Chaque projet peut avoir son propre espace pour stocker ses paquets."
msgid "ProjectSettings|Every project can have its own space to store its packages. Note: The Package Registry is always visible when a project is public."
-msgstr ""
+msgstr "Chaque projet peut avoir son propre espace pour stocker ses paquets. Remarque : le Registre de Paquets est toujours visible lorsqu'un projet est public."
msgid "ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access."
-msgstr ""
+msgstr "Tout projet peut effectuer des déploiements vers des environnements via CI/CD ou appel d'API. Les membres extérieurs au projet ont un accès en lecture seule."
msgid "ProjectSettings|Everyone"
msgstr ""
msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
-msgstr ""
+msgstr "Les demandes de fusion et les branches protégées existantes ne sont pas affectées."
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Impossible de protéger l’étiquette"
@@ -31055,58 +31588,58 @@ msgid "ProjectSettings|Fast-forward merge"
msgstr ""
msgid "ProjectSettings|Fast-forward merges only."
-msgstr ""
+msgstr "Fusions en avance rapide uniquement."
msgid "ProjectSettings|Feature flags"
-msgstr ""
+msgstr "Indicateurs de fonctionnalité"
msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
-msgstr ""
+msgstr "Un outil souple pour développer des idées collaborativement et pour planifier le travail sur ce projet."
msgid "ProjectSettings|Forks"
-msgstr ""
+msgstr "Forks"
msgid "ProjectSettings|Git Large File Storage (LFS)"
-msgstr ""
+msgstr "Git Large File Storage (LFS)"
msgid "ProjectSettings|Global"
-msgstr ""
+msgstr "Global"
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 "Mettre en évidence l'usage de caractères unicode cachés. Ils peuvent être utilisés de manière légitime pour les langues écrites de droite à gauche, mais ils peuvent aussi servir pour des exploits potentiels."
msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
-msgstr ""
+msgstr "Maintenance, export, archivage, modification de chemin, transfert et suppression."
msgid "ProjectSettings|How do they differ?"
msgstr ""
msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
-msgstr ""
+msgstr "Si les trains de fusion sont activés, la fusion n'est possible que si la branche peut être rebasée sans conflits."
msgid "ProjectSettings|Internal"
msgstr ""
msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
-msgstr ""
+msgstr "Présente le risque de fusionner des modifications qui ne passent pas le pipeline."
msgid "ProjectSettings|Issues"
msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
-msgstr ""
+msgstr "Les objets LFS de ce dépôt sont disponibles pour les forks. %{linkStart}Comment puis-je les supprimer ?%{linkEnd}"
msgid "ProjectSettings|Leave empty to use default template."
-msgstr ""
+msgstr "Laisser vide pour utiliser le modèle par défaut."
msgid "ProjectSettings|Manage who can see the project in the public access directory."
-msgstr ""
+msgstr "Gérer qui peut voir le projet dans le répertoire d'accès public."
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
-msgstr ""
+msgstr "Gère les fichiers volumineux tels que les fichiers audio, vidéo et graphique."
msgid "ProjectSettings|Maximum %{maxLength} characters."
-msgstr ""
+msgstr "%{maxLength} caractères maximum."
msgid "ProjectSettings|Merge checks"
msgstr ""
@@ -31115,7 +31648,7 @@ msgid "ProjectSettings|Merge commit"
msgstr ""
msgid "ProjectSettings|Merge commit message template"
-msgstr ""
+msgstr "Modèle de message pour les validations de fusion"
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -31133,31 +31666,37 @@ msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelin
msgstr ""
msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
-msgstr ""
+msgstr "Les demandes de fusion ne peuvent pas être fusionnées si le dernier pipeline a échoué ou est toujours en cours d'exécution."
msgid "ProjectSettings|Merge suggestions"
msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
-msgstr ""
+msgstr "La fusion n’est autorisée que lorsque la branche source est à jour avec sa cible."
+
+msgid "ProjectSettings|Monitor"
+msgstr "Supervision"
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
+msgstr "Remarque : Le registre de conteneurs est toujours visible lorsqu'un projet est public et que le registre de conteneurs est défini sur « %{access_level_description} »"
+
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Seuls les commits signés peuvent être poussés sur ce dépôt Git."
msgid "ProjectSettings|Operations"
-msgstr ""
+msgstr "Opérations"
msgid "ProjectSettings|Override user notification preferences for all project members."
msgstr ""
msgid "ProjectSettings|Package registry"
-msgstr ""
+msgstr "Registre de paquets"
msgid "ProjectSettings|Packages"
msgstr ""
@@ -31172,7 +31711,7 @@ msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
msgid "ProjectSettings|Prevents direct linking to potentially sensitive media files"
-msgstr ""
+msgstr "Empêche les liens directs vers des fichiers multimédia potentiellement sensibles"
msgid "ProjectSettings|Private"
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr "Versions"
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31193,25 +31735,25 @@ msgid "ProjectSettings|Require an associated issue from Jira"
msgstr ""
msgid "ProjectSettings|Require authentication to view media files"
-msgstr ""
+msgstr "Nécessite une authentification pour afficher les fichiers multimédias"
msgid "ProjectSettings|Requirements"
-msgstr ""
+msgstr "Exigences"
msgid "ProjectSettings|Requirements management system."
-msgstr ""
+msgstr "Système de gestion des exigences."
msgid "ProjectSettings|Roll out new features without redeploying with feature flags."
-msgstr ""
+msgstr "Intégrez de nouvelles fonctionnalités sans faire de nouveau déploiement grâce aux indicateurs de fonctionnalités."
msgid "ProjectSettings|Search for topic"
-msgstr ""
+msgstr "Rechercher un sujet"
msgid "ProjectSettings|Security & Compliance"
-msgstr ""
+msgstr "Sécurité & Conformité"
msgid "ProjectSettings|Security & Compliance for this project"
-msgstr ""
+msgstr "Sécurité & Conformité de ce projet"
msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
@@ -31226,49 +31768,49 @@ msgid "ProjectSettings|Show link to create or view a merge request when pushing
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
-msgstr ""
+msgstr "Les pipelines ignorés sont considérés comme réussis"
msgid "ProjectSettings|Snippets"
msgstr ""
msgid "ProjectSettings|Squash commit message template"
-msgstr ""
+msgstr "Modèle de message pour les squash de validation"
msgid "ProjectSettings|Squash commits when merging"
-msgstr ""
+msgstr "Squasher les commits lors de la fusion"
msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
-msgstr ""
+msgstr "Le squashing est toujours effectué. La case à cocher est visible et sélectionnée, et les utilisateurs ne peuvent pas la modifier."
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
-msgstr ""
+msgstr "Le squashing n’est jamais effectué et la case à cocher est cachée."
msgid "ProjectSettings|Submit changes to be merged upstream."
-msgstr ""
+msgstr "Soumettre les modifications à fusionner en amont."
msgid "ProjectSettings|Target project"
-msgstr ""
+msgstr "Projet cible"
msgid "ProjectSettings|The commit message used when applying merge request suggestions."
-msgstr ""
+msgstr "Le message de commit utilisé lorsque les suggestions de demande de fusion sont appliquées."
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
-msgstr ""
+msgstr "Le message de commit utilisé lors de la fusion, si la méthode de fusion crée un commit de fusion."
msgid "ProjectSettings|The commit message used when squashing commits."
-msgstr ""
+msgstr "Le message de commit utilisé lors de l'écrasement de commits."
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
-msgstr ""
+msgstr "Le projet cible par défaut pour les demandes de fusion créées dans ce projet divergent."
msgid "ProjectSettings|The default template will be applied on save."
-msgstr ""
+msgstr "Le modèle par défaut s’appliquera à l’enregistrement."
msgid "ProjectSettings|These checks must pass before merge requests can be merged."
-msgstr ""
+msgstr "Ces vérifications doivent être faites avant de pouvoir effectuer la fusion des demandes de fusion."
msgid "ProjectSettings|This project"
-msgstr ""
+msgstr "Ce projet"
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Ce paramètre s’applique au niveau du serveur mais il peut être outrepassé par un administrateur."
@@ -31283,13 +31825,13 @@ msgid "ProjectSettings|Transfer project"
msgstr ""
msgid "ProjectSettings|Upstream project"
-msgstr ""
+msgstr "Projet amont"
msgid "ProjectSettings|Used for every new merge request."
-msgstr ""
+msgstr "Utilisé pour chaque nouvelle demande de fusion."
msgid "ProjectSettings|Users can copy the repository to a new project."
-msgstr ""
+msgstr "Les utilisateurs peuvent copier le dépôt vers un nouveau projet."
msgid "ProjectSettings|Users can only push commits to this repository if the committer email is one of their own verified emails."
msgstr ""
@@ -31298,46 +31840,46 @@ msgid "ProjectSettings|Users can request access"
msgstr ""
msgid "ProjectSettings|View and edit files in this project."
-msgstr ""
+msgstr "Afficher et modifier des fichiers dans ce projet."
msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
-msgstr ""
+msgstr "Afficher et modifier les fichiers de ce projet. Les membres qui n'en font pas partie n'ont qu'un accès en lecture."
msgid "ProjectSettings|View project analytics."
msgstr ""
msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
-msgstr ""
+msgstr "Les options de visibilité de ce fork sont limitées par la visibilité actuelle du projet source."
msgid "ProjectSettings|Visualize the project's performance metrics."
-msgstr ""
+msgstr "Visualiser les métriques de performance du projet."
msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
-msgstr ""
+msgstr "Avertir en cas de Caractères Potentiellement Indésirables"
msgid "ProjectSettings|What are badges?"
-msgstr ""
+msgstr "Que sont les badges ?"
msgid "ProjectSettings|What are merge trains?"
-msgstr ""
+msgstr "Que sont les trains de fusion ?"
msgid "ProjectSettings|What is squashing?"
-msgstr ""
+msgstr "Qu'est-ce que l'écrasement ?"
msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
-msgstr ""
+msgstr "Quand les pipelines des demandes de fusion sont activés dans le fichier de configuration CI/CD, ceux-ci valident les résultats combinés des branches source et cible. %{link_start}Comment configurer les pipelines pour les demandes de fusion ?%{link_end}"
msgid "ProjectSettings|When semi-linear merge is not possible, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
-msgstr ""
+msgstr "En cas de conflit de fusion, l’utilisateur a la possibilité de rebaser."
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr ""
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr "Grâce aux Pages GitLab, vous pouvez héberger vos sites web statiques sur GitLab. Les Pages GitLab utilisent un mécanisme de cache pour plus d'efficacité. Vos modifications ne seront effectives que lorsque le cache sera invalidé, ce qui prend en général moins d'une minute."
msgid "ProjectTemplates|.NET Core"
msgstr ""
@@ -31349,16 +31891,16 @@ msgid "ProjectTemplates|GitLab Cluster Management"
msgstr ""
msgid "ProjectTemplates|Gitpod/Spring Petclinic"
-msgstr ""
+msgstr "Gitpod/Spring Petclinic"
msgid "ProjectTemplates|Go Micro"
msgstr ""
msgid "ProjectTemplates|HIPAA Audit Protocol"
-msgstr ""
+msgstr "Protocole d'audit HIPAA"
msgid "ProjectTemplates|Jsonnet for Dynamic Child Pipelines"
-msgstr ""
+msgstr "Jsonnet pour les Pipelines Enfants Dynamiques"
msgid "ProjectTemplates|Kotlin Native for Linux"
msgstr ""
@@ -31382,7 +31924,7 @@ msgid "ProjectTemplates|NodeJS Express"
msgstr ""
msgid "ProjectTemplates|Pages/Gatsby"
-msgstr ""
+msgstr "Pages/Gatsby"
msgid "ProjectTemplates|Pages/GitBook"
msgstr ""
@@ -31400,7 +31942,7 @@ msgid "ProjectTemplates|Pages/Middleman"
msgstr ""
msgid "ProjectTemplates|Pages/Pelican"
-msgstr ""
+msgstr "Pages/Pelican"
msgid "ProjectTemplates|Pages/Plain HTML"
msgstr ""
@@ -31409,31 +31951,34 @@ msgid "ProjectTemplates|Ruby on Rails"
msgstr ""
msgid "ProjectTemplates|SalesforceDX"
-msgstr ""
+msgstr "SalesforceDX"
msgid "ProjectTemplates|Sample GitLab Project"
-msgstr ""
+msgstr "Exemple de projet GitLab"
msgid "ProjectTemplates|Serverless Framework/JS"
-msgstr ""
+msgstr "Serverless Framework/JS"
msgid "ProjectTemplates|Spring"
msgstr ""
msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
-msgstr ""
+msgstr "Tencent Serverless Framework/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr "Une erreur s’est produite lors de la récupération des emplacements des transferts, veuillez actualiser la page et réessayer."
+
msgid "ProjectView|Activity"
-msgstr ""
+msgstr "Activité"
msgid "ProjectView|Files and Readme (default)"
-msgstr ""
+msgstr "Fichiers et Readme (par défaut)"
msgid "ProjectView|Readme"
-msgstr ""
+msgstr "Readme"
msgid "Projects"
msgstr "Projets"
@@ -31448,22 +31993,22 @@ msgid "Projects Successfully Retrieved"
msgstr ""
msgid "Projects are graded based on the highest severity vulnerability present"
-msgstr ""
+msgstr "Les projets sont classés selon la gravité la plus élevée des vulnérabilités présentes"
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "Les projets sont organisés en groupes"
msgid "Projects are where you store your code, access issues, wiki and other features of GitLab."
-msgstr ""
+msgstr "Les projets sont l'endroit où vous stockez votre code, accédez aux tickets, au wiki et aux autres fonctionnalités de GitLab."
msgid "Projects contributed to"
msgstr ""
msgid "Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more."
-msgstr ""
+msgstr "Les projets vous aident à organiser votre travail. Ils contiennent votre dépôt de fichiers, vos tickets, vos demandes de fusion et bien plus encore."
msgid "Projects in this group can use Git LFS"
-msgstr ""
+msgstr "Les projets de ce groupe peuvent utiliser Git LFS"
msgid "Projects shared with %{group_name}"
msgstr "Projets partagés avec %{group_name}"
@@ -31475,22 +32020,22 @@ msgid "Projects to index"
msgstr ""
msgid "Projects with critical vulnerabilities"
-msgstr ""
+msgstr "Projets avec des vulnérabilités critiques"
msgid "Projects with high or unknown vulnerabilities"
-msgstr ""
+msgstr "Projets avec des vulnérabilités élevées ou inconnues"
msgid "Projects with low vulnerabilities"
-msgstr ""
+msgstr "Projets avec des vulnérabilités faibles"
msgid "Projects with medium vulnerabilities"
-msgstr ""
+msgstr "Projets avec des vulnérabilités moyennes"
msgid "Projects with no vulnerabilities and security scanning enabled"
-msgstr ""
+msgstr "Projets sans vulnérabilité et avec analyse de sécurité activée"
msgid "Projects with this topic"
-msgstr ""
+msgstr "Projets sur ce sujet"
msgid "Projects with write access"
msgstr ""
@@ -31520,28 +32065,28 @@ msgid "ProjectsNew|Allows you to immediately clone this project’s repository.
msgstr ""
msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "Analyser votre code source à la recherche de failles de sécurité connues."
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
-msgstr ""
+msgstr "Connecter votre dépôt externe à GitLab CI/CD."
msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
msgstr ""
msgid "ProjectsNew|Create"
-msgstr ""
+msgstr "Créer"
msgid "ProjectsNew|Create a blank project to store your files, plan your work, and collaborate on code, among other things."
-msgstr ""
+msgstr "Créez un projet vierge pour, entre autres choses, stocker vos fichiers, planifier votre travail et collaborer sur le code."
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
+msgstr "Créer un projet pré-rempli avec les fichiers nécessaires pour vous permettre de démarrer rapidement."
msgid "ProjectsNew|Create blank project"
msgstr ""
msgid "ProjectsNew|Create from template"
-msgstr ""
+msgstr "Créer à partir d’un modèle"
msgid "ProjectsNew|Create new project"
msgstr ""
@@ -31550,13 +32095,13 @@ msgid "ProjectsNew|Description format"
msgstr ""
msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "Activer les Tests Statiques de Sécurité des Applications (SAST)"
msgid "ProjectsNew|Import"
msgstr ""
msgid "ProjectsNew|Import project"
-msgstr ""
+msgstr "Importer un projet"
msgid "ProjectsNew|Include a Getting Started README"
msgstr ""
@@ -31565,7 +32110,7 @@ msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
+msgstr "Migrez vos données depuis une source externe comme GitHub, Bitbucket ou une autre instance de GitLab."
msgid "ProjectsNew|No import options available"
msgstr ""
@@ -31577,7 +32122,7 @@ msgid "ProjectsNew|Pick a group or namespace where you want to create this proje
msgstr ""
msgid "ProjectsNew|Project Configuration"
-msgstr ""
+msgstr "Configuration du Projet"
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -31592,16 +32137,16 @@ msgid "ProjectsNew|Visibility Level"
msgstr ""
msgid "ProjectsNew|Want to organize several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
-msgstr ""
+msgstr "Vous souhaitez organiser plusieurs projets interdépendants sous un même espace de noms ? %{link_start}Créez un groupe.%{link_end}"
msgid "PrometheusAlerts|exceeded"
msgstr ""
msgid "PrometheusAlerts|is equal to"
-msgstr ""
+msgstr "est égal(e) à"
msgid "PrometheusAlerts|is less than"
-msgstr ""
+msgstr "est inférieur(e) à"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{exporters} avec %{metrics} ont été trouvés"
@@ -31610,7 +32155,7 @@ msgid "PrometheusService|Active"
msgstr "Actif"
msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
-msgstr ""
+msgstr "Les paramètres de configuration auto sont utilisés à moins que vous ne redéfinissiez leurs valeurs ici."
msgid "PrometheusService|Common metrics"
msgstr "Métriques communes"
@@ -31619,7 +32164,7 @@ msgid "PrometheusService|Common metrics are automatically monitored based on a l
msgstr "Les métriques courantes sont automatiquement supervisées grâce à une bibliothèque de métriques provenant d’exportateurs populaires."
msgid "PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters."
-msgstr ""
+msgstr "Configurer GitLab pour interroger un Prometheus installé sur l'une de vos grappes de serveurs."
msgid "PrometheusService|Custom metrics"
msgstr "Métriques personnalisées"
@@ -31637,7 +32182,7 @@ msgid "PrometheusService|Finding custom metrics..."
msgstr "Recherche des métriques personnalisées en cours…"
msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
-msgstr ""
+msgstr "IAP_CLIENT_ID.apps.googleusercontent.com"
msgid "PrometheusService|Manage clusters"
msgstr "Gérer les grappes de serveurs"
@@ -31652,7 +32197,7 @@ msgid "PrometheusService|Missing environment variable"
msgstr "Variable d’environnement manquante"
msgid "PrometheusService|Monitor application health with Prometheus metrics and dashboards"
-msgstr ""
+msgstr "Surveiller la santé de l'application grâce aux tableaux de bord et aux métriques de Prometheus"
msgid "PrometheusService|More information"
msgstr "Plus d’informations"
@@ -31661,43 +32206,43 @@ msgid "PrometheusService|New metric"
msgstr "Nouvelle métrique"
msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
-msgstr ""
+msgstr "Aucune %{docsUrlStart}métrique commune%{docsUrlEnd} n’a été trouvée"
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
msgid "PrometheusService|Prometheus cluster integration"
-msgstr ""
+msgstr "Intégration de grappe de serveurs Prometheus"
msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
-msgstr ""
+msgstr "Cochez cette case pour remplacer les paramètres de configuration auto par vos propres réglages."
msgid "PrometheusService|The ID of the IAP-secured resource."
-msgstr ""
+msgstr "L'ID de la ressource sécurisée par IAP."
msgid "PrometheusService|The Prometheus API base URL."
-msgstr ""
+msgstr "L'URL de base de l'API Prometheus."
msgid "PrometheusService|The contents of the credentials.json file of your service account."
-msgstr ""
+msgstr "Le contenu du fichier credentials.json de votre compte de service."
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr "Ces métriques ne seront supervisées qu’après votre premier déploiement dans un environnement"
msgid "PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration."
-msgstr ""
+msgstr "Pour utiliser un Prometheus installé sur une grappe de serveurs, désactivez la configuration manuelle."
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
msgstr "En attente de votre premier déploiement dans un environnement pour trouver des métriques communes"
msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
-msgstr ""
+msgstr "Vous avez une grappe de serveurs avec l’intégration Prometheus activée."
msgid "PrometheusService|https://prometheus.example.com/"
-msgstr ""
+msgstr "https://prometheus.exemple.com/"
msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
-msgstr ""
+msgstr "{ \"type\": \"service_account\", \"project_id\": ... }"
msgid "Promote"
msgstr "Promouvoir"
@@ -31709,19 +32254,19 @@ msgid "Promote issue to incident"
msgstr ""
msgid "Promote to epic"
-msgstr ""
+msgstr "Promouvoir en épopée"
msgid "Promote to group label"
msgstr "Promouvoir en tant qu’étiquette de groupe"
msgid "PromoteMilestone|Only project milestones can be promoted."
-msgstr ""
+msgstr "Seuls les jalons du projet peuvent être promus."
msgid "PromoteMilestone|Project does not belong to a group."
-msgstr ""
+msgstr "Le projet n'appartient pas à un groupe."
msgid "PromoteMilestone|Promotion failed - %{message}"
-msgstr ""
+msgstr "La promotion a échoué - %{message}"
msgid "Promoted issue to an epic."
msgstr ""
@@ -31730,49 +32275,49 @@ msgid "Promotes issue to incident"
msgstr ""
msgid "Promotion is not supported."
-msgstr ""
+msgstr "La promotion n'est pas prise en charge."
msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
-msgstr ""
+msgstr "Ajoutez des %{link_start} modèles de description %{link_end} pour aider vos contributeurs à communiquer efficacement !"
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Ajouter Points d'Ancrage Web de Groupe et GitLab Édition Entreprise."
msgid "Promotions|Better Protected Branches"
msgstr ""
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
-msgstr ""
+msgstr "Les graphiques d'avancement sont des représentations visuelles de la progression de la réalisation d’un jalon. En un coup d'œil, vous voyez l'état actuel de la réalisation d'un jalon donné. Sans eux, vous devrez organiser les données à partir du jalon et le tracer vous-même pour avoir la même impression de progrès."
msgid "Promotions|Buy EE"
-msgstr ""
+msgstr "Acheter EE"
msgid "Promotions|Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "Acheter l'Édition Entreprise de GitLab"
msgid "Promotions|Configure Service Desk"
-msgstr ""
+msgstr "Configurer le Service d’assistance"
msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
-msgstr ""
+msgstr "Contactez un propriétaire du groupe %{namespace_name} pour mettre à niveau le forfait."
msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
-msgstr ""
+msgstr "Contactez le propriétaire %{link_start}%{owner_name}%{link_end} pour mettre à niveau le forfait."
msgid "Promotions|Contact your Administrator to upgrade your license."
-msgstr ""
+msgstr "Contactez votre administrateur pour mettre à niveau votre licence."
msgid "Promotions|Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr ""
+msgstr "Les modèles de description vous permettent de définir des modèles spécifiques à un contexte pour les champs de description des tickets et des demandes de fusion de votre projet."
msgid "Promotions|Dismiss Service Desk promotion"
-msgstr ""
+msgstr "Ignorer l'offre promotionnelle du Service d'assistance"
msgid "Promotions|Dismiss burndown charts promotion"
-msgstr ""
+msgstr "Rejeter la promotion sur les graphiques d'avancement"
msgid "Promotions|Dismiss repository features promotion"
-msgstr ""
+msgstr "Rejeter l'offre d'augmentation des fonctionnalités du dépôt"
msgid "Promotions|Don't show me this again"
msgstr "Ne plus réafficher ce message"
@@ -31781,88 +32326,88 @@ msgid "Promotions|Epics let you manage your portfolio of projects more efficient
msgstr "Les épopées vous permettent de gérer votre portefeuille de projets plus efficacement et avec moins d’efforts grâce au suivi de groupes de tickets qui partagent un thème commun au travers de différents projets et jalons."
msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Améliorer la gestion des tickets grâce au poids des tickets et à GitLab Édition Enterprise."
msgid "Promotions|Improve merge requests and customer support with GitLab Enterprise Edition."
-msgstr ""
+msgstr "Améliorez les demandes de fusion et le support client avec GitLab Édition Entreprise."
msgid "Promotions|Improve milestones with Burndown Charts."
-msgstr ""
+msgstr "Améliorer les jalons grâce aux graphiques d'avancement."
msgid "Promotions|Improve repositories with GitLab Enterprise Edition."
-msgstr ""
+msgstr "Améliorez les dépôts avec GitLab Édition Entreprise."
msgid "Promotions|Improve search with Advanced Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Améliorez la recherche avec la Recherche Avancée et GitLab Édition Entreprise."
msgid "Promotions|Keep track of events in your project"
-msgstr ""
+msgstr "Gardez une trace des événements de votre projet"
msgid "Promotions|Learn more"
msgstr ""
msgid "Promotions|Merge request approvals"
-msgstr ""
+msgstr "Approbations de demande de fusion"
msgid "Promotions|Not now, thanks!"
-msgstr ""
+msgstr "Pas maintenant, merci !"
msgid "Promotions|Push Rules"
-msgstr ""
+msgstr "Règles de Poussée"
msgid "Promotions|Push Rules are defined per project so you can have different rules applied to different projects depends on your needs."
-msgstr ""
+msgstr "Les Règles de Poussée sont définies par projet afin que vous puissiez appliquer des règles distinctes à des projets différents selon vos besoins."
msgid "Promotions|Repository Mirroring"
-msgstr ""
+msgstr "Mise en miroir de dépôt"
msgid "Promotions|Repository Mirroring is a way to mirror repositories from external sources. It can be used to mirror all branches, tags, and commits that you have in your repository."
-msgstr ""
+msgstr "La Mise en Miroir est un moyen de faire un miroir de dépôts issus de sources externes. Elle peut être utilisée pour faire un miroir de toutes les branches, étiquettes et commits que vous avez dans votre dépôt."
msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
-msgstr ""
+msgstr "Voir les autres fonctionnalités dans le %{subscription_link_start}forfait Premium%{subscription_link_end}"
msgid "Promotions|Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
-msgstr ""
+msgstr "Définit le nombre d'approbations nécessaires ainsi que la liste des approbateurs requis pour les demandes de fusion d'un projet."
msgid "Promotions|Start GitLab Ultimate trial"
-msgstr ""
+msgstr "Commencer l'essai de GitLab Ultimate"
msgid "Promotions|The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
-msgstr ""
+msgstr "Dans GitLab, la Recherche Avancée est un service de recherche puissant qui vous fait gagner du temps. Au lieu de créer du code en double et de perdre du temps, vous pouvez à présent rechercher du code au sein d'autres équipes qui peuvent contribuer à votre propre projet."
msgid "Promotions|This feature is locked."
msgstr "Cette fonctionnalité est verrouillée."
msgid "Promotions|Try it for free"
-msgstr ""
+msgstr "Essayez-le gratuitement"
msgid "Promotions|Upgrade plan"
msgstr "Mise à niveau du forfait"
msgid "Promotions|Upgrade your plan to activate Advanced Search."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour activer la Recherche Avancée."
msgid "Promotions|Upgrade your plan to activate Audit Events."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour activer les Événements d'Audit."
msgid "Promotions|Upgrade your plan to activate Group Webhooks."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour activer les Points d'Ancrage Web de Groupe."
msgid "Promotions|Upgrade your plan to improve merge requests."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour améliorer les demandes de fusion."
msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour améliorer les jalons grâce aux graphiques d'avancement."
msgid "Promotions|Upgrade your plan to improve repositories."
-msgstr ""
+msgstr "Mettez à niveau votre forfait pour améliorer les dépôts."
msgid "Promotions|Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr ""
+msgstr "Les points d'ancrage web vous permettent de déclencher une URL si, par exemple, du nouveau code est poussé ou un nouveau ticket est créé. Vous pouvez en configurer pour écouter des événements spécifiques tels que des poussées, des tickets ou des demandes de fusion. Les points d'ancrage web de groupe s’appliqueront à tous les projets d'un groupe, ce qui vous permet d'uniformiser leurs fonctionnalités dans la totalité de votre groupe."
msgid "Promotions|Weight"
-msgstr ""
+msgstr "Poids"
msgid "Promotions|Weighting your issue"
msgstr ""
@@ -31871,22 +32416,22 @@ msgid "Promotions|When you have a lot of issues, it can be hard to get an overvi
msgstr ""
msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
-msgstr ""
+msgstr "Vous pouvez restreindre l'accès aux branches protégées en sélectionnant un rôle (Mainteneurs, Développeurs) ou des utilisateurs spécifiques."
msgid "Promotions|description templates"
-msgstr ""
+msgstr "modèles de description"
msgid "Promotions|to help your contributors communicate effectively!"
-msgstr ""
+msgstr "pour aider vos contributeurs à communiquer efficacement !"
msgid "Prompt users to upload SSH keys"
msgstr ""
msgid "Protect"
-msgstr ""
+msgstr "Protéger"
msgid "Protect a tag"
-msgstr ""
+msgstr "Protéger une étiquette"
msgid "Protect variable"
msgstr ""
@@ -31898,43 +32443,43 @@ msgid "Protected Branch"
msgstr ""
msgid "Protected Branches"
-msgstr ""
+msgstr "Branches protégées"
msgid "Protected Environment"
msgstr ""
msgid "Protected Paths: requests"
-msgstr ""
+msgstr "Chemins protégés : demandes"
msgid "Protected Tag"
msgstr ""
msgid "Protected Tags"
-msgstr ""
+msgstr "Étiquettes protégées"
msgid "Protected branches"
msgstr ""
msgid "Protected environments"
-msgstr ""
+msgstr "Environnements protégés"
msgid "Protected paths"
-msgstr ""
+msgstr "Chemins protégés"
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 "Les %{wildcards_link_start}caractères génériques%{wildcards_link_end} tels que %{code_tag_start}*-stable%{code_tag_end} ou %{code_tag_start}production/*%{code_tag_end} sont pris en charge."
msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
-msgstr ""
+msgstr "Autoriser tous les utilisateurs ayant un accès pour pousser à %{tag_start}forcer les poussées%{tag_end}."
msgid "ProtectedBranch|Allow all users with push access to force push."
-msgstr ""
+msgstr "Autoriser tous les utilisateurs ayant un accès pour pousser à forcer les poussées."
msgid "ProtectedBranch|Allowed to force push"
-msgstr ""
+msgstr "Autoriser à forcer les poussées"
msgid "ProtectedBranch|Allowed to force push:"
-msgstr ""
+msgstr "Autoriser à forcer les poussées :"
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -31948,14 +32493,17 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr "Une erreur s'est produite lors du chargement des règles de branche. Veuillez réessayer."
+
msgid "ProtectedBranch|Branch"
msgstr ""
msgid "ProtectedBranch|Branch will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "La branche sera accessible en écriture pour les développeurs. Êtes-vous sûr de vouloir cela ?"
msgid "ProtectedBranch|Branch:"
-msgstr ""
+msgstr "Branche :"
msgid "ProtectedBranch|By default, protected branches restrict who can modify the branch."
msgstr ""
@@ -31964,13 +32512,13 @@ msgid "ProtectedBranch|Code owner approval"
msgstr ""
msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
-msgstr ""
+msgstr "Ne s'applique pas aux utilisateurs autorisés à pousser. Les sections facultatives ne sont pas appliquées."
msgid "ProtectedBranch|Keep stable branches secure and force developers to use merge requests."
-msgstr ""
+msgstr "Gardez les branches stables sécurisées et forcez les développeurs à utiliser des demandes de fusion."
msgid "ProtectedBranch|Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "ProtectedBranch|Protect"
msgstr ""
@@ -31984,8 +32532,11 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr "Une fois configurées, les branches protégées, les approbations de demandes de fusion et les vérifications d'état apparaîtront ici."
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
-msgstr ""
+msgstr "Rejeter les poussées de code qui modifient les fichiers répertoriés dans le fichier CODEOWNERS."
msgid "ProtectedBranch|Require approval from code owners:"
msgstr ""
@@ -31994,55 +32545,58 @@ msgid "ProtectedBranch|There are currently no protected branches, protect a bran
msgstr ""
msgid "ProtectedBranch|Toggle allowed to force push"
-msgstr ""
+msgstr "Inverser l'autorisation de forcer les poussées"
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
msgid "ProtectedBranch|Unprotect"
-msgstr ""
+msgstr "Déprotéger"
msgid "ProtectedBranch|Unprotect branch"
-msgstr ""
+msgstr "Déprotéger la branche"
msgid "ProtectedBranch|What are protected branches?"
+msgstr "Que sont les branches protégées ?"
+
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
msgstr ""
msgid "ProtectedBranch|default"
-msgstr ""
+msgstr "par défaut"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} sera accessible en écriture aux développeurs. Êtesâ€vous sûr de vouloir cela ?"
msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
-msgstr ""
+msgstr "Tous les environnements spécifiés avec les niveaux de déploiement ci-dessous sont protégés par un groupe parent. %{link_start}En savoir plus%{link_end}."
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Autorisé à déployer"
msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
-msgstr ""
+msgstr "Autorisés à déployer sur %{project} / %{environment}"
msgid "ProtectedEnvironment|Environment"
msgstr "Environnement"
msgid "ProtectedEnvironment|Environments protected upstream"
-msgstr ""
+msgstr "Environnements protégés en amont"
msgid "ProtectedEnvironment|Failed to load details for this group."
-msgstr ""
+msgstr "Échec du chargement des détails de ce groupe."
msgid "ProtectedEnvironment|No environments in this project are protected."
-msgstr ""
+msgstr "Aucun environnement de ce projet n'est protégé."
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
-msgstr ""
+msgstr "Seuls les groupes spécifiés peuvent exécuter des déploiements dans les environnements protégés."
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
-msgstr ""
+msgstr "Seuls les utilisateurs spécifiés peuvent exécuter des déploiements dans un environnement protégé."
msgid "ProtectedEnvironment|Parent group"
-msgstr ""
+msgstr "Groupe parent"
msgid "ProtectedEnvironment|Protect"
msgstr "Protéger"
@@ -32054,7 +32608,7 @@ msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_coun
msgstr "Environnements protégés (%{protected_environments_count})"
msgid "ProtectedEnvironment|Required approvals"
-msgstr ""
+msgstr "Approbations requises"
msgid "ProtectedEnvironment|Select an environment"
msgstr "Sélectionner un environnement"
@@ -32066,7 +32620,7 @@ msgid "ProtectedEnvironment|Select users"
msgstr ""
msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
-msgstr ""
+msgstr "Il n’y a actuellement aucun environnement protégé. Protégezâ€en un avec ce formulaire."
msgid "ProtectedEnvironment|Unprotect"
msgstr "Déprotéger"
@@ -32081,49 +32635,49 @@ msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr "Votre environnement a été déprotégé"
msgid "ProtectedTags|Unprotect tag"
-msgstr ""
+msgstr "Déprotéger l'étiquette"
msgid "ProtectedTags|default"
-msgstr ""
+msgstr "par défaut"
msgid "ProtectedTag|By default, protected tags restrict who can modify the tag."
msgstr ""
msgid "ProtectedTag|Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "ProtectedTag|Limit access to creating and updating tags."
-msgstr ""
+msgstr "Limiter les accès à la création et à la mise à jour des étiquettes."
msgid "ProtectedTag|Protected tags"
-msgstr ""
+msgstr "Étiquettes protégées"
msgid "ProtectedTag|What are protected tags?"
-msgstr ""
+msgstr "Que sont les étiquettes protégées ?"
msgid "ProtectedTag|default"
-msgstr ""
+msgstr "par défaut"
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
-msgstr ""
+msgstr "Conseil d'expert : %{linkStart}Auto DevOps%{linkEnd} utilise des grappes de serveurs Kubernetes pour déployer votre code !"
msgid "Provide Feedback"
msgstr ""
msgid "Provide a number our sales team can use to call you."
-msgstr ""
+msgstr "Indiquez un numéro sur lequel notre équipe commerciale pourra vous appeler."
msgid "Provider"
msgstr "Fournisseur"
msgid "Provision instructions"
-msgstr ""
+msgstr "Instructions de provisionnement"
msgid "Provisioned by:"
-msgstr ""
+msgstr "Fourni par :"
msgid "Proxy support for this API is not available currently"
-msgstr ""
+msgstr "Le support du proxy pour cette API n'est pas disponible pour le moment"
msgid "Public"
msgstr ""
@@ -32135,7 +32689,7 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "Public - le projet est accessible sans aucune authentification."
msgid "Public Access Help"
-msgstr ""
+msgstr "Aide sur l’Accès Public"
msgid "Public deploy keys"
msgstr ""
@@ -32144,37 +32698,40 @@ msgid "Public pipelines"
msgstr "Pipelines publics"
msgid "Public projects Minutes cost factor"
-msgstr ""
+msgstr "Facteur de coût des Minutes des projets publics"
msgid "Public projects are an easy way to allow everyone to have read-only access."
msgstr ""
msgid "Publish to status page"
-msgstr ""
+msgstr "Publier sur la page d'état"
msgid "Published"
-msgstr ""
+msgstr "Publié"
msgid "Published on status page"
-msgstr ""
+msgstr "Publication sur la page d'état"
msgid "Publishes this issue to the associated status page."
-msgstr ""
+msgstr "Publie ce ticket sur la page d'état associée."
msgid "Pull"
msgstr "Récupérer"
-msgid "Pull requests from fork are not supported"
+msgid "Pull mirroring updated %{time}."
msgstr ""
+msgid "Pull requests from fork are not supported"
+msgstr "Les demandes « pull » depuis un fork ne sont pas prises en charge"
+
msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
-msgstr ""
+msgstr "Puma fonctionne avec un nombre de threads supérieur à 1 et le service Rugged est activé. Cela peut diminuer les performances dans certains environnements. Consultez notre %{link_start}documentation%{link_end} pour plus de détails sur ce problème."
msgid "PumbleIntegration|Send notifications about project events to Pumble."
-msgstr ""
+msgstr "Envoyer à Pumble des notifications concernant les évènements du projet."
msgid "PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}"
-msgstr ""
+msgstr "Envoyer à Pumble des notifications concernant les évènements du projet. %{docs_link}"
msgid "Purchase more minutes"
msgstr ""
@@ -32183,7 +32740,7 @@ msgid "Purchase more storage"
msgstr ""
msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'étape d'achat. Si le problème persiste, veuillez contacter le support sur https://support.gitlab.com."
msgid "Push"
msgstr "Push"
@@ -32204,10 +32761,10 @@ msgid "Push an existing folder"
msgstr ""
msgid "Push code to the repository."
-msgstr ""
+msgstr "Pousser du code vers le dépôt."
msgid "Push commits to the source branch or add previously merged commits to review them."
-msgstr ""
+msgstr "Poussez des commits dans la branche source ou ajoutez des commits précédemment fusionnés pour les examiner."
msgid "Push events"
msgstr "Événements de poussée"
@@ -32222,49 +32779,79 @@ msgid "Push to create a project"
msgstr "Pousser pour créer un projet"
msgid "PushRules|All branch names must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any branch name is allowed."
-msgstr ""
+msgstr "Tous les noms de branche doivent correspondre à cette %{wiki_syntax_link_start}expression rationnelle%{wiki_syntax_link_end}. Si vide, tout nom de branche est autorisé."
msgid "PushRules|All commit author's email must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any email is allowed."
-msgstr ""
+msgstr "Toutes les adresses de courriel des auteurs de commits doivent correspondre à cette %{wiki_syntax_link_start}expression rationnelle%{wiki_syntax_link_end}. Si vide, toute adresse de courriel est autorisée."
msgid "PushRules|All commit messages must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not required to match any expression."
-msgstr ""
+msgstr "Tous les messages de commit doivent correspondre à cette %{wiki_syntax_link_start}expression rationnelle%{wiki_syntax_link_end}. Si vide, les messages de commit n'ont pas à correspondre à une expression."
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr "Nom de la branche"
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr "Vérifier si l'auteur du commit est un utilisateur de GitLab"
+
+msgid "PushRules|Commit author's email"
+msgstr "Courriel de l'auteur du commit"
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
-msgstr ""
+msgstr "Ne pas autoriser les utilisateurs à supprimer des étiquettes Git avec %{code_block_start}git push%{code_block_end}"
+
+msgid "PushRules|Maximum file size (MB)"
+msgstr "Taille maximale de fichier (Mo)"
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr "Empêcher la poussée de fichiers secrets"
+
+msgid "PushRules|Prohibited file names"
+msgstr "Noms de fichiers interdits"
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
+msgstr "Rejeter tout fichier susceptible de contenir des secrets. %{secret_files_link_start}Quels sont les fichiers secrets rejetés ?%{secret_files_link_end}"
+
+msgid "PushRules|Reject commits that aren't DCO certified"
msgstr ""
+msgid "PushRules|Reject expression in commit messages"
+msgstr "Rejeter les expressions dans les messages de commit"
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
-msgstr ""
+msgstr "Rejeter les fichiers de taille supérieure ou égale à celle indiquée. Si définie à 0, les fichiers de toutes tailles sont autorisés. Cette règle ne s'applique pas aux fichiers suivis par Git LFS."
+
+msgid "PushRules|Reject unsigned commits"
+msgstr "Rejeter les commits non signés"
+
+msgid "PushRules|Require expression in commit messages"
+msgstr "Exiger une expression dans les messages de commit"
msgid "PushRules|Restrict commits to existing GitLab users."
-msgstr ""
+msgstr "Restreindre les commits aux utilisateurs existants de GitLab."
msgid "PushRules|Restrict push operations for this project."
-msgstr ""
+msgstr "Restreindre les opérations de poussée de ce projet."
msgid "PushRules|Save push rules"
-msgstr ""
+msgstr "Enregistrer les règles de poussée"
msgid "PushRules|Select push rules"
-msgstr ""
+msgstr "Sélectionner les règles de poussée"
msgid "PushRules|Users can still delete tags through the GitLab UI."
-msgstr ""
+msgstr "Les utilisateurs peuvent toujours supprimer des étiquettes par l'intermédiaire de l'interface utilisateur de GitLab."
msgid "PushRule|Push rules"
-msgstr ""
+msgstr "Règles de poussée"
msgid "PushRule|Reject unverified users"
-msgstr ""
+msgstr "Rejeter les utilisateurs non vérifiés"
msgid "Pushed"
msgstr "Poussé"
@@ -32282,7 +32869,7 @@ msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
msgstr ""
msgid "PushoverService|Enter new user key"
-msgstr ""
+msgstr "Entrez la nouvelle clé d'utilisateur"
msgid "PushoverService|Enter your application key."
msgstr ""
@@ -32291,16 +32878,16 @@ msgid "PushoverService|Enter your user key."
msgstr ""
msgid "PushoverService|Get real-time notifications on your device."
-msgstr ""
+msgstr "Recevez des notifications en temps réel sur votre appareil."
msgid "PushoverService|High priority"
msgstr "Priorité haute"
msgid "PushoverService|Leave blank for all active devices."
-msgstr ""
+msgstr "Laisser vide pour tous les appareils actifs."
msgid "PushoverService|Leave blank to use your current user key."
-msgstr ""
+msgstr "Laisser vide pour utiliser votre clé d'utilisateur actuelle."
msgid "PushoverService|Low priority"
msgstr "Priorité basse"
@@ -32318,61 +32905,61 @@ msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
msgid "QualitySummary|Project quality"
-msgstr ""
+msgstr "Qualité du projet"
msgid "Query"
msgstr ""
msgid "Query cannot be processed"
-msgstr ""
+msgstr "La requête ne peut pas être traitée"
msgid "Queued"
-msgstr ""
+msgstr "En file d'attente"
msgid "Quick actions can be used in description and comment boxes."
-msgstr ""
+msgstr "Les actions rapides peuvent être utilisées dans les zones de saisie de description et de commentaire."
msgid "Quick help"
-msgstr ""
+msgstr "Aide rapide"
msgid "Quick range"
msgstr ""
msgid "Quota of CI/CD minutes"
-msgstr ""
+msgstr "Quota de minutes CI/CD"
msgid "Quota of CI/CD minutes:"
-msgstr ""
+msgstr "Quota de minutes CI/CD :"
msgid "README"
msgstr ""
msgid "Rails"
-msgstr ""
+msgstr "Rails"
msgid "Rake Tasks Help"
-msgstr ""
+msgstr "Aide sur les Tâches Rake"
msgid "Random"
msgstr ""
msgid "Rate Limits"
-msgstr ""
+msgstr "Limites de Fréquence"
msgid "Rate limit"
-msgstr ""
+msgstr "Limite de fréquence"
msgid "Rate limit access to specified paths."
msgstr ""
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
-msgstr ""
+msgstr "Les limitations de fréquence contribuent à réduire le volume de requêtes (p. ex. celles de robots d'exploration ou de bots abusifs)."
msgid "Raw blob request rate limit per minute"
msgstr ""
msgid "Raw blob requests"
-msgstr ""
+msgstr "Demandes de blobs bruts"
msgid "Re-authentication period expired or never requested. Please try again"
msgstr ""
@@ -32381,22 +32968,19 @@ msgid "Re-authentication required"
msgstr ""
msgid "Re-import"
-msgstr ""
+msgstr "Réimporter"
msgid "Re-request review"
-msgstr ""
+msgstr "Redemander un examen"
msgid "Read documentation"
-msgstr ""
+msgstr "Lire la documentation"
msgid "Read more"
msgstr "Lire plus"
msgid "Read more about GitLab at %{link_to_promo}."
-msgstr ""
-
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
+msgstr "En savoir plus sur GitLab sur %{link_to_promo}."
msgid "Read more about related epics"
msgstr ""
@@ -32405,46 +32989,46 @@ msgid "Read more about related issues"
msgstr ""
msgid "Read their documentation."
-msgstr ""
+msgstr "Lisez leur documentation."
msgid "Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
-msgstr ""
+msgstr "Prêt à démarrer avec GitLab ? Suivez ces étapes pour configurer votre espace de travail, planifier et valider les modifications et déployer votre projet."
msgid "Ready to merge by members who can write to the target branch."
msgstr ""
msgid "Ready to merge!"
-msgstr ""
+msgstr "Prêt pour la fusion !"
msgid "Reauthenticating with SAML provider."
-msgstr ""
+msgstr "Réauthentification avec le fournisseur SAML."
msgid "Rebase"
msgstr ""
msgid "Rebase completed"
-msgstr ""
+msgstr "Rebasage terminé"
msgid "Rebase in progress"
msgstr ""
msgid "Rebase source branch"
-msgstr ""
+msgstr "Rebaser la branche source"
msgid "Rebase source branch on the target branch."
-msgstr ""
+msgstr "Rebaser la branche source sur la branche cible."
msgid "Rebase without pipeline"
msgstr ""
msgid "Recaptcha verified?"
-msgstr ""
+msgstr "Recaptcha vérifié ?"
msgid "Receive any notifications from GitLab."
-msgstr ""
+msgstr "Recevoir toutes les notifications de GitLab."
msgid "Receive notification of abuse reports by email."
-msgstr ""
+msgstr "Recevoir une notification de rapports d'abus par courriel."
msgid "Receive notifications about your own activity"
msgstr ""
@@ -32462,7 +33046,7 @@ msgid "Recent Searches Service is unavailable"
msgstr ""
msgid "Recent events"
-msgstr ""
+msgstr "Événements récents"
msgid "Recent searches"
msgstr "Recherches récentes"
@@ -32471,10 +33055,10 @@ msgid "Recently used"
msgstr "Récemment utilisé"
msgid "Reconfigure"
-msgstr ""
+msgstr "Reconfigurer"
msgid "Recover password"
-msgstr ""
+msgstr "Récupérer le mot de passe"
msgid "Recovery Codes"
msgstr ""
@@ -32483,31 +33067,31 @@ msgid "Redirect to SAML provider to test configuration"
msgstr "Rediriger vers le fournisseur SAML pour tester la configuration"
msgid "Redirecting"
-msgstr ""
+msgstr "Redirection"
msgid "Redis"
-msgstr ""
+msgstr "Redis"
msgid "Reduce incident management alert volume (for example, if too many issues are being created)."
msgstr ""
msgid "Reduce project visibility"
-msgstr ""
+msgstr "Réduire la visibilité du projet"
msgid "Reduce risk and triage fewer vulnerabilities with security training"
msgstr ""
msgid "Reduce this project’s visibility?"
-msgstr ""
+msgstr "Réduire la visibilité de ce projet ?"
msgid "Reference"
-msgstr ""
+msgstr "Référence"
msgid "References"
-msgstr ""
+msgstr "Références"
msgid "Refine your search criteria (select a %{strong_open}group%{strong_close} and %{strong_open}project%{strong_close} when possible)"
-msgstr ""
+msgstr "Affinez vos critères de recherche (sélectionnez un %{strong_open}groupe%{strong_close} et un %{strong_open}projet%{strong_close} si possible)"
msgid "Refresh the page and try again."
msgstr ""
@@ -32551,91 +33135,88 @@ msgid "Register Universal Two-Factor (U2F) Device"
msgstr ""
msgid "Register WebAuthn Device"
-msgstr ""
-
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
+msgstr "Enregistrer un Appareil WebAuthn"
msgid "Register device"
-msgstr ""
+msgstr "Enregistrer un appareil"
msgid "Register now"
msgstr ""
msgid "Register the runner with this URL:"
-msgstr ""
+msgstr "Enregistrez l'exécuteur avec cette URL :"
msgid "Register with two-factor app"
msgstr ""
msgid "Register with:"
-msgstr ""
+msgstr "S'inscrire avec :"
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
-msgstr ""
+msgstr "Activez le Ping de Service et inscrivez cette fonctionnalité."
msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
-msgstr ""
+msgstr "En savoir plus sur le %{link_start}Programme de Fonctionnalités d'Insription%{link_end}."
msgid "RegistrationFeatures|Registration Features Program"
-msgstr ""
+msgstr "Programme des Fonctionnalités d'Inscription"
msgid "RegistrationFeatures|Want to %{feature_title} for free?"
-msgstr ""
+msgstr "Souhaitez-vous %{feature_title} gratuitement ?"
msgid "RegistrationFeatures|send emails to users"
-msgstr ""
+msgstr "envoyer des courriels aux utilisateurs"
msgid "RegistrationFeatures|use this feature"
-msgstr ""
+msgstr "utiliser cette fonctionnalité"
msgid "RegistrationVerification|Are you sure you want to skip this step?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir ignorer cette étape ?"
msgid "RegistrationVerification|Enable free CI/CD minutes"
-msgstr ""
+msgstr "Activer les minutes CI/CD gratuites"
msgid "RegistrationVerification|GitLab will not charge your card, it will only be used for validation."
-msgstr ""
+msgstr "GitLab ne débitera pas votre carte, elle ne sera utilisée que pour la validation."
msgid "RegistrationVerification|Pipelines using shared GitLab runners will fail until you validate your account."
-msgstr ""
+msgstr "Les pipelines utilisant les exécuteurs partagés de GitLab échoueront tant que vous n'aurez pas validé votre compte."
msgid "RegistrationVerification|Skip this for now"
-msgstr ""
+msgstr "Ignorer cela pour l'instant"
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 ""
+msgstr "Pour garder GitLab à l'abri du pourriel et des abus, nous vous demandons de vérifier votre identité avec une méthode de paiement valide, comme une carte de débit ou de crédit. Tant que ce n'est pas fait, vous ne pouvez pas utiliser les minutes gratuites de CI/CD pour construire votre application."
msgid "RegistrationVerification|Validate account"
-msgstr ""
+msgstr "Valider le compte"
msgid "RegistrationVerification|Verify your identity"
-msgstr ""
+msgstr "Vérifiez votre identité"
msgid "RegistrationVerification|Yes, I'd like to skip"
msgstr ""
msgid "RegistrationVerification|You can alway verify your account at a later time."
-msgstr ""
+msgstr "Vous pourrez toujours vérifier votre compte ultérieurement."
msgid "Registration|Checkout"
-msgstr ""
+msgstr "Commander"
msgid "Registration|Your GitLab group"
-msgstr ""
+msgstr "Votre groupe GitLab"
msgid "Registration|Your first project"
-msgstr ""
+msgstr "Votre premier projet"
msgid "Registration|Your profile"
-msgstr ""
+msgstr "Votre profil"
msgid "Registry setup"
-msgstr ""
+msgstr "Configuration du Registre"
msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
-msgstr ""
+msgstr "État de la réindexation : %{status} (Multiplicateur de tranches : %{multiplier}, Nombre maximum de tranches en cours d'exécution : %{max_slices})"
msgid "Reject"
msgstr ""
@@ -32644,10 +33225,10 @@ msgid "Rejected (closed)"
msgstr ""
msgid "Relate to %{issuable_type} %{add_related_issue_link}"
-msgstr ""
+msgstr "Est lié au %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
-msgstr ""
+msgstr "Indicateurs de fonctionnalité associés"
msgid "Related issues"
msgstr ""
@@ -32664,16 +33245,16 @@ msgstr[0] ""
msgstr[1] ""
msgid "Release %{deletedRelease} has been successfully deleted."
-msgstr ""
+msgstr "La version %{deletedRelease} a été supprimée avec succès."
msgid "Release assets"
-msgstr ""
+msgstr "Ressources de version"
msgid "Release assets documentation"
-msgstr ""
+msgstr "Documentation des ressources de version"
msgid "Release date"
-msgstr ""
+msgstr "Date de publication"
msgid "Release does not have the same project as the milestone"
msgstr ""
@@ -32688,79 +33269,79 @@ msgid "Release title"
msgstr ""
msgid "Release with tag \"%{tag}\" was not found"
-msgstr ""
+msgstr "La version avec l'étiquette « %{tag} » est introuvable"
msgid "ReleaseAssetLinkType|Image"
-msgstr ""
+msgstr "Image"
msgid "ReleaseAssetLinkType|Images"
-msgstr ""
+msgstr "Images"
msgid "ReleaseAssetLinkType|Other"
-msgstr ""
+msgstr "Autre"
msgid "ReleaseAssetLinkType|Package"
-msgstr ""
+msgstr "Paquet"
msgid "ReleaseAssetLinkType|Packages"
-msgstr ""
+msgstr "Paquets"
msgid "ReleaseAssetLinkType|Runbook"
-msgstr ""
+msgstr "Dossier d'exploitation"
msgid "ReleaseAssetLinkType|Runbooks"
-msgstr ""
+msgstr "Dossiers d'exploitation"
msgid "Released date"
-msgstr ""
+msgstr "Date de sortie"
msgid "Releases"
-msgstr ""
+msgstr "Versions"
msgid "Releases are based on Git tags and mark specific points in a project's development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software."
-msgstr ""
+msgstr "Les Versions sont basées sur les étiquettes Git et marquent des points spécifiques dans l'historique de développement d'un projet. Elles peuvent contenir des informations sur le type de modifications et peuvent également fournir des binaires tels que des versions compilées de votre logiciel."
msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
-msgstr ""
+msgstr "Les versions sont basées sur les étiquettes Git. Nous recommandons d'utiliser une gestion sémantique des versions pour les étiquettes, par exemple %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgid "Releases documentation"
-msgstr ""
+msgstr "Documentation des versions"
msgid "Releases|New Release"
-msgstr ""
+msgstr "Nouvelle version"
msgid "Releases|Tag message"
-msgstr ""
+msgstr "Message de l'étiquette"
msgid "Release|Include message from the annotated tag."
-msgstr ""
+msgstr "Inclure le message de l'étiquette annotée."
msgid "Release|Something went wrong while creating a new release."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création d'une nouvelle version."
msgid "Release|Something went wrong while deleting the release."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de la version."
msgid "Release|Something went wrong while getting the release details."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des détails de la version."
msgid "Release|Something went wrong while saving the release details."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'enregistrement des détails de la version."
msgid "Release|Unable to fetch the tag notes."
-msgstr ""
+msgstr "Impossible de récupérer les notes de l'étiquette."
msgid "Release|You can edit the content later by editing the release. %{linkStart}How do I edit a release?%{linkEnd}"
-msgstr ""
+msgstr "Vous pouvez éditer le contenu plus tard en modifiant la version. %{linkStart}Comment puis-je modifier une version ?%{linkEnd}"
msgid "Reload page"
-msgstr ""
+msgstr "Recharger la page"
msgid "Remediations"
-msgstr ""
+msgstr "Remédiations"
msgid "Remember me"
-msgstr ""
+msgstr "Se souvenir de moi"
msgid "Remind later"
msgstr "Me le rappeler ultérieurement"
@@ -32772,16 +33353,16 @@ msgid "Remove"
msgstr "Supprimer"
msgid "Remove %{displayReference}"
-msgstr ""
+msgstr "Supprimer %{displayReference}"
msgid "Remove Zoom meeting"
msgstr ""
msgid "Remove Zoom meeting."
-msgstr ""
+msgstr "Supprimer la réunion Zoom."
msgid "Remove access"
-msgstr ""
+msgstr "Supprimer l'accès"
msgid "Remove all or specific assignee(s)"
msgstr ""
@@ -32799,7 +33380,7 @@ msgid "Remove approvers?"
msgstr ""
msgid "Remove asset link"
-msgstr ""
+msgstr "Supprimer le lien des ressources"
msgid "Remove assignee"
msgstr ""
@@ -32820,7 +33401,7 @@ msgid "Remove customer relation contacts"
msgstr ""
msgid "Remove deploy key"
-msgstr ""
+msgstr "Supprimer la clé de déploiement"
msgid "Remove description history"
msgstr ""
@@ -32829,10 +33410,10 @@ msgid "Remove due date"
msgstr ""
msgid "Remove favicon"
-msgstr ""
+msgstr "Supprimer la favicon"
msgid "Remove file"
-msgstr ""
+msgstr "Supprimer le fichier"
msgid "Remove fork relationship"
msgstr ""
@@ -32847,10 +33428,10 @@ msgid "Remove group"
msgstr "Supprimer le groupe"
msgid "Remove header logo"
-msgstr ""
+msgstr "Supprimer le logo d'en-tête"
msgid "Remove iteration"
-msgstr ""
+msgstr "Supprimer l'itération"
msgid "Remove license"
msgstr ""
@@ -32862,19 +33443,19 @@ msgid "Remove link"
msgstr ""
msgid "Remove list"
-msgstr ""
+msgstr "Supprimer la liste"
msgid "Remove log"
-msgstr ""
+msgstr "Supprimer les journaux"
msgid "Remove logo"
-msgstr ""
+msgstr "Supprimer le logo"
msgid "Remove member"
msgstr ""
msgid "Remove milestone"
-msgstr ""
+msgstr "Supprimer le jalon"
msgid "Remove parent epic from an epic"
msgstr ""
@@ -32883,16 +33464,16 @@ msgid "Remove priority"
msgstr "Supprimer la priorité"
msgid "Remove report"
-msgstr ""
+msgstr "Supprimer le rapport"
msgid "Remove reviewer"
msgstr ""
msgid "Remove runner"
-msgstr ""
+msgstr "Supprimer l'exécuteur"
msgid "Remove secondary email"
-msgstr ""
+msgstr "Supprimer l'adresse de courriel secondaire"
msgid "Remove spent time"
msgstr ""
@@ -32904,16 +33485,16 @@ msgid "Remove topic avatar"
msgstr ""
msgid "Remove user"
-msgstr ""
+msgstr "Supprimer l'utilisateur"
msgid "Remove user & report"
-msgstr ""
+msgstr "Supprimer utilisateur et rapport"
msgid "Remove user from group"
-msgstr ""
+msgstr "Supprimer l'utilisateur du groupe"
msgid "Remove user from project"
-msgstr ""
+msgstr "Supprimer l'utilisateur du projet"
msgid "Remove..."
msgstr ""
@@ -32922,19 +33503,19 @@ msgid "Removed"
msgstr ""
msgid "Removed %{assignee_text} %{assignee_references}."
-msgstr ""
+msgstr "%{assignee_text} %{assignee_references} a été retiré ."
msgid "Removed %{epic_ref} from child epics."
msgstr ""
msgid "Removed %{iteration_reference} iteration."
-msgstr ""
+msgstr "Itération %{iteration_reference} supprimée."
msgid "Removed %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} supprimé."
msgid "Removed %{milestone_reference} milestone."
-msgstr ""
+msgstr "Le jalon %{milestone_reference} a été supprimé."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
@@ -32967,7 +33548,7 @@ msgid "RemovedProjects|No projects pending deletion found"
msgstr ""
msgid "RemovedProjects|Projects that are pending deletion that you have access to are listed here."
-msgstr ""
+msgstr "Les projets dont la suppression est en attente et auxquels vous avez accès sont listés ici."
msgid "Removes %{assignee_text} %{assignee_references}."
msgstr ""
@@ -32976,13 +33557,13 @@ msgid "Removes %{epic_ref} from child epics."
msgstr ""
msgid "Removes %{iteration_reference} iteration."
-msgstr ""
+msgstr "Supprime l'itération %{iteration_reference}."
msgid "Removes %{label_references} %{label_text}."
msgstr ""
msgid "Removes %{milestone_reference} milestone."
-msgstr ""
+msgstr "Supprime le jalon %{milestone_reference}."
msgid "Removes %{reviewer_text} %{reviewer_references}."
msgstr ""
@@ -33006,7 +33587,7 @@ msgid "Removes time estimate."
msgstr ""
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
-msgstr ""
+msgstr "La suppression de ce groupe supprime également tous les projets enfants, y compris les projets archivés et leurs ressources."
msgid "Rename file"
msgstr "Renommer le fichier"
@@ -33015,13 +33596,13 @@ msgid "Rename folder"
msgstr "Renommer le dossier"
msgid "Rename/Move"
-msgstr ""
+msgstr "Renommer/Déplacer"
msgid "Render diagrams in your documents using PlantUML."
-msgstr ""
+msgstr "Générer des diagrammes dans vos documents grâce à PlantUML."
msgid "Renew subscription"
-msgstr ""
+msgstr "Renouveler l'abonnement"
msgid "Renews"
msgstr ""
@@ -33039,10 +33620,10 @@ msgid "Reopen epic"
msgstr "Rouvrir l’épopée"
msgid "Reopen milestone"
-msgstr ""
+msgstr "Rouvrir le jalon"
msgid "Reopen test case"
-msgstr ""
+msgstr "Rouvrir le cas de test"
msgid "Reopen this %{quick_action_target}"
msgstr ""
@@ -33081,13 +33662,13 @@ msgid "Replaces the clone URL root."
msgstr ""
msgid "Replication"
-msgstr ""
+msgstr "Réplication"
msgid "Reply"
msgstr "Répondre"
msgid "Reply by email"
-msgstr ""
+msgstr "Répondre par email"
msgid "Reply internally"
msgstr ""
@@ -33099,25 +33680,25 @@ msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
msgid "Reply…"
-msgstr ""
+msgstr "Répondre…"
msgid "Report Finding not found"
-msgstr ""
+msgstr "Découverte de Rapport introuvable"
msgid "Report abuse"
msgstr "Signaler un abus"
msgid "Report abuse to admin"
-msgstr ""
+msgstr "Signaler un abus à l'administrateur"
msgid "Report couldn't be prepared."
msgstr ""
msgid "Report for the scan has been removed from the database."
-msgstr ""
+msgstr "Le rapport de cette analyse a été supprimé de la base de données."
msgid "Report version not provided, %{report_type} report type supports versions: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
-msgstr ""
+msgstr "Version de rapport non fournie, le type rapport de %{report_type} prend en charge les versions : %{supported_schema_versions}. GitLab essaiera de valider ce rapport avec les versions les plus anciennes prises en charge pour ce type de rapport afin d'afficher toutes les erreurs mais ne l'ingérera pas"
msgid "Report your license usage data to GitLab"
msgstr ""
@@ -33126,24 +33707,24 @@ msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
msgid "Reported by"
-msgstr ""
+msgstr "Signalé par"
msgid "Reported by %{reporter}"
-msgstr ""
+msgstr "Signalé par %{reporter}"
msgid "Reporting"
msgstr "Rapports"
msgid "Reports|%{combinedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{combinedString} et %{resolvedString}"
msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
-msgstr ""
+msgstr "%{recentlyFailed} test sur %{failed} ayant échoué a échoué plus d'une fois au cours des 14 derniers jours"
msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{recentlyFailed} test en échec sur %{failed} a échoué plus d'une fois au cours des 14 derniers jours"
+msgstr[1] "%{recentlyFailed} tests en échec sur %{failed} ont échoué plus d'une fois au cours des 14 derniers jours"
msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
@@ -33152,29 +33733,29 @@ msgstr[1] ""
msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "L’analyse d’accessibilité a détecté %{strong_start}%{number}%{strong_end} problème pour la branche source uniquement"
+msgstr[1] "L’analyse d’accessibilité a détecté %{strong_start}%{number}%{strong_end} problèmes pour la branche source uniquement"
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
msgstr ""
msgid "Reports|Accessibility scanning failed loading results"
-msgstr ""
+msgstr "L'analyse d'accessibilité a échoué à charger les résultats"
msgid "Reports|Accessibility scanning results are being parsed"
-msgstr ""
+msgstr "Les résultats de l'analyse d'accessibilité sont en cours d'analyse"
msgid "Reports|Actions"
msgstr "Actions"
msgid "Reports|Activity"
-msgstr ""
+msgstr "Activité"
msgid "Reports|An error occurred while loading %{name} results"
msgstr ""
msgid "Reports|An error occurred while loading report"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement du rapport"
msgid "Reports|Base report parsing error:"
msgstr ""
@@ -33183,35 +33764,35 @@ msgid "Reports|Classname"
msgstr ""
msgid "Reports|Copy failed test names to run locally"
-msgstr ""
+msgstr "Copier les noms des tests échoués pour les exécuter en local"
msgid "Reports|Copy failed tests"
-msgstr ""
+msgstr "Copier les tests échoués"
msgid "Reports|Execution time"
msgstr "Durée d’exécution"
msgid "Reports|Failed %{count} time in %{baseBranch} in the last 14 days"
msgid_plural "Reports|Failed %{count} times in %{baseBranch} in the last 14 days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Échec %{count} fois dans %{baseBranch} au cours des 14 derniers jours"
+msgstr[1] "Échec %{count} fois dans %{baseBranch} au cours des 14 derniers jours"
msgid "Reports|Failed %{count} time in %{base_branch} in the last 14 days"
msgid_plural "Reports|Failed %{count} times in %{base_branch} in the last 14 days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Échec %{count} fois dans %{base_branch} au cours des 14 derniers jours"
+msgstr[1] "Échec %{count} fois dans %{base_branch} au cours des 14 derniers jours"
msgid "Reports|Failure"
msgstr "Échec"
msgid "Reports|Filename"
-msgstr ""
+msgstr "Nom de fichier"
msgid "Reports|Fixed"
msgstr ""
msgid "Reports|Full report"
-msgstr ""
+msgstr "Rapport complet"
msgid "Reports|Head report parsing error:"
msgstr ""
@@ -33220,7 +33801,7 @@ msgid "Reports|Identifier"
msgstr ""
msgid "Reports|Metrics report scanning detected no new changes"
-msgstr ""
+msgstr "L’analyse des rapports métriques n’a détecté aucun nouveau changement"
msgid "Reports|Metrics reports are loading"
msgstr ""
@@ -33244,7 +33825,7 @@ msgid "Reports|New"
msgstr ""
msgid "Reports|Scanner"
-msgstr ""
+msgstr "Scanner"
msgid "Reports|Severity"
msgstr "Sévérité"
@@ -33268,40 +33849,40 @@ msgid "Reports|Test summary results are loading"
msgstr ""
msgid "Reports|Tool"
-msgstr ""
+msgstr "Outil"
msgid "Reports|Vulnerability"
msgstr "Vulnérabilité"
msgid "Reports|Vulnerability Name"
-msgstr ""
+msgstr "Nom de vulnérabilité"
msgid "Reports|metrics report"
-msgstr ""
+msgstr "rapport des métriques"
msgid "Reports|no changed test results"
msgstr "aucun résultat de test modifié"
msgid "Repositories"
-msgstr ""
+msgstr "Dépôts"
msgid "Repositories Analytics"
-msgstr ""
+msgstr "Analytiques des Dépôts"
msgid "RepositoriesAnalytics|Analyze repositories for projects in %{groupName}. Data doesn't include projects in subgroups. %{learnMoreLink}."
-msgstr ""
+msgstr "Analyser les dépôts des projets présents dans %{groupName}. Les données ne prennent pas en compte les projets situés dans les sous-groupes. %{learnMoreLink}."
msgid "RepositoriesAnalytics|Average Coverage by Job"
-msgstr ""
+msgstr "Couverture Moyenne par Tâche"
msgid "RepositoriesAnalytics|Average coverage"
-msgstr ""
+msgstr "Couverture moyenne"
msgid "RepositoriesAnalytics|Average test coverage"
-msgstr ""
+msgstr "Couverture de test moyenne"
msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
-msgstr ""
+msgstr "Couverture de Code : %{averageCoverage}"
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -33310,74 +33891,74 @@ msgid "RepositoriesAnalytics|Coverage Jobs"
msgstr ""
msgid "RepositoriesAnalytics|Download historic test coverage data"
-msgstr ""
+msgstr "Télécharger les données de couverture de test historisées"
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
-msgstr ""
+msgstr "Télécharger les données de couverture de test historisées (.csv)"
msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
-msgstr ""
+msgstr "Télécharger les données de couverture de test (.csv)"
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
-msgstr ""
+msgstr "Les Données de Couverture de Test Historisées sont disponibles en format brut (.csv) pour une analyse plus approfondie."
msgid "RepositoriesAnalytics|In the last day, %{metricValue} job has code coverage."
msgid_plural "RepositoriesAnalytics|In the last day, %{metricValue} jobs have code coverage."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Au cours du dernier jour, %{metricValue} tâche dispose d'une couverture de code."
+msgstr[1] "Au cours du dernier jour, %{metricValue} tâches disposent d'une couverture de code."
msgid "RepositoriesAnalytics|In the last day, %{metricValue} project in %{groupName} has code coverage enabled."
msgid_plural "RepositoriesAnalytics|In the last day, %{metricValue} projects in %{groupName} have code coverage enabled."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Au cours du dernier jour, la couverture de code est activée pour %{metricValue} projet de %{groupName}."
+msgstr[1] "Au cours du dernier jour, la couverture de code est activée pour %{metricValue} projets de %{groupName}."
msgid "RepositoriesAnalytics|In the last day, on average, %{metricValue} of all jobs are covered."
-msgstr ""
+msgstr "Au cours du dernier jour, en moyenne, %{metricValue} tâches sur la totalité sont couvertes."
msgid "RepositoriesAnalytics|Jobs with Coverage"
-msgstr ""
+msgstr "Tâches avec Couverture"
msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
-msgstr ""
+msgstr "Tâches avec Couverture : %{coverageCount}"
msgid "RepositoriesAnalytics|Last 30 days"
-msgstr ""
+msgstr "30 derniers jours"
msgid "RepositoriesAnalytics|Last Update"
-msgstr ""
+msgstr "Dernière mise à jour"
msgid "RepositoriesAnalytics|Last updated %{timeAgo}"
-msgstr ""
+msgstr "Dernière mise à jour %{timeAgo}"
msgid "RepositoriesAnalytics|Latest test coverage results"
-msgstr ""
+msgstr "Derniers résultats de la couverture de test"
msgid "RepositoriesAnalytics|Latest test coverage results for all projects in %{groupName} (excluding projects in subgroups)."
-msgstr ""
+msgstr "Derniers résultats de la couverture de test sur l'ensemble des projets de %{groupName} (en excluant les projets présents dans les sous-groupes)."
msgid "RepositoriesAnalytics|No test coverage to display"
-msgstr ""
+msgstr "Aucune couverture de test à afficher"
msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
-msgstr ""
+msgstr "Veuillez sélectionner un ou plusieurs projets pour afficher leurs données de couverture de test les plus récentes."
msgid "RepositoriesAnalytics|Please select projects to display."
-msgstr ""
+msgstr "Veuillez sélectionner les projets à afficher."
msgid "RepositoriesAnalytics|Projects with Coverage"
-msgstr ""
+msgstr "Projets avec Couverture"
msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
-msgstr ""
+msgstr "Projets avec Couverture : %{projectCount}"
msgid "RepositoriesAnalytics|Repositories Analytics"
-msgstr ""
+msgstr "Analyses des Dépôts"
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets."
msgid "Repository"
msgstr "Dépôt"
@@ -33392,10 +33973,10 @@ msgid "Repository Settings"
msgstr "Paramètres du dépôt"
msgid "Repository already read-only"
-msgstr ""
+msgstr "Dépôt déjà en lecture seule"
msgid "Repository by URL"
-msgstr ""
+msgstr "Dépôt par URL"
msgid "Repository check"
msgstr ""
@@ -33404,7 +33985,7 @@ msgid "Repository check was triggered."
msgstr ""
msgid "Repository checks"
-msgstr ""
+msgstr "Vérifications de dépôt"
msgid "Repository cleanup"
msgstr ""
@@ -33413,22 +33994,22 @@ msgid "Repository cleanup has started. You will receive an email once the cleanu
msgstr ""
msgid "Repository clone URL"
-msgstr ""
+msgstr "URL de clonage du dépôt"
msgid "Repository files count over the limit"
-msgstr ""
+msgstr "Le nombre de fichiers du dépôt dépasse la limite"
msgid "Repository has an invalid default branch name."
-msgstr ""
+msgstr "Le dépôt a un nom de branche par défaut non valide."
msgid "Repository has more than one branch."
-msgstr ""
+msgstr "Le dépôt a plus d'une branche."
msgid "Repository has no locks."
msgstr "Le dépôt n’a aucun verrou."
msgid "Repository has tags."
-msgstr ""
+msgstr "Le dépôt a des étiquettes."
msgid "Repository maintenance"
msgstr "Maintenance du dépôt"
@@ -33437,13 +34018,16 @@ msgid "Repository mirroring"
msgstr ""
msgid "Repository mirroring configuration"
+msgstr "Configuration de la mise en miroir du dépôt"
+
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
msgstr ""
msgid "Repository must contain at least 1 file."
-msgstr ""
+msgstr "Le dépôt doit contenir au moins 1 fichier."
msgid "Repository size is above the limit."
-msgstr ""
+msgstr "La taille du dépôt est supérieure à la limite."
msgid "Repository size limit (MB)"
msgstr ""
@@ -33452,13 +34036,13 @@ msgid "Repository storage"
msgstr "Stockage du dépôt"
msgid "Repository update events"
-msgstr ""
+msgstr "Événements de mise à jour du dépôt"
msgid "Repository usage recalculation started"
-msgstr ""
+msgstr "Le recalcul de l'utilisation du dépôt a démarré"
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 ""
+msgstr "Dépôt : %{counter_repositories} / Wikis: %{counter_wikis} / Artéfacts de Construction : %{counter_build_artifacts} / Artéfacts de Pipeline : %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Extraits : %{counter_snippets} / Paquets : %{counter_packages} / Téléversements : %{counter_uploads}"
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Sélectionner"
@@ -33473,13 +34057,13 @@ msgid "Request a new one"
msgstr ""
msgid "Request data is too large"
-msgstr ""
+msgstr "Les données de la requête sont trop volumineuses"
msgid "Request details"
-msgstr ""
+msgstr "Détails de la requête"
msgid "Request parameter %{param} is missing."
-msgstr ""
+msgstr "Le paramètre de requête %{param} est manquant."
msgid "Request review from"
msgstr ""
@@ -33491,40 +34075,40 @@ msgid "Request to link SAML account must be authorized"
msgstr ""
msgid "Requested"
-msgstr ""
+msgstr "Demandé"
msgid "Requested %{time_ago}"
-msgstr ""
+msgstr "Demandé %{time_ago}"
msgid "Requested design version does not exist."
-msgstr ""
+msgstr "La version de design demandée n'existe pas."
msgid "Requested review"
msgstr ""
msgid "Requested states are invalid"
-msgstr ""
+msgstr "Les états demandés sont invalides"
msgid "Requests"
-msgstr ""
+msgstr "Requêtes"
msgid "Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}"
-msgstr ""
+msgstr "Les requêtes pour les pages %{code_start}%{help_text_url}%{code_end} font une redirection vers l'URL. La destination doit répondre à certaines exigences. %{docs_link_start}En savoir plus.%{docs_link_end}"
msgid "Requests per period"
-msgstr ""
+msgstr "Demandes par période"
msgid "Require additional authentication for administrative tasks."
-msgstr ""
+msgstr "Exiger une authentification supplémentaire pour les tâches administratives."
msgid "Required approvals (%{approvals_given} given)"
-msgstr ""
+msgstr "Approbations requises (%{approvals_given} données)"
msgid "Required approvals (%{approvals_given} given, you've approved)"
-msgstr ""
+msgstr "Approbations requises (%{approvals_given} données, vous avez approuvé)"
msgid "Required in this project."
-msgstr ""
+msgstr "Requis dans ce projet."
msgid "Required only if you are not using role instance credentials."
msgstr ""
@@ -33533,25 +34117,25 @@ msgid "Requirement"
msgstr ""
msgid "Requirement %{reference} has been added"
-msgstr ""
+msgstr "L'exigence %{reference} a été ajoutée"
msgid "Requirement %{reference} has been archived"
-msgstr ""
+msgstr "L'exigence %{reference} a été archivée"
msgid "Requirement %{reference} has been reopened"
-msgstr ""
+msgstr "L'exigence %{reference} a été rouverte"
msgid "Requirement %{reference} has been updated"
-msgstr ""
+msgstr "L'exigence %{reference} a été mise à jour"
msgid "Requirement title cannot have more than %{limit} characters."
-msgstr ""
+msgstr "Le titre de l'exigence ne peut pas avoir plus de %{limit} caractères."
msgid "Requirements"
-msgstr ""
+msgstr "Exigences"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
-msgstr ""
+msgstr "Les exigences peuvent être basées sur les utilisateurs, les intervenants, le système, les logiciels ou tout autre élément dont la capture vous paraît importante."
msgid "Requires %d approval from eligible users."
msgid_plural "Requires %d approvals from eligible users."
@@ -33560,26 +34144,26 @@ msgstr[1] ""
msgid "Requires %{count} approval from %{names}."
msgid_plural "Requires %{count} approvals from %{names}."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Nécessite %{count} approbation de %{names}."
+msgstr[1] "Nécessite %{count} approbations de %{names}"
msgid "Requires values to meet regular expression requirements."
-msgstr ""
+msgstr "Nécessite des valeurs pour répondre aux exigences des expressions régulières."
msgid "Requires you to deploy or set up cloud-hosted Sentry."
-msgstr ""
+msgstr "Nécessite que vous déployiez ou configuriez Sentry dans le Cloud."
msgid "Requires your primary GitLab email address."
-msgstr ""
+msgstr "Nécessite votre adresse de courriel GitLab principale."
msgid "Resend"
-msgstr ""
+msgstr "Renvoyer"
msgid "Resend Request"
-msgstr ""
+msgstr "Renvoyer la Demande"
msgid "Resend confirmation e-mail"
-msgstr ""
+msgstr "Renvoyer le courriel de confirmation"
msgid "Resend confirmation email"
msgstr ""
@@ -33591,46 +34175,46 @@ msgid "Resend it"
msgstr ""
msgid "Resend unlock instructions"
-msgstr ""
+msgstr "Renvoyer les instructions de déverrouillage"
msgid "Reset"
-msgstr ""
+msgstr "Réinitialiser"
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "Réinitialiser le jeton d'accès du suivi des erreurs"
msgid "Reset file"
msgstr ""
msgid "Reset filters"
-msgstr ""
+msgstr "Réinitialiser les filtres"
msgid "Reset health check access token"
msgstr "Réinitialiser le jeton d’accès au bilan de santé"
msgid "Reset password"
-msgstr ""
+msgstr "Réinitialiser le mot de passe"
msgid "Reset registration token"
-msgstr ""
+msgstr "Réinitialiser le jeton d'inscription"
msgid "Reset template"
msgstr ""
msgid "Reset to project defaults"
-msgstr ""
+msgstr "Réinitialiser aux valeurs par défaut du projet"
msgid "Resolve"
msgstr ""
msgid "Resolve conflicts"
-msgstr ""
+msgstr "Résoudre les conflits"
msgid "Resolve conflicts on source branch"
msgstr "Résoudre les conflits sur la branche source"
msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
-msgstr ""
+msgstr "Résolvez ces conflits ou demandez à une personne disposant d'un accès en écriture sur ce référentiel de faire la fusion localement."
msgid "Resolve thread"
msgstr ""
@@ -33645,10 +34229,10 @@ msgid "Resolved all discussions."
msgstr ""
msgid "Resolved by"
-msgstr ""
+msgstr "Résolu par"
msgid "Resolved by %{name}"
-msgstr ""
+msgstr "Résolu par %{name}"
msgid "Response"
msgstr ""
@@ -33678,13 +34262,13 @@ msgid "Response text"
msgstr ""
msgid "Restart GitLab to apply changes."
-msgstr ""
+msgstr "Redémarrez GitLab pour appliquer les modifications."
msgid "Restart Terminal"
msgstr ""
msgid "Restore"
-msgstr ""
+msgstr "Restaurer"
msgid "Restore group"
msgstr ""
@@ -33693,22 +34277,22 @@ msgid "Restore project"
msgstr ""
msgid "Restoring projects"
-msgstr ""
+msgstr "Restauration des projets"
msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
-msgstr ""
+msgstr "La restauration du groupe empêchera le groupe, ses sous-groupes et les projets d'être supprimés à cette date."
msgid "Restoring the project will prevent the project from being removed on this date and restore people's ability to make changes to it."
-msgstr ""
+msgstr "La restauration du projet empêchera celui-ci d'être supprimé à cette date et rétablira la possibilité à des personnes d'y apporter des modifications."
msgid "Restrict access by IP address"
-msgstr ""
+msgstr "Restreindre l'accès selon l'adresse IP"
msgid "Restrict membership by email domain"
-msgstr ""
+msgstr "Restreindre l'adhésion par domaine de messagerie"
msgid "Restrict projects for this runner"
-msgstr ""
+msgstr "Restreindre les projets de cet exécuteur"
msgid "Restricted shift times are not available for hourly shifts"
msgstr ""
@@ -33717,25 +34301,25 @@ msgid "Resume"
msgstr "Reprendre"
msgid "Resync"
-msgstr ""
+msgstr "Resynchroniser"
msgid "Retrieving the compliance report failed. Refresh the page and try again."
-msgstr ""
+msgstr "La récupération du rapport de conformité a échoué. Actualisez la page et réessayez."
msgid "Retry"
msgstr "Réessayer"
msgid "Retry all failed or cancelled jobs"
-msgstr ""
+msgstr "Réessayer toutes les tâches échouées ou annulées"
msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
-msgstr ""
+msgstr "Relancer la tâche"
msgid "Retry migration"
-msgstr ""
+msgstr "Retenter la migration"
msgid "Retry this job"
msgstr "Relancer cette tâche"
@@ -33764,16 +34348,16 @@ msgid "Review"
msgstr "Examiner"
msgid "Review App|View app"
-msgstr ""
+msgstr "Voir l'application"
msgid "Review App|View latest app"
-msgstr ""
+msgstr "Voir la dernière application"
msgid "Review changes"
-msgstr ""
+msgstr "Examiner les modifications"
msgid "Review requests for you"
-msgstr ""
+msgstr "Demandes d'examen pour vous"
msgid "Review the changes locally."
msgstr ""
@@ -33782,27 +34366,27 @@ msgid "Review the process for configuring service providers in your identity pro
msgstr "Revoyez le processus de configuration des fournisseurs de service chez votre fournisseur d’identité — dans le cas présent, GitLab est le « fournisseur de service » ou le « tiers de confiance »."
msgid "Review the target project before submitting to avoid exposing %{source} changes."
-msgstr ""
+msgstr "Examinez le projet cible avant d'y publier quelque chose pour éviter d'exposer des modifications %{source}."
msgid "Review time"
-msgstr ""
+msgstr "Durée de revue"
msgid "Review time is defined as the time it takes from first comment until merged."
-msgstr ""
+msgstr "La durée de revue est définie comme le temps passé depuis le premier commentaire jusqu'à la fusion."
msgid "ReviewApp|Enable Review App"
-msgstr ""
+msgstr "Activer Review App"
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Relecteur"
+msgstr[1] "%d Relecteurs"
msgid "Reviewer(s)"
-msgstr ""
+msgstr "Relecteur(s)"
msgid "Reviewers"
-msgstr ""
+msgstr "Relecteurs"
msgid "Reviewing"
msgstr "Examen"
@@ -33825,11 +34409,14 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Copy email address"
+msgid "Rich text"
msgstr ""
+msgid "RightSidebar|Copy email address"
+msgstr "Copier l'adresse de courriel"
+
msgid "RightSidebar|Issue email"
-msgstr ""
+msgstr "Adresse de courriel du ticket"
msgid "Roadmap"
msgstr "Feuille de route"
@@ -33846,17 +34433,20 @@ msgstr ""
msgid "Rollback"
msgstr ""
-msgid "Ruby"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
msgstr ""
+msgid "Ruby"
+msgstr "Ruby"
+
msgid "Rule name is already taken."
-msgstr ""
+msgstr "Le nom de la règle est déjà pris."
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
-msgstr ""
+msgstr "Règles qui définissent quelles poussées git sont acceptées pour un projet de ce groupe. Tous les nouveaux projets de ce groupe utiliseront ces paramètres."
msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
-msgstr ""
+msgstr "Règles qui définissent quelles poussées git sont acceptées pour un projet. Tous les projets nouvellement créés utiliseront ces paramètres."
msgid "Run %{code_start}git fsck%{code_end} periodically in all project and wiki repositories to look for silent disk corruption issues."
msgstr ""
@@ -33865,16 +34455,16 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "Exécuter des pipelines CI / CD pour les dépôts externes"
msgid "Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}"
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec Jenkins lors des poussées vers un dépôt, ou quand une demande de fusion est créée, mise à jour ou fusionnée. %{docs_link}"
msgid "Run CI/CD pipelines with Jenkins."
-msgstr ""
+msgstr "Exécuter des pipelines CI/CD avec Jenkins."
msgid "Run housekeeping"
msgstr ""
msgid "Run manual or delayed jobs"
-msgstr ""
+msgstr "Exécuter des tâches manuelles ou différées"
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -33883,13 +34473,13 @@ msgid "Run untagged jobs"
msgstr "Exécuter les tâches non étiquetées"
msgid "Runner"
-msgstr ""
+msgstr "Exécuteur"
msgid "Runner API"
-msgstr ""
+msgstr "API Runner"
msgid "Runner tokens"
-msgstr ""
+msgstr "Jetons d’exécuteur"
msgid "Runner was not updated."
msgstr ""
@@ -33901,23 +34491,23 @@ msgid "Runners"
msgstr "Exécuteurs"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
-msgstr ""
+msgstr "Les exécuteurs sont des processus qui vont chercher des tâches CI/CD et les exécutent pour GitLab."
msgid "Runners page."
msgstr "Page des exécuteurs."
msgid "Runners|%d selected runner deleted"
msgid_plural "Runners|%d selected runners deleted"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exécuteur sélectionné supprimé"
+msgstr[1] "%d exécuteurs sélectionnés supprimés"
msgid "Runners|%{percentage} spot."
msgstr ""
msgid "Runners|%{strongStart}%{count}%{strongEnd} runner selected"
msgid_plural "Runners|%{strongStart}%{count}%{strongEnd} runners selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strongStart}%{count}%{strongEnd} exécuteur sélectionné"
+msgstr[1] "%{strongStart}%{count}%{strongEnd} exécuteurs sélectionnés"
msgid "Runners|%{strongStart}%{count}%{strongEnd} runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
msgid_plural "Runners|%{strongStart}%{count}%{strongEnd} runners will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
@@ -33928,64 +34518,64 @@ msgid "Runners|A capacity of 1 enables warm HA through Auto Scaling group re-spa
msgstr ""
msgid "Runners|A new version is available"
-msgstr ""
+msgstr "Une nouvelle version est disponible"
msgid "Runners|A periodic background task deletes runners that haven't contacted GitLab in more than %{elapsedTime}. %{linkStart}Can I view how many runners were deleted?%{linkEnd}"
-msgstr ""
+msgstr "Une tâche périodique en arrière-plan supprime les exécuteurs qui n'ont pas contacté GitLab dans plus de %{elapsedTime}. %{linkStart}Puis-je voir combien d'exécuteurs ont été supprimés ?%{linkEnd}"
msgid "Runners|Active"
-msgstr ""
+msgstr "Actif"
msgid "Runners|Add notes, like who owns the runner or what it should be used for."
-msgstr ""
+msgstr "Ajouter des notes, comme à qui appartient l'exécuteur ou à quoi il doit servir."
msgid "Runners|Add your feedback in the issue"
msgstr ""
msgid "Runners|All"
-msgstr ""
+msgstr "Tous"
msgid "Runners|All group runners that have not contacted GitLab in more than %{elapsedTime} are deleted permanently. This task runs periodically in the background."
-msgstr ""
+msgstr "Tous les exécuteurs de groupe qui n’ont pas contacté GitLab en plus de %{elapsedTime} sont supprimés définitivement. Cette tâche s’exécute périodiquement en arrière-plan."
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
-msgstr ""
+msgstr "Docker HA Amazon Linux 2 avec mise à l'échelle manuelle et planification facultative. Spot %{percentage}."
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot."
msgstr ""
msgid "Runners|An error has occurred fetching instructions"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des instructions"
msgid "Runners|An upgrade is available for this runner"
-msgstr ""
+msgstr "Une mise à jour est disponible pour cet exécuteur"
msgid "Runners|An upgrade is recommended for this runner"
-msgstr ""
+msgstr "Une mise à jour est recommandée pour cet exécuteur"
msgid "Runners|Architecture"
-msgstr ""
+msgstr "Architecture"
msgid "Runners|Assigned Group"
-msgstr ""
+msgstr "Groupe assigné"
msgid "Runners|Assigned Projects (%{projectCount})"
-msgstr ""
+msgstr "Projets assignés (%{projectCount})"
msgid "Runners|Associated with one or more projects"
-msgstr ""
+msgstr "Associé à un ou plusieurs projets"
msgid "Runners|Available"
-msgstr ""
+msgstr "Disponible"
msgid "Runners|Available to all projects"
-msgstr ""
+msgstr "Disponible pour tous les projets"
msgid "Runners|Available to all projects and subgroups in the group"
-msgstr ""
+msgstr "Disponible pour tous les projets et sous-groupes du groupe"
msgid "Runners|Can run untagged jobs"
-msgstr ""
+msgstr "Possibilité d'exécuter les tâches non étiquetées"
msgid "Runners|Capacity of 1 enables warm HA through Auto Scaling group re-spawn. Capacity of 2 enables hot HA because the service is available even when a node is lost. Capacity of 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
@@ -34000,19 +34590,19 @@ msgid "Runners|Clear selection"
msgstr ""
msgid "Runners|Command to register runner"
-msgstr ""
+msgstr "Commande pour enregistrer l'exécuteur"
msgid "Runners|Configuration"
-msgstr ""
+msgstr "Configuration"
msgid "Runners|Copy instructions"
-msgstr ""
+msgstr "Copier les instructions"
msgid "Runners|Copy registration token"
-msgstr ""
+msgstr "Copier le jeton d'inscription"
msgid "Runners|Created %{timeAgo}"
-msgstr ""
+msgstr "Créé %{timeAgo}"
msgid "Runners|Delete %d runner"
msgid_plural "Runners|Delete %d runners"
@@ -34020,109 +34610,112 @@ msgstr[0] ""
msgstr[1] ""
msgid "Runners|Delete runner"
-msgstr ""
+msgstr "Supprimer l’exécuteur"
msgid "Runners|Delete runner %{name}?"
-msgstr ""
+msgstr "Supprimer l'exécuteur %{name} ?"
msgid "Runners|Delete selected"
msgstr ""
msgid "Runners|Deploy GitLab Runner in AWS"
-msgstr ""
+msgstr "Déployer GitLab Runner sur AWS"
msgid "Runners|Description"
-msgstr ""
+msgstr "Description"
msgid "Runners|Details"
-msgstr ""
+msgstr "Détails"
msgid "Runners|Don't see what you are looking for? See the full list of options, including a fully customizable option %{linkStart}here%{linkEnd}."
-msgstr ""
+msgstr "Vous ne trouvez pas ce que vous cherchez ? Consultez la liste complète des options, incluant une option entièrement personnalisable %{linkStart}ici%{linkEnd}."
msgid "Runners|Download and install binary"
-msgstr ""
+msgstr "Télécharger et installer le binaire"
msgid "Runners|Download latest binary"
-msgstr ""
+msgstr "Télécharger le dernier binaire"
msgid "Runners|Edit your search and try again"
-msgstr ""
+msgstr "Modifiez votre recherche et réessayez"
msgid "Runners|Enable stale runner cleanup"
-msgstr ""
+msgstr "Activer le nettoyage des exécuteurs périmés"
msgid "Runners|Enable stale runner cleanup?"
-msgstr ""
+msgstr "Activer le nettoyage des exécuteurs périmés ?"
msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
-msgstr ""
+msgstr "Entrez le nombre de secondes. Ce délai d'expiration a la priorité sur les délais inférieurs définis pour le projet."
msgid "Runners|Executor"
-msgstr ""
+msgstr "Exécuteur"
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "Filtrer les projets"
msgid "Runners|Get started with runners"
-msgstr ""
+msgstr "Démarrez avec les exécuteurs"
msgid "Runners|Group"
+msgstr "Groupe"
+
+msgid "Runners|How do runners pick up jobs?"
msgstr ""
msgid "Runners|How do we upgrade GitLab runner?"
-msgstr ""
+msgstr "Comment mettons-nous à jour GitLab Runner ?"
msgid "Runners|IP Address"
-msgstr ""
+msgstr "Adresse IP"
msgid "Runners|Install a runner"
-msgstr ""
+msgstr "Installer un exécuteur"
msgid "Runners|Instance"
-msgstr ""
+msgstr "Instance"
msgid "Runners|Jobs"
-msgstr ""
+msgstr "Tâches"
msgid "Runners|Last contact"
-msgstr ""
+msgstr "Dernier contact"
msgid "Runners|Last contact: %{timeAgo}"
-msgstr ""
+msgstr "Dernier contact : %{timeAgo}"
msgid "Runners|Locked to this project"
-msgstr ""
+msgstr "Verrouillé sur ce projet"
msgid "Runners|Maintenance note"
-msgstr ""
+msgstr "Note de maintenance"
msgid "Runners|Maximum job timeout"
-msgstr ""
+msgstr "Délai d'expiration maximal des tâches"
msgid "Runners|Members of the %{type} can register runners"
-msgstr ""
-
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
+msgstr "Les membres du %{type} peuvent enregistrer des exécuteurs"
msgid "Runners|Name"
-msgstr ""
+msgstr "Nom"
msgid "Runners|Never contacted"
-msgstr ""
+msgstr "Jamais contacté"
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr "N'expire jamais"
+
msgid "Runners|New group runners view"
msgstr ""
msgid "Runners|New registration token generated!"
-msgstr ""
+msgstr "Nouveau jeton d’inscription généré !"
msgid "Runners|No results found"
-msgstr ""
+msgstr "Aucun résultat trouvé"
msgid "Runners|No spot. Default choice for Windows Shell executor."
msgstr ""
@@ -34131,86 +34724,92 @@ msgid "Runners|No spot. This is the default choice for Linux Docker executor."
msgstr ""
msgid "Runners|Not accepting jobs"
-msgstr ""
+msgstr "Tâches non acceptées"
msgid "Runners|Offline"
-msgstr ""
+msgstr "Hors ligne"
msgid "Runners|Offline:"
msgstr ""
msgid "Runners|Online"
-msgstr ""
+msgstr "En ligne"
msgid "Runners|Online:"
msgstr ""
msgid "Runners|Pause from accepting jobs"
-msgstr ""
+msgstr "Acceptation de tâches suspendue"
msgid "Runners|Paused"
-msgstr ""
+msgstr "En pause"
msgid "Runners|Permanently delete %d runner"
msgid_plural "Runners|Permanently delete %d runners"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Supprimer définitivement %d exécuteur"
+msgstr[1] "Supprimer définitivement %d exécuteurs"
msgid "Runners|Platform"
-msgstr ""
+msgstr "Plateforme"
msgid "Runners|Project"
-msgstr ""
+msgstr "Projet"
msgid "Runners|Property Name"
-msgstr ""
+msgstr "Nom de la propriété"
msgid "Runners|Protected"
-msgstr ""
+msgstr "Protégé"
msgid "Runners|Recommended"
-msgstr ""
+msgstr "Recommandé"
msgid "Runners|Register a group runner"
-msgstr ""
+msgstr "Enregistrer un exécuteur de groupe"
msgid "Runners|Register a project runner"
-msgstr ""
+msgstr "Enregistrer un exécuteur de projet"
msgid "Runners|Register a runner"
-msgstr ""
+msgstr "Enregistrer un exécuteur"
msgid "Runners|Register an instance runner"
+msgstr "Enregistrer un exécuteur d'instance"
+
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
msgstr ""
msgid "Runners|Registration token"
-msgstr ""
+msgstr "Jeton d'inscription"
msgid "Runners|Registration token copied!"
-msgstr ""
+msgstr "Jeton d'inscription copié !"
msgid "Runners|Reset token"
-msgstr ""
+msgstr "Réinitialiser le jeton"
msgid "Runners|Resume accepting jobs"
-msgstr ""
+msgstr "Reprendre l'acceptation de tâches"
msgid "Runners|Revision"
-msgstr ""
+msgstr "Révision"
msgid "Runners|Runner"
-msgstr ""
+msgstr "Exécuteur"
msgid "Runners|Runner #%{runner_id}"
-msgstr ""
+msgstr "Exécuteur #%{runner_id}"
msgid "Runners|Runner %{name} was deleted"
-msgstr ""
+msgstr "L'exécuteur %{name} a été supprimé"
msgid "Runners|Runner assigned to project."
-msgstr ""
+msgstr "Exécuteur assigné au projet."
+
+msgid "Runners|Runner authentication token expiration"
+msgstr "Expiration du jeton d'authentification de l'exécuteur"
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34220,7 +34819,7 @@ msgid "Runners|Runner has never contacted GitLab (when you register a runner, us
msgstr ""
msgid "Runners|Runner has never contacted this instance"
-msgstr ""
+msgstr "L'exécuteur n'a jamais contacté cette instance"
msgid "Runners|Runner has not contacted GitLab in more than %{elapsedTime}"
msgstr ""
@@ -34229,16 +34828,16 @@ msgid "Runners|Runner is locked and available for currently assigned projects on
msgstr ""
msgid "Runners|Runner is offline; last contact was %{runner_contact} ago"
-msgstr ""
+msgstr "L'exécuteur est hors-ligne ; le dernier contact était il y a %{runner_contact}"
msgid "Runners|Runner is offline; last contact was %{timeAgo}"
-msgstr ""
+msgstr "L'exécuteur est hors-ligne ; le dernier contact était %{timeAgo}"
msgid "Runners|Runner is online; last contact was %{runner_contact} ago"
-msgstr ""
+msgstr "L'exécuteur est en ligne ; le dernier contact était il y a %{runner_contact}"
msgid "Runners|Runner is online; last contact was %{timeAgo}"
-msgstr ""
+msgstr "L'exécuteur est en ligne ; le dernier contact était %{timeAgo}"
msgid "Runners|Runner is stale; it has never contacted this instance"
msgstr ""
@@ -34250,43 +34849,49 @@ msgid "Runners|Runner is stale; last contact was %{timeAgo}"
msgstr ""
msgid "Runners|Runner registration"
-msgstr ""
+msgstr "Enregistrement d'exécuteur"
msgid "Runners|Runner statuses"
-msgstr ""
+msgstr "États des exécuteurs"
msgid "Runners|Runner unassigned from project."
-msgstr ""
+msgstr "Exécuteur désassigné du projet."
msgid "Runners|Runners"
+msgstr "Exécuteurs"
+
+msgid "Runners|Runners are either:"
msgstr ""
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
-msgstr ""
+msgstr "Les exécuteurs sont les agents qui exécutent vos tâches CI/CD. Suivez les %{linkStart}instructions d'installation et d'enregistrement%{linkEnd} pour mettre en place un exécuteur."
msgid "Runners|Runs untagged jobs"
-msgstr ""
+msgstr "Exécute des tâches non marquées"
msgid "Runners|Select projects to assign to this runner"
-msgstr ""
+msgstr "Sélectionnez les projets à attribuer à cet exécuteur"
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
-msgid "Runners|Show runner installation and registration instructions"
+msgid "Runners|Show only inherited"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr "Afficher les instructions d'installation et d'enregistrement d'exécuteur"
+
msgid "Runners|Show runner installation instructions"
-msgstr ""
+msgstr "Afficher les instructions d'installation des exécuteurs"
msgid "Runners|Something went wrong while deleting. Please refresh the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression. Veuillez actualiser la page pour réessayer."
msgid "Runners|Something went wrong while fetching runner data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données des exécuteurs."
msgid "Runners|Something went wrong while fetching the tags suggestions"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des suggestions d'étiquettes"
msgid "Runners|Stale"
msgstr ""
@@ -34295,129 +34900,135 @@ msgid "Runners|Stale:"
msgstr ""
msgid "Runners|Status"
-msgstr ""
+msgstr "État"
msgid "Runners|Stop the runner from accepting new jobs."
-msgstr ""
+msgstr "Ne plus accepter de nouvelles tâches pour l'exécuteur."
msgid "Runners|Tags"
+msgstr "Étiquettes"
+
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
msgstr ""
msgid "Runners|Take me there!"
msgstr ""
msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
-msgstr ""
+msgstr "La nouvelle vue vous donne plus d'espace et une meilleure visibilité sur votre flotte d'exécuteurs."
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 ""
+msgstr "L'exécuteur sera définitivement supprimé et ne sera plus disponible pour les projets ou les groupes de l'instance. Êtes-vous sûr de vouloir continuer ?"
msgid "Runners|This group currently has 1 stale runner."
msgid_plural "Runners|This group currently has %d stale runners."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ce groupe a actuellement 1 exécuteur périmé."
+msgstr[1] "Ce groupe a actuellement %d exécuteurs périmés."
msgid "Runners|This group currently has no stale runners."
-msgstr ""
+msgstr "Ce groupe n'a actuellement aucun exécuteur périmé."
msgid "Runners|This runner has not run any jobs."
-msgstr ""
+msgstr "Cet exécuteur n'a exécuté aucune tâche."
msgid "Runners|This runner is associated with specific projects."
-msgstr ""
+msgstr "Cet exécuteur est associé à des projets spécifiques."
msgid "Runners|This runner is available to all projects and subgroups in a group."
-msgstr ""
+msgstr "Cet exécuteur est disponible pour tous les projets et sous-groupes d'un groupe."
msgid "Runners|This runner is outdated, an upgrade is recommended"
-msgstr ""
+msgstr "Cet exécuteur est obsolète, une mise à jour est recommandée"
msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
-msgstr ""
+msgstr "Pour installer Runner dans Kubernetes, suivez les instructions décrites dans la documentation de GitLab."
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
-msgstr ""
+msgstr "Pour installer Runner dans un conteneur, suivez les instructions décrites dans la documentation de GitLab"
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
-msgstr ""
+msgstr "Pour les enregistrer, allez sur la %{link_start}page des Exécuteurs du groupe%{link_end}."
+
+msgid "Runners|Token expiry"
+msgstr "Expiration du jeton"
msgid "Runners|Up to date"
-msgstr ""
+msgstr "À jour"
msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
-msgstr ""
+msgstr "Mettez à jour GitLab Runner pour correspondre à la version de GitLab que vous utilisez. Les %{linkStart}versions majeure et mineure%{linkEnd} doivent toutes deux correspondre."
msgid "Runners|Upgrade Status"
-msgstr ""
+msgstr "État de mise à niveau"
msgid "Runners|Upgrade available"
-msgstr ""
+msgstr "Mise à jour disponible"
msgid "Runners|Upgrade recommended"
-msgstr ""
+msgstr "Mise à jour recommandée"
msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
-msgstr ""
+msgstr "Utilisez les Exécuteurs de groupe quand vous souhaitez que tous les projets d'un groupe aient accès à un ensemble d'exécuteurs."
msgid "Runners|Use the runner for jobs without tags, in addition to tagged jobs."
-msgstr ""
+msgstr "Utiliser l'exécuteur pour les tâches sans étiquette, en plus des tâches étiquetées."
msgid "Runners|Use the runner for the currently assigned projects only. Only administrators can change the assigned projects."
msgstr ""
msgid "Runners|Use the runner on pipelines for protected branches only."
-msgstr ""
+msgstr "Utiliser l'exécuteur sur les pipelines pour les branches protégées uniquement."
msgid "Runners|Value"
-msgstr ""
+msgstr "Valeur"
msgid "Runners|Version"
-msgstr ""
+msgstr "Version"
msgid "Runners|Version %{version}"
-msgstr ""
+msgstr "Version %{version}"
msgid "Runners|View installation instructions"
-msgstr ""
+msgstr "Afficher les instructions d'installation"
msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
-msgstr ""
+msgstr "Nous voulons que vous puissiez gérer vos exécuteurs facilement et efficacement à partir de cette page, et nous apportons des modifications pour atteindre ce but. Donnez-nous votre avis sur ce que nous faisons !"
msgid "Runners|We've made some changes and want your feedback"
-msgstr ""
+msgstr "Nous avons apporté quelques modifications et souhaitons avoir votre avis"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
-msgstr ""
+msgstr "Shell Windows 2019 avec mise à l'échelle manuelle et planification facultative. Spot %{percentage}."
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot."
msgstr ""
msgid "Runners|Yes, start deleting stale runners"
-msgstr ""
+msgstr "Oui, commencer à supprimer les exécuteurs périmés"
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
-msgstr ""
+msgstr "Vous pouvez configurer un exécuteur spécifique pour une utilisation par plusieurs projets, mais vous ne pouvez pas en faire un exécuteur partagé."
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
msgid "Runners|active"
-msgstr ""
+msgstr "actif"
msgid "Runners|group"
-msgstr ""
+msgstr "groupe"
msgid "Runners|paused"
-msgstr ""
+msgstr "en pause"
msgid "Runners|shared"
-msgstr ""
+msgstr "partagé"
msgid "Runners|specific"
-msgstr ""
+msgstr "spécifique"
msgid "Runner|Owner"
-msgstr ""
+msgstr "Propriétaire"
msgid "Running"
msgstr "En cours d’exécution"
@@ -34426,7 +35037,7 @@ msgid "Runs a number of housekeeping tasks within the current repository, such a
msgstr ""
msgid "SAML"
-msgstr ""
+msgstr "SAML"
msgid "SAML SSO"
msgstr "Authentification unique SAML"
@@ -34435,34 +35046,34 @@ msgid "SAML SSO for %{group_name}"
msgstr "Authentification unique SAML pour %{group_name}"
msgid "SAML discovery tokens"
-msgstr ""
+msgstr "Jetons de découverte SAML"
msgid "SAML for %{group_name}"
msgstr ""
msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
-msgstr ""
+msgstr "Sélectionner « Autoriser » va transférer la propriété de votre compte GitLab « %{username} » (%{email}) à votre organisation."
msgid "SAML|Sign in to GitLab to connect your organization's account"
-msgstr ""
+msgstr "Connectez-vous à GitLab pour connecter le compte de votre organisation"
msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
-msgstr ""
+msgstr "Le groupe « %{group_path} » vous autorise à vous connecter avec votre compte SSO."
msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
-msgstr ""
+msgstr "Pour accéder à « %{group_name} », vous devez vous connecter avec votre compte SSO via une page de connexion externe."
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
-msgstr ""
+msgstr "Le SSO de votre organisation a été connecté à votre compte GitLab"
msgid "SAST Configuration"
-msgstr ""
+msgstr "Configuration SAST"
msgid "SHA256"
msgstr ""
msgid "SSH Fingerprints"
-msgstr ""
+msgstr "Empreintes SSH"
msgid "SSH Key"
msgstr ""
@@ -34471,10 +35082,10 @@ msgid "SSH Keys"
msgstr "Clefs SSH"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "Aide sur les clés SSH"
msgid "SSH fingerprints verify that the client is connecting to the correct host. Check the %{config_link_start}current instance configuration%{config_link_end}."
-msgstr ""
+msgstr "Les empreintes SSH garantissent que le client se connecte au bon hôte. Vérifiez la %{config_link_start}configuration de l'instance actuelle%{config_link_end}."
msgid "SSH host key fingerprints"
msgstr ""
@@ -34483,34 +35094,34 @@ msgid "SSH host keys"
msgstr "Clefs SSH de l’hôte"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
-msgstr ""
+msgstr "Les clés d'hôtes SSH ne sont pas disponibles sur ce système. Veuillez utiliser la commande %{ssh_keyscan} ou contacter votre administrateur GitLab pour plus d'informations."
msgid "SSH key"
-msgstr ""
+msgstr "Clé SSH"
msgid "SSH keys"
-msgstr ""
+msgstr "Clés SSH"
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
msgid "SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:"
-msgstr ""
+msgstr "Les clés SSH avec les empreintes suivantes vont bientôt arriver à expiration. Les clés SSH expirées ne peuvent pas être utilisées :"
msgid "SSH keys with the following fingerprints have expired and can no longer be used:"
-msgstr ""
+msgstr "Les clés SSH avec les empreintes suivantes ont expiré et ne peuvent plus être utilisées :"
msgid "SSH public key"
msgstr "Clef SSH publique"
msgid "SSL Verification:"
-msgstr ""
+msgstr "Vérification SSL :"
msgid "SSL verification"
-msgstr ""
+msgstr "Vérification SSL"
msgid "Sat"
-msgstr ""
+msgstr "Sam"
msgid "Satisfied"
msgstr ""
@@ -34537,13 +35148,13 @@ msgid "Save changes before testing"
msgstr "Enregistrer les modifications avant de tester"
msgid "Save comment"
-msgstr ""
+msgstr "Enregistrer le commentaire"
msgid "Save deploy freeze"
-msgstr ""
+msgstr "Enregistrer le gel de déploiement"
msgid "Save internal note"
-msgstr ""
+msgstr "Enregistrer la note interne"
msgid "Save password"
msgstr ""
@@ -34558,46 +35169,43 @@ msgid "Saving project."
msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
-msgstr ""
-
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
+msgstr "%{ifLabelStart}if%{ifLabelEnd} %{rules} actions pour les %{scopes} %{branches}"
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
-msgstr ""
+msgstr "%{period} %{days} à %{time}"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
-msgstr ""
+msgstr "%{thenLabelStart}Then%{thenLabelEnd} Nécessite une analyse %{scan} pour s'exécuter"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
msgstr ""
msgid "ScanExecutionPolicy|A pipeline is run"
-msgstr ""
+msgstr "Un pipeline est exécuté"
msgid "ScanExecutionPolicy|Scanner profile"
-msgstr ""
+msgstr "Profil de scanner"
msgid "ScanExecutionPolicy|Schedule"
-msgstr ""
+msgstr "Planification"
msgid "ScanExecutionPolicy|Schedule rule component"
-msgstr ""
+msgstr "Composant de règle de planification"
msgid "ScanExecutionPolicy|Select branches"
-msgstr ""
+msgstr "Sélectionnez des branches"
msgid "ScanExecutionPolicy|Select scanner profile"
-msgstr ""
+msgstr "Sélectionner un profil de scanner"
msgid "ScanExecutionPolicy|Select site profile"
-msgstr ""
+msgstr "Sélectionner un profil de site"
msgid "ScanExecutionPolicy|Site profile"
-msgstr ""
+msgstr "Profil de site"
msgid "ScanExecutionPolicy|branch"
-msgstr ""
+msgstr "branche"
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34606,31 +35214,31 @@ msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval fr
msgstr ""
msgid "ScanResultPolicy|add an approver"
-msgstr ""
+msgstr "ajouter un approbateur"
msgid "ScanResultPolicy|scanners"
-msgstr ""
+msgstr "analyseurs"
msgid "ScanResultPolicy|severity levels"
-msgstr ""
+msgstr "niveaux de gravité"
msgid "ScanResultPolicy|vulnerability states"
-msgstr ""
+msgstr "états de vulnérabilité"
msgid "Scanner"
-msgstr ""
+msgstr "Scanner"
msgid "Scanner profile failed to delete"
msgstr ""
msgid "Scanner profile not found for given parameters"
-msgstr ""
+msgstr "Profil de scanner introuvable pour les paramètres donnés"
msgid "Schedule a new pipeline"
msgstr "Planifier un nouveau pipeline"
msgid "Schedule-based escalation rules must have a schedule in the same project as the policy"
-msgstr ""
+msgstr "Les règles d'escalade basées sur un calendrier doivent avoir un calendrier dans le même projet que celui de la politique"
msgid "Scheduled"
msgstr "Planifié"
@@ -34639,19 +35247,19 @@ msgid "Scheduled Deletion At - %{permanent_deletion_time}"
msgstr ""
msgid "Scheduled a rebase of branch %{branch}."
-msgstr ""
+msgstr "Rebase de la branche %{branch} planifié."
msgid "Scheduled pipelines cannot run more frequently than once per %{limit} minutes. A pipeline configured to run more frequently only starts after %{limit} minutes have elapsed since the last time it ran."
-msgstr ""
+msgstr "Les pipelines planifiés ne peuvent pas être exécutés plus d'une fois toutes les %{limit} minutes. Un pipeline configuré pour s'exécuter plus souvent ne va démarrer qu'après que %{limit} minutes se soient écoulées depuis sa dernière exécution."
msgid "Scheduled to merge this merge request (%{strategy})."
-msgstr ""
+msgstr "Fusion de cette demande de fusion planifiée (%{strategy})."
msgid "Schedules"
msgstr "Planifications"
msgid "Schedules to merge this merge request (%{strategy})."
-msgstr ""
+msgstr "Planifie la fusion de cette demande de fusion (%{strategy})."
msgid "Scheduling Pipelines"
msgstr "Planification des pipelines"
@@ -34660,19 +35268,19 @@ msgid "Scope"
msgstr "Portée"
msgid "Scope board to current iteration"
-msgstr ""
+msgstr "Limiter la portée du tableau à l'itération actuelle"
msgid "Scopes"
msgstr ""
msgid "Scopes (select at least one)"
-msgstr ""
+msgstr "Portées (sélectionnez-en au moins une)"
msgid "Scopes can't be blank"
-msgstr ""
+msgstr "Les portées ne peuvent pas être vides"
msgid "Scopes: %{scope_list}"
-msgstr ""
+msgstr "Portées : %{scope_list}"
msgid "Scroll down"
msgstr ""
@@ -34699,17 +35307,20 @@ msgid "Search GitLab"
msgstr "Rechercher dans GitLab"
msgid "Search a group"
-msgstr ""
+msgstr "Rechercher un groupe"
msgid "Search an environment spec"
msgstr ""
msgid "Search assignees"
-msgstr ""
+msgstr "Rechercher des assigné(e)s"
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Rechercher des branches"
@@ -34717,16 +35328,16 @@ msgid "Search branches and tags"
msgstr "Rechercher dans les branches et les étiquettes"
msgid "Search branches, tags, and commits"
-msgstr ""
+msgstr "Rechercher des branches, tags et commits"
msgid "Search by Git revision"
-msgstr ""
+msgstr "Rechercher par révision Git"
msgid "Search by author"
-msgstr ""
+msgstr "Recherche par auteur·e"
msgid "Search by commit title or SHA"
-msgstr ""
+msgstr "Rechercher par titre de commit ou par SHA"
msgid "Search by message"
msgstr "Rechercher par message"
@@ -34738,7 +35349,7 @@ msgid "Search files"
msgstr "Rechercher des fichiers"
msgid "Search for Namespace"
-msgstr ""
+msgstr "Rechercher un Espace de noms"
msgid "Search for a LDAP group"
msgstr ""
@@ -34750,7 +35361,7 @@ msgid "Search for a user"
msgstr "Rechercher un utilisateur"
msgid "Search for an emoji"
-msgstr ""
+msgstr "Rechercher un emoji"
msgid "Search for projects, issues, etc."
msgstr "Rechercher des projets, des tickets, etc."
@@ -34762,13 +35373,13 @@ msgid "Search forks"
msgstr ""
msgid "Search groups"
-msgstr ""
+msgstr "Rechercher des groupes"
msgid "Search iterations"
-msgstr ""
+msgstr "Rechercher des itérations"
msgid "Search labels"
-msgstr ""
+msgstr "Rechercher des étiquettes"
msgid "Search merge requests"
msgstr "Rechercher des demandes de fusion"
@@ -34777,7 +35388,7 @@ msgid "Search milestones"
msgstr "Rechercher des jalons"
msgid "Search or create tag"
-msgstr ""
+msgstr "Rechercher ou créer une étiquette"
msgid "Search or filter results..."
msgstr "Rechercher ou filtrer les résultats…"
@@ -34786,7 +35397,7 @@ msgid "Search or filter results…"
msgstr ""
msgid "Search page"
-msgstr ""
+msgstr "Rechercher dans la page"
msgid "Search project"
msgstr "Rechercher des projets"
@@ -34797,6 +35408,9 @@ msgstr "Rechercher des projets"
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr "Rechercher des branches protégées"
+
msgid "Search rate limits"
msgstr ""
@@ -34816,7 +35430,7 @@ msgid "Search users or groups"
msgstr ""
msgid "Search your project dependencies for their licenses and apply policies."
-msgstr ""
+msgstr "Rechercher les licences dans les dépendances de votre projet et appliquer les stratégies."
msgid "Search your projects"
msgstr "Rechercher dans vos projets"
@@ -34852,16 +35466,16 @@ msgid "SearchCodeResults|of %{link_to_project}"
msgstr ""
msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "Affichage de %{count} %{scope} pour %{term_element}"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "Affichage de %{count} %{scope} pour %{term_element} dans vos extraits personnels et de projets"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "Affichage de %{from} - %{to} sur %{count} %{scope} pour %{term_element}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "Affichage de %{from} - %{to} sur %{count} %{scope} pour %{term_element} dans vos extraits personnels et de projets"
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
@@ -34880,8 +35494,8 @@ msgstr[1] ""
msgid "SearchResults|epic"
msgid_plural "SearchResults|epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "épopée"
+msgstr[1] "épopées"
msgid "SearchResults|issue"
msgid_plural "SearchResults|issues"
@@ -34895,8 +35509,8 @@ msgstr[1] ""
msgid "SearchResults|milestone"
msgid_plural "SearchResults|milestones"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "jalon"
+msgstr[1] "jalons"
msgid "SearchResults|project"
msgid_plural "SearchResults|projects"
@@ -34925,52 +35539,52 @@ msgid "SearchToken|Reviewer"
msgstr "Relecteur"
msgid "Searching by both author and message is currently not supported."
-msgstr ""
+msgstr "La recherche simultanée par auteur·e et par message n'est pas prise en charge actuellement."
msgid "Seats"
-msgstr ""
+msgstr "Sièges"
msgid "Seats owed"
msgstr ""
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
-msgstr ""
+msgstr "Données d'utilisation des sièges depuis le %{last_enqueue_time} (Actualisées chaque jour)"
msgid "Seats usage data is updated every day at 12:00pm UTC"
-msgstr ""
+msgstr "Les données d'utilisation des sièges sont actualisées chaque jour à 12h00 UTC"
msgid "Secondary email:"
-msgstr ""
+msgstr "Adresse de courriel secondaire :"
msgid "Seconds"
-msgstr ""
+msgstr "Secondes"
msgid "Secret"
msgstr "Secret"
msgid "Secret Detection"
-msgstr ""
+msgstr "Détection de secret"
msgid "Secret token"
-msgstr ""
+msgstr "Jeton secret"
msgid "Secure Code Warrior"
-msgstr ""
+msgstr "Secure Code Warrior"
msgid "Secure Files"
msgstr ""
msgid "Secure token that identifies an external storage request."
-msgstr ""
+msgstr "Jeton sécurisé qui identifie une requête de stockage externe."
msgid "SecureFiles|Delete %{name}?"
-msgstr ""
+msgstr "Supprimer %{name} ?"
msgid "SecureFiles|Delete secure file"
-msgstr ""
+msgstr "Supprimer le fichier sécurisé"
msgid "SecureFiles|Secure File %{name} will be permanently deleted. Are you sure?"
-msgstr ""
+msgstr "Le Fichier Sécurisé %{name} sera définitivement supprimé. Êtes-vous sûr ?"
msgid "Security"
msgstr "Sécurité"
@@ -34979,13 +35593,13 @@ msgid "Security & Compliance"
msgstr ""
msgid "Security Configuration"
-msgstr ""
+msgstr "Configuration de la sécurité"
msgid "Security Dashboard"
msgstr "Tableau de bord de sécurité"
msgid "Security Finding not found"
-msgstr ""
+msgstr "Découverte de Sécurité introuvable"
msgid "Security dashboard"
msgstr ""
@@ -34994,64 +35608,64 @@ msgid "Security navigation"
msgstr ""
msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
-msgstr ""
+msgstr "Le rapport de sécurité n'est pas à jour. Veuillez mettre à jour votre branche avec les derniers changements de la branche cible (%{targetBranchName})"
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
-msgstr ""
+msgstr "Le rapport de sécurité n'est pas à jour. Exécutez %{newPipelineLinkStart}un nouveau pipeline%{newPipelineLinkEnd} pour la branche cible (%{targetBranchName})"
msgid "SecurityApprovals|A merge request approval is required when test coverage declines."
-msgstr ""
+msgstr "Une approbation de demande de fusion est requise lorsque la couverture de tests diminue."
msgid "SecurityApprovals|A merge request approval is required when the license compliance report contains a denied license."
-msgstr ""
+msgstr "Une approbation de demande de fusion est requise lorsque le rapport de conformité de licence contient une licence refusée."
msgid "SecurityApprovals|Coverage-Check"
-msgstr ""
+msgstr "Vérification de Couverture"
msgid "SecurityApprovals|Learn more about Coverage-Check"
-msgstr ""
+msgstr "En savoir plus sur la Vérification de Couverture"
msgid "SecurityApprovals|Learn more about License-Check"
-msgstr ""
+msgstr "En savoir plus sur la Vérification de Licence"
msgid "SecurityApprovals|License-Check"
-msgstr ""
+msgstr "Vérification de Licence"
msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Nécessite une approbation pour les Licences refusées. %{linkStart}En savoir plus.%{linkEnd}"
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Nécessite une approbation en cas de diminution de la couverture de tests. %{linkStart}En savoir plus.%{linkEnd}"
msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
msgstr ""
msgid "SecurityConfiguration|%{scanType} configuration code snippet"
-msgstr ""
+msgstr "Extrait de code de configuration %{scanType}"
msgid "SecurityConfiguration|An error occurred while creating the merge request."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création de la demande de fusion."
msgid "SecurityConfiguration|Available with Ultimate"
-msgstr ""
+msgstr "Disponible avec 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."
-msgstr ""
+msgstr "Par défaut, tous les analyseurs sont appliqués afin de couvrir tous les langages de votre projet et ne s'exécutent que si le langage est détecté dans la demande de fusion."
msgid "SecurityConfiguration|Compliance"
-msgstr ""
+msgstr "Conformité"
msgid "SecurityConfiguration|Configuration guide"
-msgstr ""
+msgstr "Guide de configuration"
msgid "SecurityConfiguration|Configuration history"
-msgstr ""
+msgstr "Historique de la configuration"
msgid "SecurityConfiguration|Configure %{feature}"
-msgstr ""
+msgstr "Configurer %{feature}"
msgid "SecurityConfiguration|Configure with a merge request"
-msgstr ""
+msgstr "Configurer avec une demande de fusion"
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -35060,295 +35674,292 @@ msgid "SecurityConfiguration|Copy code only"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Impossible de récupérer les données de configuration. Veuillez actualiser la page ou réessayer plus tard."
msgid "SecurityConfiguration|Create merge request"
-msgstr ""
+msgstr "Créer une demande de fusion"
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
-msgstr ""
+msgstr "Personnalisez les paramètres communs de SAST pour répondre à vos besoins. Les paramètres qui seront modifiés ici prendront le dessus sur ceux fournis par GitLab et seront exclus des mises à jour. Pour les détails sur les options avancées de configuration, voir la %{linkStart}documentation SAST de GitLab%{linkEnd}."
msgid "SecurityConfiguration|Enable %{feature}"
-msgstr ""
+msgstr "Activer %{feature}"
msgid "SecurityConfiguration|Enable Auto DevOps"
-msgstr ""
+msgstr "Activer Auto DevOps"
msgid "SecurityConfiguration|Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
msgstr ""
msgid "SecurityConfiguration|Enabled"
-msgstr ""
+msgstr "Activé"
msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups"
-msgstr ""
+msgstr "Statistiques des vulnérabilités de haut niveau parmi les groupes et projets"
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 ""
+msgstr "Démarrez immédiatement l'analyse et la résolution des risques avec les fonctionnalités de sécurité des applications. Commencez avec SAST et la Détection de Secrets, disponibles dans tous les forfaits. Passez à Ultimate pour obtenir l'ensemble des fonctionnalités, notamment :"
msgid "SecurityConfiguration|Learn more about vulnerability training"
msgstr ""
msgid "SecurityConfiguration|Manage corpus"
-msgstr ""
+msgstr "Gestion de corpus"
msgid "SecurityConfiguration|Manage corpus files used as seed inputs with coverage-guided fuzzing."
msgstr ""
msgid "SecurityConfiguration|Manage profiles"
-msgstr ""
+msgstr "Gérer les profils"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
-msgstr ""
+msgstr "Gérer les profils utilisés par les analyses DAST."
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "Activer rapidement tous les outils de test continu et de conformité en activant %{linkStart}Auto DevOps%{linkEnd}"
msgid "SecurityConfiguration|Runtime security metrics for application environments"
-msgstr ""
+msgstr "Métriques de sécurité en cours d'exécution pour les environnements des applications"
msgid "SecurityConfiguration|SAST Analyzers"
-msgstr ""
+msgstr "Analyseurs SAST"
msgid "SecurityConfiguration|SAST Configuration"
-msgstr ""
+msgstr "Configuration SAST"
msgid "SecurityConfiguration|Secure your project"
-msgstr ""
+msgstr "Sécurisez votre projet"
msgid "SecurityConfiguration|Security testing"
-msgstr ""
+msgstr "Tests de sécurité"
msgid "SecurityConfiguration|Security training"
-msgstr ""
+msgstr "Formation à la sécurité"
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
-msgstr ""
+msgstr "L'état des outils ne s'applique qu'à la branche par défaut et se base sur le %{linkStart}dernier pipeline%{linkEnd}."
msgid "SecurityConfiguration|Upgrade or start a free trial"
msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
-msgstr ""
+msgstr "Utilisation de paramètres personnalisés. Vous ne recevrez pas de mises à jour automatiques sur cette variable. %{anchorStart}Restaurer la valeur par défaut%{anchorEnd}"
msgid "SecurityConfiguration|Vulnerability Management"
-msgstr ""
+msgstr "Gestion des Vulnérabilités"
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
-msgstr ""
+msgstr "Détails et statistiques de vulnérabilité de la demande de fusion"
msgid "SecurityOrchestration| and "
-msgstr ""
+msgstr "et "
msgid "SecurityOrchestration| or "
-msgstr ""
+msgstr " ou "
msgid "SecurityOrchestration|%{branches} %{plural}"
-msgstr ""
+msgstr "Les %{branches} %{plural}"
msgid "SecurityOrchestration|%{branches} and %{lastBranch} %{plural}"
-msgstr ""
+msgstr "Les %{branches} et %{lastBranch} %{plural}"
msgid "SecurityOrchestration|%{scanners}"
-msgstr ""
+msgstr "%{scanners}"
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
-msgstr ""
-
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
+msgstr "%{scanners} %{severities} dans une demande de fusion ouverte ciblant %{branches}."
msgid "SecurityOrchestration|, and %{count} more"
-msgstr ""
+msgstr ", et %{count} de plus"
msgid "SecurityOrchestration|.yaml mode"
-msgstr ""
+msgstr "mode .yaml"
msgid "SecurityOrchestration|.yaml preview"
-msgstr ""
+msgstr "Aperçu .yaml"
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "Actions"
msgid "SecurityOrchestration|Add action"
-msgstr ""
+msgstr "Ajouter une action"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "Ajouter une règle"
msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again."
-msgstr ""
+msgstr "Après avoir rejeté l'alerte, les informations ne seront plus réaffichées."
msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group."
-msgstr ""
+msgstr "Après avoir activé une stratégie au niveau du groupe, cette stratégie s'applique automatiquement à tous les projets et sous-groupes de ce groupe."
msgid "SecurityOrchestration|All policies"
-msgstr ""
+msgstr "Toutes les politiques"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'affectation de votre projet de politique de sécurité"
msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
-msgstr ""
+msgstr "Une erreur s'est produite en enlevant l'affectation de votre projet de politique de sécurité"
msgid "SecurityOrchestration|An error occurred while fetching the scan result policies."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des stratégies de résultats d’analyse."
msgid "SecurityOrchestration|Any scanner finds"
-msgstr ""
+msgstr "Un scanner quelconque trouve"
msgid "SecurityOrchestration|Are you sure you want to delete this policy? This action cannot be undone."
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer cette politique ? Cette action ne pourra pas être annulée."
msgid "SecurityOrchestration|Choose a project"
-msgstr ""
+msgstr "Choisir un projet"
msgid "SecurityOrchestration|Create more robust vulnerability rules and apply them to all your projects."
-msgstr ""
+msgstr "Créez des règles de vulnérabilité plus robustes et appliquez-les à tous vos projets."
msgid "SecurityOrchestration|Create policy"
-msgstr ""
+msgstr "Créer une politique"
msgid "SecurityOrchestration|Create security policy"
-msgstr ""
+msgstr "Créer une politique de sécurité"
msgid "SecurityOrchestration|Define this policy's location, conditions and actions."
-msgstr ""
+msgstr "Définir l’emplacement, les conditions et les actions de cette politique."
msgid "SecurityOrchestration|Delete policy"
-msgstr ""
+msgstr "Supprimer une politique"
msgid "SecurityOrchestration|Delete policy: %{policy}"
-msgstr ""
+msgstr "Supprimer la politique : %{policy}"
msgid "SecurityOrchestration|Description"
-msgstr ""
+msgstr "Description"
msgid "SecurityOrchestration|Direct"
-msgstr ""
+msgstr "Direct"
msgid "SecurityOrchestration|Don't show the alert anymore"
-msgstr ""
+msgstr "Ne plus afficher l'alerte"
msgid "SecurityOrchestration|Edit policy"
-msgstr ""
+msgstr "Modifier la politique"
msgid "SecurityOrchestration|Edit policy project"
-msgstr ""
+msgstr "Modifier le projet de politique"
msgid "SecurityOrchestration|Edit scan execution policy"
-msgstr ""
+msgstr "Modifier la stratégie d'exécution d'analyse"
msgid "SecurityOrchestration|Edit scan result policy"
-msgstr ""
+msgstr "Modifier la stratégie de résultat d'analyse"
msgid "SecurityOrchestration|Empty policy name"
-msgstr ""
+msgstr "Nom de politique vide"
msgid "SecurityOrchestration|Enabled"
-msgstr ""
+msgstr "Activée"
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
-msgstr ""
+msgstr "Forcer la sécurité pour ce projet. %{linkStart}Plus d’informations.%{linkEnd}"
msgid "SecurityOrchestration|Failed to load cluster agents."
-msgstr ""
+msgstr "Échec du chargement des agents de grappes de serveurs."
msgid "SecurityOrchestration|Failed to load images."
-msgstr ""
+msgstr "Échec du chargement des images."
msgid "SecurityOrchestration|Failed to load vulnerability scanners."
-msgstr ""
+msgstr "Échec du chargement des scanneurs de vulnérabilités."
msgid "SecurityOrchestration|If any scanner finds a newly detected critical vulnerability in an open merge request targeting the master branch, then require two approvals from any member of App security."
-msgstr ""
+msgstr "Si un scanner quelconque trouve une vulnérabilité critique récemment détectée dans une demande de fusion ouverte ciblant la branche maître, alors exiger deux approbations de tout membre de l'Appli sécurité."
msgid "SecurityOrchestration|Inherited"
-msgstr ""
+msgstr "Hérité"
msgid "SecurityOrchestration|Inherited from %{namespace}"
-msgstr ""
+msgstr "Héritée de %{namespace}"
msgid "SecurityOrchestration|Invalid policy type"
-msgstr ""
+msgstr "Type de politique non valide"
msgid "SecurityOrchestration|Latest scan run against %{agent}"
-msgstr ""
+msgstr "Dernière analyse exécutée avec %{agent}"
msgid "SecurityOrchestration|New policy"
-msgstr ""
+msgstr "Nouvelle politique"
msgid "SecurityOrchestration|New scan execution policy"
-msgstr ""
+msgstr "Nouvelle stratégie d'exécution d'analyse"
msgid "SecurityOrchestration|New scan result policy"
-msgstr ""
+msgstr "Nouvelle stratégie de résultats d'analyse"
msgid "SecurityOrchestration|No actions defined - policy will not run."
-msgstr ""
+msgstr "Aucune action définie - la politique ne sera pas exécutée."
msgid "SecurityOrchestration|No description"
-msgstr ""
+msgstr "Aucune description"
msgid "SecurityOrchestration|No rules defined - policy will not run."
-msgstr ""
+msgstr "Aucune règle définie - la politique ne sera pas exécutée."
msgid "SecurityOrchestration|Not enabled"
-msgstr ""
+msgstr "Non activée"
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
-msgstr ""
+msgstr "Seuls les propriétaires peuvent mettre à jour le Projet de Politique de Sécurité"
msgid "SecurityOrchestration|Policies"
-msgstr ""
+msgstr "Politiques"
msgid "SecurityOrchestration|Policy Type"
-msgstr ""
+msgstr "Type de Politique"
msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
-msgstr ""
+msgstr "La politique ne peut pas être activée pour les branches inexistantes (%{branches})"
msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
-msgstr ""
+msgstr "La stratégie ne peut pas être activée sans information de branche"
msgid "SecurityOrchestration|Policy definition"
msgstr ""
msgid "SecurityOrchestration|Policy editor"
-msgstr ""
+msgstr "Éditeur de politique"
msgid "SecurityOrchestration|Policy status"
-msgstr ""
+msgstr "État de la politique"
msgid "SecurityOrchestration|Policy type"
-msgstr ""
+msgstr "Type de politique"
msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
msgstr ""
msgid "SecurityOrchestration|Rule mode"
-msgstr ""
+msgstr "Mode Règle"
msgid "SecurityOrchestration|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
-msgstr ""
+msgstr "Le mode Règle n'est pas disponible pour cette stratégie. Dans certains cas, il n'est pas possible d'analyser le fichier YAML une fois de retour dans l'éditeur de règles."
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "Règles"
msgid "SecurityOrchestration|Run a DAST scan with Scan Profile A and Site Profile A when a pipeline run against the main branch."
-msgstr ""
+msgstr "Exécutez une analyse DAST avec le profil d'analyse A et le profil de site A lorsqu'un pipeline s'exécute sur la branche principale."
msgid "SecurityOrchestration|Runs %{actions} and %{lastAction} scans"
-msgstr ""
+msgstr "Exécute %{actions} et %{lastAction} analyses"
msgid "SecurityOrchestration|Runs a %{action} scan"
msgstr ""
@@ -35360,64 +35971,64 @@ msgid "SecurityOrchestration|Scan Execution"
msgstr ""
msgid "SecurityOrchestration|Scan Result"
-msgstr ""
+msgstr "Résultat de l'analyse"
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
-msgstr ""
+msgstr "Les politiques d'exécution d'analyse ne peuvent être créées que par des propriétaires du projet."
msgid "SecurityOrchestration|Scan execution policy"
-msgstr ""
+msgstr "Politique d'exécution d'analyse"
msgid "SecurityOrchestration|Scan result"
-msgstr ""
+msgstr "Résultat de l'analyse"
msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
-msgstr ""
+msgstr "Les stratégies de résultats d'analyse ne peuvent être créées que par les propriétaires du projet."
msgid "SecurityOrchestration|Scan result policy"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
-msgstr ""
+msgstr "Analyse à effectuer %{cadence}"
msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
-msgstr ""
+msgstr "Analyse à effectuer %{cadence} sur les %{branches}"
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
-msgstr ""
+msgstr "Analyse à effectuer sur chaque pipeline des %{branches}"
msgid "SecurityOrchestration|Security Approvals"
msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
-msgstr ""
+msgstr "Le projet de politique de sécurité a été lié avec succès"
msgid "SecurityOrchestration|Security policy project was unlinked successfully"
-msgstr ""
+msgstr "Le projet de politique de sécurité a été dissocié avec succès"
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
-msgstr ""
+msgstr "Sélectionnez un projet dans lequel stocker vos politiques de sécurité. %{linkStart}Plus d'informations.%{linkEnd}"
msgid "SecurityOrchestration|Select policy"
msgstr ""
msgid "SecurityOrchestration|Select security project"
-msgstr ""
+msgstr "Sélectionner un projet de sécurité"
msgid "SecurityOrchestration|Something went wrong, unable to fetch policies"
-msgstr ""
+msgstr "Une erreur s’est produite, impossible de récupérer les stratégies"
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche."
msgid "SecurityOrchestration|Source"
-msgstr ""
+msgstr "Source"
msgid "SecurityOrchestration|Status"
-msgstr ""
+msgstr "État"
msgid "SecurityOrchestration|Step 1: Choose a policy type"
msgstr ""
@@ -35426,79 +36037,79 @@ msgid "SecurityOrchestration|Step 2: Policy details"
msgstr ""
msgid "SecurityOrchestration|Summary"
-msgstr ""
+msgstr "Résumé"
msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all branches to ensure the values are accurate before updating this policy."
-msgstr ""
+msgstr "Les branches suivantes n'existent pas sur ce projet de développement : %{branches}. Veuillez examiner toutes les branches pour vous assurer de l'exactitude des valeurs avant de mettre à jour cette politique."
msgid "SecurityOrchestration|There was a problem creating the new security policy"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création de la nouvelle politique de sécurité"
msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
-msgstr ""
+msgstr "Ce %{namespaceType} ne contient aucune stratégie de sécurité."
msgid "SecurityOrchestration|This %{namespaceType} is not linked to a security policy project"
-msgstr ""
+msgstr "Ce %{namespaceType} n'est pas lié à un projet de politique de sécurité"
msgid "SecurityOrchestration|This group"
-msgstr ""
+msgstr "Ce groupe"
msgid "SecurityOrchestration|This is a group-level policy"
-msgstr ""
+msgstr "Il s'agit d'une stratégie au niveau du groupe"
msgid "SecurityOrchestration|This is a project-level policy"
-msgstr ""
+msgstr "Il s'agit d'une stratégie au niveau du projet"
msgid "SecurityOrchestration|This policy is inherited from %{namespace}"
-msgstr ""
+msgstr "Cette stratégie est héritée de %{namespace}"
msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
-msgstr ""
+msgstr "Cette stratégie est héritée de l'%{linkStart}espace de noms%{linkEnd} et doit être modifiée à son niveau"
msgid "SecurityOrchestration|This project"
-msgstr ""
+msgstr "Ce projet"
msgid "SecurityOrchestration|This view only shows scan results for the agent %{agent}. You can view scan results for all agents in the %{linkStart}Operational Vulnerabilities tab of the vulnerability report%{linkEnd}."
-msgstr ""
+msgstr "Cette vue n'affiche que les résultats d'analyse de l'agent %{agent}. Vous pouvez consulter les résultats d'analyse de tous les agents dans l'%{linkStart}onglet Vulnérabilités Opérationnelles du rapport de vulnérabilités%{linkEnd}."
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
-msgstr ""
+msgstr "Pour élargir votre recherche, modifiez les filtres ci-dessus ou sélectionnez un projet de politique de sécurité différent."
msgid "SecurityOrchestration|Unlink project"
-msgstr ""
+msgstr "Dissocier un projet"
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
-msgstr ""
+msgstr "Dissocier un projet de sécurité supprime toutes les politiques stockées dans le projet de sécurité lié. Enregistrez pour confirmer cette action."
msgid "SecurityOrchestration|Update scan policies"
-msgstr ""
+msgstr "Mettre à jour les politiques d'analyse"
msgid "SecurityOrchestration|Use a scan execution policy to create rules which enforce security scans for particular branches at a certain time. Supported types are SAST, DAST, Secret detection, and Container scanning."
-msgstr ""
+msgstr "Utilisez une stratégie d'exécution d'analyse pour créer des règles qui forcent les analyses de sécurité sur des branches particulières à un moment donné. Les types pris en charge sont SAST, DAST, Détection de Secret et analyse de Conteneur."
msgid "SecurityOrchestration|Use a scan result policy to create rules that ensure security issues are checked before merging a merge request."
-msgstr ""
+msgstr "Utilisez une stratégie de résultats d'analyse pour créer des règles qui garantissent que les problèmes de sécurité sont vérifiés avant de fusionner une demande de fusion."
msgid "SecurityOrchestration|View policy project"
-msgstr ""
+msgstr "Voir le projet de stratégie"
msgid "SecurityOrchestration|You don't have any security policies yet"
-msgstr ""
+msgstr "Vous n'avez pas encore de politique de sécurité"
msgid "SecurityOrchestration|a"
-msgstr ""
+msgstr "un(e)"
msgid "SecurityOrchestration|all branches"
-msgstr ""
+msgstr "toutes les branches"
msgid "SecurityOrchestration|an"
-msgstr ""
+msgstr "un(e)"
msgid "SecurityOrchestration|branch"
-msgstr ""
+msgstr "branche"
msgid "SecurityOrchestration|branches"
-msgstr ""
+msgstr "branches"
msgid "SecurityOrchestration|scanner finds"
msgstr ""
@@ -35507,49 +36118,49 @@ msgid "SecurityOrchestration|scanners find"
msgstr ""
msgid "SecurityOrchestration|the %{branches}"
-msgstr ""
+msgstr "les %{branches}"
msgid "SecurityOrchestration|vulnerabilities"
-msgstr ""
+msgstr "vulnérabilités"
msgid "SecurityOrchestration|vulnerability"
-msgstr ""
+msgstr "vulnérabilité"
msgid "SecurityReports|%{count} Selected"
-msgstr ""
+msgstr "%{count} sélectionnés"
msgid "SecurityReports|%{count}+ projects"
-msgstr ""
+msgstr "%{count}+ projets"
msgid "SecurityReports|%{firstProject} and %{secondProject}"
-msgstr ""
+msgstr "%{firstProject} et %{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
-msgstr ""
+msgstr "%{firstProject}, %{secondProject}, et %{rest}"
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
-msgstr ""
+msgstr "Ajouter ou supprimer des projets à surveiller dans la zone de sécurité. Les résultats des projets inclus dans cette liste seront présentés sur le tableau de bord de sécurité et dans le rapport de vulnérabilité."
msgid "SecurityReports|Add projects"
-msgstr ""
+msgstr "Ajouter des projets"
msgid "SecurityReports|All activity"
-msgstr ""
+msgstr "Toute l'activité"
msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
-msgstr ""
+msgstr "Bien qu'il soit rare de ne pas avoir de vulnérabilités, cela peut arriver. Vérifiez vos paramètres afin de vous assurer que vous avez configuré votre tableau de bord correctement."
msgid "SecurityReports|At GitLab, we're all about iteration and feedback. That's why we are reaching out to customers like you to help guide what we work on this year for Vulnerability Management. We have a lot of exciting ideas and ask that you assist us by taking a short survey %{boldStart}no longer than 10 minutes%{boldEnd} to evaluate a few of our potential features."
-msgstr ""
+msgstr "Chez GitLab, tout est question d'action et réaction. C'est pourquoi nous nous adressons aux clients tels que vous pour orienter cette année notre travail sur la Gestion des Vulnérabilités. Nous avons de très nombreuses idées passionnantes et vous demandons de nous accompagner en répondant à une brève enquête %{boldStart}qui ne prendra pas plus de 10 minutes%{boldEnd} pour évaluer quelques-unes de nos fonctionnalités potentielles."
msgid "SecurityReports|Change status"
-msgstr ""
+msgstr "Modifier l'état"
msgid "SecurityReports|Check the messages generated while parsing the following security reports, as they may prevent the results from being ingested by GitLab. Ensure the security report conforms to a supported %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
msgstr ""
msgid "SecurityReports|Cluster"
-msgstr ""
+msgstr "Grappe de serveurs"
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
msgstr ""
@@ -35558,154 +36169,166 @@ msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "Commentaire édité sur « %{vulnerabilityName} »"
msgid "SecurityReports|Configure security testing"
-msgstr ""
+msgstr "Configurer le test de sécurité"
msgid "SecurityReports|Create Jira issue"
-msgstr ""
+msgstr "Créer un ticket Jira"
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr "Détection"
+
msgid "SecurityReports|Development vulnerabilities"
-msgstr ""
+msgstr "Vulnérabilités de développement"
msgid "SecurityReports|Dismiss vulnerability"
-msgstr ""
+msgstr "Rejeter la vulnérabilité"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
-msgstr ""
+msgstr "« %{vulnerabilityName} » rejetée"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr "« %{vulnerabilityName} » rejetée. Désactivez le masquage des rejets pour l'afficher."
+
+msgid "SecurityReports|Does not have issue"
msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
msgid "SecurityReports|Download results"
-msgstr ""
+msgstr "Télécharger les résultats"
msgid "SecurityReports|Download scanned URLs"
-msgstr ""
+msgstr "Télécharger les URL analysées"
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
-msgstr ""
+msgstr "Soit vous n’avez pas la permission de voir ce tableau de bord, soit il n’a pas été configuré. Veuillez vérifier vos permissions avec votre administrateur ou vérifiez vos configurations de tableau de bord pour continuer."
msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
-msgstr ""
+msgstr "Assurez-vous que le %{trackingStart}suivi des tickets%{trackingEnd} est activé pour ce projet et que vous avez la %{permissionsStart}permission de créer de nouveaux tickets%{permissionsEnd}."
msgid "SecurityReports|Error fetching the vulnerabilities over time. Please check your network connection and try again."
-msgstr ""
+msgstr "Erreur lors de la récupération des vulnérabilités au cours du temps. Veuillez vérifier votre connexion réseau et réessayer."
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "Erreur lors de la récupération du nombre de vulnérabilités. Veuillez vérifier votre connexion réseau et réessayer."
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "Erreur lors de la récupération de la liste des vulnérabilités. Veuillez vérifier votre connexion réseau et réessayer."
msgid "SecurityReports|Error parsing security reports"
-msgstr ""
+msgstr "Erreur lors de l’analyse des rapports de sécurité"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr "Échec de l'obtention des informations de rapport de sécurité. Veuillez recharger la page ou réessayer plus tard."
+
+msgid "SecurityReports|Has issue"
msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
+msgstr "Image"
+
+msgid "SecurityReports|Issue"
msgstr ""
msgid "SecurityReports|Issue Created"
-msgstr ""
+msgstr "Ticket créé"
msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
-msgstr ""
+msgstr "Les tickets créés à partir d’une vulnérabilité ne peuvent pas être supprimés."
msgid "SecurityReports|Learn more about setting up your dashboard"
-msgstr ""
+msgstr "En savoir plus sur la configuration de votre tableau de bord"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
-msgstr ""
+msgstr "Gérer et suivre les vulnérabilités identifiées dans les projets de votre groupe.Celles-ci sont affichées ici lorsque les tests de sécurité sont configurés."
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
-msgstr ""
+msgstr "Gérer et suivre les vulnérabilités identifiées dans votre projet.Elles sont affichées ici lorsque les tests de sécurité sont configurés."
msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
-msgstr ""
+msgstr "Gérer et suivre les vulnérabilités identifiées dans les projets que vous avez sélectionnés.Les vulnérabilités des projets qui sont sélectionnés, et dont les tests de sécurité sont configurés, sont affichées ici."
msgid "SecurityReports|Maximum selected projects limit reached"
-msgstr ""
+msgstr "Limite maximale de projets sélectionnés atteinte"
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
-msgstr ""
+msgstr "Surveiller les vulnérabilités de tous vos projets"
msgid "SecurityReports|Monitor vulnerabilities in your group"
-msgstr ""
+msgstr "Surveiller les vulnérabilités de votre groupe"
msgid "SecurityReports|Monitor vulnerabilities in your project"
-msgstr ""
+msgstr "Surveiller les vulnérabilités de votre projet"
msgid "SecurityReports|Monitored projects"
-msgstr ""
+msgstr "Projets surveillés"
msgid "SecurityReports|More info"
-msgstr ""
+msgstr "Plus d’informations"
msgid "SecurityReports|No activity"
-msgstr ""
+msgstr "Aucune activité"
msgid "SecurityReports|No longer detected"
msgstr ""
msgid "SecurityReports|No vulnerabilities found"
-msgstr ""
+msgstr "Aucune vulnérabilité trouvée"
msgid "SecurityReports|No vulnerabilities found for this pipeline"
-msgstr ""
+msgstr "Aucune vulnérabilité trouvée pour ce pipeline"
msgid "SecurityReports|Oops, something doesn't seem right."
-msgstr ""
+msgstr "Oups, quelque chose semble ne pas s'être passé correctement."
msgid "SecurityReports|Operational vulnerabilities"
-msgstr ""
+msgstr "Vulnérabilités opérationnelles"
msgid "SecurityReports|Parsing errors and warnings in pipeline"
-msgstr ""
+msgstr "Analyse des erreurs et avertissements du pipeline"
msgid "SecurityReports|Parsing errors in pipeline"
-msgstr ""
+msgstr "Analyse des erreurs du pipeline"
msgid "SecurityReports|Parsing warnings in pipeline"
-msgstr ""
+msgstr "Analyse des avertissements du pipeline"
msgid "SecurityReports|Project"
-msgstr ""
+msgstr "Projet"
msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "Le projet n’a pas été trouvé ou vous n’avez pas la permission de l’ajouter aux Tableaux de bord de Sécurité."
msgid "SecurityReports|Projects added"
-msgstr ""
+msgstr "Projets ajoutés"
msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Report has expired"
-msgstr ""
+msgstr "Le rapport a expiré"
msgid "SecurityReports|Results show vulnerabilities introduced by the merge request, in addition to existing vulnerabilities from the latest successful pipeline in your project's default branch."
-msgstr ""
+msgstr "Les résultats montrent les vulnérabilités introduites par la demande de fusion, en plus des vulnérabilités existantes du dernier pipeline réussi dans la branche par défaut de votre projet."
msgid "SecurityReports|Scan details"
-msgstr ""
+msgstr "Détails de l'analyse"
msgid "SecurityReports|Security Dashboard"
-msgstr ""
+msgstr "Tableau de bord de sécurité"
msgid "SecurityReports|Security reports can only be accessed by authorized users."
-msgstr ""
+msgstr "Les rapports de sécurité ne peuvent être consultés que par les utilisateurs autorisés."
msgid "SecurityReports|Security reports help page link"
msgstr ""
@@ -35714,130 +36337,133 @@ msgid "SecurityReports|Security scans have run"
msgstr ""
msgid "SecurityReports|Select a project to add by using the project search field above."
-msgstr ""
+msgstr "Sélectionnez un projet à ajouter en utilisant le champ de recherche du projet ci-dessus."
msgid "SecurityReports|Set status"
msgstr ""
msgid "SecurityReports|Severity"
-msgstr ""
+msgstr "Gravité"
msgid "SecurityReports|Show %{pageSize} items"
msgstr "Afficher %{pageSize} éléments"
msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
-msgstr ""
+msgstr "Il peut parfois arriver qu'un scanner ne puisse pas déterminer la gravité de ce qu'il trouve. Ces éléments détectés peuvent pourtant toujours représenter une source potentielle de risque. Veuillez les examiner manuellement."
msgid "SecurityReports|Sorry, your filter produced no results"
msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche."
msgid "SecurityReports|Status"
+msgstr "État"
+
+msgid "SecurityReports|Still detected"
msgstr ""
msgid "SecurityReports|Submit vulnerability"
msgstr ""
msgid "SecurityReports|Take survey"
-msgstr ""
+msgstr "Participer à l'enquête"
msgid "SecurityReports|The Vulnerability Report shows results of successful scans on your project's default branch, manually added vulnerability records, and vulnerabilities found from scanning operational environments. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Le Rapport de Vulnérabilité montre les résultats des analyses réussies sur la branche par défaut de votre projet, les enregistrements des vulnérabilités ajoutées manuellement et les vulnérabilités trouvées à partir de l'analyse d'environnements opérationnels. %{linkStart}En savoir plus.%{linkEnd}"
msgid "SecurityReports|The following security reports contain one or more vulnerability findings that could not be parsed and were not recorded. To investigate a report, download the artifacts in the job output. Ensure the security report conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
-msgstr ""
+msgstr "Les rapports de sécurité suivants signalent la découverte d'une ou plusieurs vulnérabilités qui n'ont pas pu être traitées et qui n'ont pas été enregistrées. Pour étudier un rapport, téléchargez les artéfacts issus de la tâche. Assurez-vous que le rapport de sécurité est bien conforme au %{helpPageLinkStart}schéma JSON%{helpPageLinkEnd} approprié."
msgid "SecurityReports|The security report for this pipeline has %{helpPageLinkStart}expired%{helpPageLinkEnd}. Re-run the pipeline to generate a new security report."
-msgstr ""
+msgstr "Le rapport de sécurité de ce pipeline a %{helpPageLinkStart}expiré%{helpPageLinkEnd}. Relancez-le pour générer un nouveau rapport de sécurité."
msgid "SecurityReports|There was an error adding the comment."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l'ajout du commentaire."
msgid "SecurityReports|There was an error creating the issue."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création du ticket."
msgid "SecurityReports|There was an error creating the merge request."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création de la demande de fusion."
msgid "SecurityReports|There was an error deleting the comment."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la suppression du commentaire."
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
-msgstr ""
+msgstr "Une erreur s’est produite lors du rejet des vulnérabilités."
msgid "SecurityReports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "Une erreur s’est produite lors du rejet de la vulnérabilité."
msgid "SecurityReports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’annulation du rejet."
msgid "SecurityReports|There was an error reverting this dismissal."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’annulation de ce rejet."
msgid "SecurityReports|There was an error while generating the report."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la génération du rapport."
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 ""
+msgstr "Ces vulnérabilités ont été détectées dans des sources externes. Elles ne sont pas forcément liées à votre projet GitLab. Par exemple : conteneurs en cours d'exécution, URL, etc."
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr "Pour élargir votre recherche, modifiez ou supprimez les filtres ci-dessus"
msgid "SecurityReports|Tool"
-msgstr ""
+msgstr "Outil"
msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
-msgstr ""
+msgstr "Impossible d'ajouter %{invalidProjectsMessage} : %{errorMessage}"
msgid "SecurityReports|Undo dismiss"
-msgstr ""
+msgstr "Annuler le rejet"
msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
-msgstr ""
+msgstr "Mettez à niveau pour interagir, suivre et tester au plus tôt les vulnérabilités grâce à leurs fonctionnalités de gestion dans l'interface utilisateur."
msgid "SecurityReports|Upgrade to manage vulnerabilities"
-msgstr ""
+msgstr "Mettez à niveau pour gérer les vulnérabilités"
msgid "SecurityReports|Vulnerability Management feature survey"
-msgstr ""
+msgstr "Enquête sur la fonctionnalité de Gestion des Vulnérabilités"
msgid "SecurityReports|Vulnerability Report"
-msgstr ""
+msgstr "Rapport de vulnérabilité"
msgid "SecurityReports|Warning parsing security reports"
-msgstr ""
+msgstr "Avertissement lors de l'analyse des rapports de sécurité"
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 ""
+msgstr "Bien qu'il soit rare de ne pas avoir de vulnérabilité pour votre pipeline, cela peut se produire. Dans tous les cas, nous vous demandons de revérifier vos paramètres pour vous assurer que toutes les tâches d'analyse de sécurité se sont déroulées avec succès."
msgid "SecurityReports|With issues"
msgstr ""
msgid "SecurityReports|You do not have sufficient permissions to access this report"
-msgstr ""
+msgstr "Vous n’avez pas les autorisations suffisantes pour accéder à ce rapport"
msgid "SecurityReports|You must sign in as an authorized user to see this report"
-msgstr ""
+msgstr "Vous devez vous connecter en tant qu’utilisateur autorisé pour voir ce rapport"
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
-msgstr ""
+msgstr "Votre avis est important pour nous ! Nous vous le demanderons de nouveau dans une semaine."
msgid "SecurityReports|scanned resources"
-msgstr ""
+msgstr "ressources analysées"
msgid "SecurityTraining|Primary Training"
-msgstr ""
+msgstr "Formation primaire"
msgid "SecurityTraining|Training from this partner takes precedence when more than one training partner is enabled."
-msgstr ""
+msgstr "La formation provenant de ce partenaire est prioritaire lorsqu'il y a plus d'un partenaire de formation activé."
msgid "See example DevOps Score page in our documentation."
-msgstr ""
+msgstr "Voir l'exemple de page Score DevOps dans notre documentation."
msgid "See metrics"
msgstr ""
msgid "See our website for help"
-msgstr ""
+msgstr "Consultez notre site Web pour obtenir de l'aide"
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
@@ -35846,7 +36472,7 @@ msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
msgid "See vulnerability %{vulnerability_link} for any Solution details."
-msgstr ""
+msgstr "Voir la vulnérabilité %{vulnerability_link} pour tout détail de Solution."
msgid "Select"
msgstr "Sélectionner"
@@ -35857,20 +36483,17 @@ msgstr "Sélectionnez le format de l’archive"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
msgid "Select a branch"
-msgstr ""
+msgstr "Sélectionner une branche"
msgid "Select a branch to compare"
msgstr ""
msgid "Select a color"
-msgstr ""
+msgstr "Sélectionnez une couleur"
msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
msgstr ""
@@ -35891,10 +36514,10 @@ msgid "Select a project"
msgstr ""
msgid "Select a reason"
-msgstr ""
+msgstr "Choisissez un motif"
msgid "Select a repository containing templates for common files."
-msgstr ""
+msgstr "Sélectionnez un dépôt contenant les modèles des fichiers ordinaires."
msgid "Select a role"
msgstr ""
@@ -35903,22 +36526,19 @@ msgid "Select a template repository"
msgstr "Sélectionner un modèle de dépôt"
msgid "Select a template type"
-msgstr ""
-
-msgid "Select a time zone"
-msgstr ""
+msgstr "Sélectionner un type de modèle"
msgid "Select a timezone"
msgstr "Sélectionnez un fuseau horaire"
msgid "Select all"
-msgstr ""
+msgstr "Tout sélectionner"
msgid "Select an assignee"
msgstr "Sélectionnez un(e) assigné(e)"
msgid "Select an iteration"
-msgstr ""
+msgstr "Sélectionner une itération"
msgid "Select assignee"
msgstr "Sélectionner une personne assignée"
@@ -35929,14 +36549,20 @@ msgstr "Sélectionner une personne assignée"
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr "Sélectionnez une branche ou créez un joker"
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Sélectionner la date d'échéance"
msgid "Select epic"
-msgstr ""
+msgstr "Sélectionner une épopée"
msgid "Select group"
msgstr ""
@@ -35948,7 +36574,7 @@ msgid "Select health status"
msgstr ""
msgid "Select iteration"
-msgstr ""
+msgstr "Sélectionner une itération"
msgid "Select label"
msgstr "Sélectionnez une étiquette"
@@ -35969,7 +36595,7 @@ msgid "Select project"
msgstr "Sélectionner un projet"
msgid "Select project to create %{type}"
-msgstr ""
+msgstr "Sélectionnez un projet pour créer un(e) %{type}"
msgid "Select project to create issue"
msgstr "Sélectionner un projet pour créer un ticket"
@@ -35977,17 +36603,20 @@ msgstr "Sélectionner un projet pour créer un ticket"
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
msgid "Select source"
-msgstr ""
+msgstr "Sélectionner la source"
msgid "Select source branch"
msgstr "Sélectionner une branche source"
msgid "Select source project"
-msgstr ""
+msgstr "Sélectionner le projet source"
msgid "Select start date"
msgstr ""
@@ -35999,7 +36628,7 @@ msgid "Select strategy activation method"
msgstr ""
msgid "Select subgroup"
-msgstr ""
+msgstr "Sélectionner un sous-groupe"
msgid "Select subscription"
msgstr ""
@@ -36011,13 +36640,13 @@ msgid "Select target branch or tag"
msgstr ""
msgid "Select target project"
-msgstr ""
+msgstr "Sélectionnez le projet cible"
msgid "Select timezone"
msgstr ""
msgid "Select type"
-msgstr ""
+msgstr "Sélectionner le type"
msgid "Selected"
msgstr ""
@@ -36035,55 +36664,55 @@ msgid "Selected levels cannot be used by non-admin users for groups, projects or
msgstr ""
msgid "Selected tag is already in use. Choose another option."
-msgstr ""
+msgstr "L'étiquette sélectionnée est déjà utilisée. Faites un autre choix."
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "Sélectionner un utilisateur GitLab ajoutera un lien vers celui-ci dans la description et les commentaires des tickets (p. ex. « Par %{link_open}@johnsmith%{link_close} »). Cela associera également et/ou assignera ces tickets et ces commentaires à l'utilisateur sélectionné."
msgid "Self monitoring"
-msgstr ""
+msgstr "Auto-surveillance"
msgid "Self monitoring project does not exist"
-msgstr ""
+msgstr "Le projet d'auto-surveillance n'existe pas"
msgid "Self-monitoring project does not exist. Please check logs for any error messages"
-msgstr ""
+msgstr "Le projet d'auto-surveillance n'existe pas. Veuillez vérifier les messages d'erreur dans les journaux"
msgid "Self-monitoring project has been successfully deleted"
-msgstr ""
+msgstr "Le projet d'auto-surveillance a été supprimé avec succès"
msgid "Self-monitoring project was not deleted. Please check logs for any error messages"
-msgstr ""
+msgstr "Le projet d'auto-surveillance n'a pas été supprimé. Veuillez vérifier les messages d'erreur dans les journaux"
msgid "SelfMonitoring|Activate or deactivate instance self monitoring."
-msgstr ""
+msgstr "Activer ou désactiver l'auto-surveillance de l'instance."
msgid "SelfMonitoring|Activate self monitoring to create a project to use to monitor the health of your instance."
-msgstr ""
+msgstr "Activez l'auto-surveillance pour créer un projet à utiliser pour surveiller la santé de votre instance."
msgid "SelfMonitoring|Deactivate self monitoring?"
-msgstr ""
+msgstr "Désactiver l'auto-surveillance ?"
msgid "SelfMonitoring|Deactivating self monitoring deletes the self monitoring project. Are you sure you want to deactivate self monitoring and delete the project?"
-msgstr ""
+msgstr "La désactivation de l'auto-surveillance supprime le projet d'auto-surveillance. Voulez-vous vraiment désactiver l'auto-surveillance et supprimer le projet ?"
msgid "SelfMonitoring|Self monitoring"
-msgstr ""
+msgstr "Auto-surveillance"
msgid "SelfMonitoring|Self monitoring is active. Use the %{projectLinkStart}self monitoring project%{projectLinkEnd} to monitor the health of your instance."
-msgstr ""
+msgstr "L'auto-surveillance est active. Utilisez le %{projectLinkStart}projet d'auto-surveillance%{projectLinkEnd} pour surveiller la santé de votre instance."
msgid "SelfMonitoring|Self monitoring project successfully created."
-msgstr ""
+msgstr "Le projet d'auto-surveillance a été créé avec succès."
msgid "SelfMonitoring|Self monitoring project successfully deleted."
-msgstr ""
+msgstr "Le projet d’auto-surveillance a été supprimé avec succès."
msgid "Send"
-msgstr ""
+msgstr "Envoyer"
msgid "Send a single email notification to Owners and Maintainers for new alerts."
-msgstr ""
+msgstr "Envoyer un unique courriel de notification aux Propriétaires et aux Mainteneurs pour les nouvelles alertes."
msgid "Send confirmation email"
msgstr ""
@@ -36092,28 +36721,28 @@ msgid "Send email"
msgstr "Envoyer un courriel"
msgid "Send email in multipart format (HTML and plain text). Uncheck to send email messages in plain text only."
-msgstr ""
+msgstr "Envoyez des courriels au format multipart (HTML et texte brut). Décochez pour les envoyer en texte brut uniquement."
msgid "Send email notification"
-msgstr ""
+msgstr "Envoyer une notification par courriel"
msgid "Send emails to help guide new users through the onboarding process."
-msgstr ""
+msgstr "Envoyer des courriels pour contribuer à guider les nouveaux utilisateurs tout au long du processus d'intégration."
msgid "Send emails to users upon account deactivation."
-msgstr ""
+msgstr "Envoyer des courriels aux utilisateurs lors de la désactivation de compte."
msgid "Send message"
-msgstr ""
+msgstr "Envoyer un message"
msgid "Send notifications about project events to Mattermost channels."
-msgstr ""
+msgstr "Envoyer des notifications concernant les événements du projet vers des canaux Mattermost."
msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
-msgstr ""
+msgstr "Envoyer des notifications concernant les événements du projet vers des canaux Mattermost. %{docs_link}"
msgid "Send notifications about project events to a Discord channel. %{docs_link}"
-msgstr ""
+msgstr "Envoyer des notifications concernant les événements du projet vers un canal Discord. %{docs_link}"
msgid "Send report"
msgstr ""
@@ -36122,7 +36751,7 @@ msgid "Send service data"
msgstr ""
msgid "Sentry"
-msgstr ""
+msgstr "Sentry"
msgid "Sentry API URL"
msgstr ""
@@ -36140,10 +36769,10 @@ msgid "SeriesFinalConjunction|and"
msgstr ""
msgid "Serve repository static objects (for example, archives and blobs) from external storage."
-msgstr ""
+msgstr "Desservir les objets statiques du dépôt (archives et blobs par exemple) depuis un stockage externe."
msgid "Server (optional)"
-msgstr ""
+msgstr "Serveur (facultatif)"
msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
msgstr ""
@@ -36152,73 +36781,73 @@ msgid "Server version"
msgstr "Version du serveur"
msgid "Service"
-msgstr ""
+msgstr "Service"
msgid "Service Account"
-msgstr ""
+msgstr "Compte de Service"
msgid "Service Account Key"
-msgstr ""
+msgstr "Clé de Compte de Service"
msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
-msgstr ""
+msgstr "Les clés de Comptes de Service autorisent GitLab à déployer votre projet Google Cloud"
msgid "Service Desk"
msgstr "Service d’assistance"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
-msgstr ""
+msgstr "Le Service d'Assistance permet à l'utilisateur de créer des tickets sur votre instance GitLab sans qu'il n'ait besoin d'avoir son propre compte. Une adresse de courriel est fournie pour que les utilisateurs finaux créent des tickets sur un projet. Les réponses peuvent être envoyées soit via l'interface de GitLab, soit par courriel. Les utilisateurs finaux ne voient les fils de discussion qu'à travers les courriels."
msgid "Service Ping payload not found in the application cache"
-msgstr ""
+msgstr "Charge utile du Ping de Service introuvable dans le cache de l'application"
msgid "Service account generated successfully"
-msgstr ""
+msgstr "Compte de service généré avec succès"
msgid "Service accounts"
-msgstr ""
+msgstr "Comptes de service"
msgid "Service usage data"
msgstr ""
msgid "ServiceDesk|Enable Service Desk"
-msgstr ""
+msgstr "Activer le Service d'Assistance"
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr ""
+msgstr "Pour obtenir de l'aide sur la mise en place du Service d'Assistance sur votre instance, veuillez contacter un administrateur."
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
-msgstr ""
+msgstr "Les tickets créés à partir des courriels du Service d'Assistance apparaîtront ici. Chaque commentaire devient un élément de la discussion par courriel."
msgid "ServiceDesk|Service Desk is not enabled"
-msgstr ""
+msgstr "Le Service d'Assistance n'est pas activé"
msgid "ServiceDesk|Service Desk is not supported"
-msgstr ""
+msgstr "Le Service d'Assistance n'est pas pris en charge"
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
+msgstr "Pour activer le Service d'Assistance sur cette instance, un administrateur de celle-ci doit au préalable définir une adresse de courriel entrant."
msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
-msgstr ""
+msgstr "Utilisez le Service d'Assistance pour être en contact avec vos utilisateurs et proposer un support client par courriel directement dans GitLab"
msgid "ServiceDesk|Your users can send emails to this address:"
-msgstr ""
+msgstr "Vos utilisateurs peuvent envoyer des courriels à cette adresse :"
msgid "ServicePing|Service ping is off"
-msgstr ""
+msgstr "Le ping de service est désactivé"
msgid "ServicePing|To view instance-level analytics, ask an admin to turn on %{docLinkStart}service ping%{docLinkEnd}."
-msgstr ""
+msgstr "Pour afficher les données analytiques de niveau instance, demandez à un administrateur d'activer le %{docLinkStart}ping de service%{docLinkEnd}."
msgid "ServicePing|Turn on service ping"
-msgstr ""
+msgstr "Activer le ping de service"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
-msgstr ""
+msgstr "Activer le ping de service pour examiner les données analytiques de niveau instance."
msgid "Session ID"
-msgstr ""
+msgstr "ID de session"
msgid "Session duration (minutes)"
msgstr ""
@@ -36227,34 +36856,34 @@ msgid "Set %{epic_ref} as the parent epic."
msgstr ""
msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
-msgstr ""
+msgstr "Définir un modèle de description par défaut qui sera utilisé pour les nouveaux tickets. %{link_start}Que sont les modèles de description ?%{link_end}"
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Définissez un mot de passe pour votre compte afin de pouvoir récupérer ou pousser vos modification via %{protocol}."
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
-msgstr ""
+msgstr "Définissez une limitation de fréquence sur %{code_open}0%{code_close} pour la désactiver."
msgid "Set due date"
msgstr ""
msgid "Set health status"
-msgstr ""
+msgstr "Définir l'état de santé"
msgid "Set health status to %{health_status}."
-msgstr ""
+msgstr "Définir l'état de santé sur %{health_status}."
msgid "Set iteration"
msgstr ""
msgid "Set limit to 0 to allow any file size."
-msgstr ""
+msgstr "Définissez la limite sur 0 pour autoriser n'importe quelle taille de fichier."
msgid "Set limits for web and API requests."
-msgstr ""
+msgstr "Définir des limitations pour les requêtes Web et d'API."
msgid "Set milestone"
-msgstr ""
+msgstr "Définir un jalon"
msgid "Set new password"
msgstr ""
@@ -36263,13 +36892,13 @@ msgid "Set parent epic to an epic"
msgstr ""
msgid "Set per-user rate limits for imports and exports of projects and groups."
-msgstr ""
+msgstr "Définir des limitations de fréquence d'importations et d'exportations de projets ou groupes par utilisateur."
msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
msgstr ""
msgid "Set rate limits for package registry API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "Configurer des limitations de fréquence pour les requêtes à l'API du registre de paquets pour remplacer celles générales aux IP et utilisateurs."
msgid "Set rate limits for searches performed by web or API requests."
msgstr ""
@@ -36278,10 +36907,10 @@ msgid "Set severity"
msgstr ""
msgid "Set sign-in restrictions for all users."
-msgstr ""
+msgstr "Définir des restrictions de connexion pour tous les utilisateurs."
msgid "Set size limits for displaying diffs in the browser."
-msgstr ""
+msgstr "Définir les limitations de taille pour l'affichage des diffs dans le navigateur."
msgid "Set target branch"
msgstr ""
@@ -36289,29 +36918,32 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr "Définir à l'état Brouillon"
+
msgid "Set the Ready status"
msgstr ""
msgid "Set the default branch for this project. All merge requests and commits are made against this branch unless you specify a different one."
-msgstr ""
+msgstr "Définissez la branche par défaut de ce projet. Tous les commits et demandes de fusion seront effectués sur cette branche à moins que vous n'en spécifiez une autre."
msgid "Set the default expiration time for job artifacts in all projects. Set to %{code_open}0%{code_close} to never expire artifacts by default. If no unit is written, it defaults to seconds. For example, these are all equivalent: %{code_open}3600%{code_close}, %{code_open}60 minutes%{code_close}, or %{code_open}one hour%{code_close}."
-msgstr ""
+msgstr "Définir le délai d'expiration par défaut des artéfacts des tâches dans tous les projets. Mettre à %{code_open}0%{code_close} pour que les artéfacts n'expirent jamais par défaut. Si aucune unité n'est précisée, ce sera la seconde par défaut. Ces exemples sont tous équivalents : %{code_open}3600%{code_close}, %{code_open}60 minutes%{code_close} et %{code_open}une heure%{code_close}."
msgid "Set the due date to %{due_date}."
msgstr ""
msgid "Set the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "Définir le jalon à %{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 ""
+msgstr "Définit le nombre maximal de tranches autorisées à s'exécuter simultanément pendant la réindexation Elasticsearch. En savoir plus sur la %{max_slices_running_link_start}configuration du nombre maximal de tranches d'exécution%{max_slices_link_end}."
msgid "Set the maximum session time for a web terminal."
-msgstr ""
+msgstr "Définir la durée maximale de session pour un terminal Web."
msgid "Set the milestone to %{milestone_reference}."
-msgstr ""
+msgstr "Définir le jalon à %{milestone_reference}."
msgid "Set the per-user rate limit for getting a user by ID via the API."
msgstr ""
@@ -36320,7 +36952,7 @@ msgid "Set the per-user rate limit for notes created by web or API requests."
msgstr ""
msgid "Set this number to 0 to disable the limit."
-msgstr ""
+msgstr "Définissez ce nombre à 0 pour désactiver la limite."
msgid "Set time estimate"
msgstr ""
@@ -36329,7 +36961,7 @@ msgid "Set time estimate to %{time_estimate}."
msgstr ""
msgid "Set to 0 for no size limit."
-msgstr ""
+msgstr "Définir à 0 pour qu'il n'y ait pas de limite."
msgid "Set up CI/CD"
msgstr "Configuration CI/CD"
@@ -36338,16 +36970,16 @@ msgid "Set up Jira Integration"
msgstr ""
msgid "Set up a %{type} runner for a project"
-msgstr ""
+msgstr "Mettre en place un exécuteur %{type} pour un projet"
msgid "Set up a hardware device as a second factor to sign in."
-msgstr ""
+msgstr "Configurer un appareil matériel comme deuxième facteur pour se connecter."
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Configure les assertions, attributs et revendications (courriel, prénom et nom), ainsi que le NameID, conformément à %{docsLinkStart}la documentation %{icon}%{docsLinkEnd}"
msgid "Set up new device"
-msgstr ""
+msgstr "Configurer un nouvel appareil"
msgid "Set up new password"
msgstr ""
@@ -36356,7 +36988,7 @@ msgid "Set up your project to automatically push and/or pull changes to/from ano
msgstr "Configurez votre projet afin de pouvoir pousser et/ou récupérer automatiquement les modifications vers ou depuis un autre dépôt. Les branches, les étiquettes et les commits seront automatiquement synchronisés."
msgid "Set visibility of project contents. Configure import sources and Git access protocols."
-msgstr ""
+msgstr "Définir la visibilité du contenu du projet. Configurer les sources d'importation et les protocoles d'accès à Git."
msgid "Set weight"
msgstr ""
@@ -36364,17 +36996,14 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "Effacer l’état"
msgid "SetStatusModal|Clear status after"
-msgstr ""
+msgstr "Effacer l’état après"
+
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "Montre que vous êtes occupé ou dans l'impossibilité de répondre"
msgid "SetStatusModal|Edit status"
msgstr "Modifier l’état"
@@ -36388,23 +37017,26 @@ msgstr "Définir un état"
msgid "SetStatusModal|Set status"
msgstr "Définir l’état"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "Vous définir vous-même comme occupé"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Désolé, l’état n’a pas pu être défini. Veuillez réessayer ultérieurement."
msgid "SetStatusModal|Status updated"
-msgstr ""
+msgstr "État actualisé"
msgid "SetStatusModal|What's your status?"
msgstr "Quel est votre état ?"
msgid "SetStatusModal|Your status resets on %{date}."
-msgstr ""
+msgstr "Votre état est réinitialisé le %{date}."
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
msgid "Sets health status to %{health_status}."
-msgstr ""
+msgstr "Définit l'état de santé sur %{health_status}."
msgid "Sets target branch to %{branch_name}."
msgstr ""
@@ -36413,13 +37045,13 @@ msgid "Sets the due date to %{due_date}."
msgstr ""
msgid "Sets the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "Définit l'itération à %{iteration_reference}."
msgid "Sets the milestone to %{milestone_reference}."
-msgstr ""
+msgstr "Définit le jalon à %{milestone_reference}."
msgid "Sets the severity"
-msgstr ""
+msgstr "Définit la gravité"
msgid "Sets time estimate to %{time_estimate}."
msgstr ""
@@ -36431,42 +37063,42 @@ msgid "Setting"
msgstr ""
msgid "Setting enforced"
-msgstr ""
+msgstr "Paramètre imposé"
msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Paramètre enregistré avec succès"
+msgstr[1] "Paramètres enregistrés avec succès"
msgid "Settings"
msgstr "Paramètres"
msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
-msgstr ""
+msgstr "Impossible de charger les paramètres des options de demande de fusion. Essayez de recharger la page."
msgid "Setup"
-msgstr ""
+msgstr "Configuration"
msgid "Severity"
-msgstr ""
+msgstr "Gravité"
msgid "Severity updated to %{severity}."
-msgstr ""
+msgstr "Gravité mise à jour à %{severity}."
msgid "SeverityWidget|Severity"
-msgstr ""
+msgstr "Gravité"
msgid "SeverityWidget|Severity: %{severity}"
-msgstr ""
+msgstr "Gravité : %{severity}"
msgid "SeverityWidget|There was an error while updating severity."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de la gravité."
msgid "Share"
msgstr "Partager"
msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "Partagez l'%{strong_open}URL d'authentification unique GitLab%{strong_close} avec des membres pour qu'ils puissent se connecter à votre groupe par l'intermédiaire de votre fournisseur d'identité"
msgid "Shared Runners"
msgstr "Exécuteurs partagés"
@@ -36475,16 +37107,16 @@ msgid "Shared projects"
msgstr "Projets partagés"
msgid "Shared runners"
-msgstr ""
+msgstr "Exécuteurs partagés"
msgid "Shared runners are disabled for the parent group"
-msgstr ""
+msgstr "Les exécuteurs partagés du groupe parent sont désactivés"
msgid "Shared runners are disabled on group level"
-msgstr ""
+msgstr "Les exécuteurs partagés sont désactivés au niveau du groupe"
msgid "Shared runners details"
-msgstr ""
+msgstr "Détails des exécuteurs partagés"
msgid "Shared runners enabled cannot be enabled until a valid credit card is on file"
msgstr ""
@@ -36502,25 +37134,25 @@ msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "Réinitialiser les minutes du pipeline utilisées"
msgid "Shimo|Go to Shimo Workspace"
-msgstr ""
+msgstr "Aller sur l'Espace de travail Shimo"
msgid "Shimo|Link to a Shimo Workspace from the sidebar."
-msgstr ""
+msgstr "Lier un Espace de travail Shimo à la barre latérale."
msgid "Shimo|Shimo"
-msgstr ""
+msgstr "Shimo"
msgid "Shimo|Shimo Workspace"
-msgstr ""
+msgstr "Espace de travail Shimo"
msgid "Shimo|Shimo Workspace URL"
-msgstr ""
+msgstr "URL de l'Espace de travail Shimo"
msgid "Shimo|Shimo Workspace integration is enabled"
-msgstr ""
+msgstr "L'intégration de l'Espace de travail Shimo est activée"
msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
-msgstr ""
+msgstr "Vous avez activé l'intégration de l'Espace de travail Shimo. Vous pouvez voir votre wiki directement dans Shimo."
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -36529,7 +37161,7 @@ msgid "Show Pipeline ID"
msgstr ""
msgid "Show Pipeline IID"
-msgstr ""
+msgstr "Afficher l'IID de Pipeline"
msgid "Show all %{issuable_type}."
msgstr ""
@@ -36538,19 +37170,19 @@ msgid "Show all activity"
msgstr ""
msgid "Show all breadcrumbs"
-msgstr ""
+msgstr "Afficher tous les fils d'Ariane"
msgid "Show all epics"
-msgstr ""
+msgstr "Afficher toutes les épopées"
msgid "Show all issues."
-msgstr ""
+msgstr "Afficher tous les tickets."
msgid "Show all milestones"
-msgstr ""
+msgstr "Afficher tous les jalons"
msgid "Show all test cases."
-msgstr ""
+msgstr "Afficher tous les cas de test."
msgid "Show archived projects"
msgstr "Afficher les projets archivés"
@@ -36559,7 +37191,7 @@ msgid "Show archived projects only"
msgstr "Afficher uniquement les projets archivés"
msgid "Show closed epics"
-msgstr ""
+msgstr "Afficher les épopées fermées"
msgid "Show command"
msgstr "Afficher la commande"
@@ -36568,7 +37200,7 @@ msgid "Show comments"
msgstr ""
msgid "Show comments on this file"
-msgstr ""
+msgstr "Afficher les commentaires sur ce fichier"
msgid "Show comments only"
msgstr ""
@@ -36577,43 +37209,43 @@ msgid "Show complete raw log"
msgstr "Afficher le journal brut complet"
msgid "Show details"
-msgstr ""
+msgstr "Afficher les détails"
msgid "Show file browser"
msgstr ""
msgid "Show file contents"
-msgstr ""
+msgstr "Afficher le contenu du fichier"
msgid "Show group milestones"
-msgstr ""
+msgstr "Afficher les jalons de groupe"
msgid "Show labels"
-msgstr ""
+msgstr "Afficher les étiquettes"
msgid "Show latest version"
msgstr "Afficher la dernière version"
msgid "Show list"
-msgstr ""
+msgstr "Afficher la liste"
msgid "Show one file at a time"
-msgstr ""
+msgstr "Afficher un fichier à la fois"
msgid "Show open epics"
-msgstr ""
+msgstr "Afficher les épopées ouvertes"
msgid "Show project milestones"
-msgstr ""
+msgstr "Afficher les jalons du projet"
msgid "Show sub-group milestones"
-msgstr ""
+msgstr "Afficher les jalons du sous-groupe"
msgid "Show the Closed list"
-msgstr ""
+msgstr "Afficher la liste Fermé(e)s"
msgid "Show the Open list"
-msgstr ""
+msgstr "Afficher la liste Ouvert(e)s"
msgid "Show thread"
msgstr ""
@@ -36622,114 +37254,114 @@ msgid "Show whitespace changes"
msgstr "Afficher les modifications des espaces"
msgid "ShowcaseSecurity|Access a dedicated area for vulnerability management. This includes a security dashboard, vulnerability report, and settings."
-msgstr ""
+msgstr "Accéder à un espace dédié à la gestion des vulnérabilités. Il contient un tableau de bord sur la sécurité, un rapport de vulnérabilités et des paramètres."
msgid "ShowcaseSecurity|Audit your Docker-based app. Scan for known vulnerabilities in the Docker images where your code is shipped."
-msgstr ""
+msgstr "Auditer votre application basée sur Docker. Analyser le contenu des images Docker où votre code a été envoyé pour rechercher des vulnérabilités connues."
msgid "ShowcaseSecurity|Container scanning"
-msgstr ""
+msgstr "Analyse de conteneurs"
msgid "ShowcaseSecurity|Dependency scanning"
-msgstr ""
+msgstr "Analyse des dépendances"
msgid "ShowcaseSecurity|Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "Tests dynamiques de la sécurité des applications (DAST)"
msgid "ShowcaseSecurity|Dynamically examine your application for vulnerabilities in deployed environments."
-msgstr ""
+msgstr "Examinez dynamiquement votre application à la recherche de vulnérabilités dans les environnements déployés."
msgid "ShowcaseSecurity|Enable SAST"
-msgstr ""
+msgstr "Activer SAST"
msgid "ShowcaseSecurity|Enable Secret Detection"
-msgstr ""
+msgstr "Activer la détection de secrets"
msgid "ShowcaseSecurity|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "Activer les tests statiques de sécurité des applications (SAST)"
msgid "ShowcaseSecurity|Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
-msgstr ""
+msgstr "Découvrez si vos bibliothèques externes sont sûres. Lancez des tâches d'analyse de dépendances pour vérifier s'il y a des vulnérabilités connues dans vos bibliothèques externes."
msgid "ShowcaseSecurity|Identify vulnerabilities in your code now"
-msgstr ""
+msgstr "Identifiez maintenant les vulnérabilités de votre code"
msgid "ShowcaseSecurity|Scan your code to detect unintentionally committed secrets, like keys, passwords, and API tokens."
-msgstr ""
+msgstr "Analyser votre code pour détecter l'envoi accidentel de secrets, tels que des mots de passe, des clés ou des jetons d'API."
msgid "ShowcaseSecurity|Scan your source code using GitLab CI/CD and uncover vulnerabilities before deploying."
-msgstr ""
+msgstr "Analysez votre code source en utilisant GitLab CI/CD et découvrez les vulnérabilités avant d'effectuer le déploiement."
msgid "ShowcaseSecurity|Start a free 30-day Ultimate trial or upgrade your instance to access organization-wide security and compliance features. See the other features of the Ultimate plan."
-msgstr ""
+msgstr "Commencez une période d'essai Ultimate gratuite de 30 jours ou mettez à niveau votre instance pour accéder aux fonctionnalités de sécurité et de conformité à l'échelle de l'organisation. Voir les autres fonctionnalités du forfait Ultimate."
msgid "ShowcaseSecurity|Start a free trial"
-msgstr ""
+msgstr "Commencer un essai gratuit"
msgid "ShowcaseSecurity|Take your security to the next level"
-msgstr ""
+msgstr "Faites passer votre sécurité à un niveau supérieur"
msgid "ShowcaseSecurity|Upgrade now"
-msgstr ""
+msgstr "Mettre à niveau maintenant"
msgid "ShowcaseSecurity|Use GitLab CI/CD to analyze your source code for known vulnerabilities. Compare the found vulnerabilities between your source and target branches."
-msgstr ""
+msgstr "Utilisez GitLab CI/CD pour analyser votre code source à la recherche de vulnérabilités connues. Comparez les vulnérabilités trouvées entre vos branches source et cible."
msgid "ShowcaseSecurity|Vulnerability management"
-msgstr ""
+msgstr "Gestion des vulnérabilités"
msgid "Showing %{conflict}"
msgstr ""
msgid "Showing %{count} of %{total} projects"
-msgstr ""
+msgstr "Affichage de %{count} projets sur %{total}"
msgid "Showing %{count} project"
msgid_plural "Showing %{count} projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Affichage de %{count} projet"
+msgstr[1] "Affichage de %{count} projets"
msgid "Showing %{limit} of %{total_count} issues. "
-msgstr ""
+msgstr "Affichage de %{limit} tickets sur %{total_count}. "
msgid "Showing %{pageSize} of %{total} %{issuableType}"
-msgstr ""
+msgstr "Affichage de %{pageSize} %{issuableType} sur %{total}"
msgid "Showing all epics"
-msgstr ""
+msgstr "Affichage de toutes les épopées"
msgid "Showing all issues"
msgstr ""
msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
-msgstr ""
+msgstr "Affichage des données des éléments du flux de travail sur cette plage de dates. Celle-ci est limitée à %{maxDateRange} jours."
msgid "Showing graphs based on events of the last %{timerange} days."
-msgstr ""
+msgstr "Affichage des graphiques en fonction des événements des %{timerange} derniers jours."
msgid "Showing last %{size} of log -"
msgstr ""
msgid "Showing latest version"
-msgstr ""
+msgstr "Affichage de la dernière version"
msgid "Showing version #%{versionNumber}"
-msgstr ""
+msgstr "Affichage de la version #%{versionNumber}"
msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr ""
+msgstr "Affiche les tickets pour le groupe « %{group_name} » du 1er nov 2019 au 31 déc 2019"
msgid "Side-by-side"
msgstr "côte à côte"
msgid "Sidebar|%{name}: %{value}"
-msgstr ""
+msgstr "%{name} : %{value}"
msgid "Sidebar|Assign health status"
msgstr ""
msgid "Sidebar|Health status"
-msgstr ""
+msgstr "État de santé"
msgid "Sidebar|No status"
msgstr ""
@@ -36738,13 +37370,13 @@ msgid "Sidebar|None"
msgstr "Aucun"
msgid "Sidekiq job compression threshold (bytes)"
-msgstr ""
+msgstr "Seuil de compression des tâches Sidekiq (octets)"
msgid "Sidekiq job size limit (bytes)"
-msgstr ""
+msgstr "Limite de taille des tâches Sidekiq (octets)"
msgid "Sidekiq job size limits"
-msgstr ""
+msgstr "Limites de taille des tâches Sidekiq"
msgid "Sign in"
msgstr "Connexion"
@@ -36753,7 +37385,7 @@ msgid "Sign in / Register"
msgstr "Connexion / Inscription"
msgid "Sign in as a user with the matching email address, add the email to this account, or sign-up for a new account using the matching email."
-msgstr ""
+msgstr "Connectez-vous comme utilisateur avec l'adresse de courriel correspondante, ajoutez l'adresse à ce compte ou créez-un nouveau en utilisant l'adresse correspondante."
msgid "Sign in preview"
msgstr ""
@@ -36762,7 +37394,7 @@ msgid "Sign in to \"%{group_name}\""
msgstr ""
msgid "Sign in to GitLab"
-msgstr ""
+msgstr "Se connecter à GitLab"
msgid "Sign in using smart card"
msgstr ""
@@ -36771,7 +37403,7 @@ msgid "Sign in via 2FA code"
msgstr ""
msgid "Sign in with"
-msgstr ""
+msgstr "Connexion avec"
msgid "Sign in with Single Sign-On"
msgstr "Se connecter avec une authentification unique"
@@ -36780,7 +37412,7 @@ msgid "Sign in with smart card"
msgstr ""
msgid "Sign in/Sign up pages"
-msgstr ""
+msgstr "Pages de Connexion/Inscription"
msgid "Sign out"
msgstr "Se déconnecter"
@@ -36792,31 +37424,31 @@ msgid "Sign up"
msgstr ""
msgid "Sign up now"
-msgstr ""
+msgstr "S'inscrire maintenant"
msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
msgid "Sign-in and Help page"
-msgstr ""
+msgstr "Pages d'aide et de connexion"
msgid "Sign-in count:"
-msgstr ""
+msgstr "Nombre de connexions :"
msgid "Sign-in failed because %{error}."
-msgstr ""
+msgstr "La connexion a échoué car %{error}."
msgid "Sign-in page"
-msgstr ""
+msgstr "Page de connexion"
msgid "Sign-in restrictions"
msgstr "Restrictions de connexion"
msgid "Sign-in text"
-msgstr ""
+msgstr "Texte de connexion"
msgid "Sign-in using %{provider} auth failed"
-msgstr ""
+msgstr "La connexion via l'authentification de %{provider} a échoué"
msgid "Sign-out page URL"
msgstr ""
@@ -36825,34 +37457,34 @@ msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the GitLab%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "En cliquant sur %{button_text} ou en s'inscrivant via un service tiers, vous acceptez les %{link_start} Conditions d'Utilisation et reconnaissez avoir pris connaissance de la Politique de Confidentialité et de la Politique de gestion des cookies%{link_end} de GitLab."
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "En cliquant sur %{button_text} ou en s'inscrivant via un service tiers, vous acceptez les %{link_start} Conditions d'Utilisation et reconnaissez avoir pris connaissance de la Politique de Confidentialité et de la Politique de gestion des cookies%{link_end}"
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
-msgstr ""
+msgstr "En cliquant sur %{button_text}, je reconnais avoir lu et accepté les %{link_start}Conditions Générales d'Utilisation et Politique de Confidentialité%{link_end}"
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
-msgstr ""
+msgstr "En cliquant sur %{button_text}, je reconnais avoir lu et accepté les %{link_start}Conditions Générales d'Utilisation et Politique de Confidentialité%{link_end} de GitLab"
msgid "SignUp|By signing in you accept the %{link_start}Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}."
msgstr ""
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "Le prénom est trop long (le maximum est de %{max_length} caractères)."
msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "Le nom de famille est trop long (le maximum est de %{max_length} caractères)."
msgid "SignUp|Minimum length is %{minimum_password_length} characters."
-msgstr ""
+msgstr "La longueur minimale est de %{minimum_password_length} caractères."
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr ""
msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
-msgstr ""
+msgstr "Le nom d'utilisateur est trop court (le minimum est de %{min_length} caractères)."
msgid "Signed in"
msgstr ""
@@ -36876,37 +37508,37 @@ msgid "Similar issues"
msgstr ""
msgid "Simulate a pipeline created for the default branch"
-msgstr ""
+msgstr "Simuler un pipeline créé pour la branche par défaut"
msgid "Site profile failed to delete"
msgstr ""
msgid "Site profile not found for given parameters"
-msgstr ""
+msgstr "Profil de site introuvable pour les paramètres donnés"
msgid "Sites"
-msgstr ""
+msgstr "Sites"
msgid "Size"
msgstr "Taille"
msgid "Size Limits"
-msgstr ""
+msgstr "Limitations des Tailles"
msgid "Size limit per repository (MB)"
msgstr ""
msgid "Skip outdated deployment jobs"
-msgstr ""
+msgstr "Ignorer les tâches de déploiement dépassées"
msgid "Skipped"
msgstr ""
msgid "Skipped deployment to"
-msgstr ""
+msgstr "Omission du déploiement vers"
msgid "Skype:"
-msgstr ""
+msgstr "Skype :"
msgid "Slack application"
msgstr "Application Slack"
@@ -36915,82 +37547,115 @@ msgid "Slack integration allows you to interact with GitLab via slash commands i
msgstr "L’intégration de Slack permet d’interagir avec GitLab via des commandes slash dans une fenêtre de messagerie instantanée."
msgid "Slack logo"
-msgstr ""
+msgstr "Logo Slack"
msgid "SlackIntegration|Are you sure you want to remove this project from the Slack application?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer ce projet de l'application Slack ?"
msgid "SlackIntegration|Client ID"
-msgstr ""
+msgstr "ID client"
msgid "SlackIntegration|Client secret"
msgstr ""
msgid "SlackIntegration|GitLab for Slack"
-msgstr ""
+msgstr "GitLab pour Slack"
msgid "SlackIntegration|GitLab for Slack was successfully installed."
-msgstr ""
+msgstr "GitLab pour Slack a été installé avec succès."
msgid "SlackIntegration|Install Slack app"
-msgstr ""
+msgstr "Installer l'application Slack"
msgid "SlackIntegration|Project alias"
-msgstr ""
+msgstr "Alias du projet"
msgid "SlackIntegration|Reinstall Slack app"
-msgstr ""
+msgstr "Réinstaller l'application Slack"
msgid "SlackIntegration|Remove project"
-msgstr ""
+msgstr "Supprimer le projet"
msgid "SlackIntegration|See the list of available commands in Slack after setting up this integration by entering"
-msgstr ""
+msgstr "Voir la liste des commandes disponibles dans Slack après avoir configuré cette intégration, en entrant"
msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
-msgstr ""
+msgstr "Sélectionnez un projet GitLab à relier à votre espace de travail Slack."
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
-msgstr ""
+msgstr "Envoie des notifications sur les événements du projet vers des canaux Slack."
msgid "SlackIntegration|Signing secret"
-msgstr ""
+msgstr "Clé de signature"
msgid "SlackIntegration|Team name"
-msgstr ""
+msgstr "Nom de l'équipe"
msgid "SlackIntegration|This integration allows users to perform common operations on this project by entering slash commands in Slack."
-msgstr ""
+msgstr "Cette intégration permet aux utilisateurs d'effectuer des opérations courantes sur ce projet en entrant des commandes barre oblique dans Slack."
msgid "SlackIntegration|Verification token"
-msgstr ""
+msgstr "Jeton de vérification"
msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
-msgstr ""
+msgstr "Vous pouvez à présent fermer cette fenêtre et rejoindre votre espace de travail Slack."
msgid "SlackIntegration|You may need to reinstall the Slack application when we %{linkStart}make updates or change permissions%{linkEnd}."
msgstr ""
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
-msgstr ""
+msgstr "1. %{slash_command_link_start}Ajoutez une commande barre oblique%{slash_command_link_end} dans votre équipe Slack avec cette information :"
msgid "SlackService|2. Paste the token from Slack in the %{strong_open}Token%{strong_close} field below."
-msgstr ""
+msgstr "2. Collez le jeton issu de Slack dans le champ %{strong_open}Jeton%{strong_close} ci-dessous."
msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, select %{strong_open}Save changes%{strong_close}, and start using slash commands in Slack!"
-msgstr ""
+msgstr "3. Cochez la case %{strong_open}Actif%{strong_close}, sélectionnez %{strong_open}Enregistrer les modifications%{strong_close} et commencez à utiliser les commandes barre oblique dans Slack !"
msgid "SlackService|After setup, get a list of available Slack slash commands by entering"
-msgstr ""
+msgstr "Après la configuration, obtenez une liste des commandes barre oblique de Slack disponibles en entrant"
msgid "SlackService|Fill in the word that works best for your team."
msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
-msgstr ""
+msgstr "Effectuez des opérations courantes sur ce projet en entrant des commandes barre oblique dans Slack."
+
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr "%{asterisk}Étape 1.%{asterisk} Connectez-vous à votre compte GitLab pour commencer."
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr "%{asterisk}Étape 2.%{asterisk} Essayez !"
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr "%{emoji}Connecté au compte GitLab %{account}"
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr "%{emoji}Bienvenue dans GitLab pour Slack !"
+
+msgid "Slack|Connect your GitLab account"
+msgstr "Connecter à votre compte GitLab"
+
+msgid "Slack|Create a new issue"
+msgstr "Créer un nouveau ticket"
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr "Créer de nouveaux tickets à partir de Slack : %{command}"
+
+msgid "Slack|Run a CI/CD job"
+msgstr "Exécuter une tâche CI/CD"
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr "Voir une liste des commandes disponibles : %{command})"
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr "Rationalisez vos déploiements GitLab avec ChatOps. Une fois vos %{startMarkup}pipelines CI/CD%{endMarkup} configurés, essayez : %{command}"
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr "Afficher et contrôler le contenu GitLab pendant que vous travaillez sur Slack. Tapez la commande en tant que message dans votre client de chat pour l'activer. %{startMarkup}En savoir plus%{endMarkup}."
msgid "Slice multiplier"
-msgstr ""
+msgstr "Multiplicateur de tranches"
msgid "Smartcard"
msgstr "Carte à puce"
@@ -36999,19 +37664,19 @@ msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "L’authentification par carte à puce a échoué : un enâ€tête de certificat client est manquant."
msgid "Snippet"
-msgstr ""
+msgstr "Extrait"
msgid "Snippets"
msgstr "Extraits de code"
msgid "Snippets with non-text files can only be edited via Git."
-msgstr ""
+msgstr "Les extraits contenant des fichiers non textuels ne peuvent être édités que via Git."
msgid "SnippetsEmptyState|Code snippets"
-msgstr ""
+msgstr "Extraits de code"
msgid "SnippetsEmptyState|Documentation"
-msgstr ""
+msgstr "Documentation"
msgid "SnippetsEmptyState|New snippet"
msgstr ""
@@ -37020,58 +37685,61 @@ msgid "SnippetsEmptyState|No snippets found"
msgstr ""
msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
-msgstr ""
+msgstr "Stocker, partager et intégrer des petites portions de code et de texte."
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} a été soumis à Akismet avec succès."
msgid "Snippets|Add another file %{num}/%{total}"
-msgstr ""
+msgstr "Ajouter un autre fichier %{num}/%{total}"
msgid "Snippets|Delete file"
-msgstr ""
+msgstr "Supprimer le fichier"
msgid "Snippets|Description (optional)"
-msgstr ""
+msgstr "Description (facultatif)"
msgid "Snippets|Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Erreur avec Akismet. Veuillez vérifier les journaux pour plus d'informations."
msgid "Snippets|Files"
-msgstr ""
+msgstr "Fichiers"
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
-msgstr ""
+msgstr "Donnez un nom à votre fichier pour mettre le code en évidence, p. ex. exemple.rb pour Ruby"
msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
-msgstr ""
+msgstr "Ajoutez éventuellement une description de ce que fait votre extrait ou de comment l'utiliser…"
msgid "Snippets|Snippets can't contain empty files. Ensure all files have content, or delete them."
-msgstr ""
+msgstr "Les extraits ne peuvent pas contenir de fichiers vides. Assurez-vous que tous les fichiers ont du contenu, ou supprimez-les."
msgid "Snowplow"
msgstr ""
-msgid "Solid"
+msgid "Soft wrap"
msgstr ""
+msgid "Solid"
+msgstr "Solide"
+
msgid "Solution"
-msgstr ""
+msgstr "Solution"
msgid "Some changes are not shown"
-msgstr ""
+msgstr "Certaines modifications ne sont pas affichées"
msgid "Some child epics may be hidden due to applied filters"
-msgstr ""
+msgstr "Des épopées enfants peuvent être cachées en raison des filtres appliqués."
msgid "Some common domains are not allowed. %{learn_more_link}."
-msgstr ""
+msgstr "Certains domaines usuels ne sont pas autorisés. %{learn_more_link}."
msgid "Someone edited the file the same time you did. Please check out %{link_start}the file %{icon}%{link_end} and make sure your changes will not unintentionally remove theirs."
-msgstr ""
+msgstr "Quelqu'un a modifié le fichier en même temps que vous. Veuillez vérifier %{link_start}le fichier %{icon}%{link_end} et assurez-vous que ses modifications ne seront pas supprimées accidentellement par les vôtres."
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -37083,13 +37751,13 @@ msgid "Someone edited this merge request at the same time you did. Please refres
msgstr ""
msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
-msgstr ""
+msgstr "Quelqu'un a modifié ce cas de test en même temps que vous. La description a été mise à jour et vous allez devoir refaire vos modifications."
msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
-msgstr ""
+msgstr "Quelqu'un, en espérant qu'il s'agit de vous, a demandé la réinitialisation du mot de passe de votre compte GitLab sur %{link_to_gitlab}."
msgid "Something went wrong"
-msgstr ""
+msgstr "Une erreur s’est produite"
msgid "Something went wrong on our end"
msgstr "Une erreur est survenue de notre côté"
@@ -37107,13 +37775,13 @@ msgid "Something went wrong trying to change the locked state of this %{issuable
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 ""
+msgstr "Une erreur s'est produite lors de la tentative de chargement des contacts du ticket."
msgid "Something went wrong when reordering designs. Please try again"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la réorganisation des designs. Veuillez réessayer"
msgid "Something went wrong while adding timeline event."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'ajout d'un événement de chronologie."
msgid "Something went wrong while adding your award. Please try again."
msgstr ""
@@ -37125,16 +37793,16 @@ msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
msgid "Something went wrong while archiving a requirement."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'archivage d'une exigence."
msgid "Something went wrong while closing the epic. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la fermeture de l'épopée. Veuillez réessayer plus tard."
msgid "Something went wrong while closing the merge request. Please try again later."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la fermeture de la demande de fusion. Veuillez réessayer plus tard."
msgid "Something went wrong while creating a requirement."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création d'une exigence."
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
@@ -37146,16 +37814,16 @@ msgid "Something went wrong while deleting your note. Please try again."
msgstr ""
msgid "Something went wrong while deploying this environment. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors du déploiement de cet environnement. Veuillez réessayer."
msgid "Something went wrong while editing your comment. Please try again."
msgstr ""
msgid "Something went wrong while exporting requirements"
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'export des exigences."
msgid "Something went wrong while fetching branches"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des branches"
msgid "Something went wrong while fetching comments. Please try again."
msgstr "Une erreur est survenue lors de la récupération des commentaires. Veuillez réessayer."
@@ -37164,31 +37832,31 @@ msgid "Something went wrong while fetching description changes. Please try again
msgstr ""
msgid "Something went wrong while fetching details"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des détails"
msgid "Something went wrong while fetching group member contributions"
msgstr "Une erreur s’est produite lors de la récupération des contributions des membres du groupe"
msgid "Something went wrong while fetching latest comments."
-msgstr ""
+msgstr "Quelque chose s'est mal passé lors de la récupération des derniers commentaires."
msgid "Something went wrong while fetching projects"
msgstr ""
msgid "Something went wrong while fetching projects."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets."
msgid "Something went wrong while fetching related merge requests."
msgstr ""
msgid "Something went wrong while fetching requirements count."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération du nombre d'exigences."
msgid "Something went wrong while fetching requirements list."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la liste des exigences."
msgid "Something went wrong while fetching source branches."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des branches sources."
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."
@@ -37200,64 +37868,64 @@ msgid "Something went wrong while initializing the OpenAPI viewer"
msgstr ""
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention du certificat Let's Encrypt."
msgid "Something went wrong while promoting the issue to an epic. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la promotion du ticket en épopée. Veuillez réessayer."
msgid "Something went wrong while promoting the note to timeline event."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la promotion de la note à l'événement de chronologie."
msgid "Something went wrong while reopening a requirement."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la réouverture d'une exigence."
msgid "Something went wrong while reopening the epic. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la réouverture de l'épopée. Veuillez réessayer plus tard."
msgid "Something went wrong while reopening the merge request. Please try again later."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la réouverture de la demande de fusion. Veuillez réessayer plus tard."
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "Une erreur s’est produite lors de la « résolution » de la discussion. Veuillez réessayer."
msgid "Something went wrong while setting %{issuableType} %{dateType} date."
-msgstr ""
+msgstr "Une erreur s'est produite lors du réglage de la date %{dateType} de %{issuableType}."
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
msgid "Something went wrong while setting %{issuableType} health status."
-msgstr ""
+msgstr "Une erreur s'est produite lors du réglage de l'état de santé de %{issuableType}."
msgid "Something went wrong while setting %{issuableType} notifications."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la configuration des notifications des %{issuableType}."
msgid "Something went wrong while setting %{issuableType} to-do item."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la configuration de l'élément à-faire de %{issuableType}."
msgid "Something went wrong while setting %{issuableType} weight."
-msgstr ""
+msgstr "Une erreur s'est produite lors du réglage du poids de %{issuableType}."
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
msgid "Something went wrong while updating a requirement."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour d'une exigence."
msgid "Something went wrong while updating assignees"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des assigné(e)s"
msgid "Something went wrong while updating your list settings"
msgstr ""
msgid "Something went wrong with your automatic subscription renewal."
-msgstr ""
+msgstr "Une erreur s'est produite lors du renouvellement automatique de votre abonnement."
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Une erreur est survenue, impossible d’ajouter %{project} au tableau de bord"
msgid "Something went wrong, unable to delete project"
-msgstr ""
+msgstr "Une erreur s'est produite, impossible de supprimer le projet"
msgid "Something went wrong, unable to get projects"
msgstr ""
@@ -37266,7 +37934,7 @@ msgid "Something went wrong, unable to search projects"
msgstr ""
msgid "Something went wrong. Please try again later"
-msgstr ""
+msgstr "Une erreur s'est produite. Veuillez réessayer plus tard"
msgid "Something went wrong. Please try again."
msgstr "Quelque chose s’est mal passé. Veuillez réessayer."
@@ -37287,7 +37955,7 @@ msgid "Sort by"
msgstr "Trier par"
msgid "Sort direction"
-msgstr ""
+msgstr "Sens de tri"
msgid "Sort direction: Ascending"
msgstr "Sens de tri : Croissant"
@@ -37295,6 +37963,9 @@ msgstr "Sens de tri : Croissant"
msgid "Sort direction: Descending"
msgstr "Sens de tri : Décroissant"
+msgid "Sort or filter"
+msgstr "Trier ou filtrer"
+
msgid "SortOptions|Blocking"
msgstr "Faisant blocage"
@@ -37337,6 +38008,9 @@ msgstr "Contact le plus récent"
msgid "SortOptions|Last created"
msgstr "Créé récemment"
+msgid "SortOptions|Latest version"
+msgstr "Version la plus récente"
+
msgid "SortOptions|Least popular"
msgstr "Popularité croissante"
@@ -37397,6 +38071,9 @@ msgstr "Étoiles les plus anciennes"
msgid "SortOptions|Oldest updated"
msgstr "Date de mise à jour croissante"
+msgid "SortOptions|Oldest version"
+msgstr "Version la plus ancienne"
+
msgid "SortOptions|Popularity"
msgstr "Popularité"
@@ -37455,13 +38132,13 @@ msgid "Source (branch or tag)"
msgstr "Source (branche ou étiquette)"
msgid "Source Branch"
-msgstr ""
+msgstr "Branche Source"
msgid "Source IP"
-msgstr ""
+msgstr "IP source"
msgid "Source branch"
-msgstr ""
+msgstr "Branche source"
msgid "Source branch will be deleted."
msgstr ""
@@ -37470,10 +38147,10 @@ msgid "Source branch will not be deleted."
msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
-msgstr ""
+msgstr "Branche Source : %{source_branch_open}%{source_branch}%{source_branch_close}"
msgid "Source code (%{fileExtension})"
-msgstr ""
+msgstr "Code source (%{fileExtension})"
msgid "Source is not available"
msgstr "La source n’est pas disponible"
@@ -37482,82 +38159,82 @@ msgid "Source project cannot be found."
msgstr ""
msgid "SourceEditor|\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "Le paramètre « el » est requis pour createInstance()"
msgid "SourceEditor|%{name} is not registered."
-msgstr ""
+msgstr "%{name} n'est pas enregistré."
msgid "SourceEditor|Extension definition should be either a class or a function"
-msgstr ""
+msgstr "La définition de l'extension doit être soit une classe, soit une fonction"
msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
-msgstr ""
+msgstr "La définition de l'extension doit être une classe, une fonction ou un tableau de définitions."
msgid "SourceEditor|Extensions Store is required to check for an extension."
-msgstr ""
+msgstr "La boutique d'extensions est nécessaire pour rechercher une extension"
msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
-msgstr ""
+msgstr "Conflit de nom pour la méthode « %{prop}() »."
msgid "SourceEditor|No extension for unuse has been specified."
-msgstr ""
+msgstr "Aucune extension pour inutilisation n'a été spécifiée."
msgid "SourceEditor|Source Editor instance is required to set up an extension."
-msgstr ""
+msgstr "Une instance de l'Éditeur de Source est requise pour mettre en place une extension."
msgid "SourceEditor|`definition` property is expected on the extension."
msgstr ""
msgid "Sourcegraph"
-msgstr ""
+msgstr "Sourcegraph"
msgid "SourcegraphAdmin|Block on private and internal projects"
msgstr ""
msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
-msgstr ""
+msgstr "Configurer l’URL d’une instance de Sourcegraph qui peut lire vos projets GitLab."
msgid "SourcegraphAdmin|Enable Sourcegraph"
-msgstr ""
+msgstr "Activer Sourcegraph"
msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
-msgstr ""
+msgstr "Activer le code intelligent propulsé par %{link_start}Sourcegraph%{link_end} sur les vues de code et les demandes de fusion de votre instance GitLab."
msgid "SourcegraphAdmin|Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph."
-msgstr ""
+msgstr "Seuls les projets publics ont l'intelligence de code activée et communiquent avec Sourcegraph."
msgid "SourcegraphAdmin|Save changes"
-msgstr ""
+msgstr "Enregistrer les modifications"
msgid "SourcegraphAdmin|Sourcegraph URL"
-msgstr ""
+msgstr "URL de Sourcegraph"
msgid "SourcegraphAdmin|https://sourcegraph.example.com"
-msgstr ""
+msgstr "https://sourcegraph.exemple.com"
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
-msgstr ""
+msgstr "Cette fonctionnalité est expérimentale et actuellement limitée à certains projets."
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
-msgstr ""
+msgstr "Cette fonctionnalité est expérimentale et limitée aux projets publics."
msgid "SourcegraphPreferences|This feature is experimental."
-msgstr ""
+msgstr "Cette fonctionnalité est expérimentale."
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "Utilise %{linkStart}Sourcegraph.com%{linkEnd}."
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
-msgstr ""
+msgstr "Utilise une %{linkStart}instance Sourcegraph%{linkEnd} personnalisée."
msgid "Spam Check"
-msgstr ""
+msgstr "Spam Check"
msgid "Spam Check API key"
-msgstr ""
+msgstr "Clé d'API de Spam Check"
msgid "Spam Logs"
msgstr "Journaux des messages indésirables"
@@ -37569,19 +38246,19 @@ msgid "Spam log successfully submitted as ham."
msgstr ""
msgid "Specific runners"
-msgstr ""
+msgstr "Exécuteurs spécifiques"
msgid "Specified URL cannot be used: \"%{reason}\""
-msgstr ""
+msgstr "L'URL spécifiée ne peut pas être utilisée : \"%{reason}\""
msgid "Specify IP ranges that are always allowed for inbound traffic, for use with group-level IP restrictions. Runner and Pages daemon internal IPs should be listed here so that they can access project artifacts."
-msgstr ""
+msgstr "Spécifie les plages IP qui sont toujours autorisées pour le trafic entrant lors de l'utilisation des restrictions IP au niveau du groupe. Les IPs internes des daemons des Pages et des Exécuteurs doivent être listées ici afin que ceux_ci puissent accéder aux artéfacts du projet."
msgid "Specify an email address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Spécifier une expression rationnelle pour les adresses électroniques afin d'identifier les utilisateurs qui sont internes par défaut."
msgid "Speed up your pipelines with Needs relationships"
-msgstr ""
+msgstr "Accélérez vos pipelines avec des relations de Besoins"
msgid "Spent at"
msgstr ""
@@ -37593,19 +38270,19 @@ msgid "Squash commits"
msgstr "Combiner (squash) les commits"
msgid "Squash commits when merge request is accepted."
-msgstr ""
+msgstr "Écraser les commits lorsque la demande de fusion est acceptée."
msgid "Stack trace"
msgstr ""
msgid "Stacktrace snippet"
-msgstr ""
+msgstr "Extrait de la trace de pile"
msgid "Stage"
msgstr "Étape"
msgid "Stage:"
-msgstr ""
+msgstr "Étape :"
msgid "Standard"
msgstr ""
@@ -37653,13 +38330,13 @@ msgid "Start a %{new_merge_request} with these changes"
msgstr "Créer une %{new_merge_request} avec ces changements"
msgid "Start a Free Ultimate Trial"
-msgstr ""
+msgstr "Commencez un Essai Ultimate Gratuit"
msgid "Start a new discussion…"
-msgstr ""
+msgstr "Démarrer une nouvelle discussion…"
msgid "Start a new merge request with these changes"
-msgstr ""
+msgstr "Démarrer une nouvelle demande de fusion avec ces modifications"
msgid "Start a review"
msgstr "Démarrer une revue de code"
@@ -37677,7 +38354,7 @@ msgid "Start free trial"
msgstr ""
msgid "Start inputting changes and we will generate a YAML-file for you to add to your repository"
-msgstr ""
+msgstr "Commencez à saisir des modifications et nous régénérerons un fichier YAML à votre attention pour l'ajouter à votre dépôt"
msgid "Start internal thread"
msgstr ""
@@ -37698,7 +38375,7 @@ msgid "Start thread"
msgstr ""
msgid "Start your Free Ultimate Trial"
-msgstr ""
+msgstr "Commencez votre Essai Ultimate Gratuit"
msgid "Start your free trial"
msgstr ""
@@ -37719,7 +38396,7 @@ msgid "Starting..."
msgstr ""
msgid "Starts"
-msgstr ""
+msgstr "Commence"
msgid "Starts %{startsIn}"
msgstr ""
@@ -37734,7 +38411,7 @@ msgid "Starts on"
msgstr ""
msgid "Starts: %{startsAt}"
-msgstr ""
+msgstr "Commence : %{startsAt}"
msgid "State your message to activate"
msgstr "Énoncez votre message à activer"
@@ -37746,7 +38423,7 @@ msgid "State/Province/City"
msgstr ""
msgid "Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "Test statique de la sécurité des applications (SAST)"
msgid "Statistics"
msgstr ""
@@ -37764,94 +38441,94 @@ msgid "Status: %{title}"
msgstr "État : %{title}"
msgid "StatusCheck| %{failed} failed, and %{pending} pending"
-msgstr ""
+msgstr " %{failed} en échec, et %{pending} en attente"
msgid "StatusCheck|%{failed} failed"
-msgstr ""
+msgstr "%{failed} a échoué"
msgid "StatusCheck|%{pending} pending"
-msgstr ""
+msgstr "%{pending} en attente"
msgid "StatusCheck|API to check"
-msgstr ""
+msgstr "API à vérifier"
msgid "StatusCheck|Add status check"
msgstr ""
msgid "StatusCheck|All passed"
-msgstr ""
+msgstr "Toutes passées"
msgid "StatusCheck|An error occurred deleting the %{name} status check."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de la vérification d'état %{name}."
msgid "StatusCheck|An error occurred fetching the status checks."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des vérifications d'état."
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
-msgstr ""
+msgstr "Appliquer cette vérification d'état à toutes les branches ou à une branche protégée spécifique."
msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "Vérifier l'état d'une réponse dans les demandes de fusion. Les échecs ne bloquent pas les fusions. %{link_start}En savoir plus%{link_end}."
msgid "StatusCheck|Examples: QA, Security."
-msgstr ""
+msgstr "Exemples : QA, Sécurité."
msgid "StatusCheck|External API is already in use by another status check."
-msgstr ""
+msgstr "L'API externe est déjà utilisée par une autre vérification d'état."
msgid "StatusCheck|Failed to load status checks"
-msgstr ""
+msgstr "Échec du chargement des vérifications d'état"
msgid "StatusCheck|Failed to load status checks."
-msgstr ""
+msgstr "Impossible de charger les vérifications d'état."
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
-msgstr ""
+msgstr "Invoquer une API externe dans le cadre du processus de pipeline."
msgid "StatusCheck|No status checks are defined yet."
-msgstr ""
+msgstr "Aucune vérification d'état n'est encore définie."
msgid "StatusCheck|Remove status check"
-msgstr ""
+msgstr "Supprimer la vérification de l'état"
msgid "StatusCheck|Remove status check?"
-msgstr ""
+msgstr "Supprimer la vérification de l'état ?"
msgid "StatusCheck|Service name"
-msgstr ""
+msgstr "Nom du service"
msgid "StatusCheck|Status checks"
msgstr ""
msgid "StatusCheck|Status checks all passed"
-msgstr ""
+msgstr "Les vérifications d'état sont toutes passées"
msgid "StatusCheck|Status checks are being fetched"
-msgstr ""
+msgstr "Les vérifications d'état sont en cours de récupération"
msgid "StatusCheck|Status to check"
-msgstr ""
+msgstr "État à vérifier"
msgid "StatusCheck|Target branch"
-msgstr ""
+msgstr "Branche cible"
msgid "StatusCheck|Update status check"
-msgstr ""
+msgstr "Mettre à jour la vérification de l'état"
msgid "StatusCheck|You are about to remove the %{name} status check."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer la vérification d'état %{name}."
msgid "StatusCheck|status checks"
-msgstr ""
+msgstr "vérifications d’état"
msgid "StatusPage|AWS %{docsLink}"
-msgstr ""
+msgstr "%{docsLink} AWS"
msgid "StatusPage|AWS Secret access key"
-msgstr ""
+msgstr "Clé d’accès secrète AWS"
msgid "StatusPage|AWS access key ID"
-msgstr ""
+msgstr "ID de la clé d'accès AWS"
msgid "StatusPage|AWS region"
msgstr ""
@@ -37860,34 +38537,34 @@ msgid "StatusPage|Active"
msgstr ""
msgid "StatusPage|Bucket %{docsLink}"
-msgstr ""
+msgstr "%{docsLink} Bucket"
msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
-msgstr ""
+msgstr "Configurer les paramètres de stockage de fichiers pour lier les tickets de ce projet à une page d’état externe."
msgid "StatusPage|S3 Bucket name"
msgstr ""
msgid "StatusPage|Status page"
-msgstr ""
+msgstr "Page d'état"
msgid "StatusPage|Status page URL"
-msgstr ""
+msgstr "URL de la page d'état"
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
-msgstr ""
+msgstr "Pour publier des incidents sur une page d'état externe, GitLab enregistre un fichier JSON sur votre compte Amazon S3 dans un emplacement accessible à votre service de page d'état externe. Assurez-vous également de configurer %{docsLink}"
msgid "StatusPage|configuration documentation"
-msgstr ""
+msgstr "documentation de configuration"
msgid "StatusPage|your status page frontend."
-msgstr ""
+msgstr "votre page frontale d'état."
msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
msgstr ""
msgid "Step %{currentStep} of %{stepCount}"
-msgstr ""
+msgstr "Étape %{currentStep} sur %{stepCount}"
msgid "Step 1."
msgstr ""
@@ -37920,7 +38597,7 @@ msgid "Storage"
msgstr "Stockage"
msgid "Storage nodes for new repositories"
-msgstr ""
+msgstr "Nœuds de stockage pour les nouveaux dépôts"
msgid "Storage:"
msgstr "Stockage :"
@@ -37929,31 +38606,31 @@ msgid "StorageSize|Unknown"
msgstr ""
msgid "Store your files, plan your work, collaborate on code, and more."
-msgstr ""
+msgstr "Stocker vos fichiers, planifiez votre travail, collaborez sur du code et bien plus encore."
msgid "Strikethrough"
-msgstr ""
+msgstr "Barré"
msgid "Strikethrough text"
-msgstr ""
+msgstr "Texte barré"
msgid "Sub-batch size"
msgstr ""
msgid "Subdomains of the Pages root domain %{root_domain} are reserved and cannot be used as custom Pages domains."
-msgstr ""
+msgstr "Les sous-domaines du domaine racine des Pages %{root_domain} sont réservés et ne peuvent pas être utilisés comme domaines de Pages personnalisés."
msgid "Subgroup information"
-msgstr ""
+msgstr "Informations sur le sous-groupe"
msgid "Subgroup milestone"
-msgstr ""
+msgstr "Jalon de sous-groupe"
msgid "Subgroup navigation"
msgstr ""
msgid "SubgroupCreationLevel|Roles allowed to create subgroups"
-msgstr ""
+msgstr "Rôles autorisés à créer des sous-groupes"
msgid "SubgroupCreationlevel|Allowed to create subgroups"
msgstr ""
@@ -37971,7 +38648,7 @@ msgid "Subgroups and projects"
msgstr "Sousâ€groupes et projets"
msgid "Subgroups can set up their own two-factor authentication rules"
-msgstr ""
+msgstr "Les sous-groupes peuvent configurer leurs propres règles d'authentification à deux facteurs"
msgid "Subject Key Identifier:"
msgstr ""
@@ -37980,13 +38657,13 @@ msgid "Subkeys"
msgstr ""
msgid "Submit"
-msgstr ""
+msgstr "Envoyer"
msgid "Submit a review"
msgstr ""
msgid "Submit as ham"
-msgstr ""
+msgstr "Soumettre comme acceptable"
msgid "Submit as spam"
msgstr "Soumettre comme indésirable"
@@ -38004,7 +38681,7 @@ msgid "Submit the current review."
msgstr ""
msgid "Submitted as ham"
-msgstr ""
+msgstr "Soumis comme acceptable"
msgid "Submitted the current review."
msgstr ""
@@ -38031,28 +38708,28 @@ msgid "Subscribed to this %{quick_action_target}."
msgstr ""
msgid "Subscribed to this project"
-msgstr ""
+msgstr "Abonné à ce projet"
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
msgid "Subscript"
-msgstr ""
+msgstr "Indice"
msgid "Subscription"
msgstr ""
msgid "Subscription History"
-msgstr ""
+msgstr "Historique d'Abonnement"
msgid "Subscription deletion failed."
msgstr ""
msgid "Subscription service outage"
-msgstr ""
+msgstr "Panne du service abonnement"
msgid "Subscription successfully applied to \"%{group_name}\""
-msgstr ""
+msgstr "Abonnement appliqué avec succès à \"%{group_name}\""
msgid "Subscription successfully created."
msgstr ""
@@ -38061,19 +38738,19 @@ msgid "Subscription successfully deleted."
msgstr ""
msgid "SubscriptionBanner|Add new license"
-msgstr ""
+msgstr "Ajouter une nouvelle licence"
msgid "SubscriptionBanner|Export license usage file"
msgstr ""
msgid "SubscriptionBanner|Upload new license"
-msgstr ""
+msgstr "Téléverser une nouvelle licence"
msgid "SubscriptionTable|Add seats"
-msgstr ""
+msgstr "Ajouter des sièges"
msgid "SubscriptionTable|An error occurred while loading the subscription details."
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des détails de l'abonnement."
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -38100,10 +38777,10 @@ msgid "SubscriptionTable|Next invoice"
msgstr ""
msgid "SubscriptionTable|Refresh Seats"
-msgstr ""
+msgstr "Actualiser les Sièges"
msgid "SubscriptionTable|Renew"
-msgstr ""
+msgstr "Renouveler"
msgid "SubscriptionTable|Seats currently in use"
msgstr ""
@@ -38115,10 +38792,10 @@ msgid "SubscriptionTable|Seats owed"
msgstr ""
msgid "SubscriptionTable|See usage"
-msgstr ""
+msgstr "Voir l'utilisation"
msgid "SubscriptionTable|Something went wrong trying to refresh seats"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative d'actualisation des sièges"
msgid "SubscriptionTable|Subscription end date"
msgstr ""
@@ -38157,22 +38834,22 @@ msgid "Subscriptions"
msgstr ""
msgid "Subscriptions|Chat with sales"
-msgstr ""
+msgstr "Discuter avec le service commercial"
msgid "Subscriptions|Close"
-msgstr ""
+msgstr "Fermer"
msgid "Subscriptions|Not ready to buy yet?"
-msgstr ""
+msgstr "Pas encore décidé à acheter ?"
msgid "Subscriptions|Start a free trial"
-msgstr ""
+msgstr "Démarrer un essai gratuit"
msgid "Subscriptions|We understand. Maybe you have some questions for our sales team, or maybe you'd like to try some of the paid features first. What would you like to do?"
-msgstr ""
+msgstr "Nous comprenons. Peut-être avez-vous des questions pour notre service commercial, ou préférez-vous d'abord essayer quelques-unes des fonctionnalités payantes. Que souhaitez-vous ?"
msgid "Subscription|Your subscription for %{strong}%{namespace_name}%{strong_close} has expired and you are now on %{pricing_link_start}the GitLab Free tier%{pricing_link_end}. Don't worry, your data is safe. Get in touch with our support team (%{support_email}). They'll gladly help with your subscription renewal."
-msgstr ""
+msgstr "Votre abonnement à %{strong}%{namespace_name}%{strong_close} a expiré et vous êtes maintenant sur l'%{pricing_link_start}offre GitLab Free%{pricing_link_end}. Ne vous inquiétez pas, vos données sont en sécurité. Contactez notre équipe d'assistance (%{support_email}). Ils se feront un plaisir de vous aider pour le renouvellement de votre abonnement."
msgid "Subtracted"
msgstr ""
@@ -38187,10 +38864,10 @@ msgid "Successfully activated"
msgstr ""
msgid "Successfully approved"
-msgstr ""
+msgstr "Approuvé avec succès"
msgid "Successfully banned"
-msgstr ""
+msgstr "Banni avec succès"
msgid "Successfully blocked"
msgstr ""
@@ -38205,7 +38882,7 @@ msgid "Successfully deleted U2F device."
msgstr ""
msgid "Successfully deleted WebAuthn device."
-msgstr ""
+msgstr "L'appareil WebAuthn a été supprimé avec succès."
msgid "Successfully removed email."
msgstr ""
@@ -38214,10 +38891,10 @@ msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_star
msgstr ""
msgid "Successfully synced %{synced_timeago}."
-msgstr ""
+msgstr "Synchronisation réussie %{synced_timeago}."
msgid "Successfully unbanned"
-msgstr ""
+msgstr "Gracié avec succès"
msgid "Successfully unblocked"
msgstr ""
@@ -38229,82 +38906,82 @@ msgid "Successfully updated %{last_updated_timeago}."
msgstr "Mise à jour réussie %{last_updated_timeago}."
msgid "Successfully updated the environment."
-msgstr ""
+msgstr "L'environnement a été mis à jour avec succès."
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
-msgstr ""
+msgstr "Suggérer des modifications de code qui peuvent être appliquées immédiatement en un seul clic. Essayez !"
msgid "Suggested change"
msgstr ""
msgid "SuggestedColors|Aztec Gold"
-msgstr ""
+msgstr "Or aztèque"
msgid "SuggestedColors|Blue"
-msgstr ""
+msgstr "Bleu"
msgid "SuggestedColors|Blue-gray"
-msgstr ""
+msgstr "Bleu-gris"
msgid "SuggestedColors|Carrot orange"
-msgstr ""
+msgstr "Orange carotte"
msgid "SuggestedColors|Champagne"
-msgstr ""
+msgstr "Champagne"
msgid "SuggestedColors|Charcoal grey"
-msgstr ""
+msgstr "Gris charbon"
msgid "SuggestedColors|Crimson"
-msgstr ""
+msgstr "Cramoisi"
msgid "SuggestedColors|Current addition color"
-msgstr ""
+msgstr "Couleur actuelle des ajouts"
msgid "SuggestedColors|Current removal color"
-msgstr ""
+msgstr "Couleur actuelle des suppressions"
msgid "SuggestedColors|Dark coral"
-msgstr ""
+msgstr "Corail foncé"
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "Vert foncé"
msgid "SuggestedColors|Dark sea green"
-msgstr ""
+msgstr "Vert océan foncé"
msgid "SuggestedColors|Dark violet"
-msgstr ""
+msgstr "Violet foncé"
msgid "SuggestedColors|Deep violet"
-msgstr ""
+msgstr "Violet profond"
msgid "SuggestedColors|Default addition color"
-msgstr ""
+msgstr "Couleur par défaut des ajouts"
msgid "SuggestedColors|Default removal color"
-msgstr ""
+msgstr "Couleur par défaut des suppressions"
msgid "SuggestedColors|Gray"
-msgstr ""
+msgstr "Gris"
msgid "SuggestedColors|Green"
-msgstr ""
+msgstr "Vert"
msgid "SuggestedColors|Green screen"
msgstr ""
msgid "SuggestedColors|Green-cyan"
-msgstr ""
+msgstr "Turquoise foncé"
-msgid "SuggestedColors|Lavendar"
-msgstr ""
+msgid "SuggestedColors|Lavender"
+msgstr "Lavande"
msgid "SuggestedColors|Magenta-pink"
-msgstr ""
+msgstr "Magenta-rose"
msgid "SuggestedColors|Medium sea green"
-msgstr ""
+msgstr "Vert océan moyen"
msgid "SuggestedColors|Orange"
msgstr ""
@@ -38313,15 +38990,27 @@ msgid "SuggestedColors|Purple"
msgstr ""
msgid "SuggestedColors|Red"
-msgstr ""
+msgstr "Rouge"
msgid "SuggestedColors|Rose red"
msgstr ""
msgid "SuggestedColors|Titanium yellow"
-msgstr ""
+msgstr "Jaune titane"
+
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "Obtenir des suggestions pour les relecteurs grâce à l'outil d'apprentissage automatique de GitLab."
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "Relecteurs suggérés"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "Les suggestions apparaissent dans la section Relecteur de la barre latérale droite"
msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr "La suggestion n'est pas applicable car elle n'a pas été trouvée."
+
+msgid "Suggestion(s)"
msgstr ""
msgid "Suggestions are not applicable as one or more suggestions were not found."
@@ -38331,7 +39020,7 @@ msgid "Suggestions are not applicable as their lines cannot overlap."
msgstr ""
msgid "Suggestions must all be on the same branch."
-msgstr ""
+msgstr "Les suggestions doivent toutes être sur la même branche."
msgid "Suggestions:"
msgstr ""
@@ -38343,67 +39032,73 @@ msgid "Summary"
msgstr ""
msgid "Summary / note"
-msgstr ""
+msgstr "Résumé / note"
msgid "Summary comment (optional)"
msgstr ""
msgid "Sun"
-msgstr ""
+msgstr "Dim"
msgid "Sunday"
msgstr ""
msgid "SuperSonics|Activate subscription"
-msgstr ""
+msgstr "Activer l'abonnement"
msgid "SuperSonics|Activation code"
-msgstr ""
+msgstr "Code d'activation"
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
msgstr ""
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr "L'activation n'est pas possible à cause d'un ajustement incorrect"
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr "Une erreur s’est produite lors de l’ajout de votre abonnement"
+
msgid "SuperSonics|Billable users"
-msgstr ""
+msgstr "Utilisateurs facturables"
msgid "SuperSonics|Buy subscription"
-msgstr ""
+msgstr "Souscrire un abonnement"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr ""
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr "Impossible d'activer l'instance en raison d'un problème de connectivité"
msgid "SuperSonics|Cloud licensing"
-msgstr ""
+msgstr "Licences pour le Cloud"
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
-msgstr ""
+msgstr "Les licences pour le Cloud sont maintenant disponibles. C'est un moyen plus simple pour activer des instances et gérer les abonnements. Apprenez-en davantage sur le %{blogPostLinkStart}message de notre blog%{blogPostLinkEnd}. Les codes d'activation sont disponibles sur le %{portalLinkStart}Portail Clients%{portalLinkEnd}."
msgid "SuperSonics|Enter activation code"
-msgstr ""
+msgstr "Entrez le code d'activation"
msgid "SuperSonics|Export license usage file"
msgstr ""
msgid "SuperSonics|Free trial"
-msgstr ""
+msgstr "Essai gratuit"
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
+msgstr "J'accepte que mon utilisation du Logiciel GitLab soit soumise au Contrat d'Abonnement situé dans les %{linkStart}Conditions Générales d'Utilisation%{linkEnd}, sauf accord contraire par écrit avec GitLab."
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
+msgstr "Découvrez comment %{linkStart}activer votre abonnement%{linkEnd}."
msgid "SuperSonics|Learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
-msgstr ""
+msgstr "En savoir plus sur l'%{activationLinkStart}activation de votre abonnement%{activationLinkEnd}. Si vous avez besoin d'assistance supplémentaire, %{supportLinkStart}contactez le Support GitLab%{supportLinkEnd}."
msgid "SuperSonics|Licensed to"
-msgstr ""
+msgstr "Licence accordée à"
msgid "SuperSonics|Manage"
-msgstr ""
+msgstr "Gérer"
msgid "SuperSonics|Maximum users"
-msgstr ""
+msgstr "Nombre maximum d'utilisateurs"
msgid "SuperSonics|Offline license"
msgstr ""
@@ -38412,46 +39107,46 @@ msgid "SuperSonics|Online license"
msgstr ""
msgid "SuperSonics|Paste your activation code"
-msgstr ""
+msgstr "Collez votre code d'activation"
msgid "SuperSonics|Please agree to the Subscription Agreement"
-msgstr ""
+msgstr "Veuillez accepter les Termes du Contrat d’Abonnement"
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
+msgstr "Prêt à commencer ? Un forfait GitLab est parfait pour des entreprises qui se développent et pour une utilisation entre plusieurs équipes."
msgid "SuperSonics|Start free trial"
-msgstr ""
+msgstr "Commencer un essai gratuit"
msgid "SuperSonics|Subscription details"
-msgstr ""
+msgstr "Détails de l'abonnement"
msgid "SuperSonics|Subscription unavailable"
-msgstr ""
+msgstr "Abonnement non disponible"
msgid "SuperSonics|Sync subscription details"
-msgstr ""
+msgstr "Synchroniser les détails de l'abonnement"
msgid "SuperSonics|Sync subscription request."
-msgstr ""
+msgstr "Demande de synchro d'abonnement."
msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
-msgstr ""
+msgstr "Le code d'activation n'est pas valide. Veuillez vous assurer de l'avoir copié de manière exacte depuis le Portail Clients ou depuis le courriel de confirmation. En savoir plus sur l'%{linkStart}activation de votre abonnement%{linkEnd}."
msgid "SuperSonics|The activation code should be a 24-character alphanumeric string"
-msgstr ""
+msgstr "Le code d'activation doit être une chaîne alphanumérique de 24 caractères"
msgid "SuperSonics|There is a connectivity issue."
-msgstr ""
+msgstr "Il y a un problème de connectivité."
msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
-msgstr ""
+msgstr "Il s'agit du pic d'utilisateurs le plus élevé de votre installation depuis que la licence a démarré."
msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
+msgstr "Il s'agit du nombre d'%{billableUsersLinkStart}utilisateurs facturables%{billableUsersLinkEnd} sur votre installation et cela correspond à la quantité minimale que vous devez acheter lors du renouvellement de votre licence."
msgid "SuperSonics|To activate your subscription, your instance needs to connect to GitLab. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "Pour activer votre abonnement, votre instance a besoin de se connecter à GitLab. %{learnMoreLinkStart}En savoir plus%{learnMoreLinkEnd}."
msgid "SuperSonics|User in subscription"
msgid_plural "SuperSonics|Users in subscription"
@@ -38462,22 +39157,22 @@ msgid "SuperSonics|Users in subscription"
msgstr ""
msgid "SuperSonics|Users over subscription"
-msgstr ""
+msgstr "Utilisateurs non abonnés"
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
+msgstr "Les utilisateurs ayant un rôle d'Invité et ceux qui ne font pas partie d'un Projet ou d'un Groupe n'utiliseront pas de licence de siège."
msgid "SuperSonics|You can %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} and try again. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
-msgstr ""
+msgstr "Vous pouvez %{purchaseSubscriptionLinkStart}souscrire un nouvel abonnement%{purchaseSubscriptionLinkEnd} et réessayer. Si vous avez besoin d’une assistance supplémentaire, %{supportLinkStart}contactez le Support GitLab%{supportLinkEnd}."
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
-msgstr ""
+msgstr "Vous ne pouvez plus synchroniser les détails de votre abonnement avec GitLab. Obtenez de l'aide sur les problèmes de connectivité les plus courants avec le %{connectivityHelpLinkStart}dépannage du code d'activation%{connectivityHelpLinkEnd}."
msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
+msgstr "Vous pouvez commencer un essai gratuit de GitLab Ultimate sans aucune obligation ou détails de paiement."
msgid "SuperSonics|You do not have an active subscription"
-msgstr ""
+msgstr "Vous n'avez pas d'abonnement actif"
msgid "SuperSonics|You have a future dated license"
msgstr ""
@@ -38485,41 +39180,53 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "Vous avez fait un ajustement pour %{trueUpQuantity} %{trueUpQuantityUsers} mais vous devez en faire un pour %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. Pour vous acquitter des sièges supplémentaires, contactez votre représentant commercial. Pour une assistance complémentaire, contactez le %{licenseSupportLinkStart}support GitLab%{licenseSupportLinkEnd}."
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
-msgstr ""
+msgstr "Vous avez ajouté avec succès une licence qui s'active le %{date}. Veuillez consulter le tableau de l'historique des abonnements ci-dessous pour plus de détails."
+
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr "Vous avez peut-être entré un code d'activation expiré ou non admissible. Pour demander un nouveau code d'activation, %{purchaseSubscriptionLinkStart}souscrivez un nouvel abonnement%{purchaseSubscriptionLinkEnd} ou %{supportLinkStart}contactez le Support GitLab%{supportLinkEnd} pour obtenir de l'aide."
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
+msgstr "La facturation des %{trueUpLinkStart}utilisateurs hors licence%{trueUpLinkEnd} se fera sur une base trimestrielle ou annuelle, en fonction des termes de votre contrat."
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr "Votre %{subscriptionEntryName} ne peut pas être affiché pour le moment. Veuillez actualiser la page pour réessayer."
+
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
msgstr ""
msgid "SuperSonics|Your future dated license was successfully added"
-msgstr ""
+msgstr "Votre licence postdatée a été ajoutée avec succès"
msgid "SuperSonics|Your subscription"
-msgstr ""
+msgstr "Votre abonnement"
+
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr "Votre abonnement est introuvable"
msgid "SuperSonics|Your subscription details will sync shortly."
-msgstr ""
+msgstr "Les détails de votre abonnement seront synchronisés sous peu."
-msgid "SuperSonics|Your subscription is expired."
-msgstr ""
+msgid "SuperSonics|Your subscription is expired"
+msgstr "Votre abonnement a expiré"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
-msgstr ""
+msgstr "Votre abonnement a été activé avec succès. Vous pouvez voir les détails ci-dessous."
msgid "SuperSonics|current subscription"
-msgstr ""
+msgstr "abonnement actuel"
msgid "SuperSonics|future subscriptions"
-msgstr ""
+msgstr "abonnements futurs"
msgid "SuperSonics|past subscriptions"
-msgstr ""
+msgstr "abonnements passés"
msgid "Superscript"
-msgstr ""
+msgstr "Exposant"
msgid "Support"
msgstr ""
@@ -38531,19 +39238,19 @@ msgid "Support page URL"
msgstr ""
msgid "Surveys|Delighted"
-msgstr ""
+msgstr "Très satisfait"
msgid "Surveys|Happy"
-msgstr ""
+msgstr "Satisfait"
msgid "Surveys|Neutral"
-msgstr ""
+msgstr "Neutre"
msgid "Surveys|Sad"
-msgstr ""
+msgstr "Peu satisfait"
msgid "Surveys|Unhappy"
-msgstr ""
+msgstr "Très insatisfait"
msgid "Switch Branches"
msgstr ""
@@ -38555,52 +39262,52 @@ msgid "Switch branch/tag"
msgstr "Changer de branche ou d’étiquette"
msgid "Switch to GitLab Next"
-msgstr ""
+msgstr "Passer à GitLab Next"
msgid "Switch to the source to copy the file contents"
msgstr ""
msgid "Symbolic link"
-msgstr ""
+msgstr "Lien symbolique"
msgid "Sync LDAP"
-msgstr ""
+msgstr "Synchro LDAP"
msgid "Sync now"
-msgstr ""
+msgstr "Synchroniser maintenant"
msgid "Synced"
msgstr ""
msgid "Synchronize LDAP"
-msgstr ""
+msgstr "Synchronisation LDAP"
msgid "Syncing…"
-msgstr ""
+msgstr "Synchronisation..."
msgid "Syntax is correct."
-msgstr ""
+msgstr "La syntaxe est correcte."
msgid "Syntax is incorrect."
-msgstr ""
+msgstr "La syntaxe est incorrecte."
msgid "SynthaxHighlightingTheme|Dark"
-msgstr ""
+msgstr "Sombre"
msgid "SynthaxHighlightingTheme|Light"
-msgstr ""
+msgstr "Clair"
msgid "SynthaxHighlightingTheme|Monokai"
-msgstr ""
+msgstr "Monokai"
msgid "SynthaxHighlightingTheme|None"
-msgstr ""
+msgstr "Aucun"
msgid "SynthaxHighlightingTheme|Solarized Dark"
-msgstr ""
+msgstr "Sombre solarisé"
msgid "SynthaxHighlightingTheme|Solarized Light"
-msgstr ""
+msgstr "Clair solarisé"
msgid "System"
msgstr ""
@@ -38609,7 +39316,7 @@ msgid "System Hooks"
msgstr "« Hooks » système"
msgid "System Hooks Help"
-msgstr ""
+msgstr "Aide sur les « Hooks » système"
msgid "System Info"
msgstr "Informations système"
@@ -38621,7 +39328,7 @@ msgid "System header and footer"
msgstr ""
msgid "System hooks are triggered on sets of events like creating a project or adding an SSH key. You can also enable extra triggers, such as push events."
-msgstr ""
+msgstr "Les crochets systèmes sont déclenchés selon un ensemble d'événements, tels que la création d'un projet ou l'ajout d'une clé SSH. Vous pouvez également activer des déclencheurs supplémentaires comme des événements de poussée."
msgid "System metrics (Custom)"
msgstr "Métriques du système (personnalisées)"
@@ -38630,16 +39337,16 @@ msgid "System metrics (Kubernetes)"
msgstr "Métriques du système (Kubernetes)"
msgid "System output"
-msgstr ""
+msgstr "Sortie système"
msgid "System started"
-msgstr ""
+msgstr "Système démarré"
msgid "Table of Contents"
msgstr ""
msgid "Table of contents"
-msgstr ""
+msgstr "Table des matières"
msgid "Tag"
msgstr ""
@@ -38651,19 +39358,19 @@ msgid "Tag name"
msgstr ""
msgid "Tag name is required."
-msgstr ""
+msgstr "Le nom de l'étiquette est requis."
msgid "Tag push"
msgstr ""
msgid "Tag push events"
-msgstr ""
+msgstr "Événements de poussée d'étiquette"
msgid "Tag this commit."
msgstr ""
msgid "Tag:"
-msgstr ""
+msgstr "Étiquette :"
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
msgstr ""
@@ -38675,7 +39382,7 @@ msgid "Tags"
msgstr "Étiquettes"
msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
-msgstr ""
+msgstr "Les étiquettes sont supprimées jusqu'à ce que le délai d'expiration soit atteint. Toutes les étiquettes restantes seront incluses la prochaine fois que la stratégie sera exécutée. Pour enlever la limite de temps, définissez-la à 0."
msgid "Tags feed"
msgstr "Flux d’étiquettes"
@@ -38690,7 +39397,7 @@ msgid "Tags:"
msgstr "Étiquettes :"
msgid "TagsPage|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this tag."
-msgstr ""
+msgstr "Une fois que vous aurez confirmé et cliqué sur %{strongStart}%{buttonText}%{strongEnd}, vous ne pourrez plus restaurer cette étiquette."
msgid "TagsPage|Browse commits"
msgstr "Parcourir les commits"
@@ -38705,31 +39412,31 @@ msgid "TagsPage|Cancel"
msgstr "Annuler"
msgid "TagsPage|Cancel, keep tag"
-msgstr ""
+msgstr "Annuler, conserver l'étiquette"
msgid "TagsPage|Create release"
-msgstr ""
+msgstr "Créer une version"
msgid "TagsPage|Create tag"
msgstr "Créer l’étiquette"
msgid "TagsPage|Delete protected tag"
-msgstr ""
+msgstr "Supprimer l’étiquette protégée"
msgid "TagsPage|Delete protected tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Supprimer l'étiquette protégée. Êtes-vous ABSOLUMENT SÛR ?"
msgid "TagsPage|Delete tag"
msgstr "Supprimer l’étiquette"
msgid "TagsPage|Delete tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Supprimer l'étiquette. Êtes-vous ABSOLUMENT SÛR ?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "La suppression de l’étiquette %{strongStart}%{tagName}%{strongEnd} ne peut être annulée. Êtes-vous sûr(e) ?"
msgid "TagsPage|Edit release"
-msgstr ""
+msgstr "Modifier la version"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Branche, étiquette ou condensat SHA d’un commit"
@@ -38744,16 +39451,16 @@ msgid "TagsPage|New tag"
msgstr "Nouvelle étiquette"
msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
-msgstr ""
+msgstr "Seul un propriétaire ou un mainteneur du projet peut supprimer une étiquette protégée"
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
msgstr ""
msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
-msgstr ""
+msgstr "Éventuellement, créez une Version publique de votre projet, basée sur cette étiquette. Les notes de version sont affichées sur la page des %{releases_page_link_start}Versions%{link_end} . %{docs_link_start}Plus d'informations%{link_end}"
msgid "TagsPage|Please type the following to confirm:"
-msgstr ""
+msgstr "Veuillez taper ce qui suit pour confirmer :"
msgid "TagsPage|Release notes"
msgstr "Notes de version"
@@ -38774,7 +39481,7 @@ msgid "TagsPage|This tag has no release notes."
msgstr "Cette étiquette n’a pas de notes de version."
msgid "TagsPage|Unable to load tags"
-msgstr ""
+msgstr "Impossible de charger les étiquettes"
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "Utilisez la commande « git tag » pour en rajouter :"
@@ -38783,16 +39490,16 @@ msgid "TagsPage|Write your release notes or drag files here…"
msgstr "Rédigez vos notes de version ou faites glisser des fichiers ici…"
msgid "TagsPage|Yes, delete protected tag"
-msgstr ""
+msgstr "Oui, supprimer l’étiquette protégée"
msgid "TagsPage|Yes, delete tag"
-msgstr ""
+msgstr "Oui, supprimer l’étiquette"
msgid "TagsPage|You're about to permanently delete the protected tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement l’étiquette protégée %{strongStart}%{tagName}.%{strongEnd}"
msgid "TagsPage|You're about to permanently delete the tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement l'étiquette %{strongStart}%{tagName}.%{strongEnd}"
msgid "TagsPage|protected"
msgstr "protégé"
@@ -38804,7 +39511,7 @@ msgid "Target Branch"
msgstr "Branche cible"
msgid "Target Path"
-msgstr ""
+msgstr "Chemin cible"
msgid "Target branch"
msgstr "Branche cible"
@@ -38816,25 +39523,25 @@ msgid "Target roles"
msgstr ""
msgid "Target-Branch"
-msgstr ""
+msgstr "Branche-cible"
msgid "Task"
-msgstr ""
+msgstr "Tâche"
msgid "Task ID: %{elastic_task}"
-msgstr ""
+msgstr "ID de la tâche : %{elastic_task}"
msgid "Task list"
-msgstr ""
+msgstr "Liste des tâches"
msgid "TasksToBeDone|Create/import code into a project (repository)"
-msgstr ""
+msgstr "Créer/importer du code dans un projet (dépôt)"
msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
-msgstr ""
+msgstr "Créer/importer des tickets pour collaborer sur des idées et planifier le travail"
msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
-msgstr ""
+msgstr "Configurer des pipelines CI/CD pour construire, tester, déployer et surveiller le code"
msgid "Team"
msgstr "Équipe"
@@ -38843,40 +39550,40 @@ msgid "Team domain"
msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
-msgstr ""
+msgstr "Déclencher TeamCity CI après la création ou la mise à jour d'une demande de fusion"
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
-msgstr ""
+msgstr "Déclencher TeamCity CI après chaque poussée vers le dépôt, sauf suppression de branche"
msgid "Telephone number"
-msgstr ""
+msgstr "Numéro de téléphone"
msgid "Template"
msgstr "Modèle"
msgid "Template to append to all Service Desk issues"
-msgstr ""
+msgstr "Modèle à ajouter à tous les tickets du service d'assistance"
msgid "TemplateRepository|Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "Créer des fichiers ordinaires plus rapidement, et uniformiser leur format."
msgid "Templates"
msgstr ""
msgid "TemporaryStorageIncrease|can only be set once"
-msgstr ""
+msgstr "ne peut être défini qu'une seule fois"
msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
-msgstr ""
+msgstr "ne peut être défini qu'avec plus de %{percentage}%% d'utilisation"
msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
-msgstr ""
+msgstr "GitLab vous autorise une %{strongStart}augmentation gratuite, ponctuelle, du stockage%{strongEnd}. Pendant 30 jours, votre espace de stockage sera illimité. Cela vous donne le temps d'en réduire votre utilisation. Après 30 jours, votre limite d'origine de %{limit} sera appliquée. Si vous êtes à la capacité de stockage maximale, votre compte sera en lecture seule. Pour continuer à utiliser GitLab, vous devrez en acheter davantage ou en diminuer l'utilisation."
msgid "TemporaryStorage|Increase storage temporarily"
-msgstr ""
+msgstr "Augmenter temporairement le stockage"
msgid "TemporaryStorage|Temporarily increase storage now?"
-msgstr ""
+msgstr "Augmenter temporairement le stockage maintenant ?"
msgid "Terminal"
msgstr ""
@@ -38894,22 +39601,22 @@ msgid "Terms of Service and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
msgid "Terms of service"
-msgstr ""
+msgstr "Conditions d’Utilisation"
msgid "Terraform"
msgstr ""
msgid "TerraformBanner|Learn more about GitLab's Backend State"
-msgstr ""
+msgstr "En savoir plus sur le Backend État de GitLab"
msgid "TerraformBanner|The GitLab managed Terraform state backend can store your Terraform state easily and securely, and spares you from setting up additional remote resources. Its features include: versioning, encryption of the state file both in transit and at rest, locking, and remote Terraform plan/apply execution."
-msgstr ""
+msgstr "Le backend d'état Terraform géré par GitLab peut stocker votre état Terraform facilement et en toute sécurité, et vous évite de configurer des ressources distantes supplémentaires. Ses fonctionnalités incluent : la gestion des versions, le chiffrement du fichier d'état à la fois en transit et au repos, le verrouillage et l'exécution à distance de Terraform plan/apply."
msgid "TerraformBanner|Using Terraform? Try the GitLab Managed Terraform State"
-msgstr ""
+msgstr "Terraform est utilisé ? Essayez l'État Terraform Géré par GitLab"
msgid "Terraform|%{name} successfully removed"
-msgstr ""
+msgstr "%{name} supprimé avec succès"
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
@@ -38918,8 +39625,8 @@ msgstr[1] ""
msgid "Terraform|%{number} Terraform report was generated in your pipelines"
msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{number} rapport Terraform a été généré dans vos pipelines"
+msgstr[1] "%{number} rapports Terraform ont été générés dans vos pipelines"
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
@@ -38928,47 +39635,47 @@ msgstr[1] ""
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report was generated in your pipelines"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports were generated in your pipelines"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{number}%{strong_end} rapport Terraform a été généré dans vos pipelines"
+msgstr[1] "%{strong_start}%{number}%{strong_end} rapports Terraform ont été générés dans vos pipelines"
msgid "Terraform|%{user} updated %{timeAgo}"
-msgstr ""
+msgstr "Actualisation par %{user} %{timeAgo}"
msgid "Terraform|A Terraform report failed to generate."
-msgstr ""
+msgstr "La génération d'un rapport Terraform a échoué."
msgid "Terraform|A Terraform report was generated in your pipelines."
-msgstr ""
+msgstr "Un rapport Terraform a été généré dans vos pipelines."
msgid "Terraform|A report failed to generate."
-msgstr ""
+msgstr "La génération d'un rapport a échoué."
msgid "Terraform|A report was generated in your pipelines."
-msgstr ""
+msgstr "Un rapport a été généré dans vos pipelines."
msgid "Terraform|Actions"
-msgstr ""
+msgstr "Actions"
msgid "Terraform|An error occurred while changing the state file"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la modification du fichier d'état"
msgid "Terraform|An error occurred while loading your Terraform States"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement de vos États Terraform"
msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir supprimer l’État Terraform %{name} ?"
msgid "Terraform|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "Terraform|Cannot remove a locked state"
-msgstr ""
+msgstr "Impossible de supprimer un état verrouillé"
msgid "Terraform|Copy Terraform init command"
-msgstr ""
+msgstr "Copier la commande Terraform init"
msgid "Terraform|Deletion in progress"
-msgstr ""
+msgstr "Suppression en cours"
msgid "Terraform|Details"
msgstr ""
@@ -38977,40 +39684,40 @@ msgid "Terraform|Download JSON"
msgstr ""
msgid "Terraform|Failed to load Terraform reports"
-msgstr ""
+msgstr "Échec du chargement des rapports Terraform"
msgid "Terraform|Generating the report caused an error."
-msgstr ""
+msgstr "La génération du rapport a provoqué une erreur."
msgid "Terraform|How to use GitLab-managed Terraform state?"
msgstr ""
msgid "Terraform|Job status"
-msgstr ""
+msgstr "État de la tâche"
msgid "Terraform|Loading Terraform reports..."
-msgstr ""
+msgstr "Chargement des rapports Terraform..."
msgid "Terraform|Lock"
-msgstr ""
+msgstr "Verrouiller"
msgid "Terraform|Locked"
msgstr ""
msgid "Terraform|Locked by %{user} %{timeAgo}"
-msgstr ""
+msgstr "Verrouillage par %{user} %{timeAgo}"
msgid "Terraform|Locking state"
msgstr ""
msgid "Terraform|Name"
-msgstr ""
+msgstr "Nom"
msgid "Terraform|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "Terraform|Remove"
-msgstr ""
+msgstr "Supprimer"
msgid "Terraform|Remove state file and versions"
msgstr ""
@@ -39019,119 +39726,119 @@ msgid "Terraform|Removed"
msgstr ""
msgid "Terraform|Removing"
-msgstr ""
+msgstr "Suppression"
msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
-msgstr ""
+msgstr "Modifications de ressources signalées : %{addNum} à ajouter, %{changeNum} à modifier, %{deleteNum} à supprimer"
msgid "Terraform|States"
-msgstr ""
+msgstr "États"
msgid "Terraform|Terraform init command"
-msgstr ""
+msgstr "Commande Terraform init"
msgid "Terraform|Terraform reports"
-msgstr ""
+msgstr "Rapports Terraform"
msgid "Terraform|The job %{name} failed to generate a report."
-msgstr ""
+msgstr "La tâche %{name} n'a pas pu générer de rapport."
msgid "Terraform|The job %{name} generated a report."
-msgstr ""
+msgstr "La tâche %{name} a généré un rapport."
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
-msgstr ""
+msgstr "La tâche %{strong_start}%{name}%{strong_end} n'a pas réussi à générer un rapport."
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} generated a report."
-msgstr ""
+msgstr "La tâche %{strong_start}%{name}%{strong_end} a généré un rapport."
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 ""
+msgstr "Pour obtenir l'accès à cet état terraform depuis votre ordinateur local, exécutez la commande suivante sur la ligne de commande. La première ligne nécessite un jeton d'accès personnel avec accès en lecture et en écriture à l'API. %{linkStart}Comment créer un jeton d'accès personnel ?%{linkEnd}."
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
msgstr ""
msgid "Terraform|Unknown User"
-msgstr ""
+msgstr "Utilisateur Inconnu"
msgid "Terraform|Unlock"
-msgstr ""
+msgstr "Déverrouiller"
msgid "Terraform|Unlocking state"
msgstr ""
msgid "Terraform|You are about to remove the state file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously will remain intact, and only the state file with all its versions will be removed. This action cannot be undone."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer le fichier d'état %{name}. Cela supprimera définitivement toutes les versions de l'état ainsi que l'historique. L'infrastructure provisionnée précédemment restera intacte, et seuls le fichier d'état et la totalité de ses versions seront supprimés. Cette action n'est pas réversible."
msgid "Terraform|You have insufficient permissions to delete this state"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer cet état"
msgid "Terraform|Your project doesn't have any Terraform state files"
-msgstr ""
+msgstr "Votre projet n'a aucun fichier d'état Terraform"
msgid "Test"
-msgstr ""
+msgstr "Test"
msgid "Test Cases"
-msgstr ""
+msgstr "Cas de test"
msgid "Test case"
-msgstr ""
+msgstr "Scénario de test"
msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La valeur de la couverture de test de ce pipeline a été calculée à partir de celle de %d tâche."
+msgstr[1] "La valeur de la couverture de test de ce pipeline a été calculée en faisant la moyenne de celles résultant de %d tâches."
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Couverture de test : %d atteint"
+msgstr[1] "Couverture de test : %d atteints"
msgid "Test settings"
-msgstr ""
+msgstr "Paramètres de test"
msgid "TestCases|Move test case"
-msgstr ""
+msgstr "Déplacer le cas de test"
msgid "TestCases|Moving test case"
-msgstr ""
+msgstr "Déplacement du cas de test"
msgid "TestCases|New Test Case"
-msgstr ""
+msgstr "Nouveau Cas de Test"
msgid "TestCases|New test case"
-msgstr ""
+msgstr "Nouveau cas de test"
msgid "TestCases|Search test cases"
-msgstr ""
+msgstr "Rechercher des cas de test"
msgid "TestCases|Something went wrong while adding test case to a to-do item."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'ajout du scénario de test à un élément À faire."
msgid "TestCases|Something went wrong while creating a test case."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création d'un cas de test."
msgid "TestCases|Something went wrong while fetching test case."
msgstr ""
msgid "TestCases|Something went wrong while fetching test cases list."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de la liste des cas de test."
msgid "TestCases|Something went wrong while marking test case to-do item as done."
-msgstr ""
+msgstr "Une erreur s'est produite lors du marquage de l'élément À faire du scénario de test comme terminé."
msgid "TestCases|Something went wrong while moving test case."
-msgstr ""
+msgstr "Une erreur s'est produite lors du déplacement du cas de test."
msgid "TestCases|Something went wrong while updating the test case labels."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des étiquettes des cas de test."
msgid "TestCases|Something went wrong while updating the test case."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du cas de test."
msgid "TestCases|Submit test case"
-msgstr ""
+msgstr "Envoyer un cas de test"
msgid "TestHooks|Ensure one of your projects has merge requests."
msgstr ""
@@ -39167,34 +39874,34 @@ msgid "TestReports|%{count} failures"
msgstr ""
msgid "TestReports|%{count} tests"
-msgstr ""
+msgstr "%{count} tests"
msgid "TestReports|%{rate}%{sign} success rate"
msgstr ""
msgid "TestReports|Attachment"
-msgstr ""
+msgstr "Pièce jointe"
msgid "TestReports|Copy test name to rerun locally"
-msgstr ""
+msgstr "Copier le nom du test pour le relancer en local"
msgid "TestReports|Job artifacts are expired"
-msgstr ""
+msgstr "Les artéfacts de tâche ont expiré"
msgid "TestReports|Jobs"
-msgstr ""
+msgstr "Tâches"
msgid "TestReports|Learn how to upload pipeline test reports"
-msgstr ""
+msgstr "Apprenez à téléverser des rapports de tests de pipeline"
msgid "TestReports|Learn more about pipeline test reports"
-msgstr ""
+msgstr "En savoir plus sur les rapports de tests de pipeline"
msgid "TestReports|No test cases were found in the test report."
-msgstr ""
+msgstr "Aucun cas de test n'a été trouvé dans le rapport de tests."
msgid "TestReports|Test reports require job artifacts but all artifacts are expired. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Les rapports de tests nécessitent des artéfacts de tâche mais tous ces derniers ont expiré. %{linkStart}En savoir plus%{linkEnd}"
msgid "TestReports|Tests"
msgstr ""
@@ -39203,52 +39910,52 @@ msgid "TestReports|There are no test cases to display."
msgstr ""
msgid "TestReports|There are no test reports for this pipeline"
-msgstr ""
+msgstr "Il n’y a aucun rapport de tests pour ce pipeline"
msgid "TestReports|There are no test suites to show."
msgstr ""
msgid "TestReports|There are no tests to display"
-msgstr ""
+msgstr "Il n'y a aucun test à afficher"
msgid "TestReports|There was an error fetching the summary."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération du résumé."
msgid "TestReports|There was an error fetching the test suite."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération de la suite de tests."
msgid "TestReports|You can configure your job to use unit test reports, and GitLab displays a report here and in the related merge request."
-msgstr ""
+msgstr "Vous pouvez configurer votre tâche pour utiliser des rapports de tests unitaires, et GitLab affichera un rapport ici ainsi que dans la demande de fusion associée."
msgid "Tests"
msgstr ""
msgid "Text (optional)"
-msgstr ""
+msgstr "Texte (facultatif)"
msgid "Text added to the body of all email messages. %{character_limit} character limit"
-msgstr ""
+msgstr "Texte ajouté au corps de tous les courriels. Limite de %{character_limit} caractères"
msgid "Text style"
-msgstr ""
+msgstr "Style de texte"
msgid "Thank you for your business."
-msgstr ""
+msgstr "Merci de votre confiance."
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
-msgstr ""
+msgstr "Merci pour votre demande de support ! Nous suivrons votre demande via le ticket #%{issue_iid} et nous y répondrons dès que possible."
msgid "Thanks for signing up to GitLab!"
-msgstr ""
+msgstr "Merci de vous être inscrit sur GitLab !"
msgid "Thanks for your purchase!"
-msgstr ""
+msgstr "Merci pour votre achat !"
msgid "That's OK, I don't want to renew"
-msgstr ""
+msgstr "Merci, je ne souhaite pas de renouvellement"
msgid "That's it, well done!"
msgstr "Voilà, bien joué!"
@@ -39257,7 +39964,7 @@ msgid "The %{link_start}true-up model%{link_end} allows having more users, and a
msgstr ""
msgid "The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}."
-msgstr ""
+msgstr "Le %{plan_name} n'est plus disponible à l'achat. Pour plus d'informations sur l'impact que cela aura sur vous, consultez notre %{faq_link_start}foire aux questions%{faq_link_end}."
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
@@ -39265,19 +39972,19 @@ msgstr[0] ""
msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
-msgstr ""
+msgstr "La clé d'API utilisée par GitLab pour accéder au point de terminaison du service Spam Check."
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
msgstr "L'export CSV sera créé en tâche de fond. Une fois terminé, il sera envoyé en pièce-jointe à %{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 ""
+msgstr "Le service abonnement de GitLab (customers.gitlab.com) connaît actuellement une panne. Vous pouvez surveiller la situation et avoir des nouvelles sur %{linkStart}status.gitlab.com%{linkEnd}."
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
-msgstr ""
+msgstr "L’utilisateur GitLab auquel l’utilisateur Jira %{jiraDisplayName} sera associé"
msgid "The ID of the application."
-msgstr ""
+msgstr "L'ID de l'application."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "Le système de suivi est un endroit où l’on peut ouvrir un ticket pour signaler des choses à améliorer ou des dysfonctionnements à résoudre dans un projet"
@@ -39286,19 +39993,19 @@ msgid "The Issue Tracker is the place to add things that need to be improved or
msgstr "Le système de suivi est un endroit où l’on peut ouvrir un ticket pour signaler des choses à améliorer ou des dysfonctionnements à résoudre dans un projet. Vous pouvez vous inscrire ou vous connecter pour créer des tickets de suivi pour ce projet."
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
-msgstr ""
+msgstr "Le serveur Prometheus a répondu par « mauvaise requête ». Veuillez vérifier que vos requêtes sont correctes et prises en charge par votre version de Prometheus. %{documentationLink}"
msgid "The Snowplow cookie domain."
-msgstr ""
+msgstr "Le domaine des cookies de Snowplow."
msgid "The URL of the Jenkins server."
-msgstr ""
+msgstr "L'URL du serveur Jenkins."
msgid "The URL should start with http:// or https://"
-msgstr ""
+msgstr "L'URL doit commencer par http:// ou https://"
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
-msgstr ""
+msgstr "Les URLs pour se connecter à Elasticsearch. Pour les grappes de serveurs, ajoutez les URLs séparées par des virgules."
msgid "The `/merge` quick action requires the SHA of the head of the branch."
msgstr ""
@@ -39313,22 +40020,22 @@ msgid "The branch for this project has no active pipeline configuration."
msgstr ""
msgid "The branch or tag does not exist"
-msgstr ""
+msgstr "La branche ou le tag n'existe pas"
msgid "The broadcast message displays only to users in projects and groups who have these roles."
-msgstr ""
+msgstr "Le message de diffusion ne s'adresse qu'aux utilisateurs des projets et des groupes qui ont ces rôles."
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "Le surligneur de caractères vous aide à garder la longueur de l’objet à %{titleLength} caractères maximum et à faire des renvois à la ligne pour limiter les lignes du corps du message à %{bodyLength} caractères, afin de les rendre lisibles sous Git."
msgid "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?"
-msgstr ""
+msgstr "Le commentaire que vous êtes en train d'éditer a été modifié par un autre utilisateur. Voulez-vous conserver vos modifications et remplacer la nouvelle description ou les abandonner ?"
msgid "The commit does not exist"
-msgstr ""
+msgstr "La validation n’existe pas"
msgid "The comparison view may be inaccurate due to merge conflicts."
-msgstr ""
+msgstr "La vue comparative peut être inexacte en raison de conflits de fusion."
msgid "The complete DevOps platform. One application with endless possibilities. Organizations rely on GitLab’s source code management, CI/CD, security, and more to deliver software rapidly."
msgstr ""
@@ -39343,7 +40050,7 @@ msgid "The contact does not belong to the issue group's root ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
-msgstr ""
+msgstr "L'éditeur de contenu peut modifier le style de mise en forme markdown du document, qui peut ne pas correspondre à votre style markdown d'origine."
msgid "The content for this wiki page failed to load. To fix this error, reload the page."
msgstr ""
@@ -39358,31 +40065,31 @@ msgid "The contents of this group, its subgroups and projects will be permanentl
msgstr ""
msgid "The current epic"
-msgstr ""
+msgstr "L'épopée actuelle"
msgid "The current incident"
-msgstr ""
+msgstr "L'incident actuel"
msgid "The current issue"
msgstr ""
msgid "The current user is not authorized to access the job log."
-msgstr ""
+msgstr "L'utilisateur actuel n'est pas autorisé à accéder au journal des tâches."
msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
-msgstr ""
+msgstr "Les données de ce pipeline sont trop anciennes pour être rendues sous forme de graphique. Veuillez vérifier l'onglet Tâches pour accéder à l'historique des données."
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
-msgstr ""
+msgstr "La source de données est connectée mais il n'y a aucune donnée à afficher. %{documentationLink}"
msgid "The date when the release is ready. A release with a date in the future is labeled as an %{linkStart}Upcoming Release%{linkEnd}."
-msgstr ""
+msgstr "La date à laquelle la version est prête. Une version avec une date dans le futur est étiquetée en tant que %{linkStart}version à venir%{linkEnd}."
msgid "The default CI/CD configuration file and path for new projects."
-msgstr ""
+msgstr "Le fichier de configuration CI/CD et le chemin par défaut des nouveaux projets."
msgid "The default branch for this project has been changed. Please update your bookmarks."
-msgstr ""
+msgstr "La branche par défaut de ce projet a été modifiée. Veuillez mettre à jour vos favoris."
msgid "The dependency list details information about the components used within your project."
msgstr ""
@@ -39400,19 +40107,19 @@ msgid "The domain you entered is not allowed."
msgstr ""
msgid "The download link will expire in 24 hours."
-msgstr ""
+msgstr "Le lien de téléchargement expirera dans 24 heures."
msgid "The environment tiers must be from %{environment_tiers}."
-msgstr ""
+msgstr "Le type d'environnement doit au moins être %{environment_tiers}."
msgid "The errors we encountered were:"
-msgstr ""
+msgstr "Les erreurs que nous avons rencontrées sont :"
msgid "The file containing the export is not available yet; it may still be transferring. Please try again later."
-msgstr ""
+msgstr "Le fichier contenant l'export n'est pas encore disponible ; il peut toujours être en cours de transfert. Veuillez réessayer plus tard."
msgid "The file could not be displayed because it is empty or larger than the maximum file size indexed (%{size})."
-msgstr ""
+msgstr "Le fichier ne peut pas être affiché car il est vide ou de taille supérieure à celle maximale indexée (%{size})."
msgid "The file has been successfully created."
msgstr ""
@@ -39421,10 +40128,10 @@ msgid "The file has been successfully deleted."
msgstr ""
msgid "The file name should have a .yml extension"
-msgstr ""
+msgstr "Le nom du fichier doit avoir une extension .yml"
msgid "The finding is not a vulnerability because it is part of a test or is test data."
-msgstr ""
+msgstr "L'élément découvert n'est pas une vulnérabilité car il fait partie d'un test ou correspond aux données d'un test."
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -39436,7 +40143,7 @@ msgid "The following Personal Access Token was revoked by an administrator, %{us
msgstr ""
msgid "The following SSH key was deleted by an administrator, %{username}."
-msgstr ""
+msgstr "La clé SSH suivante a été supprimée par un administrateur, %{username}."
msgid "The following items will NOT be exported:"
msgstr ""
@@ -39454,14 +40161,14 @@ msgstr "La relation de divergence a été supprimée."
msgid "The form contains the following error:"
msgid_plural "The form contains the following errors:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le formulaire contient l'erreur suivante :"
+msgstr[1] "Le formulaire contient les erreurs suivantes :"
msgid "The form contains the following warning:"
-msgstr ""
+msgstr "Le formulaire contient l'avertissement suivant :"
msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
-msgstr ""
+msgstr "Le serveur git, Gitaly, n'est pas disponible pour le moment. Veuillez contacter votre administrateur."
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -39476,7 +40183,7 @@ msgid "The group and its projects can only be viewed by members."
msgstr ""
msgid "The group export can be downloaded from:"
-msgstr ""
+msgstr "L'export du groupe peut être téléchargé à partir de :"
msgid "The group has already been shared with this group"
msgstr ""
@@ -39485,13 +40192,13 @@ msgid "The group settings for %{group_links} require you to enable Two-Factor Au
msgstr ""
msgid "The group_project_ids parameter is only allowed for a group"
-msgstr ""
+msgstr "Le paramètre group_project_ids n'est autorisé que pour un groupe"
msgid "The hostname of your PlantUML server."
-msgstr ""
+msgstr "Le nom d'hôte de votre serveur PlantUML."
msgid "The hostname of your Snowplow collector."
-msgstr ""
+msgstr "Le nom d'hôte de votre collecteur Snowplow."
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "L’importation expirera après %{timeout}. Pour les dépôts qui prennent plus de temps, utilisez une combinaison de clone et push."
@@ -39500,7 +40207,7 @@ msgid "The interval must be one of %{intervals}."
msgstr ""
msgid "The invitation can not be found with the provided invite token."
-msgstr ""
+msgstr "L'invitation ne peut pas être trouvée avec le jeton d'invitation fourni."
msgid "The invitation could not be accepted."
msgstr ""
@@ -39515,25 +40222,25 @@ msgid "The invitation was successfully resent."
msgstr ""
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
-msgstr ""
+msgstr "Le ticket a été promu en épopée avec succès. Redirection vers l'épopée..."
msgid "The last owner cannot be set to awaiting"
msgstr ""
msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
-msgstr ""
+msgstr "Les derniers artéfacts créés par les tâches du pipeline réussi le plus récemment seront enregistrés."
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
-msgstr ""
+msgstr "Le dernier pipeline de cette demande de fusion n'a pas réussi. Les dernières modifications ne sont pas vérifiées."
msgid "The latest pipeline for this merge request has failed."
-msgstr ""
+msgstr "Le dernier pipeline de cette demande de fusion a échoué."
msgid "The license key is invalid."
-msgstr ""
+msgstr "La clé de licence n'est pas valide."
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
-msgstr ""
+msgstr "La clé de licence n’est pas valide. Assurez-vous qu'elle est exactement telle que vous l'avez reçue de GitLab Inc."
msgid "The license was removed. GitLab has fallen back on the previous license."
msgstr ""
@@ -39545,34 +40252,34 @@ msgid "The license was successfully uploaded and is now active. You can see the
msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
-msgstr ""
+msgstr "La licence a été téléversée avec succès et sera active à partir du %{starts_at}. Vous pouvez voir les détails ci-dessous."
msgid "The license you uploaded is invalid. If the issue persists, contact support at %{link}."
-msgstr ""
+msgstr "La licence que vous avez téléversée n'est pas valide. Si le problème persiste, contactez le support sur %{link}."
msgid "The list creation wizard is already open"
-msgstr ""
+msgstr "L'assistant de création de liste est déjà ouvert"
msgid "The maximum amount of time users have to set up two-factor authentication before it's enforced."
-msgstr ""
+msgstr "La durée maximale avant que l'authentification à deux facteurs ne soit imposée pour les utilisateurs qui l'ont activée."
msgid "The maximum file size allowed is %{size}."
msgstr ""
msgid "The maximum file size for job artifacts."
-msgstr ""
+msgstr "La taille maximale de fichier pour les artéfacts des tâches."
msgid "The maximum file size in megabytes for individual job artifacts."
-msgstr ""
+msgstr "La taille maximale de fichier en mégaoctets pour les artéfacts de tâche individuels."
msgid "The maximum file size is %{size}."
-msgstr ""
+msgstr "La taille de fichier maximale est de %{size}."
msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
-msgstr ""
+msgstr "Le nombre maximal de minutes CI/CD sur les exécuteurs partagés qu'un groupe peut utiliser chaque mois. 0 pour illimité."
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 ""
+msgstr "Le nombre maximal d'étiquettes qu'un worker unique accepte de nettoyer. Si le nombre d'étiquettes vient à dépasser cette limite, la liste des étiquettes à supprimer est tronquée à cette valeur. Pour enlever cette limite, définissez-la à 0."
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -39587,43 +40294,43 @@ msgid "The metric must be one of %{metrics}."
msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
-msgstr ""
+msgstr "Le nom \"%{name}\" est déjà pris dans ce répertoire."
msgid "The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close})."
-msgstr ""
+msgstr "Le nom du fichier de configuration CI/CD. Un chemin relatif au répertoire racine est optionnel (par exemple %{code_open}mon/chemin/.myfile.yml%{code_close})."
msgid "The name of the Jenkins project. Copy the name from the end of the URL to the project."
-msgstr ""
+msgstr "Le nom du projet Jenkins. Copiez-le en prenant la fin de l'URL du projet."
msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
-msgstr ""
+msgstr "Le nombre de modifications à récupérer depuis GitLab lors du clonage d'un dépôt. Des valeurs plus basses peuvent accélérer l'exécution du pipeline. Définir sur %{code_open}0%{code_close} ou laisser vide pour récupérer toutes les branches et étiquettes pour chaque tâche"
msgid "The number of merge requests merged by month."
-msgstr ""
+msgstr "Le nombre de demandes de fusion fusionnées par mois."
msgid "The number of times an upload record could not find its file"
msgstr ""
msgid "The page could not be displayed because it timed out."
-msgstr ""
+msgstr "La page n'a pas pu être affichée car le délai d'attente a expiré."
msgid "The parent epic is confidential and can only contain confidential epics and issues"
-msgstr ""
+msgstr "L'épopée parente est confidentielle et ne peut contenir que des épopées et des tickets confidentiels"
msgid "The parsed YAML is too big"
-msgstr ""
+msgstr "Le YAML analysé est trop volumineux"
msgid "The password for the Jenkins server."
-msgstr ""
+msgstr "Le mot de passe du serveur Jenkins."
msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
-msgstr ""
+msgstr "Le mot de passe de votre compte GitLab sur %{gitlab_url} a été modifié avec succès."
msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
-msgstr ""
+msgstr "Le mot de passe de votre compte GitLab sur %{link_to_gitlab} a été modifié avec succès."
msgid "The pipeline has been deleted"
-msgstr ""
+msgstr "La pipeline a été supprimée"
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr "La planification des pipelines permet l’exécution de pipelines programmés, de manière récurrente, pour des branches ou des étiquettes spécifiques. Ces pipelines programmés hériteront d’un accès limité aux projets en fonction de l’utilisateur qui leur est associé."
@@ -39635,13 +40342,13 @@ msgid "The project can be accessed without any authentication."
msgstr "Votre projet est accessible sans aucune authentification."
msgid "The project has already been added to your dashboard."
-msgstr ""
+msgstr "Le projet a déjà été ajouté à votre tableau de bord."
msgid "The project is still being deleted. Please try again later."
msgstr ""
msgid "The project size exceeds the export limit."
-msgstr ""
+msgstr "La taille du projet dépasse la limite d'exportation."
msgid "The project was successfully forked."
msgstr ""
@@ -39653,7 +40360,7 @@ msgid "The related CI build failed."
msgstr ""
msgid "The remote mirror URL is invalid."
-msgstr ""
+msgstr "L'URL du miroir distant n'est pas valide."
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -39665,10 +40372,10 @@ msgid "The report artifact provided by the CI build couldn't be parsed."
msgstr ""
msgid "The report has been successfully prepared."
-msgstr ""
+msgstr "Le rapport a été préparé avec succès."
msgid "The repository can be committed to, and issues, comments and other entities can be created."
-msgstr ""
+msgstr "Des commits, des tickets, des commentaires et d'autres entités peuvent être créés sur le dépôt."
msgid "The repository for this project does not exist."
msgstr "Le dépôt de ce projet n’existe pas."
@@ -39680,18 +40387,21 @@ msgid "The repository is being updated..."
msgstr ""
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "Le dépôt doit être accessible avec %{code_open}http://%{code_close}, %{code_open}https://%{code_close} ou %{code_open}git://%{code_close}."
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "Le dépôt doit être accessible avec %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} ou %{code_open}git://%{code_close}."
msgid "The resource that you are attempting to access does not exist or you don't have permission to perform this action."
-msgstr ""
+msgstr "La ressource à laquelle vous essayez d'accéder n'existe pas ou vous n'avez pas la permission d'effectuer cette action."
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
-msgstr ""
+msgstr "Le même exécuteur partagé exécute du code à partir de plusieurs projets, sauf si vous configurez le dimensionnement automatique avec %{link} à 1 (ce qui est le cas sur GitLab.com)."
msgid "The scan has been created."
+msgstr "L'analyse a été créée."
+
+msgid "The secret is only available when you first create the application."
msgstr ""
msgid "The snippet can be accessed without any authentication."
@@ -39704,40 +40414,40 @@ msgid "The snippet is visible only to project members."
msgstr ""
msgid "The snippet is visible to any logged in user except external users."
-msgstr ""
+msgstr "Tous les utilisateurs connectés peuvent voir l'extrait, à l'exception des utilisateurs externes."
msgid "The source project of this merge request has been removed."
-msgstr ""
+msgstr "Le projet source de cette demande de fusion a été supprimé."
msgid "The source topic and the target topic are identical."
-msgstr ""
+msgstr "Le sujet source et le sujet destination sont identiques."
msgid "The source topic is not a topic."
-msgstr ""
+msgstr "Le sujet source n'est pas un sujet."
msgid "The specified tab is invalid, please select another"
msgstr ""
msgid "The start date must be ealier than the end date."
-msgstr ""
+msgstr "La date de début doit être antérieure à la date de fin."
msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
-msgstr ""
+msgstr "Le sujet servira de titre pour le nouveau ticket et le message sera utilisé comme description. Les %{quickActionsLinkStart}actions rapides%{quickActionsLinkEnd} et la mise en forme avec %{markdownLinkStart}Markdown%{markdownLinkEnd} sont prises en charge."
msgid "The tag name can't be changed for an existing release."
-msgstr ""
+msgstr "Le nom d'étiquette d'une version existante ne peut pas être modifié."
msgid "The target topic is not a topic."
-msgstr ""
+msgstr "Le sujet destination n'est pas un sujet."
msgid "The time period in seconds that the maximum requests per project limit applies to."
-msgstr ""
+msgstr "La période en secondes à laquelle s'applique la limitation du nombre maximal de requêtes par projet."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "L’action de mise à jour expirera au bout de %{number_of_minutes} minutes. Pour les gros dépôts, utilisez une combinaison de clone et push."
msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
-msgstr ""
+msgstr "Le fichier téléversé n'était pas valide. Les extensions de fichier prises en charge sont %{extensions}."
msgid "The user is being deleted."
msgstr ""
@@ -39749,16 +40459,16 @@ msgid "The user map is a mapping of the FogBugz users that participated on your
msgstr "La carte des utilisateurs met en correspondance les utilisateurs de FogBugz qui ont participé à vos projets en précisant la manière dont leurs adresses de courriel et leurs noms d’utilisateur sont importés dans GitLab. Vous pouvez y apporter des modifications en remplissant le tableau ciâ€dessous."
msgid "The user you are trying to approve is not pending approval"
-msgstr ""
+msgstr "L'utilisateur que vous essayez d'approuver n'est pas en attente d'approbation"
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
msgid "The username for the Jenkins server."
-msgstr ""
+msgstr "Le nom d'utilisateur du serveur Jenkins."
msgid "The value of the provided variable exceeds the %{count} character limit"
-msgstr ""
+msgstr "La valeur de la variable fournie dépasse la limite de %{count} caractère"
msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
msgstr ""
@@ -39767,22 +40477,22 @@ msgid "The vulnerability is known, and has not been remediated or mitigated, but
msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
-msgstr ""
+msgstr "La vulnérabilité n'est plus détectée. Vérifiez qu'elle a été corrigée ou supprimée avant de changer son état."
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
-msgstr ""
+msgstr "La vulnérabilité n'est plus détectée. Vérifiez qu'elle a été corrigée avant de changer son état."
msgid "Theme"
msgstr ""
msgid "There are currently no events."
-msgstr ""
+msgstr "Il n'y a actuellement aucun événement."
msgid "There are currently no mirrored repositories."
-msgstr ""
+msgstr "Il n'y a actuellement aucun dépôt mis en miroir."
msgid "There are merge conflicts"
-msgstr ""
+msgstr "Il y a des conflits de fusion"
msgid "There are no GPG keys associated with this account."
msgstr ""
@@ -39797,7 +40507,7 @@ msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no Spam Logs"
-msgstr ""
+msgstr "Il n'y a pas de Journaux d'Indésirables"
msgid "There are no abuse reports!"
msgstr "Il n'y a aucun rapport d'abus !"
@@ -39806,22 +40516,22 @@ msgid "There are no archived projects yet"
msgstr "Il n’y a pas encore de projets archivés"
msgid "There are no archived requirements"
-msgstr ""
+msgstr "Il n'y a aucune exigence archivée"
msgid "There are no archived test cases"
-msgstr ""
+msgstr "Il n'y a aucun cas de test archivé"
msgid "There are no changed labels"
-msgstr ""
+msgstr "Il n'y a pas d'étiquettes modifiées"
msgid "There are no changes"
-msgstr ""
+msgstr "Il n'y a aucun changement"
msgid "There are no charts configured for this page"
msgstr ""
msgid "There are no closed epics"
-msgstr ""
+msgstr "Il n'y a pas d'épopée fermée"
msgid "There are no closed issues"
msgstr ""
@@ -39830,7 +40540,7 @@ msgid "There are no closed merge requests"
msgstr ""
msgid "There are no commits yet."
-msgstr ""
+msgstr "Il n'y a pas encore de commit."
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
@@ -39839,13 +40549,13 @@ msgid "There are no issues to show"
msgstr "Il n’y a aucun ticket à afficher"
msgid "There are no issues with the selected labels"
-msgstr ""
+msgstr "Il n'y a aucun ticket avec les étiquettes sélectionnées"
msgid "There are no matching files"
msgstr ""
msgid "There are no open epics"
-msgstr ""
+msgstr "Il n'y a pas d'épopée ouverte"
msgid "There are no open issues"
msgstr ""
@@ -39854,10 +40564,10 @@ msgid "There are no open merge requests"
msgstr ""
msgid "There are no open requirements"
-msgstr ""
+msgstr "Il n'y a aucune exigence ouverte"
msgid "There are no open test cases"
-msgstr ""
+msgstr "Il n'y a aucun cas de test ouvert"
msgid "There are no packages yet"
msgstr ""
@@ -39866,136 +40576,133 @@ msgid "There are no projects shared with this group yet"
msgstr "Il n’y a pas encore de projets partagés avec ce groupe"
msgid "There are no secure files yet."
-msgstr ""
+msgstr "Il n'y a pas encore de fichier sécurisé."
msgid "There are no topics to show."
msgstr "Il n'y a aucun sujet à afficher."
msgid "There are no variables yet."
-msgstr ""
+msgstr "Aucune variable pour le moment."
msgid "There are running deployments on the environment. Please retry later."
-msgstr ""
+msgstr "Des déploiements sont en cours sur l'environnement. Veuillez réessayer plus tard."
msgid "There are several file size limits in place for the Package Registry."
-msgstr ""
+msgstr "Plusieurs limitations sur la taille des fichiers sont définies pour le Registre de Paquets."
msgid "There are several rate limits in place to protect the system."
-msgstr ""
+msgstr "Il existe plusieurs limites de fréquence mises en place pour protéger le système."
msgid "There are several size limits in place."
-msgstr ""
+msgstr "Plusieurs limitations de tailles sont définies."
msgid "There is already a repository with that name on disk"
msgstr ""
msgid "There is already a to-do item for this design."
-msgstr ""
+msgstr "Il y a déjà un élément « À faire » pour ce design."
msgid "There is no chart data available."
-msgstr ""
+msgstr "Il n'y a aucune donnée de graphique disponible."
msgid "There is no data available."
-msgstr ""
+msgstr "Il n'y a aucune donnée disponible."
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
-msgstr ""
+msgstr "Il n'y a aucune donnée de tableau disponible."
msgid "There is too much data to calculate. Please change your selection."
-msgstr ""
+msgstr "Il y a trop de données à calculer. Veuillez modifier votre sélection."
msgid "There was a problem communicating with your device."
msgstr ""
msgid "There was a problem fetching CRM contacts."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des contacts du CRM."
msgid "There was a problem fetching CRM organizations."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des organisations du CRM."
msgid "There was a problem fetching branches."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des branches."
msgid "There was a problem fetching emojis."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des émojis."
msgid "There was a problem fetching epics."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des épopées."
msgid "There was a problem fetching groups."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des groupes."
msgid "There was a problem fetching iterations."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des itérations."
msgid "There was a problem fetching labels."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étiquettes."
msgid "There was a problem fetching linked pipelines."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des pipelines liés."
msgid "There was a problem fetching milestones."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des jalons."
msgid "There was a problem fetching project branches."
-msgstr ""
+msgstr "Un problème est survenu lors de la récupération des branches du projet."
msgid "There was a problem fetching project tags."
-msgstr ""
+msgstr "Un problème est survenu lors de la récupération des étiquettes du projet."
msgid "There was a problem fetching project users."
-msgstr ""
+msgstr "Un problème est survenu lors de la récupération des utilisateurs du projet."
msgid "There was a problem fetching recent groups."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des groupes récents."
msgid "There was a problem fetching recent projects."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets récents."
msgid "There was a problem fetching releases."
msgstr ""
msgid "There was a problem fetching the job token scope value"
-msgstr ""
+msgstr "Un problème est survenu lors de la récupération de la valeur de la portée du jeton de tâche"
msgid "There was a problem fetching the keep latest artifacts setting."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération du paramètre de conservation des derniers artéfacts."
msgid "There was a problem fetching the latest pipeline status."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération de l'état du dernier pipeline."
msgid "There was a problem fetching the pipeline stages."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étapes du pipeline."
msgid "There was a problem fetching the projects"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets"
msgid "There was a problem fetching users."
-msgstr ""
+msgstr "Un problème est survenu lors de la récupération des utilisateurs."
msgid "There was a problem handling the pipeline data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la gestion des données du pipeline."
msgid "There was a problem sending the confirmation email"
msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du paramètre de conservation des derniers artéfacts."
msgid "There was an error adding a To Do."
msgstr ""
msgid "There was an error creating the dashboard, branch name is invalid."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du tableau de bord, le nom de la branche n'est pas valide."
msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création du tableau de bord, la branche nommée : %{branch} existe déjà."
msgid "There was an error creating the issue"
msgstr ""
@@ -40016,52 +40723,52 @@ msgid "There was an error fetching label data for the selected group"
msgstr ""
msgid "There was an error fetching median data for stages"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données médianes des étapes"
msgid "There was an error fetching projects"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets"
msgid "There was an error fetching stage total counts"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération du nombre total d'étapes"
msgid "There was an error fetching the %{replicableType}"
msgstr ""
msgid "There was an error fetching the deploy freezes."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des gels de déploiement."
msgid "There was an error fetching the environments information."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des informations sur les environnements."
msgid "There was an error fetching the jobs for your project."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tâches de votre projet."
msgid "There was an error fetching the top labels for the selected group"
msgstr ""
msgid "There was an error fetching the variables."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des variables."
msgid "There was an error fetching value stream analytics stages."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des étapes de l'analyse des chaînes de valeur."
msgid "There was an error gathering the chart data"
msgstr ""
msgid "There was an error getting the epic participants."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'obtention des participants à l'épopée."
msgid "There was an error importing the Jira project."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'importation du projet Jira."
msgid "There was an error loading related feature flags"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des indicateurs de fonctionnalité associés"
msgid "There was an error loading users activity calendar."
msgstr "Une erreur s’est produite lors du chargement du calendrier d’activité des utilisateurs."
msgid "There was an error parsing the data for this graph."
-msgstr ""
+msgstr "Une erreur s'est produite lors de l'analyse des données de ce graphe."
msgid "There was an error removing the e-mail."
msgstr ""
@@ -40070,7 +40777,7 @@ msgid "There was an error resetting user pipeline minutes."
msgstr ""
msgid "There was an error retrieving the Jira users."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des utilisateurs Jira."
msgid "There was an error saving your changes."
msgstr ""
@@ -40079,7 +40786,7 @@ msgid "There was an error subscribing to this label."
msgstr "Une erreur s’est produite lors de l’abonnement à cette étiquette."
msgid "There was an error syncing project %{name}"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la synchronisation du projet %{name}"
msgid "There was an error syncing the %{replicableType}"
msgstr ""
@@ -40088,13 +40795,13 @@ msgid "There was an error trying to validate your query"
msgstr ""
msgid "There was an error updating the Maintenance Mode Settings"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour des Paramètres du Mode Maintenance"
msgid "There was an error updating the dashboard, branch name is invalid."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du tableau de bord, le nom de la branche n'est pas valide."
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la mise à jour du tableau de bord, la branche nommée : %{branch} existe déjà."
msgid "There was an error when reseting email token."
msgstr "Une erreur s’est produite lors de la réinitialisation du jeton de courriel."
@@ -40106,40 +40813,40 @@ msgid "There was an error when unsubscribing from this label."
msgstr "Une erreur s’est produite lors de la désinscription à cette étiquette."
msgid "There was an error while fetching the chart data. Please refresh the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données du graphique. Veuillez actualiser la page pour réessayer."
msgid "There was an error while fetching the table data. Please refresh the page to try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données du tableau. Veuillez actualiser la page pour réessayer."
msgid "There was an error while fetching value stream analytics data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données de l'analyse de chaînes de valeur."
msgid "There was an error while fetching value stream analytics duration data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données de durée de l'analyse des chaînes de valeur."
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
msgid "These dates affect how your epics appear in the roadmap. Set a fixed date or one inherited from the milestones assigned to issues in this epic."
-msgstr ""
+msgstr "Ces dates affectent la façon dont vos épopées apparaissent sur la feuille de route. Définissez une date fixe ou une date héritée des jalons attribués aux tickets de cette épopée."
msgid "These examples show how to trigger this project's pipeline for a branch or tag."
-msgstr ""
+msgstr "Ces exemples montrent comment déclencher le pipeline de ce groupe pour une branche ou une étiquette."
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
msgid "These runners are shared across projects in this group."
-msgstr ""
+msgstr "Ces exécuteurs sont partagés par tous les projets de ce groupe."
msgid "These runners are shared across this GitLab instance."
-msgstr ""
+msgstr "Ces exécuteurs sont partagés sur cette instance de GitLab."
msgid "These runners are specific to this project."
-msgstr ""
+msgstr "Ces exécuteurs sont spécifiques à ce projet."
msgid "These variables are inherited from the parent group."
-msgstr ""
+msgstr "Ces variables sont héritées du groupe parent."
msgid "These will be sent to %{email} in an attachment once finished."
msgstr ""
@@ -40148,13 +40855,13 @@ msgid "Things to be aware of before transferring:"
msgstr ""
msgid "Third Party Advisory Link"
-msgstr ""
+msgstr "Liens des Annonces d'Offres Tierces"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
-msgstr ""
+msgstr "Ce(tte) %{issuable} est verrouillé(e). Seuls les %{strong_open}membres du projet%{strong_close} peuvent apporter des commentaires."
msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{confidentialLinkEnd} and %{lockedLinkStart}locked%{lockedLinkEnd}."
msgstr ""
@@ -40166,70 +40873,67 @@ msgid "This %{viewer} could not be displayed because %{reason}. You can %{option
msgstr ""
msgid "This Cron pattern is invalid"
-msgstr ""
+msgstr "Ce motif Cron n'est pas valide"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
-msgstr ""
-
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
+msgstr "Cette instance de GitLab ne fournit aucun exécuteur partagé pour le moment. Les administrateurs de l’instance peuvent en enregistrer dans l'espace d’administration."
msgid "This PDF is too large to display. Please download to view."
-msgstr ""
+msgstr "Ce PDF est trop volumineux pour être affiché. Veuillez le télécharger pour pouvoir le faire."
msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
-msgstr ""
+msgstr "Ce projet est actuellement archivé et en lecture seule. Veuillez d'abord le désarchiver si vous voulez reprendre la mise en miroir de type pull"
msgid "This URL already exists."
-msgstr ""
+msgstr "Cette URL existe déjà."
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
-msgstr ""
+msgstr "Cette action ne pourra pas être annulée et supprimera définitivement la clé SSH %{key}"
msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} and everything this project contains. %{strongOpen}There is no going back.%{strongClose}"
-msgstr ""
+msgstr "Cette action supprime %{codeOpen}%{project_path_with_namespace}%{codeClose} et tout ce que ce projet contient. %{strongOpen}Il n'y a pas de retour possible.%{strongClose}"
msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains."
-msgstr ""
+msgstr "Cette action supprime %{codeOpen}%{project_path_with_namespace}%{codeClose} et tout ce que ce projet contient le %{date}."
msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains. %{strongOpen}There is no going back.%{strongClose}"
-msgstr ""
+msgstr "Cette action supprime %{codeOpen}%{project_path_with_namespace}%{codeClose} et tout ce que ce projet contient le %{date}. %{strongOpen}Il n'y a pas de retour possible.%{strongClose}"
msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}immediately%{strongClose}."
-msgstr ""
+msgstr "Cette action va %{strongOpen}supprimer définitivement%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}tout de suite%{strongClose}."
msgid "This also resolves all related threads"
msgstr ""
msgid "This also resolves this thread"
-msgstr ""
+msgstr "Cela résout également ce fil de conversation"
msgid "This application was created by %{user_link}."
-msgstr ""
+msgstr "Cette application a été créée par %{user_link}."
msgid "This application was created for group %{group_link}."
-msgstr ""
+msgstr "Cette application a été créée pour le groupe %{group_link}."
msgid "This application will be able to:"
msgstr "Cette application sera en mesure de :"
msgid "This archive has been requested too many times. Try again later."
-msgstr ""
+msgstr "Cette archive a été demandée trop souvent. Réessayez plus tard."
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 ""
+msgstr "Cette pièce-jointe a été tronquée pour éviter de dépasser la taille maximale autorisée de %{size_limit}. %{written_count} des %{count} %{issuables} ont été inclus. Envisagez de réexporter avec une sélection plus restreinte de %{issuables}."
msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr ""
+msgstr "Cette pièce-jointe a été tronquée pour éviter de dépasser la taille maximale autorisée de %{size_limit}. %{written_count} des %{issues_count} tickets ont été inclus. Envisagez de réexporter avec une sélection plus restreinte de tickets."
msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests."
-msgstr ""
+msgstr "Cette pièce-jointe a été tronquée pour éviter de dépasser la taille maximale autorisée de %{size_limit}. %{written_count} des %{merge_requests_count} demandes de fusion ont été incluses. Envisagez de réexporter avec une sélection plus restreinte de demandes de fusion."
msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{requirements_count} requirements have been included. Consider re-exporting with a narrower selection of requirements."
-msgstr ""
+msgstr "Cette pièce-jointe a été tronquée pour éviter de dépasser la taille maximale autorisée de %{size_limit}. %{written_count} des %{requirements_count} exigences ont été incluses. Envisagez de réexporter avec une sélection plus restreinte d'exigences."
msgid "This block is self-referential"
msgstr ""
@@ -40237,29 +40941,32 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr "La portée de ce tableau est réduite"
-msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
+msgid "This branch has diverged from upstream."
msgstr ""
+msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
+msgstr "Cette modification va supprimer %{strongOpen}TOUTES%{strongClose} les fonctionnalités Premium et Ultimate pour %{strongOpen}TOUS%{strongClose} les clients SaaS et faire échouer le démarrage des tests."
+
msgid "This chart could not be displayed"
msgstr ""
msgid "This clears repository check states for all projects in the database and cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Ceci efface les états de vérification du dépôt pour tous les projets de la base de données et cela ne peut pas être annulé. Êtes-vous sûr(e) ?"
msgid "This code snippet contains everything reflected in the configuration form. Copy and paste it into %{linkStart}.gitlab-ci.yml%{linkEnd} file and save your changes. Future %{scanType} scans will use these settings."
-msgstr ""
+msgstr "Cet extrait de code reflète tout ce que contient le formulaire de configuration. Faites-en un copier-coller dans le fichier %{linkStart}.gitlab-ci.yml%{linkEnd} puis enregistrez vos modifications. Les prochaines analyses %{scanType} utiliseront ces paramètres."
msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
-msgstr ""
+msgstr "Ce commentaire a changé depuis que vous avez commencé à le modifier. Examinez sa %{startTag}version actualisée%{endTag} pour vous assurer qu'il n'y a pas de perte d'information."
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 ""
+msgstr "Ce commit a été signé avec %{strong_open}plusieurs%{strong_close} signatures."
msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
-msgstr ""
+msgstr "Ce commit a été signé avec une signature %{strong_open}vérifiée%{strong_close} et le courriel du contributeur a bien été vérifié comme correspondant au même utilisateur."
msgid "This commit was signed with a different user's verified signature."
msgstr ""
@@ -40268,20 +40975,23 @@ msgid "This commit was signed with a verified signature, but the committer email
msgstr ""
msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
-msgstr ""
+msgstr "Ce commit a été signé avec une signature %{strong_open}non vérifiée%{strong_close}."
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "Ce contenu n'a pas pu être affiché car %{reason}. Vous pouvez %{options} à la place."
msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
-msgstr ""
+msgstr "Ce contenu n'a pas pu être affiché car il est stocké dans LFS. Vous pouvez %{linkStart}le télécharger%{linkEnd} à la place."
msgid "This credential has expired"
-msgstr ""
+msgstr "Ces identifiants ont expiré"
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "Cette tâche de déploiement ne s'exécute pas automatiquement et doit être démarrée manuellement, mais elle est antérieure au déploiement le plus récent et ne peut donc pas s'exécuter."
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40301,33 +41011,54 @@ msgid "This domain is not verified. You will need to verify ownership before acc
msgstr ""
msgid "This email address does not look right, are you sure you typed it correctly?"
-msgstr ""
+msgstr "Cette adresse de courriel semble incorrecte, êtes-vous sûr de l'avoir saisie correctement ?"
msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_link}."
-msgstr ""
+msgstr "Ce courriel remplace tous les précédents que vous auriez pu recevoir à propos de la suppression planifiée de %{project_link}."
msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_name}."
-msgstr ""
+msgstr "Ce courriel remplace tous les précédents que vous auriez pu recevoir à propos de la suppression planifiée de %{project_name}."
msgid "This endpoint has been requested too many times. Try again later."
-msgstr ""
+msgstr "Ce point de terminaison a été sollicité trop souvent. Réessayez plus tard."
msgid "This environment has no deployments yet."
msgstr ""
msgid "This environment is being deployed"
-msgstr ""
+msgstr "Cet environnement est en cours de déploiement"
msgid "This environment is being re-deployed"
-msgstr ""
+msgstr "Cet environnement est en cours de redéploiement"
msgid "This environment is not protected."
-msgstr ""
+msgstr "Cet environnement n'est pas protégé."
msgid "This environment's canary ingress has been updated recently. Please retry later."
-msgstr ""
+msgstr "Le Canari Ingress de l'environnement a été mis à jour récemment. Veuillez réessayer plus tard."
msgid "This epic already has the maximum number of child epics."
+msgstr "Cette épopée a déjà le nombre maximum d'épopées enfants."
+
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
@@ -40340,55 +41071,55 @@ msgid "This feature requires local storage to be enabled"
msgstr ""
msgid "This field is required"
-msgstr ""
+msgstr "Ce champ est requis"
msgid "This field is required."
msgstr ""
msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
-msgstr ""
+msgstr "Ce fichier a été modifié pour être plus lisible, et ne peut pas accepter de suggestions. Modifiez-le directement."
msgid "This form is disabled in preview"
-msgstr ""
+msgstr "Ce formulaire est désactivé dans l'aperçu"
msgid "This group"
msgstr "Ce groupe"
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 ""
+msgstr "Ce groupe et ses sous-groupes et projets seront placés dans un état de « suppression en attente » pendant %{deletion_adjourned_period} jours, puis définitivement supprimés le %{date}. Le groupe peut être entièrement restauré avant cette date."
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 ""
+msgstr "Ce groupe ne peut pas être supprimé car il est lié à un abonnement. Pour supprimer ce groupe, %{linkStart}associez l'abonnement%{linkEnd} à un groupe différent."
msgid "This group can't be transferred because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group."
-msgstr ""
+msgstr "Ce groupe ne peut pas être transféré car il est lié à un abonnement. Pour transférer ce groupe, %{linkStart}associez l'abonnement%{linkEnd} à un groupe différent."
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
msgid "This group does not have any group runners yet."
-msgstr ""
+msgstr "Il n'y a pas encore d'exécuteur de groupe pour ce groupe."
msgid "This group has been scheduled for permanent removal on %{date}"
-msgstr ""
+msgstr "La suppression de ce groupe a été programmée pour le %{date}"
msgid "This group has no active access tokens."
-msgstr ""
+msgstr "Ce groupe n'a aucun jeton d'accès actif."
msgid "This group is linked to a subscription"
-msgstr ""
+msgstr "Ce groupe est lié à un abonnement"
msgid "This group is not permitted to create compliance violations"
msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
-msgstr ""
+msgstr "Ce groupe, ses sous-groupes et ses projets ont été programmés pour être supprimés le %{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 "Ce groupe, ses sous-groupes et ses projets seront supprimés le %{date} car son groupe parent « %{parent_group_name} » a été programmé pour suppression."
msgid "This incident is already escalated with '%{escalation_policy_name}'."
-msgstr ""
+msgstr "Cet incident est déjà escaladé avec « %{escalation_policy_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 ""
@@ -40397,10 +41128,10 @@ msgid "This is a \"Ghost User\", created to hold all issues authored by users th
msgstr ""
msgid "This is a Jira user."
-msgstr ""
+msgstr "C'est un utilisateur de Jira."
msgid "This is a confidential %{noteableTypeText}."
-msgstr ""
+msgstr "C'est un(e) %{noteableTypeText} confidentiel(le)."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Il s’agit d’une tâche différée devant être exécutée dans %{remainingTime}"
@@ -40409,43 +41140,46 @@ msgid "This is a list of devices that have logged into your account. Revoke any
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 ""
+msgstr "Il s'agit d'une adresse de courriel privée %{helpIcon} générée uniquement pour vous. Quiconque la connait peut créer des tickets ou des demandes de fusion comme s'il s'agissait de vous. Si cela arrive, %{resetLinkStart}réinitialisez ce jeton%{resetLinkEnd}."
msgid "This is a security log of authentication events involving your account."
-msgstr ""
+msgstr "Ceci est un journal de sécurité des événements d'authentification impliquant votre compte."
msgid "This is a self-managed instance of GitLab."
-msgstr ""
+msgstr "Il s'agit d'une instance auto-gérée de GitLab."
msgid "This is an experimental feature developed by GitLab Incubation Engineering."
-msgstr ""
+msgstr "Il s'agit d'une fonctionnalité expérimentale développée par GitLab Incubation Engineering."
msgid "This is the highest peak of users on your installation since the license started."
-msgstr ""
+msgstr "Il s'agit du pic d'utilisateurs le plus élevé de votre installation depuis que la licence a démarré."
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
+msgstr "Il s'agit du nombre d'%{billable_users_link_start}utilisateurs facturables%{link_end} sur votre installation et cela correspond à la quantité minimale que vous devez acheter lors du renouvellement de votre licence."
+
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr "C'est la seule fois où le secret est accessible. Copiez-le et stockez-le en sécurité."
msgid "This is your current session"
msgstr ""
msgid "This issue cannot be assigned to a confidential epic because it is public."
-msgstr ""
+msgstr "Ce ticket ne peut pas être assigné à une épopée confidentielle car il est public."
msgid "This issue cannot be made public because it belongs to a confidential epic."
-msgstr ""
+msgstr "Ce ticket ne peut pas être rendu public car il appartient à une épopée confidentielle."
msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
msgstr "Ce ticket est confidentiel et ne devrait être visible que par les membres de l’équipe ayant au moins un accès à Rapporteur."
msgid "This issue is currently blocked by the following issues:"
-msgstr ""
+msgstr "Ce ticket est actuellement bloqué par les tickets suivants :"
msgid "This issue is hidden because its author has been banned"
-msgstr ""
+msgstr "Ce ticket est caché car son auteur a été banni"
msgid "This issue is in a child epic of the filtered epic"
-msgstr ""
+msgstr "Ce ticket est une épopée enfant de l'épopée filtrée"
msgid "This job could not start because it could not retrieve the needed artifacts%{punctuation}%{invalid_dependencies}"
msgstr ""
@@ -40475,10 +41209,10 @@ msgid "This job has not started yet"
msgstr "Cette tâche n’a pas encore commencé"
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "Cette tâche est un déploiement obsolète vers %{environmentLink} en utilisant la grappe de serveurs %{clusterNameOrLink} et l'espace de noms %{kubernetesNamespace}."
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
-msgstr ""
+msgstr "Cette tâche est un déploiement obsolète vers %{environmentLink} utilisant la grappe de serveurs %{clusterNameOrLink} et l'espace de noms %{kubernetesNamespace}. Voir le %{deploymentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
msgstr ""
@@ -40496,13 +41230,13 @@ msgid "This job is archived. Only the complete pipeline can be retried."
msgstr "Cette tâche est archivée. Seul le pipeline complet peut faire l’objet d’une nouvelle exécution."
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "Cette tâche est en train de créer un déploiement vers %{environmentLink} en utilisant la grappe de serveurs %{clusterNameOrLink} et l'espace de noms %{kubernetesNamespace}."
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "Cette tâche est en train de créer un déploiement vers %{environmentLink} en utilisant la grappe de serveurs %{clusterNameOrLink} et l'espace de noms %{kubernetesNamespace}. Cela écrasera le %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
-msgstr ""
+msgstr "Cette tâche est en train de créer un déploiement sur %{environmentLink} en utilisant la grappe de serveurs %{clusterNameOrLink}."
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
msgstr ""
@@ -40514,7 +41248,7 @@ msgid "This job is creating a deployment to %{environmentLink}. This will overwr
msgstr ""
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "Cette tâche est déployée sur %{environmentLink} en utilisant la grappe de serveurs %{clusterNameOrLink} et l'espace de noms %{kubernetesNamespace}."
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
msgstr ""
@@ -40532,7 +41266,7 @@ msgid "This job is preparing to start"
msgstr ""
msgid "This job is waiting for resource: "
-msgstr ""
+msgstr "Cette tâche est en attente de ressource : "
msgid "This job requires a manual action"
msgstr "Cette tâche nécessite une action manuelle"
@@ -40544,10 +41278,10 @@ msgid "This job will automatically run after its timer finishes. Often they are
msgstr ""
msgid "This license has already expired."
-msgstr ""
+msgstr "Cette licence a déjà expiré."
msgid "This link points to external content"
-msgstr ""
+msgstr "Ce lien pointe vers un contenu externe"
msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
msgstr ""
@@ -40559,87 +41293,90 @@ msgid "This merge request branch is protected from force push."
msgstr ""
msgid "This merge request cannot be rebased while there are conflicts."
-msgstr ""
+msgstr "Cette demande de fusion ne peut pas être rebasée tant qu'il existe des conflits."
msgid "This merge request does not have accessibility reports"
-msgstr ""
+msgstr "Cette demande de fusion ne dispose d'aucun rapport d'accessibilité"
msgid "This merge request does not have codequality reports"
msgstr ""
msgid "This merge request is closed. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "Cette demande de fusion est fermée. Pour appliquer cette suggestion, modifiez ce fichier directement."
msgid "This merge request is from a private project to a public project."
-msgstr ""
+msgstr "Cette demande de fusion est issue d'un projet privé pour un projet public."
msgid "This merge request is from a private project to an internal project."
-msgstr ""
+msgstr "Cette demande de fusion est issue d'un projet privé pour un projet interne."
msgid "This merge request is from an internal project to a public project."
-msgstr ""
+msgstr "Cette demande de fusion est issue d'un projet interne pour un projet public."
msgid "This merge request is locked."
msgstr "Cette demande de fusion est verrouillée."
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "Cette demande de fusion a été fusionnée. Pour appliquer cette suggestion, modifiez ce fichier directement."
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
msgid "This only applies to repository indexing operations."
-msgstr ""
+msgstr "Cela ne s'applique qu'aux opérations d'indexation des dépôts."
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
msgstr "Cette page n’est pas disponible car vous n’êtes pas autorisé à lire des informations à travers de multiples projets."
msgid "This page sends a payload. Go back to the events page to see a newly created event."
-msgstr ""
+msgstr "Cette page envoie une charge utile. Retournez à la page des événements pour voir un événement nouvellement créé."
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
-msgstr ""
+msgstr "Ce pipeline utilise une configuration CI/CD prédéfinie activée par %{b_open}Auto DevOps.%{b_close}"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
msgstr ""
msgid "This pipeline was triggered by a schedule."
-msgstr ""
+msgstr "Ce pipeline a été déclenché par une planification."
msgid "This process deletes the project repository and all related resources."
-msgstr ""
+msgstr "Ce processus supprime le dépôt du projet et toutes les ressources associées."
msgid "This project"
msgstr "Ce projet"
msgid "This project can be restored until %{date}."
-msgstr ""
+msgstr "Ce projet peut être restauré jusqu'au %{date}."
msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
-msgstr ""
+msgstr "Ce projet ne peut pas être %{visibilityLevel} car la visibilité de %{openShowLink}%{name}%{closeShowLink} est %{visibility}. Pour rendre ce projet %{visibilityLevel}, vous devez d'abord %{openEditLink}modifier la visibilité%{closeEditLink} du groupe parent."
msgid "This project does not belong to a group and cannot make use of group runners."
-msgstr ""
+msgstr "Ce projet ne fait pas partie d'un groupe et ne peut pas utiliser des exécuteurs de groupe."
msgid "This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity."
-msgstr ""
+msgstr "Le %{service_desk_link_start}Service d'Assistance%{service_desk_link_end} n'est pas activé pour ce projet, l'utilisateur qui a créé le ticket ne recevra plus de notifications par courriel à propos des nouvelles activités."
msgid "This project does not have a wiki homepage yet"
msgstr "Ce projet n’a pas encore de page d’accueil de wiki"
msgid "This project has no active access tokens."
-msgstr ""
+msgstr "Ce projet n'a pas de jeton d'accès actif."
msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
msgstr ""
msgid "This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources."
-msgstr ""
+msgstr "Ce projet %{strongStart}N'EST PAS%{strongEnd} une divergence. Ce processus supprime le dépôt du projet et toutes ses ressources associées."
msgid "This project is archived and cannot be commented on."
msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
+msgstr "Ce projet est sous licence %{strong_start}%{license_name}%{strong_end}."
+
+msgid "This project is mirrored from %{link}."
msgstr ""
msgid "This project is not subscribed to any project pipelines."
@@ -40649,37 +41386,43 @@ msgid "This project is public. Non-members can guess the Service Desk email addr
msgstr ""
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
-msgstr ""
+msgstr "Les dépendances de ce projet sont gérées grâce à %{strong_start}%{manager_name}%{strong_end}"
msgid "This project path either does not exist or you do not have access."
-msgstr ""
+msgstr "Soit ce chemin d'accès au projet n'existe pas, soit vous n'en avez pas l'accès."
+
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr "Ce projet a atteint la limite des domaines personnalisés. (Max %d)"
msgid "This project will be deleted on %{date}"
-msgstr ""
+msgstr "Ce projet sera supprimé le %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
+msgstr "Ce projet sera supprimé le %{date} car la suppression de son groupe parent « %{parent_group_name} » a été programmée."
+
+msgid "This project's pipeline configuration is located outside this repository"
msgstr ""
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
-msgstr ""
+msgstr "Cette version a été créée avec une date dans le passé. La collecte de preuves au moment de la publication n'est pas disponible."
msgid "This report uses a supported MAJOR.MINOR schema version but the PATCH version doesn't match any vendored schema version. Validation will be attempted against version %{find_latest_patch_version}"
-msgstr ""
+msgstr "Ce rapport utilise une version de schéma MAJEURE.MINEURE prise en charge mais la version PATCH ne correspond à aucune version de schéma vendue. La validation sera tentée en se basant sur la version %{find_latest_patch_version}"
msgid "This repository"
msgstr "Ce dépôt"
msgid "This repository has never been checked."
-msgstr ""
+msgstr "Ce dépôt n'a jamais été vérifié."
msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
msgstr ""
msgid "This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages."
-msgstr ""
+msgstr "Ce dépôt a été vérifié pour la dernière fois %{last_check_timestamp}. La vérification %{strong_start}a échoué.%{strong_end} Voir le fichier « repocheck.log » pour les messages d'erreur."
msgid "This repository was last checked %{last_check_timestamp}. The check passed."
-msgstr ""
+msgstr "Ce dépôt a été vérifié pour la dernière fois %{last_check_timestamp}. La vérification est passée."
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Cet exécuteur ne fonctionnera que sur les pipelines déclenchés sur des branches protégées"
@@ -40691,46 +41434,46 @@ msgid "This setting has been configured at the instance level and cannot be over
msgstr ""
msgid "This setting is allowed for forked projects only"
-msgstr ""
+msgstr "Ce paramètre n'est autorisé que pour les projets divergents"
msgid "This subscription is for"
msgstr ""
msgid "This suggestion already matches its content."
-msgstr ""
+msgstr "Cette suggestion correspond déjà à son contenu."
msgid "This title already exists."
-msgstr ""
+msgstr "Ce titre existe déjà."
msgid "This user cannot be unlocked manually from GitLab"
msgstr ""
msgid "This user has an unconfirmed email address (%{email}). You may force a confirmation."
-msgstr ""
+msgstr "Cet utilisateur possède une adresse de courriel (%{email}) non confirmée. Vous pouvez forcer une confirmation."
msgid "This user has an unconfirmed email address. You may force a confirmation."
-msgstr ""
+msgstr "L'adresse de messagerie de cet utilisateur n'est pas confirmée. Vous pouvez forcer une confirmation."
msgid "This user has no active %{accessTokenTypePlural}."
-msgstr ""
+msgstr "Cet utilisateur n'a pas de %{accessTokenTypePlural} actifs."
msgid "This user has no active %{type}."
-msgstr ""
+msgstr "Cet utilisateur n'a aucun(e) %{type} actif(ve)."
msgid "This user has no identities"
msgstr "Cet utilisateur ou cette utilisatrice n’a aucune identité"
msgid "This user has no personal projects."
-msgstr ""
+msgstr "Cet utilisateur n'a pas de projets personnels."
msgid "This user has previously committed to the %{name} project."
-msgstr ""
+msgstr "Cet utilisateur a précédemment fait des commits vers le projet %{name}."
msgid "This user has the %{access} role in the %{name} project."
-msgstr ""
+msgstr "Cet utilisateur possède le rôle %{access} dans le projet %{name}."
msgid "This user is the author of this %{noteable}."
-msgstr ""
+msgstr "Cet utilisateur est l'auteur de ce(tte) %{noteable}."
msgid "This variable can not be masked."
msgstr ""
@@ -40742,19 +41485,22 @@ msgid "This will invalidate your registered applications and U2F devices."
msgstr ""
msgid "This will remove the fork relationship between this project and %{fork_source}."
-msgstr ""
+msgstr "Cela supprimera la relation de fork entre ce projet et %{fork_source}."
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
msgid "Threshold in bytes at which to compress Sidekiq job arguments."
-msgstr ""
+msgstr "Seuil en octets à partir duquel compresser les arguments des tâches Sidekiq."
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
-msgstr ""
+msgstr "Seuil en octets à partir duquel rejeter les tâches Sidekiq. Définissez-le sur 0 si vous ne souhaitez pas de limite sur les tâches Sidekiq."
msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
msgstr ""
@@ -40763,7 +41509,7 @@ msgid "Throughput"
msgstr ""
msgid "Thu"
-msgstr ""
+msgstr "Jeu"
msgid "Thursday"
msgstr ""
@@ -40772,7 +41518,7 @@ msgid "Time"
msgstr ""
msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
-msgstr ""
+msgstr "Durée (en heures) pendant laquelle les utilisateurs sont autorisés à ignorer la configuration obligatoire de l’authentification à deux facteurs."
msgid "Time based: Yes"
msgstr ""
@@ -40814,7 +41560,7 @@ msgid "Time to merge"
msgstr ""
msgid "Time to subtract exceeds the total time spent"
-msgstr ""
+msgstr "La durée à soustraire excède le temps passé total"
msgid "Time tracking"
msgstr "Suivi du temps"
@@ -40826,19 +41572,19 @@ msgid "Time until first merge request"
msgstr "Temps jusqu’à la première demande de fusion"
msgid "Time zone"
-msgstr ""
+msgstr "Fuseau horaire"
msgid "TimeTrackingEstimated|Est"
msgstr "Est"
msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
-msgstr ""
+msgstr "%{spentStart}Temps passé : %{spentEnd}"
msgid "TimeTracking|An error occurred while removing the timelog."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la suppression de l'entrée de temps passé."
msgid "TimeTracking|Delete time spent"
-msgstr ""
+msgstr "Supprimer le temps passé"
msgid "TimeTracking|Estimated:"
msgstr "Estimé :"
@@ -40976,7 +41722,7 @@ msgid "Timeago|right now"
msgstr "immédiatement"
msgid "Timeline event added successfully."
-msgstr ""
+msgstr "Événement de chronologie ajouté avec succès."
msgid "Timeline|Turn recent updates view off"
msgstr ""
@@ -40985,43 +41731,43 @@ msgid "Timeline|Turn recent updates view on"
msgstr ""
msgid "Timelog doesn't exist or you don't have permission to delete it"
-msgstr ""
+msgstr "L'entrée de temps passé n'existe pas ou vous n'avez pas la permission de la supprimer"
msgid "Timeout"
msgstr "Délai d’attente"
msgid "Timeout connecting to the Google API. Please try again."
-msgstr ""
+msgstr "Expiration du délai pour se connecter à l'API Google. Veuillez réessayer."
msgid "Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout."
-msgstr ""
+msgstr "Délai d'expiration pour les opérations Gitaly modérément rapides (en secondes). Fournir une valeur entre le délai par Défaut et le délai Rapide."
msgid "Timeout for most Gitaly operations (in seconds)."
-msgstr ""
+msgstr "Délai d'expiration pour la plupart des opérations Gitaly (en secondes)."
msgid "Timeout for the fastest Gitaly operations (in seconds)."
-msgstr ""
+msgstr "Délai d'expiration pour les opérations Gitaly les plus rapides (en secondes)."
msgid "Timezone"
-msgstr ""
+msgstr "Fuseau horaire"
msgid "Time|A"
-msgstr ""
+msgstr "A"
msgid "Time|AM"
-msgstr ""
+msgstr "AM"
msgid "Time|P"
-msgstr ""
+msgstr "P"
msgid "Time|PM"
-msgstr ""
+msgstr "PM"
msgid "Time|a"
-msgstr ""
+msgstr "a"
msgid "Time|am"
-msgstr ""
+msgstr "am"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -41034,19 +41780,19 @@ msgstr[0] "min"
msgstr[1] "mins"
msgid "Time|p"
-msgstr ""
+msgstr "p"
msgid "Time|pm"
-msgstr ""
+msgstr "pm"
msgid "Time|s"
msgstr "s"
msgid "Tip: Hover over a job to see the jobs it depends on to run."
-msgstr ""
+msgstr "Astuce : Survolez une tâche pour voir celles dont elle dépend pour pouvoir s'exécuter."
msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
-msgstr ""
+msgstr "Conseil: ajoutez un %{linkStart}CODEOWNERS%{linkEnd} pour ajouter automatiquement des approbateurs en fonction des chemins d'accès et des types de fichiers."
msgid "Title"
msgstr "Titre"
@@ -41064,7 +41810,7 @@ msgid "To"
msgstr ""
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
-msgstr ""
+msgstr "Pour %{link_to_help} de votre domaine, ajoutez la clé ci-dessus à un enregistrement TXT dans votre configuration DNS."
msgid "To Do"
msgstr ""
@@ -41073,13 +41819,13 @@ msgid "To GitLab"
msgstr "Vers GitLab"
msgid "To accept this invitation, create an account or sign in."
-msgstr ""
+msgstr "Pour accepter cette invitation, créez un compte ou connectez-vous."
msgid "To accept this invitation, sign in or create an account."
-msgstr ""
+msgstr "Pour accepter cette invitation, connectez-vous ou créez un compte."
msgid "To accept this invitation, sign in."
-msgstr ""
+msgstr "Pour accepter cette invitation, connectez-vous."
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -41088,22 +41834,25 @@ msgid "To activate your trial, we need additional details from you."
msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Pour ajouter un suffixe personnalisé, configurez une adresse électronique pour le Service d'Assistance. %{linkStart}En savoir plus.%{linkEnd}"
+
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
msgid "To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
-msgstr ""
+msgstr "Pour approuver cette demande de fusion, veuillez saisir votre mot de passe. Ce projet nécessite que toutes les approbations soient authentifiées."
msgid "To complete registration, we need additional details from you."
msgstr ""
msgid "To confirm, type %{phrase_code}"
-msgstr ""
+msgstr "Pour confirmer, tapez %{phrase_code}"
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Pour connecter des dépôts GitHub, vous pouvez utiliser un %{personal_access_token_link}. Lorsque vous créez votre Jeton d'Accès Personnel, vous devez sélectionner la portée %{code_open}repo%{code_close} pour que nous puissions afficher une liste de vos dépôts publics et privés qui sont disponibles pour connexion."
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
msgstr ""
@@ -41115,17 +41864,20 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "Pour connecter un dépôt SVN, veuillez consulter %{svn_link}."
msgid "To continue using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
-msgstr ""
+msgstr "Pour continuer à utiliser GitLab Édition Entreprise, téléversez le fichier %{codeOpen}.gitlab-license%{codeClose} ou entrez la clé de licence que vous avez reçue de GitLab Inc."
msgid "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}"
-msgstr ""
+msgstr "Pour continuer, afin de vérifier vous adresse de courriel, vous devez cliquer sur le lien présent dans le courriel de confirmation que nous vous avons envoyé. Si vous ne l'avez pas reçu, sélectionnez %{strongStart}Renvoyer un courriel de confirmation%{strongEnd}"
msgid "To define internal users, first enable new users set to external"
msgstr "Afin de définir les utilisateurs internes, veuillez d’abord activer les nouveaux utilisateurs définis comme externes"
-msgid "To enable Registration Features, first enable Service Ping."
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
msgstr ""
+msgid "To enable Registration Features, first enable Service Ping."
+msgstr "Pour activer les Fonctionnalités d'Inscription, activez d'abord le Ping de Service."
+
msgid "To ensure %{project_link} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
msgstr ""
@@ -41133,28 +41885,28 @@ msgid "To ensure %{project_name} is unscheduled for deletion, check that activit
msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
-msgstr ""
+msgstr "Pour éviter toute perte de contenu personnel, ce compte ne doit être utilisé qu'en rapport avec %{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 ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
-msgstr ""
+msgstr "Pour protéger davantage votre compte, envisagez de configurer une méthode d'%{mfa_link_start}authentification à deux facteurs%{mfa_link_end}."
msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
-msgstr ""
+msgstr "Pour protéger davantage votre compte, envisagez de configurer une méthode d'authentification à deux facteurs : %{mfa_link}."
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr "Pour commencer, entrez votre URL FogBugz et vos informations de connexion ciâ€dessous. Dans les étapes suivantes, vous pourrez mettre en correspondance les comptes des utilisateurs et sélectionner les projets à importer."
msgid "To get started, click the link below to confirm your account."
-msgstr ""
+msgstr "Pour commencer, cliquez sur le lien ci-dessous pour confirmer votre compte."
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Pour commencer, entrez l’URL de votre hôte Gitea et un %{link_to_personal_token}."
msgid "To get started, use the link below to confirm your account."
-msgstr ""
+msgstr "Pour commencer, utilisez le lien ci-dessous pour confirmer votre compte."
msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
@@ -41169,46 +41921,46 @@ 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 "Pour en savoir plus sur ce projet, lisez %{link_to_wiki}"
msgid "To manage seats for all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
-msgstr ""
+msgstr "Pour gérer les sièges de tous les membres associés à ce groupe et ses sous-groupes et projets, visitez la page %{link_start}quotas d'utilisation%{link_end}."
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 "Pour déplacer ou copier un projet GitLab entier depuis une autre installation de GitLab vers celleâ€ci, accédez à la page des paramètres du projet d’origine, générez un fichier d’exportation et téléversezâ€le ici."
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
-msgstr ""
+msgstr "Pour utiliser les fonctionnalités CI/CD pour un dépôt externe uniquement, choisissez %{strong_open}Intégration et livraisons continues pour dépôt externe%{strong_close}."
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
-msgstr ""
+msgstr "Pour transmettre des variables au pipeline déclenché, ajoutez %{code_start}variables[VARIABLE]=VALEUR%{code_end} à la requête API."
msgid "To personalize your GitLab experience, we'd like to know a bit more about you"
-msgstr ""
+msgstr "Pour personnaliser votre expérience avec GitLab, nous souhaiterions en savoir un peu plus sur vous"
msgid "To preserve performance only %{strongStart}%{visible} of %{total}%{strongEnd} files are displayed."
-msgstr ""
+msgstr "Pour ne pas réduire les performances, seuls %{strongStart}%{visible} des %{total}%{strongEnd} fichiers sont affichés."
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
-msgstr ""
+msgstr "Pour préserver les performances, seuls %{strong_open}%{display_size} fichiers sur %{real_size}%{strong_close} sont affichés."
msgid "To protect this issue's confidentiality, %{linkStart}fork this project%{linkEnd} and set the fork's visibility to private."
-msgstr ""
+msgstr "Pour protéger la confidentialité de ce ticket, %{linkStart}créez un projet divergent%{linkEnd} et définissez sa visibilité sur privée."
msgid "To protect this issue's confidentiality, a private fork of this project was selected."
msgstr ""
msgid "To reactivate your account, %{gitlab_link_start}sign in to GitLab.%{link_end}"
-msgstr ""
+msgstr "Pour réactiver votre compte, %{gitlab_link_start}connectez-vous à GitLab.%{link_end}"
msgid "To reactivate your account, sign in to GitLab at %{gitlab_url}."
-msgstr ""
+msgstr "Pour réactiver votre compte, connectez-vous à GitLab sur %{gitlab_url}."
msgid "To resolve this, try to:"
-msgstr ""
+msgstr "Pour résoudre cela, essayez de :"
msgid "To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings."
-msgstr ""
+msgstr "Pour exécuter des pipelines CI/CD avec JetBrains TeamCity, entrez les détails du projet GitLab dans les Paramètres de Contrôle de Version du projet TeamCity."
msgid "To see all the user's personal access tokens you must impersonate them first."
msgstr ""
@@ -41220,34 +41972,34 @@ msgid "To see this project's operational details, contact an owner of group %{gr
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 ""
+msgstr "Pour voir ce qui a été modifié ou pour créer une demande de fusion, choisissez une branche ou une étiquette (comme %{branch}) ou entrez un commit ( comme %{sha})."
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é :"
msgid "To set up this integration:"
-msgstr ""
+msgstr "Pour configurer cette intégration :"
msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
msgstr ""
msgid "To start using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
-msgstr ""
+msgstr "Pour commencer à utiliser GitLab Édition Entreprise, téléversez le fichier %{codeOpen}.gitlab-license%{codeClose} ou entrez la clé de licence que vous avez reçue de GitLab Inc."
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
-msgstr ""
+msgstr "Pour vous désabonner de ce ticket, veuillez coller le lien suivant dans votre navigateur :"
msgid "To update Snippets with multiple files, you must use the `files` parameter"
-msgstr ""
+msgstr "Pour mettre à jour les Extraits de code avec plusieurs fichiers, vous devez utiliser le paramètre « files »"
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
-msgstr ""
+msgstr "Pour utiliser des formats supplémentaires, vous devez démarrer les %{container_link_start}conteneurs complémentaires%{container_link_end} requis."
msgid "To use the system's default, set this value to 0."
-msgstr ""
+msgstr "Pour utiliser la valeur par défaut du système, définissez cette valeur à 0."
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
-msgstr ""
+msgstr "Pour voir toutes les %{scannedResourcesCount} URLs analysées, %{linkStart}veuillez télécharger le fichier CSV%{linkEnd}"
msgid "To view usage, refresh this page in a few minutes."
msgstr ""
@@ -41271,31 +42023,31 @@ msgid "Todos count"
msgstr ""
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
-msgstr ""
+msgstr "Cherchez-vous des choses à faire ? Jetez un coup d'œil aux %{strongStart}%{openIssuesLinkStart}tickets ouverts%{openIssuesLinkEnd}%{strongEnd}, contribuez à %{strongStart}%{mergeRequestLinkStart}une demande de fusion%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd} ou mentionnez quelqu'un dans un commentaire pour lui assigner automatiquement une nouvelle tâche."
msgid "Todos|Filter by author"
-msgstr ""
+msgstr "Filtrer par auteur"
msgid "Todos|Filter by group"
-msgstr ""
+msgstr "Filtrer par groupe"
msgid "Todos|Filter by project"
-msgstr ""
+msgstr "Filtrer par projet"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "Vous pouvez vous féliciter !"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "Bon travail ! Il semblerait qu'il ne reste plus rien sur votre Liste de Tâches"
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
msgstr ""
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "Une Liste de Tâches vide, n'est-ce-pas magnifique ?"
msgid "Todos|It's how you always know what to work on next."
-msgstr ""
+msgstr "C'est ainsi que vous savez toujours sur quoi travailler ensuite."
msgid "Todos|Mark all as done"
msgstr "Tout marquer comme terminé"
@@ -41304,22 +42056,22 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr "Il n'y a rien sur votre liste de tâches. Beau travail !"
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "Plus rien à faire. Tope là !"
msgid "Todos|Undo mark all as done"
-msgstr "Annuler tout marquer comme fait"
+msgstr "Annuler Tout marquer comme terminé"
msgid "Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List."
-msgstr ""
+msgstr "Quand un ticket ou une demande de fusion vous est assigné, ou quand vous recevez une %{strongStart}@mention%{strongEnd} dans un commentaire, cela génère automatiquement un nouvel élément sur votre Liste de Tâches."
msgid "Todos|You're all done!"
msgstr "Vous avez terminé !"
msgid "Todos|Your To-Do List shows what to work on next"
-msgstr ""
+msgstr "Votre Liste de Tâches montre sur quoi travailler ensuite"
msgid "Toggle GitLab Next"
-msgstr ""
+msgstr "Activer/désactiver GitLab Next"
msgid "Toggle Markdown preview"
msgstr ""
@@ -41342,17 +42094,14 @@ msgstr "Afficher ou masquer la description du commit"
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
msgid "Toggle focus mode"
-msgstr ""
+msgstr "Activer/désactiver le mode focus"
msgid "Toggle keyboard shortcuts help dialog"
-msgstr ""
+msgstr "Afficher/masquer la boîte de dialogue d'aide des raccourcis clavier"
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Afficher/masquer la barre latérale"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41379,22 +42125,22 @@ msgid "Toggles :%{name}: emoji award."
msgstr ""
msgid "Token"
-msgstr ""
+msgstr "Jeton"
msgid "Token Access"
-msgstr ""
+msgstr "Accès au Jeton"
msgid "Token name"
msgstr ""
msgid "Token valid until revoked"
-msgstr ""
+msgstr "Jeton valide jusqu'à sa révocation"
msgid "Tokens|Scopes set the permission levels granted to the token."
-msgstr ""
+msgstr "Les portées définissent les niveaux de permissions accordés au jeton."
msgid "Tokens|Select scopes"
-msgstr ""
+msgstr "Sélectionnez les portées"
msgid "Tomorrow"
msgstr "Demain"
@@ -41403,40 +42149,40 @@ msgid "Too many changes to show."
msgstr "Trop de changements à afficher."
msgid "Too many namespaces enabled. Manage them through the console or the API."
-msgstr ""
+msgstr "Trop d'espaces de noms activés. Gérez-les à travers la console ou l'API."
msgid "Too many projects enabled. Manage them through the console or the API."
-msgstr ""
+msgstr "Trop de projets activés. Gérez-les à travers la console ou l'API."
msgid "Too many references. Quick actions are limited to at most %{max_count} user references"
-msgstr ""
+msgstr "Trop de références. Les actions rapides sont limitées à %{max_count} références d'utilisateurs au maximum"
msgid "Too many users found. Quick actions are limited to at most %{max_count} users"
-msgstr ""
+msgstr "Trop d'utilisateurs trouvés. Les actions rapides sont limitées à %{max_count} utilisateurs maximum"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "Explorer"
msgid "TopNav|Go back"
msgstr ""
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "Basculer vers"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "Vos tableaux de bord"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr ""
msgid "Topic %{topic_name} was successfully created."
-msgstr ""
+msgstr "Le sujet %{topic_name} a été créé avec succès."
msgid "Topic %{topic_name} was successfully removed."
-msgstr ""
+msgstr "Le sujet %{topic_name} a été supprimé avec succès."
msgid "Topic avatar"
-msgstr ""
+msgstr "Avatar du sujet"
msgid "Topic avatar for %{name} will be removed. This cannot be undone."
msgstr ""
@@ -41445,25 +42191,25 @@ msgid "Topic slug (name)"
msgstr ""
msgid "Topic title"
-msgstr ""
+msgstr "Titre du sujet"
msgid "Topic was successfully updated."
-msgstr ""
+msgstr "Le sujet a été mis à jour avec succès."
msgid "TopicSelect|No matching results"
-msgstr ""
+msgstr "Aucun résultat correspondant"
msgid "TopicSelect|Search topics"
-msgstr ""
+msgstr "Rechercher des sujets"
msgid "TopicSelect|Select a topic"
-msgstr ""
+msgstr "Sélectionner un sujet"
msgid "Topics"
-msgstr ""
+msgstr "Sujets"
msgid "Topics could not be merged!"
-msgstr ""
+msgstr "Les sujets n'ont pas pu être fusionnés !"
msgid "Total"
msgstr ""
@@ -41478,16 +42224,19 @@ msgid "Total artifacts size: %{total_size}"
msgstr ""
msgid "Total cores (CPUs)"
+msgstr "Nombre de cœurs (CPUs)"
+
+msgid "Total issue weight"
msgstr ""
msgid "Total memory (GB)"
-msgstr ""
+msgstr "Mémoire totale (Go)"
msgid "Total test time for all commits/merges"
msgstr "Temps total de test pour tous les commits/fusions"
msgid "Total users"
-msgstr ""
+msgstr "Nombre total d'utilisateurs"
msgid "Total weight"
msgstr ""
@@ -41496,46 +42245,46 @@ msgid "Total: %{total}"
msgstr "Total : %{total}"
msgid "TotalMilestonesIndicator|1000+"
-msgstr ""
+msgstr "1000+"
msgid "TotalRefCountIndicator|1000+"
-msgstr ""
+msgstr "1000+"
msgid "Track groups of issues that share a theme, across projects and milestones"
msgstr "Suivre les groupes de tickets qui partagent un thème, entre différents projets et jalons"
msgid "Track important events in your GitLab instance."
-msgstr ""
+msgstr "Suivre les événements importants de votre instance GitLab."
msgid "Track important events in your group."
-msgstr ""
+msgstr "Suivre les événements importants de votre groupe."
msgid "Track important events in your project."
-msgstr ""
+msgstr "Suivre les événements importants de votre projet."
msgid "Track time with quick actions"
msgstr "Suivre le temps estimé/passé avec les actions rapides"
msgid "Training mode"
-msgstr ""
+msgstr "Mode formation"
msgid "Transfer"
msgstr ""
msgid "Transfer group to another parent group."
-msgstr ""
+msgstr "Transférer le groupe à un autre groupe parent."
msgid "Transfer ownership"
-msgstr ""
+msgstr "Transfert de propriété"
msgid "Transfer project"
msgstr ""
msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Transférer votre projet dans un autre espace de noms. %{link_start}En savoir plus.%{link_end}"
msgid "TransferGroup|Cannot transfer group to one of its subgroup."
-msgstr ""
+msgstr "Impossible de transférer le groupe vers un de ses sous-groupes."
msgid "TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
msgstr ""
@@ -41544,7 +42293,7 @@ msgid "TransferGroup|Database is not supported."
msgstr ""
msgid "TransferGroup|Group contains contacts/organizations and you don't have enough permissions to move them to the new root group."
-msgstr ""
+msgstr "Le groupe contient des contacts/organisations et vous n'avez pas les permissions suffisantes pour les déplacer vers le nouveau groupe racine."
msgid "TransferGroup|Group contains projects with NPM packages."
msgstr ""
@@ -41556,7 +42305,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 "Le groupe parent possède déjà un sous-groupe ou un projet avec le même chemin."
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr ""
@@ -41574,7 +42323,7 @@ msgid "TransferProject|Project cannot be transferred, because tags are present i
msgstr ""
msgid "TransferProject|Project is already in this namespace."
-msgstr ""
+msgstr "Le projet est déjà dans cet espace de noms."
msgid "TransferProject|Project with same name or path in target namespace already exists"
msgstr ""
@@ -41583,10 +42332,10 @@ msgid "TransferProject|Root namespace can't be updated if project has NPM packag
msgstr ""
msgid "TransferProject|You don't have permission to transfer projects into that namespace."
-msgstr ""
+msgstr "Vous n'avez pas la permission de transférer des projets dans cet espace de noms."
msgid "TransferProject|You don't have permission to transfer this project."
-msgstr ""
+msgstr "Vous n'avez pas la permission de transférer ce projet."
msgid "Tree view"
msgstr "Vue arborescente"
@@ -41595,43 +42344,45 @@ msgid "Trending"
msgstr "Tendance"
msgid "Trials|%{planName} Trial"
-msgstr ""
+msgstr "Essai %{planName}"
msgid "Trials|Compare all plans"
-msgstr ""
+msgstr "Comparer tous les forfaits"
msgid "Trials|Create a new group to start your GitLab Ultimate trial."
-msgstr ""
+msgstr "Créez un nouveau groupe pour commencer votre essai GitLab Ultimate."
msgid "Trials|Day %{daysUsed}/%{duration}"
-msgstr ""
+msgstr "Jour %{daysUsed}/%{duration}"
msgid "Trials|Go back to GitLab"
-msgstr ""
-
-msgid "Trials|Hey there"
-msgstr ""
+msgstr "Retour à GitLab"
msgid "Trials|Skip Trial"
-msgstr ""
+msgstr "Ignorer l'Essai"
msgid "Trials|Upgrade %{groupName} to %{planName}"
-msgstr ""
+msgstr "Mettre à niveau %{groupName} vers %{planName}"
msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
-msgstr ""
+msgstr "Vous pouvez toujours reprendre ce processus en sélectionnant votre avatar et en choisissant « Démarrer un essai Ultimate »"
msgid "Trials|You can apply your trial to a new group or an existing group."
-msgstr ""
+msgstr "Vous pouvez appliquer votre essai à un nouveau groupe ou à un groupe existant."
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
-msgstr ""
+msgstr "Vous n'obtiendrez pas d'essai gratuit maintenant mais vous pourrez toujours reprendre ce processus en sélectionnant votre avatar et en choisissant « Démarrer un essai Ultimate »"
+
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] "Il vous reste %{daysRemaining} jour sur GitLab %{planName} !"
+msgstr[1] "Il vous reste %{daysRemaining} jours sur GitLab %{planName} !"
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 "Votre essai se termine le %{boldStart}%{trialEndDate}%{boldEnd}. Nous espérons qui vous appréciez les fonctionnalités de GitLab %{planName}. Pour conserver celles-ci après la fin de votre période d'essai, vous devez souscrire à un abonnement. (Vous pouvez également choisir GitLab Premium si cela répond à vos besoins.)"
msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "Caractères autorisés : +, 0-9, - et espaces."
msgid "Trial|Continue"
msgstr ""
@@ -41640,37 +42391,37 @@ msgid "Trial|Dismiss"
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 "Votre essai de Gitlab Ultimate a une durée de 30 jours mais vous pouvez conserver votre compte gratuit Gitlab sans limite de temps. Nous avons seulement besoin de quelques informations supplémentaires pour activer votre période d'essai."
msgid "Trigger"
msgstr ""
msgid "Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions."
-msgstr ""
+msgstr "Déclencher un pipeline pour une branche ou une étiquette en générant un jeton de déclenchement et en l'utilisant avec un appel d'API. Un emprunt d'identité donnera au jeton les permissions et l'accès au projet de l'utilisateur."
msgid "Trigger cluster reindexing"
-msgstr ""
+msgstr "Déclencher la réindexation de la grappe de serveurs"
msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
-msgstr ""
+msgstr "Déclencher une réindexation de la grappe de serveurs. N'utilisez cela qu'avec un index créé avec GitLab 13.0 ou supérieur."
msgid "Trigger job"
msgstr ""
msgid "Trigger manual job"
-msgstr ""
+msgstr "Déclencher une tâche manuelle"
msgid "Trigger pipelines for mirror updates"
msgstr "Déclencher des pipelines pour les mises à jour de miroirs"
msgid "Trigger pipelines when branches or tags are updated in the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load. %{strong_start}CI will run using the credentials assigned above.%{strong_end} %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Déclencher les pipelines lorsque les branches ou les étiquettes sont mises à jour sur le dépôt amont. Selon l’activité qu'il y a sur ce dernier, cela peut considérablement augmenter la charge de vos exécuteurs CI. N’activez cette option que si vous savez qu’ils peuvent la supporter. %{strong_start}La CI sera lancée avec les identifiants ci-dessus.%{strong_end} %{link_start}En savoir plus.%{link_end}"
msgid "Trigger removed."
msgstr ""
msgid "Trigger repository check"
-msgstr ""
+msgstr "Déclencher la vérification du dépôt"
msgid "Trigger this manual action"
msgstr "Déclencher cette action manuelle"
@@ -41691,10 +42442,10 @@ msgid "Triggerer"
msgstr ""
msgid "Trigger|Trigger user has insufficient permissions to project"
-msgstr ""
+msgstr "L’utilisateur du déclencheur n’a pas les autorisations suffisantes sur ce projet"
msgid "Trigger|invalid"
-msgstr ""
+msgstr "invalide"
msgid "Trusted"
msgstr ""
@@ -41709,64 +42460,64 @@ msgid "Try again?"
msgstr ""
msgid "Try all GitLab features for free for 30 days. No credit card required."
-msgstr ""
+msgstr "Essayez toutes les fonctionnalités de GitLab gratuitement pendant 30 jours. Aucune carte de crédit n'est requise."
msgid "Try all GitLab has to offer for 30 days."
msgstr "Essayez tout ce que GitLab peut vous offrir pendant 30 jours."
msgid "Try changing or removing filters."
-msgstr ""
+msgstr "Essayez de modifier ou de supprimer des filtres."
msgid "Try grouping with different labels"
msgstr ""
msgid "Try logging in using your username or email. If you have forgotten your password, try recovering it"
-msgstr ""
+msgstr "Essayez de vous connecter en utilisant votre nom d'utilisateur ou votre adresse de messagerie. Si vous avez oublié votre mot de passe, tentez de le récupérer"
msgid "Try out GitLab Pipelines"
-msgstr ""
+msgstr "Essayez les Pipelines GitLab"
msgid "Try the troubleshooting steps here."
-msgstr ""
+msgstr "Essayez les étapes de dépannage ici."
msgid "Try to fork again"
msgstr ""
msgid "Try to keep the first line under 52 characters and the others under 72."
-msgstr ""
+msgstr "Essayez de garder la première ligne en dessous de 52 caractères et les autres en dessous de 72."
msgid "Try using a different search term to find the file you are looking for."
msgstr ""
msgid "Trying to communicate with your device. Plug it in (if needed) and press the button on the device now."
-msgstr ""
+msgstr "Tentative de communication avec votre appareil. Branchez-le (si nécessaire) et appuyez sur le bouton de l'appareil maintenant."
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
msgid "Tue"
-msgstr ""
+msgstr "Mar"
msgid "Tuesday"
msgstr ""
msgid "Turn off"
-msgstr ""
+msgstr "Désactiver"
msgid "Turn on"
-msgstr ""
+msgstr "Activer"
msgid "Twitter"
msgstr "Twitter"
msgid "Twitter:"
-msgstr ""
+msgstr "Twitter :"
msgid "Two-Factor Authentication"
msgstr ""
msgid "Two-Factor Authentication code"
-msgstr ""
+msgstr "Code d'authentification à deux facteurs"
msgid "Two-factor Authentication"
msgstr ""
@@ -41775,31 +42526,31 @@ msgid "Two-factor Authentication Recovery codes"
msgstr ""
msgid "Two-factor Authentication:"
-msgstr ""
+msgstr "Authentification à deux facteurs :"
msgid "Two-factor authentication"
msgstr "Authentification à double facteur"
msgid "Two-factor authentication disabled"
-msgstr ""
+msgstr "Authentification à deux facteurs désactivée"
msgid "Two-factor authentication grace period"
msgstr ""
msgid "Two-factor authentication has been disabled for this user"
-msgstr ""
+msgstr "L'authentification à deux facteurs a été désactivée pour cet utilisateur"
msgid "Two-factor authentication has been disabled for your GitLab account."
-msgstr ""
+msgstr "L'authentification à deux facteurs a été désactivée pour votre compte GitLab."
msgid "Two-factor authentication has been disabled successfully!"
-msgstr ""
+msgstr "L'authentification à deux facteurs a été désactivée avec succès !"
msgid "Two-factor authentication is not enabled for this user"
-msgstr ""
+msgstr "L'authentification à deux facteurs n'est pas activée pour cet utilisateur"
msgid "Two-factor grace period"
-msgstr ""
+msgstr "Délai de grâce des deux facteurs"
msgid "Type"
msgstr "Type"
@@ -41817,55 +42568,55 @@ msgid "URL"
msgstr ""
msgid "URL cannot be blank"
-msgstr ""
+msgstr "L'URL ne peut pas être vide"
msgid "URL is invalid"
-msgstr ""
+msgstr "L'URL n'est pas valide"
msgid "URL is required"
-msgstr ""
+msgstr "Une URL est requise."
msgid "URL is triggered for each branch updated to the repository"
-msgstr ""
+msgstr "L'URL est déclenchée pour chaque branche mise à jour sur le dépôt"
msgid "URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
+msgstr "L'URL est déclenchée quand une demande de fusion est créée, mise à jour ou fusionnée"
msgid "URL is triggered when a new tag is pushed to the repository"
-msgstr ""
+msgstr "L'URL est déclenchée quand une nouvelle étiquette est poussée vers le dépôt"
msgid "URL is triggered when repository is updated"
-msgstr ""
+msgstr "L'URL est déclenchée quand le dépôt est mis à jour"
msgid "URL must be percent-encoded if necessary."
-msgstr ""
+msgstr "L’URL doit être encodée en pourcent si nécessaire."
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
-msgstr ""
+msgstr "L'URL doit commencer par %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, ou %{codeStart}ftp://%{codeEnd}"
msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
-msgstr ""
+msgstr "URL de l'instance Grafana à laquelle se relier depuis l'option de menu Tableau de Bord des Métriques."
msgid "URL of the external Spam Check endpoint"
-msgstr ""
+msgstr "URL du point de terminaison Spam Check externe"
msgid "URL of the external storage to serve the repository static objects."
-msgstr ""
+msgstr "URL du stockage externe pour desservir les objets statiques du dépôt."
msgid "URL or request ID"
msgstr ""
msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "L'UTILISATEUR %{user_name} SERA SUPPRIMÉ ! Êtes-vous sûr(e) ?"
msgid "USER %{user} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "L'UTILISATEUR %{user} SERA SUPPRIMÉ ! Êtes-vous sûr(e) ?"
msgid "USER WILL BE BLOCKED! Are you sure?"
-msgstr ""
+msgstr "L'UTILISATEUR SERA BLOQUÉ ! Êtes-vous sûr(e) ?"
msgid "UTC"
-msgstr ""
+msgstr "UTC"
msgid "Unable to apply suggestions to a deleted line."
msgstr ""
@@ -41886,55 +42637,55 @@ msgid "Unable to connect to server: %{error}"
msgstr ""
msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
-msgstr ""
+msgstr "Impossible de se connecter à l'instance Jira. Veuillez vérifier votre configuration d'intégration Jira."
msgid "Unable to create link to vulnerability"
-msgstr ""
+msgstr "Impossible de créer le lien vers la vulnérabilité"
msgid "Unable to fetch branch list for this project."
-msgstr ""
+msgstr "Impossible de récupérer la liste des branches de ce projet."
msgid "Unable to fetch branches list, please close the form and try again"
-msgstr ""
+msgstr "Impossible de récupérer la liste des branches, veuillez fermer le formulaire et réessayer"
msgid "Unable to fetch upstream and downstream pipelines."
msgstr ""
msgid "Unable to find Jira project to import data from."
-msgstr ""
+msgstr "Impossible de trouver le projet Jira à partir duquel importer les données."
msgid "Unable to fully load the default commit message. You can still apply this suggestion and the commit message will be correct."
-msgstr ""
+msgstr "Impossible de charger entièrement le message de commit par défaut. Vous pouvez néanmoins appliquer cette suggestion et le message de commit sera corrigé."
msgid "Unable to generate new instance ID"
msgstr ""
msgid "Unable to load commits. Try again later."
-msgstr ""
+msgstr "Impossible de charger les commits. Réessayez plus tard."
msgid "Unable to load file contents. Try again later."
-msgstr ""
+msgstr "Impossible de charger le contenu du fichier. Réessayez plus tard."
msgid "Unable to load refs"
msgstr ""
msgid "Unable to load the diff"
-msgstr ""
+msgstr "Impossible de charger le diff"
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Impossible de charger le diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
-msgstr ""
+msgstr "Impossible de charger le widget de demande de fusion. Essayez de recharger la page."
msgid "Unable to parse JSON"
-msgstr ""
+msgstr "Impossible d’analyser le JSON"
msgid "Unable to parse the vulnerability report's options."
-msgstr ""
+msgstr "Impossible d'analyser les options du rapport de vulnérabilités."
msgid "Unable to save iteration. Please try again"
-msgstr ""
+msgstr "Impossible d'enregistrer l'itération. Veuillez réessayer"
msgid "Unable to save your changes. Please try again."
msgstr ""
@@ -41949,7 +42700,7 @@ msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Impossible de vous connecter au groupe via SAML en raison de « %{reason} »"
msgid "Unable to suggest a path. Please refresh and try again."
-msgstr ""
+msgstr "Impossible de suggérer un chemin. Veuillez actualiser et réessayer."
msgid "Unable to update label prioritization at this time"
msgstr ""
@@ -41964,40 +42715,40 @@ msgid "Unable to verify the user"
msgstr ""
msgid "Unapprove a merge request"
-msgstr ""
+msgstr "Désapprouver une demande de fusion"
msgid "Unapprove the current merge request."
-msgstr ""
+msgstr "Désapprouver la demande de fusion actuelle."
msgid "Unapproved the current merge request."
-msgstr ""
+msgstr "Demande de fusion actuelle désapprouvée."
msgid "Unarchive project"
msgstr ""
msgid "Unarchiving the project restores its members' ability to make commits, and create issues, comments, and other entities. %{strong_start}After you unarchive the project, it displays in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Le désarchivage du projet redonnera à ses membres la possibilité d'y faire des commits et d'y créer des tickets, commentaires ou autres entités. %{strong_start}Une fois le projet désarchivé, il apparaîtra dans les recherches et sur le tableau de bord.%{strong_end} %{link_start}En savoir plus.%{link_end}"
msgid "Unassign from commenting user"
-msgstr ""
+msgstr "Ne plus assigner à l'émetteur du commentaire"
msgid "Unassigned"
msgstr "Non assigné(e)"
msgid "Unauthenticated API rate limit period in seconds"
-msgstr ""
+msgstr "Durée de la limitation de fréquence des requêtes d'API non authentifiées en secondes"
msgid "Unauthenticated requests"
-msgstr ""
+msgstr "Demandes non authentifiées"
msgid "Unauthenticated web rate limit period in seconds"
-msgstr ""
+msgstr "Durée de la limitation de fréquence des requêtes Web non authentifiées en secondes"
msgid "Unban"
msgstr ""
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
-msgstr ""
+msgstr "Les modifications non validées seront perdues si vous changez de branche. Voulez-vous continuer ?"
msgid "Undo"
msgstr "Annuler"
@@ -42009,22 +42760,22 @@ msgid "Undo ignore"
msgstr ""
msgid "Unexpected error"
-msgstr ""
+msgstr "Erreur inattendue"
msgid "Unfollow"
-msgstr ""
+msgstr "Ne plus suivre"
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
msgid "Unhappy?"
-msgstr ""
+msgstr "Non satisfait ?"
msgid "Units|ms"
-msgstr ""
+msgstr "ms"
msgid "Units|s"
-msgstr ""
+msgstr "s"
msgid "Unknown"
msgstr "Inconnu"
@@ -42042,25 +42793,25 @@ msgid "Unknown response text"
msgstr ""
msgid "Unknown user"
-msgstr ""
+msgstr "Utilisateur inconnu"
msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
-msgstr ""
+msgstr "Sauf accord contraire écrit avec GitLab, en cliquant sur « Téléverser la licence », vous acceptez que votre utilisation du logiciel GitLab soit soumise aux %{eula_link_start}Conditions Générales d'Utilisation%{eula_link_end}."
msgid "Unlimited"
msgstr ""
msgid "Unlink"
-msgstr ""
+msgstr "Dissocier"
msgid "Unlock"
msgstr "Déverrouiller"
msgid "Unlock account"
-msgstr ""
+msgstr "Déverrouiller le compte"
msgid "Unlock merge request"
-msgstr ""
+msgstr "Déverrouiller la demande de fusion"
msgid "Unlock more features with GitLab Ultimate"
msgstr ""
@@ -42069,7 +42820,7 @@ msgid "Unlock the discussion"
msgstr ""
msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "Déverrouiller ce %{issuableDisplayName} ? %{strongStart}Tout le monde%{strongEnd} sera en mesure de mettre un commentaire."
msgid "Unlocked"
msgstr "Déverrouillé"
@@ -42081,13 +42832,13 @@ msgid "Unlocks the discussion."
msgstr ""
msgid "Unreachable"
-msgstr ""
+msgstr "Injoignable"
msgid "Unrecognized approval status."
msgstr ""
msgid "Unrecognized cluster type"
-msgstr ""
+msgstr "Type de grappe de serveurs non reconnu"
msgid "Unresolve"
msgstr ""
@@ -42117,7 +42868,7 @@ msgid "Unsubscribe at project level"
msgstr "Se désabonner au niveau du projet"
msgid "Unsubscribe from %{type}"
-msgstr ""
+msgstr "Se désabonner de %{type}"
msgid "Unsubscribed from this %{quick_action_target}."
msgstr ""
@@ -42129,13 +42880,13 @@ msgid "Unsupported sort value."
msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
-msgstr ""
+msgstr "Type « À faire » non pris en charge. Les types « À faire » supportés sont : %{todo_types}"
msgid "Unused"
msgstr ""
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
-msgstr ""
+msgstr "Inutilisés, les index précédents : %{index_names} seront supprimés automatiquement après %{time}."
msgid "Unverified"
msgstr "Non vérifié"
@@ -42156,16 +42907,16 @@ msgid "Update %{sourcePath} file"
msgstr ""
msgid "Update Now"
-msgstr ""
+msgstr "Mettre à jour maintenant"
msgid "Update Scheduled…"
-msgstr ""
+msgstr "Mise à jour planifiée…"
msgid "Update all"
msgstr "Tout mettre à jour"
msgid "Update appearance settings"
-msgstr ""
+msgstr "Mettre à jour les paramètres d'apparence"
msgid "Update approval rule"
msgstr ""
@@ -42174,7 +42925,7 @@ msgid "Update approvers"
msgstr ""
msgid "Update broadcast message"
-msgstr ""
+msgstr "Mettre à jour le message de diffusion"
msgid "Update failed"
msgstr ""
@@ -42183,7 +42934,7 @@ msgid "Update it"
msgstr ""
msgid "Update milestone"
-msgstr ""
+msgstr "Mettre à jour le jalon"
msgid "Update now"
msgstr "Mettre à jour maintenant"
@@ -42216,7 +42967,7 @@ msgid "UpdateProject|Project could not be updated!"
msgstr "Le projet n'a pas pu être mis à jour!"
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
-msgstr ""
+msgstr "Échec de la vérification de la somme de contrôle du dépôt %{type} entre %{old} et %{new}"
msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
msgstr ""
@@ -42234,22 +42985,22 @@ msgid "Updating"
msgstr "Mise à jour en cours"
msgid "Updating…"
-msgstr ""
+msgstr "Mise à jour…"
msgid "Upgrade offers available!"
-msgstr ""
+msgstr "Des offres de mise à niveau sont disponibles !"
msgid "Upload"
-msgstr ""
+msgstr "Téléverser"
msgid "Upload %{file_name} file"
-msgstr ""
+msgstr "Téléversez le fichier %{file_name}"
msgid "Upload CSV file"
msgstr ""
msgid "Upload File"
-msgstr ""
+msgstr "Téléverser un Fichier"
msgid "Upload New File"
msgstr "Téléverser un nouveau fichier"
@@ -42261,28 +43012,28 @@ msgid "Upload a private key for your certificate"
msgstr ""
msgid "Upload could not be deleted."
-msgstr ""
+msgstr "Le téléversement n'a pas pu être supprimé."
msgid "Upload file"
msgstr "Téléverser un fichier"
msgid "Upload image"
-msgstr ""
+msgstr "Téléverser l'image"
msgid "Upload new file"
-msgstr ""
+msgstr "Téléverser un nouveau fichier"
msgid "Upload object map"
msgstr ""
msgid "Uploaded date"
-msgstr ""
+msgstr "Date de téléversement"
msgid "Uploading changes to terminal"
msgstr ""
msgid "Uploading..."
-msgstr ""
+msgstr "Téléversement en cours..."
msgid "Upstream"
msgstr ""
@@ -42291,7 +43042,7 @@ msgid "Upvotes"
msgstr "Votes positifs"
msgid "Usage Trends"
-msgstr ""
+msgstr "Tendances d'Utilisation"
msgid "Usage statistics"
msgstr "Statistiques d’utilisation"
@@ -42300,14 +43051,17 @@ msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled,
msgstr ""
msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there are no limits set on pipeline usage"
-msgstr ""
+msgstr "Les %{linkStart}Exécuteurs Partagés%{linkEnd} sont désactivés. Aucune limite d'utilisation du pipeline n'est donc définie"
msgid "UsageQuota|%{linkTitle} help link"
-msgstr ""
+msgstr "lien d'aide %{linkTitle}"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr "%{storage_limit_link_start}Une limite de stockage d'espace de noms%{link_end} sera bientôt imposée pour l'espace de noms %{strong_start}%{namespace_name}%{strong_end}. %{extra_message}"
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42315,19 +43069,19 @@ msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
-msgstr ""
+msgstr "Échantillons sonores, vidéos, jeux de données et graphismes."
msgid "UsageQuota|Buy additional minutes"
msgstr ""
msgid "UsageQuota|Buy storage"
-msgstr ""
+msgstr "Acheter du stockage"
msgid "UsageQuota|CI minutes usage by month"
-msgstr ""
+msgstr "Utilisation des minutes CI par mois"
msgid "UsageQuota|CI minutes usage by project"
-msgstr ""
+msgstr "Utilisation des minutes CI par projet"
msgid "UsageQuota|CI/CD minutes usage"
msgstr ""
@@ -42336,55 +43090,55 @@ msgid "UsageQuota|CI/CD minutes usage since %{timeElapsed}"
msgstr ""
msgid "UsageQuota|CI/CD minutes usage since %{usageSince}"
-msgstr ""
+msgstr "Utilisation des minutes CI/CD depuis %{usageSince}"
msgid "UsageQuota|Code packages and container images."
-msgstr ""
+msgstr "Paquets de code et images de conteneur."
msgid "UsageQuota|Container Registry"
-msgstr ""
+msgstr "Registre de Conteneur"
msgid "UsageQuota|Current period usage"
msgstr ""
msgid "UsageQuota|Dependency proxy"
-msgstr ""
-
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr ""
+msgstr "Proxy de dépendance"
msgid "UsageQuota|File attachments and smaller design graphics."
-msgstr ""
+msgstr "Pièces-jointes et graphismes de design plus petits."
+
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr "Pour plus d'informations sur les limites de stockage, consultez notre %{faq_link_start}FAQ%{link_end}."
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Dépôt Git."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
-msgstr ""
+msgstr "Registre de Conteneurs Docker intégré à GitLab pour le stockage d'Images Docker."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "UsageQuota|Group settings &gt; Usage quotas"
-msgstr ""
+msgstr "Paramètres de groupe &gt; Quotas d'utilisation"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
-msgstr ""
+msgstr "Comprend les artéfacts, les dépôts, le wiki, les téléversements et d'autres éléments."
msgid "UsageQuota|Increase storage temporarily"
-msgstr ""
+msgstr "Augmenter temporairement le stockage"
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "Stockage LFS"
msgid "UsageQuota|Learn more about excess storage usage"
-msgstr ""
+msgstr "En savoir plus sur l'utilisation de stockage excédentaire"
msgid "UsageQuota|Learn more about usage quotas"
-msgstr ""
+msgstr "En savoir plus sur les quotas d'utilisation"
msgid "UsageQuota|Learn more about usage quotas."
-msgstr ""
+msgstr "En savoir plus sur les quotas d'utilisation."
msgid "UsageQuota|Local proxy used for frequently-accessed upstream Docker images. %{linkStart}More information%{linkEnd}"
msgstr ""
@@ -42393,31 +43147,31 @@ msgid "UsageQuota|Namespace storage used"
msgstr ""
msgid "UsageQuota|No CI minutes usage data available."
-msgstr ""
+msgstr "Aucune donnée d'utilisation des minutes CI disponible."
msgid "UsageQuota|Packages"
msgstr ""
msgid "UsageQuota|Pending Members"
-msgstr ""
+msgstr "Membres en attente"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
-msgstr ""
+msgstr "Artéfacts de pipeline et de tâches créés par CI/CD."
msgid "UsageQuota|Pipelines"
msgstr ""
msgid "UsageQuota|Purchase more storage"
-msgstr ""
+msgstr "Acheter plus de stockage"
msgid "UsageQuota|Purchased storage"
-msgstr ""
+msgstr "Stockage acheté"
msgid "UsageQuota|Purchased storage available"
msgstr ""
msgid "UsageQuota|Purchased storage used"
-msgstr ""
+msgstr "Stockage acheté utilisé"
msgid "UsageQuota|Recalculate repository usage"
msgstr ""
@@ -42426,85 +43180,82 @@ msgid "UsageQuota|Repository"
msgstr ""
msgid "UsageQuota|Seats"
-msgstr ""
-
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
+msgstr "Sièges"
msgid "UsageQuota|Shared bits of code and text."
-msgstr ""
+msgstr "Bouts de code et de texte partagés."
msgid "UsageQuota|Shared runner duration"
msgstr ""
msgid "UsageQuota|Snippets"
-msgstr ""
+msgstr "Extraits"
msgid "UsageQuota|Something went wrong while fetching pipeline statistics"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des statistiques des pipelines"
msgid "UsageQuota|Something went wrong while fetching project storage statistics"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des statistiques de stockage du projet"
msgid "UsageQuota|Something went wrong while loading usage details"
-msgstr ""
+msgstr "Une erreur s'est produite lors du chargement des détails d'utilisation"
msgid "UsageQuota|Storage"
msgstr ""
msgid "UsageQuota|Storage type"
-msgstr ""
+msgstr "Type de stockage"
msgid "UsageQuota|Storage used"
-msgstr ""
+msgstr "Stockage utilisé"
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "
-msgstr ""
+msgstr "Cela affectera le groupe %{strong_start}%{context_name}%{strong_end}. "
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
-msgstr ""
+msgstr "Cela affectera le projet %{strong_start}%{context_name}%{strong_end}. "
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
-msgstr ""
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr "L'espace de noms utilise actuellement %{strong_start}%{used_storage}%{strong_end} du stockage de l'espace de noms. Les propriétaires du groupe peuvent voir l'utilisation du stockage d'espace de noms et en acheter davantage depuis les %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Comment puis-je gérer mon stockage ?%{link_end}."
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
-msgstr ""
+msgstr "L'espace de noms utilise actuellement %{strong_start}%{used_storage}%{strong_end} du stockage de l'espace de noms. Affichez et gérez votre utilisation depuis les %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}En savoir plus%{link_end} sur comment diminuer votre stockage."
msgid "UsageQuota|The table below shows current period usage"
-msgstr ""
+msgstr "Le tableau ci-dessous montre l'utilisation sur la période actuelle"
msgid "UsageQuota|The table below shows usage since %{timeElapsed}"
-msgstr ""
+msgstr "Le tableau ci-dessous montre l'utilisation depuis %{timeElapsed}"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
-msgstr ""
+msgstr "Il s'agit de la quantité totale de stockage utilisée par tous vos projets dans cet espace de noms."
msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
-msgstr ""
+msgstr "Il s'agit de la quantité totale de stockage utilisée par les projets au-dessus de la limite de stockage gratuit de %{actualRepositorySizeLimit}."
msgid "UsageQuota|This namespace contains locked projects"
-msgstr ""
+msgstr "Cet espace de noms contient des projets verrouillés"
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
msgid "UsageQuota|This namespace has no projects which used shared runners in the current period"
-msgstr ""
+msgstr "Aucun projet de cet espace de noms n'a utilisé d'exécuteurs partagés sur la période actuelle"
msgid "UsageQuota|This table omits projects that used 0 CI/CD minutes or 0 shared runners duration"
-msgstr ""
+msgstr "Ce tableau omet les projets qui ont utilisé 0 minute CI/CD ou 0 durée des exécuteurs partagés"
msgid "UsageQuota|Total excess storage used"
-msgstr ""
+msgstr "Quantité totale de stockage excédentaire utilisée"
msgid "UsageQuota|Total namespace storage used"
-msgstr ""
+msgstr "Quantité totale de stockage utilisé pour l'espace de noms"
msgid "UsageQuota|Unlimited"
msgstr ""
msgid "UsageQuota|Uploads"
-msgstr ""
+msgstr "Téléversements"
msgid "UsageQuota|Usage"
msgstr ""
@@ -42513,7 +43264,7 @@ msgid "UsageQuota|Usage Quotas"
msgstr ""
msgid "UsageQuota|Usage breakdown"
-msgstr ""
+msgstr "Répartition de l'utilisation"
msgid "UsageQuota|Usage by month"
msgstr ""
@@ -42525,115 +43276,115 @@ msgid "UsageQuota|Usage of group resources across the projects in the %{strong_s
msgstr ""
msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project"
-msgstr ""
+msgstr "Utilisation des ressources du projet à travers le projet %{strong_start}%{project_name}%{strong_end}"
msgid "UsageQuota|Usage of resources across your projects"
-msgstr ""
+msgstr "Utilisation des ressources par tous vos projets"
msgid "UsageQuota|Usage quotas help link"
-msgstr ""
+msgstr "Lien d'aide sur les quotas d'utilisation"
msgid "UsageQuota|User settings &gt; Usage quotas"
-msgstr ""
+msgstr "Paramètres utilisateur &gt; Quotas d'utilisation"
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
-msgstr ""
+msgstr "Dès le moment où vous achetez de l'espace de stockage supplémentaire, nous débloquons automatiquement les projets qui ont été verrouillés lorsque vous avez atteint la limite de %{actualRepositorySizeLimit}."
msgid "UsageQuota|Wiki"
msgstr ""
msgid "UsageQuota|Wiki content."
-msgstr ""
+msgstr "Contenu Wiki."
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
-msgstr ""
+msgstr "Vous avez utilisé la totalité de votre stockage supplémentaire, veuillez en acheter davantage pour déverrouiller vos projets au-delà de la limite gratuite de %{actualRepositorySizeLimit}."
msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
-msgstr ""
+msgstr "Vous avez atteint la limite de stockage gratuit de %{actualRepositorySizeLimit} sur %{projectsLockedText}. Pour les déverrouiller, veuillez acheter de l'espace de stockage supplémentaire."
msgid "UsageQuota|You used: %{usage} %{limit}"
-msgstr ""
+msgstr "Vous avez utilisé : %{usage} %{limit}"
msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
-msgstr ""
+msgstr "Le stockage que vous avez acheté arrive bientôt à saturation. Pour éviter le verrouillage des projets, veuillez en acquérir davantage."
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
-msgstr ""
+msgstr "sur %{formattedLimit} du stockage de votre espace de noms"
msgid "UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again."
-msgstr ""
+msgstr "Impossible de charger le graphique des tickets et des demandes de fusion. Veuillez actualiser la page pour réessayer."
msgid "UsageTrends|Could not load the pipelines chart. Please refresh the page to try again."
-msgstr ""
+msgstr "Impossible de charger le graphique des pipelines. Veuillez actualiser la page pour réessayer."
msgid "UsageTrends|Could not load the projects and groups chart. Please refresh the page to try again."
-msgstr ""
+msgstr "Impossible de charger le graphique des groupes et projets. Veuillez actualiser la page pour réessayer."
msgid "UsageTrends|Groups"
-msgstr ""
+msgstr "Groupes"
msgid "UsageTrends|Issues"
-msgstr ""
+msgstr "Tickets"
msgid "UsageTrends|Issues & merge requests"
-msgstr ""
+msgstr "Tickets et demandes de fusion"
msgid "UsageTrends|Items"
-msgstr ""
+msgstr "Éléments"
msgid "UsageTrends|Merge requests"
-msgstr ""
+msgstr "Demandes de fusion"
msgid "UsageTrends|Month"
-msgstr ""
+msgstr "Mois"
msgid "UsageTrends|No data available."
-msgstr ""
+msgstr "Aucune donnée disponible."
msgid "UsageTrends|Pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "UsageTrends|Pipelines canceled"
-msgstr ""
+msgstr "Pipelines annulés"
msgid "UsageTrends|Pipelines failed"
-msgstr ""
+msgstr "Pipelines ayant échoué"
msgid "UsageTrends|Pipelines skipped"
-msgstr ""
+msgstr "Pipelines ignorés"
msgid "UsageTrends|Pipelines succeeded"
-msgstr ""
+msgstr "Pipelines ayant réussi"
msgid "UsageTrends|Pipelines total"
msgstr ""
msgid "UsageTrends|Projects"
-msgstr ""
+msgstr "Projets"
msgid "UsageTrends|There was an error fetching the cancelled pipelines. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des pipelines annulés. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the failed pipelines. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des pipelines qui ont échoué. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the groups. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des groupes. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the issues. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des tickets. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the merge requests. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des demandes de fusion. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des projets. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the skipped pipelines. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des pipelines ignorés. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the successful pipelines. Please try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des pipelines réussis. Veuillez réessayer."
msgid "UsageTrends|There was an error fetching the total pipelines. Please try again."
msgstr ""
@@ -42645,10 +43396,10 @@ msgid "UsageTrends|Total projects"
msgstr ""
msgid "UsageTrends|Total projects & groups"
-msgstr ""
+msgstr "Nombre total de groupes et projets"
msgid "UsageTrends|Users"
-msgstr ""
+msgstr "Utilisateurs"
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -42657,22 +43408,22 @@ msgid "Use .gitlab-ci.yml"
msgstr ""
msgid "Use GitLab Runner in AWS"
-msgstr ""
+msgstr "Utiliser GitLab Runner sur AWS"
msgid "Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates."
msgstr ""
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
-msgstr ""
+msgstr "Utilisez un générateur de mot de passe à usage unique sur votre appareil mobile ou votre ordinateur pour activer l'authentification à deux facteurs (A2F)."
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
-msgstr ""
+msgstr "Utilisez un modèle AWS CloudFormation (CFT) pour installer et configurer GitLab Runner sur AWS."
msgid "Use authorized_keys file to authenticate SSH keys"
-msgstr ""
+msgstr "Utiliser le fichier authorized_keys pour authentifier les clés SSH"
msgid "Use banners and notifications to notify your users about scheduled maintenance, recent upgrades, and more."
-msgstr ""
+msgstr "Utilisez des bannières et des notifications pour informer vos utilisateurs des maintenances planifiées, des mises à jour récentes, etc."
msgid "Use cURL"
msgstr ""
@@ -42681,58 +43432,58 @@ msgid "Use custom color #FF0000"
msgstr ""
msgid "Use double quotes for multiple keywords, such as %{code_open}\"your search\"%{code_close}"
-msgstr ""
+msgstr "Utilisez des guillemets doubles s'il y a plusieurs mots-clés, comme %{code_open}\"votre recherche\"%{code_close}"
msgid "Use hashed storage"
msgstr ""
msgid "Use hashed storage paths for newly created and renamed repositories. Always enabled since 13.0. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Utiliser des chemins de stockage hachés pour les dépôts renommés ou nouvellement créés. Toujours activé depuis la version 13.0. %{link_start}En savoir plus.%{link_end}"
msgid "Use issue count"
-msgstr ""
+msgstr "Utiliser le nombre de tickets"
msgid "Use issue weight"
-msgstr ""
+msgstr "Utiliser le poids des tickets"
msgid "Use issues to collaborate on ideas, solve problems, and plan work"
-msgstr ""
+msgstr "Utiliser les tickets pour collaborer sur des idées, résoudre des problèmes et planifier le travail"
msgid "Use one line per URI"
msgstr "Utilisez une ligne par URI"
msgid "Use primary email (%{email})"
-msgstr ""
+msgstr "Utiliser l'adresse de courriel principale (%{email})"
msgid "Use shortcuts"
-msgstr ""
+msgstr "Utiliser les raccourcis"
msgid "Use slash commands."
-msgstr ""
+msgstr "Utiliser les commandes barre oblique."
msgid "Use template"
msgstr "Utiliser ce modèle"
msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
-msgstr ""
+msgstr "Utiliser l'option %{strongStart}Test%{strongEnd} ci-dessus pour créer un événement."
msgid "Use the link below to confirm your email address (%{email})"
-msgstr ""
+msgstr "Utilisez le lien ci-dessous pour confirmer votre adresse de courriel (%{email})"
msgid "Use the link below to confirm your email address."
-msgstr ""
+msgstr "Utilisez le lien ci-dessous pour confirmer votre adresse de courriel."
msgid "Use the public cloud instance URL (%{kroki_public_url}) or %{install_link_start}install Kroki%{install_link_end} on your own infrastructure and use your own instance URL."
-msgstr ""
+msgstr "Utilisez l'URL de l'instance Cloud publique (%{kroki_public_url}) ou %{install_link_start}installez Kroki%{install_link_end} sur votre propre infrastructure pour utiliser l'URL de votre instance."
msgid "Use the search bar on the top of this page"
-msgstr ""
+msgstr "Utilisez la barre de recherche en haut de cette page"
msgid "Use this token to validate received payloads."
-msgstr ""
+msgstr "Utiliser ce jeton pour valider les charges utiles reçues."
msgid "Use webhook"
-msgstr ""
+msgstr "Utiliser un point d'ancrage web"
msgid "Use your global notification setting"
msgstr "Utiliser vos paramètres de notification globaux"
@@ -42745,35 +43496,35 @@ msgstr ""
msgid "Used by %d package"
msgid_plural "Used by %d packages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Utilisation par %d paquet"
+msgstr[1] "Utilisation par %d paquets"
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilisé par les membres pour se connecter à votre groupe dans GitLab"
msgid "Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises."
-msgstr ""
+msgstr "Utilisé par plus de 100000 organisations, GitLab est la solution la plus populaire pour gérer des dépôts git sur site."
msgid "Used programming language"
-msgstr ""
+msgstr "Langage de programmation utilisé"
msgid "Used to help configure your identity provider"
msgstr ""
msgid "User"
-msgstr ""
+msgstr "Utilisateur"
msgid "User %{current_user_username} has started impersonating %{username}"
-msgstr ""
+msgstr "L'utilisateur %{current_user_username} a commencé à emprunter l'identité de %{username}"
msgid "User %{username} was successfully removed."
-msgstr ""
+msgstr "L'utilisateur %{username} a été supprimé avec succès."
msgid "User %{user} was removed from %{group}."
-msgstr ""
+msgstr "L'utilisateur %{user} a été supprimé de %{group}."
msgid "User ID"
-msgstr ""
+msgstr "ID utilisateur"
msgid "User OAuth applications"
msgstr ""
@@ -42782,7 +43533,7 @@ msgid "User Settings"
msgstr "Paramètres de l’utilisateur"
msgid "User and IP rate limits"
-msgstr ""
+msgstr "Limitations de fréquence des IP et Utilisateurs"
msgid "User cap"
msgstr ""
@@ -42794,7 +43545,7 @@ msgid "User created at"
msgstr ""
msgid "User does not have a pending request"
-msgstr ""
+msgstr "L'utilisateur n'a pas de requête en attente"
msgid "User identity was successfully created."
msgstr ""
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr "L'utilisateur est bloqué"
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42827,16 +43581,16 @@ msgid "User restrictions"
msgstr ""
msgid "User settings"
-msgstr ""
+msgstr "Paramètres utilisateur"
msgid "User was successfully created."
msgstr ""
msgid "User was successfully removed from group and any subgroups and projects."
-msgstr ""
+msgstr "L'utilisateur a été supprimé du groupe et de ses sous-groupes et projets avec succès."
msgid "User was successfully removed from group."
-msgstr ""
+msgstr "L'utilisateur a été supprimé du groupe avec succès."
msgid "User was successfully removed from project."
msgstr ""
@@ -42848,94 +43602,94 @@ msgid "User was successfully updated."
msgstr ""
msgid "User-based escalation rules must have a user with access to the project"
-msgstr ""
+msgstr "Les règles d'escalade basées sur l'utilisateur doivent avoir un utilisateur ayant un accès au projet"
msgid "UserAvailability|%{author} %{spanStart}(Busy)%{spanEnd}"
-msgstr ""
+msgstr "%{author} %{spanStart}(Occupé)%{spanEnd}"
msgid "UserAvailability|%{author} (Busy)"
-msgstr ""
+msgstr "%{author} (Occupé)"
msgid "UserAvailability|(Busy)"
-msgstr ""
+msgstr "(Occupé)"
msgid "UserLists|Add"
-msgstr ""
+msgstr "Ajouter"
msgid "UserLists|Add Users"
-msgstr ""
+msgstr "Ajouter des Utilisateurs"
msgid "UserLists|Add users"
-msgstr ""
+msgstr "Ajouter des utilisateurs"
msgid "UserLists|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "UserLists|Create"
-msgstr ""
+msgstr "Créer"
msgid "UserLists|Define a set of users to be used within feature flag strategies"
-msgstr ""
+msgstr "Définissez un ensemble d'utilisateurs à utiliser dans les stratégies d'indicateurs de fonctionnalités"
msgid "UserLists|Edit"
-msgstr ""
+msgstr "Modifier"
msgid "UserLists|Edit %{name}"
-msgstr ""
+msgstr "Modifier %{name}"
msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
-msgstr ""
+msgstr "Entrez une liste d'IDs d'utilisateurs séparés par des virgules. Ces IDs doivent être ceux des utilisateurs du système dont l'indicateur de fonctionnalité est défini, et non des IDs GitLab"
msgid "UserLists|Feature flag user list"
-msgstr ""
+msgstr "liste d'utilisateurs des indicateurs de fonctionnalités"
msgid "UserLists|Get started with user lists"
-msgstr ""
+msgstr "Premiers pas avec les listes d'utilisateurs"
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
-msgstr ""
+msgstr "Les listes vous permettent de définir un ensemble d'utilisateurs à utiliser avec les indicateurs de fonctionnalités. %{linkStart}En savoir plus sur les listes d'indicateurs de fonctionnalités.%{linkEnd}"
msgid "UserLists|Loading user lists"
-msgstr ""
+msgstr "Chargement des listes d'utilisateurs"
msgid "UserLists|Name"
-msgstr ""
+msgstr "Nom"
msgid "UserLists|New list"
-msgstr ""
+msgstr "Nouvelle liste"
msgid "UserLists|New user list"
-msgstr ""
+msgstr "Nouvelle liste d'utilisateurs"
msgid "UserLists|Save"
-msgstr ""
+msgstr "Enregistrer"
msgid "UserLists|There are no users"
-msgstr ""
+msgstr "Il n'y a aucun utilisateur"
msgid "UserLists|There was an error fetching the user lists."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des listes d’utilisateurs."
msgid "UserLists|User ID"
-msgstr ""
+msgstr "ID utilisateur"
msgid "UserLists|User IDs"
-msgstr ""
+msgstr "IDs utilisateur"
msgid "UserLists|User Lists"
-msgstr ""
+msgstr "Listes d'Utilisateurs"
msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
-msgstr ""
+msgstr "Les listes d'utilisateurs vous permettent de définir un ensemble d'utilisateurs à utiliser avec les Indicateurs de Fonctionnalités."
msgid "UserList|Delete %{name}?"
-msgstr ""
+msgstr "Supprimer %{name} ?"
msgid "UserList|created %{timeago}"
msgstr ""
msgid "UserProfile|(Busy)"
-msgstr ""
+msgstr "(Occupé)"
msgid "UserProfile|Activity"
msgstr "Activité"
@@ -42947,13 +43701,13 @@ msgid "UserProfile|Blocked user"
msgstr ""
msgid "UserProfile|Bot activity"
-msgstr ""
+msgstr "Activité du bot"
msgid "UserProfile|Contributed projects"
msgstr "A contribué aux projets"
msgid "UserProfile|Copy user ID"
-msgstr ""
+msgstr "Copier l'ID utilisateur"
msgid "UserProfile|Edit profile"
msgstr "Modifier le profil"
@@ -42962,10 +43716,10 @@ msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr "Explorez les groupes publics pour trouver des projets pour lesquels contribuer."
msgid "UserProfile|Followers"
-msgstr ""
+msgstr "Abonnés"
msgid "UserProfile|Following"
-msgstr ""
+msgstr "Suivi"
msgid "UserProfile|Groups"
msgstr "Groupes"
@@ -42995,7 +43749,7 @@ msgid "UserProfile|Report abuse"
msgstr "Signaler un abus"
msgid "UserProfile|Retry"
-msgstr ""
+msgstr "Réessayer"
msgid "UserProfile|Snippets"
msgstr "Fragments de code"
@@ -43013,7 +43767,7 @@ msgid "UserProfile|Subscribe"
msgstr "S’abonner"
msgid "UserProfile|This user doesn't have any followers."
-msgstr ""
+msgstr "Cet utilisateur n'a aucun abonné."
msgid "UserProfile|This user doesn't have any personal projects"
msgstr "Cet utilisateur ne dispose pas de projets personnels"
@@ -43031,13 +43785,13 @@ msgid "UserProfile|This user is blocked"
msgstr ""
msgid "UserProfile|This user isn't following other users."
-msgstr ""
+msgstr "Cet utilisateur ne suit pas d'autres utilisateurs."
msgid "UserProfile|Unconfirmed user"
-msgstr ""
+msgstr "Utilisateur non confirmé"
msgid "UserProfile|User ID: %{id}"
-msgstr ""
+msgstr "ID utilisateur : %{id}"
msgid "UserProfile|View all"
msgstr "Tout afficher"
@@ -43046,13 +43800,13 @@ msgid "UserProfile|View user in admin area"
msgstr "Afficher l’utilisateur dans l’espace d’administration"
msgid "UserProfile|You are not following other users."
-msgstr ""
+msgstr "Vous ne suivez pas d'autres utilisateurs."
msgid "UserProfile|You can create a group for several dependent projects."
msgstr ""
msgid "UserProfile|You do not have any followers."
-msgstr ""
+msgstr "Vous n'avez aucun abonné."
msgid "UserProfile|You haven't created any personal projects."
msgstr ""
@@ -43064,13 +43818,13 @@ msgid "UserProfile|Your projects can be available publicly, internally, or priva
msgstr ""
msgid "UserProfile|at"
-msgstr ""
+msgstr "chez"
msgid "UserProfile|made a private contribution"
-msgstr ""
+msgstr "a fait une contribution privée"
msgid "Username"
-msgstr ""
+msgstr "Nom d’utilisateur"
msgid "Username (optional)"
msgstr ""
@@ -43085,10 +43839,10 @@ msgid "Username or email"
msgstr ""
msgid "Username:"
-msgstr ""
+msgstr "Nom d’utilisateur :"
msgid "Username: %{username}"
-msgstr ""
+msgstr "Nom d'utilisateur : %{username}"
msgid "Users"
msgstr "Utilisateurs et utilisatrices"
@@ -43097,40 +43851,37 @@ msgid "Users API rate limit"
msgstr ""
msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
-msgstr ""
+msgstr "Les utilisateurs peuvent lancer un environnement de développement depuis un onglet de navigateur GitLab lorsque l'intégration %{linkStart}Gitpod%{linkEnd} est activée."
msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Les utilisateurs peuvent réactiver leur compte en se connectant. %{link_start}En savoir plus.%{link_end}"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
-msgstr ""
+msgstr "Les utilisateurs peuvent générer des diagrammes en AsciiDoc, Markdown, reStructuredText ainsi que des documents Textile en utilisant Kroki."
msgid "Users can request access (if visibility is public or internal)"
-msgstr ""
+msgstr "Les utilisateurs peuvent demander un accès (si la visibilité est publique ou interne)"
msgid "Users cannot be added to projects in this group"
-msgstr ""
+msgstr "Les utilisateurs ne peuvent pas être ajoutés aux projets de ce groupe"
msgid "Users in License"
-msgstr ""
+msgstr "Utilisateurs avec Licence"
msgid "Users or groups set as approvers in the project's or merge request's settings."
-msgstr ""
+msgstr "Utilisateurs ou groupes définis comme approbateurs dans les paramètres du projet ou des demandes de fusion."
msgid "Users over License"
-msgstr ""
+msgstr "Utilisateurs hors Licence"
msgid "Users requesting access to"
msgstr ""
msgid "Users to exclude from the rate limit"
-msgstr ""
-
-msgid "Users were successfully added."
-msgstr ""
+msgstr "Utilisateurs à exclure de la limitation de fréquence"
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
+msgstr "Les utilisateurs ayant un rôle d'Invité et ceux qui ne font pas partie d'un Projet ou d'un Groupe n'utiliseront pas de licence de siège."
msgid "UsersSelect|%{name} + %{length} more"
msgstr ""
@@ -43142,14 +43893,41 @@ msgid "UsersSelect|Assignee"
msgstr "Assigné"
msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
-msgstr ""
+msgstr "Non attribué - %{openingTag} Attribuer à vous même %{closingTag}"
msgid "UsersSelect|Unassigned"
+msgstr "Non assigné"
+
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr "Ingénieur Devops"
+
+msgid "User|Other"
+msgstr "Autre"
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Software Developer"
msgstr ""
+msgid "User|Systems Administrator"
+msgstr "Administrateur Système"
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr "Utilise GitLab comme une alternative à Sentry."
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
@@ -43157,7 +43935,7 @@ msgid "Using required encryption strategy when encrypted field is missing!"
msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
-msgstr ""
+msgstr "L'utilisation du mot-clé %{codeStart}needs%{codeEnd} (nécessité) permet aux tâches d'être exécutées avant que leur étape ne soit atteinte. Les tâches s'exécutent dès que leurs relations avec les %{codeStart}needs%{codeEnd} sont satisfaites, ce qui accélère vos pipelines."
msgid "Valid From"
msgstr ""
@@ -43166,7 +43944,7 @@ msgid "Validate"
msgstr ""
msgid "Validate your GitLab CI configuration"
-msgstr ""
+msgstr "Valider votre configuration GitLab CI"
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -43187,121 +43965,121 @@ msgid "Value"
msgstr ""
msgid "Value Stream Analytics"
-msgstr ""
+msgstr "Analyse des chaînes de valeur"
msgid "Value Stream Analytics can help you determine your team’s velocity"
-msgstr ""
+msgstr "L'analyse des chaînes de valeur peut vous aider à déterminer la vélocité de votre équipe"
msgid "Value might contain a variable reference"
-msgstr ""
+msgstr "La valeur peut contenir une référence de variable"
msgid "Value stream"
-msgstr ""
+msgstr "Chaînes de valeur"
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
-msgstr ""
+msgstr "Il n'y a pas assez de données pour afficher cette étape."
msgid "ValueStreamAnalytics|%{stageCount}+ items"
-msgstr ""
+msgstr "%{stageCount}+ éléments"
msgid "ValueStreamAnalytics|%{value}M"
-msgstr ""
+msgstr "%{value}M"
msgid "ValueStreamAnalytics|%{value}d"
-msgstr ""
+msgstr "%{value}d"
msgid "ValueStreamAnalytics|%{value}h"
-msgstr ""
+msgstr "%{value}h"
msgid "ValueStreamAnalytics|%{value}m"
-msgstr ""
+msgstr "%{value}m"
msgid "ValueStreamAnalytics|%{value}w"
-msgstr ""
+msgstr "%{value}w"
msgid "ValueStreamAnalytics|&lt;1m"
-msgstr ""
+msgstr "&lt;1m"
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
-msgstr ""
+msgstr "Nombre moyen de déploiements en production par jour."
msgid "ValueStreamAnalytics|DORA metrics"
-msgstr ""
+msgstr "Métriques DORA"
msgid "ValueStreamAnalytics|Dashboard"
-msgstr ""
+msgstr "Tableau de bord"
msgid "ValueStreamAnalytics|Go to docs"
-msgstr ""
+msgstr "Aller à la doc"
msgid "ValueStreamAnalytics|Key metrics"
-msgstr ""
+msgstr "Clés de mesures"
msgid "ValueStreamAnalytics|Median time an incident was open on a production environment in the given time period."
-msgstr ""
+msgstr "Temps médian pendant lequel un incident est resté ouvert dans un environnement de production sur la période temps donnée."
msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
-msgstr ""
+msgstr "Médiane de la durée de la création du ticket à sa fermeture."
msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
-msgstr ""
+msgstr "Nombre de commits poussés vers la branche par défaut"
msgid "ValueStreamAnalytics|Number of new issues created."
-msgstr ""
+msgstr "Nombre de nouveaux tickets créés."
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
-msgstr ""
+msgstr "Pourcentage des déploiements provoquant un icident en production."
msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Affiche %{selectedSubjectFilterText} et %{labelsCount} pour le groupe « %{groupName} » et %{projectsCount} du %{createdAfter} au %{createdBefore}"
msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Affiche %{selectedSubjectFilterText} et %{labelsCount} pour le groupe « %{groupName} » du %{createdAfter} au %{createdBefore}"
msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Affiche %{selectedSubjectFilterText} pour le groupe « %{groupName} » et %{projectsCount} du %{createdAfter} au %{createdBefore}"
msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Affiche %{selectedSubjectFilterText} pour le groupe « %{groupName} » du %{createdAfter} au %{createdBefore}"
msgid "ValueStreamAnalytics|Tasks by type"
-msgstr ""
+msgstr "Tâches par type"
msgid "ValueStreamAnalytics|There was an error while fetching value stream analytics %{requestTypeName} data."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la récupération des données d'analyse %{requestTypeName}."
msgid "ValueStreamAnalytics|Total number of deploys to production."
-msgstr ""
+msgstr "Nombre total de déploiements en production."
msgid "ValueStreamAnalytics|Value stream"
-msgstr ""
+msgstr "Chaîne de valeur"
msgid "ValueStreamEvent|Items in stage"
-msgstr ""
+msgstr "Éléments dans l'étape"
msgid "ValueStreamEvent|Stage time (median)"
-msgstr ""
+msgstr "Durée de l'étape (médiane)"
msgid "ValueStreamEvent|Start"
-msgstr ""
+msgstr "Démarrer"
msgid "ValueStreamEvent|Stop"
-msgstr ""
+msgstr "Arrêter"
msgid "ValueStream|The Default Value Stream cannot be deleted"
-msgstr ""
+msgstr "La Chaîne de Valeur par Défaut ne peut pas être supprimée"
msgid "Values that contain the %{codeStart}$%{codeEnd} character can be considered a variable reference and expanded. %{docsLinkStart}Learn more.%{docsLinkEnd}"
-msgstr ""
+msgstr "Les valeurs qui contiennent le caractère %{codeStart}$%{codeEnd} peuvent être considérées comme une référence à une variable et développées. %{docsLinkStart}En savoir plus.%{docsLinkEnd}"
msgid "Variable"
-msgstr ""
+msgstr "Variable"
msgid "Variable will be masked in job logs."
msgstr ""
@@ -43310,13 +44088,13 @@ msgid "Variables"
msgstr ""
msgid "Variables can be:"
-msgstr ""
+msgstr "Les variables peuvent être :"
msgid "Variables store information, like passwords and secret keys, that you can use in job scripts."
-msgstr ""
+msgstr "Les variables stockent des informations, telles que les mots de passe et les clés secrètes, que vous pouvez utiliser dans les scripts de tâche."
msgid "Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables."
-msgstr ""
+msgstr "Les variables stockent des informations, telles que les mots de passe et les clés secrètes, que vous pouvez utiliser dans les scripts de tâche. Tous les projets de l'instance peuvent les utiliser."
msgid "Various container registry settings."
msgstr "Divers paramètres de registre de conteneur."
@@ -43331,25 +44109,25 @@ msgid "Verification status"
msgstr ""
msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity."
-msgstr ""
+msgstr "Pipeline en échec ? Pour garder GitLab à l'abri des pourriels et des abus nous vous demandons de vérifier votre identité."
msgid "VerificationReminder|Until then, shared runners will be unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
-msgstr ""
+msgstr "D'ici-là, les exécuteurs partagés ne seront pas disponibles. %{validateLinkStart}Validez votre compte%{validateLinkEnd} ou %{docsLinkStart}utilisez vos propres exécuteurs%{docsLinkEnd}."
msgid "VerificationReminder|Your account has been validated"
-msgstr ""
+msgstr "Votre compte a été validé"
msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "Vous pourrez maintenant profiter des minutes CI/CD gratuites sur les exécuteurs partagés."
msgid "Verified"
msgstr "Vérifié"
msgid "Verify SAML Configuration"
-msgstr ""
+msgstr "Vérifier la configuration SAML"
msgid "Verify code"
-msgstr ""
+msgstr "Vérifier le code"
msgid "Verify configuration"
msgstr ""
@@ -43358,54 +44136,57 @@ msgid "Version"
msgstr "Version"
msgid "Version %{report_version} for report type %{report_type} has been deprecated, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to parse and ingest this report if valid."
-msgstr ""
+msgstr "La version %{report_version} du type de rapport %{report_type} est obsolète, les versions prises en charge pour ce type de rapport sont : %{supported_schema_versions}. GitLab essaiera d'analyser et d'ingérer ce rapport s'il est valide."
msgid "Version %{report_version} for report type %{report_type} is unsupported, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
-msgstr ""
+msgstr "La version %{report_version} du type rapport de %{report_type} n'est pas prise en charge, les versions prises en charge pour ce type de rapport sont : %{supported_schema_versions}. GitLab essaiera de valider ce rapport avec les versions les plus anciennes prises en charge pour ce type de rapport afin d'afficher toutes les erreurs mais ne l'ingérera pas"
msgid "Version %{versionNumber}"
-msgstr ""
+msgstr "Version %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
-msgstr ""
+msgstr "Version %{versionNumber} (dernière)"
msgid "VersionCheck|Up to date"
-msgstr ""
+msgstr "À jour"
msgid "VersionCheck|Update ASAP"
-msgstr ""
+msgstr "Mettre à jour dès que possible"
msgid "VersionCheck|Update available"
-msgstr ""
+msgstr "Mise à jour disponible"
msgid "VersionCheck|Your GitLab Version"
msgstr "Votre Version de GitLab"
msgid "View Stage: %{title}"
-msgstr ""
+msgstr "Vue de l'Étape : %{title}"
msgid "View alert details at"
msgstr ""
msgid "View alert details."
-msgstr ""
+msgstr "Afficher les détails de l'alerte."
msgid "View all environments."
-msgstr ""
+msgstr "Voir tous les environnements."
msgid "View all groups"
-msgstr ""
+msgstr "Voir tous les groupes"
msgid "View all issues"
msgstr ""
msgid "View all projects"
-msgstr ""
+msgstr "Voir tous les projets"
msgid "View blame"
msgstr ""
msgid "View blame prior to this change"
+msgstr "Voir les informations « blame » antérieures à cette modification"
+
+msgid "View card matches"
msgstr ""
msgid "View chart"
@@ -43426,13 +44207,13 @@ msgid "View details: %{details_url}"
msgstr ""
msgid "View documentation"
-msgstr ""
+msgstr "Voir la documentation"
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
-msgstr "Afficher la liste des épopées"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43464,10 +44245,10 @@ msgid "View incident details at"
msgstr ""
msgid "View incident details."
-msgstr ""
+msgstr "Voir les détails de l'incident."
msgid "View incident issues."
-msgstr ""
+msgstr "Voir les tickets d'incident."
msgid "View issue"
msgstr ""
@@ -43494,36 +44275,36 @@ msgid "View log"
msgstr "Afficher le journal"
msgid "View logs"
-msgstr ""
+msgstr "Voir les journaux"
msgid "View milestones"
-msgstr ""
+msgstr "Voir les jalons"
msgid "View on %{url}"
-msgstr ""
+msgstr "Voir sur %{url}"
msgid "View open merge request"
msgstr "Afficher la demande de fusion"
msgid "View page @ "
-msgstr ""
+msgstr "Voir la page @ "
msgid "View performance dashboard."
msgstr ""
msgid "View project"
-msgstr ""
+msgstr "Voir le projet"
msgid "View project in admin area"
-msgstr ""
+msgstr "Voir le projet dans l'espace d’administration"
msgid "View project labels"
msgstr "Afficher les labels de projet"
msgid "View public GPG key"
msgid_plural "View public GPG keys"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Afficher la clé GPG publique"
+msgstr[1] "Afficher les clés GPG publiques"
msgid "View replaced file @ "
msgstr "Voir le fichier remplacé @ "
@@ -43532,25 +44313,25 @@ msgid "View seat usage"
msgstr ""
msgid "View supported languages and frameworks"
-msgstr ""
+msgstr "Voir les cadres et langages pris en charge"
msgid "View the %{code_open}last_activity_at%{code_close} attribute for %{project_link} using the %{projects_api_link}."
-msgstr ""
+msgstr "Voir l'attribut %{code_open}last_activity_at%{code_close} de %{project_link} en utilisant l'%{projects_api_link}."
msgid "View the documentation"
msgstr "Afficher la documentation"
msgid "View the latest successful deployment to this environment"
-msgstr ""
+msgstr "Voir le dernier déploiement réussi dans cet environnement"
msgid "View the performance dashboard at"
msgstr ""
msgid "View usage details"
-msgstr ""
+msgstr "Afficher les détails d'utilisation"
msgid "View users statistics"
-msgstr ""
+msgstr "Voir les statistiques des utilisateurs"
msgid "Viewed"
msgstr ""
@@ -43559,7 +44340,7 @@ msgid "Viewing commit"
msgstr ""
msgid "Viewing projects and designs data from a primary site is not possible when using a unified URL. Visit the secondary site directly. %{geo_help_url}"
-msgstr ""
+msgstr "L'affichage des projets et des données de conception depuis un site principal n'est pas possible quand une URL unifiée est utilisée. Consultez le site secondaire directement. %{geo_help_url}"
msgid "Violation"
msgstr ""
@@ -43598,7 +44379,7 @@ msgid "VisibilityLevel|Unknown"
msgstr "Inconnu"
msgid "Visual Studio Code (HTTPS)"
-msgstr ""
+msgstr "Visual Studio Code (HTTPS)"
msgid "Visual Studio Code (SSH)"
msgstr ""
@@ -43610,22 +44391,22 @@ msgid "Vulnerabilities over time"
msgstr ""
msgid "Vulnerability"
-msgstr ""
+msgstr "Vulnérabilité"
msgid "Vulnerability Report"
-msgstr ""
+msgstr "Rapport de vulnérabilité"
msgid "Vulnerability remediated. Review before resolving."
-msgstr ""
+msgstr "Remédiation de la vulnérabilité effectuée. À examiner avant de résoudre."
msgid "Vulnerability report"
-msgstr ""
+msgstr "Rapport de vulnérabilité"
msgid "Vulnerability resolved in %{branch}"
-msgstr ""
+msgstr "Vulnérabilité résolue dans %{branch}"
msgid "Vulnerability resolved in the default branch"
-msgstr ""
+msgstr "Vulnérabilité résolue dans la branche par défaut"
msgid "VulnerabilityChart|%{formattedStartDate} to today"
msgstr ""
@@ -43634,64 +44415,64 @@ msgid "VulnerabilityChart|Severity"
msgstr ""
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{statusStart}Confirmée%{statusEnd} %{timeago} par %{user}"
msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
+msgstr "%{statusStart}Détectée%{statusEnd} %{timeago} dans le pipeline %{pipelineLink}"
msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{statusStart}Rejetée%{statusEnd} %{timeago} par %{user}"
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "%{statusStart}Résolue%{statusEnd} %{timeago} par %{user}"
msgid "VulnerabilityManagement|(optional) Include the solution to the vulnerability if available."
-msgstr ""
+msgstr "(facultatif) Inclure la solution à la vulnérabilité si disponible."
msgid "VulnerabilityManagement|A removed or remediated vulnerability"
-msgstr ""
+msgstr "Une vulnérabilité supprimée ou corrigée"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
msgid "VulnerabilityManagement|A verified true-positive vulnerability"
-msgstr ""
+msgstr "Une vulnérabilité confirmée comme vrai positif"
msgid "VulnerabilityManagement|Add vulnerability finding"
-msgstr ""
+msgstr "Ajouter une vulnérabilité découverte"
msgid "VulnerabilityManagement|An unverified non-confirmed finding"
msgstr ""
msgid "VulnerabilityManagement|Change status"
-msgstr ""
+msgstr "Changer l'état"
msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
-msgstr ""
+msgstr "Impossible de traiter %{issueReference} : %{errorMessage}."
msgid "VulnerabilityManagement|Create Jira issue"
-msgstr ""
+msgstr "Créer un ticket Jira"
msgid "VulnerabilityManagement|Enter a name"
-msgstr ""
+msgstr "Entrez un nom"
msgid "VulnerabilityManagement|Enter the CVE or CWE code"
-msgstr ""
+msgstr "Entrez le code CVE ou CWE"
msgid "VulnerabilityManagement|Enter the CVE or CWE identifier URL"
-msgstr ""
+msgstr "Entrez l'URL de l'identifiant CVE ou CWE"
msgid "VulnerabilityManagement|Fetching linked Jira issues"
-msgstr ""
+msgstr "Récupération des tickets Jira liés"
msgid "VulnerabilityManagement|Identifier code and URL are required fields"
msgstr ""
msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
-msgstr ""
+msgstr "Ajoutez manuellement une entrée de vulnérabilité dans le rapport de vulnérabilité."
msgid "VulnerabilityManagement|Name is a required field"
-msgstr ""
+msgstr "Le nom est un champ requis"
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -43703,46 +44484,46 @@ msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
msgid "VulnerabilityManagement|Requires assessment"
-msgstr ""
+msgstr "Nécessite une évaluation"
msgid "VulnerabilityManagement|Select a method"
-msgstr ""
+msgstr "Sélectionnez une méthode"
msgid "VulnerabilityManagement|Select a severity level"
-msgstr ""
+msgstr "Sélectionnez un niveau de gravité"
msgid "VulnerabilityManagement|Select a status"
msgstr ""
msgid "VulnerabilityManagement|Severity is a required field"
-msgstr ""
+msgstr "La gravité est un champ requis"
msgid "VulnerabilityManagement|Something went wrong while creating vulnerability"
-msgstr ""
+msgstr "Une erreur s'est produite lors de la création de la vulnérabilité"
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la suppression du commentaire. Veuillez réessayer plus tard."
msgid "VulnerabilityManagement|Something went wrong while trying to fetch related Jira issues. Please check the %{linkStart}Jira integration settings%{linkEnd} and try again."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la tentative de récupération des tickets associés à Jira. Veuillez vérifier les %{linkStart}paramètres d'intégration Jira%{linkEnd} et réessayer."
msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la mise à jour de la vulnérabilité. Veuillez réessayer plus tard."
msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la tentative de récupération de l’historique des vulnérabilités. Veuillez réessayer plus tard."
msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de l’enregistrement du commentaire. Veuillez réessayer plus tard."
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la tentative de dissociation du ticket. Veuillez réessayer plus tard."
msgid "VulnerabilityManagement|Something went wrong, could not get user."
-msgstr ""
+msgstr "Une erreur s’est produite, impossible d’obtenir l’utilisateur."
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
-msgstr ""
+msgstr "Une erreur s’est produite, impossible de mettre à jour l’état de la vulnérabilité."
msgid "VulnerabilityManagement|Status is a required field"
msgstr ""
@@ -43751,121 +44532,124 @@ msgid "VulnerabilityManagement|Submit vulnerability"
msgstr ""
msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
-msgstr ""
+msgstr "Résumé, description détaillée, étapes de reproductibilité, etc."
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
-msgstr ""
+msgstr "Nom ou type de la vulnérabilité : Ex : Script intersites"
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
msgid "VulnerabilityManagement|invalid issue link or ID"
-msgstr ""
+msgstr "ID ou lien de ticket non valide"
msgid "VulnerabilityStatusTypes|All statuses"
-msgstr ""
+msgstr "Tous les états"
msgid "VulnerabilityStatusTypes|Confirmed"
-msgstr ""
+msgstr "Confirmé"
msgid "VulnerabilityStatusTypes|Dismissed"
-msgstr ""
+msgstr "Rejeté"
msgid "VulnerabilityStatusTypes|Needs triage"
-msgstr ""
+msgstr "Nécessite un triage"
msgid "VulnerabilityStatusTypes|Resolved"
-msgstr ""
+msgstr "Résolu"
msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
-msgstr ""
+msgstr "%{scannerName} (version %{scannerVersion})"
msgid "Vulnerability|Activity"
-msgstr ""
+msgstr "Activité"
msgid "Vulnerability|Actual Response"
-msgstr ""
+msgstr "Véritable réponse"
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
-msgstr ""
+msgstr "La véritable réponse reçue est celle qui a été réceptionnée au moment où l'erreur a été détectée"
msgid "Vulnerability|Add another identifier"
-msgstr ""
+msgstr "Ajouter un autre identifiant"
msgid "Vulnerability|Additional Info"
-msgstr ""
+msgstr "Infos supplémentaires"
msgid "Vulnerability|Bug Bounty"
-msgstr ""
+msgstr "Prime aux Bogues"
msgid "Vulnerability|CVSS v3"
-msgstr ""
+msgstr "CVSS v3"
msgid "Vulnerability|Class"
msgstr "Classe"
msgid "Vulnerability|Cluster"
-msgstr ""
+msgstr "Grappe de serveurs"
msgid "Vulnerability|Code Review"
-msgstr ""
+msgstr "Revue de Code"
msgid "Vulnerability|Comments"
-msgstr ""
+msgstr "Commentaires"
msgid "Vulnerability|Crash address"
-msgstr ""
+msgstr "Adresse du plantage"
msgid "Vulnerability|Crash state"
-msgstr ""
+msgstr "État du plantage"
msgid "Vulnerability|Crash type"
-msgstr ""
+msgstr "Type du plantage"
msgid "Vulnerability|Description"
msgstr "Description"
msgid "Vulnerability|Details"
-msgstr ""
+msgstr "Détails"
msgid "Vulnerability|Detected"
-msgstr ""
+msgstr "Détectée(s)"
msgid "Vulnerability|Detection method"
-msgstr ""
+msgstr "Méthode de détection"
msgid "Vulnerability|Download"
-msgstr ""
+msgstr "Télécharger"
msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
-msgstr ""
+msgstr "Saisissez les entrées CVE ou CWE associées pour cette vulnérabilité."
msgid "Vulnerability|Evidence"
msgstr ""
msgid "Vulnerability|External Security Report"
-msgstr ""
+msgstr "Rapport de Sécurité Externe"
msgid "Vulnerability|False positive detected"
-msgstr ""
+msgstr "Faux positif détecté"
msgid "Vulnerability|File"
msgstr "Fichier"
+msgid "Vulnerability|File:"
+msgstr "Fichier :"
+
msgid "Vulnerability|GitLab Security Report"
-msgstr ""
+msgstr "Rapport de Sécurité de GitLab"
msgid "Vulnerability|Identifier"
-msgstr ""
+msgstr "Identifiant"
msgid "Vulnerability|Identifier URL"
-msgstr ""
+msgstr "URL de l'identifiant"
msgid "Vulnerability|Identifier code"
-msgstr ""
+msgstr "Code identifiant"
msgid "Vulnerability|Identifiers"
msgstr "Identifiants"
@@ -43874,16 +44658,16 @@ msgid "Vulnerability|Image"
msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
-msgstr ""
-
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
+msgstr "Informations relatives à la manière dont la vulnérabilité a été découverte et à son impact sur le système."
msgid "Vulnerability|Links"
msgstr "Liens"
+msgid "Vulnerability|Location"
+msgstr "Emplacement :"
+
msgid "Vulnerability|Method"
-msgstr ""
+msgstr "Méthode"
msgid "Vulnerability|Namespace"
msgstr ""
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Projet"
+msgid "Vulnerability|Project:"
+msgstr "Projet :"
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43901,46 +44688,55 @@ msgid "Vulnerability|Request"
msgstr ""
msgid "Vulnerability|Request/Response"
-msgstr ""
+msgstr "Requête/Réponse"
msgid "Vulnerability|Scanner Provider"
-msgstr ""
+msgstr "Fournisseur de scanner"
msgid "Vulnerability|Security Audit"
-msgstr ""
+msgstr "Audit de Sécurité"
msgid "Vulnerability|Select a severity"
-msgstr ""
+msgstr "Sélectionnez une gravité"
msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
-msgstr ""
+msgstr "Définissez l'état de la vulnérabilité découverte en fonction des informations dont vous disposez."
msgid "Vulnerability|Severity"
msgstr "Gravité"
+msgid "Vulnerability|Severity:"
+msgstr "Gravité :"
+
msgid "Vulnerability|Status"
-msgstr ""
+msgstr "État"
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
-msgstr ""
+msgstr "Le scanner a déterminé que cette vulnérabilité est un faux positif. Vérifiez cette évaluation avant d'en modifier l'état. %{linkStart}En savoir plus sur la détection des faux positifs.%{linkEnd}"
msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
-msgstr ""
+msgstr "La réponse non modifiée est la réponse originale qui n'a subit aucune altération suite à la requête"
msgid "Vulnerability|Tool"
+msgstr "Outil"
+
+msgid "Vulnerability|Tool:"
msgstr ""
msgid "Vulnerability|Training"
-msgstr ""
+msgstr "Formation"
msgid "Vulnerability|Training not available for this vulnerability."
-msgstr ""
+msgstr "Formation non disponible pour cette vulnérabilité."
msgid "Vulnerability|Unmodified Response"
-msgstr ""
+msgstr "Réponse non modifiée"
msgid "Vulnerability|View training"
-msgstr ""
+msgstr "Voir la formation"
+
+msgid "WARNING:"
+msgstr "AVERTISSEMENT :"
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43949,7 +44745,7 @@ msgid "Wait for the file to load to copy its contents"
msgstr ""
msgid "Waiting for approval"
-msgstr ""
+msgstr "En attente d’approbation"
msgid "Waiting for merge (open and assigned)"
msgstr ""
@@ -43961,28 +44757,28 @@ msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
msgid "Warning"
-msgstr ""
+msgstr "Avertissement"
msgid "Warning:"
-msgstr ""
+msgstr "Avertissement :"
msgid "Warning: Displaying this diagram might cause performance issues on this page."
-msgstr ""
+msgstr "Avertissement : L'affichage de ce diagramme peut entraîner des problèmes de performances sur cette page."
msgid "Warning: Synchronizing LDAP removes direct members' access."
-msgstr ""
+msgstr "Avertissement : La synchronisation LDAP supprime l'accès des membres directs."
msgid "Watch how"
msgstr ""
msgid "We also use email for avatar detection if no avatar is uploaded."
-msgstr ""
+msgstr "Nous utilisons aussi l'adresse de courriel pour la détection d'avatar si aucun n'est téléversé."
msgid "We are currently unable to fetch data for the pipeline header."
-msgstr ""
+msgstr "Il est actuellement impossible de récupérer les données de l'en-tête de pipeline."
msgid "We are currently unable to fetch data for this graph."
-msgstr ""
+msgstr "Nous sommes actuellement dans l'impossibilité de récupérer les données de ce graphe."
msgid "We could not determine the path to remove the epic"
msgstr ""
@@ -44000,9 +44796,15 @@ msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
msgstr ""
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
-msgstr ""
+msgstr "Nous n'avons pas pu atteindre le serveur Prometheus. Soit le serveur n'existe plus, soit les détails de la configuration doivent être mis à jour."
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
+msgstr "Nous avons créé un projet bac à sable pour vous aider à apprendre les bases de GitLab. Vous serez guidé(e) par des tickets dans un tableau de tickets. Vous pouvez les suivre à votre propre rythme."
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
msgstr ""
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
@@ -44015,49 +44817,49 @@ msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
-msgstr ""
+msgstr "Nous avons un retour de votre appareil. Vous avez été authentifié."
msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
-msgstr ""
+msgstr "Nous vous invitons à %{featureLinkStart}faire une demande de fonctionnalité%{featureLinkEnd}, %{bugLinkStart}signaler un bogue%{bugLinkEnd} ou %{feedbackLinkStart}partager vos réactions%{feedbackLinkEnd}"
msgid "We recommend a work email address."
msgstr ""
msgid "We recommend leaving all SAST analyzers enabled"
-msgstr ""
+msgstr "Nous vous recommandons de laisser tous les analyseurs SAST activés"
msgid "We recommend that you buy additional Pipeline minutes to avoid any interruption of service."
-msgstr ""
+msgstr "Nous vous recommandons d'acheter des minutes de pipeline supplémentaires pour éviter une interruption de service."
msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
-msgstr ""
+msgstr "Nous vous recommandons d'acheter des minutes de pipeline supplémentaires pour revenir à un service normal."
msgid "We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device."
-msgstr ""
+msgstr "Nous vous recommandons d'utiliser des applications d'authentification basées sur le cloud qui peuvent restaurer l'accès si vous perdez votre périphérique matériel."
msgid "We sent you an email with reset password instructions"
msgstr ""
msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
-msgstr ""
+msgstr "Nous avons essayé de renouveler automatiquement votre abonnement pour %{strong}%{namespace_name}%{strong_close} le %{expires_on} mais une erreur s'est produite et il a donc été rétrogradé vers le forfait gratuit. Ne vous inquiétez pas, vos données sont en sécurité. Nous vous suggérons de vérifier votre mode de paiement et de contacter notre équipe d'assistance (%{support_link}). Ils se feront un plaisir de vous accompagner pour le renouvellement de votre abonnement."
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Nous voulons nous assurer qu’il s’agit bien de vous, merci de confirmer que vous n’êtes pas un robot."
msgid "We want to let you know %{username} has been banned from %{scope} due to them downloading more than %{max_project_downloads} project repositories within %{within_minutes} minutes."
-msgstr ""
+msgstr "Nous voulons vous informer que %{username} a été banni de %{scope} car il a téléchargé plus de %{max_project_downloads} dépôts de projets en l'espace de %{within_minutes} minutes."
msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
-msgstr ""
+msgstr "Nous informerons %{inviter} que vous avez refusé leur invitation à rejoindre GitLab. Vous ne recevrez plus de rappels."
msgid "We would like to inform you that your subscription GitLab Enterprise Edition %{plan_name} is nearing its user limit. You have %{active_user_count} active users, which is almost at the user limit of %{maximum_user_count}."
-msgstr ""
+msgstr "Nous tenons à vous informer que votre abonnement GitLab Édition Entreprise %{plan_name} approche de la limite de son nombre d'utilisateurs. Vous avez %{active_user_count} utilisateurs actifs, ce qui est presque la limite qui est de %{maximum_user_count}."
msgid "We'll continuously validate your pipeline configuration. The validation results will appear here."
-msgstr ""
+msgstr "Nous validerons votre configuration de pipeline en continu. Les résultats de validation apparaîtront ici."
msgid "We'll use this to help surface the right features and information to you."
-msgstr ""
+msgstr "Cela contribuera à nous permettre de vous présenter des fonctionnalités et informations personnalisées."
msgid "We're experiencing difficulties and this tab content is currently unavailable."
msgstr ""
@@ -44066,10 +44868,10 @@ msgid "We've detected some unusual activity"
msgstr ""
msgid "We've detected unusual activity"
-msgstr ""
+msgstr "Nous avons détecté une activité inhabituelle"
msgid "We've found no vulnerabilities"
-msgstr ""
+msgstr "Nous n'avons trouvé aucune vulnérabilité"
msgid "Web IDE"
msgstr "EDI Web"
@@ -44081,73 +44883,73 @@ msgid "Web terminal"
msgstr "Terminal Web"
msgid "WebAuthn Devices (%{length})"
-msgstr ""
+msgstr "Appareils WebAuthn (%{length})"
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
-msgstr ""
+msgstr "WebAuthn ne fonctionne qu'avec les sites Web accessibles en HTTPS. Contactez votre administrateur pour plus de détails."
msgid "WebIDE|Fork project"
-msgstr ""
+msgstr "Créer un projet divergent"
msgid "WebIDE|Go to fork"
-msgstr ""
+msgstr "Aller au projet divergent"
msgid "WebIDE|Merge request"
-msgstr ""
+msgstr "Demande de fusion"
msgid "WebIDE|Quickly and easily edit multiple files in your project."
-msgstr ""
+msgstr "Modifier rapidement et facilement plusieurs fichiers de votre projet."
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
-msgstr ""
+msgstr "Modifier rapidement et facilement plusieurs fichiers de votre projet. Appuyez sur . pour ouvrir\n"
msgid "WebIDE|This project does not accept unsigned commits."
-msgstr ""
+msgstr "Ce projet n’accepte pas les commits non signés."
msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
-msgstr ""
+msgstr "Ce projet n'accepte pas les commits non signés. Vous ne pouvez pas valider de modifications dans l'EDI Web."
msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "Vous ne pouvez pas directement modifier les fichiers de ce projet. Créez une divergence, puis proposez une demande de fusion avec vos modifications."
msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
-msgstr ""
+msgstr "Vous ne pouvez pas directement modifier les fichiers de ce projet. Allez sur votre projet divergent puis proposez une demande de fusion avec vos modifications."
msgid "WebIDE|You need permission to edit files directly in this project."
-msgstr ""
+msgstr "Vous avez besoin d'une autorisation pour modifier des fichiers directement dans ce projet."
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
-msgstr ""
+msgstr "Envoyer des notifications sur les événements du projet vers Webex Teams."
msgid "WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}"
-msgstr ""
+msgstr "Envoyer des notifications sur les événements du projet dans une conversation Webex Teams. %{docs_link}"
msgid "WebexTeamsService|Webex Teams"
-msgstr ""
+msgstr "Webex Teams"
msgid "Webhook"
-msgstr ""
+msgstr "Webhook"
msgid "Webhook Logs"
-msgstr ""
+msgstr "Journaux Webhook"
msgid "Webhook Settings"
-msgstr ""
+msgstr "Paramètres Webhook"
msgid "Webhook events will be displayed here."
-msgstr ""
+msgstr "Les événements de crochet web seront affichés ici."
msgid "Webhook:"
-msgstr ""
+msgstr "Point d'ancrage web :"
msgid "Webhooks"
msgstr ""
msgid "Webhooks Help"
-msgstr ""
+msgstr "Aide sur les Webhooks"
msgid "Webhooks|A comment is added to a confidential issue."
-msgstr ""
+msgstr "Un commentaire est ajouté à un ticket confidentiel."
msgid "Webhooks|A comment is added to an issue or merge request."
msgstr ""
@@ -44156,37 +44958,37 @@ msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr "Un ticket confidentiel est créé, mis à jour, fermé ou rouvert."
msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
-msgstr ""
+msgstr "Un déploiement commence, finit, échoue ou est annulé."
msgid "Webhooks|A feature flag is turned on or off."
-msgstr ""
+msgstr "Un indicateur de fonctionnalité est activé ou désactivé."
msgid "Webhooks|A group member is created, updated, or removed."
-msgstr ""
+msgstr "Un membre de groupe est créé, mis à jour ou supprimé."
msgid "Webhooks|A job's status changes."
-msgstr ""
+msgstr "L'état d'une tâche change."
msgid "Webhooks|A merge request is created, updated, or merged."
-msgstr ""
+msgstr "Une demande de fusion est créée, mise à jour ou fusionnée."
msgid "Webhooks|A new tag is pushed to the repository."
-msgstr ""
+msgstr "Une nouvelle étiquette est poussée vers le dépôt."
msgid "Webhooks|A pipeline's status changes."
-msgstr ""
+msgstr "L'état d'un pipeline change."
msgid "Webhooks|A release is created or updated."
-msgstr ""
+msgstr "Une version est créée ou mise à jour."
msgid "Webhooks|A subgroup is created or removed."
-msgstr ""
+msgstr "Un sous-groupe est créé ou supprimé."
msgid "Webhooks|A webhook in this project was automatically disabled after being retried multiple times."
-msgstr ""
+msgstr "Un webhook de ce projet a été désactivé automatiquement après avoir été retenté plusieurs fois."
msgid "Webhooks|A wiki page is created or updated."
-msgstr ""
+msgstr "Une page wiki est créée ou mise à jour."
msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr "Un ticket est créé, mis à jour, fermé ou rouvert."
@@ -44198,25 +45000,28 @@ msgid "Webhooks|Are you sure you want to delete this project hook?"
msgstr ""
msgid "Webhooks|Are you sure you want to delete this webhook?"
-msgstr ""
+msgstr "Êtes-vous sûr(e) de vouloir supprimer ce webhook ?"
msgid "Webhooks|Comments"
-msgstr ""
+msgstr "Commentaires"
msgid "Webhooks|Confidential comments"
-msgstr ""
+msgstr "Commentaires confidentiels"
msgid "Webhooks|Confidential issues events"
-msgstr ""
+msgstr "Événements de tickets confidentiels"
msgid "Webhooks|Delete webhook"
-msgstr ""
+msgstr "Supprimer le webhook"
msgid "Webhooks|Deployment events"
+msgstr "Événements de déploiement"
+
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
msgstr ""
msgid "Webhooks|Enable SSL verification"
-msgstr ""
+msgstr "Activer la vérification SSL"
msgid "Webhooks|Failed to connect"
msgstr ""
@@ -44225,97 +45030,112 @@ msgid "Webhooks|Fails to connect"
msgstr ""
msgid "Webhooks|Feature flag events"
-msgstr ""
+msgstr "Événements d'indicateur de fonctionnalité"
msgid "Webhooks|Go to webhooks"
+msgstr "Aller aux webhooks"
+
+msgid "Webhooks|How it looks in the UI"
msgstr ""
msgid "Webhooks|Issues events"
-msgstr ""
+msgstr "Événements des tickets"
msgid "Webhooks|Job events"
+msgstr "Événements des tâches"
+
+msgid "Webhooks|Mask portions of URL"
msgstr ""
msgid "Webhooks|Member events"
-msgstr ""
+msgstr "Événements des membres"
msgid "Webhooks|Merge request events"
-msgstr ""
+msgstr "Événements de demande de fusion"
msgid "Webhooks|Pipeline events"
-msgstr ""
+msgstr "Événements des pipelines"
msgid "Webhooks|Push events"
-msgstr ""
+msgstr "Événements de poussées"
msgid "Webhooks|Push to the repository."
-msgstr ""
+msgstr "Poussée vers le dépôt."
msgid "Webhooks|Releases events"
-msgstr ""
+msgstr "Événements de Versions"
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "Vérification SSL"
msgid "Webhooks|Secret token"
+msgstr "Jeton secret"
+
+msgid "Webhooks|Sensitive portion of URL"
msgstr ""
-msgid "Webhooks|Subgroup events"
+msgid "Webhooks|Show full URL"
msgstr ""
+msgid "Webhooks|Subgroup events"
+msgstr "Événements de sous-groupe"
+
msgid "Webhooks|Tag push events"
-msgstr ""
+msgstr "Événements de poussée d'étiquette"
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 ""
+msgstr "Le point d'ancrage Wab %{help_link_start}n'a pas réussi à se connecter%{help_link_end}, et réessayera dans %{retry_time}. Pour le réactiver, vérifiez les détails de l'erreur dans les %{strong_start}Événements récents%{strong_end} puis testez vos paramètres ci-dessous."
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 ""
+msgstr "Le point d'ancrage Web n'a pas réussi à se connecter et est désactivé. Pour le réactiver, vérifiez les détails de l'erreur dans les %{strong_start}Événements récents%{strong_end} puis testez vos paramètres ci-dessous."
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 ""
+msgstr "Le point d'ancrage Web a été déclenché plus de %{limit} fois par minute et est maintenant désactivé. Pour le réactiver, corrigez les problèmes affichés dans les %{strong_start}Événements récents%{strong_end} puis retestez vos paramètres. %{support_link_start}Contactez le Support%{support_link_end} si vous avez besoin d'aide pour réactiver votre point d'ancrage Web."
msgid "Webhooks|Trigger"
-msgstr ""
+msgstr "Déclencheur"
msgid "Webhooks|URL"
-msgstr ""
+msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
+msgstr "L'URL doit être en encodage-pourcent si elle contient un ou plusieurs caractères spéciaux."
+
+msgid "Webhooks|URL preview"
msgstr ""
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
-msgstr ""
+msgstr "Utilisé pour valider les charges utiles reçues. Envoyé avec la requête dans l'en-tête %{code_start}HTTP X-Gitlab-Token%{code_end}."
msgid "Webhooks|Webhook disabled"
-msgstr ""
+msgstr "Webhook désactivé"
msgid "Webhooks|Webhook failed to connect"
-msgstr ""
+msgstr "Le point d'ancrage Web n'a pas réussi à se connecter"
msgid "Webhooks|Webhook fails to connect"
-msgstr ""
+msgstr "Le point d'ancrage Web n'arrive pas à se connecter"
msgid "Webhooks|Webhook was automatically disabled"
-msgstr ""
+msgstr "Le point d'ancrage Web a été automatiquement désactivé"
msgid "Webhooks|Wiki page events"
-msgstr ""
+msgstr "Événements des Pages Wiki"
msgid "Website"
-msgstr ""
+msgstr "Site Web"
msgid "Website:"
-msgstr ""
+msgstr "Site web :"
msgid "Wed"
-msgstr ""
+msgstr "Mer"
msgid "Wednesday"
msgstr ""
msgid "Weekday"
-msgstr ""
+msgstr "Jour de la semaine"
msgid "Weeks"
msgstr "Semaines"
@@ -44333,70 +45153,70 @@ msgid "Welcome to GitLab"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
-msgstr ""
+msgstr "Bienvenue sur GitLab, %{first_name} !"
msgid "Welcome to GitLab,%{br_tag}%{name}!"
-msgstr ""
+msgstr "Bienvenue sur GitLab,%{br_tag}%{name} !"
msgid "Welcome, %{name}!"
-msgstr ""
+msgstr "Bienvenue, %{name} !"
msgid "What are CI/CD minutes?"
-msgstr ""
+msgstr "Que sont les minutes CI/CD ?"
msgid "What are group audit events?"
-msgstr ""
+msgstr "Que sont les événements d'audit de groupe ?"
msgid "What are instance audit events?"
-msgstr ""
+msgstr "Que sont les événements d'audit d'instance ?"
msgid "What are project audit events?"
-msgstr ""
+msgstr "Que sont les événements d'audit de projet ?"
msgid "What are some examples?"
msgstr ""
msgid "What does the setting affect?"
-msgstr ""
+msgstr "Qu'est-ce que le réglage affecte ?"
msgid "What does this command do?"
-msgstr ""
+msgstr "Que fait cette commande ?"
msgid "What is GitLab Runner?"
msgstr ""
msgid "What is Markdown?"
-msgstr ""
+msgstr "Qu'est-ce que Markdown ?"
msgid "What is listed here?"
msgstr ""
msgid "What is repository mirroring?"
-msgstr ""
+msgstr "Qu'est-ce que la mise en miroir de dépôt ?"
msgid "What is squashing?"
-msgstr ""
+msgstr "Que signifie « squasher » ?"
msgid "What templates can I create?"
-msgstr ""
+msgstr "Quels modèles puis-je créer ?"
msgid "What will you use this group for?"
-msgstr ""
+msgstr "À quoi vous servira ce groupe ?"
msgid "What would you like to do?"
-msgstr ""
+msgstr "Que souhaitez-vous faire ?"
msgid "What's new"
msgstr "Nouveautés"
msgid "When a deployment job is successful, skip older deployment jobs that are still pending."
-msgstr ""
+msgstr "Quand une tâche de déploiement réussit, ignorer celles plus anciennes qui sont toujours en attente."
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 ""
+msgstr "Lorsque cette option est activée, les clés SSH sans date d'expiration ou avec une date d'expiration invalide ne sont plus acceptées. Laisser vide pour aucune limite."
msgid "When enabled, cleanup polices execute faster but put more load on Redis."
msgstr ""
@@ -44408,7 +45228,7 @@ msgid "When enabled, job logs are collected by Datadog and displayed along with
msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
-msgstr ""
+msgstr "Quand des demandes de fusion et des commits sont fermés sur la branche par défaut, tous les tickets auxquels ils font référence sont également clôturés."
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
@@ -44416,27 +45236,27 @@ msgstr[0] ""
msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
+msgstr "Lors de l'utilisation des protocoles %{code_open}http://%{code_close} ou %{code_open}https://%{code_close}, veuillez fournir l'URL exacte du dépôt. Les redirections HTTP ne seront pas suivies."
msgid "When you transfer your project to a group, you can easily manage multiple projects, view usage quotas for storage, pipeline minutes, and users, and start a trial or upgrade to a paid tier."
msgstr ""
msgid "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seat. %{free_user_limit} seat will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
msgid_plural "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seats. %{free_user_limit} seats will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "À la fin de votre période d'essai, vous basculerez sur l'édition Gratuite qui est limitée à %{free_user_limit} siège. %{free_user_limit} siège restera actif, et les membres qui n'occupent pas de siège passeront à l'%{link_start}état Hors limite%{link_end} et perdront l'accès à ce groupe."
+msgstr[1] "À la fin de votre période d'essai, vous basculerez sur l'édition Gratuite qui est limitée à %{free_user_limit} sièges. %{free_user_limit} sièges resteront actifs, et les membres qui n'occupent pas de siège passeront à l'%{link_start}état Hors limite%{link_end} et perdront l'accès à ce groupe."
msgid "When:"
msgstr ""
msgid "Which API requests are affected?"
-msgstr ""
+msgstr "Quelles requêtes d'API sont affectées ?"
msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
-msgstr ""
+msgstr "Bien qu'il soit rare de ne pas avoir de vulnérabilités, cela peut se produire. Dans tous les cas, nous vous demandons de bien vouloir revérifier vos paramètres pour vous assurer que vous avez correctement configuré votre tableau de bord."
msgid "Who can approve?"
-msgstr ""
+msgstr "Qui peut approuver ?"
msgid "Who can see this group?"
msgstr "Qui peut voir ce groupe ?"
@@ -44445,16 +45265,16 @@ msgid "Who will be able to see this group?"
msgstr "Qui sera en mesure de voir ce groupe ?"
msgid "Who will be using GitLab?"
-msgstr ""
+msgstr "Qui utilisera GitLab ?"
msgid "Who will be using this GitLab subscription?"
-msgstr ""
+msgstr "Qui utilisera cet abonnement GitLab ?"
msgid "Who will be using this GitLab trial?"
-msgstr ""
+msgstr "Qui utilisera cet essai GitLab ?"
msgid "Who will be using this group?"
-msgstr ""
+msgstr "Qui utilisera ce groupe ?"
msgid "Why are you signing up? (optional)"
msgstr ""
@@ -44462,23 +45282,17 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
msgid "Wiki page was successfully created."
-msgstr ""
+msgstr "La page wiki a été créée avec succès."
msgid "Wiki page was successfully deleted."
-msgstr ""
+msgstr "La page wiki a été supprimée avec succès."
msgid "Wiki page was successfully updated."
-msgstr ""
+msgstr "La page wiki a été mise à jour avec succès."
msgid "WikiClone|Clone your wiki"
msgstr "Clonez votre wiki"
@@ -44508,49 +45322,49 @@ msgid "WikiEmptyIssueMessage|issue tracker"
msgstr "Suivi d’incidents"
msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
-msgstr ""
+msgstr "Vous avez déjà un wiki Confluence ? Utilisez-le à la place."
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 "Un wiki est l'endroit où vous pouvez stocker tous les détails concernant votre groupe. Cela peut inclure pourquoi vous l'avez créé, ses principes, comment l'utiliser, et ainsi de suite."
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 "Un wiki est un endroit où vous pouvez stocker tous les détails concernant votre projet. Ceci peut inclure sa raison d’être, ses principes, comment l’utiliser, etc."
msgid "WikiEmpty|Confluence is enabled"
-msgstr ""
+msgstr "Confluence est activé"
msgid "WikiEmpty|Create your first page"
msgstr "Créer votre première page"
msgid "WikiEmpty|Enable the Confluence Wiki integration"
-msgstr ""
+msgstr "Activer l’intégration du Wiki Confluence"
msgid "WikiEmpty|Go to Confluence"
-msgstr ""
+msgstr "Aller à Confluence"
msgid "WikiEmpty|Suggest wiki improvement"
msgstr "Suggérer une amélioration du wiki"
msgid "WikiEmpty|The wiki lets you write documentation for your group"
-msgstr ""
+msgstr "Le wiki vous permet d'écrire de la documentation pour votre groupe"
msgid "WikiEmpty|The wiki lets you write documentation for your project"
msgstr "Le wiki vous permet d’écrire la documentation de votre projet"
msgid "WikiEmpty|This group has no wiki pages"
-msgstr ""
+msgstr "Ce groupe n’a aucune page wiki"
msgid "WikiEmpty|This project has no wiki pages"
msgstr "Ce projet n’a pas de pages wiki"
msgid "WikiEmpty|You must be a group member in order to add wiki pages."
-msgstr ""
+msgstr "Vous devez être un membre du groupe pour ajouter des pages wiki."
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
msgstr "Vous devez être un membre du projet pour ajouter des pages wiki."
msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
-msgstr ""
+msgstr "Vous avez activé l’intégration de l’espace de travail Confluence. Votre wiki sera visible directement dans Confluence. Nous nous efforçons d'intégrer Confluence de manière plus transparente dans GitLab. Si vous souhaitez rester à jour, suivez notre %{wiki_confluence_epic_link_start}épopée Confluence%{wiki_confluence_epic_link_end}."
msgid "WikiHistoricalPage|This is an old version of this page."
msgstr "Il s’agit d’une ancienne version de la page."
@@ -44574,55 +45388,55 @@ msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr "Supprimer la page %{pageTitle} ?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
-msgstr ""
+msgstr "Une personne a modifié la page en même temps que vous. Veuillez vérifier %{wikiLinkStart}la page%{wikiLinkEnd} et vous assurer que vos modifications n'ont pas supprimé accidentellement les siennes."
msgid "WikiPage|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "WikiPage|Commit message"
-msgstr ""
+msgstr "Message de commit"
msgid "WikiPage|Content"
-msgstr ""
+msgstr "Contenu"
msgid "WikiPage|Create %{pageTitle}"
-msgstr ""
+msgstr "Création de %{pageTitle}"
msgid "WikiPage|Create page"
-msgstr ""
+msgstr "Créer une page"
msgid "WikiPage|Format"
-msgstr ""
+msgstr "Format"
msgid "WikiPage|Learn more."
-msgstr ""
+msgstr "En savoir plus."
msgid "WikiPage|Page title"
-msgstr ""
+msgstr "Titre de la page"
msgid "WikiPage|Save changes"
-msgstr ""
+msgstr "Enregistrer les modifications"
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr ""
+msgstr "Astuce : Vous pouvez déplacer cette page en ajoutant le chemin d'accès devant le titre."
msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr ""
+msgstr "Astuce : Vous pouvez spécifier le chemin d’accès complet du nouveau fichier. Tous les répertoires manquants seront automatiquement créés."
msgid "WikiPage|Title"
-msgstr ""
+msgstr "Titre"
msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
-msgstr ""
+msgstr "Pour créer un lien vers une (nouvelle) page, tapez simplement %{linkExample}. Davantage d’exemples sont présents dans la %{linkStart}documentation%{linkEnd}."
msgid "WikiPage|Update %{pageTitle}"
-msgstr ""
+msgstr "Mise à jour de %{pageTitle}"
msgid "WikiPage|Write your content or drag files here…"
msgstr "Écrivez du contenu ou faites glisser des fichiers ici…"
msgid "Wikis"
-msgstr ""
+msgstr "Wikis"
msgid "Wiki|Create New Page"
msgstr ""
@@ -44646,13 +45460,13 @@ msgid "Wiki|Pages"
msgstr "Pages"
msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
-msgstr ""
+msgstr "Le chargement de la barre latérale a échoué. Vous pouvez recharger la page pour réessayer."
msgid "Wiki|Title"
msgstr ""
msgid "Wiki|View All Pages"
-msgstr ""
+msgstr "Voir toutes les pages"
msgid "Wiki|Wiki Pages"
msgstr "Pages du Wiki"
@@ -44661,16 +45475,16 @@ msgid "Will be created"
msgstr ""
msgid "Will be mapped to"
-msgstr ""
+msgstr "Sera associé à"
msgid "Will deploy to"
msgstr ""
msgid "Wireframe"
-msgstr ""
+msgstr "Maquette"
msgid "With requirements, you can set criteria to check your products against."
-msgstr ""
+msgstr "Avec les exigences, vous pouvez définir des critères auxquels confronter vos produits."
msgid "With test cases, you can define conditions for your project to meet in determining quality"
msgstr ""
@@ -44679,7 +45493,7 @@ msgid "Withdraw Access Request"
msgstr "Retirer la demande d’accès"
msgid "Won't fix / Accept risk"
-msgstr ""
+msgstr "Ne sera pas corrigé / Accepter le risque"
msgid "Work in progress (open and unassigned)"
msgstr ""
@@ -44688,90 +45502,102 @@ msgid "Work in progress Limit"
msgstr ""
msgid "WorkItem|%{workItemType} deleted"
-msgstr ""
+msgstr "%{workItemType} supprimé"
msgid "WorkItem|Add"
-msgstr ""
+msgstr "Ajouter"
msgid "WorkItem|Add a title"
-msgstr ""
+msgstr "Ajouter un titre"
msgid "WorkItem|Add assignee"
-msgstr ""
+msgstr "Ajouter un assigné"
msgid "WorkItem|Add assignees"
-msgstr ""
+msgstr "Ajouter des assignés"
+
+msgid "WorkItem|Add due date"
+msgstr "Ajouter une date d'échéance"
+
+msgid "WorkItem|Add start date"
+msgstr "Ajouter une date de début"
msgid "WorkItem|Add task"
msgstr "Ajouter une tâche"
msgid "WorkItem|Are you sure you want to cancel editing?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir annuler la modification ?"
msgid "WorkItem|Are you sure you want to delete the %{workItemType}? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Assigné"
+msgstr[1] "Assignés"
msgid "WorkItem|Cancel"
-msgstr ""
+msgstr "Annuler"
msgid "WorkItem|Child removed"
-msgstr ""
+msgstr "Enfant supprimé"
msgid "WorkItem|Closed"
msgstr "Fermé"
msgid "WorkItem|Collapse tasks"
-msgstr ""
+msgstr "Réduire les tâches"
msgid "WorkItem|Create task"
-msgstr ""
+msgstr "Créer une tâche"
msgid "WorkItem|Create work item"
-msgstr ""
+msgstr "Créer un élément de travail"
+
+msgid "WorkItem|Dates"
+msgstr "Dates"
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr "Date d'échéance"
+
msgid "WorkItem|Expand tasks"
-msgstr ""
+msgstr "Étendre les tâches"
msgid "WorkItem|Incident"
-msgstr ""
+msgstr "Incident"
msgid "WorkItem|Introducing tasks"
-msgstr ""
+msgstr "Introduction aux tâches"
msgid "WorkItem|Issue"
-msgstr ""
+msgstr "Ticket"
msgid "WorkItem|Learn about tasks."
msgstr ""
msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
-msgstr ""
+msgstr "Aucune tâche n’est actuellement assignée. Utilisez des tâches pour scinder ce ticket en parties plus petites."
msgid "WorkItem|None"
-msgstr ""
+msgstr "Aucun"
msgid "WorkItem|Only project members with at least the Reporter role, the author, and assignees can view or be notified about this task."
-msgstr ""
+msgstr "Seuls l'auteur, les assignés et les membres du projet ayant au moins le rôle de Rapporteur peuvent voir cette tâche ou recevoir des notifications la concernant."
msgid "WorkItem|Open"
-msgstr ""
+msgstr "Ouvrir"
msgid "WorkItem|Remove"
-msgstr ""
+msgstr "Supprimer"
msgid "WorkItem|Requirements"
msgstr ""
msgid "WorkItem|Select type"
-msgstr ""
+msgstr "Sélectionner le type"
msgid "WorkItem|Something went wrong when creating %{workItemType}. Please try again."
msgstr ""
@@ -44780,10 +45606,10 @@ msgid "WorkItem|Something went wrong when deleting the %{workItemType}. Please t
msgstr ""
msgid "WorkItem|Something went wrong when deleting the task. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la suppression de la tâche. Veuillez réessayer."
msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération des tâches. Veuillez actualiser cette page."
msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
msgstr ""
@@ -44792,10 +45618,10 @@ msgid "WorkItem|Something went wrong when fetching work item types. Please try a
msgstr ""
msgid "WorkItem|Something went wrong when trying to add a child. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la tentative d’ajout d’un enfant. Veuillez réessayer."
msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la création d’un enfant. Veuillez réessayer."
msgid "WorkItem|Something went wrong while updating the %{workItemType}. Please try again."
msgstr ""
@@ -44803,41 +45629,44 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr "Date de début"
+
msgid "WorkItem|Task"
-msgstr ""
+msgstr "Tâche"
msgid "WorkItem|Task deleted"
-msgstr ""
+msgstr "Tâche supprimée"
msgid "WorkItem|Tasks"
-msgstr ""
+msgstr "Tâches"
msgid "WorkItem|Test case"
-msgstr ""
+msgstr "Cas de test"
msgid "WorkItem|Turn off confidentiality"
-msgstr ""
+msgstr "Désactiver la confidentialité"
msgid "WorkItem|Turn on confidentiality"
-msgstr ""
+msgstr "Activer la confidentialité"
msgid "WorkItem|Undo"
-msgstr ""
+msgstr "Annuler"
msgid "WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}"
msgstr ""
msgid "WorkItem|Work Items"
-msgstr ""
+msgstr "Éléments de Travail"
msgid "WorkItem|Work item"
-msgstr ""
+msgstr "Élément de travail"
msgid "Would you like to create a new branch?"
-msgstr ""
+msgstr "Voulez-vous créer une nouvelle branche ?"
msgid "Would you like to try auto-generating a branch name?"
-msgstr ""
+msgstr "Souhaitez-vous essayer de générer automatiquement un nom de branche ?"
msgid "Write"
msgstr "Rédiger"
@@ -44867,10 +45696,10 @@ msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr ""
msgid "Xcode"
-msgstr ""
+msgstr "Xcode"
msgid "YYYY-MM-DD"
-msgstr ""
+msgstr "AAAA-MM-JJ"
msgid "Yes"
msgstr "Oui"
@@ -44882,10 +45711,10 @@ msgid "Yes, add it"
msgstr "Oui, l’ajouter"
msgid "Yes, close issue"
-msgstr ""
+msgstr "Oui, fermer le ticket"
msgid "Yes, delete project"
-msgstr ""
+msgstr "Oui, supprimer le projet"
msgid "Yesterday"
msgstr "Hier"
@@ -44894,10 +45723,10 @@ msgid "You"
msgstr ""
msgid "You already have pending todo for this alert"
-msgstr ""
+msgstr "Vous avez déjà une tâche « À faire » en attente pour cette alerte"
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
-msgstr ""
+msgstr "Vous allez ajouter %{usersTag} personnes à la discussion. Elles recevront toutes une notification."
msgid "You are about to clear %{count} image from the cache. Once you confirm, the next time a pipeline runs it must pull an image or tag from Docker Hub. Are you sure?"
msgid_plural "You are about to clear %{count} images from the cache. Once you confirm, the next time a pipeline runs it must pull an image or tag from Docker Hub. Are you sure?"
@@ -44905,22 +45734,22 @@ msgstr[0] ""
msgstr[1] ""
msgid "You are about to delete this forked project containing:"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer ce projet divergent qui contient :"
msgid "You are about to delete this project containing:"
msgstr ""
msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
-msgstr ""
+msgstr "Vous êtes sur le point de transférer le contrôle de votre compte au groupe %{group_name}. Cette action n'est PAS réversible, vous ne pourrez plus accéder à aucun de vos groupes et projets en dehors de %{group_name} une fois ce transfert terminé."
msgid "You are already a member of this %{member_source}."
msgstr ""
msgid "You are already impersonating another user"
-msgstr ""
+msgstr "Vous empruntez déjà l'identité d'un autre utilisateur"
msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
-msgstr ""
+msgstr "Vous êtes un administrateur, ce qui signifie qu’accorder l’accès à %{client_name} leur permettra d’interagir avec GitLab en tant qu’administrateur. Procédez avec précaution."
msgid "You are attempting to delete a file that has been previously updated."
msgstr ""
@@ -44929,73 +45758,73 @@ msgid "You are attempting to update a file that has changed since you started ed
msgstr ""
msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
-msgstr ""
+msgstr "Vous serez facturé si ce nombre est dépassé. %{qsrOverageLinkStart}Comment fonctionne la facturation ?%{qsrOverageLinkEnd}"
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
msgid "You are currently offline, or the GitLab instance is not reachable."
-msgstr ""
+msgstr "Vous êtes actuellement hors ligne, ou l'instance GitLab n'est pas joignable."
msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer %{project_full_name}. Les projets supprimés NE PEUVENT PAS être restaurés ! Êtes-vous ABSOLUMENT sûr(e) ?"
msgid "You are going to remove %{group_name}. This will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer la relation de fork du projet %{project_full_name}. Êtesâ€vous ABSOLUMENT sûr ?"
msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Vous allez transférer %{group_name} vers un autre espace de noms. Êtes-vous ABSOLUMENT sûr ?"
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Vous allez transférer %{project_full_name} vers un autre espace de noms. Êtes-vous ABSOLUMENT sûr ?"
msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
-msgstr ""
+msgstr "Vous allez désactiver la confidentialité. Cela signifie que %{strongStart}tout le monde%{strongEnd} sera en mesure de voir et laisser un commentaire sur ce(tte) %{issuableType}."
msgid "You are going to turn on confidentiality. Only %{context} members with %{strongStart}%{permissions}%{strongEnd} can view or be notified about this %{issuableType}."
msgstr ""
msgid "You are not allowed to %{action} a user"
-msgstr ""
+msgstr "Vous n'avez pas le droit de %{action} un utilisateur"
msgid "You are not allowed to approve a user"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé(e) à approuver un utilisateur"
msgid "You are not allowed to log in using password"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à vous connecter avec un mot de passe"
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à pousser dans cette branche. Créez une autre branche ou ouvrez une demande de fusion."
msgid "You are not allowed to reject a user"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé(e) à rejeter un utilisateur"
msgid "You are not allowed to unlink your primary login account"
msgstr ""
msgid "You are not authorized to delete this site profile"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé(e) à supprimer ce profil de site"
msgid "You are not authorized to perform this action"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à effectuer cette action"
msgid "You are not authorized to run this manual job"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à exécuter cette tâche manuelle"
msgid "You are not authorized to update this profile"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à mettre à jour ce profil"
msgid "You are not authorized to update this scanner profile"
-msgstr ""
+msgstr "Vous n'êtes pas autorisé à mettre à jour ce profil de scanner"
msgid "You are not authorized to upload metric images"
msgstr ""
msgid "You are now impersonating %{username}"
-msgstr ""
+msgstr "Vous utilisez maintenant l'identité de %{username}"
msgid "You are on a read-only GitLab instance."
msgstr "Vous êtes sur une instance GitLab en lecture seule."
@@ -45007,22 +45836,22 @@ msgid "You are signed in to GitLab as:"
msgstr ""
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
-msgstr ""
+msgstr "Vous essayez de téléverser autre chose qu'une image. Veuillez envoyer un .png, .jpg, .jpeg, .gif, .bmp, .tiff ou .ico."
msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
-msgstr ""
+msgstr "Vous utilisez PostgreSQL %{pg_version_current}, mais cette version de GitLab nécessite au minimum PostgreSQL %{pg_version_minimum}. Veuillez mettre à jour votre environnement vers une version de PostgreSQL prise en charge, voir %{pg_requirements_url} pour plus de détails."
msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
-msgstr ""
+msgstr "Vous pouvez %{gitlabLinkStart}résoudre les conflits sur GitLab%{gitlabLinkEnd} ou %{resolveLocallyStart}le faire localement%{resolveLocallyEnd}."
msgid "You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
-msgstr ""
+msgstr "Vous pouvez %{resolveLocallyStart}effectuer la résolution localement%{resolveLocallyEnd}."
msgid "You can adjust rules on auto-banning %{link_start}here%{link_end}."
-msgstr ""
+msgstr "Vous pouvez ajuster les règles de bannissement automatique %{link_start}ici%{link_end}."
msgid "You can adjust rules on auto-banning here: %{url}."
-msgstr ""
+msgstr "Vous pouvez ajuster les règles de bannissement automatique ici : %{url}."
msgid "You can also create a project from the command line."
msgstr "Vous pouvez également créer un projet en ligne de commande."
@@ -45031,7 +45860,7 @@ msgid "You can also press Ctrl-Enter"
msgstr ""
msgid "You can also press ⌘-Enter"
-msgstr ""
+msgstr "Vous pouvez aussi appuyer sur ⌘-Entrée"
msgid "You can also star a label to make it a priority label."
msgstr "Vous pouvez marquer un label comme important pour en faire un label prioritaire."
@@ -45043,21 +45872,21 @@ msgid "You can also upload existing files from your computer using the instructi
msgstr ""
msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Vous pouvez également utiliser des jetons d'accès de groupe avec Git pour vous authentifier via HTTP(S). %{link_start}En savoir plus.%{link_end}"
msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Vous pouvez également utiliser des jetons d'accès au projet avec Git pour vous authentifier via HTTP(S). %{link_start}En savoir plus.%{link_end}"
msgid "You can always change your URL later"
-msgstr ""
+msgstr "Vous pouvez toujours modifier votre URL plus tard"
msgid "You can always edit this later"
-msgstr ""
+msgstr "Vous pouvez toujours modifier ceci plus tard"
msgid "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} member has %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} member who maintains access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} member. The remaining members will get a status of Over limit and lose access to the group."
msgid_plural "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} members have %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Vous pouvez maintenant commencer à déplacer des membres dans %{namespace_name}. Un membre perd l'accès au groupe lorsque vous désactivez %{strong_start}Dans un siège%{strong_end}. Si plus de %{free_user_limit} membre a l'option %{strong_start}Dans un siège%{strong_end} activée après le 19 octobre 2022, nous sélectionnerons le %{free_user_limit} membre dont l'accès sera conservé. Nous prendrons en compte en premier les membres ayant les rôles de Propriétaire et de Mainteneur, puis ceux actifs le plus récemment, jusqu'à atteindre %{free_user_limit} membre. Les membres restants passeront à l'état Hors limite et n'auront plus accès au groupe."
+msgstr[1] "Vous pouvez maintenant commencer à déplacer des membres dans %{namespace_name}. Un membre perd l'accès au groupe lorsque vous désactivez %{strong_start}Dans un siège%{strong_end}. Si plus de %{free_user_limit} membres ont l'option %{strong_start}Dans un siège%{strong_end} activée après le 19 octobre 2022, nous sélectionnerons les %{free_user_limit} membres dont l'accès sera conservé. Nous prendrons en compte en premier les membres ayant les rôles de Propriétaire et de Mainteneur, puis ceux actifs le plus récemment, jusqu'à atteindre %{free_user_limit} membres. Les membres restants passeront à l'état Hors limite et n'auront plus accès au groupe."
msgid "You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
msgstr ""
@@ -45065,77 +45894,83 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr "Vous pouvez vérifier vos jetons ou en créer de nouveaux dans vos %{pat_link_start}paramètres de jetons d'accès personnels%{pat_link_end}."
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr "Vous pouvez vérifier vos jetons ou en créer de nouveaux dans vos paramètres de jetons d'accès personnels %{pat_link}."
+
msgid "You can create a new %{link}."
msgstr ""
msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
-msgstr ""
+msgstr "Vous pouvez créer un(e) nouveau(elle) %{name} dans ce projet en envoyant un courriel à l'adresse de messagerie suivante :"
msgid "You can create a new Personal Access Token by visiting %{link}"
-msgstr ""
+msgstr "Vous pouvez créer un nouveau Jeton d'Accès Personnel en visitant %{link}"
msgid "You can create a new SSH key by visiting %{link}"
-msgstr ""
+msgstr "Vous pouvez créer une nouvelle clé SSH en visitant %{link}"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
-msgstr ""
+msgstr "Vous pouvez en créer un nouveau ou les vérifier dans vos paramètres de %{pat_link_start}jetons d'accès personnels%{pat_link_end}."
msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
-msgstr ""
+msgstr "Vous pouvez en créer une nouvelle ou les vérifier dans vos paramètres de %{ssh_key_link_start}Clés SSH%{ssh_key_link_end}."
msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
-msgstr ""
+msgstr "Vous pouvez en créer une nouvelle ou les vérifier dans vos paramètres de clés SSH %{ssh_key_link}."
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}."
-msgstr ""
+msgstr "Vous pouvez en créer un nouveau ou les vérifier dans vos paramètres de jetons d'accès personnels %{pat_link}."
msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
-msgstr ""
+msgstr "Vous pouvez en créer de nouveaux dans vos paramètres de %{pat_link_start}Jetons d'Accès Personnels%{pat_link_end}"
msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
-msgstr ""
+msgstr "Vous pouvez en créer de nouveaux dans vos paramètres de Jetons d'Accès Personnels %{pat_link}"
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Vous pouvez facilement y contribuer en demandant à rejoindre ces groupes."
msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
-msgstr ""
+msgstr "Vous pouvez activer les Fonctionnalités d'Inscription car le Ping de Service est activé. Pour continuer à les utiliser à l'avenir, vous aurez également besoin de vous inscrire auprès de GitLab via un nouveau service de licence Cloud."
msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
-msgstr ""
+msgstr "Vous pouvez activer la création de jetons d'accès de groupe dans les %{link_start}paramètres de groupe%{link_end}."
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
-msgstr ""
+msgstr "Vous pouvez activer la création de jetons d'accès au projet dans les %{link_start}paramètres de groupe%{link_end}."
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
-msgstr ""
+msgstr "Vous pouvez trouver plus d’informations sur les abonnements à GitLab dans %{subscriptions_doc_link}."
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
-msgstr ""
+msgstr "Vous pouvez commencer par cloner le dépôt ou par y ajouter des fichiers avec l'une des options suivantes."
msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
-msgstr ""
+msgstr "Vous pouvez regrouper les cas de test avec des étiquettes. Pour en savoir plus sur la direction future de cette fonctionnalité, visitez %{linkStart}Gestion de la Qualité sur la page Direction%{linkEnd}."
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "Vous pouvez inviter un nouveau membre sur %{project_name} ou inviter un autre groupe."
msgid "You can invite a new member to %{project_name}."
-msgstr ""
+msgstr "Vous pouvez inviter un nouveau membre sur %{project_name}."
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "Vous pouvez inviter un autre groupe sur %{project_name}."
msgid "You can move around the graph by using the arrow keys."
msgstr "Vous pouvez vous déplacer dans le graphique en utilisant les touches fléchées."
msgid "You can notify the app / group or a project by sending them an email notification"
-msgstr ""
+msgstr "Vous pouvez notifier l'application / groupe ou un projet en leur envoyant une notification par courriel"
msgid "You can now close this window."
-msgstr ""
+msgstr "Vous pouvez maintenant fermer cette fenêtre."
msgid "You can now export your security dashboard to a CSV report."
msgstr "Vous pouvez maintenant exporter votre tableau de bord de sécurité vers un rapport CSV."
@@ -45147,10 +45982,10 @@ msgid "You can now submit a merge request to get this change into the original p
msgstr ""
msgid "You can only %{action} files when you are on a branch"
-msgstr ""
+msgstr "Vous pouvez seulement %{action} des fichiers lorsque vous êtes sur une branche"
msgid "You can only add up to %{max_contacts} contacts at one time"
-msgstr ""
+msgstr "Vous ne pouvez ajouter au maximum que %{max_contacts} contacts à la fois"
msgid "You can only edit files when you are on a branch"
msgstr "Vous ne pouvez modifier des fichiers que dans une branche"
@@ -45168,7 +46003,7 @@ msgid "You can see your chat accounts."
msgstr ""
msgid "You can set up jobs to only use runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Vous pouvez configurer des tâches pour utiliser uniquement des exécuteurs qui possèdent des étiquettes spécifiques. Utilisez des virgules pour séparer les étiquettes."
msgid "You can specify notification level per group or per project."
msgstr ""
@@ -45177,22 +46012,25 @@ msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Vous pouvez tester votre fichier « .gitlab-ci.yml » avec %{linkStart}CI Lint%{linkEnd}."
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
-msgstr ""
+msgstr "Vous pouvez afficher la source ou %{linkStart}%{cloneIcon} cloner le dépot%{linkEnd}"
msgid "You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members. To get more members an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "Vous ne pouvez pas en ajouter davantage mais vous pouvez gérer les membres existants, par exemple, en supprimant ceux inactifs pour les remplacer par de nouveaux. Pour obtenir plus de membres, un propriétaire du groupe peut démarrer une période d'essai ou faire une mise à niveau vers une édition payante."
msgid "You cannot %{action} %{state} users."
-msgstr ""
+msgstr "Vous ne pouvez pas %{action} les utilisateurs %{state}."
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr "Vous ne pouvez pas ajouter davantage d'épopées. Cette épopée contient déjà le nombre maximal d'épopées enfants."
+
msgid "You cannot approve your own deployment."
msgstr ""
msgid "You cannot combine replace_ids with add_ids or remove_ids"
-msgstr ""
+msgstr "Vous ne pouvez pas combiner replace_ids avec add_ids ou remove_ids"
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -45207,7 +46045,7 @@ msgid "You cannot play this scheduled pipeline at the moment. Please wait a minu
msgstr ""
msgid "You cannot rename an environment after it's created."
-msgstr ""
+msgstr "Vous ne pouvez pas renommer un environnement après sa création."
msgid "You cannot set yourself to awaiting"
msgstr ""
@@ -45219,7 +46057,7 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "Vous ne pouvez pas écrire sur cette instance GitLab en lecture seule."
msgid "You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "Vous ne pouvez pas modifier directement des fichiers dans ce projet. Créez un projet divergent, puis proposez une demande de fusion avec vos modifications."
msgid "You could not create a new trigger."
msgstr ""
@@ -45228,34 +46066,34 @@ 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 ""
+msgstr "Vous n'avez pas la permission d'accéder aux métriques dora."
msgid "You do not have permission to approve a member"
-msgstr ""
+msgstr "Vous n'avez pas la permission d'approuver un membre"
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
msgid "You do not have permission to run a pipeline on this branch."
-msgstr ""
+msgstr "Vous n'avez pas la permission d'exécuter un pipeline sur cette branche."
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have permission to set a member awaiting"
-msgstr ""
+msgstr "Vous n'avez pas la permission de mettre un membre en attente"
msgid "You do not have permission to update the environment."
-msgstr ""
+msgstr "Vous n'avez pas la permission pour mettre à jour l'environnement."
msgid "You do not have permissions to run the import."
-msgstr ""
+msgstr "Vous n'avez pas la permission de lancer l'importation."
msgid "You don't have any U2F devices registered yet."
msgstr ""
msgid "You don't have any WebAuthn devices registered yet."
-msgstr ""
+msgstr "Vous n'avez pas encore d'appareil WebAuthn enregistré."
msgid "You don't have any active chat names."
msgstr ""
@@ -45270,13 +46108,13 @@ msgid "You don't have any deployments right now."
msgstr ""
msgid "You don't have any open merge requests"
-msgstr ""
+msgstr "Vous n'avez aucune demande de fusion ouverte"
msgid "You don't have any recent searches"
-msgstr ""
+msgstr "Vous n'avez aucune recherche récente"
msgid "You don't have permission to review this deployment. Contact the project or group owner for help."
-msgstr ""
+msgstr "Vous n'avez pas la permission d'examiner ce déploiement. Contactez le propriétaire du projet ou du groupe pour obtenir de l'aide."
msgid "You don't have permissions to create this project"
msgstr ""
@@ -45285,16 +46123,16 @@ msgid "You don't have sufficient permission to perform this action."
msgstr ""
msgid "You don't have the %{role} role for any groups in this instance."
-msgstr ""
+msgstr "Vous n'avez le rôle %{role} dans aucun groupe dans cette instance."
msgid "You don't have write access to the source branch."
-msgstr ""
+msgstr "Vous n'avez pas d'accès en écriture à la branche source."
msgid "You don’t have access to Productivity Analytics in this group"
msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
-msgstr ""
+msgstr "Vous n'avez pas accès à l'analyse des chaînes de valeur de ce groupe"
msgid "You have %{pendingMembersCount} pending member that needs approval."
msgid_plural "You have %{pendingMembersCount} pending members that need approval."
@@ -45308,37 +46146,37 @@ msgid "You have been granted %{access_level} access to the %{source_name} %{sour
msgstr ""
msgid "You have been granted %{member_human_access} access to group %{name}."
-msgstr ""
+msgstr "Vous avez obtenu un accès %{member_human_access} au groupe %{name}."
msgid "You have been granted %{member_human_access} access to project %{name}."
-msgstr ""
+msgstr "Vous avez obtenu un accès %{member_human_access} au projet %{name}."
msgid "You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}"
-msgstr ""
+msgstr "Vous avez été invité par %{link_to_inviter} à rejoindre %{source_name} %{strong_open}%{link_to_source}%{strong_close} en tant que %{role}"
msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
-msgstr ""
+msgstr "Vous avez été redirigé(e) vers l'unique résultat ; voir les %{a_start}résultats de la recherche%{a_end} à la place."
msgid "You have been unsubscribed from this thread."
-msgstr ""
+msgstr "Vous avez été désabonné(e) des notifications de ce ticket."
msgid "You have declined the invitation to join %{title} %{name}."
-msgstr ""
+msgstr "Vous avez décliné l'invitation à rejoindre %{title} %{name}."
msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
-msgstr ""
+msgstr "Vous avez déjà fait des importations à %{numberOfPreviousImports} reprises depuis ce projet. Chaque nouvelle importation va créer des tickets en double."
msgid "You have insufficient permissions to configure escalation policies for this project"
-msgstr ""
+msgstr "Vous ne disposez pas des permissions suffisantes pour configurer des politiques d'escalade sur ce projet"
msgid "You have insufficient permissions to create a Todo for this alert"
-msgstr ""
+msgstr "Vous n'avez pas les autorisations suffisantes pour créer une tâche « À faire » pour cette alerte"
msgid "You have insufficient permissions to create an HTTP integration for this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour créer une intégration HTTP pour ce projet"
msgid "You have insufficient permissions to create an on-call schedule for this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour créer un calendrier des astreintes pour ce projet"
msgid "You have insufficient permissions to manage resource links for this incident"
msgstr ""
@@ -45347,34 +46185,34 @@ msgid "You have insufficient permissions to manage timeline events for this inci
msgstr ""
msgid "You have insufficient permissions to remove an on-call rotation from this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer un cycle de travail pour ce projet"
msgid "You have insufficient permissions to remove an on-call schedule from this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer un calendrier des astreintes pour ce projet"
msgid "You have insufficient permissions to remove this HTTP integration"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer cette intégration HTTP"
msgid "You have insufficient permissions to remove this Namespace Ban"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour supprimer ce Bannissement d'Espace de noms"
msgid "You have insufficient permissions to set customer relations contacts for this issue"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour définir des contacts de relation client sur ce ticket"
msgid "You have insufficient permissions to update an on-call schedule for this project"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour créer un calendrier d'astreintes pour ce projet"
msgid "You have insufficient permissions to update this HTTP integration"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour mettre à jour cette intégration HTTP"
msgid "You have insufficient permissions to view shifts for this rotation"
-msgstr ""
+msgstr "Vous n'avez pas les permissions suffisantes pour voir les quarts de travail de ce cycle"
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 add this license to your instance."
-msgstr ""
+msgstr "Vous avez un nombre d'utilisateurs actifs plus élevé que celui autorisé par votre licence. Avant le %{date}, GitLab doit ajuster votre abonnement. Pour achever ce processus, exportez votre fichier d'utilisation de licence et envoyez-le par courriel à %{renewal_service_email}. Une nouvelle licence vous sera envoyée par courriel à l'adresse de messagerie enregistrée dans le %{customers_dot}. Vous pouvez ajouter cette licence à votre instance."
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 add this license to your instance."
-msgstr ""
+msgstr "Vous avez un nombre d'utilisateurs actifs plus élevé que celui autorisé par votre licence. GitLab doit donc modifier votre abonnement. Pour achever ce processus, exportez votre fichier d'utilisation de licence et envoyez-le par courriel à %{renewal_service_email}. Une nouvelle licence vous sera envoyée par courriel à l'adresse de messagerie enregistrée dans le %{customers_dot}. Vous pouvez ajouter cette licence à votre instance."
msgid "You have no permissions"
msgstr "Vous n’avez pas les autorisations"
@@ -45383,16 +46221,16 @@ msgid "You have not added any approvers. Start by adding users or groups."
msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
-msgstr ""
+msgstr "Vous avez configuré l'A2F sur votre compte ! Si vous perdez l'accès à votre périphérique A2F, vous pouvez utiliser vos codes de récupération pour accéder à votre compte. Sinon, en envoyant une clé SSH, vous pourrez %{anchorOpen}utiliser celle-ci pour générer des codes de récupération supplémentaires%{anchorClose}."
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
-msgstr ""
+msgstr "Vous avez des modifications non enregistrées"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -45401,12 +46239,12 @@ msgid "You may close the milestone now."
msgstr ""
msgid "You must be authenticated to access this path."
-msgstr ""
+msgstr "Vous devez être authentifié pour accéder à ce chemin."
msgid "You must be logged in to search across all of GitLab"
msgstr "Vous devez être connecté(e) pour rechercher dans tout GitLab"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45419,10 +46257,10 @@ msgid "You must provide your current password in order to change it."
msgstr ""
msgid "You must sign in to search for specific projects."
-msgstr ""
+msgstr "Vous devez vous connecter pour rechercher des projets spécifiques."
msgid "You must sign in to search for specific terms."
-msgstr ""
+msgstr "Vous devez vous connecter pour rechercher des termes spécifiques."
msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
@@ -45437,7 +46275,7 @@ msgid "You need permission."
msgstr "Vous avez besoin d’une autorisation."
msgid "You need to register a two-factor authentication app before you can set up a device."
-msgstr ""
+msgstr "Vous devez enregistrer une application d'authentification à deux facteurs avant de pouvoir configurer un appareil."
msgid "You need to set terms to be enforced"
msgstr ""
@@ -45449,31 +46287,31 @@ msgid "You need to upload a GitLab project export archive (ending in .gz)."
msgstr ""
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
-msgstr ""
+msgstr "Vous devez vérifier votre adresse de courriel principale avant de pouvoir activer l'Authentification à Deux Facteurs."
msgid "You see projects here when you're added to a group or project."
-msgstr ""
+msgstr "Les projets sont visibles ici lorsque vous êtes ajouté dans un groupe ou dans un projet."
msgid "You successfully declined the invitation"
-msgstr ""
+msgstr "Vous avez refusé l'invitation avec succès"
msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
msgstr ""
msgid "You will be removed from existing projects/groups"
-msgstr ""
+msgstr "Vous serez retiré des projets/groupes existants"
msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "Vous serez l'auteur de tous les événements du flux d'activité résultant d'une mise à jour, comme lors de la création de nouvelles branches ou des nouveaux commits qui sont poussés vers des branches existantes."
msgid "You will first need to set up Jira Integration to use this feature."
-msgstr ""
+msgstr "Vous devrez au préalable configurer l'intégration de Jira pour utiliser cette fonctionnalité."
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
-msgstr ""
+msgstr "Vous allez perdre toutes les modifications non validées que vous avez apportées à ce projet. Cette action ne peut pas être annulée."
msgid "You will need to update your local repositories to point to the new location."
msgstr ""
@@ -45494,10 +46332,10 @@ msgid "You will receive notifications only for comments in which you were @menti
msgstr "Vous ne recevrez de notifications que pour les commentaires où vous êtes @mentionné"
msgid "You won't be able to create new projects because you have reached your project limit."
-msgstr ""
+msgstr "Vous ne pourrez pas créer de nouveaux projets car vous en avez atteint la limite."
msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
+msgstr "La facturation des %{true_up_link_start}utilisateurs hors licence%{link_end} se fera sur une base trimestrielle ou annuelle, en fonction des termes de votre contrat."
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -45506,16 +46344,16 @@ msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Vous devrez utiliser différents noms de branches pour obtenir une comparaison valide."
msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end} in %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
+msgstr "Vous êtes sur le point de réduire la visibilité du projet %{strong_start}%{project_name}%{strong_end} dans %{strong_start}%{group_name}%{strong_end}."
msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
-msgstr ""
+msgstr "Vous êtes sur le point de réduire la visibilité du projet %{strong_start}%{project_name}%{strong_end}."
msgid "You're at the first commit"
-msgstr ""
+msgstr "Vous êtes à la première validation"
msgid "You're at the last commit"
-msgstr ""
+msgstr "Vous êtes à la dernière validation"
msgid "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request."
msgstr ""
@@ -45530,22 +46368,22 @@ msgid "You're receiving this email because of your account on %{host}."
msgstr "Vous recevez ce courriel parce que vous possédez un compte sur %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_label_subscriptions_link_start}Manage label subscriptions%{manage_label_subscriptions_link_end} &middot; %{help_link_start}Help%{help_link_end}"
-msgstr ""
+msgstr "Vous recevez cet e-mail en raison de votre compte sur %{host}. %{manage_label_subscriptions_link_start}Gérer les abonnements d'étiquettes%{manage_label_subscriptions_link_end} &middot; %{help_link_start}Aide%{help_link_end}"
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
-msgstr ""
+msgstr "Vous recevez cet e-mail en raison de votre compte sur %{host}. %{manage_notifications_link_start}Gérez toutes les notifications%{manage_notifications_link_end} &middot; %{help_link_start}Aide%{help_link_end}"
msgid "You're receiving this email because of your account on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
msgstr ""
msgid "You're receiving this email because of your activity on %{host}."
-msgstr ""
+msgstr "Vous recevez ce courriel en raison de votre activité sur %{host}."
msgid "You're receiving this email because of your activity on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
msgstr ""
msgid "You're receiving this email because you have been assigned an item on %{host}."
-msgstr ""
+msgstr "Vous recevez ce courriel car un élément vous a été assigné sur %{host}."
msgid "You're receiving this email because you have been assigned an item on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
msgstr "Vous recevez ce courriel car un ticket vous a été assigné sur %{host}. %{unsubscribe_link_start}Se désabonner%{unsubscribe_link_end} des notifications de ce ticket &middot; %{manage_notifications_link_start}Gérer toutes les notifications%{manage_notifications_link_end} &middot; %{help_link_start}Aide%{help_link_end}"
@@ -45554,28 +46392,28 @@ msgid "You're receiving this email because you have been mentioned on %{host}."
msgstr "Vous recevez ce courriel parce que vous avez été mentionné sur %{host}."
msgid "You're receiving this email because you have been mentioned on %{host}. %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
-msgstr ""
+msgstr "Vous recevez cet e-mail parce que vous avez été mentionné sur %{host}. %{manage_notifications_link_start}Gérez toutes les notifications%{manage_notifications_link_end} &middot; %{help_link_start}Aide%{help_link_end}"
msgid "You're receiving this email because you have been mentioned on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
-msgstr ""
+msgstr "Vous recevez cet e-mail parce que vous avez été mentionné sur %{host}. %{unsubscribe_link_start}Désabonnez-vous%{unsubscribe_link_end} de ce sujet &middot; %{manage_notifications_link_start}Gérer toutes les notifications%{manage_notifications_link_end} &middot; %{help_link_start}Aide%{help_link_end}"
msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
+msgstr "Vous voyez actuellement les membres de %{strong_start}%{group_name}%{strong_end}."
msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
msgstr ""
msgid "You've rejected %{user}"
-msgstr ""
+msgstr "Vous avez rejeté %{user}"
msgid "YouTube"
msgstr "YouTube"
msgid "Your %{group} membership will now expire in %{days}."
-msgstr ""
+msgstr "Votre adhésion à %{group} va désormais expirer dans %{days}."
msgid "Your %{host} account was signed in to from a new location"
-msgstr ""
+msgstr "Une connexion à votre compte %{host} a eu lieu depuis un nouvel emplacement"
msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded."
msgstr ""
@@ -45584,52 +46422,52 @@ msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change
msgstr ""
msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. If you do not renew, you will lose access to your paid features on %{strong}%{downgrades_on}%{strong_close}. After that date, you can't create issues or merge requests, or use many other features."
-msgstr ""
+msgstr "Votre abonnement %{strong}%{plan_name}%{strong_close} arrive à échéance le %{strong}%{expires_on}%{strong_close}. Si vous ne le renouvelez pas, vous perdrez l'accès à vos fonctionnalités payantes le %{strong}%{downgrades_on}%{strong_close}. Après cette date, vous ne pourrez plus créer de tickets ni de demandes de fusion, ni utiliser d'autres fonctionnalités."
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr ""
msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more details."
-msgstr ""
+msgstr "La syntaxe de votre configuration CI/CD n'est pas valide. Voir l'onglet Lint pour plus de détails."
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
-msgstr ""
+msgstr "Votre exportation CSV a commencé. Elle sera envoyée à %{email} une fois terminée."
msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr "Votre export CSV de %{count} depuis le projet %{project_link} a été ajouté à ce courriel en pièce-jointe."
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
-msgstr ""
+msgstr "Votre export CSV de %{written_count} du projet %{project_name} (%{project_url}) a été ajouté en pièce-jointe à ce courriel."
msgid "Your CSV import for project"
-msgstr ""
+msgstr "Votre importation CSV pour le projet"
msgid "Your Chain of Custody CSV export for the group %{group_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "L'export CSV de votre Chaîne de Traçabilité pour le groupe %{group_link} a été ajouté à ce courriel en tant que pièce jointe."
msgid "Your Chain of Custody CSV export for the group %{group_name} has been added to this email as an attachment."
-msgstr ""
+msgstr "L'export CSV de votre Chaîne de Traçabilité pour le groupe %{group_name} a été ajouté à ce courriel en tant que pièce jointe."
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 ""
+msgstr "Vos Rapports DevOps apportent une vue d'ensemble de la façon dont vous utilisez GitLab du point de vue des fonctionnalités. Utilisez-les pour voir comment vous vous situez vis-à-vis d'autres organisations, et pour que vos équipes se comparent entre elles."
msgid "Your GPG keys (%{count})"
msgstr ""
msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now."
-msgstr ""
+msgstr "Votre compte GitLab a été verrouillé en raison d'un nombre excessif de tentatives de connexion infructueuses. Vous pouvez attendre que votre compte soit déverrouillé automatiquement dans %{duration} ou vous pouvez cliquer sur le lien ci-dessous pour le déverrouiller maintenant."
msgid "Your GitLab account request has been approved!"
-msgstr ""
+msgstr "Votre demande de compte GitLab a été approuvée !"
msgid "Your GitLab group"
-msgstr ""
+msgstr "Votre groupe GitLab"
msgid "Your Groups"
msgstr "Vos groupes"
msgid "Your Personal Access Token was revoked"
-msgstr ""
+msgstr "Votre Jeton d'Accès Personnel a été révoqué"
msgid "Your Projects (default)"
msgstr "Vos projets (défaut)"
@@ -45638,13 +46476,13 @@ msgid "Your Projects' Activity"
msgstr "Activité de vos projets favoris"
msgid "Your SSH key has expired"
-msgstr ""
+msgstr "Votre clé SSH a expiré"
msgid "Your SSH key is expiring soon."
-msgstr ""
+msgstr "Votre clé SSH va bientôt expirer."
msgid "Your SSH key was deleted"
-msgstr ""
+msgstr "Votre clé SSH a été supprimée"
msgid "Your SSH keys (%{count})"
msgstr ""
@@ -45659,37 +46497,37 @@ msgid "Your U2F device was registered!"
msgstr ""
msgid "Your WebAuthn device did not send a valid JSON response."
-msgstr ""
+msgstr "Votre appareil WebAuthn n'a pas envoyé de réponse JSON valide."
msgid "Your WebAuthn device was registered!"
-msgstr ""
+msgstr "Votre appareil WebAuthn a été enregistré !"
msgid "Your access request to the %{source_type} has been withdrawn."
msgstr ""
msgid "Your account has been deactivated"
-msgstr ""
+msgstr "Votre compte a été désactivé"
msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
-msgstr ""
+msgstr "Votre compte a été désactivé. Vous ne pourrez pas : "
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 ""
+msgstr "Votre compte est authentifié avec SSO ou SAML. Pour %{push_pull_link_start}pousser et récupérer%{link_end} via %{protocol} avec Git en utilisant ce compte, vous devez %{set_password_link_start}définir un mot de passe%{link_end} ou %{set_up_pat_link_start}configurer un Jeton d'Accès Personnel%{link_end} à utiliser au lieu d'un mot de passe. Pour plus d'informations, voir %{clone_with_https_link_start}Cloner avec HTTPS%{link_end}."
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 ""
+msgstr "Votre compte est authentifié avec SSO ou SAML. Pour %{push_pull_link_start}pousser et récupérer%{link_end} via %{protocol} avec Git en utilisant ce compte, vous devez %{set_up_pat_link_start}configurer un Jeton d'Accès Personnel%{link_end} à utiliser au lieu d'un mot de passe. Pour plus d'informations, voir %{clone_with_https_link_start}Cloner avec HTTPS%{link_end}."
msgid "Your account is locked."
-msgstr ""
+msgstr "Votre compte est verrouillé."
msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
msgstr ""
msgid "Your action succeeded."
-msgstr ""
+msgstr "Votre action a réussi."
msgid "Your applications (%{size})"
msgstr "Vos applications (%{size})"
@@ -45698,13 +46536,13 @@ msgid "Your authorized applications"
msgstr "Vos applications autorisées"
msgid "Your browser does not support iFrames"
-msgstr ""
+msgstr "Votre navigateur ne prend pas en charge les iFrames"
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
-msgstr ""
+msgstr "Votre navigateur ne prend pas en charge WebAuthn. Veuillez utiliser un navigateur supporté, p. ex. Chrome (67+) ou Firefox (60+)."
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Vos modifications peuvent être validées sur %{branch_name} car une demande de fusion est ouverte."
@@ -45719,7 +46557,7 @@ msgid "Your changes have been successfully committed."
msgstr ""
msgid "Your comment could not be submitted because %{error}"
-msgstr ""
+msgstr "Votre commentaire n'a pas pu être soumis car %{error}"
msgid "Your comment could not be submitted! Please check your network connection and try again."
msgstr ""
@@ -45731,50 +46569,50 @@ msgid "Your comment will be discarded."
msgstr ""
msgid "Your commit email is used for web based operations, such as edits and merges."
-msgstr ""
+msgstr "Votre adresse de courriel de commit est utilisée pour les opérations Web basiques, telles que les modifications et les fusions."
msgid "Your current password is required to register a two-factor authenticator app."
-msgstr ""
+msgstr "Votre mot de passe actuel est requis pour enregistrer une application d'authentification à deux facteurs."
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
-msgstr ""
+msgstr "Votre tableau de bord a été copié. Vous pouvez %{web_ide_link_start}le modifier ici%{web_ide_link_end}."
msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
-msgstr ""
+msgstr "Votre tableau de bord a été mis à jour. Vous pouvez %{web_ide_link_start}le modifier ici%{web_ide_link_end}."
msgid "Your default notification email is used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
-msgstr ""
+msgstr "Votre courriel de notification par défaut est utilisé pour les notifications liées au compte dans le cas où aucune %{openingTag}adresse de courriel spécifique au groupe%{closingTag} n'est définie."
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
msgid "Your device is not compatible with GitLab. Please try another device"
-msgstr ""
+msgstr "Votre appareil n'est pas compatible avec GitLab. Veuillez essayer un autre appareil"
msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
-msgstr ""
+msgstr "Votre appareil doit être configuré. Branchez-le (si nécessaire) et cliquez sur le bouton à gauche."
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr ""
msgid "Your file must contain a column named %{codeStart}title%{codeEnd}. A %{codeStart}description%{codeEnd} column is optional. The maximum file size allowed is 10 MB."
-msgstr ""
+msgstr "Votre fichier doit contenir une colonne nommée %{codeStart}title%{codeEnd}. Une colonne %{codeStart}description%{codeEnd} est optionnelle. La taille de fichier maximale autorisée est de 10 Mo."
msgid "Your free group is now limited to %d member"
msgid_plural "Your free group is now limited to %d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Votre groupe gratuit est maintenant limité à %d membre"
+msgstr[1] "Votre groupe gratuit est maintenant limité à %d membres"
msgid "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} member. From October 19, 2022, the %{free_user_limit} most recently active member will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} member will remain in your group."
msgid_plural "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} members. From October 19, 2022, the %{free_user_limit} most recently active members will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} members will remain in your group."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Votre groupe %{strong_start}%{namespace_name}%{strong_end} contient plus de %{free_user_limit} membre. À partir du 19 octobre 2022, le %{free_user_limit} membre le plus récemment actif restera actif et ceux restants passeront à l'%{link_start}état Hors limite%{link_end} et perdront l'accès au groupe. Vous pouvez vous rendre sur la page Quotas d'Utilisation pour gérer lesquel des %{free_user_limit} membre restera dans votre groupe."
+msgstr[1] "Votre groupe %{strong_start}%{namespace_name}%{strong_end} contient plus de %{free_user_limit} membres. À partir du 19 octobre 2022, les %{free_user_limit} membres les plus récemment actifs resteront actifs et ceux restants passeront à l'%{link_start}état Hors limite%{link_end} et perdront l'accès au groupe. Vous pouvez vous rendre sur la page Quotas d'Utilisation pour gérer lesquels des %{free_user_limit} membres resteront dans votre groupe."
msgid "Your groups"
msgstr "Vos groupes"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
-msgstr ""
+msgstr "Votre instance dispose de %{remaining_user_count} utilisateurs restants sur les %{total_user_count} inclus dans votre abonnement. Vous pouvez en ajouter plus que le nombre inclus dans votre licence, et nous intégrerons le surplus à votre prochaine facture."
msgid "Your instance has exceeded your subscription's licensed user count."
msgstr ""
@@ -45789,168 +46627,168 @@ msgid "Your issues will be imported in the background. Once finished, you'll get
msgstr ""
msgid "Your license does not support on-call rotations"
-msgstr ""
+msgstr "Votre licence ne prend pas en charge les cycles de travail"
msgid "Your license does not support on-call schedules"
-msgstr ""
+msgstr "Votre licence n'intègre pas les calendriers d'astreintes"
msgid "Your license is valid from"
msgstr ""
msgid "Your membership in %{group} no longer expires."
-msgstr ""
+msgstr "Votre adhésion à %{group} ne va plus expirer."
msgid "Your message here"
-msgstr ""
+msgstr "Votre message ici"
msgid "Your name"
msgstr "Votre nom"
msgid "Your new %{accessTokenType}"
-msgstr ""
+msgstr "Votre nouveau %{accessTokenType}"
msgid "Your new %{accessTokenType} has been created."
-msgstr ""
+msgstr "Votre nouveau %{accessTokenType} a été créé."
msgid "Your new %{type}"
msgstr ""
msgid "Your new access token has been created."
-msgstr ""
+msgstr "Votre nouveau jeton d'accès a été créé."
msgid "Your new comment"
-msgstr ""
+msgstr "Votre nouveau commentaire"
msgid "Your password"
-msgstr ""
+msgstr "Votre mot de passe"
msgid "Your password reset token has expired."
msgstr ""
msgid "Your personal access token has expired"
-msgstr ""
+msgstr "Votre jeton d'accès personnel a expiré"
msgid "Your personal access tokens will expire in %{days_to_expire} days or less"
-msgstr ""
+msgstr "Vos jetons d'accès personnels expireront dans %{days_to_expire} jours ou moins"
msgid "Your primary email is used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}."
-msgstr ""
+msgstr "Votre adresse de courriel principale est utilisée pour la détection d'avatar. Vous pouvez la modifier dans les %{openingTag}paramètres de votre profil%{closingTag}."
msgid "Your profile"
-msgstr ""
+msgstr "Votre profil"
msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
-msgstr ""
+msgstr "Votre projet ne bénéficie plus des avantages de GitLab Ultimate depuis le 01/07/2022. Comme précédemment notifié dans l'appli, les projets open source publics de l'édition Gratuite peuvent postuler au programme GitLab for Open Source pour profiter de ces avantages. Veuillez vous référer à la %{faq_link_start}FAQ%{link_end} pour plus d'informations."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""
msgid "Your project will be created at:"
-msgstr ""
+msgstr "Votre projet sera créé à :"
msgid "Your projects"
msgstr "Vos projets"
msgid "Your public email will be displayed on your public profile."
-msgstr ""
+msgstr "Votre adresse de courriel publique sera affichée sur votre profil public."
msgid "Your request for access could not be processed: %{error_message}"
-msgstr ""
+msgstr "Votre demande d'accès n'a pas pu être traitée : %{error_message}"
msgid "Your request for access has been queued for review."
msgstr ""
msgid "Your request to join %{host} has been rejected."
-msgstr ""
+msgstr "Votre demande pour rejoindre %{host} a été rejetée."
msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
-msgstr ""
+msgstr "Vos exigences sont en cours d'importation. Une fois que cela sera terminé, vous recevrez un courriel de confirmation."
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
-msgstr ""
+msgstr "Vos exigences seront importées en arrière-plan. Après la fin de l'importation, vous recevrez un courriel de confirmation."
msgid "Your search didn't match any commits."
-msgstr ""
+msgstr "Votre recherche ne correspond à aucune validation."
msgid "Your search didn't match any commits. Try a different query."
-msgstr ""
+msgstr "Aucun commit ne correspond à votre recherche. Essayez une requête différente."
msgid "Your search timed out"
-msgstr ""
+msgstr "Votre recherche a expiré"
msgid "Your sign-in page is %{url}."
-msgstr ""
+msgstr "Votre page de connexion est %{url}."
msgid "Your snippets"
-msgstr ""
+msgstr "Vos extraits"
msgid "Your subscription expired!"
-msgstr ""
+msgstr "Votre abonnement a expiré."
msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seat remaining."
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Votre abonnement dispose de %{remaining_seat_count} siège restant sur %{total_seat_count}."
+msgstr[1] "Votre abonnement dispose de %{remaining_seat_count} sièges restants sur %{total_seat_count}."
msgid "Your subscription will expire on %{expires_on}"
-msgstr ""
+msgstr "Votre abonnement va arriver à échéance le %{expires_on}"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
-msgstr ""
+msgstr "Votre mise à jour a échoué. Vous ne pouvez téléverser qu'un seul design lorsque vous le déposez sur un design existant."
msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
-msgstr ""
+msgstr "Votre mise à jour a échoué. Vous devez téléverser un fichier de même nom lorsque vous le déposez sur un design existant."
msgid "Your username is %{username}."
-msgstr ""
+msgstr "Votre nom d'utilisateur est %{username}."
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
-msgstr ""
+msgstr "Échec du chargement du ticket ZenTao. Affichez le ticket dans ZenTao ou rechargez la page."
msgid "ZenTaoIntegration|This is a ZenTao user."
-msgstr ""
+msgstr "Il s'agit d'un utilisateur de ZenTao."
msgid "ZenTaoIntegration|ZenTao user"
-msgstr ""
+msgstr "Utilisateur ZenTao"
msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
-msgstr ""
+msgstr "Une erreur s'est produite lors de la demande de données auprès du service ZenTao."
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
-msgstr ""
+msgstr "URL de base de l'instance ZenTao."
msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
-msgstr ""
+msgstr "Avant d'activer cette intégration, vous devez configurer ZenTao. Pour plus de détails, lisez la %{link_start}documentation d'intégration ZenTao%{link_end}."
msgid "ZentaoIntegration|Enter new ZenTao API token"
-msgstr ""
+msgstr "Entrez le nouveau jeton d'API ZenTao"
msgid "ZentaoIntegration|If different from Web URL."
-msgstr ""
+msgstr "Si différente de l'URL Web."
msgid "ZentaoIntegration|Open ZenTao"
-msgstr ""
+msgstr "Ouvrir ZenTao"
msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
-msgstr ""
+msgstr "Utiliser ZenTao comme gestionnaire de tickets pour ce projet."
msgid "ZentaoIntegration|ZenTao"
-msgstr ""
+msgstr "ZenTao"
msgid "ZentaoIntegration|ZenTao API URL (optional)"
-msgstr ""
+msgstr "URL de l'API ZenTao (facultatif)"
msgid "ZentaoIntegration|ZenTao API token"
-msgstr ""
+msgstr "Jeton d'API ZenTao"
msgid "ZentaoIntegration|ZenTao Product ID"
-msgstr ""
+msgstr "ID de produit ZenTao"
msgid "ZentaoIntegration|ZenTao Web URL"
-msgstr ""
+msgstr "URL Web de ZenTao"
msgid "ZentaoIntegration|ZenTao issues"
-msgstr ""
+msgstr "Tickets ZenTao"
msgid "Zoom meeting added"
msgstr ""
@@ -45959,7 +46797,7 @@ msgid "Zoom meeting removed"
msgstr ""
msgid "[No reason]"
-msgstr ""
+msgstr "[Sans raison]"
msgid "[REDACTED]"
msgstr ""
@@ -45968,24 +46806,24 @@ msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
-msgstr ""
+msgstr "« end_time » ne devrait pas dépasser « start_time » de plus d'un mois"
msgid "`start_time` should precede `end_time`"
-msgstr ""
+msgstr "L'heure de début « start_time » doit être antérieure à celle de fin « end_time »"
msgid "`work_items_hierarchy` feature flag disabled for this project"
-msgstr ""
+msgstr "L'indicateur de fonctionnalité « work_items_hierarchy » est désactivé sur ce projet"
msgid "a deleted user"
msgstr "un utilisateur supprimé"
msgid "about 1 hour"
msgid_plural "about %d hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "environ 1 heure"
+msgstr[1] "environ %d heures"
msgid "access:"
-msgstr ""
+msgstr "accès :"
msgid "added"
msgstr ""
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46000,7 +46841,7 @@ msgid "ago"
msgstr ""
msgid "alert"
-msgstr ""
+msgstr "alerte"
msgid "allowed to fail"
msgstr ""
@@ -46009,19 +46850,19 @@ msgid "already banned from namespace"
msgstr ""
msgid "already being used for another group or project %{timebox_name}."
-msgstr ""
+msgstr "déjà en cours d'utilisation pour un autre groupe ou projet %{timebox_name}."
msgid "already being used for another iteration within this cadence."
-msgstr ""
+msgstr "déjà en cours d'utilisation par une autre itération de cette cadence."
msgid "already has a \"created\" issue link"
-msgstr ""
+msgstr "a déjà un lien vers un ticket « créé »"
msgid "already shared with this group"
msgstr ""
msgid "and"
-msgstr ""
+msgstr "et"
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -46031,8 +46872,8 @@ msgstr ""
msgid "approval"
msgid_plural "approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "approbation"
+msgstr[1] "approbations"
msgid "archived"
msgstr ""
@@ -46041,7 +46882,7 @@ msgid "archived:"
msgstr ""
msgid "artifacts"
-msgstr ""
+msgstr "artéfacts"
msgid "assign yourself"
msgstr ""
@@ -46062,18 +46903,18 @@ msgid "attach a new file"
msgstr ""
msgid "authored"
-msgstr ""
+msgstr "rédigé"
msgid "banned user already exists"
-msgstr ""
+msgstr "l’utilisateur banni existe déjà"
msgid "blocks"
msgstr ""
msgid "branch"
msgid_plural "branches"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "branche"
+msgstr[1] "branches"
msgid "branch name"
msgstr "nom de la branche"
@@ -46085,13 +46926,16 @@ msgid "by"
msgstr "par"
msgid "cURL:"
+msgstr "cURL :"
+
+msgid "can contain only digits"
msgstr ""
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
-msgstr ""
+msgstr "ne peut contenir que les lettres de l'alphabet Base64 (RFC4648) ainsi que « @ » et « . »"
msgid "can contain only lowercase letters, digits, and '_'."
-msgstr ""
+msgstr "ne peut contenir que des minuscules, des chiffres et '_'."
msgid "can not be changed for existing notes"
msgstr ""
@@ -46103,10 +46947,10 @@ msgid "can not be set for this type of note"
msgstr ""
msgid "can only be changed by a group admin."
-msgstr ""
+msgstr "ne peut être modifié que par un administrateur de groupe."
msgid "can only have one escalation policy"
-msgstr ""
+msgstr "ne peut avoir qu'une seule politique d'escalade"
msgid "can't be enabled when delayed group deletion is disabled"
msgstr ""
@@ -46118,20 +46962,23 @@ msgid "can't be solely blank"
msgstr ""
msgid "can't be the same as the source project"
-msgstr ""
+msgstr "ne peut pas être identique au projet source"
msgid "can't include: %{invalid_storages}"
-msgstr ""
+msgstr "ne peut/peuvent pas inclure : %{invalid_storages}"
msgid "can't reference a branch that does not exist"
-msgstr ""
+msgstr "ne peut pas référencer une branche qui n'existe pas"
msgid "cannot assign a non-confidential work item to a confidential parent. Make the work item confidential and try again."
-msgstr ""
+msgstr "ne peut pas assigner un élément de travail non confidentiel à un parent confidentiel. Rendez cet élément de travail confidentiel et réessayez."
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46142,7 +46989,7 @@ msgid "cannot be changed if shared runners are enabled"
msgstr ""
msgid "cannot be changed since member is associated with a custom role"
-msgstr ""
+msgstr "ne peut pas être changé car le membre est associé à un rôle personnalisé"
msgid "cannot be enabled"
msgstr ""
@@ -46157,7 +47004,7 @@ msgid "cannot be enabled unless all domains have TLS certificates"
msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
-msgstr ""
+msgstr "impossible à activer tant qu'une carte de crédit valide n'est pas enregistrée"
msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
msgstr ""
@@ -46169,7 +47016,7 @@ msgid "cannot block others"
msgstr ""
msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
-msgstr ""
+msgstr "ne peut pas contenir de balises HTML/XML ni de mot entre crochets (&lt;, &gt;)."
msgid "cannot include leading slash or directory traversal."
msgstr ""
@@ -46182,29 +47029,29 @@ msgstr ""
msgid "change"
msgid_plural "changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "modification"
+msgstr[1] "modifications"
msgid "ciReport|%{criticalStart}critical%{criticalEnd}, %{highStart}high%{highEnd} and %{otherStart}others%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}critiques%{criticalEnd} %{highStart}hautes%{highEnd} et %{otherStart}autres%{otherEnd}"
msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}"
-msgstr ""
+msgstr "%{danger_start}%{degradedNum} dégradées%{danger_end}, %{same_start}%{sameNum} identiques%{same_end}, and %{success_start}%{improvedNum} améliorées%{success_end}"
msgid "ciReport|%{degradedNum} degraded"
-msgstr ""
+msgstr "%{degradedNum} dégradé(e)s"
msgid "ciReport|%{improvedNum} improved"
-msgstr ""
+msgstr "%{improvedNum} amélioré(e)s"
msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}En savoir plus sur l'API Fuzzing%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}En savoir plus à propos de l’analyse des conteneurs %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}En savoir plus sur les Tests à données aléatoires guidés par la Couverture de code %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
msgstr "%{linkStartTag}En savoir plus sur DAST%{linkEndTag}"
@@ -46216,13 +47063,13 @@ msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
msgstr "%{linkStartTag}En savoir plus sur SAST %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}En savoir plus sur la Détection de Secrets %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}En savoir plus sur les rapports de qualité de code %{linkEndTag}"
msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
-msgstr ""
+msgstr "%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} dans %{path}"
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} restant(s)"
@@ -46234,34 +47081,34 @@ msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr "%{reportType} : le chargement a généré une erreur"
msgid "ciReport|%{sameNum} same"
-msgstr ""
+msgstr "%{sameNum} identiques"
msgid "ciReport|%{scanner} detected %{number} new potential %{vulnStr}"
-msgstr ""
+msgstr "%{scanner} a détecté %{number} nouvelles %{vulnStr} potentielles"
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
-msgstr ""
+msgstr "%{scanner} a détecté %{strong_start}%{number}%{strong_end} nouveau potentiel %{vulnStr}"
msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
-msgstr ""
+msgstr "%{scanner} n'a détecté aucune %{boldStart}nouvelle%{boldEnd} vulnérabilité potentielle"
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
-msgstr ""
+msgstr "%{scanner} n'a détecté aucun %{strong_start}nouveau%{strong_end} %{vulnStr}"
msgid "ciReport|: Loading resulted in an error"
-msgstr ""
+msgstr "Le chargement a entraîné une erreur"
msgid "ciReport|API Fuzzing"
-msgstr ""
+msgstr "API Fuzzing"
msgid "ciReport|API fuzzing"
-msgstr ""
+msgstr "API fuzzing"
msgid "ciReport|All clusters"
-msgstr ""
+msgstr "Toutes les grappes de serveurs"
msgid "ciReport|All images"
-msgstr ""
+msgstr "Toutes les images"
msgid "ciReport|All projects"
msgstr ""
@@ -46270,16 +47117,16 @@ msgid "ciReport|All severities"
msgstr ""
msgid "ciReport|All tools"
-msgstr ""
+msgstr "Tous les outils"
msgid "ciReport|Analyze a deployed version of your web application for known vulnerabilities by examining it from the outside in. DAST works by simulating external attacks on your application while it is running."
-msgstr ""
+msgstr "Analyser une version déployée de votre application web à la recherche de vulnérabilités connues en l’examinant de l’extérieur. DAST fonctionne en simulant des attaques externes sur votre application pendant son exécution."
msgid "ciReport|Automatically apply the patch in a new branch"
msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
-msgstr ""
+msgstr "Artéfact de qualité de code du pipeline de base introuvable"
msgid "ciReport|Browser Performance"
msgstr ""
@@ -46288,24 +47135,24 @@ msgid "ciReport|Browser performance test metrics results are being parsed"
msgstr ""
msgid "ciReport|Browser performance test metrics: "
-msgstr ""
+msgstr "Métriques du test de performances du navigateur : "
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] ""
+msgstr[0] "Métriques du test de performance du navigateur : %{strong_start}%{changesFound}%{strong_end} modification"
+msgstr[1] "Métriques du test de performance du navigateur : %{strong_start}%{changesFound}%{strong_end} modifications"
msgid "ciReport|Browser performance test metrics: No changes"
-msgstr ""
+msgstr "Métriques du test de performances du navigateur : Aucun changement"
msgid "ciReport|Checks"
-msgstr ""
+msgstr "Vérifications"
msgid "ciReport|Cluster Image Scanning"
-msgstr ""
+msgstr "Analyse des Images de la Grappe de serveurs"
msgid "ciReport|Code Quality"
-msgstr ""
+msgstr "Qualité de Code"
msgid "ciReport|Code Quality failed loading results"
msgstr ""
@@ -46315,16 +47162,16 @@ msgstr ""
msgid "ciReport|Code quality degraded due to 1 new issue"
msgid_plural "ciReport|Code quality degraded due to %d new issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La qualité de code s'est dégradée en raison d’1 nouveau ticket"
+msgstr[1] "La qualité de code s'est dégradée en raison de %d nouveaux tickets"
msgid "ciReport|Code quality improved due to 1 resolved issue"
msgid_plural "ciReport|Code quality improved due to %d resolved issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "La qualité de code s'est améliorée grâce à la résolution d'1 ticket"
+msgstr[1] "La qualité de code s'est améliorée grâce à la résolution de %d tickets"
msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
-msgstr ""
+msgstr "L'analyse de la qualité du code a détecté %{issueCount} changements dans les résultats fusionnés"
msgid "ciReport|Container Scanning"
msgstr ""
@@ -46336,22 +47183,22 @@ msgid "ciReport|Container scanning detects known vulnerabilities in your docker
msgstr "L’analyse des conteneurs permet la détection de vulnérabilités connues dans vos images Docker."
msgid "ciReport|Could not dismiss vulnerability because the associated pipeline no longer exists. Refresh the page and try again."
-msgstr ""
+msgstr "Impossible de rejeter la vulnérabilité car le pipeline associé n'existe plus. Actualisez la page et réessayez."
msgid "ciReport|Coverage Fuzzing"
-msgstr ""
+msgstr "Tests à données aléatoires guidés par la Couverture de code"
msgid "ciReport|Coverage fuzzing"
-msgstr ""
+msgstr "Tests à données aléatoires guidés par la couverture de code"
msgid "ciReport|Create Jira issue"
-msgstr ""
+msgstr "Créer un ticket Jira"
msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
msgstr ""
msgid "ciReport|Create issue"
-msgstr ""
+msgstr "Créer un ticket"
msgid "ciReport|DAST"
msgstr "DAST"
@@ -46378,7 +47225,7 @@ msgid "ciReport|Failed to load %{reportName} report"
msgstr "Impossible de charger le rapport %{reportName}"
msgid "ciReport|Failed to load Code Quality report"
-msgstr ""
+msgstr "Échec du chargement du rapport sur la Qualité du Code"
msgid "ciReport|Fixed"
msgstr ""
@@ -46387,13 +47234,16 @@ msgid "ciReport|Fixed:"
msgstr "Corrigé :"
msgid "ciReport|Found %{issuesWithCount}"
-msgstr ""
+msgstr "%{issuesWithCount} trouvés"
msgid "ciReport|Full Report"
+msgstr "Rapport complet"
+
+msgid "ciReport|Generic Report"
msgstr ""
msgid "ciReport|IaC Scanning"
-msgstr ""
+msgstr "Analyse IaC"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -46405,18 +47255,18 @@ msgid "ciReport|License Compliance failed loading results"
msgstr ""
msgid "ciReport|License Compliance test metrics results are being parsed"
-msgstr ""
+msgstr "Les résultats des métriques des tests de Conformité de Licence sont en cours d’analyse"
msgid "ciReport|Load Performance"
msgstr ""
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] ""
+msgstr[0] "Les métriques du test de performances de la charge ont détecté %{strong_start}%{changesFound}%{strong_end} modification"
+msgstr[1] "Les métriques du test de performances de la charge ont détecté %{strong_start}%{changesFound}%{strong_end} modifications"
msgid "ciReport|Load performance test metrics results are being parsed"
-msgstr ""
+msgstr "Les résultats des métriques des tests de performance de charge sont en cours d’analyse"
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -46428,10 +47278,10 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "Chargement du rapport %{reportName}"
msgid "ciReport|Loading Code Quality report"
-msgstr ""
+msgstr "Chargement du rapport de Qualité de Code"
msgid "ciReport|Manage Licenses"
-msgstr ""
+msgstr "Gérer les licences"
msgid "ciReport|Manage licenses"
msgstr "Gérer les licences"
@@ -46440,7 +47290,7 @@ msgid "ciReport|Manually added"
msgstr ""
msgid "ciReport|New"
-msgstr ""
+msgstr "Nouveau"
msgid "ciReport|No changes to Code Quality."
msgstr ""
@@ -46449,10 +47299,10 @@ msgid "ciReport|No changes to code quality"
msgstr "Aucun changement dans la qualité du code"
msgid "ciReport|No code quality issues found"
-msgstr ""
+msgstr "Aucun problème de qualité de code n'a été trouvé"
msgid "ciReport|RPS"
-msgstr ""
+msgstr "RPS"
msgid "ciReport|Resolve with merge request"
msgstr ""
@@ -46461,16 +47311,16 @@ msgid "ciReport|SAST"
msgstr "SAST"
msgid "ciReport|Secret Detection"
-msgstr ""
+msgstr "Détection de secret"
msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
-msgstr ""
+msgstr "La Détection de Secret détecte les secrets et les vulnérabilités d’identifiants dans votre code source."
msgid "ciReport|Secret detection"
-msgstr ""
+msgstr "Détection de Secret"
msgid "ciReport|Security reports failed loading results"
-msgstr ""
+msgstr "Les rapports de sécurité ont échoué à charger les résultats"
msgid "ciReport|Security scanning"
msgstr "Analyse de sécurité"
@@ -46479,10 +47329,10 @@ 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|Security scanning is loading"
-msgstr ""
+msgstr "L'analyse de sécurité est en cours de chargement"
msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
-msgstr ""
+msgstr "Affichage de %{fetchedItems} éléments sur %{totalItems}"
msgid "ciReport|Solution"
msgstr "Solution"
@@ -46491,10 +47341,10 @@ msgid "ciReport|Static Application Security Testing (SAST) detects known vulnera
msgstr "Le test de sécurité d’applications statique (Static Application Security Testing — SAST) a détecté une vulnérabilité connue dans votre application Web."
msgid "ciReport|TTFB P90"
-msgstr ""
+msgstr "TTFB P90"
msgid "ciReport|TTFB P95"
-msgstr ""
+msgstr "TTFB P95"
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr "Une erreur s’est produite lors de la création du ticket. Veuillez réessayer."
@@ -46506,13 +47356,13 @@ msgid "ciReport|There was an error dismissing the vulnerability. Please try agai
msgstr "Une erreur s’est produite lors du rejet de la vulnérabilité. Veuillez réessayer."
msgid "ciReport|There was an error fetching the codequality report."
-msgstr ""
+msgstr "Une erreur s’est produite lors de la récupération du rapport de qualité de code."
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Une erreur s’est produite lors de l’annulation du rejet. Veuillez réessayer."
msgid "ciReport|This report contains all Code Quality issues in the source branch."
-msgstr ""
+msgstr "Ce rapport contient tous les problèmes de Qualité de Code de la branche source."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
@@ -46523,16 +47373,16 @@ msgid "ciReport|View full report"
msgstr "Voir le rapport complet"
msgid "ciReport|in"
-msgstr ""
+msgstr "dans"
msgid "ciReport|is loading"
-msgstr ""
+msgstr "est en cours de chargement"
msgid "ciReport|is loading, errors when loading results"
-msgstr ""
+msgstr "est en cours de chargement, erreurs lors du chargement des résultats"
msgid "ci_database"
-msgstr ""
+msgstr "ci_database"
msgid "closed"
msgstr ""
@@ -46544,11 +47394,14 @@ msgid "closed issue"
msgstr "ticket fermé"
msgid "collect usage information"
-msgstr ""
+msgstr "collecter des informations d'utilisation"
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr "a commenté"
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46568,13 +47421,13 @@ msgid "container registry images"
msgstr ""
msgid "contains URLs that exceed the 1024 character limit (%{urls})"
-msgstr ""
+msgstr "contient des URL qui dépassent la limite de 1024 caractères (%{urls})"
msgid "contains invalid URLs (%{urls})"
-msgstr ""
+msgstr "contient des URL non valides (%{urls})"
msgid "contribute to this project."
-msgstr ""
+msgstr "contribue à ce projet."
msgid "could not read private key, is the passphrase correct?"
msgstr "impossible de lire la clef privée, la phrase secrète estâ€elle correcte ?"
@@ -46586,22 +47439,25 @@ msgid "created %{issuable_created} by %{author}"
msgstr "créé %{issuable_created} par %{author}"
msgid "created %{timeAgoString} by %{email} via %{user}"
-msgstr ""
+msgstr "créé %{timeAgoString} par %{email} via %{user}"
msgid "created %{timeAgo}"
msgstr ""
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "créé il y a %{timeAgo} par %{author}"
+
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr "créé %{timeAgo} par %{author} dans %{project_link}"
msgid "created by"
-msgstr ""
+msgstr "créé par"
msgid "daily"
msgstr ""
msgid "data"
-msgstr ""
+msgstr "données"
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46612,10 +47468,10 @@ msgstr[0] "jour"
msgstr[1] "jours"
msgid "days"
-msgstr ""
+msgstr "jours"
msgid "default branch"
-msgstr ""
+msgstr "branche par défaut"
msgid "deleted"
msgstr ""
@@ -46633,16 +47489,16 @@ msgid "disabled"
msgstr "désactivé"
msgid "does not exist"
-msgstr ""
+msgstr "n'existe pas"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
msgid "does not match dast_site.project"
-msgstr ""
+msgstr "ne correspond pas à dast_site.project"
msgid "does not match dast_site_validation.project"
-msgstr ""
+msgstr "ne correspond pas à dast_site_validation.project"
msgid "download it"
msgstr ""
@@ -46659,7 +47515,7 @@ msgid "element is not a hierarchy"
msgstr ""
msgid "eligible users"
-msgstr ""
+msgstr "utilisateurs éligibles"
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -46674,7 +47530,7 @@ msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
msgid "ending with a reserved file extension is not allowed."
-msgstr ""
+msgstr "se terminant par une extension de fichier réservée n'est pas autorisé."
msgid "entries cannot be larger than 255 characters"
msgstr ""
@@ -46686,34 +47542,34 @@ msgid "entries cannot contain HTML tags"
msgstr ""
msgid "epic"
-msgstr ""
+msgstr "épopée"
msgid "error"
msgstr ""
msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
-msgstr ""
+msgstr "%{slash_command} écrase le temps passé total."
msgid "example.com"
-msgstr ""
+msgstr "exemple.com"
msgid "exceeds maximum length (100 usernames)"
-msgstr ""
+msgstr "dépasse la longueur maximale (100 noms d'utilisateurs)"
msgid "exceeds the %{max_value_length} character limit"
-msgstr ""
+msgstr "dépasse la limite fixée à %{max_value_length} caractères"
msgid "exceeds the limit of %{bytes} bytes"
-msgstr ""
+msgstr "dépasse la limite de %{bytes} octets"
msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
-msgstr ""
+msgstr "dépasse la limite de %{bytes} octets pour le nom du répertoire \"%{dirname}\""
msgid "expired on %{timebox_due_date}"
msgstr ""
msgid "expires on %{timebox_due_date}"
-msgstr ""
+msgstr "arrive à échéance le %{timebox_due_date}"
msgid "failed"
msgstr ""
@@ -46722,10 +47578,10 @@ msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
msgid "failed to dismiss finding: %{message}"
-msgstr ""
+msgstr "a échoué à rejeter la découverte : %{message}"
msgid "failed to dismiss security finding: %{message}"
-msgstr ""
+msgstr "a échoué à rejeter la découverte de sécurité : %{message}"
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr ""
@@ -46742,7 +47598,7 @@ msgid "following"
msgstr ""
msgid "for"
-msgstr ""
+msgstr "pendant"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
msgstr ""
@@ -46767,32 +47623,32 @@ msgstr "de"
msgid "from %d job"
msgid_plural "from %d jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "à partir de %d tâche"
+msgstr[1] "à partir de %d tâches"
msgid "frontmatter"
-msgstr ""
+msgstr "frontmatter"
msgid "group"
msgstr ""
msgid "group access token"
-msgstr ""
+msgstr "jeton d'accès de groupe"
msgid "group access tokens"
-msgstr ""
+msgstr "jetons d'accès de groupe"
msgid "group members"
msgstr ""
msgid "groups"
-msgstr ""
+msgstr "groupes"
msgid "groups and projects"
-msgstr ""
+msgstr "groupes et projets"
msgid "groups only"
-msgstr ""
+msgstr "groupes uniquement"
msgid "had %{count} failed job"
msgid_plural "had %{count} failed jobs"
@@ -46800,7 +47656,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "has already been linked to another vulnerability"
-msgstr ""
+msgstr "dispose déjà d'un lien vers une autre vulnérabilité"
msgid "has already been taken"
msgstr ""
@@ -46812,40 +47668,40 @@ msgid "has already been taken as Suite"
msgstr ""
msgid "has been completed."
-msgstr ""
+msgstr "a fini."
msgid "has too deep level of nesting"
-msgstr ""
+msgstr "a un niveau d'imbrication trop profond"
msgid "help"
-msgstr ""
+msgstr "aide"
msgid "http:"
msgstr ""
msgid "http://www.example.com"
-msgstr ""
+msgstr "http://www.exemple.com"
msgid "https://bamboo.example.com"
-msgstr ""
+msgstr "https://bamboo.exemple.com"
msgid "https://your-bitbucket-server"
msgstr "https://votre-serveur-bitbucket"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
-msgstr ""
+msgstr "%{language} (traduit à %{percent_translated}%%)"
msgid "if"
-msgstr ""
+msgstr "si"
msgid "image diff"
msgstr ""
msgid "impersonation token"
-msgstr ""
+msgstr "jeton d'emprunt d'identité"
msgid "impersonation tokens"
-msgstr ""
+msgstr "jetons d'emprunt d'identité"
msgid "import flow"
msgstr "flux d’importation"
@@ -46865,7 +47721,7 @@ msgstr[0] "instance terminée"
msgstr[1] "instances terminées"
msgid "internal note"
-msgstr ""
+msgstr "note interne"
msgid "invalid milestone state `%{state}`"
msgstr ""
@@ -46880,7 +47736,7 @@ msgid "is an invalid IP address range"
msgstr ""
msgid "is blocked by"
-msgstr ""
+msgstr "est bloqué par"
msgid "is forbidden by a top-level group"
msgstr ""
@@ -46904,22 +47760,19 @@ msgid "is not allowed for sign-up. Please use your regular email address."
msgstr ""
msgid "is not allowed for this group."
-msgstr ""
+msgstr "n'est pas autorisé pour ce groupe."
msgid "is not allowed for this project."
-msgstr ""
+msgstr "n'est pas autorisé pour ce projet."
msgid "is not allowed since the group is not top-level group."
-msgstr ""
+msgstr "n'est pas autorisé car le groupe n'est pas un groupe de premier niveau."
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
-msgstr ""
+msgstr "n'est pas dans le groupe qui impose le Compte Géré de Groupe"
msgid "is not in the member group"
msgstr ""
@@ -46931,16 +47784,16 @@ msgid "is not valid. The iteration group has to match the iteration cadence grou
msgstr ""
msgid "is read-only"
-msgstr ""
+msgstr "est en lecture seule"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
-msgstr ""
+msgstr "est de taille trop longue (%{current_value}). La taille maximale est de %{max_size}."
msgid "is too long (%{size}). The maximum size is %{max_size}."
-msgstr ""
+msgstr "est de taille trop longue (%{size}). La taille maximale est de %{max_size}."
msgid "is too long (maximum is %{count} characters)"
-msgstr ""
+msgstr "est trop long (le maximum est de %{count} caractères)"
msgid "is too long (maximum is 100 entries)"
msgstr ""
@@ -46949,13 +47802,13 @@ msgid "is too long (maximum is 1000 entries)"
msgstr ""
msgid "issue"
-msgstr ""
+msgstr "ticket"
msgid "issues at risk"
-msgstr ""
+msgstr "tickets à risque"
msgid "issues need attention"
-msgstr ""
+msgstr "Les tickets nécessitent une attention"
msgid "issues on track"
msgstr ""
@@ -46979,13 +47832,13 @@ msgid "jigsaw is not defined"
msgstr ""
msgid "kuromoji custom analyzer"
-msgstr ""
+msgstr "analyseur personnalisé kuromoji"
msgid "last commit:"
-msgstr ""
+msgstr "dernier commit :"
msgid "latest"
-msgstr ""
+msgstr "plus récent"
msgid "latest deployment"
msgstr "dernier déploiement"
@@ -46997,17 +47850,22 @@ msgid "leave %{group_name}"
msgstr ""
msgid "less than a minute"
-msgstr ""
+msgstr "moins d'une minute"
msgid "level: %{level}"
-msgstr ""
+msgstr "niveau : %{level}"
msgid "lfs objects"
-msgstr ""
+msgstr "objets lfs"
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "ligne"
+msgstr[1] "lignes"
+
msgid "load it anyway"
msgstr ""
@@ -47018,21 +47876,21 @@ msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
msgid "main_database"
-msgstr ""
+msgstr "main_database"
msgid "manual"
msgstr ""
msgid "math|Displaying this math block may cause performance issues on this page"
-msgstr ""
+msgstr "L'affichage de cet élément mathématique peut entraîner des problèmes de performances sur cette page"
msgid "math|There was an error rendering this math block"
msgstr ""
msgid "member"
msgid_plural "members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "membre"
+msgstr[1] "membres"
msgid "merge request"
msgid_plural "merge requests"
@@ -47043,13 +47901,16 @@ msgid "mergedCommitsAdded| (commits were squashed)"
msgstr ""
msgid "metric_id must be unique across a project"
-msgstr ""
+msgstr "metric_id doit être unique au sein d'un projet"
+
+msgid "milestone should belong either to a project or a group."
+msgstr "le jalon doit appartenir à un projet ou à un groupe."
msgid "missing"
msgstr ""
msgid "months"
-msgstr ""
+msgstr "mois"
msgid "most recent deployment"
msgstr ""
@@ -47061,31 +47922,31 @@ msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
msgstr ""
msgid "mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit"
-msgstr ""
+msgstr "%{strongStart}1%{strongEnd} commit de fusion"
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
-msgstr ""
+msgstr "Modifications fusionnées dans %{targetBranch} avec %{mergeCommitSha}%{squashedCommits}."
msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
-msgstr ""
+msgstr "Les modifications n’ont pas été fusionnées dans %{targetBranch}."
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
-msgstr ""
+msgstr "Cette demande de fusion ne contient aucune modification."
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
-msgstr ""
+msgstr "Utilisez les demandes de fusion pour proposer des modifications à votre projet et discutez-en avec votre équipe. Pour apporter les modifications, poussez un commit ou modifiez cette demande de fusion pour utiliser une autre branche. Avec la %{linkStart}CI/CD%{linkEnd}, testez automatiquement vos modifications avant la fusion."
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
-msgstr ""
+msgstr "%{boldHeaderStart}Il semble ne pas y avoir de pipeline ici.%{boldHeaderEnd}"
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "%{linkStart}Configurer maintenant%{linkEnd} pour analyser votre code source à la recherche de failles de sécurité connues."
msgid "mrWidget|%{mergeError}."
-msgstr ""
+msgstr "%{mergeError}."
msgid "mrWidget|%{mergeError}. Try again."
-msgstr ""
+msgstr "%{mergeError}. Réessayez."
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}a diminué%{emphasisEnd} de %{memoryFrom}MO à %{memoryTo}MO"
@@ -47100,13 +47961,13 @@ msgid "mrWidget|A merge train is a queued list of merge requests waiting to be m
msgstr ""
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
-msgstr ""
+msgstr "Un nouveau train de fusion a démarré et cette demande de fusion est la première de la file d’attente."
msgid "mrWidget|Added to the merge train by %{merge_author}"
-msgstr ""
+msgstr "Ajouté au train de fusion par %{merge_author}"
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
-msgstr ""
+msgstr "Ajoutée au train de fusion. Il y a %{mergeTrainPosition} demandes de fusion en attente de fusion"
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -47118,16 +47979,16 @@ msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Une erreur est survenue lors de l’envoi de votre approbation."
msgid "mrWidget|Approval is optional"
-msgstr ""
+msgstr "L'approbation est facultative"
msgid "mrWidget|Approval password is invalid."
msgstr ""
msgid "mrWidget|Approval rule %{rules} is invalid. GitLab has approved this rule automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "La règle d’approbation %{rules} n'est pas valide. GitLab l'a approuvée automatiquement pour débloquer la demande de fusion. %{link}"
msgid "mrWidget|Approval rules %{rules} are invalid. GitLab has approved these rules automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "Les règles d’approbation %{rules} ne sont pas valides. GitLab les a approuvées automatiquement pour débloquer la demande de fusion. %{link}"
msgid "mrWidget|Approve"
msgstr "Approuver"
@@ -47139,22 +48000,22 @@ msgid "mrWidget|Approved by"
msgstr "Approuvée par"
msgid "mrWidget|Approved by you"
-msgstr ""
+msgstr "Approuvé par vous"
msgid "mrWidget|Approved by you and others"
-msgstr ""
+msgstr "Approuvé par vous et d'autres personnes"
msgid "mrWidget|Assign yourself to these issues"
-msgstr ""
+msgstr "Assignez-vous sur ces tickets"
msgid "mrWidget|Assign yourself to this issue"
-msgstr ""
+msgstr "Assignez-vous sur ce ticket"
msgid "mrWidget|Cancel auto-merge"
-msgstr ""
+msgstr "Annuler la fusion automatique"
msgid "mrWidget|Checking if merge request can be merged…"
-msgstr ""
+msgstr "Vérification de la possibilité de fusionner la demande de fusion…"
msgid "mrWidget|Cherry-pick"
msgstr "Picorer"
@@ -47170,11 +48031,11 @@ msgstr "Fermée par"
msgid "mrWidget|Closes issue"
msgid_plural "mrWidget|Closes issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ferme le ticket"
+msgstr[1] "Ferme les tickets"
msgid "mrWidget|Create issue to resolve all threads"
-msgstr ""
+msgstr "Créer un ticket pour résoudre tous les fils de conversation"
msgid "mrWidget|Delete source branch"
msgstr ""
@@ -47186,114 +48047,114 @@ msgid "mrWidget|Did not close"
msgstr "N’a pas résolu"
msgid "mrWidget|Dismiss"
-msgstr ""
+msgstr "Rejeter"
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 ""
+msgstr "GitLab %{linkStart}CI/CD peut construire, tester et déployer automatiquement votre application.%{linkEnd} Cela ne prend que quelques minutes pour démarrer, et nous pouvons vous aider à créer un fichier de configuration de pipeline."
msgid "mrWidget|Hide %{widget} details"
-msgstr ""
+msgstr "Masquer les détails de %{widget}"
msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
-msgstr ""
+msgstr "Si la branche %{type} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement en utilisant la ligne de commande."
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 ""
+msgstr "Si le dernier pipeline a été exécuté sur le projet divergent, il pourrait ne pas être exact. Avant la fusion, nous vous conseillons d'exécuter un pipeline sur ce projet."
msgid "mrWidget|Jump to first unresolved thread"
-msgstr ""
+msgstr "Aller au premier fil de conversation non résolu"
msgid "mrWidget|Learn more"
-msgstr ""
+msgstr "En savoir plus"
msgid "mrWidget|Loading deployment statistics"
msgstr "Chargement des statistiques de déploiement"
msgid "mrWidget|Mark as ready"
-msgstr ""
+msgstr "Marquer comme prêt"
msgid "mrWidget|Members who can merge are allowed to add commits."
-msgstr ""
+msgstr "Les membres qui peuvent fusionner sont autorisés à ajouter des commits."
msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Mentionne le ticket"
+msgstr[1] "Mentionne les tickets"
msgid "mrWidget|Merge blocked: a Jira issue key must be mentioned in the title or description."
-msgstr ""
+msgstr "Fusion bloquée : une clé de ticket Jira doit être citée dans le titre ou dans la description."
msgid "mrWidget|Merge blocked: all required approvals must be given."
-msgstr ""
+msgstr "Fusion bloquée : toutes les approbations requises doivent être données."
msgid "mrWidget|Merge blocked: all threads must be resolved."
-msgstr ""
+msgstr "Fusion bloquée : tous les fils de conversation doivent être résolus."
msgid "mrWidget|Merge blocked: denied licenses must be removed."
-msgstr ""
+msgstr "Fusion bloquée : les licences refusées doivent être supprimées."
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "Fusion bloquée : la fusion en avance rapide n’est pas possible. Pour fusionner cette demande, rebasez localement au préalable."
msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
-msgstr ""
+msgstr "Fusion bloquée : des conflits de fusion doivent être résolus."
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
-msgstr ""
+msgstr "Fusion bloquée : le pipeline doit réussir. Il est en attente d'une action manuelle pour continuer."
msgid "mrWidget|Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
-msgstr ""
+msgstr "Fusion bloquée : le pipeline doit réussir. Poussez une validation qui corrige l'erreur, ou %{linkStart}explorez d'autres solutions.%{linkEnd}"
msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
-msgstr ""
+msgstr "Fusion bloquée : vous ne pouvez fusionner qu'après résolution des éléments ci-dessus."
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
-msgstr ""
+msgstr "Fusion indisponible : les demandes de fusion sur les projets archivés sont en lecture seule."
msgid "mrWidget|Merged by"
msgstr "Fusionnée par"
msgid "mrWidget|Merging! Changes are being shipped…"
-msgstr ""
+msgstr "Fusion en cours ! Les modifications sont en cours d'application…"
msgid "mrWidget|Merging! Changes will land soon…"
-msgstr ""
+msgstr "Fusion en cours ! Les modifications seront bientôt faites…"
msgid "mrWidget|Merging! Drum roll, please…"
-msgstr ""
+msgstr "Fusion en cours ! Roulement de tambour…"
msgid "mrWidget|Merging! Everything's good…"
-msgstr ""
+msgstr "Fusion en cours ! Tout va bien…"
msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
-msgstr ""
+msgstr "Fusion ! Décollage dans 5… 4… 3…"
msgid "mrWidget|Merging! Take a deep breath and relax…"
-msgstr ""
+msgstr "Fusion ! Respirez profondément et détendez-vous…"
msgid "mrWidget|Merging! The changes are leaving the station…"
-msgstr ""
+msgstr "Fusion ! Les modifications sont en route…"
msgid "mrWidget|Merging! This is going to be great…"
-msgstr ""
+msgstr "Fusion en cours ! Ça va bien se passer…"
msgid "mrWidget|Merging! We're almost there…"
-msgstr ""
+msgstr "Fusion en cours ! Nous y sommes presque…"
msgid "mrWidget|More information"
-msgstr ""
+msgstr "Plus d'informations"
msgid "mrWidget|No users match the rule's criteria."
-msgstr ""
+msgstr "Aucun utilisateur ne correspond aux critères de la règle."
msgid "mrWidget|Please restore it or use a different %{type} branch."
-msgstr ""
+msgstr "Veuillez le restaurer ou utiliser une branche %{type} différente."
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr "Prête à être fusionnée automatiquement. Demandez à quelqu’un ayant un accès en écriture à ce dépôt d’effectuer cette fusion"
@@ -47326,25 +48187,25 @@ msgid "mrWidget|Revoke approval"
msgstr ""
msgid "mrWidget|SAST and Secret Detection is not enabled."
-msgstr ""
+msgstr "SAST et la Détection de Secrets ne sont pas activés."
msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the pipeline succeeds"
-msgstr ""
+msgstr "Configuré par %{merge_author} pour être ajouté au train de fusion lorsque le pipeline réussit"
msgid "mrWidget|Set by %{merge_author} to be merged automatically when the pipeline succeeds"
-msgstr ""
+msgstr "Configurée par %{merge_author} pour être fusionnée automatiquement lorsque le pipeline réussit"
msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline succeeds"
-msgstr ""
+msgstr "Configuré par %{merge_author} pour démarrer un train de fusion lorsque le pipeline réussit"
msgid "mrWidget|Show %{widget} details"
-msgstr ""
+msgstr "Afficher les détails de %{widget}"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
-msgstr ""
+msgstr "La branche %{type} %{codeStart}%{name}%{codeEnd} n'existe pas."
msgid "mrWidget|The source branch is %{link} the target branch"
-msgstr ""
+msgstr "La branche source est %{link} à la branche cible"
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
@@ -47356,70 +48217,73 @@ msgid "mrWidget|To change these default messages, edit the templates for both th
msgstr ""
msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Pour modifier ce message par défaut, éditez le modèle des messages pour les validations de fusion. %{linkStart}En savoir plus.%{linkEnd}"
msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Pour modifier ce message par défaut, éditez le modèle des messages pour les squash de validations. %{linkStart}En savoir plus.%{linkEnd}"
msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
-msgstr ""
+msgstr "Les utilisateurs qui peuvent écrire dans les branches source ou cible peuvent résoudre les conflits."
msgid "mrWidget|What is a merge train?"
-msgstr ""
+msgstr "Qu'est-ce qu'un train de fusion ?"
msgid "mrWidget|Your password"
-msgstr ""
+msgstr "Votre mot de passe"
msgid "must be a Debian package"
-msgstr ""
+msgstr "doit être un paquet Debian"
msgid "must be a boolean value"
-msgstr ""
+msgstr "doit être une valeur booléenne"
msgid "must be a root namespace"
-msgstr ""
+msgstr "doit être un espace de noms racine"
msgid "must be a valid IPv4 or IPv6 address"
-msgstr ""
+msgstr "doit être une adresse IPv4 ou IPv6 valide"
msgid "must be a valid json schema"
-msgstr ""
+msgstr "doit être un schéma json valide"
msgid "must be after start"
msgstr ""
msgid "must be an email you have verified"
-msgstr ""
+msgstr "doit être un courriel que vous avez vérifié"
msgid "must be greater than start date"
msgstr ""
msgid "must be inside the fork network"
-msgstr ""
+msgstr "doit se trouver à l'intérieur d'un réseau de divergences"
msgid "must be less than the limit of %{tag_limit} tags"
-msgstr ""
+msgstr "doit être inférieur à la limite de %{tag_limit} étiquettes"
msgid "must be set for a project namespace"
-msgstr ""
+msgstr "doit être défini pour un espace de noms de projet"
msgid "must be unique by status and elapsed time within a policy"
-msgstr ""
+msgstr "doit être unique au niveau état et temps écoulé dans une politique"
msgid "must have a repository"
-msgstr ""
+msgstr "doit avoir un dépôt"
msgid "must match %{association}.project_id"
-msgstr ""
+msgstr "doit correspondre à %{association}.project_id"
+
+msgid "must not contain commonly used combinations of words and letters"
+msgstr "ne doit pas contenir des combinaisons de mots ou de lettres couramment utilisées"
msgid "my-awesome-group"
-msgstr ""
+msgstr "mon-super-groupe"
msgid "my-channel"
-msgstr ""
+msgstr "mon-canal"
msgid "my-topic"
-msgstr ""
+msgstr "mon-sujet"
msgid "need attention"
msgstr ""
@@ -47428,10 +48292,10 @@ msgid "needs to be between 10 minutes and 1 month"
msgstr ""
msgid "never"
-msgstr ""
+msgstr "jamais"
msgid "never expires"
-msgstr ""
+msgstr "n'expire jamais"
msgid "new merge request"
msgstr "nouvelle demande de fusion"
@@ -47440,13 +48304,13 @@ msgid "no expiration"
msgstr ""
msgid "no name set"
-msgstr ""
+msgstr "aucun nom défini"
msgid "no one can merge"
msgstr ""
msgid "no scopes selected"
-msgstr ""
+msgstr "aucune portée sélectionnée"
msgid "none"
msgstr "aucun"
@@ -47464,7 +48328,7 @@ msgid "nounSeries|%{firstItem} and %{lastItem}"
msgstr ""
msgid "nounSeries|%{item}"
-msgstr ""
+msgstr "%{item}"
msgid "nounSeries|%{item}, %{nextItem}"
msgstr ""
@@ -47476,16 +48340,16 @@ msgid "on track"
msgstr ""
msgid "only %{parent_types} can be parent of Task."
-msgstr ""
+msgstr "seuls des %{parent_types} peuvent être parents d'une Tâche."
msgid "only Task can be assigned as a child in hierarchy."
-msgstr ""
+msgstr "seule une Tâche peut être assignée en tant qu'enfant dans une hiérarchie."
msgid "only available on top-level groups."
-msgstr ""
+msgstr "uniquement disponible pour les groupes de niveau supérieur."
msgid "open issue"
-msgstr ""
+msgstr "ouvrir un ticket"
msgid "or"
msgstr ""
@@ -47493,19 +48357,16 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "sur un total de %d test"
msgstr[1] "sur un total de %d tests"
msgid "packages"
-msgstr ""
+msgstr "paquets"
msgid "pages"
-msgstr ""
+msgstr "pages"
msgid "parent"
msgid_plural "parents"
@@ -47513,10 +48374,10 @@ msgstr[0] "parent"
msgstr[1] "parents"
msgid "parent already has maximum number of children."
-msgstr ""
+msgstr "le parent a déjà le nombre maximal d'enfants."
msgid "parent must be in the same project as child."
-msgstr ""
+msgstr "le parent doit être dans le même projet que l'enfant."
msgid "password"
msgstr "mot de passe"
@@ -47525,45 +48386,45 @@ msgid "pending comment"
msgstr ""
msgid "pending deletion"
-msgstr ""
+msgstr "en attente de suppression"
msgid "personal access token"
-msgstr ""
+msgstr "jeton d'accès personnel"
msgid "personal access tokens"
-msgstr ""
+msgstr "jetons d'accès personnels"
msgid "pipeline"
msgstr ""
msgid "pipeline schedules documentation"
-msgstr ""
+msgstr "documentation des planifications de pipeline"
msgid "pipelineEditorWalkthrough|Let's do this!"
msgstr ""
msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
-msgstr ""
+msgstr "Voir comment fonctionnent les pipelines GitLab"
msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
-msgstr ""
+msgstr "Ce fichier %{codeStart}.gitlab-ci.yml%{codeEnd} crée un simple pipeline de test."
msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
-msgstr ""
+msgstr "Utilisez le bouton %{boldStart}valider les modifications%{boldEnd} en bas de la page pour lancer le pipeline."
msgid "pipelineEditorWalkthrough|You can use the file tree to view your pipeline configuration files. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "Vous pouvez utiliser l'arborescence des fichiers pour voir vos fichiers de configuration de pipelines. %{linkStart}En savoir plus%{linkEnd}"
msgid "point"
msgid_plural "points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "point"
+msgstr[1] "points"
msgid "previously merged commits"
-msgstr ""
+msgstr "commits précédemment fusionnés"
msgid "private"
-msgstr ""
+msgstr "privé"
msgid "private key does not match certificate."
msgstr "la clef privée ne correspond pas au certificat."
@@ -47577,43 +48438,43 @@ msgstr[0] "projet"
msgstr[1] "projets"
msgid "project access token"
-msgstr ""
+msgstr "jeton d'accès au projet"
msgid "project access tokens"
-msgstr ""
+msgstr "jetons d'accès au projet"
msgid "project bots cannot be added to other groups / projects"
msgstr ""
msgid "project is read-only"
-msgstr ""
+msgstr "le projet est en lecture seule"
msgid "project members"
-msgstr ""
+msgstr "membres du projet"
msgid "project name"
-msgstr ""
+msgstr "nom du projet"
msgid "project namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "l'espace de noms du projet ne peut pas être le parent d'un autre espace de noms"
msgid "projects"
-msgstr ""
+msgstr "projets"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
-msgstr ""
+msgstr "reCAPTCHA contribue à empêcher le remplissage automatisé des identifiants."
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "Clé privée reCAPTCHA"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "Clé du site reCAPTCHA"
msgid "recent activity"
-msgstr ""
+msgstr "activité récente"
msgid "register"
msgstr ""
@@ -47631,7 +48492,7 @@ msgid "remove due date"
msgstr "supprimer la date d’échéance"
msgid "remove start date"
-msgstr ""
+msgstr "supprimer la date de début"
msgid "remove weight"
msgstr "supprimer le poids"
@@ -47639,6 +48500,9 @@ msgstr "supprimer le poids"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47654,7 +48518,7 @@ msgid "reply should have same confidentiality as top-level note"
msgstr ""
msgid "repositories"
-msgstr ""
+msgstr "dépôts"
msgid "repository:"
msgstr ""
@@ -47666,52 +48530,57 @@ msgid "satisfied"
msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
-msgstr ""
+msgstr "scan-execution-policy : politique non appliquée, le fichier %{policy_path} n'est pas valide"
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
-msgstr ""
+msgstr "scan-execution-policy : politique non appliquée, le fichier %{policy_path} est manquant"
+
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "siège"
+msgstr[1] "sièges"
msgid "security Reports|There was an error creating the merge request"
msgstr ""
msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
-msgstr ""
+msgstr "selective_code_owner_removals ne peut être activé que si retain_approvals_on_push est activé"
msgid "severity|Blocker"
-msgstr ""
+msgstr "Bloquante"
msgid "severity|Critical"
-msgstr ""
+msgstr "Critique"
msgid "severity|High"
-msgstr ""
+msgstr "Haute"
msgid "severity|Info"
-msgstr ""
+msgstr "Info"
msgid "severity|Low"
-msgstr ""
+msgstr "Basse"
msgid "severity|Major"
-msgstr ""
+msgstr "Majeure"
msgid "severity|Medium"
-msgstr ""
+msgstr "Moyenne"
msgid "severity|Minor"
-msgstr ""
+msgstr "Mineure"
msgid "severity|None"
msgstr "Aucune"
msgid "severity|Unknown"
-msgstr ""
+msgstr "Inconnue"
msgid "should be an array of %{object_name} objects"
msgstr ""
msgid "should be an array of existing usernames. %{invalid} does not exist"
-msgstr ""
+msgstr "devrait être un tableau de noms d'utilisateurs existants. %{invalid} n'existe pas"
msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
@@ -47723,13 +48592,13 @@ msgid "show fewer"
msgstr ""
msgid "show less"
-msgstr ""
+msgstr "afficher moins"
msgid "sign in"
msgstr ""
msgid "smartcn custom analyzer"
-msgstr ""
+msgstr "analyseur personnalisé smartcn"
msgid "source"
msgstr "source"
@@ -47741,7 +48610,7 @@ msgid "specified top is not part of the tree"
msgstr ""
msgid "spendCommand|%{slash_command} adds or subtracts time already spent."
-msgstr ""
+msgstr "%{slash_command} ajoute ou soustrait du temps déjà passé."
msgid "ssh:"
msgstr ""
@@ -47756,7 +48625,7 @@ msgid "starts on %{timebox_start_date}"
msgstr ""
msgid "structure is too large"
-msgstr ""
+msgstr "la structure est trop grande"
msgid "stuck"
msgstr ""
@@ -47771,37 +48640,40 @@ msgid "suggestPipeline|2/2: Commit your changes"
msgstr ""
msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
-msgstr ""
+msgstr "Choisissez %{boldStart}Qualité de Code%{boldEnd} pour ajouter un pipeline qui teste la qualité de votre code."
msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
-msgstr ""
+msgstr "Le modèle est prêt ! Vous pouvez maintenant l'envoyer pour créer votre premier pipeline."
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
+msgstr "Nous ajoutons un fichier de configuration GitLab CI pour ajouter un pipeline au projet. Vous pouvez le créer manuellement, mais nous vous recommandons de commencer avec un modèle GitLab qui fonctionnera aussitôt."
+
+msgid "supported SSH public key."
msgstr ""
msgid "tag name"
msgstr ""
msgid "terraform states"
-msgstr ""
+msgstr "états terraform"
msgid "the correct format."
-msgstr ""
+msgstr "le format correct."
msgid "the following epics"
-msgstr ""
+msgstr "les épopées suivantes"
msgid "the following incidents or issues"
-msgstr ""
+msgstr "les tickets ou incidents suivants"
msgid "the following issues"
-msgstr ""
+msgstr "les tickets suivants"
msgid "the wiki"
-msgstr ""
+msgstr "le wiki"
msgid "then"
-msgstr ""
+msgstr "ensuite"
msgid "this document"
msgstr "ce document"
@@ -47810,25 +48682,25 @@ msgid "time summary"
msgstr ""
msgid "today"
-msgstr ""
+msgstr "aujourd'hui"
msgid "toggle collapse"
msgstr ""
msgid "total must be less than or equal to %{size}"
-msgstr ""
+msgstr "le total doit être inférieur ou égal à %{size}"
msgid "triggered"
msgstr ""
msgid "two-factor authentication settings"
-msgstr ""
+msgstr "paramètres d'authentification à deux facteurs"
msgid "type must be Debian"
msgstr ""
msgid "type parameter is missing and is required"
-msgstr ""
+msgstr "le paramètre de type est manquant et est requis"
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -47837,31 +48709,36 @@ msgid "updated"
msgstr ""
msgid "updated %{timeAgo}"
-msgstr ""
+msgstr "mis à jour %{timeAgo}"
msgid "updated %{time_ago}"
-msgstr ""
+msgstr "mis à jour %{time_ago}"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] "utilisateur"
+msgstr[1] " utilisateurs"
+
msgid "user avatar"
msgstr ""
msgid "user namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "l'espace de noms de l'utilisateur ne peut pas être le parent d'un autre espace de noms"
msgid "username"
msgstr "nom d’utilisateur"
msgid "v%{version} published %{timeAgo}"
-msgstr ""
+msgstr "v%{version} publiée %{timeAgo}"
msgid "value for '%{storage}' must be an integer"
-msgstr ""
+msgstr "la valeur de « %{storage} » doit être un nombre entier"
msgid "value for '%{storage}' must be between 0 and 100"
-msgstr ""
+msgstr "la valeur de « %{storage} » doit être comprise entre 0 et 100"
msgid "verify ownership"
msgstr ""
@@ -47885,33 +48762,33 @@ msgid "view the source"
msgstr ""
msgid "visibility"
-msgstr ""
+msgstr "visibilité"
msgid "vulnerability"
msgid_plural "vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "vulnérabilité"
+msgstr[1] "vulnérabilités"
msgid "vulnerability|Add a comment"
-msgstr ""
+msgstr "Ajouter un commentaire"
msgid "vulnerability|Add a comment or reason for dismissal"
msgstr ""
msgid "vulnerability|Add comment"
-msgstr ""
+msgstr "Ajouter un commentaire"
msgid "vulnerability|Add comment & dismiss"
msgstr ""
msgid "vulnerability|Add comment and dismiss"
-msgstr ""
+msgstr "Ajouter un commentaire et rejeter"
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
msgid "vulnerability|Save comment"
-msgstr ""
+msgstr "vulnerability|Enregistrer le commentaire"
msgid "vulnerability|Undo dismiss"
msgstr ""
@@ -47923,10 +48800,10 @@ msgid "was scheduled to merge after pipeline succeeds by"
msgstr ""
msgid "weekly"
-msgstr ""
+msgstr "hebdomadaire"
msgid "wiki page"
-msgstr ""
+msgstr "page wiki"
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "avec %{additions} ajouts, %{deletions} suppressions."
@@ -47941,20 +48818,20 @@ msgid "yaml invalid"
msgstr ""
msgid "your GitLab instance"
-msgstr ""
+msgstr "votre instance GitLab"
msgid "your group (%{group_name})"
-msgstr ""
+msgstr "votre groupe (%{group_name})"
msgid "your settings"
-msgstr ""
+msgstr "vos paramètres"
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
msgid "✔"
-msgstr ""
+msgstr "✔"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a494df7b1ff..545a2ca4855 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -138,6 +138,16 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approval required"
+msgid_plural "%d approvals required"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -508,6 +518,9 @@ msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%{chartTitle} no data series"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -1035,6 +1048,9 @@ msgstr[1] ""
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "%{strong_open}%{group_name}%{strong_close} projects:"
+msgstr ""
+
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
msgstr[0] ""
@@ -1096,9 +1112,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1145,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1237,6 +1253,9 @@ msgstr ""
msgid "'%{template_name}' is unknown or invalid"
msgstr ""
+msgid "'%{value}' days of inactivity must be greater than or equal to 90"
+msgstr ""
+
msgid "(%d closed)"
msgid_plural "(%d closed)"
msgstr[0] ""
@@ -1275,6 +1294,9 @@ msgstr ""
msgid "(max size 15 MB)"
msgstr ""
+msgid "(no user)"
+msgstr ""
+
msgid "(optional)"
msgstr ""
@@ -1560,6 +1582,9 @@ msgstr ""
msgid "404|Make sure the address is correct and the page hasn't moved."
msgstr ""
+msgid "404|Not found"
+msgstr ""
+
msgid "404|Page Not Found"
msgstr ""
@@ -1674,9 +1699,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1695,6 +1717,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -1908,6 +1939,9 @@ msgstr ""
msgid "Acceptable for use in this project"
msgstr ""
+msgid "Access Denied"
+msgstr ""
+
msgid "Access Git repositories or the API."
msgstr ""
@@ -2019,15 +2053,9 @@ 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 "AccessibilityReport|Learn more"
-msgstr ""
-
msgid "AccessibilityReport|Message: %{message}"
msgstr ""
-msgid "AccessibilityReport|New"
-msgstr ""
-
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
msgstr ""
@@ -2376,12 +2404,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2478,6 +2500,12 @@ msgstr ""
msgid "Adds a Zoom meeting."
msgstr ""
+msgid "Adds a resource link"
+msgstr ""
+
+msgid "Adds a resource link for this incident."
+msgstr ""
+
msgid "Adds a timeline event to incident."
msgstr ""
@@ -3456,9 +3484,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3885,6 +3925,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3909,7 +3952,7 @@ msgstr ""
msgid "All users with matching cards"
msgstr ""
-msgid "Allow \"%{group_name}\" to sign you in"
+msgid "Allow %{strongOpen}%{group_name}%{strongClose} to sign you in?"
msgstr ""
msgid "Allow access to members of the following group"
@@ -3960,6 +4003,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4206,6 +4252,9 @@ msgstr ""
msgid "An error occurred while fetching terraform reports."
msgstr ""
+msgid "An error occurred while fetching the health status."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -4493,6 +4542,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4716,6 +4768,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5359,6 +5414,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6030,6 +6088,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6749,33 +6810,84 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
+msgid "BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Merge Request Approvals"
+msgstr ""
+
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6785,6 +6897,21 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Required approvals (%{total})"
+msgstr ""
+
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6938,6 +7065,9 @@ msgstr ""
msgid "Broadcast Messages"
msgstr ""
+msgid "BroadcastMessages|There was an issue deleting this message, please try again later."
+msgstr ""
+
msgid "Browse Directory"
msgstr ""
@@ -7085,6 +7215,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7258,6 +7391,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7528,7 +7664,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -9734,6 +9870,9 @@ msgstr ""
msgid "Complete verification to sign up."
msgstr ""
+msgid "Complete with errors"
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9803,7 +9942,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10121,6 +10260,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10907,6 +11049,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11123,6 +11268,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11135,6 +11283,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -11875,6 +12029,9 @@ msgstr ""
msgid "DashboardProjects|Trending"
msgstr ""
+msgid "Dashboards"
+msgstr ""
+
msgid "Dashboard|%{firstProject} and %{secondProject}"
msgstr ""
@@ -12109,6 +12266,9 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scan Method"
+msgstr ""
+
msgid "DastProfiles|Scan method"
msgstr ""
@@ -12390,6 +12550,9 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
msgid "DateRange|%{start_date}–%{end_date}"
msgstr ""
@@ -12411,6 +12574,9 @@ msgstr ""
msgid "Days"
msgstr ""
+msgid "Days of inactivity before deactivation"
+msgstr ""
+
msgid "Days to merge"
msgstr ""
@@ -12444,6 +12610,9 @@ msgstr ""
msgid "Decrease"
msgstr ""
+msgid "Default - Never run"
+msgstr ""
+
msgid "Default CI/CD configuration file"
msgstr ""
@@ -13068,6 +13237,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13113,6 +13285,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13134,6 +13309,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13149,6 +13327,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13405,25 +13589,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13444,7 +13625,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13465,12 +13646,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13543,6 +13718,9 @@ msgstr ""
msgid "DevOps adoption"
msgstr ""
+msgid "Developer"
+msgstr ""
+
msgid "Development"
msgstr ""
@@ -13989,6 +14167,9 @@ msgstr ""
msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
msgstr ""
+msgid "Do not show again"
+msgstr ""
+
msgid "Do you want to remove this deploy key?"
msgstr ""
@@ -14391,6 +14572,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14403,6 +14587,12 @@ msgstr ""
msgid "Edited %{timeago}"
msgstr ""
+msgid "Edited %{timeago} by %{author}"
+msgstr ""
+
+msgid "Edited by %{author}"
+msgstr ""
+
msgid "Editing"
msgstr ""
@@ -14646,6 +14836,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14730,22 +14923,40 @@ msgstr ""
msgid "Enable version check"
msgstr ""
-msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
+msgid "EnableReviewApp|Add a job in your CI/CD configuration that:"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet"
+msgstr ""
+
+msgid "EnableReviewApp|Have access to infrastructure that can host and deploy the review apps."
msgstr ""
-msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
+msgid "EnableReviewApp|Install and configure a runner to do the deployment."
msgstr ""
-msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
+msgid "EnableReviewApp|Make sure your project has an environment configured with the target URL set to your website URL. If not, create a new one before continuing."
msgstr ""
-msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
+msgid "EnableReviewApp|Only runs for feature branches or merge requests."
msgstr ""
-msgid "EnableReviewApp|Close"
+msgid "EnableReviewApp|Recommended: Set up a job that manually stops the Review Apps."
msgstr ""
-msgid "EnableReviewApp|Copy snippet text"
+msgid "EnableReviewApp|Review apps are dynamic environments that you can use to provide a live preview of changes made in a feature branch."
+msgstr ""
+
+msgid "EnableReviewApp|To configure a dynamic review app, you must:"
+msgstr ""
+
+msgid "EnableReviewApp|Uses a predefined CI/CD variable like %{codeStart}$(CI_COMMIT_REF_SLUG)%{codeEnd} to dynamically create the review app environments. For example, for a configuration using merge request pipelines:"
+msgstr ""
+
+msgid "EnableReviewApp|Using a static site?"
+msgstr ""
+
+msgid "EnableReviewApp|View more example projects"
msgstr ""
msgid "Enabled"
@@ -14973,6 +15184,9 @@ msgstr ""
msgid "Environments|Commit"
msgstr ""
+msgid "Environments|Copy live environment URL"
+msgstr ""
+
msgid "Environments|Delete"
msgstr ""
@@ -14994,6 +15208,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15027,6 +15244,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15051,6 +15271,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15144,6 +15367,9 @@ msgstr ""
msgid "Epics|Add an existing epic"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr ""
@@ -15327,9 +15553,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred while updating the %{issuableType} status"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -15636,6 +15859,57 @@ msgstr ""
msgid "Events API"
msgstr ""
+msgid "Event|accepted"
+msgstr ""
+
+msgid "Event|added"
+msgstr ""
+
+msgid "Event|approved"
+msgstr ""
+
+msgid "Event|closed"
+msgstr ""
+
+msgid "Event|commented on"
+msgstr ""
+
+msgid "Event|created"
+msgstr ""
+
+msgid "Event|deleted"
+msgstr ""
+
+msgid "Event|destroyed"
+msgstr ""
+
+msgid "Event|imported"
+msgstr ""
+
+msgid "Event|joined"
+msgstr ""
+
+msgid "Event|left"
+msgstr ""
+
+msgid "Event|opened"
+msgstr ""
+
+msgid "Event|pushed new"
+msgstr ""
+
+msgid "Event|pushed to"
+msgstr ""
+
+msgid "Event|removed"
+msgstr ""
+
+msgid "Event|removed due to membership expiration from"
+msgstr ""
+
+msgid "Event|updated"
+msgstr ""
+
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
msgstr ""
@@ -16039,6 +16313,9 @@ msgstr ""
msgid "Failed to add a Zoom meeting"
msgstr ""
+msgid "Failed to add a resource link"
+msgstr ""
+
msgid "Failed to apply commands."
msgstr ""
@@ -16086,9 +16363,6 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
-msgid "Failed to create new access token: %{token_response_message}"
-msgstr ""
-
msgid "Failed to create repository"
msgstr ""
@@ -16964,14 +17238,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17233,6 +17540,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17572,6 +17882,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18451,6 +18764,9 @@ msgstr ""
msgid "Group"
msgstr ""
+msgid "Group %{group_name} and its Mattermost team were successfully created."
+msgstr ""
+
msgid "Group %{group_name} couldn't be exported."
msgstr ""
@@ -18658,6 +18974,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18694,6 +19013,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18910,7 +19232,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19207,12 +19529,6 @@ msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|No groups matched your search"
-msgstr ""
-
-msgid "GroupsTree|No groups or projects matched your search"
-msgstr ""
-
msgid "GroupsTree|Options"
msgstr ""
@@ -19255,6 +19571,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19273,6 +19595,12 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
+msgid "Guest"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19294,7 +19622,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19451,9 +19779,6 @@ msgstr ""
msgid "Health status"
msgstr ""
-msgid "Health status cannot be edited because this issue is closed"
-msgstr ""
-
msgid "HealthCheck|Access token is"
msgstr ""
@@ -19908,6 +20233,15 @@ msgstr ""
msgid "IdentityVerification|Something went wrong. Please try again."
msgstr ""
+msgid "IdentityVerification|Step %{stepNumber}: Verify a payment method"
+msgstr ""
+
+msgid "IdentityVerification|Step %{stepNumber}: Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Step %{stepNumber}: Verify phone number"
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
@@ -20028,6 +20362,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20037,6 +20377,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20218,6 +20561,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20242,6 +20588,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21147,6 +21496,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21650,9 +22002,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21737,6 +22086,9 @@ msgstr ""
msgid "Invalid yaml"
msgstr ""
+msgid "Invalidated"
+msgstr ""
+
msgid "Investigate vulnerability: %{title}"
msgstr ""
@@ -22072,6 +22424,18 @@ msgstr ""
msgid "IssuableStatus|promoted"
msgstr ""
+msgid "Issuable|epic"
+msgstr ""
+
+msgid "Issuable|escalation policy"
+msgstr ""
+
+msgid "Issuable|iteration"
+msgstr ""
+
+msgid "Issuable|milestone"
+msgstr ""
+
msgid "Issue"
msgstr ""
@@ -22150,6 +22514,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22522,9 +22889,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23372,6 +23736,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -24227,6 +24594,9 @@ msgstr ""
msgid "Main menu"
msgstr ""
+msgid "Maintainer"
+msgstr ""
+
msgid "Maintenance mode"
msgstr ""
@@ -24242,6 +24612,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24293,10 +24666,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24380,6 +24753,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Click to expand"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
+msgid "MarkdownEditor|header"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
@@ -24644,6 +25035,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25621,6 +26015,9 @@ msgstr ""
msgid "Milestone lists not available with your current license"
msgstr ""
+msgid "Milestone(s) not found: %{milestones}"
+msgstr ""
+
msgid "MilestoneCombobox|An error occurred while searching for milestones"
msgstr ""
@@ -25780,6 +26177,9 @@ msgstr ""
msgid "Min Value"
msgstr ""
+msgid "Minimal Access"
+msgstr ""
+
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
@@ -25801,6 +26201,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26035,6 +26438,9 @@ msgstr ""
msgid "Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1."
msgstr ""
+msgid "Must be 90 days or more."
+msgstr ""
+
msgid "My awesome group"
msgstr ""
@@ -26282,6 +26688,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26492,6 +26901,9 @@ msgstr ""
msgid "No Work Item Link found"
msgstr ""
+msgid "No access"
+msgstr ""
+
msgid "No active admin user found"
msgstr ""
@@ -26782,6 +27194,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26902,7 +27317,7 @@ msgstr ""
msgid "Notes|Expand replies"
msgstr ""
-msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
+msgid "Notes|Internal notes are only visible to members with the role of Reporter or higher"
msgstr ""
msgid "Notes|Last reply by %{name}"
@@ -27102,9 +27517,18 @@ msgstr ""
msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
msgstr ""
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr ""
+
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
msgstr ""
@@ -27234,6 +27658,15 @@ msgstr ""
msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
msgstr ""
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} couldn't be exported."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
msgid "Notify|Remote mirror"
msgstr ""
@@ -27249,6 +27682,15 @@ msgstr ""
msgid "Notify|The diff was not included because it is too large."
msgstr ""
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The errors we encountered were:"
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
msgstr ""
@@ -27270,6 +27712,9 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
msgid "Notify|Your CSV import for project %{project_link} has been completed."
msgstr ""
@@ -27518,6 +27963,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28078,6 +28526,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28329,12 +28780,21 @@ msgstr ""
msgid "PackageRegistry|Delete package asset"
msgstr ""
+msgid "PackageRegistry|Delete package version"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
msgid "PackageRegistry|Delete this package"
msgstr ""
+msgid "PackageRegistry|Deleting all package assets will remove version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|Deleting the last package asset will remove version %{version} of %{name}. Are you sure?"
+msgstr ""
+
msgid "PackageRegistry|Duplicate packages"
msgstr ""
@@ -28395,6 +28855,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28448,6 +28911,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28559,7 +29025,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28774,9 +29240,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28906,12 +29369,6 @@ msgstr ""
msgid "Period in seconds"
msgstr ""
-msgid "Period of inactivity (days)"
-msgstr ""
-
-msgid "Period of inactivity before deactivation."
-msgstr ""
-
msgid "Permalink"
msgstr ""
@@ -29179,9 +29636,24 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29191,15 +29663,30 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem deleting the pipeline schedule."
+msgstr ""
+
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29314,6 +29801,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29995,6 +30488,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30061,12 +30557,36 @@ msgstr ""
msgid "Pre-defined push rules"
msgstr ""
+msgid "PreScanVerification|(optional)"
+msgstr ""
+
+msgid "PreScanVerification|Last run %{timeAgo} in pipeline"
+msgstr ""
+
+msgid "PreScanVerification|Pre-scan verification"
+msgstr ""
+
+msgid "PreScanVerification|Started %{timeAgo} in pipeline"
+msgstr ""
+
+msgid "PreScanVerification|Test your configuration and identify potential errors before running a full scan."
+msgstr ""
+
+msgid "PreScanVerification|Verify configuration"
+msgstr ""
+
+msgid "PreScanVerification|View results"
+msgstr ""
+
msgid "Preferences"
msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30178,6 +30698,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30292,9 +30815,15 @@ msgstr ""
msgid "Product Analytics"
msgstr ""
+msgid "ProductAnalytics|Audience"
+msgstr ""
+
msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
msgstr ""
+msgid "ProductAnalytics|Widgets content"
+msgstr ""
+
msgid "Productivity"
msgstr ""
@@ -31240,6 +31769,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31372,6 +31904,9 @@ msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31564,7 +32099,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31654,6 +32189,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32242,6 +32780,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32398,6 +32939,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32494,6 +33038,9 @@ msgstr ""
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
msgid "PushRules|Reject expression in commit messages"
msgstr ""
@@ -32656,9 +33203,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32814,9 +33358,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -32927,6 +33468,9 @@ msgstr[1] ""
msgid "Release %{deletedRelease} has been successfully deleted."
msgstr ""
+msgid "Release already exists"
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32936,6 +33480,9 @@ msgstr ""
msgid "Release date"
msgstr ""
+msgid "Release does not exist"
+msgstr ""
+
msgid "Release does not have the same project as the milestone"
msgstr ""
@@ -33392,6 +33939,9 @@ msgstr ""
msgid "Reported by %{reporter}"
msgstr ""
+msgid "Reporter"
+msgstr ""
+
msgid "Reporting"
msgstr ""
@@ -33406,11 +33956,6 @@ msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have faile
msgstr[0] ""
msgstr[1] ""
-msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
-msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
msgstr[0] ""
@@ -33700,6 +34245,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33911,6 +34459,9 @@ msgstr ""
msgid "Resolved by %{name}"
msgstr ""
+msgid "Resource link added"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -34086,6 +34637,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34107,6 +34661,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34172,6 +34729,9 @@ msgid_plural "Runners|%d selected runners deleted"
msgstr[0] ""
msgstr[1] ""
+msgid "Runners|%{link_start}These runners%{link_end} are available to all groups and projects."
+msgstr ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -34203,6 +34763,9 @@ msgstr ""
msgid "Runners|Add your feedback in the issue"
msgstr ""
+msgid "Runners|Administrator"
+msgstr ""
+
msgid "Runners|All"
msgstr ""
@@ -34331,6 +34894,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34364,9 +34930,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34409,6 +34972,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Owner"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -34447,6 +35013,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34480,9 +35049,6 @@ msgstr ""
msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr ""
-
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
msgstr ""
@@ -34531,18 +35097,30 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
+msgid "Runners|Runners are the agents that run your CI/CD jobs. To register new runners, please contact your administrator."
+msgstr ""
+
msgid "Runners|Runs untagged jobs"
msgstr ""
+msgid "Runners|Select all"
+msgstr ""
+
msgid "Runners|Select projects to assign to this runner"
msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34573,12 +35151,18 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
msgstr ""
+msgid "Runners|The project, group or instance where the runner was registered. Instance runners are always owned by Administrator."
+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 ""
@@ -34614,6 +35198,9 @@ msgstr ""
msgid "Runners|Token expiry"
msgstr ""
+msgid "Runners|Unselect all"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34713,16 +35300,22 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
-msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
+msgid "SAML single sign-on"
+msgstr ""
+
+msgid "SAML single sign-on for %{group_name}"
msgstr ""
msgid "SAML|Sign in to GitLab to connect your organization's account"
msgstr ""
-msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
+msgid "SAML|The %{strongOpen}%{group_path}%{strongClose} group allows you to sign in using single sign-on."
msgstr ""
-msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
+msgid "SAML|To access %{strongOpen}%{group_name}%{strongClose}, you must sign in using single sign-on through an external sign-in page."
+msgstr ""
+
+msgid "SAML|To allow %{strongOpen}%{group_name}%{strongClose} to manage your GitLab account %{strongOpen}%{username}%{strongClose} (%{email}) after you sign in successfully using single sign-on, select %{strongOpen}Authorize%{strongClose}."
msgstr ""
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
@@ -34830,10 +35423,10 @@ msgstr ""
msgid "Saving project."
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
+msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
-msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
+msgid "ScanExecutionPolicy|%{rules} actions for the %{scopes} %{branches} %{agents} %{namespaces}"
msgstr ""
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
@@ -34854,9 +35447,15 @@ msgstr ""
msgid "ScanExecutionPolicy|Schedule rule component"
msgstr ""
+msgid "ScanExecutionPolicy|Select agent"
+msgstr ""
+
msgid "ScanExecutionPolicy|Select branches"
msgstr ""
+msgid "ScanExecutionPolicy|Select namespaces"
+msgstr ""
+
msgid "ScanExecutionPolicy|Select scanner profile"
msgstr ""
@@ -34866,9 +35465,15 @@ msgstr ""
msgid "ScanExecutionPolicy|Site profile"
msgstr ""
+msgid "ScanExecutionPolicy|agent"
+msgstr ""
+
msgid "ScanExecutionPolicy|branch"
msgstr ""
+msgid "ScanExecutionPolicy|in namespaces"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34980,6 +35585,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35067,6 +35675,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35371,13 +35982,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35434,9 +36045,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35839,6 +36447,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35851,6 +36462,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35881,12 +36495,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36004,6 +36624,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36094,9 +36717,15 @@ msgstr ""
msgid "SecurityReports|scanned resources"
msgstr ""
+msgid "SecurityTraining|Enable security training to learn how to fix vulnerabilities. View security training from selected educational providers relevant to the detected vulnerability."
+msgstr ""
+
msgid "SecurityTraining|Primary Training"
msgstr ""
+msgid "SecurityTraining|Resolve with security training"
+msgstr ""
+
msgid "SecurityTraining|Training from this partner takes precedence when more than one training partner is enabled."
msgstr ""
@@ -36127,9 +36756,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36175,9 +36801,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36199,9 +36822,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36247,6 +36876,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36637,18 +37269,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36661,6 +37290,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37031,7 +37663,7 @@ msgstr ""
msgid "Sign in preview"
msgstr ""
-msgid "Sign in to \"%{group_name}\""
+msgid "Sign in to %{group_name}"
msgstr ""
msgid "Sign in to GitLab"
@@ -37046,7 +37678,7 @@ msgstr ""
msgid "Sign in with"
msgstr ""
-msgid "Sign in with Single Sign-On"
+msgid "Sign in with single sign-on"
msgstr ""
msgid "Sign in with smart card"
@@ -37361,6 +37993,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37601,6 +38236,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -38075,9 +38713,6 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusCheck| %{failed} failed, and %{pending} pending"
-msgstr ""
-
msgid "StatusCheck|%{failed} failed"
msgstr ""
@@ -38090,9 +38725,6 @@ msgstr ""
msgid "StatusCheck|Add status check"
msgstr ""
-msgid "StatusCheck|All passed"
-msgstr ""
-
msgid "StatusCheck|An error occurred deleting the %{name} status check."
msgstr ""
@@ -38114,9 +38746,6 @@ msgstr ""
msgid "StatusCheck|Failed to load status checks"
msgstr ""
-msgid "StatusCheck|Failed to load status checks."
-msgstr ""
-
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
msgstr ""
@@ -38633,9 +39262,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38974,6 +39615,9 @@ msgstr ""
msgid "Tag"
msgstr ""
+msgid "Tag does not exist"
+msgstr ""
+
msgid "Tag list:"
msgstr ""
@@ -39058,6 +39702,9 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
+msgid "TagsPage|Do you want to create a release with the new tag? You can do that in the %{link_start}New release page%{link_end}."
+msgstr ""
+
msgid "TagsPage|Edit release"
msgstr ""
@@ -39079,15 +39726,9 @@ msgstr ""
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
msgstr ""
-msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
-msgstr ""
-
msgid "TagsPage|Please type the following to confirm:"
msgstr ""
-msgid "TagsPage|Release notes"
-msgstr ""
-
msgid "TagsPage|Repository has no tags yet."
msgstr ""
@@ -39109,9 +39750,6 @@ msgstr ""
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
-msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
-
msgid "TagsPage|Yes, delete protected tag"
msgstr ""
@@ -39241,16 +39879,6 @@ msgstr ""
msgid "Terraform|%{name} successfully removed"
msgstr ""
-msgid "Terraform|%{number} Terraform report failed to generate"
-msgid_plural "Terraform|%{number} Terraform reports failed to generate"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "Terraform|%{number} Terraform report was generated in your pipelines"
-msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
msgstr[0] ""
@@ -39270,12 +39898,6 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
-msgid "Terraform|A report failed to generate."
-msgstr ""
-
-msgid "Terraform|A report was generated in your pipelines."
-msgstr ""
-
msgid "Terraform|Actions"
msgstr ""
@@ -39363,12 +39985,6 @@ msgstr ""
msgid "Terraform|Terraform reports"
msgstr ""
-msgid "Terraform|The job %{name} failed to generate a report."
-msgstr ""
-
-msgid "Terraform|The job %{name} generated a report."
-msgstr ""
-
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
msgstr ""
@@ -39823,6 +40439,9 @@ msgstr ""
msgid "The hostname of your Snowplow collector."
msgstr ""
+msgid "The import cannot be canceled because it is %{project_status}"
+msgstr ""
+
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -40018,9 +40637,6 @@ msgstr ""
msgid "The resource that you are attempting to access does not exist or you don't have permission to perform this action."
msgstr ""
-msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
-msgstr ""
-
msgid "The scan has been created."
msgstr ""
@@ -40234,9 +40850,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40465,9 +41078,6 @@ msgstr ""
msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "These runners are shared across this GitLab instance."
-msgstr ""
-
msgid "These runners are specific to this project."
msgstr ""
@@ -40504,9 +41114,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40570,6 +41177,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40666,6 +41276,24 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40711,6 +41339,9 @@ msgstr ""
msgid "This group has no active access tokens."
msgstr ""
+msgid "This group has no projects yet"
+msgstr ""
+
msgid "This group is linked to a subscription"
msgstr ""
@@ -40927,6 +41558,9 @@ msgstr ""
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
+msgid "This namespace has already been taken. Choose a different one."
+msgstr ""
+
msgid "This only applies to repository indexing operations."
msgstr ""
@@ -40981,6 +41615,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41002,6 +41639,9 @@ msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41089,6 +41729,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41468,6 +42111,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41615,9 +42261,30 @@ msgstr ""
msgid "Todos count"
msgstr ""
+msgid "Todos|Added"
+msgstr ""
+
+msgid "Todos|Alert"
+msgstr ""
+
+msgid "Todos|Any Action"
+msgstr ""
+
+msgid "Todos|Any Type"
+msgstr ""
+
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
msgstr ""
+msgid "Todos|Assigned"
+msgstr ""
+
+msgid "Todos|Design"
+msgstr ""
+
+msgid "Todos|Epic"
+msgstr ""
+
msgid "Todos|Filter by author"
msgstr ""
@@ -41639,18 +42306,33 @@ msgstr ""
msgid "Todos|Isn't an empty To-Do List beautiful?"
msgstr ""
+msgid "Todos|Issue"
+msgstr ""
+
msgid "Todos|It's how you always know what to work on next."
msgstr ""
msgid "Todos|Mark all as done"
msgstr ""
+msgid "Todos|Mentioned"
+msgstr ""
+
+msgid "Todos|Merge request"
+msgstr ""
+
msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr ""
msgid "Todos|Nothing left to do. High five!"
msgstr ""
+msgid "Todos|Pipelines"
+msgstr ""
+
+msgid "Todos|Review requested"
+msgstr ""
+
msgid "Todos|Undo mark all as done"
msgstr ""
@@ -41687,9 +42369,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41954,9 +42633,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41972,6 +42648,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42641,6 +43322,12 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuotas|The project-level storage statistics for the Container Registry are directional only and do not include savings for instance-wide deduplication."
+msgstr ""
+
+msgid "UsageQuotas|This project-level storage statistic does not include savings for site-wide deduplication and is not used to calculate total namespace storage."
+msgstr ""
+
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
msgstr ""
@@ -42653,6 +43340,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42695,10 +43385,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42773,9 +43463,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42809,7 +43496,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43474,9 +44161,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43495,7 +44179,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43756,6 +44467,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43782,9 +44496,6 @@ msgstr ""
msgid "View entire blame"
msgstr ""
-msgid "View epics list"
-msgstr ""
-
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
msgstr[0] ""
@@ -43799,9 +44510,6 @@ msgstr ""
msgid "View full dashboard"
msgstr ""
-msgid "View full log"
-msgstr ""
-
msgid "View group in admin area"
msgstr ""
@@ -44206,6 +44914,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44230,6 +44941,9 @@ msgstr ""
msgid "Vulnerability|Links"
msgstr ""
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr ""
@@ -44275,6 +44989,9 @@ msgstr ""
msgid "Vulnerability|Status"
msgstr ""
+msgid "Vulnerability|Status:"
+msgstr ""
+
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
msgstr ""
@@ -44284,6 +45001,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44362,6 +45082,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44503,6 +45229,9 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
+msgid "Webhooks|+ Mask another portion of URL"
+msgstr ""
+
msgid "Webhooks|A comment is added to a confidential issue."
msgstr ""
@@ -44572,6 +45301,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44587,12 +45319,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44617,6 +45355,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44629,9 +45373,6 @@ 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 ""
@@ -44641,6 +45382,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44653,7 +45397,10 @@ msgstr ""
msgid "Webhooks|Webhook fails to connect"
msgstr ""
-msgid "Webhooks|Webhook was automatically disabled"
+msgid "Webhooks|Webhook rate limit has been reached"
+msgstr ""
+
+msgid "Webhooks|Webhooks for %{root_namespace} are now disabled because they've been triggered more than %{limit} times per minute. They'll be automatically re-enabled in the next minute."
msgstr ""
msgid "Webhooks|Wiki page events"
@@ -44819,12 +45566,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45068,6 +45809,12 @@ msgstr ""
msgid "WorkItem|Add task"
msgstr ""
+msgid "WorkItem|Add to iteration"
+msgstr ""
+
+msgid "WorkItem|Add to milestone"
+msgstr ""
+
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr ""
@@ -45118,9 +45865,24 @@ msgstr ""
msgid "WorkItem|Issue"
msgstr ""
+msgid "WorkItem|Iteration"
+msgstr ""
+
msgid "WorkItem|Learn about tasks."
msgstr ""
+msgid "WorkItem|Milestone"
+msgstr ""
+
+msgid "WorkItem|No iteration"
+msgstr ""
+
+msgid "WorkItem|No matching results"
+msgstr ""
+
+msgid "WorkItem|No milestone"
+msgstr ""
+
msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
msgstr ""
@@ -45151,10 +45913,13 @@ msgstr ""
msgid "WorkItem|Something went wrong when deleting the task. Please try again."
msgstr ""
-msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
+msgid "WorkItem|Something went wrong when fetching iterations. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when fetching labels. Please try again."
msgstr ""
-msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
+msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
msgstr ""
msgid "WorkItem|Something went wrong when fetching work item types. Please try again"
@@ -45166,6 +45931,9 @@ msgstr ""
msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
msgstr ""
+msgid "WorkItem|Something went wrong while fetching milestones. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong while updating the %{workItemType}. Please try again."
msgstr ""
@@ -45187,6 +45955,9 @@ msgstr ""
msgid "WorkItem|Test case"
msgstr ""
+msgid "WorkItem|This work item is not available. It either doesn't exist or you don't have permission to view it."
+msgstr ""
+
msgid "WorkItem|Turn off confidentiality"
msgstr ""
@@ -45205,6 +45976,9 @@ msgstr ""
msgid "WorkItem|Work item"
msgstr ""
+msgid "WorkItem|Work item not found"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -45336,6 +46110,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to create this tag as it is protected."
+msgstr ""
+
msgid "You are not allowed to log in using password"
msgstr ""
@@ -45437,6 +46214,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45554,12 +46337,18 @@ msgstr ""
msgid "You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members. To get more members an owner of the group can start a trial or upgrade to a paid tier."
msgstr ""
+msgid "You can't follow more than %{limit} users. To follow more users, unfollow some others."
+msgstr ""
+
msgid "You cannot %{action} %{state} users."
msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45760,7 +46549,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45778,7 +46567,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46187,9 +46976,6 @@ msgstr ""
msgid "Your new %{type}"
msgstr ""
-msgid "Your new access token has been created."
-msgstr ""
-
msgid "Your new comment"
msgstr ""
@@ -46359,9 +47145,6 @@ msgstr[1] ""
msgid "access:"
msgstr ""
-msgid "added"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -46430,9 +47213,6 @@ msgstr ""
msgid "at least the Reporter role, the author, and assignees"
msgstr ""
-msgid "at risk"
-msgstr ""
-
msgid "attach a new file"
msgstr ""
@@ -46462,6 +47242,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46507,6 +47290,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46767,6 +47553,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46972,6 +47761,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47275,6 +48067,9 @@ msgstr ""
msgid "is not a descendant of the Group owning the template"
msgstr ""
+msgid "is not a valid URL."
+msgstr ""
+
msgid "is not a valid X509 certificate."
msgstr ""
@@ -47293,9 +48088,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47428,6 +48220,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47786,6 +48581,9 @@ msgstr ""
msgid "must be set for a project namespace"
msgstr ""
+msgid "must be top-level namespace"
+msgstr ""
+
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
@@ -47807,9 +48605,6 @@ msgstr ""
msgid "my-topic"
msgstr ""
-msgid "need attention"
-msgstr ""
-
msgid "needs to be between 10 minutes and 1 month"
msgstr ""
@@ -47858,9 +48653,6 @@ msgstr ""
msgid "nounSeries|%{item}, and %{lastItem}"
msgstr ""
-msgid "on track"
-msgstr ""
-
msgid "only %{parent_types} can be parent of Task."
msgstr ""
@@ -47879,9 +48671,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47893,6 +48682,9 @@ msgstr ""
msgid "pages"
msgstr ""
+msgid "params is empty"
+msgstr ""
+
msgid "parent"
msgid_plural "parents"
msgstr[0] ""
@@ -48022,9 +48814,6 @@ msgstr ""
msgid "remove weight"
msgstr ""
-msgid "removed"
-msgstr ""
-
msgid "removed a %{link_type} link"
msgstr ""
@@ -48173,6 +48962,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 9ea0836a034..1537c004781 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr " %{start} a %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 0b74df4c695..9374a4148ac 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1210,13 +1217,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} זמין"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1925,9 +1941,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr "הוספת ×ž×©×ª×ž×©×™× ×œ×§×‘×•×¦×”"
-
msgid "Add variable"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "כל המיזמי×"
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index a7e63580e0e..74cf39192c0 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index f34e6425ded..0404a32cc8a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -151,6 +151,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1117,12 +1123,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1165,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1198,9 +1204,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1234,6 +1237,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1255,10 +1261,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1282,6 +1291,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1795,9 +1810,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1816,6 +1828,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2497,12 +2518,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2896,9 +2911,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2911,6 +2932,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2932,6 +2956,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2968,6 +2995,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3019,9 +3049,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3208,6 +3250,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3547,9 +3592,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3976,6 +4033,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4051,6 +4111,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4339,9 +4402,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4588,6 +4648,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4813,6 +4876,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5464,6 +5530,9 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6136,6 +6205,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6457,7 +6529,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6496,6 +6568,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6817,6 +6892,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6853,33 +6931,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6889,6 +7012,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7189,6 +7324,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7363,6 +7501,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7372,7 +7513,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7633,7 +7774,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7828,6 +7969,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8845,6 +8989,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8944,6 +9091,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8971,6 +9121,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8980,6 +9133,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9046,6 +9202,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9715,6 +9874,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9820,6 +9982,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9889,7 +10054,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10207,6 +10372,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10666,13 +10834,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10996,6 +11164,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11212,6 +11383,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11224,6 +11398,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12481,6 +12661,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12667,6 +12853,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12811,6 +13000,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13156,6 +13348,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13201,6 +13396,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13222,6 +13420,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13237,6 +13438,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13423,18 +13630,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13504,25 +13702,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13543,7 +13738,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13564,12 +13759,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14116,6 +14305,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14482,6 +14683,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14620,9 +14824,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14740,6 +14941,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15088,6 +15292,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15121,6 +15328,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15145,6 +15355,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16246,9 +16459,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16933,6 +17143,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17062,15 +17275,48 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17335,6 +17581,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17674,6 +17923,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17896,9 +18148,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18763,6 +19012,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18799,6 +19051,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19015,7 +19270,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19360,6 +19615,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19378,6 +19639,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19399,7 +19663,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19447,6 +19711,9 @@ msgstr[2] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19492,7 +19759,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19927,24 +20194,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19984,16 +20272,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20005,6 +20299,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20014,10 +20314,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20098,6 +20401,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20107,6 +20416,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20290,6 +20602,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20314,6 +20629,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21220,6 +21538,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21442,6 +21763,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21502,12 +21826,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21520,6 +21850,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21712,9 +22045,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22108,6 +22438,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22207,6 +22543,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22579,9 +22918,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23431,6 +23767,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23512,7 +23851,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24307,6 +24646,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24358,10 +24700,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24445,9 +24787,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24457,9 +24814,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24472,7 +24826,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24709,6 +25063,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25843,6 +26200,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25867,6 +26227,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26131,6 +26494,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26347,6 +26713,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26848,6 +27217,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27139,33 +27511,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27187,12 +27592,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27211,6 +27634,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27235,6 +27661,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27244,15 +27676,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27265,12 +27733,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27331,6 +27820,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27493,6 +27985,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28054,6 +28549,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28297,15 +28795,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28372,6 +28870,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28405,13 +28906,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28426,6 +28927,9 @@ msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28477,10 +28981,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28537,7 +29041,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28753,9 +29257,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29158,9 +29659,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29170,15 +29683,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29293,6 +29818,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29974,6 +30505,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29983,6 +30517,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30043,6 +30580,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30154,6 +30694,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30367,15 +30910,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30388,9 +30925,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30406,9 +30940,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30421,6 +30952,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30658,9 +31192,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30706,9 +31237,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31198,6 +31726,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31228,6 +31759,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31351,12 +31885,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31393,6 +31933,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31546,7 +32089,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31636,6 +32179,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32158,6 +32704,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32194,6 +32743,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32218,6 +32770,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32374,6 +32929,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32443,18 +33001,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32605,9 +33193,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32764,9 +33349,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33658,6 +34240,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34048,6 +34633,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34069,6 +34657,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34297,6 +34888,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34330,9 +34924,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34342,6 +34933,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34411,6 +35005,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34438,7 +35035,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34489,6 +35089,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34501,6 +35104,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34531,6 +35137,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34570,6 +35179,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34789,9 +35401,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34939,6 +35548,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35026,6 +35638,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35341,13 +35956,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35404,9 +36019,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35809,6 +36421,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35821,6 +36436,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35851,12 +36469,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35974,6 +36598,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36097,9 +36724,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36145,9 +36769,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36169,9 +36790,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36217,6 +36844,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36529,6 +37159,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36604,18 +37237,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36628,6 +37258,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37231,6 +37864,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37297,6 +37963,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37537,6 +38206,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37579,6 +38251,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37639,6 +38314,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38539,7 +39217,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38563,9 +39241,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38602,7 +39292,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38611,7 +39307,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38728,25 +39424,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39946,6 +40654,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40153,9 +40864,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40423,9 +41131,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40489,6 +41194,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40534,6 +41242,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40582,6 +41293,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40678,6 +41410,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40894,6 +41629,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40906,12 +41644,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40999,6 +41743,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41344,6 +42091,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41377,6 +42127,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41596,9 +42349,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41620,9 +42370,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41734,6 +42481,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41863,9 +42613,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41881,6 +42628,12 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
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 ""
@@ -42562,6 +43315,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42604,10 +43360,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42682,9 +43438,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42718,7 +43471,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43060,6 +43813,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43381,9 +44137,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43402,7 +44155,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43663,6 +44443,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43687,7 +44470,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44113,6 +44896,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44134,10 +44920,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44149,6 +44935,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44176,6 +44965,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44188,6 +44980,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44200,6 +44995,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44263,6 +45061,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44473,6 +45277,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44488,12 +45295,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44518,6 +45331,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44542,6 +45361,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44722,12 +45544,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44962,6 +45778,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44995,9 +45817,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45064,6 +45892,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45328,6 +46159,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45451,6 +46288,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45652,7 +46492,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45670,7 +46510,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46261,6 +47101,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46357,6 +47200,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46402,6 +47248,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46666,6 +47515,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46825,6 +47677,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46870,6 +47725,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47197,9 +48055,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47290,6 +48145,12 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "load it anyway"
msgstr ""
@@ -47329,6 +48190,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47698,6 +48562,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47779,9 +48646,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47929,6 +48793,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47962,6 +48829,12 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48070,6 +48943,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48136,6 +49012,12 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index fea93c01ceb..b3731b7b9eb 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index c3c7a482471..bbd604854fd 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index ab5f599ae40..09c641e1958 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28750,15 +29261,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index eb8be053df0..f87fa7cea88 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28750,15 +29261,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index a9fbeb17260..64be7974357 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 0b7127ad4ca..250f15c17b2 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} è disponibile"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Pagina profilo di %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Jobs"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr "Collaboratori"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr "E-mail"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr "Rilascio"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr "Ancora nessuna chiave di rilascio"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Mostra tutti"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallo di Pattern"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr "Nuova pianificazione Pipeline"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Ott"
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Attiva"
msgid "PipelineSchedules|All"
msgstr "Tutto"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inattiva"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Prossima esecuzione"
@@ -28960,15 +29472,27 @@ msgstr "Nessuna"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Fornisci una breve descrizione per questa pipeline"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Prendi possesso"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Target"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variabili"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr "Preferenze"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Vedi altro"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Seleziona formato d'archivio"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Seleziona una timezone"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index df943c8cfb5..a2ea5dc6717 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} ã¾ã§"
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] "%d 人ã®è¿½åŠ ã‚³ãƒŸãƒƒã‚¿ãƒ¼"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d 人ã®æ‰¿èªè€…"
@@ -877,7 +881,7 @@ msgid "%{runner} created %{timeago}"
msgstr ""
msgid "%{scope} results for term '%{term}'"
-msgstr ""
+msgstr "期間'%{term}' ã®%{scope} 件ã®çµæžœ"
msgid "%{seconds}s"
msgstr "%{seconds} 秒"
@@ -931,10 +935,6 @@ msgstr "%{spanStart} 関数内%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} ã‹ã‚‰ %{end} ã¾ã§"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}警告:%{strongClose} SAML グループ リンクã«ã‚ˆã‚Šã€GitLab ã¯ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰ãƒ¡ãƒ³ãƒãƒ¼ã‚’自動的ã«å‰Šé™¤ã—ã¾ã™ã€‚"
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] "マージã™ã‚‹ãŸã‚ã« %{strong_start}%{count} 人ã®ãƒ¡ãƒ³ãƒãƒ¼%{strong_end} ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚開発者以上ã®ãƒ­ãƒ¼ãƒ«ã®ãƒ¡ãƒ³ãƒãƒ¼ã¯èª°ã§ã‚‚承èªã§ãã¾ã™ã€‚"
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr "%{template_project_id} ã¯ä¸æ˜Žã€ã¾ãŸã¯ç„¡åŠ¹ã§ã™"
msgid "%{text} is available"
msgstr "%{text} ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} ã¯ã€ãƒ—ロジェクトã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ã„ãšã‚Œã‹ã«å±žã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} ã¯ãƒãƒ¼ãƒ³ã‚¢ãƒƒãƒ—ãƒãƒ£ãƒ¼ãƒˆã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“"
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: 最åˆã® %{warningsDisplayed} を表示"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,12 +1055,15 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "%{user_name} プロフィールページ"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} ãŒãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ %{mr_link} ã®ãƒ‰ãƒ©ãƒ•ãƒˆã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’変更ã—ã¾ã—ãŸ"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} ãŒã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ %{host} ã® GitLab アカウントをリクエストã—ã¾ã—ãŸã€‚"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "%{username}ã®ã‚¢ãƒã‚¿ãƒ¼"
@@ -1078,6 +1085,12 @@ msgstr "%{value} 秒"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} ã—㦠%{time_spent_value} ãŒçµŒéŽã—ã¾ã—ãŸã€‚"
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} を使ã†ã¨ã€ã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ãƒ—ロジェクトã®ã‚¤ãƒ™ãƒ³ãƒˆã«å¿œã˜ã¦ã‚¦ã‚§ãƒ–アプリケーションã«é€šçŸ¥ã‚’é€ä¿¡ã§ãã¾ã™ã€‚"
@@ -1535,9 +1548,6 @@ msgstr "%{name} ã®æ–°ã—ã„リリース %{tag} ãŒå…¬é–‹ã•ã‚Œã¾ã—ãŸã€‚ リã
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "æ–°ã—ã„å½è£…トークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "プレーンHTMLã®ã‚µã‚¤ãƒˆã§GitLabã®ä»£ã‚ã‚Šã«Netlifyã‚’CI/CDã§ä½¿ç”¨ã—ã¦ã„ãŸã¨ã—ã¦ã‚‚ã€GitLabã«ã¯ã»ã‹ã«ã‚‚素晴らã—ã„機能ãŒãŸãã•ã‚“ã‚ã‚Šã¾ã™ã€‚"
@@ -2237,12 +2256,6 @@ msgstr "プロジェクトã«ãƒˆãƒ”ックを追加ã—ã¦ã€ãƒ¦ãƒ¼ã‚¶ãŒãƒ—ロジ
msgid "Add trigger"
msgstr "トリガーを追加"
-msgid "Add user(s) to the group:"
-msgstr "グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加:"
-
-msgid "Add users to group"
-msgstr "ユーザーをグループã¸è¿½åŠ "
-
msgid "Add variable"
msgstr "変数ã®è¿½åŠ "
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr "ブロック済ã¿"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "ユーザーã®ãƒ–ロックã«ã¯æ¬¡ã®åŠ¹æžœãŒã‚ã‚Šã¾ã™:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "パスワードã®æ›´æ–°ã«æˆåŠŸã™ã‚‹ã¨ã€ãƒ­ã‚°ã‚¤ãƒ³ç”»é¢ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚"
@@ -3716,6 +3771,9 @@ msgstr "ä¾å­˜ã™ã‚‹ã™ã¹ã¦ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã—
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr "ブランãƒã®ãƒ«ãƒ¼ãƒ«ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "An error occurred while loading chart data"
msgstr "グラフデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr "分æž"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "ä¾å­˜é–¢ä¿‚ã«å«ã¾ã‚Œã¦ã„る既知ã®è„†å¼±æ€§ã‚’分æžã—ã¾ã™ã€‚"
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] "%d 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付"
msgid "Attaching the file failed."
msgstr "ファイルã®æ·»ä»˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "監査イベント"
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "以下ã«å…¬é–‹ã•ã‚Œã¦ã„る全グループを表示ã—ã¾ã™ã€‚"
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -5868,7 +5938,7 @@ msgid "BillingPlans|10,000 CI/CD minutes per month"
msgstr ""
msgid "BillingPlans|10GB transfer per month"
-msgstr ""
+msgstr "1ヶ月ã‚ãŸã‚Š10GBã®è»¢é€"
msgid "BillingPlans|400 CI/CD minutes per month"
msgstr ""
@@ -6173,8 +6243,8 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
-msgstr "Explore all plans"
+msgid "Billing|Explore paid plans"
+msgstr ""
msgid "Billing|Export list"
msgstr ""
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr "%{branchId} ブランãƒã¯ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Branch rules"
msgstr "ブランãƒãƒ«ãƒ¼ãƒ«"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã® Auto DevOps パイãƒ
msgid "CICD|Deployment strategy"
msgstr "デプロイ戦略"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "ジョブ"
@@ -7078,7 +7217,7 @@ msgstr "制é™"
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr "グループã«æ‰€å±žã—ã¦ã„ãªã„ãŸã‚ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’プロモー
msgid "Cannot promote issue due to insufficient permissions."
msgstr "権é™ãŒä¸å分ãªãŸã‚ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’プロモートã§ãã¾ã›ã‚“。"
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr "タイトルを \"%{title_param}\" ã«å¤‰æ›´ã—ã¾ã™ã€‚"
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr "次ã¸ã®ã‚³ãƒŸãƒƒãƒˆ"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "マージリクエストデータã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -9516,6 +9676,9 @@ msgstr "完了"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr "コンテナレジストリ"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "コンテナã®ã‚¹ã‚­ãƒ£ãƒ³"
@@ -10356,13 +10522,13 @@ msgstr "貢献者"
msgid "Control emails linked to your account"
msgstr "アカウントã«ç´ã¥ãメールã®ç®¡ç†"
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸"
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr "グループを作æˆ"
msgid "Create, update, or delete a merge request."
msgstr "マージリクエストを作æˆã€æ›´æ–°ã€ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "ã‚ãªãŸã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µãƒ–グループを作æˆã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "アーãƒãƒ•ã‚¡ã‚¯ãƒˆã‚’削除"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr "削除完了"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "ãƒãƒ£ãƒƒãƒˆãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’削除ã—ã¾ã—ãŸï¼š %{chat_name}ï¼"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr "読ã¿å–り専用"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "アクティブãªãƒ‡ãƒ—ロイトークン (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "有効期é™"
@@ -12896,6 +13092,9 @@ msgstr "%{name} ã‚’å–り消ã™"
msgid "DeployTokens|Scopes"
msgstr "スコープ"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "ã“ã® %{entity_type} ã«ã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ‡ãƒ—ロイトークンã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "ユーザーå"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr "æˆåŠŸ"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "本当ã«ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¸ã®å¤‰æ›´ã‚’å–り消ã—ã¦ã‚ˆã‚ã—ã„ã§ã—ょã†ã‹ï¼Ÿ"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "本当ã«ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆã‚’キャンセルã—ã¾ã™ã‹ï¼Ÿ"
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "コメントã®èªè¨¼ã‚’削除"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,8 +13406,8 @@ msgstr "å…¨ã¦é¸æŠžã‚’解除"
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
-msgstr "コメントã®ç ´æ£„"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13234,12 +13427,6 @@ msgstr "次ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã¸"
msgid "DesignManagement|Go to previous design"
msgstr "å‰ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã¸"
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr "コメントã®ç¶­æŒ"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "è¦æ±‚ã•ã‚ŒãŸãƒ‡ã‚¶ã‚¤ãƒ³ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯å­˜åœ¨ã—ã¾ã›ã‚“。代ã‚ã‚Šã«æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示ã—ã¦ã„ã¾ã™"
@@ -13778,6 +13965,18 @@ msgstr "ドメイン"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr "Wikiページã®ç·¨é›†"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "スレッド内ã®æœ€æ–°ã®ã‚ãªãŸã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’編集 (空ã®ãƒ†ã‚­ã‚¹ãƒˆé ˜åŸŸã‹ã‚‰)"
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr "メール"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr "デプロイ"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr "Review Appを有効ã«ã™ã‚‹"
@@ -14783,6 +14988,9 @@ msgstr "デプロイã•ã‚ŒãŸç’°å¢ƒã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Environments|No deployments yet"
msgstr "未デプロイ"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ç’°å¢ƒã‚’åœæ­¢ã™ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。ã—ã‹ã—ã€%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} ファイルã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€ç’°å¢ƒåœæ­¢ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ä»¥å¤–ã«ã‚ˆã‚‹ã€ã‚らゆる既存ã®ãƒ‡ãƒ—ロイメントã«å½±éŸ¿ã‚’ %{emphasisStart}与ãˆã¾ã›ã‚“%{emphasisEnd}。"
@@ -14807,6 +15015,9 @@ msgstr "環境ã®ãƒ­ãƒ¼ãƒ«ãƒãƒƒã‚¯"
msgid "Environments|Rollback environment %{name}?"
msgstr "環境 %{name} をロールãƒãƒƒã‚¯ã—ã¾ã™ã‹?"
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "全件を表示"
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "絵文字リストã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-
msgid "Failed to load error details from Sentry."
msgstr "Sentry ã‹ã‚‰ã®ã‚¨ãƒ©ãƒ¼è©³ç´°ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ."
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ".gitlab-ci.yml ã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失敗"
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr "GitLabイシュー"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ã
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚ %{startDate} ã‹ã‚‰ %{endDate} ã¾ã§"
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "文字ã€æ•°å­—ã€çµµæ–‡å­—ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã§å§‹ã¾ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ピリオドã€ãƒ€ãƒƒã‚·ãƒ¥ã€ã‚¹ãƒšãƒ¼ã‚¹ã€æ‹¬å¼§ã‚’å«ã‚€ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "ガイドライン"
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] "%{count} 件ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ãƒªãƒã‚¸ãƒˆãƒª"
msgid "HarborRegistry|-- artifacts"
msgstr "-- アーティファクト"
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr "ダイジェスト: %{imageId}"
@@ -19134,8 +19399,8 @@ msgstr "ã“ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã«ã¯ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆãŒã‚ã‚Šã¾ã›ã‚“"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "より多ãを検索ã™ã‚‹ã«ã¯ã€ä¸Šã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr "Harbor Registryã¸ã®æŽ¥ç¶šã§å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ページを更新ã—ã¦ã¿ã¦ãã ã•ã„。 ã“ã®ã‚¨ãƒ©ãƒ¼ãŒè§£æ±ºã—ãªã„å ´åˆã¯ã€ %{docLinkStart}トラブルシューティングã®æ–‡æ›¸%{docLinkEnd}ã‚’ã”覧ãã ã•ã„。"
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
msgstr "Harbor Registry ã§ã¯ã€å„プロジェクト㯠Harbor 空間ã«æŽ¥ç¶šã—ã¦ãã® Dockerイメージを格ç´ã§ãã¾ã™ã€‚"
@@ -19565,24 +19830,45 @@ msgstr "識別å­"
msgid "Identities"
msgstr "ID"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr "リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’紛失ã—ãŸå ´åˆã¯ã€æ–°ã—ã„リカãƒãƒª
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã¸æŽ¥ç¶š"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "ブロックã•ã‚ŒãŸã‚¤ãƒ³ãƒãƒ¼ãƒˆURL: %{message}"
@@ -19948,6 +20261,9 @@ msgstr "%{provider} リãƒã‚¸ãƒˆãƒªã®è¦æ±‚ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "リモートデータをインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr "インテグレーションを追加"
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "é–“éš”ã®ãƒ‘ターン"
-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 ""
@@ -21736,6 +22064,12 @@ msgstr "ライセンスシートã®ä½¿ç”¨:"
msgid "Is using seat"
msgstr "シート利用中"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr "イシューã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´
msgid "IssueAnalytics|Issue"
msgstr "イシュー"
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr "マイルストーン"
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr "最後ã®æˆåŠŸã—ãŸæ›´æ–°"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr "å‰å›žã®ç¢ºèªæ—¥æ™‚"
@@ -23136,7 +23473,7 @@ msgstr "GitLabã§ã®%{no_packages_link_start}パッケージã®å…±æœ‰ã¨å…¬é–‹%{
msgid "Learn more"
msgstr "詳細"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr "ãƒãƒ¼ãƒ å…¨å“¡ãŒå ´æ‰€ã«é–¢ä¿‚ãªãより生産的ã«æ´»å‹•ã§ãã¾
msgid "Make issue confidential"
msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr "プロジェクトã®ç®¡ç†ã€‚"
msgid "Manage two-factor authentication"
msgstr "2è¦ç´ èªè¨¼ã®ç®¡ç†"
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ %{issue_ref} ã¨é–¢é€£ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã—ã
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr "開始ã—ã¦ã„ãªã„イシュー (オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr "ミラーã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "ミラーã•ã‚ŒãŸãƒªãƒã‚¸ãƒˆãƒª"
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr "æ–°ã—ã„ラベルã«åå‰ã‚’ã¤ã‘ã‚‹"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "åå‰:"
@@ -25947,6 +26311,9 @@ msgstr "æ–°è¦ãƒ‘イプラインスケジュール"
msgid "New Project"
msgstr "æ–°è¦ãƒ—ロジェクト"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "オブジェクトãŒã‚µãƒ¼ãƒãƒ¼ã«å­˜åœ¨ã—ã¾ã›ã‚“ã€ã¾ãŸã¯ã€ãã‚Œã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "10月"
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr "å¤ã„ブラウザã§ã¯ GitLab ãŒæ­£ã—ã機能ã—ãªã„ã“ã¨ãŒã‚ã
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "ユーザーエクスペリエンスをå‘上ã•ã›ã‚‹ãŸã‚ã«ã€ %{browser_link_start} サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹Webブラウザー%{browser_link_end} をインストールã—ã¦ãã ã•ã„。"
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "パッケージãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®å‰Šé™¤"
msgid "PackageRegistry|Delete package"
msgstr "パッケージã®å‰Šé™¤"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "GitLabã§%{noPackagesLinkStart}ã‚ãªãŸã®ãƒ‘ッケージを公開ã—共有%{noPackagesLinkEnd}ã™ã‚‹æ–¹æ³•ã‚’å­¦ã¶ã€‚"
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr "åœæ­¢"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr "アクティブ"
msgid "PipelineSchedules|All"
msgstr "全件"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "無効"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "次ã®å®Ÿè¡Œ"
@@ -28750,15 +29261,27 @@ msgstr "ãªã—"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "ã“ã®ãƒ‘イプラインã«ã¤ã„ã¦ç°¡å˜ã«è¨˜è¿°ã—ã¦ãã ã•ã„。"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "権é™ã‚’å–å¾—ã™ã‚‹"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "ターゲット"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "変数"
@@ -28873,6 +29396,12 @@ msgstr "%{project_name} ã®ãƒ‘イプライン設定を正常ã«æ›´æ–°ã—ã¾ã—ã
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr "続行ã™ã‚‹ã«ã¯ %{phrase_code} を入力ã—ã¦ãã ã•ã„。キャãƒ
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "イシューやコメントã¸ã®ã‚¹ãƒ‘ム行為ã€ã¾ãŸä¸é©åˆ‡ãªæŒ™å‹•ã‚’ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¤ã„ã¦ã¯ã€ã“ã¡ã‚‰ã®ãƒ•ã‚©ãƒ¼ãƒ ã‹ã‚‰ç®¡ç†è€…ã«å ±å‘Šã—ã¦ãã ã•ã„。"
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "少々ãŠå¾…ã¡ãã ã•ã„。準備ãŒæ•´ã„次第ã“ã®ãƒšãƒ¼ã‚¸ã¯è‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
@@ -29563,6 +30095,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã§ãã‚‹ã¾ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹ã®ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。完了ã™ã‚‹ã¨ã€ç”»é¢ãŒè‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "使用中ã®ãƒãƒƒãƒ‰"
@@ -29623,6 +30158,9 @@ msgstr "基本設定"
msgid "Preferences saved."
msgstr "設定ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "挙動"
@@ -29734,6 +30272,9 @@ msgstr "時間設定"
msgid "Preferences|Use relative times"
msgstr "相対時間を使用"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "説明欄やコメント欄ã«æ–‡å­—を入力ã™ã‚‹å ´åˆã€æ¬¡ã®æ–‡å­—ã®ã„ãšã‚Œã‹ã‚’入力ã™ã‚‹ã¨ã€é¸æŠžã—ãŸæ–‡å­—ãŒå¯¾å¿œã™ã‚‹æ–‡å­—ã§å›²ã¾ã‚Œã¾ã™: %{supported_characters}。"
@@ -29947,15 +30488,9 @@ msgstr "アクティブ"
msgid "Profiles|Add key"
msgstr "キーを追加"
-msgid "Profiles|Add status emoji"
-msgstr "ステータス絵文字を追加"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚¯ãƒ­ãƒƒãƒ‘ー"
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "BIO"
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr "ユーザーåã®å¤‰æ›´"
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "国ã€éƒ½é“府県"
-msgid "Profiles|Clear status"
-msgstr "ステータスをクリア"
-
msgid "Profiles|Commit email"
msgstr "コミットメール"
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "接続ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆ"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "ç¾åœ¨ã®ãƒ‘ス: %{path}"
@@ -30238,9 +30770,6 @@ msgstr "åå‰ã«çµµæ–‡å­—を使ã†ã®ã¯æ¥½ã—ãã†ã§ã™ãŒã€ä»£ã‚ã‚Šã«ã‚¹
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "ã‚ãªãŸã¯ã©ã‚“ãªã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã§ã™ã‹ï¼Ÿ"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr "ã‚ãªãŸã®åå‰ã¯ã‚ãªãŸã® %{provider_label} アカウントã«åŸ
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "ã‚ãªãŸã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr "マージã®æ–¹æ³•ã€ãƒžãƒ¼ã‚¸ã‚ªãƒ—ションã€ãƒžãƒ¼ã‚¸ãƒã‚§ãƒƒã‚¯ãŠ
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr "マージæ案"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ç½²åã•ã‚ŒãŸã‚³ãƒŸãƒƒãƒˆã®ã¿ãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -30973,6 +31511,9 @@ msgstr "プロジェクトã®å¯è¦–性"
msgid "ProjectSettings|Public"
msgstr "公開"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "リãƒã‚¸ãƒˆãƒª"
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr "プッシュを許å¯"
msgid "ProtectedBranch|Allowed to push:"
msgstr "プッシュを許å¯:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "ブランãƒ"
@@ -31774,6 +32321,9 @@ msgstr "ä¿è­·ãƒ–ランム(%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr "プル"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr "続ãを読む"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr "ユニãƒãƒ¼ã‚µãƒ«ãª2è¦ç´ èªè¨¼ãƒ‡ãƒã‚¤ã‚¹ã‚’登録ã™ã‚‹"
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã®ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°"
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr "代ç†ãƒˆãƒ¼ã‚¯ãƒ³ %{token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "パーソナルアクセストークン㮠%{personal_access_token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr "役割"
msgid "Rollback"
msgstr "ロールãƒãƒƒã‚¯"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -33843,6 +34432,9 @@ msgstr "Runners を始ã‚ã¾ã—ょã†"
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr "マルãƒãƒ—ロジェクトランナーã¯å‰Šé™¤ã§ãã¾ã›ã‚“"
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr "プロジェクトをä¿å­˜"
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "ブランãƒã‚’検索"
@@ -34568,6 +35178,9 @@ msgstr "プロジェクトを検索"
msgid "Search projects..."
msgstr "プロジェクトを検索..."
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "有効ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} 以上"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "イシューを作æˆã™ã‚‹"
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr "éžè¡¨ç¤ºã«ã•ã‚ŒãŸ '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "'%{vulnerabilityName}'ã‚’éžè¡¨ç¤ºã«ã—ã¾ã—ãŸã€‚表示ã™ã‚‹ã«ã¯ã€éžè¡¨ç¤ºåˆ‡ã‚Šæ›¿ãˆã‚’オフã«ã—ã¾ã™ã€‚"
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr "アーカイブã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’é¸æŠž"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr "ページを変更"
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr "テンプレートリãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
msgid "Select a template type"
msgstr "テンプレートタイプをé¸æŠž"
-msgid "Select a time zone"
-msgstr "タイムゾーンをé¸æŠž"
-
msgid "Select a timezone"
msgstr "タイムゾーンをé¸æŠž"
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr "ブランãƒã®é¸æŠž"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr "プロジェクトã®é¸æŠž"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr "ターゲットブランãƒã‚’設定"
msgid "Set target branch to %{branch_name}."
msgstr "ターゲットブランãƒã‚’ %{branch_name} ã«è¨­å®šã—ã¾ã—ãŸã€‚"
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr "ウェイトを設定"
msgid "Set weight to %{weight}."
msgstr "ウェイトを %{weight} ã«è¨­å®š"
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "ステータスをåˆæœŸåŒ–"
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "ステータスを編集"
@@ -36148,6 +36776,9 @@ msgstr "ステータスを設定"
msgid "SetStatusModal|Set status"
msgstr "ステータスを設定"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "ã‚ãªãŸã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’設定ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -36747,6 +37378,39 @@ msgstr "ãƒãƒ¼ãƒ ã«æœ€é©ãªãƒ¯ãƒ¼ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„。"
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr "最後ã«å‚加ã—ãŸé †"
msgid "SortOptions|Last created"
msgstr "最新作æˆé †"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "人気順"
@@ -37155,6 +37828,9 @@ msgstr "ãŠæ°—ã«ã„ã‚Šã§å¤ã„é †"
msgid "SortOptions|Oldest updated"
msgstr "å¤ã„æ›´æ–°é †"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "人気順"
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr "ã“ã®ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯èªè¨¼ç„¡ã—ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "利用ã§ãるデータã¯ã‚ã‚Šã¾ã›ã‚“。é¸æŠžã—ç›´ã—ã¦ãã ã•ã„。"
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr "ã“ã®ãƒ–ロックã¯è‡ªå·±å‚ç…§ã—ã¦ã„ã¾ã™ã€‚"
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr "ã“ã®ã‚¨ãƒ”ックã«ã¯ã€æ—¢ã«æœ€å¤§æ•°ã®å­ã‚¨ãƒ”ックãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "ã“ã®ã‚¨ãƒ”ックã¯å­˜åœ¨ã—ãªã„ã‹ã€ã‚ãªãŸã«å分ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -40174,6 +40904,9 @@ msgstr "ライセンスãŒé–‹å§‹ã•ã‚Œã¦ã‹ã‚‰ã€ã‚ãªãŸã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã™"
@@ -40390,6 +41123,9 @@ msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ãŠã‚Šã€ã‚³ãƒ¡ãƒ³ãƒˆ
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr "ã“ã®æ“作ã¯ã€ã“ã®ãƒ—ロジェクト㨠%{fork_source} é–“ã®ãƒ•ã‚
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr "ã“ã®æ“作ã¯ã€ã“ã®ãƒ—ロジェクトã¨ãƒ•ã‚©ãƒ¼ã‚¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®ä»–ã®ãƒ—ロジェクトã®é–“ã®ãƒ•ã‚©ãƒ¼ã‚¯é–¢ä¿‚を削除ã—ã¾ã™ã€‚"
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "エントリーを手動ã§è¿½åŠ ã™ã‚‹ã«ã¯ã€ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã®ã‚¢ãƒ—リケーションã«æ¬¡ã®è©³ç´°ã‚’入力ã—ã¦ãã ã•ã„"
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr "内部ユーザーを定義ã™ã‚‹ãŸã‚ã«ã¯ã€å…ˆã«æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’外部ユーザーã«è¨­å®šã§ãるよã†ã«ã—ã¾ã™ã€‚"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr "コミットã®èª¬æ˜Žã®åˆ‡ã‚Šæ›¿ãˆ"
msgid "Toggle commit list"
msgstr "コミットリストを切り替ãˆ"
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr "絵文字リアクションをトグル"
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "パフォーマンスãƒãƒ¼ã®åˆ‡ã‚Šæ›¿ãˆ"
@@ -41226,6 +41971,9 @@ msgstr "アーティファクトã®ã‚µã‚¤ã‚º(åˆè¨ˆ): %{total_size}"
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "GitLab ã«æˆ»ã‚‹"
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "アーティファクト"
@@ -42096,10 +42848,10 @@ msgstr "ç¾åœ¨ã®ä½¿ç”¨çŠ¶æ³"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr "リãƒã‚¸ãƒˆãƒª"
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr "ユーザーã®è­˜åˆ¥å­ã‚’正常ã«å‰Šé™¤ã§ãã¾ã—ãŸã€‚"
msgid "User identity was successfully updated."
msgstr "ユーザーã®è­˜åˆ¥å­ã‚’正常ã«æ›´æ–°ã§ãã¾ã—ãŸã€‚"
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr "次ã®å ´æ‰€ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„るユーザー"
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "ユーザーを正常ã«è¿½åŠ ã§ãã¾ã—ãŸã€‚"
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr "è­²å—人ãªã— - %{openingTag} 自分自身を割り当ã¦ã‚‹ %{closing
msgid "UsersSelect|Unassigned"
msgstr "未割り当ã¦"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr "ã“ã®å¤‰æ›´å‰ã® blame を表示"
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,8 +43954,8 @@ msgstr "ドキュメントã®è¡¨ç¤º"
msgid "View eligible approvers"
msgstr "資格ã®ã‚る承èªè€…を表示"
-msgid "View epics list"
-msgstr "エピックリストを表示"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "ファイル"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,12 +44400,12 @@ msgstr "イメージ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "リンク"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr ""
@@ -43633,6 +44415,9 @@ msgstr "åå‰ç©ºé–“"
msgid "Vulnerability|Project"
msgstr "プロジェクト"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "é‡è¦åº¦"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "状態"
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr "Prometheusサーãƒãƒ¼ã«åˆ°é”ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚サーãƒãƒ¼ã
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "%{humanized_resource_name} ã«ã‚¹ãƒ‘ムãŒã‚ã‚‹å¯èƒ½æ€§ã‚’検出ã—ã¾ã—ãŸã€‚続行ã™ã‚‹ã«ã¯ reCAPTCHA を実行ã—ã¦ãã ã•ã„。"
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr "デプロイイベント"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "SSL証明書検証ã®æœ‰åŠ¹åŒ–"
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr "Webhook ã«ç§»å‹•"
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "イシューイベント"
msgid "Webhooks|Job events"
msgstr "ジョブイベント"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr "SSL検証"
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。"
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«Zoomコールを追加ã—ã¾ã—ãŸ"
@@ -45817,6 +46656,9 @@ msgstr "by"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr "コメント"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "%{link_to_project} ã«ã¤ã„ã¦ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸ"
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ç¾åœ¨ã€ãƒ—ロジェクトレベルã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。"
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr "%{project_limit} ã®åˆ¶é™ã«é”ã—ã¾ã—ãŸ"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr "metric_id ã¯ãƒ—ロジェクト全体ã§ä¸€æ„ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr "ã¾ãŸã¯"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "テスト全件数 %d ã®ã†ã¡"
@@ -47349,6 +48207,9 @@ msgstr "ウェイトを削除"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‹ã‚‰Zoomコールを削除ã—ã¾ã—ãŸã€‚"
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "ã‚¿ã‚°å"
@@ -47554,6 +48422,10 @@ msgstr "%{time_ago} ã«æ›´æ–°"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr "ユーザーã®ã‚¢ãƒã‚¿ãƒ¼"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 3cce8abe02e..c172dd781a0 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index d4eeadfda24..2e4799fe41c 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:26\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 3c55fab6892..4d869b92867 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 15:01\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -24,7 +24,7 @@ msgstr " (%{timeoutSource} 로부터)"
msgid " (squashes %{strongStart}%{count}%{strongEnd} commit)"
msgid_plural " (squashes %{strongStart}%{count}%{strongEnd} commits)"
-msgstr[0] ""
+msgstr[0] " ( %{strongStart}%{count}%{strongEnd} 커밋 스쿼시)"
msgid " Collected %{time}"
msgstr " %{time}ì— ìˆ˜ì§‘í–ˆìŠµë‹ˆë‹¤"
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] "추가 커미터 %d"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%dëª…ì˜ ìŠ¹ì¸ìž"
@@ -135,7 +139,7 @@ msgstr[0] "%dëª…ì˜ ìŠ¹ì¸ìž (ë‚´ê°€ 승ì¸í•¨)"
msgid "%d artifact"
msgid_plural "%d artifacts"
-msgstr[0] ""
+msgstr[0] "%d 아티팩트"
msgid "%d assigned issue"
msgid_plural "%d assigned issues"
@@ -335,7 +339,7 @@ msgstr[0] "%d ì´ˆ"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
+msgstr[0] "%d 스테ì´ì§€"
msgid "%d star"
msgid_plural "%d stars"
@@ -650,7 +654,7 @@ msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgstr ""
msgid "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
-msgstr ""
+msgstr "%{labelStart}í¬ëž˜ì‰¬ ìƒíƒœ: %{labelEnd} %{crash_state}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr ""
@@ -810,7 +814,7 @@ msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues}개 열림, %{closedIssues}개 닫힘"
msgid "%{over_limit_message} To get more members, an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "%{over_limit_message} ë” ë§Žì€ íšŒì›ì„ 확보하기 위해 그룹 소유ìžëŠ” í‰ê°€íŒì„ 시작하거나 유료 등급으로 업그레ì´ë“œí•  수 있습니다."
msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
msgstr "%{over_limit_message} ë” ë§Žì€ ì¢Œì„ì„ ì–»ìœ¼ë ¤ë©´ %{link_start}유료 요금제%{link_end}ë¡œ 업그레ì´ë“œí•˜ì‹­ì‹œì˜¤."
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start}부터 %{end}까지"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}경고:%{strongClose} SAML 그룹 ë§í¬ë¡œ ì¸í•´ GitLabì´ ê·¸ë£¹ì—ì„œ 구성ì›ì„ ìžë™ìœ¼ë¡œ 제거할 수 있습니다."
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr "%{template_project_id}(ì€)는 ì•Œ 수 없거나 잘못ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "%{text} is available"
msgstr "%{text} 사용 가능"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name}ì€(는) 프로ì íŠ¸ë‚˜ ê·¸ë£¹ì— ì†í•´ì•¼í•©ë‹ˆë‹¤."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr "%{total} ë‚¨ì€ ì´ìŠˆ 가중치"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} ì€ %{name} ì´ë¦„만 지ì›í•©ë‹ˆë‹¤."
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "%{user_name} 프로필 페ì´ì§€"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr "%{value}ì´ˆ"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} ì‹œê°„ì´ ì§€ë‚¬ìŠµë‹ˆë‹¤."
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} ì´ %{noun} ì„ ì´ˆì•ˆìœ¼ë¡œ."
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} ì´ %{noun} ì„ ì¤€ë¹„ ìƒíƒœë¡œ"
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1479,10 +1492,10 @@ msgid "A complete DevOps platform"
msgstr "완벽한 DevOps 플랫í¼"
msgid "A confidential issue cannot have a parent that already has non-confidential children."
-msgstr ""
+msgstr "기밀 ì´ìŠˆëŠ” ì´ë¯¸ ê¸°ë°€ì´ ì•„ë‹Œ ìžì‹ì´ 있는 부모를 가질 수 없습니다."
msgid "A confidential work item cannot have a parent that already has non-confidential children."
-msgstr ""
+msgstr "기밀 ìž‘ì—… í•­ëª©ì€ ì´ë¯¸ ê¸°ë°€ì´ ì•„ë‹Œ ìžì‹ í•­ëª©ì´ ìžˆëŠ” 부모 í•­ëª©ì„ ê°€ì§ˆ 수 없습니다."
msgid "A default branch cannot be chosen for an empty project."
msgstr "빈 프로ì íŠ¸ì—서는 기본 브랜치를 ì„ íƒí•  수 없습니다."
@@ -1535,9 +1548,6 @@ msgstr "새 릴리스 %{tag}(ì´)ê°€ %{name}(으)ë¡œ 공개ë˜ì—ˆìŠµë‹ˆë‹¤. 릴ë
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr "새 ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -1548,14 +1558,23 @@ msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
msgstr ""
msgid "A non-confidential issue cannot have a confidential parent."
-msgstr ""
+msgstr "ê¸°ë°€ì´ ì•„ë‹Œ ì´ìŠˆëŠ” 기밀 부모를 가질 수 없습니다."
msgid "A non-confidential work item cannot have a confidential parent."
-msgstr ""
+msgstr "ê¸°ë°€ì´ ì•„ë‹Œ ìž‘ì—… 항목ì—는 기밀 부모를 가질 수 없습니다."
msgid "A page with that title already exists"
msgstr "ë™ì¼í•œ ì œëª©ì˜ íŽ˜ì´ì§€ê°€ ì´ë¯¸ 존재합니다"
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2040,7 +2059,7 @@ msgid "Add a confidential internal note to this %{noteableDisplayName}."
msgstr ""
msgid "Add a custom message with details about the instance's shared runners. The message is visible when you view runners for projects and groups. Markdown is supported."
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ì˜ 공유 ëŸ¬ë„ˆì— ëŒ€í•œ 세부 ì •ë³´ê°€ í¬í•¨ëœ ì‚¬ìš©ìž ì§€ì • 메시지를 추가합니다. 메시지는 프로ì íŠ¸ ë° ê·¸ë£¹ì˜ ëŸ¬ë„ˆë¥¼ ë³¼ ë•Œ 표시ë©ë‹ˆë‹¤. 마í¬ë‹¤ìš´ì´ 지ì›ë©ë‹ˆë‹¤."
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "ì´ %{noteableDisplayName} ì— ì¼ë°˜ì ì¸ 코멘트를 추가 합니다."
@@ -2067,7 +2086,7 @@ msgid "Add a table"
msgstr "í…Œì´ë¸” 추가"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "ì¸ì‹œë˜íŠ¸ì— 타임ë¼ì¸ ì´ë²¤íŠ¸ 추가"
msgid "Add a title..."
msgstr ""
@@ -2163,10 +2182,10 @@ msgid "Add label(s)"
msgstr "ë ˆì´ë¸” 추가"
msgid "Add labels"
-msgstr ""
+msgstr "ë ˆì´ë¸” 추가"
msgid "Add license"
-msgstr ""
+msgstr "ë¼ì´ì„ ìŠ¤ 추가"
msgid "Add list"
msgstr "ëª©ë¡ ì¶”ê°€"
@@ -2237,12 +2256,6 @@ msgstr "사용ìžê°€ 쉽게 ì°¾ì„ ìˆ˜ 있ë„ë¡ í”„ë¡œì íŠ¸ì— 주제를 추ê°
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€:"
-
-msgid "Add users to group"
-msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€"
-
msgid "Add variable"
msgstr "변수 추가"
@@ -2340,7 +2353,7 @@ msgid "Adds a Zoom meeting."
msgstr "Zoom íšŒì˜ ì¶”ê°€í•˜ê¸°"
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "ì¸ì‹œë˜íŠ¸ì— 타임ë¼ì¸ ì´ë²¤íŠ¸ 추가."
msgid "Adds a to do."
msgstr "í•  ì¼ ì¶”ê°€."
@@ -2604,7 +2617,7 @@ msgid "AdminSettings|Enable Service Ping"
msgstr "서비스 핑 활성화"
msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
-msgstr ""
+msgstr "ì‘ìš© 프로그램 메트릭 ìˆ˜ì§‘ì„ í™œì„±í™”í•©ë‹ˆë‹¤. 다시 시작해야 합니다. %{link_start}Prometheus%{link_end}ë¡œ ë©”íŠ¸ë¦­ì„ ë‚´ë³´ë‚´ëŠ” ë°©ë²•ì„ ì•Œì•„ë´…ë‹ˆë‹¤."
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
msgstr ""
@@ -2634,11 +2647,17 @@ msgid "AdminSettings|Feed token"
msgstr "피드 토í°"
msgid "AdminSettings|Git abuse rate limit"
-msgstr ""
+msgstr "Git 악용 비율 제한"
+
+msgid "AdminSettings|Group runners expiration"
+msgstr "그룹 러너 만료"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "단위를 쓰지 않으면 기본ì ìœ¼ë¡œ 초가 사용ë©ë‹ˆë‹¤. 예를 들어, %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}ë˜ëŠ” %{oneDayHumanReadable}는 ëª¨ë‘ ë™ì¼í•©ë‹ˆë‹¤. ìµœì†Œê°’ì€ 2시간입니다. %{linkStart}ìžì„¸ížˆ 알아보십시오.%{linkEnd}"
+
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}입니다. 기존 ì €ìž¥ì†Œì— ì˜í–¥ì„ 주지 않습니다."
@@ -2651,6 +2670,9 @@ msgstr "소스 가져오기"
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr "ì¸ìŠ¤í„´ìŠ¤ 러너 만료"
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "프로ì íŠ¸ë‹¹ 최대 ì‚¬ìš©ìž ì •ì˜ ë„ë©”ì¸ ìˆ˜"
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr "페ì´ë¡œë“œ 미리보기"
msgid "AdminSettings|Project export"
msgstr "프로ì íŠ¸ 내보내기"
+msgid "AdminSettings|Project runners expiration"
+msgstr "프로ì íŠ¸ 러너 만료"
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "ì´ë¥¼ 비활성화하려면 제한 ê°’ì„ 0으로 설정하십시오."
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "새로 등ë¡ëœ 그룹 ëŸ¬ë„ˆì˜ ì¸ì¦ í† í° ë§Œë£Œ ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "새로 등ë¡ëœ ì¸ìŠ¤í„´ìŠ¤ ëŸ¬ë„ˆì˜ ì¸ì¦ í† í° ë§Œë£Œ ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤. ì¸ì¦ 토í°ì€ ì´ ê°„ê²©ìœ¼ë¡œ ìžë™ìœ¼ë¡œ 재설정ë©ë‹ˆë‹¤."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "새로 등ë¡ëœ 프로ì íŠ¸ ëŸ¬ë„ˆì˜ ì¸ì¦ í† í° ë§Œë£Œ ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤."
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "프로ì íŠ¸ë‹¹ GitLab 페ì´ì§€ ì‚¬ìš©ìž ì •ì˜ ë„ë©”ì¸ì˜ 최대 수를 설정합니다(ë¬´ì œí•œì˜ ê²½ìš° 0). %{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 ""
@@ -2865,7 +2905,7 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA 사용"
msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user. Validated users can use free CI minutes on shared runners."
-msgstr ""
+msgstr "사용ìžëŠ” ì‹ ìš©/ì§ë¶ˆ 카드를 입력하여 ìžì‹ ì„ 확ì¸í•˜ê±°ë‚˜ 관리ìžê°€ 수ë™ìœ¼ë¡œ 사용ìžë¥¼ 확ì¸í•  수 있습니다. ê²€ì¦ëœ 사용ìžëŠ” 공유 러너ì—ì„œ 무료 CI 회ì˜ë¡ì„ 사용할 수 있습니다."
msgid "AdminUsers|Access"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr "차단ë¨"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "사용ìžë¥¼ 차단하면 다ìŒê³¼ ê°™ì€ íš¨ê³¼ê°€ 있습니다."
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "그룹 ìƒì„± 가능"
@@ -3024,7 +3067,7 @@ msgid "AdminUsers|It's you!"
msgstr "ì´ê²ƒì€ 나!"
msgid "AdminUsers|LDAP Blocked"
-msgstr ""
+msgstr "LDAP 차단ë¨"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
@@ -3084,7 +3127,7 @@ msgid "AdminUsers|Rejected users:"
msgstr "ê±°ë¶€ëœ ì‚¬ìš©ìž:"
msgid "AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in."
-msgstr ""
+msgstr "리셋 ë§í¬ê°€ ìƒì„±ë˜ì–´ 사용ìžì—게 전송ë©ë‹ˆë‹¤. 사용ìžëŠ” ì²˜ìŒ ë¡œê·¸ì¸í•  ë•Œ 비밀번호를 설정해야 합니다."
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
@@ -3105,7 +3148,7 @@ msgid "AdminUsers|Sort by"
msgstr "정렬 기준"
msgid "AdminUsers|The maximum number of CI/CD minutes on shared runners that a group can use each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
-msgstr ""
+msgstr "ê·¸ë£¹ì´ ë§¤ì›” 사용할 수 있는 공유 ëŸ¬ë„ˆì˜ ìµœëŒ€ CI/CD 시간(분). ë¬´ì œí•œì˜ ê²½ìš° 0ì„ ì„¤ì •í•©ë‹ˆë‹¤. %{minutes}ì˜ ì „ì—­ ì„¤ì •ì„ ìƒì†í•˜ë ¤ë©´ 공백으로 설정하십시오."
msgid "AdminUsers|The user can't access git repositories."
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "비밀번호가 성공ì ìœ¼ë¡œ ë³€ê²½ëœ ë’¤ì— ë¡œê·¸ì¸ í™”ë©´ìœ¼ë¡œ ì´ë™ 합니다."
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr "모든 프로ì íŠ¸ 구성ì›"
+
msgid "All projects"
msgstr "모든 프로ì íŠ¸"
@@ -3729,7 +3787,7 @@ msgid "All threads resolved!"
msgstr "모든 스레드가 í•´ê²°ë˜ì—ˆìŠµë‹ˆë‹¤!"
msgid "All users in this group must set up two-factor authentication"
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì˜ ëª¨ë“  사용ìžëŠ” ì´ì¤‘ ì¸ì¦ì„ 설정해야 합니다."
msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
msgstr "GitLabì— ì•¡ì„¸ìŠ¤í•˜ë ¤ë©´ 모든 사용ìžê°€ 서비스 약관 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…ì— ë™ì˜í•´ì•¼ 합니다."
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr "ë¼ì´ì„ ìŠ¤ëœ EE 기능 사용 허용"
+msgid "Allow users to create top-level groups"
+msgstr "사용ìžê°€ 최ìƒìœ„ ê·¸ë£¹ì„ ë§Œë“¤ 수 있ë„ë¡ í—ˆìš©"
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -3885,7 +3946,7 @@ msgid "An email notification was recently sent from the admin panel. Please wait
msgstr "최근 ê´€ë¦¬ìž íŒ¨ë„ì—ì„œ ì´ë©”ì¼ ì•Œë¦¼ì´ ì „ì†¡ë˜ì—ˆìŠµë‹ˆë‹¤. 다른 메시지를 보내기 ì „ì— %{wait_time_in_words} 기다리십시오."
msgid "An email will be sent with the report attached after it is generated."
-msgstr ""
+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 í™ ê¸¸ë™)ì„ ì´ìŠˆ ë° ì»¤ë§¨íŠ¸ì˜ ì„¤ëª…ìœ¼ë¡œ 추가 합니다. ë˜í•œ ì´ ì´ìŠˆì™€ 커맨트를 프로ì íŠ¸ 작성ìžì— 알리고 할당 í•  것입니다."
@@ -4079,9 +4140,6 @@ msgstr "ì´ íŽ˜ì´ì§€ì˜ ì„¹ì…˜ì„ ë¡œë“œí•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆ
msgid "An error occurred while loading all the files."
msgstr "모든 파ì¼ì„ 불러오는 ë„ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "차트 ë°ì´í„°ë¥¼ ë¡œë“œí•˜ë˜ ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -4228,7 +4286,7 @@ msgid "An error occurred while trying to generate the report. Please try again l
msgstr ""
msgid "An error occurred while trying to render the content editor. Please try again."
-msgstr ""
+msgstr "콘í…츠 편집기를 ë Œë”ë§í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
msgid "An error occurred while trying to run a new pipeline for this merge request."
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr "ì•Œ 수 없는 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Analytics"
msgstr "분ì„"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -4739,7 +4803,7 @@ msgid "ApprovalSettings|Remove all approvals"
msgstr "모든 ìŠ¹ì¸ ì œê±°"
msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
-msgstr ""
+msgstr "파ì¼ì´ ë³€ê²½ëœ ê²½ìš° 코드 소유ìžì˜ ìŠ¹ì¸ ì œê±°"
msgid "ApprovalSettings|Require user password to approve"
msgstr ""
@@ -4757,7 +4821,7 @@ msgid "ApprovalSettings|This setting is configured in %{groupName} and can only
msgstr ""
msgid "ApprovalSettings|When a commit is added:"
-msgstr ""
+msgstr "ì»¤ë°‹ì´ ì¶”ê°€ë  ë•Œ:"
msgid "Approvals are optional."
msgstr ""
@@ -4835,7 +4899,7 @@ msgid "Archived projects"
msgstr "ì•„ì¹´ì´ë¸Œëœ 프로ì íŠ¸"
msgid "Archiving the project makes it entirely read-only. It is hidden from the dashboard and doesn't display in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ 보관하면 완전히 ì½ê¸° ì „ìš©ì´ ë©ë‹ˆë‹¤. 대시보드ì—ì„œ 숨겨져 ê²€ìƒ‰ì— í‘œì‹œë˜ì§€ 않습니다. %{strong_start}리í¬ì§€í† ë¦¬ë¥¼ 커밋할 수 없으며 문제, ì˜ê²¬ ë˜ëŠ” 기타 엔터티를 만들 수 없습니다.%{strong_end} %{link_start}ìžì„¸ížˆ 알아보세요.%{link_end}"
msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
msgstr "ì´ ê·¸ë£¹ì„ ì œê±°í•˜ëŠ” ê²ƒì´ í™•ì‹¤í•©ë‹ˆê¹Œ?"
@@ -5182,6 +5246,9 @@ msgstr[0] "íŒŒì¼ %d ê°œ 첨부"
msgid "Attaching the file failed."
msgstr "íŒŒì¼ ì²¨ë¶€ê°€ 실패했습니다."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
@@ -5283,7 +5350,7 @@ msgid "AuditStreams|Cancel editing"
msgstr "편집 취소"
msgid "AuditStreams|Custom HTTP headers (optional)"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì •ì˜ HTTP í—¤ë”(옵션)"
msgid "AuditStreams|Delete %{link}"
msgstr ""
@@ -5301,10 +5368,10 @@ msgid "AuditStreams|Header"
msgstr "í—¤ë”"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
-msgstr ""
+msgstr "최대 %{number} ê°œì˜ HTTP í—¤ë”ì— ë„달했습니다."
msgid "AuditStreams|Remove custom header"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì •ì˜ í—¤ë” ì œê±°"
msgid "AuditStreams|Save external stream destination"
msgstr ""
@@ -5466,7 +5533,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 ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "공개 ëœ ëª¨ë“  ê·¸ë£¹ì„ ì•„ëž˜ì—ì„œ ì°¾ì„ ìˆ˜ 있습니다."
+msgid "Beta"
+msgstr "베타"
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,8 +6243,8 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
-msgstr ""
+msgid "Billing|Explore paid plans"
+msgstr "유료 요금제 살펴보기"
msgid "Billing|Export list"
msgstr ""
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr "í‰ê°€íŒ 기간 ë™ì•ˆ íšŒì› ë¬´ì œí•œ"
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6220,7 +6293,7 @@ msgid "Billing|You are about to remove user %{username} from your subscription.
msgstr ""
msgid "Billing|Your group recently changed to use the Free plan. %{over_limit_message} You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
-msgstr ""
+msgstr "ê·€í•˜ì˜ ê·¸ë£¹ì€ ìµœê·¼ 무료 요금제를 사용하ë„ë¡ ë³€ê²½ë˜ì—ˆìŠµë‹ˆë‹¤. %{over_limit_message} ë” ì´ìƒ 액세스할 필요가 없는 사용ìžë¥¼ 제거하거나 초과 제한으로 전환하여 새 회ì›ì„ 위한 ê³µê°„ì„ í™•ë³´í•  수 있습니다. 무제한 회ì›ì„ 얻으려면 %{link_start}업그레ì´ë“œ%{link_end} 를 유료 등급으로 업그레ì´ë“œí•  수 있습니다."
msgid "Bitbucket Server Import"
msgstr "Bitbucket 서버ì—ì„œ 가져 오기"
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "SSH ë° HTTP(S) 모ë‘"
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr "브랜치 규칙"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr "*-stable ë˜ëŠ” production/*ê³¼ ê°™ì€ %{linkStart}와ì¼ë“œì¹´ë“œ%{linkEnd}ê°€ 지ì›ë©ë‹ˆë‹¤."
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "푸시 액세스 ê¶Œí•œì´ ìžˆëŠ” 모든 사용ìžì—게 %{linkStart}ê°•ì œ 푸시%{linkEnd}를 허용합니다."
msgid "BranchRules|Allowed to merge"
msgstr "머지 허용"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "푸시 허용"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr "브랜치를 가져오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr "브랜치"
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr "와ì¼ë“œì¹´ë“œ ìƒì„±: %{searchTerm}"
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr "ì¼ì¹˜í•˜ëŠ” 결과가 없습니다"
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,12 +6718,24 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr "코드 소유ìžì˜ 승ì¸ì´ 필요합니다."
-msgid "BranchRules|default"
+msgid "BranchRules|Roles"
msgstr ""
-msgid "BranchRules|protected"
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
msgstr ""
+msgid "BranchRules|default"
+msgstr "기본값"
+
+msgid "BranchRules|protected"
+msgstr "보호ë¨"
+
msgid "Branches"
msgstr "브랜치"
@@ -6769,7 +6902,7 @@ msgid "Browse templates"
msgstr ""
msgid "Build cannot be erased"
-msgstr ""
+msgstr "빌드를 지울 수 없습니다."
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr ""
@@ -6897,11 +7030,14 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
msgid "Bullet list"
-msgstr ""
+msgstr "글머리 기호 목ë¡"
msgid "Burndown chart"
msgstr ""
@@ -7034,7 +7170,7 @@ msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr "릴리스 통계를 가져오는 ë° ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "CICDAnalytics|Time to restore service"
-msgstr ""
+msgstr "서비스 ë³µì› ì‹œê°„"
msgid "CICDAnalytics|What is shared runner duration?"
msgstr "공유 러너 ì§€ì† ì‹œê°„ì´ëž€ 무엇입니까?"
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr "ë°°í¬ ì „ëžµ"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "ìž‘ì—…"
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7358,7 +7497,7 @@ msgid "Card number:"
msgstr "카드번호:"
msgid "CascadingSettings|Enforce deletion protection for all subgroups"
-msgstr ""
+msgstr "모든 하위 ê·¸ë£¹ì— ëŒ€í•´ ì‚­ì œ 방지 ì ìš©"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr "변경사항:"
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -7777,10 +7919,10 @@ msgid "Checkout|Group"
msgstr ""
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use) or more."
-msgstr ""
+msgstr "%{minimumNumberOfUsers} (사용 ì¤‘ì¸ ì¢Œì„) ì´ìƒì´ì–´ì•¼ 합니다."
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use, plus all over limit members) or more. To buy fewer seats, remove members from the group."
-msgstr ""
+msgstr "%{minimumNumberOfUsers} (사용 ì¤‘ì¸ ì¢Œì„ê³¼ 제한 초과 íšŒì› ëª¨ë‘) ì´ìƒì´ì–´ì•¼ 합니다. ì¢Œì„ ìˆ˜ë¥¼ 줄ì´ë ¤ë©´ 그룹ì—ì„œ 구성ì›ì„ 제거하세요."
msgid "Checkout|Name of company or organization using GitLab"
msgstr ""
@@ -8297,19 +8439,19 @@ msgid "Cloud Storage"
msgstr ""
msgid "CloudSeed|All"
-msgstr ""
+msgstr "ì „ì²´"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "Postgresìš© AlloyDB"
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ë¥¼ ìƒì„±í•  수 있는 사용 가능한 ë°ì´í„°ë² ì´ìŠ¤ 서비스"
msgid "CloudSeed|Cancel"
msgstr "취소"
msgid "CloudSeed|Cloud Firestore"
-msgstr ""
+msgstr "Cloud Firestore"
msgid "CloudSeed|Cloud SQL for MySQL"
msgstr "MySQLìš© Cloud SQL"
@@ -8363,34 +8505,34 @@ msgid "CloudSeed|Deployments"
msgstr ""
msgid "CloudSeed|Description"
-msgstr ""
+msgstr "설명"
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ì— 사용 가능한 메모리 ë° ê°€ìƒ ì½”ì–´ ê²°ì •"
msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "비밀 관리ìžì— ë°ì´í„°ë² ì´ìŠ¤ 변수를 저장하여 보안 ê°•í™” - GitLab%{docLinkEnd}ë¡œ %{docLinkStart}비밀 ê´€ë¦¬ì— ëŒ€í•´ ìžì„¸ížˆ 알아보기"
msgid "CloudSeed|Environment"
-msgstr ""
+msgstr "환경"
msgid "CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development"
-msgstr ""
+msgstr "í´ë¼ì´ì–¸íŠ¸ ë° ì„œë²„ 사ì´ë“œ ê°œë°œì„ ìœ„í•œ 유연하고 확장 가능한 NoSQL í´ë¼ìš°ë“œ ë°ì´í„°ë² ì´ìŠ¤"
msgid "CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads"
-msgstr ""
+msgstr "ë†’ì€ ìš”êµ¬ ìˆ˜ì¤€ì˜ ì›Œí¬ë¡œë“œë¥¼ 위한 완전 관리형 PostgreSQL 호환 서비스"
msgid "CloudSeed|Fully managed relational database service for MySQL"
-msgstr ""
+msgstr "MySQLìš© 완전 관리형 관계형 ë°ì´í„°ë² ì´ìŠ¤ 서비스"
msgid "CloudSeed|Fully managed relational database service for PostgreSQL"
-msgstr ""
+msgstr "PostgreSQLìš© 완전 관리형 관계형 ë°ì´í„°ë² ì´ìŠ¤ 서비스"
msgid "CloudSeed|Fully managed relational database service for SQL Server"
-msgstr ""
+msgstr "SQL Serverìš© 완전 관리형 관계형 ë°ì´í„°ë² ì´ìŠ¤ 서비스"
msgid "CloudSeed|Generated database instance is linked to the selected branch or tag"
-msgstr ""
+msgstr "ìƒì„±ëœ ë°ì´í„°ë² ì´ìŠ¤ ì¸ìŠ¤í„´ìŠ¤ëŠ” ì„ íƒí•œ 브랜치 ë˜ëŠ” íƒœê·¸ì— ì—°ê²°ë©ë‹ˆë‹¤."
msgid "CloudSeed|Google Cloud Error - %{message}"
msgstr "구글 í´ë¼ìš°ë“œ 오류 - %{message}"
@@ -8408,19 +8550,19 @@ msgid "CloudSeed|Instances"
msgstr "ì¸ìŠ¤í„´ìŠ¤"
msgid "CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}."
-msgstr ""
+msgstr "%{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} ë° %{firestorePricingStart}Firestore%{firestorePricingEnd}ì˜ ê°€ê²© ì •ì±…ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
msgid "CloudSeed|Machine type"
-msgstr ""
+msgstr "머신 유형"
msgid "CloudSeed|Memorystore for Redis"
-msgstr ""
+msgstr "Redis용 메모리 저장소"
msgid "CloudSeed|No instances"
msgstr "ì¸ìŠ¤í„´ìŠ¤ ì—†ìŒ"
msgid "CloudSeed|Refs"
-msgstr ""
+msgstr "참조"
msgid "CloudSeed|Regions"
msgstr "지역"
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr "%{userName}ì— ì˜í•´ 토í°ì´ 취소ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9090,7 +9247,7 @@ msgid "ClusterIntegration|The certificate-based method to connect clusters to Gi
msgstr ""
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, and Web terminals."
-msgstr ""
+msgstr "프로ì íŠ¸ì™€ ê´€ë ¨ëœ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤. ì´ê²ƒì€ ë°°í¬ ë³´ë“œ ë° ì›¹ 터미ë„ì— ì‚¬ìš©ë©ë‹ˆë‹¤."
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr "커밋:"
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "머지 리퀘스트(MR) ë°ì´í„°ë¥¼ ë°˜ì˜í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -9448,7 +9608,7 @@ msgid "Compare Revisions"
msgstr "리비전 비êµ"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "브랜치를 비êµí•˜ê³  계ì†"
msgid "Compare changes"
msgstr "변경 사항 비êµ"
@@ -9516,6 +9676,9 @@ msgstr "완료"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr "ê°€ìž…ì„ ìœ„í•´ ì¸ì¦ì„ 완료하세요."
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr "컨테ì´ë„ˆ 레지스트리"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -9951,7 +10117,7 @@ msgid "ContainerRegistry|CLI Commands"
msgstr ""
msgid "ContainerRegistry|Clean up image tags"
-msgstr ""
+msgstr "ContainerRegistry|ì´ë¯¸ì§€ 태그 정리"
msgid "ContainerRegistry|Cleanup disabled"
msgstr ""
@@ -10026,7 +10192,7 @@ msgid "ContainerRegistry|Docker connection error"
msgstr ""
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "정리 규칙 편집"
msgid "ContainerRegistry|Enable expiration policy"
msgstr ""
@@ -10129,13 +10295,13 @@ msgid "ContainerRegistry|Run cleanup:"
msgstr ""
msgid "ContainerRegistry|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 "ContainerRegistry|컨테ì´ë„ˆ 레지스트리ì—ì„œ 태그를 ìžë™ìœ¼ë¡œ 삭제하고 ì›í•˜ëŠ” 태그를 유지하여 저장 ê³µê°„ì„ ì ˆì•½í•©ë‹ˆë‹¤. %{linkStart}정리는 ë°©ë²•ì— ëŒ€í•œ ìƒì„¸ì •ë³´%{linkEnd}"
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "정리 규칙 설정"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "저장 ê³µê°„ì„ ì ˆì•½í•˜ê¸° 위해 사용하지 않는 패키지를 ìžë™ìœ¼ë¡œ 제거하ë„ë¡ ê·œì¹™ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "ContainerRegistry|Set up cleanup"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr "기여ìž"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr "êµ­ê°€"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "CreateGitTag|메시지를 íƒœê·¸ì— ì¶”ê°€í•©ë‹ˆë‹¤. ì´ ê³µë°±ì„ ë‚¨ê²¨ë‘ë©´ %{linkStart}lightweight 태그%{linkEnd}ê°€ ìƒì„±ë©ë‹ˆë‹¤."
+
+msgid "CreateGitTag|Set tag message"
+msgstr "CreateGitTag|태그 메시지를 설정합니다."
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -11155,7 +11333,7 @@ msgid "Critical vulnerabilities present"
msgstr ""
msgid "Crm|Active"
-msgstr ""
+msgstr "활성"
msgid "Crm|Contact"
msgstr ""
@@ -11564,7 +11742,7 @@ msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Change failure rate"
-msgstr ""
+msgstr "DORA4Metrics|실패율 변경"
msgid "DORA4Metrics|Change failure rate (percentage)"
msgstr "DORA4Metrics|실패율(í¼ì„¼íŠ¸) 변경"
@@ -11573,7 +11751,7 @@ msgid "DORA4Metrics|Date"
msgstr ""
msgid "DORA4Metrics|Days for an open incident"
-msgstr ""
+msgstr "DORA4Metrics|ì¸ì‹œë˜íŠ¸ê°€ ì˜¤í”ˆëœ ê¸°ê°„ (ì¼)"
msgid "DORA4Metrics|Days from merge to deploy"
msgstr ""
@@ -11591,13 +11769,13 @@ msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Median time (last %{days}d)"
-msgstr ""
+msgstr "DORA4Metrics|중간값 시간(지난 %{days}ì¼)"
msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
-msgstr ""
+msgstr "DORA4Metrics|주어진 기간 ë™ì•ˆ 프로ë•ì…˜ 환경ì—ì„œ ì¸ì‹œë˜íŠ¸ê°€ ì—´ë ¤ìžˆì—ˆë˜ ì‹œê°„ì˜ ì¤‘ê°„ê°’ìž…ë‹ˆë‹¤."
msgid "DORA4Metrics|No incidents during this period"
-msgstr ""
+msgstr "DORA4Metrics|ì´ ê¸°ê°„ ë™ì•ˆ ì¸ì‹œë˜íŠ¸ ì—†ìŒ"
msgid "DORA4Metrics|No merge requests were deployed during this period"
msgstr ""
@@ -11606,13 +11784,13 @@ msgid "DORA4Metrics|Number of deployments"
msgstr ""
msgid "DORA4Metrics|Number of incidents divided by the number of deployments to a production environment in the given time period."
-msgstr ""
+msgstr "DORA4Metrics|주어진 기간 ë™ì•ˆ ì¸ì‹œë˜íŠ¸ 수를 프로ë•ì…˜ í™˜ê²½ì— ëŒ€í•œ ë°°í¬ ìˆ˜ë¡œ 나눈 ê°’ 입니다."
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr ""
+msgstr "DORA4Metrics|ë°°í¬ì— 실패한 비율"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr ""
+msgstr "DORA4Metrics|실패율 ë°ì´í„°ë¥¼ 변경하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
msgstr ""
@@ -11621,7 +11799,7 @@ msgid "DORA4Metrics|Something went wrong while getting lead time data."
msgstr ""
msgid "DORA4Metrics|Something went wrong while getting time to restore service data."
-msgstr ""
+msgstr "DORA4Metrics|서비스 ë°ì´í„°ë¥¼ ë³µì› ì‹œê°„ì„ ê°€ì ¸ì˜¤ëŠ” ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
@@ -11630,7 +11808,7 @@ msgid "DORA4Metrics|The chart displays the median time between a merge request b
msgstr ""
msgid "DORA4Metrics|Time to restore service"
-msgstr ""
+msgstr "DORA4Metrics|서비스 ë³µì› ì‹œê°„"
msgid "DORA4Metrics|Time to restore service (median days)"
msgstr "DORA4Metrics|서비스 ë³µì› ì‹œê°„ (median days)"
@@ -11669,7 +11847,7 @@ msgid "DastConfig|DAST CI/CD configuration"
msgstr "DAST CI/CD 설정"
msgid "DastConfig|Enable DAST to automatically test for vulnerabilities in your project's running application, website, or API, in the CI/CD pipeline. Configuration changes must be applied to your .gitlab-ci.yml file to take effect. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
-msgstr ""
+msgstr "DAST를 활성화하여 CI/CD 파ì´í”„ë¼ì¸ì—ì„œ 프로ì íŠ¸ì˜ 실행 ì¤‘ì¸ ì• í”Œë¦¬ì¼€ì´ì…˜, 웹사ì´íŠ¸ ë˜ëŠ” APIì˜ ì·¨ì•½ì ì„ ìžë™ìœ¼ë¡œ 테스트합니다. ì ìš©í•˜ë ¤ë©´ .gitlab-ci.yml 파ì¼ì— 설정 변경 ì‚¬í•­ì„ ì ìš©í•´ì•¼ 합니다. 모든 구성 ì˜µì…˜ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì€ %{linkStart}GitLab DAST 문서%{linkEnd}ì„ ì°¸ì¡°í•˜ì‹­ì‹œì˜¤."
msgid "DastConfig|Enabled"
msgstr "활성화ë¨"
@@ -11690,10 +11868,10 @@ msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and resp
msgstr ""
msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "스ìºë„ˆ í”„ë¡œí•„ì€ ë³´ì•ˆ 스ìºë„ˆì˜ 구성 세부 정보를 ì •ì˜í•©ë‹ˆë‹¤. %{linkStart}ìžì„¸ížˆ 알아보기%{linkEnd}."
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "사ì´íŠ¸ í”„ë¡œí•„ì€ ë°°í¬ëœ 애플리케ì´ì…˜, 웹 사ì´íŠ¸ ë˜ëŠ” APIì˜ ì†ì„± ë° êµ¬ì„± 세부 정보를 ì •ì˜í•©ë‹ˆë‹¤. %{linkStart}ìžì„¸ížˆ 알아보기%{linkEnd}."
msgid "DastProfiles|AJAX spider"
msgstr ""
@@ -11897,10 +12075,10 @@ msgid "DastProfiles|Scanner name"
msgstr ""
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "스ìºë„ˆ 프로필"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "스ìºë„ˆ 프로필"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr ""
@@ -11924,10 +12102,10 @@ msgid "DastProfiles|Site name"
msgstr ""
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "사ì´íŠ¸ 프로필"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "사ì´íŠ¸ 프로필"
msgid "DastProfiles|Site type"
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr "아티팩트 삭제"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr "ì‚­ì œë¨"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr "ì‚­ì œëœ ì»¤ë°‹:"
+
msgid "Deleted projects cannot be restored!"
msgstr "ì‚­ì œëœ í”„ë¡œì íŠ¸ëŠ” ë³µì›í•  수 없습니다!"
@@ -12519,31 +12709,31 @@ msgid "Deletion pending. This project will be deleted on %{date}. Repository and
msgstr "ì‚­ì œ 대기 중. ì´ í”„ë¡œì íŠ¸ëŠ” %{date}ì— ì‚­ì œë©ë‹ˆë‹¤. 저장소와 다른 프로ì íŠ¸ 리소스는 ì½ê¸° 전용입니다."
msgid "DeletionSettings|All projects are deleted immediately."
-msgstr ""
+msgstr "모든 프로ì íŠ¸ê°€ 즉시 ì‚­ì œë©ë‹ˆë‹¤."
msgid "DeletionSettings|Deletion protection"
-msgstr ""
+msgstr "삭제 방지"
msgid "DeletionSettings|Keep deleted"
-msgstr ""
+msgstr "ì‚­ì œëœ ìƒíƒœë¡œ 유지"
msgid "DeletionSettings|Keep deleted projects for %{number} days"
-msgstr ""
+msgstr "ì‚­ì œëœ í”„ë¡œì íŠ¸ë¥¼ %{number} ì¼ ë™ì•ˆ ë³´ê´€"
msgid "DeletionSettings|Keep deleted projects for 1 day"
-msgstr ""
+msgstr "하루 ë™ì•ˆ ì‚­ì œëœ í”„ë¡œì íŠ¸ 유지"
msgid "DeletionSettings|None, delete immediately"
msgstr "ì—†ìŒ, 즉시 ì‚­ì œ"
msgid "DeletionSettings|Only administrators can delete projects."
-msgstr ""
+msgstr "관리ìžë§Œ 프로ì íŠ¸ë¥¼ 삭제할 수 있습니다."
msgid "DeletionSettings|Owners and administrators can delete projects."
-msgstr ""
+msgstr "소유ìžì™€ 관리ìžëŠ” 프로ì íŠ¸ë¥¼ 삭제할 수 있습니다."
msgid "DeletionSettings|Retention period that deleted groups and projects will remain restorable. Personal projects are always deleted immediately. Some groups can opt-out their projects."
-msgstr ""
+msgstr "ì‚­ì œëœ ê·¸ë£¹ ë° í”„ë¡œì íŠ¸ê°€ ë³µì› ê°€ëŠ¥í•œ ìƒíƒœë¡œ 유지ë˜ëŠ” ë³´ì¡´ 기간입니다. ê°œì¸ í”„ë¡œì íŠ¸ëŠ” í•­ìƒ ì¦‰ì‹œ ì‚­ì œë©ë‹ˆë‹¤. ì¼ë¶€ ê·¸ë£¹ì€ í”„ë¡œì íŠ¸ë¥¼ ì„ íƒ í•´ì œí•  수 있습니다."
msgid "Denied"
msgstr ""
@@ -12678,7 +12868,7 @@ msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
-msgstr ""
+msgstr "ìºì‹œ 지우기를 위한 종ì†ì„± 프ë¡ì‹œ ë° ì„¤ì •ì„ í™œì„±í™”í•©ë‹ˆë‹¤."
msgid "DependencyProxy|Image list"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr "ì½ê¸° 엑세스 ì „ìš©"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "활성 ë°°í¬ í† í° (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr "토í°ì˜ ì‚¬ìš©ìž ì´ë¦„ì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤. ê¸°ë³¸ê°’ì€ %{code_st
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "만료"
@@ -12896,6 +13092,9 @@ msgstr "%{name} 취소"
msgid "DeployTokens|Scopes"
msgstr "범위"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "ì‚¬ìš©ìž ì´ë¦„"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,19 +13370,10 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "ì´ ëŒ“ê¸€ì˜ ë³€ê²½ ì‚¬í•­ì„ ì·¨ì†Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "ì´ ëŒ“ê¸€ ìž‘ì„±ì„ ì·¨ì†Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
-msgid "DesignManagement|Cancel changes"
-msgstr ""
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr ""
-
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
@@ -13195,6 +13382,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "댓글"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr ""
@@ -13213,11 +13406,11 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "토론"
msgid "DesignManagement|Download design"
msgstr ""
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13298,7 +13485,7 @@ msgid "Details (default)"
msgstr ""
msgid "Details block"
-msgstr ""
+msgstr "세부 ì •ë³´ 블ë¡"
msgid "Detect host keys"
msgstr "호스트 키 발견"
@@ -13313,7 +13500,7 @@ msgid "DevOps adoption"
msgstr ""
msgid "Development"
-msgstr ""
+msgstr "개발"
msgid "Devices (optional)"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr "ë„ë©”ì¸"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr "ë„ë©”ì¸ ì¸ì¦"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "ë„ë©”ì¸ì„ 어떻게 구성합니까?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "êµ¬ì„±ëœ ë„ë©”ì¸ì´ 없습니다. ì´ ê·¸ë£¹ ê³„ì¸µì˜ í”„ë¡œì íŠ¸ì— ë„ë©”ì¸ì„ 만듭니다."
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "ì´ ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ì— 대해 ë‹¤ìŒ ë„ë©”ì¸ì´ 구성ë©ë‹ˆë‹¤. 확ì¸ëœ ë„ë©”ì¸ê³¼ ì¼ì¹˜í•˜ëŠ” ì´ë©”ì¼ ì£¼ì†Œë¥¼ 가진 사용ìžëŠ” ê³„ì •ì„ í™•ì¸í•  필요가 없습니다."
+
msgid "Don't have a group?"
msgstr ""
@@ -13872,7 +14071,7 @@ msgid "Draft: %{filename}"
msgstr ""
msgid "Drag to reorder prioritized labels and change their relative priority."
-msgstr ""
+msgstr "드래그하여 ìš°ì„  순위가 ì§€ì •ëœ ë ˆì´ë¸”ì„ ìž¬ì •ë ¬í•˜ê³  ìƒëŒ€ì  ìš°ì„  순위를 변경합니다."
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -13896,10 +14095,10 @@ msgid "DropdownWidget|Assign %{issuableAttribute}"
msgstr ""
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "취소"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "%{issuableAttribute} 편집"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr ""
@@ -13917,10 +14116,10 @@ msgid "DropdownWidget|No open %{issuableAttribute} found"
msgstr ""
msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
-msgstr ""
+msgstr "현재 ì§€ì •ëœ %{issuableAttribute} ì„ ë³¼ 수 있는 ê¶Œí•œì´ ì—†ìœ¼ë©° 재지정하면 다시 ì„ íƒí•  수 없습니다."
msgid "DropdownWidget|You don't have permission to view this %{issuableAttribute}."
-msgstr ""
+msgstr "ì´ %{issuableAttribute}ì„ ë³¼ ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Due Date"
msgstr ""
@@ -14144,9 +14343,12 @@ msgstr "위키 페ì´ì§€ 편집"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
-msgid "Edit your search filter and try again."
+msgid "Edit your search and try again"
msgstr ""
+msgid "Edit your search filter and try again."
+msgstr "검색 필터를 수정하고 다시 ì‹œë„하세요."
+
msgid "Edit, lint, and visualize your pipeline."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr "ì´ë©”ì¼"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14334,7 +14533,7 @@ msgid "Enable GitLab Error Tracking"
msgstr "GitLab 오류 ì¶”ì  í™œì„±í™”"
msgid "Enable GitLab Prometheus metrics endpoint"
-msgstr ""
+msgstr "GitLab Prometheus 메트릭 엔드í¬ì¸íŠ¸ 활성화"
msgid "Enable Gitpod"
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "ì´ë©”ì¼ ì•Œë¦¼ 활성화"
@@ -14750,6 +14952,9 @@ msgstr "ë°°í¬"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr "ë°°í¬ê°€ 없습니다."
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "ëª¨ë‘ ë³´ê¸°"
@@ -14823,10 +15034,10 @@ msgid "Environments|There are no deployments for this environment yet. %{linkSta
msgstr ""
msgid "Environments|This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì»¤ë°‹ %{commitId}ë¡œ ì´ í™˜ê²½ì— ëŒ€í•´ %{docsStart}ì§ì „ ë°°í¬ë¥¼ 재시ë„%{docsEnd} 합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Environments|This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì»¤ë°‹ %{commitId}ë¡œ ì´ì „ì— ì„±ê³µí•œ ë°°í¬ë¡œ %{docsStart}ì´ í™˜ê²½ì„ ë¡¤ë°±%{docsEnd} 합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Environments|Upcoming"
msgstr ""
@@ -15006,7 +15217,7 @@ msgid "Error deleting project. Check logs for error details."
msgstr ""
msgid "Error fetching branches"
-msgstr ""
+msgstr "브랜치를 가져오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error fetching burnup chart data"
msgstr ""
@@ -15451,7 +15662,7 @@ msgid "Everyone With Access"
msgstr ""
msgid "Everyone can access the wiki."
-msgstr ""
+msgstr "누구나 위키를 사용할 수 있습니다."
msgid "Everyone can contribute"
msgstr "모ë‘ê°€ 기여할 수 있ìŒ."
@@ -15595,7 +15806,7 @@ msgid "Expires"
msgstr ""
msgid "Expires %{preposition} %{expires_at}"
-msgstr ""
+msgstr "만료 %{preposition} %{expires_at}"
msgid "Expires on"
msgstr ""
@@ -15760,7 +15971,7 @@ msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
msgstr ""
msgid "ExternalWikiService|Enter the URL to the external wiki."
-msgstr ""
+msgstr "외부 ìœ„í‚¤ì— ëŒ€í•œ URLì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤."
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "ì´ëª¨ì§€ 목ë¡ì„ 불러올 수 없습니다"
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -15918,7 +16126,7 @@ msgid "Failed to load groups, users and deploy keys."
msgstr ""
msgid "Failed to load groups."
-msgstr ""
+msgstr "ê·¸ë£¹ì„ ë¡œë“œí•˜ì§€ 못했습니다."
msgid "Failed to load iteration cadences."
msgstr ""
@@ -16510,13 +16718,13 @@ msgid "Flags"
msgstr ""
msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
-msgstr ""
+msgstr "FLoC 참여 여부를 설정합니다. %{floc_link_start}FLoCì´ëž€ 무엇입니까?%{floc_link_end}"
msgid "FloC|Federated Learning of Cohorts (FLoC)"
-msgstr ""
+msgstr "FLoC(Federated Learning of Cohort)"
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "FLoCì— ì°¸ì—¬"
msgid "FlowdockService|Enter your Flowdock token."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr "ë” ë¹ ë¥¸ íƒìƒ‰ì„ 위해 모든 기ë¡ì´ 표시ë˜ì§€ëŠ” 않습니다."
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16666,7 +16877,7 @@ msgid "ForkProject|Select a namespace"
msgstr ""
msgid "ForkProject|Something went wrong while loading data. Please refresh the page to try again."
-msgstr ""
+msgstr "ForkProject|ë°ì´í„°ë¥¼ 로드하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하려면 페ì´ì§€ë¥¼ 새로고침하세요."
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -16716,12 +16927,45 @@ msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
-msgstr[0] ""
+msgstr[0] "무료 요금제ì—ì„œ ê·¸ë£¹ì€ êµ¬ì„±ì›ì´ %{free_user_limit}명으로 제한ë˜ë©° 나머지 구성ì›ì€ 제한 초과 ìƒíƒœê°€ ë˜ì–´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없습니다."
+
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "실패"
@@ -17087,10 +17334,10 @@ msgid "Geo|Next sync scheduled at"
msgstr ""
msgid "Geo|No %{replicable_type} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "%{replicable_type} ì„ ì°¾ì„ ìˆ˜ 없습니다. ì´ê²ƒì´ ì˜¤ë¥˜ì¼ ìˆ˜ 있다고 ìƒê°ë˜ë©´ %{linkStart}지역 문제 í•´ê²°%{linkEnd} 문서ì—ì„œ ìžì„¸í•œ 정보를 참조하십시오."
msgid "Geo|No %{replicable} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "%{replicable} ì„ ì°¾ì„ ìˆ˜ 없습니다. ì´ê²ƒì´ ì˜¤ë¥˜ì¼ ìˆ˜ 있다고 ìƒê°ë˜ë©´ %{linkStart}지역 문제 í•´ê²°%{linkEnd} 문서ì—ì„œ ìžì„¸í•œ 정보를 참조하십시오."
msgid "Geo|No Geo site found"
msgstr ""
@@ -17300,7 +17547,7 @@ msgid "Geo|There are no %{replicable_type} to show"
msgstr ""
msgid "Geo|There are no %{replicable} to show"
-msgstr ""
+msgstr "표시할 %{replicable} ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Geo|There was an error deleting the Geo Site"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr "GitLab 로고"
-
msgid "GitLab Pages"
msgstr ""
@@ -17606,7 +17853,7 @@ msgid "GitLab is open source software to collaborate on code."
msgstr ""
msgid "GitLab is undergoing maintenance"
-msgstr ""
+msgstr "GitLabì´ ìœ ì§€ 보수 중입니다."
msgid "GitLab logo"
msgstr ""
@@ -17657,7 +17904,7 @@ msgid "GitLabPages|Are you sure?"
msgstr ""
msgid "GitLabPages|Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
-msgstr ""
+msgstr "GitLabPages|프로ì íŠ¸ë³„ë¡œ 재정ì˜í•  수 있습니다. ì œí•œì´ ì—†ëŠ” 경우 0ì„ ìž…ë ¥í•©ë‹ˆë‹¤. ê°’ì„ ìƒì†í•˜ë ¤ë©´ 비워 둡니다."
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
@@ -17837,7 +18084,7 @@ msgid "Global Shortcuts"
msgstr ""
msgid "Global notification level"
-msgstr ""
+msgstr "글로벌 알림 수준"
msgid "Global notification settings"
msgstr ""
@@ -17927,10 +18174,10 @@ msgid "GlobalSearch|project"
msgstr "프로ì íŠ¸"
msgid "GlobalShortcuts|Copied source branch name to clipboard."
-msgstr ""
+msgstr "í´ë¦½ë³´ë“œì— 소스 브랜치 ì´ë¦„ì„ ë³µì‚¬í–ˆìŠµë‹ˆë‹¤."
msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
-msgstr ""
+msgstr "현재 소스 브랜치 ì´ë¦„ì„ ë³µì‚¬í•  수 없습니다."
msgid "Globally-allowed IP ranges"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr "ì‹œìž‘ì¼ ë° ë§ˆê°ì¼ ì—†ìŒ"
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -18689,7 +18942,7 @@ msgid "GroupSettings|Git abuse rate limit"
msgstr "GroupSettings|Git 악용 비율 제한"
msgid "GroupSettings|Group members are not notified if the group is mentioned."
-msgstr ""
+msgstr "ê·¸ë£¹ì´ ì–¸ê¸‰ëœ ê²½ìš° 그룹 구성ì›ì—게 ì•Œë¦¼ì´ ì „ì†¡ë˜ì§€ 않습니다."
msgid "GroupSettings|Group mentions are disabled"
msgstr ""
@@ -18725,7 +18978,7 @@ msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
msgid "GroupSettings|Reporting"
-msgstr ""
+msgstr "GroupSettings|리í¬íŠ¸"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
@@ -18740,7 +18993,7 @@ msgid "GroupSettings|Select the project containing your custom Insights file. %{
msgstr ""
msgid "GroupSettings|Set a size limit for all content in each Pages site in this group. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "GroupSettings|ì´ ê·¸ë£¹ì˜ ê° íŽ˜ì´ì§€ 사ì´íŠ¸ì— 있는 모든 콘í…ì¸ ì— ëŒ€í•œ í¬ê¸° ì œí•œì„ ì„¤ì •í•©ë‹ˆë‹¤. %{link_start}ìžì„¸ížˆ 알아보기%{link_end}"
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
@@ -18839,13 +19092,13 @@ msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr "ê·¸ë£¹ì€ ì—¬ëŸ¬ 프로ì íŠ¸ì˜ 모ìŒìž…니다."
msgid "GroupsEmptyState|Create new project"
-msgstr ""
+msgstr "GroupsEmptyState|새 프로ì íŠ¸ ìƒì„±"
msgid "GroupsEmptyState|Create new subgroup"
-msgstr ""
+msgstr "GroupsEmptyState|새 하위 그룹 만들기"
msgid "GroupsEmptyState|Groups are the best way to manage multiple projects and members."
-msgstr ""
+msgstr "GroupsEmptyState|ê·¸ë£¹ì€ ì—¬ëŸ¬ 프로ì íŠ¸ì™€ 구성ì›ì„ 관리하는 가장 ì¢‹ì€ ë°©ë²•ìž…ë‹ˆë‹¤."
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
msgstr "프로ì íŠ¸ë¥¼ ê·¸ë£¹ì— êµ¬ì„±í•˜ë©´, 마치 í´ë”처럼 ë™ìž‘합니다."
@@ -18854,16 +19107,16 @@ msgid "GroupsEmptyState|No groups found"
msgstr "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "GroupsEmptyState|No subgroups or projects."
-msgstr ""
+msgstr "GroupsEmptyState|하위 그룹ì´ë‚˜ 프로ì íŠ¸ê°€ 없습니다."
msgid "GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab."
-msgstr ""
+msgstr "GroupsEmptyState|프로ì íŠ¸ëŠ” 코드, 액세스 문제, Wiki ë° Gitlabì˜ ê¸°íƒ€ ê¸°ëŠ¥ì„ ì €ìž¥í•  수 있는 곳입니다."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "그룹 구성ì›ì˜ 사용 ê¶Œí•œì„ ê´€ë¦¬í•˜ê³  ê·¸ë£¹ì˜ ê° í”„ë¡œì íŠ¸ì— ì ‘ê·¼ í•  수 있습니다."
msgid "GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project."
-msgstr ""
+msgstr "GroupsEmptyState|ì´ ê·¸ë£¹ì— í•˜ìœ„ 그룹ì´ë‚˜ 프로ì íŠ¸ë¥¼ 만드는 ë° í•„ìš”í•œ ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤. 새 하위 그룹ì´ë‚˜ 프로ì íŠ¸ë¥¼ 만들려면 ì´ ê·¸ë£¹ì˜ ì†Œìœ ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
msgid "GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr "하위 그룹 ì´ë¦„"
msgid "Groups|Subgroup slug"
msgstr "하위 그룹 슬러그"
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "ê°€ì´ë“œë¼ì¸"
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr "-- 태그"
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19286,7 +19551,7 @@ msgid_plural "Hide charts"
msgstr[0] ""
msgid "Hide comments"
-msgstr ""
+msgstr "댓글 숨기기"
msgid "Hide comments on this file"
msgstr "ì´ íŒŒì¼ì˜ 댓글 숨기기"
@@ -19452,7 +19717,7 @@ msgid "How the job limiter handles jobs exceeding the thresholds specified below
msgstr ""
msgid "How to track time"
-msgstr ""
+msgstr "ì‹œê°„ì„ ì¶”ì í•˜ëŠ” 방법"
msgid "I accept the %{terms_link}"
msgstr "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
@@ -19565,26 +19830,47 @@ msgstr "ì‹ë³„ìž"
msgid "Identities"
msgstr "ID"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
-msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
msgstr ""
+msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
+msgstr "보안 강화를 위해 몇 가지 빠른 단계를 통해 ì‹ ì›ì„ 확ì¸í•´ì•¼ 합니다."
+
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr "GitLabì€ ê²°ì œ 정보를 청구하거나 저장하지 않으며 í™•ì¸ ìš©ë„로만 사용ë©ë‹ˆë‹¤."
+
msgid "IdentityVerification|Help us keep GitLab secure"
-msgstr ""
+msgstr "GitLabì„ ì•ˆì „í•˜ê²Œ 유지하ë„ë¡ ë„와주세요."
msgid "IdentityVerification|Help us protect your account"
msgstr ""
@@ -19599,22 +19885,22 @@ msgid "IdentityVerification|If you've lost access to the email associated to thi
msgstr ""
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "êµ­ì œ ì „í™” 다ì´ì–¼ 코드"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
msgstr ""
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "전화 번호"
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "전화번호는 비워둘 수 없습니다."
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
-msgstr ""
+msgstr "ì „í™” 번호는 %{maxLength} ìžë¦¬ ì´í•˜ì—¬ì•¼ 합니다."
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "ì „í™” 번호는 숫ìžë§Œ í¬í•¨í•´ì•¼ 합니다."
msgid "IdentityVerification|Please enter a valid code"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
+msgstr "코드 보내기"
+
+msgid "IdentityVerification|Something went wrong. Please try again."
msgstr ""
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr "1단계: 전화번호 확ì¸"
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "ê²°ì œ 수단 확ì¸"
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19650,12 +19948,15 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
+msgstr "코드가 í¬í•¨ëœ 문ìžë¥¼ 받게 ë©ë‹ˆë‹¤. 표준 ìš”ê¸ˆì´ ì ìš©ë  수 있습니다."
+
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr "복구 코드를 분실한 경우 새 코드를 ìƒì„±í•˜ì—¬ ì´ì „ ì½”ë
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20823,7 +21139,7 @@ msgid "Include the username in the URL if required: %{code_open}https://username
msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
-msgstr ""
+msgstr "LFS 개체를 í¬í•¨í•©ë‹ˆë‹¤. 그룹 ë˜ëŠ” 프로ì íŠ¸ë³„ë¡œ 재정ì˜í•  수 있습니다. ì œí•œì´ ì—†ëŠ” 경우 0으로 설정합니다."
msgid "Includes an MVC structure to help you get started"
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -20970,7 +21289,7 @@ msgid "Insights"
msgstr "ì¸ì‚¬ì´íŠ¸"
msgid "Insights|Configure a custom report for insights into your group processes such as amount of issues, bugs, and merge requests per month. %{linkStart}How do I configure an insights report?%{linkEnd}"
-msgstr ""
+msgstr "월별로 ì´ìŠˆ, 버그 ë° ë¨¸ì§€ ë¦¬í€˜ìŠ¤íŠ¸ì˜ ì´ëŸ‰ê³¼ ê°™ì€ ê·¸ë£¹ 프로세스를 검토를 í•  수 있는 ì‚¬ìš©ìž í†µí•© 보고서를 구성합니다. %{linkStart}통합 보고서는 어떻게 구성합니까?%{linkEnd}"
msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21241,7 +21572,7 @@ msgid "Integrations|Send notifications about project events to a Unify Circuit c
msgstr ""
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "%{url}ì— ë¡œê·¸ì¸"
msgid "Integrations|Sign in to GitLab"
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "주기 패턴"
-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 ""
@@ -21508,7 +21836,7 @@ msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this gr
msgstr ""
msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "ë” ë§Žì€ íšŒì›ì„ 확보하고 추가 유료 ê¸°ëŠ¥ì— ì•¡ì„¸ìŠ¤í•˜ê¸° 위해 그룹 소유ìžëŠ” í‰ê°€íŒì„ 시작하거나 유료 요금제로 업그레ì´ë“œ 해야 합니다."
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
msgstr ""
@@ -21574,10 +21902,10 @@ msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Show less"
-msgstr ""
+msgstr "간략히 보기"
msgid "InviteMembersModal|Show more (%{count})"
-msgstr ""
+msgstr "(%{count}) ë” ë³´ê¸°"
msgid "InviteMembersModal|Something went wrong"
msgstr ""
@@ -21593,7 +21921,7 @@ msgid "InviteMembersModal|To assign issues to a new team member, you need a proj
msgstr ""
msgid "InviteMembersModal|To get more members an owner of the group can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-msgstr ""
+msgstr "ë” ë§Žì€ íšŒì›ì„ 가입시키기 위해서는 그룹 소유ìžê°€ %{trialLinkStart}í‰ê°€íŒì„ 시작하거나%{trialLinkEnd} ë˜ëŠ” %{upgradeLinkStart}유료 요금제로 업그레ì´ë“œ%{upgradeLinkEnd} 해야 합니다."
msgid "InviteMembersModal|Username or email address"
msgstr ""
@@ -21736,8 +22064,14 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr "ì œê±°ëœ ê²€í†  요청 "
+
+msgid "IssuableEvents|requested review from"
+msgstr "검토 요청 보낸사람"
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
-msgstr ""
+msgstr "%{wi_type}ì´ %{created_at}ì— ìƒì„±ë¨. ìž‘ì„±ìž "
msgid "IssuableStatus|Closed"
msgstr ""
@@ -21746,7 +22080,7 @@ msgid "IssuableStatus|Closed (%{link})"
msgstr ""
msgid "IssuableStatus|Created %{created_at} by"
-msgstr ""
+msgstr "%{created_at}ì— ìƒì„±ë¨ ìž‘ì„±ìž "
msgid "IssuableStatus|duplicated"
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22013,7 +22350,7 @@ msgid "Iteration"
msgstr "ì´í„°ë ˆì´ì…˜"
msgid "Iteration cannot be created for cadence"
-msgstr ""
+msgstr "ì¼€ì´ë˜ìŠ¤ì— 대한 ë°˜ë³µì„ ìƒì„±í•  수 없습니다."
msgid "Iteration changed to"
msgstr ""
@@ -22031,10 +22368,10 @@ msgid "Iterations"
msgstr "ì´í„°ë ˆì´ì…˜"
msgid "Iterations cadence not found"
-msgstr ""
+msgstr "반복 ì¼€ì´ë˜ìŠ¤ë¥¼ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Iterations cannot be manually added to cadences that use automatic scheduling"
-msgstr ""
+msgstr "ìžë™ ì¼ì •ì„ 사용하는 ì¼€ì´ë˜ìŠ¤ì—는 ë°˜ë³µì„ ìˆ˜ë™ìœ¼ë¡œ 추가할 수 없습니다."
msgid "IterationsCadence|The automation start date must come after the active iteration %{iteration_dates}."
msgstr "IterationsCadence|ìžë™í™” 시작 날짜는 활성 반복 %{iteration_dates}ì´í›„여야 합니다."
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -22721,7 +23055,7 @@ msgid "Job|triggered"
msgstr ""
msgid "Join GitLab today! You and your team can plan, build, and ship secure code all in one application. Get started here for free!"
-msgstr ""
+msgstr "지금 GitLabì— ê°€ìž…í•˜ì„¸ìš”! 당신과 ë‹¹ì‹ ì˜ íŒ€ì€ ëª¨ë‘ í•˜ë‚˜ì˜ ì• í”Œë¦¬ì¼€ì´ì…˜ì—ì„œ 보안 코드를 계íš, 빌드 ë° ì œê³µí•  수 있습니다. 여기ì—ì„œ 무료로 시작하세요!"
msgid "Join Zoom meeting"
msgstr ""
@@ -22935,7 +23269,7 @@ msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì¹´í…Œê³ ë¼ì´ì¦ˆë¥¼ 위해 ì ìš©ê°€ëŠ¥í•©ë‹ˆë‹¤."
msgid "Labels can be applied to issues and merge requests. Star a label to make it a priority label."
-msgstr ""
+msgstr "ë ˆì´ë¸”ì€ ë¬¸ì œ ë° ë¨¸ì§€ ë¦¬í€˜ìŠ¤íŠ¸ì— ì ìš©í•  수 있습니다. ë ˆì´ë¸”ì— ë³„í‘œë¥¼ 표시하여 ìš°ì„  순위 ë ˆì´ë¸”ë¡œ 만드십시오."
msgid "Labels with no issues in this iteration:"
msgstr ""
@@ -22950,7 +23284,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr ""
msgid "Label|Assignee"
-msgstr ""
+msgstr "담당ìž"
msgid "Language"
msgstr "언어"
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,8 +23473,8 @@ msgstr ""
msgid "Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
-msgid "Learn more about %{username}"
-msgstr ""
+msgid "Learn more about %{name}"
+msgstr "%{name}ì— ëŒ€í•´ ìžì„¸ížˆ 알아보기"
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -23902,7 +24239,7 @@ msgid "Mailgun events"
msgstr ""
msgid "Main menu"
-msgstr ""
+msgstr "ë©”ì¸ ë©”ë‰´"
msgid "Maintenance mode"
msgstr ""
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr "ì´ìŠˆë¥¼ 비공개로 설정"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "%{markdownDocsLinkStart}마í¬ë‹¤ìš´%{markdownDocsLinkEnd} 지ì›"
+msgid "Marked"
+msgstr "표시ëœ"
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,8 +24436,8 @@ msgstr ""
msgid "Marked to do as done."
msgstr "í•  ì¼ì„ 완료로 표시했습니다."
-msgid "Marks this %{noun} as a draft."
-msgstr ""
+msgid "Marks"
+msgstr "표시들"
msgid "Marks this %{noun} as ready."
msgstr ""
@@ -24193,7 +24545,7 @@ msgid "Maximum allowable lifetime for access token (days)"
msgstr ""
msgid "Maximum allowed lifetime for SSH keys (days)"
-msgstr ""
+msgstr "SSH í‚¤ì˜ ìµœëŒ€ 허용 수명(ì¼)"
msgid "Maximum artifacts size"
msgstr ""
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -24675,7 +25030,7 @@ msgid "Merge requests"
msgstr "머지 리퀘스트(MR)"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "머지 리퀘스트 ë° ìŠ¹ì¸ ì„¤ì •ì´ ì´ë™ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³  변경 ì‚¬í•­ì„ ë‹¤ë¥¸ 사람들과 ë…¼ì˜ í•˜ëŠ” 곳입니다."
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} 완료"
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr "미러 사용ìž"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "미러ë§ëœ 저장소"
@@ -25550,7 +25911,7 @@ msgid "Monitor"
msgstr "모니터ë§"
msgid "Monitor GitLab with Prometheus."
-msgstr ""
+msgstr "Prometheusë¡œ GitLabì„ ëª¨ë‹ˆí„°ë§í•˜ì‹­ì‹œì˜¤."
msgid "Monitor Settings"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr "Service Deskì—ì„œ 보낸 ì´ë©”ì¼ì˜ 발신ìžë¡œ 사용할 ì´ë¦„입니다."
+
msgid "Name:"
msgstr "ì´ë¦„:"
@@ -25947,6 +26311,9 @@ msgstr "새로운 파ì´í”„ë¼ì¸ ì¼ì •"
msgid "New Project"
msgstr "새 프로ì íŠ¸"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26224,7 +26591,7 @@ msgid "No credit card required."
msgstr "신용 카드가 필요하지 않습니다."
msgid "No data available"
-msgstr ""
+msgstr "ìžë£Œ ì—†ìŒ"
msgid "No data found"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26570,7 +26940,7 @@ msgid "Notes|Internal notes are only visible to the author, assignees, and membe
msgstr "내부 메모는 작성ìž, ë‹´ë‹¹ìž ë° ë¦¬í¬í„° ì´ìƒì˜ ì—­í• ì„ ê°€ì§„ 구성ì›ë§Œ ë³¼ 수 있습니다."
msgid "Notes|Last reply by %{name}"
-msgstr ""
+msgstr "%{name}ì˜ ë§ˆì§€ë§‰ ì‘답"
msgid "Notes|Make this an internal note"
msgstr ""
@@ -26600,7 +26970,7 @@ msgid "Nothing to preview."
msgstr "미리 ë³¼ ë‚´ìš©ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Notification Email"
-msgstr ""
+msgstr "알림 ì´ë©”ì¼"
msgid "Notification events"
msgstr "알림 ì´ë²¤íŠ¸"
@@ -26729,11 +27099,20 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr "%{author_name} %{action_name} %{ref_type} %{ref_name} 위치 %{project_link}"
+
+msgid "Notify|%{changed_files}:"
+msgstr "%{changed_files}:"
+
msgid "Notify|%{commit_link} in %{mr_link}"
-msgstr ""
+msgstr "%{mr_link}ì˜ %{commit_link} "
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
-msgstr ""
+msgstr "브랜치 `%{target_branch}`ì˜ %{commits_text}"
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr "%{committed_by_start} ìž‘ì„±ìž %{author_name} %{committed_by_end} %{committed_at_start} ì¼ì‹œ %{committed_date} %{committed_at_end}"
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
@@ -26741,27 +27120,51 @@ msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "Notify|%{invited_user} ì€ %{highlight_start}ì—ì„œ %{highlight_end} ì„ ê±°ë¶€ 했습니다. ê·€í•˜ì˜ ê°€ìž… 초대 %{target_link} %{target_name} 입니다."
+msgid "Notify|%{issues} imported."
+msgstr "%{issues} 가져왔습니다."
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr "Notify|%{paragraph_start}안녕하세요 %{name}!%{paragraph_end} %{paragraph_start}새 공개 키가 ê·€í•˜ì˜ ê³„ì •ì— ì¶”ê°€ë˜ì—ˆìŠµë‹ˆë‹¤:%{paragraph_end} %{paragraph_start}제목: %{key_title}%{paragraph_end} %{paragraph_start}ì´ í‚¤ê°€ 실수로 ì¶”ê°€ëœ ê²½ìš° 아래 %{removal_link}ì—ì„œ 제거할 수 있습니다.%{paragraph_end}"
-msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
msgstr ""
+msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
+msgstr "%{updated_by_user_name}ê°€ 머지 리퀘스트 %{mr_link}ì— ëŒ€í•œ 새 ì»¤ë°‹ì„ í‘¸ì‹œí–ˆìŠµë‹ˆë‹¤."
+
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
-msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
+msgid "Notify|A remote mirror update has failed."
msgstr ""
-msgid "Notify|And %{total_stripped_new_commits_count} more"
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
msgstr ""
+msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
+msgstr "머지 리퀘스트 %{mr_link} ì— ëŒ€í•œ 모든 í† ë¡ ì´ %{name}ì— ì˜í•´ í•´ê²°ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+msgid "Notify|And %{total_stripped_new_commits_count} more"
+msgstr "그리고 %{total_stripped_new_commits_count} ê°œ ë”"
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "담당ìžê°€ %{fromNames} ì—ì„œ %{toNames}ë¡œ 변경ë¨"
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr "CI/CD 프로ì íŠ¸ 설정"
-msgid "Notify|Don't want to receive updates from GitLab administrators?"
+msgid "Notify|Click here to set your password"
msgstr ""
+msgid "Notify|Commit Author"
+msgstr "커밋 작성ìž"
+
+msgid "Notify|Committed by"
+msgstr "ì˜í•´ì„œ 커밋ë¨"
+
+msgid "Notify|Don't want to receive updates from GitLab administrators?"
+msgstr "GitLab 관리ìžë¡œë¶€í„° ì—…ë°ì´íŠ¸ë¥¼ 받고 싶지 않습니까?"
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr "CSV 파ì¼ì„ 파싱하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 형ì‹ì´ 올바른지 확ì¸í•˜ì„¸ìš”. 쉼표를 사용하여 ê°’ì„ êµ¬ë¶„í•˜ëŠ” êµ¬ë¶„ëœ í…스트 파ì¼ìž…니다."
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "%{singular_or_plural_line}: %{error_lines}ì— ì˜¤ë¥˜ê°€ 발견ë˜ì—ˆìŠµë‹ˆë‹¤. ì´ ë¼ì¸ì¤‘ì— ì´ìŠˆ ì œëª©ì´ ìžˆëŠ”ì§€ 확ì¸í•˜ì‹­ì‹œì˜¤."
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26790,7 +27211,7 @@ msgid "Notify|If this key was added in error, you can remove it under %{removal_
msgstr ""
msgid "Notify|If you no longer wish to use this domain with GitLab Pages, please remove it from your GitLab project and delete any related DNS records."
-msgstr ""
+msgstr "ì´ ë„ë©”ì¸ì„ GitLab 페ì´ì§€ì™€ 함께 ë” ì´ìƒ 사용하지 않으려면 GitLab 프로ì íŠ¸ì—ì„œ 제거하고 관련 DNS 레코드를 삭제하십시오."
msgid "Notify|Issue was %{issue_status} by %{updated_by}"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr "Auto DevOpsì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,27 +27249,69 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ì´ 제거ë¨"
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr "ì´ íŒŒì¼ í˜•ì‹ì— 대한 미리보기가 없습니다."
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
+msgstr "다ìŒì— ì˜í•´ íŠ¸ë¦¬ê±°ëœ íŒŒì´í”„ë¼ì¸ %{pipeline_link}"
+
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "파ì´í”„ë¼ì¸ì´ 수정ë˜ì—ˆìœ¼ë©° #%{pipeline_id} ì´ í†µê³¼ë˜ì—ˆìŠµë‹ˆë‹¤!"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
msgstr ""
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "ìžë™ DevOps 파ì´í”„ë¼ì¸ì€ 파ì´í”„ë¼ì¸ %{pipeline_link} ì— ëŒ€í•´ 실패했으며 %{project_link}ì— ëŒ€í•´ 비활성화ë˜ì—ˆìŠµë‹ˆë‹¤. 프로ì íŠ¸ì—ì„œ Auto DevOps 파ì´í”„ë¼ì¸ì„ 사용하려면 %{supported_langs_link}를 검토하고 ê·¸ì— ë”°ë¼ í”„ë¡œì íŠ¸ë¥¼ ì¡°ì •í•œ ë‹¤ìŒ %{settings_link}ë‚´ì—ì„œ Auto DevOps 파ì´í”„ë¼ì¸ì„ 켜십시오."
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr "ì´ íŒŒì¼ì— 대한 diff는 너무 커서 í¬í•¨ë˜ì§€ 않았습니다."
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr "ì´ íŒŒì¼ì— 대한 diff는 너무 커서 í¬í•¨ë˜ì§€ 않았습니다."
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr "푸시ì—는 새 ì»¤ë°‹ì´ í¬í•¨ë˜ì–´ 있지 않지만 ì•„ëž˜ì˜ ì»¤ë°‹ê³¼ 변경 ì‚¬í•­ì„ ì‚­ì œí•˜ë„ë¡ ê°•ì œë¡œ 푸시했습니다."
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
-msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
msgstr ""
+msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
+msgstr "%{time_start}%{time}%{time_end} 까지 ë„ë©”ì¸ì„ 확ì¸í•˜ì§€ 않으면 GitLab 프로ì íŠ¸ì—ì„œ 제거ë©ë‹ˆë‹¤."
+
msgid "Notify|You don't have access to the project."
msgstr ""
@@ -26855,15 +27321,36 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr "Notify|ë‹¹ì‹ ì´ ë¨¸ì§€ 리퀘스트 %{mr_link}ì—ì„œ 언급ë˜ì—ˆìŠµë‹ˆë‹¤"
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "GitLab ê´€ë¦¬ìž ì•Œë¦¼ ìˆ˜ì‹ ì„ êµ¬ë… í•´ì œ 했습니다."
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr "프로ì íŠ¸ %{project_link} ì— ëŒ€í•œ CSV 가져오기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "%{target_to_join}ì˜ %{target_type} 가입 ìš”ì²­ì´ %{denied_tag} ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Notify|currently supported languages"
msgstr ""
-msgid "Notify|successfully completed %{jobs} in %{stages}."
+msgid "Notify|deleted"
+msgstr "ì‚­ì œë¨"
+
+msgid "Notify|login.........................................."
msgstr ""
+msgid "Notify|pushed new"
+msgstr "새로 푸시ë¨"
+
+msgid "Notify|pushed to"
+msgstr "푸시ë¨"
+
+msgid "Notify|successfully completed %{jobs} in %{stages}."
+msgstr "%{jobs} in %{stages}ì„ ì„±ê³µì ìœ¼ë¡œ 완료했습니다."
+
msgid "Nov"
msgstr "11ì›”"
@@ -26921,6 +27408,9 @@ msgstr "확ì¸"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr "관찰 가능성"
+
msgid "Oct"
msgstr "10ì›”"
@@ -26959,7 +27449,7 @@ msgid_plural "On %{end_date}, your trial will end and %{namespace_name} will be
msgstr[0] "%{end_date}ì— í‰ê°€íŒì´ 종료ë˜ê³  %{namespace_name} ì€ %{free_user_limit} 명으로 제한ë©ë‹ˆë‹¤."
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "왼쪽 사ì´ë“œë°”ì—ì„œ %{merge_requests_link} ì„ ì„ íƒí•˜ë©´ ë³¼ 수 있습니다."
msgid "On track"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27383,7 +27876,7 @@ msgid "One or more of your personal access tokens will expire in %{days_to_expir
msgstr ""
msgid "Only %{workspaceType} members with %{permissions} can view or be notified about this %{issuableType}."
-msgstr ""
+msgstr "%{permissions} ì„ ê°€ì§„ %{workspaceType} ëª…ì˜ íšŒì›ë§Œì´ ì´ %{issuableType}를 보거나 ì•Œë¦¼ì„ ë°›ì„ ìˆ˜ 있습니다."
msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
@@ -27401,7 +27894,7 @@ msgid "Only Project Members"
msgstr ""
msgid "Only SSH"
-msgstr ""
+msgstr "SSH만"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
msgstr ""
@@ -27416,13 +27909,13 @@ msgid "Only effective when remote storage is enabled. Set to 0 for no size limit
msgstr ""
msgid "Only group members with at least the Reporter role can view or be notified about this epic"
-msgstr ""
+msgstr "최소한 리í¬í„° ì—­í• ì„ ê°€ì§„ 그룹 구성ì›ë§Œ ì´ ì—í”½ì„ ë³´ê±°ë‚˜ ì•Œë¦¼ì„ ë°›ì„ ìˆ˜ 있습니다."
msgid "Only include features new to your current subscription tier."
msgstr ""
msgid "Only members of this group can access the wiki."
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì˜ êµ¬ì„±ì›ë§Œ wikiì— ì•¡ì„¸ìŠ¤í•  수 있습니다."
msgid "Only policy:"
msgstr ""
@@ -27446,7 +27939,7 @@ msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
msgid "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
-msgstr ""
+msgstr "ì´ ë„ë©”ì¸ì— ì´ë©”ì¼ ì£¼ì†Œê°€ 있는 확ì¸ëœ 사용ìžë§Œ ê·¸ë£¹ì— ì¶”ê°€í•  수 있습니다. ë³µìˆ˜ì˜ ë„ë©”ì¸ì´ 지ì›ë©ë‹ˆë‹¤."
msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
@@ -27572,7 +28065,7 @@ msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Ordered list"
-msgstr ""
+msgstr "번호순 목ë¡"
msgid "Organizations"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27665,7 +28161,7 @@ msgid "Owner"
msgstr "소유ìž"
msgid "Owners and administrators"
-msgstr ""
+msgstr "ì†Œìœ ìž ë° ê´€ë¦¬ìž"
msgid "Owners can modify this selection."
msgstr ""
@@ -27713,7 +28209,7 @@ msgid "Package already exists"
msgstr ""
msgid "Package and registry settings"
-msgstr ""
+msgstr "패키지 ë° ë ˆì§€ìŠ¤íŠ¸ë¦¬ 설정"
msgid "Package deleted successfully"
msgstr ""
@@ -27752,7 +28248,7 @@ msgid "Package type must be PyPi"
msgstr ""
msgid "Package type must be RPM"
-msgstr ""
+msgstr "패키지 ìœ í˜•ì€ RPMì´ì–´ì•¼ 합니다."
msgid "Package type must be RubyGems"
msgstr ""
@@ -27776,13 +28272,13 @@ msgid "PackageRegistry|Add composer registry"
msgstr ""
msgid "PackageRegistry|Additional metadata"
-msgstr ""
+msgstr "추가 메타ë°ì´í„°"
msgid "PackageRegistry|Allow duplicates"
msgstr ""
msgid "PackageRegistry|Allow packages with the same name and version to be uploaded to the registry. The newest version of a package is always used when installing."
-msgstr ""
+msgstr "ì´ë¦„ê³¼ ë²„ì „ì´ ê°™ì€ íŒ¨í‚¤ì§€ë¥¼ ë ˆì§€ìŠ¤íŠ¸ë¦¬ì— ì—…ë¡œë“œí•  수 있습니다. 설치 ì‹œ í•­ìƒ ìµœì‹  ë²„ì „ì˜ íŒ¨í‚¤ì§€ê°€ 사용ë©ë‹ˆë‹¤."
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -27879,10 +28375,7 @@ msgstr ""
msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
-msgstr[0] ""
-
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
+msgstr[0] "%d ìžì‚° ì‚­ì œ"
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -27890,14 +28383,17 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Delete selected"
+msgid "PackageRegistry|Delete package asset"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr "ì„ íƒí•œ 항목 ì‚­ì œ"
+
msgid "PackageRegistry|Delete this package"
msgstr ""
msgid "PackageRegistry|Duplicate packages"
-msgstr ""
+msgstr "중복 패키지"
msgid "PackageRegistry|Error publishing"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr "패키지 ìžì‚°ì´ 성공ì ìœ¼ë¡œ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,9 +28507,12 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Permanently delete assets"
+msgid "PackageRegistry|Permanently delete"
msgstr ""
+msgid "PackageRegistry|Permanently delete assets"
+msgstr "ìžì‚°ì„ ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œ"
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28059,11 +28561,11 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr "패키지 ìžì‚°ì„ 삭제하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr ""
@@ -28072,7 +28574,7 @@ msgid "PackageRegistry|Something went wrong while fetching the package history."
msgstr ""
msgid "PackageRegistry|Something went wrong while fetching the package metadata."
-msgstr ""
+msgstr "패키지 메타ë°ì´í„°ë¥¼ 가져오는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -28119,12 +28621,12 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
-msgstr[0] ""
+msgstr[0] "%d ìžì‚°ì„ 삭제하려고 합니다. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다."
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
msgstr ""
@@ -28133,7 +28635,7 @@ msgid "PackageRegistry|You may also need to setup authentication using an auth t
msgstr ""
msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
-msgstr ""
+msgstr "PackageRegistry|%{linkStart}ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°%{linkEnd}ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "PackageRegistry|npm"
msgstr ""
@@ -28142,7 +28644,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr ""
msgid "Packages and registries"
-msgstr ""
+msgstr "패키지 ë° ë ˆì§€ìŠ¤íŠ¸ë¦¬"
msgid "Page not found"
msgstr ""
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr "중지"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28373,7 +28872,7 @@ msgid "People without permission will never get a notification."
msgstr ""
msgid "Per your subscription agreement with GitLab, you must report your license usage data on a monthly basis. GitLab uses this data to keep your subscription up to date. To report your license usage data, export your license usage file and email it to %{renewal_service_email}. If you need an updated license, GitLab will send the license to the email address registered in the %{customers_dot}, and you can upload this license to your instance."
-msgstr ""
+msgstr "GitLabê³¼ì˜ êµ¬ë… ê³„ì•½ì— ë”°ë¼ ë§¤ì›” ë¼ì´ì„ ìŠ¤ 사용 ë°ì´í„°ë¥¼ 보고해야 합니다. GitLabì€ ì´ ë°ì´í„°ë¥¼ 사용하여 구ë…ì„ ìµœì‹  ìƒíƒœë¡œ 유지합니다. ë¼ì´ì„ ìŠ¤ 사용 ë°ì´í„°ë¥¼ 보고하려면 ë¼ì´ì„ ìŠ¤ 사용 파ì¼ì„ ë‚´ë³´ë‚´ê³  %{renewal_service_email}으로 ì´ë©”ì¼ì„ 보내십시오. ì—…ë°ì´íŠ¸ëœ ë¼ì´ì„ ìŠ¤ê°€ 필요한 경우 GitLabì—ì„œ %{customers_dot}ì— ë“±ë¡ëœ ì´ë©”ì¼ ì£¼ì†Œë¡œ ë¼ì´ì„ ìŠ¤ë¥¼ ë³´ë‚´ë©° ì´ ë¼ì´ì„ ìŠ¤ë¥¼ ì¸ìŠ¤í„´ìŠ¤ì— 업로드할 수 있습니다."
msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
@@ -28469,7 +28968,7 @@ msgid "Period of inactivity (days)"
msgstr ""
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "비활성화 전 비활성 기간입니다."
msgid "Permalink"
msgstr ""
@@ -28685,10 +29184,10 @@ msgid "PipelineEditor|Pipeline Source"
msgstr "파ì´í”„ë¼ì¸ 소스"
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies."
-msgstr ""
+msgstr "%{codeEnd} 와 %{codeStart}ì€%{codeEnd} ìž‘ì—… 종ì†ì„±ì„ 필요로 하는 ê²ƒì„ ì œì™¸í•˜ê³  %{codeStart}ê°œì˜ ê·œì¹™%{codeEnd} %{codeStart}만%{codeEnd} %{codeStart}를 í¬í•¨í•˜ì—¬ 파ì´í”„ë¼ì¸ ë™ìž‘ì´ ì‹œë®¬ë ˆì´ì…˜ë©ë‹ˆë‹¤."
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "%{codeEnd} 와 %{codeStart}ì€%{codeEnd} ìž‘ì—… 종ì†ì„±ì„ 필요로 하는 ê²ƒì„ ì œì™¸í•˜ê³  %{codeStart}ê°œì˜ ê·œì¹™%{codeEnd} %{codeStart}만%{codeEnd} %{codeStart}를 í¬í•¨í•˜ì—¬ 파ì´í”„ë¼ì¸ ë™ìž‘ì´ ì‹œë®¬ë ˆì´ì…˜ë©ë‹ˆë‹¤. %{linkStart}ìžì„¸ížˆ 알아보기%{linkEnd}"
msgid "PipelineEditor|Pipeline simulation completed with errors"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr "활성"
msgid "PipelineSchedules|All"
msgstr "모ë‘"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "비활성"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "ë‹¤ìŒ ì‹¤í–‰"
@@ -28750,15 +29261,27 @@ msgstr "ì—†ìŒ"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ì— 대한 간단한 설명 제공"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "소유권 가져 오기"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "대ìƒ"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "변수"
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29102,7 +29631,7 @@ msgid "Pipelines|Use template"
msgstr ""
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "ê²€ì¦"
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
@@ -29186,7 +29715,7 @@ msgid "Pipeline|Manual"
msgstr ""
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "머지 리퀘스트 파ì´í”„ë¼ì¸"
msgid "Pipeline|Merge train pipeline"
msgstr ""
@@ -29348,7 +29877,7 @@ msgid "PlantUML URL"
msgstr ""
msgid "PlantUML diagram"
-msgstr ""
+msgstr "PlantUML 다ì´ì–´ê·¸ëž¨"
msgid "Play"
msgstr "Play"
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "저장소를 가져오는 ë™ì•ˆ 기다려주십시오. 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 페ì´ì§€ë¥¼ 새로고침 합니다."
+msgid "Please wait while we prepare for verification."
+msgstr "확ì¸ì„ 준비하는 ë™ì•ˆ 기다려 주십시오."
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr "환경설정"
msgid "Preferences saved."
msgstr "ì„¤ì •ì„ ì €ìž¥í–ˆìŠµë‹ˆë‹¤."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29630,7 +30168,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr ""
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "대시보드ì—ì„œ 기본ì ìœ¼ë¡œ 보여줄 콘í…츠를 ì„ íƒí•©ë‹ˆë‹¤."
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
@@ -29642,7 +30180,7 @@ msgid "Preferences|Color for removed lines"
msgstr ""
msgid "Preferences|Color theme"
-msgstr ""
+msgstr "ìƒ‰ìƒ í…Œë§ˆ"
msgid "Preferences|Configure how dates and times display for you."
msgstr ""
@@ -29651,13 +30189,13 @@ msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the color of GitLab."
-msgstr ""
+msgstr "GitLabì˜ ìƒ‰ìƒì„ 사용ìžê°€ 지정합니다."
msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr ""
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "대시보드"
msgid "Preferences|Diff colors"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr "시간 설정"
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr "활성화"
msgid "Profiles|Add key"
msgstr "키 추가"
-msgid "Profiles|Add status emoji"
-msgstr "ìƒíƒœ ì´ëª¨í‹°ì½˜ 추가"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr "아바타 ìžë¥´ê¸°"
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr "ë°”ì¨"
-
msgid "Profiles|Change username"
msgstr "사용ìžëª… 변경"
@@ -29981,14 +30513,11 @@ msgid "Profiles|Choose file..."
msgstr "íŒŒì¼ ì„ íƒ.."
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr ""
+msgstr "프로ì íŠ¸, 저장소 ë˜ëŠ” ì¡°ì§ ì •ë³´ ì—†ì´ ê³µê°œ í”„ë¡œí•„ì— ë¹„ê³µê°œ 프로ì íŠ¸ì˜ 기여ë„를 표시하려면 ì„ íƒí•©ë‹ˆë‹¤."
msgid "Profiles|City, country"
msgstr "ë„ì‹œ, êµ­ê°€"
-msgid "Profiles|Clear status"
-msgstr "ìƒíƒœ 지우기"
-
msgid "Profiles|Commit email"
msgstr "커밋 ì´ë©”ì¼"
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "ì—°ê²°ëœ ê³„ì •"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "현재 경로: %{path}"
@@ -30026,7 +30558,7 @@ msgid "Profiles|Do not show on profile"
msgstr "í”„ë¡œí•„ì— í‘œì‹œí•˜ì§€ ì•ŠìŒ"
msgid "Profiles|Don't display activity-related personal information on your profile."
-msgstr ""
+msgstr "í”„ë¡œí•„ì— í™œë™ ê´€ë ¨ ê°œì¸ ì •ë³´ë¥¼ 표시하지 마십시오."
msgid "Profiles|Edit Profile"
msgstr "프로필 편집"
@@ -30035,16 +30567,16 @@ msgid "Profiles|Ensure you have two-factor authentication recovery codes stored
msgstr ""
msgid "Profiles|Enter how your name is pronounced to help people address you correctly."
-msgstr ""
+msgstr "ì‚¬ëžŒë“¤ì´ ë‹¹ì‹ ì„ ì˜¬ë°”ë¥´ê²Œ 부를 수 있ë„ë¡ ë‹¹ì‹ ì˜ ì´ë¦„ì„ ë°œìŒí•˜ëŠ” ë°©ë²•ì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤."
msgid "Profiles|Enter your name, so people you know can recognize you."
-msgstr ""
+msgstr "아는 ì‚¬ëžŒë“¤ì´ ë‹¹ì‹ ì„ ì•Œì•„ë³¼ 수 있ë„ë¡ ë‹¹ì‹ ì˜ ì´ë¦„ì„ ìž…ë ¥í•˜ì„¸ìš”."
msgid "Profiles|Enter your password to confirm the email change"
msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you."
-msgstr ""
+msgstr "ì‚¬ëžŒë“¤ì´ ë‹¹ì‹ ì„ ë¶€ë¥´ëŠ” ë°©ë²•ì„ ì•Œ 수 있ë„ë¡ ë°œìŒ ë°©ë²•ì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤."
msgid "Profiles|Example: MacBook key"
msgstr ""
@@ -30122,7 +30654,7 @@ msgid "Profiles|Notification email"
msgstr "알림 ì´ë©”ì¼"
msgid "Profiles|Optional but recommended. If set, key becomes invalid on the specified date."
-msgstr ""
+msgstr "옵션ì´ì§€ë§Œ 권장ë©ë‹ˆë‹¤. 설정하면 ì§€ì •ëœ ë‚ ì§œì— í‚¤ê°€ 무효가 ë©ë‹ˆë‹¤."
msgid "Profiles|Organization"
msgstr "ì¡°ì§"
@@ -30179,7 +30711,7 @@ msgid "Profiles|Static object token was successfully reset"
msgstr ""
msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr ""
+msgstr "250ìž ì´ë‚´ë¡œ ìžì‹ ì— 대해 알려주십시오."
msgid "Profiles|The ability to update your name has been disabled by your administrator."
msgstr ""
@@ -30188,10 +30720,10 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "최대 허용ë˜ëŠ” 파ì¼ì˜ í¬ê¸°ëŠ” 200KB입니다."
msgid "Profiles|This email will be displayed on your public profile."
-msgstr ""
+msgstr "ì´ ì´ë©”ì¼ì€ 공개 í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more.%{commit_email_link_end}"
-msgstr ""
+msgstr "ì´ ì´ë©”ì¼ì€ 편집 ë° ë¨¸ì§€ê³¼ ê°™ì€ ì›¹ 기반 ìž‘ì—…ì— ì‚¬ìš©ë©ë‹ˆë‹¤. %{commit_email_link_start}ìžì„¸ížˆ 알아보기%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "ì´ ê·¸ë¦¼ê³¼ 메시지는 프로필과 ì¸í„°íŽ˜ì´ìŠ¤ ì „ì²´ì— ë‚˜íƒ€ë‚©ë‹ˆë‹¤."
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "ìƒíƒœëŠ” 어떤가요?"
-
msgid "Profiles|Who you represent or work for."
msgstr "대표로 있는 ê³³ ë˜ëŠ” ì¼í•˜ëŠ” ê³³"
@@ -30284,10 +30813,7 @@ msgid "Profiles|Your name was automatically set based on your %{provider_label}
msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr ""
-
-msgid "Profiles|Your status"
-msgstr "ë‚˜ì˜ ìƒíƒœ"
+msgstr "ê·€í•˜ì˜ ì´ë¦„ì€ %{provider_label} ê°œì˜ ê³„ì •ì„ ê¸°ë°˜ìœ¼ë¡œ ìžë™ 설정ë˜ì—ˆìœ¼ë¯€ë¡œ 아는 ì‚¬ëžŒë“¤ì´ ê·€í•˜ë¥¼ 알아볼 수 있습니다."
msgid "Profiles|https://website.com"
msgstr ""
@@ -30497,7 +31023,7 @@ msgid "ProjectCreationLevel|No one"
msgstr ""
msgid "ProjectCreationLevel|Roles allowed to create projects"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ ìƒì„±í•  수 있는 ì—­í• "
msgid "ProjectFileTree|Name"
msgstr "ì´ë¦„"
@@ -30620,7 +31146,7 @@ msgid "ProjectSelect|Select a project"
msgstr ""
msgid "ProjectSelect|Something went wrong while fetching projects"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ 가져오는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr "git 태그를 릴리스 ì •ë³´, 릴리스 ì¦ê±° ë° ìžì‚°ê³¼ 결합하여 릴리스를 만듭니다."
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "프로ì íŠ¸ 리소스를 설정하고 ìƒíƒœë¥¼ 모니터ë§í•©ë‹ˆë‹¤."
@@ -30808,11 +31337,14 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "ProjectSettings|ì œì•ˆëœ ê²€í† ìžë¥¼ 활성화합니다."
+
msgid "ProjectSettings|Encourage"
msgstr ""
msgid "ProjectSettings|Environments"
-msgstr ""
+msgstr "환경"
msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
@@ -30827,7 +31359,7 @@ msgid "ProjectSettings|Every project can have its own space to store its package
msgstr ""
msgid "ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access."
-msgstr ""
+msgstr "모든 프로ì íŠ¸ëŠ” CI/CD ë˜ëŠ” API í˜¸ì¶œì„ í†µí•´ í™˜ê²½ì— ë°°í¬í•  수 있습니다. 프로ì íŠ¸ 구성ì›ì´ 아니면 ì½ê¸° ì „ìš© 액세스 ê¶Œí•œì„ ê°€ì§‘ë‹ˆë‹¤."
msgid "ProjectSettings|Everyone"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ì´ ì €ìž¥ì†Œì—는 ì„œëª…ëœ ì»¤ë°‹ë§Œ 푸쉬할 수 있습니다."
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr "릴리스"
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31112,7 +31653,7 @@ msgid "ProjectSettings|What are merge trains?"
msgstr ""
msgid "ProjectSettings|What is squashing?"
-msgstr ""
+msgstr "스쿼싱ì´ëž€ 무엇입니까?"
msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31253,7 +31797,7 @@ msgid "Projects help you organize your work. They contain your file repository,
msgstr ""
msgid "Projects in this group can use Git LFS"
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ëŠ” Git LFS를 사용할 수 있습니다."
msgid "Projects shared with %{group_name}"
msgstr "%{group_name}ê³¼ 공유ë˜ëŠ” 프로ì íŠ¸"
@@ -31541,7 +32085,7 @@ msgid "Promotions|Buy GitLab Enterprise Edition"
msgstr ""
msgid "Promotions|Configure Service Desk"
-msgstr ""
+msgstr "서비스 ë°ìŠ¤í¬ 설정"
msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -31556,7 +32100,7 @@ msgid "Promotions|Description templates allow you to define context-specific tem
msgstr ""
msgid "Promotions|Dismiss Service Desk promotion"
-msgstr ""
+msgstr "서비스 ë°ìŠ¤í¬ 프로모션 닫기"
msgid "Promotions|Dismiss burndown charts promotion"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31805,7 +32358,7 @@ msgid "ProtectedEnvironment|%{environment_name} will be writable for developers.
msgstr ""
msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
-msgstr ""
+msgstr "아래 ë°°í¬ ê³„ì¸µìœ¼ë¡œ ì§€ì •ëœ ëª¨ë“  í™˜ê²½ì€ ìƒìœ„ ê·¸ë£¹ì— ì˜í•´ 보호ë©ë‹ˆë‹¤. %{link_start}ìžì„¸ížˆ 알아보기%{link_end}."
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
@@ -31823,10 +32376,10 @@ msgid "ProtectedEnvironment|Failed to load details for this group."
msgstr "ProtectedEnvironment|ì´ ê·¸ë£¹ì— ëŒ€í•œ 세부 정보를 로드하지 못했습니다."
msgid "ProtectedEnvironment|No environments in this project are protected."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ì˜ í™˜ê²½ì€ ë³´í˜¸ë˜ì§€ 않습니다."
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
-msgstr ""
+msgstr "ProtectedEnvironment|ì§€ì •ëœ ê·¸ë£¹ë§Œ ë³´í˜¸ëœ í™˜ê²½ì—ì„œ ë°°í¬ë¥¼ 실행할 수 있습니다."
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
msgstr ""
@@ -31850,7 +32403,7 @@ msgid "ProtectedEnvironment|Select an environment"
msgstr ""
msgid "ProtectedEnvironment|Select groups"
-msgstr ""
+msgstr "ProtectedEnvironment|그룹 ì„ íƒ"
msgid "ProtectedEnvironment|Select users"
msgstr ""
@@ -31898,7 +32451,7 @@ msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to dep
msgstr ""
msgid "Provide Feedback"
-msgstr ""
+msgstr "ì˜ê²¬ 보내기"
msgid "Provide a number our sales team can use to call you."
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -31961,10 +32517,10 @@ msgid "Puma is running with a thread count above 1 and the Rugged service is ena
msgstr ""
msgid "PumbleIntegration|Send notifications about project events to Pumble."
-msgstr ""
+msgstr "프로ì íŠ¸ ì´ë²¤íŠ¸ì— 대한 ì•Œë¦¼ì„ Pumbleì— ë³´ëƒ…ë‹ˆë‹¤."
msgid "PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}"
-msgstr ""
+msgstr "프로ì íŠ¸ ì´ë²¤íŠ¸ì— 대한 ì•Œë¦¼ì„ Pumbleì— ë³´ëƒ…ë‹ˆë‹¤. %{docs_link}"
msgid "Purchase more minutes"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr "ë” ì½ê¸°"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -32461,7 +33041,7 @@ msgid "Release assets documentation"
msgstr ""
msgid "Release date"
-msgstr ""
+msgstr "릴리스 날짜"
msgid "Release does not have the same project as the milestone"
msgstr "ë¦´ë¦¬ìŠ¤ì— ë§ˆì¼ìŠ¤í†¤ê³¼ ë™ì¼í•œ 프로ì íŠ¸ê°€ 없습니다."
@@ -32872,7 +33452,7 @@ msgid "Replication"
msgstr ""
msgid "Reply"
-msgstr ""
+msgstr "답장"
msgid "Reply by email"
msgstr ""
@@ -32905,7 +33485,7 @@ msgid "Report for the scan has been removed from the database."
msgstr ""
msgid "Report version not provided, %{report_type} report type supports versions: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
-msgstr ""
+msgstr "ë³´ê³ ì„œ ë²„ì „ì´ ì œê³µë˜ì§€ 않았습니다. %{report_type} ë³´ê³ ì„œ ìœ í˜•ì´ ì§€ì›í•˜ëŠ” 버전: %{supported_schema_versions}. GitLabì€ ëª¨ë“  오류를 표시하기 위해 ì´ ë³´ê³ ì„œ ìœ í˜•ì˜ ì§€ì›ë˜ëŠ” 가장 ì˜¤ëž˜ëœ ë²„ì „ì— ëŒ€í•´ ì´ ë³´ê³ ì„œì˜ ìœ íš¨ì„±ì„ ê²€ì‚¬í•˜ë ¤ê³  ì‹œë„하지만, 보고서를 수집하지는 않습니다."
msgid "Report your license usage data to GitLab"
msgstr "ë¼ì´ì„ ìŠ¤ 사용 ë°ì´í„°ë¥¼ GitLabì— ë³´ê³ "
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33702,7 +34291,7 @@ msgid "Runners|A capacity of 1 enables warm HA through Auto Scaling group re-spa
msgstr ""
msgid "Runners|A new version is available"
-msgstr ""
+msgstr "Runners|새 ë²„ì „ì„ ì‚¬ìš©í•  수 있습니다."
msgid "Runners|A periodic background task deletes runners that haven't contacted GitLab in more than %{elapsedTime}. %{linkStart}Can I view how many runners were deleted?%{linkEnd}"
msgstr ""
@@ -33714,7 +34303,7 @@ msgid "Runners|Add notes, like who owns the runner or what it should be used for
msgstr ""
msgid "Runners|Add your feedback in the issue"
-msgstr ""
+msgstr "ì´ìŠˆì— ë‹¹ì‹ ì˜ ì˜ê²¬ 추가"
msgid "Runners|All"
msgstr ""
@@ -33820,7 +34409,7 @@ msgid "Runners|Download latest binary"
msgstr ""
msgid "Runners|Edit your search and try again"
-msgstr ""
+msgstr "Runners|ê²€ìƒ‰ì„ ìˆ˜ì •í•˜ê³  다시 ì‹œë„하십시오."
msgid "Runners|Enable stale runner cleanup"
msgstr ""
@@ -33835,17 +34424,20 @@ msgid "Runners|Executor"
msgstr ""
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "프로ì íŠ¸ í•„í„°"
msgid "Runners|Get started with runners"
-msgstr ""
+msgstr "Runners|러너 시작하기"
msgid "Runners|Group"
msgstr ""
-msgid "Runners|How do we upgrade GitLab runner?"
+msgid "Runners|How do runners pick up jobs?"
msgstr ""
+msgid "Runners|How do we upgrade GitLab runner?"
+msgstr "GitLab 러너를 어떻게 업그레ì´ë“œí•©ë‹ˆê¹Œ?"
+
msgid "Runners|IP Address"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr "만료ë˜ì§€ ì•ŠìŒ"
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33895,7 +34487,7 @@ msgid "Runners|New registration token generated!"
msgstr ""
msgid "Runners|No results found"
-msgstr ""
+msgstr "Runners|ê²€ìƒ‰ëœ ê²°ê³¼ê°€ 없습니다"
msgid "Runners|No spot. Default choice for Windows Shell executor."
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,8 +34577,11 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr ""
+msgid "Runners|Runner authentication token expiration"
+msgstr "러너 ì¸ì¦ í† í° ë§Œë£Œ"
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
+msgstr "Runner ì¸ì¦ 토í°ì€ ì„¤ì •ëœ ì£¼ê¸°ë¡œ 만료ë©ë‹ˆë‹¤. 만료ë˜ë©´ ìžë™ìœ¼ë¡œ 전환ë©ë‹ˆë‹¤."
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
msgstr ""
@@ -34033,9 +34631,12 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
-msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
+msgid "Runners|Runners are either:"
msgstr ""
+msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
+msgstr "Runners|러너는 CI/CD ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” ì—ì´ì „트입니다. %{linkStart}설치 ë° ë“±ë¡ ë°©ë²•%{linkEnd} ì„ ë”°ë¼ ëŸ¬ë„ˆë¥¼ 설정하십시오."
+
msgid "Runners|Runs untagged jobs"
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34052,7 +34656,7 @@ msgid "Runners|Show runner installation instructions"
msgstr ""
msgid "Runners|Something went wrong while deleting. Please refresh the page to try again."
-msgstr ""
+msgstr "삭제하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하려면 페ì´ì§€ë¥¼ 새로고침하세요."
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34101,7 +34708,7 @@ msgid "Runners|This runner is available to all projects and subgroups in a group
msgstr ""
msgid "Runners|This runner is outdated, an upgrade is recommended"
-msgstr ""
+msgstr "Runners|ì´ ëŸ¬ë„ˆëŠ” ì´ì „ 버전입니다. 업그레ì´ë“œë¥¼ 권장합니다."
msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
msgstr ""
@@ -34112,11 +34719,14 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr "Runners|등ë¡í•˜ë ¤ë©´ %{link_start}ê·¸ë£¹ì˜ ëŸ¬ë„ˆ 페ì´ì§€%{link_end}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
+msgid "Runners|Token expiry"
+msgstr "í† í° ë§Œë£Œ"
+
msgid "Runners|Up to date"
msgstr ""
msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
-msgstr ""
+msgstr "실행 ì¤‘ì¸ GitLab 버전과 ì¼ì¹˜í•˜ë„ë¡ GitLab Runner를 업그레ì´ë“œí•©ë‹ˆë‹¤. %{linkStart}주 버전과 부 버전%{linkEnd} ì´ ëª¨ë‘ ì¼ì¹˜í•´ì•¼ 합니다."
msgid "Runners|Upgrade Status"
msgstr ""
@@ -34152,10 +34762,10 @@ msgid "Runners|View installation instructions"
msgstr ""
msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
-msgstr ""
+msgstr "ì´ íŽ˜ì´ì§€ì—ì„œ 러너를 쉽고 효율ì ìœ¼ë¡œ 관리할 수 있기를 ë°”ëžë‹ˆë‹¤. 우리가 하고 있는 ê²ƒì— ëŒ€í•´ ì˜ê²¬ì„ 주세요!"
msgid "Runners|We've made some changes and want your feedback"
-msgstr ""
+msgstr "우리는 ì¼ë¶€ 변경 ì‚¬í•­ì„ ì ìš©í–ˆìœ¼ë©° ì—¬ëŸ¬ë¶„ì˜ ì˜ê²¬ì„ 듣고 싶습니다."
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -34212,19 +34822,19 @@ msgid "SAML for %{group_name}"
msgstr ""
msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
-msgstr ""
+msgstr "\"승ì¸\"ì„ ì„ íƒí•˜ë©´ GitLab 계정 \"%{username}\"(%{email})ì˜ ì†Œìœ ê¶Œì´ ë³¸ì¸ì´ ì†í•œ ì¡°ì§ìœ¼ë¡œ ì´ì „ë©ë‹ˆë‹¤."
msgid "SAML|Sign in to GitLab to connect your organization's account"
-msgstr ""
+msgstr "GitLabì— ë¡œê·¸ì¸í•˜ì—¬ ì¡°ì§ì˜ ê³„ì •ì— ì—°ê²°"
msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
-msgstr ""
+msgstr "\"%{group_path}\" ê·¸ë£¹ì„ ì‚¬ìš©í•˜ë©´ Single Sign-On 계정으로 로그ì¸í•  수 있습니다."
msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
-msgstr ""
+msgstr "\"%{group_name}\"ì— ì•¡ì„¸ìŠ¤í•˜ë ¤ë©´ 외부 ë¡œê·¸ì¸ íŽ˜ì´ì§€ë¥¼ 통해 Single Sign-On 계정으로 로그ì¸í•´ì•¼ 합니다."
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
-msgstr ""
+msgstr "ì¡°ì§ì˜ SSOê°€ GitLab ê³„ì •ì— ì—°ê²°ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "SAST Configuration"
msgstr ""
@@ -34331,23 +34941,20 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr "ScanExecutionPolicy|%{ifLabelStart}ì´ë©´%{ifLabelEnd} %{rules} %{scopes} %{branches}ì— ëŒ€í•œ ìž‘ì—…"
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr "ScanExecutionPolicy| %{time}ì—ì„œ%{period} %{days}"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
-msgstr ""
+msgstr "%{thenLabelStart}다ìŒ%{thenLabelEnd} 실행하려면 %{scan} 스캔 í•„ìš”"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
-msgstr ""
+msgstr "%{thenLabelStart}그런 다ìŒ%{thenLabelEnd} 사ì´íŠ¸ 프로필 %{siteProfile} ë° ìŠ¤ìºë„ˆ 프로필 %{scannerProfile}ë¡œ 실행하려면 %{scan} ìŠ¤ìº”ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "ScanExecutionPolicy|A pipeline is run"
msgstr ""
msgid "ScanExecutionPolicy|Scanner profile"
-msgstr ""
+msgstr "스ìºë„ˆ 프로필"
msgid "ScanExecutionPolicy|Schedule"
msgstr ""
@@ -34359,13 +34966,13 @@ msgid "ScanExecutionPolicy|Select branches"
msgstr ""
msgid "ScanExecutionPolicy|Select scanner profile"
-msgstr ""
+msgstr "스ìºë„ˆ 프로필 ì„ íƒ"
msgid "ScanExecutionPolicy|Select site profile"
-msgstr ""
+msgstr "사ì´íŠ¸ 프로필 ì„ íƒ"
msgid "ScanExecutionPolicy|Site profile"
-msgstr ""
+msgstr "사ì´íŠ¸ 프로필"
msgid "ScanExecutionPolicy|branch"
msgstr "ScanExecutionPolicy|브랜치"
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr "ìž‘ì„±ìž ê²€ìƒ‰"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "브랜치 검색"
@@ -34568,6 +35178,9 @@ msgstr "프로ì íŠ¸ 검색"
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr "프로필 관리"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -34940,7 +35550,7 @@ msgid "SecurityOrchestration|Actions"
msgstr ""
msgid "SecurityOrchestration|Add action"
-msgstr ""
+msgstr "작업 추가"
msgid "SecurityOrchestration|Add rule"
msgstr ""
@@ -35021,7 +35631,7 @@ msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More
msgstr ""
msgid "SecurityOrchestration|Failed to load cluster agents."
-msgstr ""
+msgstr "SecurityOrchestration|í´ëŸ¬ìŠ¤í„° ì—ì´ì „트를 로드하지 못했습니다."
msgid "SecurityOrchestration|Failed to load images."
msgstr "SecurityOrchestration|ì´ë¯¸ì§€ë¥¼ 로드하지 못했습니다."
@@ -35204,13 +35814,13 @@ msgid "SecurityOrchestration|This group"
msgstr ""
msgid "SecurityOrchestration|This is a group-level policy"
-msgstr ""
+msgstr "SecurityOrchestration|그룹 수준 정책입니다."
msgid "SecurityOrchestration|This is a project-level policy"
-msgstr ""
+msgstr "SecurityOrchestration|프로ì íŠ¸ 수준 정책입니다."
msgid "SecurityOrchestration|This policy is inherited from %{namespace}"
-msgstr ""
+msgstr "SecurityOrchestration|ì´ ì •ì±…ì€ %{namespace}ì—ì„œ ìƒì†ë©ë‹ˆë‹¤."
msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
msgstr ""
@@ -35234,7 +35844,7 @@ msgid "SecurityOrchestration|Update scan policies"
msgstr ""
msgid "SecurityOrchestration|Use a scan execution policy to create rules which enforce security scans for particular branches at a certain time. Supported types are SAST, DAST, Secret detection, and Container scanning."
-msgstr ""
+msgstr "검사 실행 ì •ì±…ì„ ì‚¬ìš©í•˜ì—¬ 특정 ì‹œê°„ì— íŠ¹ì • ë¸Œëžœì¹˜ì— ëŒ€í•œ 보안 검사를 시행하는 ê·œì¹™ì„ ë§Œë“­ë‹ˆë‹¤. 지ì›ë˜ëŠ” ìœ í˜•ì€ SAST, DAST, 비밀 검출 ë° ì»¨í…Œì´ë„ˆ 스ìºë‹ìž…니다."
msgid "SecurityOrchestration|Use a scan result policy to create rules that ensure security issues are checked before merging a merge request."
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr "SecurityReports|ì´ë¯¸ì§€"
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr "저장소 템플릿 ì„ íƒ"
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "시간대 ì„ íƒ"
@@ -35689,9 +36308,15 @@ msgstr "ë‹´ë‹¹ìž ì„ íƒ"
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr "ì´ìŠˆë¥¼ ìƒì„±í•  프로ì íŠ¸ ì„ íƒ"
msgid "Select projects"
msgstr "프로ì íŠ¸ ì„ íƒ"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "리뷰어 ì„ íƒí•˜ê¸°"
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr "초안 ìƒíƒœë¡œ 설정"
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "ì´ë¦„ê³¼ 아바타 ì˜†ì— ìƒíƒœê°€ 표시ë©ë‹ˆë‹¤."
-
-msgid "SetStatusModal|Busy"
-msgstr "ë°”ì¨"
-
msgid "SetStatusModal|Clear status"
msgstr "ìƒíƒœ 지우기"
msgid "SetStatusModal|Clear status after"
msgstr "ë‹¤ìŒ ì´í›„ ìƒíƒœë¥¼ 지움:"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "ìƒíƒœ 수정"
@@ -36148,6 +36776,9 @@ msgstr "ìƒíƒœ 설정"
msgid "SetStatusModal|Set status"
msgstr "ìƒíƒœ 설정"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "죄송합니다, ë‹¹ì‹ ì˜ ìƒíƒœë¥¼ 설정할 수 없습니다. 잠시후 다시 ì‹œë„해주세요."
@@ -36438,7 +37069,7 @@ msgid "ShowcaseSecurity|Vulnerability management"
msgstr ""
msgid "Showing %{conflict}"
-msgstr ""
+msgstr "표시 %{conflict}"
msgid "Showing %{count} of %{total} projects"
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -36871,7 +37538,7 @@ msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
msgid "Something went wrong while adding timeline event."
-msgstr ""
+msgstr "타임ë¼ì¸ ì´ë²¤íŠ¸ë¥¼ 추가하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Something went wrong while adding your award. Please try again."
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr "ìµœê·¼ì— ìƒì„±ëœ"
+msgid "SortOptions|Latest version"
+msgstr "최신 버전"
+
msgid "SortOptions|Least popular"
msgstr "ëœ ì¸ê¸°ìžˆëŠ”"
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr "ì—…ë°ì´íŠ¸ëœì§€ 오래ëœ"
+msgid "SortOptions|Oldest version"
+msgstr "가장 ì˜¤ëž˜ëœ ë²„ì „"
+
msgid "SortOptions|Popularity"
msgstr "ì¸ê¸°"
@@ -37795,7 +38471,7 @@ msgid "Subscribes to this %{quick_action_target}."
msgstr ""
msgid "Subscript"
-msgstr ""
+msgstr "아래첨ìž"
msgid "Subscription"
msgstr ""
@@ -38047,7 +38723,7 @@ msgid "SuggestedColors|Gray"
msgstr ""
msgid "SuggestedColors|Green"
-msgstr ""
+msgstr "SuggestedColors|ì´ˆë¡ìƒ‰"
msgid "SuggestedColors|Green screen"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38068,7 +38744,7 @@ msgid "SuggestedColors|Orange"
msgstr ""
msgid "SuggestedColors|Purple"
-msgstr ""
+msgstr "SuggestedColors|ë³´ë¼ìƒ‰"
msgid "SuggestedColors|Red"
msgstr ""
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "SuggestedReviewers|GitLabì˜ ë¨¸ì‹  ëŸ¬ë‹ ë„구를 기반으로 검토ìžì— 대한 제안 ì‚¬í•­ì„ ê°€ì ¸ì˜µë‹ˆë‹¤."
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "SuggestedReviewers|ì œì•ˆëœ ê²€í† ìž"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "SuggestedReviewers|오른쪽 사ì´ë“œë°”ì˜ Reviewer ì„¹ì…˜ì— ì œì•ˆ ì‚¬í•­ì´ ë‚˜íƒ€ë‚©ë‹ˆë‹¤."
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr "제안"
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,8 +38806,14 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
-msgstr ""
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr "ì¢Œì„ ë¶ˆì¼ì¹˜ë¡œ ì¸í•´ 활성화할 수 없습니다."
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr "true-up ê°’ 불ì¼ì¹˜ë¡œ ì¸í•´ 활성화할 수 ì—†ìŒ"
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr "구ë…ì„ ì¶”ê°€í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "SuperSonics|Billable users"
msgstr ""
@@ -38127,8 +38821,8 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr ""
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr "ì—°ê²° 문제로 ì¸í•´ ì¸ìŠ¤í„´ìŠ¤ë¥¼ 활성화할 수 ì—†ìŒ"
msgid "SuperSonics|Cloud licensing"
msgstr ""
@@ -38242,26 +38936,38 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "%{trueUpQuantity} %{trueUpQuantityUsers} ì— ëŒ€í•´ íŠ¸ë£¨ì—…ì„ ì ìš©í–ˆì§€ë§Œ %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}ì— ëŒ€í•´ íŠ¸ë£¨ì—…ì´ í•„ìš”í•©ë‹ˆë‹¤. 초과 좌ì„ì— ëŒ€í•œ ë¹„ìš©ì„ ì§€ë¶ˆí•˜ë ¤ë©´ ì˜ì—… 담당ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤. 추가 지ì›ì´ 필요한 경우 %{licenseSupportLinkStart}GitLab 지ì›%{licenseSupportLinkEnd}ì— ë¬¸ì˜í•˜ì‹­ì‹œì˜¤."
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr "만료ë˜ì—ˆê±°ë‚˜ 사용할 수 없는 활성화 코드를 ìž…ë ¥í–ˆì„ ìˆ˜ 있습니다. 새 활성화 코드를 요청하려면 %{purchaseSubscriptionLinkStart}새 구ë…ì„ êµ¬ìž…í•˜ì‹­ì‹œì˜¤%{purchaseSubscriptionLinkEnd} ë˜ëŠ” %{supportLinkStart}추가 지ì›ì„ 위해 GitLab 지ì›%{supportLinkEnd} ì— ë¬¸ì˜í•˜ì‹­ì‹œì˜¤."
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "현재 GitLab 설치ì—는 %{userCount} 활성 %{userCountUsers}ì´ ìžˆìœ¼ë©° ì´ëŠ” 새 êµ¬ë… ì¢Œì„ ìˆ˜ %{licenseUserCount} x %{overageCount}ì„ ì´ˆê³¼í•©ë‹ˆë‹¤. 새 구ë…ì„ í™œì„±í™”í•˜ë ¤ë©´ %{purchaseLinkStart}ê°€%{purchaseLinkEnd} 를 추가로 구매 %{overageCount} %{overageCountSeats}ë˜ëŠ” %{deactivateLinkStart}ì´%{deactivateLinkEnd} ë˜ëŠ” %{blockLinkStart}블ë¡%{blockLinkEnd} %{overageCount} %{overageCountUsers}ì„ ë¹„í™œì„±í™”í•©ë‹ˆë‹¤. 추가 지ì›ì´ 필요한 경우 %{licenseSupportLinkStart}GitLab 지ì›%{licenseSupportLinkEnd}ì— ë¬¸ì˜í•˜ì‹­ì‹œì˜¤."
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr "ê·€í•˜ì˜ êµ¬ë…ì„ ì°¾ì„ ìˆ˜ 없습니다"
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
-msgstr ""
+msgid "SuperSonics|Your subscription is expired"
+msgstr "ê·€í•˜ì˜ êµ¬ë…ì´ ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr ""
@@ -38276,7 +38982,7 @@ msgid "SuperSonics|past subscriptions"
msgstr ""
msgid "Superscript"
-msgstr ""
+msgstr "윗첨ìž"
msgid "Support"
msgstr "지ì›"
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39458,10 +40167,10 @@ msgid "The source project of this merge request has been removed."
msgstr ""
msgid "The source topic and the target topic are identical."
-msgstr ""
+msgstr "ì›ë³¸ 주제와 ëŒ€ìƒ ì£¼ì œê°€ ë™ì¼í•©ë‹ˆë‹¤."
msgid "The source topic is not a topic."
-msgstr ""
+msgstr "ì›ë³¸ 주제는 주제가 아닙니다."
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -39476,7 +40185,7 @@ msgid "The tag name can't be changed for an existing release."
msgstr "기존 ë¦´ë¦¬ìŠ¤ì˜ íƒœê·¸ ì´ë¦„ì€ ë³€ê²½í•  수 없습니다."
msgid "The target topic is not a topic."
-msgstr ""
+msgstr "ëŒ€ìƒ ì£¼ì œëŠ” 주제가 아닙니다."
msgid "The time period in seconds that the maximum requests per project limit applies to."
msgstr ""
@@ -39527,7 +40236,7 @@ msgid "There are currently no events."
msgstr ""
msgid "There are currently no mirrored repositories."
-msgstr ""
+msgstr "현재 미러ë§ëœ 저장소가 없습니다."
msgid "There are merge conflicts"
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr "사용 가능한 ë°ì´í„°ê°€ 없습니다."
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr "사용 가능한 í…Œì´ë¸” ë°ì´í„°ê°€ 없습니다."
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr "ì´ ë³´ë“œì˜ ë²”ìœ„ê°€ 축소ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40013,7 +40719,7 @@ msgid "This commit was signed with a different user's verified signature."
msgstr ""
msgid "This commit was signed with a verified signature, but the committer email is not associated with the GPG Key."
-msgstr ""
+msgstr "ì´ ì»¤ë°‹ì€ ì¸ì¦ëœ 서명으로 서명ë˜ì—ˆì§€ë§Œ 커미터 ì´ë©”ì¼ì€ GPG 키와 ì¼ì¹˜í•˜ì§€ 않습니다."
msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "ì´ ë°°í¬ ìž‘ì—…ì€ ìžë™ìœ¼ë¡œ 실행ë˜ì§€ 않으며 수ë™ìœ¼ë¡œ 시작해야 하지만, 최신 ë°°í¬ë³´ë‹¤ 오래ë˜ì–´ 실행할 수 없습니다."
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,17 +41138,23 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” 사용ìžì§€ì • ë„ë©”ì¸ í•œë„ì— ë„달했습니다. (최대 %d)"
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
msgid "This report uses a supported MAJOR.MINOR schema version but the PATCH version doesn't match any vendored schema version. Validation will be attempted against version %{find_latest_patch_version}"
-msgstr ""
+msgstr "ì´ ë³´ê³ ì„œëŠ” 지ì›ë˜ëŠ” MAJOR.MINOR 스키마 ë²„ì „ì„ ì‚¬ìš©í•˜ì§€ë§Œ PATCH ë²„ì „ì€ ê³µê¸‰ì—…ì²´ 스키마 버전과 ì¼ì¹˜í•˜ì§€ 않습니다. 버전 %{find_latest_patch_version}ì— ëŒ€í•´ 유효성 검사를 ì‹œë„합니다."
msgid "This repository"
msgstr "ì´ ì €ìž¥ì†Œ"
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40724,7 +41469,7 @@ msgid "Timeago|right now"
msgstr "지금"
msgid "Timeline event added successfully."
-msgstr ""
+msgstr "타임ë¼ì¸ ì´ë²¤íŠ¸ê°€ 성공ì ìœ¼ë¡œ 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Timeline|Turn recent updates view off"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr "표시 ì´ë¦„ì„ ì¶”ê°€í•˜ë ¤ë©´ 서비스 ë°ìŠ¤í¬ ì´ë©”ì¼ ì£¼ì†Œë¥¼ 설정하십시오. %{linkStart}ìžì„¸ížˆ 알아보기%{linkEnd}"
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41029,16 +41780,16 @@ msgid "Todos|Filter by project"
msgstr "프로ì íŠ¸ë¡œ í•„í„°ë§"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "스스로 격려해 주세요!"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "수고했습니다! í•  ì¼ ëª©ë¡ì— ì•„ë¬´ê²ƒë„ ë‚¨ì§€ ì•Šì€ ê²ƒ 같습니다."
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
-msgstr ""
+msgstr "ë‹¹ì‹ ì€ \"í• ì¼ ëª©ë¡ íŒŒê´´ìž\"ë¡œ 칭하겠습니다."
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "비어 있는 í• ì¼ ë¦¬ìŠ¤íŠ¸ê°€ 아름답지 않나요?"
msgid "Todos|It's how you always know what to work on next."
msgstr ""
@@ -41050,7 +41801,7 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr "í•  ì¼ ëª©ë¡ì— ì•„ë¬´ê²ƒë„ ì—†ìŠµë‹ˆë‹¤. 잘 하셨어요!"
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "ë” ì´ìƒ í•  ì¼ì´ 없습니다. í•˜ì´ íŒŒì´ë¸Œ!"
msgid "Todos|Undo mark all as done"
msgstr "ëª¨ë‘ ì™„ë£Œë¡œ 표시한 ê²ƒì„ ì·¨ì†Œ"
@@ -41088,9 +41839,6 @@ msgstr "커밋 설명 토글"
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "사ì´ë“œë°” 토글"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41161,16 +41906,16 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr ""
msgid "TopNav|Explore"
-msgstr ""
+msgstr "íƒìƒ‰"
msgid "TopNav|Go back"
msgstr ""
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "전환"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "내 대시보드"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr "토픽 %{source_topic} ì´ %{target_topic} í† í”½ì— ì„±ê³µì ìœ¼ë¡œ 병합ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -41209,7 +41954,7 @@ msgid "Topics"
msgstr ""
msgid "Topics could not be merged!"
-msgstr ""
+msgstr "주제를 병합할 수 없습니다!"
msgid "Total"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr "ì´ ì´ìŠˆ 가중치"
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "구매한 저장 공간 중 %{percentageLeft} 사용 가능"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "아티팩트"
@@ -42096,12 +42848,12 @@ msgstr "ì´ë²ˆ ê²°ì œ 주기 사용량"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr "UsageQuota|유효 %{storage_enforcement_date}, 네임스페ì´ìŠ¤ 저장공간 ì œí•œì€ %{strong_start}%{namespace_name}%{strong_end} 네임스페ì´ìŠ¤ì— ì ìš©ë©ë‹ˆë‹¤. %{extra_message}ì´ ë³€ê²½ ì‚¬í•­ì— ëŒ€í•œ %{rollout_link_start}롤아웃 ì¼ì • 보기%{link_end}."
-
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr ""
+
msgid "UsageQuota|Git repository."
msgstr ""
@@ -42112,7 +42864,7 @@ msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker
msgstr ""
msgid "UsageQuota|Group settings &gt; Usage quotas"
-msgstr ""
+msgstr "그룹 설정 &gt; 사용 할당량"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
@@ -42174,9 +42926,6 @@ msgstr "저장소"
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,11 +42959,11 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
-msgstr ""
+msgstr "네임스페ì´ìŠ¤ëŠ” 현재 %{strong_start}%{used_storage}%{strong_end} 네임스페ì´ìŠ¤ 저장소를 사용하고 있습니다. %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}ì—ì„œ ì‚¬ìš©ëŸ‰ì„ ë³´ê³  관리합니다. %{docs_link_start}스토리지를 줄ì´ëŠ” 방법%{link_end}."
msgid "UsageQuota|The table below shows current period usage"
msgstr ""
@@ -42280,7 +43029,7 @@ msgid "UsageQuota|Usage quotas help link"
msgstr "사용량 제한 ë„움 ë§í¬"
msgid "UsageQuota|User settings &gt; Usage quotas"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì„¤ì • &gt; 사용 할당량"
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr "사용ìžê°€ 차단ë¨"
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42845,7 +43597,7 @@ msgid "Users can launch a development environment from a GitLab browser tab when
msgstr ""
msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "사용ìžëŠ” 로그ì¸í•˜ì—¬ ê³„ì •ì„ ë‹¤ì‹œ 활성화할 수 있습니다. %{link_start}ìžì„¸ížˆ 알아보기.%{link_end}"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43103,10 +43879,10 @@ msgid "Version"
msgstr "버전"
msgid "Version %{report_version} for report type %{report_type} has been deprecated, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to parse and ingest this report if valid."
-msgstr ""
+msgstr "ë³´ê³ ì„œ 유형 %{report_type} ì˜ ë²„ì „ %{report_version} ì€ ë” ì´ìƒ 사용ë˜ì§€ 않으며 ì´ ë³´ê³ ì„œ ìœ í˜•ì— ì§€ì›ë˜ëŠ” ë²„ì „ì€ %{supported_schema_versions}입니다. GitLabì€ ìœ íš¨í•œ 경우 ì´ ë³´ê³ ì„œë¥¼ 구문 분ì„하고 수집하려고 ì‹œë„합니다."
msgid "Version %{report_version} for report type %{report_type} is unsupported, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
-msgstr ""
+msgstr "ë³´ê³ ì„œ 유형 %{report_type} ì— ëŒ€í•œ 버전 %{report_version} ì€ ì§€ì›ë˜ì§€ 않으며 ì´ ë³´ê³ ì„œ ìœ í˜•ì— ëŒ€í•´ 지ì›ë˜ëŠ” ë²„ì „ì€ %{supported_schema_versions}입니다. GitLabì€ ëª¨ë“  오류를 표시하기 위해 ì´ ë³´ê³ ì„œ ìœ í˜•ì˜ ì§€ì›ë˜ëŠ” 가장 ì˜¤ëž˜ëœ ë²„ì „ì— ëŒ€í•´ ì´ ë³´ê³ ì„œì˜ ìœ íš¨ì„±ì„ ê²€ì‚¬í•˜ë ¤ê³  ì‹œë„하지만 보고서를 수집하지는 않습니다."
msgid "Version %{versionNumber}"
msgstr ""
@@ -43139,13 +43915,13 @@ msgid "View all environments."
msgstr ""
msgid "View all groups"
-msgstr ""
+msgstr "모든 그룹 보기"
msgid "View all issues"
msgstr ""
msgid "View all projects"
-msgstr ""
+msgstr "모든 프로ì íŠ¸ 보기"
msgid "View blame"
msgstr ""
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,8 +43954,8 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
-msgstr "ì—픽 ëª©ë¡ ë³´ê¸°"
+msgid "View entire blame"
+msgstr "전체 비난 보기"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "파ì¼"
+msgid "Vulnerability|File:"
+msgstr "파ì¼:"
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,12 +44400,12 @@ msgstr "ì´ë¯¸ì§€"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr ""
+msgid "Vulnerability|Location"
+msgstr "위치"
+
msgid "Vulnerability|Method"
msgstr ""
@@ -43633,6 +44415,9 @@ msgstr "네임스페ì´ìŠ¤"
msgid "Vulnerability|Project"
msgstr "프로ì íŠ¸"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "심ê°ë„"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "ìƒíƒœ"
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr "경고:"
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr "Prometheus ì„œë²„ì— ì—°ê²°í•  수 없습니다. 서버가 ë” ì´ìƒ ì¡
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë‹¤. 계ì†í•˜ë ¤ë©´ reCAPTCHA를 진행하세요."
@@ -43841,7 +44641,7 @@ msgid "WebIDE|Quickly and easily edit multiple files in your project."
msgstr "프로ì íŠ¸ì˜ 여러 파ì¼ì„ 빠르고 쉽게 편집합니다."
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
-msgstr ""
+msgstr "프로ì íŠ¸ì˜ 여러 파ì¼ì„ 빠르고 쉽게 편집합니다. . ì„ ëˆŒëŸ¬ì„œ 열어보세요."
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr "ìž‘ì—… ì´ë²¤íŠ¸"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44164,7 +44982,7 @@ msgstr ""
msgid "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seat. %{free_user_limit} seat will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
msgid_plural "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seats. %{free_user_limit} seats will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
-msgstr[0] "í‰ê°€íŒì´ 종료ë˜ë©´ %{free_user_limit} ì„으로 제한ë˜ëŠ” 프리 요금제로 ì´ë™í•©ë‹ˆë‹¤. %{free_user_limit} 시트는 활성 ìƒíƒœë¡œ 유지ë˜ë©°, 시트를 차지하지 않는 구성ì›ì€ %{link_start}제한 초과 ìƒíƒœ%{link_end} ì´ ë˜ì–´ ì´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없게 ë©ë‹ˆë‹¤."
+msgstr[0] ""
msgid "When:"
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr "위키"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr "소스"
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr "ë‹´ë‹¹ìž ì¶”ê°€"
msgid "WorkItem|Add assignees"
msgstr "ë‹´ë‹¹ìž ì¶”ê°€"
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44465,7 +45283,7 @@ msgid "WorkItem|Closed"
msgstr ""
msgid "WorkItem|Collapse tasks"
-msgstr ""
+msgstr "작업 축소"
msgid "WorkItem|Create task"
msgstr ""
@@ -44473,12 +45291,18 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr "%{workItemType} 삭제"
-msgid "WorkItem|Expand tasks"
+msgid "WorkItem|Due date"
msgstr ""
+msgid "WorkItem|Expand tasks"
+msgstr "작업 펼침"
+
msgid "WorkItem|Incident"
msgstr "ì¸ì‹œë˜íŠ¸"
@@ -44492,7 +45316,7 @@ msgid "WorkItem|Learn about tasks."
msgstr "태스í¬ì— 대해 알아보기"
msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
-msgstr ""
+msgstr "현재 í• ë‹¹ëœ ìž‘ì—…ì´ ì—†ìŠµë‹ˆë‹¤. ìž‘ì—…ì„ ì‚¬ìš©í•˜ì—¬ ì´ ë¬¸ì œë¥¼ ë” ìž‘ì€ ë¶€ë¶„ìœ¼ë¡œ 나눕니다."
msgid "WorkItem|None"
msgstr "ì—†ìŒ"
@@ -44522,7 +45346,7 @@ msgid "WorkItem|Something went wrong when deleting the task. Please try again."
msgstr ""
msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
-msgstr ""
+msgstr "ìž‘ì—…ì„ ê°€ì ¸ì˜¬ ë•Œ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ì´ íŽ˜ì´ì§€ë¥¼ 새로고침하세요."
msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
msgstr ""
@@ -44542,14 +45366,17 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
-msgid "WorkItem|Task"
+msgid "WorkItem|Start date"
msgstr ""
+msgid "WorkItem|Task"
+msgstr "ìž‘ì—…"
+
msgid "WorkItem|Task deleted"
msgstr ""
msgid "WorkItem|Tasks"
-msgstr ""
+msgstr "태스í¬"
msgid "WorkItem|Test case"
msgstr "테스트 ì¼€ì´ìŠ¤"
@@ -44794,7 +45621,7 @@ msgstr "ë‚˜ì¤‘ì— ì–¸ì œë“ ì§€ 수정할 수 있습니다."
msgid "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} member has %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} member who maintains access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} member. The remaining members will get a status of Over limit and lose access to the group."
msgid_plural "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} members have %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr[0] ""
+msgstr[0] "ì´ì œ %{namespace_name} ì—ì„œ 멤버 ì´ë™ì„ 시작할 수 있습니다. %{strong_start}좌ì„ì—ì„œ%{strong_end}삭제하면 구성ì›ì´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없습니다. 2022ë…„ 10ì›” 19ì¼ ì´í›„ì— %{strong_start}좌ì„ì—ì„œ%{strong_end} %{free_user_limit} ì´ìƒì˜ 구성ì›ì´ í™œì„±í™”ëœ ê²½ìš° 액세스를 유지할 %{free_user_limit} ëª…ì˜ êµ¬ì„±ì›ì„ ì„ íƒí•©ë‹ˆë‹¤. 먼저 ì†Œìœ ìž ë° ìœ ì§€ ê´€ë¦¬ìž ì—­í• ì´ ìžˆëŠ” 구성ì›ì„ 계산한 ë‹¤ìŒ êµ¬ì„±ì›ì´ %{free_user_limit} ëª…ì— ë„달할 때까지 가장 ìµœê·¼ì— í™œë™í•œ 구성ì›ì„ 계산합니다. 나머지 구성ì›ì€ í•œë„ ì´ˆê³¼ ìƒíƒœê°€ ë˜ê³  ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없게 ë©ë‹ˆë‹¤."
msgid "You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44917,7 +45750,7 @@ msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%
msgstr ""
msgid "You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members. To get more members an owner of the group can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "ë” ì´ìƒ 추가할 수 없지만 비활성 구성ì›ì„ 제거하고 새 구성ì›ìœ¼ë¡œ êµì²´í•˜ëŠ” 등 기존 구성ì›ì„ 관리할 수 있습니다. ë” ë§Žì€ íšŒì›ì„ 가입시키려면 그룹 소유ìžëŠ” í‰ê°€íŒì„ 시작하거나 유료 계층으로 업그레ì´ë“œí•´ì•¼ 합니다."
msgid "You cannot %{action} %{state} users."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,8 +45978,8 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
-msgstr "디버그 추ì ì´ í™œì„±í™”ëœ ê²½ìš° ìž‘ì—… 로그를 보려면 ì—°ê²°ëœ í”„ë¡œì íŠ¸ì—ì„œ ê°œë°œìž ì´ìƒì˜ ê¶Œí•œì´ ìžˆì–´ì•¼ 합니다. 디버그 추ì ì„ 비활성화하려면 파ì´í”„ë¼ì¸ 구성 ë˜ëŠ” CI/CD 설정ì—ì„œ 'CI_DEBUG_TRACE' 변수를 'false'ë¡œ 설정하십시오. ì´ ìž‘ì—… 로그를 확ì¸í•´ì•¼ 하는 경우 프로ì íŠ¸ 관리ìžê°€ ê°œë°œìž ê¶Œí•œ ì´ìƒìœ¼ë¡œ 사용ìžë¥¼ 프로ì íŠ¸ì— 추가해야 합니다."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
+msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr "강제로 ìž ê¸ˆì„ ì œê±°í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
@@ -45296,7 +46132,7 @@ msgid "You're receiving this email because you have been mentioned on %{host}. %
msgstr ""
msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
+msgstr "%{strong_start}%{group_name}%{strong_end}ì˜ íšŒì›ì„ ë³´ê³  있습니다."
msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
msgstr "ì´ë¯¸ ì¼íšŒìš© ì¸ì¦ê¸°ë¥¼ ì´ìš©í•˜ì—¬ ì´ì¤‘ ì¸ì¦ì„ 활성화했습니다. 다른 기기를 등ë¡í•˜ë ¤ë©´ ì´ì¤‘ ì¸ì¦ì„ 먼저 비활성화해야 합니다."
@@ -45341,10 +46177,10 @@ msgid "Your CSV import for project"
msgstr ""
msgid "Your Chain of Custody CSV export for the group %{group_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "그룹 %{group_link} ì— ëŒ€í•œ CoC CSV 내보내기가 ì´ ì´ë©”ì¼ì— 첨부 파ì¼ë¡œ 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Your Chain of Custody CSV export for the group %{group_name} has been added to this email as an attachment."
-msgstr ""
+msgstr "그룹 %{group_name} ì— ëŒ€í•œ CoC CSV 내보내기가 ì´ ì´ë©”ì¼ì— 첨부 파ì¼ë¡œ 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
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 ""
@@ -45502,7 +46338,7 @@ msgstr[0] "무료 ê·¸ë£¹ì€ ì´ì œ %d 명으로 제한ë©ë‹ˆë‹¤."
msgid "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} member. From October 19, 2022, the %{free_user_limit} most recently active member will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} member will remain in your group."
msgid_plural "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} members. From October 19, 2022, the %{free_user_limit} most recently active members will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} members will remain in your group."
-msgstr[0] ""
+msgstr[0] "ê·€í•˜ì˜ ê·¸ë£¹ì¸ %{strong_start}%{namespace_name}%{strong_end} ì—는 %{free_user_limit} 명 ì´ìƒì˜ 회ì›ì´ 있습니다. 2022ë…„ 10ì›” 19ì¼ë¶€í„° 가장 ìµœê·¼ì— í™œë™í•œ %{free_user_limit} ëª…ì˜ êµ¬ì„±ì›ì´ 활ë™ì„ 유지하고 나머지 구성ì›ì€ %{link_start}명 초과 ìƒíƒœ%{link_end} ì´ ë˜ì–´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없습니다. 사용 할당량 페ì´ì§€ë¡œ ì´ë™í•˜ì—¬ ê·¸ë£¹ì— ë‚¨ì„ %{free_user_limit} ëª…ì˜ êµ¬ì„±ì›ì„ 관리할 수 있습니다."
msgid "Your groups"
msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
@@ -45574,7 +46410,7 @@ msgid "Your profile"
msgstr ""
msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
-msgstr ""
+msgstr "ê·€í•˜ì˜ í”„ë¡œì íŠ¸ëŠ” 2022-07-01 현재 GitLab Ultimate 혜íƒì„ ë” ì´ìƒ ë°›ì„ ìˆ˜ 없습니다. ì´ì „ì— ì¸ì•±ì—ì„œ 공지한 바와 ê°™ì´ í”„ë¦¬ í‹°ì–´ì˜ ê³µê°œ 오픈 소스 프로ì íŠ¸ëŠ” GitLab Ultimate 혜íƒì„ 받기 위해 오픈 소스 프로그램용 GitLabì— ì‹ ì²­í•  수 있습니다. ìžì„¸í•œ ë‚´ìš©ì€ %{faq_link_start}FAQ%{link_end} ì„ ì°¸ì¡°í•˜ì‹­ì‹œì˜¤."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""
@@ -45623,7 +46459,7 @@ msgstr ""
msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seat remaining."
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
-msgstr[0] ""
+msgstr[0] "구ë…ì— ë‚¨ì€ ì¢Œì„ì´ %{total_seat_count} 중 %{remaining_seat_count} ê°œ 있습니다."
msgid "Your subscription will expire on %{expires_on}"
msgstr "구ë…ì´ %{expires_on}ì— ë§Œë£Œë©ë‹ˆë‹¤."
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr "%{link_type} ë§í¬ë¥¼ 추가했습니다"
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr "by"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr "ê¸°ë°€ì´ ì•„ë‹Œ ìž‘ì—… í•­ëª©ì„ ê¸°ë°€ 부모ì—게 할당할 수 ì—†ì
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -45872,7 +46717,7 @@ msgid "cannot be changed if shared runners are enabled"
msgstr ""
msgid "cannot be changed since member is associated with a custom role"
-msgstr ""
+msgstr "구성ì›ì´ ì‚¬ìš©ìž ì§€ì • ì—­í• ê³¼ ì—°ê²°ë˜ì–´ 있으므로 변경할 수 없습니다."
msgid "cannot be enabled"
msgstr ""
@@ -45890,7 +46735,7 @@ msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
-msgstr ""
+msgstr "ì†ìƒëœ ê°œì¸ í‚¤ì— ì†í•˜ê¸° ë•Œë¬¸ì— ì‚¬ìš©í•  수 없습니다. ì´ í‚¤ ì‚¬ìš©ì„ ì¤‘ì§€í•˜ê³  새 키를 ìƒì„±í•˜ì‹­ì‹œì˜¤."
msgid "cannot be used for user namespace"
msgstr ""
@@ -45915,7 +46760,7 @@ msgid_plural "changes"
msgstr[0] ""
msgid "ciReport|%{criticalStart}critical%{criticalEnd}, %{highStart}high%{highEnd} and %{otherStart}others%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}중요%{criticalEnd}, %{highStart}높ìŒ%{highEnd} ë° %{otherStart}기타%{otherEnd}"
msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}"
msgstr ""
@@ -45969,13 +46814,13 @@ msgid "ciReport|%{scanner} detected %{number} new potential %{vulnStr}"
msgstr ""
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
-msgstr ""
+msgstr "%{scanner}가 %{vulnStr} 가능성 %{strong_start}%{number}%{strong_end} 개를 검출함"
msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
msgstr "ciReport|%{scanner}ê°€ no %{boldStart} 새로운 %{boldEnd} 잠재 보안 취약ì ë“¤ íƒì§€í•¨"
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
-msgstr ""
+msgstr "%{scanner}ê°€ %{strong_start}새로운%{strong_end} %{vulnStr} ê°€ëŠ¥ì„±ì„ ê²€ì¶¯í•˜ì§€ 못함"
msgid "ciReport|: Loading resulted in an error"
msgstr ""
@@ -45987,7 +46832,7 @@ msgid "ciReport|API fuzzing"
msgstr ""
msgid "ciReport|All clusters"
-msgstr ""
+msgstr "모든 í´ëŸ¬ìŠ¤í„°"
msgid "ciReport|All images"
msgstr "ciReport|모든 ì´ë¯¸ì§€"
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46262,7 +47110,7 @@ msgid "closed"
msgstr ""
msgid "closed %{timeago}"
-msgstr ""
+msgstr "종료 %{timeago}"
msgid "closed issue"
msgstr "닫힌 ì´ìŠˆ"
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr "댓글"
+msgid "commented"
+msgstr "코멘트"
+
msgid "commented on %{link_to_project}"
msgstr "%{link_to_project}ì— ëŒ“ê¸€ì„ ë‹¬ì•˜ìŠµë‹ˆë‹¤."
@@ -46318,6 +47169,9 @@ msgstr "%{timeAgo} ì „ ìƒì„±ë¨"
msgid "created %{timeAgo} by %{author}"
msgstr "%{timeAgo} ì „ %{author}ì— ì˜í•´ ìƒì„±ë¨"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46463,7 +47317,7 @@ msgid "following"
msgstr "팔로잉"
msgid "for"
-msgstr ""
+msgstr "for"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
msgstr ""
@@ -46516,7 +47370,7 @@ msgstr "그룹만"
msgid "had %{count} failed job"
msgid_plural "had %{count} failed jobs"
-msgstr[0] ""
+msgstr[0] "실패한 ìž‘ì—…ì´ %{count} ê°œ 있었습니다."
msgid "has already been linked to another vulnerability"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "ë¼ì¸"
+
msgid "load it anyway"
msgstr ""
@@ -46756,11 +47611,14 @@ msgid_plural "merge requests"
msgstr[0] "머지 리퀘스트(MR)"
msgid "mergedCommitsAdded| (commits were squashed)"
-msgstr ""
+msgstr "(ì»¤ë°‹ì´ ìŠ¤ì¿¼ì‹œë¨)"
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -46777,7 +47635,7 @@ msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
msgstr ""
msgid "mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit"
-msgstr ""
+msgstr "%{strongStart}1%{strongEnd} 커밋 머지"
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46840,10 +47698,10 @@ msgid "mrWidget|Approval password is invalid."
msgstr ""
msgid "mrWidget|Approval rule %{rules} is invalid. GitLab has approved this rule automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "mrWidget|ìŠ¹ì¸ ê·œì¹™ %{rules} ì´ ìœ íš¨í•˜ì§€ 않습니다. GitLabì€ ë¨¸ì§€ 리퀘스트 ì°¨ë‹¨ì„ í•´ì œí•˜ê¸° 위해 ì´ ê·œì¹™ì„ ìžë™ìœ¼ë¡œ 승ì¸í–ˆìŠµë‹ˆë‹¤. %{link}"
msgid "mrWidget|Approval rules %{rules} are invalid. GitLab has approved these rules automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "ìŠ¹ì¸ ê·œì¹™ %{rules} ì´ ìœ íš¨í•˜ì§€ 않습니다. GitLabì€ ë¨¸ì§€ 리퀘스트를 차단 해제하기 위해 ì´ëŸ¬í•œ ê·œì¹™ì„ ìžë™ìœ¼ë¡œ 승ì¸í–ˆìŠµë‹ˆë‹¤. %{link}"
msgid "mrWidget|Approve"
msgstr ""
@@ -47004,7 +47862,7 @@ msgid "mrWidget|More information"
msgstr ""
msgid "mrWidget|No users match the rule's criteria."
-msgstr ""
+msgstr "ê·œì¹™ì˜ ê¸°ì¤€ê³¼ ì¼ì¹˜í•˜ëŠ” 사용ìžê°€ 없습니다."
msgid "mrWidget|Please restore it or use a different %{type} branch."
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "전체 테스트 중 %d"
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr "%{link_type} ë§í¬ë¥¼ 제거했습니다"
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,11 +48241,15 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "좌ì„"
+
msgid "security Reports|There was an error creating the merge request"
msgstr "머지 리퀘스트를 ìƒì„±í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
-msgstr ""
+msgstr "selective_code_owner_removals는 retain_approvals_on_pushê°€ í™œì„±í™”ëœ ê²½ìš°ì—만 í™œì„±í™”ë  ìˆ˜ 있습니다."
msgid "severity|Blocker"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr "í…œí”Œë¦¿ì´ ì¤€ë¹„ë˜ì—ˆìŠµë‹ˆë‹¤! ì´ì œ ì´ë¥¼ 커밋하여 첫 번ì§
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr "프로ì íŠ¸ì— 파ì´í”„ë¼ì¸ì„ 추가하기 위해 GitLab CI 구성 파ì¼ì„ 추가하고 있습니다. 수ë™ìœ¼ë¡œ ìƒì„±í•  ìˆ˜ë„ ìžˆì§€ë§Œ 기본ì ìœ¼ë¡œ ìž‘ë™í•˜ëŠ” GitLab 템플릿으로 시작하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr "%{time_ago} ì „ ì—…ë°ì´íŠ¸ë¨"
msgid "uploads"
msgstr "업로드"
+msgid "user"
+msgid_plural "users"
+msgstr[0] "사용ìž"
+
msgid "user avatar"
msgstr "ì‚¬ìš©ìž ì•„ë°”íƒ€"
@@ -47652,7 +48524,7 @@ msgid "your GitLab instance"
msgstr "ë‹¹ì‹ ì˜ GitLab ì¸ìŠ¤í„´ìŠ¤"
msgid "your group (%{group_name})"
-msgstr ""
+msgstr "본ì¸ì˜ 그룹 (%{group_name})"
msgid "your settings"
msgstr "ë‹¹ì‹ ì˜ ì„¤ì •"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 283bda8ab85..ca67694f76a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index 688b66f734f..294541b6d87 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index f7a8f2e11f1..e66368e856f 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1210,13 +1217,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1925,9 +1941,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 126ff9ad4c0..ca9cf1d01a5 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ml_IN/gitlab.po b/locale/ml_IN/gitlab.po
index d3a3b2fdf39..cfa2339e1cc 100644
--- a/locale/ml_IN/gitlab.po
+++ b/locale/ml_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ml-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 55de11a66a6..5f9cb63fea4 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 33065af8318..fcad820e52d 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] "%d ekstra committer"
msgstr[1] "%d ekstra committere"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkjenner"
@@ -1024,11 +1029,6 @@ msgstr "%{spanStart}i%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} til %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}!%{strongClose} SAML-gruppelenker kan føre til at GitLab automatisk fjerner medlemmer fra grupper."
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] "%{strong_start}%{count} medlem%{strong_end} må godkjenne sammenslåing. Alle med «Utvikler»-rollen eller høyere kan godkjenne."
msgstr[1] "%{strong_start}%{count} medlemmer%{strong_end} må godkjenne sammenslåing. Alle med «Utvikler»-rollen eller høyere kan godkjenne."
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} prosjektlagring"
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} er ukjent eller ugyldig"
msgid "%{text} is available"
msgstr "%{text} er tilgjengelig"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} burde tilhøre enten et prosjekt eller en gruppe."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} støtter ikke utbrenningskart"
@@ -1132,6 +1134,9 @@ msgstr "%{total} saksvekt gjenstår"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advarsler funnet: viser første %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} støtter kun %{name} navn"
@@ -1153,12 +1158,15 @@ msgstr "%{user_name} (%{user_username}) ble fjernet fra følgende eskaleringspol
msgid "%{user_name} profile page"
msgstr "%{user_name} sin profilside"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} endret utkaststatusen til fletteforespørselen %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} har bedt om en GitLab-konto på din forekomst %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "%{username} sin avatar"
@@ -1180,6 +1188,12 @@ msgstr "%{value} sek"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} brukt tid."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler til nettapplikasjoner som svar på hendelser i en gruppe eller et prosjekt."
@@ -1665,9 +1679,6 @@ msgstr "En ny utgivelse %{tag} for %{name} ble publisert. Besøk 'Utgivelser'-si
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr "En side med den tittelen finnes allerede"
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr "Legg til bruker(e) til gruppen:"
-
-msgid "Add users to group"
-msgstr "Legg til brukere i gruppen"
-
msgid "Add variable"
msgstr "Legg til variabel"
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Blokkert"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Å blokkere brukeren har følgende effekter:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr "Avanserte eksportinnstillinger"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr "Alle fletteforespørselsavhengigheter har blitt innflettet"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Alle prosjekter"
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Tillat brukere å avvise utsendingsmeldingen"
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr "En feil oppstod under innlasting av alle filene."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "En feil oppstod under innlasting av diagramdata"
@@ -4457,6 +4516,9 @@ msgstr "En ukjent feil har oppstått."
msgid "Analytics"
msgstr "Analyser"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analyser avhengighetene dine for kjente sårbarheter."
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "Legger ved %d filer"
msgid "Attaching the file failed."
msgstr "Vedlegging av filen mislyktes."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Nedenfor vil du finne alle de gruppene som er offentlige."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr "Direkte medlemskap"
msgid "Billing|Enter at least three characters to search."
msgstr "Skriv inn minst tre tegn for å søke."
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr "Laster inn eposer"
msgid "Bold text"
msgstr "Fet tekst"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr "Grenen ble ikke lastet inn - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr "må være en gruppe"
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr "Distribusjonsstrategi"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Jobber"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr "Kan ikke forfremme saken på grunn av manglende tillatelser."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr "Endrer tittelen til \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Ukjent bruker"
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr "Commiter til"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "Commiter som du har valgt vises her. Gå til den første fanen og velg commiter å legge til i denne fletteforespørselen."
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "En feil oppstod under innhenting av fletteforespørselsdata."
@@ -9668,6 +9829,9 @@ msgstr "Fullført"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr "Fullført"
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr "Kontakter"
msgid "Container Registry"
msgstr "Container-register"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Containerskanning"
@@ -10511,13 +10678,13 @@ msgstr "Bidragsytere"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr "Land"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Dekning"
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr "Opprett bruker"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Opprett jokertegn: %{searchTerm}"
@@ -11069,6 +11242,12 @@ msgstr "Opprett gruppen din"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "Du har ikke tillatelse til å opprette en undergruppe i denne gruppen."
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Dag i måneden"
@@ -12510,6 +12695,9 @@ msgstr "Slett konto"
msgid "Delete artifacts"
msgstr "Slett artefakter"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr "Slettet"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr "Kun lesetilgang"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "Utløper"
@@ -13059,6 +13256,9 @@ msgstr "Tilbakekall %{name}"
msgid "DeployTokens|Scopes"
msgstr "Omfang"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Brukernavn"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr "suksess"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,19 +13536,10 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
-msgstr "Avbryt endringer"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Avbryt kommentarbekreftelse"
-
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
@@ -13360,6 +13548,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "Kommentar"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Klarte ikke å legge til en ny kommentar. Vennligst prøv igjen."
@@ -13378,8 +13572,8 @@ msgstr "Avvelg alle"
msgid "DesignManagement|Designs"
msgstr "Design"
-msgid "DesignManagement|Discard comment"
-msgstr "Forkast kommentar"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr "GÃ¥ til neste design"
msgid "DesignManagement|Go to previous design"
msgstr "GÃ¥ til forrige design"
-msgid "DesignManagement|Keep changes"
-msgstr "Behold endringer"
-
-msgid "DesignManagement|Keep comment"
-msgstr "Behold kommentaren"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr "Domene"
msgid "Domain Name"
msgstr "Domenenavn"
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Rediger wiki-side"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr "E-poster"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "Skru på E-postvarsler"
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Merk at denne handlingen vil stoppe miljøet, men det vil %{emphasisStart}ikke%{emphasisEnd} ha en effekt på noen eksisterende distribusjoner fordi ingen «Stopp miljøhandling» er definert i %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}-filen."
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Vis alle"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "Klarte ikke å laste inn emojilisten."
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr "Fant feil i din .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr "Gitlab-sak"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr "GitLab-sider"
@@ -18586,6 +18834,9 @@ msgstr "%{startDateInWords} - %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Laster inn eposer"
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr "Ingen start- eller sluttdato"
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr "Innen 3 år"
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "Retningslinje"
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr "Identifikasjoner"
msgid "Identities"
msgstr "Identiteter"
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr "Koble til kodelagre fra"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr "Uferdig"
msgid "Increase"
msgstr "Forstørr"
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr "Indeks"
@@ -21257,6 +21577,9 @@ msgstr "Legg til en integrasjon"
msgid "Integrations|Add namespace"
msgstr "Legg til et navneområde"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Alle detaljer"
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Skru på kommentarer"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr "GitLab-administratorer kan sette opp integrasjoner som alle grupper og prosjekter arver og benytter som standard. Disse integrasjonene gjelder for alle grupper og prosjekter som ikke allerede bruker tilpassede innstillinger. Du kan overstyre tilpassede innstillinger for en gruppe eller prosjekt dersom innstillingene er nødvendige på det nivået. Lær mer om %{integrations_link_start}integrasjonsbehandling på instans-nivå%{link_end}."
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallmønster"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr "Bruker lisenssetet:"
msgid "Is using seat"
msgstr "Benytter sete"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr "Sak"
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr "Milepæl"
@@ -22052,7 +22390,7 @@ msgid "IssueBoards|Switch board"
msgstr "Bytt bord"
msgid "IssueList|created %{timeAgoString} by %{user}"
-msgstr ""
+msgstr "IssueList|opprettet %{timeAgoString} av %{user}"
msgid "IssueTracker|Custom issue tracker"
msgstr "Tilpasset sakssporer"
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
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"
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr "Nyligst pålogget kl.:"
msgid "Last successful update"
msgstr "Forrige vellykkede oppdatering"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr "Senest verifisert"
@@ -23324,8 +23662,8 @@ msgstr ""
msgid "Learn more"
msgstr "Lær mer"
-msgid "Learn more about %{username}"
-msgstr "Lær mer om %{username}"
+msgid "Learn more about %{name}"
+msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Lær mer om Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr "Gjør alle på teamet ditt mer produktive, uansett hvor de befinner seg.
msgid "Make issue confidential"
msgstr "Gjør saken konfidensiell"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,12 +24505,12 @@ msgstr "Behandle prosjekter."
msgid "Manage two-factor authentication"
msgstr "Behandle 2-trinnsautentisering"
-msgid "Manage your license"
-msgstr "Behandle lisensen din"
-
msgid "Manage your project's triggers"
msgstr ""
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "Behandlet konto"
@@ -24251,9 +24592,24 @@ msgstr "Legg til gjennomstreket tekst (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Legg til gjennomstreket tekst (%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "Støtter %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr "Markerte oppgaven som ferdig."
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr "Speilingsinnstillinger er bare tilgjengelige for GitLab-administratorer.
msgid "Mirror user"
msgstr "Speil bruker"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Speilede kodelagre"
@@ -25933,6 +26295,9 @@ msgstr "Navnet er allerede tatt."
msgid "Name new label"
msgstr "Navnet på nytt stempel"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Navn:"
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr "Nytt prosjekt"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Nytt krav"
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "Antall commiter"
@@ -26747,7 +27118,7 @@ msgid "NoteForm|Note"
msgstr "Notis"
msgid "NoteToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd}, type %{keyboardStart}/%{keyboardEnd}."
-msgstr "NoteToolbar|Støtter %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}hurtighandlinger%{quickActionsDocsLinkEnd}, tast %{keyboardEnd}%{keyboardStart}."
+msgstr "NoteToolbar|Støtter %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}hurtighandlinger%{quickActionsDocsLinkEnd}, tast %{keyboardStart}/%{keyboardEnd}."
msgid "Notes"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr "Notify|%{changed_files}:"
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "Notify |%{member_link} ba om %{member_role}-tilgang til %{target_source_link} %{target_type}."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Okt"
@@ -27287,6 +27778,9 @@ msgstr "Rotasjoner"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr "Overstyrt"
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Slett pakkeversjonen"
msgid "PackageRegistry|Delete package"
msgstr "Slett pakke"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Lær hvordan man %{noPackagesLinkStart}publiserer og deler pakkene dine%{noPackagesLinkEnd} med GitLab."
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr "Vis PyPi-kommandoer"
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr "Pause"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Aktiv"
msgid "PipelineSchedules|All"
msgstr "Alle"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inaktive"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Neste kjøring"
@@ -28960,15 +29472,27 @@ msgstr "Ingen"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "MÃ¥l"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variabler"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Vennligst vent et øyeblikk, denne siden vil automatisk oppfriskes når det er klart."
@@ -29773,6 +30306,9 @@ msgstr "Vennligst vent mens vi kobler til kodelageret ditt. Oppdater når du vil
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Vennligst vent mens vi importerer kodelageret ditt. Oppdater når du vil."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "Podder som brukes"
@@ -29833,6 +30369,9 @@ msgstr "Innstillinger"
msgid "Preferences saved."
msgstr "Innstillingene ble lagret."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Oppførsel"
@@ -29944,6 +30483,9 @@ msgstr "Tidspreferanser"
msgid "Preferences|Use relative times"
msgstr "Bruk relative tidspunkter"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr "Aktiv"
msgid "Profiles|Add key"
msgstr "Legg til nøkkel"
-msgid "Profiles|Add status emoji"
-msgstr "Legg til status emoji"
-
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 ""
-
msgid "Profiles|Avatar cropper"
msgstr "Avatarbeskjærer"
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "Profil"
-msgid "Profiles|Busy"
-msgstr "Opptatt"
-
msgid "Profiles|Change username"
msgstr "Endre brukernavn"
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "By, land"
-msgid "Profiles|Clear status"
-msgstr "Tøm status"
-
msgid "Profiles|Commit email"
msgstr "Commit-E-post"
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Tilkoblede kontoer"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Nåværende bane: %{path}"
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "Hva er statusen din?"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr "Navnet ditt ble automatisk satt, basert på din %{provider_label}-konto,
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Din status"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr "Oppmuntre til"
@@ -31141,12 +31674,18 @@ msgstr "Fletteforslag"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr "Prosjektsynlighet"
msgid "ProjectSettings|Public"
msgstr "Offentlig"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Kodelager"
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Gren"
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr "Beskyttede grener"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr "Kodeforespørsler fra utgreininger er ikke støttet"
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Les mer"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr "Les mer om GitLab på %{link_to_promo}."
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr "Registrer enhet"
@@ -33439,6 +34020,9 @@ msgstr "Kodelagerspeiling"
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr "Kopier E-postadressen"
@@ -33846,6 +34433,9 @@ msgstr "Rolle"
msgid "Rollback"
msgstr "Tilbakeføring"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr "Navn"
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Løpere"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr "Etiketter"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr "Lagrer prosjekt."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr "Søk blant tilordnede"
msgid "Search authors"
msgstr "Søk etter skapere"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Søk i grener"
@@ -34797,6 +35408,9 @@ msgstr "Søk i prosjekter"
msgid "Search projects..."
msgstr "Søk blant prosjekter …"
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "Ikke skrudd på"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Opprett saker"
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr "Avfeide '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Sak opprettet"
@@ -35734,6 +36357,9 @@ msgstr "Beklager, filteret ditt ga ingen resultater"
msgid "SecurityReports|Status"
msgstr "Status"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Velg arkivformat"
msgid "Select Git revision"
msgstr "Velg Git-revisjon"
-msgid "Select Page"
-msgstr "Velg side"
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr "Velg et mal-kodelager"
msgid "Select a template type"
msgstr "Velg en maltype"
-msgid "Select a time zone"
-msgstr "Velg en tidssone"
-
msgid "Select a timezone"
msgstr "Velg en tidssone"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr "Velg gren"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Velg måldato"
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr "Velg prosjekter"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Velg anmelder(e)"
@@ -36289,6 +36918,9 @@ msgstr "Bestem målgren"
msgid "Set target branch to %{branch_name}."
msgstr "Sett målgrenen til %{branch_name}."
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr "Bestem vektlegging"
msgid "Set weight to %{weight}."
msgstr "Sett vektlegging til %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr "Opptatt"
-
msgid "SetStatusModal|Clear status"
msgstr "Tøm status"
msgid "SetStatusModal|Clear status after"
msgstr "Fjern statusen etter"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Rediger status"
@@ -36388,6 +37017,9 @@ msgstr "Bestem en status"
msgid "SetStatusModal|Set status"
msgstr "Bestem status"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snøplog"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr "Sorter retning: stigende"
msgid "Sort direction: Descending"
msgstr "Sorter retning: synkende"
+msgid "Sort or filter"
+msgstr "Sorter eller filtrer"
+
msgid "SortOptions|Blocking"
msgstr "Blokkering"
@@ -37337,6 +38008,9 @@ msgstr "Siste kontakt"
msgid "SortOptions|Last created"
msgstr "Sist opprettet"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Minst populær"
@@ -37397,6 +38071,9 @@ msgstr "Eldste stjernemerkede"
msgid "SortOptions|Oldest updated"
msgstr "Eldste oppdaterte"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "Popularitet"
@@ -38297,8 +38974,8 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr "Grønn-cyan"
-msgid "SuggestedColors|Lavendar"
-msgstr "Lavendel"
+msgid "SuggestedColors|Lavender"
+msgstr ""
msgid "SuggestedColors|Magenta-pink"
msgstr "Magenta-rosa"
@@ -38321,9 +38998,21 @@ msgstr "Rosenrød"
msgid "SuggestedColors|Titanium yellow"
msgstr "Titanium-gul"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr "Aktiver abonnement"
msgid "SuperSonics|Activation code"
msgstr "Aktiveringskode"
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr "Fakturerbare brukere"
msgid "SuperSonics|Buy subscription"
msgstr "Kjøp abonnement"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "Abonnementet ditt"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr "Det er ingen tilgjengelige data."
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr "Dette Cron-mønsteret er ugyldig"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr "Denne blokken refererer til seg selv"
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Dette er din nåværende økt"
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Dette prosjektet er lisensiert som %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr "Dette prosjektet vil bli slettet den %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr "Veksle commit-beskrivelsen"
msgid "Toggle commit list"
msgstr "Veksle commit-listen"
-msgid "Toggle dropdown"
-msgstr "Veksle nedfall"
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Veksle sidelinje"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr "Totalt antall kjerner (CPU-er)"
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr "Totalt minne (GB)"
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "GÃ¥ tilbake til GitLab"
-msgid "Trials|Hey there"
-msgstr "Heisann"
-
msgid "Trials|Skip Trial"
msgstr "Hopp over prøveperiode"
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artifakter"
@@ -42350,10 +43104,10 @@ msgstr "Bruk i nåværende periode"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr "Kodelager"
msgid "UsageQuota|Seats"
msgstr "Seter"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr "Brukeridentiteten ble vellykket fjernet."
msgid "User identity was successfully updated."
msgstr "Brukeridentiteten ble vellykket oppdatert."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr "Brukeren har ikke tillatelse til å oppklare tråden"
@@ -43126,9 +43880,6 @@ msgstr "Brukere som ber om tilgang til"
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "Brukerne ble vellykket lagt til."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr "Utildelt"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Vis diagram"
@@ -43431,8 +44212,8 @@ msgstr "Vis dokumentasjon"
msgid "View eligible approvers"
msgstr "Vis kvalifiserte godkjennere"
-msgid "View epics list"
-msgstr "Vis epos-liste"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "File"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,12 +44660,12 @@ msgstr "Bilde"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "Lenker"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr "Metode"
@@ -43891,6 +44675,9 @@ msgstr "Navnefelt"
msgid "Vulnerability|Project"
msgstr "Prosjekt"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Alvorlighetsgrad"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "Status"
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Verktøy"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "Skru på SSL-verifisering"
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "Sakshendelser"
msgid "Webhooks|Job events"
msgstr "Jobb-hendelser"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr "SSL-verifisering"
msgid "Webhooks|Secret token"
msgstr "Hemmelig sjetong"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "Undergruppehendelser"
@@ -44284,6 +45101,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,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 add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr "lagt til"
msgid "added %{emails}"
msgstr "la til %{emails}"
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr "av"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "kan ikke endres"
@@ -46392,6 +47239,9 @@ msgstr "Fant %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr "kommentar"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "kommenterte på %{link_to_project}"
@@ -46586,7 +47439,7 @@ msgid "created %{issuable_created} by %{author}"
msgstr ""
msgid "created %{timeAgoString} by %{email} via %{user}"
-msgstr ""
+msgstr "Ã¥pnet %{timeAgoString} av %{email} via %{user}"
msgid "created %{timeAgo}"
msgstr "opprettet %{timeAgo}"
@@ -46594,6 +47447,9 @@ msgstr "opprettet %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "opprettet for %{timeAgo} av %{author}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr "laget av"
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr "grensen på %{project_limit} er nådd"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr "last den inn likevel"
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "mangler"
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "min-kule-gruppe"
@@ -47493,9 +48357,6 @@ msgstr "eller"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr "fjern vektlegging"
msgid "removed"
msgstr "fjernet"
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr "Vi legger til en GitLab CI-konfigurasjonsfil for å legge til en rørledning i prosjektet. Du kan opprette det manuelt, men vi anbefaler at du starter med en GitLab-mal som fungerer rett ut av boksen."
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "etikettnavn"
@@ -47845,6 +48717,11 @@ msgstr "oppdatert %{time_ago}"
msgid "uploads"
msgstr "opplastinger"
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "brukerens profilbilde"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 2a3f0347766..92e99e1b842 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} is beschikbaar"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/or_IN/gitlab.po b/locale/or_IN/gitlab.po
index 422403bddf4..c45da23d6c7 100644
--- a/locale/or_IN/gitlab.po
+++ b/locale/or_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: or\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index ef106bedba5..663cd9071ff 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/pa_PK/gitlab.po b/locale/pa_PK/gitlab.po
new file mode 100644
index 00000000000..d5c98b786df
--- /dev/null
+++ b/locale/pa_PK/gitlab.po
@@ -0,0 +1,48837 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Punjabi, Pakistan\n"
+"Language: pa_PK\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Project-ID: 288872\n"
+"X-Crowdin-Language: pa-PK\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 16\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
+
+msgid " %{start} to %{end}"
+msgstr ""
+
+msgid " (from %{timeoutSource})"
+msgstr ""
+
+msgid " (squashes %{strongStart}%{count}%{strongEnd} commit)"
+msgid_plural " (squashes %{strongStart}%{count}%{strongEnd} commits)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " Collected %{time}"
+msgstr ""
+
+msgid " Please sign in."
+msgstr ""
+
+msgid " Try to %{action} this file again."
+msgstr ""
+
+msgid " You need to do this before %{grace_period_deadline}."
+msgstr ""
+
+msgid " and "
+msgstr ""
+
+msgid " and %{sliced}"
+msgstr ""
+
+msgid " or "
+msgstr ""
+
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}#id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
+
+msgid " or references (e.g. path/to/project!merge_request_id)"
+msgstr ""
+
+msgid " reacted with :%{name}:"
+msgstr ""
+
+msgid "\"%{path}\" did not exist on \"%{ref}\""
+msgstr ""
+
+msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
+msgstr ""
+
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
+msgid "#general, #development"
+msgstr ""
+
+msgid "%d Alert"
+msgid_plural "%d Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Alert:"
+msgid_plural "%d Alerts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Approval"
+msgid_plural "%d Approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Module"
+msgid_plural "%d Modules"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Other"
+msgid_plural "%d Others"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Package"
+msgid_plural "%d Packages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Scanned URL"
+msgid_plural "%d Scanned URLs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d URL scanned"
+msgid_plural "%d URLs scanned"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional approver"
+msgid_plural "%d additional approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional assignee"
+msgid_plural "%d additional assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional commenter"
+msgid_plural "%d additional commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional committer"
+msgid_plural "%d additional committers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver"
+msgid_plural "%d approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver (you've approved)"
+msgid_plural "%d approvers (you've approved)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d artifact"
+msgid_plural "%d artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d assigned issue"
+msgid_plural "%d assigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d child epic"
+msgid_plural "%d child epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d code quality issue"
+msgid_plural "%d code quality issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment on this commit"
+msgid_plural "%d comments on this commit"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commenter"
+msgid_plural "%d commenters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit author"
+msgid_plural "%d commit authors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit,"
+msgid_plural "%d commits,"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d completed issue"
+msgid_plural "%d completed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d contributor"
+msgid_plural "%d contributors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d epic"
+msgid_plural "%d epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error"
+msgid_plural "%d errors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed"
+msgid_plural "%d failed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d inaccessible merge request"
+msgid_plural "%d inaccessible merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue in this group"
+msgid_plural "%d issues in this group"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue successfully imported with the label"
+msgid_plural "%d issues successfully imported with the label"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d job"
+msgid_plural "%d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d milestone"
+msgid_plural "%d milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d pending comment"
+msgid_plural "%d pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d personal project will be removed and cannot be restored."
+msgid_plural "%d personal projects will be removed and cannot be restored."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d point"
+msgid_plural "%d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d previously merged commit"
+msgid_plural "%d previously merged commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project"
+msgid_plural "%d projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project selected"
+msgid_plural "%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d push"
+msgid_plural "%d pushes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d remaining"
+msgid_plural "%d remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d reply"
+msgid_plural "%d replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d stage"
+msgid_plural "%d stages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag"
+msgid_plural "%d tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag per image name"
+msgid_plural "%d tags per image name"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unresolved thread"
+msgid_plural "%d unresolved threads"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability"
+msgid_plural "%d vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability dismissed"
+msgid_plural "%d vulnerabilities dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to confirmed"
+msgid_plural "%d vulnerabilities set to confirmed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to dismissed"
+msgid_plural "%d vulnerabilities set to dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to needs triage"
+msgid_plural "%d vulnerabilities set to needs triage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability set to resolved"
+msgid_plural "%d vulnerabilities set to resolved"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d warning found:"
+msgid_plural "%d warnings found:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
+msgstr ""
+
+msgid "%{author_link} wrote:"
+msgstr ""
+
+msgid "%{authorsName}'s thread"
+msgstr ""
+
+msgid "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
+msgstr ""
+
+msgid "%{board_target} not found"
+msgstr ""
+
+msgid "%{bold_start}%{count}%{bold_end} issue"
+msgid_plural "%{bold_start}%{count}%{bold_end} issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{bold_start}%{count}%{bold_end} member"
+msgid_plural "%{bold_start}%{count}%{bold_end} members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{bold_start}%{count}%{bold_end} opened merge request"
+msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
+msgstr ""
+
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags."
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_authored_timeago}"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
+msgstr ""
+
+msgid "%{completedCount} completed weight"
+msgstr ""
+
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{completedWeight} of %{totalWeight} weight completed"
+msgstr ""
+
+msgid "%{completed} of %{total} issues closed"
+msgstr ""
+
+msgid "%{completed} of %{total} weight completed"
+msgstr ""
+
+msgid "%{cores} cores"
+msgstr ""
+
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
+msgid "%{count} LOC/commit"
+msgstr ""
+
+msgid "%{count} approval required from %{name}"
+msgid_plural "%{count} approvals required from %{name}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} files touched"
+msgstr ""
+
+msgid "%{count} item"
+msgid_plural "%{count} items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} items per page"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} more release"
+msgid_plural "%{count} more releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} of %{required} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} of %{total}"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} related %{pluralized_subject}: %{links}"
+msgstr ""
+
+msgid "%{count} selected"
+msgstr ""
+
+msgid "%{count} total weight"
+msgstr ""
+
+msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
+msgstr ""
+
+msgid "%{dashboard_path} could not be found."
+msgstr ""
+
+msgid "%{days} days until tags are automatically removed"
+msgstr ""
+
+msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
+msgstr ""
+
+msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
+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 ""
+
+msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
+msgstr ""
+
+msgid "%{due_date} (Past due)"
+msgstr ""
+
+msgid "%{duration}ms"
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to upload a file again."
+msgstr ""
+
+msgid "%{emailPrefix}@company.com"
+msgstr ""
+
+msgid "%{enable_service_ping_link_start}Enable%{link_end} or %{generate_manually_link_start}generate%{link_end} Service Ping to preview and download service usage data payload."
+msgstr ""
+
+msgid "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
+msgstr ""
+
+msgid "%{gitlab_experience_text}. We won't share this information with anyone."
+msgstr ""
+
+msgid "%{global_id} is not a valid ID for %{expected_types}."
+msgstr ""
+
+msgid "%{group_name} activity"
+msgstr ""
+
+msgid "%{group_name} group members"
+msgstr ""
+
+msgid "%{group_name} is approaching the limit of available seats"
+msgstr ""
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
+msgstr ""
+
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
+msgid "%{host} sign-in from new location"
+msgstr ""
+
+msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr ""
+
+msgid "%{issuable}(s) already assigned"
+msgstr ""
+
+msgid "%{issueType} actions"
+msgstr ""
+
+msgid "%{issuesSize} with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
+msgstr ""
+
+msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
+msgstr ""
+
+msgid "%{labelStart}Class:%{labelEnd} %{class}"
+msgstr ""
+
+msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
+msgstr ""
+
+msgid "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
+msgstr ""
+
+msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
+msgstr ""
+
+msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
+msgstr ""
+
+msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
+msgstr ""
+
+msgid "%{labelStart}File:%{labelEnd} %{file}"
+msgstr ""
+
+msgid "%{labelStart}Image:%{labelEnd} %{image}"
+msgstr ""
+
+msgid "%{labelStart}Method:%{labelEnd} %{method}"
+msgstr ""
+
+msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+msgstr ""
+
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr ""
+
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgstr ""
+
+msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
+msgstr ""
+
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{label_for_message} unavailable"
+msgstr ""
+
+msgid "%{lessThan} 1 hour"
+msgstr ""
+
+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 ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
+msgid "%{link_start}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 draft from merging before it's ready."
+msgstr ""
+
+msgid "%{listToShow}, and %{awardsListLength} more"
+msgstr ""
+
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{mergeLength}/%{usersLength} can merge"
+msgstr ""
+
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{message}. Your attention request was removed."
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
+msgid "%{minutesUsed} minutes"
+msgstr ""
+
+msgid "%{model_name} not found"
+msgstr ""
+
+msgid "%{mrText}, this issue will be closed automatically."
+msgstr ""
+
+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 ""
+
+msgid "%{name_with_link} namespace has run out of Shared Runner Pipeline minutes. No new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name} (Busy)"
+msgstr ""
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
+msgid "%{name} is already being used for another emoji"
+msgstr ""
+
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
+msgid "%{name} is scheduled for %{action}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+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 ""
+
+msgid "%{name}(%{url}) namespace has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name}, confirm your email address now!"
+msgstr ""
+
+msgid "%{name}: %{resultsString}"
+msgstr ""
+
+msgid "%{no_of_days} day"
+msgid_plural "%{no_of_days} days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{oneMonthAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneWeekAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneYearAgo} - %{today}"
+msgstr ""
+
+msgid "%{openedEpics} open, %{closedEpics} closed"
+msgstr ""
+
+msgid "%{openedIssues} open, %{closedIssues} closed"
+msgstr ""
+
+msgid "%{over_limit_message} To get more members, an owner of the group can start a trial or upgrade to a paid tier."
+msgstr ""
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "%{percentageUsed}%% used"
+msgstr ""
+
+msgid "%{percentage}%% issues closed"
+msgstr ""
+
+msgid "%{percentage}%% weight completed"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{percent}%{percentSymbol} complete"
+msgstr ""
+
+msgid "%{placeholder} is not a valid color scheme"
+msgstr ""
+
+msgid "%{placeholder} is not a valid theme"
+msgstr ""
+
+msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
+msgid "%{project_name}"
+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 ""
+
+msgid "%{releases} release"
+msgid_plural "%{releases} releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{remaining_approvals} left"
+msgstr ""
+
+msgid "%{reportType} %{status}"
+msgstr ""
+
+msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
+msgstr ""
+
+msgid "%{reportType} detected no %{totalStart}new%{totalEnd} vulnerabilities."
+msgstr ""
+
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{runner} created %{timeago}"
+msgstr ""
+
+msgid "%{scope} results for term '%{term}'"
+msgstr ""
+
+msgid "%{seconds}s"
+msgstr ""
+
+msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{securityScanner} result is not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{size} %{unit}"
+msgstr ""
+
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
+msgid "%{source} %{copyButton} into %{target}"
+msgstr ""
+
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
+msgstr ""
+
+msgid "%{spanStart}in%{spanEnd} %{errorFn}"
+msgstr ""
+
+msgid "%{start} to %{end}"
+msgstr ""
+
+msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
+msgstr ""
+
+msgid "%{strongStart}%{count}%{strongEnd} commit"
+msgid_plural "%{strongStart}%{count}%{strongEnd} commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} approval rule%{strong_end} requires eligible members to approve before merging."
+msgid_plural "%{strong_start}%{count} approval rules%{strong_end} require eligible members to approve before merging."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} eligible member%{strong_end} must approve to merge."
+msgid_plural "%{strong_start}%{count} eligible members%{strong_end} must approve to merge."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
+msgstr ""
+
+msgid "%{strong_start}%{release_count}%{strong_end} Release"
+msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{tabname} changed"
+msgstr ""
+
+msgid "%{tags} tag per image name"
+msgstr ""
+
+msgid "%{tags} tags per image name"
+msgstr ""
+
+msgid "%{tag}-%{evidence}-%{filename}"
+msgstr ""
+
+msgid "%{template_project_id} is unknown or invalid"
+msgstr ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{timebox_type} does not support burnup charts"
+msgstr ""
+
+msgid "%{timebox_type} must have a start and due date"
+msgstr ""
+
+msgid "%{time} UTC"
+msgstr ""
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalWeight} total weight"
+msgstr ""
+
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
+msgid "%{total} remaining issue weight"
+msgstr ""
+
+msgid "%{total} warnings found: showing first %{warningsDisplayed}"
+msgstr ""
+
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+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 ""
+
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
+msgid "%{username}'s avatar"
+msgstr ""
+
+msgid "%{user} created a merge request: %{mr_link}"
+msgstr ""
+
+msgid "%{user} created an epic: %{epic_link}"
+msgstr ""
+
+msgid "%{user} created an issue: %{issue_link}"
+msgstr ""
+
+msgid "%{value} is not included in the list"
+msgstr ""
+
+msgid "%{value} s"
+msgstr ""
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
+msgstr ""
+
+msgid "%{widget} options"
+msgstr ""
+
+msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{name}' Value Stream created"
+msgstr ""
+
+msgid "'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "'%{template_name}' is unknown or invalid"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
+msgid "(%{value}) has already been taken"
+msgstr ""
+
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
+msgid "(Group Managed Account)"
+msgstr ""
+
+msgid "(No changes)"
+msgstr ""
+
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(expired)"
+msgstr ""
+
+msgid "(leave blank if you don't want to change it)"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(optional)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "(this user)"
+msgstr ""
+
+msgid "(we need your current password to confirm your changes)"
+msgstr ""
+
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
+msgid "*Required"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
+msgid "+%{tags} more"
+msgstr ""
+
+msgid ", "
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
+msgid "- Add or remove a user."
+msgstr ""
+
+msgid "- Available to run jobs."
+msgstr ""
+
+msgid "- Create or close an issue."
+msgstr ""
+
+msgid "- Create, update, or delete a merge request."
+msgstr ""
+
+msgid "- Event"
+msgid_plural "- Events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- Go to the Activity page for %{project_name}."
+msgstr ""
+
+msgid "- List the visible events for %{project_name} using the Events API %{events_api_link}."
+msgstr ""
+
+msgid "- Not available to run jobs."
+msgstr ""
+
+msgid "- Push code to the repository."
+msgstr ""
+
+msgid "- Select -"
+msgstr ""
+
+msgid "- User"
+msgid_plural "- Users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- View the last_activity_at attribute for %{project_name} using the Project API %{projects_api_link}."
+msgstr ""
+
+msgid "- of - issues closed"
+msgstr ""
+
+msgid "- of - weight completed"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "."
+msgstr ""
+
+msgid "/"
+msgstr ""
+
+msgid "/day"
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "1 Code quality finding"
+msgid_plural "%d Code quality findings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Day"
+msgid_plural "%d Days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Issue"
+msgid_plural "%d Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day selected"
+msgid_plural "%d days selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 deploy key"
+msgid_plural "%d deploy keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 follower"
+msgid_plural "%{count} followers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%{num} users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
+msgid "1000+"
+msgstr ""
+
+msgid "192.168.0.0/24 or 2001:0DB8:1234::/48"
+msgstr ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "20-29 contributions"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FADevice|Registered On"
+msgstr ""
+
+msgid "3 hours"
+msgstr ""
+
+msgid "30 minutes"
+msgstr ""
+
+msgid "30+ contributions"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "409|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "409|There was a conflict with your request."
+msgstr ""
+
+msgid "8 hours"
+msgstr ""
+
+msgid ":%{startLine} to %{endLine}"
+msgstr ""
+
+msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
+msgstr ""
+
+msgid "A .NET Core console application template, customizable for any .NET Core project"
+msgstr ""
+
+msgid "A CI/CD pipeline must run and be successful before merge."
+msgstr ""
+
+msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Gitpod configured Webapplication in Spring and Java"
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
+msgstr ""
+
+msgid "A Work Item can be a parent or a child, but not both."
+msgstr ""
+
+msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
+msgstr ""
+
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
+msgid "A complete DevOps platform"
+msgstr ""
+
+msgid "A confidential issue cannot have a parent that already has non-confidential children."
+msgstr ""
+
+msgid "A confidential work item cannot have a parent that already has non-confidential children."
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A different reason"
+msgstr ""
+
+msgid "A file has been changed."
+msgstr ""
+
+msgid "A file was not found."
+msgstr ""
+
+msgid "A file with '%{file_name}' already exists in %{branch} branch"
+msgstr ""
+
+msgid "A file with this name already exists."
+msgstr ""
+
+msgid "A group is a collection of several projects"
+msgstr ""
+
+msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
+msgstr ""
+
+msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
+msgstr ""
+
+msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
+msgstr ""
+
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
+msgstr ""
+
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
+msgstr ""
+
+msgid "A new email address has been added to your GitLab account: %{email}"
+msgstr ""
+
+msgid "A new personal access token has been created"
+msgstr ""
+
+msgid "A new personal access token, named %{token_name}, has been created."
+msgstr ""
+
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
+msgid "A non-confidential issue cannot have a confidential parent."
+msgstr ""
+
+msgid "A non-confidential work item cannot have a confidential parent."
+msgstr ""
+
+msgid "A page with that title already exists"
+msgstr ""
+
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
+msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A platform value can be web, mob or app."
+msgstr ""
+
+msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
+msgstr ""
+
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
+msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
+msgstr ""
+
+msgid "A project’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 ""
+
+msgid "A ready-to-go template for use with iOS Swift apps"
+msgstr ""
+
+msgid "A rebase is already in progress."
+msgstr ""
+
+msgid "A sign-in to your account has been made from the following IP address: %{ip}"
+msgstr ""
+
+msgid "A title is required"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
+msgstr ""
+
+msgid "API"
+msgstr ""
+
+msgid "API Fuzzing"
+msgstr ""
+
+msgid "API Fuzzing Configuration"
+msgstr ""
+
+msgid "API Help"
+msgstr ""
+
+msgid "API Token"
+msgstr ""
+
+msgid "API key"
+msgstr ""
+
+msgid "API?"
+msgstr ""
+
+msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
+msgstr ""
+
+msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
+msgstr ""
+
+msgid "APIFuzzing|Choose a method"
+msgstr ""
+
+msgid "APIFuzzing|Choose a profile"
+msgstr ""
+
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Customize your project's API fuzzing configuration options and copy the code snippet to your .gitlab-ci.yml file to apply any changes. Note that this tool does not reflect or update your .gitlab-ci.yml file automatically. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Enable authentication"
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
+msgstr ""
+
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
+msgstr ""
+
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
+msgstr ""
+
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
+msgstr ""
+
+msgid "APIFuzzing|Generate code snippet"
+msgstr ""
+
+msgid "APIFuzzing|Make sure your credentials are secured"
+msgstr ""
+
+msgid "APIFuzzing|Password for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|Predefined profiles"
+msgstr ""
+
+msgid "APIFuzzing|Scan mode"
+msgstr ""
+
+msgid "APIFuzzing|Scan profile"
+msgstr ""
+
+msgid "APIFuzzing|Show code snippet for the profile"
+msgstr ""
+
+msgid "APIFuzzing|Target URL"
+msgstr ""
+
+msgid "APIFuzzing|There are three ways to perform scans."
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all stages"
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
+msgstr ""
+
+msgid "APIFuzzing|Username for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
+msgstr ""
+
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
+msgid "AWS Access Key"
+msgstr ""
+
+msgid "AWS OpenSearch IAM credentials"
+msgstr ""
+
+msgid "AWS Secret Access Key"
+msgstr ""
+
+msgid "AWS access key ID (Optional)"
+msgstr ""
+
+msgid "AWS secret access key (Optional)"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
+
+msgid "Abort"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "About your company"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Abuse reports notification email"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Acceptable for use in this project"
+msgstr ""
+
+msgid "Access Git repositories or the API."
+msgstr ""
+
+msgid "Access Token"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied for your LDAP account."
+msgstr ""
+
+msgid "Access denied: %{error}"
+msgstr ""
+
+msgid "Access expires"
+msgstr ""
+
+msgid "Access forbidden. Check your access level."
+msgstr ""
+
+msgid "Access granted"
+msgstr ""
+
+msgid "Access requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "AccessDropdown|Deploy Keys"
+msgstr ""
+
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "AccessTokens|Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Are you sure?"
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Copy feed token"
+msgstr ""
+
+msgid "AccessTokens|Copy incoming email token"
+msgstr ""
+
+msgid "AccessTokens|Copy static object token"
+msgstr ""
+
+msgid "AccessTokens|Created"
+msgstr ""
+
+msgid "AccessTokens|Feed token"
+msgstr ""
+
+msgid "AccessTokens|Incoming email token"
+msgstr ""
+
+msgid "AccessTokens|It cannot be used to access any other data."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who 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 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 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|Personal Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Static object token"
+msgstr ""
+
+msgid "AccessTokens|The last time a token was used"
+msgstr ""
+
+msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
+msgstr ""
+
+msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
+msgstr ""
+
+msgid "AccessTokens|You can generate a personal access token for each application you use that needs access to the GitLab API."
+msgstr ""
+
+msgid "AccessTokens|Your feed token 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."
+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 ""
+
+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 "AccessibilityReport|Learn more"
+msgstr ""
+
+msgid "AccessibilityReport|Message: %{message}"
+msgstr ""
+
+msgid "AccessibilityReport|New"
+msgstr ""
+
+msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
+msgstr ""
+
+msgid "Accessible by any user who is logged in."
+msgstr ""
+
+msgid "Accessible by anyone, regardless of authentication."
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account ID"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Account:"
+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|In order to use free CI/CD minutes on shared runners, you'll need to validate your account using one of our verification options. If you prefer not to, 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 CI/CD minutes"
+msgstr ""
+
+msgid "AccountValidation|Validate your account"
+msgstr ""
+
+msgid "AccountValidation|Verification is required to discourage and reduce the abuse on GitLab infrastructure. If you verify with a credit or debit card, %{strong_start}GitLab will not charge your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
+msgstr ""
+
+msgid "Acknowledge"
+msgstr ""
+
+msgid "Action"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activated on"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{accessTokenTypePlural} (%{totalAccessTokens})"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Active chat names (%{count})"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Activity|An error occurred while retrieving activity. Reload the page to try again."
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add LICENSE"
+msgstr ""
+
+msgid "Add License"
+msgstr ""
+
+msgid "Add New Site"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add Zoom meeting"
+msgstr ""
+
+msgid "Add a %{type}"
+msgstr ""
+
+msgid "Add a GCP region"
+msgstr ""
+
+msgid "Add a GPG key"
+msgstr ""
+
+msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
+msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
+msgstr ""
+
+msgid "Add a bullet list"
+msgstr ""
+
+msgid "Add a checklist"
+msgstr ""
+
+msgid "Add a collapsible section"
+msgstr ""
+
+msgid "Add a comment to this line"
+msgstr ""
+
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
+msgid "Add a confidential internal note to this %{noteableDisplayName}."
+msgstr ""
+
+msgid "Add a custom message with details about the instance's shared runners. The message is visible when you view runners for projects and groups. Markdown is supported."
+msgstr ""
+
+msgid "Add a general comment to this %{noteableDisplayName}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a new issue"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
+msgid "Add a related epic"
+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 timeline event to incident"
+msgstr ""
+
+msgid "Add a title..."
+msgstr ""
+
+msgid "Add a to do"
+msgstr ""
+
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
+msgid "Add an existing issue"
+msgstr ""
+
+msgid "Add an impersonation token"
+msgstr ""
+
+msgid "Add another link"
+msgstr ""
+
+msgid "Add approval rule"
+msgstr ""
+
+msgid "Add approvers"
+msgstr ""
+
+msgid "Add broadcast message"
+msgstr ""
+
+msgid "Add child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add comment to incident timeline"
+msgstr ""
+
+msgid "Add comment..."
+msgstr ""
+
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+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 ""
+
+msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
+msgid "Add email participant(s)"
+msgstr ""
+
+msgid "Add environment"
+msgstr ""
+
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
+msgid "Add existing issue"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add internal note"
+msgstr ""
+
+msgid "Add key"
+msgstr ""
+
+msgid "Add label(s)"
+msgstr ""
+
+msgid "Add labels"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add list"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add or remove a user."
+msgstr ""
+
+msgid "Add or remove previously merged commits"
+msgstr ""
+
+msgid "Add or subtract spent time"
+msgstr ""
+
+msgid "Add people"
+msgstr ""
+
+msgid "Add previously merged commits"
+msgstr ""
+
+msgid "Add project"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add request manually"
+msgstr ""
+
+msgid "Add suggestion to batch"
+msgstr ""
+
+msgid "Add system hook"
+msgstr ""
+
+msgid "Add text to the sign-in page. Markdown enabled."
+msgstr ""
+
+msgid "Add to board"
+msgstr ""
+
+msgid "Add to epic"
+msgstr ""
+
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add to tree"
+msgstr ""
+
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
+msgid "Add trigger"
+msgstr ""
+
+msgid "Add variable"
+msgstr ""
+
+msgid "Add vulnerability finding"
+msgstr ""
+
+msgid "Add webhook"
+msgstr ""
+
+msgid "Add your team members and others to GitLab."
+msgstr ""
+
+msgid "Add/remove"
+msgstr ""
+
+msgid "AddContextCommits|Add previously merged commits"
+msgstr ""
+
+msgid "AddContextCommits|Add/remove"
+msgstr ""
+
+msgid "AddMember|Invite email is invalid"
+msgstr ""
+
+msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
+msgstr ""
+
+msgid "AddMember|Invites cannot be blank"
+msgstr ""
+
+msgid "AddMember|No invite source provided."
+msgstr ""
+
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
+msgid "Added"
+msgstr ""
+
+msgid "Added %{epic_ref} as a child epic."
+msgstr ""
+
+msgid "Added %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Added a to do."
+msgstr ""
+
+msgid "Added an issue to an epic."
+msgstr ""
+
+msgid "Added for this merge request"
+msgstr ""
+
+msgid "Added in this version"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional minutes"
+msgstr ""
+
+msgid "Additional minutes:"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Additional text for the sign-in and Help page."
+msgstr ""
+
+msgid "Additional text to show on the Help page"
+msgstr ""
+
+msgid "Additional text to show on the sign-in page"
+msgstr ""
+
+msgid "Address"
+msgstr ""
+
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds %{labels} %{label_text}."
+msgstr ""
+
+msgid "Adds a Zoom meeting."
+msgstr ""
+
+msgid "Adds a timeline event to incident."
+msgstr ""
+
+msgid "Adds a to do."
+msgstr ""
+
+msgid "Adds an issue to an epic."
+msgstr ""
+
+msgid "Adds email participant(s)."
+msgstr ""
+
+msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
+msgstr ""
+
+msgid "Adjust how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "Admin"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Mode"
+msgstr ""
+
+msgid "Admin Note"
+msgstr ""
+
+msgid "Admin Notifications"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin Section"
+msgstr ""
+
+msgid "Admin mode already enabled"
+msgstr ""
+
+msgid "Admin mode disabled"
+msgstr ""
+
+msgid "Admin mode enabled"
+msgstr ""
+
+msgid "Admin navigation"
+msgstr ""
+
+msgid "Admin notes"
+msgstr ""
+
+msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
+msgstr ""
+
+msgid "AdminArea|Active users"
+msgstr ""
+
+msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
+msgstr ""
+
+msgid "AdminArea|Billable users"
+msgstr ""
+
+msgid "AdminArea|Blocked users"
+msgstr ""
+
+msgid "AdminArea|Bots"
+msgstr ""
+
+msgid "AdminArea|Components"
+msgstr ""
+
+msgid "AdminArea|Developer"
+msgstr ""
+
+msgid "AdminArea|Features"
+msgstr ""
+
+msgid "AdminArea|Get security updates from GitLab and stay up to date"
+msgstr ""
+
+msgid "AdminArea|Groups"
+msgstr ""
+
+msgid "AdminArea|Guest"
+msgstr ""
+
+msgid "AdminArea|Included Free in license"
+msgstr ""
+
+msgid "AdminArea|Instance OAuth applications"
+msgstr ""
+
+msgid "AdminArea|Latest groups"
+msgstr ""
+
+msgid "AdminArea|Latest projects"
+msgstr ""
+
+msgid "AdminArea|Latest users"
+msgstr ""
+
+msgid "AdminArea|Maintainer"
+msgstr ""
+
+msgid "AdminArea|Manage applications for your instance that can use GitLab as an %{docs_link_start}OAuth provider%{docs_link_end}."
+msgstr ""
+
+msgid "AdminArea|Minimal access"
+msgstr ""
+
+msgid "AdminArea|New group"
+msgstr ""
+
+msgid "AdminArea|New project"
+msgstr ""
+
+msgid "AdminArea|New user"
+msgstr ""
+
+msgid "AdminArea|No applications found"
+msgstr ""
+
+msgid "AdminArea|Owner"
+msgstr ""
+
+msgid "AdminArea|Projects"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+msgstr ""
+
+msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
+msgstr ""
+
+msgid "AdminArea|Sign up for the GitLab newsletter"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|Total users"
+msgstr ""
+
+msgid "AdminArea|Users"
+msgstr ""
+
+msgid "AdminArea|Users statistics"
+msgstr ""
+
+msgid "AdminArea|Users with highest role"
+msgstr ""
+
+msgid "AdminArea|Users without a Group and Project"
+msgstr ""
+
+msgid "AdminArea|View latest groups"
+msgstr ""
+
+msgid "AdminArea|View latest projects"
+msgstr ""
+
+msgid "AdminArea|View latest users"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminDashboard|Error loading the statistics. Please try again"
+msgstr ""
+
+msgid "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 ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminSettings|%{strongStart}WARNING:%{strongEnd} Environment variable %{environment_variable} does not exist or is not pointing to a valid directory. %{icon_link}"
+msgstr ""
+
+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 ""
+
+msgid "AdminSettings|Affects all new and existing groups."
+msgstr ""
+
+msgid "AdminSettings|All new projects can use the instance's shared runners by default."
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|CI/CD limits"
+msgstr ""
+
+msgid "AdminSettings|Configure Let's Encrypt"
+msgstr ""
+
+msgid "AdminSettings|Configure limits on the number of repositories users can download in a given time."
+msgstr ""
+
+msgid "AdminSettings|Configure when inactive projects should be automatically deleted. %{linkStart}What are inactive projects?%{linkEnd}"
+msgstr ""
+
+msgid "AdminSettings|Delete inactive projects"
+msgstr ""
+
+msgid "AdminSettings|Delete inactive projects that exceed"
+msgstr ""
+
+msgid "AdminSettings|Delete project after"
+msgstr ""
+
+msgid "AdminSettings|Disable Elasticsearch until indexing completes."
+msgstr ""
+
+msgid "AdminSettings|Disable feed token"
+msgstr ""
+
+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 ""
+
+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|Elasticsearch indexing"
+msgstr ""
+
+msgid "AdminSettings|Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|Enable Registration Features"
+msgstr ""
+
+msgid "AdminSettings|Enable Service Ping"
+msgstr ""
+
+msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "AdminSettings|Enable kuromoji custom analyzer: Search"
+msgstr ""
+
+msgid "AdminSettings|Enable pipeline suggestion banner"
+msgstr ""
+
+msgid "AdminSettings|Enable shared runners for new projects"
+msgstr ""
+
+msgid "AdminSettings|Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "AdminSettings|Enable smartcn custom analyzer: Search"
+msgstr ""
+
+msgid "AdminSettings|Enabled"
+msgstr ""
+
+msgid "AdminSettings|Enforce invitation flow for groups and projects"
+msgstr ""
+
+msgid "AdminSettings|Feed token"
+msgstr ""
+
+msgid "AdminSettings|Git abuse rate limit"
+msgstr ""
+
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
+msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
+msgstr ""
+
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
+msgstr ""
+
+msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
+msgstr ""
+
+msgid "AdminSettings|Import sources"
+msgstr ""
+
+msgid "AdminSettings|Inactive project deletion"
+msgstr ""
+
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
+msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
+msgstr ""
+
+msgid "AdminSettings|Let's Encrypt email"
+msgstr ""
+
+msgid "AdminSettings|Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
+msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
+msgstr ""
+
+msgid "AdminSettings|Maximum number of DAG dependencies that a job can have"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of active pipelines per project"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of jobs in a single pipeline"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of pipeline schedules"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of pipeline subscriptions to and from a project"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of runners registered per group"
+msgstr ""
+
+msgid "AdminSettings|Maximum number of runners registered per project"
+msgstr ""
+
+msgid "AdminSettings|Minimum size must be at least 0."
+msgstr ""
+
+msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
+msgstr ""
+
+msgid "AdminSettings|No required pipeline"
+msgstr ""
+
+msgid "AdminSettings|Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
+msgid "AdminSettings|Pause Elasticsearch indexing"
+msgstr ""
+
+msgid "AdminSettings|Preview payload"
+msgstr ""
+
+msgid "AdminSettings|Project export"
+msgstr ""
+
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
+msgid "AdminSettings|Protect CI/CD variables by default"
+msgstr ""
+
+msgid "AdminSettings|Registration Features include:"
+msgstr ""
+
+msgid "AdminSettings|Require users to prove ownership of custom domains"
+msgstr ""
+
+msgid "AdminSettings|Required pipeline configuration"
+msgstr ""
+
+msgid "AdminSettings|Requires %{linkStart}email notifications%{linkEnd}"
+msgstr ""
+
+msgid "AdminSettings|Restrict group access by IP address. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|Save %{name} limits"
+msgstr ""
+
+msgid "AdminSettings|Search with Elasticsearch enabled"
+msgstr ""
+
+msgid "AdminSettings|Select a CI/CD template"
+msgstr ""
+
+msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
+msgstr ""
+
+msgid "AdminSettings|Select to disable public access for Pages sites, which requires users to sign in for access to the Pages sites in your instance. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Send email to maintainers after project is inactive for"
+msgstr ""
+
+msgid "AdminSettings|Send warning email"
+msgstr ""
+
+msgid "AdminSettings|Service ping is disabled in your configuration file, and cannot be enabled through this form. For more information, see the documentation on %{link_start}deactivating service ping%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
+msgstr ""
+
+msgid "AdminSettings|Set a CI/CD template as the required pipeline configuration for all projects in the instance. Project CI/CD configuration merges into the required pipeline configuration when the pipeline runs. %{link_start}What is a required pipeline configuration?%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Set limit to 0 to disable it."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
+msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
+msgstr ""
+
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Setting must be greater than 0."
+msgstr ""
+
+msgid "AdminSettings|Size and domain settings for Pages static sites."
+msgstr ""
+
+msgid "AdminSettings|The default domain to use for Auto Review Apps and Auto Deploy stages in all projects."
+msgstr ""
+
+msgid "AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
+msgstr ""
+
+msgid "AdminSettings|The projects in this group can be selected as templates for new projects created on the instance. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
+msgid "AdminSettings|The template for the required pipeline configuration can be one of the GitLab-provided templates, or a custom template added to an instance template repository. %{link_start}How do I create an instance template repository?%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
+msgid "AdminSettings|To enable Registration Features, first enable Service Ping."
+msgstr ""
+
+msgid "AdminSettings|To help improve GitLab and its user experience, GitLab periodically collects usage information. %{link_start}What information is shared with GitLab Inc.?%{link_end}"
+msgstr ""
+
+msgid "AdminSettings|Total number of jobs in currently active pipelines"
+msgstr ""
+
+msgid "AdminSettings|Use AWS OpenSearch Service with IAM credentials"
+msgstr ""
+
+msgid "AdminSettings|Users and groups must accept the invitation before they're added to a group or project."
+msgstr ""
+
+msgid "AdminSettings|When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
+msgstr ""
+
+msgid "AdminSettings|When to delete inactive projects"
+msgstr ""
+
+msgid "AdminSettings|You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
+msgstr ""
+
+msgid "AdminSettings|You can't delete projects before the warning email is sent."
+msgstr ""
+
+msgid "AdminStatistics|Active Users"
+msgstr ""
+
+msgid "AdminStatistics|Forks"
+msgstr ""
+
+msgid "AdminStatistics|Issues"
+msgstr ""
+
+msgid "AdminStatistics|Merge requests"
+msgstr ""
+
+msgid "AdminStatistics|Milestones"
+msgstr ""
+
+msgid "AdminStatistics|Notes"
+msgstr ""
+
+msgid "AdminStatistics|SSH Keys"
+msgstr ""
+
+msgid "AdminStatistics|Snippets"
+msgstr ""
+
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Locked)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user. Validated users can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|Access"
+msgstr ""
+
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access level"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
+msgid "AdminUsers|Activate"
+msgstr ""
+
+msgid "AdminUsers|Activate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Adjust the user cap setting on your instance"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Administrator"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Avatar"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Block user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Blocking user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Bot"
+msgstr ""
+
+msgid "AdminUsers|Can create group"
+msgstr ""
+
+msgid "AdminUsers|Cannot sign in or access instance information"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
+msgid "AdminUsers|Confirm user"
+msgstr ""
+
+msgid "AdminUsers|Confirm user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "AdminUsers|Deactivate"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Deactivated"
+msgstr ""
+
+msgid "AdminUsers|Deactivating a user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
+msgstr ""
+
+msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
+msgstr ""
+
+msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
+msgstr ""
+
+msgid "AdminUsers|Important information about usage on your GitLab instance"
+msgstr ""
+
+msgid "AdminUsers|Is using seat"
+msgstr ""
+
+msgid "AdminUsers|Issues authored by this user are hidden from other users."
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|LDAP Blocked"
+msgstr ""
+
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
+msgid "AdminUsers|Limits"
+msgstr ""
+
+msgid "AdminUsers|Linkedin"
+msgstr ""
+
+msgid "AdminUsers|Locked"
+msgstr ""
+
+msgid "AdminUsers|Log in"
+msgstr ""
+
+msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Owned groups will be left"
+msgstr ""
+
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
+msgid "AdminUsers|Personal projects will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects, group and user history will be left intact"
+msgstr ""
+
+msgid "AdminUsers|Quota of CI/CD minutes"
+msgstr ""
+
+msgid "AdminUsers|Reactivating a user will:"
+msgstr ""
+
+msgid "AdminUsers|Regular"
+msgstr ""
+
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
+
+msgid "AdminUsers|Reject"
+msgstr ""
+
+msgid "AdminUsers|Reject user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Rejected users:"
+msgstr ""
+
+msgid "AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in."
+msgstr ""
+
+msgid "AdminUsers|Restore user access to the account, including web, Git and API."
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Skype"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|The maximum number of CI/CD minutes on shared runners that a group can use each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
+msgstr ""
+
+msgid "AdminUsers|The user can't access git repositories."
+msgstr ""
+
+msgid "AdminUsers|The user can't log in."
+msgstr ""
+
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
+msgid "AdminUsers|The user will be logged out"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access the API"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to use slash commands"
+msgstr ""
+
+msgid "AdminUsers|The user will not receive any notifications"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
+msgid "AdminUsers|Unban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unblock"
+msgstr ""
+
+msgid "AdminUsers|Unblock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unlock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|User administration"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to login"
+msgstr ""
+
+msgid "AdminUsers|Users"
+msgstr ""
+
+msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
+msgstr ""
+
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
+msgid "AdminUsers|View pending member requests"
+msgstr ""
+
+msgid "AdminUsers|Website URL"
+msgstr ""
+
+msgid "AdminUsers|What can I do?"
+msgstr ""
+
+msgid "AdminUsers|What does this mean?"
+msgstr ""
+
+msgid "AdminUsers|When banned:"
+msgstr ""
+
+msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
+msgstr ""
+
+msgid "AdminUsers|Will be deleted"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You can always block their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always deactivate their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You can ban their account in the future if necessary."
+msgstr ""
+
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
+msgid "AdminUsers|You cannot remove your own administrator access."
+msgstr ""
+
+msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
+msgstr ""
+
+msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
+msgstr ""
+
+msgid "AdminUsers|approve them"
+msgstr ""
+
+msgid "AdminUsers|contact our support team"
+msgstr ""
+
+msgid "AdminUsers|docs"
+msgstr ""
+
+msgid "AdminUsers|user cap"
+msgstr ""
+
+msgid "Administration"
+msgstr ""
+
+msgid "Administrators"
+msgstr ""
+
+msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
+msgstr ""
+
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Learn more about quarterly reconciliation"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
+msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
+msgstr ""
+
+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 ""
+
+msgid "Admin|The number of max users in your instance exceeds the number of users in your license. 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 ""
+
+msgid "Admin|View pending user approvals"
+msgstr ""
+
+msgid "Admin|Your instance has reached its user cap"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced export options"
+msgstr ""
+
+msgid "AdvancedSearch|Elasticsearch version not compatible"
+msgstr ""
+
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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 it expires, you can't use merge approvals, code quality, or many other features."
+msgstr ""
+
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
+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 ""
+
+msgid "Akismet"
+msgstr ""
+
+msgid "Akismet API Key"
+msgstr ""
+
+msgid "Akismet helps prevent the creation of spam issues in public projects."
+msgstr ""
+
+msgid "Alert"
+msgstr ""
+
+msgid "AlertManagement|Acknowledged"
+msgstr ""
+
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
+msgid "AlertManagement|Alert"
+msgstr ""
+
+msgid "AlertManagement|Alert assignee(s): %{assignees}"
+msgstr ""
+
+msgid "AlertManagement|Alert detail"
+msgstr ""
+
+msgid "AlertManagement|Alert details"
+msgstr ""
+
+msgid "AlertManagement|Alert status: %{status}"
+msgstr ""
+
+msgid "AlertManagement|Alerts"
+msgstr ""
+
+msgid "AlertManagement|All alerts"
+msgstr ""
+
+msgid "AlertManagement|Assign status"
+msgstr ""
+
+msgid "AlertManagement|Assignees"
+msgstr ""
+
+msgid "AlertManagement|Authorize external service"
+msgstr ""
+
+msgid "AlertManagement|Create incident"
+msgstr ""
+
+msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
+msgstr ""
+
+msgid "AlertManagement|Edit"
+msgstr ""
+
+msgid "AlertManagement|Environment"
+msgstr ""
+
+msgid "AlertManagement|Events"
+msgstr ""
+
+msgid "AlertManagement|Incident"
+msgstr ""
+
+msgid "AlertManagement|Key"
+msgstr ""
+
+msgid "AlertManagement|Metrics"
+msgstr ""
+
+msgid "AlertManagement|Metrics weren't available in the alerts payload."
+msgstr ""
+
+msgid "AlertManagement|More information"
+msgstr ""
+
+msgid "AlertManagement|No alert data to display."
+msgstr ""
+
+msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "AlertManagement|No alerts to display."
+msgstr ""
+
+msgid "AlertManagement|None"
+msgstr ""
+
+msgid "AlertManagement|Open"
+msgstr ""
+
+msgid "AlertManagement|Please try again."
+msgstr ""
+
+msgid "AlertManagement|Reported %{when}"
+msgstr ""
+
+msgid "AlertManagement|Reported %{when} by %{tool}"
+msgstr ""
+
+msgid "AlertManagement|Resolved"
+msgstr ""
+
+msgid "AlertManagement|Runbook"
+msgstr ""
+
+msgid "AlertManagement|Service"
+msgstr ""
+
+msgid "AlertManagement|Severity"
+msgstr ""
+
+msgid "AlertManagement|Start time"
+msgstr ""
+
+msgid "AlertManagement|Status"
+msgstr ""
+
+msgid "AlertManagement|Surface alerts in GitLab"
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the status of the alert."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the to-do item of the alert."
+msgstr ""
+
+msgid "AlertManagement|This assignee cannot be assigned to this alert."
+msgstr ""
+
+msgid "AlertManagement|Tool"
+msgstr ""
+
+msgid "AlertManagement|Triggered"
+msgstr ""
+
+msgid "AlertManagement|Value"
+msgstr ""
+
+msgid "AlertManagement|View incident"
+msgstr ""
+
+msgid "AlertMappingBuilder|Define fallback"
+msgstr ""
+
+msgid "AlertMappingBuilder|GitLab alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Make selection"
+msgstr ""
+
+msgid "AlertMappingBuilder|Payload alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Select key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
+msgstr ""
+
+msgid "AlertSettings|A 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 ""
+
+msgid "AlertSettings|Alert settings"
+msgstr ""
+
+msgid "AlertSettings|Authorization key"
+msgstr ""
+
+msgid "AlertSettings|Configure details"
+msgstr ""
+
+msgid "AlertSettings|Current integrations"
+msgstr ""
+
+msgid "AlertSettings|Customize alert payload mapping (optional)"
+msgstr ""
+
+msgid "AlertSettings|Delete integration"
+msgstr ""
+
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
+msgid "AlertSettings|Edit payload"
+msgstr ""
+
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
+msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
+msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
+msgstr ""
+
+msgid "AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
+msgstr ""
+
+msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
+msgstr ""
+
+msgid "AlertSettings|Integration successfully saved"
+msgstr ""
+
+msgid "AlertSettings|Name integration"
+msgstr ""
+
+msgid "AlertSettings|Parse payload fields"
+msgstr ""
+
+msgid "AlertSettings|Proceed with editing"
+msgstr ""
+
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
+msgid "AlertSettings|Prometheus API base URL"
+msgstr ""
+
+msgid "AlertSettings|Reset Key"
+msgstr ""
+
+msgid "AlertSettings|Reset the mapping"
+msgstr ""
+
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgstr ""
+
+msgid "AlertSettings|Save & create test alert"
+msgstr ""
+
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Save integration & send"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
+msgid "AlertSettings|Send test alert"
+msgstr ""
+
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
+msgid "AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the \"Parse payload fields\" button to continue."
+msgstr ""
+
+msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
+msgstr ""
+
+msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|View URL and authorization key"
+msgstr ""
+
+msgid "AlertSettings|View credentials"
+msgstr ""
+
+msgid "AlertSettings|Webhook URL"
+msgstr ""
+
+msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
+msgstr ""
+
+msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration payload is invalid."
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet."
+msgstr ""
+
+msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be added. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is deleted."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
+msgstr ""
+
+msgid "Algorithm"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All %{replicableType} are being scheduled for %{action}"
+msgstr ""
+
+msgid "All (default)"
+msgstr ""
+
+msgid "All GitLab"
+msgstr ""
+
+msgid "All Members"
+msgstr ""
+
+msgid "All branches"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All eligible users"
+msgstr ""
+
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
+msgid "All environments"
+msgstr ""
+
+msgid "All groups and projects"
+msgstr ""
+
+msgid "All issues"
+msgstr ""
+
+msgid "All issues for this milestone are closed."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All merge conflicts were resolved. The merge request can now be merged."
+msgstr ""
+
+msgid "All merge request dependencies have been merged"
+msgstr ""
+
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
+
+msgid "All project members"
+msgstr ""
+
+msgid "All projects"
+msgstr ""
+
+msgid "All projects selected"
+msgstr ""
+
+msgid "All protected branches"
+msgstr ""
+
+msgid "All threads resolved!"
+msgstr ""
+
+msgid "All users in this group must set up two-factor authentication"
+msgstr ""
+
+msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
+msgstr ""
+
+msgid "All users must have a name."
+msgstr ""
+
+msgid "All users with matching cards"
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow access to members of the following group"
+msgstr ""
+
+msgid "Allow access to the following IP addresses"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch. %{link_start}About this feature.%{link_end}"
+msgstr ""
+
+msgid "Allow group owners to manage LDAP-related settings"
+msgstr ""
+
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
+
+msgid "Allow only the selected protocols to be used for Git access."
+msgstr ""
+
+msgid "Allow owners to manage default branch protection per group."
+msgstr ""
+
+msgid "Allow owners to manually add users outside of LDAP"
+msgstr ""
+
+msgid "Allow password authentication for Git over HTTP(S)"
+msgstr ""
+
+msgid "Allow password authentication for the web interface"
+msgstr ""
+
+msgid "Allow project maintainers to configure repository mirroring"
+msgstr ""
+
+msgid "Allow projects and subgroups to override the group setting"
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
+
+msgid "Allow this key to push to this repository"
+msgstr ""
+
+msgid "Allow use of licensed EE features"
+msgstr ""
+
+msgid "Allow users to create top-level groups"
+msgstr ""
+
+msgid "Allow users to dismiss the broadcast message"
+msgstr ""
+
+msgid "Allow users to register any application to use GitLab as an OAuth provider"
+msgstr ""
+
+msgid "Allowed"
+msgstr ""
+
+msgid "Allowed email domain restriction only permitted for top-level groups"
+msgstr ""
+
+msgid "Allowed to create:"
+msgstr ""
+
+msgid "Allowed to delete projects"
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
+msgid "Allows projects to track errors using an Opstrace integration."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Almost there"
+msgstr ""
+
+msgid "Almost there..."
+msgstr ""
+
+msgid "Already blocked"
+msgstr ""
+
+msgid "Already have login and password?"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
+msgid "Also unassign this user from related issues and merge requests"
+msgstr ""
+
+msgid "Alternate support URL for Help page and Help dropdown."
+msgstr ""
+
+msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
+msgstr ""
+
+msgid "Amazon EKS"
+msgstr ""
+
+msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
+msgstr ""
+
+msgid "Amazon Web Services Logo"
+msgstr ""
+
+msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr ""
+
+msgid "An Administrator has set the maximum expiration date to %{maxDate}. %{helpLinkStart}Learn more%{helpLinkEnd}."
+msgstr ""
+
+msgid "An Enterprise User GitLab account has been created for you by your organization:"
+msgstr ""
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An alert has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
+msgstr ""
+
+msgid "An email will be sent with the report attached after it is generated."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
+msgid "An error occurred adding a draft to the thread."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred fetching the approval rules."
+msgstr ""
+
+msgid "An error occurred fetching the approvers for the new rule."
+msgstr ""
+
+msgid "An error occurred fetching the dropdown data."
+msgstr ""
+
+msgid "An error occurred fetching the project authors."
+msgstr ""
+
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when loading the user verification challenge. Refresh to try again."
+msgstr ""
+
+msgid "An error occurred when updating the title"
+msgstr ""
+
+msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while adding approvers"
+msgstr ""
+
+msgid "An error occurred while adding formatted title for epic"
+msgstr ""
+
+msgid "An error occurred while approving, please try again."
+msgstr ""
+
+msgid "An error occurred while authorizing your role"
+msgstr ""
+
+msgid "An error occurred while checking group path. Please refresh and try again."
+msgstr ""
+
+msgid "An error occurred while decoding the file."
+msgstr ""
+
+msgid "An error occurred while deleting the approvers group"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while deleting the pipeline."
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while disabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while drawing job relationship links."
+msgstr ""
+
+msgid "An error occurred while enabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while fetching Markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching ancestors"
+msgstr ""
+
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching codequality mr diff reports."
+msgstr ""
+
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching coverage reports."
+msgstr ""
+
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching exposed artifacts."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching issues."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
+msgid "An error occurred while fetching participants"
+msgstr ""
+
+msgid "An error occurred while fetching participants."
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
+msgid "An error occurred while fetching reference"
+msgstr ""
+
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
+msgid "An error occurred while fetching tags. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching terraform reports."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job logs."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
+msgid "An error occurred while getting files for - %{branchId}"
+msgstr ""
+
+msgid "An error occurred while getting issue counts"
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading a section of this page."
+msgstr ""
+
+msgid "An error occurred while loading all the files."
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading code owners."
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading designs. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading group members."
+msgstr ""
+
+msgid "An error occurred while loading issues"
+msgstr ""
+
+msgid "An error occurred while loading merge requests."
+msgstr ""
+
+msgid "An error occurred while loading projects."
+msgstr ""
+
+msgid "An error occurred while loading the Jobs tab."
+msgstr ""
+
+msgid "An error occurred while loading the Needs tab."
+msgstr ""
+
+msgid "An error occurred while loading the Test Reports tab."
+msgstr ""
+
+msgid "An error occurred while loading the blob controls."
+msgstr ""
+
+msgid "An error occurred while loading the data. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the file content."
+msgstr ""
+
+msgid "An error occurred while loading the file."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again later."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred while loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred while loading the merge request."
+msgstr ""
+
+msgid "An error occurred while loading the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the pipeline."
+msgstr ""
+
+msgid "An error occurred while loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
+
+msgid "An error occurred while parsing the file."
+msgstr ""
+
+msgid "An error occurred while pasting text in the editor. Please try again."
+msgstr ""
+
+msgid "An error occurred while performing this action."
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while rendering the editor"
+msgstr ""
+
+msgid "An error occurred while reordering issues."
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
+msgid "An error occurred while retrieving your settings. Reload the page to try again."
+msgstr ""
+
+msgid "An error occurred while saving changes: %{error}"
+msgstr ""
+
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "An error occurred while saving your settings. Try saving them again."
+msgstr ""
+
+msgid "An error occurred while triggering the job."
+msgstr ""
+
+msgid "An error occurred while trying to follow this user, please try again."
+msgstr ""
+
+msgid "An error occurred while trying to generate the report. Please try again later."
+msgstr ""
+
+msgid "An error occurred while trying to render the content editor. Please try again."
+msgstr ""
+
+msgid "An error occurred while trying to run a new pipeline for this merge request."
+msgstr ""
+
+msgid "An error occurred while trying to unfollow this user, please try again."
+msgstr ""
+
+msgid "An error occurred while updating approvers"
+msgstr ""
+
+msgid "An error occurred while updating assignees."
+msgstr ""
+
+msgid "An error occurred while updating configuration."
+msgstr ""
+
+msgid "An error occurred while updating labels."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
+msgid "An error occurred while updating the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while uploading the file. Please try again."
+msgstr ""
+
+msgid "An error occurred while validating group path"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An example project for managing Kubernetes clusters integrated with GitLab"
+msgstr ""
+
+msgid "An example project that shows off the best practices for setting up GitLab for your own organization, including sample issues, merge requests, and milestones"
+msgstr ""
+
+msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr ""
+
+msgid "An 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 ""
+
+msgid "An unauthenticated user"
+msgstr ""
+
+msgid "An unexpected error occurred"
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while loading the code quality diff."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "An unknown error occurred while loading this graph."
+msgstr ""
+
+msgid "An unknown error occurred."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "AnalyticsDashboards|Dashboards"
+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 ""
+
+msgid "Analyze your source code for known vulnerabilities."
+msgstr ""
+
+msgid "Analyzing file…"
+msgstr ""
+
+msgid "Ancestors"
+msgstr ""
+
+msgid "And this registration token:"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Another action is currently in progress"
+msgstr ""
+
+msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
+msgstr ""
+
+msgid "Another third-party wiki is already in use. Only one third-party wiki integration can be active at a time"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any %{header}"
+msgstr ""
+
+msgid "Any Author"
+msgstr ""
+
+msgid "Any Milestone"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any label"
+msgstr ""
+
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
+
+msgid "Any milestone"
+msgstr ""
+
+msgid "Any namespace"
+msgstr ""
+
+msgid "Anyone can register for an account."
+msgstr ""
+
+msgid "App ID"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Appearance was successfully created."
+msgstr ""
+
+msgid "Appearance was successfully updated."
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
+msgid "Append the comment with %{tableflip}"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application limits saved successfully"
+msgstr ""
+
+msgid "Application settings saved successfully"
+msgstr ""
+
+msgid "Application settings saved successfully."
+msgstr ""
+
+msgid "Application settings update failed"
+msgstr ""
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
+msgid "Application was successfully destroyed."
+msgstr ""
+
+msgid "Application was successfully updated."
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "ApplicationSettings|A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
+msgstr ""
+
+msgid "ApplicationSettings|Add a link to Grafana"
+msgstr ""
+
+msgid "ApplicationSettings|After sign-up text"
+msgstr ""
+
+msgid "ApplicationSettings|After the instance reaches the user cap, any user who is added or requests access must be approved by an administrator. Leave blank for unlimited."
+msgstr ""
+
+msgid "ApplicationSettings|Allowed domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Any user that visits %{host} and creates an account must be explicitly approved by an administrator before they can sign in. Only effective if sign-ups are enabled."
+msgstr ""
+
+msgid "ApplicationSettings|Any user that visits %{host} can create an account."
+msgstr ""
+
+msgid "ApplicationSettings|Approve %d user"
+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 ""
+
+msgid "ApplicationSettings|Approve users who are pending approval?"
+msgstr ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve %d user who is pending approval."
+msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users who are pending approval."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve all users who are pending approval."
+msgstr ""
+
+msgid "ApplicationSettings|Denied domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|Domain denylist"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable Slack application"
+msgstr ""
+
+msgid "ApplicationSettings|Enable domain denylist for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable email restrictions for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enter denylist manually"
+msgstr ""
+
+msgid "ApplicationSettings|Minimum password length (number of characters)"
+msgstr ""
+
+msgid "ApplicationSettings|Only users with e-mail addresses that match these domain(s) can sign up. Wildcards allowed. Use separate lines for multiple entries. Example: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Require admin approval for new sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Require lowercase letters"
+msgstr ""
+
+msgid "ApplicationSettings|Require numbers"
+msgstr ""
+
+msgid "ApplicationSettings|Require symbols"
+msgstr ""
+
+msgid "ApplicationSettings|Require uppercase letters"
+msgstr ""
+
+msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. %{linkStart}What is the supported syntax?%{linkEnd}"
+msgstr ""
+
+msgid "ApplicationSettings|Save changes"
+msgstr ""
+
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr ""
+
+msgid "ApplicationSettings|Send confirmation email on sign-up"
+msgstr ""
+
+msgid "ApplicationSettings|Sign-up enabled"
+msgstr ""
+
+msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
+msgstr ""
+
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
+msgid "ApplicationSettings|This option is only available on GitLab.com"
+msgstr ""
+
+msgid "ApplicationSettings|Upload denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|User cap"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) cannot sign up. Wildcards allowed. Use separate lines for multiple entries. Example: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) cannot sign up. Wildcards allowed. Use separate lines or commas for multiple entries."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one lowercase letter (a-z)."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one symbol."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one uppercase letter (A-Z)."
+msgstr ""
+
+msgid "ApplicationSettings|domain.com"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply %d suggestion"
+msgid_plural "Apply %d suggestions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to all branches or a specific protected branch."
+msgstr ""
+
+msgid "Applying"
+msgstr ""
+
+msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
+msgstr ""
+
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion..."
+msgstr ""
+
+msgid "Applying suggestions..."
+msgstr ""
+
+msgid "Approval rules"
+msgstr ""
+
+msgid "Approval rules reset to project defaults"
+msgstr ""
+
+msgid "Approval settings"
+msgstr ""
+
+msgid "ApprovalRuleRemove|%d member"
+msgid_plural "ApprovalRuleRemove|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} member%{strongEnd}. Approvals from this member are not revoked."
+msgid_plural "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{strongStart}%{count} members%{strongEnd}. Approvals from these members are not revoked."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%d member"
+msgid_plural "ApprovalRuleSummary|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
+msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRule|A merge request author collaborating with a merge request approver"
+msgstr ""
+
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
+msgid "ApprovalRule|Approval rules"
+msgstr ""
+
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
+msgid "ApprovalRule|Approver Type"
+msgstr ""
+
+msgid "ApprovalRule|Approvers"
+msgstr ""
+
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
+msgid "ApprovalRule|Improve your organization's code review with required approvals."
+msgstr ""
+
+msgid "ApprovalRule|Increase quality and maintain standards."
+msgstr ""
+
+msgid "ApprovalRule|Learn more about merge request approval rules."
+msgstr ""
+
+msgid "ApprovalRule|Name"
+msgstr ""
+
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Reduce your time to merge."
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
+msgid "ApprovalRule|Rule name"
+msgstr ""
+
+msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
+msgstr ""
+
+msgid "ApprovalRule|Target branch"
+msgstr ""
+
+msgid "ApprovalRule|Try for free"
+msgstr ""
+
+msgid "ApprovalSettings|Keep approvals"
+msgstr ""
+
+msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approval by author"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent approvals by users who add commits"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests"
+msgstr ""
+
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
+msgstr ""
+
+msgid "ApprovalSettings|Remove all approvals"
+msgstr ""
+
+msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
+msgstr ""
+
+msgid "ApprovalSettings|Require user password to approve"
+msgstr ""
+
+msgid "ApprovalSettings|There was an error loading merge request approval settings."
+msgstr ""
+
+msgid "ApprovalSettings|There was an error updating merge request approval settings."
+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 in the group settings by an administrator or group owner."
+msgstr ""
+
+msgid "ApprovalSettings|When a commit is added:"
+msgstr ""
+
+msgid "Approvals are optional."
+msgstr ""
+
+msgid "Approvals|Section: %section"
+msgstr ""
+
+msgid "Approve"
+msgstr ""
+
+msgid "Approve a merge request"
+msgstr ""
+
+msgid "Approve merge request"
+msgstr ""
+
+msgid "Approve the current merge request."
+msgstr ""
+
+msgid "Approved"
+msgstr ""
+
+msgid "Approved MRs"
+msgstr ""
+
+msgid "Approved the current merge request."
+msgstr ""
+
+msgid "Approved-By"
+msgstr ""
+
+msgid "Approver"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Architecture not found for OS"
+msgstr ""
+
+msgid "Archive"
+msgstr ""
+
+msgid "Archive jobs"
+msgstr ""
+
+msgid "Archive project"
+msgstr ""
+
+msgid "Archive test case"
+msgstr ""
+
+msgid "Archived"
+msgstr ""
+
+msgid "Archived (%{movedToStart}moved%{movedToEnd})"
+msgstr ""
+
+msgid "Archived in this version"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Archiving the project makes it entirely read-only. It is hidden from the dashboard and doesn't display in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
+msgstr ""
+
+msgid "Are you absolutely sure?"
+msgstr ""
+
+msgid "Are you sure that you want to archive this project?"
+msgstr ""
+
+msgid "Are you sure that you want to destroy %{application}"
+msgstr ""
+
+msgid "Are you sure that you want to unarchive this project?"
+msgstr ""
+
+msgid "Are you sure you want to %{action} %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to approve %{user}?"
+msgstr ""
+
+msgid "Are you sure you want to attempt to merge?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this %{commentType}?"
+msgstr ""
+
+msgid "Are you sure you want to close this blocked issue?"
+msgstr ""
+
+msgid "Are you sure you want to delete %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to delete these artifacts?"
+msgstr ""
+
+msgid "Are you sure you want to delete this %{commentType}?"
+msgstr ""
+
+msgid "Are you sure you want to delete this SSH key?"
+msgstr ""
+
+msgid "Are you sure you want to delete this comment?"
+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 ""
+
+msgid "Are you sure you want to delete this label?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to discard this comment?"
+msgstr ""
+
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to import %d repository?"
+msgid_plural "Are you sure you want to import %d repositories?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to merge immediately?"
+msgstr ""
+
+msgid "Are you sure you want to re-deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to reindex?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{email}?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{topic_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove the license?"
+msgstr ""
+
+msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to remove this list?"
+msgstr ""
+
+msgid "Are you sure you want to remove this nickname?"
+msgstr ""
+
+msgid "Are you sure you want to reset the error tracking access token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the registration token?"
+msgstr ""
+
+msgid "Are you sure you want to retry this migration?"
+msgstr ""
+
+msgid "Are you sure you want to revoke this %{accessTokenType}? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this project access token? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
+
+msgid "Arrange charts"
+msgstr ""
+
+msgid "Artifact"
+msgstr ""
+
+msgid "Artifact could not be deleted."
+msgstr ""
+
+msgid "Artifact was successfully deleted."
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Add commit messages as comments to Asana tasks."
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask again later"
+msgstr ""
+
+msgid "Ask someone with write access to resolve it."
+msgstr ""
+
+msgid "Ask your group owner to set up a group runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assets:"
+msgstr ""
+
+msgid "Assign"
+msgstr ""
+
+msgid "Assign Iteration"
+msgstr ""
+
+msgid "Assign To"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign myself"
+msgstr ""
+
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
+msgid "Assign severity"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assign to commenting user"
+msgstr ""
+
+msgid "Assign to me"
+msgstr ""
+
+msgid "Assigned %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned merge requests"
+msgstr ""
+
+msgid "Assigned projects"
+msgstr ""
+
+msgid "Assigned to %{assigneeName}"
+msgstr ""
+
+msgid "Assigned to %{assignee_name}"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assigned to you"
+msgstr ""
+
+msgid "Assignee"
+msgid_plural "%d Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Assignee has no permissions"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Assignees"
+msgstr ""
+
+msgid "Assigns %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
+msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
+msgstr ""
+
+msgid "At least one field of %{one_of_required_fields} must be present"
+msgstr ""
+
+msgid "At least one of group_id or project_id must be specified"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens is expired. %{generate_new}"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens will expire soon. %{generate_new}"
+msgstr ""
+
+msgid "At risk"
+msgstr ""
+
+msgid "Attach a file or image"
+msgstr ""
+
+msgid "Attaching File - %{progress}"
+msgstr ""
+
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Audit events"
+msgstr ""
+
+msgid "AuditLogs|(removed)"
+msgstr ""
+
+msgid "AuditLogs|Action"
+msgstr ""
+
+msgid "AuditLogs|Author"
+msgstr ""
+
+msgid "AuditLogs|Date"
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please try again."
+msgstr ""
+
+msgid "AuditLogs|Group Events"
+msgstr ""
+
+msgid "AuditLogs|IP Address"
+msgstr ""
+
+msgid "AuditLogs|Log"
+msgstr ""
+
+msgid "AuditLogs|Member Events"
+msgstr ""
+
+msgid "AuditLogs|No matching %{type} found."
+msgstr ""
+
+msgid "AuditLogs|Object"
+msgstr ""
+
+msgid "AuditLogs|Project Events"
+msgstr ""
+
+msgid "AuditLogs|Target"
+msgstr ""
+
+msgid "AuditLogs|This month"
+msgstr ""
+
+msgid "AuditLogs|User Events"
+msgstr ""
+
+msgid "AuditStreams|%d destination"
+msgid_plural "AuditStreams|%d destinations"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "AuditStreams|A header with this name already exists."
+msgstr ""
+
+msgid "AuditStreams|Active"
+msgstr ""
+
+msgid "AuditStreams|Add a custom header"
+msgstr ""
+
+msgid "AuditStreams|Add a custom value"
+msgstr ""
+
+msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party systems."
+msgstr ""
+
+msgid "AuditStreams|Add another custom header"
+msgstr ""
+
+msgid "AuditStreams|Add external stream destination"
+msgstr ""
+
+msgid "AuditStreams|Add header"
+msgstr ""
+
+msgid "AuditStreams|Add streaming destination"
+msgstr ""
+
+msgid "AuditStreams|An error occurred when creating external audit event stream destination. Please try it again."
+msgstr ""
+
+msgid "AuditStreams|An error occurred when deleting external audit event stream destination. Please try it again."
+msgstr ""
+
+msgid "AuditStreams|An error occurred when fetching external audit event streams. Please try it again"
+msgstr ""
+
+msgid "AuditStreams|An error occurred when updating external audit event stream destination. Please try it again."
+msgstr ""
+
+msgid "AuditStreams|Cancel editing"
+msgstr ""
+
+msgid "AuditStreams|Custom HTTP headers (optional)"
+msgstr ""
+
+msgid "AuditStreams|Delete %{link}"
+msgstr ""
+
+msgid "AuditStreams|Destination URL"
+msgstr ""
+
+msgid "AuditStreams|Destinations receive all audit event data"
+msgstr ""
+
+msgid "AuditStreams|Edit %{link}"
+msgstr ""
+
+msgid "AuditStreams|Header"
+msgstr ""
+
+msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
+msgstr ""
+
+msgid "AuditStreams|Remove custom header"
+msgstr ""
+
+msgid "AuditStreams|Save external stream destination"
+msgstr ""
+
+msgid "AuditStreams|Setup streaming for audit events"
+msgstr ""
+
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
+msgid "AuditStreams|Streams"
+msgstr ""
+
+msgid "AuditStreams|This could include sensitive information. Make sure you trust the destination endpoint."
+msgstr ""
+
+msgid "AuditStreams|This is great for keeping everything one place."
+msgstr ""
+
+msgid "AuditStreams|Value"
+msgstr ""
+
+msgid "AuditStreams|Verification token"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authenticate"
+msgstr ""
+
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead. %{link_start}How do I configure authentication using the GitLab database? %{link_end}"
+msgstr ""
+
+msgid "Authenticate with GitHub"
+msgstr ""
+
+msgid "Authenticated API rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated API requests"
+msgstr ""
+
+msgid "Authenticated Git LFS rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated Git LFS request rate limit"
+msgstr ""
+
+msgid "Authenticated Git LFS requests"
+msgstr ""
+
+msgid "Authenticated web rate limit period in seconds"
+msgstr ""
+
+msgid "Authenticated web requests"
+msgstr ""
+
+msgid "Authentication"
+msgstr ""
+
+msgid "Authentication Failure"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication error: enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}"
+msgstr ""
+
+msgid "Authentication failed: %{error_message}"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Authentication method updated"
+msgstr ""
+
+msgid "Authentication via U2F device failed."
+msgstr ""
+
+msgid "Authentication via WebAuthn device failed."
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Author: %{author_name}"
+msgstr ""
+
+msgid "Authored %{timeago}"
+msgstr ""
+
+msgid "Authored %{timeago} by %{author}"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization required"
+msgstr ""
+
+msgid "Authorization token duration (minutes)"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorize %{user} to use your account?"
+msgstr ""
+
+msgid "Authorized %{new_chat_name}"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "AuthorizedApplication|Are you sure you want to revoke this application?"
+msgstr ""
+
+msgid "AuthorizedApplication|Revoke application"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto stop successfully canceled."
+msgstr ""
+
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
+
+msgid "Auto-close referenced issues on default branch"
+msgstr ""
+
+msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Dismiss Auto DevOps box"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
+msgstr ""
+
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
+
+msgid "Autocomplete"
+msgstr ""
+
+msgid "Autocomplete description"
+msgstr ""
+
+msgid "Autocomplete hint"
+msgstr ""
+
+msgid "Autocomplete usage hint"
+msgstr ""
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
+msgid "Automatic event tracking provides a traceable history for audits."
+msgstr ""
+
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available ID"
+msgstr ""
+
+msgid "Available group runners: %{runners}"
+msgstr ""
+
+msgid "Available on-demand"
+msgstr ""
+
+msgid "Available shared runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Awaiting user signup"
+msgstr ""
+
+msgid "Award added"
+msgstr ""
+
+msgid "Award removed"
+msgstr ""
+
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
+msgid "Back"
+msgstr ""
+
+msgid "Back to page %{number}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background Migrations"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "BackgroundMigrations|Background Migrations"
+msgstr ""
+
+msgid "BackgroundMigrations|Background migrations are used to perform data migrations whenever a migration exceeds the time limits in our guidelines. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "BackgroundMigrations|Batch size"
+msgstr ""
+
+msgid "BackgroundMigrations|Database"
+msgstr ""
+
+msgid "BackgroundMigrations|Failed jobs:"
+msgstr ""
+
+msgid "BackgroundMigrations|Finished at"
+msgstr ""
+
+msgid "BackgroundMigrations|Started at"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Badge saved."
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|Name"
+msgstr ""
+
+msgid "Badges|New badge added."
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo"
+msgstr ""
+
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key."
+msgstr ""
+
+msgid "BambooService|Bamboo service root URL."
+msgstr ""
+
+msgid "BambooService|Enter new build key"
+msgstr ""
+
+msgid "BambooService|Leave blank to use your current build key."
+msgstr ""
+
+msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
+msgstr ""
+
+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 ""
+
+msgid "BambooService|The user with API access to the Bamboo server."
+msgstr ""
+
+msgid "Banned"
+msgstr ""
+
+msgid "Banner message"
+msgstr ""
+
+msgid "Based on"
+msgstr ""
+
+msgid "Batch size"
+msgstr ""
+
+msgid "Batched Job|Background Migrations"
+msgstr ""
+
+msgid "Batched Job|Batched Job (Id: %{id})"
+msgstr ""
+
+msgid "BatchedJob|Attempts"
+msgstr ""
+
+msgid "BatchedJob|Batch size"
+msgstr ""
+
+msgid "BatchedJob|Batched Jobs"
+msgstr ""
+
+msgid "BatchedJob|Created At"
+msgstr ""
+
+msgid "BatchedJob|Created at"
+msgstr ""
+
+msgid "BatchedJob|Exception Class"
+msgstr ""
+
+msgid "BatchedJob|Exception Message"
+msgstr ""
+
+msgid "BatchedJob|Exception class"
+msgstr ""
+
+msgid "BatchedJob|Exception message"
+msgstr ""
+
+msgid "BatchedJob|Finished at"
+msgstr ""
+
+msgid "BatchedJob|Max Value"
+msgstr ""
+
+msgid "BatchedJob|Max value"
+msgstr ""
+
+msgid "BatchedJob|Min Value"
+msgstr ""
+
+msgid "BatchedJob|Min value"
+msgstr ""
+
+msgid "BatchedJob|Next Status"
+msgstr ""
+
+msgid "BatchedJob|Next status"
+msgstr ""
+
+msgid "BatchedJob|Pause ms"
+msgstr ""
+
+msgid "BatchedJob|Pause time (ms)"
+msgstr ""
+
+msgid "BatchedJob|Previous Status"
+msgstr ""
+
+msgid "BatchedJob|Previous status"
+msgstr ""
+
+msgid "BatchedJob|Started at"
+msgstr ""
+
+msgid "BatchedJob|Transition logs:"
+msgstr ""
+
+msgid "Be careful. Changing the project's namespace can have unintended side effects."
+msgstr ""
+
+msgid "Be careful. Renaming a project's repository can have unintended side effects."
+msgstr ""
+
+msgid "Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}"
+msgstr ""
+
+msgid "Before inserting code, be sure to read the comment that separated each code group."
+msgstr ""
+
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are the fingerprints for the current instance SSH host keys."
+msgstr ""
+
+msgid "Below are the settings for %{link_to_gitlab_pages}."
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Beta"
+msgstr ""
+
+msgid "Bi-weekly code coverage"
+msgstr ""
+
+msgid "Billable Users"
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}"
+msgstr ""
+
+msgid "BillingPlans|10,000 CI/CD minutes per month"
+msgstr ""
+
+msgid "BillingPlans|10GB transfer per month"
+msgstr ""
+
+msgid "BillingPlans|400 CI/CD minutes per month"
+msgstr ""
+
+msgid "BillingPlans|5 users per namespace"
+msgstr ""
+
+msgid "BillingPlans|50,000 CI/CD minutes per month"
+msgstr ""
+
+msgid "BillingPlans|5GB storage"
+msgstr ""
+
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
+
+msgid "BillingPlans|Advanced CI/CD"
+msgstr ""
+
+msgid "BillingPlans|All plans have unlimited (private) repositories."
+msgstr ""
+
+msgid "BillingPlans|All the features from Free"
+msgstr ""
+
+msgid "BillingPlans|All the features from Premium"
+msgstr ""
+
+msgid "BillingPlans|Billed annually at %{price_per_year} USD"
+msgstr ""
+
+msgid "BillingPlans|Check out all groups"
+msgstr ""
+
+msgid "BillingPlans|Compliance"
+msgstr ""
+
+msgid "BillingPlans|Congratulations, your free trial is activated."
+msgstr ""
+
+msgid "BillingPlans|End of availability for the Bronze Plan"
+msgstr ""
+
+msgid "BillingPlans|Enhance team productivity and collaboration"
+msgstr ""
+
+msgid "BillingPlans|Enterprise agile planning"
+msgstr ""
+
+msgid "BillingPlans|Faster code reviews"
+msgstr ""
+
+msgid "BillingPlans|Free forever features for individual users"
+msgstr ""
+
+msgid "BillingPlans|Free guest users"
+msgstr ""
+
+msgid "BillingPlans|Free upgrade!"
+msgstr ""
+
+msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
+msgstr ""
+
+msgid "BillingPlans|Includes free static websites"
+msgstr ""
+
+msgid "BillingPlans|Learn more"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
+msgid "BillingPlans|Loved and trusted by our customers"
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Not the group you're looking for? %{all_groups_link}."
+msgstr ""
+
+msgid "BillingPlans|Open Source - MIT License"
+msgstr ""
+
+msgid "BillingPlans|Organization wide security, compliance and planning"
+msgstr ""
+
+msgid "BillingPlans|Portfolio management"
+msgstr ""
+
+msgid "BillingPlans|Premium"
+msgstr ""
+
+msgid "BillingPlans|Pricing page"
+msgstr ""
+
+msgid "BillingPlans|Ready to explore the value of the paid features today? Start a trial, no credit card required."
+msgstr ""
+
+msgid "BillingPlans|Recommended"
+msgstr ""
+
+msgid "BillingPlans|Release controls"
+msgstr ""
+
+msgid "BillingPlans|Security risk mitigation"
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|Self-managed reliability"
+msgstr ""
+
+msgid "BillingPlans|Spans the DevOps lifecycle"
+msgstr ""
+
+msgid "BillingPlans|Start a free Ultimate trial"
+msgstr ""
+
+msgid "BillingPlans|Still have questions?"
+msgstr ""
+
+msgid "BillingPlans|Support"
+msgstr ""
+
+msgid "BillingPlans|Talk to an expert today."
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Ultimate"
+msgstr ""
+
+msgid "BillingPlans|Upgrade to Premium"
+msgstr ""
+
+msgid "BillingPlans|Upgrade to Ultimate"
+msgstr ""
+
+msgid "BillingPlans|Value stream management"
+msgstr ""
+
+msgid "BillingPlans|We're here to help."
+msgstr ""
+
+msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
+msgstr ""
+
+msgid "BillingPlans|You don't have any groups. You'll need to %{create_group_link_start}create one%{create_group_link_end} and %{move_link_start}move this project to it%{move_link_end}."
+msgstr ""
+
+msgid "BillingPlans|You'll have to %{move_link_start}move this project%{move_link_end} to one of your groups."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|Your current plan"
+msgstr ""
+
+msgid "BillingPlans|billed annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|group"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "BillingPlans|per user/month"
+msgstr ""
+
+msgid "BillingPlan|Upgrade"
+msgstr ""
+
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
+msgid "Billings|%{planName} plan"
+msgstr ""
+
+msgid "Billings|An error occurred while extending your trial."
+msgstr ""
+
+msgid "Billings|An error occurred while reactivating your trial."
+msgstr ""
+
+msgid "Billings|By extending your trial, you will receive an additional 30 days of %{planName}. Your trial can be only extended once."
+msgstr ""
+
+msgid "Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once."
+msgstr ""
+
+msgid "Billings|Error validating card details"
+msgstr ""
+
+msgid "Billings|Extend trial"
+msgstr ""
+
+msgid "Billings|Free groups are limited to %{number} seats."
+msgstr ""
+
+msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
+msgstr ""
+
+msgid "Billings|In a seat"
+msgstr ""
+
+msgid "Billings|Reactivate trial"
+msgstr ""
+
+msgid "Billings|Seats in use / Seats available"
+msgstr ""
+
+msgid "Billings|Seats in use / Seats in subscription"
+msgstr ""
+
+msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
+msgstr ""
+
+msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
+msgstr ""
+
+msgid "Billings|Your account has been validated"
+msgstr ""
+
+msgid "Billing|%{user} was successfully approved"
+msgstr ""
+
+msgid "Billing|Add seats"
+msgstr ""
+
+msgid "Billing|An email address is only visible for users with public emails."
+msgstr ""
+
+msgid "Billing|An error occurred while approving %{user}"
+msgstr ""
+
+msgid "Billing|An error occurred while getting a billable member details."
+msgstr ""
+
+msgid "Billing|An error occurred while loading GitLab subscription details."
+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 ""
+
+msgid "Billing|Direct memberships"
+msgstr ""
+
+msgid "Billing|Enter at least three characters to search."
+msgstr ""
+
+msgid "Billing|Explore paid plans"
+msgstr ""
+
+msgid "Billing|Export list"
+msgstr ""
+
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Groups in the Free tier are limited to %d seat"
+msgid_plural "Billing|Groups in the Free tier are limited to %d seats"
+msgstr[0] ""
+msgstr[1] ""
+
+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 ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Private"
+msgstr ""
+
+msgid "Billing|Project invite"
+msgstr ""
+
+msgid "Billing|Remove user %{username} from your subscription"
+msgstr ""
+
+msgid "Billing|To ensure all members can access the group when your trial ends, you can upgrade to a paid tier."
+msgstr ""
+
+msgid "Billing|Toggle seat details"
+msgstr ""
+
+msgid "Billing|Type %{username} to confirm"
+msgstr ""
+
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
+msgid "Billing|User was successfully removed"
+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 ""
+
+msgid "Billing|Your group recently changed to use the Free plan. %{over_limit_message} You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+msgstr ""
+
+msgid "BlobViewer|View on %{environmentName}"
+msgstr ""
+
+msgid "Block user"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blocked by %d issue"
+msgid_plural "Blocked by %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked issue"
+msgstr ""
+
+msgid "Blocking"
+msgstr ""
+
+msgid "Blocking epics"
+msgstr ""
+
+msgid "Blocking issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewEpic|Groups"
+msgstr ""
+
+msgid "BoardNewEpic|Loading groups"
+msgstr ""
+
+msgid "BoardNewEpic|No matching results"
+msgstr ""
+
+msgid "BoardNewEpic|Search groups"
+msgstr ""
+
+msgid "BoardNewEpic|Select a group"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
+msgid "BoardScope|%{iterationTitle} iteration in %{iterationCadence}"
+msgstr ""
+
+msgid "BoardScope|An error occurred while getting iterations. Please try again."
+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 ""
+
+msgid "BoardScope|Any Milestone"
+msgstr ""
+
+msgid "BoardScope|Any assignee"
+msgstr ""
+
+msgid "BoardScope|Any iteration"
+msgstr ""
+
+msgid "BoardScope|Any label"
+msgstr ""
+
+msgid "BoardScope|Assignee"
+msgstr ""
+
+msgid "BoardScope|Choose labels"
+msgstr ""
+
+msgid "BoardScope|Current iteration"
+msgstr ""
+
+msgid "BoardScope|Don't filter milestone"
+msgstr ""
+
+msgid "BoardScope|Edit"
+msgstr ""
+
+msgid "BoardScope|Iteration"
+msgstr ""
+
+msgid "BoardScope|Labels"
+msgstr ""
+
+msgid "BoardScope|Milestone"
+msgstr ""
+
+msgid "BoardScope|No iteration"
+msgstr ""
+
+msgid "BoardScope|No milestone"
+msgstr ""
+
+msgid "BoardScope|Search iterations"
+msgstr ""
+
+msgid "BoardScope|Search milestones"
+msgstr ""
+
+msgid "BoardScope|Select assignee"
+msgstr ""
+
+msgid "BoardScope|Select iteration"
+msgstr ""
+
+msgid "BoardScope|Select labels"
+msgstr ""
+
+msgid "BoardScope|Select milestone"
+msgstr ""
+
+msgid "BoardScope|Select weight"
+msgstr ""
+
+msgid "BoardScope|Started"
+msgstr ""
+
+msgid "BoardScope|Upcoming"
+msgstr ""
+
+msgid "BoardScope|Weight"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and board lists"
+msgstr ""
+
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|An error occurred while creating the epic. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching child groups. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching group projects. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while removing the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while updating the board list. Please try again."
+msgstr ""
+
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Move card"
+msgstr ""
+
+msgid "Boards|Move to end of list"
+msgstr ""
+
+msgid "Boards|Move to start of list"
+msgstr ""
+
+msgid "Boards|New board"
+msgstr ""
+
+msgid "Boards|New epic"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+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 ""
+
+msgid "Board|Create board"
+msgstr ""
+
+msgid "Board|Create new board"
+msgstr ""
+
+msgid "Board|Delete board"
+msgstr ""
+
+msgid "Board|Edit board"
+msgstr ""
+
+msgid "Board|Enter board name"
+msgstr ""
+
+msgid "Board|Failed to delete board. Please try again."
+msgstr ""
+
+msgid "Board|Load more epics"
+msgstr ""
+
+msgid "Board|Load more issues"
+msgstr ""
+
+msgid "Board|Loading epics"
+msgstr ""
+
+msgid "Bold text"
+msgstr ""
+
+msgid "Bot"
+msgstr ""
+
+msgid "Both SSH and HTTP(S)"
+msgstr ""
+
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
+msgid "Branch"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch already exists"
+msgstr ""
+
+msgid "Branch changed"
+msgstr ""
+
+msgid "Branch has been updated since the merge was requested."
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
+msgid "Branch rules"
+msgstr ""
+
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+msgstr ""
+
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
+msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr ""
+
+msgid "BranchRules|Allowed to merge"
+msgstr ""
+
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
+msgid "BranchRules|Allowed to push"
+msgstr ""
+
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Approvals"
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+msgstr ""
+
+msgid "BranchRules|Protect branch"
+msgstr ""
+
+msgid "BranchRules|Protections"
+msgstr ""
+
+msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
+
+msgid "BranchRules|Require approval from code owners."
+msgstr ""
+
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
+msgid "BranchRules|default"
+msgstr ""
+
+msgid "BranchRules|protected"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this branch."
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn't been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|Unable to load branches"
+msgstr ""
+
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{branchName}."
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{branchName}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Breadcrumbs"
+msgstr ""
+
+msgid "Broadcast Message was successfully created."
+msgstr ""
+
+msgid "Broadcast Message was successfully updated."
+msgstr ""
+
+msgid "Broadcast Messages"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Browse templates"
+msgstr ""
+
+msgid "Build cannot be erased"
+msgstr ""
+
+msgid "BuildArtifacts|An error occurred while fetching the artifacts"
+msgstr ""
+
+msgid "BuildArtifacts|Loading artifacts"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Bulk request concurrency"
+msgstr ""
+
+msgid "Bulk update"
+msgstr ""
+
+msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
+msgstr ""
+
+msgid "BulkImport|%{feature} (require v%{version})"
+msgstr ""
+
+msgid "BulkImport|Destination"
+msgstr ""
+
+msgid "BulkImport|Destination group"
+msgstr ""
+
+msgid "BulkImport|Existing groups"
+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 ""
+
+msgid "BulkImport|Group import history"
+msgstr ""
+
+msgid "BulkImport|History"
+msgstr ""
+
+msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
+msgid "BulkImport|Import selected"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed."
+msgstr ""
+
+msgid "BulkImport|Last imported to %{link}"
+msgstr ""
+
+msgid "BulkImport|Name already exists."
+msgstr ""
+
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
+msgid "BulkImport|No additional information provided."
+msgstr ""
+
+msgid "BulkImport|No groups found"
+msgstr ""
+
+msgid "BulkImport|No history is available"
+msgstr ""
+
+msgid "BulkImport|No parent"
+msgstr ""
+
+msgid "BulkImport|Only groups that you have the %{role} role for are listed as groups you can import."
+msgstr ""
+
+msgid "BulkImport|Project import history"
+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 ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own from %{link}"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own matching filter \"%{filter}\" from %{link}"
+msgstr ""
+
+msgid "BulkImport|Source"
+msgstr ""
+
+msgid "BulkImport|Source group"
+msgstr ""
+
+msgid "BulkImport|Template / File-based import / GitLab Migration"
+msgstr ""
+
+msgid "BulkImport|To new group"
+msgstr ""
+
+msgid "BulkImport|Update of import statuses with realtime changes failed"
+msgstr ""
+
+msgid "BulkImport|Your imported groups will appear here."
+msgstr ""
+
+msgid "BulkImport|Your imported projects will appear here."
+msgstr ""
+
+msgid "BulkImport|expected an associated Group but has an associated Project"
+msgstr ""
+
+msgid "BulkImport|expected an associated Project but has an associated Group"
+msgstr ""
+
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
+msgid "BulkImport|must be a group"
+msgstr ""
+
+msgid "Bullet list"
+msgstr ""
+
+msgid "Burndown chart"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
+msgid "Burnup chart"
+msgstr ""
+
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "Busy"
+msgstr ""
+
+msgid "Buy CI Minutes"
+msgstr ""
+
+msgid "Buy Storage"
+msgstr ""
+
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "By month"
+msgstr ""
+
+msgid "By quarter"
+msgstr ""
+
+msgid "By week"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI configuration validated, including all configuration added with the %{codeStart}include%{codeEnd} keyword. %{link}"
+msgstr ""
+
+msgid "CI settings"
+msgstr ""
+
+msgid "CI variables"
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD configuration file"
+msgstr ""
+
+msgid "CI/CD limits"
+msgstr ""
+
+msgid "CI/CD minutes"
+msgstr ""
+
+msgid "CI/CD|No projects have been added to the scope"
+msgstr ""
+
+msgid "CICDAnalytics|%{percent}%{percentSymbol}"
+msgstr ""
+
+msgid "CICDAnalytics|All time"
+msgstr ""
+
+msgid "CICDAnalytics|Change failure rate"
+msgstr ""
+
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
+msgid "CICDAnalytics|Lead time"
+msgstr ""
+
+msgid "CICDAnalytics|No shared runner minute usage data available"
+msgstr ""
+
+msgid "CICDAnalytics|Projects with releases"
+msgstr ""
+
+msgid "CICDAnalytics|Release"
+msgid_plural "CICDAnalytics|Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
+msgid "CICDAnalytics|Releases"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner duration is the total runtime of all jobs that ran on shared runners"
+msgstr ""
+
+msgid "CICDAnalytics|Shared runner pipeline minute duration by month"
+msgstr ""
+
+msgid "CICDAnalytics|Something went wrong while fetching release statistics"
+msgstr ""
+
+msgid "CICDAnalytics|Time to restore service"
+msgstr ""
+
+msgid "CICDAnalytics|What is shared runner duration?"
+msgstr ""
+
+msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
+msgstr ""
+
+msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
+msgstr ""
+
+msgid "CICD|Add an existing project to the scope"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline for all projects"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Limit"
+msgstr ""
+
+msgid "CICD|Limit CI_JOB_TOKEN access"
+msgstr ""
+
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|There are several CI/CD limits in place."
+msgstr ""
+
+msgid "CICD|Unprotected branches will not have access to the cache from protected branches."
+msgstr ""
+
+msgid "CICD|Use separate caches for protected branches"
+msgstr ""
+
+msgid "CICD|group enabled"
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CLOSED"
+msgstr ""
+
+msgid "CLOSED (MOVED)"
+msgstr ""
+
+msgid "CODEOWNERS rule violation"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "CPU"
+msgstr ""
+
+msgid "CSV is being generated and will be emailed to you upon completion."
+msgstr ""
+
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
+msgid "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 ""
+
+msgid "Campfire room ID (optional)"
+msgstr ""
+
+msgid "Campfire subdomain (optional)"
+msgstr ""
+
+msgid "Campfire token"
+msgstr ""
+
+msgid "CampfireService|API authentication token from Campfire."
+msgstr ""
+
+msgid "CampfireService|From the end of the room URL."
+msgstr ""
+
+msgid "CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}"
+msgstr ""
+
+msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
+msgstr ""
+
+msgid "Can be manually deployed to"
+msgstr ""
+
+msgid "Can be overridden in each project."
+msgstr ""
+
+msgid "Can create groups:"
+msgstr ""
+
+msgid "Can not delete primary training"
+msgstr ""
+
+msgid "Can't apply as the source branch was deleted."
+msgstr ""
+
+msgid "Can't apply as these lines were changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply as this line was changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply this suggestion."
+msgstr ""
+
+msgid "Can't be empty"
+msgstr ""
+
+msgid "Can't create snippet: %{err}"
+msgstr ""
+
+msgid "Can't fetch content for the blob: %{err}"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
+msgid "Can't update snippet: %{err}"
+msgstr ""
+
+msgid "Canary"
+msgstr ""
+
+msgid "Canary Ingress does not exist in the environment."
+msgstr ""
+
+msgid "Canary weight must be specified and valid range (0..100)."
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}"
+msgstr ""
+
+msgid "CanaryIngress|Canary"
+msgstr ""
+
+msgid "CanaryIngress|Change ratio"
+msgstr ""
+
+msgid "CanaryIngress|Change the ratio of canary deployments?"
+msgstr ""
+
+msgid "CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished."
+msgstr ""
+
+msgid "CanaryIngress|Stable"
+msgstr ""
+
+msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel and close"
+msgstr ""
+
+msgid "Cancel downstream pipeline"
+msgstr ""
+
+msgid "Cancel editing"
+msgstr ""
+
+msgid "Cancel index deletion"
+msgstr ""
+
+msgid "Cancel running"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cancel your account"
+msgstr ""
+
+msgid "Cancel, keep project"
+msgstr ""
+
+msgid "Canceled deployment to"
+msgstr ""
+
+msgid "Cancelled"
+msgstr ""
+
+msgid "Cancelling Preview"
+msgstr ""
+
+msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
+msgstr ""
+
+msgid "Cannot assign an issue that does not belong under the same group (or descendant) as the epic."
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
+msgstr ""
+
+msgid "Cannot create the abuse report. The user has been deleted."
+msgstr ""
+
+msgid "Cannot create the abuse report. This user has been blocked."
+msgstr ""
+
+msgid "Cannot delete %{profile_name} referenced in security policy"
+msgstr ""
+
+msgid "Cannot have multiple Jira imports running at the same time"
+msgstr ""
+
+msgid "Cannot have multiple unresolved alerts"
+msgstr ""
+
+msgid "Cannot import because issues are not available in this project."
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
+
+msgid "Cannot merge"
+msgstr ""
+
+msgid "Cannot modify %{profile_name} referenced in security policy"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Cannot modify provider during creation"
+msgstr ""
+
+msgid "Cannot promote issue because it does not belong to a group."
+msgstr ""
+
+msgid "Cannot promote issue due to insufficient permissions."
+msgstr ""
+
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
+msgid "Cannot skip two factor authentication setup"
+msgstr ""
+
+msgid "Capacity threshold"
+msgstr ""
+
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
+msgid "CascadingSettings|Enforce deletion protection for all subgroups"
+msgstr ""
+
+msgid "CascadingSettings|Enforce for all subgroups"
+msgstr ""
+
+msgid "CascadingSettings|Setting enforced"
+msgstr ""
+
+msgid "CascadingSettings|Subgroups cannot change this setting."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an instance admin."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
+msgstr ""
+
+msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
+msgstr ""
+
+msgid "CascadingSettings|cannot be nil when locking the attribute"
+msgstr ""
+
+msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate Issuer"
+msgstr ""
+
+msgid "Certificate Subject"
+msgstr ""
+
+msgid "Change Failure Rate"
+msgstr ""
+
+msgid "Change assignee"
+msgstr ""
+
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
+msgid "Change branches"
+msgstr ""
+
+msgid "Change label"
+msgstr ""
+
+msgid "Change made by"
+msgstr ""
+
+msgid "Change milestone"
+msgstr ""
+
+msgid "Change path"
+msgstr ""
+
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
+msgid "Change role"
+msgstr ""
+
+msgid "Change status"
+msgstr ""
+
+msgid "Change subscription"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Unassigned"
+msgstr ""
+
+msgid "ChangeTypeAction|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 ""
+
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Search branches"
+msgstr ""
+
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
+msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
+msgid "Changed"
+msgstr ""
+
+msgid "Changed assignee(s)."
+msgstr ""
+
+msgid "Changed merge method to %{merge_method}"
+msgstr ""
+
+msgid "Changed reviewer(s)."
+msgstr ""
+
+msgid "Changed squash option to %{squash_option}"
+msgstr ""
+
+msgid "Changed the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes"
+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 saved."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes to the title have not been saved"
+msgstr ""
+
+msgid "Changes:"
+msgstr ""
+
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
+msgid "Characters left"
+msgstr ""
+
+msgid "Characters over limit"
+msgstr ""
+
+msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Branch"
+msgstr ""
+
+msgid "ChatMessage|Commit"
+msgstr ""
+
+msgid "ChatMessage|Failed job"
+msgstr ""
+
+msgid "ChatMessage|Failed stage"
+msgstr ""
+
+msgid "ChatMessage|Invalid CI config YAML file"
+msgstr ""
+
+msgid "ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}"
+msgstr ""
+
+msgid "ChatMessage|Tag"
+msgstr ""
+
+msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
+msgstr ""
+
+msgid "ChatMessage|has failed"
+msgstr ""
+
+msgid "ChatMessage|has passed"
+msgstr ""
+
+msgid "ChatMessage|has passed with warnings"
+msgstr ""
+
+msgid "ChatMessage|in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|in %{project_link}"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "Check feature availability on namespace plan"
+msgstr ""
+
+msgid "Check out branch"
+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 with your administrator."
+msgstr ""
+
+msgid "Check your Docker images for known vulnerabilities."
+msgstr ""
+
+msgid "Check your Kubernetes cluster images for known vulnerabilities."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Checking group path availability..."
+msgstr ""
+
+msgid "Checking username availability..."
+msgstr ""
+
+msgid "Checkout"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per user per year"
+msgstr ""
+
+msgid "Checkout|%d CI minute pack"
+msgid_plural "Checkout|%d CI minute packs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
+msgstr ""
+
+msgid "Checkout|%{name}'s CI minutes"
+msgstr ""
+
+msgid "Checkout|%{name}'s GitLab subscription"
+msgstr ""
+
+msgid "Checkout|%{name}'s storage subscription"
+msgstr ""
+
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
+msgid "Checkout|%{quantity} GB of storage"
+msgstr ""
+
+msgid "Checkout|%{quantity} storage pack"
+msgid_plural "Checkout|%{quantity} storage packs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Checkout|%{selectedPlanText} plan"
+msgstr ""
+
+msgid "Checkout|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
+msgstr ""
+
+msgid "Checkout|(x%{numberOfUsers})"
+msgstr ""
+
+msgid "Checkout|(x%{quantity})"
+msgstr ""
+
+msgid "Checkout|An unknown error has occurred. Please try again by refreshing this page."
+msgstr ""
+
+msgid "Checkout|Billing address"
+msgstr ""
+
+msgid "Checkout|CI minute pack"
+msgstr ""
+
+msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
+msgstr ""
+
+msgid "Checkout|CI minutes"
+msgstr ""
+
+msgid "Checkout|Calculating your subscription..."
+msgstr ""
+
+msgid "Checkout|Checkout"
+msgstr ""
+
+msgid "Checkout|City"
+msgstr ""
+
+msgid "Checkout|Confirm purchase"
+msgstr ""
+
+msgid "Checkout|Confirming..."
+msgstr ""
+
+msgid "Checkout|Continue to billing"
+msgstr ""
+
+msgid "Checkout|Continue to payment"
+msgstr ""
+
+msgid "Checkout|Country"
+msgstr ""
+
+msgid "Checkout|Create a new group"
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load. Please try again."
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load: %{message}"
+msgstr ""
+
+msgid "Checkout|Edit"
+msgstr ""
+
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
+msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order! Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load countries. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load states. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load the payment form. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to register credit card. Please try again."
+msgstr ""
+
+msgid "Checkout|GB"
+msgstr ""
+
+msgid "Checkout|GitLab group"
+msgstr ""
+
+msgid "Checkout|GitLab plan"
+msgstr ""
+
+msgid "Checkout|Group"
+msgstr ""
+
+msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use) or more."
+msgstr ""
+
+msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use, plus all over limit members) or more. To buy fewer seats, remove members from the group."
+msgstr ""
+
+msgid "Checkout|Name of company or organization using GitLab"
+msgstr ""
+
+msgid "Checkout|Name: %{errors}"
+msgstr ""
+
+msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
+msgstr ""
+
+msgid "Checkout|Number of users"
+msgstr ""
+
+msgid "Checkout|Payment method"
+msgstr ""
+
+msgid "Checkout|Please select a country"
+msgstr ""
+
+msgid "Checkout|Please select a state"
+msgstr ""
+
+msgid "Checkout|Purchase details"
+msgstr ""
+
+msgid "Checkout|Select"
+msgstr ""
+
+msgid "Checkout|State"
+msgstr ""
+
+msgid "Checkout|Storage packs"
+msgstr ""
+
+msgid "Checkout|Street address"
+msgstr ""
+
+msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
+msgstr ""
+
+msgid "Checkout|Subscription details"
+msgstr ""
+
+msgid "Checkout|Subtotal"
+msgstr ""
+
+msgid "Checkout|Success: subscription"
+msgstr ""
+
+msgid "Checkout|Tax"
+msgstr ""
+
+msgid "Checkout|Total"
+msgstr ""
+
+msgid "Checkout|Total minutes: %{quantity}"
+msgstr ""
+
+msgid "Checkout|Total storage: %{quantity} GB"
+msgstr ""
+
+msgid "Checkout|Users"
+msgstr ""
+
+msgid "Checkout|You'll create your new group after checkout"
+msgstr ""
+
+msgid "Checkout|Your organization"
+msgstr ""
+
+msgid "Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly."
+msgstr ""
+
+msgid "Checkout|Your subscription will be applied to this group"
+msgstr ""
+
+msgid "Checkout|Zip code"
+msgstr ""
+
+msgid "Checkout|a storage subscription"
+msgstr ""
+
+msgid "Checkout|company or team"
+msgstr ""
+
+msgid "Checkout|minutes"
+msgstr ""
+
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
+msgid "Checkout|x %{quantity} %{units} per pack ="
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Child"
+msgstr ""
+
+msgid "Child epic"
+msgstr ""
+
+msgid "Child epic does not exist."
+msgstr ""
+
+msgid "Child epic doesn't exist."
+msgstr ""
+
+msgid "Child issues and epics"
+msgstr ""
+
+msgid "Chinese language support using"
+msgstr ""
+
+msgid "Choose File..."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a group"
+msgstr ""
+
+msgid "Choose a template"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose file…"
+msgstr ""
+
+msgid "Choose the preferred Runner and populate the AWS CFT."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
+
+msgid "Choose which Git strategy to use when fetching the project."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose your framework"
+msgstr ""
+
+msgid "CiCdAnalytics|Date range: %{range}"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|preparing"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for resource"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|preparing"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatusText|waiting"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
+msgid "CiVariables|Environments"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
+msgid "CiVariables|Protected"
+msgstr ""
+
+msgid "CiVariables|Remove variable"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
+msgid "CiVariables|Variables"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "Classification Label (optional)"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clean up after running %{link_start}git filter-repo%{link_end} on the repository."
+msgstr ""
+
+msgid "Cleanup policies are executed by background workers. This setting defines the maximum number of workers that can run concurrently. Set it to 0 to remove all workers and not execute the cleanup policies."
+msgstr ""
+
+msgid "Cleanup policy maximum number of tags to be deleted"
+msgstr ""
+
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
+msgid "Cleanup policy maximum workers running concurrently"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear %{count} image from cache?"
+msgid_plural "Clear %{count} images from cache?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Clear all repository checks"
+msgstr ""
+
+msgid "Clear chart filters"
+msgstr ""
+
+msgid "Clear due date"
+msgstr ""
+
+msgid "Clear health status"
+msgstr ""
+
+msgid "Clear recent searches"
+msgstr ""
+
+msgid "Clear repository checks"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Clear start date"
+msgstr ""
+
+msgid "Clear templates search input"
+msgstr ""
+
+msgid "Clear this checkbox to use a personal access token instead."
+msgstr ""
+
+msgid "Clear this checkbox to use a personal access token or LDAP password instead."
+msgstr ""
+
+msgid "Clear this checkbox to use an external authentication provider instead."
+msgstr ""
+
+msgid "Clear weight"
+msgstr ""
+
+msgid "Cleared health status."
+msgstr ""
+
+msgid "Cleared weight."
+msgstr ""
+
+msgid "Clears health status."
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
+msgid "Click %{link_start}here%{link_end} to view the request."
+msgstr ""
+
+msgid "Click %{link_to} to view the request."
+msgstr ""
+
+msgid "Click the link below to confirm your email address (%{email})"
+msgstr ""
+
+msgid "Click the link below to confirm your email address."
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Click to hide"
+msgstr ""
+
+msgid "Click to reveal"
+msgstr ""
+
+msgid "Client request timeout"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clientside DSN"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone this issue"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with %{protocol}"
+msgstr ""
+
+msgid "Clone with KRB5"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
+msgstr ""
+
+msgid "Cloned this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Clones this issue, without comments, to %{project}."
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close %{issueType}"
+msgstr ""
+
+msgid "Close %{noteable}"
+msgstr ""
+
+msgid "Close %{tabname}"
+msgstr ""
+
+msgid "Close design"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Close sidebar"
+msgstr ""
+
+msgid "Close this %{quick_action_target}"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Closed MRs"
+msgstr ""
+
+msgid "Closed date"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "Closed this %{quick_action_target}."
+msgstr ""
+
+msgid "Closed: %{closed}"
+msgstr ""
+
+msgid "Closes this %{quick_action_target}."
+msgstr ""
+
+msgid "Cloud Run"
+msgstr ""
+
+msgid "Cloud SQL instances are fully managed, relational MySQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
+msgstr ""
+
+msgid "Cloud SQL instances are fully managed, relational SQL Server databases. Google handles replication, patch management, and database management to ensure availability and performance."
+msgstr ""
+
+msgid "Cloud Storage"
+msgstr ""
+
+msgid "CloudSeed|All"
+msgstr ""
+
+msgid "CloudSeed|AlloyDB for Postgres"
+msgstr ""
+
+msgid "CloudSeed|Available database services through which instances may be created"
+msgstr ""
+
+msgid "CloudSeed|Cancel"
+msgstr ""
+
+msgid "CloudSeed|Cloud Firestore"
+msgstr ""
+
+msgid "CloudSeed|Cloud SQL for MySQL"
+msgstr ""
+
+msgid "CloudSeed|Cloud SQL for Postgres"
+msgstr ""
+
+msgid "CloudSeed|Cloud SQL for SQL Server"
+msgstr ""
+
+msgid "CloudSeed|Cloud SQL instance creation request successful. Expected resolution time is ~5 minutes."
+msgstr ""
+
+msgid "CloudSeed|Cloud SQL instances are fully managed, relational PostgreSQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
+msgstr ""
+
+msgid "CloudSeed|CloudSQL Instance"
+msgstr ""
+
+msgid "CloudSeed|Configuration"
+msgstr ""
+
+msgid "CloudSeed|Create MySQL Instance"
+msgstr ""
+
+msgid "CloudSeed|Create Postgres Instance"
+msgstr ""
+
+msgid "CloudSeed|Create cluster"
+msgstr ""
+
+msgid "CloudSeed|Create database"
+msgstr ""
+
+msgid "CloudSeed|Create instance"
+msgstr ""
+
+msgid "CloudSeed|Database instance is generated within the selected Google Cloud project"
+msgstr ""
+
+msgid "CloudSeed|Database instances associated with this project"
+msgstr ""
+
+msgid "CloudSeed|Database version"
+msgstr ""
+
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
+msgid "CloudSeed|Description"
+msgstr ""
+
+msgid "CloudSeed|Determines memory and virtual cores available to your instance"
+msgstr ""
+
+msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
+msgstr ""
+
+msgid "CloudSeed|Environment"
+msgstr ""
+
+msgid "CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development"
+msgstr ""
+
+msgid "CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads"
+msgstr ""
+
+msgid "CloudSeed|Fully managed relational database service for MySQL"
+msgstr ""
+
+msgid "CloudSeed|Fully managed relational database service for PostgreSQL"
+msgstr ""
+
+msgid "CloudSeed|Fully managed relational database service for SQL Server"
+msgstr ""
+
+msgid "CloudSeed|Generated database instance is linked to the selected branch or tag"
+msgstr ""
+
+msgid "CloudSeed|Google Cloud Error - %{message}"
+msgstr ""
+
+msgid "CloudSeed|Google Cloud Project"
+msgstr ""
+
+msgid "CloudSeed|Google Cloud project"
+msgstr ""
+
+msgid "CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances"
+msgstr ""
+
+msgid "CloudSeed|Instances"
+msgstr ""
+
+msgid "CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}."
+msgstr ""
+
+msgid "CloudSeed|Machine type"
+msgstr ""
+
+msgid "CloudSeed|Memorystore for Redis"
+msgstr ""
+
+msgid "CloudSeed|No instances"
+msgstr ""
+
+msgid "CloudSeed|Refs"
+msgstr ""
+
+msgid "CloudSeed|Regions"
+msgstr ""
+
+msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
+msgstr ""
+
+msgid "CloudSeed|Service"
+msgstr ""
+
+msgid "CloudSeed|Service Account"
+msgstr ""
+
+msgid "CloudSeed|Services"
+msgstr ""
+
+msgid "CloudSeed|There are no instances to display."
+msgstr ""
+
+msgid "CloudSeed|Version"
+msgstr ""
+
+msgid "Cluster"
+msgstr ""
+
+msgid "Cluster Health"
+msgstr ""
+
+msgid "Cluster cache cleared."
+msgstr ""
+
+msgid "Cluster is required for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "Cluster level"
+msgstr ""
+
+msgid "Cluster type must be specified for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "ClusterAgents|%{linkStart}View the documentation%{linkEnd} for advanced installation. Ensure you have your access token available."
+msgstr ""
+
+msgid "ClusterAgents|%{name} successfully deleted"
+msgstr ""
+
+msgid "ClusterAgents|%{name} successfully revoked"
+msgstr ""
+
+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|%{tokenName} created"
+msgstr ""
+
+msgid "ClusterAgents|%{tokenName} revoked"
+msgstr ""
+
+msgid "ClusterAgents|Access tokens"
+msgstr ""
+
+msgid "ClusterAgents|Add an agent configuration file to %{linkStart}this repository%{linkEnd} and select it, or create a new one to register with GitLab:"
+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 access token:"
+msgstr ""
+
+msgid "ClusterAgents|Agent might not be connected to GitLab"
+msgstr ""
+
+msgid "ClusterAgents|Agent never connected to GitLab"
+msgstr ""
+
+msgid "ClusterAgents|Agent version mismatch"
+msgstr ""
+
+msgid "ClusterAgents|Agent version mismatch and update"
+msgstr ""
+
+msgid "ClusterAgents|Agent version update required"
+msgstr ""
+
+msgid "ClusterAgents|All"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your agent"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your agents"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while retrieving agent activity. Reload the page to try again."
+msgstr ""
+
+msgid "ClusterAgents|An unknown error occurred. Please try again."
+msgstr ""
+
+msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
+msgstr ""
+
+msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
+msgstr ""
+
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
+msgid "ClusterAgents|Configuration"
+msgstr ""
+
+msgid "ClusterAgents|Connect a Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect a cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect a cluster (agent)"
+msgstr ""
+
+msgid "ClusterAgents|Connect a cluster (certificate - deprecated)"
+msgstr ""
+
+msgid "ClusterAgents|Connect a cluster (deprecated)"
+msgstr ""
+
+msgid "ClusterAgents|Connected"
+msgstr ""
+
+msgid "ClusterAgents|Connection status"
+msgstr ""
+
+msgid "ClusterAgents|Copy command"
+msgstr ""
+
+msgid "ClusterAgents|Copy token"
+msgstr ""
+
+msgid "ClusterAgents|Create a cluster"
+msgstr ""
+
+msgid "ClusterAgents|Create agent access token"
+msgstr ""
+
+msgid "ClusterAgents|Create agent: %{searchTerm}"
+msgstr ""
+
+msgid "ClusterAgents|Create token"
+msgstr ""
+
+msgid "ClusterAgents|Created by"
+msgstr ""
+
+msgid "ClusterAgents|Created by %{name} %{time}"
+msgstr ""
+
+msgid "ClusterAgents|Date created"
+msgstr ""
+
+msgid "ClusterAgents|Default configuration"
+msgstr ""
+
+msgid "ClusterAgents|Delete"
+msgstr ""
+
+msgid "ClusterAgents|Delete agent"
+msgstr ""
+
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
+msgid "ClusterAgents|Description"
+msgstr ""
+
+msgid "ClusterAgents|Event occurred"
+msgstr ""
+
+msgid "ClusterAgents|Failed to create a token"
+msgstr ""
+
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
+
+msgid "ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included in the command."
+msgstr ""
+
+msgid "ClusterAgents|GitLab agent"
+msgstr ""
+
+msgid "ClusterAgents|GitLab agent for Kubernetes"
+msgstr ""
+
+msgid "ClusterAgents|Give feedback"
+msgstr ""
+
+msgid "ClusterAgents|How do I register an agent?"
+msgstr ""
+
+msgid "ClusterAgents|How to update an agent?"
+msgstr ""
+
+msgid "ClusterAgents|Install using Helm (recommended)"
+msgstr ""
+
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
+msgid "ClusterAgents|Last connected %{timeAgo}."
+msgstr ""
+
+msgid "ClusterAgents|Last contact"
+msgstr ""
+
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
+msgid "ClusterAgents|Make sure you are using a valid token."
+msgstr ""
+
+msgid "ClusterAgents|Name"
+msgstr ""
+
+msgid "ClusterAgents|Never"
+msgstr ""
+
+msgid "ClusterAgents|Never connected"
+msgstr ""
+
+msgid "ClusterAgents|No activity occurred in the past day"
+msgid_plural "ClusterAgents|No activity occurred in the past %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
+msgid "ClusterAgents|Not connected"
+msgstr ""
+
+msgid "ClusterAgents|Premium"
+msgstr ""
+
+msgid "ClusterAgents|Recommended"
+msgstr ""
+
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Registering agent"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
+msgstr ""
+
+msgid "ClusterAgents|Requires a Maintainer or greater role to perform this action"
+msgstr ""
+
+msgid "ClusterAgents|Revoke access token?"
+msgstr ""
+
+msgid "ClusterAgents|Revoke token"
+msgstr ""
+
+msgid "ClusterAgents|Security"
+msgstr ""
+
+msgid "ClusterAgents|See agent activity updates, like tokens created or revoked and clusters connected or not connected."
+msgstr ""
+
+msgid "ClusterAgents|Select an agent or enter a name to create new"
+msgstr ""
+
+msgid "ClusterAgents|Tell us what you think"
+msgstr ""
+
+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 agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgstr ""
+
+msgid "ClusterAgents|The agent uses the token to connect with GitLab."
+msgstr ""
+
+msgid "ClusterAgents|The agent version do not match each other across your cluster's pods. This can happen when a new agent version was just deployed and Kubernetes is shutting down the old pods."
+msgstr ""
+
+msgid "ClusterAgents|This agent has no tokens"
+msgstr ""
+
+msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
+msgstr ""
+
+msgid "ClusterAgents|To revoke the token, type %{name} to confirm:"
+msgstr ""
+
+msgid "ClusterAgents|Token created by %{userName}"
+msgstr ""
+
+msgid "ClusterAgents|Token revoked by %{userName}"
+msgstr ""
+
+msgid "ClusterAgents|Unknown user"
+msgstr ""
+
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
+msgstr ""
+
+msgid "ClusterAgents|What is agent activity?"
+msgstr ""
+
+msgid "ClusterAgents|What is default configuration?"
+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 agent version is out of sync with your GitLab version (v%{version}), which might cause compatibility problems. Update the agent installed on your cluster to the most recent version."
+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 ""
+
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|API URL should be a valid http/https url."
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
+msgid "ClusterIntegration|Amazon EKS"
+msgstr ""
+
+msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
+msgstr ""
+
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Authentication Error"
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Check your CA certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Check your cluster status"
+msgstr ""
+
+msgid "ClusterIntegration|Check your token"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Civo Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Clear cluster cache"
+msgstr ""
+
+msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster management project"
+msgstr ""
+
+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|Connect a Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Connection Error"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Create a Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Kubernetes Service"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Prometheus integration"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter details about your cluster. %{linkStart}How do I use a certificate to connect to my cluster?%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Enter new Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Enter your Kubernetes cluster certificate details"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope is required."
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to authenticate."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to connect to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Google GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|HTTP Error"
+msgstr ""
+
+msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
+msgstr ""
+
+msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
+msgstr ""
+
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Integration disabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integration enabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your API endpoint is correct"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
+msgstr ""
+
+msgid "ClusterIntegration|Namespace per environment"
+msgstr ""
+
+msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Provider details"
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Service token is required."
+msgstr ""
+
+msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
+msgstr ""
+
+msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
+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, and Web terminals."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|This process is %{issue_link_start}deprecated%{issue_link_end}. Use the %{docs_link_start}the GitLab agent for Kubernetes%{docs_link_end} instead."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|Troubleshooting tips:"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Authenticate"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Connect"
+msgstr ""
+
+msgid "ClusterIntegration|Unknown Error"
+msgstr ""
+
+msgid "ClusterIntegration|Use GitLab to deploy to your cluster, run jobs, use review apps, and more."
+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|Using AutoDevOps with multiple clusters? %{help_link_start}Read this first.%{help_link_end}"
+msgstr ""
+
+msgid "ClusterIntegration|Where do you want to create a cluster?"
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Clusters|An error occurred while loading clusters"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
+msgstr ""
+
+msgid "Code Coverage| Empty code coverage data"
+msgstr ""
+
+msgid "Code Coverage|Couldn't fetch the code coverage data"
+msgstr ""
+
+msgid "Code Owner"
+msgstr ""
+
+msgid "Code Owners"
+msgstr ""
+
+msgid "Code Quality"
+msgstr ""
+
+msgid "Code Review"
+msgstr ""
+
+msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
+msgstr ""
+
+msgid "Code block"
+msgstr ""
+
+msgid "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
+msgstr ""
+
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
+msgstr ""
+
+msgid "Code owner approval is required"
+msgstr ""
+
+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 ""
+
+msgid "CodeNavigation|No references found"
+msgstr ""
+
+msgid "CodeOwner|Pattern"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations on this line"
+msgstr ""
+
+msgid "Cohorts|Inactive users"
+msgstr ""
+
+msgid "Cohorts|Month %{month_index}"
+msgstr ""
+
+msgid "Cohorts|New users"
+msgstr ""
+
+msgid "Cohorts|Registration month"
+msgstr ""
+
+msgid "Cohorts|Returning users"
+msgstr ""
+
+msgid "Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately."
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse all threads"
+msgstr ""
+
+msgid "Collapse approvers"
+msgstr ""
+
+msgid "Collapse issues"
+msgstr ""
+
+msgid "Collapse jobs"
+msgstr ""
+
+msgid "Collapse merge details"
+msgstr ""
+
+msgid "Collapse milestones"
+msgstr ""
+
+msgid "Collapse replies"
+msgstr ""
+
+msgid "Collapse settings section"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
+msgid "Collector hostname"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "ColorWidget|An error occurred while updating color."
+msgstr ""
+
+msgid "ColorWidget|Assign epic color"
+msgstr ""
+
+msgid "ColorWidget|Color"
+msgstr ""
+
+msgid "ColorWidget|Error fetching epic color."
+msgstr ""
+
+msgid "Colorize messages"
+msgstr ""
+
+msgid "ComboSearch is not defined"
+msgstr ""
+
+msgid "Comma-separated list of email addresses."
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Commands applied"
+msgstr ""
+
+msgid "Commands did not apply"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve thread"
+msgstr ""
+
+msgid "Comment & unresolve thread"
+msgstr ""
+
+msgid "Comment '%{label}' position"
+msgstr ""
+
+msgid "Comment added to the timeline."
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comment is being updated"
+msgstr ""
+
+msgid "Comment on lines %{startLine} to %{endLine}"
+msgstr ""
+
+msgid "Comment/Reply (quoting selected text)"
+msgstr ""
+
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit (when editing commit message)"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit SHA"
+msgstr ""
+
+msgid "Commit changes"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit message (optional)"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits to"
+msgstr ""
+
+msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
+msgstr ""
+
+msgid "Commits:"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Community forum"
+msgstr ""
+
+msgid "Company"
+msgstr ""
+
+msgid "Company Name"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare %{oldCommitId}...%{newCommitId}"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare GitLab editions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare branches and continue"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "Compare submodule commit revisions"
+msgstr ""
+
+msgid "Compare with previous version"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "CompareRevisions|Branches"
+msgstr ""
+
+msgid "CompareRevisions|Compare"
+msgstr ""
+
+msgid "CompareRevisions|Create merge request"
+msgstr ""
+
+msgid "CompareRevisions|Filter by Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select branch/tag"
+msgstr ""
+
+msgid "CompareRevisions|Select target project"
+msgstr ""
+
+msgid "CompareRevisions|Swap revisions"
+msgstr ""
+
+msgid "CompareRevisions|Tags"
+msgstr ""
+
+msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|View open merge request"
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Complete verification to sign in."
+msgstr ""
+
+msgid "Complete verification to sign up."
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
+
+msgid "Compliance framework"
+msgstr ""
+
+msgid "Compliance report"
+msgstr ""
+
+msgid "ComplianceFrameworks|Add framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance framework deleted successfully"
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
+msgid "ComplianceFrameworks|Edit framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error deleting the compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Frameworks that have been added will appear here."
+msgstr ""
+
+msgid "ComplianceFrameworks|Invalid format"
+msgstr ""
+
+msgid "ComplianceFrameworks|Name"
+msgstr ""
+
+msgid "ComplianceFrameworks|Name is required"
+msgstr ""
+
+msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
+msgstr ""
+
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
+msgstr ""
+
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgstr ""
+
+msgid "ComplianceFramework|Add a framework to %{linkStart}%{groupName}%{linkEnd} and it will appear here."
+msgstr ""
+
+msgid "ComplianceFramework|Add framework in %{groupName}"
+msgstr ""
+
+msgid "ComplianceFramework|After a framework is added to %{linkStart}%{groupName}%{linkEnd}, it will appear here."
+msgstr ""
+
+msgid "ComplianceFramework|Edit compliance framework"
+msgstr ""
+
+msgid "ComplianceFramework|New compliance framework"
+msgstr ""
+
+msgid "ComplianceFramework|No compliance frameworks are set up yet"
+msgstr ""
+
+msgid "ComplianceReport|Approved by author"
+msgstr ""
+
+msgid "ComplianceReport|Approved by committer"
+msgstr ""
+
+msgid "ComplianceReport|Less than 2 approvers"
+msgstr ""
+
+msgid "ComplianceReport|No violations found"
+msgstr ""
+
+msgid "Component"
+msgstr ""
+
+msgid "Confidence"
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidential issue"
+msgstr ""
+
+msgid "Confidential note"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Configuration help"
+msgstr ""
+
+msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
+msgstr ""
+
+msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and %{housekeeping_link_start}housekeeping%{link_end} on repositories."
+msgstr ""
+
+msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings) to customize Container Scanning settings."
+msgstr ""
+
+msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+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 ""
+
+msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+msgid "Configure Error Tracking"
+msgstr ""
+
+msgid "Configure GitLab"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Integrations"
+msgstr ""
+
+msgid "Configure 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 ""
+
+msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
+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 ""
+
+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 a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
+msgstr ""
+
+msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
+msgstr ""
+
+msgid "Configure existing installation"
+msgstr ""
+
+msgid "Configure pipeline"
+msgstr ""
+
+msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
+msgstr ""
+
+msgid "Configure region"
+msgstr ""
+
+msgid "Configure region for environment"
+msgstr ""
+
+msgid "Configure regions"
+msgstr ""
+
+msgid "Configure repository mirroring."
+msgstr ""
+
+msgid "Configure repository storage."
+msgstr ""
+
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
+msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure specific limits for deprecated API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the default first day of the week and time tracking units."
+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 ""
+
+msgid "Configure with a merge request"
+msgstr ""
+
+msgid "Configure your environments to be deployed to specific geographical regions"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "Confirm approval"
+msgstr ""
+
+msgid "Confirm destroy application"
+msgstr ""
+
+msgid "Confirm new password"
+msgstr ""
+
+msgid "Confirm user"
+msgstr ""
+
+msgid "Confirm your account"
+msgstr ""
+
+msgid "Confirm your email address"
+msgstr ""
+
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
+msgid "Confirmation required"
+msgstr ""
+
+msgid "Confirmed at:"
+msgstr ""
+
+msgid "Confirmed:"
+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 ""
+
+msgid "Conflict: This file was modified in the source branch, but removed in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was removed in the source branch, but modified in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was removed in the source branch, but renamed in the target branch."
+msgstr ""
+
+msgid "Conflict: This file was renamed differently in the source and target branches."
+msgstr ""
+
+msgid "Conflict: This file was renamed in the source branch, but removed in the target branch."
+msgstr ""
+
+msgid "Confluence"
+msgstr ""
+
+msgid "Confluence Cloud Workspace URL"
+msgstr ""
+
+msgid "ConfluenceService|Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
+msgstr ""
+
+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 ""
+
+msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
+msgstr ""
+
+msgid "Congratulations, your free trial is activated."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect a Kubernetes Cluster"
+msgstr ""
+
+msgid "Connect a cluster"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connected"
+msgstr ""
+
+msgid "Connecting"
+msgstr ""
+
+msgid "Connecting to terminal sync service"
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Connection failed"
+msgstr ""
+
+msgid "Connection failure"
+msgstr ""
+
+msgid "Connection timed out"
+msgstr ""
+
+msgid "Consistency guarantee method"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Contacts"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Repository"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container must be a project or a group."
+msgstr ""
+
+msgid "Container registry images"
+msgstr ""
+
+msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
+msgstr ""
+
+msgid "Container repositories"
+msgstr ""
+
+msgid "Container repository"
+msgstr ""
+
+msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
+msgstr ""
+
+msgid "ContainerRegistry|%{count} Image repository"
+msgid_plural "ContainerRegistry|%{count} Image repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{count} Tag"
+msgid_plural "ContainerRegistry|%{count} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
+msgstr ""
+
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
+msgid "ContainerRegistry|Build an image"
+msgstr ""
+
+msgid "ContainerRegistry|CLI Commands"
+msgstr ""
+
+msgid "ContainerRegistry|Clean up image tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup in progress"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup incomplete"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is currently removing tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is disabled for this project"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is ongoing"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup pending"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy for tags is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy successfully saved."
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run soon"
+msgstr ""
+
+msgid "ContainerRegistry|Configuration digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Copy build command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy image path"
+msgstr ""
+
+msgid "ContainerRegistry|Copy login command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy push command"
+msgstr ""
+
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
+msgid "ContainerRegistry|Delete selected tags"
+msgstr ""
+
+msgid "ContainerRegistry|Delete tag"
+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 ""
+
+msgid "ContainerRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "ContainerRegistry|Docker connection error"
+msgstr ""
+
+msgid "ContainerRegistry|Edit cleanup rules"
+msgstr ""
+
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy is disabled."
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy will run in %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|If you are not already logged in, you need to authenticate to the Container Registry by using your GitLab username and password. If you have %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd} instead of a password."
+msgstr ""
+
+msgid "ContainerRegistry|Image repository deletion failed"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository not found"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository will be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
+msgid "ContainerRegistry|Image tags"
+msgstr ""
+
+msgid "ContainerRegistry|Invalid tag: missing manifest digest"
+msgstr ""
+
+msgid "ContainerRegistry|Keep tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep the most recent:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Login"
+msgstr ""
+
+msgid "ContainerRegistry|Manifest digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Next cleanup scheduled to run on:"
+msgstr ""
+
+msgid "ContainerRegistry|Not yet scheduled"
+msgstr ""
+
+msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
+msgstr ""
+
+msgid "ContainerRegistry|Partial cleanup complete"
+msgstr ""
+
+msgid "ContainerRegistry|Please try different search criteria"
+msgstr ""
+
+msgid "ContainerRegistry|Published %{timeInfo}"
+msgstr ""
+
+msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
+msgstr ""
+
+msgid "ContainerRegistry|Push an image"
+msgstr ""
+
+msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgid_plural "ContainerRegistry|Remove tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|Remove tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tags older than:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Run cleanup:"
+msgstr ""
+
+msgid "ContainerRegistry|Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Set cleanup rules"
+msgstr ""
+
+msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
+msgstr ""
+
+msgid "ContainerRegistry|Set up cleanup"
+msgstr ""
+
+msgid "ContainerRegistry|Show full path"
+msgstr ""
+
+msgid "ContainerRegistry|Some tags were not deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the image details."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the repository list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the tags list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "ContainerRegistry|Tag successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The cleanup will continue within %{time}. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The filter returned no results"
+msgstr ""
+
+msgid "ContainerRegistry|The image repository could not be found."
+msgstr ""
+
+msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
+msgstr ""
+
+msgid "ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
+msgstr ""
+
+msgid "ContainerRegistry|The value of this input should be less than 256 characters"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images available in this group"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images stored for this project"
+msgstr ""
+
+msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
+msgstr ""
+
+msgid "ContainerRegistry|This image has no active tags"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository has failed to be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository is scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
+msgstr ""
+
+msgid "ContainerRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
+msgstr ""
+
+msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
+msgstr ""
+
+msgid "Content parsed with %{link}."
+msgstr ""
+
+msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "ContextCommits|Failed to create context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to create/remove context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to delete context commits. Please try again."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue editing"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Analytics"
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{pushes}, more than %{commits} by %{contributors}."
+msgstr ""
+
+msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
+msgstr ""
+
+msgid "ContributionAnalytics|Issues"
+msgstr ""
+
+msgid "ContributionAnalytics|Last 3 months"
+msgstr ""
+
+msgid "ContributionAnalytics|Last month"
+msgstr ""
+
+msgid "ContributionAnalytics|Last week"
+msgstr ""
+
+msgid "ContributionAnalytics|Merge requests"
+msgstr ""
+
+msgid "ContributionAnalytics|No issues for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No merge requests for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No pushes for the selected time period."
+msgstr ""
+
+msgid "Contributions for %{calendar_date}"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributor"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Control emails linked to your account"
+msgstr ""
+
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr ""
+
+msgid "Control how the GitLab Package Registry functions."
+msgstr ""
+
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgstr ""
+
+msgid "Cookie domain"
+msgstr ""
+
+msgid "Copied"
+msgstr ""
+
+msgid "Copied labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy"
+msgstr ""
+
+msgid "Copy %{accessTokenType}"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{name}"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{type}"
+msgstr ""
+
+msgid "Copy ID"
+msgstr ""
+
+msgid "Copy KRB5 clone URL"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy URL"
+msgstr ""
+
+msgid "Copy audio URL"
+msgstr ""
+
+msgid "Copy branch name"
+msgstr ""
+
+msgid "Copy code"
+msgstr ""
+
+msgid "Copy codes"
+msgstr ""
+
+msgid "Copy command"
+msgstr ""
+
+msgid "Copy commands"
+msgstr ""
+
+msgid "Copy commit SHA"
+msgstr ""
+
+msgid "Copy environment"
+msgstr ""
+
+msgid "Copy evidence SHA"
+msgstr ""
+
+msgid "Copy failed. Please manually copy the value."
+msgstr ""
+
+msgid "Copy file contents"
+msgstr ""
+
+msgid "Copy file path"
+msgstr ""
+
+msgid "Copy image URL"
+msgstr ""
+
+msgid "Copy issue URL to clipboard"
+msgstr ""
+
+msgid "Copy key"
+msgstr ""
+
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy link URL"
+msgstr ""
+
+msgid "Copy link to chart"
+msgstr ""
+
+msgid "Copy reference"
+msgstr ""
+
+msgid "Copy secret"
+msgstr ""
+
+msgid "Copy source branch name"
+msgstr ""
+
+msgid "Copy the code below to implement tracking in your application:"
+msgstr ""
+
+msgid "Copy this registration token."
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token"
+msgstr ""
+
+msgid "Copy trigger token"
+msgstr ""
+
+msgid "Copy value"
+msgstr ""
+
+msgid "Copy video URL"
+msgstr ""
+
+msgid "Corpus Management"
+msgstr ""
+
+msgid "Corpus Management|Are you sure you want to delete the corpus?"
+msgstr ""
+
+msgid "CorpusManagement|A corpus is used by fuzz testing to improve coverage. Corpus files can be manually created or auto-generated. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "CorpusManagement|Actions"
+msgstr ""
+
+msgid "CorpusManagement|Corpus file"
+msgstr ""
+
+msgid "CorpusManagement|Corpus files are used in coverage-guided fuzz testing as seed inputs to improve testing."
+msgstr ""
+
+msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Corpus name"
+msgstr ""
+
+msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
+msgstr ""
+
+msgid "CorpusManagement|File too large, Maximum 5 GB"
+msgstr ""
+
+msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
+msgstr ""
+
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
+msgid "CorpusManagement|Last updated"
+msgstr ""
+
+msgid "CorpusManagement|Last used"
+msgstr ""
+
+msgid "CorpusManagement|Latest Job:"
+msgstr ""
+
+msgid "CorpusManagement|Manage your fuzz testing corpus files"
+msgstr ""
+
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|New upload"
+msgstr ""
+
+msgid "CorpusManagement|Not Set"
+msgstr ""
+
+msgid "CorpusManagement|Target"
+msgstr ""
+
+msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
+msgid "Could not add admins as members"
+msgstr ""
+
+msgid "Could not apply %{name} command."
+msgstr ""
+
+msgid "Could not apply %{name} command. %{message}."
+msgstr ""
+
+msgid "Could not authorize chat nickname. Try again!"
+msgstr ""
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
+msgid "Could not commit. An unexpected error occurred."
+msgstr ""
+
+msgid "Could not connect to FogBugz, check your URL"
+msgstr ""
+
+msgid "Could not connect to Sentry. Refresh the page to try again."
+msgstr ""
+
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
+msgid "Could not create Wiki Repository at this time. Please try again later."
+msgstr ""
+
+msgid "Could not create environment"
+msgstr ""
+
+msgid "Could not create group"
+msgstr ""
+
+msgid "Could not create issue"
+msgstr ""
+
+msgid "Could not create project"
+msgstr ""
+
+msgid "Could not create wiki page"
+msgstr ""
+
+msgid "Could not delete chat nickname %{chat_name}."
+msgstr ""
+
+msgid "Could not delete wiki page"
+msgstr ""
+
+msgid "Could not draw the lines for job relationships"
+msgstr ""
+
+msgid "Could not fetch policy because existing policy YAML is invalid"
+msgstr ""
+
+msgid "Could not fetch training providers. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "Could not find design."
+msgstr ""
+
+msgid "Could not find iteration"
+msgstr ""
+
+msgid "Could not get the data properly"
+msgstr ""
+
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not load usage counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+msgstr ""
+
+msgid "Could not revoke access token %{access_token_name}."
+msgstr ""
+
+msgid "Could not revoke impersonation token %{token_name}."
+msgstr ""
+
+msgid "Could not revoke personal access token %{personal_access_token_name}."
+msgstr ""
+
+msgid "Could not save configuration. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "Could not save group ID"
+msgstr ""
+
+msgid "Could not save project ID"
+msgstr ""
+
+msgid "Could not save prometheus manual configuration"
+msgstr ""
+
+msgid "Could not update the LDAP settings"
+msgstr ""
+
+msgid "Could not update wiki page"
+msgstr ""
+
+msgid "Could not upload your designs as one or more files uploaded are not supported."
+msgstr ""
+
+msgid "Couldn't assign policy to project or group"
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create %{workspace} label"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr ""
+
+msgid "Create a Kubernetes cluster"
+msgstr ""
+
+msgid "Create a Mattermost team for this group"
+msgstr ""
+
+msgid "Create a cluster"
+msgstr ""
+
+msgid "Create a group"
+msgstr ""
+
+msgid "Create a merge request"
+msgstr ""
+
+msgid "Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new project"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create a project"
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+msgid "Create an incident. Incidents are created for each alert triggered."
+msgstr ""
+
+msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create commit..."
+msgstr ""
+
+msgid "Create common files more quickly, and standardize their format."
+msgstr ""
+
+msgid "Create confidential merge request"
+msgstr ""
+
+msgid "Create confidential merge request and branch"
+msgstr ""
+
+msgid "Create custom type"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create from"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create issue to resolve all threads"
+msgstr ""
+
+msgid "Create iteration"
+msgstr ""
+
+msgid "Create label"
+msgstr ""
+
+msgid "Create list"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new"
+msgstr ""
+
+msgid "Create new %{name} by email"
+msgstr ""
+
+msgid "Create new Value Stream"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new project"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create one"
+msgstr ""
+
+msgid "Create or close an issue."
+msgstr ""
+
+msgid "Create or import your first project"
+msgstr ""
+
+msgid "Create project"
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create release"
+msgstr ""
+
+msgid "Create requirement"
+msgstr ""
+
+msgid "Create service account"
+msgstr ""
+
+msgid "Create snippet"
+msgstr ""
+
+msgid "Create tag %{tagName}"
+msgstr ""
+
+msgid "Create topic"
+msgstr ""
+
+msgid "Create user"
+msgstr ""
+
+msgid "Create wildcard"
+msgstr ""
+
+msgid "Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "Create your group"
+msgstr ""
+
+msgid "Create, update, or delete a merge request."
+msgstr ""
+
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr ""
+
+msgid "CreateValueStreamForm|Code stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create new Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
+msgstr ""
+
+msgid "CreateValueStreamForm|Edit value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Editing stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter value stream name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Issue stage end"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Plan stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select an end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore defaults"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Save value stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage %{index}"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name already exists"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Update stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Created %{timestamp}"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created On"
+msgstr ""
+
+msgid "Created a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created by %{job}"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created by:"
+msgstr ""
+
+msgid "Created compliance violations if any were found"
+msgstr ""
+
+msgid "Created date"
+msgstr ""
+
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on %{created_at}"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creates a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creating"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
+msgstr ""
+
+msgid "Creation date"
+msgstr ""
+
+msgid "Creator"
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "CredentialsInventory|GPG Keys"
+msgstr ""
+
+msgid "CredentialsInventory|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|Project Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Credit card required to be on file in order to create a pipeline"
+msgstr ""
+
+msgid "Credit card:"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Crm|Active"
+msgstr ""
+
+msgid "Crm|Contact"
+msgstr ""
+
+msgid "Crm|Contact has been added."
+msgstr ""
+
+msgid "Crm|Contact has been updated."
+msgstr ""
+
+msgid "Crm|Customer relations contacts"
+msgstr ""
+
+msgid "Crm|Customer relations organizations"
+msgstr ""
+
+msgid "Crm|Default rate"
+msgstr ""
+
+msgid "Crm|Edit contact"
+msgstr ""
+
+msgid "Crm|Edit organization"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|New organization"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organization"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Organization"
+msgstr ""
+
+msgid "Crm|Organization has been added."
+msgstr ""
+
+msgid "Crm|Organization has been updated."
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crowd"
+msgstr ""
+
+msgid "CsvParser|Failed to render the CSV file for the following reasons:"
+msgstr ""
+
+msgid "CsvParser|Quoted field unterminated"
+msgstr ""
+
+msgid "CsvParser|Too few fields"
+msgstr ""
+
+msgid "CsvParser|Too many fields"
+msgstr ""
+
+msgid "CsvParser|Trailing quote on quoted field is malformed"
+msgstr ""
+
+msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
+msgstr ""
+
+msgid "Current"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current Project"
+msgstr ""
+
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
+msgid "Current node must be the primary node or you will be locking yourself out"
+msgstr ""
+
+msgid "Current password"
+msgstr ""
+
+msgid "Current sign-in IP:"
+msgstr ""
+
+msgid "Current sign-in at:"
+msgstr ""
+
+msgid "Current sign-in ip"
+msgstr ""
+
+msgid "Current vulnerabilities count"
+msgstr ""
+
+msgid "CurrentUser|Buy Pipeline minutes"
+msgstr ""
+
+msgid "CurrentUser|Edit profile"
+msgstr ""
+
+msgid "CurrentUser|One of your groups is running out"
+msgstr ""
+
+msgid "CurrentUser|Preferences"
+msgstr ""
+
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
+
+msgid "Currently unable to fetch data for this pipeline."
+msgstr ""
+
+msgid "Custom (%{language})"
+msgstr ""
+
+msgid "Custom Attributes"
+msgstr ""
+
+msgid "Custom Git clone URL for HTTP(S)"
+msgstr ""
+
+msgid "Custom analyzers: language support"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom metrics"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Custom range"
+msgstr ""
+
+msgid "Custom range (UTC)"
+msgstr ""
+
+msgid "Customer experience improvement and third-party offers"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
+msgid "Customer relations contacts"
+msgstr ""
+
+msgid "Customer relations organizations"
+msgstr ""
+
+msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize icon"
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize name"
+msgstr ""
+
+msgid "Customize your pipeline configuration."
+msgstr ""
+
+msgid "Cycle Time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first commit time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first deployed to production"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build finish time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build start time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request merged"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Total"
+msgstr ""
+
+msgid "CycleAnalyticsStage|is not available for the selected group"
+msgstr ""
+
+msgid "CycleAnalyticsStage|should be under a group"
+msgstr ""
+
+msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
+msgstr ""
+
+msgid "CycleAnalytics|'%{name}' is collecting the data. This can take a few minutes."
+msgstr ""
+
+msgid "CycleAnalytics|Average time to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Average time to completion (days)"
+msgstr ""
+
+msgid "CycleAnalytics|Change Failure Rate"
+msgstr ""
+
+msgid "CycleAnalytics|Create a custom value stream to view metrics about stages specific to your development process. Use your value stream to visualize your DevSecOps lifecycle, determine the velocity of your group, and identify inefficient processes."
+msgstr ""
+
+msgid "CycleAnalytics|Create a custom value stream…"
+msgstr ""
+
+msgid "CycleAnalytics|Custom value streams to measure your DevSecOps lifecycle"
+msgstr ""
+
+msgid "CycleAnalytics|Data is collecting and loading."
+msgstr ""
+
+msgid "CycleAnalytics|Date"
+msgstr ""
+
+msgid "CycleAnalytics|Display chart filters"
+msgstr ""
+
+msgid "CycleAnalytics|If you have recently upgraded to GitLab Premium, it can take up to 30 minutes for data to collect and display."
+msgstr ""
+
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
+msgid "CycleAnalytics|Number of tasks"
+msgstr ""
+
+msgid "CycleAnalytics|Only %{maxLabels} labels can be selected at this time"
+msgstr ""
+
+msgid "CycleAnalytics|Project selected"
+msgid_plural "CycleAnalytics|%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CycleAnalytics|Select labels"
+msgstr ""
+
+msgid "CycleAnalytics|Show"
+msgstr ""
+
+msgid "CycleAnalytics|Stage time: %{title}"
+msgstr ""
+
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
+msgid "CycleAnalytics|The average time items spent in this stage. Data limited to items completed within this date range."
+msgstr ""
+
+msgid "CycleAnalytics|The given date range is larger than 180 days"
+msgstr ""
+
+msgid "CycleAnalytics|The total time items spent across each value stream stage. Data limited to items completed within this date range."
+msgstr ""
+
+msgid "CycleAnalytics|There is no data for 'Stage time' available. Adjust the current filters."
+msgstr ""
+
+msgid "CycleAnalytics|There is no data for 'Total time' available. Adjust the current filters."
+msgstr ""
+
+msgid "CycleAnalytics|Time to Restore Service"
+msgstr ""
+
+msgid "CycleAnalytics|Total time"
+msgstr ""
+
+msgid "CycleAnalytics|group dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|not allowed for the given start event"
+msgstr ""
+
+msgid "CycleAnalytics|project dropdown filter"
+msgstr ""
+
+msgid "DAG visualization requires at least 3 dependent jobs."
+msgstr ""
+
+msgid "DAST Configuration"
+msgstr ""
+
+msgid "DAST configuration not found"
+msgstr ""
+
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
+msgid "DAST profiles"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "DORA4Metrics|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "DORA4Metrics|Average (last %{days}d)"
+msgstr ""
+
+msgid "DORA4Metrics|Change failure rate"
+msgstr ""
+
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
+msgid "DORA4Metrics|Date"
+msgstr ""
+
+msgid "DORA4Metrics|Days for an open incident"
+msgstr ""
+
+msgid "DORA4Metrics|Days from merge to deploy"
+msgstr ""
+
+msgid "DORA4Metrics|Deployment frequency"
+msgstr ""
+
+msgid "DORA4Metrics|Lead time for changes"
+msgstr ""
+
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
+msgid "DORA4Metrics|Median (last %{days}d)"
+msgstr ""
+
+msgid "DORA4Metrics|Median time (last %{days}d)"
+msgstr ""
+
+msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
+msgstr ""
+
+msgid "DORA4Metrics|No incidents during this period"
+msgstr ""
+
+msgid "DORA4Metrics|No merge requests were deployed during this period"
+msgstr ""
+
+msgid "DORA4Metrics|Number of deployments"
+msgstr ""
+
+msgid "DORA4Metrics|Number of incidents divided by the number of deployments to a production environment in the given time period."
+msgstr ""
+
+msgid "DORA4Metrics|Percentage of failed deployments"
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting lead time data."
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting time to restore service 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 ""
+
+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 "DORA4Metrics|Time to restore service"
+msgstr ""
+
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
+msgid "DSN"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "Dashboard uid not found"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "DashboardProjects|Trending"
+msgstr ""
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+msgstr ""
+
+msgid "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 ""
+
+msgid "DastConfig|DAST CI/CD configuration"
+msgstr ""
+
+msgid "DastConfig|Enable DAST to automatically test for vulnerabilities in your project's running application, website, or API, in the CI/CD pipeline. Configuration changes must be applied to your .gitlab-ci.yml file to take effect. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "DastConfig|Enabled"
+msgstr ""
+
+msgid "DastConfig|Generate code snippet"
+msgstr ""
+
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr ""
+
+msgid "DastConfig|No previous scans found for this project"
+msgstr ""
+
+msgid "DastConfig|Not enabled"
+msgstr ""
+
+msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|API"
+msgstr ""
+
+msgid "DastProfiles|API endpoint URL"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
+msgid "DastProfiles|Additional request headers (optional)"
+msgstr ""
+
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Attacks the target to find potential vulnerabilities. Active scans are potentially harmful to the site being scanned."
+msgstr ""
+
+msgid "DastProfiles|Authentication"
+msgstr ""
+
+msgid "DastProfiles|Authentication URL"
+msgstr ""
+
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
+msgid "DastProfiles|Change scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Change site profile"
+msgstr ""
+
+msgid "DastProfiles|Choose a scan method"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not create the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not update the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not update the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|DAST profile library"
+msgstr ""
+
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
+msgid "DastProfiles|Edit scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Edit site profile"
+msgstr ""
+
+msgid "DastProfiles|Enable Authentication"
+msgstr ""
+
+msgid "DastProfiles|Enable Basic Authentication"
+msgstr ""
+
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Error Details"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (optional)"
+msgstr ""
+
+msgid "DastProfiles|Excluded paths"
+msgstr ""
+
+msgid "DastProfiles|Excluded paths (optional)"
+msgstr ""
+
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
+msgid "DastProfiles|Manage %{profileType} profiles"
+msgstr ""
+
+msgid "DastProfiles|Manage profiles"
+msgstr ""
+
+msgid "DastProfiles|Manage site profiles"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|Monitors all HTTP requests sent to the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
+msgstr ""
+
+msgid "DastProfiles|New site profile"
+msgstr ""
+
+msgid "DastProfiles|No scanner profile selected"
+msgstr ""
+
+msgid "DastProfiles|No scanner profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|No site profile selected"
+msgstr ""
+
+msgid "DastProfiles|No site profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|Not Validated"
+msgstr ""
+
+msgid "DastProfiles|Passive"
+msgstr ""
+
+msgid "DastProfiles|Password"
+msgstr ""
+
+msgid "DastProfiles|Password form field"
+msgstr ""
+
+msgid "DastProfiles|Profile in use and cannot be renamed"
+msgstr ""
+
+msgid "DastProfiles|Profile is being used by this on-demand scan"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
+msgid "DastProfiles|Request headers"
+msgstr ""
+
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
+msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
+msgstr ""
+
+msgid "DastProfiles|Save profile"
+msgstr ""
+
+msgid "DastProfiles|Scan method"
+msgstr ""
+
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
+msgid "DastProfiles|Scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner profiles"
+msgstr ""
+
+msgid "DastProfiles|Select a scanner profile to run a DAST scan"
+msgstr ""
+
+msgid "DastProfiles|Select a site profile to run a DAST scan"
+msgstr ""
+
+msgid "DastProfiles|Select branch"
+msgstr ""
+
+msgid "DastProfiles|Select scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Select site profile"
+msgstr ""
+
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
+msgid "DastProfiles|Site name"
+msgstr ""
+
+msgid "DastProfiles|Site profile"
+msgstr ""
+
+msgid "DastProfiles|Site profiles"
+msgstr ""
+
+msgid "DastProfiles|Site type"
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Submit button"
+msgstr ""
+
+msgid "DastProfiles|Submit button (optional)"
+msgstr ""
+
+msgid "DastProfiles|Target URL"
+msgstr ""
+
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|URL"
+msgstr ""
+
+msgid "DastProfiles|URLs to skip during the authenticated scan."
+msgstr ""
+
+msgid "DastProfiles|Username"
+msgstr ""
+
+msgid "DastProfiles|Username form field"
+msgstr ""
+
+msgid "DastProfiles|Validated"
+msgstr ""
+
+msgid "DastProfiles|Validation status"
+msgstr ""
+
+msgid "DastProfiles|Website"
+msgstr ""
+
+msgid "DastProfiles|What does each method do?"
+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 ""
+
+msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
+msgstr ""
+
+msgid "DastProfiles|https://example.com/dast_example.har"
+msgstr ""
+
+msgid "DastProfiles|https://example.com/openapi.json"
+msgstr ""
+
+msgid "DastProfiles|https://example.com/postman_collection.json"
+msgstr ""
+
+msgid "DastSiteValidation|Copy HTTP header to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Copy Meta tag to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Could not create validation token. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Could not revoke validation. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Download validation text file"
+msgstr ""
+
+msgid "DastSiteValidation|Header validation"
+msgstr ""
+
+msgid "DastSiteValidation|Meta tag validation"
+msgstr ""
+
+msgid "DastSiteValidation|Not validated"
+msgstr ""
+
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
+msgid "DastSiteValidation|Revoke validation"
+msgstr ""
+
+msgid "DastSiteValidation|Step 1 - Choose site validation method."
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add the following HTTP header to your site."
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add the following meta tag to your site."
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Download the following text file, then upload it to the target site."
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm header location."
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm meta tag location."
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm text file location."
+msgstr ""
+
+msgid "DastSiteValidation|Text file validation"
+msgstr ""
+
+msgid "DastSiteValidation|The validation has failed. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|The validation is in progress. Please wait..."
+msgstr ""
+
+msgid "DastSiteValidation|This will affect %d other profile targeting the same URL."
+msgid_plural "DastSiteValidation|This will affect %d other profiles targeting the same URL."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "DastSiteValidation|To run an active scan, validate your site. Site profile validation reduces the risk of running an active scan against the wrong website. All site profiles that share the same base URL share the same validation status."
+msgstr ""
+
+msgid "DastSiteValidation|Validate"
+msgstr ""
+
+msgid "DastSiteValidation|Validate site"
+msgstr ""
+
+msgid "DastSiteValidation|Validated"
+msgstr ""
+
+msgid "DastSiteValidation|Validating..."
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed"
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
+msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
+msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Data refresh"
+msgstr ""
+
+msgid "Data type"
+msgstr ""
+
+msgid "Database update failed"
+msgstr ""
+
+msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
+msgstr ""
+
+msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
+msgstr ""
+
+msgid "DatadogIntegration|API URL"
+msgstr ""
+
+msgid "DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}"
+msgstr ""
+
+msgid "DatadogIntegration|Environment"
+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 ""
+
+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 ""
+
+msgid "DatadogIntegration|Service"
+msgstr ""
+
+msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments."
+msgstr ""
+
+msgid "DatadogIntegration|Tags"
+msgstr ""
+
+msgid "DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}."
+msgstr ""
+
+msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
+msgstr ""
+
+msgid "DatadogIntegration|have an invalid format"
+msgstr ""
+
+msgid "Datasource name not found"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Date merged"
+msgstr ""
+
+msgid "Date range"
+msgstr ""
+
+msgid "Date range limited to %{number} days"
+msgstr ""
+
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
+msgid "Day of month"
+msgstr ""
+
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
+msgid "Days"
+msgstr ""
+
+msgid "Days to merge"
+msgstr ""
+
+msgid "Deactivate dormant users after a period of inactivity"
+msgstr ""
+
+msgid "Dear Administrator,"
+msgstr ""
+
+msgid "Debian package already exists in Distribution"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Decompressed archive size validation failed."
+msgstr ""
+
+msgid "Decrease"
+msgstr ""
+
+msgid "Default CI/CD configuration file"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default description template for issues"
+msgstr ""
+
+msgid "Default description template for merge requests"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default projects limit"
+msgstr ""
+
+msgid "Default timeout"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "DefaultBranchLabel|default"
+msgstr ""
+
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+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 ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define custom rules for what constitutes spam, independent of Akismet"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
+msgstr ""
+
+msgid "Define how approval rules are applied to merge requests."
+msgstr ""
+
+msgid "Define rules for who can push, merge, and the required approvals for each branch."
+msgstr ""
+
+msgid "Definition"
+msgstr ""
+
+msgid "Delay 2FA enforcement (hours)"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Run the delayed job now?"
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete %{issuableType}"
+msgstr ""
+
+msgid "Delete %{name}"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete File"
+msgstr ""
+
+msgid "Delete Key"
+msgstr ""
+
+msgid "Delete Selected"
+msgstr ""
+
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete asset"
+msgstr ""
+
+msgid "Delete audio"
+msgstr ""
+
+msgid "Delete badge"
+msgstr ""
+
+msgid "Delete code block"
+msgstr ""
+
+msgid "Delete column"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete corpus"
+msgstr ""
+
+msgid "Delete deploy key"
+msgstr ""
+
+msgid "Delete epic"
+msgstr ""
+
+msgid "Delete file"
+msgstr ""
+
+msgid "Delete identity"
+msgstr ""
+
+msgid "Delete image"
+msgstr ""
+
+msgid "Delete image repository"
+msgstr ""
+
+msgid "Delete internal note"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{labelName}"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete pipeline schedule"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
+msgid "Delete row"
+msgstr ""
+
+msgid "Delete self monitoring project"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete source branch when merge request is accepted."
+msgstr ""
+
+msgid "Delete subscription"
+msgstr ""
+
+msgid "Delete table"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete this epic and all descendants?"
+msgstr ""
+
+msgid "Delete this project"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+msgstr ""
+
+msgid "Delete video"
+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 ""
+
+msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove webhooks. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteRelease|Are you sure you want to delete this release?"
+msgstr ""
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr ""
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr ""
+
+msgid "DeleteValueStream|'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
+msgstr ""
+
+msgid "DeleteValueStream|Delete %{name}"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deleted chat nickname: %{chat_name}!"
+msgstr ""
+
+msgid "Deleted commits:"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
+
+msgid "Deleted the source branch."
+msgstr ""
+
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deleting"
+msgstr ""
+
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "Deleting the project will delete its repository and all related resources, including issues and merge requests."
+msgstr ""
+
+msgid "Deletion pending. This project will be deleted on %{date}. Repository and other project resources are read-only."
+msgstr ""
+
+msgid "DeletionSettings|All projects are deleted immediately."
+msgstr ""
+
+msgid "DeletionSettings|Deletion protection"
+msgstr ""
+
+msgid "DeletionSettings|Keep deleted"
+msgstr ""
+
+msgid "DeletionSettings|Keep deleted projects for %{number} days"
+msgstr ""
+
+msgid "DeletionSettings|Keep deleted projects for 1 day"
+msgstr ""
+
+msgid "DeletionSettings|None, delete immediately"
+msgstr ""
+
+msgid "DeletionSettings|Only administrators can delete projects."
+msgstr ""
+
+msgid "DeletionSettings|Owners and administrators can delete projects."
+msgstr ""
+
+msgid "DeletionSettings|Retention period that deleted groups and projects will remain restorable. Personal projects are always deleted immediately. Some groups can opt-out their projects."
+msgstr ""
+
+msgid "Denied"
+msgstr ""
+
+msgid "Denied authorization of chat nickname %{user_name}."
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny access request"
+msgstr ""
+
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies help page link"
+msgstr ""
+
+msgid "Dependencies|%d additional vulnerability not shown"
+msgid_plural "Dependencies|%d additional vulnerabilities not shown"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d vulnerability detected"
+msgid_plural "Dependencies|%d vulnerabilities detected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%{remainingLicensesCount} more"
+msgstr ""
+
+msgid "Dependencies|(top level)"
+msgstr ""
+
+msgid "Dependencies|All"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Dependency path"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Learn more about dependency paths"
+msgstr ""
+
+msgid "Dependencies|License"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Location and dependency path"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|Software Bill of Materials (SBOM) based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
+msgstr ""
+
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
+msgid "Dependencies|Toggle vulnerability list"
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Vulnerable components"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency List has no entries"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency Scanning"
+msgstr ""
+
+msgid "Dependency list"
+msgstr ""
+
+msgid "DependencyProxy|All items in the cache are scheduled for removal."
+msgstr ""
+
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
+
+msgid "DependencyProxy|Clear cache"
+msgstr ""
+
+msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
+msgstr ""
+
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
+
+msgid "DependencyProxy|Copy prefix"
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|Scheduled for deletion"
+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] ""
+msgstr[1] ""
+
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Key"
+msgstr ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "Deploy Token"
+msgstr ""
+
+msgid "Deploy container based web apps on Google managed clusters"
+msgstr ""
+
+msgid "Deploy freezes"
+msgstr ""
+
+msgid "Deploy key was successfully updated."
+msgstr ""
+
+msgid "Deploy keys"
+msgstr ""
+
+msgid "Deploy keys grant read/write access to all repositories in your instance"
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy static assets and resources to Google managed CDN"
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployBoards|To see deployment progress for your environments, make sure you are deploying to %{codeStart}$KUBE_NAMESPACE%{codeEnd} and annotating with %{codeStart}app.gitlab.com/app=$CI_PROJECT_PATH_SLUG%{codeEnd} and %{codeStart}app.gitlab.com/env=$CI_ENVIRONMENT_SLUG%{codeEnd}."
+msgstr ""
+
+msgid "DeployBoard|Kubernetes Pods"
+msgstr ""
+
+msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
+msgstr ""
+
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Delete"
+msgstr ""
+
+msgid "DeployFreeze|Delete deploy freeze?"
+msgstr ""
+
+msgid "DeployFreeze|Delete freeze period"
+msgstr ""
+
+msgid "DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Grant write permissions to this key"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows read and write access to the package registry."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the package registry."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository."
+msgstr ""
+
+msgid "DeployTokens|Allows write access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+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 ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+msgstr ""
+
+msgid "DeployTokens|Enter a unique name for your deploy token."
+msgstr ""
+
+msgid "DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}."
+msgstr ""
+
+msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
+msgstr ""
+
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|New deploy token"
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
+msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new Deploy Token username"
+msgstr ""
+
+msgid "DeployTokens|Your new group deploy token has been created."
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deploying to AWS is easy with GitLab"
+msgstr ""
+
+msgid "Deployment"
+msgstr ""
+
+msgid "Deployment Frequency"
+msgstr ""
+
+msgid "Deployment Target|%{linkStart}How to provision or deploy to Kubernetes clusters from GitLab?%{linkEnd}"
+msgstr ""
+
+msgid "Deployment Target|Project deployment target (optional)"
+msgstr ""
+
+msgid "Deployment Target|Select the deployment target"
+msgstr ""
+
+msgid "Deployment frequency"
+msgstr ""
+
+msgid "DeploymentApproval| Current approvals: %{current}"
+msgstr ""
+
+msgid "DeploymentApproval|Approval options"
+msgstr ""
+
+msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
+msgstr ""
+
+msgid "DeploymentApproval|Approved %{time}"
+msgstr ""
+
+msgid "DeploymentApproval|Approved by you %{time}"
+msgstr ""
+
+msgid "DeploymentApproval|Approving will run the manual job from deployment #%{deploymentIid}. Rejecting will fail the manual job."
+msgstr ""
+
+msgid "DeploymentApproval|Deployment tier: %{tier}"
+msgstr ""
+
+msgid "DeploymentApproval|Environment: %{environment}"
+msgstr ""
+
+msgid "DeploymentApproval|Manual job: %{jobName}"
+msgstr ""
+
+msgid "DeploymentApproval|Rejected %{time}"
+msgstr ""
+
+msgid "DeploymentApproval|Rejected by you %{time}"
+msgstr ""
+
+msgid "DeploymentTarget|GitLab Pages"
+msgstr ""
+
+msgid "DeploymentTarget|Heroku"
+msgstr ""
+
+msgid "DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)"
+msgstr ""
+
+msgid "DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)"
+msgstr ""
+
+msgid "DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)"
+msgstr ""
+
+msgid "DeploymentTarget|Mobile app store"
+msgstr ""
+
+msgid "DeploymentTarget|No deployment planned"
+msgstr ""
+
+msgid "DeploymentTarget|Other hosting service"
+msgstr ""
+
+msgid "DeploymentTarget|Registry (package or container)"
+msgstr ""
+
+msgid "DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)"
+msgstr ""
+
+msgid "DeploymentTarget|Serverless backend (Lambda, Cloud functions)"
+msgstr ""
+
+msgid "DeploymentTarget|Virtual machine (for example, EC2)"
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
+msgid "Deployments|%{deployments} environment impacted."
+msgid_plural "Deployments|%{deployments} environments impacted."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deployment|API"
+msgstr ""
+
+msgid "Deployment|Cancelled"
+msgstr ""
+
+msgid "Deployment|Created"
+msgstr ""
+
+msgid "Deployment|Deployment ID"
+msgstr ""
+
+msgid "Deployment|Failed"
+msgstr ""
+
+msgid "Deployment|Latest Deployed"
+msgstr ""
+
+msgid "Deployment|Needs Approval"
+msgstr ""
+
+msgid "Deployment|Running"
+msgstr ""
+
+msgid "Deployment|Skipped"
+msgstr ""
+
+msgid "Deployment|Success"
+msgstr ""
+
+msgid "Deployment|This deployment was created using the API"
+msgstr ""
+
+msgid "Deployment|Triggerer"
+msgstr ""
+
+msgid "Deployment|Waiting"
+msgstr ""
+
+msgid "Deployment|blocked"
+msgstr ""
+
+msgid "Deployment|canceled"
+msgstr ""
+
+msgid "Deployment|created"
+msgstr ""
+
+msgid "Deployment|failed"
+msgstr ""
+
+msgid "Deployment|running"
+msgstr ""
+
+msgid "Deployment|skipped"
+msgstr ""
+
+msgid "Deployment|success"
+msgstr ""
+
+msgid "Deprecated API rate limits"
+msgstr ""
+
+msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
+msgstr ""
+
+msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Describe the goal of the changes and what reviewers should be aware of."
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description (alt text)"
+msgstr ""
+
+msgid "Description (optional)"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Design Management files and data"
+msgstr ""
+
+msgid "Design repositories"
+msgstr ""
+
+msgid "Design repository"
+msgstr ""
+
+msgid "DesignManagement|%{current_design} of %{designs_count}"
+msgstr ""
+
+msgid "DesignManagement|%{filename} did not change."
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
+msgstr ""
+
+msgid "DesignManagement|Archive design"
+msgstr ""
+
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
+
+msgid "DesignManagement|Comment"
+msgstr ""
+
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
+msgid "DesignManagement|Could not add a new comment. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not create new discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update note. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Deselect all"
+msgstr ""
+
+msgid "DesignManagement|Designs"
+msgstr ""
+
+msgid "DesignManagement|Discard changes"
+msgstr ""
+
+msgid "DesignManagement|Discussion"
+msgstr ""
+
+msgid "DesignManagement|Download design"
+msgstr ""
+
+msgid "DesignManagement|Error uploading a new design. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Go back to designs"
+msgstr ""
+
+msgid "DesignManagement|Go to next design"
+msgstr ""
+
+msgid "DesignManagement|Go to previous design"
+msgstr ""
+
+msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
+msgstr ""
+
+msgid "DesignManagement|Resolve thread"
+msgstr ""
+
+msgid "DesignManagement|Resolved Comments"
+msgstr ""
+
+msgid "DesignManagement|Save comment"
+msgstr ""
+
+msgid "DesignManagement|Select all"
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
+msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
+msgstr ""
+
+msgid "DesignManagement|To upload designs, you'll need to enable LFS and have an admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+msgstr ""
+
+msgid "DesignManagement|Unresolve thread"
+msgstr ""
+
+msgid "DesignManagement|Upload designs"
+msgstr ""
+
+msgid "DesignManagement|Upload skipped. %{reason}"
+msgstr ""
+
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Details block"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps Adoption"
+msgstr ""
+
+msgid "DevOps Reports"
+msgstr ""
+
+msgid "DevOps adoption"
+msgstr ""
+
+msgid "Development"
+msgstr ""
+
+msgid "Devices (optional)"
+msgstr ""
+
+msgid "DevopsAdoption|%{adoptedCount}/%{featuresCount} %{title} features adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Add a group to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Add or remove groups"
+msgstr ""
+
+msgid "DevopsAdoption|Add or remove subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption by group"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption by subgroup"
+msgstr ""
+
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
+msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on a merge request"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
+msgstr ""
+
+msgid "DevopsAdoption|At least one issue created"
+msgstr ""
+
+msgid "DevopsAdoption|At least one merge request created"
+msgstr ""
+
+msgid "DevopsAdoption|At least one pipeline successfully run"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Confirm remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|DAST"
+msgstr ""
+
+msgid "DevopsAdoption|DAST enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Dependency Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Deploys"
+msgstr ""
+
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
+msgstr ""
+
+msgid "DevopsAdoption|Edit groups"
+msgstr ""
+
+msgid "DevopsAdoption|Edit subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Feature adoption is based on usage in the previous calendar month. Data is updated at the beginning of each month. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsAdoption|Fuzz Testing"
+msgstr ""
+
+msgid "DevopsAdoption|Fuzz Testing enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|No results…"
+msgstr ""
+
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
+msgid "DevopsAdoption|Not adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
+msgid "DevopsAdoption|Overall adoption"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group from the table."
+msgstr ""
+
+msgid "DevopsAdoption|Runner configured for project/group"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|SAST"
+msgstr ""
+
+msgid "DevopsAdoption|SAST enabled for at least one project"
+msgstr ""
+
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
+msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|This group has no subgroups"
+msgstr ""
+
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
+msgid "DevopsAdoption|You cannot remove the group you are currently in."
+msgstr ""
+
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsReport|High"
+msgstr ""
+
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
+msgstr ""
+
+msgid "DevopsReport|Overview"
+msgstr ""
+
+msgid "DevopsReport|Score"
+msgstr ""
+
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
+msgid "Diagram (%{language})"
+msgstr ""
+
+msgid "Did not delete the source branch."
+msgstr ""
+
+msgid "Didn't receive a confirmation email?"
+msgstr ""
+
+msgid "Didn't receive confirmation instructions?"
+msgstr ""
+
+msgid "Didn't receive unlock instructions?"
+msgstr ""
+
+msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diff notes"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|%d addition"
+msgid_plural "Diffs|%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|%d deletion"
+msgid_plural "Diffs|%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|Expand all lines"
+msgstr ""
+
+msgid "Diffs|Next 20 lines"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Previous 20 lines"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
+msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Diffs|with %{additions} and %{deletions}"
+msgstr ""
+
+msgid "Direct member"
+msgstr ""
+
+msgid "Direct members"
+msgstr ""
+
+msgid "Direct non-authenticated users to this page."
+msgstr ""
+
+msgid "Direct users to this page after they sign out."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable Two-factor Authentication"
+msgstr ""
+
+msgid "Disable What's new"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group runners"
+msgstr ""
+
+msgid "Disable two-factor authentication"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Send notifications about project events to a Discord channel."
+msgstr ""
+
+msgid "Discover"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
+msgstr ""
+
+msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
+msgstr ""
+
+msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
+msgstr ""
+
+msgid "Discover|Start a free trial"
+msgstr ""
+
+msgid "Discover|Upgrade now"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question internally that needs to be resolved."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question internally."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question."
+msgstr ""
+
+msgid "Discussion to reply to cannot be found"
+msgstr ""
+
+msgid "Disk Usage"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss %d selected vulnerability as"
+msgid_plural "Dismiss %d selected vulnerabilities as"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dismiss Alert"
+msgstr ""
+
+msgid "Dismiss merge request promotion"
+msgstr ""
+
+msgid "Dismiss selected"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Dismissable"
+msgstr ""
+
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
+msgid "Display"
+msgstr ""
+
+msgid "Display alerts from all configured monitoring tools."
+msgstr ""
+
+msgid "Display milestones"
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display progress of child issues"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Display time tracking in issues in total hours only. %{link_start}What is time tracking?%{link_end}"
+msgstr ""
+
+msgid "Do not display content for customer experience improvement and offers from third parties"
+msgstr ""
+
+msgid "Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}"
+msgstr ""
+
+msgid "Do you want to remove this deploy key?"
+msgstr ""
+
+msgid "Dockerfile"
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Documentation pages URL"
+msgstr ""
+
+msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Domain Name"
+msgstr ""
+
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
+msgid "Don't have a group?"
+msgstr ""
+
+msgid "Don't have an account yet?"
+msgstr ""
+
+msgid "Don't include description in commit message"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
+msgid "Don't send service data"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Dormant users"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download (%{fileSizeReadable})"
+msgstr ""
+
+msgid "Download (%{size})"
+msgstr ""
+
+msgid "Download CSV"
+msgstr ""
+
+msgid "Download PDF"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download codes"
+msgstr ""
+
+msgid "Download evidence JSON"
+msgstr ""
+
+msgid "Download export"
+msgstr ""
+
+msgid "Download image"
+msgstr ""
+
+msgid "Download payload"
+msgstr ""
+
+msgid "Download raw data (.csv)"
+msgstr ""
+
+msgid "Download source code"
+msgstr ""
+
+msgid "Download this directory"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Draft"
+msgstr ""
+
+msgid "Draft: %{filename}"
+msgstr ""
+
+msgid "Drag to reorder prioritized labels and change their relative priority."
+msgstr ""
+
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
+msgstr ""
+
+msgid "Drop your designs to start your upload."
+msgstr ""
+
+msgid "Drop your files to start your upload."
+msgstr ""
+
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Cancel"
+msgstr ""
+
+msgid "DropdownWidget|Edit %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
+msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
+msgstr ""
+
+msgid "DropdownWidget|You don't have permission to view this %{issuableAttribute}."
+msgstr ""
+
+msgid "Due Date"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "Due to inactivity, the %{project_link} project is scheduled to be deleted on %{b_open}%{deletion_date}%{b_close}. To unschedule the deletion of %{project_link}, perform some activity on it. For example:"
+msgstr ""
+
+msgid "Due to inactivity, the %{project_name} (%{project_link}) project is scheduled to be deleted on %{deletion_date}. To unschedule the deletion of %{project_name}, perform some activity on it. For example:"
+msgstr ""
+
+msgid "Due to inactivity, this project is scheduled to be deleted on %{deletion_date}. %{link_start}Why is this scheduled?%{link_end}"
+msgstr ""
+
+msgid "Duplicate page: %{error_message}"
+msgstr ""
+
+msgid "Duration"
+msgstr ""
+
+msgid "Duration (min)"
+msgstr ""
+
+msgid "Duration|%s days"
+msgstr ""
+
+msgid "Duration|%s hours"
+msgstr ""
+
+msgid "Duration|%s minutes"
+msgstr ""
+
+msgid "Duration|%s months"
+msgstr ""
+
+msgid "Duration|%s seconds"
+msgstr ""
+
+msgid "Duration|%s weeks"
+msgstr ""
+
+msgid "Duration|%s years"
+msgstr ""
+
+msgid "Duration|1 day"
+msgstr ""
+
+msgid "Duration|1 hour"
+msgstr ""
+
+msgid "Duration|1 minute"
+msgstr ""
+
+msgid "Duration|1 month"
+msgstr ""
+
+msgid "Duration|1 week"
+msgstr ""
+
+msgid "Duration|1 year"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "E-mail:"
+msgstr ""
+
+msgid "Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit %{profileType} profile"
+msgstr ""
+
+msgid "Edit Comment"
+msgstr ""
+
+msgid "Edit Deploy Key"
+msgstr ""
+
+msgid "Edit Geo Site"
+msgstr ""
+
+msgid "Edit Group Hook"
+msgstr ""
+
+msgid "Edit Identity"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Password"
+msgstr ""
+
+msgid "Edit Pipeline Schedule"
+msgstr ""
+
+msgid "Edit Release"
+msgstr ""
+
+msgid "Edit Requirement"
+msgstr ""
+
+msgid "Edit Slack integration"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit System Hook"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit audio description"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit commit message"
+msgstr ""
+
+msgid "Edit deploy freeze"
+msgstr ""
+
+msgid "Edit deploy key"
+msgstr ""
+
+msgid "Edit description"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit epics"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit fork in Web IDE"
+msgstr ""
+
+msgid "Edit group application"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit image description"
+msgstr ""
+
+msgid "Edit in pipeline editor"
+msgstr ""
+
+msgid "Edit in single-file editor"
+msgstr ""
+
+msgid "Edit inline"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Edit link"
+msgstr ""
+
+msgid "Edit merge requests"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit sidebar"
+msgstr ""
+
+msgid "Edit table"
+msgstr ""
+
+msgid "Edit this file only."
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit title and description"
+msgstr ""
+
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
+msgid "Edit user: %{user_name}"
+msgstr ""
+
+msgid "Edit video description"
+msgstr ""
+
+msgid "Edit wiki page"
+msgstr ""
+
+msgid "Edit your most recent comment in a thread (from an empty textarea)"
+msgstr ""
+
+msgid "Edit your search and try again"
+msgstr ""
+
+msgid "Edit your search filter and try again."
+msgstr ""
+
+msgid "Edit, lint, and visualize your pipeline."
+msgstr ""
+
+msgid "Edited"
+msgstr ""
+
+msgid "Edited %{timeago}"
+msgstr ""
+
+msgid "Editing"
+msgstr ""
+
+msgid "Elapsed time"
+msgstr ""
+
+msgid "Elasticsearch HTTP client timeout value in seconds."
+msgstr ""
+
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
+msgid "Elasticsearch migration halted"
+msgstr ""
+
+msgid "Elasticsearch reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email a new %{name} to this project"
+msgstr ""
+
+msgid "Email address suffix"
+msgstr ""
+
+msgid "Email address to use for Support Desk"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+msgstr ""
+
+msgid "Email not verified. Please verify your email in Salesforce."
+msgstr ""
+
+msgid "Email notification for unknown sign-ins"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Email patches"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipeline status to a list of recipients."
+msgstr ""
+
+msgid "Email updates (optional)"
+msgstr ""
+
+msgid "Email:"
+msgstr ""
+
+msgid "Email: %{email}"
+msgstr ""
+
+msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
+msgstr ""
+
+msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't find the project. Please check if there's any typo."
+msgstr ""
+
+msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|and %{moreCount} more"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Emails sent to %{email} are also supported."
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace."
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains})."
+msgstr ""
+
+msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Akismet"
+msgstr ""
+
+msgid "Enable Amazon EKS integration"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable GitLab Error Tracking"
+msgstr ""
+
+msgid "Enable GitLab Prometheus metrics endpoint"
+msgstr ""
+
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
+msgid "Enable Kroki"
+msgstr ""
+
+msgid "Enable Mailgun event receiver"
+msgstr ""
+
+msgid "Enable PlantUML"
+msgstr ""
+
+msgid "Enable SSL verification"
+msgstr ""
+
+msgid "Enable Sentry error tracking"
+msgstr ""
+
+msgid "Enable Snowplow tracking"
+msgstr ""
+
+msgid "Enable Spam Check via external API endpoint"
+msgstr ""
+
+msgid "Enable What's new: All tiers"
+msgstr ""
+
+msgid "Enable What's new: Current tier only"
+msgstr ""
+
+msgid "Enable access to the performance bar for non-administrators in a given group."
+msgstr ""
+
+msgid "Enable admin mode"
+msgstr ""
+
+msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Enable authenticated API request rate limit"
+msgstr ""
+
+msgid "Enable authenticated Git LFS request rate limit"
+msgstr ""
+
+msgid "Enable authenticated web request rate limit"
+msgstr ""
+
+msgid "Enable authentication"
+msgstr ""
+
+msgid "Enable automatic repository housekeeping"
+msgstr ""
+
+msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
+msgstr ""
+
+msgid "Enable container expiration caching."
+msgstr ""
+
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
+msgid "Enable email notification"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable feature to choose access level"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group runners"
+msgstr ""
+
+msgid "Enable header and footer in emails"
+msgstr ""
+
+msgid "Enable in-product marketing emails"
+msgstr ""
+
+msgid "Enable incident management inbound alert limit"
+msgstr ""
+
+msgid "Enable integration"
+msgstr ""
+
+msgid "Enable logs collection"
+msgstr ""
+
+msgid "Enable maintenance mode"
+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 version check and Service Ping."
+msgstr ""
+
+msgid "Enable rate limiting for POST requests to the specified paths"
+msgstr ""
+
+msgid "Enable reCAPTCHA"
+msgstr ""
+
+msgid "Enable reCAPTCHA for login."
+msgstr ""
+
+msgid "Enable repository checks"
+msgstr ""
+
+msgid "Enable security training"
+msgstr ""
+
+msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable shared runners for this project"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable unauthenticated API request rate limit"
+msgstr ""
+
+msgid "Enable unauthenticated web request rate limit"
+msgstr ""
+
+msgid "Enable user deactivation emails"
+msgstr ""
+
+msgid "Enable version check"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
+msgstr ""
+
+msgid "EnableReviewApp|Close"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet text"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Enabled Git access protocols"
+msgstr ""
+
+msgid "Enabled OAuth authentication sources"
+msgstr ""
+
+msgid "End Time"
+msgstr ""
+
+msgid "Ends"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
+msgid "Enforce two-factor authentication"
+msgstr ""
+
+msgid "Enforce two-factor authentication for all user sign-ins."
+msgstr ""
+
+msgid "Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
+msgstr ""
+
+msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
+msgstr ""
+
+msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd} of your CI pipeline to track deployments to your cluster."
+msgstr ""
+
+msgid "Enter %{weights_link_start}weights%{weights_link_end} for storages for new repositories. Configured storages appear below."
+msgstr ""
+
+msgid "Enter 2FA for Admin Mode"
+msgstr ""
+
+msgid "Enter Admin Mode"
+msgstr ""
+
+msgid "Enter a number"
+msgstr ""
+
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter license key"
+msgstr ""
+
+msgid "Enter merge request URLs"
+msgstr ""
+
+msgid "Enter new AWS Secret Access Key"
+msgstr ""
+
+msgid "Enter number of issues"
+msgstr ""
+
+msgid "Enter one or more user ID separated by commas"
+msgstr ""
+
+msgid "Enter the %{name} description"
+msgstr ""
+
+msgid "Enter the %{name} title"
+msgstr ""
+
+msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
+msgstr ""
+
+msgid "Enter the following to confirm:"
+msgstr ""
+
+msgid "Enter the name of your application, and we'll return a unique %{type}."
+msgstr ""
+
+msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
+msgid "Enter 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 ""
+
+msgid "Enter your Packagist token."
+msgstr ""
+
+msgid "Enter your Packagist username."
+msgstr ""
+
+msgid "Enter your password to approve"
+msgstr ""
+
+msgid "Enterprise"
+msgstr ""
+
+msgid "Environment"
+msgstr ""
+
+msgid "Environment is required for Stages::MetricEndpointInserter"
+msgstr ""
+
+msgid "Environment is required for Stages::VariableEndpointInserter"
+msgstr ""
+
+msgid "Environment scope"
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "EnvironmentDashboard|API"
+msgstr ""
+
+msgid "EnvironmentDashboard|Created through the Deployment API"
+msgstr ""
+
+msgid "EnvironmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments Dashboard"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
+msgstr ""
+
+msgid "Environments in %{name}"
+msgstr ""
+
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|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. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "Environments|An error occurred while canceling the auto stop, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while re-deploying the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while rolling back the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Auto stop"
+msgstr ""
+
+msgid "Environments|Auto stops %{autoStopAt}"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Delete"
+msgstr ""
+
+msgid "Environments|Delete '%{environmentName}'?"
+msgstr ""
+
+msgid "Environments|Delete environment"
+msgstr ""
+
+msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
+msgid "Environments|Enable review app"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|How do I create an environment?"
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn about environments"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployed environments"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No results found"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Open"
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Re-deploy environment"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Rollback environment %{name}?"
+msgstr ""
+
+msgid "Environments|Search by environment name"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping %{environmentName}"
+msgstr ""
+
+msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
+msgstr ""
+
+msgid "Environments|This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments."
+msgstr ""
+
+msgid "Environments|You don't have any stopped environments."
+msgstr ""
+
+msgid "Environments|by %{avatar}"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Environment|Auto stop %{time}"
+msgstr ""
+
+msgid "Environment|Deployment tier"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic Boards"
+msgstr ""
+
+msgid "Epic actions"
+msgstr ""
+
+msgid "Epic cannot be found."
+msgstr ""
+
+msgid "Epic details"
+msgstr ""
+
+msgid "Epic events"
+msgstr ""
+
+msgid "Epic not found for given params"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics, issues, and merge requests"
+msgstr ""
+
+msgid "Epics|%{startDate} – %{dueDate}"
+msgstr ""
+
+msgid "Epics|%{startDate} – No due date"
+msgstr ""
+
+msgid "Epics|Add a new epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic"
+msgstr ""
+
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Assign Epic"
+msgstr ""
+
+msgid "Epics|Leave empty to inherit from milestone dates"
+msgstr ""
+
+msgid "Epics|No start date – %{dueDate}"
+msgstr ""
+
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
+msgid "Epics|Show more"
+msgstr ""
+
+msgid "Epics|Something went wrong while assigning issue to epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating issue."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching epics list."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching group epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while moving item."
+msgstr ""
+
+msgid "Epics|Something went wrong while ordering item."
+msgstr ""
+
+msgid "Epics|Something went wrong while removing issue from epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while updating epics."
+msgstr ""
+
+msgid "Epics|The color for the epic when it's visualized, such as on roadmap timeline bars."
+msgstr ""
+
+msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
+msgid "Epics|Unable to save epic. Please try again"
+msgstr ""
+
+msgid "Erased"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Details"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error creating label."
+msgstr ""
+
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
+msgid "Error creating new iteration"
+msgstr ""
+
+msgid "Error creating repository for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Error creating the snippet"
+msgstr ""
+
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
+msgid "Error deleting project. Check logs for error details."
+msgstr ""
+
+msgid "Error fetching branches"
+msgstr ""
+
+msgid "Error fetching burnup chart data"
+msgstr ""
+
+msgid "Error fetching diverging counts for branches. Please try again."
+msgstr ""
+
+msgid "Error fetching forked projects. Please try again."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching payload data."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
+msgid "Error loading issues"
+msgstr ""
+
+msgid "Error loading iterations"
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading milestone tab"
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
+msgid "Error occurred when saving assignees"
+msgstr ""
+
+msgid "Error occurred when saving reviewers"
+msgstr ""
+
+msgid "Error occurred while updating the %{issuableType} status"
+msgstr ""
+
+msgid "Error occurred while updating the issue status"
+msgstr ""
+
+msgid "Error occurred. A blocked user cannot be deactivated"
+msgstr ""
+
+msgid "Error occurred. A blocked user must be unblocked to be activated"
+msgstr ""
+
+msgid "Error occurred. User was not banned"
+msgstr ""
+
+msgid "Error occurred. User was not blocked"
+msgstr ""
+
+msgid "Error occurred. User was not confirmed"
+msgstr ""
+
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
+msgid "Error occurred. User was not unblocked"
+msgstr ""
+
+msgid "Error occurred. User was not unlocked"
+msgstr ""
+
+msgid "Error parsing CSV file. Please make sure it has"
+msgstr ""
+
+msgid "Error promoting the note to timeline event: %{error}"
+msgstr ""
+
+msgid "Error rendering Markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error setting up editor. Please try again."
+msgstr ""
+
+msgid "Error tracking"
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all to-do items."
+msgstr ""
+
+msgid "Error updating status of to-do item."
+msgstr ""
+
+msgid "Error updating the snippet"
+msgstr ""
+
+msgid "Error uploading file"
+msgstr ""
+
+msgid "Error uploading file. Please try again."
+msgstr ""
+
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error while migrating %{upload_id}: %{error_message}"
+msgstr ""
+
+msgid "Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Error: %{error_message}"
+msgstr ""
+
+msgid "Error: %{error}"
+msgstr ""
+
+msgid "Error: Couldn't load some or all of the changes."
+msgstr ""
+
+msgid "Error: No AWS credentials were supplied"
+msgstr ""
+
+msgid "Error: No AWS provision role found for user"
+msgstr ""
+
+msgid "Error: Unable to create deploy freeze"
+msgstr ""
+
+msgid "Error: Unable to delete deploy freeze"
+msgstr ""
+
+msgid "Error: Unable to find AWS role for current user"
+msgstr ""
+
+msgid "ErrorTracking|Access token is %{token_in_code_tag}"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection failed. Check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|Enable error tracking"
+msgstr ""
+
+msgid "ErrorTracking|Error tracking backend"
+msgstr ""
+
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
+
+msgid "ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a %{settingsLinkStart}Sentry API URL and Auth Token%{settingsLinkEnd} on your project settings page. However, error tracking is not ready for production use and cannot be enabled on GitLab.com."
+msgstr ""
+
+msgid "ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a Sentry API URL and Auth Token below. However, error tracking is not ready for production use and cannot be enabled on GitLab.com."
+msgstr ""
+
+msgid "ErrorTracking|No projects available"
+msgstr ""
+
+msgid "ErrorTracking|Select project"
+msgstr ""
+
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
+
+msgid "ErrorTracking|View project settings"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
+msgstr ""
+
+msgid "Escalate this incident"
+msgstr ""
+
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies may not have more than %{rule_count} rules"
+msgstr ""
+
+msgid "Escalation policies must have at least one rule"
+msgstr ""
+
+msgid "Escalation policy"
+msgstr ""
+
+msgid "Escalation policy:"
+msgstr ""
+
+msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
+msgstr ""
+
+msgid "EscalationPolicies|%{notificationIcon} THEN %{doAction} %{forScheduleOrUser}"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first."
+msgstr ""
+
+msgid "EscalationPolicies|A user is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add policy"
+msgstr ""
+
+msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Delete escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Email user"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation policies"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Maximum of 10 rules has been reached."
+msgstr ""
+
+msgid "EscalationPolicies|Minutes must be between 0 and 1440."
+msgstr ""
+
+msgid "EscalationPolicies|Remove escalation rule"
+msgstr ""
+
+msgid "EscalationPolicies|Search for user"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+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 ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{scheduleOrUser}"
+msgstr ""
+
+msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
+msgstr ""
+
+msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
+msgstr ""
+
+msgid "EscalationPolicies|This policy has no escalation rules."
+msgstr ""
+
+msgid "EscalationPolicies|mins"
+msgstr ""
+
+msgid "Estimate"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "Even if you reach the number of seats in your subscription, you can continue to add users, and GitLab will bill you for the overage."
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by designs"
+msgstr ""
+
+msgid "EventFilterBy|Filter by epic events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "EventFilterBy|Filter by wiki"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Events API"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every 3 months"
+msgstr ""
+
+msgid "Every 3 months on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every 6 months"
+msgstr ""
+
+msgid "Every 6 months on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every day"
+msgstr ""
+
+msgid "Every day (at %{time})"
+msgstr ""
+
+msgid "Every day at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every month"
+msgstr ""
+
+msgid "Every month (Day %{day} at %{time})"
+msgstr ""
+
+msgid "Every month on the %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every three months"
+msgstr ""
+
+msgid "Every two weeks"
+msgstr ""
+
+msgid "Every week"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Every week (%{weekday} at %{time})"
+msgstr ""
+
+msgid "Every week on %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Every year"
+msgstr ""
+
+msgid "Every year on %{day} at %{time} %{timezone}"
+msgstr ""
+
+msgid "Everyone With Access"
+msgstr ""
+
+msgid "Everyone can access the wiki."
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything on your to-do list is marked as done."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Gatsby"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Middleman"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Pelican"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
+
+msgid "Evidence collection"
+msgstr ""
+
+msgid "Exactly one of %{attributes} is required"
+msgstr ""
+
+msgid "Example: @sub\\.company\\.com$"
+msgstr ""
+
+msgid "Examples"
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Exceptions"
+msgstr ""
+
+msgid "Excluding merge commits. Limited to %{limit} commits."
+msgstr ""
+
+msgid "Excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "Execution time"
+msgstr ""
+
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "Existing projects may be moved into a group"
+msgstr ""
+
+msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
+msgstr ""
+
+msgid "Existing sign in methods may be removed"
+msgstr ""
+
+msgid "Exit."
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand all files"
+msgstr ""
+
+msgid "Expand all threads"
+msgstr ""
+
+msgid "Expand approvers"
+msgstr ""
+
+msgid "Expand file"
+msgstr ""
+
+msgid "Expand issues"
+msgstr ""
+
+msgid "Expand jobs"
+msgstr ""
+
+msgid "Expand merge details"
+msgstr ""
+
+msgid "Expand milestones"
+msgstr ""
+
+msgid "Expand panel"
+msgstr ""
+
+msgid "Expand settings section"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "ExperimentSubject|Must have exactly one of User, Namespace, or Project."
+msgstr ""
+
+msgid "Expiration"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expiration date (optional)"
+msgstr ""
+
+msgid "Expiration date:"
+msgstr ""
+
+msgid "Expired"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expired:"
+msgstr ""
+
+msgid "Expires"
+msgstr ""
+
+msgid "Expires %{preposition} %{expires_at}"
+msgstr ""
+
+msgid "Expires on"
+msgstr ""
+
+msgid "Expires:"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore paid plans"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Explore public projects"
+msgstr ""
+
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
+msgid "Export"
+msgstr ""
+
+msgid "Export %{requirementsCount} requirements?"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export commit custody report"
+msgstr ""
+
+msgid "Export group"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
+msgid "Export project"
+msgstr ""
+
+msgid "Export requirements"
+msgstr ""
+
+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}"
+msgstr ""
+
+msgid "Export variable to pipelines running on protected branches and tags only."
+msgstr ""
+
+msgid "Exported requirements"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External User:"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External storage URL"
+msgstr ""
+
+msgid "External storage authentication token"
+msgstr ""
+
+msgid "External storage for repository static objects"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
+msgstr ""
+
+msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
+msgstr ""
+
+msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization certificate"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key"
+msgstr ""
+
+msgid "ExternalAuthorization|Client authorization key password (optional)"
+msgstr ""
+
+msgid "ExternalAuthorization|Default classification label"
+msgstr ""
+
+msgid "ExternalAuthorization|Enable classification control using an external service"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization"
+msgstr ""
+
+msgid "ExternalAuthorization|External authorization request timeout (seconds)"
+msgstr ""
+
+msgid "ExternalAuthorization|External classification policy authorization."
+msgstr ""
+
+msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Period GitLab waits for a response from the external service. If there is no response, access is denied. Default: 0.5 seconds."
+msgstr ""
+
+msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
+msgstr ""
+
+msgid "ExternalAuthorization|Service URL"
+msgstr ""
+
+msgid "ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project features are available and can still specify classification labels for projects."
+msgstr ""
+
+msgid "ExternalIssueIntegration|Another issue tracker is already in use"
+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|Only one issue tracker integration can be active at a time. Please disable the active tracker first and try again."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
+msgid "ExternalWikiService|Enter the URL to the external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
+
+msgid "ExternalWikiService|Link to an external wiki from the sidebar."
+msgstr ""
+
+msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed job"
+msgid_plural "Failed jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Failed on"
+msgstr ""
+
+msgid "Failed to add a Zoom meeting"
+msgstr ""
+
+msgid "Failed to apply commands."
+msgstr ""
+
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Failed to assign a reviewer because no user was specified."
+msgstr ""
+
+msgid "Failed to assign a user because no user was found."
+msgstr ""
+
+msgid "Failed to cancel auto stop because failed to update the environment."
+msgstr ""
+
+msgid "Failed to cancel auto stop because the environment is not set as auto stop."
+msgstr ""
+
+msgid "Failed to cancel auto stop because you do not have permission to update the environment."
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to clone this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to clone this issue: wrong parameters."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create a to-do item for the design."
+msgstr ""
+
+msgid "Failed to create framework"
+msgstr ""
+
+msgid "Failed to create import label for jira import."
+msgstr ""
+
+msgid "Failed to create new access token: %{token_response_message}"
+msgstr ""
+
+msgid "Failed to create repository"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr ""
+
+msgid "Failed to create wiki"
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
+msgstr ""
+
+msgid "Failed to fetch the iteration for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to fetch the iterations for the group. Please try again."
+msgstr ""
+
+msgid "Failed to find import label for Jira import."
+msgstr ""
+
+msgid "Failed to find users for %{missing}"
+msgstr ""
+
+msgid "Failed to generate export, please try again later."
+msgstr ""
+
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
+msgid "Failed to load"
+msgstr ""
+
+msgid "Failed to load Roadmap"
+msgstr ""
+
+msgid "Failed to load assignees."
+msgstr ""
+
+msgid "Failed to load assignees. Please try again."
+msgstr ""
+
+msgid "Failed to load authors. Please try again."
+msgstr ""
+
+msgid "Failed to load branches. Please try again."
+msgstr ""
+
+msgid "Failed to load deploy keys."
+msgstr ""
+
+msgid "Failed to load error details from Sentry."
+msgstr ""
+
+msgid "Failed to load errors from Sentry."
+msgstr ""
+
+msgid "Failed to load group activity metrics. Please try again."
+msgstr ""
+
+msgid "Failed to load groups, users and deploy keys."
+msgstr ""
+
+msgid "Failed to load groups."
+msgstr ""
+
+msgid "Failed to load iteration cadences."
+msgstr ""
+
+msgid "Failed to load iterations."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+msgstr ""
+
+msgid "Failed to load milestones."
+msgstr ""
+
+msgid "Failed to load milestones. Please try again."
+msgstr ""
+
+msgid "Failed to load projects"
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
+msgid "Failed to load stacktrace."
+msgstr ""
+
+msgid "Failed to make repository read-only. %{reason}"
+msgstr ""
+
+msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
+msgstr ""
+
+msgid "Failed to move this issue because label was not found."
+msgstr ""
+
+msgid "Failed to move this issue because only a single label can be provided."
+msgstr ""
+
+msgid "Failed to move this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to promote issue to incident"
+msgstr ""
+
+msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr ""
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
+msgid "Failed to publish issue on status page."
+msgstr ""
+
+msgid "Failed to remove a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove a to-do item for the design."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to remove timelog"
+msgstr ""
+
+msgid "Failed to remove user identity."
+msgstr ""
+
+msgid "Failed to remove user key."
+msgstr ""
+
+msgid "Failed to retrieve page"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
+msgid "Failed to save new settings"
+msgstr ""
+
+msgid "Failed to save preferences (%{error_message})."
+msgstr ""
+
+msgid "Failed to save preferences."
+msgstr ""
+
+msgid "Failed to save timelog"
+msgstr ""
+
+msgid "Failed to set due date because the date format is invalid."
+msgstr ""
+
+msgid "Failed to set iteration on this issue. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to toggle the to-do status for the design."
+msgstr ""
+
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
+msgid "Failed to update framework"
+msgstr ""
+
+msgid "Failed to update issue status"
+msgstr ""
+
+msgid "Failed to update the Canary Ingress."
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "False positive"
+msgstr ""
+
+msgid "Fast timeout"
+msgstr ""
+
+msgid "Faster releases. Better code. Less pain."
+msgstr ""
+
+msgid "Favicon"
+msgstr ""
+
+msgid "Favicon was successfully removed."
+msgstr ""
+
+msgid "Favicon will be removed. Are you sure?"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "Feature deprecation"
+msgstr ""
+
+msgid "Feature flag status"
+msgstr ""
+
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
+msgid "FeatureFlags|%d user"
+msgid_plural "FeatureFlags|%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Add strategy"
+msgstr ""
+
+msgid "FeatureFlags|All Environments"
+msgstr ""
+
+msgid "FeatureFlags|All Users"
+msgstr ""
+
+msgid "FeatureFlags|All users"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Edit User List"
+msgstr ""
+
+msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User List Details"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag has no strategies"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|List details"
+msgstr ""
+
+msgid "FeatureFlags|Loading feature flags"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|New User List"
+msgstr ""
+
+msgid "FeatureFlags|New feature flag"
+msgstr ""
+
+msgid "FeatureFlags|No user list selected"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Strategies"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "FeatureFlags|User IDs"
+msgstr ""
+
+msgid "FeatureFlags|User List"
+msgstr ""
+
+msgid "FeatureFlags|User Lists"
+msgstr ""
+
+msgid "FeatureFlags|View user lists"
+msgstr ""
+
+msgid "FeatureFlag|Percentage"
+msgstr ""
+
+msgid "FeatureFlag|Select a user list"
+msgstr ""
+
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
+msgid "FeatureFlag|There are no configured user lists"
+msgstr ""
+
+msgid "FeatureFlag|Type"
+msgstr ""
+
+msgid "FeatureFlag|User IDs"
+msgstr ""
+
+msgid "FeatureFlag|User List"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fetch and check out this merge request's feature branch:"
+msgstr ""
+
+msgid "Fetching incoming email"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "File %{current} of %{total}"
+msgstr ""
+
+msgid "File Hooks"
+msgstr ""
+
+msgid "File Hooks (%{count})"
+msgstr ""
+
+msgid "File Tree"
+msgstr ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File name"
+msgstr ""
+
+msgid "File renamed with no changes."
+msgstr ""
+
+msgid "File suppressed by a .gitattributes entry or the file's encoding is unsupported."
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File too large. Secure Files must be less than %{limit} MB."
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Filename"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files API Rate Limits"
+msgstr ""
+
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by"
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently open."
+msgstr ""
+
+msgid "Filter by Git revision"
+msgstr ""
+
+msgid "Filter by issues that are currently closed."
+msgstr ""
+
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
+msgid "Filter by label"
+msgstr ""
+
+msgid "Filter by merge requests that are currently closed and unmerged."
+msgstr ""
+
+msgid "Filter by merge requests that are currently merged."
+msgstr ""
+
+msgid "Filter by milestone"
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently open."
+msgstr ""
+
+msgid "Filter by user"
+msgstr ""
+
+msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
+msgstr ""
+
+msgid "Filter pipelines"
+msgstr ""
+
+msgid "Filter results"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter results..."
+msgstr ""
+
+msgid "Filter users"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find File"
+msgstr ""
+
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
+msgid "Find bugs in your code with coverage-guided fuzzing."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Fingerprint (MD5)"
+msgstr ""
+
+msgid "Fingerprint (SHA256)"
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finish setting up your dedicated account for %{group_name}."
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First Name"
+msgstr ""
+
+msgid "First Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed"
+msgstr ""
+
+msgid "Fixed burndown chart"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "Flags"
+msgstr ""
+
+msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts (FLoC)"
+msgstr ""
+
+msgid "FloC|Participate in FLoC"
+msgstr ""
+
+msgid "FlowdockService|Enter your Flowdock token."
+msgstr ""
+
+msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows."
+msgstr ""
+
+msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}"
+msgstr ""
+
+msgid "Focus filter bar"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Fogbugz|Fogbugz import failed due to an error: %{error}"
+msgstr ""
+
+msgid "Fogbugz|Project %{repo} could not be found"
+msgstr ""
+
+msgid "Folder/%{name}"
+msgstr ""
+
+msgid "Follow"
+msgstr ""
+
+msgid "Followed Users' Activity"
+msgstr ""
+
+msgid "Followed users"
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For a faster browsing experience, some files are collapsed by default."
+msgstr ""
+
+msgid "For additional information, review your %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For additional information, review your group membership: %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For each job, clone the repository."
+msgstr ""
+
+msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
+msgstr ""
+
+msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
+msgstr ""
+
+msgid "For faster browsing, not all history is shown."
+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 ""
+
+msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
+msgstr ""
+
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "Forgot your password?"
+msgstr ""
+
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
+msgid "Fork project?"
+msgstr ""
+
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
+msgid "ForkProject|Cancel"
+msgstr ""
+
+msgid "ForkProject|Create a group"
+msgstr ""
+
+msgid "ForkProject|Fork project"
+msgstr ""
+
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
+msgid "ForkProject|Internal"
+msgstr ""
+
+msgid "ForkProject|Please select a namespace"
+msgstr ""
+
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
+msgid "ForkProject|Private"
+msgstr ""
+
+msgid "ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "ForkProject|Public"
+msgstr ""
+
+msgid "ForkProject|Select a namespace"
+msgstr ""
+
+msgid "ForkProject|Something went wrong while loading data. Please refresh the page to try again."
+msgstr ""
+
+msgid "ForkProject|The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "ForkProject|The project can be accessed without any authentication."
+msgstr ""
+
+msgid "ForkProject|Visibility level"
+msgstr ""
+
+msgid "ForkProject|Want to organize several dependent projects under the same namespace?"
+msgstr ""
+
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from an inaccessible project"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format: %{dateFormat}"
+msgstr ""
+
+msgid "Forward %{package_type} package requests to the %{registry_type} Registry if the packages are not found in the GitLab Package Registry"
+msgstr ""
+
+msgid "Found errors in your %{gitlab_ci_yml}:"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Framework successfully deleted"
+msgstr ""
+
+msgid "Free"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Ultimate"
+msgstr ""
+
+msgid "Free User Cap"
+msgstr ""
+
+msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
+msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
+msgid "Freeze end"
+msgstr ""
+
+msgid "Freeze start"
+msgstr ""
+
+msgid "Frequency"
+msgstr ""
+
+msgid "Frequently searched"
+msgstr ""
+
+msgid "Fri"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "From %{code_open}%{source_title}%{code_close} into"
+msgstr ""
+
+msgid "From %{providerTitle}"
+msgstr ""
+
+msgid "From October 19, 2022, free private groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free private groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "Full"
+msgstr ""
+
+msgid "Full log"
+msgstr ""
+
+msgid "Full name"
+msgstr ""
+
+msgid "GCP region configured"
+msgstr ""
+
+msgid "GPG Key ID:"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
+msgid "GPG signature (loading...)"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General Settings"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "General settings"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
+msgstr ""
+
+msgid "Generate new export"
+msgstr ""
+
+msgid "Generate project access tokens scoped to this project for your applications that need access to the GitLab API."
+msgstr ""
+
+msgid "Generate site and private keys at"
+msgstr ""
+
+msgid "Generated with JSON data"
+msgstr ""
+
+msgid "Generic"
+msgstr ""
+
+msgid "Generic package file size in bytes"
+msgstr ""
+
+msgid "GenericReport|After"
+msgstr ""
+
+msgid "GenericReport|Before"
+msgstr ""
+
+msgid "GenericReport|Diff"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Replication"
+msgstr ""
+
+msgid "Geo Settings"
+msgstr ""
+
+msgid "Geo Sites"
+msgstr ""
+
+msgid "Geo sites"
+msgstr ""
+
+msgid "Geo|%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Geo|%d shard selected"
+msgid_plural "%d shards selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Geo|%{boldStart}Not applicable%{boldEnd}: Geo does not verify this component yet. See the %{linkStart}data types we plan to support%{linkEnd}."
+msgstr ""
+
+msgid "Geo|%{component} synced"
+msgstr ""
+
+msgid "Geo|%{component} verified"
+msgstr ""
+
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
+msgid "Geo|%{label} can't be blank"
+msgstr ""
+
+msgid "Geo|%{label} should be between 1-999"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-verify"
+msgstr ""
+
+msgid "Geo|%{timeAgoStr} (%{pendingEvents} events)"
+msgstr ""
+
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
+msgid "Geo|Add New Site"
+msgstr ""
+
+msgid "Geo|Add site"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All %{replicable_name}"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for resync"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for reverify"
+msgstr ""
+
+msgid "Geo|Allow this secondary site to replicate content on Object Storage"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP can't be blank"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP should contain valid IP addresses"
+msgstr ""
+
+msgid "Geo|Checksummed"
+msgstr ""
+
+msgid "Geo|Choose specific groups or storage shards"
+msgstr ""
+
+msgid "Geo|Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
+msgstr ""
+
+msgid "Geo|Configure various settings for your %{siteType} site. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "Geo|Connection timeout"
+msgstr ""
+
+msgid "Geo|Connection timeout can't be blank"
+msgstr ""
+
+msgid "Geo|Connection timeout must be a number"
+msgstr ""
+
+msgid "Geo|Connection timeout should be between 1-120"
+msgstr ""
+
+msgid "Geo|Consult Geo troubleshooting information"
+msgstr ""
+
+msgid "Geo|Container repositories synchronization concurrency limit"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Data replication lag"
+msgstr ""
+
+msgid "Geo|Data type"
+msgstr ""
+
+msgid "Geo|Disabled"
+msgstr ""
+
+msgid "Geo|Discover GitLab Geo"
+msgstr ""
+
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "Geo|Edit %{nodeType} site"
+msgstr ""
+
+msgid "Geo|Edit Geo Site"
+msgstr ""
+
+msgid "Geo|Edit your search and try again."
+msgstr ""
+
+msgid "Geo|Errors:"
+msgstr ""
+
+msgid "Geo|External URL"
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File synchronization concurrency limit"
+msgstr ""
+
+msgid "Geo|Filter Geo sites"
+msgstr ""
+
+msgid "Geo|Filter by name"
+msgstr ""
+
+msgid "Geo|Filter by status"
+msgstr ""
+
+msgid "Geo|Full details"
+msgstr ""
+
+msgid "Geo|Geo Settings"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Geo allows you to choose specific groups or storage shards to replicate."
+msgstr ""
+
+msgid "Geo|Geo can replicate objects stored in Object Storage (AWS S3, or other compatible object storage)."
+msgstr ""
+
+msgid "Geo|Geo sites"
+msgstr ""
+
+msgid "Geo|Geo sites are paused using a command run on the site"
+msgstr ""
+
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|Healthy"
+msgstr ""
+
+msgid "Geo|If enabled, GitLab will handle Object Storage replication using Geo."
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
+msgid "Geo|In progress"
+msgstr ""
+
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Internal URL (optional)"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Learn more about Geo"
+msgstr ""
+
+msgid "Geo|Learn more about Geo site statuses"
+msgstr ""
+
+msgid "Geo|Limit the number of concurrent operations this secondary site can run in the background."
+msgstr ""
+
+msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Geo|Minimum interval in days"
+msgstr ""
+
+msgid "Geo|Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
+msgstr ""
+
+msgid "Geo|Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|No %{replicable_type} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Geo|No %{replicable} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Geo|No Geo site found"
+msgstr ""
+
+msgid "Geo|No available replication slots"
+msgstr ""
+
+msgid "Geo|Nothing found…"
+msgstr ""
+
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Object Storage replication"
+msgstr ""
+
+msgid "Geo|Offline"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Primary"
+msgstr ""
+
+msgid "Geo|Primary site"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Queued"
+msgstr ""
+
+msgid "Geo|Re-verification interval"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove %{nodeType} site"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove site"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
+msgstr ""
+
+msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
+msgstr ""
+
+msgid "Geo|Replicated data is verified with the secondary site(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
+msgid "Geo|Repository synchronization concurrency limit"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|Resync all %{projects_count} projects"
+msgstr ""
+
+msgid "Geo|Resync all %{total}%{replicableType}"
+msgstr ""
+
+msgid "Geo|Resync project"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Reverify"
+msgstr ""
+
+msgid "Geo|Reverify all"
+msgstr ""
+
+msgid "Geo|Reverify all %{projects_count} projects"
+msgstr ""
+
+msgid "Geo|Reverify project"
+msgstr ""
+
+msgid "Geo|Review replication status, and resynchronize and reverify items with the primary site."
+msgstr ""
+
+msgid "Geo|Secondary"
+msgstr ""
+
+msgid "Geo|Secondary site"
+msgstr ""
+
+msgid "Geo|Select groups to replicate"
+msgstr ""
+
+msgid "Geo|Select shards to replicate"
+msgstr ""
+
+msgid "Geo|Selective (%{syncLabel})"
+msgstr ""
+
+msgid "Geo|Selective synchronization"
+msgstr ""
+
+msgid "Geo|Set the timeout in seconds to send a secondary site status to the primary and IPs allowed for the secondary sites."
+msgstr ""
+
+msgid "Geo|Set verification limit and frequency."
+msgstr ""
+
+msgid "Geo|Set what should be replicated by this secondary site."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Show more"
+msgstr ""
+
+msgid "Geo|Site name can't be blank"
+msgstr ""
+
+msgid "Geo|Site name should be between 1 and 255 characters"
+msgstr ""
+
+msgid "Geo|Site's status was updated %{timeAgo}."
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Storage config"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Synchronization settings"
+msgstr ""
+
+msgid "Geo|Synchronization status"
+msgstr ""
+
+msgid "Geo|The URL of the primary site that is used internally by the secondary sites."
+msgstr ""
+
+msgid "Geo|The URL of the secondary site that is used internally by the primary site."
+msgstr ""
+
+msgid "Geo|The database is currently %{db_lag} behind the primary site."
+msgstr ""
+
+msgid "Geo|The site is currently %{minutes_behind} behind the primary site."
+msgstr ""
+
+msgid "Geo|There are no %{replicable_type} to show"
+msgstr ""
+
+msgid "Geo|There are no %{replicable} to show"
+msgstr ""
+
+msgid "Geo|There was an error deleting the Geo Site"
+msgstr ""
+
+msgid "Geo|There was an error fetching the Geo Settings"
+msgstr ""
+
+msgid "Geo|There was an error fetching the Geo Sites"
+msgstr ""
+
+msgid "Geo|There was an error fetching the Sites's Groups"
+msgstr ""
+
+msgid "Geo|There was an error saving this Geo Site"
+msgstr ""
+
+msgid "Geo|There was an error updating the Geo Settings"
+msgstr ""
+
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
+msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Geo|This will resync all projects. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Geo|This will reverify all projects. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Geo|Time in seconds"
+msgstr ""
+
+msgid "Geo|Tracking database entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tuning settings"
+msgstr ""
+
+msgid "Geo|URL can't be blank"
+msgstr ""
+
+msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
+msgstr ""
+
+msgid "Geo|Undefined"
+msgstr ""
+
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
+msgid "Geo|Updated %{timeAgo}"
+msgstr ""
+
+msgid "Geo|Verification"
+msgstr ""
+
+msgid "Geo|Verification concurrency limit"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Verification information"
+msgstr ""
+
+msgid "Geo|Verification status"
+msgstr ""
+
+msgid "Geo|Verified"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|With GitLab Geo, you can install a special read-only and replicated instance anywhere."
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo site."
+msgstr ""
+
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get a free trial"
+msgstr ""
+
+msgid "Get a support subscription"
+msgstr ""
+
+msgid "Get started"
+msgstr ""
+
+msgid "Get started with GitLab"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Get started with performance monitoring"
+msgstr ""
+
+msgid "Get started!"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git GC period"
+msgstr ""
+
+msgid "Git LFS Rate Limits"
+msgstr ""
+
+msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr ""
+
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
+msgstr ""
+
+msgid "Git LFS status:"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git shallow clone"
+msgstr ""
+
+msgid "Git strategy"
+msgstr ""
+
+msgid "Git transfer in progress"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitAbuse|Automatically ban users from this %{scope} when they exceed the specified limits"
+msgstr ""
+
+msgid "GitAbuse|Excluded users"
+msgstr ""
+
+msgid "GitAbuse|Number of repositories"
+msgstr ""
+
+msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
+msgstr ""
+
+msgid "GitAbuse|Number of repositories must be a number."
+msgstr ""
+
+msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
+msgstr ""
+
+msgid "GitAbuse|Reporting time period (seconds)"
+msgstr ""
+
+msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
+msgstr ""
+
+msgid "GitAbuse|Reporting time period must be a number."
+msgstr ""
+
+msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
+msgstr ""
+
+msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
+msgstr ""
+
+msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
+msgstr ""
+
+msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
+msgstr ""
+
+msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitHubImporter|*Merged by: %{author} at %{timestamp}*"
+msgstr ""
+
+msgid "GitLab"
+msgstr ""
+
+msgid "GitLab (self-managed)"
+msgstr ""
+
+msgid "GitLab / Unsubscribe"
+msgstr ""
+
+msgid "GitLab API"
+msgstr ""
+
+msgid "GitLab Account Request"
+msgstr ""
+
+msgid "GitLab Billing Team."
+msgstr ""
+
+msgid "GitLab Error Tracking"
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Issue"
+msgstr ""
+
+msgid "GitLab KAS"
+msgstr ""
+
+msgid "GitLab Pages"
+msgstr ""
+
+msgid "GitLab Shell"
+msgstr ""
+
+msgid "GitLab Support Bot"
+msgstr ""
+
+msgid "GitLab Team Member"
+msgstr ""
+
+msgid "GitLab Ultimate trial"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab Workhorse"
+msgstr ""
+
+msgid "GitLab account request rejected"
+msgstr ""
+
+msgid "GitLab commit"
+msgstr ""
+
+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 ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab for Jira Cloud"
+msgstr ""
+
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
+msgid "GitLab informs you if a new version is available. %{link_start}What information does GitLab Inc. collect?%{link_end}"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
+msgstr ""
+
+msgid "GitLab is free to use. Many features for larger teams are part of our %{link_start}paid products%{link_end}. You can try Ultimate for free without any obligation or payment details."
+msgstr ""
+
+msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
+msgstr ""
+
+msgid "GitLab is open source software to collaborate on code."
+msgstr ""
+
+msgid "GitLab is undergoing maintenance"
+msgstr ""
+
+msgid "GitLab logo"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs"
+msgstr ""
+
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
+msgid "GitLab.com"
+msgstr ""
+
+msgid "GitLab.com (SaaS)"
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLabPagesDomains|Retry"
+msgstr ""
+
+msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
+msgstr ""
+
+msgid "GitLabPages|Access pages"
+msgstr ""
+
+msgid "GitLabPages|Are you sure?"
+msgstr ""
+
+msgid "GitLabPages|Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
+msgstr ""
+
+msgid "GitLabPages|Certificate: %{subject}"
+msgstr ""
+
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
+msgid "GitLabPages|Configure pages"
+msgstr ""
+
+msgid "GitLabPages|Domains"
+msgstr ""
+
+msgid "GitLabPages|Edit"
+msgstr ""
+
+msgid "GitLabPages|Expired"
+msgstr ""
+
+msgid "GitLabPages|Force HTTPS (requires valid certificates)"
+msgstr ""
+
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
+
+msgid "GitLabPages|Maximum size (MB)"
+msgstr ""
+
+msgid "GitLabPages|New Domain"
+msgstr ""
+
+msgid "GitLabPages|Only project maintainers can remove pages"
+msgstr ""
+
+msgid "GitLabPages|Pages"
+msgstr ""
+
+msgid "GitLabPages|Remove"
+msgstr ""
+
+msgid "GitLabPages|Remove certificate"
+msgstr ""
+
+msgid "GitLabPages|Remove domain"
+msgstr ""
+
+msgid "GitLabPages|Remove pages"
+msgstr ""
+
+msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
+msgstr ""
+
+msgid "GitLabPages|Save changes"
+msgstr ""
+
+msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Start over"
+msgstr ""
+
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "GitLabPages|Unverified"
+msgstr ""
+
+msgid "GitLabPages|Updating your Pages configuration..."
+msgstr ""
+
+msgid "GitLabPages|Verified"
+msgstr ""
+
+msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
+msgstr ""
+
+msgid "GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with subdomains of subdomains. If your namespace or groupname contains a dot, it does not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages work if you don't redirect HTTP to HTTPS. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Your Project has been configured for Pages. Now we have to wait for the Pipeline to succeed for the first time."
+msgstr ""
+
+msgid "GitLabPages|Your pages are served under:"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly relative path:"
+msgstr ""
+
+msgid "Gitaly storage name:"
+msgstr ""
+
+msgid "Gitaly timeouts"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "GithubImporter|PR mergers"
+msgstr ""
+
+msgid "GithubImporter|PR reviews"
+msgstr ""
+
+msgid "GithubImporter|Pull requests"
+msgstr ""
+
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
+msgid "Gitpod"
+msgstr ""
+
+msgid "Gitpod|Enable Gitpod integration"
+msgstr ""
+
+msgid "Gitpod|Gitpod URL"
+msgstr ""
+
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Given epic is already related to this epic."
+msgstr ""
+
+msgid "Global Search is disabled for this scope"
+msgstr ""
+
+msgid "Global Shortcuts"
+msgstr ""
+
+msgid "Global notification level"
+msgstr ""
+
+msgid "Global notification settings"
+msgstr ""
+
+msgid "GlobalSearch| %{search} %{description} %{scope}"
+msgstr ""
+
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Groups"
+msgstr ""
+
+msgid "GlobalSearch|Help"
+msgstr ""
+
+msgid "GlobalSearch|In this project"
+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|Projects"
+msgstr ""
+
+msgid "GlobalSearch|Recent epics"
+msgstr ""
+
+msgid "GlobalSearch|Recent issues"
+msgstr ""
+
+msgid "GlobalSearch|Recent merge requests"
+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 for projects, issues, etc."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Settings"
+msgstr ""
+
+msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
+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|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
+msgstr ""
+
+msgid "GlobalSearch|What are you searching for?"
+msgstr ""
+
+msgid "GlobalSearch|all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|group"
+msgstr ""
+
+msgid "GlobalSearch|in %{scope}"
+msgstr ""
+
+msgid "GlobalSearch|project"
+msgstr ""
+
+msgid "GlobalShortcuts|Copied source branch name to clipboard."
+msgstr ""
+
+msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
+msgstr ""
+
+msgid "Globally-allowed IP ranges"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go Micro is a framework for micro service development"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go back (while searching for files)"
+msgstr ""
+
+msgid "Go back to configuration"
+msgstr ""
+
+msgid "Go full screen"
+msgstr ""
+
+msgid "Go to %{source_name}"
+msgstr ""
+
+msgid "Go to commits"
+msgstr ""
+
+msgid "Go to definition"
+msgstr ""
+
+msgid "Go to environments"
+msgstr ""
+
+msgid "Go to environments page to approve or reject"
+msgstr ""
+
+msgid "Go to epic"
+msgstr ""
+
+msgid "Go to file"
+msgstr ""
+
+msgid "Go to file permalink (while viewing a file)"
+msgstr ""
+
+msgid "Go to files"
+msgstr ""
+
+msgid "Go to find file"
+msgstr ""
+
+msgid "Go to issue boards"
+msgstr ""
+
+msgid "Go to issues"
+msgstr ""
+
+msgid "Go to jobs"
+msgstr ""
+
+msgid "Go to kubernetes"
+msgstr ""
+
+msgid "Go to merge requests"
+msgstr ""
+
+msgid "Go to metrics"
+msgstr ""
+
+msgid "Go to next page"
+msgstr ""
+
+msgid "Go to next unresolved thread"
+msgstr ""
+
+msgid "Go to page %{page}"
+msgstr ""
+
+msgid "Go to parent"
+msgstr ""
+
+msgid "Go to parent directory"
+msgstr ""
+
+msgid "Go to previous page"
+msgstr ""
+
+msgid "Go to previous unresolved thread"
+msgstr ""
+
+msgid "Go to primary site"
+msgstr ""
+
+msgid "Go to project"
+msgstr ""
+
+msgid "Go to releases"
+msgstr ""
+
+msgid "Go to repository charts"
+msgstr ""
+
+msgid "Go to repository graph"
+msgstr ""
+
+msgid "Go to snippets"
+msgstr ""
+
+msgid "Go to the %{b_open}Activity%{b_close} page for %{project_link}."
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Email restrictions for sign-ups'."
+msgstr ""
+
+msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check the 'Domain denylist'."
+msgstr ""
+
+msgid "Go to the activity feed"
+msgstr ""
+
+msgid "Go to the group’s 'Settings &gt; General' page, and check 'Restrict membership by email domain'."
+msgstr ""
+
+msgid "Go to the milestone list"
+msgstr ""
+
+msgid "Go to the project's activity feed"
+msgstr ""
+
+msgid "Go to the project's overview page"
+msgstr ""
+
+msgid "Go to wiki"
+msgstr ""
+
+msgid "Go to your To-Do list"
+msgstr ""
+
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Go to your groups"
+msgstr ""
+
+msgid "Go to your issues"
+msgstr ""
+
+msgid "Go to your merge requests"
+msgstr ""
+
+msgid "Go to your projects"
+msgstr ""
+
+msgid "Go to your snippets"
+msgstr ""
+
+msgid "Google Cloud"
+msgstr ""
+
+msgid "Google Cloud Error - %{error}"
+msgstr ""
+
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "GoogleCloud|Cancel"
+msgstr ""
+
+msgid "GoogleCloud|Configured region is linked to the selected branch or tag"
+msgstr ""
+
+msgid "GoogleCloud|Create service account"
+msgstr ""
+
+msgid "GoogleCloud|Generated service account is linked to the selected branch or tag"
+msgstr ""
+
+msgid "GoogleCloud|Google Cloud project"
+msgstr ""
+
+msgid "GoogleCloud|Google OAuth2 token revocation request failed"
+msgstr ""
+
+msgid "GoogleCloud|Google OAuth2 token revocation requested"
+msgstr ""
+
+msgid "GoogleCloud|I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
+msgid "GoogleCloud|New service account is generated for the selected Google Cloud project"
+msgstr ""
+
+msgid "GoogleCloud|Refs"
+msgstr ""
+
+msgid "GoogleCloud|Revoke authorizations"
+msgstr ""
+
+msgid "GoogleCloud|Revoke authorizations granted to GitLab. This does not invalidate service accounts."
+msgstr ""
+
+msgid "Got it"
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grafana URL"
+msgstr ""
+
+msgid "Grafana response contains invalid json"
+msgstr ""
+
+msgid "GrafanaIntegration|API token"
+msgstr ""
+
+msgid "GrafanaIntegration|Active"
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana URL"
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana authentication"
+msgstr ""
+
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Grant write permissions to this key"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "GraphViewType|Job dependencies"
+msgstr ""
+
+msgid "GraphViewType|Show dependencies"
+msgstr ""
+
+msgid "GraphViewType|Stage"
+msgstr ""
+
+msgid "Graphs"
+msgstr ""
+
+msgid "Gravatar"
+msgstr ""
+
+msgid "Gravatar enabled"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group %{group_name} couldn't be exported."
+msgstr ""
+
+msgid "Group %{group_name} was exported successfully."
+msgstr ""
+
+msgid "Group %{group_name} was scheduled for deletion."
+msgstr ""
+
+msgid "Group %{group_name} was successfully created."
+msgstr ""
+
+msgid "Group Access Tokens"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group Hooks"
+msgstr ""
+
+msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
+msgid "Group audit events"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group by"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group export could not be started."
+msgstr ""
+
+msgid "Group export download requests"
+msgstr ""
+
+msgid "Group export error"
+msgstr ""
+
+msgid "Group export link has expired. Please generate a new export from your group settings."
+msgstr ""
+
+msgid "Group export requests"
+msgstr ""
+
+msgid "Group export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Group has been already marked for deletion"
+msgstr ""
+
+msgid "Group has not been marked for deletion"
+msgstr ""
+
+msgid "Group import could not be scheduled"
+msgstr ""
+
+msgid "Group import requests"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group information"
+msgstr ""
+
+msgid "Group is required when cluster_type is :group"
+msgstr ""
+
+msgid "Group jobs by"
+msgstr ""
+
+msgid "Group members"
+msgstr ""
+
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
+msgid "Group milestone"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group name (your organization)"
+msgstr ""
+
+msgid "Group navigation"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group path is already taken. We've suggested one that is available."
+msgstr ""
+
+msgid "Group path is available."
+msgstr ""
+
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "Group project URLs are prefixed with the group namespace"
+msgstr ""
+
+msgid "Group requires separate account"
+msgstr ""
+
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
+msgid "Group variables (inherited)"
+msgstr ""
+
+msgid "Group was exported"
+msgstr ""
+
+msgid "Group was successfully updated."
+msgstr ""
+
+msgid "Group wikis"
+msgstr ""
+
+msgid "Group-level wiki is disabled."
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "Group: %{name}"
+msgstr ""
+
+msgid "GroupActivityMetrics|Issues created"
+msgstr ""
+
+msgid "GroupActivityMetrics|Last 30 days"
+msgstr ""
+
+msgid "GroupActivityMetrics|Members added"
+msgstr ""
+
+msgid "GroupActivityMetrics|Merge Requests created"
+msgstr ""
+
+msgid "GroupActivityMetrics|Recent activity"
+msgstr ""
+
+msgid "GroupImport|Failed to import group."
+msgstr ""
+
+msgid "GroupImport|Group '%{group_name}' is being imported."
+msgstr ""
+
+msgid "GroupImport|Group could not be imported: %{errors}"
+msgstr ""
+
+msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
+msgstr ""
+
+msgid "GroupImport|The group was successfully imported."
+msgstr ""
+
+msgid "GroupImport|Unable to process group import file"
+msgstr ""
+
+msgid "GroupPage|Copy group ID"
+msgstr ""
+
+msgid "GroupPage|Group ID: %{group_id}"
+msgstr ""
+
+msgid "GroupRoadmap|%{dateWord} – No end date"
+msgstr ""
+
+msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading epics"
+msgstr ""
+
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
+msgid "GroupRoadmap|No start and end date"
+msgstr ""
+
+msgid "GroupRoadmap|No start date – %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching milestones"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|This quarter"
+msgstr ""
+
+msgid "GroupRoadmap|This year"
+msgstr ""
+
+msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
+msgid "GroupRoadmap|Within 3 years"
+msgstr ""
+
+msgid "GroupSAML|\"persistent\" recommended"
+msgstr ""
+
+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 ""
+
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
+msgstr ""
+
+msgid "GroupSAML|Certificate fingerprint"
+msgstr ""
+
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Copy SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|Could not create SAML group link: %{errors}."
+msgstr ""
+
+msgid "GroupSAML|Default membership role"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
+msgstr ""
+
+msgid "GroupSAML|Identifier"
+msgstr ""
+
+msgid "GroupSAML|Identity provider single sign-on URL"
+msgstr ""
+
+msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
+msgstr ""
+
+msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "GroupSAML|Members"
+msgstr ""
+
+msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "GroupSAML|NameID"
+msgstr ""
+
+msgid "GroupSAML|NameID Format"
+msgstr ""
+
+msgid "GroupSAML|New SAML group link saved."
+msgstr ""
+
+msgid "GroupSAML|No active SAML group links"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks for this group"
+msgstr ""
+
+msgid "GroupSAML|Reset SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Role to assign members of this SAML group."
+msgstr ""
+
+msgid "GroupSAML|SAML Group Links"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name"
+msgstr ""
+
+msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
+msgstr ""
+
+msgid "GroupSAML|SAML Response Output"
+msgstr ""
+
+msgid "GroupSAML|SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On Settings"
+msgstr ""
+
+msgid "GroupSAML|SAML group link was successfully removed."
+msgstr ""
+
+msgid "GroupSAML|SCIM Token"
+msgstr ""
+
+msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
+msgstr ""
+
+msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
+msgstr ""
+
+msgid "GroupSAML|This will be set as the access level of users added to the group."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
+msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
+msgstr ""
+
+msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
+msgstr ""
+
+msgid "GroupSAML|Valid SAML Response"
+msgstr ""
+
+msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
+msgstr ""
+
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
+msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" to identify user and allow sign in"
+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 ""
+
+msgid "GroupSelect|Search groups"
+msgstr ""
+
+msgid "GroupSelect|Select a group"
+msgstr ""
+
+msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Available only on the top-level group. Applies to all subgroups. Groups already shared with a group outside %{group} are still shared unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+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."
+msgstr ""
+
+msgid "GroupSettings|Change group URL"
+msgstr ""
+
+msgid "GroupSettings|Changing a group's URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores."
+msgstr ""
+
+msgid "GroupSettings|Compliance frameworks"
+msgstr ""
+
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
+
+msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customer relations is enabled"
+msgstr ""
+
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
+
+msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
+msgstr ""
+
+msgid "GroupSettings|Email notifications are disabled"
+msgstr ""
+
+msgid "GroupSettings|Export group"
+msgstr ""
+
+msgid "GroupSettings|Git abuse rate limit"
+msgstr ""
+
+msgid "GroupSettings|Group members are not notified if the group is mentioned."
+msgstr ""
+
+msgid "GroupSettings|Group mentions are disabled"
+msgstr ""
+
+msgid "GroupSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
+msgstr ""
+
+msgid "GroupSettings|If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
+msgstr ""
+
+msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
+msgstr ""
+
+msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
+msgstr ""
+
+msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
+msgstr ""
+
+msgid "GroupSettings|Pipeline settings was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Please choose a group URL with no special characters or spaces."
+msgstr ""
+
+msgid "GroupSettings|Prevent forking outside of the group"
+msgstr ""
+
+msgid "GroupSettings|Prevent forking setting was not saved"
+msgstr ""
+
+msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
+msgstr ""
+
+msgid "GroupSettings|Reporting"
+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 containing the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
+msgid "GroupSettings|Select the project containing your custom Insights file. %{help_link_start}What is Insights?%{help_link_end}"
+msgstr ""
+
+msgid "GroupSettings|Set a size limit for all content in each Pages site in this group. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
+msgstr ""
+
+msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+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 ""
+
+msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|Transfer group"
+msgstr ""
+
+msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group"
+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 ""
+
+msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "GroupSettings|cannot be changed by you"
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|cannot change when group contains projects with NPM packages"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups (%{count})"
+msgstr ""
+
+msgid "Groups and projects"
+msgstr ""
+
+msgid "Groups are a great way to organize projects and people."
+msgstr ""
+
+msgid "Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|Create new project"
+msgstr ""
+
+msgid "GroupsEmptyState|Create new subgroup"
+msgstr ""
+
+msgid "GroupsEmptyState|Groups are the best way to manage multiple projects and members."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|No subgroups or projects."
+msgstr ""
+
+msgid "GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab."
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project."
+msgstr ""
+
+msgid "GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+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|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
+msgid "GroupsNew|Contact an administrator to enable options for importing your group."
+msgstr ""
+
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Create subgroup"
+msgstr ""
+
+msgid "GroupsNew|Create this in the %{pat_link_start}user settings%{pat_link_end} of the source GitLab instance. For %{short_living_link_start}security reasons%{short_living_link_end}, use a short expiration date when creating the token."
+msgstr ""
+
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
+
+msgid "GroupsNew|Import a group and related data from another GitLab instance."
+msgstr ""
+
+msgid "GroupsNew|Import group"
+msgstr ""
+
+msgid "GroupsNew|Import groups from another instance of GitLab"
+msgstr ""
+
+msgid "GroupsNew|No import options available"
+msgstr ""
+
+msgid "GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}."
+msgstr ""
+
+msgid "GroupsNew|Personal access token"
+msgstr ""
+
+msgid "GroupsNew|Please fill in GitLab source URL."
+msgstr ""
+
+msgid "GroupsNew|Please fill in your personal access token."
+msgstr ""
+
+msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
+msgstr ""
+
+msgid "GroupsNew|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 ""
+
+msgid "GroupsNew|Upload file"
+msgstr ""
+
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
+msgid "GroupsNew|e.g. h8d3f016698e..."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Delete"
+msgstr ""
+
+msgid "GroupsTree|Edit"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Options"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Groups|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Groups|Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "Groups|Checking group URL availability..."
+msgstr ""
+
+msgid "Groups|Enter a descriptive name for your group."
+msgstr ""
+
+msgid "Groups|Group ID"
+msgstr ""
+
+msgid "Groups|Group URL"
+msgstr ""
+
+msgid "Groups|Group avatar"
+msgstr ""
+
+msgid "Groups|Group description (optional)"
+msgstr ""
+
+msgid "Groups|Group name"
+msgstr ""
+
+msgid "Groups|Group path is available."
+msgstr ""
+
+msgid "Groups|Group path is unavailable. Path has been replaced with a suggested available path."
+msgstr ""
+
+msgid "Groups|Learn more"
+msgstr ""
+
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
+msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
+msgstr ""
+
+msgid "Groups|Remove avatar"
+msgstr ""
+
+msgid "Groups|Save changes"
+msgstr ""
+
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
+msgid "Guideline"
+msgstr ""
+
+msgid "HAR (HTTP Archive)"
+msgstr ""
+
+msgid "HAR file URL"
+msgstr ""
+
+msgid "HAR file path or URL"
+msgstr ""
+
+msgid "HTTP Archive (HAR)"
+msgstr ""
+
+msgid "HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url}"
+msgstr ""
+
+msgid "Harbor Registry"
+msgstr ""
+
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
+msgstr ""
+
+msgid "HarborIntegration|Base URL of the Harbor instance."
+msgstr ""
+
+msgid "HarborIntegration|Enter new Harbor password"
+msgstr ""
+
+msgid "HarborIntegration|Harbor URL"
+msgstr ""
+
+msgid "HarborIntegration|Harbor password"
+msgstr ""
+
+msgid "HarborIntegration|Harbor project name"
+msgstr ""
+
+msgid "HarborIntegration|Harbor username"
+msgstr ""
+
+msgid "HarborIntegration|Leave blank to use your current password."
+msgstr ""
+
+msgid "HarborIntegration|Password for your Harbor username."
+msgstr ""
+
+msgid "HarborIntegration|The name of the project in Harbor."
+msgstr ""
+
+msgid "HarborIntegration|Use Harbor as this project's container registry."
+msgstr ""
+
+msgid "HarborRegistry|%d artifact"
+msgid_plural "HarborRegistry|%d artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "HarborRegistry|%{count} Image repository"
+msgid_plural "HarborRegistry|%{count} Image repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "HarborRegistry|-- artifacts"
+msgstr ""
+
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
+msgid "HarborRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "HarborRegistry|Harbor Registry"
+msgstr ""
+
+msgid "HarborRegistry|Harbor connection error"
+msgstr ""
+
+msgid "HarborRegistry|Please try different search criteria"
+msgstr ""
+
+msgid "HarborRegistry|Published %{timeInfo}"
+msgstr ""
+
+msgid "HarborRegistry|Root image"
+msgstr ""
+
+msgid "HarborRegistry|Something went wrong while fetching the artifact list."
+msgstr ""
+
+msgid "HarborRegistry|Something went wrong while fetching the repository list."
+msgstr ""
+
+msgid "HarborRegistry|Something went wrong while fetching the tags."
+msgstr ""
+
+msgid "HarborRegistry|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "HarborRegistry|Tag"
+msgstr ""
+
+msgid "HarborRegistry|The filter returned no results"
+msgstr ""
+
+msgid "HarborRegistry|There are no harbor images stored for this project"
+msgstr ""
+
+msgid "HarborRegistry|This image has no artifacts"
+msgstr ""
+
+msgid "HarborRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr ""
+
+msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
+msgstr ""
+
+msgid "HarborRegistry|With the Harbor Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "Hashed Storage must be enabled to use Geo"
+msgstr ""
+
+msgid "Hashed repository storage paths"
+msgstr ""
+
+msgid "Hashed storage can't be disabled anymore for new projects"
+msgstr ""
+
+msgid "Header logo"
+msgstr ""
+
+msgid "Header logo was successfully removed."
+msgstr ""
+
+msgid "Header logo will be removed. Are you sure?"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
+msgstr ""
+
+msgid "Headers"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
+msgid "Heading 4"
+msgstr ""
+
+msgid "Health"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "Health status"
+msgstr ""
+
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Hello %{name},"
+msgstr ""
+
+msgid "Hello, %{name}!"
+msgstr ""
+
+msgid "Hello, %{username}!"
+msgstr ""
+
+msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
+msgstr ""
+
+msgid "HelloMessage|%{magnifier_emoji} Create a new GitLab issue: %{new_issue_link}"
+msgstr ""
+
+msgid "HelloMessage|%{rocket_emoji} We like your curiosity! Help us improve GitLab by joining the team: %{jobs_page_link}"
+msgstr ""
+
+msgid "HelloMessage|Does this page need fixes or improvements? Open an issue or contribute a merge request to help make GitLab more lovable. At GitLab, everyone can contribute!"
+msgstr ""
+
+msgid "HelloMessage|Welcome to GitLab!"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help translate GitLab into your language"
+msgstr ""
+
+msgid "Helps prevent bots from brute-force attacks."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts. %{link_start}How do I configure it?%{link_end}"
+msgstr ""
+
+msgid "Helps prevent bots from creating issues."
+msgstr ""
+
+msgid "Helps prevent malicious users hide their activity."
+msgstr ""
+
+msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
+msgstr ""
+
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
+
+msgid "Hi %{username}!"
+msgstr ""
+
+msgid "Hi %{username},"
+msgstr ""
+
+msgid "Hidden"
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "Hide Live Preview"
+msgstr ""
+
+msgid "Hide archived projects"
+msgstr ""
+
+msgid "Hide chart"
+msgid_plural "Hide charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide comments"
+msgstr ""
+
+msgid "Hide comments on this file"
+msgstr ""
+
+msgid "Hide details"
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide group projects"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide list"
+msgstr ""
+
+msgid "Hide marketing-related entries from the Help page"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide thread"
+msgstr ""
+
+msgid "Hide tooltips or popovers"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "Hierarchy|Current structure"
+msgstr ""
+
+msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work into a hierarchical structure. This structure helps teams understand scope, priorities, and how work cascades up toward larger goals."
+msgstr ""
+
+msgid "Hierarchy|Help us improve work items in GitLab!"
+msgstr ""
+
+msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
+msgstr ""
+
+msgid "Hierarchy|Planning hierarchy"
+msgstr ""
+
+msgid "Hierarchy|Take the work items survey"
+msgstr ""
+
+msgid "Hierarchy|These items are unavailable in the current structure."
+msgstr ""
+
+msgid "Hierarchy|Unavailable structure"
+msgstr ""
+
+msgid "Hierarchy|You can start using these items now."
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest role:"
+msgstr ""
+
+msgid "HighlightBar|Alert events:"
+msgstr ""
+
+msgid "HighlightBar|Alert start time:"
+msgstr ""
+
+msgid "HighlightBar|Original alert:"
+msgstr ""
+
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
+msgid "Historical release"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Holder name:"
+msgstr ""
+
+msgid "Home page URL"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully updated."
+msgstr ""
+
+msgid "Horizontal rule"
+msgstr ""
+
+msgid "Hostname"
+msgstr ""
+
+msgid "Hostname used in private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "Hour (UTC)"
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "How do I configure Akismet?"
+msgstr ""
+
+msgid "How do I configure this integration?"
+msgstr ""
+
+msgid "How do I generate it?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
+msgid "How do I rename an environment?"
+msgstr ""
+
+msgid "How do I set up a Google Chat webhook?"
+msgstr ""
+
+msgid "How do I set up this service?"
+msgstr ""
+
+msgid "How do I use a web terminal?"
+msgstr ""
+
+msgid "How do I use file templates?"
+msgstr ""
+
+msgid "How does pull mirroring work?"
+msgstr ""
+
+msgid "How many seconds an IP counts toward the IP address limit."
+msgstr ""
+
+msgid "How the job limiter handles jobs exceeding the thresholds specified below. The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and raises an exception if the compressed size exceeds the limit."
+msgstr ""
+
+msgid "How to track time"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to store my code"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
+
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Commit to %{branchName} branch"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IDE|Start a new merge request"
+msgstr ""
+
+msgid "IDE|Successful commit"
+msgstr ""
+
+msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
+msgstr ""
+
+msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
+msgstr ""
+
+msgid "INFO: Your SSH key has expired. Please generate a new key."
+msgstr ""
+
+msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "IP address expiration time"
+msgstr ""
+
+msgid "IP address restrictions"
+msgstr ""
+
+msgid "IP addresses per user"
+msgstr ""
+
+msgid "IP subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Id"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
+msgstr ""
+
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
+msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
+msgstr ""
+
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
+msgid "IdentityVerification|Create a project"
+msgstr ""
+
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
+msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
+msgstr ""
+
+msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
+msgstr ""
+
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
+msgid "IdentityVerification|Help us keep GitLab secure"
+msgstr ""
+
+msgid "IdentityVerification|Help us protect your account"
+msgstr ""
+
+msgid "IdentityVerification|If you have not recently tried to sign into GitLab, we recommend %{password_link_start}changing your password%{link_end} and %{two_fa_link_start}setting up Two-Factor Authentication%{link_end} to keep your account safe. Your verification code expires after %{expires_in_minutes} minutes."
+msgstr ""
+
+msgid "IdentityVerification|If you have not recently tried to sign into GitLab, we recommend changing your password (%{password_link}) and setting up Two-Factor Authentication (%{two_fa_link}) to keep your account safe."
+msgstr ""
+
+msgid "IdentityVerification|If you've lost access to the email associated to this account or having trouble with the code, %{link_start}here are some other steps you can take.%{link_end}"
+msgstr ""
+
+msgid "IdentityVerification|International dial code"
+msgstr ""
+
+msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|Phone number"
+msgstr ""
+
+msgid "IdentityVerification|Phone number can't be blank."
+msgstr ""
+
+msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
+msgstr ""
+
+msgid "IdentityVerification|Phone number must contain only digits."
+msgstr ""
+
+msgid "IdentityVerification|Please enter a valid code"
+msgstr ""
+
+msgid "IdentityVerification|Resend code"
+msgstr ""
+
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
+msgid "IdentityVerification|Send code"
+msgstr ""
+
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
+msgid "IdentityVerification|Step 1: Verify phone number"
+msgstr ""
+
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr ""
+
+msgid "IdentityVerification|Verification code"
+msgstr ""
+
+msgid "IdentityVerification|Verification successful"
+msgstr ""
+
+msgid "IdentityVerification|Verify code"
+msgstr ""
+
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
+msgid "IdentityVerification|Verify your identity"
+msgstr ""
+
+msgid "IdentityVerification|You can always verify your account at a later time to create a group."
+msgstr ""
+
+msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr ""
+
+msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
+msgstr ""
+
+msgid "Identity|Provider ID"
+msgstr ""
+
+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 ""
+
+msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
+msgstr ""
+
+msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
+msgstr ""
+
+msgid "If checked, new group memberships and permissions can only be added via LDAP synchronization"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "If disabled, only administrators can configure repository mirroring."
+msgstr ""
+
+msgid "If enabled, only protected branches will be mirrored."
+msgstr ""
+
+msgid "If no options are selected, only administrators can register runners."
+msgstr ""
+
+msgid "If none of the options work, try contacting a GitLab administrator."
+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 this email was added in error, you can remove it here:"
+msgstr ""
+
+msgid "If this email was added in error, you can remove it here: %{profile_emails_url}"
+msgstr ""
+
+msgid "If this is a mistake, you can %{link_start}unban them%{link_end}."
+msgstr ""
+
+msgid "If this is a mistake, you can unban them: %{url}."
+msgstr ""
+
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
+msgstr ""
+
+msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
+msgstr ""
+
+msgid "If you did not initiate this change, please contact your administrator immediately."
+msgstr ""
+
+msgid "If you did not perform this request, you can safely ignore this email."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr ""
+
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If you want to remove this email address, visit %{profile_link}"
+msgstr ""
+
+msgid "If you want to remove this email address, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
+
+msgid "Ignore"
+msgstr ""
+
+msgid "Ignored"
+msgstr ""
+
+msgid "Image URL"
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "ImageViewerDimensions|H"
+msgstr ""
+
+msgid "ImageViewerDimensions|W"
+msgstr ""
+
+msgid "Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior."
+msgstr ""
+
+msgid "Impersonate"
+msgstr ""
+
+msgid "Impersonation Tokens"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import %d compatible repository"
+msgid_plural "Import %d compatible repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import %d repository"
+msgid_plural "Import %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import and export rate limits"
+msgstr ""
+
+msgid "Import failed due to a GitHub error: %{original} (HTTP %{code})"
+msgstr ""
+
+msgid "Import from"
+msgstr ""
+
+msgid "Import from Jira"
+msgstr ""
+
+msgid "Import group"
+msgstr ""
+
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
+msgid "Import history"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import in progress. Refresh page to see newly added issues."
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project from"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import requirements"
+msgstr ""
+
+msgid "Import started by: %{importInitiator}"
+msgstr ""
+
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "ImportAProjectModal|Import from a project"
+msgstr ""
+
+msgid "ImportAProjectModal|Import members from another project"
+msgstr ""
+
+msgid "ImportAProjectModal|Import project members"
+msgstr ""
+
+msgid "ImportAProjectModal|Only project members (not group members) are imported, and they get the same permissions as the project you import from."
+msgstr ""
+
+msgid "ImportAProjectModal|Successfully imported"
+msgstr ""
+
+msgid "ImportAProjectModal|Unable to import project members"
+msgstr ""
+
+msgid "ImportAProjectModal|You're importing members to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
+msgstr ""
+
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "ImportProjects|Import repositories"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr ""
+
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the repositories you want to import"
+msgstr ""
+
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
+msgid "ImportProjects|Update of imported projects with realtime changes failed"
+msgstr ""
+
+msgid "Imported requirements"
+msgstr ""
+
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Importing..."
+msgstr ""
+
+msgid "Import|The repository could not be imported."
+msgstr ""
+
+msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
+msgstr ""
+
+msgid "Improve customer support with Service Desk"
+msgstr ""
+
+msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
+msgstr ""
+
+msgid "In progress"
+msgstr ""
+
+msgid "In the background, we're attempting to connect you again."
+msgstr ""
+
+msgid "In this page you will find information about the settings that are used in your current instance."
+msgstr ""
+
+msgid "In use"
+msgstr ""
+
+msgid "InProductMarketing|%{organization_name} logo"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
+msgstr ""
+
+msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Ultimate"
+msgstr ""
+
+msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|A single application eliminates complex integrations, data chokepoints, and toolchain maintenance, resulting in greater productivity and lower cost."
+msgstr ""
+
+msgid "InProductMarketing|Access advanced features, build more efficiently, strengthen security and compliance."
+msgstr ""
+
+msgid "InProductMarketing|Access advanced features."
+msgstr ""
+
+msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
+msgstr ""
+
+msgid "InProductMarketing|And finally %{deploy_link} a Python application."
+msgstr ""
+
+msgid "InProductMarketing|And many more..."
+msgstr ""
+
+msgid "InProductMarketing|Are your runners ready?"
+msgstr ""
+
+msgid "InProductMarketing|Automated security scans directly within GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Be a DevOps hero"
+msgstr ""
+
+msgid "InProductMarketing|Beef up your security"
+msgstr ""
+
+msgid "InProductMarketing|Better code in less time"
+msgstr ""
+
+msgid "InProductMarketing|Blog"
+msgstr ""
+
+msgid "InProductMarketing|Break down silos to coordinate seamlessly across development, operations, and security with a consistent experience across the development lifecycle."
+msgstr ""
+
+msgid "InProductMarketing|Building for iOS? We've got you covered."
+msgstr ""
+
+msgid "InProductMarketing|Burn up/down charts"
+msgstr ""
+
+msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
+msgstr ""
+
+msgid "InProductMarketing|Code owners"
+msgstr ""
+
+msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Code review analytics"
+msgstr ""
+
+msgid "InProductMarketing|Collaboration across stages in GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Collaboration made easy"
+msgstr ""
+
+msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
+msgstr ""
+
+msgid "InProductMarketing|Create a custom runner"
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create well-defined workflows by using scoped labels on issues, merge requests, and epics. Labels with the same scope cannot be used together, which prevents conflicts."
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Define who owns specific files or directories, so the right reviewers are suggested when a merge request introduces changes to those files."
+msgstr ""
+
+msgid "InProductMarketing|Deliver Better Products Faster"
+msgstr ""
+
+msgid "InProductMarketing|Dependency scanning"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+msgstr ""
+
+msgid "InProductMarketing|Discover Premium & Ultimate"
+msgstr ""
+
+msgid "InProductMarketing|Discover Premium & Ultimate."
+msgstr ""
+
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
+msgid "InProductMarketing|Dynamic application security testing"
+msgstr ""
+
+msgid "InProductMarketing|Epics"
+msgstr ""
+
+msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
+msgstr ""
+
+msgid "InProductMarketing|Explore GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Explore the options"
+msgstr ""
+
+msgid "InProductMarketing|Explore the power of GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Facebook"
+msgstr ""
+
+msgid "InProductMarketing|Feel the need for speed?"
+msgstr ""
+
+msgid "InProductMarketing|Find and fix bottlenecks in your code review process by understanding how long open merge requests have been in review."
+msgstr ""
+
+msgid "InProductMarketing|Find out how your teams are really doing"
+msgstr ""
+
+msgid "InProductMarketing|Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
+msgstr ""
+
+msgid "InProductMarketing|Follow our steps"
+msgstr ""
+
+msgid "InProductMarketing|Free 30-day trial"
+msgstr ""
+
+msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy."
+msgstr ""
+
+msgid "InProductMarketing|Get our import guides"
+msgstr ""
+
+msgid "InProductMarketing|Get set up to build for iOS"
+msgstr ""
+
+msgid "InProductMarketing|Get started today"
+msgstr ""
+
+msgid "InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get to know GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get your team set up on GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Git basics"
+msgstr ""
+
+msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|GitLab is infrastructure agnostic (supporting GCP, AWS, Azure, OpenShift, VMWare, On Prem, Bare Metal, and more), offering a consistent workflow experience – irrespective of the environment."
+msgstr ""
+
+msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
+msgstr ""
+
+msgid "InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"
+msgstr ""
+
+msgid "InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"
+msgstr ""
+
+msgid "InProductMarketing|Give us one minute..."
+msgstr ""
+
+msgid "InProductMarketing|Go farther with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
+msgstr ""
+
+msgid "InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}."
+msgstr ""
+
+msgid "InProductMarketing|Here's what you need to know"
+msgstr ""
+
+msgid "InProductMarketing|How (and why) mirroring makes sense"
+msgstr ""
+
+msgid "InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?"
+msgstr ""
+
+msgid "InProductMarketing|How many days does it take our team to complete various tasks?"
+msgstr ""
+
+msgid "InProductMarketing|How to build and test faster"
+msgstr ""
+
+msgid "InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}."
+msgstr ""
+
+msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
+msgstr ""
+
+msgid "InProductMarketing|Import your project and code from GitHub, Bitbucket and others"
+msgstr ""
+
+msgid "InProductMarketing|Improve app security with a 30-day trial"
+msgstr ""
+
+msgid "InProductMarketing|Improve code quality and streamline reviews"
+msgstr ""
+
+msgid "InProductMarketing|Increase Operational Efficiencies"
+msgstr ""
+
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues to join in less than one minute"
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues today"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team in less than 60 seconds"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team now"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
+msgstr ""
+
+msgid "InProductMarketing|It's all in the stats"
+msgstr ""
+
+msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
+msgstr ""
+
+msgid "InProductMarketing|Keep your code quality high by defining who should approve merge requests and how many approvals are required."
+msgstr ""
+
+msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
+msgstr ""
+
+msgid "InProductMarketing|Learn how to build for iOS"
+msgstr ""
+
+msgid "InProductMarketing|Lower cost of development"
+msgstr ""
+
+msgid "InProductMarketing|Make it easier to collaborate on high-level ideas by grouping related issues in an epic."
+msgstr ""
+
+msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
+msgstr ""
+
+msgid "InProductMarketing|Master the art of importing!"
+msgstr ""
+
+msgid "InProductMarketing|Merge request approval rule"
+msgstr ""
+
+msgid "InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}"
+msgstr ""
+
+msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"
+msgstr ""
+
+msgid "InProductMarketing|Multiple required approvers"
+msgstr ""
+
+msgid "InProductMarketing|Need an alternative to importing?"
+msgstr ""
+
+msgid "InProductMarketing|No credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Protect your web application by using DAST to examine for vulnerabilities in deployed environments."
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+msgstr ""
+
+msgid "InProductMarketing|Reduce Security & Compliance Risk"
+msgstr ""
+
+msgid "InProductMarketing|Require multiple approvers on a merge request, so you know it's in good shape before it's merged."
+msgstr ""
+
+msgid "InProductMarketing|Roadmaps"
+msgstr ""
+
+msgid "InProductMarketing|Scoped labels"
+msgstr ""
+
+msgid "InProductMarketing|Security that's integrated into your development lifecycle"
+msgstr ""
+
+msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
+msgstr ""
+
+msgid "InProductMarketing|Speed. Efficiency. Trust."
+msgstr ""
+
+msgid "InProductMarketing|Spin up an autoscaling runner in GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a Self-Managed trial"
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial"
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
+msgstr ""
+
+msgid "InProductMarketing|Start a trial"
+msgstr ""
+
+msgid "InProductMarketing|Start by %{performance_link}"
+msgstr ""
+
+msgid "InProductMarketing|Start by importing your projects"
+msgstr ""
+
+msgid "InProductMarketing|Start with a GitLab Ultimate free trial"
+msgstr ""
+
+msgid "InProductMarketing|Start your trial now!"
+msgstr ""
+
+msgid "InProductMarketing|Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!"
+msgstr ""
+
+msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
+msgstr ""
+
+msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
+msgstr ""
+
+msgid "InProductMarketing|Take your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+msgstr ""
+
+msgid "InProductMarketing|Team members collaborating"
+msgstr ""
+
+msgid "InProductMarketing|Team up in GitLab for greater efficiency"
+msgstr ""
+
+msgid "InProductMarketing|Team work makes the dream work"
+msgstr ""
+
+msgid "InProductMarketing|Test, create, deploy"
+msgstr ""
+
+msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
+msgstr ""
+
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
+msgstr ""
+
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgstr ""
+
+msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
+msgstr ""
+
+msgid "InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}."
+msgstr ""
+
+msgid "InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}."
+msgstr ""
+
+msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
+msgstr ""
+
+msgid "InProductMarketing|Track completed issues in a chart, so you can see how a milestone is progressing at a glance."
+msgstr ""
+
+msgid "InProductMarketing|Try GitLab Ultimate for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+msgstr ""
+
+msgid "InProductMarketing|Turn coworkers into collaborators"
+msgstr ""
+
+msgid "InProductMarketing|Twitter"
+msgstr ""
+
+msgid "InProductMarketing|Understand repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|Understand your project options"
+msgstr ""
+
+msgid "InProductMarketing|Use GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Use our AWS cloudformation template to spin up your runners in just a few clicks!"
+msgstr ""
+
+msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
+msgstr ""
+
+msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
+msgstr ""
+
+msgid "InProductMarketing|Want to get your iOS app up and running, including publishing all the way to TestFlight? Follow our guide to set up GitLab and fastlane to publish iOS apps to the App Store."
+msgstr ""
+
+msgid "InProductMarketing|Want to host GitLab on your servers?"
+msgstr ""
+
+msgid "InProductMarketing|Watch iOS building in action."
+msgstr ""
+
+msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
+msgstr ""
+
+msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
+msgstr ""
+
+msgid "InProductMarketing|When your team is on GitLab these answers are a click away."
+msgstr ""
+
+msgid "InProductMarketing|Working in GitLab = more efficient"
+msgstr ""
+
+msgid "InProductMarketing|YouTube"
+msgstr ""
+
+msgid "InProductMarketing|Your software, deployed your way"
+msgstr ""
+
+msgid "InProductMarketing|Your teams can be more efficient"
+msgstr ""
+
+msgid "InProductMarketing|comprehensive guide"
+msgstr ""
+
+msgid "InProductMarketing|connect an external repository"
+msgstr ""
+
+msgid "InProductMarketing|create a project"
+msgstr ""
+
+msgid "InProductMarketing|from Bitbucket"
+msgstr ""
+
+msgid "InProductMarketing|go to about.gitlab.com"
+msgstr ""
+
+msgid "InProductMarketing|how easy it is to get started"
+msgstr ""
+
+msgid "InProductMarketing|quick start guide"
+msgstr ""
+
+msgid "InProductMarketing|repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|set up a repo"
+msgstr ""
+
+msgid "InProductMarketing|test and deploy"
+msgstr ""
+
+msgid "InProductMarketing|testing browser performance"
+msgstr ""
+
+msgid "InProductMarketing|unsubscribe"
+msgstr ""
+
+msgid "InProductMarketing|update your preferences"
+msgstr ""
+
+msgid "InProductMarketing|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
+msgid "Inactive"
+msgstr ""
+
+msgid "Incident"
+msgstr ""
+
+msgid "Incident Management Limits"
+msgstr ""
+
+msgid "Incident details"
+msgstr ""
+
+msgid "Incident template (optional)."
+msgstr ""
+
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
+msgid "IncidentManagement|Acknowledged"
+msgstr ""
+
+msgid "IncidentManagement|All"
+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|An error occurred while fetching the incident status. Please reload the page."
+msgstr ""
+
+msgid "IncidentManagement|An error occurred while updating the incident status. Please reload the page and try again."
+msgstr ""
+
+msgid "IncidentManagement|Assign paging status"
+msgstr ""
+
+msgid "IncidentManagement|Assignees"
+msgstr ""
+
+msgid "IncidentManagement|Closed"
+msgstr ""
+
+msgid "IncidentManagement|Create incident"
+msgstr ""
+
+msgid "IncidentManagement|Critical - S1"
+msgstr ""
+
+msgid "IncidentManagement|Date created"
+msgstr ""
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
+msgid "IncidentManagement|High - S2"
+msgstr ""
+
+msgid "IncidentManagement|Incident"
+msgstr ""
+
+msgid "IncidentManagement|Incidents"
+msgstr ""
+
+msgid "IncidentManagement|Learn more about incident statuses"
+msgstr ""
+
+msgid "IncidentManagement|Low - S4"
+msgstr ""
+
+msgid "IncidentManagement|Medium - S3"
+msgstr ""
+
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
+msgid "IncidentManagement|No incidents to display."
+msgstr ""
+
+msgid "IncidentManagement|None"
+msgstr ""
+
+msgid "IncidentManagement|Open"
+msgstr ""
+
+msgid "IncidentManagement|Page your team with escalation policies"
+msgstr ""
+
+msgid "IncidentManagement|Paged"
+msgstr ""
+
+msgid "IncidentManagement|Published"
+msgstr ""
+
+msgid "IncidentManagement|Published to status page"
+msgstr ""
+
+msgid "IncidentManagement|Resolved"
+msgstr ""
+
+msgid "IncidentManagement|Setting the status to Acknowledged or Resolved stops paging when escalation policies are selected for the incident."
+msgstr ""
+
+msgid "IncidentManagement|Severity"
+msgstr ""
+
+msgid "IncidentManagement|Status"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
+msgid "IncidentManagement|There was an error displaying the incidents."
+msgstr ""
+
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
+msgid "IncidentManagement|Triggered"
+msgstr ""
+
+msgid "IncidentManagement|Unassigned"
+msgstr ""
+
+msgid "IncidentManagement|Unknown"
+msgstr ""
+
+msgid "IncidentManagement|Unpublished"
+msgstr ""
+
+msgid "IncidentManagement|Use escalation policies to automatically page your team when incidents are created."
+msgstr ""
+
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
+msgid "IncidentSettings|Grafana integration"
+msgstr ""
+
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|Introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer starts automatically when the incident is created, and sets a time limit for resolving the incident. When activated, the time to SLA countdown appears on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number."
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0."
+msgstr ""
+
+msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
+msgid "Incidents"
+msgstr ""
+
+msgid "Incidents|Add image details"
+msgstr ""
+
+msgid "Incidents|Add text or a link to display with your image. If you don't add either, the file name displays instead."
+msgstr ""
+
+msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
+msgstr ""
+
+msgid "Incidents|Must start with http or https"
+msgstr ""
+
+msgid "Incident|Add new timeline event"
+msgstr ""
+
+msgid "Incident|Alert details"
+msgstr ""
+
+msgid "Incident|Are you sure you want to delete this event?"
+msgstr ""
+
+msgid "Incident|Are you sure you wish to delete this image?"
+msgstr ""
+
+msgid "Incident|Delete event"
+msgstr ""
+
+msgid "Incident|Delete image"
+msgstr ""
+
+msgid "Incident|Deleting %{filename}"
+msgstr ""
+
+msgid "Incident|Edit image text or link"
+msgstr ""
+
+msgid "Incident|Editing %{filename}"
+msgstr ""
+
+msgid "Incident|Error creating incident timeline event: %{error}"
+msgstr ""
+
+msgid "Incident|Error deleting incident timeline event: %{error}"
+msgstr ""
+
+msgid "Incident|Error updating incident timeline event: %{error}"
+msgstr ""
+
+msgid "Incident|Metrics"
+msgstr ""
+
+msgid "Incident|No timeline items have been added yet."
+msgstr ""
+
+msgid "Incident|Save and add another event"
+msgstr ""
+
+msgid "Incident|Something went wrong while creating the incident timeline event."
+msgstr ""
+
+msgid "Incident|Something went wrong while deleting the incident timeline event."
+msgstr ""
+
+msgid "Incident|Something went wrong while fetching incident timeline events."
+msgstr ""
+
+msgid "Incident|Something went wrong while updating the incident timeline event."
+msgstr ""
+
+msgid "Incident|Summary"
+msgstr ""
+
+msgid "Incident|There was an issue loading alert data. Please try again."
+msgstr ""
+
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
+msgid "Incident|Timeline"
+msgstr ""
+
+msgid "Incident|Timeline text"
+msgstr ""
+
+msgid "Incident|Timeline text..."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include new features from all tiers."
+msgstr ""
+
+msgid "Include the name of the author of the issue, merge request or comment in the email body. By default, GitLab overrides the email sender's name. Some email servers don't support that option."
+msgstr ""
+
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
+msgstr ""
+
+msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
+
+msgid "Incoming email"
+msgstr ""
+
+msgid "Incoming!"
+msgstr ""
+
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Incompatible project"
+msgstr ""
+
+msgid "Incomplete"
+msgstr ""
+
+msgid "Increase"
+msgstr ""
+
+msgid "Indent line"
+msgstr ""
+
+msgid "Index"
+msgstr ""
+
+msgid "Index all projects"
+msgstr ""
+
+msgid "Index deletion is canceled"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
+msgstr ""
+
+msgid "Infrastructure"
+msgstr ""
+
+msgid "Infrastructure Registry"
+msgstr ""
+
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
+msgid "InfrastructureRegistry|Copy Terraform Command"
+msgstr ""
+
+msgid "InfrastructureRegistry|Copy Terraform Setup Command"
+msgstr ""
+
+msgid "InfrastructureRegistry|Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
+msgstr ""
+
+msgid "InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}."
+msgstr ""
+
+msgid "InfrastructureRegistry|Infrastructure Registry"
+msgstr ""
+
+msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "InfrastructureRegistry|Terraform"
+msgstr ""
+
+msgid "InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab."
+msgstr ""
+
+msgid "InfrastructureRegistry|To authorize access to the Terraform registry:"
+msgstr ""
+
+msgid "InfrastructureRegistry|You have no Terraform modules in your project"
+msgstr ""
+
+msgid "Inherited"
+msgstr ""
+
+msgid "Inherited:"
+msgstr ""
+
+msgid "Initial default branch name"
+msgstr ""
+
+msgid "Initial default branch protection"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Inline math"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input the remote repository URL"
+msgstr ""
+
+msgid "Insert"
+msgstr ""
+
+msgid "Insert a %{rows}x%{cols} table."
+msgstr ""
+
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
+msgid "Insert column after"
+msgstr ""
+
+msgid "Insert column before"
+msgstr ""
+
+msgid "Insert image"
+msgstr ""
+
+msgid "Insert link"
+msgstr ""
+
+msgid "Insert row after"
+msgstr ""
+
+msgid "Insert row before"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Insert table"
+msgstr ""
+
+msgid "Insights"
+msgstr ""
+
+msgid "Insights|Configure a custom report for insights into your group processes such as amount of issues, bugs, and merge requests per month. %{linkStart}How do I configure an insights report?%{linkEnd}"
+msgstr ""
+
+msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
+
+msgid "Install on clusters"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Configuration"
+msgstr ""
+
+msgid "Instance access request"
+msgstr ""
+
+msgid "Instance access request approved"
+msgstr ""
+
+msgid "Instance access request rejected"
+msgstr ""
+
+msgid "Instance administrators group already exists"
+msgstr ""
+
+msgid "Instance audit events"
+msgstr ""
+
+msgid "Instance overview"
+msgstr ""
+
+msgid "Insufficient permissions"
+msgstr ""
+
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "IntegrationEvents|A comment is added on a confidential issue"
+msgstr ""
+
+msgid "IntegrationEvents|A comment is added on an issue"
+msgstr ""
+
+msgid "IntegrationEvents|A confidential issue is created, updated, or closed"
+msgstr ""
+
+msgid "IntegrationEvents|A merge request is created, updated, or merged"
+msgstr ""
+
+msgid "IntegrationEvents|A pipeline status changes"
+msgstr ""
+
+msgid "IntegrationEvents|A push is made to the repository"
+msgstr ""
+
+msgid "IntegrationEvents|A tag is pushed to the repository"
+msgstr ""
+
+msgid "IntegrationEvents|A wiki page is created or updated"
+msgstr ""
+
+msgid "IntegrationEvents|An issue is created, updated, or closed"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|%{integrationTitle}: active"
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+msgstr ""
+
+msgid "Integrations|Active integrations"
+msgstr ""
+
+msgid "Integrations|Add an integration"
+msgstr ""
+
+msgid "Integrations|Add namespace"
+msgstr ""
+
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Integrations|All details"
+msgstr ""
+
+msgid "Integrations|All projects inheriting these settings will also be reset."
+msgstr ""
+
+msgid "Integrations|An error occurred while loading projects using custom settings."
+msgstr ""
+
+msgid "Integrations|An event will be triggered when one of the following items happen."
+msgstr ""
+
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
+msgid "Integrations|Clear if using a self-signed certificate."
+msgstr ""
+
+msgid "Integrations|Comment detail:"
+msgstr ""
+
+msgid "Integrations|Comment settings:"
+msgstr ""
+
+msgid "Integrations|Configure the scope of notifications."
+msgstr ""
+
+msgid "Integrations|Connection details"
+msgstr ""
+
+msgid "Integrations|Connection failed. Check your integration settings."
+msgstr ""
+
+msgid "Integrations|Connection successful."
+msgstr ""
+
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
+msgid "Integrations|Create new issue in ZenTao"
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Edit project alias"
+msgstr ""
+
+msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
+msgstr ""
+
+msgid "Integrations|Enable SSL verification"
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Integrations|Enter your alias"
+msgstr ""
+
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load subscriptions."
+msgstr ""
+
+msgid "Integrations|Failed to sign in to GitLab."
+msgstr ""
+
+msgid "Integrations|Failed to unlink namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
+msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
+msgstr ""
+
+msgid "Integrations|GitLab administrators can set up integrations that all projects in a group inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a project if the settings are necessary at that level. Learn more about %{integrations_link_start}group-level integration management%{link_end}."
+msgstr ""
+
+msgid "Integrations|Group-level integration management"
+msgstr ""
+
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
+msgstr ""
+
+msgid "Integrations|Includes commit title and branch."
+msgstr ""
+
+msgid "Integrations|Instance-level integration management"
+msgstr ""
+
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Keep your PHP dependencies updated on Packagist."
+msgstr ""
+
+msgid "Integrations|Known limitations"
+msgstr ""
+
+msgid "Integrations|Link namespaces"
+msgstr ""
+
+msgid "Integrations|Linked namespaces"
+msgstr ""
+
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
+msgid "Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance."
+msgstr ""
+
+msgid "Integrations|No available namespaces."
+msgstr ""
+
+msgid "Integrations|No linked namespaces"
+msgstr ""
+
+msgid "Integrations|Notification settings"
+msgstr ""
+
+msgid "Integrations|Projects using custom settings"
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be affected."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
+msgstr ""
+
+msgid "Integrations|Reset integration?"
+msgstr ""
+
+msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
+msgstr ""
+
+msgid "Integrations|Restrict to branch (optional)"
+msgstr ""
+
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
+msgid "Integrations|SSL verification"
+msgstr ""
+
+msgid "Integrations|Save settings?"
+msgstr ""
+
+msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
+msgstr ""
+
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
+msgid "Integrations|Search ZenTao issues"
+msgstr ""
+
+msgid "Integrations|Send notifications about project events to Unify Circuit."
+msgstr ""
+
+msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
+msgstr ""
+
+msgid "Integrations|Sign in to %{url}"
+msgstr ""
+
+msgid "Integrations|Sign in to GitLab"
+msgstr ""
+
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
+msgid "Integrations|Standard"
+msgstr ""
+
+msgid "Integrations|There are no projects using custom settings"
+msgstr ""
+
+msgid "Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Integrations|This integration, and inheriting projects were reset."
+msgstr ""
+
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Trigger"
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+msgid "Integrations|You can close this window."
+msgstr ""
+
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
+msgid "Integrations|You haven't activated any integrations yet."
+msgstr ""
+
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
+msgid "Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app."
+msgstr ""
+
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "Integrations|You've activated every integration 🎉"
+msgstr ""
+
+msgid "Integrations|Your browser is not supported"
+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 "IntelliJ IDEA (HTTPS)"
+msgstr ""
+
+msgid "IntelliJ IDEA (SSH)"
+msgstr ""
+
+msgid "Interactive mode"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal error occurred while delivering this webhook."
+msgstr ""
+
+msgid "Internal note"
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
+msgid "Interval"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
+msgstr ""
+
+msgid "Invalid"
+msgstr ""
+
+msgid "Invalid Insights config file detected"
+msgstr ""
+
+msgid "Invalid OS"
+msgstr ""
+
+msgid "Invalid URL"
+msgstr ""
+
+msgid "Invalid URL: %{url}"
+msgstr ""
+
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
+msgstr ""
+
+msgid "Invalid date range"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
+msgid "Invalid file format with specified file type"
+msgstr ""
+
+msgid "Invalid file."
+msgstr ""
+
+msgid "Invalid format selected"
+msgstr ""
+
+msgid "Invalid hash"
+msgstr ""
+
+msgid "Invalid import params"
+msgstr ""
+
+msgid "Invalid input, please avoid emojis"
+msgstr ""
+
+msgid "Invalid login or password"
+msgstr ""
+
+msgid "Invalid period"
+msgstr ""
+
+msgid "Invalid pin code."
+msgstr ""
+
+msgid "Invalid policy type"
+msgstr ""
+
+msgid "Invalid repository bundle for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid rule"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
+msgid "Invalid status"
+msgstr ""
+
+msgid "Invalid two-factor code."
+msgstr ""
+
+msgid "Invalid yaml"
+msgstr ""
+
+msgid "Investigate vulnerability: %{title}"
+msgstr ""
+
+msgid "Invisible Captcha"
+msgstr ""
+
+msgid "Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form."
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invitation declined"
+msgstr ""
+
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
+msgid "Invite Members"
+msgstr ""
+
+msgid "Invite a group"
+msgstr ""
+
+msgid "Invite members"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} details"
+msgstr ""
+
+msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
+msgstr ""
+
+msgid "InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}"
+msgstr ""
+
+msgid "InviteEmail|Projects are used to host and collaborate on code, track issues, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
+msgid "InviteEmail|What's it about?"
+msgstr ""
+
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of the group can start a trial or upgrade to a paid tier."
+msgstr ""
+
+msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
+msgstr ""
+
+msgid "InviteMembersModal|Access expiration date (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|Cancel"
+msgstr ""
+
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
+msgid "InviteMembersModal|Close invite team members"
+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|Explore paid plans"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab is better with colleagues!"
+msgstr ""
+
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
+msgid "InviteMembersModal|Invite"
+msgstr ""
+
+msgid "InviteMembersModal|Invite a group"
+msgstr ""
+
+msgid "InviteMembersModal|Invite members"
+msgstr ""
+
+msgid "InviteMembersModal|Manage members"
+msgstr ""
+
+msgid "InviteMembersModal|Members were successfully added"
+msgstr ""
+
+msgid "InviteMembersModal|Please select members or type email addresses to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Review the invite errors and try again:"
+msgstr ""
+
+msgid "InviteMembersModal|Search for a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select a role"
+msgstr ""
+
+msgid "InviteMembersModal|Select members or type email addresses"
+msgstr ""
+
+msgid "InviteMembersModal|Show less"
+msgstr ""
+
+msgid "InviteMembersModal|Show more (%{count})"
+msgstr ""
+
+msgid "InviteMembersModal|Something went wrong"
+msgstr ""
+
+msgid "InviteMembersModal|The following member couldn't be invited"
+msgid_plural "InviteMembersModal|The following %d members couldn't be invited"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
+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|To get more members an owner of the group can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+msgstr ""
+
+msgid "InviteMembersModal|Username or email address"
+msgstr ""
+
+msgid "InviteMembersModal|You cannot add more members, but you can remove members who no longer need access."
+msgstr ""
+
+msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembersModal|You've reached your %{count} %{members} limit for %{name}"
+msgstr ""
+
+msgid "InviteMembers|Invite a group"
+msgstr ""
+
+msgid "InviteMembers|Invite team members"
+msgstr ""
+
+msgid "InviteMember|Add members to this project and start collaborating with your team."
+msgstr ""
+
+msgid "InviteMember|Invite Members (optional)"
+msgstr ""
+
+msgid "InviteMember|Invite another member"
+msgstr ""
+
+msgid "InviteMember|Invite members"
+msgstr ""
+
+msgid "InviteMember|Invite your team"
+msgstr ""
+
+msgid "InviteMember|Invited users will be added with developer level permissions. %{linkStart}View the documentation%{linkEnd} to see how to change this later."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
+msgid "Invited group allowed email domains must contain a subset of the allowed email domains of the root ancestor group. Go to the group's 'Settings &gt; General' page and check 'Restrict membership by email domain'."
+msgstr ""
+
+msgid "IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}"
+msgstr ""
+
+msgid "IrkerService|Default IRC URI (optional)"
+msgstr ""
+
+msgid "IrkerService|How to enter channels or users?"
+msgstr ""
+
+msgid "IrkerService|Recipients"
+msgstr ""
+
+msgid "IrkerService|Send update messages to an irker server."
+msgstr ""
+
+msgid "IrkerService|Send update messages to an irker server. Before you can use this, you need to set up the irker daemon. %{docs_link}"
+msgstr ""
+
+msgid "IrkerService|Server host (optional)"
+msgstr ""
+
+msgid "IrkerService|Server port (optional)"
+msgstr ""
+
+msgid "IrkerService|URI to add before each recipient."
+msgstr ""
+
+msgid "IrkerService|irker (IRC gateway)"
+msgstr ""
+
+msgid "IrkerService|irker daemon hostname (defaults to localhost)."
+msgstr ""
+
+msgid "IrkerService|irker daemon port (defaults to 6659)."
+msgstr ""
+
+msgid "Is blocked by"
+msgstr ""
+
+msgid "Is using license seat:"
+msgstr ""
+
+msgid "Is using seat"
+msgstr ""
+
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
+msgid "IssuableStatus|%{wi_type} created %{created_at} by "
+msgstr ""
+
+msgid "IssuableStatus|Closed"
+msgstr ""
+
+msgid "IssuableStatus|Closed (%{link})"
+msgstr ""
+
+msgid "IssuableStatus|Created %{created_at} by"
+msgstr ""
+
+msgid "IssuableStatus|duplicated"
+msgstr ""
+
+msgid "IssuableStatus|moved"
+msgstr ""
+
+msgid "IssuableStatus|promoted"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
+msgstr ""
+
+msgid "Issue Analytics"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue Type"
+msgstr ""
+
+msgid "Issue already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr ""
+
+msgid "Issue creation requests"
+msgstr ""
+
+msgid "Issue details"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first deployed to production"
+msgstr ""
+
+msgid "Issue has been promoted to incident"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or merge request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue types"
+msgstr ""
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
+msgid "Issue weight"
+msgstr ""
+
+msgid "IssueAnalytics|Age"
+msgstr ""
+
+msgid "IssueAnalytics|Assignees"
+msgstr ""
+
+msgid "IssueAnalytics|Created by"
+msgstr ""
+
+msgid "IssueAnalytics|Due date"
+msgstr ""
+
+msgid "IssueAnalytics|Failed to load issues. Please try again."
+msgstr ""
+
+msgid "IssueAnalytics|Issue"
+msgstr ""
+
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
+msgid "IssueAnalytics|Milestone"
+msgstr ""
+
+msgid "IssueAnalytics|Status"
+msgstr ""
+
+msgid "IssueAnalytics|Weight"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, add a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "IssueTracker|Custom issue tracker"
+msgstr ""
+
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use Redmine as the issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use Redmine as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use YouTrack as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}"
+msgstr ""
+
+msgid "IssueTracker|Use a custom issue tracker as this project's issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and merge requests"
+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 ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues exist in projects, so to create an issue, first create a project."
+msgstr ""
+
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
+msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
+msgstr ""
+
+msgid "Issues with label %{label}"
+msgstr ""
+
+msgid "Issues with no epic assigned"
+msgstr ""
+
+msgid "Issues, merge requests, pushes, and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Avg/Month:"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "IssuesAnalytics|Total:"
+msgstr ""
+
+msgid "Issue|Title"
+msgstr ""
+
+msgid "It is not possible to %{action} files that are stored in LFS using the web interface"
+msgstr ""
+
+msgid "It looks like you have some draft commits in this branch."
+msgstr ""
+
+msgid "It looks like you're attempting to activate your subscription. Use %{a_start}the Subscription page%{a_end} instead."
+msgstr ""
+
+msgid "It may be several days before you see feature usage data."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
+msgstr ""
+
+msgid "It seems that there is currently no available data for code coverage"
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Italic text"
+msgstr ""
+
+msgid "Iteration"
+msgstr ""
+
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
+msgid "Iteration changed to"
+msgstr ""
+
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
+msgid "Iteration removed"
+msgstr ""
+
+msgid "Iteration updated"
+msgstr ""
+
+msgid "Iterations"
+msgstr ""
+
+msgid "Iterations cadence not found"
+msgstr ""
+
+msgid "Iterations cannot be manually added to cadences that use automatic scheduling"
+msgstr ""
+
+msgid "IterationsCadence|The automation start date must come after the active iteration %{iteration_dates}."
+msgstr ""
+
+msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
+msgstr ""
+
+msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
+msgstr ""
+
+msgid "Iterations|Add iteration"
+msgstr ""
+
+msgid "Iterations|All"
+msgstr ""
+
+msgid "Iterations|All scheduled iterations will remain scheduled even if you use a smaller number."
+msgstr ""
+
+msgid "Iterations|Automatic scheduling"
+msgstr ""
+
+msgid "Iterations|Automation start date"
+msgstr ""
+
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
+msgid "Iterations|Cadence name"
+msgstr ""
+
+msgid "Iterations|Cancel"
+msgstr ""
+
+msgid "Iterations|Couldn't find iteration cadence"
+msgstr ""
+
+msgid "Iterations|Create cadence"
+msgstr ""
+
+msgid "Iterations|Create iteration"
+msgstr ""
+
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
+msgid "Iterations|Delete cadence"
+msgstr ""
+
+msgid "Iterations|Delete iteration cadence?"
+msgstr ""
+
+msgid "Iterations|Delete iteration?"
+msgstr ""
+
+msgid "Iterations|Description"
+msgstr ""
+
+msgid "Iterations|Done"
+msgstr ""
+
+msgid "Iterations|Due date"
+msgstr ""
+
+msgid "Iterations|Duration"
+msgstr ""
+
+msgid "Iterations|Edit cadence"
+msgstr ""
+
+msgid "Iterations|Edit iteration"
+msgstr ""
+
+msgid "Iterations|Edit iteration cadence"
+msgstr ""
+
+msgid "Iterations|Enable automatic scheduling"
+msgstr ""
+
+msgid "Iterations|Enable roll over"
+msgstr ""
+
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
+msgid "Iterations|Iteration cadences"
+msgstr ""
+
+msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
+msgstr ""
+
+msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
+msgstr ""
+
+msgid "Iterations|Move incomplete issues to the next iteration."
+msgstr ""
+
+msgid "Iterations|New iteration"
+msgstr ""
+
+msgid "Iterations|New iteration cadence"
+msgstr ""
+
+msgid "Iterations|No closed iterations."
+msgstr ""
+
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations found"
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
+msgid "Iterations|No open iterations."
+msgstr ""
+
+msgid "Iterations|Number of upcoming iterations that should be scheduled at a time."
+msgstr ""
+
+msgid "Iterations|Open"
+msgstr ""
+
+msgid "Iterations|Roll over issues"
+msgstr ""
+
+msgid "Iterations|Save changes"
+msgstr ""
+
+msgid "Iterations|Select duration"
+msgstr ""
+
+msgid "Iterations|Select number"
+msgstr ""
+
+msgid "Iterations|Select start date"
+msgstr ""
+
+msgid "Iterations|Start date"
+msgstr ""
+
+msgid "Iterations|The date of the first iteration to schedule. This date determines the day of the week when each iteration starts."
+msgstr ""
+
+msgid "Iterations|The duration of each iteration (in weeks)."
+msgstr ""
+
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
+msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
+msgstr ""
+
+msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
+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 "Iterations|Upcoming iterations"
+msgstr ""
+
+msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
+msgstr ""
+
+msgid "Iteration|cannot be more than 500 years in the future"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Japanese language support using"
+msgstr ""
+
+msgid "Jira display name"
+msgstr ""
+
+msgid "Jira import is already running."
+msgstr ""
+
+msgid "Jira integration not configured."
+msgstr ""
+
+msgid "Jira project key is not configured."
+msgstr ""
+
+msgid "Jira project: %{importProject}"
+msgstr ""
+
+msgid "Jira service not configured."
+msgstr ""
+
+msgid "Jira user"
+msgstr ""
+
+msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
+msgstr ""
+
+msgid "Jira-GitLab user mapping template"
+msgstr ""
+
+msgid "JiraConnect|Cannot find namespace. Make sure you have sufficient permissions."
+msgstr ""
+
+msgid "JiraConnect|Configure your Jira Connect Application ID."
+msgstr ""
+
+msgid "JiraConnect|Could not fetch user information from Jira. Check the permissions in Jira and try again."
+msgstr ""
+
+msgid "JiraConnect|Create branch for Jira issue %{jiraIssue}"
+msgstr ""
+
+msgid "JiraConnect|Failed to create branch."
+msgstr ""
+
+msgid "JiraConnect|Failed to create branch. Please try again."
+msgstr ""
+
+msgid "JiraConnect|GitLab for Jira App"
+msgstr ""
+
+msgid "JiraConnect|Jira Connect Application ID"
+msgstr ""
+
+msgid "JiraConnect|New branch was successfully created."
+msgstr ""
+
+msgid "JiraConnect|The Jira user is not a site administrator. Check the permissions in Jira and try again."
+msgstr ""
+
+msgid "JiraConnect|You can now close this window and return to Jira."
+msgstr ""
+
+msgid "JiraConnect|You don't have permission to create branches for this project. Select a different project or contact the project owner for access. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "JiraRequest|A connection error occurred while connecting to Jira. Try your request again."
+msgstr ""
+
+msgid "JiraRequest|A timeout error occurred while connecting to Jira. Try your request again."
+msgstr ""
+
+msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
+msgstr ""
+
+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 ""
+
+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 ""
+
+msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
+msgstr ""
+
+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 ""
+
+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 ""
+
+msgid "JiraService| on branch %{branch_link}"
+msgstr ""
+
+msgid "JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgstr ""
+
+msgid "JiraService|An error occurred while fetching issue list"
+msgstr ""
+
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Base URL of the Jira instance."
+msgstr ""
+
+msgid "JiraService|Change GitLab version"
+msgstr ""
+
+msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
+msgstr ""
+
+msgid "JiraService|Displaying Jira issues while leaving GitLab issues also enabled might be confusing. Consider %{gitlab_issues_link_start}disabling GitLab issues%{link_end} if they won't otherwise be used."
+msgstr ""
+
+msgid "JiraService|Enable Jira issue creation from vulnerabilities"
+msgstr ""
+
+msgid "JiraService|Enable Jira issues"
+msgstr ""
+
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
+msgid "JiraService|For example, AB"
+msgstr ""
+
+msgid "JiraService|For example: https://gitlab.example.com"
+msgstr ""
+
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
+msgid "JiraService|GitLab instance URL"
+msgstr ""
+
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
+msgid "JiraService|If different from Web URL."
+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 comments are created when an issue is referenced in a commit."
+msgstr ""
+
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issues"
+msgstr ""
+
+msgid "JiraService|Jira project key"
+msgstr ""
+
+msgid "JiraService|Leave blank to use your current password or API token."
+msgstr ""
+
+msgid "JiraService|Move to Done"
+msgstr ""
+
+msgid "JiraService|Open Jira"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Project key changed, refresh list"
+msgstr ""
+
+msgid "JiraService|Project key is required to generate issue types"
+msgstr ""
+
+msgid "JiraService|Select issue type"
+msgstr ""
+
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Sign in to GitLab to link namespaces."
+msgstr ""
+
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
+msgid "JiraService|Use Jira as this project's issue tracker."
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version."
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version."
+msgstr ""
+
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
+msgid "JiraService|Warning: All GitLab users with access to this GitLab project can view all issues from the Jira project you select."
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|Welcome to GitLab for Jira"
+msgstr ""
+
+msgid "JiraService|What version of GitLab are you using?"
+msgstr ""
+
+msgid "JiraService|When a Jira issue is mentioned in a commit or merge request, a remote link and comment (if enabled) will be created."
+msgstr ""
+
+msgid "JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues."
+msgstr ""
+
+msgid "JiraService|Work on Jira issues without leaving GitLab. Add a Jira menu to access a read-only list of your Jira issues. %{jira_issues_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "JiraService|You can now close this window and%{br}return to the GitLab for Jira application."
+msgstr ""
+
+msgid "JiraService|You must configure Jira before enabling this integration. %{jira_doc_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job %{jobName}"
+msgstr ""
+
+msgid "Job Failed #%{build_id}"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job has been successfully erased!"
+msgstr ""
+
+msgid "Job has wrong arguments format."
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job logs and artifacts"
+msgstr ""
+
+msgid "Job to create self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job to delete self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Jobs fail if they run longer than the timeout time. Input value is in seconds by default. Human readable input is also accepted, for example %{code_open}1 hour%{code_close}."
+msgstr ""
+
+msgid "Jobs older than the configured time are considered expired and are archived. Archived jobs can no longer be retried. Leave empty to never archive jobs automatically. The default unit is in days, but you can use other units, for example %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}. Minimum value is 1 day."
+msgstr ""
+
+msgid "Jobs|All"
+msgstr ""
+
+msgid "Jobs|An error occurred while loading the Failed Jobs tab."
+msgstr ""
+
+msgid "Jobs|Are you sure you want to proceed?"
+msgstr ""
+
+msgid "Jobs|Are you sure you want to retry this job?"
+msgstr ""
+
+msgid "Jobs|Create CI/CD configuration file"
+msgstr ""
+
+msgid "Jobs|Filter jobs"
+msgstr ""
+
+msgid "Jobs|Finished"
+msgstr ""
+
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
+msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
+msgstr ""
+
+msgid "Jobs|No jobs to show"
+msgstr ""
+
+msgid "Jobs|Raw text search is not currently supported for the jobs filtered search feature. Please use the available search tokens."
+msgstr ""
+
+msgid "Jobs|Status"
+msgstr ""
+
+msgid "Jobs|There was a problem fetching the failed jobs."
+msgstr ""
+
+msgid "Jobs|Use jobs to automate your tasks"
+msgstr ""
+
+msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
+msgstr ""
+
+msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id}"
+msgstr ""
+
+msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source}"
+msgstr ""
+
+msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source} into %{target}"
+msgstr ""
+
+msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
+msgstr ""
+
+msgid "Job|%{searchLength} results found for %{searchTerm}"
+msgstr ""
+
+msgid "Job|Are you sure you want to erase this job log and artifacts?"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Cancel"
+msgstr ""
+
+msgid "Job|Canceled"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Created"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log and artifacts"
+msgstr ""
+
+msgid "Job|Failed"
+msgstr ""
+
+msgid "Job|Finished at"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
+
+msgid "Job|Job log search"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Manual"
+msgstr ""
+
+msgid "Job|No search results found"
+msgstr ""
+
+msgid "Job|Passed"
+msgstr ""
+
+msgid "Job|Pending"
+msgstr ""
+
+msgid "Job|Preparing"
+msgstr ""
+
+msgid "Job|Retry"
+msgstr ""
+
+msgid "Job|Running"
+msgstr ""
+
+msgid "Job|Scheduled"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to next failure"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Search for substrings in your job log output. Currently search is only supported for the visible job log output, not for any log output that is truncated due to size."
+msgstr ""
+
+msgid "Job|Search job log"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|Skipped"
+msgstr ""
+
+msgid "Job|Status"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|There was a problem retrying the failed job."
+msgstr ""
+
+msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
+msgstr ""
+
+msgid "Job|This job failed because the necessary resources were not successfully created."
+msgstr ""
+
+msgid "Job|This job is stuck because of one of the following problems. There are no active runners online, no runners for the %{linkStart}protected branch%{linkEnd}, or no runners that match all of the job's tags:"
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "Job|Waiting for resource"
+msgstr ""
+
+msgid "Job|We could not find this element"
+msgstr ""
+
+msgid "Job|allowed to fail"
+msgstr ""
+
+msgid "Job|delayed"
+msgstr ""
+
+msgid "Job|manual"
+msgstr ""
+
+msgid "Job|triggered"
+msgstr ""
+
+msgid "Join GitLab today! You and your team can plan, build, and ship secure code all in one application. Get started here for free!"
+msgstr ""
+
+msgid "Join Zoom meeting"
+msgstr ""
+
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
+msgid "Joined %{time_ago}"
+msgstr ""
+
+msgid "Joined %{user_created_time}"
+msgstr ""
+
+msgid "Joined projects (%{projects_count})"
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Just me"
+msgstr ""
+
+msgid "K8s pod health"
+msgstr ""
+
+msgid "KEY"
+msgstr ""
+
+msgid "Keep"
+msgstr ""
+
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Keeping all SAST analyzers enabled future-proofs the project in case new languages are added later on. Determining which analyzers apply is a process that consumes minimal resources and adds minimal time to the pipeline. Leaving all SAST analyzers enabled ensures maximum coverage."
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key:"
+msgstr ""
+
+msgid "Keyboard shortcuts"
+msgstr ""
+
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl+"
+msgstr ""
+
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
+msgid "Keys"
+msgstr ""
+
+msgid "Ki"
+msgstr ""
+
+msgid "Kroki"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration and resources are being removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes clusters"
+msgstr ""
+
+msgid "Kubernetes deployment not found"
+msgstr ""
+
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
+msgid "LDAP"
+msgstr ""
+
+msgid "LDAP Synchronization"
+msgstr ""
+
+msgid "LDAP group settings"
+msgstr ""
+
+msgid "LDAP settings"
+msgstr ""
+
+msgid "LDAP settings updated"
+msgstr ""
+
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
+msgid "LDAP synchronizations"
+msgstr ""
+
+msgid "LDAP uid:"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFS objects"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "LICENSE"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label added: %{labels}"
+msgid_plural "Labels added: %{labels}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Label priority"
+msgstr ""
+
+msgid "Label was created"
+msgstr ""
+
+msgid "Label was removed"
+msgstr ""
+
+msgid "Label was successfully updated."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests. Star a label to make it a priority label."
+msgstr ""
+
+msgid "Labels with no issues in this iteration:"
+msgstr ""
+
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Label|Assignee"
+msgstr ""
+
+msgid "Language"
+msgstr ""
+
+msgid "Language type"
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last %{days} days"
+msgstr ""
+
+msgid "Last 2 weeks"
+msgstr ""
+
+msgid "Last 30 days"
+msgstr ""
+
+msgid "Last 60 days"
+msgstr ""
+
+msgid "Last 90 days"
+msgstr ""
+
+msgid "Last Accessed On"
+msgstr ""
+
+msgid "Last Activity"
+msgstr ""
+
+msgid "Last Name"
+msgstr ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+msgstr ""
+
+msgid "Last Sync"
+msgstr ""
+
+msgid "Last Used"
+msgstr ""
+
+msgid "Last accessed on"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
+
+msgid "Last event"
+msgstr ""
+
+msgid "Last item before this page loaded in your browser:"
+msgstr ""
+
+msgid "Last modified"
+msgstr ""
+
+msgid "Last month"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last sign-in"
+msgstr ""
+
+msgid "Last sign-in IP:"
+msgstr ""
+
+msgid "Last sign-in at:"
+msgstr ""
+
+msgid "Last successful update"
+msgstr ""
+
+msgid "Last successful update %{time}."
+msgstr ""
+
+msgid "Last time verified"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last update attempt"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "Last updated %{time} ago"
+msgstr ""
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
+msgid "Last week"
+msgstr ""
+
+msgid "Last year"
+msgstr ""
+
+msgid "LastCommit|authored"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for the most recent commit on this branch"
+msgstr ""
+
+msgid "Launch a ready-to-code development environment for your project."
+msgstr ""
+
+msgid "Layout|Fixed"
+msgstr ""
+
+msgid "Layout|Fluid"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Lead Time for Changes"
+msgstr ""
+
+msgid "Lead time"
+msgstr ""
+
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn More"
+msgstr ""
+
+msgid "Learn More."
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{name}"
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about GitLab"
+msgstr ""
+
+msgid "Learn more about Needs relationships"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about X.509 signed commits"
+msgstr ""
+
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about deploying to AWS"
+msgstr ""
+
+msgid "Learn more about deploying to a cluster"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about groups."
+msgstr ""
+
+msgid "Learn more about issues."
+msgstr ""
+
+msgid "Learn more about max seats used"
+msgstr ""
+
+msgid "Learn more about seats owed"
+msgstr ""
+
+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 ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more."
+msgstr ""
+
+msgid "LearnGitLab|%{percentage}%{percentSymbol} completed"
+msgstr ""
+
+msgid "LearnGitLab|Add code owners"
+msgstr ""
+
+msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
+msgstr ""
+
+msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
+msgstr ""
+
+msgid "LearnGitLab|Create a repository"
+msgstr ""
+
+msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
+msgstr ""
+
+msgid "LearnGitLab|Create an issue"
+msgstr ""
+
+msgid "LearnGitLab|Create or import your first repository into your new project."
+msgstr ""
+
+msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work."
+msgstr ""
+
+msgid "LearnGitLab|Deploy"
+msgstr ""
+
+msgid "LearnGitLab|Enable require merge approvals"
+msgstr ""
+
+msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features."
+msgstr ""
+
+msgid "LearnGitLab|Invite your colleagues"
+msgstr ""
+
+msgid "LearnGitLab|Learn GitLab"
+msgstr ""
+
+msgid "LearnGitLab|Plan and execute"
+msgstr ""
+
+msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths."
+msgstr ""
+
+msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
+msgstr ""
+
+msgid "LearnGitLab|Review and edit proposed changes to source code."
+msgstr ""
+
+msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
+msgstr ""
+
+msgid "LearnGitLab|Run a Security scan using CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
+msgstr ""
+
+msgid "LearnGitLab|Scan dependencies for licenses"
+msgstr ""
+
+msgid "LearnGitLab|Scan dependencies for vulnerabilities"
+msgstr ""
+
+msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
+msgstr ""
+
+msgid "LearnGitLab|Set up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Set up your first project's CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Set up your workspace"
+msgstr ""
+
+msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request (MR)"
+msgstr ""
+
+msgid "LearnGitLab|Try GitLab Ultimate for free"
+msgstr ""
+
+msgid "LearnGitLab|Try all GitLab features for 30 days, no credit card required."
+msgstr ""
+
+msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
+msgstr ""
+
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
+msgid "LearnGitlab|- Included in trial"
+msgstr ""
+
+msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
+msgstr ""
+
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
+msgid "LearnGitlab|View administrator list"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave Admin Mode"
+msgstr ""
+
+msgid "Leave edit mode? All unsaved changes will be lost."
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave zen mode"
+msgstr ""
+
+msgid "Leaving this setting enabled is recommended."
+msgstr ""
+
+msgid "Legacy burndown chart"
+msgstr ""
+
+msgid "Legacy license"
+msgstr ""
+
+msgid "Less Details"
+msgstr ""
+
+msgid "Less restrictive visibility"
+msgstr ""
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "License Compliance"
+msgstr ""
+
+msgid "License Compliance| Used by %{dependencies}"
+msgstr ""
+
+msgid "License compliance"
+msgstr ""
+
+msgid "License key"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable for use in this project"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related policy"
+msgstr ""
+
+msgid "LicenseCompliance|Add license policy"
+msgstr ""
+
+msgid "LicenseCompliance|Allow"
+msgstr ""
+
+msgid "LicenseCompliance|Allowed"
+msgstr ""
+
+msgid "LicenseCompliance|Denied"
+msgstr ""
+
+msgid "LicenseCompliance|Deny"
+msgstr ""
+
+msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
+msgstr ""
+
+msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected no new licenses"
+msgstr ""
+
+msgid "LicenseCompliance|License name"
+msgstr ""
+
+msgid "LicenseCompliance|No policy matches this license"
+msgstr ""
+
+msgid "LicenseCompliance|Out-of-compliance with the project's policies and should be removed"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license?"
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
+
+msgid "LicenseCompliance|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseCompliance|Uncategorized"
+msgstr ""
+
+msgid "LicenseCompliance|Update approvals"
+msgstr ""
+
+msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "LicenseManagement|Allowed"
+msgstr ""
+
+msgid "LicenseManagement|Denied"
+msgstr ""
+
+msgid "LicenseManagement|Uncategorized"
+msgstr ""
+
+msgid "Licensed Enterprise Edition features can be used if the project namespace's plan includes the feature, or if the project is public."
+msgstr ""
+
+msgid "Licensed Features"
+msgstr ""
+
+msgid "Licensed to:"
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Licenses|%{remainingComponentsCount} more"
+msgstr ""
+
+msgid "Licenses|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "Licenses|Component"
+msgstr ""
+
+msgid "Licenses|Components"
+msgstr ""
+
+msgid "Licenses|Detected in Project"
+msgstr ""
+
+msgid "Licenses|Displays licenses detected in the project that are out of compliance with the project's policies, based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Licenses|Drag your license file here or %{linkStart}click to upload%{linkEnd}."
+msgstr ""
+
+msgid "Licenses|Drop your license file to start the upload."
+msgstr ""
+
+msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Licenses|Error: You are trying to upload something other than a file"
+msgstr ""
+
+msgid "Licenses|License Compliance"
+msgstr ""
+
+msgid "Licenses|Name"
+msgstr ""
+
+msgid "Licenses|Policies"
+msgstr ""
+
+msgid "Licenses|Policy"
+msgstr ""
+
+msgid "Licenses|Policy violation: denied"
+msgstr ""
+
+msgid "Licenses|Specified policies in this project"
+msgstr ""
+
+msgid "Licenses|The file could not be uploaded."
+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 sign in from multiple IP addresses"
+msgstr ""
+
+msgid "Limit the number of inbound incident management alerts that can be sent to a project."
+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 pipeline creation requests per minute. This limit includes pipelines created through the UI, the API, and by background processing."
+msgstr ""
+
+msgid "Limit the size of Sidekiq jobs stored in Redis."
+msgstr ""
+
+msgid "Limiting mode"
+msgstr ""
+
+msgid "Line changes"
+msgstr ""
+
+msgid "Link"
+msgstr ""
+
+msgid "Link (optional)"
+msgstr ""
+
+msgid "Link Sentry to GitLab to discover and view the errors your application generates."
+msgstr ""
+
+msgid "Link URL"
+msgstr ""
+
+msgid "Link an external wiki from the project's sidebar. %{docs_link}"
+msgstr ""
+
+msgid "Link copied"
+msgstr ""
+
+msgid "Link text"
+msgstr ""
+
+msgid "Link title"
+msgstr ""
+
+msgid "Link title is required"
+msgstr ""
+
+msgid "Link to go to GitLab pipeline documentation"
+msgstr ""
+
+msgid "Link to your Grafana instance."
+msgstr ""
+
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
+msgid "Linked epics"
+msgstr ""
+
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "LinkedIn:"
+msgstr ""
+
+msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
+msgstr ""
+
+msgid "LinkedResources|Add"
+msgstr ""
+
+msgid "LinkedResources|Add a resource link"
+msgstr ""
+
+msgid "LinkedResources|Cancel"
+msgstr ""
+
+msgid "LinkedResources|Error creating resource link for the incident: %{error}"
+msgstr ""
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr ""
+
+msgid "LinkedResources|Fetching linked resources"
+msgstr ""
+
+msgid "LinkedResources|Link"
+msgstr ""
+
+msgid "LinkedResources|Linked resources"
+msgstr ""
+
+msgid "LinkedResources|Remove"
+msgstr ""
+
+msgid "LinkedResources|Something went wrong while creating the resource link for the incident."
+msgstr ""
+
+msgid "LinkedResources|Something went wrong while deleting the linked resource for the incident."
+msgstr ""
+
+msgid "LinkedResources|Something went wrong while fetching linked resources for the incident."
+msgstr ""
+
+msgid "LinkedResources|Text (Optional)"
+msgstr ""
+
+msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List of all merge commits"
+msgstr ""
+
+msgid "List of suitable GCP locations"
+msgstr ""
+
+msgid "List of users who are allowed to exceed the rate limit. Example: username1, username2"
+msgstr ""
+
+msgid "List options"
+msgstr ""
+
+msgid "List settings"
+msgstr ""
+
+msgid "List the merge requests that must be merged before this one."
+msgstr ""
+
+msgid "List the visible events for %{project_link} using the %{events_api_link}."
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Load more"
+msgstr ""
+
+msgid "Load more users"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "Loading %{name}"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Loading more"
+msgstr ""
+
+msgid "Loading snippet"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading, please wait."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Location"
+msgstr ""
+
+msgid "Location:"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock File?"
+msgstr ""
+
+msgid "Lock memberships to LDAP synchronization"
+msgstr ""
+
+msgid "Lock merge request"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock the discussion"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked by %{fileLockUserName}"
+msgstr ""
+
+msgid "Locked the discussion."
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Locks the discussion."
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|About GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Explore GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Get started"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab Learn"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab docs"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|How GitLab compares"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Install GitLab"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Pricing"
+msgstr ""
+
+msgid "LoggedOutMarketingHeader|Talk to an expert"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logo was successfully removed."
+msgstr ""
+
+msgid "Logo will be removed. Are you sure?"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Looks like you've reached your %{free_limit} member limit for %{strong_start}%{namespace_name}%{strong_end}"
+msgstr ""
+
+msgid "Low vulnerabilities present"
+msgstr ""
+
+msgid "MB"
+msgstr ""
+
+msgid "MD5"
+msgstr ""
+
+msgid "MERGED"
+msgstr ""
+
+msgid "MR widget|Back to the merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
+msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
+msgstr ""
+
+msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgstr ""
+
+msgid "MRApprovals|Approvals"
+msgstr ""
+
+msgid "MRApprovals|Approved by"
+msgstr ""
+
+msgid "MRApprovals|Approvers"
+msgstr ""
+
+msgid "MRApprovals|Commented by"
+msgstr ""
+
+msgid "MRDiffFile|Changes are too large to be shown."
+msgstr ""
+
+msgid "MRDiffFile|View file @ %{commitSha}"
+msgstr ""
+
+msgid "MRDiff|Show changes only"
+msgstr ""
+
+msgid "MRDiff|Show full file"
+msgstr ""
+
+msgid "Made this issue confidential."
+msgstr ""
+
+msgid "Mailgun"
+msgstr ""
+
+msgid "Mailgun HTTP webhook signing key"
+msgstr ""
+
+msgid "Mailgun events"
+msgstr ""
+
+msgid "Main menu"
+msgstr ""
+
+msgid "Maintenance mode"
+msgstr ""
+
+msgid "Make adjustments to how your GitLab instance is set up."
+msgstr ""
+
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make issue confidential"
+msgstr ""
+
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
+msgid "Make sure you have the correct permissions to link your project."
+msgstr ""
+
+msgid "Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "Makes this issue confidential."
+msgstr ""
+
+msgid "Manage %{workspace} labels"
+msgstr ""
+
+msgid "Manage Web IDE features."
+msgstr ""
+
+msgid "Manage access"
+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 use GitLab as an OAuth provider."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage git repositories with fine-grained access controls that keep your code secure."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage members"
+msgstr ""
+
+msgid "Manage milestones"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage projects."
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your project's triggers"
+msgstr ""
+
+msgid "Manage your subscription"
+msgstr ""
+
+msgid "Managed Account"
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Manifest import"
+msgstr ""
+
+msgid "Manual"
+msgstr ""
+
+msgid "ManualOrdering|Couldn't save the order of the issues"
+msgstr ""
+
+msgid "Manually link this issue by adding it to the linked issue section of the %{linkStart}originating vulnerability%{linkEnd}."
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark as done"
+msgstr ""
+
+msgid "Mark as draft"
+msgstr ""
+
+msgid "Mark as ready"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark this issue as related to another issue"
+msgstr ""
+
+msgid "Mark to do as done"
+msgstr ""
+
+msgid "Markdown Help"
+msgstr ""
+
+msgid "Markdown enabled."
+msgstr ""
+
+msgid "Markdown supported."
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add strikethrough text (%{modifierKey}⇧X)"
+msgstr ""
+
+msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
+msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgstr ""
+
+msgid "Marked"
+msgstr ""
+
+msgid "Marked For Deletion At - %{deletion_time}"
+msgstr ""
+
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
+msgid "Marked as ready. Merging is now allowed."
+msgstr ""
+
+msgid "Marked this %{noun} as ready."
+msgstr ""
+
+msgid "Marked this issue as a duplicate of %{duplicate_param}."
+msgstr ""
+
+msgid "Marked this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marked to do as done."
+msgstr ""
+
+msgid "Marks"
+msgstr ""
+
+msgid "Marks this %{noun} as ready."
+msgstr ""
+
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marks to do as done."
+msgstr ""
+
+msgid "Mask variable"
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
+msgid "Mattermost"
+msgstr ""
+
+msgid "Mattermost URL:"
+msgstr ""
+
+msgid "Mattermost notifications"
+msgstr ""
+
+msgid "MattermostService|Add to Mattermost"
+msgstr ""
+
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
+msgid "MattermostService|Command trigger word"
+msgstr ""
+
+msgid "MattermostService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "MattermostService|Request URL"
+msgstr ""
+
+msgid "MattermostService|Request method"
+msgstr ""
+
+msgid "MattermostService|Response icon"
+msgstr ""
+
+msgid "MattermostService|Response username"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max 100,000 events"
+msgstr ""
+
+msgid "Max Value"
+msgstr ""
+
+msgid "Max authenticated Git LFS requests per period per user"
+msgstr ""
+
+msgid "Max file size is 200 KB."
+msgstr ""
+
+msgid "Max role"
+msgstr ""
+
+msgid "Max seats used"
+msgstr ""
+
+msgid "Max session time"
+msgstr ""
+
+msgid "Maximum 20 characters"
+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 ""
+
+msgid "Maximum NuGet package file size in bytes"
+msgstr ""
+
+msgid "Maximum PyPI package file size in bytes"
+msgstr ""
+
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
+msgid "Maximum Users"
+msgstr ""
+
+msgid "Maximum allowable lifetime for access token (days)"
+msgstr ""
+
+msgid "Maximum allowed lifetime for SSH keys (days)"
+msgstr ""
+
+msgid "Maximum artifacts size"
+msgstr ""
+
+msgid "Maximum artifacts size (MB)"
+msgstr ""
+
+msgid "Maximum attachment size"
+msgstr ""
+
+msgid "Maximum attachment size (MB)"
+msgstr ""
+
+msgid "Maximum authenticated API requests per rate limit period per user"
+msgstr ""
+
+msgid "Maximum authenticated web requests per rate limit period per user"
+msgstr ""
+
+msgid "Maximum bulk request size (MiB)"
+msgstr ""
+
+msgid "Maximum capacity"
+msgstr ""
+
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
+msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
+msgstr ""
+
+msgid "Maximum delay (Minutes)"
+msgstr ""
+
+msgid "Maximum diff patch size"
+msgstr ""
+
+msgid "Maximum diff patch size (Bytes)"
+msgstr ""
+
+msgid "Maximum duration of a session."
+msgstr ""
+
+msgid "Maximum export size"
+msgstr ""
+
+msgid "Maximum export size (MB)"
+msgstr ""
+
+msgid "Maximum field length"
+msgstr ""
+
+msgid "Maximum file size indexed (KiB)"
+msgstr ""
+
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr ""
+
+msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
+msgstr ""
+
+msgid "Maximum file size is 1MB. Pages are optimized for a 640x360 px logo."
+msgstr ""
+
+msgid "Maximum files in a diff"
+msgstr ""
+
+msgid "Maximum group export download requests per minute"
+msgstr ""
+
+msgid "Maximum group export requests per minute"
+msgstr ""
+
+msgid "Maximum group import requests per minute"
+msgstr ""
+
+msgid "Maximum import size"
+msgstr ""
+
+msgid "Maximum import size (MB)"
+msgstr ""
+
+msgid "Maximum job artifact size"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
+msgid "Maximum lines in a diff"
+msgstr ""
+
+msgid "Maximum npm package file size in bytes"
+msgstr ""
+
+msgid "Maximum number of %{name} (%{count}) exceeded"
+msgstr ""
+
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
+msgid "Maximum number of comments exceeded"
+msgstr ""
+
+msgid "Maximum number of mirrors that can be synchronizing at the same time."
+msgstr ""
+
+msgid "Maximum number of projects."
+msgstr ""
+
+msgid "Maximum number of requests per minute"
+msgstr ""
+
+msgid "Maximum number of requests per minute for an authenticated user"
+msgstr ""
+
+msgid "Maximum number of requests per minute for an unauthenticated IP address"
+msgstr ""
+
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
+msgid "Maximum number of unique IP addresses per user."
+msgstr ""
+
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
+msgid "Maximum of 255 characters"
+msgstr ""
+
+msgid "Maximum page reached"
+msgstr ""
+
+msgid "Maximum page size"
+msgstr ""
+
+msgid "Maximum project export download requests per minute"
+msgstr ""
+
+msgid "Maximum project export requests per minute"
+msgstr ""
+
+msgid "Maximum project import requests per minute"
+msgstr ""
+
+msgid "Maximum push size"
+msgstr ""
+
+msgid "Maximum push size (MB)"
+msgstr ""
+
+msgid "Maximum requests per 10 minutes per user"
+msgstr ""
+
+msgid "Maximum requests per minute"
+msgstr ""
+
+msgid "Maximum running slices"
+msgstr ""
+
+msgid "Maximum size limit for a single commit."
+msgstr ""
+
+msgid "Maximum size limit for each repository."
+msgstr ""
+
+msgid "Maximum size of Elasticsearch bulk indexing requests."
+msgstr ""
+
+msgid "Maximum size of export files."
+msgstr ""
+
+msgid "Maximum size of import files."
+msgstr ""
+
+msgid "Maximum size of individual attachments in comments."
+msgstr ""
+
+msgid "Maximum size of pages (MB)"
+msgstr ""
+
+msgid "Maximum snippet size"
+msgstr ""
+
+msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
+msgstr ""
+
+msgid "Maximum time that users are allowed to skip the setup of two-factor authentication (in hours). Set to 0 (zero) to enforce at next sign in."
+msgstr ""
+
+msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited."
+msgstr ""
+
+msgid "Maximum unauthenticated API requests per rate limit period per IP"
+msgstr ""
+
+msgid "Maximum unauthenticated web requests per rate limit period per IP"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Mean time to merge"
+msgstr ""
+
+msgid "Measured in bytes of code. Excludes generated and vendored code."
+msgstr ""
+
+msgid "Medium timeout"
+msgstr ""
+
+msgid "Medium vulnerabilities present"
+msgstr ""
+
+msgid "Member since"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Member since:"
+msgstr ""
+
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr ""
+
+msgid "Members listed as CODEOWNERS of affected files."
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "Members of a group may only view projects they have permission to access"
+msgstr ""
+
+msgid "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seat in use and will be billed for the overage."
+msgid_plural "MembersOverage|If you continue, the %{groupName} group will have %{quantity} seats in use and will be billed for the overage."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "MembersOverage|You are about to incur additional charges"
+msgstr ""
+
+msgid "MembersOverage|Your subscription includes %d seat."
+msgid_plural "MembersOverage|Your subscription includes %d seats."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Membership"
+msgstr ""
+
+msgid "Members|%{time} by %{user}"
+msgstr ""
+
+msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|2FA"
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Direct"
+msgstr ""
+
+msgid "Members|Disabled"
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Enabled"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
+msgid "Members|Filter groups"
+msgstr ""
+
+msgid "Members|Filter members"
+msgstr ""
+
+msgid "Members|Inherited"
+msgstr ""
+
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
+msgid "Members|Membership"
+msgstr ""
+
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
+msgid "Members|Search groups"
+msgstr ""
+
+msgid "Members|Search invited"
+msgstr ""
+
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Menu"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge Conflicts"
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request Analytics"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge Requests in Review"
+msgstr ""
+
+msgid "Merge Requests merged"
+msgstr ""
+
+msgid "Merge automatically (%{strategy})"
+msgstr ""
+
+msgid "Merge blocked: all merge request dependencies must be merged."
+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 ""
+
+msgid "Merge blocked: the source branch must be rebased onto the target branch."
+msgstr ""
+
+msgid "Merge commit SHA"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge details"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge locally"
+msgstr ""
+
+msgid "Merge options"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
+msgstr ""
+
+msgid "Merge request actions"
+msgstr ""
+
+msgid "Merge request analytics"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge request commits"
+msgstr ""
+
+msgid "Merge request dependencies"
+msgstr ""
+
+msgid "Merge request events"
+msgstr ""
+
+msgid "Merge request locked."
+msgstr ""
+
+msgid "Merge request not merged"
+msgstr ""
+
+msgid "Merge request reports"
+msgstr ""
+
+msgid "Merge request unlocked."
+msgstr ""
+
+msgid "Merge request was scheduled to merge after pipeline succeeds"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests and approvals settings have moved."
+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 the feature branch into the target branch and fix any conflicts. %{linkStart}How do I fix them?%{linkEnd}"
+msgstr ""
+
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
+msgstr ""
+
+msgid "Merge unverified changes"
+msgstr ""
+
+msgid "Merge unverified changes?"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "Merge..."
+msgstr ""
+
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Select comment starting line"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Create issue to resolve thread"
+msgstr ""
+
+msgid "MergeRequests|Reference copied"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch."
+msgstr ""
+
+msgid "MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging."
+msgstr ""
+
+msgid "MergeRequests|Thread stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a thread"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest|Approved by @%{username}"
+msgstr ""
+
+msgid "MergeRequest|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 %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch."
+msgstr ""
+
+msgid "MergeRequest|Compare %{target} and %{source}"
+msgstr ""
+
+msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
+msgstr ""
+
+msgid "MergeRequest|Error loading full diff. Please try again."
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
+msgstr ""
+
+msgid "MergeTopics|%{sourceTopic} will be removed"
+msgstr ""
+
+msgid "MergeTopics|All assigned projects will be moved to %{targetTopic}"
+msgstr ""
+
+msgid "MergeTopics|Merge topics"
+msgstr ""
+
+msgid "MergeTopics|Merging topics will cause the following:"
+msgstr ""
+
+msgid "MergeTopics|Move all assigned projects from the source topic to the target topic and remove the source topic."
+msgstr ""
+
+msgid "MergeTopics|Source topic"
+msgstr ""
+
+msgid "MergeTopics|Target topic"
+msgstr ""
+
+msgid "MergeTopics|This action cannot be undone."
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Merged MRs"
+msgstr ""
+
+msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Merged by"
+msgstr ""
+
+msgid "Merged this merge request."
+msgstr ""
+
+msgid "Merged: %{merged}"
+msgstr ""
+
+msgid "Merges this merge request immediately."
+msgstr ""
+
+msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
+msgstr ""
+
+msgid "Mermaid diagram"
+msgstr ""
+
+msgid "Message"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Method"
+msgstr ""
+
+msgid "Method call threshold (ms)"
+msgstr ""
+
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
+msgid "Metric:"
+msgstr ""
+
+msgid "MetricChart|Please select a metric"
+msgstr ""
+
+msgid "MetricChart|Selected"
+msgstr ""
+
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "MetricImages|There was an issue deleting the image."
+msgstr ""
+
+msgid "MetricImages|There was an issue loading metric images."
+msgstr ""
+
+msgid "MetricImages|There was an issue updating your image."
+msgstr ""
+
+msgid "MetricImages|There was an issue uploading your image."
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Grafana"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics Dashboard"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is invalid:"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is valid."
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics:"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
+msgstr ""
+
+msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
+msgstr ""
+
+msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
+msgstr ""
+
+msgid "MetricsSettings|Dashboard timezone"
+msgstr ""
+
+msgid "MetricsSettings|External dashboard URL"
+msgstr ""
+
+msgid "MetricsSettings|Manage metrics dashboard settings."
+msgstr ""
+
+msgid "MetricsSettings|Metrics"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
+msgid "Metrics|1. Define and preview panel"
+msgstr ""
+
+msgid "Metrics|2. Paste panel YAML into dashboard"
+msgstr ""
+
+msgid "Metrics|Add metric"
+msgstr ""
+
+msgid "Metrics|Add panel"
+msgstr ""
+
+msgid "Metrics|Avg"
+msgstr ""
+
+msgid "Metrics|Back to dashboard"
+msgstr ""
+
+msgid "Metrics|Cancel"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
+msgid "Metrics|Copy YAML"
+msgstr ""
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr ""
+
+msgid "Metrics|Create custom dashboard %{fileName}"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Create new dashboard"
+msgstr ""
+
+msgid "Metrics|Create your dashboard configuration file"
+msgstr ""
+
+msgid "Metrics|Current"
+msgstr ""
+
+msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Define panel YAML below to preview panel."
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Duplicate"
+msgstr ""
+
+msgid "Metrics|Duplicate current dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
+msgid "Metrics|Duplicating..."
+msgstr ""
+
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgid_plural "Metrics|Edit metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Metrics|Expand panel"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Invalid time range, please verify."
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
+msgstr ""
+
+msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
+msgstr ""
+
+msgid "Metrics|Manage chart links"
+msgstr ""
+
+msgid "Metrics|Max"
+msgstr ""
+
+msgid "Metrics|Metrics Settings"
+msgstr ""
+
+msgid "Metrics|Min"
+msgstr ""
+
+msgid "Metrics|More actions"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|Open repository"
+msgstr ""
+
+msgid "Metrics|Panel YAML"
+msgstr ""
+
+msgid "Metrics|Panel YAML copied"
+msgstr ""
+
+msgid "Metrics|Preview panel"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
+msgid "Metrics|Refresh dashboard"
+msgstr ""
+
+msgid "Metrics|Select a value"
+msgstr ""
+
+msgid "Metrics|Set refresh rate"
+msgstr ""
+
+msgid "Metrics|Star dashboard"
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard."
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard. %{error}"
+msgstr ""
+
+msgid "Metrics|There was an error fetching annotations. Please try again."
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting annotations information."
+msgstr ""
+
+msgid "Metrics|There was an error getting dashboard validation warnings information."
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error getting options for variable \"%{name}\"."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics. %{message}"
+msgstr ""
+
+msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Unstar dashboard"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Validating query"
+msgstr ""
+
+msgid "Metrics|Values"
+msgstr ""
+
+msgid "Metrics|View documentation"
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You can save a copy of this dashboard to your repository so it can be customized. Select a file name and branch to save it."
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Mi"
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration"
+msgstr ""
+
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone due date"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Group milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
+msgid "MilestoneSidebar|Closed:"
+msgstr ""
+
+msgid "MilestoneSidebar|Copy reference"
+msgstr ""
+
+msgid "MilestoneSidebar|Due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Edit"
+msgstr ""
+
+msgid "MilestoneSidebar|From"
+msgstr ""
+
+msgid "MilestoneSidebar|Issues"
+msgstr ""
+
+msgid "MilestoneSidebar|Merge requests"
+msgstr ""
+
+msgid "MilestoneSidebar|Merged:"
+msgstr ""
+
+msgid "MilestoneSidebar|New Issue"
+msgstr ""
+
+msgid "MilestoneSidebar|New issue"
+msgstr ""
+
+msgid "MilestoneSidebar|No due date"
+msgstr ""
+
+msgid "MilestoneSidebar|No start date"
+msgstr ""
+
+msgid "MilestoneSidebar|None"
+msgstr ""
+
+msgid "MilestoneSidebar|Open:"
+msgstr ""
+
+msgid "MilestoneSidebar|Reference:"
+msgstr ""
+
+msgid "MilestoneSidebar|Start date"
+msgstr ""
+
+msgid "MilestoneSidebar|Toggle sidebar"
+msgstr ""
+
+msgid "MilestoneSidebar|Until"
+msgstr ""
+
+msgid "MilestoneSidebar|complete"
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|Close Milestone"
+msgstr ""
+
+msgid "Milestones|Completed Issues (closed)"
+msgstr ""
+
+msgid "Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Group Milestone"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Ongoing Issues (open and assigned)"
+msgstr ""
+
+msgid "Milestones|Organize issues and merge requests into a cohesive group, and set optional start and due dates. %{learn_more_link}"
+msgstr ""
+
+msgid "Milestones|Project Milestone"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promote to Group Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|Reopen Milestone"
+msgstr ""
+
+msgid "Milestones|There are no closed milestones"
+msgstr ""
+
+msgid "Milestones|There are no open milestones"
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Milestones|Unstarted Issues (open and unassigned)"
+msgstr ""
+
+msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
+msgstr ""
+
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
+msgid "Min Value"
+msgstr ""
+
+msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror only protected branches"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror settings are only available to GitLab administrators."
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored from %{link}."
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "Mirroring settings were successfully updated."
+msgstr ""
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Add SSH key"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Don't show again"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|You 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 ""
+
+msgid "ModalButton|Add projects"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modified"
+msgstr ""
+
+msgid "Modified in this version"
+msgstr ""
+
+msgid "Modify commit message"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Mon"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor GitLab with Prometheus."
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry."
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Month"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More Details"
+msgstr ""
+
+msgid "More Information"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More details"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information and share feedback"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "More information."
+msgstr ""
+
+msgid "More than %{number_commits_distance} commits different with %{default_branch}"
+msgstr ""
+
+msgid "More topics"
+msgstr ""
+
+msgid "Most common"
+msgstr ""
+
+msgid "Most relevant"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move down"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move selection down"
+msgstr ""
+
+msgid "Move selection up"
+msgstr ""
+
+msgid "Move test case"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "Move up"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
+msgstr ""
+
+msgid "Moved issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moved this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
+msgid "MrDeploymentActions|Deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Re-deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Stop environment"
+msgstr ""
+
+msgid "MrList|Assigned to %{name}"
+msgstr ""
+
+msgid "MrList|Review requested from %{name}"
+msgstr ""
+
+msgid "MrSurvey|By continuing, you acknowledge that responses will be used to improve GitLab and in accordance with the %{linkStart}GitLab Privacy Policy%{linkEnd}."
+msgstr ""
+
+msgid "MrSurvey|How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
+msgstr ""
+
+msgid "MrSurvey|Merge request experience survey"
+msgstr ""
+
+msgid "MrSurvey|Overall, how satisfied are you with merge requests?"
+msgstr ""
+
+msgid "MrSurvey|Thank you for your feedback!"
+msgstr ""
+
+msgid "Multi-project"
+msgstr ""
+
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr ""
+
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
+msgid "Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1."
+msgstr ""
+
+msgid "My awesome group"
+msgstr ""
+
+msgid "My company or team"
+msgstr ""
+
+msgid "My topic"
+msgstr ""
+
+msgid "My-Reaction"
+msgstr ""
+
+msgid "NEW"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name can't be blank"
+msgstr ""
+
+msgid "Name has already been taken"
+msgstr ""
+
+msgid "Name is already taken."
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Namespace"
+msgstr ""
+
+msgid "Namespace ID:"
+msgstr ""
+
+msgid "Namespace:"
+msgstr ""
+
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
+msgstr ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
+msgid "NamespaceStorage|%{name_with_link} namespace has approximately %{percent} (%{size}) namespace storage space remaining."
+msgstr ""
+
+msgid "NamespaceStorage|%{name_with_link} namespace has exceeded its namespace storage limit."
+msgstr ""
+
+msgid "NamespaceStorage|%{name}(%{url}) namespace has approximately %{percent} (%{size}) namespace storage space remaining."
+msgstr ""
+
+msgid "NamespaceStorage|%{name}(%{url}) namespace has exceeded its namespace storage limit."
+msgstr ""
+
+msgid "NamespaceStorage|Action required: Approximately %{percentage_of_available_storage}%% of namespace storage remains for %{namespace_name}"
+msgstr ""
+
+msgid "NamespaceStorage|Action required: Storage has been exceeded for %{namespace_name}"
+msgstr ""
+
+msgid "NamespaceStorage|Buy more storage"
+msgstr ""
+
+msgid "NamespaceStorage|We recommend that you buy additional storage to ensure your service is not interrupted."
+msgstr ""
+
+msgid "NamespaceStorage|We recommend that you buy additional storage to resume normal service."
+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 ""
+
+msgid "NamespaceUserCap|View pending approvals"
+msgstr ""
+
+msgid "NamespaceUserCap|Your group has reached its billable member limit"
+msgstr ""
+
+msgid "Namespaces"
+msgstr ""
+
+msgid "Namespaces to index"
+msgstr ""
+
+msgid "Naming, topics, avatar"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
+msgid "Navigation bar"
+msgstr ""
+
+msgid "NavigationTheme|Blue"
+msgstr ""
+
+msgid "NavigationTheme|Dark Mode (alpha)"
+msgstr ""
+
+msgid "NavigationTheme|Gray"
+msgstr ""
+
+msgid "NavigationTheme|Green"
+msgstr ""
+
+msgid "NavigationTheme|Indigo"
+msgstr ""
+
+msgid "NavigationTheme|Light Blue"
+msgstr ""
+
+msgid "NavigationTheme|Light Gray"
+msgstr ""
+
+msgid "NavigationTheme|Light Green"
+msgstr ""
+
+msgid "NavigationTheme|Light Indigo"
+msgstr ""
+
+msgid "NavigationTheme|Light Red"
+msgstr ""
+
+msgid "NavigationTheme|Red"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Needs"
+msgstr ""
+
+msgid "Needs attention"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Network:"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New %{type} in %{project}"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Branch"
+msgstr ""
+
+msgid "New Deploy Key"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Epic"
+msgstr ""
+
+msgid "New File"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Group Name"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Jira import"
+msgstr ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Project"
+msgstr ""
+
+msgid "New Protected Branch"
+msgstr ""
+
+msgid "New Requirement"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Test Case"
+msgstr ""
+
+msgid "New User"
+msgstr ""
+
+msgid "New application"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New confidential epic title "
+msgstr ""
+
+msgid "New confidential issue title"
+msgstr ""
+
+msgid "New deploy key"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New discussion"
+msgstr ""
+
+msgid "New email address added"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New epic title"
+msgstr ""
+
+msgid "New error tracking access token has been generated!"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New health check access token has been generated!"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New issue in %{project}"
+msgstr ""
+
+msgid "New issue title"
+msgstr ""
+
+msgid "New iteration created"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New list"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New name"
+msgstr ""
+
+msgid "New password"
+msgstr ""
+
+msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New project page"
+msgstr ""
+
+msgid "New project pages"
+msgstr ""
+
+msgid "New project/repository"
+msgstr ""
+
+msgid "New public deploy key"
+msgstr ""
+
+msgid "New related %{issueType}"
+msgstr ""
+
+msgid "New release"
+msgstr ""
+
+msgid "New requirement"
+msgstr ""
+
+msgid "New response for issue #%{issue_iid}:"
+msgstr ""
+
+msgid "New runners registration token has been generated!"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New test case"
+msgstr ""
+
+msgid "New topic"
+msgstr ""
+
+msgid "New users set to external"
+msgstr ""
+
+msgid "New! Suggest changes directly"
+msgstr ""
+
+msgid "Newest first"
+msgstr ""
+
+msgid "Newly-registered users are external by default"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next design"
+msgstr ""
+
+msgid "Next file in diff"
+msgstr ""
+
+msgid "Next scan"
+msgstr ""
+
+msgid "Next unresolved discussion"
+msgstr ""
+
+msgid "Next update"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No %{header} for this request."
+msgstr ""
+
+msgid "No %{providerTitle} repositories found"
+msgstr ""
+
+msgid "No CSV data to display."
+msgstr ""
+
+msgid "No Epic"
+msgstr ""
+
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
+msgid "No Matching Results"
+msgstr ""
+
+msgid "No Milestone"
+msgstr ""
+
+msgid "No Scopes"
+msgstr ""
+
+msgid "No Work Item Link found"
+msgstr ""
+
+msgid "No active admin user found"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No application_settings found"
+msgstr ""
+
+msgid "No approvers"
+msgstr ""
+
+msgid "No artifacts found"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No authentication methods configured."
+msgstr ""
+
+msgid "No available branches"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No change to this %{noun}'s draft status."
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{source} and %{target}"
+msgstr ""
+
+msgid "No child epics match applied filters"
+msgstr ""
+
+msgid "No commenters"
+msgstr ""
+
+msgid "No commits present here"
+msgstr ""
+
+msgid "No committers"
+msgstr ""
+
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No contributions"
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card data for matching"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No data available"
+msgstr ""
+
+msgid "No data found"
+msgstr ""
+
+msgid "No data to display"
+msgstr ""
+
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
+msgid "No deployments found"
+msgstr ""
+
+msgid "No email participants were added. Either none were provided, or they already exist."
+msgstr ""
+
+msgid "No endpoint provided"
+msgstr ""
+
+msgid "No errors to display."
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen."
+msgstr ""
+
+msgid "No file hooks found."
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No forks are available to you."
+msgstr ""
+
+msgid "No group provided"
+msgstr ""
+
+msgid "No grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+msgstr ""
+
+msgid "No iterations to show"
+msgstr ""
+
+msgid "No job log"
+msgstr ""
+
+msgid "No jobs to show"
+msgstr ""
+
+msgid "No label"
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matches found"
+msgstr ""
+
+msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} ID."
+msgstr ""
+
+msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} URL."
+msgstr ""
+
+msgid "No matching labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No matching results..."
+msgstr ""
+
+msgid "No members found"
+msgstr ""
+
+msgid "No memberships found"
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestone"
+msgstr ""
+
+msgid "No namespace"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No panels matching properties %{opts}"
+msgstr ""
+
+msgid "No parent group"
+msgstr ""
+
+msgid "No plan"
+msgstr ""
+
+msgid "No policy matches this license"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritized labels with such name or description"
+msgstr ""
+
+msgid "No project subscribes to the pipelines in this project."
+msgstr ""
+
+msgid "No projects available."
+msgstr ""
+
+msgid "No projects found"
+msgstr ""
+
+msgid "No public deploy keys"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No ref selected"
+msgstr ""
+
+msgid "No regions configured"
+msgstr ""
+
+msgid "No related merge requests found."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No results"
+msgstr ""
+
+msgid "No results found"
+msgstr ""
+
+msgid "No runner executable"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No service accounts"
+msgstr ""
+
+msgid "No severity matches the provided parameter"
+msgstr ""
+
+msgid "No source selected"
+msgstr ""
+
+msgid "No stack trace for this error"
+msgstr ""
+
+msgid "No starrers matched your search"
+msgstr ""
+
+msgid "No suggestions found"
+msgstr ""
+
+msgid "No tag selected"
+msgstr ""
+
+msgid "No template"
+msgstr ""
+
+msgid "No template selected"
+msgstr ""
+
+msgid "No test coverage"
+msgstr ""
+
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
+msgid "No user provided"
+msgstr ""
+
+msgid "No vulnerabilities present"
+msgstr ""
+
+msgid "No webhook events"
+msgstr ""
+
+msgid "No webhooks enabled. Select trigger events above."
+msgstr ""
+
+msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
+msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "No wrap"
+msgstr ""
+
+msgid "No. of commits"
+msgstr ""
+
+msgid "Nobody has starred this repository yet"
+msgstr ""
+
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "Non-admin users are restricted to read-only access, in both GitLab UI and API."
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
+msgid "Normal text"
+msgstr ""
+
+msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
+msgstr ""
+
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
+msgid "Not applicable."
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not found"
+msgstr ""
+
+msgid "Not found."
+msgstr ""
+
+msgid "Not permitted to destroy framework"
+msgstr ""
+
+msgid "Not ready yet. Try again later."
+msgstr ""
+
+msgid "Not started"
+msgstr ""
+
+msgid "Not supported"
+msgstr ""
+
+msgid "Note"
+msgstr ""
+
+msgid "Note creation requests"
+msgstr ""
+
+msgid "Note parameters are invalid: %{errors}"
+msgstr ""
+
+msgid "Note that pushing to GitLab requires write access to this repository."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: current forks will keep their visibility level."
+msgstr ""
+
+msgid "NoteForm|Note"
+msgstr ""
+
+msgid "NoteToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd}, type %{keyboardStart}/%{keyboardEnd}."
+msgstr ""
+
+msgid "Notes"
+msgstr ""
+
+msgid "Notes rate limit"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this %{commentType}?"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Expand replies"
+msgstr ""
+
+msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
+msgstr ""
+
+msgid "Notes|Last reply by %{name}"
+msgstr ""
+
+msgid "Notes|Make this an internal note"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Notes|This internal note will always remain confidential"
+msgstr ""
+
+msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
+msgid "Note|The created date provided is too far in the past."
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
+msgid "Notification Email"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "Notification settings saved"
+msgstr ""
+
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEvent|Change reviewer merge request"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Fixed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Issue due"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|Merge when pipeline succeeds"
+msgstr ""
+
+msgid "NotificationEvent|Moved project"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|New release"
+msgstr ""
+
+msgid "NotificationEvent|Push to merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Reopen merge request"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications have been disabled by the project or group owner"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Notifications turned off."
+msgstr ""
+
+msgid "Notifications turned on."
+msgstr ""
+
+msgid "Notify users by email when sign-in location is not recognized."
+msgstr ""
+
+msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
+msgstr ""
+
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
+msgid "Notify|%{commit_link} in %{mr_link}"
+msgstr ""
+
+msgid "Notify|%{commits_text} from branch `%{target_branch}`"
+msgstr ""
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
+msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
+msgstr ""
+
+msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
+msgstr ""
+
+msgid "Notify|%{issues} imported."
+msgstr ""
+
+msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr ""
+
+msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
+msgstr ""
+
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
+msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
+msgstr ""
+
+msgid "Notify|A new GPG key was added to your account:"
+msgstr ""
+
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
+msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
+msgstr ""
+
+msgid "Notify|And %{total_stripped_new_commits_count} more"
+msgstr ""
+
+msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
+msgstr ""
+
+msgid "Notify|Assignee changed to %{toNames}"
+msgstr ""
+
+msgid "Notify|Author: %{author_name}"
+msgstr ""
+
+msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
+msgstr ""
+
+msgid "Notify|CI/CD project settings"
+msgstr ""
+
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
+msgid "Notify|Don't want to receive updates from GitLab administrators?"
+msgstr ""
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
+msgid "Notify|Fingerprint: %{fingerprint}"
+msgstr ""
+
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
+msgid "Notify|Hi %{user}!"
+msgstr ""
+
+msgid "Notify|If this key was added in error, you can remove it under %{removal_link}"
+msgstr ""
+
+msgid "Notify|If you no longer wish to use this domain with GitLab Pages, please remove it from your GitLab project and delete any related DNS records."
+msgstr ""
+
+msgid "Notify|Issue was %{issue_status} by %{updated_by}"
+msgstr ""
+
+msgid "Notify|Issue was moved to another project."
+msgstr ""
+
+msgid "Notify|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
+msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
+msgstr ""
+
+msgid "Notify|Merge request %{merge_request} was %{mr_status}"
+msgstr ""
+
+msgid "Notify|Merge request %{merge_request} was %{mr_status} by %{updated_by}"
+msgstr ""
+
+msgid "Notify|Merge request %{merge_request} was merged"
+msgstr ""
+
+msgid "Notify|Merge request %{mr_link} was closed by %{closed_by}"
+msgstr ""
+
+msgid "Notify|Merge request URL: %{merge_request_url}"
+msgstr ""
+
+msgid "Notify|Merge request was approved"
+msgstr ""
+
+msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
+msgid "Notify|Milestone changed to %{milestone}"
+msgstr ""
+
+msgid "Notify|Milestone removed"
+msgstr ""
+
+msgid "Notify|New issue: %{project_issue_url}"
+msgstr ""
+
+msgid "Notify|No preview for this file type"
+msgstr ""
+
+msgid "Notify|Pipeline %{pipeline_link} triggered by"
+msgstr ""
+
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
+msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
+msgstr ""
+
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
+msgid "Notify|This issue is due on: %{issue_due_date}"
+msgstr ""
+
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
+msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
+msgstr ""
+
+msgid "Notify|You don't have access to the project."
+msgstr ""
+
+msgid "Notify|You have been mentioned in an issue."
+msgstr ""
+
+msgid "Notify|You have been mentioned in merge request %{mr_link}"
+msgstr ""
+
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
+msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
+msgstr ""
+
+msgid "Notify|currently supported languages"
+msgstr ""
+
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
+msgid "Notify|successfully completed %{jobs} in %{stages}."
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "Now, personalize your GitLab experience"
+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 ""
+
+msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full %{code_start}git repack%{code_end} is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run."
+msgstr ""
+
+msgid "Number of LOCs per commit"
+msgstr ""
+
+msgid "Number of commits"
+msgstr ""
+
+msgid "Number of commits per MR"
+msgstr ""
+
+msgid "Number of employees"
+msgstr ""
+
+msgid "Number of events"
+msgstr ""
+
+msgid "Number of events for this project: %{total_count}."
+msgstr ""
+
+msgid "Number of files touched"
+msgstr ""
+
+msgid "Number of replicas"
+msgstr ""
+
+msgid "Number of shards"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Object does not exist on the server or you don't have permissions to access it"
+msgstr ""
+
+msgid "Observability"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Off"
+msgstr ""
+
+msgid "Offline"
+msgstr ""
+
+msgid "Oh no!"
+msgstr ""
+
+msgid "Ok, let's go"
+msgstr ""
+
+msgid "Okay"
+msgstr ""
+
+msgid "Oldest first"
+msgstr ""
+
+msgid "OmniAuth"
+msgstr ""
+
+msgid "On"
+msgstr ""
+
+msgid "On %{end_date}, your trial will end and %{namespace_name} will be limited to %{free_user_limit} member"
+msgid_plural "On %{end_date}, your trial will end and %{namespace_name} will be limited to %{free_user_limit} members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "On the left sidebar, select %{merge_requests_link} to view them."
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "On-call Schedules"
+msgstr ""
+
+msgid "On-call schedules"
+msgstr ""
+
+msgid "On-demand scans run outside of the DevOps cycle and find vulnerabilities in your projects"
+msgstr ""
+
+msgid "OnCallScheduless|Any escalation rules that are using this schedule will also be deleted."
+msgstr ""
+
+msgid "OnCallSchedules|1 day"
+msgstr ""
+
+msgid "OnCallSchedules|2 weeks"
+msgstr ""
+
+msgid "OnCallSchedules|Add a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add a schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Add an additional schedule to your project"
+msgstr ""
+
+msgid "OnCallSchedules|Add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteRotation}\" rotation? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\" schedule? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Collapse schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Create on-call schedules in GitLab"
+msgstr ""
+
+msgid "OnCallSchedules|Currently no rotation."
+msgstr ""
+
+msgid "OnCallSchedules|Delete rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Delete schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Edit rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
+msgid "OnCallSchedules|Expand schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedules"
+msgstr ""
+
+msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
+msgstr ""
+
+msgid "OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification."
+msgstr ""
+
+msgid "OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification."
+msgstr ""
+
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation length"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation name cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation participants cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation start date cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotations"
+msgstr ""
+
+msgid "OnCallSchedules|Route alerts directly to specific members of your team"
+msgstr ""
+
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
+msgid "OnCallSchedules|Select participant"
+msgstr ""
+
+msgid "OnCallSchedules|Select timezone"
+msgstr ""
+
+msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully created a new rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully edited your rotation"
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|Try adding a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|User %{name} is currently part of:"
+msgstr ""
+
+msgid "OnCallSchedules|View next timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|View previous timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|You are currently a part of:"
+msgstr ""
+
+msgid "OnCallSchedules|Your schedule has been successfully created. 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|%{profileType} profile library"
+msgstr ""
+
+msgid "OnDemandScans|Add a schedule to run this scan at a specified date and time or on a recurring basis. Scheduled scans are automatically saved to scan library."
+msgstr ""
+
+msgid "OnDemandScans|Analyze a deployed version of your web application for known vulnerabilities by examining it from the outside in. DAST works by simulating external attacks on your application while it is running."
+msgstr ""
+
+msgid "OnDemandScans|Are you sure you want to delete this scan?"
+msgstr ""
+
+msgid "OnDemandScans|Cancel"
+msgstr ""
+
+msgid "OnDemandScans|Could not delete saved scan. Please refresh the page, or try again later."
+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 ""
+
+msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not run the scan. Please try again."
+msgstr ""
+
+msgid "OnDemandScans|Create new scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Create new site profile"
+msgstr ""
+
+msgid "OnDemandScans|DAST configuration"
+msgstr ""
+
+msgid "OnDemandScans|DAST scans for vulnerabilities in your project's running application, website, or API. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Define the fundamental configuration options for your on-demand scan."
+msgstr ""
+
+msgid "OnDemandScans|Delete profile"
+msgstr ""
+
+msgid "OnDemandScans|Description (optional)"
+msgstr ""
+
+msgid "OnDemandScans|Discard changes"
+msgstr ""
+
+msgid "OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost."
+msgstr ""
+
+msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "OnDemandScans|Edit %{profileType} profile"
+msgstr ""
+
+msgid "OnDemandScans|Edit on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|Edit on-demand scan"
+msgstr ""
+
+msgid "OnDemandScans|Edit profile"
+msgstr ""
+
+msgid "OnDemandScans|Enable scan schedule"
+msgstr ""
+
+msgid "OnDemandScans|For example: Tests the login page for SQL injections"
+msgstr ""
+
+msgid "OnDemandScans|Keep editing"
+msgstr ""
+
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
+msgid "OnDemandScans|New %{profileType} profile"
+msgstr ""
+
+msgid "OnDemandScans|New on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|New on-demand scan"
+msgstr ""
+
+msgid "OnDemandScans|New profile"
+msgstr ""
+
+msgid "OnDemandScans|New scan"
+msgstr ""
+
+msgid "OnDemandScans|No %{profileType} profiles found for DAST"
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
+msgid "OnDemandScans|On-demand Scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+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|Run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save and run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan configuration"
+msgstr ""
+
+msgid "OnDemandScans|Scan library"
+msgstr ""
+
+msgid "OnDemandScans|Scan name"
+msgstr ""
+
+msgid "OnDemandScans|Scan results will be associated with the selected branch."
+msgstr ""
+
+msgid "OnDemandScans|Scan schedule"
+msgstr ""
+
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
+msgid "OnDemandScans|Scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profile"
+msgstr ""
+
+msgid "OnDemandScans|Start by creating a new profile. Profiles make it easy to save and reuse configuration details for GitLab’s security tools."
+msgstr ""
+
+msgid "OnDemandScans|Start time"
+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 saved scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no scheduled scans."
+msgstr ""
+
+msgid "OnDemandScans|Timezone"
+msgstr ""
+
+msgid "OnDemandScans|Use existing scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "OnDemandScans|View results"
+msgstr ""
+
+msgid "OnDemandScans|You have unsaved changes"
+msgstr ""
+
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgstr ""
+
+msgid "OnDemandScans|at"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
+
+msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
+msgstr ""
+
+msgid "Once you confirm and press \"Reduce project visibility\":"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more arguments are invalid: %{args}."
+msgstr ""
+
+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 ""
+
+msgid "One or more of you personal access tokens were revoked"
+msgstr ""
+
+msgid "One or more of your %{provider} projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
+msgid "One or more of your personal access tokens has expired."
+msgstr ""
+
+msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less:"
+msgstr ""
+
+msgid "Only %{workspaceType} members with %{permissions} can view or be notified about this %{issuableType}."
+msgstr ""
+
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
+msgstr ""
+
+msgid "Only 1 appearances row can exist"
+msgstr ""
+
+msgid "Only HTTP(S)"
+msgstr ""
+
+msgid "Only Issue ID or merge request ID is required"
+msgstr ""
+
+msgid "Only Project Members"
+msgstr ""
+
+msgid "Only SSH"
+msgstr ""
+
+msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
+msgstr ""
+
+msgid "Only active projects show up in the search and on the dashboard."
+msgstr ""
+
+msgid "Only allow anyone to register for accounts on GitLab instances that you intend to be used by anyone. Allowing anyone to register makes GitLab instances more vulnerable."
+msgstr ""
+
+msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
+msgstr ""
+
+msgid "Only group members with at least the Reporter role can view or be notified about this epic"
+msgstr ""
+
+msgid "Only include features new to your current subscription tier."
+msgstr ""
+
+msgid "Only members of this group can access the wiki."
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only projects created under a Ultimate license are available in Security Dashboards."
+msgstr ""
+
+msgid "Only reCAPTCHA v2 is supported:"
+msgstr ""
+
+msgid "Only required if not using role instance credentials."
+msgstr ""
+
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
+msgid "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
+msgstr ""
+
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Selection"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Gitpod"
+msgstr ""
+
+msgid "Open in Web IDE"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open in your IDE"
+msgstr ""
+
+msgid "Open new window"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{open}"
+msgstr ""
+
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI Specification file URL"
+msgstr ""
+
+msgid "OpenAPI Specification file path or URL"
+msgstr ""
+
+msgid "OpenSearch's region."
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MRs"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Created"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Opens new window"
+msgstr ""
+
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation not allowed"
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add projects"
+msgstr ""
+
+msgid "OperationsDashboard|More information"
+msgstr ""
+
+msgid "OperationsDashboard|Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The Operations and Environments dashboards share the same list of projects. When you add or remove a project from one, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "Opstrace endpoint for Error Tracking integration"
+msgstr ""
+
+msgid "Optimize your workflow with CI/CD Pipelines"
+msgstr ""
+
+msgid "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Ordered list"
+msgstr ""
+
+msgid "Organizations"
+msgstr ""
+
+msgid "Orphaned member"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other available runners"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Other merge requests block this MR"
+msgstr ""
+
+msgid "Other versions"
+msgstr ""
+
+msgid "Other visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Otherwise, click the link below to complete the process."
+msgstr ""
+
+msgid "Otherwise, click the link below to complete the process:"
+msgstr ""
+
+msgid "Our team has been notified. Please try again."
+msgstr ""
+
+msgid "Out-of-compliance with this project's policies and should be removed"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "OutboundRequests|Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
+msgstr ""
+
+msgid "OutboundRequests|Outbound requests"
+msgstr ""
+
+msgid "OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded."
+msgstr ""
+
+msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "Outdent line"
+msgstr ""
+
+msgid "Overridden"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owned by %{image_tag}"
+msgstr ""
+
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
+msgid "Owned by:"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Owners and administrators"
+msgstr ""
+
+msgid "Owners can modify this selection."
+msgstr ""
+
+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 ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+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 ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
+msgid "Package Registry"
+msgstr ""
+
+msgid "Package Registry: authenticated API requests"
+msgstr ""
+
+msgid "Package Registry: unauthenticated API requests"
+msgstr ""
+
+msgid "Package already exists"
+msgstr ""
+
+msgid "Package and registry settings"
+msgstr ""
+
+msgid "Package deleted successfully"
+msgstr ""
+
+msgid "Package file size limits"
+msgstr ""
+
+msgid "Package recipe already exists"
+msgstr ""
+
+msgid "Package registry rate limits"
+msgstr ""
+
+msgid "Package type"
+msgstr ""
+
+msgid "Package type must be Conan"
+msgstr ""
+
+msgid "Package type must be Debian"
+msgstr ""
+
+msgid "Package type must be Helm"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NPM"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "Package type must be RPM"
+msgstr ""
+
+msgid "Package type must be RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+msgstr ""
+
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Add NuGet Source"
+msgstr ""
+
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
+msgid "PackageRegistry|Additional metadata"
+msgstr ""
+
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
+msgid "PackageRegistry|Allow packages with the same name and version to be uploaded to the registry. The newest version of a package is always used when installing."
+msgstr ""
+
+msgid "PackageRegistry|App group: %{group}"
+msgstr ""
+
+msgid "PackageRegistry|App name: %{name}"
+msgstr ""
+
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|Composer"
+msgstr ""
+
+msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
+msgstr ""
+
+msgid "PackageRegistry|Conan"
+msgstr ""
+
+msgid "PackageRegistry|Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy .pypirc content"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven registry XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Pip command"
+msgstr ""
+
+msgid "PackageRegistry|Copy SHA"
+msgstr ""
+
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
+msgstr ""
+
+msgid "PackageRegistry|Copy npm command"
+msgstr ""
+
+msgid "PackageRegistry|Copy npm setup command"
+msgstr ""
+
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
+msgid "PackageRegistry|Copy target SHA"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn command"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn setup command"
+msgstr ""
+
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
+msgid "PackageRegistry|Debian"
+msgstr ""
+
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "PackageRegistry|Delete Package Version"
+msgstr ""
+
+msgid "PackageRegistry|Delete package"
+msgstr ""
+
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
+msgid "PackageRegistry|Delete this package"
+msgstr ""
+
+msgid "PackageRegistry|Duplicate packages"
+msgstr ""
+
+msgid "PackageRegistry|Error publishing"
+msgstr ""
+
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr ""
+
+msgid "PackageRegistry|Failed to load the package data"
+msgstr ""
+
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|Generic"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
+msgid "PackageRegistry|Helm"
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|Install package version"
+msgstr ""
+
+msgid "PackageRegistry|Instance-level"
+msgstr ""
+
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
+msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
+msgstr ""
+
+msgid "PackageRegistry|License information located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
+msgid "PackageRegistry|Manually Published"
+msgstr ""
+
+msgid "PackageRegistry|Maven"
+msgstr ""
+
+msgid "PackageRegistry|Maven Command"
+msgstr ""
+
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
+msgid "PackageRegistry|Package Registry"
+msgstr ""
+
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr ""
+
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
+msgid "PackageRegistry|Package deleted successfully"
+msgstr ""
+
+msgid "PackageRegistry|Package formats"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
+msgid "PackageRegistry|Permanently delete assets"
+msgstr ""
+
+msgid "PackageRegistry|Pip Command"
+msgstr ""
+
+msgid "PackageRegistry|Project-level"
+msgstr ""
+
+msgid "PackageRegistry|Publish packages if their name or version matches this regex."
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPI"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|Required Python: %{pythonVersion}"
+msgstr ""
+
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Yarn commands"
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while deleting the package."
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while fetching the package history."
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while fetching the package metadata."
+msgstr ""
+
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Target SHA: %{sha}"
+msgstr ""
+
+msgid "PackageRegistry|There are no other versions of this package."
+msgstr ""
+
+msgid "PackageRegistry|There are no packages yet"
+msgstr ""
+
+msgid "PackageRegistry|There was a problem fetching the details for this package."
+msgstr ""
+
+msgid "PackageRegistry|There was a timeout and the package was not published. Delete this package and try again."
+msgstr ""
+
+msgid "PackageRegistry|There was an error publishing a %{packageName} package"
+msgstr ""
+
+msgid "PackageRegistry|This NuGet package has no dependencies."
+msgstr ""
+
+msgid "PackageRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "PackageRegistry|Type"
+msgstr ""
+
+msgid "PackageRegistry|Unable to fetch package version information."
+msgstr ""
+
+msgid "PackageRegistry|Unable to load package"
+msgstr ""
+
+msgid "PackageRegistry|When a package with same name and version is uploaded to the registry, more assets are added to the package. To save storage space, keep only the most recent assets."
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
+msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
+msgstr ""
+
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|npm"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "Packages and registries"
+msgstr ""
+
+msgid "Page not found"
+msgstr ""
+
+msgid "PagerDutySettings|Active"
+msgstr ""
+
+msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
+msgstr ""
+
+msgid "PagerDutySettings|Failed to update Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Reset webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL update was successful"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pagination|First"
+msgstr ""
+
+msgid "Pagination|Go to first page"
+msgstr ""
+
+msgid "Pagination|Go to last page"
+msgstr ""
+
+msgid "Pagination|Go to next page"
+msgstr ""
+
+msgid "Pagination|Go to previous page"
+msgstr ""
+
+msgid "Pagination|Last"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
+msgstr ""
+
+msgid "Parent"
+msgstr ""
+
+msgid "Parent epic doesn't exist."
+msgstr ""
+
+msgid "Parent epic is not present."
+msgstr ""
+
+msgid "Parsing error for param :embed_json. %{message}"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Partial import"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Pass job variables"
+msgstr ""
+
+msgid "Passed"
+msgstr ""
+
+msgid "Passed on"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password (optional)"
+msgstr ""
+
+msgid "Password authentication is unavailable."
+msgstr ""
+
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
+
+msgid "PasswordPrompt|Confirm password"
+msgstr ""
+
+msgid "PasswordPrompt|Confirm password to continue"
+msgstr ""
+
+msgid "PasswordPrompt|Password is required"
+msgstr ""
+
+msgid "PasswordPrompt|Please enter your password to confirm"
+msgstr ""
+
+msgid "Passwords should be unique and not used for any other sites or services."
+msgstr ""
+
+msgid "Password|requires at least one lowercase letter"
+msgstr ""
+
+msgid "Password|requires at least one number"
+msgstr ""
+
+msgid "Password|requires at least one symbol character"
+msgstr ""
+
+msgid "Password|requires at least one uppercase letter"
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste a public key here."
+msgstr ""
+
+msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
+msgstr ""
+
+msgid "Paste confidential epic link"
+msgstr ""
+
+msgid "Paste confidential issue link"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste link"
+msgstr ""
+
+msgid "Paste project path (i.e. gitlab-org/gitlab)"
+msgstr ""
+
+msgid "Paste this DSN into your Sentry SDK"
+msgstr ""
+
+msgid "Patch to apply"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause time (ms)"
+msgstr ""
+
+msgid "Paused"
+msgstr ""
+
+msgid "Paused runners don't accept new jobs"
+msgstr ""
+
+msgid "Peer review by"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "Pending Deletion"
+msgstr ""
+
+msgid "Pending comments"
+msgstr ""
+
+msgid "Pending deletion"
+msgstr ""
+
+msgid "Pending owner action"
+msgstr ""
+
+msgid "Pending sync…"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "People without permission will never get a notification."
+msgstr ""
+
+msgid "Per your subscription agreement with GitLab, you must report your license usage data on a monthly basis. GitLab uses this data to keep your subscription up to date. To report your license usage data, export your license usage file and email it to %{renewal_service_email}. If you need an updated license, GitLab will send the license to the email address registered in the %{customers_dot}, and you can upload this license to your instance."
+msgstr ""
+
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "Percentage"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
+msgstr ""
+
+msgid "Perform code reviews and enhance collaboration with merge requests."
+msgstr ""
+
+msgid "Perform common operations on GitLab project"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Backend"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|DOM Content Loaded"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
+msgid "PerformanceBar|First Contentful Paint"
+msgstr ""
+
+msgid "PerformanceBar|Flamegraph with mode:"
+msgstr ""
+
+msgid "PerformanceBar|Frontend resources"
+msgstr ""
+
+msgid "PerformanceBar|Gitaly calls"
+msgstr ""
+
+msgid "PerformanceBar|Memory"
+msgstr ""
+
+msgid "PerformanceBar|Memory report"
+msgstr ""
+
+msgid "PerformanceBar|Redis calls"
+msgstr ""
+
+msgid "PerformanceBar|Rugged calls"
+msgstr ""
+
+msgid "PerformanceBar|SQL queries"
+msgstr ""
+
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
+msgid "PerformanceBar|Stats"
+msgstr ""
+
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
+
+msgid "PerformanceBar|cpu"
+msgstr ""
+
+msgid "PerformanceBar|object"
+msgstr ""
+
+msgid "PerformanceBar|wall"
+msgstr ""
+
+msgid "Period in seconds"
+msgstr ""
+
+msgid "Period of inactivity (days)"
+msgstr ""
+
+msgid "Period of inactivity before deactivation."
+msgstr ""
+
+msgid "Permalink"
+msgstr ""
+
+msgid "Permanently remove group"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions Help"
+msgstr ""
+
+msgid "Permissions and group features"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal Access Token prefix"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Personal projects"
+msgstr ""
+
+msgid "Personal projects limit:"
+msgstr ""
+
+msgid "PersonalProject|Learn to move a project to a group"
+msgstr ""
+
+msgid "PersonalProject|Some GitLab features, including the ability to upgrade to a paid plan or start a free trial, are only available for groups and projects inside groups. %{projectName} is a personal project, so none of this is available. We recommend you move your project to a group to unlock GitLab's full potential."
+msgstr ""
+
+msgid "PersonalProject|We have some instructions to help you create a group and move your project into it."
+msgstr ""
+
+msgid "PersonalProject|Your project %{projectName} is not in a group"
+msgstr ""
+
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
+msgid "Phone"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pin code"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline %{label}"
+msgstr ""
+
+msgid "Pipeline %{label} for \"%{dataTitle}\""
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
+msgid "Pipeline ID"
+msgstr ""
+
+msgid "Pipeline IID"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline URL"
+msgstr ""
+
+msgid "Pipeline creation rate limits"
+msgstr ""
+
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
+msgid "Pipeline ran in fork of project"
+msgstr ""
+
+msgid "Pipeline status emails"
+msgstr ""
+
+msgid "Pipeline subscriptions"
+msgstr ""
+
+msgid "Pipeline subscriptions trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "Pipeline: %{status}"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the analytics data"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
+msgstr ""
+
+msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
+msgstr ""
+
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|There was an error parsing the data for the charts."
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineEditorFileTree|Configuration files added with the include keyword"
+msgstr ""
+
+msgid "PipelineEditorFileTree|When you use the include keyword to add pipeline configuration from files in the project, those files will be listed here."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run."
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline status is at the top of the page."
+msgstr ""
+
+msgid "PipelineEditorTutorial|This template creates a simple test pipeline. To use it:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
+msgid "PipelineEditor|Configuration content has changed. Re-run validation for updated results."
+msgstr ""
+
+msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
+msgstr ""
+
+msgid "PipelineEditor|Git push event to the default branch"
+msgstr ""
+
+msgid "PipelineEditor|Other pipeline sources are not available yet."
+msgstr ""
+
+msgid "PipelineEditor|Pipeline Source"
+msgstr ""
+
+msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies."
+msgstr ""
+
+msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditor|Pipeline simulation completed with errors"
+msgstr ""
+
+msgid "PipelineEditor|Simulated a %{codeStart}git push%{codeEnd} event for a default branch. %{codeStart}Rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd}, and %{codeStart}needs%{codeEnd} job dependencies logic have been evaluated. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditor|Simulation completed successfully"
+msgstr ""
+
+msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
+msgstr ""
+
+msgid "PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|Validate pipeline"
+msgstr ""
+
+msgid "PipelineEditor|Validate pipeline under selected conditions"
+msgstr ""
+
+msgid "PipelineEditor|Validate pipeline under simulated conditions"
+msgstr ""
+
+msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
+msgstr ""
+
+msgid "PipelineEditor|Waiting for CI content to load..."
+msgstr ""
+
+msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
+msgstr ""
+
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
+msgid "PipelineSource|API"
+msgstr ""
+
+msgid "PipelineSource|Chat"
+msgstr ""
+
+msgid "PipelineSource|External"
+msgstr ""
+
+msgid "PipelineSource|External Pull Request"
+msgstr ""
+
+msgid "PipelineSource|Merge Request"
+msgstr ""
+
+msgid "PipelineSource|On-Demand DAST Scan"
+msgstr ""
+
+msgid "PipelineSource|On-Demand DAST Validation"
+msgstr ""
+
+msgid "PipelineSource|Parent Pipeline"
+msgstr ""
+
+msgid "PipelineSource|Pipeline"
+msgstr ""
+
+msgid "PipelineSource|Push"
+msgstr ""
+
+msgid "PipelineSource|Schedule"
+msgstr ""
+
+msgid "PipelineSource|Trigger"
+msgstr ""
+
+msgid "PipelineSource|Web"
+msgstr ""
+
+msgid "PipelineSource|Web IDE"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
+msgid "PipelineWizardDefaultCommitMessage|Add %{filename}"
+msgstr ""
+
+msgid "PipelineWizardDefaultCommitMessage|Update %{filename}"
+msgstr ""
+
+msgid "PipelineWizardInputValidation|At least one entry is required"
+msgstr ""
+
+msgid "PipelineWizardInputValidation|This field is required"
+msgstr ""
+
+msgid "PipelineWizardInputValidation|This value is not valid"
+msgstr ""
+
+msgid "PipelineWizardListWidget|add another step"
+msgstr ""
+
+msgid "PipelineWizardListWidget|remove step"
+msgstr ""
+
+msgid "PipelineWizard|Commit"
+msgstr ""
+
+msgid "PipelineWizard|Commit Message"
+msgstr ""
+
+msgid "PipelineWizard|Commit changes to your file"
+msgstr ""
+
+msgid "PipelineWizard|Commit file to Branch"
+msgstr ""
+
+msgid "PipelineWizard|Commit your new file"
+msgstr ""
+
+msgid "PipelineWizard|The file has been committed."
+msgstr ""
+
+msgid "PipelineWizard|There was a problem committing the changes."
+msgstr ""
+
+msgid "PipelineWizard|There was a problem while checking whether your file already exists in the specified branch."
+msgstr ""
+
+msgid "PipelineWizard|There was an unexpected error trying to set up the template. The error has been logged."
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines|\"Hello world\" with GitLab CI"
+msgstr ""
+
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
+msgid "Pipelines|1. Set up a runner"
+msgstr ""
+
+msgid "Pipelines|2. Configure deployment pipeline"
+msgstr ""
+
+msgid "Pipelines|A GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. Install GitLab Runner and register your own runners to get started with CI/CD."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr ""
+
+msgid "Pipelines|Are you sure you want to run this pipeline?"
+msgstr ""
+
+msgid "Pipelines|Auto DevOps"
+msgstr ""
+
+msgid "Pipelines|Based on your project, we recommend this template:"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|Building for iOS?"
+msgstr ""
+
+msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
+msgstr ""
+
+msgid "Pipelines|CI lint"
+msgstr ""
+
+msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
+msgstr ""
+
+msgid "Pipelines|Clear runner caches"
+msgstr ""
+
+msgid "Pipelines|Configuration validation currently not available."
+msgstr ""
+
+msgid "Pipelines|Configure pipeline"
+msgstr ""
+
+msgid "Pipelines|Continuous integration and deployment template to test and deploy your %{name} project."
+msgstr ""
+
+msgid "Pipelines|Copy trigger token"
+msgstr ""
+
+msgid "Pipelines|Could not load artifacts."
+msgstr ""
+
+msgid "Pipelines|Could not load merged YAML content"
+msgstr ""
+
+msgid "Pipelines|Description"
+msgstr ""
+
+msgid "Pipelines|Don't need a guide? Jump in right away with a template."
+msgstr ""
+
+msgid "Pipelines|Edit"
+msgstr ""
+
+msgid "Pipelines|Editor"
+msgstr ""
+
+msgid "Pipelines|Follow these instructions to install GitLab Runner on macOS."
+msgstr ""
+
+msgid "Pipelines|Get familiar with GitLab CI syntax by setting up a simple pipeline running a \"Hello world\" script to see how it runs, explore how CI/CD works."
+msgstr ""
+
+msgid "Pipelines|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "Pipelines|GitLab CI/CD can automatically build, test, and deploy your code. Let GitLab take care of time consuming tasks, so you can spend more time creating."
+msgstr ""
+
+msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline."
+msgstr ""
+
+msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. There are active runners available to run your jobs right now. If you prefer, you can %{settingsLinkStart}configure your runners%{settingsLinkEnd} or %{docsLinkStart}learn more%{docsLinkEnd} about runners."
+msgstr ""
+
+msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
+msgstr ""
+
+msgid "Pipelines|Install GitLab Runner"
+msgstr ""
+
+msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
+msgstr ""
+
+msgid "Pipelines|Last Used"
+msgstr ""
+
+msgid "Pipelines|Learn the basics of pipelines and .yml files"
+msgstr ""
+
+msgid "Pipelines|Let's get that runner set up! %{emojiStart}tada%{emojiEnd}"
+msgstr ""
+
+msgid "Pipelines|Lint"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading pipelines"
+msgstr ""
+
+msgid "Pipelines|Merged YAML is view only"
+msgstr ""
+
+msgid "Pipelines|More Information"
+msgstr ""
+
+msgid "Pipelines|Need more information to set up your runner? %{linkStart}Check out our documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipelines|No runners detected"
+msgstr ""
+
+msgid "Pipelines|No triggers have been created yet. Add one using the form above."
+msgstr ""
+
+msgid "Pipelines|Not building for iOS or not what you're looking for? %{linkStart}See what else%{linkEnd} GitLab CI/CD has to offer."
+msgstr ""
+
+msgid "Pipelines|Owner"
+msgstr ""
+
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Ready to set up CI/CD for your project?"
+msgstr ""
+
+msgid "Pipelines|Revoke trigger"
+msgstr ""
+
+msgid "Pipelines|Runners are available to run your jobs now"
+msgstr ""
+
+msgid "Pipelines|Set up a runner"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|The %{namespace_name} namespace has %{percentage}%% or less Shared Runner Pipeline minutes remaining. After it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|The %{namespace_name} namespace has exceeded its pipeline minutes quota. Buy additional pipeline minutes, or no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|The CI configuration was not loaded, please try again."
+msgstr ""
+
+msgid "Pipelines|The GitLab CI configuration could not be updated."
+msgstr ""
+
+msgid "Pipelines|There are currently no finished pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid:"
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is valid."
+msgstr ""
+
+msgid "Pipelines|This is a child pipeline within the parent pipeline"
+msgstr ""
+
+msgid "Pipelines|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
+msgstr ""
+
+msgid "Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch."
+msgstr ""
+
+msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipelines|Token"
+msgstr ""
+
+msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Pipelines|Try test template"
+msgstr ""
+
+msgid "Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works."
+msgstr ""
+
+msgid "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD."
+msgstr ""
+
+msgid "Pipelines|Use template"
+msgstr ""
+
+msgid "Pipelines|Validate"
+msgstr ""
+
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
+msgid "Pipelines|View merged YAML"
+msgstr ""
+
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|We'll guide you through a simple pipeline set-up."
+msgstr ""
+
+msgid "Pipelines|We'll walk you through how to deploy to iOS in two easy steps."
+msgstr ""
+
+msgid "Pipelines|You have runners available to run your job now. No need to do anything else."
+msgstr ""
+
+msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
+msgstr ""
+
+msgid "Pipelines|error"
+msgstr ""
+
+msgid "Pipelines|invalid"
+msgstr ""
+
+msgid "Pipelines|latest"
+msgstr ""
+
+msgid "Pipelines|merge request"
+msgstr ""
+
+msgid "Pipelines|merge train"
+msgstr ""
+
+msgid "Pipelines|stuck"
+msgstr ""
+
+msgid "Pipelines|yaml invalid"
+msgstr ""
+
+msgid "Pipeline|Actions"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Branches or tags could not be loaded."
+msgstr ""
+
+msgid "Pipeline|Canceled"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status."
+msgstr ""
+
+msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
+msgid "Pipeline|Date"
+msgstr ""
+
+msgid "Pipeline|Failed"
+msgstr ""
+
+msgid "Pipeline|In progress"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline jobs can not be retried"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
+msgstr ""
+
+msgid "Pipeline|Pipeline cannot be run."
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Run pipeline"
+msgstr ""
+
+msgid "Pipeline|Running"
+msgstr ""
+
+msgid "Pipeline|Skipped"
+msgstr ""
+
+msgid "Pipeline|Source"
+msgstr ""
+
+msgid "Pipeline|Source|Security Policy"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Tag name"
+msgstr ""
+
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
+msgstr ""
+
+msgid "Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch."
+msgstr ""
+
+msgid "Pipeline|To run a merge request pipeline, the jobs in the CI/CD configuration file %{linkStart}must be configured%{linkEnd} to run in merge request pipelines."
+msgstr ""
+
+msgid "Pipeline|Trigger author"
+msgstr ""
+
+msgid "Pipeline|Triggerer"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|View commit"
+msgstr ""
+
+msgid "Pipeline|View pipeline"
+msgstr ""
+
+msgid "Pipeline|We are currently unable to fetch pipeline data"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|for"
+msgstr ""
+
+msgid "Pipeline|merge request"
+msgstr ""
+
+msgid "Pipeline|merge train"
+msgstr ""
+
+msgid "Pipeline|on"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "PivotalTrackerService|Add commit messages as comments to Pivotal Tracker stories."
+msgstr ""
+
+msgid "PivotalTrackerService|Comma-separated list of branches to automatically inspect. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user."
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "Plain-text response to send to clients that hit a rate limit"
+msgstr ""
+
+msgid "Plan"
+msgstr ""
+
+msgid "Plan:"
+msgstr ""
+
+msgid "Planning hierarchy"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "PlantUML URL"
+msgstr ""
+
+msgid "PlantUML diagram"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Play all manual"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
+msgstr ""
+
+msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
+msgstr ""
+
+msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
+msgid "Please check your email %{email} to confirm your account"
+msgstr ""
+
+msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
+msgstr ""
+
+msgid "Please click the link in the confirmation email before continuing. It was sent to %{html_tag_strong_start}%{email}%{html_tag_strong_end}."
+msgstr ""
+
+msgid "Please complete your profile with email address"
+msgstr ""
+
+msgid "Please confirm your email address"
+msgstr ""
+
+msgid "Please contact an admin to register runners."
+msgstr ""
+
+msgid "Please contact your GitLab administrator if you think this is an error."
+msgstr ""
+
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
+msgid "Please contact your administrator."
+msgstr ""
+
+msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
+msgstr ""
+
+msgid "Please copy, download, or print your recovery codes before proceeding."
+msgstr ""
+
+msgid "Please create a password for your new account."
+msgstr ""
+
+msgid "Please create a username with only alphanumeric characters."
+msgstr ""
+
+msgid "Please create an index before enabling indexing"
+msgstr ""
+
+msgid "Please delete your current license if you want to downgrade to the free plan."
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please enter a non-negative number"
+msgstr ""
+
+msgid "Please enter a number greater than %{number} (from the project settings)"
+msgstr ""
+
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
+msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
+msgstr ""
+
+msgid "Please enter a valid number"
+msgstr ""
+
+msgid "Please enter a valid time interval"
+msgstr ""
+
+msgid "Please enter your current password."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please fill in a name for your topic."
+msgstr ""
+
+msgid "Please fill in a title for your topic."
+msgstr ""
+
+msgid "Please fill out this field."
+msgstr ""
+
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr ""
+
+msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please provide a name"
+msgstr ""
+
+msgid "Please provide a name."
+msgstr ""
+
+msgid "Please provide a valid URL."
+msgstr ""
+
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please provide attributes to update"
+msgstr ""
+
+msgid "Please reach out if you have any questions and we'll be happy to assist."
+msgstr ""
+
+msgid "Please review the %{linkStart}contribution guidelines%{linkEnd} for this project."
+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 ""
+
+msgid "Please select a Jira project"
+msgstr ""
+
+msgid "Please select a country"
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
+msgid "Please select a group"
+msgstr ""
+
+msgid "Please select a valid target branch"
+msgstr ""
+
+msgid "Please select a valid target branch."
+msgstr ""
+
+msgid "Please select and add a member"
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please select what should be included in each exported requirement."
+msgstr ""
+
+msgid "Please select..."
+msgstr ""
+
+msgid "Please set a new password before proceeding."
+msgstr ""
+
+msgid "Please solve the captcha"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
+msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
+msgid "Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
+msgid "Pods in use"
+msgstr ""
+
+msgid "Point to any links you like: documentation, built binaries, or other related materials. These can be internal or external links from your GitLab instance. Each URL and link title must be unique."
+msgstr ""
+
+msgid "Policies"
+msgstr ""
+
+msgid "Policy '%{escalation_policy_name}' does not exist."
+msgstr ""
+
+msgid "Policy management project does not have any policies in %{policy_path}"
+msgstr ""
+
+msgid "Policy project doesn't exist"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|%{firstLabel} +%{numberOfAdditionalLabels} more"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|All %{itemTypeName}"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|Select %{itemTypeName}"
+msgstr ""
+
+msgid "PolicyRuleMultiSelect|Select all"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Port"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
+msgid "Postman collection file URL"
+msgstr ""
+
+msgid "Postman collection file path or URL"
+msgstr ""
+
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
+msgid "Pre-defined push rules"
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences saved."
+msgstr ""
+
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see by default on your dashboard."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Color for added lines"
+msgstr ""
+
+msgid "Preferences|Color for removed lines"
+msgstr ""
+
+msgid "Preferences|Color theme"
+msgstr ""
+
+msgid "Preferences|Configure how dates and times display for you."
+msgstr ""
+
+msgid "Preferences|Customize integrations with third party services."
+msgstr ""
+
+msgid "Preferences|Customize the color of GitLab."
+msgstr ""
+
+msgid "Preferences|Customize the colors of removed and added lines in diffs."
+msgstr ""
+
+msgid "Preferences|Dashboard"
+msgstr ""
+
+msgid "Preferences|Diff colors"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|Enable Gitpod integration"
+msgstr ""
+
+msgid "Preferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "Preferences|Failed to save preferences."
+msgstr ""
+
+msgid "Preferences|For example: 30 minutes ago."
+msgstr ""
+
+msgid "Preferences|Gitpod"
+msgstr ""
+
+msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgstr ""
+
+msgid "Preferences|Integrations"
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
+msgid "Preferences|Must be a number between %{min} and %{max}"
+msgstr ""
+
+msgid "Preferences|Preview"
+msgstr ""
+
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Render whitespace characters in the Web IDE"
+msgstr ""
+
+msgid "Preferences|Show one file at a time on merge request's Changes tab"
+msgstr ""
+
+msgid "Preferences|Show whitespace changes in diffs"
+msgstr ""
+
+msgid "Preferences|Sourcegraph"
+msgstr ""
+
+msgid "Preferences|Surround text selection when typing quotes or brackets"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|Tab width"
+msgstr ""
+
+msgid "Preferences|This feature is experimental and translations are not yet complete."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
+msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
+msgstr ""
+
+msgid "Preparing the report for the scan."
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Prevent auto-stopping"
+msgstr ""
+
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr ""
+
+msgid "Prevent environment from auto-stopping"
+msgstr ""
+
+msgid "Prevent project forking outside current group"
+msgstr ""
+
+msgid "Prevent users from changing their profile name"
+msgstr ""
+
+msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
+msgid "Preview Markdown"
+msgstr ""
+
+msgid "Preview changes"
+msgstr ""
+
+msgid "Preview diagram"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Previous Artifacts"
+msgstr ""
+
+msgid "Previous commit"
+msgstr ""
+
+msgid "Previous design"
+msgstr ""
+
+msgid "Previous file in diff"
+msgstr ""
+
+msgid "Previous unresolved discussion"
+msgstr ""
+
+msgid "Primary Action"
+msgstr ""
+
+msgid "Print codes"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Priority"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Guest users are not allowed to view detailed release information like title and source code."
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private group(s)"
+msgstr ""
+
+msgid "Private profile"
+msgstr ""
+
+msgid "Private projects Minutes cost factor"
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Problem with %{name} command: %{message}."
+msgstr ""
+
+msgid "Proceed"
+msgstr ""
+
+msgid "Product Analytics"
+msgstr ""
+
+msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
+msgstr ""
+
+msgid "Productivity"
+msgstr ""
+
+msgid "Productivity Analytics"
+msgstr ""
+
+msgid "Productivity analytics can help identify the problems that are delaying your team"
+msgstr ""
+
+msgid "ProductivityAanalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Ascending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Descending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Hours"
+msgstr ""
+
+msgid "ProductivityAnalytics|List"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Time to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Trendline"
+msgstr ""
+
+msgid "ProductivityAnalytics|is earlier than the given merged at after date"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profile failed to delete"
+msgstr ""
+
+msgid "Profile image guideline"
+msgstr ""
+
+msgid "Profile page:"
+msgstr ""
+
+msgid "Profile parameter missing"
+msgstr ""
+
+msgid "ProfileSession|on"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|%{provider} Active"
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|An error occurred while updating your username, please try again."
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Begins with %{ssh_key_algorithms}."
+msgstr ""
+
+msgid "Profiles|Bio"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Commit email"
+msgstr ""
+
+msgid "Profiles|Connect %{provider}"
+msgstr ""
+
+msgid "Profiles|Connect a service for sign-in."
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Default notification email"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Disconnect %{provider}"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profile."
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Ensure you have two-factor authentication recovery codes stored in a safe place."
+msgstr ""
+
+msgid "Profiles|Enter how your name is pronounced to help people address you correctly."
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Enter your password to confirm the email change"
+msgstr ""
+
+msgid "Profiles|Enter your pronouns to let people know how to refer to you."
+msgstr ""
+
+msgid "Profiles|Example: MacBook key"
+msgstr ""
+
+msgid "Profiles|Expiration date"
+msgstr ""
+
+msgid "Profiles|Expired:"
+msgstr ""
+
+msgid "Profiles|Expires:"
+msgstr ""
+
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|GitLab is unable to verify your identity automatically. For security purposes, you must set a password by %{openingTag}resetting your password%{closingTag} to delete your account."
+msgstr ""
+
+msgid "Profiles|If after setting a password, the option to delete your account is still not available, please %{link_start}submit a request%{link_end} to begin the account deletion process."
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Job title"
+msgstr ""
+
+msgid "Profiles|Key"
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key titles are publicly visible."
+msgstr ""
+
+msgid "Profiles|Last used:"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Location"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|Manage two-factor authentication"
+msgstr ""
+
+msgid "Profiles|No file chosen."
+msgstr ""
+
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Optional but recommended. If set, key becomes invalid on the specified date."
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Primary email"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
+msgid "Profiles|Pronouns"
+msgstr ""
+
+msgid "Profiles|Pronunciation"
+msgstr ""
+
+msgid "Profiles|Public avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Publicly visible private SSH keys can compromise your system."
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
+msgid "Profiles|Service sign-in"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Set your local time zone."
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Static object token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The ability to update your name has been disabled by your administrator."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more.%{commit_email_link_end}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Time settings"
+msgstr ""
+
+msgid "Profiles|Title"
+msgstr ""
+
+msgid "Profiles|Two-factor authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|User ID"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|Website url"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for."
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|https://website.com"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profile|%{job_title} at %{organization}"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Progress tracking"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
+msgid "Project %{project_repo} could not be found"
+msgstr ""
+
+msgid "Project & Group can not be assigned at the same time"
+msgstr ""
+
+msgid "Project '%{project_name}' is being imported."
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' is restored."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted on %{date}"
+msgstr ""
+
+msgid "Project Access Tokens"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+msgstr ""
+
+msgid "Project Templates"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
+msgstr ""
+
+msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Project already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+msgstr ""
+
+msgid "Project audit events"
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
+msgid "Project configuration, excluding integrations"
+msgstr ""
+
+msgid "Project description (optional)"
+msgstr ""
+
+msgid "Project does not exist or you don't have permission to perform this action"
+msgstr ""
+
+msgid "Project does not have a policy configuration"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export download requests"
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export requests"
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Project has too many %{label_for_message} to search"
+msgstr ""
+
+msgid "Project import requests"
+msgstr ""
+
+msgid "Project info:"
+msgstr ""
+
+msgid "Project information"
+msgstr ""
+
+msgid "Project is required when cluster_type is :project"
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project milestone"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project navigation"
+msgstr ""
+
+msgid "Project order will not be saved as local storage is not available."
+msgstr ""
+
+msgid "Project path"
+msgstr ""
+
+msgid "Project security status"
+msgstr ""
+
+msgid "Project security status help page"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project uploads"
+msgstr ""
+
+msgid "Project visibility level is less restrictive than the group settings."
+msgstr ""
+
+msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
+msgstr ""
+
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "Project: %{name}"
+msgstr ""
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr ""
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectCreationLevel|Roles allowed to create projects"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Starrer"
+msgstr ""
+
+msgid "ProjectOverview|Starrers"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Failure"
+msgstr ""
+
+msgid "ProjectQualitySummary|Get insight into the overall percentage of tests in your project that succeed, fail and are skipped."
+msgstr ""
+
+msgid "ProjectQualitySummary|Help us improve this page"
+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|Provide feedback"
+msgstr ""
+
+msgid "ProjectQualitySummary|See full report"
+msgstr ""
+
+msgid "ProjectQualitySummary|See project Code Coverage Statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Set up test runs"
+msgstr ""
+
+msgid "ProjectQualitySummary|Set up test runs (opens in a new tab)"
+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 "ProjectQualitySummary|This page helps you understand the code testing trends for your project. Let us know how we can improve it!"
+msgstr ""
+
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|No matching results"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSelect|Search projects"
+msgstr ""
+
+msgid "ProjectSelect|Select a project"
+msgstr ""
+
+msgid "ProjectSelect|Something went wrong while fetching projects"
+msgstr ""
+
+msgid "ProjectSelect|There was an error fetching the projects. Please try again."
+msgstr ""
+
+msgid "ProjectService|Drone server URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Enter new password."
+msgstr ""
+
+msgid "ProjectService|Enter new token"
+msgstr ""
+
+msgid "ProjectService|Jenkins server URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key."
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password."
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with Buildkite."
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with Drone."
+msgstr ""
+
+msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
+msgstr ""
+
+msgid "ProjectService|TeamCity server URL"
+msgstr ""
+
+msgid "ProjectService|The build configuration ID of the TeamCity project."
+msgstr ""
+
+msgid "ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository."
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectService|Token for the Drone project."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments on confidential issues."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new tags pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event for pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
+msgstr ""
+
+msgid "ProjectService|Trigger event when a pipeline status changes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a wiki page is created or updated."
+msgstr ""
+
+msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional options"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
+
+msgid "ProjectSettings|All threads must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
+msgstr ""
+
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff threads when they become outdated"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Build, test, and deploy your changes."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and selected by default."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and unselected by default."
+msgstr ""
+
+msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
+msgstr ""
+
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
+msgid "ProjectSettings|Configure your project resources and monitor their health."
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Container registry"
+msgstr ""
+
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
+
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
+msgid "ProjectSettings|Disable email notifications"
+msgstr ""
+
+msgid "ProjectSettings|Do not allow"
+msgstr ""
+
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
+
+msgid "ProjectSettings|Enable merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Enable merged results pipelines"
+msgstr ""
+
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
+msgid "ProjectSettings|Encourage"
+msgstr ""
+
+msgid "ProjectSettings|Environments"
+msgstr ""
+
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its Docker images"
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its packages."
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its packages. Note: The Package Registry is always visible when a project is public."
+msgstr ""
+
+msgid "ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access."
+msgstr ""
+
+msgid "ProjectSettings|Everyone"
+msgstr ""
+
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
+
+msgid "ProjectSettings|Feature flags"
+msgstr ""
+
+msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
+msgstr ""
+
+msgid "ProjectSettings|Forks"
+msgstr ""
+
+msgid "ProjectSettings|Git Large File Storage (LFS)"
+msgstr ""
+
+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 ""
+
+msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
+msgstr ""
+
+msgid "ProjectSettings|How do they differ?"
+msgstr ""
+
+msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
+msgstr ""
+
+msgid "ProjectSettings|Internal"
+msgstr ""
+
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
+msgid "ProjectSettings|Issues"
+msgstr ""
+
+msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgstr ""
+
+msgid "ProjectSettings|Leave empty to use default template."
+msgstr ""
+
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
+msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
+msgstr ""
+
+msgid "ProjectSettings|Maximum %{maxLength} 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 ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
+msgstr ""
+
+msgid "ProjectSettings|Merge suggestions"
+msgstr ""
+
+msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
+msgstr ""
+
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
+
+msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
+msgstr ""
+
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Operations"
+msgstr ""
+
+msgid "ProjectSettings|Override user notification preferences for all project members."
+msgstr ""
+
+msgid "ProjectSettings|Package registry"
+msgstr ""
+
+msgid "ProjectSettings|Packages"
+msgstr ""
+
+msgid "ProjectSettings|Pages"
+msgstr ""
+
+msgid "ProjectSettings|Pages for project documentation."
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Prevents direct linking to potentially sensitive media files"
+msgstr ""
+
+msgid "ProjectSettings|Private"
+msgstr ""
+
+msgid "ProjectSettings|Project visibility"
+msgstr ""
+
+msgid "ProjectSettings|Public"
+msgstr ""
+
+msgid "ProjectSettings|Releases"
+msgstr ""
+
+msgid "ProjectSettings|Repository"
+msgstr ""
+
+msgid "ProjectSettings|Require"
+msgstr ""
+
+msgid "ProjectSettings|Require an associated issue from Jira"
+msgstr ""
+
+msgid "ProjectSettings|Require authentication to view media files"
+msgstr ""
+
+msgid "ProjectSettings|Requirements"
+msgstr ""
+
+msgid "ProjectSettings|Requirements management system."
+msgstr ""
+
+msgid "ProjectSettings|Roll out new features without redeploying with feature flags."
+msgstr ""
+
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance for this project"
+msgstr ""
+
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Share code with others outside the project."
+msgstr ""
+
+msgid "ProjectSettings|Show default award emojis"
+msgstr ""
+
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|Skipped pipelines are considered successful"
+msgstr ""
+
+msgid "ProjectSettings|Snippets"
+msgstr ""
+
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
+msgid "ProjectSettings|Squash commits when merging"
+msgstr ""
+
+msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
+msgstr ""
+
+msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
+msgstr ""
+
+msgid "ProjectSettings|Submit changes to be merged upstream."
+msgstr ""
+
+msgid "ProjectSettings|Target project"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when applying merge request suggestions."
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits."
+msgstr ""
+
+msgid "ProjectSettings|The default target project for merge requests created in this fork project."
+msgstr ""
+
+msgid "ProjectSettings|The default template will be applied on save."
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
+msgstr ""
+
+msgid "ProjectSettings|This project"
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Transfer project"
+msgstr ""
+
+msgid "ProjectSettings|Upstream project"
+msgstr ""
+
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
+msgid "ProjectSettings|Users can copy the repository to a new project."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository if the committer email is one of their own verified emails."
+msgstr ""
+
+msgid "ProjectSettings|Users can request access"
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project."
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
+msgstr ""
+
+msgid "ProjectSettings|View project analytics."
+msgstr ""
+
+msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
+msgstr ""
+
+msgid "ProjectSettings|Visualize the project's performance metrics."
+msgstr ""
+
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
+msgid "ProjectSettings|What are badges?"
+msgstr ""
+
+msgid "ProjectSettings|What are merge trains?"
+msgstr ""
+
+msgid "ProjectSettings|What is squashing?"
+msgstr ""
+
+msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|When semi-linear merge is not possible, the user is given the option to rebase."
+msgstr ""
+
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
+
+msgid "ProjectSettings|Wiki"
+msgstr ""
+
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|GitLab Cluster Management"
+msgstr ""
+
+msgid "ProjectTemplates|Gitpod/Spring Petclinic"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|HIPAA Audit Protocol"
+msgstr ""
+
+msgid "ProjectTemplates|Jsonnet for Dynamic Child Pipelines"
+msgstr ""
+
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Gatsby"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Middleman"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Pelican"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|SalesforceDX"
+msgstr ""
+
+msgid "ProjectTemplates|Sample GitLab Project"
+msgstr ""
+
+msgid "ProjectTemplates|Serverless Framework/JS"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
+msgid "ProjectView|Activity"
+msgstr ""
+
+msgid "ProjectView|Files and Readme (default)"
+msgstr ""
+
+msgid "ProjectView|Readme"
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects (%{count})"
+msgstr ""
+
+msgid "Projects API"
+msgstr ""
+
+msgid "Projects Successfully Retrieved"
+msgstr ""
+
+msgid "Projects are graded based on the highest severity vulnerability present"
+msgstr ""
+
+msgid "Projects are organized into groups"
+msgstr ""
+
+msgid "Projects are where you store your code, access issues, wiki and other features of GitLab."
+msgstr ""
+
+msgid "Projects contributed to"
+msgstr ""
+
+msgid "Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more."
+msgstr ""
+
+msgid "Projects in this group can use Git LFS"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that can be accessed"
+msgstr ""
+
+msgid "Projects to index"
+msgstr ""
+
+msgid "Projects with critical vulnerabilities"
+msgstr ""
+
+msgid "Projects with high or unknown vulnerabilities"
+msgstr ""
+
+msgid "Projects with low vulnerabilities"
+msgstr ""
+
+msgid "Projects with medium vulnerabilities"
+msgstr ""
+
+msgid "Projects with no vulnerabilities and security scanning enabled"
+msgstr ""
+
+msgid "Projects with this topic"
+msgstr ""
+
+msgid "Projects with write access"
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
+msgstr ""
+
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
+msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
+msgstr ""
+
+msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
+msgstr ""
+
+msgid "ProjectsNew|Create"
+msgstr ""
+
+msgid "ProjectsNew|Create a blank project to store your files, plan your work, and collaborate on code, among other things."
+msgstr ""
+
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
+msgid "ProjectsNew|Create blank project"
+msgstr ""
+
+msgid "ProjectsNew|Create from template"
+msgstr ""
+
+msgid "ProjectsNew|Create new project"
+msgstr ""
+
+msgid "ProjectsNew|Description format"
+msgstr ""
+
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "ProjectsNew|Import"
+msgstr ""
+
+msgid "ProjectsNew|Import project"
+msgstr ""
+
+msgid "ProjectsNew|Include a Getting Started README"
+msgstr ""
+
+msgid "ProjectsNew|Initialize repository with a README"
+msgstr ""
+
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
+msgid "ProjectsNew|No import options available"
+msgstr ""
+
+msgid "ProjectsNew|Pick a group or namespace"
+msgstr ""
+
+msgid "ProjectsNew|Pick a group or namespace where you want to create this project."
+msgstr ""
+
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
+msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
+msgstr ""
+
+msgid "ProjectsNew|Recommended if you're new to GitLab"
+msgstr ""
+
+msgid "ProjectsNew|Run CI/CD for external repository"
+msgstr ""
+
+msgid "ProjectsNew|Visibility Level"
+msgstr ""
+
+msgid "ProjectsNew|Want to organize several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
+msgstr ""
+
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope \"*\" OR a manually configured Prometheus to be available."
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|Monitor application health with Prometheus metrics and dashboards"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
+msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
+msgstr ""
+
+msgid "PrometheusService|Prometheus cluster integration"
+msgstr ""
+
+msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
+msgstr ""
+
+msgid "PrometheusService|The ID of the IAP-secured resource."
+msgstr ""
+
+msgid "PrometheusService|The Prometheus API base URL."
+msgstr ""
+
+msgid "PrometheusService|The contents of the credentials.json file of your service account."
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration."
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
+msgstr ""
+
+msgid "PrometheusService|https://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote issue to an epic"
+msgstr ""
+
+msgid "Promote issue to incident"
+msgstr ""
+
+msgid "Promote to epic"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
+msgid "Promoted 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 ""
+
+msgid "Promotions|Better Protected Branches"
+msgstr ""
+
+msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
+msgstr ""
+
+msgid "Promotions|Buy EE"
+msgstr ""
+
+msgid "Promotions|Buy GitLab Enterprise Edition"
+msgstr ""
+
+msgid "Promotions|Configure Service Desk"
+msgstr ""
+
+msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact your Administrator to upgrade your license."
+msgstr ""
+
+msgid "Promotions|Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Promotions|Dismiss Service Desk promotion"
+msgstr ""
+
+msgid "Promotions|Dismiss burndown charts promotion"
+msgstr ""
+
+msgid "Promotions|Dismiss repository features promotion"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Improve repositories with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Keep track of events in your project"
+msgstr ""
+
+msgid "Promotions|Learn more"
+msgstr ""
+
+msgid "Promotions|Merge request approvals"
+msgstr ""
+
+msgid "Promotions|Not now, thanks!"
+msgstr ""
+
+msgid "Promotions|Push Rules"
+msgstr ""
+
+msgid "Promotions|Push Rules are defined per project so you can have different rules applied to different projects depends on your needs."
+msgstr ""
+
+msgid "Promotions|Repository Mirroring"
+msgstr ""
+
+msgid "Promotions|Repository Mirroring is a way to mirror repositories from external sources. It can be used to mirror all branches, tags, and commits that you have in your repository."
+msgstr ""
+
+msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
+msgstr ""
+
+msgid "Promotions|Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
+msgid "Promotions|Start GitLab Ultimate trial"
+msgstr ""
+
+msgid "Promotions|The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Try it for free"
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Advanced Search."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Audit Events."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve merge requests."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve repositories."
+msgstr ""
+
+msgid "Promotions|Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Promotions|Weight"
+msgstr ""
+
+msgid "Promotions|Weighting your issue"
+msgstr ""
+
+msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them."
+msgstr ""
+
+msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
+msgstr ""
+
+msgid "Promotions|description templates"
+msgstr ""
+
+msgid "Promotions|to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "Prompt users to upload SSH keys"
+msgstr ""
+
+msgid "Protect"
+msgstr ""
+
+msgid "Protect a tag"
+msgstr ""
+
+msgid "Protect variable"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Branches"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
+msgid "Protected Paths: requests"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
+msgid "Protected Tags"
+msgstr ""
+
+msgid "Protected branches"
+msgstr ""
+
+msgid "Protected environments"
+msgstr ""
+
+msgid "Protected paths"
+msgstr ""
+
+msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
+msgstr ""
+
+msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
+msgstr ""
+
+msgid "ProtectedBranch|Allow all users with push access to force push."
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to force push:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push:"
+msgstr ""
+
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
+msgid "ProtectedBranch|Branch"
+msgstr ""
+
+msgid "ProtectedBranch|Branch will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
+msgid "ProtectedBranch|By default, protected branches restrict who can modify the branch."
+msgstr ""
+
+msgid "ProtectedBranch|Code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
+msgstr ""
+
+msgid "ProtectedBranch|Keep stable branches secure and force developers to use merge requests."
+msgstr ""
+
+msgid "ProtectedBranch|Learn more."
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branches"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
+
+msgid "ProtectedBranch|Require approval from code owners:"
+msgstr ""
+
+msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
+msgstr ""
+
+msgid "ProtectedBranch|Toggle allowed to force push"
+msgstr ""
+
+msgid "ProtectedBranch|Toggle code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Unprotect"
+msgstr ""
+
+msgid "ProtectedBranch|Unprotect branch"
+msgstr ""
+
+msgid "ProtectedBranch|What are protected branches?"
+msgstr ""
+
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
+msgid "ProtectedBranch|default"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
+msgid "ProtectedEnvironment|Parent group"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Required approvals"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select groups"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "ProtectedTags|Unprotect tag"
+msgstr ""
+
+msgid "ProtectedTags|default"
+msgstr ""
+
+msgid "ProtectedTag|By default, protected tags restrict who can modify the tag."
+msgstr ""
+
+msgid "ProtectedTag|Learn more."
+msgstr ""
+
+msgid "ProtectedTag|Limit access to creating and updating tags."
+msgstr ""
+
+msgid "ProtectedTag|Protected tags"
+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 ""
+
+msgid "Provide Feedback"
+msgstr ""
+
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Provision instructions"
+msgstr ""
+
+msgid "Provisioned by:"
+msgstr ""
+
+msgid "Proxy support for this API is not available currently"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public Access Help"
+msgstr ""
+
+msgid "Public deploy keys"
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Public projects Minutes cost factor"
+msgstr ""
+
+msgid "Public projects are an easy way to allow everyone to have read-only access."
+msgstr ""
+
+msgid "Publish to status page"
+msgstr ""
+
+msgid "Published"
+msgstr ""
+
+msgid "Published on status page"
+msgstr ""
+
+msgid "Publishes this issue to the associated status page."
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
+msgid "Pull requests from fork are not supported"
+msgstr ""
+
+msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
+msgstr ""
+
+msgid "PumbleIntegration|Send notifications about project events to Pumble."
+msgstr ""
+
+msgid "PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}"
+msgstr ""
+
+msgid "Purchase more minutes"
+msgstr ""
+
+msgid "Purchase more storage"
+msgstr ""
+
+msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rule updated successfully."
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push Rules updated successfully."
+msgstr ""
+
+msgid "Push an existing Git repository"
+msgstr ""
+
+msgid "Push an existing folder"
+msgstr ""
+
+msgid "Push code to the repository."
+msgstr ""
+
+msgid "Push commits to the source branch or add previously merged commits to review them."
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push the target branch up to GitLab."
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRules|All branch names must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any branch name is allowed."
+msgstr ""
+
+msgid "PushRules|All commit author's email must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any email is allowed."
+msgstr ""
+
+msgid "PushRules|All commit messages must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not required to match any expression."
+msgstr ""
+
+msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
+msgstr ""
+
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
+msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
+msgstr ""
+
+msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
+msgstr ""
+
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
+msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
+msgstr ""
+
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
+msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
+msgstr ""
+
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
+msgid "PushRules|Restrict commits to existing GitLab users."
+msgstr ""
+
+msgid "PushRules|Restrict push operations for this project."
+msgstr ""
+
+msgid "PushRules|Save push rules"
+msgstr ""
+
+msgid "PushRules|Select push rules"
+msgstr ""
+
+msgid "PushRules|Users can still delete tags through the GitLab UI."
+msgstr ""
+
+msgid "PushRule|Push rules"
+msgstr ""
+
+msgid "PushRule|Reject unverified users"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|Enter new user key"
+msgstr ""
+
+msgid "PushoverService|Enter your application key."
+msgstr ""
+
+msgid "PushoverService|Enter your user key."
+msgstr ""
+
+msgid "PushoverService|Get real-time notifications on your device."
+msgstr ""
+
+msgid "PushoverService|High priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices."
+msgstr ""
+
+msgid "PushoverService|Leave blank to use your current user key."
+msgstr ""
+
+msgid "PushoverService|Low priority"
+msgstr ""
+
+msgid "PushoverService|Lowest priority"
+msgstr ""
+
+msgid "PushoverService|Normal priority"
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "QualitySummary|Project quality"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query cannot be processed"
+msgstr ""
+
+msgid "Queued"
+msgstr ""
+
+msgid "Quick actions can be used in description and comment boxes."
+msgstr ""
+
+msgid "Quick help"
+msgstr ""
+
+msgid "Quick range"
+msgstr ""
+
+msgid "Quota of CI/CD minutes"
+msgstr ""
+
+msgid "Quota of CI/CD minutes:"
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Rails"
+msgstr ""
+
+msgid "Rake Tasks Help"
+msgstr ""
+
+msgid "Random"
+msgstr ""
+
+msgid "Rate Limits"
+msgstr ""
+
+msgid "Rate limit"
+msgstr ""
+
+msgid "Rate limit access to specified paths."
+msgstr ""
+
+msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
+msgstr ""
+
+msgid "Raw blob request rate limit per minute"
+msgstr ""
+
+msgid "Raw blob requests"
+msgstr ""
+
+msgid "Re-authentication period expired or never requested. Please try again"
+msgstr ""
+
+msgid "Re-authentication required"
+msgstr ""
+
+msgid "Re-import"
+msgstr ""
+
+msgid "Re-request review"
+msgstr ""
+
+msgid "Read documentation"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about GitLab at %{link_to_promo}."
+msgstr ""
+
+msgid "Read more about related epics"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Read their documentation."
+msgstr ""
+
+msgid "Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
+msgstr ""
+
+msgid "Ready to merge by members who can write to the target branch."
+msgstr ""
+
+msgid "Ready to merge!"
+msgstr ""
+
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
+msgid "Rebase"
+msgstr ""
+
+msgid "Rebase completed"
+msgstr ""
+
+msgid "Rebase in progress"
+msgstr ""
+
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
+msgid "Rebase without pipeline"
+msgstr ""
+
+msgid "Recaptcha verified?"
+msgstr ""
+
+msgid "Receive any notifications from GitLab."
+msgstr ""
+
+msgid "Receive notification of abuse reports by email."
+msgstr ""
+
+msgid "Receive notifications about your own activity"
+msgstr ""
+
+msgid "Receive product marketing emails"
+msgstr ""
+
+msgid "Recent"
+msgstr ""
+
+msgid "Recent Project Activity"
+msgstr ""
+
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
+msgid "Recent events"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Recently used"
+msgstr ""
+
+msgid "Reconfigure"
+msgstr ""
+
+msgid "Recover password"
+msgstr ""
+
+msgid "Recovery Codes"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Redirecting"
+msgstr ""
+
+msgid "Redis"
+msgstr ""
+
+msgid "Reduce incident management alert volume (for example, if too many issues are being created)."
+msgstr ""
+
+msgid "Reduce project visibility"
+msgstr ""
+
+msgid "Reduce risk and triage fewer vulnerabilities with security training"
+msgstr ""
+
+msgid "Reduce this project’s visibility?"
+msgstr ""
+
+msgid "Reference"
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid "Refine your search criteria (select a %{strong_open}group%{strong_close} and %{strong_open}project%{strong_close} when possible)"
+msgstr ""
+
+msgid "Refresh the page and try again."
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate export"
+msgstr ""
+
+msgid "Regenerate instance ID"
+msgstr ""
+
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Region"
+msgstr ""
+
+msgid "Regions"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
+msgid "Register WebAuthn Device"
+msgstr ""
+
+msgid "Register device"
+msgstr ""
+
+msgid "Register now"
+msgstr ""
+
+msgid "Register the runner with this URL:"
+msgstr ""
+
+msgid "Register with two-factor app"
+msgstr ""
+
+msgid "Register with:"
+msgstr ""
+
+msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
+msgstr ""
+
+msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
+msgstr ""
+
+msgid "RegistrationFeatures|Registration Features Program"
+msgstr ""
+
+msgid "RegistrationFeatures|Want to %{feature_title} for free?"
+msgstr ""
+
+msgid "RegistrationFeatures|send emails to users"
+msgstr ""
+
+msgid "RegistrationFeatures|use this feature"
+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 ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
+msgstr ""
+
+msgid "Reject"
+msgstr ""
+
+msgid "Rejected (closed)"
+msgstr ""
+
+msgid "Relate to %{issuable_type} %{add_related_issue_link}"
+msgstr ""
+
+msgid "Related feature flags"
+msgstr ""
+
+msgid "Related issues"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Relates to"
+msgstr ""
+
+msgid "Release"
+msgid_plural "Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
+msgid "Release assets"
+msgstr ""
+
+msgid "Release assets documentation"
+msgstr ""
+
+msgid "Release date"
+msgstr ""
+
+msgid "Release does not have the same project as the milestone"
+msgstr ""
+
+msgid "Release notes"
+msgstr ""
+
+msgid "Release notes:"
+msgstr ""
+
+msgid "Release title"
+msgstr ""
+
+msgid "Release with tag \"%{tag}\" was not found"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Image"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Images"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Other"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Package"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Packages"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbook"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbooks"
+msgstr ""
+
+msgid "Released date"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases are based on Git tags and mark specific points in a project's development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software."
+msgstr ""
+
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
+msgstr ""
+
+msgid "Releases documentation"
+msgstr ""
+
+msgid "Releases|New Release"
+msgstr ""
+
+msgid "Releases|Tag message"
+msgstr ""
+
+msgid "Release|Include message from the annotated tag."
+msgstr ""
+
+msgid "Release|Something went wrong while creating a new release."
+msgstr ""
+
+msgid "Release|Something went wrong while deleting the release."
+msgstr ""
+
+msgid "Release|Something went wrong while getting the release details."
+msgstr ""
+
+msgid "Release|Something went wrong while saving the release details."
+msgstr ""
+
+msgid "Release|Unable to fetch the tag notes."
+msgstr ""
+
+msgid "Release|You can edit the content later by editing the release. %{linkStart}How do I edit a release?%{linkEnd}"
+msgstr ""
+
+msgid "Reload page"
+msgstr ""
+
+msgid "Remediations"
+msgstr ""
+
+msgid "Remember me"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remote object has no absolute path."
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove %{displayReference}"
+msgstr ""
+
+msgid "Remove Zoom meeting"
+msgstr ""
+
+msgid "Remove Zoom meeting."
+msgstr ""
+
+msgid "Remove access"
+msgstr ""
+
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr ""
+
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
+msgid "Remove approvers"
+msgstr ""
+
+msgid "Remove approvers?"
+msgstr ""
+
+msgid "Remove asset link"
+msgstr ""
+
+msgid "Remove assignee"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove card"
+msgstr ""
+
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
+msgid "Remove deploy key"
+msgstr ""
+
+msgid "Remove description history"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
+msgid "Remove favicon"
+msgstr ""
+
+msgid "Remove file"
+msgstr ""
+
+msgid "Remove fork relationship"
+msgstr ""
+
+msgid "Remove from batch"
+msgstr ""
+
+msgid "Remove from epic"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove header logo"
+msgstr ""
+
+msgid "Remove iteration"
+msgstr ""
+
+msgid "Remove license"
+msgstr ""
+
+msgid "Remove limit"
+msgstr ""
+
+msgid "Remove link"
+msgstr ""
+
+msgid "Remove list"
+msgstr ""
+
+msgid "Remove log"
+msgstr ""
+
+msgid "Remove logo"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove report"
+msgstr ""
+
+msgid "Remove reviewer"
+msgstr ""
+
+msgid "Remove runner"
+msgstr ""
+
+msgid "Remove secondary email"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Remove topic avatar"
+msgstr ""
+
+msgid "Remove user"
+msgstr ""
+
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+msgstr ""
+
+msgid "Remove user from project"
+msgstr ""
+
+msgid "Remove..."
+msgstr ""
+
+msgid "Removed"
+msgstr ""
+
+msgid "Removed %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removed %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removed %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removed %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removed %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removed all labels."
+msgstr ""
+
+msgid "Removed an issue from an epic."
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removed parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removed spent time."
+msgstr ""
+
+msgid "Removed the due date."
+msgstr ""
+
+msgid "Removed time estimate."
+msgstr ""
+
+msgid "Removed upload with id %{id}"
+msgstr ""
+
+msgid "RemovedProjects|No projects pending deletion found"
+msgstr ""
+
+msgid "RemovedProjects|Projects that are pending deletion that you have access to are listed here."
+msgstr ""
+
+msgid "Removes %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removes %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes an issue from an epic."
+msgstr ""
+
+msgid "Removes parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
+msgid "Removing this group also removes all child projects, including archived projects, and their resources."
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Rename/Move"
+msgstr ""
+
+msgid "Render diagrams in your documents using PlantUML."
+msgstr ""
+
+msgid "Renew subscription"
+msgstr ""
+
+msgid "Renews"
+msgstr ""
+
+msgid "Reopen"
+msgstr ""
+
+msgid "Reopen %{issueType}"
+msgstr ""
+
+msgid "Reopen %{noteable}"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reopen test case"
+msgstr ""
+
+msgid "Reopen this %{quick_action_target}"
+msgstr ""
+
+msgid "Reopened this %{quick_action_target}."
+msgstr ""
+
+msgid "Reopens this %{quick_action_target}."
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace %{name}"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replace audio"
+msgstr ""
+
+msgid "Replace file"
+msgstr ""
+
+msgid "Replace image"
+msgstr ""
+
+msgid "Replace video"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Reply"
+msgstr ""
+
+msgid "Reply by email"
+msgstr ""
+
+msgid "Reply internally"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Reply…"
+msgstr ""
+
+msgid "Report Finding not found"
+msgstr ""
+
+msgid "Report abuse"
+msgstr ""
+
+msgid "Report abuse to admin"
+msgstr ""
+
+msgid "Report couldn't be prepared."
+msgstr ""
+
+msgid "Report for the scan has been removed from the database."
+msgstr ""
+
+msgid "Report version not provided, %{report_type} report type supports versions: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
+msgstr ""
+
+msgid "Report your license usage data to GitLab"
+msgstr ""
+
+msgid "Reported %{timeAgo} by %{reportedBy}"
+msgstr ""
+
+msgid "Reported by"
+msgstr ""
+
+msgid "Reported by %{reporter}"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{combinedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
+msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected no issues for the source branch only"
+msgstr ""
+
+msgid "Reports|Accessibility scanning failed loading results"
+msgstr ""
+
+msgid "Reports|Accessibility scanning results are being parsed"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Activity"
+msgstr ""
+
+msgid "Reports|An error occurred while loading %{name} results"
+msgstr ""
+
+msgid "Reports|An error occurred while loading report"
+msgstr ""
+
+msgid "Reports|Base report parsing error:"
+msgstr ""
+
+msgid "Reports|Classname"
+msgstr ""
+
+msgid "Reports|Copy failed test names to run locally"
+msgstr ""
+
+msgid "Reports|Copy failed tests"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failed %{count} time in %{baseBranch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{baseBranch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failed %{count} time in %{base_branch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{base_branch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Fixed"
+msgstr ""
+
+msgid "Reports|Full report"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
+msgid "Reports|Identifier"
+msgstr ""
+
+msgid "Reports|Metrics report scanning detected no new changes"
+msgstr ""
+
+msgid "Reports|Metrics reports are loading"
+msgstr ""
+
+msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
+msgstr ""
+
+msgid "Reports|Metrics reports did not change"
+msgstr ""
+
+msgid "Reports|Metrics reports failed loading results"
+msgstr ""
+
+msgid "Reports|Metrics reports failed to load results"
+msgstr ""
+
+msgid "Reports|Metrics reports: %{strong_start}%{numberOfChanges}%{strong_end} %{changes}"
+msgstr ""
+
+msgid "Reports|New"
+msgstr ""
+
+msgid "Reports|Scanner"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary failed to load results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Test summary results are loading"
+msgstr ""
+
+msgid "Reports|Tool"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|Vulnerability Name"
+msgstr ""
+
+msgid "Reports|metrics report"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repositories"
+msgstr ""
+
+msgid "Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Analyze repositories for projects in %{groupName}. Data doesn't include projects in subgroups. %{learnMoreLink}."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average Coverage by Job"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average test coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
+msgstr ""
+
+msgid "RepositoriesAnalytics|In the last day, %{metricValue} job has code coverage."
+msgid_plural "RepositoriesAnalytics|In the last day, %{metricValue} jobs have code coverage."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "RepositoriesAnalytics|In the last day, %{metricValue} project in %{groupName} has code coverage enabled."
+msgid_plural "RepositoriesAnalytics|In the last day, %{metricValue} projects in %{groupName} have code coverage enabled."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "RepositoriesAnalytics|In the last day, on average, %{metricValue} of all jobs are covered."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Jobs with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last 30 days"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last updated %{timeAgo}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results for all projects in %{groupName} (excluding projects in subgroups)."
+msgstr ""
+
+msgid "RepositoriesAnalytics|No test coverage to display"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Projects with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Test Code Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|There was an error fetching the projects."
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Analytics"
+msgstr ""
+
+msgid "Repository Graph"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository already read-only"
+msgstr ""
+
+msgid "Repository by URL"
+msgstr ""
+
+msgid "Repository check"
+msgstr ""
+
+msgid "Repository check was triggered."
+msgstr ""
+
+msgid "Repository checks"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository clone URL"
+msgstr ""
+
+msgid "Repository files count over the limit"
+msgstr ""
+
+msgid "Repository has an invalid default branch name."
+msgstr ""
+
+msgid "Repository has more than one branch."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository has tags."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirroring"
+msgstr ""
+
+msgid "Repository mirroring configuration"
+msgstr ""
+
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
+msgid "Repository must contain at least 1 file."
+msgstr ""
+
+msgid "Repository size is above the limit."
+msgstr ""
+
+msgid "Repository size limit (MB)"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "Repository update events"
+msgstr ""
+
+msgid "Repository usage recalculation started"
+msgstr ""
+
+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 ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Request a new one"
+msgstr ""
+
+msgid "Request data is too large"
+msgstr ""
+
+msgid "Request details"
+msgstr ""
+
+msgid "Request parameter %{param} is missing."
+msgstr ""
+
+msgid "Request review from"
+msgstr ""
+
+msgid "Request time"
+msgstr ""
+
+msgid "Request to link SAML account must be authorized"
+msgstr ""
+
+msgid "Requested"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requested design version does not exist."
+msgstr ""
+
+msgid "Requested review"
+msgstr ""
+
+msgid "Requested states are invalid"
+msgstr ""
+
+msgid "Requests"
+msgstr ""
+
+msgid "Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}"
+msgstr ""
+
+msgid "Requests per period"
+msgstr ""
+
+msgid "Require additional authentication for administrative tasks."
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given)"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given, you've approved)"
+msgstr ""
+
+msgid "Required in this project."
+msgstr ""
+
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
+msgid "Requirement"
+msgstr ""
+
+msgid "Requirement %{reference} has been added"
+msgstr ""
+
+msgid "Requirement %{reference} has been archived"
+msgstr ""
+
+msgid "Requirement %{reference} has been reopened"
+msgstr ""
+
+msgid "Requirement %{reference} has been updated"
+msgstr ""
+
+msgid "Requirement title cannot have more than %{limit} characters."
+msgstr ""
+
+msgid "Requirements"
+msgstr ""
+
+msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
+msgstr ""
+
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires values to meet regular expression requirements."
+msgstr ""
+
+msgid "Requires you to deploy or set up cloud-hosted Sentry."
+msgstr ""
+
+msgid "Requires your primary GitLab email address."
+msgstr ""
+
+msgid "Resend"
+msgstr ""
+
+msgid "Resend Request"
+msgstr ""
+
+msgid "Resend confirmation e-mail"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Resend it"
+msgstr ""
+
+msgid "Resend unlock instructions"
+msgstr ""
+
+msgid "Reset"
+msgstr ""
+
+msgid "Reset error tracking access token"
+msgstr ""
+
+msgid "Reset file"
+msgstr ""
+
+msgid "Reset filters"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset password"
+msgstr ""
+
+msgid "Reset registration token"
+msgstr ""
+
+msgid "Reset template"
+msgstr ""
+
+msgid "Reset to project defaults"
+msgstr ""
+
+msgid "Resolve"
+msgstr ""
+
+msgid "Resolve conflicts"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
+msgid "Resolve thread"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Resolved 1 discussion."
+msgstr ""
+
+msgid "Resolved all discussions."
+msgstr ""
+
+msgid "Resolved by"
+msgstr ""
+
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response didn't include `service_desk_address`"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Response text"
+msgstr ""
+
+msgid "Restart GitLab to apply changes."
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Restore"
+msgstr ""
+
+msgid "Restore group"
+msgstr ""
+
+msgid "Restore project"
+msgstr ""
+
+msgid "Restoring projects"
+msgstr ""
+
+msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
+msgstr ""
+
+msgid "Restoring the project will prevent the project from being removed on this date and restore people's ability to make changes to it."
+msgstr ""
+
+msgid "Restrict access by IP address"
+msgstr ""
+
+msgid "Restrict membership by email domain"
+msgstr ""
+
+msgid "Restrict projects for this runner"
+msgstr ""
+
+msgid "Restricted shift times are not available for hourly shifts"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Resync"
+msgstr ""
+
+msgid "Retrieving the compliance report failed. Refresh the page and try again."
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry all failed or cancelled jobs"
+msgstr ""
+
+msgid "Retry downstream pipeline"
+msgstr ""
+
+msgid "Retry job"
+msgstr ""
+
+msgid "Retry migration"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry this job in order to create the necessary resources."
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review App|View app"
+msgstr ""
+
+msgid "Review App|View latest app"
+msgstr ""
+
+msgid "Review changes"
+msgstr ""
+
+msgid "Review requests for you"
+msgstr ""
+
+msgid "Review the changes locally."
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
+msgid "Review time"
+msgstr ""
+
+msgid "Review time is defined as the time it takes from first comment until merged."
+msgstr ""
+
+msgid "ReviewApp|Enable Review App"
+msgstr ""
+
+msgid "Reviewer"
+msgid_plural "%d Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reviewer(s)"
+msgstr ""
+
+msgid "Reviewers"
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoked"
+msgstr ""
+
+msgid "Revoked access token %{access_token_name}!"
+msgstr ""
+
+msgid "Revoked impersonation token %{token_name}!"
+msgstr ""
+
+msgid "Revoked personal access token %{personal_access_token_name}!"
+msgstr ""
+
+msgid "Rich text"
+msgstr ""
+
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Roadmap settings"
+msgstr ""
+
+msgid "Roadmap view"
+msgstr ""
+
+msgid "Role"
+msgstr ""
+
+msgid "Rollback"
+msgstr ""
+
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
+msgid "Ruby"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
+msgstr ""
+
+msgid "Run %{code_start}git fsck%{code_end} periodically in all project and wiki repositories to look for silent disk corruption issues."
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}"
+msgstr ""
+
+msgid "Run CI/CD pipelines with Jenkins."
+msgstr ""
+
+msgid "Run housekeeping"
+msgstr ""
+
+msgid "Run manual or delayed jobs"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner"
+msgstr ""
+
+msgid "Runner API"
+msgstr ""
+
+msgid "Runner tokens"
+msgstr ""
+
+msgid "Runner was not updated."
+msgstr ""
+
+msgid "Runner was successfully updated."
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|%{percentage} spot."
+msgstr ""
+
+msgid "Runners|%{strongStart}%{count}%{strongEnd} runner selected"
+msgid_plural "Runners|%{strongStart}%{count}%{strongEnd} runners selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|%{strongStart}%{count}%{strongEnd} runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
+msgid_plural "Runners|%{strongStart}%{count}%{strongEnd} runners will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|A capacity of 1 enables warm HA through Auto Scaling group re-spawn. A capacity of 2 enables hot HA because the service is available even when a node is lost. A capacity of 3 or more enables hot HA and manual scaling of runner fleet."
+msgstr ""
+
+msgid "Runners|A new version is available"
+msgstr ""
+
+msgid "Runners|A periodic background task deletes runners that haven't contacted GitLab in more than %{elapsedTime}. %{linkStart}Can I view how many runners were deleted?%{linkEnd}"
+msgstr ""
+
+msgid "Runners|Active"
+msgstr ""
+
+msgid "Runners|Add notes, like who owns the runner or what it should be used for."
+msgstr ""
+
+msgid "Runners|Add your feedback in the issue"
+msgstr ""
+
+msgid "Runners|All"
+msgstr ""
+
+msgid "Runners|All group runners that have not contacted GitLab in more than %{elapsedTime} are deleted permanently. This task runs periodically in the background."
+msgstr ""
+
+msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
+msgstr ""
+
+msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot."
+msgstr ""
+
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
+msgid "Runners|An upgrade is available for this runner"
+msgstr ""
+
+msgid "Runners|An upgrade is recommended for this runner"
+msgstr ""
+
+msgid "Runners|Architecture"
+msgstr ""
+
+msgid "Runners|Assigned Group"
+msgstr ""
+
+msgid "Runners|Assigned Projects (%{projectCount})"
+msgstr ""
+
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Capacity of 1 enables warm HA through Auto Scaling group re-spawn. Capacity of 2 enables hot HA because the service is available even when a node is lost. Capacity of 3 or more enables hot HA and manual scaling of runner fleet."
+msgstr ""
+
+msgid "Runners|Checkbox"
+msgstr ""
+
+msgid "Runners|Choose your preferred GitLab Runner"
+msgstr ""
+
+msgid "Runners|Clear selection"
+msgstr ""
+
+msgid "Runners|Command to register runner"
+msgstr ""
+
+msgid "Runners|Configuration"
+msgstr ""
+
+msgid "Runners|Copy instructions"
+msgstr ""
+
+msgid "Runners|Copy registration token"
+msgstr ""
+
+msgid "Runners|Created %{timeAgo}"
+msgstr ""
+
+msgid "Runners|Delete %d runner"
+msgid_plural "Runners|Delete %d runners"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|Delete runner"
+msgstr ""
+
+msgid "Runners|Delete runner %{name}?"
+msgstr ""
+
+msgid "Runners|Delete selected"
+msgstr ""
+
+msgid "Runners|Deploy GitLab Runner in AWS"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Details"
+msgstr ""
+
+msgid "Runners|Don't see what you are looking for? See the full list of options, including a fully customizable option %{linkStart}here%{linkEnd}."
+msgstr ""
+
+msgid "Runners|Download and install binary"
+msgstr ""
+
+msgid "Runners|Download latest binary"
+msgstr ""
+
+msgid "Runners|Edit your search and try again"
+msgstr ""
+
+msgid "Runners|Enable stale runner cleanup"
+msgstr ""
+
+msgid "Runners|Enable stale runner cleanup?"
+msgstr ""
+
+msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
+msgid "Runners|Executor"
+msgstr ""
+
+msgid "Runners|Filter projects"
+msgstr ""
+
+msgid "Runners|Get started with runners"
+msgstr ""
+
+msgid "Runners|Group"
+msgstr ""
+
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
+msgid "Runners|How do we upgrade GitLab runner?"
+msgstr ""
+
+msgid "Runners|IP Address"
+msgstr ""
+
+msgid "Runners|Install a runner"
+msgstr ""
+
+msgid "Runners|Instance"
+msgstr ""
+
+msgid "Runners|Jobs"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Last contact: %{timeAgo}"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maintenance note"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Members of the %{type} can register runners"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Never contacted"
+msgstr ""
+
+msgid "Runners|Never contacted:"
+msgstr ""
+
+msgid "Runners|Never expires"
+msgstr ""
+
+msgid "Runners|New group runners view"
+msgstr ""
+
+msgid "Runners|New registration token generated!"
+msgstr ""
+
+msgid "Runners|No results found"
+msgstr ""
+
+msgid "Runners|No spot. Default choice for Windows Shell executor."
+msgstr ""
+
+msgid "Runners|No spot. This is the default choice for Linux Docker executor."
+msgstr ""
+
+msgid "Runners|Not accepting jobs"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Offline:"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Online:"
+msgstr ""
+
+msgid "Runners|Pause from accepting jobs"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
+msgid "Runners|Permanently delete %d runner"
+msgid_plural "Runners|Permanently delete %d runners"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Project"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Recommended"
+msgstr ""
+
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
+msgid "Runners|Reset token"
+msgstr ""
+
+msgid "Runners|Resume accepting jobs"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Runner"
+msgstr ""
+
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
+msgid "Runners|Runner %{name} was deleted"
+msgstr ""
+
+msgid "Runners|Runner assigned to project."
+msgstr ""
+
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
+msgstr ""
+
+msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
+msgstr ""
+
+msgid "Runners|Runner has never contacted GitLab (when you register a runner, use %{codeStart}gitlab-runner run%{codeEnd} to bring it online)"
+msgstr ""
+
+msgid "Runners|Runner has never contacted this instance"
+msgstr ""
+
+msgid "Runners|Runner has not contacted GitLab in more than %{elapsedTime}"
+msgstr ""
+
+msgid "Runners|Runner is locked and available for currently assigned projects only. Only administrators can change the assigned projects."
+msgstr ""
+
+msgid "Runners|Runner is offline; last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is offline; last contact was %{timeAgo}"
+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 stale; it has never contacted this instance"
+msgstr ""
+
+msgid "Runners|Runner is stale; last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is stale; last contact was %{timeAgo}"
+msgstr ""
+
+msgid "Runners|Runner registration"
+msgstr ""
+
+msgid "Runners|Runner statuses"
+msgstr ""
+
+msgid "Runners|Runner unassigned from project."
+msgstr ""
+
+msgid "Runners|Runners"
+msgstr ""
+
+msgid "Runners|Runners are either:"
+msgstr ""
+
+msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
+msgstr ""
+
+msgid "Runners|Runs untagged jobs"
+msgstr ""
+
+msgid "Runners|Select projects to assign to this runner"
+msgstr ""
+
+msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
+msgstr ""
+
+msgid "Runners|Show only inherited"
+msgstr ""
+
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
+msgid "Runners|Show runner installation instructions"
+msgstr ""
+
+msgid "Runners|Something went wrong while deleting. Please refresh the page to try again."
+msgstr ""
+
+msgid "Runners|Something went wrong while fetching runner data."
+msgstr ""
+
+msgid "Runners|Something went wrong while fetching the tags suggestions"
+msgstr ""
+
+msgid "Runners|Stale"
+msgstr ""
+
+msgid "Runners|Stale:"
+msgstr ""
+
+msgid "Runners|Status"
+msgstr ""
+
+msgid "Runners|Stop the runner from accepting new jobs."
+msgstr ""
+
+msgid "Runners|Tags"
+msgstr ""
+
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
+msgid "Runners|Take me there!"
+msgstr ""
+
+msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
+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 group currently has 1 stale runner."
+msgid_plural "Runners|This group currently has %d stale runners."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|This group currently has no stale runners."
+msgstr ""
+
+msgid "Runners|This runner has not run any jobs."
+msgstr ""
+
+msgid "Runners|This runner is associated with specific projects."
+msgstr ""
+
+msgid "Runners|This runner is available to all projects and subgroups in a group."
+msgstr ""
+
+msgid "Runners|This runner is outdated, an upgrade is recommended"
+msgstr ""
+
+msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
+msgstr ""
+
+msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
+msgstr ""
+
+msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
+msgstr ""
+
+msgid "Runners|Token expiry"
+msgstr ""
+
+msgid "Runners|Up to date"
+msgstr ""
+
+msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
+msgstr ""
+
+msgid "Runners|Upgrade Status"
+msgstr ""
+
+msgid "Runners|Upgrade available"
+msgstr ""
+
+msgid "Runners|Upgrade recommended"
+msgstr ""
+
+msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
+msgstr ""
+
+msgid "Runners|Use the runner for jobs without tags, in addition to tagged jobs."
+msgstr ""
+
+msgid "Runners|Use the runner for the currently assigned projects only. Only administrators can change the assigned projects."
+msgstr ""
+
+msgid "Runners|Use the runner on pipelines for protected branches only."
+msgstr ""
+
+msgid "Runners|Value"
+msgstr ""
+
+msgid "Runners|Version"
+msgstr ""
+
+msgid "Runners|Version %{version}"
+msgstr ""
+
+msgid "Runners|View installation instructions"
+msgstr ""
+
+msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
+msgstr ""
+
+msgid "Runners|We've made some changes and want your feedback"
+msgstr ""
+
+msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
+msgstr ""
+
+msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot."
+msgstr ""
+
+msgid "Runners|Yes, start deleting stale runners"
+msgstr ""
+
+msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
+msgstr ""
+
+msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Runners|active"
+msgstr ""
+
+msgid "Runners|group"
+msgstr ""
+
+msgid "Runners|paused"
+msgstr ""
+
+msgid "Runners|shared"
+msgstr ""
+
+msgid "Runners|specific"
+msgstr ""
+
+msgid "Runner|Owner"
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
+msgstr ""
+
+msgid "SAML"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML discovery tokens"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
+msgstr ""
+
+msgid "SAML|Sign in to GitLab to connect your organization's account"
+msgstr ""
+
+msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
+msgstr ""
+
+msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
+msgstr ""
+
+msgid "SAML|Your organization's SSO has been connected to your GitLab account"
+msgstr ""
+
+msgid "SAST Configuration"
+msgstr ""
+
+msgid "SHA256"
+msgstr ""
+
+msgid "SSH Fingerprints"
+msgstr ""
+
+msgid "SSH Key"
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH Keys Help"
+msgstr ""
+
+msgid "SSH fingerprints verify that the client is connecting to the correct host. Check the %{config_link_start}current instance configuration%{config_link_end}."
+msgstr ""
+
+msgid "SSH host key fingerprints"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
+msgstr ""
+
+msgid "SSH key"
+msgstr ""
+
+msgid "SSH keys"
+msgstr ""
+
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
+msgid "SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:"
+msgstr ""
+
+msgid "SSH keys with the following fingerprints have expired and can no longer be used:"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification:"
+msgstr ""
+
+msgid "SSL verification"
+msgstr ""
+
+msgid "Sat"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save %{name} size limits"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save deploy freeze"
+msgstr ""
+
+msgid "Save internal note"
+msgstr ""
+
+msgid "Save password"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
+msgstr ""
+
+msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
+msgstr ""
+
+msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Scanner profile"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select scanner profile"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select site profile"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Site profile"
+msgstr ""
+
+msgid "ScanExecutionPolicy|branch"
+msgstr ""
+
+msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
+msgstr ""
+
+msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval from %{approvalsRequired} of the following approvers:"
+msgstr ""
+
+msgid "ScanResultPolicy|add an approver"
+msgstr ""
+
+msgid "ScanResultPolicy|scanners"
+msgstr ""
+
+msgid "ScanResultPolicy|severity levels"
+msgstr ""
+
+msgid "ScanResultPolicy|vulnerability states"
+msgstr ""
+
+msgid "Scanner"
+msgstr ""
+
+msgid "Scanner profile failed to delete"
+msgstr ""
+
+msgid "Scanner profile not found for given parameters"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Schedule-based escalation rules must have a schedule in the same project as the policy"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+msgstr ""
+
+msgid "Scheduled a rebase of branch %{branch}."
+msgstr ""
+
+msgid "Scheduled pipelines cannot run more frequently than once per %{limit} minutes. A pipeline configured to run more frequently only starts after %{limit} minutes have elapsed since the last time it ran."
+msgstr ""
+
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Schedules to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scope board to current iteration"
+msgstr ""
+
+msgid "Scopes"
+msgstr ""
+
+msgid "Scopes (select at least one)"
+msgstr ""
+
+msgid "Scopes can't be blank"
+msgstr ""
+
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
+msgid "Scroll down"
+msgstr ""
+
+msgid "Scroll left"
+msgstr ""
+
+msgid "Scroll right"
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Scroll up"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search GitLab"
+msgstr ""
+
+msgid "Search a group"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search assignees"
+msgstr ""
+
+msgid "Search authors"
+msgstr ""
+
+msgid "Search branch"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search branches, tags, and commits"
+msgstr ""
+
+msgid "Search by Git revision"
+msgstr ""
+
+msgid "Search by author"
+msgstr ""
+
+msgid "Search by commit title or SHA"
+msgstr ""
+
+msgid "Search by message"
+msgstr ""
+
+msgid "Search by name"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for Namespace"
+msgstr ""
+
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
+msgid "Search for an emoji"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search for this text"
+msgstr ""
+
+msgid "Search forks"
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search iterations"
+msgstr ""
+
+msgid "Search labels"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or create tag"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search page"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search projects..."
+msgstr ""
+
+msgid "Search protected branches"
+msgstr ""
+
+msgid "Search rate limits"
+msgstr ""
+
+msgid "Search refs"
+msgstr ""
+
+msgid "Search requirements"
+msgstr ""
+
+msgid "Search settings"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search users or groups"
+msgstr ""
+
+msgid "Search your project dependencies for their licenses and apply policies."
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in group %{groupName}"
+msgstr ""
+
+msgid "SearchAutocomplete|in project %{projectName}"
+msgstr ""
+
+msgid "SearchCodeResults|of %{link_to_project}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for %{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|code result"
+msgid_plural "SearchResults|code results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|comment"
+msgid_plural "SearchResults|comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|commit"
+msgid_plural "SearchResults|commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|epic"
+msgid_plural "SearchResults|epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|issue"
+msgid_plural "SearchResults|issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|merge request"
+msgid_plural "SearchResults|merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|milestone"
+msgid_plural "SearchResults|milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|project"
+msgid_plural "SearchResults|projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|snippet"
+msgid_plural "SearchResults|snippets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|user"
+msgid_plural "SearchResults|users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|wiki result"
+msgid_plural "SearchResults|wiki results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
+msgid "Searching by both author and message is currently not supported."
+msgstr ""
+
+msgid "Seats"
+msgstr ""
+
+msgid "Seats owed"
+msgstr ""
+
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
+msgstr ""
+
+msgid "Seats usage data is updated every day at 12:00pm UTC"
+msgstr ""
+
+msgid "Secondary email:"
+msgstr ""
+
+msgid "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "Secret token"
+msgstr ""
+
+msgid "Secure Code Warrior"
+msgstr ""
+
+msgid "Secure Files"
+msgstr ""
+
+msgid "Secure token that identifies an external storage request."
+msgstr ""
+
+msgid "SecureFiles|Delete %{name}?"
+msgstr ""
+
+msgid "SecureFiles|Delete secure file"
+msgstr ""
+
+msgid "SecureFiles|Secure File %{name} will be permanently deleted. Are you sure?"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security & Compliance"
+msgstr ""
+
+msgid "Security Configuration"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Finding not found"
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "Security navigation"
+msgstr ""
+
+msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "SecurityApprovals|A merge request approval is required when test coverage declines."
+msgstr ""
+
+msgid "SecurityApprovals|A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
+
+msgid "SecurityApprovals|Coverage-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Learn more about Coverage-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Learn more about License-Check"
+msgstr ""
+
+msgid "SecurityApprovals|License-Check"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
+msgid "SecurityConfiguration|%{scanType} configuration code snippet"
+msgstr ""
+
+msgid "SecurityConfiguration|An error occurred while creating the merge request."
+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|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration history"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure %{feature}"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure with a merge request"
+msgstr ""
+
+msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
+msgstr ""
+
+msgid "SecurityConfiguration|Copy code only"
+msgstr ""
+
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create merge request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable Auto DevOps"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups"
+msgstr ""
+
+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 ""
+
+msgid "SecurityConfiguration|Learn more about vulnerability training"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage corpus"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage corpus files used as seed inputs with coverage-guided fuzzing."
+msgstr ""
+
+msgid "SecurityConfiguration|Manage profiles"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
+msgstr ""
+
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Not enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
+msgstr ""
+
+msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|Runtime security metrics for application environments"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Analyzers"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
+msgid "SecurityConfiguration|Secure your project"
+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 ""
+
+msgid "SecurityConfiguration|Upgrade or start a free trial"
+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 ""
+
+msgid "SecurityOrchestration| and "
+msgstr ""
+
+msgid "SecurityOrchestration| or "
+msgstr ""
+
+msgid "SecurityOrchestration|%{branches} %{plural}"
+msgstr ""
+
+msgid "SecurityOrchestration|%{branches} and %{lastBranch} %{plural}"
+msgstr ""
+
+msgid "SecurityOrchestration|%{scanners}"
+msgstr ""
+
+msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
+msgstr ""
+
+msgid "SecurityOrchestration|, and %{count} more"
+msgstr ""
+
+msgid "SecurityOrchestration|.yaml mode"
+msgstr ""
+
+msgid "SecurityOrchestration|.yaml preview"
+msgstr ""
+
+msgid "SecurityOrchestration|Actions"
+msgstr ""
+
+msgid "SecurityOrchestration|Add action"
+msgstr ""
+
+msgid "SecurityOrchestration|Add rule"
+msgstr ""
+
+msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again."
+msgstr ""
+
+msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group."
+msgstr ""
+
+msgid "SecurityOrchestration|All policies"
+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|An error occurred while fetching the scan result policies."
+msgstr ""
+
+msgid "SecurityOrchestration|Any scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|Are you sure you want to delete this policy? This action cannot be undone."
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
+msgid "SecurityOrchestration|Create more robust vulnerability rules and apply them to all your projects."
+msgstr ""
+
+msgid "SecurityOrchestration|Create policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Create security policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Define this policy's location, conditions and actions."
+msgstr ""
+
+msgid "SecurityOrchestration|Delete policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Delete policy: %{policy}"
+msgstr ""
+
+msgid "SecurityOrchestration|Description"
+msgstr ""
+
+msgid "SecurityOrchestration|Direct"
+msgstr ""
+
+msgid "SecurityOrchestration|Don't show the alert anymore"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit scan execution policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Edit scan result policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Empty policy name"
+msgstr ""
+
+msgid "SecurityOrchestration|Enabled"
+msgstr ""
+
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityOrchestration|Failed to load cluster agents."
+msgstr ""
+
+msgid "SecurityOrchestration|Failed to load images."
+msgstr ""
+
+msgid "SecurityOrchestration|Failed to load vulnerability scanners."
+msgstr ""
+
+msgid "SecurityOrchestration|If any scanner finds a newly detected critical vulnerability in an open merge request targeting the master branch, then require two approvals from any member of App security."
+msgstr ""
+
+msgid "SecurityOrchestration|Inherited"
+msgstr ""
+
+msgid "SecurityOrchestration|Inherited from %{namespace}"
+msgstr ""
+
+msgid "SecurityOrchestration|Invalid policy type"
+msgstr ""
+
+msgid "SecurityOrchestration|Latest scan run against %{agent}"
+msgstr ""
+
+msgid "SecurityOrchestration|New policy"
+msgstr ""
+
+msgid "SecurityOrchestration|New scan execution policy"
+msgstr ""
+
+msgid "SecurityOrchestration|New scan result policy"
+msgstr ""
+
+msgid "SecurityOrchestration|No actions defined - policy will not run."
+msgstr ""
+
+msgid "SecurityOrchestration|No description"
+msgstr ""
+
+msgid "SecurityOrchestration|No rules defined - policy will not run."
+msgstr ""
+
+msgid "SecurityOrchestration|Not enabled"
+msgstr ""
+
+msgid "SecurityOrchestration|Only owners can update Security Policy Project"
+msgstr ""
+
+msgid "SecurityOrchestration|Policies"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy Type"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy definition"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy editor"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy status"
+msgstr ""
+
+msgid "SecurityOrchestration|Policy type"
+msgstr ""
+
+msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
+msgstr ""
+
+msgid "SecurityOrchestration|Rule mode"
+msgstr ""
+
+msgid "SecurityOrchestration|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
+msgid "SecurityOrchestration|Rules"
+msgstr ""
+
+msgid "SecurityOrchestration|Run a DAST scan with Scan Profile A and Site Profile A when a pipeline run against the main branch."
+msgstr ""
+
+msgid "SecurityOrchestration|Runs %{actions} and %{lastAction} scans"
+msgstr ""
+
+msgid "SecurityOrchestration|Runs a %{action} scan"
+msgstr ""
+
+msgid "SecurityOrchestration|Save changes"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan Execution"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan Result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan execution"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
+msgid "SecurityOrchestration|Scan execution policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
+msgstr ""
+
+msgid "SecurityOrchestration|Scan result policy"
+msgstr ""
+
+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 ""
+
+msgid "SecurityOrchestration|Security Approvals"
+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 ""
+
+msgid "SecurityOrchestration|Select policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Select security project"
+msgstr ""
+
+msgid "SecurityOrchestration|Something went wrong, unable to fetch policies"
+msgstr ""
+
+msgid "SecurityOrchestration|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "SecurityOrchestration|Source"
+msgstr ""
+
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
+msgid "SecurityOrchestration|Step 1: Choose a policy type"
+msgstr ""
+
+msgid "SecurityOrchestration|Step 2: Policy details"
+msgstr ""
+
+msgid "SecurityOrchestration|Summary"
+msgstr ""
+
+msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all branches to ensure the values are accurate before updating this policy."
+msgstr ""
+
+msgid "SecurityOrchestration|There was a problem creating the new security policy"
+msgstr ""
+
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr ""
+
+msgid "SecurityOrchestration|This %{namespaceType} is not linked to a security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|This group"
+msgstr ""
+
+msgid "SecurityOrchestration|This is a group-level policy"
+msgstr ""
+
+msgid "SecurityOrchestration|This is a project-level policy"
+msgstr ""
+
+msgid "SecurityOrchestration|This policy is inherited from %{namespace}"
+msgstr ""
+
+msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
+msgstr ""
+
+msgid "SecurityOrchestration|This project"
+msgstr ""
+
+msgid "SecurityOrchestration|This view only shows scan results for the agent %{agent}. You can view scan results for all agents in the %{linkStart}Operational Vulnerabilities tab of the vulnerability report%{linkEnd}."
+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 policies"
+msgstr ""
+
+msgid "SecurityOrchestration|Use a scan execution policy to create rules which enforce security scans for particular branches at a certain time. Supported types are SAST, DAST, Secret detection, and Container scanning."
+msgstr ""
+
+msgid "SecurityOrchestration|Use a scan result policy to create rules that ensure security issues are checked before merging a merge request."
+msgstr ""
+
+msgid "SecurityOrchestration|View policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|You don't have any security policies yet"
+msgstr ""
+
+msgid "SecurityOrchestration|a"
+msgstr ""
+
+msgid "SecurityOrchestration|all branches"
+msgstr ""
+
+msgid "SecurityOrchestration|an"
+msgstr ""
+
+msgid "SecurityOrchestration|branch"
+msgstr ""
+
+msgid "SecurityOrchestration|branches"
+msgstr ""
+
+msgid "SecurityOrchestration|scanner finds"
+msgstr ""
+
+msgid "SecurityOrchestration|scanners find"
+msgstr ""
+
+msgid "SecurityOrchestration|the %{branches}"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerabilities"
+msgstr ""
+
+msgid "SecurityOrchestration|vulnerability"
+msgstr ""
+
+msgid "SecurityReports|%{count} Selected"
+msgstr ""
+
+msgid "SecurityReports|%{count}+ projects"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
+
+msgid "SecurityReports|Add projects"
+msgstr ""
+
+msgid "SecurityReports|All activity"
+msgstr ""
+
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "SecurityReports|At GitLab, we're all about iteration and feedback. That's why we are reaching out to customers like you to help guide what we work on this year for Vulnerability Management. We have a lot of exciting ideas and ask that you assist us by taking a short survey %{boldStart}no longer than 10 minutes%{boldEnd} to evaluate a few of our potential features."
+msgstr ""
+
+msgid "SecurityReports|Change status"
+msgstr ""
+
+msgid "SecurityReports|Check the messages generated while parsing the following security reports, as they may prevent the results from being ingested by GitLab. Ensure the security report conforms to a supported %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
+msgstr ""
+
+msgid "SecurityReports|Cluster"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
+msgid "SecurityReports|Create Jira issue"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Detection"
+msgstr ""
+
+msgid "SecurityReports|Development vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Dismiss vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr ""
+
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
+msgid "SecurityReports|Download %{artifactName}"
+msgstr ""
+
+msgid "SecurityReports|Download results"
+msgstr ""
+
+msgid "SecurityReports|Download scanned URLs"
+msgstr ""
+
+msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
+msgstr ""
+
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerabilities over time. Please check your network connection and try again."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "SecurityReports|Error parsing security reports"
+msgstr ""
+
+msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
+msgid "SecurityReports|Has issue"
+msgstr ""
+
+msgid "SecurityReports|Hide dismissed"
+msgstr ""
+
+msgid "SecurityReports|Image"
+msgstr ""
+
+msgid "SecurityReports|Issue"
+msgstr ""
+
+msgid "SecurityReports|Issue Created"
+msgstr ""
+
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
+msgid "SecurityReports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Maximum selected projects limit reached"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|No activity"
+msgstr ""
+
+msgid "SecurityReports|No longer detected"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found for this pipeline"
+msgstr ""
+
+msgid "SecurityReports|Oops, something doesn't seem right."
+msgstr ""
+
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Parsing errors and warnings in pipeline"
+msgstr ""
+
+msgid "SecurityReports|Parsing errors in pipeline"
+msgstr ""
+
+msgid "SecurityReports|Parsing warnings in pipeline"
+msgstr ""
+
+msgid "SecurityReports|Project"
+msgstr ""
+
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "SecurityReports|Projects added"
+msgstr ""
+
+msgid "SecurityReports|Remove project from dashboard"
+msgstr ""
+
+msgid "SecurityReports|Report has expired"
+msgstr ""
+
+msgid "SecurityReports|Results show vulnerabilities introduced by the merge request, in addition to existing vulnerabilities from the latest successful pipeline in your project's default branch."
+msgstr ""
+
+msgid "SecurityReports|Scan details"
+msgstr ""
+
+msgid "SecurityReports|Security Dashboard"
+msgstr ""
+
+msgid "SecurityReports|Security reports can only be accessed by authorized users."
+msgstr ""
+
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run"
+msgstr ""
+
+msgid "SecurityReports|Select a project to add by using the project search field above."
+msgstr ""
+
+msgid "SecurityReports|Set status"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Show %{pageSize} items"
+msgstr ""
+
+msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|Still detected"
+msgstr ""
+
+msgid "SecurityReports|Submit vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Take survey"
+msgstr ""
+
+msgid "SecurityReports|The Vulnerability Report shows results of successful scans on your project's default branch, manually added vulnerability records, and vulnerabilities found from scanning operational environments. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityReports|The following security reports contain one or more vulnerability findings that could not be parsed and were not recorded. To investigate a report, download the artifacts in the job output. Ensure the security report conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
+msgstr ""
+
+msgid "SecurityReports|The security report for this pipeline has %{helpPageLinkStart}expired%{helpPageLinkEnd}. Re-run the pipeline to generate a new security report."
+msgstr ""
+
+msgid "SecurityReports|There was an error adding the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the issue."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the merge request."
+msgstr ""
+
+msgid "SecurityReports|There was an error deleting the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error while generating the report."
+msgstr ""
+
+msgid "SecurityReports|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 ""
+
+msgid "SecurityReports|Tool"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
+
+msgid "SecurityReports|Undo dismiss"
+msgstr ""
+
+msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
+msgstr ""
+
+msgid "SecurityReports|Upgrade to manage vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Management feature survey"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Report"
+msgstr ""
+
+msgid "SecurityReports|Warning parsing security reports"
+msgstr ""
+
+msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
+msgstr ""
+
+msgid "SecurityReports|With issues"
+msgstr ""
+
+msgid "SecurityReports|You do not have sufficient permissions to access this report"
+msgstr ""
+
+msgid "SecurityReports|You must sign in as an authorized user to see this report"
+msgstr ""
+
+msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
+msgstr ""
+
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
+msgid "SecurityTraining|Primary Training"
+msgstr ""
+
+msgid "SecurityTraining|Training from this partner takes precedence when more than one training partner is enabled."
+msgstr ""
+
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See our website for help"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select Git revision"
+msgstr ""
+
+msgid "Select Profile"
+msgstr ""
+
+msgid "Select a branch"
+msgstr ""
+
+msgid "Select a branch to compare"
+msgstr ""
+
+msgid "Select a color"
+msgstr ""
+
+msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Select a label"
+msgstr ""
+
+msgid "Select a milestone"
+msgstr ""
+
+msgid "Select a new namespace"
+msgstr ""
+
+msgid "Select a project"
+msgstr ""
+
+msgid "Select a reason"
+msgstr ""
+
+msgid "Select a repository containing templates for common files."
+msgstr ""
+
+msgid "Select a role"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a template type"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select all"
+msgstr ""
+
+msgid "Select an assignee"
+msgstr ""
+
+msgid "Select an iteration"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select assignee(s)"
+msgstr ""
+
+msgid "Select branch"
+msgstr ""
+
+msgid "Select branch or create wildcard"
+msgstr ""
+
+msgid "Select branches"
+msgstr ""
+
+msgid "Select default branch"
+msgstr ""
+
+msgid "Select due date"
+msgstr ""
+
+msgid "Select epic"
+msgstr ""
+
+msgid "Select group"
+msgstr ""
+
+msgid "Select group or project"
+msgstr ""
+
+msgid "Select health status"
+msgstr ""
+
+msgid "Select iteration"
+msgstr ""
+
+msgid "Select label"
+msgstr ""
+
+msgid "Select labels"
+msgstr ""
+
+msgid "Select merge moment"
+msgstr ""
+
+msgid "Select milestone"
+msgstr ""
+
+msgid "Select private project"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project to create %{type}"
+msgstr ""
+
+msgid "Select project to create issue"
+msgstr ""
+
+msgid "Select projects"
+msgstr ""
+
+msgid "Select report"
+msgstr ""
+
+msgid "Select reviewer(s)"
+msgstr ""
+
+msgid "Select source"
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select source project"
+msgstr ""
+
+msgid "Select start date"
+msgstr ""
+
+msgid "Select status"
+msgstr ""
+
+msgid "Select strategy activation method"
+msgstr ""
+
+msgid "Select subgroup"
+msgstr ""
+
+msgid "Select subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select target branch or tag"
+msgstr ""
+
+msgid "Select target project"
+msgstr ""
+
+msgid "Select timezone"
+msgstr ""
+
+msgid "Select type"
+msgstr ""
+
+msgid "Selected"
+msgstr ""
+
+msgid "Selected commits"
+msgstr ""
+
+msgid "Selected for all items."
+msgstr ""
+
+msgid "Selected for some items."
+msgstr ""
+
+msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
+msgstr ""
+
+msgid "Selected tag is already in use. Choose another option."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Self monitoring"
+msgstr ""
+
+msgid "Self monitoring project does not exist"
+msgstr ""
+
+msgid "Self-monitoring project does not exist. Please check logs for any error messages"
+msgstr ""
+
+msgid "Self-monitoring project has been successfully deleted"
+msgstr ""
+
+msgid "Self-monitoring project was not deleted. Please check logs for any error messages"
+msgstr ""
+
+msgid "SelfMonitoring|Activate or deactivate instance self monitoring."
+msgstr ""
+
+msgid "SelfMonitoring|Activate self monitoring to create a project to use to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Deactivate self monitoring?"
+msgstr ""
+
+msgid "SelfMonitoring|Deactivating self monitoring deletes the self monitoring project. Are you sure you want to deactivate self monitoring and delete the project?"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring is active. Use the %{projectLinkStart}self monitoring project%{projectLinkEnd} to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project successfully created."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project successfully deleted."
+msgstr ""
+
+msgid "Send"
+msgstr ""
+
+msgid "Send a single email notification to Owners and Maintainers for new alerts."
+msgstr ""
+
+msgid "Send confirmation email"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send email in multipart format (HTML and plain text). Uncheck to send email messages in plain text only."
+msgstr ""
+
+msgid "Send email notification"
+msgstr ""
+
+msgid "Send emails to help guide new users through the onboarding process."
+msgstr ""
+
+msgid "Send emails to users upon account deactivation."
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Send notifications about project events to Mattermost channels."
+msgstr ""
+
+msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
+msgstr ""
+
+msgid "Send notifications about project events to a Discord channel. %{docs_link}"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send service data"
+msgstr ""
+
+msgid "Sentry"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sentry event"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "SeriesFinalConjunction|and"
+msgstr ""
+
+msgid "Serve repository static objects (for example, archives and blobs) from external storage."
+msgstr ""
+
+msgid "Server (optional)"
+msgstr ""
+
+msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
+msgid "Service Ping payload not found in the application cache"
+msgstr ""
+
+msgid "Service account generated successfully"
+msgstr ""
+
+msgid "Service accounts"
+msgstr ""
+
+msgid "Service usage data"
+msgstr ""
+
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
+msgid "ServicePing|Service ping is off"
+msgstr ""
+
+msgid "ServicePing|To view instance-level analytics, ask an admin to turn on %{docLinkStart}service ping%{docLinkEnd}."
+msgstr ""
+
+msgid "ServicePing|Turn on service ping"
+msgstr ""
+
+msgid "ServicePing|Turn on service ping to review instance-level analytics."
+msgstr ""
+
+msgid "Session ID"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
+msgstr ""
+
+msgid "Set due date"
+msgstr ""
+
+msgid "Set health status"
+msgstr ""
+
+msgid "Set health status to %{health_status}."
+msgstr ""
+
+msgid "Set iteration"
+msgstr ""
+
+msgid "Set limit to 0 to allow any file size."
+msgstr ""
+
+msgid "Set limits for web and API requests."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set per-user rate limits for imports and exports of projects and groups."
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set rate limits for package registry API requests that supersede the general user and IP rate limits."
+msgstr ""
+
+msgid "Set rate limits for searches performed by web or API requests."
+msgstr ""
+
+msgid "Set severity"
+msgstr ""
+
+msgid "Set sign-in restrictions for all users."
+msgstr ""
+
+msgid "Set size limits for displaying diffs in the browser."
+msgstr ""
+
+msgid "Set target branch"
+msgstr ""
+
+msgid "Set target branch to %{branch_name}."
+msgstr ""
+
+msgid "Set the Draft status"
+msgstr ""
+
+msgid "Set the Ready status"
+msgstr ""
+
+msgid "Set the default branch for this project. All merge requests and commits are made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Set the default expiration time for job artifacts in all projects. Set to %{code_open}0%{code_close} to never expire artifacts by default. If no unit is written, it defaults to seconds. For example, these are all equivalent: %{code_open}3600%{code_close}, %{code_open}60 minutes%{code_close}, or %{code_open}one hour%{code_close}."
+msgstr ""
+
+msgid "Set the due date to %{due_date}."
+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 ""
+
+msgid "Set the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Set the per-user rate limit for getting a user by ID via the API."
+msgstr ""
+
+msgid "Set the per-user rate limit for notes created by web or API requests."
+msgstr ""
+
+msgid "Set this number to 0 to disable the limit."
+msgstr ""
+
+msgid "Set time estimate"
+msgstr ""
+
+msgid "Set time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Set to 0 for no size limit."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up Jira Integration"
+msgstr ""
+
+msgid "Set up a %{type} runner for a project"
+msgstr ""
+
+msgid "Set up a hardware device as a second factor to sign in."
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new device"
+msgstr ""
+
+msgid "Set up new password"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "Set visibility of project contents. Configure import sources and Git access protocols."
+msgstr ""
+
+msgid "Set weight"
+msgstr ""
+
+msgid "Set weight to %{weight}."
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|Status updated"
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
+msgid "Sets %{epic_ref} as parent epic."
+msgstr ""
+
+msgid "Sets health status to %{health_status}."
+msgstr ""
+
+msgid "Sets target branch to %{branch_name}."
+msgstr ""
+
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets the severity"
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
+msgid "Setting"
+msgstr ""
+
+msgid "Setting enforced"
+msgstr ""
+
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
+msgstr ""
+
+msgid "Setup"
+msgstr ""
+
+msgid "Severity"
+msgstr ""
+
+msgid "Severity updated to %{severity}."
+msgstr ""
+
+msgid "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners are disabled on group level"
+msgstr ""
+
+msgid "Shared runners details"
+msgstr ""
+
+msgid "Shared runners enabled cannot be enabled until a valid credit card is on file"
+msgstr ""
+
+msgid "Shared runners help link"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "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 ""
+
+msgid "Show Pipeline IID"
+msgstr ""
+
+msgid "Show all %{issuable_type}."
+msgstr ""
+
+msgid "Show all activity"
+msgstr ""
+
+msgid "Show all breadcrumbs"
+msgstr ""
+
+msgid "Show all epics"
+msgstr ""
+
+msgid "Show all issues."
+msgstr ""
+
+msgid "Show all milestones"
+msgstr ""
+
+msgid "Show all test cases."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show closed epics"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments on this file"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show details"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show file contents"
+msgstr ""
+
+msgid "Show group milestones"
+msgstr ""
+
+msgid "Show labels"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show list"
+msgstr ""
+
+msgid "Show one file at a time"
+msgstr ""
+
+msgid "Show open epics"
+msgstr ""
+
+msgid "Show project milestones"
+msgstr ""
+
+msgid "Show sub-group milestones"
+msgstr ""
+
+msgid "Show the Closed list"
+msgstr ""
+
+msgid "Show the Open list"
+msgstr ""
+
+msgid "Show thread"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "ShowcaseSecurity|Access a dedicated area for vulnerability management. This includes a security dashboard, vulnerability report, and settings."
+msgstr ""
+
+msgid "ShowcaseSecurity|Audit your Docker-based app. Scan for known vulnerabilities in the Docker images where your code is shipped."
+msgstr ""
+
+msgid "ShowcaseSecurity|Container scanning"
+msgstr ""
+
+msgid "ShowcaseSecurity|Dependency scanning"
+msgstr ""
+
+msgid "ShowcaseSecurity|Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "ShowcaseSecurity|Dynamically examine your application for vulnerabilities in deployed environments."
+msgstr ""
+
+msgid "ShowcaseSecurity|Enable SAST"
+msgstr ""
+
+msgid "ShowcaseSecurity|Enable Secret Detection"
+msgstr ""
+
+msgid "ShowcaseSecurity|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "ShowcaseSecurity|Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
+msgstr ""
+
+msgid "ShowcaseSecurity|Identify vulnerabilities in your code now"
+msgstr ""
+
+msgid "ShowcaseSecurity|Scan your code to detect unintentionally committed secrets, like keys, passwords, and API tokens."
+msgstr ""
+
+msgid "ShowcaseSecurity|Scan your source code using GitLab CI/CD and uncover vulnerabilities before deploying."
+msgstr ""
+
+msgid "ShowcaseSecurity|Start a free 30-day Ultimate trial or upgrade your instance to access organization-wide security and compliance features. See the other features of the Ultimate plan."
+msgstr ""
+
+msgid "ShowcaseSecurity|Start a free trial"
+msgstr ""
+
+msgid "ShowcaseSecurity|Take your security to the next level"
+msgstr ""
+
+msgid "ShowcaseSecurity|Upgrade now"
+msgstr ""
+
+msgid "ShowcaseSecurity|Use GitLab CI/CD to analyze your source code for known vulnerabilities. Compare the found vulnerabilities between your source and target branches."
+msgstr ""
+
+msgid "ShowcaseSecurity|Vulnerability management"
+msgstr ""
+
+msgid "Showing %{conflict}"
+msgstr ""
+
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{limit} of %{total_count} issues. "
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
+msgid "Showing all epics"
+msgstr ""
+
+msgid "Showing all issues"
+msgstr ""
+
+msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
+msgstr ""
+
+msgid "Showing graphs based on events of the last %{timerange} days."
+msgstr ""
+
+msgid "Showing last %{size} of log -"
+msgstr ""
+
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgstr ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
+msgid "Sidebar|Assign health status"
+msgstr ""
+
+msgid "Sidebar|Health status"
+msgstr ""
+
+msgid "Sidebar|No status"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidekiq job compression threshold (bytes)"
+msgstr ""
+
+msgid "Sidekiq job size limit (bytes)"
+msgstr ""
+
+msgid "Sidekiq job size limits"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in as a user with the matching email address, add the email to this account, or sign-up for a new account using the matching email."
+msgstr ""
+
+msgid "Sign in preview"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in to GitLab"
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign in/Sign up pages"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up now"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in and Help page"
+msgstr ""
+
+msgid "Sign-in count:"
+msgstr ""
+
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
+msgid "Sign-in page"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-in text"
+msgstr ""
+
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
+msgid "Sign-out page URL"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the GitLab%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By signing in you accept the %{link_start}Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}."
+msgstr ""
+
+msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in to GitLab"
+msgstr ""
+
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
+msgid "Signing in using %{label} has been disabled"
+msgstr ""
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
+msgid "Site profile failed to delete"
+msgstr ""
+
+msgid "Site profile not found for given parameters"
+msgstr ""
+
+msgid "Sites"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size Limits"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "Skipped deployment to"
+msgstr ""
+
+msgid "Skype:"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slack logo"
+msgstr ""
+
+msgid "SlackIntegration|Are you sure you want to remove this project from the Slack application?"
+msgstr ""
+
+msgid "SlackIntegration|Client ID"
+msgstr ""
+
+msgid "SlackIntegration|Client secret"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack"
+msgstr ""
+
+msgid "SlackIntegration|GitLab for Slack was successfully installed."
+msgstr ""
+
+msgid "SlackIntegration|Install Slack app"
+msgstr ""
+
+msgid "SlackIntegration|Project alias"
+msgstr ""
+
+msgid "SlackIntegration|Reinstall Slack app"
+msgstr ""
+
+msgid "SlackIntegration|Remove project"
+msgstr ""
+
+msgid "SlackIntegration|See the list of available commands in Slack after setting up this integration by entering"
+msgstr ""
+
+msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
+msgstr ""
+
+msgid "SlackIntegration|Sends notifications about project events to Slack channels."
+msgstr ""
+
+msgid "SlackIntegration|Signing secret"
+msgstr ""
+
+msgid "SlackIntegration|Team name"
+msgstr ""
+
+msgid "SlackIntegration|This integration allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "SlackIntegration|Verification token"
+msgstr ""
+
+msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
+msgstr ""
+
+msgid "SlackIntegration|You may need to reinstall the Slack application when we %{linkStart}make updates or change permissions%{linkEnd}."
+msgstr ""
+
+msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
+msgstr ""
+
+msgid "SlackService|2. Paste the token from Slack in the %{strong_open}Token%{strong_close} field below."
+msgstr ""
+
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, select %{strong_open}Save changes%{strong_close}, and start using slash commands in Slack!"
+msgstr ""
+
+msgid "SlackService|After setup, get a list of available Slack slash commands by entering"
+msgstr ""
+
+msgid "SlackService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
+msgid "Slice multiplier"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippet"
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Snippets with non-text files can only be edited via Git."
+msgstr ""
+
+msgid "SnippetsEmptyState|Code snippets"
+msgstr ""
+
+msgid "SnippetsEmptyState|Documentation"
+msgstr ""
+
+msgid "SnippetsEmptyState|New snippet"
+msgstr ""
+
+msgid "SnippetsEmptyState|No snippets found"
+msgstr ""
+
+msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
+msgstr ""
+
+msgid "SnippetsEmptyState|There are no snippets to show."
+msgstr ""
+
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
+msgid "Snippets|Description (optional)"
+msgstr ""
+
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Snippets|Files"
+msgstr ""
+
+msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
+msgstr ""
+
+msgid "Snippets|Snippets can't contain empty files. Ensure all files have content, or delete them."
+msgstr ""
+
+msgid "Snowplow"
+msgstr ""
+
+msgid "Soft wrap"
+msgstr ""
+
+msgid "Solid"
+msgstr ""
+
+msgid "Solution"
+msgstr ""
+
+msgid "Some changes are not shown"
+msgstr ""
+
+msgid "Some child epics may be hidden due to applied filters"
+msgstr ""
+
+msgid "Some common domains are not allowed. %{learn_more_link}."
+msgstr ""
+
+msgid "Someone edited the file the same time you did. Please check out %{link_start}the file %{icon}%{link_end} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
+msgstr ""
+
+msgid "Something went wrong"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
+msgid "Something went wrong while adding timeline event."
+msgstr ""
+
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the batch of suggestions. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while archiving a requirement."
+msgstr ""
+
+msgid "Something went wrong while closing the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while closing the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while creating a requirement."
+msgstr ""
+
+msgid "Something went wrong while deleting description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting your note. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deploying this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while editing your comment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while exporting requirements"
+msgstr ""
+
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching details"
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
+msgid "Something went wrong while fetching projects"
+msgstr ""
+
+msgid "Something went wrong while fetching projects."
+msgstr ""
+
+msgid "Something went wrong while fetching related merge requests."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements count."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements list."
+msgstr ""
+
+msgid "Something went wrong while fetching source branches."
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the packages list."
+msgstr ""
+
+msgid "Something went wrong while initializing the OpenAPI viewer"
+msgstr ""
+
+msgid "Something went wrong while obtaining the Let's Encrypt certificate."
+msgstr ""
+
+msgid "Something went wrong while promoting the issue to an epic. Please try again."
+msgstr ""
+
+msgid "Something went wrong while promoting the note to timeline event."
+msgstr ""
+
+msgid "Something went wrong while reopening a requirement."
+msgstr ""
+
+msgid "Something went wrong while reopening the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while reopening the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} %{dateType} date."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} confidentiality."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} health status."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} to-do item."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} weight."
+msgstr ""
+
+msgid "Something went wrong while stopping this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while updating a requirement."
+msgstr ""
+
+msgid "Something went wrong while updating assignees"
+msgstr ""
+
+msgid "Something went wrong while updating your list settings"
+msgstr ""
+
+msgid "Something went wrong with your automatic subscription renewal."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
+msgid "Something went wrong, unable to get projects"
+msgstr ""
+
+msgid "Something went wrong, unable to search projects"
+msgstr ""
+
+msgid "Something went wrong. Please try again later"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Something went wrong. Try again later."
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further."
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "Sort direction: Ascending"
+msgstr ""
+
+msgid "Sort direction: Descending"
+msgstr ""
+
+msgid "Sort or filter"
+msgstr ""
+
+msgid "SortOptions|Blocking"
+msgstr ""
+
+msgid "SortOptions|Closed date"
+msgstr ""
+
+msgid "SortOptions|Closed earlier"
+msgstr ""
+
+msgid "SortOptions|Closed recently"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Expired date"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Latest version"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+msgstr ""
+
+msgid "SortOptions|Merged date"
+msgstr ""
+
+msgid "SortOptions|Merged earlier"
+msgstr ""
+
+msgid "SortOptions|Merged recently"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest starred"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Oldest version"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Project"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Recently starred"
+msgstr ""
+
+msgid "SortOptions|Size"
+msgstr ""
+
+msgid "SortOptions|Sort by:"
+msgstr ""
+
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Title"
+msgstr ""
+
+msgid "SortOptions|Type"
+msgstr ""
+
+msgid "SortOptions|Version"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source Branch"
+msgstr ""
+
+msgid "Source IP"
+msgstr ""
+
+msgid "Source branch"
+msgstr ""
+
+msgid "Source branch will be deleted."
+msgstr ""
+
+msgid "Source branch will not be deleted."
+msgstr ""
+
+msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
+msgstr ""
+
+msgid "Source code (%{fileExtension})"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "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 ""
+
+msgid "SourcegraphAdmin|Block on private and internal projects"
+msgstr ""
+
+msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
+msgstr ""
+
+msgid "SourcegraphAdmin|Learn more."
+msgstr ""
+
+msgid "SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph."
+msgstr ""
+
+msgid "SourcegraphAdmin|Save changes"
+msgstr ""
+
+msgid "SourcegraphAdmin|Sourcegraph URL"
+msgstr ""
+
+msgid "SourcegraphAdmin|https://sourcegraph.example.com"
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
+msgstr ""
+
+msgid "Spam Check"
+msgstr ""
+
+msgid "Spam Check API key"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Spam log successfully submitted as ham."
+msgstr ""
+
+msgid "Specific runners"
+msgstr ""
+
+msgid "Specified URL cannot be used: \"%{reason}\""
+msgstr ""
+
+msgid "Specify IP ranges that are always allowed for inbound traffic, for use with group-level IP restrictions. Runner and Pages daemon internal IPs should be listed here so that they can access project artifacts."
+msgstr ""
+
+msgid "Specify an email address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Speed up your pipelines with Needs relationships"
+msgstr ""
+
+msgid "Spent at"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Squash commits when merge request is accepted."
+msgstr ""
+
+msgid "Stack trace"
+msgstr ""
+
+msgid "Stacktrace snippet"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage:"
+msgstr ""
+
+msgid "Standard"
+msgstr ""
+
+msgid "Star labels to start sorting by priority"
+msgstr ""
+
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
+msgstr ""
+
+msgid "StarredProjectsEmptyState|You don't have starred projects yet."
+msgstr ""
+
+msgid "Starrers"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Date"
+msgstr ""
+
+msgid "Start Time"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a Free Ultimate Trial"
+msgstr ""
+
+msgid "Start a new discussion…"
+msgstr ""
+
+msgid "Start a new merge request with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start free trial"
+msgstr ""
+
+msgid "Start inputting changes and we will generate a YAML-file for you to add to your repository"
+msgstr ""
+
+msgid "Start internal thread"
+msgstr ""
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Start merge train..."
+msgstr ""
+
+msgid "Start search"
+msgstr ""
+
+msgid "Start thread"
+msgstr ""
+
+msgid "Start your Free Ultimate Trial"
+msgstr ""
+
+msgid "Start your free trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Started asynchronous removal of all repository check states."
+msgstr ""
+
+msgid "Started escalation for this incident."
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts"
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "Starts escalations for this incident"
+msgstr ""
+
+msgid "Starts on"
+msgstr ""
+
+msgid "Starts: %{startsAt}"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "State/Province"
+msgstr ""
+
+msgid "State/Province/City"
+msgstr ""
+
+msgid "Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status was retried."
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Status: %{title}"
+msgstr ""
+
+msgid "StatusCheck| %{failed} failed, and %{pending} pending"
+msgstr ""
+
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
+msgid "StatusCheck|%{pending} pending"
+msgstr ""
+
+msgid "StatusCheck|API to check"
+msgstr ""
+
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|All passed"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+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 ""
+
+msgid "StatusCheck|Examples: QA, Security."
+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 ""
+
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
+msgid "StatusCheck|Remove status check"
+msgstr ""
+
+msgid "StatusCheck|Remove status check?"
+msgstr ""
+
+msgid "StatusCheck|Service name"
+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 ""
+
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
+msgid "StatusCheck|You are about to remove the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|status checks"
+msgstr ""
+
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS region"
+msgstr ""
+
+msgid "StatusPage|Active"
+msgstr ""
+
+msgid "StatusPage|Bucket %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+msgstr ""
+
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|configuration documentation"
+msgstr ""
+
+msgid "StatusPage|your status page frontend."
+msgstr ""
+
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
+msgid "Step %{currentStep} of %{stepCount}"
+msgstr ""
+
+msgid "Step 1."
+msgstr ""
+
+msgid "Step 2."
+msgstr ""
+
+msgid "Step 3."
+msgstr ""
+
+msgid "Step 4."
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage nodes for new repositories"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "StorageSize|Unknown"
+msgstr ""
+
+msgid "Store your files, plan your work, collaborate on code, and more."
+msgstr ""
+
+msgid "Strikethrough"
+msgstr ""
+
+msgid "Strikethrough text"
+msgstr ""
+
+msgid "Sub-batch size"
+msgstr ""
+
+msgid "Subdomains of the Pages root domain %{root_domain} are reserved and cannot be used as custom Pages domains."
+msgstr ""
+
+msgid "Subgroup information"
+msgstr ""
+
+msgid "Subgroup milestone"
+msgstr ""
+
+msgid "Subgroup navigation"
+msgstr ""
+
+msgid "SubgroupCreationLevel|Roles allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Maintainers"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Owners"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Subgroups can set up their own two-factor authentication rules"
+msgstr ""
+
+msgid "Subject Key Identifier:"
+msgstr ""
+
+msgid "Subkeys"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Submit a review"
+msgstr ""
+
+msgid "Submit as ham"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submitted as ham"
+msgstr ""
+
+msgid "Submitted the current review."
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Subscribed to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscribed to this project"
+msgstr ""
+
+msgid "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscript"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription History"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription service outage"
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionBanner|Add new license"
+msgstr ""
+
+msgid "SubscriptionBanner|Export license usage file"
+msgstr ""
+
+msgid "SubscriptionBanner|Upload new license"
+msgstr ""
+
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Refresh Seats"
+msgstr ""
+
+msgid "SubscriptionTable|Renew"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|See usage"
+msgstr ""
+
+msgid "SubscriptionTable|Something went wrong trying to refresh seats"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Subscriptions"
+msgstr ""
+
+msgid "Subscriptions|Chat with sales"
+msgstr ""
+
+msgid "Subscriptions|Close"
+msgstr ""
+
+msgid "Subscriptions|Not ready to buy yet?"
+msgstr ""
+
+msgid "Subscriptions|Start a free trial"
+msgstr ""
+
+msgid "Subscriptions|We understand. Maybe you have some questions for our sales team, or maybe you'd like to try some of the paid features first. What would you like to do?"
+msgstr ""
+
+msgid "Subscription|Your subscription for %{strong}%{namespace_name}%{strong_close} has expired and you are now on %{pricing_link_start}the GitLab Free tier%{pricing_link_end}. Don't worry, your data is safe. Get in touch with our support team (%{support_email}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "Subtracted"
+msgstr ""
+
+msgid "Subtracts"
+msgstr ""
+
+msgid "Succeeded"
+msgstr ""
+
+msgid "Successfully activated"
+msgstr ""
+
+msgid "Successfully approved"
+msgstr ""
+
+msgid "Successfully banned"
+msgstr ""
+
+msgid "Successfully blocked"
+msgstr ""
+
+msgid "Successfully confirmed"
+msgstr ""
+
+msgid "Successfully deactivated"
+msgstr ""
+
+msgid "Successfully deleted U2F device."
+msgstr ""
+
+msgid "Successfully deleted WebAuthn device."
+msgstr ""
+
+msgid "Successfully removed email."
+msgstr ""
+
+msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
+msgstr ""
+
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
+msgid "Successfully unbanned"
+msgstr ""
+
+msgid "Successfully unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully updated %{last_updated_timeago}."
+msgstr ""
+
+msgid "Successfully updated the environment."
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "SuggestedColors|Aztec Gold"
+msgstr ""
+
+msgid "SuggestedColors|Blue"
+msgstr ""
+
+msgid "SuggestedColors|Blue-gray"
+msgstr ""
+
+msgid "SuggestedColors|Carrot orange"
+msgstr ""
+
+msgid "SuggestedColors|Champagne"
+msgstr ""
+
+msgid "SuggestedColors|Charcoal grey"
+msgstr ""
+
+msgid "SuggestedColors|Crimson"
+msgstr ""
+
+msgid "SuggestedColors|Current addition color"
+msgstr ""
+
+msgid "SuggestedColors|Current removal color"
+msgstr ""
+
+msgid "SuggestedColors|Dark coral"
+msgstr ""
+
+msgid "SuggestedColors|Dark green"
+msgstr ""
+
+msgid "SuggestedColors|Dark sea green"
+msgstr ""
+
+msgid "SuggestedColors|Dark violet"
+msgstr ""
+
+msgid "SuggestedColors|Deep violet"
+msgstr ""
+
+msgid "SuggestedColors|Default addition color"
+msgstr ""
+
+msgid "SuggestedColors|Default removal color"
+msgstr ""
+
+msgid "SuggestedColors|Gray"
+msgstr ""
+
+msgid "SuggestedColors|Green"
+msgstr ""
+
+msgid "SuggestedColors|Green screen"
+msgstr ""
+
+msgid "SuggestedColors|Green-cyan"
+msgstr ""
+
+msgid "SuggestedColors|Lavender"
+msgstr ""
+
+msgid "SuggestedColors|Magenta-pink"
+msgstr ""
+
+msgid "SuggestedColors|Medium sea green"
+msgstr ""
+
+msgid "SuggestedColors|Orange"
+msgstr ""
+
+msgid "SuggestedColors|Purple"
+msgstr ""
+
+msgid "SuggestedColors|Red"
+msgstr ""
+
+msgid "SuggestedColors|Rose red"
+msgstr ""
+
+msgid "SuggestedColors|Titanium yellow"
+msgstr ""
+
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
+msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr ""
+
+msgid "Suggestion(s)"
+msgstr ""
+
+msgid "Suggestions are not applicable as one or more suggestions were not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as their lines cannot overlap."
+msgstr ""
+
+msgid "Suggestions must all be on the same branch."
+msgstr ""
+
+msgid "Suggestions:"
+msgstr ""
+
+msgid "Suite"
+msgstr ""
+
+msgid "Summary"
+msgstr ""
+
+msgid "Summary / note"
+msgstr ""
+
+msgid "Summary comment (optional)"
+msgstr ""
+
+msgid "Sun"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr ""
+
+msgid "SuperSonics|Cloud licensing"
+msgstr ""
+
+msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
+msgid "SuperSonics|Export license usage file"
+msgstr ""
+
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|Learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|Licensed to"
+msgstr ""
+
+msgid "SuperSonics|Manage"
+msgstr ""
+
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Offline license"
+msgstr ""
+
+msgid "SuperSonics|Online license"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
+msgid "SuperSonics|Please agree to the Subscription Agreement"
+msgstr ""
+
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
+msgid "SuperSonics|Subscription details"
+msgstr ""
+
+msgid "SuperSonics|Subscription unavailable"
+msgstr ""
+
+msgid "SuperSonics|Sync subscription details"
+msgstr ""
+
+msgid "SuperSonics|Sync subscription request."
+msgstr ""
+
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|The activation code should be a 24-character alphanumeric string"
+msgstr ""
+
+msgid "SuperSonics|There is a connectivity issue."
+msgstr ""
+
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, your instance needs to connect to GitLab. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|User in subscription"
+msgid_plural "SuperSonics|Users in subscription"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
+msgid "SuperSonics|You can %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} and try again. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
+msgid "SuperSonics|You do not have an active subscription"
+msgstr ""
+
+msgid "SuperSonics|You have a future dated license"
+msgstr ""
+
+msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
+msgstr ""
+
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
+msgstr ""
+
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
+msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
+msgstr ""
+
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
+msgid "SuperSonics|Your future dated license was successfully added"
+msgstr ""
+
+msgid "SuperSonics|Your subscription"
+msgstr ""
+
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
+msgid "SuperSonics|Your subscription details will sync shortly."
+msgstr ""
+
+msgid "SuperSonics|Your subscription is expired"
+msgstr ""
+
+msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
+msgstr ""
+
+msgid "SuperSonics|current subscription"
+msgstr ""
+
+msgid "SuperSonics|future subscriptions"
+msgstr ""
+
+msgid "SuperSonics|past subscriptions"
+msgstr ""
+
+msgid "Superscript"
+msgstr ""
+
+msgid "Support"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Support page URL"
+msgstr ""
+
+msgid "Surveys|Delighted"
+msgstr ""
+
+msgid "Surveys|Happy"
+msgstr ""
+
+msgid "Surveys|Neutral"
+msgstr ""
+
+msgid "Surveys|Sad"
+msgstr ""
+
+msgid "Surveys|Unhappy"
+msgstr ""
+
+msgid "Switch Branches"
+msgstr ""
+
+msgid "Switch branch"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy the file contents"
+msgstr ""
+
+msgid "Symbolic link"
+msgstr ""
+
+msgid "Sync LDAP"
+msgstr ""
+
+msgid "Sync now"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronize LDAP"
+msgstr ""
+
+msgid "Syncing…"
+msgstr ""
+
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Dark"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Light"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Monokai"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|None"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Solarized Dark"
+msgstr ""
+
+msgid "SynthaxHighlightingTheme|Solarized Light"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Hooks Help"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System hooks are triggered on sets of events like creating a project or adding an SSH key. You can also enable extra triggers, such as push events."
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "System output"
+msgstr ""
+
+msgid "System started"
+msgstr ""
+
+msgid "Table of Contents"
+msgstr ""
+
+msgid "Table of contents"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tag name"
+msgstr ""
+
+msgid "Tag name is required."
+msgstr ""
+
+msgid "Tag push"
+msgstr ""
+
+msgid "Tag push events"
+msgstr ""
+
+msgid "Tag this commit."
+msgstr ""
+
+msgid "Tag:"
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this tag."
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Cancel, keep tag"
+msgstr ""
+
+msgid "TagsPage|Create release"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete protected tag"
+msgstr ""
+
+msgid "TagsPage|Delete protected tag. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Please type the following to confirm:"
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|Yes, delete protected tag"
+msgstr ""
+
+msgid "TagsPage|Yes, delete tag"
+msgstr ""
+
+msgid "TagsPage|You're about to permanently delete the protected tag %{strongStart}%{tagName}.%{strongEnd}"
+msgstr ""
+
+msgid "TagsPage|You're about to permanently delete the tag %{strongStart}%{tagName}.%{strongEnd}"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Take a look at the documentation to discover all of GitLab’s capabilities."
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target Path"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Target branch or tag"
+msgstr ""
+
+msgid "Target roles"
+msgstr ""
+
+msgid "Target-Branch"
+msgstr ""
+
+msgid "Task"
+msgstr ""
+
+msgid "Task ID: %{elastic_task}"
+msgstr ""
+
+msgid "Task list"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Team domain"
+msgstr ""
+
+msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
+msgstr ""
+
+msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
+msgstr ""
+
+msgid "Telephone number"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Template to append to all Service Desk issues"
+msgstr ""
+
+msgid "TemplateRepository|Create common files more quickly, and standardize their format."
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set once"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
+msgstr ""
+
+msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
+msgstr ""
+
+msgid "TemporaryStorage|Increase storage temporarily"
+msgstr ""
+
+msgid "TemporaryStorage|Temporarily increase storage now?"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terminal sync service is running"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Terms of service"
+msgstr ""
+
+msgid "Terraform"
+msgstr ""
+
+msgid "TerraformBanner|Learn more about GitLab's Backend State"
+msgstr ""
+
+msgid "TerraformBanner|The GitLab managed Terraform state backend can store your Terraform state easily and securely, and spares you from setting up additional remote resources. Its features include: versioning, encryption of the state file both in transit and at rest, locking, and remote Terraform plan/apply execution."
+msgstr ""
+
+msgid "TerraformBanner|Using Terraform? Try the GitLab Managed Terraform State"
+msgstr ""
+
+msgid "Terraform|%{name} successfully removed"
+msgstr ""
+
+msgid "Terraform|%{number} Terraform report failed to generate"
+msgid_plural "Terraform|%{number} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{number} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
+msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{user} updated %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|A Terraform report failed to generate."
+msgstr ""
+
+msgid "Terraform|A Terraform report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|A report failed to generate."
+msgstr ""
+
+msgid "Terraform|A report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|Actions"
+msgstr ""
+
+msgid "Terraform|An error occurred while changing the state file"
+msgstr ""
+
+msgid "Terraform|An error occurred while loading your Terraform States"
+msgstr ""
+
+msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
+msgstr ""
+
+msgid "Terraform|Cancel"
+msgstr ""
+
+msgid "Terraform|Cannot remove a locked state"
+msgstr ""
+
+msgid "Terraform|Copy Terraform init command"
+msgstr ""
+
+msgid "Terraform|Deletion in progress"
+msgstr ""
+
+msgid "Terraform|Details"
+msgstr ""
+
+msgid "Terraform|Download JSON"
+msgstr ""
+
+msgid "Terraform|Failed to load Terraform reports"
+msgstr ""
+
+msgid "Terraform|Generating the report caused an error."
+msgstr ""
+
+msgid "Terraform|How to use GitLab-managed Terraform state?"
+msgstr ""
+
+msgid "Terraform|Job status"
+msgstr ""
+
+msgid "Terraform|Loading Terraform reports..."
+msgstr ""
+
+msgid "Terraform|Lock"
+msgstr ""
+
+msgid "Terraform|Locked"
+msgstr ""
+
+msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|Locking state"
+msgstr ""
+
+msgid "Terraform|Name"
+msgstr ""
+
+msgid "Terraform|Pipeline"
+msgstr ""
+
+msgid "Terraform|Remove"
+msgstr ""
+
+msgid "Terraform|Remove state file and versions"
+msgstr ""
+
+msgid "Terraform|Removed"
+msgstr ""
+
+msgid "Terraform|Removing"
+msgstr ""
+
+msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
+msgstr ""
+
+msgid "Terraform|States"
+msgstr ""
+
+msgid "Terraform|Terraform init command"
+msgstr ""
+
+msgid "Terraform|Terraform reports"
+msgstr ""
+
+msgid "Terraform|The job %{name} failed to generate a report."
+msgstr ""
+
+msgid "Terraform|The job %{name} generated a report."
+msgstr ""
+
+msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
+msgstr ""
+
+msgid "Terraform|The job %{strong_start}%{name}%{strong_end} 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 ""
+
+msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
+msgstr ""
+
+msgid "Terraform|Unknown User"
+msgstr ""
+
+msgid "Terraform|Unlock"
+msgstr ""
+
+msgid "Terraform|Unlocking state"
+msgstr ""
+
+msgid "Terraform|You are about to remove the state file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously will remain intact, and only the state file with all its versions will be removed. This action cannot be undone."
+msgstr ""
+
+msgid "Terraform|You have insufficient permissions to delete this state"
+msgstr ""
+
+msgid "Terraform|Your project doesn't have any Terraform state files"
+msgstr ""
+
+msgid "Test"
+msgstr ""
+
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test case"
+msgstr ""
+
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test coverage: %d hit"
+msgid_plural "Test coverage: %d hits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test settings"
+msgstr ""
+
+msgid "TestCases|Move test case"
+msgstr ""
+
+msgid "TestCases|Moving test case"
+msgstr ""
+
+msgid "TestCases|New Test Case"
+msgstr ""
+
+msgid "TestCases|New test case"
+msgstr ""
+
+msgid "TestCases|Search test cases"
+msgstr ""
+
+msgid "TestCases|Something went wrong while adding test case to a to-do item."
+msgstr ""
+
+msgid "TestCases|Something went wrong while creating a test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test cases list."
+msgstr ""
+
+msgid "TestCases|Something went wrong while marking test case to-do item as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while moving test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
+msgid "TestCases|Submit test case"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has deployments."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has releases."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
+msgid "TestReports|%{count} errors"
+msgstr ""
+
+msgid "TestReports|%{count} failures"
+msgstr ""
+
+msgid "TestReports|%{count} tests"
+msgstr ""
+
+msgid "TestReports|%{rate}%{sign} success rate"
+msgstr ""
+
+msgid "TestReports|Attachment"
+msgstr ""
+
+msgid "TestReports|Copy test name to rerun locally"
+msgstr ""
+
+msgid "TestReports|Job artifacts are expired"
+msgstr ""
+
+msgid "TestReports|Jobs"
+msgstr ""
+
+msgid "TestReports|Learn how to upload pipeline test reports"
+msgstr ""
+
+msgid "TestReports|Learn more about pipeline test reports"
+msgstr ""
+
+msgid "TestReports|No test cases were found in the test report."
+msgstr ""
+
+msgid "TestReports|Test reports require job artifacts but all artifacts are expired. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test reports for this pipeline"
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to display"
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "TestReports|You can configure your job to use unit test reports, and GitLab displays a report here and in the related merge request."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Text (optional)"
+msgstr ""
+
+msgid "Text added to the body of all email messages. %{character_limit} character limit"
+msgstr ""
+
+msgid "Text style"
+msgstr ""
+
+msgid "Thank you for your business."
+msgstr ""
+
+msgid "Thank you for your report. A GitLab administrator will look into it shortly."
+msgstr ""
+
+msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
+msgstr ""
+
+msgid "Thanks for signing up to GitLab!"
+msgstr ""
+
+msgid "Thanks for your purchase!"
+msgstr ""
+
+msgid "That's OK, I don't want to renew"
+msgstr ""
+
+msgid "That's it, well done!"
+msgstr ""
+
+msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
+msgstr ""
+
+msgid "The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}."
+msgstr ""
+
+msgid "The %{type} contains the following error:"
+msgid_plural "The %{type} contains the following errors:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
+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 ""
+
+msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
+msgstr ""
+
+msgid "The ID of the application."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
+msgstr ""
+
+msgid "The Snowplow cookie domain."
+msgstr ""
+
+msgid "The URL of the Jenkins server."
+msgstr ""
+
+msgid "The URL should start with http:// or https://"
+msgstr ""
+
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
+
+msgid "The `/merge` quick action requires the SHA of the head of the branch."
+msgstr ""
+
+msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
+msgstr ""
+
+msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
+msgstr ""
+
+msgid "The branch for this project has no active pipeline configuration."
+msgstr ""
+
+msgid "The branch or tag does not exist"
+msgstr ""
+
+msgid "The broadcast message displays only to users in projects and groups who have these roles."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The 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?"
+msgstr ""
+
+msgid "The commit does not exist"
+msgstr ""
+
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
+msgid "The complete DevOps platform. One application with endless possibilities. Organizations rely on GitLab’s source code management, CI/CD, security, and more to deliver software rapidly."
+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 ""
+
+msgid "The contact does not belong to the issue group's root ancestor"
+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 for this wiki page failed to load. To fix this error, reload the page."
+msgstr ""
+
+msgid "The content for this wiki page failed to render."
+msgstr ""
+
+msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr ""
+
+msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
+msgstr ""
+
+msgid "The current epic"
+msgstr ""
+
+msgid "The current incident"
+msgstr ""
+
+msgid "The current issue"
+msgstr ""
+
+msgid "The current user is not authorized to access the job log."
+msgstr ""
+
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
+msgid "The data source is connected, but there is no data to display. %{documentationLink}"
+msgstr ""
+
+msgid "The date when the release is ready. A release with a date in the future is labeled as an %{linkStart}Upcoming Release%{linkEnd}."
+msgstr ""
+
+msgid "The default CI/CD configuration file and path for new projects."
+msgstr ""
+
+msgid "The default branch for this project has been changed. Please update your bookmarks."
+msgstr ""
+
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The directory has been successfully created."
+msgstr ""
+
+msgid "The domain you entered is misformatted."
+msgstr ""
+
+msgid "The domain you entered is not allowed."
+msgstr ""
+
+msgid "The download link will expire in 24 hours."
+msgstr ""
+
+msgid "The environment tiers must be from %{environment_tiers}."
+msgstr ""
+
+msgid "The errors we encountered were:"
+msgstr ""
+
+msgid "The file containing the export is not available yet; it may still be transferring. Please try again later."
+msgstr ""
+
+msgid "The file could not be displayed because it is empty or larger than the maximum file size indexed (%{size})."
+msgstr ""
+
+msgid "The file has been successfully created."
+msgstr ""
+
+msgid "The file has been successfully deleted."
+msgstr ""
+
+msgid "The file name should have a .yml extension"
+msgstr ""
+
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
+msgid "The following items will NOT be exported:"
+msgstr ""
+
+msgid "The following items will be exported:"
+msgstr ""
+
+msgid "The following personal access token: %{token_names} was revoked, because a new policy to expire personal access tokens were set."
+msgid_plural "The following personal access tokens: %{token_names} were revoked, because a new policy to expire personal access tokens were set."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The form contains the following error:"
+msgid_plural "The form contains the following errors:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The form contains the following warning:"
+msgstr ""
+
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
+msgid "The global settings require you to enable Two-Factor Authentication for your account."
+msgstr ""
+
+msgid "The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "The group export can be downloaded from:"
+msgstr ""
+
+msgid "The group has already been shared with this group"
+msgstr ""
+
+msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
+msgstr ""
+
+msgid "The group_project_ids parameter is only allowed for a group"
+msgstr ""
+
+msgid "The hostname of your PlantUML server."
+msgstr ""
+
+msgid "The hostname of your Snowplow collector."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
+msgid "The invitation could not be accepted."
+msgstr ""
+
+msgid "The invitation could not be declined."
+msgstr ""
+
+msgid "The invitation has already been accepted."
+msgstr ""
+
+msgid "The invitation was successfully resent."
+msgstr ""
+
+msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
+msgstr ""
+
+msgid "The last owner cannot be set to awaiting"
+msgstr ""
+
+msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
+msgstr ""
+
+msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
+msgstr ""
+
+msgid "The latest pipeline for this merge request has failed."
+msgstr ""
+
+msgid "The license key is invalid."
+msgstr ""
+
+msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
+msgstr ""
+
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
+msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
+msgstr ""
+
+msgid "The license you uploaded is invalid. If the issue persists, contact support at %{link}."
+msgstr ""
+
+msgid "The list creation wizard is already open"
+msgstr ""
+
+msgid "The maximum amount of time users have to set up two-factor authentication before it's enforced."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size for job artifacts."
+msgstr ""
+
+msgid "The maximum file size in megabytes for individual job artifacts."
+msgstr ""
+
+msgid "The maximum file size is %{size}."
+msgstr ""
+
+msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
+msgstr ""
+
+msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
+msgstr ""
+
+msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
+msgstr ""
+
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
+msgid "The name \"%{name}\" is already taken in this directory."
+msgstr ""
+
+msgid "The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close})."
+msgstr ""
+
+msgid "The name of the Jenkins project. Copy the name from the end of the URL to the project."
+msgstr ""
+
+msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
+msgstr ""
+
+msgid "The number of merge requests merged by month."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
+msgid "The page could not be displayed because it timed out."
+msgstr ""
+
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
+
+msgid "The parsed YAML is too big"
+msgstr ""
+
+msgid "The password for the Jenkins server."
+msgstr ""
+
+msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
+msgstr ""
+
+msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
+msgstr ""
+
+msgid "The pipeline has been deleted"
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
+msgid "The project size exceeds the export limit."
+msgstr ""
+
+msgid "The project was successfully forked."
+msgstr ""
+
+msgid "The project was successfully imported."
+msgstr ""
+
+msgid "The related CI build failed."
+msgstr ""
+
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
+msgid "The remote repository is being updated..."
+msgstr ""
+
+msgid "The report artifact provided by the CI build couldn't be parsed."
+msgstr ""
+
+msgid "The report has been successfully prepared."
+msgstr ""
+
+msgid "The repository can be committed to, and issues, comments and other entities can be created."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository is being updated..."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The resource that you are attempting to access does not exist or you don't have permission to perform this action."
+msgstr ""
+
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "The scan has been created."
+msgstr ""
+
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
+msgid "The snippet can be accessed without any authentication."
+msgstr ""
+
+msgid "The snippet is visible only to me."
+msgstr ""
+
+msgid "The snippet is visible only to project members."
+msgstr ""
+
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
+
+msgid "The source project of this merge request has been removed."
+msgstr ""
+
+msgid "The source topic and the target topic are identical."
+msgstr ""
+
+msgid "The source topic is not a topic."
+msgstr ""
+
+msgid "The specified tab is invalid, please select another"
+msgstr ""
+
+msgid "The start date must be ealier than the end date."
+msgstr ""
+
+msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
+msgstr ""
+
+msgid "The tag name can't be changed for an existing release."
+msgstr ""
+
+msgid "The target topic is not a topic."
+msgstr ""
+
+msgid "The time period in seconds that the maximum requests per project limit applies to."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
+msgstr ""
+
+msgid "The user is being deleted."
+msgstr ""
+
+msgid "The user map has been saved. Continue by selecting the projects you want to import."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The user you are trying to approve is not pending approval"
+msgstr ""
+
+msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
+msgstr ""
+
+msgid "The username for the Jenkins server."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
+msgstr ""
+
+msgid "Theme"
+msgstr ""
+
+msgid "There are currently no events."
+msgstr ""
+
+msgid "There are currently no mirrored repositories."
+msgstr ""
+
+msgid "There are merge conflicts"
+msgstr ""
+
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
+
+msgid "There are no Spam Logs"
+msgstr ""
+
+msgid "There are no abuse reports!"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no archived requirements"
+msgstr ""
+
+msgid "There are no archived test cases"
+msgstr ""
+
+msgid "There are no changed labels"
+msgstr ""
+
+msgid "There are no changes"
+msgstr ""
+
+msgid "There are no charts configured for this page"
+msgstr ""
+
+msgid "There are no closed epics"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no commits yet."
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no issues with the selected labels"
+msgstr ""
+
+msgid "There are no matching files"
+msgstr ""
+
+msgid "There are no open epics"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no open requirements"
+msgstr ""
+
+msgid "There are no open test cases"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no secure files yet."
+msgstr ""
+
+msgid "There are no topics to show."
+msgstr ""
+
+msgid "There are no variables yet."
+msgstr ""
+
+msgid "There are running deployments on the environment. Please retry later."
+msgstr ""
+
+msgid "There are several file size limits in place for the Package Registry."
+msgstr ""
+
+msgid "There are several rate limits in place to protect the system."
+msgstr ""
+
+msgid "There are several size limits in place."
+msgstr ""
+
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There is already a to-do item for this design."
+msgstr ""
+
+msgid "There is no chart data available."
+msgstr ""
+
+msgid "There is no data available."
+msgstr ""
+
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no table data available."
+msgstr ""
+
+msgid "There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem fetching CRM contacts."
+msgstr ""
+
+msgid "There was a problem fetching CRM organizations."
+msgstr ""
+
+msgid "There was a problem fetching branches."
+msgstr ""
+
+msgid "There was a problem fetching emojis."
+msgstr ""
+
+msgid "There was a problem fetching epics."
+msgstr ""
+
+msgid "There was a problem fetching groups."
+msgstr ""
+
+msgid "There was a problem fetching iterations."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+msgstr ""
+
+msgid "There was a problem fetching linked pipelines."
+msgstr ""
+
+msgid "There was a problem fetching milestones."
+msgstr ""
+
+msgid "There was a problem fetching project branches."
+msgstr ""
+
+msgid "There was a problem fetching project tags."
+msgstr ""
+
+msgid "There was a problem fetching project users."
+msgstr ""
+
+msgid "There was a problem fetching recent groups."
+msgstr ""
+
+msgid "There was a problem fetching recent projects."
+msgstr ""
+
+msgid "There was a problem fetching releases."
+msgstr ""
+
+msgid "There was a problem fetching the job token scope value"
+msgstr ""
+
+msgid "There was a problem fetching the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was a problem fetching the latest pipeline status."
+msgstr ""
+
+msgid "There was a problem fetching the pipeline stages."
+msgstr ""
+
+msgid "There was a problem fetching the projects"
+msgstr ""
+
+msgid "There was a problem fetching users."
+msgstr ""
+
+msgid "There was a problem handling the pipeline data."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was a problem updating the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was an error adding a To Do."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error creating the issue"
+msgstr ""
+
+msgid "There was an error deleting the To Do."
+msgstr ""
+
+msgid "There was an error fetching configuration for charts"
+msgstr ""
+
+msgid "There was an error fetching data for the selected stage"
+msgstr ""
+
+msgid "There was an error fetching data for the tasks by type chart"
+msgstr ""
+
+msgid "There was an error fetching label data for the selected group"
+msgstr ""
+
+msgid "There was an error fetching median data for stages"
+msgstr ""
+
+msgid "There was an error fetching projects"
+msgstr ""
+
+msgid "There was an error fetching stage total counts"
+msgstr ""
+
+msgid "There was an error fetching the %{replicableType}"
+msgstr ""
+
+msgid "There was an error fetching the deploy freezes."
+msgstr ""
+
+msgid "There was an error fetching the environments information."
+msgstr ""
+
+msgid "There was an error fetching the jobs for your project."
+msgstr ""
+
+msgid "There was an error fetching the top labels for the selected group"
+msgstr ""
+
+msgid "There was an error fetching the variables."
+msgstr ""
+
+msgid "There was an error fetching value stream analytics stages."
+msgstr ""
+
+msgid "There was an error gathering the chart data"
+msgstr ""
+
+msgid "There was an error getting the epic participants."
+msgstr ""
+
+msgid "There was an error importing the Jira project."
+msgstr ""
+
+msgid "There was an error loading related feature flags"
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error parsing the data for this graph."
+msgstr ""
+
+msgid "There was an error removing the e-mail."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
+msgid "There was an error retrieving the Jira users."
+msgstr ""
+
+msgid "There was an error saving your changes."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error syncing project %{name}"
+msgstr ""
+
+msgid "There was an error syncing the %{replicableType}"
+msgstr ""
+
+msgid "There was an error trying to validate your query"
+msgstr ""
+
+msgid "There was an error updating the Maintenance Mode Settings"
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics data."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics duration data."
+msgstr ""
+
+msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
+msgstr ""
+
+msgid "These dates affect how your epics appear in the roadmap. Set a fixed date or one inherited from the milestones assigned to issues in this epic."
+msgstr ""
+
+msgid "These examples show how to trigger this project's pipeline for a branch or tag."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
+msgstr ""
+
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
+msgstr ""
+
+msgid "These will be sent to %{email} in an attachment once finished."
+msgstr ""
+
+msgid "Things to be aware of before transferring:"
+msgstr ""
+
+msgid "Third Party Advisory Link"
+msgstr ""
+
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
+msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgstr ""
+
+msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{confidentialLinkEnd} and %{lockedLinkStart}locked%{lockedLinkEnd}."
+msgstr ""
+
+msgid "This %{noteableTypeText} is locked."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This Cron pattern is invalid"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
+msgstr ""
+
+msgid "This 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 ""
+
+msgid "This URL already exists."
+msgstr ""
+
+msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
+msgstr ""
+
+msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
+msgstr ""
+
+msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} and everything this project contains. %{strongOpen}There is no going back.%{strongClose}"
+msgstr ""
+
+msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains."
+msgstr ""
+
+msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains. %{strongOpen}There is no going back.%{strongClose}"
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}immediately%{strongClose}."
+msgstr ""
+
+msgid "This also resolves all related threads"
+msgstr ""
+
+msgid "This also resolves this thread"
+msgstr ""
+
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+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 ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{requirements_count} requirements have been included. Consider re-exporting with a narrower selection of requirements."
+msgstr ""
+
+msgid "This block is self-referential"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has diverged from upstream."
+msgstr ""
+
+msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
+msgid "This clears repository check states for all projects in the database and cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "This code snippet contains everything reflected in the configuration form. Copy and paste it into %{linkStart}.gitlab-ci.yml%{linkEnd} file and save your changes. Future %{scanType} scans will use these settings."
+msgstr ""
+
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
+
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with %{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 ""
+
+msgid "This commit was signed with a different user's verified signature."
+msgstr ""
+
+msgid "This commit was signed with a verified signature, but the committer email is not associated with the GPG Key."
+msgstr ""
+
+msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
+msgstr ""
+
+msgid "This content could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
+msgstr ""
+
+msgid "This credential has expired"
+msgstr ""
+
+msgid "This deployment is not waiting for approvals."
+msgstr ""
+
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
+msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
+msgstr ""
+
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This email address does not look right, are you sure you typed it correctly?"
+msgstr ""
+
+msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_link}."
+msgstr ""
+
+msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_name}."
+msgstr ""
+
+msgid "This endpoint has been requested too many times. Try again later."
+msgstr ""
+
+msgid "This environment has no deployments yet."
+msgstr ""
+
+msgid "This environment is being deployed"
+msgstr ""
+
+msgid "This environment is being re-deployed"
+msgstr ""
+
+msgid "This environment is not protected."
+msgstr ""
+
+msgid "This environment's canary ingress has been updated recently. Please retry later."
+msgstr ""
+
+msgid "This epic already has the maximum number of child epics."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
+msgid "This epic does not exist or you don't have sufficient permission."
+msgstr ""
+
+msgid "This epic would exceed maximum number of related epics."
+msgstr ""
+
+msgid "This feature requires local storage to be enabled"
+msgstr ""
+
+msgid "This field is required"
+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 form is disabled in preview"
+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 ""
+
+msgid "This group can't be transferred because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
+msgid "This group cannot be invited to a project inside a group with enforced SSO"
+msgstr ""
+
+msgid "This group does not have any group runners yet."
+msgstr ""
+
+msgid "This group has been scheduled for permanent removal on %{date}"
+msgstr ""
+
+msgid "This group has no active access tokens."
+msgstr ""
+
+msgid "This group is linked to a subscription"
+msgstr ""
+
+msgid "This group is not permitted to create compliance violations"
+msgstr ""
+
+msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
+msgstr ""
+
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
+
+msgid "This incident is already escalated with '%{escalation_policy_name}'."
+msgstr ""
+
+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 ""
+
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
+msgid "This is a Jira user."
+msgstr ""
+
+msgid "This is a confidential %{noteableTypeText}."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a 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 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 ""
+
+msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
+msgid "This is your current session"
+msgstr ""
+
+msgid "This issue cannot be assigned to a confidential epic because it is public."
+msgstr ""
+
+msgid "This issue cannot be made public because it belongs to a confidential epic."
+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 ""
+
+msgid "This issue is hidden because its author has been banned"
+msgstr ""
+
+msgid "This issue is in a child epic of the filtered epic"
+msgstr ""
+
+msgid "This job could not start because it could not retrieve the needed artifacts%{punctuation}%{invalid_dependencies}"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job deploys to the protected environment \"%{environment}\" which requires approvals."
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job does not run automatically and must be started manually, but you do not have access to it."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is performing tasks that must complete before it can start"
+msgstr ""
+
+msgid "This job is preparing to start"
+msgstr ""
+
+msgid "This job is waiting for resource: "
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes."
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This license has already expired."
+msgstr ""
+
+msgid "This link points to external content"
+msgstr ""
+
+msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request branch is protected from force push."
+msgstr ""
+
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
+msgid "This merge request does not have accessibility reports"
+msgstr ""
+
+msgid "This merge request does not have codequality reports"
+msgstr ""
+
+msgid "This merge request is closed. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This merge request is from a private project to a public project."
+msgstr ""
+
+msgid "This merge request is from a private project to an internal project."
+msgstr ""
+
+msgid "This merge request is from an internal project to a public project."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This merge request was merged. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This namespace has already been taken! Please choose another one."
+msgstr ""
+
+msgid "This only applies to repository indexing operations."
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page sends a payload. Go back to the events page to see a newly created event."
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline was triggered by a schedule."
+msgstr ""
+
+msgid "This process deletes the project repository and all related resources."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project can be restored until %{date}."
+msgstr ""
+
+msgid "This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group."
+msgstr ""
+
+msgid "This project does not belong to a group and cannot make use of group runners."
+msgstr ""
+
+msgid "This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project has no active access tokens."
+msgstr ""
+
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources."
+msgstr ""
+
+msgid "This project is archived and cannot be commented on."
+msgstr ""
+
+msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
+msgstr ""
+
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
+msgid "This project is not subscribed to any project pipelines."
+msgstr ""
+
+msgid "This project is public. Non-members can guess the Service Desk email address, because it contains the group and project name. %{linkStart}How do I create a custom email address?%{linkEnd}"
+msgstr ""
+
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
+msgid "This project path either does not exist or you do not have access."
+msgstr ""
+
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
+msgid "This project will be deleted on %{date}"
+msgstr ""
+
+msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
+msgstr ""
+
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
+msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
+msgstr ""
+
+msgid "This report uses a supported MAJOR.MINOR schema version but the PATCH version doesn't match any vendored schema version. Validation will be attempted against version %{find_latest_patch_version}"
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This repository has never been checked."
+msgstr ""
+
+msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check passed."
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting has been configured at the instance level and cannot be overridden per group"
+msgstr ""
+
+msgid "This setting is allowed for forked projects only"
+msgstr ""
+
+msgid "This subscription is for"
+msgstr ""
+
+msgid "This suggestion already matches its content."
+msgstr ""
+
+msgid "This title already exists."
+msgstr ""
+
+msgid "This user cannot be unlocked manually from GitLab"
+msgstr ""
+
+msgid "This user has an unconfirmed email address (%{email}). You may force a confirmation."
+msgstr ""
+
+msgid "This user has an unconfirmed email address. You may force a confirmation."
+msgstr ""
+
+msgid "This user has no active %{accessTokenTypePlural}."
+msgstr ""
+
+msgid "This user has no active %{type}."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user has no personal projects."
+msgstr ""
+
+msgid "This user has previously committed to the %{name} project."
+msgstr ""
+
+msgid "This user has the %{access} role in the %{name} project."
+msgstr ""
+
+msgid "This user is the author of this %{noteable}."
+msgstr ""
+
+msgid "This variable can not be masked."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and %{fork_source}."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and other projects in the fork network."
+msgstr ""
+
+msgid "Thread options"
+msgstr ""
+
+msgid "Thread to reply to cannot be found"
+msgstr ""
+
+msgid "Threshold in bytes at which to compress Sidekiq job arguments."
+msgstr ""
+
+msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
+msgstr ""
+
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
+msgid "Throughput"
+msgstr ""
+
+msgid "Thu"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time from first comment to last commit"
+msgstr ""
+
+msgid "Time from first commit until first comment"
+msgstr ""
+
+msgid "Time from last commit to merge"
+msgstr ""
+
+msgid "Time of import: %{importTime}"
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time to Restore Service"
+msgstr ""
+
+msgid "Time to merge"
+msgstr ""
+
+msgid "Time to subtract exceeds the total time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time tracking report"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "Time zone"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
+msgstr ""
+
+msgid "TimeTracking|An error occurred while removing the timelog."
+msgstr ""
+
+msgid "TimeTracking|Delete time spent"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "TimeTracking|Time remaining: %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeline event added successfully."
+msgstr ""
+
+msgid "Timeline|Turn recent updates view off"
+msgstr ""
+
+msgid "Timeline|Turn recent updates view on"
+msgstr ""
+
+msgid "Timelog doesn't exist or you don't have permission to delete it"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout connecting to the Google API. Please try again."
+msgstr ""
+
+msgid "Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout."
+msgstr ""
+
+msgid "Timeout for most Gitaly operations (in seconds)."
+msgstr ""
+
+msgid "Timeout for the fastest Gitaly operations (in seconds)."
+msgstr ""
+
+msgid "Timezone"
+msgstr ""
+
+msgid "Time|A"
+msgstr ""
+
+msgid "Time|AM"
+msgstr ""
+
+msgid "Time|P"
+msgstr ""
+
+msgid "Time|PM"
+msgstr ""
+
+msgid "Time|a"
+msgstr ""
+
+msgid "Time|am"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|p"
+msgstr ""
+
+msgid "Time|pm"
+msgstr ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip: Hover over a job to see the jobs it depends on to run."
+msgstr ""
+
+msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Title (required)"
+msgstr ""
+
+msgid "Title:"
+msgstr ""
+
+msgid "Titles and Descriptions"
+msgstr ""
+
+msgid "To"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
+
+msgid "To Do"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To activate your trial, we need additional details from you."
+msgstr ""
+
+msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
+msgid "To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+msgid "To complete registration, we need additional details from you."
+msgstr ""
+
+msgid "To confirm, type %{phrase_code}"
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To continue using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
+msgid "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}"
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
+msgid "To enable Registration Features, first enable Service Ping."
+msgstr ""
+
+msgid "To ensure %{project_link} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
+msgstr ""
+
+msgid "To ensure %{project_name} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
+msgstr ""
+
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
+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 ""
+
+msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
+msgstr ""
+
+msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To get started, use the link below to confirm your account."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To learn more about this project, read %{link_to_wiki}"
+msgstr ""
+
+msgid "To manage seats for all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
+msgstr ""
+
+msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
+
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you"
+msgstr ""
+
+msgid "To preserve performance only %{strongStart}%{visible} of %{total}%{strongEnd} files are displayed."
+msgstr ""
+
+msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, %{linkStart}fork this project%{linkEnd} and set the fork's visibility to private."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, a private fork of this project was selected."
+msgstr ""
+
+msgid "To reactivate your account, %{gitlab_link_start}sign in to GitLab.%{link_end}"
+msgstr ""
+
+msgid "To reactivate your account, sign in to GitLab at %{gitlab_url}."
+msgstr ""
+
+msgid "To resolve this, try to:"
+msgstr ""
+
+msgid "To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings."
+msgstr ""
+
+msgid "To see all the user's personal access tokens you must impersonate them first."
+msgstr ""
+
+msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Premium%{linkEnd}. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To 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 ""
+
+msgid "To set up this integration:"
+msgstr ""
+
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
+msgid "To start using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
+msgstr ""
+
+msgid "To unsubscribe from this issue, please paste the following link into your browser:"
+msgstr ""
+
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
+msgid "To use 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 ""
+
+msgid "To view usage, refresh this page in a few minutes."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters above."
+msgstr ""
+
+msgid "To-Do List"
+msgstr ""
+
+msgid "To-do item successfully marked as done."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todos count"
+msgstr ""
+
+msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
+msgstr ""
+
+msgid "Todos|Filter by author"
+msgstr ""
+
+msgid "Todos|Filter by group"
+msgstr ""
+
+msgid "Todos|Filter by project"
+msgstr ""
+
+msgid "Todos|Give yourself a pat on the back!"
+msgstr ""
+
+msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
+msgstr ""
+
+msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
+msgstr ""
+
+msgid "Todos|Isn't an empty To-Do List beautiful?"
+msgstr ""
+
+msgid "Todos|It's how you always know what to work on next."
+msgstr ""
+
+msgid "Todos|Mark all as done"
+msgstr ""
+
+msgid "Todos|Nothing is on your to-do list. Nice work!"
+msgstr ""
+
+msgid "Todos|Nothing left to do. High five!"
+msgstr ""
+
+msgid "Todos|Undo mark all as done"
+msgstr ""
+
+msgid "Todos|When an issue or merge request is assigned to you, or when you receive a %{strongStart}@mention%{strongEnd} in a comment, this automatically triggers a new item in your To-Do List."
+msgstr ""
+
+msgid "Todos|You're all done!"
+msgstr ""
+
+msgid "Todos|Your To-Do List shows what to work on next"
+msgstr ""
+
+msgid "Toggle GitLab Next"
+msgstr ""
+
+msgid "Toggle Markdown preview"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle backtrace"
+msgstr ""
+
+msgid "Toggle collapse"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle emoji award"
+msgstr ""
+
+msgid "Toggle focus mode"
+msgstr ""
+
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle project select"
+msgstr ""
+
+msgid "Toggle shortcuts"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "Toggle the Performance Bar"
+msgstr ""
+
+msgid "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Token Access"
+msgstr ""
+
+msgid "Token name"
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tokens|Scopes set the permission levels granted to the token."
+msgstr ""
+
+msgid "Tokens|Select scopes"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
+
+msgid "Too many references. Quick actions are limited to at most %{max_count} user references"
+msgstr ""
+
+msgid "Too many users found. Quick actions are limited to at most %{max_count} users"
+msgstr ""
+
+msgid "TopNav|Explore"
+msgstr ""
+
+msgid "TopNav|Go back"
+msgstr ""
+
+msgid "TopNav|Switch to"
+msgstr ""
+
+msgid "TopNav|Your dashboards"
+msgstr ""
+
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic %{topic_name} was successfully removed."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic avatar for %{name} will be removed. This cannot be undone."
+msgstr ""
+
+msgid "Topic slug (name)"
+msgstr ""
+
+msgid "Topic title"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "TopicSelect|No matching results"
+msgstr ""
+
+msgid "TopicSelect|Search topics"
+msgstr ""
+
+msgid "TopicSelect|Select a topic"
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
+msgid "Topics could not be merged!"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Score"
+msgstr ""
+
+msgid "Total artifacts size: %{total_size}"
+msgstr ""
+
+msgid "Total cores (CPUs)"
+msgstr ""
+
+msgid "Total issue weight"
+msgstr ""
+
+msgid "Total memory (GB)"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total users"
+msgstr ""
+
+msgid "Total weight"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "TotalMilestonesIndicator|1000+"
+msgstr ""
+
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track important events in your GitLab instance."
+msgstr ""
+
+msgid "Track important events in your group."
+msgstr ""
+
+msgid "Track important events in your project."
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Training mode"
+msgstr ""
+
+msgid "Transfer"
+msgstr ""
+
+msgid "Transfer group to another parent group."
+msgstr ""
+
+msgid "Transfer ownership"
+msgstr ""
+
+msgid "Transfer project"
+msgstr ""
+
+msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "TransferGroup|Cannot transfer group to one of its subgroup."
+msgstr ""
+
+msgid "TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group contains contacts/organizations and you don't have enough permissions to move them to the new root group."
+msgstr ""
+
+msgid "TransferGroup|Group contains projects with NPM packages."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project is already in this namespace."
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
+msgstr ""
+
+msgid "TransferProject|You don't have permission to transfer projects into that namespace."
+msgstr ""
+
+msgid "TransferProject|You don't have permission to transfer this project."
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trials|%{planName} Trial"
+msgstr ""
+
+msgid "Trials|Compare all plans"
+msgstr ""
+
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
+msgstr ""
+
+msgid "Trials|Day %{daysUsed}/%{duration}"
+msgstr ""
+
+msgid "Trials|Go back to GitLab"
+msgstr ""
+
+msgid "Trials|Skip Trial"
+msgstr ""
+
+msgid "Trials|Upgrade %{groupName} to %{planName}"
+msgstr ""
+
+msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group or an existing group."
+msgstr ""
+
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
+msgstr ""
+
+msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
+msgid "Trial|Continue"
+msgstr ""
+
+msgid "Trial|Dismiss"
+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 ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions."
+msgstr ""
+
+msgid "Trigger cluster reindexing"
+msgstr ""
+
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
+msgstr ""
+
+msgid "Trigger job"
+msgstr ""
+
+msgid "Trigger manual job"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated in the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load. %{strong_start}CI will run using the credentials assigned above.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Trigger removed."
+msgstr ""
+
+msgid "Trigger repository check"
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Trigger was created successfully."
+msgstr ""
+
+msgid "Trigger was successfully updated."
+msgstr ""
+
+msgid "Triggerer"
+msgstr ""
+
+msgid "Trigger|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Trigger|invalid"
+msgstr ""
+
+msgid "Trusted"
+msgstr ""
+
+msgid "Trusted applications are automatically authorized on GitLab OAuth flow. It's highly recommended for the security of users that trusted applications have the confidential setting set to true."
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab features for free for 30 days. No credit card required."
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Try changing or removing filters."
+msgstr ""
+
+msgid "Try grouping with different labels"
+msgstr ""
+
+msgid "Try logging in using your username or email. If you have forgotten your password, try recovering it"
+msgstr ""
+
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
+msgid "Try to fork again"
+msgstr ""
+
+msgid "Try to keep the first line under 52 characters and the others under 72."
+msgstr ""
+
+msgid "Try using a different search term to find the file you are looking for."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if needed) and press the button on the device now."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Tue"
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Turn off"
+msgstr ""
+
+msgid "Turn on"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Twitter:"
+msgstr ""
+
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-Factor Authentication code"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
+msgid "Two-factor Authentication:"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication grace period"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
+msgid "Two-factor grace period"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Type to search"
+msgstr ""
+
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
+msgid "URL is required"
+msgstr ""
+
+msgid "URL is triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "URL is triggered when a merge request is created, updated, or merged"
+msgstr ""
+
+msgid "URL is triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "URL is triggered when repository is updated"
+msgstr ""
+
+msgid "URL must be percent-encoded if necessary."
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage to serve the repository static objects."
+msgstr ""
+
+msgid "URL or request ID"
+msgstr ""
+
+msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER %{user} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER WILL BE BLOCKED! Are you sure?"
+msgstr ""
+
+msgid "UTC"
+msgstr ""
+
+msgid "Unable to apply suggestions to a deleted line."
+msgstr ""
+
+msgid "Unable to build Slack link."
+msgstr ""
+
+msgid "Unable to collect CPU info"
+msgstr ""
+
+msgid "Unable to collect memory info"
+msgstr ""
+
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
+msgid "Unable to connect to server: %{error}"
+msgstr ""
+
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
+msgid "Unable to create link to vulnerability"
+msgstr ""
+
+msgid "Unable to fetch branch list for this project."
+msgstr ""
+
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
+msgid "Unable to find Jira project to import data from."
+msgstr ""
+
+msgid "Unable to fully load the default commit message. You can still apply this suggestion and the commit message will be correct."
+msgstr ""
+
+msgid "Unable to generate new instance ID"
+msgstr ""
+
+msgid "Unable to load commits. Try again later."
+msgstr ""
+
+msgid "Unable to load file contents. Try again later."
+msgstr ""
+
+msgid "Unable to load refs"
+msgstr ""
+
+msgid "Unable to load the diff"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to load the merge request widget. Try reloading the page."
+msgstr ""
+
+msgid "Unable to parse JSON"
+msgstr ""
+
+msgid "Unable to parse the vulnerability report's options."
+msgstr ""
+
+msgid "Unable to save iteration. Please try again"
+msgstr ""
+
+msgid "Unable to save your changes. Please try again."
+msgstr ""
+
+msgid "Unable to save your preference"
+msgstr ""
+
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to suggest a path. Please refresh and try again."
+msgstr ""
+
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
+msgid "Unable to verify the user"
+msgstr ""
+
+msgid "Unapprove a merge request"
+msgstr ""
+
+msgid "Unapprove the current merge request."
+msgstr ""
+
+msgid "Unapproved the current merge request."
+msgstr ""
+
+msgid "Unarchive project"
+msgstr ""
+
+msgid "Unarchiving the project restores its members' ability to make commits, and create issues, comments, and other entities. %{strong_start}After you unarchive the project, it displays in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Unassign from commenting user"
+msgstr ""
+
+msgid "Unassigned"
+msgstr ""
+
+msgid "Unauthenticated API rate limit period in seconds"
+msgstr ""
+
+msgid "Unauthenticated requests"
+msgstr ""
+
+msgid "Unauthenticated web rate limit period in seconds"
+msgstr ""
+
+msgid "Unban"
+msgstr ""
+
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Undo Ignore"
+msgstr ""
+
+msgid "Undo ignore"
+msgstr ""
+
+msgid "Unexpected error"
+msgstr ""
+
+msgid "Unfollow"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Unhappy?"
+msgstr ""
+
+msgid "Units|ms"
+msgstr ""
+
+msgid "Units|s"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unknown Error"
+msgstr ""
+
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
+msgid "Unknown user"
+msgstr ""
+
+msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
+msgstr ""
+
+msgid "Unlimited"
+msgstr ""
+
+msgid "Unlink"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock account"
+msgstr ""
+
+msgid "Unlock merge request"
+msgstr ""
+
+msgid "Unlock more features with GitLab Ultimate"
+msgstr ""
+
+msgid "Unlock the discussion"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unlocked the discussion."
+msgstr ""
+
+msgid "Unlocks the discussion."
+msgstr ""
+
+msgid "Unreachable"
+msgstr ""
+
+msgid "Unrecognized approval status."
+msgstr ""
+
+msgid "Unrecognized cluster type"
+msgstr ""
+
+msgid "Unresolve"
+msgstr ""
+
+msgid "Unresolve thread"
+msgstr ""
+
+msgid "Unresolved"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unstarted"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unsubscribed from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsubscribes from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsupported sort value."
+msgstr ""
+
+msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
+msgstr ""
+
+msgid "Unused"
+msgstr ""
+
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Upcoming Release"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update %{sourcePath} file"
+msgstr ""
+
+msgid "Update Now"
+msgstr ""
+
+msgid "Update Scheduled…"
+msgstr ""
+
+msgid "Update all"
+msgstr ""
+
+msgid "Update appearance settings"
+msgstr ""
+
+msgid "Update approval rule"
+msgstr ""
+
+msgid "Update approvers"
+msgstr ""
+
+msgid "Update broadcast message"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update it"
+msgstr ""
+
+msgid "Update milestone"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update username"
+msgstr ""
+
+msgid "Update variable"
+msgstr ""
+
+msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
+msgstr ""
+
+msgid "Updated"
+msgstr ""
+
+msgid "Updated %{updated_at} by %{updated_by}"
+msgstr ""
+
+msgid "Updated date"
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Updating…"
+msgstr ""
+
+msgid "Upgrade offers available!"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "Upload %{file_name} file"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload File"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload could not be deleted."
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload image"
+msgstr ""
+
+msgid "Upload new file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "Uploaded date"
+msgstr ""
+
+msgid "Uploading changes to terminal"
+msgstr ""
+
+msgid "Uploading..."
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage Trends"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|%{linkTitle} help link"
+msgstr ""
+
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
+
+msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Buy storage"
+msgstr ""
+
+msgid "UsageQuota|CI minutes usage by month"
+msgstr ""
+
+msgid "UsageQuota|CI minutes usage by project"
+msgstr ""
+
+msgid "UsageQuota|CI/CD minutes usage"
+msgstr ""
+
+msgid "UsageQuota|CI/CD minutes usage since %{timeElapsed}"
+msgstr ""
+
+msgid "UsageQuota|CI/CD minutes usage since %{usageSince}"
+msgstr ""
+
+msgid "UsageQuota|Code packages and container images."
+msgstr ""
+
+msgid "UsageQuota|Container Registry"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|Dependency proxy"
+msgstr ""
+
+msgid "UsageQuota|File attachments and smaller design graphics."
+msgstr ""
+
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr ""
+
+msgid "UsageQuota|Git repository."
+msgstr ""
+
+msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
+msgstr ""
+
+msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "UsageQuota|Group settings &gt; Usage quotas"
+msgstr ""
+
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about excess storage usage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about usage quotas"
+msgstr ""
+
+msgid "UsageQuota|Learn more about usage quotas."
+msgstr ""
+
+msgid "UsageQuota|Local proxy used for frequently-accessed upstream Docker images. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "UsageQuota|Namespace storage used"
+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 ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage used"
+msgstr ""
+
+msgid "UsageQuota|Recalculate repository usage"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Seats"
+msgstr ""
+
+msgid "UsageQuota|Shared bits of code and text."
+msgstr ""
+
+msgid "UsageQuota|Shared runner duration"
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Something went wrong while fetching pipeline statistics"
+msgstr ""
+
+msgid "UsageQuota|Something went wrong while fetching project storage statistics"
+msgstr ""
+
+msgid "UsageQuota|Something went wrong while loading usage details"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|Storage type"
+msgstr ""
+
+msgid "UsageQuota|Storage used"
+msgstr ""
+
+msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "
+msgstr ""
+
+msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
+msgstr ""
+
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr ""
+
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
+msgstr ""
+
+msgid "UsageQuota|The table below shows current period usage"
+msgstr ""
+
+msgid "UsageQuota|The table below shows usage since %{timeElapsed}"
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which used shared runners in the current period"
+msgstr ""
+
+msgid "UsageQuota|This table omits projects that used 0 CI/CD minutes or 0 shared runners duration"
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Uploads"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
+msgid "UsageQuota|Usage by month"
+msgstr ""
+
+msgid "UsageQuota|Usage by project"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project"
+msgstr ""
+
+msgid "UsageQuota|Usage of resources across your projects"
+msgstr ""
+
+msgid "UsageQuota|Usage quotas help link"
+msgstr ""
+
+msgid "UsageQuota|User settings &gt; Usage quotas"
+msgstr ""
+
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "UsageQuota|Wiki content."
+msgstr ""
+
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
+msgid "UsageQuota|You used: %{usage} %{limit}"
+msgstr ""
+
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
+msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
+msgstr ""
+
+msgid "UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Groups"
+msgstr ""
+
+msgid "UsageTrends|Issues"
+msgstr ""
+
+msgid "UsageTrends|Issues & merge requests"
+msgstr ""
+
+msgid "UsageTrends|Items"
+msgstr ""
+
+msgid "UsageTrends|Merge requests"
+msgstr ""
+
+msgid "UsageTrends|Month"
+msgstr ""
+
+msgid "UsageTrends|No data available."
+msgstr ""
+
+msgid "UsageTrends|Pipelines"
+msgstr ""
+
+msgid "UsageTrends|Pipelines canceled"
+msgstr ""
+
+msgid "UsageTrends|Pipelines failed"
+msgstr ""
+
+msgid "UsageTrends|Pipelines skipped"
+msgstr ""
+
+msgid "UsageTrends|Pipelines succeeded"
+msgstr ""
+
+msgid "UsageTrends|Pipelines total"
+msgstr ""
+
+msgid "UsageTrends|Projects"
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the cancelled pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the failed pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the groups. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the issues. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the merge requests. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the projects. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the skipped pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the successful pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the total pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|Total groups"
+msgstr ""
+
+msgid "UsageTrends|Total projects"
+msgstr ""
+
+msgid "UsageTrends|Total projects & groups"
+msgstr ""
+
+msgid "UsageTrends|Users"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgstr ""
+
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
+msgid "Use GitLab Runner in AWS"
+msgstr ""
+
+msgid "Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates."
+msgstr ""
+
+msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
+msgstr ""
+
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
+msgid "Use banners and notifications to notify your users about scheduled maintenance, recent upgrades, and more."
+msgstr ""
+
+msgid "Use cURL"
+msgstr ""
+
+msgid "Use custom color #FF0000"
+msgstr ""
+
+msgid "Use double quotes for multiple keywords, such as %{code_open}\"your search\"%{code_close}"
+msgstr ""
+
+msgid "Use hashed storage"
+msgstr ""
+
+msgid "Use hashed storage paths for newly created and renamed repositories. Always enabled since 13.0. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Use issue count"
+msgstr ""
+
+msgid "Use issue weight"
+msgstr ""
+
+msgid "Use issues to collaborate on ideas, solve problems, and plan work"
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use primary email (%{email})"
+msgstr ""
+
+msgid "Use shortcuts"
+msgstr ""
+
+msgid "Use slash commands."
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
+msgid "Use the link below to confirm your email address (%{email})"
+msgstr ""
+
+msgid "Use the link below to confirm your email address."
+msgstr ""
+
+msgid "Use the public cloud instance URL (%{kroki_public_url}) or %{install_link_start}install Kroki%{install_link_end} on your own infrastructure and use your own instance URL."
+msgstr ""
+
+msgid "Use the search bar on the top of this page"
+msgstr ""
+
+msgid "Use this token to validate received payloads."
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used"
+msgstr ""
+
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises."
+msgstr ""
+
+msgid "Used programming language"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "User %{current_user_username} has started impersonating %{username}"
+msgstr ""
+
+msgid "User %{username} was successfully removed."
+msgstr ""
+
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
+msgid "User ID"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP rate limits"
+msgstr ""
+
+msgid "User cap"
+msgstr ""
+
+msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
+msgid "User does not have a pending request"
+msgstr ""
+
+msgid "User identity was successfully created."
+msgstr ""
+
+msgid "User identity was successfully removed."
+msgstr ""
+
+msgid "User identity was successfully updated."
+msgstr ""
+
+msgid "User is blocked"
+msgstr ""
+
+msgid "User is not allowed to resolve thread"
+msgstr ""
+
+msgid "User key"
+msgstr ""
+
+msgid "User key was successfully removed."
+msgstr ""
+
+msgid "User list %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "User restrictions"
+msgstr ""
+
+msgid "User settings"
+msgstr ""
+
+msgid "User was successfully created."
+msgstr ""
+
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully unbanned."
+msgstr ""
+
+msgid "User was successfully updated."
+msgstr ""
+
+msgid "User-based escalation rules must have a user with access to the project"
+msgstr ""
+
+msgid "UserAvailability|%{author} %{spanStart}(Busy)%{spanEnd}"
+msgstr ""
+
+msgid "UserAvailability|%{author} (Busy)"
+msgstr ""
+
+msgid "UserAvailability|(Busy)"
+msgstr ""
+
+msgid "UserLists|Add"
+msgstr ""
+
+msgid "UserLists|Add Users"
+msgstr ""
+
+msgid "UserLists|Add users"
+msgstr ""
+
+msgid "UserLists|Cancel"
+msgstr ""
+
+msgid "UserLists|Create"
+msgstr ""
+
+msgid "UserLists|Define a set of users to be used within feature flag strategies"
+msgstr ""
+
+msgid "UserLists|Edit"
+msgstr ""
+
+msgid "UserLists|Edit %{name}"
+msgstr ""
+
+msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
+msgstr ""
+
+msgid "UserLists|Feature flag user list"
+msgstr ""
+
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
+msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
+msgstr ""
+
+msgid "UserLists|Loading user lists"
+msgstr ""
+
+msgid "UserLists|Name"
+msgstr ""
+
+msgid "UserLists|New list"
+msgstr ""
+
+msgid "UserLists|New user list"
+msgstr ""
+
+msgid "UserLists|Save"
+msgstr ""
+
+msgid "UserLists|There are no users"
+msgstr ""
+
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
+msgid "UserLists|User ID"
+msgstr ""
+
+msgid "UserLists|User IDs"
+msgstr ""
+
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
+msgid "UserList|Delete %{name}?"
+msgstr ""
+
+msgid "UserList|created %{timeago}"
+msgstr ""
+
+msgid "UserProfile|(Busy)"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Blocked user"
+msgstr ""
+
+msgid "UserProfile|Bot activity"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Followers"
+msgstr ""
+
+msgid "UserProfile|Following"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Pronounced as: %{pronunciation}"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Retry"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Star projects to track their progress and show your appreciation."
+msgstr ""
+
+msgid "UserProfile|Starred projects"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any followers."
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|This user hasn't starred any projects"
+msgstr ""
+
+msgid "UserProfile|This user is blocked"
+msgstr ""
+
+msgid "UserProfile|This user isn't following other users."
+msgstr ""
+
+msgid "UserProfile|Unconfirmed user"
+msgstr ""
+
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You are not following other users."
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You do not have any followers."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "UserProfile|at"
+msgstr ""
+
+msgid "UserProfile|made a private contribution"
+msgstr ""
+
+msgid "Username"
+msgstr ""
+
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
+msgid "Username or email"
+msgstr ""
+
+msgid "Username:"
+msgstr ""
+
+msgid "Username: %{username}"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users API rate limit"
+msgstr ""
+
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
+msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
+msgstr ""
+
+msgid "Users can request access (if visibility is public or internal)"
+msgstr ""
+
+msgid "Users cannot be added to projects in this group"
+msgstr ""
+
+msgid "Users in License"
+msgstr ""
+
+msgid "Users or groups set as approvers in the project's or merge request's settings."
+msgstr ""
+
+msgid "Users over License"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Users to exclude from the rate limit"
+msgstr ""
+
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr ""
+
+msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
+msgstr ""
+
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
+msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
+msgstr ""
+
+msgid "Valid From"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
+msgid "Validations failed."
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Value Stream Analytics"
+msgstr ""
+
+msgid "Value Stream Analytics can help you determine your team’s velocity"
+msgstr ""
+
+msgid "Value might contain a variable reference"
+msgstr ""
+
+msgid "Value stream"
+msgstr ""
+
+msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{stageCount}+ items"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Average number of deployments to production per day."
+msgstr ""
+
+msgid "ValueStreamAnalytics|DORA metrics"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Key metrics"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time an incident was open on a production environment in the given time period."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+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 ""
+
+msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Number of new issues created."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Tasks by type"
+msgstr ""
+
+msgid "ValueStreamAnalytics|There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Total number of deploys to production."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Value stream"
+msgstr ""
+
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
+msgid "ValueStreamEvent|Stage time (median)"
+msgstr ""
+
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
+msgid "Values that contain the %{codeStart}$%{codeEnd} character can be considered a variable reference and expanded. %{docsLinkStart}Learn more.%{docsLinkEnd}"
+msgstr ""
+
+msgid "Variable"
+msgstr ""
+
+msgid "Variable will be masked in job logs."
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables can be:"
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts."
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity."
+msgstr ""
+
+msgid "VerificationReminder|Until then, shared runners will be 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 CI/CD minutes on shared runners."
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Verify SAML Configuration"
+msgstr ""
+
+msgid "Verify code"
+msgstr ""
+
+msgid "Verify configuration"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "Version %{report_version} for report type %{report_type} has been deprecated, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to parse and ingest this report if valid."
+msgstr ""
+
+msgid "Version %{report_version} for report type %{report_type} is unsupported, supported versions for this report type are: %{supported_schema_versions}. GitLab will attempt to validate this report against the earliest supported versions of this report type, to show all the errors but will not ingest the report"
+msgstr ""
+
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
+msgid "VersionCheck|Up to date"
+msgstr ""
+
+msgid "VersionCheck|Update ASAP"
+msgstr ""
+
+msgid "VersionCheck|Update available"
+msgstr ""
+
+msgid "VersionCheck|Your GitLab Version"
+msgstr ""
+
+msgid "View Stage: %{title}"
+msgstr ""
+
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
+msgid "View all environments."
+msgstr ""
+
+msgid "View all groups"
+msgstr ""
+
+msgid "View all issues"
+msgstr ""
+
+msgid "View all projects"
+msgstr ""
+
+msgid "View blame"
+msgstr ""
+
+msgid "View blame prior to this change"
+msgstr ""
+
+msgid "View card matches"
+msgstr ""
+
+msgid "View chart"
+msgid_plural "View charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View dependency details for your project"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View eligible approvers"
+msgstr ""
+
+msgid "View entire blame"
+msgstr ""
+
+msgid "View exposed artifact"
+msgid_plural "View %d exposed artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View file @ %{commitSha}"
+msgstr ""
+
+msgid "View full dashboard"
+msgstr ""
+
+msgid "View full log"
+msgstr ""
+
+msgid "View group in admin area"
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View group pipeline usage quota"
+msgstr ""
+
+msgid "View incident details at"
+msgstr ""
+
+msgid "View incident details."
+msgstr ""
+
+msgid "View incident issues."
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View issues"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View job"
+msgstr ""
+
+msgid "View job log"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View logs"
+msgstr ""
+
+msgid "View milestones"
+msgstr ""
+
+msgid "View on %{url}"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View page @ "
+msgstr ""
+
+msgid "View performance dashboard."
+msgstr ""
+
+msgid "View project"
+msgstr ""
+
+msgid "View project in admin area"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View public GPG key"
+msgid_plural "View public GPG keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View seat usage"
+msgstr ""
+
+msgid "View supported languages and frameworks"
+msgstr ""
+
+msgid "View the %{code_open}last_activity_at%{code_close} attribute for %{project_link} using the %{projects_api_link}."
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "View the latest successful deployment to this environment"
+msgstr ""
+
+msgid "View the performance dashboard at"
+msgstr ""
+
+msgid "View usage details"
+msgstr ""
+
+msgid "View users statistics"
+msgstr ""
+
+msgid "Viewed"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Viewing projects and designs data from a primary site is not possible when using a unified URL. Visit the secondary site directly. %{geo_help_url}"
+msgstr ""
+
+msgid "Violation"
+msgstr ""
+
+msgid "Visibility"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Visibility, project features, permissions"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Visual Studio Code (HTTPS)"
+msgstr ""
+
+msgid "Visual Studio Code (SSH)"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability report"
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "VulnerabilityChart|%{formattedStartDate} to today"
+msgstr ""
+
+msgid "VulnerabilityChart|Severity"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|(optional) Include the solution to the vulnerability if available."
+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 ""
+
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
+msgstr ""
+
+msgid "VulnerabilityManagement|Create Jira issue"
+msgstr ""
+
+msgid "VulnerabilityManagement|Enter a name"
+msgstr ""
+
+msgid "VulnerabilityManagement|Enter the CVE or CWE code"
+msgstr ""
+
+msgid "VulnerabilityManagement|Enter the CVE or CWE identifier URL"
+msgstr ""
+
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Identifier code and URL are required fields"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
+
+msgid "VulnerabilityManagement|Name is a required field"
+msgstr ""
+
+msgid "VulnerabilityManagement|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityManagement|Read more about related issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Related Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a method"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a severity level"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Severity is a required field"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while creating vulnerability"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to fetch related Jira issues. Please check the %{linkStart}Jira integration settings%{linkEnd} and try again."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not get user."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
+msgstr ""
+
+msgid "VulnerabilityManagement|Status is a required field"
+msgstr ""
+
+msgid "VulnerabilityManagement|Submit vulnerability"
+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 ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All statuses"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Resolved"
+msgstr ""
+
+msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
+msgstr ""
+
+msgid "Vulnerability|Activity"
+msgstr ""
+
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
+msgid "Vulnerability|Actual received response is the one received when this fault was detected"
+msgstr ""
+
+msgid "Vulnerability|Add another identifier"
+msgstr ""
+
+msgid "Vulnerability|Additional Info"
+msgstr ""
+
+msgid "Vulnerability|Bug Bounty"
+msgstr ""
+
+msgid "Vulnerability|CVSS v3"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Cluster"
+msgstr ""
+
+msgid "Vulnerability|Code Review"
+msgstr ""
+
+msgid "Vulnerability|Comments"
+msgstr ""
+
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|Details"
+msgstr ""
+
+msgid "Vulnerability|Detected"
+msgstr ""
+
+msgid "Vulnerability|Detection method"
+msgstr ""
+
+msgid "Vulnerability|Download"
+msgstr ""
+
+msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
+msgstr ""
+
+msgid "Vulnerability|Evidence"
+msgstr ""
+
+msgid "Vulnerability|External Security Report"
+msgstr ""
+
+msgid "Vulnerability|False positive detected"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|File:"
+msgstr ""
+
+msgid "Vulnerability|GitLab Security Report"
+msgstr ""
+
+msgid "Vulnerability|Identifier"
+msgstr ""
+
+msgid "Vulnerability|Identifier URL"
+msgstr ""
+
+msgid "Vulnerability|Identifier code"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Image"
+msgstr ""
+
+msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Location"
+msgstr ""
+
+msgid "Vulnerability|Method"
+msgstr ""
+
+msgid "Vulnerability|Namespace"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Project:"
+msgstr ""
+
+msgid "Vulnerability|Remove identifier row"
+msgstr ""
+
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
+msgid "Vulnerability|Request/Response"
+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 ""
+
+msgid "Vulnerability|Severity:"
+msgstr ""
+
+msgid "Vulnerability|Status"
+msgstr ""
+
+msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
+msgstr ""
+
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
+msgid "Vulnerability|Tool"
+msgstr ""
+
+msgid "Vulnerability|Tool:"
+msgstr ""
+
+msgid "Vulnerability|Training"
+msgstr ""
+
+msgid "Vulnerability|Training not available for this vulnerability."
+msgstr ""
+
+msgid "Vulnerability|Unmodified Response"
+msgstr ""
+
+msgid "Vulnerability|View training"
+msgstr ""
+
+msgid "WARNING:"
+msgstr ""
+
+msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
+msgstr ""
+
+msgid "Wait for the file to load to copy its contents"
+msgstr ""
+
+msgid "Waiting for approval"
+msgstr ""
+
+msgid "Waiting for merge (open and assigned)"
+msgstr ""
+
+msgid "Waiting for performance data"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "Warning"
+msgstr ""
+
+msgid "Warning:"
+msgstr ""
+
+msgid "Warning: Displaying this diagram might cause performance issues on this page."
+msgstr ""
+
+msgid "Warning: Synchronizing LDAP removes direct members' access."
+msgstr ""
+
+msgid "Watch how"
+msgstr ""
+
+msgid "We also use email for avatar detection if no avatar is uploaded."
+msgstr ""
+
+msgid "We are currently unable to fetch data for the pipeline header."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this graph."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
+msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
+msgstr ""
+
+msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We have found the following errors:"
+msgstr ""
+
+msgid "We heard back from your device. You have been authenticated."
+msgstr ""
+
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
+msgstr ""
+
+msgid "We recommend a work email address."
+msgstr ""
+
+msgid "We recommend leaving all SAST analyzers enabled"
+msgstr ""
+
+msgid "We recommend that you buy additional Pipeline minutes to avoid any interruption of service."
+msgstr ""
+
+msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
+msgstr ""
+
+msgid "We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device."
+msgstr ""
+
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "We want to let you know %{username} has been banned from %{scope} due to them downloading more than %{max_project_downloads} project repositories within %{within_minutes} minutes."
+msgstr ""
+
+msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
+msgstr ""
+
+msgid "We would like to inform you that your subscription GitLab Enterprise Edition %{plan_name} is nearing its user limit. You have %{active_user_count} active users, which is almost at the user limit of %{maximum_user_count}."
+msgstr ""
+
+msgid "We'll continuously validate your pipeline configuration. The validation results will appear here."
+msgstr ""
+
+msgid "We'll use this to help surface the right features and information to you."
+msgstr ""
+
+msgid "We're experiencing difficulties and this tab content is currently unavailable."
+msgstr ""
+
+msgid "We've detected some unusual activity"
+msgstr ""
+
+msgid "We've detected unusual activity"
+msgstr ""
+
+msgid "We've found no vulnerabilities"
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "WebAuthn Devices (%{length})"
+msgstr ""
+
+msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
+msgid "WebIDE|Merge request"
+msgstr ""
+
+msgid "WebIDE|Quickly and easily edit multiple files in your project."
+msgstr ""
+
+msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
+msgstr ""
+
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
+msgstr ""
+
+msgid "WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}"
+msgstr ""
+
+msgid "WebexTeamsService|Webex Teams"
+msgstr ""
+
+msgid "Webhook"
+msgstr ""
+
+msgid "Webhook Logs"
+msgstr ""
+
+msgid "Webhook Settings"
+msgstr ""
+
+msgid "Webhook events will be displayed here."
+msgstr ""
+
+msgid "Webhook:"
+msgstr ""
+
+msgid "Webhooks"
+msgstr ""
+
+msgid "Webhooks Help"
+msgstr ""
+
+msgid "Webhooks|A comment is added to a confidential issue."
+msgstr ""
+
+msgid "Webhooks|A comment is added to an issue or merge request."
+msgstr ""
+
+msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
+msgstr ""
+
+msgid "Webhooks|A feature flag is turned on or off."
+msgstr ""
+
+msgid "Webhooks|A group member is created, updated, or removed."
+msgstr ""
+
+msgid "Webhooks|A job's status changes."
+msgstr ""
+
+msgid "Webhooks|A merge request is created, updated, or merged."
+msgstr ""
+
+msgid "Webhooks|A new tag is pushed to the repository."
+msgstr ""
+
+msgid "Webhooks|A pipeline's status changes."
+msgstr ""
+
+msgid "Webhooks|A release is created or updated."
+msgstr ""
+
+msgid "Webhooks|A subgroup is created or removed."
+msgstr ""
+
+msgid "Webhooks|A webhook in this project was automatically disabled after being retried multiple times."
+msgstr ""
+
+msgid "Webhooks|A wiki page is created or updated."
+msgstr ""
+
+msgid "Webhooks|An issue is created, updated, closed, or reopened."
+msgstr ""
+
+msgid "Webhooks|Are you sure you want to delete this group hook?"
+msgstr ""
+
+msgid "Webhooks|Are you sure you want to delete this project hook?"
+msgstr ""
+
+msgid "Webhooks|Are you sure you want to delete this webhook?"
+msgstr ""
+
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential comments"
+msgstr ""
+
+msgid "Webhooks|Confidential issues events"
+msgstr ""
+
+msgid "Webhooks|Delete webhook"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+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 ""
+
+msgid "Webhooks|Go to webhooks"
+msgstr ""
+
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
+msgid "Webhooks|Member events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|Push to the repository."
+msgstr ""
+
+msgid "Webhooks|Releases events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret token"
+msgstr ""
+
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
+msgid "Webhooks|Subgroup events"
+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 ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
+msgstr ""
+
+msgid "Webhooks|URL preview"
+msgstr ""
+
+msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
+msgstr ""
+
+msgid "Webhooks|Webhook disabled"
+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 ""
+
+msgid "Website"
+msgstr ""
+
+msgid "Website:"
+msgstr ""
+
+msgid "Wed"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Weekday"
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
+msgstr ""
+
+msgid "Welcome to GitLab"
+msgstr ""
+
+msgid "Welcome to GitLab, %{first_name}!"
+msgstr ""
+
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
+msgid "Welcome, %{name}!"
+msgstr ""
+
+msgid "What are CI/CD minutes?"
+msgstr ""
+
+msgid "What are group audit events?"
+msgstr ""
+
+msgid "What are instance audit events?"
+msgstr ""
+
+msgid "What are project audit events?"
+msgstr ""
+
+msgid "What are some examples?"
+msgstr ""
+
+msgid "What does the setting affect?"
+msgstr ""
+
+msgid "What does this command do?"
+msgstr ""
+
+msgid "What is GitLab Runner?"
+msgstr ""
+
+msgid "What is Markdown?"
+msgstr ""
+
+msgid "What is listed here?"
+msgstr ""
+
+msgid "What is repository mirroring?"
+msgstr ""
+
+msgid "What is squashing?"
+msgstr ""
+
+msgid "What templates can I create?"
+msgstr ""
+
+msgid "What will you use this group for?"
+msgstr ""
+
+msgid "What would you like to do?"
+msgstr ""
+
+msgid "What's new"
+msgstr ""
+
+msgid "When a deployment job is successful, skip older deployment jobs that are still pending."
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
+msgid "When enabled, cleanup polices execute faster but put more load on Redis."
+msgstr ""
+
+msgid "When enabled, existing access tokens may be revoked. Leave blank for no limit."
+msgstr ""
+
+msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
+msgstr ""
+
+msgid "When merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
+msgid "When this merge request is accepted"
+msgid_plural "When these merge requests are accepted"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When you transfer your project to a group, you can easily manage multiple projects, view usage quotas for storage, pipeline minutes, and users, and start a trial or upgrade to a paid tier."
+msgstr ""
+
+msgid "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seat. %{free_user_limit} seat will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
+msgid_plural "When your trial ends, you'll move to the Free tier, which has a limit of %{free_user_limit} seats. %{free_user_limit} seats will remain active, and members not occupying a seat will have the %{link_start}Over limit status%{link_end} and lose access to this group."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "When:"
+msgstr ""
+
+msgid "Which API requests are affected?"
+msgstr ""
+
+msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Who can approve?"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Who will be using GitLab?"
+msgstr ""
+
+msgid "Who will be using this GitLab subscription?"
+msgstr ""
+
+msgid "Who will be using this GitLab trial?"
+msgstr ""
+
+msgid "Who will be using this group?"
+msgstr ""
+
+msgid "Why are you signing up? (optional)"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "Wiki page"
+msgstr ""
+
+msgid "Wiki page was successfully created."
+msgstr ""
+
+msgid "Wiki page was successfully deleted."
+msgstr ""
+
+msgid "Wiki page was successfully updated."
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Confluence is enabled"
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Enable the Confluence Wiki integration"
+msgstr ""
+
+msgid "WikiEmpty|Go to Confluence"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your group"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This group has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a group member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPage|Cancel"
+msgstr ""
+
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Learn more."
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Save changes"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wikis"
+msgstr ""
+
+msgid "Wiki|Create New Page"
+msgstr ""
+
+msgid "Wiki|Created date"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
+msgstr ""
+
+msgid "Wiki|Title"
+msgstr ""
+
+msgid "Wiki|View All Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will be created"
+msgstr ""
+
+msgid "Will be mapped to"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "Wireframe"
+msgstr ""
+
+msgid "With requirements, you can set criteria to check your products against."
+msgstr ""
+
+msgid "With test cases, you can define conditions for your project to meet in determining quality"
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Won't fix / Accept risk"
+msgstr ""
+
+msgid "Work in progress (open and unassigned)"
+msgstr ""
+
+msgid "Work in progress Limit"
+msgstr ""
+
+msgid "WorkItem|%{workItemType} deleted"
+msgstr ""
+
+msgid "WorkItem|Add"
+msgstr ""
+
+msgid "WorkItem|Add a title"
+msgstr ""
+
+msgid "WorkItem|Add assignee"
+msgstr ""
+
+msgid "WorkItem|Add assignees"
+msgstr ""
+
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
+msgid "WorkItem|Add task"
+msgstr ""
+
+msgid "WorkItem|Are you sure you want to cancel editing?"
+msgstr ""
+
+msgid "WorkItem|Are you sure you want to delete the %{workItemType}? This action cannot be reversed."
+msgstr ""
+
+msgid "WorkItem|Assignee"
+msgid_plural "WorkItem|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "WorkItem|Cancel"
+msgstr ""
+
+msgid "WorkItem|Child removed"
+msgstr ""
+
+msgid "WorkItem|Closed"
+msgstr ""
+
+msgid "WorkItem|Collapse tasks"
+msgstr ""
+
+msgid "WorkItem|Create task"
+msgstr ""
+
+msgid "WorkItem|Create work item"
+msgstr ""
+
+msgid "WorkItem|Dates"
+msgstr ""
+
+msgid "WorkItem|Delete %{workItemType}"
+msgstr ""
+
+msgid "WorkItem|Due date"
+msgstr ""
+
+msgid "WorkItem|Expand tasks"
+msgstr ""
+
+msgid "WorkItem|Incident"
+msgstr ""
+
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Issue"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks."
+msgstr ""
+
+msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
+msgstr ""
+
+msgid "WorkItem|None"
+msgstr ""
+
+msgid "WorkItem|Only project members with at least the Reporter role, the author, and assignees can view or be notified about this task."
+msgstr ""
+
+msgid "WorkItem|Open"
+msgstr ""
+
+msgid "WorkItem|Remove"
+msgstr ""
+
+msgid "WorkItem|Requirements"
+msgstr ""
+
+msgid "WorkItem|Select type"
+msgstr ""
+
+msgid "WorkItem|Something went wrong when creating %{workItemType}. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when deleting the %{workItemType}. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when fetching work item types. Please try again"
+msgstr ""
+
+msgid "WorkItem|Something went wrong when trying to add a child. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong while updating the %{workItemType}. Please try again."
+msgstr ""
+
+msgid "WorkItem|Something went wrong while updating the work item. Please try again."
+msgstr ""
+
+msgid "WorkItem|Start date"
+msgstr ""
+
+msgid "WorkItem|Task"
+msgstr ""
+
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Tasks"
+msgstr ""
+
+msgid "WorkItem|Test case"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
+msgid "WorkItem|Undo"
+msgstr ""
+
+msgid "WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}"
+msgstr ""
+
+msgid "WorkItem|Work Items"
+msgstr ""
+
+msgid "WorkItem|Work item"
+msgstr ""
+
+msgid "Would you like to create a new branch?"
+msgstr ""
+
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write a comment…"
+msgstr ""
+
+msgid "Write a description or drag your files here…"
+msgstr ""
+
+msgid "Write a description…"
+msgstr ""
+
+msgid "Write an internal note or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Write your release notes or drag your files here…"
+msgstr ""
+
+msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
+msgstr ""
+
+msgid "Xcode"
+msgstr ""
+
+msgid "YYYY-MM-DD"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes or No"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, close issue"
+msgstr ""
+
+msgid "Yes, delete project"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You already have pending todo for this alert"
+msgstr ""
+
+msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
+msgstr ""
+
+msgid "You are about to clear %{count} image from the cache. Once you confirm, the next time a pipeline runs it must pull an image or tag from Docker Hub. Are you sure?"
+msgid_plural "You are about to clear %{count} images from the cache. Once you confirm, the next time a pipeline runs it must pull an image or tag from Docker Hub. Are you sure?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "You are about to delete this forked project containing:"
+msgstr ""
+
+msgid "You are about to delete this project containing:"
+msgstr ""
+
+msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
+msgstr ""
+
+msgid "You are already a member of this %{member_source}."
+msgstr ""
+
+msgid "You are already impersonating another user"
+msgstr ""
+
+msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
+msgstr ""
+
+msgid "You are connected to the Prometheus server, but there is currently no data to display."
+msgstr ""
+
+msgid "You are currently offline, or the GitLab instance is not reachable."
+msgstr ""
+
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{group_name}. This will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on confidentiality. Only %{context} members with %{strongStart}%{permissions}%{strongEnd} can view or be notified about this %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to %{action} a user"
+msgstr ""
+
+msgid "You are not allowed to approve a user"
+msgstr ""
+
+msgid "You are not allowed to log in using password"
+msgstr ""
+
+msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
+msgstr ""
+
+msgid "You are not allowed to reject a user"
+msgstr ""
+
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
+msgid "You are not authorized to delete this site profile"
+msgstr ""
+
+msgid "You are not authorized to perform this action"
+msgstr ""
+
+msgid "You are not authorized to run this manual job"
+msgstr ""
+
+msgid "You are not authorized to update this profile"
+msgstr ""
+
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
+msgid "You are not authorized to upload metric images"
+msgstr ""
+
+msgid "You are now impersonating %{username}"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You are signed in to GitLab as:"
+msgstr ""
+
+msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
+msgstr ""
+
+msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
+msgstr ""
+
+msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
+msgstr ""
+
+msgid "You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
+msgstr ""
+
+msgid "You can adjust rules on auto-banning %{link_start}here%{link_end}."
+msgstr ""
+
+msgid "You can adjust rules on auto-banning here: %{url}."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
+msgstr ""
+
+msgid "You can also upload existing files from your computer using the instructions below."
+msgstr ""
+
+msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "You can also use project access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "You can always change your URL later"
+msgstr ""
+
+msgid "You can always edit this later"
+msgstr ""
+
+msgid "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} member has %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} member who maintains access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} member. The remaining members will get a status of Over limit and lose access to the group."
+msgid_plural "You can begin moving members in %{namespace_name} now. A member loses access to the group when you turn off %{strong_start}In a seat%{strong_end}. If over %{free_user_limit} members have %{strong_start}In a seat%{strong_end} enabled after October 19, 2022, we'll select the %{free_user_limit} members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach %{free_user_limit} members. The remaining members will get a status of Over limit and lose access to the group."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
+msgstr ""
+
+msgid "You can check it in your in your personal access tokens settings %{pat_link}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
+msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}."
+msgstr ""
+
+msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service."
+msgstr ""
+
+msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
+msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
+msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
+msgstr ""
+
+msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
+msgstr ""
+
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
+msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
+
+msgid "You can invite another group to %{project_name}."
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can notify the app / group or a project by sending them an email notification"
+msgstr ""
+
+msgid "You can now close this window."
+msgstr ""
+
+msgid "You can now export your security dashboard to a CSV report."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original branch."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original project."
+msgstr ""
+
+msgid "You can only %{action} files when you are on a branch"
+msgstr ""
+
+msgid "You can only 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 transfer the project to namespaces you manage."
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can see your chat accounts."
+msgstr ""
+
+msgid "You can set up jobs to only use runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
+msgstr ""
+
+msgid "You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members. To get more members an owner of the group can start a trial or upgrade to a paid tier."
+msgstr ""
+
+msgid "You cannot %{action} %{state} users."
+msgstr ""
+
+msgid "You cannot access the raw file. Please wait a minute."
+msgstr ""
+
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
+msgid "You cannot approve your own deployment."
+msgstr ""
+
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
+msgid "You cannot impersonate a blocked user"
+msgstr ""
+
+msgid "You cannot impersonate a user who cannot log in"
+msgstr ""
+
+msgid "You cannot impersonate an internal user"
+msgstr ""
+
+msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
+msgstr ""
+
+msgid "You cannot rename an environment after it's created."
+msgstr ""
+
+msgid "You cannot set yourself to awaiting"
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
+msgid "You could not create a new trigger."
+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 ""
+
+msgid "You do not have permission to run a pipeline on this branch."
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have permission to set a member awaiting"
+msgstr ""
+
+msgid "You do not have permission to update the environment."
+msgstr ""
+
+msgid "You do not have permissions to run the import."
+msgstr ""
+
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any WebAuthn devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You don't have any open merge requests"
+msgstr ""
+
+msgid "You don't have any recent searches"
+msgstr ""
+
+msgid "You don't have permission to review this deployment. Contact the project or group owner for help."
+msgstr ""
+
+msgid "You don't have permissions to create this project"
+msgstr ""
+
+msgid "You don't have sufficient permission to perform this action."
+msgstr ""
+
+msgid "You don't have the %{role} role for any groups in this instance."
+msgstr ""
+
+msgid "You don't have write access to the source branch."
+msgstr ""
+
+msgid "You don’t have access to Productivity Analytics in this group"
+msgstr ""
+
+msgid "You don’t have access to Value Stream Analytics for this group"
+msgstr ""
+
+msgid "You have %{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 ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to group %{name}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to project %{name}."
+msgstr ""
+
+msgid "You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}"
+msgstr ""
+
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
+msgid "You have been unsubscribed from this thread."
+msgstr ""
+
+msgid "You have declined the invitation to join %{title} %{name}."
+msgstr ""
+
+msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
+msgstr ""
+
+msgid "You have insufficient permissions to configure escalation policies for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to create a Todo for this alert"
+msgstr ""
+
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to create an on-call schedule for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to manage resource links for this incident"
+msgstr ""
+
+msgid "You have insufficient permissions to manage timeline events for this incident"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call rotation from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call schedule from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this Namespace Ban"
+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 ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to view shifts for this rotation"
+msgstr ""
+
+msgid "You have 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 add 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 add this license to your instance."
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have not added any approvers. Start by adding users or groups."
+msgstr ""
+
+msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
+msgstr ""
+
+msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr ""
+
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr ""
+
+msgid "You have unsaved changes"
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must be authenticated to access this path."
+msgstr ""
+
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
+msgid "You must sign in to search for specific projects."
+msgstr ""
+
+msgid "You must sign in to search for specific terms."
+msgstr ""
+
+msgid "You must solve the CAPTCHA in order to submit"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a device."
+msgstr ""
+
+msgid "You need to set terms to be enforced"
+msgstr ""
+
+msgid "You need to specify both an Access Token and a Host URL."
+msgstr ""
+
+msgid "You need to upload a GitLab project export archive (ending in .gz)."
+msgstr ""
+
+msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
+msgstr ""
+
+msgid "You see projects here when you're added to a group or project."
+msgstr ""
+
+msgid "You successfully declined the invitation"
+msgstr ""
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
+msgid "You will be removed from existing projects/groups"
+msgstr ""
+
+msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "You will first need to set up Jira Integration to use this feature."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to create new projects because you have reached your project limit."
+msgstr ""
+
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end} in %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
+msgstr ""
+
+msgid "You're at the first commit"
+msgstr ""
+
+msgid "You're at the last commit"
+msgstr ""
+
+msgid "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_label_subscriptions_link_start}Manage label subscriptions%{manage_label_subscriptions_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because of your activity on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your activity on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because you have been assigned an item on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been assigned an item on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}. %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}. %{unsubscribe_link_start}Unsubscribe%{unsubscribe_link_end} from this thread &middot; %{manage_notifications_link_start}Manage all notifications%{manage_notifications_link_end} &middot; %{help_link_start}Help%{help_link_end}"
+msgstr ""
+
+msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
+msgid "You've rejected %{user}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your %{group} membership will now expire in %{days}."
+msgstr ""
+
+msgid "Your %{host} account was signed in to from a new location"
+msgstr ""
+
+msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded."
+msgstr ""
+
+msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. If you do not renew, you will lose access to your paid features on %{strong}%{downgrades_on}%{strong_close}. After that date, you can't create issues or merge requests, or use many other features."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more details."
+msgstr ""
+
+msgid "Your CSV export has started. It will be emailed to %{email} when complete."
+msgstr ""
+
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV import for project"
+msgstr ""
+
+msgid "Your Chain of Custody CSV export for the group %{group_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your Chain of Custody CSV export for the group %{group_name} has been added to this email as an attachment."
+msgstr ""
+
+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 ""
+
+msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now."
+msgstr ""
+
+msgid "Your GitLab account request has been approved!"
+msgstr ""
+
+msgid "Your GitLab group"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your SSH key has expired"
+msgstr ""
+
+msgid "Your SSH key is expiring soon."
+msgstr ""
+
+msgid "Your SSH key was deleted"
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
+msgid "Your To-Do List"
+msgstr ""
+
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your WebAuthn device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your WebAuthn device was registered!"
+msgstr ""
+
+msgid "Your access request to the %{source_type} has been withdrawn."
+msgstr ""
+
+msgid "Your account has been deactivated"
+msgstr ""
+
+msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
+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 ""
+
+msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
+msgstr ""
+
+msgid "Your action succeeded."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser does not support iFrames"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your changes have been successfully committed."
+msgstr ""
+
+msgid "Your comment could not be submitted because %{error}"
+msgstr ""
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment will be discarded."
+msgstr ""
+
+msgid "Your commit email is used for web based operations, such as edits and merges."
+msgstr ""
+
+msgid "Your current password is required to register a two-factor authenticator app."
+msgstr ""
+
+msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your default notification email is used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
+msgstr ""
+
+msgid "Your device is not compatible with GitLab. Please try another device"
+msgstr ""
+
+msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your file must contain a column named %{codeStart}title%{codeEnd}. A %{codeStart}description%{codeEnd} column is optional. The maximum file size allowed is 10 MB."
+msgstr ""
+
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} member. From October 19, 2022, the %{free_user_limit} most recently active member will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} member will remain in your group."
+msgid_plural "Your group, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_user_limit} members. From October 19, 2022, the %{free_user_limit} most recently active members will remain active, and the remaining members will have the %{link_start}Over limit status%{link_end} and lose access to the group. You can go to the Usage Quotas page to manage which %{free_user_limit} members will remain in your group."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
+msgstr ""
+
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
+msgid "Your instance is approaching its licensed user count"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your license does not support on-call rotations"
+msgstr ""
+
+msgid "Your license does not support on-call schedules"
+msgstr ""
+
+msgid "Your license is valid from"
+msgstr ""
+
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
+msgid "Your message here"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your new %{accessTokenType}"
+msgstr ""
+
+msgid "Your new %{accessTokenType} has been created."
+msgstr ""
+
+msgid "Your new %{type}"
+msgstr ""
+
+msgid "Your new access token has been created."
+msgstr ""
+
+msgid "Your new comment"
+msgstr ""
+
+msgid "Your password"
+msgstr ""
+
+msgid "Your password reset token has expired."
+msgstr ""
+
+msgid "Your personal access token has expired"
+msgstr ""
+
+msgid "Your personal access tokens will expire in %{days_to_expire} days or less"
+msgstr ""
+
+msgid "Your primary email is used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}."
+msgstr ""
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your project will be created at:"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "Your public email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your request for access could not be processed: %{error_message}"
+msgstr ""
+
+msgid "Your request for access has been queued for review."
+msgstr ""
+
+msgid "Your request to join %{host} has been rejected."
+msgstr ""
+
+msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
+msgstr ""
+
+msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your search didn't match any commits."
+msgstr ""
+
+msgid "Your search didn't match any commits. Try a different query."
+msgstr ""
+
+msgid "Your search timed out"
+msgstr ""
+
+msgid "Your sign-in page is %{url}."
+msgstr ""
+
+msgid "Your snippets"
+msgstr ""
+
+msgid "Your subscription expired!"
+msgstr ""
+
+msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seat remaining."
+msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Your subscription will expire on %{expires_on}"
+msgstr ""
+
+msgid "Your update failed. You can only upload one design when dropping onto an existing design."
+msgstr ""
+
+msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
+msgstr ""
+
+msgid "Your username is %{username}."
+msgstr ""
+
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+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 ""
+
+msgid "ZentaoIntegration|If different from Web URL."
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
+msgstr ""
+
+msgid "Zoom meeting added"
+msgstr ""
+
+msgid "Zoom meeting removed"
+msgstr ""
+
+msgid "[No reason]"
+msgstr ""
+
+msgid "[REDACTED]"
+msgstr ""
+
+msgid "[Redacted]"
+msgstr ""
+
+msgid "`end_time` should not exceed one month after `start_time`"
+msgstr ""
+
+msgid "`start_time` should precede `end_time`"
+msgstr ""
+
+msgid "`work_items_hierarchy` feature flag disabled for this project"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "about 1 hour"
+msgid_plural "about %d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "access:"
+msgstr ""
+
+msgid "added"
+msgstr ""
+
+msgid "added %{emails}"
+msgstr ""
+
+msgid "added a %{link_type} link"
+msgstr ""
+
+msgid "added a Zoom call to this issue"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "alert"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "already banned from namespace"
+msgstr ""
+
+msgid "already being used for another group or project %{timebox_name}."
+msgstr ""
+
+msgid "already being used for another iteration within this cadence."
+msgstr ""
+
+msgid "already has a \"created\" issue link"
+msgstr ""
+
+msgid "already shared with this group"
+msgstr ""
+
+msgid "and"
+msgstr ""
+
+msgid "any-approver for the merge request already exists"
+msgstr ""
+
+msgid "any-approver for the project already exists"
+msgstr ""
+
+msgid "approval"
+msgid_plural "approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "archived"
+msgstr ""
+
+msgid "archived:"
+msgstr ""
+
+msgid "artifacts"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "at"
+msgstr ""
+
+msgid "at least the Reporter role"
+msgstr ""
+
+msgid "at least the Reporter role, the author, and assignees"
+msgstr ""
+
+msgid "at risk"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
+msgid "banned user already exists"
+msgstr ""
+
+msgid "blocks"
+msgstr ""
+
+msgid "branch"
+msgid_plural "branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "builds"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "cURL:"
+msgstr ""
+
+msgid "can contain only digits"
+msgstr ""
+
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+msgstr ""
+
+msgid "can contain only lowercase letters, digits, and '_'."
+msgstr ""
+
+msgid "can not be changed for existing notes"
+msgstr ""
+
+msgid "can not be set for this resource"
+msgstr ""
+
+msgid "can not be set for this type of note"
+msgstr ""
+
+msgid "can only be changed by a group admin."
+msgstr ""
+
+msgid "can only have one escalation policy"
+msgstr ""
+
+msgid "can't be enabled when delayed group deletion is disabled"
+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 ""
+
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
+msgid "cannot assign a non-confidential work item to a confidential parent. Make the work item confidential and try again."
+msgstr ""
+
+msgid "cannot be a date in the past"
+msgstr ""
+
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
+msgid "cannot be changed"
+msgstr ""
+
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be changed if shared runners are enabled"
+msgstr ""
+
+msgid "cannot be changed since member is associated with a custom role"
+msgstr ""
+
+msgid "cannot be enabled"
+msgstr ""
+
+msgid "cannot be enabled because parent group does not allow it"
+msgstr ""
+
+msgid "cannot be enabled because parent group has shared Runners disabled"
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot be enabled until a valid credit card is on file"
+msgstr ""
+
+msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
+msgstr ""
+
+msgid "cannot be used for user namespace"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
+msgid "cannot merge"
+msgstr ""
+
+msgid "change"
+msgid_plural "changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{criticalStart}critical%{criticalEnd}, %{highStart}high%{highEnd} and %{otherStart}others%{otherEnd}"
+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 ""
+
+msgid "ciReport|%{improvedNum} improved"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|%{sameNum} same"
+msgstr ""
+
+msgid "ciReport|%{scanner} detected %{number} new potential %{vulnStr}"
+msgstr ""
+
+msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
+msgstr ""
+
+msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
+msgstr ""
+
+msgid "ciReport|: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|API Fuzzing"
+msgstr ""
+
+msgid "ciReport|API fuzzing"
+msgstr ""
+
+msgid "ciReport|All clusters"
+msgstr ""
+
+msgid "ciReport|All images"
+msgstr ""
+
+msgid "ciReport|All projects"
+msgstr ""
+
+msgid "ciReport|All severities"
+msgstr ""
+
+msgid "ciReport|All tools"
+msgstr ""
+
+msgid "ciReport|Analyze a deployed version of your web application for known vulnerabilities by examining it from the outside in. DAST works by simulating external attacks on your application while it is running."
+msgstr ""
+
+msgid "ciReport|Automatically apply the patch in a new branch"
+msgstr ""
+
+msgid "ciReport|Base pipeline codequality artifact not found"
+msgstr ""
+
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: "
+msgstr ""
+
+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] ""
+
+msgid "ciReport|Browser performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Checks"
+msgstr ""
+
+msgid "ciReport|Cluster Image Scanning"
+msgstr ""
+
+msgid "ciReport|Code Quality"
+msgstr ""
+
+msgid "ciReport|Code Quality failed loading results"
+msgstr ""
+
+msgid "ciReport|Code Quality test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Code quality degraded due to 1 new issue"
+msgid_plural "ciReport|Code quality degraded due to %d new issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Code quality improved due to 1 resolved issue"
+msgid_plural "ciReport|Code quality improved due to %d resolved issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
+
+msgid "ciReport|Container Scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|Could not dismiss vulnerability because the associated pipeline no longer exists. Refresh the page and try again."
+msgstr ""
+
+msgid "ciReport|Coverage Fuzzing"
+msgstr ""
+
+msgid "ciReport|Coverage fuzzing"
+msgstr ""
+
+msgid "ciReport|Create Jira issue"
+msgstr ""
+
+msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
+msgstr ""
+
+msgid "ciReport|Create issue"
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Download patch to resolve"
+msgstr ""
+
+msgid "ciReport|Download the patch to apply it manually"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
+msgid "ciReport|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|Full Report"
+msgstr ""
+
+msgid "ciReport|Generic Report"
+msgstr ""
+
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+msgstr ""
+
+msgid "ciReport|License Compliance"
+msgstr ""
+
+msgid "ciReport|License Compliance failed loading results"
+msgstr ""
+
+msgid "ciReport|License Compliance test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Load Performance"
+msgstr ""
+
+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] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
+msgid "ciReport|Manage Licenses"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Manually added"
+msgstr ""
+
+msgid "ciReport|New"
+msgstr ""
+
+msgid "ciReport|No changes to Code Quality."
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No code quality issues found"
+msgstr ""
+
+msgid "ciReport|RPS"
+msgstr ""
+
+msgid "ciReport|Resolve with merge request"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Secret Detection"
+msgstr ""
+
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Secret detection"
+msgstr ""
+
+msgid "ciReport|Security reports failed loading results"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Security scanning is loading"
+msgstr ""
+
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error creating the merge request. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error fetching the codequality report."
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|This report contains all Code Quality issues in the source branch."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|in"
+msgstr ""
+
+msgid "ciReport|is loading"
+msgstr ""
+
+msgid "ciReport|is loading, errors when loading results"
+msgstr ""
+
+msgid "ci_database"
+msgstr ""
+
+msgid "closed"
+msgstr ""
+
+msgid "closed %{timeago}"
+msgstr ""
+
+msgid "closed issue"
+msgstr ""
+
+msgid "collect usage information"
+msgstr ""
+
+msgid "comment"
+msgstr ""
+
+msgid "commented"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "commit %{commit_id}"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
+msgid "compliance violation has already been recorded"
+msgstr ""
+
+msgid "contacts can only be added to root groups"
+msgstr ""
+
+msgid "container registry images"
+msgstr ""
+
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
+msgid "contribute to this project."
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "created"
+msgstr ""
+
+msgid "created %{issuable_created} by %{author}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgo}"
+msgstr ""
+
+msgid "created %{timeAgo} by %{author}"
+msgstr ""
+
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
+msgid "created by"
+msgstr ""
+
+msgid "daily"
+msgstr ""
+
+msgid "data"
+msgstr ""
+
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "days"
+msgstr ""
+
+msgid "default branch"
+msgstr ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "denied"
+msgstr ""
+
+msgid "deploy"
+msgstr ""
+
+msgid "design"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "does not exist"
+msgstr ""
+
+msgid "does not have a supported extension. Only %{extension_list} are supported"
+msgstr ""
+
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
+msgid "download it"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "e.g. %{token}"
+msgstr ""
+
+msgid "element is not a hierarchy"
+msgstr ""
+
+msgid "eligible users"
+msgstr ""
+
+msgid "email '%{email}' is not a verified email."
+msgstr ""
+
+msgid "email address settings"
+msgstr ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
+msgid "ending with a reserved file extension is not allowed."
+msgstr ""
+
+msgid "entries cannot be larger than 255 characters"
+msgstr ""
+
+msgid "entries cannot be nil"
+msgstr ""
+
+msgid "entries cannot contain HTML tags"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
+msgstr ""
+
+msgid "example.com"
+msgstr ""
+
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
+msgstr ""
+
+msgid "expired on %{timebox_due_date}"
+msgstr ""
+
+msgid "expires on %{timebox_due_date}"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
+msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
+msgstr ""
+
+msgid "failed to dismiss finding: %{message}"
+msgstr ""
+
+msgid "failed to dismiss security finding: %{message}"
+msgstr ""
+
+msgid "failed to revert associated finding(id=%{finding_id}) to detected"
+msgstr ""
+
+msgid "file"
+msgid_plural "files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "finding is not found or is already attached to a vulnerability"
+msgstr ""
+
+msgid "following"
+msgstr ""
+
+msgid "for"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
+msgstr ""
+
+msgid "for %{link_to_pipeline_ref}"
+msgstr ""
+
+msgid "for %{ref}"
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "fork"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "frontmatter"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
+msgid "group access token"
+msgstr ""
+
+msgid "group access tokens"
+msgstr ""
+
+msgid "group members"
+msgstr ""
+
+msgid "groups"
+msgstr ""
+
+msgid "groups and projects"
+msgstr ""
+
+msgid "groups only"
+msgstr ""
+
+msgid "had %{count} failed job"
+msgid_plural "had %{count} failed jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "has already been linked to another vulnerability"
+msgstr ""
+
+msgid "has already been taken"
+msgstr ""
+
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
+msgid "has been completed."
+msgstr ""
+
+msgid "has too deep level of nesting"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "http:"
+msgstr ""
+
+msgid "http://www.example.com"
+msgstr ""
+
+msgid "https://bamboo.example.com"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
+msgid "if"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "impersonation token"
+msgstr ""
+
+msgid "impersonation tokens"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "in"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "internal note"
+msgstr ""
+
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is"
+msgstr ""
+
+msgid "is already associated to a GitLab Issue. New issue will not be associated."
+msgstr ""
+
+msgid "is an invalid IP address range"
+msgstr ""
+
+msgid "is blocked by"
+msgstr ""
+
+msgid "is forbidden by a top-level group"
+msgstr ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not"
+msgstr ""
+
+msgid "is not a descendant of the Group owning the template"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is not allowed for sign-up. Please use your regular email address."
+msgstr ""
+
+msgid "is not allowed for this group."
+msgstr ""
+
+msgid "is not allowed for this project."
+msgstr ""
+
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
+msgid "is not allowed. Please use your regular email address."
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+msgstr ""
+
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
+msgid "is not valid. The iteration group has to match the iteration cadence group."
+msgstr ""
+
+msgid "is read-only"
+msgstr ""
+
+msgid "is too long (%{current_value}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (%{size}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
+msgid "is too long (maximum is 100 entries)"
+msgstr ""
+
+msgid "is too long (maximum is 1000 entries)"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issues at risk"
+msgstr ""
+
+msgid "issues need attention"
+msgstr ""
+
+msgid "issues on track"
+msgstr ""
+
+msgid "it is larger than %{limit}"
+msgstr ""
+
+msgid "it is stored as a job artifact"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "jigsaw is not defined"
+msgstr ""
+
+msgid "kuromoji custom analyzer"
+msgstr ""
+
+msgid "last commit:"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "leave %{group_name}"
+msgstr ""
+
+msgid "less than a minute"
+msgstr ""
+
+msgid "level: %{level}"
+msgstr ""
+
+msgid "lfs objects"
+msgstr ""
+
+msgid "limit of %{project_limit} reached"
+msgstr ""
+
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "load it anyway"
+msgstr ""
+
+msgid "loading"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "main_database"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "member"
+msgid_plural "members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mergedCommitsAdded| (commits were squashed)"
+msgstr ""
+
+msgid "metric_id must be unique across a project"
+msgstr ""
+
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
+msgid "missing"
+msgstr ""
+
+msgid "months"
+msgstr ""
+
+msgid "most recent deployment"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
+
+msgid "mrWidget|%{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 ""
+
+msgid "mrWidget|%{mergeError}."
+msgstr ""
+
+msgid "mrWidget|%{mergeError}. Try again."
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|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 ""
+
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
+msgid "mrWidget|Added to the merge train by %{merge_author}"
+msgstr ""
+
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
+msgid "mrWidget|Approval rule %{rules} is invalid. GitLab has approved this rule automatically to unblock the merge request. %{link}"
+msgstr ""
+
+msgid "mrWidget|Approval rules %{rules} are invalid. GitLab has approved these rules automatically to unblock the merge request. %{link}"
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approve additionally"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
+msgid "mrWidget|Assign yourself to these issues"
+msgstr ""
+
+msgid "mrWidget|Assign yourself to this issue"
+msgstr ""
+
+msgid "mrWidget|Cancel auto-merge"
+msgstr ""
+
+msgid "mrWidget|Checking if merge request can be merged…"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes issue"
+msgid_plural "mrWidget|Closes issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Create issue to resolve all threads"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Dismiss"
+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 ""
+
+msgid "mrWidget|If the %{type} branch exists in your local repository, you can merge this merge request manually using the command line."
+msgstr ""
+
+msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
+msgstr ""
+
+msgid "mrWidget|Jump to first unresolved thread"
+msgstr ""
+
+msgid "mrWidget|Learn more"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mark as ready"
+msgstr ""
+
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
+msgid "mrWidget|Mentions issue"
+msgid_plural "mrWidget|Mentions issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Merge blocked: a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Merge blocked: all required approvals must be given."
+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: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
+msgstr ""
+
+msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|Merging! Changes are being shipped…"
+msgstr ""
+
+msgid "mrWidget|Merging! Changes will land soon…"
+msgstr ""
+
+msgid "mrWidget|Merging! Drum roll, please…"
+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 ""
+
+msgid "mrWidget|Merging! We're almost there…"
+msgstr ""
+
+msgid "mrWidget|More information"
+msgstr ""
+
+msgid "mrWidget|No users match the rule's criteria."
+msgstr ""
+
+msgid "mrWidget|Please restore it or use a different %{type} branch."
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove from merge train"
+msgstr ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Revoke approval"
+msgstr ""
+
+msgid "mrWidget|SAST and Secret Detection is not enabled."
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|Show %{widget} details"
+msgstr ""
+
+msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
+msgstr ""
+
+msgid "mrWidget|The source branch is %{link} the target branch"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+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 change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
+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 ""
+
+msgid "must be a Debian package"
+msgstr ""
+
+msgid "must be a boolean value"
+msgstr ""
+
+msgid "must be a root namespace"
+msgstr ""
+
+msgid "must be a valid IPv4 or IPv6 address"
+msgstr ""
+
+msgid "must be a valid json schema"
+msgstr ""
+
+msgid "must be after start"
+msgstr ""
+
+msgid "must be an email you have verified"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
+msgid "must be inside the fork network"
+msgstr ""
+
+msgid "must be less than the limit of %{tag_limit} tags"
+msgstr ""
+
+msgid "must be set for a project namespace"
+msgstr ""
+
+msgid "must be unique by status and elapsed time within a policy"
+msgstr ""
+
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
+msgid "my-awesome-group"
+msgstr ""
+
+msgid "my-channel"
+msgstr ""
+
+msgid "my-topic"
+msgstr ""
+
+msgid "need attention"
+msgstr ""
+
+msgid "needs to be between 10 minutes and 1 month"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "never expires"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "no expiration"
+msgstr ""
+
+msgid "no name set"
+msgstr ""
+
+msgid "no one can merge"
+msgstr ""
+
+msgid "no scopes selected"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "not authorized to create member"
+msgstr ""
+
+msgid "not authorized to update member"
+msgstr ""
+
+msgid "not found"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "on track"
+msgstr ""
+
+msgid "only %{parent_types} can be parent of Task."
+msgstr ""
+
+msgid "only Task can be assigned as a child in hierarchy."
+msgstr ""
+
+msgid "only available on top-level groups."
+msgstr ""
+
+msgid "open issue"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "organizations can only be added to root groups"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "packages"
+msgstr ""
+
+msgid "pages"
+msgstr ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent already has maximum number of children."
+msgstr ""
+
+msgid "parent must be in the same project as child."
+msgstr ""
+
+msgid "password"
+msgstr ""
+
+msgid "pending comment"
+msgstr ""
+
+msgid "pending deletion"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "personal access tokens"
+msgstr ""
+
+msgid "pipeline"
+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 "pipelineEditorWalkthrough|You can use the file tree to view your pipeline configuration files. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "point"
+msgid_plural "points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "previously merged commits"
+msgstr ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "processing"
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "project access token"
+msgstr ""
+
+msgid "project access tokens"
+msgstr ""
+
+msgid "project bots cannot be added to other groups / projects"
+msgstr ""
+
+msgid "project is read-only"
+msgstr ""
+
+msgid "project members"
+msgstr ""
+
+msgid "project name"
+msgstr ""
+
+msgid "project namespace cannot be the parent of another namespace"
+msgstr ""
+
+msgid "projects"
+msgstr ""
+
+msgid "reCAPTCHA"
+msgstr ""
+
+msgid "reCAPTCHA helps prevent credential stuffing."
+msgstr ""
+
+msgid "reCAPTCHA private key"
+msgstr ""
+
+msgid "reCAPTCHA site key"
+msgstr ""
+
+msgid "recent activity"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "relates to"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove start date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "removed"
+msgstr ""
+
+msgid "removed a %{link_type} link"
+msgstr ""
+
+msgid "removed a Zoom call from this issue"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "reply should have same confidentiality as top-level note"
+msgstr ""
+
+msgid "repositories"
+msgstr ""
+
+msgid "repository:"
+msgstr ""
+
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
+msgid "satisfied"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "security Reports|There was an error creating the merge request"
+msgstr ""
+
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr ""
+
+msgid "severity|Blocker"
+msgstr ""
+
+msgid "severity|Critical"
+msgstr ""
+
+msgid "severity|High"
+msgstr ""
+
+msgid "severity|Info"
+msgstr ""
+
+msgid "severity|Low"
+msgstr ""
+
+msgid "severity|Major"
+msgstr ""
+
+msgid "severity|Medium"
+msgstr ""
+
+msgid "severity|Minor"
+msgstr ""
+
+msgid "severity|None"
+msgstr ""
+
+msgid "severity|Unknown"
+msgstr ""
+
+msgid "should be an array of %{object_name} objects"
+msgstr ""
+
+msgid "should be an array of existing usernames. %{invalid} does not exist"
+msgstr ""
+
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show %{count} more"
+msgstr ""
+
+msgid "show fewer"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "smartcn custom analyzer"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} adds or subtracts time already spent."
+msgstr ""
+
+msgid "ssh:"
+msgstr ""
+
+msgid "started a discussion on %{design_link}"
+msgstr ""
+
+msgid "started on %{timebox_start_date}"
+msgstr ""
+
+msgid "starts on %{timebox_start_date}"
+msgstr ""
+
+msgid "structure is too large"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "success"
+msgstr ""
+
+msgid "suggestPipeline|1/2: Choose a template"
+msgstr ""
+
+msgid "suggestPipeline|2/2: Commit your changes"
+msgstr ""
+
+msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
+msgstr ""
+
+msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
+msgstr ""
+
+msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
+msgstr ""
+
+msgid "supported SSH public key."
+msgstr ""
+
+msgid "tag name"
+msgstr ""
+
+msgid "terraform states"
+msgstr ""
+
+msgid "the correct format."
+msgstr ""
+
+msgid "the following epics"
+msgstr ""
+
+msgid "the following incidents or issues"
+msgstr ""
+
+msgid "the following issues"
+msgstr ""
+
+msgid "the wiki"
+msgstr ""
+
+msgid "then"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "time summary"
+msgstr ""
+
+msgid "today"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "type must be Debian"
+msgstr ""
+
+msgid "type parameter is missing and is required"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "updated %{timeAgo}"
+msgstr ""
+
+msgid "updated %{time_ago}"
+msgstr ""
+
+msgid "uploads"
+msgstr ""
+
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "user avatar"
+msgstr ""
+
+msgid "user namespace cannot be the parent of another namespace"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "v%{version} published %{timeAgo}"
+msgstr ""
+
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "version %{versionIndex}"
+msgstr ""
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "view the source"
+msgstr ""
+
+msgid "visibility"
+msgstr ""
+
+msgid "vulnerability"
+msgid_plural "vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "vulnerability|Add a comment"
+msgstr ""
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Save comment"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
+msgid "was scheduled to merge after pipeline succeeds by"
+msgstr ""
+
+msgid "weekly"
+msgstr ""
+
+msgid "wiki page"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
+msgstr ""
+
+msgid "with expiry remaining unchanged at %{old_expiry}"
+msgstr ""
+
+msgid "yaml invalid"
+msgstr ""
+
+msgid "your GitLab instance"
+msgstr ""
+
+msgid "your group (%{group_name})"
+msgstr ""
+
+msgid "your settings"
+msgstr ""
+
+msgid "{group}"
+msgstr ""
+
+msgid "{project}"
+msgstr ""
+
+msgid "✔"
+msgstr ""
+
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 00514d46bf4..b4a58f577da 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:23\n"
+"PO-Revision-Date: 2022-10-10 14:03\n"
msgid " %{start} to %{end}"
msgstr " %{start} do %{end}"
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d zatwierdzajÄ…cy"
@@ -1210,13 +1217,6 @@ msgstr "%{spanStart}w%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} do %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr "%{template_project_id} jest nieznany lub nieprawidłowy"
msgid "%{text} is available"
msgstr "%{text} jest dostępny"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} powinien należeć albo do projektu albo do grupy."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} nie obsługuje wykresów wypalania (burnup)"
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} ostrzeżeń znaleziono: pokazano pierwsze %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Strona profilowa %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} wykorzystanego czasu."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} umożliwia wysyłanie powiadomień do aplikacji internetowych w odpowiedzi na zdarzenia w grupie lub projekcie."
@@ -1925,9 +1941,6 @@ msgstr "Nowe Wydanie %{tag} dla %{name} zostało opublikowane. Odwiedź Stronę
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Zwykła strona HTML, która używa Netlify dla CI/CD zamiast GitLab'a, ale nadal ze wszystkimi innymi wspaniałymi funkcjami GitLab"
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Dodaj wyzwalacz"
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr "Dodaj użytkowników do grupy"
-
msgid "Add variable"
msgstr "Dodaj zmiennÄ…"
@@ -3026,9 +3042,15 @@ msgstr "Token kanału informacyjnego"
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "Zachowaj ostatnie artefakty dla wszystkich zadań w ostatnich udanych potokach"
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Wszystkie projekty"
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr "Wystąpił błąd podczas ładowania wszystkich plików."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Wystąpił błąd podczas ładowania danych wykresu"
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr "Ostatni Kontakt"
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 66f0f9f7698..5ce8bc30ef9 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr " %{start} até %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] "%d comentarista adicional"
msgstr[1] "%d comentaristas adicionais"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d usuário adicional"
+msgstr[1] "%d usuários adicionais"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprovador"
@@ -525,8 +530,8 @@ msgstr "%{completedCount} peso concluído"
msgid "%{completedCount} of %{count} checklist item completed"
msgid_plural "%{completedCount} of %{count} checklist items completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{completedCount} de %{count} item da lista de verificação concluído"
+msgstr[1] "%{completedCount} de %{count} itens da lista de verificação concluídos"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} de %{totalWeight} peso concluído"
@@ -1024,11 +1029,6 @@ msgstr "%{spanStart}em%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} até %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} ponto"
+msgstr[1] "%{strong_start}%{errors}%{strong_end} pontos"
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} Armazenamento do projeto"
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} é desconhecido ou inválido"
msgid "%{text} is available"
msgstr "%{text} está disponível"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} não suporta o gráfico de burnup"
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} avisos encontrados: mostrando os primeiros %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,12 +1158,15 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Página de perfil de %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} pediu por uma conta do GitLab na sua instância %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr "%{username} marcou a solicitação de mesclagem %{mr_link} como pronta"
+
msgid "%{username}'s avatar"
msgstr "Avatar de %{username}"
@@ -1180,6 +1188,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} tempo gasto."
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} este %{noun} como rascunho."
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{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."
@@ -1576,7 +1590,7 @@ msgid "A .NET Core console application template, customizable for any .NET Core
msgstr "Um modelo de aplicação console .NET Core personalizável para qualquer projeto .NET Code"
msgid "A CI/CD pipeline must run and be successful before merge."
-msgstr ""
+msgstr "Um pipeline de CI/CD deve ser executado e bem-sucedido antes de mesclar."
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Um site GitBook que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do GitLab"
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr "Um novo endereço de e-mail foi adicionado à sua conta do GitLab: %{email}"
-msgid "A new impersonation token has been created."
-msgstr "Um novo token de representação foi criado."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr "Já existe uma página com este nome."
+msgid "A personal access token has been revoked"
+msgstr "Um token de acesso pessoal foi revogado"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -1693,10 +1713,10 @@ msgid "A platform value can be web, mob or app."
msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
-msgstr ""
+msgstr "Um projeto modelo para desenvolvimento de aplicativos Salesforce com as ferramentas de desenvolvedor Salesforce"
msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
-msgstr ""
+msgstr "Um projeto boilerplate para Tencent Serverless Framework que usa o 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 ""
@@ -2197,7 +2217,7 @@ msgid "Add a table"
msgstr "Adicionar uma tabela"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "Adicionar um evento de linha do tempo ao incidente"
msgid "Add a title..."
msgstr "Adicionar um título..."
@@ -2239,7 +2259,7 @@ msgid "Add comment to design"
msgstr "Adicionar comentário ao design"
msgid "Add comment to incident timeline"
-msgstr ""
+msgstr "Adicionar comentário à linha do tempo do incidente"
msgid "Add comment..."
msgstr "Adicionar comentário..."
@@ -2293,10 +2313,10 @@ msgid "Add label(s)"
msgstr "Adicionar etiqueta(s)"
msgid "Add labels"
-msgstr ""
+msgstr "Adicionar etiquetas"
msgid "Add license"
-msgstr ""
+msgstr "Adicionar licença"
msgid "Add list"
msgstr "Adicionar lista"
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Adicionar gatilho"
-msgid "Add user(s) to the group:"
-msgstr "Adicionar usuário(s) ao grupo:"
-
-msgid "Add users to group"
-msgstr "Adicionar usuários ao grupo"
-
msgid "Add variable"
msgstr "Adicionar variável"
@@ -2470,7 +2484,7 @@ msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "Adiciona um evento de linha do tempo ao incidente."
msgid "Adds a to do."
msgstr "Adiciona uma tarefa pendente."
@@ -2766,9 +2780,15 @@ msgstr "Token de feed"
msgid "AdminSettings|Git abuse rate limit"
msgstr "Limite de taxa de abuso do Git"
+msgid "AdminSettings|Group runners expiration"
+msgstr "Expiração dos executores do grupo"
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "Li e concordo com os termos de serviço%{link_end} %{link_start}(PDF) de Let's Encrypt."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
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."
@@ -2781,6 +2801,9 @@ msgstr "Importar fontes"
msgid "AdminSettings|Inactive project deletion"
msgstr "Exclusão de projeto inativo"
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "Manter os artefatos mais recentes para todas as tarefas nos pipelines de sucesso mais recentes"
@@ -2802,6 +2825,9 @@ msgstr "Número máximo de dependências DAG que um trabalho pode ter"
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr "Número máximo de pipelines ativos por projeto"
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "Número máximo de domínios personalizados por projeto"
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr "Número máximo de tarefas em um único pipeline"
@@ -2838,6 +2864,9 @@ msgstr "pré-visualizar carga"
msgid "AdminSettings|Project export"
msgstr "Exportação do projeto"
+msgid "AdminSettings|Project runners expiration"
+msgstr "|Expiração dos executores do projeto"
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "Proteger variáveis CI/CD por padrão"
@@ -2889,9 +2918,21 @@ msgstr "Defina um modelo de CI/CD como a configuração de pipeline necessária
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "Defina o limite como 0 para desativá-lo."
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "Defina o tempo de expiração dos tokens de autenticação dos executores do projeto recém-registrados."
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr "Defina o nome inicial e as proteções para a ramificação padrão dos novos repositórios criados na instância."
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "Defina o número máximo de domínios personalizados do GitLab Pages por projeto (0 para ilimitado). %{link_start}Saiba mais.%{link_end}"
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr "Defina o tamanho máximo de páginas GitLab por projeto (0 para ilimitado). %{link_start}. Saiba mais.%{link_end}"
@@ -3049,7 +3090,7 @@ msgid "AdminUsers|Automatically marked as default internal user"
msgstr "Marcados automaticamente como usuários internos predefinidos"
msgid "AdminUsers|Avatar"
-msgstr ""
+msgstr "Avatar"
msgid "AdminUsers|Ban user"
msgstr "Banir usuário"
@@ -3078,6 +3119,9 @@ msgstr "Bloqueado"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Bloquear o usuário tem os seguintes efeitos:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "Pode criar grupo"
@@ -3417,9 +3461,21 @@ msgstr "Opções de exportação avançadas"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr "Versão do Elasticsearch não compatível"
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr "Todas as dependências da solicitação de mesclagem tiveram foram mescl
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
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 project members"
+msgstr "Todos os membros do projeto"
+
msgid "All projects"
msgstr "Todos os projetos"
@@ -3892,10 +3951,10 @@ msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que apenas os protocolos selecionados sejam usados para acesso ao Git."
msgid "Allow owners to manage default branch protection per group."
-msgstr ""
+msgstr "Permitir que proprietários gerenciem a predefinição da proteção de ramificação por grupo."
msgid "Allow owners to manually add users outside of LDAP"
-msgstr ""
+msgstr "Permitir que os donos adicionem usuários manualmente fora do LDAP"
msgid "Allow password authentication for Git over HTTP(S)"
msgstr "Permitir autenticação de senha para Git sobre HTTP(S)"
@@ -3921,6 +3980,9 @@ msgstr "Permitir que esta chave faça push para este repositório"
msgid "Allow use of licensed EE features"
msgstr "Permitir o uso de funcionalidades da licença EE"
+msgid "Allow users to create top-level groups"
+msgstr "Permitir que os usuários criem grupos de nível superior"
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -3973,7 +4035,7 @@ msgid "Also remove direct user membership from subgroups and projects"
msgstr ""
msgid "Also unassign this user from related issues and merge requests"
-msgstr ""
+msgstr "Também desatribuir este usuário de issues relacionadas e solicitações de mesclagem"
msgid "Alternate support URL for Help page and Help dropdown."
msgstr "URL de suporte alternativo para a página de Ajuda e lista suspensa de Ajuda."
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr "Ocorreu um erro ao carregar todos os arquivos."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Ocorreu um erro ao carregar os dados do gráfico"
@@ -4410,7 +4469,7 @@ msgid "An example project that shows off the best practices for setting up GitLa
msgstr "Um projeto de exemplo que mostra as melhores práticas para configurar o GitLab para sua própria organização, incluindo exemplos de issues, merge request e marcos"
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
-msgstr ""
+msgstr "Um exemplo mostrando como usar Jsonnet com pipelines filhos dinâmicos do GitLab"
msgid "An incident has been resolved in %{project_path}."
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr "Ocorreu um erro desconhecido."
msgid "Analytics"
msgstr "Telemetria"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analise suas dependências em busca de vulnerabilidades conhecidas."
@@ -4654,10 +4716,10 @@ msgid "ApplicationSettings|Require lowercase letters"
msgstr ""
msgid "ApplicationSettings|Require numbers"
-msgstr ""
+msgstr "Requer números"
msgid "ApplicationSettings|Require symbols"
-msgstr ""
+msgstr "Requer símbolos"
msgid "ApplicationSettings|Require uppercase letters"
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr "Cadastro ativado"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr "Texto mostrado após um usuário se cadastrar. Markdown ativado."
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr "Este recurso está disponível apenas no GitLab.com"
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr "Esta opção só está disponível no GitLab.com"
@@ -4892,7 +4957,7 @@ msgid "ApprovalSettings|This setting is configured at the instance level and can
msgstr "Esta configuração está caracterizada no nível de instância e pode ser somente alterada por um administrador."
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed in the group settings by an administrator or group owner."
-msgstr ""
+msgstr "Este parâmetro está configurado em %{groupName} e poderá ser alterado apenas nos parâmetros de grupo pelo administrador ou proprietário do grupo."
msgid "ApprovalSettings|When a commit is added:"
msgstr "Quando um commit é adicionado:"
@@ -5188,7 +5253,7 @@ msgid "Ask someone with write access to resolve it."
msgstr ""
msgid "Ask your group owner to set up a group runner."
-msgstr ""
+msgstr "Solicite ao proprietário de seu grupo para configurar um Runner de grupo."
msgid "Assertion consumer service URL"
msgstr "URL de serviço do consumidor de asserção"
@@ -5230,7 +5295,7 @@ msgid "Assign severity"
msgstr "Atribuir severidade"
msgid "Assign some issues to this milestone."
-msgstr "Atribua alguns issues a este marco."
+msgstr "Atribua algumas issues a este marco."
msgid "Assign to"
msgstr "Atribuir à"
@@ -5323,6 +5388,9 @@ msgstr[1] "Anexando %d arquivos"
msgid "Attaching the file failed."
msgstr "Falha ao anexar o arquivo."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr "Tentativa de entrada em %{host} usando um código de autenticação de dois fatores incorreto"
+
msgid "Audit Events"
msgstr "Eventos de auditoria"
@@ -5881,7 +5949,7 @@ msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up
msgstr "Executa CI/CD pipelines com Atlassian Bamboo. Você deve configurar a rotulagem de revisão automática e um gatilho de repositório no Bamboo. %{docs_link}"
msgid "BambooService|The user with API access to the Bamboo server."
-msgstr ""
+msgstr "O usuário com acesso API ao servidor Bamboo."
msgid "Banned"
msgstr "Banido"
@@ -5977,7 +6045,7 @@ msgid "Before enabling this integration, create a webhook for the room in Google
msgstr "Antes de ativar esta integração, crie um webhook para a sala no Google Chat onde você deseja receber notificações deste projeto. %{docs_link}"
msgid "Before inserting code, be sure to read the comment that separated each code group."
-msgstr ""
+msgstr "Antes de inserir o código, tenha certeza de ter lido o comentário que separou cada grupo de código."
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Abaixo você encontrará todos os grupos que são públicos."
+msgid "Beta"
+msgstr "Beta"
+
msgid "Bi-weekly code coverage"
msgstr "Cobertura semestral de código"
@@ -6304,7 +6375,7 @@ msgid "Billing|An error occurred while removing a billable member."
msgstr "Ocorreu um erro ao carregar a lista de membros faturáveis."
msgid "Billing|Awaiting member signup"
-msgstr ""
+msgstr "Aguardando cadastro de membro"
msgid "Billing|Cannot remove user"
msgstr "Não é possível remover usuário"
@@ -6313,10 +6384,10 @@ msgid "Billing|Direct memberships"
msgstr "Membros diretos"
msgid "Billing|Enter at least three characters to search."
-msgstr ""
+msgstr "Digite pelo menos três caracteres para pesquisar."
-msgid "Billing|Explore all plans"
-msgstr "Explorar todos os planos"
+msgid "Billing|Explore paid plans"
+msgstr "Explorar planos pagos"
msgid "Billing|Export list"
msgstr "Exportar lista"
@@ -6330,7 +6401,7 @@ msgstr[0] "Grupos no nível Gratuito são limitados a %d assentos"
msgstr[1] "Grupos no nível Gratuito são limitados a %d assentos"
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 "Membros que foram convidados por meio de um convite de grupo, não podem ser removidos. Você pode remover o grupo inteiro, ou pedir ao Proprietário do grupo convidado para remover o membro."
msgid "Billing|No users to display."
msgstr "Nenhum usuário para exibir"
@@ -6348,11 +6419,14 @@ msgid "Billing|To ensure all members can access the group when your trial ends,
msgstr "Para garantir que todos os membros possam acessar o grupo quando sua avaliação terminar, você pode atualizar para um nível pago."
msgid "Billing|Toggle seat details"
-msgstr ""
+msgstr "Alternar detalhes de assento"
msgid "Billing|Type %{username} to confirm"
msgstr "Digite %{username} para confirmar"
+msgid "Billing|Unlimited members during your trial"
+msgstr "Membros ilimitados durante sua avaliação"
+
msgid "Billing|User was successfully removed"
msgstr "O usuário foi removido com sucesso"
@@ -6671,6 +6745,9 @@ msgstr "Carregando épicos"
msgid "Bold text"
msgstr "Texto em negrito"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "Ambos SSH e HTTP(S)"
@@ -6707,45 +6784,102 @@ msgstr "Branch não carregado - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "Permitir que todos os usuários com acesso push a %{linkStart}force push%{linkEnd}."
msgid "BranchRules|Allowed to merge"
msgstr "Permitido para mesclar"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "Permitido push"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr "Detalhes"
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "Grupos"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
-msgid "BranchRules|Protections"
+msgid "BranchRules|Protect branch"
msgstr ""
+msgid "BranchRules|Protections"
+msgstr "Proteções"
+
msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
-msgid "BranchRules|default"
+msgid "BranchRules|Roles"
+msgstr "Cargos"
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
msgstr ""
+msgid "BranchRules|Users"
+msgstr "Usuários"
+
+msgid "BranchRules|default"
+msgstr "padrão"
+
msgid "BranchRules|protected"
msgstr ""
@@ -6915,7 +7049,7 @@ msgid "Browse templates"
msgstr "Navegar por modelos"
msgid "Build cannot be erased"
-msgstr ""
+msgstr "A compilação não pode ser apagada"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7146,7 +7283,7 @@ msgid "CICDAnalytics|All time"
msgstr "Todo o período"
msgid "CICDAnalytics|Change failure rate"
-msgstr ""
+msgstr "Taxa de falha de mudança"
msgid "CICDAnalytics|Deployment frequency"
msgstr "Frequência de implantação"
@@ -7216,6 +7353,9 @@ msgstr "Padrão para pipeline de Auto DevOps para todos os projetos"
msgid "CICD|Deployment strategy"
msgstr "Estratégia de implantação"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr "Ativar recurso para limitar o acesso do token de tarefa aos projetos a seguir."
+
msgid "CICD|Jobs"
msgstr "Tarefas"
@@ -7225,8 +7365,8 @@ msgstr "Limite"
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr "Limite de acesso de 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 "Selecione projetos que podem ser acessados por solicitações de API autenticadas com a variável CI_JOB_TOKEN deste projeto."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr ""
@@ -7486,8 +7626,8 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr "Não é possível promover a issue devido a permissões insuficientes."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "Não é possível se referir a um marco de grupo por um Id interno!"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "Não foi possível mostrar a pré-visualização. Para pré-visualizações em arquivos de sketch, eles devem ter o formato de arquivo introduzido pela versão 43 ou superior do Sketch."
@@ -7544,7 +7684,7 @@ msgid "Certificate Subject"
msgstr "Assunto do certificado"
msgid "Change Failure Rate"
-msgstr "Mudança de taxa de falha"
+msgstr "Taxa de falha de mudança"
msgid "Change assignee"
msgstr "Alterar responsável"
@@ -7631,7 +7771,7 @@ msgid "ChangeTypeAction|Search projects"
msgstr "Pesquisar projetos"
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
-msgstr ""
+msgstr "Comece %{newMergeRequest} com essas mudanças"
msgid "ChangeTypeAction|Switch branch"
msgstr "Trocar branch"
@@ -7681,6 +7821,9 @@ msgstr "Altera o título para \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr "Mudanças:"
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8339,7 +8482,7 @@ msgid "Click to reveal"
msgstr "Clique para revelar"
msgid "Client request timeout"
-msgstr ""
+msgstr "Tempo limite da requisição do cliente"
msgid "Clients"
msgstr "Clientes"
@@ -8695,6 +8838,9 @@ msgstr "Tem certeza de que deseja excluir esse agente? Você não pode desfazer
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr "Certificado"
@@ -8794,6 +8940,9 @@ msgstr "Como atualizar um agente?"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr "Instalar usando o Helm (recomendado)"
+msgid "ClusterAgents|Integration Status"
+msgstr "Status de integração"
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Última conexão %{timeAgo}."
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr "Nenhum token de acesso do agente"
+
msgid "ClusterAgents|No agents"
msgstr "Sem agentes"
@@ -8829,6 +8981,9 @@ msgstr "Nenhum cluster conectado por meio de certificados de cluster"
msgid "ClusterAgents|Not connected"
msgstr "Não conectado"
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr "Recomendado"
@@ -8895,6 +9050,9 @@ msgstr "Token revogado por %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Usuário desconhecido"
+msgid "ClusterAgents|Valid access token"
+msgstr "Token de acesso válido"
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "Ver todos os %{number} agentes"
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr "Commits:"
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Erro ao recuperar dados da solicitação de mesclagem."
@@ -9600,7 +9761,7 @@ msgid "Compare Revisions"
msgstr "Comparar revisões"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "Comparar ramificações e continuar"
msgid "Compare changes"
msgstr "Comparar alterações"
@@ -9668,6 +9829,9 @@ msgstr "Completo"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr "Conclua a verificação para cadastrar."
+
msgid "Completed"
msgstr "Completo"
@@ -9737,7 +9901,7 @@ msgstr "O nome é necessário"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr "Nenhuma estrutura de conformidade está configurada ainda"
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9987,16 +10151,16 @@ msgid "Confluence"
msgstr "Confluence"
msgid "Confluence Cloud Workspace URL"
-msgstr ""
+msgstr "URL da área de trabalho do Confluence Cloud"
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
-msgstr ""
+msgstr "Link para um área de trabalho Confluence a partir da barra lateral."
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 "Link para um -area de trabalho Confluence a partir da barra lateral. Habilitando essa integração substitui o link da barra lateral \"Wiki\" por um link para o espaço de trabalho de Confluence . A wiki do GitLab ainda está disponível no URL original."
msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
msgstr ""
@@ -10055,6 +10219,9 @@ msgstr "Contatos"
msgid "Container Registry"
msgstr "Registro de contêiner"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Verificação de container"
@@ -10180,7 +10347,7 @@ msgid "ContainerRegistry|Docker connection error"
msgstr "Erro de conexão do Docker"
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "Editar regras de limpeza"
msgid "ContainerRegistry|Enable expiration policy"
msgstr "Ativar política de expiração"
@@ -10287,10 +10454,10 @@ msgid "ContainerRegistry|Save storage space by automatically deleting tags from
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 "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "Configurar regras de limpeza"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "Defina regras para remover automaticamente pacotes não utilizados para economizar espaço de armazenamento."
msgid "ContainerRegistry|Set up cleanup"
msgstr "Configurar limpeza"
@@ -10511,15 +10678,15 @@ msgstr "Contribuidores"
msgid "Control emails linked to your account"
msgstr "Controle e-mails vinculados à sua conta"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr ""
+
msgid "Control how the GitLab Package Registry functions."
msgstr ""
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
-msgid "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."
-msgstr "Controle quais projetos podem ser acessados por solicitações de API autenticadas com a variável CI_JOB_TOKEN CI/CD deste projeto. É um risco de segurança desativar esse recurso, pois projetos não autorizados podem tentar recuperar um token ativo e acessar a API."
-
msgid "Cookie domain"
msgstr ""
@@ -10794,7 +10961,7 @@ msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
-msgstr ""
+msgstr "Não foi possível remover %{user} de %{group}. Não é possível remover o último proprietário do grupo."
msgid "Could not remove %{user} from %{group}. User is not a group member."
msgstr "Não foi possível remover %{user} de %{group}. Usuário não é um membro do grupo."
@@ -10841,6 +11008,9 @@ msgstr "Não foi possível atribuir política ao projeto ou grupo"
msgid "Country"
msgstr "País"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Cobertura"
@@ -11057,6 +11227,9 @@ msgstr "Criar tópico"
msgid "Create user"
msgstr "Criar usuário"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Criar curinga: %{searchTerm}"
@@ -11069,6 +11242,12 @@ msgstr "Criar seu grupo"
msgid "Create, update, or delete a merge request."
msgstr "Criar, atualizar ou excluir uma solicitação de mesclagem."
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "Adicione uma mensagem à tag. Deixar este espaço em branco cria uma tag leve %{linkStart}%{linkEnd}."
+
+msgid "CreateGitTag|Set tag message"
+msgstr "Definir mensagem da tag"
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "Você não tem permissão para criar um subgrupo neste grupo."
@@ -11616,7 +11795,7 @@ msgid "CycleAnalytics|Average time to completion (days)"
msgstr "Média de dias para conclusão (dias)"
msgid "CycleAnalytics|Change Failure Rate"
-msgstr ""
+msgstr "Taxa de falha de mudança"
msgid "CycleAnalytics|Create a custom value stream to view metrics about stages specific to your development process. Use your value stream to visualize your DevSecOps lifecycle, determine the velocity of your group, and identify inefficient processes."
msgstr ""
@@ -11720,10 +11899,10 @@ msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Change failure rate"
-msgstr "Alterar taxa de falha"
+msgstr "Taxa de falha de mudança"
msgid "DORA4Metrics|Change failure rate (percentage)"
-msgstr "Alterar taxa de falha (porcentagem)"
+msgstr "Taxa de falha de mudança (porcentagem)"
msgid "DORA4Metrics|Date"
msgstr "Data"
@@ -11768,7 +11947,7 @@ msgid "DORA4Metrics|Percentage of failed deployments"
msgstr "Porcentagem de implantações com falha"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr "Algo deu errado ao obter dados de taxa de falha de alteração."
+msgstr "Algo deu errado ao obter dados de taxa de falha de mudança."
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
msgstr ""
@@ -11849,7 +12028,7 @@ msgid "DastProfiles|A scanner profile defines the configuration details of a sec
msgstr ""
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Um perfil do site define os atributos e detalhes de configuração de seu aplicativo, site ou API implantado. %{linkStart}Saiba mais%{linkEnd}."
msgid "DastProfiles|AJAX spider"
msgstr ""
@@ -12053,10 +12232,10 @@ msgid "DastProfiles|Scanner name"
msgstr "Nome da verificação"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "Perfil da verificação"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "Perfis da verificação"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr "Selecione um perfil de verificação para executar uma verificação de DAST"
@@ -12080,10 +12259,10 @@ msgid "DastProfiles|Site name"
msgstr "Nome do site"
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "Perfil do site"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "Perfis do site"
msgid "DastProfiles|Site type"
msgstr "Tipo de site"
@@ -12182,7 +12361,7 @@ msgid "DastSiteValidation|Meta tag validation"
msgstr "Validação de metatag"
msgid "DastSiteValidation|Not validated"
-msgstr ""
+msgstr "Não validado"
msgid "DastSiteValidation|Retry validation"
msgstr "Tentar novamente a validação"
@@ -12324,6 +12503,12 @@ msgstr "Período limitado a %{number} dias"
msgid "Date range must be shorter than %{max_range} days."
msgstr "O intervalo de datas deve ser menor que %{max_range} dias."
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Dia do mês"
@@ -12510,6 +12695,9 @@ msgstr "Excluir conta"
msgid "Delete artifacts"
msgstr "Excluir artefatos"
+msgid "Delete asset"
+msgstr "Excluir ativos"
+
msgid "Delete audio"
msgstr "Excluir áudio"
@@ -12574,7 +12762,7 @@ msgid "Delete row"
msgstr "Excluir linha"
msgid "Delete self monitoring project"
-msgstr ""
+msgstr "Excluir projeto de automonitoramento"
msgid "Delete snippet"
msgstr "Excluir snippet"
@@ -12654,6 +12842,9 @@ msgstr "Excluído"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Apelido de bate-papo excluído: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr "Commits: excluídas:"
+
msgid "Deleted projects cannot be restored!"
msgstr "Projetos excluídos não podem ser restaurados!"
@@ -12993,6 +13184,9 @@ msgstr "Apenas acesso de leitura"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Tokens de implantação ativos (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "Permite acesso de leitura e gravação às imagens de registro."
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "Permite acesso de leitura e gravação ao registro do pacote."
@@ -13038,6 +13232,9 @@ msgstr "Digite um nome de usuário para o seu token. O padrão é %{code_start}g
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr "Digite uma data de expiração para o seu token. O padrão é nunca expirar."
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "Data de expiração (opcional)"
+
msgid "DeployTokens|Expires"
msgstr "Expira"
@@ -13059,6 +13256,9 @@ msgstr "Revogar %{name}"
msgid "DeployTokens|Scopes"
msgstr "Escopos"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr "Escopos (selecione pelo menos um)"
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "Este %{entity_type} não tem nenhum tokem de implantação ativa."
@@ -13074,6 +13274,12 @@ msgstr "Use este token como uma senha. Salve isso. Esta senha não pode ser recu
msgid "DeployTokens|Username"
msgstr "Nome de usuário"
+msgid "DeployTokens|Username (optional)"
+msgstr "Nome de usuário (opcional)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "Seu novo token de implantação"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr "Seu novo nome de usuário do token de implantação"
@@ -13259,18 +13465,9 @@ msgstr "sucesso"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr "Remoção e depreciação de funcionalidades"
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr "Para informações sobre uma possível substituição %{epicStart} leia mais sobre Opstrace %{epicEnd}."
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr "Para informações sobre uma possível substituição %{opstrace_link_start} leia mais sobre Opstrace %{link_end}."
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr "Os registros e recursos de rastreamento também foram descontinuados no GitLab 14.7 e estão %{removal_link_start} programados para remoção %{link_end} no GitLab 15.0."
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr "O recurso de métricas foi descontinuado no GitLab 14.7."
@@ -13339,20 +13536,11 @@ msgstr "Os designs arquivados ainda estarão disponíveis nas versões anteriore
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr "Tem certeza de que deseja arquivar os designs selecionados?"
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "Você tem certeza que quer cancelar a alteração deste comentário?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Você tem certeza que quer cancelar a criação deste comentário?"
-msgid "DesignManagement|Cancel changes"
-msgstr "Cancelar as alterações"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Cancelar a confirmação de comentário"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "Cancelar a confirmação de atualização dos comentários"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
@@ -13360,6 +13548,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "Comentário"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Não foi possível adicionar um novo comentário. Por favor, tente novamente."
@@ -13378,11 +13572,11 @@ msgstr "Desmarcar tudo"
msgid "DesignManagement|Designs"
msgstr "Designs"
-msgid "DesignManagement|Discard comment"
-msgstr "Descartar comentário"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "Discussão"
msgid "DesignManagement|Download design"
msgstr "Baixar design"
@@ -13399,12 +13593,6 @@ msgstr "Ir para o próximo design"
msgid "DesignManagement|Go to previous design"
msgstr "Ir para o design anterior"
-msgid "DesignManagement|Keep changes"
-msgstr "Manter as alterações"
-
-msgid "DesignManagement|Keep comment"
-msgstr "Manter o comentário"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "A versão de design solicitada não existe. Mostrando a versão mais recente como alternativa"
@@ -13478,7 +13666,7 @@ msgid "DevOps adoption"
msgstr "Adoção de DevOps"
msgid "Development"
-msgstr ""
+msgstr "Desenvolvimento"
msgid "Devices (optional)"
msgstr "Dispositivos (opcional)"
@@ -13520,7 +13708,7 @@ msgid "DevopsAdoption|At least one approval on a merge request"
msgstr "Pelo menos uma aprovação em uma solicitação de mesclagem"
msgid "DevopsAdoption|At least one deploy"
-msgstr ""
+msgstr "Pelo menos uma implantação"
msgid "DevopsAdoption|At least one issue created"
msgstr "Pelo menos uma issue foi criada"
@@ -13529,7 +13717,7 @@ msgid "DevopsAdoption|At least one merge request created"
msgstr "Pelo menos uma solicitação de mesclagem foi criada"
msgid "DevopsAdoption|At least one pipeline successfully run"
-msgstr ""
+msgstr "Pelo menos um pipeline executado com sucesso"
msgid "DevopsAdoption|Code owners"
msgstr "Proprietários de código"
@@ -13544,13 +13732,13 @@ msgid "DevopsAdoption|DAST"
msgstr "DAST"
msgid "DevopsAdoption|DAST enabled for at least one project"
-msgstr ""
+msgstr "DAST ativado para pelo menos um projeto"
msgid "DevopsAdoption|Dependency Scanning"
msgstr "Verificação de dependência"
msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
-msgstr ""
+msgstr "Verificação de dependência ativada para pelo menos um projeto"
msgid "DevopsAdoption|Deploys"
msgstr "Implementações"
@@ -13586,7 +13774,7 @@ msgid "DevopsAdoption|No results…"
msgstr "Sem resultados…"
msgid "DevopsAdoption|No tracked features"
-msgstr ""
+msgstr "Nenhum recurso de acompanhamento"
msgid "DevopsAdoption|Not adopted"
msgstr "Não adotado"
@@ -13604,7 +13792,7 @@ msgid "DevopsAdoption|Remove Group"
msgstr "Remover grupo"
msgid "DevopsAdoption|Remove Group from the table."
-msgstr ""
+msgstr "Remover grupo da tabela."
msgid "DevopsAdoption|Runner configured for project/group"
msgstr ""
@@ -13616,7 +13804,7 @@ msgid "DevopsAdoption|SAST"
msgstr "SAST"
msgid "DevopsAdoption|SAST enabled for at least one project"
-msgstr ""
+msgstr "SAST ativado para pelo menos um projeto"
msgid "DevopsAdoption|Sec"
msgstr "Sec"
@@ -13634,10 +13822,10 @@ msgid "DevopsAdoption|This group has no subgroups"
msgstr "O grupo não tem subgrupos"
msgid "DevopsAdoption|Total number of features adopted"
-msgstr ""
+msgstr "Número total de funcionalidades adotadas"
msgid "DevopsAdoption|You cannot remove the group you are currently in."
-msgstr ""
+msgstr "Você não pode remover o grupo em que está atualmente."
msgid "DevopsReport|DevOps Score"
msgstr "Pontuação de DevOps"
@@ -13947,6 +14135,18 @@ msgstr "Domínio"
msgid "Domain Name"
msgstr "Nome do domínio"
+msgid "Domain Verification"
+msgstr "Verificação de domínio"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "Como configuro um domínio?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "Nenhum domínio configurado. Crie um domínio em um projeto nesta hierarquia de grupos."
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "Os domínios a seguir estão configurados para projetos neste grupo. Os usuários com endereços de e-mail que correspondem a um domínio verificado não precisam confirmar sua conta."
+
msgid "Don't have a group?"
msgstr "Você não tem um grupo?"
@@ -14065,10 +14265,10 @@ msgid "DropdownWidget|Assign %{issuableAttribute}"
msgstr "Atribuir %{issuableAttribute}"
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "Editar %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Editar página da wiki"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Editar seu comentário mais recente em um tópico (a partir de uma área de texto vazia)"
+msgid "Edit your search and try again"
+msgstr "Edite sua pesquisa e tente novamente"
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14431,7 +14634,7 @@ msgid "EmailError|We couldn't find the project. Please check if there's any typo
msgstr "Não conseguimos encontrar o projeto. Por favor, verifique se há algum erro de digitação."
msgid "EmailError|We couldn't process your email because it is too large. Please create your issue or comment through the web interface."
-msgstr ""
+msgstr "Não foi possível processar seu e-mail porque é muito grande. Crie sua issue ou comentário por meio da interface web."
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
msgstr "Você não tem permissão para realizar esta ação. Se você acredita que isso é um erro, entre em contato com um membro da equipe."
@@ -14451,9 +14654,6 @@ msgstr "e %{moreCount} mais"
msgid "Emails"
msgstr "E-mails"
-msgid "Emails sent from Service Desk have this name."
-msgstr "Os e-mails enviados pela central de serviços tem esse nome."
-
msgid "Emails sent to %{email} are also supported."
msgstr "E-mails enviados para %{email} também são suportados."
@@ -14551,10 +14751,10 @@ msgid "Enable and disable Service Desk. Some additional configuration might be r
msgstr "Ativar e e desativar a central de serviços. Algumas configurações adicionais podem ser necessárias. %{link_start}Saiba mais%{link_end}."
msgid "Enable authenticated API request rate limit"
-msgstr ""
+msgstr "Ativar o limite da taxa de solicitação das requisições de API autenticada"
msgid "Enable authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "Ativar o limite da taxa de requisição das requisições autenticadas de Git LFS"
msgid "Enable authenticated web request rate limit"
msgstr "Ativar o limite da taxa de solicitação das requisições web autenticada"
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr "Ativar o cache de expiração de contêiner."
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "Ativar notificações por e-mail"
@@ -14919,6 +15122,9 @@ msgstr "Implantação"
msgid "Environments|Deployment %{status}"
msgstr "Implantação %{status}"
+msgid "Environments|Edit your search and try again"
+msgstr "Edite sua pesquisa e tente novamente"
+
msgid "Environments|Enable review app"
msgstr "Ativar app de revisão"
@@ -14952,6 +15158,9 @@ msgstr "Nenhum ambiente de implantação"
msgid "Environments|No deployments yet"
msgstr "Nenhuma implantação ainda"
+msgid "Environments|No results found"
+msgstr "Nenhum resultado encontrado"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Observe que esta ação irá parar o ambiente mas %{emphasisStart}não%{emphasisEnd} terá efeito sobre qualquer deploy existente devido a \"ação de parar ambiente\" sendo definida no arquivo %{ciConfigLinkEnd}.gitlab-ci.yml%{ciConfigLinkStart}."
@@ -14976,6 +15185,9 @@ msgstr "Reverter ambiente"
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr "Pesquisar pelo nome do ambiente"
+
msgid "Environments|Show all"
msgstr "Mostrar tudo"
@@ -15136,10 +15348,10 @@ msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle
msgstr "Isto também irá remover quaisquer descendentes de %{bStart}%{targetEpicTitle}%{bEnd} de %{bStart}%{parentEpicTitle}%{bEnd}. Você tem certeza?"
msgid "Epics|Unable to save epic. Please try again"
-msgstr ""
+msgstr "Não foi possível salvar o épico. Por favor, tente novamente"
msgid "Erased"
-msgstr ""
+msgstr "Apagado"
msgid "Error"
msgstr "Erro"
@@ -15415,7 +15627,7 @@ msgid "Escalation policies"
msgstr "Políticas de escalação"
msgid "Escalation policies may not have more than %{rule_count} rules"
-msgstr ""
+msgstr "As políticas de encaminhamento não podem ter mais de %{rule_count} regras"
msgid "Escalation policies must have at least one rule"
msgstr "As políticas de escalonamento devem ter pelo menos uma regra"
@@ -15454,7 +15666,7 @@ msgid "EscalationPolicies|Add policy"
msgstr "Adicionar política"
msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
-msgstr ""
+msgstr "Tem certeza de que deseja excluir a política de escalação \"%{escalationPolicy}\"? Essa ação não pode ser desfeita."
msgid "EscalationPolicies|Create an escalation policy in GitLab"
msgstr "Crie uma política de escalação no GitLab"
@@ -15490,7 +15702,7 @@ msgid "EscalationPolicies|Maximum of 10 rules has been reached."
msgstr "O máximo de 10 regras foi atingido."
msgid "EscalationPolicies|Minutes must be between 0 and 1440."
-msgstr ""
+msgstr "Os minutos devem estar entre 0 e 1440."
msgid "EscalationPolicies|Remove escalation rule"
msgstr "Remover regra de escalação"
@@ -15508,13 +15720,13 @@ msgid "EscalationPolicies|THEN %{doAction} %{scheduleOrUser}"
msgstr "ENTÃO %{doAction} %{scheduleOrUser}"
msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
-msgstr ""
+msgstr "A política de escalação não pôde ser excluída. Por favor, tente novamente."
msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
-msgstr ""
+msgstr "A política de escalação não pôde ser atualizada. Por favor, tente novamente"
msgid "EscalationPolicies|This policy has no escalation rules."
-msgstr ""
+msgstr "Esta política não tem regras de escalação."
msgid "EscalationPolicies|mins"
msgstr "mins"
@@ -15690,7 +15902,7 @@ msgid "Existing projects will be able to use expiration policies. Avoid enabling
msgstr ""
msgid "Existing sign in methods may be removed"
-msgstr ""
+msgstr "Os métodos de entrada existentes podem ser removidos"
msgid "Exit."
msgstr ""
@@ -15717,7 +15929,7 @@ msgid "Expand issues"
msgstr "Expandir issues"
msgid "Expand jobs"
-msgstr ""
+msgstr "Expandir tarefas"
msgid "Expand merge details"
msgstr ""
@@ -15927,7 +16139,7 @@ msgid "ExternalIssueIntegration|Only one issue tracker integration can be active
msgstr ""
msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
-msgstr ""
+msgstr "Essa issue está sincronizada com %{trackerName}"
msgid "ExternalWikiService|Enter the URL to the external wiki."
msgstr ""
@@ -15942,7 +16154,7 @@ msgid "ExternalWikiService|Link to an external wiki from the sidebar."
msgstr "Link para uma wiki externa para a barra lateral."
msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
-msgstr ""
+msgstr "https://exemplo.com/xxx/wiki/..."
msgid "Facebook"
msgstr "Facebook"
@@ -16074,9 +16286,6 @@ msgstr "Falha ao carregar os branchs. Por favor, tente novamente."
msgid "Failed to load deploy keys."
msgstr "Falha ao carregar a chave de implantação."
-msgid "Failed to load emoji list."
-msgstr "Falha ao carregar a lista de emojis."
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16482,7 +16691,7 @@ msgid "File"
msgstr "Arquivo"
msgid "File %{current} of %{total}"
-msgstr ""
+msgstr "Arquivo %{current} de %{total}"
msgid "File Hooks"
msgstr ""
@@ -16689,7 +16898,7 @@ msgid "FloC|Federated Learning of Cohorts (FLoC)"
msgstr ""
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "Participar do FLoC"
msgid "FlowdockService|Enter your Flowdock token."
msgstr "Insira seu token do Flowdock."
@@ -16760,6 +16969,9 @@ msgstr "Para cada tarefa, reutilize o espaço de tarefa do projeto. Se o espaço
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr "O nome da aplicação que vai usar o token ou seu propósito, por exemplo. Não coloque informações sensíveis no nome do token. Ele vai estar visível a todos os membros de %{resource_type}."
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr "Para arquivos maiores que este limite indexam apenas o nome do arquivo. O conteúdo do arquivo não é indexado nem pesquisável."
@@ -16889,14 +17101,47 @@ msgstr "Erros encontrados em seu .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Avaliação gratuita do GitLab.com Ultimate"
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] "Os grupos gratuitos são limitados a %{free_user_limit} membros e os membros restantes terão um status de limite e perderão o acesso ao grupo."
msgstr[1] "Os grupos gratuitos são limitados a %{free_user_limit} membros e os membros restantes terão um status de limite e perderão o acesso ao grupo."
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "Alternativamente, você pode atualizar para o GitLab Premium ou GitLab Ultimate:"
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "Explorar planos pagos"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "Explorar planos pagos:"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr "Gerenciar membros"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "Gerenciar membros:"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "Para obter mais membros %{trial_link_start}inicie uma avaliação %{trial_link_end} ou %{upgrade_link_start}atualize%{upgrade_link_end} para GitLab Premium ou GitLab Ultimate."
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "Para obter mais membros, inicie uma avaliação:"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "Você atingiu seu limite de membros!"
+
msgid "Freeze end"
msgstr ""
@@ -16945,7 +17190,7 @@ msgid "Full name"
msgstr "Nome completo"
msgid "GCP region configured"
-msgstr ""
+msgstr "Região do GCP configurada"
msgid "GPG Key ID:"
msgstr "ID da chave GPG:"
@@ -17008,10 +17253,10 @@ msgid "Geo"
msgstr "Geo"
msgid "Geo Replication"
-msgstr ""
+msgstr "Replicação de Geo"
msgid "Geo Settings"
-msgstr ""
+msgstr "Configurações de Geo"
msgid "Geo Sites"
msgstr ""
@@ -17072,7 +17317,7 @@ msgid "Geo|All"
msgstr "Todos"
msgid "Geo|All %{replicable_name}"
-msgstr ""
+msgstr "Todos %{replicable_name}"
msgid "Geo|All projects"
msgstr "Todos os projetos"
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr "Erros:"
+msgid "Geo|External URL"
+msgstr "URL externo"
+
msgid "Geo|Failed"
msgstr "Falha"
@@ -17420,7 +17668,7 @@ msgid "Geo|Set the timeout in seconds to send a secondary site status to the pri
msgstr ""
msgid "Geo|Set verification limit and frequency."
-msgstr ""
+msgstr "Definir limite e frequência de verificação."
msgid "Geo|Set what should be replicated by this secondary site."
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17564,7 +17815,7 @@ msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo site."
msgstr ""
msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Você pode ser capaz de fazer um número limitado de mudanças ou executar uma quantidade limitada de ações nessa página."
msgid "Geo|misconfigured"
msgstr "mal configurado"
@@ -17582,7 +17833,7 @@ msgid "Get a free trial"
msgstr "Obtenha um teste gratuito"
msgid "Get a support subscription"
-msgstr ""
+msgstr "Obtenha uma assinatura de suporte"
msgid "Get started"
msgstr "Começar"
@@ -17636,7 +17887,7 @@ msgid "Git strategy"
msgstr "Estratégia de Git"
msgid "Git transfer in progress"
-msgstr ""
+msgstr "Transferência do Git em andamento"
msgid "Git version"
msgstr "Versão do Git"
@@ -17719,9 +17970,6 @@ msgstr "Issue do GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
-msgid "GitLab Logo"
-msgstr "Logotipo do GitLab"
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17753,10 +18001,10 @@ msgid "GitLab events trigger webhooks. Use the request details of a webhook to h
msgstr ""
msgid "GitLab export"
-msgstr ""
+msgstr "Exportação do GitLab"
msgid "GitLab for Jira Cloud"
-msgstr ""
+msgstr "GitLab para Jira Cloud"
msgid "GitLab group: %{source_link}"
msgstr "Grupo do GitLab: %{source_link}"
@@ -17915,7 +18163,7 @@ msgid "GitLabPages|When enabled, all attempts to visit your website through HTTP
msgstr "Quando ativado, todas as tentativas de visitar seu site através de HTTP são redirecionadas automaticamente para HTTPS usando uma resposta com o código de status 301. Requer um certificado válido para todos os domínios. %{docs_link_start}Saiba mais.%{link_end}"
msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with subdomains of subdomains. If your namespace or groupname contains a dot, it does not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages work if you don't redirect HTTP to HTTPS. %{docs_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Ao usar Pages sob o domínio geral de uma instância do GitLab (%{pages_host}), você não pode usar HTTPS com subdomínios de subdomínios. Se seu namespace ou nome de grupo contiver um ponto, ele não funcionará. Esta é uma limitação do protocolo HTTP sobre TLS. As páginas HTTP funcionam se você não redirecionar HTTP para HTTPS. %{docs_link_start}Saiba mais.%{link_end}"
msgid "GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}"
msgstr "Com GitLab Pages, você pode hospedar seu site estático diretamente do seu repositório do GitLab. %{docs_link_start}Saiba mais.%{link_end}"
@@ -18014,7 +18262,7 @@ msgid "Global Shortcuts"
msgstr "Atalhos Globais"
msgid "Global notification level"
-msgstr ""
+msgstr "Nível de notificação global"
msgid "Global notification settings"
msgstr "Configurações de notificação global"
@@ -18068,7 +18316,7 @@ msgid "GlobalSearch|Search GitLab"
msgstr "Pesquisar no GitLab"
msgid "GlobalSearch|Search for projects, issues, etc."
-msgstr ""
+msgstr "Pesquisar por projetos, issues, etc."
msgid "GlobalSearch|Search results are loading"
msgstr "Os resultados da pesquisa estão sendo carregados"
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr "Carregando épicos"
+msgid "GroupRoadmap|New epic"
+msgstr "Novo épico"
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr "Para visualizar o planejamento, adicione uma data de início ou de venci
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para expandir a sua pesquisa, altere ou remova filtros; de %{startDate} para %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr "Ver lista de épicos"
+
msgid "GroupRoadmap|Within 3 years"
msgstr "Dentro de 3 anos"
@@ -18838,8 +19092,8 @@ msgstr "Escolha um caminho de grupo que não comece com um traço ou termine com
msgid "GroupSettings|Compliance frameworks"
msgstr "Frameworks de conformidade"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr "Configure estruturas de conformidade para disponibilizá-las para projetos neste grupo. %{linkStart}Saiba mais.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
msgstr "Configure limites no número de repositórios que os usuários podem baixar em um determinado momento."
@@ -19040,7 +19294,7 @@ msgid "GroupsEmptyState|You can manage your group member’s permissions and acc
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
msgid "GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project."
-msgstr ""
+msgstr "Você não tem as permissões necessárias para criar um subgrupo ou projeto neste grupo. Entre em contato com um proprietário deste grupo para criar um novo subgrupo ou projeto."
msgid "GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
@@ -19183,6 +19437,12 @@ msgstr "O caminho do grupo não está disponível. O caminho foi substituído po
msgid "Groups|Learn more"
msgstr "Saiba mais"
+msgid "Groups|Learn more about subgroups"
+msgstr "Saiba mais sobre subgrupos"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "Deve começar com letra, dígito, emoji ou sublinhado. Também pode conter pontos, traços, espaços e parênteses."
@@ -19201,6 +19461,9 @@ msgstr "Nome do subgrupo"
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr "Você está criando um novo grupo de nível superior"
+
msgid "Guideline"
msgstr "Diretriz"
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr "-- tags"
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19466,7 +19732,7 @@ msgstr[0] "Ocultar gráfico"
msgstr[1] "Ocultar gráficos"
msgid "Hide comments"
-msgstr ""
+msgstr "Ocultar comentários"
msgid "Hide comments on this file"
msgstr "Ocultar comentários nesse arquivo"
@@ -19516,7 +19782,7 @@ msgid "Hierarchy|Deliver value more efficiently by breaking down necessary work
msgstr ""
msgid "Hierarchy|Help us improve work items in GitLab!"
-msgstr ""
+msgstr "Ajude-nos a melhorar os itens de trabalho no GitLab!"
msgid "Hierarchy|Is there a framework or type of work item you wish you had access to in GitLab? Give us your feedback and help us build the experiences valuable to you."
msgstr ""
@@ -19746,24 +20012,45 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "Um novo código foi enviado."
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "Antes de terminar de criar sua conta, precisamos verificar sua identidade. Na página de verificação, insira o código a seguir."
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr "Confirme seu endereço de e-mail"
+
msgid "IdentityVerification|Create a project"
msgstr "Criar um projeto"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "Não recebeu um código?"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "Digitar um código."
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "Digitar um código válido."
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19780,43 +20067,49 @@ msgid "IdentityVerification|If you've lost access to the email associated to thi
msgstr ""
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "Código de discagem internacional"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
msgstr ""
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "Número de telefone"
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "O número de telefone não pode ficar em branco."
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
msgstr ""
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "O número de telefone deve conter apenas dígitos."
msgid "IdentityVerification|Please enter a valid code"
-msgstr ""
+msgstr "Por favor insira um código válido"
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr "Enviar um novo código"
+
msgid "IdentityVerification|Send code"
+msgstr "Enviar código"
+
+msgid "IdentityVerification|Something went wrong. Please try again."
msgstr ""
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr "Etapa 1: verificar o número de telefone"
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr "O código expirou. Envie um novo código e tente novamente."
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr "O código está incorreto. Digite-o novamente ou envie um novo código."
msgid "IdentityVerification|Verification code"
-msgstr ""
+msgstr "Código de verificação"
msgid "IdentityVerification|Verification successful"
msgstr "Verificação bem-sucedida"
@@ -19824,6 +20117,12 @@ msgstr "Verificação bem-sucedida"
msgid "IdentityVerification|Verify code"
msgstr "Verificar código"
+msgid "IdentityVerification|Verify email address"
+msgstr "Verificar endereço de e-mail"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "Verificar forma de pagamento"
+
msgid "IdentityVerification|Verify your identity"
msgstr "Verificar sua identidade"
@@ -19833,14 +20132,17 @@ msgstr "Você sempre pode verificar sua conta posteriormente para criar um grupo
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "Você atingiu a quantidade máxima de reenvios. Aguarde %{interval} e tente novamente."
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr "Você atingiu o número máximo de tentativas. Aguarde %{interval} ou envie um novo código e tente novamente."
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "Sua conta foi verificada com sucesso. Você será redirecionado para sua conta em alguns instantes. Você também pode %{redirect_url_start}atualizar a página%{redirect_url_end}."
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
-msgstr ""
+msgstr "Seu código de verificação expira após %{expires_in_minutes} minutos."
msgid "Identity|Provider ID"
msgstr "ID do provedor"
@@ -19917,6 +20219,12 @@ msgstr "Se você não entrou recentemente, deve imediatamente %{password_link_st
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "Se você não entrou recentemente, deve alterar sua senha imediatamente: %{password_link}."
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr "Se você não tentou entrar recentemente, você deve %{password_link_start}alterar imediatamente sua senha%{password_link_end}."
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr "Se você não tentou entrar recentemente, você deve alterar imediatamente sua senha: %{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 ""
@@ -19926,11 +20234,14 @@ msgstr "Se você perder seus códigos de recuperação, você pode gerar novos,
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "Se você entrou recentemente e reconhece o endereço IP, pode desconsiderar este e-mail."
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr "Se você tentou entrar recentemente, mas inseriu por engano um código de autenticação de dois fatores errado, ignore este e-mail."
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
-msgstr ""
+msgstr "Se você quiser reativar a autenticação de dois fatores, visite %{two_factor_link}"
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
-msgstr ""
+msgstr "Se você quiser reativar a autenticação de dois fatores, visite a página %{settings_link_to}."
msgid "If you want to remove this email address, visit %{profile_link}"
msgstr ""
@@ -20075,7 +20386,7 @@ msgid "Import tasks"
msgstr "Importar tarefas"
msgid "Import tasks from Phabricator into issues"
-msgstr ""
+msgstr "Importar tarefas do Phabricator como issues"
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr "Importação expirou. A importação demorou mais de %{import_jobs_expiration} segundos"
@@ -20107,6 +20418,9 @@ msgstr "Conectar repositórios de"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "URL de importação bloqueada: %{message}"
@@ -20131,6 +20445,9 @@ msgstr "Falha ao solicitar seus repositórios do %{provider}"
msgid "ImportProjects|Select the repositories you want to import"
msgstr "Selecione os repositórios que você deseja importar"
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr "Incompleto"
msgid "Increase"
msgstr "Aumentar"
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr "Ãndice"
@@ -21257,6 +21577,9 @@ msgstr "Adicionar uma integração"
msgid "Integrations|Add namespace"
msgstr "Adicionar espaço de nome"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Todos os detalhes"
@@ -21317,12 +21640,18 @@ msgstr "Ativar verificação de SSL"
msgid "Integrations|Enable comments"
msgstr "Ativar comentários"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr "Digite seu alias"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr "Intervalo"
msgid "Interval Pattern"
msgstr "Padrão de intervalo"
-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 ""
@@ -21678,10 +22007,10 @@ msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{
msgstr "Você foi convidado a participar em %{project_or_group_name} %{project_or_group} como %{role}"
msgid "InviteEmail|You were assigned the following tasks:"
-msgstr ""
+msgstr "Você recebeu as seguintes tarefas:"
msgid "InviteEmail|and has assigned you the following tasks:"
-msgstr ""
+msgstr "e lhe atribuiu as seguintes tarefas:"
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "Colabore com sua equipe"
@@ -21922,6 +22251,12 @@ msgstr "Está usando o assento de licença:"
msgid "Is using seat"
msgstr "Está usando licença"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr "%{wi_type} criado %{created_at} por "
@@ -22021,6 +22356,9 @@ msgstr "Falha ao carregar as issues. Por favor, tente novamente."
msgid "IssueAnalytics|Issue"
msgstr "Issue"
+msgid "IssueAnalytics|Iteration"
+msgstr "Iteração"
+
msgid "IssueAnalytics|Milestone"
msgstr "Marcos"
@@ -22121,7 +22459,7 @@ msgid "Issues closed"
msgstr "Issues fechadas"
msgid "Issues exist in projects, so to create an issue, first create a project."
-msgstr ""
+msgstr "Existem issues em projetos, portanto, para criar uma issue, primeiro crie um projeto."
msgid "Issues must match this scope to appear in this list."
msgstr "As issues devem corresponder a este escopo para aparecer nesta lista."
@@ -22223,13 +22561,13 @@ msgid "Iterations cannot be manually added to cadences that use automatic schedu
msgstr "As iterações não podem ser adicionadas manualmente a cadências que usam agendamento automático"
msgid "IterationsCadence|The automation start date must come after the active iteration %{iteration_dates}."
-msgstr ""
+msgstr "A data de início da automação deve vir após a iteração ativa %{iteration_dates}."
msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
-msgstr ""
+msgstr "A data de início da automação deve vir após a iteração anterior %{iteration_dates}."
msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
-msgstr ""
+msgstr "A data de início da automação criaria retroativamente uma iteração passada. %{start_date} é a data de início mais próxima possível."
msgid "Iterations|Add iteration"
msgstr "Adicionar iteração"
@@ -22310,7 +22648,7 @@ msgid "Iterations|Iteration cadences"
msgstr "Cadências de iteração"
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
-msgstr ""
+msgstr "Iterações|As iterações são uma maneira de acompanhar issues durante um período de tempo, permitindo que as equipes também acompanhem as métricas de velocidade e volatilidade."
msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
msgstr ""
@@ -22364,7 +22702,7 @@ msgid "Iterations|Start date"
msgstr "Data de início"
msgid "Iterations|The date of the first iteration to schedule. This date determines the day of the week when each iteration starts."
-msgstr ""
+msgstr "A data da primeira iteração a ser agendada. Essa data determina o dia da semana em que cada iteração é iniciada."
msgid "Iterations|The duration of each iteration (in weeks)."
msgstr "A duração de cada iteração (em semanas)."
@@ -22373,7 +22711,7 @@ msgid "Iterations|The iteration has been deleted."
msgstr "A iteração foi excluída."
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
-msgstr ""
+msgstr "Isso excluirá a cadência, bem como todas as iterações dentro dela."
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
msgstr "Isso removerá a iteração de quaisquer issues atribuídos a ela."
@@ -22391,13 +22729,10 @@ msgid "Iterations|Unable to save cadence. Please try again."
msgstr ""
msgid "Iterations|Upcoming iterations"
-msgstr ""
-
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
+msgstr "Próximas iterações"
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
-msgstr ""
+msgstr "As datas não podem se sobrepor a outras iterações existentes dentro desta cadência de iterações"
msgid "Iteration|cannot be more than 500 years in the future"
msgstr ""
@@ -22727,7 +23062,7 @@ msgid "Jobs|Create CI/CD configuration file"
msgstr "Criar arquivo de configuração de CI/CD"
msgid "Jobs|Filter jobs"
-msgstr ""
+msgstr "Filtrar tarefas"
msgid "Jobs|Finished"
msgstr "Concluídos"
@@ -23137,7 +23472,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr ""
msgid "Label|Assignee"
-msgstr ""
+msgstr "Responsável"
msgid "Language"
msgstr "Idioma"
@@ -23243,6 +23578,9 @@ msgstr "Última data de entrada:"
msgid "Last successful update"
msgstr "Última atualização bem-sucedida"
+msgid "Last successful update %{time}."
+msgstr "Última atualização bem-sucedida %{time}."
+
msgid "Last time verified"
msgstr ""
@@ -23324,8 +23662,8 @@ msgstr "Saiba como %{no_packages_link_start}publicar e compartilhar seus pacotes
msgid "Learn more"
msgstr "Saiba mais"
-msgid "Learn more about %{username}"
-msgstr "Saiba mais sobre o %{username}"
+msgid "Learn more about %{name}"
+msgstr "Saiba mais sobre o %{name}"
msgid "Learn more about Auto DevOps"
msgstr "Saiba mais sobre o Auto DevOps"
@@ -23391,7 +23729,7 @@ msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
msgstr "Analise seu aplicativo em busca de vulnerabilidades com o DAST"
msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
-msgstr ""
+msgstr "Conclua essas tarefas primeiro para que possa aproveitar ao máximo os recursos do GitLab:"
msgid "LearnGitLab|Create a repository"
msgstr "Criar um repositório"
@@ -23427,7 +23765,7 @@ msgid "LearnGitLab|Plan and execute"
msgstr ""
msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths."
-msgstr ""
+msgstr "Previne mudanças inesperadas em arquivos importantes atribuindo a propriedade de arquivos e caminhos."
msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
msgstr "Pronto para começar com o GitLab? Siga estas etapas para configurar sua área de trabalho, planejar e comprometer as alterações e publicar seu projeto."
@@ -23442,7 +23780,7 @@ msgid "LearnGitLab|Run a Security scan using CI/CD"
msgstr "Execute uma verificação de segurança usando CI/CD"
msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
-msgstr ""
+msgstr "Aprenda tempo economizando ao automatizar suas tarefas de integração e implementação."
msgid "LearnGitLab|Scan dependencies for licenses"
msgstr ""
@@ -23466,7 +23804,7 @@ msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
msgstr "Comece uma avaliação gratuita do GitLab Ultimate"
msgid "LearnGitLab|Submit a merge request (MR)"
-msgstr ""
+msgstr "Enviar uma solicitação de mesclagem (MR)"
msgid "LearnGitLab|Try GitLab Ultimate for free"
msgstr ""
@@ -23538,7 +23876,7 @@ msgid "License Compliance"
msgstr "Conformidade de licença"
msgid "License Compliance| Used by %{dependencies}"
-msgstr ""
+msgstr "Usado por %{dependencies}"
msgid "License compliance"
msgstr "Conformidade de licença"
@@ -23592,18 +23930,18 @@ msgstr[1] ""
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
-msgstr[0] "License Compliance detectou %d violação de licença e política apenas para a filial de origem; aprovação necessária"
-msgstr[1] "License Compliance detectou %d licenças e violações de política apenas para a filial de origem; aprovação necessária"
+msgstr[0] "Conformidade de licença detectou %d violação de licença e política apenas para a filial de origem; aprovação necessária"
+msgstr[1] "Conformidade de licença detectou %d licenças e violações de política apenas para a filial de origem; aprovação necessária"
msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
-msgstr[0] "License Compliance detectou %d licença apenas para o branch de origem"
-msgstr[1] "License Compliance detectou %d licenças apenas para o branch de origem"
+msgstr[0] "Conformidade de licença detectou %d licença apenas para o branch de origem"
+msgstr[1] "Conformidade de licença detectou %d licenças apenas para o branch de origem"
msgid "LicenseCompliance|License Compliance detected %d new license"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
-msgstr[0] "License Compliance detectou %d nova licença"
-msgstr[1] "License Compliance detectou %d novas licenças"
+msgstr[0] "Conformidade de licença detectou %d nova licença"
+msgstr[1] "Conformidade de licença detectou %d novas licenças"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
@@ -23616,10 +23954,10 @@ msgstr[0] ""
msgstr[1] ""
msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
-msgstr "License Compliance não detectou licenças apenas para o branch de origem"
+msgstr "Conformidade de licença não detectou licenças apenas para o branch de origem"
msgid "LicenseCompliance|License Compliance detected no new licenses"
-msgstr "License Compliance não detectou novas licenças"
+msgstr "Conformidade de licença não detectou novas licenças"
msgid "LicenseCompliance|License name"
msgstr "Nome da licença"
@@ -23649,7 +23987,7 @@ msgid "LicenseCompliance|Uncategorized"
msgstr "Sem categoria"
msgid "LicenseCompliance|Update approvals"
-msgstr ""
+msgstr "Atualizar aprovações"
msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
msgstr "Você está prestes a remover a licença %{name} deste projeto."
@@ -24096,7 +24434,7 @@ msgid "Mailgun events"
msgstr ""
msgid "Main menu"
-msgstr ""
+msgstr "Menu principal"
msgid "Maintenance mode"
msgstr ""
@@ -24113,6 +24451,9 @@ msgstr "Faça com que todos em sua equipe sejam mais produtivos, independentemen
msgid "Make issue confidential"
msgstr "Tornar essa issue confidencial"
+msgid "Make sure you choose a strong, unique password."
+msgstr "Certifique-se de escolher uma senha forte e única."
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,12 +24505,12 @@ msgstr "Gerencie projeto."
msgid "Manage two-factor authentication"
msgstr "Gerenciar a autenticação de dois fatores"
-msgid "Manage your license"
-msgstr "Gerenciar sua licença"
-
msgid "Manage your project's triggers"
msgstr "Gerenciar os gatilhos do seu projeto"
+msgid "Manage your subscription"
+msgstr "Gerencie sua assinatura"
+
msgid "Managed Account"
msgstr "Conta gerenciada"
@@ -24251,7 +24592,22 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgstr "Suporta %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+
+msgid "Marked"
msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr "Marcado como uma issue relacionada a %{issue_ref}."
msgid "Marked to do as done."
msgstr "Marcou tarefa como concluída."
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24456,13 +24809,13 @@ msgid "Maximum files in a diff"
msgstr ""
msgid "Maximum group export download requests per minute"
-msgstr ""
+msgstr "Máximo de requisições de download de exportação de grupo por minuto"
msgid "Maximum group export requests per minute"
-msgstr ""
+msgstr "Máximo de requisições de exportação de grupo por minuto"
msgid "Maximum group import requests per minute"
-msgstr ""
+msgstr "Máximo de requisições de importação de grupo por minuto"
msgid "Maximum import size"
msgstr "Tamanho máximo de importação"
@@ -24501,10 +24854,10 @@ msgid "Maximum number of projects."
msgstr "Número máximo de projetos."
msgid "Maximum number of requests per minute"
-msgstr ""
+msgstr "Número máximo de requisições por minuto"
msgid "Maximum number of requests per minute for an authenticated user"
-msgstr ""
+msgstr "Número máximo de requisições por minuto para um usuário autenticado"
msgid "Maximum number of requests per minute for an unauthenticated IP address"
msgstr ""
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr "Máximo de 255 caracteres"
@@ -24540,7 +24896,7 @@ msgid "Maximum push size (MB)"
msgstr "Tamanho máximo de push (MB)"
msgid "Maximum requests per 10 minutes per user"
-msgstr ""
+msgstr "Máximo de requisições por 10 minutos por usuário"
msgid "Maximum requests per minute"
msgstr "Requisições máximas por minuto"
@@ -24871,7 +25227,7 @@ msgid "Merge requests"
msgstr "Solicitações de mesclagem"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "As configurações de solicitações e aprovações de mesclagem foram movidas."
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"
@@ -25589,7 +25945,7 @@ msgid "Milestones|Completed Issues (closed)"
msgstr "Issues concluídas (fechadas)"
msgid "Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}"
-msgstr ""
+msgstr "Crie um marco para acompanhar melhor seus problemas e solicitações de mesclagem. %{learn_more_link}"
msgid "Milestones|Delete milestone"
msgstr "Excluir marco"
@@ -25610,7 +25966,7 @@ msgid "Milestones|Ongoing Issues (open and assigned)"
msgstr "Issues em andamento (abertas e atribuídas)"
msgid "Milestones|Organize issues and merge requests into a cohesive group, and set optional start and due dates. %{learn_more_link}"
-msgstr ""
+msgstr "Organize issues e mescle solicitações em um grupo coeso e defina datas opcionais de início e vencimento. %{learn_more_link}"
msgid "Milestones|Project Milestone"
msgstr "Marco do projeto"
@@ -25631,10 +25987,10 @@ msgid "Milestones|Reopen Milestone"
msgstr "Reabrir marco"
msgid "Milestones|There are no closed milestones"
-msgstr ""
+msgstr "Não há marcos fechados"
msgid "Milestones|There are no open milestones"
-msgstr ""
+msgstr "Não há marcos abertos"
msgid "Milestones|This action cannot be reversed."
msgstr "Essa ação não pode ser revertida."
@@ -25643,7 +25999,10 @@ msgid "Milestones|Unstarted Issues (open and unassigned)"
msgstr "Issues não iniciadas (abertas e não atribuídas)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
-msgstr ""
+msgstr "Use marcos para acompanhar issues e mesclar solicitações em um período fixo de tempo"
+
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} completo"
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr "Espelhar usuário"
+msgid "Mirrored from %{link}."
+msgstr "Espelhado de %{link}."
+
msgid "Mirrored repositories"
msgstr "Repositórios espelhados"
@@ -25829,7 +26191,7 @@ msgid "Move selection up"
msgstr "Mover a seleção para cima"
msgid "Move test case"
-msgstr ""
+msgstr "Mover caso de teste"
msgid "Move this issue to another project."
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr "O nome já está em uso."
msgid "Name new label"
msgstr "Nome da nova etiqueta"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Nome:"
@@ -26147,6 +26512,9 @@ msgstr "Novo Agendamento de Pipeline"
msgid "New Project"
msgstr "Novo projeto"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Novo requisito"
@@ -26637,7 +27005,7 @@ msgid "No vulnerabilities present"
msgstr ""
msgid "No webhook events"
-msgstr ""
+msgstr "Nenhum evento de webhook"
msgid "No webhooks enabled. Select trigger events above."
msgstr "Nenhum webhooks ativado. Selecione os eventos de gatilho acima."
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr "Sem quebra automática"
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr "Notificar usuários por e-mail quando o local de login não for reconhec
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} em %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email}, agora conhecido como %{user_name}, aceitou seu convite para se juntar ao %{target_name} %{target_model_name}."
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "%{invited_user} %{highlight_start}recusou%{highlight_end} seu convite para participar do %{target_link} %{target_name}."
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} solicitou %{member_role} acesso ao %{target_source_link} %{target_type}."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
-msgstr "%{mr_highlight}A solicitação de mesclagem%{highlight_end} %{mr_link} %{approved_highlight}foi aprovada por%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}A solicitação de mesclagem%{highlight_end} %{mr_link} %{reviewer_highlight}foi aprovada por%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}A solicitação de mesclagem%{highlight_end} %{mr_link} %{reviewer_highlight}não foi aprovada por%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr "%{name} solicitou uma nova revisão em %{mr_link}."
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr "Uma nova chave GPG foi adicionada à sua conta:"
+msgid "Notify|A remote mirror update has failed."
+msgstr "Uma atualização de espelho remoto falhou."
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr "O pipeline de DevOps automático foi desativado para %{project}"
msgid "Notify|CI/CD project settings"
msgstr "Configurações do projeto CI/CD"
+msgid "Notify|Click here to set your password"
+msgstr "Clique aqui para definir sua senha"
+
+msgid "Notify|Commit Author"
+msgstr "Autor do commit "
+
+msgid "Notify|Committed by"
+msgstr "Comit por"
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr "Impressão digital: %{fingerprint}"
+msgid "Notify|Hi %{username}!"
+msgstr "Olá %{username}!"
+
msgid "Notify|Hi %{user}!"
msgstr "Olá %{user}!"
@@ -27006,6 +27428,9 @@ msgstr "A issue foi movida para outro projeto."
msgid "Notify|Learn more about Auto DevOps"
msgstr "Saiba mais sobre Auto DevOps"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr "A solicitação de mesclagem %{merge_request} não pode mais ser mesclada devido a conflito."
@@ -27030,24 +27455,66 @@ msgstr "A solicitação de mesclagem foi aprovada"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr "A solicitação de mesclagem foi aprovada (%{approvals}%{required_approvals}"
+msgid "Notify|Merge request was unapproved"
+msgstr "A solicitação de mesclagem não foi aprovada"
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr "A solicitação de mesclagem não foi aprovada%{approvals_count}%{approvals_required})"
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr "Marco alterado para %{milestone}"
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "Marco removido"
msgid "Notify|New issue: %{project_issue_url}"
msgstr "Nova issue: %{project_issue_url}"
+msgid "Notify|No preview for this file type"
+msgstr "Nenhuma pré-visualização disponível para este tipo de arquivo"
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline %{pipeline_link} acionado por"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "Pipeline foi corrigido e #%{pipeline_id} foi aprovado!"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr "O projeto %{project_name} foi exportado com sucesso."
+
+msgid "Notify|Remote mirror"
+msgstr "Espelho remoto"
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "O link de download expirará em 24 horas."
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr "Essa issue vence em: %{issue_due_date}"
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr "A menos que você verifique seu domínio até %{time_start}%{time}%{time_end} , ele será removido do seu projeto no GitLab."
@@ -27060,12 +27527,33 @@ msgstr "Você foi mencionado em uma issue."
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr "Você foi mencionado na solicitação de mesclagem %{mr_link}"
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "Você cancelou o recebimento de notificações do administrador do GitLab."
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "Sua solicitação para participar do %{target_to_join} %{target_type} foi %{denied_tag}."
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr "excluído"
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "concluído com sucesso %{jobs} em %{stages}."
@@ -27126,6 +27614,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "O objeto não existe no servidor ou você não tem permissão para acessá-lo"
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Out"
@@ -27165,7 +27656,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "Na barra lateral esquerda, selecione %{merge_requests_link} para visualizá-las."
msgid "On track"
msgstr "Sob controle"
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr "Roteamento de alertas de diretamente para membros específicos de sua equipe"
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27662,7 +28156,7 @@ msgid "Oops, are you sure?"
msgstr "Oops, você tem certeza?"
msgid "Open"
-msgstr "Aberta"
+msgstr "Aberto"
msgid "Open Selection"
msgstr "Abrir seleção"
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27920,7 +28417,7 @@ msgid "Package already exists"
msgstr ""
msgid "Package and registry settings"
-msgstr ""
+msgstr "Configurações de pacote e registro"
msgid "Package deleted successfully"
msgstr ""
@@ -27998,7 +28495,7 @@ msgid "PackageRegistry|App name: %{name}"
msgstr ""
msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
-msgstr ""
+msgstr "Construído pelo pipeline %{link} disparado %{datetime} por %{author}"
msgid "PackageRegistry|Composer"
msgstr ""
@@ -28079,7 +28576,7 @@ msgid "PackageRegistry|Copy yarn setup command"
msgstr "Copiar comando de configuração yarn"
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
-msgstr ""
+msgstr "Criado pelo commit %{link} na ramificação %{branch}"
msgid "PackageRegistry|Debian"
msgstr "Debian"
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Excluir versão do pacote"
msgid "PackageRegistry|Delete package"
msgstr "Excluir pacote"
+msgid "PackageRegistry|Delete package asset"
+msgstr "Excluir ativos do pacote"
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr "Nível de instância"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "Último download %{dateTime}"
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Saiba como %{noPackagesLinkStart}publicar e compartilhar seus pacotes%{noPackagesLinkEnd} com o GitLab."
@@ -28197,13 +28697,13 @@ msgstr "Número de ativos duplicados a serem mantidos"
msgid "PackageRegistry|Package Registry"
msgstr "Registro de pacote"
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28230,7 +28733,7 @@ msgid "PackageRegistry|Publish packages if their name or version matches this re
msgstr "Publique pacotes se seu nome ou versão corresponder a este regex."
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
-msgstr ""
+msgstr "Publicado no registro do pacote %{project} há %{datetime}"
msgid "PackageRegistry|PyPI"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr "Quando um pacote com o mesmo nome e versão é carregado no registro, ma
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28352,7 +28855,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr "publicado por %{author}"
msgid "Packages and registries"
-msgstr ""
+msgstr "Pacotes e registros"
msgid "Page not found"
msgstr "Página não encontrada"
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr "Pausar"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28679,7 +29179,7 @@ msgid "Period of inactivity (days)"
msgstr "Período de inatividade (dias)"
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "Período de inatividade antes da desativação."
msgid "Permalink"
msgstr "Link permanente"
@@ -28691,7 +29191,7 @@ msgid "Permissions"
msgstr "Permissões"
msgid "Permissions Help"
-msgstr ""
+msgstr "Ajuda de permissões"
msgid "Permissions and group features"
msgstr "Permissões e funcionalidade de grupo"
@@ -28730,7 +29230,7 @@ msgid "Phabricator Server URL"
msgstr ""
msgid "Phabricator Tasks"
-msgstr ""
+msgstr "Tarefas de Phabricator"
msgid "Phone"
msgstr "Telefone"
@@ -28883,22 +29383,22 @@ msgid "PipelineEditor|Configuration content has changed. Re-run validation for u
msgstr ""
msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
-msgstr ""
+msgstr "O conteúdo atual na guia Editar será usado para a simulação."
msgid "PipelineEditor|Git push event to the default branch"
-msgstr ""
+msgstr "Evento de Git push para a ramificação padrão"
msgid "PipelineEditor|Other pipeline sources are not available yet."
-msgstr ""
+msgstr "Outras fontes de pipeline ainda não estão disponíveis."
msgid "PipelineEditor|Pipeline Source"
-msgstr ""
+msgstr "Fonte do pipeline"
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies."
-msgstr ""
+msgstr "O comportamento do pipeline será simulado incluindo as dependências de trabalho de %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}only%{codeEnd} e %{codeStart}needs%{codeEnd}."
msgid "PipelineEditor|Pipeline behavior will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "O comportamento do pipeline será simulado incluindo as dependências de trabalho de %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}only%{codeEnd} e %{codeStart}needs%{codeEnd}. %{linkStart}Saiba mais%{linkEnd}"
msgid "PipelineEditor|Pipeline simulation completed with errors"
msgstr ""
@@ -28922,16 +29422,16 @@ msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file
msgstr ""
msgid "PipelineEditor|Validate pipeline"
-msgstr ""
+msgstr "Validar pipeline"
msgid "PipelineEditor|Validate pipeline under selected conditions"
-msgstr ""
+msgstr "Validar pipeline sob condições selecionadas"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
-msgstr ""
+msgstr "Validar pipeline sob condições simuladas"
msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
-msgstr ""
+msgstr "Validando pipeline... Pode levar até um minuto."
msgid "PipelineEditor|Waiting for CI content to load..."
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Ativo"
msgid "PipelineSchedules|All"
msgstr "Todos"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr "Descrição"
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inativo"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Próxima Execução"
@@ -28960,15 +29472,27 @@ msgstr "Nenhum"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Digite uma descrição curta para esta pipeline"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Tornar-se proprietário"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Destino"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variáveis"
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29123,7 +29653,7 @@ msgid "Pipelines|Clear runner caches"
msgstr "Limpar cache dos executores"
msgid "Pipelines|Configuration validation currently not available."
-msgstr ""
+msgstr "Validação de configuração atualmente não disponível."
msgid "Pipelines|Configure pipeline"
msgstr ""
@@ -29282,10 +29812,10 @@ msgid "Pipelines|This is a child pipeline within the parent pipeline"
msgstr "Este é um pipeline filho dentro do pipeline pai"
msgid "Pipelines|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
-msgstr ""
+msgstr "Este pipeline foi executado no conteúdo desta solicitação de mesclagem combinado com o conteúdo de todas as outras solicitações de mesclagem enfileiradas para mesclagem na ramificação de destino."
msgid "Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+msgstr "Este pipeline foi executado no conteúdo da ramificação de origem desta solicitação de mesclagem, não na ramificação de destino."
msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
msgstr ""
@@ -29312,7 +29842,7 @@ msgid "Pipelines|Use template"
msgstr "Usar modelo"
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "Validar"
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr "Validando a configuração do GitLab CI…"
@@ -29396,7 +29926,7 @@ msgid "Pipeline|Manual"
msgstr "Manual"
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "Pipeline de solicitação de mesclagem"
msgid "Pipeline|Merge train pipeline"
msgstr "Pipeline de merge train"
@@ -29480,10 +30010,10 @@ msgid "Pipeline|This change will not change the overall test coverage if merged.
msgstr ""
msgid "Pipeline|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch."
-msgstr ""
+msgstr "Este pipeline foi executado no conteúdo desta solicitação de mesclagem combinado com o conteúdo de todas as outras solicitações de mesclagem enfileiradas para mesclagem na ramificação de destino."
msgid "Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+msgstr "Este pipeline foi executado no conteúdo da ramificação de origem desta solicitação de mesclagem, não na ramificação de destino."
msgid "Pipeline|To run a merge request pipeline, the jobs in the CI/CD configuration file %{linkStart}must be configured%{linkEnd} to run in merge request pipelines."
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr "Por favor, digite %{phrase_code} para continuar ou feche este modal para
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "Por favor, use este formulário para denunciar aos administradores as contas que criam spam em issues, comentários ou se comportam de maneira inapropriada."
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr "Por favor, aguarde alguns instantes enquanto carregamos o histórico do arquivo para esta linha."
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Por favor, espere um momento, essa página será atualizada automaticamente."
@@ -29773,6 +30306,9 @@ msgstr "Por favor, aguarde enquanto conectamos ao seu repositório. Atualize à
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Por favor, aguarde enquanto importamos o repositório para você. Atualize à vontade."
+msgid "Please wait while we prepare for verification."
+msgstr "Por favor, aguarde enquanto nos preparamos para a verificação."
+
msgid "Pods in use"
msgstr "Pods em uso"
@@ -29833,6 +30369,9 @@ msgstr "Preferências"
msgid "Preferences saved."
msgstr "Preferências salvas."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Comportamento"
@@ -29840,7 +30379,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr "Escolha entre layout do aplicativo fixo (máx. 1280px) ou fluido (%{percentage})."
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "Escolha o conteúdo que você deseja ver por padrão em seu painel."
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Escolha o conteúdo que você quer ver na página de visão geral de um projeto."
@@ -29867,7 +30406,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr "Personalize as cores das linhas removidas e adicionadas em diffs."
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "Painel"
msgid "Preferences|Diff colors"
msgstr "Cores em Diff"
@@ -29944,6 +30483,9 @@ msgstr "Preferências de hora"
msgid "Preferences|Use relative times"
msgstr "Usar tempos relativos"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "Quando você digita em uma descrição ou caixa de comentário, o texto selecionado é cercado pelo caractere correspondente após digitar um dos seguintes caracteres: %{supported_characters}."
@@ -30157,15 +30699,9 @@ msgstr "Ativo"
msgid "Profiles|Add key"
msgstr "Adicionar chave"
-msgid "Profiles|Add status emoji"
-msgstr "Adicionar emoji de status"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "Ocorreu um erro ao atualizar seu nome de usuário, por favor, tente novamente."
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr "Um indicador aparece ao lado do seu nome e avatar."
-
msgid "Profiles|Avatar cropper"
msgstr "Recortar Avatar"
@@ -30178,9 +30714,6 @@ msgstr "Começa com %{ssh_key_algorithms}."
msgid "Profiles|Bio"
msgstr "Bio"
-msgid "Profiles|Busy"
-msgstr "Ocupado"
-
msgid "Profiles|Change username"
msgstr "Alterar nome de usuário"
@@ -30196,9 +30729,6 @@ msgstr "Escolha para mostrar contribuições de projetos privados em seu perfil
msgid "Profiles|City, country"
msgstr "Cidade, país"
-msgid "Profiles|Clear status"
-msgstr "Limpar status"
-
msgid "Profiles|Commit email"
msgstr "E-mail de commit"
@@ -30211,6 +30741,9 @@ msgstr "Conecte um serviço para entrar."
msgid "Profiles|Connected Accounts"
msgstr "Contas conectadas"
+msgid "Profiles|Created%{time_ago}"
+msgstr "Criado há %{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "Caminho atual: %{path}"
@@ -30448,9 +30981,6 @@ msgstr "Usar emojis em nomes parece divertido, mas tente definir uma mensagem de
msgid "Profiles|Website url"
msgstr "URL do site"
-msgid "Profiles|What's your status?"
-msgstr "Qual é o seu status?"
-
msgid "Profiles|Who you represent or work for."
msgstr "Por quem você representa ou trabalha."
@@ -30473,7 +31003,7 @@ msgid "Profiles|You must accept the Terms of Service in order to perform this ac
msgstr ""
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
-msgstr ""
+msgstr "Você deve transferir a propriedade ou excluir grupos dos quais você é proprietário antes de poder excluir sua conta"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
msgstr "Você precisa delegar outro usuário para ser dono ou apagar esses grupos antes de excluir sua conta."
@@ -30496,9 +31026,6 @@ msgstr "O seu nome foi definido automaticamente com base na sua conta do %{provi
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "Seu nome foi definido automaticamente com base na sua conta %{provider_label}, para que as pessoas que você conhece possam reconhecê-lo."
-msgid "Profiles|Your status"
-msgstr "Seu status"
-
msgid "Profiles|https://website.com"
msgstr "https://website.com"
@@ -30662,7 +31189,7 @@ msgid "Project security status"
msgstr "Status de segurança do projeto"
msgid "Project security status help page"
-msgstr ""
+msgstr "Página de ajuda do status de segurança do projeto"
msgid "Project slug"
msgstr "Slug do projeto"
@@ -30988,6 +31515,9 @@ msgstr "Escolha seu método de mesclagem, opções de mesclagem, verificações
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr "Escolha seu método de mesclagem, opções, verificações e opções de compactação."
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "Configure os recursos do projeto e monitore a saúde deles."
@@ -31018,6 +31548,9 @@ msgstr "Ativar merge train"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr "Ativar pipelines de resultados mesclados"
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "Ativar revisores sugeridos"
+
msgid "ProjectSettings|Encourage"
msgstr "Incentivar"
@@ -31141,12 +31674,18 @@ msgstr "Sugestões de mesclagem"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr "Mesclar só é permitido quando a ramificação de origem está atualizada com seu destino."
+msgid "ProjectSettings|Monitor"
+msgstr "Monitor"
+
msgid "ProjectSettings|No merge commits are created."
msgstr "Nenhum commit de mesclagem foi criado."
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr "Observação: o container registry está sempre visível quando um projeto é público e o container registry está definido como '%{access_level_description}'"
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Apenas para commits assinados pode-se fazer push para este repositório."
@@ -31183,6 +31722,9 @@ msgstr "Visibilidade do projeto"
msgid "ProjectSettings|Public"
msgstr "Público"
+msgid "ProjectSettings|Releases"
+msgstr "Versões"
+
msgid "ProjectSettings|Repository"
msgstr "Repositório"
@@ -31283,7 +31825,7 @@ msgid "ProjectSettings|Transfer project"
msgstr "Transferir projeto"
msgid "ProjectSettings|Upstream project"
-msgstr ""
+msgstr "Projeto upstream"
msgid "ProjectSettings|Used for every new merge request."
msgstr "Usado para cada nova solicitação de mesclagem."
@@ -31336,8 +31878,8 @@ msgstr "Quando há um conflito de mesclagem, o usuário tem a opção de rebase.
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr "Com o GitLab Pages você pode hospedar seus sites estáticos no GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr "Com GitLab Pages você pode hospedar seus sites estáticos no GitLab. O GitLab Pages usa um mecanismo de cache para eficiência. Suas alterações podem não entrar em vigor até que o cache seja invalidado, o que geralmente leva menos de um minuto."
msgid "ProjectTemplates|.NET Core"
msgstr ".NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr "Atividade"
@@ -31948,6 +32493,9 @@ msgstr "Permitido para push"
msgid "ProtectedBranch|Allowed to push:"
msgstr "Permitido para push:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Ramificação"
@@ -31984,6 +32532,9 @@ msgstr "Ramificação protegida (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "Ramificações protegidas"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr "Ramificações protegidas, aprovações de solicitações de mesclagem e verificações de status aparecerão aqui depois de configurados."
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr "Rejeitar o código envia os arquivos de alteração listados no arquivo CODEOWNERS."
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr "O que são ramificações protegidas?"
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr "Você pode adicionar apenas grupos que tenham este projeto compartilhado. %{learn_more_link}"
+
msgid "ProtectedBranch|default"
msgstr "padrão"
@@ -32108,7 +32662,7 @@ msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to dep
msgstr ""
msgid "Provide Feedback"
-msgstr ""
+msgstr "Fornecer feedback"
msgid "Provide a number our sales team can use to call you."
msgstr "Forneça um número que nossa equipe de vendas possa usar para ligar para você."
@@ -32135,7 +32689,7 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "Público - O projeto pode ser acessado sem nenhuma autenticação."
msgid "Public Access Help"
-msgstr ""
+msgstr "Ajuda de acesso público"
msgid "Public deploy keys"
msgstr "Chaves públicas de implantação"
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr "Todas as mensagens de commit devem corresponder a esta %{wiki_syntax_lin
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr "Todos os nomes de arquivos confirmados não podem corresponder a essa %{wiki_syntax_link_start}expressão regular%{wiki_syntax_link_end}. Se vazio, qualquer nome de arquivo é permitido."
+msgid "PushRules|Branch name"
+msgstr "Nome da ramificação"
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr "Verifique se o autor do commit é um usuário do GitLab"
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr "Mensagens de commit não podem corresponder a essa %{wiki_syntax_link_start}expressão regular%{wiki_syntax_link_end}. Se estiver vazio, as mensagens de confirmação não serão rejeitadas com base em nenhuma expressão."
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr "Não permitir que os usuários removam tags do Git com %{code_block_start}git push%{code_block_end}"
+msgid "PushRules|Maximum file size (MB)"
+msgstr "Tamanho máximo do arquivo (MB)"
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr "Nomes de arquivos proibidos"
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr "Rejeita quaisquer arquivos que provavelmente contenham segredos. %{secret_files_link_start}Quais arquivos secretos são rejeitados?%{secret_files_link_end}"
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr "Rejeitar expressão em mensagens de confirmação"
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr "Rejeitar tamanhos de arquivo iguais ou maiores que este tamanho. Se definido como 0, arquivos de qualquer tamanho são permitidos. Esta regra não se aplica a arquivos rastreados pelo Git LFS."
+msgid "PushRules|Reject unsigned commits"
+msgstr "Rejeitar commits não assinados"
+
+msgid "PushRules|Require expression in commit messages"
+msgstr "Requer expressão em mensagens de confirmação"
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr "Restringir commits para usuários existentes do GitLab."
@@ -32395,9 +32982,6 @@ msgstr "Leia mais"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr "Leia mais sobre épicos relacionados"
@@ -32411,7 +32995,7 @@ msgid "Ready to get started with GitLab? Follow these steps to set up your works
msgstr ""
msgid "Ready to merge by members who can write to the target branch."
-msgstr ""
+msgstr "Pronto para mesclar por membros que podem escrever na ramificação de destino."
msgid "Ready to merge!"
msgstr "Pronto para mesclar!"
@@ -32553,9 +33137,6 @@ msgstr "Registrar dispositivo de dois fatores universal (U2F)"
msgid "Register WebAuthn Device"
msgstr "Registrar dispositivo WebAuthn"
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr "Registre quantos executores você quiser. Você pode registrar executores como usuários separados, em servidores separados e em sua máquina local. Os executores também são:"
-
msgid "Register device"
msgstr "Registar dispositivo"
@@ -33042,7 +33623,7 @@ msgid "Reopen milestone"
msgstr "Reabrir marco"
msgid "Reopen test case"
-msgstr ""
+msgstr "Reabrir caso de teste"
msgid "Reopen this %{quick_action_target}"
msgstr "Reabrir este %{quick_action_target}"
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr "Configuração de espelhamento de repositório"
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "O repositório deve conter pelo menos 1 arquivo."
@@ -33825,6 +34409,9 @@ msgstr "Revogado o token de representação %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Revogado o token de acesso pessoal %{personal_access_token_name}!"
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr "Copiar endereço de e-mail"
@@ -33846,6 +34433,9 @@ msgstr "Cargo"
msgid "Rollback"
msgstr "Reverter"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -34062,7 +34652,7 @@ msgid "Runners|Executor"
msgstr "Executor"
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "Filtrar projetos"
msgid "Runners|Get started with runners"
msgstr "Comece com os executores"
@@ -34070,6 +34660,9 @@ msgstr "Comece com os executores"
msgid "Runners|Group"
msgstr "Grupo"
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr "Tempo limite máximo da tarefa"
msgid "Runners|Members of the %{type} can register runners"
msgstr "Membros do %{type} podem registrar executores"
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr "Executores de vários projetos não podem ser excluídos"
-
msgid "Runners|Name"
msgstr "Nome"
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr "Nunca contatados:"
+msgid "Runners|Never expires"
+msgstr "Nunca expira"
+
msgid "Runners|New group runners view"
msgstr "Visualização dos novos executores no grupo"
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "Token de registro"
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr "Executor atribuído ao projeto."
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr "Expiração do token de autenticação do executor"
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr "Executores"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "Executores são os agentes que executam seus trabalhos de CI/CD. Siga as %{linkStart}instruções de instalação e registro%{linkEnd} para configurar um runner."
@@ -34273,6 +34875,9 @@ msgstr "Selecione projetos para atribuir a este executor"
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr "Mostrar instruções de instalação e registro do executor"
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr "Tags"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr "Leve-me lá!"
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr "Expiração do token"
+
msgid "Runners|Up to date"
msgstr "Atualizado"
@@ -34471,7 +35082,7 @@ msgid "SSH Keys"
msgstr "Chaves SSH"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "Ajuda de chaves SSH"
msgid "SSH fingerprints verify that the client is connecting to the correct host. Check the %{config_link_start}current instance configuration%{config_link_end}."
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr "Salvando projeto."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr "%{ifLabelStart}se%{ifLabelEnd} %{rules} ações para os %{scopes} %{branches}"
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr "%{period} %{days} a %{time}"
@@ -34710,6 +35318,9 @@ msgstr "Pesquisar responsável"
msgid "Search authors"
msgstr "Pesquisar autores"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Pesquisar ramificações"
@@ -34797,6 +35408,9 @@ msgstr "Pesquisar projetos"
msgid "Search projects..."
msgstr "Pesquisar projetos..."
+msgid "Search protected branches"
+msgstr "Pesquisar ramificações protegidas"
+
msgid "Search rate limits"
msgstr ""
@@ -35101,14 +35715,14 @@ msgstr "Gerenciar perfis"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr "Gerenciar perfis para uso pelas verificações de DAST."
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr "Mais tipos de verificação, incluindo verificação de contêiner, DAST, verificação de dependência, fuzzing e conformidade de licença"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "Não ativado"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
-msgstr "Depois de ativar uma verificação para a ramificação padrão, qualquer ramificação de recurso subsequente que você criar incluirá a verificação."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
+msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
msgstr "Ative rapidamente todos os testes contínuos e ferramentas de conformidade ativando %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} mais"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35258,7 +35869,7 @@ msgid "SecurityOrchestration|Enabled"
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}"
+msgstr "Forçar segurança para este projeto. %{linkStart}Mais informações.%{linkEnd}"
msgid "SecurityOrchestration|Failed to load cluster agents."
msgstr ""
@@ -35306,7 +35917,7 @@ msgid "SecurityOrchestration|Not enabled"
msgstr ""
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
-msgstr ""
+msgstr "Somente proprietários podem atualizar o projeto de política de segurança"
msgid "SecurityOrchestration|Policies"
msgstr "Políticas"
@@ -35569,6 +36180,9 @@ msgstr "Criar uma Jira do Jira"
msgid "SecurityReports|Create issue"
msgstr "Criar issue"
+msgid "SecurityReports|Detection"
+msgstr "Detecção"
+
msgid "SecurityReports|Development vulnerabilities"
msgstr "Vulnerabilidades de desenvolvimento"
@@ -35581,6 +36195,9 @@ msgstr "Dispensar '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr "Não tem issue"
+
msgid "SecurityReports|Download %{artifactName}"
msgstr "Baixar %{artifactName}"
@@ -35611,12 +36228,18 @@ msgstr "Erro ao analisar relatórios de segurança"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr "Tem issue"
+
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar dispensados"
msgid "SecurityReports|Image"
msgstr "Imagem"
+msgid "SecurityReports|Issue"
+msgstr "Issue"
+
msgid "SecurityReports|Issue Created"
msgstr "Issue criada"
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "Status"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Selecionar Formato do Arquivo"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr "Selecionar Página"
-
msgid "Select Profile"
msgstr "Selecionar perfil"
@@ -35905,9 +36528,6 @@ msgstr "Selecione um repositório de modelos"
msgid "Select a template type"
msgstr "Selecione um tipo de modelo"
-msgid "Select a time zone"
-msgstr "Selecione um fuso horário"
-
msgid "Select a timezone"
msgstr "Selecionar fuso horário"
@@ -35929,9 +36549,15 @@ msgstr "Selecionar responsável"
msgid "Select branch"
msgstr "Selecionar ramificação"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Selecionar validade"
@@ -35977,6 +36603,9 @@ msgstr "Selecione o projeto para criar a issue"
msgid "Select projects"
msgstr "Selecionar projetos"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Selecionar revisor(es)"
@@ -36068,7 +36697,7 @@ msgid "SelfMonitoring|Deactivating self monitoring deletes the self monitoring p
msgstr ""
msgid "SelfMonitoring|Self monitoring"
-msgstr ""
+msgstr "Automonitoramento"
msgid "SelfMonitoring|Self monitoring is active. Use the %{projectLinkStart}self monitoring project%{projectLinkEnd} to monitor the health of your instance."
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr "Selecionar ramificação de destino"
msgid "Set target branch to %{branch_name}."
msgstr "Definir ramificação de destino à %{branch_name}."
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr "Definir peso"
msgid "Set weight to %{weight}."
msgstr "Define o peso para %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "Um indicador aparece ao lado do seu nome e avatar"
-
-msgid "SetStatusModal|Busy"
-msgstr "Ocupado"
-
msgid "SetStatusModal|Clear status"
msgstr "Limpar status"
msgid "SetStatusModal|Clear status after"
msgstr "Limpar status após"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "Exibe que você está ocupado ou não pode responder"
+
msgid "SetStatusModal|Edit status"
msgstr "Editar status"
@@ -36388,6 +37017,9 @@ msgstr "Definir um status"
msgid "SetStatusModal|Set status"
msgstr "Definir status"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "Defina-se como ocupado"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Desculpe, nós não fomos capazes de definir o seu status. Por favor, tente novamente mais tarde."
@@ -36989,6 +37621,39 @@ msgstr "Preencha a palavra que funciona melhor para sua equipe."
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr "Conecte sua conta do GitLab"
+
+msgid "Slack|Create a new issue"
+msgstr "Criar uma nova issue"
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37287,7 +37955,7 @@ msgid "Sort by"
msgstr "Ordenar por"
msgid "Sort direction"
-msgstr ""
+msgstr "Sentido da ordenação"
msgid "Sort direction: Ascending"
msgstr "Sentido da ordenação: Acrescente"
@@ -37295,6 +37963,9 @@ msgstr "Sentido da ordenação: Acrescente"
msgid "Sort direction: Descending"
msgstr "Sentido da ordenação: Decrescente"
+msgid "Sort or filter"
+msgstr "Ordenar ou filtrar"
+
msgid "SortOptions|Blocking"
msgstr "Bloqueado"
@@ -37337,6 +38008,9 @@ msgstr "Último contato"
msgid "SortOptions|Last created"
msgstr "Últimos criados"
+msgid "SortOptions|Latest version"
+msgstr "Última versão"
+
msgid "SortOptions|Least popular"
msgstr "Menos populares"
@@ -37397,6 +38071,9 @@ msgstr "Favoritado mais antigo"
msgid "SortOptions|Oldest updated"
msgstr "Atualização mais antiga"
+msgid "SortOptions|Oldest version"
+msgstr "Versão mais antiga"
+
msgid "SortOptions|Popularity"
msgstr "Popularidade"
@@ -37641,7 +38318,7 @@ msgid "Stars"
msgstr "Favoritos"
msgid "Start Date"
-msgstr ""
+msgstr "Data de início"
msgid "Start Time"
msgstr "Hora de início"
@@ -38268,7 +38945,7 @@ msgid "SuggestedColors|Dark coral"
msgstr "Coral escuro"
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "Verde escuro"
msgid "SuggestedColors|Dark sea green"
msgstr "Verde escuro do mar"
@@ -38297,7 +38974,7 @@ msgstr "Tela verde"
msgid "SuggestedColors|Green-cyan"
msgstr "Verde-ciano"
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr "Lavanda"
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr "Rosa vermelha"
msgid "SuggestedColors|Titanium yellow"
msgstr "Amarelo titânio"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "Obter sugestões para revisores com base na ferramenta de aprendizado de máquina do GitLab."
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "Revisores sugeridos"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "Sugestões aparecem na seção Revisor da barra lateral direita"
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr "Código de ativação"
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr "Usuários faturáveis"
msgid "SuperSonics|Buy subscription"
msgstr "Comprar assinatura"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "Sua assinatura"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -38657,7 +39364,7 @@ msgid "Tag push"
msgstr ""
msgid "Tag push events"
-msgstr ""
+msgstr "Eventos de envio de tags"
msgid "Tag this commit."
msgstr "Marcar este commit."
@@ -38744,7 +39451,7 @@ msgid "TagsPage|New tag"
msgstr "Novo tag"
msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
-msgstr ""
+msgstr "Somente um mantenedor ou proprietário do projeto pode excluir uma tag protegida"
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
msgstr ""
@@ -38819,7 +39526,7 @@ msgid "Target-Branch"
msgstr "Ramificação de destino"
msgid "Task"
-msgstr ""
+msgstr "Tarefa"
msgid "Task ID: %{elastic_task}"
msgstr "ID da tarefa: %{elastic_task}"
@@ -39076,12 +39783,12 @@ msgid "Test Cases"
msgstr "Casos de teste"
msgid "Test case"
-msgstr ""
+msgstr "Caso de teste"
msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "O valor de cobertura de teste para este pipeline foi calculado pelo valor de cobertura de %d tarefa."
+msgstr[1] "O valor de cobertura de teste para esse pipeline foi calculado pela média dos valores de cobertura resultantes de %d tarefas."
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
@@ -39593,7 +40300,7 @@ msgid "The name of the CI/CD configuration file. A path relative to the root dir
msgstr "O nome do arquivo de configuração de CI/CD. Um caminho relativo ao diretório raiz é opcional (por exemplo, %{code_open}my/path/.myfile.yml%{code_close})."
msgid "The name of the Jenkins project. Copy the name from the end of the URL to the project."
-msgstr ""
+msgstr "O nome do projeto Jenkins. Copie o nome do final da URL para o projeto."
msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
msgstr "O número de alterações a serem buscadas no GitLab ao clonar um repositório. Valores mais baixos podem acelerar a execução do pipeline. Defina como %{code_open}0%{code_close} ou em branco para buscar todas as ramificações e tags para cada tarefa"
@@ -39614,7 +40321,7 @@ msgid "The parsed YAML is too big"
msgstr "O YAML analisado é muito grande"
msgid "The password for the Jenkins server."
-msgstr ""
+msgstr "A senha para o servidor Jenkins."
msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
msgstr ""
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr "O snippet pode ser acessado sem nenhuma autenticação."
@@ -39755,7 +40465,7 @@ msgid "The user you are trying to deactivate has been active in the past %{minim
msgstr ""
msgid "The username for the Jenkins server."
-msgstr ""
+msgstr "O nome de usuário do servidor Jenkins."
msgid "The value of the provided variable exceeds the %{count} character limit"
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "Não há dados disponíveis. Por favor mude sua seleção."
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr "Esse bloco é autorreferencial"
msgid "This board's scope is reduced"
msgstr "O escopo deste painel está reduzido"
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Esse épico não existe ou você não tem permissão suficiente."
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Esta é a sua sessão atual"
@@ -40433,7 +41167,7 @@ msgid "This issue cannot be assigned to a confidential epic because it is public
msgstr "Essa issue não pode ser atribuída a um épico confidencial porque é público."
msgid "This issue cannot be made public because it belongs to a confidential epic."
-msgstr ""
+msgstr "Essa issue não pode ser tornada pública porque pertence a um épico confidencial."
msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
msgstr "Essa issue é confidencial e deve ser visível apenas para membros da equipe com pelo menos acesso de Repórter."
@@ -40642,6 +41376,9 @@ msgstr "Este projeto está arquivado e não pode ser comentado."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Este projeto está licenciado sob o %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is mirrored from %{link}."
+msgstr "Este projeto é espelhado de %{link}."
+
msgid "This project is not subscribed to any project pipelines."
msgstr "Este projeto não está inscrito em nenhum pipeline de projeto."
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr "Este projeto será excluído em %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr "Esta versão foi criada com uma data no passado. A coleta de evidências no momento da liberação não está disponível."
@@ -40727,7 +41470,7 @@ msgid "This user has previously committed to the %{name} project."
msgstr ""
msgid "This user has the %{access} role in the %{name} project."
-msgstr ""
+msgstr "Este usuário tem o cargo de %{access} no projeto %{name}."
msgid "This user is the author of this %{noteable}."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr "Isso removerá o relacionamento do fork entre esse projeto e %{fork_sour
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr "Para ativar sua avaliação, precisamos de detalhes adicionais de você.
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Para adicionar a entrada manualmente, forneça os seguintes detalhes ao aplicativo em seu telefone."
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir usuários internos, primeiro ative os novos usuários definidos como externos"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41271,7 +42023,7 @@ msgid "Todos count"
msgstr ""
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
-msgstr "Você está procurando coisas para fazer? Dê uma olhada em %{strongStart}%{openIssuesLinkStart}issues abertas%{openIssuesLinkEnd}%{strongEnd}, contribua para %{strongStart}%{mergeRequestLinkStart}uma solicitação de mesclagem%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}ou mencione alguém em um comentário para atribuir automaticamente uma nova tarefa."
+msgstr "Você está procurando coisas para fazer? Dê uma olhada em %{strongStart}%{openIssuesLinkStart}issues abertas%{openIssuesLinkEnd}%{strongEnd}, contribua para %{strongStart}%{mergeRequestLinkStart}uma solicitação de mesclagem%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd} ou mencione alguém em um comentário para atribuir automaticamente uma nova tarefa."
msgid "Todos|Filter by author"
msgstr "Filtrar por autor"
@@ -41283,16 +42035,16 @@ msgid "Todos|Filter by project"
msgstr "Filtrar por projeto"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "Dê um tapinha nas costas!"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "Bom trabalho! Parece que você não tem mais nada na sua lista de tarefas"
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
-msgstr ""
+msgstr "De agora em diante, você será conhecido como \"Destruidor de tarefas\""
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "Uma lista de tarefas vazia não é linda?"
msgid "Todos|It's how you always know what to work on next."
msgstr "É assim que você sempre sabe no que trabalhar a seguir."
@@ -41304,7 +42056,7 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr ""
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "Nada a fazer. Toca aqui!"
msgid "Todos|Undo mark all as done"
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr "Alternar descrição de commit"
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr "Alternar prêmio de emoji"
@@ -41366,9 +42115,6 @@ msgstr "Alternar atalhos"
msgid "Toggle sidebar"
msgstr "Ativar/Desativar barra lateral"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "Alternar a barra de desempenho"
@@ -41415,16 +42161,16 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr "Muitos usuários encontrados. Ações rápidas são limitadas a no máximo %{max_count} usuários"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "Explorar"
msgid "TopNav|Go back"
msgstr "Voltar"
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "Mudar para"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "Seus painéis"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr "O tópico %{source_topic} foi mesclado com sucesso no tópico %{target_topic}."
@@ -41480,6 +42226,9 @@ msgstr "Tamanho total de artefatos: %{total_size}"
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr "Peso toral da issue"
+
msgid "Total memory (GB)"
msgstr "Memória total (GB)"
@@ -41609,9 +42358,6 @@ msgstr "Dia %{daysUsed}/%{duration}"
msgid "Trials|Go back to GitLab"
msgstr "Voltar para o GitLab"
-msgid "Trials|Hey there"
-msgstr "Olá"
-
msgid "Trials|Skip Trial"
msgstr "Pular avaliação"
@@ -41627,6 +42373,11 @@ msgstr "Você pode aplicar sua avaliação a um novo grupo ou a um grupo existen
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr "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|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] "Você tem %{daysRemaining} dias restantes no GitLab %{planName}!"
+msgstr[1] "Você tem %{daysRemaining} dias restantes no GitLab %{planName}!"
+
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 "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.)"
@@ -42308,6 +43059,9 @@ msgstr "link de ajuda %{linkTitle}"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft} de armazenamento comprado está disponível"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Artefatos"
@@ -42350,12 +43104,12 @@ msgstr "Uso do período atual"
msgid "UsageQuota|Dependency proxy"
msgstr "Proxy de dependência"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr ""
-
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "Anexos de arquivo e gráficos de design menores."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr "Para obter mais informações sobre limites de armazenamento, consulte nosso %{faq_link_start}FAQ%{link_end}."
+
msgid "UsageQuota|Git repository."
msgstr "Repositório Gif."
@@ -42428,9 +43182,6 @@ msgstr "Repositório"
msgid "UsageQuota|Seats"
msgstr "Assentos"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr "Bits compartilhados de código e texto."
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr "A identidade do usuário foi removida com sucesso."
msgid "User identity was successfully updated."
msgstr "A identidade do usuário foi atualizada com sucesso."
+msgid "User is blocked"
+msgstr "Usuário está bloqueado"
+
msgid "User is not allowed to resolve thread"
msgstr "O usuário não tem permissão para resolver o tópico"
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "Usuário adicionado com sucesso"
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "Os usuários com um cargo de convidado ou aqueles que não pertencem a um projeto ou grupo não usarão uma licença de sua licença."
@@ -43147,8 +43898,35 @@ msgstr "Nenhum responsável - %{openingTag} atribua a você mesmo %{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr "Não atribuído"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr "Use o GitLab como uma alternativa leve ao Sentry."
+msgid "User|Data Analyst"
+msgstr "Analista de dados"
+
+msgid "User|Development Team Lead"
+msgstr "Líder de Equipe de desenvolvimento"
+
+msgid "User|Devops Engineer"
+msgstr "Engenheiro de Devops"
+
+msgid "User|Other"
+msgstr "Outros"
+
+msgid "User|Product Designer"
+msgstr "Designer de produto"
+
+msgid "User|Product Manager"
+msgstr "Gerente de produto"
+
+msgid "User|Security Analyst"
+msgstr "Analista de segurança"
+
+msgid "User|Software Developer"
+msgstr "Desenvolvedor de software"
+
+msgid "User|Systems Administrator"
+msgstr "Administrador de sistemas"
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "Usando %{code_start}::%{code_end} denota um conjunto de rótulos com %{link_start}escopos%{link_end}"
@@ -43172,13 +43950,13 @@ msgid "Validate your GitLab CI configuration file"
msgstr "Valide seu arquivo de configuração de GitLab CI"
msgid "Validated at"
-msgstr ""
+msgstr "Validado em"
msgid "Validated at:"
-msgstr ""
+msgstr "Validado em:"
msgid "Validated:"
-msgstr ""
+msgstr "Validado:"
msgid "Validations failed."
msgstr "Falha na verificação"
@@ -43334,10 +44112,10 @@ msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free
msgstr ""
msgid "VerificationReminder|Until then, shared runners will be unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
-msgstr ""
+msgstr "Até então, os executores compartilhados não estarão disponíveis. %{validateLinkStart}Valide sua conta%{validateLinkEnd} ou %{docsLinkStart}use seus próprios executores%{docsLinkEnd}."
msgid "VerificationReminder|Your account has been validated"
-msgstr ""
+msgstr "Sua conta foi validada"
msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD minutes on shared runners."
msgstr ""
@@ -43394,13 +44172,13 @@ msgid "View all environments."
msgstr "Ver todos os ambientes."
msgid "View all groups"
-msgstr ""
+msgstr "Ver todos os grupos"
msgid "View all issues"
msgstr "Ver todas as issues"
msgid "View all projects"
-msgstr ""
+msgstr "Ver todos os projetos"
msgid "View blame"
msgstr ""
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Ver gráfico"
@@ -43431,8 +44212,8 @@ msgstr "Ver documentação"
msgid "View eligible approvers"
msgstr "Visualizar aprovadores elegíveis"
-msgid "View epics list"
-msgstr "Ve lista de épicos"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43793,7 +44574,7 @@ msgid "Vulnerability|Actual received response is the one received when this faul
msgstr ""
msgid "Vulnerability|Add another identifier"
-msgstr ""
+msgstr "Adicionar outro identificador"
msgid "Vulnerability|Additional Info"
msgstr "Informações adicionais"
@@ -43811,10 +44592,10 @@ msgid "Vulnerability|Cluster"
msgstr ""
msgid "Vulnerability|Code Review"
-msgstr ""
+msgstr "Revisão de código"
msgid "Vulnerability|Comments"
-msgstr ""
+msgstr "Comentários"
msgid "Vulnerability|Crash address"
msgstr ""
@@ -43823,19 +44604,19 @@ msgid "Vulnerability|Crash state"
msgstr ""
msgid "Vulnerability|Crash type"
-msgstr ""
+msgstr "Tipo de falha"
msgid "Vulnerability|Description"
msgstr "Descrição"
msgid "Vulnerability|Details"
-msgstr ""
+msgstr "Detalhes"
msgid "Vulnerability|Detected"
msgstr ""
msgid "Vulnerability|Detection method"
-msgstr ""
+msgstr "Método de detecção"
msgid "Vulnerability|Download"
msgstr "Baixar"
@@ -43844,7 +44625,7 @@ msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerabil
msgstr ""
msgid "Vulnerability|Evidence"
-msgstr ""
+msgstr "Evidência"
msgid "Vulnerability|External Security Report"
msgstr ""
@@ -43855,17 +44636,20 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Arquivo"
+msgid "Vulnerability|File:"
+msgstr "Arquivo:"
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
msgid "Vulnerability|Identifier"
-msgstr ""
+msgstr "Identificador"
msgid "Vulnerability|Identifier URL"
-msgstr ""
+msgstr "URL do identificador"
msgid "Vulnerability|Identifier code"
-msgstr ""
+msgstr "Código identificador"
msgid "Vulnerability|Identifiers"
msgstr "Identificadores"
@@ -43874,16 +44658,16 @@ msgid "Vulnerability|Image"
msgstr "Imagem"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
-msgstr ""
-
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
+msgstr "Informações relacionadas a como a vulnerabilidade foi descoberta e seu impacto no sistema."
msgid "Vulnerability|Links"
msgstr "Links"
+msgid "Vulnerability|Location"
+msgstr "Localização"
+
msgid "Vulnerability|Method"
-msgstr ""
+msgstr "Método"
msgid "Vulnerability|Namespace"
msgstr "Espaço de nome"
@@ -43891,6 +44675,9 @@ msgstr "Espaço de nome"
msgid "Vulnerability|Project"
msgstr "Projeto"
+msgid "Vulnerability|Project:"
+msgstr "Projeto:"
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43898,19 +44685,19 @@ msgid "Vulnerability|Reproduction Assets"
msgstr ""
msgid "Vulnerability|Request"
-msgstr ""
+msgstr "Requisição"
msgid "Vulnerability|Request/Response"
msgstr ""
msgid "Vulnerability|Scanner Provider"
-msgstr ""
+msgstr "Provedor de verificação"
msgid "Vulnerability|Security Audit"
-msgstr ""
+msgstr "Auditoria de segurança"
msgid "Vulnerability|Select a severity"
-msgstr ""
+msgstr "Selecione uma severidade"
msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
msgstr ""
@@ -43918,8 +44705,11 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Gravidade"
+msgid "Vulnerability|Severity:"
+msgstr "Severidade:"
+
msgid "Vulnerability|Status"
-msgstr ""
+msgstr "Status"
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "Ferramenta"
+msgid "Vulnerability|Tool:"
+msgstr "Ferramenta:"
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43937,11 +44730,14 @@ msgid "Vulnerability|Training not available for this vulnerability."
msgstr ""
msgid "Vulnerability|Unmodified Response"
-msgstr ""
+msgstr "Resposta não modificada"
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr "AVISO:"
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr "Detectamos uma tentativa de entrada na sua conta %{host} usando um código de autenticação de dois fatores incorreto"
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr "Detectamos uma tentativa de entrada na sua conta %{host} usando um código de autenticação de dois fatores incorreto, do seguinte endereço IP: %{ip}, em %{time}"
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Detectamos spam potencial no %{humanized_resource_name}. Por favor, resolva o reCAPTCHA para continuar."
@@ -44060,7 +44862,7 @@ msgid "We'll use this to help surface the right features and information to you.
msgstr "Vamos usar isso para ajudar a supervisionar os recursos e informações certos para você."
msgid "We're experiencing difficulties and this tab content is currently unavailable."
-msgstr ""
+msgstr "Estamos com dificuldades e o conteúdo desta aba não está disponível no momento."
msgid "We've detected some unusual activity"
msgstr ""
@@ -44162,7 +44964,7 @@ msgid "Webhooks|A feature flag is turned on or off."
msgstr "Um Feature flag está ativado ou desativado."
msgid "Webhooks|A group member is created, updated, or removed."
-msgstr ""
+msgstr "Um membro do grupo é criado, atualizado ou removido."
msgid "Webhooks|A job's status changes."
msgstr "O status de uma tarefa muda."
@@ -44180,7 +44982,7 @@ msgid "Webhooks|A release is created or updated."
msgstr "Uma versão é criada ou atualizada."
msgid "Webhooks|A subgroup is created or removed."
-msgstr ""
+msgstr "Um subgrupo é criado ou removido."
msgid "Webhooks|A webhook in this project was automatically disabled after being retried multiple times."
msgstr "Um webhook neste projeto foi desativado automaticamente após ser repetido várias vezes."
@@ -44215,6 +45017,9 @@ msgstr "Excluir webhook"
msgid "Webhooks|Deployment events"
msgstr "Eventos de implantação"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "Ativar verificação SSL"
@@ -44230,12 +45035,18 @@ msgstr "Eventos de feature flag"
msgid "Webhooks|Go to webhooks"
msgstr "Ir para webhooks"
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "Eventos de issues"
msgid "Webhooks|Job events"
msgstr "Eventos de tarefa"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "Eventos de membro"
@@ -44260,11 +45071,17 @@ msgstr "Verificação SSL"
msgid "Webhooks|Secret token"
msgstr "Token secreto"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr "Mostrar URL completo"
+
msgid "Webhooks|Subgroup events"
msgstr "Eventos de subgrupo"
msgid "Webhooks|Tag push events"
-msgstr ""
+msgstr "Eventos de envio de tags"
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 ""
@@ -44284,6 +45101,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr "URL deve ser codificado por porcentagem se contiver um ou mais caracteres especiais."
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr "Usado para validar as cargas recebidas. Enviado com a solicitação no cabeçalho %{code_start}X-Gitlab-Token HTTP%{code_end}."
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr "Fonte"
-
msgid "Wiki page"
msgstr "Página da wiki"
@@ -44702,8 +45516,14 @@ msgstr "Adicionar responsável"
msgid "WorkItem|Add assignees"
msgstr "Adicionar responsáveis"
+msgid "WorkItem|Add due date"
+msgstr "Adicionar data de vencimento"
+
+msgid "WorkItem|Add start date"
+msgstr "Adicionar data de início"
+
msgid "WorkItem|Add task"
-msgstr ""
+msgstr "Adicionar tarefa"
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr "Criar tarefa"
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr "Datas"
+
msgid "WorkItem|Delete %{workItemType}"
msgstr "Excluir %{workItemType}"
+msgid "WorkItem|Due date"
+msgstr "Data de vencimento"
+
msgid "WorkItem|Expand tasks"
msgstr "Expandir tarefas"
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr "Data de início"
+
msgid "WorkItem|Task"
msgstr "Tarefa"
@@ -44813,7 +45642,7 @@ msgid "WorkItem|Tasks"
msgstr "Tarefas"
msgid "WorkItem|Test case"
-msgstr ""
+msgstr "Caso de teste"
msgid "WorkItem|Turn off confidentiality"
msgstr "Desativar confidencialidade"
@@ -44825,7 +45654,7 @@ msgid "WorkItem|Undo"
msgstr "Desfazer"
msgid "WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}"
-msgstr ""
+msgstr "Use tarefas para dividir seu trabalho em uma issue em partes menores. %{learnMoreLink}"
msgid "WorkItem|Work Items"
msgstr ""
@@ -44956,7 +45785,7 @@ msgid "You are going to turn off the confidentiality. This means %{strongStart}e
msgstr "Você vai desligar a confidencialidade. Isso significa que %{strongStart}todos%{strongEnd} poderão ver e deixar um comentário sobre essa %{issuableType}."
msgid "You are going to turn on confidentiality. Only %{context} members with %{strongStart}%{permissions}%{strongEnd} can view or be notified about this %{issuableType}."
-msgstr ""
+msgstr "Você vai ativar a confidencialidade. Apenas %{context} membros com %{strongStart}%{permissions}%{strongEnd} podem ver ou ser notificados sobre isso %{issuableType}."
msgid "You are not allowed to %{action} a user"
msgstr "Você não tem permissão para %{action} um usuário"
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,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 add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr "Você configurou o 2FA para sua conta! Se você perder o acesso ao seu d
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr "Você deve estar conectado para pesquisar em todo o GitLab"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45449,7 +46287,7 @@ msgid "You need to upload a GitLab project export archive (ending in .gz)."
msgstr "Você precisa enviar um arquivo de exportação de projeto no GitLab (terminando em .gz)."
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
-msgstr ""
+msgstr "Você precisa verificar seu e-mail principal antes de ativar a autenticação de dois fatores."
msgid "You see projects here when you're added to a group or project."
msgstr "Você vê projetos aqui quando é adicionado a um grupo ou projeto."
@@ -45626,7 +46464,7 @@ msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
-msgstr "Seus Grupos"
+msgstr "Seus grupos"
msgid "Your Personal Access Token was revoked"
msgstr "Seu token de acesso pessoal foi revogado"
@@ -45840,7 +46678,7 @@ msgid "Your profile"
msgstr ""
msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
-msgstr ""
+msgstr "Seu projeto não está mais recebendo os benefícios do GitLab Ultimate a partir de 01/07/2022. Conforme notificado anteriormente no aplicativo, os projetos públicos de código aberto no nível Gratuito podem se inscrever no GitLab for Open Source Program para receber os benefícios do GitLab Ultimate. Consulte o %{faq_link_start}FAQ%{link_end} para obter mais detalhes."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""
@@ -45993,6 +46831,9 @@ msgstr "adicionado"
msgid "added %{emails}"
msgstr "adicionou %{emails}"
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr "adicionou uma chamada do Zoom nesta issue"
@@ -46087,6 +46928,9 @@ msgstr "por"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "não pode ser alterado"
@@ -46390,6 +47237,9 @@ msgid "ciReport|Found %{issuesWithCount}"
msgstr "Encontrado %{issuesWithCount}"
msgid "ciReport|Full Report"
+msgstr "Relatório completo"
+
+msgid "ciReport|Generic Report"
msgstr ""
msgid "ciReport|IaC Scanning"
@@ -46402,7 +47252,7 @@ msgid "ciReport|License Compliance"
msgstr "Conformidade de licença"
msgid "ciReport|License Compliance failed loading results"
-msgstr "A licença de conformidadee falhou ao carregar os resultados"
+msgstr "A conformidade de licença falhou ao carregar os resultados"
msgid "ciReport|License Compliance test metrics results are being parsed"
msgstr "Os resultados das métricas de teste de conformidade de licença estão sendo analisados"
@@ -46428,7 +47278,7 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "Carregando relatório %{reportName}"
msgid "ciReport|Loading Code Quality report"
-msgstr ""
+msgstr "Carregando relatório de qualidade de código"
msgid "ciReport|Manage Licenses"
msgstr "Gerenciar licenças"
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr "comentário"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "comentou em %{link_to_project}"
@@ -46594,6 +47447,9 @@ msgstr "criado em %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "criado %{timeAgo} por %{author}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr "criado em %{timeAgo} por %{author} no %{project_link}"
+
msgid "created by"
msgstr "criado por"
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "linha"
+msgstr[1] "linhas"
+
msgid "load it anyway"
msgstr "carregá-lo mesmo assim"
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr " marco deve pertencer a um projeto ou a um grupo."
+
msgid "missing"
msgstr ""
@@ -47073,7 +47934,7 @@ msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Essa solicitação de mesclagem não contém alterações"
msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
-msgstr ""
+msgstr "Use solicitações de mesclagem para propor alterações ao seu projeto e discuti-las com sua equipe. Para fazer alterações, envie um commit ou edite esta solicitação de mesclagem para usar uma ramificação diferente. Com %{linkStart}CI/CD%{linkEnd}, teste automaticamente suas alterações antes de mesclar."
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
msgstr ""
@@ -47245,7 +48106,7 @@ msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual
msgstr ""
msgid "mrWidget|Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
-msgstr ""
+msgstr "Mesclagem bloqueada: o pipeline deve ser bem-sucedido. Envie um commit que corrige a falha ou %{linkStart}aprenda sobre outras soluções.%{linkEnd}"
msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr "deve ter um repositório"
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "meu-grupo-incrível"
@@ -47493,9 +48357,6 @@ msgstr "ou"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "de um total de %d teste"
@@ -47631,7 +48492,7 @@ msgid "remove due date"
msgstr "remover a data de vencimento"
msgid "remove start date"
-msgstr ""
+msgstr "remover data de início"
msgid "remove weight"
msgstr "remover peso"
@@ -47639,6 +48500,9 @@ msgstr "remover peso"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "removeu uma chamada do Zoom desta issue"
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "assento"
+msgstr[1] "assentos"
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "nome da tag"
@@ -47845,6 +48717,11 @@ msgstr "atualizado em %{time_ago}"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] "usuário"
+msgstr[1] "usuários"
+
msgid "user avatar"
msgstr "avatar do usuário"
@@ -47917,7 +48794,7 @@ msgid "vulnerability|Undo dismiss"
msgstr "Desfazer dispensa"
msgid "vulnerability|dismissed"
-msgstr ""
+msgstr "dispensada"
msgid "was scheduled to merge after pipeline succeeds by"
msgstr ""
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index fd2d8ebe308..be0f5131021 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:22\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} está disponível"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Página de perfil de %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} tempo passado."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "Um novo token de representação foi criado."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr "Adicionar utilizador(es) ao grupo:"
-
-msgid "Add users to group"
-msgstr "Adicionar utilizadores ao grupo"
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Bloqueado"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Todos os projetos"
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Ocorreu um erro ao carregar os dados do gráfico"
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr "Estatísticas"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "Anexar %d ficheiros"
msgid "Attaching the file failed."
msgstr "Falha ao anexar o ficheiro."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Eventos de Auditoria"
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr "Abaixo vais encontrar todos os grupos que são públicos."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr "Ramo não carregado - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr "Padrão para o pipeline de Auto DevOps para todos os projetos"
msgid "CICD|Deployment strategy"
msgstr "Estratégia de implantação"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Trabalhos"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr "Altera o título para \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr "Último Contacto"
msgid "SortOptions|Last created"
msgstr "Último criado"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 723e138f9eb..8a5440b288c 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:58\n"
msgid " %{start} to %{end}"
msgstr " de la %{start} până la %{end}"
@@ -151,6 +151,12 @@ msgstr[0] "%d comitent suplimentar"
msgstr[1] "%d comitenți suplimentari"
msgstr[2] "%d de comitenți suplimentari"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d utilizator suplimentar"
+msgstr[1] "%d utilizatori suplimentari"
+msgstr[2] "%d de utilizatori suplimentari"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d aprobator"
@@ -1117,12 +1123,6 @@ msgstr "%{spanStart}în%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} la %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] "%{strongOpen}%{errors}%{strongClose} punct"
-msgstr[1] "%{strongOpen}%{errors}%{strongClose} puncte"
-msgstr[2] "%{strongOpen}%{errors}%{strongClose} de puncte"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}Avertisment:%{strongClose} Linkurile de grup SAML pot face ca GitLab să înlăture automat membrii din grupuri."
@@ -1165,6 +1165,12 @@ msgstr[0] "%{strong_start}%{count} membru%{strong_end} trebuie să aprobe îmbin
msgstr[1] "%{strong_start}%{count} membri%{strong_end} trebuie să aprobe îmbinarea. Oricine cu rol de Dezvoltator sau mai mare poate aproba."
msgstr[2] "%{strong_start}%{count} de membri%{strong_end} trebuie să aprobe îmbinarea. Oricine cu rol de Dezvoltator sau mai mare poate aproba."
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} punct"
+msgstr[1] "%{strong_start}%{errors}%{strong_end} puncte"
+msgstr[2] "%{strong_start}%{errors}%{strong_end} de puncte"
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} Stocare pentru proiect"
@@ -1198,9 +1204,6 @@ msgstr "%{template_project_id} este necunoscut sau invalid"
msgid "%{text} is available"
msgstr "%{text} este disponibil(ă)"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} trebuie să aparțină fie unui proiect, fie unui grup."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} nu acceptă grafice burnup"
@@ -1234,6 +1237,9 @@ msgstr "%{total} greutate de problemă rămasă"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} (de) avertismente găsite: se afișează primul %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} acceptă numai numele %{name}"
@@ -1255,12 +1261,15 @@ msgstr "%{user_name} (%{user_username}) a fost eliminat din următoarele politic
msgid "%{user_name} profile page"
msgstr "Pagina de profil %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} a schimbat statutul de draft al merge request-ului %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} a solicitat un cont GitLab pe instanța dvs. %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr "%{username} a marcat merge request-ul %{mr_link} ca fiind un draft"
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr "%{username} a marcat merge request-ul %{mr_link} ca fiind gata"
+
msgid "%{username}'s avatar"
msgstr "Avatarul lui %{username}"
@@ -1282,6 +1291,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} de timp petrecut."
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} acest %{noun} ca fiind un draft."
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} acest %{noun} ca fiind gata."
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} vă permit să trimiteți notificări către aplicațiile web ca răspuns la evenimente dintr-un grup sau proiect."
@@ -1795,9 +1810,6 @@ msgstr "A fost publicată o nouă Lansare %{tag} pentru %{name}. Vizitați pagin
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr "O nouă adresă de e-mail a fost adăugată la contul dvs. GitLab: %{email}"
-msgid "A new impersonation token has been created."
-msgstr "A fost creat un nou token de impersonare."
-
msgid "A new personal access token has been created"
msgstr "S-a creat un nou token de acces personal"
@@ -1816,6 +1828,15 @@ msgstr "Un element de lucru neconfidențial nu poate avea un părinte confidenț
msgid "A page with that title already exists"
msgstr "O pagină cu acest titlu există deja"
+msgid "A personal access token has been revoked"
+msgstr "Un token de acces personal a fost revocat"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr "Un token de acces personal, numit %{code_start}%{token_name}%{code_end}, a fost revocat."
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr "Un token de acces personal, numit %{token_name}, a fost revocat."
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Un site HTML simplu care folosește Netlify pentru CI/CD în loc de GitLab, dar totuși cu toate celelalte caracteristici grozave ale GitLab."
@@ -2327,7 +2348,7 @@ msgid "Add a table"
msgstr "Adăugați un tabel"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "Adăugați un eveniment cronologic la incident"
msgid "Add a title..."
msgstr "Adăugați un titlu..."
@@ -2423,10 +2444,10 @@ msgid "Add label(s)"
msgstr "Adăugare etichetă(e)"
msgid "Add labels"
-msgstr ""
+msgstr "Adăugați etichete"
msgid "Add license"
-msgstr ""
+msgstr "Adăugați licență"
msgid "Add list"
msgstr "Adăugare listă"
@@ -2497,12 +2518,6 @@ msgstr "Adăugați subiecte la proiecte pentru a-i ajuta utilizatorii să le gă
msgid "Add trigger"
msgstr "Adăugare declanșator"
-msgid "Add user(s) to the group:"
-msgstr "Adăugați utilizator(i) la grup:"
-
-msgid "Add users to group"
-msgstr "Adăugare utilizatorii la grup"
-
msgid "Add variable"
msgstr "Adăugare variabilă"
@@ -2600,7 +2615,7 @@ msgid "Adds a Zoom meeting."
msgstr "Adaugă o reuniune Zoom."
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "Adaugă un eveniment de cronologie la incident."
msgid "Adds a to do."
msgstr "Adăugă o sarcină de făcut."
@@ -2864,7 +2879,7 @@ msgid "AdminSettings|Enable Service Ping"
msgstr "Activați serviciul Ping"
msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
-msgstr ""
+msgstr "Activați colectarea metricilor aplicației. Necesită repornirea. %{link_start}Aflați cum să exportați metrici în Prometheus%{link_end}."
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
msgstr "Activați analizatorul personalizat kuromoji: Indexare"
@@ -2896,9 +2911,15 @@ msgstr "Token de fluxuri"
msgid "AdminSettings|Git abuse rate limit"
msgstr "Limita ratei de abuz Git"
+msgid "AdminSettings|Group runners expiration"
+msgstr "Expirarea executorilor de grup"
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "Am citit și sunt de acord cu %{link_start}Termenii și condițiile de utilizare%{link_end} Let's Encrypt (PDF)."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Dacă nu se indică unitatea, aceasta este în mod implicit în secunde. De exemplu, toate acestea sunt echivalente: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable} sau %{oneDayHumanReadable}. Valoarea minimă este de două ore. %{linkStart}Aflați mai multe.%{linkEnd}"
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr "Dacă nu este specificat la nivel de grup sau de instanță, valoarea implicită este %{default_initial_branch_name}. Nu afectează repozitoriile existente."
@@ -2911,6 +2932,9 @@ msgstr "Surse de import"
msgid "AdminSettings|Inactive project deletion"
msgstr "Ștergerea proiectelor inactive"
+msgid "AdminSettings|Instance runners expiration"
+msgstr "Expirarea executanților de instanță"
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "Păstrați cele mai recente artefacte pentru toate joburile din cele mai recente pipeline-uri de succes"
@@ -2932,6 +2956,9 @@ msgstr "Numărul maxim de dependențe DAG pe care le poate avea un job"
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr "Numărul maxim de pipeline-uri active pe proiect"
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "Numărul maxim de domenii personalizate pe proiect"
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr "Numărul maxim de joburi într-un singur pipeline"
@@ -2968,6 +2995,9 @@ msgstr "Previzualizare payload"
msgid "AdminSettings|Project export"
msgstr "Export de proiecte"
+msgid "AdminSettings|Project runners expiration"
+msgstr "Expirare executanți de proiecte"
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "Protejați în mod implicit variabilele CI/CD"
@@ -3019,9 +3049,21 @@ msgstr "Setați un șablon CI/CD ca fiind configurația necesară de pipeline pe
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "Setați limita la 0 pentru a o dezactiva."
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "Setați timpul de expirare a tokenurilor de autentificare ale executorilor de grup nou înregistrați."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "Setați perioada de expirare a tokenurilor de autentificare ale instanțelor nou înregistrate. Tokenurile de autentificare sunt resetate automat la aceste intervale."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "Setați perioada de expirare a tokenurilor de autentificare ale executorilor de proiecte nou înregistrați."
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr "Setați numele și protecțiile inițiale pentru ramura implicită a noilor repozitorii create în instanță."
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "Setați numărul maxim de domenii personalizate GitLab Pages pe proiect (0 pentru nelimitat). %{link_start}Aflați mai multe.%{link_end}"
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr "Setați dimensiunea maximă a GitLab Pages per proiect (0 pentru nelimitat). %{link_start}Aflați mai multe.%{link_end}"
@@ -3208,6 +3250,9 @@ msgstr "Blocat"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Blocarea utilizatorului are următoarele efecte:"
+msgid "AdminUsers|Bot"
+msgstr "Bot"
+
msgid "AdminUsers|Can create group"
msgstr "Poate crea un grup"
@@ -3547,9 +3592,21 @@ msgstr "Opțiuni avansate de export"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr "Versiunea Elasticsearch nu este compatibilă"
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "Reindexare necesară"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "După o actualizare reușită a parolei, veți fi redirecționat către ecranul de conectare."
@@ -3976,6 +4033,9 @@ msgstr "Toate dependențele merge request-ului au fost îmbinate"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr "Toate căile sunt relative la URL-ul GitLab. Nu includeți %{relative_url_link_start} URL-uri relative%{relative_url_link_end}."
+msgid "All project members"
+msgstr "Toți membrii proiectului"
+
msgid "All projects"
msgstr "Toate proiectele"
@@ -4051,6 +4111,9 @@ msgstr "Permiteți acestei chei să facă push către acest repozitoriu"
msgid "Allow use of licensed EE features"
msgstr "Permiteți utilizarea funcțiilor EE licențiate"
+msgid "Allow users to create top-level groups"
+msgstr "Permiteți utilizatorilor să creeze grupuri de nivel superior"
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Permiteți utilizatorilor să respingă mesajul difuzat"
@@ -4339,9 +4402,6 @@ msgstr "A apărut o eroare în timpul încărcării unei secțiuni a acestei pag
msgid "An error occurred while loading all the files."
msgstr "A apărut o eroare în timpul încărcării tuturor fișierelor."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr "S-a produs o eroare la încărcarea regulilor ramurii. Vă rugăm să încercați din nou."
-
msgid "An error occurred while loading chart data"
msgstr "A apărut o eroare la încărcarea datelor graficului"
@@ -4490,7 +4550,7 @@ msgid "An error occurred while trying to generate the report. Please try again l
msgstr "A apărut o eroare în timpul încercării de generare a raportului. Vă rugăm să încercați din nou mai târziu."
msgid "An error occurred while trying to render the content editor. Please try again."
-msgstr ""
+msgstr "A survenit o eroare în timpul încercării de a afișa editorul de conținut. Încercați din nou."
msgid "An error occurred while trying to run a new pipeline for this merge request."
msgstr "A apărut o eroare în timpul încercării de a rula un nou pipeline pentru acest merge request."
@@ -4588,6 +4648,9 @@ msgstr "A apărut o eroare necunoscută."
msgid "Analytics"
msgstr "Analize"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analizați-vă dependențele pentru vulnerabilități cunoscute."
@@ -4813,6 +4876,9 @@ msgstr "Înregistrare activată"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr "Text afișat după ce un utilizator se înregistrează. Markdown activat."
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr "Această caracteristică este disponibilă numai pe GitLab.com"
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr "Această opțiune este disponibilă doar pe GitLab.com"
@@ -5464,6 +5530,9 @@ msgstr[2] "Se atașează %d de fișiere"
msgid "Attaching the file failed."
msgstr "Atașarea fișierului a eșuat."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr "S-a încercat conectarea la %{host} folosind un cod de autentificare cu doi factori greșit"
+
msgid "Audit Events"
msgstr "Evenimente de audit"
@@ -6136,6 +6205,9 @@ msgstr "Mai jos sunt setările pentru %{link_to_gitlab_pages}."
msgid "Below you will find all the groups that are public."
msgstr "Mai jos veți găsi toate grupurile care sunt publice."
+msgid "Beta"
+msgstr "Beta"
+
msgid "Bi-weekly code coverage"
msgstr "Coverage de cod bisăptămânal"
@@ -6457,8 +6529,8 @@ msgstr "Membri direcți"
msgid "Billing|Enter at least three characters to search."
msgstr "Introduceți cel puțin trei caractere pentru a căuta."
-msgid "Billing|Explore all plans"
-msgstr "Explorați toate planurile"
+msgid "Billing|Explore paid plans"
+msgstr "Explorați planurile plătite"
msgid "Billing|Export list"
msgstr "Exportați lista"
@@ -6496,6 +6568,9 @@ msgstr "Comutare detalii seat on/off"
msgid "Billing|Type %{username} to confirm"
msgstr "Introduceți %{username} pentru a confirma"
+msgid "Billing|Unlimited members during your trial"
+msgstr "Membri nelimitați în perioada de probă"
+
msgid "Billing|User was successfully removed"
msgstr "Utilizatorul a fost înlăturat cu succes"
@@ -6817,6 +6892,9 @@ msgstr "Se încarcă epicele"
msgid "Bold text"
msgstr "Text îngroșat"
+msgid "Bot"
+msgstr "Bot"
+
msgid "Both SSH and HTTP(S)"
msgstr "Atât SSH, cât și HTTP(S)"
@@ -6853,33 +6931,78 @@ msgstr "Ramura nu a fost încărcată - %{branchId}"
msgid "Branch rules"
msgstr "Reguli pentru ramură"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr "Sunt acceptate wildcard-uri %{linkStart}%{linkEnd}, cum ar fi *-stable sau production/*."
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "Permiteți tuturor utilizatorilor cu acces push să %{linkStart}forțeze push%{linkEnd}."
msgid "BranchRules|Allowed to merge"
msgstr "Permise pentru îmbinare"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "Permise pentru push"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr "A apărut o eroare în timpul preluării ramurilor."
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr "Ramura"
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr "Detaliile regulilor ramurii"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr "Creați un wildcard: %{searchTerm}"
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "Grupuri"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr "Păstrați ramurile stabile în siguranță și forțați dezvoltatorii să folosească merge request-uri. %{linkStart}Ce sunt ramurile protejate?%{linkEnd}"
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr "Nu există rezultate care să corespundă"
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr "Protecții"
@@ -6889,11 +7012,23 @@ msgstr "Refuzați împingerile de cod care modifică fișierele enumerate în fi
msgid "BranchRules|Require approval from code owners."
msgstr "Necesită aprobarea proprietarilor de coduri."
-msgid "BranchRules|default"
+msgid "BranchRules|Roles"
+msgstr "Roluri"
+
+msgid "BranchRules|Status checks"
msgstr ""
+msgid "BranchRules|Target Branch"
+msgstr "Ramura țintă"
+
+msgid "BranchRules|Users"
+msgstr "Utilizatori"
+
+msgid "BranchRules|default"
+msgstr "implicit"
+
msgid "BranchRules|protected"
-msgstr ""
+msgstr "protejat"
msgid "Branches"
msgstr "Ramuri"
@@ -7061,7 +7196,7 @@ msgid "Browse templates"
msgstr "Răsfoiți șabloanele"
msgid "Build cannot be erased"
-msgstr ""
+msgstr "Build-ul nu poate fi șters"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "A apărut o eroare la preluarea artefactelor"
@@ -7189,6 +7324,9 @@ msgstr "se aștepta la un Grup asociat, dar are un Proiect asociat"
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr "se aștepta la un Proiect asociat, dar are un Grup asociat"
+msgid "BulkImport|invalid entity source type"
+msgstr "tip de entitate sursă invalidă"
+
msgid "BulkImport|must be a group"
msgstr "trebuie să fie un grup"
@@ -7363,6 +7501,9 @@ msgstr "Setare implicită pentru pipeline-ul Auto DevOps pentru toate proiectele
msgid "CICD|Deployment strategy"
msgstr "Strategia de implementare"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr "Activați caracteristica pentru a limita accesul la tokenul jobului pentru următoarele proiecte."
+
msgid "CICD|Jobs"
msgstr "Joburi"
@@ -7372,8 +7513,8 @@ msgstr "Limita"
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr "Limitați accesul 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 "Selectați proiectele care pot fi accesate prin solicitări API autentificate cu variabila CI/CD CI_JOB_TOKEN a acestui proiect."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Selectați proiectele care pot fi accesate prin solicitări API autentificate cu variabila CI_JOB_TOKEN CI/CD a acestui proiect. Dezactivarea acestei funcții reprezintă un risc de securitate, deoarece proiectele neautorizate ar putea încerca să recupereze un token activ și să aibă acces la API. %{linkStart}Aflați mai multe.%{linkEnd}"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr "Pipeline-ul Auto DevOps rulează în mod implicit în toate proiectele fără niciun fișier de configurare CI/CD. %{link_start}Ce este Auto DevOps?%{link_end}"
@@ -7633,8 +7774,8 @@ msgstr "Nu se poate promova problema pentru că nu aparține unui grup."
msgid "Cannot promote issue due to insufficient permissions."
msgstr "Nu se poate promova problema din cauza permisiunilor insuficiente."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr "Nu se poate face referire la un grup %{timebox_type} printr-un id intern!"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "Nu se poate face referință la un obiectiv de grup printr-un ID intern!"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "Nu se poate afișa previzualizarea. Pentru previzualizarea fișierelor schiță, ele trebuie să aibă formatul de fișier introdus de Sketch versiunea 43 și mai sus."
@@ -7828,6 +7969,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 "Changes:"
+msgstr "Modificări:"
+
msgid "Changing any setting here requires an application restart"
msgstr "Modificarea oricărei setări de aici necesită o repornire a aplicației"
@@ -8845,6 +8989,9 @@ msgstr "Sunteți sigur că doriți să ștergeți acest agent? Acest lucru nu po
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr "Sunteți sigur că doriți să revocați acest token? Nu puteți anula această acțiune."
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr "Flux de lucru CI/CD cu acces restricționat"
+
msgid "ClusterAgents|Certificate"
msgstr "Certificat"
@@ -8944,6 +9091,9 @@ msgstr "Cum să actualizez un agent?"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr "Instalați folosind Helm (recomandat)"
+msgid "ClusterAgents|Integration Status"
+msgstr "Starea integrării"
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Ultima conectare %{timeAgo}."
@@ -8971,6 +9121,9 @@ msgstr[0] "Nu a avut loc nicio activitate în ultima zi"
msgstr[1] "Nu a avut loc nicio activitate în ultimele %d zile"
msgstr[2] "Nu a avut loc nicio activitate în ultimele %d de zile"
+msgid "ClusterAgents|No agent access token"
+msgstr "Niciun token de acces al agentului"
+
msgid "ClusterAgents|No agents"
msgstr "Fără agenți"
@@ -8980,6 +9133,9 @@ msgstr "Nu există clustere conectate prin certificate de cluster"
msgid "ClusterAgents|Not connected"
msgstr "Neconectat"
+msgid "ClusterAgents|Premium"
+msgstr "Premium"
+
msgid "ClusterAgents|Recommended"
msgstr "Recomandat"
@@ -9046,6 +9202,9 @@ msgstr "Token revocat de %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Utilizator necunoscut"
+msgid "ClusterAgents|Valid access token"
+msgstr "Token de acces valid"
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "Vedeți toți cei %{number} (de) agenți"
@@ -9383,10 +9542,10 @@ msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "URL-ul utilizat pentru a accesa API-ul Kubernetes."
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "Integrarea Kubernetes bazată pe certificate a fost depreciată și va fi dezactivată la sfârșitul lunii februarie 2023. %{linkStart}Migrați la agentul GitLab pentru Kubernetes%{linkEnd} sau contactați asistența GitLab."
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "Integrarea Kubernetes bazată pe certificate a fost depreciată și va fi dezactivată la sfârșitul lunii februarie 2023. %{linkStart}Migrați la agentul GitLab pentru Kubernetes%{linkEnd}."
msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
msgstr "Metoda bazată pe certificate pentru conectarea clusterelor la GitLab a fost %{linkStart}depreciată%{linkEnd} în GitLab 14.5."
@@ -9715,6 +9874,9 @@ msgstr "Comiteți la"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "Commit-urile pe care le selectați apar aici. Mergeți la prima filă și selectați commit-urile pe care să le adăugați la acest merge request"
+msgid "Commits:"
+msgstr "Commit-uri:"
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "A apărut o eroare în timpul preluării datelor merge request-urilor."
@@ -9752,7 +9914,7 @@ msgid "Compare Revisions"
msgstr "Comparați revizuirile"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "Comparați ramurile și continuați"
msgid "Compare changes"
msgstr "Comparați modificările"
@@ -9820,6 +9982,9 @@ msgstr "Complet"
msgid "Complete verification to sign in."
msgstr "Completați verificarea pentru a vă autentifica."
+msgid "Complete verification to sign up."
+msgstr "Completați verificarea pentru a vă înscrie."
+
msgid "Completed"
msgstr "Completat"
@@ -9889,8 +10054,8 @@ msgstr "Numele este obligatoriu"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr "Încă nu sunt configurate framework-uri de conformitate"
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr "Format necesar: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Aflați mai multe.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
+msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "Nu se poate salva acest framework de conformitate. Vă rugăm să încercați din nou"
@@ -10207,6 +10372,9 @@ msgstr "Contacte"
msgid "Container Registry"
msgstr "Registrul de containere"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Scanarea containerelor"
@@ -10334,7 +10502,7 @@ msgid "ContainerRegistry|Docker connection error"
msgstr "Eroare de conexiune Docker"
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "Editați regulile de curățare"
msgid "ContainerRegistry|Enable expiration policy"
msgstr "Activați politica de expirare"
@@ -10442,10 +10610,10 @@ msgid "ContainerRegistry|Save storage space by automatically deleting tags from
msgstr "Economisiți spațiu de stocare prin ștergerea automată a etichetelor din registrul container și păstrarea celor pe care le doriți. %{linkStart}Cum funcționează curățarea?%{linkEnd}"
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "Setați reguli de curățare"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "Setați reguli pentru a elimina automat pachetele neutilizate pentru a economisi spațiu de stocare."
msgid "ContainerRegistry|Set up cleanup"
msgstr "Configurați curățarea"
@@ -10666,15 +10834,15 @@ msgstr "Colaboratori"
msgid "Control emails linked to your account"
msgstr "Controlați e-mailurile legate de contul d-voastră"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr "Controlați cum este utilizată variabila CI_JOB_TOKEN CI/CD pentru accesul API între proiecte."
+
msgid "Control how the GitLab Package Registry functions."
msgstr "Controlați modul în care funcționează Registrul de pachete GitLab."
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr "Controlați dacă doriți să afișați conținutul de îmbunătățire a experienței clienților și ofertele terților în GitLab."
-msgid "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."
-msgstr "Controlați ce proiecte pot fi accesate prin cereri API autentificate cu variabila CI/CD CI_JOB_TOKEN a acestui proiect. Dezactivarea acestei funcții reprezintă un risc de securitate, deoarece proiectele neautorizate ar putea încerca să recupereze un token activ și să acceseze API-ul."
-
msgid "Cookie domain"
msgstr "Domeniul cookie"
@@ -10996,6 +11164,9 @@ msgstr "Nu s-a putut atribui politica unui proiect sau grup"
msgid "Country"
msgstr "Å¢ara"
+msgid "Counts reflect children you may not have access to."
+msgstr "Numerele reflectă copiii la care este posibil să nu aveți acces."
+
msgid "Coverage"
msgstr "Coverage"
@@ -11212,6 +11383,9 @@ msgstr "Creați un subiect"
msgid "Create user"
msgstr "Creați utilizatorul"
+msgid "Create wildcard"
+msgstr "Creați un wildcard"
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Creați un wildcard: %{searchTerm}"
@@ -11224,6 +11398,12 @@ msgstr "Creați-vă grupul"
msgid "Create, update, or delete a merge request."
msgstr "Creați, actualizați sau ștergeți un merge request."
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "Adăugați un mesaj la etichetă. Lăsând acest spațiu necompletat, se creează o %{linkStart}etichetă ușoară%{linkEnd}."
+
+msgid "CreateGitTag|Set tag message"
+msgstr "Setați mesajul etichetei"
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "Nu aveți permisiunea de a crea un subgrup în acest grup."
@@ -12002,10 +12182,10 @@ msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and resp
msgstr "O scanare pasivă monitorizează toate mesajele HTTP (solicitări și răspunsuri) trimise către țintă. O scanare activă atacă ținta pentru a găsi vulnerabilități potențiale."
msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Un profil de scaner definește detaliile de configurare ale unui scaner de securitate. %{linkStart}Aflați mai multe%{linkEnd}."
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Un profil de site definește atributele și detaliile de configurare ale aplicației, website-ului sau API-ului implementat. %{linkStart}Aflați mai multe%{linkEnd}."
msgid "DastProfiles|AJAX spider"
msgstr "Spiderul AJAX"
@@ -12209,10 +12389,10 @@ msgid "DastProfiles|Scanner name"
msgstr "Numele scanerului"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "Profil de scaner"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "Profiluri de scaner"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr "Selectați un profil de scaner pentru a rula o scanare DAST"
@@ -12236,10 +12416,10 @@ msgid "DastProfiles|Site name"
msgstr "Numele site-ului"
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "Profil de site"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "Profiluri de site"
msgid "DastProfiles|Site type"
msgstr "Tipul site-ului"
@@ -12481,6 +12661,12 @@ msgstr "Intervalul de date limitat la %{number} (de) zile"
msgid "Date range must be shorter than %{max_range} days."
msgstr "Intervalul de date trebuie să fie mai mic de %{max_range} (de) zile."
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr "Data de punere în aplicare pe noile spații de nume create"
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr "%{start_date}–%{end_date}"
+
msgid "Day of month"
msgstr "Ziua lunii"
@@ -12667,6 +12853,9 @@ msgstr "Ștergeți contul"
msgid "Delete artifacts"
msgstr "Ștergeți artefactele"
+msgid "Delete asset"
+msgstr "Ștergeți activul"
+
msgid "Delete audio"
msgstr "Ștergeți audio"
@@ -12811,6 +13000,9 @@ msgstr "S-a șters"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "S-a șters porecla de chat: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr "Commit-uri șterse:"
+
msgid "Deleted projects cannot be restored!"
msgstr "Proiectele șterse nu pot fi restaurate!"
@@ -13156,6 +13348,9 @@ msgstr "Acces numai în citire"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Tokenuri de implementare active (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "Permite accesul în citire și scriere la imaginile de registru."
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "Permite acces în citire și scriere la registrul de pachete."
@@ -13201,6 +13396,9 @@ msgstr "Introduceți un nume de utilizator pentru tokenul dumneavoastră. Valoar
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr "Introduceți o dată de expirare pentru tokenul dumneavoastră. În mod implicit, nu expiră niciodată."
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "Data expirării (opțional)"
+
msgid "DeployTokens|Expires"
msgstr "Expiră"
@@ -13222,6 +13420,9 @@ msgstr "Revocați %{name}"
msgid "DeployTokens|Scopes"
msgstr "Scopuri"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr "Domenii (selectați cel puțin unul)"
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "Acest tip de %{entity_type} nu are Token de implementare active."
@@ -13237,6 +13438,12 @@ msgstr "Utilizați acest token ca parolă. Salvați-l. Această parolă %{i_star
msgid "DeployTokens|Username"
msgstr "Nume de utilizator"
+msgid "DeployTokens|Username (optional)"
+msgstr "Nume de utilizator (opțional)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "Noul dvs. token de implementare"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr "Noul dvs. nume de utilizator al Tokenului de implementare"
@@ -13423,18 +13630,9 @@ msgstr "succes"
msgid "Deprecated API rate limits"
msgstr "Limite de rată API depreciate"
-msgid "Deprecations|Feature deprecation and removal"
-msgstr "Deprecierea și înlăturarea funcțiilor"
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr "Pentru informații cu privire la un posibil înlocuitor, %{epicStart}aflați mai multe despre Opstrace %{epicEnd}."
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr "Pentru informații despre un posibil înlocuitor, %{opstrace_link_start} aflați mai multe despre Opstrace %{link_end}."
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr "Funcțiile de jurnale și de urmărire au fost, de asemenea, depreciate în GitLab 14.7, și sunt %{removal_link_start} programate pentru înlăturare %{link_end} în GitLab 15.0."
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr "Funcția de metrici a fost abandonată în GitLab 14.7."
@@ -13504,20 +13702,11 @@ msgstr "Activele designului arhivate vor fi în continuare disponibile în versi
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr "Sunteți sigur că doriți să arhivați elementele de design selectate?"
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "Sunteți sigur că doriți să anulați modificările la acest comentariu?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Sunteți sigur că doriți să anulați crearea acestui comentariu?"
-msgid "DesignManagement|Cancel changes"
-msgstr "Anulați modificările"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Anulați confirmarea comentariului"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "Anulați confirmarea actualizării comentariilor"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr "Faceți clic pe imagine acolo unde doriți să începeți o nouă discuție"
@@ -13525,6 +13714,12 @@ msgstr "FaceÈ›i clic pe imagine acolo unde doriÈ›i să începeÈ›i o nouă discuÈ
msgid "DesignManagement|Comment"
msgstr "Comentariu"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Nu s-a putut adăuga un comentariu nou. Vă rugăm să încercați din nou."
@@ -13543,11 +13738,11 @@ msgstr "Deselectați totul"
msgid "DesignManagement|Designs"
msgstr "Design"
-msgid "DesignManagement|Discard comment"
-msgstr "Înlăturați comentariul"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "Discuție"
msgid "DesignManagement|Download design"
msgstr "Descărcați elementul de design"
@@ -13564,12 +13759,6 @@ msgstr "Mergeți la următorul element de design"
msgid "DesignManagement|Go to previous design"
msgstr "Mergeți la elementul de design anterior"
-msgid "DesignManagement|Keep changes"
-msgstr "Păstrați modificările"
-
-msgid "DesignManagement|Keep comment"
-msgstr "Păstrați comentariul"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "Versiunea de design solicitată nu există. În schimb, se afișează cea mai recentă versiune"
@@ -13643,7 +13832,7 @@ msgid "DevOps adoption"
msgstr "Adoptarea DevOps"
msgid "Development"
-msgstr ""
+msgstr "Dezvoltare"
msgid "Devices (optional)"
msgstr "Dispozitive (opțional)"
@@ -14116,6 +14305,18 @@ msgstr "Domeniu"
msgid "Domain Name"
msgstr "Numele domeniului"
+msgid "Domain Verification"
+msgstr "Verificarea domeniului"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "Cum configurez un domeniu?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "Niciun domeniu configurat. Creați un domeniu într-un proiect din această ierarhie de grup."
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "Domeniile următoare sunt configurate pentru proiectele din acest grup. Utilizatorii cu adrese de e-mail care corespund unui domeniu verificat nu trebuie să-și confirme contul."
+
msgid "Don't have a group?"
msgstr "Nu aveți un grup?"
@@ -14234,10 +14435,10 @@ msgid "DropdownWidget|Assign %{issuableAttribute}"
msgstr "Atribuiți %{issuableAttribute}"
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "Anulare"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "Editați %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr "Nu s-a putut prelua %{issuableAttribute} pentru acest/această %{issuableType}. Vă rugăm să încercați din nou."
@@ -14255,10 +14456,10 @@ msgid "DropdownWidget|No open %{issuableAttribute} found"
msgstr "Nu s-a găsit niciun/nicio %{issuableAttribute} deschis(ă)"
msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
-msgstr ""
+msgstr "Nu aveți permisiunea de a vizualiza %{issuableAttribute} care s-a atribuit în prezent, iar în caz de reatribuire, nu se va mai putea alege din nou."
msgid "DropdownWidget|You don't have permission to view this %{issuableAttribute}."
-msgstr ""
+msgstr "Nu aveți permisiunea de a vizualiza acest %{issuableAttribute}."
msgid "Due Date"
msgstr "Data scadentă"
@@ -14482,6 +14683,9 @@ msgstr "Editați pagina wiki"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Editați cel mai recent comentariu al dvs. dintr-un subiect (dintr-o zonă de text goală)"
+msgid "Edit your search and try again"
+msgstr "Editați căutarea și încercați din nou"
+
msgid "Edit your search filter and try again."
msgstr "Editați filtrul de căutare și încercați din nou"
@@ -14570,7 +14774,7 @@ msgid "Email sent"
msgstr "E-mail trimis"
msgid "Email the pipeline status to a list of recipients."
-msgstr "Trimiteți prin e-mail starea conductei către o listă de destinatari."
+msgstr "Trimiteți prin e-mail starea pipeline-ului către o listă de destinatari."
msgid "Email updates (optional)"
msgstr "Actualizări prin e-mail (opțional)"
@@ -14620,9 +14824,6 @@ msgstr "și %{moreCount} alții"
msgid "Emails"
msgstr "E-mailuri"
-msgid "Emails sent from Service Desk have this name."
-msgstr "E-mailurile trimise de la Service Desk au acest nume."
-
msgid "Emails sent to %{email} are also supported."
msgstr "Se acceptă, de asemenea, e-mailurile trimise la %{email}."
@@ -14672,7 +14873,7 @@ msgid "Enable GitLab Error Tracking"
msgstr "Activați urmărirea erorilor GitLab"
msgid "Enable GitLab Prometheus metrics endpoint"
-msgstr ""
+msgstr "Activați punctul final de metrici GitLab Prometheus"
msgid "Enable Gitpod"
msgstr "Activați Gitpod"
@@ -14740,6 +14941,9 @@ msgstr "Activați politicile de expirare și păstrare a containerelor pentru pr
msgid "Enable container expiration caching."
msgstr "Activați caching-ul de expirare a containerului."
+msgid "Enable dashboard limits on namespaces"
+msgstr "Activați limitele spațiilor de nume în tabloul de bord"
+
msgid "Enable email notification"
msgstr "Activați notificarea prin e-mail"
@@ -15088,6 +15292,9 @@ msgstr "Implementare"
msgid "Environments|Deployment %{status}"
msgstr "Implementare %{status}"
+msgid "Environments|Edit your search and try again"
+msgstr "Editați căutarea și încercați din nou"
+
msgid "Environments|Enable review app"
msgstr "Activați aplicația de revizuire"
@@ -15121,6 +15328,9 @@ msgstr "Nu există medii implementate"
msgid "Environments|No deployments yet"
msgstr "Nu există încă implementări"
+msgid "Environments|No results found"
+msgstr "Nu s-au găsit rezultate"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "ReÈ›ineÈ›i că această acÈ›iune va opri mediul, dar %{emphasisStart}nu%{emphasisEnd} va avea efect asupra niciunei implementări existente, deoarece în fiÈ™ierul %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} nu este definită nicio „acÈ›iune de oprire a mediuluiâ€."
@@ -15145,6 +15355,9 @@ msgstr "Mediu de revenire"
msgid "Environments|Rollback environment %{name}?"
msgstr "Mediul de revenire %{name}?"
+msgid "Environments|Search by environment name"
+msgstr "Căutați după numele mediului"
+
msgid "Environments|Show all"
msgstr "Afișați toate"
@@ -15344,7 +15557,7 @@ msgid "Error deleting project. Check logs for error details."
msgstr "Eroare la ștergerea proiectului. Verificați jurnalele pentru detalii despre eroare."
msgid "Error fetching branches"
-msgstr ""
+msgstr "Eroare la preluarea ramurilor"
msgid "Error fetching burnup chart data"
msgstr "Eroare la preluarea datelor graficului burnup"
@@ -16246,9 +16459,6 @@ msgstr "Nu s-a reușit încărcarea ramurilor. Vă rugăm să încercați din no
msgid "Failed to load deploy keys."
msgstr "Nu s-a reușit încărcarea cheilor de distribuție."
-msgid "Failed to load emoji list."
-msgstr "Nu s-a reușit încărcarea listei de emoji."
-
msgid "Failed to load error details from Sentry."
msgstr "Nu s-a reușit încărcarea detaliilor de eroare din Sentry."
@@ -16856,13 +17066,13 @@ msgid "Flags"
msgstr "Semnalizatori"
msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
-msgstr ""
+msgstr "Configurați dacă doriți să participați la FLoC. %{floc_link_start}Ce este FLoC?%{floc_link_end}"
msgid "FloC|Federated Learning of Cohorts (FLoC)"
-msgstr ""
+msgstr "Federated Learning of Cohorts (FLoC)"
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "Participați la FLoC"
msgid "FlowdockService|Enter your Flowdock token."
msgstr "Introduceți tokenul Flowdock."
@@ -16933,6 +17143,9 @@ msgstr "Pentru fiecare job, reutilizați spațiul de lucru al proiectului. Dacă
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr "De exemplu, aplicația care utilizează tokenul sau scopul său. Nu furnizați informații sensibile pentru numele tokenului, deoarece acesta va fi vizibil pentru toți membrii %{resource_type}."
+msgid "For faster browsing, not all history is shown."
+msgstr "Pentru o navigare mai rapidă, nu se afișează tot istoricul."
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr "Pentru fișiere mai mari decât această limită, indexați numai numele fișierului. Conținutul fișierului nu este nici indexat, nici nu poate fi căutat."
@@ -17062,15 +17275,48 @@ msgstr "S-au găsit erori în fișierul d-voastră .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr "Framework-ul a fost eliminat cu succes"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Versiune de încercare gratuită a GitLab.com Ultimate"
+msgid "Free User Cap"
+msgstr "Limită gratuită utilizator"
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] "Grupurile gratuite sunt limitate la %{free_user_limit} membru, iar membrii rămași vor primi statutul de peste limită și vor pierde accesul la grup."
msgstr[1] "Grupurile gratuite sunt limitate la %{free_user_limit} membri, iar membrii rămași vor primi statutul de peste limită și vor pierde accesul la grup."
msgstr[2] "Grupurile gratuite sunt limitate la %{free_user_limit} de membri, iar membrii rămași vor primi statutul de peste limită și vor pierde accesul la grup."
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "O altă opțiune este de a face upgrade la GitLab Premium sau GitLab Ultimate:"
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "Explorați planurile plătite"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "Explorați planurile plătite:"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr "Se pare că aÈ›i atins limita de %{free_user_limit} membri pentru „%{namespace_name}â€. Nu mai puteÈ›i adăuga alÈ›i membri, dar îi puteÈ›i gestiona pe cei existenÈ›i, de exemplu, prin înlăturarea celor inactivi È™i înlocuirea lor cu membri noi."
+
+msgid "FreeUserCap|Manage members"
+msgstr "Gestionați membrii"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "Gestionați membrii:"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "Pentru a obține mai mulți membri, %{trial_link_start}începeți o perioadă de încercare%{trial_link_end} sau %{upgrade_link_start}faceți upgrade%{upgrade_link_end} la GitLab Premium sau GitLab Ultimate."
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "Pentru a obține mai mulți membri, începeți o perioadă de încercare:"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "Ați atins limita de membri!"
+
msgid "Freeze end"
msgstr "Înghețul se termină"
@@ -17335,6 +17581,9 @@ msgstr "Modificați căutarea și încercați din nou."
msgid "Geo|Errors:"
msgstr "Erori:"
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Eșuat"
@@ -17674,6 +17923,9 @@ msgstr "A apărut o eroare la salvarea acestui site Geo"
msgid "Geo|There was an error updating the Geo Settings"
msgstr "A apărut o eroare la actualizarea setărilor Geo"
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "Aceasta va resincroniza toate %{replicableType}. S-ar putea să dureze ceva timp până la finalizare. Sunteți sigur că doriți să continuați?"
@@ -17896,9 +18148,6 @@ msgstr "Problema GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
-msgid "GitLab Logo"
-msgstr "Logoul GitLab"
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -18191,7 +18440,7 @@ msgid "Global Shortcuts"
msgstr "Comenzi rapide globale"
msgid "Global notification level"
-msgstr ""
+msgstr "Nivelul global de notificare"
msgid "Global notification settings"
msgstr "Setări de notificare globale"
@@ -18281,10 +18530,10 @@ msgid "GlobalSearch|project"
msgstr "proiect"
msgid "GlobalShortcuts|Copied source branch name to clipboard."
-msgstr ""
+msgstr "Numele ramurii sursă a fost copiat în clipboard."
msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
-msgstr ""
+msgstr "Numele ramurii sursă nu poate fi copiat în acest moment."
msgid "Globally-allowed IP ranges"
msgstr "Intervale IP permise la nivel global"
@@ -18763,6 +19012,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Se încarcă epicele"
+msgid "GroupRoadmap|New epic"
+msgstr "Noua epică"
+
msgid "GroupRoadmap|No start and end date"
msgstr "Fără dată de început și de sfârșit"
@@ -18788,7 +19040,7 @@ msgid "GroupRoadmap|This year"
msgstr "Anul acesta"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
-msgstr "Pentru a face ca epicele dvs. să apară în foaia de parcurs, adăugați-le date de început sau de scadență."
+msgstr "Pentru ca epicele să vă apară în foaia de parcurs, adăugați-le date de început sau de scadență."
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
msgstr "Pentru vizualizarea foii de parcurs, adăugați o dată de început sau o dată scadentă la una dintre %{linkStart}epicele copil%{linkEnd}."
@@ -18799,6 +19051,9 @@ msgstr "Pentru a vizualiza foaia de parcurs, adăugați o dată de început sau
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Pentru a lărgi căutarea, modificați sau eliminați filtrele; de la %{startDate} la %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr "Vedeți lista de epice"
+
msgid "GroupRoadmap|Within 3 years"
msgstr "ÃŽn decurs de 3 ani"
@@ -19015,8 +19270,8 @@ msgstr "AlegeÈ›i o cale de grup care nu începe cu o liniuță È™i nu se terminÄ
msgid "GroupSettings|Compliance frameworks"
msgstr "Framework-uri de conformitate"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr "Configurați framework-urile de conformitate pentru a le face disponibile proiectelor din acest grup. %{linkStart}Aflați mai multe.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
msgstr "Configurați limitele numărului de repozitorii care pot fi descărcate de utilizatori într-un anumit interval de timp."
@@ -19360,6 +19615,12 @@ msgstr "Calea grupului nu este disponibilă. Calea a fost înlocuită cu o cale
msgid "Groups|Learn more"
msgstr "Aflați mai multe"
+msgid "Groups|Learn more about subgroups"
+msgstr "Aflați mai multe despre subgrupuri"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr "Membrii, proiectele, evaluările și abonamentele plătite sunt legate de un anumit grup de nivel superior. Dacă sunteți deja membru al unui astfel de grup, puteți crea un subgrup, astfel încât noua dvs. activitate să facă parte din acest grup de nivel superior existent. Doriți să creați mai degrabă un subgrup?"
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "Trebuie să înceapă cu o literă, o cifră, un emoji sau un caracter de subliniere. Poate conține, de asemenea, puncte, liniuțe, spații și paranteze."
@@ -19378,6 +19639,9 @@ msgstr "Numele subgrupului"
msgid "Groups|Subgroup slug"
msgstr "Slug-ul subgrupului"
+msgid "Groups|You're creating a new top-level group"
+msgstr "Creați un nou grup de nivel superior"
+
msgid "Guideline"
msgstr "Ghid"
@@ -19399,8 +19663,8 @@ msgstr "HTTP Basic: Acces refuzat. Parola sau tokenul furnizat este incorect sau
msgid "Harbor Registry"
msgstr "Registrul Harbor"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
-msgstr "Odată ce integrarea Harbor este activată, se vor crea variabilele globale \"$HARBOR_USERNAME\", \"$HARBOR_HOST\", \"$HARBOR_OCI\", \"$HARBOR_PASSWORD\", \"$HARBOR_URL\" și \"$HARBOR_PROJECT\" pentru utilizarea CI/CD."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
+msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
msgstr "URL-ul de bază al instanței Harbor."
@@ -19447,6 +19711,9 @@ msgstr[2] "%{count} de Repozitorii de imagini"
msgid "HarborRegistry|-- artifacts"
msgstr "-- artefacte"
+msgid "HarborRegistry|-- tags"
+msgstr "-- etichete"
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr "Digest: %{imageId}"
@@ -19492,8 +19759,8 @@ msgstr "Această imagine nu are artefacte"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "Pentru a vă extinde căutarea, modificați sau eliminați filtrele de mai sus."
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr "Avem probleme cu conectarea la Registrul Harbor. Vă rugăm să încercați să reîmprospătați pagina. Dacă această eroare persistă, vă rugăm să consultați %{docLinkStart}documentația de depanare.%{docLinkEnd}"
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr "Avem probleme cu conectarea la Harbor Registry. Vă rugăm să încercați să reîmprospătați pagina. Dacă această eroare persistă, consultați %{docLinkStart}documentația%{docLinkEnd}."
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
msgstr "Cu Harbor Registry, fiecare proiect se poate conecta la un spațiu harbor pentru a-și stoca imaginile Docker."
@@ -19646,7 +19913,7 @@ msgstr[1] "Ascundeți graficele"
msgstr[2] "Ascundeți graficele"
msgid "Hide comments"
-msgstr ""
+msgstr "Ascundeți comentariile"
msgid "Hide comments on this file"
msgstr "Ascundeți comentariile la acest fișier"
@@ -19814,7 +20081,7 @@ msgid "How the job limiter handles jobs exceeding the thresholds specified below
msgstr "Modul în care limitatorul de joburi gestionează joburile care depășesc pragurile specificate mai jos. Modul „urmărire†înregistrează doar joburile. Modul „comprimare†comprimă joburile și generează o excepție în cazul în care dimensiunea comprimată depășește limita."
msgid "How to track time"
-msgstr ""
+msgstr "Cum să urmăriți timpul"
msgid "I accept the %{terms_link}"
msgstr "Accept %{terms_link}"
@@ -19927,26 +20194,47 @@ msgstr "Identificatori"
msgid "Identities"
msgstr "Identități"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "A fost trimis un nou cod."
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "Înainte de a crea primul dvs. proiect, avem nevoie să vă verificați identitatea cu o metodă de plată validă. Nu veți fi taxat în această etapă. Dacă va fi nevoie să vă taxăm vreodată, vă vom anunța."
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "Înainte de a vă crea grupul, avem nevoie să vă verificați identitatea cu o metodă de plată validă. Nu veți fi taxat în această etapă. Dacă va trebui să vă taxăm vreodată, vă vom anunța."
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "Înaintea creării contului dvs., trebuie să vă verificăm identitatea. Pe pagina de verificare, introduceți următorul cod."
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr "Înainte de a vă autentifica, trebuie să vă verificăm identitatea. Introduceți următorul cod pe pagina de conectare."
+msgid "IdentityVerification|Confirm your email address"
+msgstr "Confirmați-vă adresa de e-mail"
+
msgid "IdentityVerification|Create a project"
msgstr "Creați un proiect"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "Nu ați primit un cod?"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "Introduceți codul."
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "Introduceți un cod valid."
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
-msgstr ""
+msgstr "Pentru mai multă siguranță, va fi necesar să vă verificați identitatea în câțiva pași rapizi."
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr "Pentru mai multă siguranță, va trebui să vă verificați identitatea. V-am trimis un cod de verificare la %{email}."
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr "GitLab nu va percepe sau stoca informațiile dvs. de plată, acestea vor fi folosite numai pentru verificare."
+
msgid "IdentityVerification|Help us keep GitLab secure"
-msgstr ""
+msgstr "Ajutați-ne să păstrăm GitLab în siguranță"
msgid "IdentityVerification|Help us protect your account"
msgstr "Ajutați-ne să vă protejăm contul"
@@ -19961,22 +20249,22 @@ msgid "IdentityVerification|If you've lost access to the email associated to thi
msgstr "Dacă ați pierdut accesul la adresa de e-mail asociată acestui cont sau aveți probleme cu codul, %{link_start}există și alte măsuri pe care le puteți lua.%{link_end}"
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "Codul de apelare internațional"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
msgstr "Numărul maxim de încercări de autentificare a fost depășit. Așteptați %{interval} și încercați din nou."
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "Număr de telefon"
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "Numărul de telefon trebuie completat."
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
-msgstr ""
+msgstr "Numărul de telefon trebuie să aibă cel mult %{maxLength} cifre."
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "Numărul de telefon trebuie să conțină numai cifre."
msgid "IdentityVerification|Please enter a valid code"
msgstr "Vă rugăm să introduceți un cod valid"
@@ -19984,17 +20272,23 @@ msgstr "Vă rugăm să introduceți un cod valid"
msgid "IdentityVerification|Resend code"
msgstr "Retrimiteți codul"
+msgid "IdentityVerification|Send a new code"
+msgstr "Trimiteți-mi un nou cod"
+
msgid "IdentityVerification|Send code"
-msgstr ""
+msgstr "Trimiteți codul"
+
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr "Ceva nu a mers bine. Vă rugăm să încercați din nou."
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr "Etapa 1: Verificarea numărului de telefon"
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr "Codul a expirat. Retrimiteți un nou cod și încercați din nou."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr "Codul a expirat. Trimiteți-mi un nou cod și încercați din nou."
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr "Codul este incorect. Introduceți-l din nou sau retrimiteți un nou cod."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr "Codul este incorect. Introduceți-l din nou sau trimiteți-mi un nou cod."
msgid "IdentityVerification|Verification code"
msgstr "Cod de verificare"
@@ -20005,6 +20299,12 @@ msgstr "Verificare reușită"
msgid "IdentityVerification|Verify code"
msgstr "Verificați codul"
+msgid "IdentityVerification|Verify email address"
+msgstr "Verificați adresa de e-mail"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "Metodă de verificare prin plată"
+
msgid "IdentityVerification|Verify your identity"
msgstr "Verificați-vă identitatea"
@@ -20012,13 +20312,16 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr "Puteți oricând să vă verificați contul ulterior pentru a crea un grup."
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
-msgstr ""
+msgstr "Veți primi un SMS cu un cod. Se pot aplica taxe standard."
+
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "Ați atins numărul maxim de retrimiteri. Așteptați %{interval} și încercați din nou."
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr "Ați atins numărul maxim de încercări. Așteptați %{interval} sau retrimiteți un nou cod și încercați din nou."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr "Ați atins numărul maxim de încercări. Așteptați %{interval} sau trimiteți un nou cod și încercați din nou."
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "Contul dvs. a fost verificat cu succes. Veți fi redirecționat către contul dvs. în câteva momente sau %{redirect_url_start}faceți clic%{redirect_url_end} aici pentru a reîmprospăta."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "Contul dvs. a fost verificat cu succes. Veți fi redirecționat către acest cont în câteva momente. Puteți, de asemenea, %{redirect_url_start}să reîmprospătați pagina%{redirect_url_end}."
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "Codul dvs. de verificare expiră după %{expires_in_minutes} (de) minute."
@@ -20098,6 +20401,12 @@ msgstr "Dacă nu v-ați autentificat recent, trebuie să vă %{password_link_sta
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "Dacă nu v-ați conectat recent, ar trebui să vă schimbați imediat parola: %{password_link}."
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr "Dacă nu dvs. ați încercat recent să vă conectați, trebuie %{password_link_start}să vă schimbați parola%{password_link_end} imediat."
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr "Dacă nu dvs. ați încercat recent să vă conectați, trebuie să vă schimbați imediat parola: %{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 "Dacă primiți o mulțime de alarme false din verificările repozitoriului, puteți șterge toate informațiile verificării repozitoriului din baza de date."
@@ -20107,6 +20416,9 @@ msgstr "Dacă vă pierdeți codurile de recuperare, puteți genera altele noi, i
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "Dacă v-ați conectat recent și recunoașteți adresa IP, puteți ignora acest e-mail."
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr "Dacă dvs. ați încercat recent să vă conectați, dar ați introdus un cod de autentificare cu doi factori greșit, puteți ignora acest e-mail."
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr "Dacă doriți să reactivați autentificarea cu doi factori, vizitați %{two_factor_link}"
@@ -20290,6 +20602,9 @@ msgstr "Conectați repozitoriile de la"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr "Limita de rată %{provider} a fost depășită. Încercați din nou mai târziu"
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "URL de import blocat: %{message}"
@@ -20314,6 +20629,9 @@ msgstr "Solicitarea repozitoriilor dvs. %{provider} a eșuat"
msgid "ImportProjects|Select the repositories you want to import"
msgstr "Selectați repozitoriile pe care doriți să le importați"
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "Datele remote nu au putut fi importate."
@@ -21191,7 +21509,7 @@ msgid "Include the username in the URL if required: %{code_open}https://username
msgstr "Includeți numele de utilizator în URL, dacă este necesar: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
-msgstr ""
+msgstr "Include obiecte LFS. Se poate modifica pentru fiecare grup sau proiect în parte. Setați la 0 pentru nicio limită."
msgid "Includes an MVC structure to help you get started"
msgstr "Include o structură MVC pentru a vă ajuta să începeți"
@@ -21220,6 +21538,9 @@ msgstr "Incomplet"
msgid "Increase"
msgstr "Creștere"
+msgid "Indent line"
+msgstr "Linie de indentare"
+
msgid "Index"
msgstr "Index"
@@ -21442,6 +21763,9 @@ msgstr "Adăugați o integrare"
msgid "Integrations|Add namespace"
msgstr "Adăugare spațiu de nume"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr "Adăugarea unui spațiu de nume funcționează numai în browserele care permit cookie-uri între site-uri. %{linkStart}Aflați mai multe%{linkEnd}."
+
msgid "Integrations|All details"
msgstr "Toate detaliile"
@@ -21502,12 +21826,18 @@ msgstr "Activați verificarea SSL"
msgid "Integrations|Enable comments"
msgstr "Activați comentariile"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr "Verificați dacă URL-ul instanței dvs. este corect și dacă instanța este configurată corect. %{linkStart}Aflați mai multe%{linkEnd}."
+
msgid "Integrations|Enter your alias"
msgstr "Introduceți aliasul dvs."
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "Spațiul de nume n-a putut fi conectat. Vă rugăm să încercați din nou."
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr "Nu s-a putut încărca ID-ul aplicației Jira Connect. Vă rugăm să încercați din nou."
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr "Spațiile de nume n-au putut fi încărcate. Vă rugăm să încercați din nou."
@@ -21520,6 +21850,9 @@ msgstr "Nu s-a reușit conectarea la GitLab."
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr "Spațiul de nume n-a putut fi deconectat. Vă rugăm să încercați din nou."
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr "Nu s-a putut actualiza versiunea GitLab. Vă rugăm să încercați din nou."
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr "Administratorii GitLab pot configura integrări pe care toate grupurile și proiectele le preiau și le utilizează în mod implicit. Aceste integrări se aplică tuturor grupurilor și proiectelor care nu utilizează deja setări personalizate. Puteți suprascrie setările personalizate pentru un grup sau proiect dacă setările sunt necesare la nivelul respectiv. Aflați mai multe despre %{integrations_link_start}gestionarea integrărilor la nivel de instanță%{link_end}."
@@ -21611,7 +21944,7 @@ msgid "Integrations|Send notifications about project events to a Unify Circuit c
msgstr "Trimiteți notificări despre evenimentele proiectului către o conversație Unify Circuit. %{docs_link}"
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "Conectați-vă la %{url}"
msgid "Integrations|Sign in to GitLab"
msgstr "Autentificați-vă în GitLab"
@@ -21712,9 +22045,6 @@ msgstr "Interval"
msgid "Interval Pattern"
msgstr "Model de intervale"
-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 "Introdus în GitLab 13.1, înainte de a utiliza %{reindexing_link_start}reindexarea cu indisponibilitate-zero%{link_end} și %{migrations_link_start}migrările de Căutare avansată%{link_end}, trebuie să %{recreate_link_start}vă recreați indexul%{link_end}."
-
msgid "Introducing Your DevOps Reports"
msgstr "Prezentarea rapoartelor dvs. DevOps"
@@ -22108,6 +22438,12 @@ msgstr "Folosește seat de licență:"
msgid "Is using seat"
msgstr "Folosește seat"
+msgid "IssuableEvents|removed review request for"
+msgstr "a înlăturat solicitarea de revizuire pentru"
+
+msgid "IssuableEvents|requested review from"
+msgstr "a solicitat revizuirea de la"
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr "%{wi_type} creat(ă) la %{created_at} de "
@@ -22207,6 +22543,9 @@ msgstr "Nu s-a reușit încărcarea problemelor. Vă rugăm să încercați din
msgid "IssueAnalytics|Issue"
msgstr "Problemă"
+msgid "IssueAnalytics|Iteration"
+msgstr "Iterație"
+
msgid "IssueAnalytics|Milestone"
msgstr "Obiectiv"
@@ -22579,9 +22918,6 @@ msgstr "Nu se poate salva cadența. Vă rugăm să încercați din nou."
msgid "Iterations|Upcoming iterations"
msgstr "Iterațiile viitoare"
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr "Datele nu se pot suprapune cu alte Iterații existente în cadrul acestui grup."
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr "Datele nu se pot suprapune cu alte iterații existente în cadrul acestei cadențe de iterații."
@@ -23324,7 +23660,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr "Promovarea etichetei %{labelTitle} o va face disponibilă pentru toate proiectele din cadrul %{groupName}. Etichetele de proiect existente cu același titlu vor fi îmbinate. Dacă există o etichetă de grup cu același titlu, aceasta va fi, de asemenea, îmbinată. Această acțiune este ireversibilă."
msgid "Label|Assignee"
-msgstr ""
+msgstr "Responsabil"
msgid "Language"
msgstr "Limbaj"
@@ -23431,6 +23767,9 @@ msgstr "Ultima conectare la:"
msgid "Last successful update"
msgstr "Ultima actualizare reușită"
+msgid "Last successful update %{time}."
+msgstr "Ultima actualizare reușită %{time}."
+
msgid "Last time verified"
msgstr "Ultima dată verificat(ă)"
@@ -23512,8 +23851,8 @@ msgstr "AflaÈ›i cum să %{no_packages_link_start}vă publicaÈ›i È™i să partajaÈ
msgid "Learn more"
msgstr "Aflați mai multe"
-msgid "Learn more about %{username}"
-msgstr "Aflați mai multe despre %{username}"
+msgid "Learn more about %{name}"
+msgstr "Aflați mai multe despre %{name}"
msgid "Learn more about Auto DevOps"
msgstr "Aflați mai multe despre Auto DevOps"
@@ -24290,7 +24629,7 @@ msgid "Mailgun events"
msgstr "Evenimente Mailgun"
msgid "Main menu"
-msgstr ""
+msgstr "Meniul principal"
msgid "Maintenance mode"
msgstr "Modul de întreținere"
@@ -24307,6 +24646,9 @@ msgstr "Faceți ca toți membrii echipei dvs. să fie mai productivi, indiferent
msgid "Make issue confidential"
msgstr "Faceți problema confidențială"
+msgid "Make sure you choose a strong, unique password."
+msgstr "Asigurați-vă că alegeți o parolă puternică și unică."
+
msgid "Make sure you have the correct permissions to link your project."
msgstr "Asigurați-vă că aveți permisiunile adecvate pentru a vă conecta proiectul."
@@ -24358,12 +24700,12 @@ msgstr "Gestionați proiectele."
msgid "Manage two-factor authentication"
msgstr "Gestionați autentificarea cu două factori"
-msgid "Manage your license"
-msgstr "Gestionați-vă licența"
-
msgid "Manage your project's triggers"
msgstr "Gestionați declanșatoarele proiectului dumneavoastră"
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "Cont gestionat"
@@ -24445,9 +24787,24 @@ msgstr "Adăugați text tăiat cu o linie (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Adăugați text tăiat cu o linie (%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr "Linie de indentare (%{modifierKey}])"
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr "Linie de indentare (%{modifier_key}])"
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "Linie de indentare negativă (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "Linie de indentare negativă (%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "Acceptă %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr "Marcat"
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "S-a marcat pentru ștergere la - %{deletion_time}"
@@ -24457,9 +24814,6 @@ msgstr "Marcat ca draft. Poate fi îmbinat doar atunci când este marcat ca fiin
msgid "Marked as ready. Merging is now allowed."
msgstr "Marcat ca gata. Îmbinarea este acum permisă."
-msgid "Marked this %{noun} as a draft."
-msgstr "Acest %{noun} a fost marcat ca un draft"
-
msgid "Marked this %{noun} as ready."
msgstr "Acest/această %{noun} a fost marcat(ă) ca fiind gata."
@@ -24472,8 +24826,8 @@ msgstr "S-a marcat această problemă ca fiind legată de %{issue_ref}."
msgid "Marked to do as done."
msgstr "S-a marcat de făcut ca terminat."
-msgid "Marks this %{noun} as a draft."
-msgstr "Marchează acest %{noun} ca fiind un draft."
+msgid "Marks"
+msgstr "Marcaje"
msgid "Marks this %{noun} as ready."
msgstr "Marchează acest/această %{noun} ca fiind gata."
@@ -24581,7 +24935,7 @@ msgid "Maximum allowable lifetime for access token (days)"
msgstr "Durata de viață maximă permisă pentru tokenul de acces (zile)"
msgid "Maximum allowed lifetime for SSH keys (days)"
-msgstr ""
+msgstr "Durata de viață maximă permisă pentru cheile SSH (zile)"
msgid "Maximum artifacts size"
msgstr "Mărimea maximă a artefactelor"
@@ -24709,6 +25063,9 @@ msgstr "Numărul maxim de solicitări pe minut pentru fiecare cale brută (valoa
msgid "Maximum number of unique IP addresses per user."
msgstr "Numărul maxim de adrese IP unice pe utilizator."
+msgid "Maximum number of variables loaded (2000)"
+msgstr "Numărul maxim de variabile încărcate (2000)"
+
msgid "Maximum of 255 characters"
msgstr "Maxim 255 de caractere"
@@ -25067,7 +25424,7 @@ msgid "Merge requests"
msgstr "Merge request-uri"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "Setările merge request-urilor și aprobărilor au fost mutate."
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Merge request-urile sunt un loc în care puteți propune modificările pe care le-ați făcut la un proiect și să discutați aceste modificări cu alții."
@@ -25843,6 +26200,9 @@ msgstr "Probleme neîncepute (deschise și neatribuite)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr "Folosiți obiectivele pentru a urmări problemele și merge request-urile pe o perioadă fixă de timp"
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} finalizat"
+
msgid "Min Value"
msgstr "Valoare minimă"
@@ -25867,6 +26227,9 @@ msgstr "Setările pentru replici sunt disponibile numai administratorilor GitLab
msgid "Mirror user"
msgstr "Utilizatorul replicii"
+msgid "Mirrored from %{link}."
+msgstr "Replicare din %{link}."
+
msgid "Mirrored repositories"
msgstr "Repozitorii replicate"
@@ -25946,7 +26309,7 @@ msgid "Monitor"
msgstr "Monitor"
msgid "Monitor GitLab with Prometheus."
-msgstr ""
+msgstr "Monitorizați GitLab cu Prometheus."
msgid "Monitor Settings"
msgstr "Setări monitor"
@@ -26131,6 +26494,9 @@ msgstr "Numele este deja luat."
msgid "Name new label"
msgstr "Denumiți noua etichetă"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr "Nume de utilizat ca expeditor pentru e-mailurile de la Service Desk."
+
msgid "Name:"
msgstr "Nume:"
@@ -26347,6 +26713,9 @@ msgstr "Noul program de pipeline"
msgid "New Project"
msgstr "Proiect nou"
+msgid "New Protected Branch"
+msgstr "Noua ramură protejată"
+
msgid "New Requirement"
msgstr "Cerință nouă"
@@ -26552,7 +26921,7 @@ msgid "No Milestone"
msgstr "Niciun Obiectiv"
msgid "No Scopes"
-msgstr "Fără scopuri"
+msgstr "Fără domenii"
msgid "No Work Item Link found"
msgstr "Nu s-a găsit niciun link cu elementul de lucru"
@@ -26624,7 +26993,7 @@ msgid "No credit card required."
msgstr "Nu este nevoie de card de credit."
msgid "No data available"
-msgstr ""
+msgstr "Nu există date disponibile"
msgid "No data found"
msgstr "Nu s-au găsit date"
@@ -26848,6 +27217,9 @@ msgstr[0] "Nu vă faceți griji, puteți utiliza în continuare toate caracteris
msgstr[1] "Nu vă faceți griji, puteți utiliza în continuare toate caracteristicile %{strong}%{plan_name}%{strong_close} pentru acum. Aveți la dispoziție %{remaining_days} zile pentru a vă reînnoi abonamentul."
msgstr[2] "Nu vă faceți griji, puteți utiliza în continuare toate caracteristicile %{strong}%{plan_name}%{strong_close} pentru acum. Aveți la dispoziție %{remaining_days} de zile pentru a vă reînnoi abonamentul."
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "Nr. de commit-uri"
@@ -27002,7 +27374,7 @@ msgid "Nothing to preview."
msgstr "Nimic de previzualizat."
msgid "Notification Email"
-msgstr ""
+msgstr "E-mail de notificare"
msgid "Notification events"
msgstr "Evenimente de notificare"
@@ -27139,11 +27511,20 @@ msgstr "Notificați utilizatorii prin e-mail atunci când locația de conectare
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr "Problema creată de %{author_link} %{issue_reference_link} va expira în curând."
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr "%{author_name} %{action_name} %{ref_type} %{ref_name} din %{project_link}"
+
+msgid "Notify|%{changed_files}:"
+msgstr "%{changed_files}:"
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} în %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
-msgstr ""
+msgstr "%{commits_text} de la ramura „%{target_branch}â€"
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr "%{committed_by_start} de %{author_name} %{committed_by_end} %{committed_at_start} la %{committed_date} %{committed_at_end}"
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email}, cunoscut acum sub numele de %{user_name}, a acceptat invitația de a se alătura la %{target_name} %{target_model_name}."
@@ -27151,26 +27532,50 @@ msgstr "%{invite_email}, cunoscut acum sub numele de %{user_name}, a acceptat in
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "%{invited_user} a %{highlight_start}refuzat%{highlight_end} invitația de a se alătura grupului dvs. %{target_link} %{target_name}."
+msgid "Notify|%{issues} imported."
+msgstr "%{issues} s-a importat."
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} a solicitat %{member_role} acces la %{target_source_link} %{target_type}."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
-msgstr "%{mr_highlight}Merge request-ul%{highlight_end} %{mr_link} %{approved_highlight}a fost aprobată de%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}Merge request-ul%{highlight_end} %{mr_link} %{reviewer_highlight}a fost aprobat de%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}Merge request-ul%{highlight_end} %{mr_link} %{reviewer_highlight}a fost dezaprobat de%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr "%{name} a solicitat o nouă revizuire pentru %{mr_link}."
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr "%{p_start}Pentru a actualiza adresa URL remote în repozitoriul local executați (pentru ssh):%{p_end} %{ssh_url_to_repo} %{p_start}sau pentru http(s):%{p_end} %{http_url_to_repo}."
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr "%{paragraph_start}Bună, %{name}!%{paragraph_end} %{paragraph_start}A fost adăugată o nouă cheie publică în contul dvs.:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}În cazul în care această cheie a fost adăugată din greșeală, o puteți elimina la %{removal_link}%{paragraph_end}"
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr "%{project_link_start}Descărcați%{project_link_end} exportul proiectului."
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr "%{update_at_start} Ultima actualizare la %{update_at_mid} %{last_update_at} %{update_at_end}"
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
-msgstr ""
+msgstr "%{updated_by_user_name} a împins noi commit-uri în merge request-ul %{mr_link}"
msgid "Notify|A new GPG key was added to your account:"
msgstr "O nouă cheie GPG a fost adăugată în contul dvs.:"
+msgid "Notify|A remote mirror update has failed."
+msgstr "O actualizare a replicii remote a eșuat."
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr "După ce acesta expiră, puteți %{a_start} solicita unul nou %{a_end}."
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
-msgstr ""
+msgstr "Toate discuțiile legate de merge request-ul %{mr_link} au fost rezolvate de %{name}"
msgid "Notify|And %{total_stripped_new_commits_count} more"
-msgstr ""
+msgstr "Și încă %{total_stripped_new_commits_count}"
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "Responsabilul a fost schimbat de la %{fromNames} la %{toNames}"
@@ -27187,12 +27592,30 @@ msgstr "Pipeline-ul Auto DevOps a fost dezactivat pentru %{project}"
msgid "Notify|CI/CD project settings"
msgstr "Setări de proiect CI/CD"
+msgid "Notify|Click here to set your password"
+msgstr "Dați click aici pentru a vă seta parola"
+
+msgid "Notify|Commit Author"
+msgstr "Autorul commit-ului"
+
+msgid "Notify|Committed by"
+msgstr "Commit făcut de"
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
-msgstr ""
+msgstr "Nu doriți să primiți actualizări de la administratorii GitLab?"
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr "Eroare la analizarea fișierului CSV. Asigurați-vă că are formatul corect: un fișier text delimitat care utilizează virgula pentru a separa valorile."
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "S-au găsit erori pe %{singular_or_plural_line}: %{error_lines}. Verificați dacă aceste linii au un titlu de problemă."
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr "Amprenta: %{fingerprint}"
+msgid "Notify|Hi %{username}!"
+msgstr "Bună %{username}!"
+
msgid "Notify|Hi %{user}!"
msgstr "Salut %{user}!"
@@ -27211,6 +27634,9 @@ msgstr "Problema a fost mutată la un alt proiect."
msgid "Notify|Learn more about Auto DevOps"
msgstr "Aflați mai multe despre Auto DevOps"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr "Jurnalele pot conține date sensibile. Vă rugăm să luați în considerare acest lucru înainte de a trimite acest e-mail."
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr "Merge request-ul %{merge_request} nu mai poate fi îmbinat din cauza unui conflict."
@@ -27235,24 +27661,66 @@ msgstr "Merge request-ul a fost aprobat"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr "Merge request-ul a fost aprobat (%{approvals}/%{required_approvals})"
+msgid "Notify|Merge request was unapproved"
+msgstr "Merge request-ul nu a fost aprobat"
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr "Merge request-ul nu a fost aprobat (%{approvals_count}/%{approvals_required})"
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr "Obiectivul a fost schimbat in %{milestone}"
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "Obiectiv eliminat"
msgid "Notify|New issue: %{project_issue_url}"
msgstr "Problema nouă: %{project_issue_url}"
+msgid "Notify|No preview for this file type"
+msgstr "Acest tip de fișier nu poate fi previzualizat"
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline-ul %{pipeline_link} declanșat de"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "Pipeline-ul a fost reparat și #%{pipeline_id} a trecut!"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr "Proiectul %{old_path_with_namespace} a fost mutat în altă locație."
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr "Exportul proiectului %{project_name} s-a finalizat."
+
+msgid "Notify|Remote mirror"
+msgstr "Replicare remote"
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr "Administratorul v-a creat un cont. Acum sunteți membru al aplicației GitLab a companiei GitLab."
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "Pipeline-ul Auto DevOps a eșuat pentru pipeline-ul %{pipeline_link} și a fost dezactivat pentru %{project_link}. Pentru a utiliza pipeline-ul Auto DevOps cu proiectul dvs., vă rugăm să revizuiți %{supported_langs_link}, să vă ajustați proiectul în consecință și să activați pipeline-ul Auto DevOps în %{settings_link}."
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr "Diff-ul pentru acest fișier nu a fost inclus pentru că este prea mare."
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr "Diff-ul nu a fost inclus pentru că este prea mare."
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "Linkul de descărcare va expira în 24 de ore."
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr "Proiectul este acum localizat sub %{project_full_name_link_start}%{project_full_name}%{link_end}."
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr "Acest push nu conținea niciun commit nou, dar a executat un push forțat pentru a șterge commit-urile și modificările de mai jos."
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr "Această problemă expiră pe: %{issue_due_date}"
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "Acest link este valabil pentru %{password_reset_token_valid_time}."
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr "Dacă nu vă verificați domeniul până la %{time_start}%{time}%{time_end}, acesta va fi înlăturat din proiectul dumneavoastră GitLab."
@@ -27265,12 +27733,33 @@ msgstr "Ați fost menționat într-o problemă."
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr "Ați fost menționat în merge request-ul %{mr_link}"
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "Ați fost dezabonat de la primirea de notificări de la administratorul GitLab."
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr "Importul CSV pentru proiectul %{project_link} s-a încheiat."
+
+msgid "Notify|Your account has been created successfully."
+msgstr "Crearea contului dvs. s-a finalizat."
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "Solicitarea dvs. de a vă alătura la %{target_to_join} %{target_type} a fost %{denied_tag}."
msgid "Notify|currently supported languages"
msgstr "limbaje acceptate în prezent"
+msgid "Notify|deleted"
+msgstr "șters"
+
+msgid "Notify|login.........................................."
+msgstr "conectare.........................................."
+
+msgid "Notify|pushed new"
+msgstr "a împins nou"
+
+msgid "Notify|pushed to"
+msgstr "a împins spre"
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "s-a(u) finalizat cu succes %{jobs} în %{stages}."
@@ -27331,6 +27820,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "Obiectul nu există pe server sau nu aveți permisiuni pentru a-l accesa"
+msgid "Observability"
+msgstr "Observabilitate"
+
msgid "Oct"
msgstr "Oct"
@@ -27371,7 +27863,7 @@ msgstr[1] "La %{end_date}, perioada de probă se va încheia, iar %{namespace_na
msgstr[2] "La %{end_date}, perioada de probă se va încheia, iar %{namespace_name} va fi limitat la %{free_user_limit} de membri."
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "În bara laterală din stânga, selectați %{merge_requests_link} pentru a le vizualiza."
msgid "On track"
msgstr "Conform planului"
@@ -27493,6 +27985,9 @@ msgstr "Rotații"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr "Direcționați alertele direct către anumiți membri ai echipei dumneavoastră"
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr "Alertați direct anumiți membri ai echipei dvs. Pentru a avea acces la această funcție, solicitați %{linkStart}unui proprietar de proiect%{linkEnd} să vă acorde cel puțin rolul de Întreținător."
+
msgid "OnCallSchedules|Select participant"
msgstr "Selectați participantul"
@@ -28054,6 +28549,9 @@ msgstr "S-ar putea ca GitLab să nu funcționeze corect, deoarece utilizați un
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "Vă rugăm să instalați un %{browser_link_start}browser compatibil%{browser_link_end} pentru o experiență mai bună."
+msgid "Outdent line"
+msgstr "Linie indentare negativă"
+
msgid "Overridden"
msgstr "Suprascris"
@@ -28127,7 +28625,7 @@ msgid "Package already exists"
msgstr "Pachetul există deja"
msgid "Package and registry settings"
-msgstr ""
+msgstr "Setările pachetului și ale registrului"
msgid "Package deleted successfully"
msgstr "Pachetul a fost șters cu succes"
@@ -28166,7 +28664,7 @@ msgid "Package type must be PyPi"
msgstr "Tipul pachetului trebuie să fie PyPi"
msgid "Package type must be RPM"
-msgstr ""
+msgstr "Tipul pachetului trebuie să fie RPM"
msgid "Package type must be RubyGems"
msgstr "Tipul pachetului trebuie să fie RubyGems"
@@ -28297,15 +28795,15 @@ msgstr[0] "Ștergeți 1 activ"
msgstr[1] "Ștergeți %d active"
msgstr[2] "Ștergeți %d de active"
-msgid "PackageRegistry|Delete Package File"
-msgstr "Ștergeți fișierul pachetului"
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Ștergeți versiunea pachetului"
msgid "PackageRegistry|Delete package"
msgstr "Ștergeți pachetul"
+msgid "PackageRegistry|Delete package asset"
+msgstr "Ștergeți activul pachetului"
+
msgid "PackageRegistry|Delete selected"
msgstr "Ștergeți selectat"
@@ -28372,6 +28870,9 @@ msgstr "Nivel de instanță"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr "Pachet invalid: extracția metadatelor a eșuat"
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "Ultima descărcare %{dateTime}"
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Aflați cum să vă %{noPackagesLinkStart}publicați și să partajați pachetele%{noPackagesLinkEnd} cu GitLab."
@@ -28405,15 +28906,15 @@ msgstr "Numărul de active duplicate care trebuie păstrate"
msgid "PackageRegistry|Package Registry"
msgstr "Registrul de pachete"
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr "Ștergerea activului pachetului s-a finalizat"
+
msgid "PackageRegistry|Package assets deleted successfully"
msgstr "Activele pachetului au fost șterse"
msgid "PackageRegistry|Package deleted successfully"
msgstr "Pachetul a fost șters cu succes"
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr "Fișierul pachet a fost șters cu succes"
-
msgid "PackageRegistry|Package formats"
msgstr "Formatele pachetelor"
@@ -28426,6 +28927,9 @@ msgstr[2] "Pachetul are %{updatesCount} de actualizări arhivate"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr "Pachet actualizat de commit-ul %{link} pe ramura %{branch}, construit de pipeline-ul %{pipeline} și publicat în registru la %{datetime}"
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr "Ștergeți permanent activele"
@@ -28477,12 +28981,12 @@ msgstr "Afișați comenzile PyPi"
msgid "PackageRegistry|Show Yarn commands"
msgstr "Afișați comenzile Yarn"
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
+msgstr "Ceva nu a mers bine la ștergerea activului pachetului."
+
msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr "Ceva nu a mers bine la ștergerea activelor pachetului."
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr "Ceva nu a mers bine la ștergerea fișierului pachetului."
-
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr "Ceva nu a mers bine la ștergerea pachetului."
@@ -28537,8 +29041,8 @@ msgstr "Atunci când un pachet cu același nume și versiune este încărcat în
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr "Sunteți pe cale să ștergeți %{filename}. Aceasta este o acțiune distructivă care poate face pachetul dvs. inutilizabil. Sunteți sigur?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "Sunteți pe cale să ștergeți %{name}, această operațiune este ireversibilă, sunteți sigur?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28562,7 +29066,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr "publicat de %{author}"
msgid "Packages and registries"
-msgstr ""
+msgstr "Pachete și registre"
msgid "Page not found"
msgstr "Pagina nu a fost găsită"
@@ -28753,9 +29257,6 @@ msgstr "Căile care trebuie protejate cu limitarea ratei"
msgid "Pause"
msgstr "Pauză"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr "Întrerupeți indexarea și actualizați Elasticsearch la o versiune acceptată."
-
msgid "Pause time (ms)"
msgstr "Timp de pauză (ms)"
@@ -28889,7 +29390,7 @@ msgid "Period of inactivity (days)"
msgstr "Perioada de inactivitate (zile)"
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "Perioada de inactivitate înainte de dezactivare."
msgid "Permalink"
msgstr "Permalink"
@@ -29158,9 +29659,21 @@ msgstr "Activ"
msgid "PipelineSchedules|All"
msgstr "Toate"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Inactiv"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Următoarea execuție"
@@ -29170,15 +29683,27 @@ msgstr "Niciunul"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr "Proprietarul unui program de pipeline este singurul care poate să-l modifice. Doriți să vă asumați proprietatea asupra acestui program?"
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Furnizați o scurtă descriere pentru acest pipeline"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Asumați-vă proprietatea"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Țintă"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Variabile"
@@ -29293,6 +29818,12 @@ msgstr "Setările pipeline-urilor pentru „%{project_name}†au fost actualiza
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr "„Hello world†cu GitLab Cl"
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr "%{jobs} %{ref_text} în %{duration}"
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr "(în coadă de așteptare pentru %{queued_duration})"
+
msgid "Pipelines|1. Set up a runner"
msgstr "1. Configurați un executor"
@@ -29606,7 +30137,7 @@ msgid "Pipeline|Manual"
msgstr "Manual"
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "Pipeline de merge request"
msgid "Pipeline|Merge train pipeline"
msgstr "Pipeline de merge train"
@@ -29974,6 +30505,9 @@ msgstr "Vă rugăm să introduceți %{phrase_code} pentru a continua sau să în
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "Vă rugăm să folosiți acest formular pentru a raporta administratorului utilizatorii care creează probleme de spam, comentarii sau se comportă necorespunzător."
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr "Vă rugăm să așteptați câteva momente în timp ce încărcăm istoricul fișierului pentru această linie."
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Vă rugăm să așteptați un moment, această pagină se va reîmprospăta automat când va fi gata."
@@ -29983,6 +30517,9 @@ msgstr "Vă rugăm să așteptați în timp ce ne conectăm la repozitoriul dumn
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Vă rugăm să așteptați până când importăm repozitoriul pentru dumneavoastră. Reîncărcați în orice moment."
+msgid "Please wait while we prepare for verification."
+msgstr "Vă rugăm să așteptați în timp ce ne pregătim pentru verificare."
+
msgid "Pods in use"
msgstr "Pod-uri în uz"
@@ -30043,6 +30580,9 @@ msgstr "Preferințe"
msgid "Preferences saved."
msgstr "Preferințe salvate."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Comportament"
@@ -30050,7 +30590,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr "Alegeți între aspectul fix (max. 1280px) și fluid (%{percentage}) al aplicației."
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "Alegeți conținutul implicit pe care doriți să-l vedeți în tabloul de bord."
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Alegeți ce conținut doriți să vedeți în pagina de prezentare generală a unui proiect."
@@ -30077,7 +30617,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr "Personalizați culorile liniilor eliminate și adăugate în diff-uri."
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "Tabloul de bord"
msgid "Preferences|Diff colors"
msgstr "Culorile diff-ului"
@@ -30154,6 +30694,9 @@ msgstr "Preferințele de timp"
msgid "Preferences|Use relative times"
msgstr "Utilizați timpi relativi"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "Atunci când introduceți text într-o casetă de descriere sau de comentariu, textul selectat este înconjurat de caracterul corespunzător după ce ați introdus unul dintre caracterele următoare: %{supported_characters}."
@@ -30367,15 +30910,9 @@ msgstr "Activ"
msgid "Profiles|Add key"
msgstr "Adăugați cheia"
-msgid "Profiles|Add status emoji"
-msgstr "Adăugați emoji de stare"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "A apărut o eroare la actualizarea numelui de utilizator, vă rugăm să încercați din nou."
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr "Un indicator apare lângă numele și avatarul dumneavoastră."
-
msgid "Profiles|Avatar cropper"
msgstr "Decupator de avatar"
@@ -30388,9 +30925,6 @@ msgstr "ÃŽncepe cu %{ssh_key_algorithms}."
msgid "Profiles|Bio"
msgstr "Scurtă biografie"
-msgid "Profiles|Busy"
-msgstr "Ocupat"
-
msgid "Profiles|Change username"
msgstr "Schimbați numele de utilizator"
@@ -30406,9 +30940,6 @@ msgstr "Selectați afișarea contribuțiilor din proiectele private în profilul
msgid "Profiles|City, country"
msgstr "Oraș, țară"
-msgid "Profiles|Clear status"
-msgstr "Ștergeți starea"
-
msgid "Profiles|Commit email"
msgstr "E-mail pentru commit-uri"
@@ -30421,6 +30952,9 @@ msgstr "Conectați un serviciu pentru autentificare."
msgid "Profiles|Connected Accounts"
msgstr "Conturi conectate"
+msgid "Profiles|Created%{time_ago}"
+msgstr "Creată %{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "Calea curentă: %{path}"
@@ -30658,9 +31192,6 @@ msgstr "Utilizarea emojiurilor în nume pare amuzantă, în schimb, vă rugăm s
msgid "Profiles|Website url"
msgstr "URL-ul site-ului web"
-msgid "Profiles|What's your status?"
-msgstr "Care este starea dvs. actuală?"
-
msgid "Profiles|Who you represent or work for."
msgstr "Pe cine reprezentați sau pentru cine lucrați."
@@ -30706,9 +31237,6 @@ msgstr "Numele dvs. a fost setat automat în funcție de contul dvs. %{provider_
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "Numele dvs. a fost setat automat pe baza contului dvs. %{provider_label}, pentru ca cei pe care îi cunoașteți să vă poată recunoaște."
-msgid "Profiles|Your status"
-msgstr "Starea dumneavoastră"
-
msgid "Profiles|https://website.com"
msgstr "https://website.com"
@@ -31198,6 +31726,9 @@ msgstr "Alegeți-vă metoda de îmbinare, opțiunile de îmbinare, verificările
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr "Alegeți metoda de îmbinare, opțiunile, verificările și opțiunile de squash."
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr "Combinați etichetele git cu notele de lansare, dovezile de lansare și activele pentru a crea o versiune."
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "Configurați resursele proiectului și monitorizați starea lor de sănătate."
@@ -31228,6 +31759,9 @@ msgstr "Activați merge train-urile"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr "Activați pipeline-urile de rezultate combinate"
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "Activați recenzenții recomandați"
+
msgid "ProjectSettings|Encourage"
msgstr "Încurajați"
@@ -31351,12 +31885,18 @@ msgstr "Sugestii de îmbinare"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr "Îmbinarea este permisă numai atunci când ramura sursă este actualizată cu cea țintă."
+msgid "ProjectSettings|Monitor"
+msgstr "Monitorizare"
+
msgid "ProjectSettings|No merge commits are created."
msgstr "Nu se creează niciun commit de îmbinare"
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr "Notă: Registrul containerului este întotdeauna vizibil când un proiect este public È™i registrul containerului este setat la „%{access_level_description}â€"
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Numai la commit-urile semnate se poate face push către acest repozitoriu."
@@ -31393,6 +31933,9 @@ msgstr "Vizibilitatea proiectului"
msgid "ProjectSettings|Public"
msgstr "Public"
+msgid "ProjectSettings|Releases"
+msgstr "Versiuni"
+
msgid "ProjectSettings|Repository"
msgstr "Repozitoriu"
@@ -31546,8 +32089,8 @@ msgstr "Atunci când există un conflict de îmbinare, utilizatorului i se oferÄ
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr "Cu GitLab Pages puteți găzdui site-urile dvs. statice pe GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr "Cu GitLab Pages vă puteți găzdui site-urile statice pe GitLab. GitLab Pages utilizează un mecanism de caching pentru eficiență. S-ar putea ca modificările pe care le faceți să nu aibă efect până când această memorie cache nu este invalidată, ceea ce durează de obicei mai puțin de un minut."
msgid "ProjectTemplates|.NET Core"
msgstr ".NET Core"
@@ -31636,6 +32179,9 @@ msgstr "Tencent Serverless Framework/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr "A apărut o eroare la preluarea locațiilor de transfer, vă rugăm să reîmprospătați pagina și să încercați din nou."
+
msgid "ProjectView|Activity"
msgstr "Activitate"
@@ -32158,6 +32704,9 @@ msgstr "Autorizați să facă push"
msgid "ProtectedBranch|Allowed to push:"
msgstr "Autorizați să facă push:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr "S-a produs o eroare la încărcarea regulilor ramurii. Vă rugăm să încercați din nou."
+
msgid "ProtectedBranch|Branch"
msgstr "Ramura"
@@ -32194,6 +32743,9 @@ msgstr "Ramuri protejate (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "Ramuri protejate"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr "Ramurile protejate, aprobările de merge request și verificările de stare vor apărea aici odată configurate."
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr "Refuzați împingerile de cod care modifică fișierele enumerate în fișierul CODEOWNERS."
@@ -32218,6 +32770,9 @@ msgstr "Deprotejați ramura"
msgid "ProtectedBranch|What are protected branches?"
msgstr "Ce sunt ramurile protejate?"
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr "Puteți adăuga numai grupurile care au acest proiect partajat. %{learn_more_link}"
+
msgid "ProtectedBranch|default"
msgstr "implicit"
@@ -32225,7 +32780,7 @@ msgid "ProtectedEnvironment|%{environment_name} will be writable for developers.
msgstr "%{environment_name} va putea fi editat de dezvoltatori. Sunteți sigur?"
msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
-msgstr ""
+msgstr "Toate mediile specificate cu nivelurile de implementare de mai jos sunt protejate de un grup părinte. %{link_start}Aflați mai multe%{link_end}."
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Autorizat să desfășoare"
@@ -32243,7 +32798,7 @@ msgid "ProtectedEnvironment|Failed to load details for this group."
msgstr "Încărcarea detaliilor pentru acest grup a eșuat."
msgid "ProtectedEnvironment|No environments in this project are protected."
-msgstr ""
+msgstr "Nu există medii protejate în acest proiect."
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
msgstr "Numai grupurile specificate pot executa implementări în medii protejate."
@@ -32374,6 +32929,9 @@ msgstr "Publică această problemă pe pagina de stare asociată."
msgid "Pull"
msgstr "Pull"
+msgid "Pull mirroring updated %{time}."
+msgstr "Replicarea pull actualizată %{time}."
+
msgid "Pull requests from fork are not supported"
msgstr "Pull request-urile din fork nu sunt acceptate"
@@ -32443,18 +33001,48 @@ msgstr "Toate mesajele de commit trebuie să corespundă acestei %{wiki_syntax_l
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr "Toate numele de fișiere comise nu se pot potrivi cu această %{wiki_syntax_link_start}expresie regulată%{wiki_syntax_link_end}. Dacă este necompletă, este permis orice nume de fișier."
+msgid "PushRules|Branch name"
+msgstr "Numele ramurii"
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr "Verificați dacă autorul commit-ului este un utilizator GitLab"
+
+msgid "PushRules|Commit author's email"
+msgstr "E-mailul autorului commit-ului"
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr "Mesajele de commit nu se pot potrivi cu această %{wiki_syntax_link_start}expresie regulată%{wiki_syntax_link_end}. Dacă este necompletă, mesajele de commit nu sunt respinse pe baza niciunei expresii."
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr "Nu permiteți utilizatorilor să elimine etichete Git cu %{code_block_start}git push%{code_block_end}"
+msgid "PushRules|Maximum file size (MB)"
+msgstr "Mărimea maximă a fișierului (MB)"
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr "Nu permiteți să se facă push de fișiere secrete"
+
+msgid "PushRules|Prohibited file names"
+msgstr "Nume interzise pentru fișiere"
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr "Respingeți orice fișier care ar putea conține secrete. %{secret_files_link_start}Ce fișiere secrete sunt respinse?%{secret_files_link_end}"
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr "Respingeți mesajele de commit bazate pe această expresie"
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr "Respingeți fișierele de mărimi egale sau mai mari decât această mărime. Dacă este setat la 0, sunt permise fișiere de orice mărime. Această regulă nu se aplică fișierelor urmărite de Git LFS."
+msgid "PushRules|Reject unsigned commits"
+msgstr "Respingeți commit-urile nesemnate"
+
+msgid "PushRules|Require expression in commit messages"
+msgstr "Solicitați o expresie în mesajele commit-urilor"
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr "Limitați commit-urile la utilizatorii GitLab existenți."
@@ -32605,9 +33193,6 @@ msgstr "Citiți mai mult"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr "Citiți mai multe despre GitLab la %{link_to_promo}."
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr "Citiți mai multe despre permisiunile de proiect %{help_link_open}aici%{help_link_close}"
-
msgid "Read more about related epics"
msgstr "Citiți mai multe despre epicele conexe"
@@ -32764,9 +33349,6 @@ msgstr "Înregistrați dispozitivul universal cu doi factori (U2F)"
msgid "Register WebAuthn Device"
msgstr "Înregistrați dispozitivul WebAuthn"
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr "Înregistrați cât de mulți executori doriți. Puteți înregistra executorii ca utilizatori separați, pe servere separate și pe computerul dvs. local. Executorii sunt fie:"
-
msgid "Register device"
msgstr "Înregistrați dispozitivul"
@@ -33658,6 +34240,9 @@ msgstr "Replicarea repozitoriului"
msgid "Repository mirroring configuration"
msgstr "Configurația replicării repozitoriului"
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "Repozitoriul trebuie să conțină cel puțin 1 fișier."
@@ -34048,6 +34633,9 @@ msgstr "Tokenul de impersonare %{token_name} a fost revocat!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Token de acces personal revocat %{personal_access_token_name}!"
+msgid "Rich text"
+msgstr "Text îmbogățit"
+
msgid "RightSidebar|Copy email address"
msgstr "Copiați adresa de e-mail"
@@ -34069,6 +34657,9 @@ msgstr "Rol"
msgid "Rollback"
msgstr "Rollback"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr "Introducerea de limite gratuite de utilizatori în GitLab.com. Nu modificați aceste valori decât dacă s-a acordat aprobarea prin %{link_start}această problemă%{link_end}."
+
msgid "Ruby"
msgstr "Ruby"
@@ -34166,7 +34757,7 @@ msgid "Runners|Add notes, like who owns the runner or what it should be used for
msgstr "Adăugați note, cum ar fi cine este proprietarul executorului sau la ce ar trebui să fie folosit."
msgid "Runners|Add your feedback in the issue"
-msgstr ""
+msgstr "Adăugați un feedback la problemă"
msgid "Runners|All"
msgstr "Toți"
@@ -34289,7 +34880,7 @@ msgid "Runners|Executor"
msgstr "Executor"
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "Filtrare proiecte"
msgid "Runners|Get started with runners"
msgstr "Începeți cu executorii"
@@ -34297,6 +34888,9 @@ msgstr "Începeți cu executorii"
msgid "Runners|Group"
msgstr "Grup"
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr "Cum actualizăm executorul GitLab?"
@@ -34330,9 +34924,6 @@ msgstr "Timpul maxim de expirare a jobului"
msgid "Runners|Members of the %{type} can register runners"
msgstr "Membrii cu rol de %{type} pot înregistra executori"
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr "Nu se pot șterge executorii multi-proiect"
-
msgid "Runners|Name"
msgstr "Nume"
@@ -34342,6 +34933,9 @@ msgstr "Niciodată contactat"
msgid "Runners|Never contacted:"
msgstr "Niciodată contactat:"
+msgid "Runners|Never expires"
+msgstr "Nu expiră niciodată"
+
msgid "Runners|New group runners view"
msgstr "Noua vizualizare a executorilor de grup"
@@ -34411,6 +35005,9 @@ msgstr "Înregistrați un executor"
msgid "Runners|Register an instance runner"
msgstr "Înregistrați un executor de instanță"
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "Tokenul de înregistrare"
@@ -34438,8 +35035,11 @@ msgstr "Executorul %{name} a fost șters"
msgid "Runners|Runner assigned to project."
msgstr "Executorul a fost atribuit proiectului."
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr "Executorul nu poate fi șters, vă rugăm să contactați administratorul d-voastră"
+msgid "Runners|Runner authentication token expiration"
+msgstr "Expirarea tokenului de autentificare a executorului"
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
+msgstr "Tokenurile de autentificare ale executorului vor expira după un interval stabilit. Odată expirate, acestea vor fi înlocuite automat."
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
msgstr "Executorul a contactat GitLab în ultimele %{elapsedTime}"
@@ -34489,6 +35089,9 @@ msgstr "Executorul a fost dezasociat din proiect"
msgid "Runners|Runners"
msgstr "Executori"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "Executorii sunt agenții care execută joburile CI/CD. Urmați %{linkStart}instrucțiunile de instalare și înregistrare%{linkEnd} pentru a configura un executor."
@@ -34501,6 +35104,9 @@ msgstr "Selectați proiectele pe care să le atribuiți acestui executor"
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr "Selectați opțiunea preferată aici. În etapa următoare, puteți alege capacitatea executorului dvs. în consola AWS CloudFormation."
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr "Afișați instrucțiunile de instalare și înregistrare a executorului"
@@ -34531,6 +35137,9 @@ msgstr "Împiedicați executorul să mai accepte noi joburi."
msgid "Runners|Tags"
msgstr "Etichete"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr "Duceți-mă acolo!"
@@ -34570,6 +35179,9 @@ msgstr "Pentru a instala un Executor într-un container, urmați instrucțiunile
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr "Pentru a-i înscrie, mergeți la %{link_start}pagina executorilor grupului%{link_end}."
+msgid "Runners|Token expiry"
+msgstr "Expirarea tokenului"
+
msgid "Runners|Up to date"
msgstr "La zi"
@@ -34610,10 +35222,10 @@ msgid "Runners|View installation instructions"
msgstr "Vizualizați instrucțiunile de instalare"
msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
-msgstr ""
+msgstr "Dorim să vă puteți gestiona executorii ușor și eficient de pe această pagină și facem schimbări pentru a atinge acest obiectiv. Dați-ne feedback cu privire la modul în care ne descurcăm!"
msgid "Runners|We've made some changes and want your feedback"
-msgstr ""
+msgstr "Am efectuat câteva modificări și am dori să avem feedbackul d-voastră"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
msgstr "Windows 2019 Shell cu scalare manuală și programare opțională. Spot %{percentage}."
@@ -34789,9 +35401,6 @@ msgstr "Se salvează proiectul."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr "%{ifLabelStart}dacă%{ifLabelEnd} acțiunile %{rules} pentru %{scopes} %{branches}"
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr "%{ifLabelStart}dacă%{ifLabelEnd} %{rules} pentru ramura/ramurile %{branches}"
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr "ScanExecutionPolicy|%{period} %{days} la %{time}"
@@ -34799,13 +35408,13 @@ msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan
msgstr "%{thenLabelStart}Atunci%{thenLabelEnd} necesită executarea unei scanări %{scan}"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
-msgstr ""
+msgstr "%{thenLabelStart}Atunci%{thenLabelEnd} Solicitați executarea unei scanări %{scan} cu profilul de site %{siteProfile} și profilul de scaner %{scannerProfile}"
msgid "ScanExecutionPolicy|A pipeline is run"
msgstr "Se execută un pipeline"
msgid "ScanExecutionPolicy|Scanner profile"
-msgstr ""
+msgstr "Profil de scaner"
msgid "ScanExecutionPolicy|Schedule"
msgstr "Programare"
@@ -34817,13 +35426,13 @@ msgid "ScanExecutionPolicy|Select branches"
msgstr "Selectați ramurile"
msgid "ScanExecutionPolicy|Select scanner profile"
-msgstr ""
+msgstr "Selectați profilul scanerului"
msgid "ScanExecutionPolicy|Select site profile"
-msgstr ""
+msgstr "Selectați profilul site-ului"
msgid "ScanExecutionPolicy|Site profile"
-msgstr ""
+msgstr "Profil de site"
msgid "ScanExecutionPolicy|branch"
msgstr "ramura"
@@ -34939,6 +35548,9 @@ msgstr "Căutați responsabili"
msgid "Search authors"
msgstr "Căutați autorii"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Căutați ramuri"
@@ -35026,6 +35638,9 @@ msgstr "Căutați proiecte"
msgid "Search projects..."
msgstr "Căutare proiecte..."
+msgid "Search protected branches"
+msgstr "Căutare ramuri protejate"
+
msgid "Search rate limits"
msgstr "Limitele ratei de căutare"
@@ -35341,14 +35956,14 @@ msgstr "Gestionați profilurile"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr "Gestionați profilurile de utilizat de către scanările DAST."
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr "Mai multe tipuri de scanare, inclusiv Scanarea de containere, DAST, Scanarea dependențelor, Fuzzing și Conformitatea licenței"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "Neactivat"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
-msgstr "Odată ce ați activat o scanare pentru ramura implicită, orice ramură de caracteristică ulterioară pe care o creați va include scanarea."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
+msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
msgstr "Activați rapid toate instrumentele de testare continuă și de conformitate prin activarea %{linkStart}Auto DevOps%{linkEnd}"
@@ -35404,9 +36019,6 @@ msgstr "%{scanners}"
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr "%{scanners} %{severities} într-un merge request deschis care vizează %{branches}."
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} mai mult"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ", și %{count} mai mult"
@@ -35809,6 +36421,9 @@ msgstr "Creați o problemă Jira"
msgid "SecurityReports|Create issue"
msgstr "Creați o problemă"
+msgid "SecurityReports|Detection"
+msgstr "Detecție"
+
msgid "SecurityReports|Development vulnerabilities"
msgstr "Vulnerabilități de dezvoltare"
@@ -35821,6 +36436,9 @@ msgstr "„%{vulnerabilityName}†a fost respinsă"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "„%{vulnerabilityName}†a fost respinsă. Dezactivați comutatorul de ascundere a respingerilor pentru a vizualiza."
+msgid "SecurityReports|Does not have issue"
+msgstr "Nu are probleme"
+
msgid "SecurityReports|Download %{artifactName}"
msgstr "Descărcați %{artifactName}"
@@ -35851,12 +36469,18 @@ msgstr "Eroare la analizarea rapoartelor de securitate"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr "Nu s-au putut obține informații despre raportul de securitate. Vă rugăm să reîncărcați pagina sau să încercați din nou mai târziu."
+msgid "SecurityReports|Has issue"
+msgstr "Are probleme"
+
msgid "SecurityReports|Hide dismissed"
msgstr "Ascundeți elementele respinse"
msgid "SecurityReports|Image"
msgstr "Imagine"
+msgid "SecurityReports|Issue"
+msgstr "Problema"
+
msgid "SecurityReports|Issue Created"
msgstr "Problemă creată"
@@ -35974,6 +36598,9 @@ msgstr "Ne pare rău, filtrul dvs. nu a produs rezultate"
msgid "SecurityReports|Status"
msgstr "Status"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr "Trimiteți vulnerabilitatea"
@@ -36097,9 +36724,6 @@ msgstr "Selectați formatul arhivei"
msgid "Select Git revision"
msgstr "Selectați revizuirea Git"
-msgid "Select Page"
-msgstr "Selectați pagina"
-
msgid "Select Profile"
msgstr "Selectați profilul"
@@ -36145,9 +36769,6 @@ msgstr "Selectați un repozitoriu de șabloane"
msgid "Select a template type"
msgstr "Selectați un tip de șablon"
-msgid "Select a time zone"
-msgstr "Selectați un fus orar"
-
msgid "Select a timezone"
msgstr "Selectați un fus orar"
@@ -36169,9 +36790,15 @@ msgstr "Selectați responsabilul"
msgid "Select branch"
msgstr "Selectați ramura"
+msgid "Select branch or create wildcard"
+msgstr "Selectați ramura sau creați un wildcard"
+
msgid "Select branches"
msgstr "Selectați ramura"
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Selectați data scadentă"
@@ -36217,6 +36844,9 @@ msgstr "Selectați proiectul pentru a crea problema"
msgid "Select projects"
msgstr "Selectați proiecte"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Selectare recenzent(i)"
@@ -36529,6 +37159,9 @@ msgstr "Setați ramura țintă"
msgid "Set target branch to %{branch_name}."
msgstr "Setați ramura țintă la %{branch_name}."
+msgid "Set the Draft status"
+msgstr "Setați starea de Draft"
+
msgid "Set the Ready status"
msgstr "Setați starea Gata"
@@ -36604,18 +37237,15 @@ msgstr "Setați greutatea"
msgid "Set weight to %{weight}."
msgstr "Setați greutate la %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "Un indicator apare lângă numele și avatarul dumneavoastră"
-
-msgid "SetStatusModal|Busy"
-msgstr "Ocupat"
-
msgid "SetStatusModal|Clear status"
msgstr "Ștergeți starea"
msgid "SetStatusModal|Clear status after"
msgstr "Ștergeți starea după"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "Afișează faptul că sunteți ocupat sau că nu puteți răspunde"
+
msgid "SetStatusModal|Edit status"
msgstr "Editați starea"
@@ -36628,6 +37258,9 @@ msgstr "Setați o stare"
msgid "SetStatusModal|Set status"
msgstr "Setați starea"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "Setați-vă ca fiind ocupat"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Ne pare rău, nu am putut să vă stabilim statusul. Vă rugăm să încercați din nou mai târziu."
@@ -37231,6 +37864,39 @@ msgstr "Completați cuvântul care se potrivește cel mai bine echipei dumneavoa
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr "Efectuați operații comune în acest proiect introducând comenzi slash în Slack."
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr "%{asterisk}Etapa 1.%{asterisk} Conectați-vă contul GitLab pentru a începe."
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr "%{asterisk}Etapa 2.%{asterisk} Încercați-l!"
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr "%{emoji}Conectat la contul GitLab %{account}"
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr "%{emoji}Bine ați venit la GitLab pentru Slack!"
+
+msgid "Slack|Connect your GitLab account"
+msgstr "Conectează-ți contul GitLab"
+
+msgid "Slack|Create a new issue"
+msgstr "Creați o nouă problemă"
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr "Creați probleme noi din Slack: %{command}"
+
+msgid "Slack|Run a CI/CD job"
+msgstr "Rulați o sarcină CI/CD"
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr "Vedeți o listă de comenzi disponibile: %{command})"
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr "Simplificați-vă implementările GitLab cu ChatOps. După ce v-ați configurat %{startMarkup}pipeline-urile CI/CD%{endMarkup}, încercați: %{command}"
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr "Vizualizați și controlați conținutul GitLab în timp ce lucrați în Slack. Introduceți comanda ca mesaj în clientul dvs. de chat pentru a o activa. %{startMarkup}Aflați mai multe%{endMarkup}."
+
msgid "Slice multiplier"
msgstr "Multiplicator de tranșe"
@@ -37297,6 +37963,9 @@ msgstr "Fragmentele de cod nu pot conține fișiere goale. Asigurați-vă că to
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr "Solid"
@@ -37355,7 +38024,7 @@ msgid "Something went wrong when reordering designs. Please try again"
msgstr "Ceva nu a mers bine atunci când am reordonat design-urile. Vă rugăm să încercați din nou"
msgid "Something went wrong while adding timeline event."
-msgstr ""
+msgstr "Ceva nu a mers bine la adăugarea evenimentului cronologic."
msgid "Something went wrong while adding your award. Please try again."
msgstr "Ceva nu a mers bine la adăugarea premiului dumneavoastră. Vă rugăm să încercați din nou."
@@ -37537,6 +38206,9 @@ msgstr "Direcția de sortare: Ascendentă"
msgid "Sort direction: Descending"
msgstr "Direcția de sortare: Descendentă"
+msgid "Sort or filter"
+msgstr "Sortare sau filtrare"
+
msgid "SortOptions|Blocking"
msgstr "Blocări"
@@ -37579,6 +38251,9 @@ msgstr "Ultimul contact"
msgid "SortOptions|Last created"
msgstr "Ultimul creat"
+msgid "SortOptions|Latest version"
+msgstr "Versiunea cea mai recentă"
+
msgid "SortOptions|Least popular"
msgstr "Cel mai puțin popular"
@@ -37639,6 +38314,9 @@ msgstr "Cel mai vechi marcat cu stea"
msgid "SortOptions|Oldest updated"
msgstr "Cea mai veche actualizare"
+msgid "SortOptions|Oldest version"
+msgstr "Versiunea cea mai veche"
+
msgid "SortOptions|Popularity"
msgstr "Popularitate"
@@ -38539,8 +39217,8 @@ msgstr "Ecran verde"
msgid "SuggestedColors|Green-cyan"
msgstr "Verde-cyan"
-msgid "SuggestedColors|Lavendar"
-msgstr "Levănțică"
+msgid "SuggestedColors|Lavender"
+msgstr "Lavandă"
msgid "SuggestedColors|Magenta-pink"
msgstr "Magenta-roz"
@@ -38563,9 +39241,21 @@ msgstr "Roșu trandafiriu"
msgid "SuggestedColors|Titanium yellow"
msgstr "Galben titan"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "Obțineți recomandări pentru recenzenți bazate pe instrumentul de învățare automată al GitLab."
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "Recenzenți recomandați"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "Recomandările apar în secțiunea Recenzent din bara laterală din dreapta."
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr "Sugestia nu se aplică, deoarece sugestia nu a fost găsită."
+msgid "Suggestion(s)"
+msgstr "Sugestie (sugestii)"
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr "Sugestiile nu se aplică deoarece nu au fost găsite una sau mai multe sugestii."
@@ -38602,8 +39292,14 @@ msgstr "Activați abonamentul"
msgid "SuperSonics|Activation code"
msgstr "Cod de activare"
-msgid "SuperSonics|An error occurred while adding your subscription."
-msgstr "A apărut o eroare la adăugarea abonamentului dumneavoastră."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr "Activarea nu este posibilă din cauza unei nepotriviri de seat-uri"
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr "Activarea nu este posibilă din cauza nepotrivirii valorii true-up"
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr "A apărut o eroare la adăugarea abonamentului dumneavoastră"
msgid "SuperSonics|Billable users"
msgstr "Utilizatori facturabili"
@@ -38611,8 +39307,8 @@ msgstr "Utilizatori facturabili"
msgid "SuperSonics|Buy subscription"
msgstr "Cumpărați un abonament"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr "Nu se poate activa instanța din cauza unei probleme de conectivitate."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr "Instanța nu poate fi activată datorită unei probleme de conectivitate"
msgid "SuperSonics|Cloud licensing"
msgstr "Licențiere în cloud"
@@ -38728,26 +39424,38 @@ msgstr "Aveți o licență postdatată"
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "Ați adăugat o licență care se activează pe %{date}. Pentru mai multe detalii, consultați tabelul cu istoricul abonamentelor de mai jos."
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "Ați aplicat un true-up pentru %{trueUpQuantity} %{trueUpQuantityUsers}, dar aveți nevoie de unul pentru %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. Pentru a plăti pentru depășirea de seat-uri, contactați reprezentantul dvs. de vânzări. Pentru asistență suplimentară, contactați %{licenseSupportLinkStart}serviciul de asistență GitLab%{licenseSupportLinkEnd}."
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "Ați adăugat cu succes o licență care se activează pe %{date}. Pentru mai multe detalii, consultați tabelul cu istoricul abonamentelor de mai jos."
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr "Se poate să fi introdus un cod de activare expirat sau neeligibil. Pentru a solicita un nou cod de activare, %{purchaseSubscriptionLinkStart}achiziționați un nou abonament%{purchaseSubscriptionLinkEnd} sau %{supportLinkStart}contactați Asistența GitLab%{supportLinkEnd} pentru ajutor suplimentar."
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "Veți fi taxat pentru %{trueUpLinkStart}utilizatorii peste licența%{trueUpLinkEnd} pe o bază trimestrială sau anuală, în funcție de termenii contractului dumneavoastră."
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr "Abonamentul dvs. %{subscriptionEntryName} nu poate fi afișat în acest moment. Vă rugăm să reîmprospătați pagina pentru a încerca din nou."
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "Instalarea GitLab actuală are %{userCount} %{userCountUsers} activi, care depășește cu %{overageCount} numărul de %{licenseUserCount} de seat-uri pentru noul abonament. Pentru a vă activa noul abonament, %{purchaseLinkStart}achiziționați%{purchaseLinkEnd} încă %{overageCount} %{overageCountSeats}, sau %{deactivateLinkStart}dezactivați%{deactivateLinkEnd} sau %{blockLinkStart}blocați%{blockLinkEnd} %{overageCount} %{overageCountUsers}. Pentru ajutor suplimentar, contactați %{licenseSupportLinkStart}asistența GitLab%{licenseSupportLinkEnd}."
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr "Licența dvs. postdatată a fost adăugată cu succes"
msgid "SuperSonics|Your subscription"
msgstr "Abonamentul d-voastră"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr "Abonamentul dvs. nu poate fi localizat"
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr "Detaliile abonamentului dvs. se vor sincroniza în scurt timp."
-msgid "SuperSonics|Your subscription is expired."
-msgstr "Abonamentul dvs. a expirat."
+msgid "SuperSonics|Your subscription is expired"
+msgstr "Abonamentul dvs. a expirat"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr "Abonamentul dvs. a fost activat cu succes. Puteți vedea detaliile de mai jos."
@@ -39946,6 +40654,9 @@ msgstr "Același executor partajat execută cod din mai multe proiecte, numai da
msgid "The scan has been created."
msgstr "Scanarea a fost creată."
+msgid "The secret is only available when you first create the application."
+msgstr "Secretul este accesibil numai atunci când creați prima dată aplicația."
+
msgid "The snippet can be accessed without any authentication."
msgstr "Fragmentul de cod poate fi accesat fără nicio autentificare."
@@ -39962,10 +40673,10 @@ msgid "The source project of this merge request has been removed."
msgstr "Proiectul sursă al acestui merge request a fost înlăturat."
msgid "The source topic and the target topic are identical."
-msgstr ""
+msgstr "Subiectul sursă și subiectul țintă sunt identice."
msgid "The source topic is not a topic."
-msgstr ""
+msgstr "Subiectul sursă nu este un subiect."
msgid "The specified tab is invalid, please select another"
msgstr "Fila specificată nu este validă, vă rugăm să selectați alta"
@@ -39980,7 +40691,7 @@ msgid "The tag name can't be changed for an existing release."
msgstr "Numele etichetei nu poate fi modificat pentru o versiune existentă."
msgid "The target topic is not a topic."
-msgstr ""
+msgstr "Subiectul țintă nu este un subiect."
msgid "The time period in seconds that the maximum requests per project limit applies to."
msgstr "Perioada de timp în secunde la care se aplică limita maximă de solicitări pe proiect."
@@ -40153,9 +40864,6 @@ msgstr "Nu există date disponibile."
msgid "There is no data available. Please change your selection."
msgstr "Nu există date disponibile. Vă rugăm să schimbați selecția."
-msgid "There is no seat left to activate the member"
-msgstr "Nu mai există niciun seat pentru a activa membrul"
-
msgid "There is no table data available."
msgstr "Nu există date de tabel disponibile."
@@ -40423,9 +41131,6 @@ msgstr "Acest model Cron nu este valid"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr "Această instanță GitLab nu oferă încă niciun executor partajat. Administratorii instanței pot înregistra executorii partajați în zona admin."
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr "Licența pentru această instanță GitLab este la nivelul %{insufficient_license}. Geo este disponibil numai pentru utilizatorii care au cel puțin o licență Premium."
-
msgid "This PDF is too large to display. Please download to view."
msgstr "Acest PDF este prea mare pentru a fi afișat. Vă rugăm să-l descărcați pentru a-l vizualiza."
@@ -40489,6 +41194,9 @@ msgstr "Acest bloc este autoreferențial"
msgid "This board's scope is reduced"
msgstr "Acest bord a fost restrâns în scop"
+msgid "This branch has diverged from upstream."
+msgstr "Această ramură a deviat din amonte."
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr "Această modificare va înlătura %{strongOpen}TOATE%{strongClose} caracteristicile Premium și Ultimate pentru %{strongOpen}TOȚI%{strongClose} clienții SaaS și va face ca testele să înceapă să eșueze."
@@ -40534,6 +41242,9 @@ msgstr "Această acreditare a expirat"
msgid "This deployment is not waiting for approvals."
msgstr "Această implementare nu este în așteptarea aprobărilor."
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "Acest job de implementare nu se execută automat și trebuie pornit manual, dar este mai vechi decât ultima implementare și, prin urmare, nu poate fi executat."
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr "Acest job de implementare nu se execută automat și trebuie pornit manual, dar nu aveți acces la mediul protejat al acestui job. Jobul poate fi inițiat numai de un membru al proiectului care are permisiunea de implementare în mediul respectiv."
@@ -40582,6 +41293,27 @@ msgstr "Canary ingress al acestui mediu a fost actualizat recent. Vă rugăm să
msgid "This epic already has the maximum number of child epics."
msgstr "Această epică are deja numărul maxim de epice copil."
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Această epică nu există sau nu aveți permisiunea suficientă."
@@ -40678,6 +41410,9 @@ msgstr "Acesta este numărul cel mai mare de utilizatori de pe instalația dvs.
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr "Acesta este numărul de %{billable_users_link_start}utilizatori facturabili%{link_end} de pe instalația dvs. și acesta este numărul minim pe care trebuie să-l achiziționați atunci când vă reînnoiți licența."
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr "Aceasta este singura dată când secretul este accesibil. Copiați secretul și păstrați-l în siguranță."
+
msgid "This is your current session"
msgstr "Aceasta este sesiunea dvs. curentă"
@@ -40894,6 +41629,9 @@ msgstr "Acest proiect este arhivat și nu poate fi comentat."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "Acest proiect este licențiat sub %{strong_start}%{license_name}%{strong_end}."
+msgid "This project is mirrored from %{link}."
+msgstr "Acest proiect este replicat din %{link}."
+
msgid "This project is not subscribed to any project pipelines."
msgstr "Acest proiect nu este abonat la niciun pipeline de proiecte."
@@ -40906,12 +41644,18 @@ msgstr "Acest proiect își gestionează dependențele folosind %{strong_start}%
msgid "This project path either does not exist or you do not have access."
msgstr "Această cale a proiectului fie nu există, fie nu aveți acces."
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr "Acest proiect a atins limita de domenii personalizate. (Max %d)"
+
msgid "This project will be deleted on %{date}"
msgstr "Acest proiect va fi șters pe %{date}"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr "Acest proiect va fi șters la %{date}, deoarece grupul său părinte „%{parent_group_name}†a fost programat pentru ștergere."
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr "Această versiune a fost creată cu o dată din trecut. Colectarea probelor la momentul lansării nu este disponibilă."
@@ -40999,6 +41743,9 @@ msgstr "Aceasta va elimina relația de fork dintre acest proiect și %{fork_sour
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr "Aceasta va elimina relația fork dintre acest proiect și alte proiecte din rețeaua fork."
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr "Nu se poate găsi subiectul la care să răspundeți"
@@ -41228,7 +41975,7 @@ msgid "Timeago|right now"
msgstr "chiar acum"
msgid "Timeline event added successfully."
-msgstr ""
+msgstr "Adăugarea evenimentului cronologic a reușit."
msgid "Timeline|Turn recent updates view off"
msgstr "Dezactivați afișarea actualizărilor recente"
@@ -41344,6 +42091,9 @@ msgstr "Pentru a vă activa perioada de încercare, avem nevoie de detalii supli
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr "Pentru a adăuga un sufix personalizat, configurați o adresă de e-mail Service Desk. %{linkStart}Aflați mai multe.%{linkEnd}"
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Pentru a adăuga un nume de afișare, setați o adresă de e-mail Service Desk. %{linkStart}Aflați mai multe.%{linkEnd}"
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Pentru a adăuga manual intrarea, furnizați următoarele detalii aplicației de pe telefon."
@@ -41377,6 +42127,9 @@ msgstr "Pentru a continua, trebuie să selectați linkul din e-mailul de confirm
msgid "To define internal users, first enable new users set to external"
msgstr "Pentru a defini utilizatorii interni, activați mai întâi setarea ca noii utilizatori să fie externi"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr "Pentru a activa Funcțiile de înregistrare, activați mai întâi Serviciul Ping."
@@ -41537,16 +42290,16 @@ msgid "Todos|Filter by project"
msgstr "Filtrați după proiect"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "Meritați să fiți felicitat!"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "Excelent! Se pare că nu mai aveți nimic în lista De-Făcut."
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
-msgstr ""
+msgstr "De acum înainte, veÈ›i fi cunoscut ca „Distrugătorul de sarcini De-Făcutâ€."
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "Nu-i așa că o listă De-Făcut este frumoasă?"
msgid "Todos|It's how you always know what to work on next."
msgstr "În acest fel știți totdeauna la ce să lucrați în continuare."
@@ -41558,7 +42311,7 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr "Nu aveți nimic pe lista lucrurilor de-făcut. Bine lucrat!"
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "Nu mai e nimic de făcut. Bate palma!"
msgid "Todos|Undo mark all as done"
msgstr "Anulați marcarea tuturor ca fiind făcute"
@@ -41596,9 +42349,6 @@ msgstr "Comutare la descrierea commit-ului"
msgid "Toggle commit list"
msgstr "Comutare la lista de commit-uri"
-msgid "Toggle dropdown"
-msgstr "Comutați lista verticală"
-
msgid "Toggle emoji award"
msgstr "Schimbați premiul emoji"
@@ -41620,9 +42370,6 @@ msgstr "Comutați comenzile rapide"
msgid "Toggle sidebar"
msgstr "Comutați bara laterală"
-msgid "Toggle the Draft status"
-msgstr "Comutați starea Draft"
-
msgid "Toggle the Performance Bar"
msgstr "Comutați bara de performanță"
@@ -41669,16 +42416,16 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr "S-au găsit prea mulți utilizatori. Acțiunile rapide sunt limitate la cel mult %{max_count} utilizatori"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "Explorați"
msgid "TopNav|Go back"
msgstr "ÃŽnapoi"
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "Comutați la"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "Tablourile dvs. de bord"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr "Îmbinarea subiectului %{source_topic} în subiectul %{target_topic} a reușit."
@@ -41717,7 +42464,7 @@ msgid "Topics"
msgstr "Subiecte"
msgid "Topics could not be merged!"
-msgstr ""
+msgstr "Subiectele nu au putut fi îmbinate!"
msgid "Total"
msgstr "Total"
@@ -41734,6 +42481,9 @@ msgstr "Mărimea totală a artefactelor: %{total_size}"
msgid "Total cores (CPUs)"
msgstr "Total nuclee (CPU)"
+msgid "Total issue weight"
+msgstr "Greutate totală a problemei"
+
msgid "Total memory (GB)"
msgstr "Memorie totală (GB)"
@@ -41863,9 +42613,6 @@ msgstr "Ziua %{daysUsed}/%{duration}"
msgid "Trials|Go back to GitLab"
msgstr "ÃŽnapoi la GitLab"
-msgid "Trials|Hey there"
-msgstr "Salut"
-
msgid "Trials|Skip Trial"
msgstr "Săriți perioada de încercare"
@@ -41881,6 +42628,12 @@ msgstr "Puteți aplica perioada de încercare unui grup nou sau unui grup existe
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr "Nu veÈ›i obÈ›ine o perioadă de încercare gratuită chiar acum, dar puteÈ›i relua oricând acest proces prin selectarea avatarului dvs. È™i alegerea „ÎncepeÈ›i o perioadă de încercare Ultimateâ€."
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] "V-a mai rămas %{daysRemaining} zi de GitLab %{planName}!"
+msgstr[1] "V-au mai rămas %{daysRemaining} zile de GitLab %{planName}!\n"
+msgstr[2] "V-au mai rămas %{daysRemaining} de zile de GitLab %{planName}!"
+
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 "Perioada dvs. de încercare se încheie la %{boldStart}%{trialEndDate}%{boldEnd}. Sperăm că vă bucurați de caracteristicile GitLab %{planName}. Pentru a păstra aceste caracteristici după ce se termină perioada de încercare, va trebui să cumpărați un abonament. (De asemenea, puteți alege GitLab Premium, dacă vă satisface nevoile)."
@@ -42562,6 +43315,9 @@ msgstr "%{linkTitle} link de ajutor"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft} din stocarea achiziționată este disponibilă"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr "%{storage_limit_link_start}O limită de stocare a spațiului de nume%{link_end} va fi în curând impusă pentru spațiul de nume %{strong_start}%{namespace_name}%{strong_end}. %{extra_message}"
+
msgid "UsageQuota|Artifacts"
msgstr "Artefacte"
@@ -42604,12 +43360,12 @@ msgstr "Utilizarea în perioada curentă"
msgid "UsageQuota|Dependency proxy"
msgstr "Proxy de dependență"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr "Începând cu %{storage_enforcement_date}, limitele de stocare a spațiului de nume se vor aplica spațiului de nume %{strong_start}%{namespace_name}%{strong_end}. %{extra_message}Vizualizați %{rollout_link_start}programul de implementare pentru această modificare%{link_end}."
-
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "Fișiere atașate și elemente grafice de design mai mici."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr "Pentru mai multe informații despre limitele de stocare, consultați %{faq_link_start}Întrebări frecvente%{link_end}."
+
msgid "UsageQuota|Git repository."
msgstr "Repozitoriul Git."
@@ -42682,9 +43438,6 @@ msgstr "Repozitoriu"
msgid "UsageQuota|Seats"
msgstr "Seat-uri"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr "Consultați pagina noastră %{faq_link_start}FAQ%{link_end} pentru mai multe informații."
-
msgid "UsageQuota|Shared bits of code and text."
msgstr "Fragmente de cod și de text partajate."
@@ -42718,8 +43471,8 @@ msgstr "Grupul %{strong_start}%{context_name}%{strong_end} va fi afectat de aces
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr "Proiectul %{strong_start}%{context_name}%{strong_end} va fi afectat de acest lucru. "
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
-msgstr "Spațiul de nume utilizează în prezent %{strong_start}%{used_storage}%{strong_end} de spațiu de stocare al spațiului de nume. Proprietarii de grupuri pot vizualiza utilizarea spațiului de stocare al spațiului de nume și pot achiziționa mai mult din %{strong_start}%{usage_quotas_nav_instruction}%{strong_end} %{docs_link_start}Aflați mai multe%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr "Spațiul de nume utilizează în prezent %{strong_start}%{used_storage}%{strong_end} de stocare a spațiului de nume. Proprietarii de grup pot vizualiza utilizarea stocării spațiului de nume și pot achiziționa mai mult de la %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Cum îmi pot gestiona spațiul de stocare?%{link_end}"
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
msgstr "Spațiul de nume utilizează în prezent %{strong_start}%{used_storage}%{strong_end} de spațiul de stocare al spațiului de nume. Vizualizați și gestionați utilizarea din %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Aflați mai multe%{link_end} despre cum să reduceți spațiul de stocare"
@@ -43060,6 +43813,9 @@ msgstr "Identitatea utilizatorului a fost înlăturată cu succes."
msgid "User identity was successfully updated."
msgstr "Identitatea utilizatorului a fost actualizată cu succes."
+msgid "User is blocked"
+msgstr "Utilizatorul este blocat"
+
msgid "User is not allowed to resolve thread"
msgstr "Utilizatorul nu are voie să rezolve subiectul"
@@ -43355,7 +44111,7 @@ msgid "Users can launch a development environment from a GitLab browser tab when
msgstr "Utilizatorii pot lansa un mediu de dezvoltare dintr-o filă de browser GitLab atunci când este activată integrarea %{linkStart}Gitpod%{linkEnd}"
msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Utilizatorii își pot reactiva conturile conectându-se. %{link_start}Aflați mai multe.%{link_end}"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
msgstr "Utilizatorii pot reda diagrame în documente AsciiDoc, Markdown, reStructuredText, și Textile utilizând Kroki."
@@ -43381,9 +44137,6 @@ msgstr "Utilizatorii care solicită acces la"
msgid "Users to exclude from the rate limit"
msgstr "Utilizatori de exclus de la limita de rată"
-msgid "Users were successfully added."
-msgstr "Utilizatorii au fost adăugați cu succes."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "Utilizatorii cu rol de Invitat sau cei care nu aparțin unui Proiect sau Grup nu vor utiliza un seat din licența dumneavoastră."
@@ -43402,8 +44155,35 @@ msgstr "Niciun responsabil - %{openingTag} atribuiați-vă %{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr "Neatribuit"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr "Folosiți GitLab ca o alternativă ușoară la Sentry."
+msgid "User|Data Analyst"
+msgstr "Analist de date"
+
+msgid "User|Development Team Lead"
+msgstr "Șef de echipă"
+
+msgid "User|Devops Engineer"
+msgstr "Inginer de dezvoltare"
+
+msgid "User|Other"
+msgstr "Altele"
+
+msgid "User|Product Designer"
+msgstr "Designer de produs"
+
+msgid "User|Product Manager"
+msgstr "Manager de produs"
+
+msgid "User|Security Analyst"
+msgstr "Analist de securitate"
+
+msgid "User|Software Developer"
+msgstr "Dezvoltator de software"
+
+msgid "User|Systems Administrator"
+msgstr "Administrator de sisteme"
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr "Folosiți GitLab ca o alternativă la Sentry."
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "Folosirea %{code_start}::%{code_end} indică un %{link_start}set de etichete cu scop%{link_end}"
@@ -43649,13 +44429,13 @@ msgid "View all environments."
msgstr "Vizualizați toate mediile."
msgid "View all groups"
-msgstr ""
+msgstr "Afișați toate grupurile"
msgid "View all issues"
msgstr "Vizualizați toate problemele"
msgid "View all projects"
-msgstr ""
+msgstr "Afișați toate proiectele"
msgid "View blame"
msgstr "Vizualizați blame"
@@ -43663,6 +44443,9 @@ msgstr "Vizualizați blame"
msgid "View blame prior to this change"
msgstr "Consultați blame înainte de această modificare"
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Vizualizați graficul"
@@ -43687,8 +44470,8 @@ msgstr "Vizualizați documentația"
msgid "View eligible approvers"
msgstr "Vizualizați aprobatorii eligibili"
-msgid "View epics list"
-msgstr "Vizualizați lista de epice"
+msgid "View entire blame"
+msgstr "Vizualizați întregul blame"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -44113,6 +44896,9 @@ msgstr "Fals pozitiv detectat"
msgid "Vulnerability|File"
msgstr "Fișier"
+msgid "Vulnerability|File:"
+msgstr "Fișier:"
+
msgid "Vulnerability|GitLab Security Report"
msgstr "Raport de securitate GitLab"
@@ -44134,12 +44920,12 @@ msgstr "Imagine"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr "Informații referitoare la modul în care a fost descoperită vulnerabilitatea și la impactul acesteia asupra sistemului."
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr "Aflați mai multe despre această vulnerabilitate și modalitatea cea mai bună de a o rezolva."
-
msgid "Vulnerability|Links"
msgstr "Linkuri"
+msgid "Vulnerability|Location"
+msgstr "Locația"
+
msgid "Vulnerability|Method"
msgstr "Metoda"
@@ -44149,6 +44935,9 @@ msgstr "Spațiu de nume"
msgid "Vulnerability|Project"
msgstr "Proiect"
+msgid "Vulnerability|Project:"
+msgstr "Proiect:"
+
msgid "Vulnerability|Remove identifier row"
msgstr "Înlăturați rândul identificatorului"
@@ -44176,6 +44965,9 @@ msgstr "SetaÈ›i statusul detectării vulnerabilității în funcÈ›ie de informaÈ
msgid "Vulnerability|Severity"
msgstr "Severitate"
+msgid "Vulnerability|Severity:"
+msgstr "Severitate:"
+
msgid "Vulnerability|Status"
msgstr "Status"
@@ -44188,6 +44980,9 @@ msgstr "Răspunsul nemodificat este răspunsul original care nu a suferit nicio
msgid "Vulnerability|Tool"
msgstr "Instrument"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr "Formare"
@@ -44200,6 +44995,9 @@ msgstr "Răspuns nemodificat"
msgid "Vulnerability|View training"
msgstr "Vizualizați formarea"
+msgid "WARNING:"
+msgstr "AVERTISMENT:"
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr "AVERTISMENT: Acest fragment de cod conține fișiere ascunse care pot fi folosite pentru a masca un comportament rău intenționat. Fiți precauți la clonarea și executarea codului din acest fragment de cod."
@@ -44263,6 +45061,12 @@ msgstr "Nu am putut ajunge la serverul Prometheus. Fie serverul nu mai există,
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr "Am creat un proiect sandbox care vă va ajuta să învățați elementele de bază ale GitLab. Veți fi ghidat prin probleme într-un tablou de probleme. Puteți parcurge problemele în propriul ritm."
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr "Am detectat o tentativă de conectare la contul dvs. %{host} folosind un cod de autentificare cu doi factori greșit"
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr "Am detectat o tentativă de conectare la contul dvs. %{host} folosind un cod de autentificare cu doi factori greșit, de la următoarea adresă IP: %{ip}, la %{time}."
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Am detectat un spam potențial în %{humanized_resource_name}. Vă rugăm să rezolvați reCAPTCHA pentru a continua."
@@ -44473,6 +45277,9 @@ msgstr "Ștergeți webhook-ul"
msgid "Webhooks|Deployment events"
msgstr "Evenimente de desfășurare"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "Activați verificarea SSL"
@@ -44488,12 +45295,18 @@ msgstr "Evenimentele Feature Flag"
msgid "Webhooks|Go to webhooks"
msgstr "Mergeți la webhook-uri"
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "Evenimente de probleme"
msgid "Webhooks|Job events"
msgstr "Evenimente de job"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "Evenimente de membri"
@@ -44518,6 +45331,12 @@ msgstr "Verificarea SSL"
msgid "Webhooks|Secret token"
msgstr "Token secret"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "Evenimente de subgrup"
@@ -44542,6 +45361,9 @@ msgstr "URL"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr "URL-ul trebuie să fie codificat-procentual atunci când conține unul sau mai multe caractere speciale."
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr "Utilizat pentru a valida payload-urile primite. Trimis împreună cu cererea în antetul %{code_start}X-Gitlab-Token HTTP%{code_end}."
@@ -44722,12 +45544,6 @@ msgstr "De ce vă înscrieți? (opțional)"
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr "Text îmbogățit"
-
-msgid "Wiki Page|Source"
-msgstr "Sursa"
-
msgid "Wiki page"
msgstr "Pagina Wiki"
@@ -44962,6 +45778,12 @@ msgstr "Adăugare responsabil"
msgid "WorkItem|Add assignees"
msgstr "Adăugare responsabili"
+msgid "WorkItem|Add due date"
+msgstr "Adăugați data de scadență"
+
+msgid "WorkItem|Add start date"
+msgstr "Adăugați data de început"
+
msgid "WorkItem|Add task"
msgstr "Adăugați sarcina"
@@ -44995,9 +45817,15 @@ msgstr "Creați o sarcină"
msgid "WorkItem|Create work item"
msgstr "Creați elementul de lucru"
+msgid "WorkItem|Dates"
+msgstr "Date"
+
msgid "WorkItem|Delete %{workItemType}"
msgstr "Ștergeți %{workItemType}"
+msgid "WorkItem|Due date"
+msgstr "Data scadenței"
+
msgid "WorkItem|Expand tasks"
msgstr "Extindeți sarcinile"
@@ -45064,6 +45892,9 @@ msgstr "Ceva nu a mers bine în timp ce se actualiza %{workItemType}. Vă rugăm
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr "Ceva nu a mers bine în timp ce se actualiza elementul de lucru. Vă rugăm să încercați din nou."
+msgid "WorkItem|Start date"
+msgstr "Data de început"
+
msgid "WorkItem|Task"
msgstr "Sarcină"
@@ -45328,6 +46159,12 @@ msgstr "Îl puteți verifica în setările %{pat_link_start}tokenurilor de acces
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr "Îl puteți verifica în setările tokenurilor de acces personale %{pat_link}."
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr "Vă puteți verifica tokenurile sau puteți crea unul nou în %{pat_link_start}setările pentru tokenurile de acces personale%{pat_link_end}."
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr "Vă puteți verifica tokenurile sau puteți crea unul nou în setările pentru tokenurile de acces personale %{pat_link}."
+
msgid "You can create a new %{link}."
msgstr "Puteți crea un nou %{link}."
@@ -45451,6 +46288,9 @@ msgstr "Nu puteți %{action} utilizatorii %{state}."
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Nu puteți accesa fișierul brut. Vă rugăm să așteptați un minut."
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr "Nu mai puteți adăuga alte epice. Această epică are deja numărul maxim de epice copil."
+
msgid "You cannot approve your own deployment."
msgstr "Nu puteți aproba propria implementare."
@@ -45652,8 +46492,8 @@ msgstr "Ați configurat 2FA pentru contul dvs.! Dacă pierdeți accesul la dispo
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr "Ați cumpărat cu succes %{product}. Veți primi o chitanță prin e-mail. Achiziția dvs. poate dura un minut pentru a se sincroniza, așa că reîmprospătați pagina dacă nu o vedeți încă."
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
-msgstr "Ați achiziționat cu succes un abonament %{plan} pentru %{seats}. Factura o veți primi prin e-mail. S-ar putea să dureze un moment până când GitLab.com va reflecta complet achiziția dvs."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr "Achiziționarea abonamentului la planul %{plan} pentru %{seats} s-a efectuat. Veți primi o chitanță prin e-mail. Sincronizarea achiziției poate dura un minut, așa că reîmprospătați pagina dacă nu o vedeți încă."
msgid "You have unsaved changes"
msgstr "Aveți modificări nesalvate"
@@ -45670,8 +46510,8 @@ msgstr "Trebuie să fiți autentificat pentru a accesa această cale."
msgid "You must be logged in to search across all of GitLab"
msgstr "Trebuie să fiți autentificat pentru a căuta peste tot în GitLab"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
-msgstr "Trebuie să aveți permisiuni de dezvoltator sau mai mari în proiectul asociat pentru a vizualiza jurnalele de joburi atunci când este activată urmărirea de depanare. Pentru a dezactiva urmărirea de depanare, setați variabila „CI_DEBUG_TRACE†la „false†în configurația pipeline-ului sau în setările CI/CD. Dacă aveți nevoie să vizualizați acest jurnal de joburi, un întreținător de proiect trebuie să vă adauge la proiect cu permisiuni de dezvoltator sau mai mari."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
+msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr "Trebuie să aveți acces de întreținător pentru a forța ștergerea unui blocaj."
@@ -46106,7 +46946,7 @@ msgid "Your profile"
msgstr "Profilul d-voastră"
msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
-msgstr ""
+msgstr "Proiectul dvs. nu mai primește beneficii GitLab Ultimate începând cu 2022-07-01. După cum a fost notificat în aplicație anterior, proiectele publice cu sursă deschisă de pe nivelul Gratuit se pot aplica la programul GitLab for Open Source pentru a primi beneficiile GitLab Ultimate. Consultați %{faq_link_start}FAQ%{link_end} pentru mai multe detalii."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr "Limita proiectelor dvs. este de %{limit} (de) proiecte! Vă rugăm să contactați administratorul dvs. pentru a o mări"
@@ -46261,6 +47101,9 @@ msgstr "adăugat(ă)"
msgid "added %{emails}"
msgstr "adăugat %{emails}"
+msgid "added a %{link_type} link"
+msgstr "a adăugat un link %{link_type}"
+
msgid "added a Zoom call to this issue"
msgstr "a adăugat un apel Zoom la această problemă"
@@ -46357,6 +47200,9 @@ msgstr "de"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr "poate conÈ›ine numai litere din alfabetul Base64 (RFC4648), la care se adaugă „@â€, „:†și „.â€."
@@ -46402,6 +47248,9 @@ msgstr "nu se poate atribui un element de lucru neconfidențial unui părinte co
msgid "cannot be a date in the past"
msgstr "nu poate fi o dată în trecut"
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "nu se poate modifica"
@@ -46412,7 +47261,7 @@ msgid "cannot be changed if shared runners are enabled"
msgstr "nu se poate modifica dacă executorii partajați sunt activați"
msgid "cannot be changed since member is associated with a custom role"
-msgstr ""
+msgstr "nu se poate modifica, deoarece membrul este asociat cu un rol personalizat"
msgid "cannot be enabled"
msgstr "nu se poate activa"
@@ -46666,6 +47515,9 @@ msgstr "S-a(u) găsit %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr "Raportul complet"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr "Scanarea IaC"
@@ -46825,6 +47677,9 @@ msgstr "colectează informații de utilizare"
msgid "comment"
msgstr "comentariu"
+msgid "commented"
+msgstr "comentat"
+
msgid "commented on %{link_to_project}"
msgstr "a comentat pe %{link_to_project}"
@@ -46870,6 +47725,9 @@ msgstr "creat(ă) %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "creat(ă) %{timeAgo} de %{author}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr "creat %{timeAgo} de %{author} în %{project_link}"
+
msgid "created by"
msgstr "creat(ă) de"
@@ -47197,9 +48055,6 @@ msgstr "nu este permis, deoarece grupul nu este un grup de nivel superior."
msgid "is not allowed. Please use your regular email address."
msgstr "nu este permisă. Vă rugăm să folosiți adresa dvs. obișnuită de e-mail."
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr "nu este permis. În prezent nu acceptăm iterații la nivel de proiect"
-
msgid "is not in the group enforcing Group Managed Account"
msgstr "nu face parte din grupul care impune Contul gestionat de grup"
@@ -47290,6 +48145,12 @@ msgstr "obiecte lfs"
msgid "limit of %{project_limit} reached"
msgstr "limita de %{project_limit} a fost atinsă"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "linie"
+msgstr[1] "linii"
+msgstr[2] "de linii"
+
msgid "load it anyway"
msgstr "încărcați-l oricum"
@@ -47329,6 +48190,9 @@ msgstr "(squashing-ul commit-urilor s-a efectuat)"
msgid "metric_id must be unique across a project"
msgstr "metric_id trebuie să fie unic în cadrul unui proiect"
+msgid "milestone should belong either to a project or a group."
+msgstr "obiectivul trebuie să aparțină fie unui proiect, fie unui grup."
+
msgid "missing"
msgstr "lipsește"
@@ -47698,6 +48562,9 @@ msgstr "trebuie să aibă un repozitoriu"
msgid "must match %{association}.project_id"
msgstr "trebuie să corespundă cu %{association}.project_id"
+msgid "must not contain commonly used combinations of words and letters"
+msgstr "nu trebuie să conțină combinații de cuvinte și litere utilizate în mod obișnuit"
+
msgid "my-awesome-group"
msgstr "grupul-meu-formidabil"
@@ -47779,9 +48646,6 @@ msgstr "sau"
msgid "organizations can only be added to root groups"
msgstr "organizațiile pot fi adăugate numai la grupurile rădăcină"
-msgid "other card matches"
-msgstr "alte potriviri de card"
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "din %d test total"
@@ -47929,6 +48793,9 @@ msgstr "înlăturați greutatea"
msgid "removed"
msgstr "înlăturat"
+msgid "removed a %{link_type} link"
+msgstr "a înlăturat un link %{link_type}"
+
msgid "removed a Zoom call from this issue"
msgstr "a înlăturat un apel Zoom din această problemă"
@@ -47962,6 +48829,12 @@ msgstr "scan-execution-policy: politica nu s-a aplicat, fișierul %{policy_path}
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr "scan-execution-policy: politica nu s-a aplicat, fișierul %{policy_path} lipsește"
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "seat"
+msgstr[1] "seat-uri"
+msgstr[2] "de seat-uri"
+
msgid "security Reports|There was an error creating the merge request"
msgstr "A apărut o eroare la crearea merge request-ului"
@@ -48070,6 +48943,9 @@ msgstr "Șablonul este gata! Acum îl puteți comite pentru a crea primul dvs. p
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr "Adăugăm un fișier de configurare GitLab CI pentru a adăuga un pipeline la proiect. Ați putea să-l creați manual, dar vă recomandăm să începeți cu un șablon GitLab care funcționează din start."
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "numele etichetei"
@@ -48136,6 +49012,12 @@ msgstr "s-a actualizat %{time_ago}"
msgid "uploads"
msgstr "încărcări"
+msgid "user"
+msgid_plural "users"
+msgstr[0] "utilizator"
+msgstr[1] "utilizatori"
+msgstr[2] "de utilizatori"
+
msgid "user avatar"
msgstr "avatar utilizator"
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index cc42983a61c..a34471e3e34 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d утверждающий"
@@ -1210,13 +1217,6 @@ msgstr "%{spanStart}в%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} по %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] "%{strong_start}%{count} учаÑтника%{strong_end} должны
msgstr[2] "%{strong_start}%{count} учаÑтников%{strong_end} должны одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
msgstr[3] "%{strong_start}%{count} учаÑтников%{strong_end} должны одобрить ÑлиÑние. Одобрить может кто угодно Ñ Ñ€Ð¾Ð»ÑŒÑŽ Developer или выше."
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr "%{template_project_id}' неизвеÑтен или недейÑтвит
msgid "%{text} is available"
msgstr "%{text} доÑтупен"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} должен принадлежать проекту или группе"
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} не поддерживает диаграммы ÑгораниÑ"
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,12 +1364,15 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Ñтраница Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %{user_name}"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} изменил ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡ÐµÑ€Ð½Ð¾Ð²Ð¸ÐºÐ° запроÑа на ÑлиÑние %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} запрашивает Ð´Ð»Ñ ÑÐµÐ±Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½ÑƒÑŽ запиÑÑŒ GitLab на вашем ÑкземплÑре %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "аватар %{username}"
@@ -1384,6 +1394,12 @@ msgstr "%{value} Ñ"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} потраченного времени."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} позволÑÑŽÑ‚ отправлÑÑ‚ÑŒ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÐ±-приложениÑм в ответ на ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð² группе или проекте."
@@ -1925,9 +1941,6 @@ msgstr "Ðовый релиз %{tag} Ð´Ð»Ñ %{name} опубликован. По
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "Был Ñоздан новый токен заимÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð°Ð²."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Сайт на проÑтом HTML иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ же пользуетÑÑ Ð²Ñеми другими замечательными возможноÑÑ‚Ñми GitLab"
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Добавить триггер"
-msgid "Add user(s) to the group:"
-msgstr "Добавить пользовател(Ñ/ей) в группу:"
-
-msgid "Add users to group"
-msgstr "Добавить пользователей в группу"
-
msgid "Add variable"
msgstr "Добавить переменную"
@@ -3026,9 +3042,15 @@ msgstr "Токен канала"
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "Я прочёл и принимаю %{link_start}УÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ð±ÑлуживаниÑ%{link_end} (PDF) Let's Encrypt."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
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}, еÑли не указано на уровне группы или ÑкземплÑра. Ðе влиÑет на ÑущеÑтвующие репозитории."
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "СохранÑÑ‚ÑŒ поÑледние артефакты Ð´Ð»Ñ Ð²Ñех заданий в поÑледних уÑпешных Ñборочных линиÑÑ…"
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "Защищать переменные CI/CD по умолчанию"
@@ -3149,9 +3180,21 @@ msgstr "Задайте шаблон CI/CD в качеÑтве обÑзатель
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr "Задайте макÑимальный размер GitLab Pages на проект (0 — без ограничений). %{link_start}Подробнее.%{link_end}"
@@ -3338,6 +3381,9 @@ msgstr "Заблокированные"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Блокировка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð¼ÐµÐµÑ‚ Ñледующие Ñффекты:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr "РаÑширенные параметры ÑкÑпорта"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "ТребуетÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ Ð¸Ð½Ð´ÐµÐºÑациÑ"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "ПоÑле уÑпешного Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ñ‹ будете перенаправлены на Ñкран входа в ÑиÑтему."
@@ -4106,6 +4164,9 @@ msgstr "Ð’Ñе завиÑимоÑти запроÑа на ÑлиÑние былÐ
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Ð’Ñе проекты"
@@ -4181,6 +4242,9 @@ msgstr "Разрешить Ñтому ключу выполнÑÑ‚ÑŒ push в да
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Разрешить пользователÑм закрыть Ñообщение"
@@ -4469,9 +4533,6 @@ msgstr "Произошла ошибка при загрузке раздела Ñ
msgid "An error occurred while loading all the files."
msgstr "Произошла ошибка при загрузке вÑех файлов."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Произошла ошибка при загрузке данных диаграммы"
@@ -4719,6 +4780,9 @@ msgstr "Произошла неизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°."
msgid "Analytics"
msgstr "Ðналитика"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Ðнализируйте ваши завиÑимоÑти на предмет извеÑтных уÑзвимоÑтей."
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] "Прикрепить %d файлов"
msgid "Attaching the file failed."
msgstr "Ðе удалоÑÑŒ прикрепить файл."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Ðудит Ñобытий"
@@ -6278,6 +6348,9 @@ msgstr "Ðиже приведены наÑтройки Ð´Ð»Ñ %{link_to_gitlab_p
msgid "Below you will find all the groups that are public."
msgstr "Ðиже показаны вÑе открытые группы."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr "Двухнедельное покрытие кода"
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr "Введите минимум три Ñимвола Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка."
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr "Переключить подробноÑти о меÑтах"
msgid "Billing|Type %{username} to confirm"
msgstr "Введите %{username} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ"
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr "Пользователь был уÑпешно удалён"
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr "Ветка не загружена - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr "Параметры автоматичеÑкого DevOps по умолч
msgid "CICD|Deployment strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ð¸Ñ Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "ЗаданиÑ"
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr "ИзменÑет название на \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² заголовке не были Ñохранены"
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr "Коммитов в"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "Произошла ошибка при получении данных запроÑа на ÑлиÑниÑ."
@@ -9972,6 +10135,9 @@ msgstr "Завершено"
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr "РееÑÑ‚Ñ€ контейнеров"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Сканирование контейнеров"
@@ -10821,15 +10990,15 @@ msgstr "УчаÑтники"
msgid "Control emails linked to your account"
msgstr "Управление адреÑами Ñлектронной почты, ÑвÑзанными Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑью"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr ""
+
msgid "Control how the GitLab Package Registry functions."
msgstr "УправлÑйте работой РееÑтра пакетов GitLab."
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
-msgid "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."
-msgstr ""
-
msgid "Cookie domain"
msgstr ""
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Покрытие"
@@ -11367,6 +11539,9 @@ msgstr "Создать тему"
msgid "Create user"
msgstr "Создать пользователÑ"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Создать шаблон: %{searchTerm}"
@@ -11379,6 +11554,12 @@ msgstr "Создать группу"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на Ñоздание подгруппы в Ñтой группе."
@@ -12638,6 +12819,12 @@ msgstr "Диапазон дат ограничен %{number} днÑми"
msgid "Date range must be shorter than %{max_range} days."
msgstr "Диапазон дат должен быть короче %{max_range} дней."
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "День меÑÑца"
@@ -12824,6 +13011,9 @@ msgstr "Удалить аккаунт"
msgid "Delete artifacts"
msgstr "Удалить артефакты"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr "Удалено"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Удалённый никнейм чата: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr "Удаленные проекты не могут воÑÑтановлены!"
@@ -13319,6 +13512,9 @@ msgstr "ДоÑтуп только на чтение"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Ðктивные токены Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "Разрешает чтение и запиÑÑŒ в рееÑÑ‚Ñ€ пакетов."
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "ИÑтекает"
@@ -13385,6 +13584,9 @@ msgstr "Отозвать %{name}"
msgid "DeployTokens|Scopes"
msgstr "ОблаÑти"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "%{entity_type} не имеет токенов развертываниÑ."
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr "уÑпешно"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите отменить Ñоздание Ñтого комментариÑ?"
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "Отменить подтверждение комментариÑ"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr "Отменить вÑе"
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ð° не ÑущеÑтвует. ВмеÑто неё показана поÑледнÑÑ Ð²ÐµÑ€ÑиÑ"
@@ -14285,6 +14475,18 @@ msgstr "Домен"
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr "Изменить wiki Ñтраницу"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Редактировать Ñвой поÑледний комментарий в теме (в пуÑтом текÑтовом поле)"
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr "ÐдреÑа Ñл. почты"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr "Развертывание"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr "Еще нет развертываний"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Обратите внимание, что Ñто дейÑтвие оÑтановит окружение, но %{emphasisStart}не%{emphasisEnd} повлиÑет на уже запущенные фазы развёртываниÑ, в Ñлучае еÑли в файле %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} не определено дейÑтвие \"оÑтановка окружениÑ\"."
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr "Откатить окружение %{name}?"
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Показать вÑе"
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr "Ðайдены ошибки в вашем .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðе удалоÑÑŒ"
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Загрузка целей"
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr "Без даты начала и окончаниÑ"
@@ -18976,6 +19229,9 @@ msgstr "Чтобы проÑмотреть план развитиÑ, добавÑ
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Чтобы раÑширить поиÑк, измените или удалите фильтры; Ñ %{startDate} до %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr "РуководÑтво"
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr "ЕÑли вы потерÑете Ñвои коды воÑÑтановлÐ
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "Заблокирован URL импорта: %{message}"
@@ -20497,6 +20813,9 @@ msgstr "Ðе удалоÑÑŒ запроÑить %{provider} репозиториÐ
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "Удаленные данные не могут быть импортированы."
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон интервала"
-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 ""
@@ -22294,6 +22625,12 @@ msgstr "ИÑпользует лицензионное меÑто:"
msgid "Is using seat"
msgstr "ИÑпользует меÑто"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr "ПоÑледний вход:"
msgid "Last successful update"
msgstr "ПоÑледнее уÑпешное обновление"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr "Узнайте, как %{no_packages_link_start}опубликовать
msgid "Learn more"
msgstr "Подробнее"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr "Сделайте вÑех в Ñвоей команде более про
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,12 +24895,12 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr "Управление двухфакторной аутентификацией"
-msgid "Manage your license"
-msgstr "УправлÑйте Ñвоей лицензией"
-
msgid "Manage your project's triggers"
msgstr ""
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr "ÐаÑтройки Ð·ÐµÑ€ÐºÐ°Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾Ñтупны толÑ
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Отзеркаленные репозитории"
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr "Ðазвать новую метку"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Ðаименование:"
@@ -26547,6 +26914,9 @@ msgstr "Ðовое РаÑпиÑание Сборочной Линии"
msgid "New Project"
msgstr "Ðовый проект"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr "ОК"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Окт."
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Удалить верÑию пакета"
msgid "PackageRegistry|Delete package"
msgstr "Удалить пакет"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Узнайте, как %{noPackagesLinkStart}публиковать и делитьÑÑ Ñвоими пакетами%{noPackagesLinkEnd} в GitLab."
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr "РееÑÑ‚Ñ€ пакетов"
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr "ПриоÑтановить"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr "Ðктивно"
msgid "PipelineSchedules|All"
msgstr "Ð’Ñе"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Ðеактивно"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Следующий запуÑк"
@@ -29380,15 +29894,27 @@ msgstr "ОтÑутÑтвует"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "ПредоÑтавьте краткое опиÑание Ñтой Ñборочной линии"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Стать владельцем"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Цель"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Переменные"
@@ -29503,6 +30029,12 @@ msgstr "ÐаÑтройки Ñборочных линий Ð´Ð»Ñ '%{project_name}
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr "ПожалуйÑта, введите %{phrase_code} чтобы продÐ
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "ПожалуйÑта, иÑпользуйте Ñту форму Ð´Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтраторов о пользователÑÑ…, Ñоздающих задачи и комментарии, Ñодержащие Ñпам или ведущих ÑÐµÐ±Ñ Ð½ÐµÐ°Ð´ÐµÐºÐ²Ð°Ñ‚Ð½Ð¾."
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "ПожалуйÑта, подождите, Ñта Ñтраница автоматичеÑки обновитÑÑ, когда вÑÑ‘ будет готово."
@@ -30193,6 +30728,9 @@ msgstr "ПожалуйÑта, подождите, пока мы не подклÑ
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "ПожалуйÑта, подождите пока мы импортируем к ваш репозиторий. ОбновлÑйте Ñтраницу по желанию."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "ИÑпользуемые поды"
@@ -30253,6 +30791,9 @@ msgstr "ПредпочтениÑ"
msgid "Preferences saved."
msgstr "ÐаÑтройки Ñохранены."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Поведение"
@@ -30364,6 +30905,9 @@ msgstr "ÐаÑтройки времени"
msgid "Preferences|Use relative times"
msgstr "ИÑпользовать отноÑительное времÑ"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr "ÐктивноÑÑ‚ÑŒ"
msgid "Profiles|Add key"
msgstr "Добавить ключ"
-msgid "Profiles|Add status emoji"
-msgstr "Добавить Ñмайл к ÑтатуÑу"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr "Обрезать аватар"
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "О Ñебе"
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr "Изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "Город, Ñтрана"
-msgid "Profiles|Clear status"
-msgstr "ОчиÑтить ÑтатуÑ"
-
msgid "Profiles|Commit email"
msgstr "Email коммита"
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Подключенные аккаунты"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Текущий путь: %{path}"
@@ -30868,9 +31403,6 @@ msgstr "ИÑпользовать Ñмайлы в имени - веÑьма крÐ
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "Как у Ð²Ð°Ñ Ð´ÐµÐ»Ð°?"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr "Ваше Ð¸Ð¼Ñ Ð±Ñ‹Ð»Ð¾ автоматичеÑки уÑтановлен
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Ваш ÑтатуÑ"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr "Выберите методы ÑлиÑниÑ, наÑтройки, про
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "ÐаÑтройка реÑурÑов проекта и мониторинг их здоровьÑ."
@@ -31438,6 +31970,9 @@ msgstr "Разрешить цепочки ÑлиÑний"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr "Включить Ñборочные линии Ð´Ð»Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¾Ð² ÑлиÑний"
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr "ПоощрÑÑ‚ÑŒ"
@@ -31561,12 +32096,18 @@ msgstr "ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑлиÑнию"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr "Коммиты ÑлиÑÐ½Ð¸Ñ Ð½Ðµ ÑоздаютÑÑ."
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Только подпиÑанные коммиты могут быть отправлены в Ñтот репозиторий."
@@ -31603,6 +32144,9 @@ msgstr "ВидимоÑÑ‚ÑŒ проекта"
msgid "ProjectSettings|Public"
msgstr "ПубличнаÑ"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Репозиторий"
@@ -31756,7 +32300,7 @@ msgstr "При возникновении конфликтов ÑлиÑÐ½Ð¸Ñ Ð¿
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr "Отправка разрешена"
msgid "ProtectedBranch|Allowed to push:"
msgstr "Отправка разрешена:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Ветка"
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr "Получить"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr "Подробнее"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr "ЗарегиÑтрируйте универÑальное двухфак
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr "Зеркалирование репозиториÑ"
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr "Выбрать формат архива"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Выбор временной зоны"
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr "УÑтановить приоритет"
msgid "Set weight to %{weight}."
msgstr "УÑтановить приоритет на %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "ОчиÑтить ÑтатуÑ"
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Изменить ÑтатуÑ"
@@ -36868,6 +37499,9 @@ msgstr "Изменить ÑтатуÑ"
msgid "SetStatusModal|Set status"
msgstr "Изменить ÑтатуÑ"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Извините, мы не Ñмогли изменить ваш ÑтатуÑ. ПожалуйÑта, попробуйте позже."
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr "По поÑледнему контакту"
msgid "SortOptions|Last created"
msgstr "Сначала недавно Ñозданные"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Ðаименее популÑрный"
@@ -37881,6 +38557,9 @@ msgstr "Сначала давно избранные"
msgid "SortOptions|Oldest updated"
msgstr "Сначала давно обновлённые"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "ПопулÑронÑÑ‚ÑŒ"
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr "Ðктивировать подпиÑку"
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr "ДоÑтуп к Ñниппету можно получить без какой-либо аутентификации."
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "Ðет доÑтупных данных. ПожалуйÑта, измените ваш выбор."
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr "Этот ÑкземплÑÑ€ GitLab лицензирован на уровне %{insufficient_license}. Geo доÑтупен только тем пользователÑм, у которых еÑÑ‚ÑŒ по крайней мере Premium-лицензиÑ."
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr "Эта цель уже имеет макÑимально возможное количеÑтво дочерних целей."
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Этой цели не ÑущеÑтвует, или у Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно прав."
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Это ваша Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ ÑеÑÑиÑ"
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Чтобы добавить запиÑÑŒ вручную, предоÑтавьте Ñледующую информацию в приложении на Ñвоем телефоне."
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr "Переключить опиÑание коммита"
msgid "Toggle commit list"
msgstr "Открыть или закрыть ÑпиÑок коммитов"
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Переключить боковую панель"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "Показать/Ñкрыть панель производительноÑти"
@@ -41988,6 +42736,9 @@ msgstr "Общий размер артефактов: %{total_size}"
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Ðртефакты"
@@ -42858,10 +43616,10 @@ msgstr "Текущий период иÑпользованиÑ"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr "Репозиторий"
msgid "UsageQuota|Seats"
msgstr "МеÑта"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr "Идентификатор Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð» уÑпешнÐ
msgid "User identity was successfully updated."
msgstr "Идентификатор Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð» уÑпешно обновлен."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "Пользователи были уÑпешно добавлены."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "Пользователи Ñ Ñ€Ð¾Ð»ÑŒÑŽ Guest или те, кто не входит в проект или группу, не займут меÑта в вашей лицензии."
@@ -43657,7 +44412,34 @@ msgstr "Ðет ответÑтвенного - %{openingTag} назначить Ñ
msgid "UsersSelect|Unassigned"
msgstr "Ðе назначено"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Показать график"
@@ -43943,8 +44728,8 @@ msgstr ""
msgid "View eligible approvers"
msgstr "Увидеть подходÑщих утверждающих"
-msgid "View epics list"
-msgstr "Показать ÑпиÑок целей"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr "Образ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr "ПроÑтранÑтво имён"
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr "по"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr "Ðайдено %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr "комментарий"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr "невозможно. Ðа данный момент мы не поддерживаем итерации ÑƒÑ€Ð¾Ð²Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "отÑутÑтвует"
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr "или"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr "удалить приоритет"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "название тега"
@@ -48427,6 +49307,13 @@ msgstr "обновлено %{time_ago}"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr "аватар пользователÑ"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index ef9794cfc14..37539f6c29a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr " %{start} සිට %{end}"
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "අනුමතකරුවන් %d"
@@ -698,7 +703,7 @@ msgid "%{hook_type} was scheduled for deletion"
msgstr ""
msgid "%{host} sign-in from new location"
-msgstr "%{host} නව ස්ථà·à¶±à¶ºà¶šà·’න් ඇතුළුව ඇත"
+msgstr "%{host} වෙත නව ස්ථà·à¶±à¶ºà¶šà·’න් ඇතුළු වී ඇත"
msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
msgstr ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} සිට %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} තිබේ"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "අවවà·à¶¯ %{total} ක් හමු විය: පළමු %{warningsDisplayed} පෙන්වයි"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{name} නමකට පමණක් %{type} සහà·à¶º දක්වයි"
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "%{user_name} පà·à¶­à·’කඩ පිටුව"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr "මෙම සිරà·à·ƒà·’ය සහිත පිටුවක් පවතී"
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr "පරිà·à·“ලකයින් සමූහයට එකතු කරන්න"
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr "මූලà·à·à·Šâ€à¶» ආයà·à¶­à¶º"
msgid "AdminSettings|Inactive project deletion"
msgstr "අක්â€à¶»à·’ය ව්â€à¶ºà·à¶´à·˜à¶­à·’ මකà·à¶¯à·à¶¸à·“ම"
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය නිර්යà·à¶­à¶º"
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "එය අබල කිරීමට සීමà·à·€ 0 ට සකසන්න."
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් සඳහ෠උපරිම ගිට්ලà·à¶¶à·Š පිටු ගණන සකසන්න (0 යනු අසීමිතයි). %{link_start}තව දà·à¶±à¶œà¶±à·Šà¶±.%{link_end}"
@@ -3078,6 +3119,9 @@ msgstr "අවහිරයි"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "සමූහයක් සෑදිය à·„à·à¶šà·’ය"
@@ -3214,7 +3258,7 @@ msgid "AdminUsers|Rejected users:"
msgstr ""
msgid "AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in."
-msgstr ""
+msgstr "යළි à·ƒà·à¶šà·ƒà·“මේ සබà·à¶³à·’ය උත්පà·à¶¯à¶±à¶º කර පරිà·à·“ලකය෠වෙත යවනු ලà·à¶¶à·š. පළමු පිවිසුමේදී මුරපදය à·ƒà·à¶šà·ƒà·“මට පරිà·à·“ලකයà·à¶§ බල කෙරෙනු ඇත."
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
@@ -3304,7 +3348,7 @@ msgid "AdminUsers|View pending member requests"
msgstr ""
msgid "AdminUsers|Website URL"
-msgstr "අඩවියේ ඒ.ස.නි."
+msgstr "අඩවියෙහි ඒ.ස.නි."
msgid "AdminUsers|What can I do?"
msgstr "මට කුමක් කළ à·„à·à¶šà·’ද?"
@@ -3417,9 +3461,21 @@ msgstr "à·€à·à¶©à·’දුර ආයà·à¶­ විකල්ප"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr "සියළුම සංයුක්ත ඉල්ලීම් පරà·
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "සියළුම ව්â€à¶ºà·à¶´à·˜à¶­à·’"
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -3952,16 +4014,16 @@ msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
msgid "Almost there"
-msgstr ""
+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 ""
@@ -4209,9 +4271,6 @@ msgstr "මෙම පිටුවේ කොටසක් පූරණය කිà¶
msgid "An error occurred while loading all the files."
msgstr "සියළුම ගොනු පූරණය කිරීමේදී දà·à·‚යක් ඇති විය."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "ප්â€à¶»à·ƒà·Šà¶®à·à¶» දත්ත පූරණය කිරීමේදී දà·à·‚යක් ඇති විය"
@@ -4457,6 +4516,9 @@ msgstr "නොදන්න෠දà·à·‚යක් සිදුවිය."
msgid "Analytics"
msgstr "විà·à·Šà¶½à·šà·‚ණ"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4521,7 +4583,7 @@ msgid "Any namespace"
msgstr ""
msgid "Anyone can register for an account."
-msgstr "ඕනෑම අයෙකුට ගිණුමක් සෑදීමට à·„à·à¶šà·’ය."
+msgstr "ඕනෑම අයෙක්ට ගිණුමක් සෑදීමට à·„à·à¶šà·’ය."
msgid "App ID"
msgstr "යෙදුමේ à·„à·à¶³à·”."
@@ -4648,7 +4710,7 @@ msgid "ApplicationSettings|Only users with e-mail addresses that match these dom
msgstr ""
msgid "ApplicationSettings|Require admin approval for new sign-ups"
-msgstr ""
+msgstr "නව ලියà·à¶´à¶¯à·’ංචි සඳහ෠පරිපà·à¶½à¶š අනුමà·à¶­à·’ය අවà·à·Šâ€à¶º වේ"
msgid "ApplicationSettings|Require lowercase letters"
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "ගොනු %d ක් අමුණමින්"
msgid "Attaching the file failed."
msgstr "ගොනුව ඇමිණීමට අසමත්!."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6082,7 +6153,7 @@ msgid "BillingPlans|Learn more"
msgstr "තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
-msgstr ""
+msgstr "අපගේ %{faq_link} කියවීමෙන් එක් එක් à·ƒà·à¶½à·ƒà·”ම ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±, හෝ දවස් 30 ක නොමිලේ GitLab.com අල්ටිමේට් නà·à·„à·à·ƒà·”මක් අරඹන්න."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "අපගේ %{pricing_page_link} වෙත පිවිසීමෙන් එක් එක් à·ƒà·à¶½à·ƒà·”ම ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±."
@@ -6115,7 +6186,7 @@ msgid "BillingPlans|Pricing page"
msgstr "මිලකරණ පිටුව"
msgid "BillingPlans|Ready to explore the value of the paid features today? Start a trial, no credit card required."
-msgstr ""
+msgstr "ගෙවන විà·à·šà·‚à·à¶‚ගවල වටිනà·à¶šà¶¸ ගවේà·à¶±à¶º කිරීමට අද සූදà·à¶±à¶¸à·Šà¶¯? නà·à·„à·à·ƒà·”මක් අරඹන්න, ණය පතක් අවà·à·Šâ€à¶º නොවේ."
msgid "BillingPlans|Recommended"
msgstr "නිර්දේà·à·’තයි"
@@ -6315,8 +6386,8 @@ msgstr "සෘජු à·ƒà·à¶¸à·à¶¢à·’කත්ව"
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
-msgstr ""
+msgid "Billing|Explore paid plans"
+msgstr "ගෙවන à·ƒà·à¶½à·ƒà·”ම් ගවේà·à¶±à¶º"
msgid "Billing|Export list"
msgstr ""
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr "තද පෙළ"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "SSH සහ HTTP(S) දෙකම"
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr "à·à·à¶›à·à·€à·š නීති"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr "සීමà·à·€"
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr "මà·à¶­à·˜à¶šà·à·€ \"%{title_param}\" ලෙස වෙනස් කà¶
msgid "Changes to the title have not been saved"
msgstr "මà·à¶­à·˜à¶šà·à·€à·š වෙනස්කම් සුරà·à¶šà·“ නà·à¶­"
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr "මෙහි ඕනෑම à·ƒà·à¶šà·ƒà·”මක් වෙනස් කිරීමට යෙදුම යළි ඇරඹිය යුතුය"
@@ -7781,7 +7924,7 @@ msgid "Checking group path availability..."
msgstr ""
msgid "Checking username availability..."
-msgstr ""
+msgstr "නම තිබේදà·à¶ºà·’ පරීක්â€à·‚෠වෙමින්..."
msgid "Checkout"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr "ඔබට මෙම නියà·à¶­à¶º මà·à¶šà·“මට අවà·à·Šâ€
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr "සහතිකය"
@@ -8794,6 +8940,9 @@ msgstr "නියà·à¶­à¶ºà¶šà·Š යà·à·€à¶­à·Šà¶šà·à¶½ කරන්නේ ක
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr "නියà·à¶­ නà·à¶­"
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr "සම්බන්ධ නà·à¶­"
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr "නිර්දේà·à·’ත"
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9304,7 +9462,7 @@ msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your AP
msgstr ""
msgid "ClusterIntegration|sign up"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචිය"
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr "සම්පූර්ණයි"
msgid "Complete verification to sign in."
msgstr "පිවිසීමට තහවුරුව නිම කරන්න."
+msgid "Complete verification to sign up."
+msgstr "පිවිසීමට සත්â€à¶ºà·à¶´à¶±à¶º නිම කරන්න."
+
msgid "Completed"
msgstr "සම්පූර්ණයි"
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9945,7 +10109,7 @@ msgid "Confirm user"
msgstr ""
msgid "Confirm your account"
-msgstr ""
+msgstr "ගිණුම තහවුරු කරන්න"
msgid "Confirm your email address"
msgstr ""
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr "දà·à¶ºà¶šà¶ºà·’න්"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -11286,7 +11465,7 @@ msgid "Credentials"
msgstr ""
msgid "CredentialsInventory|GPG Keys"
-msgstr ""
+msgstr "ජීපීජී යතුරු"
msgid "CredentialsInventory|No credentials found"
msgstr ""
@@ -11334,7 +11513,7 @@ msgid "Crm|Edit contact"
msgstr "සබඳතà·à·€à¶º සංස්කරණය"
msgid "Crm|Edit organization"
-msgstr ""
+msgstr "සංවිධà·à¶±à¶º සංස්කරණය"
msgid "Crm|New contact"
msgstr "නව සබඳතà·à·€à¶º"
@@ -11346,19 +11525,19 @@ msgid "Crm|No contacts found"
msgstr "කිසිදු සබඳතà·à·€à¶ºà¶šà·Š හමු නොවිණි"
msgid "Crm|No organization"
-msgstr ""
+msgstr "සංවිධà·à¶±à¶ºà¶šà·Š නà·à¶­"
msgid "Crm|No organizations found"
msgstr "සංවිධà·à¶± කිසිවක් හමු නොවිණි"
msgid "Crm|Organization"
-msgstr ""
+msgstr "සංවිධà·à¶±à¶º"
msgid "Crm|Organization has been added."
-msgstr ""
+msgstr "සංවිධà·à¶±à¶º යà·à·€à¶­à·Šà¶šà·à¶½ කර ඇත."
msgid "Crm|Organization has been updated."
-msgstr ""
+msgstr "සංවිධà·à¶±à¶º යà·à·€à¶­à·Šà¶šà·à¶½ කර ඇත."
msgid "Cron Timezone"
msgstr ""
@@ -11403,7 +11582,7 @@ msgid "Current node must be the primary node or you will be locking yourself out
msgstr ""
msgid "Current password"
-msgstr ""
+msgstr "වත්මන් මුරපදය"
msgid "Current sign-in IP:"
msgstr ""
@@ -11421,13 +11600,13 @@ msgid "CurrentUser|Buy Pipeline minutes"
msgstr ""
msgid "CurrentUser|Edit profile"
-msgstr ""
+msgstr "පà·à¶­à·’කඩ සංස්කරණය"
msgid "CurrentUser|One of your groups is running out"
msgstr ""
msgid "CurrentUser|Preferences"
-msgstr ""
+msgstr "අභිප්â€à¶»à·šà¶­"
msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
@@ -11927,16 +12106,16 @@ msgid "DastProfiles|Debug messages"
msgstr ""
msgid "DastProfiles|Delete profile"
-msgstr ""
+msgstr "පà·à¶­à·’කඩ මකන්න"
msgid "DastProfiles|Edit profile"
-msgstr ""
+msgstr "පà·à¶­à·’කඩ සංස්කරණය"
msgid "DastProfiles|Edit scanner profile"
msgstr ""
msgid "DastProfiles|Edit site profile"
-msgstr ""
+msgstr "අඩවියේ පà·à¶­à·’කඩ සංස්කරණය"
msgid "DastProfiles|Enable Authentication"
msgstr ""
@@ -11951,7 +12130,7 @@ msgid "DastProfiles|Enter headers in a comma-separated list."
msgstr ""
msgid "DastProfiles|Error Details"
-msgstr ""
+msgstr "දà·à·‚ විස්තර"
msgid "DastProfiles|Excluded URLs"
msgstr ""
@@ -12014,7 +12193,7 @@ msgid "DastProfiles|Passive"
msgstr ""
msgid "DastProfiles|Password"
-msgstr ""
+msgstr "මුරපදය"
msgid "DastProfiles|Password form field"
msgstr ""
@@ -12080,10 +12259,10 @@ msgid "DastProfiles|Site name"
msgstr ""
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "අඩවියේ පà·à¶­à·’කඩ"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "අඩවි පà·à¶­à·’කඩ"
msgid "DastProfiles|Site type"
msgstr ""
@@ -12128,7 +12307,7 @@ msgid "DastProfiles|URLs to skip during the authenticated scan."
msgstr ""
msgid "DastProfiles|Username"
-msgstr ""
+msgstr "පරිà·à·“ලක නà·à¶¸à¶º"
msgid "DastProfiles|Username form field"
msgstr ""
@@ -12152,13 +12331,13 @@ msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
msgstr ""
msgid "DastProfiles|https://example.com/dast_example.har"
-msgstr ""
+msgstr "https://නිදසුන.ලංකà·/dast_example.har"
msgid "DastProfiles|https://example.com/openapi.json"
-msgstr ""
+msgstr "https://නිදසුන.ලංකà·/openapi.json"
msgid "DastProfiles|https://example.com/postman_collection.json"
-msgstr ""
+msgstr "https://නිදසුන.ලංකà·/postman_collection.json"
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12766,7 +12957,7 @@ msgid "Dependencies|License"
msgstr ""
msgid "Dependencies|Location"
-msgstr ""
+msgstr "ස්ථà·à¶±à¶º"
msgid "Dependencies|Location and dependency path"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13072,6 +13272,12 @@ msgid "DeployTokens|Use this token as a password. Save it. This password can %{i
msgstr ""
msgid "DeployTokens|Username"
+msgstr "පරිà·à·“ලක නà·à¶¸à¶º"
+
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
msgstr ""
msgid "DeployTokens|Your new Deploy Token username"
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr ""
+msgid "DesignManagement|Comment"
+msgstr "අදහස"
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13373,16 +13567,16 @@ msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
msgid "DesignManagement|Deselect all"
-msgstr ""
+msgstr "සියල්ල නොතà·à¶»à¶±à·Šà¶±"
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "à·ƒà·à¶šà¶ à·Šà¶¡à·à·€"
msgid "DesignManagement|Download design"
msgstr ""
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13415,10 +13603,10 @@ msgid "DesignManagement|Resolved Comments"
msgstr ""
msgid "DesignManagement|Save comment"
-msgstr ""
+msgstr "අදහස සුරකින්න"
msgid "DesignManagement|Select all"
-msgstr ""
+msgstr "සියල්ල තà·à¶»à¶±à·Šà¶±"
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
msgstr ""
@@ -13679,7 +13867,7 @@ msgid "Didn't receive a confirmation email?"
msgstr ""
msgid "Didn't receive confirmation instructions?"
-msgstr ""
+msgstr "තහවුරු කිරීමේ උපදෙස් ලà·à¶¶à·”නේ නà·à¶¯à·Šà¶¯?"
msgid "Didn't receive unlock instructions?"
msgstr ""
@@ -13947,11 +14135,23 @@ msgstr "වසම"
msgid "Domain Name"
msgstr "වසමේ නම"
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
msgid "Don't have an account yet?"
-msgstr ""
+msgstr "තවම ගිණුමක් නà·à¶¯à·Šà¶¯?"
msgid "Don't include description in commit message"
msgstr ""
@@ -13966,7 +14166,7 @@ msgid "Don't show again"
msgstr "යළි පෙන්වන්න එපà·"
msgid "Done"
-msgstr ""
+msgstr "අහවරයි"
msgid "Dormant users"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14449,10 +14652,7 @@ msgid "EmailParticipantsWarning|and %{moreCount} more"
msgstr ""
msgid "Emails"
-msgstr ""
-
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
+msgstr "වි-තà·à¶´à·à¶½à·Š"
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14938,7 +15144,7 @@ msgid "Environments|Job"
msgstr ""
msgid "Environments|Learn about environments"
-msgstr ""
+msgstr "පරිසර ගà·à¶± දà·à¶±à¶œà¶±à·Šà¶±"
msgid "Environments|Learn more about stopping environments"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15624,7 +15836,7 @@ msgid "Everyone can access the wiki."
msgstr ""
msgid "Everyone can contribute"
-msgstr ""
+msgstr "à·ƒà·à¶¸à¶§ දà·à¶ºà¶š විය à·„à·à¶šà·’ය"
msgid "Everything on your to-do list is marked as done."
msgstr ""
@@ -15777,34 +15989,34 @@ msgid "Explain the problem. If appropriate, provide a link to the relevant issue
msgstr ""
msgid "Explore"
-msgstr ""
+msgstr "ගවේà·à¶±à¶º"
msgid "Explore GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š ගවේà·à¶±à¶º"
msgid "Explore Groups"
-msgstr ""
+msgstr "සමූහ ගවේà·à¶±à¶º"
msgid "Explore groups"
-msgstr ""
+msgstr "සමූහ ගවේà·à¶±à¶º"
msgid "Explore paid plans"
-msgstr ""
+msgstr "ගෙවන à·ƒà·à¶½à·ƒà·”ම් ගවේà·à¶±à¶º"
msgid "Explore projects"
-msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගවේà·à¶«à¶º"
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගවේà·à¶±à¶º"
msgid "Explore public groups"
-msgstr ""
+msgstr "පොදු සමූහ ගවේà·à¶±à¶º"
msgid "Explore public projects"
-msgstr ""
+msgstr "පොදු ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගවේà·à¶±à¶º"
msgid "Explore snippets"
msgstr ""
msgid "Explore topics"
-msgstr "මà·à¶­à·˜à¶šà· ගවේà·à¶«à¶º"
+msgstr "මà·à¶­à·˜à¶šà· ගවේà·à¶±à¶º"
msgid "Export"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16162,7 +16371,7 @@ msgid "Failed to remove timelog"
msgstr ""
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "පරිà·à·“ලක අනන්â€à¶ºà¶­à·à·€à¶º ඉවත් කිරීමට අසමත් විය."
msgid "Failed to remove user key."
msgstr ""
@@ -16180,7 +16389,7 @@ msgid "Failed to save preferences (%{error_message})."
msgstr ""
msgid "Failed to save preferences."
-msgstr ""
+msgstr "අභිප්â€à¶»à·šà¶­ සුරà·à¶šà·“මට අසමත් විය."
msgid "Failed to save timelog"
msgstr ""
@@ -16434,7 +16643,7 @@ msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "FeatureFlags|User IDs"
-msgstr ""
+msgstr "පරිà·à·“ලක à·„à·à¶³à·”."
msgid "FeatureFlags|User List"
msgstr ""
@@ -16461,7 +16670,7 @@ msgid "FeatureFlag|Type"
msgstr ""
msgid "FeatureFlag|User IDs"
-msgstr ""
+msgstr "පරිà·à·“ලක à·„à·à¶³à·”."
msgid "FeatureFlag|User List"
msgstr ""
@@ -16656,7 +16865,7 @@ msgid "Finished"
msgstr ""
msgid "First Name"
-msgstr ""
+msgstr "මුල් නම"
msgid "First Seen"
msgstr ""
@@ -16665,7 +16874,7 @@ msgid "First day of the week"
msgstr ""
msgid "First name"
-msgstr ""
+msgstr "මුල් නම"
msgid "First seen"
msgstr ""
@@ -16710,7 +16919,7 @@ msgid "FogBugz Import"
msgstr ""
msgid "FogBugz Password"
-msgstr ""
+msgstr "FogBugz මුරපදය"
msgid "FogBugz URL"
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16785,7 +16997,7 @@ msgid "For more information, see the File Hooks documentation."
msgstr ""
msgid "Forgot your password?"
-msgstr ""
+msgstr "මුරපදය අමතක වුනà·à¶¯?"
msgid "Fork"
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16942,7 +17187,7 @@ msgid "Full log"
msgstr ""
msgid "Full name"
-msgstr ""
+msgstr "සම්පූර්ණ නම"
msgid "GCP region configured"
msgstr ""
@@ -16951,7 +17196,7 @@ msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
-msgstr ""
+msgstr "ජීපීජී යතුරු"
msgid "GPG keys allow you to verify signed commits."
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17258,7 +17506,7 @@ msgid "Geo|Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStar
msgstr ""
msgid "Geo|Never"
-msgstr ""
+msgstr "කවදà·à·€à¶­à·Š"
msgid "Geo|Next sync scheduled at"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr "ගිට්ලà·à¶¶à·Š KAS"
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -17798,7 +18046,7 @@ msgid "GitLab single sign-on URL"
msgstr ""
msgid "GitLab username"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š පරිà·à·“ලක නà·à¶¸à¶º"
msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs"
msgstr ""
@@ -18029,10 +18277,10 @@ msgid "GlobalSearch|Groups"
msgstr "සමූහ"
msgid "GlobalSearch|Help"
-msgstr ""
+msgstr "උදව්"
msgid "GlobalSearch|In this project"
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’යෙහි"
msgid "GlobalSearch|Issues I've created"
msgstr ""
@@ -18065,7 +18313,7 @@ msgid "GlobalSearch|Results updated. %{count} results available. Use the up and
msgstr ""
msgid "GlobalSearch|Search GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š à·„à·’ සොයන්න"
msgid "GlobalSearch|Search for projects, issues, etc."
msgstr ""
@@ -18074,7 +18322,7 @@ msgid "GlobalSearch|Search results are loading"
msgstr ""
msgid "GlobalSearch|Settings"
-msgstr ""
+msgstr "à·ƒà·à¶šà·ƒà·”ම්"
msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
msgstr ""
@@ -18488,7 +18736,7 @@ msgid "Group name"
msgstr ""
msgid "Group name (your organization)"
-msgstr ""
+msgstr "සමූහයේ නම (ඔබගේ සංවිධà·à¶±à¶º)"
msgid "Group navigation"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19398,7 +19664,7 @@ msgid "Hello, %{name}!"
msgstr ""
msgid "Hello, %{username}!"
-msgstr ""
+msgstr "ආයුබà·, %{username}!"
msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
msgstr ""
@@ -19443,10 +19709,10 @@ msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Hi %{username}!"
-msgstr ""
+msgstr "ආයුබ෠%{username}!"
msgid "Hi %{username},"
-msgstr ""
+msgstr "ආයුබ෠%{username},"
msgid "Hidden"
msgstr ""
@@ -19582,7 +19848,7 @@ msgid "Horizontal rule"
msgstr ""
msgid "Hostname"
-msgstr ""
+msgstr "සත්කà·à¶»à¶šà¶º"
msgid "Hostname used in private commit emails. %{learn_more}"
msgstr ""
@@ -19639,7 +19905,7 @@ msgid "I accept the %{terms_link}"
msgstr ""
msgid "I forgot my password"
-msgstr ""
+msgstr "මà·à¶œà·š මුරපදය අමතක වුණà·"
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -19660,7 +19926,7 @@ msgid "I'd like to receive updates about GitLab via email"
msgstr ""
msgid "I'm signing up for GitLab because:"
-msgstr ""
+msgstr "මම ගිට්ලà·à¶¶à·Š වෙත ලියà·à¶´à¶¯à·’ංචි වන්නේ:"
msgid "ID"
msgstr ""
@@ -19720,16 +19986,16 @@ msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
msgstr ""
msgid "IP Address"
-msgstr ""
+msgstr "අ.ජà·.කෙ."
msgid "IP address expiration time"
-msgstr ""
+msgstr "අ.ජà·.කෙ. ඉකුත් වීමේ කà·à¶½à¶º"
msgid "IP address restrictions"
-msgstr ""
+msgstr "අ.ජà·.කෙ. ලිපින සීමà·"
msgid "IP addresses per user"
-msgstr ""
+msgstr "එක් අයෙක්ට අ.ජà·.කෙ. ලිපින"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr ""
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,17 +20090,23 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr "කේතය යළි යවන්න"
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr "කේතය කල් ඉකුත්ය. නව කේතයක් යව෠යළි උත්සà·à·„ කරන්න."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr "කේතය à·€à·à¶»à¶¯à·’යි. යළි ඇතුල් කරන්න, හෝ නව කේතයක් යවන්න."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr ""
msgid "IdentityVerification|Verification code"
msgstr "තහවුරු කේතය"
@@ -19824,6 +20117,12 @@ msgstr "තහවුරුව à·ƒà·à¶»à·Šà¶®à¶šà¶ºà·’"
msgid "IdentityVerification|Verify code"
msgstr "තහවුරු කරන්න"
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,11 +20132,14 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr "උපරිම තà·à¶­à·Š කිරීම් ගණනට ළඟ෠වී ඇත. %{interval} ක් රà·à¶³à·“ සිටින්න හ෠නව කේතයක් යව෠උත්සà·à·„ කරන්න."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "ඔබගේ ගිණුම à·ƒà·à¶»à·Šà¶®à¶šà·€ තහවුරු කර ඇත. මොහොතකින් ඔබගේ ගිණුමට හරව෠යවනු ඇත, හෝ නà·à·€à·”ම් කිරීමට %{redirect_url_start}ඔබන්න%{redirect_url_end}."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "තහවුරු කේතය විනà·à¶©à·’ %{expires_in_minutes} කින් ඉකුත් වේ."
@@ -19909,12 +20211,18 @@ msgid "If you did not initiate this change, please contact your administrator im
msgstr ""
msgid "If you did not perform this request, you can safely ignore this email."
-msgstr ""
+msgstr "ඔබ මෙය සිදු නොකළේ නම්, මෙම වි-තà·à¶´à·‘ල නොසලකන්න."
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
-msgstr ""
+msgstr "ඔබ මෑත දී ඇතුළු වී නà·à¶­à·’ නම්, වහà·à¶¸ %{password_link_start}ඔබගේ මුරපදය වෙනස් කළ යුතුය%{password_link_end}."
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr "ඔබ මෑත දී ඇතුළු වී නà·à¶­à·’ නම්, වහà·à¶¸ ඔබගේ මුරපදය වෙනස් කළ යුතුය: %{password_link}"
+
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
msgstr ""
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
@@ -19924,6 +20232,9 @@ msgid "If you lose your recovery codes you can generate new ones, invalidating a
msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr "ඔබ මෑත දී ඇතුළු වී හ෠අ.ජà·.කෙ. ලිපිනය හඳුන෠ගන්නේ නම්, මෙම වි-තà·à¶´à·‘ල නොසලකන්න."
+
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
msgstr ""
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20317,13 +20634,13 @@ msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
msgstr ""
msgid "InProductMarketing|Explore GitLab CI/CD"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š CI/CD ගවේà·à¶±à¶º"
msgid "InProductMarketing|Explore the options"
-msgstr ""
+msgstr "විකල්ප ගවේà·à¶±à¶º"
msgid "InProductMarketing|Explore the power of GitLab CI/CD"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š CI/CD à·„à·’ බලය ගවේà·à¶±à¶º"
msgid "InProductMarketing|Facebook"
msgstr ""
@@ -20686,7 +21003,7 @@ msgid "InProductMarketing|from Bitbucket"
msgstr ""
msgid "InProductMarketing|go to about.gitlab.com"
-msgstr ""
+msgstr "about.gitlab.com වෙත යන්න"
msgid "InProductMarketing|how easy it is to get started"
msgstr ""
@@ -20881,7 +21198,7 @@ msgid "IncidentSettings|PagerDuty integration"
msgstr ""
msgid "IncidentSettings|Time limit"
-msgstr ""
+msgstr "කà·à¶½ සීමà·à·€"
msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21330,11 +21659,14 @@ msgid "Integrations|Failed to load subscriptions."
msgstr ""
msgid "Integrations|Failed to sign in to GitLab."
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත පිවිසීමට අසමත් විය."
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21426,10 +21758,10 @@ msgid "Integrations|Send notifications about project events to a Unify Circuit c
msgstr ""
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "%{url} වෙත පිවිසෙන්න"
msgid "Integrations|Sign in to GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත පිවිසෙන්න"
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21711,13 +22040,13 @@ msgid "InviteMembersModal|Close invite team members"
msgstr ""
msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
-msgstr ""
+msgstr "ඔබගේම ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් à·ƒà·à¶¯à· ගà·à¶±à·“මට සුභ පà·à¶­à·”ම්, ඔබ බොහ෠දුර පà·à¶¸à·’ණ ඇත!"
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
msgid "InviteMembersModal|Explore paid plans"
-msgstr ""
+msgstr "ගෙවන à·ƒà·à¶½à·ƒà·”ම් ගවේà·à¶±à¶º"
msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22280,7 +22618,7 @@ msgid "Iterations|Description"
msgstr ""
msgid "Iterations|Done"
-msgstr ""
+msgstr "අහවරයි"
msgid "Iterations|Due date"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -22616,7 +22951,7 @@ msgid "JiraService|Sign in to GitLab to link namespaces."
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
-msgstr ""
+msgstr "පටන් ගà·à¶±à·“මට GitLab.com වෙත පිවිසෙන්න."
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -22637,7 +22972,7 @@ msgid "JiraService|Use custom transitions"
msgstr ""
msgid "JiraService|Username or Email"
-msgstr ""
+msgstr "පරිà·à·“ලක නà·à¶¸à¶º හ෠වි-තà·à¶´à·‘ල"
msgid "JiraService|Using Jira for issue tracking?"
msgstr ""
@@ -23175,7 +23510,7 @@ msgid "Last Activity"
msgstr ""
msgid "Last Name"
-msgstr ""
+msgstr "අග නම"
msgid "Last Pipeline"
msgstr ""
@@ -23220,7 +23555,7 @@ msgid "Last month"
msgstr ""
msgid "Last name"
-msgstr ""
+msgstr "අග නම"
msgid "Last reply by"
msgstr ""
@@ -23232,7 +23567,7 @@ msgid "Last seen"
msgstr ""
msgid "Last sign-in"
-msgstr ""
+msgstr "අවසà·à¶± පිවිසුම"
msgid "Last sign-in IP:"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,14 +23662,14 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
msgid "Learn more about GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "Learn more about Needs relationships"
msgstr ""
@@ -23739,7 +24077,7 @@ msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit sign in from multiple IP addresses"
-msgstr ""
+msgstr "අ.ජà·.කෙ. ලිපින කිහිපයකින් පිවිසීම සීම෠කරන්න"
msgid "Limit the number of inbound incident management alerts that can be sent to a project."
msgstr ""
@@ -23805,10 +24143,10 @@ msgid "Linked items"
msgstr ""
msgid "LinkedIn"
-msgstr ""
+msgstr "ලින්ක්ඩින්"
msgid "LinkedIn:"
-msgstr ""
+msgstr "ලින්ක්ඩින්:"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
@@ -23937,10 +24275,10 @@ msgid "Localization"
msgstr ""
msgid "Location"
-msgstr ""
+msgstr "ස්ථà·à¶±à¶º"
msgid "Location:"
-msgstr ""
+msgstr "ස්ථà·à¶±à¶º:"
msgid "Lock"
msgstr ""
@@ -23991,7 +24329,7 @@ msgid "LoggedOutMarketingHeader|About GitLab"
msgstr ""
msgid "LoggedOutMarketingHeader|Explore GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š ගවේà·à¶±à¶º"
msgid "LoggedOutMarketingHeader|Get started"
msgstr ""
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr "මෙම %{noun} සූදà·à¶±à¶¸à·Š ලෙස යොදන්න."
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -24603,13 +24959,13 @@ msgid "Medium vulnerabilities present"
msgstr ""
msgid "Member since"
-msgstr ""
+msgstr "à·ƒà·à¶¸à·à¶¢à·’කත්â€à·€à¶º"
msgid "Member since %{date}"
-msgstr ""
+msgstr "%{date} දී à·ƒà·à¶¸à·à¶¢à·’ක විය"
msgid "Member since:"
-msgstr ""
+msgstr "à·ƒà·à¶¸à·à¶¢à·’කත්â€à·€à¶º:"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26059,19 +26424,19 @@ msgid "NavigationTheme|Red"
msgstr ""
msgid "Nav|Help"
-msgstr ""
+msgstr "උදව්"
msgid "Nav|Home"
msgstr ""
msgid "Nav|Sign In / Register"
-msgstr ""
+msgstr "පිවිසෙන්න / ලියà·à¶´à¶¯à·’ංචිය"
msgid "Nav|Sign out and sign in with a different account"
-msgstr ""
+msgstr "නික්ම ගොස් වෙනත් ගිණුමකින් පිවිසෙන්න"
msgid "Need help?"
-msgstr ""
+msgstr "උදව් වුවමන෠ද?"
msgid "Needs"
msgstr ""
@@ -26086,7 +26451,7 @@ msgid "Network:"
msgstr ""
msgid "Never"
-msgstr ""
+msgstr "කවදà·à·€à¶­à·Š"
msgid "New"
msgstr ""
@@ -26139,7 +26504,7 @@ msgid "New Pages Domain"
msgstr ""
msgid "New Password"
-msgstr ""
+msgstr "නව මුරපදය"
msgid "New Pipeline Schedule"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26238,7 +26606,7 @@ msgid "New name"
msgstr ""
msgid "New password"
-msgstr ""
+msgstr "නව මුරපදය"
msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
msgstr ""
@@ -26406,7 +26774,7 @@ msgid "No committers"
msgstr ""
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 ""
@@ -26451,7 +26819,7 @@ msgid "No estimate or time spent"
msgstr ""
msgid "No file chosen."
-msgstr ""
+msgstr "ගොනුවක් තà·à¶»à· නà·à¶­."
msgid "No file hooks found."
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26911,16 +27282,16 @@ msgid "NotificationLevel|Watch"
msgstr ""
msgid "Notifications"
-msgstr ""
+msgstr "දà·à¶±à·”ම්දීම්"
msgid "Notifications have been disabled by the project or group owner"
msgstr ""
msgid "Notifications off"
-msgstr ""
+msgstr "දà·à¶±à·”ම්දීම් අක්â€à¶»à·’යයි"
msgid "Notifications on"
-msgstr ""
+msgstr "දà·à¶±à·”ම්දීම් සක්â€à¶»à·’යයි"
msgid "Notifications turned off."
msgstr "දà·à¶±à·”ම්දීම් අක්â€à¶»à·’යයි."
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr "ආයුබ෠%{username}!"
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "මෙම සබà·à¶³à·’ය %{password_reset_token_valid_time} ක් දක්ව෠වලංගු වේ."
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr "දà·à¶±à¶§ සහà·à¶º දක්වන භà·à·‚à·"
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "වප්"
@@ -27287,11 +27778,14 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
msgid "OnCallSchedules|Select timezone"
-msgstr ""
+msgstr "වේල෠කලà·à¶´à¶º තà·à¶»à¶±à·Šà¶±"
msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
msgstr ""
@@ -27405,7 +27899,7 @@ msgid "OnDemandScans|Edit on-demand scan"
msgstr ""
msgid "OnDemandScans|Edit profile"
-msgstr ""
+msgstr "පà·à¶­à·’කඩ සංස්කරණය"
msgid "OnDemandScans|Enable scan schedule"
msgstr ""
@@ -27782,7 +28276,7 @@ msgid "Ordered list"
msgstr ""
msgid "Organizations"
-msgstr ""
+msgstr "සංවිධà·à¶±"
msgid "Orphaned member"
msgstr ""
@@ -27806,10 +28300,10 @@ msgid "Other visibility settings have been disabled by the administrator."
msgstr ""
msgid "Otherwise, click the link below to complete the process."
-msgstr ""
+msgstr "නà·à¶­à·’නම්, ක්â€à¶»à·’යà·à·€à¶½à·’ය නිම කිරීමට පහත සබà·à¶³à·’ය ඔබන්න."
msgid "Otherwise, click the link below to complete the process:"
-msgstr ""
+msgstr "නà·à¶­à·’නම්, ක්â€à¶»à·’යà·à·€à¶½à·’ය නිම කිරීමට පහත සබà·à¶³à·’ය ඔබන්න.:"
msgid "Our team has been notified. Please try again."
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27893,7 +28390,7 @@ msgid "PQL|Contact sales"
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 ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28451,31 +28954,31 @@ msgid "Passed on"
msgstr ""
msgid "Password"
-msgstr ""
+msgstr "මුරපදය"
msgid "Password (optional)"
-msgstr ""
+msgstr "මුරපදය (විකල්ප)"
msgid "Password authentication is unavailable."
msgstr ""
msgid "Password confirmation"
-msgstr ""
+msgstr "මුරපදය තහවුරු කිරීම"
msgid "Password successfully changed"
-msgstr ""
+msgstr "මුරපදය à·ƒà·à¶»à·Šà¶®à¶šà·€ වෙනස් විය"
msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "මුරපදය තහවුරුව"
msgid "PasswordPrompt|Confirm password to continue"
msgstr ""
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "මුරපදය ඇවà·à·ƒà·’ය"
msgid "PasswordPrompt|Please enter your password to confirm"
msgstr ""
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29567,16 +30097,16 @@ msgid "Play all manual"
msgstr ""
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
-msgstr ""
+msgstr "අදහස් දà·à¶šà·Šà·€à·“මට %{link_to_sign_in} à·„à· %{link_to_register}"
msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to reply."
-msgstr ""
+msgstr "පිළිතුරු දීමට %{registerLinkStart}ලියà·à¶´à¶¯à·’ංචි වන්න%{registerLinkEnd} à·„à· %{signInLinkStart}පිවිසෙන්න%{signInLinkEnd}."
msgid "Please %{registerLinkStart}register%{registerLinkEnd} or %{signInLinkStart}sign in%{signInLinkEnd} to start a new discussion."
-msgstr ""
+msgstr "නව à·ƒà·à¶šà¶ à·Šà¶¡à·à·€à¶šà·Š ඇරඹීමට %{registerLinkStart}ලියà·à¶´à¶¯à·’ංචි වන්න%{registerLinkEnd} à·„à· %{signInLinkStart}පිවිසෙන්න%{signInLinkEnd}."
msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
-msgstr ""
+msgstr "පිළිතුරු දීමට %{startTagRegister}ලියà·à¶´à¶¯à·’ංචි වන්න%{endRegisterTag} à·„à· %{startTagSignIn}පිවිසෙන්න%{endSignInTag}"
msgid "Please accept the Terms of Service before continuing."
msgstr ""
@@ -29594,7 +30124,7 @@ msgid "Please check the configuration file to ensure that it is available and th
msgstr ""
msgid "Please check your email %{email} to confirm your account"
-msgstr ""
+msgstr "ඔබගේ ගිණුම තහවුරු කිරීමට වි-තà·à¶´à·‘ල %{email} බලන්න"
msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29831,10 +30367,13 @@ msgid "Preferences"
msgstr "අභිප්â€à¶»à·šà¶­"
msgid "Preferences saved."
+msgstr "අභිප්â€à¶»à·šà¶­ සුරà·à¶šà·’ණි."
+
+msgid "Preferences|Automatically add new list items"
msgstr ""
msgid "Preferences|Behavior"
-msgstr ""
+msgstr "à·„à·à·ƒà·’රීම"
msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
msgstr ""
@@ -29867,7 +30406,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr ""
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "උපකරණ පුවරුව"
msgid "Preferences|Diff colors"
msgstr ""
@@ -29888,13 +30427,13 @@ msgid "Preferences|For example: 30 minutes ago."
msgstr ""
msgid "Preferences|Gitpod"
-msgstr ""
+msgstr "ගිට්පොඩ්"
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
msgid "Preferences|Integrations"
-msgstr ""
+msgstr "අනුකලන"
msgid "Preferences|Layout width"
msgstr ""
@@ -29903,7 +30442,7 @@ msgid "Preferences|Must be a number between %{min} and %{max}"
msgstr ""
msgid "Preferences|Preview"
-msgstr ""
+msgstr "පෙරදසුන"
msgid "Preferences|Project overview content"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30041,7 +30583,7 @@ msgid "Private group(s)"
msgstr ""
msgid "Private profile"
-msgstr ""
+msgstr "පෞද්ගලික පà·à¶­à·’කඩ"
msgid "Private projects Minutes cost factor"
msgstr ""
@@ -30143,7 +30685,7 @@ msgid "Profiles|%{provider} Active"
msgstr ""
msgid "Profiles|@username"
-msgstr ""
+msgstr "@පරිà·à·“ලකනà·à¶¸à¶º"
msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30176,10 +30712,7 @@ msgid "Profiles|Begins with %{ssh_key_algorithms}."
msgstr ""
msgid "Profiles|Bio"
-msgstr ""
-
-msgid "Profiles|Busy"
-msgstr ""
+msgstr "සටහන"
msgid "Profiles|Change username"
msgstr ""
@@ -30191,14 +30724,11 @@ msgid "Profiles|Choose file..."
msgstr ""
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
-msgstr ""
+msgstr "කිසිදු ව්â€à¶ºà·à¶´à·˜à¶­à·’යක්, කà·à·‚්ඨයක් හ෠සංවිධà·à¶±à¶ºà¶š තොරතුරක් රහිතව ඔබගේ ප්â€à¶»à·ƒà·’ද්ධ පà·à¶­à·’කඩෙහි පෞද්ගලික ව්â€à¶ºà·à¶´à·˜à¶­à·’වල දà·à¶ºà¶šà¶­à·Šà·€ පෙන්වීමට තà·à¶»à¶±à·Šà¶±."
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,11 +30741,14 @@ msgstr "පිවිසීමට සේවà·à·€à¶šà·Š සබඳින්න."
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
msgid "Profiles|Current status"
-msgstr ""
+msgstr "වත්මන් තත්â€à·€à¶º"
msgid "Profiles|Default notification email"
msgstr ""
@@ -30236,16 +30769,16 @@ msgid "Profiles|Do not show on profile"
msgstr ""
msgid "Profiles|Don't display activity-related personal information on your profile."
-msgstr "ඔබගේ පà·à¶­à·’කඩෙහි ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ආà·à·Šâ€à¶»à·’ත පුද්ගලික තොරතුරු නොපෙන්වන්න."
+msgstr "ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ආà·à·Šâ€à¶»à·’ත පෞද්ගලික තොරතුරු ඔබගේ පà·à¶­à·’කඩෙහි නොපෙන්වන්න."
msgid "Profiles|Edit Profile"
-msgstr ""
+msgstr "පà·à¶­à·’කඩ සංස්කරණය"
msgid "Profiles|Ensure you have two-factor authentication recovery codes stored in a safe place."
msgstr ""
msgid "Profiles|Enter how your name is pronounced to help people address you correctly."
-msgstr "පහසුව සඳහ෠ඔබගේ නම උච්චà·à¶»à¶«à¶º කරන ආකà·à¶»à¶º ඇතුල් කරන්න."
+msgstr "පහසුව සඳහ෠ඔබගේ නම උච්චà·à¶»à¶«à¶º කරන ආකà·à¶»à¶º යොදන්න."
msgid "Profiles|Enter your name, so people you know can recognize you."
msgstr "නම ඇතුල් කරන්න, එවිට මිනිසුන්ට ඔබව හඳුනà·à¶œà¶­ à·„à·à¶šà·’ය."
@@ -30254,7 +30787,7 @@ msgid "Profiles|Enter your password to confirm the email change"
msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you."
-msgstr ""
+msgstr "ඔබ ගà·à¶± සඳහන් කිරීමට සුදුසු ඔබගේ සර්වනà·à¶¸ යොදන්න."
msgid "Profiles|Example: MacBook key"
msgstr ""
@@ -30272,7 +30805,7 @@ msgid "Profiles|Feed token was successfully reset"
msgstr ""
msgid "Profiles|Full name"
-msgstr ""
+msgstr "සම්පූර්ණ නම"
msgid "Profiles|GitLab is unable to verify your identity automatically. For security purposes, you must set a password by %{openingTag}resetting your password%{closingTag} to delete your account."
msgstr ""
@@ -30281,7 +30814,7 @@ msgid "Profiles|If after setting a password, the option to delete your account i
msgstr ""
msgid "Profiles|Include private contributions on my profile"
-msgstr ""
+msgstr "මà·à¶œà·š පà·à¶­à·’කඩට පෞද්ගලික දà·à¶ºà¶šà¶­à·Šà·€ ද යොදන්න"
msgid "Profiles|Incoming email token was successfully reset"
msgstr ""
@@ -30296,7 +30829,7 @@ msgid "Profiles|Invalid username"
msgstr ""
msgid "Profiles|Job title"
-msgstr ""
+msgstr "රà·à¶šà·’යà·à·€"
msgid "Profiles|Key"
msgstr ""
@@ -30314,19 +30847,19 @@ msgid "Profiles|Learn more"
msgstr ""
msgid "Profiles|Location"
-msgstr ""
+msgstr "ස්ථà·à¶±à¶º"
msgid "Profiles|Made a private contribution"
msgstr ""
msgid "Profiles|Main settings"
-msgstr ""
+msgstr "ප්â€à¶»à¶°à·à¶± à·ƒà·à¶šà·ƒà·”ම්"
msgid "Profiles|Manage two-factor authentication"
msgstr ""
msgid "Profiles|No file chosen."
-msgstr ""
+msgstr "ගොනුවක් තà·à¶»à· නà·à¶­."
msgid "Profiles|Notification email"
msgstr ""
@@ -30335,7 +30868,7 @@ msgid "Profiles|Optional but recommended. If set, key becomes invalid on the spe
msgstr ""
msgid "Profiles|Organization"
-msgstr ""
+msgstr "සංවිධà·à¶±à¶º"
msgid "Profiles|Path"
msgstr ""
@@ -30347,19 +30880,19 @@ msgid "Profiles|Primary email"
msgstr ""
msgid "Profiles|Private contributions"
-msgstr ""
+msgstr "පෞද්ගලික දà·à¶ºà¶šà¶­à·Šà·€à¶º"
msgid "Profiles|Profile was successfully updated"
msgstr ""
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "සර්වනà·à¶¸à¶º"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "උච්චà·à¶»à¶«à¶º"
msgid "Profiles|Public avatar"
-msgstr ""
+msgstr "ප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶­à·’රූපය"
msgid "Profiles|Public email"
msgstr ""
@@ -30401,16 +30934,16 @@ msgid "Profiles|This email will be displayed on your public profile."
msgstr "මෙම වි-තà·à¶´à·‘ල ඔබගේ පොදු පà·à¶­à·’කඩෙහි පෙන්වයි."
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more.%{commit_email_link_end}"
-msgstr "සංස්කරණ හ෠සංයුක්ත කිරීම් à·€à·à¶±à·’ වියමන පà·à¶¯à¶š මෙහෙයුම් සඳහ෠මෙම වි-තà·à¶´à·‘ල භà·à·€à·’ත෠කෙරේ. %{commit_email_link_start}තව දà·à¶±à¶œà¶±à·Šà¶±.%{commit_email_link_end}"
+msgstr "සංස්කරණ හ෠සංයුක්ත කà·à¶»à·Šà¶ºà¶º à·€à·à¶±à·’ වියමන පà·à¶¯à¶š මෙහෙයුම් සඳහ෠භà·à·€à·’ත෠කෙරේ. %{commit_email_link_start}තව දà·à¶±à¶œà¶±à·Šà¶±.%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "මෙම ඉමොජිය සහ පණිවිඩය ඔබගේ පà·à¶­à·’කඩෙහි සහ අතුරු මුහුණත පුර෠දිස්වනු ඇත."
msgid "Profiles|This information will appear on your profile."
msgstr "මෙම තොරතුරු ඔබගේ පà·à¶­à·’කඩෙහි දිස්වේ."
msgid "Profiles|Time settings"
-msgstr ""
+msgstr "වේලà·à·€ à·ƒà·à¶šà·ƒà·“ම"
msgid "Profiles|Title"
msgstr ""
@@ -30428,31 +30961,28 @@ msgid "Profiles|Update username"
msgstr ""
msgid "Profiles|Upload new avatar"
-msgstr ""
+msgstr "නව ප්â€à¶»à¶­à·’රූපයක් යොදන්න"
msgid "Profiles|Use a private email - %{email}"
msgstr ""
msgid "Profiles|User ID"
-msgstr ""
+msgstr "පරිà·à·“ලක à·„à·à¶³à·”."
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
-msgstr ""
+msgstr "පරිà·à·“ලක නà·à¶¸à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ වෙනස් කෙරිණි"
msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
msgstr ""
msgid "Profiles|Website url"
-msgstr ""
-
-msgid "Profiles|What's your status?"
-msgstr ""
+msgstr "අඩවියෙහි ඒ.ස.නි."
msgid "Profiles|Who you represent or work for."
-msgstr "ඔබගේ නියà·à¶¢à¶±à¶º à·„à· à·€à·à¶© කරන්නේ කà·à¶§à¶¯."
+msgstr "ඔබගේ නියà·à¶¢à¶±à¶º à·„à· à·€à·à¶©à¶´à¶½."
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -30464,7 +30994,7 @@ msgid "Profiles|You can upload your avatar here"
msgstr ""
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "ඔබගේ ප්â€à¶»à¶­à·’රූපය මෙහි උඩුගත කිරීමට හ෠එය %{gravatar_link} à·„à·’ à·ƒà·à¶šà·ƒà·“මට à·„à·à¶šà·’ය"
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -30479,7 +31009,7 @@ msgid "Profiles|You must transfer ownership or delete these groups before you ca
msgstr ""
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr ""
+msgstr "linkedin.com/in/profilename වෙතින් පà·à¶­à·’කඩ නà·à¶¸à¶º"
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
@@ -30496,20 +31026,17 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "%{provider_label} ගිණුම මත පදනම්ව ඔබගේ නම ස්වයංක්â€à¶»à·“යව සකස෠ඇත, එබà·à·€à·’න් ඔබ දන්න෠පුද්ගලයින්ට හඳුනà·à¶œà¶­ à·„à·à¶šà·’ය."
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
msgid "Profiles|username"
-msgstr ""
+msgstr "පරිà·à·“ලක නà·à¶¸à¶º"
msgid "Profiles|your account"
msgstr ""
msgid "Profile|%{job_title} at %{organization}"
-msgstr ""
+msgstr "%{organization} à·„à·’ %{job_title}"
msgid "Profiling - Performance bar"
msgstr ""
@@ -30824,7 +31351,7 @@ msgid "ProjectSelect|Search for project"
msgstr ""
msgid "ProjectSelect|Search projects"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොයන්න"
msgid "ProjectSelect|Select a project"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "අයිඕඑස් (ස්විෆ්ට්)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32333,7 +32920,7 @@ msgid "Quick actions can be used in description and comment boxes."
msgstr ""
msgid "Quick help"
-msgstr ""
+msgstr "ඉක්මන් උදව්"
msgid "Quick range"
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32474,7 +33058,7 @@ msgid "Reconfigure"
msgstr ""
msgid "Recover password"
-msgstr ""
+msgstr "මුරපදය ප්â€à¶»à¶­à·’à·ƒà·à¶°à¶±à¶º"
msgid "Recovery Codes"
msgstr ""
@@ -32539,13 +33123,13 @@ msgid "Regions"
msgstr ""
msgid "Register"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචිය"
msgid "Register / Sign In"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචිය / පිවිසෙන්න"
msgid "Register Two-Factor Authenticator"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶šà¶º සකසන්න"
msgid "Register Universal Two-Factor (U2F) Device"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -32569,7 +33150,7 @@ msgid "Register with two-factor app"
msgstr ""
msgid "Register with:"
-msgstr ""
+msgstr "මෙමගින් ලියà·à¶´à¶¯à·’ංචිය:"
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
@@ -32760,7 +33341,7 @@ msgid "Remediations"
msgstr ""
msgid "Remember me"
-msgstr ""
+msgstr "මතක තබ෠ගන්න"
msgid "Remind later"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33570,7 +34154,7 @@ msgid "Requires you to deploy or set up cloud-hosted Sentry."
msgstr ""
msgid "Requires your primary GitLab email address."
-msgstr ""
+msgstr "ඔබගේ ප්â€à¶»à·à¶®à¶¸à·’ක ගිට්ලà·à¶¶à·Š වි-තà·à¶´à·‘ල අවà·à·Šâ€à¶ºà¶ºà·’."
msgid "Resend"
msgstr ""
@@ -33609,7 +34193,7 @@ msgid "Reset health check access token"
msgstr ""
msgid "Reset password"
-msgstr ""
+msgstr "මුරපදය යළි සකසන්න"
msgid "Reset registration token"
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,11 +34660,14 @@ msgstr "ධà·à·€à¶š සමඟ පටන් ගන්න"
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
msgid "Runners|IP Address"
-msgstr ""
+msgstr "අ.ජà·.කෙ. ලිපිනය"
msgid "Runners|Install a runner"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34468,10 +35079,10 @@ msgid "SSH Key"
msgstr ""
msgid "SSH Keys"
-msgstr ""
+msgstr "SSH යතුරු"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "SSH යතුරු උදව්"
msgid "SSH fingerprints verify that the client is connecting to the correct host. Check the %{config_link_start}current instance configuration%{config_link_end}."
msgstr ""
@@ -34480,7 +35091,7 @@ msgid "SSH host key fingerprints"
msgstr ""
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH සත්කà·à¶»à¶š යතුරු"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
msgstr ""
@@ -34489,7 +35100,7 @@ msgid "SSH key"
msgstr ""
msgid "SSH keys"
-msgstr ""
+msgstr "SSH යතුරු"
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -34546,7 +35157,7 @@ msgid "Save internal note"
msgstr ""
msgid "Save password"
-msgstr ""
+msgstr "මුරපදය සුරකින්න"
msgid "Save pipeline schedule"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34792,9 +35403,12 @@ msgid "Search project"
msgstr ""
msgid "Search projects"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොයන්න"
msgid "Search projects..."
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොයන්න..."
+
+msgid "Search protected branches"
msgstr ""
msgid "Search rate limits"
@@ -34819,7 +35433,7 @@ msgid "Search your project dependencies for their licenses and apply policies."
msgstr ""
msgid "Search your projects"
-msgstr ""
+msgstr "ඔබගේ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොයන්න"
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -35009,10 +35623,10 @@ msgid "SecurityApprovals|Coverage-Check"
msgstr ""
msgid "SecurityApprovals|Learn more about Coverage-Check"
-msgstr ""
+msgstr "ආවරණය-පරීක්â€à·‚à·à·€ ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "SecurityApprovals|Learn more about License-Check"
-msgstr ""
+msgstr "බලපත්â€à¶»à¶º-පරීක්â€à·‚à·à·€ ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "SecurityApprovals|License-Check"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "තවත් +%{count}"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35624,7 +36247,7 @@ msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
-msgstr ""
+msgstr "ඔබගේ උපකරණ පුවරුව පිහිටුවීම ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
@@ -35717,7 +36340,7 @@ msgid "SecurityReports|Select a project to add by using the project search field
msgstr ""
msgid "SecurityReports|Set status"
-msgstr ""
+msgstr "තත්â€à·€à¶º සකසන්න"
msgid "SecurityReports|Severity"
msgstr "තීව්â€à¶»à¶­à·à·€"
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35837,7 +36463,7 @@ msgid "See metrics"
msgstr ""
msgid "See our website for help"
-msgstr ""
+msgstr "උදව් සඳහ෠අපගේ අඩවිය බලන්න"
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,11 +36528,8 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
-msgstr ""
+msgstr "වේල෠කලà·à¶´à¶ºà¶šà·Š තà·à¶»à¶±à·Šà¶±"
msgid "Select all"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36014,7 +36643,7 @@ msgid "Select target project"
msgstr "ඉලක්කගත ව්â€à¶ºà·à¶´à·˜à¶­à·’ය තà·à¶»à¶±à·Šà¶±"
msgid "Select timezone"
-msgstr ""
+msgstr "වේල෠කලà·à¶´à¶º තà·à¶»à¶±à·Šà¶±"
msgid "Select type"
msgstr ""
@@ -36239,7 +36868,7 @@ msgid "Set due date"
msgstr ""
msgid "Set health status"
-msgstr ""
+msgstr "සෞඛ්â€à¶º තත්â€à·€à¶º සකසන්න"
msgid "Set health status to %{health_status}."
msgstr ""
@@ -36257,7 +36886,7 @@ msgid "Set milestone"
msgstr ""
msgid "Set new password"
-msgstr ""
+msgstr "නව මුරපදය සකසන්න"
msgid "Set parent epic to an epic"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr "සූදà·à¶±à¶¸à·Š තත්â€à·€à¶º සකසන්න"
@@ -36364,28 +36996,28 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
-msgstr ""
+msgstr "තත්â€à·€à¶º මකන්න"
msgid "SetStatusModal|Clear status after"
+msgstr "තත්â€à·€à¶º මක෠දà·à¶¸à·“ම"
+
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
msgstr ""
msgid "SetStatusModal|Edit status"
-msgstr ""
+msgstr "තත්â€à·€à¶º සංස්කරණය"
msgid "SetStatusModal|Remove status"
-msgstr ""
+msgstr "තත්â€à·€à¶º ඉවත් කරන්න"
msgid "SetStatusModal|Set a status"
-msgstr ""
+msgstr "තත්â€à·€à¶ºà¶šà·Š සකසන්න"
msgid "SetStatusModal|Set status"
+msgstr "තත්â€à·€à¶º සකසන්න"
+
+msgid "SetStatusModal|Set yourself as busy"
msgstr ""
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
@@ -36395,7 +37027,7 @@ msgid "SetStatusModal|Status updated"
msgstr ""
msgid "SetStatusModal|What's your status?"
-msgstr ""
+msgstr "ඔබගේ තත්â€à·€à¶º කුමක්ද?"
msgid "SetStatusModal|Your status resets on %{date}."
msgstr ""
@@ -36747,10 +37379,10 @@ msgid "Sidekiq job size limits"
msgstr ""
msgid "Sign in"
-msgstr ""
+msgstr "පිවිසෙන්න"
msgid "Sign in / Register"
-msgstr ""
+msgstr "පිවිසෙන්න / ලියà·à¶´à¶¯à·’ංචිය"
msgid "Sign in as a user with the matching email address, add the email to this account, or sign-up for a new account using the matching email."
msgstr ""
@@ -36759,19 +37391,19 @@ msgid "Sign in preview"
msgstr ""
msgid "Sign in to \"%{group_name}\""
-msgstr ""
+msgstr "“%{group_name}†වෙත පිවිසෙන්න"
msgid "Sign in to GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත පිවිසෙන්න"
msgid "Sign in using smart card"
msgstr ""
msgid "Sign in via 2FA code"
-msgstr ""
+msgstr "2FA කේතය මගින් පිවිසෙන්න"
msgid "Sign in with"
-msgstr ""
+msgstr "මෙමගින් පිවිසෙන්න"
msgid "Sign in with Single Sign-On"
msgstr ""
@@ -36780,37 +37412,37 @@ msgid "Sign in with smart card"
msgstr ""
msgid "Sign in/Sign up pages"
-msgstr ""
+msgstr "පිවිසීම / ලියà·à¶´à¶¯à·’ංචිය පිටු"
msgid "Sign out"
-msgstr ""
+msgstr "නික්මෙන්න"
msgid "Sign out & Register"
-msgstr ""
+msgstr "නික්මෙන්න හ෠ලියà·à¶´à¶¯à·’ංචිය"
msgid "Sign up"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචිය"
msgid "Sign up now"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචි වන්න"
msgid "Sign up was successful! Please confirm your email to sign in."
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචි වීම à·ƒà·à¶»à·Šà¶®à¶š විය! පිවිසීමට ඔබගේ වි-තà·à¶´à·‘ල තහවුරු කරන්න."
msgid "Sign-in and Help page"
-msgstr ""
+msgstr "පිවිසෙන්න හ෠උපකà·à¶» පිටුව"
msgid "Sign-in count:"
-msgstr ""
+msgstr "පිවිසුම් ගණන:"
msgid "Sign-in failed because %{error}."
-msgstr ""
+msgstr "%{error} නිස෠පිවිසීමට අසමත් විය."
msgid "Sign-in page"
-msgstr ""
+msgstr "පිවිසෙන පිටුව"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "පිවිසුම් සීමà·"
msgid "Sign-in text"
msgstr ""
@@ -36822,52 +37454,52 @@ msgid "Sign-out page URL"
msgstr ""
msgid "Sign-up restrictions"
-msgstr ""
+msgstr "ලියà·à¶´à¶¯à·’ංචි සීමà·"
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the GitLab%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "%{button_text} එබීමෙන් හ෠තෙවන පà·à¶»à·Šà·à·Šà·€à¶ºà¶šà·Š හරහ෠ලියà·à¶´à¶¯à·’ංචි වීමෙන් ඔබ ගිට්ලà·à¶¶à·Š %{link_start}භà·à·€à·’තà·à·€à·š නියම මෙන්ම රහස්â€à¶ºà¶­à· ප්â€à¶»à¶­à·’පත්තිය සහ දත්තකඩ ප්â€à¶»à¶­à·’පත්තිය%{link_end} පිළිගනියි."
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "%{button_text} එබීමෙන් හ෠තෙවන පà·à¶»à·Šà·à·Šà·€à¶ºà¶šà·Š හරහ෠ලියà·à¶´à¶¯à·’ංචි වීමෙන් ඔබ %{link_start}භà·à·€à·’තà·à·€à·š නියම මෙන්ම රහස්â€à¶ºà¶­à· ප්â€à¶»à¶­à·’පත්තිය සහ දත්තකඩ ප්â€à¶»à¶­à·’පත්තිය%{link_end} පිළිගනියි."
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
-msgstr ""
+msgstr "%{button_text} එබීමෙන්, මම %{link_start}භà·à·€à·’තà·à·€à·š නියම සහ රහස්â€à¶ºà¶­à· ප්â€à¶»à¶­à·’පත්තිය%{link_end} කියව෠පිළිගත් බවට ප්â€à¶»à¶­à·’ඥ෠දෙමි."
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
-msgstr ""
+msgstr "%{button_text} එබීමෙන්, මම ගිට්ලà·à¶¶à·Š %{link_start}භà·à·€à·’තà·à·€à·š නියම සහ රහස්â€à¶ºà¶­à· ප්â€à¶»à¶­à·’පත්තිය%{link_end} කියව෠පිළිගත් බවට ප්â€à¶»à¶­à·’ඥ෠දෙමි."
msgid "SignUp|By signing in you accept the %{link_start}Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}."
-msgstr ""
+msgstr "පිවිසීමෙන් ඔබ %{link_start}භà·à·€à·’තà·à·€à·š නියම මෙන්ම රහස්â€à¶ºà¶­à· ප්â€à¶»à¶­à·’පත්තිය සහ දත්තකඩ ප්â€à¶»à¶­à·’පත්තිය%{link_end} පිළිගනියි."
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "මුල් නම දිග à·€à·à¶©à·’යි (උපරිම අකුරු ගණන %{max_length} කි)."
msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "අග නම දිග à·€à·à¶©à·’යි (උපරිම අකුරු ගණන %{max_length} කි)."
msgid "SignUp|Minimum length is %{minimum_password_length} characters."
-msgstr ""
+msgstr "අවම දිග අකුරු %{minimum_password_length} කි."
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
-msgstr ""
+msgstr "නම දිග à·€à·à¶©à·’යි (උපරිම අකුරු ගණන %{max_length} කි)."
msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
-msgstr ""
+msgstr "නම ඉත෠කෙටිය (අවම අකුරු ගණන %{min_length} කි)."
msgid "Signed in"
msgstr ""
msgid "Signed in to GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත පිවිසෙන්න"
msgid "Signed in to GitLab as %{user_link}"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත %{user_link} ලෙස පිවිස ඇත"
msgid "Signed in with %{authentication} authentication"
msgstr ""
msgid "Signing in using %{label} has been disabled"
-msgstr ""
+msgstr "%{label} භà·à·€à·’තයෙන් පිවිසීම අබල කර ඇත"
msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
msgstr ""
@@ -36906,7 +37538,7 @@ msgid "Skipped deployment to"
msgstr ""
msgid "Skype:"
-msgstr ""
+msgstr "ස්කයිප්:"
msgid "Slack application"
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37086,7 +37754,7 @@ msgid "Someone edited this test case at the same time you did. The description h
msgstr ""
msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
-msgstr ""
+msgstr "යමෙක්, බොහà·à·€à·’ට ඔබ, %{link_to_gitlab} à·„à·’ ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුමේ මුරපදය යළි පිහිටුවීමට ඉල්ල෠ඇත."
msgid "Something went wrong"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr "අවහිරය"
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr "කොළ තිරය"
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr "රà·à·ƒ රතු"
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr "යà·à¶¢à¶±à·à·€ සොයà·à¶œà¶­ නොහà·à¶šà·’ බà·à·€à·’න් යà·à¶¢à¶±à·à·€ අදà·à·… නොවේ."
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr "යà·à¶¢à¶±à· එකක් හ෠කිහිපයක් හමු නොවූ බà·à·€à·’න් යà·à¶¢à¶±à· අදà·à·… නොවේ."
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr "අය කළ à·„à·à¶šà·’ පුද්ගලයින්"
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,26 +39180,38 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šà·€ විස්තර ඉක්මනින් සමමුහූර්ත වනු ඇත."
-msgid "SuperSonics|Your subscription is expired."
-msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º කල් ඉකුත් වී ඇත."
+msgid "SuperSonics|Your subscription is expired"
+msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ සක්â€à¶»à·’ය කර ඇත. ඔබට පහත විස්තර බà·à¶½à·“මට à·„à·à¶šà·’ය."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr "සුපිරික්සීම à·ƒà·à¶¯à· ඇත."
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr "කිසිදු දත්තයක් නà·à¶­."
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr "කිසිදු වගුවක දත්ත නොතිබේ."
@@ -40118,7 +40825,7 @@ msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
+msgstr "අභියà·à¶œà¶ºà·™à·„à·’ දà·à·‚යක් මතු විය. කරුණà·à¶šà¶» අභියà·à¶œà¶º නà·à·€à¶­ විසඳන්න."
msgid "These dates affect how your epics appear in the roadmap. Set a fixed date or one inherited from the milestones assigned to issues in this epic."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr "මෙම අක්තපත්â€à¶»à¶º කල් ඉකුත්ය"
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "මෙය ඔබගේ වත්මන් à·€à·à¶»à¶ºà¶ºà·’"
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය %{date} දී මකනු ඇත"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41139,22 +41891,22 @@ msgid "To find the state of this project's repository at the time of any of thes
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
-msgstr ""
+msgstr "ඔබගේ ගිණුම තවදුරටත් ආරක්â€à·‚෠කිරීම සඳහà·, %{mfa_link_start}ද්වි à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±%{mfa_link_end} ක්â€à¶»à¶¸à¶ºà¶šà·Š පිහිටුවීමට බලන්න."
msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
-msgstr ""
+msgstr "ඔබගේ ගිණුම තවදුරටත් ආරක්â€à·‚෠කිරීම සඳහà·, ද්වි à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶± ක්â€à¶»à¶¸à¶ºà¶šà·Š පිහිටුවන්න: %{mfa_link}."
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
msgid "To get started, click the link below to confirm your account."
-msgstr ""
+msgstr "පහත සබà·à¶³à·’ය එබීමෙන් ගිණුම තහවුරු කර පටන් ගන්න."
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
msgid "To get started, use the link below to confirm your account."
-msgstr ""
+msgstr "පහත සබà·à¶³à·’ය භà·à·€à·’තයෙන් ගිණුම තහවුරු කර පටන් ගන්න."
msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
@@ -41259,7 +42011,7 @@ msgid "To widen your search, change or remove filters above."
msgstr ""
msgid "To-Do List"
-msgstr "කළ යුතු ලේඛනය"
+msgstr "කළ-යුතු ලේඛනය"
msgid "To-do item successfully marked as done."
msgstr ""
@@ -41268,7 +42020,7 @@ msgid "Today"
msgstr "අද"
msgid "Todos count"
-msgstr "කළ යුතු ගණන"
+msgstr "කළ-යුතු ගණන"
msgid "Todos|Are you looking for things to do? Take a look at %{strongStart}%{openIssuesLinkStart}open issues%{openIssuesLinkEnd}%{strongEnd}, contribute to %{strongStart}%{mergeRequestLinkStart}a merge request%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd}, or mention someone in a comment to automatically assign them a new to-do item."
msgstr ""
@@ -41313,7 +42065,7 @@ msgid "Todos|When an issue or merge request is assigned to you, or when you rece
msgstr ""
msgid "Todos|You're all done!"
-msgstr ""
+msgstr "සියල්ල අහවරයි!"
msgid "Todos|Your To-Do List shows what to work on next"
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41415,7 +42161,7 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr "බොහ෠පරිà·à·“ලකයින් හමු විය. ඉක්මන් ක්â€à¶»à·’යà·à¶¸à·à¶»à·Šà¶œ බොහ෠දුරට %{max_count} දෙනෙකුට සීම෠වේ"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "ගවේà·à¶±à¶º"
msgid "TopNav|Go back"
msgstr "ආපසු යන්න"
@@ -41454,7 +42200,7 @@ msgid "TopicSelect|No matching results"
msgstr ""
msgid "TopicSelect|Search topics"
-msgstr ""
+msgstr "මà·à¶­à·˜à¶šà· සොයන්න"
msgid "TopicSelect|Select a topic"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr "මුළු මතකය (ගි.බ.)"
@@ -41609,9 +42358,6 @@ msgstr "දවස් %{daysUsed}/%{duration}"
msgid "Trials|Go back to GitLab"
msgstr "ගිට්ලà·à¶¶à·Š වෙත ආපසු යන්න"
-msgid "Trials|Hey there"
-msgstr "ආයුබà·"
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -41805,7 +42556,7 @@ msgid "Type"
msgstr "වර්ගය"
msgid "Type to search"
-msgstr ""
+msgstr "සෙවීමට ලියන්න"
msgid "U2F Devices (%{length})"
msgstr "U2F උපà·à¶‚ග (%{length})"
@@ -42308,6 +43059,9 @@ msgstr "උදව් සබà·à¶³à·’ය %{linkTitle}"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr "පරà·à¶ºà¶­à·Šà¶­ ප්â€à¶»à¶­à·’යුක්තය"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr "කà·à·‚්ඨය"
msgid "UsageQuota|Seats"
msgstr "ආසන"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42702,7 +43453,7 @@ msgid "Use one line per URI"
msgstr ""
msgid "Use primary email (%{email})"
-msgstr "ප්â€à¶»à·à¶®à¶¸à·’ක වි-තà·à¶´à·‘ල භà·à·€à·’ත෠කරන්න (%{email})"
+msgstr "ප්â€à¶»à·à¶®à¶¸à·’ක තà·à¶´à·‘ල යොද෠ගන්න (%{email})"
msgid "Use shortcuts"
msgstr "කෙටිමං භà·à·€à·’ත෠කරන්න"
@@ -42805,6 +43556,9 @@ msgstr "පරිà·à·“ලකයà·à¶œà·š අනන්â€à¶ºà¶­à·à·€à¶º à·ƒà·à
msgid "User identity was successfully updated."
msgstr "පරිà·à·“ලකයà·à¶œà·š අනන්â€à¶ºà¶­à·à·€à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42953,7 +43707,7 @@ msgid "UserProfile|Contributed projects"
msgstr "දà·à¶ºà¶š වූ ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "UserProfile|Copy user ID"
-msgstr ""
+msgstr "පරිà·à·“ලක à·„à·à¶³à·”. පිටපතක්"
msgid "UserProfile|Edit profile"
msgstr "පà·à¶­à·’කඩ සංස්කරණය"
@@ -42962,10 +43716,10 @@ msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶ºà¶§ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොය෠ගà·à¶±à·“මට ප්â€à¶»à·ƒà·’ද්ධ සමූහ ගවේෂණය කරන්න."
msgid "UserProfile|Followers"
-msgstr ""
+msgstr "අනුගà·à¶¸à·’කයින්"
msgid "UserProfile|Following"
-msgstr ""
+msgstr "අනුගමනය"
msgid "UserProfile|Groups"
msgstr "සමූහ"
@@ -43013,7 +43767,7 @@ msgid "UserProfile|Subscribe"
msgstr "දà·à¶ºà¶š වන්න"
msgid "UserProfile|This user doesn't have any followers."
-msgstr ""
+msgstr "මෙම පරිà·à·“ලකයà·à¶§ අනුගà·à¶¸à·’කයින් නà·à¶­."
msgid "UserProfile|This user doesn't have any personal projects"
msgstr "මෙම පරිà·à·“ලකයà·à¶§ කිසිදු පෞද්ගලික ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් නà·à¶­"
@@ -43031,13 +43785,13 @@ msgid "UserProfile|This user is blocked"
msgstr "මෙම පරිà·à·“ලකය෠අවහිර කර ඇත"
msgid "UserProfile|This user isn't following other users."
-msgstr ""
+msgstr "මෙම පුද්ගලය෠වෙනත් පරිà·à·“ලකයින් අනුගමනය නොකරයි."
msgid "UserProfile|Unconfirmed user"
msgstr "තහවුරු නොකළ පරිà·à·“ලක"
msgid "UserProfile|User ID: %{id}"
-msgstr ""
+msgstr "පරිà·à·“ලක à·„à·à¶³à·”.: %{id}"
msgid "UserProfile|View all"
msgstr "සියල්ල දකින්න"
@@ -43046,13 +43800,13 @@ msgid "UserProfile|View user in admin area"
msgstr ""
msgid "UserProfile|You are not following other users."
-msgstr ""
+msgstr "ඔබ වෙනත් පරිà·à·“ලකයින් අනුගමනය නොකරයි."
msgid "UserProfile|You can create a group for several dependent projects."
msgstr ""
msgid "UserProfile|You do not have any followers."
-msgstr ""
+msgstr "ඔබට අනුගà·à¶¸à·’කයින් නà·à¶­."
msgid "UserProfile|You haven't created any personal projects."
msgstr "ඔබ කිසිදු පෞද්ගලික ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් à·ƒà·à¶¯à· නà·à¶­."
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr "අනුපà·à¶­ සීමà·à·€à·™à¶±à·Š බà·à·„à·à¶» කිරීමට පරිà·à·“ලකයින්"
-msgid "Users were successfully added."
-msgstr "පුද්ගලයින් à·ƒà·à¶»à·Šà¶®à¶šà·€ එක් කෙරිණි."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr "ප්â€à¶»à¶½à·šà¶›à¶±à¶º බලන්න"
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "ගොනුව"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr "ගිට්ලà·à¶¶à·Š ආරක්â€à·‚ණ à·€à·à¶»à·Šà¶­à·à·€"
@@ -43876,12 +44660,12 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "සබà·à¶³à·’"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr "ක්â€à¶»à¶¸à¶º"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr "හඳුන්වන පේළිය ඉවතලන්න "
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "තීව්â€à¶»à¶­à·à·€"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "තත්â€à·€à¶º"
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr "මෙවලම"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr "අසංà·à·à¶°à·’ත ප්â€à¶»à¶­à·’චà·à¶»à¶º"
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr "අපට ප්â€à¶»à·à¶¸à·’තියස් සේවà·à¶¯à·à¶ºà¶šà
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "SSL තහවුරුව සබල කරන්න"
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "à·ƒà·à¶¸à·à¶¢à·’ක සිදුවීම්"
@@ -44260,6 +45071,12 @@ msgstr "SSL තහවුරුව"
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "උපසමූහ සිදුවීම්"
@@ -44284,6 +45101,9 @@ msgstr "ඒ.ස.නි."
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44457,17 +45277,11 @@ msgid "Who will be using this group?"
msgstr "මෙම සමූහය භà·à·€à·’ත෠කරන්නේ කවුද?"
msgid "Why are you signing up? (optional)"
-msgstr ""
+msgstr "ඔබ ලියà·à¶´à¶¯à·’ංචි වන්නේ ඇයි? (විකල්ප)"
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr "කà·à¶»à·Šà¶ºà¶ºà¶šà·Š à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45004,7 +45833,7 @@ msgid "You are receiving this message because you are a GitLab administrator for
msgstr ""
msgid "You are signed in to GitLab as:"
-msgstr "ලෙස ගිට්ලà·à¶¶à·Š වෙත ඇතුළුව ඇත:"
+msgstr "මෙලෙස ගිට්ලà·à¶¶à·Š වෙත ඇතුළු වී ඇත:"
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr "ඔබට නව %{link} සෑදීමට à·„à·à¶šà·’ය."
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr "ගිට්ලà·à¶¶à·Š à·„à·’ à·ƒà·à¶¸à¶­à·à¶± සෙවීමට ඇතුළු වී සිටිය යුතුය"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45527,7 +46365,7 @@ msgid "You're not allowed to make changes to this project directly. A fork of th
msgstr ""
msgid "You're receiving this email because of your account on %{host}."
-msgstr "ඔබට මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à¶±à·Šà¶±à·š %{host} à·„à·’ ගිණුම නිසà·à¶º."
+msgstr "මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à¶±à·Šà¶±à·š %{host} à·„à·’ ගිණුම නිසà·à¶º."
msgid "You're receiving this email because of your account on %{host}. %{manage_label_subscriptions_link_start}Manage label subscriptions%{manage_label_subscriptions_link_end} &middot; %{help_link_start}Help%{help_link_end}"
msgstr "ඔබට මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à¶±à·Šà¶±à·š %{host} à·„à·’ ඔබගේ ගිණුම නිසà·à¶º. %{manage_label_subscriptions_link_start}නම්පත් දà·à¶ºà¶šà¶­à·Šâ€à·€ කළමනà·à¶šà¶»à¶«à¶º%{manage_label_subscriptions_link_end} &middot; %{help_link_start}උදව්%{help_link_end}"
@@ -45822,7 +46660,7 @@ msgid "Your new comment"
msgstr "ඔබගේ නව අදහස"
msgid "Your password"
-msgstr ""
+msgstr "ඔබගේ මුරපදය"
msgid "Your password reset token has expired."
msgstr ""
@@ -45993,6 +46831,9 @@ msgstr "එකතු කෙරිණි"
msgid "added %{emails}"
msgstr "%{emails} එක් කළà·"
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr "අතීත දිනයක් විය නොහà·à¶šà·’ය"
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "වෙනස් කළ නොහà·à¶šà·’ය"
@@ -46392,6 +47239,9 @@ msgstr "%{issuesWithCount} හමුවිය"
msgid "ciReport|Full Report"
msgstr "පූර්ණ à·€à·à¶»à·Šà¶­à·à·€"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr "IaC සුපිරික්සමින්"
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr "අදහස"
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46739,7 +47595,7 @@ msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
msgid "following"
-msgstr ""
+msgstr "අනුගමනය"
msgid "for"
msgstr "සදහà·"
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr "ඉඩ නොදේ. ඔබගේ à·ƒà·à¶¸à·à¶±à·Šâ€à¶º වි-තà·à¶´à·‘ල භà·à·€à·’ත෠කරන්න."
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr "lfs වස්තූන්"
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr "කෙසේ හ෠පූරණය"
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47284,7 +48145,7 @@ msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
msgid "mrWidget|Merging! We're almost there…"
-msgstr ""
+msgstr "සංයුක්ත වෙමින්…"
msgid "mrWidget|More information"
msgstr "තව තොරතුරු"
@@ -47412,6 +48273,9 @@ msgstr "කà·à·‚්ඨයක් තිබිය යුතුය"
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "මà·à¶œà·š-සමූහය"
@@ -47493,9 +48357,6 @@ msgstr "à·„à·"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr "ඉවත් කර ඇත"
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "අනන්â€à¶ºà¶±à¶ºà·š නම"
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr "උඩුගත කිරීම්"
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "පරිà·à·“ලක ප්â€à¶»à¶­à·’රූපය"
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 4e16188b54b..7ec8eab02b6 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1210,13 +1217,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1925,9 +1941,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 241db225abd..642dd8a06d1 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1210,13 +1217,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1300,9 +1307,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1336,6 +1340,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1357,10 +1364,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1384,6 +1394,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1925,9 +1941,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2627,12 +2649,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -3041,6 +3063,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3149,9 +3180,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3338,6 +3381,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3677,9 +3723,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -4106,6 +4164,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4181,6 +4242,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4469,9 +4533,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4719,6 +4780,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4946,6 +5010,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5605,6 +5672,9 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6278,6 +6348,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6599,7 +6672,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6639,6 +6712,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6963,6 +7039,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6999,33 +7078,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -7035,6 +7159,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7510,6 +7649,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7519,7 +7661,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7780,7 +7922,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7975,6 +8117,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -9094,6 +9242,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -9131,6 +9285,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9197,6 +9354,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9867,6 +10027,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9972,6 +10135,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -10041,7 +10207,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10359,6 +10525,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10821,13 +10990,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11367,6 +11539,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11379,6 +11554,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12824,6 +13011,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13319,6 +13512,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13385,6 +13584,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13587,18 +13795,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,25 +13868,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13708,7 +13904,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13729,12 +13925,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14285,6 +14475,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14651,6 +14853,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15257,6 +15462,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15314,6 +15525,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18976,6 +19229,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19192,7 +19448,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19576,7 +19841,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,16 +20454,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20195,10 +20496,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20473,6 +20786,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20497,6 +20813,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21404,6 +21723,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21627,6 +21949,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21687,12 +22012,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22294,6 +22625,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23700,7 +24040,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,10 +24895,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24639,9 +24982,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -26041,6 +26399,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26329,6 +26693,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26547,6 +26914,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27440,6 +27867,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27449,15 +27882,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27470,12 +27939,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27536,6 +28026,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28505,15 +29004,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28613,13 +29115,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,7 +29251,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29380,15 +29894,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29503,6 +30029,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -30193,6 +30728,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30253,6 +30791,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30364,6 +30905,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30577,15 +31121,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30616,9 +31151,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30868,9 +31403,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30916,9 +31448,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31408,6 +31937,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31603,6 +32144,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32368,6 +32915,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32404,6 +32954,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34524,6 +35116,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34666,7 +35264,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34717,6 +35318,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -35018,9 +35631,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -35168,6 +35778,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35255,6 +35868,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36457,6 +37085,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36769,6 +37400,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36868,6 +37499,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37473,6 +38107,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37881,6 +38557,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38781,7 +39460,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40405,9 +41117,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -41146,6 +41882,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42858,10 +43616,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,7 +43727,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43315,6 +44070,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,7 +44412,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43943,7 +44728,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,10 +45180,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44407,6 +45195,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -45222,6 +46040,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45256,9 +46080,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46627,6 +47472,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr ""
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -48219,6 +49086,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48427,6 +49307,13 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 9a41ad24ce8..f44da24dc42 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 24e5e42c6ae..d05e2e90d0e 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -151,6 +151,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1117,12 +1123,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1165,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1198,9 +1204,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1234,6 +1237,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1255,10 +1261,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1282,6 +1291,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1795,9 +1810,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1816,6 +1828,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2497,12 +2518,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2896,9 +2911,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2911,6 +2932,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2932,6 +2956,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2968,6 +2995,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3019,9 +3049,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3208,6 +3250,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3547,9 +3592,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3976,6 +4033,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4051,6 +4111,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4339,9 +4402,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4588,6 +4648,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4813,6 +4876,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5464,6 +5530,9 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6136,6 +6205,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6457,7 +6529,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6496,6 +6568,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6817,6 +6892,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6853,33 +6931,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6889,6 +7012,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7189,6 +7324,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7363,6 +7501,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7372,7 +7513,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7633,7 +7774,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7828,6 +7969,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8845,6 +8989,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8944,6 +9091,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8971,6 +9121,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8980,6 +9133,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9046,6 +9202,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9715,6 +9874,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9820,6 +9982,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9889,7 +10054,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10207,6 +10372,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10666,13 +10834,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10996,6 +11164,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11212,6 +11383,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11224,6 +11398,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12481,6 +12661,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12667,6 +12853,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12811,6 +13000,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13156,6 +13348,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13201,6 +13396,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13222,6 +13420,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13237,6 +13438,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13423,18 +13630,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13504,25 +13702,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13543,7 +13738,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13564,12 +13759,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14116,6 +14305,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14482,6 +14683,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14620,9 +14824,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14740,6 +14941,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15088,6 +15292,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15121,6 +15328,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15145,6 +15355,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16246,9 +16459,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16933,6 +17143,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17062,15 +17275,48 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17335,6 +17581,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17674,6 +17923,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17896,9 +18148,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18763,6 +19012,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18799,6 +19051,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19015,7 +19270,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19360,6 +19615,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19378,6 +19639,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19399,7 +19663,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19447,6 +19711,9 @@ msgstr[2] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19492,7 +19759,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19927,24 +20194,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19984,16 +20272,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20005,6 +20299,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20014,10 +20314,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20098,6 +20401,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20107,6 +20416,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20290,6 +20602,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20314,6 +20629,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21220,6 +21538,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21442,6 +21763,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21502,12 +21826,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21520,6 +21850,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21712,9 +22045,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22108,6 +22438,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22207,6 +22543,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22579,9 +22918,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23431,6 +23767,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23512,7 +23851,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24307,6 +24646,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24358,10 +24700,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24445,9 +24787,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24457,9 +24814,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24472,7 +24826,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24709,6 +25063,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25843,6 +26200,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25867,6 +26227,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26131,6 +26494,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26347,6 +26713,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26848,6 +27217,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27139,33 +27511,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27187,12 +27592,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27211,6 +27634,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27235,6 +27661,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27244,15 +27676,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27265,12 +27733,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27331,6 +27820,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27493,6 +27985,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28054,6 +28549,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28297,15 +28795,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28372,6 +28870,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28405,13 +28906,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28426,6 +28927,9 @@ msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28477,10 +28981,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28537,7 +29041,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28753,9 +29257,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29158,9 +29659,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29170,15 +29683,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29293,6 +29818,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29974,6 +30505,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29983,6 +30517,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30043,6 +30580,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30154,6 +30694,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30367,15 +30910,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30388,9 +30925,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30406,9 +30940,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30421,6 +30952,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30658,9 +31192,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30706,9 +31237,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31198,6 +31726,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31228,6 +31759,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31351,12 +31885,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31393,6 +31933,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31546,7 +32089,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31636,6 +32179,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32158,6 +32704,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32194,6 +32743,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32218,6 +32770,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32374,6 +32929,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32443,18 +33001,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32605,9 +33193,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32764,9 +33349,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33658,6 +34240,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34048,6 +34633,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34069,6 +34657,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34297,6 +34888,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34330,9 +34924,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34342,6 +34933,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34411,6 +35005,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34438,7 +35035,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34489,6 +35089,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34501,6 +35104,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34531,6 +35137,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34570,6 +35179,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34789,9 +35401,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34939,6 +35548,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35026,6 +35638,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35341,13 +35956,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35404,9 +36019,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35809,6 +36421,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35821,6 +36436,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35851,12 +36469,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35974,6 +36598,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36097,9 +36724,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36145,9 +36769,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36169,9 +36790,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36217,6 +36844,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36529,6 +37159,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36604,18 +37237,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36628,6 +37258,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37231,6 +37864,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37297,6 +37963,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37537,6 +38206,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37579,6 +38251,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37639,6 +38314,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38539,7 +39217,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38563,9 +39241,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38602,7 +39292,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38611,7 +39307,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38728,25 +39424,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39946,6 +40654,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40153,9 +40864,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40423,9 +41131,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40489,6 +41194,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40534,6 +41242,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40582,6 +41293,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40678,6 +41410,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40894,6 +41629,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40906,12 +41644,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40999,6 +41743,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41344,6 +42091,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41377,6 +42127,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41596,9 +42349,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41620,9 +42370,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41734,6 +42481,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41863,9 +42613,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41881,6 +42628,12 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
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 ""
@@ -42562,6 +43315,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42604,10 +43360,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42682,9 +43438,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42718,7 +43471,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43060,6 +43813,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43381,9 +44137,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43402,7 +44155,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43663,6 +44443,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43687,7 +44470,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44113,6 +44896,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44134,10 +44920,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44149,6 +44935,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44176,6 +44965,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44188,6 +44980,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44200,6 +44995,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44263,6 +45061,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44473,6 +45277,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44488,12 +45295,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44518,6 +45331,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44542,6 +45361,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44722,12 +45544,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44962,6 +45778,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44995,9 +45817,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45064,6 +45892,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45328,6 +46159,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45451,6 +46288,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45652,7 +46492,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45670,7 +46510,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46261,6 +47101,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46357,6 +47200,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46402,6 +47248,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46666,6 +47515,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46825,6 +47677,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46870,6 +47725,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47197,9 +48055,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47290,6 +48145,12 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "load it anyway"
msgstr ""
@@ -47329,6 +48190,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47698,6 +48562,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47779,9 +48646,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47929,6 +48793,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47962,6 +48829,12 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48070,6 +48943,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48136,6 +49012,12 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 94dcd2c7a51..e70bc29509a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -151,6 +151,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1117,12 +1123,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1165,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1198,9 +1204,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1234,6 +1237,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1255,10 +1261,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1282,6 +1291,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1795,9 +1810,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1816,6 +1828,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2497,12 +2518,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2896,9 +2911,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2911,6 +2932,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2932,6 +2956,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2968,6 +2995,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -3019,9 +3049,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3208,6 +3250,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3547,9 +3592,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3976,6 +4033,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -4051,6 +4111,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4339,9 +4402,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4588,6 +4648,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4813,6 +4876,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5464,6 +5530,9 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -6136,6 +6205,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6457,7 +6529,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6496,6 +6568,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6817,6 +6892,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6853,33 +6931,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6889,6 +7012,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7189,6 +7324,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7363,6 +7501,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7372,7 +7513,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7633,7 +7774,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7828,6 +7969,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8845,6 +8989,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8944,6 +9091,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8971,6 +9121,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8980,6 +9133,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -9046,6 +9202,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9715,6 +9874,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9820,6 +9982,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9889,7 +10054,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10207,6 +10372,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10666,13 +10834,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10996,6 +11164,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11212,6 +11383,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11224,6 +11398,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12481,6 +12661,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12667,6 +12853,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12811,6 +13000,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -13156,6 +13348,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13201,6 +13396,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13222,6 +13420,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13237,6 +13438,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13423,18 +13630,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13504,25 +13702,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13543,7 +13738,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13564,12 +13759,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -14116,6 +14305,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14482,6 +14683,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14620,9 +14824,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14740,6 +14941,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -15088,6 +15292,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15121,6 +15328,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -15145,6 +15355,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16246,9 +16459,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16933,6 +17143,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17062,15 +17275,48 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17335,6 +17581,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17674,6 +17923,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17896,9 +18148,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18763,6 +19012,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18799,6 +19051,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -19015,7 +19270,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19360,6 +19615,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19378,6 +19639,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19399,7 +19663,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19447,6 +19711,9 @@ msgstr[2] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19492,7 +19759,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19927,24 +20194,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19984,16 +20272,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -20005,6 +20299,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -20014,10 +20314,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -20098,6 +20401,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20107,6 +20416,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20290,6 +20602,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20314,6 +20629,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21220,6 +21538,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21442,6 +21763,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21502,12 +21826,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21520,6 +21850,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21712,9 +22045,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -22108,6 +22438,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22207,6 +22543,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22579,9 +22918,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23431,6 +23767,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23512,7 +23851,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24307,6 +24646,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24358,10 +24700,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24445,9 +24787,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24457,9 +24814,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24472,7 +24826,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24709,6 +25063,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25843,6 +26200,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25867,6 +26227,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -26131,6 +26494,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26347,6 +26713,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26848,6 +27217,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -27139,33 +27511,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27187,12 +27592,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27211,6 +27634,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27235,6 +27661,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27244,15 +27676,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27265,12 +27733,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27331,6 +27820,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27493,6 +27985,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28054,6 +28549,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28297,15 +28795,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28372,6 +28870,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28405,13 +28906,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28426,6 +28927,9 @@ msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28477,10 +28981,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28537,7 +29041,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28753,9 +29257,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29158,9 +29659,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -29170,15 +29683,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29293,6 +29818,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29974,6 +30505,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29983,6 +30517,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -30043,6 +30580,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -30154,6 +30694,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30367,15 +30910,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30388,9 +30925,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30406,9 +30940,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30421,6 +30952,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30658,9 +31192,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30706,9 +31237,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31198,6 +31726,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31228,6 +31759,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31351,12 +31885,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31393,6 +31933,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31546,7 +32089,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31636,6 +32179,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -32158,6 +32704,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -32194,6 +32743,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32218,6 +32770,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32374,6 +32929,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32443,18 +33001,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32605,9 +33193,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32764,9 +33349,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33658,6 +34240,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34048,6 +34633,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34069,6 +34657,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34297,6 +34888,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34330,9 +34924,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34342,6 +34933,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34411,6 +35005,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34438,7 +35035,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34489,6 +35089,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34501,6 +35104,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34531,6 +35137,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34570,6 +35179,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34789,9 +35401,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34939,6 +35548,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -35026,6 +35638,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35341,13 +35956,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35404,9 +36019,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35809,6 +36421,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35821,6 +36436,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35851,12 +36469,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35974,6 +36598,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36097,9 +36724,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -36145,9 +36769,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -36169,9 +36790,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -36217,6 +36844,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36529,6 +37159,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36604,18 +37237,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36628,6 +37258,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -37231,6 +37864,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37297,6 +37963,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37537,6 +38206,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37579,6 +38251,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37639,6 +38314,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38539,7 +39217,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38563,9 +39241,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38602,7 +39292,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38611,7 +39307,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38728,25 +39424,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39946,6 +40654,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -40153,9 +40864,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40423,9 +41131,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40489,6 +41194,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40534,6 +41242,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40582,6 +41293,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40678,6 +41410,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40894,6 +41629,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40906,12 +41644,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40999,6 +41743,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41344,6 +42091,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41377,6 +42127,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41596,9 +42349,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41620,9 +42370,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41734,6 +42481,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41863,9 +42613,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41881,6 +42628,12 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
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 ""
@@ -42562,6 +43315,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42604,10 +43360,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42682,9 +43438,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42718,7 +43471,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -43060,6 +43813,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43381,9 +44137,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43402,7 +44155,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43663,6 +44443,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43687,7 +44470,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -44113,6 +44896,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44134,10 +44920,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -44149,6 +44935,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44176,6 +44965,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -44188,6 +44980,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44200,6 +44995,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44263,6 +45061,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44473,6 +45277,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44488,12 +45295,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44518,6 +45331,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44542,6 +45361,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44722,12 +45544,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44962,6 +45778,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44995,9 +45817,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45064,6 +45892,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45328,6 +46159,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45451,6 +46288,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45652,7 +46492,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45670,7 +46510,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46261,6 +47101,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46357,6 +47200,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46402,6 +47248,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46666,6 +47515,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46825,6 +47677,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46870,6 +47725,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47197,9 +48055,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47290,6 +48145,12 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "load it anyway"
msgstr ""
@@ -47329,6 +48190,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47698,6 +48562,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47779,9 +48646,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47929,6 +48793,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47962,6 +48829,12 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -48070,6 +48943,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -48136,6 +49012,12 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 84b72c691f8..a25bd260db4 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d godkännare"
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} till %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 3f250958394..5986a004f5d 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:24\n"
+"PO-Revision-Date: 2022-10-10 14:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index 707fad3d5f7..5d225586e07 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/th_TH/gitlab.po b/locale/th_TH/gitlab.po
index 061a04124da..565627b2b95 100644
--- a/locale/th_TH/gitlab.po
+++ b/locale/th_TH/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: th\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 16\n"
-"PO-Revision-Date: 2022-09-11 06:21\n"
+"PO-Revision-Date: 2022-10-10 14:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28750,15 +29261,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index eebae2c8cfe..21930809973 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d onaylayan"
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} - %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr "%{template_project_id} bilinmiyor ya da geçersiz"
msgid "%{text} is available"
msgstr "%{text} kullanılabilir"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} bir projeye ya da bir gruba ait olmalıdır."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "%{user_name} profil sayfası"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} zaman harcandı."
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr "Yeni bir kimliğe bürünme belirteci oluşturuldu."
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr "Tetikleyici ekle"
-msgid "Add user(s) to the group:"
-msgstr "Gruba kullanıcı(lar) ekleyin:"
-
-msgid "Add users to group"
-msgstr "Kullanıcıları gruba ekle"
-
msgid "Add variable"
msgstr "DeÄŸiÅŸken ekle"
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr "Engellendi"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Kullanıcıyı engelleme aşağıdaki etkilere sahiptir:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+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."
@@ -3846,6 +3902,9 @@ msgstr "Tüm birleştirme isteği bağımlılıkları birleştirildi"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Tüm projeler"
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Kullanıcıların yayın mesajını kapatmalarına izin ver"
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr "Tüm dosyalar yüklenirken bir hata oluştu."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "Tablo verileri alınırken bir hata oluştu"
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr "Analizler"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] "%d dosya ekleniyor"
msgid "Attaching the file failed."
msgstr "Dosya ekleme başarısız oldu."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Denetim Etkinlikleri"
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr "Dal yüklü değil - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr "Tüm projeler için varsayılan Otomatik DevOps iş hattı"
msgid "CICD|Deployment strategy"
msgstr "Dağıtım stratejisi"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "Ä°ÅŸler"
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "BirleÅŸtirme istek verileri getirilirken bir hata oluÅŸtu."
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr "Kapsayıcı Kaydı"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr "Katkıda Bulunanlar"
msgid "Control emails linked to your account"
msgstr "Hesabınıza bağlı e-postaları kontrol edin"
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "Kapsam"
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr "Bir grup oluÅŸtur"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr "Ayın günü"
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr "Silindi"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Silinen sohbet takma adı: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr "Sadece okuma eriÅŸimi"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr "Sona Eriyor"
@@ -13059,6 +13256,9 @@ msgstr "%{name} iptal et"
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Kullanıcı adı"
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr "başarılı"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,19 +13536,10 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
-msgstr ""
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr ""
-
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
@@ -13360,6 +13548,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "Yorum"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr ""
@@ -13378,7 +13572,7 @@ msgstr "Tümünün seçimini kaldır"
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr "Sonraki tasarıma git"
msgid "DesignManagement|Go to previous design"
msgstr "Önceki tasarıma dön"
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "İstenen tasarım sürümü mevcut değil. Bunun yerine en son sürüm gösteriliyor"
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr "Viki sayfasını düzenle"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Bir konudaki en son yorumunu düzenle (boş bir metin alanından)"
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr "E-postalar"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr "Dağıtım"
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr "Dağıtılmış ortam yok"
msgid "Environments|No deployments yet"
msgstr "Henüz dağıtım yok"
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr "Tümünü göster"
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr "GitLab Sorunu"
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Aramanızı genişletmek için süzgeçleri değiştirin veya kaldırın; %{startDate} - %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr ""
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr "Yakın zamanda oturum açmadıysanız, hemen %{password_link_start}şifr
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "Yakın zamanda oturum açmadıysanız, şifrenizi hemen değiştirmelisiniz: %{password_link}."
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "Yakın zamanda oturum açtıysanız ve IP adresini tanıyorsanız, bu e-postayı dikkate almayabilirsiniz."
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Tüm ayrıntılar"
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Yorumları etkinleştir"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Aralık Deseni"
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr "Dönüm noktası"
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr "Son başarılı güncelleme"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr "Daha fazlasını öğrenin"
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr "Yeni etiketi adlandır"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Ä°sim:"
@@ -26147,6 +26512,9 @@ msgstr "Yeni İş Hattı Takvimi"
msgid "New Project"
msgstr "Yeni Proje"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "Eki"
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr "Etkin"
msgid "PipelineSchedules|All"
msgstr "Tümü"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Etkin deÄŸil"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "Sonraki çalışma"
@@ -28960,15 +29472,27 @@ msgstr "Yok"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Bu iş hattı için kısa bir açıklama girin"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "SahipliÄŸi al"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Hedef"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr "'%{project_name}' için iş hattı ayarları başarıyla güncellendi."
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr "Lütfen devam etmek için %{phrase_code} yazın ya da iptal etmek için
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr "Tercihler"
msgid "Preferences saved."
msgstr "Tercihler kaydedildi."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Davranış"
@@ -29944,6 +30483,9 @@ msgstr "Zaman tercihleri"
msgid "Preferences|Use relative times"
msgstr "Göreceli zamanları kullan"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr "Etkin"
msgid "Profiles|Add key"
msgstr "Anahtar ekle"
-msgid "Profiles|Add status emoji"
-msgstr "Durum ifadesi ekle"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "Kullanıcı adınız güncellenirken bir hata oluştu, lütfen tekrar deneyin."
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr "Profil resmi kırpıcı"
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "Hakkında"
-msgid "Profiles|Busy"
-msgstr "MeÅŸgul"
-
msgid "Profiles|Change username"
msgstr "Kullanıcı adını değiştir"
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr "Şehir, ülke"
-msgid "Profiles|Clear status"
-msgstr "Durumu temizle"
-
msgid "Profiles|Commit email"
msgstr "İşlem e-postası"
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Bağlı Hesaplar"
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr "Geçerli yol: %{path}"
@@ -30448,9 +30981,6 @@ msgstr "İsimlerdeki ifadeleri kullanmak eğlenceli görünüyor. Ancak bunun ye
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr "Durumunuz nedir?"
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr "Adınız, %{provider_label} hesabınıza göre otomatik olarak ayarlandÄ
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr "Durumunuz"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr "Birleştirme yönteminizi, birleştirme seçeneklerini, birleştirme den
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr "Birleştirme önerileri"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Bu depoya yalnızca imzalanmış işlemler yollanabilir."
@@ -31183,6 +31722,9 @@ msgstr "Proje görünürlüğü"
msgid "ProjectSettings|Public"
msgstr "Herkese açık"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Depo"
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Viki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr "Devamını oku"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr "Rol"
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Dalları ara"
@@ -34797,6 +35408,9 @@ msgstr "Projeleri ara"
msgid "Search projects..."
msgstr "Projeleri ara..."
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Sorun oluÅŸtur"
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr "Arşiv Biçimini Seçin"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr "Sayfa Seç"
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Zaman dilimini seçin"
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr "Projeleri seç"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "Adınızın ve profil resminizin yanında bir gösterge belirir"
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr "Durumu temizle"
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Durumu düzenle"
@@ -36388,6 +37017,9 @@ msgstr "Bir durum ayarla"
msgid "SetStatusModal|Set status"
msgstr "Durum ayarla"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Üzgünüz, durumunuzu belirleyemedik. Lütfen daha sonra tekrar deneyin."
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr "Son iletiÅŸim"
msgid "SortOptions|Last created"
msgstr "Son oluÅŸturulan"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "En az popüler"
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr "En eski güncelleme"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "Popülerlik"
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr "Bu sizin mevcut oturumunuz"
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr "Bu, proje ile %{fork_source} arasındaki çatal ilişkisini kaldıracakt
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr "İşlem açıklamasını aç/kapat"
msgid "Toggle commit list"
msgstr "İşlem listesini aç/kapat"
-msgid "Toggle dropdown"
-msgstr "Açılır listeyi aç/kapat"
-
msgid "Toggle emoji award"
msgstr "İfade ödülünü aç/kapat"
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Kenar çubuğunu aç/kapat"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "Performans Çubuğunu aç/kapat"
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr "Mevcut dönem kullanımı"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr "Depo"
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr "Kullanıcı kimliği başarıyla güncellendi."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr "Vekil yok - %{openingTag} kendinizi atayın %{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "Çizelgeyi görüntüle"
@@ -43431,8 +44212,8 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
-msgstr "Epik listesini görüntüle"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Dosya"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr "Proje"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr "Viki"
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr "tarafından"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr "Yorumladı: %{link_to_project}"
@@ -46594,6 +47447,9 @@ msgstr "%{timeAgo} oluÅŸturuldu"
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "eksik"
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr "veya"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr "ağırlığı kaldır"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "etiket adı"
@@ -47845,6 +48717,11 @@ msgstr "%{time_ago} güncellendi"
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr "kullanıcının profil resmi"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 08fec90b133..d70773216ae 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: 16\n"
-"PO-Revision-Date: 2022-09-11 08:06\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -164,6 +164,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d затверджуюча оÑоба"
@@ -1010,10 +1017,10 @@ 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 "%{name_with_link} проÑÑ‚Ñ–Ñ€ імен %{percent} або менше хвилин загальних Runner'ів. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк він закінчитьÑÑ, нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ конвеєри в його проєктах не працюватимуть."
+msgstr "%{name_with_link} проÑÑ‚Ñ–Ñ€ імен %{percent} або менше хвилин загальних ранерів. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк він закінчитьÑÑ, нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ конвеєри в його проєктах не працюватимуть."
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'ів конвеєра. Ðових завдань у проєктах не буде."
+msgstr "%{name_with_link} у проÑторі імен вичерпано хвилин загальних ранерів конвеєра. Ðових завдань у проєктах не буде."
msgid "%{name} (Busy)"
msgstr "%{name} (зайнÑто)"
@@ -1040,7 +1047,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 "%{name}(%{url}) проÑÑ‚Ñ–Ñ€ імен вичерпавÑÑ Ñƒ хвилинах конвеєра загальних Runner'ів, тому нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ðµ запуÑкатимутьÑÑ Ð² Ñвоїх проєктах."
+msgstr "%{name}(%{url}) проÑÑ‚Ñ–Ñ€ імен вичерпавÑÑ Ñƒ хвилинах конвеєра загальних ранерів, тому нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ðµ запуÑкатимутьÑÑ Ð² Ñвоїх проєктах."
msgid "%{name}, confirm your email address now!"
msgstr "%{name}, підтвердіть Ñвою адреÑу електронної пошти зараз!"
@@ -1210,13 +1217,6 @@ msgstr "%{spanStart}в%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} до %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}ПопередженнÑ:%{strongClose} поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ SAML може Ñпричинити автоматичне Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑƒÑ‡Ð°Ñників із груп."
@@ -1265,6 +1265,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} Сховище проєкту"
@@ -1300,9 +1307,6 @@ msgstr "%{template_project_id} невідомий або неправильниÐ
msgid "%{text} is available"
msgstr "%{text} доÑтупний"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} повинен належати до проєкту або до групи."
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type} не підтримує графік згорÑннÑ"
@@ -1336,6 +1340,9 @@ msgstr "%{total} загальна вага відкритих задач"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total}знайдено Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ : показано перше%{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} підтримує лише %{name} ім'Ñ"
@@ -1357,12 +1364,15 @@ msgstr "%{user_name}%{user_username} було видалено з таких пÐ
msgid "%{user_name} profile page"
msgstr "%{user_name} Ñторінка профілю"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} змінив ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡ÐµÑ€Ð½ÐµÑ‚ÐºÐ¸ запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} попроÑив Ñтворити обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab у вашому випадку%{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr ""
+
msgid "%{username}'s avatar"
msgstr "%{username} аватар"
@@ -1384,6 +1394,12 @@ msgstr "%{value} Ñ"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} витрачено чаÑу."
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} цей %{noun} Ñк чернетку."
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} цей %{noun} Ñк готовий."
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} надає можливіÑÑ‚ÑŒ надÑилати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð½Ð° веб-заÑтоÑунки у відповідь на події у групі або в проєкті."
@@ -1925,9 +1941,6 @@ msgstr "Опубліковано новий Реліз %{tag} Ð´Ð»Ñ %{name}. П
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr "Ðова адреÑа електронної пошти була додана до вашого облікового запиÑу GitLab: %{email}"
-msgid "A new impersonation token has been created."
-msgstr "Створено новий токен імітуваннÑ."
-
msgid "A new personal access token has been created"
msgstr "Ðовий перÑональний токен доÑтупу було згенеровано"
@@ -1946,6 +1959,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr "Сторінка з таким заголовком вже Ñ–Ñнує"
+msgid "A personal access token has been revoked"
+msgstr "ПерÑональний токен було відкликано"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Сайт на HTML, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab"
@@ -2307,10 +2329,10 @@ msgid "AccountValidation|Fix your pipelines by validating your account"
msgstr "Виправте Ñвої конвеєри, підтвердивши Ñвій обліковий запиÑ"
msgid "AccountValidation|I'll bring my own runners"
-msgstr "Я зареєÑтрую мої влаÑні runner'и"
+msgstr "Я зареєÑтрую мої влаÑні ранери"
msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, you'll need to validate your account using one of our verification options. If you prefer not to, you can run pipelines by bringing your own runners and disabling shared runners for your project."
-msgstr "Щоб викориÑтовувати безкоштовні хвилини CI/CD на Ñпільних Runner'ах, вам потрібно підтвердити Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою одного з наших варіантів підтвердженнÑ. Якщо ви віддаєте перевагу цьому не робити, ви можете запуÑкати конвеєри, додавши влаÑні runner'и та вимкнувши Ñпільні runner'и Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту."
+msgstr "Щоб викориÑтовувати безкоштовні хвилини CI/CD на Ñпільних ранер'ах, вам потрібно підтвердити Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою одного з наших варіантів підтвердженнÑ. Якщо ви віддаєте перевагу цьому не робити, ви можете запуÑкати конвеєри, додавши влаÑні ранери та вимкнувши Ñпільні ранери Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту."
msgid "AccountValidation|Learn more."
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ."
@@ -2627,12 +2649,6 @@ msgstr "Додайте теми до проєктів, щоб допомогти
msgid "Add trigger"
msgstr "Додати тригер"
-msgid "Add user(s) to the group:"
-msgstr "Додати кориÑтувачів до групу:"
-
-msgid "Add users to group"
-msgstr "Додати кориÑтувача до групи"
-
msgid "Add variable"
msgstr "Додати змінну"
@@ -2940,7 +2956,7 @@ msgid "AdminSettings|Affects all new and existing groups."
msgstr "Впливає на вÑÑ– нові та Ñ–Ñнуючі групи."
msgid "AdminSettings|All new projects can use the instance's shared runners by default."
-msgstr "Ð’ÑÑ– нові проєкти за замовчуваннÑм можуть викориÑтовувати загальні runner'и (Runner'и) інÑтанÑа."
+msgstr "Ð’ÑÑ– нові проєкти за замовчуваннÑм можуть викориÑтовувати загальні ранери (ранери) інÑтанÑа."
msgid "AdminSettings|Auto DevOps domain"
msgstr "Домен Auto DevOps"
@@ -3006,7 +3022,7 @@ msgid "AdminSettings|Enable pipeline suggestion banner"
msgstr "Увімкнути банер пропозицій конвеєра"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів"
+msgstr "Увімкнути загальні ранери Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів"
msgid "AdminSettings|Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -3026,9 +3042,15 @@ msgstr "Токен доÑтупу до каналів"
msgid "AdminSettings|Git abuse rate limit"
msgstr "Ліміт кількоÑÑ‚Ñ– порушень Git"
+msgid "AdminSettings|Group runners expiration"
+msgstr "Термін дії групових ранерів"
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "Я прочитав Ñ– погоджуюÑÑŒ %{link_start}умовами викориÑтаннÑ%{link_end} (PDF)."
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "Якщо не вказано жодної одиниці вимірюваннÑ, за замовчуваннÑм викориÑтовуютьÑÑ Ñекунди. Ðаприклад, уÑÑ– вони еквівалентні: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}або %{oneDayHumanReadable}. Мінімальне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñтановить дві години. %{linkStart}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{linkEnd}"
+
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}. Ðе впливає на наÑвні репозиторії."
@@ -3041,6 +3063,9 @@ msgstr "Імпорт джерел"
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr "Термін дії групових ранерів"
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "Зберегти оÑтанні артефакти Ð´Ð»Ñ Ð²ÑÑ–Ñ… завдань в оÑтанніх уÑпішних конвеєрах"
@@ -3062,6 +3087,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -3098,6 +3126,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr "ЕкÑпорт проєкту"
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "ЗахиÑтити змінні CI/CD за замовчуваннÑм"
@@ -3149,9 +3180,21 @@ msgstr "Ð’Ñтановити шаблон CI/CD Ñк необхідну конф
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "Ð’Ñтановити термін дії токенів автентифікації щойно зареєÑтрованих групових ранерів."
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr "Ð’Ñтановіть макÑимальний розмір GitLab Pages Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ проєкту (0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ñ— кількоÑÑ‚Ñ–). %{link_start}ДовідайтеÑÑŒ більше.%{link_end}"
@@ -3255,7 +3298,7 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA увімкнено"
msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user. Validated users can use free CI minutes on shared runners."
-msgstr "КориÑтувач може підтвердити Ñебе, ввівши кредитну/дебетову картку, або адмініÑтратор може вручну підтвердити кориÑтувача. Перевірені кориÑтувачі можуть викориÑтовувати безкоштовні CI хвилини у Ñпільних runner'ах."
+msgstr "КориÑтувач може підтвердити Ñебе, ввівши кредитну/дебетову картку, або адмініÑтратор може вручну підтвердити кориÑтувача. Перевірені кориÑтувачі можуть викориÑтовувати безкоштовні CI хвилини у Ñпільних ранерах."
msgid "AdminUsers|Access"
msgstr "ДоÑтуп"
@@ -3338,6 +3381,9 @@ msgstr "Заблоковано"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача має наÑтупні наÑлідки:"
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr "Може Ñтворювати групи"
@@ -3495,7 +3541,7 @@ msgid "AdminUsers|Sort by"
msgstr "Сортувати за"
msgid "AdminUsers|The maximum number of CI/CD minutes on shared runners that a group can use each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
-msgstr "МакÑимальна кількіÑÑ‚ÑŒ CI/CD хвилин на Ñпільних runner'ах, Ñкі група може викориÑтовувати щоміÑÑцÑ. Ð’Ñтановіть 0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ñ— кількоÑÑ‚Ñ–. Ð’Ñтановіть пуÑтим, щоб уÑпадкувати глобальне Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{minutes}"
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ CI/CD хвилин на Ñпільних ранерах, Ñкі група може викориÑтовувати щоміÑÑцÑ. Ð’Ñтановіть 0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ñ— кількоÑÑ‚Ñ–. Ð’Ñтановіть пуÑтим, щоб уÑпадкувати глобальне Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{minutes}"
msgid "AdminUsers|The user can't access git repositories."
msgstr "КориÑтувач не може отримати доÑтуп до репозиторіїв git."
@@ -3677,9 +3723,21 @@ msgstr "Розширені параметри екÑпорту"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "Потрібна повторна індекÑаціÑ"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "ПіÑÐ»Ñ ÑƒÑпішного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ð¸ перейдете на екран входу."
@@ -4106,6 +4164,9 @@ msgstr "Ð’ÑÑ– залежноÑÑ‚Ñ– запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¸ зл
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr "Ð’ÑÑ– шлÑхи Ñ” відноÑними до URL-адреÑи GitLab. Ðе включайте %{relative_url_link_start}відноÑні URL-адреÑи%{relative_url_link_end}."
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr "Ð’ÑÑ– проєкти"
@@ -4181,6 +4242,9 @@ msgstr "Дозволити відправлÑти ключ до цього реÐ
msgid "Allow use of licensed EE features"
msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ… функцій EE"
+msgid "Allow users to create top-level groups"
+msgstr "Дозволити кориÑтувачам Ñтворювати групи верхнього рівнÑ"
+
msgid "Allow users to dismiss the broadcast message"
msgstr "Дозволити кориÑтувачам відхилÑти повідомленнÑ"
@@ -4469,9 +4533,6 @@ msgstr "При завантаженні розділу цієї Ñторінки
msgid "An error occurred while loading all the files."
msgstr "Помилка при завантаженні вÑÑ–Ñ… файлів."
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
-
msgid "An error occurred while loading chart data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… діаграми"
@@ -4696,7 +4757,7 @@ msgid "An unexpected error occurred while checking the project environment."
msgstr "Ðеочікувана помилка при перевірці Ñередовища проєкту."
msgid "An unexpected error occurred while checking the project runners."
-msgstr "Ðеочікувана помилка при перевірці runner'ів проєкту."
+msgstr "Ðеочікувана помилка при перевірці ранерів проєкту."
msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr "Ðеочікувана помилка з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ–Ð· Веб-терміналом."
@@ -4719,6 +4780,9 @@ msgstr "СталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка."
msgid "Analytics"
msgstr "Ðналітика"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Проаналізуйте ваші залежноÑÑ‚Ñ– на предмет відомих вразливоÑтей."
@@ -4946,6 +5010,9 @@ msgstr "РеєÑтрацію увімкнено"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr "ТекÑÑ‚, Ñкий відображаєтьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€ÐµÑ”Ñтрації кориÑтувача. Markdown увімкнено."
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr "Цей параметр доÑтупний лише на GitLab.com"
@@ -5466,7 +5533,7 @@ msgid "Ask someone with write access to resolve it."
msgstr "ПопроÑÑ–Ñ‚ÑŒ когоÑÑŒ із правом запиÑу вирішити цю проблему."
msgid "Ask your group owner to set up a group runner."
-msgstr "ПопроÑÑ–Ñ‚ÑŒ керівника групи налаштувати груповий Runner."
+msgstr "ПопроÑÑ–Ñ‚ÑŒ керівника групи налаштувати груповий ранер."
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
@@ -5605,6 +5672,9 @@ msgstr[3] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %d файлів"
msgid "Attaching the file failed."
msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¸ÐºÑ€Ñ–Ð¿Ð¸Ñ‚Ð¸ файл."
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr "Події аудиту"
@@ -5991,16 +6061,16 @@ msgid "Available ID"
msgstr "ДоÑтупний ідентифікатор"
msgid "Available group runners: %{runners}"
-msgstr "ДоÑтупна група runner'ів: %{runners}"
+msgstr "ДоÑтупна група ранерів: %{runners}"
msgid "Available on-demand"
msgstr ""
msgid "Available shared runners:"
-msgstr "ДоÑтупні Ñпільні Runner'и:"
+msgstr "ДоÑтупні Ñпільні ранери:"
msgid "Available specific runners"
-msgstr "ДоÑтупні Ñпеціальні Runner’и"
+msgstr "ДоÑтупні Ñпеціальні ранери"
msgid "Avatar for %{assigneeName}"
msgstr "Ðватар Ð´Ð»Ñ %{assigneeName}"
@@ -6278,6 +6348,9 @@ msgstr "Ðижче наведені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ %{link_to_gi
msgid "Below you will find all the groups that are public."
msgstr "Ðижче ви знайдете вÑÑ– загальнодоÑтупні групи."
+msgid "Beta"
+msgstr "Бета"
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6537,13 +6610,13 @@ msgid "Billings|Seats in use / Seats in subscription"
msgstr ""
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr "ДоÑтупні Runner'и будуть ввімкнені піÑÐ»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ñ–Ð¹Ñної кредитної картки."
+msgstr "ДоÑтупні ранери будуть ввімкнені піÑÐ»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ñ–Ð¹Ñної кредитної картки."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ñ… хвилин CI/CD на Ñпільних runner'ах, вам необхідно підтвердити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою кредитної картки. Якщо ви не бажаєте Ñ—Ñ— надавати, ви можете запуÑкати конвеєри, додаючи ваші влаÑні runner'и та вимикаючи Ñпільні runner'и Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту. Це необхідно Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ñ‚Ð° Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. %{strongStart} Gitlab не буде ÑÑ‚Ñгувати кошти з вашої картки, вона необхідна лише Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. %{strongEnd}%{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{linkEnd}."
+msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ñ… хвилин CI/CD на Ñпільних ранерах, вам необхідно підтвердити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою кредитної картки. Якщо ви не бажаєте Ñ—Ñ— надавати, ви можете запуÑкати конвеєри, додаючи ваші влаÑні ранери та вимикаючи Ñпільні ранери Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту. Це необхідно Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ñ‚Ð° Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. %{strongStart} Gitlab не буде ÑÑ‚Ñгувати кошти з вашої картки, вона необхідна лише Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. %{strongEnd}%{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{linkEnd}."
msgid "Billings|To use free CI/CD minutes on shared runners, you’ll need to validate your account with a credit 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 "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ñ… хвилин CI/CD на Ñпільних runner'ах, вам необхідно перевірити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою кредитної картки. Це необхідно Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ñ‚Ð° Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. %{strongStart} Gitlab не буде ÑÑ‚Ñгувати кошти з вашої картки, вона необхідна лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ облікового запиÑу. %{strongEnd}"
+msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ñ… хвилин CI/CD на Ñпільних ранерах, вам необхідно перевірити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою кредитної картки. Це необхідно Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ñ‚Ð° Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. %{strongStart} Gitlab не буде ÑÑ‚Ñгувати кошти з вашої картки, вона необхідна лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ облікового запиÑу. %{strongEnd}"
msgid "Billings|User validation required"
msgstr "Ðеобхідна перевірка кориÑтувача."
@@ -6555,7 +6628,7 @@ msgid "Billings|Validate user account"
msgstr "Перевірити обліковий Ð·Ð°Ð¿Ð¸Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr "Тепер ви зможете ÑкориÑтатиÑÑ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ð¼Ð¸ хвилинами CI/CD на Ñпільних runner'ах."
+msgstr "Тепер ви зможете ÑкориÑтатиÑÑ Ð²Ñ–Ð»ÑŒÐ½Ð¸Ð¼Ð¸ хвилинами CI/CD на Ñпільних ранерах."
msgid "Billings|Your account has been validated"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ перевірено"
@@ -6599,8 +6672,8 @@ msgstr "ПрÑме членÑтво"
msgid "Billing|Enter at least three characters to search."
msgstr "Введіть щонайменше три Ñимволи Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ."
-msgid "Billing|Explore all plans"
-msgstr "ПереглÑнути вÑÑ– плани"
+msgid "Billing|Explore paid plans"
+msgstr ""
msgid "Billing|Export list"
msgstr "ЕкÑпортувати ÑпиÑок"
@@ -6639,6 +6712,9 @@ msgstr "Увімкнути/вимкнути подробиці міÑцÑ."
msgid "Billing|Type %{username} to confirm"
msgstr "Введіть %{username} щоб підтвердити"
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr "КориÑтувача уÑпішно видалено"
@@ -6752,7 +6828,7 @@ msgid "BoardScope|Any assignee"
msgstr "Будь-Ñкий виконавець"
msgid "BoardScope|Any iteration"
-msgstr ""
+msgstr "Будь-Ñка ітераціÑ"
msgid "BoardScope|Any label"
msgstr "Будь-Ñка мітка"
@@ -6764,7 +6840,7 @@ msgid "BoardScope|Choose labels"
msgstr "Вибрати мітки"
msgid "BoardScope|Current iteration"
-msgstr ""
+msgstr "Поточна ітераціÑ"
msgid "BoardScope|Don't filter milestone"
msgstr ""
@@ -6773,7 +6849,7 @@ msgid "BoardScope|Edit"
msgstr "Редагувати"
msgid "BoardScope|Iteration"
-msgstr ""
+msgstr "ІтераціÑ"
msgid "BoardScope|Labels"
msgstr "Мітки"
@@ -6963,6 +7039,9 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑ–Ð²"
msgid "Bold text"
msgstr "Жирний текÑÑ‚"
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr "SSH Ñ– HTTP(S)"
@@ -6999,33 +7078,78 @@ msgstr "Гілку не завантажено: %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr "ПідтримуютьÑÑ%{linkStart}шаблони%{linkEnd}, такі Ñк *-stable або production/*."
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "Дозволити вÑім кориÑтувачам з push-доÑтупом %{linkStart}примуÑово push%{linkEnd}."
msgid "BranchRules|Allowed to merge"
msgstr "Дозволено злиттÑ"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "Дозволено здійÑнити push"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð³Ñ–Ð»Ð¾Ðº ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr "Гілка"
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr "Деталі правил гілки"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr "Створити шаблон: %{searchTerm}"
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "Групи"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr "Захищайте Ñтабільні гілки та змушуйте розробників викориÑтовувати запити на злиттÑ. %{linkStart}Що таке захищені гілки?%{linkEnd}"
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr "Ðемає відповідних результатів"
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr "ЗахиÑÑ‚"
@@ -7035,11 +7159,23 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr "Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ влаÑників коду."
+msgid "BranchRules|Roles"
+msgstr "Ролі"
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr "Цільова гілка"
+
+msgid "BranchRules|Users"
+msgstr "КориÑтувачі"
+
msgid "BranchRules|default"
msgstr "за умовчаннÑм"
msgid "BranchRules|protected"
-msgstr ""
+msgstr "захищена"
msgid "Branches"
msgstr "Гілки"
@@ -7207,7 +7343,7 @@ msgid "Browse templates"
msgstr "ОглÑд шаблонів"
msgid "Build cannot be erased"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñтерти збірку"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "Помилка при отриманні артефактів"
@@ -7335,6 +7471,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr "повинен бути групою"
@@ -7510,6 +7649,9 @@ msgstr "ВикориÑтовувати Auto DevOps конвеєр за замоÐ
msgid "CICD|Deployment strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr "ЗавданнÑ"
@@ -7519,8 +7661,8 @@ msgstr "Ліміт"
msgid "CICD|Limit CI_JOB_TOKEN access"
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 "Виберіть проєкти, до Ñких можна отримати доÑтуп за допомогою запитів API, автентифікованих за допомогою змінної CI_JOB_TOKEN CI/CD цього проєкту."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr ""
@@ -7780,8 +7922,8 @@ msgstr "Ðеможливо переміÑтити задачу, тому що в
msgid "Cannot promote issue due to insufficient permissions."
msgstr "Ðе вдаєтьÑÑ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰Ð¸Ñ‚Ð¸ задачу через недоÑтатній доÑтуп."
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr "Ðеможливо поÑилатиÑÑ Ð½Ð° групу %{timebox_type} за внутрішнім ідентифікатором!"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "Ðеможливо показати попередній переглÑд. Ð”Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду файлів Sketch, вони повинні мати формат, введений верÑією 43 або вище."
@@ -7975,6 +8117,9 @@ msgstr "Змінює заголовок на \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr "Зміни в заголовку не збережені"
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8371,7 +8516,7 @@ msgid "Choose file…"
msgstr "Виберіть файл…"
msgid "Choose the preferred Runner and populate the AWS CFT."
-msgstr "Виберіть потрібний Runner і заповніть AWS CFT."
+msgstr "Виберіть потрібний ранер і заповніть AWS CFT."
msgid "Choose the top-level group for your repository imports."
msgstr "Оберіть групу найвищого Ñ€Ñ–Ð²Ð½Ñ Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторіїв."
@@ -8750,7 +8895,7 @@ msgid "CloudSeed|All"
msgstr "Ð’ÑÑ–"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "AlloyDB Ð´Ð»Ñ Postgres"
msgid "CloudSeed|Available database services through which instances may be created"
msgstr ""
@@ -8995,6 +9140,9 @@ msgstr "Ви впевнені, що хочете видалити цього аÐ
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr "Ви впевнені, що хочете відкликати цей токен? Цю дію не можна відмінити."
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr "Сертифікат"
@@ -9094,6 +9242,9 @@ msgstr "Як оновити агента?"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr "Ð’Ñтановити за допомогою Helm (рекомендовано)"
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "ОÑтаннє Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ %{timeAgo}."
@@ -9122,6 +9273,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr "Ðемає агентів"
@@ -9131,6 +9285,9 @@ msgstr "Ðемає клаÑтерів, підключених через ÑерÑ
msgid "ClusterAgents|Not connected"
msgstr "Ðе підключений"
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr "Рекомендовано"
@@ -9197,6 +9354,9 @@ msgstr "Токен відкликано %{userName}"
msgid "ClusterAgents|Unknown user"
msgstr "Ðевідомий кориÑтувач"
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "ПереглÑнути вÑÑ– %{number} агентів"
@@ -9867,6 +10027,9 @@ msgstr "Комітить до"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "Тут з’ÑвлÑÑ‚ÑŒÑÑ Ð¾Ð±Ñ€Ð°Ð½Ñ– вами коміти. Перейдіть до першої вкладки та оберіть коміти, щоб додати Ñ—Ñ… до цього запиту на злиттÑ."
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… запиту на злиттÑ."
@@ -9972,6 +10135,9 @@ msgstr "Завершено"
msgid "Complete verification to sign in."
msgstr "Пройдіть верифікацію, щоб зареєÑтруватиÑÑ."
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr "Завершено"
@@ -10041,8 +10207,8 @@ msgstr "Потрібна назва"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr "Ðеобхідний формат: %{codeStart}шлÑÑ…/файл.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
+msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ цей фреймворк відповідноÑÑ‚Ñ–. Будь лаÑка, Ñпробуйте ще раз"
@@ -10135,7 +10301,7 @@ msgid "Configure GitLab"
msgstr "Ðалаштувати GitLab"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Ðалаштувати runner'ів GitLab Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ викориÑÑ‚Ð°Ð½Ð½Ñ Ð’ÐµÐ±-терміналу. %{helpStart}Докладніше.%{helpEnd}"
+msgstr "Ðалаштувати ранерів GitLab Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ викориÑÑ‚Ð°Ð½Ð½Ñ Ð’ÐµÐ±-терміналу. %{helpStart}Докладніше.%{helpEnd}"
msgid "Configure Gitaly timeouts."
msgstr "Ðалаштувати таймаути Gitaly."
@@ -10359,6 +10525,9 @@ msgstr "Контакти"
msgid "Container Registry"
msgstr "РеєÑÑ‚Ñ€ Контейнерів"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ð°"
@@ -10597,7 +10766,7 @@ msgid "ContainerRegistry|Save storage space by automatically deleting tags from
msgstr ""
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "Ð’Ñтановити правила очищеннÑ"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
msgstr ""
@@ -10821,15 +10990,15 @@ msgstr "УчаÑники"
msgid "Control emails linked to your account"
msgstr "Керувати адреÑами електронної пошти, пов’Ñзаними з вашим обліковим запиÑом"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr ""
+
msgid "Control how the GitLab Package Registry functions."
msgstr ""
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr "Контролює, чи показувати контент Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñького доÑвіду та Ñторонні пропозиції в GitLab."
-msgid "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."
-msgstr ""
-
msgid "Cookie domain"
msgstr "Домен cookie"
@@ -11151,6 +11320,9 @@ msgstr ""
msgid "Country"
msgstr "Країна"
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr "ПокриттÑ"
@@ -11367,6 +11539,9 @@ msgstr "Створити тему"
msgid "Create user"
msgstr "Створити кориÑтувача"
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Створити шаблон: %{searchTerm}"
@@ -11379,6 +11554,12 @@ msgstr "Створити групи"
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу Ñтворювати підгрупу в цій групі."
@@ -11794,7 +11975,7 @@ msgid "Customer relations organizations"
msgstr ""
msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
-msgstr "Ðалаштуйте параметри CI/CD, зокрема Auto DevOps, Ñпільні Runner'и та артефакти завдань."
+msgstr "Ðалаштуйте параметри CI/CD, зокрема Auto DevOps, Ñпільні ранери та артефакти завдань."
msgid "Customize colors"
msgstr "Параметри кольорів"
@@ -12365,10 +12546,10 @@ msgid "DastProfiles|Scanner name"
msgstr "Ім'Ñ Ñканера"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "Профіль Ñканера"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "Профілі Ñканера"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr ""
@@ -12638,6 +12819,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr "%{start_date}–%{end_date}"
+
msgid "Day of month"
msgstr "День міÑÑцÑ"
@@ -12824,6 +13011,9 @@ msgstr "Видалити обліковий запиÑ"
msgid "Delete artifacts"
msgstr "Видалити артефакти"
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12968,6 +13158,9 @@ msgstr "Видалено"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Видалено пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr "Видалені проєкти неможливо відновити!"
@@ -13319,6 +13512,9 @@ msgstr "ДоÑтуп тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Ðктивні токени Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ (%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "ДозволÑÑ” читати та запиÑувати доÑтуп до образів реєÑтру."
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "ДозволÑÑ” доÑтуп Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° запиÑу до реєÑтру пакетів."
@@ -13329,7 +13525,7 @@ msgid "DeployTokens|Allows read-only access to the package registry."
msgstr "ДозволÑÑ” доÑтуп лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ реєÑтру пакетів."
msgid "DeployTokens|Allows read-only access to the repository."
-msgstr ""
+msgstr "ДозволÑÑ” доÑтуп лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ репозиторію."
msgid "DeployTokens|Allows write access to registry images."
msgstr ""
@@ -13364,6 +13560,9 @@ msgstr "Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ ток
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr "Введіть термін придатноÑÑ‚Ñ– Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ токену. За замовчуваннÑм — ніколи не закінчитьÑÑ."
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "Дата Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ (необов’Ñзково)"
+
msgid "DeployTokens|Expires"
msgstr "Термін дії"
@@ -13385,6 +13584,9 @@ msgstr "Відкликати %{name}"
msgid "DeployTokens|Scopes"
msgstr "ОблаÑÑ‚ÑŒ дії"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13400,6 +13602,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "DeployTokens|Username (optional)"
+msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача (необов'Ñзково)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "Ваш новий токен розгортаннÑ"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr "Ваше нове ім'Ñ Ð´Ð»Ñ Ñ‚Ð¾ÐºÐµÐ½Ñƒ розгортаннÑ"
@@ -13587,18 +13795,9 @@ msgstr "уÑпішно"
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13669,19 +13868,10 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ коментарÑ?"
-msgid "DesignManagement|Cancel changes"
-msgstr "СкаÑувати зміни"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "СкаÑувати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ"
-
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
@@ -13690,6 +13880,12 @@ msgstr ""
msgid "DesignManagement|Comment"
msgstr "Коментар"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ новий коментар. Будь лаÑка, Ñпробуйте ще раз."
@@ -13708,8 +13904,8 @@ msgstr "ЗнÑти Ð²Ð¸Ð´Ñ–Ð»ÐµÐ½Ð½Ñ Ð· уÑÑ–Ñ…"
msgid "DesignManagement|Designs"
msgstr "Дизайни"
-msgid "DesignManagement|Discard comment"
-msgstr "Відхилити коментар"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
msgstr ""
@@ -13729,12 +13925,6 @@ msgstr "Перейти до наÑтупного дизайну"
msgid "DesignManagement|Go to previous design"
msgstr "Перейти до попереднього дизайну"
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr "Залишити коментар"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "Бажана верÑÑ–Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñƒ не Ñ–Ñнує. ЗаміÑÑ‚ÑŒ неї відображаєтьÑÑ Ð¾ÑтаннÑ"
@@ -13937,10 +14127,10 @@ msgid "DevopsAdoption|Remove Group from the table."
msgstr "Видалити групу з таблиці."
msgid "DevopsAdoption|Runner configured for project/group"
-msgstr "Runner, налаштований Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ/групи"
+msgstr "Ранер, налаштований Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ/групи"
msgid "DevopsAdoption|Runners"
-msgstr "Runner'и"
+msgstr "Ранери"
msgid "DevopsAdoption|SAST"
msgstr "SAST"
@@ -14000,7 +14190,7 @@ msgid "DevopsReport|Your usage"
msgstr "Ваше викориÑтаннÑ"
msgid "Diagram (%{language})"
-msgstr ""
+msgstr "Діаграма (%{language})"
msgid "Did not delete the source branch."
msgstr ""
@@ -14108,7 +14298,7 @@ msgid "Disable for this project"
msgstr "Вимкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "Disable group runners"
-msgstr "Вимкнути групові runner'и"
+msgstr "Вимкнути групові ранери"
msgid "Disable two-factor authentication"
msgstr "Вимкнути двофакторну автентифікацію"
@@ -14285,6 +14475,18 @@ msgstr "Домен"
msgid "Domain Name"
msgstr "Доменне ім'Ñ"
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr "Ðе маєте групи?"
@@ -14406,7 +14608,7 @@ msgid "DropdownWidget|Cancel"
msgstr "СкаÑувати"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "Редагувати %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ %{issuableAttribute} Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ %{issuableType}. Будь лаÑка, Ñпробуйте ще раз."
@@ -14651,6 +14853,9 @@ msgstr "Редагувати wiki-Ñторінку"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Редагувати ваш оÑтанній коментар в обговоренні (в порожньому текÑтовому полі)"
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14789,9 +14994,6 @@ msgstr "і ще %{moreCount}"
msgid "Emails"
msgstr "ÐдреÑи електронної пошти"
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14909,6 +15111,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr "Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
@@ -14922,7 +15127,7 @@ msgid "Enable for this project"
msgstr "Увімкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "Enable group runners"
-msgstr "Увімкнути групові Runner'и"
+msgstr "Увімкнути групові ранери"
msgid "Enable header and footer in emails"
msgstr "Увімкнути заголовок та футер в електронних лиÑтах"
@@ -14970,13 +15175,13 @@ msgid "Enable security training to help your developers learn how to fix vulnera
msgstr "Увімкніть Ñ‚Ñ€ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸, щоб допомогти вашим розробникам навчитиÑÑ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»Ñти вразливоÑÑ‚Ñ–. Розробники можуть переглÑдати Ñ‚Ñ€ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ вибраних оÑвітніх провайдерів, що ÑтоÑуютьÑÑ Ð²Ð¸Ñвленої вразливоÑÑ‚Ñ–."
msgid "Enable shared runners for all projects and subgroups in this group."
-msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів Ñ– підгруп у цій групі."
+msgstr "Увімкнути загальні ранери Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів Ñ– підгруп у цій групі."
msgid "Enable shared runners for this group"
-msgstr "Увімкнути загальні Runner'и Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
+msgstr "Увімкнути загальні ранери Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
msgid "Enable shared runners for this project"
-msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
+msgstr "Увімкнути загальні ранери Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "Enable two-factor authentication"
msgstr "Увімкнути двофакторну автентифікацію"
@@ -15257,6 +15462,9 @@ msgstr "РозгортаннÑ"
msgid "Environments|Deployment %{status}"
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ %{status}"
+msgid "Environments|Edit your search and try again"
+msgstr "Відредагуйте пошук Ñ– повторіть Ñпробу"
+
msgid "Environments|Enable review app"
msgstr ""
@@ -15290,6 +15498,9 @@ msgstr "Ðемає розгорнутих Ñередовищ"
msgid "Environments|No deployments yet"
msgstr "Ще немає розгортань"
+msgid "Environments|No results found"
+msgstr "Ðе знайдено результатів"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "Зверніть увагу, що Ñ†Ñ Ð´Ñ–Ñ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚ÑŒ Ñередовище, але це %{emphasisStart}не%{emphasisEnd} впливатиме на будь-Ñке Ñ–Ñнуюче Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· відÑутніÑÑ‚ÑŒ операції зупинки в файлі %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}."
@@ -15314,6 +15525,9 @@ msgstr "Відкотити Ñередовище"
msgid "Environments|Rollback environment %{name}?"
msgstr "Відкотити Ñередовище %{name}?"
+msgid "Environments|Search by environment name"
+msgstr "Пошук за назвою Ñередовища"
+
msgid "Environments|Show all"
msgstr "Показати вÑÑ–"
@@ -16374,10 +16588,10 @@ msgid "Failed to enqueue the rebase operation, possibly due to a long-lived tran
msgstr "Ðе вдалоÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ rebase в чергу, можливо через довгоживучу транзакцію. Спробуйте знову через деÑкий чаÑ."
msgid "Failed to fetch the iteration for this issue. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ітерації Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі. Будь лаÑка, Ñпробуйте ще раз."
msgid "Failed to fetch the iterations for the group. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ітерації Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸. Будь лаÑка, Ñпробуйте ще раз."
msgid "Failed to find import label for Jira import."
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ мітку Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ ÑиÑтеми Jira."
@@ -16418,9 +16632,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑпиÑок Ñмайликів."
-
msgid "Failed to load error details from Sentry."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ деталі помилок із Sentry."
@@ -17106,6 +17317,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr "Ð”Ð»Ñ ÑˆÐ²Ð¸Ð´ÑˆÐ¾Ð³Ð¾ переглÑду, не вÑÑ Ñ–ÑÑ‚Ð¾Ñ€Ñ–Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ."
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -17235,9 +17449,15 @@ msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr "Фреймворк уÑпішно видалено"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Безкоштовна пробна верÑÑ–Ñ GitLab.com Ultimate"
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
@@ -17245,6 +17465,33 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17512,6 +17759,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðевдало"
@@ -17851,6 +18101,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -18073,9 +18326,6 @@ msgstr "Задача GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
-msgid "GitLab Logo"
-msgstr "Логотип GitLab"
-
msgid "GitLab Pages"
msgstr "Gitlab Pages"
@@ -18866,7 +19116,7 @@ msgid "Group requires separate account"
msgstr "Група вимагає окремий обліковий запиÑ"
msgid "Group runners"
-msgstr "Групові runner'и"
+msgstr "Групові ранери"
msgid "Group runners can be managed with the %{link}."
msgstr ""
@@ -18940,6 +19190,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑ–Ð²"
+msgid "GroupRoadmap|New epic"
+msgstr "Ðовий епік"
+
msgid "GroupRoadmap|No start and end date"
msgstr "Дати початку та Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð½ÐµÐ¼Ð°Ñ”"
@@ -18976,6 +19229,9 @@ msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте да
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Щоб розширити пошук, змініть або видаліть фільтри; від %{startDate} до %{endDate}."
+msgid "GroupRoadmap|View epics list"
+msgstr "ПереглÑнути ÑпиÑок епіків"
+
msgid "GroupRoadmap|Within 3 years"
msgstr "ПротÑгом 3-Ñ… років"
@@ -19192,8 +19448,8 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr "Фреймворки відповідноÑÑ‚Ñ–"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr "Ðалаштуйте рамки відповідноÑÑ‚Ñ–, щоб зробити Ñ—Ñ… доÑтупними Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð² цієї групи. %{linkStart}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
msgstr ""
@@ -19537,6 +19793,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
+msgid "Groups|Learn more about subgroups"
+msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про підгрупи"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19555,6 +19817,9 @@ msgstr "Ðазва підгрупи"
msgid "Groups|Subgroup slug"
msgstr "ШлÑÑ… підгрупи"
+msgid "Groups|You're creating a new top-level group"
+msgstr "Ви Ñтворюєте нову групу верхнього рівнÑ"
+
msgid "Guideline"
msgstr "Керівництво"
@@ -19576,8 +19841,8 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
-msgstr "ПіÑÐ»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— інтеграції в Harbor глобальні змінні '$HARBOR_USERNAME'$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' та '$HARBOR_PROJECT' будуть Ñтворені Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ CI/CD."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
+msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
msgstr ""
@@ -19626,6 +19891,9 @@ msgstr[3] ""
msgid "HarborRegistry|-- artifacts"
msgstr "- артефакти"
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19671,7 +19939,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -20108,24 +20376,45 @@ msgstr "Ідентифікатори"
msgid "Identities"
msgstr "ІдентифікаціÑ"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "Ðовий код надіÑлано."
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "Перш ніж Ñтворити Ñвій перший проєкт, вам потрібно підтвердити Ñвою оÑобу за допомогою дійÑного ÑпоÑобу оплати. З Ð²Ð°Ñ Ð½Ðµ ÑÑ‚ÑгуватиметьÑÑ Ð¿Ð»Ð°Ñ‚Ð° під Ñ‡Ð°Ñ Ñ†Ñ–Ñ”Ñ— операції. Якщо нам колиÑÑŒ буде потрібно ÑÑ‚Ñгнути з Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñƒ, ми вам повідомимо."
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "Перш ніж Ñтворити Ñвою групу, вам потрібно підтвердити Ñвою оÑобу за допомогою дійÑного ÑпоÑобу оплати. З Ð²Ð°Ñ Ð½Ðµ ÑÑ‚ÑгуватиметьÑÑ Ð¿Ð»Ð°Ñ‚Ð° під Ñ‡Ð°Ñ Ñ†Ñ–Ñ”Ñ— операції. Якщо нам колиÑÑŒ буде потрібно ÑÑ‚Ñгнути з Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñƒ, ми вам повідомимо."
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "Перед тим, Ñк ви завершите ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу, нам потрібно підтвердити вашу оÑобу. Ðа Ñторінці Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ наÑтупний код."
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr "Підтведіть Ñвою електронну адреÑу"
+
msgid "IdentityVerification|Create a project"
msgstr "Створити проєкт"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "Ðе отримали код?"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "Введіть код."
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "Введіть правильний код."
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -20165,17 +20454,23 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr "ÐадіÑлати новий код"
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr "ЩоÑÑŒ пішло не так. Будь лаÑка, Ñпробуйте ще раз."
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr "Термін дії коду закінчивÑÑ. Ðадішліть новий код Ñ– повторіть Ñпробу."
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
+msgstr "Код хибний. Введіть його ще раз або надішліть новий код."
msgid "IdentityVerification|Verification code"
msgstr ""
@@ -20186,6 +20481,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr "Підтвердити адреÑу електронної пошти"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr "Підтвердити Ñвою оÑобу"
@@ -20195,11 +20496,14 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "Ви доÑÑгли макÑимальної кількоÑÑ‚Ñ– повторних відправлень. Зачекайте %{interval} Ñ– повторіть Ñпробу."
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr ""
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr "Ви доÑÑгли макÑимальної кількоÑÑ‚Ñ– Ñпроб. Зачекайте %{interval} або надішліть новий код Ñ– повторіть Ñпробу."
+
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ ÑƒÑпішно перевірено. За мить Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ перенаправлено до вашого облікового запиÑу. Ви також можете %{redirect_url_start}оновити Ñторінку%{redirect_url_end}."
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr ""
@@ -20279,6 +20583,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -20288,6 +20598,9 @@ msgstr "Якщо ви втратите коди відновленнÑ, ви мÐ
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr "Якщо ви хочете знову увімкнути двофакторну автентифікацію, перейдіть на Ñторінку %{two_factor_link}"
@@ -20473,6 +20786,9 @@ msgstr "Підключити репозиторії із"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr "%{provider} перевищено ліміт чаÑтоти. Спробуйте знову пізніше"
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "Заблокований URL Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ: %{message}"
@@ -20497,6 +20813,9 @@ msgstr "Запит ваших %{provider} репозиторіїв пройшоÐ
msgid "ImportProjects|Select the repositories you want to import"
msgstr "Виберіть репозиторії, Ñкі ви хочете імпортувати"
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "Віддалені дані не можуть бути імпортовані."
@@ -20592,7 +20911,7 @@ msgid "InProductMarketing|And many more..."
msgstr "І багато іншого..."
msgid "InProductMarketing|Are your runners ready?"
-msgstr "Чи готові ваші runner'и?"
+msgstr "Чи готові ваші ранери?"
msgid "InProductMarketing|Automated security scans directly within GitLab"
msgstr "Ðвтоматичні ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ безпоÑередньо в GitLab"
@@ -21404,6 +21723,9 @@ msgstr "Ðе завершено"
msgid "Increase"
msgstr "Збільшити"
+msgid "Indent line"
+msgstr "ВідÑтуп Ñ€Ñдка"
+
msgid "Index"
msgstr "ІндекÑ"
@@ -21627,6 +21949,9 @@ msgstr "Додати інтеграцію"
msgid "Integrations|Add namespace"
msgstr "Додати проÑÑ‚Ñ–Ñ€ імен"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Ð’ÑÑ– деталі"
@@ -21687,12 +22012,18 @@ msgstr "Увімкнути перевірку SSL"
msgid "Integrations|Enable comments"
msgstr "Увімкнути коментарі"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr "Введіть ваш пÑевдонім"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "Ðе вдалоÑÑ Ð·Ð²â€™Ñзати проÑÑ‚Ñ–Ñ€ імен. Будь лаÑка, Ñпробуйте ще раз."
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr "Помилка при завантаженні проÑторів імен. Будь лаÑка, Ñпробуйте ще раз."
@@ -21705,6 +22036,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´â€™Ñ”Ð´Ð½Ð°Ñ‚Ð¸ проÑÑ‚Ñ–Ñ€ імен. Будь лаÑка, Ñпробуйте ще раз."
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21897,9 +22231,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон інтервалу"
-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 "Введено в GitLab 13.1, перш ніж викориÑтовувати %{reindexing_link_start}переіндекÑацію з нульовим проÑтоєм%{link_end} Ñ– %{migrations_link_start}міграції розширеного пошуку%{link_end}, вам потрібно %{recreate_link_start}відтворити Ñвій індекÑ%{link_end}."
-
msgid "Introducing Your DevOps Reports"
msgstr "ПредÑтавлÑємо ваші DevOps звіти"
@@ -22294,6 +22625,12 @@ msgstr "ВикориÑтовує міÑце в ліцензії:"
msgid "Is using seat"
msgstr "ВикориÑтовує міÑце"
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22393,6 +22730,9 @@ msgstr "Помилка при завантаженні задач. Будь ла
msgid "IssueAnalytics|Issue"
msgstr "Задача"
+msgid "IssueAnalytics|Iteration"
+msgstr "ІтераціÑ"
+
msgid "IssueAnalytics|Milestone"
msgstr "Етап"
@@ -22577,7 +22917,7 @@ msgid "Iteration changed to"
msgstr "Ітерацію змінено на"
msgid "Iteration lists not available with your current license"
-msgstr ""
+msgstr "СпиÑки ітерацій недоÑтупні з вашою поточною ліцензією"
msgid "Iteration removed"
msgstr "Ітерацію видалено"
@@ -22604,7 +22944,7 @@ msgid "IterationsCadence|The automation start date would retroactively create a
msgstr ""
msgid "Iterations|Add iteration"
-msgstr ""
+msgstr "Додати ітерацію"
msgid "Iterations|All"
msgstr "Ð’ÑÑ–"
@@ -22646,7 +22986,7 @@ msgid "Iterations|Delete iteration cadence?"
msgstr ""
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "Видалити ітерацію?"
msgid "Iterations|Description"
msgstr "ОпиÑ"
@@ -22664,10 +23004,10 @@ msgid "Iterations|Edit cadence"
msgstr ""
msgid "Iterations|Edit iteration"
-msgstr ""
+msgstr "Редагувати ітерацію"
msgid "Iterations|Edit iteration cadence"
-msgstr ""
+msgstr "Редагувати Ð·Ð½Ð¸Ð¶ÐµÐ½Ð½Ñ Ñ–Ñ‚ÐµÑ€Ð°Ñ†Ñ–Ñ—"
msgid "Iterations|Enable automatic scheduling"
msgstr "Увімкнути автоматичне плануваннÑ"
@@ -22709,7 +23049,7 @@ msgid "Iterations|No iterations in cadence."
msgstr ""
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "Ðемає відкритих ітерацій."
msgid "Iterations|Number of upcoming iterations that should be scheduled at a time."
msgstr ""
@@ -22727,7 +23067,7 @@ msgid "Iterations|Select duration"
msgstr ""
msgid "Iterations|Select number"
-msgstr ""
+msgstr "Вибрати номер"
msgid "Iterations|Select start date"
msgstr "Обрати дату початку"
@@ -22765,9 +23105,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23060,7 +23397,7 @@ msgid "Job has wrong arguments format."
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” неправильний формат аргументів."
msgid "Job is stuck. Check runners."
-msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ. Перевірте runner'и."
+msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ. Перевірте ранери."
msgid "Job logs and artifacts"
msgstr "Журнали завдань та артефакти"
@@ -23255,7 +23592,7 @@ msgid "Job|This job is stuck because of one of the following problems. There are
msgstr ""
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
-msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що цей проєкт не має жодних runner'ів призначених Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾."
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що цей проєкт не має жодних ранерів призначених Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾."
msgid "Job|This job is stuck because you don't have any active runners that can run this job."
msgstr ""
@@ -23619,6 +23956,9 @@ msgstr ""
msgid "Last successful update"
msgstr "ОÑтаннє уÑпішне оновленнÑ"
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr "ОÑтанній раз перевірено"
@@ -23700,8 +24040,8 @@ msgstr "ДізнайтеÑÑ Ñк %{no_packages_link_start}публікуватÐ
msgid "Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
-msgid "Learn more about %{username}"
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{username}"
+msgid "Learn more about %{name}"
+msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
@@ -24501,6 +24841,9 @@ msgstr "Зробіть кожного учаÑника команди більш
msgid "Make issue confidential"
msgstr "Зробити задачу конфіденційною"
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24552,12 +24895,12 @@ msgstr "Керувати проєктами"
msgid "Manage two-factor authentication"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾ÑŽ автентифікацією"
-msgid "Manage your license"
-msgstr "Керувати вашою ліцензією"
-
msgid "Manage your project's triggers"
msgstr ""
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "Керований обліковий запиÑ"
@@ -24639,9 +24982,24 @@ msgstr "Додати закреÑлений текÑÑ‚ (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Додати закреÑлений текÑÑ‚ (%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr "ВідÑтуп Ñ€Ñдка (%{modifierKey}])"
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr "ВідÑтуп Ñ€Ñдка (%{modifier_key}])"
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "ВиÑтуп Ñ€Ñдка (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "ВиÑтуп Ñ€Ñдка (%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "ПідтримуєтьÑÑ %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24651,9 +25009,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr "Позначено Ñк готове. Тепер Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾."
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24666,7 +25021,7 @@ msgstr "Цю задачу позначено пов’Ñзаною з %{issue_re
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24903,6 +25258,9 @@ msgstr "МакÑимальна кількіÑÑ‚ÑŒ запитів на хвили
msgid "Maximum number of unique IP addresses per user."
msgstr "МакÑимальна кількіÑÑ‚ÑŒ унікальних IP-Ð°Ð´Ñ€ÐµÑ Ð½Ð° кориÑтувача."
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr "МакÑимум 255 Ñимволів"
@@ -25263,7 +25621,7 @@ msgid "Merge requests"
msgstr "Запити на злиттÑ"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "Запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ перенеÑені."
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ â€” це ÑпоÑіб запропонувати Ñвої зміни до проєкту Ñ– обговорити Ñ—Ñ… із іншими"
@@ -26041,6 +26399,9 @@ msgstr "Ðерозпочаті задачі (відкриті та не приз
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr "ВикориÑтовуйте етапи Ð´Ð»Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ та запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ñ‚Ñгом фікÑованого періоду чаÑу"
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} завершено"
+
msgid "Min Value"
msgstr "Мінімальне значеннÑ"
@@ -26065,6 +26426,9 @@ msgstr ""
msgid "Mirror user"
msgstr "КориÑтувач Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ"
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr "Віддзеркалені репозиторії"
@@ -26329,6 +26693,9 @@ msgstr "Ім'Ñ Ð²Ð¶Ðµ зайнÑто."
msgid "Name new label"
msgstr "Ðазвіть нову мітку"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr "Ім’Ñ:"
@@ -26547,6 +26914,9 @@ msgstr "Ðовий розклад Конвеєра"
msgid "New Project"
msgstr "Ðовий Проєкт"
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr "Ðова вимога"
@@ -27049,6 +27419,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "КількіÑÑ‚ÑŒ комітів"
@@ -27230,10 +27603,10 @@ msgstr[3] ""
msgid "NotificationEmail|Reviewer"
msgid_plural "NotificationEmail|Reviewers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "оглÑдач"
+msgstr[1] "оглÑдача"
+msgstr[2] "оглÑдачів"
+msgstr[3] "оглÑдачів"
msgid "NotificationEmail|Reviewer: %{users}"
msgid_plural "NotificationEmail|Reviewers: %{users}"
@@ -27344,33 +27717,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} в %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email}, тепер відомий Ñк %{user_name}, прийнÑв ваше Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ %{target_name} %{target_model_name}."
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "%{invited_user} %{highlight_start}відхилив%{highlight_end} ваше Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ %{target_link} %{target_name}."
+msgid "Notify|%{issues} imported."
+msgstr "%{issues} імпортовано."
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} запроÑив %{member_role} доÑтуп до %{target_source_link} %{target_type}."
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr "ПіÑÐ»Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії ви можете %{a_start} подати запит на новий %{a_end}."
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -27392,12 +27798,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ CI/CD"
+msgid "Notify|Click here to set your password"
+msgstr "ÐатиÑніть тут, щоб уÑтановити пароль"
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr "Закомічено"
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "Знайдені помилки %{singular_or_plural_line}: %{error_lines}. Будь лаÑка, перевірте, чи ці Ñ€Ñдки мають заголовок проблеми."
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr "Відбиток: %{fingerprint}"
+msgid "Notify|Hi %{username}!"
+msgstr "Привіт %{username}!"
+
msgid "Notify|Hi %{user}!"
msgstr "Привіт %{user}!"
@@ -27416,6 +27840,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27438,26 +27865,68 @@ msgid "Notify|Merge request was approved"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ² Ñхвалений"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
+msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ² затверджений (%{approvals}/%{required_approvals})"
+
+msgid "Notify|Merge request was unapproved"
msgstr ""
-msgid "Notify|Milestone changed to %{milestone}"
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
msgstr ""
+msgid "Notify|Milestone changed to %{milestone}"
+msgstr "Етап змінено на %{milestone}"
+
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "Етап видалено"
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "Термін дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ñ‚ÑŒÑÑ Ñ‡ÐµÑ€ÐµÐ· 24 години."
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "Це поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ñ–Ð¹Ñне Ð´Ð»Ñ %{password_reset_token_valid_time}."
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27465,17 +27934,38 @@ msgid "Notify|You don't have access to the project."
msgstr "Ви не маєте доÑтупу до цього проєкту"
msgid "Notify|You have been mentioned in an issue."
-msgstr ""
+msgstr "Ð’Ð°Ñ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ у задачі."
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr "Ð’Ð°Ñ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ у запиті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{mr_link}"
-msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
msgstr ""
+msgid "Notify|Your account has been created successfully."
+msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² уÑпішно Ñтворений"
+
+msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
+msgstr "Ваш запит на Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ %{target_to_join} %{target_type} був %{denied_tag}."
+
msgid "Notify|currently supported languages"
msgstr "Ðаразі підтримуютьÑÑ Ð¼Ð¾Ð²Ð¸"
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr "увійти................................................."
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "УÑпішно завершено %{jobs} у %{stages}."
@@ -27536,6 +28026,9 @@ msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "Об’єкт не Ñ–Ñнує на Ñервері або у Ð²Ð°Ñ Ð½Ðµ має до нього доÑтупу"
+msgid "Observability"
+msgstr "СпоÑтережливіÑÑ‚ÑŒ"
+
msgid "Oct"
msgstr "жовт."
@@ -27577,7 +28070,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "Ðа лівій бічній панелі, виберіть %{merge_requests_link} Ð´Ð»Ñ Ñ—Ñ… переглÑду."
msgid "On track"
msgstr ""
@@ -27699,6 +28192,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -28261,6 +28757,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr "ВиÑтуп Ñ€Ñдка"
+
msgid "Overridden"
msgstr "Перевизначено"
@@ -28505,15 +29004,15 @@ msgstr[1] "Видалити %d реÑурÑи"
msgstr[2] "Видалити %d реÑурÑів"
msgstr[3] "Видалити %d реÑурÑів"
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr "Видалити верÑÑ–ÑŽ пакету"
msgid "PackageRegistry|Delete package"
msgstr "Видалити пакет"
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr "Видалити вибране"
@@ -28580,6 +29079,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "ОÑтаннє Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ %{dateTime}"
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "ДізнайтеÑÑ Ñк %{noPackagesLinkStart}публікувати та ділитиÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ пакетами%{noPackagesLinkEnd} через GitLab."
@@ -28613,15 +29115,15 @@ msgstr "КількіÑÑ‚ÑŒ дублікатів, Ñкі потрібно збеÑ
msgid "PackageRegistry|Package Registry"
msgstr "РеєÑÑ‚Ñ€ пакетів"
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
msgid "PackageRegistry|Package deleted successfully"
msgstr "Пакет уÑпішно видалено"
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr ""
-
msgid "PackageRegistry|Package formats"
msgstr "Формати пакетів"
@@ -28635,6 +29137,9 @@ msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr "Пакет оновлено через коміт %{link} в гілці %{branch}, побудований через конвеєр %{pipeline}та опублікований в реєÑÑ‚Ñ€ %{datetime}"
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28686,10 +29191,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28746,8 +29251,8 @@ msgstr "Коли пакет із такою ж назвою та верÑією
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{name}, Ñ– Ñ†Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ñ” незворотною. Ви впевнені?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28772,7 +29277,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr "опубліковано %{author}"
msgid "Packages and registries"
-msgstr ""
+msgstr "Пакети та реєÑтри"
msgid "Page not found"
msgstr "Сторінку не знайдено"
@@ -28963,9 +29468,6 @@ msgstr ""
msgid "Pause"
msgstr "Призупинити"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -29368,9 +29870,21 @@ msgstr "Ðктивні"
msgid "PipelineSchedules|All"
msgstr "Ð’ÑÑ–"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "Ðеактивні"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "ÐаÑтупний запуÑк"
@@ -29380,15 +29894,27 @@ msgstr "Ðемає"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr "Лише влаÑник розкладу конвеєрів може внеÑти до нього зміни. Ви хочете взÑти право влаÑноÑÑ‚Ñ– на цей розклад?"
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Задайте короткий Ð¾Ð¿Ð¸Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ конвеєру"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "Стати влаÑником"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "Ціль"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "Змінні"
@@ -29503,6 +30029,12 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² Ð´Ð»Ñ \"%{project_name}\" Ñ
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr "%{jobs} %{ref_text} у %{duration}"
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29510,7 +30042,7 @@ msgid "Pipelines|2. Configure deployment pipeline"
msgstr ""
msgid "Pipelines|A GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. Install GitLab Runner and register your own runners to get started with CI/CD."
-msgstr "GitLab Runner — це заÑтоÑунок, Ñкий працює з GitLab CI/CD Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½ÑŒ у конвеєрі. Ð’Ñтановіть GitLab Runner та зареєÑтруйте влаÑні runner'и Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку з CI/CD."
+msgstr "GitLab ранер — це заÑтоÑунок, Ñкий працює з GitLab CI/CD Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½ÑŒ у конвеєрі. Ð’Ñтановіть GitLab ранер та зареєÑтруйте влаÑні ранери Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку з CI/CD."
msgid "Pipelines|API"
msgstr "API"
@@ -29660,7 +30192,7 @@ msgid "Pipelines|Set up a runner"
msgstr ""
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr "Помилка при очищенні кеша runner'ів."
+msgstr "Помилка при очищенні кеша ранерів."
msgid "Pipelines|The %{namespace_name} namespace has %{percentage}%% or less Shared Runner Pipeline minutes remaining. After it runs out, no new jobs or pipelines in its projects will run."
msgstr ""
@@ -30184,6 +30716,9 @@ msgstr "Будь лаÑка, введіть %{phrase_code} Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "Будь лаÑка, викориÑтовуйте цю форму щоб повідомити адміну Ñкі кориÑтувачі Ñтворюють Ñпам (задачі або коментарі) або поводÑÑ‚ÑŒÑÑ Ð½ÐµÐ½Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼ чином."
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "Будь лаÑка, зачекайте, Ñ†Ñ Ñторінка автоматично оновитьÑÑ, коли буде готова."
@@ -30193,6 +30728,9 @@ msgstr "Будь лаÑка, почекайте поки ми з’єднуємÐ
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Будь лаÑка, почекайте поки ми імпортуємо ваш репозиторій. Оновлюйте Ñторінку за бажаннÑм."
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr "Pod’и у викориÑтанні"
@@ -30253,6 +30791,9 @@ msgstr "Параметри"
msgid "Preferences saved."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð¾."
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "Поведінка"
@@ -30364,6 +30905,9 @@ msgstr "Параметри чаÑу"
msgid "Preferences|Use relative times"
msgstr "ВикориÑтовувати відноÑний чаÑ"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "Коли ви вводите Ð¾Ð¿Ð¸Ñ Ð°Ð±Ð¾ поле коментарÑ, виділений текÑÑ‚ оточуєтьÑÑ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¸Ð¼ Ñимволом піÑÐ»Ñ Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ з таких Ñимволів: %{supported_characters}."
@@ -30577,15 +31121,9 @@ msgstr "Ðктивний"
msgid "Profiles|Add key"
msgstr "Додати ключ"
-msgid "Profiles|Add status emoji"
-msgstr "Додати Ñмайлик-ÑтатуÑ"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr "Обрізка аватарів"
@@ -30598,9 +31136,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr "Про Ñебе"
-msgid "Profiles|Busy"
-msgstr "ЗайнÑтий"
-
msgid "Profiles|Change username"
msgstr "Змінити ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
@@ -30616,9 +31151,6 @@ msgstr "Виберіть Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ внеÑків до приватнÐ
msgid "Profiles|City, country"
msgstr "МіÑто, країна"
-msgid "Profiles|Clear status"
-msgstr "ОчиÑтити ÑтатуÑ"
-
msgid "Profiles|Commit email"
msgstr "ÐдреÑа електронної пошти Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²"
@@ -30631,6 +31163,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Підключені облікові запиÑи"
+msgid "Profiles|Created%{time_ago}"
+msgstr "Створено%{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "Поточний шлÑÑ…: %{path}"
@@ -30868,9 +31403,6 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñмайликів в іменах виглÑд
msgid "Profiles|Website url"
msgstr "ÐдреÑа Ñайту"
-msgid "Profiles|What's your status?"
-msgstr "Який ваш ÑтатуÑ?"
-
msgid "Profiles|Who you represent or work for."
msgstr "Кого ви предÑтавлÑєте або на кого працюєте."
@@ -30916,9 +31448,6 @@ msgstr "Ваше Ñ–Ð¼â€™Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановленÐ
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "Ваше Ñ–Ð¼â€™Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановлено на оÑнові вашого облікового запиÑу %{provider_label}, щоб люди могли Ð²Ð°Ñ Ð²Ð¿Ñ–Ð·Ð½Ð°Ñ‚Ð¸."
-msgid "Profiles|Your status"
-msgstr "Ваш ÑтатуÑ"
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -31367,7 +31896,7 @@ msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
msgstr ""
msgid "ProjectSettings|Additional options"
-msgstr ""
+msgstr "Додаткові параметри"
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr "Додаткові налаштуваннÑ, Ñкі впливають на те, Ñк Ñ– коли виконуютьÑÑ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ."
@@ -31408,6 +31937,9 @@ msgstr "Виберіть метод злиттÑ, Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð°
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "Ðалаштуйте реÑурÑи вашого проєкту Ñ– відÑтежуйте Ñ—Ñ… здоров'Ñ."
@@ -31438,6 +31970,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31505,7 +32040,7 @@ msgid "ProjectSettings|If merge trains are enabled, merging is only possible if
msgstr ""
msgid "ProjectSettings|Internal"
-msgstr "Внутрішні"
+msgstr "Внутрішній"
msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
@@ -31561,12 +32096,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Тільки підпиÑані коміти можуть бути надіÑлані в цей репозиторій."
@@ -31603,6 +32144,9 @@ msgstr "ВидиміÑÑ‚ÑŒ проєкту"
msgid "ProjectSettings|Public"
msgstr "Публічний"
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr "Репозиторій"
@@ -31715,7 +32259,7 @@ msgid "ProjectSettings|Users can only push commits to this repository if the com
msgstr ""
msgid "ProjectSettings|Users can request access"
-msgstr ""
+msgstr "КориÑтувачі можуть запитувати доÑтуп"
msgid "ProjectSettings|View and edit files in this project."
msgstr "ПереглÑдати та редагувати файли в цьому проєкті."
@@ -31756,7 +32300,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Вікі"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31846,6 +32390,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr "ÐктивніÑÑ‚ÑŒ"
@@ -32368,6 +32915,9 @@ msgstr "Дозволена відправка"
msgid "ProtectedBranch|Allowed to push:"
msgstr "Дозволена відправка:"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr "Гілка"
@@ -32404,6 +32954,9 @@ msgstr "Захищена гілка (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "Захищені гілки"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32428,6 +32981,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32584,6 +33140,9 @@ msgstr ""
msgid "Pull"
msgstr "Отримати (pull)"
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32653,18 +33212,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32815,9 +33404,6 @@ msgstr "Докладніше"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32975,9 +33561,6 @@ msgstr "ЗареєÑтрувати універÑальний двофактор
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33520,7 +34103,7 @@ msgid "Reply to comment"
msgstr "ВідповіÑти на коментар"
msgid "Reply to this email directly or %{view_it_on_gitlab}."
-msgstr "ВідповіÑти на це електронне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿Ð¾Ñередньо або %{view_it_on_gitlab}."
+msgstr "ВідповіÑти на це електронне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ %{view_it_on_gitlab}."
msgid "Reply…"
msgstr ""
@@ -33877,6 +34460,9 @@ msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -34271,6 +34857,9 @@ msgstr "Відкликано токен Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "Відкликано перÑональний токен доÑтупу %{personal_access_token_name}!"
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -34292,6 +34881,9 @@ msgstr "Роль"
msgid "Rollback"
msgstr "Відкотити"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -34338,19 +34930,19 @@ msgid "Runner tokens"
msgstr ""
msgid "Runner was not updated."
-msgstr "Runner не було оновлено."
+msgstr "Ранер не було оновлено."
msgid "Runner was successfully updated."
-msgstr "Runner оновлено уÑпішно."
+msgstr "Ранер оновлено уÑпішно."
msgid "Runners"
-msgstr "Runner'и"
+msgstr "Ранери"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
msgid "Runners page."
-msgstr "Сторінка Runner'ів."
+msgstr "Сторінка ранерів."
msgid "Runners|%d selected runner deleted"
msgid_plural "Runners|%d selected runners deleted"
@@ -34483,7 +35075,7 @@ msgid "Runners|Delete selected"
msgstr "Видалити вибрані"
msgid "Runners|Deploy GitLab Runner in AWS"
-msgstr "Розгортати Runner GitLab в AWS"
+msgstr "Розгортати ранер GitLab в AWS"
msgid "Runners|Description"
msgstr "ОпиÑ"
@@ -34524,6 +35116,9 @@ msgstr "Розпочати роботу з runner'ами"
msgid "Runners|Group"
msgstr "Група"
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34557,9 +35152,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr "Ім'Ñ"
@@ -34569,6 +35161,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr "Ðіколи не закінчуєтьÑÑ"
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34639,6 +35234,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr "ЗареєÑтрувати runner інÑтанÑа"
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "Токен Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
@@ -34655,18 +35253,21 @@ msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
msgid "Runners|Runner"
-msgstr "Runner"
+msgstr "Ранер"
msgid "Runners|Runner #%{runner_id}"
-msgstr "Runner #%{runner_id}"
+msgstr "Ранер #%{runner_id}"
msgid "Runners|Runner %{name} was deleted"
-msgstr "Runner %{name} було видалено"
+msgstr "Ранер %{name} було видалено"
msgid "Runners|Runner assigned to project."
-msgstr "Runner призначено Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
+msgstr "Ранер призначено Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
+
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34709,13 +35310,16 @@ msgid "Runners|Runner registration"
msgstr ""
msgid "Runners|Runner statuses"
-msgstr "СтатуÑи Runner"
+msgstr "СтатуÑи ранер"
msgid "Runners|Runner unassigned from project."
msgstr ""
msgid "Runners|Runners"
-msgstr "Runner'и"
+msgstr "Ранери"
+
+msgid "Runners|Runners are either:"
+msgstr ""
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34729,6 +35333,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr "Показати інÑтрукції Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° реєÑтрації runner"
@@ -34759,6 +35366,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr "Теги"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34799,6 +35409,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr "Термін дії токену"
+
msgid "Runners|Up to date"
msgstr "Ð’ актуальному Ñтані"
@@ -34857,7 +35470,7 @@ msgid "Runners|You can set up a specific runner to be used by multiple projects
msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
-msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних runner'ів."
+msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних ранерів."
msgid "Runners|active"
msgstr "активні"
@@ -35018,9 +35631,6 @@ msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr "%{ifLabelStart}Ñкщо%{ifLabelEnd} %{rules} дії Ð´Ð»Ñ %{scopes} %{branches}"
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr "%{period} %{days} на %{time}"
@@ -35168,6 +35778,9 @@ msgstr "Пошук виконавців"
msgid "Search authors"
msgstr "Пошук авторів"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "Пошук у гілках"
@@ -35255,6 +35868,9 @@ msgstr "Пошук проєктів"
msgid "Search projects..."
msgstr "Пошук проєктів..."
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35581,13 +36197,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "Ðе увімкнено"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35644,9 +36260,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -36049,6 +36662,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Створити задачу"
+msgid "SecurityReports|Detection"
+msgstr "ВиÑвленнÑ"
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -36061,6 +36677,9 @@ msgstr "Відхилено \"%{vulnerabilityName}\""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "Відхилено \"%{vulnerabilityName}\". Щоб переглÑнути вимкніть перемикач \"Ñховати відхилені\"."
+msgid "SecurityReports|Does not have issue"
+msgstr "Ðе має задачі"
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -36091,12 +36710,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr "Має задачу"
+
msgid "SecurityReports|Hide dismissed"
msgstr "Сховати відхилені"
msgid "SecurityReports|Image"
msgstr "Образ"
+msgid "SecurityReports|Issue"
+msgstr "Задача"
+
msgid "SecurityReports|Issue Created"
msgstr "Задача Ñтворена"
@@ -36214,6 +36839,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "СтатуÑ"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -36337,9 +36965,6 @@ msgstr "Виберіть формат архіву"
msgid "Select Git revision"
msgstr "Вибрати ревізію Git"
-msgid "Select Page"
-msgstr "Вибрати Ñторінку"
-
msgid "Select Profile"
msgstr ""
@@ -36385,9 +37010,6 @@ msgstr "Вибрати шаблон репозиторію"
msgid "Select a template type"
msgstr "Вибрати тип шаблону"
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "Вибрати чаÑовий поÑÑ"
@@ -36409,9 +37031,15 @@ msgstr ""
msgid "Select branch"
msgstr "Виберіть гілку"
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "Виберіть заплановану дату завершеннÑ"
@@ -36457,6 +37085,9 @@ msgstr "Виберіть проєкт Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ–"
msgid "Select projects"
msgstr "Вибрати проєкти"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "Вибрати оглÑдача(ів)"
@@ -36769,6 +37400,9 @@ msgstr "Ð’Ñтановити цільову гілку"
msgid "Set target branch to %{branch_name}."
msgstr "Ð’Ñтановити цільову гілку %{branch_name}."
+msgid "Set the Draft status"
+msgstr "Ð’Ñтановити ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡ÐµÑ€Ð½ÐµÑ‚ÐºÐ¸"
+
msgid "Set the Ready status"
msgstr ""
@@ -36844,18 +37478,15 @@ msgstr "Ð’Ñтановити вагу"
msgid "Set weight to %{weight}."
msgstr "Ð’Ñтановити вагу %{weight}."
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr "ЗайнÑтий"
-
msgid "SetStatusModal|Clear status"
msgstr "ОчиÑтити ÑтатуÑ"
msgid "SetStatusModal|Clear status after"
msgstr "ОчиÑтити ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ–ÑлÑ"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Змінити ÑтатуÑ"
@@ -36868,6 +37499,9 @@ msgstr "Ð’Ñтановити ÑтатуÑ"
msgid "SetStatusModal|Set status"
msgstr "Ð’Ñтановити ÑтатуÑ"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "Вибачте, нам не вдалоÑÑ Ð²Ñтановити ваш ÑтатуÑ. Будь лаÑка, Ñпробуйте знову пізніше."
@@ -36951,7 +37585,7 @@ msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with mem
msgstr ""
msgid "Shared Runners"
-msgstr "Загальні Runner'и"
+msgstr "Загальні ранери"
msgid "Shared projects"
msgstr "Спільні проєкти"
@@ -37473,6 +38107,39 @@ msgstr "Вкажіть Ñлово, Ñке найбільше підходить
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37495,7 +38162,7 @@ msgid "SnippetsEmptyState|Code snippets"
msgstr ""
msgid "SnippetsEmptyState|Documentation"
-msgstr ""
+msgstr "ДокументаціÑ"
msgid "SnippetsEmptyState|New snippet"
msgstr "Ðовий Ñніпет"
@@ -37539,6 +38206,9 @@ msgstr ""
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37779,6 +38449,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37821,6 +38494,9 @@ msgstr "ОÑтанній контакт"
msgid "SortOptions|Last created"
msgstr "ОÑтанній Ñтворений"
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr "Ðайменш популÑрний"
@@ -37881,6 +38557,9 @@ msgstr "Ðайдавніше в обраних"
msgid "SortOptions|Oldest updated"
msgstr "Оновлений найраніше"
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr "ПопулÑрніÑÑ‚ÑŒ"
@@ -38781,8 +39460,8 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
-msgstr ""
+msgid "SuggestedColors|Lavender"
+msgstr "Лавандовий"
msgid "SuggestedColors|Magenta-pink"
msgstr ""
@@ -38805,9 +39484,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38844,7 +39535,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38853,7 +39550,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38971,25 +39668,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr "Ваша підпиÑка"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -40073,7 +40782,7 @@ msgid "The maximum file size is %{size}."
msgstr "МакÑимальний розмір файлу це %{size}."
msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
-msgstr "МакÑимальна кількіÑÑ‚ÑŒ CI/CD хвилин Ð´Ð»Ñ Ñпільних runner'ів, Ñкі можна викориÑтовувати щоміÑÑцÑ. 0 - без обмежень."
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ CI/CD хвилин Ð´Ð»Ñ Ñпільних ранерів, Ñкі можна викориÑтовувати щоміÑÑцÑ. 0 - без обмежень."
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 ""
@@ -40198,6 +40907,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr "Секрет доÑтупний лише при першому Ñтворенні програми."
+
msgid "The snippet can be accessed without any authentication."
msgstr "ДоÑтуп до Ñніпета можливий без будь-Ñкої автентифікації."
@@ -40405,9 +41117,6 @@ msgstr "Ðемає даних"
msgid "There is no data available. Please change your selection."
msgstr "Даних немає. Будь лаÑка, змініть Ñвій вибір."
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40675,9 +41384,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40741,6 +41447,9 @@ msgstr "Цей блок поÑилаєтьÑÑ Ñам на Ñебе"
msgid "This board's scope is reduced"
msgstr "ВидиміÑÑ‚ÑŒ цієї дошки обмежена"
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40786,6 +41495,9 @@ msgstr "Термін дії цих облікових даних закінчиÐ
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð· Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ðµ запуÑкаєтьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ Ñ– повинно бути запущено вручну, але воно Ñтаріше за оÑтаннє Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ– тому не може бути запущене."
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40834,6 +41546,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Цей епік не Ñ–Ñнує або у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтатніх дозволів."
@@ -40930,6 +41663,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr "Це єдиний раз, коли Ñекрет доÑтупний. Скопіюйте Ñ– збережіть його."
+
msgid "This is your current session"
msgstr "Це ваш поточний ÑеанÑ"
@@ -41027,7 +41763,7 @@ msgid "This job is deployed to %{environmentLink}."
msgstr "Це Ð·Ð°Ð´Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¾ на %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ±ÑƒÐ²Ð°Ñ” в Ñтані Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ– чекає на запуÑк Runner"
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ±ÑƒÐ²Ð°Ñ” в Ñтані Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ– чекає на запуÑк ранер"
msgid "This job is performing tasks that must complete before it can start"
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÑ” кроки, Ñкі повинні бути завершені перед його початком"
@@ -41146,6 +41882,9 @@ msgstr "Цей проєкт заархівовано і його не можна
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -41158,12 +41897,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -41251,6 +41996,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41598,6 +42346,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Щоб додати Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ, надайте наÑтупні відомоÑÑ‚Ñ– заÑтоÑунку у вашому телефоні."
@@ -41631,6 +42382,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr "Ð”Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… кориÑтувачів, Ñпочатку вÑтановіть Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів \"зовнішній по замовчанню\""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41850,9 +42604,6 @@ msgstr "Перемкнути Ð¾Ð¿Ð¸Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²"
msgid "Toggle commit list"
msgstr "Відкрити або закрити ÑпиÑок комітів"
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr "Увімкнути/вимкнути Ñмайлики-нагороди"
@@ -41874,9 +42625,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr "Перемикач бічної панелі"
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr "Увімкнути/вимкнути панель продуктивноÑÑ‚Ñ–"
@@ -41902,7 +42650,7 @@ msgid "Tokens|Scopes set the permission levels granted to the token."
msgstr ""
msgid "Tokens|Select scopes"
-msgstr ""
+msgstr "Вибрати облаÑÑ‚ÑŒ дії"
msgid "Tomorrow"
msgstr "Завтра"
@@ -41923,13 +42671,13 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr ""
msgid "TopNav|Explore"
-msgstr ""
+msgstr "ОглÑд"
msgid "TopNav|Go back"
msgstr ""
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "Перейти до"
msgid "TopNav|Your dashboards"
msgstr ""
@@ -41988,6 +42736,9 @@ msgstr "Загальний розмір артефактів: %{total_size}"
msgid "Total cores (CPUs)"
msgstr "Ð’Ñього Ñдер (ЦП)"
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr "Ð’Ñього памʼÑÑ‚Ñ– (ГБ)"
@@ -42117,9 +42868,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "ПовернутиÑÑ Ð´Ð¾ GitLab"
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -42135,6 +42883,13 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
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 ""
@@ -42805,7 +43560,7 @@ msgid "Usage statistics"
msgstr "СтатиÑтика викориÑтаннÑ"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
-msgstr "%{help_link_start}Загальні runner'и%{help_link_end} вимкнено, тому ліміти на викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² відÑутні"
+msgstr "%{help_link_start}Загальні ранери%{help_link_end} вимкнено, тому ліміти на викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² відÑутні"
msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there are no limits set on pipeline usage"
msgstr ""
@@ -42816,6 +43571,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr "Ðртефакти"
@@ -42858,10 +43616,10 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð° поточний період"
msgid "UsageQuota|Dependency proxy"
msgstr "ПрокÑÑ– залежноÑтей"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42936,9 +43694,6 @@ msgstr "Репозиторій"
msgid "UsageQuota|Seats"
msgstr "МіÑцÑ"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42972,8 +43727,8 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
-msgstr "ПроÑÑ‚Ñ–Ñ€ імен наразі викориÑтовує %{strong_start}%{used_storage}%{strong_end} пам’ÑÑ‚Ñ– проÑтору імен. ВлаÑники груп можуть переглÑдати викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору імен Ñ– купувати більше в %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
msgstr "ПроÑÑ‚Ñ–Ñ€ імен наразі викориÑтовує %{strong_start}%{used_storage}%{strong_end} пам’ÑÑ‚Ñ– проÑтору імен. ПереглÑдайте та керуйте Ñвоїм викориÑтаннÑм із %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{link_end} про те, Ñк зменшити пам’ÑÑ‚ÑŒ."
@@ -42994,7 +43749,7 @@ msgid "UsageQuota|This namespace contains locked projects"
msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
-msgstr "Цей проÑÑ‚Ñ–Ñ€ імен не міÑтить проєктів, що викориÑтовують загальні runner'и"
+msgstr "Цей проÑÑ‚Ñ–Ñ€ імен не міÑтить проєктів, що викориÑтовують загальні ранери"
msgid "UsageQuota|This namespace has no projects which used shared runners in the current period"
msgstr ""
@@ -43315,6 +44070,9 @@ msgstr "Ідентифікацію кориÑтувача уÑпішно видÐ
msgid "User identity was successfully updated."
msgstr "Ідентифікацію кориÑтувача уÑпішно оновлено."
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43636,9 +44394,6 @@ msgstr "КориÑтувачі, Ñкі запитують доÑтуп до"
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr "КориÑтувачів уÑпішно додано."
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43657,9 +44412,36 @@ msgstr "Ðемає Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ â€” %{openingTag} призначити нÐ
msgid "UsersSelect|Unassigned"
msgstr "Ðепризначено"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
msgstr ""
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr "ВикориÑтовувати GitLab Ñк альтернативу Sentry."
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{code_start}::%{code_end} вказує на %{link_start}набір Ñелективних міток%{link_end}"
@@ -43918,6 +44700,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "ПереглÑнути графік"
@@ -43943,8 +44728,8 @@ msgstr "ПереглÑнути документацію"
msgid "View eligible approvers"
msgstr "ПереглÑнути доÑтупних оÑіб Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
-msgid "View epics list"
-msgstr "ПереглÑнути ÑпиÑок епіків"
+msgid "View entire blame"
+msgstr ""
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -44371,6 +45156,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr "Файл"
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -44392,12 +45180,12 @@ msgstr "Образ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
-
msgid "Vulnerability|Links"
msgstr "ПоÑиланнÑ"
+msgid "Vulnerability|Location"
+msgstr ""
+
msgid "Vulnerability|Method"
msgstr "Метод"
@@ -44407,6 +45195,9 @@ msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Vulnerability|Project"
msgstr "Проєкт"
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -44434,6 +45225,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Рівень"
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr "СтатуÑ"
@@ -44446,6 +45240,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -44458,6 +45255,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44521,6 +45321,12 @@ msgstr "Ðе вдалоÑÑ Ð¿Ñ–Ð´ÐºÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑ Ð´Ð¾ Ñервера Prometheu
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Ми виÑвили потенційний Ñпам у %{humanized_resource_name}. Будь лаÑка, введіть цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ reCAPTCHA, щоб продовжити."
@@ -44731,6 +45537,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "Увімкнути перевірку SSL"
@@ -44746,12 +45555,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44776,6 +45591,12 @@ msgstr "Перевірка SSL"
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44800,6 +45621,9 @@ msgstr "URL-адреÑа"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44879,7 +45703,7 @@ msgid "What does this command do?"
msgstr "Що робить Ñ†Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°?"
msgid "What is GitLab Runner?"
-msgstr "Що таке GitLab Runner?"
+msgstr "Що таке GitLab ранер?"
msgid "What is Markdown?"
msgstr ""
@@ -44982,12 +45806,6 @@ msgstr ""
msgid "Wiki"
msgstr "Вікі"
-msgid "Wiki Page|Rich text"
-msgstr "Розширений текÑÑ‚"
-
-msgid "Wiki Page|Source"
-msgstr "Джерело"
-
msgid "Wiki page"
msgstr ""
@@ -45208,10 +46026,10 @@ msgid "Work in progress Limit"
msgstr ""
msgid "WorkItem|%{workItemType} deleted"
-msgstr ""
+msgstr "%{workItemType} видалено"
msgid "WorkItem|Add"
-msgstr ""
+msgstr "Додати"
msgid "WorkItem|Add a title"
msgstr "Додати заголовок"
@@ -45222,6 +46040,12 @@ msgstr "Додати виконавцÑ"
msgid "WorkItem|Add assignees"
msgstr "Додати виконавців"
+msgid "WorkItem|Add due date"
+msgstr "Додати термін виконаннÑ"
+
+msgid "WorkItem|Add start date"
+msgstr "Додати дату початку"
+
msgid "WorkItem|Add task"
msgstr ""
@@ -45229,7 +46053,7 @@ msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr ""
msgid "WorkItem|Are you sure you want to delete the %{workItemType}? This action cannot be reversed."
-msgstr ""
+msgstr "Ви впевнені, що хочете видалити %{workItemType}? Цю дію неможливо ÑкаÑувати."
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -45239,16 +46063,16 @@ msgstr[2] "Виконавців"
msgstr[3] "Виконавців"
msgid "WorkItem|Cancel"
-msgstr ""
+msgstr "СкаÑувати"
msgid "WorkItem|Child removed"
msgstr "Дочірній елемент видалено"
msgid "WorkItem|Closed"
-msgstr ""
+msgstr "Закрито"
msgid "WorkItem|Collapse tasks"
-msgstr ""
+msgstr "Згорнути завданнÑ"
msgid "WorkItem|Create task"
msgstr ""
@@ -45256,8 +46080,14 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr "Дати"
+
msgid "WorkItem|Delete %{workItemType}"
-msgstr ""
+msgstr "Видалити %{workItemType}"
+
+msgid "WorkItem|Due date"
+msgstr "Дата виконаннÑ"
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -45284,7 +46114,7 @@ msgid "WorkItem|Only project members with at least the Reporter role, the author
msgstr "Лише учаÑники проєкту з принаймні роллю Репортера, автор Ñ– виконавці можуть переглÑдати це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ отримувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ нього."
msgid "WorkItem|Open"
-msgstr ""
+msgstr "Відкрити"
msgid "WorkItem|Remove"
msgstr "Видалити"
@@ -45296,7 +46126,7 @@ msgid "WorkItem|Select type"
msgstr "Вибрати тип"
msgid "WorkItem|Something went wrong when creating %{workItemType}. Please try again."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{workItemType}. Будь лаÑка Ñпробуйте ще раз."
msgid "WorkItem|Something went wrong when deleting the %{workItemType}. Please try again."
msgstr ""
@@ -45317,7 +46147,7 @@ msgid "WorkItem|Something went wrong when trying to add a child. Please try agai
msgstr ""
msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ñпроби Ñтворити дочірній елемент ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "WorkItem|Something went wrong while updating the %{workItemType}. Please try again."
msgstr ""
@@ -45325,6 +46155,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr "Дата початку"
+
msgid "WorkItem|Task"
msgstr ""
@@ -45353,7 +46186,7 @@ msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item"
-msgstr ""
+msgstr "Робочий елемент"
msgid "Would you like to create a new branch?"
msgstr ""
@@ -45591,6 +46424,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45714,6 +46553,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Ви не можете отримати доÑтуп до неформатованого файлу. Будь лаÑка, зачекайте хвилину."
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45916,7 +46758,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45934,7 +46776,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -46529,6 +47371,9 @@ msgstr "додано"
msgid "added %{emails}"
msgstr "додано %{emails}"
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr "додано дзвінок Zoom до цієї задачі"
@@ -46627,6 +47472,9 @@ msgstr "від"
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46672,6 +47520,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46940,6 +47791,9 @@ msgstr "Знайдено %{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr "Повний звіт"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -47101,6 +47955,9 @@ msgstr ""
msgid "comment"
msgstr "коментар"
+msgid "commented"
+msgstr "прокоментовано"
+
msgid "commented on %{link_to_project}"
msgstr "прокоментовано в %{link_to_project}"
@@ -47146,6 +48003,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -47297,7 +48157,7 @@ msgid "finding is not found or is already attached to a vulnerability"
msgstr "знахідку втрачено або вже закріплено за вразливіÑÑ‚ÑŽ"
msgid "following"
-msgstr "читає"
+msgstr "підпиÑки"
msgid "for"
msgstr ""
@@ -47479,9 +48339,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47572,6 +48429,13 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr "доÑÑгнуто ліміт %{project_limit}"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "load it anyway"
msgstr "вÑе одно завантажити"
@@ -47613,6 +48477,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr "відÑутні"
@@ -47984,6 +48851,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr "не повинно міÑтити загальновживаних Ñполучень Ñлів Ñ– букв"
+
msgid "my-awesome-group"
msgstr ""
@@ -48065,9 +48935,6 @@ msgstr "або"
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "із %d теÑту"
@@ -48219,6 +49086,9 @@ msgstr "видалити вагу"
msgid "removed"
msgstr "видалено"
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr "видалено дзвінок Zoom із цієї задачі"
@@ -48253,6 +49123,13 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "помилка при Ñтворенні запиту на злиттÑ"
@@ -48361,6 +49238,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "назва тегу"
@@ -48427,6 +49307,13 @@ msgstr "оновлено %{time_ago}"
msgid "uploads"
msgstr "завантаженнÑ"
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "user avatar"
msgstr "аватар кориÑтувача"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 99668716f67..984a7761bc6 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 14:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 41cfb1907e9..3e7ecfe06a7 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -138,6 +138,11 @@ msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -1024,11 +1029,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1065,6 +1065,11 @@ msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge
msgstr[0] ""
msgstr[1] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1096,9 +1101,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1132,6 +1134,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1153,10 +1158,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1180,6 +1188,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1665,9 +1679,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1686,6 +1697,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2367,12 +2387,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2766,9 +2780,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2781,6 +2801,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2802,6 +2825,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2838,6 +2864,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2889,9 +2918,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -3078,6 +3119,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3417,9 +3461,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3846,6 +3902,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3921,6 +3980,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4209,9 +4271,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4457,6 +4516,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4680,6 +4742,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5323,6 +5388,9 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5994,6 +6062,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6315,7 +6386,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6353,6 +6424,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6671,6 +6745,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6707,33 +6784,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6743,6 +6865,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -7043,6 +7177,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7216,6 +7353,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7225,7 +7365,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7486,7 +7626,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7681,6 +7821,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8695,6 +8838,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8794,6 +8940,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8820,6 +8969,9 @@ msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
msgstr[1] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8829,6 +8981,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8895,6 +9050,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9563,6 +9721,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9668,6 +9829,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9737,7 +9901,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -10055,6 +10219,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10511,13 +10678,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10841,6 +11008,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -11057,6 +11227,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -11069,6 +11242,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12324,6 +12503,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12510,6 +12695,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12654,6 +12842,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12993,6 +13184,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -13038,6 +13232,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -13059,6 +13256,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -13074,6 +13274,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13259,18 +13465,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13339,25 +13536,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13378,7 +13572,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13399,12 +13593,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13947,6 +14135,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14313,6 +14513,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14451,9 +14654,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14571,6 +14771,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14919,6 +15122,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14952,6 +15158,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14976,6 +15185,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -16074,9 +16286,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16760,6 +16969,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16889,14 +17101,47 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
msgstr[1] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -17158,6 +17403,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17497,6 +17745,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17719,9 +17970,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18586,6 +18834,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18622,6 +18873,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18838,7 +19092,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19183,6 +19437,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19201,6 +19461,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19222,7 +19485,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19268,6 +19531,9 @@ msgstr[1] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19313,7 +19579,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19746,24 +20012,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19803,16 +20090,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19824,6 +20117,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19833,10 +20132,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19917,6 +20219,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19926,6 +20234,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -20107,6 +20418,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -20131,6 +20445,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -21036,6 +21353,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21257,6 +21577,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21317,12 +21640,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21335,6 +21664,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21527,9 +21859,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21922,6 +22251,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -22021,6 +22356,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22393,9 +22731,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23243,6 +23578,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23324,7 +23662,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -24113,6 +24451,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -24164,10 +24505,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24251,9 +24592,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24263,9 +24619,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24278,7 +24631,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24515,6 +24868,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25645,6 +26001,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25669,6 +26028,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25933,6 +26295,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -26147,6 +26512,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26647,6 +27015,9 @@ msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{stron
msgstr[0] ""
msgstr[1] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26934,33 +27305,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26982,12 +27386,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -27006,6 +27428,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -27030,6 +27455,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -27039,15 +27470,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -27060,12 +27527,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -27126,6 +27614,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27287,6 +27778,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27847,6 +28341,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -28089,15 +28586,15 @@ msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
msgstr[1] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -28164,6 +28661,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -28197,13 +28697,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28217,6 +28717,9 @@ msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28268,10 +28771,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28328,7 +28831,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28543,9 +29046,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28948,9 +29448,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28960,15 +29472,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -29083,6 +29607,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29764,6 +30294,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29773,6 +30306,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29833,6 +30369,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29944,6 +30483,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -30157,15 +30699,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -30178,9 +30714,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -30196,9 +30729,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30211,6 +30741,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30448,9 +30981,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30496,9 +31026,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30988,6 +31515,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -31018,6 +31548,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -31141,12 +31674,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -31183,6 +31722,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31336,7 +31878,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31426,6 +31968,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31948,6 +32493,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31984,6 +32532,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -32008,6 +32559,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -32164,6 +32718,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32233,18 +32790,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32395,9 +32982,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32553,9 +33137,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33439,6 +34020,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33825,6 +34409,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33846,6 +34433,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -34070,6 +34660,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -34103,9 +34696,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -34115,6 +34705,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -34183,6 +34776,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -34210,7 +34806,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34261,6 +34860,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34273,6 +34875,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34303,6 +34908,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34341,6 +34949,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34560,9 +35171,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34710,6 +35318,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34797,6 +35408,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -35101,13 +35715,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -35164,9 +35778,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35569,6 +36180,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35581,6 +36195,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35611,12 +36228,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35734,6 +36357,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35857,9 +36483,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35905,9 +36528,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35929,9 +36549,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35977,6 +36603,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36289,6 +36918,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36364,18 +36996,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36388,6 +37017,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36989,6 +37621,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -37055,6 +37720,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37295,6 +37963,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37337,6 +38008,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37397,6 +38071,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38297,7 +38974,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38321,9 +38998,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38360,7 +39049,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38369,7 +39064,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38485,25 +39180,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39694,6 +40401,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39901,9 +40611,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -40171,9 +40878,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -40237,6 +40941,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40282,6 +40989,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40330,6 +41040,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40426,6 +41157,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40642,6 +41376,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40654,12 +41391,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40747,6 +41490,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -41090,6 +41836,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -41123,6 +41872,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41342,9 +42094,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41366,9 +42115,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41480,6 +42226,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41609,9 +42358,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41627,6 +42373,11 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+msgstr[1] ""
+
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 ""
@@ -42308,6 +43059,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42350,10 +43104,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42428,9 +43182,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42464,7 +43215,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42805,6 +43556,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -43126,9 +43880,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -43147,7 +43898,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43408,6 +44186,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43431,7 +44212,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43855,6 +44636,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43876,10 +44660,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43891,6 +44675,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43918,6 +44705,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43930,6 +44720,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43942,6 +44735,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -44005,6 +44801,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -44215,6 +45017,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -44230,12 +45035,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44260,6 +45071,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44284,6 +45101,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44462,12 +45282,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44702,6 +45516,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44734,9 +45554,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44803,6 +45629,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -45065,6 +45894,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -45188,6 +46023,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45388,7 +46226,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45406,7 +46244,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45993,6 +46831,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -46087,6 +46928,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -46132,6 +46976,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46392,6 +47239,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46549,6 +47399,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46594,6 +47447,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46915,9 +47771,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -47008,6 +47861,11 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "load it anyway"
msgstr ""
@@ -47045,6 +47903,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47412,6 +48273,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47493,9 +48357,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47639,6 +48500,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47671,6 +48535,11 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47779,6 +48648,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47845,6 +48717,11 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index b2d6bde058d..fa8acc10867 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr ""
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr ""
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr ""
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr ""
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr ""
msgid "PipelineSchedules|All"
msgstr ""
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -28750,15 +29261,27 @@ msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr ""
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr ""
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr ""
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr ""
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index e37d40a61ff..219649df2e3 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] "%d 个é¢å¤–æ交者"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d 个其他用户"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%dä½æ ¸å‡†äºº"
@@ -713,7 +717,7 @@ msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title
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 "使用 %{link_start} %{draft_snippet}%{link_end} 开始标题,以防止åˆå¹¶è¯·æ±‚è‰ç¨¿åœ¨å‡†å¤‡å°±ç»ªä¹‹å‰åˆå¹¶ã€‚"
+msgstr "使用 %{link_start} %{draft_snippet}%{link_end} 作为标题开头,以防止åˆå¹¶è¯·æ±‚è‰ç¨¿åœ¨å‡†å¤‡å°±ç»ªä¹‹å‰åˆå¹¶ã€‚"
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow},还有 %{awardsListLength} 个。"
@@ -931,10 +935,6 @@ msgstr "%{spanStart}在%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "从%{start}到%{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] "%{strongOpen}%{errors}%{strongClose} 点"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}警告:%{strongClose} SAML 群组链接会导致 GitLab 自动从群组中移除æˆå‘˜ã€‚"
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] "%{strong_start}%{count}ä½æˆå‘˜%{strong_end}必须核准åŽæ‰å¯ä»¥åˆå¹¶ã€‚任何具有开å‘人员或更高æƒé™çš„用户都å¯ä»¥åˆå¹¶ã€‚"
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} 点"
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} 项目存储"
@@ -994,9 +998,6 @@ msgstr "%{template_project_id}为未知或无效"
msgid "%{text} is available"
msgstr "%{text}å¯ç”¨"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name}应该属于一个项目或一个群组。"
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type}ä¸æ”¯æŒç‡ƒçƒ§å›¾"
@@ -1030,6 +1031,9 @@ msgstr "%{total}剩余议题æƒé‡"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "找到%{total}个警告: æ˜¾ç¤ºå‰ %{warningsDisplayed}"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} åªæ”¯æŒ %{name} å称"
@@ -1051,12 +1055,15 @@ msgstr "%{user_name} (%{user_username}) 已从 %{project} 的以下å‡çº§ç­–ç•¥ä
msgid "%{user_name} profile page"
msgstr "%{user_name}的个人资料"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} 更改了åˆå¹¶è¯·æ±‚%{mr_link}çš„è‰ç¨¿çŠ¶æ€"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username}请求在您的实例 %{host}创建一个GitLab å¸æˆ·ï¼š"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr "%{username} å°†åˆå¹¶è¯·æ±‚ %{mr_link} 标记为è‰ç¨¿"
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr "%{username} å°†åˆå¹¶è¯·æ±‚ %{mr_link} 标记为就绪"
+
msgid "%{username}'s avatar"
msgstr "%{username} 的头åƒ"
@@ -1078,6 +1085,12 @@ msgstr "%{value}秒"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} 耗时 %{time_spent_value}"
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} æ­¤ %{noun} 作为è‰ç¨¿ã€‚"
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} 此 %{noun} 为就绪。"
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚"
@@ -1535,9 +1548,6 @@ msgstr "%{name}的新的版本%{tag}å·²å‘布。请访问å‘布页é¢äº†è§£æ›´å¤
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr "一个新电å­é‚®ä»¶åœ°å€å·²æ·»åŠ åˆ°æ‚¨çš„ GitLab å¸æˆ·ï¼š%{email}"
-msgid "A new impersonation token has been created."
-msgstr "已创建新的身份模拟令牌。"
-
msgid "A new personal access token has been created"
msgstr "已创建新的个人访问令牌"
@@ -1556,6 +1566,15 @@ msgstr "éžç§å¯†å·¥ä½œé¡¹ä¸èƒ½æœ‰ç§å¯†çˆ¶é¡¹ã€‚"
msgid "A page with that title already exists"
msgstr "该标题页é¢å·²å­˜åœ¨"
+msgid "A personal access token has been revoked"
+msgstr "个人访问令牌已被撤销"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr "å为 %{code_start}%{token_name}%{code_end}的个人访问令牌已被撤销。"
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr "å为 %{token_name}的个人访问令牌已被撤销。"
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "一个纯HTML站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
@@ -2040,7 +2059,7 @@ msgid "Add a confidential internal note to this %{noteableDisplayName}."
msgstr "添加内部ç§å¯†å¤‡æ³¨åˆ°%{noteableDisplayName}。"
msgid "Add a custom message with details about the instance's shared runners. The message is visible when you view runners for projects and groups. Markdown is supported."
-msgstr ""
+msgstr "添加一个自定义消æ¯ï¼ŒåŒ…å«å®žä¾‹å…±äº« runners 的详细信æ¯ã€‚ 消æ¯åœ¨æ‚¨æŸ¥çœ‹ç¾¤ç»„和项目的 runners æ—¶å¯è§ã€‚支æŒMarkdown。"
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "添加一般评论 %{noteableDisplayName}。"
@@ -2067,7 +2086,7 @@ msgid "Add a table"
msgstr "添加表格"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "添加时间线事件"
msgid "Add a title..."
msgstr "添加标题..."
@@ -2163,10 +2182,10 @@ msgid "Add label(s)"
msgstr "添加标记"
msgid "Add labels"
-msgstr ""
+msgstr "添加标记"
msgid "Add license"
-msgstr ""
+msgstr "添加许å¯è¯"
msgid "Add list"
msgstr "添加列表"
@@ -2237,12 +2256,6 @@ msgstr "将主题添加到项目以帮助用户找到它们。"
msgid "Add trigger"
msgstr "添加触å‘器"
-msgid "Add user(s) to the group:"
-msgstr "å‘群组添加用户"
-
-msgid "Add users to group"
-msgstr "将用户加入群组"
-
msgid "Add variable"
msgstr "添加å˜é‡"
@@ -2340,7 +2353,7 @@ msgid "Adds a Zoom meeting."
msgstr "添加 Zoom 会议。"
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "添加时间线事件。"
msgid "Adds a to do."
msgstr "添加一个待办事项."
@@ -2562,7 +2575,7 @@ msgid "AdminSettings|Configure Let's Encrypt"
msgstr "é…ç½® Let's Encrypt"
msgid "AdminSettings|Configure limits on the number of repositories users can download in a given time."
-msgstr ""
+msgstr "é…置用户在给定时间内å¯ä»¥ä¸‹è½½çš„仓库数é‡é™åˆ¶ã€‚"
msgid "AdminSettings|Configure when inactive projects should be automatically deleted. %{linkStart}What are inactive projects?%{linkEnd}"
msgstr "é…置何时自动删除ä¸æ´»è·ƒçš„项目。%{linkStart}什么是ä¸æ´»è·ƒçš„项目?%{linkEnd}"
@@ -2604,7 +2617,7 @@ msgid "AdminSettings|Enable Service Ping"
msgstr "å¯ç”¨æœåŠ¡Ping"
msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
-msgstr ""
+msgstr "å¯ç”¨åº”用程åºæŒ‡æ ‡é›†ã€‚需è¦é‡å¯ã€‚%{link_start}学习如何导出指标到 Prometheus%{link_end}。"
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
msgstr "å¯ç”¨ kuromoji 自定义分æžå™¨ï¼šç´¢å¼•"
@@ -2628,7 +2641,7 @@ msgid "AdminSettings|Enabled"
msgstr "å·²å¯ç”¨"
msgid "AdminSettings|Enforce invitation flow for groups and projects"
-msgstr ""
+msgstr "为群组和项目强制执行邀请æµç¨‹"
msgid "AdminSettings|Feed token"
msgstr "ä¿¡æ¯æµä»¤ç‰Œ"
@@ -2636,9 +2649,15 @@ msgstr "ä¿¡æ¯æµä»¤ç‰Œ"
msgid "AdminSettings|Git abuse rate limit"
msgstr "Git 滥用率é™åˆ¶"
+msgid "AdminSettings|Group runners expiration"
+msgstr "群组 runners 过期"
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "我已ç»é˜…读并åŒæ„ %{link_start}æœåŠ¡æ¡æ¬¾%{link_end} (PDF)。"
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "如果没有写入å•ä½ï¼Œåˆ™é»˜è®¤ä¸ºç§’。例如,这些都是等价的: %{oneDayInSeconds}〠%{oneDayInHoursHumanReadable} 或 %{oneDayHumanReadable}。最å°å€¼ä¸ºä¸¤å°æ—¶ã€‚%{linkStart}了解更多。%{linkEnd}"
+
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}。ä¸å½±å“现有的仓库。"
@@ -2651,6 +2670,9 @@ msgstr "导入æº"
msgid "AdminSettings|Inactive project deletion"
msgstr "删除ä¸æ´»è·ƒçš„项目"
+msgid "AdminSettings|Instance runners expiration"
+msgstr "实例 runners 过期"
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "在最新æˆåŠŸçš„æµæ°´çº¿ä¸­ï¼Œä¿ç•™æ‰€æœ‰ä½œä¸šçš„最新产物"
@@ -2672,6 +2694,9 @@ msgstr "作业å¯ä»¥æ‹¥æœ‰çš„ DAG ä¾èµ–项的最大数é‡"
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr "æ¯ä¸ªé¡¹ç›®çš„最大活跃æµæ°´çº¿çš„æ•°é‡"
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "æ¯ä¸ªé¡¹ç›®çš„最大自定义域åæ•°"
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr "å•ä¸ªæµæ°´çº¿ä¸­ä½œä¸šçš„最大数é‡"
@@ -2708,6 +2733,9 @@ msgstr "预览有效负载"
msgid "AdminSettings|Project export"
msgstr "导出项目"
+msgid "AdminSettings|Project runners expiration"
+msgstr "项目 runners 过期"
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "默认ä¿æŠ¤ CI/CD å˜é‡"
@@ -2730,7 +2758,7 @@ msgid "AdminSettings|Save %{name} limits"
msgstr "ä¿å­˜ %{name} é™åˆ¶"
msgid "AdminSettings|Search with Elasticsearch enabled"
-msgstr "当 Elasticsearch å¯ç”¨æ—¶ç”¨äºŽæœç´¢"
+msgstr "å¯ç”¨ Elasticsearch çš„æœç´¢"
msgid "AdminSettings|Select a CI/CD template"
msgstr "选择一个 CI/CD 模æ¿"
@@ -2759,9 +2787,21 @@ msgstr "å°†CI/CD模æ¿è®¾ç½®ä¸ºå®žä¾‹ä¸­æ‰€æœ‰é¡¹ç›®æ‰€éœ€çš„æµæ°´çº¿é…置。å
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "å°†é™åˆ¶è®¾ç½®ä¸º 0 å¯ä»¥ç¦ç”¨ã€‚"
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "设置新注册的群组 runners 认è¯ä»¤ç‰Œçš„过期时间。"
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "设置新注册的实例 runners 认è¯ä»¤ç‰Œçš„过期时间。认è¯ä»¤ç‰Œå°†åœ¨è¿™äº›æ—¶é—´é—´éš”åŽè‡ªåŠ¨é‡ç½®ã€‚"
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "设置新注册的项目 runners 认è¯ä»¤ç‰Œçš„过期时间。"
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr "设置在实例中创建的新仓库的默认分支的åˆå§‹å称和ä¿æŠ¤ã€‚"
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "设置æ¯ä¸ªé¡¹ç›®çš„ Pages 域å的最大数é‡ï¼ˆ0表示无é™åˆ¶ï¼‰ã€‚%{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 "设置æ¯ä¸ªé¡¹ç›®çš„GitLab Pagesçš„æœ€å¤§å¤§å° ï¼ˆ0表示无é™åˆ¶ï¼‰ã€‚%{link_start}了解更多信æ¯ã€‚%{link_end}"
@@ -2796,10 +2836,10 @@ msgid "AdminSettings|Total number of jobs in currently active pipelines"
msgstr "当å‰æ´»åŠ¨æµæ°´çº¿ä¸­çš„作业总数"
msgid "AdminSettings|Use AWS OpenSearch Service with IAM credentials"
-msgstr ""
+msgstr "以 IMA 凭æ®ä½¿ç”¨ AWS çš„ OpenSearch æœåŠ¡"
msgid "AdminSettings|Users and groups must accept the invitation before they're added to a group or project."
-msgstr ""
+msgstr "用户和群组在被添加到群组或项目之å‰å¿…须确认接å—邀请。"
msgid "AdminSettings|When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr "当暂åœæ—¶ï¼Œç³»ç»Ÿä»åœ¨è·Ÿè¸ªæ›´æ”¹ï¼Œå¯¹äºŽé›†ç¾¤/索引è¿ç§»æ˜¯æœ‰ç”¨çš„。"
@@ -2948,6 +2988,9 @@ msgstr "å·²ç¦ç”¨"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "ç¦ç”¨ç”¨æˆ·å…·æœ‰ä»¥ä¸‹æ•ˆæžœï¼š"
+msgid "AdminUsers|Bot"
+msgstr "Bot"
+
msgid "AdminUsers|Can create group"
msgstr "å¯ä»¥åˆ›å»ºç¾¤ç»„"
@@ -3287,9 +3330,21 @@ msgstr "高级导出选项"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr "Elasticsearch 版本ä¸å…¼å®¹"
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "需è¦é‡æ–°ç´¢å¼•"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ã€‚"
@@ -3716,6 +3771,9 @@ msgstr "所有åˆå¹¶è¯·æ±‚ä¾èµ–项å‡å·²åˆå¹¶"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr "所有路径都相对于 GitLab URL。请ä¸è¦åŒ…å«%{relative_url_link_start}相对 URL%{relative_url_link_end}。"
+msgid "All project members"
+msgstr "所有项目æˆå‘˜"
+
msgid "All projects"
msgstr "所有项目"
@@ -3791,6 +3849,9 @@ msgstr "å…许此密钥推é€åˆ°è¿™ä¸ªä»“库"
msgid "Allow use of licensed EE features"
msgstr "å…许使用许å¯çš„EE功能"
+msgid "Allow users to create top-level groups"
+msgstr "å…许用户创建顶级群组"
+
msgid "Allow users to dismiss the broadcast message"
msgstr "å…许用户关闭广播消æ¯"
@@ -3939,7 +4000,7 @@ msgid "An error occurred while adding formatted title for epic"
msgstr "为å²è¯—添加格å¼åŒ–标题时å‘生错误"
msgid "An error occurred while approving, please try again."
-msgstr ""
+msgstr "批准时å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "An error occurred while authorizing your role"
msgstr "授æƒæ‚¨çš„角色时出错"
@@ -4079,9 +4140,6 @@ msgstr "加载此页é¢çš„æŸéƒ¨åˆ†æ—¶å‡ºé”™ã€‚"
msgid "An error occurred while loading all the files."
msgstr "加载所有文件时å‘生错误。"
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr "加载图表数æ®æ—¶å‘生错误"
@@ -4228,7 +4286,7 @@ msgid "An error occurred while trying to generate the report. Please try again l
msgstr "å°è¯•ç”ŸæˆæŠ¥å‘Šæ—¶å‡ºé”™ã€‚请ç¨åŽå†è¯•ã€‚"
msgid "An error occurred while trying to render the content editor. Please try again."
-msgstr ""
+msgstr "å°è¯•æ¸²æŸ“内容编辑器时å‘生错误,请é‡è¯•ã€‚"
msgid "An error occurred while trying to run a new pipeline for this merge request."
msgstr "å°è¯•ä¸ºæ­¤åˆå¹¶è¯·æ±‚è¿è¡Œæ–°æµæ°´çº¿æ—¶å‘生错误。"
@@ -4326,6 +4384,9 @@ msgstr "å‘生未知错误。"
msgid "Analytics"
msgstr "分æž"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "分æžä¾èµ–项查找已知æ¼æ´ž."
@@ -4336,7 +4397,7 @@ msgid "Analyze your source code and git history for secrets."
msgstr "分æžä½ çš„æºä»£ç å’Œgit历å²ä¸­çš„密ç ."
msgid "Analyze your source code for known vulnerabilities."
-msgstr "分æžæºä»£ç æŸ¥æ‰¾å·²çŸ¥æ¼æ´ž."
+msgstr "分æžæºä»£ç æŸ¥æ‰¾å·²çŸ¥æ¼æ´žã€‚"
msgid "Analyzing file…"
msgstr "分æžæ–‡ä»¶â€¦"
@@ -4547,6 +4608,9 @@ msgstr "å·²å¯ç”¨æ³¨å†ŒåŠŸèƒ½"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr "用户注册åŽæ˜¾ç¤ºçš„文本。Markdownå¯ç”¨ã€‚"
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr "此功能仅在 GitLab.com 上å¯ç”¨"
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr "此选项仅在 GitLab.com 上å¯ç”¨"
@@ -5073,7 +5137,7 @@ msgid "Assign custom color like #FF0000"
msgstr "分é…自定义颜色,如FF0000"
msgid "Assign labels"
-msgstr "指派标记"
+msgstr "添加标记"
msgid "Assign milestone"
msgstr "分é…里程碑"
@@ -5182,6 +5246,9 @@ msgstr[0] "添加%d个附件"
msgid "Attaching the file failed."
msgstr "添加附件失败。"
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr "å°è¯•ç™»å½•åˆ° %{host} 时,使用了错误的åŒé‡èº«ä»½éªŒè¯ç "
+
msgid "Audit Events"
msgstr "审计事件"
@@ -5265,7 +5332,7 @@ msgid "AuditStreams|Add header"
msgstr "添加 header"
msgid "AuditStreams|Add streaming destination"
-msgstr ""
+msgstr "添加æµç›®çš„地"
msgid "AuditStreams|An error occurred when creating external audit event stream destination. Please try it again."
msgstr "创建外部审计事件æµç›®çš„地时出错。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -5283,7 +5350,7 @@ msgid "AuditStreams|Cancel editing"
msgstr "å–消编辑"
msgid "AuditStreams|Custom HTTP headers (optional)"
-msgstr ""
+msgstr "自定义 HTTP headers(å¯é€‰ï¼‰"
msgid "AuditStreams|Delete %{link}"
msgstr "删除 %{link}"
@@ -5304,7 +5371,7 @@ msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
msgstr "已达到最多 %{number} 个 HTTP headers。"
msgid "AuditStreams|Remove custom header"
-msgstr ""
+msgstr "移除自定义 header"
msgid "AuditStreams|Save external stream destination"
msgstr "添加外部事件æµç›®çš„地"
@@ -5852,6 +5919,9 @@ msgstr "以下是%{link_to_gitlab_pages}的设置。"
msgid "Below you will find all the groups that are public."
msgstr "您将在下é¢æ‰¾åˆ°æ‰€æœ‰å…¬å¼€çš„群组。"
+msgid "Beta"
+msgstr "Beta"
+
msgid "Bi-weekly code coverage"
msgstr "åŒå‘¨ä»£ç è¦†ç›–率"
@@ -6173,8 +6243,8 @@ msgstr "直接æˆå‘˜"
msgid "Billing|Enter at least three characters to search."
msgstr "请至少输入三个字符æ‰å¯æœç´¢ã€‚"
-msgid "Billing|Explore all plans"
-msgstr "æµè§ˆæ‰€æœ‰æ–¹æ¡ˆ"
+msgid "Billing|Explore paid plans"
+msgstr "æµè§ˆä»˜è´¹æ–¹æ¡ˆ"
msgid "Billing|Export list"
msgstr "导出列表"
@@ -6210,6 +6280,9 @@ msgstr "切æ¢å¸­ä½è¯¦æƒ…"
msgid "Billing|Type %{username} to confirm"
msgstr "输入 %{username} 进行确认"
+msgid "Billing|Unlimited members during your trial"
+msgstr "试用期间无é™ä¼šå‘˜"
+
msgid "Billing|User was successfully removed"
msgstr "用户已æˆåŠŸåˆ é™¤"
@@ -6269,7 +6342,7 @@ msgid "Board scope affects which epics are displayed for anyone who visits this
msgstr "看æ¿èŒƒå›´ä¼šå½±å“å‘访问此看æ¿çš„任何人显示的å²è¯—"
msgid "Board scope affects which issues are displayed for anyone who visits this board"
-msgstr "看æ¿èŒƒå›´ä¼šå½±å“访问此看æ¿çš„人å¯ä»¥æ˜¾ç¤ºå“ªäº›è®®é¢˜"
+msgstr "看æ¿èŒƒå›´ä¼šå½±å“看æ¿è®¿é—®è€…å¯è§çš„议题"
msgid "BoardNewEpic|Groups"
msgstr "群组"
@@ -6525,6 +6598,9 @@ msgstr "正在加载å²è¯—"
msgid "Bold text"
msgstr "加粗字体"
+msgid "Bot"
+msgstr "Bot"
+
msgid "Both SSH and HTTP(S)"
msgstr "SSH 和 HTTP(S)"
@@ -6561,33 +6637,78 @@ msgstr "分支未载入 - %{branchId}"
msgid "Branch rules"
msgstr "分支规则"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr "%{linkStart}支æŒé€šé…符%{linkEnd} ,例如 *-stable 或 production/*。"
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "å…许所有具有推é€è®¿é—®æƒé™çš„用户%{linkStart}强制推é€%{linkEnd}。"
msgid "BranchRules|Allowed to merge"
msgstr "å…许åˆå¹¶"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "å…许推é€"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr "获å–分支时å‘生错误。"
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr "分支"
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr "分支规则详情"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr "创建通é…符:%{searchTerm}"
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "群组"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr "ä¿æŒç¨³å®šåˆ†æ”¯çš„安全并强制开å‘者使用åˆå¹¶è¯·æ±‚。%{linkStart}什么是å—ä¿æŠ¤çš„分支?%{linkEnd}"
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr "没有匹é…的结果"
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr "ä¿æŠ¤"
@@ -6597,11 +6718,23 @@ msgstr "æ‹’ç»ä»£ç æŽ¨é€æ›´æ”¹ CODEOWNERS 文件中列出的文件。"
msgid "BranchRules|Require approval from code owners."
msgstr "需è¦ä»£ç æ‰€æœ‰è€…的核准。"
-msgid "BranchRules|default"
+msgid "BranchRules|Roles"
+msgstr "角色"
+
+msgid "BranchRules|Status checks"
msgstr ""
+msgid "BranchRules|Target Branch"
+msgstr "目标分支"
+
+msgid "BranchRules|Users"
+msgstr "用户"
+
+msgid "BranchRules|default"
+msgstr "默认"
+
msgid "BranchRules|protected"
-msgstr ""
+msgstr "å—ä¿æŠ¤çš„"
msgid "Branches"
msgstr "分支"
@@ -6769,7 +6902,7 @@ msgid "Browse templates"
msgstr "æµè§ˆæ¨¡æ¿"
msgid "Build cannot be erased"
-msgstr ""
+msgstr "构建无法被删除"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "获å–产物时出错"
@@ -6897,6 +7030,9 @@ msgstr "需与群组关è”但是当å‰ä¸Žé¡¹ç›®å…³è”"
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr "需与项目关è”但是当å‰ä¸Žç¾¤ç»„å…³è”"
+msgid "BulkImport|invalid entity source type"
+msgstr "无效的实体æºç±»åž‹"
+
msgid "BulkImport|must be a group"
msgstr "必须为群组"
@@ -7069,6 +7205,9 @@ msgstr "所有项目默认使用Auto DevOpsæµæ°´çº¿"
msgid "CICD|Deployment strategy"
msgstr "部署策略"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr "å¯ç”¨åŠŸèƒ½ä»¥é™åˆ¶å¯¹ä»¥ä¸‹é¡¹ç›®çš„作业令牌访问。"
+
msgid "CICD|Jobs"
msgstr "作业"
@@ -7078,8 +7217,8 @@ msgstr "é™åˆ¶"
msgid "CICD|Limit CI_JOB_TOKEN access"
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 "选择å¯ä»¥é€šè¿‡ API 访问的项目请求验è¯æ­¤é¡¹ç›®çš„ CI_JOB_TOKEN CI/CD å˜é‡ã€‚"
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr "选择使用此项目的 CI_JOB_TOKEN CI/CD å˜é‡è¿›è¡Œèº«ä»½éªŒè¯çš„ API 请求å¯ä»¥è®¿é—®å“ªäº›é¡¹ç›®ã€‚ç¦ç”¨æ­¤åŠŸèƒ½å­˜åœ¨å®‰å…¨é£Žé™©ï¼Œå› ä¸ºæœªç»æŽˆæƒçš„项目å¯èƒ½ä¼šå°è¯•æ£€ç´¢æ´»åŠ¨ä»¤ç‰Œå¹¶è®¿é—® API。%{linkStart}了解更多。%{linkEnd}"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr "Auto DevOps æµæ°´çº¿é»˜è®¤åœ¨æ²¡æœ‰ CI/CD é…置文件的所有项目中è¿è¡Œã€‚%{link_start}什么是 Auto DevOps?%{link_end}"
@@ -7339,8 +7478,8 @@ msgstr "ä¸èƒ½å‡çº§é—®é¢˜ï¼Œå› ä¸ºå®ƒä¸å±žäºŽä¸€ä¸ªç»„。"
msgid "Cannot promote issue due to insufficient permissions."
msgstr "由于æƒé™ä¸è¶³ï¼Œæ— æ³•å‡çº§è®®é¢˜ã€‚"
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr "无法通过内部ID引用群组%{timebox_type}ï¼"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "无法通过内部ID引用群组里程碑ï¼"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "无法显示预览。如需预览,è‰å›¾æ–‡ä»¶å¿…须具有Sketch 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
@@ -7534,6 +7673,9 @@ msgstr "将标题更改为“%{title_param}â€ã€‚"
msgid "Changes to the title have not been saved"
msgstr "标题更改尚未ä¿å­˜"
+msgid "Changes:"
+msgstr "å˜æ›´ï¼š"
+
msgid "Changing any setting here requires an application restart"
msgstr "更改此处的任何设置都需è¦é‡æ–°å¯åŠ¨åº”用程åº"
@@ -8273,7 +8415,7 @@ msgid "Closed date"
msgstr "关闭日期"
msgid "Closed issues"
-msgstr "已关闭议题"
+msgstr "已关闭的议题"
msgid "Closed this %{quick_action_target}."
msgstr "已关闭此%{quick_action_target}."
@@ -8288,10 +8430,10 @@ msgid "Cloud Run"
msgstr "Cloud Run"
msgid "Cloud SQL instances are fully managed, relational MySQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Cloud SQL 实例是完全托管的ã€å…³ç³»åž‹ MySQL æ•°æ®åº“。Google 处ç†å¤åˆ¶ã€è¡¥ä¸ç®¡ç†å’Œæ•°æ®åº“管ç†ï¼Œä»¥ç¡®ä¿å¯ç”¨æ€§å’Œæ€§èƒ½ã€‚"
msgid "Cloud SQL instances are fully managed, relational SQL Server databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Cloud SQL 实例是完全托管的ã€å…³ç³»åž‹ MySQL æ•°æ®åº“。Google 处ç†å¤åˆ¶ã€è¡¥ä¸ç®¡ç†å’Œæ•°æ®åº“管ç†ï¼Œä»¥ç¡®ä¿å¯ç”¨æ€§å’Œæ€§èƒ½ã€‚"
msgid "Cloud Storage"
msgstr "云存储"
@@ -8321,10 +8463,10 @@ msgid "CloudSeed|Cloud SQL for SQL Server"
msgstr "Cloud SQL for SQL Server"
msgid "CloudSeed|Cloud SQL instance creation request successful. Expected resolution time is ~5 minutes."
-msgstr ""
+msgstr "æˆåŠŸå‘起了 Cloud SQL 实例创建请求。预期对方回å¤è¯¥è¯·æ±‚的时间约为 5 分钟。"
msgid "CloudSeed|Cloud SQL instances are fully managed, relational PostgreSQL databases. Google handles replication, patch management, and database management to ensure availability and performance."
-msgstr ""
+msgstr "Cloud SQL 实例是完全托管的ã€å…³ç³»åž‹ MySQL æ•°æ®åº“。Google 处ç†å¤åˆ¶ã€è¡¥ä¸ç®¡ç†å’Œæ•°æ®åº“管ç†ï¼Œä»¥ç¡®ä¿å¯ç”¨æ€§å’Œæ€§èƒ½ã€‚"
msgid "CloudSeed|CloudSQL Instance"
msgstr "CloudSQL 实例"
@@ -8545,6 +8687,9 @@ msgstr "确定è¦åˆ é™¤æ­¤ä»£ç†å—?您无法撤消此æ“作。"
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr "确定è¦åˆ é™¤æ­¤ä»£ç†å—?您无法撤消此æ“作。"
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr "访问å—é™çš„ CI/CD 工作æµ"
+
msgid "ClusterAgents|Certificate"
msgstr "è¯ä¹¦"
@@ -8644,6 +8789,9 @@ msgstr "如何更新代ç†ï¼Ÿ"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr "使用 Helm 安装(推è)"
+msgid "ClusterAgents|Integration Status"
+msgstr "集æˆçŠ¶æ€"
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "上次连接在 %{timeAgo}。"
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] "过去 %d 天内没有活动"
+msgid "ClusterAgents|No agent access token"
+msgstr "无代ç†è®¿é—®ä»¤ç‰Œ"
+
msgid "ClusterAgents|No agents"
msgstr "无代ç†"
@@ -8678,6 +8829,9 @@ msgstr "没有通过集群è¯ä¹¦è¿žæŽ¥çš„集群"
msgid "ClusterAgents|Not connected"
msgstr "未连接"
+msgid "ClusterAgents|Premium"
+msgstr "专业版"
+
msgid "ClusterAgents|Recommended"
msgstr "推è"
@@ -8744,6 +8898,9 @@ msgstr "由 %{userName} 撤销的令牌"
msgid "ClusterAgents|Unknown user"
msgstr "未知用户"
+msgid "ClusterAgents|Valid access token"
+msgstr "有效的访问令牌"
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "查看所有 %{number} 个代ç†"
@@ -9081,10 +9238,10 @@ msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "用于访问 Kubernetes API 的 URL。"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "基于è¯ä¹¦çš„ Kubernetes 集æˆå·²è¢«å¼ƒç”¨ï¼Œå°†äºŽ 2023 å¹´ 2 月关闭,请%{linkStart}è¿ç§»åˆ°é€‚用于 Kubernetes 的代ç†%{linkEnd}或è”系技术支æŒã€‚"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "基于è¯ä¹¦çš„ Kubernetes 集æˆå·²è¢«å¼ƒç”¨ï¼Œå°†äºŽ 2023 å¹´ 2 月关闭,请%{linkStart}è¿ç§»åˆ°é€‚用于 Kubernetes 的代ç†%{linkEnd}。"
msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
msgstr "将集群连接到 GitLab 的基于è¯ä¹¦çš„方法%{linkStart}弃用%{linkEnd}于 14.5 版本。"
@@ -9411,6 +9568,9 @@ msgstr "æ交到"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "您选择的æ交出现在这里。转到第一个选项å¡ï¼Œç„¶åŽé€‰æ‹©æ交以添加到此åˆå¹¶è¯·æ±‚中。"
+msgid "Commits:"
+msgstr "æ交:"
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "获å–åˆå¹¶è¯·æ±‚æ•°æ®æ—¶å‡ºé”™"
@@ -9448,7 +9608,7 @@ msgid "Compare Revisions"
msgstr "比较版本"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "比较分支并继续"
msgid "Compare changes"
msgstr "比较å˜æ›´"
@@ -9516,6 +9676,9 @@ msgstr "完æˆ"
msgid "Complete verification to sign in."
msgstr "完æˆéªŒè¯æ–¹å¯ç™»å½•ã€‚"
+msgid "Complete verification to sign up."
+msgstr "完æˆéªŒè¯æ–¹å¯æ³¨å†Œã€‚"
+
msgid "Completed"
msgstr "已完æˆ"
@@ -9585,8 +9748,8 @@ msgstr "å称是必需的"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr "尚未设置åˆè§„框架"
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr "所需格å¼ï¼š %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}。 %{linkStart}了解更多。%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
+msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "无法ä¿å­˜æ­¤åˆè§„性框架。请é‡è¯•"
@@ -9903,6 +10066,9 @@ msgstr "è”系人"
msgid "Container Registry"
msgstr "容器镜åƒåº“"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "容器扫æ"
@@ -10026,7 +10192,7 @@ msgid "ContainerRegistry|Docker connection error"
msgstr "Docker连接错误"
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "编辑清ç†è§„则"
msgid "ContainerRegistry|Enable expiration policy"
msgstr "å¯ç”¨è¿‡æœŸç­–ç•¥"
@@ -10132,10 +10298,10 @@ msgid "ContainerRegistry|Save storage space by automatically deleting tags from
msgstr "通过自动从容器镜åƒåº“中删除标签,并ä¿ç•™æ‚¨æƒ³è¦çš„标签æ¥èŠ‚çœå­˜å‚¨ç©ºé—´ã€‚%{linkStart}清ç†å·¥ä½œå¦‚何进行?%{linkEnd}"
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "设置清ç†è§„则"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "设置规则æ¥è‡ªåŠ¨ç§»é™¤æœªä½¿ç”¨çš„软件包,节çœå­˜å‚¨ç©ºé—´ã€‚"
msgid "ContainerRegistry|Set up cleanup"
msgstr "设置清ç†"
@@ -10312,7 +10478,7 @@ msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %
msgstr "已创建%{created_count}个,已åˆå¹¶%{merged_count}个,已关闭%{closed_count}个。"
msgid "ContributionAnalytics|%{pushes}, more than %{commits} by %{contributors}."
-msgstr ""
+msgstr "%{pushes} 个推é€ï¼Œè¶…过 %{contributors} 个贡献者的 %{commits} 次æ交"
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
msgstr "自%{start_date}起的议题,åˆå¹¶è¯·æ±‚和推é€äº‹ä»¶çš„贡献分æž"
@@ -10356,15 +10522,15 @@ msgstr "贡献者"
msgid "Control emails linked to your account"
msgstr "控制与您å¸æˆ·å…³è”的电å­é‚®ä»¶"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr "控制 CI_JOB_TOKEN CI/CD å˜é‡å¦‚何用于项目之间的 API 访问。"
+
msgid "Control how the GitLab Package Registry functions."
msgstr "控制 GitLab 软件包仓库是如何è¿ä½œçš„。"
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr "控制是å¦åœ¨ GitLab 中显示客户体验改进内容和第三方优惠。"
-msgid "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."
-msgstr "控制使用此项目的 CI_JOB_TOKEN CI/CD å˜é‡è¿›è¡Œèº«ä»½éªŒè¯çš„ API 请求å¯ä»¥è®¿é—®å“ªäº›é¡¹ç›®ã€‚ç¦ç”¨æ­¤åŠŸèƒ½å­˜åœ¨å®‰å…¨é£Žé™©ï¼Œå› ä¸ºæœªç»æŽˆæƒçš„项目å¯èƒ½ä¼šå°è¯•æ£€ç´¢æ´»åŠ¨ä»¤ç‰Œå¹¶è®¿é—® API。"
-
msgid "Cookie domain"
msgstr "Cookie域"
@@ -10686,6 +10852,9 @@ msgstr "无法将策略分é…给项目或群组"
msgid "Country"
msgstr "国家/地区"
+msgid "Counts reflect children you may not have access to."
+msgstr "计数å映您å¯èƒ½æ²¡æœ‰è®¿é—®æƒé™çš„å­é¡¹ã€‚"
+
msgid "Coverage"
msgstr "覆盖率"
@@ -10891,7 +11060,7 @@ msgid "Create service account"
msgstr "创建æœåŠ¡å¸æˆ·"
msgid "Create snippet"
-msgstr "创建代ç ç‰‡æ–­"
+msgstr "创建代ç ç‰‡æ®µ"
msgid "Create tag %{tagName}"
msgstr "创建标签 %{tagName}"
@@ -10902,6 +11071,9 @@ msgstr "创建主题"
msgid "Create user"
msgstr "创建用户"
+msgid "Create wildcard"
+msgstr "创建通é…符"
+
msgid "Create wildcard: %{searchTerm}"
msgstr "创建通é…符: %{searchTerm}"
@@ -10914,6 +11086,12 @@ msgstr "创建您的群组"
msgid "Create, update, or delete a merge request."
msgstr "创建ã€æ›´æ–°æˆ–删除åˆå¹¶è¯·æ±‚。"
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "添加消æ¯åˆ°æ ‡ç­¾ã€‚留空时,将创建一个%{linkStart}è½»é‡æ ‡ç­¾%{linkEnd}。"
+
+msgid "CreateGitTag|Set tag message"
+msgstr "设置标签消æ¯"
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "您无æƒåœ¨æ­¤ç¾¤ç»„中创建å­ç¾¤ç»„。"
@@ -11368,7 +11546,7 @@ msgid "CycleAnalyticsEvent|Issue closed"
msgstr "议题关闭"
msgid "CycleAnalyticsEvent|Issue created"
-msgstr "议题已创建"
+msgstr "已创建的议题"
msgid "CycleAnalyticsEvent|Issue first added to a board"
msgstr "议题首次添加到看æ¿"
@@ -11395,7 +11573,7 @@ msgid "CycleAnalyticsEvent|Merge request closed"
msgstr "åˆå¹¶è¯·æ±‚关闭"
msgid "CycleAnalyticsEvent|Merge request created"
-msgstr "åˆå¹¶è¯·æ±‚已创建"
+msgstr "已创建的åˆå¹¶è¯·æ±‚"
msgid "CycleAnalyticsEvent|Merge request first commit time"
msgstr "åˆå¹¶è¯·æ±‚首次æ交时间"
@@ -11458,7 +11636,7 @@ msgid "CycleAnalytics|Average time to completion"
msgstr "å¹³å‡å®Œæˆæ—¶é—´"
msgid "CycleAnalytics|Average time to completion (days)"
-msgstr ""
+msgstr "å¹³å‡å®Œæˆæ—¶é—´ï¼ˆå¤©ï¼‰"
msgid "CycleAnalytics|Change Failure Rate"
msgstr "更改失败率"
@@ -11690,10 +11868,10 @@ msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and resp
msgstr "被动扫æ监控å‘é€åˆ°ç›®æ ‡çš„所有HTTP消æ¯(请求和å“应)。主动扫æ会对目标进行攻击以å‘现潜在æ¼æ´žã€‚"
msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "扫æ器é…置文件定义了安全扫æ器的é…置详细信æ¯ã€‚%{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "站点é…置文件定义了已部署的应用程åºã€ç½‘站或 API 的属性和é…置详细信æ¯ã€‚%{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|AJAX spider"
msgstr "AJAX爬虫"
@@ -11897,10 +12075,10 @@ msgid "DastProfiles|Scanner name"
msgstr "扫æ工具å称"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "扫æ器é…置文件"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "扫æ器é…置文件"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr "选择扫æ器é…置文件æ¥è¿è¡Œ DAST 扫æ"
@@ -11924,10 +12102,10 @@ msgid "DastProfiles|Site name"
msgstr "站点å称"
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "站点é…置文件"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "站点é…置文件"
msgid "DastProfiles|Site type"
msgstr "站点类型"
@@ -12167,6 +12345,12 @@ msgstr "日期范围é™åˆ¶ä¸º %{number} 天"
msgid "Date range must be shorter than %{max_range} days."
msgstr "日期范围必须å°äºŽ %{max_range} 天。"
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr "对新创建的命å空间实施强制执行的日期"
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr "%{start_date} - %{end_date}"
+
msgid "Day of month"
msgstr "一个月中的æ¯å¤©"
@@ -12353,6 +12537,9 @@ msgstr "删除账户"
msgid "Delete artifacts"
msgstr "删除产物"
+msgid "Delete asset"
+msgstr "删除 asset"
+
msgid "Delete audio"
msgstr "删除音频"
@@ -12497,6 +12684,9 @@ msgstr "已删除"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "已删除èŠå¤©çš„昵称: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr "已删除的æ交:"
+
msgid "Deleted projects cannot be restored!"
msgstr "已删除的项目无法æ¢å¤!"
@@ -12830,6 +13020,9 @@ msgstr "åªè¯»æƒé™"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "å¯ç”¨éƒ¨ç½²ä»¤ç‰Œï¼ˆ%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "å…许对仓库镜åƒè¿›è¡Œè¯»å†™è®¿é—®ã€‚"
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "å…许对软件包仓库进行读写访问。"
@@ -12875,6 +13068,9 @@ msgstr "为您的令牌输入用户å。默认为 %{code_start}gitlab+deploy-to
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr "输入令牌的到期日期。默认为永ä¸è¿‡æœŸã€‚"
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "到期日期(å¯é€‰ï¼‰"
+
msgid "DeployTokens|Expires"
msgstr "到期"
@@ -12896,6 +13092,9 @@ msgstr "撤销 %{name}"
msgid "DeployTokens|Scopes"
msgstr "有效范围"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr "范围(至少选择一个)"
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "该%{entity_type}æ— å¯ç”¨çš„部署令牌。"
@@ -12911,6 +13110,12 @@ msgstr "使用此令牌作为密ç ã€‚æ­¤å¯†ç  %{i_start}ä¸èƒ½%{i_end} 找回ã
msgid "DeployTokens|Username"
msgstr "用户å"
+msgid "DeployTokens|Username (optional)"
+msgstr "用户å (å¯é€‰)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "您的新部署令牌"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr "您的新部署令牌用户å"
@@ -12984,10 +13189,10 @@ msgid "DeploymentApproval|Manual job: %{jobName}"
msgstr "手动作业:%{jobName}"
msgid "DeploymentApproval|Rejected %{time}"
-msgstr ""
+msgstr "于 %{time} æ‹’ç»"
msgid "DeploymentApproval|Rejected by you %{time}"
-msgstr ""
+msgstr "由您于 %{time} æ‹’ç»"
msgid "DeploymentTarget|GitLab Pages"
msgstr "GitLab Pages"
@@ -13095,18 +13300,9 @@ msgstr "æˆåŠŸ"
msgid "Deprecated API rate limits"
msgstr "已弃用的 API 速率é™åˆ¶"
-msgid "Deprecations|Feature deprecation and removal"
-msgstr "功能弃用和移除"
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr "关于å¯èƒ½æ›¿æ¢çš„ä¿¡æ¯ï¼Œ%{epicStart}了解更多关于 Opstrace %{epicEnd}。"
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr "关于å¯èƒ½æ›¿æ¢çš„ä¿¡æ¯ï¼Œ%{opstrace_link_start}了解更多关于 Opstrace çš„ä¿¡æ¯%{link_end}。"
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr "在 14.7 版本中,日志和追踪功能也被废弃,%{removal_link_start} 计划在 15.0 版本中删除 %{link_end}。"
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr "14.7 版本中弃用了指标功能。"
@@ -13174,20 +13370,11 @@ msgstr "已存档设计ä»å¯åœ¨ä»¥å‰ç‰ˆæœ¬çš„设计集中使用。"
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr "您确定è¦å½’档选定的设计å—?"
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "您确定è¦å–消对此评论的更改å—?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消创建此评论å—?"
-msgid "DesignManagement|Cancel changes"
-msgstr "å–消更改"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "å–消评论确认"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "å–消评论更新确认"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr "å•å‡»æ‚¨è¦å¼€å§‹æ–°è®¨è®ºçš„图åƒ"
@@ -13195,6 +13382,12 @@ msgstr "å•å‡»æ‚¨è¦å¼€å§‹æ–°è®¨è®ºçš„图åƒ"
msgid "DesignManagement|Comment"
msgstr "评论"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "无法添加新评论。请å†è¯•ä¸€æ¬¡."
@@ -13213,11 +13406,11 @@ msgstr "å–消全部选择"
msgid "DesignManagement|Designs"
msgstr "设计"
-msgid "DesignManagement|Discard comment"
-msgstr "放弃评论"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "讨论"
msgid "DesignManagement|Download design"
msgstr "下载设计"
@@ -13234,12 +13427,6 @@ msgstr "转到下一个设计"
msgid "DesignManagement|Go to previous design"
msgstr "转到上一个设计"
-msgid "DesignManagement|Keep changes"
-msgstr "ä¿ç•™æ›´æ”¹"
-
-msgid "DesignManagement|Keep comment"
-msgstr "ä¿ç•™è¯„论"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "请求的设计版本ä¸å­˜åœ¨ã€‚显示最新版本"
@@ -13313,7 +13500,7 @@ msgid "DevOps adoption"
msgstr "DevOps adoption"
msgid "Development"
-msgstr ""
+msgstr "å¼€å‘"
msgid "Devices (optional)"
msgstr "设备(å¯é€‰ï¼‰"
@@ -13778,6 +13965,18 @@ msgstr "域å"
msgid "Domain Name"
msgstr "域å"
+msgid "Domain Verification"
+msgstr "域å验è¯"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "如何é…置域å?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "未é…置域å。在此群组层次结构中创建一个项目。"
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "为该群组中的项目é…置了以下域å。电å­é‚®ä»¶åœ°å€ä¸Žå·²éªŒè¯åŸŸå匹é…的用户无需确认其å¸æˆ·ã€‚"
+
msgid "Don't have a group?"
msgstr "没有群组?"
@@ -13896,10 +14095,10 @@ msgid "DropdownWidget|Assign %{issuableAttribute}"
msgstr "åˆ†é… %{issuableAttribute}"
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "编辑 %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr "无法为此%{issuableType}获å–%{issuableAttribute},请é‡è¯•ã€‚"
@@ -13917,10 +14116,10 @@ msgid "DropdownWidget|No open %{issuableAttribute} found"
msgstr "找ä¸åˆ°å¼€æ”¾çš„ %{issuableAttribute}"
msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
-msgstr ""
+msgstr "您没有æƒé™æŸ¥çœ‹å½“å‰åˆ†é…çš„ %{issuableAttribute} ,如果您é‡æ–°åˆ†é…它,您将无法å†æ¬¡é€‰æ‹©å®ƒã€‚"
msgid "DropdownWidget|You don't have permission to view this %{issuableAttribute}."
-msgstr ""
+msgstr "您没有æƒé™æŸ¥çœ‹æ­¤ %{issuableAttribute}。"
msgid "Due Date"
msgstr "截止日期"
@@ -14144,8 +14343,11 @@ msgstr "编辑Wiki页é¢"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "编辑你在最近主题中的评论(从空白文本区)"
+msgid "Edit your search and try again"
+msgstr "请编辑您的æœç´¢å¹¶é‡è¯•"
+
msgid "Edit your search filter and try again."
-msgstr ""
+msgstr "请编辑您的æœç´¢ç­›é€‰é¡¹åŽé‡è¯•ã€‚"
msgid "Edit, lint, and visualize your pipeline."
msgstr "编辑ã€æ•´ç†å’Œå¯è§†åŒ–您的æµæ°´çº¿ã€‚"
@@ -14282,9 +14484,6 @@ msgstr "还有 %{moreCount} 个"
msgid "Emails"
msgstr "电å­é‚®ä»¶"
-msgid "Emails sent from Service Desk have this name."
-msgstr "æœåŠ¡å°å‘é€çš„电å­é‚®ä»¶å…·æœ‰æ­¤å称。"
-
msgid "Emails sent to %{email} are also supported."
msgstr "也支æŒå‘é€ç”µå­é‚®ä»¶åˆ°%{email}。"
@@ -14334,7 +14533,7 @@ msgid "Enable GitLab Error Tracking"
msgstr "å¯ç”¨é”™è¯¯è·Ÿè¸ª"
msgid "Enable GitLab Prometheus metrics endpoint"
-msgstr ""
+msgstr "å¯ç”¨ Prometheus 指标端点"
msgid "Enable Gitpod"
msgstr "å¯ç”¨Gitpod"
@@ -14402,6 +14601,9 @@ msgstr "为创建于早于GitLab 12.7版本的项目å¯ç”¨å®¹å™¨è¿‡æœŸå’Œä¿ç•™ç
msgid "Enable container expiration caching."
msgstr "å¯ç”¨å®¹å™¨è¿‡æœŸç¼“存。"
+msgid "Enable dashboard limits on namespaces"
+msgstr "对命å空间å¯ç”¨ä»ªè¡¨ç›˜é™åˆ¶"
+
msgid "Enable email notification"
msgstr "å¯ç”¨ç”µå­é‚®ä»¶é€šçŸ¥"
@@ -14750,6 +14952,9 @@ msgstr "部署"
msgid "Environments|Deployment %{status}"
msgstr "部署%{status}"
+msgid "Environments|Edit your search and try again"
+msgstr "请编辑您的æœç´¢å¹¶é‡è¯•"
+
msgid "Environments|Enable review app"
msgstr "å¯ç”¨å®¡æ ¸åº”用"
@@ -14783,6 +14988,9 @@ msgstr "没有已部署的环境"
msgid "Environments|No deployments yet"
msgstr "未部署"
+msgid "Environments|No results found"
+msgstr "未找到结果"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "注æ„:继续æ“作将终止当å‰çŽ¯å¢ƒï¼ç”±äºŽæœªåœ¨%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}文件中定义“终止环境æ“作â€ï¼Œå› æ­¤%{emphasisStart}ä¸ä¼š%{emphasisEnd}å½±å“å·²ç»å­˜åœ¨çš„部署。"
@@ -14807,6 +15015,9 @@ msgstr "回滚环境"
msgid "Environments|Rollback environment %{name}?"
msgstr "回滚环境 %{name}?"
+msgid "Environments|Search by environment name"
+msgstr "按环境å称æœç´¢"
+
msgid "Environments|Show all"
msgstr "显示全部"
@@ -14862,7 +15073,7 @@ msgid "Epic Boards"
msgstr "å²è¯—看æ¿"
msgid "Epic actions"
-msgstr ""
+msgstr "å²è¯—æ“作"
msgid "Epic cannot be found."
msgstr "找ä¸åˆ°å²è¯—。"
@@ -15006,7 +15217,7 @@ msgid "Error deleting project. Check logs for error details."
msgstr "删除项目时出错。请检查错误详细信æ¯ã€‚"
msgid "Error fetching branches"
-msgstr ""
+msgstr "获å–分支时出错。"
msgid "Error fetching burnup chart data"
msgstr "æå–燃烧图数æ®æ—¶å‡ºé”™"
@@ -15117,7 +15328,7 @@ msgid "Error parsing CSV file. Please make sure it has"
msgstr "解æžCSV文件时出错。请确认它是å¦åŒ…å«"
msgid "Error promoting the note to timeline event: %{error}"
-msgstr ""
+msgstr "将注释æ交到时间线事件时出现错误:%{error}"
msgid "Error rendering Markdown preview"
msgstr "渲染Markdown预览出错"
@@ -15550,7 +15761,7 @@ msgid "Expand jobs"
msgstr "展开作业"
msgid "Expand merge details"
-msgstr ""
+msgstr "展开åˆå¹¶è¯¦æƒ…"
msgid "Expand milestones"
msgstr "展开里程碑"
@@ -15902,9 +16113,6 @@ msgstr "加载分支失败。请é‡è¯•ã€‚"
msgid "Failed to load deploy keys."
msgstr "加载部署密钥失败。"
-msgid "Failed to load emoji list."
-msgstr "无法加载表情列表。"
-
msgid "Failed to load error details from Sentry."
msgstr "无法从Sentry加载错误详细信æ¯ã€‚"
@@ -16510,13 +16718,13 @@ msgid "Flags"
msgstr "标记"
msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
-msgstr ""
+msgstr "é…置是å¦å‚与 FLoC。%{floc_link_start}什么是 FLoC?%{floc_link_end}"
msgid "FloC|Federated Learning of Cohorts (FLoC)"
-msgstr ""
+msgstr "Federated Learning of Cohorts (FLoC)"
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "å‚加 FLoC"
msgid "FlowdockService|Enter your Flowdock token."
msgstr "输入您的 Flowdock 令牌。"
@@ -16587,6 +16795,9 @@ msgstr "对于æ¯ä¸ªä½œä¸šï¼Œé‡æ–°ä½¿ç”¨é¡¹ç›®å·¥ä½œåŒºï¼Œå¦‚果工作区ä¸å­˜
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr "例如,使用令牌的应用程åºæˆ–令牌的用途。ä¸è¦æ供令牌å称的æ•æ„Ÿä¿¡æ¯ï¼Œå› ä¸ºå®ƒå°†å¯¹æ‰€æœ‰ %{resource_type} æˆå‘˜å¯è§ã€‚"
+msgid "For faster browsing, not all history is shown."
+msgstr "为了加快æµè§ˆé€Ÿåº¦ï¼Œä¸ä¼šæ˜¾ç¤ºæ‰€æœ‰åŽ†å²è®°å½•ã€‚"
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr "对于大于此é™åˆ¶çš„文件,仅索引文件å,文件内容既ä¸ç¼–入索引也ä¸å¯æœç´¢ã€‚"
@@ -16666,7 +16877,7 @@ msgid "ForkProject|Select a namespace"
msgstr "选择命å空间"
msgid "ForkProject|Something went wrong while loading data. Please refresh the page to try again."
-msgstr ""
+msgstr "加载数æ®æ—¶å‡ºé”™ã€‚请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr "任何登录用户都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ã€‚"
@@ -16716,13 +16927,46 @@ msgstr "在.gitlab-ci.yml中å‘现错误:"
msgid "Framework successfully deleted"
msgstr "框架删除æˆåŠŸ"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "å…费试用"
+msgid "Free User Cap"
+msgstr "å…费用户上é™"
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] "å…费群组é™åˆ¶ä¸º %{free_user_limit} åæˆå‘˜ï¼Œå…¶ä½™æˆå‘˜å°†èŽ·å¾—超é™çŠ¶æ€å¹¶æ— æ³•è®¿é—®è¯¥ç¾¤ç»„。"
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "或者,您å¯ä»¥å‡çº§åˆ°ä¸“业版或旗舰版:"
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "探索付费计划"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "探索付费计划:"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr "看起æ¥æ‚¨å·²è¾¾åˆ°â€œ%{namespace_name}â€çš„ %{free_user_limit} 个æˆå‘˜çš„é™åˆ¶ã€‚您无法å†æ·»åŠ ï¼Œä½†å¯ä»¥ç®¡ç†çŽ°æœ‰æˆå‘˜ï¼Œä¾‹å¦‚,通过删除éžæ´»åŠ¨æˆå‘˜å¹¶å°†å…¶æ›¿æ¢ä¸ºæ–°æˆå‘˜ã€‚"
+
+msgid "FreeUserCap|Manage members"
+msgstr "管ç†æˆå‘˜"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "管ç†æˆå‘˜ï¼š"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "è¦èŽ·å¾—更多æˆå‘˜ï¼Œ%{trial_link_start}开始试用 %{trial_link_end}或%{upgrade_link_start}å‡çº§%{upgrade_link_end}到专业版或旗舰版。"
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "è¦èŽ·å¾—更多æˆå‘˜ï¼Œè¯·å¼€å§‹è¯•ç”¨ï¼š"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "您已达到æˆå‘˜é™åˆ¶ï¼"
+
msgid "Freeze end"
msgstr "冻结结æŸ"
@@ -16736,7 +16980,7 @@ msgid "Frequently searched"
msgstr "ç»å¸¸æœç´¢çš„"
msgid "Fri"
-msgstr ""
+msgstr "星期五"
msgid "Friday"
msgstr "星期五"
@@ -16752,7 +16996,7 @@ msgstr "%{providerTitle}æºåœ°å€"
msgid "From October 19, 2022, free private groups will be limited to %d member"
msgid_plural "From October 19, 2022, free private groups will be limited to %d members"
-msgstr[0] ""
+msgstr[0] "自 2022 å¹´ 10 月 19 日起,å…è´¹ç§æœ‰ç¾¤ç»„å°†é™åˆ¶æœ€å¤š %d åæˆå‘˜åŠ å…¥"
msgid "From issue creation until deploy to production"
msgstr "从创建议题到部署至生产环境"
@@ -16981,6 +17225,9 @@ msgstr "请编辑您的æœç´¢å¹¶é‡è¯•ã€‚"
msgid "Geo|Errors:"
msgstr "错误:"
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失败"
@@ -17087,10 +17334,10 @@ msgid "Geo|Next sync scheduled at"
msgstr "下一次åŒæ­¥å®‰æŽ’在"
msgid "Geo|No %{replicable_type} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "未找到 %{replicable_type} 。若认为这是个报错,那么请å‚考 %{linkStart}Geo 故障排除%{linkEnd} 了解更多信æ¯ã€‚"
msgid "Geo|No %{replicable} were found. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "未找到 %{replicable} 。若认为这是个报错,那么请å‚考 %{linkStart}Geo 故障排除%{linkEnd} 了解更多信æ¯ã€‚"
msgid "Geo|No Geo site found"
msgstr "未找到Geo站点"
@@ -17300,7 +17547,7 @@ msgid "Geo|There are no %{replicable_type} to show"
msgstr "没有%{replicable_type}å¯æ˜¾ç¤º"
msgid "Geo|There are no %{replicable} to show"
-msgstr ""
+msgstr "无 %{replicable} 以供显示"
msgid "Geo|There was an error deleting the Geo Site"
msgstr "删除Geo站点时出错"
@@ -17320,6 +17567,9 @@ msgstr "ä¿å­˜æ­¤ Geo 站点时出错"
msgid "Geo|There was an error updating the Geo Settings"
msgstr "更新Geo设置时出错"
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "å°†è¦é‡æ–°åŒæ­¥æ‰€æœ‰%{replicableType}。å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´å®Œæˆã€‚确定继续å—?"
@@ -17465,7 +17715,7 @@ msgid "Git version"
msgstr "Git 版本"
msgid "GitAbuse|Automatically ban users from this %{scope} when they exceed the specified limits"
-msgstr ""
+msgstr "在æ¥è‡ªæ­¤ %{scope} 的用户超出了设定é™åˆ¶æ•°é‡æ—¶ï¼Œå¯¹ä»–们自动ç¦æ­¢è®¿é—®"
msgid "GitAbuse|Excluded users"
msgstr "排除的用户"
@@ -17542,9 +17792,6 @@ msgstr "GitLab议题"
msgid "GitLab KAS"
msgstr "GitLab KAS"
-msgid "GitLab Logo"
-msgstr "GitLab Logo"
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17837,7 +18084,7 @@ msgid "Global Shortcuts"
msgstr "全局快æ·é”®"
msgid "Global notification level"
-msgstr ""
+msgstr "全局通知级别"
msgid "Global notification settings"
msgstr "全局通知设置"
@@ -17852,10 +18099,10 @@ msgid "GlobalSearch|Groups"
msgstr "群组"
msgid "GlobalSearch|Help"
-msgstr ""
+msgstr "帮助"
msgid "GlobalSearch|In this project"
-msgstr ""
+msgstr "在此项目中"
msgid "GlobalSearch|Issues I've created"
msgstr "我创建的议题"
@@ -17876,13 +18123,13 @@ msgid "GlobalSearch|Projects"
msgstr "项目"
msgid "GlobalSearch|Recent epics"
-msgstr ""
+msgstr "最近的å²è¯—"
msgid "GlobalSearch|Recent issues"
-msgstr ""
+msgstr "最近的议题"
msgid "GlobalSearch|Recent merge requests"
-msgstr ""
+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 "结果已更新, %{count} 个结果å¯ç”¨ï¼Œä½¿ç”¨ä¸Šä¸‹ç®­å¤´é”®æµè§ˆæœç´¢ç»“果列表,或使用 ENTER é”®æ交。"
@@ -17897,7 +18144,7 @@ msgid "GlobalSearch|Search results are loading"
msgstr "æœç´¢ç»“果正在加载中"
msgid "GlobalSearch|Settings"
-msgstr ""
+msgstr "设置"
msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
msgstr "获å–æœç´¢è‡ªåŠ¨å®Œæˆå»ºè®®æ—¶å‡ºé”™ã€‚"
@@ -17927,10 +18174,10 @@ msgid "GlobalSearch|project"
msgstr "项目"
msgid "GlobalShortcuts|Copied source branch name to clipboard."
-msgstr ""
+msgstr "å·²å¤åˆ¶æºåˆ†æ”¯å称到剪贴æ¿ã€‚"
msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
-msgstr ""
+msgstr "无法å¤åˆ¶æºåˆ†æ”¯å称。"
msgid "Globally-allowed IP ranges"
msgstr "全局å…许的 IP 范围"
@@ -18362,7 +18609,7 @@ msgid "Group: %{name}"
msgstr "群组: %{name}"
msgid "GroupActivityMetrics|Issues created"
-msgstr "议题已创建"
+msgstr "已创建的议题"
msgid "GroupActivityMetrics|Last 30 days"
msgstr "过去 30 天"
@@ -18409,6 +18656,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "正在加载å²è¯—"
+msgid "GroupRoadmap|New epic"
+msgstr "新建å²è¯—"
+
msgid "GroupRoadmap|No start and end date"
msgstr "无开始和结æŸæ—¥æœŸ"
@@ -18445,6 +18695,9 @@ msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·åœ¨æ­¤ç¾¤ç»„或其å­ç¾¤ç»„中的一个 å²è¯— ä
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除筛选器,从 %{startDate} 到 %{endDate}。"
+msgid "GroupRoadmap|View epics list"
+msgstr "查看å²è¯—列表"
+
msgid "GroupRoadmap|Within 3 years"
msgstr "3年内"
@@ -18661,11 +18914,11 @@ msgstr "选择一个群组路径,ä¸èƒ½ä»¥ç ´æŠ˜å·å¼€å¤´æˆ–以å¥å·ç»“尾,
msgid "GroupSettings|Compliance frameworks"
msgstr "åˆè§„框架"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr "é…ç½®åˆè§„框架以æ供给此群组中的项目。 %{linkStart}了解更多信æ¯ã€‚%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
-msgstr ""
+msgstr "é…置用户在给定时间内å¯ä»¥ä¸‹è½½çš„仓库数é‡é™åˆ¶ã€‚"
msgid "GroupSettings|Custom project templates"
msgstr "自定义项目模æ¿"
@@ -19006,6 +19259,12 @@ msgstr "群组路径ä¸å¯ç”¨ï¼Œå·²æ›¿æ¢ä¸ºå»ºè®®çš„å¯ç”¨è·¯å¾„。"
msgid "Groups|Learn more"
msgstr "了解更多"
+msgid "Groups|Learn more about subgroups"
+msgstr "了解更多关于å­ç»„çš„ä¿¡æ¯"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr "æˆå‘˜ã€é¡¹ç›®ã€è¯•ç”¨å’Œä»˜è´¹è®¢é˜…与特定的顶级群组相关è”。如果您已ç»æ˜¯é¡¶çº§ç¾¤ç»„çš„æˆå‘˜ï¼Œæ‚¨å¯ä»¥åˆ›å»ºä¸€ä¸ªå­ç»„,以便您的新工作æˆä¸ºçŽ°æœ‰é¡¶çº§ç¾¤ç»„的一部分。您è¦æ”¹ä¸ºåˆ›å»ºå­ç»„å—?"
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "组å必须以字æ¯ã€æ•°å­—ã€è¡¨æƒ…或下划线开头,å¯ä»¥åŒ…å«å¥ç‚¹ã€ç ´æŠ˜å·ã€ç©ºæ ¼å’Œæ‹¬å·ã€‚"
@@ -19024,6 +19283,9 @@ msgstr "å­ç»„å称"
msgid "Groups|Subgroup slug"
msgstr "å­ç»„标识串"
+msgid "Groups|You're creating a new top-level group"
+msgstr "您正在创建一个新的顶级群组"
+
msgid "Guideline"
msgstr "å‚考"
@@ -19031,7 +19293,7 @@ msgid "HAR (HTTP Archive)"
msgstr "HAR(HTTP 存档)"
msgid "HAR file URL"
-msgstr ""
+msgstr "HAR 文件 URL"
msgid "HAR file path or URL"
msgstr "HAR 文件路径或 URL"
@@ -19040,13 +19302,13 @@ msgid "HTTP Archive (HAR)"
msgstr "HTTP 存档(HAR)"
msgid "HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url}"
-msgstr ""
+msgstr "HTTP Basic: Access denied. 所æ供的å£ä»¤æˆ–令牌ä¸æ­£ç¡®ï¼Œæˆ–ä½ çš„è´¦å·å¼€å¯äº† 2FA åŒé‡è®¤è¯ï¼Œè€Œæ­¤æ—¶å°±éœ€è¦ä¸ªäººè®¿é—®ä»¤ç‰Œï¼ˆa personal access token),而éžå£ä»¤ã€‚请å‚考 %{help_page_url}"
msgid "Harbor Registry"
msgstr "Harbor é•œåƒåº“"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
-msgstr "Harbor 集æˆæ¿€æ´»åŽï¼Œå°†åˆ›å»ºå…¨å±€å˜é‡â€œ$HARBOR_USERNAMEâ€ã€â€œ$HARBOR_HOSTâ€ã€â€œ$HARBOR_OCIâ€ã€â€œ$HARBOR_PASSWORDâ€ã€â€œ$HARBOR_URLâ€å’Œâ€œ$HARBOR_PROJECTâ€ä»¥ä¾› CI/CD 使用。"
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
+msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
msgstr "Harbor 实例的基础 URL。"
@@ -19080,14 +19342,17 @@ msgstr "使用 Harbor 作为该项目的容器镜åƒåº“。"
msgid "HarborRegistry|%d artifact"
msgid_plural "HarborRegistry|%d artifacts"
-msgstr[0] ""
+msgstr[0] "%d 个产物"
msgid "HarborRegistry|%{count} Image repository"
msgid_plural "HarborRegistry|%{count} Image repositories"
msgstr[0] "%{count} 个镜åƒä»“库"
msgid "HarborRegistry|-- artifacts"
-msgstr ""
+msgstr "-- 产物"
+
+msgid "HarborRegistry|-- tags"
+msgstr "-- tags"
msgid "HarborRegistry|Digest: %{imageId}"
msgstr "摘è¦: %{imageId}"
@@ -19108,25 +19373,25 @@ msgid "HarborRegistry|Root image"
msgstr "根镜åƒ"
msgid "HarborRegistry|Something went wrong while fetching the artifact list."
-msgstr ""
+msgstr "获å–产物清å•æ—¶å‡ºé”™ã€‚"
msgid "HarborRegistry|Something went wrong while fetching the repository list."
-msgstr ""
+msgstr "获å–仓库清å•æ—¶å‡ºé”™ã€‚"
msgid "HarborRegistry|Something went wrong while fetching the tags."
-msgstr ""
+msgstr "获å–标签时出错。"
msgid "HarborRegistry|Sorry, your filter produced no results."
msgstr "对ä¸èµ·ï¼Œæ‚¨çš„过滤器没有产生任何结果。"
msgid "HarborRegistry|Tag"
-msgstr ""
+msgstr "标签"
msgid "HarborRegistry|The filter returned no results"
msgstr "过滤器没有返回结果"
msgid "HarborRegistry|There are no harbor images stored for this project"
-msgstr ""
+msgstr "无此项目的容器镜åƒï¼ˆharbor images)。"
msgid "HarborRegistry|This image has no artifacts"
msgstr "该镜åƒæœªæœ‰äº§ç‰©"
@@ -19134,8 +19399,8 @@ msgstr "该镜åƒæœªæœ‰äº§ç‰©"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器。"
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr "连接到 Harbor Registry 出错。请å°è¯•åˆ·æ–°é¡µé¢ã€‚如果此错误ä»ç„¶å­˜åœ¨ï¼Œè¯·æŸ¥çœ‹ %{docLinkStart}故障排查文档%{docLinkEnd}。"
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr "我们在连接到 Harbour Registry æ—¶é‡åˆ°é—®é¢˜ã€‚请å°è¯•åˆ·æ–°é¡µé¢ã€‚如果此错误ä»ç„¶å­˜åœ¨ï¼Œè¯·æŸ¥çœ‹%{docLinkStart}文档%{docLinkEnd}。"
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
msgstr "使用 Harbor Registry,æ¯ä¸ªé¡¹ç›®éƒ½æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å®¹å™¨é•œåƒã€‚"
@@ -19286,7 +19551,7 @@ msgid_plural "Hide charts"
msgstr[0] "éšè—图表"
msgid "Hide comments"
-msgstr ""
+msgstr "éšè—评论"
msgid "Hide comments on this file"
msgstr "éšè—对此文件的评论"
@@ -19452,7 +19717,7 @@ msgid "How the job limiter handles jobs exceeding the thresholds specified below
msgstr "作业é™åˆ¶å™¨å¦‚何处ç†è¶…出以下指定阈值的作业。 “trackâ€æ¨¡å¼åªè®°å½•ä½œä¸šã€‚“compressâ€æ¨¡å¼åŽ‹ç¼©ä½œä¸šå¹¶åœ¨åŽ‹ç¼©å¤§å°è¶…过é™åˆ¶æ—¶å¼•å‘异常。"
msgid "How to track time"
-msgstr ""
+msgstr "如何跟踪时间"
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -19565,26 +19830,47 @@ msgstr "标识符"
msgid "Identities"
msgstr "身份标识"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "新验è¯ç å·²å‘é€ã€‚"
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "在您创建第一个项目之å‰ï¼Œæˆ‘们需è¦æ‚¨ä½¿ç”¨æœ‰æ•ˆçš„付款方å¼éªŒè¯æ‚¨çš„身份。在此步骤中ä¸ä¼šå‘您收费。如果我们需è¦å‘您收费,我们会通知您。"
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "在您创建群组之å‰ï¼Œæˆ‘们需è¦æ‚¨ä½¿ç”¨æœ‰æ•ˆçš„付款方å¼éªŒè¯æ‚¨çš„身份。在此步骤中ä¸ä¼šå‘您收费。如果我们需è¦å‘您收费,我们会通知您。"
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "在您完æˆåˆ›å»ºå¸æˆ·ä¹‹å‰ï¼Œæˆ‘们需è¦éªŒè¯æ‚¨çš„身份。在验è¯é¡µé¢ä¸Šï¼Œè¾“入以下验è¯ç ã€‚"
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr "在您登录之å‰ï¼Œæˆ‘们需è¦éªŒè¯æ‚¨çš„身份。请在登录页é¢è¾“入以下验è¯ç ã€‚"
+msgid "IdentityVerification|Confirm your email address"
+msgstr "确认您的电å­é‚®ä»¶åœ°å€"
+
msgid "IdentityVerification|Create a project"
msgstr "创建项目"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "未收到验è¯ç ï¼Ÿ"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "输入验è¯ç ã€‚"
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "输入有效的验è¯ç ã€‚"
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
-msgstr ""
+msgstr "为了增加安全性,您需è¦é€šè¿‡å‡ ä¸ªå¿«é€Ÿæ­¥éª¤æ¥éªŒè¯æ‚¨çš„身份。"
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr "为了增加安全性,您需è¦éªŒè¯æ‚¨çš„èº«ä»½ã€‚æˆ‘ä»¬å·²å‘ %{email} å‘é€éªŒè¯ç "
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr "GitLab ä¸ä¼šæ”¶å–或存储您的付款信æ¯ï¼Œå®ƒåªä¼šç”¨äºŽéªŒè¯ã€‚"
+
msgid "IdentityVerification|Help us keep GitLab secure"
-msgstr ""
+msgstr "å¸®åŠ©æˆ‘ä»¬ç¡®ä¿ GitLab 的安全"
msgid "IdentityVerification|Help us protect your account"
msgstr "帮助我们ä¿æŠ¤æ‚¨çš„å¸æˆ·"
@@ -19599,22 +19885,22 @@ msgid "IdentityVerification|If you've lost access to the email associated to thi
msgstr "如果您无法访问与此å¸æˆ·å…³è”的电å­é‚®ä»¶æˆ–验è¯ç æœ‰é—®é¢˜ï¼Œ%{link_start}这里是您å¯ä»¥é‡‡å–的其他一些步骤。%{link_end}"
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "国际拨å·ç "
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
msgstr "超过最大登录å°è¯•æ¬¡æ•°ã€‚等待 %{interval} åŽé‡è¯•ã€‚"
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "电è¯å·ç "
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "电è¯å·ç ä¸èƒ½ä¸ºç©ºã€‚"
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
-msgstr ""
+msgstr "电è¯å·ç å¿…须是 %{maxLength} ä½æˆ–更少。"
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "电è¯å·ç åªèƒ½åŒ…å«æ•°å­—。"
msgid "IdentityVerification|Please enter a valid code"
msgstr "请输入验è¯ç "
@@ -19622,16 +19908,22 @@ msgstr "请输入验è¯ç "
msgid "IdentityVerification|Resend code"
msgstr "é‡æ–°å‘é€éªŒè¯ç "
+msgid "IdentityVerification|Send a new code"
+msgstr "å‘é€æ–°çš„验è¯ç "
+
msgid "IdentityVerification|Send code"
-msgstr ""
+msgstr "å‘é€éªŒè¯ç "
+
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr "出错了,请å†è¯•ä¸€æ¬¡ã€‚"
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr "步骤1:验è¯ç”µè¯å·ç "
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr "验è¯ç å·²è¿‡æœŸã€‚é‡æ–°å‘é€æ–°éªŒè¯ç ç„¶åŽé‡è¯•ã€‚"
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr "验è¯ç ä¸æ­£ç¡®ã€‚å†æ¬¡è¾“入或é‡æ–°å‘é€æ–°éªŒè¯ç ã€‚"
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr "验è¯æˆåŠŸ"
msgid "IdentityVerification|Verify code"
msgstr "验è¯ç "
+msgid "IdentityVerification|Verify email address"
+msgstr "验è¯æ‚¨çš„电å­é‚®ä»¶åœ°å€"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "验è¯ä»˜æ¬¾æ–¹å¼"
+
msgid "IdentityVerification|Verify your identity"
msgstr "验è¯æ‚¨çš„身份"
@@ -19650,13 +19948,16 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr "您å¯ä»¥ç¨åŽéšæ—¶éªŒè¯æ‚¨çš„å¸æˆ·ï¼Œæ¥åˆ›å»ºä¸€ä¸ªç¾¤ç»„。"
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
-msgstr ""
+msgstr "您将收到包å«éªŒè¯ç çš„短信。å¯èƒ½ä¼šæ”¶å–标准费用。"
+
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "您已达到最大å°è¯•æ¬¡æ•°ã€‚等待 %{interval} 并é‡è¯•ã€‚"
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr "您已达到最大å°è¯•æ¬¡æ•°ã€‚等待 %{interval} 或é‡æ–°å‘é€æ–°ä»£ç ï¼Œç„¶åŽé‡è¯•ã€‚"
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "您的å¸æˆ·å·²æˆåŠŸéªŒè¯ã€‚ç¨åŽæ‚¨å°†è¢«é‡å®šå‘到您的å¸æˆ·æˆ–%{redirect_url_start}å•å‡»æ­¤å¤„%{redirect_url_end}刷新。"
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "您的å¸æˆ·å·²æˆåŠŸéªŒè¯ã€‚ç¨åŽæ‚¨å°†è¢«é‡å®šå‘到您的å¸æˆ·ã€‚您也å¯ä»¥ %{redirect_url_start}刷新页é¢%{redirect_url_end}。"
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "您的验è¯ç å°†åœ¨ %{expires_in_minutes} 分钟åŽè¿‡æœŸã€‚"
@@ -19736,6 +20037,12 @@ msgstr "å¦‚æžœæ‚¨æœ€è¿‘æ²¡æœ‰ç™»å½•ï¼Œè¯·ç«‹å³ %{password_link_start}更改密ç
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "如果您最近没有登录,请立å³æ›´æ”¹å¯†ç : %{password_link}。"
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr "如果您最近没有å°è¯•ç™»å½•ï¼Œè¯·ç«‹å³%{password_link_start}更改密ç %{password_link_end}。"
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr "如果您最近没有å°è¯•ç™»å½•ï¼Œè¯·ç«‹å³æ›´æ”¹å¯†ç ï¼š%{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 "如果您从仓库检查中得到大é‡è¯¯æŠ¥ï¼Œæ‚¨å¯ä»¥ä»Žæ•°æ®åº“中清除所有仓库检查信æ¯ã€‚"
@@ -19745,6 +20052,9 @@ msgstr "如果您丢失了æ¢å¤ç ï¼Œæ‚¨å¯ä»¥ç”Ÿæˆæ–°çš„æ¢å¤ç ï¼Œæ‰€æœ‰ä»¥
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "如果您最近从上述IP地å€ç™»å½•è¿‡ï¼Œåˆ™å¯ä»¥å¿½ç•¥æ­¤ç”µå­é‚®ä»¶ã€‚"
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr "如果您最近å°è¯•ç™»å½•ï¼Œä½†ä¸å°å¿ƒè¾“入了错误的åŒé‡èº«ä»½éªŒè¯ç ï¼Œæ‚¨å¯ä»¥å¿½ç•¥æ­¤ç”µå­é‚®ä»¶ã€‚"
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr "如果您想è¦é‡æ–°å¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼Œè¯·è®¿é—®%{two_factor_link}"
@@ -19924,6 +20234,9 @@ msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr "超过%{provider}的速率é™åˆ¶ã€‚请ç¨åŽå†è¯•"
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "ç¦æ­¢çš„导入URL: %{message}"
@@ -19948,6 +20261,9 @@ msgstr "获å–您的%{provider}仓库失败"
msgid "ImportProjects|Select the repositories you want to import"
msgstr "选择您想è¦å¯¼å…¥çš„仓库"
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "无法导入远程数æ®ã€‚"
@@ -20766,7 +21082,7 @@ msgid "Incident|Error deleting incident timeline event: %{error}"
msgstr "删除事件时间线事件时出错: %{error}"
msgid "Incident|Error updating incident timeline event: %{error}"
-msgstr ""
+msgstr "更新时间线事件时出错:%{error}"
msgid "Incident|Metrics"
msgstr "指标"
@@ -20787,7 +21103,7 @@ msgid "Incident|Something went wrong while fetching incident timeline events."
msgstr "获å–事件(incident)时间线事件时出了错。"
msgid "Incident|Something went wrong while updating the incident timeline event."
-msgstr ""
+msgstr "更新时间线事件时出错。"
msgid "Incident|Summary"
msgstr "摘è¦"
@@ -20823,7 +21139,7 @@ msgid "Include the username in the URL if required: %{code_open}https://username
msgstr "如果需è¦ï¼Œè¯·åœ¨URL中包å«ç”¨æˆ·å:%{code_open}https://username@gitlab.company.com/group/project.git%{code_close}。"
msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
-msgstr ""
+msgstr "包括 LFS 对象。它å¯ä»¥è¢«ç¾¤ç»„设置或项目设置覆盖。设置为 0 表示没有é™åˆ¶ã€‚"
msgid "Includes an MVC structure to help you get started"
msgstr "åŒ…å« MVC 结构以帮助您入门"
@@ -20852,6 +21168,9 @@ msgstr "未完æˆ"
msgid "Increase"
msgstr "增加"
+msgid "Indent line"
+msgstr "缩进行"
+
msgid "Index"
msgstr "索引"
@@ -20970,7 +21289,7 @@ msgid "Insights"
msgstr "洞察"
msgid "Insights|Configure a custom report for insights into your group processes such as amount of issues, bugs, and merge requests per month. %{linkStart}How do I configure an insights report?%{linkEnd}"
-msgstr ""
+msgstr "é…置自定义报告æ¥æ·±å…¥äº†è§£æ‚¨çš„群组进度,例如æ¯æœˆçš„议题数é‡ã€bug æ•°é‡å’Œåˆå¹¶è¯·æ±‚æ•°é‡ã€‚%{linkStart}如何é…置洞察报告?%{linkEnd}"
msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
msgstr "有些æ¡ç›®ä¸å¯è§ï¼Œç”±äºŽå·²åœ¨insights.yml文件中筛选掉(è§projects.onlyé…置以了解更多信æ¯)。"
@@ -21072,6 +21391,9 @@ msgstr "添加集æˆ"
msgid "Integrations|Add namespace"
msgstr "添加命å空间"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr "添加命å空间仅适用于å…许跨站点 cookie çš„æµè§ˆå™¨ã€‚%{linkStart}了解更多%{linkEnd}。"
+
msgid "Integrations|All details"
msgstr "所有详细信æ¯"
@@ -21132,12 +21454,18 @@ msgstr "å¯ç”¨ SSL 验è¯"
msgid "Integrations|Enable comments"
msgstr "å¯ç”¨è¯„论"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr "ç¡®ä¿æ‚¨çš„实例 URL 正确且您的实例é…置正确。%{linkStart}了解更多%{linkEnd}。"
+
msgid "Integrations|Enter your alias"
msgstr "输入您的别å"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "无法链接命å空间,请é‡è¯•ã€‚"
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr "无法加载 Jira Connect åº”ç”¨ç¨‹åº ID。请å†è¯•ä¸€æ¬¡ã€‚"
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr "加载命å空间失败,请é‡è¯•ã€‚"
@@ -21150,6 +21478,9 @@ msgstr "无法登录 GitLab。"
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr "无法å–消链接命å空间,请é‡è¯•ã€‚"
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr "无法更新 GitLab 版本。请é‡è¯•ã€‚"
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr "GitLab 管ç†å‘˜å¯ä»¥è®¾ç½®æ‰€æœ‰ç¾¤ç»„和项目默认继承和使用的集æˆï¼Œ 这些集æˆåº”用于所有尚未使用自定义设置的组和项目, 如果需è¦è®¾ç½®ï¼Œæ‚¨å¯ä»¥è¦†ç›–一个组或项目的自定义设置。 了解更多关于 %{integrations_link_start}实例级集æˆç®¡ç†%{link_end}。"
@@ -21241,7 +21572,7 @@ msgid "Integrations|Send notifications about project events to a Unify Circuit c
msgstr "将有关项目事件的通知å‘é€åˆ° Unify Circuit 对è¯ã€‚ %{docs_link}"
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "登录到 %{url}"
msgid "Integrations|Sign in to GitLab"
msgstr "登录到 GitLab"
@@ -21342,9 +21673,6 @@ msgstr "é—´éš”"
msgid "Interval Pattern"
msgstr "循环周期"
-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 "从 13.1 版本起,您需è¦å…ˆ%{recreate_link_start}é‡å»ºç´¢å¼•%{link_end}æ‰èƒ½æ‰§è¡Œ%{reindexing_link_start}ä¸åœæœºé‡ç´¢å¼•%{link_end}å’Œ%{migrations_link_start}高级æœç´¢è¿ç§»%{link_end}。"
-
msgid "Introducing Your DevOps Reports"
msgstr "介ç»æ‚¨çš„ DevOps 报告"
@@ -21556,7 +21884,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr "æˆå‘˜å·²æˆåŠŸæ·»åŠ "
msgid "InviteMembersModal|Please select members or type email addresses to invite"
-msgstr ""
+msgstr "请选择è¦é‚€è¯·çš„æˆå‘˜æˆ–输入电å­é‚®ä»¶åœ°å€"
msgid "InviteMembersModal|Review the invite errors and try again:"
msgstr "请检查邀请错误并é‡è¯•ï¼š"
@@ -21577,7 +21905,7 @@ msgid "InviteMembersModal|Show less"
msgstr "显示较少"
msgid "InviteMembersModal|Show more (%{count})"
-msgstr ""
+msgstr "显示更多(%{count})"
msgid "InviteMembersModal|Something went wrong"
msgstr "出现错误"
@@ -21736,8 +22064,14 @@ msgstr "正在使用许å¯è¯ï¼š"
msgid "Is using seat"
msgstr "正在使用许å¯å¸­ä½"
+msgid "IssuableEvents|removed review request for"
+msgstr "已删除审核请求"
+
+msgid "IssuableEvents|requested review from"
+msgstr "请求审核"
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
-msgstr ""
+msgstr "%{wi_type} 由 %{created_at} 创建"
msgid "IssuableStatus|Closed"
msgstr "已关闭"
@@ -21812,7 +22146,7 @@ msgid "Issue update failed"
msgstr "议题更新失败"
msgid "Issue was closed by %{name} %{reason}"
-msgstr "%{reason},议题由 %{name} 关闭。"
+msgstr "议题由 %{name} 关闭 %{reason}"
msgid "Issue weight"
msgstr "议题æƒé‡"
@@ -21835,6 +22169,9 @@ msgstr "加载议题失败。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "IssueAnalytics|Issue"
msgstr "议题"
+msgid "IssueAnalytics|Iteration"
+msgstr "迭代"
+
msgid "IssueAnalytics|Milestone"
msgstr "里程碑"
@@ -22112,7 +22449,7 @@ msgid "Iterations|Edit iteration cadence"
msgstr "编辑迭代周期"
msgid "Iterations|Enable automatic scheduling"
-msgstr ""
+msgstr "å¯ç”¨è‡ªåŠ¨è®¡åˆ’"
msgid "Iterations|Enable roll over"
msgstr "å¯ç”¨è½®æ¢"
@@ -22207,9 +22544,6 @@ msgstr "无法ä¿å­˜å‘¨æœŸï¼Œè¯·é‡è¯•ã€‚"
msgid "Iterations|Upcoming iterations"
msgstr "å³å°†è¿›è¡Œçš„迭代"
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr "日期ä¸èƒ½ä¸Žè¯¥ç¾¤ç»„内的其它现有迭代é‡å "
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr "日期ä¸èƒ½ä¸Žæ­¤è¿­ä»£å‘¨æœŸå†…的其他现有迭代é‡å "
@@ -22950,7 +23284,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr "å‡çº§%{labelTitle}将使其å¯ç”¨äºŽ%{groupName}内的所有项目。现有的åŒå项目标记将被åˆå¹¶ã€‚现有的åŒå群组标记也将被åˆå¹¶ã€‚该æ“作ä¸å¯æ’¤é”€ã€‚"
msgid "Label|Assignee"
-msgstr ""
+msgstr "指派人"
msgid "Language"
msgstr "语言"
@@ -23055,6 +23389,9 @@ msgstr "最åŽç™»å½•äºŽï¼š"
msgid "Last successful update"
msgstr "最近æˆåŠŸçš„æ›´æ–°"
+msgid "Last successful update %{time}."
+msgstr "上次æˆåŠŸæ›´æ–° %{time}。"
+
msgid "Last time verified"
msgstr "最近一次验è¯"
@@ -23136,8 +23473,8 @@ msgstr "了解如何使用GitLab%{no_packages_link_start}å‘布和共享您的åŒ
msgid "Learn more"
msgstr "进一步了解"
-msgid "Learn more about %{username}"
-msgstr "进一步了解%{username}"
+msgid "Learn more about %{name}"
+msgstr "了解更多关于 %{name}"
msgid "Learn more about Auto DevOps"
msgstr "了解更多关于Auto DevOps"
@@ -23173,7 +23510,7 @@ msgid "Learn more about groups."
msgstr "了解关于群组的更多信æ¯ã€‚"
msgid "Learn more about issues."
-msgstr ""
+msgstr "了解有关议题的更多信æ¯ã€‚"
msgid "Learn more about max seats used"
msgstr "了解更多关于最大席ä½æ•°çš„ä¿¡æ¯"
@@ -23902,7 +24239,7 @@ msgid "Mailgun events"
msgstr "Mailgun事件"
msgid "Main menu"
-msgstr ""
+msgstr "主èœå•"
msgid "Maintenance mode"
msgstr "维护模å¼"
@@ -23919,6 +24256,9 @@ msgstr "GitLab Geoå¯ä»¥åˆ›å»ºGitLab实例的åªè¯»é•œåƒ, 使得从远端克隆
msgid "Make issue confidential"
msgstr "将议题设置为ç§å¯†ã€‚"
+msgid "Make sure you choose a strong, unique password."
+msgstr "ç¡®ä¿é€‰æ‹©ä¸€ä¸ªå¼ºå¤§ä¸”唯一的密ç ã€‚"
+
msgid "Make sure you have the correct permissions to link your project."
msgstr "请确ä¿æ‚¨æœ‰æ­£ç¡®çš„æƒé™å…³è”您的项目。"
@@ -23970,12 +24310,12 @@ msgstr "管ç†é¡¹ç›®ã€‚"
msgid "Manage two-factor authentication"
msgstr "管ç†åŒé‡è®¤è¯"
-msgid "Manage your license"
-msgstr "管ç†è®¸å¯è¯"
-
msgid "Manage your project's triggers"
msgstr "管ç†æ‚¨çš„项目触å‘器"
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "托管账户"
@@ -24057,9 +24397,24 @@ msgstr "添加删除线文本 (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "添加带删除线的文本(%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr "缩进行(%{modifierKey})"
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr "缩进行 (%{modifier_key}])"
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "å‡å°‘缩进行 (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "å‡å°‘缩进行(%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "æ”¯æŒ %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr "已标记"
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "标记删除于 - %{deletion_time}"
@@ -24069,9 +24424,6 @@ msgstr "标记为è‰ç¨¿ã€‚åªæœ‰åœ¨æ ‡è®°ä¸ºå°±ç»ªåŽæ‰èƒ½åˆå¹¶ã€‚"
msgid "Marked as ready. Merging is now allowed."
msgstr "标记为已准备好。现在å…许åˆå¹¶ã€‚"
-msgid "Marked this %{noun} as a draft."
-msgstr "已标记此%{noun}为è‰ç¨¿ã€‚"
-
msgid "Marked this %{noun} as ready."
msgstr "已将 %{noun} 标记为准备就绪。"
@@ -24084,8 +24436,8 @@ msgstr "将此议题标记为%{issue_ref}的相关议题。"
msgid "Marked to do as done."
msgstr "将待办事项标记为已完æˆã€‚"
-msgid "Marks this %{noun} as a draft."
-msgstr "将标记此%{noun}为è‰ç¨¿ã€‚"
+msgid "Marks"
+msgstr "标记"
msgid "Marks this %{noun} as ready."
msgstr "将 %{noun} 标记为就绪。"
@@ -24193,7 +24545,7 @@ msgid "Maximum allowable lifetime for access token (days)"
msgstr "访问令牌的最长有效期(天)"
msgid "Maximum allowed lifetime for SSH keys (days)"
-msgstr ""
+msgstr "SSH 密钥的最长å…许生命周期(天)"
msgid "Maximum artifacts size"
msgstr "最大工件大å°"
@@ -24321,6 +24673,9 @@ msgstr "æ¯ä¸ªåŽŸå§‹è·¯å¾„æ¯åˆ†é’Ÿçš„最大请求数(默认为 300)。设ç½
msgid "Maximum number of unique IP addresses per user."
msgstr "æ¯ä¸ªç”¨æˆ·çš„最大唯一 IP 地å€æ•°ã€‚"
+msgid "Maximum number of variables loaded (2000)"
+msgstr "已加载最大å˜é‡æ•° (2000)"
+
msgid "Maximum of 255 characters"
msgstr "最多使用 255 个字符"
@@ -24675,7 +25030,7 @@ msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚和批准设置已移动。"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改并与他人进行讨论"
@@ -24765,7 +25120,7 @@ msgid "MergeRequests|Create issue to resolve thread"
msgstr "创建议题以解决主题"
msgid "MergeRequests|Reference copied"
-msgstr ""
+msgstr "å·²å¤åˆ¶å¼•ç”¨"
msgid "MergeRequests|Saving the comment failed"
msgstr "ä¿å­˜è¯„论失败"
@@ -24843,10 +25198,10 @@ msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
msgstr "æœç´¢ï¼ˆä¾‹å¦‚ *.vue)(%{modifier_key}P)"
msgid "MergeTopics|%{sourceTopic} will be removed"
-msgstr ""
+msgstr "%{sourceTopic} 将被删除"
msgid "MergeTopics|All assigned projects will be moved to %{targetTopic}"
-msgstr ""
+msgstr "所有分é…的项目将被移动到 %{targetTopic}"
msgid "MergeTopics|Merge topics"
msgstr "åˆå¹¶ä¸»é¢˜"
@@ -24855,7 +25210,7 @@ msgid "MergeTopics|Merging topics will cause the following:"
msgstr "åˆå¹¶ä¸»é¢˜å°†å¯¼è‡´ä»¥ä¸‹æƒ…况:"
msgid "MergeTopics|Move all assigned projects from the source topic to the target topic and remove the source topic."
-msgstr ""
+msgstr "将所有分é…的项目从æºä¸»é¢˜ç§»åŠ¨åˆ°ç›®æ ‡ä¸»é¢˜ï¼Œå¹¶ç§»é™¤æºä¸»é¢˜ã€‚"
msgid "MergeTopics|Source topic"
msgstr "æºä¸»é¢˜"
@@ -25447,6 +25802,9 @@ msgstr "未å¯åŠ¨çš„议题(开放和未分é…)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr "使用里程碑在固定时间段内跟踪议题和åˆå¹¶è¯·æ±‚åˆå¹¶è¯·æ±‚"
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} 完æˆ"
+
msgid "Min Value"
msgstr "最å°å€¼"
@@ -25471,6 +25829,9 @@ msgstr "é•œåƒè®¾ç½®ä»…GitLab管ç†å‘˜å¯ç”¨ã€‚"
msgid "Mirror user"
msgstr "é•œåƒç”¨æˆ·"
+msgid "Mirrored from %{link}."
+msgstr "从 %{link} é•œåƒã€‚"
+
msgid "Mirrored repositories"
msgstr "é•œåƒçš„仓库"
@@ -25550,7 +25911,7 @@ msgid "Monitor"
msgstr "监控"
msgid "Monitor GitLab with Prometheus."
-msgstr ""
+msgstr "使用 Prometheus 监控 GitLab。"
msgid "Monitor Settings"
msgstr "监控设置"
@@ -25735,6 +26096,9 @@ msgstr "å称已被å ç”¨ã€‚"
msgid "Name new label"
msgstr "命å新标记"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr "用作æœåŠ¡å°ç”µå­é‚®ä»¶å‘件人的å称。"
+
msgid "Name:"
msgstr "å称:"
@@ -25930,7 +26294,7 @@ msgid "New Jira import"
msgstr "新建Jira导入"
msgid "New Label"
-msgstr "新标签"
+msgstr "新建标记"
msgid "New Milestone"
msgstr "新建里程碑"
@@ -25947,6 +26311,9 @@ msgstr "创建æµæ°´çº¿è®¡åˆ’"
msgid "New Project"
msgstr "新建项目"
+msgid "New Protected Branch"
+msgstr "新建å—ä¿æŠ¤çš„分支"
+
msgid "New Requirement"
msgstr "新建需求"
@@ -25954,7 +26321,7 @@ msgid "New Snippet"
msgstr "新建代ç ç‰‡æ®µ"
msgid "New Test Case"
-msgstr "新测试用例"
+msgstr "新建测试用例"
msgid "New User"
msgstr "新建用户"
@@ -26032,7 +26399,7 @@ msgid "New merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
msgid "New milestone"
-msgstr "新里程碑"
+msgstr "新建里程碑"
msgid "New name"
msgstr "新建å称"
@@ -26086,7 +26453,7 @@ msgid "New tag"
msgstr "新建标签"
msgid "New test case"
-msgstr "新测试用例"
+msgstr "新建测试用例"
msgid "New topic"
msgstr "新主题"
@@ -26224,7 +26591,7 @@ msgid "No credit card required."
msgstr "无需信用å¡ã€‚"
msgid "No data available"
-msgstr ""
+msgstr "æ— å¯ç”¨æ•°æ®"
msgid "No data found"
msgstr "未找到数æ®"
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] "ä¸ç”¨æ‹…心,您现在ä»ç„¶å¯ä»¥ä½¿ç”¨æ‰€æœ‰ %{strong}%{plan_name}%{strong_close} 功能。您有 %{remaining_days} 天æ¥ç»­è®¢æ‚¨çš„订阅。"
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "æ交次数"
@@ -26600,7 +26970,7 @@ msgid "Nothing to preview."
msgstr "没有å¯é¢„览的内容。"
msgid "Notification Email"
-msgstr ""
+msgstr "邮件通知"
msgid "Notification events"
msgstr "通知事件"
@@ -26628,7 +26998,7 @@ msgid_plural "NotificationEmail|Reviewers: %{users}"
msgstr[0] "审核者: %{users}"
msgid "NotificationEvent|Change reviewer merge request"
-msgstr "更改审核者åˆå¹¶è¯·æ±‚"
+msgstr "更改åˆå¹¶è¯·æ±‚的审核者"
msgid "NotificationEvent|Close issue"
msgstr "关闭议题"
@@ -26640,7 +27010,7 @@ msgid "NotificationEvent|Failed pipeline"
msgstr "æµæ°´çº¿å¤±è´¥"
msgid "NotificationEvent|Fixed pipeline"
-msgstr "ä¿®å¤çš„æµæ°´çº¿"
+msgstr "æµæ°´çº¿è¢«ä¿®å¤"
msgid "NotificationEvent|Issue due"
msgstr "到期议题"
@@ -26729,11 +27099,20 @@ msgstr "无法识别登录ä½ç½®æ—¶é€šè¿‡ç”µå­é‚®ä»¶é€šçŸ¥ç”¨æˆ·ã€‚"
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr "%{author_link} 的议题 %{issue_reference_link} å³å°†åˆ°æœŸã€‚"
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr "%{author_name} %{action_name} %{ref_type} %{ref_name} 于 %{project_link}"
+
+msgid "Notify|%{changed_files}:"
+msgstr "%{changed_files}:"
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{mr_link} 中的 %{commit_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
-msgstr ""
+msgstr "%{commits_text} æ¥è‡ªåˆ†æ”¯ `%{target_branch}`"
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr "%{committed_by_start} 由 %{author_name} %{committed_by_end} %{committed_at_start}于 %{committed_date} %{committed_at_end}"
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email},现在称为 %{user_name},已接å—了您的邀请加入 %{target_name}%{target_model_name} 。"
@@ -26741,26 +27120,50 @@ msgstr "%{invite_email},现在称为 %{user_name},已接å—了您的邀请åŠ
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "%{invited_user} å·²%{highlight_start}æ‹’ç»%{highlight_end}您加入%{target_link}%{target_name} 的邀请。"
+msgid "Notify|%{issues} imported."
+msgstr "%{issues} 已导入。"
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} 请求访问 %{target_source_link} %{target_type} çš„ %{member_role} æƒé™ã€‚"
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
-msgstr ""
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}åˆå¹¶è¯·æ±‚%{highlight_end} %{mr_link} ç”± %{reviewer_avatar}%{reviewer_link} %{reviewer_highlight}批准%{highlight_end}"
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}åˆå¹¶è¯·æ±‚%{highlight_end} %{mr_link} ç”± %{reviewer_avatar}%{reviewer_link} %{reviewer_highlight}æ‹’ç»æ‰¹å‡†%{highlight_end}"
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr "%{name} 请求对 %{mr_link}进行新的审核。"
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr "%{p_start}è¦æ›´æ–°æœ¬åœ°ä»“库中的远端 URL,è¿è¡Œï¼ˆå¯¹äºŽ ssh):%{p_end} %{ssh_url_to_repo},%{p_start}或对于 http(s):%{p_end} %{http_url_to_repo}"
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
-msgstr ""
+msgstr "%{paragraph_start}Hi %{name}ï¼%{paragraph_end} %{paragraph_start}您的å¸æˆ·æ·»åŠ äº†ä¸€ä¸ªæ–°çš„公钥:%{paragraph_end} %{paragraph_start}标题:%{key_title}%{paragraph_end} %{paragraph_start}如果此密钥被错误添加, 您å¯ä»¥åœ¨ %{removal_link} 移除它%{paragraph_end}"
+
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr "%{project_link_start}下载%{project_link_end} 项目导出。"
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr "%{update_at_start} 最åŽæ›´æ–°äºŽ %{update_at_mid} %{last_update_at} %{update_at_end}"
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
-msgstr ""
+msgstr "%{updated_by_user_name} 推é€æ–°æ交到åˆå¹¶è¯·æ±‚ %{mr_link}"
msgid "Notify|A new GPG key was added to your account:"
-msgstr ""
+msgstr "æ–°çš„ GPG 密钥已添加到您的å¸æˆ·ï¼š"
+
+msgid "Notify|A remote mirror update has failed."
+msgstr "远程镜åƒæ›´æ–°å¤±è´¥ã€‚"
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr "到期åŽï¼Œæ‚¨å¯ä»¥%{a_start}请求一个新的%{a_end}。"
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
-msgstr ""
+msgstr "关于åˆå¹¶è¯·æ±‚ %{mr_link} 的所有讨论å‡å·²ç”± %{name} 解决"
msgid "Notify|And %{total_stripped_new_commits_count} more"
-msgstr ""
+msgstr "还有 %{total_stripped_new_commits_count} 个更多"
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "指派人从 %{fromNames} 更改为 %{toNames}"
@@ -26777,17 +27180,35 @@ msgstr "%{project} çš„ Auto DevOps æµæ°´çº¿è¢«ç¦ç”¨"
msgid "Notify|CI/CD project settings"
msgstr "CI/CD 项目设置"
+msgid "Notify|Click here to set your password"
+msgstr "点击这里设置您的密ç "
+
+msgid "Notify|Commit Author"
+msgstr "æ交作者"
+
+msgid "Notify|Committed by"
+msgstr "æ交者:"
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
-msgstr ""
+msgstr "ä¸æƒ³æŽ¥æ”¶æ¥è‡ªç®¡ç†å‘˜çš„更新?"
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr "è§£æž CSV 文件时出错。请确ä¿å®ƒå…·æœ‰æ­£ç¡®çš„æ ¼å¼ï¼šä½¿ç”¨é€—å·åˆ†éš”值的分隔文本文件。"
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "在 %{singular_or_plural_line} 行中å‘现错误: %{error_lines}。请检查这些行是å¦åŒ…å«è®®é¢˜æ ‡é¢˜ã€‚"
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr "指纹:%{fingerprint}"
+msgid "Notify|Hi %{username}!"
+msgstr "您好,%{username}ï¼"
+
msgid "Notify|Hi %{user}!"
msgstr "您好 %{user}ï¼"
msgid "Notify|If this key was added in error, you can remove it under %{removal_link}"
-msgstr ""
+msgstr "如果这个 key 是错误添加的,å¯ä»¥åœ¨ %{removal_link} 下删除"
msgid "Notify|If you no longer wish to use this domain with GitLab Pages, please remove it from your GitLab project and delete any related DNS records."
msgstr "如果您ä¸å†æƒ³åœ¨ Pages 中使用这个域å,请从您的项目中删除它,并删除任何相关的DNS记录。"
@@ -26801,6 +27222,9 @@ msgstr "议题已移动到å¦ä¸€ä¸ªé¡¹ç›®ã€‚"
msgid "Notify|Learn more about Auto DevOps"
msgstr "了解有关 Auto DevOps 的更多信æ¯"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr "日志å¯èƒ½åŒ…å«æ•æ„Ÿæ•°æ®ã€‚请在转å‘此电å­é‚®ä»¶ä¹‹å‰è€ƒè™‘一下。"
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr "åˆå¹¶è¯·æ±‚ %{merge_request} 由于冲çªæ— æ³•åˆå¹¶ã€‚"
@@ -26820,29 +27244,71 @@ msgid "Notify|Merge request URL: %{merge_request_url}"
msgstr "åˆå¹¶è¯·æ±‚ URL:%{merge_request_url}"
msgid "Notify|Merge request was approved"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚已被批准"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚已被批准(%{approvals}/%{required_approvals})"
+
+msgid "Notify|Merge request was unapproved"
+msgstr "åˆå¹¶è¯·æ±‚未被批准"
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr "åˆå¹¶è¯·æ±‚未被批准(%{approvals_count}/%{approvals_required})"
msgid "Notify|Milestone changed to %{milestone}"
msgstr "里程碑已更改为 %{milestone}"
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "里程碑已删除"
msgid "Notify|New issue: %{project_issue_url}"
msgstr "新建议题:%{project_issue_url}"
+msgid "Notify|No preview for this file type"
+msgstr "无法预览此类型文件"
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "æµæ°´çº¿ %{pipeline_link} 的触å‘者为"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "æµæ°´çº¿å·²ä¿®å¤ï¼Œ#%{pipeline_id} 已通过ï¼"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr "项目 %{old_path_with_namespace} 被移动到å¦ä¸€ä¸ªä½ç½®ã€‚"
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr "项目 %{project_name} å·²æˆåŠŸå¯¼å‡ºã€‚"
+
+msgid "Notify|Remote mirror"
+msgstr "远程镜åƒ"
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr "管ç†å‘˜ä¸ºæ‚¨åˆ›å»ºäº†ä¸€ä¸ªå¸æˆ·ã€‚现在您是公å¸åº”用程åºçš„æˆå‘˜ã€‚"
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "æµæ°´çº¿ %{pipeline_link} çš„ Auto DevOps æµæ°´çº¿å¤±è´¥ï¼Œå·²åœ¨ %{project_link} 中被ç¦ç”¨ã€‚为了使用 Auto DevOps æµæ°´çº¿å’Œæ‚¨çš„项目,请查看 %{supported_langs_link},相应调整您的项目,并在您的 %{settings_link} 内开å¯Auto DevOps æµæ°´çº¿ã€‚"
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr "未包å«æ­¤æ–‡ä»¶çš„差异,因为它太大。"
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr "未包å«å·®å¼‚,因为它太大。"
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "下载链接将于24å°æ—¶åŽè¿‡æœŸã€‚"
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr "该项目现在ä½äºŽ %{project_full_name_link_start}%{project_full_name}%{link_end}下。"
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr "推é€æ²¡æœ‰åŒ…å«ä»»ä½•æ–°çš„æ交,而是强制推é€åˆ é™¤ä¸‹é¢çš„æ交和更改。"
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr "此议题到期时间:%{issue_due_date}"
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "此链接对 %{password_reset_token_valid_time} 有效。"
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr "除éžæ‚¨é€šè¿‡ %{time_start}%{time}%{time_end} 验è¯æ‚¨çš„域,å¦åˆ™å®ƒå°†ä»Žæ‚¨çš„项目中删除。"
@@ -26850,10 +27316,19 @@ msgid "Notify|You don't have access to the project."
msgstr "您没有访问此项目的æƒé™ã€‚"
msgid "Notify|You have been mentioned in an issue."
-msgstr ""
+msgstr "您在一个议题中被æåŠã€‚"
msgid "Notify|You have been mentioned in merge request %{mr_link}"
-msgstr ""
+msgstr "您在åˆå¹¶è¯·æ±‚ %{mr_link} 中被æåŠ"
+
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "您已å–消订阅管ç†å‘˜é€šçŸ¥ã€‚"
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr "项目 %{project_link} çš„ CSV 导入已完æˆã€‚"
+
+msgid "Notify|Your account has been created successfully."
+msgstr "您的å¸æˆ·å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "您加入 %{target_to_join} %{target_type} 的请求状æ€ä¸º %{denied_tag}。"
@@ -26861,6 +27336,18 @@ msgstr "您加入 %{target_to_join} %{target_type} 的请求状æ€ä¸º %{denied_t
msgid "Notify|currently supported languages"
msgstr "当å‰æ”¯æŒçš„语言"
+msgid "Notify|deleted"
+msgstr "已删除"
+
+msgid "Notify|login.........................................."
+msgstr "登录.........................................."
+
+msgid "Notify|pushed new"
+msgstr "推é€æ–°çš„"
+
+msgid "Notify|pushed to"
+msgstr "推é€åˆ°"
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "在 %{stages} 中,%{jobs} å·²æˆåŠŸå®Œæˆã€‚"
@@ -26921,6 +27408,9 @@ msgstr "确定"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "对象在æœåŠ¡å™¨ä¸Šä¸å­˜åœ¨, 或者您没有访问它的æƒé™"
+msgid "Observability"
+msgstr "å¯è§‚测性"
+
msgid "Oct"
msgstr "10月"
@@ -26959,7 +27449,7 @@ msgid_plural "On %{end_date}, your trial will end and %{namespace_name} will be
msgstr[0] "在 %{end_date},您的试用期将结æŸï¼Œ%{namespace_name} 将被é™åˆ¶ä¸º %{free_user_limit} 个æˆå‘˜"
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "在左侧边æ ï¼Œé€‰æ‹© %{merge_requests_link} 查看它们。"
msgid "On track"
msgstr "进度正常"
@@ -27081,6 +27571,9 @@ msgstr "è½®æ¢"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr "将警报直接分é…给特定的团队æˆå‘˜"
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr "将警报直接å‘é€ç»™å›¢é˜Ÿçš„特定æˆå‘˜ã€‚è¦è®¿é—®æ­¤åŠŸèƒ½ï¼Œè¯·è¦æ±‚ %{linkStart}项目所有者%{linkEnd} 至少授予您维护者角色。"
+
msgid "OnCallSchedules|Select participant"
msgstr "选择å‚与者"
@@ -27184,7 +27677,7 @@ msgid "OnDemandScans|Discard changes"
msgstr "放弃更改"
msgid "OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost."
-msgstr ""
+msgstr "您想è¦æ”¾å¼ƒæ›´æ”¹è¿˜æ˜¯ç»§ç»­ç¼–辑此é…置文件?未ä¿å­˜çš„更改将丢失。"
msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
msgstr "动æ€åº”用程åºå®‰å…¨æ€§æµ‹è¯•(DAST)"
@@ -27491,7 +27984,7 @@ msgid "OpenAPI"
msgstr "OpenAPI"
msgid "OpenAPI Specification file URL"
-msgstr ""
+msgstr "OpenAPI 规范文件 URL"
msgid "OpenAPI Specification file path or URL"
msgstr "OpenAPI 规范文件路径或 URL"
@@ -27640,6 +28133,9 @@ msgstr "GitLabå¯èƒ½æ— æ³•æ­£å¸¸å·¥ä½œï¼Œå› ä¸ºæ‚¨æ­£åœ¨ä½¿ç”¨è¿‡æ—¶çš„æµè§ˆå™¨
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "请安装一个%{browser_link_start}支æŒçš„网页æµè§ˆå™¨%{browser_link_end}以获å–更好的体验。"
+msgid "Outdent line"
+msgstr "å‡å°‘缩进行"
+
msgid "Overridden"
msgstr "覆盖"
@@ -27713,7 +28209,7 @@ msgid "Package already exists"
msgstr "软件包已存在"
msgid "Package and registry settings"
-msgstr ""
+msgstr "软件包和镜åƒåº“设置"
msgid "Package deleted successfully"
msgstr "包已æˆåŠŸåˆ é™¤"
@@ -27752,7 +28248,7 @@ msgid "Package type must be PyPi"
msgstr "包类型必须是PyPi"
msgid "Package type must be RPM"
-msgstr ""
+msgstr "包类型必须是 RPM"
msgid "Package type must be RubyGems"
msgstr "包类型必须是 RubyGems"
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] "删除 %d 个 assets"
-msgid "PackageRegistry|Delete Package File"
-msgstr "删除软件包文件"
-
msgid "PackageRegistry|Delete Package Version"
msgstr "删除软件包版本"
msgid "PackageRegistry|Delete package"
msgstr "删除软件包"
+msgid "PackageRegistry|Delete package asset"
+msgstr "删除软件包 asset"
+
msgid "PackageRegistry|Delete selected"
msgstr "删除选中"
@@ -27956,6 +28452,9 @@ msgstr "实例级别"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr "无效的软件包:元数æ®æå–失败"
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "上次下载于 %{dateTime}"
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软件包%{noPackagesLinkEnd}。"
@@ -27989,17 +28488,17 @@ msgstr "è¦ä¿ç•™çš„é‡å¤ assets æ•°é‡"
msgid "PackageRegistry|Package Registry"
msgstr "软件包注册表"
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr "软件包 asset 删除æˆåŠŸ"
+
msgid "PackageRegistry|Package assets deleted successfully"
msgstr "软件包 assets 删除æˆåŠŸ"
msgid "PackageRegistry|Package deleted successfully"
msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…"
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…文件"
-
msgid "PackageRegistry|Package formats"
-msgstr ""
+msgstr "软件包格å¼"
msgid "PackageRegistry|Package has %{updatesCount} archived update"
msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
@@ -28008,6 +28507,9 @@ 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}å‘布到库"
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr "永久删除 assets"
@@ -28059,12 +28561,12 @@ msgstr "显示 PyPi 命令"
msgid "PackageRegistry|Show Yarn commands"
msgstr "显示 Yarn 命令"
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
+msgstr "删除软件包 asset 时出错。"
+
msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr "删除软件包 assets 时出错。"
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr "删除包文件时出错。"
-
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr "删除软件包时出错。"
@@ -28119,8 +28621,8 @@ msgstr "当一个åŒååŒç‰ˆæœ¬çš„包被上传到仓库时,更多的 assets è
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr "您将è¦åˆ é™¤ %{filename}。这是一ç§ç ´å性æ“作,å¯èƒ½ä¼šä½¿æ‚¨çš„包无法使用。您确定å—?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "您将è¦åˆ é™¤%{name},此æ“作ä¸å¯é€†ï¼Œç¡®å®šç»§ç»­å—?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28142,7 +28644,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr "ç”±%{author}å‘布"
msgid "Packages and registries"
-msgstr ""
+msgstr "软件包与镜åƒåº“"
msgid "Page not found"
msgstr "找ä¸åˆ°é¡µé¢"
@@ -28333,9 +28835,6 @@ msgstr "使用速率é™åˆ¶ä¿æŠ¤çš„路径"
msgid "Pause"
msgstr "æš‚åœ"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr "æš‚åœç´¢å¼•å¹¶å°† Elasticsearch å‡çº§åˆ°å—支æŒçš„版本。"
-
msgid "Pause time (ms)"
msgstr "æš‚åœæ—¶é—´ï¼ˆæ¯«ç§’)"
@@ -28469,7 +28968,7 @@ msgid "Period of inactivity (days)"
msgstr "ä¸æ´»åŠ¨æ—¶é•¿ï¼ˆå¤©æ•°ï¼‰"
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "åœç”¨å‰çš„ä¸æ´»åŠ¨æ—¶é—´ã€‚"
msgid "Permalink"
msgstr "永久链接"
@@ -28738,9 +29237,21 @@ msgstr "å·²å¯ç”¨"
msgid "PipelineSchedules|All"
msgstr "所有"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "未å¯ç”¨"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "下次è¿è¡Œæ—¶é—´"
@@ -28750,15 +29261,27 @@ msgstr "æ— "
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr "åªæœ‰æµæ°´çº¿è®¡åˆ’的所有者å¯ä»¥å¯¹å…¶è¿›è¡Œæ›´æ”¹ã€‚你想è¦èŽ·å¾—计划的所有æƒå—?"
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "为此æµæ°´çº¿æ供简短æè¿°"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "å–得所有æƒ"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "目标"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "å˜é‡"
@@ -28873,6 +29396,12 @@ msgstr "“%{project_name}â€çš„æµæ°´çº¿è®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr "使用 GitLab CI 实现 \"Hello world\""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr "(已排队 %{queued_duration})"
+
msgid "Pipelines|1. Set up a runner"
msgstr "1. 设置一个 runner"
@@ -29186,7 +29715,7 @@ msgid "Pipeline|Manual"
msgstr "手动"
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚æµæ°´çº¿"
msgid "Pipeline|Merge train pipeline"
msgstr "åˆå¹¶é˜Ÿåˆ—æµæ°´çº¿"
@@ -29390,7 +29919,7 @@ msgid "Please check your email (%{email}) to verify that you own this address an
msgstr "请检查您的电å­é‚®ä»¶(%{email})以确认您拥有此电å­é‚®ç®±å¹¶è§£é”CI/CD的强大功能。还没收到邮件? %{resend_link}。或是电å­é‚®ä»¶åœ°å€é”™è¯¯ï¼Ÿ%{update_link}。"
msgid "Please click the link in the confirmation email before continuing. It was sent to %{html_tag_strong_start}%{email}%{html_tag_strong_end}."
-msgstr ""
+msgstr "请在继续å‰ç‚¹å‡»ç”µå­é‚®ä»¶ä¸­çš„确认链接。它被å‘é€åˆ°äº†%{html_tag_strong_start}%{email}%{html_tag_strong_end}"
msgid "Please complete your profile with email address"
msgstr "请在您的个人资料中填写电å­é‚®ä»¶åœ°å€"
@@ -29554,6 +30083,9 @@ msgstr "请输入%{phrase_code}以继续或关闭此对è¯æ¡†ä»¥å–消。"
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "请使用此表å•å‘管ç†å‘˜æŠ¥å‘Šåˆ›å»ºåžƒåœ¾è®®é¢˜ã€è¯„论或行为ä¸å½“的用户。"
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr "请ç¨ç­‰ç‰‡åˆ»ï¼Œæˆ‘们正在加载此行的文件历å²è®°å½•ã€‚"
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "请ç¨ç­‰ç‰‡åˆ»ï¼Œæ­¤é¡µé¢åœ¨å°±ç»ªæ—¶ä¼šè‡ªåŠ¨åˆ·æ–°ã€‚"
@@ -29563,6 +30095,9 @@ msgstr "连接代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "导入代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当å‰çŠ¶æ€ã€‚"
+msgid "Please wait while we prepare for verification."
+msgstr "请ç¨ç­‰ï¼Œæˆ‘们正在准备验è¯ã€‚"
+
msgid "Pods in use"
msgstr "正在使用的Pod"
@@ -29606,7 +30141,7 @@ msgid "Postman collection"
msgstr "Postman 集åˆ"
msgid "Postman collection file URL"
-msgstr ""
+msgstr "Postman 集åˆæ–‡ä»¶ URL"
msgid "Postman collection file path or URL"
msgstr "Postman 集åˆæ–‡ä»¶è·¯å¾„或 URL"
@@ -29623,6 +30158,9 @@ msgstr "å好设置"
msgid "Preferences saved."
msgstr "å好设置已ä¿å­˜ã€‚"
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "个性化"
@@ -29630,7 +30168,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr "为应用程åºé€‰æ‹©å›ºå®šæ–¹å¼(最大值1280px)或æµåŠ¨æ–¹å¼(%{percentage})布局。"
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "选择您希望在仪表盘上默认看到的内容。"
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "选择项目概览页é¢ä¸­æ‚¨æƒ³çœ‹åˆ°çš„内容。"
@@ -29657,7 +30195,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr "自定义差异中删除行和添加行的颜色。"
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "默认仪表盘"
msgid "Preferences|Diff colors"
msgstr "差异颜色"
@@ -29734,6 +30272,9 @@ msgstr "时间å好"
msgid "Preferences|Use relative times"
msgstr "使用相对时间"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "当您在æ述或评论框中键入时,在键入以下字符之一åŽï¼Œé€‰å®šçš„文本将被相应的字符包围:%{supported_characters}。"
@@ -29825,7 +30366,7 @@ msgid "Private - Project access must be granted explicitly to each user. If this
msgstr "ç§æœ‰ - 项目访问必须明确授予æ¯ä¸ªç”¨æˆ·ã€‚ 如果此项目是在一个群组中,群组æˆå‘˜å°†ä¼šèŽ·å¾—访问æƒé™ã€‚"
msgid "Private - The group and its projects can only be viewed by members."
-msgstr "ç§äºº - 群组åŠå…¶é¡¹ç›®åªèƒ½ç”±æˆå‘˜æŸ¥çœ‹ã€‚"
+msgstr "ç§æœ‰ - 群组åŠå…¶é¡¹ç›®åªèƒ½ç”±æˆå‘˜æŸ¥çœ‹ã€‚"
msgid "Private group(s)"
msgstr "ç§æœ‰ç¾¤ç»„"
@@ -29947,15 +30488,9 @@ msgstr "活动"
msgid "Profiles|Add key"
msgstr "添加密钥"
-msgid "Profiles|Add status emoji"
-msgstr "在状æ€ä¸­æ·»åŠ è¡¨æƒ…符å·"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "更新您的用户å时出错,请é‡è¯•ã€‚"
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr "在您的å字和头åƒæ—边显示一个指示器。"
-
msgid "Profiles|Avatar cropper"
msgstr "头åƒè£å‰ª"
@@ -29968,9 +30503,6 @@ msgstr "以 %{ssh_key_algorithms} 开头。"
msgid "Profiles|Bio"
msgstr "自我介ç»"
-msgid "Profiles|Busy"
-msgstr "忙碌中"
-
msgid "Profiles|Change username"
msgstr "更改用户å"
@@ -29986,9 +30518,6 @@ msgstr "选择在您的公开个人资料上显示ç§æœ‰é¡¹ç›®çš„贡献,无需
msgid "Profiles|City, country"
msgstr "城市,国家"
-msgid "Profiles|Clear status"
-msgstr "清除状æ€"
-
msgid "Profiles|Commit email"
msgstr "æ交邮件"
@@ -30001,6 +30530,9 @@ msgstr "选择用于登录的æœåŠ¡ã€‚"
msgid "Profiles|Connected Accounts"
msgstr "å…³è”账户"
+msgid "Profiles|Created%{time_ago}"
+msgstr "创建于%{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "当å‰è·¯å¾„: %{path}"
@@ -30122,7 +30654,7 @@ msgid "Profiles|Notification email"
msgstr "通知邮件"
msgid "Profiles|Optional but recommended. If set, key becomes invalid on the specified date."
-msgstr ""
+msgstr "å¯é€‰ï¼Œä½†æŽ¨è。如果设置,密钥在指定日期无效。"
msgid "Profiles|Organization"
msgstr "组织"
@@ -30238,9 +30770,6 @@ msgstr "姓å中使用表情符å·è™½ç„¶æœ‰è¶£ï¼Œä½†è¯·è½¬åˆ°çŠ¶æ€ä¿¡æ¯é‡Œä½¿
msgid "Profiles|Website url"
msgstr "网站 URL"
-msgid "Profiles|What's your status?"
-msgstr "您当å‰çš„状æ€ï¼Ÿ"
-
msgid "Profiles|Who you represent or work for."
msgstr "您代表è°æˆ–为è°å·¥ä½œã€‚"
@@ -30286,9 +30815,6 @@ msgstr "您的姓å是根æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„,ä»
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "您的姓å是根æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„,因此您认识的人å¯ä»¥è¯†åˆ«æ‚¨ã€‚"
-msgid "Profiles|Your status"
-msgstr "您当å‰çš„状æ€ï¼Ÿ"
-
msgid "Profiles|https://website.com"
msgstr "https://website.com"
@@ -30778,6 +31304,9 @@ msgstr "选择åˆå¹¶æ–¹æ³•ã€åˆå¹¶é€‰é¡¹ï¼Œåˆå¹¶æ£€æŸ¥ä»¥åŠåˆå¹¶å»ºè®®"
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr "选择您的åˆå¹¶æ–¹æ³•ã€é€‰é¡¹ã€æ£€æŸ¥å’ŒåŽ‹ç¼©é€‰é¡¹ã€‚"
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr "å°† git 标签与å‘布说明ã€å‘布 evidence å’Œ assets 相结åˆæ¥åˆ›å»ºå‘布。"
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "é…置您的项目资æºå¹¶ç›‘控它们的è¿è¡ŒçŠ¶å†µã€‚"
@@ -30808,6 +31337,9 @@ msgstr "å¯ç”¨åˆå¹¶é˜Ÿåˆ—"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr "å¯ç”¨åˆå¹¶ç»“æžœæµæ°´çº¿"
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "å¯ç”¨æŽ¨è的审核者"
+
msgid "ProjectSettings|Encourage"
msgstr "建议"
@@ -30827,7 +31359,7 @@ msgid "ProjectSettings|Every project can have its own space to store its package
msgstr "æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å®ƒçš„软件包。注æ„:当一个项目是公开时,软件包库总是å¯è§çš„。"
msgid "ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access."
-msgstr ""
+msgstr "æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥é€šè¿‡ CI/CD 或 API 调用进行环境部署。éžé¡¹ç›®æˆå‘˜å¯ä»¥åªè¯»è®¿é—®ã€‚"
msgid "ProjectSettings|Everyone"
msgstr "所有人"
@@ -30884,7 +31416,7 @@ msgid "ProjectSettings|Issues"
msgstr "议题"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
-msgstr "此仓库中的 LFS 对象å¯ä¾›æ´¾ç”Ÿã€‚ %{linkStart}我如何移除它们?%{linkEnd}"
+msgstr "此仓库中的 LFS 对象å¯ç”¨äºŽæ´¾ç”Ÿä»“库。%{linkStart}我如何移除它们?%{linkEnd}"
msgid "ProjectSettings|Leave empty to use default template."
msgstr "留空使用默认模æ¿ã€‚"
@@ -30931,12 +31463,18 @@ msgstr "åˆå¹¶å»ºè®®"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr "åªæœ‰å½“æºåˆ†æ”¯ä¸Žå…¶ç›®æ ‡æ˜¯æœ€æ–°çš„时候,æ‰å…许åˆå¹¶ã€‚"
+msgid "ProjectSettings|Monitor"
+msgstr "监控"
+
msgid "ProjectSettings|No merge commits are created."
msgstr "没有创建åˆå¹¶æ交。"
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr "注æ„:当项目是公共的并且容器镜åƒåº“设置为“%{access_level_description}â€æ—¶ï¼Œå®¹å™¨é•œåƒåº“始终å¯è§"
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç­¾ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ä»“库。"
@@ -30973,6 +31511,9 @@ msgstr "项目å¯è§æ€§"
msgid "ProjectSettings|Public"
msgstr "公开"
+msgid "ProjectSettings|Releases"
+msgstr "å‘布"
+
msgid "ProjectSettings|Repository"
msgstr "仓库"
@@ -30992,7 +31533,7 @@ msgid "ProjectSettings|Requirements management system."
msgstr "需求管ç†ç³»ç»Ÿã€‚"
msgid "ProjectSettings|Roll out new features without redeploying with feature flags."
-msgstr ""
+msgstr "推出新功能而无需使用功能标志é‡æ–°éƒ¨ç½²ã€‚"
msgid "ProjectSettings|Search for topic"
msgstr "æœç´¢ä¸»é¢˜"
@@ -31126,8 +31667,8 @@ msgstr "当出现åˆå¹¶å†²çªæ—¶ï¼Œç”¨æˆ·å¯ä»¥é€‰æ‹©å˜åŸºï¼ˆrebase)。"
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr "使用GitLab Pages,您å¯ä»¥åœ¨GitLab上托管é™æ€ç½‘站。"
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr "使用 Pages,您å¯ä»¥æ‰˜ç®¡æ‚¨çš„é™æ€ç½‘站。Pages 使用缓存机制æ¥æ高效率。在缓存无效之å‰ï¼Œæ‚¨çš„更改å¯èƒ½ä¸ä¼šç”Ÿæ•ˆï¼Œé€šå¸¸éœ€è¦ä¸åˆ°ä¸€åˆ†é’Ÿã€‚"
msgid "ProjectTemplates|.NET Core"
msgstr ".NET Core"
@@ -31216,6 +31757,9 @@ msgstr "Tencent Serverless 框架/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr "获å–传输ä½ç½®æ—¶å‡ºé”™ï¼Œè¯·åˆ·æ–°é¡µé¢å¹¶é‡è¯•ã€‚"
+
msgid "ProjectView|Activity"
msgstr "动æ€"
@@ -31738,6 +32282,9 @@ msgstr "å…许推é€"
msgid "ProtectedBranch|Allowed to push:"
msgstr "å…许推é€ï¼š"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr "在加载分支规则期间å‘生了æŸä¸ªé”™è¯¯ã€‚请å†æ¬¡å°è¯•ã€‚"
+
msgid "ProtectedBranch|Branch"
msgstr "分支"
@@ -31774,6 +32321,9 @@ msgstr "å—ä¿æŠ¤åˆ†æ”¯ (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "å—ä¿æŠ¤åˆ†æ”¯"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr "å—ä¿æŠ¤åˆ†æ”¯ã€åˆå¹¶è¯·æ±‚批准以åŠçŠ¶æ€æ£€æŸ¥å°†åœ¨é…ç½®åŽæ˜¾ç¤ºã€‚"
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr "æ‹’ç»ä»£ç æŽ¨é€æ›´æ”¹ CODEOWNERS 文件中列出的文件。"
@@ -31798,6 +32348,9 @@ msgstr "å–消ä¿æŠ¤åˆ†æ”¯"
msgid "ProtectedBranch|What are protected branches?"
msgstr "什么是å—ä¿æŠ¤çš„分支?"
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr "您åªèƒ½æ·»åŠ å…±äº«æ­¤é¡¹ç›®çš„群组。%{learn_more_link}"
+
msgid "ProtectedBranch|default"
msgstr "默认"
@@ -31805,7 +32358,7 @@ msgid "ProtectedEnvironment|%{environment_name} will be writable for developers.
msgstr "%{environment_name} 将对开å‘人员å¯å†™ã€‚确定继续å—?"
msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
-msgstr ""
+msgstr "指定了以下部署级别的所有环境å‡å—父组ä¿æŠ¤ã€‚%{link_start}了解更多%{link_end}。"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…许部署"
@@ -31823,7 +32376,7 @@ msgid "ProtectedEnvironment|Failed to load details for this group."
msgstr "无法加载此群组的详细信æ¯ã€‚"
msgid "ProtectedEnvironment|No environments in this project are protected."
-msgstr ""
+msgstr "此项目中没有环境å—到ä¿æŠ¤ã€‚"
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
msgstr "åªæœ‰æŒ‡å®šçš„群组æ‰èƒ½åœ¨å—ä¿æŠ¤çš„环境中执行部署。"
@@ -31954,6 +32507,9 @@ msgstr "将此议题å‘布到相关的状æ€é¡µé¢ã€‚"
msgid "Pull"
msgstr "拉å–"
+msgid "Pull mirroring updated %{time}."
+msgstr "拉å–é•œåƒæ›´æ–°äºŽ %{time}。"
+
msgid "Pull requests from fork are not supported"
msgstr "ä¸æ”¯æŒæ¥è‡ªæ´¾ç”Ÿçš„拉å–请求"
@@ -32023,18 +32579,48 @@ msgstr "所有æ交消æ¯å¿…须匹é…这个 %{wiki_syntax_link_start}正则表è
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr "所有æ交的文件å都ä¸èƒ½åŒ¹é…这个 %{wiki_syntax_link_start}正则表达å¼%{wiki_syntax_link_end}。如果为空,则å…许使用任何文件å。"
+msgid "PushRules|Branch name"
+msgstr "分支å称"
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr "检查æ交者是å¦æ˜¯ GitLab 用户"
+
+msgid "PushRules|Commit author's email"
+msgstr "æ交作者的电å­é‚®ä»¶"
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr "æ交消æ¯ä¸èƒ½åŒ¹é…这个 %{wiki_syntax_link_start}正则表达å¼%{wiki_syntax_link_end}。如果为空,则ä¸ä¼šæ ¹æ®ä»»ä½•è¡¨è¾¾å¼æ‹’ç»æ交消æ¯ã€‚"
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr "ä¸å…许用户使用 %{code_block_start}git push%{code_block_end}时删除Git标签。"
+msgid "PushRules|Maximum file size (MB)"
+msgstr "最大文件大å°ï¼ˆMB)"
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr "é˜²æ­¢æŽ¨é€ secret 文件"
+
+msgid "PushRules|Prohibited file names"
+msgstr "ç¦æ­¢çš„文件å"
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr "æ‹’ç»ä»»ä½•å¯èƒ½åŒ…å« secret 的文件。 %{secret_files_link_start}哪些 secret 文件会被拒ç»ï¼Ÿ%{secret_files_link_end}"
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr "æ交消æ¯ä¸­çš„æ‹’ç»è¡¨è¾¾å¼"
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr "æ‹’ç»ç­‰äºŽæˆ–大于此大å°çš„文件。如果设置为 0,则å…许任何大å°çš„文件。此规则ä¸é€‚用于 Git LFS 跟踪的文件。"
+msgid "PushRules|Reject unsigned commits"
+msgstr "æ‹’ç»æœªç­¾åæ交"
+
+msgid "PushRules|Require expression in commit messages"
+msgstr "æ交消æ¯ä¸­çš„è¦æ±‚表达å¼"
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr "é™åˆ¶å¯¹çŽ°æœ‰ GitLab 用户的æ交。"
@@ -32185,9 +32771,6 @@ msgstr "进一步了解"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr "在%{link_to_promo}上阅读更多关于 GitLab çš„ä¿¡æ¯ã€‚"
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr "于%{help_link_open}此处%{help_link_close}了解有关项目æƒé™çš„更多信æ¯"
-
msgid "Read more about related epics"
msgstr "阅读更多关于相关å²è¯—çš„ä¿¡æ¯"
@@ -32342,9 +32925,6 @@ msgstr "注册通用åŒé‡è®¤è¯è®¾å¤‡(U2F)"
msgid "Register WebAuthn Device"
msgstr "注册WebAuthn设备"
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr "注册尽å¯èƒ½å¤šçš„runner。您å¯ä»¥ä»¥å•ç‹¬çš„用户,或者在ä¸åŒçš„æœåŠ¡å™¨æˆ–者本地计算机上注册runner。runnerå¯ä»¥æ˜¯ï¼š"
-
msgid "Register device"
msgstr "注册设备"
@@ -33220,6 +33800,9 @@ msgstr "仓库镜åƒ"
msgid "Repository mirroring configuration"
msgstr "仓库镜åƒé…ç½®"
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "仓库必须包å«è‡³å°‘1个文件。"
@@ -33263,7 +33846,7 @@ msgid "Request parameter %{param} is missing."
msgstr "请求å‚æ•°%{param}缺失。"
msgid "Request review from"
-msgstr "请求审核æ¥è‡ª"
+msgstr "请求审核者"
msgid "Request time"
msgstr "请求时间"
@@ -33602,6 +34185,9 @@ msgstr "撤销身份模拟令牌 %{token_name}ï¼"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "撤销个人访问令牌 %{personal_access_token_name}ï¼"
+msgid "Rich text"
+msgstr "富文本"
+
msgid "RightSidebar|Copy email address"
msgstr "å¤åˆ¶ç”µå­é‚®ä»¶åœ°å€"
@@ -33623,6 +34209,9 @@ msgstr "角色"
msgid "Rollback"
msgstr "回滚"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr "Ruby"
@@ -33714,7 +34303,7 @@ msgid "Runners|Add notes, like who owns the runner or what it should be used for
msgstr "添加备注,比如è°æ‹¥æœ‰ runner,或者它应该用于什么目的。"
msgid "Runners|Add your feedback in the issue"
-msgstr ""
+msgstr "在议题中添加您的å馈"
msgid "Runners|All"
msgstr "全部"
@@ -33732,10 +34321,10 @@ msgid "Runners|An error has occurred fetching instructions"
msgstr "获å–指令时å‘生错误"
msgid "Runners|An upgrade is available for this runner"
-msgstr ""
+msgstr "æ­¤ runner 有å¯ç”¨çš„å‡çº§"
msgid "Runners|An upgrade is recommended for this runner"
-msgstr ""
+msgstr "æ­¤ runner 有推èçš„å‡çº§"
msgid "Runners|Architecture"
msgstr "架构"
@@ -33786,7 +34375,7 @@ msgid "Runners|Copy registration token"
msgstr "å¤åˆ¶æ³¨å†Œä»¤ç‰Œ"
msgid "Runners|Created %{timeAgo}"
-msgstr ""
+msgstr "创建于 %{timeAgo}"
msgid "Runners|Delete %d runner"
msgid_plural "Runners|Delete %d runners"
@@ -33835,7 +34424,7 @@ msgid "Runners|Executor"
msgstr "执行器"
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "过滤项目"
msgid "Runners|Get started with runners"
msgstr "Runner 入门"
@@ -33843,6 +34432,9 @@ msgstr "Runner 入门"
msgid "Runners|Group"
msgstr "群组"
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr "我们如何å‡çº§ GitLab runner?"
@@ -33862,7 +34454,7 @@ msgid "Runners|Last contact"
msgstr "最åŽè”ç³»"
msgid "Runners|Last contact: %{timeAgo}"
-msgstr ""
+msgstr "最åŽè”系:%{timeAgo}"
msgid "Runners|Locked to this project"
msgstr "é”定到此项目"
@@ -33876,9 +34468,6 @@ msgstr "最大作业超时"
msgid "Runners|Members of the %{type} can register runners"
msgstr "%{type}çš„æˆå‘˜å¯ä»¥æ³¨å†ŒRunner"
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr "ä¸èƒ½åˆ é™¤å¤šé¡¹ç›® runners"
-
msgid "Runners|Name"
msgstr "å称"
@@ -33888,6 +34477,9 @@ msgstr "未连接过"
msgid "Runners|Never contacted:"
msgstr "从未连接过:"
+msgid "Runners|Never expires"
+msgstr "æ°¸ä¸è¿‡æœŸ"
+
msgid "Runners|New group runners view"
msgstr "新建群组 runner 视图"
@@ -33955,6 +34547,9 @@ msgstr "注册一个runner"
msgid "Runners|Register an instance runner"
msgstr "注册一个实例runner"
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "注册令牌"
@@ -33982,8 +34577,11 @@ msgstr "Runner %{name} 已删除"
msgid "Runners|Runner assigned to project."
msgstr "分é…给项目的runner"
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr "Runner 无法删除,请è”系您的管ç†å‘˜ã€‚"
+msgid "Runners|Runner authentication token expiration"
+msgstr "Runner 身份验è¯ä»¤ç‰Œè¿‡æœŸ"
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
+msgstr "Runner 身份验è¯ä»¤ç‰Œå°†æ ¹æ®è®¾ç½®çš„时间间隔过期。一旦过期,它们将自动轮æ¢ã€‚"
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
msgstr "在最近 %{elapsedTime} 内,Runner 连接过 GitLab"
@@ -34033,6 +34631,9 @@ msgstr "å–消分é…到项目的runner。"
msgid "Runners|Runners"
msgstr "Runner"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "Runners 是è¿è¡Œ CI/CD 作业的代ç†ã€‚按照 %{linkStart}安装和注册指å—%{linkEnd} æ¥è®¾ç½®ä¸€ä¸ª runner。"
@@ -34045,6 +34646,9 @@ msgstr "选择è¦åˆ†é…给此 runner 的项目"
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr "在此选择您的首选选项。在下一步中,您å¯ä»¥åœ¨ AWS CloudFormation 控制å°ä¸­é€‰æ‹©æ‚¨çš„ runner 能力。"
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr "显示runner安装和注册说明"
@@ -34075,6 +34679,9 @@ msgstr "åœæ­¢ Runner 接收新的作业。"
msgid "Runners|Tags"
msgstr "标签"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr "带我去那里ï¼"
@@ -34112,6 +34719,9 @@ msgstr "è¦åœ¨å®¹å™¨ä¸­å®‰è£…Runner,请éµå¾ª GitLab 文档中æ述的说明ã
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr "è¦æ³¨å†Œå®ƒä»¬ï¼Œè¯·è½¬åˆ°%{link_start}群组的 Runners 页é¢%{link_end}。"
+msgid "Runners|Token expiry"
+msgstr "令牌过期"
+
msgid "Runners|Up to date"
msgstr "最新"
@@ -34152,10 +34762,10 @@ msgid "Runners|View installation instructions"
msgstr "查看安装说明"
msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
-msgstr ""
+msgstr "我们希望您能够从此页é¢è½»æ¾æœ‰æ•ˆåœ°ç®¡ç† runners,我们正在åšå‡ºæ”¹å˜ä»¥å®žçŽ°ç›®æ ‡ã€‚就我们的表现给我们å馈ï¼"
msgid "Runners|We've made some changes and want your feedback"
-msgstr ""
+msgstr "我们åšäº†ä¸€äº›æ”¹å˜ï¼Œå¸Œæœ›å¾—到您的å馈"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
msgstr "Windows 2019 Shell,具有手动缩放和å¯é€‰è°ƒåº¦åŠŸèƒ½ã€‚ %{percentage} 点。"
@@ -34329,25 +34939,22 @@ msgid "Saving project."
msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
-msgstr ""
-
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{rules} 用于 %{branches} 分支"
+msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{rules} æ“作用于 %{scopes} %{branches}"
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
-msgstr ""
+msgstr "%{period}%{days} 在 %{time}"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
-msgstr ""
+msgstr "%{thenLabelStart}然åŽ%{thenLabelEnd} éœ€è¦ %{scan} 扫ææ‰èƒ½è¿è¡Œ"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
-msgstr ""
+msgstr "%{thenLabelStart}然åŽ%{thenLabelEnd} éœ€è¦ %{scan} 扫ææ‰èƒ½ä½¿ç”¨ç«™ç‚¹é…置文件 %{siteProfile} 和扫æ器é…置文件 %{scannerProfile} æ¥è¿è¡Œ"
msgid "ScanExecutionPolicy|A pipeline is run"
msgstr "æµæ°´çº¿è¿è¡Œä¸­"
msgid "ScanExecutionPolicy|Scanner profile"
-msgstr ""
+msgstr "扫æ器é…置文件"
msgid "ScanExecutionPolicy|Schedule"
msgstr "计划"
@@ -34359,13 +34966,13 @@ msgid "ScanExecutionPolicy|Select branches"
msgstr "选择分支"
msgid "ScanExecutionPolicy|Select scanner profile"
-msgstr ""
+msgstr "选择扫æ器é…置文件"
msgid "ScanExecutionPolicy|Select site profile"
-msgstr ""
+msgstr "选择站点é…置文件"
msgid "ScanExecutionPolicy|Site profile"
-msgstr ""
+msgstr "站点é…置文件"
msgid "ScanExecutionPolicy|branch"
msgstr "分支"
@@ -34481,6 +35088,9 @@ msgstr "æœç´¢æŒ‡æ´¾äºº"
msgid "Search authors"
msgstr "æœç´¢ä½œè€…"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -34568,6 +35178,9 @@ msgstr "æœç´¢é¡¹ç›®"
msgid "Search projects..."
msgstr "æœç´¢é¡¹ç›®..."
+msgid "Search protected branches"
+msgstr "æœç´¢å—ä¿æŠ¤çš„分支"
+
msgid "Search rate limits"
msgstr "æœç´¢é€ŸçŽ‡é™åˆ¶"
@@ -34861,14 +35474,14 @@ msgstr "管ç†é…置文件"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr "管ç†ä¾› DAST 扫æ使用的é…置文件。"
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr "更多扫æ类型,包括容器扫æ,DAST,ä¾èµ–扫æ,模糊和许å¯è¯åˆè§„。"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "未å¯ç”¨"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
-msgstr "一旦您å¯ç”¨äº†é»˜è®¤åˆ†æ”¯æ‰«æ,éšåŽåˆ›å»ºçš„任何功能分支将包括扫æ。"
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
+msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
msgstr "%{linkStart}Auto DevOps%{linkEnd}快速å¯ç”¨æ‰€æœ‰æŒç»­æµ‹è¯•å’Œåˆè§„性工具"
@@ -34924,9 +35537,6 @@ msgstr "%{scanners}"
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr "针对 %{branches} 的开放åˆå¹¶è¯·æ±‚中的 %{scanners} %{severities}。"
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} 更多"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ",和 %{count} 个更多"
@@ -34940,7 +35550,7 @@ msgid "SecurityOrchestration|Actions"
msgstr "行动"
msgid "SecurityOrchestration|Add action"
-msgstr ""
+msgstr "添加æ“作"
msgid "SecurityOrchestration|Add rule"
msgstr "添加规则"
@@ -35045,7 +35655,7 @@ msgid "SecurityOrchestration|Latest scan run against %{agent}"
msgstr "针对 %{agent} è¿è¡Œçš„最新扫æ"
msgid "SecurityOrchestration|New policy"
-msgstr "æ–°ç­–ç•¥"
+msgstr "新建策略"
msgid "SecurityOrchestration|New scan execution policy"
msgstr "新建扫æ执行策略"
@@ -35198,7 +35808,7 @@ msgid "SecurityOrchestration|This %{namespaceType} does not contain any security
msgstr "æ­¤ %{namespaceType} ä¸åŒ…å«ä»»ä½•å®‰å…¨ç­–略。"
msgid "SecurityOrchestration|This %{namespaceType} is not linked to a security policy project"
-msgstr ""
+msgstr "æ­¤ %{namespaceType} 没有关è”到安全策略项目"
msgid "SecurityOrchestration|This group"
msgstr "此群组"
@@ -35329,6 +35939,9 @@ msgstr "创建 Jira 议题"
msgid "SecurityReports|Create issue"
msgstr "创建议题"
+msgid "SecurityReports|Detection"
+msgstr "检测"
+
msgid "SecurityReports|Development vulnerabilities"
msgstr "å¼€å‘æ¼æ´ž"
@@ -35341,6 +35954,9 @@ msgstr "已忽略的'%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "已忽略'%{vulnerabilityName}'。请关闭éšè—忽略开关以查看。"
+msgid "SecurityReports|Does not have issue"
+msgstr "没有问题"
+
msgid "SecurityReports|Download %{artifactName}"
msgstr "下载 %{artifactName}"
@@ -35371,12 +35987,18 @@ msgstr "解æžå®‰å…¨æŠ¥å‘Šæ—¶å‡ºé”™"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr "无法获å–安全报告信æ¯ã€‚请é‡æ–°åŠ è½½é¡µé¢æˆ–ç¨åŽå†è¯•ã€‚"
+msgid "SecurityReports|Has issue"
+msgstr "有问题"
+
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
msgid "SecurityReports|Image"
msgstr "é•œåƒ"
+msgid "SecurityReports|Issue"
+msgstr "问题"
+
msgid "SecurityReports|Issue Created"
msgstr "已创建议题"
@@ -35494,6 +36116,9 @@ msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
msgid "SecurityReports|Status"
msgstr "状æ€"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr "æ交æ¼æ´ž"
@@ -35617,9 +36242,6 @@ msgstr "选择下载格å¼"
msgid "Select Git revision"
msgstr "选择Git版本"
-msgid "Select Page"
-msgstr "选择页é¢"
-
msgid "Select Profile"
msgstr "选择个人资料"
@@ -35665,9 +36287,6 @@ msgstr "选择模æ¿ä»“库"
msgid "Select a template type"
msgstr "选择模æ¿ç±»åž‹"
-msgid "Select a time zone"
-msgstr "选择时区"
-
msgid "Select a timezone"
msgstr "选择时区"
@@ -35689,9 +36308,15 @@ msgstr "选择指派人"
msgid "Select branch"
msgstr "选择分支"
+msgid "Select branch or create wildcard"
+msgstr "选择分支或创建通é…符"
+
msgid "Select branches"
msgstr "选择分支"
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "设置截止日期"
@@ -35737,6 +36362,9 @@ msgstr "选择è¦åˆ›å»ºè®®é¢˜çš„项目"
msgid "Select projects"
msgstr "选择项目"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "选择审核者"
@@ -36049,6 +36677,9 @@ msgstr "设置目标分支"
msgid "Set target branch to %{branch_name}."
msgstr "设置目标分支为%{branch_name}。"
+msgid "Set the Draft status"
+msgstr "设置è‰ç¨¿çŠ¶æ€"
+
msgid "Set the Ready status"
msgstr "设置就绪状æ€"
@@ -36124,18 +36755,15 @@ msgstr "设置æƒé‡"
msgid "Set weight to %{weight}."
msgstr "å°†æƒé‡è®¾ç½®ä¸º%{weight}。"
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "您的å字和头åƒæ—边显示标识。"
-
-msgid "SetStatusModal|Busy"
-msgstr "忙碌"
-
msgid "SetStatusModal|Clear status"
msgstr "清除状æ€"
msgid "SetStatusModal|Clear status after"
msgstr "清除状æ€"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "显示您正忙或无法å“应"
+
msgid "SetStatusModal|Edit status"
msgstr "编辑状æ€"
@@ -36148,6 +36776,9 @@ msgstr "设置一个状æ€"
msgid "SetStatusModal|Set status"
msgstr "设置状æ€"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "设置自己为忙碌中"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "对ä¸èµ·ï¼Œæˆ‘们无法设置您的状æ€ã€‚请ç¨åŽå†è¯•ã€‚"
@@ -36583,10 +37214,10 @@ msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the GitLab%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "点击 %{button_text} 或通过第三方注册,å³è¡¨ç¤ºæ‚¨æŽ¥å—%{link_start}使用æ¡æ¬¾å¹¶æŽ¥å—éšç§æ”¿ç­–å’Œ Cookie 政策%{link_end}"
msgid "SignUp|By clicking %{button_text} or registering through a third party you accept the%{link_start} Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}"
-msgstr ""
+msgstr "点击 %{button_text} 或通过第三方注册,å³è¡¨ç¤ºæ‚¨æŽ¥å—%{link_start}使用æ¡æ¬¾å¹¶æŽ¥å—éšç§æ”¿ç­–å’Œ Cookie 政策%{link_end}"
msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
msgstr "通过点击 %{button_text},我åŒæ„æˆ‘å·²é˜…è¯»å¹¶æŽ¥å— %{link_start}使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{link_end}"
@@ -36595,7 +37226,7 @@ msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted
msgstr "点击 %{button_text},我åŒæ„æˆ‘å·²é˜…è¯»å¹¶æŽ¥å— GitLab %{link_start}使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{link_end}"
msgid "SignUp|By signing in you accept the %{link_start}Terms of Use and acknowledge the Privacy Policy and Cookie Policy%{link_end}."
-msgstr ""
+msgstr "登录å³è¡¨ç¤ºæ‚¨æŽ¥å—%{link_start}使用æ¡æ¬¾å¹¶æŽ¥å—éšç§æ”¿ç­–å’Œ Cookie 政策%{link_end}。"
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr "å字太长(最多%{max_length}字符)。"
@@ -36747,6 +37378,39 @@ msgstr "填写最适åˆä½ çš„团队的文字。"
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr "通过在Slack中输入指令æ¥æ‰§è¡Œè¿™ä¸ªé¡¹ç›®ä¸­çš„常用æ“作。"
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr "%{asterisk}步骤 1 %{asterisk} 连接您的 GitLab å¸æˆ·å¼€å§‹æ“作。"
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr "%{asterisk}步骤 2 %{asterisk} 试试å§ï¼"
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr "%{emoji} 连接到 GitLab å¸æˆ· %{account}"
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr "%{emoji} 欢迎使用 GitLab for Slackï¼"
+
+msgid "Slack|Connect your GitLab account"
+msgstr "连接您的 GitLab å¸æˆ·"
+
+msgid "Slack|Create a new issue"
+msgstr "创建新议题"
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr "从 Slack 创建新议题:%{command}"
+
+msgid "Slack|Run a CI/CD job"
+msgstr "è¿è¡Œä¸€ä¸ª CI/CD 作业"
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr "查看å¯ç”¨å‘½ä»¤åˆ—表:%{command}"
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr "使用 ChatOps 简化您的部署。é…置完 %{startMarkup}CI/CD æµæ°´çº¿%{endMarkup}åŽï¼Œå°è¯•ï¼š%{command}"
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr "在 Slack 中工作时查看和控制 GitLab 内容。在您的èŠå¤©å®¢æˆ·ç«¯ä¸­é”®å…¥å‘½ä»¤ä½œä¸ºæ¶ˆæ¯å¯ä»¥æ¿€æ´»å®ƒã€‚%{startMarkup}了解更多%{endMarkup}。"
+
msgid "Slice multiplier"
msgstr "切片å€æ•°"
@@ -36813,6 +37477,9 @@ msgstr "代ç ç‰‡æ®µä¸èƒ½åŒ…å«ç©ºæ–‡ä»¶ã€‚ç¡®ä¿æ‰€æœ‰æ–‡ä»¶éƒ½åŒ…å«å†…容,
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr "实心"
@@ -36871,7 +37538,7 @@ msgid "Something went wrong when reordering designs. Please try again"
msgstr "é‡æ–°æŽ’åºè®¾è®¡æ—¶å‡ºäº†ç‚¹é—®é¢˜ã€‚请å†è¯•ä¸€æ¬¡"
msgid "Something went wrong while adding timeline event."
-msgstr ""
+msgstr "添加时间线事件时出错。"
msgid "Something went wrong while adding your award. Please try again."
msgstr "添加赞èµæ—¶å‡ºé”™ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
@@ -36964,7 +37631,7 @@ msgid "Something went wrong while promoting the issue to an epic. Please try aga
msgstr "将议题å‡çº§åˆ°å²è¯—时出错。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Something went wrong while promoting the note to timeline event."
-msgstr ""
+msgstr "将备注å‡çº§åˆ°æ—¶é—´çº¿äº‹ä»¶æ—¶å‡ºé”™ã€‚"
msgid "Something went wrong while reopening a requirement."
msgstr "é‡æ–°æ‰“开需求时出了错。"
@@ -37053,6 +37720,9 @@ msgstr "排åºæ–¹å‘:å‡åº"
msgid "Sort direction: Descending"
msgstr "排åºæ–¹å‘:é™åº"
+msgid "Sort or filter"
+msgstr "排åºæˆ–过滤"
+
msgid "SortOptions|Blocking"
msgstr "阻塞议题数"
@@ -37095,6 +37765,9 @@ msgstr "最åŽè”ç³»"
msgid "SortOptions|Last created"
msgstr "最近创建"
+msgid "SortOptions|Latest version"
+msgstr "最新版本"
+
msgid "SortOptions|Least popular"
msgstr "最ä¸å—欢迎"
@@ -37155,6 +37828,9 @@ msgstr "最早星标"
msgid "SortOptions|Oldest updated"
msgstr "最早更新"
+msgid "SortOptions|Oldest version"
+msgstr "最旧版本"
+
msgid "SortOptions|Popularity"
msgstr "人气"
@@ -37351,7 +38027,7 @@ msgid "Squash commits"
msgstr "压缩æ交"
msgid "Squash commits when merge request is accepted."
-msgstr "接å—åˆå¹¶è¯·æ±‚时压缩æ交"
+msgstr "接å—åˆå¹¶è¯·æ±‚时压缩æ交。"
msgid "Stack trace"
msgstr "堆栈跟踪"
@@ -37399,7 +38075,7 @@ msgid "Stars"
msgstr "星标"
msgid "Start Date"
-msgstr "开始时间"
+msgstr "开始日期"
msgid "Start Time"
msgstr "开始时间"
@@ -38055,8 +38731,8 @@ msgstr "绿å±"
msgid "SuggestedColors|Green-cyan"
msgstr "绿é’色"
-msgid "SuggestedColors|Lavendar"
-msgstr "è–°è¡£è‰ç´«"
+msgid "SuggestedColors|Lavender"
+msgstr "淡紫色"
msgid "SuggestedColors|Magenta-pink"
msgstr "å“红色-粉色"
@@ -38079,9 +38755,21 @@ msgstr "玫红色"
msgid "SuggestedColors|Titanium yellow"
msgstr "钛黄色"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "基于机器学习工具å‘审核者æ供建议。"
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "推è的审核者"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "建议出现在å³ä¾§è¾¹æ çš„审核者部分中"
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr "建议ä¸é€‚用,因为无法找到建议。"
+msgid "Suggestion(s)"
+msgstr "建议"
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr "建议ä¸é€‚用,因为无法找到一个或多个建议。"
@@ -38118,7 +38806,13 @@ msgstr "激活订阅"
msgid "SuperSonics|Activation code"
msgstr "激活ç "
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr "由于席ä½ä¸åŒ¹é…而无法激活"
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr "由于校正值ä¸åŒ¹é…而无法激活"
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr "添加您的订阅时å‘生错误。"
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr "计费用户"
msgid "SuperSonics|Buy subscription"
msgstr "购买订阅"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr "由于连接问题,无法激活实例。"
msgid "SuperSonics|Cloud licensing"
@@ -38242,26 +38936,38 @@ msgstr "您有一个未æ¥æ—¥æœŸçš„许å¯è¯"
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "您已ç»æ·»åŠ äº†æ¿€æ´»äºŽ %{date} 的许å¯è¯ã€‚详情请查看下é¢çš„订阅历å²è¡¨ã€‚"
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "您已æˆåŠŸæ·»åŠ åœ¨ %{date} 激活的许å¯è¯ã€‚有关更多详细信æ¯ï¼Œè¯·å‚阅下é¢çš„订阅历å²è¡¨ã€‚"
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr "您å¯èƒ½è¾“入了过期或ä¸åˆæ ¼çš„激活ç ã€‚è¦è¯·æ±‚新的激活ç ï¼Œ%{purchaseSubscriptionLinkStart}购买新订阅%{purchaseSubscriptionLinkEnd},或%{supportLinkStart}è”系技术支æŒ%{supportLinkEnd}获得进一步帮助。"
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "æ ¹æ®æ‚¨çš„åè®®æ¡æ¬¾ï¼Œæ‚¨å°†æŒ‰å­£åº¦æˆ–æ¯å¹´ä¸º %{trueUpLinkStart}超过许å¯è¯çš„用户%{trueUpLinkEnd}付费。"
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr "您的 %{subscriptionEntryName} 暂时无法显示。请刷新此页é¢ã€‚"
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "您当å‰çš„安装实例有 %{userCount} 个活动的 %{userCountUsers},这超出了您的新订阅座ä½æ•° %{licenseUserCount},超出数é‡ä¸º %{overageCount}。è¦æ¿€æ´»æ‚¨çš„新订阅, %{purchaseLinkStart}è´­ä¹°%{purchaseLinkEnd}é¢å¤– %{overageCount} 个 %{overageCountSeats},也å¯ä»¥%{deactivateLinkStart}åœç”¨%{deactivateLinkEnd}或%{blockLinkStart}ç¦ç”¨%{blockLinkEnd} %{overageCount} 个 %{overageCountUsers}。如需进一步帮助,请è”ç³»%{licenseSupportLinkStart}技术支æŒ%{licenseSupportLinkEnd}。"
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr "您的未æ¥æ—¥æœŸè®¸å¯è¯å·²æˆåŠŸæ·»åŠ "
msgid "SuperSonics|Your subscription"
msgstr "您的订阅"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr "无法找到您的订阅"
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr "您的订阅信æ¯å°†å¾ˆå¿«åŒæ­¥"
-msgid "SuperSonics|Your subscription is expired."
-msgstr "您的订阅已过期。"
+msgid "SuperSonics|Your subscription is expired"
+msgstr "您的订阅已过期"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr "您的订阅已æˆåŠŸæ¿€æ´»ã€‚您å¯ä»¥åœ¨ä¸‹é¢æŸ¥çœ‹è¯¦ç»†ä¿¡æ¯ã€‚"
@@ -39359,7 +40065,7 @@ msgid "The parent epic is confidential and can only contain confidential epics a
msgstr "父å²è¯—是ç§å¯†çš„,åªèƒ½åŒ…å«ç§å¯†å²è¯—和议题"
msgid "The parsed YAML is too big"
-msgstr ""
+msgstr "解æžçš„ YAML 文件过大"
msgid "The password for the Jenkins server."
msgstr "Jenkins æœåŠ¡å™¨çš„密ç ã€‚"
@@ -39442,6 +40148,9 @@ msgstr "åŒä¸€ä¸ªå…±äº«runnerå¯æ‰§è¡Œå¤šä¸ªé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨é…置了
msgid "The scan has been created."
msgstr "扫æ已创建。"
+msgid "The secret is only available when you first create the application."
+msgstr "该密钥仅在您首次创建应用程åºæ—¶å¯ç”¨ã€‚"
+
msgid "The snippet can be accessed without any authentication."
msgstr "无需任何身份验è¯å³å¯è®¿é—®è¯¥ä»£ç ç‰‡æ®µã€‚"
@@ -39458,10 +40167,10 @@ msgid "The source project of this merge request has been removed."
msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æºé¡¹ç›®å·²è¢«åˆ é™¤ã€‚"
msgid "The source topic and the target topic are identical."
-msgstr ""
+msgstr "æºä¸»é¢˜å’Œç›®æ ‡ä¸»é¢˜æ˜¯ç›¸åŒçš„。"
msgid "The source topic is not a topic."
-msgstr ""
+msgstr "æºä¸»é¢˜ä¸æ˜¯ä¸»é¢˜ã€‚"
msgid "The specified tab is invalid, please select another"
msgstr "指定标签页无效,请选择å¦ä¸€ä¸ª"
@@ -39476,7 +40185,7 @@ msgid "The tag name can't be changed for an existing release."
msgstr "对于现有å‘布,ä¸èƒ½æ›´æ”¹æ ‡ç­¾å称。"
msgid "The target topic is not a topic."
-msgstr ""
+msgstr "目标主题ä¸æ˜¯ä¸»é¢˜ã€‚"
msgid "The time period in seconds that the maximum requests per project limit applies to."
msgstr "æ¯ä¸ªé¡¹ç›®æœ€å¤§è¯·æ±‚所适用的时间间隔(秒)。"
@@ -39527,7 +40236,7 @@ msgid "There are currently no events."
msgstr "当å‰æ²¡æœ‰äº‹ä»¶ã€‚"
msgid "There are currently no mirrored repositories."
-msgstr ""
+msgstr "ç›®å‰æ²¡æœ‰é•œåƒçš„仓库。"
msgid "There are merge conflicts"
msgstr "存在åˆå¹¶å†²çª"
@@ -39649,9 +40358,6 @@ msgstr "没有å¯ç”¨çš„æ•°æ®ã€‚"
msgid "There is no data available. Please change your selection."
msgstr "没有å¯ç”¨æ•°æ®ã€‚请更改选择。"
-msgid "There is no seat left to activate the member"
-msgstr "没有剩余的席ä½å¯ä»¥å¯ç”¨æˆå‘˜"
-
msgid "There is no table data available."
msgstr "没有å¯ç”¨çš„表数æ®ã€‚"
@@ -39919,9 +40625,6 @@ msgstr "æ­¤Cronæ ¼å¼æ— æ•ˆ"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr "æ­¤ GitLab 实例尚未æ供任何共享 Runner,实例管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†ä¸­å¿ƒæ³¨å†Œå…±äº«Runner。"
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr "该GitLab实例的许å¯ä¸º%{insufficient_license}级别。拥有高级版或更高级别许å¯è¯çš„用户æ‰èƒ½ä½¿ç”¨Geo。"
-
msgid "This PDF is too large to display. Please download to view."
msgstr "此 PDF 太大而无法显示。请下载查看。"
@@ -39985,8 +40688,11 @@ msgstr "该阻塞为自我引用"
msgid "This board's scope is reduced"
msgstr "此看æ¿èŒƒå›´å·²ç¼©å°"
+msgid "This branch has diverged from upstream."
+msgstr "此分支已与上游分å‰ã€‚"
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
-msgstr ""
+msgstr "此更改将为%{strongOpen}所有%{strongClose} SaaS 客户删除%{strongOpen}所有%{strongClose}专业版和旗舰版功能,并使测试开始失败。"
msgid "This chart could not be displayed"
msgstr "无法显示此图表"
@@ -40013,7 +40719,7 @@ msgid "This commit was signed with a different user's verified signature."
msgstr "æ­¤æ交使用其他用户的已验è¯ç­¾å进行签å。"
msgid "This commit was signed with a verified signature, but the committer email is not associated with the GPG Key."
-msgstr ""
+msgstr "æ­¤æ交已使用ç»è¿‡éªŒè¯çš„ç­¾å进行签å,但æ交者电å­é‚®ä»¶æœªä¸Ž GPG 密钥关è”。"
msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
msgstr "æ­¤æ交使用%{strong_open}未ç»éªŒè¯çš„%{strong_close}ç­¾å进行签署。"
@@ -40030,6 +40736,9 @@ msgstr "此凭è¯å·²è¿‡æœŸ"
msgid "This deployment is not waiting for approvals."
msgstr "此部署ä¸ç­‰å¾…批准。"
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "此部署作业ä¸ä¼šè‡ªåŠ¨è¿è¡Œï¼Œå¿…须手动å¯åŠ¨ï¼Œä½†å®ƒæ¯”最新部署旧,因此无法è¿è¡Œã€‚"
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr "此部署作业ä¸ä¼šè‡ªåŠ¨è¿è¡Œï¼Œå¿…须手动å¯åŠ¨ï¼Œä½†æ‚¨æ— æƒè®¿é—®æ­¤ä½œä¸šçš„å—ä¿æŠ¤çŽ¯å¢ƒã€‚该作业åªèƒ½ç”±å…许部署到环境的项目æˆå‘˜å¯åŠ¨ã€‚"
@@ -40078,6 +40787,27 @@ msgstr "此环境的Canary Ingress最近有更新。请ç¨åŽå†è¯•ã€‚"
msgid "This epic already has the maximum number of child epics."
msgstr "æ­¤å²è¯—çš„å­å²è¯—数目已达最大值。"
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "æ­¤å²è¯—ä¸å­˜åœ¨æˆ–者您没有足够的æƒé™ã€‚"
@@ -40174,6 +40904,9 @@ msgstr "此数字为自许å¯è¯å¯åŠ¨ä»¥æ¥ç”¨æˆ·æ•°ç›®çš„最高值。"
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr "此数目为您æœåŠ¡å™¨å½“å‰%{billable_users_link_start}收费用户%{link_end}çš„æ•°é‡ï¼Œ 也是更新许å¯è¯æ—¶éœ€è¦è´­ä¹°çš„最低数é‡ã€‚"
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr "当å‰å¯†é’¥ä»…本次访问时显示,请å¤åˆ¶å¯†é’¥å¹¶å®‰å…¨çš„存储。"
+
msgid "This is your current session"
msgstr "这是您当å‰çš„会è¯"
@@ -40390,11 +41123,14 @@ msgstr "此项目已存档,无法添加评论。"
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "该项目在 %{strong_start}%{license_name}%{strong_end}下获得许å¯ã€‚"
+msgid "This project is mirrored from %{link}."
+msgstr "该项目从 %{link} é•œåƒã€‚"
+
msgid "This project is not subscribed to any project pipelines."
msgstr "此项目未订阅任何项目æµæ°´çº¿ã€‚"
msgid "This project is public. Non-members can guess the Service Desk email address, because it contains the group and project name. %{linkStart}How do I create a custom email address?%{linkEnd}"
-msgstr ""
+msgstr "这个项目是公开的。éžé¡¹ç›®æˆå‘˜å¯èƒ½çŒœå¾—出æœåŠ¡å°çš„电å­é‚®ä»¶åœ°å€ï¼Œå› ä¸ºå®ƒåŒ…å«ç¾¤ç»„和项目å称。%{linkStart}如何创建自定义电å­é‚®ä»¶åœ°å€ï¼Ÿ%{linkEnd}"
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr "此项目使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾èµ–关系"
@@ -40402,12 +41138,18 @@ msgstr "此项目使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾èµ
msgid "This project path either does not exist or you do not have access."
msgstr "此项目路径ä¸å­˜åœ¨æˆ–您没有访问æƒé™ã€‚"
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr "此项目已达到自定义域åçš„é™åˆ¶ã€‚(最大为 %d)"
+
msgid "This project will be deleted on %{date}"
msgstr "此项目将于 %{date} 删除"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr "此项目将于 %{date} 删除,因为它的父组 '%{parent_group_name}'已计划删除。"
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr "æ­¤å‘布是使用过去的日期创建的,当时 Evidence 收集功能ä¸å¯ç”¨ã€‚"
@@ -40495,6 +41237,9 @@ msgstr "这将删除该项目和%{fork_source}之间的派生关系。"
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr "这将删除此项目与派生网络中其他项目之间的派生关系。"
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr "找ä¸åˆ°è¦å›žå¤çš„主题"
@@ -40724,7 +41469,7 @@ msgid "Timeago|right now"
msgstr "刚刚"
msgid "Timeline event added successfully."
-msgstr ""
+msgstr "时间线事件添加æˆåŠŸã€‚"
msgid "Timeline|Turn recent updates view off"
msgstr "关闭最近更新视图"
@@ -40836,11 +41581,14 @@ msgstr "è¦æ¿€æ´»æ‚¨çš„试用,我们需è¦æ‚¨æ供更多的详细信æ¯ã€‚"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr "è¦æ·»åŠ è‡ªå®šä¹‰åŽç¼€ï¼Œè¯·è®¾ç½®æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€ã€‚%{linkStart}了解更多。%{linkEnd}"
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr "è¦æ·»åŠ æ˜¾ç¤ºå称,请设置æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€ã€‚%{linkStart}了解更多。%{linkEnd}"
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "如需手动添加æ¡ç›®ï¼Œè¯·åœ¨æ‰‹æœºåº”用中æ供以下信æ¯ã€‚"
msgid "To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
-msgstr ""
+msgstr "è¦æ‰¹å‡†æ­¤åˆå¹¶è¯·æ±‚,请输入您的密ç ã€‚此项目需è¦æ‰€æœ‰æ‰¹å‡†æ‰èƒ½è®¤è¯ã€‚"
msgid "To complete registration, we need additional details from you."
msgstr "è¦å®Œæˆæ³¨å†Œï¼Œæˆ‘们需è¦æ‚¨æ供更多信æ¯ã€‚"
@@ -40869,6 +41617,9 @@ msgstr "è¦ç»§ç»­ï¼Œæ‚¨éœ€è¦é€‰æ‹©æˆ‘们å‘é€çš„确认电å­é‚®ä»¶ä¸­çš„链接
msgid "To define internal users, first enable new users set to external"
msgstr "è¦å®šä¹‰å†…部用户,请首先å¯ç”¨è®¾ç½®ä¸ºå¤–部的新用户"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr "è¦å¯ç”¨æ³¨å†ŒåŠŸèƒ½ï¼Œè¯·å…ˆå¯ç”¨Service Ping。"
@@ -41029,16 +41780,16 @@ msgid "Todos|Filter by project"
msgstr "按项目筛选"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "为自己加油ï¼"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "干得好ï¼çœ‹èµ·æ¥æ‚¨çš„待办事项列表中没有任何剩余事项了"
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
-msgstr ""
+msgstr "从此,您将被称为â€å¾…办事项破å者“"
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "一个空的待办事项列表是ä¸æ˜¯å¾ˆæ¼‚亮?"
msgid "Todos|It's how you always know what to work on next."
msgstr "这是您始终知é“下一步该åšä»€ä¹ˆçš„æ–¹å¼ã€‚"
@@ -41050,7 +41801,7 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr "您的待办事项列表中没有任何事项。"
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "没有需è¦åšçš„事情。真棒ï¼"
msgid "Todos|Undo mark all as done"
msgstr "撤销标记全部完æˆ"
@@ -41088,9 +41839,6 @@ msgstr "开关æ交æè¿°"
msgid "Toggle commit list"
msgstr "展开或éšè—æ交列表"
-msgid "Toggle dropdown"
-msgstr "切æ¢ä¸‹æ‹‰åˆ—表"
-
msgid "Toggle emoji award"
msgstr "切æ¢è¡¨æƒ…符å·èµžèµ"
@@ -41112,9 +41860,6 @@ msgstr "切æ¢å¿«æ·é”®"
msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
-msgid "Toggle the Draft status"
-msgstr "切æ¢è‰ç¨¿çŠ¶æ€"
-
msgid "Toggle the Performance Bar"
msgstr "切æ¢æ€§èƒ½æ "
@@ -41161,16 +41906,16 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr "找到了太多用户。快速æ“作仅é™äºŽæœ€å¤š %{max_count} 个用户"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "探索"
msgid "TopNav|Go back"
msgstr "返回"
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "切æ¢åˆ°"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "您的仪表盘"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr "主题 %{source_topic} å·²æˆåŠŸåˆå¹¶åˆ°ä¸»é¢˜ %{target_topic} 中。"
@@ -41209,7 +41954,7 @@ msgid "Topics"
msgstr "主题"
msgid "Topics could not be merged!"
-msgstr ""
+msgstr "主题无法åˆå¹¶ï¼"
msgid "Total"
msgstr "全部"
@@ -41226,6 +41971,9 @@ msgstr "所有产物大å°ï¼š %{total_size}"
msgid "Total cores (CPUs)"
msgstr "总核心(CPU)"
+msgid "Total issue weight"
+msgstr "总议题æƒé‡"
+
msgid "Total memory (GB)"
msgstr "总内存 (GB)"
@@ -41355,9 +42103,6 @@ msgstr "第 %{daysUsed}/%{duration} 天"
msgid "Trials|Go back to GitLab"
msgstr "返回GitLab"
-msgid "Trials|Hey there"
-msgstr "您好ï¼"
-
msgid "Trials|Skip Trial"
msgstr "跳过试用"
@@ -41373,6 +42118,10 @@ msgstr "您å¯ä»¥å°†æ‚¨åœ¨ä¸€ä¸ªæ–°ç¾¤ç»„或一个现有群组上é¢è¿›è¡Œè¯•ç”¨
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr "您现在无法获得å…费试用,但您å¯ä»¥éšæ—¶é€šè¿‡é€‰æ‹©æ‚¨çš„头åƒå¹¶é€‰æ‹©â€œå¼€å§‹æ——舰版试用â€æ¥æ¢å¤æ­¤è¿›ç¨‹ã€‚"
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] "%{planName}还剩 %{daysRemaining} 天ï¼"
+
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 "您的试用版在 %{boldStart}%{trialEndDate}%{boldEnd}结æŸï¼Œæˆ‘们希望您能享å—GitLab %{planName}的功能,为了在试用结æŸåŽä¿ç•™è¿™äº›åŠŸèƒ½ï¼Œæ‚¨éœ€è¦è´­ä¹°è®¢é˜…。(如果您满足您的需è¦ï¼Œæ‚¨ä¹Ÿå¯ä»¥é€‰æ‹©ä¸“业版。)"
@@ -42054,6 +42803,9 @@ msgstr "%{linkTitle} 帮助链接"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft}购买的存储空间å¯ç”¨"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr "%{storage_limit_link_start}命å空间存储é™åˆ¶%{link_end}将很快在 %{strong_start}%{namespace_name}%{strong_end} 命å空间中执行。%{extra_message}"
+
msgid "UsageQuota|Artifacts"
msgstr "产物"
@@ -42082,7 +42834,7 @@ msgid "UsageQuota|CI/CD minutes usage since %{timeElapsed}"
msgstr "%{timeElapsed} 以æ¥çš„ CI/CD 分钟数使用é‡"
msgid "UsageQuota|CI/CD minutes usage since %{usageSince}"
-msgstr ""
+msgstr "%{usageSince} 以æ¥çš„ CI/CD 分钟数使用é‡"
msgid "UsageQuota|Code packages and container images."
msgstr "代ç åŒ…和容器镜åƒã€‚"
@@ -42096,12 +42848,12 @@ msgstr "当å‰å‘¨æœŸä½¿ç”¨é‡"
msgid "UsageQuota|Dependency proxy"
msgstr "ä¾èµ–代ç†"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr "生效于 %{storage_enforcement_date},命å空间存储é™åˆ¶å°†åœ¨%{strong_start}%{namespace_name}%{strong_end} 命å空间中生效。%{extra_message}查看此更改的%{rollout_link_start}推出计划%{link_end}。"
-
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "文件附件和较å°çš„设计图表。"
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr "关于存储é™åˆ¶çš„更多信æ¯ï¼Œè¯·å‚阅我们的 %{faq_link_start}常è§é—®é¢˜%{link_end}。"
+
msgid "UsageQuota|Git repository."
msgstr "Git仓库。"
@@ -42112,7 +42864,7 @@ msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker
msgstr "存储 Docker é•œåƒçš„ Gitlab-integrated Docker Container Registry。%{linkStart}更多信æ¯%{linkEnd}"
msgid "UsageQuota|Group settings &gt; Usage quotas"
-msgstr ""
+msgstr "群组设置 &gt; 使用é‡é…é¢"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr "包括产物ã€ä»“库ã€wikiã€ä¸Šä¼ æ–‡ä»¶å’Œå…¶å®ƒäº‹é¡¹ã€‚"
@@ -42174,9 +42926,6 @@ msgstr "仓库"
msgid "UsageQuota|Seats"
msgstr "席ä½"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr "欲了解更多信æ¯ï¼Œè¯·å‚阅我们的%{faq_link_start}常è§é—®é¢˜æ–‡æ¡£%{link_end}。"
-
msgid "UsageQuota|Shared bits of code and text."
msgstr "代ç å’Œæ–‡æœ¬çš„共享bits。"
@@ -42210,11 +42959,11 @@ msgstr "%{strong_start}%{context_name}%{strong_end} 群组将å—此影å“。"
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr "%{strong_start}%{context_name}%{strong_end} 项目将å—此影å“。"
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
-msgstr ""
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr "命å空间目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空间存储。群组所有者å¯ä»¥æŸ¥çœ‹å‘½å空间存储空间的使用情况,并从 %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}购买更多。%{docs_link_start}我å¯ä»¥å¦‚何管ç†æˆ‘的存储设备?%{link_end}。"
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
-msgstr ""
+msgstr "命å空间当å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空间存储。从 %{strong_start}%{usage_quotas_nav_instruction}%{strong_end} 查看和管ç†æ‚¨çš„使用情况。%{docs_link_start}了解更多%{link_end}有关如何å‡å°‘存储空间的信æ¯ã€‚"
msgid "UsageQuota|The table below shows current period usage"
msgstr "下表显示当å‰æ—¶é—´æ®µä½¿ç”¨æƒ…况"
@@ -42280,7 +43029,7 @@ msgid "UsageQuota|Usage quotas help link"
msgstr "使用é…é¢å¸®åŠ©é“¾æŽ¥"
msgid "UsageQuota|User settings &gt; Usage quotas"
-msgstr ""
+msgstr "用户设置 &gt; 使用é‡é…é¢"
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
msgstr "当您购买更多的存储空间时,我们会自动解é”达到%{actualRepositorySizeLimit}é™åˆ¶æ—¶è¢«é”定的项目。"
@@ -42442,7 +43191,7 @@ msgid "Use issue weight"
msgstr "使用议题æƒé‡"
msgid "Use issues to collaborate on ideas, solve problems, and plan work"
-msgstr ""
+msgstr "使用议题就想法进行å作ã€è§£å†³é—®é¢˜å’Œè®¡åˆ’工作"
msgid "Use one line per URI"
msgstr "æ¯ä¸ªURIå ä¸€è¡Œ"
@@ -42550,6 +43299,9 @@ msgstr "å·²æˆåŠŸåˆ é™¤ç”¨æˆ·æ ‡è¯†ã€‚"
msgid "User identity was successfully updated."
msgstr "å·²æˆåŠŸæ›´æ–°ç”¨æˆ·æ ‡è¯†ã€‚"
+msgid "User is blocked"
+msgstr "用户被ç¦ç”¨"
+
msgid "User is not allowed to resolve thread"
msgstr "用户ä¸å…许解决主题"
@@ -42845,7 +43597,7 @@ msgid "Users can launch a development environment from a GitLab browser tab when
msgstr "%{linkStart}Gitpod%{linkEnd} 集æˆåŽï¼Œç”¨æˆ·å¯ä»¥ä»Ž GitLab æµè§ˆå™¨é€‰é¡¹å¡å¯åŠ¨å¼€å‘环境。"
msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "用户å¯ä»¥é€šè¿‡ç™»å½•é‡æ–°æ¿€æ´»ä»–们的å¸æˆ·ã€‚%{link_start}了解更多%{link_end}"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
msgstr "用户å¯ä»¥ä½¿ç”¨ Kroki 在 AsciiDocã€Markdownã€reStructuredText å’Œ Textile 文档中渲染图表。"
@@ -42871,9 +43623,6 @@ msgstr "请求访问的用户"
msgid "Users to exclude from the rate limit"
msgstr "从速率é™åˆ¶ä¸­æŽ’除的用户"
-msgid "Users were successfully added."
-msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "具有访客角色或ä¸å±žäºŽé¡¹ç›®æˆ–组的用户将ä¸å ç”¨æ‚¨è®¸å¯è¯ä¸­çš„座ä½ã€‚"
@@ -42892,8 +43641,35 @@ msgstr "没有指派人 - %{openingTag}分é…给自己%{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr "未分é…"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr "使用 GitLab 作为 Sentry çš„è½»é‡çº§æ›¿ä»£å“。"
+msgid "User|Data Analyst"
+msgstr "æ•°æ®åˆ†æž"
+
+msgid "User|Development Team Lead"
+msgstr "å¼€å‘团队负责人"
+
+msgid "User|Devops Engineer"
+msgstr "DevOps 工程师"
+
+msgid "User|Other"
+msgstr "其他"
+
+msgid "User|Product Designer"
+msgstr "产å“设计师"
+
+msgid "User|Product Manager"
+msgstr "产å“ç»ç†"
+
+msgid "User|Security Analyst"
+msgstr "安全分æžå¸ˆ"
+
+msgid "User|Software Developer"
+msgstr "软件开å‘人员"
+
+msgid "User|Systems Administrator"
+msgstr "系统管ç†å‘˜"
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr "使用 GitLab 作为 Sentry 的替代å“。"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "使用 %{code_start}::%{code_end} 表示 %{link_start}范围标签集%{link_end}"
@@ -43139,13 +43915,13 @@ msgid "View all environments."
msgstr "查看所有环境。"
msgid "View all groups"
-msgstr ""
+msgstr "查看所有群组"
msgid "View all issues"
msgstr "查看所有议题"
msgid "View all projects"
-msgstr ""
+msgstr "查看所有项目"
msgid "View blame"
msgstr "查看 blame"
@@ -43153,6 +43929,9 @@ msgstr "查看 blame"
msgid "View blame prior to this change"
msgstr "查看此å˜æ›´å‰çš„blame模å¼"
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "查看图表"
@@ -43175,8 +43954,8 @@ msgstr "查看文档"
msgid "View eligible approvers"
msgstr "查看具备相关资格的核准人"
-msgid "View epics list"
-msgstr "查看å²è¯—列表"
+msgid "View entire blame"
+msgstr "查看完整的 blame"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43597,6 +44376,9 @@ msgstr "检测到误报"
msgid "Vulnerability|File"
msgstr "文件"
+msgid "Vulnerability|File:"
+msgstr "文件:"
+
msgid "Vulnerability|GitLab Security Report"
msgstr "GitLab 安全报告"
@@ -43618,12 +44400,12 @@ msgstr "é•œåƒ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr "关于如何å‘现æ¼æ´žåŠå…¶å¯¹ç³»ç»Ÿçš„å½±å“相关的信æ¯ã€‚"
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr "了解有关此æ¼æ´žçš„更多信æ¯ä»¥åŠè§£å†³å®ƒçš„最佳方法。"
-
msgid "Vulnerability|Links"
msgstr "链接"
+msgid "Vulnerability|Location"
+msgstr "ä½ç½®"
+
msgid "Vulnerability|Method"
msgstr "方法"
@@ -43633,6 +44415,9 @@ msgstr "命å空间"
msgid "Vulnerability|Project"
msgstr "项目"
+msgid "Vulnerability|Project:"
+msgstr "项目:"
+
msgid "Vulnerability|Remove identifier row"
msgstr "删除标识符行"
@@ -43660,6 +44445,9 @@ msgstr "æ ¹æ®æ‚¨å¯ä»¥èŽ·å¾—çš„ä¿¡æ¯è®¾ç½®æ¼æ´žå‘现的状æ€ã€‚"
msgid "Vulnerability|Severity"
msgstr "严é‡çº§åˆ«"
+msgid "Vulnerability|Severity:"
+msgstr "严é‡æ€§ï¼š"
+
msgid "Vulnerability|Status"
msgstr "状æ€"
@@ -43672,6 +44460,9 @@ msgstr "未修改的å“应是原始å“应没有对请求进行çªå˜çš„å“应"
msgid "Vulnerability|Tool"
msgstr "工具"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr "培训"
@@ -43684,6 +44475,9 @@ msgstr "未修改的å“应"
msgid "Vulnerability|View training"
msgstr "查看培训"
+msgid "WARNING:"
+msgstr "警告:"
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr "警告:此代ç ç‰‡æ®µåŒ…å«å¯èƒ½ç”¨äºŽæŽ©ç›–æ¶æ„行为的éšè—文件,克隆和执行其中的代ç éœ€è¦è°¨æ…Žã€‚"
@@ -43747,6 +44541,12 @@ msgstr "无法连接PrometheusæœåŠ¡å™¨ã€‚æœåŠ¡å™¨ä¸å†å­˜åœ¨ï¼Œæˆ–者é…ç½®ä¿
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr "我们创建了一个沙盒项目,将帮助您学习 GitLab 的基础知识。您将通过议题é¢æ¿ä¸­çš„议题获得指导。您å¯ä»¥æŒ‰ç…§è‡ªå·±çš„节å¥é€šè¯»è¿™äº›è®®é¢˜ã€‚"
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr "我们检测到有人å°è¯•ä½¿ç”¨é”™è¯¯çš„åŒé‡èº«ä»½éªŒè¯ç ç™»å½•æ‚¨çš„ %{host} å¸æˆ·"
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr "我们检测到有人å°è¯•ä½¿ç”¨é”™è¯¯çš„åŒé‡èº«ä»½éªŒè¯ç ä»Žä»¥ä¸‹ IP 地å€ç™»å½•åˆ°æ‚¨çš„ %{host} å¸æˆ·ï¼š%{ip},%{time}"
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "我们在%{humanized_resource_name}检测到潜在滥用行为。请输入此reCAPTCHA验è¯ç å¹¶ç»§ç»­ã€‚"
@@ -43841,7 +44641,7 @@ msgid "WebIDE|Quickly and easily edit multiple files in your project."
msgstr "快速轻æ¾åœ°ç¼–辑您项目中的多个文件。"
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
-msgstr ""
+msgstr "轻快地编辑您项目中的多个文件。按 . 打开"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr "此项目ä¸æŽ¥å—未签åçš„æ交。"
@@ -43925,7 +44725,7 @@ msgid "Webhooks|A subgroup is created or removed."
msgstr "已创建或删除å­ç»„。"
msgid "Webhooks|A webhook in this project was automatically disabled after being retried multiple times."
-msgstr ""
+msgstr "此项目中的 Webhook 在多次é‡è¯•åŽè‡ªåŠ¨ç¦ç”¨ã€‚"
msgid "Webhooks|A wiki page is created or updated."
msgstr "已创建或更新 wiki 页é¢ã€‚"
@@ -43957,6 +44757,9 @@ msgstr "删除 webhook"
msgid "Webhooks|Deployment events"
msgstr "部署事件"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "å¯ç”¨SSL验è¯"
@@ -43972,12 +44775,18 @@ msgstr "功能标志事件"
msgid "Webhooks|Go to webhooks"
msgstr "跳转到 Webhooks"
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "议题事件"
msgid "Webhooks|Job events"
msgstr "作业事件"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "æˆå‘˜äº‹ä»¶"
@@ -44002,6 +44811,12 @@ msgstr "SSL验è¯"
msgid "Webhooks|Secret token"
msgstr "Secret 令牌"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "å­ç¾¤ç»„事件"
@@ -44026,6 +44841,9 @@ msgstr "网å€"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr "如果 URL 包å«ä¸€ä¸ªæˆ–多个特殊字符,则必须进行百分å·ç¼–ç ã€‚"
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr "用于验è¯æŽ¥æ”¶åˆ°çš„有效载è·ã€‚与 %{code_start}X-Gitlab-Token HTTP%{code_end} 标头中的请求一起å‘é€ã€‚"
@@ -44202,12 +45020,6 @@ msgstr "您为什么è¦æ³¨å†Œï¼Ÿï¼ˆå¯é€‰ï¼‰"
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr "富文本"
-
-msgid "Wiki Page|Source"
-msgstr "æ¥æº"
-
msgid "Wiki page"
msgstr "Wiki 页é¢"
@@ -44442,6 +45254,12 @@ msgstr "添加指派人"
msgid "WorkItem|Add assignees"
msgstr "添加指派人"
+msgid "WorkItem|Add due date"
+msgstr "添加截止日期"
+
+msgid "WorkItem|Add start date"
+msgstr "添加起始日期"
+
msgid "WorkItem|Add task"
msgstr "添加任务"
@@ -44449,7 +45267,7 @@ msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr "您确定è¦å–消编辑å—?"
msgid "WorkItem|Are you sure you want to delete the %{workItemType}? This action cannot be reversed."
-msgstr ""
+msgstr "确定è¦åˆ é™¤ %{workItemType} å—?此æ“作无法撤消。"
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -44473,9 +45291,15 @@ msgstr "创建任务"
msgid "WorkItem|Create work item"
msgstr "创建工作项"
+msgid "WorkItem|Dates"
+msgstr "日期"
+
msgid "WorkItem|Delete %{workItemType}"
msgstr "删除 %{workItemType}"
+msgid "WorkItem|Due date"
+msgstr "截止日期"
+
msgid "WorkItem|Expand tasks"
msgstr "展开任务"
@@ -44492,13 +45316,13 @@ msgid "WorkItem|Learn about tasks."
msgstr "了解任务详情。"
msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
-msgstr ""
+msgstr "当å‰æœªè¢«åˆ†é…任何任务。使用任务功能将这个议题分解æˆæ›´å°çš„部分。"
msgid "WorkItem|None"
msgstr "æ— "
msgid "WorkItem|Only project members with at least the Reporter role, the author, and assignees can view or be notified about this task."
-msgstr ""
+msgstr "åªæœ‰ä½œè€…ã€æŒ‡æ´¾äººå’Œè‡³å°‘是报告者的项目æˆå‘˜ï¼Œå¯ä»¥æŸ¥çœ‹æˆ–收到有关此任务的通知。"
msgid "WorkItem|Open"
msgstr "开放"
@@ -44513,16 +45337,16 @@ msgid "WorkItem|Select type"
msgstr "选择类型"
msgid "WorkItem|Something went wrong when creating %{workItemType}. Please try again."
-msgstr ""
+msgstr "创建 %{workItemType} 时出现问题。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong when deleting the %{workItemType}. Please try again."
-msgstr ""
+msgstr "删除 %{workItemType} 时出现问题。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong when deleting the task. Please try again."
msgstr "删除任务时出错。请é‡è¯•ã€‚"
msgid "WorkItem|Something went wrong when fetching tasks. Please refresh this page."
-msgstr ""
+msgstr "获å–任务时出错。请刷新此页é¢ã€‚"
msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
msgstr "获å–工作项时出现错误,请å†è¯•ä¸€æ¬¡ã€‚"
@@ -44537,11 +45361,14 @@ msgid "WorkItem|Something went wrong when trying to create a child. Please try a
msgstr "å°è¯•åˆ›å»ºå­é¡¹æ—¶å‡ºé”™ï¼Œè¯·å†è¯•ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong while updating the %{workItemType}. Please try again."
-msgstr ""
+msgstr "æ›´æ–° %{workItemType} 时出现问题。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr "更新工作项时出现错误,请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "WorkItem|Start date"
+msgstr "起始日期"
+
msgid "WorkItem|Task"
msgstr "任务"
@@ -44564,7 +45391,7 @@ msgid "WorkItem|Undo"
msgstr "撤消"
msgid "WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}"
-msgstr ""
+msgstr "使用任务功能,将您在一个议题中的工作划分æˆæ›´å°çš„部分。%{learnMoreLink}"
msgid "WorkItem|Work Items"
msgstr "工作事项"
@@ -44802,6 +45629,12 @@ msgstr "您å¯ä»¥åœ¨ %{pat_link_start}个人访问令牌%{pat_link_end} 中查çœ
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr "您å¯ä»¥åœ¨æ‚¨çš„个人访问令牌设置 %{pat_link} 中查看它。"
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr "您å¯ä»¥æ£€æŸ¥æ‚¨çš„令牌或在您的 %{pat_link_start}个人访问令牌设置%{pat_link_end}中创建一个新令牌。"
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„个人访问令牌设置 %{pat_link} 中检查您的令牌或创建一个新的令牌。"
+
msgid "You can create a new %{link}."
msgstr "您å¯ä»¥åˆ›å»ºä¸€ä¸ªæ–°çš„%{link}。"
@@ -44925,6 +45758,9 @@ msgstr "您ä¸èƒ½ %{action} %{state} 用户。"
msgid "You cannot access the raw file. Please wait a minute."
msgstr "您ä¸èƒ½è®¿é—®åŽŸå§‹æ–‡ä»¶ã€‚请ç¨å€™ã€‚"
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr "您ä¸èƒ½æ·»åŠ æ›´å¤šçš„å²è¯—。这个å²è¯—å·²ç»æœ‰äº†æœ€å¤§æ•°é‡çš„å­å²è¯—。"
+
msgid "You cannot approve your own deployment."
msgstr "您ä¸èƒ½æ‰¹å‡†æ‚¨è‡ªå·±çš„部署。"
@@ -45124,8 +45960,8 @@ msgstr "您已ç»ä¸ºæ‚¨çš„å¸æˆ·è®¾ç½®äº†ä¸¤æ­¥éªŒè¯ï¼ 如果您无法访问æ‚
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr "您已æˆåŠŸè´­ä¹° %{product}。您将通过电å­é‚®ä»¶æ”¶åˆ°æ”¶æ®ã€‚您的购买å¯èƒ½éœ€è¦ä¸€åˆ†é’Ÿæ‰èƒ½åŒæ­¥ï¼Œå¦‚果您还没有看到,请刷新页é¢ã€‚"
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
-msgstr ""
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr "您已æˆåŠŸè´­ä¹° %{seats} çš„ %{plan} 计划订阅。您将通过电å­é‚®ä»¶æ”¶åˆ°æ”¶æ®ã€‚您的购买å¯èƒ½éœ€è¦ä¸€åˆ†é’Ÿæ‰èƒ½åŒæ­¥ï¼Œå¦‚果您还没有看到,请刷新页é¢ã€‚"
msgid "You have unsaved changes"
msgstr "您有未ä¿å­˜çš„更改"
@@ -45142,8 +45978,8 @@ msgstr "您必须ç»è¿‡è®¤è¯æ‰èƒ½è®¿é—®æ­¤è·¯å¾„。"
msgid "You must be logged in to search across all of GitLab"
msgstr "您必须登录æ‰èƒ½åœ¨æ•´ä¸ªGitLab中进行æœç´¢"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
-msgstr "å¯ç”¨è°ƒè¯•è·Ÿè¸ªæ—¶ï¼Œæ‚¨å¿…须在关è”项目中拥有开å‘人员或更高æƒé™æ‰èƒ½æŸ¥çœ‹ä½œä¸šæ—¥å¿—。è¦ç¦ç”¨è°ƒè¯•è·Ÿè¸ªï¼Œè¯·åœ¨æµæ°´çº¿é…置或 CI/CD 设置中将“CI_DEBUG_TRACEâ€å˜é‡è®¾ç½®ä¸ºâ€œfalseâ€ã€‚如果您需è¦æŸ¥çœ‹æ­¤ä½œä¸šæ—¥å¿—,项目维护者必须将您添加到具有开å‘人员æƒé™æˆ–更高æƒé™çš„项目中。"
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
+msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
@@ -45188,7 +46024,7 @@ msgid "You need to verify your primary email first before enabling Two-Factor Au
msgstr "您需è¦å…ˆéªŒè¯æ‚¨çš„主è¦ç”µå­é‚®ä»¶ï¼Œç„¶åŽæ‰èƒ½å¯ç”¨åŒé‡èº«ä»½éªŒè¯ã€‚"
msgid "You see projects here when you're added to a group or project."
-msgstr ""
+msgstr "当您被添加到群组或项目时,您会在此处看到项目。"
msgid "You successfully declined the invitation"
msgstr "您æˆåŠŸæ‹’ç»äº†é‚€è¯·"
@@ -45341,10 +46177,10 @@ msgid "Your CSV import for project"
msgstr "您的项目CSV导入"
msgid "Your Chain of Custody CSV export for the group %{group_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "您对群组 %{group_link} 的监管链 CSV 导出已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
msgid "Your Chain of Custody CSV export for the group %{group_name} has been added to this email as an attachment."
-msgstr ""
+msgstr "您对群组 %{group_name} 的监管链 CSV 导出已作为附件添加到此电å­é‚®ä»¶ä¸­ã€‚"
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 "您的 DevOps 报告从功能角度概述了您如何使用 GitLab。使用它们æ¥æŸ¥çœ‹æ‚¨ä¸Žå…¶ä»–组织的比较情况,以åŠæ‚¨çš„团队之间的比较情况。"
@@ -45725,6 +46561,9 @@ msgstr "已添加"
msgid "added %{emails}"
msgstr "添加了 %{emails}"
+msgid "added a %{link_type} link"
+msgstr "添加了一个 %{link_type} 链接"
+
msgid "added a Zoom call to this issue"
msgstr "添加Zoom通è¯åˆ°æ­¤è®®é¢˜"
@@ -45817,6 +46656,9 @@ msgstr "æ¥è‡ª"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr "åªèƒ½åŒ…å«Base64å­—æ¯è¡¨(RFC4648)中的字æ¯ï¼Œä»¥åŠâ€œ@â€ã€â€œ:â€å’Œâ€œ.â€ã€‚"
@@ -45862,6 +46704,9 @@ msgstr "ä¸èƒ½å°†éžç§å¯†å·¥ä½œé¡¹åˆ†é…ç»™ç§å¯†çš„父级。将工作项设为
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "无法更改"
@@ -45872,7 +46717,7 @@ msgid "cannot be changed if shared runners are enabled"
msgstr "如果å¯ç”¨å…±äº«Runner,则无法更改"
msgid "cannot be changed since member is associated with a custom role"
-msgstr ""
+msgstr "无法更改,因为æˆå‘˜ä¸Žè‡ªå®šä¹‰è§’色关è”"
msgid "cannot be enabled"
msgstr "无法å¯ç”¨"
@@ -45915,7 +46760,7 @@ msgid_plural "changes"
msgstr[0] "å˜æ›´"
msgid "ciReport|%{criticalStart}critical%{criticalEnd}, %{highStart}high%{highEnd} and %{otherStart}others%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}critical%{criticalEnd}ã€%{highStart}high%{highEnd} å’Œ%{otherStart}其他%{otherEnd}"
msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}"
msgstr "%{danger_start}%{degradedNum} é™ä½Ž%{danger_end}ã€%{same_start}%{sameNum} 相åŒ%{same_end} å’Œ %{success_start}%{improvedNum} 改善%{success_end}"
@@ -46118,6 +46963,9 @@ msgstr "找到%{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr "完整报告"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr "IaC 扫æ"
@@ -46273,6 +47121,9 @@ msgstr "收集使用信æ¯"
msgid "comment"
msgstr "评论"
+msgid "commented"
+msgstr "已评论"
+
msgid "commented on %{link_to_project}"
msgstr "评论 %{link_to_project}"
@@ -46318,6 +47169,9 @@ msgstr "创建于%{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "由 %{author} 创建于 %{timeAgo}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr "由 %{author} 于 %{timeAgo},在 %{project_link} 创建"
+
msgid "created by"
msgstr "创建人:"
@@ -46435,7 +47289,7 @@ msgid "expired on %{timebox_due_date}"
msgstr "已于%{timebox_due_date}过期"
msgid "expires on %{timebox_due_date}"
-msgstr "于%{timebox_due_date}过期"
+msgstr "将于%{timebox_due_date}过期"
msgid "failed"
msgstr "已失败"
@@ -46447,7 +47301,7 @@ msgid "failed to dismiss finding: %{message}"
msgstr "忽略å‘现失败:%{message}"
msgid "failed to dismiss security finding: %{message}"
-msgstr ""
+msgstr "忽略安全å‘现失败:%{message}"
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
msgstr "无法将关è”çš„å‘现(id=%{finding_id})æ¢å¤åˆ°ä¸ºæ£€æµ‹åˆ°"
@@ -46633,9 +47487,6 @@ msgstr "ä¸å…许,因为该群组ä¸æ˜¯é¡¶çº§ç¾¤ç»„。"
msgid "is not allowed. Please use your regular email address."
msgstr "ä¸å…许。请使用您的常规电å­é‚®ä»¶åœ°å€ã€‚"
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr "ä¸è¢«å…许。我们目å‰ä¸æ”¯æŒé¡¹ç›®çº§è¿­ä»£"
-
msgid "is not in the group enforcing Group Managed Account"
msgstr "ä¸åœ¨å¼ºåˆ¶æ‰§è¡Œç¾¤ç»„托管账户的群组"
@@ -46655,7 +47506,7 @@ msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "太长(%{current_value})。最大值为%{max_size}。"
msgid "is too long (%{size}). The maximum size is %{max_size}."
-msgstr ""
+msgstr "太长(%{size})。最大值为 %{max_size}。"
msgid "is too long (maximum is %{count} characters)"
msgstr "过长(最长为 %{count} 个字符)"
@@ -46726,6 +47577,10 @@ msgstr "LFS 对象"
msgid "limit of %{project_limit} reached"
msgstr "已达到%{project_limit}çš„é™åˆ¶"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "行"
+
msgid "load it anyway"
msgstr "ä»ç„¶åŠ è½½"
@@ -46756,11 +47611,14 @@ msgid_plural "merge requests"
msgstr[0] "åˆå¹¶è¯·æ±‚"
msgid "mergedCommitsAdded| (commits were squashed)"
-msgstr ""
+msgstr "(æ交被压缩)"
msgid "metric_id must be unique across a project"
msgstr "metric_id必须是整个项目唯一的"
+msgid "milestone should belong either to a project or a group."
+msgstr "里程碑应该属于一个项目或群组。"
+
msgid "missing"
msgstr "丢失"
@@ -46777,7 +47635,7 @@ msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
msgstr "%{commitCount} 将被添加到 %{targetBranch}。"
msgid "mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit"
-msgstr ""
+msgstr "%{strongStart}1%{strongEnd} 个åˆå¹¶æ交"
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr "å·²åˆå¹¶åˆ° %{targetBranch} çš„ %{mergeCommitSha}%{squashedCommits} çš„å˜æ›´ã€‚"
@@ -46938,7 +47796,7 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] "æåŠè®®é¢˜"
msgid "mrWidget|Merge blocked: a Jira issue key must be mentioned in the title or description."
-msgstr ""
+msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šæ ‡é¢˜æˆ–æ述中必须æ到 Jira 议题的 key。"
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šå¿…须获得所有è¦æ±‚的批准。"
@@ -47126,6 +47984,9 @@ msgstr "必须有一个仓库"
msgid "must match %{association}.project_id"
msgstr "å¿…é¡»åŒ¹é… %{association}.project_id"
+msgid "must not contain commonly used combinations of words and letters"
+msgstr "ä¸èƒ½åŒ…å«å¸¸ç”¨çš„å•è¯å’Œå­—æ¯ç»„åˆ"
+
msgid "my-awesome-group"
msgstr "my-awesome-group"
@@ -47207,9 +48068,6 @@ msgstr "或"
msgid "organizations can only be added to root groups"
msgstr "机构组织åªèƒ½æ·»åŠ åˆ° root 群组"
-msgid "other card matches"
-msgstr "其他å¡ç‰‡åŒ¹é…"
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "于总计%d个测试中"
@@ -47349,6 +48207,9 @@ msgstr "移除æƒé‡"
msgid "removed"
msgstr "已删除"
+msgid "removed a %{link_type} link"
+msgstr "删除了一个 %{link_type} 链接"
+
msgid "removed a Zoom call from this issue"
msgstr "从当å‰è®®é¢˜ä¸­ç§»é™¤Zoom通è¯"
@@ -47380,6 +48241,10 @@ msgstr "扫æ执行策略:策略未应用, %{policy_path} 文件无效"
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr "扫æ执行策略:策略未应用,缺少 %{policy_path} 文件"
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "席ä½"
+
msgid "security Reports|There was an error creating the merge request"
msgstr "创建åˆå¹¶è¯·æ±‚时出错"
@@ -47462,7 +48327,7 @@ msgid "started on %{timebox_start_date}"
msgstr "开始于%{timebox_start_date}"
msgid "starts on %{timebox_start_date}"
-msgstr "开始于%{timebox_start_date}"
+msgstr "将于%{timebox_start_date}开始"
msgid "structure is too large"
msgstr "结构过大"
@@ -47488,6 +48353,9 @@ msgstr "模æ¿å·²å‡†å¤‡å°±ç»ªï¼çŽ°åœ¨ï¼Œæ‚¨å¯ä»¥æ交以创建您的第一æ¡
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr "我们正在添加GitLab CIé…置文件,以将æµæ°´çº¿æ·»åŠ åˆ°é¡¹ç›®ä¸­ã€‚您也å¯ä»¥æ‰‹åŠ¨åˆ›å»ºï¼Œä½†æˆ‘们建议您从一个开箱å³ç”¨çš„GitLab模æ¿å¼€å§‹ã€‚"
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "标签å称"
@@ -47554,6 +48422,10 @@ msgstr "更新于%{time_ago}"
msgid "uploads"
msgstr "上传"
+msgid "user"
+msgid_plural "users"
+msgstr[0] "用户"
+
msgid "user avatar"
msgstr "用户头åƒ"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 68349c33650..ae77ec6cc4b 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:25\n"
+"PO-Revision-Date: 2022-10-10 14:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] ""
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@@ -931,10 +935,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] ""
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] ""
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -994,9 +998,6 @@ msgstr ""
msgid "%{text} is available"
msgstr "%{text} å¯ç”¨"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
-
msgid "%{timebox_type} does not support burnup charts"
msgstr ""
@@ -1030,6 +1031,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr ""
@@ -1051,10 +1055,13 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
-msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
-msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr ""
+
+msgid "%{username} marked merge request %{mr_link} as ready"
msgstr ""
msgid "%{username}'s avatar"
@@ -1078,6 +1085,12 @@ msgstr ""
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
+msgid "%{verb} this %{noun} as a draft."
+msgstr ""
+
+msgid "%{verb} this %{noun} as ready."
+msgstr ""
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr ""
@@ -1535,9 +1548,6 @@ msgstr ""
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr ""
-msgid "A new impersonation token has been created."
-msgstr ""
-
msgid "A new personal access token has been created"
msgstr ""
@@ -1556,6 +1566,15 @@ msgstr ""
msgid "A page with that title already exists"
msgstr ""
+msgid "A personal access token has been revoked"
+msgstr ""
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr ""
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -2237,12 +2256,6 @@ msgstr ""
msgid "Add trigger"
msgstr ""
-msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users to group"
-msgstr ""
-
msgid "Add variable"
msgstr ""
@@ -2636,9 +2649,15 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|Group runners expiration"
+msgstr ""
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -2651,6 +2670,9 @@ msgstr ""
msgid "AdminSettings|Inactive project deletion"
msgstr ""
+msgid "AdminSettings|Instance runners expiration"
+msgstr ""
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2672,6 +2694,9 @@ msgstr ""
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr ""
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr ""
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr ""
@@ -2708,6 +2733,9 @@ msgstr ""
msgid "AdminSettings|Project export"
msgstr ""
+msgid "AdminSettings|Project runners expiration"
+msgstr ""
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2759,9 +2787,21 @@ msgstr ""
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr ""
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr ""
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr ""
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr ""
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -2948,6 +2988,9 @@ msgstr "å·²å°éŽ–"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
+msgid "AdminUsers|Bot"
+msgstr ""
+
msgid "AdminUsers|Can create group"
msgstr ""
@@ -3287,9 +3330,21 @@ msgstr ""
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr ""
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr ""
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3716,6 +3771,9 @@ msgstr ""
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
+msgid "All project members"
+msgstr ""
+
msgid "All projects"
msgstr ""
@@ -3791,6 +3849,9 @@ msgstr ""
msgid "Allow use of licensed EE features"
msgstr ""
+msgid "Allow users to create top-level groups"
+msgstr ""
+
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -4079,9 +4140,6 @@ msgstr ""
msgid "An error occurred while loading all the files."
msgstr ""
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr ""
-
msgid "An error occurred while loading chart data"
msgstr ""
@@ -4326,6 +4384,9 @@ msgstr ""
msgid "Analytics"
msgstr ""
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
@@ -4547,6 +4608,9 @@ msgstr ""
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr ""
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr ""
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr ""
@@ -5182,6 +5246,9 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -5852,6 +5919,9 @@ msgstr ""
msgid "Below you will find all the groups that are public."
msgstr ""
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -6173,7 +6243,7 @@ msgstr ""
msgid "Billing|Enter at least three characters to search."
msgstr ""
-msgid "Billing|Explore all plans"
+msgid "Billing|Explore paid plans"
msgstr ""
msgid "Billing|Export list"
@@ -6210,6 +6280,9 @@ msgstr ""
msgid "Billing|Type %{username} to confirm"
msgstr ""
+msgid "Billing|Unlimited members during your trial"
+msgstr ""
+
msgid "Billing|User was successfully removed"
msgstr ""
@@ -6525,6 +6598,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Bot"
+msgstr ""
+
msgid "Both SSH and HTTP(S)"
msgstr ""
@@ -6561,33 +6637,78 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr ""
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr ""
msgid "BranchRules|Allowed to merge"
msgstr ""
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr ""
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr ""
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr ""
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr ""
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr ""
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr ""
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr ""
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr ""
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr ""
@@ -6597,6 +6718,18 @@ msgstr ""
msgid "BranchRules|Require approval from code owners."
msgstr ""
+msgid "BranchRules|Roles"
+msgstr ""
+
+msgid "BranchRules|Status checks"
+msgstr ""
+
+msgid "BranchRules|Target Branch"
+msgstr ""
+
+msgid "BranchRules|Users"
+msgstr ""
+
msgid "BranchRules|default"
msgstr ""
@@ -6897,6 +7030,9 @@ msgstr ""
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
+msgid "BulkImport|invalid entity source type"
+msgstr ""
+
msgid "BulkImport|must be a group"
msgstr ""
@@ -7069,6 +7205,9 @@ msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr ""
+
msgid "CICD|Jobs"
msgstr ""
@@ -7078,7 +7217,7 @@ msgstr ""
msgid "CICD|Limit CI_JOB_TOKEN access"
msgstr ""
-msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
@@ -7339,7 +7478,7 @@ msgstr ""
msgid "Cannot promote issue due to insufficient permissions."
msgstr ""
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgid "Cannot refer to a group milestone by an internal id!"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -7534,6 +7673,9 @@ msgstr "將標題改為「%{title_param}ã€ã€‚"
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -8545,6 +8687,9 @@ msgstr ""
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr ""
+
msgid "ClusterAgents|Certificate"
msgstr ""
@@ -8644,6 +8789,9 @@ msgstr ""
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
+msgid "ClusterAgents|Integration Status"
+msgstr ""
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] ""
+msgid "ClusterAgents|No agent access token"
+msgstr ""
+
msgid "ClusterAgents|No agents"
msgstr ""
@@ -8678,6 +8829,9 @@ msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
+msgid "ClusterAgents|Premium"
+msgstr ""
+
msgid "ClusterAgents|Recommended"
msgstr ""
@@ -8744,6 +8898,9 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Valid access token"
+msgstr ""
+
msgid "ClusterAgents|View all %{number} agents"
msgstr ""
@@ -9411,6 +9568,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -9516,6 +9676,9 @@ msgstr ""
msgid "Complete verification to sign in."
msgstr ""
+msgid "Complete verification to sign up."
+msgstr ""
+
msgid "Completed"
msgstr ""
@@ -9585,7 +9748,7 @@ msgstr ""
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr ""
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
@@ -9903,6 +10066,9 @@ msgstr ""
msgid "Container Registry"
msgstr ""
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr ""
@@ -10356,13 +10522,13 @@ msgstr "è²¢ç»è€…"
msgid "Control emails linked to your account"
msgstr ""
-msgid "Control how the GitLab Package Registry functions."
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
msgstr ""
-msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
+msgid "Control how the GitLab Package Registry functions."
msgstr ""
-msgid "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."
+msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr ""
msgid "Cookie domain"
@@ -10686,6 +10852,9 @@ msgstr ""
msgid "Country"
msgstr ""
+msgid "Counts reflect children you may not have access to."
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10902,6 +11071,9 @@ msgstr ""
msgid "Create user"
msgstr ""
+msgid "Create wildcard"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -10914,6 +11086,12 @@ msgstr ""
msgid "Create, update, or delete a merge request."
msgstr ""
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr ""
+
+msgid "CreateGitTag|Set tag message"
+msgstr ""
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr ""
@@ -12167,6 +12345,12 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr ""
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -12353,6 +12537,9 @@ msgstr ""
msgid "Delete artifacts"
msgstr ""
+msgid "Delete asset"
+msgstr ""
+
msgid "Delete audio"
msgstr ""
@@ -12497,6 +12684,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -12830,6 +13020,9 @@ msgstr ""
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr ""
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr ""
@@ -12875,6 +13068,9 @@ msgstr ""
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr ""
+msgid "DeployTokens|Expiration date (optional)"
+msgstr ""
+
msgid "DeployTokens|Expires"
msgstr ""
@@ -12896,6 +13092,9 @@ msgstr ""
msgid "DeployTokens|Scopes"
msgstr ""
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr ""
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr ""
@@ -12911,6 +13110,12 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
+msgid "DeployTokens|Username (optional)"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -13095,18 +13300,9 @@ msgstr ""
msgid "Deprecated API rate limits"
msgstr ""
-msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr ""
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
@@ -13174,25 +13370,22 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Cancel changes"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "DesignManagement|Cancel comment confirmation"
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr ""
-msgid "DesignManagement|Cancel comment update confirmation"
+msgid "DesignManagement|Comment"
msgstr ""
-msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgid "DesignManagement|Continue creating"
msgstr ""
-msgid "DesignManagement|Comment"
+msgid "DesignManagement|Continue editing"
msgstr ""
msgid "DesignManagement|Could not add a new comment. Please try again."
@@ -13213,7 +13406,7 @@ msgstr ""
msgid "DesignManagement|Designs"
msgstr ""
-msgid "DesignManagement|Discard comment"
+msgid "DesignManagement|Discard changes"
msgstr ""
msgid "DesignManagement|Discussion"
@@ -13234,12 +13427,6 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
-msgid "DesignManagement|Keep changes"
-msgstr ""
-
-msgid "DesignManagement|Keep comment"
-msgstr ""
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
@@ -13778,6 +13965,18 @@ msgstr ""
msgid "Domain Name"
msgstr ""
+msgid "Domain Verification"
+msgstr ""
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr ""
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr ""
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr ""
+
msgid "Don't have a group?"
msgstr ""
@@ -14144,6 +14343,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr ""
+msgid "Edit your search and try again"
+msgstr ""
+
msgid "Edit your search filter and try again."
msgstr ""
@@ -14282,9 +14484,6 @@ msgstr ""
msgid "Emails"
msgstr ""
-msgid "Emails sent from Service Desk have this name."
-msgstr ""
-
msgid "Emails sent to %{email} are also supported."
msgstr ""
@@ -14402,6 +14601,9 @@ msgstr ""
msgid "Enable container expiration caching."
msgstr ""
+msgid "Enable dashboard limits on namespaces"
+msgstr ""
+
msgid "Enable email notification"
msgstr ""
@@ -14750,6 +14952,9 @@ msgstr ""
msgid "Environments|Deployment %{status}"
msgstr ""
+msgid "Environments|Edit your search and try again"
+msgstr ""
+
msgid "Environments|Enable review app"
msgstr ""
@@ -14783,6 +14988,9 @@ msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
+msgid "Environments|No results found"
+msgstr ""
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr ""
@@ -14807,6 +15015,9 @@ msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
+msgid "Environments|Search by environment name"
+msgstr ""
+
msgid "Environments|Show all"
msgstr ""
@@ -15902,9 +16113,6 @@ msgstr ""
msgid "Failed to load deploy keys."
msgstr ""
-msgid "Failed to load emoji list."
-msgstr ""
-
msgid "Failed to load error details from Sentry."
msgstr ""
@@ -16587,6 +16795,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr ""
+msgid "For faster browsing, not all history is shown."
+msgstr ""
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr ""
@@ -16716,13 +16927,46 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
+msgid "Free User Cap"
+msgstr ""
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] ""
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr ""
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr ""
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr ""
+
+msgid "FreeUserCap|Manage members"
+msgstr ""
+
+msgid "FreeUserCap|Manage members:"
+msgstr ""
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr ""
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr ""
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr ""
+
msgid "Freeze end"
msgstr ""
@@ -16981,6 +17225,9 @@ msgstr ""
msgid "Geo|Errors:"
msgstr ""
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -17320,6 +17567,9 @@ msgstr ""
msgid "Geo|There was an error updating the Geo Settings"
msgstr ""
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr ""
@@ -17542,9 +17792,6 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
-msgid "GitLab Logo"
-msgstr ""
-
msgid "GitLab Pages"
msgstr ""
@@ -18409,6 +18656,9 @@ msgstr ""
msgid "GroupRoadmap|Loading epics"
msgstr ""
+msgid "GroupRoadmap|New epic"
+msgstr ""
+
msgid "GroupRoadmap|No start and end date"
msgstr ""
@@ -18445,6 +18695,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupRoadmap|View epics list"
+msgstr ""
+
msgid "GroupRoadmap|Within 3 years"
msgstr ""
@@ -18661,7 +18914,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
@@ -19006,6 +19259,12 @@ msgstr ""
msgid "Groups|Learn more"
msgstr ""
+msgid "Groups|Learn more about subgroups"
+msgstr ""
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr ""
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr ""
@@ -19024,6 +19283,9 @@ msgstr ""
msgid "Groups|Subgroup slug"
msgstr ""
+msgid "Groups|You're creating a new top-level group"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19045,7 +19307,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
@@ -19089,6 +19351,9 @@ msgstr[0] ""
msgid "HarborRegistry|-- artifacts"
msgstr ""
+msgid "HarborRegistry|-- tags"
+msgstr ""
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr ""
@@ -19134,7 +19399,7 @@ msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
msgstr ""
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
@@ -19565,24 +19830,45 @@ msgstr ""
msgid "Identities"
msgstr ""
+msgid "IdentityVerification|A new code has been sent."
+msgstr ""
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr ""
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr ""
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr ""
+msgid "IdentityVerification|Confirm your email address"
+msgstr ""
+
msgid "IdentityVerification|Create a project"
msgstr ""
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr ""
+
+msgid "IdentityVerification|Enter a code."
+msgstr ""
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr ""
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr ""
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr ""
+
msgid "IdentityVerification|Help us keep GitLab secure"
msgstr ""
@@ -19622,16 +19908,22 @@ msgstr ""
msgid "IdentityVerification|Resend code"
msgstr ""
+msgid "IdentityVerification|Send a new code"
+msgstr ""
+
msgid "IdentityVerification|Send code"
msgstr ""
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr ""
+
msgid "IdentityVerification|Step 1: Verify phone number"
msgstr ""
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
msgstr ""
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr ""
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr ""
msgid "IdentityVerification|Verify code"
msgstr ""
+msgid "IdentityVerification|Verify email address"
+msgstr ""
+
+msgid "IdentityVerification|Verify payment method"
+msgstr ""
+
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19652,10 +19950,13 @@ msgstr ""
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
msgstr ""
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr ""
+
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
@@ -19736,6 +20037,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -19745,6 +20052,9 @@ msgstr ""
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr ""
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr ""
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19924,6 +20234,9 @@ msgstr ""
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr ""
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
@@ -19948,6 +20261,9 @@ msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr ""
@@ -20852,6 +21168,9 @@ msgstr ""
msgid "Increase"
msgstr ""
+msgid "Indent line"
+msgstr ""
+
msgid "Index"
msgstr ""
@@ -21072,6 +21391,9 @@ msgstr ""
msgid "Integrations|Add namespace"
msgstr ""
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -21132,12 +21454,18 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -21150,6 +21478,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr ""
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr ""
@@ -21342,9 +21673,6 @@ msgstr ""
msgid "Interval Pattern"
msgstr "循環週期"
-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 ""
@@ -21736,6 +22064,12 @@ msgstr ""
msgid "Is using seat"
msgstr ""
+msgid "IssuableEvents|removed review request for"
+msgstr ""
+
+msgid "IssuableEvents|requested review from"
+msgstr ""
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr ""
@@ -21835,6 +22169,9 @@ msgstr ""
msgid "IssueAnalytics|Issue"
msgstr ""
+msgid "IssueAnalytics|Iteration"
+msgstr ""
+
msgid "IssueAnalytics|Milestone"
msgstr ""
@@ -22207,9 +22544,6 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr ""
@@ -23055,6 +23389,9 @@ msgstr ""
msgid "Last successful update"
msgstr ""
+msgid "Last successful update %{time}."
+msgstr ""
+
msgid "Last time verified"
msgstr ""
@@ -23136,7 +23473,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -23919,6 +24256,9 @@ msgstr ""
msgid "Make issue confidential"
msgstr ""
+msgid "Make sure you choose a strong, unique password."
+msgstr ""
+
msgid "Make sure you have the correct permissions to link your project."
msgstr ""
@@ -23970,10 +24310,10 @@ msgstr ""
msgid "Manage two-factor authentication"
msgstr ""
-msgid "Manage your license"
+msgid "Manage your project's triggers"
msgstr ""
-msgid "Manage your project's triggers"
+msgid "Manage your subscription"
msgstr ""
msgid "Managed Account"
@@ -24057,9 +24397,24 @@ msgstr ""
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr ""
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr ""
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr ""
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr ""
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr ""
+msgid "Marked"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24069,9 +24424,6 @@ msgstr ""
msgid "Marked as ready. Merging is now allowed."
msgstr ""
-msgid "Marked this %{noun} as a draft."
-msgstr ""
-
msgid "Marked this %{noun} as ready."
msgstr ""
@@ -24084,7 +24436,7 @@ msgstr ""
msgid "Marked to do as done."
msgstr ""
-msgid "Marks this %{noun} as a draft."
+msgid "Marks"
msgstr ""
msgid "Marks this %{noun} as ready."
@@ -24321,6 +24673,9 @@ msgstr ""
msgid "Maximum number of unique IP addresses per user."
msgstr ""
+msgid "Maximum number of variables loaded (2000)"
+msgstr ""
+
msgid "Maximum of 255 characters"
msgstr ""
@@ -25447,6 +25802,9 @@ msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr ""
+
msgid "Min Value"
msgstr ""
@@ -25471,6 +25829,9 @@ msgstr ""
msgid "Mirror user"
msgstr ""
+msgid "Mirrored from %{link}."
+msgstr ""
+
msgid "Mirrored repositories"
msgstr ""
@@ -25735,6 +26096,9 @@ msgstr ""
msgid "Name new label"
msgstr ""
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr ""
+
msgid "Name:"
msgstr ""
@@ -25947,6 +26311,9 @@ msgstr "創建æµæ°´ç·šè¨ˆåŠƒ"
msgid "New Project"
msgstr ""
+msgid "New Protected Branch"
+msgstr ""
+
msgid "New Requirement"
msgstr ""
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] ""
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr ""
@@ -26729,33 +27099,66 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
+msgid "Notify|%{issues} imported."
+msgstr ""
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr ""
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr ""
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
msgstr ""
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr ""
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr ""
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr ""
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
+msgid "Notify|A remote mirror update has failed."
+msgstr ""
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr ""
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
msgstr ""
@@ -26777,12 +27180,30 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
+msgid "Notify|Click here to set your password"
+msgstr ""
+
+msgid "Notify|Commit Author"
+msgstr ""
+
+msgid "Notify|Committed by"
+msgstr ""
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
msgstr ""
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr ""
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr ""
+
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
+msgid "Notify|Hi %{username}!"
+msgstr ""
+
msgid "Notify|Hi %{user}!"
msgstr ""
@@ -26801,6 +27222,9 @@ msgstr ""
msgid "Notify|Learn more about Auto DevOps"
msgstr ""
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr ""
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26825,6 +27249,12 @@ msgstr ""
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr ""
+msgid "Notify|Merge request was unapproved"
+msgstr ""
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr ""
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr ""
@@ -26834,15 +27264,51 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr ""
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr ""
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr ""
+
+msgid "Notify|Remote mirror"
+msgstr ""
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr ""
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr ""
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr ""
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr ""
@@ -26855,12 +27321,33 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr ""
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr ""
+
+msgid "Notify|Your account has been created successfully."
+msgstr ""
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|login.........................................."
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26921,6 +27408,9 @@ msgstr ""
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr ""
+msgid "Observability"
+msgstr ""
+
msgid "Oct"
msgstr "å月"
@@ -27081,6 +27571,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr ""
+
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -27640,6 +28133,9 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
+msgid "Outdent line"
+msgstr ""
+
msgid "Overridden"
msgstr ""
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] ""
-msgid "PackageRegistry|Delete Package File"
-msgstr ""
-
msgid "PackageRegistry|Delete Package Version"
msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete package asset"
+msgstr ""
+
msgid "PackageRegistry|Delete selected"
msgstr ""
@@ -27956,6 +28452,9 @@ msgstr ""
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -27989,13 +28488,13 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package assets deleted successfully"
+msgid "PackageRegistry|Package asset deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package deleted successfully"
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
msgid "PackageRegistry|Package formats"
@@ -28008,6 +28507,9 @@ msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr ""
@@ -28059,10 +28561,10 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr ""
-msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
msgstr ""
msgid "PackageRegistry|Something went wrong while deleting the package."
@@ -28119,7 +28621,7 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr ""
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
@@ -28333,9 +28835,6 @@ msgstr ""
msgid "Pause"
msgstr ""
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
-
msgid "Pause time (ms)"
msgstr ""
@@ -28738,9 +29237,21 @@ msgstr "已啟用"
msgid "PipelineSchedules|All"
msgstr "所有"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "未啟用"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "下次é‹è¡Œæ™‚é–“"
@@ -28750,15 +29261,27 @@ msgstr "ç„¡"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "為此æµæ°´ç·šæ供簡短æè¿°"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "å–得所有權"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "目標"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "變é‡"
@@ -28873,6 +29396,12 @@ msgstr ""
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr ""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr ""
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr ""
+
msgid "Pipelines|1. Set up a runner"
msgstr ""
@@ -29554,6 +30083,9 @@ msgstr ""
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr ""
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -29563,6 +30095,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Please wait while we prepare for verification."
+msgstr ""
+
msgid "Pods in use"
msgstr ""
@@ -29623,6 +30158,9 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr ""
@@ -29734,6 +30272,9 @@ msgstr ""
msgid "Preferences|Use relative times"
msgstr ""
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr ""
@@ -29947,15 +30488,9 @@ msgstr ""
msgid "Profiles|Add key"
msgstr ""
-msgid "Profiles|Add status emoji"
-msgstr ""
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
-
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29968,9 +30503,6 @@ msgstr ""
msgid "Profiles|Bio"
msgstr ""
-msgid "Profiles|Busy"
-msgstr ""
-
msgid "Profiles|Change username"
msgstr ""
@@ -29986,9 +30518,6 @@ msgstr ""
msgid "Profiles|City, country"
msgstr ""
-msgid "Profiles|Clear status"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -30001,6 +30530,9 @@ msgstr ""
msgid "Profiles|Connected Accounts"
msgstr ""
+msgid "Profiles|Created%{time_ago}"
+msgstr ""
+
msgid "Profiles|Current path: %{path}"
msgstr ""
@@ -30238,9 +30770,6 @@ msgstr ""
msgid "Profiles|Website url"
msgstr ""
-msgid "Profiles|What's your status?"
-msgstr ""
-
msgid "Profiles|Who you represent or work for."
msgstr ""
@@ -30286,9 +30815,6 @@ msgstr ""
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
-msgid "Profiles|Your status"
-msgstr ""
-
msgid "Profiles|https://website.com"
msgstr ""
@@ -30778,6 +31304,9 @@ msgstr ""
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
msgstr ""
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr ""
+
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr ""
@@ -30808,6 +31337,9 @@ msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr ""
+
msgid "ProjectSettings|Encourage"
msgstr ""
@@ -30931,12 +31463,18 @@ msgstr ""
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr ""
+msgid "ProjectSettings|Monitor"
+msgstr ""
+
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
@@ -30973,6 +31511,9 @@ msgstr ""
msgid "ProjectSettings|Public"
msgstr ""
+msgid "ProjectSettings|Releases"
+msgstr ""
+
msgid "ProjectSettings|Repository"
msgstr ""
@@ -31126,7 +31667,7 @@ msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -31216,6 +31757,9 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr ""
+
msgid "ProjectView|Activity"
msgstr ""
@@ -31738,6 +32282,9 @@ msgstr ""
msgid "ProtectedBranch|Allowed to push:"
msgstr ""
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr ""
+
msgid "ProtectedBranch|Branch"
msgstr ""
@@ -31774,6 +32321,9 @@ msgstr ""
msgid "ProtectedBranch|Protected branches"
msgstr ""
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr ""
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr ""
@@ -31798,6 +32348,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr ""
+
msgid "ProtectedBranch|default"
msgstr ""
@@ -31954,6 +32507,9 @@ msgstr ""
msgid "Pull"
msgstr ""
+msgid "Pull mirroring updated %{time}."
+msgstr ""
+
msgid "Pull requests from fork are not supported"
msgstr ""
@@ -32023,18 +32579,48 @@ msgstr ""
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr ""
+msgid "PushRules|Branch name"
+msgstr ""
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr ""
+
+msgid "PushRules|Commit author's email"
+msgstr ""
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr ""
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr ""
+msgid "PushRules|Maximum file size (MB)"
+msgstr ""
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr ""
+
+msgid "PushRules|Prohibited file names"
+msgstr ""
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr ""
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr ""
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr ""
+msgid "PushRules|Reject unsigned commits"
+msgstr ""
+
+msgid "PushRules|Require expression in commit messages"
+msgstr ""
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr ""
@@ -32185,9 +32771,6 @@ msgstr "了解更多"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
-
msgid "Read more about related epics"
msgstr ""
@@ -32342,9 +32925,6 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr ""
-
msgid "Register device"
msgstr ""
@@ -33220,6 +33800,9 @@ msgstr ""
msgid "Repository mirroring configuration"
msgstr ""
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr ""
@@ -33602,6 +34185,9 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "Rich text"
+msgstr ""
+
msgid "RightSidebar|Copy email address"
msgstr ""
@@ -33623,6 +34209,9 @@ msgstr ""
msgid "Rollback"
msgstr ""
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr ""
+
msgid "Ruby"
msgstr ""
@@ -33843,6 +34432,9 @@ msgstr ""
msgid "Runners|Group"
msgstr ""
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr ""
@@ -33876,9 +34468,6 @@ msgstr ""
msgid "Runners|Members of the %{type} can register runners"
msgstr ""
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
-
msgid "Runners|Name"
msgstr ""
@@ -33888,6 +34477,9 @@ msgstr ""
msgid "Runners|Never contacted:"
msgstr ""
+msgid "Runners|Never expires"
+msgstr ""
+
msgid "Runners|New group runners view"
msgstr ""
@@ -33955,6 +34547,9 @@ msgstr ""
msgid "Runners|Register an instance runner"
msgstr ""
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr ""
@@ -33982,7 +34577,10 @@ msgstr ""
msgid "Runners|Runner assigned to project."
msgstr ""
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
+msgid "Runners|Runner authentication token expiration"
+msgstr ""
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
msgstr ""
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
@@ -34033,6 +34631,9 @@ msgstr ""
msgid "Runners|Runners"
msgstr ""
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr ""
@@ -34045,6 +34646,9 @@ msgstr ""
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr ""
@@ -34075,6 +34679,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr ""
@@ -34112,6 +34719,9 @@ msgstr ""
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Token expiry"
+msgstr ""
+
msgid "Runners|Up to date"
msgstr ""
@@ -34331,9 +34941,6 @@ msgstr ""
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr ""
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr ""
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr ""
@@ -34481,6 +35088,9 @@ msgstr ""
msgid "Search authors"
msgstr ""
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr ""
@@ -34568,6 +35178,9 @@ msgstr ""
msgid "Search projects..."
msgstr ""
+msgid "Search protected branches"
+msgstr ""
+
msgid "Search rate limits"
msgstr ""
@@ -34861,13 +35474,13 @@ msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
@@ -34924,9 +35537,6 @@ msgstr ""
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
-msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ""
@@ -35329,6 +35939,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Detection"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -35341,6 +35954,9 @@ msgstr ""
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr ""
+msgid "SecurityReports|Does not have issue"
+msgstr ""
+
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -35371,12 +35987,18 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
+msgid "SecurityReports|Has issue"
+msgstr ""
+
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Image"
msgstr ""
+msgid "SecurityReports|Issue"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35494,6 +36116,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr ""
@@ -35617,9 +36242,6 @@ msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select Git revision"
msgstr ""
-msgid "Select Page"
-msgstr ""
-
msgid "Select Profile"
msgstr ""
@@ -35665,9 +36287,6 @@ msgstr ""
msgid "Select a template type"
msgstr ""
-msgid "Select a time zone"
-msgstr ""
-
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
@@ -35689,9 +36308,15 @@ msgstr ""
msgid "Select branch"
msgstr ""
+msgid "Select branch or create wildcard"
+msgstr ""
+
msgid "Select branches"
msgstr ""
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr ""
@@ -35737,6 +36362,9 @@ msgstr ""
msgid "Select projects"
msgstr ""
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr ""
@@ -36049,6 +36677,9 @@ msgstr ""
msgid "Set target branch to %{branch_name}."
msgstr ""
+msgid "Set the Draft status"
+msgstr ""
+
msgid "Set the Ready status"
msgstr ""
@@ -36124,18 +36755,15 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
-
-msgid "SetStatusModal|Busy"
-msgstr ""
-
msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Clear status after"
msgstr ""
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "編輯狀態"
@@ -36148,6 +36776,9 @@ msgstr ""
msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Set yourself as busy"
+msgstr ""
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -36747,6 +37378,39 @@ msgstr ""
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr ""
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr ""
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr ""
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr ""
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr ""
+
+msgid "Slack|Connect your GitLab account"
+msgstr ""
+
+msgid "Slack|Create a new issue"
+msgstr ""
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr ""
+
+msgid "Slack|Run a CI/CD job"
+msgstr ""
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr ""
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr ""
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr ""
+
msgid "Slice multiplier"
msgstr ""
@@ -36813,6 +37477,9 @@ msgstr ""
msgid "Snowplow"
msgstr ""
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr ""
@@ -37053,6 +37720,9 @@ msgstr ""
msgid "Sort direction: Descending"
msgstr ""
+msgid "Sort or filter"
+msgstr ""
+
msgid "SortOptions|Blocking"
msgstr ""
@@ -37095,6 +37765,9 @@ msgstr ""
msgid "SortOptions|Last created"
msgstr ""
+msgid "SortOptions|Latest version"
+msgstr ""
+
msgid "SortOptions|Least popular"
msgstr ""
@@ -37155,6 +37828,9 @@ msgstr ""
msgid "SortOptions|Oldest updated"
msgstr ""
+msgid "SortOptions|Oldest version"
+msgstr ""
+
msgid "SortOptions|Popularity"
msgstr ""
@@ -38055,7 +38731,7 @@ msgstr ""
msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr ""
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr ""
msgid "SuggestedColors|Titanium yellow"
msgstr ""
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr ""
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr ""
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr ""
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
+msgid "Suggestion(s)"
+msgstr ""
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr ""
@@ -38118,7 +38806,13 @@ msgstr ""
msgid "SuperSonics|Activation code"
msgstr ""
-msgid "SuperSonics|An error occurred while adding your subscription."
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr ""
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while adding your subscription"
msgstr ""
msgid "SuperSonics|Billable users"
@@ -38127,7 +38821,7 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
msgstr ""
msgid "SuperSonics|Cloud licensing"
@@ -38242,25 +38936,37 @@ msgstr ""
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr ""
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr ""
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr ""
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr ""
-msgid "SuperSonics|Your subscription is expired."
+msgid "SuperSonics|Your subscription is expired"
msgstr ""
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
@@ -39442,6 +40148,9 @@ msgstr ""
msgid "The scan has been created."
msgstr ""
+msgid "The secret is only available when you first create the application."
+msgstr ""
+
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -39649,9 +40358,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
@@ -39919,9 +40625,6 @@ msgstr ""
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr ""
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr ""
-
msgid "This PDF is too large to display. Please download to view."
msgstr ""
@@ -39985,6 +40688,9 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
+msgid "This branch has diverged from upstream."
+msgstr ""
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr ""
@@ -40030,6 +40736,9 @@ msgstr ""
msgid "This deployment is not waiting for approvals."
msgstr ""
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr ""
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr ""
@@ -40078,6 +40787,27 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -40174,6 +40904,9 @@ msgstr ""
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr ""
+
msgid "This is your current session"
msgstr ""
@@ -40390,6 +41123,9 @@ msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
+msgid "This project is mirrored from %{link}."
+msgstr ""
+
msgid "This project is not subscribed to any project pipelines."
msgstr ""
@@ -40402,12 +41138,18 @@ msgstr ""
msgid "This project path either does not exist or you do not have access."
msgstr ""
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr ""
+
msgid "This project will be deleted on %{date}"
msgstr ""
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr ""
@@ -40495,6 +41237,9 @@ msgstr ""
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr ""
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -40836,6 +41581,9 @@ msgstr ""
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
@@ -40869,6 +41617,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr ""
@@ -41088,9 +41839,6 @@ msgstr ""
msgid "Toggle commit list"
msgstr ""
-msgid "Toggle dropdown"
-msgstr ""
-
msgid "Toggle emoji award"
msgstr ""
@@ -41112,9 +41860,6 @@ msgstr ""
msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle the Draft status"
-msgstr ""
-
msgid "Toggle the Performance Bar"
msgstr ""
@@ -41226,6 +41971,9 @@ msgstr ""
msgid "Total cores (CPUs)"
msgstr ""
+msgid "Total issue weight"
+msgstr ""
+
msgid "Total memory (GB)"
msgstr ""
@@ -41355,9 +42103,6 @@ msgstr ""
msgid "Trials|Go back to GitLab"
msgstr ""
-msgid "Trials|Hey there"
-msgstr ""
-
msgid "Trials|Skip Trial"
msgstr ""
@@ -41373,6 +42118,10 @@ msgstr ""
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] ""
+
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 ""
@@ -42054,6 +42803,9 @@ msgstr ""
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr ""
+
msgid "UsageQuota|Artifacts"
msgstr ""
@@ -42096,10 +42848,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42174,9 +42926,6 @@ msgstr ""
msgid "UsageQuota|Seats"
msgstr ""
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr ""
-
msgid "UsageQuota|Shared bits of code and text."
msgstr ""
@@ -42210,7 +42959,7 @@ msgstr ""
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr ""
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
msgstr ""
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
@@ -42550,6 +43299,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -42871,9 +43623,6 @@ msgstr ""
msgid "Users to exclude from the rate limit"
msgstr ""
-msgid "Users were successfully added."
-msgstr ""
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
@@ -42892,7 +43641,34 @@ msgstr ""
msgid "UsersSelect|Unassigned"
msgstr ""
-msgid "Uses GitLab as a lightweight alternative to Sentry."
+msgid "User|Data Analyst"
+msgstr ""
+
+msgid "User|Development Team Lead"
+msgstr ""
+
+msgid "User|Devops Engineer"
+msgstr ""
+
+msgid "User|Other"
+msgstr ""
+
+msgid "User|Product Designer"
+msgstr ""
+
+msgid "User|Product Manager"
+msgstr ""
+
+msgid "User|Security Analyst"
+msgstr ""
+
+msgid "User|Software Developer"
+msgstr ""
+
+msgid "User|Systems Administrator"
+msgstr ""
+
+msgid "Uses GitLab as an alternative to Sentry."
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
@@ -43153,6 +43929,9 @@ msgstr ""
msgid "View blame prior to this change"
msgstr ""
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] ""
@@ -43175,7 +43954,7 @@ msgstr ""
msgid "View eligible approvers"
msgstr ""
-msgid "View epics list"
+msgid "View entire blame"
msgstr ""
msgid "View exposed artifact"
@@ -43597,6 +44376,9 @@ msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|File:"
+msgstr ""
+
msgid "Vulnerability|GitLab Security Report"
msgstr ""
@@ -43618,10 +44400,10 @@ msgstr ""
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr ""
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
+msgid "Vulnerability|Links"
msgstr ""
-msgid "Vulnerability|Links"
+msgid "Vulnerability|Location"
msgstr ""
msgid "Vulnerability|Method"
@@ -43633,6 +44415,9 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
+msgid "Vulnerability|Project:"
+msgstr ""
+
msgid "Vulnerability|Remove identifier row"
msgstr ""
@@ -43660,6 +44445,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Vulnerability|Severity:"
+msgstr ""
+
msgid "Vulnerability|Status"
msgstr ""
@@ -43672,6 +44460,9 @@ msgstr ""
msgid "Vulnerability|Tool"
msgstr ""
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr ""
@@ -43684,6 +44475,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
@@ -43747,6 +44541,12 @@ msgstr ""
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr ""
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr ""
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -43957,6 +44757,9 @@ msgstr ""
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr ""
@@ -43972,12 +44775,18 @@ msgstr ""
msgid "Webhooks|Go to webhooks"
msgstr ""
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr ""
msgid "Webhooks|Job events"
msgstr ""
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr ""
@@ -44002,6 +44811,12 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr ""
@@ -44026,6 +44841,9 @@ msgstr ""
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr ""
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr ""
@@ -44202,12 +45020,6 @@ msgstr ""
msgid "Wiki"
msgstr ""
-msgid "Wiki Page|Rich text"
-msgstr ""
-
-msgid "Wiki Page|Source"
-msgstr ""
-
msgid "Wiki page"
msgstr ""
@@ -44442,6 +45254,12 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add due date"
+msgstr ""
+
+msgid "WorkItem|Add start date"
+msgstr ""
+
msgid "WorkItem|Add task"
msgstr ""
@@ -44473,9 +45291,15 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
+msgid "WorkItem|Dates"
+msgstr ""
+
msgid "WorkItem|Delete %{workItemType}"
msgstr ""
+msgid "WorkItem|Due date"
+msgstr ""
+
msgid "WorkItem|Expand tasks"
msgstr ""
@@ -44542,6 +45366,9 @@ msgstr ""
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Start date"
+msgstr ""
+
msgid "WorkItem|Task"
msgstr ""
@@ -44802,6 +45629,12 @@ msgstr ""
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr ""
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr ""
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr ""
+
msgid "You can create a new %{link}."
msgstr ""
@@ -44925,6 +45758,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr ""
+
msgid "You cannot approve your own deployment."
msgstr ""
@@ -45124,7 +45960,7 @@ msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr ""
msgid "You have unsaved changes"
@@ -45142,7 +45978,7 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
msgstr ""
msgid "You must have maintainer access to force delete a lock"
@@ -45725,6 +46561,9 @@ msgstr ""
msgid "added %{emails}"
msgstr ""
+msgid "added a %{link_type} link"
+msgstr ""
+
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45817,6 +46656,9 @@ msgstr ""
msgid "cURL:"
msgstr ""
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -45862,6 +46704,9 @@ msgstr ""
msgid "cannot be a date in the past"
msgstr ""
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr ""
@@ -46118,6 +46963,9 @@ msgstr ""
msgid "ciReport|Full Report"
msgstr ""
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr ""
@@ -46273,6 +47121,9 @@ msgstr ""
msgid "comment"
msgstr ""
+msgid "commented"
+msgstr ""
+
msgid "commented on %{link_to_project}"
msgstr ""
@@ -46318,6 +47169,9 @@ msgstr ""
msgid "created %{timeAgo} by %{author}"
msgstr ""
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr ""
+
msgid "created by"
msgstr ""
@@ -46633,9 +47487,6 @@ msgstr ""
msgid "is not allowed. Please use your regular email address."
msgstr ""
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
-
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
@@ -46726,6 +47577,10 @@ msgstr ""
msgid "limit of %{project_limit} reached"
msgstr ""
+msgid "line"
+msgid_plural "lines"
+msgstr[0] ""
+
msgid "load it anyway"
msgstr ""
@@ -46761,6 +47616,9 @@ msgstr ""
msgid "metric_id must be unique across a project"
msgstr ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -47126,6 +47984,9 @@ msgstr ""
msgid "must match %{association}.project_id"
msgstr ""
+msgid "must not contain commonly used combinations of words and letters"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -47207,9 +48068,6 @@ msgstr ""
msgid "organizations can only be added to root groups"
msgstr ""
-msgid "other card matches"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
@@ -47349,6 +48207,9 @@ msgstr "移除權é‡"
msgid "removed"
msgstr ""
+msgid "removed a %{link_type} link"
+msgstr ""
+
msgid "removed a Zoom call from this issue"
msgstr ""
@@ -47380,6 +48241,10 @@ msgstr ""
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr ""
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -47488,6 +48353,9 @@ msgstr ""
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr ""
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr ""
@@ -47554,6 +48422,10 @@ msgstr ""
msgid "uploads"
msgstr ""
+msgid "user"
+msgid_plural "users"
+msgstr[0] ""
+
msgid "user avatar"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 0a2a37cba2a..7b99907ef1a 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: 16\n"
-"PO-Revision-Date: 2022-09-11 06:20\n"
+"PO-Revision-Date: 2022-10-10 13:59\n"
msgid " %{start} to %{end}"
msgstr " %{start} 到 %{end}"
@@ -125,6 +125,10 @@ msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] "%d ä½é¡å¤–çš„æ交者"
+msgid "%d additional user"
+msgid_plural "%d additional users"
+msgstr[0] "%d ä½é¡å¤–的使用者"
+
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] "%d ä½æ ¸å‡†è€…"
@@ -401,7 +405,7 @@ msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link}將 %{original_issue}複製到 %{new_issue}。"
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
-msgstr "%{author_link} 複製了 %{original_issue}。您沒有權é™å­˜å–新專案。"
+msgstr "%{author_link} 複製了 %{original_issue},您沒有權é™å­˜å–新專案。"
msgid "%{author_link} wrote:"
msgstr "%{author_link} 說:"
@@ -551,13 +555,13 @@ msgid "%{duration}ms"
msgstr "%{duration} 毫秒"
msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
-msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試æ€é¸æ­¤æ交。"
+msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試æ€é¸ (Cherry-pick) æ­¤æ交。"
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試建立新目錄。"
msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
-msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試還原此æ交。"
+msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試還原 (Revert) æ­¤æ交。"
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
msgstr "%{edit_in_new_fork_notice} è«‹å†æ¬¡å˜—試上傳檔案。"
@@ -707,7 +711,7 @@ msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr "%{group_level_name} 群組ä¸å…許 %{level_name} 。"
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
-msgstr "由於分å‰çš„æºé …ç›®å¯è¦‹æ€§è¼ƒä½Žï¼Œå› æ­¤ä¸å…許使用 %{level_name}。"
+msgstr "由於分å‰ï¼ˆFork)的來æºå°ˆæ¡ˆå¯è¦‹æ€§è¼ƒä½Žï¼Œå› æ­¤ä¸å…許使用 %{level_name}。"
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} 以å…許此åˆä½µè«‹æ±‚在準備好時被åˆä½µã€‚"
@@ -931,10 +935,6 @@ msgstr "%{spanStart}æ–¼%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} 到 %{end}"
-msgid "%{strongOpen}%{errors}%{strongClose} point"
-msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] "%{strongOpen}%{errors}%{strongClose} 點"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}警告:%{strongClose} SAML 群組連çµæœƒä½¿ GitLab 自動從群組中移除æˆå“¡ã€‚"
@@ -965,6 +965,10 @@ msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgstr[0] "%{strong_start}%{count}ä½æˆå“¡%{strong_end}需核准æ‰å¯åˆä½µã€‚任何具有開發人員或更高權é™çš„使用者å¯é€²è¡Œæ ¸å‡†ã€‚"
+msgid "%{strong_start}%{errors}%{strong_end} point"
+msgid_plural "%{strong_start}%{errors}%{strong_end} points"
+msgstr[0] "%{strong_start}%{errors}%{strong_end} 點"
+
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} 專案儲存"
@@ -994,9 +998,6 @@ msgstr "%{template_project_id} 為未知或無效"
msgid "%{text} is available"
msgstr "%{text} å¯ç”¨"
-msgid "%{timebox_name} should belong either to a project or a group."
-msgstr "%{timebox_name} 應該屬於一個專案或一個群組。"
-
msgid "%{timebox_type} does not support burnup charts"
msgstr "%{timebox_type}ä¸æ”¯æ´ç‡ƒç›¡åœ–"
@@ -1030,6 +1031,9 @@ msgstr "%{total} 剩餘議題權é‡"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "ç™¼ç¾ %{total} 個警告訊æ¯ï¼šæ­£åœ¨é¡¯ç¤ºé–‹é ­çš„ %{warningsDisplayed} 個警告訊æ¯"
+msgid "%{type} must be a %{help_link}"
+msgstr ""
+
msgid "%{type} only supports %{name} name"
msgstr "%{type} åªæ”¯æŒ %{name} åå­—"
@@ -1051,12 +1055,15 @@ msgstr "%{user_name} (%{user_username}) 已從 %{project}çš„å‡ç´šç­–略中刪é™
msgid "%{user_name} profile page"
msgstr "%{user_name} 的個人資料"
-msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr "%{username} 更改了åˆä½µè«‹æ±‚ %{mr_link}"
-
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} 在您的 %{host} GitLab 實例上請求了一個使用者帳號:"
+msgid "%{username} marked merge request %{mr_link} as draft"
+msgstr "%{username} å°‡åˆä½µè«‹æ±‚ %{mr_link} 標記為è‰ç¨¿"
+
+msgid "%{username} marked merge request %{mr_link} as ready"
+msgstr "%{username} å°‡åˆä½µè«‹æ±‚ %{mr_link} 標記為已準備好"
+
msgid "%{username}'s avatar"
msgstr "%{username} 的大頭貼"
@@ -1078,6 +1085,12 @@ msgstr "%{value} 秒"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} 耗時 %{time_spent_value}"
+msgid "%{verb} this %{noun} as a draft."
+msgstr "%{verb} 該 %{noun} 為è‰ç¨¿ã€‚"
+
+msgid "%{verb} this %{noun} as ready."
+msgstr "%{verb} 該 %{noun} 為準備就緒。"
+
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…許您在群組或專案中發é€é€šçŸ¥è‡³ web 應用程å¼ä½œç‚ºäº‹ä»¶çš„回應。"
@@ -1535,9 +1548,6 @@ msgstr "%{name} 的新版本 %{tag} 已經發布。請存å–發布版é é¢äº†è§
msgid "A new email address has been added to your GitLab account: %{email}"
msgstr "一個新的電å­éƒµä»¶åœ°å€å·²å¢žåŠ åˆ°æ‚¨çš„ GitLab 帳號: %{email}"
-msgid "A new impersonation token has been created."
-msgstr "已建立新的身份模擬權æ–。"
-
msgid "A new personal access token has been created"
msgstr "已建立一個新的個人存å–權æ–(令牌)"
@@ -1556,6 +1566,15 @@ msgstr "éžæ©Ÿå¯†æ€§å·¥ä½œé …ä¸èƒ½æœ‰æ©Ÿå¯†æ€§çš„父級。"
msgid "A page with that title already exists"
msgstr "該標題é é¢å·²å­˜åœ¨"
+msgid "A personal access token has been revoked"
+msgstr "個人存å–權æ–已撤銷"
+
+msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
+msgstr "一個å為 %{code_start}%{token_name}%{code_end} 的個人存å–權æ–已被撤銷。"
+
+msgid "A personal access token, named %{token_name}, has been revoked."
+msgstr "一個å為 %{token_name} 的個人存å–權æ–已被撤銷。"
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "ç´” HTML 網站使用 NetLify æ¥å–代 Gitlab çš„ CI/CD,但ä»ä¿±å‚™å®Œæ•´çš„ GitLab 其他優秀功能"
@@ -1584,7 +1603,7 @@ msgid "A ready-to-go template for use with iOS Swift apps"
msgstr "é©ç”¨æ–¼ iOS Swift 應用程å¼çš„樣æ¿æº–備就緒"
msgid "A rebase is already in progress."
-msgstr "é‡è¨‚基底作業已在進行中。"
+msgstr "變基 (Rebase) 作業已在進行中。"
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "你的帳號已被從下列的IP登入: %{ip}"
@@ -2067,7 +2086,7 @@ msgid "Add a table"
msgstr "加入表格"
msgid "Add a timeline event to incident"
-msgstr ""
+msgstr "加入一個時間線事件到事故"
msgid "Add a title..."
msgstr "新增標題..."
@@ -2163,10 +2182,10 @@ msgid "Add label(s)"
msgstr "加入標記 (label)"
msgid "Add labels"
-msgstr ""
+msgstr "加入標記"
msgid "Add license"
-msgstr ""
+msgstr "加入授權憑證"
msgid "Add list"
msgstr "加入列表"
@@ -2237,12 +2256,6 @@ msgstr "加入主題到專案以幫助使用者尋找。"
msgid "Add trigger"
msgstr "新增觸發器"
-msgid "Add user(s) to the group:"
-msgstr "å‘群組加入使用者:"
-
-msgid "Add users to group"
-msgstr "å‘群組加入使用者"
-
msgid "Add variable"
msgstr "新增/變數"
@@ -2340,7 +2353,7 @@ msgid "Adds a Zoom meeting."
msgstr "加入 Zoom 會議."
msgid "Adds a timeline event to incident."
-msgstr ""
+msgstr "增加一個時間線事件到事故."
msgid "Adds a to do."
msgstr "新增待辦事項。"
@@ -2604,7 +2617,7 @@ msgid "AdminSettings|Enable Service Ping"
msgstr "啟用 Service Ping"
msgid "AdminSettings|Enable collection of application metrics. Restart required. %{link_start}Learn how to export metrics to Prometheus%{link_end}."
-msgstr ""
+msgstr "啟用應用程å¼æŒ‡æ¨™æ”¶é›†ï¼Œéœ€è¦é‡å•Ÿã€‚ %{link_start}了解如何將指標導出到 Prometheus%{link_end}。"
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
msgstr "啟用 kuromoji 自訂分æžå™¨: 索引建立中"
@@ -2636,9 +2649,15 @@ msgstr "動態權æ–"
msgid "AdminSettings|Git abuse rate limit"
msgstr "Git 濫用率é™åˆ¶"
+msgid "AdminSettings|Group runners expiration"
+msgstr "群組執行器éŽæœŸ"
+
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr "我已閱讀並åŒæ„ Let's Encrypt çš„%{link_start}æœå‹™æ¢æ¬¾%{link_end}(PDF)。"
+msgid "AdminSettings|If no unit is written, it defaults to seconds. For example, these are all equivalent: %{oneDayInSeconds}, %{oneDayInHoursHumanReadable}, or %{oneDayHumanReadable}. Minimum value is two hours. %{linkStart}Learn more.%{linkEnd}"
+msgstr "如果沒有寫入單ä½ï¼Œå‰‡é è¨­ç‚ºç§’。例如,這些都是相等的:%{oneDayInSeconds}ã€%{oneDayInHoursHumanReadable} 或 %{oneDayHumanReadable}。最å°å€¼ç‚ºå…©å°æ™‚, %{linkStart}了解更多。%{linkEnd}"
+
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}。這ä¸æœƒå½±éŸ¿ç¾æœ‰çš„檔案庫。"
@@ -2651,6 +2670,9 @@ msgstr "匯入來æº"
msgid "AdminSettings|Inactive project deletion"
msgstr "ä¸æ´»èºå°ˆæ¡ˆç§»é™¤"
+msgid "AdminSettings|Instance runners expiration"
+msgstr "æœå‹™å¯¦é«”執行器éŽæœŸ"
+
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr "ä¿ç•™æœ€æ–°ä¸”æˆåŠŸçš„æµæ°´ç·šä¸­æ‰€æœ‰ä»»å‹™çš„最新產物"
@@ -2672,6 +2694,9 @@ msgstr " 作業å¯æŒæœ‰çš„ DAG ä¾è³´æœ€å¤§æ•¸"
msgid "AdminSettings|Maximum number of active pipelines per project"
msgstr "æ¯å€‹å°ˆæ¡ˆçš„最大活動æµæ°´ç·šæ•¸é‡"
+msgid "AdminSettings|Maximum number of custom domains per project"
+msgstr "æ¯å€‹å°ˆæ¡ˆçš„最大自定義域數é‡"
+
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
msgstr "在一個æµæ°´ç·šä¸­çš„最大作業數"
@@ -2708,6 +2733,9 @@ msgstr "負載é è¦½"
msgid "AdminSettings|Project export"
msgstr "匯出專案"
+msgid "AdminSettings|Project runners expiration"
+msgstr "專案執行器éŽæœŸ"
+
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "é è¨­ä¿è­· CI / CD 變數"
@@ -2759,9 +2787,21 @@ msgstr "å°‡ CI / CD 模æ¿è¨­å®šç‚ºå¯¦ä¾‹ä¸­æ‰€æœ‰å°ˆæ¡ˆçš„å¿…è¦æµæ°´ç·šé…ç½®
msgid "AdminSettings|Set limit to 0 to disable it."
msgstr "å°‡é™åˆ¶è¨­å®šç‚º 0 以åœç”¨å®ƒã€‚"
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered group runners."
+msgstr "為新註冊的群組執行器設定身份驗證權æ–éŽæœŸæ™‚間。"
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered instance runners. Authentication tokens are automatically reset at these intervals."
+msgstr "為新註冊的æœå‹™å¯¦é«”執行器設定身份驗證權æ–éŽæœŸæ™‚間,身份驗證權æ–會在這些間隔時間自動é‡ç½®ã€‚"
+
+msgid "AdminSettings|Set the expiration time of authentication tokens of newly registered project runners."
+msgstr "為新註冊的專案執行器設定身份驗證權æ–éŽæœŸæ™‚間。"
+
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
msgstr "為實例中創建的新存儲庫的默èªåˆ†æ”¯è¨­ç½®åˆå§‹å稱和ä¿è­·ã€‚"
+msgid "AdminSettings|Set the maximum number of GitLab Pages custom domains per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
+msgstr "設定æ¯å€‹å°ˆæ¡ˆçš„ GitLab é é¢è‡ªå®šç¾©åŸŸçš„最大數é‡ï¼ˆ0 表示無é™åˆ¶ï¼‰ã€‚ %{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 "設定æ¯å€‹å°ˆæ¡ˆçš„ GitLab 網é çš„最大容é‡ï¼ˆ0 表示無é™åˆ¶ï¼‰ã€‚%{link_start}了解更多。%{link_end}"
@@ -2948,6 +2988,9 @@ msgstr "å·²å°éŽ–"
msgid "AdminUsers|Blocking user has the following effects:"
msgstr "å°éŽ–使用者具有以下效果:"
+msgid "AdminUsers|Bot"
+msgstr "機器人"
+
msgid "AdminUsers|Can create group"
msgstr "å¯ä»¥å»ºç«‹ç¾¤çµ„"
@@ -3287,9 +3330,21 @@ msgstr "進階匯出é¸é …"
msgid "AdvancedSearch|Elasticsearch version not compatible"
msgstr "Elasticsearch 版本ä¸ç›¸å®¹"
+msgid "AdvancedSearch|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 "AdvancedSearch|Pause indexing and upgrade Elasticsearch to a supported version."
+msgstr ""
+
+msgid "AdvancedSearch|Reindex recommended"
+msgstr ""
+
msgid "AdvancedSearch|Reindex required"
msgstr "需è¦é‡æ–°å»ºç«‹ç´¢å¼•"
+msgid "AdvancedSearch|You are using outdated code search mappings. To improve code search quality, we recommend you use %{reindexing_link_start}zero-downtime reindexing%{link_end} or %{recreate_link_start}re-create your index%{link_end}."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "密碼更新æˆåŠŸå¾Œï¼Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘至登入é é¢ã€‚"
@@ -3669,7 +3724,7 @@ msgid "All"
msgstr "全部"
msgid "All %{replicableType} are being scheduled for %{action}"
-msgstr "全部 %{replicableType} 計劃為 %{action}"
+msgstr "所有 %{replicableType} 都被排入 %{action} 排程"
msgid "All (default)"
msgstr "全部 (é è¨­)"
@@ -3716,6 +3771,9 @@ msgstr "所有åˆä½µè«‹æ±‚ä¾è³´é—œä¿‚å‡å·²åˆä½µ"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr "所有路徑都相å°æ–¼ GitLab URL。ä¸åŒ…括%{relative_url_link_start}ç›¸å° URL%{relative_url_link_end}。"
+msgid "All project members"
+msgstr "專案的所有æˆå“¡"
+
msgid "All projects"
msgstr "所有專案"
@@ -3791,6 +3849,9 @@ msgstr "å…許此金鑰推é€åˆ°æ­¤ç‰ˆæœ¬åº«"
msgid "Allow use of licensed EE features"
msgstr "å…許使用許å¯çš„ EE 功能"
+msgid "Allow users to create top-level groups"
+msgstr "å…許使用者創建最高階群組"
+
msgid "Allow users to dismiss the broadcast message"
msgstr "å…許使用者忽略廣播訊æ¯"
@@ -4079,9 +4140,6 @@ msgstr "加載此é é¢çš„æŸéƒ¨åˆ†æ™‚發生錯誤。"
msgid "An error occurred while loading all the files."
msgstr "載入所有檔案時發生錯誤。"
-msgid "An error occurred while loading branch rules. Please try again."
-msgstr "載入分支è¦å‰‡æ™‚發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
-
msgid "An error occurred while loading chart data"
msgstr "載入圖表資料時發生錯誤"
@@ -4228,7 +4286,7 @@ msgid "An error occurred while trying to generate the report. Please try again l
msgstr "試圖製作報告時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
msgid "An error occurred while trying to render the content editor. Please try again."
-msgstr ""
+msgstr "嘗試顯示內容編輯器時發生錯誤,請ç¨å€™å†è©¦ã€‚"
msgid "An error occurred while trying to run a new pipeline for this merge request."
msgstr "嘗試執行此åˆä½µè«‹æ±‚çš„æ–°æµæ°´ç·šæ™‚發生錯誤。"
@@ -4326,6 +4384,9 @@ msgstr "發生未知的錯誤"
msgid "Analytics"
msgstr "分æž"
+msgid "AnalyticsDashboards|Dashboards"
+msgstr ""
+
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "分æžå·²çŸ¥æ¼æ´žçš„ä¾è³´é—œä¿‚"
@@ -4547,6 +4608,9 @@ msgstr "已啟用註冊"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
msgstr "使用者註冊後顯示的文字內容。å¯ä»¥ä½¿ç”¨ Markdown。"
+msgid "ApplicationSettings|This feature is only available on GitLab.com"
+msgstr "該功能僅å¯ä½¿ç”¨æ–¼ GitLab.com"
+
msgid "ApplicationSettings|This option is only available on GitLab.com"
msgstr "該é¸é …僅å¯ä½¿ç”¨æ–¼ GitLab.com"
@@ -5182,6 +5246,9 @@ msgstr[0] "加入%d個附件"
msgid "Attaching the file failed."
msgstr "加入附件失敗。"
+msgid "Attempted sign in to %{host} using a wrong two-factor authentication code"
+msgstr "ä¼åœ–使用錯誤的雙因å­èº«ä»½é©—證碼登入 %{host}"
+
msgid "Audit Events"
msgstr "審計事件"
@@ -5852,6 +5919,9 @@ msgstr "以下是 %{link_to_gitlab_pages}的設置。"
msgid "Below you will find all the groups that are public."
msgstr "您將在下é¢æ‰¾åˆ°æ‰€æœ‰å…¬é–‹çš„群組。"
+msgid "Beta"
+msgstr "測試版"
+
msgid "Bi-weekly code coverage"
msgstr "雙周代碼覆蓋率"
@@ -6173,8 +6243,8 @@ msgstr "直接會員"
msgid "Billing|Enter at least three characters to search."
msgstr "請輸入最少 3 個字元來æœå°‹ã€‚"
-msgid "Billing|Explore all plans"
-msgstr "查看所有計劃"
+msgid "Billing|Explore paid plans"
+msgstr "ç€è¦½ä»˜è²»è¨ˆåŠƒ"
msgid "Billing|Export list"
msgstr "匯出清單"
@@ -6210,6 +6280,9 @@ msgstr "切æ›åº§ä½ï¼ˆtoggle seat)詳細資訊"
msgid "Billing|Type %{username} to confirm"
msgstr "輸入 %{username} 以確èª"
+msgid "Billing|Unlimited members during your trial"
+msgstr "試用期間æˆå“¡æ•¸é‡ä¸é™"
+
msgid "Billing|User was successfully removed"
msgstr "å·²æˆåŠŸåˆªé™¤ä½¿ç”¨è€…"
@@ -6232,7 +6305,7 @@ msgid "Bitbucket import"
msgstr "從 Bitbucket 匯入"
msgid "Blame"
-msgstr "咎責"
+msgstr "責任歸屬(blame)"
msgid "BlobViewer|View on %{environmentName}"
msgstr "BlobViewer|在 %{environmentName}上檢視"
@@ -6525,6 +6598,9 @@ msgstr "正在加載å²è©©"
msgid "Bold text"
msgstr "粗體字"
+msgid "Bot"
+msgstr "機器人"
+
msgid "Both SSH and HTTP(S)"
msgstr "SSH 和 HTTP(S)"
@@ -6561,33 +6637,78 @@ msgstr "分支未被載入 - %{branchId}"
msgid "Branch rules"
msgstr "分支è¦å‰‡"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/ are supported"
+msgstr ""
+
msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
msgstr "%{linkStart}è¬ç”¨å­—å…ƒ%{linkEnd} å¯æ”¯æ´å½¢å¦‚ *-stable or production/* 。"
+msgid "BranchRules|All branches"
+msgstr ""
+
+msgid "BranchRules|All users with push access are allowed to force push."
+msgstr ""
+
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
msgstr "å…許所有具有推é€å­˜å–權é™çš„使用者%{linkStart}強制推é€%{linkEnd}。"
msgid "BranchRules|Allowed to merge"
msgstr "å…許åˆä½µ"
+msgid "BranchRules|Allowed to merge (%{total})"
+msgstr ""
+
msgid "BranchRules|Allowed to push"
msgstr "å…許推é€"
+msgid "BranchRules|Allowed to push (%{total})"
+msgstr ""
+
msgid "BranchRules|An error occurred while fetching branches."
msgstr "æ“·å–分支時發生錯誤。"
+msgid "BranchRules|Approvals"
+msgstr ""
+
msgid "BranchRules|Branch"
msgstr "分支"
+msgid "BranchRules|Branch name or pattern"
+msgstr ""
+
+msgid "BranchRules|Branch rules details"
+msgstr "分支è¦å‰‡è©³ç´°è³‡è¨Š"
+
msgid "BranchRules|Create wildcard: %{searchTerm}"
msgstr "建立è¬ç”¨å­—元:%{searchTerm}"
+msgid "BranchRules|Details"
+msgstr ""
+
+msgid "BranchRules|Force push"
+msgstr ""
+
+msgid "BranchRules|Force push is not allowed."
+msgstr ""
+
+msgid "BranchRules|Groups"
+msgstr "群組"
+
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
msgstr "維æŒç©©å®šåˆ†æ”¯çš„安全並強制開發者使用åˆä½µè«‹æ±‚。%{linkStart}什麼是å—ä¿è­·çš„分支?%{linkEnd}"
+msgid "BranchRules|Manage in Protected Branches"
+msgstr ""
+
+msgid "BranchRules|No data to display"
+msgstr ""
+
msgid "BranchRules|No matching results"
msgstr "無符åˆçš„çµæžœ"
+msgid "BranchRules|Protect branch"
+msgstr ""
+
msgid "BranchRules|Protections"
msgstr "ä¿è­·"
@@ -6597,11 +6718,23 @@ msgstr "拒絕程å¼ç¢¼æŽ¨é€è®Šæ›´åˆ—æ–¼ CODEOWNERS 檔案中的檔案。"
msgid "BranchRules|Require approval from code owners."
msgstr "需è¦ç¨‹å¼ç¢¼æ“有者的批准。"
-msgid "BranchRules|default"
+msgid "BranchRules|Roles"
+msgstr "角色"
+
+msgid "BranchRules|Status checks"
msgstr ""
+msgid "BranchRules|Target Branch"
+msgstr "目標分支"
+
+msgid "BranchRules|Users"
+msgstr "使用者"
+
+msgid "BranchRules|default"
+msgstr "é è¨­"
+
msgid "BranchRules|protected"
-msgstr ""
+msgstr "å—ä¿è­·çš„"
msgid "Branches"
msgstr "分支"
@@ -6769,7 +6902,7 @@ msgid "Browse templates"
msgstr "ç€è¦½ç¯„本"
msgid "Build cannot be erased"
-msgstr ""
+msgstr "建置無法抹除"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "抓å–產物時發生錯誤"
@@ -6897,6 +7030,9 @@ msgstr "需關è¯åˆ°ä¸€å€‹ç¾¤çµ„,但目å‰æœ‰ä¸€å€‹é—œè¯çš„專案"
msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr "批次匯入|é æœŸç‚ºé—œè¯çš„專案,但目å‰ç‚ºé—œè¯çš„群組"
+msgid "BulkImport|invalid entity source type"
+msgstr "無效的實體來æºé¡žåž‹"
+
msgid "BulkImport|must be a group"
msgstr "批次匯入|必須是一個群組"
@@ -7069,6 +7205,9 @@ msgstr "所有項目é è¨­ä½¿ç”¨Auto DevOpsæµæ°´ç·š"
msgid "CICD|Deployment strategy"
msgstr "部署策略"
+msgid "CICD|Enable feature to limit job token access to the following projects."
+msgstr "啟用功能以é™åˆ¶ä½œæ¥­æ¬Šæ–(令牌)å°ä¸‹åˆ—專案的存å–。"
+
msgid "CICD|Jobs"
msgstr "作業"
@@ -7078,8 +7217,8 @@ msgstr "é™åˆ¶"
msgid "CICD|Limit CI_JOB_TOKEN access"
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 "é¸æ“‡å¯ä»¥é€šéŽ API 訪å•çš„專案來驗證此項目的 CI_JOB_TOKEN CI/CD 變é‡ã€‚"
+msgid "CICD|Select the projects that 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. %{linkStart}Learn more.%{linkEnd}"
+msgstr "é¸æ“‡å¯ä»¥é€šéŽä½¿ç”¨è©²å°ˆæ¡ˆçš„ CI_JOB_TOKEN CI/CD 變數驗證的 API å­˜å–請求的專案。 åœç”¨æ­¤åŠŸèƒ½æœƒå¸¶ä¾†å®‰å…¨é¢¨éšªï¼Œå› ç‚ºæœªç¶“授權的專案å¯èƒ½æœƒå˜—試å–得活動權æ–(令牌)ä¸¦å­˜å– API。 %{linkStart}了解更多。%{linkEnd}"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
msgstr "Auto DevOps æµæ°´ç·šé è¨­åœ¨æ²’有 CI/CD é…置文件的所有專案中é‹è¡Œã€‚%{link_start}什麼是 Auto DevOps?%{link_end}"
@@ -7339,8 +7478,8 @@ msgstr "ä¸èƒ½å‡ç´šå•é¡Œï¼Œå› ç‚ºå®ƒä¸å±¬æ–¼ä¸€å€‹ç¾¤çµ„。"
msgid "Cannot promote issue due to insufficient permissions."
msgstr "由於權é™ä¸è¶³ï¼Œç„¡æ³•å‡ç´šè­°é¡Œã€‚"
-msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr "無法通éŽå…§éƒ¨ID引用群組%{timebox_type}ï¼"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "無法通éŽå…§éƒ¨ ID 引用群組里程碑ï¼"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "無法顯示é è¦½ã€‚如需é è¦½ï¼Œè‰åœ–文件必須具有Sketch 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
@@ -7460,10 +7599,10 @@ msgid "ChangeReviewer|Unassigned"
msgstr "未指派"
msgid "ChangeTypeAction|Cherry-pick"
-msgstr "Cherry-pick"
+msgstr "æ€é¸ (Cherry-pick)"
msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
-msgstr "GitLab å°‡åœ¨ä½ çš„åˆ†å‰ (fork) 中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
+msgstr "GitLab 將在你的分å‰ï¼ˆFork)中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
msgid "ChangeTypeAction|Pick into branch"
msgstr "é¸æ“‡åˆ†æ”¯"
@@ -7472,10 +7611,10 @@ msgid "ChangeTypeAction|Pick into project"
msgstr "é¸æ“‡å°ˆæ¡ˆ"
msgid "ChangeTypeAction|Revert"
-msgstr "還原"
+msgstr "還原 (Revert) "
msgid "ChangeTypeAction|Revert in branch"
-msgstr "還原分支"
+msgstr "從分支還原 (Revert) "
msgid "ChangeTypeAction|Search branches"
msgstr "æœå°‹åˆ†æ”¯"
@@ -7493,7 +7632,7 @@ msgid "ChangeTypeAction|Switch project"
msgstr "切æ›å°ˆæ¡ˆ"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
-msgstr "這將建立一個新的æ交, 來還原ç¾æœ‰çš„變更。"
+msgstr "這將建立一個新的æ交, 來還原 (Revert) ç¾æœ‰çš„變更。"
msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
msgstr "åˆä½µè«‹æ±‚已開啟,變更將被æ交到%{branchName}。"
@@ -7511,7 +7650,7 @@ msgid "Changed reviewer(s)."
msgstr "已變更審閱者。"
msgid "Changed squash option to %{squash_option}"
-msgstr "已變更壓縮é¸é …為 %{squash_option}"
+msgstr "已變更壓縮 (Squash) é¸é …為 %{squash_option}"
msgid "Changed the title to \"%{title_param}\"."
msgstr "已將標題變更為「%{title_param}ã€ã€‚"
@@ -7534,6 +7673,9 @@ msgstr "將標題變更為「%{title_param}ã€ã€‚"
msgid "Changes to the title have not been saved"
msgstr "標題變更尚未儲存"
+msgid "Changes:"
+msgstr "變更:"
+
msgid "Changing any setting here requires an application restart"
msgstr "更改此處的任何設定都需è¦é‡æ–°å•Ÿå‹•æ‡‰ç”¨ç¨‹å¼"
@@ -7876,10 +8018,10 @@ msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr "x %{quantity} %{units} æ¯åŒ… ="
msgid "Cherry-pick this commit"
-msgstr "Cherry-pick 該æ交"
+msgstr "æ€é¸ (Cherry-pick) 該æ交"
msgid "Cherry-pick this merge request"
-msgstr "Cherry-pick 該åˆä½µè«‹æ±‚"
+msgstr "æ€é¸ (Cherry-pick) 該åˆä½µè«‹æ±‚"
msgid "Child"
msgstr "å­ç´š"
@@ -8198,10 +8340,10 @@ msgid "Clientside DSN"
msgstr "客戶端 DSN"
msgid "Clone"
-msgstr "複製"
+msgstr "克隆 (Clone) "
msgid "Clone repository"
-msgstr "複製版本庫"
+msgstr "克隆 (Clone) 版本庫"
msgid "Clone this issue"
msgstr "複製該議題"
@@ -8210,22 +8352,22 @@ msgid "Clone with %{http_label}"
msgstr "使用 %{http_label} 複製"
msgid "Clone with %{protocol}"
-msgstr "使用 %{protocol} 克隆"
+msgstr "以 %{protocol} 複製"
msgid "Clone with KRB5"
msgstr "以 KRB5 複製"
msgid "Clone with SSH"
-msgstr "以 SSH 複製"
+msgstr "以 SSH 克隆 (Clone)"
msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
-msgstr "CloneIssue|由於權é™ä¸è¶³ï¼Œç„¡æ³•è¤‡è£½ç‰ˆæœ¬åº«è­°é¡Œ (issue)ï¼"
+msgstr "於權é™ä¸è¶³ï¼Œç„¡æ³•è¤‡è£½ç‰ˆæœ¬åº«è­°é¡Œ (issue)ï¼"
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
-msgstr "CloneIssue|無法將議題(issue)複製到目標專案,因為正在等待刪除。"
+msgstr "無法將議題(issue)複製到目標專案,因為正在等待刪除。"
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
-msgstr "CloneIssue|無法複製“%{issue_type}â€é¡žåž‹çš„議題。"
+msgstr "無法複製“%{issue_type}â€é¡žåž‹çš„議題。"
msgid "Cloned this issue to %{path_to_project}."
msgstr "將此議題(issue)複製到%{path_to_project}。"
@@ -8545,6 +8687,9 @@ msgstr "ClusterAgents|您確定è¦åˆªé™¤æ­¤ä»£ç†å—Žï¼Ÿæ‚¨ç„¡æ³•æ’¤æ¶ˆæ­¤æ“作ã
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr "ClusterAgents|您確定è¦æ’¤éŠ·è©²ä»¤ç‰Œ(權æ–)å—Ž? 該動作無法回復。"
+msgid "ClusterAgents|CI/CD workflow with restricted access"
+msgstr " å·²é™åˆ¶å­˜å–çš„ CI/CD 工作æµç¨‹"
+
msgid "ClusterAgents|Certificate"
msgstr "ClusterAgents|憑證"
@@ -8644,6 +8789,9 @@ msgstr "ClusterAgents|如何更新代ç†ï¼Ÿ"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr "使用 Helm (建議) 進行安è£"
+msgid "ClusterAgents|Integration Status"
+msgstr "æ•´åˆç‹€æ…‹"
+
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "上次已在 %{timeAgo} 連接。"
@@ -8669,6 +8817,9 @@ msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
msgstr[0] "ClusterAgents|éŽåŽ»%d天內未發生任何活動"
+msgid "ClusterAgents|No agent access token"
+msgstr "沒有代ç†å­˜å–權æ–"
+
msgid "ClusterAgents|No agents"
msgstr "ClusterAgents|無代ç†äºº"
@@ -8678,6 +8829,9 @@ msgstr "沒有通éŽå¢é›†è­‰æ›¸é€£æŽ¥çš„å¢é›†"
msgid "ClusterAgents|Not connected"
msgstr "ClusterAgents|未連線"
+msgid "ClusterAgents|Premium"
+msgstr "高級"
+
msgid "ClusterAgents|Recommended"
msgstr "ClusterAgents|建議"
@@ -8744,6 +8898,9 @@ msgstr "ClusterAgents|令牌(權æ–)被 %{userName} 撤回"
msgid "ClusterAgents|Unknown user"
msgstr "ClusterAgents|未知使用者"
+msgid "ClusterAgents|Valid access token"
+msgstr "有效的存å–權æ–"
+
msgid "ClusterAgents|View all %{number} agents"
msgstr "ClusterAgent|檢視全部 %{number} 個代ç†äºº"
@@ -9081,10 +9238,10 @@ msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "ç”¨æ–¼å­˜å– Kubernetes API çš„ URL。"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "基於證書的 Kubernetes æ•´åˆå·²è¢«æ£„用,將於 2023 å¹´ 2 月關閉。請 %{linkStart}é·ç§»åˆ° GitLab 代ç†çš„ Kubernetes%{linkEnd} 或è¯ç¹« GitLab 支æ´æœå‹™ã€‚"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "基於憑證的 Kubernetes æ•´åˆå·²è¢«æ£„用,將於 2023 å¹´ 2 月關閉。請 %{linkStart}é·ç§»åˆ° Kubernetes çš„ GitLab 代ç†%{linkEnd}。"
msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
msgstr "採用憑證將å¢é›†é€£æŽ¥åˆ° GitLab 的方法將於 14.5 版本%{linkStart}棄用%{linkEnd}。"
@@ -9411,6 +9568,9 @@ msgstr "æ交到"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr "您é¸æ“‡çš„æ交顯示在此處。請至第一個é ç°½é¸æ“‡æ交以添加到此åˆä½µè«‹æ±‚。"
+msgid "Commits:"
+msgstr "æ交:"
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "å–å¾—åˆä½µè«‹æ±‚資料時發生錯誤"
@@ -9448,7 +9608,7 @@ msgid "Compare Revisions"
msgstr "比較版本"
msgid "Compare branches and continue"
-msgstr ""
+msgstr "比較分支並繼續"
msgid "Compare changes"
msgstr "比較變更"
@@ -9516,6 +9676,9 @@ msgstr "完æˆ"
msgid "Complete verification to sign in."
msgstr "完æˆé©—證方å¯ç™»éŒ„。"
+msgid "Complete verification to sign up."
+msgstr "完æˆé©—證方å¯è¨»å†Šã€‚"
+
msgid "Completed"
msgstr "已完æˆ"
@@ -9585,8 +9748,8 @@ msgstr "å稱是必è¦çš„"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
msgstr "尚未設置åˆè¦æ¡†æž¶"
-msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr "所需格å¼ï¼š %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}。 %{linkStart}瞭解更多。%{linkEnd}"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}What is a compliance pipeline configuration?%{linkEnd}"
+msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "無法ä¿å­˜æ­¤åˆè¦æ€§æ¡†æž¶ï¼Œè«‹é‡è©¦"
@@ -9903,6 +10066,9 @@ msgstr "è¯çµ¡äºº"
msgid "Container Registry"
msgstr "容器映åƒåº«"
+msgid "Container Repository"
+msgstr ""
+
msgid "Container Scanning"
msgstr "容器掃æ"
@@ -10026,7 +10192,7 @@ msgid "ContainerRegistry|Docker connection error"
msgstr "Docker連接錯誤"
msgid "ContainerRegistry|Edit cleanup rules"
-msgstr ""
+msgstr "編輯清ç†è¦å‰‡"
msgid "ContainerRegistry|Enable expiration policy"
msgstr "ContainerRegistry|啟用逾期策略"
@@ -10132,10 +10298,10 @@ msgid "ContainerRegistry|Save storage space by automatically deleting tags from
msgstr "通éŽè‡ªå‹•å¾žå®¹å™¨è¨»å†Šåº«ä¸­åˆªé™¤ä¸¦ä¿ç•™æ‚¨æƒ³è¦çš„標籤來節çœå„²å­˜ç©ºé–“。%{linkStart}清ç†å·¥ä½œå¦‚何進行?%{linkEnd}"
msgid "ContainerRegistry|Set cleanup rules"
-msgstr ""
+msgstr "設定清ç†è¦å‰‡"
msgid "ContainerRegistry|Set rules to automatically remove unused packages to save storage space."
-msgstr ""
+msgstr "設定自動移除未使用的軟體套件è¦å‰‡ä»¥ç¯€çœå„²å­˜ç©ºé–“。"
msgid "ContainerRegistry|Set up cleanup"
msgstr "設置清ç†"
@@ -10356,15 +10522,15 @@ msgstr "è²¢ç»è€…"
msgid "Control emails linked to your account"
msgstr "控制與您帳號關è¯çš„é›»å­éƒµä»¶"
+msgid "Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects."
+msgstr "控制 CI_JOB_TOKEN CI/CD 變é‡å¦‚何用於專案之間的 API å­˜å–。"
+
msgid "Control how the GitLab Package Registry functions."
msgstr "控制 GitLab 軟體套件倉庫如何é‹ä½œã€‚"
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
msgstr "控制是å¦åœ¨ GitLab 中顯示客戶體驗改進內容和第三方優惠。"
-msgid "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."
-msgstr "控制使用此專案的 CI_JOB_TOKEN CI/CD 變é‡é€²è¡Œèº«ä»½é©—證的 API 請求å¯ä»¥è¨ªå•å“ªäº›å°ˆæ¡ˆã€‚ç¦ç”¨æ­¤åŠŸèƒ½å­˜åœ¨å®‰å…¨é¢¨éšªï¼Œå› ç‚ºæœªç¶“授權的專案å¯èƒ½æœƒå˜—試存å–活動令牌(權æ–)ä¸¦è¨ªå• API。"
-
msgid "Cookie domain"
msgstr "Cookie域"
@@ -10381,13 +10547,13 @@ msgid "Copy %{accessTokenType}"
msgstr "複製 %{accessTokenType}"
msgid "Copy %{http_label} clone URL"
-msgstr "複製 %{http_label} 仿製(clone) URL"
+msgstr "複製 %{http_label} 克隆 (Clone) URL"
msgid "Copy %{name}"
msgstr "複製 %{name}"
msgid "Copy %{protocol} clone URL"
-msgstr "複製 %{protocol} 仿製(clone) URL"
+msgstr "複製 %{protocol} 克隆 (Clone) URL"
msgid "Copy %{type}"
msgstr "複製 %{type}"
@@ -10396,10 +10562,10 @@ msgid "Copy ID"
msgstr "複製ID"
msgid "Copy KRB5 clone URL"
-msgstr "複製KRB5仿製U(clone)URL"
+msgstr "複製 KRB5 克隆 (Clone) URL"
msgid "Copy SSH clone URL"
-msgstr "複製SSH仿製(clone)URL"
+msgstr "複製 SSH 克隆 (Clone) URL"
msgid "Copy SSH public key"
msgstr "複製SSH公鑰"
@@ -10686,6 +10852,9 @@ msgstr "無法將策略分é…給專案或群組"
msgid "Country"
msgstr "國家"
+msgid "Counts reflect children you may not have access to."
+msgstr "數值å映了您å¯èƒ½ç„¡æ¬Šå­˜å–çš„å­å…ƒç´ ã€‚"
+
msgid "Coverage"
msgstr "覆蓋率"
@@ -10902,6 +11071,9 @@ msgstr "建立主題"
msgid "Create user"
msgstr "建立使用者"
+msgid "Create wildcard"
+msgstr "建立è¬ç”¨å­—å…ƒ"
+
msgid "Create wildcard: %{searchTerm}"
msgstr "建立è¬ç”¨å­—元:%{searchTerm}"
@@ -10914,6 +11086,12 @@ msgstr "建立您的群組"
msgid "Create, update, or delete a merge request."
msgstr "建立ã€æ›´æ–°æˆ–刪除åˆä½µè«‹æ±‚。"
+msgid "CreateGitTag|Add a message to the tag. Leaving this blank creates a %{linkStart}lightweight tag%{linkEnd}."
+msgstr "加入標籤訊æ¯ï¼Œä¿ç•™ç©ºç™½æœƒå»ºç«‹ä¸€å€‹ %{linkStart} 輕é‡ç´šæ¨™ç±¤%{linkEnd}。"
+
+msgid "CreateGitTag|Set tag message"
+msgstr "設定標籤訊æ¯"
+
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
msgstr "您無權在此群組中建立å­ç¾¤çµ„。"
@@ -11242,7 +11420,7 @@ msgid "Current Project"
msgstr "ç›®å‰å°ˆæ¡ˆ"
msgid "Current forks will keep their visibility level."
-msgstr "當å‰å»¶ä¼¸çš„分å‰(fork)將維æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
+msgstr "當å‰å»¶ä¼¸çš„分å‰ï¼ˆFork)將維æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
msgid "Current node must be the primary node or you will be locking yourself out"
msgstr "當å‰ç¯€é»žå¿…須是主節點,å¦å‰‡æ‚¨å°‡æœƒéŽ–定自己。"
@@ -11287,7 +11465,7 @@ msgid "Custom Attributes"
msgstr "自訂屬性"
msgid "Custom Git clone URL for HTTP(S)"
-msgstr "自訂HTTP(S)å”è­°çš„ Git clone URL"
+msgstr "自訂 HTTP(S) å”è­°çš„ Git clone URL"
msgid "Custom analyzers: language support"
msgstr "自訂分æžå™¨ï¼šæ”¯æ´èªžç³»"
@@ -11690,10 +11868,10 @@ msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and resp
msgstr "被動掃æ監控發é€åˆ°ç›®æ¨™çš„所有 HTTP 消æ¯ï¼ˆè«‹æ±‚和回應),主動掃æ則攻擊目標以發ç¾æ½›åœ¨æ¼æ´žã€‚"
msgid "DastProfiles|A scanner profile defines the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "掃æ器é…置文件定義了安全掃æ器的組態細節。 %{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "站點é…置文件定義了您已部署的應用程åºã€ç¶²ç«™æˆ– API 的屬性和組態細節。 %{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|AJAX spider"
msgstr "AJAX 爬蟲"
@@ -11897,10 +12075,10 @@ msgid "DastProfiles|Scanner name"
msgstr "掃æ器å稱"
msgid "DastProfiles|Scanner profile"
-msgstr ""
+msgstr "掃æ器é…置文件"
msgid "DastProfiles|Scanner profiles"
-msgstr ""
+msgstr "掃æ器é…置文件"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
msgstr "é¸æ“‡æŽƒæé…置文件以執行 DAST 掃æ"
@@ -11924,10 +12102,10 @@ msgid "DastProfiles|Site name"
msgstr "站點å稱"
msgid "DastProfiles|Site profile"
-msgstr ""
+msgstr "站點é…置文件"
msgid "DastProfiles|Site profiles"
-msgstr ""
+msgstr "站點é…置文件"
msgid "DastProfiles|Site type"
msgstr "站點類型"
@@ -12167,6 +12345,12 @@ msgstr "日期範åœçš„é™åˆ¶ç‚º %{number} 天"
msgid "Date range must be shorter than %{max_range} days."
msgstr "日期範åœå¿…é ˆå°æ–¼ %{max_range} 天。"
+msgid "Date to enact enforcement on newly created namespaces"
+msgstr "å°æ–°å»ºç«‹çš„命å空間實施強制執行的日期"
+
+msgid "DateRange|%{start_date}–%{end_date}"
+msgstr "%{start_date}–%{end_date}"
+
msgid "Day of month"
msgstr "月份中的第幾天"
@@ -12353,6 +12537,9 @@ msgstr "刪除帳號"
msgid "Delete artifacts"
msgstr "刪除產物"
+msgid "Delete asset"
+msgstr "刪除素æ"
+
msgid "Delete audio"
msgstr "刪除音頻"
@@ -12497,6 +12684,9 @@ msgstr "已刪除"
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "已刪除èŠå¤©çš„暱稱: %{chat_name}!"
+msgid "Deleted commits:"
+msgstr "已刪除的æ交:"
+
msgid "Deleted projects cannot be restored!"
msgstr "已刪除的專案無法復原ï¼"
@@ -12830,6 +13020,9 @@ msgstr "唯讀權é™"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "啟用部署令牌(權æ–)(%{active_tokens})"
+msgid "DeployTokens|Allows read and write access to registry images."
+msgstr "å…許å°è¨»å†Šè¡¨æ˜ åƒé€²è¡Œè®€å¯«å­˜å–。"
+
msgid "DeployTokens|Allows read and write access to the package registry."
msgstr "å…許å°è»Ÿé«”套件包註冊庫進行讀寫訪å•ã€‚"
@@ -12875,6 +13068,9 @@ msgstr "為您的令牌輸入使用者å稱。é è¨­ç‚º %{code_start}gitlab+dep
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
msgstr "輸入令牌的到期日期。é è¨­ç‚ºæ°¸ä¸éŽæœŸã€‚"
+msgid "DeployTokens|Expiration date (optional)"
+msgstr "到期日期(å¯é¸)"
+
msgid "DeployTokens|Expires"
msgstr "éŽæœŸ"
@@ -12896,6 +13092,9 @@ msgstr "撤銷 %{name}"
msgid "DeployTokens|Scopes"
msgstr "有效範åœ"
+msgid "DeployTokens|Scopes (select at least one)"
+msgstr "ç¯„åœ (至少é¸æ“‡ä¸€é …)"
+
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "æ­¤ %{entity_type} 沒有啟用的部署令牌(權æ–)。"
@@ -12911,6 +13110,12 @@ msgstr "使用此令牌作為密碼。此密碼 %{i_start}ä¸èƒ½%{i_end} 被回å
msgid "DeployTokens|Username"
msgstr "使用者å稱"
+msgid "DeployTokens|Username (optional)"
+msgstr "使用者å稱 (å¯é¸)"
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr "您的新部署權æ–(令牌)"
+
msgid "DeployTokens|Your new Deploy Token username"
msgstr "您的新部署令牌(權æ–)使用者å稱"
@@ -13095,18 +13300,9 @@ msgstr "æˆåŠŸ"
msgid "Deprecated API rate limits"
msgstr "已棄用的 API 速率é™åˆ¶"
-msgid "Deprecations|Feature deprecation and removal"
-msgstr "棄用和移除功能"
-
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr "關於å¯èƒ½æ›¿æ›çš„訊æ¯ï¼Œ%{epicStart}瞭解更多關於 Opstrace %{epicEnd}。"
-msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr "關於å¯èƒ½æ›¿æ›çš„ä¿¡æ¯ï¼Œ%{opstrace_link_start} 了解有關 Opstrace %{link_end} 的更多信æ¯ã€‚"
-
-msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
-msgstr "GitLab 14.7 中已棄用了日誌和跟踪功能,並計劃在 GitLab 15.0 中刪除 %{link_end} %{removal_link_start}。"
-
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr "指標功能在 GitLab 14.7 中已棄用。"
@@ -13174,20 +13370,11 @@ msgstr "已存檔的設計ä»å¯åœ¨ä¹‹å‰ç‰ˆæœ¬çš„設計集中使用。"
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr "您確定è¦æ­¸æª”所é¸çš„設計嗎?"
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr "您確定è¦å–消å°æ­¤ç•™è¨€è©•è«–的更改嗎?"
-
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "您確定è¦å–消建立此留言評論嗎?"
-msgid "DesignManagement|Cancel changes"
-msgstr "å–消變更"
-
-msgid "DesignManagement|Cancel comment confirmation"
-msgstr "確èªå–消留言評論"
-
-msgid "DesignManagement|Cancel comment update confirmation"
-msgstr "確èªå–消留言更新"
+msgid "DesignManagement|Are you sure you want to cancel editing this comment?"
+msgstr ""
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
msgstr "單擊您è¦é–‹å§‹æ–°è¨Žè«–的圖åƒ"
@@ -13195,6 +13382,12 @@ msgstr "單擊您è¦é–‹å§‹æ–°è¨Žè«–的圖åƒ"
msgid "DesignManagement|Comment"
msgstr "留言(評論)"
+msgid "DesignManagement|Continue creating"
+msgstr ""
+
+msgid "DesignManagement|Continue editing"
+msgstr ""
+
msgid "DesignManagement|Could not add a new comment. Please try again."
msgstr "無法新增新留言。請é‡è©¦ã€‚"
@@ -13213,11 +13406,11 @@ msgstr "å–消全部é¸æ“‡"
msgid "DesignManagement|Designs"
msgstr "設計"
-msgid "DesignManagement|Discard comment"
-msgstr "æ¨æ£„留言"
+msgid "DesignManagement|Discard changes"
+msgstr ""
msgid "DesignManagement|Discussion"
-msgstr ""
+msgstr "討論"
msgid "DesignManagement|Download design"
msgstr "下載設計"
@@ -13234,12 +13427,6 @@ msgstr "å‰å¾€ä¸‹ä¸€å€‹è¨­è¨ˆ"
msgid "DesignManagement|Go to previous design"
msgstr "å‰å¾€ä¸Šä¸€å€‹è¨­è¨ˆ"
-msgid "DesignManagement|Keep changes"
-msgstr "ä¿ç•™æ›´æ”¹"
-
-msgid "DesignManagement|Keep comment"
-msgstr "ä¿ç•™ç•™è¨€"
-
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr "請求的設計版本ä¸å­˜åœ¨ï¼Œé¡¯ç¤ºæœ€æ–°ç‰ˆæœ¬"
@@ -13313,7 +13500,7 @@ msgid "DevOps adoption"
msgstr "DevOps adoption"
msgid "Development"
-msgstr ""
+msgstr "開發"
msgid "Devices (optional)"
msgstr "設備(å¯é¸ï¼‰"
@@ -13778,6 +13965,18 @@ msgstr "網域"
msgid "Domain Name"
msgstr "網域å稱"
+msgid "Domain Verification"
+msgstr "網域驗證"
+
+msgid "DomainVerification|How do I configure a domain?"
+msgstr "如何設定網域?"
+
+msgid "DomainVerification|No domains configured. Create a domain in a project in this group hierarchy."
+msgstr "未設定網域,請在此群組層次çµæ§‹çš„專案中建立網域。"
+
+msgid "DomainVerification|The following domains are configured for projects in this group. Users with email addresses that match a verified domain do not need to confirm their account."
+msgstr "已為該群組中的專案設定以下網域,電å­éƒµä»¶åœ°å€ç¬¦åˆå·²é©—證網域的使用者無需確èªå…¶å¸³è™Ÿã€‚"
+
msgid "Don't have a group?"
msgstr "沒有群組?"
@@ -13896,10 +14095,10 @@ msgid "DropdownWidget|Assign %{issuableAttribute}"
msgstr "分派 %{issuableAttribute}"
msgid "DropdownWidget|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "DropdownWidget|Edit %{issuableAttribute}"
-msgstr ""
+msgstr "編輯 %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
msgstr "無法為此%{issuableType}å–å¾—%{issuableAttribute},請é‡è©¦ã€‚"
@@ -13917,10 +14116,10 @@ msgid "DropdownWidget|No open %{issuableAttribute} found"
msgstr "找ä¸åˆ°é–‹æ”¾çš„ %{issuableAttribute}"
msgid "DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it."
-msgstr ""
+msgstr "您無權查看當å‰å·²æŒ‡æ´¾çš„ %{issuableAttribute},如果您é‡æ–°æŒ‡æ´¾å®ƒï¼Œæ‚¨å°‡ç„¡æ³•å†æ¬¡é¸æ“‡å®ƒã€‚"
msgid "DropdownWidget|You don't have permission to view this %{issuableAttribute}."
-msgstr ""
+msgstr "您無權查看該 %{issuableAttribute}。"
msgid "Due Date"
msgstr "截止日期"
@@ -13935,7 +14134,7 @@ msgid "Due to inactivity, the %{project_name} (%{project_link}) project is sched
msgstr "由於ä¸æ´»èºï¼Œ%{project_name}(%{project_link})專案計劃在%{deletion_date}刪除。è¦å–消%{project_name}的刪除計劃,請å°å…¶åŸ·è¡Œä¸€äº›æ´»å‹•ã€‚例如:"
msgid "Due to inactivity, this project is scheduled to be deleted on %{deletion_date}. %{link_start}Why is this scheduled?%{link_end}"
-msgstr "由於ä¸æ´»èºï¼Œæ­¤å°ˆæ¡ˆè¨ˆåŠƒæ–¼%{deletion_date}刪除。%{link_start}為什麼è¦å®‰æŽ’這個?%{link_end}"
+msgstr "由於ä¸æ´»èºï¼Œæ­¤å°ˆæ¡ˆå·²è¨ˆåŠƒæ–¼%{deletion_date}刪除。%{link_start}為什麼è¦å®‰æŽ’這個?%{link_end}"
msgid "Duplicate page: %{error_message}"
msgstr "é‡è¤‡çš„é é¢: %{error_message}"
@@ -14079,7 +14278,7 @@ msgid "Edit files in the editor and commit changes here"
msgstr "在編輯器中編輯文件,並在這裡​​æ交變更內容"
msgid "Edit fork in Web IDE"
-msgstr "在Web IDE中編輯延生的分支(fork)"
+msgstr "在Web IDE中編輯延生的分å‰ï¼ˆFork)"
msgid "Edit group application"
msgstr "編輯群組應用程å¼"
@@ -14144,6 +14343,9 @@ msgstr "編輯Wikié é¢"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "編輯你在最近話題中的留言(從空白文字å€)"
+msgid "Edit your search and try again"
+msgstr "編輯您的查詢並é‡è©¦"
+
msgid "Edit your search filter and try again."
msgstr "編輯您的查詢éŽæ¿¾å™¨ä¸¦é‡è©¦ã€‚"
@@ -14282,9 +14484,6 @@ msgstr "é›»å­éƒµä»¶åƒèˆ‡è€…警告|還有 %{moreCount} 個"
msgid "Emails"
msgstr "é›»å­éƒµä»¶"
-msgid "Emails sent from Service Desk have this name."
-msgstr "從æœå‹™å°ç™¼é€çš„é›»å­éƒµä»¶å…·æœ‰æ­¤å稱。"
-
msgid "Emails sent to %{email} are also supported."
msgstr "也支æ´ç™¼é€åˆ° %{email} çš„é›»å­éƒµä»¶ã€‚"
@@ -14334,7 +14533,7 @@ msgid "Enable GitLab Error Tracking"
msgstr "啟用 GitLab 錯誤追踪"
msgid "Enable GitLab Prometheus metrics endpoint"
-msgstr ""
+msgstr "啟用 GitLab Prometheus 指標端點"
msgid "Enable Gitpod"
msgstr "啟用 Gitpod"
@@ -14402,6 +14601,9 @@ msgstr "為建立於早於GitLab 12.7版本的專案啟用容器éŽæœŸå’Œä¿ç•™ç
msgid "Enable container expiration caching."
msgstr "啟用容器éŽæœŸç·©å­˜ã€‚"
+msgid "Enable dashboard limits on namespaces"
+msgstr "å°å‘½å空間啟用儀表æ¿é™åˆ¶"
+
msgid "Enable email notification"
msgstr "啟用電å­éƒµä»¶é€šçŸ¥"
@@ -14750,6 +14952,9 @@ msgstr "部署"
msgid "Environments|Deployment %{status}"
msgstr "部署%{status}"
+msgid "Environments|Edit your search and try again"
+msgstr "編輯您的查詢並且é‡è©¦"
+
msgid "Environments|Enable review app"
msgstr "啟用審核應用"
@@ -14783,6 +14988,9 @@ msgstr "沒有已部署的環境"
msgid "Environments|No deployments yet"
msgstr "未部署"
+msgid "Environments|No results found"
+msgstr "未找到çµæžœ"
+
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
msgstr "注æ„:繼續æ“作將終止目å‰ç’°å¢ƒï¼ç”±æ–¼æœªåœ¨%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}文件中定義「終止環境æ“作ã€ï¼Œå› æ­¤%{emphasisStart}ä¸æœƒ%{emphasisEnd}影響已經存在的部署。"
@@ -14807,6 +15015,9 @@ msgstr "還原環境"
msgid "Environments|Rollback environment %{name}?"
msgstr "還原 %{name} 環境?"
+msgid "Environments|Search by environment name"
+msgstr "ä¾ç’°å¢ƒå稱查詢"
+
msgid "Environments|Show all"
msgstr "顯示全部"
@@ -15006,7 +15217,7 @@ msgid "Error deleting project. Check logs for error details."
msgstr "刪除專案時發生錯誤。請檢視日誌以å–得錯誤詳細資訊。"
msgid "Error fetching branches"
-msgstr ""
+msgstr "讀å–分支時發生錯誤。"
msgid "Error fetching burnup chart data"
msgstr "æå–燃起圖資料時發生錯誤"
@@ -15015,7 +15226,7 @@ msgid "Error fetching diverging counts for branches. Please try again."
msgstr "å–得分支分å‰æ•¸ç›®æ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "Error fetching forked projects. Please try again."
-msgstr "讀å–已分å‰(forked)的專案時發生錯誤。請é‡è©¦ã€‚"
+msgstr "讀å–已分å‰ï¼ˆFork)的專案時發生錯誤。請é‡è©¦ã€‚"
msgid "Error fetching labels."
msgstr "å–得標記時發生錯誤。"
@@ -15312,7 +15523,7 @@ msgid "EscalationPolicies|Escalation rules"
msgstr "å‡ç´šè¦å‰‡"
msgid "EscalationPolicies|Failed to load oncall-schedules"
-msgstr "載入 on-call 計劃失敗"
+msgstr "載入 on-call 排程失敗"
msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
msgstr "如果警報在%{minutes}分é˜å…§ä¸æ˜¯%{alertStatus}"
@@ -15822,10 +16033,10 @@ msgid "Failed to check related branches."
msgstr "無法檢查相關分支。"
msgid "Failed to clone this issue because target project doesn't exist."
-msgstr "無法仿製(clone)此議題,因為目標專案ä¸å­˜åœ¨ã€‚"
+msgstr "無法複製此議題,因為目標專案ä¸å­˜åœ¨ã€‚"
msgid "Failed to clone this issue: wrong parameters."
-msgstr "無法仿製(clone)此議題:åƒæ•¸éŒ¯èª¤ã€‚"
+msgstr "無法複製此議題:åƒæ•¸éŒ¯èª¤ã€‚"
msgid "Failed to create a branch for this issue. Please try again."
msgstr "無法為此å•é¡Œå»ºç«‹åˆ†æ”¯ã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
@@ -15855,7 +16066,7 @@ msgid "Failed to deploy to"
msgstr "無法部署到"
msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
-msgstr "無法將rebaseæ“作加入佇列,å¯èƒ½æ˜¯ç”±æ–¼äº‹å‹™æ™‚é–“éŽé•·ã€‚ç¨å¾Œå†è©¦ã€‚"
+msgstr "無法將變基 (Rebase) æ“作加入佇列,å¯èƒ½æ˜¯ç”±æ–¼äº‹å‹™æ™‚é–“éŽé•·ã€‚ç¨å¾Œå†è©¦ã€‚"
msgid "Failed to fetch the iteration for this issue. Please try again."
msgstr "無法å–得此議題的迭代,請é‡è©¦ã€‚"
@@ -15902,9 +16113,6 @@ msgstr "載入分支失敗。請é‡è©¦ã€‚"
msgid "Failed to load deploy keys."
msgstr "載入部署金鑰失敗。"
-msgid "Failed to load emoji list."
-msgstr "無法載入表情列表。"
-
msgid "Failed to load error details from Sentry."
msgstr "無法從Sentry載入錯誤詳細訊æ¯ã€‚"
@@ -16510,13 +16718,13 @@ msgid "Flags"
msgstr "旗幟"
msgid "FloC|Configure whether you want to participate in FLoC. %{floc_link_start}What is FLoC?%{floc_link_end}"
-msgstr ""
+msgstr "設定您是å¦è¦åƒèˆ‡ FLoC。 %{floc_link_start} FLoC 是什麼?%{floc_link_end}"
msgid "FloC|Federated Learning of Cohorts (FLoC)"
-msgstr ""
+msgstr "基於è¯é‚¦å¼å­¸ç¿’架構的廣告投放 (FLoC)"
msgid "FloC|Participate in FLoC"
-msgstr ""
+msgstr "åƒåŠ  FLoC"
msgid "FlowdockService|Enter your Flowdock token."
msgstr "輸入您的 Flowdock 令牌(權æ–)"
@@ -16579,7 +16787,7 @@ msgid "For additional information, review your group membership: %{link_to} or c
msgstr "有關其他訊æ¯ï¼Œè«‹æŸ¥çœ‹æ‚¨çš„群組æˆå“¡èº«ä»½ï¼š %{link_to} 或è¯ç¹«æ‚¨çš„群組所有者。"
msgid "For each job, clone the repository."
-msgstr "é‡å°æ¯ä¸€å€‹ä½œæ¥­ä»¿è£½(clone)版本庫。"
+msgstr "é‡å°æ¯ä¸€å€‹ä½œæ¥­å…‹éš† (Clone) 版本庫。"
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr "é‡å°æ¯å€‹ä½œæ¥­ï¼Œé‡è¤‡ä½¿ç”¨å°ˆæ¡ˆå·¥ä½œç©ºé–“。如果工作空間ä¸å­˜åœ¨ï¼Œè«‹ä½¿ç”¨ %{code_open} git clone %{code_close}。"
@@ -16587,6 +16795,9 @@ msgstr "é‡å°æ¯å€‹ä½œæ¥­ï¼Œé‡è¤‡ä½¿ç”¨å°ˆæ¡ˆå·¥ä½œç©ºé–“。如果工作空間
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
msgstr "例如,使用令牌的應用程å¼æˆ–令牌的用途。ä¸è¦æ供令牌å稱的æ•æ„Ÿè¨Šæ¯ï¼Œå› ç‚ºå®ƒå°‡å°æ‰€æœ‰ %{resource_type} æˆå“¡å¯è¦‹ã€‚"
+msgid "For faster browsing, not all history is shown."
+msgstr "為了ç€è¦½çš„æµæš¢åº¦ï¼Œä¸æœƒé¡¯ç¤ºæ‰€æœ‰æ­·å²è¨˜éŒ„。"
+
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
msgstr "å°æ–¼å¤§æ–¼æ­¤é™åˆ¶çš„檔案,僅索引檔案å稱。檔案內容沒有索引也ä¸å¯æœå°‹ã€‚"
@@ -16615,22 +16826,22 @@ msgid "Forgot your password?"
msgstr "忘記密碼?"
msgid "Fork"
-msgstr "分å‰"
+msgstr "åˆ†å‰ Fork)"
msgid "Fork Error!"
-msgstr "分å‰éŒ¯èª¤ï¼"
+msgstr "分å‰ï¼ˆFork)錯誤ï¼"
msgid "Fork project"
-msgstr "分å‰å°ˆæ¡ˆ"
+msgstr "分å‰ï¼ˆFork)專案"
msgid "Fork project?"
msgstr "分å‰å°ˆæ¡ˆ?"
msgid "ForkProject|A fork is a copy of a project."
-msgstr "åˆ†å‰ (fork) 是複製專案。"
+msgstr "分å‰ï¼ˆFork)是專案的複製。"
msgid "ForkProject|An error occurred while forking the project. Please try again."
-msgstr "åˆ†å‰ (fork) 專案時發生錯誤。請é‡è©¦ã€‚"
+msgstr "分å‰ï¼ˆFork)專案時發生錯誤。請é‡è©¦ã€‚"
msgid "ForkProject|Cancel"
msgstr "å–消"
@@ -16639,10 +16850,10 @@ msgid "ForkProject|Create a group"
msgstr "建立群組"
msgid "ForkProject|Fork project"
-msgstr "åˆ†å‰ (fork) 專案"
+msgstr "分å‰ï¼ˆFork)專案"
msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
-msgstr "åˆ†å‰ (fork) 版本庫å…許您在ä¸å½±éŸ¿åŽŸå§‹å°ˆæ¡ˆçš„情æ³ä¸‹é€²è¡Œè®Šæ›´ã€‚"
+msgstr "分å‰ï¼ˆFork)版本庫å…許您在ä¸å½±éŸ¿åŽŸå§‹å°ˆæ¡ˆçš„情æ³ä¸‹é€²è¡Œè®Šæ›´ã€‚"
msgid "ForkProject|Internal"
msgstr "內部"
@@ -16684,13 +16895,13 @@ msgid "ForkSuggestion|Cancel"
msgstr "å–消"
msgid "ForkSuggestion|Fork"
-msgstr "分å‰(Fork)"
+msgstr "分å‰ï¼ˆFork)"
msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
msgstr "您ä¸èƒ½åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç›´æŽ¥ %{edit_start}編輯%{edit_end} 文件,請分å‰å‡ºï¼ˆFork)這個專案並æ交åˆä½µè«‹æ±‚。"
msgid "ForkedFromProjectPath|Forked from"
-msgstr "分å‰è‡ª"
+msgstr "分å‰ï¼ˆFork)自"
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
msgstr "從無法存å–的專案分å‰"
@@ -16699,7 +16910,7 @@ msgid "Forking in progress"
msgstr "分å‰è™•ç†ä¸­"
msgid "Forks"
-msgstr "分å‰"
+msgstr "分å‰ï¼ˆFork)"
msgid "Format: %{dateFormat}"
msgstr "æ ¼å¼ï¼š%{dateFormat}"
@@ -16716,13 +16927,46 @@ msgstr "在.gitlab-ci.yml中發ç¾éŒ¯èª¤ï¼š"
msgid "Framework successfully deleted"
msgstr "框架刪除æˆåŠŸ"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "å…費試用 GitLab.com Ultimate"
+msgid "Free User Cap"
+msgstr "å…費使用者上é™"
+
msgid "Free groups are limited to %{free_user_limit} member and the remaining members will get a status of over-limit and lose access to the group."
msgid_plural "Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group."
msgstr[0] "å…費群組é™åˆ¶ç‚º %{free_user_limit} ä½æˆå“¡ï¼Œå…¶é¤˜æˆå“¡å°‡è®Šç‚ºè¶…é™ç‹€æ…‹ä¸¦å¤±åŽ»å°è©²ç¾¤çµ„çš„å­˜å–權é™ã€‚"
+msgid "FreeUserCap|Alternatively you can upgrade to GitLab Premium or GitLab Ultimate:"
+msgstr "或者,您å¯ä»¥å‡ç´šåˆ° GitLab Premium 或 GitLab Ultimate:"
+
+msgid "FreeUserCap|Explore paid plans"
+msgstr "探查付費計劃"
+
+msgid "FreeUserCap|Explore paid plans:"
+msgstr "探查付費計劃:"
+
+msgid "FreeUserCap|Looks like you've reached your limit of %{free_user_limit} members for \"%{namespace_name}\". You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members."
+msgstr "您似乎已é”到“%{namespace_name}†%{free_user_limit} 個æˆå“¡çš„é™åˆ¶ï¼Œæ‚¨ç„¡æ³•å†å¢žåŠ ï¼Œä½†å¯ä»¥ç®¡ç†ç¾æœ‰æˆå“¡ï¼Œä¾‹å¦‚,刪除éžæ´»èºçš„æˆå“¡ä¸¦å°‡å…¶æ›¿æ›ç‚ºæ–°çš„æˆå“¡ã€‚"
+
+msgid "FreeUserCap|Manage members"
+msgstr "æˆå“¡ç®¡ç†"
+
+msgid "FreeUserCap|Manage members:"
+msgstr "æˆå“¡ç®¡ç†:"
+
+msgid "FreeUserCap|To get more members %{trial_link_start}start a trial %{trial_link_end} or %{upgrade_link_start}upgrade%{upgrade_link_end} to GitLab Premium or GitLab Ultimate."
+msgstr "è¦å–得更多æˆå“¡ï¼Œå¯ä»¥%{trial_link_start} 開始試用 %{trial_link_end} 或 %{upgrade_link_start}å‡ç´š%{upgrade_link_end} 到 GitLab Premium 或 GitLab Ultimate。"
+
+msgid "FreeUserCap|To get more members start a trial:"
+msgstr "開始試用以å–得更多æˆå“¡æ•¸ï¼š"
+
+msgid "FreeUserCap|You've reached your member limit!"
+msgstr "您已經é”到您的æˆå“¡äººæ•¸ä¸Šé™ï¼"
+
msgid "Freeze end"
msgstr "çµæŸå‡çµ"
@@ -16981,6 +17225,9 @@ msgstr "編輯您的查詢並且é‡è©¦"
msgid "Geo|Errors:"
msgstr "錯誤:"
+msgid "Geo|External URL"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失敗"
@@ -17069,7 +17316,7 @@ msgid "Geo|Limit the number of concurrent operations this secondary site can run
msgstr "é™åˆ¶æ­¤è¼”助站點å¯ä»¥åœ¨èƒŒæ™¯é‹è¡Œçš„並行æ“作數é‡ã€‚"
msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
-msgstr "GitLab Geo å¯ä»¥å»ºç«‹ GitLab 實例的唯讀映åƒ, 使得從é ç«¯ä»¿è£½(clone)和拉å–大型程å¼ç¢¼å€‰åº«çš„時間大大縮短,從而æ高團隊æˆå“¡çš„工作效率。"
+msgstr "GitLab Geo å¯ä»¥å»ºç«‹ GitLab 實例的唯讀映åƒ, 使得從é ç«¯å…‹éš† (Clone) å’Œæ‹‰å– (Fetch) 大型程å¼ç¢¼å€‰åº«çš„時間大大縮短,從而æ高團隊æˆå“¡çš„工作效率。"
msgid "Geo|Minimum interval in days"
msgstr "最å°é–“隔天數"
@@ -17320,6 +17567,9 @@ msgstr "儲存該Geo站點時發生錯誤"
msgid "Geo|There was an error updating the Geo Settings"
msgstr "更新Geo設定時發生錯誤"
+msgid "Geo|This GitLab instance is subscribed to the %{insufficient_license} tier. Geo is only available for users who have at least a Premium subscription."
+msgstr ""
+
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
msgstr "å°‡è¦é‡æ–°åŒæ­¥æ‰€æœ‰%{replicableType}。å¯èƒ½éœ€è¦ä¸€äº›æ™‚間完æˆã€‚確定繼續嗎?"
@@ -17453,7 +17703,7 @@ msgid "Git revision"
msgstr "Gitæ交版本"
msgid "Git shallow clone"
-msgstr "Git 淺仿製(clone)"
+msgstr "Git 淺層克隆 (Clone) "
msgid "Git strategy"
msgstr "Git ç­–ç•¥"
@@ -17542,9 +17792,6 @@ msgstr "GitLab議題"
msgid "GitLab KAS"
msgstr "GitLab KAS"
-msgid "GitLab Logo"
-msgstr "GitLab 標誌"
-
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17630,7 +17877,7 @@ msgid "GitLab version"
msgstr "GitLab版本"
msgid "GitLab will create a branch in your fork and start a merge request."
-msgstr "GitLab å°‡åœ¨ä½ çš„åˆ†å‰ (fork) 中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
+msgstr "GitLab 將在你的分å‰ï¼ˆFork)中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -17837,7 +18084,7 @@ msgid "Global Shortcuts"
msgstr "全域快æ·éµ"
msgid "Global notification level"
-msgstr ""
+msgstr "全域通知級別"
msgid "Global notification settings"
msgstr "全域通知設定"
@@ -17927,10 +18174,10 @@ msgid "GlobalSearch|project"
msgstr "專案"
msgid "GlobalShortcuts|Copied source branch name to clipboard."
-msgstr ""
+msgstr "將來æºåˆ†æ”¯å稱複製到剪貼簿。"
msgid "GlobalShortcuts|Unable to copy the source branch name at this time."
-msgstr ""
+msgstr "ç¾åœ¨ç„¡æ³•è¤‡è£½ä¾†æºåˆ†æ”¯å稱。"
msgid "Globally-allowed IP ranges"
msgstr "å…¨çƒå…許的 IP 範åœ"
@@ -18074,7 +18321,7 @@ msgid "Go to your To-Do list"
msgstr "å‰å¾€æ‚¨çš„待辦事項列表"
msgid "Go to your fork"
-msgstr "è·³å‰å¾€ä½ çš„分å‰é …ç›®"
+msgstr "è·³å‰å¾€ä½ çš„分å‰ï¼ˆFork)專案"
msgid "Go to your groups"
msgstr "å‰å¾€æ‚¨çš„群組"
@@ -18409,6 +18656,9 @@ msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "正在載入å²è©©"
+msgid "GroupRoadmap|New epic"
+msgstr "æ–°å²è©©"
+
msgid "GroupRoadmap|No start and end date"
msgstr "無開始和çµæŸæ—¥æœŸ"
@@ -18445,6 +18695,9 @@ msgstr "è¦æŸ¥çœ‹é–‹ç™¼è—圖,請在此群組或其å­ç¾¤çµ„中的一個 å²è©
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹è®Šæ›´æˆ–移除éŽæ¿¾å™¨ï¼Œå¾ž %{startDate} 到 %{endDate}。"
+msgid "GroupRoadmap|View epics list"
+msgstr "查看å²è©©åˆ—表"
+
msgid "GroupRoadmap|Within 3 years"
msgstr "3 年之內"
@@ -18539,7 +18792,7 @@ msgid "GroupSAML|No active SAML group links"
msgstr "沒有啟用的SAML群組éˆæŽ¥"
msgid "GroupSAML|Prohibit outer forks for this group"
-msgstr "ç¦æ­¢å¾žæ­¤ç¾¤çµ„å‘外分å‰(fork)。"
+msgstr "ç¦æ­¢å¾žæ­¤ç¾¤çµ„å‘外分å‰ï¼ˆFork)。"
msgid "GroupSAML|Reset SCIM token"
msgstr "GroupSAML|é‡è¨­ SCIM 令牌(權æ–)"
@@ -18661,8 +18914,8 @@ msgstr "é¸æ“‡ä¸€å€‹ç¾¤çµ„路徑,ä¸èƒ½ä»¥ç ´æŠ˜è™Ÿé–‹é ­æˆ–以å¥è™Ÿçµå°¾ï¼Œ
msgid "GroupSettings|Compliance frameworks"
msgstr "åˆè¦æ¡†æž¶"
-msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr "設定åˆè¦æ¡†æž¶ä»¥æ供給此群組中的專案。 %{linkStart}瞭解更多訊æ¯ã€‚%{linkEnd}"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}What are compliance frameworks?%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Configure limits on the number of repositories users can download in a given time."
msgstr "設定使用者在給定時間內å¯ä»¥ä¸‹è¼‰çš„版本庫數é‡é™åˆ¶ã€‚"
@@ -19006,6 +19259,12 @@ msgstr "群組路徑ä¸å¯ç”¨ã€‚路徑已替æ›ç‚ºå»ºè­°çš„å¯ç”¨è·¯å¾‘。"
msgid "Groups|Learn more"
msgstr "瞭解更多"
+msgid "Groups|Learn more about subgroups"
+msgstr "了解有關å­ç¾¤çµ„的更多訊æ¯"
+
+msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
+msgstr "æˆå“¡ã€å°ˆæ¡ˆã€è©¦ç”¨å’Œä»˜è²»è¨‚閱與特定的最上層群組相關è¯ã€‚ 如果您已經是最上層群組的æˆå“¡ï¼Œæ‚¨å¯ä»¥å»ºç«‹å­ç¾¤çµ„,以便新作å“æˆç‚ºç¾æœ‰æœ€ä¸Šå±¤ç¾¤çµ„的一部分。 您想改為建立å­ç¾¤çµ„嗎?"
+
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
msgstr "必須以字æ¯ã€æ•¸å­—ã€è¡¨æƒ…符號或下劃線開頭,也å¯ä»¥åŒ…å«å¥é»žã€ç ´æŠ˜è™Ÿã€ç©ºæ ¼å’Œæ‹¬è™Ÿã€‚"
@@ -19024,6 +19283,9 @@ msgstr "å­ç¾¤çµ„å稱"
msgid "Groups|Subgroup slug"
msgstr "å­ç¾¤çµ„ Slug"
+msgid "Groups|You're creating a new top-level group"
+msgstr "您正在建立一個新的最上層群組"
+
msgid "Guideline"
msgstr "åƒè€ƒ"
@@ -19045,8 +19307,8 @@ msgstr "基於 HTTP:存å–被拒絕。æ供的密碼或令牌ä¸æ­£ç¢ºï¼Œæˆ–è
msgid "Harbor Registry"
msgstr "Harbor 映åƒåº«"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables '$HARBOR_USERNAME', '$HARBOR_HOST', '$HARBOR_OCI', '$HARBOR_PASSWORD', '$HARBOR_URL' and '$HARBOR_PROJECT' will be created for CI/CD use."
-msgstr "啟用 Harbor æ•´åˆå¾Œï¼Œå°‡ç‚º CI/CD 的使用建立全局變é‡â€œ$HARBOR_USERNAMEâ€ã€â€œ$HARBOR_HOSTâ€ã€â€œ$HARBOR_OCIâ€ã€â€œ$HARBOR_PASSWORDâ€ã€â€œ$HARBOR_URLâ€å’Œâ€œ$HARBOR_PROJECTâ€ã€‚"
+msgid "HarborIntegration|After the Harbor integration is activated, global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL` and `$HARBOR_PROJECT` will be created for CI/CD use."
+msgstr ""
msgid "HarborIntegration|Base URL of the Harbor instance."
msgstr "Harbor 實例的基本 URL。"
@@ -19089,6 +19351,9 @@ msgstr[0] "%{count} 個映åƒå€‰åº«"
msgid "HarborRegistry|-- artifacts"
msgstr "-- 產物"
+msgid "HarborRegistry|-- tags"
+msgstr "-- 標籤"
+
msgid "HarborRegistry|Digest: %{imageId}"
msgstr "摘è¦: %{imageId}"
@@ -19134,8 +19399,8 @@ msgstr "該映åƒæª”沒有產物"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–移除上é¢çš„éŽæ¿¾å™¨ã€‚"
-msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr "連接到 Harbor Registry 發生錯誤。請嘗試é‡æ–°æ•´ç†é é¢ã€‚如果此錯誤ä»ç„¶å­˜åœ¨ï¼Œè«‹æŸ¥çœ‹ %{docLinkStart}故障排查文件%{docLinkEnd}。"
+msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}."
+msgstr "我們無法連接到 Harbour Registry,請嘗試刷新é é¢ã€‚如果該錯誤ä»ç„¶å­˜åœ¨ï¼Œè«‹æŸ¥çœ‹%{docLinkStart}文件%{docLinkEnd}。"
msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images."
msgstr "使用 Harbor Registry,æ¯å€‹å°ˆæ¡ˆéƒ½å¯ä»¥é€£æŽ¥åˆ° Harbor 空間來儲存其 Docker 映åƒã€‚"
@@ -19286,7 +19551,7 @@ msgid_plural "Hide charts"
msgstr[0] "éš±è—圖表"
msgid "Hide comments"
-msgstr ""
+msgstr "éš±è—留言"
msgid "Hide comments on this file"
msgstr "éš±è—在此檔案的留言"
@@ -19452,7 +19717,7 @@ msgid "How the job limiter handles jobs exceeding the thresholds specified below
msgstr "作業é™è£½å™¨å¦‚何處ç†è¶…出以下指定閾值的作業。 'track'模å¼åªè¨˜éŒ„作業。'compress'模å¼å£“縮作業並在壓縮大å°è¶…éŽé™åˆ¶æ™‚引發異常。"
msgid "How to track time"
-msgstr ""
+msgstr "如何追踪時間"
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -19565,26 +19830,47 @@ msgstr "識別碼"
msgid "Identities"
msgstr "身份標識"
+msgid "IdentityVerification|A new code has been sent."
+msgstr "已發é€æ–°é©—證碼。"
+
msgid "IdentityVerification|Before you create your first project, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "在您建立第一個專案之å‰ï¼Œæˆ‘們需è¦æ‚¨ä½¿ç”¨æœ‰æ•ˆçš„付款方å¼é©—證您的身份。在此步驟中ä¸æœƒå‘您收費。如果我們需è¦å‘您收費,我們會通知您。"
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method. You will not be charged during this step. If we ever need to charge you, we will let you know."
msgstr "在您建立群組之å‰ï¼Œæˆ‘們需è¦æ‚¨ä½¿ç”¨æœ‰æ•ˆçš„付款方å¼é©—證您的身份。在此步驟中ä¸æœƒå‘您收費。如果我們需è¦å‘您收費,我們會通知您。"
+msgid "IdentityVerification|Before you finish creating your account, we need to verify your identity. On the verification page, enter the following code."
+msgstr "在您完æˆå¸³è™Ÿå»ºç«‹å‰ï¼Œæˆ‘們需è¦é©—證您的身份。 請在驗證é é¢è¼¸å…¥ä»¥ä¸‹é©—證碼。"
+
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgstr "在您登入之å‰ï¼Œæˆ‘們需è¦é©—證您的身份,請在登入é é¢è¼¸å…¥ä»¥ä¸‹é©—證碼。"
+msgid "IdentityVerification|Confirm your email address"
+msgstr "請確èªæ‚¨çš„é›»å­éƒµä»¶åœ°å€"
+
msgid "IdentityVerification|Create a project"
msgstr "建立專案"
+msgid "IdentityVerification|Didn't receive a code?"
+msgstr "沒有收到驗證碼?"
+
+msgid "IdentityVerification|Enter a code."
+msgstr "輸入驗證碼。"
+
+msgid "IdentityVerification|Enter a valid code."
+msgstr "輸入有效的驗證碼。"
+
msgid "IdentityVerification|For added security, you'll need to verify your identity in a few quick steps."
-msgstr ""
+msgstr "為了增加安全性,您需è¦é€šéŽå¹¾å€‹å¿«é€Ÿæ­¥é©Ÿä¾†é©—證您的身份。"
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgstr "為了增加安全性,您需è¦é©—證您的身份。我們已發é€é©—證碼到 %{email}"
+msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification."
+msgstr "GitLab ä¸æœƒæ”¶å–或儲存您的付款信æ¯ï¼Œå®ƒåªæœƒè¢«ç”¨æ–¼é©—證。"
+
msgid "IdentityVerification|Help us keep GitLab secure"
-msgstr ""
+msgstr "å¹«åŠ©æˆ‘å€‘ç¶­æŒ GitLab 的安全"
msgid "IdentityVerification|Help us protect your account"
msgstr "幫助我們ä¿è­·æ‚¨çš„帳號"
@@ -19599,22 +19885,22 @@ msgid "IdentityVerification|If you've lost access to the email associated to thi
msgstr "如果您無法存å–與該帳號關è¯çš„é›»å­éƒµä»¶æˆ–驗證碼有å•é¡Œï¼Œ %{link_start}這裡是您å¯ä»¥æŽ¡å–的其他一些步驟。%{link_end}"
msgid "IdentityVerification|International dial code"
-msgstr ""
+msgstr "國際撥號代碼"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
msgstr "已超éŽæœ€å¤§ç™»å…¥å˜—試次數。等待 %{interval} 後å†é‡è©¦ã€‚"
msgid "IdentityVerification|Phone number"
-msgstr ""
+msgstr "電話號碼"
msgid "IdentityVerification|Phone number can't be blank."
-msgstr ""
+msgstr "電話號碼ä¸èƒ½ç‚ºç©ºã€‚"
msgid "IdentityVerification|Phone number must be %{maxLength} digits or fewer."
-msgstr ""
+msgstr "電話號碼最多åªèƒ½ç‚º %{maxLength} ä½æ•¸å­—。"
msgid "IdentityVerification|Phone number must contain only digits."
-msgstr ""
+msgstr "電話號碼åªèƒ½åŒ…å«æ•¸å­—。"
msgid "IdentityVerification|Please enter a valid code"
msgstr "請輸入有效的驗證碼"
@@ -19622,16 +19908,22 @@ msgstr "請輸入有效的驗證碼"
msgid "IdentityVerification|Resend code"
msgstr "é‡æ–°ç™¼é€é©—證碼"
+msgid "IdentityVerification|Send a new code"
+msgstr "發é€æ–°çš„驗證碼"
+
msgid "IdentityVerification|Send code"
-msgstr ""
+msgstr "發é€é©—證碼"
+
+msgid "IdentityVerification|Something went wrong. Please try again."
+msgstr "發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "IdentityVerification|Step 1: Verify phone number"
-msgstr ""
+msgstr " 步驟 1:驗證電話號碼"
-msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr "驗證碼已éŽæœŸï¼Œé‡æ–°ç™¼é€æ–°é©—證碼並é‡è©¦ã€‚"
+msgid "IdentityVerification|The code has expired. Send a new code and try again."
+msgstr "驗證碼已éŽæœŸï¼Œç™¼é€æ–°é©—證碼並é‡è©¦ã€‚"
-msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
+msgid "IdentityVerification|The code is incorrect. Enter it again, or send a new code."
msgstr "驗證碼ä¸æ­£ç¢ºï¼Œå†æ¬¡è¼¸å…¥æˆ–é‡æ–°ç™¼é€æ–°é©—證碼。"
msgid "IdentityVerification|Verification code"
@@ -19643,6 +19935,12 @@ msgstr "é©—è­‰æˆåŠŸ"
msgid "IdentityVerification|Verify code"
msgstr "æ ¸å°é©—證碼"
+msgid "IdentityVerification|Verify email address"
+msgstr "驗證您的電å­éƒµä»¶åœ°å€"
+
+msgid "IdentityVerification|Verify payment method"
+msgstr "確èªæ‚¨çš„付款方å¼"
+
msgid "IdentityVerification|Verify your identity"
msgstr "驗證您的身份"
@@ -19650,13 +19948,16 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr "您å¯ä»¥ç¨å¾Œéš¨æ™‚驗證您的帳號,來建立一個群組。"
msgid "IdentityVerification|You will receive a text containing a code. Standard charges may apply."
-msgstr ""
+msgstr "您將收到包å«é©—證碼的文字,å¯èƒ½æœƒæ”¶å–標準費用。"
+
+msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
+msgstr "您已é”到最大é‡æ–°ç™¼é€æ¬¡æ•¸ï¼Œ 請等待 %{interval} 後é‡è©¦ã€‚"
-msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr "您已é”到最大嘗試次數,等待 %{interval} 或é‡æ–°ç™¼é€æ–°é©—證碼並é‡è©¦ã€‚"
+msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
+msgstr "您已é”到最大嘗試次數,請等待 %{interval} 或發é€æ–°é©—證碼並é‡è©¦ã€‚"
-msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment or %{redirect_url_start}click here%{redirect_url_end} to refresh."
-msgstr "您的帳號已æˆåŠŸé©—證,ç¨å¾Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘至您的帳號或%{redirect_url_start}點擊此處%{redirect_url_end} 刷新。"
+msgid "IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}."
+msgstr "您的帳號已驗證完æˆï¼Œç¨å€™æ‚¨å°‡è¢«å°Žå‘到您的帳號。 您也å¯ä»¥%{redirect_url_start}刷新該é é¢%{redirect_url_end}。"
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "您的驗證碼將在 %{expires_in_minutes} 分é˜å¾ŒéŽæœŸã€‚"
@@ -19736,6 +20037,12 @@ msgstr "å¦‚æžœæ‚¨æœ€è¿‘æ²’æœ‰ç™»å…¥ï¼Œè«‹ç«‹å³ %{password_link_start}更改密ç
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "如果您最近沒有登入,請立å³æ›´æ”¹å¯†ç¢¼: %{password_link}。"
+msgid "If you did not recently try to sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr "如果您最近沒有嘗試登入,您應該立å³%{password_link_start}更改您的密碼%{password_link_end}。"
+
+msgid "If you did not recently try to sign in, you should immediately change your password: %{password_link}."
+msgstr "如果您最近沒有åšè©¦ç™»å…¥ï¼Œæ‚¨æ‡‰è©²ç«‹å³æ›´æ”¹æ‚¨çš„密碼: %{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 "如果您從版本庫檢查中得到大é‡èª¤å ±ï¼Œæ‚¨å¯ä»¥å¾žè³‡æ–™åº«ä¸­æ¸…除所有版本庫檢查訊æ¯ã€‚"
@@ -19745,6 +20052,9 @@ msgstr "如果您éºå¤±äº†å¾©åŽŸç¢¼ï¼Œæ‚¨å¯ä»¥ç”Ÿæˆæ–°çš„復原碼,所有以
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
msgstr "如果您最近從上述IP地å€ç™»å…¥éŽï¼Œå‰‡å¯ä»¥å¿½ç•¥æ­¤é›»å­éƒµä»¶ã€‚"
+msgid "If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email."
+msgstr "如果您最近嘗試登入,但ä¸å°å¿ƒè¼¸å…¥äº†éŒ¯èª¤çš„雙因å­é©—證碼,您也許å¯ä»¥å¿½ç•¥è©²é›»å­éƒµä»¶ã€‚"
+
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr "如果您想è¦é‡æ–°å•Ÿç”¨é›™å› å­èº«ä»½é©—證,請訪å•%{two_factor_link}"
@@ -19924,6 +20234,9 @@ msgstr "用以下方å¼é€£æŽ¥å„²å­˜åº«"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
msgstr "超éŽ%{provider}的速率é™åˆ¶ã€‚è«‹ç¨å¾Œå†è©¦"
+msgid "ImportProjects|Advanced import settings"
+msgstr ""
+
msgid "ImportProjects|Blocked import URL: %{message}"
msgstr "ç¦æ­¢çš„匯入URL: %{message}"
@@ -19948,6 +20261,9 @@ msgstr "å–得您的%{provider}版本庫失敗"
msgid "ImportProjects|Select the repositories you want to import"
msgstr "é¸æ“‡æ‚¨æƒ³è¦åŒ¯å…¥çš„版本庫"
+msgid "ImportProjects|The more information you select, the longer it will take to import"
+msgstr ""
+
msgid "ImportProjects|The remote data could not be imported."
msgstr "無法匯入é ç«¯è³‡æ–™ã€‚"
@@ -20823,7 +21139,7 @@ msgid "Include the username in the URL if required: %{code_open}https://username
msgstr "如果需è¦ï¼Œè«‹åœ¨URL中包å«ä½¿ç”¨è€…å:%{code_open}https://username@gitlab.company.com/group/project.git%{code_close}。"
msgid "Includes LFS objects. It can be overridden per group, or per project. Set to 0 for no limit."
-msgstr ""
+msgstr "包括 LFS 物件,它å¯ä»¥è¢«æ¯å€‹ç¾¤çµ„或æ¯å€‹å°ˆæ¡ˆè¦†å¯«ï¼Œè¨­å®šç‚º 0 表示沒有é™åˆ¶ã€‚"
msgid "Includes an MVC structure to help you get started"
msgstr "åŒ…å« MVC çµæ§‹ä»¥å¹«åŠ©æ‚¨å…¥é–€"
@@ -20852,6 +21168,9 @@ msgstr "未完æˆ"
msgid "Increase"
msgstr "增加"
+msgid "Indent line"
+msgstr "縮排"
+
msgid "Index"
msgstr "索引"
@@ -21072,6 +21391,9 @@ msgstr "加入整åˆ"
msgid "Integrations|Add namespace"
msgstr "加入命å空間"
+msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}."
+msgstr "加入一個僅é©ç”¨æ–¼å…許跨站點 cookie çš„ç€è¦½å™¨å‘½å空間。 %{linkStart}了解更多%{linkEnd}。"
+
msgid "Integrations|All details"
msgstr "所有詳細訊æ¯"
@@ -21132,12 +21454,18 @@ msgstr "啟用 SSL 驗證"
msgid "Integrations|Enable comments"
msgstr "啟用留言評論"
+msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}."
+msgstr "確ä¿æ‚¨çš„æœå‹™å¯¦ä¾‹ URL 正確並且您的實例組態é…置是正確的。 %{linkStart}了解更多%{linkEnd}。"
+
msgid "Integrations|Enter your alias"
msgstr "輸入您的別å"
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "無法éˆæŽ¥å‘½å空間,請é‡è©¦ã€‚"
+msgid "Integrations|Failed to load Jira Connect Application ID. Please try again."
+msgstr "Jira Connect Application ID 載入失敗,請å†è©¦ä¸€æ¬¡ã€‚"
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr "載入命å空間失敗,請é‡è©¦ã€‚"
@@ -21150,6 +21478,9 @@ msgstr "無法登入 GitLab。"
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr "無法å–消éˆæŽ¥å‘½å空間,請é‡è©¦ã€‚"
+msgid "Integrations|Failed to update GitLab version. Please try again."
+msgstr "æ›´æ–° GitLab 版本失敗,請å†è©¦ä¸€æ¬¡ã€‚"
+
msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}."
msgstr "GitLab 管ç†å“¡å¯ä»¥è¨­å®šæ‰€æœ‰ç¾¤çµ„和專案é è¨­ç¹¼æ‰¿å’Œä½¿ç”¨çš„æ•´åˆï¼Œ 這些整åˆæ‡‰ç”¨æ–¼æ‰€æœ‰å°šæœªä½¿ç”¨è‡ªè¨‚設定的組和專案, 如果需è¦è¨­å®šï¼Œæ‚¨å¯ä»¥è¦†è“‹ä¸€å€‹çµ„或專案的自訂設定。 瞭解更多關於 %{integrations_link_start}實例級整åˆç®¡ç†%{link_end}。"
@@ -21241,7 +21572,7 @@ msgid "Integrations|Send notifications about project events to a Unify Circuit c
msgstr "將有關專案事件的通知發é€åˆ° Unify Circuit å°è©±ã€‚ %{docs_link}"
msgid "Integrations|Sign in to %{url}"
-msgstr ""
+msgstr "登入 %{url}"
msgid "Integrations|Sign in to GitLab"
msgstr "登入到 GitLab"
@@ -21342,9 +21673,6 @@ msgstr "é–“éš”"
msgid "Interval Pattern"
msgstr "循環週期"
-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 "從 13.1 版本起,您需è¦å…ˆ%{recreate_link_start}é‡å»ºç´¢å¼•%{link_end}æ‰èƒ½åŸ·è¡Œ%{reindexing_link_start}ä¸åœæ©Ÿé‡ç´¢å¼•%{link_end}å’Œ%{migrations_link_start}高級æœå°‹é·ç§»%{link_end}。"
-
msgid "Introducing Your DevOps Reports"
msgstr "介紹您的 DevOps 報告"
@@ -21736,6 +22064,12 @@ msgstr "正在使用授權æ¢æ¬¾ï¼š"
msgid "Is using seat"
msgstr "正在使用許å¯å¸­æ¬¡"
+msgid "IssuableEvents|removed review request for"
+msgstr "已移除審查請求"
+
+msgid "IssuableEvents|requested review from"
+msgstr "審查è¦æ±‚"
+
msgid "IssuableStatus|%{wi_type} created %{created_at} by "
msgstr "%{wi_type} 創建者 %{created_at}"
@@ -21835,6 +22169,9 @@ msgstr "載入議題失敗。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "IssueAnalytics|Issue"
msgstr "議題"
+msgid "IssueAnalytics|Iteration"
+msgstr "迭代"
+
msgid "IssueAnalytics|Milestone"
msgstr "里程碑"
@@ -22207,9 +22544,6 @@ msgstr "無法ä¿å­˜é€±æœŸï¼Œè«‹é‡è©¦ã€‚"
msgid "Iterations|Upcoming iterations"
msgstr "å³å°‡åˆ°ä¾†çš„迭代"
-msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr "日期ä¸èƒ½èˆ‡è©²ç¾¤çµ„內的其它ç¾æœ‰è¿­ä»£é‡ç–Š"
-
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
msgstr "日期ä¸èƒ½èˆ‡æ­¤è¿­ä»£é€±æœŸå…§çš„其他ç¾æœ‰è¿­ä»£é‡ç–Š"
@@ -22950,7 +23284,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr "å‡ç´š%{labelTitle}將使其å¯ç”¨æ–¼%{groupName}內的所有專案。ç¾æœ‰çš„åŒå專案標記將被åˆä½µã€‚ç¾æœ‰çš„åŒå群組標記也將被åˆä½µã€‚該æ“作ä¸å¯æ’¤éŠ·ã€‚"
msgid "Label|Assignee"
-msgstr ""
+msgstr "å—指派者"
msgid "Language"
msgstr "語言"
@@ -23055,6 +23389,9 @@ msgstr "上次登入於:"
msgid "Last successful update"
msgstr "最近æˆåŠŸçš„æ›´æ–°"
+msgid "Last successful update %{time}."
+msgstr "最近一次æˆåŠŸæ›´æ–°æ–¼ %{time}。"
+
msgid "Last time verified"
msgstr "最近一次驗證"
@@ -23136,8 +23473,8 @@ msgstr "了解GitLab如何 %{no_packages_link_start}發布和共享您的包%{no
msgid "Learn more"
msgstr "進一步了解"
-msgid "Learn more about %{username}"
-msgstr "進一步了解%{username}"
+msgid "Learn more about %{name}"
+msgstr "了解關於 %{name} 的更多資訊"
msgid "Learn more about Auto DevOps"
msgstr "了解更多關於Auto DevOps"
@@ -23902,7 +24239,7 @@ msgid "Mailgun events"
msgstr "Mailgun事件"
msgid "Main menu"
-msgstr ""
+msgstr "主é¸å–®"
msgid "Maintenance mode"
msgstr "維護模å¼"
@@ -23919,6 +24256,9 @@ msgstr "GitLab Geoå¯ä»¥å»ºç«‹GitLab實體的唯讀é¡åƒ, 使得從é ç«¯è¤‡è£½
msgid "Make issue confidential"
msgstr "將議題設定為機密。"
+msgid "Make sure you choose a strong, unique password."
+msgstr "確定您é¸æ“‡äº†ä¸€å€‹é«˜å¼·åº¦ä¸”唯一的密碼。"
+
msgid "Make sure you have the correct permissions to link your project."
msgstr "確ä¿æ‚¨å…·æœ‰éˆæŽ¥å°ˆæ¡ˆçš„正確權é™ã€‚"
@@ -23970,12 +24310,12 @@ msgstr "管ç†å°ˆæ¡ˆã€‚"
msgid "Manage two-factor authentication"
msgstr "管ç†é›™å› å­é©—è­‰"
-msgid "Manage your license"
-msgstr "管ç†æ‚¨çš„授權許å¯"
-
msgid "Manage your project's triggers"
msgstr "管ç†æ‚¨çš„專案觸發器"
+msgid "Manage your subscription"
+msgstr ""
+
msgid "Managed Account"
msgstr "託管帳號"
@@ -24057,9 +24397,24 @@ msgstr "加入刪除線文本 (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "加入帶刪除線的文本 (%{modifier_key}⇧X)"
+msgid "MarkdownEditor|Indent line (%{modifierKey}])"
+msgstr "縮排 (%{modifierKey}])"
+
+msgid "MarkdownEditor|Indent line (%{modifier_key}])"
+msgstr "縮排 (%{modifier_key}])"
+
+msgid "MarkdownEditor|Outdent line (%{modifierKey}[)"
+msgstr "凸排 (%{modifierKey}[)"
+
+msgid "MarkdownEditor|Outdent line (%{modifier_key}[)"
+msgstr "凸排 (%{modifier_key}[)"
+
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgstr "支æ´%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgid "Marked"
+msgstr "已標記"
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "標記刪除於 - %{deletion_time}"
@@ -24069,9 +24424,6 @@ msgstr "標記為è‰ç¨¿ã€‚åªæœ‰åœ¨æ¨™è¨˜ç‚ºå°±ç·’後æ‰èƒ½åˆä½µã€‚"
msgid "Marked as ready. Merging is now allowed."
msgstr "標記為已準備好。ç¾åœ¨å…許åˆä½µã€‚"
-msgid "Marked this %{noun} as a draft."
-msgstr "已標記此%{noun}為è‰ç¨¿ã€‚"
-
msgid "Marked this %{noun} as ready."
msgstr "已將 %{noun} 標記為準備就緒。"
@@ -24084,8 +24436,8 @@ msgstr "將此議題標記為%{issue_ref}的相關議題。"
msgid "Marked to do as done."
msgstr "將待辦事項標記為已完æˆã€‚"
-msgid "Marks this %{noun} as a draft."
-msgstr "將標記此%{noun}為è‰ç¨¿ã€‚"
+msgid "Marks"
+msgstr "標記"
msgid "Marks this %{noun} as ready."
msgstr "標記該 %{noun} 為準備就緒。"
@@ -24193,7 +24545,7 @@ msgid "Maximum allowable lifetime for access token (days)"
msgstr "å­˜å–令牌(權æ–)的最大å…許壽命(天)"
msgid "Maximum allowed lifetime for SSH keys (days)"
-msgstr ""
+msgstr "SSH 金鑰å…許的最長生命週期(天)"
msgid "Maximum artifacts size"
msgstr "最大工件大å°"
@@ -24321,6 +24673,9 @@ msgstr "æ¯å€‹åŽŸå§‹è·¯å¾‘æ¯åˆ†é˜çš„最大請求數(é è¨­ç‚º 300)。設å®
msgid "Maximum number of unique IP addresses per user."
msgstr "æ¯å€‹ä½¿ç”¨è€…的最大唯一 IP 地å€æ•¸ã€‚"
+msgid "Maximum number of variables loaded (2000)"
+msgstr "è¼‰å…¥çš„æœ€å¤§è®Šæ•¸æ•¸é‡ (2000)"
+
msgid "Maximum of 255 characters"
msgstr "最多 255 個字元"
@@ -24606,7 +24961,7 @@ msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to co
msgstr "åˆä½µå·²ç¦æ­¢ï¼šæµæ°´ç·šå¿…é ˆæˆåŠŸã€‚正在等待手動作業繼續。"
msgid "Merge blocked: the source branch must be rebased onto the target branch."
-msgstr "åˆä½µç¦æ­¢ï¼šä¾†æºåˆ†æ”¯å¿…須變基(rebase)到目標分支。"
+msgstr "åˆä½µç¦æ­¢ï¼šä¾†æºåˆ†æ”¯å¿…須變基 (Rebase) 到目標分支。"
msgid "Merge commit SHA"
msgstr "åˆä½µæ交SHA"
@@ -24675,7 +25030,7 @@ msgid "Merge requests"
msgstr "åˆä½µè«‹æ±‚"
msgid "Merge requests and approvals settings have moved."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚與核准設定已被移動。"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆä½µè«‹æ±‚用於æ出å°å°ˆæ¡ˆçš„變更並與他人進行討論"
@@ -24771,10 +25126,10 @@ msgid "MergeRequests|Saving the comment failed"
msgstr "儲存留言失敗"
msgid "MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch."
-msgstr "壓縮失敗:壓縮本地æ交,解決任何存在的è¡çªï¼Œç„¶å¾ŒæŽ¨é€åˆ†æ”¯ã€‚"
+msgstr "壓縮 (Squash) 失敗:壓縮本地æ交,解決任何存在的è¡çªï¼Œç„¶å¾ŒæŽ¨é€åˆ†æ”¯ã€‚"
msgid "MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging."
-msgstr "ä¸å…許壓縮:此專案ä¸å…許您在åˆä½µæ™‚壓縮æ交。"
+msgstr "ä¸å…許壓縮 (Squash) : 此專案ä¸å…許您在åˆä½µæ™‚壓縮 (Squash) æ交。"
msgid "MergeRequests|Thread stays resolved"
msgstr "話題ä¿æŒå·²è§£æ±ºç‹€æ…‹"
@@ -25447,6 +25802,9 @@ msgstr "未開始的議題(開啟且尚未指派)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr "使用里程碑在固定時間內追蹤議題和åˆä½µè«‹æ±‚"
+msgid "Milestone|%{percentage}%{percent} complete"
+msgstr "%{percentage}%{percent} 完æˆ"
+
msgid "Min Value"
msgstr "最å°å€¼"
@@ -25471,6 +25829,9 @@ msgstr "é¡åƒè¨­å®šåƒ…GitLab管ç†å“¡å¯ç”¨ã€‚"
msgid "Mirror user"
msgstr "é¡åƒä½¿ç”¨è€…"
+msgid "Mirrored from %{link}."
+msgstr "來自於 %{link} çš„é¡åƒã€‚"
+
msgid "Mirrored repositories"
msgstr "é¡åƒçš„版本庫"
@@ -25550,7 +25911,7 @@ msgid "Monitor"
msgstr "監控"
msgid "Monitor GitLab with Prometheus."
-msgstr ""
+msgstr "使用 Prometheus 監控 GitLab。"
msgid "Monitor Settings"
msgstr "監控設定"
@@ -25735,6 +26096,9 @@ msgstr "å稱已被佔用。"
msgid "Name new label"
msgstr "命å新標記"
+msgid "Name to be used as the sender for emails from Service Desk."
+msgstr "用於æœå‹™å°é›»å­éƒµä»¶å¯„件者的å稱。"
+
msgid "Name:"
msgstr "å稱:"
@@ -25947,6 +26311,9 @@ msgstr "新增æµæ°´ç·šæŽ’程"
msgid "New Project"
msgstr "新增專案"
+msgid "New Protected Branch"
+msgstr "æ–°çš„å—ä¿è­·åˆ†æ”¯"
+
msgid "New Requirement"
msgstr "新增需求"
@@ -26224,7 +26591,7 @@ msgid "No credit card required."
msgstr "無需信用å¡ã€‚"
msgid "No data available"
-msgstr ""
+msgstr "沒有å¯ç”¨çš„資料"
msgid "No data found"
msgstr "未找到資料"
@@ -26446,6 +26813,9 @@ msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
msgstr[0] "ä¸ç”¨æ“”心,您ç¾åœ¨ä»ç„¶å¯ä»¥ä½¿ç”¨æ‰€æœ‰ %{strong}%{plan_name}%{strong_close} 功能。您有 %{remaining_days} 天來續訂您的訂閱。"
+msgid "No wrap"
+msgstr ""
+
msgid "No. of commits"
msgstr "æ交次數"
@@ -26540,7 +26910,7 @@ msgid "Note: Consider asking your GitLab administrator to configure %{github_int
msgstr "æ示:如GitLab管ç†å“¡é…ç½® %{github_integration_link},將å…許é€éŽGitHub登入並å…許匯入Github程å¼ç¢¼ç‰ˆæœ¬åº«è€Œä¸éœ€è¦å€‹äººå­˜å–令牌(權æ–)。"
msgid "Note: current forks will keep their visibility level."
-msgstr "注æ„:當å‰çš„分å‰ï¼ˆfork)將ä¿æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
+msgstr "注æ„:當å‰çš„分å‰ï¼ˆFork)將ä¿æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
msgid "NoteForm|Note"
msgstr "備註"
@@ -26600,7 +26970,7 @@ msgid "Nothing to preview."
msgstr "沒有å¯é è¦½çš„內容。"
msgid "Notification Email"
-msgstr ""
+msgstr "é›»å­éƒµä»¶é€šçŸ¥"
msgid "Notification events"
msgstr "通知事件"
@@ -26729,11 +27099,20 @@ msgstr "無法識別登入ä½ç½®æ™‚通éŽé›»å­éƒµä»¶é€šçŸ¥ä½¿ç”¨è€…。"
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr "%{author_link} çš„è­°é¡Œ %{issue_reference_link} å³å°‡åˆ°æœŸã€‚"
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr "%{author_name} %{action_name} %{ref_type} %{ref_name} 在 %{project_link}"
+
+msgid "Notify|%{changed_files}:"
+msgstr "%{changed_files}:"
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} 在 %{mr_link}"
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
-msgstr ""
+msgstr "%{commits_text} 來自於 `%{target_branch}` 分支"
+
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr "%{committed_by_start} 由 %{author_name} %{committed_by_end} %{committed_at_start} 在 %{committed_date} %{committed_at_end}"
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr "%{invite_email},ç¾åœ¨ç¨±ç‚º %{user_name},已接å—您的線請加入 %{target_name} %{target_model_name} 。"
@@ -26741,26 +27120,50 @@ msgstr "%{invite_email},ç¾åœ¨ç¨±ç‚º %{user_name},已接å—您的線請加å…
msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr "%{invited_user} 已 %{highlight_start}拒絕%{highlight_end} 您的加入 %{target_link} %{target_name} 邀請。"
+msgid "Notify|%{issues} imported."
+msgstr "已匯入 %{issues}。"
+
msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr "%{member_link} 已請求 %{member_role} å­˜å– %{target_source_link} %{target_type}。"
-msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
-msgstr "%{mr_highlight}åˆä½µè«‹æ±‚%{highlight_end} %{mr_link} %{approved_highlight}已被%{highlight_end} %{approver_avatar} %{approver_link}核准"
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}åˆä½µè«‹æ±‚%{highlight_end} %{mr_link} %{reviewer_highlight}被%{highlight_end} %{reviewer_avatar} %{reviewer_link}核准"
+
+msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}"
+msgstr "%{mr_highlight}åˆä½µè«‹æ±‚%{highlight_end} %{mr_link} %{reviewer_highlight}未被%{highlight_end} %{reviewer_avatar} %{reviewer_link}核准"
+
+msgid "Notify|%{name} requested a new review on %{mr_link}."
+msgstr "%{name} è«‹æ±‚å° %{mr_link} 進行新的審查。"
+
+msgid "Notify|%{p_start}To update the remote url in your local repository run (for ssh):%{p_end} %{ssh_url_to_repo} %{p_start}or for http(s):%{p_end} %{http_url_to_repo}"
+msgstr "%{p_start}è¦æ›´æ–°æœ¬åœ°ç‰ˆæœ¬åº«ä¸­çš„é ç«¯ URL,請é‹è¡Œï¼ˆssh):%{p_end} %{ssh_url_to_repo} %{p_start} 或 http(s):%{p_end} %{http_url_to_repo}"
msgid "Notify|%{paragraph_start}Hi %{name}!%{paragraph_end} %{paragraph_start}A new public key was added to your account:%{paragraph_end} %{paragraph_start}title: %{key_title}%{paragraph_end} %{paragraph_start}If this key was added in error, you can remove it under %{removal_link}%{paragraph_end}"
msgstr "%{paragraph_start}å—¨ %{name}!%{paragraph_end} %{paragraph_start}新的公鑰已加入到您的帳號:%{paragraph_end} %{paragraph_start}title:%{key_title}%{paragraph_end} %{paragraph_start}如果該公鑰加入錯誤,您å¯ä»¥åœ¨ %{removal_link}%{paragraph_end} 下將其移除"
+msgid "Notify|%{project_link_start}Download%{project_link_end} the project export."
+msgstr "%{project_link_start}下載%{project_link_end}匯出的專案。"
+
+msgid "Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}"
+msgstr "%{update_at_start} 最後更新時間為 %{update_at_mid} %{last_update_at} %{update_at_end}"
+
msgid "Notify|%{updated_by_user_name} pushed new commits to merge request %{mr_link}"
-msgstr ""
+msgstr "%{updated_by_user_name} 推é€æ–°çš„æ交到 %{mr_link} åˆä½µè«‹æ±‚"
msgid "Notify|A new GPG key was added to your account:"
msgstr "有支新的 GPG 金鑰已加至您的帳號:"
+msgid "Notify|A remote mirror update has failed."
+msgstr "é ç¨‹é¡åƒæ›´æ–°å¤±æ•—。"
+
+msgid "Notify|After it expires, you can %{a_start} request a new one %{a_end}."
+msgstr "到期後,您å¯ä»¥ %{a_start} 請求一個新的 %{a_end}。"
+
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
-msgstr ""
+msgstr "關於 %{mr_link} åˆä½µè«‹æ±‚的所有討論å‡ç”± %{name} 解決"
msgid "Notify|And %{total_stripped_new_commits_count} more"
-msgstr ""
+msgstr "還有 %{total_stripped_new_commits_count} 個"
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "被指派人從 %{fromNames} 更改為 %{toNames}"
@@ -26777,12 +27180,30 @@ msgstr "%{project} 的自動 DevOps æµæ°´ç·šå·²ç¦ç”¨"
msgid "Notify|CI/CD project settings"
msgstr "CI/CD 專案設定"
+msgid "Notify|Click here to set your password"
+msgstr "點擊此處來設定您的密碼"
+
+msgid "Notify|Commit Author"
+msgstr "æ交作者"
+
+msgid "Notify|Committed by"
+msgstr "æ交者"
+
msgid "Notify|Don't want to receive updates from GitLab administrators?"
-msgstr ""
+msgstr "ä¸æƒ³æŽ¥æ”¶ä¾†è‡ª GitLab 管ç†å“¡çš„更新?"
+
+msgid "Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values."
+msgstr "è§£æž CSV 文件時出錯。請確ä¿å®ƒå…·æœ‰æ­£ç¢ºçš„æ ¼å¼ï¼šä½¿ç”¨é€—號為分隔值的文件。"
+
+msgid "Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check if these lines have an issue title."
+msgstr "在 %{singular_or_plural_line} 上發ç¾éŒ¯èª¤ï¼š%{error_lines}。請檢查這些行是å¦æœ‰è­°é¡Œæ¨™é¡Œã€‚"
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr "指紋:%{fingerprint}"
+msgid "Notify|Hi %{username}!"
+msgstr "å—¨ %{username}!"
+
msgid "Notify|Hi %{user}!"
msgstr "%{user},歡迎使用ï¼"
@@ -26801,6 +27222,9 @@ msgstr "議題已移至其他專案"
msgid "Notify|Learn more about Auto DevOps"
msgstr "學習更多關於 Auto DevOps 的相關訊æ¯"
+msgid "Notify|Logs may contain sensitive data. Please consider before forwarding this email."
+msgstr "日誌å¯èƒ½åŒ…å«æ•æ„Ÿè³‡æ–™ï¼Œè«‹åœ¨è½‰å¯„該電å­éƒµä»¶ä¹‹å‰è€ƒæ…®ä¸€ä¸‹ã€‚"
+
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr "由於è¡çªï¼Œç„¡æ³•å†åˆä½µåˆä½µè«‹æ±‚ %{merge_request}。"
@@ -26825,24 +27249,66 @@ msgstr "åˆä½µè«‹æ±‚已被核准"
msgid "Notify|Merge request was approved (%{approvals}/%{required_approvals})"
msgstr "åˆä½µè«‹æ±‚已被 (%{approvals}/%{required_approvals}) 核准"
+msgid "Notify|Merge request was unapproved"
+msgstr "åˆä½µè«‹æ±‚未ç²æ‰¹å‡†"
+
+msgid "Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})"
+msgstr "åˆä½µè«‹æ±‚未ç²æ ¸å‡† (%{approvals_count}/%{approvals_required})"
+
msgid "Notify|Milestone changed to %{milestone}"
msgstr "里程碑已更改為 %{milestone}"
msgid "Notify|Milestone removed"
-msgstr ""
+msgstr "已移除里程碑"
msgid "Notify|New issue: %{project_issue_url}"
msgstr "新議題: %{project_issue_url}"
+msgid "Notify|No preview for this file type"
+msgstr "該文件類型無法é è¦½"
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "æµæ°´ç·š %{pipeline_link} 的觸發者為"
+msgid "Notify|Pipeline has been fixed and #%{pipeline_id} has passed!"
+msgstr "æµæ°´ç·šå·²ä¿®å¾©ï¼Œ#%{pipeline_id} 已通éŽï¼"
+
+msgid "Notify|Project %{old_path_with_namespace} was moved to another location."
+msgstr "專案 %{old_path_with_namespace} 已移到其他ä½ç½®ã€‚"
+
+msgid "Notify|Project %{project_name} was exported successfully."
+msgstr "專案 %{project_name} å·²æˆåŠŸåŒ¯å‡ºã€‚"
+
+msgid "Notify|Remote mirror"
+msgstr "é ç¨‹é¡åƒ"
+
+msgid "Notify|The Administrator created an account for you. Now you are a member of the company GitLab application."
+msgstr "管ç†å“¡å·²ç‚ºæ‚¨å»ºç«‹äº†ä¸€å€‹å¸³è™Ÿï¼Œç¾åœ¨æ‚¨æ˜¯å…¬å¸ GitLab 應用程å¼çš„æˆå“¡ã€‚"
+
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr "æµæ°´ç·š %{pipeline_link} çš„ Auto DevOps æµæ°´ç·šå¤±æ•—,且在 %{project_link} 中被ç¦ç”¨ã€‚為了在您的專案中使用 Auto DevOps æµæ°´ç·šï¼Œè«‹æŸ¥çœ‹ %{supported_langs_link},調整您的專案,並在您的 %{settings_link} 內開啟Auto DevOps æµæ°´ç·šã€‚"
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr "未包å«æ­¤æ–‡ä»¶çš„差異,因為它太大。"
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr "未包å«å·®ç•°ï¼Œå› ç‚ºå®ƒå¤ªå¤§ã€‚"
+
+msgid "Notify|The download link will expire in 24 hours."
+msgstr "該下載éˆçµå°‡åœ¨ 24 å°æ™‚後失效。"
+
+msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
+msgstr "該專案ç¾åœ¨ä½æ–¼ %{project_full_name_link_start}%{project_full_name}%{link_end} 下。"
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr "該推é€ä¸¦æœªåŒ…å«ä»»ä½•æ–°çš„æ交,而是強制推é€ä¾†åˆªé™¤ä¸‹åˆ—çš„æ交和更改。"
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr "該議題到期日: %{issue_due_date}"
+msgid "Notify|This link is valid for %{password_reset_token_valid_time}."
+msgstr "該éˆçµå° %{password_reset_token_valid_time} 是有效的。"
+
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgstr "除éžæ‚¨é€šéŽ %{time_start}%{time}%{time_end} 驗證您的網域,å¦å‰‡å®ƒå°‡å¾žæ‚¨çš„ GitLab 專案中移除。"
@@ -26855,12 +27321,33 @@ msgstr "您在一個議題中被æåŠã€‚"
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr "您在 %{mr_link} åˆä½µè«‹æ±‚中被æåŠ"
+msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
+msgstr "您已å–消訂閱 GitLab 管ç†å“¡é€šçŸ¥ã€‚"
+
+msgid "Notify|Your CSV import for project %{project_link} has been completed."
+msgstr "您 %{project_link} 專案的 CVS 匯入已完æˆã€‚"
+
+msgid "Notify|Your account has been created successfully."
+msgstr "您的帳號已æˆåŠŸå»ºç«‹ã€‚"
+
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgstr "您加入 %{target_to_join} %{target_type} 的請求已被 %{denied_tag}。"
msgid "Notify|currently supported languages"
msgstr "當å‰æ”¯æ´çš„語系"
+msgid "Notify|deleted"
+msgstr "已删除"
+
+msgid "Notify|login.........................................."
+msgstr "登入.........................................."
+
+msgid "Notify|pushed new"
+msgstr "新的推é€"
+
+msgid "Notify|pushed to"
+msgstr "推é€åˆ°"
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "在 %{stages} 中æˆåŠŸå®Œæˆäº† %{jobs}。"
@@ -26921,6 +27408,9 @@ msgstr "確定"
msgid "Object does not exist on the server or you don't have permissions to access it"
msgstr "物件在伺æœå™¨ä¸Šä¸å­˜åœ¨, 或者您沒有存å–它的權é™"
+msgid "Observability"
+msgstr "å¯è§€å¯Ÿæ€§"
+
msgid "Oct"
msgstr "10月"
@@ -26959,22 +27449,22 @@ msgid_plural "On %{end_date}, your trial will end and %{namespace_name} will be
msgstr[0] "在您的試用版於 %{end_date} çµæŸæ™‚,%{namespace_name} å°‡é™åˆ¶ç‚º %{free_user_limit} åæˆå“¡ã€‚"
msgid "On the left sidebar, select %{merge_requests_link} to view them."
-msgstr ""
+msgstr "在左å´é‚Šæ¬„中,é¸æ“‡ %{merge_requests_link} 以查看它們。"
msgid "On track"
msgstr "如期進行"
msgid "On-call Schedules"
-msgstr "排程待命中"
+msgstr "On-call 排程"
msgid "On-call schedules"
-msgstr "排程待命中"
+msgstr "On-call 排程"
msgid "On-demand scans run outside of the DevOps cycle and find vulnerabilities in your projects"
msgstr "ON-demand 掃æ在 DevOps 週期之外é‹è¡Œï¼Œä¸¦åœ¨æ‚¨çš„專案中發ç¾æ¼æ´ž"
msgid "OnCallScheduless|Any escalation rules that are using this schedule will also be deleted."
-msgstr "使用此排程的任何å‡ç´šè¦å‰‡ä¹Ÿå°‡è¢«åˆªé™¤ã€‚"
+msgstr "任何使用此排程的å‡ç´šè¦å‰‡ä¹Ÿå°‡è¢«åˆªé™¤ã€‚"
msgid "OnCallSchedules|1 day"
msgstr "1 天"
@@ -27081,6 +27571,9 @@ msgstr "輪æ›"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr "將警報直接分é…給特定的團隊æˆå“¡"
+msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
+msgstr "將警報直接發é€çµ¦åœ˜éšŠçš„特定æˆå“¡ã€‚è¦å­˜å–該功能,請è¦æ±‚ %{linkStart} 專案æ“有者%{linkEnd} 授予您至少維護者的角色。"
+
msgid "OnCallSchedules|Select participant"
msgstr "é¸æ“‡åƒèˆ‡è€…"
@@ -27346,7 +27839,7 @@ msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_st
msgstr "版本庫匯入後,å¯ä»¥é€šéŽSSH進行é¡åƒã€‚點擊%{link_start}此處%{link_end}了解更多."
msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
-msgstr "移除後將無法æ¢å¾©åˆ†å‰(fork)關係。此專案將無法å†å‘來æºå°ˆæ¡ˆæˆ–其他分å‰ç™¼é€æˆ–接收åˆä½µè«‹æ±‚。"
+msgstr "移除後將無法æ¢å¾©åˆ†å‰ï¼ˆFork)關係。此專案將無法å†å‘來æºå°ˆæ¡ˆæˆ–其他分å‰ç™¼é€æˆ–接收åˆä½µè«‹æ±‚。"
msgid "Once you confirm and press \"Reduce project visibility\":"
msgstr "一旦您確èªä¸¦æŒ‰ä¸‹\"é™ä½Žå°ˆæ¡ˆå¯è¦‹æ€§\":"
@@ -27640,6 +28133,9 @@ msgstr "GitLabå¯èƒ½ç„¡æ³•æ­£å¸¸å·¥ä½œï¼Œå› ç‚ºæ‚¨æ­£åœ¨ä½¿ç”¨éŽæ™‚çš„ç€è¦½å™¨
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "請安è£ä¸€å€‹%{browser_link_start}支æ´çš„網é ç€è¦½å™¨%{browser_link_end}以å–得更好的體驗。"
+msgid "Outdent line"
+msgstr "凸排"
+
msgid "Overridden"
msgstr "覆蓋"
@@ -27713,7 +28209,7 @@ msgid "Package already exists"
msgstr "軟體套件(Package)已存在"
msgid "Package and registry settings"
-msgstr ""
+msgstr "軟體套件和註冊表設定"
msgid "Package deleted successfully"
msgstr "軟體套件(Package)å·²æˆåŠŸåˆªé™¤"
@@ -27752,7 +28248,7 @@ msgid "Package type must be PyPi"
msgstr "軟體套件(Package)類型必須是PyPi"
msgid "Package type must be RPM"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是 RPM"
msgid "Package type must be RubyGems"
msgstr "軟體套件(Package)類型必須是 RubyGems"
@@ -27881,15 +28377,15 @@ msgid "PackageRegistry|Delete 1 asset"
msgid_plural "PackageRegistry|Delete %d assets"
msgstr[0] "刪除 %d 項資產"
-msgid "PackageRegistry|Delete Package File"
-msgstr "刪除軟體套件檔案"
-
msgid "PackageRegistry|Delete Package Version"
msgstr "刪除軟體套件版本"
msgid "PackageRegistry|Delete package"
msgstr "刪除軟體套件"
+msgid "PackageRegistry|Delete package asset"
+msgstr "刪除軟體套件資產"
+
msgid "PackageRegistry|Delete selected"
msgstr "刪除é¸å–"
@@ -27956,6 +28452,9 @@ msgstr "實例級別"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr "無效的軟體套件:元資料æå–失敗"
+msgid "PackageRegistry|Last downloaded %{dateTime}"
+msgstr "最後下載日期 %{dateTime}"
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "了解如何使用GitLab%{noPackagesLinkStart}發布和共享您的軟體套件%{noPackagesLinkEnd}。"
@@ -27989,15 +28488,15 @@ msgstr "è¦ä¿ç•™çš„é‡è¤‡è³‡ç”¢æ•¸é‡"
msgid "PackageRegistry|Package Registry"
msgstr "軟體套件註冊表"
+msgid "PackageRegistry|Package asset deleted successfully"
+msgstr "å·²æˆåŠŸåˆªé™¤è»Ÿé«”套件資產"
+
msgid "PackageRegistry|Package assets deleted successfully"
msgstr "å·²æˆåŠŸåˆªé™¤è»Ÿé«”套件資產"
msgid "PackageRegistry|Package deleted successfully"
msgstr "æˆåŠŸåˆªé™¤è»Ÿé«”套件"
-msgid "PackageRegistry|Package file deleted successfully"
-msgstr "æˆåŠŸåˆªé™¤è»Ÿé«”套件檔"
-
msgid "PackageRegistry|Package formats"
msgstr "軟體套件格å¼"
@@ -28008,6 +28507,9 @@ 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}發布到庫"
+msgid "PackageRegistry|Permanently delete"
+msgstr ""
+
msgid "PackageRegistry|Permanently delete assets"
msgstr "永久刪除資產"
@@ -28059,11 +28561,11 @@ msgstr "顯示 PyPi 指令"
msgid "PackageRegistry|Show Yarn commands"
msgstr "顯示 Yarn 指令"
-msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgid "PackageRegistry|Something went wrong while deleting the package asset."
msgstr "刪除軟體套件資產時發生錯誤。"
-msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr "刪除軟體套件檔時發生錯誤。"
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr "刪除軟體套件資產時發生錯誤。"
msgid "PackageRegistry|Something went wrong while deleting the package."
msgstr "刪除軟體套件時發生錯誤。"
@@ -28119,8 +28621,8 @@ msgstr "當具有相åŒå稱和版本的套件被上傳到註冊表時,更多
msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
msgstr "您將è¦åˆªé™¤ %{filename}。這是一種破壞性æ“作,å¯èƒ½æœƒä½¿æ‚¨çš„軟體套件無法使用。您確定嗎?"
-msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr "您將è¦åˆªé™¤%{name},此æ“作ä¸å¯é€†ï¼Œç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
+msgid "PackageRegistry|You are about to delete %{name}, are you sure?"
+msgstr ""
msgid "PackageRegistry|You are about to delete 1 asset. This operation is irreversible."
msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
@@ -28142,7 +28644,7 @@ msgid "PackageRegistry|published by %{author}"
msgstr "由%{author}發布"
msgid "Packages and registries"
-msgstr ""
+msgstr "軟體套件與註冊表"
msgid "Page not found"
msgstr "找ä¸åˆ°é é¢"
@@ -28333,9 +28835,6 @@ msgstr "使用速率é™åˆ¶ä¿è­·çš„路徑"
msgid "Pause"
msgstr "æš«åœ"
-msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr "æš«åœç´¢å¼•ä¸¦å°‡ Elasticsearch å‡ç´šåˆ°å—支æ´çš„版本。"
-
msgid "Pause time (ms)"
msgstr "æš«åœæ™‚é–“ (ms)"
@@ -28469,7 +28968,7 @@ msgid "Period of inactivity (days)"
msgstr "未活動時間(天)"
msgid "Period of inactivity before deactivation."
-msgstr ""
+msgstr "åœç”¨å‰çš„未活動的時間。"
msgid "Permalink"
msgstr "永久連çµ"
@@ -28738,9 +29237,21 @@ msgstr "已啟用"
msgid "PipelineSchedules|All"
msgstr "所有"
+msgid "PipelineSchedules|Delete pipeline schedule"
+msgstr ""
+
+msgid "PipelineSchedules|Description"
+msgstr ""
+
+msgid "PipelineSchedules|Edit pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Inactive"
msgstr "未啟用"
+msgid "PipelineSchedules|Last Pipeline"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr "下次執行時間"
@@ -28750,15 +29261,27 @@ msgstr "ç„¡"
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr "åªæœ‰æµæ°´ç·šæŽ’程的所有者,æ‰èƒ½å°å…¶é€²è¡Œè®Šæ›´ã€‚您是å¦è¦å–得這個排程的所有權?"
+msgid "PipelineSchedules|Owner"
+msgstr ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "為此æµæ°´ç·šæ供簡短æè¿°"
+msgid "PipelineSchedules|Run pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr "å–得所有權"
+msgid "PipelineSchedules|Take ownership of pipeline schedule"
+msgstr ""
+
msgid "PipelineSchedules|Target"
msgstr "目標"
+msgid "PipelineSchedules|There was a problem fetching pipeline schedules."
+msgstr ""
+
msgid "PipelineSchedules|Variables"
msgstr "變數"
@@ -28873,6 +29396,12 @@ msgstr "「%{project_name}ã€çš„æµæ°´ç·šè¨­å®šå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Pipelines|\"Hello world\" with GitLab CI"
msgstr "使用 GitLab CI å¯¦ç¾ \"Hello world\""
+msgid "Pipelines|%{jobs} %{ref_text} in %{duration}"
+msgstr "%{jobs} %{ref_text} æŒçºŒ %{duration}"
+
+msgid "Pipelines|(queued for %{queued_duration})"
+msgstr "(排隊等待 %{queued_duration})"
+
msgid "Pipelines|1. Set up a runner"
msgstr "1.設定執行器"
@@ -29186,7 +29715,7 @@ msgid "Pipeline|Manual"
msgstr "手動"
msgid "Pipeline|Merge request pipeline"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚æµæ°´ç·š"
msgid "Pipeline|Merge train pipeline"
msgstr "åˆä½µä½‡åˆ—æµæ°´ç·š"
@@ -29554,6 +30083,9 @@ msgstr "請輸入%{phrase_code}以繼續或關閉此å°è©±æ¡†ä»¥å–消。"
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "請使用此表單å‘管ç†å“¡å ±å‘Šå»ºç«‹åžƒåœ¾è­°é¡Œã€ç•™è¨€æˆ–行為ä¸ç•¶çš„使用者。"
+msgid "Please wait a few moments while we load the file history for this line."
+msgstr "è«‹ç¨å€™ï¼Œæˆ‘們正在載入此行的檔案歷å²ç´€éŒ„。"
+
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr "è«‹ç¨ç­‰ç‰‡åˆ»ï¼Œæ­¤é é¢åœ¨å°±ç·’時會自動é‡æ–°æ•´ç†ã€‚"
@@ -29563,6 +30095,9 @@ msgstr "連接程å¼ç¢¼ç‰ˆæœ¬åº«ä¸­ï¼Œè«‹ç¨å€™ã€‚å¯åœ¨ä»»æ„時刻é‡æ–°æ•´ç†
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "匯入程å¼ç¢¼ç‰ˆæœ¬åº«ä¸­ï¼Œè«‹ç¨å€™ã€‚å¯åœ¨ä»»æ„時刻é‡æ–°æ•´ç†ä»¥è®€å–ç›®å‰ç‹€æ…‹ã€‚"
+msgid "Please wait while we prepare for verification."
+msgstr "è«‹ç¨å€™ï¼Œæˆ‘們正在準備驗證。"
+
msgid "Pods in use"
msgstr "正在使用的Pod"
@@ -29623,6 +30158,9 @@ msgstr "å好設定"
msgid "Preferences saved."
msgstr "å好設定已儲存。"
+msgid "Preferences|Automatically add new list items"
+msgstr ""
+
msgid "Preferences|Behavior"
msgstr "個人化"
@@ -29630,7 +30168,7 @@ msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage})
msgstr "為應用程å¼é¸æ“‡å›ºå®šæ–¹å¼(最大值1280px)或æµå‹•æ–¹å¼(%{percentage})佈局。"
msgid "Preferences|Choose what content you want to see by default on your dashboard."
-msgstr ""
+msgstr "é¸æ“‡æ‚¨å¸Œæœ›åœ¨å„€è¡¨æ¿ä¸Šé è¨­çœ‹åˆ°çš„內容。"
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "é¸æ“‡å°ˆæ¡ˆæ¦‚覽é é¢ä¸­æ‚¨æƒ³çœ‹åˆ°çš„內容。"
@@ -29657,7 +30195,7 @@ msgid "Preferences|Customize the colors of removed and added lines in diffs."
msgstr "自定義差異中的刪除和加入行的é¡è‰²ã€‚"
msgid "Preferences|Dashboard"
-msgstr ""
+msgstr "儀表æ¿"
msgid "Preferences|Diff colors"
msgstr "差異比å°é¡è‰²"
@@ -29699,7 +30237,7 @@ msgid "Preferences|Project overview content"
msgstr "專案概覽內容"
msgid "Preferences|Render whitespace characters in the Web IDE"
-msgstr "åœ¨ç¶²é  IDE 繪製空白字元"
+msgstr "在 Web IDE 繪製空白字元"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
msgstr "在åˆä½µè«‹æ±‚的變更標籤上一次åªé¡¯ç¤ºä¸€å€‹æ–‡ä»¶"
@@ -29734,6 +30272,9 @@ msgstr "時å€è¨­å®š"
msgid "Preferences|Use relative times"
msgstr "使用相å°æ™‚é–“"
+msgid "Preferences|When you type in a description or comment box, pressing %{kbdOpen}Enter%{kbdClose} in a list adds a new item below."
+msgstr ""
+
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "當您在æ述或留言框中輸入時,在輸入以下字元之一後,é¸å®šçš„文本將被相應的字元包åœï¼š%{supported_characters}。"
@@ -29753,7 +30294,7 @@ msgid "Prevent environment from auto-stopping"
msgstr "ç¦æ­¢ç’°å¢ƒè‡ªå‹•åœæ­¢"
msgid "Prevent project forking outside current group"
-msgstr "ç¦æ­¢å°ˆæ¡ˆåˆ†å‰(fork)到當å‰ç¾¤çµ„以外"
+msgstr "ç¦æ­¢å°ˆæ¡ˆåˆ†å‰ï¼ˆFork)到當å‰ç¾¤çµ„以外"
msgid "Prevent users from changing their profile name"
msgstr "ç¦æ­¢ä½¿ç”¨è€…變更個人檔案å稱"
@@ -29947,15 +30488,9 @@ msgstr "活動"
msgid "Profiles|Add key"
msgstr "加入金鑰"
-msgid "Profiles|Add status emoji"
-msgstr "在狀態中加入表情符號"
-
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "更新您的使用者å稱時發生錯誤,請é‡è©¦ã€‚"
-msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr "在您的å字和頭åƒæ—邊顯示標識。"
-
msgid "Profiles|Avatar cropper"
msgstr "é ­åƒè£å‰ª"
@@ -29968,9 +30503,6 @@ msgstr "以 %{ssh_key_algorithms} 開頭。"
msgid "Profiles|Bio"
msgstr "自我介紹"
-msgid "Profiles|Busy"
-msgstr "忙碌中"
-
msgid "Profiles|Change username"
msgstr "變更使用者å稱"
@@ -29986,9 +30518,6 @@ msgstr "é¸æ“‡åœ¨å…¬é–‹å€‹äººè³‡æ–™ä¸­é¡¯ç¤ºç§æœ‰å°ˆæ¡ˆçš„è²¢ç»ï¼Œä½†ä¸é¡¯ç¤º
msgid "Profiles|City, country"
msgstr "城市,國家"
-msgid "Profiles|Clear status"
-msgstr "清除狀態"
-
msgid "Profiles|Commit email"
msgstr "æ交郵件"
@@ -30001,6 +30530,9 @@ msgstr "連接第三方登入æœå‹™ã€‚"
msgid "Profiles|Connected Accounts"
msgstr "已連線帳號"
+msgid "Profiles|Created%{time_ago}"
+msgstr "已建立於 %{time_ago}"
+
msgid "Profiles|Current path: %{path}"
msgstr "ç›®å‰è·¯å¾‘: %{path}"
@@ -30238,9 +30770,6 @@ msgstr "姓å中使用表情符號雖然有趣,但請å‰å¾€ç‹€æ…‹è¨Šæ¯è£¡ä½¿
msgid "Profiles|Website url"
msgstr "網站 URL"
-msgid "Profiles|What's your status?"
-msgstr "您目å‰çš„狀態?"
-
msgid "Profiles|Who you represent or work for."
msgstr "這個訊æ¯å°‡æœƒé¡¯ç¤ºåœ¨æ‚¨çš„個人資料中。"
@@ -30286,9 +30815,6 @@ msgstr "您的姓å是根據您的 %{provider_label} 帳號自動設定的,ä»
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr "您的姓å是根據您的 %{provider_label} 帳號自動設定的,以便大家èªè­˜æ‚¨."
-msgid "Profiles|Your status"
-msgstr "您目å‰çš„狀態?"
-
msgid "Profiles|https://website.com"
msgstr "https://website.com"
@@ -30770,13 +31296,16 @@ msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œå¾©é¸æ¡†æ˜¯å¯è¦‹å’Œæœªé¸å–的。"
msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
-msgstr "為åˆä½µè«‹æ±‚é¸æ“‡æ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮。您還å¯ä»¥ç‚ºä¸åŒçš„æ“作設定åˆä½µè«‹æ±‚模æ¿ã€‚"
+msgstr "為åˆä½µè«‹æ±‚é¸æ“‡æ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮 (Squash) 。您還å¯ä»¥ç‚ºä¸åŒçš„æ“作設定åˆä½µè«‹æ±‚模æ¿ã€‚"
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "è«‹é¸æ“‡æ‚¨çš„åˆä½µæ–¹æ³•ã€åˆä½µé¸é …ã€åˆä½µæª¢æŸ¥ä»¥åŠåˆä½µå»ºè­°ã€‚"
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
-msgstr "é¸æ“‡æ‚¨çš„åˆä½µæ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮é¸é …。"
+msgstr "é¸æ“‡æ‚¨çš„åˆä½µæ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮 (Squash) é¸é …。"
+
+msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
+msgstr " çµåˆ git 標籤與發布說明ã€ç™¼å¸ƒè­‰æ“šå’Œè³‡ç”¢ä¾†å»ºç«‹ç™¼å¸ƒã€‚"
msgid "ProjectSettings|Configure your project resources and monitor their health."
msgstr "設定您的專案資æºä¸¦ç›£æŽ§å®ƒå€‘的執行狀æ³ã€‚"
@@ -30808,6 +31337,9 @@ msgstr "啟用åˆä½µä½‡åˆ—"
msgid "ProjectSettings|Enable merged results pipelines"
msgstr "啟用åˆä½µçµæžœæµæ°´ç·š"
+msgid "ProjectSettings|Enable suggested reviewers"
+msgstr "啟用建議的審查者"
+
msgid "ProjectSettings|Encourage"
msgstr "激勵"
@@ -30854,7 +31386,7 @@ msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan w
msgstr "用於在此專案中å”作開發想法和計劃工作的éˆæ´»å·¥å…·ã€‚"
msgid "ProjectSettings|Forks"
-msgstr "分å‰"
+msgstr "分å‰ï¼ˆFork)"
msgid "ProjectSettings|Git Large File Storage (LFS)"
msgstr "Git大文件儲存 (LFS)"
@@ -30872,7 +31404,7 @@ msgid "ProjectSettings|How do they differ?"
msgstr "它們有何ä¸åŒï¼Ÿ"
msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
-msgstr "如果啟用了åˆä½µä½‡åˆ—,則åªæœ‰åœ¨å¯ä»¥é‡æ–°è¨­å®šåˆ†æ”¯è€Œä¸ç™¼ç”Ÿè¡çªçš„情æ³ä¸‹æ‰èƒ½é€²è¡Œåˆä½µã€‚"
+msgstr "如果啟用了åˆä½µä½‡åˆ—,則åªæœ‰åœ¨åˆ†æ”¯å¯ä»¥ä¸ç™¼ç”Ÿè¡çªçš„情æ³ä¸‹è®ŠåŸº (Rebase) æ‰èƒ½é€²è¡Œåˆä½µã€‚"
msgid "ProjectSettings|Internal"
msgstr "內部"
@@ -30931,12 +31463,18 @@ msgstr "åˆä½µå»ºè­°"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
msgstr "åªæœ‰ç•¶ä¾†æºåˆ†æ”¯èˆ‡å…¶ç›®æ¨™æ˜¯æœ€æ–°çš„時候,æ‰å…許åˆä½µã€‚"
+msgid "ProjectSettings|Monitor"
+msgstr "監控"
+
msgid "ProjectSettings|No merge commits are created."
msgstr "沒有建立åˆä½µæ交。"
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr "注æ„:當專案是公共的並且容器映åƒåº«è¨­å®šç‚ºã€Œ%{access_level_description}ã€æ™‚,容器映åƒåº«å§‹çµ‚å¯è¦‹"
+msgid "ProjectSettings|Only commits that include a %{code_block_start}Signed-off-by:%{code_block_end} element can be pushed to this repository."
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç°½ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ç‰ˆæœ¬åº«ã€‚"
@@ -30973,6 +31511,9 @@ msgstr "專案å¯è¦‹æ€§"
msgid "ProjectSettings|Public"
msgstr "公開的"
+msgid "ProjectSettings|Releases"
+msgstr "發布"
+
msgid "ProjectSettings|Repository"
msgstr "版本庫"
@@ -31022,16 +31563,16 @@ msgid "ProjectSettings|Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "ProjectSettings|Squash commit message template"
-msgstr "壓縮æ交訊æ¯æ¨¡æ¿"
+msgstr "壓縮 (Squash) æ交訊æ¯æ¨¡æ¿"
msgid "ProjectSettings|Squash commits when merging"
-msgstr "åˆä½µæ™‚壓縮æ交"
+msgstr "åˆä½µæ™‚壓縮 (Squash) æ交"
msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
-msgstr "總是執行壓縮。複é¸æ¡†æ˜¯å¯è¦‹çš„並處於é¸å–狀態,使用者無法更改它。"
+msgstr "總是執行壓縮 (Squash) ,複é¸æ¡†æ˜¯å¯è¦‹çš„並處於é¸å–狀態,使用者無法更改它。"
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
-msgstr "æ°¸é ä¸æœƒåŸ·è¡Œå£“縮,且該複é¸æ¡†æ˜¯éš±è—的。"
+msgstr "æ°¸é ä¸æœƒåŸ·è¡Œå£“縮 (Squash) ,且該複é¸æ¡†æ˜¯éš±è—的。"
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr "æ交è¦åˆä½µåˆ°ä¸Šæ¸¸çš„更改。"
@@ -31046,7 +31587,7 @@ msgid "ProjectSettings|The commit message used when merging, if the merge method
msgstr "åˆä½µæ™‚使用的æ交訊æ¯ï¼Œå¦‚æžœåˆä½µæ–¹æ³•å»ºç«‹äº†åˆä½µæ交。"
msgid "ProjectSettings|The commit message used when squashing commits."
-msgstr "壓縮æ交時使用的æ交訊æ¯ã€‚"
+msgstr "壓縮 (Squash) æ交時使用的æ交訊æ¯ã€‚"
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr "在此分å‰å°ˆæ¡ˆä¸­å»ºç«‹çš„åˆä½µè«‹æ±‚çš„é è¨­ç›®æ¨™å°ˆæ¡ˆã€‚"
@@ -31118,16 +31659,16 @@ msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD con
msgstr "在 CI/CD 設定文件中啟用åˆä½µè«‹æ±‚æµæ°´ç·šæ™‚,æµæ°´ç·šæœƒé©—證來æºåˆ†æ”¯å’Œç›®æ¨™åˆ†æ”¯çš„åˆä½µçµæžœã€‚%{link_start}如何設定åˆä½µè«‹æ±‚æµæ°´ç·šï¼Ÿ%{link_end}"
msgid "ProjectSettings|When semi-linear merge is not possible, the user is given the option to rebase."
-msgstr "當åŠç·šæ€§åˆä½µä¸å¯èƒ½æ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸº(rebase)。"
+msgstr "當無法進行åŠç·šæ€§åˆä½µæ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸº (Rebase) 。"
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
-msgstr "當出ç¾åˆä½µè¡çªæ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸºï¼ˆrebase)。"
+msgstr "當出ç¾åˆä½µè¡çªæ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸº (Rebase) 。"
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr "使用GitLab Pages,您å¯ä»¥åœ¨GitLab上託管éœæ…‹ç¶²ç«™ã€‚"
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute."
+msgstr "使用 GitLab Pages,您å¯ä»¥åœ¨ GitLab 上託管您的éœæ…‹ç¶²ç«™ã€‚ GitLab Pages 使用快å–機制來æ高效率,在快å–失效之å‰ï¼Œæ‚¨çš„æ›´å‹•å¯èƒ½ä¸æœƒç”Ÿæ•ˆï¼Œé€™é€šå¸¸éœ€è¦ä¸åˆ°ä¸€åˆ†é˜çš„時間。"
msgid "ProjectTemplates|.NET Core"
msgstr ".NET Core"
@@ -31216,6 +31757,9 @@ msgstr "Tencent Serverless 框架/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
+msgid "ProjectTransfer|An error occurred fetching the transfer locations, please refresh the page and try again."
+msgstr "æ“·å–傳輸ä½ç½®æ™‚發生錯誤,請刷新é é¢ä¸¦é‡è©¦ã€‚"
+
msgid "ProjectView|Activity"
msgstr "å‹•æ…‹"
@@ -31307,7 +31851,7 @@ msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr "此功能需è¦ç€è¦½å™¨æ”¯æ´æœ¬åœ°å„²å­˜"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
-msgstr "å…許您立å³è¤‡è£½é€™å€‹å°ˆæ¡ˆçš„版本庫。如果您計劃推é€ä¸€å€‹ç¾æœ‰çš„版本庫,請跳éŽé€™å€‹æ­¥é©Ÿã€‚"
+msgstr "å…許您立å³å…‹éš† (Clone) 這個專案的版本庫。如果您計劃推é€ä¸€å€‹ç¾æœ‰çš„版本庫,請跳éŽé€™å€‹æ­¥é©Ÿã€‚"
msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
msgstr "分æžæºç¨‹å¼ç¢¼æŸ¥æ‰¾å·²çŸ¥å®‰å…¨æ¼æ´ž."
@@ -31738,6 +32282,9 @@ msgstr "å…許推é€"
msgid "ProtectedBranch|Allowed to push:"
msgstr "å…許推é€ï¼š"
+msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again."
+msgstr "載入分支è¦å‰‡æ™‚發生錯誤,請é‡è©¦ä¸€æ¬¡ã€‚"
+
msgid "ProtectedBranch|Branch"
msgstr "分支"
@@ -31774,6 +32321,9 @@ msgstr "å—ä¿è­·åˆ†æ”¯ (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
msgstr "å—ä¿è­·åˆ†æ”¯"
+msgid "ProtectedBranch|Protected branches, merge request approvals, and status checks will appear here once configured."
+msgstr "å—ä¿è­·çš„分支ã€åˆä½µè«‹æ±‚核准和狀態檢查將在組態設定後顯示於此。"
+
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
msgstr "拒絕程å¼ç¢¼æŽ¨é€æ›´æ”¹ CODEOWNERS 文件中列出的文件。"
@@ -31798,6 +32348,9 @@ msgstr "å–消ä¿è­·åˆ†æ”¯"
msgid "ProtectedBranch|What are protected branches?"
msgstr "什麼是å—ä¿è­·çš„分支?"
+msgid "ProtectedBranch|You can add only groups that have this project shared. %{learn_more_link}"
+msgstr "您åªèƒ½å¢žåŠ å…±äº«æ­¤å°ˆæ¡ˆçš„群組。 %{learn_more_link}"
+
msgid "ProtectedBranch|default"
msgstr "é è¨­"
@@ -31805,7 +32358,7 @@ msgid "ProtectedEnvironment|%{environment_name} will be writable for developers.
msgstr "%{environment_name} å°‡å°é–‹ç™¼äººå“¡å¯å¯«å…¥ï¼Œç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
msgid "ProtectedEnvironment|All environments specified with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
-msgstr ""
+msgstr "使用以下部署層級所指定的所有環境å‡å—父群組的ä¿è­·ï¼Œ%{link_start}了解更多%{link_end}。"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…許部署"
@@ -31823,7 +32376,7 @@ msgid "ProtectedEnvironment|Failed to load details for this group."
msgstr "該群組的詳細資訊載入失敗。"
msgid "ProtectedEnvironment|No environments in this project are protected."
-msgstr ""
+msgstr "該專案中沒有å—ä¿è­·çš„環境。"
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
msgstr "åªæœ‰æŒ‡å®šçš„使用者æ‰èƒ½åœ¨å—ä¿è­·çš„環境中執行部署。"
@@ -31954,6 +32507,9 @@ msgstr "將此議題發布到相關的狀態é é¢ã€‚"
msgid "Pull"
msgstr "æå–"
+msgid "Pull mirroring updated %{time}."
+msgstr "拉å–é¡åƒå·²æ–¼ %{time} 更新。"
+
msgid "Pull requests from fork are not supported"
msgstr "ä¸æ”¯æ´ä¾†è‡ªåˆ†å‰çš„æå–è¦æ±‚"
@@ -32023,18 +32579,48 @@ msgstr "所有æ交訊æ¯å¿…須符åˆé€™å€‹ %{wiki_syntax_link_start}正則表é
msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
msgstr "所有æ交的文件å都ä¸èƒ½ç¬¦åˆé€™å€‹ %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}。如果為空,則å…許使用任何文件å。"
+msgid "PushRules|Branch name"
+msgstr "分支å稱"
+
+msgid "PushRules|Check whether the commit author is a GitLab user"
+msgstr "檢查æ交者是å¦ç‚º GitLab 使用者"
+
+msgid "PushRules|Commit author's email"
+msgstr "æ交者的電å­éƒµä»¶"
+
msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
msgstr "æ交訊æ¯ä¸èƒ½ç¬¦åˆé€™å€‹ %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}。如果為空,則ä¸æœƒæ ¹æ“šä»»ä½•è¡¨é”å¼æ‹’絕æ交消æ¯ã€‚"
msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
msgstr "ä¸å…許使用者使用 %{code_block_start}git push%{code_block_end}時刪除Git標籤。"
+msgid "PushRules|Maximum file size (MB)"
+msgstr "æœ€å¤§æª”æ¡ˆå¤§å° (MB)"
+
+msgid "PushRules|Prevent pushing secret files"
+msgstr "防止推é€æ©Ÿå¯†æª”案"
+
+msgid "PushRules|Prohibited file names"
+msgstr "被ç¦æ­¢çš„檔案å稱"
+
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
msgstr "拒絕任何å¯èƒ½åŒ…å« secret 的文件。 %{secret_files_link_start}哪些 secret 文件會被拒絕?%{secret_files_link_end}"
+msgid "PushRules|Reject commits that aren't DCO certified"
+msgstr ""
+
+msgid "PushRules|Reject expression in commit messages"
+msgstr "æ交訊æ¯ä¸­çš„拒絕表é”å¼"
+
msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
msgstr "拒絕等於或大於此大å°çš„文件。如果設定為 0,則å…許任何大å°çš„文件。此è¦å‰‡ä¸é©ç”¨æ–¼ Git LFS 追蹤的文件。"
+msgid "PushRules|Reject unsigned commits"
+msgstr "拒絕未簽åçš„æ交"
+
+msgid "PushRules|Require expression in commit messages"
+msgstr "æ交訊æ¯ä¸­éœ€è¦èªªæ˜Ž"
+
msgid "PushRules|Restrict commits to existing GitLab users."
msgstr "é™åˆ¶å°ç¾æœ‰ GitLab 使用者的æ交。"
@@ -32185,9 +32771,6 @@ msgstr "進一步了解"
msgid "Read more about GitLab at %{link_to_promo}."
msgstr "在%{link_to_promo}上閱讀更多關於 GitLab 的訊æ¯ã€‚"
-msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr "æ–¼%{help_link_open}此處%{help_link_close}了解有關專案權é™çš„更多訊æ¯"
-
msgid "Read more about related epics"
msgstr "閱讀更多關於相關å²è©©çš„訊æ¯"
@@ -32210,22 +32793,22 @@ msgid "Reauthenticating with SAML provider."
msgstr "正在與 SAML æ供商é‡æ–°é©—證。"
msgid "Rebase"
-msgstr "變基"
+msgstr "變基 (Rebase) "
msgid "Rebase completed"
msgstr "變基完æˆ"
msgid "Rebase in progress"
-msgstr "Rebase正在進行中"
+msgstr "變基 (Rebase) 正在進行中"
msgid "Rebase source branch"
-msgstr "Rebase來æºåˆ†æ”¯"
+msgstr "變基 (Rebase) 來æºåˆ†æ”¯"
msgid "Rebase source branch on the target branch."
msgstr "在目標分支上Rebase來æºåˆ†æ”¯ã€‚"
msgid "Rebase without pipeline"
-msgstr "沒有æµæ°´ç·šçš„變基"
+msgstr "沒有æµæ°´ç·šçš„變基 (Rebase) "
msgid "Recaptcha verified?"
msgstr "é‡æ–°é©—證?"
@@ -32342,9 +32925,6 @@ msgstr "註冊通用雙因å­èªè­‰è¨­å‚™(U2F)"
msgid "Register WebAuthn Device"
msgstr "註冊WebAuthn設備"
-msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
-msgstr "您å¯ä»¥è¨»å†Šç„¡ä¸Šé™å€‹çš„執行器。您å¯ä»¥åœ¨å–®ç¨çš„伺æœå™¨å’Œæ‚¨çš„本地設備上,將執行器註冊為單ç¨çš„使用者。執行器å¯ä»¥æ˜¯ï¼š"
-
msgid "Register device"
msgstr "註冊設備"
@@ -32623,7 +33203,7 @@ msgid "Remove file"
msgstr "移除文件"
msgid "Remove fork relationship"
-msgstr "移除分å‰é—œä¿‚"
+msgstr "移除分å‰ï¼ˆFork)關係"
msgid "Remove from batch"
msgstr "從批次中移除"
@@ -32866,7 +33446,7 @@ msgid "Replaced all labels with %{label_references} %{label_text}."
msgstr "已將所有標記å–代為%{label_references}%{label_text}。"
msgid "Replaces the clone URL root."
-msgstr "å–代仿製(clone)URL根地å€ã€‚"
+msgstr "å–代克隆 (Clone) URL根地å€ã€‚"
msgid "Replication"
msgstr "複製"
@@ -33194,7 +33774,7 @@ msgid "Repository cleanup has started. You will receive an email once the cleanu
msgstr "版本庫清ç†å·²ç¶“開始。一旦清ç†å®Œæˆï¼Œæ‚¨å°‡æ”¶åˆ°ä¸€å°é›»å­éƒµä»¶ã€‚"
msgid "Repository clone URL"
-msgstr "版本庫仿製(clone)地å€"
+msgstr "版本庫克隆 (Clone) 地å€"
msgid "Repository files count over the limit"
msgstr "版本庫文件數超éŽé™åˆ¶"
@@ -33220,6 +33800,9 @@ msgstr "版本庫é¡åƒ"
msgid "Repository mirroring configuration"
msgstr "版本庫é¡åƒè¨­å®š"
+msgid "Repository mirroring has been paused due to too many failed attempts. It can be resumed by a project maintainer or owner."
+msgstr ""
+
msgid "Repository must contain at least 1 file."
msgstr "版本庫必須包å«è‡³å°‘1個文件。"
@@ -33533,10 +34116,10 @@ msgid "Reveal values"
msgstr "顯示值"
msgid "Revert this commit"
-msgstr "還原此æ交"
+msgstr "還原 (Revert) æ­¤æ交"
msgid "Revert this merge request"
-msgstr "還原此åˆä½µè«‹æ±‚"
+msgstr "還原 (Revert) æ­¤åˆä½µè«‹æ±‚"
msgid "Review"
msgstr "檢閱"
@@ -33602,6 +34185,9 @@ msgstr "已撤銷身份模擬令牌 %{token_name}ï¼"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr "已撤銷個人存å–令牌 %{personal_access_token_name}ï¼"
+msgid "Rich text"
+msgstr "富文本 (Rich text)"
+
msgid "RightSidebar|Copy email address"
msgstr "複製電å­éƒµä»¶åœ°å€"
@@ -33623,6 +34209,9 @@ msgstr "角色"
msgid "Rollback"
msgstr "還原"
+msgid "Rollout of free user limits within GitLab.com. Do not edit these values unless approval has been given via %{link_start}this issue%{link_end}."
+msgstr "在 GitLab.com 內推出å…費使用者é™åˆ¶ã€‚除éžå·²ç¶“é€éŽ%{link_start}æ­¤å•é¡Œ%{link_end}å–得批准,å¦å‰‡è«‹å‹¿ç·¨è¼¯é€™äº›å€¼ã€‚"
+
msgid "Ruby"
msgstr "Ruby"
@@ -33714,7 +34303,7 @@ msgid "Runners|Add notes, like who owns the runner or what it should be used for
msgstr "增加註釋,例如執行器的æ“有者或執行器的用途。"
msgid "Runners|Add your feedback in the issue"
-msgstr ""
+msgstr "在議題中加入您的回饋"
msgid "Runners|All"
msgstr "全部"
@@ -33835,7 +34424,7 @@ msgid "Runners|Executor"
msgstr "執行者"
msgid "Runners|Filter projects"
-msgstr ""
+msgstr "éŽæ¿¾å°ˆæ¡ˆ"
msgid "Runners|Get started with runners"
msgstr "執行器入門"
@@ -33843,6 +34432,9 @@ msgstr "執行器入門"
msgid "Runners|Group"
msgstr "群組"
+msgid "Runners|How do runners pick up jobs?"
+msgstr ""
+
msgid "Runners|How do we upgrade GitLab runner?"
msgstr "如何å‡ç´š GitLab 執行器?"
@@ -33876,9 +34468,6 @@ msgstr "作業逾時最大值"
msgid "Runners|Members of the %{type} can register runners"
msgstr "%{type}的會員å¯ä»¥è¨»å†ŠåŸ·è¡Œå™¨"
-msgid "Runners|Multi-project runners cannot be deleted"
-msgstr "無法刪除多專案執行器"
-
msgid "Runners|Name"
msgstr "å稱"
@@ -33888,6 +34477,9 @@ msgstr "從未連接éŽ"
msgid "Runners|Never contacted:"
msgstr "從未連接éŽ:"
+msgid "Runners|Never expires"
+msgstr "無期é™"
+
msgid "Runners|New group runners view"
msgstr "新的群組執行器視圖"
@@ -33955,6 +34547,9 @@ msgstr "註冊執行器(runner)"
msgid "Runners|Register an instance runner"
msgstr "註冊一個實例執行器(runner)"
+msgid "Runners|Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine."
+msgstr ""
+
msgid "Runners|Registration token"
msgstr "註冊令牌(權æ–)"
@@ -33982,8 +34577,11 @@ msgstr "%{name} 執行器已刪除"
msgid "Runners|Runner assigned to project."
msgstr "指派給專案的執行器。"
-msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr "執行器(Runner)無法刪除,請è¯çµ¡æ‚¨çš„管ç†å“¡ã€‚"
+msgid "Runners|Runner authentication token expiration"
+msgstr "執行器身份驗證權æ–éŽæœŸ"
+
+msgid "Runners|Runner authentication tokens will expire based on a set interval. They will automatically rotate once expired."
+msgstr "執行器身份驗證權æ–å°‡ä¾æ“šè¨­å®šçš„間隔時間到期,一旦到期,它們將自動輪æ›ã€‚"
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
msgstr "在最近 %{elapsedTime} 內,執行器(Runner)é€£æŽ¥éŽ GitLab"
@@ -34033,6 +34631,9 @@ msgstr "å–消指派到專案的執行器(Runner)。"
msgid "Runners|Runners"
msgstr "執行器(Runners)"
+msgid "Runners|Runners are either:"
+msgstr ""
+
msgid "Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner."
msgstr "執行器是é‹è¡Œ CI/CD 作業的代ç†ã€‚按照%{linkStart}安è£å’Œè¨»å†Šèªªæ˜Ž%{linkEnd}來設定執行器。"
@@ -34045,6 +34646,9 @@ msgstr "é¸æ“‡è¦æŒ‡æ´¾çµ¦è©²åŸ·è¡Œå™¨(runner)的專案"
msgid "Runners|Select your preferred option here. In the next step, you can choose the capacity for your runner in the AWS CloudFormation console."
msgstr "執行器|在此處é¸æ“‡æ‚¨çš„首è¦é¸é …。在下一步中,您å¯ä»¥åœ¨ AWS CloudFormation 控制å°ä¸­ç‚ºæ‚¨çš„執行器(runner)é¸æ“‡å®¹é‡ã€‚"
+msgid "Runners|Show only inherited"
+msgstr ""
+
msgid "Runners|Show runner installation and registration instructions"
msgstr "顯示執行器(runner)安è£å’Œè¨»å†Šèªªæ˜Ž"
@@ -34075,6 +34679,9 @@ msgstr "åœæ­¢åŸ·è¡Œå™¨(runner)接å—新的作業。"
msgid "Runners|Tags"
msgstr "標籤"
+msgid "Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run."
+msgstr ""
+
msgid "Runners|Take me there!"
msgstr "帶我到那裡ï¼"
@@ -34112,6 +34719,9 @@ msgstr "è¦åœ¨å®¹å™¨ä¸­å®‰è£åŸ·è¡Œå™¨(runner),請按照 GitLab 的說明文ä»
msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr "è¦è¨»å†Šä»–們,請到 %{link_start}CI/CD 執行器群組%{link_end} é é¢ã€‚"
+msgid "Runners|Token expiry"
+msgstr "權æ–(令牌)到期"
+
msgid "Runners|Up to date"
msgstr "最新的"
@@ -34152,10 +34762,10 @@ msgid "Runners|View installation instructions"
msgstr "檢視安è£èªªæ˜Ž"
msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
-msgstr ""
+msgstr "我們希望您能夠從該é é¢è¼•é¬†æœ‰æ•ˆåœ°ç®¡ç†æ‚¨çš„執行器,我們正在åšå‡ºæ”¹è®Šä»¥å¯¦ç¾ç›®æ¨™ï¼Œå°±æˆ‘們的表ç¾çµ¦æˆ‘們å饋ï¼"
msgid "Runners|We've made some changes and want your feedback"
-msgstr ""
+msgstr "我們進行了一些更改並希望得到您的å饋"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
msgstr "Windows 2019 Shell,具有手動縮放和å¯é¸æŽ’程的功能。 %{percentage} 點。"
@@ -34331,9 +34941,6 @@ msgstr "正在儲存專案。"
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
msgstr "%{ifLabelStart}å‡è¨­%{ifLabelEnd} %{rules} 動作為 %{scopes} %{branches}"
-msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
-msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{rules} 用於 %{branches} 分支"
-
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
msgstr "%{period} %{days} æ–¼ %{time}"
@@ -34341,13 +34948,13 @@ msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan
msgstr "%{thenLabelStart}然後%{thenLabelEnd} éœ€è¦ %{scan} 掃ææ‰èƒ½é‹è¡Œ"
msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run with site profile %{siteProfile} and scanner profile %{scannerProfile}"
-msgstr ""
+msgstr "%{thenLabelStart}Then%{thenLabelEnd} è¦æ±‚使用 %{siteProfile} 站點é…置和 %{scannerProfile} 掃æ器é…置執行 %{scan} 掃æ"
msgid "ScanExecutionPolicy|A pipeline is run"
msgstr "æµæ°´ç·šåŸ·è¡Œä¸­"
msgid "ScanExecutionPolicy|Scanner profile"
-msgstr ""
+msgstr "掃æ器é…ç½®"
msgid "ScanExecutionPolicy|Schedule"
msgstr "排程"
@@ -34359,13 +34966,13 @@ msgid "ScanExecutionPolicy|Select branches"
msgstr "é¸æ“‡åˆ†æ”¯"
msgid "ScanExecutionPolicy|Select scanner profile"
-msgstr ""
+msgstr "é¸æ“‡æŽƒæ器é…ç½®"
msgid "ScanExecutionPolicy|Select site profile"
-msgstr ""
+msgstr "é¸æ“‡ç«™é»žé…ç½®"
msgid "ScanExecutionPolicy|Site profile"
-msgstr ""
+msgstr "站點é…ç½®"
msgid "ScanExecutionPolicy|branch"
msgstr "分支"
@@ -34398,28 +35005,28 @@ msgid "Scanner profile not found for given parameters"
msgstr "找ä¸åˆ°æŒ‡å®šåƒæ•¸çš„掃æ工具設定文件"
msgid "Schedule a new pipeline"
-msgstr "計劃新建æµæ°´ç·š"
+msgstr "建立æµæ°´ç·šæŽ’程"
msgid "Schedule-based escalation rules must have a schedule in the same project as the policy"
-msgstr "基於時間表的å‡ç´šè¦å‰‡å¿…須在與政策相åŒçš„專案中具有時間表"
+msgstr "基於排程的å‡ç´šè¦å‰‡å¿…須在與策略相åŒçš„專案中有排程"
msgid "Scheduled"
-msgstr "已計劃"
+msgstr "已排程"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
-msgstr "已計劃刪除於 - %{permanent_deletion_time}"
+msgstr "已安排於 - %{permanent_deletion_time} 刪除"
msgid "Scheduled a rebase of branch %{branch}."
-msgstr "已計劃了分支%{branch}的變基(rebase)。"
+msgstr "已安排了 %{branch} 分支的變基 (Rebase) 。"
msgid "Scheduled pipelines cannot run more frequently than once per %{limit} minutes. A pipeline configured to run more frequently only starts after %{limit} minutes have elapsed since the last time it ran."
-msgstr "已計劃的æµæ°´ç·šæ¯æ¬¡åŸ·è¡Œæ™‚é–“ä¸èƒ½è¶…éŽæ¯%{limit} 分é˜ä¸€æ¬¡ã€‚ 一個設定更頻ç¹åŸ·è¡Œçš„æµæ°´ç·šåƒ…è‡ªä¸Šæ¬¡åŸ·è¡Œå¾ŒéŽ %{limit} 分é˜æ‰å†å•Ÿå‹•ã€‚"
+msgstr "已排程的æµæ°´ç·šæ¯æ¬¡åŸ·è¡Œæ™‚é–“ä¸èƒ½è¶…éŽæ¯%{limit} 分é˜ä¸€æ¬¡ã€‚ 一個設定更頻ç¹åŸ·è¡Œçš„æµæ°´ç·šåƒ…è‡ªä¸Šæ¬¡åŸ·è¡Œå¾ŒéŽ %{limit} 分é˜æ‰å†å•Ÿå‹•ã€‚"
msgid "Scheduled to merge this merge request (%{strategy})."
msgstr "已計劃åˆä½µæ­¤åˆä½µè«‹æ±‚ (%{strategy})。"
msgid "Schedules"
-msgstr "計劃"
+msgstr "排程"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr "計劃åˆä½µæ­¤åˆä½µè«‹æ±‚ (%{strategy})。"
@@ -34481,6 +35088,9 @@ msgstr "æœå°‹æŒ‡æ´¾äºº"
msgid "Search authors"
msgstr "æœå°‹ä½œè€…"
+msgid "Search branch"
+msgstr ""
+
msgid "Search branches"
msgstr "æœå°‹åˆ†æ”¯"
@@ -34530,7 +35140,7 @@ msgid "Search for this text"
msgstr "æœå°‹æ­¤æ–‡å­—"
msgid "Search forks"
-msgstr "æœå°‹åˆ†å‰"
+msgstr "æœå°‹åˆ†å‰ï¼ˆFork)"
msgid "Search groups"
msgstr "æœå°‹ç¾¤çµ„"
@@ -34568,6 +35178,9 @@ msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search projects..."
msgstr "æœå°‹å°ˆæ¡ˆ..."
+msgid "Search protected branches"
+msgstr "æœå°‹å—ä¿è­·çš„分支"
+
msgid "Search rate limits"
msgstr "æœå°‹é€ŸçŽ‡é™åˆ¶"
@@ -34861,14 +35474,14 @@ msgstr "管ç†è¨­å®šæ–‡ä»¶"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr "管ç†ä¾› DAST 掃æ使用的設定文件。"
-msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr "更多掃æ類型,包括容器掃æ,DAST,ä¾è³´æŽƒæ,模糊和授權許å¯åˆè¦ã€‚"
+msgid "SecurityConfiguration|More scan types, including DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
+msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr "未啟用"
-msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
-msgstr "一旦您啟用了é è¨­åˆ†æ”¯æŽƒæ,隨後建立的任何功能分支將包å«æŽƒæ。"
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan. An enabled scanner will not be reflected as such until the pipeline has been successfully executed and it has generated valid artifacts."
+msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
msgstr "%{linkStart}Auto DevOps%{linkEnd}快速啟用所有æŒçºŒæ¸¬è©¦å’Œåˆè¦æ€§å·¥å…·"
@@ -34924,9 +35537,6 @@ msgstr "%{scanners}"
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr "é‡å° %{branches} 的開放åˆä½µè«‹æ±‚中的 %{scanners} %{severities}。"
-msgid "SecurityOrchestration|+%{count} more"
-msgstr "+%{count} 更多"
-
msgid "SecurityOrchestration|, and %{count} more"
msgstr ",還有 %{count} 個"
@@ -35329,6 +35939,9 @@ msgstr "建立 Jira 議題"
msgid "SecurityReports|Create issue"
msgstr "建立議題"
+msgid "SecurityReports|Detection"
+msgstr "檢測"
+
msgid "SecurityReports|Development vulnerabilities"
msgstr "開發æ¼æ´ž"
@@ -35341,6 +35954,9 @@ msgstr "已忽略的'%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
msgstr "已忽略'%{vulnerabilityName}'。請關閉隱è—忽略開關以查看。"
+msgid "SecurityReports|Does not have issue"
+msgstr "沒有議題"
+
msgid "SecurityReports|Download %{artifactName}"
msgstr "下載 %{artifactName}"
@@ -35371,12 +35987,18 @@ msgstr "解æžå®‰å…¨å ±å‘Šæ™‚發生錯誤"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr "無法å–得安全報告訊æ¯ã€‚è«‹é‡æ–°è¼‰å…¥é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
+msgid "SecurityReports|Has issue"
+msgstr "有議題"
+
msgid "SecurityReports|Hide dismissed"
msgstr "éš±è—已忽略項"
msgid "SecurityReports|Image"
msgstr "圖åƒ"
+msgid "SecurityReports|Issue"
+msgstr "議題"
+
msgid "SecurityReports|Issue Created"
msgstr "已建立議題"
@@ -35494,6 +36116,9 @@ msgstr "å°ä¸èµ·ï¼Œæ²’有符åˆéŽæ¿¾å™¨çš„任何çµæžœ"
msgid "SecurityReports|Status"
msgstr "狀態"
+msgid "SecurityReports|Still detected"
+msgstr ""
+
msgid "SecurityReports|Submit vulnerability"
msgstr "æ交æ¼æ´ž"
@@ -35617,9 +36242,6 @@ msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select Git revision"
msgstr "é¸æ“‡Git版本"
-msgid "Select Page"
-msgstr "é¸æ“‡é é¢"
-
msgid "Select Profile"
msgstr "é¸æ“‡å€‹äººè³‡æ–™"
@@ -35665,9 +36287,6 @@ msgstr "é¸æ“‡ä¸€å€‹ç¯„本版本庫"
msgid "Select a template type"
msgstr "é¸æ“‡ä¸€å€‹ç¯„本類型"
-msgid "Select a time zone"
-msgstr "é¸æ“‡ä¸€å€‹æ™‚å€"
-
msgid "Select a timezone"
msgstr "é¸æ“‡ä¸€å€‹æ™‚å€"
@@ -35689,9 +36308,15 @@ msgstr "é¸æ“‡æŒ‡æ´¾äºº(s)"
msgid "Select branch"
msgstr "é¸æ“‡åˆ†æ”¯"
+msgid "Select branch or create wildcard"
+msgstr "é¸å–分支或建立è¬ç”¨å­—å…ƒ"
+
msgid "Select branches"
msgstr "é¸æ“‡åˆ†æ”¯(s)"
+msgid "Select default branch"
+msgstr ""
+
msgid "Select due date"
msgstr "設定截止日期"
@@ -35737,6 +36362,9 @@ msgstr "é¸æ“‡è¦å»ºç«‹è­°é¡Œçš„專案"
msgid "Select projects"
msgstr "é¸æ“‡å°ˆæ¡ˆ(s)"
+msgid "Select report"
+msgstr ""
+
msgid "Select reviewer(s)"
msgstr "é¸æ“‡å¯©æ ¸è€…(s)"
@@ -36049,6 +36677,9 @@ msgstr "設定目標分支"
msgid "Set target branch to %{branch_name}."
msgstr "設定目標分支為%{branch_name}。"
+msgid "Set the Draft status"
+msgstr "設定è‰ç¨¿ç‹€æ…‹"
+
msgid "Set the Ready status"
msgstr "設定就緒狀態"
@@ -36124,18 +36755,15 @@ msgstr "設定權é‡"
msgid "Set weight to %{weight}."
msgstr "將權é‡è¨­å®šç‚º%{weight}。"
-msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr "在您的å字和頭åƒæ—邊顯示標識。"
-
-msgid "SetStatusModal|Busy"
-msgstr "忙碌"
-
msgid "SetStatusModal|Clear status"
msgstr "清除狀態"
msgid "SetStatusModal|Clear status after"
msgstr "外少時間之後清除狀態"
+msgid "SetStatusModal|Displays that you are busy or not able to respond"
+msgstr "顯示您忙碌中或無法回應"
+
msgid "SetStatusModal|Edit status"
msgstr "編輯狀態"
@@ -36148,6 +36776,9 @@ msgstr "設定一個狀態"
msgid "SetStatusModal|Set status"
msgstr "設定狀態"
+msgid "SetStatusModal|Set yourself as busy"
+msgstr "將自已的狀態設為忙碌"
+
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr "å°ä¸èµ·ï¼Œæˆ‘們無法設定您的狀態。請ç¨å¾Œå†è©¦ã€‚"
@@ -36747,6 +37378,39 @@ msgstr "填寫最é©åˆæ‚¨çš„團隊的文字。"
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
msgstr "通éŽåœ¨Slack中輸入斜槓指令來執行這個專案中的常用æ“作。"
+msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started."
+msgstr "%{asterisk}步驟 1.%{asterisk} 連接您的 GitLab 帳號以開始使用。"
+
+msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!"
+msgstr "%{asterisk}步驟 2.%{asterisk} 試試看ï¼"
+
+msgid "Slack|%{emoji}Connected to GitLab account %{account}"
+msgstr "%{emoji} 已連接到 GitLab %{account} 帳號 "
+
+msgid "Slack|%{emoji}Welcome to GitLab for Slack!"
+msgstr "%{emoji} 歡迎來到 Slack çš„ GitLabï¼"
+
+msgid "Slack|Connect your GitLab account"
+msgstr "連接您的 GitLab 帳號"
+
+msgid "Slack|Create a new issue"
+msgstr "建立新議題"
+
+msgid "Slack|Create new issues from Slack: %{command}"
+msgstr "從 Slack 建立新議題:%{command}"
+
+msgid "Slack|Run a CI/CD job"
+msgstr "執行 CI/CD 作業"
+
+msgid "Slack|See a list of available commands: %{command})"
+msgstr "查看å¯ç”¨çš„命令列表:%{command})"
+
+msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}"
+msgstr "使用 ChatOps 簡化 GitLab 部署,設定 %{startMarkup}CI/CD æµæ°´ç·š %{endMarkup} 後,嘗試: %{command}"
+
+msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}."
+msgstr "在您工作中使用 Slack 時查看和控制 GitLab 內容。在您的èŠå¤©å®¢æˆ¶ç«¯ä¸­è¼¸å…¥å‘½ä»¤ä½œç‚ºè¨Šæ¯ä»¥å•Ÿå‹•å®ƒã€‚ %{startMarkup}了解更多%{endMarkup}。"
+
msgid "Slice multiplier"
msgstr "切片乖數"
@@ -36813,6 +37477,9 @@ msgstr "片段ä¸èƒ½åŒ…å«ç©ºæ–‡ä»¶ã€‚確ä¿æ‰€æœ‰æ–‡ä»¶éƒ½æœ‰å…§å®¹ï¼Œæˆ–者刪
msgid "Snowplow"
msgstr "Snowplow"
+msgid "Soft wrap"
+msgstr ""
+
msgid "Solid"
msgstr "實心"
@@ -36871,7 +37538,7 @@ msgid "Something went wrong when reordering designs. Please try again"
msgstr "é‡æ–°æŽ’åºè¨­è¨ˆæ™‚出了點å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡"
msgid "Something went wrong while adding timeline event."
-msgstr ""
+msgstr "加入時間線事件時發生錯誤。"
msgid "Something went wrong while adding your award. Please try again."
msgstr "加入讚賞時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
@@ -37053,6 +37720,9 @@ msgstr "排åºæ–¹å‘:å‡åº"
msgid "Sort direction: Descending"
msgstr "排åºæ–¹å‘:é™åº"
+msgid "Sort or filter"
+msgstr "排åºæˆ–篩é¸"
+
msgid "SortOptions|Blocking"
msgstr "阻塞議題數"
@@ -37095,6 +37765,9 @@ msgstr "最後è¯çµ¡"
msgid "SortOptions|Last created"
msgstr "最近建立時間"
+msgid "SortOptions|Latest version"
+msgstr "最新版本"
+
msgid "SortOptions|Least popular"
msgstr "最ä¸å—æ­¡è¿Ž"
@@ -37155,6 +37828,9 @@ msgstr "最早收è—(星號)"
msgid "SortOptions|Oldest updated"
msgstr "最早更新"
+msgid "SortOptions|Oldest version"
+msgstr "最舊版本"
+
msgid "SortOptions|Popularity"
msgstr "人氣"
@@ -37345,10 +38021,10 @@ msgid "Spent at"
msgstr "花費在"
msgid "Squash commit message"
-msgstr "壓縮æ交訊æ¯"
+msgstr "壓縮 (Squash) æ交訊æ¯"
msgid "Squash commits"
-msgstr "壓縮æ交"
+msgstr "壓縮 (Squash) æ交"
msgid "Squash commits when merge request is accepted."
msgstr "當åˆä½µè«‹æ±‚被接å—時,壓縮åˆä½µæ交。"
@@ -38055,7 +38731,7 @@ msgstr "綠å±"
msgid "SuggestedColors|Green-cyan"
msgstr "綠é’色"
-msgid "SuggestedColors|Lavendar"
+msgid "SuggestedColors|Lavender"
msgstr "è–°è¡£è‰ç´«"
msgid "SuggestedColors|Magenta-pink"
@@ -38079,9 +38755,21 @@ msgstr "玫瑰紅色"
msgid "SuggestedColors|Titanium yellow"
msgstr "鈦黃色"
+msgid "SuggestedReviewers|Get suggestions for reviewers based on GitLab's machine learning tool."
+msgstr "根據 GitLab 的機器學習工具為審查者æ供建議。"
+
+msgid "SuggestedReviewers|Suggested reviewers"
+msgstr "推薦的審查人員"
+
+msgid "SuggestedReviewers|Suggestions appear in the Reviewer section of the right sidebar"
+msgstr "建議出ç¾åœ¨å³å´é‚Šæ¬„的審查者å€åŸŸ"
+
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr "建議ä¸é©ç”¨ï¼Œå› ç‚ºç„¡æ³•æ‰¾åˆ°å»ºè­°ã€‚"
+msgid "Suggestion(s)"
+msgstr "建議"
+
msgid "Suggestions are not applicable as one or more suggestions were not found."
msgstr "建議ä¸é©ç”¨ï¼Œå› ç‚ºç„¡æ³•æ‰¾åˆ°ä¸€å€‹æˆ–多個建議。"
@@ -38118,8 +38806,14 @@ msgstr "啟用訂閱"
msgid "SuperSonics|Activation code"
msgstr "啟用碼"
-msgid "SuperSonics|An error occurred while adding your subscription."
-msgstr "增加訂閱時發生錯誤"
+msgid "SuperSonics|Activation not possible due to seat mismatch"
+msgstr "因席次ä¸ç¬¦è€Œç„¡æ³•å•Ÿç”¨"
+
+msgid "SuperSonics|Activation not possible due to true-up value mismatch"
+msgstr "å›  true-up 值ä¸ç¬¦è€Œç„¡æ³•å•Ÿç”¨"
+
+msgid "SuperSonics|An error occurred while adding your subscription"
+msgstr "加入您的訂閱時發生錯誤"
msgid "SuperSonics|Billable users"
msgstr "å¯è¨ˆè²»çš„使用者"
@@ -38127,8 +38821,8 @@ msgstr "å¯è¨ˆè²»çš„使用者"
msgid "SuperSonics|Buy subscription"
msgstr "購買訂閱"
-msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr "由於連線å•é¡Œï¼Œç„¡æ³•å•Ÿç”¨å¯¦ä¾‹ã€‚"
+msgid "SuperSonics|Cannot activate instance due to a connectivity issue"
+msgstr "因連接å•é¡Œï¼Œç„¡æ³•å•Ÿç”¨æœå‹™å¯¦ä¾‹"
msgid "SuperSonics|Cloud licensing"
msgstr "Cloud 授權許å¯"
@@ -38242,26 +38936,38 @@ msgstr "您有一個未到期的授權許å¯"
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "您已經加入了啟用於 %{date} 的授權許å¯ã€‚詳情請查看下é¢çš„訂閱歷å²è¡¨ã€‚"
+msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "您已為 %{trueUpQuantity} %{trueUpQuantityUsers} 套用了 true-up,但您需è¦ç‚º %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers} 。è¦æ”¯ä»˜è¶…é¡çš„席次費用,請è¯ç¹«æ‚¨çš„銷售代表。如需進一步幫助,請è¯ç¹« %{licenseSupportLinkStart}GitLab Support%{licenseSupportLinkEnd}。"
+
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr "您已æˆåŠŸåŠ å…¥åœ¨ %{date} 啟用的授權許å¯ã€‚有關更多詳細訊æ¯ï¼Œè«‹åƒé–±ä¸‹é¢çš„訂閱歷å²è¡¨ã€‚"
+msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance."
+msgstr "您å¯èƒ½è¼¸å…¥äº†éŽæœŸæˆ–ä¸åˆæ ¼çš„啟用碼,è¦è«‹æ±‚新的啟用碼,請 %{purchaseSubscriptionLinkStart}購買新的訂閱%{purchaseSubscriptionLinkEnd} 或%{supportLinkStart}è¯ç¹« GitLab Support%{supportLinkEnd} 以ç²å¾—進一步的å”助。"
+
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "根據您的å”è­°æ¢æ¬¾ï¼Œæ‚¨å°‡æŒ‰å­£åº¦æˆ–æ¯å¹´ç‚º %{trueUpLinkStart} 超éŽæŽˆæ¬Šè¨±å¯çš„使用者%{trueUpLinkEnd}付費。"
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
msgstr "您的 %{subscriptionEntryName} 暫時無法顯示。請é‡æ–°æ•´ç†æ­¤é é¢ã€‚"
+msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}."
+msgstr "您目å‰çš„ GitLab å®‰è£ %{userCount} 個啟用的 %{userCountUsers},比您的新訂閱席次數 %{licenseUserCount} 多 %{overageCount}。è¦å•Ÿç”¨æ‚¨æ–°çš„訂閱,請%{purchaseLinkStart}購買%{purchaseLinkEnd} é¡å¤–çš„ %{overageCount} %{overageCountSeats},或 %{deactivateLinkStart}åœç”¨%{deactivateLinkEnd} 〠%{blockLinkStart}ç¦ç”¨%{blockLinkEnd} %{overageCount} %{overageCountUsers}。如需進一步å”助,請è¯ç¹« %{licenseSupportLinkStart}GitLab Support%{licenseSupportLinkEnd}。"
+
msgid "SuperSonics|Your future dated license was successfully added"
msgstr "您的未到期授權許å¯å·²æˆåŠŸåŠ å…¥"
msgid "SuperSonics|Your subscription"
msgstr "您的訂閱"
+msgid "SuperSonics|Your subscription cannot be located"
+msgstr "無法找到您的訂閱"
+
msgid "SuperSonics|Your subscription details will sync shortly."
msgstr "您的訂閱訊æ¯å°‡å¾ˆå¿«åŒæ­¥"
-msgid "SuperSonics|Your subscription is expired."
-msgstr "您的訂閱已到期"
+msgid "SuperSonics|Your subscription is expired"
+msgstr "您的訂閱已éŽæœŸ"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
msgstr "您的訂閱已æˆåŠŸå•Ÿç”¨ã€‚您å¯ä»¥åœ¨ä¸‹é¢æŸ¥çœ‹è©³ç´°è¨Šæ¯ã€‚"
@@ -39087,7 +39793,7 @@ msgid "The compliance report shows the merge request violations merged in protec
msgstr "åˆè¦æ€§å ±å‘Šé¡¯ç¤ºåœ¨å—ä¿è­·ç’°å¢ƒä¸­åˆä½µçš„åˆä½µè«‹æ±‚é•è¦ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr "該連接將在 %{timeout} 後逾時。如版本庫匯入耗時超éŽè©²æ™‚間,請使用仿製(clone)/推é€(push)組åˆã€‚"
+msgstr "該連接將在 %{timeout} 後逾時。如版本庫匯入耗時超éŽè©²æ™‚間,請使用克隆 (Clone) /推é€(Push)組åˆã€‚"
msgid "The contact does not belong to the issue group's root ancestor"
msgstr "è¯çµ¡äººä¸å±¬æ–¼è­°é¡Œç¾¤çµ„的根組"
@@ -39242,7 +39948,7 @@ msgid "The hostname of your Snowplow collector."
msgstr "您的 Snowplow 收集器的主機å。"
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr "該匯入éŽç¨‹å°‡åœ¨ %{timeout} 後逾時。å°æ–¼éœ€è¦é•·æ–¼è©²æ™‚é–“æ‰èƒ½åŒ¯å…¥çš„版本庫,請使用仿製(clone)/推é€(push)組åˆã€‚"
+msgstr "該匯入éŽç¨‹å°‡åœ¨ %{timeout} 後逾時。å°æ–¼éœ€è¦é•·æ–¼è©²æ™‚é–“æ‰èƒ½åŒ¯å…¥çš„版本庫,請使用克隆 (Clone) /æŽ¨é€ (Push)組åˆã€‚"
msgid "The interval must be one of %{intervals}."
msgstr "間隔必須是 %{intervals}。"
@@ -39344,7 +40050,7 @@ msgid "The name of the Jenkins project. Copy the name from the end of the URL to
msgstr "Jenkins 專案的å稱。將 URL 末尾的å稱複製到專案中。"
msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
-msgstr "仿製(clone)版本庫時è¦å¾ž GitLab å–得的更改數é‡ï¼Œè¼ƒä½Žçš„值å¯ä»¥åŠ é€Ÿæµæ°´ç·šåŸ·è¡Œã€‚ 設定為 %{code_open}0%{code_close} 或空白以å–å¾—æ¯å€‹ä½œæ¥­çš„所有分支和標籤"
+msgstr "複製 (Clone) 版本庫時è¦å¾ž GitLab å–得的更改數é‡ï¼Œè¼ƒä½Žçš„值å¯ä»¥åŠ é€Ÿæµæ°´ç·šåŸ·è¡Œã€‚ 設定為 %{code_open}0%{code_close} 或空白以å–å¾—æ¯å€‹ä½œæ¥­çš„所有分支和標籤"
msgid "The number of merge requests merged by month."
msgstr "æ¯æœˆåˆä½µçš„åˆä½µè«‹æ±‚數"
@@ -39392,7 +40098,7 @@ msgid "The project size exceeds the export limit."
msgstr "專案大å°è¶…éŽåŒ¯å‡ºé™åˆ¶ã€‚"
msgid "The project was successfully forked."
-msgstr "該專案æˆåŠŸåˆ†å‰ã€‚"
+msgstr "該專案æˆåŠŸåˆ†å‰ï¼ˆFork)。"
msgid "The project was successfully imported."
msgstr "該專案已æˆåŠŸåŒ¯å…¥ã€‚"
@@ -39442,6 +40148,9 @@ msgstr "åŒä¸€å€‹å…±ç”¨åŸ·è¡Œå™¨åŸ·è¡Œä¾†è‡ªå¤šå€‹å°ˆæ¡ˆçš„程å¼ç¢¼ï¼Œé™¤éžæ‚¨
msgid "The scan has been created."
msgstr "掃瞄已建立。"
+msgid "The secret is only available when you first create the application."
+msgstr "該密鑰僅å¯ç”¨æ–¼æ‚¨é¦–次建立應用程å¼æ™‚。"
+
msgid "The snippet can be accessed without any authentication."
msgstr "無需任何身份驗證å³å¯å­˜å–該程å¼ç¢¼ç‰‡æ®µã€‚"
@@ -39458,10 +40167,10 @@ msgid "The source project of this merge request has been removed."
msgstr "æ­¤åˆä½µè«‹æ±‚的來æºå°ˆæ¡ˆå·²è¢«ç§»é™¤ã€‚"
msgid "The source topic and the target topic are identical."
-msgstr ""
+msgstr "來æºä¸»é¡Œå’Œç›®æ¨™ä¸»é¡Œæ˜¯ç›¸åŒçš„。"
msgid "The source topic is not a topic."
-msgstr ""
+msgstr "來æºä¸»é¡Œä¸æ˜¯ä¸€å€‹ä¸»é¡Œã€‚"
msgid "The specified tab is invalid, please select another"
msgstr "指定é ç±¤ç„¡æ•ˆï¼Œè«‹é¸æ“‡å¦ä¸€å€‹"
@@ -39476,13 +40185,13 @@ msgid "The tag name can't be changed for an existing release."
msgstr "å°æ–¼ç¾æœ‰ç™¼å¸ƒï¼Œä¸èƒ½æ›´æ”¹æ¨™ç±¤å稱。"
msgid "The target topic is not a topic."
-msgstr ""
+msgstr "目標主題ä¸æ˜¯ä¸€å€‹ä¸»é¡Œã€‚"
msgid "The time period in seconds that the maximum requests per project limit applies to."
msgstr "æ¯å€‹å°ˆæ¡ˆæœ€å¤§è«‹æ±‚所é©ç”¨çš„時間間隔(秒)。"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr "æ›´æ–°æ“作將在 %{number_of_minutes} 分é˜å¾Œé€¾æ™‚。å°æ–¼å¤§åž‹ç‰ˆæœ¬åº«ï¼Œè«‹ä½¿ç”¨ clone/push 組åˆã€‚"
+msgstr "æ›´æ–°æ“作將在 %{number_of_minutes} 分é˜å¾Œé€¾æ™‚。å°æ–¼å¤§åž‹ç‰ˆæœ¬åº«ï¼Œè«‹ä½¿ç”¨è¤‡è£½ (Clone) /推é€(Push)組åˆã€‚"
msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
msgstr "上傳的文件無效。支æ´çš„文件擴展å為%{extensions}。"
@@ -39649,9 +40358,6 @@ msgstr "沒有å¯ç”¨çš„資料。"
msgid "There is no data available. Please change your selection."
msgstr "沒有å¯ç”¨è³‡æ–™ã€‚請變更é¸æ“‡ã€‚"
-msgid "There is no seat left to activate the member"
-msgstr "已無啟用會員的席次"
-
msgid "There is no table data available."
msgstr "沒有å¯ç”¨çš„表資料。"
@@ -39919,9 +40625,6 @@ msgstr "æ­¤Cronæ ¼å¼ç„¡æ•ˆ"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
msgstr "æ­¤ GitLab 實例尚未æ供任何共用執行器(runners)。實例管ç†å“¡å¯ä»¥åœ¨ç®¡ç†å€è¨»å†Šå…±ç”¨åŸ·è¡Œå™¨(runners)。"
-msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr "該GitLab實例的授權許å¯ç‚º%{insufficient_license}級別。Geo 僅é©ç”¨æ–¼è‡³å°‘æ“有高級授權許å¯çš„使用者。"
-
msgid "This PDF is too large to display. Please download to view."
msgstr "此 PDF 太大而無法顯示。請下載查看。"
@@ -39985,6 +40688,9 @@ msgstr "該å€å¡Šç‚ºè‡ªæˆ‘引用"
msgid "This board's scope is reduced"
msgstr "此看æ¿ç¯„åœç¸®å°äº†"
+msgid "This branch has diverged from upstream."
+msgstr "該分支已經從上游分æµäº†ã€‚"
+
msgid "This change will remove %{strongOpen}ALL%{strongClose} Premium and Ultimate features for %{strongOpen}ALL%{strongClose} SaaS customers and make tests start failing."
msgstr "此變更將移除 %{strongOpen}所有%{strongClose} SaaS 客戶的 %{strongOpen}全部%{strongClose} Premium å’Œ Ultimate 功能,並開始造æˆæ¸¬è©¦å¤±æ•—。"
@@ -40030,6 +40736,9 @@ msgstr "此憑證已éŽæœŸ"
msgid "This deployment is not waiting for approvals."
msgstr "此部署ä¸ç­‰å¾…核准。"
+msgid "This deployment job does not run automatically and must be started manually, but it's older than the latest deployment, and therefore can't run."
+msgstr "該部署作業ä¸æœƒè‡ªå‹•é‹è¡Œï¼Œå¿…須手動啟動。但它比最新的部署舊,因此無法執行。"
+
msgid "This deployment job does not run automatically and must be started manually, but you do not have access to this job's protected environment. The job can only be started by a project member allowed to deploy to the environment."
msgstr "此部署作業ä¸æœƒè‡ªå‹•åŸ·è¡Œï¼Œå¿…須手動啟動,但您無權存å–此作業的å—ä¿è­·ç’°å¢ƒã€‚該作業åªèƒ½ç”±å…許部署到環境的專案æˆå“¡å•Ÿå‹•ã€‚"
@@ -40078,6 +40787,27 @@ msgstr "此環境的Canary Ingress最近有更新。請ç¨å¾Œå†è©¦ã€‚"
msgid "This epic already has the maximum number of child epics."
msgstr "æ­¤å²è©©çš„å­å²è©©æ•¸ç›®å·²é”最大值。"
+msgid "This epic cannot be added. An epic cannot be added to itself."
+msgstr ""
+
+msgid "This epic cannot be added. An epic cannot belong to an ancestor group of its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already an ancestor of the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. It is already assigned to the parent epic."
+msgstr ""
+
+msgid "This epic cannot be added. One or more epics would exceed the maximum depth (%{max_depth}) from its most distant ancestor."
+msgstr ""
+
+msgid "This epic cannot be added. You don't have access to perform this action."
+msgstr ""
+
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "æ­¤å²è©©ä¸å­˜åœ¨æˆ–者您沒有足夠的權é™ã€‚"
@@ -40174,6 +40904,9 @@ msgstr "此數字為自授權許å¯å•Ÿå‹•ä»¥ä¾†ä½¿ç”¨è€…數目的最高值。"
msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr "此數目為您伺æœå™¨ç•¶å‰%{billable_users_link_start}收費使用者%{link_end}的數é‡ï¼Œ 也是更新授權許å¯æ™‚需è¦è³¼è²·çš„最低數é‡ã€‚"
+msgid "This is the only time the secret is accessible. Copy the secret and store it securely."
+msgstr "這是密鑰唯一å¯ä»¥å­˜å–的時間, 複製該密鑰並安全的ä¿ç®¡å®ƒã€‚"
+
msgid "This is your current session"
msgstr "這是您目å‰çš„工作階段"
@@ -40390,6 +41123,9 @@ msgstr "該專案已歸檔,無法加入留言。"
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr "該專案在 %{strong_start}%{license_name}%{strong_end}下å–得授權許å¯ã€‚"
+msgid "This project is mirrored from %{link}."
+msgstr "該專案是來自於 %{link} çš„é¡åƒã€‚"
+
msgid "This project is not subscribed to any project pipelines."
msgstr "該專案未訂閱任何專案æµæ°´ç·šã€‚"
@@ -40402,12 +41138,18 @@ msgstr "該專案使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾è³
msgid "This project path either does not exist or you do not have access."
msgstr "該專案路徑ä¸å­˜åœ¨æˆ–您沒有存å–權é™ã€‚"
+msgid "This project reached the limit of custom domains. (Max %d)"
+msgstr "該專案已é”到自定義域的é™åˆ¶ã€‚ (最大值 %d)"
+
msgid "This project will be deleted on %{date}"
msgstr "該專案將於 %{date} 刪除"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr "該專案將於 %{date} 刪除,因為它的父群組 '%{parent_group_name}' 已排入刪除排程。"
+msgid "This project's pipeline configuration is located outside this repository"
+msgstr ""
+
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
msgstr "該發布版本是使用éŽåŽ»çš„日期建立的, 無法在發布時收集證據。"
@@ -40490,11 +41232,14 @@ msgid "This will invalidate your registered applications and U2F devices."
msgstr "這將使您的註冊應用程å¼å’Œ U2F 設備無效。"
msgid "This will remove the fork relationship between this project and %{fork_source}."
-msgstr "這將移除該專案和%{fork_source}之間的分å‰é—œä¿‚。"
+msgstr "這將移除該專案和 %{fork_source} 之間的分å‰ï¼ˆFork)關係。"
msgid "This will remove the fork relationship between this project and other projects in the fork network."
msgstr "這將移除此專案與分å‰ç¶²è·¯ä¸­å…¶ä»–專案之間的分å‰é—œä¿‚。"
+msgid "Thread options"
+msgstr ""
+
msgid "Thread to reply to cannot be found"
msgstr "找ä¸åˆ°è¦å›žå¾©çš„主題"
@@ -40724,7 +41469,7 @@ msgid "Timeago|right now"
msgstr "ç«‹å³"
msgid "Timeline event added successfully."
-msgstr ""
+msgstr "å·²æˆåŠŸåŠ å…¥æ™‚間線事件。"
msgid "Timeline|Turn recent updates view off"
msgstr "關閉最近更新視圖"
@@ -40836,6 +41581,9 @@ msgstr "è¦å•Ÿç”¨æ‚¨çš„試用版,我們需è¦æ‚¨æ供更多詳細信æ¯ã€‚"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr "è¦åŠ å…¥è‡ªè¨‚後綴,請設定æœå‹™å°é›»å­éƒµä»¶åœ°å€ã€‚ %{linkStart}了解更多。%{linkEnd}"
+msgid "To add display name, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr "è¦å¢žåŠ é¡¯ç¤ºå稱,請設定æœå‹™å°é›»å­éƒµä»¶åœ°å€ã€‚ %{linkStart}了解更多。%{linkEnd}"
+
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "如需手動加入æ¢ç›®ï¼Œè«‹åœ¨æ‰‹æ©Ÿæ‡‰ç”¨ä¸­æ供以下訊æ¯ã€‚"
@@ -40869,14 +41617,17 @@ msgstr "è¦ç¹¼çºŒï¼Œæ‚¨éœ€è¦é¸æ“‡æˆ‘們發é€çš„確èªé›»å­éƒµä»¶ä¸­çš„連çµ
msgid "To define internal users, first enable new users set to external"
msgstr "è¦å®šç¾©å…§éƒ¨ä½¿ç”¨è€…,請首先啟用設定為外部的新使用者"
+msgid "To edit the pipeline configuration, you must go to the project or external site that hosts the file."
+msgstr ""
+
msgid "To enable Registration Features, first enable Service Ping."
msgstr "è¦å•Ÿç”¨è¨»å†ŠåŠŸèƒ½ï¼Œè«‹å…ˆå•Ÿç”¨ Service Ping。"
msgid "To ensure %{project_link} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
-msgstr "ç‚ºç¢ºä¿ %{project_link} 未計劃的刪除,請檢查 GitLab 是å¦å·²è¨˜éŒ„活動。例如:"
+msgstr "ç‚ºç¢ºä¿ %{project_link} 被未計劃的刪除,請檢查 GitLab 是å¦å·²è¨˜éŒ„活動。例如:"
msgid "To ensure %{project_name} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
-msgstr "è¦ç¢ºä¿ %{project_name} 未計劃的刪除,請檢查 GitLab 是å¦å·²è¨˜éŒ„活動。例如:"
+msgstr "è¦ç¢ºä¿ %{project_name} 被未計劃的刪除,請檢查 GitLab 是å¦å·²è¨˜éŒ„活動。例如:"
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr "為ä¿è­‰å€‹äººå…§å®¹ä¸éºå¤±ï¼Œæœ¬å¸³è™Ÿåƒ…用於與 %{group_name}相關的事項。"
@@ -41029,16 +41780,16 @@ msgid "Todos|Filter by project"
msgstr "ä¾å°ˆæ¡ˆéŽæ¿¾"
msgid "Todos|Give yourself a pat on the back!"
-msgstr ""
+msgstr "給自已一個稱讚!"
msgid "Todos|Good job! Looks like you don't have anything left on your To-Do List"
-msgstr ""
+msgstr "太棒了ï¼çœ‹èµ·ä¾†æ‚¨çš„待辦事項列表上沒有留下任何內容"
msgid "Todos|Henceforth, you shall be known as \"To-Do Destroyer\""
-msgstr ""
+msgstr "此後,您將被稱為“待辦事項毀滅者â€"
msgid "Todos|Isn't an empty To-Do List beautiful?"
-msgstr ""
+msgstr "空的待辦事項列表是ä¸æ˜¯å¾ˆæ¼‚亮?"
msgid "Todos|It's how you always know what to work on next."
msgstr "這是您總是知é“下一步è¦åšä»€éº¼çš„æ–¹å¼ã€‚"
@@ -41050,7 +41801,7 @@ msgid "Todos|Nothing is on your to-do list. Nice work!"
msgstr "您的待辦事項列表中沒有任何事項。"
msgid "Todos|Nothing left to do. High five!"
-msgstr ""
+msgstr "沒有待辦事項,擊掌慶ç¥ï¼"
msgid "Todos|Undo mark all as done"
msgstr "撤銷標示為全部完æˆ"
@@ -41088,9 +41839,6 @@ msgstr "é–‹é—œæ交æè¿°"
msgid "Toggle commit list"
msgstr "é–‹é—œæ交列表"
-msgid "Toggle dropdown"
-msgstr "切æ›ä¸‹æ‹‰åˆ—表"
-
msgid "Toggle emoji award"
msgstr "切æ›è¡¨æƒ…符號讚賞"
@@ -41112,9 +41860,6 @@ msgstr "切æ›å¿«æ·éµ"
msgid "Toggle sidebar"
msgstr "切æ›å´é‚Šæ¬„"
-msgid "Toggle the Draft status"
-msgstr "切æ›è‰ç¨¿ç‹€æ…‹"
-
msgid "Toggle the Performance Bar"
msgstr "切æ›æ•ˆèƒ½æ¬„"
@@ -41161,16 +41906,16 @@ msgid "Too many users found. Quick actions are limited to at most %{max_count} u
msgstr "發ç¾å¤ªå¤šä½¿ç”¨è€…。快速æ“作僅é™æ–¼æœ€å¤š %{max_count} 個使用者"
msgid "TopNav|Explore"
-msgstr ""
+msgstr "探索"
msgid "TopNav|Go back"
msgstr "返回"
msgid "TopNav|Switch to"
-msgstr ""
+msgstr "切æ›åˆ°"
msgid "TopNav|Your dashboards"
-msgstr ""
+msgstr "您的儀表æ¿"
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
msgstr "主題 %{source_topic} å·²æˆåŠŸåˆä½µè‡³ä¸»é¡Œ %{target_topic}。"
@@ -41209,7 +41954,7 @@ msgid "Topics"
msgstr "主題"
msgid "Topics could not be merged!"
-msgstr ""
+msgstr "主題無法被åˆä½µï¼"
msgid "Total"
msgstr "全部"
@@ -41226,6 +41971,9 @@ msgstr "所有產物大å°ï¼š %{total_size}"
msgid "Total cores (CPUs)"
msgstr "總核心數目 (CPUs)"
+msgid "Total issue weight"
+msgstr "總議題權é‡"
+
msgid "Total memory (GB)"
msgstr "總記憶體 (GB)"
@@ -41355,9 +42103,6 @@ msgstr "第 %{daysUsed}/%{duration} 天"
msgid "Trials|Go back to GitLab"
msgstr "返回GitLab"
-msgid "Trials|Hey there"
-msgstr "您好ï¼"
-
msgid "Trials|Skip Trial"
msgstr "è·³éŽè©¦ç”¨"
@@ -41373,6 +42118,10 @@ msgstr "您å¯ä»¥å°‡æ‚¨åœ¨ä¸€å€‹æ–°ç¾¤çµ„或一個ç¾æœ‰ç¾¤çµ„上é¢é€²è¡Œè©¦ç”¨
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr "您ç¾åœ¨ç„¡æ³•ç²å¾—å…費試用,但您å¯ä»¥éš¨æ™‚通éŽé¸æ“‡æ‚¨çš„é ­åƒä¸¦é¸æ“‡ã€Œé–‹å§‹æ——艦版試用ã€ä¾†æ¢å¾©æ­¤ç¨‹åºã€‚"
+msgid "Trials|You've got %{daysRemaining} day remaining on GitLab %{planName}!"
+msgid_plural "Trials|You've got %{daysRemaining} days remaining on GitLab %{planName}!"
+msgstr[0] "您在 GitLab %{planName} 上還有 %{daysRemaining} 天ï¼"
+
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 "您的試用版在 %{boldStart}%{trialEndDate}%{boldEnd}çµæŸï¼Œæˆ‘們希望您能享å—GitLab %{planName}的功能,為了在試用çµæŸå¾Œä¿ç•™é€™äº›åŠŸèƒ½ï¼Œæ‚¨éœ€è¦è³¼è²·è¨‚閱。(如果您滿足您的需è¦ï¼Œæ‚¨ä¹Ÿå¯ä»¥é¸æ“‡å°ˆæ¥­ç‰ˆã€‚)"
@@ -41476,7 +42225,7 @@ msgid "Try the troubleshooting steps here."
msgstr "嘗試此處的故障排除步驟。"
msgid "Try to fork again"
-msgstr "嘗試å†æ¬¡åˆ†å‰"
+msgstr "嘗試å†æ¬¡åˆ†å‰ï¼ˆFork)"
msgid "Try to keep the first line under 52 characters and the others under 72."
msgstr "請將第一行ä¿æŒåœ¨52個字元以內,其他行ä¿æŒåœ¨72個字元以內。"
@@ -42054,6 +42803,9 @@ msgstr "%{linkTitle} 幫助連çµ"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft} 購買的儲存空間å¯ç”¨"
+msgid "UsageQuota|%{storage_limit_link_start}A namespace storage limit%{link_end} will soon be enforced for the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}"
+msgstr "%{storage_limit_link_start}命å空間儲存é™åˆ¶%{link_end} å°‡å¾ˆå¿«å° %{strong_start}%{namespace_name}%{strong_end} 命å空間實施。 %{extra_message}"
+
msgid "UsageQuota|Artifacts"
msgstr "產物"
@@ -42096,12 +42848,12 @@ msgstr "當å‰é€±æœŸä½¿ç”¨é‡"
msgid "UsageQuota|Dependency proxy"
msgstr "ä¾è³´ä»£ç†"
-msgid "UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}View the %{rollout_link_start}rollout schedule for this change%{link_end}."
-msgstr "自 %{storage_enforcement_date} 起,命å空間儲存é™åˆ¶å°‡é©ç”¨æ–¼ %{strong_start}%{namespace_name}%{strong_end} 命å空間。 %{extra_message}查看%{rollout_link_start}此變更的推出計劃%{link_end}。"
-
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "文件附件和較å°çš„設計圖表。"
+msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}."
+msgstr "有關儲存é™åˆ¶çš„更多訊æ¯ï¼Œè«‹åƒé–±æˆ‘們的 %{faq_link_start}FAQ%{link_end}。"
+
msgid "UsageQuota|Git repository."
msgstr "Git版本庫。"
@@ -42174,9 +42926,6 @@ msgstr "版本庫"
msgid "UsageQuota|Seats"
msgstr "席次"
-msgid "UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information."
-msgstr "è«‹åƒé–±æˆ‘們的 %{faq_link_start}FAQ%{link_end} 以了解更多資訊。"
-
msgid "UsageQuota|Shared bits of code and text."
msgstr "共用程å¼ç¢¼å’Œæ–‡å­—"
@@ -42210,8 +42959,8 @@ msgstr "%{strong_start}%{context_name}%{strong_end} 群組將å—此影響。"
msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "
msgstr "%{strong_start}%{context_name}%{strong_end} 專案將å—此影響。"
-msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end}."
-msgstr "該命å空間目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空間儲存。群組æ“有者å¯ä»¥å¾ž %{strong_start}%{usage_quotas_nav_instruction}%{strong_end} 查看命å空間儲存使用情æ³ä¸¦è³¼è²·æ›´å¤šã€‚ %{docs_link_start}更多資訊%{link_end}。"
+msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. Group owners can view namespace storage usage and purchase more from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}How can I manage my storage?%{link_end}."
+msgstr "命å空間目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空間儲存å€ï¼Œç¾¤çµ„所有者å¯ä»¥æŸ¥çœ‹å‘½å空間儲存狀æ³ï¼Œå…·ä¸”從 %{strong_start}%{usage_quotas_nav_instruction}%{strong_end} 的購買更多的儲存空間。 %{docs_link_start}如何管ç†æˆ‘的儲存空間?%{link_end}。"
msgid "UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. View and manage your usage from %{strong_start}%{usage_quotas_nav_instruction}%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
msgstr "該命å空間目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空間儲存。從 %{strong_start}%{usage_quotas_nav_instruction}%{strong_end} 查看和管ç†æ‚¨çš„使用情æ³ã€‚ %{docs_link_start}了解更多%{link_end}關於如何減少您的儲存空間。"
@@ -42550,6 +43299,9 @@ msgstr "å·²æˆåŠŸç§»é™¤ä½¿ç”¨è€…身份。"
msgid "User identity was successfully updated."
msgstr "å·²æˆåŠŸæ›´æ–°ä½¿ç”¨è€…身份。"
+msgid "User is blocked"
+msgstr "使用者已被å°éŽ–"
+
msgid "User is not allowed to resolve thread"
msgstr "使用者ä¸è¢«å…許解決主題"
@@ -42845,7 +43597,7 @@ msgid "Users can launch a development environment from a GitLab browser tab when
msgstr "%{linkStart}Gitpod%{linkEnd} æ•´åˆå¾Œï¼Œä½¿ç”¨è€…å¯ä»¥å¾ž GitLab ç€è¦½å™¨é¸é …é å•Ÿå‹•é–‹ç™¼ç’°å¢ƒã€‚"
msgid "Users can reactivate their account by signing in. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "使用者å¯ä»¥é€šéŽç™»å…¥é‡æ–°å•Ÿç”¨ä»–們的帳號,%{link_start}了解更多%{link_end}。"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
msgstr "使用者å¯ä»¥ä½¿ç”¨ Kroki 在 AsciiDocã€Markdownã€reStructuredText å’Œ Textile 文件中渲染圖表。"
@@ -42871,9 +43623,6 @@ msgstr "請求存å–的使用者"
msgid "Users to exclude from the rate limit"
msgstr "從速率é™åˆ¶ä¸­æŽ’除的使用者"
-msgid "Users were successfully added."
-msgstr "å·²æˆåŠŸåŠ å…¥ä½¿ç”¨è€…。"
-
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "具有訪客角色或ä¸å±¬æ–¼å°ˆæ¡ˆæˆ–群組的使用者將ä¸ä½”用您授權許å¯ä¸­çš„座次。"
@@ -42892,8 +43641,35 @@ msgstr "沒有指派人 - %{openingTag}分é…給自己%{closingTag}"
msgid "UsersSelect|Unassigned"
msgstr "未分é…"
-msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr "使用 GitLab 作為 Sentry 的輕é‡ç´šæ›¿ä»£å“。"
+msgid "User|Data Analyst"
+msgstr "資料分æžå¸«"
+
+msgid "User|Development Team Lead"
+msgstr "開發團隊負責人"
+
+msgid "User|Devops Engineer"
+msgstr "開發工程師"
+
+msgid "User|Other"
+msgstr "其他"
+
+msgid "User|Product Designer"
+msgstr "產å“設計師"
+
+msgid "User|Product Manager"
+msgstr "產å“經ç†"
+
+msgid "User|Security Analyst"
+msgstr "安全分æžå¸«"
+
+msgid "User|Software Developer"
+msgstr "軟體開發人員"
+
+msgid "User|Systems Administrator"
+msgstr "系統管ç†å“¡"
+
+msgid "Uses GitLab as an alternative to Sentry."
+msgstr "使用 GitLab 作為 Sentry 的替代å“。"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "使用 %{code_start}::%{code_end} 表示 %{link_start}範åœæ¨™ç±¤é›†%{link_end}"
@@ -43139,13 +43915,13 @@ msgid "View all environments."
msgstr "查看所有環境。"
msgid "View all groups"
-msgstr ""
+msgstr "檢視所有群組"
msgid "View all issues"
msgstr "查看所有議題"
msgid "View all projects"
-msgstr ""
+msgstr "檢視所有專案"
msgid "View blame"
msgstr "查看責任歸屬(blame)"
@@ -43153,6 +43929,9 @@ msgstr "查看責任歸屬(blame)"
msgid "View blame prior to this change"
msgstr "在該變更之å‰æª¢è¦–責任歸屬(blame)"
+msgid "View card matches"
+msgstr ""
+
msgid "View chart"
msgid_plural "View charts"
msgstr[0] "查看圖表"
@@ -43175,8 +43954,8 @@ msgstr "查看文件"
msgid "View eligible approvers"
msgstr "查看具備相關資格的核准者"
-msgid "View epics list"
-msgstr "查看å²è©©åˆ—表"
+msgid "View entire blame"
+msgstr "查看全部的責任歸屬(blame)"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
@@ -43597,6 +44376,9 @@ msgstr "檢測到誤報"
msgid "Vulnerability|File"
msgstr "文件"
+msgid "Vulnerability|File:"
+msgstr "檔案:"
+
msgid "Vulnerability|GitLab Security Report"
msgstr "GitLab 安全報告"
@@ -43618,12 +44400,12 @@ msgstr "映åƒ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
msgstr "與如何發ç¾æ¼æ´žåŠå…¶å°ç³»çµ±çš„影響有關的ira æ¯ã€‚"
-msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr "詳細了解此æ¼æ´žä»¥åŠè§£æ±ºæ­¤æ¼æ´žçš„最佳方法。"
-
msgid "Vulnerability|Links"
msgstr "連çµ"
+msgid "Vulnerability|Location"
+msgstr "地點"
+
msgid "Vulnerability|Method"
msgstr "方法"
@@ -43633,6 +44415,9 @@ msgstr "命å空間"
msgid "Vulnerability|Project"
msgstr "專案"
+msgid "Vulnerability|Project:"
+msgstr "專案:"
+
msgid "Vulnerability|Remove identifier row"
msgstr "移除標識符行"
@@ -43660,6 +44445,9 @@ msgstr "根據您å¯ä»¥ç²å¾—的訊æ¯è¨­å®šæ¼æ´žç™¼ç¾çš„狀態。"
msgid "Vulnerability|Severity"
msgstr "åš´é‡ç´šåˆ¥"
+msgid "Vulnerability|Severity:"
+msgstr "åš´é‡æ€§ï¼š"
+
msgid "Vulnerability|Status"
msgstr "狀態"
@@ -43672,6 +44460,9 @@ msgstr "未修改的回應是未å°è«‹æ±‚進行任何更改的原始回應"
msgid "Vulnerability|Tool"
msgstr "工具"
+msgid "Vulnerability|Tool:"
+msgstr ""
+
msgid "Vulnerability|Training"
msgstr "培訓"
@@ -43684,8 +44475,11 @@ msgstr "未修改的回應"
msgid "Vulnerability|View training"
msgstr "查看培訓"
+msgid "WARNING:"
+msgstr "警告:"
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
-msgstr "警告:此程å¼ç¢¼ç‰‡æ®µåŒ…å«å¯èƒ½ç”¨æ–¼æŽ©è“‹æƒ¡æ„行為的隱è—文件,仿製(clone)和執行其中的程å¼ç¢¼éœ€è¦è¬¹æ…Žã€‚"
+msgstr "警告:此程å¼ç¢¼ç‰‡æ®µåŒ…å«å¯èƒ½ç”¨æ–¼æŽ©è“‹æƒ¡æ„行為的隱è—文件,複製和執行其中的程å¼ç¢¼éœ€è¦è¬¹æ…Žã€‚"
msgid "Wait for the file to load to copy its contents"
msgstr "等待文件載入以複製其內容"
@@ -43747,6 +44541,12 @@ msgstr "無法連接Prometheus伺æœå™¨ã€‚伺æœå™¨ä¸å†å­˜åœ¨ï¼Œæˆ–者設定è¨
msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
msgstr "我們建立了一個沙盒專案,將幫助您學習 GitLab 的基礎知識。您將通éŽè­°é¡Œé¢æ¿ä¸­çš„è­°é¡Œç²å¾—指導。您å¯ä»¥æŒ‰ç…§è‡ªå·±çš„節å¥é€šè®€é€™äº›è­°é¡Œã€‚"
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code"
+msgstr "我們åµæ¸¬åˆ°æœ‰äººä¼åœ–使用錯誤的雙因å­èº«ä»½é©—證碼登入您的 %{host} 帳號"
+
+msgid "We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}"
+msgstr "我們åµæ¸¬åˆ°æœ‰äººä¼åœ–使用錯誤的雙因å­èº«ä»½é©—證碼從下列 IP ä½å€ç™»å…¥æ‚¨çš„ %{host} 帳號:%{ip},於 %{time}"
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "我們在%{humanized_resource_name}檢測到潛在濫用行為。請輸入此reCAPTCHA驗證碼並繼續。"
@@ -43829,10 +44629,10 @@ msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrat
msgstr "WebAuthnåªæ”¯æ´å•Ÿç”¨äº†HTTPS的網站。您å¯ä»¥è¯çµ¡ç®¡ç†å“¡ç²å¾—更多訊æ¯"
msgid "WebIDE|Fork project"
-msgstr "分å‰å°ˆæ¡ˆ"
+msgstr "分å‰ï¼ˆFork)專案"
msgid "WebIDE|Go to fork"
-msgstr "å‰å¾€åˆ†å‰"
+msgstr "å‰å¾€åˆ†å‰ï¼ˆFork)"
msgid "WebIDE|Merge request"
msgstr "åˆä½µè«‹æ±‚"
@@ -43841,7 +44641,7 @@ msgid "WebIDE|Quickly and easily edit multiple files in your project."
msgstr "快速且輕鬆地編輯專案中的多個文件。"
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
-msgstr "快速且輕鬆地編輯專案中的多個文件。按 . 打開"
+msgstr "快速且輕鬆地編輯專案中的多個文件,按 . 來打開"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr "此專案ä¸æŽ¥å—未簽åçš„æ交。"
@@ -43853,7 +44653,7 @@ msgid "WebIDE|You can’t edit files directly in this project. Fork this project
msgstr "您ä¸èƒ½åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç›´æŽ¥ç·¨è¼¯æ–‡ä»¶ï¼Œè«‹åˆ†å‰ï¼ˆFork)這個專案並æ交åˆä½µè«‹æ±‚。"
msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
-msgstr "ä¸èƒ½ç›´æŽ¥åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç·¨è¼¯æ–‡ä»¶ï¼Œå‰å¾€æ‚¨çš„分å‰(fork)並æ交包å«æ›´æ”¹çš„åˆä½µè«‹æ±‚。"
+msgstr "ä¸èƒ½ç›´æŽ¥åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç·¨è¼¯æ–‡ä»¶ï¼Œå‰å¾€æ‚¨çš„分å‰ï¼ˆFork)並æ交包å«æ›´æ”¹çš„åˆä½µè«‹æ±‚。"
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr "您需è¦æ¬Šé™æ‰èƒ½ç›´æŽ¥åœ¨æ­¤å°ˆæ¡ˆä¸­ç·¨è¼¯æ–‡ä»¶ã€‚"
@@ -43957,6 +44757,9 @@ msgstr "刪除 webhook"
msgid "Webhooks|Deployment events"
msgstr "部署事件"
+msgid "Webhooks|Do not show sensitive data such as tokens in the UI."
+msgstr ""
+
msgid "Webhooks|Enable SSL verification"
msgstr "啟用SSL驗證"
@@ -43972,12 +44775,18 @@ msgstr "功能標誌事件"
msgid "Webhooks|Go to webhooks"
msgstr "到 webhooks"
+msgid "Webhooks|How it looks in the UI"
+msgstr ""
+
msgid "Webhooks|Issues events"
msgstr "議題事件"
msgid "Webhooks|Job events"
msgstr "作業事件"
+msgid "Webhooks|Mask portions of URL"
+msgstr ""
+
msgid "Webhooks|Member events"
msgstr "æˆå“¡äº‹ä»¶"
@@ -44002,6 +44811,12 @@ msgstr "SSLé©—è­‰"
msgid "Webhooks|Secret token"
msgstr "Secret 令牌"
+msgid "Webhooks|Sensitive portion of URL"
+msgstr ""
+
+msgid "Webhooks|Show full URL"
+msgstr ""
+
msgid "Webhooks|Subgroup events"
msgstr "å­ç¾¤çµ„事件"
@@ -44026,6 +44841,9 @@ msgstr "網å€"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr "如果 URL 包å«ä¸€å€‹æˆ–多個特殊字元,則必須進行百分號編碼。"
+msgid "Webhooks|URL preview"
+msgstr ""
+
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr "用於驗證接收到的有效資訊。與 %{code_start}X-Gitlab-Token HTTP%{code_end} 標頭中的請求一起發é€ã€‚"
@@ -44117,7 +44935,7 @@ msgid "What is repository mirroring?"
msgstr "什麼是版本庫é¡åƒï¼Ÿ"
msgid "What is squashing?"
-msgstr "什麼是壓縮(squashing)?"
+msgstr "什麼是壓縮 (Squashing)?"
msgid "What templates can I create?"
msgstr "我å¯ä»¥å»ºç«‹ä»€éº¼æ¨£çš„範本?"
@@ -44202,12 +45020,6 @@ msgstr "您為什麼註冊?(å¯é¸ï¼‰"
msgid "Wiki"
msgstr "Wiki"
-msgid "Wiki Page|Rich text"
-msgstr "è±å¯Œæ–‡å­—æ ¼å¼"
-
-msgid "Wiki Page|Source"
-msgstr "來æº"
-
msgid "Wiki page"
msgstr "Wiki é é¢"
@@ -44221,7 +45033,7 @@ msgid "Wiki page was successfully updated."
msgstr "Wikié é¢å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "WikiClone|Clone your wiki"
-msgstr "仿製(clone)您的 wiki"
+msgstr "複製您的 wiki"
msgid "WikiClone|Git Access"
msgstr "Git å­˜å–"
@@ -44442,6 +45254,12 @@ msgstr "增加指派者"
msgid "WorkItem|Add assignees"
msgstr "增加指派者"
+msgid "WorkItem|Add due date"
+msgstr "加入截止日期"
+
+msgid "WorkItem|Add start date"
+msgstr "加入開始日期"
+
msgid "WorkItem|Add task"
msgstr "增加任務"
@@ -44473,9 +45291,15 @@ msgstr "建立任務"
msgid "WorkItem|Create work item"
msgstr "建立工作項"
+msgid "WorkItem|Dates"
+msgstr "日期"
+
msgid "WorkItem|Delete %{workItemType}"
msgstr "刪除 %{workItemType}"
+msgid "WorkItem|Due date"
+msgstr "截止日期"
+
msgid "WorkItem|Expand tasks"
msgstr "展開任務"
@@ -44542,6 +45366,9 @@ msgstr "æ›´æ–° %{workItemType} 時發生錯誤,請é‡è©¦ã€‚"
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr "更新工作項時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚"
+msgid "WorkItem|Start date"
+msgstr "開始日期"
+
msgid "WorkItem|Task"
msgstr "任務"
@@ -44802,6 +45629,12 @@ msgstr "您å¯ä»¥åœ¨ %{pat_link_start}個人存å–令牌%{pat_link_end} 中查çœ
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
msgstr "您å¯ä»¥åœ¨æ‚¨çš„個人存å–令牌設定 %{pat_link} 中查看它。"
+msgid "You can check your tokens or create a new one in your %{pat_link_start}personal access tokens settings%{pat_link_end}."
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„%{pat_link_start}個人存å–權æ–設定%{pat_link_end}檢查您的權æ–或建立新的。"
+
+msgid "You can check your tokens or create a new one in your personal access tokens settings %{pat_link}."
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„個人存å–權æ–設定 %{pat_link} 檢查您的權æ–或建立新的。"
+
msgid "You can create a new %{link}."
msgstr "您å¯ä»¥å»ºç«‹ä¸€å€‹æ–°çš„%{link}。"
@@ -44851,7 +45684,7 @@ msgid "You can find more information about GitLab subscriptions in %{subscriptio
msgstr "您å¯ä»¥åœ¨ %{subscriptions_doc_link} 找到更多關於 GitLab 訂閱的資訊"
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
-msgstr "您å¯ä»¥é€šéŽä»¿è£½(clone)版本庫開始,或使用以下方å¼ä¹‹ä¸€åŠ å…¥æ–‡ä»¶ã€‚"
+msgstr "您å¯ä»¥é€šéŽè¤‡è£½ (Clone) 版本庫開始,或使用以下方å¼ä¹‹ä¸€åŠ å…¥æ–‡ä»¶ã€‚"
msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
msgstr "您å¯ä»¥ä½¿ç”¨æ¨™ç±¤å°æ¸¬è©¦æ¡ˆä¾‹é€²è¡Œåˆ†çµ„。è¦äº†è§£æ­¤åŠŸèƒ½çš„未來發展方å‘ï¼Œè«‹å­˜å– %{linkStart}質é‡ç®¡ç†æ–¹å‘é %{linkEnd}。"
@@ -44914,7 +45747,7 @@ msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "您也å¯ä»¥é€šéŽ%{linkStart}Lint%{linkEnd}測試.gitlab-ci.yml."
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
-msgstr "您å¯ä»¥æŸ¥çœ‹ä¾†æºç¨‹å¼ç¢¼æˆ–%{linkStart}%{cloneIcon}仿製(clone)版本庫%{linkEnd}"
+msgstr "您å¯ä»¥æŸ¥çœ‹ä¾†æºç¨‹å¼ç¢¼æˆ–%{linkStart}%{cloneIcon}複製 (Clone) 版本庫%{linkEnd}"
msgid "You can't add any more, but you can manage your existing members, for example, by removing inactive members and replacing them with new members. To get more members an owner of the group can start a trial or upgrade to a paid tier."
msgstr "您無法å†å¢žåŠ ï¼Œä½†å¯ä»¥ç®¡ç†ç¾æœ‰æˆå“¡ï¼Œä¾‹å¦‚,通éŽåˆªé™¤éžæ´»èºçš„æˆå“¡ä¸¦å°‡å…¶æ›¿æ›ç‚ºæ–°æˆå“¡ã€‚為了å–得更多æˆå“¡ï¼Œç¾¤çµ„çš„æ“有者å¯ä»¥é–‹å§‹è©¦ç”¨æˆ–å‡ç´šåˆ°ä»˜è²»å±¤ç´šã€‚"
@@ -44925,6 +45758,9 @@ msgstr "您ä¸èƒ½ %{action} %{state} 使用者。"
msgid "You cannot access the raw file. Please wait a minute."
msgstr "您ä¸èƒ½å­˜å–原始文件。請ç¨å€™ã€‚"
+msgid "You cannot add any more epics. This epic already has maximum number of child epics."
+msgstr "您ä¸èƒ½å†å¢žåŠ ä»»ä½•å²è©©ï¼Œè©²å²è©©å·²ç¶“æ“有最大數é‡çš„å­å²è©©ã€‚"
+
msgid "You cannot approve your own deployment."
msgstr "您ä¸èƒ½æ ¸å‡†æ‚¨è‡ªå·±çš„部署。"
@@ -45074,7 +45910,7 @@ msgid "You have insufficient permissions to create an HTTP integration for this
msgstr "您沒有足夠的權é™ç‚ºæ­¤å°ˆæ¡ˆå»ºç«‹HTTPæ•´åˆ"
msgid "You have insufficient permissions to create an on-call schedule for this project"
-msgstr "您沒有足夠的權é™ä¾†å»ºç«‹æ­¤å°ˆæ¡ˆçš„待命(on-call)計劃"
+msgstr "您沒有足夠的權é™ä¾†å»ºç«‹æ­¤å°ˆæ¡ˆçš„ on-call 排程"
msgid "You have insufficient permissions to manage resource links for this incident"
msgstr "您沒有足夠的權é™ç®¡ç†æ­¤äº‹æ•…的資æºéˆçµ"
@@ -45086,7 +45922,7 @@ msgid "You have insufficient permissions to remove an on-call rotation from this
msgstr "您的權é™ä¸è¶³ï¼Œç„¡æ³•å¾žæ­¤å°ˆæ¡ˆä¸­ç§»é™¤on-call輪æ›"
msgid "You have insufficient permissions to remove an on-call schedule from this project"
-msgstr "您沒有足夠的權é™å¾žæ­¤å°ˆæ¡ˆä¸­ç§»é™¤ on-call 計劃"
+msgstr "您沒有足夠的權é™å¾žæ­¤å°ˆæ¡ˆä¸­ç§»é™¤ on-call 排程"
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr "您沒有足夠的權é™ç§»é™¤æ­¤HTTPæ•´åˆ"
@@ -45098,7 +45934,7 @@ msgid "You have insufficient permissions to set customer relations contacts for
msgstr "您沒有足夠的權é™ç‚ºæ­¤è­°é¡Œè¨­å®šå®¢æˆ¶é—œä¿‚è¯çµ¡äºº"
msgid "You have insufficient permissions to update an on-call schedule for this project"
-msgstr "您沒有足夠的權é™ä¾†æ›´æ–°æ­¤å°ˆæ¡ˆçš„on-call計劃"
+msgstr "您沒有足夠的權é™ä¾†æ›´æ–°æ­¤å°ˆæ¡ˆçš„ on-call 排程"
msgid "You have insufficient permissions to update this HTTP integration"
msgstr "您沒有足夠的權é™ä¾†æ›´æ–°æ­¤HTTPæ•´åˆ"
@@ -45124,8 +45960,8 @@ msgstr "您已經為您的帳號設定了雙因å­(2FA)é©—è­‰ï¼ å¦‚æžœæ‚¨ç„¡æ³•
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
msgstr "您已æˆåŠŸè³¼è²· %{product}。您將通éŽé›»å­éƒµä»¶æ”¶åˆ°æ”¶æ“šã€‚您的購買å¯èƒ½éœ€è¦ä¸€åˆ†é˜æ‰èƒ½åŒæ­¥ï¼Œå¦‚果您還沒有看到,請é‡æ–°æ•´ç†é é¢ã€‚"
-msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. It might take a moment for GitLab.com to fully reflect your purchase."
-msgstr "您已æˆåŠŸè³¼è²· %{seats} çš„ %{plan} 訂閱計劃。您將通éŽé›»å­éƒµä»¶æ”¶åˆ°æ”¶æ“šã€‚ GitLab.com å¯èƒ½éœ€è¦ä¸€é»žæ™‚é–“æ‰èƒ½å®Œå…¨å應您的購買情æ³ã€‚"
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
+msgstr "您已æˆåŠŸè³¼è²· %{seats} çš„ %{plan} 方案訂閱。您將會é€éŽé›»å­éƒµä»¶æ”¶åˆ°æ”¶æ“šã€‚您的購買å¯èƒ½éœ€è¦ä¸€åˆ†é˜åŒæ­¥ï¼Œè‹¥æ‚¨é‚„沒看到,請é‡æ–°æ•´ç†é é¢ã€‚"
msgid "You have unsaved changes"
msgstr "您有未儲存的變更"
@@ -45142,8 +45978,8 @@ msgstr "您必須經éŽé©—è­‰æ‰èƒ½å­˜å–此路徑。"
msgid "You must be logged in to search across all of GitLab"
msgstr "您必須登入æ‰èƒ½åœ¨æ•´å€‹GitLab中進行æœå°‹"
-msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
-msgstr "啟用除錯追蹤時,您必須在關è¯å°ˆæ¡ˆä¸­æ“有開發人員或更高權é™æ‰èƒ½æŸ¥çœ‹ä½œæ¥­æ—¥èªŒã€‚è¦åœç”¨é™¤éŒ¯è¿½è¹¤ï¼Œè«‹åœ¨æµæ°´ç·šè¨­å®šæˆ– CI/CD 設定中將「CI_DEBUG_TRACEã€è®Šæ•¸è¨­å®šç‚ºã€Œfalseã€ã€‚如果您需è¦æŸ¥çœ‹æ­¤ä½œæ¥­æ—¥èªŒï¼Œå°ˆæ¡ˆç¶­è­·è€…必須將您加入到具有開發人員權é™æˆ–更高權é™çš„專案中。"
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher."
+msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr "å¿…é ˆæ“有維護者權é™æ‰èƒ½å¼·åˆ¶åˆªé™¤éŽ–定"
@@ -45194,7 +46030,7 @@ msgid "You successfully declined the invitation"
msgstr "您已æˆåŠŸæ‹’絕邀請"
msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
-msgstr "您已嘗試分å‰(fort) %{link_to_the_project} 但由於以下原因導致失敗:"
+msgstr "您已嘗試分å‰ï¼ˆFork) %{link_to_the_project} 但由於以下原因導致失敗:"
msgid "You will be removed from existing projects/groups"
msgstr "您將被從ç¾æœ‰å°ˆæ¡ˆ/群組中刪除"
@@ -45413,10 +46249,10 @@ 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 "æ‚¨çš„å¸³è™Ÿå·²é€šéŽ SSO 或 SAML 進行身份驗證。 è¦ä½¿ç”¨æ­¤å¸³è™Ÿä¾† %{push_pull_link_start}推é€å’Œæ‹‰å–%{link_end} çš„ %{protocol} ,您必須設定 %{set_password_link_start}密碼%{link_end} 或 %{set_up_pat_link_start}設定個人存å–令牌%{link_end} 以代替密碼。 欲了解更多訊æ¯ï¼Œè«‹å­˜å– %{clone_with_https_link_start}使用 HTTPS 仿製(clone)%{link_end}。"
+msgstr "æ‚¨çš„å¸³è™Ÿå·²é€šéŽ SSO 或 SAML 進行身份驗證。 è¦ä½¿ç”¨æ­¤å¸³è™Ÿä¾† %{push_pull_link_start}推é€å’Œæ‹‰å–%{link_end} çš„ %{protocol} ,您必須設定 %{set_password_link_start}密碼%{link_end} 或 %{set_up_pat_link_start}設定個人存å–令牌%{link_end} 以代替密碼。 欲了解更多訊æ¯ï¼Œè«‹å­˜å– %{clone_with_https_link_start}使用 HTTPS 克隆 (clone)%{link_end}。"
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 "æ‚¨çš„å¸³è™Ÿå·²é€šéŽ SSO 或 SAML 進行身份驗證。è¦ä½¿ç”¨æ­¤å¸³è™Ÿä¾† %{push_pull_link_start}推é€å’Œæ‹‰å–%{link_end} è¶…éŽ %{protocol} %{set_up_pat_link_start}設定個人存å–令牌%{link_end} 以代替密碼使用。有關詳細訊æ¯ï¼Œè«‹åƒé–± %{clone_with_https_link_start}使用 HTTPS 進行仿製(clone)%{link_end}。"
+msgstr "æ‚¨çš„å¸³è™Ÿå·²é€šéŽ SSO 或 SAML 進行身份驗證。è¦ä½¿ç”¨æ­¤å¸³è™Ÿä¾† %{push_pull_link_start}推é€å’Œæ‹‰å–%{link_end} è¶…éŽ %{protocol} %{set_up_pat_link_start}設定個人存å–令牌%{link_end} 以代替密碼使用。有關詳細訊æ¯ï¼Œè«‹åƒé–± %{clone_with_https_link_start}使用 HTTPS 進行複製 (Clone) %{link_end}。"
msgid "Your account is locked."
msgstr "您的帳號已被鎖定。"
@@ -45574,7 +46410,7 @@ msgid "Your profile"
msgstr "個人資料"
msgid "Your project is no longer receiving GitLab Ultimate benefits as of 2022-07-01. As notified in-app previously, public open source projects on the Free tier can apply to the GitLab for Open Source Program to receive GitLab Ultimate benefits. Please refer to the %{faq_link_start}FAQ%{link_end} for more details."
-msgstr ""
+msgstr "自 2022 å¹´ 7 月 1 日起,您的專案將ä¸å†ç²å¾— GitLab Ultimate ç¦åˆ©ã€‚正如之å‰åœ¨æ‡‰ç”¨ç¨‹å¼å…§çš„通知,å…費層級的公共開æºå°ˆæ¡ˆå¯ä»¥ç”³è«‹ GitLab é–‹æºè¨ˆåŠƒä»¥ç²å¾— GitLab Ultimate ç¦åˆ©ã€‚è«‹åƒé–± %{faq_link_start}FAQ%{link_end} 了解更多詳情。"
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr "您的專案é™åˆ¶ç‚º %{limit} 個專案ï¼è«‹èˆ‡æ‚¨çš„管ç†å“¡è¯çµ¡ä»¥å¢žåŠ å®ƒ"
@@ -45725,6 +46561,9 @@ msgstr "已加入"
msgid "added %{emails}"
msgstr "加入了 %{emails}"
+msgid "added a %{link_type} link"
+msgstr "增加了一個 %{link_type} éˆçµ"
+
msgid "added a Zoom call to this issue"
msgstr "加入Zoom通話到此議題"
@@ -45817,6 +46656,9 @@ msgstr "來自"
msgid "cURL:"
msgstr "cURL:"
+msgid "can contain only digits"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr "åªèƒ½åŒ…å«Base64å­—æ¯è¡¨(RFC4648)中的字æ¯ï¼Œä»¥åŠã€Œ@ã€ã€ã€Œ:ã€å’Œã€Œ.ã€ã€‚"
@@ -45862,6 +46704,9 @@ msgstr "無法將éžæ©Ÿå¯†å·¥ä½œé …目指定至機密上層。請將工作項目
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯éŽåŽ»çš„日期"
+msgid "cannot be added since you've reached your %{free_limit} member limit for %{namespace_name}"
+msgstr ""
+
msgid "cannot be changed"
msgstr "無法被更改"
@@ -45872,7 +46717,7 @@ msgid "cannot be changed if shared runners are enabled"
msgstr "如果啟用共用執行器(runners),則無法更改"
msgid "cannot be changed since member is associated with a custom role"
-msgstr ""
+msgstr "æˆå“¡èˆ‡è‡ªå®šç¾©è§’色相關è¯å³ç„¡æ³•è¢«æ›´æ”¹"
msgid "cannot be enabled"
msgstr "無法啟用"
@@ -46118,6 +46963,9 @@ msgstr "找到%{issuesWithCount}"
msgid "ciReport|Full Report"
msgstr "完整報告"
+msgid "ciReport|Generic Report"
+msgstr ""
+
msgid "ciReport|IaC Scanning"
msgstr "IaC 掃æ"
@@ -46273,6 +47121,9 @@ msgstr "收集使用訊æ¯"
msgid "comment"
msgstr "留言"
+msgid "commented"
+msgstr "評論留言"
+
msgid "commented on %{link_to_project}"
msgstr "留言 %{link_to_project}"
@@ -46318,6 +47169,9 @@ msgstr "建立於%{timeAgo}"
msgid "created %{timeAgo} by %{author}"
msgstr "由 %{author} 建立於 %{timeAgo}"
+msgid "created %{timeAgo} by %{author} in %{project_link}"
+msgstr "在 %{project_link} 中由 %{author} 建立於 %{timeAgo}"
+
msgid "created by"
msgstr "建立者:"
@@ -46633,9 +47487,6 @@ msgstr "ä¸è¢«å…許,因為該群組ä¸æ˜¯æœ€ä¸Šå±¤ç¾¤çµ„。"
msgid "is not allowed. Please use your regular email address."
msgstr "ä¸è¢«å…許。請使用您的常è¦é›»å­éƒµä»¶åœ°å€ã€‚"
-msgid "is not allowed. We do not currently support project-level iterations"
-msgstr "ä¸è¢«å…許。我們目å‰ä¸æ”¯æ´å°ˆæ¡ˆç´šè¿­ä»£"
-
msgid "is not in the group enforcing Group Managed Account"
msgstr "ä¸åœ¨å¼·åˆ¶åŸ·è¡Œç¾¤çµ„託管帳號的群組中"
@@ -46726,6 +47577,10 @@ msgstr "LFS å°åƒ"
msgid "limit of %{project_limit} reached"
msgstr "å·²é”到%{project_limit}çš„é™åˆ¶"
+msgid "line"
+msgid_plural "lines"
+msgstr[0] "行"
+
msgid "load it anyway"
msgstr "ä»ç„¶è¼‰å…¥"
@@ -46761,6 +47616,9 @@ msgstr "(æ交已被壓縮)"
msgid "metric_id must be unique across a project"
msgstr "metric_id必須是整個專案唯一的"
+msgid "milestone should belong either to a project or a group."
+msgstr "里程碑應該屬於一個專案或一個群組。"
+
msgid "missing"
msgstr "éºå¤±"
@@ -46873,10 +47731,10 @@ msgid "mrWidget|Checking if merge request can be merged…"
msgstr "正在檢查åˆä½µè«‹æ±‚是å¦å¯ä»¥åˆä½µâ€¦"
msgid "mrWidget|Cherry-pick"
-msgstr "æ€é¸(Cherry-pick)"
+msgstr "æ€é¸ (Cherry-pick)"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr "通éŽæ–°çš„åˆä½µè«‹æ±‚中æ€é¸(Cherry-pick)æ­¤åˆä½µè«‹æ±‚"
+msgstr "通éŽæ–°çš„åˆä½µè«‹æ±‚中æ€é¸ (Cherry-pick) æ­¤åˆä½µè«‹æ±‚"
msgid "mrWidget|Closed"
msgstr "已關閉"
@@ -46950,7 +47808,7 @@ 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 "åˆä½µå·²å—阻:快進åˆä½µæ˜¯ä¸å¯èƒ½çš„。è¦åˆä½µé€™å€‹è«‹æ±‚,首先在本地變基(rebase)。"
+msgstr "åˆä½µå·²å—阻:快進 (fast-forward) åˆä½µä¸å¯ç”¨ï¼Œè¦åˆä½µé€™å€‹è«‹æ±‚,首先在本地變基 (Rebase) 。"
msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
msgstr "åˆä½µå·²å—阻:必須解決åˆä½µè¡çªã€‚"
@@ -47034,7 +47892,7 @@ msgid "mrWidget|Revert"
msgstr "還原"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr "é€éŽæ–°çš„åˆä½µè«‹æ±‚中還原此åˆä½µè«‹æ±‚"
+msgstr "在新的åˆä½µè«‹æ±‚中還原 (Revert) 該åˆä½µè«‹æ±‚"
msgid "mrWidget|Revoke approval"
msgstr "撤銷核准"
@@ -47067,13 +47925,13 @@ msgid "mrWidget|To approve this merge request, please enter your password. This
msgstr "è¦æ ¸å‡†æ­¤åˆä½µè«‹æ±‚,請輸入您的密碼。此專案需è¦æ‰€æœ‰æ ¸å‡†æ‰èƒ½èªè­‰ã€‚"
msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯å£“縮與åˆä½µæ交訊æ¯çš„範本。%{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
+msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯åˆä½µèˆ‡å£“縮 (Squash) æ交訊æ¯çš„範本。%{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯åˆä½µæ交訊æ¯çš„範本。 %{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯å£“縮æ交訊æ¯çš„範本。 %{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
+msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯å£“縮 (Squash) æ交訊æ¯çš„範本。 %{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr "å¯ä»¥å¯«å…¥ä¾†æºæˆ–目標分支的使用者å¯ä»¥è§£æ±ºè¡çªã€‚"
@@ -47126,6 +47984,9 @@ msgstr "必須有一個版本庫"
msgid "must match %{association}.project_id"
msgstr "å¿…é ˆç¬¦åˆ %{association}.project_id"
+msgid "must not contain commonly used combinations of words and letters"
+msgstr "ä¸å¾—包å«å¸¸ç”¨çš„單字與字æ¯çµ„åˆ"
+
msgid "my-awesome-group"
msgstr "我的群組"
@@ -47207,9 +48068,6 @@ msgstr "或"
msgid "organizations can only be added to root groups"
msgstr "組織åªèƒ½è¢«åŠ å…¥åˆ°æ ¹(root)群組"
-msgid "other card matches"
-msgstr "其他符åˆçš„å¡ç‰‡"
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "於總計%d個測試中"
@@ -47349,6 +48207,9 @@ msgstr "移除權é‡"
msgid "removed"
msgstr "已移除"
+msgid "removed a %{link_type} link"
+msgstr "移除了一個 %{link_type} éˆçµ"
+
msgid "removed a Zoom call from this issue"
msgstr "從目å‰è­°é¡Œä¸­ç§»é™¤Zoom通話"
@@ -47380,6 +48241,10 @@ msgstr "掃æ執行政策:政策未套用, %{policy_path} 文件無效"
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
msgstr "掃æ執行政策:政策未套用,缺少 %{policy_path} 文件"
+msgid "seat"
+msgid_plural "seats"
+msgstr[0] "席次"
+
msgid "security Reports|There was an error creating the merge request"
msgstr "建立åˆä½µè«‹æ±‚時發生錯誤"
@@ -47488,6 +48353,9 @@ msgstr "範本已準備就緒ï¼ç¾åœ¨ï¼Œæ‚¨å¯ä»¥æ交來建立您的第一æ¢
msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
msgstr "我們正在加入GitLab CI設定文件,以將æµæ°´ç·šåŠ å…¥åˆ°å°ˆæ¡ˆä¸­ã€‚您也å¯ä»¥æ‰‹å‹•å»ºç«‹ï¼Œä½†æˆ‘們建議您從一個立å³å¯ç”¨çš„GitLab範本開始。"
+msgid "supported SSH public key."
+msgstr ""
+
msgid "tag name"
msgstr "標籤å稱"
@@ -47554,6 +48422,10 @@ msgstr "æ›´æ–°æ–¼%{time_ago}"
msgid "uploads"
msgstr "上傳"
+msgid "user"
+msgid_plural "users"
+msgstr[0] "使用者"
+
msgid "user avatar"
msgstr "使用者頭åƒ"
diff --git a/package.json b/package.json
index 5242ede8a09..667b423bad0 100644
--- a/package.json
+++ b/package.json
@@ -52,8 +52,8 @@
"@codesandbox/sandpack-client": "^1.2.2",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "3.3.0",
- "@gitlab/ui": "43.16.0",
+ "@gitlab/svgs": "3.5.0",
+ "@gitlab/ui": "46.1.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20220815034418",
"@rails/actioncable": "6.1.4-7",
@@ -90,6 +90,7 @@
"@tiptap/extension-task-item": "^2.0.0-beta.37",
"@tiptap/extension-task-list": "^2.0.0-beta.29",
"@tiptap/extension-text": "^2.0.0-beta.17",
+ "@tiptap/suggestion": "^2.0.0-beta.96",
"@tiptap/vue-2": "^2.0.0-beta.84",
"apollo-upload-client": "15.0.0",
"autosize": "^5.0.1",
@@ -97,13 +98,14 @@
"babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4",
"bootstrap": "4.5.3",
+ "browserslist": "^4.21.3",
"cache-loader": "^4.1.0",
"canvas-confetti": "^1.4.0",
"clipboard": "^2.0.8",
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.25.1",
+ "core-js": "^3.25.5",
"cron-validator": "^1.1.1",
"cronstrue": "^1.122.0",
"cropper": "^2.3.0",
@@ -118,11 +120,14 @@
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^10.0.0",
+ "esbuild": "0.15.9",
+ "esbuild-loader": "^2.20.0",
"fast-mersenne-twister": "1.0.2",
"file-loader": "^6.2.0",
"fuzzaldrin-plus": "^0.6.0",
"graphql": "^15.7.2",
"graphql-tag": "^2.11.0",
+ "gridstack": "^7.0.0",
"highlight.js": "^11.5.1",
"immer": "^9.0.15",
"ipaddr.js": "^1.9.1",
@@ -143,11 +148,11 @@
"minimatch": "^3.0.4",
"monaco-editor": "^0.30.1",
"monaco-editor-webpack-plugin": "^6.0.0",
- "monaco-yaml": "3.0.0",
+ "monaco-yaml": "4.0.0",
"mousetrap": "1.6.5",
"papaparse": "^5.3.1",
"patch-package": "^6.4.7",
- "pdfjs-dist": "^2.0.943",
+ "pdfjs-dist": "^2.16.105",
"pikaday": "^1.8.0",
"popper.js": "^1.16.1",
"portal-vue": "^2.1.7",
@@ -171,6 +176,7 @@
"swagger-ui-dist": "4.12.0",
"three": "^0.143.0",
"timeago.js": "^4.0.2",
+ "tippy.js": "^6.3.7",
"unified": "^10.1.2",
"unist-builder": "^3.0.0",
"unist-util-visit-parents": "^5.1.0",
@@ -197,9 +203,9 @@
"yaml": "^2.0.0-10"
},
"devDependencies": {
- "@gitlab/eslint-plugin": "17.0.0",
+ "@gitlab/eslint-plugin": "18.1.0",
"@gitlab/stylelint-config": "4.1.0",
- "@graphql-eslint/eslint-plugin": "3.10.7",
+ "@graphql-eslint/eslint-plugin": "3.12.0",
"@testing-library/dom": "^7.16.2",
"@types/jest": "^27.5.1",
"@vue/test-utils": "1.3.0",
@@ -212,7 +218,7 @@
"cheerio": "^1.0.0-rc.9",
"commander": "^2.20.3",
"custom-jquery-matchers": "^2.1.0",
- "eslint": "8.23.1",
+ "eslint": "8.25.0",
"eslint-import-resolver-jest": "3.0.2",
"eslint-import-resolver-webpack": "0.13.2",
"eslint-plugin-import": "^2.26.0",
@@ -231,8 +237,8 @@
"jest-jasmine2": "^27.5.1",
"jest-junit": "^12.0.0",
"jest-raw-loader": "^1.0.1",
- "jest-transform-graphql": "^2.1.0",
"jest-util": "^27.5.1",
+ "jsonlint": "^1.6.3",
"markdownlint-cli": "0.32.2",
"miragejs": "^0.1.40",
"mock-apollo-client": "1.2.0",
@@ -246,7 +252,7 @@
"sass": "^1.49.9",
"stylelint": "^14.9.1",
"timezone-mock": "^1.0.8",
- "webpack-dev-server": "4.11.0",
+ "webpack-dev-server": "4.11.1",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
"yarn-deduplicate": "^6.0.0"
@@ -262,4 +268,4 @@
"node": ">=12.22.1",
"yarn": "^1.10.0"
}
-}
+} \ No newline at end of file
diff --git a/qa/Gemfile b/qa/Gemfile
index cf939f8e301..12e5d66fc6b 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -2,46 +2,48 @@
source 'https://rubygems.org'
-gem 'gitlab-qa', '~> 8', require: 'gitlab/qa'
+gem 'gitlab-qa', '~> 8', '>= 8.8.0', require: 'gitlab/qa'
gem 'activesupport', '~> 6.1.4.7' # This should stay in sync with the root's Gemfile
-gem 'allure-rspec', '~> 2.16.0'
-gem 'capybara', '~> 3.35.0'
-gem 'capybara-screenshot', '~> 1.0.23'
+gem 'allure-rspec', '~> 2.18.0'
+gem 'capybara', '~> 3.37.1'
+gem 'capybara-screenshot', '~> 1.0.26'
gem 'rake', '~> 13'
-gem 'rspec', '~> 3.10'
-gem 'selenium-webdriver', '~> 4.0'
-gem 'airborne', '~> 0.3.4', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
+gem 'rspec', '~> 3.11'
+gem 'selenium-webdriver', '~> 4.5'
+gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
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 'rspec_junit_formatter', '~> 0.6.0'
+gem 'faker', '~> 2.23'
gem 'knapsack', '~> 4.0'
-gem 'parallel_tests', '~> 2.29'
-gem 'rotp', '~> 3.1.0'
-gem 'timecop', '~> 0.9.1'
+gem 'parallel_tests', '~> 3.13'
+gem 'rotp', '~> 6.2.0'
+gem 'timecop', '~> 0.9.5'
gem 'parallel', '~> 1.19'
gem 'rainbow', '~> 3.0.0'
-gem 'rspec-parameterized', '~> 0.4.2'
-gem 'octokit', '~> 4.21'
-gem 'webdrivers', '~> 5.0'
+gem 'rspec-parameterized', '~> 0.5.2'
+gem 'octokit', '~> 5.6.1'
+gem "faraday-retry", "~> 2.0"
+gem 'webdrivers', '~> 5.2'
gem 'zeitwerk', '~> 2.4'
gem 'influxdb-client', '~> 1.17'
-gem 'terminal-table', '~> 3.0.0', require: false
+gem 'terminal-table', '~> 3.0.2', require: false
gem 'slack-notifier', '~> 2.4', require: false
-gem 'fog-google', '~> 1.17', require: false
+gem 'fog-google', '~> 1.19', require: false
+gem 'fog-core', '2.1.0', require: false # fog-google generates a ton of warnings with latest core
gem "warning", "~> 1.3"
gem 'confiner', '~> 0.3'
-gem 'chemlab', '~> 0.9'
+gem 'chemlab', '~> 0.10'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
# dependencies for jenkins client
-gem 'nokogiri', '~> 1.12'
+gem 'nokogiri', '~> 1.13', '>= 1.13.9'
-gem 'deprecation_toolkit', '~> 1.5.1', require: false
+gem 'deprecation_toolkit', '~> 2.0.0', require: false
group :development do
- gem 'pry-byebug', '~> 3.5.1', platform: :mri
- gem "ruby-debug-ide", "~> 0.7.0"
+ gem 'pry-byebug', '~> 3.10.1', platform: :mri
+ gem "ruby-debug-ide", "~> 0.7.3"
end
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index dd14b675769..23f82f553f1 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -1,28 +1,24 @@
GEM
remote: https://rubygems.org/
specs:
- abstract_type (0.0.7)
activesupport (6.1.4.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
- adamantium (0.2.0)
- ice_nine (~> 0.11.0)
- memoizable (~> 0.4.0)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
- airborne (0.3.4)
+ airborne (0.3.7)
activesupport
rack
rack-test (>= 1.1.0, < 2.0)
rest-client (>= 2.0.2, < 3.0)
rspec (~> 3.8)
- allure-rspec (2.16.1)
- allure-ruby-commons (= 2.16.1)
+ allure-rspec (2.18.0)
+ allure-ruby-commons (= 2.18.0)
rspec-core (>= 3.8, < 4)
- allure-ruby-commons (2.16.1)
+ allure-ruby-commons (2.18.0)
mime-types (>= 3.3, < 4)
oj (>= 3.10, < 4)
require_all (>= 2, < 4)
@@ -30,19 +26,20 @@ GEM
ast (2.4.2)
binding_ninja (0.2.3)
builder (3.2.4)
- byebug (9.1.0)
- capybara (3.35.3)
+ byebug (11.1.3)
+ capybara (3.37.1)
addressable
+ matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
- capybara-screenshot (1.0.23)
+ capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4)
launchy
- chemlab (0.9.2)
+ chemlab (0.10.0)
colorize (~> 0.8)
i18n (~> 1.8)
rake (>= 12, < 14)
@@ -53,40 +50,25 @@ GEM
childprocess (4.1.0)
coderay (1.1.2)
colorize (0.8.1)
- concord (0.1.5)
- adamantium (~> 0.2.0)
- equalizer (~> 0.0.9)
concurrent-ruby (1.1.10)
confiner (0.3.0)
gitlab (>= 4.17)
zeitwerk (~> 2.5.1)
declarative (0.0.20)
- deprecation_toolkit (1.5.1)
- activesupport (>= 4.2)
+ deprecation_toolkit (2.0.0)
+ activesupport (>= 5.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)
- faraday-em_http (~> 1.0)
- faraday-em_synchrony (~> 1.0)
- faraday-excon (~> 1.1)
- faraday-httpclient (~> 1.0.1)
- faraday-net_http (~> 1.0)
- faraday-net_http_persistent (~> 1.1)
- faraday-patron (~> 1.0)
- multipart-post (>= 1.2, < 3)
+ excon (0.92.4)
+ faker (2.23.0)
+ i18n (>= 1.8.11, < 2)
+ faraday (2.5.2)
+ faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
- faraday-em_http (1.0.0)
- faraday-em_synchrony (1.0.0)
- faraday-excon (1.1.0)
- faraday-httpclient (1.0.1)
- faraday-net_http (1.0.1)
- faraday-net_http_persistent (1.2.0)
- faraday-patron (1.0.0)
+ faraday-net_http (3.0.0)
+ faraday-retry (2.0.0)
+ faraday (~> 2.0)
ffi (1.15.5)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
@@ -96,8 +78,8 @@ GEM
excon (~> 0.58)
formatador (~> 0.2)
mime-types
- fog-google (1.17.0)
- fog-core (<= 2.1.0)
+ fog-google (1.19.0)
+ fog-core (< 2.3)
fog-json (~> 1.2)
fog-xml (~> 0.1.0)
google-apis-compute_v1 (~> 0.14)
@@ -118,17 +100,18 @@ GEM
gitlab (4.18.0)
httparty (~> 0.18)
terminal-table (>= 1.5.1)
- gitlab-qa (8.4.2)
+ gitlab-qa (8.8.0)
activesupport (~> 6.1)
gitlab (~> 4.18.0)
http (~> 5.0)
nokogiri (~> 1.10)
- rainbow (~> 3.0.0)
+ rainbow (>= 3, < 4)
table_print (= 1.5.7)
- zeitwerk (~> 2.4)
- google-apis-compute_v1 (0.21.0)
- google-apis-core (>= 0.4, < 2.a)
- google-apis-core (0.4.1)
+ toxiproxy (~> 2.0.2)
+ zeitwerk (>= 2, < 3)
+ google-apis-compute_v1 (0.51.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-core (0.9.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@@ -137,22 +120,22 @@ GEM
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-apis-dns_v1 (0.27.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-iamcredentials_v1 (0.14.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-monitoring_v3 (0.33.0)
+ google-apis-core (>= 0.7, < 2.a)
+ google-apis-pubsub_v1 (0.28.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-sqladmin_v1beta4 (0.36.0)
+ google-apis-core (>= 0.7.2, < 2.a)
+ google-apis-storage_v1 (0.18.0)
+ google-apis-core (>= 0.7, < 2.a)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
- googleauth (1.1.0)
- faraday (>= 0.17.3, < 2.0)
+ googleauth (1.2.0)
+ faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
@@ -173,22 +156,20 @@ GEM
httpclient (2.8.3)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
- ice_nine (0.11.2)
influxdb-client (1.17.0)
- jwt (2.3.0)
+ jwt (2.5.0)
knapsack (4.0.0)
rake
- launchy (2.4.3)
- addressable (~> 2.3)
+ launchy (2.5.0)
+ addressable (~> 2.7)
llhttp-ffi (0.4.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
macaddr (1.7.2)
systemu (~> 2.6.5)
+ matrix (0.4.2)
memoist (0.16.2)
- memoizable (0.4.2)
- thread_safe (~> 0.3, >= 0.3.1)
- method_source (0.9.0)
+ method_source (1.0.0)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
@@ -197,18 +178,17 @@ GEM
minitest (5.16.3)
multi_json (1.15.0)
multi_xml (0.6.0)
- multipart-post (2.1.1)
netrc (0.11.0)
- nokogiri (1.13.8)
+ nokogiri (1.13.9)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
- octokit (4.25.1)
+ octokit (5.6.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
- oj (3.13.11)
+ oj (3.13.21)
os (1.1.4)
parallel (1.19.2)
- parallel_tests (2.29.0)
+ parallel_tests (3.13.0)
parallel
parser (3.1.2.1)
ast (~> 2.4.1)
@@ -216,13 +196,12 @@ GEM
coderay
parser
unparser
- procto (0.0.3)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry-byebug (3.5.1)
- byebug (~> 9.1)
- pry (~> 0.10)
+ pry (0.14.1)
+ coderay (~> 1.1)
+ method_source (~> 1.0)
+ pry-byebug (3.10.1)
+ byebug (~> 11.0)
+ pry (>= 0.13, < 0.15)
public_suffix (5.0.0)
racc (1.6.0)
rack (2.2.3.1)
@@ -231,7 +210,7 @@ GEM
rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
- representable (3.1.1)
+ representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
@@ -243,44 +222,45 @@ GEM
netrc (~> 0.8)
retriable (3.1.2)
rexml (3.2.5)
- rotp (3.1.0)
- rspec (3.10.0)
- rspec-core (~> 3.10.0)
- rspec-expectations (~> 3.10.0)
- rspec-mocks (~> 3.10.0)
- rspec-core (3.10.1)
- rspec-support (~> 3.10.0)
- rspec-expectations (3.10.1)
+ rotp (6.2.0)
+ rspec (3.11.0)
+ rspec-core (~> 3.11.0)
+ rspec-expectations (~> 3.11.0)
+ rspec-mocks (~> 3.11.0)
+ rspec-core (3.11.0)
+ rspec-support (~> 3.11.0)
+ rspec-expectations (3.11.1)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.10.0)
- rspec-mocks (3.10.2)
+ rspec-support (~> 3.11.0)
+ rspec-mocks (3.11.1)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.10.0)
- rspec-parameterized (0.4.2)
+ rspec-support (~> 3.11.0)
+ rspec-parameterized (0.5.2)
binding_ninja (>= 0.2.3)
parser
proc_to_ast
rspec (>= 2.13, < 4)
unparser
- rspec-retry (0.6.1)
+ rspec-retry (0.6.2)
rspec-core (> 3.3)
- rspec-support (3.10.2)
- rspec_junit_formatter (0.4.1)
+ rspec-support (3.11.1)
+ rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
- ruby-debug-ide (0.7.2)
+ ruby-debug-ide (0.7.3)
rake (>= 0.8.1)
- ruby2_keywords (0.0.4)
+ ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
- selenium-webdriver (4.0.3)
+ selenium-webdriver (4.5.0)
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
- rubyzip (>= 1.2.2)
- signet (0.16.0)
+ rubyzip (>= 1.2.2, < 3.0)
+ websocket (~> 1.0)
+ signet (0.17.0)
addressable (~> 2.8)
- faraday (>= 0.17.3, < 2.0)
+ faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
slack-notifier (2.4.0)
@@ -288,8 +268,8 @@ GEM
table_print (1.5.7)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
- thread_safe (0.3.6)
- timecop (0.9.1)
+ timecop (0.9.5)
+ toxiproxy (2.0.2)
trailblazer-option (0.1.2)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
@@ -297,26 +277,22 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
- unicode-display_width (2.2.0)
- unparser (0.4.7)
- abstract_type (~> 0.0.7)
- adamantium (~> 0.2.0)
- concord (~> 0.1.5)
+ unicode-display_width (2.3.0)
+ unparser (0.6.5)
diff-lcs (~> 1.3)
- equalizer (~> 0.0.9)
- parser (>= 2.6.5)
- procto (~> 0.0.2)
+ parser (>= 3.1.0)
uuid (2.3.9)
macaddr (~> 1.0)
warning (1.3.0)
- watir (6.19.1)
+ watir (7.1.0)
regexp_parser (>= 1.2, < 3)
- selenium-webdriver (>= 3.142.7)
- webdrivers (5.0.0)
+ selenium-webdriver (~> 4.0)
+ webdrivers (5.2.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0)
webrick (1.7.0)
+ websocket (1.2.9)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.5.4)
@@ -326,40 +302,42 @@ PLATFORMS
DEPENDENCIES
activesupport (~> 6.1.4.7)
- airborne (~> 0.3.4)
- allure-rspec (~> 2.16.0)
- capybara (~> 3.35.0)
- capybara-screenshot (~> 1.0.23)
- chemlab (~> 0.9)
+ airborne (~> 0.3.7)
+ allure-rspec (~> 2.18.0)
+ capybara (~> 3.37.1)
+ capybara-screenshot (~> 1.0.26)
+ chemlab (~> 0.10)
chemlab-library-www-gitlab-com (~> 0.1)
confiner (~> 0.3)
- deprecation_toolkit (~> 1.5.1)
- faker (~> 2.19, >= 2.19.0)
- fog-google (~> 1.17)
- gitlab-qa (~> 8)
+ deprecation_toolkit (~> 2.0.0)
+ faker (~> 2.23)
+ faraday-retry (~> 2.0)
+ fog-core (= 2.1.0)
+ fog-google (~> 1.19)
+ gitlab-qa (~> 8, >= 8.8.0)
influxdb-client (~> 1.17)
knapsack (~> 4.0)
- nokogiri (~> 1.12)
- octokit (~> 4.21)
+ nokogiri (~> 1.13, >= 1.13.9)
+ octokit (~> 5.6.1)
parallel (~> 1.19)
- parallel_tests (~> 2.29)
- pry-byebug (~> 3.5.1)
+ parallel_tests (~> 3.13)
+ pry-byebug (~> 3.10.1)
rainbow (~> 3.0.0)
rake (~> 13)
rest-client (~> 2.1.0)
- rotp (~> 3.1.0)
- rspec (~> 3.10)
- rspec-parameterized (~> 0.4.2)
+ rotp (~> 6.2.0)
+ rspec (~> 3.11)
+ rspec-parameterized (~> 0.5.2)
rspec-retry (~> 0.6.1)
- rspec_junit_formatter (~> 0.4.1)
- ruby-debug-ide (~> 0.7.0)
- selenium-webdriver (~> 4.0)
+ rspec_junit_formatter (~> 0.6.0)
+ ruby-debug-ide (~> 0.7.3)
+ selenium-webdriver (~> 4.5)
slack-notifier (~> 2.4)
- terminal-table (~> 3.0.0)
- timecop (~> 0.9.1)
+ terminal-table (~> 3.0.2)
+ timecop (~> 0.9.5)
warning (~> 1.3)
- webdrivers (~> 5.0)
+ webdrivers (~> 5.2)
zeitwerk (~> 2.4)
BUNDLED WITH
- 2.3.15
+ 2.3.24
diff --git a/qa/Rakefile b/qa/Rakefile
index ada27596ae4..6f94c63b4de 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -11,7 +11,7 @@ end
desc "Initialize GitLab with an access token"
task :initialize_gitlab_auth, [:address] do |_, args|
- QA::Tools::InitializeGitLabAuth.new(args).run
+ QA::Tools::InitializeGitlabAuth.new(args).run
end
desc "Generate Performance Testdata"
@@ -46,7 +46,7 @@ task generate_data_and_run_load_test: [:generate_perf_testdata, :run_artillery_l
desc "Deletes test ssh keys a user"
task :delete_test_ssh_keys, [:title_portion, :delete_before, :dry_run] do |_, args|
- QA::Tools::DeleteTestSSHKeys.new(args).run
+ QA::Tools::DeleteTestSshKeys.new(args).run
end
desc "Deletes projects directly under the provided group"
diff --git a/qa/chemlab-library-gitlab.gemspec b/qa/chemlab-library-gitlab.gemspec
index 9af4a650d98..309de157757 100644
--- a/qa/chemlab-library-gitlab.gemspec
+++ b/qa/chemlab-library-gitlab.gemspec
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-$:.unshift(File.expand_path('lib', __dir__))
+$LOAD_PATH.unshift(File.expand_path('lib', __dir__))
Gem::Specification.new do |spec|
spec.name = 'chemlab-library-gitlab'
diff --git a/qa/lib/gitlab/page/admin/subscription.rb b/qa/lib/gitlab/page/admin/subscription.rb
index ef73bad2879..058cf8d281e 100644
--- a/qa/lib/gitlab/page/admin/subscription.rb
+++ b/qa/lib/gitlab/page/admin/subscription.rb
@@ -23,7 +23,7 @@ module Gitlab
h2 :users_over_subscription
table :subscription_history
- span :no_valid_license_alert, text: /no longer has a valid license/
+ div :no_valid_license_alert, text: /no longer has a valid license/
h3 :no_active_subscription_title, text: /do not have an active subscription/
def accept_terms
diff --git a/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb b/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb
index 192e71e6c90..2a5d9a6bb5e 100644
--- a/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb
+++ b/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb
@@ -5,51 +5,51 @@ module Gitlab
module Group
module Settings
module UsageQuota
- # @note Defined as +link :pipeline_tab+
- # Clicks +pipeline_tab+
- def pipeline_tab
+ # @note Defined as +link :seats_tab+
+ # Clicks +seats_tab+
+ def seats_tab
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.pipeline_tab_element).to exist
+ # expect(usage_quota.seats_tab_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
- def pipeline_tab_element
+ def seats_tab_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_pipeline_tab
+ # expect(usage_quota).to be_seats_tab
# end
- # @return [Boolean] true if the +pipeline_tab+ element is present on the page
- def pipeline_tab?
+ # @return [Boolean] true if the +seats_tab+ element is present on the page
+ def seats_tab?
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +link :storage_tab+
- # Clicks +storage_tab+
- def storage_tab
+ # @note Defined as +link :pipelines_tab+
+ # Clicks +pipelines_tab+
+ def pipelines_tab
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.storage_tab_element).to exist
+ # expect(usage_quota.pipelines_tab_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
- def storage_tab_element
+ def pipelines_tab_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_storage_tab
+ # expect(usage_quota).to be_pipelines_tab
# end
- # @return [Boolean] true if the +storage_tab+ element is present on the page
- def storage_tab?
+ # @return [Boolean] true if the +pipelines_tab+ element is present on the page
+ def pipelines_tab?
# This is a stub, used for indexing. The method is dynamically generated.
end
@@ -77,6 +77,102 @@ module Gitlab
# This is a stub, used for indexing. The method is dynamically generated.
end
+ # @note Defined as +div :plan_ci_minutes+
+ # @return [String] The text content or value of +plan_ci_minutes+
+ def plan_ci_minutes
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.plan_ci_minutes_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def plan_ci_minutes_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_plan_ci_minutes
+ # end
+ # @return [Boolean] true if the +plan_ci_minutes+ element is present on the page
+ def plan_ci_minutes?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :additional_ci_minutes+
+ # @return [String] The text content or value of +additional_ci_minutes+
+ def additional_ci_minutes
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.additional_ci_minutes_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def additional_ci_minutes_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_additional_ci_minutes
+ # end
+ # @return [Boolean] true if the +additional_ci_minutes+ element is present on the page
+ def additional_ci_minutes?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :ci_purchase_successful_alert+
+ # @return [String] The text content or value of +ci_purchase_successful_alert+
+ def ci_purchase_successful_alert
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.ci_purchase_successful_alert_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def ci_purchase_successful_alert_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_ci_purchase_successful_alert
+ # end
+ # @return [Boolean] true if the +ci_purchase_successful_alert+ element is present on the page
+ def ci_purchase_successful_alert?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +link :storage_tab+
+ # Clicks +storage_tab+
+ def storage_tab
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.storage_tab_element).to exist
+ # end
+ # @return [Watir::Link] The raw +Link+ element
+ def storage_tab_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_storage_tab
+ # end
+ # @return [Boolean] true if the +storage_tab+ element is present on the page
+ def storage_tab?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
# @note Defined as +link :buy_storage+
# Clicks +buy_storage+
def buy_storage
@@ -101,123 +197,315 @@ module Gitlab
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +strong :additional_minutes+
- # @return [String] The text content or value of +additional_minutes+
- def additional_minutes
+ # @note Defined as +div :used_storage_message+
+ # @return [String] The text content or value of +used_storage_message+
+ def used_storage_message
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.used_storage_message_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def used_storage_message_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_used_storage_message
+ # end
+ # @return [Boolean] true if the +used_storage_message+ element is present on the page
+ def used_storage_message?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :group_usage_message+
+ # @return [String] The text content or value of +group_usage_message+
+ def group_usage_message
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.group_usage_message_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def group_usage_message_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_group_usage_message
+ # end
+ # @return [Boolean] true if the +group_usage_message+ element is present on the page
+ def group_usage_message?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :dependency_proxy_usage+
+ # @return [String] The text content or value of +dependency_proxy_usage+
+ def dependency_proxy_usage
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.dependency_proxy_usage_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def dependency_proxy_usage_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_dependency_proxy_usage
+ # end
+ # @return [Boolean] true if the +dependency_proxy_usage+ element is present on the page
+ def dependency_proxy_usage?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +span :dependency_proxy_size+
+ # @return [String] The text content or value of +dependency_proxy_size+
+ def dependency_proxy_size
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.additional_minutes_element).to exist
+ # expect(usage_quota.dependency_proxy_size_element).to exist
# end
- # @return [Watir::Strong] The raw +Strong+ element
- def additional_minutes_element
+ # @return [Watir::Span] The raw +Span+ element
+ def dependency_proxy_size_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_additional_minutes
+ # expect(usage_quota).to be_dependency_proxy_size
# end
- # @return [Boolean] true if the +additional_minutes+ element is present on the page
- def additional_minutes?
+ # @return [Boolean] true if the +dependency_proxy_size+ element is present on the page
+ def dependency_proxy_size?
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +div :additional_minutes_usage+
- # @return [String] The text content or value of +additional_minutes_usage+
- def additional_minutes_usage
+ # @note Defined as +div :container_registry_usage+
+ # @return [String] The text content or value of +container_registry_usage+
+ def container_registry_usage
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.additional_minutes_usage_element).to exist
+ # expect(usage_quota.container_registry_usage_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
- def additional_minutes_usage_element
+ def container_registry_usage_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_additional_minutes_usage
+ # expect(usage_quota).to be_container_registry_usage
# end
- # @return [Boolean] true if the +additional_minutes_usage+ element is present on the page
- def additional_minutes_usage?
+ # @return [Boolean] true if the +container_registry_usage+ element is present on the page
+ def container_registry_usage?
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +strong :plan_minutes+
- # @return [String] The text content or value of +plan_minutes+
- def plan_minutes
+ # @note Defined as +div :project_storage_used+
+ # @return [String] The text content or value of +project_storage_used+
+ def project_storage_used
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.plan_minutes_element).to exist
+ # expect(usage_quota.project_storage_used_element).to exist
# end
- # @return [Watir::Strong] The raw +Strong+ element
- def plan_minutes_element
+ # @return [Watir::Div] The raw +Div+ element
+ def project_storage_used_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_plan_minutes
+ # expect(usage_quota).to be_project_storage_used
# end
- # @return [Boolean] true if the +plan_minutes+ element is present on the page
- def plan_minutes?
+ # @return [Boolean] true if the +project_storage_used+ element is present on the page
+ def project_storage_used?
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +div :plan_minutes_usage+
- # @return [String] The text content or value of +plan_minutes_usage+
- def plan_minutes_usage
+ # @note Defined as +div :project+
+ # @return [String] The text content or value of +project+
+ def project
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.plan_minutes_usage_element).to exist
+ # expect(usage_quota.project_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
- def plan_minutes_usage_element
+ def project_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_plan_minutes_usage
+ # expect(usage_quota).to be_project
# end
- # @return [Boolean] true if the +plan_minutes_usage+ element is present on the page
- def plan_minutes_usage?
+ # @return [Boolean] true if the +project+ element is present on the page
+ def project?
# This is a stub, used for indexing. The method is dynamically generated.
end
- # @note Defined as +div :purchase_successful_alert+
- # @return [String] The text content or value of +purchase_successful_alert+
- def purchase_successful_alert
+ # @note Defined as +div :storage_type_legend+
+ # @return [String] The text content or value of +storage_type_legend+
+ def storage_type_legend
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota.purchase_successful_alert_element).to exist
+ # expect(usage_quota.storage_type_legend_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
- def purchase_successful_alert_element
+ def storage_type_legend_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_storage_type_legend
+ # end
+ # @return [Boolean] true if the +storage_type_legend+ element is present on the page
+ def storage_type_legend?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +span :container_registry_size+
+ # @return [String] The text content or value of +container_registry_size+
+ def container_registry_size
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.container_registry_size_element).to exist
+ # end
+ # @return [Watir::Span] The raw +Span+ element
+ def container_registry_size_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_container_registry_size
+ # end
+ # @return [Boolean] true if the +container_registry_size+ element is present on the page
+ def container_registry_size?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :purchased_usage_total_free+
+ # @return [String] The text content or value of +purchased_usage_total_free+
+ def purchased_usage_total_free
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.purchased_usage_total_free_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def purchased_usage_total_free_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_purchased_usage_total_free
+ # end
+ # @return [Boolean] true if the +purchased_usage_total_free+ element is present on the page
+ def purchased_usage_total_free?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +span :purchased_usage_total+
+ # @return [String] The text content or value of +purchased_usage_total+
+ def purchased_usage_total
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.purchased_usage_total_element).to exist
+ # end
+ # @return [Watir::Span] The raw +Span+ element
+ def purchased_usage_total_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_purchased_usage_total
+ # end
+ # @return [Boolean] true if the +purchased_usage_total+ element is present on the page
+ def purchased_usage_total?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +div :storage_purchase_successful_alert+
+ # @return [String] The text content or value of +storage_purchase_successful_alert+
+ def storage_purchase_successful_alert
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.storage_purchase_successful_alert_element).to exist
+ # end
+ # @return [Watir::Div] The raw +Div+ element
+ def storage_purchase_successful_alert_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota).to be_storage_purchase_successful_alert
+ # end
+ # @return [Boolean] true if the +storage_purchase_successful_alert+ element is present on the page
+ def storage_purchase_successful_alert?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +h2 :storage_available_alert+
+ # @return [String] The text content or value of +storage_available_alert+
+ def storage_available_alert
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
+ # expect(usage_quota.storage_available_alert_element).to exist
+ # end
+ # @return [Watir::H2] The raw +H2+ element
+ def storage_available_alert_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
- # expect(usage_quota).to be_purchase_successful_alert
+ # expect(usage_quota).to be_storage_available_alert
# end
- # @return [Boolean] true if the +purchase_successful_alert+ element is present on the page
- def purchase_successful_alert?
+ # @return [Boolean] true if the +storage_available_alert+ element is present on the page
+ def storage_available_alert?
# This is a stub, used for indexing. The method is dynamically generated.
end
end
diff --git a/qa/lib/gitlab/page/group/settings/usage_quotas.rb b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
index 2b491188595..a1ab345bf1e 100644
--- a/qa/lib/gitlab/page/group/settings/usage_quotas.rb
+++ b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
@@ -5,16 +5,30 @@ module Gitlab
module Group
module Settings
class UsageQuotas < Chemlab::Page
- # TODO: Supplant with data-qa-selectors
+ # Seats section
+ link :seats_tab
+
+ # Pipelines section
link :pipelines_tab
- link :storage_tab
link :buy_ci_minutes
- link :buy_storage
div :plan_ci_minutes
div :additional_ci_minutes
- span :purchased_usage_total
- div :purchased_usage_total_free, 'data-testid': 'purchased-usage-card' # Different UI for free namespace
div :ci_purchase_successful_alert, text: /You have successfully purchased CI minutes/
+
+ # Storage section
+ link :storage_tab
+ link :purchase_more_storage
+ div :used_storage_message
+ div :group_usage_message
+ div :dependency_proxy_usage
+ span :dependency_proxy_size
+ div :container_registry_usage
+ div :project_storage_used
+ div :project
+ div :storage_type_legend
+ span :container_registry_size
+ div :purchased_usage_total_free # Different UI for free namespace
+ span :purchased_usage_total
div :storage_purchase_successful_alert, text: /You have successfully purchased a storage/
h2 :storage_available_alert, text: /purchased storage is available/
@@ -35,6 +49,15 @@ module Gitlab
false
end
+ # Waits and Checks if storage project data loaded
+ #
+ # @return [Boolean] True if the alert presents, false if not after 5 second wait
+ def project_storage_data_available?
+ storage_type_legend_element.wait_until(timeout: 3, &: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
diff --git a/qa/qa.rb b/qa/qa.rb
index 99a8a34d6d8..bf6b75a1278 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -30,6 +30,22 @@ module QA
loader.ignore("#{root}/specs/features")
loader.ignore("#{root}/specs/spec_helper.rb")
+ # we need to eager load scenario classes
+ # zeitwerk does not have option to configure what to eager load, so all exceptions have to be defined
+ loader.do_not_eager_load("#{root}/ce")
+ loader.do_not_eager_load("#{root}/ee")
+ loader.do_not_eager_load("#{root}/flow")
+ loader.do_not_eager_load("#{root}/git")
+ loader.do_not_eager_load("#{root}/mobile")
+ loader.do_not_eager_load("#{root}/page")
+ loader.do_not_eager_load("#{root}/resource")
+ loader.do_not_eager_load("#{root}/runtime")
+ loader.do_not_eager_load("#{root}/service")
+ loader.do_not_eager_load("#{root}/specs")
+ loader.do_not_eager_load("#{root}/support")
+ loader.do_not_eager_load("#{root}/tools")
+ loader.do_not_eager_load("#{root}/vendor")
+
loader.inflector.inflect(
"ce" => "CE",
"ee" => "EE",
@@ -74,6 +90,7 @@ module QA
end
loader.setup
+ loader.eager_load
end
# Custom warning processing
diff --git a/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb b/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb
deleted file mode 100644
index 20bb5f3964e..00000000000
--- a/qa/qa/fixtures/package_managers/maven/client_pom.xml.erb
+++ /dev/null
@@ -1,19 +0,0 @@
-<project>
- <groupId><%= group_id %></groupId>
- <artifactId>maven_client</artifactId>
- <version>1.0</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id><%= package_project.name %></id>
- <url><%= gitlab_address_with_port %>/api/v4/groups/<%= package_project.group.id %>/-/packages/maven</url>
- </repository>
- </repositories>
- <dependencies>
- <dependency>
- <groupId><%= group_id %></groupId>
- <artifactId><%= artifact_id %></artifactId>
- <version><%= package_version %></version>
- </dependency>
- </dependencies>
-</project> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/build_install.gradle.erb b/qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb
index 31543d30e88..31543d30e88 100644
--- a/qa/qa/fixtures/package_managers/maven/build_install.gradle.erb
+++ b/qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb
diff --git a/qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb b/qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb
index c14e63e11df..c14e63e11df 100644
--- a/qa/qa/fixtures/package_managers/maven/build_upload.gradle.erb
+++ b/qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb
diff --git a/qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb
index 49873f124cc..49873f124cc 100644
--- a/qa/qa/fixtures/package_managers/maven/gradle_install_package.yaml.erb
+++ b/qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb
index 3f3c7dce03c..3f3c7dce03c 100644
--- a/qa/qa/fixtures/package_managers/maven/gradle_upload_package.yaml.erb
+++ b/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/gitlab_ci.yaml.erb
index 78d6255e9a9..78d6255e9a9 100644
--- a/qa/qa/fixtures/package_managers/maven/maven_install_package.yaml.erb
+++ b/qa/qa/fixtures/package_managers/maven/group/consumer/gitlab_ci.yaml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/pom.xml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/pom.xml.erb
new file mode 100644
index 00000000000..adc8b0294b3
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/group/consumer/pom.xml.erb
@@ -0,0 +1,19 @@
+<project>
+ <groupId><%= group_id %></groupId>
+ <artifactId>maven_client</artifactId>
+ <version>1.0</version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id><%= client_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/groups/<%= client_project.group.id %>/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <dependencies>
+ <dependency>
+ <groupId><%= group_id %></groupId>
+ <artifactId><%= artifact_id %></artifactId>
+ <version><%= package_version %></version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/settings.xml.erb
new file mode 100644
index 00000000000..fb7e2a4af88
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/group/consumer/settings.xml.erb
@@ -0,0 +1,16 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+<servers>
+ <server>
+ <id><%= client_project.name %></id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name><%= maven_header_name %></name>
+ <value><%= token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+</servers>
+</settings> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/group/producer/gitlab_ci.yaml.erb
index 64a63bf0bd8..64a63bf0bd8 100644
--- a/qa/qa/fixtures/package_managers/maven/maven_upload_package.yaml.erb
+++ b/qa/qa/fixtures/package_managers/maven/group/producer/gitlab_ci.yaml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/package_pom.xml.erb b/qa/qa/fixtures/package_managers/maven/group/producer/pom.xml.erb
index 5159172a170..5159172a170 100644
--- a/qa/qa/fixtures/package_managers/maven/package_pom.xml.erb
+++ b/qa/qa/fixtures/package_managers/maven/group/producer/pom.xml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/group/producer/settings.xml.erb
index b670b83cf85..b670b83cf85 100644
--- a/qa/qa/fixtures/package_managers/maven/settings.xml.erb
+++ b/qa/qa/fixtures/package_managers/maven/group/producer/settings.xml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb b/qa/qa/fixtures/package_managers/maven/group/settings_with_pat.xml.erb
index 611c232819f..611c232819f 100644
--- a/qa/qa/fixtures/package_managers/maven/settings_with_pat.xml.erb
+++ b/qa/qa/fixtures/package_managers/maven/group/settings_with_pat.xml.erb
diff --git a/qa/qa/fixtures/package_managers/maven/project/gitlab_ci.yaml.erb b/qa/qa/fixtures/package_managers/maven/project/gitlab_ci.yaml.erb
new file mode 100644
index 00000000000..44186e92ba7
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/project/gitlab_ci.yaml.erb
@@ -0,0 +1,9 @@
+deploy-and-install:
+ image: maven:3.6-jdk-11
+ script:
+ - 'mvn deploy -s settings.xml'
+ - 'mvn install -s settings.xml'
+ only:
+ - "<%= package_project.default_branch %>"
+ tags:
+ - "runner-for-<%= package_project.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/project/pom.xml.erb b/qa/qa/fixtures/package_managers/maven/project/pom.xml.erb
new file mode 100644
index 00000000000..5159172a170
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/project/pom.xml.erb
@@ -0,0 +1,22 @@
+ <project>
+ <groupId><%= group_id %></groupId>
+ <artifactId><%= artifact_id %></artifactId>
+ <version><%= package_version %></version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/groups/<%= package_project.group.id %>/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id><%= package_project.name %></id>
+ <url><%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb
new file mode 100644
index 00000000000..a41bdc4d650
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb
@@ -0,0 +1,8 @@
+install:
+ image: maven:3.6-jdk-11
+ script:
+ - 'mvn install -U -s settings.xml'
+ only:
+ - "<%= imported_project.default_branch %>"
+ tags:
+ - "runner-for-<%= imported_project.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb
new file mode 100644
index 00000000000..caf1fc9b761
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb
@@ -0,0 +1,23 @@
+<settings>
+ <servers>
+ <server>
+ <id>central-proxy</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value><%= personal_access_token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ <mirrors>
+ <mirror>
+ <id>central-proxy</id>
+ <name>GitLab proxy of central repo</name>
+ <url><%= gitlab_address_with_port %>/api/v4/projects/<%= imported_project.id %>/packages/maven</url>
+ <mirrorOf>central</mirrorOf>
+ </mirror>
+ </mirrors>
+</settings>
diff --git a/qa/qa/fixtures/package_managers/maven/project/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/project/settings.xml.erb
new file mode 100644
index 00000000000..b670b83cf85
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/project/settings.xml.erb
@@ -0,0 +1,16 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+<servers>
+ <server>
+ <id><%= package_project.name %></id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name><%= maven_header_name %></name>
+ <value><%= token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+</servers>
+</settings> \ No newline at end of file
diff --git a/qa/qa/fixtures/software_licenses/other b/qa/qa/fixtures/software_licenses/other
new file mode 100644
index 00000000000..b6652f05dab
--- /dev/null
+++ b/qa/qa/fixtures/software_licenses/other
@@ -0,0 +1,7 @@
+This software is licensed under the Other license
+=======
+
+This Other license isn't a real license and won't be used by any real project.
+This license does not come with any guarantees. The author cannot be hold liable
+in any way, and users are permitted to do anything they want with the provided
+code. \ No newline at end of file
diff --git a/qa/qa/flow/purchase.rb b/qa/qa/flow/purchase.rb
index c07e03c104d..32c4f469207 100644
--- a/qa/qa/flow/purchase.rb
+++ b/qa/qa/flow/purchase.rb
@@ -45,11 +45,12 @@ module QA
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
+ usage_quota.purchase_more_storage
end
- # Purchase checkout opens a new tab
- Chemlab.configuration.browser.session.engine.switch_window
+ # Purchase checkout opens a new tab but buying additional storage does not
+ session = Chemlab.configuration.browser.session.engine
+ session.switch_window if session.windows.size == 2
Gitlab::Page::Subscriptions::New.perform do |storage|
storage.quantity = quantity
diff --git a/qa/qa/mobile/page/main/menu.rb b/qa/qa/mobile/page/main/menu.rb
index 40bb421b383..73d3b9f7982 100644
--- a/qa/qa/mobile/page/main/menu.rb
+++ b/qa/qa/mobile/page/main/menu.rb
@@ -22,10 +22,10 @@ module QA
end
def open_mobile_menu
- if has_no_element?(:user_avatar)
+ if has_no_element?(:user_avatar_content)
Support::Retrier.retry_until do
click_element(:mobile_navbar_button)
- has_element?(:user_avatar)
+ has_element?(:user_avatar_content)
end
end
end
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
index e55e156fb8a..3164676f8e4 100644
--- a/qa/qa/page/admin/menu.rb
+++ b/qa/qa/page/admin/menu.rb
@@ -5,78 +5,79 @@ module QA
module Admin
class Menu < Page::Base
view 'app/views/layouts/nav/sidebar/_admin.html.haml' do
- element :admin_sidebar
- element :admin_sidebar_settings_submenu_content
- element :admin_settings_item
- element :admin_settings_repository_item
- element :admin_settings_general_item
- element :admin_settings_metrics_and_profiling_item
+ element :admin_sidebar_content
+ element :admin_monitoring_menu_link
+ element :admin_monitoring_submenu_content
+ element :admin_overview_submenu_content
+ element :admin_overview_users_link
+ element :admin_overview_groups_link
+ element :admin_settings_menu_link
+ element :admin_settings_submenu_content
+ element :admin_settings_general_link
+ element :admin_settings_integrations_link
+ element :admin_settings_metrics_and_profiling_link
+ element :admin_settings_network_link
element :admin_settings_preferences_link
- element :admin_monitoring_link
- element :admin_sidebar_monitoring_submenu_content
- element :admin_sidebar_overview_submenu_content
- element :users_overview_link
- element :groups_overview_link
- element :integration_settings_link
+ element :admin_settings_repository_link
end
def go_to_preferences_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
click_element :admin_settings_preferences_link
end
end
end
def go_to_repository_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
- click_element :admin_settings_repository_item
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
+ click_element :admin_settings_repository_link
end
end
end
def go_to_integration_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
- click_element :integration_settings_link
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
+ click_element :admin_settings_integrations_link
end
end
end
def go_to_general_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
- click_element :admin_settings_general_item
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
+ click_element :admin_settings_general_link
end
end
end
def go_to_metrics_and_profiling_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
- click_element :admin_settings_metrics_and_profiling_item
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
+ click_element :admin_settings_metrics_and_profiling_link
end
end
end
def go_to_network_settings
- hover_element(:admin_settings_item) do
- within_submenu(:admin_sidebar_settings_submenu_content) do
- click_element :admin_settings_network_item
+ hover_element(:admin_settings_menu_link) do
+ within_submenu(:admin_settings_submenu_content) do
+ click_element :admin_settings_network_link
end
end
end
def go_to_users_overview
- within_submenu(:admin_sidebar_overview_submenu_content) do
- click_element :users_overview_link
+ within_submenu(:admin_overview_submenu_content) do
+ click_element :admin_overview_users_link
end
end
def go_to_groups_overview
- within_submenu(:admin_sidebar_overview_submenu_content) do
- click_element :groups_overview_link
+ within_submenu(:admin_overview_submenu_content) do
+ click_element :admin_overview_groups_link
end
end
@@ -92,7 +93,7 @@ module QA
end
def within_sidebar
- within_element(:admin_sidebar) do
+ within_element(:admin_sidebar_content) do
yield
end
end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 03f753b1d61..81c518bb4c6 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -242,6 +242,11 @@ module QA
end
def fill_element(name, content)
+ # `click_element_coordinates` is used to ensure the element is focused.
+ # Without it, flakiness can occur on pages with GitLab keyboard shortcuts enabled,
+ # where certain keys trigger actions when typed elsewhere on the page.
+ click_element_coordinates(name)
+
find_element(name).set(content)
end
diff --git a/qa/qa/page/component/clone_panel.rb b/qa/qa/page/component/clone_panel.rb
index a0aea6fe44d..3ea29ff63da 100644
--- a/qa/qa/page/component/clone_panel.rb
+++ b/qa/qa/page/component/clone_panel.rb
@@ -11,18 +11,18 @@ module QA
base.view 'app/views/projects/buttons/_clone.html.haml' do
element :clone_dropdown
- element :clone_options
- element :ssh_clone_url
- element :http_clone_url
+ element :clone_dropdown_content
+ element :ssh_clone_url_content
+ element :http_clone_url_content
end
end
def repository_clone_http_location
- repository_clone_location(:http_clone_url)
+ repository_clone_location(:http_clone_url_content)
end
def repository_clone_ssh_location
- repository_clone_location(:ssh_clone_url)
+ repository_clone_location(:ssh_clone_url_content)
end
private
@@ -31,7 +31,7 @@ module QA
wait_until(reload: false) do
click_element :clone_dropdown
- within_element :clone_options do
+ within_element :clone_dropdown_content do
Git::Location.new(find_element(kind).value)
end
end
diff --git a/qa/qa/page/component/content_editor.rb b/qa/qa/page/component/content_editor.rb
index f7b055b6052..e9fc575ae39 100644
--- a/qa/qa/page/component/content_editor.rb
+++ b/qa/qa/page/component/content_editor.rb
@@ -22,8 +22,8 @@ module QA
element :file_upload_field
end
- base.view 'app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue' do
- element :wiki_hidden_content
+ base.view 'app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue' do
+ element :markdown_editor_form_field
end
end
@@ -47,7 +47,7 @@ module QA
end
QA::Support::Retrier.retry_on_exception do
- source = find_element(:wiki_hidden_content, visible: false)
+ source = find_element(:markdown_editor_form_field, visible: false)
source.value =~ %r{uploads/.*#{::File.basename(image_path)}}
end
end
diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb
index ff61c91f0f6..28b8ece918d 100644
--- a/qa/qa/page/component/groups_filter.rb
+++ b/qa/qa/page/component/groups_filter.rb
@@ -9,7 +9,7 @@ module QA
def self.included(base)
super
- base.view 'app/views/shared/groups/_search_form.html.haml' do
+ base.view 'app/assets/javascripts/groups/components/overview_tabs.vue' do
element :groups_filter_field
end
diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb
index 5c39cfd3695..27dce152367 100644
--- a/qa/qa/page/component/invite_members_modal.rb
+++ b/qa/qa/page/component/invite_members_modal.rb
@@ -62,13 +62,9 @@ module QA
Support::Waiter.wait_until { has_element?(:group_select_dropdown_item) }
- # Workaround for race condition with concurrent group API calls while searching
- # Remove Retrier after https://gitlab.com/gitlab-org/gitlab/-/issues/349379 is resolved
- Support::Retrier.retry_on_exception do
- fill_element :group_select_dropdown_search_field, group_name
- Support::WaitForRequests.wait_for_requests
- click_button group_name
- end
+ fill_element :group_select_dropdown_search_field, group_name
+ Support::WaitForRequests.wait_for_requests
+ click_button group_name
set_access_level(access_level)
end
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 68da89dc81d..71a69576c06 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -18,6 +18,10 @@ module QA
element :more_assignees_link
end
+ base.view 'app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue' do
+ element :reviewers_edit_button
+ end
+
base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue' do
element :labels_block
end
@@ -37,6 +41,7 @@ module QA
base.view 'app/views/shared/issuable/_sidebar.html.haml' do
element :assignee_block_container
element :milestone_block
+ element :reviewers_block_container
end
base.view 'app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue' do
@@ -46,6 +51,10 @@ module QA
base.view 'app/assets/javascripts/sidebar/components/sidebar_editable_item.vue' do
element :edit_link
end
+
+ base.view 'app/helpers/dropdowns_helper.rb' do
+ element :dropdown_list_content
+ end
end
def assign_milestone(milestone)
diff --git a/qa/qa/page/component/legacy_clone_panel.rb b/qa/qa/page/component/legacy_clone_panel.rb
index f15d159a712..ee372a3f9aa 100644
--- a/qa/qa/page/component/legacy_clone_panel.rb
+++ b/qa/qa/page/component/legacy_clone_panel.rb
@@ -11,8 +11,8 @@ module QA
base.view 'app/views/shared/_clone_panel.html.haml' do
element :clone_dropdown
- element :clone_options_dropdown, '.clone-options-dropdown' # rubocop:disable QA/ElementWithPattern
- element :clone_url, 'text_field_tag :clone_url' # rubocop:disable QA/ElementWithPattern
+ element :clone_dropdown_content
+ element :clone_url_content
end
end
@@ -28,7 +28,7 @@ module QA
end
def repository_location
- Git::Location.new(find('#clone_url').value)
+ Git::Location.new(find_element(:clone_url_content).text)
end
private
@@ -37,7 +37,7 @@ module QA
wait_until(reload: false) do
click_element :clone_dropdown
- page.within('.clone-options-dropdown') do
+ within_element(:clone_dropdown_content) do
click_link(kind)
end
diff --git a/qa/qa/page/component/namespace_select.rb b/qa/qa/page/component/namespace_select.rb
index 4dbcb39ced6..9b483162f1b 100644
--- a/qa/qa/page/component/namespace_select.rb
+++ b/qa/qa/page/component/namespace_select.rb
@@ -9,7 +9,7 @@ module QA
def self.included(base)
super
- base.view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
+ base.view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select_deprecated.vue" do
element :namespaces_list
element :namespaces_list_groups
element :namespaces_list_item
@@ -20,8 +20,10 @@ module QA
def select_namespace(item)
click_element :namespaces_list
+ wait_for_requests
+
within_element(:namespaces_list) do
- find_element(:namespaces_list_search).fill_in(with: item)
+ fill_element(:namespaces_list_search, item)
wait_for_requests
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index 9e558844469..7a7329e6110 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -11,9 +11,12 @@ module QA
base.view 'app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue' do
element :wiki_title_textbox
- element :wiki_content_textarea
element :wiki_message_textbox
element :wiki_submit_button
+ end
+
+ base.view 'app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue' do
+ element :markdown_editor_form_field
element :editing_mode_button
end
@@ -27,7 +30,7 @@ module QA
end
def set_content(content)
- fill_element(:wiki_content_textarea, content)
+ fill_element(:markdown_editor_form_field, content)
end
def set_message(message)
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index b057a27fa3e..a30d489e6ff 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -13,10 +13,6 @@ module QA
element :group_id_content
end
- view 'app/assets/javascripts/groups/constants.js' do
- element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern
- end
-
view 'app/views/shared/members/_access_request_links.html.haml' do
element :leave_group_link
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index aaf10e12e82..2f618224a73 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -14,7 +14,7 @@ module QA
view 'app/views/layouts/header/_default.html.haml' do
element :navbar, required: true
element :canary_badge_link
- element :user_avatar, required: !QA::Runtime::Env.mobile_layout?
+ element :user_avatar_content, required: !QA::Runtime::Env.mobile_layout?
element :user_menu, required: !QA::Runtime::Env.mobile_layout?
element :stop_impersonation_link
element :issues_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
@@ -184,11 +184,11 @@ module QA
end
def has_personal_area?(wait: Capybara.default_max_wait_time)
- has_element?(:user_avatar, wait: wait)
+ has_element?(:user_avatar_content, wait: wait)
end
def has_no_personal_area?(wait: Capybara.default_max_wait_time)
- has_no_element?(:user_avatar, wait: wait)
+ has_no_element?(:user_avatar_content, wait: wait)
end
def has_admin_area_link?(wait: Capybara.default_max_wait_time)
@@ -227,7 +227,7 @@ module QA
def within_user_menu(&block)
within_top_menu do
- click_element :user_avatar unless has_element?(:user_profile_link, wait: 1)
+ click_element :user_avatar_content unless has_element?(:user_profile_link, wait: 1)
within_element(:user_menu, &block)
end
diff --git a/qa/qa/page/main/terms.rb b/qa/qa/page/main/terms.rb
index 024510c33cf..24f6b03549b 100644
--- a/qa/qa/page/main/terms.rb
+++ b/qa/qa/page/main/terms.rb
@@ -5,7 +5,7 @@ module QA
module Main
class Terms < Page::Base
view 'app/views/layouts/terms.html.haml' do
- element :user_avatar, required: true
+ element :user_avatar_content, required: true
end
view 'app/assets/javascripts/terms/components/app.vue' do
diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb
index 79eb4f2d51b..909b37943ff 100644
--- a/qa/qa/page/merge_request/new.rb
+++ b/qa/qa/page/merge_request/new.rb
@@ -38,7 +38,6 @@ module QA
def click_diffs_tab
click_element(:diffs_tab)
- click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
end
def has_file?(file_name)
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 2587241ed18..e1add9ad434 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -108,6 +108,7 @@ module QA
view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do
element :suggestion_button
+ element :dismiss_suggestion_popover_button
end
view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do
@@ -191,8 +192,11 @@ module QA
wait_until(sleep_interval: 5) do
has_css?('a[data-linenumber="1"]')
end
+
all_elements(:new_diff_line_link, minimum: 1).first.hover
click_element(:diff_comment_button)
+ click_element(:dismiss_suggestion_popover_button) if has_element?(:dismiss_suggestion_popover_button, wait: 1)
+
fill_element(:reply_field, text)
end
@@ -208,7 +212,6 @@ module QA
def click_diffs_tab
click_element(:diffs_tab)
- click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
end
def click_pipeline_link
diff --git a/qa/qa/page/project/secure/configuration_form.rb b/qa/qa/page/project/secure/configuration_form.rb
index fa1fad44273..20999f7c92a 100644
--- a/qa/qa/page/project/secure/configuration_form.rb
+++ b/qa/qa/page/project/secure/configuration_form.rb
@@ -9,6 +9,7 @@ module QA
include QA::Page::Settings::Common
view 'app/assets/javascripts/security_configuration/components/app.vue' do
+ element :security_configuration_container
element :security_configuration_history_link
end
@@ -17,6 +18,7 @@ module QA
element :sast_status, "`${feature.type}_status`" # rubocop:disable QA/ElementWithPattern
element :sast_enable_button, "`${feature.type}_enable_button`" # rubocop:disable QA/ElementWithPattern
element :dependency_scanning_mr_button, "`${feature.type}_mr_button`" # rubocop:disable QA/ElementWithPattern
+ element :license_scanning_status, "`${feature.type}_status`" # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/security_configuration/components/auto_dev_ops_alert.vue' do
@@ -67,6 +69,18 @@ module QA
end
end
+ def has_license_compliance_status?(status_text)
+ within_element(:license_scanning_status) do
+ has_text?(status_text)
+ end
+ end
+
+ def has_no_license_compliance_status?(status_text)
+ within_element(:license_scanning_status) do
+ has_no_text?(status_text)
+ end
+ end
+
def has_auto_devops_container?
has_element?(:autodevops_container)
end
@@ -80,6 +94,18 @@ module QA
has_text?('Quickly enable all continuous testing and compliance tools by enabling Auto DevOps')
end
end
+
+ def go_to_compliance_tab
+ go_to_tab('Compliance')
+ end
+
+ private
+
+ def go_to_tab(name)
+ within_element(:security_configuration_container) do
+ find('.nav-item', text: name).click
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/default_branch.rb b/qa/qa/page/project/settings/default_branch.rb
index cc28b37b88f..575f9006c84 100644
--- a/qa/qa/page/project/settings/default_branch.rb
+++ b/qa/qa/page/project/settings/default_branch.rb
@@ -5,16 +5,22 @@ module QA
module Project
module Settings
class DefaultBranch < Page::Base
- include Page::Component::Select2
-
view 'app/views/projects/default_branch/_show.html.haml' do
element :save_changes_button
+ end
+
+ view 'app/assets/javascripts/projects/settings/components/default_branch_selector.vue' do
element :default_branch_dropdown
end
+ view 'app/assets/javascripts/ref/components/ref_selector.vue' do
+ element :ref_selector_searchbox
+ end
+
def set_default_branch(branch)
- find('.select2-chosen').click
- search_and_select(branch)
+ click_button :default_branch_dropdown
+ fill_in :ref_selector_searchbox, with: branch
+ click_button branch
end
def click_save_changes_button
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index 7eeeeefdae6..f55faff19e7 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -62,7 +62,7 @@ module QA
end
def authentication_method=(value)
- unless %w[Password None SSH\ public\ key].include?(value)
+ unless ['Password', 'None', 'SSH public key'].include?(value)
raise ArgumentError, "Authentication method must be 'SSH public key', 'Password', or 'None'"
end
diff --git a/qa/qa/page/project/settings/services/jira.rb b/qa/qa/page/project/settings/services/jira.rb
index 827508e488c..41034bbd897 100644
--- a/qa/qa/page/project/settings/services/jira.rb
+++ b/qa/qa/page/project/settings/services/jira.rb
@@ -41,10 +41,7 @@ module QA
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
+ click_save_changes_and_wait
end
def enable_jira_issues
@@ -55,6 +52,13 @@ module QA
fill_element(:service_jira_project_key_field, key)
end
+ def click_save_changes_and_wait
+ 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
+
private
def set_jira_server_url(url)
@@ -94,3 +98,5 @@ module QA
end
end
end
+
+QA::Page::Project::Settings::Services::Jira.prepend_mod_with('Page::Project::Settings::Services::Jira', namespace: QA)
diff --git a/qa/qa/page/project/tag/new.rb b/qa/qa/page/project/tag/new.rb
index dc59c07ec98..50e11acd94a 100644
--- a/qa/qa/page/project/tag/new.rb
+++ b/qa/qa/page/project/tag/new.rb
@@ -8,17 +8,9 @@ module QA
view 'app/views/projects/tags/new.html.haml' do
element :tag_name_field
element :tag_message_field
- element :release_notes_field
element :create_tag_button
end
- view 'app/views/shared/_zen.html.haml' do
- # This partial adds the `release_notes_field` selector passed from 'app/views/projects/tags/new.html.haml'
- # The checks below ensure that required lines are not removed without updating this page object
- element :_, "qa_selector = local_assigns.fetch(:qa_selector, '')" # rubocop:disable QA/ElementWithPattern
- element :_, "text_area_tag attr, current_text, data: { qa_selector: qa_selector }" # rubocop:disable QA/ElementWithPattern
- end
-
def fill_tag_name(text)
fill_element(:tag_name_field, text)
end
@@ -27,10 +19,6 @@ module QA
fill_element(:tag_message_field, text)
end
- def fill_release_notes(text)
- fill_element(:release_notes_field, text)
- end
-
def click_create_tag_button
click_element :create_tag_button
end
diff --git a/qa/qa/resource/issuable.rb b/qa/qa/resource/issuable.rb
new file mode 100644
index 00000000000..6ebdaac8298
--- /dev/null
+++ b/qa/qa/resource/issuable.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Issuable < Base
+ # Commentes (notes) path
+ #
+ # @return [String]
+ def api_comments_path
+ "#{api_get_path}/notes"
+ end
+
+ # Get issue comments
+ #
+ # @return [Array]
+ def comments(auto_paginate: false, attempts: 0)
+ return parse_body(api_get_from(api_comments_path)) unless auto_paginate
+
+ auto_paginated_response(
+ Runtime::API::Request.new(api_client, api_comments_path, per_page: '100').url,
+ attempts: attempts
+ )
+ end
+
+ # Create a new comment
+ #
+ # @param [String] body
+ # @param [Boolean] confidential
+ # @return [Hash]
+ def add_comment(body:, confidential: false)
+ api_post_to(api_comments_path, body: body, confidential: confidential)
+ end
+
+ # Issue label events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def label_events(auto_paginate: false, attempts: 0)
+ events("label", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Issue state events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def state_events(auto_paginate: false, attempts: 0)
+ events("state", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ # Issue milestone events
+ #
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def milestone_events(auto_paginate: false, attempts: 0)
+ events("milestone", auto_paginate: auto_paginate, attempts: attempts)
+ end
+
+ private
+
+ # Issue events
+ #
+ # @param [String] name event name
+ # @param [Boolean] auto_paginate
+ # @param [Integer] attempts
+ # @return [Array<Hash>]
+ def events(name, auto_paginate:, attempts:)
+ return parse_body(api_get_from("#{api_get_path}/resource_#{name}_events")) unless auto_paginate
+
+ auto_paginated_response(
+ Runtime::API::Request.new(api_client, "#{api_get_path}/resource_#{name}_events", per_page: '100').url,
+ attempts: attempts
+ )
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index 1e38de97c1e..2e18e1d0323 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -2,7 +2,7 @@
module QA
module Resource
- class Issue < Base
+ class Issue < Issuable
attr_writer :milestone, :template, :weight
attribute :project do
@@ -53,10 +53,6 @@ module QA
"/projects/#{project.id}/issues/#{iid}"
end
- def api_comments_path
- "#{api_get_path}/notes"
- end
-
def api_post_body
{
assignee_ids: assignee_ids,
@@ -83,27 +79,6 @@ module QA
QA::Runtime::Logger.debug("Successfully updated issue assignees to #{assignee_ids}")
end
- # Get issue comments
- #
- # @return [Array]
- def comments(auto_paginate: false, attempts: 0)
- return parse_body(api_get_from(api_comments_path)) unless auto_paginate
-
- auto_paginated_response(
- Runtime::API::Request.new(api_client, api_comments_path, per_page: '100').url,
- attempts: attempts
- )
- end
-
- # Create a new comment
- #
- # @param [String] body
- # @param [Boolean] confidential
- # @return [Hash]
- def add_comment(body:, confidential: false)
- api_post_to(api_comments_path, body: body, confidential: confidential)
- end
-
protected
# Return subset of fields for comparing issues
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index 0a92553690f..5d6dc12ac9c 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -2,7 +2,7 @@
module QA
module Resource
- class MergeRequest < Base
+ class MergeRequest < Issuable
attr_accessor :approval_rules,
:source_branch,
:target_new_branch,
@@ -130,10 +130,6 @@ module QA
}
end
- def api_comments_path
- "#{api_get_path}/notes"
- end
-
def merge_via_api!
Support::Waiter.wait_until(sleep_interval: 1) do
QA::Runtime::Logger.debug("Waiting until merge request with id '#{iid}' can be merged")
@@ -166,26 +162,6 @@ module QA
current_url
end
- # Get MR comments
- #
- # @return [Array]
- def comments(auto_paginate: false, attempts: 0)
- return parse_body(api_get_from(api_comments_path)) unless auto_paginate
-
- auto_paginated_response(
- Runtime::API::Request.new(api_client, api_comments_path, per_page: '100').url,
- attempts: attempts
- )
- end
-
- # Add mr comment
- #
- # @param [String] body
- # @return [Hash]
- def add_comment(body)
- api_post_to(api_comments_path, body: body)
- end
-
# Return subset of fields for comparing merge requests
#
# @return [Hash]
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 13c6f285259..e5df95f1fa5 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -226,7 +226,11 @@ module QA
end
def api_housekeeping_path
- "/projects/#{id}/housekeeping"
+ "#{api_get_path}/housekeeping"
+ end
+
+ def api_protected_branches_path
+ "#{api_get_path}/protected_branches"
end
def api_post_body
@@ -324,8 +328,11 @@ module QA
result = parse_body(response)
if result[:import_status] == "failed"
- Runtime::Logger.error("Import failed: #{result[:import_error]}")
- Runtime::Logger.error("Failed relations: #{result[:failed_relations]}")
+ Runtime::Logger.error(<<~ERR)
+ Import of project '#{full_path}' failed!
+ error: '#{result[:import_error]}'
+ failed relations: '#{result[:failed_relations]}'
+ ERR
end
result
@@ -420,7 +427,7 @@ module QA
end
def wikis
- response = get(request_url(api_wikis_path))
+ response = api_get_from(api_wikis_path)
parse_body(response)
end
@@ -437,6 +444,11 @@ module QA
api_post_to(api_releases_path, tag_name: tag, ref: ref, **params)
end
+ def protected_branches
+ response = api_get_from(api_protected_branches_path)
+ parse_body(response)
+ end
+
# Uses the API to wait until a pull mirroring update is successful (pull mirroring is treated as an import)
def wait_for_pull_mirroring
mirror_succeeded = Support::Retrier.retry_until(
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index b9dbd2a6131..9ba9723f0cc 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -3,6 +3,8 @@
module QA
module Resource
class ProjectImportedFromGithub < Resource::Project
+ attr_accessor :issue_events_import, :full_notes_import, :attachments_import
+
attribute :github_repo_id do
github_client.repository(github_repository_path).id
end
@@ -51,7 +53,12 @@ module QA
new_name: name,
target_namespace: @personal_namespace || group.full_path,
personal_access_token: github_personal_access_token,
- ci_cd_only: false
+ ci_cd_only: false,
+ optional_stages: {
+ single_endpoint_issue_events_import: issue_events_import,
+ single_endpoint_notes_import: full_notes_import,
+ attachments_import: attachments_import
+ }
}
end
diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb
index 55ad6edb3c1..7b6a3d296c4 100644
--- a/qa/qa/resource/protected_branch.rb
+++ b/qa/qa/resource/protected_branch.rb
@@ -22,9 +22,7 @@ module QA
commit.branch = branch_name
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "new_file-#{SecureRandom.hex(8)}.md", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "new_file-#{SecureRandom.hex(8)}.md", content: 'new file' }])
end
end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index a974446b3cb..71a5e1c8930 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -44,7 +44,7 @@ module QA
alias_method :ldap_username, :username
def password
- @password ||= SecureRandom.hex(8)
+ @password ||= "Pa$$w0rd"
end
alias_method :ldap_password, :password
diff --git a/qa/qa/resource/wiki/group_page.rb b/qa/qa/resource/wiki/group_page.rb
index 1e40426a389..69ad83ea10a 100644
--- a/qa/qa/resource/wiki/group_page.rb
+++ b/qa/qa/resource/wiki/group_page.rb
@@ -23,6 +23,7 @@ module QA
end
def initialize
+ # Note: A Group Wiki Home page requires title = 'Home', otherwise when going /-/wikis, Rails will render a new page creation form.
@title = 'Home'
@content = 'This wiki page is created via API'
end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index b1a912ac43e..782ba1cf2fa 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -29,6 +29,15 @@ module QA
@gitlab_url ||= ENV["QA_GITLAB_URL"] || "http://127.0.0.1:3000" # default to GDK
end
+ # Retrieves the value of the gitlab_canary cookie if set or returns an empty hash.
+ #
+ # @return [Hash]
+ def canary_cookie
+ canary = ENV['QA_COOKIES']&.scan(/gitlab_canary=(true|false)/)&.dig(0, 0)
+
+ canary ? { gitlab_canary: canary } : {}
+ end
+
def additional_repository_storage
ENV['QA_ADDITIONAL_REPOSITORY_STORAGE']
end
diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb
deleted file mode 100644
index b4098619e4e..00000000000
--- a/qa/qa/scenario/test/instance.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- # This class exists for back-compatibility so that gitlab-qa can continue
- # to call Test::Instance instead of Test::Instance::All until at least
- # the current latest GitLab version has the Test::Instance::All class.
- # As of Aug, 22nd 2018. Only GitLab >= 11.3 has this class.
- module Instance
- include Bootable
-
- def self.perform(*args)
- self.tap do |scenario|
- yield scenario if block_given?
- break scenario.do_perform(*args)
- end
- end
-
- def self.do_perform(address, *rspec_options)
- Runtime::Scenario.define(:gitlab_address, address)
-
- ##
- # Perform before hooks, which are different for CE and EE
- #
- Runtime::Release.perform_before_hooks
-
- Specs::Runner.perform do |specs|
- specs.tty = true
- specs.options = rspec_options if rspec_options.any?
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/scenario/test/integration/github.rb b/qa/qa/scenario/test/integration/github.rb
deleted file mode 100644
index 857a1f00bd5..00000000000
--- a/qa/qa/scenario/test/integration/github.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- module Integration
- class Github < Test::Instance::All
- tags :github
-
- def perform(address, *rspec_options)
- # This test suite requires a GitHub personal access token
- Runtime::Env.require_github_access_token!
-
- super
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
index 7d3916641aa..bf95a215c8e 100644
--- a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
@@ -40,9 +40,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.not_to raise_error
end
diff --git a/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
new file mode 100644
index 00000000000..c3e41e9298b
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+module QA
+ # Spec uses real github.com, which means outage of github.com can actually block deployment
+ # Keep spec in reliable bucket but don't run in blocking pipelines
+ RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin, product_group: :import do
+ describe 'Project import', issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/353583' do
+ let!(:api_client) { Runtime::API::Client.as_admin }
+ let!(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } }
+ let!(:user) do
+ Resource::User.fabricate_via_api! do |resource|
+ resource.api_client = api_client
+ resource.hard_delete_on_api_removal = true
+ end
+ end
+
+ let(:imported_project) do
+ Resource::ProjectImportedFromGithub.fabricate_via_api! do |project|
+ project.name = 'imported-project'
+ project.group = group
+ project.github_personal_access_token = Runtime::Env.github_access_token
+ project.github_repository_path = 'gitlab-qa-github/import-test'
+ project.api_client = Runtime::API::Client.new(user: user)
+ project.issue_events_import = true
+ project.full_notes_import = true
+ end
+ end
+
+ before do
+ group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
+ end
+
+ after do
+ user.remove_via_api!
+ end
+
+ it 'imports Github repo via api', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do
+ imported_project.reload! # import the project
+
+ expect { imported_project.project_import_status[:import_status] }.to eventually_eq('finished')
+ .within(max_duration: 240, sleep_interval: 1)
+
+ aggregate_failures do
+ verify_status_data
+ verify_repository_import
+ verify_protected_branches_import
+ verify_commits_import
+ verify_labels_import
+ verify_issues_import
+ verify_milestones_import
+ verify_wikis_import
+ verify_merge_requests_import
+ end
+ end
+
+ def verify_status_data
+ stats = imported_project.project_import_status.dig(:stats, :imported)
+ expect(stats).to include(
+ issue: 1,
+ label: 9,
+ milestone: 1,
+ note: 3,
+ pull_request: 1,
+ pull_request_review: 1,
+ diff_note: 1,
+ release: 1
+ )
+ end
+
+ def verify_repository_import
+ expect(imported_project.reload!.description).to eq('Project for github import test')
+ expect(imported_project.api_response[:import_error]).to be_nil
+ end
+
+ def verify_protected_branches_import
+ branches = imported_project.protected_branches.map do |branch|
+ branch.slice(:name, :allow_force_push, :code_owner_approval_required)
+ end
+ expect(branches.first).to include(
+ {
+ name: 'main'
+ # TODO: Add validation once https://gitlab.com/groups/gitlab-org/-/epics/8585 is closed
+ # At the moment both options are always set to false regardless of state in github
+ # allow_force_push: true,
+ # code_owner_approval_required: true
+ }
+ )
+ end
+
+ def verify_commits_import
+ expect(imported_project.commits.length).to eq(2)
+ end
+
+ def verify_labels_import
+ labels = imported_project.labels.map { |label| label.slice(:name, :color) }
+
+ expect(labels).to include(
+ { name: 'bug', color: '#d73a4a' },
+ { name: 'documentation', color: '#0075ca' },
+ { name: 'duplicate', color: '#cfd3d7' },
+ { name: 'enhancement', color: '#a2eeef' },
+ { name: 'good first issue', color: '#7057ff' },
+ { name: 'help wanted', color: '#008672' },
+ { name: 'invalid', color: '#e4e669' },
+ { name: 'question', color: '#d876e3' },
+ { name: 'wontfix', color: '#ffffff' }
+ )
+ end
+
+ def verify_issues_import
+ issues = imported_project.issues
+
+ expect(issues.length).to eq(1)
+ expect(issues.first).to include(
+ title: 'Test issue',
+ description: "*Created by: gitlab-qa-github*\n\nTest issue description",
+ labels: ['good first issue', 'help wanted', 'question'],
+ user_notes_count: 2
+ )
+ end
+
+ def verify_milestones_import
+ milestones = imported_project.milestones
+
+ expect(milestones.length).to eq(1)
+ expect(milestones.first).to include(title: '0.0.1', description: nil, state: 'active')
+ end
+
+ def verify_wikis_import
+ wikis = imported_project.wikis
+
+ expect(wikis.length).to eq(1)
+ expect(wikis.first).to include(title: 'Home', format: 'markdown')
+ end
+
+ def verify_merge_requests_import
+ merge_requests = imported_project.merge_requests
+ merge_request = Resource::MergeRequest.init do |mr|
+ mr.project = imported_project
+ mr.iid = merge_requests.first[:iid]
+ mr.api_client = api_client
+ end.reload!
+ mr_comments = merge_request.comments.map { |comment| comment[:body] }
+
+ expect(merge_requests.length).to eq(1)
+ expect(merge_request.api_resource).to include(
+ title: 'Test pull request',
+ state: 'opened',
+ target_branch: 'main',
+ source_branch: 'gitlab-qa-github-patch-1',
+ labels: %w[documentation],
+ description: <<~DSC.strip
+ *Created by: gitlab-qa-github*\n\nTest pull request body
+ DSC
+ )
+ expect(mr_comments).to match_array(
+ [
+ "*Created by: gitlab-qa-github*\n\n**Review:** Commented\n\nGood but needs some improvement",
+ "*Created by: gitlab-qa-github*\n\n```suggestion:-0+0\nProject for GitHub import test to GitLab\r\n```",
+ "*Created by: gitlab-qa-github*\n\nSome test PR comment"
+ ]
+ )
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
new file mode 100644
index 00000000000..5acf15dd2b4
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
@@ -0,0 +1,620 @@
+# frozen_string_literal: true
+
+require "etc"
+
+# Lifesize project import test executed from https://gitlab.com/gitlab-org/manage/import/import-metrics
+
+# rubocop:disable Rails/Pluck
+module QA
+ RSpec.describe 'Manage', :github, requires_admin: 'creates users', only: { job: 'large-github-import' } do
+ describe 'Project import', product_group: :import do # rubocop:disable RSpec/MultipleMemoizedHelpers
+ let(:github_repo) { ENV['QA_LARGE_IMPORT_REPO'] || 'rspec/rspec-core' }
+ let(:import_max_duration) { ENV['QA_LARGE_IMPORT_DURATION']&.to_i || 7200 }
+ let(:logger) { Runtime::Logger.logger }
+ let(:differ) { RSpec::Support::Differ.new(color: true) }
+ let(:gitlab_address) { QA::Runtime::Scenario.gitlab_address.chomp("/") }
+ let(:dummy_url) { "https://example.com" }
+ let(:api_request_params) { { auto_paginate: true, attempts: 2 } }
+
+ let(:created_by_pattern) { /\*Created by: \S+\*\n\n/ }
+ let(:suggestion_pattern) { /suggestion:-\d+\+\d+/ }
+ let(:gh_link_pattern) { %r{https://github.com/#{github_repo}/(issues|pull)} }
+ let(:gl_link_pattern) { %r{#{gitlab_address}/#{imported_project.path_with_namespace}/-/(issues|merge_requests)} }
+ # rubocop:disable Lint/MixedRegexpCaptureTypes
+ let(:event_pattern) do
+ Regexp.union(
+ [
+ /(?<event>(un)?assigned)( to)? @\S+/,
+ /(?<event>mentioned) in (issue|merge request) [!#]\d+/,
+ /(?<event>changed title) from \*\*.*\*\* to \*\*.*\*\*/,
+ /(?<event>requested review) from @\w+/,
+ /\*(?<event>Merged) by:/,
+ /\*\*(Review):\*\*/
+ ]
+ )
+ end
+ # rubocop:enable Lint/MixedRegexpCaptureTypes
+
+ # mapping from gitlab to github names
+ let(:event_mapping) do
+ {
+ "label_add" => "labeled",
+ "label_remove" => "unlabeled",
+ "milestone_add" => "milestoned",
+ "milestone_remove" => "demilestoned",
+ "assigned" => "assigned",
+ "unassigned" => "unassigned",
+ "changed title" => "renamed",
+ "requested review" => "review_requested",
+ "Merged" => "merged"
+ }
+ end
+
+ # github events that are not migrated or are not correctly mapable in gitlab
+ let(:unsupported_events) do
+ [
+ "head_ref_deleted",
+ "head_ref_force_pushed",
+ "head_ref_restored",
+ "base_ref_force_pushed",
+ "base_ref_changed",
+ "review_request_removed",
+ "review_dismissed",
+ "auto_squash_enabled",
+ "auto_merge_disabled",
+ "comment_deleted",
+ "convert_to_draft",
+ "ready_for_review",
+ "subscribed",
+ "unsubscribed",
+ "transferred",
+ "locked",
+ "unlocked",
+ # mentions are supported but they can be reported differently on gitlab's side
+ # for example mention of issue creation in pr will be reported in the issue on gitlab side
+ # or referenced in github will still create a 'mentioned in' comment in gitlab
+ "referenced",
+ "mentioned"
+ ]
+ end
+
+ let(:api_client) { Runtime::API::Client.as_admin }
+
+ let(:user) do
+ Resource::User.fabricate_via_api! do |resource|
+ resource.api_client = api_client
+ end
+ end
+
+ let(:github_client) do
+ Octokit::Client.new(
+ access_token: ENV['QA_LARGE_IMPORT_GH_TOKEN'] || Runtime::Env.github_access_token,
+ auto_paginate: true,
+ middleware: Faraday::RackBuilder.new do |builder|
+ builder.use(Faraday::Retry::Middleware, exceptions: [Octokit::InternalServerError, Octokit::ServerError])
+ end
+ )
+ end
+
+ let(:gh_repo) { github_client.repository(github_repo) }
+
+ let(:gh_branches) do
+ logger.info("= Fetching branches =")
+ github_client.branches(github_repo).map(&:name)
+ end
+
+ let(:gh_commits) do
+ logger.info("= Fetching commits =")
+ github_client.commits(github_repo).map(&:sha)
+ end
+
+ let(:gh_labels) do
+ logger.info("= Fetching labels =")
+ github_client.labels(github_repo).map { |label| { name: label.name, color: "##{label.color}" } }
+ end
+
+ let(:gh_milestones) do
+ logger.info("= Fetching milestones =")
+ github_client
+ .list_milestones(github_repo, state: 'all')
+ .map { |ms| { title: ms.title, description: ms.description } }
+ end
+
+ let(:gh_prs) do
+ gh_all_issues.select(&:pull_request).each_with_object({}) do |pr, hash|
+ id = pr.number
+ hash[id] = {
+ url: pr.html_url,
+ title: pr.title,
+ body: pr.body || '',
+ comments: [*gh_pr_comments[id], *gh_issue_comments[id]].compact,
+ events: gh_pr_events[id].reject { |event| unsupported_events.include?(event) }
+ }
+ end
+ end
+
+ let(:gh_issues) do
+ gh_all_issues.reject(&:pull_request).each_with_object({}) do |issue, hash|
+ id = issue.number
+ hash[id] = {
+ url: issue.html_url,
+ title: issue.title,
+ body: issue.body || '',
+ comments: gh_issue_comments[id],
+ events: gh_issue_events[id].reject { |event| unsupported_events.include?(event) }
+ }
+ end
+ end
+
+ let(:gh_all_issues) do
+ logger.info("= Fetching issues and prs =")
+ github_client.list_issues(github_repo, state: 'all')
+ end
+
+ let(:gh_all_events) do
+ logger.info("- Fetching issue and pr events -")
+ github_client.repository_issue_events(github_repo).map do |event|
+ { name: event[:event], **(event[:issue] || {}) } # some events don't have issue object at all
+ end
+ end
+
+ let(:gh_issue_events) do
+ gh_all_events.each_with_object(Hash.new { |h, k| h[k] = [] }) do |event, hash|
+ next if event[:pull_request] || !event[:number]
+
+ hash[event[:number]] << event[:name]
+ end
+ end
+
+ let(:gh_pr_events) do
+ gh_all_events.each_with_object(Hash.new { |h, k| h[k] = [] }) do |event, hash|
+ next unless event[:pull_request]
+
+ hash[event[:number]] << event[:name]
+ end
+ end
+
+ let(:gh_issue_comments) do
+ logger.info("- Fetching issue comments -")
+ github_client.issues_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
+ hash[id_from_url(c.html_url)] << c.body&.gsub(gh_link_pattern, dummy_url)
+ end
+ end
+
+ let(:gh_pr_comments) do
+ logger.info("- Fetching pr comments -")
+ github_client.pull_requests_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
+ hash[id_from_url(c.html_url)] << c.body
+ # some suggestions can contain extra whitespaces which gitlab will remove
+ &.gsub(/suggestion\s+\r/, "suggestion\r")
+ &.gsub(gh_link_pattern, dummy_url)
+ end
+ end
+
+ let(:imported_project) do
+ Resource::ProjectImportedFromGithub.fabricate_via_api! do |project|
+ project.add_name_uuid = false
+ project.name = 'imported-project'
+ project.github_personal_access_token = Runtime::Env.github_access_token
+ project.github_repository_path = github_repo
+ project.personal_namespace = user.username
+ project.api_client = Runtime::API::Client.new(user: user)
+ project.issue_events_import = true
+ project.full_notes_import = true
+ end
+ end
+
+ after do |example|
+ next unless defined?(@import_time)
+
+ # save data for comparison notification creation
+ save_json(
+ "data",
+ {
+ importer: :github,
+ import_time: @import_time,
+ errors: imported_project.project_import_status[:failed_relations],
+ reported_stats: @stats,
+ source: {
+ name: "GitHub",
+ project_name: github_repo,
+ address: "https://github.com",
+ data: {
+ branches: gh_branches.length,
+ commits: gh_commits.length,
+ labels: gh_labels.length,
+ milestones: gh_milestones.length,
+ mrs: gh_prs.length,
+ mr_comments: gh_prs.sum { |_k, v| v[:comments].length },
+ mr_events: gh_prs.sum { |_k, v| v[:events].length },
+ issues: gh_issues.length,
+ issue_comments: gh_issues.sum { |_k, v| v[:comments].length },
+ issue_events: gh_issues.sum { |_k, v| v[:events].length }
+ }
+ },
+ target: {
+ name: "GitLab",
+ project_name: imported_project.path_with_namespace,
+ address: gitlab_address,
+ data: {
+ branches: gl_branches.length,
+ commits: gl_commits.length,
+ labels: gl_labels.length,
+ milestones: gl_milestones.length,
+ mrs: mrs.length,
+ mr_comments: mrs.sum { |_k, v| v[:comments].length },
+ mr_events: mrs.sum { |_k, v| v[:events].length },
+ issues: gl_issues.length,
+ issue_comments: gl_issues.sum { |_k, v| v[:comments].length },
+ issue_events: gl_issues.sum { |_k, v| v[:events].length }
+ }
+ },
+ not_imported: {
+ mrs: @mr_diff,
+ issues: @issue_diff
+ }
+ }
+ )
+ end
+
+ it(
+ 'imports large Github repo via api',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347668'
+ ) do
+ start = Time.now
+
+ # trigger import and log project paths
+ logger.info("== Triggering import of project '#{github_repo}' in to '#{imported_project.reload!.full_path}' ==")
+
+ # fetch all objects right after import has started
+ fetch_github_objects
+
+ import_status = lambda do
+ imported_project.project_import_status.yield_self do |status|
+ @stats = status.dig(:stats, :imported)
+
+ # fail fast if import explicitly failed
+ raise "Import of '#{imported_project.full_path}' failed!" if status[:import_status] == 'failed'
+
+ status[:import_status]
+ end
+ end
+
+ logger.info("== Waiting for import to be finished ==")
+ expect(import_status).to eventually_eq('finished').within(max_duration: import_max_duration, sleep_interval: 30)
+
+ @import_time = Time.now - start
+
+ aggregate_failures do
+ verify_repository_import
+ verify_labels_import
+ verify_milestones_import
+ verify_merge_requests_import
+ verify_issues_import
+ end
+ end
+
+ # Persist all objects from repository being imported
+ #
+ # @return [void]
+ def fetch_github_objects
+ logger.info("== Fetching github repo objects ==")
+
+ gh_repo
+ gh_branches
+ gh_commits
+ gh_labels
+ gh_milestones
+ gh_prs
+ gh_issues
+ end
+
+ # Verify repository imported correctly
+ #
+ # @return [void]
+ def verify_repository_import
+ logger.info("== Verifying repository import ==")
+ expect(imported_project.description).to eq(gh_repo.description)
+ # check via include, importer creates more branches
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/332711
+ expect(gl_branches).to include(*gh_branches)
+ expect(gl_commits).to match_array(gh_commits)
+ end
+
+ # Verify imported labels
+ #
+ # @return [void]
+ def verify_labels_import
+ logger.info("== Verifying label import ==")
+ # check via include, additional labels can be inherited from parent group
+ expect(gl_labels).to include(*gh_labels)
+ end
+
+ # Verify milestones import
+ #
+ # @return [void]
+ def verify_milestones_import
+ logger.info("== Verifying milestones import ==")
+ expect(gl_milestones).to match_array(gh_milestones)
+ end
+
+ # Verify imported merge requests and mr issues
+ #
+ # @return [void]
+ def verify_merge_requests_import
+ logger.info("== Verifying merge request import ==")
+ @mr_diff = verify_mrs_or_issues('mr')
+ end
+
+ # Verify imported issues and issue comments
+ #
+ # @return [void]
+ def verify_issues_import
+ logger.info("== Verifying issue import ==")
+ @issue_diff = verify_mrs_or_issues('issue')
+ end
+
+ private
+
+ # Verify imported mrs or issues and return missing items
+ #
+ # @param [String] type verification object, 'mrs' or 'issues'
+ # @return [Hash]
+ def verify_mrs_or_issues(type)
+ # Compare length to have easy to read overview how many objects are missing
+ #
+ expected = type == 'mr' ? mrs : gl_issues
+ actual = type == 'mr' ? gh_prs : gh_issues
+ count_msg = "Expected to contain same amount of #{type}s. Gitlab: #{expected.length}, Github: #{actual.length}"
+ expect(expected.length).to eq(actual.length), count_msg
+
+ missing_objects = (actual.keys - expected.keys).map { |it| actual[it].slice(:title, :url) }
+ missing_content = verify_comments_and_events(type, actual, expected)
+
+ {
+ "#{type}s": missing_objects.empty? ? nil : missing_objects,
+ "#{type}_content": missing_content.empty? ? nil : missing_content
+ }.compact
+ end
+
+ # Verify imported comments and events
+ #
+ # @param [String] type verification object, 'mrs' or 'issues'
+ # @param [Hash] actual
+ # @param [Hash] expected
+ # @return [Hash]
+ def verify_comments_and_events(type, actual, expected)
+ actual.each_with_object([]) do |(key, actual_item), missing_content|
+ expected_item = expected[key]
+ title = actual_item[:title]
+ msg = "expected #{type} with iid '#{key}' to have"
+
+ # Print title in the error message to see which object is missing
+ #
+ expect(expected_item).to be_truthy, "#{msg} been imported"
+ next unless expected_item
+
+ # Print difference in the description
+ #
+ expected_body = expected_item[:body]
+ actual_body = actual_item[:body]
+ body_msg = <<~MSG
+ #{msg} same description. diff:\n#{differ.diff(expected_body, actual_body)}
+ MSG
+ expect(expected_body).to eq(actual_body), body_msg
+
+ # Print amount difference first
+ #
+ expected_comments = expected_item[:comments]
+ actual_comments = actual_item[:comments]
+ comment_count_msg = <<~MSG
+ #{msg} same amount of comments. Gitlab: #{expected_comments.length}, Github: #{actual_comments.length}
+ MSG
+ expect(expected_comments.length).to eq(actual_comments.length), comment_count_msg
+ expect(expected_comments).to match_array(actual_comments)
+
+ expected_events = expected_item[:events]
+ actual_events = actual_item[:events]
+ event_count_msg = <<~MSG
+ #{msg} same amount of events. Gitlab: #{expected_events.length}, Github: #{actual_events.length}
+ MSG
+ expect(expected_events.length).to eq(actual_events.length), event_count_msg
+ expect(expected_events).to match_array(actual_events)
+
+ # Save missing comments and events
+ #
+ comment_diff = actual_comments - expected_comments
+ event_diff = actual_events - expected_events
+ next if comment_diff.empty? && event_diff.empty?
+
+ missing_content << {
+ title: title,
+ github_url: actual_item[:url],
+ gitlab_url: expected_item[:url],
+ missing_comments: comment_diff.empty? ? nil : comment_diff,
+ missing_events: event_diff.empty? ? nil : event_diff
+ }.compact
+ end
+ end
+
+ # Imported project branches
+ #
+ # @return [Array]
+ def gl_branches
+ @gl_branches ||= begin
+ logger.debug("= Fetching branches =")
+ imported_project.repository_branches(auto_paginate: true).map { |b| b[:name] }
+ end
+ end
+
+ # Imported project commits
+ #
+ # @return [Array]
+ def gl_commits
+ @gl_commits ||= begin
+ logger.debug("= Fetching commits =")
+ imported_project.commits(auto_paginate: true, attempts: 2).map { |c| c[:id] }
+ end
+ end
+
+ # Imported project labels
+ #
+ # @return [Array]
+ def gl_labels
+ @gl_labels ||= begin
+ logger.debug("= Fetching labels =")
+ imported_project.labels(auto_paginate: true).map { |label| label.slice(:name, :color) }
+ end
+ end
+
+ # Imported project milestones
+ #
+ # @return [<Type>] <description>
+ def gl_milestones
+ @gl_milestones ||= begin
+ logger.debug("= Fetching milestones =")
+ imported_project.milestones(auto_paginate: true).map { |ms| ms.slice(:title, :description) }
+ end
+ end
+
+ # Imported project merge requests
+ #
+ # @return [Hash]
+ def mrs
+ @mrs ||= begin
+ logger.debug("= Fetching merge requests =")
+ imported_mrs = imported_project.merge_requests(**api_request_params)
+
+ logger.debug("= Fetching merge request comments =")
+ Parallel.map(imported_mrs, in_threads: Etc.nprocessors) do |mr|
+ resource = Resource::MergeRequest.init do |resource|
+ resource.project = imported_project
+ resource.iid = mr[:iid]
+ resource.api_client = api_client
+ end
+
+ logger.debug("Fetching events and comments for mr '!#{mr[:iid]}'")
+ comments = resource.comments(**api_request_params)
+ label_events = resource.label_events(**api_request_params)
+ state_events = resource.state_events(**api_request_params)
+ milestone_events = resource.milestone_events(**api_request_params)
+
+ [mr[:iid], {
+ url: mr[:web_url],
+ title: mr[:title],
+ body: sanitize_description(mr[:description]) || '',
+ events: events(comments, label_events, state_events, milestone_events),
+ comments: non_event_comments(comments)
+ }]
+ end.to_h
+ end
+ end
+
+ # Imported project issues
+ #
+ # @return [Hash]
+ def gl_issues
+ @gl_issues ||= begin
+ logger.debug("= Fetching issues =")
+ imported_issues = imported_project.issues(**api_request_params)
+
+ logger.debug("= Fetching issue comments =")
+ Parallel.map(imported_issues, in_threads: Etc.nprocessors) do |issue|
+ resource = Resource::Issue.init do |issue_resource|
+ issue_resource.project = imported_project
+ issue_resource.iid = issue[:iid]
+ issue_resource.api_client = api_client
+ end
+
+ logger.debug("Fetching events and comments for issue '!#{issue[:iid]}'")
+ comments = resource.comments(**api_request_params)
+ label_events = resource.label_events(**api_request_params)
+ state_events = resource.state_events(**api_request_params)
+ milestone_events = resource.milestone_events(**api_request_params)
+
+ [issue[:iid], {
+ url: issue[:web_url],
+ title: issue[:title],
+ body: sanitize_description(issue[:description]) || '',
+ events: events(comments, label_events, state_events, milestone_events),
+ comments: non_event_comments(comments)
+ }]
+ end.to_h
+ end
+ end
+
+ # Filter out event comments
+ #
+ # @param [Array] comments
+ # @return [Array]
+ def non_event_comments(comments)
+ comments
+ .reject { |c| c[:system] || c[:body].match?(event_pattern) }
+ .map { |c| sanitize_comment(c[:body]) }
+ end
+
+ # Events
+ #
+ # @param [Array] comments
+ # @param [Array] label_events
+ # @param [Array] state_events
+ # @param [Array] milestone_events
+ # @return [Array]
+ def events(comments, label_events, state_events, milestone_events)
+ mapped_label_events = label_events.map { |event| event_mapping["label_#{event[:action]}"] }
+ mapped_milestone_events = milestone_events.map { |event| event_mapping["milestone_#{event[:action]}"] }
+ mapped_state_event = state_events.map { |event| event[:state] }
+ mapped_comment_events = comments.map do |c|
+ event_mapping[c[:body].match(event_pattern)&.named_captures&.fetch("event", nil)]
+ end
+
+ [*mapped_label_events, *mapped_milestone_events, *mapped_state_event, *mapped_comment_events].compact
+ end
+
+ # Normalize comments and make them directly comparable
+ #
+ # * remove created by prefixes
+ # * unify suggestion format
+ # * replace github and gitlab urls - some of the links to objects get transformed to gitlab entities, some don't,
+ # update all links to example.com for now
+ #
+ # @param [String] body
+ # @return [String]
+ def sanitize_comment(body)
+ body
+ .gsub(created_by_pattern, "")
+ .gsub(suggestion_pattern, "suggestion\r")
+ .gsub(gl_link_pattern, dummy_url)
+ .gsub(gh_link_pattern, dummy_url)
+ end
+
+ # Remove created by prefix from descripion
+ #
+ # @param [String] body
+ # @return [String]
+ def sanitize_description(body)
+ body&.gsub(created_by_pattern, "")
+ end
+
+ # Save json as file
+ #
+ # @param [String] name
+ # @param [Hash] json
+ # @return [void]
+ def save_json(name, json)
+ File.open("tmp/#{name}.json", "w") { |file| file.write(JSON.pretty_generate(json)) }
+ end
+
+ # Extract id number from web url of issue or pull request
+ #
+ # Some endpoints don't return object id as separate parameter so web url can be used as a workaround
+ #
+ # @param [String] url
+ # @return [Integer]
+ def id_from_url(url)
+ url.match(%r{(?<type>issues|pull)/(?<id>\d+)})&.named_captures&.fetch("id", nil).to_i
+ end
+ end
+ end
+end
+# rubocop:enable Rails/Pluck
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
deleted file mode 100644
index df34bf32421..00000000000
--- a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- # Spec uses real github.com, which means outage of github.com can actually block deployment
- # Keep spec in reliable bucket but don't run in blocking pipelines
- RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin do
- describe 'Project import', issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/353583' do
- let!(:api_client) { Runtime::API::Client.as_admin }
- let!(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } }
- let!(:user) do
- Resource::User.fabricate_via_api! do |resource|
- resource.api_client = api_client
- resource.hard_delete_on_api_removal = true
- end
- end
-
- let(:imported_project) do
- Resource::ProjectImportedFromGithub.fabricate_via_api! do |project|
- project.name = 'imported-project'
- project.group = group
- project.github_personal_access_token = Runtime::Env.github_access_token
- project.github_repository_path = 'gitlab-qa-github/import-test'
- project.api_client = api_client
- end
- end
-
- before do
- group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
- end
-
- after do
- user.remove_via_api!
- end
-
- it 'imports Github repo via api', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do
- imported_project.reload! # import the project
-
- expect { imported_project.project_import_status[:import_status] }.to eventually_eq('finished')
- .within(max_duration: 240, sleep_interval: 1)
-
- aggregate_failures do
- verify_status_data
- verify_repository_import
- verify_commits_import
- verify_labels_import
- verify_issues_import
- verify_milestones_import
- verify_wikis_import
- verify_merge_requests_import
- end
- end
-
- def verify_status_data
- stats = imported_project.project_import_status.dig(:stats, :imported)
- expect(stats).to include(
- # issue: 2,
- label: 9,
- milestone: 1,
- note: 3,
- pull_request: 1,
- pull_request_review: 1,
- diff_note: 1,
- release: 1
- )
- end
-
- def verify_repository_import
- expect(imported_project.reload!.description).to eq('Project for github import test')
- expect(imported_project.api_response[:import_error]).to be_nil
- end
-
- def verify_commits_import
- expect(imported_project.commits.length).to eq(2)
- end
-
- def verify_labels_import
- labels = imported_project.labels.map { |label| label.slice(:name, :color) }
-
- expect(labels).to include(
- { name: 'bug', color: '#d73a4a' },
- { name: 'documentation', color: '#0075ca' },
- { name: 'duplicate', color: '#cfd3d7' },
- { name: 'enhancement', color: '#a2eeef' },
- { name: 'good first issue', color: '#7057ff' },
- { name: 'help wanted', color: '#008672' },
- { name: 'invalid', color: '#e4e669' },
- { name: 'question', color: '#d876e3' },
- { name: 'wontfix', color: '#ffffff' }
- )
- end
-
- def verify_issues_import
- issues = imported_project.issues
-
- expect(issues.length).to eq(1)
- expect(issues.first).to include(
- title: 'Test issue',
- description: "*Created by: gitlab-qa-github*\n\nTest issue description",
- labels: ['good first issue', 'help wanted', 'question'],
- user_notes_count: 2
- )
- end
-
- def verify_milestones_import
- milestones = imported_project.milestones
-
- expect(milestones.length).to eq(1)
- expect(milestones.first).to include(title: '0.0.1', description: nil, state: 'active')
- end
-
- def verify_wikis_import
- wikis = imported_project.wikis
-
- expect(wikis.length).to eq(1)
- expect(wikis.first).to include(title: 'Home', format: 'markdown')
- end
-
- def verify_merge_requests_import
- merge_requests = imported_project.merge_requests
- merge_request = Resource::MergeRequest.init do |mr|
- mr.project = imported_project
- mr.iid = merge_requests.first[:iid]
- mr.api_client = api_client
- end.reload!
- mr_comments = merge_request.comments.map { |comment| comment[:body] } # rubocop:disable Rails/Pluck
-
- expect(merge_requests.length).to eq(1)
- expect(merge_request.api_resource).to include(
- title: 'Test pull request',
- state: 'opened',
- target_branch: 'main',
- source_branch: 'gitlab-qa-github-patch-1',
- labels: %w[documentation],
- description: <<~DSC.strip
- *Created by: gitlab-qa-github*\n\nTest pull request body
- DSC
- )
- expect(mr_comments).to match_array(
- [
- "*Created by: gitlab-qa-github*\n\n**Review:** Commented\n\nGood but needs some improvement",
- "*Created by: gitlab-qa-github*\n\n```suggestion:-0+0\nProject for GitHub import test to GitLab\r\n```",
- "*Created by: gitlab-qa-github*\n\nSome test PR comment"
- ]
- )
- end
- end
- end
-end
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
deleted file mode 100644
index e6b60a5b090..00000000000
--- a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
+++ /dev/null
@@ -1,495 +0,0 @@
-# frozen_string_literal: true
-
-# Lifesize project import test executed from https://gitlab.com/gitlab-org/manage/import/import-metrics
-
-# rubocop:disable Rails/Pluck
-module QA
- RSpec.describe 'Manage', :github, requires_admin: 'creates users', only: { job: 'large-github-import' } do
- describe 'Project import' do
- let(:logger) { Runtime::Logger.logger }
- let(:differ) { RSpec::Support::Differ.new(color: true) }
- let(:gitlab_address) { QA::Runtime::Scenario.gitlab_address }
- let(:dummy_url) { "https://example.com" }
-
- let(:created_by_pattern) { /\*Created by: \S+\*\n\n/ }
- let(:suggestion_pattern) { /suggestion:-\d+\+\d+/ }
- let(:gh_link_pattern) { %r{https://github.com/#{github_repo}/(issues|pull)} }
- let(:gl_link_pattern) { %r{#{gitlab_address}/#{imported_project.path_with_namespace}/-/(issues|merge_requests)} }
- let(:event_pattern) { %r{(un)?assigned( to)? @\S+|mentioned in (issue|merge request) [!#]\d+|changed title from \*\*.*\*\* to \*\*.*\*\*} } # rubocop:disable Layout/LineLength
-
- let(:api_client) { Runtime::API::Client.as_admin }
-
- let(:user) do
- Resource::User.fabricate_via_api! do |resource|
- resource.api_client = api_client
- end
- end
-
- let(:github_repo) { ENV['QA_LARGE_IMPORT_REPO'] || 'rspec/rspec-core' }
- let(:import_max_duration) { ENV['QA_LARGE_IMPORT_DURATION'] ? ENV['QA_LARGE_IMPORT_DURATION'].to_i : 7200 }
- let(:github_client) do
- Octokit::Client.new(
- access_token: ENV['QA_LARGE_IMPORT_GH_TOKEN'] || Runtime::Env.github_access_token,
- auto_paginate: true
- )
- end
-
- let(:gh_repo) { github_client.repository(github_repo) }
-
- let(:gh_branches) do
- logger.debug("= Fetching branches =")
- github_client.branches(github_repo).map(&:name)
- end
-
- let(:gh_commits) do
- logger.debug("= Fetching commits =")
- github_client.commits(github_repo).map(&:sha)
- end
-
- let(:gh_labels) do
- logger.debug("= Fetching labels =")
- github_client.labels(github_repo).map { |label| { name: label.name, color: "##{label.color}" } }
- end
-
- let(:gh_milestones) do
- logger.debug("= Fetching milestones =")
- github_client
- .list_milestones(github_repo, state: 'all')
- .map { |ms| { title: ms.title, description: ms.description } }
- end
-
- let(:gh_all_issues) do
- logger.debug("= Fetching issues and prs =")
- github_client.list_issues(github_repo, state: 'all')
- end
-
- let(:gh_prs) do
- gh_all_issues.select(&:pull_request).each_with_object({}) do |pr, hash|
- hash[pr.number] = {
- url: pr.html_url,
- title: pr.title,
- body: pr.body || '',
- comments: [*gh_pr_comments[pr.html_url], *gh_issue_comments[pr.html_url]].compact
- }
- end
- end
-
- let(:gh_issues) do
- gh_all_issues.reject(&:pull_request).each_with_object({}) do |issue, hash|
- hash[issue.number] = {
- url: issue.html_url,
- title: issue.title,
- body: issue.body || '',
- comments: gh_issue_comments[issue.html_url]
- }
- end
- end
-
- let(:gh_issue_comments) do
- logger.debug("= Fetching issue comments =")
- github_client.issues_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
- # use base html url as key
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body&.gsub(gh_link_pattern, dummy_url)
- end
- end
-
- let(:gh_pr_comments) do
- logger.debug("= Fetching pr comments =")
- github_client.pull_requests_comments(github_repo).each_with_object(Hash.new { |h, k| h[k] = [] }) do |c, hash|
- # use base html url as key
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body
- # some suggestions can contain extra whitespaces which gitlab will remove
- &.gsub(/suggestion\s+\r/, "suggestion\r")
- &.gsub(gh_link_pattern, dummy_url)
- end
- end
-
- let(:imported_project) do
- Resource::ProjectImportedFromGithub.fabricate_via_api! do |project|
- project.add_name_uuid = false
- project.name = 'imported-project'
- project.github_personal_access_token = Runtime::Env.github_access_token
- project.github_repository_path = github_repo
- project.personal_namespace = user.username
- project.api_client = api_client
- end
- end
-
- # rubocop:disable RSpec/InstanceVariable
- after do |example|
- next unless defined?(@import_time)
-
- # save data for comparison notification creation
- save_json(
- "data",
- {
- importer: :github,
- import_time: @import_time,
- errors: imported_project.project_import_status[:failed_relations],
- reported_stats: @stats,
- source: {
- name: "GitHub",
- project_name: github_repo,
- address: "https://github.com",
- data: {
- branches: gh_branches.length,
- commits: gh_commits.length,
- labels: gh_labels.length,
- milestones: gh_milestones.length,
- mrs: gh_prs.length,
- mr_comments: gh_prs.sum { |_k, v| v[:comments].length },
- issues: gh_issues.length,
- issue_comments: gh_issues.sum { |_k, v| v[:comments].length }
- }
- },
- target: {
- name: "GitLab",
- project_name: imported_project.path_with_namespace,
- address: gitlab_address,
- data: {
- branches: gl_branches.length,
- commits: gl_commits.length,
- labels: gl_labels.length,
- milestones: gl_milestones.length,
- mrs: mrs.length,
- mr_comments: mrs.sum { |_k, v| v[:comments].length },
- issues: gl_issues.length,
- issue_comments: gl_issues.sum { |_k, v| v[:comments].length }
- }
- },
- not_imported: {
- mrs: @mr_diff,
- issues: @issue_diff
- }
- }
- )
- end
- # rubocop:enable RSpec/InstanceVariable
-
- it(
- 'imports large Github repo via api',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347668'
- ) do
- start = Time.now
-
- # import the project and log gitlab path
- logger.info("== Importing project '#{github_repo}' in to '#{imported_project.reload!.full_path}' ==")
- # fetch all objects right after import has started
- fetch_github_objects
-
- import_status = lambda do
- imported_project.project_import_status.yield_self do |status|
- @stats = status.dig(:stats, :imported)
-
- # fail fast if import explicitly failed
- raise "Import of '#{imported_project.name}' failed!" if status[:import_status] == 'failed'
-
- status[:import_status]
- end
- end
-
- logger.info("== Waiting for import to be finished ==")
- expect(import_status).to eventually_eq('finished').within(max_duration: import_max_duration, sleep_interval: 30)
-
- @import_time = Time.now - start
-
- aggregate_failures do
- verify_repository_import
- verify_labels_import
- verify_milestones_import
- verify_merge_requests_import
- verify_issues_import
- end
- end
-
- # Persist all objects from repository being imported
- #
- # @return [void]
- def fetch_github_objects
- logger.info("== Fetching github repo objects ==")
-
- gh_repo
- gh_branches
- gh_commits
- gh_labels
- gh_milestones
- gh_prs
- gh_issues
- end
-
- # Verify repository imported correctly
- #
- # @return [void]
- def verify_repository_import
- logger.info("== Verifying repository import ==")
- expect(imported_project.description).to eq(gh_repo.description)
- # check via include, importer creates more branches
- # https://gitlab.com/gitlab-org/gitlab/-/issues/332711
- expect(gl_branches).to include(*gh_branches)
- expect(gl_commits).to match_array(gh_commits)
- end
-
- # Verify imported labels
- #
- # @return [void]
- def verify_labels_import
- logger.info("== Verifying label import ==")
- # check via include, additional labels can be inherited from parent group
- expect(gl_labels).to include(*gh_labels)
- end
-
- # Verify milestones import
- #
- # @return [void]
- def verify_milestones_import
- logger.info("== Verifying milestones import ==")
- expect(gl_milestones).to match_array(gh_milestones)
- end
-
- # Verify imported merge requests and mr issues
- #
- # @return [void]
- def verify_merge_requests_import
- logger.info("== Verifying merge request import ==")
- @mr_diff = verify_mrs_or_issues('mr')
- end
-
- # Verify imported issues and issue comments
- #
- # @return [void]
- def verify_issues_import
- logger.info("== Verifying issue import ==")
- @issue_diff = verify_mrs_or_issues('issue')
- end
-
- private
-
- # Verify imported mrs or issues and return missing items
- #
- # @param [String] type verification object, 'mrs' or 'issues'
- # @return [Hash]
- def verify_mrs_or_issues(type)
- # Compare length to have easy to read overview how many objects are missing
- #
- expected = type == 'mr' ? mrs : gl_issues
- actual = type == 'mr' ? gh_prs : gh_issues
- count_msg = "Expected to contain same amount of #{type}s. Gitlab: #{expected.length}, Github: #{actual.length}"
- expect(expected.length).to eq(actual.length), count_msg
-
- missing_comments = verify_comments(type, actual, expected)
-
- {
- "#{type}s": (actual.keys - expected.keys).map { |it| actual[it].slice(:title, :url) },
- "#{type}_comments": missing_comments
- }
- end
-
- # Verify imported comments
- #
- # @param [String] type verification object, 'mrs' or 'issues'
- # @param [Hash] actual
- # @param [Hash] expected
- # @return [Hash]
- def verify_comments(type, actual, expected)
- actual.each_with_object([]) do |(key, actual_item), missing_comments|
- expected_item = expected[key]
- title = actual_item[:title]
- msg = "expected #{type} with title '#{title}' to have"
-
- # Print title in the error message to see which object is missing
- #
- expect(expected_item).to be_truthy, "#{msg} been imported"
- next unless expected_item
-
- # Print difference in the description
- #
- expected_body = expected_item[:body]
- actual_body = actual_item[:body]
- body_msg = <<~MSG
- #{msg} same description. diff:\n#{differ.diff(expected_body, actual_body)}
- MSG
- expect(expected_body).to eq(actual_body), body_msg
-
- # Print amount difference first
- #
- expected_comments = expected_item[:comments]
- actual_comments = actual_item[:comments]
- comment_count_msg = <<~MSG
- #{msg} same amount of comments. Gitlab: #{expected_comments.length}, Github: #{actual_comments.length}
- MSG
- expect(expected_comments.length).to eq(actual_comments.length), comment_count_msg
- expect(expected_comments).to match_array(actual_comments)
-
- # Save missing comments
- #
- comment_diff = actual_comments - expected_comments
- next if comment_diff.empty?
-
- missing_comments << {
- title: title,
- github_url: actual_item[:url],
- gitlab_url: expected_item[:url],
- missing_comments: comment_diff
- }
- end
- end
-
- # Imported project branches
- #
- # @return [Array]
- def gl_branches
- @gl_branches ||= begin
- logger.debug("= Fetching branches =")
- imported_project.repository_branches(auto_paginate: true).map { |b| b[:name] }
- end
- end
-
- # Imported project commits
- #
- # @return [Array]
- def gl_commits
- @gl_commits ||= begin
- logger.debug("= Fetching commits =")
- imported_project.commits(auto_paginate: true, attempts: 2).map { |c| c[:id] }
- end
- end
-
- # Imported project labels
- #
- # @return [Array]
- def gl_labels
- @gl_labels ||= begin
- logger.debug("= Fetching labels =")
- imported_project.labels(auto_paginate: true).map { |label| label.slice(:name, :color) }
- end
- end
-
- # Imported project milestones
- #
- # @return [<Type>] <description>
- def gl_milestones
- @gl_milestones ||= begin
- logger.debug("= Fetching milestones =")
- imported_project.milestones(auto_paginate: true).map { |ms| ms.slice(:title, :description) }
- end
- end
-
- # Imported project merge requests
- #
- # @return [Hash]
- def mrs
- @mrs ||= begin
- logger.debug("= Fetching merge requests =")
- imported_mrs = imported_project.merge_requests(auto_paginate: true, attempts: 2)
-
- logger.debug("= Fetching merge request comments =")
- Parallel.map(imported_mrs, in_threads: 4) do |mr|
- resource = Resource::MergeRequest.init do |resource|
- resource.project = imported_project
- resource.iid = mr[:iid]
- resource.api_client = api_client
- end
-
- logger.debug("Fetching comments for mr '#{mr[:title]}'")
- comments = resource
- .comments(auto_paginate: true, attempts: 2)
- .reject { |c| c[:system] || c[:body].match?(/^(\*\*Review:\*\*)|(\*Merged by:).*/) }
-
- [mr[:iid], {
- url: mr[:web_url],
- title: mr[:title],
- body: sanitize_description(mr[:description]) || '',
- events: events(comments),
- comments: non_event_comments(comments)
- }]
- end.to_h
- end
- end
-
- # Imported project issues
- #
- # @return [Hash]
- def gl_issues
- @gl_issues ||= begin
- logger.debug("= Fetching issues =")
- imported_issues = imported_project.issues(auto_paginate: true, attempts: 2)
-
- logger.debug("= Fetching issue comments =")
- Parallel.map(imported_issues, in_threads: 4) do |issue|
- resource = Resource::Issue.init do |issue_resource|
- issue_resource.project = imported_project
- issue_resource.iid = issue[:iid]
- issue_resource.api_client = api_client
- end
-
- logger.debug("Fetching comments for issue '#{issue[:title]}'")
- comments = resource.comments(auto_paginate: true, attempts: 2)
-
- [issue[:iid], {
- url: issue[:web_url],
- title: issue[:title],
- body: sanitize_description(issue[:description]) || '',
- events: events(comments),
- comments: non_event_comments(comments)
- }]
- end.to_h
- end
- end
-
- # Fetch comments without events
- #
- # @param [Array] comments
- # @return [Array]
- def non_event_comments(comments)
- comments
- .reject { |c| c[:body].match?(event_pattern) }
- .map { |c| sanitize_comment(c[:body]) }
- end
-
- # Events
- #
- # @param [Array] comments
- # @return [Array]
- def events(comments)
- comments
- .select { |c| c[:body].match?(event_pattern) }
- .map { |c| c[:body] }
- end
-
- # Normalize comments and make them directly comparable
- #
- # * remove created by prefixes
- # * unify suggestion format
- # * replace github and gitlab urls - some of the links to objects get transformed to gitlab entities, some don't,
- # update all links to example.com for now
- #
- # @param [String] body
- # @return [String]
- def sanitize_comment(body)
- body
- .gsub(created_by_pattern, "")
- .gsub(suggestion_pattern, "suggestion\r")
- .gsub(gl_link_pattern, dummy_url)
- .gsub(gh_link_pattern, dummy_url)
- end
-
- # Remove created by prefix from descripion
- #
- # @param [String] body
- # @return [String]
- def sanitize_description(body)
- body&.gsub(created_by_pattern, "")
- end
-
- # Save json as file
- #
- # @param [String] name
- # @param [Hash] json
- # @return [void]
- def save_json(name, json)
- File.open("tmp/#{name}.json", "w") { |file| file.write(JSON.pretty_generate(json)) }
- end
- end
- end
-end
-# rubocop:enable Rails/Pluck
diff --git a/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
new file mode 100644
index 00000000000..a2d66ffe8d3
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'WebHooks integration', :requires_admin, :integrations, :orchestrated, product_group: :integrations do
+ before(:context) do
+ toggle_local_requests(true)
+ end
+
+ after(:context) do
+ Vendor::Smocker::SmockerApi.teardown!
+ end
+
+ let(:session) { SecureRandom.hex(5) }
+
+ it 'sends a push event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348945' do
+ setup_webhook(push: true) do |webhook, smocker|
+ Resource::Repository::ProjectPush.fabricate! do |project_push|
+ project_push.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].push?).to be(true), "Not push event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a merge request event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349720' do
+ setup_webhook(merge_requests: true) do |webhook, smocker|
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].mr?).to be(true), "Not MR event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends a wiki page event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349722' do
+ setup_webhook(wiki_page: true) do |webhook, smocker|
+ Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
+ page.project = webhook.project
+ end
+
+ wait_until do
+ !smocker.history(session).empty?
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
+ expect(events[0].project_name).to eql(webhook.project.name)
+ expect(events[0].wiki?).to be(true), "Not wiki event: \n#{events[0].raw}"
+ end
+ end
+ end
+
+ it 'sends an issues and note event',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
+ setup_webhook(issues: true, note: true) do |webhook, smocker|
+ issue = Resource::Issue.fabricate_via_api! do |issue_init|
+ issue_init.project = webhook.project
+ end
+
+ Resource::ProjectIssueNote.fabricate_via_api! do |note|
+ note.project = issue.project
+ note.issue = issue
+ end
+
+ wait_until do
+ smocker.history(session).size > 1
+ end
+
+ events = smocker.history(session).map(&:as_hook_event)
+ aggregate_failures do
+ issue_event = events.find(&:issue?)
+ note_event = events.find(&:note?)
+
+ expect(events.size).to be(2), "Should have 2 events: \n#{events.map(&:raw).join("\n")}"
+ expect(issue_event).not_to be(nil), "Not issue event: \n#{events[0].raw}"
+ expect(note_event).not_to be(nil), "Not note event: \n#{events[1].raw}"
+ end
+ end
+ end
+
+ private
+
+ def setup_webhook(**event_args)
+ Vendor::Smocker::SmockerApi.init(wait: 10) do |smocker|
+ smocker.register(session: session)
+
+ webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
+ hook.url = smocker.url
+
+ event_args.each do |event, bool|
+ hook.send("#{event}_events=", bool)
+ end
+ end
+
+ yield(webhook, smocker)
+
+ smocker.reset
+ end
+ end
+
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
+ end
+
+ def wait_until(timeout = 120, &block)
+ Support::Waiter.wait_until(max_duration: timeout, reload_page: false, raise_on_failure: false, &block)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
index f721b3326a0..e17e12cdaf3 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :reliable, :requires_admin do
+ RSpec.describe 'Manage', :reliable, :requires_admin, product_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 }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
index 74a00e1c74c..c1f11b15068 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
let!(:source_issue) do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
index 83cc44f9958..5689fa169ce 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
@@ -5,7 +5,7 @@
# rubocop:disable Rails/Pluck, Layout/LineLength, RSpec/MultipleMemoizedHelpers
module QA
RSpec.describe "Manage", requires_admin: 'creates users', only: { job: 'large-gitlab-import' } do
- describe "Gitlab migration" do
+ describe "Gitlab migration", product_group: :import do
let(:logger) { Runtime::Logger.logger }
let(:differ) { RSpec::Support::Differ.new(color: true) }
let(:gitlab_group) { ENV['QA_LARGE_IMPORT_GROUP'] || 'gitlab-migration' }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
index 704325d9235..aa4d3becbe7 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
let(:member) do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
index d656ea4dea5..92cba005832 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with merge request' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
index 484c32956e3..3db4ff4351e 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with ci pipeline' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
index 421dbe56a99..3e0df3d1e13 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with uninitialized project' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
index 6910b6a7fa2..91dcfe6a1a3 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
@@ -4,7 +4,7 @@ require_relative 'gitlab_project_migration_common'
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration' do
+ describe 'Gitlab migration', product_group: :import do
include_context 'with gitlab project migration'
context 'with release' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
index 3581ad3d207..9c80c088917 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb
@@ -1,9 +1,11 @@
# frozen_string_literal: true
module QA
- # Disable on live envs until bulk_import_projects toggle is on by default
- # Otherwise tests running in parallel can disable feature in the middle of other test
RSpec.shared_context 'with gitlab project migration', requires_admin: 'creates a user via API',
+ quarantine: {
+ type: :flaky,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/364839'
+ },
feature_flag: {
name: 'bulk_import_projects',
scope: :global
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 539da92f471..c4be90d3759 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
@@ -33,9 +33,7 @@ module QA
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([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.not_to raise_error
end
@@ -67,9 +65,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @different_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
- ])
+ commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
end
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 874626e01f1..24088057abc 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
- describe 'rate limits', :reliable do
+ describe 'rate limits', :reliable, product_group: :integrations do
let(:rate_limited_user) { Resource::User.fabricate_via_api! }
let(:api_client) { Runtime::API::Client.new(:gitlab, user: rate_limited_user) }
let!(:request) { Runtime::API::Request.new(api_client, '/users') }
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 e518bbfc6f7..28c20344b29 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
@@ -69,9 +69,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
end
diff --git a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
index 9f0e2664213..16d4fd35b69 100644
--- a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'User', :requires_admin do
+ describe 'User', :requires_admin, product_group: :workspace do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:sub_group) do
@@ -85,9 +85,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = sub_group_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.not_to raise_error
end
@@ -167,9 +165,7 @@ module QA
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = parent_group_project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test.txt', content: 'new file' }
- ])
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
end
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError,
/403 Forbidden - You are not allowed to push into this branch/)
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 531419e8d0f..ff036c18671 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/users_spec.rb
@@ -4,7 +4,7 @@ require 'airborne'
module QA
RSpec.describe 'Manage' do
- describe 'Users API', :reliable do
+ describe 'Users API', :reliable, product_group: :workspace do
let(:api_client) { Runtime::API::Client.new(:gitlab) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
diff --git a/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb b/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb
deleted file mode 100644
index aae0329003b..00000000000
--- a/qa/qa/specs/features/api/3_create/integrations/webhook_events_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- describe 'WebHooks integration', :requires_admin, :integrations, :orchestrated do
- before(:context) do
- toggle_local_requests(true)
- end
-
- after(:context) do
- Vendor::Smocker::SmockerApi.teardown!
- end
-
- let(:session) { SecureRandom.hex(5) }
-
- it 'sends a push event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348945' do
- setup_webhook(push: true) do |webhook, smocker|
- Resource::Repository::ProjectPush.fabricate! do |project_push|
- project_push.project = webhook.project
- end
-
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].push?).to be(true), "Not push event: \n#{events[0].raw}"
- end
- end
- end
-
- it 'sends a merge request event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349720' do
- setup_webhook(merge_requests: true) do |webhook, smocker|
- Resource::MergeRequest.fabricate_via_api! do |merge_request|
- merge_request.project = webhook.project
- end
-
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].mr?).to be(true), "Not MR event: \n#{events[0].raw}"
- end
- end
- end
-
- it 'sends a wiki page event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349722' do
- setup_webhook(wiki_page: true) do |webhook, smocker|
- Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
- page.project = webhook.project
- end
-
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].wiki?).to be(true), "Not wiki event: \n#{events[0].raw}"
- end
- end
- end
-
- it 'sends an issues and note event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
- setup_webhook(issues: true, note: true) do |webhook, smocker|
- issue = Resource::Issue.fabricate_via_api! do |issue_init|
- issue_init.project = webhook.project
- end
-
- Resource::ProjectIssueNote.fabricate_via_api! do |note|
- note.project = issue.project
- note.issue = issue
- end
-
- wait_until do
- smocker.history(session).size > 1
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- issue_event = events.find(&:issue?)
- note_event = events.find(&:note?)
-
- expect(events.size).to be(2), "Should have 2 events: \n#{events.map(&:raw).join("\n")}"
- expect(issue_event).not_to be(nil), "Not issue event: \n#{events[0].raw}"
- expect(note_event).not_to be(nil), "Not note event: \n#{events[1].raw}"
- end
- end
- end
-
- private
-
- def setup_webhook(**event_args)
- Vendor::Smocker::SmockerApi.init(wait: 10) do |smocker|
- smocker.register(session: session)
-
- webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
- hook.url = smocker.url
-
- event_args.each do |event, bool|
- hook.send("#{event}_events=", bool)
- end
- end
-
- yield(webhook, smocker)
-
- smocker.reset
- end
- end
-
- def toggle_local_requests(on)
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
- end
-
- def wait_until(timeout = 120, &block)
- Support::Waiter.wait_until(max_duration: timeout, reload_page: false, raise_on_failure: false, &block)
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb b/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb
index 9d47872a774..4ee436a597a 100644
--- a/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb
@@ -16,18 +16,18 @@ module QA
commit.project = project
commit.update_files(
[
- {
- file_path: '.gitlab-ci.yml',
- content: 'script'
- }
+ {
+ file_path: '.gitlab-ci.yml',
+ content: 'script'
+ }
]
)
commit.add_files(
[
- {
- file_path: 'foo',
- content: 'bar'
- }
+ {
+ file_path: 'foo',
+ content: 'bar'
+ }
]
)
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
index a1b9e232e3d..c690202f091 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- describe 'Manage', :requires_admin, :reliable do
+ describe 'Manage', :requires_admin, :reliable, product_group: :import do
describe 'Gitlab migration' do
let!(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:user) do
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 2c331584cf7..d684eabe644 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Project transfer between groups', :reliable do
+ describe 'Project transfer between groups', :reliable, product_group: :workspace do
let(:source_group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "source-group-#{SecureRandom.hex(8)}"
@@ -27,9 +27,7 @@ module QA
before do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
- commit.add_files([
- { file_path: 'README.md', content: readme_content }
- ])
+ commit.add_files([{ file_path: 'README.md', content: readme_content }])
end
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb
new file mode 100644
index 00000000000..b8d00c2faee
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
+ describe 'Jenkins integration', product_group: :integrations do
+ let(:jenkins_server) { Service::DockerRun::Jenkins.new }
+
+ let(:jenkins_client) do
+ Vendor::Jenkins::Client.new(
+ jenkins_server.host_name,
+ port: jenkins_server.port,
+ user: Runtime::Env.jenkins_admin_username,
+ password: Runtime::Env.jenkins_admin_password
+ )
+ end
+
+ let(:jenkins_project_name) { "gitlab_jenkins_#{SecureRandom.hex(5)}" }
+
+ let(:connection_name) { 'gitlab-connection' }
+
+ let(:project_name) { "project_with_jenkins_#{SecureRandom.hex(4)}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = project_name
+ project.initialize_with_readme = true
+ project.auto_devops_enabled = false
+ end
+ end
+
+ let(:access_token) do
+ Runtime::Env.personal_access_token ||= fabricate_access_token
+ end
+
+ before do
+ toggle_local_requests(true)
+ jenkins_server.register!
+
+ Support::Waiter.wait_until(max_duration: 30, reload_page: false, retry_on_exception: true) do
+ jenkins_client.ready?
+ end
+
+ configure_gitlab_jenkins
+ end
+
+ after do
+ jenkins_server&.remove!
+ toggle_local_requests(false)
+ end
+
+ it 'integrates and displays build status for MR pipeline in GitLab',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347788' do
+ setup_project_integration
+
+ jenkins_integration = project.find_integration('jenkins')
+ expect(jenkins_integration).not_to be(nil), 'Jenkins integration did not save'
+ expect(jenkins_integration[:active]).to be(true), 'Jenkins integration is not active'
+
+ job = create_jenkins_job
+
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.new_branch = false
+ push.file_name = "file_#{SecureRandom.hex(4)}.txt"
+ end
+
+ Support::Waiter.wait_until(max_duration: 60, raise_on_failure: false, reload_page: false) do
+ job.status == :success
+ end
+
+ expect(job.status).to eql(:success), "Build failed or is not found: #{job.log}"
+
+ project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |show|
+ expect(show).to have_build('jenkins', status: :success, wait: 15)
+ end
+ end
+
+ private
+
+ def setup_project_integration
+ login_to_gitlab
+
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_project)
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ Page::Project::Settings::Integrations.perform(&:click_jenkins_ci_link)
+
+ QA::Page::Project::Settings::Services::Jenkins.perform do |jenkins|
+ jenkins.setup_service_with(
+ jenkins_url: patch_host_name(jenkins_server.host_address, 'jenkins-server'),
+ project_name: jenkins_project_name,
+ username: jenkins_server.username,
+ password: jenkins_server.password
+ )
+ end
+ end
+
+ def login_to_gitlab
+ Flow::Login.sign_in
+ end
+
+ def fabricate_access_token
+ login_to_gitlab
+
+ token = Resource::PersonalAccessToken.fabricate!.token
+ Page::Main::Menu.perform(&:sign_out)
+ token
+ end
+
+ def create_jenkins_job
+ jenkins_client.create_job jenkins_project_name do |job|
+ job.gitlab_connection = connection_name
+ job.description = 'Just a job'
+ job.repo_url = patch_host_name(project.repository_http_location.git_uri, 'gitlab')
+ job.shell_command = 'sleep 5'
+ end
+ end
+
+ def configure_gitlab_jenkins
+ jenkins_client.configure_gitlab_plugin(
+ patch_host_name(Runtime::Scenario.gitlab_address, 'gitlab'),
+ connection_name: connection_name,
+ access_token: access_token,
+ read_timeout: 20,
+ connection_timeout: 10
+ )
+ end
+
+ def patch_host_name(host_name, container_name)
+ return host_name unless host_name.include?('localhost')
+
+ ip_address = `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' #{container_name}`
+ .strip
+ host_name.gsub('localhost', ip_address)
+ end
+
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb
new file mode 100644
index 00000000000..5a4031b4305
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ include Support::API
+
+ describe 'Jira integration', :jira, :orchestrated, :requires_admin, product_group: :integrations do
+ let(:jira_project_key) { 'JITP' }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = "project_with_jira_integration"
+ end
+ end
+
+ before do
+ page.visit Vendor::Jira::JiraAPI.perform(&:base_url)
+
+ QA::Support::Retrier
+ .retry_until(sleep_interval: 3, reload_page: page, max_attempts: 20, raise_on_failure: true) do
+ page.has_text? 'Welcome to Jira'
+ end
+
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
+
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
+
+ QA::Page::Project::Settings::Services::Jira.perform do |jira|
+ jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
+ end
+
+ expect(page).not_to have_text("Requests to the local network are not allowed") # rubocop:disable RSpec/ExpectInHook
+ end
+
+ 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
+
+ push_commit("Closes #{issue_key}")
+
+ expect_issue_done(issue_key)
+ end
+
+ 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
+
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
+
+ merge_request = create_mr_with_description("Closes #{issue_key}")
+
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform(&:merge!)
+
+ expect_issue_done(issue_key)
+ end
+
+ private
+
+ def create_mr_with_description(description)
+ Resource::MergeRequest.fabricate! do |merge_request|
+ merge_request.project = project
+ merge_request.target_new_branch = !master_branch_exists?
+ merge_request.description = description
+ end
+ end
+
+ def push_commit(commit_message)
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.commit_message = commit_message
+ push.file_content = commit_message
+ push.project = project
+ push.new_branch = !master_branch_exists?
+ end
+ end
+
+ def expect_issue_done(issue_key)
+ expect do
+ Support::Waiter.wait_until(raise_on_failure: true) do
+ jira_issue = Vendor::Jira::JiraAPI.perform do |jira_api|
+ jira_api.fetch_issue(issue_key)
+ end
+
+ jira_issue[:fields][:status][:name] == 'Done'
+ end
+ end.not_to raise_error
+ end
+
+ def master_branch_exists?
+ project.repository_branches.map { |item| item[:name] }.include?(project.default_branch)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb
new file mode 100644
index 00000000000..7e46276be92
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage', :reliable do
+ describe 'Jira issue import', :jira, :orchestrated, :requires_admin, product_group: :integrations do
+ let(:jira_project_key) { "JITD" }
+ let(:jira_issue_title) { "[#{jira_project_key}-1] Jira to GitLab Test Issue" }
+ let(:jira_issue_description) { "This issue is for testing importing Jira issues to GitLab." }
+ let(:jira_issue_label_1) { "jira-import::#{jira_project_key}-1" }
+ let(:jira_issue_label_2) { "QA" }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = "jira_issue_import"
+ end
+ end
+
+ it 'imports issues from Jira', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347966' do
+ set_up_jira_integration
+ import_jira_issues
+
+ QA::Support::Retrier.retry_on_exception do
+ Page::Project::Menu.perform(&:click_issues)
+
+ Page::Project::Issue::Index.perform do |issues_page|
+ expect(issues_page).to have_content("2 issues successfully imported")
+
+ issues_page.click_issue_link(jira_issue_title)
+ end
+ end
+
+ expect(page).to have_content(jira_issue_description)
+
+ Page::Project::Issue::Show.perform do |issue|
+ expect(issue).to have_label(jira_issue_label_1)
+ expect(issue).to have_label(jira_issue_label_2)
+ end
+ end
+
+ private
+
+ def set_up_jira_integration
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
+
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
+
+ QA::Page::Project::Settings::Services::Jira.perform do |jira|
+ jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
+ end
+
+ expect(page).not_to have_text("Url is blocked")
+ expect(page).to have_text("Jira settings saved and active.")
+ end
+
+ def import_jira_issues
+ Page::Project::Menu.perform(&:click_issues)
+ Page::Project::Issue::Index.perform(&:go_to_jira_import_form)
+
+ Page::Project::Issue::JiraImport.perform do |form|
+ form.select_project_and_import(jira_project_key)
+ end
+
+ expect(page).to have_content("Import in progress")
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
new file mode 100644
index 00000000000..4495d83f336
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.shared_examples 'notifies on a pipeline' do |exit_code|
+ before do
+ push_commit(exit_code: exit_code)
+ end
+
+ it 'sends an email' do
+ meta = exit_code_meta(exit_code)
+
+ project.visit!
+ Flow::Pipeline.wait_for_latest_pipeline(status: meta[:status])
+
+ messages = mail_hog_messages(mail_hog)
+ subjects = messages.map(&:subject)
+ targets = messages.map(&:to)
+
+ aggregate_failures do
+ expect(subjects).to include(meta[:email_subject])
+ expect(subjects).to include(/#{Regexp.escape(project.name)}/)
+ expect(targets).to include(*emails)
+ end
+ end
+ end
+
+ RSpec.describe 'Manage', :orchestrated, :runner, :requires_admin, :smtp, product_group: :integrations do
+ describe 'Pipeline status emails' do
+ let(:executor) { "qa-runner-#{Time.now.to_i}" }
+ let(:emails) { %w[foo@bar.com baz@buzz.com] }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pipeline-status-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ let(:mail_hog) { Vendor::MailHog::API.new }
+
+ before(:all) do
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ before do
+ setup_pipeline_emails(emails)
+ end
+
+ describe 'when pipeline passes', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366240' do
+ include_examples 'notifies on a pipeline', 0
+ end
+
+ describe 'when pipeline fails', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366241' do
+ include_examples 'notifies on a pipeline', 1
+ end
+
+ def push_commit(exit_code: 0)
+ 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(exit_code: exit_code)
+ }
+ ]
+ )
+ end
+ end
+
+ def setup_pipeline_emails(emails)
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
+
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ QA::Page::Project::Settings::Integrations.perform(&:click_pipelines_email_link)
+
+ QA::Page::Project::Settings::Services::PipelineStatusEmails.perform do |pipeline_status_emails|
+ pipeline_status_emails.toggle_notify_broken_pipelines # notify on pass and fail
+ pipeline_status_emails.set_recipients(emails)
+ pipeline_status_emails.click_save_button
+ end
+ end
+
+ def gitlab_ci_yaml(exit_code: 0, tag: executor)
+ <<~YAML
+ test-pipeline-email:
+ tags:
+ - #{tag}
+ script: sleep 5; exit #{exit_code};
+ YAML
+ end
+
+ private
+
+ def exit_code_meta(exit_code)
+ {
+ 0 => { status: 'passed', email_subject: /Successful pipeline/ },
+ 1 => { status: 'failed', email_subject: /Failed pipeline/ }
+ }[exit_code]
+ end
+
+ def mail_hog_messages(mail_hog_api)
+ Support::Retrier.retry_until(sleep_interval: 1) do
+ Runtime::Logger.debug('Fetching email...')
+
+ messages = mail_hog_api.fetch_messages
+ logs = messages.map { |m| "#{m.to}: #{m.subject}" }
+
+ Runtime::Logger.debug("MailHog Logs: #{logs.join("\n")}")
+
+ # for failing pipelines we have three messages
+ # one for the owner
+ # and one for each recipient
+ messages if mail_hog_pipeline_count(messages) >= 2
+ end
+ end
+
+ def mail_hog_pipeline_count(messages)
+ messages.count { |message| message.subject.include?('pipeline') }
+ end
+ end
+ end
+end
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 ad90df4b90d..56883917153 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
@@ -3,8 +3,12 @@
module QA
RSpec.describe 'Manage', :requires_admin, :skip_live_env do
describe '2FA' do
+ let(:admin_api_client) { Runtime::API::Client.as_admin }
+ let(:owner_api_client) { Runtime::API::Client.new(:gitlab, user: owner_user) }
+
let!(:owner_user) do
Resource::User.fabricate_via_api! do |usr|
+ usr.username = "owner_user_#{SecureRandom.hex(4)}"
usr.api_client = admin_api_client
end
end
@@ -26,6 +30,7 @@ module QA
let(:developer_user) do
Resource::User.fabricate_via_api! do |resource|
+ resource.username = "developer_user_#{SecureRandom.hex(4)}"
resource.api_client = admin_api_client
end
end
@@ -38,8 +43,7 @@ module QA
it(
'allows enforcing 2FA via UI and logging in with 2FA',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931',
- quarantine: { type: :flaky, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/369516' }
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931'
) do
enforce_two_factor_authentication_on_group(group)
@@ -70,14 +74,6 @@ module QA
developer_user.remove_via_api!
end
- def admin_api_client
- @admin_api_client ||= Runtime::API::Client.as_admin
- end
-
- def owner_api_client
- @owner_api_client ||= Runtime::API::Client.new(:gitlab, user: owner_user)
- end
-
# We are intentionally using the UI to enforce 2FA to exercise the flow with UI.
# Any future tests should use the API for this purpose.
def enforce_two_factor_authentication_on_group(group)
@@ -87,7 +83,9 @@ module QA
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform(&:set_require_2fa_enabled)
- expect(page).to have_text(two_fa_expected_text)
+ QA::Support::Retrier.retry_on_exception(reload_page: page) do
+ expect(page).to have_text(two_fa_expected_text)
+ end
Page::Profile::TwoFactorAuth.perform(&:click_configure_it_later_button)
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 90fbff3261e..3f461e9247f 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :reliable do
+ RSpec.describe 'Manage', :reliable, product_group: :workspace do
describe 'Add project member' do
it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347887' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
index f624f2fb44f..b251b3075dd 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Create project badge', :reliable do
+ describe 'Create project badge', :reliable, product_group: :workspace do
let(:badge_name) { "project-badge-#{SecureRandom.hex(8)}" }
let(:expected_badge_link_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}" }
let(:expected_badge_image_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg" }
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 d07fff80b19..7c6b0d77219 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :smoke do
+ RSpec.describe 'Manage', :smoke, product_group: :workspace do
describe 'Project' do
shared_examples 'successful project creation' do
it 'creates a new project' do
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 d299997dd3c..2abbb6ca73c 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
+ RSpec.describe 'Manage', product_group: :workspace do
shared_examples 'loads all images' do |admin|
let(:api_client) { Runtime::API::Client.as_admin }
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 0477a9b8a1f..6ac11fea7e1 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
@@ -3,7 +3,7 @@
module QA
# Spec uses real github.com, which means outage of github can actually block deployment
# Keep spec in reliable bucket but don't run in blocking pipelines
- RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin do
+ RSpec.describe 'Manage', :github, :reliable, :skip_live_env, :requires_admin, product_group: :import do
describe 'Project import' do
let(:github_repo) { 'gitlab-qa-github/import-test' }
let(:api_client) { Runtime::API::Client.as_admin }
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb
index dbfb114dc82..164f86bffce 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Invite group', :reliable do
+ describe 'Invite group', :reliable, product_group: :workspace do
shared_examples 'invites group to project' do
it 'verifies group is added and members can access project with correct access level' do
Page::Project::Menu.perform(&:click_members)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb
index 29e590976d2..98a08dd0d9a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Project owner permissions', :reliable do
+ describe 'Project owner permissions', :reliable, product_group: :workspace do
let!(:owner) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
index 88f4996ff03..33ca5f6009c 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Project activity', :reliable do
+ describe 'Project activity', :reliable, product_group: :workspace 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
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 a384dc16064..b9b82baa6f1 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'User', :requires_admin do
+ describe 'User', :requires_admin, product_group: :workspace do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:followed_user_api_client) { Runtime::API::Client.new(:gitlab, user: followed_user) }
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb
new file mode 100644
index 00000000000..54f05f84dca
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'User', :requires_admin, :reliable, product_group: :workspace do
+ let(:admin_api_client) { Runtime::API::Client.as_admin }
+
+ let!(:user) do
+ Resource::User.fabricate_via_api! do |user|
+ user.api_client = admin_api_client
+ end
+ end
+
+ let!(:group) do
+ group = QA::Resource::Group.fabricate_via_api! do |group|
+ group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}"
+ end
+ group.sandbox.add_member(user)
+ group
+ end
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.group = group
+ project.name = "project-for-user-access-termination"
+ project.initialize_with_readme = true
+ end
+ end
+
+ context 'for after parent group membership termination' do
+ before do
+ Flow::Login.while_signed_in_as_admin do
+ group.sandbox.visit!
+
+ Page::Group::Menu.perform(&:click_group_members_item)
+ Page::Group::Members.perform do |members_page|
+ members_page.remove_member(user.username)
+ end
+ end
+ end
+
+ after do
+ user.remove_via_api!
+ project.remove_via_api!
+ group.remove_via_api!
+ end
+
+ 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!
+
+ Page::Project::Show.perform do |project|
+ project.click_file('README.md')
+ end
+
+ Page::File::Show.perform(&:click_edit)
+
+ expect(page).to have_text("You can’t edit files directly in this project.")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
deleted file mode 100644
index 8462f5db30b..00000000000
--- a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Manage' do
- describe 'User', :requires_admin, :reliable do
- let(:admin_api_client) { Runtime::API::Client.as_admin }
-
- let!(:user) do
- Resource::User.fabricate_via_api! do |user|
- user.api_client = admin_api_client
- end
- end
-
- let!(:group) do
- group = QA::Resource::Group.fabricate_via_api! do |group|
- group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}"
- end
- group.sandbox.add_member(user)
- group
- end
-
- let!(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.group = group
- project.name = "project-for-user-access-termination"
- project.initialize_with_readme = true
- end
- end
-
- context 'after parent group membership termination' do
- before do
- Flow::Login.while_signed_in_as_admin do
- group.sandbox.visit!
-
- Page::Group::Menu.perform(&:click_group_members_item)
- Page::Group::Members.perform do |members_page|
- members_page.remove_member(user.username)
- end
- end
- end
-
- 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!
-
- Page::Project::Show.perform do |project|
- project.click_file('README.md')
- end
-
- Page::File::Show.perform(&:click_edit)
-
- expect(page).to have_text("You can’t edit files directly in this project.")
- end
-
- after do
- user.remove_via_api!
- project.remove_via_api!
- group.remove_via_api!
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb
index 8de9d7c2049..b7585f00630 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'User', :requires_admin do
+ describe 'User', :requires_admin, product_group: :workspace do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:sub_group) do
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 206e6b8a456..b2c612d38fe 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
@@ -19,12 +19,13 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = template_project
commit.commit_message = 'Add custom issue template'
- commit.add_files([
- {
- file_path: ".gitlab/issue_templates/#{template_name}.md",
- content: template_content
- }
- ])
+ commit.add_files(
+ [
+ {
+ file_path: ".gitlab/issue_templates/#{template_name}.md",
+ content: template_content
+ }
+ ])
end
end
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
deleted file mode 100644
index d8435407296..00000000000
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Plan', :reliable do
- describe 'Jira issue import', :jira, :orchestrated, :requires_admin do
- let(:jira_project_key) { "JITD" }
- let(:jira_issue_title) { "[#{jira_project_key}-1] Jira to GitLab Test Issue" }
- let(:jira_issue_description) { "This issue is for testing importing Jira issues to GitLab." }
- let(:jira_issue_label_1) { "jira-import::#{jira_project_key}-1" }
- let(:jira_issue_label_2) { "QA" }
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = "jira_issue_import"
- end
- end
-
- it 'imports issues from Jira', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347966' do
- set_up_jira_integration
- import_jira_issues
-
- QA::Support::Retrier.retry_on_exception do
- Page::Project::Menu.perform(&:click_issues)
-
- Page::Project::Issue::Index.perform do |issues_page|
- expect(issues_page).to have_content("2 issues successfully imported")
-
- issues_page.click_issue_link(jira_issue_title)
- end
- end
-
- expect(page).to have_content(jira_issue_description)
-
- Page::Project::Issue::Show.perform do |issue|
- expect(issue).to have_label(jira_issue_label_1)
- expect(issue).to have_label(jira_issue_label_2)
- end
- end
-
- private
-
- def set_up_jira_integration
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
-
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
-
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
-
- QA::Page::Project::Settings::Services::Jira.perform do |jira|
- jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
- end
-
- expect(page).not_to have_text("Url is blocked")
- expect(page).to have_text("Jira settings saved and active.")
- end
-
- def import_jira_issues
- Page::Project::Menu.perform(&:click_issues)
- Page::Project::Issue::Index.perform(&:go_to_jira_import_form)
-
- Page::Project::Issue::JiraImport.perform do |form|
- form.select_project_and_import(jira_project_key)
- end
-
- expect(page).to have_content("Import in progress")
- end
- end
- end
-end
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
deleted file mode 100644
index 4bfd253c992..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
- describe 'Jenkins integration' do
- let(:jenkins_server) { Service::DockerRun::Jenkins.new }
-
- let(:jenkins_client) do
- Vendor::Jenkins::Client.new(
- jenkins_server.host_name,
- port: jenkins_server.port,
- user: Runtime::Env.jenkins_admin_username,
- password: Runtime::Env.jenkins_admin_password
- )
- end
-
- let(:jenkins_project_name) { "gitlab_jenkins_#{SecureRandom.hex(5)}" }
-
- let(:connection_name) { 'gitlab-connection' }
-
- let(:project_name) { "project_with_jenkins_#{SecureRandom.hex(4)}" }
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = project_name
- project.initialize_with_readme = true
- project.auto_devops_enabled = false
- end
- end
-
- let(:access_token) do
- Runtime::Env.personal_access_token ||= fabricate_access_token
- end
-
- before do
- toggle_local_requests(true)
- jenkins_server.register!
-
- Support::Waiter.wait_until(max_duration: 30, reload_page: false, retry_on_exception: true) do
- jenkins_client.ready?
- end
-
- configure_gitlab_jenkins
- end
-
- after do
- jenkins_server&.remove!
- toggle_local_requests(false)
- end
-
- it 'integrates and displays build status for MR pipeline in GitLab', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347788' do
- setup_project_integration
-
- jenkins_integration = project.find_integration('jenkins')
- expect(jenkins_integration).not_to be(nil), 'Jenkins integration did not save'
- expect(jenkins_integration[:active]).to be(true), 'Jenkins integration is not active'
-
- job = create_jenkins_job
-
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.new_branch = false
- push.file_name = "file_#{SecureRandom.hex(4)}.txt"
- end
-
- Support::Waiter.wait_until(max_duration: 60, raise_on_failure: false, reload_page: false) do
- job.status == :success
- end
-
- expect(job.status).to eql(:success), "Build failed or is not found: #{job.log}"
-
- project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |show|
- expect(show).to have_build('jenkins', status: :success, wait: 15)
- end
- end
-
- private
-
- def setup_project_integration
- login_to_gitlab
-
- project.visit!
-
- Page::Project::Menu.perform(&:click_project)
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- Page::Project::Settings::Integrations.perform(&:click_jenkins_ci_link)
-
- QA::Page::Project::Settings::Services::Jenkins.perform do |jenkins|
- jenkins.setup_service_with(
- jenkins_url: patch_host_name(jenkins_server.host_address, 'jenkins-server'),
- project_name: jenkins_project_name,
- username: jenkins_server.username,
- password: jenkins_server.password
- )
- end
- end
-
- def login_to_gitlab
- Flow::Login.sign_in
- end
-
- def fabricate_access_token
- login_to_gitlab
-
- token = Resource::PersonalAccessToken.fabricate!.token
- Page::Main::Menu.perform(&:sign_out)
- token
- end
-
- def create_jenkins_job
- jenkins_client.create_job jenkins_project_name do |job|
- job.gitlab_connection = connection_name
- job.description = 'Just a job'
- job.repo_url = patch_host_name(project.repository_http_location.git_uri, 'gitlab')
- job.shell_command = 'sleep 5'
- end
- end
-
- def configure_gitlab_jenkins
- jenkins_client.configure_gitlab_plugin(
- patch_host_name(Runtime::Scenario.gitlab_address, 'gitlab'),
- connection_name: connection_name,
- access_token: access_token,
- read_timeout: 20,
- connection_timeout: 10
- )
- end
-
- def patch_host_name(host_name, container_name)
- return host_name unless host_name.include?('localhost')
-
- ip_address = `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' #{container_name}`.strip
- host_name.gsub('localhost', ip_address)
- end
-
- def toggle_local_requests(on)
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
- end
- end
- end
-end
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
deleted file mode 100644
index 088556a3981..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- include Support::API
-
- describe 'Jira integration', :jira, :orchestrated, :requires_admin do
- let(:jira_project_key) { 'JITP' }
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = "project_with_jira_integration"
- end
- end
-
- before do
- page.visit Vendor::Jira::JiraAPI.perform(&:base_url)
-
- QA::Support::Retrier.retry_until(sleep_interval: 3, reload_page: page, max_attempts: 20, raise_on_failure: true) do
- page.has_text? 'Welcome to Jira'
- end
-
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
-
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
-
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
-
- QA::Page::Project::Settings::Services::Jira.perform do |jira|
- jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
- end
-
- 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/gitlab/-/quality/test_cases/347794' do
- issue_key = Vendor::Jira::JiraAPI.perform do |jira_api|
- jira_api.create_issue(jira_project_key)
- end
-
- push_commit("Closes #{issue_key}")
-
- expect_issue_done(issue_key)
- end
-
- 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
-
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
-
- merge_request = create_mr_with_description("Closes #{issue_key}")
-
- merge_request.visit!
-
- Page::MergeRequest::Show.perform(&:merge!)
-
- expect_issue_done(issue_key)
- end
-
- private
-
- def create_mr_with_description(description)
- Resource::MergeRequest.fabricate! do |merge_request|
- merge_request.project = project
- merge_request.target_new_branch = !master_branch_exists?
- merge_request.description = description
- end
- end
-
- def push_commit(commit_message)
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.commit_message = commit_message
- push.file_content = commit_message
- push.project = project
- push.new_branch = !master_branch_exists?
- end
- end
-
- def expect_issue_done(issue_key)
- expect do
- Support::Waiter.wait_until(raise_on_failure: true) do
- jira_issue = Vendor::Jira::JiraAPI.perform do |jira_api|
- jira_api.fetch_issue(issue_key)
- end
-
- jira_issue[:fields][:status][:name] == 'Done'
- end
- end.not_to raise_error
- end
-
- def master_branch_exists?
- project.repository_branches.map { |item| item[:name] }.include?(project.default_branch)
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb
index a1d8b495129..d6e9c1a13df 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
@@ -18,9 +18,7 @@ module QA
commit.branch = "development"
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: file_name, content: 'pssst!' }
- ])
+ commit.add_files([{ file_path: file_name, content: 'pssst!' }])
end
end
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 6ce4217f8ac..d975e18e962 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
@@ -20,12 +20,13 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = template_project
commit.commit_message = 'Add custom merge request template'
- commit.add_files([
- {
- file_path: ".gitlab/merge_request_templates/#{template_name}.md",
- content: template_content
- }
- ])
+ commit.add_files(
+ [
+ {
+ file_path: ".gitlab/merge_request_templates/#{template_name}.md",
+ content: template_content
+ }
+ ])
end
end
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 8885163b5e3..205ff12ff03 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
@@ -16,9 +16,7 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: file_name, content: 'pssst!' }
- ])
+ commit.add_files([{ file_path: file_name, content: 'pssst!' }])
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb
new file mode 100644
index 00000000000..37e737a4f84
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Testing wiki content creation inside a project' do
+ let(:new_wiki_title) { "just_another_wiki_page" }
+ let(:new_wiki_content) { "this content is changed or added" }
+ let(:commit_message) { "this is a new addition to the wiki" }
+
+ let(:project) { Resource::Project.fabricate_via_api! }
+ let(:wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ 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)
+ Page::Project::Wiki::Show.perform(&:click_create_your_first_page)
+
+ Page::Project::Wiki::Edit.perform do |edit|
+ edit.set_title new_wiki_title
+ edit.set_content new_wiki_content
+ edit.set_message commit_message
+ end
+
+ Page::Project::Wiki::Edit.perform(&:click_submit)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title new_wiki_title
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+
+ 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)
+
+ Page::Project::Wiki::Edit.perform do |edit|
+ edit.set_title new_wiki_title
+ edit.set_content new_wiki_content
+ edit.set_message commit_message
+ end
+
+ Page::Project::Wiki::Edit.perform(&:click_submit)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title new_wiki_title
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+
+ 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
+
+ Resource::Repository::WikiPush.fabricate! do |push|
+ push.file_name = "#{new_wiki_title}.md"
+ push.file_content = new_wiki_content
+ push.commit_message = commit_message
+ push.wiki = empty_wiki
+ push.new_branch = true
+ end.visit!
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title new_wiki_title
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+
+ 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
+ push.commit_message = commit_message
+ push.wiki = wiki
+ push.new_branch = false
+ end.visit!
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title new_wiki_title
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb
new file mode 100644
index 00000000000..a4bdb0193dd
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Testing wiki content manipulation inside a project' do
+ let(:new_wiki_title) { "just_another_wiki_page" }
+ let(:new_wiki_content) { "this content is changed or added" }
+ let(:commit_message) { "this is a new addition to the wiki" }
+
+ let(:wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ 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)
+
+ Page::Project::Wiki::Edit.perform do |edit|
+ edit.set_title new_wiki_title
+ edit.set_content new_wiki_content
+ edit.set_message commit_message
+ end
+
+ Page::Project::Wiki::Edit.perform(&:click_submit)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title new_wiki_title
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+
+ 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
+ push.wiki = wiki
+ push.new_branch = false
+ end.visit!
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_content new_wiki_content
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb
new file mode 100644
index 00000000000..0af964fc4bf
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'A project wiki' do
+ let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
+ let(:new_path) { "a/new/path-with-spaces" }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'can change the directory path of a page',
+testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347821' do
+ initial_wiki.visit!
+
+ Page::Project::Wiki::Show.perform(&:click_edit)
+
+ Page::Project::Wiki::Edit.perform do |edit|
+ edit.set_title("#{new_path}/home")
+ edit.set_message('changing the path of the home page')
+ end
+
+ Page::Project::Wiki::Edit.perform(&:click_submit)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_directory('a')
+ expect(wiki).to have_directory('new')
+ expect(wiki).to have_directory('path with spaces')
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb
new file mode 100644
index 00000000000..361fc459d54
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create', :reliable do
+ describe 'Testing project wiki file upload' 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' }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ after do
+ initial_wiki.project.remove_via_api!
+ end
+
+ it 'by creating a formatted 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.add_heading('Heading 1', heading_text)
+ edit.upload_image(File.absolute_path(File.join('qa', 'fixtures', 'designs', image_file_name)))
+ end
+
+ Page::Project::Wiki::Edit.perform(&:click_submit)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ aggregate_failures 'page shows expected content' do
+ expect(wiki).to have_title(page_title)
+ expect(wiki).to have_heading('h1', heading_text)
+ expect(wiki).to have_image(image_file_name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb
new file mode 100644
index 00000000000..5c9b97659a7
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Project Wiki' do
+ let(:small_number_of_pages) { 5 }
+ let(:large_number_of_pages) { 15 }
+ let(:random_page) { "bulk_#{rand(0..4)}" }
+
+ let(:small_wiki) { create_wiki_pages small_number_of_pages }
+ let(:large_wiki) { create_wiki_pages large_number_of_pages }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ context 'with Wiki Sidebar' 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|
+ Page::Project::Wiki::Show.perform do |list|
+ expect(list).to have_page_listed "bulk_#{index}"
+ end
+ end
+
+ Page::Project::Wiki::Show.perform do |list|
+ list.click_page_link random_page
+ end
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title random_page
+ end
+ end
+ end
+
+ context 'with Wiki Page List' 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)
+
+ large_number_of_pages.times do |index|
+ Page::Project::Wiki::List.perform do |list|
+ expect(list).to have_page_listed "bulk_#{index}"
+ end
+ end
+
+ Page::Project::Wiki::List.perform do |list|
+ list.click_page_link random_page
+ end
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_title random_page
+ end
+ end
+ end
+
+ private
+
+ def create_wiki_pages(no_of_pages)
+ wiki = Resource::Wiki::ProjectPage.fabricate_via_api!
+ no_of_pages.times do |index|
+ Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
+ page.title = "bulk_#{index}"
+ page.project = wiki.project
+ end
+ end
+ wiki
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb
new file mode 100644
index 00000000000..13e04180ab5
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Testing project wiki'
+ let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'can delete a page',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347815' do
+ initial_wiki.visit!
+
+ Page::Project::Wiki::Show.perform(&:click_edit)
+ Page::Project::Wiki::Edit.perform(&:delete_page)
+
+ Page::Project::Wiki::Show.perform do |wiki|
+ expect(wiki).to have_no_page
+ end
+ end
+ end
+end
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 aa332a76c94..0503b1b3761 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
@@ -22,9 +22,7 @@ module QA
commit.branch = branch_name
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
- commit.add_files([
- { file_path: 'test-folder/test-file.md', content: 'new content' }
- ])
+ commit.add_files([{ file_path: 'test-folder/test-file.md', content: 'new content' }])
end
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb
new file mode 100644
index 00000000000..50df8afafaf
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Repository License Detection', product_group: :source_code do
+ after do
+ project.remove_via_api!
+ end
+
+ let(:project) { Resource::Project.fabricate_via_api! }
+
+ shared_examples 'project license detection' do
+ it 'displays the name of the license on the repository' do
+ license_path = File.expand_path("../../../../../fixtures/software_licenses/#{license_file_name}", __dir__)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.add_files([{ file_path: 'LICENSE', content: File.read(license_path) }])
+ end
+
+ project.visit!
+
+ Page::Project::Show.perform do |show|
+ expect(show).to have_license(rendered_license_name)
+ end
+ end
+ end
+
+ context 'on a project with a commonly used LICENSE',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366842' do
+ it_behaves_like 'project license detection' do
+ let(:license_file_name) { 'bsd-3-clause' }
+ let(:rendered_license_name) { 'BSD 3-Clause "New" or "Revised" License' }
+ end
+ end
+
+ context 'on a project with an unrecognized LICENSE',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366843' do
+ it_behaves_like 'project license detection' do
+ let(:license_file_name) { 'other' }
+ let(:rendered_license_name) { 'LICENSE' }
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/license_detecton_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/license_detecton_spec.rb
deleted file mode 100644
index 1ae1dd87c07..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/repository/license_detecton_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- describe 'Repository License Detection', product_group: :source_code do
- after do
- project.remove_via_api!
- end
-
- let(:project) { Resource::Project.fabricate_via_api! }
-
- shared_examples 'project license detection' do
- it 'displays the name of the license on the repository' do
- license_path = File.expand_path("../../../../../fixtures/software_licenses/#{license_file_name}", __dir__)
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.add_files([{ file_path: 'LICENSE', content: File.read(license_path) }])
- end
-
- project.visit!
-
- Page::Project::Show.perform do |show|
- expect(show).to have_license(rendered_license_name)
- end
- end
- end
-
- context 'on a project with a commonly used LICENSE',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366842' do
- it_behaves_like 'project license detection' do
- let(:license_file_name) { 'bsd-3-clause' }
- let(:rendered_license_name) { 'BSD 3-Clause "New" or "Revised" License' }
- end
- end
-
- context 'on a project with a less commonly used LICENSE',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366843' do
- it_behaves_like 'project license detection' do
- let(:license_file_name) { 'GFDL-1.2-only' }
- let(:rendered_license_name) { 'Other' }
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
index 65a15ce96a5..f4ca7955a0f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
@@ -31,7 +31,6 @@ module QA
Page::Project::Tag::Show.perform do |show|
expect(show).to have_tag_name(tag_name)
expect(show).to have_tag_message(tag_message)
- expect(show).to have_tag_release_notes(tag_release_notes)
expect(show).not_to have_element(:create_tag_button)
end
end
@@ -83,7 +82,6 @@ module QA
Page::Project::Tag::New.perform do |new_tag|
new_tag.fill_tag_name(name)
new_tag.fill_tag_message(message)
- new_tag.fill_release_notes(release_notes)
new_tag.click_create_tag_button
end
end
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 9735aa7959a..561a5a2cc1c 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
@@ -22,12 +22,13 @@ module QA
before do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
- commit.add_files([
- {
- file_path: 'first_directory/test_file.txt',
- content: "Test file content"
- }
- ])
+ commit.add_files(
+ [
+ {
+ file_path: 'first_directory/test_file.txt',
+ content: "Test file content"
+ }
+ ])
end
project.visit!
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 fc5754e2c7a..f03c651992c 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
@@ -4,18 +4,18 @@ module QA
RSpec.describe 'Create' do
describe 'Open Web IDE from Diff Tab' do
files = [
- {
- file_path: 'file1',
- content: 'test1'
- },
- {
- file_path: 'file2',
- content: 'test2'
- },
- {
- file_path: 'file3',
- content: 'test3'
- }
+ {
+ file_path: 'file1',
+ content: 'test1'
+ },
+ {
+ file_path: 'file2',
+ content: 'test2'
+ },
+ {
+ file_path: 'file3',
+ content: 'test3'
+ }
]
let(:project) do
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
deleted file mode 100644
index 4b8edf8b792..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', :reliable do
- 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' }
-
- before do
- Flow::Login.sign_in
- end
-
- after do
- initial_wiki.project.remove_via_api!
- end
-
- 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.add_heading('Heading 1', heading_text)
- edit.upload_image(File.absolute_path(File.join('qa', 'fixtures', 'designs', image_file_name)))
- end
-
- Page::Project::Wiki::Edit.perform(&:click_submit)
-
- Page::Project::Wiki::Show.perform do |wiki|
- aggregate_failures 'page shows expected content' do
- expect(wiki).to have_title(page_title)
- expect(wiki).to have_heading('h1', heading_text)
- expect(wiki).to have_image(image_file_name)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
deleted file mode 100644
index 648ef513e12..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Wiki' do
- describe 'testing wiki content creation inside a project' do
- let(:new_wiki_title) { "just_another_wiki_page" }
- let(:new_wiki_content) { "this content is changed or added" }
- let(:commit_message) { "this is a new addition to the wiki" }
-
- let(:project) { Resource::Project.fabricate_via_api! }
- let(:wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
-
- before do
- Flow::Login.sign_in
- end
-
- 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)
- Page::Project::Wiki::Show.perform(&:click_create_your_first_page)
-
- Page::Project::Wiki::Edit.perform do |edit|
- edit.set_title new_wiki_title
- edit.set_content new_wiki_content
- edit.set_message commit_message
- end
-
- Page::Project::Wiki::Edit.perform(&:click_submit)
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title new_wiki_title
- expect(wiki).to have_content new_wiki_content
- end
- end
-
- 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)
-
- Page::Project::Wiki::Edit.perform do |edit|
- edit.set_title new_wiki_title
- edit.set_content new_wiki_content
- edit.set_message commit_message
- end
-
- Page::Project::Wiki::Edit.perform(&:click_submit)
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title new_wiki_title
- expect(wiki).to have_content new_wiki_content
- end
- end
-
- 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
-
- Resource::Repository::WikiPush.fabricate! do |push|
- push.file_name = "#{new_wiki_title}.md"
- push.file_content = new_wiki_content
- push.commit_message = commit_message
- push.wiki = empty_wiki
- push.new_branch = true
- end.visit!
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title new_wiki_title
- expect(wiki).to have_content new_wiki_content
- end
- end
-
- 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
- push.commit_message = commit_message
- push.wiki = wiki
- push.new_branch = false
- end.visit!
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title new_wiki_title
- expect(wiki).to have_content new_wiki_content
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 251728c149f..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Wiki' do
- describe 'testing wiki content manipulation inside a project' do
- let(:new_wiki_title) { "just_another_wiki_page" }
- let(:new_wiki_content) { "this content is changed or added" }
- let(:commit_message) { "this is a new addition to the wiki" }
-
- let(:wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
-
- before do
- Flow::Login.sign_in
- end
-
- 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)
-
- Page::Project::Wiki::Edit.perform do |edit|
- edit.set_title new_wiki_title
- edit.set_content new_wiki_content
- edit.set_message commit_message
- end
-
- Page::Project::Wiki::Edit.perform(&:click_submit)
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title new_wiki_title
- expect(wiki).to have_content new_wiki_content
- end
- end
-
- 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
- push.wiki = wiki
- push.new_branch = false
- end.visit!
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_content new_wiki_content
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 2d24f69c883..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Wiki' do
- let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
- let(:new_path) { "a/new/path-with-spaces" }
-
- before do
- Flow::Login.sign_in
- end
-
- 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)
-
- Page::Project::Wiki::Edit.perform do |edit|
- edit.set_title("#{new_path}/home")
- edit.set_message('changing the path of the home page')
- end
-
- Page::Project::Wiki::Edit.perform(&:click_submit)
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_directory('a')
- expect(wiki).to have_directory('new')
- expect(wiki).to have_directory('path with spaces')
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 703d425079d..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Wiki' do
- let(:small_number_of_pages) { 5 }
- let(:large_number_of_pages) { 15 }
- let(:random_page) { "bulk_#{rand(0..4)}" }
-
- let(:small_wiki) { create_wiki_pages small_number_of_pages }
- let(:large_wiki) { create_wiki_pages large_number_of_pages }
-
- before do
- Flow::Login.sign_in
- end
-
- context 'Sidebar' 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|
- Page::Project::Wiki::Show.perform do |list|
- expect(list).to have_page_listed "bulk_#{index}"
- end
- end
-
- Page::Project::Wiki::Show.perform do |list|
- list.click_page_link random_page
- end
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title random_page
- end
- end
- end
-
- context 'Page List' 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)
-
- large_number_of_pages.times do |index|
- Page::Project::Wiki::List.perform do |list|
- expect(list).to have_page_listed "bulk_#{index}"
- end
- end
-
- Page::Project::Wiki::List.perform do |list|
- list.click_page_link random_page
- end
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_title random_page
- end
- end
- end
-
- private
-
- def create_wiki_pages(no_of_pages)
- wiki = Resource::Wiki::ProjectPage.fabricate_via_api!
- no_of_pages.times do |index|
- Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
- page.title = "bulk_#{index}"
- page.project = wiki.project
- end
- end
- wiki
- end
- end
- end
-end
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
deleted file mode 100644
index 78d6d51f260..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Wiki' do
- let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
-
- before do
- Flow::Login.sign_in
- end
-
- context 'Page deletion' 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)
- Page::Project::Wiki::Edit.perform(&:delete_page)
-
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_no_page
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_status_emails_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_status_emails_spec.rb
deleted file mode 100644
index f4794b3a904..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_status_emails_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.shared_examples 'notifies on a pipeline' do |exit_code|
- before do
- push_commit(exit_code: exit_code)
- end
-
- it 'sends an email' do
- meta = exit_code_meta(exit_code)
-
- project.visit!
- Flow::Pipeline.wait_for_latest_pipeline(status: meta[:status])
-
- messages = mail_hog_messages(mail_hog)
- subjects = messages.map(&:subject)
- targets = messages.map(&:to)
-
- aggregate_failures do
- expect(subjects).to include(meta[:email_subject])
- expect(subjects).to include(/#{Regexp.escape(project.name)}/)
- expect(targets).to include(*emails)
- end
- end
- end
-
- RSpec.describe 'Verify', :orchestrated, :runner, :requires_admin, :smtp do
- describe 'Pipeline status emails' do
- let(:executor) { "qa-runner-#{Time.now.to_i}" }
- let(:emails) { %w[foo@bar.com baz@buzz.com] }
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'pipeline-status-project'
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.project = project
- runner.name = executor
- runner.tags = [executor]
- end
- end
-
- let(:mail_hog) { Vendor::MailHog::API.new }
-
- before(:all) do
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
- end
-
- before do
- setup_pipeline_emails(emails)
- end
-
- describe 'when pipeline passes', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366240' do
- include_examples 'notifies on a pipeline', 0
- end
-
- describe 'when pipeline fails', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366241' do
- include_examples 'notifies on a pipeline', 1
- end
-
- def push_commit(exit_code: 0)
- 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(exit_code: exit_code)
- }
- ]
- )
- end
- end
-
- def setup_pipeline_emails(emails)
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
-
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- QA::Page::Project::Settings::Integrations.perform(&:click_pipelines_email_link)
-
- QA::Page::Project::Settings::Services::PipelineStatusEmails.perform do |pipeline_status_emails|
- pipeline_status_emails.toggle_notify_broken_pipelines # notify on pass and fail
- pipeline_status_emails.set_recipients(emails)
- pipeline_status_emails.click_save_button
- end
- end
-
- def gitlab_ci_yaml(exit_code: 0, tag: executor)
- <<~YAML
- test-pipeline-email:
- tags:
- - #{tag}
- script: sleep 5; exit #{exit_code};
- YAML
- end
-
- private
-
- def exit_code_meta(exit_code)
- {
- 0 => { status: 'passed', email_subject: /Successful pipeline/ },
- 1 => { status: 'failed', email_subject: /Failed pipeline/ }
- }[exit_code]
- end
-
- def mail_hog_messages(mail_hog_api)
- Support::Retrier.retry_until(sleep_interval: 1) do
- Runtime::Logger.debug('Fetching email...')
-
- messages = mail_hog_api.fetch_messages
- logs = messages.map { |m| "#{m.to}: #{m.subject}" }
-
- Runtime::Logger.debug("MailHog Logs: #{logs.join("\n")}")
-
- # for failing pipelines we have three messages
- # one for the owner
- # and one for each recipient
- messages if mail_hog_pipeline_count(messages) >= 2
- end
- end
-
- def mail_hog_pipeline_count(messages)
- messages.count { |message| message.subject.include?('pipeline') }
- end
- end
- end
-end
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 078465770c6..222d1993bf4 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
@@ -51,16 +51,11 @@ module QA
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: helm_upload_yaml
- },
- {
- file_path: 'Chart.yaml',
- content: helm_chart_yaml
- }
- ])
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: helm_upload_yaml },
+ { file_path: 'Chart.yaml', content: helm_chart_yaml }
+ ])
end
end
@@ -94,12 +89,7 @@ module QA
commit.project = client_project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: helm_install_yaml
- }
- ])
+ commit.add_files([{ file_path: '.gitlab-ci.yml', content: helm_install_yaml }])
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
index 921b36b34af..690451f6147 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
@@ -48,26 +48,18 @@ module QA
it 'pushes and pulls a maven package', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
- maven_upload_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_upload_package.yaml.erb')).result(binding)
- package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
- settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/group/producer', 'gitlab_ci.yaml.erb')).result(binding)
+ pom_xml = ERB.new(read_fixture('package_managers/maven/group/producer', 'pom.xml.erb')).result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven/group/producer', 'settings.xml.erb')).result(binding)
commit.project = package_project
commit.commit_message = 'Add files'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: maven_upload_package_yaml
- },
- {
- file_path: 'pom.xml',
- content: package_pom_xml
- },
- {
- file_path: 'settings.xml',
- content: settings_xml
- }
- ])
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'pom.xml', content: pom_xml },
+ { file_path: 'settings.xml', content: settings_xml }
+ ])
end
end
@@ -97,26 +89,18 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
- maven_install_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_install_package.yaml.erb')).result(binding)
- client_pom_xml = ERB.new(read_fixture('package_managers/maven', 'client_pom.xml.erb')).result(binding)
- settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/group/consumer', 'gitlab_ci.yaml.erb')).result(binding)
+ pom_xml = ERB.new(read_fixture('package_managers/maven/group/consumer', 'pom.xml.erb')).result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven/group/consumer', 'settings.xml.erb')).result(binding)
commit.project = client_project
commit.commit_message = 'Add files'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: maven_install_package_yaml
- },
- {
- file_path: 'pom.xml',
- content: client_pom_xml
- },
- {
- file_path: 'settings.xml',
- content: settings_xml
- }
- ])
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'pom.xml', content: pom_xml },
+ { file_path: 'settings.xml', content: settings_xml }
+ ])
end
end
@@ -143,123 +127,57 @@ module QA
end
context 'when disabled' do
- where do
- {
- 'using a personal access token' => {
- authentication_token_type: :personal_access_token,
- maven_header_name: 'Private-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347581'
- },
- 'using a project deploy token' => {
- authentication_token_type: :project_deploy_token,
- maven_header_name: 'Deploy-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347584'
- },
- 'using a ci job token' => {
- authentication_token_type: :ci_job_token,
- maven_header_name: 'Job-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347578'
- }
- }
+ before do
+ Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_disabled)
end
- with_them do
- let(:token) do
- case authentication_token_type
- when :personal_access_token
- personal_access_token
- when :ci_job_token
- '${env.CI_JOB_TOKEN}'
- when :project_deploy_token
- project_deploy_token.token
- end
- end
+ it 'prevents users from publishing duplicates' do
+ create_duplicated_package
- before do
- Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_disabled)
- end
+ push_duplicated_package
- it 'prevents users from publishing group level Maven packages duplicates', testcase: params[:testcase] do
- create_duplicated_package
-
- push_duplicated_package
-
- client_project.visit!
+ client_project.visit!
- show_latest_deploy_job
+ show_latest_deploy_job
- Page::Project::Job::Show.perform do |job|
- expect(job).not_to be_successful(timeout: 800)
- end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).not_to be_successful(timeout: 800)
end
end
end
context 'when enabled' do
- where do
- {
- 'using a personal access token' => {
- authentication_token_type: :personal_access_token,
- maven_header_name: 'Private-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347580'
- },
- 'using a project deploy token' => {
- authentication_token_type: :project_deploy_token,
- maven_header_name: 'Deploy-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347583'
- },
- 'using a ci job token' => {
- authentication_token_type: :ci_job_token,
- maven_header_name: 'Job-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347577'
- }
- }
+ before do
+ Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled)
end
- with_them do
- let(:token) do
- case authentication_token_type
- when :personal_access_token
- personal_access_token
- when :ci_job_token
- '${env.CI_JOB_TOKEN}'
- when :project_deploy_token
- project_deploy_token.token
- end
- end
-
- before do
- Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled)
- end
-
- it 'allows users to publish group level Maven packages duplicates', testcase: params[:testcase] do
- create_duplicated_package
+ it 'allows users to publish duplicates' do
+ create_duplicated_package
- push_duplicated_package
+ push_duplicated_package
- show_latest_deploy_job
+ show_latest_deploy_job
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
end
end
end
def create_duplicated_package
- settings_xml_with_pat = ERB.new(read_fixture('package_managers/maven', 'settings_with_pat.xml.erb')).result(binding)
- package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
+ settings_xml_with_pat = ERB.new(read_fixture('package_managers/maven/group', 'settings_with_pat.xml.erb')).result(binding)
+ pom_xml = ERB.new(read_fixture('package_managers/maven/group/producer', 'pom.xml.erb')).result(binding)
with_fixtures([
- {
- file_path: 'pom.xml',
- content: package_pom_xml
- },
- {
- file_path: 'settings.xml',
- content: settings_xml_with_pat
- }
- ]) do |dir|
+ {
+ file_path: 'pom.xml',
+ content: pom_xml
+ },
+ {
+ file_path: 'settings.xml',
+ content: settings_xml_with_pat
+ }
+ ]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
end
@@ -275,26 +193,18 @@ module QA
def push_duplicated_package
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
- maven_upload_package_yaml = ERB.new(read_fixture('package_managers/maven', 'maven_upload_package.yaml.erb')).result(binding)
- package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
- settings_xml = ERB.new(read_fixture('package_managers/maven', 'settings.xml.erb')).result(binding)
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/group/producer', 'gitlab_ci.yaml.erb')).result(binding)
+ pom_xml = ERB.new(read_fixture('package_managers/maven/group/producer', 'pom.xml.erb')).result(binding)
+ settings_xml_with_pat = ERB.new(read_fixture('package_managers/maven/group', 'settings_with_pat.xml.erb')).result(binding)
commit.project = client_project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: maven_upload_package_yaml
- },
- {
- file_path: 'pom.xml',
- content: package_pom_xml
- },
- {
- file_path: 'settings.xml',
- content: settings_xml
- }
- ])
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'pom.xml', content: pom_xml },
+ { file_path: 'settings.xml', content: settings_xml_with_pat }
+ ])
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
index 13607ba1b41..324e881f160 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
@@ -1,8 +1,14 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage, :reliable do
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage, :reliable,
+ feature_flag: {
+ name: 'maven_central_request_forwarding',
+ scope: :global
+ } do
describe 'Maven project level endpoint' do
+ include Runtime::Fixtures
+
let(:group_id) { 'com.gitlab.qa' }
let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" }
let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
@@ -51,54 +57,6 @@ module QA
end
end
- let(:gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy-and-install:
- image: maven:3.6-jdk-11
- script:
- - 'mvn deploy -s settings.xml'
- - 'mvn install -s settings.xml'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.name}"
- YAML
- }
- end
-
- let(:pom_file) do
- {
- file_path: 'pom.xml',
- content: <<~XML
- <project>
- <groupId>#{group_id}</groupId>
- <artifactId>#{artifact_id}</artifactId>
- <version>#{package_version}</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/-/packages/maven</url>
- </repository>
- </repositories>
- <distributionManagement>
- <repository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>#{package_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
- </snapshotRepository>
- </distributionManagement>
- </project>
- XML
- }
- end
-
before do
Flow::Login.sign_in_unless_signed_in
runner
@@ -142,40 +100,24 @@ module QA
end
end
- let(:settings_xml) do
- {
- file_path: 'settings.xml',
- content: <<~XML
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>#{package_project.name}</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>#{maven_header_name}</name>
- <value>#{token}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
- XML
- }
- end
-
it 'pushes and pulls a maven package via maven', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/project', 'gitlab_ci.yaml.erb'))
+ .result(binding)
+ pom_xml = ERB.new(read_fixture('package_managers/maven/project', 'pom.xml.erb'))
+ .result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven/project', 'settings.xml.erb'))
+ .result(binding)
+
commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_file,
- pom_file,
- settings_xml
- ])
+ commit.commit_message = 'Add files'
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'pom.xml', content: pom_xml },
+ { file_path: 'settings.xml', content: settings_xml }
+ ])
end
end
@@ -184,17 +126,7 @@ module QA
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
-
- job.click_element(:pipeline_path)
- end
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('install')
+ pipeline.click_job('deploy-and-install')
end
Page::Project::Job::Show.perform do |job|
@@ -215,5 +147,107 @@ module QA
end
end
end
+
+ describe 'Maven request forwarding' do
+ include Runtime::Fixtures
+
+ let(:group_id) { 'com.gitlab.qa' }
+ let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" }
+ let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
+ let(:package_version) { '1.3.7' }
+ let(:package_type) { 'maven' }
+ let(:personal_access_token) { Runtime::Env.personal_access_token }
+ let(:group) { Resource::Group.fabricate_via_api! }
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = package_name
+ package.project = imported_project
+ end
+ end
+
+ let(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{imported_project.name}"]
+ runner.executor = :docker
+ runner.token = group.reload!.runners_token
+ end
+ end
+
+ let(:imported_project) do
+ Resource::ProjectImportedFromURL.fabricate_via_browser_ui! do |project|
+ project.name = "#{package_type}_imported_project"
+ project.group = group
+ project.gitlab_repository_path = 'https://gitlab.com/gitlab-org/quality/imported-projects/maven.git'
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(:maven_central_request_forwarding)
+ Flow::Login.sign_in_unless_signed_in
+
+ imported_project
+ runner
+ end
+
+ after do
+ Runtime::Feature.disable(:maven_central_request_forwarding)
+
+ runner.remove_via_api!
+ package.remove_via_api!
+ imported_project.remove_via_api!
+ end
+
+ it(
+ 'uses GitLab as a mirror of the central proxy',
+ :skip_live_env,
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/378221',
+ type: :investigating
+ },
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/375767'
+ ) do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/project/request_forwarding',
+ 'gitlab_ci.yaml.erb'
+ )
+ )
+ .result(binding)
+ settings_xml = ERB.new(read_fixture('package_managers/maven/project/request_forwarding',
+ 'settings.xml.erb'
+ )
+ )
+ .result(binding)
+
+ commit.project = imported_project
+ commit.commit_message = 'Add files'
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'settings.xml', content: settings_xml }
+ ])
+ end
+ end
+
+ imported_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+ end
end
end
diff --git a/qa/qa/specs/features/browser_ui/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 45693ecee41..22052aa4110 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
@@ -34,20 +34,15 @@ module QA
it 'pushes and pulls a maven package via gradle', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
- gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven', 'gradle_upload_package.yaml.erb')).result(binding)
- build_upload_gradle = ERB.new(read_fixture('package_managers/maven', 'build_upload.gradle.erb')).result(binding)
+ gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_package.yaml.erb')).result(binding)
+ build_upload_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_upload.gradle.erb')).result(binding)
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: gradle_upload_yaml
- },
- {
- file_path: 'build.gradle',
- content: build_upload_gradle
- }
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gradle_upload_yaml },
+ { file_path: 'build.gradle', content: build_upload_gradle }
])
end
end
@@ -78,21 +73,16 @@ module QA
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
- gradle_install_yaml = ERB.new(read_fixture('package_managers/maven', 'gradle_install_package.yaml.erb')).result(binding)
- build_install_gradle = ERB.new(read_fixture('package_managers/maven', 'build_install.gradle.erb')).result(binding)
+ gradle_install_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_install_package.yaml.erb')).result(binding)
+ build_install_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_install.gradle.erb')).result(binding)
commit.project = client_project
commit.commit_message = 'Add files'
- commit.add_files([
- {
- file_path: '.gitlab-ci.yml',
- content: gradle_install_yaml
- },
- {
- file_path: 'build.gradle',
- content: build_install_gradle
- }
- ])
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gradle_install_yaml },
+ { file_path: 'build.gradle', content: build_install_gradle }
+ ])
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
index f229f30facc..e2a7006249d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
@@ -105,14 +105,7 @@ module QA
nuget_upload_yaml = ERB.new(read_fixture('package_managers/nuget', 'nuget_upload_package.yaml.erb')).result(binding)
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: nuget_upload_yaml
- }
- ]
- )
+ commit.update_files([{ file_path: '.gitlab-ci.yml', content: nuget_upload_yaml }])
end
end
@@ -137,9 +130,9 @@ module QA
commit.commit_message = 'Add new csproj file'
commit.add_files(
[
- {
- file_path: 'otherdotnet.csproj',
- content: <<~EOF
+ {
+ file_path: 'otherdotnet.csproj',
+ content: <<~EOF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@@ -148,18 +141,11 @@ module QA
</PropertyGroup>
</Project>
- EOF
- }
- ]
- )
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: nuget_install_yaml
- }
+ EOF
+ }
]
)
+ commit.update_files([{ file_path: '.gitlab-ci.yml', content: nuget_install_yaml }])
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
index e70b95db1a5..620bb7e4988 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
@@ -101,9 +101,9 @@ module QA
commit.commit_message = 'Add files'
commit.update_files(
[
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
stages:
- deploy
- install
@@ -132,11 +132,11 @@ module QA
- if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
tags:
- "runner-for-#{project.name}"
- YAML
- },
- {
- file_path: 'dotnetcore.csproj',
- content: <<~EOF
+ YAML
+ },
+ {
+ file_path: 'dotnetcore.csproj',
+ content: <<~EOF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@@ -145,8 +145,8 @@ module QA
</PropertyGroup>
</Project>
- EOF
- }
+ EOF
+ }
]
)
end
diff --git a/qa/qa/specs/features/sanity/framework_spec.rb b/qa/qa/specs/features/sanity/framework_spec.rb
index feec56478c0..fa34f525a85 100644
--- a/qa/qa/specs/features/sanity/framework_spec.rb
+++ b/qa/qa/specs/features/sanity/framework_spec.rb
@@ -6,7 +6,7 @@ module QA
it 'succeeds' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- expect(page).to have_text('A complete DevOps platform')
+ expect(page).to have_text('GitLab')
end
end
diff --git a/qa/qa/specs/qa_deprecation_toolkit_env.rb b/qa/qa/specs/qa_deprecation_toolkit_env.rb
index 21ef5a6f229..5224a2e9ae0 100644
--- a/qa/qa/specs/qa_deprecation_toolkit_env.rb
+++ b/qa/qa/specs/qa_deprecation_toolkit_env.rb
@@ -5,20 +5,24 @@ require 'deprecation_toolkit/rspec'
require 'concurrent/utility/monotonic_time'
require 'active_support/gem_version'
-module QaDeprecationToolkitEnv
- # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
- # rubocop:disable Layout/LineLength
- def self.kwargs_warning
- %r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
- end
- # rubocop:enable Layout/LineLength
+module QA
+ module Specs
+ class QaDeprecationToolkitEnv
+ # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
+ # rubocop:disable Layout/LineLength
+ def self.kwargs_warning
+ %r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
+ end
+ # rubocop:enable Layout/LineLength
- def self.configure!
- # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7
- Warning[:deprecated] = true
+ def self.configure!
+ # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7
+ Warning[:deprecated] = true
- DeprecationToolkit::Configuration.test_runner = :rspec
- DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
- DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]
+ DeprecationToolkit::Configuration.test_runner = :rspec
+ DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
+ DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]
+ end
+ end
end
end
diff --git a/qa/qa/specs/spec_helper.rb b/qa/qa/specs/spec_helper.rb
index b9e67c2fa72..97901042883 100644
--- a/qa/qa/specs/spec_helper.rb
+++ b/qa/qa/specs/spec_helper.rb
@@ -2,8 +2,7 @@
require_relative '../../qa'
-require_relative 'qa_deprecation_toolkit_env'
-QaDeprecationToolkitEnv.configure!
+QA::Specs::QaDeprecationToolkitEnv.configure!
Knapsack::Adapters::RSpecAdapter.bind if QA::Runtime::Env.knapsack?
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 8fa6d3f23dc..ea19d9ef332 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -23,7 +23,7 @@ module QA
verify_ssl: false
}
- RestClient::Request.execute(default_args.merge(args))
+ RestClient::Request.execute(default_args.merge(with_canary(args)))
rescue StandardError => e
return_response_or_raise(e)
end
@@ -37,21 +37,22 @@ module QA
verify_ssl: false
}
- RestClient::Request.execute(
- default_args.merge(args)
- )
+ RestClient::Request.execute(default_args.merge(with_canary(args)))
rescue StandardError => e
return_response_or_raise(e)
end
end
- def patch(url, payload = nil)
+ def patch(url, payload = nil, args = {})
with_retry_on_too_many_requests do
- RestClient::Request.execute(
+ default_args = {
method: :patch,
url: url,
payload: payload,
- verify_ssl: false)
+ verify_ssl: false
+ }
+
+ RestClient::Request.execute(default_args.merge(with_canary(args)))
rescue StandardError => e
return_response_or_raise(e)
end
@@ -66,7 +67,7 @@ module QA
verify_ssl: false
}
- RestClient::Request.execute(default_args.merge(args))
+ RestClient::Request.execute(default_args.merge(with_canary(args)))
rescue StandardError => e
return_response_or_raise(e)
end
@@ -98,6 +99,14 @@ module QA
url.sub(/private_token=[^&]*/, "private_token=[****]")
end
+ # Merges the gitlab_canary cookie into existing cookies for mixed environment testing.
+ #
+ # @param [Hash] args the existing args passed to method
+ # @return [Hash] args or args with merged canary cookie if it exists
+ def with_canary(args)
+ args.deep_merge(cookies: QA::Runtime::Env.canary_cookie)
+ end
+
def with_retry_on_too_many_requests
response = nil
diff --git a/qa/qa/support/formatters/test_stats_formatter.rb b/qa/qa/support/formatters/test_stats_formatter.rb
index 9d19c2e8bb5..2cde2d0928e 100644
--- a/qa/qa/support/formatters/test_stats_formatter.rb
+++ b/qa/qa/support/formatters/test_stats_formatter.rb
@@ -84,6 +84,7 @@ module QA
job_url: QA::Runtime::Env.ci_job_url,
pipeline_url: env('CI_PIPELINE_URL'),
pipeline_id: env('CI_PIPELINE_ID'),
+ job_id: env('CI_JOB_ID'),
merge_request_iid: merge_request_iid
}
}
diff --git a/qa/qa/support/repeater.rb b/qa/qa/support/repeater.rb
index 6956987de05..26d447f8e0f 100644
--- a/qa/qa/support/repeater.rb
+++ b/qa/qa/support/repeater.rb
@@ -52,12 +52,13 @@ module QA
sleep_and_reload_if_needed(sleep_interval, reload_page)
attempts += 1
end
- rescue StandardError, RSpec::Expectations::ExpectationNotMetError
+ rescue StandardError, RSpec::Expectations::ExpectationNotMetError => e
raise unless retry_on_exception
attempts += 1
raise unless remaining_attempts?(attempts, max_attempts) && remaining_time?(start, max_duration)
+ QA::Runtime::Logger.debug("Retry block rescued following error: #{e}, trying again...")
sleep_and_reload_if_needed(sleep_interval, reload_page)
retry
end
diff --git a/qa/qa/tools/ci/non_empty_suites.rb b/qa/qa/tools/ci/non_empty_suites.rb
index 687c11a3e62..2319237fa25 100644
--- a/qa/qa/tools/ci/non_empty_suites.rb
+++ b/qa/qa/tools/ci/non_empty_suites.rb
@@ -10,42 +10,11 @@ module QA
class NonEmptySuites
include Helpers
- # rubocop:disable Layout/LineLength
- SCENARIOS = [
- { klass: "Test::Instance::All" },
- { klass: "Test::Instance::Smoke" },
- { klass: "Test::Instance::Reliable" },
- { klass: "Test::Instance::ReviewBlocking" },
- { klass: "Test::Instance::ReviewNonBlocking" },
- { klass: "Test::Instance::CloudActivation" },
- { klass: "Test::Instance::Integrations" },
- { klass: "Test::Instance::Jira" },
- { klass: "Test::Instance::LargeSetup" },
- { klass: "Test::Instance::Metrics" },
- { klass: "Test::Instance::ObjectStorage" },
- { klass: "Test::Instance::Packages" },
- { klass: "Test::Instance::RepositoryStorage" },
- { klass: "Test::Integration::ServicePingDisabled" },
- { klass: "Test::Integration::LDAPNoTLS" },
- { klass: "Test::Integration::LDAPTLS" },
- { klass: "Test::Integration::LDAPNoServer" },
- { klass: "Test::Integration::InstanceSAML" },
- { klass: "Test::Integration::RegistryWithCDN" },
- { klass: "Test::Integration::RegistryTLS" },
- { klass: "Test::Integration::Registry" },
- { klass: "Test::Integration::SMTP" },
- { klass: "QA::EE::Scenario::Test::Integration::Elasticsearch" },
- { klass: "QA::EE::Scenario::Test::Integration::GroupSAML" },
- {
- klass: "QA::EE::Scenario::Test::Geo",
- args: "--primary-address http://dummy1.test --primary-name gitlab-primary --secondary-address http://dummy2.test --secondary-name gitlab-secondary --without-setup"
- },
- {
- klass: "Test::Integration::Mattermost",
- args: "--mattermost-address http://mattermost.test"
- }
+ # @return [Array] scenarios that never run in package-and-test pipeline
+ IGNORED_SCENARIOS = [
+ "QA::EE::Scenario::Test::Geo",
+ "QA::Scenario::Test::Instance::Airgapped"
].freeze
- # rubocop:enable Layout/LineLength
def initialize(qa_tests)
@qa_tests = qa_tests
@@ -56,38 +25,58 @@ module QA
# @return [String]
def fetch
logger.info("Checking for runnable suites")
- scenarios = SCENARIOS.each_with_object([]) do |scenario, runnable_scenarios|
- logger.info(" fetching runnable specs for '#{scenario[:klass]}'")
+ scenarios.each_with_object([]) do |scenario, runnable_scenarios|
+ logger.info(" fetching runnable specs for '#{scenario}'")
+ next logger.info(" scenario is in ignore list, skipping") if IGNORED_SCENARIOS.include?(scenario)
- out, err, status = run_command(**scenario)
+ out, err, status = run_command(scenario)
unless status.success?
- logger.error(" example count failed!\n#{err}")
+ logger.error(" example count failed!\n#{err}")
next
end
count = out.split("\n").last.to_i
logger.info(" found #{count} examples to run")
- runnable_scenarios << scenario[:klass] if count > 0
- end
-
- scenarios.join(",")
+ runnable_scenarios << scenario if count > 0
+ end.join(",")
end
private
attr_reader :qa_tests
+ # Get all defined scenarios
+ #
+ # @return [Array<String>]
+ def scenarios
+ foss_scenarios = scenario_classes(QA::Scenario::Test)
+ return foss_scenarios unless QA.const_defined?("QA::EE")
+
+ foss_scenarios + scenario_classes(QA::EE::Scenario::Test)
+ end
+
+ # Fetch scenario classes recursively
+ #
+ # @param [Module] mod
+ # @return [Array<String>]
+ def scenario_classes(mod)
+ mod.constants.map do |const|
+ c = mod.const_get(const, false)
+ next c.to_s if c.is_a?(Class)
+
+ scenario_classes(c)
+ end.flatten
+ end
+
# Run scenario count command
#
# @param [String] klass
- # @param [String] args
# @return [String]
- def run_command(klass:, args: nil)
+ def run_command(klass)
cmd = ["bundle exec bin/qa"]
cmd << klass
cmd << "--count-examples-only --address http://dummy1.test"
- cmd << args if args
cmd << "-- #{qa_tests}" unless qa_tests.blank?
Open3.capture3(cmd.join(" "))
diff --git a/qa/qa/tools/ci/qa_changes.rb b/qa/qa/tools/ci/qa_changes.rb
index 75274961efe..784923714d6 100644
--- a/qa/qa/tools/ci/qa_changes.rb
+++ b/qa/qa/tools/ci/qa_changes.rb
@@ -11,17 +11,25 @@ module QA
QA_PATTERN = %r{^qa/}.freeze
SPEC_PATTERN = %r{^qa/qa/specs/features/}.freeze
-
- def initialize(mr_diff, mr_labels)
+ DEPENDENCY_PATTERN = Regexp.union(
+ /_VERSION/,
+ /Gemfile\.lock/,
+ /yarn\.lock/,
+ /Dockerfile\.assets/
+ )
+
+ def initialize(mr_diff, mr_labels, additional_group_spec_list)
@mr_diff = mr_diff
@mr_labels = mr_labels
+ @additional_group_spec_list = additional_group_spec_list
end
# Specific specs to run
#
# @return [String]
def qa_tests
- return if mr_diff.empty?
+ return if mr_diff.empty? || dependency_changes
+
# make paths relative to qa directory
return changed_files&.map { |path| path.delete_prefix("qa/") }&.join(" ") if only_spec_changes?
return qa_spec_directories_for_devops_stage&.join(" ") if non_qa_changes? && mr_labels.any?
@@ -73,6 +81,9 @@ module QA
# @return [Array]
attr_reader :mr_labels
+ # @return [Hash<String, Array<String>>]
+ attr_reader :additional_group_spec_list
+
# Are the changed files only qa specs?
#
# @return [Boolean] whether the changes files are only qa specs
@@ -94,6 +105,13 @@ module QA
mr_labels.find { |label| label =~ /^devops::/ }&.delete_prefix('devops::')
end
+ # Extract group name from MR labels
+ #
+ # @return [String] a group name
+ def group_name_from_mr_labels
+ mr_labels.find { |label| label =~ /^group::/ }&.delete_prefix('group::')
+ end
+
# Get qa spec directories for devops stage
#
# @return [Array] qa spec directories
@@ -101,14 +119,37 @@ module QA
devops_stage = devops_stage_from_mr_labels
return unless devops_stage
- Dir.glob("qa/specs/**/*/").select { |dir| dir =~ %r{\d+_#{devops_stage}/$} }
+ spec_dirs = stage_specs(devops_stage)
+
+ grp_name = group_name_from_mr_labels
+ return spec_dirs if grp_name.nil?
+
+ additional_grp_specs = additional_group_spec_list[grp_name]
+ return spec_dirs if additional_grp_specs.nil?
+
+ spec_dirs + stage_specs(*additional_grp_specs)
+ end
+
+ # Changes to gitlab dependencies
+ #
+ # @return [Boolean]
+ def dependency_changes
+ changed_files.any? { |file| file.match?(DEPENDENCY_PATTERN) }
end
# Change files in merge request
#
# @return [Array<String>]
def changed_files
- @changed_files ||= mr_diff.map { |change| change[:path] } # rubocop:disable Rails/Pluck
+ @changed_files ||= mr_diff.map { |change| change[:path] }
+ end
+
+ # Devops stage specs
+ #
+ # @param [Array<String>] devops_stages
+ # @return [Array]
+ def stage_specs(*devops_stages)
+ Dir.glob("qa/specs/**/*/").select { |dir| dir =~ %r{\d+_(#{devops_stages.join('|')})/$} }
end
end
end
diff --git a/qa/qa/tools/delete_test_ssh_keys.rb b/qa/qa/tools/delete_test_ssh_keys.rb
index 9e5728a5509..c10188eae6d 100644
--- a/qa/qa/tools/delete_test_ssh_keys.rb
+++ b/qa/qa/tools/delete_test_ssh_keys.rb
@@ -12,7 +12,7 @@
module QA
module Tools
- class DeleteTestSSHKeys
+ class DeleteTestSshKeys
include Support::API
ITEMS_PER_PAGE = '100'
diff --git a/qa/qa/tools/initialize_gitlab_auth.rb b/qa/qa/tools/initialize_gitlab_auth.rb
index 18e90f0d739..6d586f95ecf 100644
--- a/qa/qa/tools/initialize_gitlab_auth.rb
+++ b/qa/qa/tools/initialize_gitlab_auth.rb
@@ -6,7 +6,7 @@ module QA
# Also creates a personal access token
# @example
# $ bundle exec rake 'initialize_gitlab_auth[http://gitlab.test]'
- class InitializeGitLabAuth
+ class InitializeGitlabAuth
attr_reader :address
def initialize(address:)
diff --git a/qa/qa/tools/test_resources_handler.rb b/qa/qa/tools/test_resources_handler.rb
index 60c6dbfc16c..068fe37a37b 100644
--- a/qa/qa/tools/test_resources_handler.rb
+++ b/qa/qa/tools/test_resources_handler.rb
@@ -25,13 +25,17 @@ module QA
module Tools
class TestResourcesHandler
include Support::API
-
- IGNORED_RESOURCES = [
- 'QA::Resource::CiVariable',
- 'QA::Resource::Repository::Commit',
- 'QA::EE::Resource::GroupIteration',
- 'QA::EE::Resource::Settings::Elasticsearch',
- 'QA::EE::Resource::VulnerabilityItem'
+ include Ci::Helpers
+
+ IGNORED_RESOURCES = %w[
+ QA::Resource::CiVariable
+ QA::Resource::Repository::Commit
+ QA::Resource::Design
+ QA::EE::Resource::GroupIteration
+ QA::EE::Resource::Settings::Elasticsearch
+ QA::EE::Resource::VulnerabilityItem
+ QA::EE::Resource::ScanResultPolicyProject
+ QA::EE::Resource::ScanResultPolicyCommit
].freeze
PROJECT = 'gitlab-qa-resources'
@@ -44,10 +48,19 @@ module QA
def run_delete
failures = files.flat_map do |file|
resources = read_file(file)
- next if resources.nil?
+ if resources.nil?
+ logger.info("#{file} is empty, next...")
+ next
+ end
filtered_resources = filter_resources(resources)
+ if filtered_resources.nil?
+ logger.info("No resources left to delete after filtering!")
+ next
+ end
+
delete_resources(filtered_resources)
+ delete_groups_permanently(filtered_resources['QA::Resource::Group'])
end
return puts "\nDone" if failures.empty?
@@ -62,17 +75,15 @@ module QA
# E.g: staging/failed-test-resources-<randomhex>.json
def upload(ci_project_name)
if files.empty?
- puts "\nNothing to upload!"
- exit 0
+ logger.info("\nNothing to upload!")
+ return
end
files.each do |file|
file_name = "#{ci_project_name}/#{file.split('/').last}"
- Runtime::Logger.info("Uploading #{file_name}...")
+ logger.info("Uploading #{file_name}...")
gcs_storage.put_object(BUCKET, file_name, File.read(file))
end
-
- puts "\nDone"
end
# Download files from GCS bucket by environment name
@@ -85,40 +96,38 @@ module QA
end
if files_list.blank?
- puts "\nNothing to download!"
- exit 0
+ logger.info("\nNothing to download!")
+ return
end
FileUtils.mkdir_p('tmp/')
files_list.each do |file_name|
local_path = "tmp/#{file_name.split('/').last}"
- Runtime::Logger.info("Downloading #{file_name} to #{local_path}")
+ logger.info("Downloading #{file_name} to #{local_path}")
file = gcs_storage.get_object(BUCKET, file_name)
File.write(local_path, file[:body])
- Runtime::Logger.info("Deleting #{file_name} from bucket")
+ logger.info("Deleting #{file_name} from bucket")
gcs_storage.delete_object(BUCKET, file_name)
end
-
- puts "\nDone"
end
private
def files
- Runtime::Logger.info('Gathering JSON files...')
+ logger.info('Gathering JSON files...')
files = Dir.glob(@file_pattern)
if files.empty?
- puts "There is no file with this pattern #{@file_pattern}"
+ logger.info("There is no file with this pattern #{@file_pattern}")
exit 0
end
files.reject! { |file| File.zero?(file) }
if files.empty?
- puts "\nAll files were empty and rejected, nothing more to do!"
+ logger.info("\nAll files were empty and rejected, nothing more to do!")
exit 0
end
@@ -126,14 +135,15 @@ module QA
end
def read_file(file)
+ logger.info("Reading and processing #{file}...")
JSON.parse(File.read(file))
rescue JSON::ParserError
- Runtime::Logger.error("Failed to read #{file} - Invalid format")
+ logger.error("Failed to read #{file} - Invalid format")
nil
end
def filter_resources(resources)
- Runtime::Logger.info('Filtering resources - Only keep deletable resources...')
+ logger.info('Filtering resources - Only keep deletable resources...')
transformed_values = resources.transform_values! do |v|
v.reject do |attributes|
@@ -147,28 +157,55 @@ module QA
end
def delete_resources(resources)
- if resources.nil?
- puts "\nNo resources left to delete after filtering!"
- exit 0
- end
-
resources.each_with_object([]) do |(key, value), failures|
value.each do |resource|
- next if resource_not_found?(resource['api_path'])
-
resource_info = resource['info'] ? "#{key} - #{resource['info']}" : "#{key} at #{resource['api_path']}"
+ logger.info("Processing #{resource_info}...")
+
+ if resource_not_found?(resource['api_path'])
+ logger.info("#{resource['api_path']} returns 404, next...")
+ next
+ end
+
delete_response = delete(Runtime::API::Request.new(api_client, resource['api_path']).url)
if delete_response.code == 202 || delete_response.code == 204
- Runtime::Logger.info("Deleting #{resource_info}... SUCCESS")
+ if key == 'QA::Resource::Group' && !resource_not_found?(resource['api_path'])
+ logger.info("Successfully marked #{resource_info} for deletion...")
+ else
+ logger.info("Deleting #{resource_info}... \e[32mSUCCESS\e[0m")
+ end
else
- Runtime::Logger.info("Deleting #{resource_info}... FAILED - #{delete_response}")
- failures << resource_info
+ logger.info("Deleting #{resource_info}... \e[31mFAILED - #{delete_response}\e[0m")
+ # We might try to delete some groups already marked for deletion, it's fine to ignore these failures
+ failures << resource_info unless key == 'QA::Resource::Group'
end
end
end
end
+ def delete_groups_permanently(groups)
+ groups.each_with_object([]) do |group, failures|
+ logger.info("Processing QA::Resource::Group #{group['info']}...")
+
+ if resource_not_found?(group['api_path'])
+ logger.info("#{group['api_path']} returns 404, next...")
+ next
+ end
+
+ permanent_delete_path = "#{group['api_path']}?permanently_remove=true"\
+ "&full_path=#{group['info'].split("'").last}"
+ response = delete(Runtime::API::Request.new(api_client, permanent_delete_path).url)
+
+ if response.code == 202
+ logger.info("Permanently deleting group #{group['info']}... \e[32mSUCCESS\e[0m")
+ else
+ logger.info("Permanently deleting group #{group['info']}... \e[31mFAILED - #{response}\e[0m")
+ failures << "QA::Resource::Group #{group['info']}"
+ end
+ end
+ end
+
def resource_not_found?(api_path)
# if api path contains param "?hard_delete=<boolean>", remove it
get(Runtime::API::Request.new(api_client, api_path.split('?').first).url).code.eql? 404
diff --git a/qa/qa/vendor/jira/jira_issue_page.rb b/qa/qa/vendor/jira/jira_issue_page.rb
new file mode 100644
index 00000000000..5f5449513ff
--- /dev/null
+++ b/qa/qa/vendor/jira/jira_issue_page.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+module QA
+ module Vendor
+ module Jira
+ class JiraIssuePage < JiraAPI
+ include Capybara::DSL
+ include Scenario::Actable
+
+ def login(username, password)
+ QA::Runtime::Logger.debug("Logging into JIRA with username: #{username} and password:#{password}")
+
+ fill_in 'login-form-username', with: username
+ fill_in 'login-form-password', with: password
+ click_on 'login-form-submit'
+ end
+
+ def go_to_login_page
+ click_on 'log in'
+ end
+
+ def login_if_required(username, password)
+ return unless login_required?
+
+ go_to_login_page
+ login(username, password)
+ end
+
+ def summary_field
+ page.find('#summary').value
+ end
+
+ def issue_description
+ page.find('#description', visible: false).value
+ end
+
+ def login_required?
+ login_required = page.has_text?('You are not logged in')
+ QA::Runtime::Logger.debug("login_required: #{login_required}")
+ login_required
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/resource/user_spec.rb b/qa/spec/resource/user_spec.rb
index c0140abf298..d82dcc3b21e 100644
--- a/qa/spec/resource/user_spec.rb
+++ b/qa/spec/resource/user_spec.rb
@@ -23,8 +23,8 @@ RSpec.describe QA::Resource::User do
end
describe '#password' do
- it 'generates a random 16 character password by default' do
- expect(subject.password).to match(/\w{16}/)
+ it 'generates a default password' do
+ expect(subject.password).to match('Pa$$w0rd')
end
it 'is possible to set the password' do
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index a41d7385c41..61d91da8738 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -339,4 +339,35 @@ RSpec.describe QA::Runtime::Env do
end
end
end
+
+ describe '.canary_cookie' do
+ subject { described_class.canary_cookie }
+
+ context 'with QA_COOKIES set' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:cookie_value, :result) do
+ 'gitlab_canary=true' | { gitlab_canary: "true" }
+ 'other_cookie=value\;gitlab_canary=true' | { gitlab_canary: "true" }
+ 'gitlab_canary=false' | { gitlab_canary: "false" }
+ 'gitlab_canary=false\;other_cookie=value' | { gitlab_canary: "false" }
+ end
+
+ with_them do
+ before do
+ stub_env('QA_COOKIES', cookie_value)
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ context 'without QA_COOKIES set' do
+ before do
+ stub_env('QA_COOKIES', nil)
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
end
diff --git a/qa/spec/scenario/test/integration/github_spec.rb b/qa/spec/scenario/test/integration/github_spec.rb
deleted file mode 100644
index 4ad42b4f5cc..00000000000
--- a/qa/spec/scenario/test/integration/github_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe QA::Scenario::Test::Integration::Github do
- describe '#perform' do
- let(:env) { spy('Runtime::Env', knapsack?: false, dry_run: false) }
-
- before do
- stub_const('QA::Runtime::Env', env)
- end
-
- it_behaves_like 'a QA scenario class' do
- let(:tags) { [:github] }
-
- it 'requires a GitHub access token' do
- subject.perform(args)
-
- expect(env).to have_received(:require_github_access_token!)
- end
- end
- end
-end
diff --git a/qa/spec/support/formatters/test_stats_formatter_spec.rb b/qa/spec/support/formatters/test_stats_formatter_spec.rb
index ba59588d186..d0d89b5ee73 100644
--- a/qa/spec/support/formatters/test_stats_formatter_spec.rb
+++ b/qa/spec/support/formatters/test_stats_formatter_spec.rb
@@ -15,6 +15,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
let(:ci_job_url) { 'url' }
let(:ci_pipeline_url) { 'url' }
let(:ci_pipeline_id) { '123' }
+ let(:ci_job_id) { '321' }
let(:run_type) { 'staging-full' }
let(:smoke) { 'false' }
let(:reliable) { 'false' }
@@ -64,6 +65,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
job_url: ci_job_url,
pipeline_url: ci_pipeline_url,
pipeline_id: ci_pipeline_id,
+ job_id: ci_job_id,
merge_request_iid: nil
}
}
@@ -80,7 +82,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
around do |example|
RSpec::Core::Sandbox.sandboxed do |config|
- config.formatter = QA::Support::Formatters::TestStatsFormatter
+ config.formatter = described_class
config.before(:context) { RSpec.current_example = nil }
example.run
@@ -125,6 +127,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
stub_env('CI_JOB_NAME', ci_job_name)
stub_env('CI_PIPELINE_URL', ci_pipeline_url)
stub_env('CI_PIPELINE_ID', ci_pipeline_id)
+ stub_env('CI_JOB_ID', ci_job_id)
stub_env('CI_MERGE_REQUEST_IID', nil)
stub_env('TOP_UPSTREAM_MERGE_REQUEST_IID', nil)
stub_env('QA_RUN_TYPE', run_type)
diff --git a/qa/spec/tools/ci/non_empty_suites_spec.rb b/qa/spec/tools/ci/non_empty_suites_spec.rb
index d9bfe1eebe7..f71e07aa4b4 100644
--- a/qa/spec/tools/ci/non_empty_suites_spec.rb
+++ b/qa/spec/tools/ci/non_empty_suites_spec.rb
@@ -9,11 +9,11 @@ RSpec.describe QA::Tools::Ci::NonEmptySuites do
allow(Gitlab::QA::TestLogger).to receive(:logger).and_return(Logger.new(StringIO.new))
allow(Open3).to receive(:capture3).and_return(["output\n0", "", status])
allow(Open3).to receive(:capture3)
- .with("bundle exec bin/qa Test::Instance::All --count-examples-only --address http://dummy1.test")
+ .with("bundle exec bin/qa QA::Scenario::Test::Instance::All --count-examples-only --address http://dummy1.test")
.and_return(["output\n1", "", status])
end
it "returns runnable test suites" do
- expect(non_empty_suites.fetch).to eq("Test::Instance::All")
+ expect(non_empty_suites.fetch).to eq("QA::Scenario::Test::Instance::All")
end
end
diff --git a/qa/spec/tools/ci/qa_changes_spec.rb b/qa/spec/tools/ci/qa_changes_spec.rb
index bc98ec16d7f..d93d3cd9258 100644
--- a/qa/spec/tools/ci/qa_changes_spec.rb
+++ b/qa/spec/tools/ci/qa_changes_spec.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
RSpec.describe QA::Tools::Ci::QaChanges do
- subject(:qa_changes) { described_class.new(mr_diff, mr_labels) }
+ subject(:qa_changes) { described_class.new(mr_diff, mr_labels, additional_group_spec_list) }
let(:mr_labels) { [] }
+ let(:additional_group_spec_list) { [] }
before do
allow(File).to receive(:directory?).and_return(false)
@@ -35,7 +36,7 @@ RSpec.describe QA::Tools::Ci::QaChanges do
context "with framework changes" do
let(:mr_diff) { [{ path: "qa/qa.rb" }] }
- it ".qa_tests do not return specifix specs" do
+ it ".qa_tests do not return specific specs" do
expect(qa_changes.qa_tests).to be_nil
end
@@ -75,6 +76,43 @@ RSpec.describe QA::Tools::Ci::QaChanges do
)
end
end
+
+ context "when configured to run tests from other stages" do
+ let(:additional_group_spec_list) do
+ {
+ 'foo' => %w[create],
+ 'bar' => %w[monitor verify]
+ }
+ end
+
+ context "with a single extra stage configured for the group name" do
+ let(:mr_labels) { %w[devops::manage group::foo] }
+
+ it ".qa_tests return specs for both devops stage and create stage" do
+ expect(qa_changes.qa_tests.split(" ")).to include(
+ "qa/specs/features/browser_ui/1_manage/",
+ "qa/specs/features/api/1_manage/",
+ "qa/specs/features/browser_ui/3_create/",
+ "qa/specs/features/api/3_create/"
+ )
+ end
+ end
+
+ context "with a multiple extra stages configured for the group name" do
+ let(:mr_labels) { %w[devops::manage group::bar] }
+
+ it ".qa_tests return specs for both devops stage and multiple other stages" do
+ expect(qa_changes.qa_tests.split(" ")).to include(
+ "qa/specs/features/browser_ui/1_manage/",
+ "qa/specs/features/api/1_manage/",
+ "qa/specs/features/browser_ui/8_monitor/",
+ "qa/specs/features/api/8_monitor/",
+ "qa/specs/features/browser_ui/4_verify/",
+ "qa/specs/features/api/4_verify/"
+ )
+ end
+ end
+ end
end
context "with quarantine changes" do
@@ -84,4 +122,14 @@ RSpec.describe QA::Tools::Ci::QaChanges do
expect(qa_changes.quarantine_changes?).to eq(true)
end
end
+
+ %w[GITALY_SERVER_VERSION Gemfile.lock yarn.lock Dockerfile.assets].each do |dependency_file|
+ context "when #{dependency_file} change" do
+ let(:mr_diff) { [{ path: dependency_file }] }
+
+ it ".qa_tests do not return specific specs" do
+ expect(qa_changes.qa_tests).to be_nil
+ end
+ end
+ end
end
diff --git a/qa/spec/tools/reliable_report_spec.rb b/qa/spec/tools/reliable_report_spec.rb
index d5c898779b8..f08af8a717a 100644
--- a/qa/spec/tools/reliable_report_spec.rb
+++ b/qa/spec/tools/reliable_report_spec.rb
@@ -145,7 +145,8 @@ describe QA::Tools::ReliableReport do
let(:common_api_args) do
{
verify_ssl: false,
- headers: { "PRIVATE-TOKEN" => "gitlab_token" }
+ headers: { "PRIVATE-TOKEN" => "gitlab_token" },
+ cookies: {}
}
end
diff --git a/qa/tasks/ci.rake b/qa/tasks/ci.rake
index 44a794d9f94..435fe8ebb77 100644
--- a/qa/tasks/ci.rake
+++ b/qa/tasks/ci.rake
@@ -13,8 +13,10 @@ namespace :ci do
diff = mr_diff
labels = mr_labels
+ # Assign mapping of groups to tests in stages other than the groups defined stage
+ additional_group_spec_list = { 'gitaly' => %w[create] }
- qa_changes = QA::Tools::Ci::QaChanges.new(diff, labels)
+ qa_changes = QA::Tools::Ci::QaChanges.new(diff, labels, additional_group_spec_list)
logger = qa_changes.logger
logger.info("Analyzing merge request changes")
diff --git a/rubocop/check_graceful_task.rb b/rubocop/check_graceful_task.rb
index 7ae74e79e38..724f7fa6963 100644
--- a/rubocop/check_graceful_task.rb
+++ b/rubocop/check_graceful_task.rb
@@ -66,7 +66,13 @@ module RuboCop
end
channel = 'f_rubocop'
- message = ":warning: `#{job_name}` passed :green: but contained silenced offenses. See #{job_url}"
+ message = format(
+ ':warning: `%{job_name}` passed :green: but contained <%{job_url}|silenced offenses>. ' \
+ 'See <%{docs_link}|docs>.',
+ docs_link: 'https://docs.gitlab.com/ee/development/contributing/style_guides.html#silenced-offenses',
+ job_name: job_name,
+ job_url: job_url)
+
emoji = 'rubocop'
user_name = 'GitLab Bot'
diff --git a/rubocop/cop/gitlab/duplicate_spec_location.rb b/rubocop/cop/gitlab/duplicate_spec_location.rb
index ece3b9313d9..f8c19caf351 100644
--- a/rubocop/cop/gitlab/duplicate_spec_location.rb
+++ b/rubocop/cop/gitlab/duplicate_spec_location.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'rubocop/rspec/top_level_describe'
+require 'rubocop/cop/rspec/base'
+require 'rubocop/cop/rspec/mixin/top_level_group'
module RuboCop
module Cop
@@ -19,17 +20,17 @@ module RuboCop
# # good, spec for EE only code
# ee/spec/controllers/my_spec.rb # describe MyClass
#
- class DuplicateSpecLocation < RuboCop::Cop::Cop
- include RuboCop::RSpec::TopLevelDescribe
+ class DuplicateSpecLocation < RuboCop::Cop::RSpec::Base
+ include RuboCop::Cop::RSpec::TopLevelGroup
MSG = 'Duplicate spec location in `%<path>s`.'
- def on_top_level_describe(node, _args)
- path = file_path_for_node(node).sub(%r{\A#{rails_root}/}, '')
+ def on_top_level_group(node)
+ path = file_path_for_node(node.send_node).sub(%r{\A#{rails_root}/}, '')
duplicate_path = find_duplicate_path(path)
if duplicate_path && File.exist?(File.join(rails_root, duplicate_path))
- add_offense(node, message: format(MSG, path: duplicate_path))
+ add_offense(node.send_node, message: format(MSG, path: duplicate_path))
end
end
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index 8d8c84e78f5..23de0644385 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -13,11 +13,8 @@ module RuboCop
include RuboCop::CodeReuseHelpers
FEATURE_METHODS = %i[enabled? disabled?].freeze
- EXPERIMENTATION_METHODS = %i[active?].freeze
EXPERIMENT_METHODS = %i[
experiment
- experiment_enabled?
- push_frontend_experiment
].freeze
RUGGED_METHODS = %i[
use_rugged?
@@ -33,7 +30,7 @@ module RuboCop
limit_feature_flag_for_override=
].freeze + EXPERIMENT_METHODS + RUGGED_METHODS + WORKER_METHODS
- RESTRICT_ON_SEND = FEATURE_METHODS + EXPERIMENTATION_METHODS + SELF_METHODS
+ RESTRICT_ON_SEND = FEATURE_METHODS + SELF_METHODS
USAGE_DATA_COUNTERS_EVENTS_YAML_GLOBS = [
File.expand_path("../../../config/metrics/aggregates/*.yml", __dir__),
@@ -79,15 +76,6 @@ module RuboCop
else
save_used_feature_flag(flag_value)
end
-
- if experiment_method?(node) || experimentation_method?(node)
- # Additionally, mark experiment-related feature flag as used as well
- matching_feature_flags = defined_feature_flags.select { |flag| flag == "#{flag_value}_experiment_percentage" }
- matching_feature_flags.each do |matching_feature_flag|
- puts_if_debug(node, "The '#{matching_feature_flag}' feature flag tracks the #{flag_value} experiment, which is still in use, so we'll mark it as used.")
- save_used_feature_flag(matching_feature_flag)
- end
- end
elsif flag_arg_is_send_type?(flag_arg)
puts_if_debug(node, "Feature flag is dynamic: '#{flag_value}.")
elsif flag_arg_is_dstr_or_dsym?(flag_arg)
@@ -176,14 +164,6 @@ module RuboCop
class_caller(node) == "Feature::Gitaly"
end
- def caller_is_experimentation?(node)
- class_caller(node) == "Gitlab::Experimentation"
- end
-
- def experiment_method?(node)
- EXPERIMENT_METHODS.include?(method_name(node))
- end
-
def rugged_method?(node)
RUGGED_METHODS.include?(method_name(node))
end
@@ -192,10 +172,6 @@ module RuboCop
FEATURE_METHODS.include?(method_name(node)) && (caller_is_feature?(node) || caller_is_feature_gitaly?(node))
end
- def experimentation_method?(node)
- EXPERIMENTATION_METHODS.include?(method_name(node)) && caller_is_experimentation?(node)
- end
-
def worker_method?(node)
WORKER_METHODS.include?(method_name(node))
end
@@ -205,7 +181,7 @@ module RuboCop
end
def trackable_flag?(node)
- feature_method?(node) || experimentation_method?(node) || self_method?(node)
+ feature_method?(node) || self_method?(node)
end
# Marking all event's feature flags as used as Gitlab::UsageDataCounters::HLLRedisCounter.track_event{,context}
diff --git a/rubocop/cop/gitlab/no_code_coverage_comment.rb b/rubocop/cop/gitlab/no_code_coverage_comment.rb
new file mode 100644
index 00000000000..3b989930026
--- /dev/null
+++ b/rubocop/cop/gitlab/no_code_coverage_comment.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Discourages the use of `# :nocov:` to exclude code from coverage report.
+ #
+ # The nocov token can be configured via `CommentToken` option and defaults
+ # to `'nocov'`.
+ #
+ # @example CommentToken: 'nocov' (default)
+ #
+ # # bad
+ # # :nocov:
+ # def method
+ # end
+ # # :nocov:
+ #
+ # # good
+ # def method
+ # end
+ #
+ class NoCodeCoverageComment < RuboCop::Cop::Base
+ include RangeHelp
+
+ MSG = 'The use of %<nocov_comment>s is discouraged. All code must have tests. See https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#testing'
+
+ DEFAULT_COMMENT_TOKEN = 'nocov'
+
+ def on_new_investigation
+ super
+
+ nocov_token = cop_config.fetch('CommentToken', DEFAULT_COMMENT_TOKEN)
+ nocov_comment = ":#{nocov_token}:"
+ # See https://github.com/simplecov-ruby/simplecov/blob/v0.21.2/lib/simplecov/lines_classifier.rb#L16
+ regexp = /^(?:\s*)#(?:\s*)(?::#{nocov_token}:)/
+
+ processed_source.comments.each do |comment|
+ register_offense(comment, nocov_comment) if regexp.match?(comment.text)
+ end
+ end
+
+ private
+
+ def register_offense(comment, nocov_comment)
+ range = range_of_offense(comment, nocov_comment)
+ message = format(MSG, nocov_comment: nocov_comment)
+
+ add_offense(range, message: message)
+ end
+
+ def range_of_offense(comment, name)
+ start_pos = comment_start(comment) + token_indentation(comment, name)
+ range_between(start_pos, start_pos + name.size)
+ end
+
+ def comment_start(comment)
+ comment.loc.expression.begin_pos
+ end
+
+ def token_indentation(comment, name)
+ comment.text.index(name)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/service_response.rb b/rubocop/cop/gitlab/service_response.rb
new file mode 100644
index 00000000000..edde662a038
--- /dev/null
+++ b/rubocop/cop/gitlab/service_response.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require_relative '../../code_reuse_helpers'
+
+module RuboCop
+ module Cop
+ module Gitlab
+ class ServiceResponse < ::RuboCop::Cop::Base
+ include CodeReuseHelpers
+
+ # This cop checks that ServiceResponse object is not used with the
+ # deprecated attribute `http_status`.
+ #
+ # @example
+ #
+ # # bad
+ # ServiceResponse.error(message: "...", http_status: :forbidden)
+ #
+ # # good
+ # ServiceResponse.error(message: "...", reason: :insufficient_permissions)
+ MSG = 'Use `reason` instead of the deprecated `http_status`: https://gitlab.com/gitlab-org/gitlab/-/issues/356036'
+
+ RESTRICT_ON_SEND = %i[error success new].freeze
+ METHOD_NAMES = RESTRICT_ON_SEND.map(&:inspect).join(' ').freeze
+
+ def_node_matcher :service_response_with_http_status, <<~PATTERN
+ (send
+ (const {nil? cbase} :ServiceResponse)
+ {#{METHOD_NAMES}}
+ (hash <$(pair (sym :http_status) _) ...>)
+ )
+ PATTERN
+
+ def on_send(node)
+ pair = service_response_with_http_status(node)
+ return unless pair
+
+ add_offense(pair)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/background_migration_missing_active_concern.rb b/rubocop/cop/migration/background_migration_missing_active_concern.rb
new file mode 100644
index 00000000000..417472bf512
--- /dev/null
+++ b/rubocop/cop/migration/background_migration_missing_active_concern.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ # Cop that checks `ActiveSupport::Concern` is included in EE batched background migrations
+ # if they define `scope_to`.
+ class BackgroundMigrationMissingActiveConcern < RuboCop::Cop::Base
+ include MigrationHelpers
+
+ MSG = <<~MSG
+ Extend `ActiveSupport::Concern` in the EE background migration if it defines `scope_to`.
+ MSG
+
+ def_node_matcher :prepended_block_uses_scope_to?, <<~PATTERN
+ (:block (:send nil? :prepended) (:args) `(:send nil? :scope_to ...))
+ PATTERN
+
+ def_node_matcher :scope_to?, <<~PATTERN
+ (:send nil? :scope_to ...)
+ PATTERN
+
+ def_node_matcher :extend_activesupport_concern?, <<~PATTERN
+ (:send nil? :extend (:const (:const nil? :ActiveSupport) :Concern))
+ PATTERN
+
+ def on_block(node)
+ return unless in_ee_background_migration?(node)
+ return unless prepended_block_uses_scope_to?(node)
+
+ return if module_extends_activesupport_concern?(node)
+
+ node.descendants.each do |descendant|
+ next unless scope_to?(descendant)
+
+ add_offense(descendant)
+ end
+ end
+
+ private
+
+ def module_extends_activesupport_concern?(node)
+ while node = node.parent
+ break if node.type == :module
+ end
+
+ return false unless node
+
+ node.descendants.any? do |descendant|
+ extend_activesupport_concern?(descendant)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/redis_queue_usage.rb b/rubocop/cop/redis_queue_usage.rb
new file mode 100644
index 00000000000..d993abc6327
--- /dev/null
+++ b/rubocop/cop/redis_queue_usage.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ # This class complements Rubocop::Cop::SidekiqRedisCall by disallowing the use of
+ # Gitlab::Redis::Queues with the exception of initialising Sidekiq and monitoring.
+ class RedisQueueUsage < RuboCop::Cop::Base
+ MSG = 'Gitlab::Redis::Queues should only be used by Sidekiq initializers. '\
+ 'Assignments or using its params to initialise another connection is not allowed.'
+
+ def_node_matcher :calling_redis_queue_module_methods?, <<~PATTERN
+ (send (const (const (const nil? :Gitlab) :Redis) :Queues) ...)
+ PATTERN
+
+ def_node_matcher :using_redis_queue_module_as_parameter?, <<~PATTERN
+ (send ... (const (const (const nil? :Gitlab) :Redis) :Queues))
+ PATTERN
+
+ def_node_matcher :redis_queue_assignment?, <<~PATTERN
+ ({lvasgn | ivasgn | cvasgn | gvasgn | casgn | masgn | op_asgn | or_asgn | and_asgn } ...
+ `(const (const (const nil? :Gitlab) :Redis) :Queues))
+ PATTERN
+
+ def on_send(node)
+ return unless using_redis_queue_module_as_parameter?(node) || calling_redis_queue_module_methods?(node)
+
+ add_offense(node, message: MSG)
+ end
+
+ # offenses caught in assignment may overlap with on_send
+ %i[on_lvasgn on_ivasgn on_cvasgn on_gvasgn on_casgn on_masgn on_op_asgn on_or_asgn on_and_asgn].each do |name|
+ define_method(name) do |node|
+ add_offense(node, message: MSG) if redis_queue_assignment?(node)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/rspec/any_instance_of.rb b/rubocop/cop/rspec/any_instance_of.rb
index e1cacfebfd3..7016a76ec93 100644
--- a/rubocop/cop/rspec/any_instance_of.rb
+++ b/rubocop/cop/rspec/any_instance_of.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/be_success_matcher.rb b/rubocop/cop/rspec/be_success_matcher.rb
index 5a011845075..1ed55762965 100644
--- a/rubocop/cop/rspec/be_success_matcher.rb
+++ b/rubocop/cop/rspec/be_success_matcher.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/env_assignment.rb b/rubocop/cop/rspec/env_assignment.rb
index add7897c624..6994f3f0969 100644
--- a/rubocop/cop/rspec/env_assignment.rb
+++ b/rubocop/cop/rspec/env_assignment.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/expect_gitlab_tracking.rb b/rubocop/cop/rspec/expect_gitlab_tracking.rb
index 4f92980baa4..13fc7eace71 100644
--- a/rubocop/cop/rspec/expect_gitlab_tracking.rb
+++ b/rubocop/cop/rspec/expect_gitlab_tracking.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rack/utils'
+require 'rubocop-rspec'
module RuboCop
module Cop
diff --git a/rubocop/cop/rspec/factories_in_migration_specs.rb b/rubocop/cop/rspec/factories_in_migration_specs.rb
index 6dde3d4524c..7dce1264b0e 100644
--- a/rubocop/cop/rspec/factories_in_migration_specs.rb
+++ b/rubocop/cop/rspec/factories_in_migration_specs.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/factory_bot/avoid_create.rb b/rubocop/cop/rspec/factory_bot/avoid_create.rb
new file mode 100644
index 00000000000..e9bccfb37cd
--- /dev/null
+++ b/rubocop/cop/rspec/factory_bot/avoid_create.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'rubocop-rspec'
+
+module RuboCop
+ module Cop
+ module RSpec
+ module FactoryBot
+ # This cop checks for the creation of ActiveRecord objects in serializers specs specs
+ #
+ # @example
+ #
+ # # bad
+ # let(:user) { create(:user) }
+ # let(:users) { create_list(:user, 2) }
+ #
+ # # good
+ # let(:user) { build_stubbed(:user) }
+ # let(:user) { build(:user) }
+ # let(:users) { build_stubbed_list(:user, 2) }
+ # let(:users) { build_list(:user, 2) }
+ class AvoidCreate < RuboCop::Cop::Base
+ MESSAGE = "Prefer using `build_stubbed` or similar over `%{method_name}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#optimize-factory-usage"
+ FORBIDDEN_METHODS = %i[create create_list].freeze
+ RESTRICT_ON_SEND = FORBIDDEN_METHODS
+
+ def_node_matcher :forbidden_factory_usage, <<~PATTERN
+ (
+ send
+ {(const nil? :FactoryBot) nil?}
+ ${ #{FORBIDDEN_METHODS.map(&:inspect).join(' ')} }
+ ...
+ )
+ PATTERN
+
+ def on_send(node)
+ method_name = forbidden_factory_usage(node)
+ return unless method_name
+
+ add_offense(node, message: format(MESSAGE, method_name: method_name))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/rspec/factory_bot/inline_association.rb b/rubocop/cop/rspec/factory_bot/inline_association.rb
index ccc6364fb73..8d7c73b99a0 100644
--- a/rubocop/cop/rspec/factory_bot/inline_association.rb
+++ b/rubocop/cop/rspec/factory_bot/inline_association.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/have_gitlab_http_status.rb b/rubocop/cop/rspec/have_gitlab_http_status.rb
index 86ece72b4f5..29577598ba7 100644
--- a/rubocop/cop/rspec/have_gitlab_http_status.rb
+++ b/rubocop/cop/rspec/have_gitlab_http_status.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'rack/utils'
+require 'rubocop-rspec'
module RuboCop
module Cop
diff --git a/rubocop/cop/rspec/httparty_basic_auth.rb b/rubocop/cop/rspec/httparty_basic_auth.rb
index 1e0f7ae7af0..d188002673f 100644
--- a/rubocop/cop/rspec/httparty_basic_auth.rb
+++ b/rubocop/cop/rspec/httparty_basic_auth.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/modify_sidekiq_middleware.rb b/rubocop/cop/rspec/modify_sidekiq_middleware.rb
index 78e3ba223b0..2e27288933f 100644
--- a/rubocop/cop/rspec/modify_sidekiq_middleware.rb
+++ b/rubocop/cop/rspec/modify_sidekiq_middleware.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/timecop_freeze.rb b/rubocop/cop/rspec/timecop_freeze.rb
index 70e37ecfa55..b13f5050040 100644
--- a/rubocop/cop/rspec/timecop_freeze.rb
+++ b/rubocop/cop/rspec/timecop_freeze.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/timecop_travel.rb b/rubocop/cop/rspec/timecop_travel.rb
index 586567fa0cd..03f978be349 100644
--- a/rubocop/cop/rspec/timecop_travel.rb
+++ b/rubocop/cop/rspec/timecop_travel.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/rspec/top_level_describe_path.rb b/rubocop/cop/rspec/top_level_describe_path.rb
index 3cc1ee8df90..ee1a0bcc4b6 100644
--- a/rubocop/cop/rspec/top_level_describe_path.rb
+++ b/rubocop/cop/rspec/top_level_describe_path.rb
@@ -1,21 +1,20 @@
# frozen_string_literal: true
-require 'rubocop/rspec/top_level_describe'
+require 'rubocop/cop/rspec/base'
+require 'rubocop/cop/rspec/mixin/top_level_group'
module RuboCop
module Cop
module RSpec
- class TopLevelDescribePath < RuboCop::Cop::Cop
- include RuboCop::RSpec::TopLevelDescribe
+ class TopLevelDescribePath < RuboCop::Cop::RSpec::Base
+ include RuboCop::Cop::RSpec::TopLevelGroup
MESSAGE = 'A file with a top-level `describe` must end in _spec.rb.'
- SHARED_EXAMPLES = %i[shared_examples shared_examples_for].freeze
- def on_top_level_describe(node, args)
+ def on_top_level_example_group(node)
return if acceptable_file_path?(processed_source.buffer.name)
- return if shared_example?(node)
- add_offense(node, message: MESSAGE)
+ add_offense(node.send_node, message: MESSAGE)
end
private
@@ -23,12 +22,6 @@ module RuboCop
def acceptable_file_path?(path)
File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path) || File.fnmatch?('*/docs_screenshots/*_docs.rb', path)
end
-
- def shared_example?(node)
- node.ancestors.any? do |node|
- node.respond_to?(:method_name) && SHARED_EXAMPLES.include?(node.method_name)
- end
- end
end
end
end
diff --git a/rubocop/cop/rspec/web_mock_enable.rb b/rubocop/cop/rspec/web_mock_enable.rb
index 0bef16a16b0..395375e5fc1 100644
--- a/rubocop/cop/rspec/web_mock_enable.rb
+++ b/rubocop/cop/rspec/web_mock_enable.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'rubocop-rspec'
+
module RuboCop
module Cop
module RSpec
diff --git a/rubocop/cop/sidekiq_api_usage.rb b/rubocop/cop/sidekiq_api_usage.rb
new file mode 100644
index 00000000000..35e5ec474cd
--- /dev/null
+++ b/rubocop/cop/sidekiq_api_usage.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ class SidekiqApiUsage < RuboCop::Cop::Base
+ MSG = 'Refrain from directly using Sidekiq APIs.' \
+ 'Only permitted in migrations, administrations and Sidekiq middlewares.'
+
+ ALLOWED_WORKER_METHODS = [
+ :skipping_transaction_check,
+ :raise_inside_transaction_exception,
+ :raise_exception_for_being_inside_a_transaction?
+ ].freeze
+
+ def_node_matcher :using_sidekiq_api?, <<~PATTERN
+ (send (const (const nil? :Sidekiq) $_ ) $... )
+ PATTERN
+
+ def on_send(node)
+ using_sidekiq_api?(node) do |klass, methods_called|
+ next if klass == :Testing
+
+ # allow methods defined in config/initializers/forbid_sidekiq_in_transactions.rb
+ next if klass == :Worker && ALLOWED_WORKER_METHODS.include?(methods_called[0])
+
+ add_offense(node, message: MSG)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/sidekiq_redis_call.rb b/rubocop/cop/sidekiq_redis_call.rb
new file mode 100644
index 00000000000..e4ae430f7c7
--- /dev/null
+++ b/rubocop/cop/sidekiq_redis_call.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ # Cop that prevents manually setting a queue in Sidekiq workers.
+ class SidekiqRedisCall < RuboCop::Cop::Base
+ MSG = 'Refrain from directly using Sidekiq.redis unless for migration. For admin operations, use Sidekiq APIs.'
+
+ def_node_matcher :using_sidekiq_redis?, <<~PATTERN
+ (send (const nil? :Sidekiq) :redis)
+ PATTERN
+
+ def on_send(node)
+ add_offense(node, message: MSG) if using_sidekiq_redis?(node)
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/static_translation_definition.rb b/rubocop/cop/static_translation_definition.rb
index aea4dd6ae34..e7b8cdeab12 100644
--- a/rubocop/cop/static_translation_definition.rb
+++ b/rubocop/cop/static_translation_definition.rb
@@ -64,7 +64,7 @@ module RuboCop
NON_METHOD_DEFINITIONS = %i[class_methods included prepended].to_set.freeze
def_node_matcher :translation_method?, <<~PATTERN
- (send _ {#{RESTRICT_ON_SEND.map(&:inspect).join(' ')}} str*)
+ (send _ {#{RESTRICT_ON_SEND.map(&:inspect).join(' ')}} {dstr str}+)
PATTERN
def on_send(node)
diff --git a/rubocop/cop_todo.rb b/rubocop/cop_todo.rb
index a36afc08673..943f3375461 100644
--- a/rubocop/cop_todo.rb
+++ b/rubocop/cop_todo.rb
@@ -26,10 +26,14 @@ module RuboCop
@cop_class&.support_autocorrect?
end
+ def generate?
+ previously_disabled || grace_period || files.any?
+ end
+
def to_yaml
yaml = []
yaml << '---'
- yaml << '# Cop supports --auto-correct.' if autocorrectable?
+ yaml << '# Cop supports --autocorrect.' if autocorrectable?
yaml << "#{cop_name}:"
if previously_disabled
@@ -39,8 +43,12 @@ module RuboCop
end
yaml << " #{RuboCop::Formatter::GracefulFormatter.grace_period_key_value}" if grace_period
- yaml << ' Exclude:'
- yaml.concat files.sort.map { |file| " - '#{file}'" }
+
+ if files.any?
+ yaml << ' Exclude:'
+ yaml.concat files.sort.map { |file| " - '#{file}'" }
+ end
+
yaml << ''
yaml.join("\n")
diff --git a/rubocop/ext/path_util.rb b/rubocop/ext/path_util.rb
new file mode 100644
index 00000000000..3b54f046c7b
--- /dev/null
+++ b/rubocop/ext/path_util.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module PathUtil
+ def match_path?(pattern, path)
+ case pattern
+ when String
+ matched = if /[*{}]/.match?(pattern)
+ File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
+ else
+ pattern == path
+ end
+
+ matched || hidden_file_in_not_hidden_dir?(pattern, path)
+ when Regexp
+ begin
+ pattern.match?(path)
+ rescue ArgumentError => e
+ return false if e.message.start_with?('invalid byte sequence')
+
+ raise e
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/ext/variable_force.rb b/rubocop/ext/variable_force.rb
new file mode 100644
index 00000000000..def284513ed
--- /dev/null
+++ b/rubocop/ext/variable_force.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Ext
+ module VariableForce
+ def scanned_node?(node)
+ scanned_nodes.include?(node)
+ end
+
+ def scanned_nodes
+ @scanned_nodes ||= Set.new.compare_by_identity
+ end
+ end
+ end
+end
+
+RuboCop::Cop::VariableForce.prepend RuboCop::Ext::VariableForce
diff --git a/rubocop/formatter/todo_formatter.rb b/rubocop/formatter/todo_formatter.rb
index b1c6d1c1688..5e49e2dc082 100644
--- a/rubocop/formatter/todo_formatter.rb
+++ b/rubocop/formatter/todo_formatter.rb
@@ -31,6 +31,7 @@ module RuboCop
@config_inspect_todo_dir = load_config_inspect_todo_dir
@config_old_todo_yml = load_config_old_todo_yml
check_multiple_configurations!
+ create_empty_todos(@config_inspect_todo_dir)
super
end
@@ -47,11 +48,9 @@ module RuboCop
def finished(_inspected_files)
@todos.values.sort_by(&:cop_name).each do |todo|
- todo.previously_disabled = previously_disabled?(todo)
- todo.grace_period = grace_period?(todo)
- validate_todo!(todo)
- path = @todo_dir.write(todo.cop_name, todo.to_yaml)
+ next unless configure_and_validate_todo(todo)
+ path = @todo_dir.write(todo.cop_name, todo.to_yaml)
output.puts "Written to #{relative_path(path)}\n"
end
end
@@ -82,6 +81,14 @@ module RuboCop
raise "Multiple configurations found for cops:\n#{list}\n"
end
+ # For each inspected cop TODO config create a TODO object to make sure
+ # the cop TODO config will be written even without any offenses.
+ def create_empty_todos(inspected_cop_config)
+ inspected_cop_config.each_key do |cop_name|
+ @todos[cop_name]
+ end
+ end
+
def config_for(todo)
cop_name = todo.cop_name
@@ -101,10 +108,15 @@ module RuboCop
GracefulFormatter.grace_period?(todo.cop_name, config)
end
- def validate_todo!(todo)
- return unless todo.previously_disabled && todo.grace_period
+ def configure_and_validate_todo(todo)
+ todo.previously_disabled = previously_disabled?(todo)
+ todo.grace_period = grace_period?(todo)
+
+ if todo.previously_disabled && todo.grace_period
+ raise "#{todo.cop_name}: Cop must be enabled to use `#{GracefulFormatter.grace_period_key_value}`."
+ end
- raise "#{todo.cop_name}: Cop must be enabled to use `#{GracefulFormatter.grace_period_key_value}`."
+ todo.generate?
end
def load_config_inspect_todo_dir
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index f14f4d33709..16a9aa53cd3 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -34,7 +34,11 @@ module RuboCop
def in_background_migration?(node)
filepath(node).include?('/lib/gitlab/background_migration/') ||
- filepath(node).include?('/ee/lib/ee/gitlab/background_migration/')
+ in_ee_background_migration?(node)
+ end
+
+ def in_ee_background_migration?(node)
+ filepath(node).include?('/ee/lib/ee/gitlab/background_migration/')
end
def in_deployment_migration?(node)
diff --git a/rubocop/rubocop-ruby30.yml b/rubocop/rubocop-ruby30.yml
new file mode 100644
index 00000000000..6cd3f66ce55
--- /dev/null
+++ b/rubocop/rubocop-ruby30.yml
@@ -0,0 +1,16 @@
+# RuboCop configuration adjustments during the transition time from Ruby 2.7 to Ruby 3.0.
+# This configuration should be removed after the transition has been completed.
+
+# Disable cops for now since their behavior changed in Ruby 3.0.
+# See https://gitlab.com/gitlab-org/gitlab/-/jobs/3068345492
+#
+# Migration plan:
+# * Generate TODOs for these cops (with Ruby 3.0) right before the switch to Ruby 3.0
+# * Put these cops back in "grace period" to ensure `master` stability
+# * Remove "grace period" after the switch
+# * Incrementally fix TODOs
+#
+Style/MutableConstant:
+ Enabled: false
+Style/RedundantFreeze:
+ Enabled: false
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index 8d8966144f1..129dbc75acf 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -124,3 +124,4 @@ UsageData/InstrumentationSuperclass:
- :RedisHLLMetric
- :RedisMetric
- :NumbersMetric
+ - :AggregatedMetric
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 5a5e76a87e2..6b5491b27fc 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,6 +1,11 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
+# Performance improvements to be upstreamed soon:
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/377469
+require_relative 'ext/path_util'
+require_relative 'ext/variable_force'
+
# Auto-require all cops under `rubocop/cop/**/*.rb`
Dir[File.join(__dir__, 'cop', '**', '*.rb')].sort.each(&method(:require))
diff --git a/scripts/api/cancel_pipeline.rb b/scripts/api/cancel_pipeline.rb
index 2de50dcee80..2667cfb9733 100755
--- a/scripts/api/cancel_pipeline.rb
+++ b/scripts/api/cancel_pipeline.rb
@@ -25,7 +25,7 @@ class CancelPipeline
attr_reader :project, :pipeline_id, :client
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = API::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/api/download_job_artifact.rb b/scripts/api/download_job_artifact.rb
index 23202ad3912..394ad8f3a3d 100755
--- a/scripts/api/download_job_artifact.rb
+++ b/scripts/api/download_job_artifact.rb
@@ -60,7 +60,7 @@ class ArtifactFinder
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = API::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/api/get_job_id.rb b/scripts/api/get_job_id.rb
index 2ee769d58f4..12535106a4c 100755
--- a/scripts/api/get_job_id.rb
+++ b/scripts/api/get_job_id.rb
@@ -95,7 +95,7 @@ class JobFinder
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = JobFinder::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/api/pipeline_failed_jobs.rb b/scripts/api/pipeline_failed_jobs.rb
new file mode 100644
index 00000000000..c25567af698
--- /dev/null
+++ b/scripts/api/pipeline_failed_jobs.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'gitlab'
+require 'optparse'
+require_relative 'default_options'
+
+class PipelineFailedJobs
+ def initialize(options)
+ @project = options.delete(:project)
+ @pipeline_id = options.delete(:pipeline_id)
+ @exclude_allowed_to_fail_jobs = options.delete(:exclude_allowed_to_fail_jobs)
+
+ # Force the token to be a string so that if api_token is nil, it's set to '',
+ # allowing unauthenticated requests (for forks).
+ api_token = options.delete(:api_token).to_s
+
+ warn "No API token given." if api_token.empty?
+
+ @client = Gitlab.client(
+ endpoint: options.delete(:endpoint) || API::DEFAULT_OPTIONS[:endpoint],
+ private_token: api_token
+ )
+ end
+
+ def execute
+ failed_jobs = []
+
+ client.pipeline_jobs(project, pipeline_id, scope: 'failed', per_page: 100).auto_paginate do |job|
+ next if exclude_allowed_to_fail_jobs && job.allow_failure
+
+ failed_jobs << job
+ end
+
+ client.pipeline_bridges(project, pipeline_id, scope: 'failed', per_page: 100).auto_paginate do |job|
+ next if exclude_allowed_to_fail_jobs && job.allow_failure
+
+ job.web_url = job.downstream_pipeline.web_url # job.web_url is linking to an invalid page
+ failed_jobs << job
+ end
+
+ failed_jobs
+ end
+
+ private
+
+ attr_reader :project, :pipeline_id, :exclude_allowed_to_fail_jobs, :client
+end
diff --git a/scripts/build_qa_image b/scripts/build_qa_image
new file mode 100755
index 00000000000..f4ecb8ed6b6
--- /dev/null
+++ b/scripts/build_qa_image
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+QA_IMAGE_NAME="gitlab-ee-qa"
+
+if [ "${CI_PROJECT_NAME}" == "gitlabhq" ] || [ "${CI_PROJECT_NAME}" == "gitlab-foss" ]; then
+ QA_IMAGE_NAME="gitlab-ce-qa"
+fi
+
+# Tag with commit SHA by default
+QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA}"
+# For branches, tag with slugified branch name. For tags, use the tag directly
+QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"
+
+DESTINATIONS="--destination=${QA_IMAGE} --destination=${QA_IMAGE_BRANCH}"
+
+# Auto-deploy tag format uses first 12 letters of commit SHA. Tag with that
+# reference also for EE images.
+if [ "${QA_IMAGE_NAME}" == "gitlab-ee-qa" ]; then
+ QA_IMAGE_FOR_AUTO_DEPLOY="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA:0:11}"
+ DESTINATIONS="${DESTINATIONS} --destination=$QA_IMAGE_FOR_AUTO_DEPLOY"
+fi
+
+echo "Building QA image for destinations: ${DESTINATIONS}"
+
+/kaniko/executor \
+ --context="${CI_PROJECT_DIR}" \
+ --dockerfile="${CI_PROJECT_DIR}/qa/Dockerfile" \
+ --build-arg=CHROME_VERSION="${CHROME_VERSION}" \
+ --build-arg=DOCKER_VERSION="${DOCKER_VERSION}" \
+ --build-arg=QA_BUILD_TARGET="${QA_BUILD_TARGET:-qa}" \
+ --cache=true \
+ ${DESTINATIONS}
diff --git a/scripts/changed-feature-flags b/scripts/changed-feature-flags
index ded6156bfa8..8c1b219e5a6 100755
--- a/scripts/changed-feature-flags
+++ b/scripts/changed-feature-flags
@@ -90,7 +90,7 @@ class GetFeatureFlagsFromFiles
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = API::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/clean-old-cached-assets b/scripts/clean-old-cached-assets
deleted file mode 100755
index 20889b7ffe6..00000000000
--- a/scripts/clean-old-cached-assets
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Clean up cached files that are older than 4 days
-find tmp/cache/assets/sprockets/ -type f -mtime +4 -execdir rm -- "{}" \;
-find tmp/cache/webpack-dlls/ -maxdepth 1 -type d -mtime +4 -exec rm -rf -- "{}" \;
-
-du -d 0 -h tmp/cache/assets/sprockets | cut -f1 | xargs -I % echo "tmp/cache/assets/sprockets/ is currently %"
-du -d 0 -h tmp/cache/webpack-dlls | cut -f1 | xargs -I % echo "tmp/cache/webpack-dlls is currently %"
diff --git a/scripts/failed_tests.rb b/scripts/failed_tests.rb
index fb13df7bf62..319961d277c 100755
--- a/scripts/failed_tests.rb
+++ b/scripts/failed_tests.rb
@@ -87,7 +87,7 @@ class FailedTests
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = {
previous_tests_report_path: 'test_results/previous/test_reports.json',
output_directory: 'tmp/previous_failed_tests/',
diff --git a/scripts/generate-e2e-pipeline b/scripts/generate-e2e-pipeline
index f541ae6665c..0d46a117719 100755
--- a/scripts/generate-e2e-pipeline
+++ b/scripts/generate-e2e-pipeline
@@ -18,8 +18,11 @@ if [ "$QA_SKIP_ALL_TESTS" == "true" ]; then
exit
fi
+# set custom cache key to override default cache in pipeline-common because we use bundle to install gitlab-qa gem
+qa_cache_key="qa-e2e-ruby-${RUBY_VERSION}-$(md5sum qa/Gemfile.lock | awk '{ print $1 }')"
variables=$(cat <<YML
variables:
+ GITLAB_QA_CACHE_KEY: "$qa_cache_key"
GITLAB_VERSION: "$(cat VERSION)"
COLORIZED_LOGS: "true"
QA_TESTS: "$QA_TESTS"
diff --git a/scripts/generate-failed-pipeline-slack-message.rb b/scripts/generate-failed-pipeline-slack-message.rb
new file mode 100755
index 00000000000..699e32872e6
--- /dev/null
+++ b/scripts/generate-failed-pipeline-slack-message.rb
@@ -0,0 +1,112 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require_relative 'api/pipeline_failed_jobs'
+
+finder_options = API::DEFAULT_OPTIONS.dup.merge(exclude_allowed_to_fail_jobs: true)
+failed_jobs = PipelineFailedJobs.new(finder_options).execute
+
+class SlackReporter
+ DEFAULT_FAILED_PIPELINE_REPORT_FILE = 'failed_pipeline_report.json'
+
+ def initialize(failed_jobs)
+ @failed_jobs = failed_jobs
+ @failed_pipeline_report_file = ENV.fetch('FAILED_PIPELINE_REPORT_FILE', DEFAULT_FAILED_PIPELINE_REPORT_FILE)
+ end
+
+ def report
+ payload = {
+ channel: ENV['SLACK_CHANNEL'],
+ username: "Failed pipeline reporter",
+ icon_emoji: ":boom:",
+ text: "*#{title}*",
+ blocks: [
+ {
+ type: "section",
+ text: {
+ type: "mrkdwn",
+ text: "*#{title}*"
+ }
+ },
+ {
+ type: "section",
+ fields: [
+ {
+ type: "mrkdwn",
+ text: "*Commit*\n#{commit_link}"
+ },
+ {
+ type: "mrkdwn",
+ text: "*Triggered by*\n#{triggered_by_link}"
+ }
+ ]
+ },
+ {
+ type: "section",
+ fields: [
+ {
+ type: "mrkdwn",
+ text: "*Source*\n#{source} from #{project_link}"
+ },
+ {
+ type: "mrkdwn",
+ text: "*Duration*\n#{pipeline_duration} minutes"
+ }
+ ]
+ },
+ {
+ type: "section",
+ text: {
+ type: "mrkdwn",
+ text: "*Failed jobs (#{failed_jobs.size}):* #{failed_jobs_list}"
+ }
+ }
+ ]
+ }
+
+ File.write(failed_pipeline_report_file, JSON.pretty_generate(payload))
+ end
+
+ private
+
+ attr_reader :failed_jobs, :failed_pipeline_report_file
+
+ def title
+ "Pipeline #{pipeline_link} for #{branch_link} failed"
+ end
+
+ def pipeline_link
+ "<#{ENV['CI_PIPELINE_URL']}|##{ENV['CI_PIPELINE_ID']}>"
+ end
+
+ def branch_link
+ "<#{ENV['CI_PROJECT_URL']}/-/commits/#{ENV['CI_COMMIT_REF_NAME']}|`#{ENV['CI_COMMIT_REF_NAME']}`>"
+ end
+
+ def pipeline_duration
+ ((Time.now - Time.parse(ENV['CI_PIPELINE_CREATED_AT'])) / 60.to_f).round(2)
+ end
+
+ def commit_link
+ "<#{ENV['CI_PROJECT_URL']}/-/commit/#{ENV['CI_COMMIT_SHA']}|#{ENV['CI_COMMIT_TITLE']}>"
+ end
+
+ def source
+ "`#{ENV['CI_PIPELINE_SOURCE']}`"
+ end
+
+ def project_link
+ "<#{ENV['CI_PROJECT_URL']}|#{ENV['CI_PROJECT_NAME']}>"
+ end
+
+ def triggered_by_link
+ "<#{ENV['CI_SERVER_URL']}/#{ENV['GITLAB_USER_LOGIN']}|#{ENV['GITLAB_USER_NAME']}>"
+ end
+
+ def failed_jobs_list
+ failed_jobs.map { |job| "<#{job.web_url}|#{job.name}>" }.join(', ')
+ end
+end
+
+SlackReporter.new(failed_jobs).report
diff --git a/scripts/generate-rspec-foss-impact-pipeline b/scripts/generate-rspec-foss-impact-pipeline
new file mode 100755
index 00000000000..3277f38ebe1
--- /dev/null
+++ b/scripts/generate-rspec-foss-impact-pipeline
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Script to generate `rspec foss-impact` test child pipeline with dynamically parallelized jobs.
+
+source scripts/utils.sh
+
+rspec_matching_tests_foss_path="${1}"
+pipeline_yml="${2}"
+
+test_file_count=$(wc -w "${rspec_matching_tests_foss_path}" | awk '{ print $1 }')
+echoinfo "test_file_count: ${test_file_count}"
+
+if [[ "${test_file_count}" -eq 0 ]]; then
+ skip_pipeline=".gitlab/ci/_skip.yml"
+
+ echo "Using ${skip_pipeline} due to no impacted FOSS rspec tests to run"
+ cp $skip_pipeline "$pipeline_yml"
+ exit
+fi
+
+# As of 2022-09-01:
+# $ find spec -type f | wc -l
+# 12825
+# and
+# $ find ee/spec -type f | wc -l
+# 5610
+# which gives a total of 18435 test files (`number_of_tests_in_total_in_the_test_suite`).
+#
+# Total time to run all tests (based on https://gitlab-org.gitlab.io/rspec_profiling_stats/) is 170183 seconds (`duration_of_the_test_suite_in_seconds`).
+#
+# This gives an approximate 170183 / 18435 = 9.2 seconds per test file (`average_test_file_duration_in_seconds`).
+#
+# If we want each test job to finish in 10 minutes, given we have 3 minutes of setup (`setup_duration_in_seconds`), then we need to give 7 minutes of testing to each test node (`optimal_test_runtime_duration_in_seconds`).
+# (7 * 60) / 9.2 = 45.6
+#
+# So if we'd want to run the full test suites in 10 minutes (`optimal_test_job_duration_in_seconds`), we'd need to run at max 45 test file per nodes (`optimal_test_file_count_per_node`).
+number_of_tests_in_total_in_the_test_suite=18435
+duration_of_the_test_suite_in_seconds=170183
+optimal_test_job_duration_in_seconds=600 # 10 minutes
+setup_duration_in_seconds=180 # 3 minutes
+
+optimal_test_runtime_duration_in_seconds=$(( optimal_test_job_duration_in_seconds - setup_duration_in_seconds ))
+echoinfo "optimal_test_runtime_duration_in_seconds: ${optimal_test_runtime_duration_in_seconds}"
+
+average_test_file_duration_in_seconds=$(( duration_of_the_test_suite_in_seconds / number_of_tests_in_total_in_the_test_suite ))
+echoinfo "average_test_file_duration_in_seconds: ${average_test_file_duration_in_seconds}"
+
+optimal_test_file_count_per_node=$(( optimal_test_runtime_duration_in_seconds / average_test_file_duration_in_seconds ))
+echoinfo "optimal_test_file_count_per_node: ${optimal_test_file_count_per_node}"
+
+node_count=$(( test_file_count / optimal_test_file_count_per_node ))
+echoinfo "node_count: ${node_count}"
+
+echoinfo "Optimal node count for 'rspec foss-impact' jobs is ${node_count}."
+
+MAX_NODES_COUNT=50 # Maximum parallelization allowed by GitLab
+if [[ "${node_count}" -gt "${MAX_NODES_COUNT}" ]]; then
+ echoinfo "We don't want to parallelize 'rspec foss-impact' to more than ${MAX_NODES_COUNT} jobs for now! Decreasing the parallelization to ${MAX_NODES_COUNT}."
+ node_count=${MAX_NODES_COUNT}
+fi
+
+ruby -rerb -e "puts ERB.new(File.read('.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb')).result_with_hash(parallel_value: ${node_count})" > "${pipeline_yml}"
+
+echosuccess "Generated ${pipeline_yml} pipeline with following content:"
+cat "${pipeline_yml}"
diff --git a/scripts/gitlab_component_helpers.sh b/scripts/gitlab_component_helpers.sh
new file mode 100644
index 00000000000..0d72f940036
--- /dev/null
+++ b/scripts/gitlab_component_helpers.sh
@@ -0,0 +1,151 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}"
+
+export GITLAB_COM_CANONICAL_PROJECT_ID="278964" # https://gitlab.com/gitlab-org/gitlab
+export JIHULAB_COM_CANONICAL_PROJECT_ID="13953" # https://jihulab.com/gitlab-cn/gitlab
+export CANONICAL_PROJECT_ID="${GITLAB_COM_CANONICAL_PROJECT_ID}"
+
+# By default, we only want to store/retrieve packages from GitLab.com...
+export API_V4_URL="https://gitlab.com/api/v4"
+
+# Unless we're in the JiHu project, which needs to use its own package registry
+if [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then
+ export API_V4_URL="${CI_API_V4_URL}"
+ export CANONICAL_PROJECT_ID="${JIHULAB_COM_CANONICAL_PROJECT_ID}"
+fi
+
+export API_PACKAGES_BASE_URL="${API_V4_URL}/projects/${CANONICAL_PROJECT_ID}/packages/generic"
+
+export UPLOAD_TO_CURRENT_SERVER="false"
+# We only want to upload artifacts to https://gitlab.com and https://jihulab.com instances
+if [[ "${CI_SERVER_HOST}" = "gitlab.com" ]] || [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then
+ export UPLOAD_TO_CURRENT_SERVER="true"
+fi
+
+export UPLOAD_PACKAGE_FLAG="false"
+# And only if we're in a pipeline from the canonical project
+if [[ "${UPLOAD_TO_CURRENT_SERVER}" = "true" ]] && [[ "${CI_PROJECT_ID}" = "${CANONICAL_PROJECT_ID}" ]]; then
+ export UPLOAD_PACKAGE_FLAG="true"
+fi
+
+# Workhorse constants
+export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse"
+export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE"
+export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)}
+export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz"
+export GITLAB_WORKHORSE_PACKAGE_URL="${API_PACKAGES_BASE_URL}/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}"
+
+# Assets constants
+export GITLAB_ASSETS_PATHS_LIST="cached-assets-hash.txt app/assets/javascripts/locale/**/app.js public/assets/"
+export GITLAB_ASSETS_PACKAGE_VERSION="v2" # bump this version each time GITLAB_ASSETS_PATHS_LIST is changed
+
+export GITLAB_EDITION="ee"
+if [[ "${FOSS_ONLY:-no}" = "1" ]] || [[ "${CI_PROJECT_NAME}" = "gitlab-foss" ]]; then
+ export GITLAB_EDITION="foss"
+fi
+
+export GITLAB_ASSETS_HASH="${GITLAB_ASSETS_HASH:-"NO_HASH"}"
+export GITLAB_ASSETS_PACKAGE="assets-${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}-${GITLAB_ASSETS_PACKAGE_VERSION}.tar.gz"
+export GITLAB_ASSETS_PACKAGE_URL="${API_PACKAGES_BASE_URL}/assets/${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}/${GITLAB_ASSETS_PACKAGE}"
+
+# Generic helper functions
+function archive_doesnt_exist() {
+ local package_url="${1}"
+
+ status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}")
+
+ [[ "${status}" != "200" ]]
+}
+
+function create_package() {
+ local archive_filename="${1}"
+ local paths_to_archive="${2}"
+ local tar_working_folder="${3:-.}"
+
+ echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive}'"
+ tar -czf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive}
+ du -h ${archive_filename}
+}
+
+function upload_package() {
+ local archive_filename="${1}"
+ local package_url="${2}"
+ local token_header="${CURL_TOKEN_HEADER}"
+ local token="${CI_JOB_TOKEN}"
+
+ if [[ "${UPLOAD_PACKAGE_FLAG}" = "false" ]]; then
+ echoerr "The archive ${archive_filename} isn't supposed to be uploaded for this instance (${CI_SERVER_HOST}) & project (${CI_PROJECT_PATH})!"
+ exit 1
+ fi
+
+ echoinfo "Uploading ${archive_filename} to ${package_url} ..."
+ curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}"
+}
+
+function read_curl_package() {
+ local package_url="${1}"
+ local token_header="${CURL_TOKEN_HEADER}"
+ local token="${CI_JOB_TOKEN}"
+
+ echoinfo "Downloading from ${package_url} ..."
+
+ curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}"
+}
+
+function extract_package() {
+ local tar_working_folder="${1:-.}"
+ mkdir -p "${tar_working_folder}"
+
+ echoinfo "Extracting archive to ${tar_working_folder}"
+
+ tar -xz -C ${tar_working_folder} < /dev/stdin
+}
+
+# Workhorse functions
+function gitlab_workhorse_archive_doesnt_exist() {
+ archive_doesnt_exist "${GITLAB_WORKHORSE_PACKAGE_URL}"
+}
+
+function create_gitlab_workhorse_package() {
+ create_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_FOLDER}" "${TMP_TEST_FOLDER}"
+}
+
+function upload_gitlab_workhorse_package() {
+ upload_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_PACKAGE_URL}"
+}
+
+function download_and_extract_gitlab_workhorse_package() {
+ read_curl_package "${GITLAB_WORKHORSE_PACKAGE_URL}" | extract_package "${TMP_TEST_FOLDER}"
+}
+
+function select_gitlab_workhorse_essentials() {
+ local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}"
+ local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
+
+ mkdir -p ${tmp_path}
+ cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd -
+ rm -rf ${original_gitlab_workhorse_path}
+
+ # Move the temp folder to its final destination
+ mv ${tmp_path} ${TMP_TEST_FOLDER}
+}
+
+# Assets functions
+function gitlab_assets_archive_doesnt_exist() {
+ archive_doesnt_exist "${GITLAB_ASSETS_PACKAGE_URL}"
+}
+
+function download_and_extract_gitlab_assets() {
+ read_curl_package "${GITLAB_ASSETS_PACKAGE_URL}" | extract_package
+}
+
+function create_gitlab_assets_package() {
+ create_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PATHS_LIST}"
+}
+
+function upload_gitlab_assets_package() {
+ upload_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PACKAGE_URL}"
+}
diff --git a/scripts/gitlab_workhorse_component_helpers.sh b/scripts/gitlab_workhorse_component_helpers.sh
deleted file mode 100644
index ebd43a125b9..00000000000
--- a/scripts/gitlab_workhorse_component_helpers.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}"
-export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse"
-export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE"
-export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)}
-export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz"
-export GITLAB_WORKHORSE_PACKAGE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}"
-
-function gitlab_workhorse_archive_doesnt_exist() {
- local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
-
- status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}")
-
- [[ "${status}" != "200" ]]
-}
-
-function create_gitlab_workhorse_package() {
- local archive_filename="${GITLAB_WORKHORSE_PACKAGE}"
- local folder_to_archive="${GITLAB_WORKHORSE_FOLDER}"
- local workhorse_folder_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
- local tar_working_folder="${TMP_TEST_FOLDER}"
-
- echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive}'"
- tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive}
- du -h ${archive_filename}
-}
-
-function extract_gitlab_workhorse_package() {
- local tar_working_folder="${TMP_TEST_FOLDER}"
- mkdir -p "${tar_working_folder}"
-
- echoinfo "Extracting archive to ${tar_working_folder}"
-
- tar -xzv -C ${tar_working_folder} < /dev/stdin
-}
-
-function upload_gitlab_workhorse_package() {
- local archive_filename="${GITLAB_WORKHORSE_PACKAGE}"
- local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
- local token_header="${CURL_TOKEN_HEADER}"
- local token="${CI_JOB_TOKEN}"
-
- echoinfo "Uploading ${archive_filename} to ${package_url} ..."
- curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}"
-}
-
-function read_curl_gitlab_workhorse_package() {
- local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
- local token_header="${CURL_TOKEN_HEADER}"
- local token="${CI_JOB_TOKEN}"
-
- echoinfo "Downloading from ${package_url} ..."
-
- curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}"
-}
-
-function download_and_extract_gitlab_workhorse_package() {
- read_curl_gitlab_workhorse_package | extract_gitlab_workhorse_package
-}
-
-function select_gitlab_workhorse_essentials() {
- local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}"
- local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
-
- mkdir -p ${tmp_path}
- cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd -
- rm -rf ${original_gitlab_workhorse_path}
-
- # Move the temp folder to its final destination
- mv ${tmp_path} ${TMP_TEST_FOLDER}
-}
diff --git a/scripts/glfm/verify-all-generated-files-are-up-to-date.rb b/scripts/glfm/verify-all-generated-files-are-up-to-date.rb
new file mode 100755
index 00000000000..7710997e3ed
--- /dev/null
+++ b/scripts/glfm/verify-all-generated-files-are-up-to-date.rb
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative '../lib/glfm/verify_all_generated_files_are_up_to_date'
+Glfm::VerifyAllGeneratedFilesAreUpToDate.new.process
diff --git a/scripts/lib/glfm/constants.rb b/scripts/lib/glfm/constants.rb
index e5790bbdd88..d020d2fec5c 100644
--- a/scripts/lib/glfm/constants.rb
+++ b/scripts/lib/glfm/constants.rb
@@ -10,25 +10,29 @@ module Glfm
# GitHub Flavored Markdown specification file
GHFM_SPEC_TXT_URI = 'https://raw.githubusercontent.com/github/cmark-gfm/master/test/spec.txt'
GHFM_SPEC_VERSION = '0.29'
- GHFM_SPEC_TXT_FILENAME = "ghfm_spec_v_#{GHFM_SPEC_VERSION}.txt"
- GHFM_SPEC_TXT_PATH = specification_path.join('input/github_flavored_markdown', GHFM_SPEC_TXT_FILENAME)
+ GHFM_SPEC_MD_FILENAME = "ghfm_spec_v_#{GHFM_SPEC_VERSION}.md"
+ GHFM_SPEC_MD_PATH = specification_path.join('input/github_flavored_markdown', GHFM_SPEC_MD_FILENAME)
# GitLab Flavored Markdown specification files
specification_input_glfm_path = specification_path.join('input/gitlab_flavored_markdown')
- GLFM_INTRO_TXT_PATH = specification_input_glfm_path.join('glfm_intro.txt')
- GLFM_EXAMPLES_TXT_PATH = specification_input_glfm_path.join('glfm_canonical_examples.txt')
+ GLFM_INTRO_MD_PATH = specification_input_glfm_path.join('glfm_intro.md')
+ GLFM_OFFICIAL_SPECIFICATION_EXAMPLES_MD_PATH =
+ specification_input_glfm_path.join('glfm_official_specification_examples.md')
+ GLFM_INTERNAL_EXTENSION_EXAMPLES_MD_PATH = specification_input_glfm_path.join('glfm_internal_extension_examples.md')
GLFM_EXAMPLE_STATUS_YML_PATH = specification_input_glfm_path.join('glfm_example_status.yml')
GLFM_EXAMPLE_METADATA_YML_PATH =
specification_input_glfm_path.join('glfm_example_metadata.yml')
GLFM_EXAMPLE_NORMALIZATIONS_YML_PATH = specification_input_glfm_path.join('glfm_example_normalizations.yml')
- GLFM_SPEC_TXT_PATH = specification_path.join('output/spec.txt')
+ GLFM_SPEC_OUTPUT_PATH = specification_path.join('output')
+ GLFM_SPEC_TXT_PATH = GLFM_SPEC_OUTPUT_PATH.join('spec.txt')
+ GLFM_SPEC_HTML_PATH = GLFM_SPEC_OUTPUT_PATH.join('spec.html')
# Example Snapshot (ES) files
- es_fixtures_path = File.expand_path("../../../glfm_specification/example_snapshots", __dir__)
- ES_EXAMPLES_INDEX_YML_PATH = File.join(es_fixtures_path, 'examples_index.yml')
- ES_MARKDOWN_YML_PATH = File.join(es_fixtures_path, 'markdown.yml')
- ES_HTML_YML_PATH = File.join(es_fixtures_path, 'html.yml')
- ES_PROSEMIRROR_JSON_YML_PATH = File.join(es_fixtures_path, 'prosemirror_json.yml')
+ EXAMPLE_SNAPSHOTS_PATH = File.expand_path("../../../glfm_specification/example_snapshots", __dir__)
+ ES_EXAMPLES_INDEX_YML_PATH = File.join(EXAMPLE_SNAPSHOTS_PATH, 'examples_index.yml')
+ ES_MARKDOWN_YML_PATH = File.join(EXAMPLE_SNAPSHOTS_PATH, 'markdown.yml')
+ ES_HTML_YML_PATH = File.join(EXAMPLE_SNAPSHOTS_PATH, 'html.yml')
+ ES_PROSEMIRROR_JSON_YML_PATH = File.join(EXAMPLE_SNAPSHOTS_PATH, 'prosemirror_json.yml')
# Other constants used for processing files
GLFM_SPEC_TXT_HEADER = <<~MARKDOWN
diff --git a/scripts/lib/glfm/render_static_html.rb b/scripts/lib/glfm/render_static_html.rb
index 8d72aec7c3b..6af73cd845d 100644
--- a/scripts/lib/glfm/render_static_html.rb
+++ b/scripts/lib/glfm/render_static_html.rb
@@ -20,21 +20,26 @@ require_relative 'shared'
# Factorybot factory methods to create persisted model objects with stable
# and consistent data values, to ensure consistent example snapshot HTML
# across various machines and environments. RSpec also makes it easy to invoke
-# the API # and obtain the response.
+# the API and obtain the response.
#
# It is intended to be invoked as a helper subprocess from the `update_example_snapshots.rb`
# script class. It's not intended to be run or used directly. This usage is also reinforced
# by not naming the file with a `_spec.rb` ending.
-RSpec.describe 'Render Static HTML', :api, type: :request do # rubocop:disable RSpec/TopLevelDescribePath
+RSpec.describe 'Render Static HTML', :api, type: :request do
include Glfm::Constants
include Glfm::Shared
# noinspection RailsParamDefResolve (RubyMine can't find the shared context from this file location)
include_context 'with GLFM example snapshot fixtures'
- it 'can create a project dependency graph using factories' do
+ it do
markdown_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_MARKDOWN_YML_PATH')), symbolize_names: true)
- metadata_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_METADATA_YML_PATH')), symbolize_names: true)
+ metadata_hash =
+ if input_metadata_yml_path = ENV['INPUT_METADATA_YML_PATH']
+ YAML.safe_load(File.open(input_metadata_yml_path), symbolize_names: true) || {}
+ else
+ {}
+ end
# NOTE: We cannot parallelize this loop like the Javascript WYSIWYG example generation does,
# because the rspec `post` API cannot be parallized (it is not thread-safe, it can't find
@@ -66,8 +71,7 @@ RSpec.describe 'Render Static HTML', :api, type: :request do # rubocop:disable R
private
def write_output_file(static_html_hash)
- tmpfile = File.open(ENV.fetch('OUTPUT_STATIC_HTML_TEMPFILE_PATH'), 'w')
yaml_string = dump_yaml_with_formatting(static_html_hash)
- write_file(tmpfile, yaml_string)
+ write_file(ENV.fetch('OUTPUT_STATIC_HTML_TEMPFILE_PATH'), yaml_string)
end
end
diff --git a/scripts/lib/glfm/update_example_snapshots.rb b/scripts/lib/glfm/update_example_snapshots.rb
index 7dc0d0f7c4b..9075260e748 100644
--- a/scripts/lib/glfm/update_example_snapshots.rb
+++ b/scripts/lib/glfm/update_example_snapshots.rb
@@ -5,11 +5,12 @@ require 'yaml'
require 'psych'
require 'tempfile'
require 'open3'
+require 'active_support/core_ext/enumerable'
require_relative 'constants'
require_relative 'shared'
require_relative 'parse_examples'
-# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-example-snapshotsrb-script
# for details on the implementation and usage of this script. This developers guide
# contains diagrams and documentation of this script,
# including explanations and examples of all files it reads and writes.
@@ -29,8 +30,6 @@ module Glfm
def process(skip_static_and_wysiwyg: false)
output('Updating example snapshots...')
- output('(Skipping static HTML generation)') if skip_static_and_wysiwyg
-
output("Reading #{GLFM_SPEC_TXT_PATH}...")
glfm_spec_txt_lines = File.open(GLFM_SPEC_TXT_PATH).readlines
@@ -115,11 +114,13 @@ module Glfm
def write_snapshot_example_files(all_examples, skip_static_and_wysiwyg:)
output("Reading #{GLFM_EXAMPLE_STATUS_YML_PATH}...")
- glfm_examples_statuses = YAML.safe_load(File.open(GLFM_EXAMPLE_STATUS_YML_PATH), symbolize_names: true)
+ glfm_examples_statuses = YAML.safe_load(File.open(GLFM_EXAMPLE_STATUS_YML_PATH), symbolize_names: true) || {}
validate_glfm_example_status_yml(glfm_examples_statuses)
write_examples_index_yml(all_examples)
+ validate_glfm_config_file_example_names(all_examples)
+
write_markdown_yml(all_examples)
if skip_static_and_wysiwyg
@@ -151,6 +152,50 @@ module Glfm
end
end
+ def validate_glfm_config_file_example_names(all_examples)
+ valid_example_names = all_examples.pluck(:name).map(&:to_sym) # rubocop:disable CodeReuse/ActiveRecord
+
+ # We are re-reading GLFM_EXAMPLE_STATUS_YML_PATH here, but that's OK, it's a small file, and rereading it
+ # allows us to handle it in the same loop as the other manually-curated config files.
+ [
+ GLFM_EXAMPLE_STATUS_YML_PATH,
+ GLFM_EXAMPLE_METADATA_YML_PATH,
+ GLFM_EXAMPLE_NORMALIZATIONS_YML_PATH
+ ].each do |path|
+ output("Reading #{path}...")
+ io = File.open(path)
+ config_file_examples = YAML.safe_load(io, symbolize_names: true, aliases: true)
+
+ # Skip validation if the config file is empty
+ next unless config_file_examples
+
+ config_file_example_names = config_file_examples.keys
+
+ # Validate that all example names exist in the config file refer to an existing example in `examples_index.yml`,
+ # unless it starts with the special prefix `00_`, which is preserved for usage as YAML anchors.
+ invalid_name = config_file_example_names.detect do |name|
+ !name.start_with?('00_') && valid_example_names.exclude?(name)
+ end
+ next unless invalid_name
+
+ # NOTE: The extra spaces before punctuation in the error message allows for easier copy/pasting of the paths.
+ err_msg =
+ <<~TXT
+
+ Error in input specification config file #{path} :
+
+ Config file entry named #{invalid_name}
+ does not have a corresponding example entry in
+ #{ES_EXAMPLES_INDEX_YML_PATH} .
+
+ Please delete or rename this config file entry.
+
+ If this entry is being used as a YAML anchor, please rename it to start with '00_'.
+ TXT
+ raise err_msg
+ end
+ end
+
def write_examples_index_yml(all_examples)
generate_and_write_for_all_examples(
all_examples, ES_EXAMPLES_INDEX_YML_PATH, literal_scalars: false
@@ -219,7 +264,7 @@ module Glfm
# NOTE 2: We run this as an RSpec process, for the same reasons we run via Jest process below:
# because that's the easiest way to ensure a reliable, fully-configured environment in which
- # to execute the markdown-generation logic. Also, in the static/backend case, Rspec
+ # to execute the markdown-processing logic. Also, in the static/backend case, Rspec
# provides the easiest and most reliable way to generate example data via Factorybot
# creation of stable model records. This ensures consistent snapshot values across
# machines/environments.
@@ -244,7 +289,7 @@ module Glfm
wysiwyg_html_and_json_tempfile_path = Dir::Tmpname.create(WYSIWYG_HTML_AND_JSON_TEMPFILE_BASENAME) {}
ENV['OUTPUT_WYSIWYG_HTML_AND_JSON_TEMPFILE_PATH'] = wysiwyg_html_and_json_tempfile_path
- cmd = %(yarn jest --testMatch '**/render_wysiwyg_html_and_json.js' #{__dir__}/render_wysiwyg_html_and_json.js)
+ cmd = "yarn jest --testMatch '**/render_wysiwyg_html_and_json.js' #{__dir__}/render_wysiwyg_html_and_json.js"
run_external_cmd(cmd)
output("Reading generated WYSIWYG HTML and prosemirror JSON from tempfile " \
diff --git a/scripts/lib/glfm/update_specification.rb b/scripts/lib/glfm/update_specification.rb
index 73c23d40de5..c7264547e44 100644
--- a/scripts/lib/glfm/update_specification.rb
+++ b/scripts/lib/glfm/update_specification.rb
@@ -2,26 +2,45 @@
require 'fileutils'
require 'open-uri'
require 'pathname'
+require 'tempfile'
+require 'yaml'
require_relative 'constants'
require_relative 'shared'
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-specificationrb-script
+# for details on the implementation and usage of this script. This developers guide
+# contains diagrams and documentation of this script,
+# including explanations and examples of all files it reads and writes.
+#
+# Also note that this script is intentionally written in a pure-functional (not OO) style,
+# with no dependencies on Rails or the GitLab libraries. These choices are intended to make
+# it faster and easier to test and debug.
module Glfm
class UpdateSpecification
include Constants
include Shared
- def process
+ def process(skip_spec_html_generation: false)
output('Updating specification...')
- ghfm_spec_txt_lines = load_ghfm_spec_txt
- glfm_spec_txt_string = build_glfm_spec_txt(ghfm_spec_txt_lines)
+
+ ghfm_spec_lines = load_ghfm_spec
+ glfm_spec_txt_string = build_glfm_spec_txt(ghfm_spec_lines)
write_glfm_spec_txt(glfm_spec_txt_string)
+
+ if skip_spec_html_generation
+ output("Skipping GLFM spec.html generation...")
+ return
+ end
+
+ glfm_spec_html_string = generate_glfm_spec_html(glfm_spec_txt_string)
+ write_glfm_spec_html(glfm_spec_html_string)
end
private
- def load_ghfm_spec_txt
+ def load_ghfm_spec
# We only re-download the GitHub Flavored Markdown specification if the
- # UPDATE_GHFM_SPEC_TXT environment variable is set to true, which should only
+ # UPDATE_GHFM_SPEC_MD environment variable is set to true, which should only
# ever be done manually and locally, never in CI. This provides some security
# protection against a possible injection attack vector, if the GitHub-hosted
# version of the spec is ever temporarily compromised with an injection attack.
@@ -29,40 +48,44 @@ module Glfm
# This also avoids doing external network access to download the file
# in CI jobs, which can avoid potentially flaky builds if the GitHub-hosted
# version of the file is temporarily unavailable.
- if ENV['UPDATE_GHFM_SPEC_TXT'] == 'true'
- download_and_write_ghfm_spec_txt
+ if ENV['UPDATE_GHFM_SPEC_MD'] == 'true'
+ update_ghfm_spec_md
else
- read_existing_ghfm_spec_txt
+ read_existing_ghfm_spec_md
end
end
- def read_existing_ghfm_spec_txt
- output("Reading existing #{GHFM_SPEC_TXT_PATH}...")
- File.open(GHFM_SPEC_TXT_PATH).readlines
+ def read_existing_ghfm_spec_md
+ output("Reading existing #{GHFM_SPEC_MD_PATH}...")
+ File.open(GHFM_SPEC_MD_PATH).readlines
end
- def download_and_write_ghfm_spec_txt
+ def update_ghfm_spec_md
output("Downloading #{GHFM_SPEC_TXT_URI}...")
- ghfm_spec_txt_uri_io = URI.open(GHFM_SPEC_TXT_URI)
+ # NOTE: We use `URI.parse` to avoid RuboCop warning "Security/Open",
+ # even though we are using a trusted URI from a string literal constant.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98656#note_1138595002 for details.
+ ghfm_spec_txt_uri_parsed = URI.parse(GHFM_SPEC_TXT_URI)
+ ghfm_spec_txt_uri_io = ghfm_spec_txt_uri_parsed.open
# Read IO stream into an array of lines for easy processing later
- ghfm_spec_txt_lines = ghfm_spec_txt_uri_io.readlines
- raise "Unable to read lines from #{GHFM_SPEC_TXT_URI}" if ghfm_spec_txt_lines.empty?
+ ghfm_spec_lines = ghfm_spec_txt_uri_io.readlines
+ raise "Unable to read lines from #{GHFM_SPEC_TXT_URI}" if ghfm_spec_lines.empty?
# Make sure the GHFM spec version has not changed
- validate_expected_spec_version!(ghfm_spec_txt_lines[2])
+ validate_expected_spec_version!(ghfm_spec_lines[2])
# Reset IO stream and re-read into a single string for easy writing
# noinspection RubyNilAnalysis
ghfm_spec_txt_uri_io.seek(0)
- ghfm_spec_txt_string = ghfm_spec_txt_uri_io.read
- raise "Unable to read string from #{GHFM_SPEC_TXT_URI}" unless ghfm_spec_txt_string
+ ghfm_spec_string = ghfm_spec_txt_uri_io.read
+ raise "Unable to read string from #{GHFM_SPEC_TXT_URI}" unless ghfm_spec_string
- output("Writing #{GHFM_SPEC_TXT_PATH}...")
- GHFM_SPEC_TXT_PATH.dirname.mkpath
- write_file(GHFM_SPEC_TXT_PATH, ghfm_spec_txt_string)
+ output("Writing #{GHFM_SPEC_MD_PATH}...")
+ GHFM_SPEC_MD_PATH.dirname.mkpath
+ write_file(GHFM_SPEC_MD_PATH, ghfm_spec_string)
- ghfm_spec_txt_lines
+ ghfm_spec_lines
end
def validate_expected_spec_version!(version_line)
@@ -76,7 +99,7 @@ module Glfm
glfm_spec_txt_lines = ghfm_spec_txt_lines.dup
replace_header(glfm_spec_txt_lines)
replace_intro_section(glfm_spec_txt_lines)
- insert_examples_txt(glfm_spec_txt_lines)
+ insert_examples(glfm_spec_txt_lines)
glfm_spec_txt_lines.join('')
end
@@ -85,13 +108,13 @@ module Glfm
end
def replace_intro_section(spec_txt_lines)
- glfm_intro_txt_lines = File.open(GLFM_INTRO_TXT_PATH).readlines
- raise "Unable to read lines from #{GLFM_INTRO_TXT_PATH}" if glfm_intro_txt_lines.empty?
+ glfm_intro_md_lines = File.open(GLFM_INTRO_MD_PATH).readlines
+ raise "Unable to read lines from #{GLFM_INTRO_MD_PATH}" if glfm_intro_md_lines.empty?
ghfm_intro_header_begin_index = spec_txt_lines.index do |line|
line =~ INTRODUCTION_HEADER_LINE_TEXT
end
- raise "Unable to locate introduction header line in #{GHFM_SPEC_TXT_PATH}" if ghfm_intro_header_begin_index.nil?
+ raise "Unable to locate introduction header line in #{GHFM_SPEC_MD_PATH}" if ghfm_intro_header_begin_index.nil?
# Find the index of the next header after the introduction header, starting from the index
# of the introduction header this is the length of the intro section
@@ -100,20 +123,29 @@ module Glfm
end
# Replace the intro section with the GitLab flavored Markdown intro section
- spec_txt_lines[ghfm_intro_header_begin_index, ghfm_intro_section_length] = glfm_intro_txt_lines
+ spec_txt_lines[ghfm_intro_header_begin_index, ghfm_intro_section_length] = glfm_intro_md_lines
end
- def insert_examples_txt(spec_txt_lines)
- glfm_examples_txt_lines = File.open(GLFM_EXAMPLES_TXT_PATH).readlines
- raise "Unable to read lines from #{GLFM_EXAMPLES_TXT_PATH}" if glfm_examples_txt_lines.empty?
+ def insert_examples(spec_txt_lines)
+ official_spec_lines = File.open(GLFM_OFFICIAL_SPECIFICATION_EXAMPLES_MD_PATH).readlines
+ raise "Unable to read lines from #{GLFM_OFFICIAL_SPECIFICATION_EXAMPLES_MD_PATH}" if official_spec_lines.empty?
+
+ internal_extension_lines = File.open(GLFM_INTERNAL_EXTENSION_EXAMPLES_MD_PATH).readlines
+ raise "Unable to read lines from #{GLFM_INTERNAL_EXTENSION_EXAMPLES_MD_PATH}" if internal_extension_lines.empty?
ghfm_end_tests_comment_index = spec_txt_lines.index do |line|
line =~ END_TESTS_COMMENT_LINE_TEXT
end
- raise "Unable to locate 'END TESTS' comment line in #{GHFM_SPEC_TXT_PATH}" if ghfm_end_tests_comment_index.nil?
+ raise "Unable to locate 'END TESTS' comment line in #{GHFM_SPEC_MD_PATH}" if ghfm_end_tests_comment_index.nil?
# Insert the GLFM examples before the 'END TESTS' comment line
- spec_txt_lines[ghfm_end_tests_comment_index - 1] = ["\n", glfm_examples_txt_lines, "\n"].flatten
+ spec_txt_lines[ghfm_end_tests_comment_index - 1] = [
+ "\n",
+ official_spec_lines,
+ "\n",
+ internal_extension_lines,
+ "\n"
+ ].flatten
spec_txt_lines
end
@@ -123,5 +155,49 @@ module Glfm
FileUtils.mkdir_p(Pathname.new(GLFM_SPEC_TXT_PATH).dirname)
write_file(GLFM_SPEC_TXT_PATH, glfm_spec_txt_string)
end
+
+ def generate_glfm_spec_html(glfm_spec_txt_string)
+ output("Generating spec.html from spec.txt markdown...")
+
+ input_markdown_yml_string = <<~MARKDOWN
+ ---
+ spec_txt: |
+ #{glfm_spec_txt_string.gsub(/^/, ' ')}
+ MARKDOWN
+
+ # NOTE: We must copy the input YAML file used by the `render_static_html.rb`
+ # to a separate temporary file in order for the script to read them, because it is run in
+ # a separate subprocess, and during unit testing we are unable to substitute the mock
+ # StringIO when reading the input files in the subprocess.
+ ENV['INPUT_MARKDOWN_YML_PATH'] = Dir::Tmpname.create(MARKDOWN_TEMPFILE_BASENAME) do |path|
+ write_file(path, input_markdown_yml_string)
+ end
+
+ # NOTE 1: We shell out to perform the conversion of markdown to static HTML by invoking a
+ # separate subprocess. This allows us to avoid using the Rails API or environment in this
+ # script, which makes developing and running the unit tests for this script much faster,
+ # because they can use 'fast_spec_helper' which does not require the entire Rails environment.
+
+ # NOTE 2: We run this as an RSpec process, for the same reasons we run via Jest process below:
+ # because that's the easiest way to ensure a reliable, fully-configured environment in which
+ # to execute the markdown-processing logic. Also, in the static/backend case.
+
+ # Dir::Tmpname.create requires a block, but we are using the non-block form to get the path
+ # via the return value, so we pass an empty block to avoid an error.
+ static_html_tempfile_path = Dir::Tmpname.create(STATIC_HTML_TEMPFILE_BASENAME) {}
+ ENV['OUTPUT_STATIC_HTML_TEMPFILE_PATH'] = static_html_tempfile_path
+
+ cmd = %(bin/rspec #{__dir__}/render_static_html.rb)
+ run_external_cmd(cmd)
+
+ output("Reading generated spec.html from tempfile #{static_html_tempfile_path}...")
+ YAML.safe_load(File.open(static_html_tempfile_path), symbolize_names: true).fetch(:spec_txt)
+ end
+
+ def write_glfm_spec_html(glfm_spec_html_string)
+ output("Writing #{GLFM_SPEC_TXT_PATH}...")
+ FileUtils.mkdir_p(Pathname.new(GLFM_SPEC_HTML_PATH).dirname)
+ write_file(GLFM_SPEC_HTML_PATH, "#{glfm_spec_html_string}\n")
+ end
end
end
diff --git a/scripts/lib/glfm/verify_all_generated_files_are_up_to_date.rb b/scripts/lib/glfm/verify_all_generated_files_are_up_to_date.rb
new file mode 100644
index 00000000000..0b824fc589d
--- /dev/null
+++ b/scripts/lib/glfm/verify_all_generated_files_are_up_to_date.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+require_relative 'constants'
+require_relative 'shared'
+
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#verify-all-generated-files-are-up-to-daterb-script
+# for details on the implementation and usage of this script. This developers guide
+# contains diagrams and documentation of this script,
+# including explanations and examples of all files it reads and writes.
+module Glfm
+ class VerifyAllGeneratedFilesAreUpToDate
+ include Constants
+ include Shared
+
+ def process
+ verify_cmd = "git status --porcelain #{GLFM_SPEC_OUTPUT_PATH} #{EXAMPLE_SNAPSHOTS_PATH}"
+ verify_cmd_output = run_external_cmd(verify_cmd)
+ unless verify_cmd_output.empty?
+ msg = "ERROR: Cannot run `#{__FILE__}` because `#{verify_cmd}` shows the following uncommitted changes:\n" \
+ "#{verify_cmd_output}"
+ raise(msg)
+ end
+
+ output('Verifying all generated files are up to date after running GLFM scripts...')
+
+ output("Running `yarn install --frozen-lockfile` to ensure `yarn check-dependencies` doesn't fail...")
+ run_external_cmd('yarn install --frozen-lockfile')
+
+ # noinspection RubyMismatchedArgumentType
+ update_specification_script = File.expand_path('../../glfm/update-specification.rb', __dir__)
+ # noinspection RubyMismatchedArgumentType
+ update_example_snapshots_script = File.expand_path('../../glfm/update-example-snapshots.rb', __dir__)
+
+ output("Running `#{update_specification_script}`...")
+ run_external_cmd(update_specification_script)
+
+ output("Running `#{update_example_snapshots_script}`...")
+ run_external_cmd(update_example_snapshots_script)
+
+ output("Running `#{verify_cmd}` to check that no modifications to generated files have occurred...")
+ verify_cmd_output = run_external_cmd(verify_cmd)
+
+ return if verify_cmd_output.empty?
+
+ raise "The following files were modified by running GLFM scripts. Please review, verify, and commit " \
+ "the changes:\n#{verify_cmd_output}"
+ end
+ end
+end
diff --git a/scripts/lint-json.sh b/scripts/lint-json.sh
new file mode 100755
index 00000000000..685661c789a
--- /dev/null
+++ b/scripts/lint-json.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+for file in "$@"
+do
+ yarn run -s jsonlint -p "$file" | perl -pe 'chomp if eof' | diff "$file" -
+done
diff --git a/scripts/migration_schema_validator.rb b/scripts/migration_schema_validator.rb
new file mode 100644
index 00000000000..08b904ce46c
--- /dev/null
+++ b/scripts/migration_schema_validator.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+require 'open3'
+
+class MigrationSchemaValidator
+ FILENAME = 'db/structure.sql'
+
+ MIGRATION_DIRS = %w[db/migrate db/post_migrate].freeze
+
+ SCHEMA_VERSION_DIR = 'db/schema_migrations'
+
+ VERSION_DIGITS = 14
+
+ def validate!
+ if committed_migrations.empty?
+ puts "\e[32m No migrations found, skipping schema validation\e[0m"
+ return
+ end
+
+ validate_schema_on_rollback!
+ validate_schema_on_migrate!
+ validate_schema_version_files!
+ end
+
+ private
+
+ def validate_schema_on_rollback!
+ committed_migrations.reverse_each do |filename|
+ version = find_migration_version(filename)
+
+ run("scripts/db_tasks db:migrate:down VERSION=#{version}")
+ run("scripts/db_tasks db:schema:dump")
+ end
+
+ git_command = "git diff #{diff_target} -- #{FILENAME}"
+ base_message = "rollback of added migrations does not revert #{FILENAME} to previous state"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def validate_schema_on_migrate!
+ run("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"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def validate_schema_version_files!
+ git_command = "git add -A -n #{SCHEMA_VERSION_DIR}"
+ base_message = "the committed files in #{SCHEMA_VERSION_DIR} do not match those expected by the added migrations"
+
+ validate_clean_output!(git_command, base_message)
+ end
+
+ def committed_migrations
+ @committed_migrations ||= begin
+ git_command = "git diff --name-only --diff-filter=A #{diff_target} -- #{MIGRATION_DIRS.join(' ')}"
+
+ run(git_command).split("\n")
+ end
+ end
+
+ def diff_target
+ @diff_target ||= pipeline_for_merged_results? ? target_branch : merge_base
+ end
+
+ def merge_base
+ run("git merge-base #{target_branch} #{source_ref}")
+ end
+
+ def target_branch
+ ENV['CI_MERGE_REQUEST_TARGET_BRANCH_NAME'] || ENV['TARGET'] || ENV['CI_DEFAULT_BRANCH'] || 'master'
+ end
+
+ def source_ref
+ ENV['CI_COMMIT_SHA'] || 'HEAD'
+ end
+
+ def pipeline_for_merged_results?
+ ENV.key?('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA')
+ end
+
+ def find_migration_version(filename)
+ file_basename = File.basename(filename)
+ version_match = /\A(?<version>\d{#{VERSION_DIGITS}})_/o.match(file_basename)
+
+ die "#{filename} has an invalid migration version" if version_match.nil?
+
+ version_match[:version]
+ end
+
+ def validate_clean_output!(command, base_message)
+ command_output = run(command)
+
+ return if command_output.empty?
+
+ die "#{base_message}:\n#{command_output}"
+ end
+
+ def die(message, error_code: 1)
+ puts "\e[31mError: #{message}\e[0m"
+ exit error_code
+ end
+
+ def run(cmd)
+ puts "\e[32m$ #{cmd}\e[37m"
+ stdout_str, stderr_str, status = Open3.capture3(cmd)
+ puts "#{stdout_str}#{stderr_str}\e[0m"
+
+ die "command failed: #{stderr_str}" unless status.success?
+
+ stdout_str.chomp
+ end
+end
diff --git a/scripts/packages/automated_cleanup.rb b/scripts/packages/automated_cleanup.rb
new file mode 100755
index 00000000000..2b5a0011079
--- /dev/null
+++ b/scripts/packages/automated_cleanup.rb
@@ -0,0 +1,126 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require 'optparse'
+require 'gitlab'
+
+module Packages
+ class AutomatedCleanup
+ PACKAGES_PER_PAGE = 100
+
+ # $GITLAB_PROJECT_PACKAGES_CLEANUP_API_TOKEN => `Packages Cleanup` project token
+ def initialize(
+ project_path: ENV['CI_PROJECT_PATH'],
+ gitlab_token: ENV['GITLAB_PROJECT_PACKAGES_CLEANUP_API_TOKEN'],
+ api_endpoint: ENV['CI_API_V4_URL'],
+ options: {}
+ )
+ @project_path = project_path
+ @gitlab_token = gitlab_token
+ @api_endpoint = api_endpoint
+ @dry_run = options[:dry_run]
+
+ puts "Dry-run mode." if dry_run
+ end
+
+ def gitlab
+ @gitlab ||= begin
+ Gitlab.configure do |config|
+ config.endpoint = api_endpoint
+ config.private_token = gitlab_token
+ end
+
+ Gitlab
+ end
+ end
+
+ def perform_gitlab_package_cleanup!(package_name:, days_for_delete:)
+ puts "Checking for '#{package_name}' packages created at least #{days_for_delete} days ago..."
+
+ gitlab.project_packages(project_path,
+ package_type: 'generic',
+ package_name: package_name,
+ per_page: PACKAGES_PER_PAGE).auto_paginate do |package|
+ next unless package.name == package_name # the search is fuzzy, so we better check the actual package name
+
+ if old_enough(package, days_for_delete) && not_recently_downloaded(package, days_for_delete)
+ delete_package(package)
+ end
+ end
+ end
+
+ private
+
+ attr_reader :project_path, :gitlab_token, :api_endpoint, :dry_run
+
+ def delete_package(package)
+ print_package_state(package)
+ gitlab.delete_project_package(project_path, package.id) unless dry_run
+ rescue Gitlab::Error::Forbidden
+ puts "Package #{package_full_name(package)} is forbidden: skipping it"
+ end
+
+ def time_ago(days:)
+ Time.now - days * 24 * 3600
+ end
+
+ def old_enough(package, days_for_delete)
+ Time.parse(package.created_at) < time_ago(days: days_for_delete)
+ end
+
+ def not_recently_downloaded(package, days_for_delete)
+ package.last_downloaded_at.nil? ||
+ Time.parse(package.last_downloaded_at) < time_ago(days: days_for_delete)
+ end
+
+ def print_package_state(package)
+ download_text =
+ if package.last_downloaded_at
+ "last downloaded on #{package.last_downloaded_at}"
+ else
+ "never downloaded"
+ end
+
+ puts "\nPackage #{package_full_name(package)} (created on #{package.created_at}) was " \
+ "#{download_text}: deleting it.\n"
+ end
+
+ def package_full_name(package)
+ "'#{package.name}/#{package.version}'"
+ end
+ end
+end
+
+def timed(task)
+ start = Time.now
+ yield(self)
+ puts "#{task} finished in #{Time.now - start} seconds.\n"
+end
+
+if $PROGRAM_NAME == __FILE__
+ options = {
+ dry_run: false
+ }
+
+ OptionParser.new do |opts|
+ opts.on("-d", "--dry-run", "Whether to perform a dry-run or not.") do |value|
+ options[:dry_run] = true
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ automated_cleanup = Packages::AutomatedCleanup.new(options: options)
+
+ timed('"gitlab-workhorse" packages cleanup') do
+ automated_cleanup.perform_gitlab_package_cleanup!(package_name: 'gitlab-workhorse', days_for_delete: 30)
+ end
+
+ timed('"assets" packages cleanup') do
+ automated_cleanup.perform_gitlab_package_cleanup!(package_name: 'assets', days_for_delete: 7)
+ end
+end
diff --git a/scripts/perf/query_limiting_report.rb b/scripts/perf/query_limiting_report.rb
index 89abc1b301b..364cd6fc5d4 100755
--- a/scripts/perf/query_limiting_report.rb
+++ b/scripts/perf/query_limiting_report.rb
@@ -149,7 +149,7 @@ class QueryLimitingReport
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = QueryLimitingReport::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/pipeline_test_report_builder.rb b/scripts/pipeline_test_report_builder.rb
index 649b68427ea..90af0451864 100755
--- a/scripts/pipeline_test_report_builder.rb
+++ b/scripts/pipeline_test_report_builder.rb
@@ -128,7 +128,7 @@ class PipelineTestReportBuilder
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = Host::DEFAULT_OPTIONS.dup
OptionParser.new do |opts|
diff --git a/scripts/post_deployment_migrations_validator b/scripts/post_deployment_migrations_validator
new file mode 100755
index 00000000000..3df2f772197
--- /dev/null
+++ b/scripts/post_deployment_migrations_validator
@@ -0,0 +1,31 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require_relative 'migration_schema_validator'
+
+class PostDeploymentMigrationsValidator < MigrationSchemaValidator
+ def validate!
+ if committed_migrations.empty?
+ puts "\e[32m No migrations found, skipping post-deployment migrations validation\e[0m"
+ return
+ end
+
+ rollback_commited_migrations
+
+ run("SKIP_POST_DEPLOYMENT_MIGRATIONS=true scripts/db_tasks db:migrate")
+ run("scripts/db_tasks db:migrate")
+ end
+
+ private
+
+ def rollback_commited_migrations
+ committed_migrations.reverse_each do |filename|
+ version = find_migration_version(filename)
+
+ run("scripts/db_tasks db:migrate:down VERSION=#{version}")
+ end
+ end
+end
+
+PostDeploymentMigrationsValidator.new.validate!
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
index e6efbca9e86..2440df6958d 100755
--- a/scripts/review_apps/automated_cleanup.rb
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -1,252 +1,263 @@
+#!/usr/bin/env ruby
+
# frozen_string_literal: true
+require 'optparse'
require 'gitlab'
require_relative File.expand_path('../../tooling/lib/tooling/helm3_client.rb', __dir__)
require_relative File.expand_path('../../tooling/lib/tooling/kubernetes_client.rb', __dir__)
-class AutomatedCleanup
- attr_reader :project_path, :gitlab_token
-
- DEPLOYMENTS_PER_PAGE = 100
- ENVIRONMENT_PREFIX = {
- review_app: 'review/',
- docs_review_app: 'review-docs/'
- }.freeze
- IGNORED_HELM_ERRORS = [
- 'transport is closing',
- 'error upgrading connection',
- 'not found'
- ].freeze
- IGNORED_KUBERNETES_ERRORS = [
- 'NotFound'
- ].freeze
-
- def self.ee?
- # Support former project name for `dev`
- %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME'])
- end
+module ReviewApps
+ class AutomatedCleanup
+ DEPLOYMENTS_PER_PAGE = 100
+ ENVIRONMENT_PREFIX = {
+ review_app: 'review/',
+ docs_review_app: 'review-docs/'
+ }.freeze
+ IGNORED_HELM_ERRORS = [
+ 'transport is closing',
+ 'error upgrading connection',
+ 'not found'
+ ].freeze
+ IGNORED_KUBERNETES_ERRORS = [
+ 'NotFound'
+ ].freeze
+
+ # $GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN => `Automated Review App Cleanup` project token
+ def initialize(
+ project_path: ENV['CI_PROJECT_PATH'],
+ gitlab_token: ENV['GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN'],
+ api_endpoint: ENV['CI_API_V4_URL'],
+ options: {}
+ )
+ @project_path = project_path
+ @gitlab_token = gitlab_token
+ @api_endpoint = api_endpoint
+ @dry_run = options[:dry_run]
+
+ puts "Dry-run mode." if dry_run
+ end
- # $GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN => `Automated Review App Cleanup` project token
- def initialize(project_path: ENV['CI_PROJECT_PATH'], gitlab_token: ENV['GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN'])
- @project_path = project_path
- @gitlab_token = gitlab_token
- end
+ def gitlab
+ @gitlab ||= begin
+ Gitlab.configure do |config|
+ config.endpoint = api_endpoint
+ # gitlab-bot's token "GitLab review apps cleanup"
+ config.private_token = gitlab_token
+ end
- def gitlab
- @gitlab ||= begin
- Gitlab.configure do |config|
- config.endpoint = 'https://gitlab.com/api/v4'
- # gitlab-bot's token "GitLab review apps cleanup"
- config.private_token = gitlab_token
+ Gitlab
end
-
- Gitlab
end
- end
- def review_apps_namespace
- 'review-apps'
- end
+ def review_apps_namespace
+ 'review-apps'
+ end
- def helm
- @helm ||= Tooling::Helm3Client.new(namespace: review_apps_namespace)
- end
+ def helm
+ @helm ||= Tooling::Helm3Client.new(namespace: review_apps_namespace)
+ end
- def kubernetes
- @kubernetes ||= Tooling::KubernetesClient.new(namespace: review_apps_namespace)
- end
+ def kubernetes
+ @kubernetes ||= Tooling::KubernetesClient.new(namespace: review_apps_namespace)
+ end
- def perform_gitlab_environment_cleanup!(days_for_stop:, days_for_delete:)
- puts "Checking for Review Apps not updated in the last #{days_for_stop} days..."
+ def perform_gitlab_environment_cleanup!(days_for_stop:, days_for_delete:)
+ puts "Checking for Review Apps not updated in the last #{days_for_stop} days..."
- checked_environments = []
- delete_threshold = threshold_time(days: days_for_delete)
- stop_threshold = threshold_time(days: days_for_stop)
- deployments_look_back_threshold = threshold_time(days: days_for_delete * 5)
+ checked_environments = []
+ delete_threshold = threshold_time(days: days_for_delete)
+ stop_threshold = threshold_time(days: days_for_stop)
+ deployments_look_back_threshold = threshold_time(days: days_for_delete * 5)
- releases_to_delete = []
+ releases_to_delete = []
- # Delete environments via deployments
- gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
- break if Time.parse(deployment.created_at) < deployments_look_back_threshold
+ # Delete environments via deployments
+ gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
+ break if Time.parse(deployment.created_at) < deployments_look_back_threshold
- environment = deployment.environment
+ environment = deployment.environment
- next unless environment
- next unless environment.name.start_with?(ENVIRONMENT_PREFIX[:review_app])
- next if checked_environments.include?(environment.slug)
+ next unless environment
+ next unless environment.name.start_with?(ENVIRONMENT_PREFIX[:review_app])
+ next if checked_environments.include?(environment.slug)
- last_deploy = deployment.created_at
- deployed_at = Time.parse(last_deploy)
+ last_deploy = deployment.created_at
+ deployed_at = Time.parse(last_deploy)
- if deployed_at < delete_threshold
- deleted_environment = delete_environment(environment, deployment)
- if deleted_environment
- release = Tooling::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
- releases_to_delete << release
- end
- else
- if deployed_at >= stop_threshold
- print_release_state(subject: 'Review App', release_name: environment.slug, release_date: last_deploy, action: 'leaving')
+ if deployed_at < delete_threshold
+ deleted_environment = delete_environment(environment, deployment)
+ if deleted_environment
+ release = Tooling::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
+ releases_to_delete << release
+ end
else
- environment_state = fetch_environment(environment)&.state
- stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
+ if deployed_at >= stop_threshold
+ print_release_state(subject: 'Review App', release_name: environment.slug, release_date: last_deploy, action: 'leaving')
+ else
+ environment_state = fetch_environment(environment)&.state
+ stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
+ end
end
+
+ checked_environments << environment.slug
end
- checked_environments << environment.slug
- end
+ delete_stopped_environments(environment_type: :review_app, checked_environments: checked_environments, last_updated_threshold: delete_threshold) do |environment|
+ releases_to_delete << Tooling::Helm3Client::Release.new(environment.slug, 1, environment.updated_at, nil, nil, review_apps_namespace)
+ end
- delete_stopped_environments(environment_type: :review_app, checked_environments: checked_environments, last_updated_threshold: delete_threshold) do |environment|
- releases_to_delete << Tooling::Helm3Client::Release.new(environment.slug, 1, environment.updated_at, nil, nil, review_apps_namespace)
+ delete_helm_releases(releases_to_delete)
end
- delete_helm_releases(releases_to_delete)
- end
+ def perform_gitlab_docs_environment_cleanup!(days_for_stop:, days_for_delete:)
+ puts "Checking for Docs Review Apps not updated in the last #{days_for_stop} days..."
- def perform_gitlab_docs_environment_cleanup!(days_for_stop:, days_for_delete:)
- puts "Checking for Docs Review Apps not updated in the last #{days_for_stop} days..."
+ checked_environments = []
+ stop_threshold = threshold_time(days: days_for_stop)
+ delete_threshold = threshold_time(days: days_for_delete)
- checked_environments = []
- stop_threshold = threshold_time(days: days_for_stop)
- delete_threshold = threshold_time(days: days_for_delete)
+ # Delete environments via deployments
+ gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
+ environment = deployment.environment
- # Delete environments via deployments
- gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
- environment = deployment.environment
+ next unless environment
+ next unless environment.name.start_with?(ENVIRONMENT_PREFIX[:docs_review_app])
+ next if checked_environments.include?(environment.slug)
- next unless environment
- next unless environment.name.start_with?(ENVIRONMENT_PREFIX[:docs_review_app])
- next if checked_environments.include?(environment.slug)
+ last_deploy = deployment.created_at
+ deployed_at = Time.parse(last_deploy)
- last_deploy = deployment.created_at
- deployed_at = Time.parse(last_deploy)
+ if deployed_at < stop_threshold
+ environment_state = fetch_environment(environment)&.state
+ stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
+ end
- if deployed_at < stop_threshold
- environment_state = fetch_environment(environment)&.state
- stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
- end
+ delete_environment(environment, deployment) if deployed_at < delete_threshold
- delete_environment(environment, deployment) if deployed_at < delete_threshold
+ checked_environments << environment.slug
+ end
- checked_environments << environment.slug
+ delete_stopped_environments(environment_type: :docs_review_app, checked_environments: checked_environments, last_updated_threshold: delete_threshold)
end
- delete_stopped_environments(environment_type: :docs_review_app, checked_environments: checked_environments, last_updated_threshold: delete_threshold)
- end
-
- def perform_helm_releases_cleanup!(days:)
- puts "Checking for Helm releases that are failed or not updated in the last #{days} days..."
+ def perform_helm_releases_cleanup!(days:)
+ puts "Checking for Helm releases that are failed or not updated in the last #{days} days..."
- threshold = threshold_time(days: days)
+ threshold = threshold_time(days: days)
- releases_to_delete = []
+ releases_to_delete = []
- helm_releases.each do |release|
- # Prevents deleting `dns-gitlab-review-app` releases or other unrelated releases
- next unless release.name.start_with?('review-')
+ helm_releases.each do |release|
+ # Prevents deleting `dns-gitlab-review-app` releases or other unrelated releases
+ next unless release.name.start_with?('review-')
- if release.status == 'failed' || release.last_update < threshold
- releases_to_delete << release
- else
- print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
+ if release.status == 'failed' || release.last_update < threshold
+ releases_to_delete << release
+ else
+ print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
+ end
end
+
+ delete_helm_releases(releases_to_delete)
end
- delete_helm_releases(releases_to_delete)
- end
+ def perform_stale_namespace_cleanup!(days:)
+ kubernetes_client = Tooling::KubernetesClient.new(namespace: nil)
- def perform_stale_namespace_cleanup!(days:)
- kubernetes_client = Tooling::KubernetesClient.new(namespace: nil)
+ kubernetes_client.cleanup_review_app_namespaces(created_before: threshold_time(days: days), wait: false) unless dry_run
+ end
- kubernetes_client.cleanup_review_app_namespaces(created_before: threshold_time(days: days), wait: false)
- end
+ def perform_stale_pvc_cleanup!(days:)
+ kubernetes.cleanup_by_created_at(resource_type: 'pvc', created_before: threshold_time(days: days), wait: false) unless dry_run
+ end
- def perform_stale_pvc_cleanup!(days:)
- kubernetes.cleanup_by_created_at(resource_type: 'pvc', created_before: threshold_time(days: days), wait: false)
- end
+ private
- private
+ attr_reader :project_path, :gitlab_token, :api_endpoint, :dry_run
- def fetch_environment(environment)
- gitlab.environment(project_path, environment.id)
- rescue Errno::ETIMEDOUT => ex
- puts "Failed to fetch '#{environment.name}' / '#{environment.slug}' (##{environment.id}):\n#{ex.message}"
- nil
- end
+ def fetch_environment(environment)
+ gitlab.environment(project_path, environment.id)
+ rescue Errno::ETIMEDOUT => ex
+ puts "Failed to fetch '#{environment.name}' / '#{environment.slug}' (##{environment.id}):\n#{ex.message}"
+ nil
+ end
- def delete_environment(environment, deployment = nil)
- release_date = deployment ? deployment.created_at : environment.updated_at
- print_release_state(subject: 'Review app', release_name: environment.slug, release_date: release_date, action: 'deleting')
- gitlab.delete_environment(project_path, environment.id)
+ def delete_environment(environment, deployment = nil)
+ release_date = deployment ? deployment.created_at : environment.updated_at
+ print_release_state(subject: 'Review app', release_name: environment.slug, release_date: release_date, action: 'deleting')
+ gitlab.delete_environment(project_path, environment.id) unless dry_run
- rescue Gitlab::Error::Forbidden
- puts "Review app '#{environment.name}' / '#{environment.slug}' (##{environment.id}) is forbidden: skipping it"
- end
+ rescue Gitlab::Error::Forbidden
+ puts "Review app '#{environment.name}' / '#{environment.slug}' (##{environment.id}) is forbidden: skipping it"
+ end
- def stop_environment(environment, deployment)
- print_release_state(subject: 'Review app', release_name: environment.slug, release_date: deployment.created_at, action: 'stopping')
- gitlab.stop_environment(project_path, environment.id)
+ def stop_environment(environment, deployment)
+ print_release_state(subject: 'Review app', release_name: environment.slug, release_date: deployment.created_at, action: 'stopping')
+ gitlab.stop_environment(project_path, environment.id) unless dry_run
- rescue Gitlab::Error::Forbidden
- puts "Review app '#{environment.name}' / '#{environment.slug}' (##{environment.id}) is forbidden: skipping it"
- end
+ rescue Gitlab::Error::Forbidden
+ puts "Review app '#{environment.name}' / '#{environment.slug}' (##{environment.id}) is forbidden: skipping it"
+ end
- def delete_stopped_environments(environment_type:, checked_environments:, last_updated_threshold:)
- gitlab.environments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc', states: 'stopped', search: ENVIRONMENT_PREFIX[environment_type]).auto_paginate do |environment|
- next if skip_environment?(environment: environment, checked_environments: checked_environments, last_updated_threshold: last_updated_threshold, environment_type: environment_type)
+ def delete_stopped_environments(environment_type:, checked_environments:, last_updated_threshold:)
+ gitlab.environments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc', states: 'stopped', search: ENVIRONMENT_PREFIX[environment_type]).auto_paginate do |environment|
+ next if skip_environment?(environment: environment, checked_environments: checked_environments, last_updated_threshold: last_updated_threshold, environment_type: environment_type)
- yield environment if delete_environment(environment)
+ yield environment if delete_environment(environment)
- checked_environments << environment.slug
+ checked_environments << environment.slug
+ end
end
- end
- def skip_environment?(environment:, checked_environments:, last_updated_threshold:, environment_type:)
- return true unless environment.name.start_with?(ENVIRONMENT_PREFIX[environment_type])
- return true if checked_environments.include?(environment.slug)
- return true if Time.parse(environment.updated_at) > last_updated_threshold
+ def skip_environment?(environment:, checked_environments:, last_updated_threshold:, environment_type:)
+ return true unless environment.name.start_with?(ENVIRONMENT_PREFIX[environment_type])
+ return true if checked_environments.include?(environment.slug)
+ return true if Time.parse(environment.updated_at) > last_updated_threshold
- false
- end
+ false
+ end
- def helm_releases
- args = ['--all', '--date']
+ def helm_releases
+ args = ['--all', '--date']
- helm.releases(args: args)
- end
+ helm.releases(args: args)
+ end
- def delete_helm_releases(releases)
- return if releases.empty?
+ def delete_helm_releases(releases)
+ return if releases.empty?
- releases.each do |release|
- print_release_state(subject: 'Release', release_name: release.name, release_status: release.status, release_date: release.last_update, action: 'cleaning')
- end
+ releases.each do |release|
+ print_release_state(subject: 'Release', release_name: release.name, release_status: release.status, release_date: release.last_update, action: 'cleaning')
+ end
- releases_names = releases.map(&:name)
- helm.delete(release_name: releases_names)
- kubernetes.cleanup_by_release(release_name: releases_names, wait: false)
+ releases_names = releases.map(&:name)
+ unless dry_run
+ helm.delete(release_name: releases_names)
+ kubernetes.cleanup_by_release(release_name: releases_names, wait: false)
+ end
- rescue Tooling::Helm3Client::CommandFailedError => ex
- raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
+ rescue Tooling::Helm3Client::CommandFailedError => ex
+ raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
- puts "Ignoring the following Helm error:\n#{ex}\n"
- rescue Tooling::KubernetesClient::CommandFailedError => ex
- raise ex unless ignore_exception?(ex.message, IGNORED_KUBERNETES_ERRORS)
+ puts "Ignoring the following Helm error:\n#{ex}\n"
+ rescue Tooling::KubernetesClient::CommandFailedError => ex
+ raise ex unless ignore_exception?(ex.message, IGNORED_KUBERNETES_ERRORS)
- puts "Ignoring the following Kubernetes error:\n#{ex}\n"
- end
+ puts "Ignoring the following Kubernetes error:\n#{ex}\n"
+ end
- def threshold_time(days:)
- Time.now - days * 24 * 3600
- end
+ def threshold_time(days:)
+ Time.now - days * 24 * 3600
+ end
- def ignore_exception?(exception_message, exceptions_ignored)
- exception_message.match?(/(#{exceptions_ignored})/)
- end
+ def ignore_exception?(exception_message, exceptions_ignored)
+ exception_message.match?(/(#{exceptions_ignored})/)
+ end
- def print_release_state(subject:, release_name:, release_date:, action:, release_status: nil)
- puts "\n#{subject} '#{release_name}' #{"(#{release_status}) " if release_status}was last deployed on #{release_date}: #{action} it.\n"
+ def print_release_state(subject:, release_name:, release_date:, action:, release_status: nil)
+ puts "\n#{subject} '#{release_name}' #{"(#{release_status}) " if release_status}was last deployed on #{release_date}: #{action} it.\n"
+ end
end
end
@@ -256,28 +267,43 @@ def timed(task)
puts "#{task} finished in #{Time.now - start} seconds.\n"
end
-automated_cleanup = AutomatedCleanup.new
+if $PROGRAM_NAME == __FILE__
+ options = {
+ dry_run: false
+ }
-timed('Review Apps cleanup') do
- automated_cleanup.perform_gitlab_environment_cleanup!(days_for_stop: 5, days_for_delete: 6)
-end
+ OptionParser.new do |opts|
+ opts.on("-d", "--dry-run", "Whether to perform a dry-run or not.") do |value|
+ options[:dry_run] = true
+ end
-timed('Docs Review Apps cleanup') do
- automated_cleanup.perform_gitlab_docs_environment_cleanup!(days_for_stop: 20, days_for_delete: 30)
-end
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
-puts
+ automated_cleanup = ReviewApps::AutomatedCleanup.new(options: options)
-timed('Helm releases cleanup') do
- automated_cleanup.perform_helm_releases_cleanup!(days: 7)
-end
+ timed('Review Apps cleanup') do
+ automated_cleanup.perform_gitlab_environment_cleanup!(days_for_stop: 5, days_for_delete: 6)
+ end
-timed('Stale Namespace cleanup') do
- automated_cleanup.perform_stale_namespace_cleanup!(days: 14)
-end
+ timed('Docs Review Apps cleanup') do
+ automated_cleanup.perform_gitlab_docs_environment_cleanup!(days_for_stop: 20, days_for_delete: 30)
+ end
-timed('Stale PVC cleanup') do
- automated_cleanup.perform_stale_pvc_cleanup!(days: 30)
-end
+ puts
+
+ timed('Helm releases cleanup') do
+ automated_cleanup.perform_helm_releases_cleanup!(days: 7)
+ end
-exit(0)
+ timed('Stale Namespace cleanup') do
+ automated_cleanup.perform_stale_namespace_cleanup!(days: 14)
+ end
+
+ timed('Stale PVC cleanup') do
+ automated_cleanup.perform_stale_pvc_cleanup!(days: 30)
+ end
+end
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index e979d0f75cf..0fc245a409f 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -154,12 +154,8 @@ function disable_sign_ups() {
true
fi
- # Create the root token
- local set_token_rb="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end"
- retry "run_task \"${set_token_rb}\""
-
- # Disable sign-ups
- local disable_signup_rb="Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false)"
+ # Create the root token + Disable sign-ups
+ local disable_signup_rb="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end; Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false)"
if (retry "run_task \"${disable_signup_rb}\""); then
echoinfo "Sign-ups have been disabled successfully."
else
@@ -239,16 +235,21 @@ function create_application_secret() {
}
function download_chart() {
- echoinfo "Downloading the GitLab chart..." true
+ # If the requirements.lock is present, it means we got everything we need from the cache.
+ if [[ -f "gitlab-${GITLAB_HELM_CHART_REF}/requirements.lock" ]]; then
+ echosuccess "Downloading/Building chart dependencies skipped. Using the chart ${gitlab-${GITLAB_HELM_CHART_REF}} local folder'..."
+ else
+ echoinfo "Downloading the GitLab chart..." true
- curl --location -o gitlab.tar.bz2 "https://gitlab.com/gitlab-org/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2"
- tar -xjf gitlab.tar.bz2
+ curl --location -o gitlab.tar.bz2 "https://gitlab.com/gitlab-org/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2"
+ tar -xjf gitlab.tar.bz2
- echoinfo "Adding the gitlab repo to Helm..."
- helm repo add gitlab https://charts.gitlab.io
+ echoinfo "Adding the gitlab repo to Helm..."
+ helm repo add gitlab https://charts.gitlab.io
- echoinfo "Building the gitlab chart's dependencies..."
- helm dependency build "gitlab-${GITLAB_HELM_CHART_REF}"
+ echoinfo "Building the gitlab chart's dependencies..."
+ helm dependency build "gitlab-${GITLAB_HELM_CHART_REF}"
+ fi
}
function base_config_changed() {
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 5d7bd844c2c..73030d2ad6c 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -247,7 +247,12 @@ function rspec_paralellized_job() {
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
- export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
+ export KNAPSACK_TEST_FILE_PATTERN="spec/{,**/}*_spec.rb"
+
+ if [[ "${test_level}" != "foss-impact" ]]; then
+ export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
+ fi
+
export FLAKY_RSPEC_REPORT_PATH="${rspec_flaky_folder_path}all_${report_name}_report.json"
export NEW_FLAKY_RSPEC_REPORT_PATH="${rspec_flaky_folder_path}new_${report_name}_report.json"
export SKIPPED_FLAKY_TESTS_REPORT_PATH="${rspec_flaky_folder_path}skipped_flaky_tests_${report_name}_report.txt"
@@ -268,8 +273,8 @@ function rspec_paralellized_job() {
debug_rspec_variables
- if [[ -n $RSPEC_TESTS_MAPPING_ENABLED ]]; then
- tooling/bin/parallel_rspec --rspec_args "$(rspec_args "${rspec_opts}")" --filter "${RSPEC_MATCHING_TESTS_PATH}" || rspec_run_status=$?
+ if [[ -n "${RSPEC_TESTS_MAPPING_ENABLED}" ]]; then
+ tooling/bin/parallel_rspec --rspec_args "$(rspec_args "${rspec_opts}")" --filter "${RSPEC_TESTS_FILTER_FILE}" || rspec_run_status=$?
else
tooling/bin/parallel_rspec --rspec_args "$(rspec_args "${rspec_opts}")" || rspec_run_status=$?
fi
@@ -292,6 +297,12 @@ function rspec_paralellized_job() {
function retry_failed_rspec_examples() {
local rspec_run_status=0
+ # Sometimes the file isn't created or is empty. In that case we exit(1) ourselves, otherwise, RSpec would
+ # not run any examples an exit successfully, actually hiding failed tests!
+ if [[ ! -f "${RSPEC_LAST_RUN_RESULTS_FILE}" ]] || [[ ! -s "${RSPEC_LAST_RUN_RESULTS_FILE}" ]]; then
+ exit 1
+ fi
+
# Keep track of the tests that are retried, later consolidated in a single file by the `rspec:flaky-tests-report` job
local failed_examples=$(grep " failed" ${RSPEC_LAST_RUN_RESULTS_FILE})
echo "${CI_JOB_URL}" > "${RETRIED_TESTS_REPORT_PATH}"
@@ -357,41 +368,12 @@ function rspec_fail_fast() {
fi
}
-function rspec_matched_foss_tests() {
- local test_file_count_threshold=20
- local matching_tests_file=${1}
- local foss_matching_tests_file="${matching_tests_file}-foss"
+function filter_rspec_matched_foss_tests() {
+ local matching_tests_file="${1}"
+ local foss_matching_tests_file="${2}"
# Keep only files that exists (i.e. exclude EE speficic files)
- cat ${matching_tests_file} | ruby -e 'puts $stdin.read.split(" ").select { |f| File.exist?(f) && f.include?("spec/") }.join(" ")' > "${foss_matching_tests_file}"
-
- echo "Matching tests file:"
- cat ${matching_tests_file}
- echo -e "\n\n"
-
- echo "FOSS matching tests file:"
- cat ${foss_matching_tests_file}
- echo -e "\n\n"
-
- local rspec_opts=${2}
- local test_files="$(cat ${foss_matching_tests_file})"
- local test_file_count=$(wc -w "${foss_matching_tests_file}" | awk {'print $1'})
-
- if [[ "${test_file_count}" -gt "${test_file_count_threshold}" ]]; then
- echo "This job is intentionally failed because there are more than ${test_file_count_threshold} FOSS test files matched,"
- echo "which would take too long to run in this job."
- echo "To reduce the likelihood of breaking FOSS pipelines,"
- echo "please add ~\"pipeline:run-as-if-foss\" label to the merge request and trigger a new pipeline."
- echo "This would run all as-if-foss jobs in this merge request"
- echo "and remove this failing job from the pipeline."
- exit 1
- fi
-
- if [[ -n $test_files ]]; then
- rspec_simple_job "${rspec_opts} ${test_files}"
- else
- echo "No impacted FOSS rspec tests to run"
- fi
+ cat ${matching_tests_file} | ruby -e 'puts $stdin.read.split(" ").select { |f| f.start_with?("spec/") && File.exist?(f) }.join(" ")' > "${foss_matching_tests_file}"
}
function generate_frontend_fixtures_mapping() {
diff --git a/scripts/rubocop-max-files-in-cache-check b/scripts/rubocop-max-files-in-cache-check
index 5b422d0a0f4..34caa0e197c 100755
--- a/scripts/rubocop-max-files-in-cache-check
+++ b/scripts/rubocop-max-files-in-cache-check
@@ -1,7 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
-require 'yaml'
+require_relative '../config/bundler_setup'
+require 'rubocop'
MINIMUM_MAX_FILES_IN_CACHE_MARGIN = 1.05
RECOMMENDED_MAX_FILES_IN_CACHE_MARGIN = 1.25
@@ -14,7 +15,7 @@ rubocop_target_files_count = `#{RUBOCOP_LIST_TARGET_FILES_COMMAND}`.strip.to_i
raise Error, "#{RUBOCOP_LIST_TARGET_FILES_COMMAND} failed with status #{$?}!" if rubocop_target_files_count == 0
rubocop_target_files_count = rubocop_target_files_count.to_i
-rubocop_current_max_files_in_cache = YAML.load_file(File.expand_path('../.rubocop.yml', __dir__)).dig('AllCops', 'MaxFilesInCache').to_i
+rubocop_current_max_files_in_cache = RuboCop::ConfigLoader.load_yaml_configuration(File.expand_path('../.rubocop.yml', __dir__)).dig('AllCops', 'MaxFilesInCache').to_i
minimum_max_files_in_cache = (rubocop_target_files_count * MINIMUM_MAX_FILES_IN_CACHE_MARGIN).round(-3)
# We want AllCops.MaxFilesInCache to be at least 5% above the actual files count at any time to give us enough time to increase it accordingly
diff --git a/scripts/rubocop-parse b/scripts/rubocop-parse
index 4c82be5934b..0a234df81cd 100755
--- a/scripts/rubocop-parse
+++ b/scripts/rubocop-parse
@@ -30,23 +30,57 @@ require_relative '../config/bundler_setup'
require 'rubocop'
require 'optparse'
-def print_ast(file, source, version)
- version ||= RuboCop::ConfigStore.new.for_file(file).target_ruby_version
- puts RuboCop::AST::ProcessedSource.new(source, version).ast.to_s
+module Helper
+ extend self
+
+ class << self
+ attr_writer :ruby_version
+ end
+
+ def ast(source, file: '', version: nil)
+ version ||= ruby_version
+ puts RuboCop::AST::ProcessedSource.new(source, version).ast.to_s
+ end
+
+ def ruby_version
+ @ruby_version ||= rubocop_target_ruby_version
+ end
+
+ def rubocop_target_ruby_version
+ @rubocop_target_ruby_version ||= RuboCop::ConfigStore.new.for_file('.').target_ruby_version
+ end
end
-options = Struct.new(:eval, :ruby_version, :print_help, keyword_init: true).new
+def start_irb
+ require 'irb'
+
+ include Helper # rubocop:disable Style/MixinUsage
+
+ puts "Ruby version: #{ruby_version}"
+ puts
+ puts "Use `ast(source_string, version: nil)` method to parse code and output AST. For example:"
+ puts " ast('puts :hello')"
+ puts
+
+ IRB.start
+end
+
+options = Struct.new(:eval, :interactive, :print_help, keyword_init: true).new
parser = OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} [-e code] [FILE...]"
+ opts.banner = "Usage: #{$PROGRAM_NAME} [-e code] [FILE...]"
opts.on('-e FRAGMENT', '--eval FRAGMENT', 'Process a fragment of Ruby code') do |code|
options.eval = code
end
+ opts.on('-i', '--interactive', '') do
+ options.interactive = true
+ end
+
opts.on('-v RUBY_VERSION', '--ruby-version RUBY_VERSION',
'Parse as Ruby would. Defaults to RuboCop TargetRubyVersion setting.') do |ruby_version|
- options.ruby_version = Float(ruby_version)
+ Helper.ruby_version = Float(ruby_version)
end
opts.on('-h', '--help') do
@@ -54,20 +88,31 @@ parser = OptionParser.new do |opts|
end
end
-args = parser.parse!
+files = parser.parse!
if options.print_help
puts parser
- exit
-end
-
-print_ast('', options.eval, options.ruby_version) if options.eval
+elsif options.interactive
+ if options.eval || files.any?
+ puts "Cannot combine `--interactive` with `--eval` or passing files. Aborting..."
+ puts
-args.each do |arg|
- if File.file?(arg)
- source = File.read(arg)
- print_ast(arg, source, options.ruby_version)
+ puts parser
+ exit 1
else
- warn "Skipping non-file #{arg.inspect}"
+ start_irb
end
+elsif options.eval
+ Helper.ast(options.eval)
+elsif files.any?
+ files.each do |file|
+ if File.file?(file)
+ source = File.read(file)
+ Helper.ast(source, file: file)
+ else
+ warn "Skipping non-file #{file.inspect}"
+ end
+ end
+else
+ puts parser
end
diff --git a/scripts/setup/find-jh-branch.rb b/scripts/setup/find-jh-branch.rb
index a7c1cafd74c..5b36aa7a1f4 100755
--- a/scripts/setup/find-jh-branch.rb
+++ b/scripts/setup/find-jh-branch.rb
@@ -97,6 +97,6 @@ class FindJhBranch
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
puts FindJhBranch.new.run
end
diff --git a/scripts/slack b/scripts/slack
index 293f8070504..3ce2b4553ee 100755
--- a/scripts/slack
+++ b/scripts/slack
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# This is based on https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/bin/slack
#
# Sends Slack notification MSG to CI_SLACK_WEBHOOK_URL (which needs to be set).
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 53f84c19ac6..c6cf09e056b 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -191,7 +191,7 @@ class StaticAnalysis
end
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
options = {}
if ARGV.include?('--dry-run')
diff --git a/scripts/trigger-build.rb b/scripts/trigger-build.rb
index b368bbdb1f1..897ca9f473e 100755
--- a/scripts/trigger-build.rb
+++ b/scripts/trigger-build.rb
@@ -427,7 +427,7 @@ module Trigger
Job = Class.new(Pipeline)
end
-if $0 == __FILE__
+if $PROGRAM_NAME == __FILE__
case ARGV[0]
when 'cng'
Trigger::CNG.new.invoke!.wait!
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 10b7f856ee6..ea2b390f249 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -62,6 +62,22 @@ function bundle_install_script() {
echo -e "section_end:`date +%s`:bundle-install\r\e[0K"
}
+function yarn_install_script() {
+ echo -e "section_start:`date +%s`:yarn-install[collapsed=true]\r\e[0KInstalling Yarn packages"
+
+ retry yarn install --frozen-lockfile
+
+ echo -e "section_end:`date +%s`:yarn-install\r\e[0K"
+}
+
+function assets_compile_script() {
+ echo -e "section_start:`date +%s`:assets-compile[collapsed=true]\r\e[0KCompiling frontend assets"
+
+ bin/rake gitlab:assets:compile
+
+ echo -e "section_end:`date +%s`:assets-compile\r\e[0K"
+}
+
function setup_db_user_only() {
source scripts/create_postgres_user.sh
}
@@ -77,12 +93,12 @@ function setup_db() {
}
function install_gitlab_gem() {
- run_timed_command "gem install httparty --no-document --version 0.18.1"
- run_timed_command "gem install gitlab --no-document --version 4.17.0"
+ run_timed_command "gem install httparty --no-document --version 0.20.0"
+ run_timed_command "gem install gitlab --no-document --version 4.19.0"
}
function install_tff_gem() {
- run_timed_command "gem install test_file_finder --no-document --version 0.1.1"
+ run_timed_command "gem install test_file_finder --no-document --version 0.1.4"
}
function install_junit_merge_gem() {
diff --git a/scripts/validate_migration_schema b/scripts/validate_migration_schema
index 5c389851844..c6f93b855ec 100755
--- a/scripts/validate_migration_schema
+++ b/scripts/validate_migration_schema
@@ -2,120 +2,6 @@
# frozen_string_literal: true
-require 'open3'
-
-class MigrationSchemaValidator
- FILENAME = 'db/structure.sql'
-
- MIGRATION_DIRS = %w[db/migrate db/post_migrate].freeze
-
- SCHEMA_VERSION_DIR = 'db/schema_migrations'
-
- VERSION_DIGITS = 14
-
- def validate!
- if committed_migrations.empty?
- puts "\e[32m No migrations found, skipping schema validation\e[0m"
- return
- end
-
- validate_schema_on_rollback!
- validate_schema_on_migrate!
- validate_schema_version_files!
- end
-
- private
-
- def validate_schema_on_rollback!
- committed_migrations.reverse_each do |filename|
- version = find_migration_version(filename)
-
- run("scripts/db_tasks db:migrate:down VERSION=#{version}")
- run("scripts/db_tasks db:schema:dump")
- end
-
- git_command = "git diff #{diff_target} -- #{FILENAME}"
- base_message = "rollback of added migrations does not revert #{FILENAME} to previous state"
-
- validate_clean_output!(git_command, base_message)
- end
-
- def validate_schema_on_migrate!
- run("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"
-
- validate_clean_output!(git_command, base_message)
- end
-
- def validate_schema_version_files!
- git_command = "git add -A -n #{SCHEMA_VERSION_DIR}"
- base_message = "the committed files in #{SCHEMA_VERSION_DIR} do not match those expected by the added migrations"
-
- validate_clean_output!(git_command, base_message)
- end
-
- def committed_migrations
- @committed_migrations ||= begin
- git_command = "git diff --name-only --diff-filter=A #{diff_target} -- #{MIGRATION_DIRS.join(' ')}"
-
- run(git_command).split("\n")
- end
- end
-
- def diff_target
- @diff_target ||= pipeline_for_merged_results? ? target_branch : merge_base
- end
-
- def merge_base
- run("git merge-base #{target_branch} #{source_ref}")
- end
-
- def target_branch
- ENV['CI_MERGE_REQUEST_TARGET_BRANCH_NAME'] || ENV['TARGET'] || ENV['CI_DEFAULT_BRANCH'] || 'master'
- end
-
- def source_ref
- ENV['CI_COMMIT_SHA'] || 'HEAD'
- end
-
- def pipeline_for_merged_results?
- ENV.key?('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA')
- end
-
- def find_migration_version(filename)
- file_basename = File.basename(filename)
- version_match = /\A(?<version>\d{#{VERSION_DIGITS}})_/o.match(file_basename)
-
- die "#{filename} has an invalid migration version" if version_match.nil?
-
- version_match[:version]
- end
-
- def validate_clean_output!(command, base_message)
- command_output = run(command)
-
- return if command_output.empty?
-
- die "#{base_message}:\n#{command_output}"
- end
-
- def die(message, error_code: 1)
- puts "\e[31mError: #{message}\e[0m"
- exit error_code
- end
-
- def run(cmd)
- puts "\e[32m$ #{cmd}\e[37m"
- stdout_str, stderr_str, status = Open3.capture3(cmd)
- puts "#{stdout_str}#{stderr_str}\e[0m"
-
- die "command failed: #{stderr_str}" unless status.success?
-
- stdout_str.chomp
- end
-end
+require_relative 'migration_schema_validator'
MigrationSchemaValidator.new.validate!
diff --git a/spec/bin/diagnostic_reports_uploader_spec.rb b/spec/bin/diagnostic_reports_uploader_spec.rb
new file mode 100644
index 00000000000..9a929de6d0e
--- /dev/null
+++ b/spec/bin/diagnostic_reports_uploader_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'tempfile'
+
+RSpec.describe 'bin/diagnostic-reports-uploader' do
+ let(:reports_dir) { Dir.mktmpdir }
+ let(:gcs_key) { Tempfile.new }
+ let(:gcs_project) { 'test_gcs_project' }
+ let(:gcs_bucket) { 'test_gcs_bucket' }
+
+ after do
+ FileUtils.remove_entry(reports_dir)
+ FileUtils.remove_entry(gcs_key)
+ end
+
+ subject(:load_bin) { load File.expand_path('../../bin/diagnostic-reports-uploader', __dir__) }
+
+ context 'when necessary ENV vars are set' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', reports_dir)
+ stub_env('GITLAB_GCP_KEY_PATH', gcs_key.path)
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PROJECT', gcs_project)
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_BUCKET', gcs_bucket)
+ end
+
+ let(:reports_uploader) { instance_double(Gitlab::Memory::ReportsUploader) }
+ let(:upload_and_cleanup_reports) { instance_double(Gitlab::Memory::UploadAndCleanupReports) }
+ let(:logger) { instance_double(Gitlab::Memory::DiagnosticReportsLogger) }
+
+ it 'runs successfully' do
+ expect(Gitlab::Memory::DiagnosticReportsLogger).to receive(:new).and_return(logger)
+
+ expect(Gitlab::Memory::ReportsUploader)
+ .to receive(:new).with(gcs_key: gcs_key.path, gcs_project: gcs_project, gcs_bucket: gcs_bucket, logger: logger)
+ .and_return(reports_uploader)
+
+ expect(Gitlab::Memory::UploadAndCleanupReports)
+ .to receive(:new).with(uploader: reports_uploader, reports_path: reports_dir, logger: logger)
+ .and_return(upload_and_cleanup_reports)
+
+ expect(upload_and_cleanup_reports).to receive(:call)
+
+ load_bin
+ end
+ end
+
+ context 'when GITLAB_DIAGNOSTIC_REPORTS_PATH is missing' do
+ it 'raises RuntimeError' do
+ expect { load_bin }.to raise_error(RuntimeError, 'GITLAB_DIAGNOSTIC_REPORTS_PATH dir is missing')
+ end
+ end
+
+ context 'when GITLAB_GCP_KEY_PATH is missing' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', reports_dir)
+ end
+
+ it 'raises RuntimeError' do
+ expect { load_bin }.to raise_error(RuntimeError, /GCS keyfile not found/)
+ end
+ end
+
+ context 'when GITLAB_DIAGNOSTIC_REPORTS_PROJECT is missing' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', reports_dir)
+ stub_env('GITLAB_GCP_KEY_PATH', gcs_key.path)
+ end
+
+ it 'raises RuntimeError' do
+ expect { load_bin }.to raise_error(RuntimeError, 'GITLAB_DIAGNOSTIC_REPORTS_PROJECT is missing')
+ end
+ end
+
+ context 'when GITLAB_DIAGNOSTIC_REPORTS_BUCKET is missing' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', reports_dir)
+ stub_env('GITLAB_GCP_KEY_PATH', gcs_key.path)
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PROJECT', gcs_project)
+ end
+
+ it 'raises RuntimeError' do
+ expect { load_bin }.to raise_error(RuntimeError, 'GITLAB_DIAGNOSTIC_REPORTS_BUCKET is missing')
+ end
+ end
+end
diff --git a/spec/commands/diagnostic_reports/uploader_smoke_spec.rb b/spec/commands/diagnostic_reports/uploader_smoke_spec.rb
new file mode 100644
index 00000000000..9fbceb68844
--- /dev/null
+++ b/spec/commands/diagnostic_reports/uploader_smoke_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'tempfile'
+
+# We need to capture pid from Process.spawn and then clean up by killing the process, which requires instance variables.
+# rubocop: disable RSpec/InstanceVariable
+RSpec.describe 'bin/diagnostic-reports-uploader' do
+ # This is a smoke test for 'bin/diagnostic-reports-uploader'.
+ # We intend to run this binary with `ruby bin/diagnostic-reports-uploader`, without preloading the entire Rails app.
+ # Also, we use inline gemfile, to avoid pulling full Gemfile from the main app into memory.
+ # The goal of that test is to confirm that the binary starts that way.
+ # The implementation logic is covered in 'spec/bin/diagnostic_reports_uploader_spec.rb'
+ include FastRailsRoot
+
+ let(:gcs_bucket) { 'test_bucket' }
+ let(:gcs_project) { 'test_project' }
+ let(:gcs_key) { Tempfile.new }
+ let(:reports_dir) { Dir.mktmpdir }
+ let(:report) { Tempfile.new('report.json', reports_dir) }
+
+ let(:env) do
+ {
+ 'GITLAB_DIAGNOSTIC_REPORTS_BUCKET' => gcs_bucket,
+ 'GITLAB_DIAGNOSTIC_REPORTS_PROJECT' => gcs_project,
+ 'GITLAB_GCP_KEY_PATH' => gcs_key.path,
+ 'GITLAB_DIAGNOSTIC_REPORTS_PATH' => reports_dir,
+ 'GITLAB_DIAGNOSTIC_REPORTS_UPLOADER_SLEEP_S' => '1'
+ }
+ end
+
+ before do
+ gcs_key.write(
+ {
+ type: "service_account",
+ client_email: 'test@gitlab.com',
+ private_key_id: "test_id",
+ private_key: File.read(rails_root_join('spec/fixtures/ssl_key.pem'))
+ }.to_json
+ )
+ gcs_key.rewind
+
+ FileUtils.touch(report.path)
+ end
+
+ after do
+ if @pid
+ Timeout.timeout(10) do
+ Process.kill('TERM', @pid)
+ Process.waitpid(@pid)
+ end
+ end
+ rescue Errno::ESRCH, Errno::ECHILD => _
+ # 'No such process' or 'No child processes' means the process died before
+ ensure
+ gcs_key.unlink
+ FileUtils.rm_rf(reports_dir, secure: true)
+ end
+
+ it 'starts successfully' do
+ expect(File.exist?(report.path)).to be true
+
+ bin_path = rails_root_join("bin/diagnostic-reports-uploader")
+
+ cmd = ['bundle', 'exec', 'ruby', bin_path]
+ @pid = Process.spawn(env, *cmd)
+
+ expect(Gitlab::ProcessManagement.process_alive?(@pid)).to be true
+
+ expect do
+ Timeout.timeout(10) do
+ # Uploader will remove the file, no matter the upload result. We are waiting for exactly that.
+ # The report being removed means the uploader loop works. We are not attempting real upload.
+ attempted_upload_and_cleanup = false
+ until attempted_upload_and_cleanup
+ sleep 1
+ attempted_upload_and_cleanup = !File.exist?(report.path)
+ end
+ end
+ end.not_to raise_error
+ end
+end
+# rubocop: enable RSpec/InstanceVariable
diff --git a/spec/components/pajamas/alert_component_spec.rb b/spec/components/pajamas/alert_component_spec.rb
index c60724c7b78..4a90a9e0b88 100644
--- a/spec/components/pajamas/alert_component_spec.rb
+++ b/spec/components/pajamas/alert_component_spec.rb
@@ -45,11 +45,37 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do
end
end
+ describe 'title' do
+ before do
+ render_inline described_class.new(title: title)
+ end
+
+ context 'with non-empty string' do
+ let(:title) { '_title_' }
+
+ it 'sets the title' do
+ expect(page).to have_selector('.gl-alert-title')
+ expect(page).to have_content(title)
+ expect(page).not_to have_selector('.gl-alert-icon-no-title')
+ end
+ end
+
+ context 'with nil, empty or blank string' do
+ where(:title) { [nil, '', ' '] }
+
+ with_them do
+ it 'does not set a title' do
+ expect(page).not_to have_selector('.gl-alert-title')
+ expect(page).to have_selector('.gl-alert-icon-no-title')
+ end
+ end
+ end
+ end
+
context 'with custom options' do
context 'with simple options' do
before do
render_inline described_class.new(
- title: '_title_',
alert_options: {
class: '_alert_class_',
data: {
@@ -60,12 +86,6 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do
)
end
- it 'sets the title' do
- expect(page).to have_selector('.gl-alert-title')
- expect(page).to have_content('_title_')
- expect(page).not_to have_selector('.gl-alert-icon-no-title')
- end
-
it 'sets the alert_class' do
expect(page).to have_selector('._alert_class_')
end
@@ -129,7 +149,7 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do
end
context 'with setting variant type' do
- where(:variant) { [:warning, :success, :danger, :tip] }
+ where(:variant) { [:warning, "success", :danger, "tip"] }
before do
render_inline described_class.new(variant: variant)
@@ -138,7 +158,18 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do
with_them do
it 'renders the variant' do
expect(page).to have_selector(".gl-alert-#{variant}")
- expect(page).to have_selector("[data-testid='#{described_class::ICONS[variant]}-icon']")
+ expect(page).to have_selector("[data-testid='#{described_class::VARIANT_ICONS[variant.to_sym]}-icon']")
+ end
+ end
+
+ context "with unknown or nil variant" do
+ where(:variant) { [:foo, nil] }
+
+ with_them do
+ it "adds the default variant class" do
+ expect(page).to have_selector(".gl-alert-info")
+ expect(page).to have_selector("[data-testid='information-o-icon']")
+ end
end
end
end
diff --git a/spec/components/pajamas/progress_component_spec.rb b/spec/components/pajamas/progress_component_spec.rb
new file mode 100644
index 00000000000..5172f459a84
--- /dev/null
+++ b/spec/components/pajamas/progress_component_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Pajamas::ProgressComponent, type: :component do
+ before do
+ render_inline(described_class.new(value: value, variant: variant))
+ end
+
+ let(:value) { 33 }
+ let(:variant) { nil }
+
+ describe "value" do
+ it "sets the width of the progressbar" do
+ expect(page).to have_css ".progress-bar[style='width: #{value}%;']"
+ end
+ end
+
+ describe "variant" do
+ where(:variant) { [:primary, :success] }
+
+ with_them do
+ it "adds variant class" do
+ expect(page).to have_css ".progress-bar.bg-#{variant}"
+ end
+ end
+
+ context "with unknown variant" do
+ let(:variant) { :nope }
+
+ it "adds the default variant class" do
+ expect(page).to have_css ".progress-bar.bg-primary"
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/alert_component_preview.rb b/spec/components/previews/pajamas/alert_component_preview.rb
index 9a6b77715f5..e1889032c8b 100644
--- a/spec/components/previews/pajamas/alert_component_preview.rb
+++ b/spec/components/previews/pajamas/alert_component_preview.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
module Pajamas
class AlertComponentPreview < ViewComponent::Preview
+ # @param title text
# @param body text
# @param dismissible toggle
# @param variant select [info, warning, success, danger, tip]
- def default(body: nil, dismissible: true, variant: :info)
+ def default(title: "Alert title (optional)", body: "Alert message goes here.", dismissible: true, variant: :info)
render(Pajamas::AlertComponent.new(
- title: "Title",
+ title: title,
dismissible: dismissible,
variant: variant.to_sym
)) do |c|
diff --git a/spec/components/previews/pajamas/progress_component_preview.rb b/spec/components/previews/pajamas/progress_component_preview.rb
new file mode 100644
index 00000000000..4de07872a80
--- /dev/null
+++ b/spec/components/previews/pajamas/progress_component_preview.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Pajamas
+ class ProgressComponentPreview < ViewComponent::Preview
+ # Progress
+ # ---
+ #
+ # See its design reference [here](https://design.gitlab.com/components/progress-bar).
+ #
+ # @param value number
+ # @param variant select [primary, success]
+ def default(value: 50, variant: :primary)
+ render Pajamas::ProgressComponent.new(value: value, variant: variant)
+ end
+ end
+end
diff --git a/spec/config/object_store_settings_spec.rb b/spec/config/object_store_settings_spec.rb
index 8ddb5652dae..9275c809550 100644
--- a/spec/config/object_store_settings_spec.rb
+++ b/spec/config/object_store_settings_spec.rb
@@ -113,6 +113,27 @@ RSpec.describe ObjectStoreSettings do
expect(settings.lfs['object_store']['bucket_prefix']).to eq('lfs')
end
+ context 'with Google CDN enabled' do
+ let(:cdn_config) do
+ {
+ 'provider' => 'Google',
+ 'url' => 'https://cdn.example.org',
+ 'key_name' => 'stanhu-key',
+ 'key' => Base64.urlsafe_encode64(SecureRandom.hex)
+ }
+ end
+
+ before do
+ config['object_store']['objects']['artifacts']['cdn'] = cdn_config
+ end
+
+ it 'populates artifacts CDN config' do
+ subject
+
+ expect(settings.artifacts['object_store']['cdn']).to eq(cdn_config)
+ end
+ end
+
it 'raises an error when a bucket is missing' do
config['object_store']['objects']['lfs'].delete('bucket')
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index ab0cad989cb..0ad0a111156 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -211,6 +211,13 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set
expect(ApplicationSetting.current.valid_runner_registrars).to eq(['project'])
end
+ it 'updates can_create_group setting' do
+ put :update, params: { application_setting: { can_create_group: false } }
+
+ expect(response).to redirect_to(general_admin_application_settings_path)
+ expect(ApplicationSetting.current.can_create_group).to eq(false)
+ end
+
context "personal access token prefix settings" do
let(:application_settings) { ApplicationSetting.current }
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb
index 766073977c6..50626a5da91 100644
--- a/spec/controllers/admin/cohorts_controller_spec.rb
+++ b/spec/controllers/admin/cohorts_controller_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Admin::CohortsController do
let(:target_id) { 'i_analytics_cohorts' }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :index }
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
index 5d7a7e089aa..52a46b5e99a 100644
--- a/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Admin::DevOpsReportController do
let(:request_params) { { tab: 'devops-score' } }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :show, format: :html }
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb
index fb843ac6a7a..37cb0a1f289 100644
--- a/spec/controllers/admin/groups_controller_spec.rb
+++ b/spec/controllers/admin/groups_controller_spec.rb
@@ -44,64 +44,4 @@ RSpec.describe Admin::GroupsController do
end.to change { Namespace::AdminNote.count }.by(1)
end
end
-
- describe 'PUT #members_update' do
- let_it_be(:group_user) { create(:user) }
-
- it 'adds user to members', :aggregate_failures, :snowplow do
- put :members_update, params: {
- id: group,
- user_id: group_user.id,
- access_level: Gitlab::Access::GUEST
- }
-
- expect(controller).to set_flash.to 'Users were successfully added.'
- expect(response).to redirect_to(admin_group_path(group))
- expect(group.users).to include group_user
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'create_member',
- label: 'admin-group-page',
- property: 'existing_user',
- user: admin
- )
- end
-
- it 'can add unlimited members', :aggregate_failures do
- put :members_update, params: {
- id: group,
- user_id: 1.upto(1000).to_a.join(','),
- access_level: Gitlab::Access::GUEST
- }
-
- expect(controller).to set_flash.to 'Users were successfully added.'
- expect(response).to redirect_to(admin_group_path(group))
- end
-
- it 'adds no user to members', :aggregate_failures do
- put :members_update, params: {
- id: group,
- user_id: '',
- access_level: Gitlab::Access::GUEST
- }
-
- expect(controller).to set_flash.to 'No users specified.'
- expect(response).to redirect_to(admin_group_path(group))
- expect(group.users).not_to include group_user
- end
-
- it 'updates the project_creation_level successfully' do
- expect do
- post :update, params: { id: group.to_param, group: { project_creation_level: ::Gitlab::Access::NO_ONE_PROJECT_ACCESS } }
- end.to change { group.reload.project_creation_level }.to(::Gitlab::Access::NO_ONE_PROJECT_ACCESS)
- end
-
- it 'updates the subgroup_creation_level successfully' do
- expect do
- post :update,
- params: { id: group.to_param,
- group: { subgroup_creation_level: ::Gitlab::Access::OWNER_SUBGROUP_ACCESS } }
- end.to change { group.reload.subgroup_creation_level }.to(::Gitlab::Access::OWNER_SUBGROUP_ACCESS)
- end
- end
end
diff --git a/spec/controllers/admin/usage_trends_controller_spec.rb b/spec/controllers/admin/usage_trends_controller_spec.rb
index 356f603bf57..87cf8988b4e 100644
--- a/spec/controllers/admin/usage_trends_controller_spec.rb
+++ b/spec/controllers/admin/usage_trends_controller_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Admin::UsageTrendsController do
let(:target_id) { 'i_analytics_instance_statistics' }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :index }
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 70e58124d21..e9b39d44e46 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -96,7 +96,7 @@ RSpec.describe AutocompleteController do
end
context 'user order' do
- it 'shows exact matches first' do
+ it 'shows exact matches first', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375028' do
reported_user = create(:user, username: 'reported_user', name: 'Doug')
user = create(:user, username: 'user', name: 'User')
user1 = create(:user, username: 'user1', name: 'Ian')
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
deleted file mode 100644
index 3e1cdfccc61..00000000000
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ /dev/null
@@ -1,596 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Boards::IssuesController do
- include ExternalAuthorizationServiceHelpers
-
- let(:project) { create(:project, :private) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
- let(:guest) { create(:user) }
-
- let(:planning) { create(:label, project: project, name: 'Planning') }
- let(:development) { create(:label, project: project, name: 'Development') }
-
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: board, label: development, position: 1) }
-
- before do
- project.add_maintainer(user)
- project.add_guest(guest)
- end
-
- describe 'GET index', :request_store do
- let(:johndoe) { create(:user, avatar: fixture_file_upload(File.join('spec/fixtures/dk.png'))) }
-
- context 'with invalid board id' do
- it 'returns a not found 404 response' do
- list_issues user: user, board: non_existing_record_id, list: list2
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when list id is present' do
- context 'with valid list id' do
- let(:group) { create(:group, :private, projects: [project]) }
- let(:group_board) { create(:board, group: group) }
- let!(:list3) { create(:list, board: group_board, label: development, position: 2) }
- let(:sub_group_1) { create(:group, :private, parent: group) }
-
- before do
- group.add_maintainer(user)
- end
-
- it 'returns issues that have the list label applied' do
- issue = create(:labeled_issue, project: project, labels: [planning])
- create(:labeled_issue, project: project, labels: [planning])
- create(:labeled_issue, project: project, labels: [development], due_date: Date.tomorrow)
- create(:labeled_issue, project: project, labels: [development], assignees: [johndoe])
- issue.subscribe(johndoe, project)
- expect(Issue).to receive(:move_nulls_to_end)
-
- list_issues user: user, board: board, list: list2
-
- expect(response).to match_response_schema('entities/issue_boards')
- expect(json_response['issues'].length).to eq 2
- expect(development.issues.map(&:relative_position)).not_to include(nil)
- end
-
- it 'returns issues by closed_at in descending order in closed list' do
- create(:closed_issue, project: project, title: 'New Issue 1', closed_at: 1.day.ago)
- create(:closed_issue, project: project, title: 'New Issue 2', closed_at: 1.week.ago)
-
- list_issues user: user, board: board, list: board.lists.last.id
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['issues'].length).to eq(2)
- expect(json_response['issues'][0]['title']).to eq('New Issue 1')
- expect(json_response['issues'][1]['title']).to eq('New Issue 2')
- end
-
- it 'avoids N+1 database queries' do
- create(:labeled_issue, project: project, labels: [development])
- control_count = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: board, list: list2) }.count
-
- # 25 issues is bigger than the page size
- # the relative position will ignore the `#make_sure_position_set` queries
- create_list(:labeled_issue, 25, project: project, labels: [development], assignees: [johndoe], relative_position: 1)
-
- expect { list_issues(user: user, board: board, list: list2) }.not_to exceed_query_limit(control_count)
- end
-
- it 'avoids N+1 database queries when adding a project', :request_store do
- create(:labeled_issue, project: project, labels: [development])
- control_count = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: group_board, list: list3) }.count
-
- 2.times do
- p = create(:project, group: group)
- create(:labeled_issue, project: p, labels: [development])
- end
-
- project_2 = create(:project, group: group)
- create(:labeled_issue, project: project_2, labels: [development], assignees: [johndoe])
-
- # because each issue without relative_position must be updated with
- # a different value, we have 8 extra queries per issue
- expect { list_issues(user: user, board: group_board, list: list3) }.not_to exceed_query_limit(control_count + (2 * 8 - 1))
- end
-
- it 'avoids N+1 database queries when adding a subgroup, project, and issue' do
- create(:project, group: sub_group_1)
- create(:labeled_issue, project: project, labels: [development])
- control_count = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: group_board, list: list3) }.count
- project_2 = create(:project, group: group)
-
- 2.times do
- p = create(:project, group: sub_group_1)
- create(:labeled_issue, project: p, labels: [development])
- end
-
- create(:labeled_issue, project: project_2, labels: [development], assignees: [johndoe])
-
- expect { list_issues(user: user, board: group_board, list: list3) }.not_to exceed_query_limit(control_count + (2 * 8 - 1))
- end
-
- it 'does not query issues table more than once' do
- recorder = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: board, list: list1) }
- query_count = recorder.occurrences.select { |query,| query.match?(/FROM "?issues"?/) }.each_value.first
-
- expect(query_count).to eq(1)
- end
-
- context 'when block_issue_repositioning feature flag is enabled' do
- before do
- stub_feature_flags(block_issue_repositioning: true)
- end
-
- it 'does not reposition issues with null position' do
- expect(Issue).not_to receive(:move_nulls_to_end)
-
- list_issues(user: user, board: group_board, list: list3)
- end
- end
- end
-
- context 'with invalid list id' do
- it 'returns a not found 404 response' do
- list_issues user: user, board: board, list: non_existing_record_id
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'when list id is missing' do
- it 'returns opened issues without board labels applied' do
- bug = create(:label, project: project, name: 'Bug')
- create(:issue, project: project)
- create(:labeled_issue, project: project, labels: [planning])
- create(:labeled_issue, project: project, labels: [development])
- create(:labeled_issue, project: project, labels: [bug])
-
- list_issues user: user, board: board
-
- expect(response).to match_response_schema('entities/issue_boards')
- expect(json_response['issues'].length).to eq 2
- end
- end
-
- context 'with unauthorized user' do
- let(:unauth_user) { create(:user) }
-
- it 'returns a forbidden 403 response' do
- list_issues user: unauth_user, board: board, list: list2
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'with external authorization' do
- before do
- sign_in(user)
- enable_external_authorization_service_check
- end
-
- it 'returns a 403 for group boards' do
- group = create(:group)
- group_board = create(:board, group: group)
-
- list_issues(user: user, board: group_board)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'is successful for project boards' do
- project_board = create(:board, project: project)
-
- list_issues(user: user, board: project_board)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- describe 'PUT bulk_move' do
- let(:todo) { create(:group_label, group: group, name: 'Todo') }
- let(:development) { create(:group_label, group: group, name: 'Development') }
- let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
- let(:guest) { create(:group_member, :guest, user: create(:user), group: group ).user }
- let(:project) { create(:project, group: group) }
- let(:group) { create(:group) }
- let(:board) { create(:board, project: project) }
- let(:list1) { create(:list, board: board, label: todo, position: 0) }
- let(:list2) { create(:list, board: board, label: development, position: 1) }
- let(:issue1) { create(:labeled_issue, project: project, labels: [todo], author: user, relative_position: 10) }
- let(:issue2) { create(:labeled_issue, project: project, labels: [todo], author: user, relative_position: 20) }
- let(:issue3) { create(:labeled_issue, project: project, labels: [todo], author: user, relative_position: 30) }
- let(:issue4) { create(:labeled_issue, project: project, labels: [development], author: user, relative_position: 100) }
-
- let(:move_params) do
- {
- board_id: board.id,
- ids: [issue1.id, issue2.id, issue3.id],
- from_list_id: list1.id,
- to_list_id: list2.id,
- move_before_id: issue4.id,
- move_after_id: nil
- }
- end
-
- before do
- project.add_maintainer(user)
- project.add_guest(guest)
- end
-
- shared_examples 'move issues endpoint provider' do
- before do
- sign_in(signed_in_user)
- end
-
- it 'responds as expected' do
- put :bulk_move, params: move_issues_params
- expect(response).to have_gitlab_http_status(expected_status)
-
- if expected_status == 200
- expect(json_response).to include(
- 'count' => move_issues_params[:ids].size,
- 'success' => true
- )
-
- expect(json_response['issues'].pluck('id')).to match_array(move_issues_params[:ids])
- end
- end
-
- it 'moves issues as expected' do
- put :bulk_move, params: move_issues_params
- expect(response).to have_gitlab_http_status(expected_status)
-
- list_issues user: requesting_user, board: board, list: list2
- expect(response).to have_gitlab_http_status(:ok)
-
- expect(response).to match_response_schema('entities/issue_boards')
-
- responded_issues = json_response['issues']
- expect(responded_issues.length).to eq expected_issue_count
-
- ids_in_order = responded_issues.pluck('id')
- expect(ids_in_order).to eq(expected_issue_ids_in_order)
- end
- end
-
- context 'when items are moved to another list' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) { move_params }
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 4 }
- let(:expected_issue_ids_in_order) { [issue4.id, issue1.id, issue2.id, issue3.id] }
- end
- end
-
- context 'when moving just one issue' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:ids] = [issue2.id]
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 2 }
- let(:expected_issue_ids_in_order) { [issue4.id, issue2.id] }
- end
- end
-
- context 'when user is not allowed to move issue' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { guest }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:ids] = [issue2.id]
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 403 }
- let(:expected_issue_count) { 1 }
- let(:expected_issue_ids_in_order) { [issue4.id] }
- end
- end
-
- context 'when issues should be moved visually above existing issue in list' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:move_after_id] = issue4.id
- hash[:move_before_id] = nil
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 4 }
- let(:expected_issue_ids_in_order) { [issue1.id, issue2.id, issue3.id, issue4.id] }
- end
- end
-
- context 'when destination list is empty' do
- before do
- # Remove issue from list
- issue4.labels -= [development]
- issue4.save!
- end
-
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:move_before_id] = nil
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 3 }
- let(:expected_issue_ids_in_order) { [issue1.id, issue2.id, issue3.id] }
- end
- end
-
- context 'when no position arguments are given' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:move_before_id] = nil
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 4 }
- let(:expected_issue_ids_in_order) { [issue1.id, issue2.id, issue3.id, issue4.id] }
- end
- end
-
- context 'when move_before_id and move_after_id are given' do
- let(:issue5) { create(:labeled_issue, project: project, labels: [development], author: user, relative_position: 90) }
-
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:move_before_id] = issue5.id
- hash[:move_after_id] = issue4.id
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 200 }
- let(:expected_issue_count) { 5 }
- let(:expected_issue_ids_in_order) { [issue5.id, issue1.id, issue2.id, issue3.id, issue4.id] }
- end
- end
-
- context 'when request contains too many issues' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:ids] = (0..51).to_a
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 422 }
- let(:expected_issue_count) { 1 }
- let(:expected_issue_ids_in_order) { [issue4.id] }
- end
- end
-
- context 'when request is malformed' do
- it_behaves_like 'move issues endpoint provider' do
- let(:signed_in_user) { user }
- let(:move_issues_params) do
- move_params.dup.tap do |hash|
- hash[:ids] = 'foobar'
- end
- end
-
- let(:requesting_user) { user }
- let(:expected_status) { 400 }
- let(:expected_issue_count) { 1 }
- let(:expected_issue_ids_in_order) { [issue4.id] }
- end
- end
- end
-
- def list_issues(user:, board:, list: nil)
- sign_in(user)
-
- params = {
- board_id: board.to_param,
- list_id: list.try(:to_param)
- }
-
- unless board.try(:parent).is_a?(Group)
- params[:namespace_id] = project.namespace.to_param
- params[:project_id] = project
- end
-
- get :index, params: params.compact
- end
- end
-
- describe 'POST create' do
- context 'when trying to create issue on an unauthorized project' do
- let(:unauthorized_project) { create(:project, :private) }
- let(:issue_params) { { project_id: unauthorized_project.id } }
-
- it 'creates the issue on the board\'s project' do
- expect do
- create_issue user: user, board: board, list: list1, title: 'New issue', additional_issue_params: issue_params
- end.to change(Issue, :count).by(1)
-
- created_issue = Issue.last
-
- expect(created_issue.project).to eq(project)
- expect(unauthorized_project.reload.issues.count).to eq(0)
- end
- end
-
- context 'with valid params' do
- before do
- create_issue user: user, board: board, list: list1, title: 'New issue'
- end
-
- it 'returns a successful 200 response' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns the created issue' do
- expect(response).to match_response_schema('entities/issue_board')
- end
-
- it 'sets the default work_item_type' do
- expect(Issue.last.work_item_type.base_type).to eq('issue')
- end
- end
-
- context 'with invalid params' do
- context 'when title is nil' do
- it 'returns an unprocessable entity 422 response' do
- create_issue user: user, board: board, list: list1, title: nil
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
-
- context 'when list does not belongs to project board' do
- it 'returns a not found 404 response' do
- list = create(:list)
-
- create_issue user: user, board: board, list: list, title: 'New issue'
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'with invalid board id' do
- it 'returns a not found 404 response' do
- create_issue user: user, board: non_existing_record_id, list: list1, title: 'New issue'
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'with invalid list id' do
- it 'returns a not found 404 response' do
- create_issue user: user, board: board, list: non_existing_record_id, title: 'New issue'
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- 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)
- create_issue user: guest, board: board, list: open_list, title: 'New issue'
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'in label list' do
- it 'returns a forbidden 403 response' do
- create_issue user: guest, board: board, list: list1, title: 'New issue'
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- def create_issue(user:, board:, list:, title:, additional_issue_params: {})
- sign_in(user)
-
- post :create, params: {
- board_id: board.to_param,
- list_id: list.to_param,
- issue: { title: title, project_id: project.id }.merge(additional_issue_params)
- },
- format: :json
- end
- end
-
- describe 'PATCH update' do
- let!(:issue) { create(:labeled_issue, project: project, labels: [planning]) }
-
- context 'with valid params' do
- it 'returns a successful 200 response' do
- move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'moves issue to the desired list' do
- move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
-
- expect(issue.reload.labels).to contain_exactly(development)
- end
- end
-
- context 'with invalid params' do
- it 'returns a unprocessable entity 422 response for invalid lists' do
- move user: user, board: board, issue: issue, from_list_id: nil, to_list_id: nil
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
-
- it 'returns a not found 404 response for invalid board id' do
- move user: user, board: non_existing_record_id, issue: issue, from_list_id: list1.id, to_list_id: list2.id
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- it 'returns a not found 404 response for invalid issue id' do
- move user: user, board: board, issue: double(id: non_existing_record_id), from_list_id: list1.id, to_list_id: list2.id
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'with unauthorized user' do
- let(:guest) { create(:user) }
-
- before do
- project.add_guest(guest)
- end
-
- it 'returns a forbidden 403 response' do
- move user: guest, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- def move(user:, board:, issue:, from_list_id:, to_list_id:)
- sign_in(user)
-
- patch :update, params: {
- namespace_id: project.namespace.to_param,
- project_id: project.id,
- board_id: board.to_param,
- id: issue.id,
- from_list_id: from_list_id,
- to_list_id: to_list_id
- },
- format: :json
- end
- end
-end
diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb
deleted file mode 100644
index 95334974e66..00000000000
--- a/spec/controllers/boards/lists_controller_spec.rb
+++ /dev/null
@@ -1,333 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Boards::ListsController do
- let(:project) { create(:project) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
- let(:guest) { create(:user) }
-
- before do
- project.add_maintainer(user)
- project.add_guest(guest)
- end
-
- describe 'GET index' do
- before do
- create(:list, board: board)
- end
-
- it 'returns a successful 200 response' do
- read_board_list user: user, board: board
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq 'application/json'
- end
-
- it 'returns a list of board lists' do
- read_board_list user: user, board: board
-
- expect(response).to match_response_schema('lists')
- expect(json_response.length).to eq 3
- end
-
- context 'when another user has list preferences' do
- before do
- board.lists.first.update_preferences_for(guest, collapsed: true)
- end
-
- it 'returns the complete list of board lists' do
- read_board_list user: user, board: board
-
- expect(json_response.length).to eq 3
- end
- end
-
- context 'with unauthorized user' do
- let(:unauth_user) { create(:user) }
-
- it 'returns a forbidden 403 response' do
- read_board_list user: unauth_user, board: board
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- def read_board_list(user:, board:)
- sign_in(user)
-
- get :index, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- board_id: board.to_param
- },
- format: :json
- end
- end
-
- describe 'POST create' do
- context 'with valid params' do
- let(:label) { create(:label, project: project, name: 'Development') }
-
- it 'returns a successful 200 response' do
- create_board_list user: user, board: board, label_id: label.id
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns the created list' do
- create_board_list user: user, board: board, label_id: label.id
-
- expect(response).to match_response_schema('list')
- end
- end
-
- context 'with invalid params' do
- context 'when label is nil' do
- it 'returns an unprocessable entity 422 response' do
- create_board_list user: user, board: board, label_id: nil
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response['errors']).to eq(['Label not found'])
- end
- end
-
- context 'when label that does not belongs to project' do
- it 'returns an unprocessable entity 422 response' do
- label = create(:label, name: 'Development')
-
- create_board_list user: user, board: board, label_id: label.id
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response['errors']).to eq(['Label not found'])
- end
- end
- end
-
- context 'with unauthorized user' do
- it 'returns a forbidden 403 response' do
- label = create(:label, project: project, name: 'Development')
-
- create_board_list user: guest, board: board, label_id: label.id
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- def create_board_list(user:, board:, label_id:)
- sign_in(user)
-
- post :create, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- board_id: board.to_param,
- list: { label_id: label_id }
- },
- format: :json
- end
- end
-
- describe 'PATCH update' do
- let!(:planning) { create(:list, board: board, position: 0) }
- let!(:development) { create(:list, board: board, position: 1) }
-
- context 'with valid position' do
- it 'returns a successful 200 response' do
- move user: user, board: board, list: planning, position: 1
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'moves the list to the desired position' do
- move user: user, board: board, list: planning, position: 1
-
- expect(planning.reload.position).to eq 1
- end
- end
-
- context 'with invalid position' do
- it 'returns an unprocessable entity 422 response' do
- move user: user, board: board, list: planning, position: 6
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
-
- context 'with invalid list id' do
- it 'returns a not found 404 response' do
- move user: user, board: board, list: non_existing_record_id, position: 1
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'with unauthorized user' do
- it 'returns a 422 unprocessable entity response' do
- move user: guest, board: board, list: planning, position: 6
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
-
- context 'with collapsed preference' do
- it 'saves collapsed preference for user' do
- save_setting user: user, board: board, list: planning, setting: { collapsed: true }
-
- expect(planning.preferences_for(user).collapsed).to eq(true)
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'saves not collapsed preference for user' do
- save_setting user: user, board: board, list: planning, setting: { collapsed: false }
-
- expect(planning.preferences_for(user).collapsed).to eq(false)
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with a list_type other than :label' do
- let!(:closed) { create(:closed_list, board: board, position: 2) }
-
- it 'saves collapsed preference for user' do
- save_setting user: user, board: board, list: closed, setting: { collapsed: true }
-
- expect(closed.preferences_for(user).collapsed).to eq(true)
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'saves not collapsed preference for user' do
- save_setting user: user, board: board, list: closed, setting: { collapsed: false }
-
- expect(closed.preferences_for(user).collapsed).to eq(false)
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- def move(user:, board:, list:, position:)
- sign_in(user)
-
- params = { namespace_id: project.namespace.to_param,
- project_id: project.id,
- board_id: board.to_param,
- id: list.to_param,
- list: { position: position },
- format: :json }
-
- patch :update, params: params, as: :json
- end
-
- def save_setting(user:, board:, list:, setting: {})
- sign_in(user)
-
- params = { namespace_id: project.namespace.to_param,
- project_id: project.id,
- board_id: board.to_param,
- id: list.to_param,
- list: setting,
- format: :json }
-
- patch :update, params: params, as: :json
- end
- end
-
- describe 'DELETE destroy' do
- let!(:planning) { create(:list, board: board, position: 0) }
-
- context 'with valid list id' do
- it 'returns a successful 200 response' do
- remove_board_list user: user, board: board, list: planning
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'removes list from board' do
- expect { remove_board_list user: user, board: board, list: planning }.to change(board.lists, :size).by(-1)
- end
- end
-
- context 'with invalid list id' do
- it 'returns a not found 404 response' do
- remove_board_list user: user, board: board, list: non_existing_record_id
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'with unauthorized user' do
- it 'returns a forbidden 403 response' do
- remove_board_list user: guest, board: board, list: planning
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'with an error service response' do
- it 'returns an unprocessable entity response' do
- allow(Boards::Lists::DestroyService).to receive(:new)
- .and_return(double(execute: ServiceResponse.error(message: 'error')))
-
- remove_board_list user: user, board: board, list: planning
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
-
- def remove_board_list(user:, board:, list:)
- sign_in(user)
-
- delete :destroy, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- board_id: board.to_param,
- id: list.to_param
- },
- format: :json
- end
- end
-
- describe 'POST generate' do
- context 'when board lists is empty' do
- it 'returns a successful 200 response' do
- generate_default_lists user: user, board: board
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns the defaults lists' do
- generate_default_lists user: user, board: board
-
- expect(response).to match_response_schema('lists')
- end
- end
-
- context 'when board lists is not empty' do
- it 'returns an unprocessable entity 422 response' do
- create(:list, board: board)
-
- generate_default_lists user: user, board: board
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
-
- context 'with unauthorized user' do
- it 'returns a forbidden 403 response' do
- generate_default_lists user: guest, board: board
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- def generate_default_lists(user:, board:)
- sign_in(user)
-
- post :generate, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- board_id: board.to_param
- },
- format: :json
- end
- end
-end
diff --git a/spec/controllers/concerns/boards_responses_spec.rb b/spec/controllers/concerns/boards_responses_spec.rb
deleted file mode 100644
index 553a547d42c..00000000000
--- a/spec/controllers/concerns/boards_responses_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BoardsResponses do
- let(:controller_class) do
- Class.new do
- include BoardsResponses
- end
- end
-
- subject(:controller) { controller_class.new }
-
- describe '#serialize_as_json' do
- let!(:board) { create(:board) }
-
- it 'serializes properly' do
- expected = { "id" => board.id }
-
- expect(subject.serialize_as_json(board)).to include(expected)
- end
- end
-end
diff --git a/spec/controllers/concerns/product_analytics_tracking_spec.rb b/spec/controllers/concerns/product_analytics_tracking_spec.rb
index 2e734d81ea0..28b79a10624 100644
--- a/spec/controllers/concerns/product_analytics_tracking_spec.rb
+++ b/spec/controllers/concerns/product_analytics_tracking_spec.rb
@@ -51,15 +51,21 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
end
end
- def expect_tracking(user: self.user)
+ def expect_redis_hll_tracking
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to have_received(:track_event)
.with('g_analytics_valuestream', values: instance_of(String))
+ end
+
+ def expect_snowplow_tracking(user)
+ context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'g_analytics_valuestream')
+ .to_context.to_json
expect_snowplow_event(
category: anything,
action: 'g_analytics_valuestream',
namespace: group,
- user: user
+ user: user,
+ context: [context]
)
end
@@ -77,7 +83,8 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
it 'tracks the event' do
get :index
- expect_tracking
+ expect_redis_hll_tracking
+ expect_snowplow_tracking(user)
end
context 'when FF is disabled' do
@@ -97,7 +104,8 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
get :index
- expect_tracking
+ expect_redis_hll_tracking
+ expect_snowplow_tracking(user)
end
it 'does not track the event if DNT is enabled' do
@@ -137,7 +145,8 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
get :show, params: { id: 1 }
- expect_tracking(user: nil)
+ expect_redis_hll_tracking
+ expect_snowplow_tracking(nil)
end
end
@@ -151,21 +160,24 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
it 'tracks the event when there is custom id' do
get :show, params: { id: 1 }
- expect_tracking(user: nil)
+ expect_redis_hll_tracking
+ expect_snowplow_tracking(nil)
end
- it 'does not track the HLL event when there is no custom id' do
- allow(controller).to receive(:get_custom_id).and_return(nil)
+ context 'when there is no custom_id set' do
+ before do
+ allow(controller).to receive(:get_custom_id).and_return(nil)
- get :show, params: { id: 2 }
+ get :show, params: { id: 2 }
+ end
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
- expect_snowplow_event(
- category: anything,
- action: 'g_analytics_valuestream',
- namespace: group,
- user: nil
- )
+ it 'does not track the HLL event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+ end
+
+ it 'tracks Snowplow event' do
+ expect_snowplow_tracking(nil)
+ end
end
end
end
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index f9a6afb95ea..32304815bbb 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -96,9 +96,10 @@ RSpec.describe SendFileUpload do
expect(controller).to receive(:params).at_least(:once).and_return(width: '64')
expect(controller).to receive(:head).with(:ok)
- expect(Gitlab::Workhorse).to receive(:send_scaled_image).with(a_string_matching('^(/.+|https://.+)'), 64, 'image/png').and_return([
- Gitlab::Workhorse::SEND_DATA_HEADER, "send-scaled-img:faux"
- ])
+ expect(Gitlab::Workhorse).to receive(:send_scaled_image)
+ .with(a_string_matching('^(/.+|https://.+)'), 64, 'image/png')
+ .and_return([Gitlab::Workhorse::SEND_DATA_HEADER, "send-scaled-img:faux"])
+
expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, "send-scaled-img:faux")
subject
diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb
index aed310531e6..21810f64cb4 100644
--- a/spec/controllers/dashboard_controller_spec.rb
+++ b/spec/controllers/dashboard_controller_spec.rb
@@ -4,11 +4,14 @@ require 'spec_helper'
RSpec.describe DashboardController do
context 'signed in' do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
- before do
+ before_all do
project.add_maintainer(user)
+ end
+
+ before do
sign_in(user)
end
@@ -30,6 +33,28 @@ RSpec.describe DashboardController do
end
it_behaves_like 'issuables requiring filter', :issues
+
+ it 'includes tasks in issue list' do
+ task = create(:work_item, :task, project: project, author: user)
+
+ get :issues, params: { author_id: user.id }
+
+ expect(assigns[:issues].map(&:id)).to include(task.id)
+ end
+
+ context 'when work_items is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not include tasks in issue list' do
+ task = create(:work_item, :task, project: project, author: user)
+
+ get :issues, params: { author_id: user.id }
+
+ expect(assigns[:issues].map(&:id)).not_to include(task.id)
+ end
+ end
end
describe 'GET merge requests' do
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index 6201cddecb0..4e441f86765 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -3,11 +3,14 @@
require 'spec_helper'
RSpec.describe Groups::BoardsController do
- let(:group) { create(:group) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
- before do
+ before_all do
group.add_maintainer(user)
+ end
+
+ before do
sign_in(user)
end
@@ -57,46 +60,17 @@ RSpec.describe Groups::BoardsController do
end
end
- context 'when format is JSON' do
- it 'return an array with one group board' do
- create(:board, group: group)
-
- expect(Boards::VisitsFinder).not_to receive(:new)
-
- list_boards format: :json
-
- expect(response).to match_response_schema('boards')
- expect(json_response.length).to eq 1
- end
-
- context 'with unauthorized user' do
- before do
- expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_issue_board, group).and_return(false)
- end
-
- it 'returns a not found 404 response' do
- list_boards format: :json
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.media_type).to eq 'application/json'
- end
- end
- end
-
it_behaves_like 'disabled when using an external authorization service' do
subject { list_boards }
end
- def list_boards(format: :html)
- get :index, params: { group_id: group }, format: format
+ def list_boards
+ get :index, params: { group_id: group }
end
end
describe 'GET show' do
- let!(:board) { create(:board, group: group) }
+ let_it_be(:board) { create(:board, group: group) }
context 'when format is HTML' do
it 'renders template' do
@@ -123,12 +97,12 @@ RSpec.describe Groups::BoardsController do
end
context 'when user is signed out' do
- let(:group) { create(:group, :public) }
+ let(:public_board) { create(:board, group: create(:group, :public)) }
it 'does not save visit' do
sign_out(user)
- expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(0)
+ expect { read_board board: public_board }.to change(BoardGroupRecentVisit, :count).by(0)
expect(response).to render_template :show
expect(response.media_type).to eq 'text/html'
@@ -136,37 +110,11 @@ RSpec.describe Groups::BoardsController do
end
end
- context 'when format is JSON' do
- it 'returns project board' do
- expect(Boards::Visits::CreateService).not_to receive(:new)
-
- read_board board: board, format: :json
-
- expect(response).to match_response_schema('board')
- end
-
- context 'with unauthorized user' do
- before do
- expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(false)
- end
-
- it 'returns a not found 404 response' do
- read_board board: board, format: :json
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.media_type).to eq 'application/json'
- end
- end
- end
-
context 'when board does not belong to group' do
it 'returns a not found 404 response' do
another_board = create(:board)
- read_board board: another_board
+ get :show, params: { group_id: group, id: another_board.to_param }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -176,12 +124,8 @@ RSpec.describe Groups::BoardsController do
subject { read_board board: board }
end
- def read_board(board:, format: :html)
- get :show, params: {
- group_id: group,
- id: board.to_param
- },
- format: format
+ def read_board(board:)
+ get :show, params: { group_id: board.group, id: board.to_param }
end
end
end
diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
index 77c62c0d930..6dbf0803892 100644
--- a/spec/controllers/groups/runners_controller_spec.rb
+++ b/spec/controllers/groups/runners_controller_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe Groups::RunnersController do
let_it_be(:project) { create(:project, group: group) }
let!(:runner) { create(:ci_runner, :group, groups: [group]) }
- let!(:runner_project) { create(:ci_runner, :project, projects: [project]) }
+ let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
+ let!(:instance_runner) { create(:ci_runner, :instance) }
- let(:params_runner_project) { { group_id: group, id: runner_project } }
+ let(:params_runner_project) { { group_id: group, id: project_runner } }
+ let(:params_runner_instance) { { group_id: group, id: instance_runner } }
let(:params) { { group_id: group, id: runner } }
before do
@@ -70,8 +72,15 @@ RSpec.describe Groups::RunnersController do
expect(response).to render_template(:show)
end
+ it 'renders show with 200 status code instance runner' do
+ get :show, params: { group_id: group, id: instance_runner }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ end
+
it 'renders show with 200 status code project runner' do
- get :show, params: { group_id: group, id: runner_project }
+ get :show, params: { group_id: group, id: project_runner }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
@@ -89,8 +98,14 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
end
+ it 'renders a 404 instance runner' do
+ get :show, params: { group_id: group, id: instance_runner }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
it 'renders a 404 project runner' do
- get :show, params: { group_id: group, id: runner_project }
+ get :show, params: { group_id: group, id: project_runner }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -103,15 +118,21 @@ RSpec.describe Groups::RunnersController do
group.add_owner(user)
end
- it 'renders show with 200 status code' do
+ it 'renders edit with 200 status code' do
get :edit, params: { group_id: group, id: runner }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:edit)
end
- it 'renders show with 200 status code project runner' do
- get :edit, params: { group_id: group, id: runner_project }
+ it 'renders a 404 instance runner' do
+ get :edit, params: { group_id: group, id: instance_runner }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'renders edit with 200 status code project runner' do
+ get :edit, params: { group_id: group, id: project_runner }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:edit)
@@ -130,7 +151,7 @@ RSpec.describe Groups::RunnersController do
end
it 'renders a 404 project runner' do
- get :edit, params: { group_id: group, id: runner_project }
+ get :edit, params: { group_id: group, id: project_runner }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -154,15 +175,26 @@ RSpec.describe Groups::RunnersController do
expect(runner.reload.description).to eq(new_desc)
end
+ it 'does not update the instance runner' do
+ new_desc = instance_runner.description.swapcase
+
+ expect do
+ post :update, params: params_runner_instance.merge(runner: { description: new_desc } )
+ end.to not_change { instance_runner.ensure_runner_queue_value }
+ .and not_change { instance_runner.description }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
it 'updates the project runner, ticks the queue, and redirects project runner' do
- new_desc = runner_project.description.swapcase
+ new_desc = project_runner.description.swapcase
expect do
post :update, params: params_runner_project.merge(runner: { description: new_desc } )
- end.to change { runner_project.ensure_runner_queue_value }
+ end.to change { project_runner.ensure_runner_queue_value }
expect(response).to have_gitlab_http_status(:found)
- expect(runner_project.reload.description).to eq(new_desc)
+ expect(project_runner.reload.description).to eq(new_desc)
end
end
@@ -182,15 +214,26 @@ RSpec.describe Groups::RunnersController do
expect(runner.reload.description).to eq(old_desc)
end
+ it 'rejects the update and responds 404 instance runner' do
+ old_desc = instance_runner.description
+
+ expect do
+ post :update, params: params_runner_instance.merge(runner: { description: old_desc.swapcase } )
+ end.not_to change { instance_runner.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(instance_runner.reload.description).to eq(old_desc)
+ end
+
it 'rejects the update and responds 404 project runner' do
- old_desc = runner_project.description
+ old_desc = project_runner.description
expect do
post :update, params: params_runner_project.merge(runner: { description: old_desc.swapcase } )
- end.not_to change { runner_project.ensure_runner_queue_value }
+ end.not_to change { project_runner.ensure_runner_queue_value }
expect(response).to have_gitlab_http_status(:not_found)
- expect(runner_project.reload.description).to eq(old_desc)
+ expect(project_runner.reload.description).to eq(old_desc)
end
end
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index c4e4eeec953..5bbe236077c 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -229,7 +229,7 @@ RSpec.describe GroupsController, factory_default: :keep do
sign_in(user)
expect do
- post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ post :create, params: { group: { name: 'new_group', path: 'new_group' } }
end.to change { Group.count }.by(1)
expect(response).to have_gitlab_http_status(:found)
@@ -240,13 +240,31 @@ RSpec.describe GroupsController, factory_default: :keep do
sign_in(create(:admin))
expect do
- post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ post :create, params: { group: { name: 'new_group', path: 'new_group' } }
end.to change { Group.count }.by(1)
expect(response).to have_gitlab_http_status(:found)
end
end
+ context 'when creating chat team' do
+ before do
+ stub_mattermost_setting(enabled: true)
+ end
+
+ it 'triggers Mattermost::CreateTeamService' do
+ sign_in(user)
+
+ expect_next_instance_of(::Mattermost::CreateTeamService) do |service|
+ expect(service).to receive(:execute).and_return({ name: 'test-chat-team', id: 1 })
+ end
+
+ post :create, params: { group: { name: 'new_group', path: 'new_group', create_chat_team: 1 } }
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
context 'when creating subgroups' do
[true, false].each do |can_create_group_status|
context "and can_create_group is #{can_create_group_status}" do
diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
index 7f55c4407dd..47290b1d0d6 100644
--- a/spec/controllers/health_check_controller_spec.rb
+++ b/spec/controllers/health_check_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe HealthCheckController, :request_store do
+RSpec.describe HealthCheckController, :request_store, :use_clean_rails_memory_store_caching do
include StubENV
let(:xml_response) { Hash.from_xml(response.body)['hash'] }
@@ -93,12 +93,13 @@ RSpec.describe HealthCheckController, :request_store do
context 'when a service is down and an endpoint is accessed from whitelisted ip' do
before do
- allow(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
- allow(HealthCheck::Utils).to receive(:process_checks).with(['email']).and_return('Email is on fire')
+ allow(::HealthCheck).to receive(:include_error_in_response_body).and_return(true)
allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(whitelisted_ip)
end
it 'supports failure plaintext response' do
+ expect(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
+
get :index
expect(response).to have_gitlab_http_status(:internal_server_error)
@@ -107,6 +108,8 @@ RSpec.describe HealthCheckController, :request_store do
end
it 'supports failure json response' do
+ expect(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
+
get :index, format: :json
expect(response).to have_gitlab_http_status(:internal_server_error)
@@ -116,6 +119,8 @@ RSpec.describe HealthCheckController, :request_store do
end
it 'supports failure xml response' do
+ expect(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
+
get :index, format: :xml
expect(response).to have_gitlab_http_status(:internal_server_error)
@@ -125,6 +130,8 @@ RSpec.describe HealthCheckController, :request_store do
end
it 'supports failure responses for specific checks' do
+ expect(HealthCheck::Utils).to receive(:process_checks).with(['email']).and_return('Email is on fire')
+
get :index, params: { checks: 'email' }, format: :json
expect(response).to have_gitlab_http_status(:internal_server_error)
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index 3be12717664..a0bb39f3e98 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -247,10 +247,10 @@ RSpec.describe Import::BulkImportsController do
"source_full_path" => "full_path",
"destination_slug" => "destination_name",
"destination_namespace" => "root" },
- { "source_type" => "group_entity2",
- "source_full_path" => "full_path2",
- "destination_slug" => "destination_name2",
- "destination_namespace" => "root" }]
+ { "source_type" => "group_entity",
+ "source_full_path" => "full_path",
+ "destination_slug" => "destination_name",
+ "destination_namespace" => "invalid-namespace" }]
end
before do
@@ -308,6 +308,21 @@ RSpec.describe Import::BulkImportsController do
expect(json_response).to match_array([{ "success" => true, "id" => bulk_import.id, "message" => nil }])
end
end
+
+ context 'when source type is project' do
+ let(:bulk_import_params) do
+ [{ "source_type" => "project_entity",
+ "source_full_path" => "full_path",
+ "destination_slug" => "destination_name",
+ "destination_namespace" => "root" }]
+ end
+
+ it 'returns 422' do
+ post :create, params: { bulk_import: bulk_import_params }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
end
end
diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb
index 269eb62cae6..f3632e7370c 100644
--- a/spec/controllers/import/github_controller_spec.rb
+++ b/spec/controllers/import/github_controller_spec.rb
@@ -44,13 +44,6 @@ RSpec.describe Import::GithubController do
end
describe "GET callback" do
- before do
- allow(controller).to receive(:get_token).and_return(token)
- allow(controller).to receive(:oauth_options).and_return({})
-
- stub_omniauth_provider('github')
- end
-
context "when auth state param is missing from session" do
it "reports an error" do
get :callback
@@ -63,17 +56,31 @@ RSpec.describe Import::GithubController do
context "when auth state param is present in session" do
let(:valid_auth_state) { "secret-state" }
- before do
- session[:github_auth_state_key] = valid_auth_state
- end
+ context 'when remove_legacy_github_client feature is disabled' do
+ before do
+ stub_feature_flags(remove_legacy_github_client: false)
+ allow_next_instance_of(Gitlab::LegacyGithubImport::Client) do |client|
+ allow(client).to receive(:get_token).and_return(token)
+ end
+ session[:github_auth_state_key] = valid_auth_state
+ end
+
+ it "updates access token if state param is valid" do
+ token = "asdasd12345"
- it "updates access token if state param is valid" do
- token = "asdasd12345"
+ get :callback, params: { state: valid_auth_state }
- get :callback, params: { state: valid_auth_state }
+ expect(session[:github_access_token]).to eq(token)
+ expect(controller).to redirect_to(status_import_github_url)
+ end
+
+ it "includes namespace_id from query params if it is present" do
+ namespace_id = 1
+
+ get :callback, params: { state: valid_auth_state, namespace_id: namespace_id }
- expect(session[:github_access_token]).to eq(token)
- expect(controller).to redirect_to(status_import_github_url)
+ expect(controller).to redirect_to(status_import_github_url(namespace_id: namespace_id))
+ end
end
it "reports an error if state param is invalid" do
@@ -83,12 +90,31 @@ RSpec.describe Import::GithubController do
expect(flash[:alert]).to eq('Access denied to your GitHub account.')
end
- it "includes namespace_id from query params if it is present" do
- namespace_id = 1
+ context 'when remove_legacy_github_client feature is enabled' do
+ before do
+ stub_feature_flags(remove_legacy_github_client: true)
+ allow_next_instance_of(OAuth2::Client) do |client|
+ allow(client).to receive_message_chain(:auth_code, :get_token, :token).and_return(token)
+ end
+ session[:github_auth_state_key] = valid_auth_state
+ end
+
+ it "updates access token if state param is valid" do
+ token = "asdasd12345"
- get :callback, params: { state: valid_auth_state, namespace_id: namespace_id }
+ get :callback, params: { state: valid_auth_state }
+
+ expect(session[:github_access_token]).to eq(token)
+ expect(controller).to redirect_to(status_import_github_url)
+ end
- expect(controller).to redirect_to(status_import_github_url(namespace_id: namespace_id))
+ it "includes namespace_id from query params if it is present" do
+ namespace_id = 1
+
+ get :callback, params: { state: valid_auth_state, namespace_id: namespace_id }
+
+ expect(controller).to redirect_to(status_import_github_url(namespace_id: namespace_id))
+ end
end
end
end
@@ -218,7 +244,7 @@ RSpec.describe Import::GithubController do
it 'makes request to github search api' do
expect_next_instance_of(Octokit::Client) do |client|
- expect(client).to receive(:user).and_return(double(login: user_login))
+ expect(client).to receive(:user).and_return({ login: user_login })
expect(client).to receive(:search_repositories).with(search_query, { page: 1, per_page: 25 }).and_return({ items: [].to_enum })
end
@@ -234,7 +260,7 @@ RSpec.describe Import::GithubController do
context 'when no page is specified' do
it 'requests first page' do
expect_next_instance_of(Octokit::Client) do |client|
- expect(client).to receive(:user).and_return(double(login: user_login))
+ expect(client).to receive(:user).and_return({ login: user_login })
expect(client).to receive(:search_repositories).with(search_query, { page: 1, per_page: 25 }).and_return({ items: [].to_enum })
end
@@ -250,7 +276,7 @@ RSpec.describe Import::GithubController do
context 'when page is specified' do
it 'requests repos with specified page' do
expect_next_instance_of(Octokit::Client) do |client|
- expect(client).to receive(:user).and_return(double(login: user_login))
+ expect(client).to receive(:user).and_return({ login: user_login })
expect(client).to receive(:search_repositories).with(search_query, { page: 2, per_page: 25 }).and_return({ items: [].to_enum })
end
@@ -321,4 +347,37 @@ RSpec.describe Import::GithubController do
expect(json_response[0]['stats']).to include('imported')
end
end
+
+ describe "POST cancel" do
+ let_it_be(:project) { create(:project, :import_started, import_type: 'github', import_url: 'https://fake.url') }
+
+ context 'when project import was canceled' do
+ before do
+ allow(Import::Github::CancelProjectImportService)
+ .to receive(:new).with(project, user)
+ .and_return(double(execute: { status: :success, project: project }))
+ end
+
+ it 'returns success' do
+ post :cancel, params: { project_id: project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when project import was not canceled' do
+ before do
+ allow(Import::Github::CancelProjectImportService)
+ .to receive(:new).with(project, user)
+ .and_return(double(execute: { status: :error, message: 'The import cannot be canceled because it is finished', http_status: :bad_request }))
+ end
+
+ it 'returns error' do
+ post :cancel, params: { project_id: project.id }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['errors']).to eq('The import cannot be canceled because it is finished')
+ end
+ end
+ end
end
diff --git a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
index 99e9644da66..8dee0490fd6 100644
--- a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
+++ b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
@@ -35,6 +35,18 @@ RSpec.describe Profiles::PersonalAccessTokensController do
expect(created_token).not_to be_nil
expect(created_token.expires_at).to eq(expires_at)
end
+
+ it 'does not allow creation when personal access tokens are disabled' do
+ allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
+
+ post :create, params: { personal_access_token: token_attributes }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it_behaves_like "#create access token" do
+ let(:url) { :create }
+ end
end
describe '#index' do
@@ -66,6 +78,14 @@ RSpec.describe Profiles::PersonalAccessTokensController do
)
end
+ it 'returns 404 when personal access tokens are disabled' do
+ allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
context "access_token_pagination feature flag is enabled" do
before do
stub_feature_flags(access_token_pagination: true)
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
index 7add3a72337..e2a216bb462 100644
--- a/spec/controllers/profiles/preferences_controller_spec.rb
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -53,7 +53,8 @@ RSpec.describe Profiles::PreferencesController do
first_day_of_week: '1',
preferred_language: 'jp',
tab_width: '5',
- render_whitespace_in_code: 'true'
+ render_whitespace_in_code: 'true',
+ use_legacy_web_ide: 'true'
}.with_indifferent_access
expect(user).to receive(:assign_attributes).with(ActionController::Parameters.new(prefs).permit!)
diff --git a/spec/controllers/profiles/two_factor_auths_controller_spec.rb b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
index 33cba675777..1dd564427d3 100644
--- a/spec/controllers/profiles/two_factor_auths_controller_spec.rb
+++ b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
@@ -31,13 +31,26 @@ RSpec.describe Profiles::TwoFactorAuthsController do
shared_examples 'user must enter a valid current password' do
let(:current_password) { '123' }
- let(:redirect_path) { profile_two_factor_auth_path }
+ let(:error_message) { { message: _('You must provide a valid current password') } }
it 'requires the current password', :aggregate_failures do
go
- expect(response).to redirect_to(redirect_path)
- expect(flash[:alert]).to eq(_('You must provide a valid current password'))
+ expect(assigns[:error]).to eq(error_message)
+ expect(response).to render_template(:show)
+ end
+
+ it 'assigns qr_code' do
+ code = double('qr code')
+ expect(subject).to receive(:build_qr_code).and_return(code)
+
+ go
+ expect(assigns[:qr_code]).to eq(code)
+ end
+
+ it 'assigns account_string' do
+ go
+ expect(assigns[:account_string]).to eq("#{Gitlab.config.gitlab.host}:#{user.email}")
end
context 'when the user is on the last sign in attempt' do
@@ -58,8 +71,7 @@ RSpec.describe Profiles::TwoFactorAuthsController do
it 'does not require the current password', :aggregate_failures do
go
- expect(response).not_to redirect_to(redirect_path)
- expect(flash[:alert]).to be_nil
+ expect(assigns[:error]).not_to eq(error_message)
end
end
@@ -71,8 +83,7 @@ RSpec.describe Profiles::TwoFactorAuthsController do
it 'does not require the current password', :aggregate_failures do
go
- expect(response).not_to redirect_to(redirect_path)
- expect(flash[:alert]).to be_nil
+ expect(assigns[:error]).not_to eq(error_message)
end
end
@@ -84,8 +95,7 @@ RSpec.describe Profiles::TwoFactorAuthsController do
it 'does not require the current password', :aggregate_failures do
go
- expect(response).not_to redirect_to(redirect_path)
- expect(flash[:alert]).to be_nil
+ expect(assigns[:error]).not_to eq(error_message)
end
end
end
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 263f488ddbf..808e67eff3d 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -229,7 +229,7 @@ RSpec.describe Projects::ArtifactsController do
expect(response.body).to include(
'You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. ' \
'To disable debug trace, set the &#39;CI_DEBUG_TRACE&#39; variable to &#39;false&#39; in your pipeline configuration or CI/CD settings. ' \
- 'If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher.'
+ 'If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher.'
)
end
end
diff --git a/spec/controllers/projects/autocomplete_sources_controller_spec.rb b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
index a5274b6543e..7077aae6b45 100644
--- a/spec/controllers/projects/autocomplete_sources_controller_spec.rb
+++ b/spec/controllers/projects/autocomplete_sources_controller_spec.rb
@@ -5,37 +5,133 @@ require 'spec_helper'
RSpec.describe Projects::AutocompleteSourcesController do
let_it_be(:group, reload: true) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
- let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:public_project) { create(:project, :public, group: group) }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:issue) { create(:labeled_issue, project: project, labels: [development]) }
let_it_be(:user) { create(:user) }
def members_by_username(username)
json_response.find { |member| member['username'] == username }
end
- describe 'GET members' do
+ describe 'GET commands' do
+ before do
+ group.add_owner(user)
+ end
+
+ context 'with a public project' do
+ shared_examples 'issuable commands' do
+ it 'returns empty array when no user logged in' do
+ get :commands, format: :json, params: { namespace_id: group.path, project_id: public_project.path, type: issuable_type, type_id: issuable_iid }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+
+ it 'raises an error when no target type specified' do
+ sign_in(user)
+
+ expect { get :commands, format: :json, params: { namespace_id: group.path, project_id: project.path } }
+ .to raise_error(ActionController::ParameterMissing)
+ end
+
+ it 'returns an array of commands' do
+ sign_in(user)
+
+ get :commands, format: :json, params: { namespace_id: group.path, project_id: public_project.path, type: issuable_type, type_id: issuable_iid }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_present
+ end
+ end
+
+ context 'with an issue' do
+ let(:issuable_type) { issue.class.name }
+ let(:issuable_iid) { issue.iid }
+
+ it_behaves_like 'issuable commands'
+ end
+
+ context 'with merge request' do
+ let(:merge_request) { create(:merge_request, target_project: public_project, source_project: public_project) }
+ let(:issuable_type) { merge_request.class.name }
+ let(:issuable_iid) { merge_request.iid }
+
+ it_behaves_like 'issuable commands'
+ end
+ end
+ end
+
+ describe 'GET labels' do
before do
group.add_owner(user)
sign_in(user)
end
- it 'returns an array of member object' do
- get :members, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
+ it 'raises an error when no target type specified' do
+ expect { get :labels, format: :json, params: { namespace_id: group.path, project_id: project.path } }
+ .to raise_error(ActionController::ParameterMissing)
+ end
+
+ it 'returns an array of labels' do
+ get :labels, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
+
+ expect(json_response).to be_a(Array)
+ expect(json_response.count).to eq(1)
+ expect(json_response[0]['title']).to eq('Development')
+ end
+ end
+
+ describe 'GET members' do
+ context 'when logged in' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'returns 400 when no target type specified' do
+ expect { get :members, format: :json, params: { namespace_id: group.path, project_id: project.path } }
+ .to raise_error(ActionController::ParameterMissing)
+ end
+
+ it 'returns an array of member object' do
+ get :members, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
+
+ expect(members_by_username('all').symbolize_keys).to include(
+ username: 'all',
+ name: 'All Project and Group Members',
+ count: 1)
+
+ expect(members_by_username(group.full_path).symbolize_keys).to include(
+ type: group.class.name,
+ name: group.full_name,
+ avatar_url: group.avatar_url,
+ count: 1)
+
+ expect(members_by_username(user.username).symbolize_keys).to include(
+ type: user.class.name,
+ name: user.name,
+ avatar_url: user.avatar_url)
+ end
+ end
+
+ context 'when anonymous' do
+ it 'redirects to login page' do
+ get :members, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
- expect(members_by_username('all').symbolize_keys).to include(
- username: 'all',
- name: 'All Project and Group Members',
- count: 1)
+ expect(response).to redirect_to new_user_session_path
+ end
- expect(members_by_username(group.full_path).symbolize_keys).to include(
- type: group.class.name,
- name: group.full_name,
- avatar_url: group.avatar_url,
- count: 1)
+ context 'with public project' do
+ it 'returns no members' do
+ get :members, format: :json, params: { namespace_id: group.path, project_id: public_project.path, type: issue.class.name, type_id: issue.id }
- expect(members_by_username(user.username).symbolize_keys).to include(
- type: user.class.name,
- name: user.name,
- avatar_url: user.avatar_url)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_a(Array)
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['count']).to eq(0)
+ end
+ end
end
end
@@ -88,7 +184,7 @@ RSpec.describe Projects::AutocompleteSourcesController do
it 'lists contacts' do
group.add_developer(user)
- get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
emails = json_response.map { |contact_data| contact_data["email"] }
expect(emails).to match_array([contact_1.email, contact_2.email])
@@ -97,7 +193,7 @@ RSpec.describe Projects::AutocompleteSourcesController do
context 'when a user can not read contacts' do
it 'renders 404' do
- get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -108,7 +204,7 @@ RSpec.describe Projects::AutocompleteSourcesController do
it 'renders 404' do
group.add_developer(user)
- get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path }
+ get :contacts, format: :json, params: { namespace_id: group.path, project_id: project.path, type: issue.class.name, type_id: issue.id }
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index cde3a8d4761..89d0669f47b 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -3,11 +3,14 @@
require 'spec_helper'
RSpec.describe Projects::BoardsController do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
- before do
+ before_all do
project.add_maintainer(user)
+ end
+
+ before do
sign_in(user)
end
@@ -16,77 +19,63 @@ RSpec.describe Projects::BoardsController do
expect { list_boards }.to change(project.boards, :count).by(1)
end
- it 'sets boards_endpoint instance variable to a boards path' do
+ it 'renders template' do
list_boards
- expect(assigns(:boards_endpoint)).to eq project_boards_path(project)
+ expect(response).to render_template :index
+ expect(response.media_type).to eq 'text/html'
end
- context 'when format is HTML' do
- it 'renders template' do
- list_boards
+ context 'when there are recently visited boards' do
+ let_it_be(:boards) { create_list(:board, 3, resource_parent: project) }
- expect(response).to render_template :index
- expect(response.media_type).to eq 'text/html'
+ before_all do
+ visit_board(boards[2], Time.current + 1.minute)
+ visit_board(boards[0], Time.current + 2.minutes)
+ visit_board(boards[1], Time.current + 5.minutes)
end
- context 'with unauthorized user' do
- before do
- expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_issue_board, project).and_return(false)
- end
-
- it 'returns a not found 404 response' do
- list_boards
+ it 'redirects to latest visited board' do
+ list_boards
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.media_type).to eq 'text/html'
- end
+ expect(response).to redirect_to(
+ namespace_project_board_path(namespace_id: project.namespace, project_id: project, id: boards[1].id)
+ )
end
- context 'when user is signed out' do
- let(:project) { create(:project, :public) }
-
- it 'renders template' do
- sign_out(user)
+ def visit_board(board, time)
+ create(:board_project_recent_visit, project: project, board: board, user: user, updated_at: time)
+ end
+ end
- board = create(:board, project: project)
- create(:board_project_recent_visit, project: board.project, board: board, user: user)
+ context 'with unauthorized user' do
+ before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
+ allow(Ability).to receive(:allowed?).with(user, :read_issue_board, project).and_return(false)
+ end
- list_boards
+ it 'returns a not found 404 response' do
+ list_boards
- expect(response).to render_template :index
- expect(response.media_type).to eq 'text/html'
- end
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.media_type).to eq 'text/html'
end
end
- context 'when format is JSON' do
- it 'returns a list of project boards' do
- create_list(:board, 2, project: project)
-
- expect(Boards::VisitsFinder).not_to receive(:new)
-
- list_boards format: :json
+ context 'when user is signed out' do
+ let(:project) { create(:project, :public) }
- expect(response).to match_response_schema('boards')
- expect(json_response.length).to eq 2
- end
+ it 'renders template' do
+ sign_out(user)
- context 'with unauthorized user' do
- before do
- expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_issue_board, project).and_return(false)
- end
+ board = create(:board, project: project)
+ create(:board_project_recent_visit, project: board.project, board: board, user: user)
- it 'returns a not found 404 response' do
- list_boards format: :json
+ list_boards
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.media_type).to eq 'application/json'
- end
+ expect(response).to render_template :index
+ expect(response.media_type).to eq 'text/html'
end
end
@@ -104,23 +93,16 @@ RSpec.describe Projects::BoardsController do
subject { list_boards }
end
- def list_boards(format: :html)
+ def list_boards
get :index, params: {
namespace_id: project.namespace,
project_id: project
- },
- format: format
+ }
end
end
describe 'GET show' do
- let!(:board) { create(:board, project: project) }
-
- it 'sets boards_endpoint instance variable to a boards path' do
- read_board board: board
-
- expect(assigns(:boards_endpoint)).to eq project_boards_path(project)
- end
+ let_it_be(:board) { create(:board, project: project) }
context 'when format is HTML' do
it 'renders template' do
@@ -146,12 +128,12 @@ RSpec.describe Projects::BoardsController do
end
context 'when user is signed out' do
- let(:project) { create(:project, :public) }
+ let(:public_board) { create(:board, project: create(:project, :public)) }
it 'does not save visit' do
sign_out(user)
- expect { read_board board: board }.to change(BoardProjectRecentVisit, :count).by(0)
+ expect { read_board board: public_board }.to change(BoardProjectRecentVisit, :count).by(0)
expect(response).to render_template :show
expect(response.media_type).to eq 'text/html'
@@ -159,48 +141,18 @@ RSpec.describe Projects::BoardsController do
end
end
- context 'when format is JSON' do
- it 'returns project board' do
- expect(Boards::Visits::CreateService).not_to receive(:new)
-
- read_board board: board, format: :json
-
- expect(response).to match_response_schema('board')
- end
-
- context 'with unauthorized user' do
- before do
- expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
- allow(Ability).to receive(:allowed?).with(user, :read_issue_board, project).and_return(false)
- end
-
- it 'returns a not found 404 response' do
- read_board board: board, format: :json
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.media_type).to eq 'application/json'
- end
- end
- end
-
context 'when board does not belong to project' do
it 'returns a not found 404 response' do
another_board = create(:board)
- read_board board: another_board
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: another_board.to_param }
expect(response).to have_gitlab_http_status(:not_found)
end
end
- def read_board(board:, format: :html)
- get :show, params: {
- namespace_id: project.namespace,
- project_id: project,
- id: board.to_param
- },
- format: format
+ def read_board(board:)
+ get :show, params: { namespace_id: board.project.namespace, project_id: board.project, id: board.to_param }
end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 6ed6f7017e3..3751b89951c 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -67,11 +67,13 @@ RSpec.describe Projects::CompareController do
from: from_ref,
to: to_ref,
w: whitespace,
- page: page
+ page: page,
+ straight: straight
}
end
let(:whitespace) { nil }
+ let(:straight) { nil }
let(:page) { nil }
context 'when the refs exist in the same project' do
@@ -142,6 +144,58 @@ RSpec.describe Projects::CompareController do
end
end
+ context 'when comparing missing commits between source and target' do
+ let(:from_project_id) { nil }
+ let(:from_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
+ let(:to_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+ let(:page) { 1 }
+
+ context 'when comparing them in the other direction' do
+ let(:straight) { "false" }
+ let(:from_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+ let(:to_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
+
+ it 'the commits are there' do
+ show_request
+
+ expect(response).to be_successful
+ expect(assigns(:commits).length).to be >= 2
+ expect(assigns(:diffs).raw_diff_files.size).to be >= 2
+ expect(assigns(:diffs).diff_files.first).to be_present
+ end
+ end
+
+ context 'with straight mode true' do
+ let(:from_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
+ let(:to_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+
+ let(:straight) { "true" }
+
+ it 'the commits are empty, but the removed lines are visible as diffs' do
+ show_request
+
+ expect(response).to be_successful
+ expect(assigns(:commits).length).to be == 0
+ expect(assigns(:diffs).diff_files.size).to be >= 4
+ end
+ end
+
+ context 'with straight mode false' do
+ let(:from_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
+ let(:to_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+
+ let(:straight) { "false" }
+
+ it 'the additional commits are not visible in diffs and commits' do
+ show_request
+
+ expect(response).to be_successful
+ expect(assigns(:commits).length).to be == 0
+ expect(assigns(:diffs).diff_files.size).to be == 0
+ end
+ end
+ end
+
context 'when the refs exist in different projects but the user cannot see' do
let(:from_project_id) { private_fork.id }
let(:from_ref) { 'improve%2Fmore-awesome' }
@@ -450,10 +504,13 @@ RSpec.describe Projects::CompareController do
project_id: project,
from: from_ref,
to: to_ref,
+ straight: straight,
format: :json
}
end
+ let(:straight) { nil }
+
context 'when the source and target refs exist' do
let(:from_ref) { 'improve%2Fawesome' }
let(:to_ref) { 'feature' }
@@ -469,10 +526,43 @@ RSpec.describe Projects::CompareController do
escaped_to_ref = Addressable::URI.unescape(to_ref)
compare_service = CompareService.new(project, escaped_to_ref)
+ compare = compare_service.execute(project, escaped_from_ref, straight: false)
+
+ expect(CompareService).to receive(:new).with(project, escaped_to_ref).and_return(compare_service)
+ expect(compare_service).to receive(:execute).with(project, escaped_from_ref, straight: false).and_return(compare)
+
+ expect(compare).to receive(:commits).and_return(CommitCollection.new(project, [signature_commit, non_signature_commit]))
+ expect(non_signature_commit).to receive(:has_signature?).and_return(false)
+ end
+
+ it 'returns only the commit with a signature' do
+ signatures_request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ signatures = json_response['signatures']
+
+ expect(signatures.size).to eq(1)
+ expect(signatures.first['commit_sha']).to eq(signature_commit.sha)
+ expect(signatures.first['html']).to be_present
+ end
+ end
+
+ context 'when the user has access to the project with straight compare' do
+ render_views
+
+ let(:signature_commit) { project.commit_by(oid: '0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
+ let(:non_signature_commit) { build(:commit, project: project, safe_message: "message", sha: 'non_signature_commit') }
+ let(:straight) { "true" }
+
+ before do
+ escaped_from_ref = Addressable::URI.unescape(from_ref)
+ escaped_to_ref = Addressable::URI.unescape(to_ref)
+
+ compare_service = CompareService.new(project, escaped_to_ref)
compare = compare_service.execute(project, escaped_from_ref)
expect(CompareService).to receive(:new).with(project, escaped_to_ref).and_return(compare_service)
- expect(compare_service).to receive(:execute).with(project, escaped_from_ref).and_return(compare)
+ expect(compare_service).to receive(:execute).with(project, escaped_from_ref, straight: true).and_return(compare)
expect(compare).to receive(:commits).and_return(CommitCollection.new(project, [signature_commit, non_signature_commit]))
expect(non_signature_commit).to receive(:has_signature?).and_return(false)
diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb
index f5dd8abd67b..034e6104f99 100644
--- a/spec/controllers/projects/cycle_analytics_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Projects::CycleAnalyticsController do
let(:target_id) { 'p_analytics_valuestream' }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :show, params: request_params, format: :html }
let(:request_params) { { namespace_id: project.namespace, project_id: project } }
diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb
index 308146ce792..fd844808d81 100644
--- a/spec/controllers/projects/deploy_keys_controller_spec.rb
+++ b/spec/controllers/projects/deploy_keys_controller_spec.rb
@@ -72,13 +72,15 @@ RSpec.describe Projects::DeployKeysController do
end
describe 'POST create' do
+ let(:deploy_key_content) { attributes_for(:deploy_key)[:key] }
+
def create_params(title = 'my-key')
{
namespace_id: project.namespace.path,
project_id: project.path,
deploy_key: {
title: title,
- key: attributes_for(:deploy_key)[:key],
+ key: deploy_key_content,
deploy_keys_projects_attributes: { '0' => { can_push: '1' } }
}
}
@@ -96,13 +98,38 @@ RSpec.describe Projects::DeployKeysController do
expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-deploy-keys-settings'))
end
- context 'when the deploy key is invalid' do
+ context 'when the deploy key has an invalid title' do
it 'shows an alert with the validations errors' do
post :create, params: create_params(nil)
expect(flash[:alert]).to eq("Title can't be blank, Deploy keys projects deploy key title can't be blank")
end
end
+
+ context 'when the deploy key is not supported SSH public key' do
+ let(:deploy_key_content) { 'bogus ssh public key' }
+
+ it 'shows an alert with a help link' do
+ post :create, params: create_params
+
+ expect(assigns(:key).errors.count).to be > 1
+ expect(flash[:alert]).to eq('Deploy Key must be a <a target="_blank" rel="noopener noreferrer" ' \
+ 'href="/help/user/ssh#supported-ssh-key-types">supported SSH public key.</a>')
+ end
+ end
+
+ context 'when the deploy key already exists' do
+ before do
+ create(:deploy_key, title: 'my-key', key: deploy_key_content, projects: [project])
+ end
+
+ it 'shows an alert with the validations errors' do
+ post :create, params: create_params
+
+ expect(flash[:alert]).to eq("Fingerprint sha256 has already been taken, " \
+ "Deploy keys projects deploy key fingerprint sha256 has already been taken")
+ end
+ end
end
describe '/enable/:id' do
diff --git a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
index 55ab0f0eefa..2d39e0e5317 100644
--- a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
+++ b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
@@ -132,7 +132,7 @@ RSpec.describe Projects::DesignManagement::Designs::RawImagesController do
subject
expect(response.header['ETag']).to be_present
- expect(response.header['Cache-Control']).to eq("max-age=60, private")
+ expect(response.header['Cache-Control']).to eq("max-age=60, private, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60")
end
end
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index 9227c7dd70a..3dfc22927cf 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe Projects::GraphsController do
let(:target_id) { 'p_analytics_repo' }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject do
sign_in(user)
get :charts, params: request_params, format: :html
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index c48be8efb1b..0c3795540e0 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -1107,6 +1107,46 @@ RSpec.describe Projects::IssuesController do
end
end
+ context 'when create service return an unrecoverable error with http_status' do
+ let(:http_status) { 403 }
+
+ before do
+ allow_next_instance_of(::Issues::CreateService) do |create_service|
+ allow(create_service).to receive(:execute).and_return(
+ ServiceResponse.error(message: 'unrecoverable error', http_status: http_status)
+ )
+ end
+ end
+
+ it 'renders 403 and logs the error' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Cannot create issue',
+ errors: ['unrecoverable error'],
+ http_status: http_status
+ )
+
+ post_new_issue
+
+ expect(response).to have_gitlab_http_status :forbidden
+ end
+
+ context 'when no render method is found for the returned http_status' do
+ let(:http_status) { nil }
+
+ it 'renders 404 and logs the error' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Cannot create issue',
+ errors: ['unrecoverable error'],
+ http_status: http_status
+ )
+
+ post_new_issue
+
+ expect(response).to have_gitlab_http_status :not_found
+ end
+ end
+ end
+
it 'creates the issue successfully', :aggregate_failures do
issue = post_new_issue
@@ -1661,13 +1701,27 @@ RSpec.describe Projects::IssuesController do
end
it 'allows CSV export' do
- expect(IssuableExportCsvWorker).to receive(:perform_async).with(:issue, viewer.id, project.id, anything)
+ expect(IssuableExportCsvWorker).to receive(:perform_async)
+ .with(:issue, viewer.id, project.id, hash_including('issue_types' => Issue::TYPES_FOR_LIST))
request_csv
expect(response).to redirect_to(project_issues_path(project))
expect(controller).to set_flash[:notice].to match(/\AYour CSV export has started/i)
end
+
+ context 'when work_items is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not include tasks in CSV export' do
+ expect(IssuableExportCsvWorker).to receive(:perform_async)
+ .with(:issue, viewer.id, project.id, hash_including('issue_types' => Issue::TYPES_FOR_LIST.excluding('task')))
+
+ request_csv
+ end
+ end
end
context 'when not logged in' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 9c4baeae836..a41abd8c16d 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -77,7 +77,8 @@ RSpec.describe Projects::MergeRequestsController do
merge_request,
'json',
diff_head: true,
- view: 'inline'))
+ view: 'inline',
+ w: '0'))
end
context 'when diff files were cleaned' do
@@ -498,7 +499,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when a squash commit message is passed' do
let(:message) { 'My custom squash commit message' }
- it 'passes the same message to SquashService', :sidekiq_might_not_need_inline do
+ it 'passes the same message to SquashService', :sidekiq_inline do
params = { squash: '1',
squash_commit_message: message,
sha: merge_request.diff_head_sha }
@@ -790,7 +791,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'with private builds' do
context 'for the target project member' do
- it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do
+ it 'does not respond with serialized pipelines' do
expect(json_response['pipelines']).to be_empty
expect(json_response['count']['all']).to eq(0)
expect(response).to include_pagination_headers
@@ -800,7 +801,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'for the source project member' do
let(:user) { fork_user }
- it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do
+ it 'responds with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@@ -816,7 +817,7 @@ RSpec.describe Projects::MergeRequestsController do
end
context 'for the target project member' do
- it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do
+ it 'does not respond with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@@ -826,7 +827,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'for the source project member' do
let(:user) { fork_user }
- it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do
+ it 'responds with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@@ -1855,13 +1856,13 @@ RSpec.describe Projects::MergeRequestsController do
create(:merge_request, source_project: forked, target_project: project, target_branch: 'master', head_pipeline: pipeline)
end
- it 'links to the environment on that project', :sidekiq_might_not_need_inline do
+ it 'links to the environment on that project' do
get_ci_environments_status
expect(json_response.first['url']).to match(/#{forked.full_path}/)
end
- context "when environment_target is 'merge_commit'", :sidekiq_might_not_need_inline do
+ context "when environment_target is 'merge_commit'" do
it 'returns nothing' do
get_ci_environments_status(environment_target: 'merge_commit')
@@ -1891,13 +1892,13 @@ RSpec.describe Projects::MergeRequestsController do
# we're trying to reduce the overall number of queries for this method.
# set a hard limit for now. https://gitlab.com/gitlab-org/gitlab-foss/issues/52287
- it 'keeps queries in check', :sidekiq_might_not_need_inline do
+ it 'keeps queries in check' do
control_count = ActiveRecord::QueryRecorder.new { get_ci_environments_status }.count
expect(control_count).to be <= 137
end
- it 'has no N+1 SQL issues for environments', :request_store, :sidekiq_might_not_need_inline, retry: 0 do
+ it 'has no N+1 SQL issues for environments', :request_store, retry: 0 do
# First run to insert test data from lets, which does take up some 30 queries
get_ci_environments_status
@@ -2144,7 +2145,7 @@ RSpec.describe Projects::MergeRequestsController do
sign_in(fork_owner)
end
- it 'returns 200', :sidekiq_might_not_need_inline do
+ it 'returns 200' do
expect_rebase_worker_for(fork_owner)
post_rebase
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index b62353784b3..28da7eff8fc 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -44,6 +44,26 @@ RSpec.describe Projects::MilestonesController do
end
end
+ describe "#create" do
+ it 'does not redirect without redirect_path' do
+ post :create, params: { namespace_id: project.namespace.id, project_id: project.id, milestone: { title: 'test' } }
+
+ expect(response).to redirect_to(project_milestone_path(project, project.milestones.last))
+ end
+
+ it 'redirects when given a redirect_path' do
+ post :create, params: { namespace_id: project.namespace.id, project_id: project.id, redirect_path: 'new_release', milestone: { title: 'test' } }
+
+ expect(response).to redirect_to(new_project_release_path(project))
+ end
+
+ it 'will not redirect when given a redirect_path with an error' do
+ post :create, params: { namespace_id: project.namespace.id, project_id: project.id, redirect_path: 'new_release', milestone: { title: nil } }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
describe "#index" do
context "as html" do
def render_index(project:, page:, search_title: '')
diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb
index 691508d1e14..b29bbef0c40 100644
--- a/spec/controllers/projects/pages_domains_controller_spec.rb
+++ b/spec/controllers/projects/pages_domains_controller_spec.rb
@@ -63,9 +63,15 @@ RSpec.describe Projects::PagesDomainsController do
describe 'POST create' do
it "creates a new pages domain" do
- expect do
- post(:create, params: request_params.merge(pages_domain: pages_domain_params))
- end.to change { PagesDomain.count }.by(1)
+ expect { post(:create, params: request_params.merge(pages_domain: pages_domain_params)) }
+ .to change { PagesDomain.count }.by(1)
+ .and publish_event(PagesDomains::PagesDomainCreatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain_params[:domain]
+ )
created_domain = PagesDomain.reorder(:id).last
@@ -106,6 +112,17 @@ RSpec.describe Projects::PagesDomainsController do
end.to change { pages_domain.reload.certificate }.to(pages_domain_params[:user_provided_certificate])
end
+ it 'publishes PagesDomainUpdatedEvent event' do
+ expect { patch(:update, params: params) }
+ .to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain.domain
+ )
+ end
+
it 'redirects to the project page' do
patch(:update, params: params)
@@ -134,6 +151,11 @@ RSpec.describe Projects::PagesDomainsController do
expect(response).to render_template('show')
end
+
+ it 'does not publish PagesDomainUpdatedEvent event' do
+ expect { patch(:update, params: params) }
+ .to not_publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ end
end
context 'when parameters include the domain' do
@@ -197,9 +219,15 @@ RSpec.describe Projects::PagesDomainsController do
describe 'DELETE destroy' do
it "deletes the pages domain" do
- expect do
- delete(:destroy, params: request_params.merge(id: pages_domain.domain))
- end.to change { PagesDomain.count }.by(-1)
+ expect { delete(:destroy, params: request_params.merge(id: pages_domain.domain)) }
+ .to change(PagesDomain, :count).by(-1)
+ .and publish_event(PagesDomains::PagesDomainDeletedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain.domain
+ )
expect(response).to redirect_to(project_pages_path(project))
end
@@ -216,6 +244,17 @@ RSpec.describe Projects::PagesDomainsController do
expect(response).to redirect_to(project_pages_domain_path(project, pages_domain))
end
+ it 'publishes PagesDomainUpdatedEvent event' do
+ expect { subject }
+ .to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain.domain
+ )
+ end
+
it 'removes certificate' do
expect do
subject
@@ -245,6 +284,11 @@ RSpec.describe Projects::PagesDomainsController do
expect(pages_domain.key).to be_present
end
+ it 'does not publish PagesDomainUpdatedEvent event' do
+ expect { subject }
+ .to not_publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ end
+
it 'redirects to show page with a flash message' do
subject
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index b9acaf65892..6e2de0c4d57 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -859,7 +859,7 @@ RSpec.describe Projects::PipelinesController do
let(:target_id) { ['p_analytics_pipelines', tab[:event]] }
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :charts, params: request_params, format: :html }
let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
diff --git a/spec/controllers/projects/prometheus/metrics_controller_spec.rb b/spec/controllers/projects/prometheus/metrics_controller_spec.rb
index cd195b95100..327651b2058 100644
--- a/spec/controllers/projects/prometheus/metrics_controller_spec.rb
+++ b/spec/controllers/projects/prometheus/metrics_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::Prometheus::MetricsController do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:prometheus_project) }
+ let_it_be(:project) { create(:project, :with_prometheus_integration) }
let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) }
diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb
index 4996bd90005..14728618633 100644
--- a/spec/controllers/projects/protected_branches_controller_spec.rb
+++ b/spec/controllers/projects/protected_branches_controller_spec.rb
@@ -4,26 +4,23 @@ require('spec_helper')
RSpec.describe Projects::ProtectedBranchesController do
let_it_be_with_reload(:project) { create(:project, :repository) }
- let_it_be(:maintainer) { create(:user) }
+ let_it_be_with_reload(:empty_project) { create(:project, :empty_repo) }
+ let_it_be(:maintainer) { create(:user, maintainer_projects: [project, empty_project]) }
let(:protected_branch) { create(:protected_branch, project: project) }
let(:project_params) { { namespace_id: project.namespace.to_param, project_id: project } }
let(:base_params) { project_params.merge(id: protected_branch.id) }
let(:user) { maintainer }
- before_all do
- project.add_maintainer(maintainer)
- end
-
before do
sign_in(user)
end
describe "GET #index" do
- let(:project) { create(:project_empty_repo, :public) }
+ it 'redirects to repository settings' do
+ get(:index, params: { namespace_id: empty_project.namespace.to_param, project_id: empty_project })
- it "redirects empty repo to projects page" do
- get(:index, params: { namespace_id: project.namespace.to_param, project_id: project })
+ expect(response).to redirect_to(project_settings_repository_path(empty_project))
end
end
@@ -42,6 +39,18 @@ RSpec.describe Projects::ProtectedBranchesController do
end.to change(ProtectedBranch, :count).by(1)
end
+ context 'when repository is empty' do
+ let(:project) { empty_project }
+
+ it 'creates the protected branch rule' do
+ expect do
+ post(:create, params: project_params.merge(protected_branch: create_params))
+ end.to change(ProtectedBranch, :count).by(1)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
context 'when a policy restricts rule creation' do
it "prevents creation of the protected branch rule" do
disallow(:create_protected_branch, an_instance_of(ProtectedBranch))
@@ -63,6 +72,17 @@ RSpec.describe Projects::ProtectedBranchesController do
expect(json_response["name"]).to eq('new_name')
end
+ context 'when repository is empty' do
+ let(:project) { empty_project }
+
+ it 'updates the protected branch rule' do
+ put(:update, params: base_params.merge(protected_branch: update_params))
+
+ expect(protected_branch.reload.name).to eq('new_name')
+ expect(json_response["name"]).to eq('new_name')
+ end
+ end
+
context 'when a policy restricts rule update' do
it "prevents update of the protected branch rule" do
disallow(:update_protected_branch, protected_branch)
@@ -83,6 +103,16 @@ RSpec.describe Projects::ProtectedBranchesController do
expect { ProtectedBranch.find(protected_branch.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
+ context 'when repository is empty' do
+ let(:project) { empty_project }
+
+ it 'deletes the protected branch rule' do
+ delete(:destroy, params: base_params)
+
+ expect { ProtectedBranch.find(protected_branch.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
context 'when a policy restricts rule deletion' do
it "prevents deletion of the protected branch rule" do
disallow(:destroy_protected_branch, protected_branch)
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index e0d88fa799f..1c9aafacbd9 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -247,9 +247,11 @@ RSpec.describe Projects::RawController do
sign_in create(:user)
request_file
- expect(response.cache_control[:public]).to eq(true)
- expect(response.cache_control[:max_age]).to eq(60)
+ expect(response.headers['ETag']).to eq("\"bdd5aa537c1e1f6d1b66de4bac8a6132\"")
expect(response.cache_control[:no_store]).to be_nil
+ expect(response.header['Cache-Control']).to eq(
+ 'max-age=60, public, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60'
+ )
end
context 'when a public project has private repo' do
@@ -260,7 +262,9 @@ RSpec.describe Projects::RawController do
sign_in user
request_file
- expect(response.header['Cache-Control']).to include('max-age=60, private')
+ expect(response.header['Cache-Control']).to eq(
+ 'max-age=60, private, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60'
+ )
end
end
@@ -274,6 +278,21 @@ RSpec.describe Projects::RawController do
expect(response).to have_gitlab_http_status(:not_modified)
end
end
+
+ context 'when improve_blobs_cache_headers disabled' do
+ before do
+ stub_feature_flags(improve_blobs_cache_headers: false)
+ end
+
+ it 'uses weak etags with a restricted set of headers' do
+ sign_in create(:user)
+ request_file
+
+ expect(response.headers['ETag']).to eq("W/\"bdd5aa537c1e1f6d1b66de4bac8a6132\"")
+ expect(response.cache_control[:no_store]).to be_nil
+ expect(response.header['Cache-Control']).to eq('max-age=60, public')
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index b30610d98d7..b5797e374f3 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -231,7 +231,7 @@ RSpec.describe ProjectsController do
end
context "project with broken repo" do
- let_it_be(:empty_project) { create(:project_broken_repo, :public) }
+ let_it_be(:empty_project) { create(:project, :public) }
before do
sign_in(user)
@@ -246,8 +246,6 @@ RSpec.describe ProjectsController do
end
it "renders the empty project view" do
- allow(Project).to receive(:repo).and_raise(Gitlab::Git::Repository::NoRepository)
-
expect(response).to render_template('projects/no_repo')
end
end
@@ -299,14 +297,16 @@ RSpec.describe ProjectsController do
end
it "renders files even with invalid license" do
+ invalid_license = ::Gitlab::Git::DeclaredLicense.new(key: 'woozle', name: 'woozle wuzzle')
+
controller.instance_variable_set(:@project, public_project)
- expect(public_project.repository).to receive(:license_key).and_return('woozle wuzzle').at_least(:once)
+ expect(public_project.repository).to receive(:license).and_return(invalid_license).at_least(:once)
get_show
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template('_files')
- expect(response.body).to have_content('LICENSE') # would be 'MIT license' if stub not works
+ expect(response.body).to have_content('woozle wuzzle')
end
describe 'tracking events', :snowplow do
@@ -1233,26 +1233,6 @@ RSpec.describe ProjectsController do
get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
end
- context 'when use_gitaly_pagination_for_refs is disabled' do
- before do
- stub_feature_flags(use_gitaly_pagination_for_refs: false)
- end
-
- it 'does not use gitaly pagination' do
- expected_params = ActionController::Parameters.new(ref: '123456', per_page: 100).permit!
-
- expect_next_instance_of(BranchesFinder, project.repository, expected_params) do |finder|
- expect(finder).to receive(:execute).with(gitaly_pagination: false).and_call_original
- end
-
- expect_next_instance_of(TagsFinder, project.repository, expected_params) do |finder|
- expect(finder).to receive(:execute).with(gitaly_pagination: false).and_call_original
- end
-
- get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
- end
- end
-
context 'when gitaly is unavailable' do
before do
expect_next_instance_of(TagsFinder) do |finder|
diff --git a/spec/controllers/registrations/welcome_controller_spec.rb b/spec/controllers/registrations/welcome_controller_spec.rb
index 14e88d469ba..a3b246fbedd 100644
--- a/spec/controllers/registrations/welcome_controller_spec.rb
+++ b/spec/controllers/registrations/welcome_controller_spec.rb
@@ -31,7 +31,6 @@ RSpec.describe Registrations::WelcomeController do
context 'when role and setup_for_company is set' do
before do
- stub_feature_flags(about_your_company_registration_flow: false)
user.update!(setup_for_company: false)
sign_in(user)
end
@@ -61,10 +60,6 @@ RSpec.describe Registrations::WelcomeController do
end
describe '#update' do
- before do
- stub_feature_flags(about_your_company_registration_flow: false)
- end
-
subject(:update) do
patch :update, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 4131bd148da..7ab66b04a6e 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -218,7 +218,7 @@ RSpec.describe SearchController do
end
end
- it_behaves_like 'Snowplow event tracking' do
+ it_behaves_like 'Snowplow event tracking with RedisHLL context' do
subject { get :show, params: { group_id: namespace.id, scope: 'blobs', search: 'term' } }
let(:project) { nil }
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 0e0770fb94c..80cf060bc45 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -399,18 +399,30 @@ RSpec.describe SessionsController do
end
context 'when OTP is invalid' do
- before do
- authenticate_2fa(otp_attempt: 'invalid')
- end
+ let(:code) { 'invalid' }
it 'does not authenticate' do
+ authenticate_2fa(otp_attempt: code)
+
expect(subject.current_user).not_to eq user
end
it 'warns about invalid OTP code' do
+ authenticate_2fa(otp_attempt: code)
+
expect(controller).to set_flash.now[:alert]
.to(/Invalid two-factor code/)
end
+
+ it 'sends an email to the user informing about the attempt to sign in with a wrong OTP code' do
+ controller.request.remote_addr = '1.2.3.4'
+
+ expect_next_instance_of(NotificationService) do |instance|
+ expect(instance).to receive(:two_factor_otp_attempt_failed).with(user, '1.2.3.4')
+ end
+
+ authenticate_2fa(otp_attempt: code)
+ end
end
end
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
index c27e58634f6..e128db8d1c1 100644
--- a/spec/controllers/uploads_controller_spec.rb
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -216,7 +216,7 @@ RSpec.describe UploadsController do
end
context 'for PDF files' do
- let(:filename) { 'git-cheat-sheet.pdf' }
+ let(:filename) { 'sample.pdf' }
let(:expected_disposition) { 'inline;' }
let(:note) { create(:note, :with_pdf_attachment, project: project) }
diff --git a/spec/factories/bulk_import/entities.rb b/spec/factories/bulk_import/entities.rb
index cf31ffec4f6..eeb4f8325ae 100644
--- a/spec/factories/bulk_import/entities.rb
+++ b/spec/factories/bulk_import/entities.rb
@@ -9,6 +9,7 @@ FactoryBot.define do
sequence(:destination_namespace) { |n| "destination-path-#{n}" }
destination_name { 'Imported Entity' }
+ sequence(:source_xid)
trait(:group_entity) do
source_type { :group_entity }
diff --git a/spec/factories/ci/build_metadata.rb b/spec/factories/ci/build_metadata.rb
index cfc86c4ef4b..a0a5305ef39 100644
--- a/spec/factories/ci/build_metadata.rb
+++ b/spec/factories/ci/build_metadata.rb
@@ -3,5 +3,9 @@
FactoryBot.define do
factory :ci_build_metadata, class: 'Ci::BuildMetadata' do
build { association(:ci_build, strategy: :build, metadata: instance) }
+
+ after(:build) do |metadata|
+ metadata.build&.valid?
+ end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 8c2edc8cd9f..9a3b2837ab8 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -424,79 +424,79 @@ FactoryBot.define do
trait :codequality_report do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :codequality, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :codequality, job: build)
end
end
trait :sast_report do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :sast, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :sast, job: build)
end
end
trait :secret_detection_report do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :secret_detection, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :secret_detection, job: build)
end
end
trait :test_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :junit, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :junit, job: build)
end
end
trait :test_reports_with_attachment do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :junit_with_attachment, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :junit_with_attachment, job: build)
end
end
trait :broken_test_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :junit_with_corrupted_data, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :junit_with_corrupted_data, job: build)
end
end
trait :test_reports_with_duplicate_failed_test_names do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :junit_with_duplicate_failed_test_names, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :junit_with_duplicate_failed_test_names, job: build)
end
end
trait :test_reports_with_three_failures do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :junit_with_three_failures, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :junit_with_three_failures, job: build)
end
end
trait :accessibility_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :accessibility, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :accessibility, job: build)
end
end
trait :coverage_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :cobertura, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :cobertura, job: build)
end
end
trait :codequality_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :codequality, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :codequality, job: build)
end
end
trait :codequality_reports_without_degradation do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :codequality_without_errors, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :codequality_without_errors, job: build)
end
end
trait :terraform_reports do
after(:build) do |build|
- build.job_artifacts << create(:ci_job_artifact, :terraform, job: build)
+ build.job_artifacts << build(:ci_job_artifact, :terraform, job: build)
end
end
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index f8b964cf8e0..304d77e8521 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -352,6 +352,18 @@ FactoryBot.define do
end
end
+ # Equivalent Semgrep report for combined :sast_bandit and :sast_gosec reports.
+ # This report includes signature tracking.
+ trait :sast_semgrep_for_multiple_findings do
+ file_type { :sast }
+ file_format { :raw }
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-multiple-findings.json'), 'application/json')
+ end
+ end
+
trait :common_security_report do
file_format { :raw }
file_type { :dependency_scanning }
@@ -381,16 +393,6 @@ FactoryBot.define do
end
end
- trait :sast_deprecated do
- file_type { :sast }
- file_format { :raw }
-
- after(:build) do |artifact, _|
- artifact.file = fixture_file_upload(
- Rails.root.join('spec/fixtures/security_reports/deprecated/gl-sast-report.json'), 'application/json')
- end
- end
-
trait :sast_with_corrupted_data do
file_type { :sast }
file_format { :raw }
diff --git a/spec/factories/ci/pipeline_artifacts.rb b/spec/factories/ci/pipeline_artifacts.rb
index d096f149c3a..bdd390126dd 100644
--- a/spec/factories/ci/pipeline_artifacts.rb
+++ b/spec/factories/ci/pipeline_artifacts.rb
@@ -17,6 +17,11 @@ FactoryBot.define do
association :pipeline, :unlocked, factory: :ci_pipeline
end
+ trait :artifact_unlocked do
+ association :pipeline, :unlocked, factory: :ci_pipeline
+ locked { :unlocked }
+ end
+
trait :checksummed do
verification_checksum { 'abc' }
end
diff --git a/spec/factories/ci/pipeline_metadata.rb b/spec/factories/ci/pipeline_metadata.rb
new file mode 100644
index 00000000000..600cfaa92c6
--- /dev/null
+++ b/spec/factories/ci/pipeline_metadata.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_pipeline_metadata, class: 'Ci::PipelineMetadata' do
+ title { 'Pipeline title' }
+
+ pipeline factory: :ci_empty_pipeline
+ project
+ end
+end
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index d6b1da1d5c2..650b8647237 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -8,6 +8,7 @@ FactoryBot.define do
sha { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
status { 'pending' }
add_attribute(:protected) { false }
+ partition_id { 1234 }
project
@@ -18,6 +19,8 @@ FactoryBot.define do
transient { child_of { nil } }
transient { upstream_of { nil } }
+ transient { title { nil } }
+
after(:build) do |pipeline, evaluator|
if evaluator.child_of
pipeline.project = evaluator.child_of.project
@@ -25,6 +28,10 @@ FactoryBot.define do
end
pipeline.ensure_project_iid!
+
+ if evaluator.title
+ pipeline.pipeline_metadata = build(:ci_pipeline_metadata, title: evaluator.title, project: pipeline.project, pipeline: pipeline)
+ end
end
after(:create) do |pipeline, evaluator|
@@ -47,6 +54,7 @@ FactoryBot.define do
end
factory :ci_pipeline do
+ partition_id { 1234 }
transient { ci_ref_presence { true } }
before(:create) do |pipeline, evaluator|
diff --git a/spec/factories/ci/reports/sbom/components.rb b/spec/factories/ci/reports/sbom/components.rb
index 317e1c863cf..fd9b4386130 100644
--- a/spec/factories/ci/reports/sbom/components.rb
+++ b/spec/factories/ci/reports/sbom/components.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :ci_reports_sbom_component, class: '::Gitlab::Ci::Reports::Sbom::Component' do
- type { :library }
+ type { "library" }
sequence(:name) { |n| "component-#{n}" }
sequence(:version) { |n| "v0.0.#{n}" }
diff --git a/spec/factories/ci/reports/sbom/reports.rb b/spec/factories/ci/reports/sbom/reports.rb
new file mode 100644
index 00000000000..4a83b5898ef
--- /dev/null
+++ b/spec/factories/ci/reports/sbom/reports.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_reports_sbom_report, class: '::Gitlab::Ci::Reports::Sbom::Report' do
+ transient do
+ num_components { 5 }
+ components { build_list :ci_reports_sbom_component, num_components }
+ source { association :ci_reports_sbom_source }
+ end
+
+ after(:build) do |report, options|
+ options.components.each { |component| report.add_component(component) }
+ report.set_source(options.source)
+ end
+
+ skip_create
+ end
+end
diff --git a/spec/factories/ci/reports/sbom/sources.rb b/spec/factories/ci/reports/sbom/sources.rb
index 9093aba86a6..688c0250b5f 100644
--- a/spec/factories/ci/reports/sbom/sources.rb
+++ b/spec/factories/ci/reports/sbom/sources.rb
@@ -19,15 +19,12 @@ FactoryBot.define do
}
end
- fingerprint { Digest::SHA256.hexdigest(data.to_json) }
-
skip_create
initialize_with do
::Gitlab::Ci::Reports::Sbom::Source.new(
type: type,
- data: data,
- fingerprint: fingerprint
+ data: data
)
end
end
diff --git a/spec/factories/customer_relations/contacts.rb b/spec/factories/customer_relations/contacts.rb
index 821c45d7514..1896510d362 100644
--- a/spec/factories/customer_relations/contacts.rb
+++ b/spec/factories/customer_relations/contacts.rb
@@ -11,5 +11,9 @@ FactoryBot.define do
trait :with_organization do
organization
end
+
+ trait :inactive do
+ state { :inactive }
+ end
end
end
diff --git a/spec/factories/events.rb b/spec/factories/events.rb
index 403165a3935..a4f06a48621 100644
--- a/spec/factories/events.rb
+++ b/spec/factories/events.rb
@@ -26,10 +26,10 @@ FactoryBot.define do
factory :wiki_page_event do
action { :created }
- # rubocop: disable FactoryBot/InlineAssociation
+ # rubocop: disable RSpec/FactoryBot/InlineAssociation
# A persistent project is needed to have a wiki page being created properly.
project { @overrides[:wiki_page]&.container || create(:project, :wiki_repo) }
- # rubocop: enable FactoryBot/InlineAssociation
+ # rubocop: enable RSpec/FactoryBot/InlineAssociation
target { association(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
transient do
@@ -54,6 +54,16 @@ FactoryBot.define do
target { note }
end
+ trait :for_issue do
+ target { association(:issue, issue_type: :issue) }
+ target_type { 'Issue' }
+ end
+
+ trait :for_work_item do
+ target { association(:work_item, :task) }
+ target_type { 'WorkItem' }
+ end
+
factory :design_event, traits: [:has_design] do
action { :created }
target { design }
diff --git a/spec/factories/git_wiki_commit_details.rb b/spec/factories/git_wiki_commit_details.rb
deleted file mode 100644
index fb3f2954b12..00000000000
--- a/spec/factories/git_wiki_commit_details.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :git_wiki_commit_details, class: 'Gitlab::Git::Wiki::CommitDetails' do
- skip_create
-
- transient do
- author { association(:user) }
- end
-
- sequence(:message) { |n| "Commit message #{n}" }
-
- initialize_with { new(author.id, author.username, author.name, author.email, message) }
- end
-end
diff --git a/spec/factories/go_module_commits.rb b/spec/factories/go_module_commits.rb
index 4f86d38954c..44f4ce9ea31 100644
--- a/spec/factories/go_module_commits.rb
+++ b/spec/factories/go_module_commits.rb
@@ -7,12 +7,12 @@ FactoryBot.define do
transient do
files { { 'foo.txt' => 'content' } }
message { 'Message' }
- # rubocop: disable FactoryBot/InlineAssociation
+ # rubocop: disable RSpec/FactoryBot/InlineAssociation
# We need a persisted project so we can create commits and tags
# in `commit` otherwise linting this factory with `build` strategy
# will fail.
project { create(:project, :repository) }
- # rubocop: enable FactoryBot/InlineAssociation
+ # rubocop: enable RSpec/FactoryBot/InlineAssociation
service do
Files::MultiService.new(
diff --git a/spec/factories/incident_management/timeline_event_tag_links.rb b/spec/factories/incident_management/timeline_event_tag_links.rb
new file mode 100644
index 00000000000..883aca29f99
--- /dev/null
+++ b/spec/factories/incident_management/timeline_event_tag_links.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :incident_management_timeline_event_tag_link, class: 'IncidentManagement::TimelineEventTagLink' do
+ association :timeline_event_tag, factory: :incident_management_timeline_event_tag
+ association :timeline_event, factory: :incident_management_timeline_event
+ end
+end
diff --git a/spec/factories/incident_management/timeline_event_tags.rb b/spec/factories/incident_management/timeline_event_tags.rb
new file mode 100644
index 00000000000..6333872ee4f
--- /dev/null
+++ b/spec/factories/incident_management/timeline_event_tags.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :incident_management_timeline_event_tag, class: 'IncidentManagement::TimelineEventTag' do
+ project
+ name { 'Start time' }
+ end
+end
diff --git a/spec/factories/ml/candidate_metrics.rb b/spec/factories/ml/candidate_metrics.rb
new file mode 100644
index 00000000000..28e3974d39f
--- /dev/null
+++ b/spec/factories/ml/candidate_metrics.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ml_candidate_metrics, class: '::Ml::CandidateMetric' do
+ association :candidate, factory: :ml_candidates
+
+ sequence(:name) { |n| "metric#{n}" }
+ value { 2.0 }
+ step { 1 }
+ tracked_at { 1234 }
+ end
+end
diff --git a/spec/factories/ml/candidate_params.rb b/spec/factories/ml/candidate_params.rb
new file mode 100644
index 00000000000..73cb0c54089
--- /dev/null
+++ b/spec/factories/ml/candidate_params.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ml_candidate_params, class: '::Ml::CandidateParam' do
+ association :candidate, factory: :ml_candidates
+
+ sequence(:name) { |n| "metric#{n}" }
+ sequence(:value) { |n| "value#{n}" }
+ end
+end
diff --git a/spec/factories/ml/candidates.rb b/spec/factories/ml/candidates.rb
index b5644ee3841..4fbcdc46103 100644
--- a/spec/factories/ml/candidates.rb
+++ b/spec/factories/ml/candidates.rb
@@ -3,5 +3,12 @@ FactoryBot.define do
factory :ml_candidates, class: '::Ml::Candidate' do
association :experiment, factory: :ml_experiments
association :user
+
+ trait :with_metrics_and_params do
+ after(:create) do |candidate|
+ candidate.metrics = FactoryBot.create_list(:ml_candidate_metrics, 2, candidate: candidate )
+ candidate.params = FactoryBot.create_list(:ml_candidate_params, 2, candidate: candidate )
+ end
+ end
end
end
diff --git a/spec/factories/ml/experiments.rb b/spec/factories/ml/experiments.rb
index 043ca712e60..e4f5a0da6cf 100644
--- a/spec/factories/ml/experiments.rb
+++ b/spec/factories/ml/experiments.rb
@@ -2,7 +2,8 @@
FactoryBot.define do
factory :ml_experiments, class: '::Ml::Experiment' do
sequence(:name) { |n| "experiment#{n}" }
- association :project
- association :user
+
+ project
+ user
end
end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 2159f5b2dc1..530b4616765 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -184,7 +184,7 @@ FactoryBot.define do
end
trait :with_pdf_attachment do
- attachment { fixture_file_upload("spec/fixtures/git-cheat-sheet.pdf", "application/pdf") }
+ attachment { fixture_file_upload("spec/fixtures/sample.pdf", "application/pdf") }
end
trait :confidential do
diff --git a/spec/factories/packages/packages.rb b/spec/factories/packages/packages.rb
index 8074e505243..1da4f0cedbc 100644
--- a/spec/factories/packages/packages.rb
+++ b/spec/factories/packages/packages.rb
@@ -253,7 +253,7 @@ FactoryBot.define do
end
trait(:without_loaded_metadatum) do
- conan_metadatum { build(:conan_metadatum, package: nil) } # rubocop:disable FactoryBot/InlineAssociation
+ conan_metadatum { build(:conan_metadatum, package: nil) } # rubocop:disable RSpec/FactoryBot/InlineAssociation
end
end
diff --git a/spec/factories/packages/rpm/rpm_repository_files.rb b/spec/factories/packages/rpm/rpm_repository_files.rb
new file mode 100644
index 00000000000..079d32b3995
--- /dev/null
+++ b/spec/factories/packages/rpm/rpm_repository_files.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :rpm_repository_file, class: 'Packages::Rpm::RepositoryFile' do
+ project
+
+ file_name { 'repomd.xml' }
+ file_sha1 { 'efae869b4e95d54796a46481f3a211d6a88d0323' }
+ file_md5 { 'ddf8a75330c896a8d7709e75f8b5982a' }
+ size { 3127.kilobytes }
+ status { :default }
+
+ transient do
+ file_metadatum_trait { :xml }
+ end
+
+ transient do
+ file_fixture { 'spec/fixtures/packages/rpm/repodata/repomd.xml' }
+ end
+
+ after(:build) do |package_file, evaluator|
+ package_file.file = fixture_file_upload(evaluator.file_fixture)
+ end
+
+ trait(:object_storage) do
+ file_store { Packages::Rpm::RepositoryFileUploader::Store::REMOTE }
+ end
+
+ trait :pending_destruction do
+ status { :pending_destruction }
+ end
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 93ed68a4573..b62995dce42 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -54,7 +54,8 @@ FactoryBot.define do
import_last_error { nil }
forward_deployment_enabled { nil }
restrict_user_defined_variables { nil }
- ci_job_token_scope_enabled { nil }
+ ci_outbound_job_token_scope_enabled { nil }
+ ci_inbound_job_token_scope_enabled { nil }
runner_token_expiration_interval { nil }
runner_token_expiration_interval_human_readable { nil }
end
@@ -112,7 +113,8 @@ FactoryBot.define do
project.merge_trains_enabled = evaluator.merge_trains_enabled unless evaluator.merge_trains_enabled.nil?
project.keep_latest_artifact = evaluator.keep_latest_artifact unless evaluator.keep_latest_artifact.nil?
project.restrict_user_defined_variables = evaluator.restrict_user_defined_variables unless evaluator.restrict_user_defined_variables.nil?
- project.ci_job_token_scope_enabled = evaluator.ci_job_token_scope_enabled unless evaluator.ci_job_token_scope_enabled.nil?
+ project.ci_outbound_job_token_scope_enabled = evaluator.ci_outbound_job_token_scope_enabled unless evaluator.ci_outbound_job_token_scope_enabled.nil?
+ project.ci_inbound_job_token_scope_enabled = evaluator.ci_inbound_job_token_scope_enabled unless evaluator.ci_inbound_job_token_scope_enabled.nil?
project.runner_token_expiration_interval = evaluator.runner_token_expiration_interval unless evaluator.runner_token_expiration_interval.nil?
project.runner_token_expiration_interval_human_readable = evaluator.runner_token_expiration_interval_human_readable unless evaluator.runner_token_expiration_interval_human_readable.nil?
@@ -330,12 +332,6 @@ FactoryBot.define do
repository_read_only { true }
end
- trait :broken_repo do
- after(:create) do |project|
- TestEnv.rm_storage_dir(project.repository_storage, "#{project.disk_path}.git/refs")
- end
- end
-
trait :test_repo do
after :create do |project|
# There are various tests that rely on there being no repository cache.
@@ -427,12 +423,24 @@ FactoryBot.define do
error_tracking_setting { association :project_error_tracking_setting }
end
+ trait :with_redmine_integration do
+ has_external_issue_tracker { true }
+
+ redmine_integration
+ end
+
trait :with_jira_integration do
has_external_issue_tracker { true }
jira_integration
end
+ trait :with_prometheus_integration do
+ after :create do |project|
+ create(:prometheus_integration, project: project)
+ end
+ end
+
# Project with empty repository
#
# This is a case when you just created a project
@@ -441,13 +449,6 @@ FactoryBot.define do
empty_repo
end
- # Project with broken repository
- #
- # Project with an invalid repository state
- factory :project_broken_repo, parent: :project do
- broken_repo
- end
-
factory :forked_project_with_submodules, parent: :project do
path { 'forked-gitlabhq' }
@@ -459,42 +460,6 @@ FactoryBot.define do
end
end
- factory :redmine_project, parent: :project do
- has_external_issue_tracker { true }
-
- redmine_integration
- end
-
- factory :youtrack_project, parent: :project do
- has_external_issue_tracker { true }
-
- youtrack_integration
- end
-
- factory :jira_project, parent: :project do
- has_external_issue_tracker { true }
-
- jira_integration
- end
-
- factory :prometheus_project, parent: :project do
- after :create do |project|
- project.create_prometheus_integration(
- active: true,
- properties: {
- api_url: 'https://prometheus.example.com/',
- manual_configuration: true
- }
- )
- end
- end
-
- factory :ewm_project, parent: :project do
- has_external_issue_tracker { true }
-
- ewm_integration
- end
-
factory :project_with_design, parent: :project do
after(:create) do |project|
issue = create(:issue, project: project)
diff --git a/spec/factories/users/namespace_user_callouts.rb b/spec/factories/users/namespace_user_callouts.rb
deleted file mode 100644
index fded63d0cce..00000000000
--- a/spec/factories/users/namespace_user_callouts.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :namespace_callout, class: 'Users::NamespaceCallout' do
- feature_name { :invite_members_banner }
-
- user
- namespace
- end
-end
diff --git a/spec/factories/users/phone_number_validations.rb b/spec/factories/users/phone_number_validations.rb
new file mode 100644
index 00000000000..da53dda89b4
--- /dev/null
+++ b/spec/factories/users/phone_number_validations.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :phone_number_validation, class: 'Users::PhoneNumberValidation' do
+ user
+ country { 'US' }
+ international_dial_code { 1 }
+ phone_number { '555' }
+ end
+end
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index db4d9125e6e..393cd6f6a21 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-if $".include?(File.expand_path('spec_helper.rb', __dir__))
+if $LOADED_FEATURES.include?(File.expand_path('spec_helper.rb', __dir__))
# There's no need to load anything here if spec_helper is already loaded
# because spec_helper is more extensive than fast_spec_helper
return
diff --git a/spec/features/admin/admin_broadcast_messages_spec.rb b/spec/features/admin/admin_broadcast_messages_spec.rb
index 875eb9dd0ce..b5416f539f1 100644
--- a/spec/features/admin/admin_broadcast_messages_spec.rb
+++ b/spec/features/admin/admin_broadcast_messages_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Admin Broadcast Messages' do
before do
admin = create(:admin)
sign_in(admin)
+ stub_feature_flags(vue_broadcast_messages: false)
gitlab_enable_admin_mode_sign_in(admin)
create(
:broadcast_message,
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 040c6a65b7c..657dd52228e 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -207,31 +207,6 @@ RSpec.describe 'Admin Groups' do
end
describe 'add user into a group', :js do
- shared_examples 'adds user into a group' do
- it do
- visit admin_group_path(group)
-
- select2(user_selector, from: '#user_id', multiple: true)
- page.within '#new_project_member' do
- select2(Gitlab::Access::REPORTER, from: '#access_level')
- end
- click_button "Add users to group"
-
- page.within ".group-users-list" do
- expect(page).to have_content(user.name)
- expect(page).to have_content('Reporter')
- end
- end
- end
-
- it_behaves_like 'adds user into a group' do
- let(:user_selector) { user.id }
- end
-
- it_behaves_like 'adds user into a group' do
- let(:user_selector) { user.email }
- end
-
context 'when membership is set to expire' do
it 'renders relative time' do
expire_time = Time.current + 2.days
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index fe9fd01d3d5..35e57213bdb 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -66,10 +66,26 @@ RSpec.describe "Admin Runners" do
it 'has all necessary texts' do
expect(page).to have_text "Register an instance runner"
+ expect(page).to have_text "#{s_('Runners|All')} 3"
expect(page).to have_text "#{s_('Runners|Online')} 1"
expect(page).to have_text "#{s_('Runners|Offline')} 2"
expect(page).to have_text "#{s_('Runners|Stale')} 1"
end
+
+ describe 'delete all runners in bulk' do
+ before do
+ check s_('Runners|Select all')
+ click_button s_('Runners|Delete selected')
+
+ within_modal do
+ click_on 'Permanently delete 3 runners'
+ end
+
+ wait_for_requests
+ end
+
+ it_behaves_like 'shows no runners registered'
+ end
end
it 'shows a job count' do
@@ -351,14 +367,15 @@ RSpec.describe "Admin Runners" do
end
describe 'filter by tag' do
- before_all do
- create(:ci_runner, :instance, description: 'runner-blue', tag_list: ['blue'])
- create(:ci_runner, :instance, description: 'runner-red', tag_list: ['red'])
- end
+ let_it_be(:runner_1) { create(:ci_runner, :instance, description: 'runner-blue', tag_list: ['blue']) }
+ let_it_be(:runner_2) { create(:ci_runner, :instance, description: 'runner-2-blue', tag_list: ['blue']) }
+ let_it_be(:runner_3) { create(:ci_runner, :instance, description: 'runner-red', tag_list: ['red']) }
- it 'shows tags suggestions' do
+ before do
visit admin_runners_path
+ end
+ it 'shows tags suggestions' do
open_filtered_search_suggestions('Tags')
page.within(search_bar_selector) do
@@ -367,23 +384,25 @@ RSpec.describe "Admin Runners" do
end
end
- it 'shows correct runner when tag matches' do
- visit admin_runners_path
+ it_behaves_like 'filters by tag' do
+ let(:tag) { 'blue' }
+ let(:found_runner) { runner_1.description }
+ let(:missing_runner) { runner_3.description }
+ end
- expect(page).to have_content 'runner-blue'
- expect(page).to have_content 'runner-red'
+ context 'when tag does not match' do
+ before do
+ input_filtered_search_filter_is_only('Tags', 'green')
+ end
- input_filtered_search_filter_is_only('Tags', 'blue')
+ it_behaves_like 'shows no runners found'
- expect(page).to have_content 'runner-blue'
- expect(page).not_to have_content 'runner-red'
+ it 'shows no runner' do
+ expect(page).not_to have_content 'runner-blue'
+ end
end
it 'shows correct runner when tag is selected and search term is entered' do
- create(:ci_runner, :instance, description: 'runner-2-blue', tag_list: ['blue'])
-
- visit admin_runners_path
-
input_filtered_search_filter_is_only('Tags', 'blue')
expect(page).to have_content 'runner-blue'
@@ -396,19 +415,6 @@ RSpec.describe "Admin Runners" do
expect(page).not_to have_content 'runner-blue'
expect(page).not_to have_content 'runner-red'
end
-
- context 'when tag does not match' do
- before do
- visit admin_runners_path
- input_filtered_search_filter_is_only('Tags', 'green')
- end
-
- it_behaves_like 'shows no runners found'
-
- it 'shows no runner' do
- expect(page).not_to have_content 'runner-blue'
- end
- end
end
it 'sorts by last contact date' do
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index a5df142d188..94c5f397670 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Admin updates settings' do
include TermsHelper
include UsageDataHelpers
- let(:admin) { create(:admin) }
+ let_it_be(:admin) { create(:admin) }
let(:dot_com?) { false }
context 'application setting :admin_mode is enabled', :request_store do
@@ -177,10 +177,10 @@ RSpec.describe 'Admin updates settings' do
end
it 'change Dormant users period' do
- expect(page).to have_field _('Period of inactivity (days)')
+ expect(page).to have_field _('Days of inactivity before deactivation')
page.within(find('[data-testid="account-limit"]')) do
- fill_in _('application_setting_deactivate_dormant_users_period'), with: '35'
+ fill_in _('application_setting_deactivate_dormant_users_period'), with: '90'
click_button 'Save changes'
end
@@ -188,7 +188,7 @@ RSpec.describe 'Admin updates settings' do
page.refresh
- expect(page).to have_field _('Period of inactivity (days)'), with: '35'
+ expect(page).to have_field _('Days of inactivity before deactivation'), with: '90'
end
end
end
@@ -400,39 +400,19 @@ RSpec.describe 'Admin updates settings' do
end
context 'Runner Registration' do
- context 'when feature is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
-
- it 'allows admins to control who has access to register runners' do
- visit ci_cd_admin_application_settings_path
-
- expect(current_settings.valid_runner_registrars).to eq(ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
+ it 'allows admins to control who has access to register runners' do
+ visit ci_cd_admin_application_settings_path
- page.within('.as-runner') do
- find_all('input[type="checkbox"]').each(&:click)
+ expect(current_settings.valid_runner_registrars).to eq(ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
- click_button 'Save changes'
- end
-
- expect(current_settings.valid_runner_registrars).to eq([])
- expect(page).to have_content "Application settings saved successfully"
- end
- end
+ page.within('.as-runner') do
+ find_all('input[type="checkbox"]').each(&:click)
- context 'when feature is disabled' do
- before do
- stub_feature_flags(runner_registration_control: false)
+ click_button 'Save changes'
end
- it 'does not allow admins to control who has access to register runners' do
- visit ci_cd_admin_application_settings_path
-
- expect(current_settings.valid_runner_registrars).to eq(ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
-
- expect(page).not_to have_css('.as-runner')
- end
+ expect(current_settings.valid_runner_registrars).to eq([])
+ expect(page).to have_content "Application settings saved successfully"
end
end
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index 7e57cffc791..45dccf9921f 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -9,15 +9,11 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
let!(:user) { create(:user) }
def active_impersonation_tokens
- find(".table.active-tokens")
- end
-
- def no_personal_access_tokens_message
- find(".settings-message")
+ find("[data-testid='active-tokens']")
end
def created_impersonation_token
- find("#created-personal-access-token").value
+ find_field('new-access-token').value
end
before do
@@ -80,8 +76,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
accept_gl_confirm(button_text: 'Revoke') { click_on "Revoke" }
- expect(page).to have_selector(".settings-message")
- expect(no_personal_access_tokens_message).to have_text("This user has no active impersonation tokens.")
+ expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.")
end
it "removes expired tokens from 'active' section" do
@@ -89,8 +84,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
visit admin_user_impersonation_tokens_path(user_id: user.username)
- expect(page).to have_selector(".settings-message")
- expect(no_personal_access_tokens_message).to have_text("This user has no active impersonation tokens.")
+ expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.")
end
end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index 236327ea687..9c59f0226e0 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -366,7 +366,7 @@ RSpec.describe 'Admin::Users' do
expect(user.projects_limit)
.to eq(Gitlab.config.gitlab.default_projects_limit)
expect(user.can_create_group)
- .to eq(Gitlab.config.gitlab.default_can_create_group)
+ .to eq(Gitlab::CurrentSettings.can_create_group)
end
it 'creates user with valid data' do
@@ -481,14 +481,14 @@ RSpec.describe 'Admin::Users' do
end
it 'lists groups' do
- within(:css, '.gl-mb-3 + .card') do
+ within(:css, '.gl-mb-3 + .gl-card') do
expect(page).to have_content 'Groups'
expect(page).to have_link group.name, href: admin_group_path(group)
end
end
it 'allows navigation to the group details' do
- within(:css, '.gl-mb-3 + .card') do
+ within(:css, '.gl-mb-3 + .gl-card') do
click_link group.name
end
expect(page).to have_content "Group: #{group.name}"
@@ -496,7 +496,7 @@ RSpec.describe 'Admin::Users' do
end
it 'shows the group access level' do
- within(:css, '.gl-mb-3 + .card') do
+ within(:css, '.gl-mb-3 + .gl-card') do
expect(page).to have_content 'Developer'
end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index f279af90aa3..a09c9d258dc 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -23,7 +23,6 @@ RSpec.describe 'Project issue boards', :js do
project.add_maintainer(user2)
sign_in(user)
- stub_feature_flags(gl_avatar_for_all_user_avatars: false)
set_cookie('sidebar_collapsed', 'true')
end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index 48a6976f263..875ae41c55d 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -41,9 +41,9 @@ RSpec.describe 'Tooltips on .timeago dates', :js do
end
it 'has the datetime formated correctly' do
- expect(page).to have_selector('.js-timeago.snippet-created-ago', text: '1 day ago')
+ expect(page).to have_selector('[data-testid=snippet-created-at] .js-timeago', text: '1 day ago')
- page.find('.js-timeago.snippet-created-ago').hover
+ page.find('[data-testid=snippet-created-at] .js-timeago').hover
expect(datetime_in_tooltip).to eq(created_date)
end
diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb
index 3c774f8b269..0d10aed955a 100644
--- a/spec/features/dashboard/issues_filter_spec.rb
+++ b/spec/features/dashboard/issues_filter_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Dashboard Issues filtering', :js do
it 'updates atom feed link' do
visit_issues(milestone_title: '', assignee_username: user.username)
- link = find('.nav-controls a[title="Subscribe to RSS feed"]')
+ link = find('[data-testid="rss-feed-link"]')
params = CGI.parse(URI.parse(link[:href]).query)
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 847d0faf60d..0b468854322 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -112,13 +112,12 @@ RSpec.describe 'Dashboard Projects' do
end
context 'when on Starred projects tab', :js do
- it 'shows the empty state when there are no starred projects', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222357' do
+ it 'shows the empty state when there are no starred projects' do
visit(starred_dashboard_projects_path)
element = page.find('.row.empty-state')
expect(element).to have_content("You don't have starred projects yet.")
- expect(element.find('.svg-content img')['src']).to have_content('illustrations/starred_empty')
end
it 'shows only starred projects' do
diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb
index 2cf56f93cf9..e25da5854ab 100644
--- a/spec/features/dashboard/user_filters_projects_spec.rb
+++ b/spec/features/dashboard/user_filters_projects_spec.rb
@@ -145,7 +145,14 @@ RSpec.describe 'Dashboard > User filters projects' do
end
it 'filters any project' do
+ # Selecting the same option in the `GlListbox` does not emit `select` event
+ # and that is why URL update won't be triggered. Given that `Any` is a default option
+ # we need to explicitly switch from some other option (e.g. `Internal`) to `Any`
+ # to trigger the page update
+ select_dropdown_option '#filtered-search-visibility-dropdown > .dropdown', 'Internal', '.dropdown-item'
+
select_dropdown_option '#filtered-search-visibility-dropdown > .dropdown', 'Any', '.dropdown-item'
+
list = page.all('.projects-list .project-name').map(&:text)
expect(list).to contain_exactly("Internal project", "Private project", "Treasure", "Victorialand")
diff --git a/spec/features/discussion_comments/issue_spec.rb b/spec/features/discussion_comments/issue_spec.rb
index 0bb43343ecd..ebb57b37918 100644
--- a/spec/features/discussion_comments/issue_spec.rb
+++ b/spec/features/discussion_comments/issue_spec.rb
@@ -8,7 +8,6 @@ RSpec.describe 'Thread Comments Issue', :js do
let(:issue) { create(:issue, project: project) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb
index 4fa82de3b4b..a90ff3721d3 100644
--- a/spec/features/discussion_comments/merge_request_spec.rb
+++ b/spec/features/discussion_comments/merge_request_spec.rb
@@ -8,7 +8,6 @@ RSpec.describe 'Thread Comments Merge Request', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
index 98282e47488..c3096677a73 100644
--- a/spec/features/expand_collapse_diffs_spec.rb
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -4,12 +4,13 @@ require 'spec_helper'
RSpec.describe 'Expand and collapse diffs', :js do
let(:branch) { 'expand-collapse-diffs' }
- let(:project) { create(:project, :repository) }
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:admin) { create(:admin) }
before do
allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
- admin = create(:admin)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
index baa691d244e..666bf3594de 100644
--- a/spec/features/global_search_spec.rb
+++ b/spec/features/global_search_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'Global search' do
let(:project) { create(:project, namespace: user.namespace) }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb
index f11e5c56545..84882fc674e 100644
--- a/spec/features/groups/empty_states_spec.rb
+++ b/spec/features/groups/empty_states_spec.rb
@@ -94,9 +94,7 @@ RSpec.describe 'Group empty states' do
end
it "shows a new #{issuable_name} button" do
- within '.empty-state' do
- expect(page).to have_content("create #{issuable_name}")
- end
+ expect(page).to have_content("create #{issuable_name}")
end
it "the new #{issuable_name} button opens a project dropdown" do
diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb
index ada03726c97..e9807c487d5 100644
--- a/spec/features/groups/group_runners_spec.rb
+++ b/spec/features/groups/group_runners_spec.rb
@@ -114,6 +114,35 @@ RSpec.describe "Group Runners" do
end
end
+ context "with an online instance runner" do
+ let!(:instance_runner) do
+ create(:ci_runner, :instance, description: 'runner-baz', contacted_at: Time.zone.now)
+ end
+
+ before do
+ visit group_runners_path(group)
+ end
+
+ context "when selecting 'Show only inherited'" do
+ before do
+ find("[data-testid='runner-membership-toggle'] button").click
+
+ wait_for_requests
+ end
+
+ it_behaves_like 'shows runner in list' do
+ let(:runner) { instance_runner }
+ end
+
+ it 'shows runner details page' do
+ click_link("##{instance_runner.id} (#{instance_runner.short_sha})")
+
+ expect(current_url).to include(group_runner_path(group, instance_runner))
+ expect(page).to have_content "#{s_('Runners|Description')} runner-baz"
+ end
+ end
+ end
+
context 'with a multi-project runner' do
let(:project) { create(:project, group: group) }
let(:project_2) { create(:project, group: group) }
@@ -123,7 +152,7 @@ RSpec.describe "Group Runners" do
visit group_runners_path(group)
within_runner_row(runner.id) do
- expect(page).to have_button 'Delete runner', disabled: true
+ expect(page).not_to have_button 'Delete runner'
end
end
end
@@ -142,6 +171,21 @@ RSpec.describe "Group Runners" do
end
end
end
+
+ describe 'filter by tag' do
+ let!(:runner_1) { create(:ci_runner, :group, groups: [group], description: 'runner-blue', tag_list: ['blue']) }
+ let!(:runner_2) { create(:ci_runner, :group, groups: [group], description: 'runner-red', tag_list: ['red']) }
+
+ before do
+ visit group_runners_path(group)
+ end
+
+ it_behaves_like 'filters by tag' do
+ let(:tag) { 'blue' }
+ let(:found_runner) { runner_1.description }
+ let(:missing_runner) { runner_2.description }
+ end
+ end
end
describe "Group runner show page", :js do
diff --git a/spec/features/groups/labels/sort_labels_spec.rb b/spec/features/groups/labels/sort_labels_spec.rb
index fba166449f8..9d05703aae6 100644
--- a/spec/features/groups/labels/sort_labels_spec.rb
+++ b/spec/features/groups/labels/sort_labels_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Sort labels', :js do
it 'sorts by date' do
click_button 'Name'
- sort_options = find('ul.dropdown-menu').all('li').collect(&:text)
+ sort_options = find('ul[role="listbox"]').all('li').collect(&:text)
expect(sort_options[0]).to eq('Name')
expect(sort_options[1]).to eq('Name, descending')
@@ -37,7 +37,7 @@ RSpec.describe 'Sort labels', :js do
expect(sort_options[4]).to eq('Updated date')
expect(sort_options[5]).to eq('Oldest updated')
- click_button 'Name, descending'
+ find('li', text: 'Name, descending').click
# assert default sorting
within '.other-labels' do
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index be1db970e9d..296b839c8fc 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -57,6 +57,16 @@ RSpec.describe 'Group merge requests page' do
expect(find('#js-dropdown-assignee .filter-dropdown')).to have_content(user.name)
expect(find('#js-dropdown-assignee .filter-dropdown')).not_to have_content(user2.name)
end
+
+ it 'will still show the navbar with no results' do
+ search_term = 'some-search-term-that-produces-zero-results'
+
+ filtered_search.set(search_term)
+ filtered_search.send_keys(:enter)
+
+ expect(page).to have_content('filter produced no results')
+ expect(page).to have_link('Open', href: "/groups/#{group.name}/-/merge_requests?scope=all&search=#{search_term}&state=opened")
+ end
end
describe 'new merge request dropdown' do
diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb
index 22d7ff91d41..125bf9ce3a7 100644
--- a/spec/features/groups/milestones_sorting_spec.rb
+++ b/spec/features/groups/milestones_sorting_spec.rb
@@ -29,9 +29,9 @@ RSpec.describe 'Milestones sorting', :js do
within '[data-testid=milestone_sort_by_dropdown]' do
click_button 'Due soon'
- expect(find('.gl-new-dropdown-contents').all('.gl-new-dropdown-item-text-wrapper p').map(&:text)).to eq(['Due soon', 'Due later', 'Start soon', 'Start later', 'Name, ascending', 'Name, descending'])
+ expect(find('ul[role="listbox"]').all('li').map(&:text)).to eq(['Due soon', 'Due later', 'Start soon', 'Start later', 'Name, ascending', 'Name, descending'])
- click_button 'Due later'
+ find('li', text: 'Due later').click
expect(page).to have_button('Due later')
end
diff --git a/spec/features/groups/new_group_page_spec.rb b/spec/features/groups/new_group_page_spec.rb
new file mode 100644
index 00000000000..6a8af9c31fd
--- /dev/null
+++ b/spec/features/groups/new_group_page_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'New group page', :js do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'new top level group alert' do
+ context 'when a user visits the new group page' do
+ it 'shows the new top level group alert' do
+ visit new_group_path(anchor: 'create-group-pane')
+
+ expect(page).to have_selector('[data-testid="new-top-level-alert"]')
+ end
+ end
+
+ context 'when a user visits the new sub group page' do
+ let(:parent_group) { create(:group) }
+
+ it 'does not show the new top level group alert' do
+ visit new_group_path(parent_id: parent_group.id, anchor: 'create-group-pane')
+
+ expect(page).not_to have_selector('[data-testid="new-top-level-alert"]')
+ end
+ end
+ end
+end
diff --git a/spec/features/groups/settings/repository_spec.rb b/spec/features/groups/settings/repository_spec.rb
index 159deb2a4e3..f6b8bbdd35f 100644
--- a/spec/features/groups/settings/repository_spec.rb
+++ b/spec/features/groups/settings/repository_spec.rb
@@ -2,14 +2,17 @@
require 'spec_helper'
-RSpec.describe 'Group Repository settings' do
+RSpec.describe 'Group Repository settings', :js do
include WaitForRequests
- let(:user) { create(:user) }
- let(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group, reload: true) { create(:group) }
- before do
+ before_all do
group.add_owner(user)
+ end
+
+ before do
sign_in(user)
end
@@ -20,9 +23,26 @@ RSpec.describe 'Group Repository settings' do
stub_container_registry_config(enabled: true)
end
- it_behaves_like 'a deploy token in settings' do
- let(:entity_type) { 'group' }
- let(:page_path) { group_settings_repository_path(group) }
+ context 'when ajax deploy tokens is enabled' do
+ before do
+ stub_feature_flags(ajax_new_deploy_token: true)
+ end
+
+ it_behaves_like 'a deploy token in settings' do
+ let(:entity_type) { 'group' }
+ let(:page_path) { group_settings_repository_path(group) }
+ end
+ end
+
+ context 'when ajax deploy tokens is disabled' do
+ before do
+ stub_feature_flags(ajax_new_deploy_token: false)
+ end
+
+ it_behaves_like 'a deploy token in settings' do
+ let(:entity_type) { 'group' }
+ let(:page_path) { group_settings_repository_path(group) }
+ end
end
end
diff --git a/spec/features/help_dropdown_spec.rb b/spec/features/help_dropdown_spec.rb
index e64c19d4708..a9c014a9408 100644
--- a/spec/features/help_dropdown_spec.rb
+++ b/spec/features/help_dropdown_spec.rb
@@ -59,6 +59,10 @@ RSpec.describe "Help Dropdown", :js do
expect(page).to have_text('Your GitLab Version')
expect(page).to have_text("#{Gitlab.version_info.major}.#{Gitlab.version_info.minor}")
expect(page).to have_selector('.version-check-badge')
+ expect(page).to have_selector(
+ 'a[data-testid="gitlab-version-container"][href="/help/update/index"]'
+ )
+ expect(page).to have_selector('.version-check-badge[href="/help/update/index"]')
expect(page).to have_text(ui_text)
end
end
diff --git a/spec/features/ide/user_commits_changes_spec.rb b/spec/features/ide/user_commits_changes_spec.rb
deleted file mode 100644
index 04b215710b3..00000000000
--- a/spec/features/ide/user_commits_changes_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'IDE user commits changes', :js do
- include WebIdeSpecHelpers
-
- let(:project) { create(:project, :public, :repository) }
- let(:user) { project.first_owner }
-
- before do
- stub_feature_flags(vscode_web_ide: false)
-
- sign_in(user)
-
- ide_visit(project)
- end
-
- it 'user updates nested files' do
- content = <<~HEREDOC
- Lorem ipsum
- Dolar sit
- Amit
- HEREDOC
-
- ide_create_new_file('foo/bar/lorem_ipsum.md', content: content)
- ide_delete_file('foo/bar/.gitkeep')
-
- ide_commit
-
- expect(page).to have_content('All changes are committed')
- expect(project.repository.blob_at('master', 'foo/bar/.gitkeep')).to be_nil
- expect(project.repository.blob_at('master', 'foo/bar/lorem_ipsum.md').data).to eql(content)
- end
-end
diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb
index 6db9f87d6f2..ef0eb27d310 100644
--- a/spec/features/incidents/incident_timeline_events_spec.rb
+++ b/spec/features/incidents/incident_timeline_events_spec.rb
@@ -12,7 +12,6 @@ RSpec.describe 'Incident timeline events', :js do
end
before do
- stub_feature_flags(incident_timeline: true)
sign_in(developer)
visit project_issues_incident_path(project, incident)
diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb
index 9d46b3a274e..66d0022f7e9 100644
--- a/spec/features/issuables/markdown_references/jira_spec.rb
+++ b/spec/features/issuables/markdown_references/jira_spec.rb
@@ -15,8 +15,6 @@ RSpec.describe "Jira", :js do
before do
remotelink = double(:remotelink, all: [], build: double(save!: true))
- stub_feature_flags(remove_user_attributes_projects: false)
-
stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5")
stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment")
allow_next_instance_of(JIRA::Resource::Issue) do |instance|
@@ -59,7 +57,7 @@ RSpec.describe "Jira", :js do
visit(issue_path(issue_actual_project))
page.within("#notes") do
- expect(page).to have_content("#{user.to_reference} mentioned in merge request #{merge_request.to_reference}")
+ expect(page).to have_content("#{user.name} mentioned in merge request #{merge_request.to_reference}")
end
end
@@ -67,7 +65,7 @@ RSpec.describe "Jira", :js do
visit(issue_path(issue_other_project))
page.within("#notes") do
- expect(page).to have_content("#{user.to_reference} mentioned in merge request #{merge_request.to_reference(other_project)}")
+ expect(page).to have_content("#{user.name} mentioned in merge request #{merge_request.to_reference(other_project)}")
end
end
end
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index 56be1493ed2..d6cde466d1b 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -26,7 +26,6 @@ RSpec.describe 'Incident Detail', :js do
context 'when user displays the incident' do
before do
- stub_feature_flags(incident_timeline: project)
project.add_developer(user)
sign_in(user)
@@ -52,8 +51,8 @@ RSpec.describe 'Incident Detail', :js do
aggregate_failures 'when on summary tab (default tab)' do
hidden_items = find_all('.js-issue-widgets')
- # Linked Issues/MRs and comment box
- expect(hidden_items.count).to eq(2)
+ # Linked Issues/MRs and comment box and emoji block
+ expect(hidden_items.count).to eq(3)
expect(hidden_items).to all(be_visible)
edit_button = find_all('[aria-label="Edit title and description"]')
@@ -67,13 +66,13 @@ RSpec.describe 'Incident Detail', :js do
expect(incident_tabs).to have_content('"yet.another": 73')
# does not show the linked issues and notes/comment components' do
- hidden_items = find_all('.js-issue-widgets')
+ hidden_items = find_all('.js-issue-widgets', wait: false)
# Linked Issues/MRs and comment box are hidden on page
expect(hidden_items.count).to eq(0)
# does not show the edit title and description button
- edit_button = find_all('[aria-label="Edit title and description"]')
+ edit_button = find_all('[aria-label="Edit title and description"]', wait: false)
expect(edit_button.count).to eq(0)
end
end
@@ -83,32 +82,19 @@ RSpec.describe 'Incident Detail', :js do
before do
visit project_issue_path(project, incident)
wait_for_requests
+
click_link 'Timeline'
+ wait_for_requests
end
it 'does not show the linked issues and notes/comment components' do
page.within('.issuable-details') do
- hidden_items = find_all('.js-issue-widgets')
+ hidden_items = find_all('.js-issue-widgets', wait: false)
# Linked Issues/MRs and comment box are hidden on page
expect(hidden_items.count).to eq(0)
end
end
end
-
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
-
- visit project_issues_incident_path(project, incident)
- wait_for_requests
- end
-
- it 'does not show Timeline tab' do
- tabs = find('[data-testid="incident-tabs"]')
-
- expect(tabs).not_to have_content('Timeline')
- end
- end
end
end
diff --git a/spec/features/issues/related_issues_spec.rb b/spec/features/issues/related_issues_spec.rb
index 818e99f2ec9..62127295a7c 100644
--- a/spec/features/issues/related_issues_spec.rb
+++ b/spec/features/issues/related_issues_spec.rb
@@ -3,42 +3,41 @@
require 'spec_helper'
RSpec.describe 'Related issues', :js do
- let(:user) { create(:user) }
- let(:project) { create(:project_empty_repo, :public) }
- let(:project_b) { create(:project_empty_repo, :public) }
- let(:project_unauthorized) { create(:project_empty_repo, :public) }
- let(:issue_a) { create(:issue, project: project) }
- let(:issue_b) { create(:issue, project: project) }
- let(:issue_c) { create(:issue, project: project) }
- let(:issue_d) { create(:issue, project: project) }
- let(:issue_project_b_a) { create(:issue, project: project_b) }
- let(:issue_project_unauthorized_a) { create(:issue, project: project_unauthorized) }
+ let_it_be(:user) { create(:user) }
+
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:project_b) { create(:project_empty_repo, :public) }
+ let_it_be(:project_unauthorized) { create(:project_empty_repo, :public) }
+ let_it_be(:internal_project) { create(:project_empty_repo, :internal) }
+ let_it_be(:private_project) { create(:project_empty_repo, :private) }
+ let_it_be(:public_project) { create(:project_empty_repo, :public) }
+
+ let_it_be(:issue_a) { create(:issue, project: project) }
+ let_it_be(:issue_b) { create(:issue, project: project) }
+ let_it_be(:issue_c) { create(:issue, project: project) }
+ let_it_be(:issue_d) { create(:issue, project: project) }
+ let_it_be(:issue_project_b_a) { create(:issue, project: project_b) }
+ let_it_be(:issue_project_unauthorized_a) { create(:issue, project: project_unauthorized) }
+ let_it_be(:internal_issue) { create(:issue, project: internal_project) }
+ let_it_be(:private_issue) { create(:issue, project: private_project) }
+ let_it_be(:public_issue) { create(:issue, project: public_project) }
context 'widget visibility' do
context 'when not logged in' do
it 'does not show widget when internal project' do
- project = create :project_empty_repo, :internal
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(internal_project, internal_issue)
expect(page).not_to have_css('.related-issues-block')
end
it 'does not show widget when private project' do
- project = create :project_empty_repo, :private
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(private_project, private_issue)
expect(page).not_to have_css('.related-issues-block')
end
it 'shows widget when public project' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, public_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
@@ -51,39 +50,29 @@ RSpec.describe 'Related issues', :js do
end
it 'shows widget when internal project' do
- project = create :project_empty_repo, :internal
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(internal_project, internal_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
end
it 'does not show widget when private project' do
- project = create :project_empty_repo, :private
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(private_project, private_issue)
expect(page).not_to have_css('.related-issues-block')
end
it 'shows widget when public project' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project
-
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, public_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
end
it 'shows widget on their own public issue' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project, author: user
+ issue = create :issue, project: public_project, author: user
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
@@ -96,33 +85,27 @@ RSpec.describe 'Related issues', :js do
end
it 'shows widget when internal project' do
- project = create :project_empty_repo, :internal
- issue = create :issue, project: project
- project.add_guest(user)
+ internal_project.add_guest(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(internal_project, internal_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
end
it 'shows widget when private project' do
- project = create :project_empty_repo, :private
- issue = create :issue, project: project
- project.add_guest(user)
+ private_project.add_guest(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(private_project, private_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
end
it 'shows widget when public project' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project
- project.add_guest(user)
+ public_project.add_guest(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, public_issue)
expect(page).to have_css('.related-issues-block')
expect(page).not_to have_button 'Add a related issue'
@@ -135,44 +118,37 @@ RSpec.describe 'Related issues', :js do
end
it 'shows widget when internal project' do
- project = create :project_empty_repo, :internal
- issue = create :issue, project: project
- project.add_reporter(user)
+ internal_project.add_reporter(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(internal_project, internal_issue)
expect(page).to have_css('.related-issues-block')
expect(page).to have_button 'Add a related issue'
end
it 'shows widget when private project' do
- project = create :project_empty_repo, :private
- issue = create :issue, project: project
- project.add_reporter(user)
+ private_project.add_reporter(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(private_project, private_issue)
expect(page).to have_css('.related-issues-block')
expect(page).to have_button 'Add a related issue'
end
it 'shows widget when public project' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project
- project.add_reporter(user)
+ public_project.add_reporter(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, public_issue)
expect(page).to have_css('.related-issues-block')
expect(page).to have_button 'Add a related issue'
end
it 'shows widget on their own public issue' do
- project = create :project_empty_repo, :public
- issue = create :issue, project: project, author: user
- project.add_reporter(user)
+ issue = create :issue, project: public_project, author: user
+ public_project.add_reporter(user)
- visit project_issue_path(project, issue)
+ visit project_issue_path(public_project, issue)
expect(page).to have_css('.related-issues-block')
expect(page).to have_button 'Add a related issue'
@@ -184,8 +160,11 @@ RSpec.describe 'Related issues', :js do
let!(:issue_link_b) { create :issue_link, source: issue_a, target: issue_b }
let!(:issue_link_c) { create :issue_link, source: issue_a, target: issue_c }
- before do
+ before_all do
project.add_guest(user)
+ end
+
+ before do
sign_in(user)
end
@@ -213,9 +192,12 @@ RSpec.describe 'Related issues', :js do
end
context 'when user has permission to manage related issues' do
- before do
+ before_all do
project.add_maintainer(user)
project_b.add_maintainer(user)
+ end
+
+ before do
sign_in(user)
end
diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb
index e4da2f67516..e8158b3e2aa 100644
--- a/spec/features/issues/resource_label_events_spec.rb
+++ b/spec/features/issues/resource_label_events_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'List issue resource label events', :js do
let!(:event) { create(:resource_label_event, user: user, issue: issue, label: label) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
visit project_issue_path(project, issue)
wait_for_requests
end
@@ -22,13 +21,7 @@ RSpec.describe 'List issue resource label events', :js do
it 'shows both notes and resource label events' do
page.within('#notes') do
expect(find("#note_#{note.id}")).to have_content 'some note'
- expect(find("#note_#{event.discussion_id}")).to have_content 'added foo label'
- end
- end
-
- it 'shows the user status on the system note for the label' do
- page.within("#note_#{event.discussion_id}") do
- expect(page).to show_user_status user_status
+ expect(find("#note_#{event.reload.discussion_id}")).to have_content 'added foo label'
end
end
end
diff --git a/spec/features/issues/service_desk_spec.rb b/spec/features/issues/service_desk_spec.rb
index cc0d35afd60..87cd00fac6b 100644
--- a/spec/features/issues/service_desk_spec.rb
+++ b/spec/features/issues/service_desk_spec.rb
@@ -90,7 +90,6 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
it 'displays the small info box, documentation, a button to configure service desk, and the address' do
aggregate_failures do
- expect(page).to have_css('.non-empty-state')
expect(page).to have_link('Learn more.', href: help_page_path('user/project/service_desk'))
expect(page).not_to have_link('Enable Service Desk')
expect(page).to have_content(project.service_desk_address)
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 8ed56108f00..47b28b88108 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -218,7 +218,7 @@ RSpec.describe 'User interacts with awards' do
expect(first('[data-testid="award-button"]')).to have_content '1'
end
- it 'removes award from issue' do
+ it 'removes award from issue', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375241' do
first('[data-testid="award-button"]').click
find('[data-testid="award-button"].selected').click
diff --git a/spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb b/spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb
index 5aae5abaf10..1fa8f533869 100644
--- a/spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb
+++ b/spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe 'User scrolls to deep-linked note' do
context 'on issue page', :js do
it 'on comment' do
- stub_feature_flags(gl_avatar_for_all_user_avatars: false)
visit project_issue_path(project, issue, anchor: "note_#{comment_1.id}")
wait_for_requests
diff --git a/spec/features/markdown/gitlab_flavored_markdown_spec.rb b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
index e831d1be608..17fe2dab8f7 100644
--- a/spec/features/markdown/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe "GitLab Flavored Markdown" do
- include CycleAnalyticsHelpers
-
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project) }
@@ -24,7 +22,12 @@ RSpec.describe "GitLab Flavored Markdown" do
let(:commit) { project.commit }
before do
- create_commit("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details", project, user, 'master')
+ project.repository.commit_files(
+ user,
+ branch_name: 'master',
+ message: "fix #{issue.to_reference}\n\nask #{fred.to_reference} for details",
+ actions: [{ action: :create, file_path: 'a/new.file', content: 'This is a file' }]
+ )
end
it "renders title in commits#index" do
diff --git a/spec/features/markdown/metrics_spec.rb b/spec/features/markdown/metrics_spec.rb
index 44354c9df47..61dd41204f8 100644
--- a/spec/features/markdown/metrics_spec.rb
+++ b/spec/features/markdown/metrics_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Metrics rendering', :js, :kubeclient, :use_clean_rails_memory_st
include MetricsDashboardUrlHelpers
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:prometheus_project) }
+ let_it_be(:project) { create(:project, :with_prometheus_integration) }
let_it_be(:environment) { create(:environment, project: project) }
let(:issue) { create(:issue, project: project, description: description) }
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index bccdc3c4c62..f01217df8c5 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -74,6 +74,24 @@ RSpec.describe 'Merge request > Batch comments', :js do
expect(page).to have_selector('.draft-note-component', text: 'Testing update')
end
+ context 'multiple times on the same diff line' do
+ it 'shows both drafts at once' do
+ write_diff_comment
+
+ # All of the Diff helpers like click_diff_line (or write_diff_comment)
+ # fail very badly when run a second time.
+ # This recreates the relevant logic.
+ line = find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']")
+ line.hover
+ line.find('.js-add-diff-note-button').click
+
+ write_comment(text: 'A second draft!', button_text: 'Add to review')
+
+ expect(page).to have_text('Line is wrong')
+ expect(page).to have_text('A second draft!')
+ end
+ end
+
context 'with image and file draft note' do
let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project) }
let!(:draft_on_text) { create(:draft_note_on_text_diff, merge_request: merge_request, author: user, path: 'README.md', note: 'Lorem ipsum on text...') }
diff --git a/spec/features/merge_request/close_reopen_report_toggle_spec.rb b/spec/features/merge_request/close_reopen_report_toggle_spec.rb
index dea9a10a4ec..5e9400935c3 100644
--- a/spec/features/merge_request/close_reopen_report_toggle_spec.rb
+++ b/spec/features/merge_request/close_reopen_report_toggle_spec.rb
@@ -24,14 +24,14 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
context 'close/reopen/report toggle' do
it 'opens a dropdown when toggle is clicked' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(container).to have_link("Close merge request")
expect(container).to have_link('Report abuse')
end
it 'links to Report Abuse' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
click_link 'Report abuse'
expect(page).to have_content('Report abuse to admin')
@@ -42,7 +42,7 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
let(:issuable) { create(:merge_request, :opened, source_project: project) }
it 'shows the `Edit` and `Mark as draft` buttons' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(container).to have_link('Edit')
expect(container).to have_link('Mark as draft')
@@ -56,7 +56,7 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
let(:issuable) { create(:merge_request, :closed, source_project: project) }
it 'shows both the `Edit` and `Reopen` button' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(container).to have_link('Edit')
expect(container).to have_link('Report abuse')
@@ -68,7 +68,7 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
let(:issuable) { create(:merge_request, :closed, source_project: project, author: user) }
it 'shows both the `Edit` and `Reopen` button' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(container).to have_link('Edit')
expect(container).to have_link('Reopen merge request')
diff --git a/spec/features/merge_request/merge_request_discussion_lock_spec.rb b/spec/features/merge_request/merge_request_discussion_lock_spec.rb
index a7bc2a062af..d69295744f7 100644
--- a/spec/features/merge_request/merge_request_discussion_lock_spec.rb
+++ b/spec/features/merge_request/merge_request_discussion_lock_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'Merge Request Discussion Lock', :js do
end
it 'the user can lock the merge_request' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(page).to have_content('Lock merge request')
end
@@ -103,7 +103,7 @@ RSpec.describe 'Merge Request Discussion Lock', :js do
end
it 'the user can unlock the merge_request' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(page).to have_content('Unlock merge request')
end
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index fd33731cb7b..ffaf403e873 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'User comments on a diff', :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_comments_on_merge_request_spec.rb b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
index ec1e2fea851..dbcfc2b968f 100644
--- a/spec/features/merge_request/user_comments_on_merge_request_spec.rb
+++ b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe 'User comments on a merge request', :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
index f5b5460769e..07d99a786ba 100644
--- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
+++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Batch diffs', :js do
include MergeRequestDiffHelpers
include RepoHelpers
- let(:project) { create(:project, :repository) }
- let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') }
before do
sign_in(project.first_owner)
diff --git a/spec/features/merge_request/user_jumps_to_discussion_spec.rb b/spec/features/merge_request/user_jumps_to_discussion_spec.rb
deleted file mode 100644
index 9bded1c5572..00000000000
--- a/spec/features/merge_request/user_jumps_to_discussion_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User jumps to the next unresolved discussion', :js do
- let(:project) { create(:project, :repository) }
- let(:merge_request) do
- create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test')
- end
-
- let(:user) { create(:user) }
-
- before do
- create(:discussion_note, noteable: merge_request, project: project, author: user)
-
- project.add_maintainer(user)
- sign_in(user)
-
- visit(diffs_project_merge_request_path(project, merge_request))
-
- wait_for_requests
- end
-
- it 'jumps to overview tab' do
- find('.discussion-next-btn').click
-
- expect(page).to have_css('.notes-tab.active')
- end
-end
diff --git a/spec/features/merge_request/user_manages_subscription_spec.rb b/spec/features/merge_request/user_manages_subscription_spec.rb
index 9fb85957979..a8d59a6ffb5 100644
--- a/spec/features/merge_request/user_manages_subscription_spec.rb
+++ b/spec/features/merge_request/user_manages_subscription_spec.rb
@@ -43,22 +43,18 @@ RSpec.describe 'User manages subscription', :js do
it 'toggles subscription' do
wait_for_requests
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
expect(page).to have_selector('.gl-toggle:not(.is-checked)')
find('[data-testid="notifications-toggle"] .gl-toggle').click
wait_for_requests
- click_button 'Toggle dropdown'
-
expect(page).to have_selector('.gl-toggle.is-checked')
find('[data-testid="notifications-toggle"] .gl-toggle').click
wait_for_requests
- click_button 'Toggle dropdown'
-
expect(page).to have_selector('.gl-toggle:not(.is-checked)')
end
end
diff --git a/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb
index c3a61476442..d85f275b724 100644
--- a/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb
+++ b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb
@@ -16,12 +16,12 @@ RSpec.describe 'Merge request > User marks merge request as draft', :js do
end
it 'toggles draft status' do
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
click_link 'Mark as draft'
expect(page).to have_content("Draft: #{merge_request.title}")
- click_button 'Toggle dropdown'
+ find('[data-testid="merge-request-actions"]').click
page.within('.detail-page-header-actions') do
click_link 'Mark as ready'
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 1eebb6c2e28..8af0e957c14 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
include MergeRequestDiffHelpers
include Spec::Support::Helpers::ModalHelpers
- let(:merge_request) { create(:merge_request) }
+ let_it_be(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
let(:user) { project.creator }
let(:comment_button_class) { '.add-diff-note' }
@@ -219,7 +219,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
end
context 'with a match line' do
- it 'does not allow commenting' do
+ it 'does not allow commenting', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375024' do
match_should_not_allow_commenting(find_by_scrolling('.match', match: :first))
end
end
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 8225fcbfd89..a6c024be698 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -8,10 +8,11 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
include Spec::Support::Helpers::ModalHelpers
include MergeRequestDiffHelpers
- let(:project) { create(:project, :public, :repository) }
- let(:user) { project.creator }
- let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: 'Bug NS-04') }
- let(:path) { 'files/ruby/popen.rb' }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { project.creator }
+ let_it_be(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: 'Bug NS-04') }
+
+ let(:path) { 'files/ruby/popen.rb' }
let(:position) do
build(:text_diff_position, :added,
file: path,
@@ -22,10 +23,12 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position) }
- before do
+ before_all do
project.add_maintainer(user)
+ end
+
+ before do
sign_in user
- stub_feature_flags(gl_avatar_for_all_user_avatars: false)
set_cookie('sidebar_collapsed', 'true')
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index c2a0e528ea7..77ac6fac22f 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -13,13 +13,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
let(:merge_request_in_only_mwps_project) { create(:merge_request, source_project: project_only_mwps) }
+ def click_expand_button
+ find('[data-testid="report-section-expand-button"]').click
+ end
+
before do
project.add_maintainer(user)
project_only_mwps.add_maintainer(user)
sign_in(user)
- stub_feature_flags(refactor_mr_widgets_extensions: false)
- stub_feature_flags(refactor_mr_widgets_extensions_user: false)
stub_feature_flags(refactor_mr_widget_test_summary: false)
end
@@ -606,7 +608,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the new failure' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 failed out of 2 total tests')
within(".js-report-section-container") do
@@ -621,7 +623,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the new failure' do
it 'shows the test report detail' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'addTest'
@@ -654,7 +656,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the existing failure' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 failed out of 2 total tests')
within(".js-report-section-container") do
@@ -668,7 +670,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the existing failure' do
it 'shows test report detail of it' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'Test#sum when a is 1 and b is 3 returns summary'
@@ -701,7 +703,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the resolved failure' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests')
within(".js-report-section-container") do
@@ -715,7 +717,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the resolved failure' do
it 'shows test report detail of it' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'addTest'
@@ -747,7 +749,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the new error' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 error out of 2 total tests')
within(".js-report-section-container") do
@@ -762,7 +764,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the new error' do
it 'shows the test report detail' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'addTest'
@@ -794,7 +796,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the existing error' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 error out of 2 total tests')
within(".js-report-section-container") do
@@ -808,7 +810,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the existing error' do
it 'shows test report detail of it' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'Test#sum when a is 4 and b is 4 returns summary'
@@ -840,7 +842,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the resolved error' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests')
within(".js-report-section-container") do
@@ -854,7 +856,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the resolved error' do
it 'shows test report detail of it' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
within(".js-report-section-container") do
click_button 'addTest'
@@ -894,7 +896,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'shows test reports summary which includes the resolved failure' do
within(".js-reports-container") do
- click_button 'Expand'
+ click_expand_button
expect(page).to have_content('Test summary contained 20 failed out of 20 total tests')
within(".js-report-section-container") do
diff --git a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb b/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb
deleted file mode 100644
index d3ea8b955f2..00000000000
--- a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Project > Merge request > View user status' do
- let(:project) { create(:project, :public, :repository) }
- let(:merge_request) do
- create(:merge_request, source_project: project, target_project: project, author: create(:user))
- end
-
- before do
- stub_feature_flags(remove_user_attributes_projects: false)
- end
-
- subject { visit merge_request_path(merge_request) }
-
- context 'for notes', :js do
- describe 'the status of the author of a note on a merge request' do
- let(:note) { create(:note, noteable: merge_request, project: project, author: create(:user)) }
-
- it_behaves_like 'showing user status' do
- let(:user_with_status) { note.author }
- end
- end
-
- describe 'the status of the author of a diff note on a merge request' do
- let(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, author: create(:user)) }
-
- it_behaves_like 'showing user status' do
- let(:user_with_status) { note.author }
- end
- end
- end
-end
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index 2a1ea1a4e73..98d623902a5 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -23,11 +23,17 @@ RSpec.describe 'Milestone' do
fill_in "milestone_due_date", with: '2016-12-16'
end
- find('input[name="commit"]').click
+ click_button 'Create milestone'
expect(find('[data-testid="no-issues-alert"]')).to have_content('Assign some issues to this milestone.')
expect(page).to have_content('Nov 16, 2016–Dec 16, 2016')
end
+
+ it 'passes redirect_path through to form' do
+ visit new_project_milestone_path(project, redirect_path: 'new_release')
+
+ expect(find('#redirect_path', visible: :all)[:value]).to eq('new_release')
+ end
end
describe 'Open a milestone with closed issues' do
@@ -49,7 +55,7 @@ RSpec.describe 'Milestone' do
page.within '.milestone-form' do
fill_in "milestone_title", with: milestone.title
end
- find('input[name="commit"]').click
+ click_button 'Create milestone'
expect(find('.gl-alert-danger')).to have_content('already being used for another group or project milestone.')
end
@@ -62,7 +68,7 @@ RSpec.describe 'Milestone' do
page.within '.milestone-form' do
fill_in "milestone_title", with: milestone.title
end
- find('input[name="commit"]').click
+ click_button 'Create milestone'
expect(find('.gl-alert-danger')).to have_content('already being used for another group or project milestone.')
end
diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb
index dd377aa4a26..1ab231632fb 100644
--- a/spec/features/milestones/user_creates_milestone_spec.rb
+++ b/spec/features/milestones/user_creates_milestone_spec.rb
@@ -3,29 +3,100 @@
require 'spec_helper'
RSpec.describe "User creates milestone", :js do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:inherited_guest) { create(:user) }
+ let_it_be(:inherited_developer) { create(:user) }
+ let_it_be(:group) { create(:group, :public) }
+
+ shared_examples 'creates milestone' do
+ specify do
+ title = "v2.3"
+
+ fill_in("Title", with: title)
+ fill_in("Description", with: "# Description header")
+ click_button("Create milestone")
+
+ expect(page).to have_content(title)
+ .and have_content("Issues")
+ .and have_header_with_correct_id_and_link(1, "Description header", "description-header")
+
+ visit(activity_project_path(project))
+
+ expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone")
+ end
+ end
+
+ shared_examples 'renders not found' do
+ specify do
+ expect(page).to have_title('Not Found')
+ expect(page).to have_content('Page Not Found')
+ end
+ end
+
+ before_all do
+ group.add_guest(inherited_guest)
+ group.add_developer(inherited_developer)
+ end
before do
- project.add_developer(user)
sign_in(user)
-
visit(new_project_milestone_path(project))
end
- it "creates milestone" do
- title = "v2.3"
+ context 'when project is public' do
+ let_it_be(:project) { create(:project, :public, group: group) }
+
+ context 'and issues and merge requests are private' do
+ before_all do
+ project.project_feature.update!(
+ issues_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE
+ )
+ end
+
+ context 'when user is an inherited member from the group' do
+ context 'and user is a guest' do
+ let(:user) { inherited_guest }
+
+ it_behaves_like 'renders not found'
+ end
+
+ context 'and user is a developer' do
+ let(:user) { inherited_developer }
+
+ it_behaves_like 'creates milestone'
+ end
+ end
+ end
+ end
+
+ context 'when project is private' do
+ let_it_be(:project) { create(:project, :private, group: group) }
+
+ context 'and user is a direct project member' do
+ before_all do
+ project.add_developer(developer)
+ end
+
+ context 'when user is a developer' do
+ let(:user) { developer }
+
+ it_behaves_like 'creates milestone'
+ end
+ end
- fill_in("Title", with: title)
- fill_in("Description", with: "# Description header")
- click_button("Create milestone")
+ context 'and user is an inherited member from the group' do
+ context 'when user is a guest' do
+ let(:user) { inherited_guest }
- expect(page).to have_content(title)
- .and have_content("Issues")
- .and have_header_with_correct_id_and_link(1, "Description header", "description-header")
+ it_behaves_like 'renders not found'
+ end
- visit(activity_project_path(project))
+ context 'when user is a developer' do
+ let(:user) { inherited_developer }
- expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone")
+ it_behaves_like 'creates milestone'
+ end
+ end
end
end
diff --git a/spec/features/oauth_registration_spec.rb b/spec/features/oauth_registration_spec.rb
index cb8343b8065..0a35b5a7e42 100644
--- a/spec/features/oauth_registration_spec.rb
+++ b/spec/features/oauth_registration_spec.rb
@@ -3,126 +3,139 @@
require 'spec_helper'
RSpec.describe 'OAuth Registration', :js, :allow_forgery_protection do
- include DeviseHelpers
include LoginHelpers
include TermsHelper
using RSpec::Parameterized::TableSyntax
+ let(:uid) { 'my-uid' }
+ let(:email) { 'user@example.com' }
+
around do |example|
with_omniauth_full_host { example.run }
end
- context 'when the user registers using single-sign on provider' do
- let(:uid) { 'my-uid' }
- let(:email) { 'user@example.com' }
-
- where(:provider, :additional_info) do
- :github | {}
- :twitter | {}
- :bitbucket | {}
- :gitlab | {}
- :google_oauth2 | {}
- :facebook | {}
- :cas3 | {}
- :auth0 | {}
- :authentiq | {}
- :salesforce | { extra: { email_verified: true } }
- :dingtalk | {}
- :alicloud | {}
+ where(:provider, :additional_info) do
+ :github | {}
+ :twitter | {}
+ :bitbucket | {}
+ :gitlab | {}
+ :google_oauth2 | {}
+ :facebook | {}
+ :cas3 | {}
+ :auth0 | {}
+ :authentiq | {}
+ :salesforce | { extra: { email_verified: true } }
+ :dingtalk | {}
+ :alicloud | {}
+ end
+
+ with_them do
+ before do
+ stub_omniauth_provider(provider)
+ stub_feature_flags(update_oauth_registration_flow: true)
end
- with_them do
+ context 'when block_auto_created_users is true' do
before do
- stub_omniauth_provider(provider)
- stub_feature_flags(update_oauth_registration_flow: true)
+ stub_omniauth_setting(block_auto_created_users: true)
end
- context 'when block_auto_created_users is true' do
- before do
- stub_omniauth_setting(block_auto_created_users: true)
- end
+ it 'redirects back to the sign-in page' do
+ register_via(provider, uid, email, additional_info: additional_info)
- it 'redirects back to the sign-in page' do
- register_via(provider, uid, email, additional_info: additional_info)
+ expect(page).to have_current_path new_user_session_path
+ expect(page).to have_content('Your account is pending approval')
+ end
+ end
- expect(page).to have_current_path new_user_session_path
- expect(page).to have_content('Your account is pending approval')
- end
+ context 'when block_auto_created_users is false' do
+ before do
+ stub_omniauth_setting(block_auto_created_users: false)
+ end
+
+ it 'redirects to the initial welcome path' do
+ register_via(provider, uid, email, additional_info: additional_info)
+
+ expect(page).to have_current_path users_sign_up_welcome_path
+ expect(page).to have_content('Welcome to GitLab, mockuser!')
end
- context 'when block_auto_created_users is false' do
+ context 'when terms are enforced' do
before do
- stub_omniauth_setting(block_auto_created_users: false)
+ enforce_terms
end
- it 'redirects to the initial welcome path' do
+ it 'auto accepts terms and redirects to the initial welcome path' do
register_via(provider, uid, email, additional_info: additional_info)
expect(page).to have_current_path users_sign_up_welcome_path
expect(page).to have_content('Welcome to GitLab, mockuser!')
end
+ end
- context 'when terms are enforced' do
- before do
- enforce_terms
- end
+ context 'when provider does not send a verified email address' do
+ let(:email) { 'temp-email-for-oauth@email.com' }
- it 'auto accepts terms and redirects to the initial welcome path' do
- register_via(provider, uid, email, additional_info: additional_info)
+ it 'redirects to the profile path' do
+ register_via(provider, uid, email, additional_info: additional_info)
- expect(page).to have_current_path users_sign_up_welcome_path
- expect(page).to have_content('Welcome to GitLab, mockuser!')
- end
+ expect(page).to have_current_path profile_path
+ expect(page).to have_content('Please complete your profile with email address')
end
+ end
- context 'when provider does not send a verified email address' do
- let(:email) { 'temp-email-for-oauth@email.com' }
+ context 'when registering via an invitation email' do
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'Owned') }
+ let_it_be(:project) { create(:project, :repository, namespace: group) }
+
+ let(:invite_email) { generate(:email) }
+ let(:extra_params) { { invite_type: Emails::Members::INITIAL_INVITE } }
+ let(:group_invite) do
+ create(
+ :group_member, :invited,
+ group: group,
+ invite_email: invite_email,
+ created_by: owner
+ )
+ end
- it 'redirects to the profile path' do
- register_via(provider, uid, email, additional_info: additional_info)
+ before do
+ project.add_maintainer(owner)
+ group.add_owner(owner)
+ group_invite.generate_invite_token!
- expect(page).to have_current_path profile_path
- expect(page).to have_content('Please complete your profile with email address')
- end
+ mock_auth_hash(provider, uid, invite_email, additional_info: additional_info)
end
- context 'when registering via an invitation email' do
- let_it_be(:owner) { create(:user) }
- let_it_be(:group) { create(:group, name: 'Owned') }
- let_it_be(:project) { create(:project, :repository, namespace: group) }
-
- let(:invite_email) { generate(:email) }
- let(:extra_params) { { invite_type: Emails::Members::INITIAL_INVITE } }
- let(:group_invite) do
- create(
- :group_member, :invited,
- group: group,
- invite_email: invite_email,
- created_by: owner
- )
- end
-
- before do
- project.add_maintainer(owner)
- group.add_owner(owner)
- group_invite.generate_invite_token!
-
- mock_auth_hash(provider, uid, invite_email, additional_info: additional_info)
- end
-
- it 'redirects to the activity page with all the projects/groups invitations accepted' do
- visit invite_path(group_invite.raw_invite_token, extra_params)
- click_link_or_button "oauth-login-#{provider}"
- fill_in_welcome_form
-
- expect(page).to have_content('You have been granted Owner access to group Owned.')
- expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
- end
+ it 'redirects to the activity page with all the projects/groups invitations accepted' do
+ visit invite_path(group_invite.raw_invite_token, extra_params)
+ click_link_or_button "oauth-login-#{provider}"
+ fill_in_welcome_form
+
+ expect(page).to have_content('You have been granted Owner access to group Owned.')
+ expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
end
end
end
end
+ context 'when update_oauth_registration_flow is disabled' do
+ before do
+ stub_omniauth_provider(:github)
+ stub_omniauth_setting(block_auto_created_users: false)
+ stub_feature_flags(update_oauth_registration_flow: false)
+
+ enforce_terms
+ end
+
+ it 'presents the terms page' do
+ register_via(:github, uid, email)
+
+ expect(page).to have_content('These are the terms')
+ end
+ end
+
def fill_in_welcome_form
select 'Software Developer', from: 'user_role'
click_button 'Get started!'
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 1d0db488751..6c860740354 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -51,11 +51,11 @@ RSpec.describe 'Profile > Password' do
end
context 'Password authentication unavailable' do
- before do
- gitlab_sign_in(user)
- end
-
context 'Regular user' do
+ before do
+ gitlab_sign_in(user)
+ end
+
let(:user) { create(:user) }
it 'renders 404 when password authentication is disabled for the web interface and Git' do
@@ -69,7 +69,22 @@ RSpec.describe 'Profile > Password' do
end
context 'LDAP user' do
+ include LdapHelpers
+
+ let(:ldap_settings) { { enabled: true } }
let(:user) { create(:omniauth_user, provider: 'ldapmain') }
+ let(:provider) { 'ldapmain' }
+ let(:provider_label) { 'Main LDAP' }
+
+ before do
+ stub_ldap_setting(ldap_settings)
+ stub_ldap_access(user, provider, provider_label)
+ sign_in_using_ldap!(user, provider_label, provider)
+ end
+
+ after(:all) do
+ Rails.application.reload_routes!
+ end
it 'renders 404' do
visit edit_profile_password_path
diff --git a/spec/features/profiles/two_factor_auths_spec.rb b/spec/features/profiles/two_factor_auths_spec.rb
index 9a58950b8f3..b4355f2d669 100644
--- a/spec/features/profiles/two_factor_auths_spec.rb
+++ b/spec/features/profiles/two_factor_auths_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe 'Two factor auths' do
include Spec::Support::Helpers::ModalHelpers
context 'when signed in' do
+ let(:invalid_current_pwd_msg) { 'You must provide a valid current password' }
+
before do
sign_in(user)
end
@@ -18,7 +20,7 @@ RSpec.describe 'Two factor auths' do
register_2fa(user.current_otp, '123')
- expect(page).to have_content('You must provide a valid current password')
+ expect(page).to have_selector('.gl-alert-title', text: invalid_current_pwd_msg, count: 1)
register_2fa(user.reload.current_otp, user.password)
@@ -76,7 +78,7 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable'
end
- expect(page).to have_content('You must provide a valid current password')
+ expect(page).to have_selector('.gl-alert-title', text: invalid_current_pwd_msg, count: 1)
fill_in 'current_password', with: user.password
@@ -97,7 +99,7 @@ RSpec.describe 'Two factor auths' do
click_button 'Regenerate recovery codes'
- expect(page).to have_content('You must provide a valid current password')
+ expect(page).to have_selector('.gl-alert-title', text: invalid_current_pwd_msg, count: 1)
fill_in 'current_password', with: user.password
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index d887a367fcb..56a70f37779 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -5,10 +5,9 @@ require 'spec_helper'
RSpec.describe 'User edit profile' do
include Spec::Support::Helpers::Features::NotesHelpers
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
- stub_feature_flags(remove_user_attributes_projects: false)
sign_in(user)
visit(profile_path)
end
@@ -456,6 +455,8 @@ RSpec.describe 'User edit profile' do
end
context 'Remove status button' do
+ let(:user) { create(:user) }
+
before do
user.status = UserStatus.new(message: 'Eating bread', emoji: 'stuffed_flatbread')
@@ -495,45 +496,6 @@ RSpec.describe 'User edit profile' do
expect(page).to have_emoji('speech_balloon')
end
-
- context 'note header' do
- let(:project) { create(:project_empty_repo, :public) }
- let(:issue) { create(:issue, project: project) }
- let(:emoji) { "stuffed_flatbread" }
-
- before do
- project.add_guest(user)
- create(:user_status, user: user, message: 'Taking notes', emoji: emoji)
-
- visit(project_issue_path(project, issue))
-
- add_note("This is a comment")
- visit(project_issue_path(project, issue))
-
- wait_for_requests
- end
-
- it 'displays the status emoji' do
- first_note = page.find_all(".main-notes-list .timeline-entry").first
-
- expect(first_note).to have_emoji(emoji)
- end
-
- it 'clears the status emoji' do
- open_edit_status_modal
-
- page.within "#set-user-status-modal" do
- click_button 'Remove status'
- end
-
- visit(project_issue_path(project, issue))
- wait_for_requests
-
- first_note = page.find_all(".main-notes-list .timeline-entry").first
-
- expect(first_note).not_to have_css('.user-status-emoji')
- end
- end
end
context 'User time preferences', :js do
@@ -551,13 +513,13 @@ RSpec.describe 'User edit profile' do
it 'allows the user to select a time zone from a dropdown list of options' do
expect(page.find('.user-time-preferences .dropdown')).not_to have_css('.show')
- page.find('.user-time-preferences .js-timezone-dropdown').click
+ page.find('.user-time-preferences .dropdown').click
expect(page.find('.user-time-preferences .dropdown')).to have_css('.show')
- page.find("a", text: "Nuku'alofa").click
+ page.find("button", text: "Arizona").click
- expect(page).to have_field(:user_timezone, with: 'Pacific/Tongatapu', type: :hidden)
+ expect(page).to have_field(:user_timezone, with: 'America/Phoenix', type: :hidden)
end
it 'timezone defaults to empty' do
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 13a4c1b5912..93e5be18229 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -675,7 +675,7 @@ RSpec.describe 'File blob', :js do
expect(page).to have_content('This project is licensed under the MIT License.')
# shows a learn more link
- expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
+ expect(page).to have_link('Learn more', href: 'https://opensource.org/licenses/MIT')
end
end
end
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index f198a1f42e2..5587b8abab3 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -7,8 +7,8 @@ RSpec.describe 'Editing file blob', :js do
include TreeHelper
include BlobSpecHelpers
- let(:project) { create(:project, :public, :repository) }
- let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
let(:branch) { 'master' }
let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
let(:readme_file_path) { 'README.md' }
@@ -82,6 +82,34 @@ RSpec.describe 'Editing file blob', :js do
end
end
+ context 'blob edit toolbar' do
+ toolbar_buttons = [
+ "Add bold text",
+ "Add italic text",
+ "Add strikethrough text",
+ "Insert a quote",
+ "Insert code",
+ "Add a link",
+ "Add a bullet list",
+ "Add a numbered list",
+ "Add a checklist",
+ "Add a collapsible section",
+ "Add a table"
+ ]
+
+ before do
+ visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
+ end
+
+ it "has defined set of toolbar buttons" do
+ buttons = page.all('.file-buttons .md-header-toolbar button[type="button"]')
+ expect(buttons.length).to eq(toolbar_buttons.length)
+ toolbar_buttons.each_with_index do |button_title, i|
+ expect(buttons[i]['title']).to include(button_title)
+ end
+ end
+ end
+
context 'from blob file path' do
before do
visit project_blob_path(project, tree_join(branch, file_path))
@@ -156,11 +184,14 @@ RSpec.describe 'Editing file blob', :js do
end
context 'as developer' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
let(:protected_branch) { 'protected-branch' }
- before do
+ before_all do
project.add_developer(user)
+ end
+
+ before do
project.repository.add_branch(user, protected_branch, 'master')
create(:protected_branch, project: project, name: protected_branch)
sign_in(user)
diff --git a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
deleted file mode 100644
index d2774aa74c9..00000000000
--- a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User creates new blob', :js do
- include WebIdeSpecHelpers
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :empty_repo) }
-
- before do
- stub_feature_flags(vscode_web_ide: false)
- end
-
- shared_examples 'creating a file' do
- it 'allows the user to add a new file in Web IDE' do
- visit project_path(project)
-
- click_link 'New file'
-
- wait_for_requests
-
- ide_create_new_file('dummy-file', content: "Hello world\n")
-
- ide_commit
-
- expect(page).to have_content('All changes are committed')
- expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
- end
- end
-
- describe 'as a maintainer' do
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- it_behaves_like 'creating a file'
- end
-
- describe 'as an admin' do
- let(:user) { create(:user, :admin) }
-
- before do
- sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
- end
-
- it_behaves_like 'creating a file'
- end
-
- describe 'as a developer' do
- before do
- project.add_developer(user)
- sign_in(user)
- visit project_path(project)
- end
-
- it 'does not allow pushing to the default branch' do
- expect(page).not_to have_content('New file')
- end
- end
-end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 727f9aa486e..361a07ebd0b 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe 'Branches' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
let(:repository) { project.repository }
context 'logged in as developer' do
@@ -175,7 +175,7 @@ RSpec.describe 'Branches' do
search_for_branch('fix')
expect(page).not_to have_content('fix')
- expect(all('.all-branches').last).to have_selector('li', count: 0)
+ expect(all('.all-branches', wait: false).last).to have_selector('li', count: 0)
end
end
@@ -233,7 +233,7 @@ RSpec.describe 'Branches' do
end
context 'with one or more pipeline', :js do
- let(:project) { create(:project, :public, :empty_repo) }
+ let_it_be(:project) { create(:project, :public, :empty_repo) }
before do
sha = create_file(branch_name: "branch")
diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb
index 8197fe46c7b..c96d5f5823f 100644
--- a/spec/features/projects/ci/editor_spec.rb
+++ b/spec/features/projects/ci/editor_spec.rb
@@ -135,6 +135,19 @@ RSpec.describe 'Pipeline Editor', :js do
end
end
+ describe 'Commit Form' do
+ it 'is preserved when changing tabs' do
+ find('#commit-message').set('message', clear: :backspace)
+ find('#source-branch-field').set('new_branch', clear: :backspace)
+
+ click_link 'Validate'
+ click_link 'Edit'
+
+ expect(find('#commit-message').value).to eq('message')
+ expect(find('#source-branch-field').value).to eq('new_branch')
+ end
+ end
+
describe 'Editor content' do
it 'user can reset their CI configuration' do
page.within('#source-editor-') do
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index 608511ae5a5..8d5f62d8a06 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -5,13 +5,16 @@ require 'spec_helper'
RSpec.describe 'CI Lint', :js do
include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
let(:content_selector) { '.content .view-lines' }
- before do
+ before_all do
project.add_developer(user)
+ end
+
+ before do
sign_in(user)
visit project_ci_lint_path(project)
diff --git a/spec/features/projects/environments/environment_metrics_spec.rb b/spec/features/projects/environments/environment_metrics_spec.rb
index bf0949443de..d486d8cf551 100644
--- a/spec/features/projects/environments/environment_metrics_spec.rb
+++ b/spec/features/projects/environments/environment_metrics_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Environment > Metrics' do
include PrometheusHelpers
let(:user) { create(:user) }
- let(:project) { create(:prometheus_project, :repository) }
+ let(:project) { create(:project, :with_prometheus_integration, :repository) }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:environment) { create(:environment, project: project) }
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index be4b21dfff4..dc6e496d081 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -97,6 +97,10 @@ RSpec.describe 'Environment' do
it 'does show deployments' do
expect(page).to have_link("#{build.name} (##{build.id})")
end
+
+ it 'shows a tooltip on the job name' do
+ expect(page).to have_css("[title=\"#{build.name} (##{build.id})\"].has-tooltip")
+ end
end
context 'when there is a failed deployment' do
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index b8c127f0078..24943e7dd0f 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -118,17 +118,28 @@ RSpec.describe 'Project fork' do
end
end
+ shared_examples "increments the fork counter on the source project's page" do
+ specify :sidekiq_might_not_need_inline do
+ create_forks
+
+ visit project_path(project)
+
+ expect(page).to have_css('.fork-count', text: 2)
+ end
+ end
+
it_behaves_like 'fork button on project page'
it_behaves_like 'create fork page', 'Fork project'
context 'fork form', :js do
let(:group) { create(:group) }
+ let(:group2) { create(:group) }
let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
- def submit_form
+ def submit_form(group_obj = group)
find('[data-testid="select_namespace_dropdown"]').click
- find('[data-testid="select_namespace_dropdown_search_field"]').fill_in(with: group.name)
- click_button group.name
+ find('[data-testid="select_namespace_dropdown_search_field"]').fill_in(with: group_obj.name)
+ click_button group_obj.name
click_button 'Fork project'
end
@@ -166,5 +177,41 @@ RSpec.describe 'Project fork' do
expect(page).to have_content("#{group.name} / #{fork_name}")
end
end
+
+ context 'with cache_home_panel feature flag' do
+ before do
+ create(:group_member, :maintainer, user: user, group: group2 )
+ end
+
+ context 'when caching is enabled' do
+ before do
+ stub_feature_flags(cache_home_panel: project)
+ end
+
+ it_behaves_like "increments the fork counter on the source project's page"
+ end
+
+ context 'when caching is disabled' do
+ before do
+ stub_feature_flags(cache_home_panel: false)
+ end
+
+ it_behaves_like "increments the fork counter on the source project's page"
+ end
+ end
end
end
+
+private
+
+def create_fork(group_obj = group)
+ visit project_path(project)
+ find('.fork-btn').click
+ submit_form(group_obj)
+ wait_for_requests
+end
+
+def create_forks
+ create_fork
+ create_fork(group2)
+end
diff --git a/spec/features/projects/infrastructure_registry_spec.rb b/spec/features/projects/infrastructure_registry_spec.rb
index 27d0866bc69..aab1cec8762 100644
--- a/spec/features/projects/infrastructure_registry_spec.rb
+++ b/spec/features/projects/infrastructure_registry_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe 'Infrastructure Registry' do
it 'allows you to delete a module', :aggregate_failures do
# this is still using the package copy in the UI too
click_button('Remove package')
- click_button('Delete package')
+ click_button('Permanently delete')
expect(page).to have_content 'Package deleted successfully'
expect(page).not_to have_content(terraform_module.name)
diff --git a/spec/features/projects/labels/sort_labels_spec.rb b/spec/features/projects/labels/sort_labels_spec.rb
index ecbc4b524dc..f2f1acd2348 100644
--- a/spec/features/projects/labels/sort_labels_spec.rb
+++ b/spec/features/projects/labels/sort_labels_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Sort labels', :js do
it 'sorts by date' do
click_button 'Name'
- sort_options = find('ul.dropdown-menu').all('li').collect(&:text)
+ sort_options = find('ul[role="listbox"]').all('li').collect(&:text)
expect(sort_options[0]).to eq('Name')
expect(sort_options[1]).to eq('Name, descending')
@@ -37,7 +37,7 @@ RSpec.describe 'Sort labels', :js do
expect(sort_options[4]).to eq('Updated date')
expect(sort_options[5]).to eq('Oldest updated')
- click_button 'Name, descending'
+ find('li', text: 'Name, descending').click
# assert default sorting
within '.other-labels' do
diff --git a/spec/features/projects/milestones/milestones_sorting_spec.rb b/spec/features/projects/milestones/milestones_sorting_spec.rb
index c47350fb663..5ba4289fd11 100644
--- a/spec/features/projects/milestones/milestones_sorting_spec.rb
+++ b/spec/features/projects/milestones/milestones_sorting_spec.rb
@@ -42,10 +42,10 @@ RSpec.describe 'Milestones sorting', :js do
milestones_for_sort_by.each do |sort_by, expected_milestones|
within '[data-testid=milestone_sort_by_dropdown]' do
click_button selected_sort_order
- milestones = find('.gl-new-dropdown-contents').all('.gl-new-dropdown-item-text-wrapper p').map(&:text)
+ milestones = find('ul[role="listbox"]').all('li').map(&:text)
expect(milestones).to eq(ordered_milestones)
- click_button sort_by
+ find('li', text: sort_by).click
expect(page).to have_button(sort_by)
end
diff --git a/spec/features/projects/packages_spec.rb b/spec/features/projects/packages_spec.rb
index f518cc1fc63..bbe913cf1e5 100644
--- a/spec/features/projects/packages_spec.rb
+++ b/spec/features/projects/packages_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'Packages' do
it 'allows you to delete a package' do
find('[data-testid="delete-dropdown"]').click
find('[data-testid="action-delete"]').click
- click_button('Delete package')
+ click_button('Permanently delete')
expect(page).to have_content 'Package deleted successfully'
expect(page).not_to have_content(package.name)
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index dcc46f5d223..4ed0a11da38 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -11,6 +11,10 @@ RSpec.describe 'Pipeline Schedules', :js do
let(:scope) { nil }
let!(:user) { create(:user) }
+ before do
+ stub_feature_flags(pipeline_schedules_vue: false)
+ end
+
context 'logged in as the pipeline schedule owner' do
before do
project.add_developer(user)
diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
index 250a336469c..d93c951791d 100644
--- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
@@ -735,6 +735,8 @@ RSpec.describe 'Pipeline', :js do
end
it 'displays the PipelineSchedule in an inactive state' do
+ stub_feature_flags(pipeline_schedules_vue: false)
+
visit project_pipeline_schedules_path(project)
page.click_link('Inactive')
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 51a6fbc4d36..0b43e13996f 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -860,6 +860,8 @@ RSpec.describe 'Pipeline', :js do
end
it 'displays the PipelineSchedule in an inactive state' do
+ stub_feature_flags(pipeline_schedules_vue: false)
+
visit project_pipeline_schedules_path(project)
page.click_link('Inactive')
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 404e51048bc..1190b0f3558 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -673,7 +673,7 @@ RSpec.describe 'Pipelines', :js do
end
context 'when variables are specified' do
- it 'creates a new pipeline with variables' do
+ it 'creates a new pipeline with variables', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375552' do
page.within(find("[data-testid='ci-variable-row']")) do
find("[data-testid='pipeline-form-ci-variable-key']").set('key_name')
find("[data-testid='pipeline-form-ci-variable-value']").set('value')
@@ -701,7 +701,7 @@ RSpec.describe 'Pipelines', :js do
it { expect(page).to have_content('Missing CI config file') }
- it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again' do
+ it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375552' do
stub_ci_pipeline_to_return_yaml_file
expect do
diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb
index d82c4229b71..4eb7581222e 100644
--- a/spec/features/projects/releases/user_creates_release_spec.rb
+++ b/spec/features/projects/releases/user_creates_release_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'User creates release', :js do
let_it_be(:user) { create(:user) }
let(:new_page_url) { new_project_release_path(project) }
+ let(:tag_name) { 'new-tag' }
before do
project.add_developer(user)
@@ -33,6 +34,8 @@ RSpec.describe 'User creates release', :js do
end
it 'defaults the "Create from" dropdown to the project\'s default branch' do
+ select_new_tag_name(tag_name)
+
expect(page.find('[data-testid="create-from-field"] .ref-selector button')).to have_content(project.default_branch)
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 63e0ee4a251..d9bdbf7aa1a 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
context 'for maintainer' do
let(:role) { :maintainer }
- context 'Deploy tokens' do
+ context 'Deploy tokens', :js do
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
before do
diff --git a/spec/features/projects/settings/user_changes_default_branch_spec.rb b/spec/features/projects/settings/user_changes_default_branch_spec.rb
index 84e6c50cf61..508bbcc5327 100644
--- a/spec/features/projects/settings/user_changes_default_branch_spec.rb
+++ b/spec/features/projects/settings/user_changes_default_branch_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > User changes default branch' do
- include Select2Helper
-
let(:user) { create(:user) }
before do
@@ -17,16 +15,21 @@ RSpec.describe 'Projects > Settings > User changes default branch' do
let(:project) { create(:project, :repository, namespace: user.namespace) }
it 'allows to change the default branch', :js do
+ dropdown_selector = '[data-testid="default-branch-dropdown"]'
# Otherwise, running JS may overwrite our change to project_default_branch
wait_for_requests
- select2('fix', from: '#project_default_branch')
+ expect(page).to have_selector(dropdown_selector)
+ find(dropdown_selector).click
+
+ fill_in 'Search branch', with: 'fix'
+ click_button 'fix'
page.within '#default-branch-settings' do
click_button 'Save changes'
end
- expect(find('#project_default_branch', visible: false).value).to eq 'fix'
+ expect(find("#{dropdown_selector} input", visible: false).value).to eq 'fix'
end
end
@@ -34,7 +37,7 @@ RSpec.describe 'Projects > Settings > User changes default branch' do
let(:project) { create(:project_empty_repo, namespace: user.namespace) }
it 'does not show default branch selector' do
- expect(page).not_to have_selector('#project_default_branch')
+ expect(page).not_to have_selector('[data-testid="default-branch-dropdown"]')
end
end
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 6041dca305b..23e10a36cee 100644
--- a/spec/features/projects/settings/user_transfers_a_project_spec.rb
+++ b/spec/features/projects/settings/user_transfers_a_project_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Projects > Settings > User transfers a project', :js do
let(:group) { create(:group) }
before do
- stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 120)
+ allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(120)
group.add_owner(user)
sign_in(user)
diff --git a/spec/features/projects/settings/webhooks_settings_spec.rb b/spec/features/projects/settings/webhooks_settings_spec.rb
index d525544ac15..25752bcaf45 100644
--- a/spec/features/projects/settings/webhooks_settings_spec.rb
+++ b/spec/features/projects/settings/webhooks_settings_spec.rb
@@ -48,10 +48,10 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do
expect(page).to have_content('Releases events')
end
- it 'create webhook' do
+ it 'create webhook', :js do
visit webhooks_path
- fill_in 'hook_url', with: url
+ fill_in 'URL', with: url
check 'Tag push events'
fill_in 'hook_push_events_branch_filter', with: 'master'
check 'Enable SSL verification'
@@ -66,12 +66,12 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do
expect(page).to have_content('Job events')
end
- it 'edit existing webhook' do
+ it 'edit existing webhook', :js do
hook
visit webhooks_path
click_link 'Edit'
- fill_in 'hook_url', with: url
+ fill_in 'URL', with: url
check 'Enable SSL verification'
click_button 'Save changes'
diff --git a/spec/features/projects/show/user_interacts_with_stars_spec.rb b/spec/features/projects/show/user_interacts_with_stars_spec.rb
index e0dd4f65010..158b6aa9b46 100644
--- a/spec/features/projects/show/user_interacts_with_stars_spec.rb
+++ b/spec/features/projects/show/user_interacts_with_stars_spec.rb
@@ -13,6 +13,14 @@ RSpec.describe 'Projects > Show > User interacts with project stars' do
visit(project_path(project))
end
+ it 'retains the star count even after a page reload' do
+ star_project
+
+ reload_page
+
+ expect(page).to have_css('.star-count', text: 1)
+ end
+
it 'toggles the star' do
star_project
@@ -63,6 +71,10 @@ end
private
+def reload_page
+ visit current_path
+end
+
def star_project
click_button(_('Star'))
wait_for_requests
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index 1440db141a6..c63427e56e6 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Projects > Show > Collaboration links', :js do
using RSpec::Parameterized::TableSyntax
- let(:project) { create(:project, :repository, :public) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -17,7 +17,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
end
context 'with developer user' do
- before do
+ before_all do
project.add_developer(user)
end
diff --git a/spec/features/projects/user_sorts_projects_spec.rb b/spec/features/projects/user_sorts_projects_spec.rb
index b9b28398279..c40f01f3aa1 100644
--- a/spec/features/projects/user_sorts_projects_spec.rb
+++ b/spec/features/projects/user_sorts_projects_spec.rb
@@ -24,7 +24,6 @@ RSpec.describe 'User sorts projects and order persists' do
end
it "is set on the group_canonical_path" do
- stub_feature_flags(group_overview_tabs_vue: false)
visit(group_canonical_path(group))
within '[data-testid=group_sort_by_dropdown]' do
@@ -33,7 +32,6 @@ RSpec.describe 'User sorts projects and order persists' do
end
it "is set on the details_group_path" do
- stub_feature_flags(group_overview_tabs_vue: false)
visit(details_group_path(group))
within '[data-testid=group_sort_by_dropdown]' do
@@ -42,7 +40,7 @@ RSpec.describe 'User sorts projects and order persists' do
end
end
- context "from explore projects" do
+ context "from explore projects", :js do
before do
sign_in(user)
visit(explore_projects_path)
@@ -50,10 +48,10 @@ RSpec.describe 'User sorts projects and order persists' do
first(:link, 'Updated date').click
end
- it_behaves_like "sort order persists across all views", 'Updated date', 'Updated date'
+ it_behaves_like "sort order persists across all views", 'Updated date', 'Updated'
end
- context 'from dashboard projects' do
+ context 'from dashboard projects', :js do
before do
sign_in(user)
visit(dashboard_projects_path)
@@ -66,29 +64,29 @@ RSpec.describe 'User sorts projects and order persists' do
context 'from group homepage', :js do
before do
- stub_feature_flags(group_overview_tabs_vue: false)
sign_in(user)
visit(group_canonical_path(group))
within '[data-testid=group_sort_by_dropdown]' do
find('button.gl-dropdown-toggle').click
- first(:button, 'Last created').click
+ first(:button, 'Created').click
+ wait_for_requests
end
end
- it_behaves_like "sort order persists across all views", "Created date", "Last created"
+ it_behaves_like "sort order persists across all views", "Created date", "Created"
end
context 'from group details', :js do
before do
- stub_feature_flags(group_overview_tabs_vue: false)
sign_in(user)
visit(details_group_path(group))
within '[data-testid=group_sort_by_dropdown]' do
find('button.gl-dropdown-toggle').click
- first(:button, 'Most stars').click
+ first(:button, 'Stars').click
+ wait_for_requests
end
end
- it_behaves_like "sort order persists across all views", "Stars", "Most stars"
+ it_behaves_like "sort order persists across all views", "Stars", "Stars"
end
end
diff --git a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
index fbb5c24f6e1..db2b3fc2f4b 100644
--- a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Projects > Wiki > User views wiki in project page' do
end
context 'when repository is disabled for project' do
- let_it_be(:project) do
+ let(:project) do
create(:project,
:wiki_repo,
:repository_disabled,
@@ -17,16 +17,31 @@ RSpec.describe 'Projects > Wiki > User views wiki in project page' do
end
context 'when wiki homepage contains a link' do
- before do
- create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)')
+ shared_examples 'wiki homepage contains a link' do
+ it 'displays the correct URL for the link' do
+ visit project_path(project)
+ expect(page).to have_link(
+ 'some link',
+ href: project_wiki_path(project, 'other-page')
+ )
+ end
end
- it 'displays the correct URL for the link' do
- visit project_path(project)
- expect(page).to have_link(
- 'some link',
- href: project_wiki_path(project, 'other-page')
- )
+ context 'when using markdown' do
+ before do
+ create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)')
+ end
+
+ it_behaves_like 'wiki homepage contains a link'
+ end
+
+ context 'when using asciidoc' do
+ before do
+ create(:wiki_page, wiki: project.wiki, title: 'home', content: 'link:other-page[some link]',
+ format: :asciidoc)
+ end
+
+ it_behaves_like 'wiki homepage contains a link'
end
end
end
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 389a51a10e0..174716d646d 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -183,7 +183,7 @@ RSpec.describe 'Protected Branches', :js do
end
include_examples 'Deploy keys with protected branches' do
- let(:all_dropdown_sections) { %w(Roles Deploy\ Keys) }
+ let(:all_dropdown_sections) { ['Roles', 'Deploy Keys'] }
end
end
end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 482f3d62f36..cee0910aef7 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -160,16 +160,6 @@ RSpec.describe 'Runners' do
end
context 'shared runner text' do
- context 'when application settings have no shared_runners_text' do
- it 'user sees default shared runners description' do
- visit project_runners_path(project)
-
- page.within("[data-testid='shared-runners-description']") do
- expect(page).to have_content('The same shared runner executes code from multiple projects')
- end
- end
- end
-
context 'when application settings have shared_runners_text' do
let(:shared_runners_text) { 'custom **shared** runners description' }
let(:shared_runners_html) { 'custom shared runners description' }
diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb
index e2c8708be78..50e6eb66466 100644
--- a/spec/features/search/user_searches_for_code_spec.rb
+++ b/spec/features/search/user_searches_for_code_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'User searches for code' do
context 'when signed in' do
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_maintainer(user)
sign_in(user)
end
@@ -214,6 +215,7 @@ RSpec.describe 'User searches for code' do
let(:project) { create(:project, :public, :repository) }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
visit(project_path(project))
end
diff --git a/spec/features/search/user_searches_for_comments_spec.rb b/spec/features/search/user_searches_for_comments_spec.rb
index 5185a2460dc..a6793bc3aa7 100644
--- a/spec/features/search/user_searches_for_comments_spec.rb
+++ b/spec/features/search/user_searches_for_comments_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'User searches for comments' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_reporter(user)
sign_in(user)
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index 2dceda09d7c..4ec2a9e6cff 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -3,13 +3,12 @@
require 'spec_helper'
RSpec.describe 'User searches for commits', :js do
- include CycleAnalyticsHelpers
-
let(:project) { create(:project, :repository) }
let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
let(:user) { create(:user) }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_reporter(user)
sign_in(user)
@@ -34,7 +33,12 @@ RSpec.describe 'User searches for commits', :js do
context 'when searching by message' do
it 'finds a commit and holds on /search page' do
- create_commit('Message referencing another sha: "deadbeef"', project, user, 'master')
+ project.repository.commit_files(
+ user,
+ message: 'Message referencing another sha: "deadbeef"',
+ branch_name: 'master',
+ actions: [{ action: :create, file_path: 'a/new.file', contents: 'new file' }]
+ )
submit_search('deadbeef')
diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb
index c23a54594d4..51d2f355848 100644
--- a/spec/features/search/user_searches_for_issues_spec.rb
+++ b/spec/features/search/user_searches_for_issues_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe 'User searches for issues', :js do
before do
project.add_maintainer(user)
sign_in(user)
+ stub_feature_flags(search_page_vertical_nav: false)
visit(search_path)
end
@@ -110,6 +111,7 @@ RSpec.describe 'User searches for issues', :js do
before do
stub_feature_flags(block_anonymous_global_searches: false)
+ stub_feature_flags(search_page_vertical_nav: false)
visit(search_path)
end
@@ -127,6 +129,7 @@ RSpec.describe 'User searches for issues', :js do
context 'when block_anonymous_global_searches is enabled' do
before do
+ stub_feature_flags(search_page_vertical_nav: false)
visit(search_path)
end
diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb
index 61c61d793db..a4fbe3a6e59 100644
--- a/spec/features/search/user_searches_for_merge_requests_spec.rb
+++ b/spec/features/search/user_searches_for_merge_requests_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'User searches for merge requests', :js do
end
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/search/user_searches_for_milestones_spec.rb b/spec/features/search/user_searches_for_milestones_spec.rb
index 61f2e8e0c8f..6773059830c 100644
--- a/spec/features/search/user_searches_for_milestones_spec.rb
+++ b/spec/features/search/user_searches_for_milestones_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'User searches for milestones', :js do
before do
project.add_maintainer(user)
sign_in(user)
+ stub_feature_flags(search_page_vertical_nav: false)
visit(search_path)
end
diff --git a/spec/features/search/user_searches_for_projects_spec.rb b/spec/features/search/user_searches_for_projects_spec.rb
index 562da56275c..5902859d1f5 100644
--- a/spec/features/search/user_searches_for_projects_spec.rb
+++ b/spec/features/search/user_searches_for_projects_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'User searches for projects', :js do
context 'when signed out' do
context 'when block_anonymous_global_searches is disabled' do
before do
+ stub_feature_flags(search_page_vertical_nav: false)
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit).and_return(1000)
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit_unauthenticated).and_return(1000)
stub_feature_flags(block_anonymous_global_searches: false)
diff --git a/spec/features/search/user_searches_for_users_spec.rb b/spec/features/search/user_searches_for_users_spec.rb
index a5cf12fa068..e21a66fed92 100644
--- a/spec/features/search/user_searches_for_users_spec.rb
+++ b/spec/features/search/user_searches_for_users_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'User searches for users' do
let(:user3) { create(:user, username: 'gob_2018', name: 'George Oscar Bluth') }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
sign_in(user1)
end
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index 9808383adb7..2e390309022 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'User searches for wiki pages', :js do
let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'directory/title', content: 'Some Wiki content') }
before do
+ stub_feature_flags(search_page_vertical_nav: false)
project.add_maintainer(user)
sign_in(user)
@@ -18,6 +19,10 @@ RSpec.describe 'User searches for wiki pages', :js do
include_examples 'search timeouts', 'wiki_blobs'
shared_examples 'search wiki blobs' do
+ before do
+ stub_feature_flags(search_page_vertical_nav: false)
+ end
+
it 'finds a page' do
find('[data-testid="project-filter"]').click
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 41288a34fb2..827e3984896 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe 'User uses header search field', :js do
end
before do
+ stub_feature_flags(search_page_vertical_nav: false)
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(0)
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit).and_return(1000)
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit_unauthenticated).and_return(1000)
diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb
index 46bc3b7caad..69b9a0aa64d 100644
--- a/spec/features/snippets/search_snippets_spec.rb
+++ b/spec/features/snippets/search_snippets_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe 'Search Snippets' do
+ before do
+ stub_feature_flags(search_page_vertical_nav: false)
+ end
+
it 'user searches for snippets by title' do
public_snippet = create(:personal_snippet, :public, title: 'Beginning and Middle')
private_snippet = create(:personal_snippet, :private, title: 'Middle and End')
diff --git a/spec/features/tags/developer_creates_tag_spec.rb b/spec/features/tags/developer_creates_tag_spec.rb
index ca76a94092e..5657115fb3c 100644
--- a/spec/features/tags/developer_creates_tag_spec.rb
+++ b/spec/features/tags/developer_creates_tag_spec.rb
@@ -46,18 +46,6 @@ RSpec.describe 'Developer creates tag' do
end
end
- it 'with multiline release notes parses the release note as Markdown' do
- create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world")
-
- expect(page).to have_current_path(
- project_tag_path(project, 'v4.0'), ignore_query: true)
- expect(page).to have_content 'v4.0'
- page.within '.description' do
- expect(page).to have_content 'Awesome release notes'
- expect(page).to have_selector('ul li', count: 2)
- end
- end
-
it 'opens dropdown for ref', :js do
click_link 'New tag'
ref_row = find('.form-group:nth-of-type(2) .col-sm-12')
@@ -73,19 +61,6 @@ RSpec.describe 'Developer creates tag' do
end
end
- context 'from new tag page' do
- before do
- visit new_project_tag_path(project)
- end
-
- it 'description has emoji autocomplete', :js do
- find('#release_description').native.send_keys('')
- fill_in 'release_description', with: ':'
-
- expect(page).to have_selector('.atwho-view')
- end
- end
-
def create_tag_in_form(tag:, ref:, message: nil, desc: nil)
click_link 'New tag'
fill_in 'tag_name', with: tag
diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb
index 5317f586390..12d2f0a9bb6 100644
--- a/spec/features/unsubscribe_links_spec.rb
+++ b/spec/features/unsubscribe_links_spec.rb
@@ -2,14 +2,15 @@
require 'spec_helper'
-RSpec.describe 'Unsubscribe links', :sidekiq_might_not_need_inline do
+RSpec.describe 'Unsubscribe links', :sidekiq_inline do
include Warden::Test::Helpers
- let(:recipient) { create(:user) }
- let(:author) { create(:user) }
- let(:project) { create(:project, :public) }
- let(:params) { { title: 'A bug!', description: 'Fix it!', assignees: [recipient] } }
- let(:issue) { Issues::CreateService.new(project: project, current_user: author, params: params, spam_params: nil).execute }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:author) { create(:user).tap { |u| project.add_reporter(u) } }
+ let_it_be(:recipient) { create(:user) }
+
+ let(:params) { { title: 'A bug!', description: 'Fix it!', assignee_ids: [recipient.id] } }
+ let(:issue) { Issues::CreateService.new(project: project, current_user: author, params: params, spam_params: nil).execute[:issue] }
let(:mail) { ActionMailer::Base.deliveries.last }
let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) }
diff --git a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
index cbd2d30d726..02f9d57fcfe 100644
--- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe 'User uploads avatar to profile' do
wait_for_all_requests
- data_uri = find('.avatar-image .avatar')['src']
+ data_uri = find('.avatar-image .gl-avatar')['src']
expect(page.find('.header-user-avatar')['src']).to eq data_uri
expect(page.find('[data-testid="sidebar-user-avatar"]')['src']).to eq data_uri
end
diff --git a/spec/features/user_opens_link_to_comment_spec.rb b/spec/features/user_opens_link_to_comment_spec.rb
index 3fb1505ff5b..59dea91c666 100644
--- a/spec/features/user_opens_link_to_comment_spec.rb
+++ b/spec/features/user_opens_link_to_comment_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'User opens link to comment', :js do
wait_for_requests
- expect(find('#discussion-preferences-dropdown')).to have_content('Sort or filter')
+ expect(find('#discussion-preferences-dropdown')).to have_content(_('Sort or filter'))
expect(page).not_to have_content('Something went wrong while fetching comments')
# Auto-switching to show all notes shouldn't be persisted
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index de53e722603..9b1a102f07b 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -349,7 +349,6 @@ RSpec.describe 'Signup' do
end
it 'redirects to step 2 of the signup process, sets the role and redirects back' do
- stub_feature_flags(about_your_company_registration_flow: false)
visit new_user_registration_path
fill_in_signup_form
diff --git a/spec/features/work_items/work_item_spec.rb b/spec/features/work_items/work_item_spec.rb
new file mode 100644
index 00000000000..686b82de868
--- /dev/null
+++ b/spec/features/work_items/work_item_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Work item', :js do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:work_item) { create(:work_item, project: project) }
+
+ context 'for signed in user' do
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+
+ visit project_work_items_path(project, work_items_path: work_item.id)
+ end
+
+ context 'in work item description' do
+ it 'shows GFM autocomplete', :aggregate_failures do
+ click_button "Edit description"
+
+ find('[aria-label="Description"]').send_keys("@#{user.username}")
+
+ wait_for_requests
+
+ page.within('.atwho-container') do
+ expect(page).to have_text(user.name)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index 8d3c375385a..18eecd0f073 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -319,6 +319,17 @@ RSpec.describe Ci::RunnersFinder do
end
end
+ context 'with :all_available membership' do
+ let(:membership) { :all_available }
+
+ it 'returns runners available to group' do
+ expect(subject).to match_array([runner_project_7, runner_project_6, runner_project_5,
+ runner_project_4, runner_project_3, runner_project_2,
+ runner_project_1, runner_sub_group_4, runner_sub_group_3,
+ runner_sub_group_2, runner_sub_group_1, runner_group, runner_instance])
+ end
+ end
+
context 'with unknown membership' do
let(:membership) { :unsupported }
@@ -400,11 +411,31 @@ RSpec.describe Ci::RunnersFinder do
with_them do
before do
- create(:group_member, user_permission, group: group, user: user)
+ create(:group_member, user_permission, group: sub_group_1, user: user)
+ end
+
+ context 'with :sub_group_1 as target group' do
+ let(:target_group) { sub_group_1 }
+
+ it 'returns no runners' do
+ is_expected.to be_empty
+ end
end
- it 'returns no runners' do
- expect(subject).to be_empty
+ context 'with :group as target group' do
+ let(:target_group) { group }
+
+ it 'returns no runners' do
+ is_expected.to be_empty
+ end
+
+ context 'with :all_available membership' do
+ let(:membership) { :all_available }
+
+ it 'returns no runners' do
+ expect(subject).to be_empty
+ end
+ end
end
end
end
diff --git a/spec/finders/clusters/agent_authorizations_finder_spec.rb b/spec/finders/clusters/agent_authorizations_finder_spec.rb
index 687906db0d7..2d90f32adc5 100644
--- a/spec/finders/clusters/agent_authorizations_finder_spec.rb
+++ b/spec/finders/clusters/agent_authorizations_finder_spec.rb
@@ -9,6 +9,10 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
let_it_be(:subgroup2) { create(:group, parent: subgroup1) }
let_it_be(:bottom_level_group) { create(:group, parent: subgroup2) }
+ let_it_be(:non_ancestor_group) { create(:group, parent: top_level_group) }
+ let_it_be(:non_ancestor_project) { create(:project, namespace: non_ancestor_group) }
+ let_it_be(:non_ancestor_agent) { create(:cluster_agent, project: non_ancestor_project) }
+
let_it_be(:agent_configuration_project) { create(:project, namespace: subgroup1) }
let_it_be(:requesting_project, reload: true) { create(:project, namespace: bottom_level_group) }
@@ -56,6 +60,20 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
it { is_expected.to be_empty }
end
+ context 'agent configuration project shares a root namespace, but does not belong to an ancestor of the given project' do
+ let!(:project_authorization) { create(:agent_project_authorization, agent: non_ancestor_agent, project: requesting_project) }
+
+ it { is_expected.to match_array([project_authorization]) }
+
+ context 'agent_authorization_include_descendants feature flag is disabled' do
+ before do
+ stub_feature_flags(agent_authorization_include_descendants: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+
context 'with project authorizations present' do
let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project) }
@@ -116,6 +134,20 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
end
end
+ context 'agent configuration project does not belong to an ancestor of the authorized group' do
+ let!(:group_authorization) { create(:agent_group_authorization, agent: non_ancestor_agent, group: bottom_level_group) }
+
+ it { is_expected.to match_array([group_authorization]) }
+
+ context 'agent_authorization_include_descendants feature flag is disabled' do
+ before do
+ stub_feature_flags(agent_authorization_include_descendants: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+
it_behaves_like 'access_as' do
let!(:authorization) { create(:agent_group_authorization, agent: production_agent, group: top_level_group, config: config) }
end
diff --git a/spec/finders/groups/accepting_group_transfers_finder_spec.rb b/spec/finders/groups/accepting_group_transfers_finder_spec.rb
index 1a6c6f9243b..06e6fa05892 100644
--- a/spec/finders/groups/accepting_group_transfers_finder_spec.rb
+++ b/spec/finders/groups/accepting_group_transfers_finder_spec.rb
@@ -117,19 +117,6 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do
expect(result).to contain_exactly(great_grandparent_group)
end
end
-
- context 'when the feature flag `include_groups_from_group_shares_in_group_transfer_locations` is turned off' do
- before do
- stub_feature_flags(include_groups_from_group_shares_in_group_transfer_locations: false)
- end
-
- it 'excludes the groups where the user has OWNER access through group shares' do
- expect(result).not_to include(
- shared_with_group_where_direct_owner_as_owner,
- subgroup_of_shared_with_group_where_direct_owner_as_owner
- )
- end
- end
end
end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index deeca6132e0..349ffd09324 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -228,9 +228,9 @@ RSpec.describe MergeRequestsFinder do
end
describe ':label_name parameter' do
- let(:common_labels) { create_list(:label, 3) }
- let(:distinct_labels) { create_list(:label, 3) }
- let(:merge_requests) do
+ let_it_be(:common_labels) { create_list(:label, 3) }
+ let_it_be(:distinct_labels) { create_list(:label, 3) }
+ let_it_be(:merge_requests) do
common_attrs = {
source_project: project1, target_project: project1, author: user
}
@@ -496,20 +496,15 @@ RSpec.describe MergeRequestsFinder do
context 'filtering by approved by username' do
let(:params) { { approved_by_usernames: user2.username } }
+ where(:sort) { [nil] + %w(milestone merged_at merged_at_desc closed_at closed_at_desc) }
+
before do
create(:approval, merge_request: merge_request3, user: user2)
end
- it 'returns merge requests approved by that user' do
- merge_requests = described_class.new(user, params).execute
-
- expect(merge_requests).to contain_exactly(merge_request3)
- end
-
- context 'with sorting by milestone' do
- let(:params) { { approved_by_usernames: user2.username, sort: 'milestone' } }
-
+ with_them do
it 'returns merge requests approved by that user' do
+ params = { approved_by_usernames: user2.username, sort: sort }
merge_requests = described_class.new(user, params).execute
expect(merge_requests).to contain_exactly(merge_request3)
@@ -566,7 +561,7 @@ RSpec.describe MergeRequestsFinder do
end
context 'filtering by created_at/updated_at' do
- let(:new_project) { create(:project, forked_from_project: project1) }
+ let_it_be(:new_project) { create(:project, forked_from_project: project1) }
let!(:new_merge_request) do
create(:merge_request,
@@ -589,7 +584,7 @@ RSpec.describe MergeRequestsFinder do
target_project: new_project)
end
- before do
+ before_all do
new_project.add_maintainer(user)
end
@@ -651,10 +646,10 @@ RSpec.describe MergeRequestsFinder do
end
context 'filtering by the merge request deployments' do
- let(:gstg) { create(:environment, project: project4, name: 'gstg') }
- let(:gprd) { create(:environment, project: project4, name: 'gprd') }
+ let_it_be(:gstg) { create(:environment, project: project4, name: 'gstg') }
+ let_it_be(:gprd) { create(:environment, project: project4, name: 'gprd') }
- let(:mr1) do
+ let_it_be(:mr1) do
create(
:merge_request,
:simple,
@@ -665,7 +660,7 @@ RSpec.describe MergeRequestsFinder do
)
end
- let(:mr2) do
+ let_it_be(:mr2) do
create(
:merge_request,
:simple,
@@ -676,7 +671,7 @@ RSpec.describe MergeRequestsFinder do
)
end
- let(:deploy1) do
+ let_it_be(:deploy1) do
create(
:deployment,
:success,
@@ -688,7 +683,7 @@ RSpec.describe MergeRequestsFinder do
)
end
- let(:deploy2) do
+ let_it_be(:deploy2) do
create(
:deployment,
:success,
@@ -700,7 +695,7 @@ RSpec.describe MergeRequestsFinder do
)
end
- before do
+ before_all do
deploy1.link_merge_requests(MergeRequest.where(id: mr1.id))
deploy2.link_merge_requests(MergeRequest.where(id: mr2.id))
end
@@ -838,13 +833,13 @@ RSpec.describe MergeRequestsFinder do
end
context 'when projects require different access levels for merge requests' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
- let(:public_project) { create(:project, :public) }
- let(:internal) { create(:project, :internal) }
- let(:private_project) { create(:project, :private) }
- let(:public_with_private_repo) { create(:project, :public, :repository, :repository_private) }
- let(:internal_with_private_repo) { create(:project, :internal, :repository, :repository_private) }
+ let_it_be(:public_project) { create(:project, :public) }
+ let_it_be(:internal) { create(:project, :internal) }
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:public_with_private_repo) { create(:project, :public, :repository, :repository_private) }
+ let_it_be(:internal_with_private_repo) { create(:project, :internal, :repository, :repository_private) }
let(:merge_requests) { described_class.new(user, {}).execute }
@@ -855,7 +850,7 @@ RSpec.describe MergeRequestsFinder do
let!(:mr_internal_private_repo_access) { create(:merge_request, source_project: internal_with_private_repo) }
context 'with admin user' do
- let(:user) { create(:user, :admin) }
+ let_it_be(:user) { create(:user, :admin) }
context 'when admin mode is enabled', :enable_admin_mode do
it 'returns all merge requests' do
@@ -973,7 +968,7 @@ RSpec.describe MergeRequestsFinder do
let_it_be(:labels) { create_list(:label, 2, project: project) }
let_it_be(:merge_requests) { create_list(:merge_request, 4, :unique_branches, author: user, target_project: project, source_project: project, labels: labels) }
- before do
+ before_all do
project.add_developer(user)
end
diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb
index 415bf796a72..6a6eebca778 100644
--- a/spec/finders/packages/nuget/package_finder_spec.rb
+++ b/spec/finders/packages/nuget/package_finder_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Packages::Nuget::PackageFinder do
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project) { create(:project, namespace: subgroup) }
let_it_be_with_refind(:package1) { create(:nuget_package, project: project) }
- let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0', project: project) }
+ let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0-ABC', project: project) }
let_it_be(:package3) { create(:nuget_package, name: 'Another.Dummy.Package', project: project) }
let_it_be(:other_package_1) { create(:nuget_package, name: package1.name, version: package1.version) }
let_it_be(:other_package_2) { create(:nuget_package, name: package1.name, version: package2.version) }
@@ -43,7 +43,13 @@ RSpec.describe Packages::Nuget::PackageFinder do
end
context 'with valid version' do
- let(:package_version) { '2.0.0' }
+ let(:package_version) { '2.0.0-ABC' }
+
+ it { is_expected.to match_array([package2]) }
+ end
+
+ context 'with varying case version' do
+ let(:package_version) { '2.0.0-abC' }
it { is_expected.to match_array([package2]) }
end
diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb
index f22bff62082..21380cb6632 100644
--- a/spec/finders/personal_access_tokens_finder_spec.rb
+++ b/spec/finders/personal_access_tokens_finder_spec.rb
@@ -7,6 +7,50 @@ RSpec.describe PersonalAccessTokensFinder do
described_class.new(options, current_user)
end
+ describe '# searches PATs' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:time_token) do
+ create(:personal_access_token, created_at: DateTime.new(2022, 01, 02),
+ last_used_at: DateTime.new(2022, 01, 02))
+ end
+
+ let_it_be(:name_token) { create(:personal_access_token, name: 'test_1') }
+
+ let_it_be(:impersonated_token) do
+ create(:personal_access_token, :impersonation,
+ created_at: DateTime.new(2022, 01, 02),
+ last_used_at: DateTime.new(2022, 01, 02),
+ name: 'imp_token'
+ )
+ end
+
+ shared_examples 'finding tokens by user and options' do
+ subject { finder(option, user).execute }
+
+ it 'finds exactly' do
+ subject
+
+ is_expected.to contain_exactly(*result)
+ end
+ end
+
+ context 'by' do
+ where(:option, :user, :result) do
+ { created_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
+ { created_after: DateTime.new(2022, 01, 01) } | create(:admin) | lazy { [time_token, name_token, impersonated_token] }
+ { last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
+ { last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
+ { impersonation: true } | create(:admin) | lazy { [impersonated_token] }
+ { search: 'test' } | create(:admin) | lazy { [name_token] }
+ end
+
+ with_them do
+ it_behaves_like 'finding tokens by user and options'
+ end
+ end
+ end
+
describe '#execute' do
let(:user) { create(:user) }
let(:params) { {} }
diff --git a/spec/fixtures/api/schemas/board.json b/spec/fixtures/api/schemas/board.json
deleted file mode 100644
index 7c146647948..00000000000
--- a/spec/fixtures/api/schemas/board.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "type": "object",
- "required" : [
- "id"
- ],
- "properties" : {
- "id": { "type": "integer" },
- "name": { "type": "string" }
- }
-}
diff --git a/spec/fixtures/api/schemas/boards.json b/spec/fixtures/api/schemas/boards.json
deleted file mode 100644
index 117564ef77a..00000000000
--- a/spec/fixtures/api/schemas/boards.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "type": "array",
- "items": { "$ref": "board.json" }
-}
diff --git a/spec/fixtures/api/schemas/current-board.json b/spec/fixtures/api/schemas/current-board.json
deleted file mode 100644
index 2ddc038e908..00000000000
--- a/spec/fixtures/api/schemas/current-board.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "type": "object",
- "allOf": [
- { "$ref": "board.json" },
- {
- "required" : [
- "id",
- "name"
- ],
- "properties": {
- "id": { "type": "integer" },
- "name": { "type": "string" }
- }
- }
- ]
-}
diff --git a/spec/fixtures/api/schemas/ml/get_experiment.json b/spec/fixtures/api/schemas/ml/get_experiment.json
index cf8da7f999f..482455a89e1 100644
--- a/spec/fixtures/api/schemas/ml/get_experiment.json
+++ b/spec/fixtures/api/schemas/ml/get_experiment.json
@@ -6,18 +6,31 @@
"properties": {
"experiment": {
"type": "object",
- "required" : [
+ "required": [
"experiment_id",
"name",
"artifact_location",
"lifecycle_stage"
],
- "properties" : {
- "experiment_id": { "type": "string" },
- "name": { "type": "string" },
- "artifact_location": { "type": "string" },
- "lifecycle_stage": { "type": { "enum" : ["active", "deleted"] } }
+ "properties": {
+ "experiment_id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "artifact_location": {
+ "type": "string"
+ },
+ "lifecycle_stage": {
+ "type": {
+ "enum": [
+ "active",
+ "deleted"
+ ]
+ }
+ }
}
}
}
-}
+} \ No newline at end of file
diff --git a/spec/fixtures/api/schemas/ml/list_experiments.json b/spec/fixtures/api/schemas/ml/list_experiments.json
new file mode 100644
index 00000000000..4c3e834abc6
--- /dev/null
+++ b/spec/fixtures/api/schemas/ml/list_experiments.json
@@ -0,0 +1,39 @@
+{
+ "type": "object",
+ "required": [
+ "experiments"
+ ],
+ "properties": {
+ "experiments": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "experiment_id",
+ "name",
+ "artifact_location",
+ "lifecycle_stage"
+ ],
+ "properties": {
+ "experiment_id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "artifact_location": {
+ "type": "string"
+ },
+ "lifecycle_stage": {
+ "type": {
+ "enum": [
+ "active",
+ "deleted"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/fixtures/api/schemas/public_api/v4/user/admin.json b/spec/fixtures/api/schemas/public_api/v4/user/admin.json
index 8d06e16848f..f0d3cf3ba0e 100644
--- a/spec/fixtures/api/schemas/public_api/v4/user/admin.json
+++ b/spec/fixtures/api/schemas/public_api/v4/user/admin.json
@@ -4,6 +4,7 @@
"id",
"username",
"email",
+ "commit_email",
"name",
"state",
"avatar_url",
@@ -12,6 +13,7 @@
"is_admin",
"bio",
"location",
+ "pronouns",
"skype",
"linkedin",
"twitter",
diff --git a/spec/fixtures/ci_secure_files/sample.cer b/spec/fixtures/ci_secure_files/sample.cer
new file mode 100644
index 00000000000..9cca06d53c9
--- /dev/null
+++ b/spec/fixtures/ci_secure_files/sample.cer
Binary files differ
diff --git a/spec/fixtures/ci_secure_files/sample.mobileprovision b/spec/fixtures/ci_secure_files/sample.mobileprovision
new file mode 100644
index 00000000000..89bf7246b75
--- /dev/null
+++ b/spec/fixtures/ci_secure_files/sample.mobileprovision
Binary files differ
diff --git a/spec/fixtures/ci_secure_files/sample.p12 b/spec/fixtures/ci_secure_files/sample.p12
new file mode 100644
index 00000000000..c74df26a8d4
--- /dev/null
+++ b/spec/fixtures/ci_secure_files/sample.p12
Binary files differ
diff --git a/spec/fixtures/git-cheat-sheet.pdf b/spec/fixtures/git-cheat-sheet.pdf
deleted file mode 100644
index 5ef905c0889..00000000000
--- a/spec/fixtures/git-cheat-sheet.pdf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:35967a21e5d856eaea89d2e5dd55a5e3b5f4e1e4efe3b000ef6d60b31600f1d2
-size 7352215
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index f3fc69e4936..a03177ba85e 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -6957,6 +6957,12 @@
"duration": null,
"source": "push",
"merge_request_id": null,
+ "pipeline_metadata": {
+ "id": 2,
+ "pipeline_id": 36,
+ "project_id": 5,
+ "title": "Build pipeline"
+ },
"notes": [
{
"id": 2147483547,
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/ci_pipelines.ndjson b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/ci_pipelines.ndjson
index a9d04ec5d6d..0c19f23cc24 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/ci_pipelines.ndjson
+++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/ci_pipelines.ndjson
@@ -1,7 +1,7 @@
{"id":19,"project_id":5,"ref":"master","sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.763Z","updated_at":"2016-03-22T15:20:35.763Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"stages":[{"id":24,"project_id":5,"pipeline_id":40,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":79,"project_id":5,"status":"failed","finished_at":"2016-03-29T06:28:12.695Z","trace":"Sed culpa est et facere saepe vel id ab. Quas temporibus aut similique dolorem consequatur corporis aut praesentium. Cum officia molestiae sit earum excepturi.\n\nSint possimus aut ratione quia. Quis nesciunt ratione itaque illo. Tenetur est dolor assumenda possimus voluptatem quia minima. Accusamus reprehenderit ut et itaque non reiciendis incidunt.\n\nRerum suscipit quibusdam dolore nam omnis. Consequatur ipsa nihil ut enim blanditiis delectus. Nulla quis hic occaecati mollitia qui placeat. Quo rerum sed perferendis a accusantium consequatur commodi ut. Sit quae et cumque vel eius tempora nostrum.\n\nUllam dolorem et itaque sint est. Ea molestias quia provident dolorem vitae error et et. Ea expedita officiis iste non. Qui vitae odit saepe illum. Dolores enim ratione deserunt tempore expedita amet non neque.\n\nEligendi asperiores voluptatibus omnis repudiandae expedita distinctio qui aliquid. Autem aut doloremque distinctio ab. Nostrum sapiente repudiandae aspernatur ea et quae voluptas. Officiis perspiciatis nisi laudantium asperiores error eligendi ab. Eius quia amet magni omnis exercitationem voluptatum et.\n\nVoluptatem ullam labore quas dicta est ex voluptas. Pariatur ea modi voluptas consequatur dolores perspiciatis similique. Numquam in distinctio perspiciatis ut qui earum. Quidem omnis mollitia facere aut beatae. Ea est iure et voluptatem.","created_at":"2016-03-22T15:20:35.950Z","updated_at":"2016-03-29T06:28:12.696Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":40,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null},{"id":80,"project_id":5,"status":"success","finished_at":null,"trace":"Impedit et optio nemo ipsa. Non ad non quis ut sequi laudantium omnis velit. Corporis a enim illo eos. Quia totam tempore inventore ad est.\n\nNihil recusandae cupiditate eaque voluptatem molestias sint. Consequatur id voluptatem cupiditate harum. Consequuntur iusto quaerat reiciendis aut autem libero est. Quisquam dolores veritatis rerum et sint maxime ullam libero. Id quas porro ut perspiciatis rem amet vitae.\n\nNemo inventore minus blanditiis magnam. Modi consequuntur nostrum aut voluptatem ex. Sunt rerum rem optio mollitia qui aliquam officiis officia. Aliquid eos et id aut minus beatae reiciendis.\n\nDolores non in temporibus dicta. Fugiat voluptatem est aspernatur expedita voluptatum nam qui. Quia et eligendi sit quae sint tempore exercitationem eos. Est sapiente corrupti quidem at. Qui magni odio repudiandae saepe tenetur optio dolore.\n\nEos placeat soluta at dolorem adipisci provident. Quo commodi id reprehenderit possimus quo tenetur. Ipsum et quae eligendi laborum. Et qui nesciunt at quasi quidem voluptatem cum rerum. Excepturi non facilis aut sunt vero sed.\n\nQui explicabo ratione ut eligendi recusandae. Quis quasi quas molestiae consequatur voluptatem et voluptatem. Ex repellat saepe occaecati aperiam ea eveniet dignissimos facilis.","created_at":"2016-03-22T15:20:35.966Z","updated_at":"2016-03-22T15:20:35.966Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":40,"commands":"$ build command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]}]}
{"id":20,"project_id":5,"ref":"master","sha":"ce84140e8b878ce6e7c4d298c7202ff38170e3ac","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.763Z","updated_at":"2016-03-22T15:20:35.763Z","tag":false,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"stages":[],"source":"external_pull_request_event","external_pull_request":{"id":3,"pull_request_iid":4,"source_branch":"feature","target_branch":"master","source_repository":"the-repository","target_repository":"the-repository","source_sha":"ce84140e8b878ce6e7c4d298c7202ff38170e3ac","target_sha":"a09386439ca39abe575675ffd4b89ae824fec22f","status":"open","created_at":"2016-03-22T15:20:35.763Z","updated_at":"2016-03-22T15:20:35.763Z"}}
{"id":26,"project_id":5,"ref":"master","sha":"048721d90c449b244b7b4c53a9186b04330174ec","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.757Z","updated_at":"2016-03-22T15:20:35.757Z","tag":false,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"source":"merge_request_event","merge_request_id":27,"stages":[{"id":21,"project_id":5,"pipeline_id":37,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":74,"project_id":5,"status":"success","finished_at":null,"trace":"Ad ut quod repudiandae iste dolor doloribus. Adipisci consequuntur deserunt omnis quasi eveniet et sed fugit. Aut nemo omnis molestiae impedit ex consequatur ducimus. Voluptatum exercitationem quia aut est et hic dolorem.\n\nQuasi repellendus et eaque magni eum facilis. Dolorem aperiam nam nihil pariatur praesentium ad aliquam. Commodi enim et eos tenetur. Odio voluptatibus laboriosam mollitia rerum exercitationem magnam consequuntur. Tenetur ea vel eum corporis.\n\nVoluptatibus optio in aliquid est voluptates. Ad a ut ab placeat vero blanditiis. Earum aspernatur quia beatae expedita voluptatem dignissimos provident. Quis minima id nemo ut aut est veritatis provident.\n\nRerum voluptatem quidem eius maiores magnam veniam. Voluptatem aperiam aut voluptate et nulla deserunt voluptas. Quaerat aut accusantium laborum est dolorem architecto reiciendis. Aliquam asperiores doloribus omnis maxime enim nesciunt. Eum aut rerum repellendus debitis et ut eius.\n\nQuaerat assumenda ea sit consequatur autem in. Cum eligendi voluptatem quo sed. Ut fuga iusto cupiditate autem sint.\n\nOfficia totam officiis architecto corporis molestiae amet ut. Tempora sed dolorum rerum omnis voluptatem accusantium sit eum. Quia debitis ipsum quidem aliquam inventore sunt consequatur qui.","created_at":"2016-03-22T15:20:35.846Z","updated_at":"2016-03-22T15:20:35.846Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":37,"commands":"$ build command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null},{"id":73,"project_id":5,"status":"canceled","finished_at":null,"trace":null,"created_at":"2016-03-22T15:20:35.842Z","updated_at":"2016-03-22T15:20:35.842Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":37,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]}],"merge_request":{"id":27,"target_branch":"feature","source_branch":"feature_conflict","source_project_id":2147483547,"author_id":1,"assignee_id":null,"title":"MR1","created_at":"2016-06-14T15:02:36.568Z","updated_at":"2016-06-14T15:02:56.815Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":9,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"diff_head_sha":"HEAD","source_branch_sha":"ABCD","target_branch_sha":"DCBA","merge_params":{"force_remove_source_branch":null}}}
-{"id":36,"project_id":5,"ref":null,"sha":"sha-notes","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.755Z","updated_at":"2016-03-22T15:20:35.755Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"user_id":2147483547,"duration":null,"source":"push","merge_request_id":null,"notes":[{"id":2147483547,"note":"Natus rerum qui dolorem dolorum voluptas.","noteable_type":"Commit","author_id":1,"created_at":"2016-03-22T15:19:59.469Z","updated_at":"2016-03-22T15:19:59.469Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":"be93687618e4b132087f430a4d8fc3a609c9b77c","noteable_id":36,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"}}],"stages":[{"id":11,"project_id":5,"pipeline_id":36,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":71,"project_id":5,"status":"failed","finished_at":"2016-03-29T06:28:12.630Z","trace":null,"created_at":"2016-03-22T15:20:35.772Z","updated_at":"2016-03-29T06:28:12.634Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":36,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":{"image":"busybox:latest"},"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"stage_id":11,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null,"type":"Ci::Build","token":"abcd","artifacts_file_store":1,"artifacts_metadata_store":1,"artifacts_size":10},{"id":72,"project_id":5,"status":"success","finished_at":null,"trace":"Porro ea qui ut dolores. Labore ab nemo explicabo aspernatur quis voluptates corporis. Et quasi delectus est sit aperiam perspiciatis asperiores. Repudiandae cum aut consectetur accusantium officia sunt.\n\nQuidem dolore iusto quaerat ut aut inventore et molestiae. Libero voluptates atque nemo qui. Nulla temporibus ipsa similique facere.\n\nAliquam ipsam perferendis qui fugit accusantium omnis id voluptatum. Dignissimos aliquid dicta eos voluptatem assumenda quia. Sed autem natus unde dolor et non nisi et. Consequuntur nihil consequatur rerum est.\n\nSimilique neque est iste ducimus qui fuga cupiditate. Libero autem est aut fuga. Consectetur natus quis non ducimus ut dolore. Magni voluptatibus eius et maxime aut.\n\nAd officiis tempore voluptate vitae corrupti explicabo labore est. Consequatur expedita et sunt nihil aut. Deleniti porro iusto molestiae et beatae.\n\nDeleniti modi nulla qui et labore sequi corrupti. Qui voluptatem assumenda eum cupiditate et. Nesciunt ipsam ut ea possimus eum. Consectetur quidem suscipit atque dolore itaque voluptatibus et cupiditate.","created_at":"2016-03-22T15:20:35.777Z","updated_at":"2016-03-22T15:20:35.777Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":36,"commands":"$ deploy command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"deploy","trigger_request_id":null,"stage_idx":1,"stage_id":12,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]},{"id":12,"project_id":5,"pipeline_id":36,"name":"deploy","status":2,"created_at":"2016-03-22T15:45:45.772Z","updated_at":"2016-03-29T06:45:45.634Z"}]}
+{"id":36,"project_id":5,"ref":null,"sha":"sha-notes","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.755Z","updated_at":"2016-03-22T15:20:35.755Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"user_id":2147483547,"duration":null,"source":"push","merge_request_id":null,"pipeline_metadata": {"id": 2, "project_id": 5, "pipeline_id": 36, "title": "Build pipeline"},"notes":[{"id":2147483547,"note":"Natus rerum qui dolorem dolorum voluptas.","noteable_type":"Commit","author_id":1,"created_at":"2016-03-22T15:19:59.469Z","updated_at":"2016-03-22T15:19:59.469Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":"be93687618e4b132087f430a4d8fc3a609c9b77c","noteable_id":36,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"}}],"stages":[{"id":11,"project_id":5,"pipeline_id":36,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":71,"project_id":5,"status":"failed","finished_at":"2016-03-29T06:28:12.630Z","trace":null,"created_at":"2016-03-22T15:20:35.772Z","updated_at":"2016-03-29T06:28:12.634Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":36,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":{"image":"busybox:latest"},"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"stage_id":11,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null,"type":"Ci::Build","token":"abcd","artifacts_file_store":1,"artifacts_metadata_store":1,"artifacts_size":10},{"id":72,"project_id":5,"status":"success","finished_at":null,"trace":"Porro ea qui ut dolores. Labore ab nemo explicabo aspernatur quis voluptates corporis. Et quasi delectus est sit aperiam perspiciatis asperiores. Repudiandae cum aut consectetur accusantium officia sunt.\n\nQuidem dolore iusto quaerat ut aut inventore et molestiae. Libero voluptates atque nemo qui. Nulla temporibus ipsa similique facere.\n\nAliquam ipsam perferendis qui fugit accusantium omnis id voluptatum. Dignissimos aliquid dicta eos voluptatem assumenda quia. Sed autem natus unde dolor et non nisi et. Consequuntur nihil consequatur rerum est.\n\nSimilique neque est iste ducimus qui fuga cupiditate. Libero autem est aut fuga. Consectetur natus quis non ducimus ut dolore. Magni voluptatibus eius et maxime aut.\n\nAd officiis tempore voluptate vitae corrupti explicabo labore est. Consequatur expedita et sunt nihil aut. Deleniti porro iusto molestiae et beatae.\n\nDeleniti modi nulla qui et labore sequi corrupti. Qui voluptatem assumenda eum cupiditate et. Nesciunt ipsam ut ea possimus eum. Consectetur quidem suscipit atque dolore itaque voluptatibus et cupiditate.","created_at":"2016-03-22T15:20:35.777Z","updated_at":"2016-03-22T15:20:35.777Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":36,"commands":"$ deploy command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"deploy","trigger_request_id":null,"stage_idx":1,"stage_id":12,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]},{"id":12,"project_id":5,"pipeline_id":36,"name":"deploy","status":2,"created_at":"2016-03-22T15:45:45.772Z","updated_at":"2016-03-29T06:45:45.634Z"}]}
{"id":38,"iid":1,"project_id":5,"ref":"master","sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.759Z","updated_at":"2016-03-22T15:20:35.759Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"stages":[{"id":22,"project_id":5,"pipeline_id":38,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":76,"project_id":5,"status":"success","finished_at":null,"trace":"Et rerum quia ea cumque ut modi non. Libero eaque ipsam architecto maiores expedita deleniti. Ratione quia qui est id.\n\nQuod sit officiis sed unde inventore veniam quisquam velit. Ea harum cum quibusdam quisquam minima quo possimus non. Temporibus itaque aliquam aut rerum veritatis at.\n\nMagnam ipsum eius recusandae qui quis sit maiores eum. Et animi iusto aut itaque. Doloribus harum deleniti nobis accusantium et libero.\n\nRerum fuga perferendis magni commodi officiis id repudiandae. Consequatur ratione consequatur suscipit facilis sunt iure est dicta. Qui unde quasi facilis et quae nesciunt. Magnam iste et nobis officiis tenetur. Aspernatur quo et temporibus non in.\n\nNisi rerum velit est ad enim sint molestiae consequuntur. Quaerat nisi nesciunt quasi officiis. Possimus non blanditiis laborum quos.\n\nRerum laudantium facere animi qui. Ipsa est iusto magnam nihil. Enim omnis occaecati non dignissimos ut recusandae eum quasi. Qui maxime dolor et nemo voluptates incidunt quia.","created_at":"2016-03-22T15:20:35.882Z","updated_at":"2016-03-22T15:20:35.882Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":38,"commands":"$ build command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null},{"id":75,"project_id":5,"status":"failed","finished_at":null,"trace":"Sed et iste recusandae dicta corporis. Sunt alias porro fugit sunt. Fugiat omnis nihil dignissimos aperiam explicabo doloremque sit aut. Harum fugit expedita quia rerum ut consequatur laboriosam aliquam.\n\nNatus libero ut ut tenetur earum. Tempora omnis autem omnis et libero dolores illum autem. Deleniti eos sunt mollitia ipsam. Cum dolor repellendus dolorum sequi officia. Ullam sunt in aut pariatur excepturi.\n\nDolor nihil debitis et est eos. Cumque eos eum saepe ducimus autem. Alias architecto consequatur aut pariatur possimus. Aut quos aut incidunt quam velit et. Quas voluptatum ad dolorum dignissimos.\n\nUt voluptates consectetur illo et. Est commodi accusantium vel quo. Eos qui fugiat soluta porro.\n\nRatione possimus alias vel maxime sint totam est repellat. Ipsum corporis eos sint voluptatem eos odit. Temporibus libero nulla harum eligendi labore similique ratione magnam. Suscipit sequi in omnis neque.\n\nLaudantium dolor amet omnis placeat mollitia aut molestiae. Aut rerum similique ipsum quod illo quas unde. Sunt aut veritatis eos omnis porro. Rem veritatis mollitia praesentium dolorem. Consequatur sequi ad cumque earum omnis quia necessitatibus.","created_at":"2016-03-22T15:20:35.864Z","updated_at":"2016-03-22T15:20:35.864Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":38,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]}]}
{"id":39,"project_id":5,"ref":"master","sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.761Z","updated_at":"2016-03-22T15:20:35.761Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"stages":[{"id":23,"project_id":5,"pipeline_id":39,"name":"test","status":1,"created_at":"2016-03-22T15:44:44.772Z","updated_at":"2016-03-29T06:44:44.634Z","statuses":[{"id":78,"project_id":5,"status":"success","finished_at":null,"trace":"Dolorem deserunt quas quia error hic quo cum vel. Natus voluptatem cumque expedita numquam odit. Eos expedita nostrum corporis consequatur est recusandae.\n\nCulpa blanditiis rerum repudiandae alias voluptatem. Velit iusto est ullam consequatur doloribus porro. Corporis voluptas consectetur est veniam et quia quae.\n\nEt aut magni fuga nesciunt officiis molestias. Quaerat et nam necessitatibus qui rerum. Architecto quia officiis voluptatem laborum est recusandae. Quasi ducimus soluta odit necessitatibus labore numquam dignissimos. Quia facere sint temporibus inventore sunt nihil saepe dolorum.\n\nFacere dolores quis dolores a. Est minus nostrum nihil harum. Earum laborum et ipsum unde neque sit nemo. Corrupti est consequatur minima fugit. Illum voluptatem illo error ducimus officia qui debitis.\n\nDignissimos porro a autem harum aut. Aut id reprehenderit et exercitationem. Est et quisquam ipsa temporibus molestiae. Architecto natus dolore qui fugiat incidunt. Autem odit veniam excepturi et voluptatibus culpa ipsum eos.\n\nAmet quo quisquam dignissimos soluta modi dolores. Sint omnis eius optio corporis dolor. Eligendi animi porro quia placeat ut.","created_at":"2016-03-22T15:20:35.927Z","updated_at":"2016-03-22T15:20:35.927Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":39,"commands":"$ build command","job_id":null,"name":"test build 2","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null},{"id":77,"project_id":5,"status":"failed","finished_at":null,"trace":"Rerum ut et suscipit est perspiciatis. Inventore debitis cum eius vitae. Ex incidunt id velit aut quo nisi. Laboriosam repellat deserunt eius reiciendis architecto et. Est harum quos nesciunt nisi consectetur.\n\nAlias esse omnis sint officia est consequatur in nobis. Dignissimos dolorum vel eligendi nesciunt dolores sit. Veniam mollitia ducimus et exercitationem molestiae libero sed. Atque omnis debitis laudantium voluptatibus qui. Repellendus tempore est commodi pariatur.\n\nExpedita voluptate illum est alias non. Modi nesciunt ab assumenda laborum nulla consequatur molestias doloremque. Magnam quod officia vel explicabo accusamus ut voluptatem incidunt. Rerum ut aliquid ullam saepe. Est eligendi debitis beatae blanditiis reiciendis.\n\nQui fuga sit dolores libero maiores et suscipit. Consectetur asperiores omnis minima impedit eos fugiat. Similique omnis nisi sed vero inventore ipsum aliquam exercitationem.\n\nBlanditiis magni iure dolorum omnis ratione delectus molestiae. Atque officia dolor voluptatem culpa quod. Incidunt suscipit quidem possimus veritatis non vel. Iusto aliquid et id quia quasi.\n\nVel facere velit blanditiis incidunt cupiditate sed maiores consequuntur. Quasi quia dicta consequuntur et quia voluptatem iste id. Incidunt et rerum fuga esse sint.","created_at":"2016-03-22T15:20:35.905Z","updated_at":"2016-03-22T15:20:35.905Z","started_at":null,"runner_id":null,"coverage":null,"commit_id":39,"commands":"$ build command","job_id":null,"name":"test build 1","deploy":false,"options":null,"allow_failure":false,"stage":"test","trigger_request_id":null,"stage_idx":1,"tag":null,"ref":"master","user_id":null,"target_url":null,"description":null,"erased_by_id":null,"erased_at":null}]}]}
{"id":41,"project_id":5,"ref":"master","sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","before_sha":null,"push_data":null,"created_at":"2016-03-22T15:20:35.763Z","updated_at":"2016-03-22T15:20:35.763Z","tag":null,"yaml_errors":null,"committed_at":null,"status":"failed","started_at":null,"finished_at":null,"duration":null,"stages":[]}
diff --git a/spec/fixtures/markdown/markdown_golden_master_examples.yml b/spec/fixtures/markdown/markdown_golden_master_examples.yml
index 495d00026d7..6a1e75348cf 100644
--- a/spec/fixtures/markdown/markdown_golden_master_examples.yml
+++ b/spec/fixtures/markdown/markdown_golden_master_examples.yml
@@ -427,6 +427,14 @@
html: |-
<a class="no-attachment-icon" href="http://localhost:8080/png/U9nJK73CoKnELT2rKt3AJx9IS2mjoKZDAybCJYp9pCzJ24ejB4qjBk5I0Cagw09LWPLZKLTSa9zNdCe5L8bcO5u-K6MHGY8kWo7ARNHr2QY7MW00AeWxTG00" target="_blank" rel="noopener noreferrer" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,ICBBbGljZSAtPiBCb2I6IEF1dGhlbnRpY2F0aW9uIFJlcXVlc3QKICBCb2IgLS0+IEFsaWNlOiBBdXRoZW50aWNhdGlvbiBSZXNwb25zZQoKICBBbGljZSAtPiBCb2I6IEFub3RoZXIgYXV0aGVudGljYXRpb24gUmVxdWVzdAogIEFsaWNlIDwtLSBCb2I6IEFub3RoZXIgYXV0aGVudGljYXRpb24gUmVzcG9uc2UK"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" decoding="async" class="lazy" data-src="http://localhost:8080/png/U9nJK73CoKnELT2rKt3AJx9IS2mjoKZDAybCJYp9pCzJ24ejB4qjBk5I0Cagw09LWPLZKLTSa9zNdCe5L8bcO5u-K6MHGY8kWo7ARNHr2QY7MW00AeWxTG00"></a>
+- name: diagram_plantuml_unicode
+ markdown: |-
+ ```plantuml
+ A -> B : Text with norwegian characters: æøå
+ ```
+ html: |-
+ <a class="no-attachment-icon" href="http://localhost:8080/png/U9npLD2rKt1Ii588IQqeKIZFBCbGoCilAazDpqpCKqZEI2nAJ2v9BIgsKZYyxF2Emqkv07hO4WG0" target="_blank" rel="noopener noreferrer" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,QSAtPiBCIDogVGV4dCB3aXRoIG5vcndlZ2lhbiBjaGFyYWN0ZXJzOiDDpsO4w6UK"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" decoding="async" class="lazy" data-src="http://localhost:8080/png/U9npLD2rKt1Ii588IQqeKIZFBCbGoCilAazDpqpCKqZEI2nAJ2v9BIgsKZYyxF2Emqkv07hO4WG0"></a>
+
- name: div
markdown: |-
<div>plain text</div>
@@ -762,18 +770,18 @@
# 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+?)(")'
+ - regex: '(data-user|data-project|data-issue|data-iid|data-merge-request|data-milestone|data-label)(=")(\d+?)(")'
replacement: '\1\2ID\4'
text_attribute_substitution:
- - regex: '(title)(=")(.+?)(")'
+ - 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
+ Hi @gfm_user - thank you for reporting this ~"UX 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-reference-type="user" data-user="1" 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-reference-type="issue" data-original="#1" data-link="false" data-link-reference="false" data-project="11" data-issue="11" data-project-path="group1/project1" data-iid="1" data-issue-type="issue" data-container="body" data-placement="top" title="My title 1" class="gfm gfm-issue">#1</a>) we hope to fix it in <a href="/group1/project1/-/milestones/1" data-reference-type="milestone" data-original="%1.1" data-link="false" data-link-reference="false" data-project="11" data-milestone="11" 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-reference-type="merge_request" 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-container="body" data-placement="top" title="My title 2" class="gfm gfm-merge_request">!1</a></p>
+ <p data-sourcepos="1:1-1:98" dir="auto">Hi <a href="/gfm_user" data-reference-type="user" data-user="1" 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 <span class="gl-label gl-label-sm"><a href="/groupID/projectID/-/issues?label_name=UX+bug" data-reference-type="label" data-original='~"UX bug"' data-link="false" data-link-reference="false" data-project="ID" data-label="2" data-container="body" data-placement="top" title="TEXT" class="gfm gfm-label has-tooltip gl-link gl-label-link"><span class="gl-label-text gl-label-text-light" data-container="body" data-html="true" style="background-color: #990000">UX bug</span></a></span> (<a href="/group1/project1/-/issues/1" data-reference-type="issue" data-original="#1" data-link="false" data-link-reference="false" data-project="11" data-issue="11" data-project-path="group1/project1" data-iid="1" data-issue-type="issue" data-container="body" data-placement="top" title="My title 1" class="gfm gfm-issue">#1</a>) we hope to fix it in <a href="/group1/project1/-/milestones/1" data-reference-type="milestone" data-original="%1.1" data-link="false" data-link-reference="false" data-project="11" data-milestone="11" 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-reference-type="merge_request" 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-container="body" data-placement="top" title="My title 2" class="gfm gfm-merge_request">!1</a></p>
- name: strike
markdown: |-
~~del~~
diff --git a/spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.src.rpm b/spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.src.rpm
new file mode 100644
index 00000000000..8284faab80a
--- /dev/null
+++ b/spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.src.rpm
Binary files differ
diff --git a/spec/fixtures/packages/rpm/payload.json b/spec/fixtures/packages/rpm/payload.json
new file mode 100644
index 00000000000..0240dbaca21
--- /dev/null
+++ b/spec/fixtures/packages/rpm/payload.json
@@ -0,0 +1,47 @@
+{
+ "files": [
+ "/usr/bin/hello.sh"
+ ],
+ "changelogs": [
+ {
+ "changelogtext": "First build",
+ "changelogtime": 1662552000
+ }
+ ],
+ "requirements": [
+ {
+ "requirename": "bash",
+ "requireversion": "",
+ "requireflags": 0
+ },
+ {
+ "requirename": "rpmlib(CompressedFileNames)",
+ "requireversion": "3.0.4-1",
+ "requireflags": 16777226
+ }
+ ],
+ "provides": [
+ {
+ "providename": "hello",
+ "provideflags": 8,
+ "provideversion": "0.0.1-1.fc29"
+ },
+ {
+ "providename": "hello(x86-64)",
+ "provideflags": 8,
+ "provideversion": "0.0.1-1.fc29"
+ }
+ ],
+ "name": "hello",
+ "version": "0.0.1",
+ "release": "1.fc29",
+ "summary": "Simple RPM package",
+ "description": "Fake rpm package",
+ "arch": "x86_64",
+ "license": "MIT",
+ "sourcerpm": "hello-0.0.1-1.fc29.src.rpm",
+ "group": "Unspecified",
+ "buildhost": "localhost",
+ "packager": null,
+ "vendor": null
+} \ No newline at end of file
diff --git a/spec/fixtures/packages/rpm/repodata/repomd.xml b/spec/fixtures/packages/rpm/repodata/repomd.xml
new file mode 100644
index 00000000000..4554ee9a6d0
--- /dev/null
+++ b/spec/fixtures/packages/rpm/repodata/repomd.xml
@@ -0,0 +1,27 @@
+<repomd xmlns="http://gitlab.com/api/v4/projects/1/packages/rpm/repodata/repomd.xml" xmlns:rpm="http://gitlab.com/api/v4/projects/1/packages/rpm/repodata/repomd.xml">
+ <revision>1644602779</revision>
+ <data type="filelists">
+ <checksum type="sha256">6503673de76312406ff8ecb06d9733c32b546a65abae4d4170d9b51fb75bf253</checksum>
+ <open-checksum type="sha256">7652c7496daa2507f08675a5b4f59a5428aaba72997400ae3d5e7bab8e3d9cc1</open-checksum>
+ <location href="repodata/6503673de76312406ff8ecb06d9733c32b546a65abae4d4170d9b51fb75bf253-filelists.xml"/>
+ <timestamp>1644602784</timestamp>
+ <size>1144067</size>
+ <open-size>25734004</open-size>
+ </data>
+ <data type="primary">
+ <checksum type="sha256">80279a863b6236e60c3e63036b8a9a25e3764dfb3121292b91e9f583af9e7b7e</checksum>
+ <open-checksum type="sha256">f852f3bb39f89520434d97f6913716dc448077ad49f2e5200327367f98a89d55</open-checksum>
+ <location href="repodata/80279a863b6236e60c3e63036b8a9a25e3764dfb3121292b91e9f583af9e7b7e-primary.xml"/>
+ <timestamp>1644602784</timestamp>
+ <size>66996</size>
+ <open-size>1008586</open-size>
+ </data>
+ <data type="other">
+ <checksum type="sha256">34408890500ec72c0f181542a91f7ff9320d2ef32c8e613540a5b9e1b8763e02</checksum>
+ <open-checksum type="sha256">acac5033036264cd26100713b014242471ade45487c28c7793466a84af512624</open-checksum>
+ <location href="repodata/34408890500ec72c0f181542a91f7ff9320d2ef32c8e613540a5b9e1b8763e02-other.xml"/>
+ <timestamp>1644602784</timestamp>
+ <size>43329</size>
+ <open-size>730393</open-size>
+ </data>
+</repomd>
diff --git a/spec/fixtures/packages/rubygems/package.gemspec b/spec/fixtures/packages/rubygems/package.gemspec
index ea03414cc6f..60acd078fad 100644
--- a/spec/fixtures/packages/rubygems/package.gemspec
+++ b/spec/fixtures/packages/rubygems/package.gemspec
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.post_install_message = 'Installed, thank you!'
s.rdoc_options = ['--main', 'README.md']
- s.required_ruby_version = '>= 2.7.0'
+ s.required_ruby_version = '>= 2.7.0' # rubocop:disable Gemspec/RequiredRubyVersion
s.required_rubygems_version = '>= 1.8.11'
s.requirements = 'A high powered server or calculator'
s.rubygems_version = '1.8.09'
diff --git a/spec/fixtures/sample.pdf b/spec/fixtures/sample.pdf
new file mode 100644
index 00000000000..81ea09d7d12
--- /dev/null
+++ b/spec/fixtures/sample.pdf
@@ -0,0 +1,13 @@
+%PDF-1.3
+%�����������
+4 0 obj
+<< /Length 5 0 R /Filter /FlateDecode >>
+stream
+xe���0 ��>�@���
+ba�d�1U�V��_8��n�e}�� fXU�`\F�d2�����S%,�Q]�;XC�9�+Qy���k>a2>31B4�;���d)!Md�M�-�B��F���N�[v��~��E�5���^�Z_�� ΢�o�l.�
+endstream
+endobj
+5 0 obj
+155
+endobj
+2 0 obj
diff --git a/spec/fixtures/security_reports/deprecated/gl-sast-report.json b/spec/fixtures/security_reports/deprecated/gl-sast-report.json
deleted file mode 100644
index c5b0148fe3e..00000000000
--- a/spec/fixtures/security_reports/deprecated/gl-sast-report.json
+++ /dev/null
@@ -1,964 +0,0 @@
-[
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 1,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 47,
- "end_line": 47,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken2"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 47,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Predictable pseudorandom number generator",
- "message": "Predictable pseudorandom number generator",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 41,
- "end_line": 41,
- "class": "com.gitlab.security_products.tests.App",
- "method": "generateSecretToken1"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-PREDICTABLE_RANDOM",
- "value": "PREDICTABLE_RANDOM",
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 41,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 11,
- "end_line": 11
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 11,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 12,
- "end_line": 12
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 12,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 13,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 14,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Pickle library appears to be in use, possible security issue.",
- "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 15,
- "end_line": 15
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B301",
- "value": "B301"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 15,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "name": "ECB mode is insecure",
- "message": "ECB mode is insecure",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-ECB_MODE",
- "value": "ECB_MODE",
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "name": "Cipher with no integrity",
- "message": "Cipher with no integrity",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "find_sec_bugs",
- "name": "Find Security Bugs"
- },
- "location": {
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
- },
- "identifiers": [
- {
- "type": "find_sec_bugs_type",
- "name": "Find Security Bugs-CIPHER_INTEGRITY",
- "value": "CIPHER_INTEGRITY",
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
- }
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 14,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 10,
- "end_line": 10
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 10,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 22,
- "end_line": 22
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B106",
- "value": "B106",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 22,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'root'",
- "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 5,
- "end_line": 5
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 5,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: ''",
- "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 13,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 23,
- "end_line": 23
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 23,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 24,
- "end_line": 24
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 24,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-function.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-function.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 7,
- "end_line": 7
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
- "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B602",
- "value": "B602",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 1,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 7,
- "end_line": 8
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with loads module.",
- "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "c/subdir/utils.c",
- "start_line": 4
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - char",
- "value": "char"
- },
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 4,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
- "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
- "confidence": "Low",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "c/subdir/utils.c",
- "start_line": 8
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - fopen",
- "value": "fopen"
- },
- {
- "type": "cwe",
- "name": "CWE-362",
- "value": "362",
- "url": "https://cwe.mitre.org/data/definitions/362.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 8,
- "url": "https://cwe.mitre.org/data/definitions/362.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "cplusplus/src/hello.cpp",
- "start_line": 6
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - char",
- "value": "char"
- },
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 6,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
- "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
- "confidence": "Low",
- "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "cplusplus/src/hello.cpp",
- "start_line": 7
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - strcpy",
- "value": "strcpy"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 7,
- "url": "https://cwe.mitre.org/data/definitions/120.html",
- "tool": "flawfinder"
- }
-] \ No newline at end of file
diff --git a/spec/fixtures/security_reports/feature-branch/gl-sast-report.json b/spec/fixtures/security_reports/feature-branch/gl-sast-report.json
index 51761583c70..083042e19ff 100644
--- a/spec/fixtures/security_reports/feature-branch/gl-sast-report.json
+++ b/spec/fixtures/security_reports/feature-branch/gl-sast-report.json
@@ -171,7 +171,7 @@
},
"type": "sast",
"status": "success",
- "start_time": "placeholder-value",
- "end_time": "placeholder-value"
+ "start_time": "2022-08-10T22:37:00",
+ "end_time": "2022-08-10T22:38:00"
}
} \ No newline at end of file
diff --git a/spec/fixtures/security_reports/master/gl-common-scanning-report-names.json b/spec/fixtures/security_reports/master/gl-common-scanning-report-names.json
index ef2ff7443d3..cdad960026c 100644
--- a/spec/fixtures/security_reports/master/gl-common-scanning-report-names.json
+++ b/spec/fixtures/security_reports/master/gl-common-scanning-report-names.json
@@ -12,8 +12,29 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
- "identifiers": [],
+ "location": {
+ "file": "yarn/yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "value": "2017-11429",
+ "type": "cwe",
+ "name": "CWE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cwename.cgi?name=CWE-2017-11429"
+ },
+ {
+ "value": "2017-11429",
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
"links": [
{
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-1020"
@@ -33,8 +54,29 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
- "identifiers": [],
+ "location": {
+ "file": "yarn/yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "value": "2017-11429",
+ "type": "cwe",
+ "name": "CWE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cwename.cgi?name=CWE-2017-11429"
+ },
+ {
+ "value": "2017-11429",
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
"links": [
{
"name": "CVE-1030",
@@ -161,8 +203,9 @@
"version": "2.18.0"
},
"type": "dependency_scanning",
- "start_time": "placeholder-value",
- "end_time": "placeholder-value",
+ "start_time": "2022-08-10T21:37:00",
+ "end_time": "2022-08-10T21:38:00",
"status": "success"
- }
-} \ No newline at end of file
+ },
+ "version": "14.0.6"
+}
diff --git a/spec/fixtures/security_reports/master/gl-common-scanning-report.json b/spec/fixtures/security_reports/master/gl-common-scanning-report.json
index 1295b44d4df..4c494963a79 100644
--- a/spec/fixtures/security_reports/master/gl-common-scanning-report.json
+++ b/spec/fixtures/security_reports/master/gl-common-scanning-report.json
@@ -12,7 +12,15 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -27,18 +35,8 @@
],
"details": {
"commit": {
- "name": [
- {
- "lang": "en",
- "value": "The Commit"
- }
- ],
- "description": [
- {
- "lang": "en",
- "value": "Commit where the vulnerability was identified"
- }
- ],
+ "name": "the commit",
+ "description": "description",
"type": "commit",
"value": "41df7b7eb3be2b5be2c406c2f6d28cd6631eeb19"
}
@@ -56,7 +54,15 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -71,18 +77,8 @@
],
"details": {
"commit": {
- "name": [
- {
- "lang": "en",
- "value": "The Commit"
- }
- ],
- "description": [
- {
- "lang": "en",
- "value": "Commit where the vulnerability was identified"
- }
- ],
+ "name": "the commit",
+ "description": "description",
"type": "commit",
"value": "41df7b7eb3be2b5be2c406c2f6d28cd6631eeb19"
}
@@ -100,7 +96,15 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -115,18 +119,8 @@
],
"details": {
"commit": {
- "name": [
- {
- "lang": "en",
- "value": "The Commit"
- }
- ],
- "description": [
- {
- "lang": "en",
- "value": "Commit where the vulnerability was identified"
- }
- ],
+ "name": "the commit",
+ "description": "description",
"type": "commit",
"value": "41df7b7eb3be2b5be2c406c2f6d28cd6631eeb19"
}
@@ -144,7 +138,15 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -159,18 +161,8 @@
],
"details": {
"commit": {
- "name": [
- {
- "lang": "en",
- "value": "The Commit"
- }
- ],
- "description": [
- {
- "lang": "en",
- "value": "Commit where the vulnerability was identified"
- }
- ],
+ "name": "the commit",
+ "description": "description",
"type": "commit",
"value": "41df7b7eb3be2b5be2c406c2f6d28cd6631eeb19"
}
@@ -258,7 +250,15 @@
}
]
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -273,18 +273,8 @@
],
"details": {
"commit": {
- "name": [
- {
- "lang": "en",
- "value": "The Commit"
- }
- ],
- "description": [
- {
- "lang": "en",
- "value": "Commit where the vulnerability was identified"
- }
- ],
+ "name": "the commit",
+ "description": "description",
"type": "commit",
"value": "41df7b7eb3be2b5be2c406c2f6d28cd6631eeb19"
}
@@ -373,7 +363,15 @@
}
]
},
- "location": {},
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
"identifiers": [
{
"type": "GitLab",
@@ -400,8 +398,22 @@
"id": "gemnasium",
"name": "Gemnasium"
},
- "location": {},
- "identifiers": [],
+ "location": {
+ "file": "some/kind/of/file.c",
+ "dependency": {
+ "package": {
+ "name": "io.netty/netty"
+ },
+ "version": "3.9.1.Final"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "GitLab",
+ "name": "Foo vulnerability",
+ "value": "foo"
+ }
+ ],
"links": []
}
],
@@ -442,8 +454,8 @@
"cve": "CVE-1020"
}
],
- "summary": "",
- "diff": ""
+ "summary": "this fixes CVE-1020",
+ "diff": "dG90YWxseSBsZWdpdGltYXRlIGRpZmYsIDEwLzEwIHdvdWxkIGFwcGx5"
},
{
"fixes": [
@@ -452,8 +464,8 @@
"id": "bb2fbeb1b71ea360ce3f86f001d4e84823c3ffe1a1f7d41ba7466b14cfa953d3"
}
],
- "summary": "",
- "diff": ""
+ "summary": "this fixes CVE",
+ "diff": "dG90YWxseSBsZWdpdGltYXRlIGRpZmYsIDEwLzEwIHdvdWxkIGFwcGx5"
},
{
"fixes": [
@@ -462,8 +474,8 @@
"id": "bb2fbeb1b71ea360ce3f86f001d4e84823c3ffe1a1f7d41ba7466b14cfa953d3"
}
],
- "summary": "",
- "diff": ""
+ "summary": "this fixed CVE",
+ "diff": "dG90YWxseSBsZWdpdGltYXRlIGRpZmYsIDEwLzEwIHdvdWxkIGFwcGx5"
},
{
"fixes": [
@@ -472,8 +484,8 @@
"cve": "CVE-1"
}
],
- "summary": "",
- "diff": ""
+ "summary": "this fixes CVE-1",
+ "diff": "dG90YWxseSBsZWdpdGltYXRlIGRpZmYsIDEwLzEwIHdvdWxkIGFwcGx5"
}
],
"dependency_files": [],
@@ -497,9 +509,9 @@
"version": "2.18.0"
},
"type": "dependency_scanning",
- "start_time": "placeholder-value",
- "end_time": "placeholder-value",
+ "start_time": "2022-08-10T21:37:00",
+ "end_time": "2022-08-10T21:38:00",
"status": "success"
},
"version": "14.0.2"
-} \ No newline at end of file
+}
diff --git a/spec/fixtures/security_reports/master/gl-sast-report-minimal.json b/spec/fixtures/security_reports/master/gl-sast-report-minimal.json
index 5e9273d43b1..53d15224b30 100644
--- a/spec/fixtures/security_reports/master/gl-sast-report-minimal.json
+++ b/spec/fixtures/security_reports/master/gl-sast-report-minimal.json
@@ -62,7 +62,7 @@
},
"type": "sast",
"status": "success",
- "start_time": "placeholder-value",
- "end_time": "placeholder-value"
+ "start_time": "2022-08-10T21:37:00",
+ "end_time": "2022-08-10T21:38:00"
}
} \ No newline at end of file
diff --git a/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json b/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json
index f01d26a69c9..8fa85c30b56 100644
--- a/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json
+++ b/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json
@@ -62,6 +62,13 @@
},
"version": "0.82.0"
},
+ "primary_identifiers": [
+ {
+ "type": "semgrep_id",
+ "name": "gosec.G106-1",
+ "value": "gosec.G106-1"
+ }
+ ],
"type": "sast",
"start_time": "2022-03-15T20:36:58",
"end_time": "2022-03-15T20:37:05",
diff --git a/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-multiple-findings.json b/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-multiple-findings.json
new file mode 100644
index 00000000000..cbdfdb86f6b
--- /dev/null
+++ b/spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-multiple-findings.json
@@ -0,0 +1,134 @@
+{
+ "version": "14.0.4",
+ "vulnerabilities": [
+ {
+ "id": "985a5666dcae22adef5ac12f8a8a2dacf9b9b481ae5d87cd0ac1712b0fd64864",
+ "category": "sast",
+ "message": "Deserialization of Untrusted Data",
+ "description": "Avoid using `load()`. `PyYAML.load` can create arbitrary Python\nobjects. A malicious actor could exploit this to run arbitrary\ncode. Use `safe_load()` instead.\n",
+ "cve": "",
+ "severity": "Critical",
+ "scanner": {
+ "id": "semgrep",
+ "name": "Semgrep"
+ },
+ "location": {
+ "file": "app/app.py",
+ "start_line": 39
+ },
+ "identifiers": [
+ {
+ "type": "semgrep_id",
+ "name": "bandit.B506",
+ "value": "bandit.B506",
+ "url": "https://semgrep.dev/r/gitlab.bandit.B506"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-502",
+ "value": "502",
+ "url": "https://cwe.mitre.org/data/definitions/502.html"
+ },
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B506",
+ "value": "B506"
+ }
+ ],
+ "tracking": {
+ "type": "source",
+ "items": [
+ {
+ "file": "app/app.py",
+ "line_start": 39,
+ "line_end": 39,
+ "signatures": [
+ {
+ "algorithm": "scope_offset",
+ "value": "app/app.py|yaml_hammer[0]:13"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "id": "79f6537b7ec83c7717f5bd1a4f12645916caafefe2e4359148d889855505aa67",
+ "category": "sast",
+ "message": "Key Exchange without Entity Authentication",
+ "description": "Audit the use of ssh.InsecureIgnoreHostKey\n",
+ "cve": "",
+ "severity": "Medium",
+ "scanner": {
+ "id": "semgrep",
+ "name": "Semgrep"
+ },
+ "location": {
+ "file": "og.go",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "semgrep_id",
+ "name": "gosec.G106-1",
+ "value": "gosec.G106-1"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-322",
+ "value": "322",
+ "url": "https://cwe.mitre.org/data/definitions/322.html"
+ },
+ {
+ "type": "gosec_rule_id",
+ "name": "Gosec Rule ID G106",
+ "value": "G106"
+ }
+ ],
+ "tracking": {
+ "type": "source",
+ "items": [
+ {
+ "file": "og.go",
+ "line_start": 8,
+ "line_end": 8,
+ "signatures": [
+ {
+ "algorithm": "scope_offset",
+ "value": "og.go|foo[0]:1"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ],
+ "scan": {
+ "scanner": {
+ "id": "semgrep",
+ "name": "Semgrep",
+ "url": "https://github.com/returntocorp/semgrep",
+ "vendor": {
+ "name": "GitLab"
+ },
+ "version": "0.82.0"
+ },
+ "primary_identifiers": [
+ {
+ "type": "semgrep_id",
+ "name": "bandit.B506",
+ "value": "bandit.B506",
+ "url": "https://semgrep.dev/r/gitlab.bandit.B506"
+ },
+ {
+ "type": "semgrep_id",
+ "name": "gosec.G106-1",
+ "value": "gosec.G106-1"
+ }
+ ],
+ "type": "sast",
+ "start_time": "2022-03-15T20:36:58",
+ "end_time": "2022-03-15T20:37:05",
+ "status": "success"
+ }
+} \ No newline at end of file
diff --git a/spec/fixtures/security_reports/master/gl-sast-report.json b/spec/fixtures/security_reports/master/gl-sast-report.json
index 1aa8db1a65f..0ec31252e97 100644
--- a/spec/fixtures/security_reports/master/gl-sast-report.json
+++ b/spec/fixtures/security_reports/master/gl-sast-report.json
@@ -194,7 +194,7 @@
},
"type": "sast",
"status": "success",
- "start_time": "placeholder-value",
- "end_time": "placeholder-value"
+ "start_time": "2022-08-10T21:37:00",
+ "end_time": "2022-08-10T21:38:00"
}
} \ No newline at end of file
diff --git a/spec/fixtures/security_reports/master/gl-secret-detection-report.json b/spec/fixtures/security_reports/master/gl-secret-detection-report.json
index 21d4f3f1798..cb97b60ced1 100644
--- a/spec/fixtures/security_reports/master/gl-secret-detection-report.json
+++ b/spec/fixtures/security_reports/master/gl-secret-detection-report.json
@@ -18,6 +18,9 @@
"file": "aws-key.py",
"dependency": {
"package": {}
+ },
+ "commit": {
+ "sha": "e9c3a56590d5bed4155c0d128f1552d52fdcc7ae"
}
},
"identifiers": [
diff --git a/spec/frontend/__helpers__/class_spec_helper.js b/spec/frontend/__helpers__/class_spec_helper.js
deleted file mode 100644
index b26f087f0c5..00000000000
--- a/spec/frontend/__helpers__/class_spec_helper.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// eslint-disable-next-line jest/no-export
-export default class ClassSpecHelper {
- static itShouldBeAStaticMethod(base, method) {
- return it('should be a static method', () => {
- expect(Object.prototype.hasOwnProperty.call(base, method)).toBeTruthy();
- });
- }
-}
-
-window.ClassSpecHelper = ClassSpecHelper;
diff --git a/spec/frontend/__helpers__/class_spec_helper_spec.js b/spec/frontend/__helpers__/class_spec_helper_spec.js
deleted file mode 100644
index 533d5687bde..00000000000
--- a/spec/frontend/__helpers__/class_spec_helper_spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* global ClassSpecHelper */
-
-import './class_spec_helper';
-
-describe('ClassSpecHelper', () => {
- let testContext;
-
- beforeEach(() => {
- testContext = {};
- });
-
- describe('itShouldBeAStaticMethod', () => {
- beforeEach(() => {
- class TestClass {
- instanceMethod() {
- this.prop = 'val';
- }
- static staticMethod() {}
- }
-
- testContext.TestClass = TestClass;
- });
-
- ClassSpecHelper.itShouldBeAStaticMethod(ClassSpecHelper, 'itShouldBeAStaticMethod');
- });
-});
diff --git a/spec/frontend/__helpers__/dom_shims/index.js b/spec/frontend/__helpers__/dom_shims/index.js
index 742d55196b4..3b41e2ca2a7 100644
--- a/spec/frontend/__helpers__/dom_shims/index.js
+++ b/spec/frontend/__helpers__/dom_shims/index.js
@@ -11,3 +11,4 @@ import './window_scroll_to';
import './scroll_by';
import './size_properties';
import './image_element_properties';
+import './text_encoder';
diff --git a/spec/frontend/__helpers__/dom_shims/text_encoder.js b/spec/frontend/__helpers__/dom_shims/text_encoder.js
new file mode 100644
index 00000000000..d3d5221a003
--- /dev/null
+++ b/spec/frontend/__helpers__/dom_shims/text_encoder.js
@@ -0,0 +1,4 @@
+import { TextEncoder, TextDecoder } from 'util';
+
+global.TextEncoder = TextEncoder;
+global.TextDecoder = TextDecoder;
diff --git a/spec/frontend/__helpers__/graphql_transformer.js b/spec/frontend/__helpers__/graphql_transformer.js
new file mode 100644
index 00000000000..e776e2ea6ac
--- /dev/null
+++ b/spec/frontend/__helpers__/graphql_transformer.js
@@ -0,0 +1,8 @@
+/* eslint-disable import/no-commonjs */
+const loader = require('graphql-tag/loader');
+
+module.exports = {
+ process(src) {
+ return loader.call({ cacheable() {} }, src);
+ },
+};
diff --git a/spec/frontend/__helpers__/shared_test_setup.js b/spec/frontend/__helpers__/shared_test_setup.js
index 45a7b8e0352..2fe9fe89a90 100644
--- a/spec/frontend/__helpers__/shared_test_setup.js
+++ b/spec/frontend/__helpers__/shared_test_setup.js
@@ -1,7 +1,7 @@
/* 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 { enableAutoDestroy } from '@vue/test-utils';
import 'jquery';
import Translate from '~/vue_shared/translate';
import setWindowLocation from './set_window_location_helper';
@@ -13,6 +13,8 @@ import './dom_shims';
import './jquery';
import '~/commons/bootstrap';
+enableAutoDestroy(afterEach);
+
// This module has some fairly decent visual test coverage in it's own repository.
jest.mock('@gitlab/favicon-overlay');
jest.mock('~/lib/utils/axios_utils', () => jest.requireActual('helpers/mocks/axios_utils'));
@@ -44,16 +46,6 @@ Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
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`',
- ];
- if (!ALLOWED_DEPRECATED_METHODS.includes(method)) {
- global.console.error(message);
- }
-};
-
Object.assign(global, {
requestIdleCallback(cb) {
const start = Date.now();
@@ -72,6 +64,7 @@ Object.assign(global, {
beforeEach(() => {
// make sure that each test actually tests something
// see https://jestjs.io/docs/en/expect#expecthasassertions
+ // eslint-disable-next-line jest/no-standalone-expect
expect.hasAssertions();
// Reset the mocked window.location. This ensures tests don't interfere with
diff --git a/spec/frontend/__helpers__/stub_component.js b/spec/frontend/__helpers__/stub_component.js
index 4f9d1ee6f5d..3e9af994ee3 100644
--- a/spec/frontend/__helpers__/stub_component.js
+++ b/spec/frontend/__helpers__/stub_component.js
@@ -38,7 +38,7 @@ export function stubComponent(Component, options = {}) {
// Do not render any slots/scoped slots except default
// This differs from VTU behavior which renders all slots
template: '<div><slot></slot></div>',
- // allows wrapper.find(Component) to work for stub
+ // allows wrapper.findComponent(Component) to work for stub
$_vueTestUtils_original: Component,
...options,
};
diff --git a/spec/frontend/__helpers__/vue_mount_component_helper.js b/spec/frontend/__helpers__/vue_mount_component_helper.js
deleted file mode 100644
index ed43355ea5b..00000000000
--- a/spec/frontend/__helpers__/vue_mount_component_helper.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Deprecated. Please do not use.
- * Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
- */
-const mountComponent = (Component, props = {}, el = null) =>
- new Component({
- propsData: props,
- }).$mount(el);
-
-/**
- * Deprecated. Please do not use.
- * Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
- */
-export const createComponentWithStore = (Component, store, propsData = {}) =>
- new Component({
- store,
- propsData,
- });
-
-/**
- * Deprecated. Please do not use.
- * Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
- */
-export const mountComponentWithStore = (Component, { el, props, store }) =>
- new Component({
- store,
- propsData: props || {},
- }).$mount(el);
-
-/**
- * Deprecated. Please do not use.
- * Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
- */
-export default mountComponent;
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index ae180c3b49d..466333f8a89 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
@@ -140,11 +140,12 @@ describe('Vue test utils helpers', () => {
const text = 'foo bar';
const options = { selector: 'div' };
const mockDiv = document.createElement('div');
- const mockVm = new Vue({ render: (h) => h('div') }).$mount();
+ let mockVm;
let wrapper;
beforeEach(() => {
jest.spyOn(vtu, 'createWrapper');
+ mockVm = new Vue({ render: (h) => h('div') }).$mount();
wrapper = extendedWrapper(
shallowMount({
diff --git a/spec/frontend/__mocks__/monaco-editor/index.js b/spec/frontend/__mocks__/monaco-editor/index.js
index 384f9993150..d09672a4ecf 100644
--- a/spec/frontend/__mocks__/monaco-editor/index.js
+++ b/spec/frontend/__mocks__/monaco-editor/index.js
@@ -8,10 +8,8 @@ import 'monaco-editor/esm/vs/language/css/monaco.contribution';
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
import 'monaco-editor/esm/vs/language/html/monaco.contribution';
import 'monaco-editor/esm/vs/basic-languages/monaco.contribution';
-import 'monaco-yaml/lib/esm/monaco.contribution';
// This language starts trying to spin up web workers which obviously breaks in Jest environment
jest.mock('monaco-editor/esm/vs/language/typescript/tsMode');
-jest.mock('monaco-yaml/lib/esm/yamlMode');
export * from 'monaco-editor/esm/vs/editor/editor.api';
diff --git a/spec/frontend/__mocks__/monaco-yaml/index.js b/spec/frontend/__mocks__/monaco-yaml/index.js
new file mode 100644
index 00000000000..36681854d0b
--- /dev/null
+++ b/spec/frontend/__mocks__/monaco-yaml/index.js
@@ -0,0 +1,4 @@
+const setDiagnosticsOptions = jest.fn();
+const yamlDefaults = {};
+
+export { setDiagnosticsOptions, yamlDefaults };
diff --git a/spec/frontend/access_tokens/components/access_token_table_app_spec.js b/spec/frontend/access_tokens/components/access_token_table_app_spec.js
index aed3db4aa4c..2fa14810578 100644
--- a/spec/frontend/access_tokens/components/access_token_table_app_spec.js
+++ b/spec/frontend/access_tokens/components/access_token_table_app_spec.js
@@ -1,6 +1,6 @@
import { GlButton, GlPagination, GlTable } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import AccessTokenTableApp from '~/access_tokens/components/access_token_table_app.vue';
import { EVENT_SUCCESS, PAGE_SIZE } from '~/access_tokens/components/constants';
import { __, s__, sprintf } from '~/locale';
@@ -11,7 +11,7 @@ describe('~/access_tokens/components/access_token_table_app', () => {
const accessTokenType = 'personal access token';
const accessTokenTypePlural = 'personal access tokens';
- const initialActiveAccessTokens = [];
+ const information = undefined;
const noActiveTokensMessage = 'This user has no active personal access tokens.';
const showRole = false;
@@ -43,11 +43,12 @@ describe('~/access_tokens/components/access_token_table_app', () => {
];
const createComponent = (props = {}) => {
- wrapper = mount(AccessTokenTableApp, {
+ wrapper = mountExtended(AccessTokenTableApp, {
provide: {
accessTokenType,
accessTokenTypePlural,
- initialActiveAccessTokens,
+ information,
+ initialActiveAccessTokens: defaultActiveAccessTokens,
noActiveTokensMessage,
showRole,
...props,
@@ -71,8 +72,8 @@ describe('~/access_tokens/components/access_token_table_app', () => {
wrapper?.destroy();
});
- it('should render the `GlTable` with default empty message', () => {
- createComponent();
+ it('should render an empty table with a default message', () => {
+ createComponent({ initialActiveAccessTokens: [] });
const cells = findCells();
expect(cells).toHaveLength(1);
@@ -81,58 +82,61 @@ describe('~/access_tokens/components/access_token_table_app', () => {
);
});
- it('should render the `GlTable` with custom empty message', () => {
+ it('should render an empty table with a custom message', () => {
const noTokensMessage = 'This group has no active access tokens.';
- createComponent({ noActiveTokensMessage: noTokensMessage });
+ createComponent({ initialActiveAccessTokens: [], noActiveTokensMessage: noTokensMessage });
const cells = findCells();
expect(cells).toHaveLength(1);
expect(cells.at(0).text()).toBe(noTokensMessage);
});
- it('should render an h5 element', () => {
+ it('should show a title indicating the amount of tokens', () => {
createComponent();
expect(wrapper.find('h5').text()).toBe(
sprintf(__('Active %{accessTokenTypePlural} (%{totalAccessTokens})'), {
accessTokenTypePlural,
- totalAccessTokens: initialActiveAccessTokens.length,
+ totalAccessTokens: defaultActiveAccessTokens.length,
}),
);
});
- it('should render the `GlTable` component with default 6 column headers', () => {
- createComponent();
+ it('should render information section', () => {
+ const info = 'This is my information';
+ createComponent({ information: info });
- const headers = findHeaders();
- expect(headers).toHaveLength(6);
- [
- __('Token name'),
- __('Scopes'),
- s__('AccessTokens|Created'),
- __('Last Used'),
- __('Expires'),
- __('Action'),
- ].forEach((text, index) => {
- expect(headers.at(index).text()).toBe(text);
- });
+ expect(wrapper.findByTestId('information-section').text()).toBe(info);
});
- it('should render the `GlTable` component with 7 headers', () => {
- createComponent({ showRole: true });
+ describe('table headers', () => {
+ it('should include `Action` column', () => {
+ createComponent();
+
+ const headers = findHeaders();
+ expect(headers.wrappers.map((header) => header.text())).toStrictEqual([
+ __('Token name'),
+ __('Scopes'),
+ s__('AccessTokens|Created'),
+ __('Last Used'),
+ __('Expires'),
+ __('Action'),
+ ]);
+ });
- const headers = findHeaders();
- expect(headers).toHaveLength(7);
- [
- __('Token name'),
- __('Scopes'),
- s__('AccessTokens|Created'),
- __('Last Used'),
- __('Expires'),
- __('Role'),
- __('Action'),
- ].forEach((text, index) => {
- expect(headers.at(index).text()).toBe(text);
+ it('should include `Role` column', () => {
+ createComponent({ showRole: true });
+
+ const headers = findHeaders();
+ expect(headers.wrappers.map((header) => header.text())).toStrictEqual([
+ __('Token name'),
+ __('Scopes'),
+ s__('AccessTokens|Created'),
+ __('Last Used'),
+ __('Expires'),
+ __('Role'),
+ __('Action'),
+ ]);
});
});
@@ -150,8 +154,8 @@ describe('~/access_tokens/components/access_token_table_app', () => {
expect(assistiveElement.text()).toBe(s__('AccessTokens|The last time a token was used'));
});
- it('updates the table after a success AJAX event', async () => {
- createComponent({ showRole: true });
+ it('updates the table after new tokens are created', async () => {
+ createComponent({ initialActiveAccessTokens: [], showRole: true });
await triggerSuccess();
const cells = findCells();
@@ -190,16 +194,43 @@ describe('~/access_tokens/components/access_token_table_app', () => {
expect(button.props('category')).toBe('tertiary');
});
- describe('revoke path', () => {
- beforeEach(() => {
- createComponent({ showRole: true });
+ describe('when revoke_path is', () => {
+ describe('absent in all tokens', () => {
+ it('should not include `Action` column', () => {
+ createComponent({
+ initialActiveAccessTokens: defaultActiveAccessTokens.map(
+ ({ revoke_path, ...rest }) => rest,
+ ),
+ showRole: true,
+ });
+
+ const headers = findHeaders();
+ expect(headers).toHaveLength(6);
+ [
+ __('Token name'),
+ __('Scopes'),
+ s__('AccessTokens|Created'),
+ __('Last Used'),
+ __('Expires'),
+ __('Role'),
+ ].forEach((text, index) => {
+ expect(headers.at(index).text()).toBe(text);
+ });
+ });
});
it.each([{ revoke_path: null }, { revoke_path: undefined }])(
- 'with %p, does not show revoke button',
- async (input) => {
- await triggerSuccess(defaultActiveAccessTokens.map((data) => ({ ...data, ...input })));
-
+ '%p in some tokens, does not show revoke button',
+ (input) => {
+ createComponent({
+ initialActiveAccessTokens: [
+ defaultActiveAccessTokens.map((data) => ({ ...data, ...input }))[0],
+ defaultActiveAccessTokens[1],
+ ],
+ showRole: true,
+ });
+
+ expect(findHeaders().at(6).text()).toBe(__('Action'));
expect(findCells().at(6).findComponent(GlButton).exists()).toBe(false);
},
);
@@ -207,7 +238,6 @@ describe('~/access_tokens/components/access_token_table_app', () => {
it('sorts rows alphabetically', async () => {
createComponent({ showRole: true });
- await triggerSuccess();
const cells = findCells();
@@ -226,7 +256,6 @@ describe('~/access_tokens/components/access_token_table_app', () => {
it('sorts rows by date', async () => {
createComponent({ showRole: true });
- await triggerSuccess();
const cells = findCells();
@@ -242,14 +271,20 @@ describe('~/access_tokens/components/access_token_table_app', () => {
expect(cells.at(10).text()).toBe('Never');
});
- it('should show the pagination component when needed', async () => {
- createComponent();
- expect(findPagination().exists()).toBe(false);
+ describe('pagination', () => {
+ it('does not show pagination component', () => {
+ createComponent({
+ initialActiveAccessTokens: Array(PAGE_SIZE).fill(defaultActiveAccessTokens[0]),
+ });
- await triggerSuccess(Array(PAGE_SIZE).fill(defaultActiveAccessTokens[0]));
- expect(findPagination().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(false);
+ });
- await triggerSuccess(Array(PAGE_SIZE + 1).fill(defaultActiveAccessTokens[0]));
- expect(findPagination().exists()).toBe(true);
+ it('shows the pagination component', () => {
+ createComponent({
+ initialActiveAccessTokens: Array(PAGE_SIZE + 1).fill(defaultActiveAccessTokens[0]),
+ });
+ expect(findPagination().exists()).toBe(true);
+ });
});
});
diff --git a/spec/frontend/access_tokens/components/new_access_token_app_spec.js b/spec/frontend/access_tokens/components/new_access_token_app_spec.js
index d12d200d214..b4af11169ad 100644
--- a/spec/frontend/access_tokens/components/new_access_token_app_spec.js
+++ b/spec/frontend/access_tokens/components/new_access_token_app_spec.js
@@ -22,6 +22,8 @@ describe('~/access_tokens/components/new_access_token_app', () => {
});
};
+ const findButtonEl = () => document.querySelector('[type=submit]');
+
const triggerSuccess = async (newToken = 'new token') => {
wrapper
.findComponent(DomElementListener)
@@ -41,7 +43,7 @@ describe('~/access_tokens/components/new_access_token_app', () => {
<input type="text" id="expires_at" value="2022-01-01"/>
<input type="text" value='1'/>
<input type="checkbox" checked/>
- <input type="submit" value="Create"/>
+ <button type="submit" value="Create" class="disabled" disabled="disabled"/>
</form>`,
);
@@ -120,10 +122,10 @@ describe('~/access_tokens/components/new_access_token_app', () => {
});
it('should not reset the submit button value', async () => {
- expect(document.querySelector('input[type=submit]').value).toBe('Create');
+ expect(findButtonEl().value).toBe('Create');
await triggerSuccess();
- expect(document.querySelector('input[type=submit]').value).toBe('Create');
+ expect(findButtonEl().value).toBe('Create');
});
});
});
@@ -162,6 +164,17 @@ describe('~/access_tokens/components/new_access_token_app', () => {
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
});
+
+ it('should enable the submit button', async () => {
+ const button = findButtonEl();
+ expect(button).toBeDisabled();
+ expect(button.className).toBe('disabled');
+
+ await triggerError();
+
+ expect(button).not.toBeDisabled();
+ expect(button.className).toBe('');
+ });
});
describe('before error or success', () => {
diff --git a/spec/frontend/access_tokens/index_spec.js b/spec/frontend/access_tokens/index_spec.js
index 55575ab25fc..1157e44f41a 100644
--- a/spec/frontend/access_tokens/index_spec.js
+++ b/spec/frontend/access_tokens/index_spec.js
@@ -1,7 +1,4 @@
-/* eslint-disable vue/require-prop-types */
-/* eslint-disable vue/one-component-per-file */
import { createWrapper } from '@vue/test-utils';
-import Vue from 'vue';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import {
@@ -10,10 +7,11 @@ import {
initNewAccessTokenApp,
initTokensApp,
} from '~/access_tokens';
-import * as AccessTokenTableApp from '~/access_tokens/components/access_token_table_app.vue';
+import AccessTokenTableApp from '~/access_tokens/components/access_token_table_app.vue';
import ExpiresAtField from '~/access_tokens/components/expires_at_field.vue';
-import * as NewAccessTokenApp from '~/access_tokens/components/new_access_token_app.vue';
-import * as TokensApp from '~/access_tokens/components/tokens_app.vue';
+import NewAccessTokenApp from '~/access_tokens/components/new_access_token_app.vue';
+import TokensApp from '~/access_tokens/components/tokens_app.vue';
+import { FORM_SELECTOR } from '~/access_tokens/components/constants';
import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from '~/access_tokens/constants';
import { __, sprintf } from '~/locale';
@@ -28,26 +26,7 @@ describe('access tokens', () => {
describe('initAccessTokenTableApp', () => {
const accessTokenType = 'personal access token';
const accessTokenTypePlural = 'personal access tokens';
- const initialActiveAccessTokens = [{ id: '1' }];
-
- const FakeAccessTokenTableApp = Vue.component('FakeComponent', {
- inject: [
- 'accessTokenType',
- 'accessTokenTypePlural',
- 'initialActiveAccessTokens',
- 'noActiveTokensMessage',
- 'showRole',
- ],
- props: [
- 'accessTokenType',
- 'accessTokenTypePlural',
- 'initialActiveAccessTokens',
- 'noActiveTokensMessage',
- 'showRole',
- ],
- render: () => null,
- });
- AccessTokenTableApp.default = FakeAccessTokenTableApp;
+ const initialActiveAccessTokens = [{ revoked_path: '1' }];
it('mounts the component and provides required values', () => {
setHTMLFixture(
@@ -60,19 +39,18 @@ describe('access tokens', () => {
);
const vueInstance = initAccessTokenTableApp();
-
wrapper = createWrapper(vueInstance);
- const component = wrapper.findComponent(FakeAccessTokenTableApp);
+ const component = wrapper.findComponent({ name: 'AccessTokenTableRoot' });
expect(component.exists()).toBe(true);
-
- expect(component.props()).toMatchObject({
+ expect(wrapper.findComponent(AccessTokenTableApp).vm).toMatchObject({
// Required value
accessTokenType,
accessTokenTypePlural,
initialActiveAccessTokens,
// Default values
+ information: undefined,
noActiveTokensMessage: sprintf(__('This user has no active %{accessTokenTypePlural}.'), {
accessTokenTypePlural,
}),
@@ -81,12 +59,14 @@ describe('access tokens', () => {
});
it('mounts the component and provides all values', () => {
+ const information = 'Additional information';
const noActiveTokensMessage = 'This group has no active access tokens.';
setHTMLFixture(
`<div id="js-access-token-table-app"
data-access-token-type="${accessTokenType}"
data-access-token-type-plural="${accessTokenTypePlural}"
data-initial-active-access-tokens=${JSON.stringify(initialActiveAccessTokens)}
+ data-information="${information}"
data-no-active-tokens-message="${noActiveTokensMessage}"
data-show-role
>
@@ -94,15 +74,15 @@ describe('access tokens', () => {
);
const vueInstance = initAccessTokenTableApp();
-
wrapper = createWrapper(vueInstance);
- const component = wrapper.findComponent(FakeAccessTokenTableApp);
+ const component = wrapper.findComponent({ name: 'AccessTokenTableRoot' });
expect(component.exists()).toBe(true);
- expect(component.props()).toMatchObject({
+ expect(component.findComponent(AccessTokenTableApp).vm).toMatchObject({
accessTokenType,
accessTokenTypePlural,
initialActiveAccessTokens,
+ information,
noActiveTokensMessage,
showRole: true,
});
@@ -157,23 +137,16 @@ describe('access tokens', () => {
it('mounts the component and sets `accessTokenType` prop', () => {
const accessTokenType = 'personal access token';
setHTMLFixture(
- `<div id="js-new-access-token-app" data-access-token-type="${accessTokenType}"></div>`,
+ `<div id="js-new-access-token-app" data-access-token-type="${accessTokenType}"></div>
+ <form id="${FORM_SELECTOR.slice(1)}"></form>`,
);
- const FakeNewAccessTokenApp = Vue.component('FakeComponent', {
- inject: ['accessTokenType'],
- props: ['accessTokenType'],
- render: () => null,
- });
- NewAccessTokenApp.default = FakeNewAccessTokenApp;
-
const vueInstance = initNewAccessTokenApp();
-
wrapper = createWrapper(vueInstance);
- const component = wrapper.findComponent(FakeNewAccessTokenApp);
+ const component = wrapper.findComponent({ name: 'NewAccessTokenRoot' });
expect(component.exists()).toBe(true);
- expect(component.props('accessTokenType')).toEqual(accessTokenType);
+ expect(component.findComponent(NewAccessTokenApp).vm).toMatchObject({ accessTokenType });
});
it('returns `null`', () => {
@@ -192,20 +165,12 @@ describe('access tokens', () => {
`<div id="js-tokens-app" data-tokens-data=${JSON.stringify(tokensData)}></div>`,
);
- const FakeTokensApp = Vue.component('FakeComponent', {
- inject: ['tokenTypes'],
- props: ['tokenTypes'],
- render: () => null,
- });
- TokensApp.default = FakeTokensApp;
-
const vueInstance = initTokensApp();
-
wrapper = createWrapper(vueInstance);
- const component = wrapper.findComponent(FakeTokensApp);
+ const component = wrapper.findComponent(TokensApp);
expect(component.exists()).toBe(true);
- expect(component.props('tokenTypes')).toEqual(tokensData);
+ expect(component.vm).toMatchObject({ tokenTypes: tokensData });
});
it('returns `null`', () => {
diff --git a/spec/frontend/admin/broadcast_messages/components/base_spec.js b/spec/frontend/admin/broadcast_messages/components/base_spec.js
new file mode 100644
index 00000000000..020e1c1d7c1
--- /dev/null
+++ b/spec/frontend/admin/broadcast_messages/components/base_spec.js
@@ -0,0 +1,112 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlPagination } from '@gitlab/ui';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
+import { createAlert } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { redirectTo } from '~/lib/utils/url_utility';
+import BroadcastMessagesBase from '~/admin/broadcast_messages/components/base.vue';
+import MessagesTable from '~/admin/broadcast_messages/components/messages_table.vue';
+import { generateMockMessages, MOCK_MESSAGES } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/lib/utils/url_utility');
+
+describe('BroadcastMessagesBase', () => {
+ let wrapper;
+ let axiosMock;
+
+ useMockLocationHelper();
+
+ const findTable = () => wrapper.findComponent(MessagesTable);
+ const findPagination = () => wrapper.findComponent(GlPagination);
+
+ function createComponent(props = {}) {
+ wrapper = shallowMount(BroadcastMessagesBase, {
+ propsData: {
+ page: 1,
+ messagesCount: MOCK_MESSAGES.length,
+ messages: MOCK_MESSAGES,
+ ...props,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ });
+
+ afterEach(() => {
+ axiosMock.restore();
+ wrapper.destroy();
+ });
+
+ it('renders the table and pagination when there are existing messages', () => {
+ createComponent();
+
+ expect(findTable().exists()).toBe(true);
+ expect(findPagination().exists()).toBe(true);
+ });
+
+ it('does not render the table when there are no visible messages', () => {
+ createComponent({ messages: [] });
+
+ expect(findTable().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(true);
+ });
+
+ it('does not remove a deleted message if it was not in visibleMessages', async () => {
+ createComponent();
+
+ findTable().vm.$emit('delete-message', -1);
+ await waitForPromises();
+
+ expect(axiosMock.history.delete).toHaveLength(0);
+ expect(wrapper.vm.visibleMessages.length).toBe(MOCK_MESSAGES.length);
+ });
+
+ it('does not remove a deleted message if the request fails', async () => {
+ createComponent();
+ const { id, delete_path } = MOCK_MESSAGES[0];
+ axiosMock.onDelete(delete_path).replyOnce(500);
+
+ findTable().vm.$emit('delete-message', id);
+ await waitForPromises();
+
+ expect(wrapper.vm.visibleMessages.find((m) => m.id === id)).not.toBeUndefined();
+ expect(createAlert).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: BroadcastMessagesBase.i18n.deleteError,
+ }),
+ );
+ });
+
+ it('removes a deleted message from visibleMessages on success', async () => {
+ createComponent();
+ const { id, delete_path } = MOCK_MESSAGES[0];
+ axiosMock.onDelete(delete_path).replyOnce(200);
+
+ findTable().vm.$emit('delete-message', id);
+ await waitForPromises();
+
+ expect(wrapper.vm.visibleMessages.find((m) => m.id === id)).toBeUndefined();
+ expect(wrapper.vm.totalMessages).toBe(MOCK_MESSAGES.length - 1);
+ });
+
+ it('redirects to the first page when totalMessages changes from 21 to 20', async () => {
+ window.location.pathname = `${TEST_HOST}/admin/broadcast_messages`;
+
+ const messages = generateMockMessages(21);
+ const { id, delete_path } = messages[0];
+ createComponent({ messages, messagesCount: messages.length });
+
+ axiosMock.onDelete(delete_path).replyOnce(200);
+
+ findTable().vm.$emit('delete-message', id);
+ await waitForPromises();
+
+ expect(redirectTo).toHaveBeenCalledWith(`${TEST_HOST}/admin/broadcast_messages?page=1`);
+ });
+});
diff --git a/spec/frontend/admin/broadcast_messages/components/messages_table_spec.js b/spec/frontend/admin/broadcast_messages/components/messages_table_spec.js
new file mode 100644
index 00000000000..349fab03853
--- /dev/null
+++ b/spec/frontend/admin/broadcast_messages/components/messages_table_spec.js
@@ -0,0 +1,51 @@
+import { mount } from '@vue/test-utils';
+import MessagesTable from '~/admin/broadcast_messages/components/messages_table.vue';
+import { MOCK_MESSAGES } from '../mock_data';
+
+describe('MessagesTable', () => {
+ let wrapper;
+
+ const findRows = () => wrapper.findAll('[data-testid="message-row"]');
+ const findTargetRoles = () => wrapper.find('[data-testid="target-roles-th"]');
+ const findDeleteButton = (id) => wrapper.find(`[data-testid="delete-message-${id}"]`);
+
+ function createComponent(props = {}, glFeatures = {}) {
+ wrapper = mount(MessagesTable, {
+ provide: {
+ glFeatures,
+ },
+ propsData: {
+ messages: MOCK_MESSAGES,
+ ...props,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a table row for each message', () => {
+ createComponent();
+
+ expect(findRows()).toHaveLength(MOCK_MESSAGES.length);
+ });
+
+ it('renders the "Target Roles" column when roleTargetedBroadcastMessages is enabled', () => {
+ createComponent({}, { roleTargetedBroadcastMessages: true });
+ expect(findTargetRoles().exists()).toBe(true);
+ });
+
+ it('does not render the "Target Roles" column when roleTargetedBroadcastMessages is disabled', () => {
+ createComponent();
+ expect(findTargetRoles().exists()).toBe(false);
+ });
+
+ it('emits a delete-message event when a delete button is clicked', () => {
+ const { id } = MOCK_MESSAGES[0];
+ createComponent();
+ findDeleteButton(id).element.click();
+ expect(wrapper.emitted('delete-message')).toHaveLength(1);
+ expect(wrapper.emitted('delete-message')[0]).toEqual([id]);
+ });
+});
diff --git a/spec/frontend/admin/broadcast_messages/mock_data.js b/spec/frontend/admin/broadcast_messages/mock_data.js
new file mode 100644
index 00000000000..8dd98c2319d
--- /dev/null
+++ b/spec/frontend/admin/broadcast_messages/mock_data.js
@@ -0,0 +1,17 @@
+const generateMockMessage = (id) => ({
+ id,
+ delete_path: `/admin/broadcast_messages/${id}.js`,
+ edit_path: `/admin/broadcast_messages/${id}/edit`,
+ starts_at: new Date().toISOString(),
+ ends_at: new Date().toISOString(),
+ preview: '<div>YEET</div>',
+ status: 'Expired',
+ target_path: '*/welcome',
+ target_roles: 'Maintainer, Owner',
+ type: 'Banner',
+});
+
+export const generateMockMessages = (n) =>
+ [...Array(n).keys()].map((id) => generateMockMessage(id + 1));
+
+export const MOCK_MESSAGES = generateMockMessages(5).map((id) => generateMockMessage(id));
diff --git a/spec/frontend/admin/deploy_keys/components/table_spec.js b/spec/frontend/admin/deploy_keys/components/table_spec.js
index a18506c0916..4d4a2caedde 100644
--- a/spec/frontend/admin/deploy_keys/components/table_spec.js
+++ b/spec/frontend/admin/deploy_keys/components/table_spec.js
@@ -9,7 +9,7 @@ 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';
+import { createAlert } from '~/flash';
jest.mock('~/api');
jest.mock('~/flash');
@@ -243,7 +243,7 @@ describe('DeployKeysTable', () => {
itRendersTheEmptyState();
it('displays flash', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DeployKeysTable.i18n.apiErrorMessage,
captureError: true,
error,
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index fe07f0fce00..a0aec347b6b 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -10,7 +10,7 @@ import AdminUserActions from '~/admin/users/components/user_actions.vue';
import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
import AdminUsersTable from '~/admin/users/components/users_table.vue';
import getUsersGroupCountsQuery from '~/admin/users/graphql/queries/get_users_group_counts.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import AdminUserDate from '~/vue_shared/components/user_date.vue';
import { users, paths, createGroupCountResponse } from '../mock_data';
@@ -135,7 +135,7 @@ describe('AdminUsersTable component', () => {
});
it('creates a flash message and captures the error', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Could not load user group counts. Please refresh the page to try again.',
captureError: true,
error: expect.any(Error),
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index 3e1438c37d6..7fb4f2d2463 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -1,4 +1,4 @@
-import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar } from '@gitlab/ui';
+import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
@@ -31,6 +31,7 @@ describe('AlertManagementTable', () => {
const findSearch = () => wrapper.findComponent(FilteredSearchBar);
const findSeverityColumnHeader = () => wrapper.findByTestId('alert-management-severity-sort');
const findFirstIDField = () => wrapper.findAllByTestId('idField').at(0);
+ const findFirstIDLink = () => wrapper.findAllByTestId('idField').at(0).findComponent(GlLink);
const findAssignees = () => wrapper.findAllByTestId('assigneesField');
const findSeverityFields = () => wrapper.findAllByTestId('severityField');
const findIssueFields = () => wrapper.findAllByTestId('issueField');
@@ -135,10 +136,11 @@ describe('AlertManagementTable', () => {
expect(findLoader().exists()).toBe(false);
expect(findAlertsTable().exists()).toBe(true);
expect(findAlerts()).toHaveLength(mockAlerts.length);
- expect(findAlerts().at(0).classes()).toContain('gl-hover-bg-blue-50');
+ expect(findAlerts().at(0).classes()).toContain('gl-hover-bg-gray-50');
+ expect(findAlerts().at(0).classes()).not.toContain('gl-hover-border-blue-200');
});
- it('displays the alert ID and title formatted correctly', () => {
+ it('displays the alert ID and title as a link', () => {
mountComponent({
data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
@@ -146,6 +148,8 @@ describe('AlertManagementTable', () => {
expect(findFirstIDField().exists()).toBe(true);
expect(findFirstIDField().text()).toBe(`#${mockAlerts[0].iid} ${mockAlerts[0].title}`);
+ expect(findFirstIDLink().text()).toBe(`#${mockAlerts[0].iid} ${mockAlerts[0].title}`);
+ expect(findFirstIDLink().attributes('href')).toBe('/1527542/details');
});
it('displays status dropdown', () => {
@@ -266,7 +270,8 @@ describe('AlertManagementTable', () => {
alerts: {
list: [
{
- iid: 1,
+ iid: '1',
+ title: 'SyntaxError: Invalid or unexpected token',
status: 'acknowledged',
startedAt: '2020-03-17T23:18:14.996Z',
severity: 'high',
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
index fb9e97e7505..e0075aa71d9 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
@@ -304,12 +304,12 @@ describe('AlertsSettingsForm', () => {
});
describe.each`
- payload | resetPayloadAndMappingConfirmed | disabled
- ${validSamplePayload} | ${true} | ${undefined}
- ${emptySamplePayload} | ${true} | ${undefined}
- ${validSamplePayload} | ${false} | ${'disabled'}
- ${emptySamplePayload} | ${false} | ${undefined}
- `('', ({ payload, resetPayloadAndMappingConfirmed, disabled }) => {
+ context | payload | resetPayloadAndMappingConfirmed | disabled
+ ${'valid payload, confirmed and enabled'} | ${validSamplePayload} | ${true} | ${undefined}
+ ${'empty payload, confirmed and enabled'} | ${emptySamplePayload} | ${true} | ${undefined}
+ ${'valid payload, unconfirmed and disabled'} | ${validSamplePayload} | ${false} | ${'disabled'}
+ ${'empty payload, unconfirmed and enabled'} | ${emptySamplePayload} | ${false} | ${undefined}
+ `('given $context', ({ payload, resetPayloadAndMappingConfirmed, disabled }) => {
const payloadResetMsg = resetPayloadAndMappingConfirmed
? 'was confirmed'
: 'was not confirmed';
@@ -333,12 +333,12 @@ describe('AlertsSettingsForm', () => {
describe('action buttons for sample payload', () => {
describe.each`
- resetPayloadAndMappingConfirmed | payloadExample | caption
- ${false} | ${validSamplePayload} | ${'Edit payload'}
- ${true} | ${emptySamplePayload} | ${'Parse payload fields'}
- ${true} | ${validSamplePayload} | ${'Parse payload fields'}
- ${false} | ${emptySamplePayload} | ${'Parse payload fields'}
- `('', ({ resetPayloadAndMappingConfirmed, payloadExample, caption }) => {
+ context | resetPayloadAndMappingConfirmed | payloadExample | caption
+ ${'valid payload, unconfirmed'} | ${false} | ${validSamplePayload} | ${'Edit payload'}
+ ${'empty payload, confirmed'} | ${true} | ${emptySamplePayload} | ${'Parse payload fields'}
+ ${'valid payload, confirmed'} | ${true} | ${validSamplePayload} | ${'Parse payload fields'}
+ ${'empty payload, unconfirmed'} | ${false} | ${emptySamplePayload} | ${'Parse payload fields'}
+ `('given $context', ({ resetPayloadAndMappingConfirmed, payloadExample, caption }) => {
const samplePayloadMsg = payloadExample ? 'was provided' : 'was not provided';
const payloadResetMsg = resetPayloadAndMappingConfirmed
? 'was confirmed'
@@ -402,24 +402,27 @@ describe('AlertsSettingsForm', () => {
${true} | ${true} | ${2} | ${false}
${true} | ${false} | ${1} | ${false}
${false} | ${true} | ${1} | ${false}
- `('', ({ alertFieldsProvided, multiIntegrations, integrationOption, visible }) => {
- const visibleMsg = visible ? 'rendered' : 'not rendered';
- const alertFieldsMsg = alertFieldsProvided ? 'provided' : 'not provided';
- const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
- const multiIntegrationsEnabled = multiIntegrations ? 'enabled' : 'not enabled';
+ `(
+ 'given alertFieldsProvided: $alertFieldsProvided, multiIntegrations: $multiIntegrations, integrationOption: $integrationOption, visible: $visible',
+ ({ alertFieldsProvided, multiIntegrations, integrationOption, visible }) => {
+ const visibleMsg = visible ? 'rendered' : 'not rendered';
+ const alertFieldsMsg = alertFieldsProvided ? 'provided' : 'not provided';
+ const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
+ const multiIntegrationsEnabled = multiIntegrations ? 'enabled' : 'not enabled';
+
+ it(`is ${visibleMsg} when multiIntegrations are ${multiIntegrationsEnabled}, integration type is ${integrationType} and alert fields are ${alertFieldsMsg}`, async () => {
+ createComponent({
+ multiIntegrations,
+ props: {
+ alertFields: alertFieldsProvided ? alertFields : [],
+ },
+ });
+ await selectOptionAtIndex(integrationOption);
- it(`is ${visibleMsg} when multiIntegrations are ${multiIntegrationsEnabled}, integration type is ${integrationType} and alert fields are ${alertFieldsMsg}`, async () => {
- createComponent({
- multiIntegrations,
- props: {
- alertFields: alertFieldsProvided ? alertFields : [],
- },
+ expect(findMappingBuilder().exists()).toBe(visible);
});
- await selectOptionAtIndex(integrationOption);
-
- expect(findMappingBuilder().exists()).toBe(visible);
- });
- });
+ },
+ );
});
describe('Form validation', () => {
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
index 0266adeb6c7..fcefcb7cf66 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -30,7 +30,7 @@ import {
INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
DELETE_INTEGRATION_ERROR,
} from '~/alerts_settings/utils/error_messages';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_SUCCESS } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
import {
@@ -327,7 +327,7 @@ describe('AlertsSettingsWrapper', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: ADD_INTEGRATION_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: ADD_INTEGRATION_ERROR });
});
it('shows an error alert when integration token reset fails', async () => {
@@ -336,7 +336,7 @@ describe('AlertsSettingsWrapper', () => {
findAlertsSettingsForm().vm.$emit('reset-token', {});
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
});
it('shows an error alert when integration update fails', async () => {
@@ -345,7 +345,7 @@ describe('AlertsSettingsWrapper', () => {
findAlertsSettingsForm().vm.$emit('update-integration', {});
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
});
describe('Test alert failure', () => {
@@ -360,17 +360,17 @@ describe('AlertsSettingsWrapper', () => {
it('shows an error alert when integration test payload is invalid', async () => {
mock.onPost(/(.*)/).replyOnce(httpStatusCodes.UNPROCESSABLE_ENTITY);
await wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' });
- expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
it('shows an error alert when integration is not activated', async () => {
mock.onPost(/(.*)/).replyOnce(httpStatusCodes.FORBIDDEN);
await wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' });
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
});
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
});
@@ -444,9 +444,9 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(alertsUpdateService, 'updateTestAlert').mockResolvedValueOnce({});
findAlertsSettingsForm().vm.$emit('test-alert-payload', '');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: i18n.alertSent,
- type: FLASH_TYPES.SUCCESS,
+ variant: VARIANT_SUCCESS,
});
});
@@ -454,7 +454,7 @@ describe('AlertsSettingsWrapper', () => {
jest.spyOn(alertsUpdateService, 'updateTestAlert').mockRejectedValueOnce({});
findAlertsSettingsForm().vm.$emit('test-alert-payload', '');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: INTEGRATION_PAYLOAD_TEST_ERROR,
});
});
@@ -486,7 +486,7 @@ describe('AlertsSettingsWrapper', () => {
await destroyHttpIntegration(wrapper);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
it('displays flash if mutation had a non-recoverable error', async () => {
@@ -497,7 +497,7 @@ describe('AlertsSettingsWrapper', () => {
await destroyHttpIntegration(wrapper);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_INTEGRATION_ERROR,
});
});
diff --git a/spec/frontend/api/projects_api_spec.js b/spec/frontend/api/projects_api_spec.js
index 8f40b557e1f..8459021421f 100644
--- a/spec/frontend/api/projects_api_spec.js
+++ b/spec/frontend/api/projects_api_spec.js
@@ -1,5 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
+import getTransferLocationsResponse from 'test_fixtures/api/projects/transfer_locations_page_1.json';
import * as projectsApi from '~/api/projects_api';
+import { DEFAULT_PER_PAGE } from '~/api';
import axios from '~/lib/utils/axios_utils';
describe('~/api/projects_api.js', () => {
@@ -59,4 +61,25 @@ describe('~/api/projects_api.js', () => {
});
});
});
+
+ describe('getTransferLocations', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'get');
+ });
+
+ it('retrieves transfer locations from the correct URL and returns them in the response data', async () => {
+ const params = { page: 1 };
+ const expectedUrl = '/api/v7/projects/1/transfer_locations';
+
+ mock.onGet(expectedUrl).replyOnce(200, { data: getTransferLocationsResponse });
+
+ await expect(projectsApi.getTransferLocations(projectId, params)).resolves.toMatchObject({
+ data: { data: getTransferLocationsResponse },
+ });
+
+ expect(axios.get).toHaveBeenCalledWith(expectedUrl, {
+ params: { ...params, per_page: DEFAULT_PER_PAGE },
+ });
+ });
+ });
});
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index b14bc5122b9..1a54b9909ba 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -185,7 +185,9 @@ describe('AwardsHandler', () => {
describe('::getAwardUrl', () => {
it('returns the url for request', () => {
- expect(awardsHandler.getAwardUrl()).toBe('http://test.host/-/snippets/1/toggle_award_emoji');
+ expect(awardsHandler.getAwardUrl()).toBe(
+ document.querySelector('.js-awards-block').dataset.awardUrl,
+ );
});
});
diff --git a/spec/frontend/badges/components/badge_form_spec.js b/spec/frontend/badges/components/badge_form_spec.js
index 6d8a00eb50b..0a736df7075 100644
--- a/spec/frontend/badges/components/badge_form_spec.js
+++ b/spec/frontend/badges/components/badge_form_spec.js
@@ -1,195 +1,183 @@
import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mount } from '@vue/test-utils';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'helpers/test_constants';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeForm from '~/badges/components/badge_form.vue';
import createEmptyBadge from '~/badges/empty_badge';
-import store from '~/badges/store';
+
+import createState from '~/badges/store/state';
+import mutations from '~/badges/store/mutations';
+import actions from '~/badges/store/actions';
+
import axios from '~/lib/utils/axios_utils';
-// avoid preview background process
-BadgeForm.methods.debouncedPreview = () => {};
+Vue.use(Vuex);
describe('BadgeForm component', () => {
- const Component = Vue.extend(BadgeForm);
let axiosMock;
- let vm;
+ let mockedActions;
+ let wrapper;
+
+ const createComponent = (propsData, customState = {}) => {
+ mockedActions = Object.fromEntries(Object.keys(actions).map((name) => [name, jest.fn()]));
+
+ const store = new Vuex.Store({
+ state: {
+ ...createState(),
+ ...customState,
+ },
+ mutations,
+ actions: mockedActions,
+ });
- beforeEach(() => {
- setHTMLFixture(`
- <div id="dummy-element"></div>
- `);
+ wrapper = mount(BadgeForm, {
+ store,
+ propsData,
+ attachTo: document.body,
+ });
+ };
+ beforeEach(() => {
axiosMock = new MockAdapter(axios);
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
axiosMock.restore();
- resetHTMLFixture();
});
- describe('methods', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- el: '#dummy-element',
- store,
- props: {
- isEditing: false,
- },
- });
- });
+ it('stops editing when cancel button is clicked', async () => {
+ createComponent({ isEditing: true });
- describe('onCancel', () => {
- it('calls stopEditing', () => {
- jest.spyOn(vm, 'stopEditing').mockImplementation(() => {});
+ const cancelButton = wrapper.find('.row-content-block button');
- vm.onCancel();
+ await cancelButton.trigger('click');
- expect(vm.stopEditing).toHaveBeenCalled();
- });
- });
+ expect(mockedActions.stopEditing).toHaveBeenCalled();
});
- const sharedSubmitTests = (submitAction) => {
+ const sharedSubmitTests = (submitAction, props) => {
const nameSelector = '#badge-name';
const imageUrlSelector = '#badge-image-url';
- const findImageUrlElement = () => vm.$el.querySelector(imageUrlSelector);
+ const findImageUrl = () => wrapper.find(imageUrlSelector);
const linkUrlSelector = '#badge-link-url';
- const findLinkUrlElement = () => vm.$el.querySelector(linkUrlSelector);
+ const findLinkUrl = () => wrapper.find(linkUrlSelector);
const setValue = (inputElementSelector, value) => {
- const inputElement = vm.$el.querySelector(inputElementSelector);
- inputElement.value = value;
- inputElement.dispatchEvent(new Event('input'));
+ const input = wrapper.find(inputElementSelector);
+ return input.setValue(value);
};
const submitForm = () => {
- const submitButton = vm.$el.querySelector('button[type="submit"]');
- submitButton.click();
+ const submitButton = wrapper.find('button[type="submit"]');
+ return submitButton.trigger('click');
};
const expectInvalidInput = (inputElementSelector) => {
- const inputElement = vm.$el.querySelector(inputElementSelector);
+ const input = wrapper.find(inputElementSelector);
- expect(inputElement.checkValidity()).toBe(false);
- const feedbackElement = vm.$el.querySelector(`${inputElementSelector} + .invalid-feedback`);
+ expect(input.element.checkValidity()).toBe(false);
+ const feedbackElement = wrapper.find(`${inputElementSelector} + .invalid-feedback`);
- expect(feedbackElement).toBeVisible();
+ expect(feedbackElement.isVisible()).toBe(true);
};
- beforeEach(async () => {
- jest.spyOn(vm, submitAction).mockReturnValue(Promise.resolve());
- store.replaceState({
- ...store.state,
+ beforeEach(() => {
+ createComponent(props, {
badgeInAddForm: createEmptyBadge(),
badgeInEditForm: createEmptyBadge(),
isSaving: false,
});
- await nextTick();
setValue(nameSelector, 'TestBadge');
setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
});
- it('returns immediately if imageUrl is empty', () => {
- setValue(imageUrlSelector, '');
+ it('returns immediately if imageUrl is empty', async () => {
+ await setValue(imageUrlSelector, '');
- submitForm();
+ await submitForm();
expectInvalidInput(imageUrlSelector);
- expect(vm[submitAction]).not.toHaveBeenCalled();
+ expect(mockedActions[submitAction]).not.toHaveBeenCalled();
});
- it('returns immediately if imageUrl is malformed', () => {
- setValue(imageUrlSelector, 'not-a-url');
+ it('returns immediately if imageUrl is malformed', async () => {
+ await setValue(imageUrlSelector, 'not-a-url');
- submitForm();
+ await submitForm();
expectInvalidInput(imageUrlSelector);
- expect(vm[submitAction]).not.toHaveBeenCalled();
+ expect(mockedActions[submitAction]).not.toHaveBeenCalled();
});
- it('returns immediately if linkUrl is empty', () => {
- setValue(linkUrlSelector, '');
+ it('returns immediately if linkUrl is empty', async () => {
+ await setValue(linkUrlSelector, '');
- submitForm();
+ await submitForm();
expectInvalidInput(linkUrlSelector);
- expect(vm[submitAction]).not.toHaveBeenCalled();
+ expect(mockedActions[submitAction]).not.toHaveBeenCalled();
});
- it('returns immediately if linkUrl is malformed', () => {
- setValue(linkUrlSelector, 'not-a-url');
+ it('returns immediately if linkUrl is malformed', async () => {
+ await setValue(linkUrlSelector, 'not-a-url');
- submitForm();
+ await submitForm();
expectInvalidInput(linkUrlSelector);
- expect(vm[submitAction]).not.toHaveBeenCalled();
+ expect(mockedActions[submitAction]).not.toHaveBeenCalled();
});
- it(`calls ${submitAction}`, () => {
- submitForm();
+ it(`calls ${submitAction}`, async () => {
+ await submitForm();
- expect(findImageUrlElement().checkValidity()).toBe(true);
- expect(findLinkUrlElement().checkValidity()).toBe(true);
- expect(vm[submitAction]).toHaveBeenCalled();
+ expect(findImageUrl().element.checkValidity()).toBe(true);
+ expect(findLinkUrl().element.checkValidity()).toBe(true);
+ expect(mockedActions[submitAction]).toHaveBeenCalled();
});
};
describe('if isEditing is false', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- el: '#dummy-element',
- store,
- props: {
- isEditing: false,
- },
- });
- });
+ const props = { isEditing: false };
it('renders one button', () => {
- expect(vm.$el.querySelector('.row-content-block')).toBeNull();
- const buttons = vm.$el.querySelectorAll('.form-group:last-of-type button');
+ createComponent(props);
+
+ expect(wrapper.find('.row-content-block').exists()).toBe(false);
+ const buttons = wrapper.findAll('.form-group:last-of-type button');
- expect(buttons.length).toBe(1);
- const buttonAddElement = buttons[0];
+ expect(buttons).toHaveLength(1);
+ const buttonAddWrapper = buttons.at(0);
- expect(buttonAddElement).toBeVisible();
- expect(buttonAddElement).toHaveText('Add badge');
+ expect(buttonAddWrapper.isVisible()).toBe(true);
+ expect(buttonAddWrapper.text()).toBe('Add badge');
});
- sharedSubmitTests('addBadge');
+ sharedSubmitTests('addBadge', props);
});
describe('if isEditing is true', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(Component, {
- el: '#dummy-element',
- store,
- props: {
- isEditing: true,
- },
- });
- });
+ const props = { isEditing: true };
it('renders two buttons', () => {
- const buttons = vm.$el.querySelectorAll('.row-content-block button');
+ createComponent(props);
+ const buttons = wrapper.findAll('.row-content-block button');
- expect(buttons.length).toBe(2);
- const buttonSaveElement = buttons[1];
+ expect(buttons).toHaveLength(2);
- expect(buttonSaveElement).toBeVisible();
- expect(buttonSaveElement).toHaveText('Save changes');
- const buttonCancelElement = buttons[0];
+ const saveButton = buttons.at(1);
+ expect(saveButton.isVisible()).toBe(true);
+ expect(saveButton.text()).toBe('Save changes');
- expect(buttonCancelElement).toBeVisible();
- expect(buttonCancelElement).toHaveText('Cancel');
+ const cancelButton = buttons.at(0);
+ expect(cancelButton.isVisible()).toBe(true);
+ expect(cancelButton.text()).toBe('Cancel');
});
- sharedSubmitTests('saveBadge');
+ sharedSubmitTests('saveBadge', props);
});
});
diff --git a/spec/frontend/badges/components/badge_list_row_spec.js b/spec/frontend/badges/components/badge_list_row_spec.js
index ad8426f3168..ee7ccac974a 100644
--- a/spec/frontend/badges/components/badge_list_row_spec.js
+++ b/spec/frontend/badges/components/badge_list_row_spec.js
@@ -1,103 +1,118 @@
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mount } from '@vue/test-utils';
+
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeListRow from '~/badges/components/badge_list_row.vue';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
-import store from '~/badges/store';
+
+import createState from '~/badges/store/state';
+import mutations from '~/badges/store/mutations';
+import actions from '~/badges/store/actions';
+
import { createDummyBadge } from '../dummy_badge';
+Vue.use(Vuex);
+
describe('BadgeListRow component', () => {
- const Component = Vue.extend(BadgeListRow);
let badge;
- let vm;
-
- beforeEach(() => {
- setHTMLFixture(`
- <div id="delete-badge-modal" class="modal"></div>
- <div id="dummy-element"></div>
- `);
- store.replaceState({
- ...store.state,
- kind: PROJECT_BADGE,
+ let wrapper;
+ let mockedActions;
+
+ const createComponent = (kind) => {
+ setHTMLFixture(`<div id="delete-badge-modal" class="modal"></div>`);
+
+ mockedActions = Object.fromEntries(Object.keys(actions).map((name) => [name, jest.fn()]));
+
+ const store = new Vuex.Store({
+ state: {
+ ...createState(),
+ kind: PROJECT_BADGE,
+ },
+ mutations,
+ actions: mockedActions,
});
+
badge = createDummyBadge();
- vm = mountComponentWithStore(Component, {
- el: '#dummy-element',
+ badge.kind = kind;
+ wrapper = mount(BadgeListRow, {
+ attachTo: document.body,
store,
- props: { badge },
+ propsData: { badge },
});
- });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
resetHTMLFixture();
});
- it('renders the badge', () => {
- const badgeElement = vm.$el.querySelector('.project-badge');
+ describe('for a project badge', () => {
+ beforeEach(() => {
+ createComponent(PROJECT_BADGE);
+ });
- expect(badgeElement).not.toBeNull();
- expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
- });
+ it('renders the badge', () => {
+ const badgeImage = wrapper.find('.project-badge');
- it('renders the badge name', () => {
- expect(vm.$el.innerText).toMatch(badge.name);
- });
+ expect(badgeImage.exists()).toBe(true);
+ expect(badgeImage.attributes('src')).toBe(badge.renderedImageUrl);
+ });
- it('renders the badge link', () => {
- expect(vm.$el.innerText).toMatch(badge.linkUrl);
- });
+ it('renders the badge name', () => {
+ expect(wrapper.text()).toMatch(badge.name);
+ });
- it('renders the badge kind', () => {
- expect(vm.$el.innerText).toMatch('Project Badge');
- });
+ it('renders the badge link', () => {
+ expect(wrapper.text()).toMatch(badge.linkUrl);
+ });
- it('shows edit and delete buttons', () => {
- const buttons = vm.$el.querySelectorAll('.table-button-footer button');
+ it('renders the badge kind', () => {
+ expect(wrapper.text()).toMatch('Project Badge');
+ });
- expect(buttons).toHaveLength(2);
- const buttonEditElement = buttons[0];
+ it('shows edit and delete buttons', () => {
+ const buttons = wrapper.findAll('.table-button-footer button');
- expect(buttonEditElement).toBeVisible();
- expect(buttonEditElement).toHaveSpriteIcon('pencil');
- const buttonDeleteElement = buttons[1];
+ expect(buttons).toHaveLength(2);
+ const editButton = buttons.at(0);
- expect(buttonDeleteElement).toBeVisible();
- expect(buttonDeleteElement).toHaveSpriteIcon('remove');
- });
+ expect(editButton.isVisible()).toBe(true);
+ expect(editButton.element).toHaveSpriteIcon('pencil');
- it('calls editBadge when clicking then edit button', () => {
- jest.spyOn(vm, 'editBadge').mockImplementation(() => {});
+ const deleteButton = buttons.at(1);
+ expect(deleteButton.isVisible()).toBe(true);
+ expect(deleteButton.element).toHaveSpriteIcon('remove');
+ });
- const editButton = vm.$el.querySelector('.table-button-footer button:first-of-type');
- editButton.click();
+ it('calls editBadge when clicking then edit button', async () => {
+ const editButton = wrapper.find('.table-button-footer button:first-of-type');
- expect(vm.editBadge).toHaveBeenCalled();
- });
+ await editButton.trigger('click');
+
+ expect(mockedActions.editBadge).toHaveBeenCalled();
+ });
- it('calls updateBadgeInModal and shows modal when clicking then delete button', async () => {
- jest.spyOn(vm, 'updateBadgeInModal').mockImplementation(() => {});
+ it('calls updateBadgeInModal and shows modal when clicking then delete button', async () => {
+ const deleteButton = wrapper.find('.table-button-footer button:last-of-type');
- const deleteButton = vm.$el.querySelector('.table-button-footer button:last-of-type');
- deleteButton.click();
+ await deleteButton.trigger('click');
- await nextTick();
- expect(vm.updateBadgeInModal).toHaveBeenCalled();
+ expect(mockedActions.updateBadgeInModal).toHaveBeenCalled();
+ });
});
describe('for a group badge', () => {
- beforeEach(async () => {
- badge.kind = GROUP_BADGE;
-
- await nextTick();
+ beforeEach(() => {
+ createComponent(GROUP_BADGE);
});
it('renders the badge kind', () => {
- expect(vm.$el.innerText).toMatch('Group Badge');
+ expect(wrapper.text()).toMatch('Group Badge');
});
it('hides edit and delete buttons', () => {
- const buttons = vm.$el.querySelectorAll('.table-button-footer button');
+ const buttons = wrapper.findAll('.table-button-footer button');
expect(buttons).toHaveLength(0);
});
diff --git a/spec/frontend/badges/components/badge_list_spec.js b/spec/frontend/badges/components/badge_list_spec.js
index 32cd9483ef8..606b1bc9cce 100644
--- a/spec/frontend/badges/components/badge_list_spec.js
+++ b/spec/frontend/badges/components/badge_list_spec.js
@@ -1,83 +1,96 @@
-import Vue, { nextTick } from 'vue';
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mount } from '@vue/test-utils';
+
import BadgeList from '~/badges/components/badge_list.vue';
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
-import store from '~/badges/store';
+
+import createState from '~/badges/store/state';
+import mutations from '~/badges/store/mutations';
+import actions from '~/badges/store/actions';
+
import { createDummyBadge } from '../dummy_badge';
-describe('BadgeList component', () => {
- const Component = Vue.extend(BadgeList);
- const numberOfDummyBadges = 3;
- let vm;
-
- beforeEach(() => {
- setHTMLFixture('<div id="dummy-element"></div>');
- const badges = [];
- for (let id = 0; id < numberOfDummyBadges; id += 1) {
- badges.push({ id, ...createDummyBadge() });
- }
- store.replaceState({
- ...store.state,
- badges,
- kind: PROJECT_BADGE,
- isLoading: false,
- });
+Vue.use(Vuex);
- // Can be removed once GlLoadingIcon no longer throws a warning
- jest.spyOn(global.console, 'warn').mockImplementation(() => jest.fn());
+const numberOfDummyBadges = 3;
+const badges = Array.from({ length: numberOfDummyBadges }).map((_, idx) => ({
+ ...createDummyBadge(),
+ id: idx,
+}));
- vm = mountComponentWithStore(Component, {
- el: '#dummy-element',
- store,
+describe('BadgeList component', () => {
+ let wrapper;
+
+ const createComponent = (customState) => {
+ const mockedActions = Object.fromEntries(Object.keys(actions).map((name) => [name, jest.fn()]));
+
+ const store = new Vuex.Store({
+ state: {
+ ...createState(),
+ isLoading: false,
+ ...customState,
+ },
+ mutations,
+ actions: mockedActions,
});
- });
+
+ wrapper = mount(BadgeList, { store });
+ };
afterEach(() => {
- vm.$destroy();
- resetHTMLFixture();
+ wrapper.destroy();
});
- it('renders a header with the badge count', () => {
- const header = vm.$el.querySelector('.card-header');
+ describe('for project badges', () => {
+ it('renders a header with the badge count', () => {
+ createComponent({
+ kind: PROJECT_BADGE,
+ badges,
+ });
- expect(header).toHaveText(new RegExp(`Your badges\\s+${numberOfDummyBadges}`));
- });
+ const header = wrapper.find('.card-header');
- it('renders a row for each badge', () => {
- const rows = vm.$el.querySelectorAll('.gl-responsive-table-row');
+ expect(header.text()).toMatchInterpolatedText('Your badges 3');
+ });
- expect(rows).toHaveLength(numberOfDummyBadges);
- });
+ it('renders a row for each badge', () => {
+ createComponent({
+ kind: PROJECT_BADGE,
+ badges,
+ });
- it('renders a message if no badges exist', async () => {
- store.state.badges = [];
+ const rows = wrapper.findAll('.gl-responsive-table-row');
- await nextTick();
- expect(vm.$el.innerText).toMatch('This project has no badges');
- });
+ expect(rows).toHaveLength(numberOfDummyBadges);
+ });
- it('shows a loading icon when loading', async () => {
- store.state.isLoading = true;
+ it('renders a message if no badges exist', () => {
+ createComponent({
+ kind: PROJECT_BADGE,
+ badges: [],
+ });
- await nextTick();
- const loadingIcon = vm.$el.querySelector('.gl-spinner');
+ expect(wrapper.text()).toMatch('This project has no badges');
+ });
- expect(loadingIcon).toBeVisible();
- });
+ it('shows a loading icon when loading', () => {
+ createComponent({ isLoading: true });
- describe('for group badges', () => {
- beforeEach(async () => {
- store.state.kind = GROUP_BADGE;
+ const loadingIcon = wrapper.find('.gl-spinner');
- await nextTick();
+ expect(loadingIcon.isVisible()).toBe(true);
});
+ });
- it('renders a message if no badges exist', async () => {
- store.state.badges = [];
+ describe('for group badges', () => {
+ it('renders a message if no badges exist', () => {
+ createComponent({
+ kind: GROUP_BADGE,
+ badges: [],
+ });
- await nextTick();
- expect(vm.$el.innerText).toMatch('This group has no badges');
+ expect(wrapper.text()).toMatch('This group has no badges');
});
});
});
diff --git a/spec/frontend/badges/components/badge_spec.js b/spec/frontend/badges/components/badge_spec.js
index 19b3a9f23a6..b468e38f19e 100644
--- a/spec/frontend/badges/components/badge_spec.js
+++ b/spec/frontend/badges/components/badge_spec.js
@@ -1,138 +1,78 @@
-import Vue, { nextTick } from 'vue';
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+
import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants';
import Badge from '~/badges/components/badge.vue';
describe('Badge component', () => {
- const Component = Vue.extend(Badge);
const dummyProps = {
imageUrl: DUMMY_IMAGE_URL,
linkUrl: `${TEST_HOST}/badge/link/url`,
};
- let vm;
+ let wrapper;
const findElements = () => {
- const buttons = vm.$el.querySelectorAll('button');
+ const buttons = wrapper.findAll('button');
return {
- badgeImage: vm.$el.querySelector('img.project-badge'),
- loadingIcon: vm.$el.querySelector('.gl-spinner'),
- reloadButton: buttons[buttons.length - 1],
+ badgeImage: wrapper.find('img.project-badge'),
+ loadingIcon: wrapper.find('.gl-spinner'),
+ reloadButton: buttons.at(buttons.length - 1),
};
};
- const createComponent = (props, el = null) => {
- vm = mountComponent(Component, props, el);
- const { badgeImage } = findElements();
- return new Promise((resolve) => {
- badgeImage.addEventListener('load', resolve);
- // Manually dispatch load event as it is not triggered
- badgeImage.dispatchEvent(new Event('load'));
- }).then(() => nextTick());
+ const createComponent = (propsData) => {
+ wrapper = mount(Badge, { propsData });
};
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- describe('watchers', () => {
- describe('imageUrl', () => {
- it('sets isLoading and resets numRetries and hasError', async () => {
- const props = { ...dummyProps };
- await createComponent(props);
- expect(vm.isLoading).toBe(false);
- vm.hasError = true;
- vm.numRetries = 42;
-
- vm.imageUrl = `${props.imageUrl}#something/else`;
- await nextTick();
- expect(vm.isLoading).toBe(true);
- expect(vm.numRetries).toBe(0);
- expect(vm.hasError).toBe(false);
- });
- });
+ beforeEach(() => {
+ return createComponent({ ...dummyProps }, '#dummy-element');
});
- describe('methods', () => {
- beforeEach(async () => {
- await createComponent({ ...dummyProps });
- });
+ it('shows a badge image after loading', async () => {
+ const { badgeImage, loadingIcon, reloadButton } = findElements();
+ badgeImage.element.dispatchEvent(new Event('load'));
- it('onError resets isLoading and sets hasError', () => {
- vm.hasError = false;
- vm.isLoading = true;
+ await nextTick();
- vm.onError();
+ expect(badgeImage.isVisible()).toBe(true);
+ expect(loadingIcon.isVisible()).toBe(false);
+ expect(reloadButton.isVisible()).toBe(false);
+ expect(wrapper.find('.btn-group').isVisible()).toBe(false);
+ });
- expect(vm.hasError).toBe(true);
- expect(vm.isLoading).toBe(false);
- });
+ it('shows a loading icon when loading', () => {
+ const { badgeImage, loadingIcon, reloadButton } = findElements();
- it('onLoad sets isLoading', () => {
- vm.isLoading = true;
+ expect(badgeImage.isVisible()).toBe(false);
+ expect(loadingIcon.isVisible()).toBe(true);
+ expect(reloadButton.isVisible()).toBe(false);
+ expect(wrapper.find('.btn-group').isVisible()).toBe(false);
+ });
- vm.onLoad();
+ it('shows an error and reload button if loading failed', async () => {
+ const { badgeImage, loadingIcon, reloadButton } = findElements();
+ badgeImage.element.dispatchEvent(new Event('error'));
- expect(vm.isLoading).toBe(false);
- });
+ await nextTick();
- it('reloadImage resets isLoading and hasError and increases numRetries', () => {
- vm.hasError = true;
- vm.isLoading = false;
- vm.numRetries = 0;
+ expect(badgeImage.isVisible()).toBe(false);
+ expect(loadingIcon.isVisible()).toBe(false);
+ expect(reloadButton.isVisible()).toBe(true);
+ expect(reloadButton.element).toHaveSpriteIcon('retry');
+ expect(wrapper.text()).toBe('No badge image');
+ });
- vm.reloadImage();
+ it('retries an image when loading failed and reload button is clicked', async () => {
+ const { badgeImage, reloadButton } = findElements();
+ badgeImage.element.dispatchEvent(new Event('error'));
+ await nextTick();
- expect(vm.hasError).toBe(false);
- expect(vm.isLoading).toBe(true);
- expect(vm.numRetries).toBe(1);
- });
- });
+ await reloadButton.trigger('click');
- describe('behavior', () => {
- beforeEach(() => {
- setHTMLFixture('<div id="dummy-element"></div>');
- return createComponent({ ...dummyProps }, '#dummy-element');
- });
-
- afterEach(() => {
- resetHTMLFixture();
- });
-
- it('shows a badge image after loading', () => {
- expect(vm.isLoading).toBe(false);
- expect(vm.hasError).toBe(false);
- const { badgeImage, loadingIcon, reloadButton } = findElements();
-
- expect(badgeImage).toBeVisible();
- expect(loadingIcon).toBeHidden();
- expect(reloadButton).toBeHidden();
- expect(vm.$el.querySelector('.btn-group')).toBeHidden();
- });
-
- it('shows a loading icon when loading', async () => {
- vm.isLoading = true;
-
- await nextTick();
- const { badgeImage, loadingIcon, reloadButton } = findElements();
-
- expect(badgeImage).toBeHidden();
- expect(loadingIcon).toBeVisible();
- expect(reloadButton).toBeHidden();
- expect(vm.$el.querySelector('.btn-group')).toBeHidden();
- });
-
- it('shows an error and reload button if loading failed', async () => {
- vm.hasError = true;
-
- await nextTick();
- const { badgeImage, loadingIcon, reloadButton } = findElements();
-
- expect(badgeImage).toBeHidden();
- expect(loadingIcon).toBeHidden();
- expect(reloadButton).toBeVisible();
- expect(reloadButton).toHaveSpriteIcon('retry');
- expect(vm.$el.innerText.trim()).toBe('No badge image');
- });
+ expect(badgeImage.attributes('src')).toBe(`${dummyProps.imageUrl}#retries=1`);
});
});
diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js
index 390ef21929c..c3a7946c85c 100644
--- a/spec/frontend/batch_comments/components/drafts_count_spec.js
+++ b/spec/frontend/batch_comments/components/drafts_count_spec.js
@@ -1,40 +1,36 @@
-import Vue, { nextTick } from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import DraftsCount from '~/batch_comments/components/drafts_count.vue';
import { createStore } from '~/batch_comments/stores';
describe('Batch comments drafts count component', () => {
- let vm;
- let Component;
-
- beforeAll(() => {
- Component = Vue.extend(DraftsCount);
- });
+ let store;
+ let wrapper;
beforeEach(() => {
- const store = createStore();
+ store = createStore();
store.state.batchComments.drafts.push('comment');
- vm = mountComponentWithStore(Component, { store });
+ wrapper = mount(DraftsCount, { store });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders count', () => {
- expect(vm.$el.textContent).toContain('1');
+ expect(wrapper.text()).toContain('1');
});
it('renders screen reader text', async () => {
- const el = vm.$el.querySelector('.sr-only');
+ const el = wrapper.find('.sr-only');
- expect(el.textContent).toContain('draft');
-
- vm.$store.state.batchComments.drafts.push('comment 2');
+ expect(el.text()).toContain('draft');
+ store.state.batchComments.drafts.push('comment 2');
await nextTick();
- expect(el.textContent).toContain('drafts');
+
+ expect(el.text()).toContain('drafts');
});
});
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 91e6b84a216..6a104f0c787 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -1,5 +1,4 @@
-import Vue from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import PreviewItem from '~/batch_comments/components/preview_item.vue';
import { createStore } from '~/batch_comments/stores';
import diffsModule from '~/diffs/store/modules';
@@ -8,8 +7,7 @@ import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
describe('Batch comments draft preview item component', () => {
- let vm;
- let Component;
+ let wrapper;
let draft;
function createComponent(isLast = false, extra = {}, extendStore = () => {}) {
@@ -24,21 +22,17 @@ describe('Batch comments draft preview item component', () => {
...extra,
};
- vm = mountComponentWithStore(Component, { store, props: { draft, isLast } });
+ wrapper = mount(PreviewItem, { store, propsData: { draft, isLast } });
}
- beforeAll(() => {
- Component = Vue.extend(PreviewItem);
- });
-
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders text content', () => {
createComponent(false, { note_html: '<img src="" /><p>Hello world</p>' });
- expect(vm.$el.querySelector('.review-preview-item-content').innerHTML).toEqual(
+ expect(wrapper.find('.review-preview-item-content').element.innerHTML).toBe(
'<p>Hello world</p>',
);
});
@@ -47,9 +41,7 @@ describe('Batch comments draft preview item component', () => {
it('renders file path', () => {
createComponent(false, { file_path: 'index.js', file_hash: 'abc', position: {} });
- expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
- 'index.js',
- );
+ expect(wrapper.find('.review-preview-item-header-text').text()).toContain('index.js');
});
it('renders new line position', () => {
@@ -66,7 +58,7 @@ describe('Batch comments draft preview item component', () => {
},
});
- expect(vm.$el.querySelector('.bold').textContent).toContain(':+1');
+ expect(wrapper.find('.bold').text()).toContain(':+1');
});
it('renders old line position', () => {
@@ -82,7 +74,7 @@ describe('Batch comments draft preview item component', () => {
},
});
- expect(vm.$el.querySelector('.bold').textContent).toContain(':2');
+ expect(wrapper.find('.bold').text()).toContain(':2');
});
it('renders image position', () => {
@@ -92,7 +84,7 @@ describe('Batch comments draft preview item component', () => {
position: { position_type: 'image', x: 10, y: 20 },
});
- expect(vm.$el.querySelector('.bold').textContent).toContain('10x 20y');
+ expect(wrapper.find('.bold').text()).toContain('10x 20y');
});
});
@@ -113,15 +105,13 @@ describe('Batch comments draft preview item component', () => {
});
it('renders title', () => {
- expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
+ expect(wrapper.find('.review-preview-item-header-text').text()).toContain(
"Author 'Nick' Name's thread",
);
});
it('renders thread resolved text', () => {
- expect(vm.$el.querySelector('.draft-note-resolution').textContent).toContain(
- 'Thread will be resolved',
- );
+ expect(wrapper.find('.draft-note-resolution').text()).toContain('Thread will be resolved');
});
});
@@ -131,9 +121,7 @@ describe('Batch comments draft preview item component', () => {
store.state.notes.discussions.push({});
});
- expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
- 'Your new comment',
- );
+ expect(wrapper.find('.review-preview-item-header-text').text()).toContain('Your new comment');
});
});
});
diff --git a/spec/frontend/batch_comments/components/publish_button_spec.js b/spec/frontend/batch_comments/components/publish_button_spec.js
index 9a782ec09b6..5e3fa3e9446 100644
--- a/spec/frontend/batch_comments/components/publish_button_spec.js
+++ b/spec/frontend/batch_comments/components/publish_button_spec.js
@@ -1,38 +1,34 @@
-import Vue, { nextTick } from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import PublishButton from '~/batch_comments/components/publish_button.vue';
import { createStore } from '~/batch_comments/stores';
describe('Batch comments publish button component', () => {
- let vm;
- let Component;
-
- beforeAll(() => {
- Component = Vue.extend(PublishButton);
- });
+ let wrapper;
+ let store;
beforeEach(() => {
- const store = createStore();
+ store = createStore();
- vm = mountComponentWithStore(Component, { store, props: { shouldPublish: true } });
+ wrapper = mount(PublishButton, { store, propsData: { shouldPublish: true } });
- jest.spyOn(vm.$store, 'dispatch').mockImplementation();
+ jest.spyOn(store, 'dispatch').mockImplementation();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- it('dispatches publishReview on click', () => {
- vm.$el.click();
+ it('dispatches publishReview on click', async () => {
+ await wrapper.trigger('click');
- expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
+ expect(store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
});
it('sets loading when isPublishing is true', async () => {
- vm.$store.state.batchComments.isPublishing = true;
+ store.state.batchComments.isPublishing = true;
await nextTick();
- expect(vm.$el.getAttribute('disabled')).toBe('disabled');
+ expect(wrapper.attributes('disabled')).toBe('disabled');
});
});
diff --git a/spec/frontend/behaviors/bind_in_out_spec.js b/spec/frontend/behaviors/bind_in_out_spec.js
index 4d958e30b4d..7b40b1d3cd7 100644
--- a/spec/frontend/behaviors/bind_in_out_spec.js
+++ b/spec/frontend/behaviors/bind_in_out_spec.js
@@ -1,4 +1,3 @@
-import ClassSpecHelper from 'helpers/class_spec_helper';
import BindInOut from '~/behaviors/bind_in_out';
describe('BindInOut', () => {
@@ -142,7 +141,9 @@ describe('BindInOut', () => {
testContext.initAll = BindInOut.initAll();
});
- ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'initAll');
+ it('should be a static method', () => {
+ expect(BindInOut.initAll).toEqual(expect.any(Function));
+ });
it('should call .querySelectorAll', () => {
expect(document.querySelectorAll).toHaveBeenCalledWith('*[data-bind-in]');
@@ -169,7 +170,9 @@ describe('BindInOut', () => {
testContext.init = BindInOut.init({}, {});
});
- ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'init');
+ it('should be a static method', () => {
+ expect(BindInOut.init).toEqual(expect.any(Function));
+ });
it('should call .addEvents', () => {
expect(BindInOut.prototype.addEvents).toHaveBeenCalled();
diff --git a/spec/frontend/blame/blame_redirect_spec.js b/spec/frontend/blame/blame_redirect_spec.js
new file mode 100644
index 00000000000..beb10139b3a
--- /dev/null
+++ b/spec/frontend/blame/blame_redirect_spec.js
@@ -0,0 +1,70 @@
+import redirectToCorrectPage from '~/blame/blame_redirect';
+import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import { createAlert } from '~/flash';
+
+jest.mock('~/flash');
+
+describe('Blame page redirect', () => {
+ beforeEach(() => {
+ global.window = Object.create(window);
+ const url = 'https://gitlab.com/flightjs/Flight/-/blame/master/file.json';
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: {
+ href: url,
+ hash: '',
+ search: '',
+ },
+ });
+
+ setHTMLFixture(`<div class="js-per-page" data-per-page="1000"></div>`);
+ });
+
+ afterEach(() => {
+ createAlert.mockClear();
+ resetHTMLFixture();
+ });
+
+ it('performs redirect to further pages when needed', () => {
+ window.location.hash = '#L1001';
+ redirectToCorrectPage();
+ expect(window.location.href).toMatch('?page=2');
+ });
+
+ it('performs redirect back to first page when needed', () => {
+ window.location.href = 'https://gitlab.com/flightjs/Flight/-/blame/master/file.json';
+ window.location.search = '?page=200';
+ window.location.hash = '#L999';
+ redirectToCorrectPage();
+ expect(window.location.href).toMatch('?page=1');
+ });
+
+ it('doesn`t perform redirect when the line is still on page 1', () => {
+ window.location.hash = '#L1000';
+ redirectToCorrectPage();
+ expect(window.location.href).not.toMatch('?page');
+ });
+
+ it('doesn`t perform redirect when "no_pagination" param is present', () => {
+ window.location.href = 'https://gitlab.com/flightjs/Flight/-/blame/master/file.json';
+ window.location.search = '?no_pagination=true';
+ window.location.hash = '#L1001';
+ redirectToCorrectPage();
+ expect(window.location.href).not.toMatch('?page');
+ });
+
+ it('doesn`t perform redirect when perPage is not present', () => {
+ setHTMLFixture(`<div class="js-per-page"></div>`);
+ window.location.hash = '#L1001';
+ redirectToCorrectPage();
+ expect(window.location.href).not.toMatch('?page');
+ });
+
+ it('shows alert with a message', () => {
+ window.location.hash = '#L1001';
+ redirectToCorrectPage();
+ expect(createAlert).toHaveBeenCalledWith({
+ message: 'Please wait a few moments while we load the file history for this line.',
+ });
+ });
+});
diff --git a/spec/frontend/blob/3d_viewer/mesh_object_spec.js b/spec/frontend/blob/3d_viewer/mesh_object_spec.js
index 3014af073f5..1b0fd362778 100644
--- a/spec/frontend/blob/3d_viewer/mesh_object_spec.js
+++ b/spec/frontend/blob/3d_viewer/mesh_object_spec.js
@@ -1,4 +1,4 @@
-import { BoxGeometry } from 'three/build/three.module';
+import { BoxGeometry } from 'three';
import MeshObject from '~/blob/3d_viewer/mesh_object';
describe('Mesh object', () => {
diff --git a/spec/frontend/blob/blob_blame_link_spec.js b/spec/frontend/blob/blob_blame_link_spec.js
index 0d19177a11f..060e8803520 100644
--- a/spec/frontend/blob/blob_blame_link_spec.js
+++ b/spec/frontend/blob/blob_blame_link_spec.js
@@ -29,19 +29,19 @@ describe('Blob links', () => {
it('adds wrapper elements with correct classes', () => {
const wrapper = document.querySelector('.line-links');
- expect(wrapper).toBeTruthy();
+ expect(wrapper).not.toBeNull();
expect(wrapper.classList).toContain('diff-line-num');
});
it('adds blame link with correct classes and path', () => {
const blameLink = document.querySelector('.file-line-blame');
- expect(blameLink).toBeTruthy();
+ expect(blameLink).not.toBeNull();
expect(blameLink.getAttribute('href')).toBe('/blamePath#L5');
});
it('adds line link within wraper with correct classes and path', () => {
const lineLink = document.querySelector('.file-line-num');
- expect(lineLink).toBeTruthy();
+ expect(lineLink).not.toBeNull();
expect(lineLink.getAttribute('href')).toBe('#L5');
});
});
diff --git a/spec/frontend/blob/components/blob_content_spec.js b/spec/frontend/blob/components/blob_content_spec.js
index 788ee0a86ab..f7b819b6e94 100644
--- a/spec/frontend/blob/components/blob_content_spec.js
+++ b/spec/frontend/blob/components/blob_content_spec.js
@@ -91,13 +91,13 @@ describe('Blob Content component', () => {
it(`properly proxies ${BLOB_RENDER_EVENT_LOAD} event`, () => {
expect(wrapper.emitted(BLOB_RENDER_EVENT_LOAD)).toBeUndefined();
findErrorEl().vm.$emit(BLOB_RENDER_EVENT_LOAD);
- expect(wrapper.emitted(BLOB_RENDER_EVENT_LOAD)).toBeTruthy();
+ expect(wrapper.emitted(BLOB_RENDER_EVENT_LOAD)).toHaveLength(1);
});
it(`properly proxies ${BLOB_RENDER_EVENT_SHOW_SOURCE} event`, () => {
expect(wrapper.emitted(BLOB_RENDER_EVENT_SHOW_SOURCE)).toBeUndefined();
findErrorEl().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE);
- expect(wrapper.emitted(BLOB_RENDER_EVENT_SHOW_SOURCE)).toBeTruthy();
+ expect(wrapper.emitted(BLOB_RENDER_EVENT_SHOW_SOURCE)).toHaveLength(1);
});
});
});
diff --git a/spec/frontend/blob/components/table_contents_spec.js b/spec/frontend/blob/components/table_contents_spec.js
index 2cbac809a0d..5fe328b65ff 100644
--- a/spec/frontend/blob/components/table_contents_spec.js
+++ b/spec/frontend/blob/components/table_contents_spec.js
@@ -71,6 +71,11 @@ describe('Markdown table of contents component', () => {
expect(dropdownItems.exists()).toBe(true);
expect(dropdownItems.length).toBe(4);
+
+ // make sure that this only happens once
+ await setLoaded(true);
+
+ expect(wrapper.findAllComponents(GlDropdownItem).length).toBe(4);
});
it('sets padding for dropdown items', async () => {
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index 2c3ec69f9ae..3ebc51c4bcb 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -5,7 +5,7 @@ import { nextTick } from 'vue';
import setWindowLocation from 'helpers/set_window_location_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { mountExtended } from 'helpers/vue_test_utils_helper';
-import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
import BoardCardInner from '~/boards/components/board_card_inner.vue';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
@@ -39,7 +39,7 @@ describe('Board card component', () => {
let list;
let store;
- const findBoardBlockedIcon = () => wrapper.findComponent(BoardBlockedIcon);
+ const findIssuableBlockedIcon = () => wrapper.findComponent(IssuableBlockedIcon);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findEpicCountablesTotalTooltip = () => wrapper.findComponent(GlTooltip);
const findEpicCountables = () => wrapper.findByTestId('epic-countables');
@@ -189,7 +189,7 @@ describe('Board card component', () => {
},
});
- expect(findBoardBlockedIcon().exists()).toBe(true);
+ expect(findIssuableBlockedIcon().exists()).toBe(true);
});
it('does not show blocked icon if issue is not blocked', () => {
@@ -200,7 +200,7 @@ describe('Board card component', () => {
},
});
- expect(findBoardBlockedIcon().exists()).toBe(false);
+ expect(findIssuableBlockedIcon().exists()).toBe(false);
});
});
@@ -595,5 +595,10 @@ describe('Board card component', () => {
expect(findEpicCountablesTotalWeight().text()).toBe('15');
expect(findEpicProgressTooltip().text()).toBe('10 of 15 weight completed');
});
+
+ it('does not render the move to position icon', () => {
+ createWrapper();
+ expect(findMoveToPositionComponent().exists()).toBe(false);
+ });
});
});
diff --git a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap b/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
deleted file mode 100644
index 34e4f996ff0..00000000000
--- a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
+++ /dev/null
@@ -1,30 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`BoardBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
-"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issue-blocked-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500 gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
- <use href=\\"#issue-block\\"></use>
- </svg>
- <div class=\\"gl-popover\\">
- <ul class=\\"gl-list-style-none gl-p-0\\">
- <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/6\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#6</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
- blocking issue title 1
- </p>
- </li>
- <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/5\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#5</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
- blocking issue title 2 + blocking issue title 2 + blocking issue title 2 + bloc…
- </p>
- </li>
- <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/4\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#4</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
- blocking issue title 3
- </p>
- </li>
- </ul>
- <div class=\\"gl-mt-4\\">
- <p data-testid=\\"hidden-blocking-count\\" class=\\"gl-mb-3\\">+ 1 more issue</p> <a data-testid=\\"view-all-issues\\" href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/0#related-issues\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">View all blocking issues</a>
- </div><span data-testid=\\"popover-title\\">Blocked by 4 issues</span>
- </div>
-</div>"
-`;
diff --git a/spec/frontend/boards/components/board_blocked_icon_spec.js b/spec/frontend/boards/components/board_blocked_icon_spec.js
deleted file mode 100644
index ffdc0a7cecc..00000000000
--- a/spec/frontend/boards/components/board_blocked_icon_spec.js
+++ /dev/null
@@ -1,264 +0,0 @@
-import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, mount } 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';
-import waitForPromises from 'helpers/wait_for_promises';
-import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
-import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
-import { truncate } from '~/lib/utils/text_utility';
-import {
- mockIssue,
- mockEpic,
- mockBlockingIssue1,
- mockBlockingIssue2,
- mockBlockingEpic1,
- mockBlockingIssuablesResponse1,
- mockBlockingIssuablesResponse2,
- mockBlockingIssuablesResponse3,
- mockBlockedIssue1,
- mockBlockedIssue2,
- mockBlockedEpic1,
- mockBlockingEpicIssuablesResponse1,
-} from '../mock_data';
-
-describe('BoardBlockedIcon', () => {
- let wrapper;
- let mockApollo;
-
- const findGlIcon = () => wrapper.findComponent(GlIcon);
- const findGlPopover = () => wrapper.findComponent(GlPopover);
- const findGlLink = () => wrapper.findComponent(GlLink);
- const findPopoverTitle = () => wrapper.findByTestId('popover-title');
- const findIssuableTitle = () => wrapper.findByTestId('issuable-title');
- const findHiddenBlockingCount = () => wrapper.findByTestId('hidden-blocking-count');
- const findViewAllIssuableLink = () => wrapper.findByTestId('view-all-issues');
-
- const waitForApollo = async () => {
- jest.runOnlyPendingTimers();
- await waitForPromises();
- };
-
- const mouseenter = async () => {
- findGlIcon().vm.$emit('mouseenter');
-
- await nextTick();
- await waitForApollo();
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const createWrapperWithApollo = ({
- item = mockBlockedIssue1,
- blockingIssuablesSpy = jest.fn().mockResolvedValue(mockBlockingIssuablesResponse1),
- issuableItem = mockIssue,
- issuableType = issuableTypes.issue,
- } = {}) => {
- mockApollo = createMockApollo([
- [blockingIssuablesQueries[issuableType].query, blockingIssuablesSpy],
- ]);
-
- Vue.use(VueApollo);
- wrapper = extendedWrapper(
- mount(BoardBlockedIcon, {
- apolloProvider: mockApollo,
- propsData: {
- item: {
- ...issuableItem,
- ...item,
- },
- uniqueId: 'uniqueId',
- issuableType,
- },
- attachTo: document.body,
- }),
- );
- };
-
- const createWrapper = ({
- item = {},
- queries = {},
- data = {},
- loading = false,
- mockIssuable = mockIssue,
- issuableType = issuableTypes.issue,
- } = {}) => {
- wrapper = extendedWrapper(
- shallowMount(BoardBlockedIcon, {
- propsData: {
- item: {
- ...mockIssuable,
- ...item,
- },
- uniqueId: 'uniqueid',
- issuableType,
- },
- data() {
- return {
- ...data,
- };
- },
- mocks: {
- $apollo: {
- queries: {
- blockingIssuables: { loading },
- ...queries,
- },
- },
- },
- stubs: {
- GlPopover,
- },
- attachTo: document.body,
- }),
- );
- };
-
- it.each`
- mockIssuable | issuableType | expectedIcon
- ${mockIssue} | ${issuableTypes.issue} | ${'issue-block'}
- ${mockEpic} | ${issuableTypes.epic} | ${'entity-blocked'}
- `(
- 'should render blocked icon for $issuableType',
- ({ mockIssuable, issuableType, expectedIcon }) => {
- createWrapper({
- mockIssuable,
- issuableType,
- });
-
- expect(findGlIcon().exists()).toBe(true);
- const icon = findGlIcon();
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe(expectedIcon);
- },
- );
-
- it('should display a loading spinner while loading', () => {
- createWrapper({ loading: true });
-
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
- });
-
- it('should not query for blocking issuables by default', async () => {
- createWrapperWithApollo();
-
- expect(findGlPopover().text()).not.toContain(mockBlockingIssue1.title);
- });
-
- describe('on mouseenter on blocked icon', () => {
- it.each`
- item | issuableType | mockBlockingIssuable | issuableItem | blockingIssuablesSpy
- ${mockBlockedIssue1} | ${issuableTypes.issue} | ${mockBlockingIssue1} | ${mockIssue} | ${jest.fn().mockResolvedValue(mockBlockingIssuablesResponse1)}
- ${mockBlockedEpic1} | ${issuableTypes.epic} | ${mockBlockingEpic1} | ${mockEpic} | ${jest.fn().mockResolvedValue(mockBlockingEpicIssuablesResponse1)}
- `(
- 'should query for blocking issuables and render the result for $issuableType',
- async ({ item, issuableType, issuableItem, mockBlockingIssuable, blockingIssuablesSpy }) => {
- createWrapperWithApollo({
- item,
- issuableType,
- issuableItem,
- blockingIssuablesSpy,
- });
-
- expect(findGlPopover().text()).not.toContain(mockBlockingIssuable.title);
-
- await mouseenter();
-
- expect(findGlPopover().exists()).toBe(true);
- expect(findIssuableTitle().text()).toContain(mockBlockingIssuable.title);
- expect(wrapper.vm.skip).toBe(true);
- },
- );
-
- it('should emit "blocking-issuables-error" event on query error', async () => {
- const mockError = new Error('mayday');
- createWrapperWithApollo({ blockingIssuablesSpy: jest.fn().mockRejectedValue(mockError) });
-
- await mouseenter();
-
- const [
- [
- {
- message,
- error: { networkError },
- },
- ],
- ] = wrapper.emitted('blocking-issuables-error');
- expect(message).toBe('Failed to fetch blocking issues');
- expect(networkError).toBe(mockError);
- });
-
- describe('with a single blocking issue', () => {
- beforeEach(async () => {
- createWrapperWithApollo();
-
- await mouseenter();
- });
-
- it('should render a title of the issuable', async () => {
- expect(findIssuableTitle().text()).toBe(mockBlockingIssue1.title);
- });
-
- it('should render issuable reference and link to the issuable', async () => {
- const formattedRef = mockBlockingIssue1.reference.split('/')[1];
-
- expect(findGlLink().text()).toBe(formattedRef);
- expect(findGlLink().attributes('href')).toBe(mockBlockingIssue1.webUrl);
- });
-
- it('should render popover title with correct blocking issuable count', async () => {
- expect(findPopoverTitle().text()).toBe('Blocked by 1 issue');
- });
- });
-
- describe('when issue has a long title', () => {
- it('should render a truncated title', async () => {
- createWrapperWithApollo({
- blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse2),
- });
-
- await mouseenter();
-
- const truncatedTitle = truncate(
- mockBlockingIssue2.title,
- wrapper.vm.$options.textTruncateWidth,
- );
- expect(findIssuableTitle().text()).toBe(truncatedTitle);
- });
- });
-
- describe('with more than three blocking issues', () => {
- beforeEach(async () => {
- createWrapperWithApollo({
- item: mockBlockedIssue2,
- blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse3),
- });
-
- await mouseenter();
- });
-
- it('matches the snapshot', () => {
- expect(wrapper.html()).toMatchSnapshot();
- });
-
- it('should render popover title with correct blocking issuable count', async () => {
- expect(findPopoverTitle().text()).toBe('Blocked by 4 issues');
- });
-
- it('should render the number of hidden blocking issuables', () => {
- expect(findHiddenBlockingCount().text()).toBe('+ 1 more issue');
- });
-
- it('should link to the blocked issue page at the related issue anchor', async () => {
- expect(findViewAllIssuableLink().text()).toBe('View all blocking issues');
- expect(findViewAllIssuableLink().attributes('href')).toBe(
- `${mockBlockedIssue2.webUrl}#related-issues`,
- );
- });
- });
- });
-});
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index 731578e15a3..1a07b9f0b78 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -126,6 +126,7 @@ describe('BoardFilteredSearch', () => {
{ type: 'weight', value: { data: '2', operator: '=' } },
{ type: 'iteration', value: { data: 'Any&3', operator: '=' } },
{ type: 'release', value: { data: 'v1.0.0', operator: '=' } },
+ { type: 'health_status', value: { data: 'onTrack', operator: '=' } },
];
jest.spyOn(urlUtility, 'updateHistory');
findFilteredSearch().vm.$emit('onFilter', mockFilters);
@@ -134,7 +135,7 @@ describe('BoardFilteredSearch', () => {
title: '',
replace: true,
url:
- 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=Any&iteration_cadence_id=3&types=INCIDENT&weight=2&release_tag=v1.0.0',
+ 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=Any&iteration_cadence_id=3&types=INCIDENT&weight=2&release_tag=v1.0.0&health_status=onTrack',
});
});
@@ -160,7 +161,9 @@ describe('BoardFilteredSearch', () => {
describe('when url params are already set', () => {
beforeEach(() => {
- createComponent({ initialFilterParams: { authorUsername: 'root', labelName: ['label'] } });
+ createComponent({
+ initialFilterParams: { authorUsername: 'root', labelName: ['label'], healthStatus: 'Any' },
+ });
jest.spyOn(store, 'dispatch');
});
@@ -169,6 +172,7 @@ describe('BoardFilteredSearch', () => {
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
{ type: 'author', value: { data: 'root', operator: '=' } },
{ type: 'label', value: { data: 'label', operator: '=' } },
+ { type: 'health_status', value: { data: 'Any', operator: '=' } },
]);
});
});
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index e919300228a..78859525a63 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1047,60 +1047,58 @@ describe('moveIssueCard and undoMoveIssueCard', () => {
let undoMutations;
describe('when re-ordering card', () => {
- beforeEach(
- ({
- itemId = 123,
- fromListId = 'gid://gitlab/List/1',
- toListId = 'gid://gitlab/List/1',
- originalIssue = { foo: 'bar' },
- originalIndex = 0,
- moveBeforeId = undefined,
- moveAfterId = undefined,
- allItemsLoadedInList = true,
- listPosition = undefined,
- } = {}) => {
- state = {
- boardLists: {
- [toListId]: { listType: ListType.backlog },
- [fromListId]: { listType: ListType.backlog },
- },
- boardItems: { [itemId]: originalIssue },
- boardItemsByListId: { [fromListId]: [123] },
- };
- params = {
- itemId,
- fromListId,
- toListId,
- moveBeforeId,
- moveAfterId,
- listPosition,
- allItemsLoadedInList,
- };
- moveMutations = [
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: {
- itemId,
- listId: toListId,
- moveBeforeId,
- moveAfterId,
- listPosition,
- allItemsLoadedInList,
- atIndex: originalIndex,
- },
- },
- ];
- undoMutations = [
- { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ beforeEach(() => {
+ const itemId = 123;
+ const fromListId = 'gid://gitlab/List/1';
+ const toListId = 'gid://gitlab/List/1';
+ const originalIssue = { foo: 'bar' };
+ const originalIndex = 0;
+ const moveBeforeId = undefined;
+ const moveAfterId = undefined;
+ const allItemsLoadedInList = true;
+ const listPosition = undefined;
+
+ state = {
+ boardLists: {
+ [toListId]: { listType: ListType.backlog },
+ [fromListId]: { listType: ListType.backlog },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123] },
+ };
+ params = {
+ itemId,
+ fromListId,
+ toListId,
+ moveBeforeId,
+ moveAfterId,
+ listPosition,
+ allItemsLoadedInList,
+ };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: {
+ itemId,
+ listId: toListId,
+ moveBeforeId,
+ moveAfterId,
+ listPosition,
+ allItemsLoadedInList,
+ atIndex: originalIndex,
},
- ];
- },
- );
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ });
it('moveIssueCard commits a correct set of actions', () => {
testAction({
@@ -1144,42 +1142,40 @@ describe('moveIssueCard and undoMoveIssueCard', () => {
},
],
])('when %s', (_, { toListType, fromListType }) => {
- beforeEach(
- ({
- itemId = 123,
- fromListId = 'gid://gitlab/List/1',
- toListId = 'gid://gitlab/List/2',
- originalIssue = { foo: 'bar' },
- originalIndex = 0,
- moveBeforeId = undefined,
- moveAfterId = undefined,
- } = {}) => {
- state = {
- boardLists: {
- [fromListId]: { listType: fromListType },
- [toListId]: { listType: toListType },
- },
- boardItems: { [itemId]: originalIssue },
- boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
- };
- params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
- moveMutations = [
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
- },
- ];
- undoMutations = [
- { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: fromListId, atIndex: originalIndex },
- },
- ];
- },
- );
+ beforeEach(() => {
+ const itemId = 123;
+ const fromListId = 'gid://gitlab/List/1';
+ const toListId = 'gid://gitlab/List/2';
+ const originalIssue = { foo: 'bar' };
+ const originalIndex = 0;
+ const moveBeforeId = undefined;
+ const moveAfterId = undefined;
+
+ state = {
+ boardLists: {
+ [fromListId]: { listType: fromListType },
+ [toListId]: { listType: toListType },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
+ };
+ params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ });
it('moveIssueCard commits a correct set of actions', () => {
testAction({
@@ -1216,47 +1212,45 @@ describe('moveIssueCard and undoMoveIssueCard', () => {
},
],
])('when %s', (_, { toListType, fromListType }) => {
- beforeEach(
- ({
- itemId = 123,
- fromListId = 'gid://gitlab/List/1',
- toListId = 'gid://gitlab/List/2',
- originalIssue = { foo: 'bar' },
- originalIndex = 0,
- moveBeforeId = undefined,
- moveAfterId = undefined,
- } = {}) => {
- state = {
- boardLists: {
- [fromListId]: { listType: fromListType },
- [toListId]: { listType: toListType },
- },
- boardItems: { [itemId]: originalIssue },
- boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
- };
- params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
- moveMutations = [
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
- },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: fromListId, atIndex: originalIndex },
- },
- ];
- undoMutations = [
- { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
- { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
- {
- type: types.ADD_BOARD_ITEM_TO_LIST,
- payload: { itemId, listId: fromListId, atIndex: originalIndex },
- },
- ];
- },
- );
+ beforeEach(() => {
+ const itemId = 123;
+ const fromListId = 'gid://gitlab/List/1';
+ const toListId = 'gid://gitlab/List/2';
+ const originalIssue = { foo: 'bar' };
+ const originalIndex = 0;
+ const moveBeforeId = undefined;
+ const moveAfterId = undefined;
+
+ state = {
+ boardLists: {
+ [fromListId]: { listType: fromListType },
+ [toListId]: { listType: toListType },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
+ };
+ params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
+ },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ });
it('moveIssueCard commits a correct set of actions', () => {
testAction({
diff --git a/spec/frontend/captcha/init_recaptcha_script_spec.js b/spec/frontend/captcha/init_recaptcha_script_spec.js
index af07c9e474e..78480821d95 100644
--- a/spec/frontend/captcha/init_recaptcha_script_spec.js
+++ b/spec/frontend/captcha/init_recaptcha_script_spec.js
@@ -1,5 +1,4 @@
import {
- RECAPTCHA_API_URL_PREFIX,
RECAPTCHA_ONLOAD_CALLBACK_NAME,
clearMemoizeCache,
initRecaptchaScript,
@@ -26,7 +25,7 @@ describe('initRecaptchaScript', () => {
<head>
<script
class="js-recaptcha-script"
- src="${RECAPTCHA_API_URL_PREFIX}?onload=${RECAPTCHA_ONLOAD_CALLBACK_NAME}&render=explicit"
+ src="undefined?onload=recaptchaOnloadCallback&render=explicit"
/>
</head>
`);
diff --git a/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
index 920ceaefb70..864041141b8 100644
--- a/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
@@ -4,8 +4,8 @@ import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/resolvers';
+import { createAlert } from '~/flash';
+import { resolvers } from '~/ci_variable_list/graphql/settings';
import ciAdminVariables from '~/ci_variable_list/components/ci_admin_variables.vue';
import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
@@ -92,8 +92,8 @@ describe('Ci Admin Variable list', () => {
);
});
- it('createFlash was not called', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ it('createAlert was not called', () => {
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -104,8 +104,8 @@ describe('Ci Admin Variable list', () => {
await createComponentWithApollo();
});
- it('calls createFlash with the expected error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
});
});
});
@@ -153,7 +153,7 @@ describe('Ci Admin Variable list', () => {
await nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
},
);
@@ -171,7 +171,7 @@ describe('Ci Admin Variable list', () => {
await findCiSettings().vm.$emit(event, newVariable);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
},
);
});
diff --git a/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
index e45656acfd8..8a48e73eb9f 100644
--- a/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
@@ -4,8 +4,8 @@ import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/resolvers';
+import { createAlert } from '~/flash';
+import { resolvers } from '~/ci_variable_list/graphql/settings';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import ciGroupVariables from '~/ci_variable_list/components/ci_group_variables.vue';
@@ -95,8 +95,8 @@ describe('Ci Group Variable list', () => {
);
});
- it('createFlash was not called', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ it('createAlert was not called', () => {
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -107,8 +107,8 @@ describe('Ci Group Variable list', () => {
await createComponentWithApollo();
});
- it('calls createFlash with the expected error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
});
});
});
@@ -158,7 +158,7 @@ describe('Ci Group Variable list', () => {
await nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
},
);
@@ -176,7 +176,7 @@ describe('Ci Group Variable list', () => {
await findCiSettings().vm.$emit(event, newVariable);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
},
);
});
diff --git a/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
index 867f8e0cf8f..c630278fbde 100644
--- a/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
@@ -4,8 +4,8 @@ import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/resolvers';
+import { createAlert } from '~/flash';
+import { resolvers } from '~/ci_variable_list/graphql/settings';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import ciProjectVariables from '~/ci_variable_list/components/ci_project_variables.vue';
@@ -112,8 +112,8 @@ describe('Ci Project Variable list', () => {
);
});
- it('createFlash was not called', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ it('createAlert was not called', () => {
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -125,8 +125,8 @@ describe('Ci Project Variable list', () => {
await createComponentWithApollo();
});
- it('calls createFlash with the expected error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
});
});
@@ -138,8 +138,8 @@ describe('Ci Project Variable list', () => {
await createComponentWithApollo();
});
- it('calls createFlash with the expected error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: environmentFetchErrorText });
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: environmentFetchErrorText });
});
});
});
@@ -190,7 +190,7 @@ describe('Ci Project Variable list', () => {
await nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
},
);
@@ -208,7 +208,7 @@ describe('Ci Project Variable list', () => {
await findCiSettings().vm.$emit(event, newVariable);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
},
);
});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js
index 9c941f99982..7def4dd4f29 100644
--- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js
+++ b/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js
@@ -9,11 +9,11 @@ Vue.use(Vuex);
describe('Ci variable table', () => {
let wrapper;
let store;
- let isGroup;
+ let isProject;
- const createComponent = (groupState) => {
+ const createComponent = (projectState) => {
store = createStore();
- store.state.isGroup = groupState;
+ store.state.isProject = projectState;
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = shallowMount(LegacyCiVariableSettings, {
store,
@@ -25,14 +25,14 @@ describe('Ci variable table', () => {
});
it('dispatches fetchEnvironments when mounted', () => {
- isGroup = false;
- createComponent(isGroup);
+ isProject = true;
+ createComponent(isProject);
expect(store.dispatch).toHaveBeenCalledWith('fetchEnvironments');
});
it('does not dispatch fetchenvironments when in group context', () => {
- isGroup = true;
- createComponent(isGroup);
+ isProject = false;
+ createComponent(isProject);
expect(store.dispatch).not.toHaveBeenCalled();
});
});
diff --git a/spec/frontend/ci_variable_list/mocks.js b/spec/frontend/ci_variable_list/mocks.js
index 6d633c8b740..6f3e73f8b83 100644
--- a/spec/frontend/ci_variable_list/mocks.js
+++ b/spec/frontend/ci_variable_list/mocks.js
@@ -45,6 +45,12 @@ const createDefaultVars = ({ withScope = true, kind } = {}) => {
return {
__typename: `Ci${kind}VariableConnection`,
+ pageInfo: {
+ startCursor: 'adsjsd12kldpsa',
+ endCursor: 'adsjsd12kldpsa',
+ hasPreviousPage: false,
+ hasNextPage: true,
+ },
nodes: base,
};
};
diff --git a/spec/frontend/ci_variable_list/store/actions_spec.js b/spec/frontend/ci_variable_list/store/actions_spec.js
index eb31fcd3ef4..e8c81a53a55 100644
--- a/spec/frontend/ci_variable_list/store/actions_spec.js
+++ b/spec/frontend/ci_variable_list/store/actions_spec.js
@@ -5,7 +5,7 @@ import * as actions from '~/ci_variable_list/store/actions';
import * as types from '~/ci_variable_list/store/mutation_types';
import getInitialState from '~/ci_variable_list/store/state';
import { prepareDataForDisplay, prepareEnvironments } from '~/ci_variable_list/store/utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import mockData from '../services/mock_data';
@@ -118,7 +118,7 @@ describe('CI variable list store actions', () => {
},
],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -155,7 +155,7 @@ describe('CI variable list store actions', () => {
},
],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -192,7 +192,7 @@ describe('CI variable list store actions', () => {
},
],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -219,7 +219,7 @@ describe('CI variable list store actions', () => {
mock.onGet(state.endpoint).reply(500);
await testAction(actions.fetchVariables, {}, state, [], [{ type: 'requestVariables' }]);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was an error fetching the variables.',
});
});
@@ -249,7 +249,7 @@ describe('CI variable list store actions', () => {
await testAction(actions.fetchEnvironments, {}, state, [], [{ type: 'requestEnvironments' }]);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was an error fetching the environments information.',
});
});
diff --git a/spec/frontend/clusters_list/store/actions_spec.js b/spec/frontend/clusters_list/store/actions_spec.js
index 7663f329b3f..09b1f80ff9b 100644
--- a/spec/frontend/clusters_list/store/actions_spec.js
+++ b/spec/frontend/clusters_list/store/actions_spec.js
@@ -5,7 +5,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { MAX_REQUESTS } from '~/clusters_list/constants';
import * as actions from '~/clusters_list/store/actions';
import * as types from '~/clusters_list/store/mutation_types';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
import { apiData } from '../mock_data';
@@ -98,7 +98,7 @@ describe('Clusters store actions', () => {
},
],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.stringMatching('error'),
});
});
diff --git a/spec/frontend/code_navigation/utils/index_spec.js b/spec/frontend/code_navigation/utils/index_spec.js
index 700c912029c..6f0d93c466c 100644
--- a/spec/frontend/code_navigation/utils/index_spec.js
+++ b/spec/frontend/code_navigation/utils/index_spec.js
@@ -87,5 +87,13 @@ describe('addInteractionClass', () => {
expect(spans[1].textContent).toBe('Text');
expect(spans[2].textContent).toBe(' ');
});
+
+ it('adds the correct class names to wrapped nodes', () => {
+ setHTMLFixture(
+ '<div data-path="index.js"><div class="blob-content"><div id="LC1" class="line"><span class="test"> Text </span></div></div></div>',
+ );
+ addInteractionClass({ ...params, wrapTextNodes: true });
+ expect(findAllSpans()[1].classList.contains('test')).toBe(true);
+ });
});
});
diff --git a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
index fddc767953a..16737003fa0 100644
--- a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
+++ b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
@@ -5,7 +5,7 @@ import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import CommitBoxPipelineMiniGraph from '~/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
import { COMMIT_BOX_POLL_INTERVAL } from '~/projects/commit_box/info/constants';
@@ -178,12 +178,12 @@ describe('Commit box pipeline mini graph', () => {
});
describe('error state', () => {
- it('createFlash should show if there is an error fetching the data', async () => {
+ it('createAlert should show if there is an error fetching the data', async () => {
createComponent({ handler: failedHandler });
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching linked pipelines.',
});
});
diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js
index 73720c1cc88..e75fb697a7b 100644
--- a/spec/frontend/commit/commit_pipeline_status_component_spec.js
+++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
import { nextTick } from 'vue';
import fixture from 'test_fixtures/pipelines/pipelines.json';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Poll from '~/lib/utils/poll';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -170,7 +170,7 @@ describe('Commit pipeline status component', () => {
});
it('displays flash error message', () => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/commit/components/commit_box_pipeline_status_spec.js b/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
index db7b7b45397..8d455f8a3d7 100644
--- a/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
+++ b/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
@@ -4,7 +4,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 createFlash from '~/flash';
+import { createAlert } from '~/flash';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CommitBoxPipelineStatus from '~/projects/commit_box/info/components/commit_box_pipeline_status.vue';
import {
@@ -78,7 +78,7 @@ describe('Commit box pipeline status', () => {
expect(findStatusIcon().exists()).toBe(true);
expect(findLoadingIcon().exists()).toBe(false);
- expect(createFlash).toHaveBeenCalledTimes(0);
+ expect(createAlert).toHaveBeenCalledTimes(0);
});
it('should link to the latest pipeline', () => {
@@ -97,12 +97,12 @@ describe('Commit box pipeline status', () => {
});
describe('error state', () => {
- it('createFlash should show if there is an error fetching the pipeline status', async () => {
+ it('createAlert should show if there is an error fetching the pipeline status', async () => {
createComponent(failedHandler);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: PIPELINE_STATUS_FETCH_ERROR,
});
});
diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js
index ae52cb05eaf..c1c2a125515 100644
--- a/spec/frontend/content_editor/components/content_editor_spec.js
+++ b/spec/frontend/content_editor/components/content_editor_spec.js
@@ -13,6 +13,7 @@ import MediaBubbleMenu from '~/content_editor/components/bubble_menus/media_bubb
import TopToolbar from '~/content_editor/components/top_toolbar.vue';
import LoadingIndicator from '~/content_editor/components/loading_indicator.vue';
import waitForPromises from 'helpers/wait_for_promises';
+import { KEYDOWN_EVENT } from '~/content_editor/constants';
jest.mock('~/emoji');
@@ -26,12 +27,13 @@ describe('ContentEditor', () => {
const findEditorStateObserver = () => wrapper.findComponent(EditorStateObserver);
const findLoadingIndicator = () => wrapper.findComponent(LoadingIndicator);
const findContentEditorAlert = () => wrapper.findComponent(ContentEditorAlert);
- const createWrapper = ({ markdown } = {}) => {
+ const createWrapper = ({ markdown, autofocus } = {}) => {
wrapper = shallowMountExtended(ContentEditor, {
propsData: {
renderMarkdown,
uploadsPath,
markdown,
+ autofocus,
},
stubs: {
EditorStateObserver,
@@ -70,14 +72,22 @@ describe('ContentEditor', () => {
expect(editorContent.classes()).toContain('md');
});
- it('renders ContentEditorProvider component', async () => {
- await createWrapper();
+ it('allows setting the tiptap editor to autofocus', async () => {
+ createWrapper({ autofocus: 'start' });
+
+ await nextTick();
+
+ expect(findEditorContent().props().editor.options.autofocus).toBe('start');
+ });
+
+ it('renders ContentEditorProvider component', () => {
+ createWrapper();
expect(wrapper.findComponent(ContentEditorProvider).exists()).toBe(true);
});
- it('renders top toolbar component', async () => {
- await createWrapper();
+ it('renders top toolbar component', () => {
+ createWrapper();
expect(wrapper.findComponent(TopToolbar).exists()).toBe(true);
});
@@ -213,6 +223,17 @@ describe('ContentEditor', () => {
});
});
+ describe('when editorStateObserver emits keydown event', () => {
+ it('bubbles up event', () => {
+ const event = new Event('keydown');
+
+ createWrapper();
+
+ findEditorStateObserver().vm.$emit(KEYDOWN_EVENT, event);
+ expect(wrapper.emitted(KEYDOWN_EVENT)).toEqual([[event]]);
+ });
+ });
+
it.each`
name | component
${'formatting'} | ${FormattingBubbleMenu}
diff --git a/spec/frontend/content_editor/components/editor_state_observer_spec.js b/spec/frontend/content_editor/components/editor_state_observer_spec.js
index e8c2d8c8793..9b42f61c98c 100644
--- a/spec/frontend/content_editor/components/editor_state_observer_spec.js
+++ b/spec/frontend/content_editor/components/editor_state_observer_spec.js
@@ -4,7 +4,7 @@ import EditorStateObserver, {
tiptapToComponentMap,
} from '~/content_editor/components/editor_state_observer.vue';
import eventHubFactory from '~/helpers/event_hub_factory';
-import { ALERT_EVENT } from '~/content_editor/constants';
+import { ALERT_EVENT, KEYDOWN_EVENT } from '~/content_editor/constants';
import { createTestEditor } from '../test_utils';
describe('content_editor/components/editor_state_observer', () => {
@@ -14,6 +14,7 @@ describe('content_editor/components/editor_state_observer', () => {
let onSelectionUpdateListener;
let onTransactionListener;
let onAlertListener;
+ let onKeydownListener;
let eventHub;
const buildEditor = () => {
@@ -30,6 +31,7 @@ describe('content_editor/components/editor_state_observer', () => {
selectionUpdate: onSelectionUpdateListener,
transaction: onTransactionListener,
[ALERT_EVENT]: onAlertListener,
+ [KEYDOWN_EVENT]: onKeydownListener,
},
});
};
@@ -39,6 +41,7 @@ describe('content_editor/components/editor_state_observer', () => {
onSelectionUpdateListener = jest.fn();
onTransactionListener = jest.fn();
onAlertListener = jest.fn();
+ onKeydownListener = jest.fn();
buildEditor();
});
@@ -67,8 +70,9 @@ describe('content_editor/components/editor_state_observer', () => {
});
it.each`
- event | listener
- ${ALERT_EVENT} | ${() => onAlertListener}
+ event | listener
+ ${ALERT_EVENT} | ${() => onAlertListener}
+ ${KEYDOWN_EVENT} | ${() => onKeydownListener}
`('listens to $event event in the eventBus object', ({ event, listener }) => {
const args = {};
@@ -97,6 +101,7 @@ describe('content_editor/components/editor_state_observer', () => {
it.each`
event
${ALERT_EVENT}
+ ${KEYDOWN_EVENT}
`('removes $event event hook from eventHub', ({ event }) => {
jest.spyOn(eventHub, '$off');
jest.spyOn(eventHub, '$on');
diff --git a/spec/frontend/content_editor/components/suggestions_dropdown_spec.js b/spec/frontend/content_editor/components/suggestions_dropdown_spec.js
new file mode 100644
index 00000000000..e72eb892e74
--- /dev/null
+++ b/spec/frontend/content_editor/components/suggestions_dropdown_spec.js
@@ -0,0 +1,286 @@
+import { GlAvatarLabeled, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import SuggestionsDropdown from '~/content_editor/components/suggestions_dropdown.vue';
+
+describe('~/content_editor/components/suggestions_dropdown', () => {
+ let wrapper;
+
+ const buildWrapper = ({ propsData } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(SuggestionsDropdown, {
+ propsData: {
+ nodeType: 'reference',
+ command: jest.fn(),
+ ...propsData,
+ },
+ }),
+ );
+ };
+
+ const exampleUser = { username: 'root', avatar_url: 'root_avatar.png', type: 'User' };
+ const exampleIssue = { iid: 123, title: 'Test Issue' };
+ const exampleMergeRequest = { iid: 224, title: 'Test MR' };
+ const exampleMilestone1 = { iid: 21, title: '13' };
+ const exampleMilestone2 = { iid: 24, title: 'Milestone with spaces' };
+
+ const exampleCommand = {
+ name: 'due',
+ description: 'Set due date',
+ params: ['<in 2 days | this Friday | December 31st>'],
+ };
+ const exampleEpic = {
+ iid: 8884,
+ title: 'â“ Remote Development | Solution validation',
+ reference: 'gitlab-org&8884',
+ };
+ const exampleLabel1 = {
+ title: 'Create',
+ color: '#E44D2A',
+ type: 'GroupLabel',
+ textColor: '#FFFFFF',
+ };
+ const exampleLabel2 = {
+ title: 'Weekly Team Announcement',
+ color: '#E44D2A',
+ type: 'GroupLabel',
+ textColor: '#FFFFFF',
+ };
+ const exampleLabel3 = {
+ title: 'devops::create',
+ color: '#E44D2A',
+ type: 'GroupLabel',
+ textColor: '#FFFFFF',
+ };
+ const exampleVulnerability = {
+ id: 60850147,
+ title: 'System procs network activity',
+ };
+ const exampleSnippet = {
+ id: 2420859,
+ title: 'Project creation QueryRecorder logs',
+ };
+ const exampleEmoji = {
+ c: 'people',
+ e: '😃',
+ d: 'smiling face with open mouth',
+ u: '6.0',
+ name: 'smiley',
+ };
+
+ const insertedEmojiProps = {
+ name: 'smiley',
+ title: 'smiling face with open mouth',
+ moji: '😃',
+ unicodeVersion: '6.0',
+ };
+
+ describe('on item select', () => {
+ it.each`
+ nodeType | referenceType | char | reference | insertedText | insertedProps
+ ${'reference'} | ${'user'} | ${'@'} | ${exampleUser} | ${`@root`} | ${{}}
+ ${'reference'} | ${'issue'} | ${'#'} | ${exampleIssue} | ${`#123`} | ${{}}
+ ${'reference'} | ${'merge_request'} | ${'!'} | ${exampleMergeRequest} | ${`!224`} | ${{}}
+ ${'reference'} | ${'milestone'} | ${'%'} | ${exampleMilestone1} | ${`%13`} | ${{}}
+ ${'reference'} | ${'milestone'} | ${'%'} | ${exampleMilestone2} | ${`%Milestone with spaces`} | ${{ originalText: '%"Milestone with spaces"' }}
+ ${'reference'} | ${'command'} | ${'/'} | ${exampleCommand} | ${'/due'} | ${{}}
+ ${'reference'} | ${'epic'} | ${'&'} | ${exampleEpic} | ${`gitlab-org&8884`} | ${{}}
+ ${'reference'} | ${'label'} | ${'~'} | ${exampleLabel1} | ${`Create`} | ${{}}
+ ${'reference'} | ${'label'} | ${'~'} | ${exampleLabel2} | ${`Weekly Team Announcement`} | ${{ originalText: '~"Weekly Team Announcement"' }}
+ ${'reference'} | ${'label'} | ${'~'} | ${exampleLabel3} | ${`devops::create`} | ${{ originalText: '~"devops::create"', text: 'devops::create' }}
+ ${'reference'} | ${'vulnerability'} | ${'[vulnerability:'} | ${exampleVulnerability} | ${`[vulnerability:60850147]`} | ${{}}
+ ${'reference'} | ${'snippet'} | ${'$'} | ${exampleSnippet} | ${`$2420859`} | ${{}}
+ ${'emoji'} | ${'emoji'} | ${':'} | ${exampleEmoji} | ${`😃`} | ${insertedEmojiProps}
+ `(
+ 'runs a command to insert the selected $referenceType',
+ ({ char, nodeType, referenceType, reference, insertedText, insertedProps }) => {
+ const commandSpy = jest.fn();
+
+ buildWrapper({
+ propsData: {
+ char,
+ command: commandSpy,
+ nodeType,
+ nodeProps: {
+ referenceType,
+ test: 'prop',
+ },
+ items: [reference],
+ },
+ });
+
+ wrapper.findComponent(GlDropdownItem).vm.$emit('click');
+
+ expect(commandSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ text: insertedText,
+ test: 'prop',
+ ...insertedProps,
+ }),
+ );
+ },
+ );
+ });
+
+ describe('rendering user references', () => {
+ it('displays avatar labeled component', () => {
+ buildWrapper({
+ propsData: {
+ char: '@',
+ nodeProps: {
+ referenceType: 'user',
+ },
+ items: [exampleUser],
+ },
+ });
+
+ expect(wrapper.findComponent(GlAvatarLabeled).attributes()).toEqual(
+ expect.objectContaining({
+ label: exampleUser.username,
+ shape: 'circle',
+ src: exampleUser.avatar_url,
+ }),
+ );
+ });
+
+ describe.each`
+ referenceType | char | reference | displaysID
+ ${'issue'} | ${'#'} | ${exampleIssue} | ${true}
+ ${'merge_request'} | ${'!'} | ${exampleMergeRequest} | ${true}
+ ${'milestone'} | ${'%'} | ${exampleMilestone1} | ${false}
+ `('rendering $referenceType references', ({ referenceType, char, reference, displaysID }) => {
+ it(`displays ${referenceType} ID and title`, () => {
+ buildWrapper({
+ propsData: {
+ char,
+ nodeType: 'reference',
+ nodeProps: {
+ referenceType,
+ },
+ items: [reference],
+ },
+ });
+
+ if (displaysID) expect(wrapper.text()).toContain(`${reference.iid}`);
+ else expect(wrapper.text()).not.toContain(`${reference.iid}`);
+ expect(wrapper.text()).toContain(`${reference.title}`);
+ });
+ });
+
+ describe.each`
+ referenceType | char | reference
+ ${'snippet'} | ${'$'} | ${exampleSnippet}
+ ${'vulnerability'} | ${'[vulnerability:'} | ${exampleVulnerability}
+ `('rendering $referenceType references', ({ referenceType, char, reference }) => {
+ it(`displays ${referenceType} ID and title`, () => {
+ buildWrapper({
+ propsData: {
+ char,
+ nodeProps: {
+ referenceType,
+ },
+ items: [reference],
+ },
+ });
+
+ expect(wrapper.text()).toContain(`${reference.id}`);
+ expect(wrapper.text()).toContain(`${reference.title}`);
+ });
+ });
+
+ describe('rendering label references', () => {
+ it.each`
+ label | displayedTitle | displayedColor
+ ${exampleLabel1} | ${'Create'} | ${'rgb(228, 77, 42)' /* #E44D2A */}
+ ${exampleLabel2} | ${'Weekly Team Announcement'} | ${'rgb(228, 77, 42)' /* #E44D2A */}
+ ${exampleLabel3} | ${'devops::create'} | ${'rgb(228, 77, 42)' /* #E44D2A */}
+ `('displays label title and color', ({ label, displayedTitle, displayedColor }) => {
+ buildWrapper({
+ propsData: {
+ char: '~',
+ nodeProps: {
+ referenceType: 'label',
+ },
+ items: [label],
+ },
+ });
+
+ expect(wrapper.text()).toContain(displayedTitle);
+ expect(wrapper.text()).not.toContain('"'); // no quotes in the dropdown list
+ expect(wrapper.findByTestId('label-color-box').attributes().style).toEqual(
+ `background-color: ${displayedColor};`,
+ );
+ });
+ });
+
+ describe('rendering epic references', () => {
+ it('displays epic title and reference', () => {
+ buildWrapper({
+ propsData: {
+ char: '&',
+ nodeProps: {
+ referenceType: 'epic',
+ },
+ items: [exampleEpic],
+ },
+ });
+
+ expect(wrapper.text()).toContain(`${exampleEpic.reference}`);
+ expect(wrapper.text()).toContain(`${exampleEpic.title}`);
+ });
+ });
+
+ describe('rendering a command (quick action)', () => {
+ it('displays command name with a slash', () => {
+ buildWrapper({
+ propsData: {
+ char: '/',
+ nodeProps: {
+ referenceType: 'command',
+ },
+ items: [exampleCommand],
+ },
+ });
+
+ expect(wrapper.text()).toContain(`${exampleCommand.name} `);
+ });
+ });
+
+ describe('rendering emoji references', () => {
+ it('displays emoji', () => {
+ const testEmojis = [
+ {
+ c: 'people',
+ e: '😄',
+ d: 'smiling face with open mouth and smiling eyes',
+ u: '6.0',
+ name: 'smile',
+ },
+ {
+ c: 'people',
+ e: '😸',
+ d: 'grinning cat face with smiling eyes',
+ u: '6.0',
+ name: 'smile_cat',
+ },
+ { c: 'people', e: '😃', d: 'smiling face with open mouth', u: '6.0', name: 'smiley' },
+ ];
+
+ buildWrapper({
+ propsData: {
+ char: ':',
+ nodeType: 'emoji',
+ nodeProps: {},
+ items: testEmojis,
+ },
+ });
+
+ testEmojis.forEach((testEmoji) => {
+ expect(wrapper.text()).toContain(testEmoji.e);
+ expect(wrapper.text()).toContain(testEmoji.d);
+ expect(wrapper.text()).toContain(testEmoji.name);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/components/wrappers/label_spec.js b/spec/frontend/content_editor/components/wrappers/label_spec.js
new file mode 100644
index 00000000000..9e58669b0ea
--- /dev/null
+++ b/spec/frontend/content_editor/components/wrappers/label_spec.js
@@ -0,0 +1,36 @@
+import { GlLabel } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import LabelWrapper from '~/content_editor/components/wrappers/label.vue';
+
+describe('content/components/wrappers/label', () => {
+ let wrapper;
+
+ const createWrapper = async (node = {}) => {
+ wrapper = shallowMountExtended(LabelWrapper, {
+ propsData: { node },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it("renders a GlLabel with the node's text and color", () => {
+ createWrapper({ attrs: { color: '#ff0000', text: 'foo bar', originalText: '~"foo bar"' } });
+
+ const glLabel = wrapper.findComponent(GlLabel);
+
+ expect(glLabel.props()).toMatchObject(
+ expect.objectContaining({
+ title: 'foo bar',
+ backgroundColor: '#ff0000',
+ }),
+ );
+ });
+
+ it('renders a scoped label if there is a "::" in the label', () => {
+ createWrapper({ attrs: { color: '#ff0000', text: 'foo::bar', originalText: '~"foo::bar"' } });
+
+ expect(wrapper.findComponent(GlLabel).props().scoped).toBe(true);
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/heading_spec.js b/spec/frontend/content_editor/extensions/heading_spec.js
new file mode 100644
index 00000000000..2fa25e03cdc
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/heading_spec.js
@@ -0,0 +1,54 @@
+import Heading from '~/content_editor/extensions/heading';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
+
+describe('content_editor/extensions/heading', () => {
+ let tiptapEditor;
+ let doc;
+ let p;
+ let heading;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [Heading] });
+ ({
+ builders: { doc, p, heading },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ heading: { nodeType: Heading.name },
+ },
+ }));
+ });
+
+ describe('when typing a valid heading input rule', () => {
+ it.each`
+ level | inputRuleText
+ ${1} | ${'# '}
+ ${2} | ${'## '}
+ ${3} | ${'### '}
+ ${4} | ${'#### '}
+ ${5} | ${'##### '}
+ ${6} | ${'###### '}
+ `('inserts a heading node for $inputRuleText', ({ level, inputRuleText }) => {
+ const expectedDoc = doc(heading({ level }));
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+ });
+
+ describe('when typing a invalid heading input rule', () => {
+ it.each`
+ inputRuleText
+ ${'#hi'}
+ ${'#\n'}
+ `('does not insert a heading node for $inputRuleText', ({ inputRuleText }) => {
+ const expectedDoc = doc(p());
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText });
+
+ // no change to the document
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/markdown_processing_spec_helper.js b/spec/frontend/content_editor/markdown_processing_spec_helper.js
index 228d009e42c..6f10f294fb0 100644
--- a/spec/frontend/content_editor/markdown_processing_spec_helper.js
+++ b/spec/frontend/content_editor/markdown_processing_spec_helper.js
@@ -1,7 +1,10 @@
import fs from 'fs';
import jsYaml from 'js-yaml';
import { memoize } from 'lodash';
+import MockAdapter from 'axios-mock-adapter';
+import axios from 'axios';
import { createContentEditor } from '~/content_editor';
+import httpStatus from '~/lib/utils/http_status';
const getFocusedMarkdownExamples = memoize(
() => process.env.FOCUSED_MARKDOWN_EXAMPLES?.split(',') || [],
@@ -42,6 +45,11 @@ const loadMarkdownApiExamples = (markdownYamlPath) => {
};
const testSerializesHtmlToMarkdownForElement = async ({ markdown, html }) => {
+ const mock = new MockAdapter(axios);
+
+ // Ignore any API requests from the suggestions plugin
+ mock.onGet().reply(httpStatus.OK, []);
+
const contentEditor = createContentEditor({
// Overwrite renderMarkdown to always return this specific html
renderMarkdown: () => html,
@@ -55,6 +63,8 @@ const testSerializesHtmlToMarkdownForElement = async ({ markdown, html }) => {
// 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.trim()).toBe(markdown.trim());
+
+ mock.restore();
};
// describeMarkdownProcesssing
@@ -74,7 +84,7 @@ export const describeMarkdownProcessing = (description, markdownYamlPath) => {
return;
}
- it(exampleName, async () => {
+ it(`${exampleName}`, async () => {
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 56394c85e8b..32193d97fd8 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -1204,6 +1204,24 @@ Oranges are orange [^1]
);
});
+ it('correctly adds a space between a preceding block element and a markdown table', () => {
+ expect(
+ serialize(
+ bulletList(listItem(paragraph('List item 1')), listItem(paragraph('List item 2'))),
+ table(tableRow(tableHeader(paragraph('header'))), tableRow(tableCell(paragraph('cell')))),
+ ).trim(),
+ ).toBe(
+ `
+* List item 1
+* List item 2
+
+| header |
+|--------|
+| cell |
+ `.trim(),
+ );
+ });
+
it('correctly serializes reference definition', () => {
expect(
serialize(
diff --git a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
index 459780cc7cf..8c1a3831a74 100644
--- a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
+++ b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
@@ -44,7 +44,7 @@ describe('content_editor/services/track_input_rules_and_shortcuts', () => {
describe('when creating a heading using an keyboard shortcut', () => {
it('sends a tracking event indicating that a heading was created using an input rule', async () => {
- const shortcuts = Heading.config.addKeyboardShortcuts.call(Heading);
+ const shortcuts = Heading.parent.config.addKeyboardShortcuts.call(Heading);
const [firstShortcut] = Object.keys(shortcuts);
const nodeName = Heading.name;
diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js
index bdf3b3636ed..2f0b5719326 100644
--- a/spec/frontend/contributors/component/contributors_spec.js
+++ b/spec/frontend/contributors/component/contributors_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import ContributorsCharts from '~/contributors/components/contributors.vue';
@@ -52,14 +53,14 @@ describe('Contributors charts', () => {
it('should display loader whiled loading data', async () => {
wrapper.vm.$store.state.loading = true;
await nextTick();
- expect(wrapper.find('.contributors-loader').exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('should render charts when loading completed and there is chart data', async () => {
wrapper.vm.$store.state.loading = false;
wrapper.vm.$store.state.chartData = chartData;
await nextTick();
- expect(wrapper.find('.contributors-loader').exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find('.contributors-charts').exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/contributors/store/actions_spec.js b/spec/frontend/contributors/store/actions_spec.js
index ef0ff8ca208..865f683a91a 100644
--- a/spec/frontend/contributors/store/actions_spec.js
+++ b/spec/frontend/contributors/store/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/contributors/stores/actions';
import * as types from '~/contributors/stores/mutation_types';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/flash.js');
@@ -47,7 +47,7 @@ describe('Contributors store actions', () => {
[{ type: types.SET_LOADING_STATE, payload: true }],
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.stringMatching('error'),
});
});
diff --git a/spec/frontend/crm/contacts_root_spec.js b/spec/frontend/crm/contacts_root_spec.js
index 7aaaf480c44..ec7172434bf 100644
--- a/spec/frontend/crm/contacts_root_spec.js
+++ b/spec/frontend/crm/contacts_root_spec.js
@@ -87,7 +87,7 @@ describe('Customer relations contacts root app', () => {
editButtonLabel: 'Edit',
title: 'Customer relations contacts',
newContact: 'New contact',
- errorText: 'Something went wrong. Please try again.',
+ errorMsg: 'Something went wrong. Please try again.',
},
serverErrorMessage: '',
filterSearchKey: 'contacts',
@@ -117,6 +117,18 @@ describe('Customer relations contacts root app', () => {
expect(wrapper.text()).toContain('Something went wrong. Please try again.');
});
+
+ it('should be removed on error-alert-dismissed event', async () => {
+ mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
+ await waitForPromises();
+
+ expect(wrapper.text()).toContain('Something went wrong. Please try again.');
+
+ findTable().vm.$emit('error-alert-dismissed');
+ await waitForPromises();
+
+ expect(wrapper.text()).not.toContain('Something went wrong. Please try again.');
+ });
});
describe('on successful load', () => {
diff --git a/spec/frontend/crm/organizations_root_spec.js b/spec/frontend/crm/organizations_root_spec.js
index a0b56596177..1fcf6aa8f50 100644
--- a/spec/frontend/crm/organizations_root_spec.js
+++ b/spec/frontend/crm/organizations_root_spec.js
@@ -91,7 +91,7 @@ describe('Customer relations organizations root app', () => {
editButtonLabel: 'Edit',
title: 'Customer relations organizations',
newOrganization: 'New organization',
- errorText: 'Something went wrong. Please try again.',
+ errorMsg: 'Something went wrong. Please try again.',
},
serverErrorMessage: '',
filterSearchKey: 'organizations',
diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
index 9c8cd6a3dbc..948dc5c9be2 100644
--- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
+++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
@@ -8,7 +8,7 @@ import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
import { VSA_METRICS_GROUPS, METRICS_POPOVER_CONTENT } from '~/analytics/shared/constants';
import { prepareTimeMetricsData } from '~/analytics/shared/utils';
import MetricTile from '~/analytics/shared/components/metric_tile.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { group } from './mock_data';
jest.mock('~/flash');
@@ -177,7 +177,7 @@ describe('ValueStreamMetrics', () => {
});
it('should render an error message', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `There was an error while fetching value stream analytics ${fakeReqName} data.`,
});
});
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
index bbafdc000db..113e0d8f60d 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
@@ -5,8 +5,9 @@ import Vuex from 'vuex';
import Api from '~/api';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import createStore from '~/deploy_freeze/store';
-import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
-import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
+import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
+import { freezePeriodsFixture } from '../helpers';
+import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers';
jest.mock('~/api');
@@ -52,7 +53,7 @@ describe('Deploy freeze modal', () => {
describe('Basic interactions', () => {
it('button is disabled when freeze period is invalid', () => {
- expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBe('true');
});
});
@@ -92,7 +93,7 @@ describe('Deploy freeze modal', () => {
});
it('disables the add deploy freeze button', () => {
- expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBe('true');
});
});
@@ -103,7 +104,7 @@ describe('Deploy freeze modal', () => {
});
it('does not disable the submit button', () => {
- expect(submitDeployFreezeButton().attributes('disabled')).toBeFalsy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBeUndefined();
});
});
});
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
index 637efe30022..27d8fea9d5e 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
@@ -5,7 +5,7 @@ import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vu
import DeployFreezeSettings from '~/deploy_freeze/components/deploy_freeze_settings.vue';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
-import { timezoneDataFixture } from '../helpers';
+import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers';
Vue.use(Vuex);
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
index 137776edfab..c2d6eb399bc 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
@@ -5,7 +5,8 @@ import Vuex from 'vuex';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
-import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
+import { freezePeriodsFixture } from '../helpers';
+import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers';
Vue.use(Vuex);
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
deleted file mode 100644
index 567d18f8b92..00000000000
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-import createStore from '~/deploy_freeze/store';
-import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
-import { findTzByName, formatTz, timezoneDataFixture } from '../helpers';
-
-Vue.use(Vuex);
-
-describe('Deploy freeze timezone dropdown', () => {
- let wrapper;
- let store;
-
- const createComponent = (searchTerm, selectedTimezone) => {
- store = createStore({
- projectId: '8',
- timezoneData: timezoneDataFixture,
- });
- wrapper = shallowMount(TimezoneDropdown, {
- store,
- propsData: {
- value: selectedTimezone,
- timezoneData: timezoneDataFixture,
- },
- });
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ searchTerm });
- };
-
- const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
- const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('No time zones found', () => {
- beforeEach(() => {
- createComponent('UTC timezone');
- });
-
- it('renders empty results message', () => {
- expect(findDropdownItemByIndex(0).text()).toBe('No matching results');
- });
- });
-
- describe('Search term is empty', () => {
- beforeEach(() => {
- createComponent('');
- });
-
- it('renders all timezones when search term is empty', () => {
- expect(findAllDropdownItems()).toHaveLength(timezoneDataFixture.length);
- });
- });
-
- describe('Time zones found', () => {
- beforeEach(() => {
- createComponent('Alaska');
- });
-
- it('renders only the time zone searched for', () => {
- const selectedTz = findTzByName('Alaska');
- expect(findAllDropdownItems()).toHaveLength(1);
- expect(findDropdownItemByIndex(0).text()).toBe(formatTz(selectedTz));
- });
-
- it('should not display empty results message', () => {
- expect(wrapper.find('[data-testid="noMatchingResults"]').exists()).toBe(false);
- });
-
- describe('Custom events', () => {
- const selectedTz = findTzByName('Alaska');
-
- it('should emit input if a time zone is clicked', () => {
- findDropdownItemByIndex(0).vm.$emit('click');
- expect(wrapper.emitted('input')).toEqual([
- [
- {
- formattedTimezone: formatTz(selectedTz),
- identifier: selectedTz.identifier,
- },
- ],
- ]);
- });
- });
- });
-
- describe('Selected time zone', () => {
- beforeEach(() => {
- createComponent('', 'Alaska');
- });
-
- it('renders selected time zone as dropdown label', () => {
- expect(wrapper.findComponent(GlDropdown).vm.text).toBe('Alaska');
- });
- });
-});
diff --git a/spec/frontend/deploy_freeze/helpers.js b/spec/frontend/deploy_freeze/helpers.js
index 43e66183ab5..920901c97a8 100644
--- a/spec/frontend/deploy_freeze/helpers.js
+++ b/spec/frontend/deploy_freeze/helpers.js
@@ -1,10 +1,3 @@
import freezePeriodsFixture from 'test_fixtures/api/freeze-periods/freeze_periods.json';
-import timezoneDataFixture from 'test_fixtures/timezones/short.json';
-import { secondsToHours } from '~/lib/utils/datetime_utility';
-export { freezePeriodsFixture, timezoneDataFixture };
-
-export const findTzByName = (identifier = '') =>
- timezoneDataFixture.find(({ name }) => name.toLowerCase() === identifier.toLowerCase());
-
-export const formatTz = ({ offset, name }) => `[UTC ${secondsToHours(offset)}] ${name}`;
+export { freezePeriodsFixture };
diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js
index ad67afdce75..ce0c924bed2 100644
--- a/spec/frontend/deploy_freeze/store/actions_spec.js
+++ b/spec/frontend/deploy_freeze/store/actions_spec.js
@@ -7,7 +7,8 @@ import getInitialState from '~/deploy_freeze/store/state';
import createFlash from '~/flash';
import * as logger from '~/lib/logger';
import axios from '~/lib/utils/axios_utils';
-import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
+import { freezePeriodsFixture } from '../helpers';
+import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers';
jest.mock('~/api.js');
jest.mock('~/flash.js');
diff --git a/spec/frontend/deploy_freeze/store/mutations_spec.js b/spec/frontend/deploy_freeze/store/mutations_spec.js
index 878a755088c..984105d6655 100644
--- a/spec/frontend/deploy_freeze/store/mutations_spec.js
+++ b/spec/frontend/deploy_freeze/store/mutations_spec.js
@@ -2,7 +2,12 @@ import * as types from '~/deploy_freeze/store/mutation_types';
import mutations from '~/deploy_freeze/store/mutations';
import state from '~/deploy_freeze/store/state';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { findTzByName, formatTz, freezePeriodsFixture, timezoneDataFixture } from '../helpers';
+import { formatTimezone } from '~/lib/utils/datetime_utility';
+import { freezePeriodsFixture } from '../helpers';
+import {
+ timezoneDataFixture,
+ findTzByName,
+} from '../../vue_shared/components/timezone_dropdown/helpers';
describe('Deploy freeze mutations', () => {
let stateCopy;
@@ -28,9 +33,9 @@ describe('Deploy freeze mutations', () => {
describe('RECEIVE_FREEZE_PERIODS_SUCCESS', () => {
it('should set freeze periods and format timezones from identifiers to names', () => {
const timezoneNames = {
- 'Europe/Berlin': '[UTC 2] Berlin',
+ 'Europe/Berlin': '[UTC + 2] Berlin',
'Etc/UTC': '[UTC 0] UTC',
- 'America/New_York': '[UTC -4] Eastern Time (US & Canada)',
+ 'America/New_York': '[UTC - 4] Eastern Time (US & Canada)',
};
mutations[types.RECEIVE_FREEZE_PERIODS_SUCCESS](stateCopy, freezePeriodsFixture);
@@ -51,7 +56,7 @@ describe('Deploy freeze mutations', () => {
it('should set the cron timezone', () => {
const selectedTz = findTzByName('Pacific Time (US & Canada)');
const timezone = {
- formattedTimezone: formatTz(selectedTz),
+ formattedTimezone: formatTimezone(selectedTz),
identifier: selectedTz.identifier,
};
mutations[types.SET_SELECTED_TIMEZONE](stateCopy, timezone);
diff --git a/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js b/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js
new file mode 100644
index 00000000000..19e9ba8b268
--- /dev/null
+++ b/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js
@@ -0,0 +1,103 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { GlButton, GlFormCheckbox, GlFormInput, GlFormInputGroup, GlDatepicker } from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import NewDeployToken from '~/deploy_tokens/components/new_deploy_token.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+
+const createNewTokenPath = `${TEST_HOST}/create`;
+const deployTokensHelpUrl = `${TEST_HOST}/help`;
+describe('New Deploy Token', () => {
+ let wrapper;
+
+ const factory = (options = {}) => {
+ const defaults = {
+ containerRegistryEnabled: true,
+ packagesRegistryEnabled: true,
+ tokenType: 'project',
+ };
+ const { containerRegistryEnabled, packagesRegistryEnabled, tokenType } = {
+ ...defaults,
+ ...options,
+ };
+ return shallowMount(NewDeployToken, {
+ propsData: {
+ deployTokensHelpUrl,
+ containerRegistryEnabled,
+ packagesRegistryEnabled,
+ createNewTokenPath,
+ tokenType,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('without a container registry', () => {
+ beforeEach(() => {
+ wrapper = factory({ containerRegistryEnabled: false });
+ });
+
+ it('should not show the read registry scope', () => {
+ wrapper
+ .findAllComponents(GlFormCheckbox)
+ .wrappers.forEach((checkbox) => expect(checkbox.text()).not.toBe('read_registry'));
+ });
+ });
+
+ describe('with a container registry', () => {
+ beforeEach(() => {
+ wrapper = factory();
+ });
+
+ it('should show the read registry scope', () => {
+ const checkbox = wrapper.findAllComponents(GlFormCheckbox).at(1);
+ expect(checkbox.text()).toBe('read_registry');
+ });
+
+ it('should make a request to create a token on submit', () => {
+ const mockAxios = new MockAdapter(axios);
+
+ const date = new Date();
+ const formInputs = wrapper.findAllComponents(GlFormInput);
+ const name = formInputs.at(0);
+ const username = formInputs.at(2);
+ name.vm.$emit('input', 'test name');
+ username.vm.$emit('input', 'test username');
+
+ const datepicker = wrapper.findAllComponents(GlDatepicker).at(0);
+ datepicker.vm.$emit('input', date);
+
+ const [readRepo, readRegistry] = wrapper.findAllComponents(GlFormCheckbox).wrappers;
+ readRepo.vm.$emit('input', true);
+ readRegistry.vm.$emit('input', true);
+
+ mockAxios
+ .onPost(createNewTokenPath, {
+ deploy_token: {
+ name: 'test name',
+ expires_at: date.toISOString(),
+ username: 'test username',
+ read_repository: true,
+ read_registry: true,
+ },
+ })
+ .replyOnce(200, { username: 'test token username', token: 'test token' });
+
+ wrapper.findAllComponents(GlButton).at(0).vm.$emit('click');
+
+ return waitForPromises()
+ .then(() => nextTick())
+ .then(() => {
+ const [tokenUsername, tokenValue] = wrapper.findAllComponents(GlFormInputGroup).wrappers;
+
+ expect(tokenUsername.props('value')).toBe('test token username');
+ expect(tokenValue.props('value')).toBe('test token');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index cee1eec792d..426a61f5a47 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -29,12 +29,12 @@ describe('Batch delete button component', () => {
createComponent();
expect(findButton().exists()).toBe(true);
- expect(findButton().attributes('disabled')).toBeFalsy();
+ expect(findButton().attributes('disabled')).toBeUndefined();
});
it('renders disabled button when design is deleting', () => {
createComponent({ isDeleting: true });
- expect(findButton().attributes('disabled')).toBeTruthy();
+ expect(findButton().attributes('disabled')).toBe('true');
});
it('emits `delete-selected-designs` event on modal ok click', async () => {
@@ -45,7 +45,7 @@ describe('Batch delete button component', () => {
findModal().vm.$emit('ok');
await nextTick();
- expect(wrapper.emitted('delete-selected-designs')).toBeTruthy();
+ expect(wrapper.emitted('delete-selected-designs')).toHaveLength(1);
});
it('renders slot content', () => {
diff --git a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
index e36f5c79e3e..5fd61b25edc 100644
--- a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
@@ -1,16 +1,10 @@
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Autosave from '~/autosave';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
-const showModal = jest.fn();
-
-const GlModal = {
- template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
- methods: {
- show: showModal,
- },
-};
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
describe('Design reply form component', () => {
let wrapper;
@@ -19,7 +13,6 @@ describe('Design reply form component', () => {
const findTextarea = () => wrapper.find('textarea');
const findSubmitButton = () => wrapper.findComponent({ ref: 'submitButton' });
const findCancelButton = () => wrapper.findComponent({ ref: 'cancelButton' });
- const findModal = () => wrapper.findComponent({ ref: 'cancelCommentModal' });
function createComponent(props = {}, mountOptions = {}) {
wrapper = mount(DesignReplyForm, {
@@ -29,7 +22,6 @@ describe('Design reply form component', () => {
noteableId: 'gid://gitlab/DesignManagement::Design/6',
...props,
},
- stubs: { GlModal },
...mountOptions,
});
}
@@ -42,6 +34,7 @@ describe('Design reply form component', () => {
afterEach(() => {
wrapper.destroy();
window.gon = originalGon;
+ confirmAction.mockReset();
});
it('textarea has focus after component mount', () => {
@@ -102,7 +95,7 @@ describe('Design reply form component', () => {
});
it('submit button is disabled', () => {
- expect(findSubmitButton().attributes().disabled).toBeTruthy();
+ expect(findSubmitButton().attributes().disabled).toBe('disabled');
});
it('does not emit submitForm event on textarea ctrl+enter keydown', async () => {
@@ -111,7 +104,7 @@ describe('Design reply form component', () => {
});
await nextTick();
- expect(wrapper.emitted('submit-form')).toBeFalsy();
+ expect(wrapper.emitted('submit-form')).toBeUndefined();
});
it('does not emit submitForm event on textarea meta+enter keydown', async () => {
@@ -120,13 +113,13 @@ describe('Design reply form component', () => {
});
await nextTick();
- expect(wrapper.emitted('submit-form')).toBeFalsy();
+ expect(wrapper.emitted('submit-form')).toBeUndefined();
});
it('emits cancelForm event on pressing escape button on textarea', () => {
findTextarea().trigger('keyup.esc');
- expect(wrapper.emitted('cancel-form')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toHaveLength(1);
});
it('emits cancelForm event on clicking Cancel button', () => {
@@ -144,7 +137,7 @@ describe('Design reply form component', () => {
});
it('submit button is enabled', () => {
- expect(findSubmitButton().attributes().disabled).toBeFalsy();
+ expect(findSubmitButton().attributes().disabled).toBeUndefined();
});
it('emits submitForm event on Comment button click', async () => {
@@ -153,7 +146,7 @@ describe('Design reply form component', () => {
findSubmitButton().vm.$emit('click');
await nextTick();
- expect(wrapper.emitted('submit-form')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toHaveLength(1);
expect(autosaveResetSpy).toHaveBeenCalled();
});
@@ -165,7 +158,7 @@ describe('Design reply form component', () => {
});
await nextTick();
- expect(wrapper.emitted('submit-form')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toHaveLength(1);
expect(autosaveResetSpy).toHaveBeenCalled();
});
@@ -177,7 +170,7 @@ describe('Design reply form component', () => {
});
await nextTick();
- expect(wrapper.emitted('submit-form')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toHaveLength(1);
expect(autosaveResetSpy).toHaveBeenCalled();
});
@@ -185,13 +178,13 @@ describe('Design reply form component', () => {
findTextarea().setValue('test2');
await nextTick();
- expect(wrapper.emitted('input')).toBeTruthy();
+ expect(wrapper.emitted('input')).toEqual([['test'], ['test2']]);
});
it('emits cancelForm event on Escape key if text was not changed', () => {
findTextarea().trigger('keyup.esc');
- expect(wrapper.emitted('cancel-form')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toHaveLength(1);
});
it('opens confirmation modal on Escape key when text has changed', async () => {
@@ -199,13 +192,13 @@ describe('Design reply form component', () => {
await nextTick();
findTextarea().trigger('keyup.esc');
- expect(showModal).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
});
it('emits cancelForm event on Cancel button click if text was not changed', () => {
findCancelButton().trigger('click');
- expect(wrapper.emitted('cancel-form')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toHaveLength(1);
});
it('opens confirmation modal on Cancel button click when text has changed', async () => {
@@ -213,17 +206,41 @@ describe('Design reply form component', () => {
await nextTick();
findCancelButton().trigger('click');
- expect(showModal).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
});
- it('emits cancelForm event on modal Ok button click', () => {
+ it('emits cancelForm event when confirmed', async () => {
+ confirmAction.mockResolvedValueOnce(true);
const autosaveResetSpy = jest.spyOn(wrapper.vm.autosaveDiscussion, 'reset');
+ wrapper.setProps({ value: 'test3' });
+ await nextTick();
+
findTextarea().trigger('keyup.esc');
- findModal().vm.$emit('ok');
+ await nextTick();
+
+ expect(confirmAction).toHaveBeenCalled();
+ await nextTick();
- expect(wrapper.emitted('cancel-form')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toHaveLength(1);
expect(autosaveResetSpy).toHaveBeenCalled();
});
+
+ it("doesn't emit cancelForm event when not confirmed", async () => {
+ confirmAction.mockResolvedValueOnce(false);
+ const autosaveResetSpy = jest.spyOn(wrapper.vm.autosaveDiscussion, 'reset');
+
+ wrapper.setProps({ value: 'test3' });
+ await nextTick();
+
+ findTextarea().trigger('keyup.esc');
+ await nextTick();
+
+ expect(confirmAction).toHaveBeenCalled();
+ await nextTick();
+
+ expect(wrapper.emitted('cancel-form')).toBeUndefined();
+ expect(autosaveResetSpy).not.toHaveBeenCalled();
+ });
});
});
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index 056959425a6..169f2dbdccb 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -170,6 +170,14 @@ describe('Design overlay component', () => {
});
it('should call an update active discussion mutation when clicking a note without moving it', async () => {
+ createComponent({
+ notes,
+ dimensions: {
+ width: 400,
+ height: 400,
+ },
+ });
+
const note = notes[0];
const { position } = note;
const mutationVariables = {
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index 774e37a8b21..a11463ab663 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -23,7 +23,7 @@ import {
DESIGN_SNOWPLOW_EVENT_TYPES,
DESIGN_SERVICE_PING_EVENT_TYPES,
} from '~/design_management/utils/tracking';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import mockAllVersions from '../../mock_data/all_versions';
import design from '../../mock_data/design';
import mockResponseWithDesigns from '../../mock_data/designs';
@@ -301,8 +301,8 @@ describe('Design management design index page', () => {
wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false });
await nextTick();
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_NOT_FOUND_ERROR });
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({ message: DESIGN_NOT_FOUND_ERROR });
expect(router.push).toHaveBeenCalledTimes(1);
expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
@@ -323,8 +323,8 @@ describe('Design management design index page', () => {
wrapper.vm.onDesignQueryResult({ data: mockResponseWithDesigns, loading: false });
await nextTick();
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: DESIGN_VERSION_NOT_EXIST_ERROR });
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({ message: DESIGN_VERSION_NOT_EXIST_ERROR });
expect(router.push).toHaveBeenCalledTimes(1);
expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
});
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 1033b509419..76ece922ded 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -29,7 +29,7 @@ import {
DESIGN_TRACKING_PAGE_NAME,
DESIGN_SNOWPLOW_EVENT_TYPES,
} from '~/design_management/utils/tracking';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import {
designListQueryResponse,
@@ -808,7 +808,7 @@ describe('Design management index page', () => {
await moveDesigns(wrapper);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
it('displays alert if mutation had a non-recoverable error', async () => {
diff --git a/spec/frontend/design_management/utils/cache_update_spec.js b/spec/frontend/design_management/utils/cache_update_spec.js
index 5e2c37e24a1..42777adfd58 100644
--- a/spec/frontend/design_management/utils/cache_update_spec.js
+++ b/spec/frontend/design_management/utils/cache_update_spec.js
@@ -10,7 +10,7 @@ import {
ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR,
} from '~/design_management/utils/error_messages';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import design from '../mock_data/design';
jest.mock('~/flash.js');
@@ -32,10 +32,10 @@ describe('Design Management cache update', () => {
${'updateStoreAfterUploadDesign'} | ${updateStoreAfterUploadDesign} | ${mockErrors[0]} | ${[]}
${'updateStoreAfterUpdateImageDiffNote'} | ${updateStoreAfterRepositionImageDiffNote} | ${UPDATE_IMAGE_DIFF_NOTE_ERROR} | ${[]}
`('$fnName handles errors in response', ({ subject, extraArgs, errorMessage }) => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(() => subject(mockStore, { errors: mockErrors }, {}, ...extraArgs)).toThrow();
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: errorMessage });
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({ message: errorMessage });
});
});
});
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index b88206c3b9a..936f4744e94 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -152,6 +152,30 @@ describe('diffs/components/app', () => {
});
});
+ describe('fetch diff with no changes', () => {
+ beforeEach(() => {
+ const fetchResolver = () => {
+ store.state.diffs.retrievingBatches = false;
+ return Promise.resolve({ real_size: null });
+ };
+
+ createComponent();
+ jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
+
+ return nextTick();
+ });
+
+ it('diff counter to be 0 after fetch', async () => {
+ expect(wrapper.vm.diffFilesLength).toEqual(0);
+ wrapper.vm.fetchData(false);
+
+ await nextTick();
+
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.diffFilesLength).toEqual(0);
+ });
+ });
+
describe('codequality diff', () => {
it('does not fetch code quality data on FOSS', async () => {
createComponent();
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index 440f169be86..75d55376d09 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -82,7 +82,7 @@ describe('diffs/components/commit_item', () => {
const imgElement = avatarElement.find('img');
expect(avatarElement.attributes('href')).toBe(commit.author.web_url);
- expect(imgElement.classes()).toContain('s32');
+ expect(imgElement.classes()).toContain('gl-avatar-s32');
expect(imgElement.attributes('alt')).toBe(commit.author.name);
expect(imgElement.attributes('src')).toBe(commit.author.avatar_url);
});
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 9f593ee0d49..0bce6451ce4 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -53,7 +53,7 @@ describe('DiffContent', () => {
namespaced: true,
getters: {
draftsForFile: () => () => true,
- draftForLine: () => () => true,
+ draftsForLine: () => () => true,
shouldRenderDraftRow: () => () => true,
hasParallelDraftLeft: () => () => true,
hasParallelDraftRight: () => () => true,
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index a74013dc2d4..a7a95ed2f35 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -219,7 +219,7 @@ describe('DiffRow', () => {
shouldRenderDraftRow: jest.fn(),
hasParallelDraftLeft: jest.fn(),
hasParallelDraftRight: jest.fn(),
- draftForLine: jest.fn(),
+ draftsForLine: jest.fn().mockReturnValue([]),
};
const applyMap = mapParallel(mockDiffContent);
diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js
index 930b8bcdb08..8b25691ce34 100644
--- a/spec/frontend/diffs/components/diff_row_utils_spec.js
+++ b/spec/frontend/diffs/components/diff_row_utils_spec.js
@@ -216,7 +216,7 @@ describe('mapParallel', () => {
diffFile: {},
hasParallelDraftLeft: () => false,
hasParallelDraftRight: () => false,
- draftForLine: () => ({}),
+ draftsForLine: () => [],
};
const line = { left: side, right: side };
const expectation = {
@@ -234,13 +234,13 @@ describe('mapParallel', () => {
const leftExpectation = {
renderDiscussion: true,
hasDraft: false,
- lineDraft: {},
+ lineDrafts: [],
hasCommentForm: true,
};
const rightExpectation = {
renderDiscussion: false,
hasDraft: false,
- lineDraft: {},
+ lineDrafts: [],
hasCommentForm: false,
};
const mapped = utils.mapParallel(content)(line);
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
index 1dd4a2f6c23..9bff6bd14f1 100644
--- a/spec/frontend/diffs/components/diff_view_spec.js
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -21,7 +21,7 @@ describe('DiffView', () => {
getters: {
shouldRenderDraftRow: () => false,
shouldRenderParallelDraftRow: () => () => true,
- draftForLine: () => false,
+ draftsForLine: () => false,
draftsForFile: () => false,
hasParallelDraftLeft: () => false,
hasParallelDraftRight: () => false,
@@ -75,12 +75,12 @@ describe('DiffView', () => {
});
it.each`
- type | side | container | sides | total
- ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
- ${'parallel'} | ${'right'} | ${'.new'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
- ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
- ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
- ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
+ type | side | container | sides | total
+ ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true }, right: { lineDrafts: [], renderDiscussion: true } }} | ${2}
+ ${'parallel'} | ${'right'} | ${'.new'} | ${{ left: { lineDrafts: [], renderDiscussion: true }, right: { lineDrafts: [], renderDiscussion: true } }} | ${2}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true } }} | ${1}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true } }} | ${1}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true } }} | ${1}
`(
'renders a $type comment row with comment cell on $side',
({ type, container, sides, total }) => {
@@ -95,7 +95,7 @@ describe('DiffView', () => {
it('renders a draft row', () => {
const wrapper = createWrapper({
- diffLines: [{ renderCommentRow: true, left: { lineDraft: { isDraft: true } } }],
+ diffLines: [{ renderCommentRow: true, left: { lineDrafts: [{ isDraft: true }] } }],
});
expect(wrapper.findComponent(DraftNote).exists()).toBe(true);
});
diff --git a/spec/frontend/diffs/components/file_row_stats_spec.js b/spec/frontend/diffs/components/file_row_stats_spec.js
index 3f5a63c19e5..7d3b60d2ba4 100644
--- a/spec/frontend/diffs/components/file_row_stats_spec.js
+++ b/spec/frontend/diffs/components/file_row_stats_spec.js
@@ -2,13 +2,21 @@ import { mount } from '@vue/test-utils';
import FileRowStats from '~/diffs/components/file_row_stats.vue';
describe('Diff file row stats', () => {
- const wrapper = mount(FileRowStats, {
- propsData: {
- file: {
- addedLines: 20,
- removedLines: 10,
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = mount(FileRowStats, {
+ propsData: {
+ file: {
+ addedLines: 20,
+ removedLines: 10,
+ },
},
- },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
});
it('renders added lines count', () => {
diff --git a/spec/frontend/diffs/mock_data/diff_code_quality.js b/spec/frontend/diffs/mock_data/diff_code_quality.js
index 2ca421a20b4..befab3b676b 100644
--- a/spec/frontend/diffs/mock_data/diff_code_quality.js
+++ b/spec/frontend/diffs/mock_data/diff_code_quality.js
@@ -36,7 +36,7 @@ export const diffCodeQuality = {
old_line: 1,
new_line: null,
codequality: [],
- lineDraft: {},
+ lineDrafts: [],
},
},
{
@@ -45,7 +45,7 @@ export const diffCodeQuality = {
old_line: 2,
new_line: 1,
codequality: [],
- lineDraft: {},
+ lineDrafts: [],
},
},
{
@@ -55,7 +55,7 @@ export const diffCodeQuality = {
new_line: 2,
codequality: [multipleFindingsArr[0]],
- lineDraft: {},
+ lineDrafts: [],
},
},
],
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 346e43e5a72..bf75f956d7f 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -13,7 +13,7 @@ import * as diffActions from '~/diffs/store/actions';
import * as types from '~/diffs/store/mutation_types';
import * as utils from '~/diffs/store/utils';
import * as treeWorkerUtils from '~/diffs/utils/tree_worker_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -54,7 +54,7 @@ describe('DiffsStoreActions', () => {
['requestAnimationFrame', 'requestIdleCallback'].forEach((method) => {
global[method] = originalMethods[method];
});
- createFlash.mockClear();
+ createAlert.mockClear();
mock.restore();
});
@@ -175,35 +175,10 @@ describe('DiffsStoreActions', () => {
[{ type: 'startRenderDiffsQueue' }, { type: 'startRenderDiffsQueue' }],
);
});
-
- it.each`
- viewStyle | otherView
- ${'inline'} | ${'parallel'}
- ${'parallel'} | ${'inline'}
- `(
- 'should make a request with the view parameter "$viewStyle" when the batchEndpoint already contains "$otherView"',
- ({ viewStyle, otherView }) => {
- const endpointBatch = '/fetch/diffs_batch';
-
- diffActions
- .fetchDiffFilesBatch({
- commit: () => {},
- state: {
- endpointBatch: `${endpointBatch}?view=${otherView}`,
- diffViewType: viewStyle,
- },
- })
- .then(() => {
- expect(mock.history.get[0].url).toContain(`view=${viewStyle}`);
- expect(mock.history.get[0].url).not.toContain(`view=${otherView}`);
- })
- .catch(() => {});
- },
- );
});
describe('fetchDiffFilesMeta', () => {
- const endpointMetadata = '/fetch/diffs_metadata.json?view=inline';
+ const endpointMetadata = '/fetch/diffs_metadata.json?view=inline&w=0';
const noFilesData = { ...diffMetadata };
beforeEach(() => {
@@ -216,7 +191,7 @@ describe('DiffsStoreActions', () => {
return testAction(
diffActions.fetchDiffFilesMeta,
{},
- { endpointMetadata, diffViewType: 'inline' },
+ { endpointMetadata, diffViewType: 'inline', showWhitespace: true },
[
{ type: types.SET_LOADING, payload: true },
{ type: types.SET_LOADING, payload: false },
@@ -254,8 +229,8 @@ describe('DiffsStoreActions', () => {
mock.onGet(endpointCoverage).reply(400);
await testAction(diffActions.fetchCoverageFiles, {}, { endpointCoverage }, [], []);
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.stringMatching('Something went wrong'),
});
});
diff --git a/spec/frontend/editor/schema/ci/ci_schema_spec.js b/spec/frontend/editor/schema/ci/ci_schema_spec.js
index c9010fbec0c..fc86907c144 100644
--- a/spec/frontend/editor/schema/ci/ci_schema_spec.js
+++ b/spec/frontend/editor/schema/ci/ci_schema_spec.js
@@ -29,12 +29,36 @@ import CacheYaml from './yaml_tests/positive_tests/cache.yml';
import FilterYaml from './yaml_tests/positive_tests/filter.yml';
import IncludeYaml from './yaml_tests/positive_tests/include.yml';
import RulesYaml from './yaml_tests/positive_tests/rules.yml';
+import ProjectPathYaml from './yaml_tests/positive_tests/project_path.yml';
+import VariablesYaml from './yaml_tests/positive_tests/variables.yml';
// YAML NEGATIVE TEST
import ArtifactsNegativeYaml from './yaml_tests/negative_tests/artifacts.yml';
import CacheNegativeYaml from './yaml_tests/negative_tests/cache.yml';
import IncludeNegativeYaml from './yaml_tests/negative_tests/include.yml';
import RulesNegativeYaml from './yaml_tests/negative_tests/rules.yml';
+import VariablesNegativeYaml from './yaml_tests/negative_tests/variables.yml';
+
+import ProjectPathIncludeEmptyYaml from './yaml_tests/negative_tests/project_path/include/empty.yml';
+import ProjectPathIncludeInvalidVariableYaml from './yaml_tests/negative_tests/project_path/include/invalid_variable.yml';
+import ProjectPathIncludeLeadSlashYaml from './yaml_tests/negative_tests/project_path/include/leading_slash.yml';
+import ProjectPathIncludeNoSlashYaml from './yaml_tests/negative_tests/project_path/include/no_slash.yml';
+import ProjectPathIncludeTailSlashYaml from './yaml_tests/negative_tests/project_path/include/tailing_slash.yml';
+import ProjectPathTriggerIncludeEmptyYaml from './yaml_tests/negative_tests/project_path/trigger/include/empty.yml';
+import ProjectPathTriggerIncludeInvalidVariableYaml from './yaml_tests/negative_tests/project_path/trigger/include/invalid_variable.yml';
+import ProjectPathTriggerIncludeLeadSlashYaml from './yaml_tests/negative_tests/project_path/trigger/include/leading_slash.yml';
+import ProjectPathTriggerIncludeNoSlashYaml from './yaml_tests/negative_tests/project_path/trigger/include/no_slash.yml';
+import ProjectPathTriggerIncludeTailSlashYaml from './yaml_tests/negative_tests/project_path/trigger/include/tailing_slash.yml';
+import ProjectPathTriggerMinimalEmptyYaml from './yaml_tests/negative_tests/project_path/trigger/minimal/empty.yml';
+import ProjectPathTriggerMinimalInvalidVariableYaml from './yaml_tests/negative_tests/project_path/trigger/minimal/invalid_variable.yml';
+import ProjectPathTriggerMinimalLeadSlashYaml from './yaml_tests/negative_tests/project_path/trigger/minimal/leading_slash.yml';
+import ProjectPathTriggerMinimalNoSlashYaml from './yaml_tests/negative_tests/project_path/trigger/minimal/no_slash.yml';
+import ProjectPathTriggerMinimalTailSlashYaml from './yaml_tests/negative_tests/project_path/trigger/minimal/tailing_slash.yml';
+import ProjectPathTriggerProjectEmptyYaml from './yaml_tests/negative_tests/project_path/trigger/project/empty.yml';
+import ProjectPathTriggerProjectInvalidVariableYaml from './yaml_tests/negative_tests/project_path/trigger/project/invalid_variable.yml';
+import ProjectPathTriggerProjectLeadSlashYaml from './yaml_tests/negative_tests/project_path/trigger/project/leading_slash.yml';
+import ProjectPathTriggerProjectNoSlashYaml from './yaml_tests/negative_tests/project_path/trigger/project/no_slash.yml';
+import ProjectPathTriggerProjectTailSlashYaml from './yaml_tests/negative_tests/project_path/trigger/project/tailing_slash.yml';
const ajv = new Ajv({
strictTypes: false,
@@ -67,6 +91,8 @@ describe('positive tests', () => {
FilterYaml,
IncludeYaml,
RulesYaml,
+ VariablesYaml,
+ ProjectPathYaml,
}),
)('schema validates %s', (_, input) => {
expect(input).toValidateJsonSchema(schema);
@@ -90,6 +116,27 @@ describe('negative tests', () => {
CacheNegativeYaml,
IncludeNegativeYaml,
RulesNegativeYaml,
+ VariablesNegativeYaml,
+ ProjectPathIncludeEmptyYaml,
+ ProjectPathIncludeInvalidVariableYaml,
+ ProjectPathIncludeLeadSlashYaml,
+ ProjectPathIncludeNoSlashYaml,
+ ProjectPathIncludeTailSlashYaml,
+ ProjectPathTriggerIncludeEmptyYaml,
+ ProjectPathTriggerIncludeInvalidVariableYaml,
+ ProjectPathTriggerIncludeLeadSlashYaml,
+ ProjectPathTriggerIncludeNoSlashYaml,
+ ProjectPathTriggerIncludeTailSlashYaml,
+ ProjectPathTriggerMinimalEmptyYaml,
+ ProjectPathTriggerMinimalInvalidVariableYaml,
+ ProjectPathTriggerMinimalLeadSlashYaml,
+ ProjectPathTriggerMinimalNoSlashYaml,
+ ProjectPathTriggerMinimalTailSlashYaml,
+ ProjectPathTriggerProjectEmptyYaml,
+ ProjectPathTriggerProjectInvalidVariableYaml,
+ ProjectPathTriggerProjectLeadSlashYaml,
+ ProjectPathTriggerProjectNoSlashYaml,
+ ProjectPathTriggerProjectTailSlashYaml,
}),
)('schema validates %s', (_, input) => {
expect(input).not.toValidateJsonSchema(schema);
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/empty.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/empty.yml
new file mode 100644
index 00000000000..d9838fbb6fd
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/empty.yml
@@ -0,0 +1,3 @@
+include:
+ - project: ''
+ file: '/templates/.gitlab-ci-template.yml'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/invalid_variable.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/invalid_variable.yml
new file mode 100644
index 00000000000..32933f856c7
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/invalid_variable.yml
@@ -0,0 +1,3 @@
+include:
+ - project: 'slug#'
+ file: '/templates/.gitlab-ci-template.yml'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/leading_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/leading_slash.yml
new file mode 100644
index 00000000000..c463318be31
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/leading_slash.yml
@@ -0,0 +1,3 @@
+include:
+ - project: '/slug'
+ file: '/templates/.gitlab-ci-template.yml'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/no_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/no_slash.yml
new file mode 100644
index 00000000000..51194a1d40c
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/no_slash.yml
@@ -0,0 +1,3 @@
+include:
+ - project: 'slug'
+ file: '/templates/.gitlab-ci-template.yml'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/tailing_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/tailing_slash.yml
new file mode 100644
index 00000000000..91f258888d8
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/include/tailing_slash.yml
@@ -0,0 +1,3 @@
+include:
+ - project: 'slug/'
+ file: '/templates/.gitlab-ci-template.yml'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/empty.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/empty.yml
new file mode 100644
index 00000000000..ee2bb3e8ace
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/empty.yml
@@ -0,0 +1,5 @@
+trigger-include:
+ trigger:
+ include:
+ - file: '/path/to/child-pipeline.yml'
+ project: ''
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/invalid_variable.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/invalid_variable.yml
new file mode 100644
index 00000000000..770305be0dc
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/invalid_variable.yml
@@ -0,0 +1,5 @@
+trigger-include:
+ trigger:
+ include:
+ - file: '/path/to/child-pipeline.yml'
+ project: 'slug#'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/leading_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/leading_slash.yml
new file mode 100644
index 00000000000..82fd77cf0d3
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/leading_slash.yml
@@ -0,0 +1,5 @@
+trigger-include:
+ trigger:
+ include:
+ - file: '/path/to/child-pipeline.yml'
+ project: '/slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/no_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/no_slash.yml
new file mode 100644
index 00000000000..f4ea59c7945
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/no_slash.yml
@@ -0,0 +1,5 @@
+trigger-include:
+ trigger:
+ include:
+ - file: '/path/to/child-pipeline.yml'
+ project: 'slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/tailing_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/tailing_slash.yml
new file mode 100644
index 00000000000..a0195c03352
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/include/tailing_slash.yml
@@ -0,0 +1,5 @@
+trigger-include:
+ trigger:
+ include:
+ - file: '/path/to/child-pipeline.yml'
+ project: 'slug/'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/empty.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/empty.yml
new file mode 100644
index 00000000000..cad8dbbf430
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/empty.yml
@@ -0,0 +1,2 @@
+trigger-minimal:
+ trigger: ''
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/invalid_variable.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/invalid_variable.yml
new file mode 100644
index 00000000000..6ca37666d09
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/invalid_variable.yml
@@ -0,0 +1,2 @@
+trigger-minimal:
+ trigger: 'slug#'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/leading_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/leading_slash.yml
new file mode 100644
index 00000000000..9d7c6b44125
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/leading_slash.yml
@@ -0,0 +1,2 @@
+trigger-minimal:
+ trigger: '/slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/no_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/no_slash.yml
new file mode 100644
index 00000000000..acd047477c8
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/no_slash.yml
@@ -0,0 +1,2 @@
+trigger-minimal:
+ trigger: 'slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/tailing_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/tailing_slash.yml
new file mode 100644
index 00000000000..0fdd00da3de
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/minimal/tailing_slash.yml
@@ -0,0 +1,2 @@
+trigger-minimal:
+ trigger: 'slug/'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/empty.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/empty.yml
new file mode 100644
index 00000000000..0aa2330cecb
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/empty.yml
@@ -0,0 +1,3 @@
+trigger-project:
+ trigger:
+ project: ''
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/invalid_variable.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/invalid_variable.yml
new file mode 100644
index 00000000000..3c17ec62039
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/invalid_variable.yml
@@ -0,0 +1,3 @@
+trigger-project:
+ trigger:
+ project: 'slug#'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/leading_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/leading_slash.yml
new file mode 100644
index 00000000000..f9884603171
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/leading_slash.yml
@@ -0,0 +1,3 @@
+trigger-project:
+ trigger:
+ project: '/slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/no_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/no_slash.yml
new file mode 100644
index 00000000000..d89e09756eb
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/no_slash.yml
@@ -0,0 +1,3 @@
+trigger-project:
+ trigger:
+ project: 'slug'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/tailing_slash.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/tailing_slash.yml
new file mode 100644
index 00000000000..3c39d6be4cb
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/project_path/trigger/project/tailing_slash.yml
@@ -0,0 +1,3 @@
+trigger-project:
+ trigger:
+ project: 'slug/'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml
new file mode 100644
index 00000000000..a7f23cf0d73
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml
@@ -0,0 +1,5 @@
+# invalid variable (unknown keyword is used)
+variables:
+ FOO:
+ value: BAR
+ desc: A single value variable
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/project_path.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/project_path.yml
new file mode 100644
index 00000000000..8a12cdf4f15
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/project_path.yml
@@ -0,0 +1,101 @@
+# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95469
+# Test cases:
+# - include file from project
+# - trigger pipeline from project, 3 forms (see schema at ci.json)
+#
+# Sub-cases - forms of project path:
+# - common case: group/project
+# - sub-group: group/sub-group/project
+# - variable: $FOO
+# - variable in string: group/$VAR/project
+# - invalid variable: $.
+# (testing regex, that does not validate variable names)
+
+# BEGIN CASE: include yml from project
+include:
+ - project: 'group/project'
+ file: '/templates/.gitlab-ci-template.yml'
+
+ - project: 'group/sub-group/project'
+ file: '/templates/.gitlab-ci-template.yml'
+
+ - project: '$FOO'
+ file: '/templates/.gitlab-ci-template.yml'
+
+ - project: 'group/$VAR/project'
+ file: '/templates/.gitlab-ci-template.yml'
+
+ - project: '$.'
+ file: '/templates/.gitlab-ci-template.yml'
+# END CASE
+
+# BEGIN CASE: trigger minimal
+trigger-minimal:
+ trigger: 'group/project'
+
+trigger-minimal-sub-group:
+ trigger: 'group/sub-group/project'
+
+trigger-minimal-variable:
+ trigger: '$FOO'
+
+trigger-minimal-variable-in-string:
+ trigger: 'group/$VAR/project'
+
+trigger-minimal-invalid-variable:
+ trigger: '$.'
+# END CASE
+
+# BEGIN CASE: trigger project
+trigger-project:
+ trigger:
+ project: 'group/project'
+
+trigger-project-sub-group:
+ trigger:
+ project: 'group/sub-group/project'
+
+trigger-project-variable:
+ trigger:
+ project: '$FOO'
+
+trigger-project-variable-in-string:
+ trigger:
+ project: 'group/$VAR/project'
+
+trigger-project-invalid-variable:
+ trigger:
+ project: '$.'
+# END CASE
+
+# BEGIN CASE: trigger file
+trigger-include:
+ trigger:
+ include:
+ - project: 'group/project'
+ file: '/path/to/child-pipeline.yml'
+
+trigger-include-sub-group:
+ trigger:
+ include:
+ - project: 'group/sub-group/project'
+ file: '/path/to/child-pipeline.yml'
+
+trigger-include-variable:
+ trigger:
+ include:
+ - project: '$FOO'
+ file: '/path/to/child-pipeline.yml'
+
+trigger-include-variable-in-string:
+ trigger:
+ include:
+ - project: 'group/$VAR/project'
+ file: '/path/to/child-pipeline.yml'
+
+trigger-include-invalid-variable:
+ trigger:
+ include:
+ - project: '$.'
+ file: '/path/to/child-pipeline.yml'
+# END CASE
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml
index 37cae6b4264..ef604f707b5 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml
@@ -15,7 +15,9 @@ rules:changes as array of strings:
# valid workflow:rules:exists
# valid rules:changes:path
+# valid workflow:name
workflow:
+ name: 'Pipeline name'
rules:
- changes:
paths:
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml
new file mode 100644
index 00000000000..ee71087a72e
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml
@@ -0,0 +1,8 @@
+variables:
+ TEST_VAR: "hello world!"
+ 123456: "123456"
+ FOO:
+ value: "BAR"
+ description: "A single value variable"
+ DEPLOY_ENVIRONMENT:
+ description: "A multi-value variable"
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 9a14e1a55eb..21f8979f1a9 100644
--- a/spec/frontend/editor/source_editor_ci_schema_ext_spec.js
+++ b/spec/frontend/editor/source_editor_ci_schema_ext_spec.js
@@ -1,4 +1,4 @@
-import { languages } from 'monaco-editor';
+import { setDiagnosticsOptions } from 'monaco-yaml';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
@@ -52,16 +52,12 @@ describe('~/editor/editor_ci_config_ext', () => {
});
describe('registerCiSchema', () => {
- beforeEach(() => {
- jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
- });
-
describe('register validations options with monaco for yaml language', () => {
const mockProjectNamespace = 'namespace1';
const mockProjectPath = 'project1';
const getConfiguredYmlSchema = () => {
- return languages.yaml.yamlDefaults.setDiagnosticsOptions.mock.calls[0][0].schemas[0];
+ return setDiagnosticsOptions.mock.calls[0][0].schemas[0];
};
it('with expected basic validation configuration', () => {
@@ -77,8 +73,8 @@ describe('~/editor/editor_ci_config_ext', () => {
completion: true,
};
- expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledTimes(1);
- expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect(setDiagnosticsOptions).toHaveBeenCalledTimes(1);
+ expect(setDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining(expectedOptions),
);
});
diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js
index 20ba23d56ff..89b5ad27690 100644
--- a/spec/frontend/editor/source_editor_instance_spec.js
+++ b/spec/frontend/editor/source_editor_instance_spec.js
@@ -160,7 +160,7 @@ describe('Source Editor Instance', () => {
});
describe('public API', () => {
- it.each(['use', 'unuse'], 'provides "%s" as public method by default', (method) => {
+ it.each(['use', 'unuse'])('provides "%s" as public method by default', (method) => {
seInstance = new SourceEditorInstance();
expect(seInstance[method]).toBeDefined();
});
diff --git a/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js b/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js
index fe20c23e4d7..1ff351b6554 100644
--- a/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js
+++ b/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js
@@ -12,7 +12,7 @@ import {
} from '~/editor/constants';
import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
import SourceEditor from '~/editor/source_editor';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import syntaxHighlight from '~/syntax_highlight';
import { spyOnApi } from './helpers';
@@ -279,7 +279,7 @@ describe('Markdown Live Preview Extension for Source Editor', () => {
mockAxios.onPost().reply(500);
await fetchPreview();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/environments/delete_environment_modal_spec.js b/spec/frontend/environments/delete_environment_modal_spec.js
index 48e4f661c1d..cc18bf754eb 100644
--- a/spec/frontend/environments/delete_environment_modal_spec.js
+++ b/spec/frontend/environments/delete_environment_modal_spec.js
@@ -6,7 +6,7 @@ import { s__, sprintf } from '~/locale';
import DeleteEnvironmentModal from '~/environments/components/delete_environment_modal.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { resolvedEnvironment } from './graphql/mock_data';
jest.mock('~/flash');
@@ -57,7 +57,7 @@ describe('~/environments/components/delete_environment_modal.vue', () => {
await nextTick();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(deleteResolver).toHaveBeenCalledWith(
expect.anything(),
@@ -76,7 +76,7 @@ describe('~/environments/components/delete_environment_modal.vue', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: s__(
'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js
index 0f2d6e95bf0..5ea23af4c16 100644
--- a/spec/frontend/environments/edit_environment_spec.js
+++ b/spec/frontend/environments/edit_environment_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import EditEnvironment from '~/environments/components/edit_environment.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -85,7 +85,7 @@ describe('~/environments/components/edit.vue', () => {
await submitForm(expected, [400, { message: ['uh oh!'] }]);
- expect(createFlash).toHaveBeenCalledWith({ message: 'uh oh!' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' });
expect(showsLoading()).toBe(false);
});
diff --git a/spec/frontend/environments/empty_state_spec.js b/spec/frontend/environments/empty_state_spec.js
index 974afc6d032..02cf2dc3c68 100644
--- a/spec/frontend/environments/empty_state_spec.js
+++ b/spec/frontend/environments/empty_state_spec.js
@@ -4,10 +4,21 @@ import EmptyState from '~/environments/components/empty_state.vue';
import { ENVIRONMENTS_SCOPE } from '~/environments/constants';
const HELP_PATH = '/help';
+const NEW_PATH = '/new';
describe('~/environments/components/empty_state.vue', () => {
let wrapper;
+ const findNewEnvironmentLink = () =>
+ wrapper.findByRole('link', {
+ name: s__('Environments|New environment'),
+ });
+
+ const findDocsLink = () =>
+ wrapper.findByRole('link', {
+ name: s__('Environments|How do I create an environment?'),
+ });
+
const createWrapper = ({ propsData = {} } = {}) =>
mountExtended(EmptyState, {
propsData: {
@@ -15,6 +26,7 @@ describe('~/environments/components/empty_state.vue', () => {
helpPath: HELP_PATH,
...propsData,
},
+ provide: { newEnvironmentPath: NEW_PATH },
});
afterEach(() => {
@@ -44,10 +56,44 @@ describe('~/environments/components/empty_state.vue', () => {
it('shows a link to the the help path', () => {
wrapper = createWrapper();
- const link = wrapper.findByRole('link', {
- name: s__('Environments|How do I create an environment?'),
- });
+ const link = findDocsLink();
expect(link.attributes('href')).toBe(HELP_PATH);
});
+
+ it('hides a link to creating a new environment', () => {
+ const link = findNewEnvironmentLink();
+
+ expect(link.exists()).toBe(false);
+ });
+
+ describe('with search term', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ propsData: { hasTerm: true } });
+ });
+
+ it('should show text about searching', () => {
+ const header = wrapper.findByRole('heading', {
+ name: s__('Environments|No results found'),
+ });
+
+ expect(header.exists()).toBe(true);
+
+ const text = wrapper.findByText(s__('Environments|Edit your search and try again'));
+
+ expect(text.exists()).toBe(true);
+ });
+
+ it('hides the documentation link', () => {
+ const link = findDocsLink();
+
+ expect(link.exists()).toBe(false);
+ });
+
+ it('shows a link to create a new environment', () => {
+ const link = findNewEnvironmentLink();
+
+ expect(link.attributes('href')).toBe(NEW_PATH);
+ });
+ });
});
diff --git a/spec/frontend/environments/enable_review_app_modal_spec.js b/spec/frontend/environments/enable_review_app_modal_spec.js
index b6dac811ea6..7939bd600dc 100644
--- a/spec/frontend/environments/enable_review_app_modal_spec.js
+++ b/spec/frontend/environments/enable_review_app_modal_spec.js
@@ -1,7 +1,8 @@
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 EnableReviewAppModal from '~/environments/components/enable_review_app_modal.vue';
+import { REVIEW_APP_MODAL_I18N as i18n } from '~/environments/constants';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
// hardcode uniqueId for determinism
@@ -9,10 +10,12 @@ jest.mock('lodash/uniqueId', () => (x) => `${x}77`);
const EXPECTED_COPY_PRE_ID = 'enable-review-app-copy-string-77';
-describe('Enable Review App Button', () => {
+describe('Enable Review App Modal', () => {
let wrapper;
let modal;
+ const findInstructions = () => wrapper.findAll('ol li');
+ const findInstructionAt = (i) => wrapper.findAll('ol li').at(i);
const findCopyString = () => wrapper.find(`#${EXPECTED_COPY_PRE_ID}`);
afterEach(() => {
@@ -22,29 +25,31 @@ describe('Enable Review App Button', () => {
describe('renders the modal', () => {
beforeEach(() => {
wrapper = extendedWrapper(
- shallowMount(EnableReviewAppButton, {
+ shallowMount(EnableReviewAppModal, {
propsData: {
modalId: 'fake-id',
visible: true,
},
- provide: {
- defaultBranchName: 'main',
- },
}),
);
modal = wrapper.findComponent(GlModal);
});
- it('renders the defaultBranchName copy', () => {
- expect(findCopyString().text()).toContain('- main');
+ it('displays instructions', () => {
+ expect(findInstructions().length).toBe(7);
+ expect(findInstructionAt(0).text()).toContain(i18n.instructions.step1);
+ });
+
+ it('renders the snippet to copy', () => {
+ expect(findCopyString().text()).toBe(wrapper.vm.modalInfoCopyStr);
});
it('renders the copyToClipboard button', () => {
expect(wrapper.findComponent(ModalCopyButton).props()).toMatchObject({
modalId: 'fake-id',
target: `#${EXPECTED_COPY_PRE_ID}`,
- title: 'Copy snippet text',
+ title: i18n.copyToClipboardText,
});
});
diff --git a/spec/frontend/environments/environment_external_url_spec.js b/spec/frontend/environments/environment_external_url_spec.js
index 4c133665979..5966993166b 100644
--- a/spec/frontend/environments/environment_external_url_spec.js
+++ b/spec/frontend/environments/environment_external_url_spec.js
@@ -1,16 +1,35 @@
import { mount } from '@vue/test-utils';
+import { s__, __ } from '~/locale';
import ExternalUrlComp from '~/environments/components/environment_external_url.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
describe('External URL Component', () => {
let wrapper;
- const externalUrl = 'https://gitlab.com';
+ let externalUrl;
- beforeEach(() => {
- wrapper = mount(ExternalUrlComp, { propsData: { externalUrl } });
+ describe('with safe link', () => {
+ beforeEach(() => {
+ externalUrl = 'https://gitlab.com';
+ wrapper = mount(ExternalUrlComp, { propsData: { externalUrl } });
+ });
+
+ it('should link to the provided externalUrl prop', () => {
+ expect(wrapper.attributes('href')).toBe(externalUrl);
+ expect(wrapper.find('a').exists()).toBe(true);
+ });
});
- it('should link to the provided externalUrl prop', () => {
- expect(wrapper.attributes('href')).toEqual(externalUrl);
- expect(wrapper.find('a').exists()).toBe(true);
+ describe('with unsafe link', () => {
+ beforeEach(() => {
+ externalUrl = 'postgres://gitlab';
+ wrapper = mount(ExternalUrlComp, { propsData: { externalUrl } });
+ });
+
+ it('should show a copy button instead', () => {
+ const button = wrapper.findComponent(ModalCopyButton);
+ expect(button.props('text')).toBe(externalUrl);
+ expect(button.text()).toBe(__('Copy URL'));
+ expect(button.props('title')).toBe(s__('Environments|Copy live environment URL'));
+ });
});
});
diff --git a/spec/frontend/environments/environment_folder_spec.js b/spec/frontend/environments/environment_folder_spec.js
index 48624f2324b..a37515bc3f7 100644
--- a/spec/frontend/environments/environment_folder_spec.js
+++ b/spec/frontend/environments/environment_folder_spec.js
@@ -31,6 +31,7 @@ describe('~/environments/components/environments_folder.vue', () => {
apolloProvider,
propsData: {
scope: 'available',
+ search: '',
...propsData,
},
stubs: { transition: stubTransition() },
@@ -137,13 +138,26 @@ describe('~/environments/components/environments_folder.vue', () => {
expect(environmentFolderMock).toHaveBeenCalledTimes(1);
expect(environmentFolderMock).toHaveBeenCalledWith(
{},
- {
- environment: nestedEnvironment.latest,
- scope,
- },
+ expect.objectContaining({ scope }),
expect.anything(),
expect.anything(),
);
},
);
+
+ it('should query for the entered parameter', async () => {
+ const search = 'hello';
+
+ wrapper = createWrapper({ nestedEnvironment, search }, createApolloProvider());
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(environmentFolderMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ search }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
});
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index aff54107d6b..65a9f2907d2 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -71,7 +71,7 @@ describe('~/environments/components/environments_app.vue', () => {
previousPage: 1,
__typename: 'LocalPageInfo',
},
- location = '?scope=available&page=2',
+ location = '?scope=available&page=2&search=prod',
}) => {
setWindowLocation(location);
environmentAppMock.mockReturnValue(environmentsApp);
@@ -104,7 +104,7 @@ describe('~/environments/components/environments_app.vue', () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
- location: '?scope=bad&page=2',
+ location: '?scope=bad&page=2&search=prod',
});
expect(environmentAppMock).toHaveBeenCalledWith(
@@ -350,7 +350,54 @@ describe('~/environments/components/environments_app.vue', () => {
next.trigger('click');
await nextTick();
- expect(window.location.search).toBe('?scope=available&page=3');
+ expect(window.location.search).toBe('?scope=available&page=3&search=prod');
+ });
+ });
+
+ describe('search', () => {
+ let searchBox;
+
+ const waitForDebounce = async () => {
+ await nextTick();
+ jest.runOnlyPendingTimers();
+ };
+
+ beforeEach(async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+ searchBox = wrapper.findByRole('searchbox', {
+ name: s__('Environments|Search by environment name'),
+ });
+ });
+
+ it('should sync the query params to the new search', async () => {
+ searchBox.setValue('hello');
+
+ await waitForDebounce();
+
+ expect(window.location.search).toBe('?scope=available&page=1&search=hello');
+ });
+
+ it('should query for the entered parameter', async () => {
+ const search = 'hello';
+
+ searchBox.setValue(search);
+
+ await waitForDebounce();
+ await waitForPromises();
+
+ expect(environmentAppMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ search }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('should sync search term from query params on load', async () => {
+ expect(searchBox.element.value).toBe('prod');
});
});
});
diff --git a/spec/frontend/environments/environments_detail_header_spec.js b/spec/frontend/environments/environments_detail_header_spec.js
index 4687119127d..1f233c05fbf 100644
--- a/spec/frontend/environments/environments_detail_header_spec.js
+++ b/spec/frontend/environments/environments_detail_header_spec.js
@@ -1,10 +1,12 @@
import { GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { __, s__ } from '~/locale';
import DeleteEnvironmentModal from '~/environments/components/delete_environment_modal.vue';
import EnvironmentsDetailHeader from '~/environments/components/environments_detail_header.vue';
import StopEnvironmentModal from '~/environments/components/stop_environment_modal.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import { createEnvironment } from './mock_data';
describe('Environments detail header component', () => {
@@ -243,4 +245,23 @@ describe('Environments detail header component', () => {
expect(findDeleteEnvironmentModal().exists()).toBe(true);
});
});
+
+ describe('when the environment has an unsafe external url', () => {
+ const externalUrl = 'postgres://staging';
+
+ beforeEach(() => {
+ createWrapper({
+ props: {
+ environment: createEnvironment({ externalUrl }),
+ },
+ });
+ });
+
+ it('should show a copy button instead', () => {
+ const button = wrapper.findComponent(ModalCopyButton);
+ expect(button.props('title')).toBe(s__('Environments|Copy live environment URL'));
+ expect(button.props('text')).toBe(externalUrl);
+ expect(button.text()).toBe(__('Copy URL'));
+ });
+ });
});
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
index 26f0659204a..7684cca2303 100644
--- a/spec/frontend/environments/graphql/resolvers_spec.js
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -41,11 +41,16 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should fetch environments and map them to frontend data', async () => {
const cache = { writeQuery: jest.fn() };
const scope = 'available';
+ const search = '';
mock
- .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search } })
.reply(200, environmentsApp, {});
- const app = await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ const app = await mockResolvers.Query.environmentApp(
+ null,
+ { scope, page: 1, search },
+ { cache },
+ );
expect(app).toEqual(resolvedEnvironmentsApp);
expect(cache.writeQuery).toHaveBeenCalledWith({
query: pollIntervalQuery,
@@ -57,12 +62,12 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const scope = 'stopped';
const interval = 3000;
mock
- .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
.reply(200, environmentsApp, {
'poll-interval': interval,
});
- await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache });
expect(cache.writeQuery).toHaveBeenCalledWith({
query: pollIntervalQuery,
data: { interval },
@@ -72,7 +77,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const cache = { writeQuery: jest.fn() };
const scope = 'stopped';
mock
- .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
.reply(200, environmentsApp, {
'x-next-page': '2',
'x-page': '1',
@@ -82,7 +87,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
'X-Total-Pages': '5',
});
- await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache });
expect(cache.writeQuery).toHaveBeenCalledWith({
query: pageInfoQuery,
data: {
@@ -102,10 +107,10 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const cache = { writeQuery: jest.fn() };
const scope = 'stopped';
mock
- .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
.reply(200, environmentsApp, {});
- await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache });
expect(cache.writeQuery).toHaveBeenCalledWith({
query: pageInfoQuery,
data: {
@@ -124,11 +129,14 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('folder', () => {
it('should fetch the folder url passed to it', async () => {
- mock.onGet(ENDPOINT, { params: { per_page: 3, scope: 'available' } }).reply(200, folder);
+ mock
+ .onGet(ENDPOINT, { params: { per_page: 3, scope: 'available', search: '' } })
+ .reply(200, folder);
const environmentFolder = await mockResolvers.Query.folder(null, {
environment: { folderPath: ENDPOINT },
scope: 'available',
+ search: '',
});
expect(environmentFolder).toEqual(resolvedFolder);
diff --git a/spec/frontend/environments/new_environment_spec.js b/spec/frontend/environments/new_environment_spec.js
index 2405cb82eac..6dd4eea7437 100644
--- a/spec/frontend/environments/new_environment_spec.js
+++ b/spec/frontend/environments/new_environment_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import NewEnvironment from '~/environments/components/new_environment.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -94,7 +94,7 @@ describe('~/environments/components/new.vue', () => {
await submitForm(expected, [400, { message: ['name taken'] }]);
- expect(createFlash).toHaveBeenCalledWith({ message: 'name taken' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'name taken' });
expect(showsLoading()).toBe(false);
});
});
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 732eff65495..9d6e46be8c4 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -18,7 +18,7 @@ import {
trackErrorDetailsViewsOptions,
trackErrorStatusUpdateOptions,
} from '~/error_tracking/utils';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_WARNING } from '~/flash';
import { __ } from '~/locale';
import Tracking from '~/tracking';
@@ -144,7 +144,7 @@ describe('ErrorDetails', () => {
await nextTick();
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
});
@@ -156,9 +156,9 @@ describe('ErrorDetails', () => {
await nextTick();
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.findComponent(GlLink).exists()).toBe(false);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Could not connect to Sentry. Refresh the page to try again.',
- type: 'warning',
+ variant: VARIANT_WARNING,
});
expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
});
diff --git a/spec/frontend/error_tracking/store/actions_spec.js b/spec/frontend/error_tracking/store/actions_spec.js
index 6bac21341a7..8f085282f80 100644
--- a/spec/frontend/error_tracking/store/actions_spec.js
+++ b/spec/frontend/error_tracking/store/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/actions';
import * as types from '~/error_tracking/store/mutation_types';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -20,7 +20,7 @@ describe('Sentry common store actions', () => {
afterEach(() => {
mock.restore();
- createFlash.mockClear();
+ createAlert.mockClear();
});
const endpoint = '123/stacktrace';
const redirectUrl = '/list';
@@ -49,7 +49,7 @@ describe('Sentry common store actions', () => {
mock.onPut().reply(400, {});
await testAction(actions.updateStatus, params, {}, [], []);
expect(visitUrl).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/error_tracking/store/details/actions_spec.js b/spec/frontend/error_tracking/store/details/actions_spec.js
index a3a6f7cc309..1893d226270 100644
--- a/spec/frontend/error_tracking/store/details/actions_spec.js
+++ b/spec/frontend/error_tracking/store/details/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/details/actions';
import * as types from '~/error_tracking/store/details/mutation_types';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
@@ -19,7 +19,7 @@ describe('Sentry error details store actions', () => {
afterEach(() => {
mockedAdapter.restore();
- createFlash.mockClear();
+ createAlert.mockClear();
if (mockedRestart) {
mockedRestart.mockRestore();
mockedRestart = null;
@@ -53,7 +53,7 @@ describe('Sentry error details store actions', () => {
[{ type: types.SET_LOADING_STACKTRACE, payload: false }],
[],
);
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
it('should not restart polling when receiving an empty 204 response', async () => {
diff --git a/spec/frontend/error_tracking/store/list/actions_spec.js b/spec/frontend/error_tracking/store/list/actions_spec.js
index 7173f68bb96..2809bbe834e 100644
--- a/spec/frontend/error_tracking/store/list/actions_spec.js
+++ b/spec/frontend/error_tracking/store/list/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/list/actions';
import * as types from '~/error_tracking/store/list/mutation_types';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -51,7 +51,7 @@ describe('error tracking actions', () => {
],
[],
);
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
index b87571830ca..22bac3fca15 100644
--- a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
+++ b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import { dismiss } from '~/feature_highlight/feature_highlight_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -32,7 +32,7 @@ describe('feature highlight helper', () => {
await dismiss(endpoint, highlightId);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message:
'An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.',
});
diff --git a/spec/frontend/fixtures/namespaces.rb b/spec/frontend/fixtures/namespaces.rb
index b11f661fe09..a3f295f4e66 100644
--- a/spec/frontend/fixtures/namespaces.rb
+++ b/spec/frontend/fixtures/namespaces.rb
@@ -7,38 +7,43 @@ RSpec.describe 'Jobs (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
include GraphqlHelpers
- describe GraphQL::Query, type: :request do
+ describe API::Projects, type: :request do
let_it_be(:user) { create(:user) }
- let_it_be(:groups) { create_list(:group, 4) }
- before_all do
- groups.each { |group| group.add_owner(user) }
- end
+ describe 'transfer_locations' do
+ let_it_be(:groups) { create_list(:group, 4) }
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
- query_name = 'search_namespaces_where_user_can_transfer_projects'
- query_extension = '.query.graphql'
+ before_all do
+ groups.each { |group| group.add_owner(user) }
+ end
- full_input_path = "projects/settings/graphql/queries/#{query_name}#{query_extension}"
- base_output_path = "graphql/projects/settings/#{query_name}"
+ it 'api/projects/transfer_locations_page_1.json' do
+ get api("/projects/#{project.id}/transfer_locations?per_page=2", user)
- it "#{base_output_path}_page_1#{query_extension}.json" do
- query = get_graphql_query_as_string(full_input_path)
+ expect(response).to be_successful
+ end
- post_graphql(query, current_user: user, variables: { first: 2 })
+ it 'api/projects/transfer_locations_page_2.json' do
+ get api("/projects/#{project.id}/transfer_locations?per_page=2&page=2", user)
- expect_graphql_errors_to_be_empty
+ expect(response).to be_successful
+ end
end
+ end
+
+ describe GraphQL::Query, type: :request do
+ let_it_be(:user) { create(:user) }
+
+ query_name = 'current_user_namespace.query.graphql'
- it "#{base_output_path}_page_2#{query_extension}.json" do
- query = get_graphql_query_as_string(full_input_path)
+ input_path = "projects/settings/graphql/queries/#{query_name}"
+ output_path = "graphql/projects/settings/#{query_name}.json"
- post_graphql(query, current_user: user, variables: { first: 2 })
+ it output_path do
+ query = get_graphql_query_as_string(input_path)
- post_graphql(
- query,
- current_user: user,
- variables: { first: 2, after: graphql_data_at('currentUser', 'groups', 'pageInfo', 'endCursor') }
- )
+ post_graphql(query, current_user: user)
expect_graphql_errors_to_be_empty
end
diff --git a/spec/frontend/fixtures/pipeline_schedules.rb b/spec/frontend/fixtures/pipeline_schedules.rb
index 5b7a445557e..4de0bd762f8 100644
--- a/spec/frontend/fixtures/pipeline_schedules.rb
+++ b/spec/frontend/fixtures/pipeline_schedules.rb
@@ -2,40 +2,74 @@
require 'spec_helper'
-RSpec.describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :controller do
+RSpec.describe 'Pipeline schedules (JavaScript fixtures)' do
+ include ApiHelpers
include JavaScriptFixturesHelpers
+ include GraphqlHelpers
let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :public, :repository) }
let(:user) { project.first_owner }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+ let!(:pipeline_schedule_inactive) { create(:ci_pipeline_schedule, :inactive, project: project, owner: user) }
let!(:pipeline_schedule_populated) { create(:ci_pipeline_schedule, project: project, owner: user) }
let!(:pipeline_schedule_variable1) { create(:ci_pipeline_schedule_variable, key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule_populated) }
let!(:pipeline_schedule_variable2) { create(:ci_pipeline_schedule_variable, key: 'bar', value: 'barvalue', pipeline_schedule: pipeline_schedule_populated) }
- render_views
+ describe Projects::PipelineSchedulesController, type: :controller do
+ render_views
- before do
- sign_in(user)
- end
+ before do
+ sign_in(user)
+ stub_feature_flags(pipeline_schedules_vue: false)
+ end
+
+ it 'pipeline_schedules/edit.html' do
+ get :edit, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: pipeline_schedule.id
+ }
+
+ expect(response).to be_successful
+ end
- it 'pipeline_schedules/edit.html' do
- get :edit, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: pipeline_schedule.id
- }
+ it 'pipeline_schedules/edit_with_variables.html' do
+ get :edit, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: pipeline_schedule_populated.id
+ }
- expect(response).to be_successful
+ expect(response).to be_successful
+ end
end
- it 'pipeline_schedules/edit_with_variables.html' do
- get :edit, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: pipeline_schedule_populated.id
- }
+ describe GraphQL::Query, type: :request do
+ before do
+ pipeline_schedule.pipelines << build(:ci_pipeline, project: project)
+ end
+
+ fixtures_path = 'graphql/pipeline_schedules/'
+ get_pipeline_schedules_query = 'get_pipeline_schedules.query.graphql'
+
+ let_it_be(:query) do
+ get_graphql_query_as_string("pipeline_schedules/graphql/queries/#{get_pipeline_schedules_query}")
+ end
+
+ it "#{fixtures_path}#{get_pipeline_schedules_query}.json" do
+ post_graphql(query, current_user: user, variables: { projectPath: project.full_path })
+
+ expect_graphql_errors_to_be_empty
+ end
+
+ it "#{fixtures_path}#{get_pipeline_schedules_query}.as_guest.json" do
+ guest = create(:user)
+ project.add_guest(user)
+
+ post_graphql(query, current_user: guest, variables: { projectPath: project.full_path })
- expect(response).to be_successful
+ expect_graphql_errors_to_be_empty
+ end
end
end
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index e26c52f0bf7..a809bf248bf 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -285,6 +285,13 @@ describe('Flash', () => {
expect(document.querySelector('.gl-alert')).toBeNull();
});
+ it('does not crash if calling .dismiss() twice', () => {
+ alert = createAlert({ message: mockMessage });
+
+ alert.dismiss();
+ expect(() => alert.dismiss()).not.toThrow();
+ });
+
it('calls onDismiss when dismissed', () => {
const dismissHandler = jest.fn();
diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
index d2111194097..021a3aa41ed 100644
--- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js
+++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import GrafanaIntegration from '~/grafana_integration/components/grafana_integration.vue';
import { createStore } from '~/grafana_integration/store';
import axios from '~/lib/utils/axios_utils';
@@ -30,7 +30,7 @@ describe('grafana integration component', () => {
afterEach(() => {
if (wrapper.destroy) {
wrapper.destroy();
- createFlash.mockReset();
+ createAlert.mockReset();
refreshCurrentPage.mockReset();
}
});
@@ -113,7 +113,7 @@ describe('grafana integration component', () => {
await nextTick();
await jest.runAllTicks();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `There was an error saving your changes. ${message}`,
});
});
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index a4a7530184d..091ec17d58e 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import appComponent from '~/groups/components/app.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue';
@@ -11,6 +11,7 @@ import eventHub from '~/groups/event_hub';
import GroupsService from '~/groups/service/groups_service';
import GroupsStore from '~/groups/store/groups_store';
import EmptyState from '~/groups/components/empty_state.vue';
+import GroupsComponent from '~/groups/components/groups.vue';
import axios from '~/lib/utils/axios_utils';
import * as urlUtilities from '~/lib/utils/url_utility';
import setWindowLocation from 'helpers/set_window_location_helper';
@@ -115,7 +116,7 @@ describe('AppComponent', () => {
return vm.fetchGroups({}).then(() => {
expect(vm.isLoading).toBe(false);
expect(window.scrollTo).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 });
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred. Please try again.',
});
});
@@ -326,7 +327,7 @@ describe('AppComponent', () => {
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
return waitForPromises().then(() => {
expect(vm.store.removeGroup).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message });
+ expect(createAlert).toHaveBeenCalledWith({ message });
expect(vm.targetGroup.isBeingRemoved).toBe(false);
});
});
@@ -341,7 +342,7 @@ describe('AppComponent', () => {
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
return waitForPromises().then(() => {
expect(vm.store.removeGroup).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({ message });
+ expect(createAlert).toHaveBeenCalledWith({ message });
expect(vm.targetGroup.isBeingRemoved).toBe(false);
});
});
@@ -388,24 +389,27 @@ describe('AppComponent', () => {
});
describe.each`
- action | groups | fromSearch | renderEmptyState | expected
- ${'subgroups_and_projects'} | ${[]} | ${false} | ${true} | ${true}
- ${''} | ${[]} | ${false} | ${true} | ${false}
- ${'subgroups_and_projects'} | ${mockGroups} | ${false} | ${true} | ${false}
- ${'subgroups_and_projects'} | ${[]} | ${true} | ${true} | ${false}
+ action | groups | fromSearch | shouldRenderEmptyState | searchEmpty
+ ${'subgroups_and_projects'} | ${[]} | ${false} | ${true} | ${false}
+ ${''} | ${[]} | ${false} | ${false} | ${false}
+ ${'subgroups_and_projects'} | ${mockGroups} | ${false} | ${false} | ${false}
+ ${'subgroups_and_projects'} | ${[]} | ${true} | ${false} | ${true}
`(
- 'when `action` is $action, `groups` is $groups, `fromSearch` is $fromSearch, and `renderEmptyState` is $renderEmptyState',
- ({ action, groups, fromSearch, renderEmptyState, expected }) => {
- it(expected ? 'renders empty state' : 'does not render empty state', async () => {
+ 'when `action` is $action, `groups` is $groups, and `fromSearch` is $fromSearch',
+ ({ action, groups, fromSearch, shouldRenderEmptyState, searchEmpty }) => {
+ it(`${shouldRenderEmptyState ? 'renders' : 'does not render'} empty state`, async () => {
createShallowComponent({
- propsData: { action, renderEmptyState },
+ propsData: { action, renderEmptyState: true },
});
+ await waitForPromises();
+
vm.updateGroups(groups, fromSearch);
await nextTick();
- expect(wrapper.findComponent(EmptyState).exists()).toBe(expected);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(shouldRenderEmptyState);
+ expect(wrapper.findComponent(GroupsComponent).props('searchEmpty')).toBe(searchEmpty);
});
},
);
@@ -440,18 +444,10 @@ describe('AppComponent', () => {
expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function));
- });
-
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', async () => {
- createShallowComponent();
- await nextTick();
- expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search');
- });
-
- it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', async () => {
- createShallowComponent({ propsData: { hideProjects: true } });
- await nextTick();
- expect(vm.searchEmptyMessage).toBe('No groups matched your search');
+ expect(eventHub.$on).toHaveBeenCalledWith(
+ 'fetchFilteredAndSortedGroups',
+ expect.any(Function),
+ );
});
});
@@ -468,6 +464,46 @@ describe('AppComponent', () => {
expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', expect.any(Function));
expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function));
+ expect(eventHub.$off).toHaveBeenCalledWith(
+ 'fetchFilteredAndSortedGroups',
+ expect.any(Function),
+ );
+ });
+ });
+
+ describe('when `fetchFilteredAndSortedGroups` event is emitted', () => {
+ const search = 'Foo bar';
+ const sort = 'created_asc';
+ const emitFetchFilteredAndSortedGroups = () => {
+ eventHub.$emit('fetchFilteredAndSortedGroups', {
+ filterGroupsBy: search,
+ sortBy: sort,
+ });
+ };
+ let setPaginationInfoSpy;
+
+ beforeEach(() => {
+ setPaginationInfoSpy = jest.spyOn(GroupsStore.prototype, 'setPaginationInfo');
+ createShallowComponent();
+ });
+
+ it('renders loading icon', async () => {
+ emitFetchFilteredAndSortedGroups();
+ await nextTick();
+
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('calls API with expected params', () => {
+ emitFetchFilteredAndSortedGroups();
+
+ expect(getGroupsSpy).toHaveBeenCalledWith(undefined, undefined, search, sort, undefined);
+ });
+
+ it('updates pagination', () => {
+ emitFetchFilteredAndSortedGroups();
+
+ expect(setPaginationInfoSpy).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index 3aa66644c19..4570aa33a6c 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -245,19 +245,14 @@ describe('GroupItemComponent', () => {
expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
});
});
+
describe('schema.org props', () => {
describe('when showSchemaMarkup is disabled on the group', () => {
- it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', (attr) => {
+ it.each(['itemprop', 'itemtype', 'itemscope'])('does not set %s', (attr) => {
expect(wrapper.attributes(attr)).toBeUndefined();
});
- it.each(
- ['.js-group-avatar', '.js-group-name', '.js-group-description'],
- 'it does not set `itemprop` on sub-nodes',
- (selector) => {
- expect(wrapper.find(selector).attributes('itemprop')).toBeUndefined();
- },
- );
});
+
describe('when group has microdata', () => {
beforeEach(() => {
const group = withMicrodata({
diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js
index 866868eff36..0cbb6cc8309 100644
--- a/spec/frontend/groups/components/groups_spec.js
+++ b/spec/frontend/groups/components/groups_spec.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { GlEmptyState } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import GroupFolderComponent from '~/groups/components/group_folder.vue';
@@ -15,7 +16,6 @@ describe('GroupsComponent', () => {
const defaultPropsData = {
groups: mockGroups,
pageInfo: mockPageInfo,
- searchEmptyMessage: 'No matching results',
searchEmpty: false,
};
@@ -67,13 +67,16 @@ describe('GroupsComponent', () => {
expect(wrapper.findComponent(GroupFolderComponent).exists()).toBe(true);
expect(findPaginationLinks().exists()).toBe(true);
- expect(wrapper.findByText(defaultPropsData.searchEmptyMessage).exists()).toBe(false);
+ expect(wrapper.findComponent(GlEmptyState).exists()).toBe(false);
});
it('should render empty search message when `searchEmpty` is `true`', () => {
createComponent({ propsData: { searchEmpty: true } });
- expect(wrapper.findByText(defaultPropsData.searchEmptyMessage).exists()).toBe(true);
+ expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({
+ title: GroupsComponent.i18n.emptyStateTitle,
+ description: GroupsComponent.i18n.emptyStateDescription,
+ });
});
});
});
diff --git a/spec/frontend/groups/components/new_top_level_group_alert_spec.js b/spec/frontend/groups/components/new_top_level_group_alert_spec.js
new file mode 100644
index 00000000000..db9a5c7b16b
--- /dev/null
+++ b/spec/frontend/groups/components/new_top_level_group_alert_spec.js
@@ -0,0 +1,75 @@
+import { shallowMount } from '@vue/test-utils';
+import NewTopLevelGroupAlert from '~/groups/components/new_top_level_group_alert.vue';
+import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+describe('NewTopLevelGroupAlert', () => {
+ let wrapper;
+ let userCalloutDismissSpy;
+
+ const findAlert = () => wrapper.findComponent({ ref: 'newTopLevelAlert' });
+ const createSubGroupPath = '/groups/new?parent_id=1#create-group-pane';
+
+ const createComponent = ({ shouldShowCallout = true } = {}) => {
+ userCalloutDismissSpy = jest.fn();
+
+ wrapper = shallowMount(NewTopLevelGroupAlert, {
+ provide: {
+ createSubGroupPath,
+ },
+ stubs: {
+ UserCalloutDismisser: makeMockUserCalloutDismisser({
+ dismiss: userCalloutDismissSpy,
+ shouldShowCallout,
+ }),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when the component is created', () => {
+ beforeEach(() => {
+ createComponent({
+ shouldShowCallout: true,
+ });
+ });
+
+ it('renders a button with a link to create a new sub-group', () => {
+ expect(findAlert().props('primaryButtonText')).toBe(
+ NewTopLevelGroupAlert.i18n.primaryBtnText,
+ );
+ expect(findAlert().props('primaryButtonLink')).toBe(
+ helpPagePath('user/group/subgroups/index'),
+ );
+ });
+ });
+
+ describe('dismissing the alert', () => {
+ beforeEach(() => {
+ findAlert().vm.$emit('dismiss');
+ });
+
+ it('calls the dismiss callback', () => {
+ expect(userCalloutDismissSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when the alert has been dismissed', () => {
+ beforeEach(() => {
+ createComponent({
+ shouldShowCallout: false,
+ });
+ });
+
+ it('does not show the alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/groups/components/overview_tabs_spec.js b/spec/frontend/groups/components/overview_tabs_spec.js
index 352bf25b84f..93e087e10f2 100644
--- a/spec/frontend/groups/components/overview_tabs_spec.js
+++ b/spec/frontend/groups/components/overview_tabs_spec.js
@@ -1,28 +1,46 @@
-import { GlTab } from '@gitlab/ui';
+import { GlSorting, GlSortingItem, GlTab } from '@gitlab/ui';
import { nextTick } from 'vue';
+import { createLocalVue } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import OverviewTabs from '~/groups/components/overview_tabs.vue';
import GroupsApp from '~/groups/components/app.vue';
+import GroupFolderComponent from '~/groups/components/group_folder.vue';
import GroupsStore from '~/groups/store/groups_store';
import GroupsService from '~/groups/service/groups_service';
import { createRouter } from '~/groups/init_overview_tabs';
+import eventHub from '~/groups/event_hub';
import {
ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
ACTIVE_TAB_SHARED,
ACTIVE_TAB_ARCHIVED,
+ OVERVIEW_TABS_SORTING_ITEMS,
} from '~/groups/constants';
import axios from '~/lib/utils/axios_utils';
+const localVue = createLocalVue();
+localVue.component('GroupFolder', GroupFolderComponent);
const router = createRouter();
+const [SORTING_ITEM_NAME, , SORTING_ITEM_UPDATED] = OVERVIEW_TABS_SORTING_ITEMS;
describe('OverviewTabs', () => {
let wrapper;
+ let axiosMock;
- const endpoints = {
- subgroups_and_projects: '/groups/foobar/-/children.json',
- shared: '/groups/foobar/-/shared_projects.json',
- archived: '/groups/foobar/-/children.json?archived=only',
+ const defaultProvide = {
+ endpoints: {
+ subgroups_and_projects: '/groups/foobar/-/children.json',
+ shared: '/groups/foobar/-/shared_projects.json',
+ archived: '/groups/foobar/-/children.json?archived=only',
+ },
+ newSubgroupPath: '/groups/new',
+ newProjectPath: 'projects/new',
+ newSubgroupIllustration: '',
+ newProjectIllustration: '',
+ emptySubgroupIllustration: '',
+ canCreateSubgroups: false,
+ canCreateProjects: false,
+ initialSort: 'name_asc',
};
const routerMock = {
@@ -31,12 +49,15 @@ describe('OverviewTabs', () => {
const createComponent = async ({
route = { name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS, params: { group: 'foo/bar/baz' } },
+ provide = {},
} = {}) => {
wrapper = mountExtended(OverviewTabs, {
router,
provide: {
- endpoints,
+ ...defaultProvide,
+ ...provide,
},
+ localVue,
mocks: { $route: route, $router: routerMock },
});
@@ -47,13 +68,13 @@ describe('OverviewTabs', () => {
const findTab = (name) => wrapper.findByRole('tab', { name });
const findSelectedTab = () => wrapper.findByRole('tab', { selected: true });
- afterEach(() => {
- wrapper.destroy();
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
});
- beforeEach(async () => {
- // eslint-disable-next-line no-new
- new AxiosMockAdapter(axios);
+ afterEach(() => {
+ wrapper.destroy();
+ axiosMock.restore();
});
it('renders `Subgroups and projects` tab with `GroupsApp` component', async () => {
@@ -68,7 +89,7 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
store: new GroupsStore({ showSchemaMarkup: true }),
- service: new GroupsService(endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
+ service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
hideProjects: false,
renderEmptyState: true,
});
@@ -89,7 +110,7 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_SHARED,
store: new GroupsStore(),
- service: new GroupsService(endpoints[ACTIVE_TAB_SHARED]),
+ service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SHARED]),
hideProjects: false,
renderEmptyState: false,
});
@@ -112,7 +133,7 @@ describe('OverviewTabs', () => {
expect(tabPanel.findComponent(GroupsApp).props()).toMatchObject({
action: ACTIVE_TAB_ARCHIVED,
store: new GroupsStore(),
- service: new GroupsService(endpoints[ACTIVE_TAB_ARCHIVED]),
+ service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_ARCHIVED]),
hideProjects: false,
renderEmptyState: false,
});
@@ -120,6 +141,14 @@ describe('OverviewTabs', () => {
expect(tabPanel.vm.$attrs.lazy).toBe(false);
});
+ it('sets `lazy` prop to `false` for initially active tab and `true` for all other tabs', async () => {
+ await createComponent({ route: { name: ACTIVE_TAB_SHARED, params: { group: 'foo/bar' } } });
+
+ expect(findTabPanels().at(0).vm.$attrs.lazy).toBe(true);
+ expect(findTabPanels().at(1).vm.$attrs.lazy).toBe(false);
+ expect(findTabPanels().at(2).vm.$attrs.lazy).toBe(true);
+ });
+
describe.each([
[
{ name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS, params: { group: 'foo/bar/baz' } },
@@ -184,4 +213,109 @@ describe('OverviewTabs', () => {
expect(routerMock.push).toHaveBeenCalledWith(expectedRoute);
});
});
+
+ describe('searching and sorting', () => {
+ const setup = async () => {
+ jest.spyOn(eventHub, '$emit');
+ await createComponent();
+
+ // Click through tabs so they are all loaded
+ await findTab(OverviewTabs.i18n[ACTIVE_TAB_SHARED]).trigger('click');
+ await findTab(OverviewTabs.i18n[ACTIVE_TAB_ARCHIVED]).trigger('click');
+ await findTab(OverviewTabs.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]).trigger('click');
+ };
+
+ const sharedAssertions = ({ search, sort }) => {
+ it('sets `lazy` prop to `true` for all of the non-active tabs so they are reloaded after sort or search is applied', () => {
+ expect(findTabPanels().at(0).vm.$attrs.lazy).toBe(false);
+ expect(findTabPanels().at(1).vm.$attrs.lazy).toBe(true);
+ expect(findTabPanels().at(2).vm.$attrs.lazy).toBe(true);
+ });
+
+ it('emits `fetchFilteredAndSortedGroups` event from `eventHub`', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ `${ACTIVE_TAB_SUBGROUPS_AND_PROJECTS}fetchFilteredAndSortedGroups`,
+ {
+ filterGroupsBy: search,
+ sortBy: sort,
+ },
+ );
+ });
+ };
+
+ describe('when search is typed in', () => {
+ const search = 'Foo bar';
+
+ beforeEach(async () => {
+ await setup();
+ await wrapper.findByPlaceholderText(OverviewTabs.i18n.searchPlaceholder).setValue(search);
+ });
+
+ it('updates query string with `filter` key', () => {
+ expect(routerMock.push).toHaveBeenCalledWith({ query: { filter: search } });
+ });
+
+ sharedAssertions({ search, sort: defaultProvide.initialSort });
+ });
+
+ describe('when sort is changed', () => {
+ beforeEach(async () => {
+ await setup();
+ wrapper.findAllComponents(GlSortingItem).at(2).vm.$emit('click');
+ await nextTick();
+ });
+
+ it('updates query string with `sort` key', () => {
+ expect(routerMock.push).toHaveBeenCalledWith({
+ query: { sort: SORTING_ITEM_UPDATED.asc },
+ });
+ });
+
+ sharedAssertions({ search: '', sort: SORTING_ITEM_UPDATED.asc });
+ });
+
+ describe('when sort direction is changed', () => {
+ beforeEach(async () => {
+ await setup();
+ await wrapper
+ .findByRole('button', { name: 'Sorting Direction: Ascending' })
+ .trigger('click');
+ });
+
+ it('updates query string with `sort` key', () => {
+ expect(routerMock.push).toHaveBeenCalledWith({
+ query: { sort: SORTING_ITEM_NAME.desc },
+ });
+ });
+
+ sharedAssertions({ search: '', sort: SORTING_ITEM_NAME.desc });
+ });
+
+ describe('when `filter` and `sort` query strings are set', () => {
+ beforeEach(async () => {
+ await createComponent({
+ route: {
+ name: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
+ params: { group: 'foo/bar/baz' },
+ query: { filter: 'Foo bar', sort: SORTING_ITEM_UPDATED.desc },
+ },
+ });
+ });
+
+ it('sets value of search input', () => {
+ expect(
+ wrapper.findByPlaceholderText(OverviewTabs.i18n.searchPlaceholder).element.value,
+ ).toBe('Foo bar');
+ });
+
+ it('sets sort dropdown', () => {
+ expect(wrapper.findComponent(GlSorting).props()).toMatchObject({
+ text: SORTING_ITEM_UPDATED.label,
+ isAscending: false,
+ });
+
+ expect(wrapper.findAllComponents(GlSortingItem).at(2).vm.$attrs.active).toBe(true);
+ });
+ });
+ });
});
diff --git a/spec/frontend/groups/components/transfer_group_form_spec.js b/spec/frontend/groups/components/transfer_group_form_spec.js
index 8cfe8ce8e18..7cbe6e5bbab 100644
--- a/spec/frontend/groups/components/transfer_group_form_spec.js
+++ b/spec/frontend/groups/components/transfer_group_form_spec.js
@@ -2,7 +2,7 @@ import { GlAlert, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Component from '~/groups/components/transfer_group_form.vue';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
-import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select_deprecated.vue';
describe('Transfer group form', () => {
let wrapper;
diff --git a/spec/frontend/groups/store/groups_store_spec.js b/spec/frontend/groups/store/groups_store_spec.js
index 8ac5d7099f1..ce1791d0062 100644
--- a/spec/frontend/groups/store/groups_store_spec.js
+++ b/spec/frontend/groups/store/groups_store_spec.js
@@ -16,13 +16,13 @@ describe('ProjectsStore', () => {
store = new GroupsStore();
expect(Object.keys(store.state).length).toBe(2);
- expect(Array.isArray(store.state.groups)).toBeTruthy();
+ expect(Array.isArray(store.state.groups)).toBe(true);
expect(Object.keys(store.state.pageInfo).length).toBe(0);
- expect(store.hideProjects).toBeFalsy();
+ expect(store.hideProjects).toBe(false);
store = new GroupsStore({ hideProjects: true });
- expect(store.hideProjects).toBeTruthy();
+ expect(store.hideProjects).toBe(true);
});
});
@@ -65,8 +65,8 @@ describe('ProjectsStore', () => {
expect(store.formatGroupItem).toHaveBeenCalledWith(expect.any(Object));
expect(mockParentGroupItem.children.length).toBe(1);
expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName')).toBeGreaterThan(-1);
- expect(mockParentGroupItem.isOpen).toBeTruthy();
- expect(mockParentGroupItem.isChildrenLoading).toBeFalsy();
+ expect(mockParentGroupItem.isOpen).toBe(true);
+ expect(mockParentGroupItem.isChildrenLoading).toBe(false);
});
});
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
index 6a138f9a247..b0bfe2b45f0 100644
--- a/spec/frontend/header_search/components/app_spec.js
+++ b/spec/frontend/header_search/components/app_spec.js
@@ -2,6 +2,7 @@ import { GlSearchBoxByType, GlToken, GlIcon } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { mockTracking } from 'helpers/tracking_helper';
import { s__, sprintf } from '~/locale';
import HeaderSearchApp from '~/header_search/components/app.vue';
import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
@@ -360,22 +361,43 @@ describe('HeaderSearchApp', () => {
describe('Header Search Input', () => {
describe('when dropdown is closed', () => {
- it('onFocus opens dropdown', async () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ it('onFocus opens dropdown and triggers snowplow event', async () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('focus');
await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'focus_input', {
+ label: 'global_search',
+ property: 'top_navigation',
+ });
});
- it('onClick opens dropdown', async () => {
+ it('onClick opens dropdown and triggers snowplow event', async () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('click');
await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'focus_input', {
+ label: 'global_search',
+ property: 'top_navigation',
+ });
+ });
+
+ it('onClick followed by onFocus only triggers a single snowplow event', async () => {
+ findHeaderSearchInput().vm.$emit('click');
+ findHeaderSearchInput().vm.$emit('focus');
+
+ expect(trackingSpy).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
index c9425f6c9cd..dc103fec5d0 100644
--- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
@@ -1,7 +1,7 @@
import Vue, { nextTick } from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import { projectData, branches } from 'jest/ide/mock_data';
-import commitActions from '~/ide/components/commit_sidebar/actions.vue';
+import CommitActions from '~/ide/components/commit_sidebar/actions.vue';
import { createStore } from '~/ide/stores';
import {
COMMIT_TO_NEW_BRANCH,
@@ -18,32 +18,27 @@ const BRANCH_REGULAR_NO_ACCESS = 'regular/no-access';
describe('IDE commit sidebar actions', () => {
let store;
- let vm;
+ let wrapper;
const createComponent = ({ hasMR = false, currentBranchId = 'main', emptyRepo = false } = {}) => {
- const Component = Vue.extend(commitActions);
-
- vm = createComponentWithStore(Component, store);
-
- vm.$store.state.currentBranchId = currentBranchId;
- vm.$store.state.currentProjectId = 'abcproject';
+ store.state.currentBranchId = currentBranchId;
+ store.state.currentProjectId = 'abcproject';
const proj = { ...projectData };
proj.branches[currentBranchId] = branches.find((branch) => branch.name === currentBranchId);
proj.empty_repo = emptyRepo;
- Vue.set(vm.$store.state.projects, 'abcproject', proj);
+ Vue.set(store.state.projects, 'abcproject', proj);
if (hasMR) {
- vm.$store.state.currentMergeRequestId = '1';
- vm.$store.state.projects[store.state.currentProjectId].mergeRequests[
+ store.state.currentMergeRequestId = '1';
+ store.state.projects[store.state.currentProjectId].mergeRequests[
store.state.currentMergeRequestId
] = { foo: 'bar' };
}
- vm.$mount();
-
- return vm;
+ wrapper = mount(CommitActions, { store });
+ return wrapper;
};
beforeEach(() => {
@@ -52,17 +47,16 @@ describe('IDE commit sidebar actions', () => {
});
afterEach(() => {
- vm.$destroy();
- vm = null;
+ wrapper.destroy();
});
- const findText = () => vm.$el.textContent;
- const findRadios = () => Array.from(vm.$el.querySelectorAll('input[type="radio"]'));
+ const findText = () => wrapper.text();
+ const findRadios = () => wrapper.findAll('input[type="radio"]');
it('renders 2 groups', () => {
createComponent();
- expect(findRadios().length).toBe(2);
+ expect(findRadios()).toHaveLength(2);
});
it('renders current branch text', () => {
@@ -79,41 +73,38 @@ describe('IDE commit sidebar actions', () => {
expect(findText()).not.toContain('Create a new branch and merge request');
});
- describe('currentBranchText', () => {
- it('escapes current branch', () => {
- const injectedSrc = '<img src="x" />';
- createComponent({ currentBranchId: injectedSrc });
+ it('escapes current branch name', () => {
+ const injectedSrc = '<img src="x" />';
+ const escapedSrc = '&lt;img src=&quot;x&quot; /&gt';
+ createComponent({ currentBranchId: injectedSrc });
- expect(vm.currentBranchText).not.toContain(injectedSrc);
- });
+ expect(wrapper.text()).not.toContain(injectedSrc);
+ expect(wrapper.text).not.toContain(escapedSrc);
});
describe('updateSelectedCommitAction', () => {
it('does not return anything if currentBranch does not exist', () => {
createComponent({ currentBranchId: null });
- expect(vm.$store.dispatch).not.toHaveBeenCalled();
+ expect(store.dispatch).not.toHaveBeenCalled();
});
it('is not called on mount if there is already a selected commitAction', () => {
store.state.commitAction = '1';
createComponent({ currentBranchId: null });
- expect(vm.$store.dispatch).not.toHaveBeenCalled();
+ expect(store.dispatch).not.toHaveBeenCalled();
});
it('calls again after staged changes', async () => {
createComponent({ currentBranchId: null });
- vm.$store.state.currentBranchId = 'main';
- vm.$store.state.changedFiles.push({});
- vm.$store.state.stagedFiles.push({});
+ store.state.currentBranchId = 'main';
+ store.state.changedFiles.push({});
+ store.state.stagedFiles.push({});
await nextTick();
- expect(vm.$store.dispatch).toHaveBeenCalledWith(
- ACTION_UPDATE_COMMIT_ACTION,
- expect.anything(),
- );
+ expect(store.dispatch).toHaveBeenCalledWith(ACTION_UPDATE_COMMIT_ACTION, expect.anything());
});
it.each`
@@ -133,9 +124,7 @@ describe('IDE commit sidebar actions', () => {
({ input, expectedOption }) => {
createComponent(input);
- expect(vm.$store.dispatch.mock.calls).toEqual([
- [ACTION_UPDATE_COMMIT_ACTION, expectedOption],
- ]);
+ expect(store.dispatch.mock.calls).toEqual([[ACTION_UPDATE_COMMIT_ACTION, expectedOption]]);
},
);
});
diff --git a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
index dea920ecb5e..c9571d39acb 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
@@ -1,133 +1,136 @@
+import { mount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import listItem from '~/ide/components/commit_sidebar/list_item.vue';
+import ListItem from '~/ide/components/commit_sidebar/list_item.vue';
import { createRouter } from '~/ide/ide_router';
import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
describe('Multi-file editor commit sidebar list item', () => {
- let vm;
- let f;
+ let wrapper;
+ let testFile;
let findPathEl;
let store;
let router;
beforeEach(() => {
store = createStore();
- router = createRouter(store);
+ jest.spyOn(store, 'dispatch');
- const Component = Vue.extend(listItem);
+ router = createRouter(store);
- f = file('test-file');
+ testFile = file('test-file');
- store.state.entries[f.path] = f;
+ store.state.entries[testFile.path] = testFile;
- vm = createComponentWithStore(Component, store, {
- file: f,
- activeFileKey: `staged-${f.key}`,
- }).$mount();
+ wrapper = mount(ListItem, {
+ store,
+ propsData: {
+ file: testFile,
+ activeFileKey: `staged-${testFile.key}`,
+ },
+ });
- findPathEl = vm.$el.querySelector('.multi-file-commit-list-path');
+ findPathEl = wrapper.find('.multi-file-commit-list-path');
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- const findPathText = () => trimText(findPathEl.textContent);
+ const findPathText = () => trimText(findPathEl.text());
it('renders file path', () => {
- expect(findPathText()).toContain(f.path);
+ expect(findPathText()).toContain(testFile.path);
});
it('correctly renders renamed entries', async () => {
- Vue.set(vm.file, 'prevName', 'Old name');
-
+ Vue.set(testFile, 'prevName', 'Old name');
await nextTick();
- expect(findPathText()).toEqual(`Old name → ${f.name}`);
+
+ expect(findPathText()).toEqual(`Old name → ${testFile.name}`);
});
it('correctly renders entry, the name of which did not change after rename (as within a folder)', async () => {
- Vue.set(vm.file, 'prevName', f.name);
-
+ Vue.set(testFile, 'prevName', testFile.name);
await nextTick();
- expect(findPathText()).toEqual(f.name);
+
+ expect(findPathText()).toEqual(testFile.name);
});
it('opens a closed file in the editor when clicking the file path', async () => {
- jest.spyOn(vm, 'openPendingTab');
jest.spyOn(router, 'push').mockImplementation(() => {});
- findPathEl.click();
-
- await nextTick();
+ await findPathEl.trigger('click');
- expect(vm.openPendingTab).toHaveBeenCalled();
+ expect(store.dispatch).toHaveBeenCalledWith('openPendingTab', expect.anything());
expect(router.push).toHaveBeenCalled();
});
it('calls updateViewer with diff when clicking file', async () => {
- jest.spyOn(vm, 'openFileInEditor');
- jest.spyOn(vm, 'updateViewer');
jest.spyOn(router, 'push').mockImplementation(() => {});
- findPathEl.click();
-
+ await findPathEl.trigger('click');
await waitForPromises();
- expect(vm.updateViewer).toHaveBeenCalledWith('diff');
+ expect(store.dispatch).toHaveBeenCalledWith('updateViewer', 'diff');
});
- describe('computed', () => {
- describe('iconName', () => {
- it('returns modified when not a tempFile', () => {
- expect(vm.iconName).toBe('file-modified');
- });
+ describe('icon name', () => {
+ const getIconName = () => wrapper.findComponent(GlIcon).props('name');
+
+ it('is modified when not a tempFile', () => {
+ expect(getIconName()).toBe('file-modified');
+ });
- it('returns addition when not a tempFile', () => {
- f.tempFile = true;
+ it('is addition when is a tempFile', async () => {
+ testFile.tempFile = true;
+ await nextTick();
- expect(vm.iconName).toBe('file-addition');
- });
+ expect(getIconName()).toBe('file-addition');
+ });
- it('returns deletion', () => {
- f.deleted = true;
+ it('is deletion when is deleted', async () => {
+ testFile.deleted = true;
+ await nextTick();
- expect(vm.iconName).toBe('file-deletion');
- });
+ expect(getIconName()).toBe('file-deletion');
});
+ });
- describe('iconClass', () => {
- it('returns modified when not a tempFile', () => {
- expect(vm.iconClass).toContain('ide-file-modified');
- });
+ describe('icon class', () => {
+ const getIconClass = () => wrapper.findComponent(GlIcon).classes();
- it('returns addition when not a tempFile', () => {
- f.tempFile = true;
+ it('is modified when not a tempFile', () => {
+ expect(getIconClass()).toContain('ide-file-modified');
+ });
- expect(vm.iconClass).toContain('ide-file-addition');
- });
+ it('is addition when is a tempFile', async () => {
+ testFile.tempFile = true;
+ await nextTick();
- it('returns deletion', () => {
- f.deleted = true;
+ expect(getIconClass()).toContain('ide-file-addition');
+ });
- expect(vm.iconClass).toContain('ide-file-deletion');
- });
+ it('returns deletion when is deleted', async () => {
+ testFile.deleted = true;
+ await nextTick();
+
+ expect(getIconClass()).toContain('ide-file-deletion');
});
});
describe('is active', () => {
it('does not add active class when dont keys match', () => {
- expect(vm.$el.querySelector('.is-active')).toBe(null);
+ expect(wrapper.find('.is-active').exists()).toBe(false);
});
it('adds active class when keys match', async () => {
- vm.keyPrefix = 'staged';
+ await wrapper.setProps({ keyPrefix: 'staged' });
- await nextTick();
- expect(vm.$el.querySelector('.is-active')).not.toBe(null);
+ expect(wrapper.find('.is-active').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
index ace266aec5e..c2ef29c1059 100644
--- a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js
@@ -1,135 +1,121 @@
-import Vue, { nextTick } from 'vue';
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import createComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
describe('IDE commit message field', () => {
- const Component = Vue.extend(CommitMessageField);
- let vm;
+ let wrapper;
beforeEach(() => {
- setHTMLFixture('<div id="app"></div>');
-
- vm = createComponent(
- Component,
- {
+ wrapper = mount(CommitMessageField, {
+ propsData: {
text: '',
placeholder: 'testing',
},
- '#app',
- );
+ attachTo: document.body,
+ });
});
afterEach(() => {
- vm.$destroy();
-
- resetHTMLFixture();
+ wrapper.destroy();
});
+ const findMessage = () => wrapper.find('textarea');
+ const findHighlights = () => wrapper.findAll('.highlights span');
+ const findMarks = () => wrapper.findAll('mark');
+
it('adds is-focused class on focus', async () => {
- vm.$el.querySelector('textarea').focus();
+ await findMessage().trigger('focus');
- await nextTick();
- expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
+ expect(wrapper.find('.is-focused').exists()).toBe(true);
});
it('removed is-focused class on blur', async () => {
- vm.$el.querySelector('textarea').focus();
+ await findMessage().trigger('focus');
- await nextTick();
- expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
+ expect(wrapper.find('.is-focused').exists()).toBe(true);
- vm.$el.querySelector('textarea').blur();
+ await findMessage().trigger('blur');
- await nextTick();
- expect(vm.$el.querySelector('.is-focused')).toBeNull();
+ expect(wrapper.find('.is-focused').exists()).toBe(false);
});
- it('emits input event on input', () => {
- jest.spyOn(vm, '$emit').mockImplementation();
-
- const textarea = vm.$el.querySelector('textarea');
- textarea.value = 'testing';
-
- textarea.dispatchEvent(new Event('input'));
+ it('emits input event on input', async () => {
+ await findMessage().setValue('testing');
- expect(vm.$emit).toHaveBeenCalledWith('input', 'testing');
+ expect(wrapper.emitted('input')[0]).toStrictEqual(['testing']);
});
describe('highlights', () => {
describe('subject line', () => {
it('does not highlight less than 50 characters', async () => {
- vm.text = 'text less than 50 chars';
+ await wrapper.setProps({ text: 'text less than 50 chars' });
- await nextTick();
- expect(vm.$el.querySelector('.highlights span').textContent).toContain(
- 'text less than 50 chars',
- );
+ expect(findHighlights()).toHaveLength(1);
+ expect(findHighlights().at(0).text()).toContain('text less than 50 chars');
- expect(vm.$el.querySelector('mark').style.display).toBe('none');
+ expect(findMarks()).toHaveLength(1);
+ expect(findMarks().at(0).isVisible()).toBe(false);
});
it('highlights characters over 50 length', async () => {
- vm.text =
- 'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
+ await wrapper.setProps({
+ text:
+ 'text less than 50 chars that should not highlighted. text more than 50 should be highlighted',
+ });
- await nextTick();
- expect(vm.$el.querySelector('.highlights span').textContent).toContain(
+ expect(findHighlights()).toHaveLength(1);
+ expect(findHighlights().at(0).text()).toContain(
'text less than 50 chars that should not highlighte',
);
- expect(vm.$el.querySelector('mark').style.display).not.toBe('none');
- expect(vm.$el.querySelector('mark').textContent).toBe(
- 'd. text more than 50 should be highlighted',
- );
+ expect(findMarks()).toHaveLength(1);
+ expect(findMarks().at(0).isVisible()).toBe(true);
+ expect(findMarks().at(0).text()).toBe('d. text more than 50 should be highlighted');
});
});
describe('body text', () => {
it('does not highlight body text less tan 72 characters', async () => {
- vm.text = 'subject line\nbody content';
+ await wrapper.setProps({ text: 'subject line\nbody content' });
- await nextTick();
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none');
+ expect(findHighlights()).toHaveLength(2);
+ expect(findMarks().at(1).isVisible()).toBe(false);
});
it('highlights body text more than 72 characters', async () => {
- vm.text =
- 'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
-
- await nextTick();
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none');
- expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
+ await wrapper.setProps({
+ text:
+ 'subject line\nbody content that will be highlighted when it is more than 72 characters in length',
+ });
+
+ expect(findHighlights()).toHaveLength(2);
+ expect(findMarks().at(1).isVisible()).toBe(true);
+ expect(findMarks().at(1).text()).toBe('in length');
});
it('highlights body text & subject line', async () => {
- vm.text =
- 'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
+ await wrapper.setProps({
+ text:
+ 'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length',
+ });
- await nextTick();
- expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
- expect(vm.$el.querySelectorAll('mark').length).toBe(2);
+ expect(findHighlights()).toHaveLength(2);
+ expect(findMarks()).toHaveLength(2);
- expect(vm.$el.querySelectorAll('mark')[0].textContent).toContain('d');
- expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
+ expect(findMarks().at(0).text()).toContain('d');
+ expect(findMarks().at(1).text()).toBe('in length');
});
});
});
describe('scrolling textarea', () => {
it('updates transform of highlights', async () => {
- vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content';
+ await wrapper.setProps({ text: 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content' });
+ findMessage().element.scrollTo(0, 50);
await nextTick();
- vm.$el.querySelector('textarea').scrollTo(0, 50);
- vm.handleScroll();
-
- await nextTick();
- expect(vm.scrollTop).toBe(50);
- expect(vm.$el.querySelector('.highlights').style.transform).toBe('translate3d(0, -50px, 0)');
+ expect(wrapper.find('.highlights').element.style.transform).toBe('translate3d(0, -50px, 0)');
});
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
index ee6ed694285..a3fa03a4aa5 100644
--- a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
@@ -1,123 +1,116 @@
-import Vue, { nextTick } from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { GlFormRadioGroup } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import RadioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
import { createStore } from '~/ide/stores';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
describe('IDE commit sidebar radio group', () => {
- let vm;
+ let wrapper;
let store;
- beforeEach(async () => {
+ const createComponent = (config = {}) => {
store = createStore();
- const Component = Vue.extend(RadioGroup);
-
store.state.commit.commitAction = '2';
+ store.state.commit.newBranchName = 'test-123';
- vm = createComponentWithStore(Component, store, {
- value: '1',
- label: 'test',
- checked: true,
+ wrapper = mount(RadioGroup, {
+ store,
+ propsData: config.props,
+ slots: config.slots,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
});
-
- vm.$mount();
-
- await nextTick();
- });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- it('uses label if present', () => {
- expect(vm.$el.textContent).toContain('test');
- });
+ describe('without input', () => {
+ const props = {
+ value: '1',
+ label: 'test',
+ checked: true,
+ };
- it('uses slot if label is not present', async () => {
- vm.$destroy();
+ it('uses label if present', () => {
+ createComponent({ props });
- vm = new Vue({
- components: {
- RadioGroup,
- },
- store,
- render: (createElement) =>
- createElement('radio-group', { props: { value: '1' } }, 'Testing slot'),
+ expect(wrapper.text()).toContain('test');
});
- vm.$mount();
+ it('uses slot if label is not present', () => {
+ createComponent({ props: { value: '1', checked: true }, slots: { default: 'Testing slot' } });
- await nextTick();
- expect(vm.$el.textContent).toContain('Testing slot');
- });
+ expect(wrapper.text()).toContain('Testing slot');
+ });
- it('updates store when changing radio button', async () => {
- vm.$el.querySelector('input').dispatchEvent(new Event('change'));
+ it('updates store when changing radio button', async () => {
+ createComponent({ props });
- await nextTick();
- expect(store.state.commit.commitAction).toBe('1');
+ await wrapper.find('input').trigger('change');
+
+ expect(store.state.commit.commitAction).toBe('1');
+ });
});
describe('with input', () => {
- beforeEach(async () => {
- vm.$destroy();
-
- const Component = Vue.extend(RadioGroup);
-
- store.state.commit.commitAction = '1';
- store.state.commit.newBranchName = 'test-123';
-
- vm = createComponentWithStore(Component, store, {
- value: '1',
- label: 'test',
- checked: true,
- showInput: true,
- });
-
- vm.$mount();
-
- await nextTick();
- });
+ const props = {
+ value: '2',
+ label: 'test',
+ checked: true,
+ showInput: true,
+ };
it('renders input box when commitAction matches value', () => {
- expect(vm.$el.querySelector('.form-control')).not.toBeNull();
+ createComponent({ props: { ...props, value: '2' } });
+
+ expect(wrapper.find('.form-control').exists()).toBe(true);
});
- it('hides input when commitAction doesnt match value', async () => {
- store.state.commit.commitAction = '2';
+ it('hides input when commitAction doesnt match value', () => {
+ createComponent({ props: { ...props, value: '1' } });
- await nextTick();
- expect(vm.$el.querySelector('.form-control')).toBeNull();
+ expect(wrapper.find('.form-control').exists()).toBe(false);
});
it('updates branch name in store on input', async () => {
- const input = vm.$el.querySelector('.form-control');
- input.value = 'testing-123';
- input.dispatchEvent(new Event('input'));
+ createComponent({ props });
+
+ await wrapper.find('.form-control').setValue('testing-123');
- await nextTick();
expect(store.state.commit.newBranchName).toBe('testing-123');
});
it('renders newBranchName if present', () => {
- const input = vm.$el.querySelector('.form-control');
+ createComponent({ props });
- expect(input.value).toBe('test-123');
+ const input = wrapper.find('.form-control');
+
+ expect(input.element.value).toBe('test-123');
});
});
describe('tooltipTitle', () => {
it('returns title when disabled', () => {
- vm.title = 'test title';
- vm.disabled = true;
+ createComponent({
+ props: { value: '1', label: 'test', disabled: true, title: 'test title' },
+ });
- expect(vm.tooltipTitle).toBe('test title');
+ const tooltip = getBinding(wrapper.findComponent(GlFormRadioGroup).element, 'gl-tooltip');
+ expect(tooltip.value).toBe('test title');
});
it('returns blank when not disabled', () => {
- vm.title = 'test title';
+ createComponent({
+ props: { value: '1', label: 'test', title: 'test title' },
+ });
+
+ const tooltip = getBinding(wrapper.findComponent(GlFormRadioGroup).element, 'gl-tooltip');
- expect(vm.tooltipTitle).not.toBe('test title');
+ expect(tooltip.value).toBe('');
});
});
});
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 5a7a1fe7db0..281c549a1b4 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -1,146 +1,146 @@
-import Vue, { nextTick } from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { mount } from '@vue/test-utils';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
-import { createStore } from '~/ide/stores';
+import { createStoreOptions } from '~/ide/stores';
import { file } from '../helpers';
describe('IDE extra file row component', () => {
- let Component;
- let vm;
+ let wrapper;
+ let store;
let unstagedFilesCount = 0;
let stagedFilesCount = 0;
let changesCount = 0;
- beforeAll(() => {
- Component = Vue.extend(FileRowExtra);
- });
+ const createComponent = (fileProps) => {
+ const storeConfig = createStoreOptions();
- beforeEach(() => {
- vm = createComponentWithStore(Component, createStore(), {
- file: {
- ...file('test'),
+ store = new Vuex.Store({
+ ...storeConfig,
+ getters: {
+ getUnstagedFilesCountForPath: () => () => unstagedFilesCount,
+ getStagedFilesCountForPath: () => () => stagedFilesCount,
+ getChangesInFolder: () => () => changesCount,
},
- dropdownOpen: false,
});
- jest.spyOn(vm, 'getUnstagedFilesCountForPath', 'get').mockReturnValue(() => unstagedFilesCount);
- jest.spyOn(vm, 'getStagedFilesCountForPath', 'get').mockReturnValue(() => stagedFilesCount);
- jest.spyOn(vm, 'getChangesInFolder', 'get').mockReturnValue(() => changesCount);
-
- vm.$mount();
- });
+ wrapper = mount(FileRowExtra, {
+ store,
+ propsData: {
+ file: {
+ ...file('test'),
+ type: 'tree',
+ ...fileProps,
+ },
+ dropdownOpen: false,
+ },
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
stagedFilesCount = 0;
unstagedFilesCount = 0;
changesCount = 0;
});
- describe('folderChangesTooltip', () => {
- it('returns undefined when changes count is 0', () => {
- changesCount = 0;
-
- expect(vm.folderChangesTooltip).toBe(undefined);
- });
-
+ describe('folder changes tooltip', () => {
[
{ input: 1, output: '1 changed file' },
{ input: 2, output: '2 changed files' },
].forEach(({ input, output }) => {
- it('returns changed files count if changes count is not 0', () => {
+ it('shows changed files count if changes count is not 0', () => {
changesCount = input;
+ createComponent();
- expect(vm.folderChangesTooltip).toBe(output);
+ expect(wrapper.find('.ide-file-modified').attributes('title')).toBe(output);
});
});
});
describe('show tree changes count', () => {
+ const findTreeChangesCount = () => wrapper.find('.ide-tree-changes');
+
it('does not show for blobs', () => {
- vm.file.type = 'blob';
+ createComponent({ type: 'blob' });
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
+ expect(findTreeChangesCount().exists()).toBe(false);
});
it('does not show when changes count is 0', () => {
- vm.file.type = 'tree';
+ createComponent({ type: 'tree' });
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
+ expect(findTreeChangesCount().exists()).toBe(false);
});
- it('does not show when tree is open', async () => {
- vm.file.type = 'tree';
- vm.file.opened = true;
+ it('does not show when tree is open', () => {
changesCount = 1;
+ createComponent({ type: 'tree', opened: true });
- await nextTick();
- expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
+ expect(findTreeChangesCount().exists()).toBe(false);
});
- it('shows for trees with changes', async () => {
- vm.file.type = 'tree';
- vm.file.opened = false;
+ it('shows for trees with changes', () => {
changesCount = 1;
+ createComponent({ type: 'tree', opened: false });
- await nextTick();
- expect(vm.$el.querySelector('.ide-tree-changes')).not.toBe(null);
+ expect(findTreeChangesCount().exists()).toBe(true);
});
});
describe('changes file icon', () => {
+ const findChangedFileIcon = () => wrapper.find('.file-changed-icon');
+
it('hides when file is not changed', () => {
- expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
+ createComponent();
+
+ expect(findChangedFileIcon().exists()).toBe(false);
});
- it('shows when file is changed', async () => {
- vm.file.changed = true;
+ it('shows when file is changed', () => {
+ createComponent({ type: 'blob', changed: true });
- await nextTick();
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
+ expect(findChangedFileIcon().exists()).toBe(true);
});
- it('shows when file is staged', async () => {
- vm.file.staged = true;
+ it('shows when file is staged', () => {
+ createComponent({ type: 'blob', staged: true });
- await nextTick();
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
+ expect(findChangedFileIcon().exists()).toBe(true);
});
- it('shows when file is a tempFile', async () => {
- vm.file.tempFile = true;
+ it('shows when file is a tempFile', () => {
+ createComponent({ type: 'blob', tempFile: true });
- await nextTick();
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
+ expect(findChangedFileIcon().exists()).toBe(true);
});
- it('shows when file is renamed', async () => {
- vm.file.prevPath = 'original-file';
+ it('shows when file is renamed', () => {
+ createComponent({ type: 'blob', prevPath: 'original-file' });
- await nextTick();
- expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
+ expect(findChangedFileIcon().exists()).toBe(true);
});
- it('hides when file is renamed', async () => {
- vm.file.prevPath = 'original-file';
- vm.file.type = 'tree';
+ it('hides when tree is renamed', () => {
+ createComponent({ type: 'tree', prevPath: 'original-path' });
- await nextTick();
- expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
+ expect(findChangedFileIcon().exists()).toBe(false);
});
});
describe('merge request icon', () => {
+ const findMergeRequestIcon = () => wrapper.find('[data-testid="git-merge-icon"]');
+
it('hides when not a merge request change', () => {
- expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
+ createComponent();
+
+ expect(findMergeRequestIcon().exists()).toBe(false);
});
- it('shows when a merge request change', async () => {
- vm.file.mrChange = true;
+ it('shows when a merge request change', () => {
+ createComponent({ mrChange: true });
- await nextTick();
- expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
+ expect(findMergeRequestIcon().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/ide/components/file_templates/bar_spec.js b/spec/frontend/ide/components/file_templates/bar_spec.js
index aaf9c17ccbf..60f37260393 100644
--- a/spec/frontend/ide/components/file_templates/bar_spec.js
+++ b/spec/frontend/ide/components/file_templates/bar_spec.js
@@ -1,19 +1,16 @@
-import Vue, { nextTick } from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import Bar from '~/ide/components/file_templates/bar.vue';
import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
describe('IDE file templates bar component', () => {
- let Component;
- let vm;
-
- beforeAll(() => {
- Component = Vue.extend(Bar);
- });
+ let wrapper;
+ let store;
beforeEach(() => {
- const store = createStore();
+ store = createStore();
+ jest.spyOn(store, 'dispatch').mockImplementation();
store.state.openFiles.push({
...file('file'),
@@ -21,24 +18,22 @@ describe('IDE file templates bar component', () => {
active: true,
});
- vm = mountComponentWithStore(Component, { store });
+ wrapper = mount(Bar, { store });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('template type dropdown', () => {
it('renders dropdown component', () => {
- expect(vm.$el.querySelector('.dropdown').textContent).toContain('Choose a type');
+ expect(wrapper.find('.dropdown').text()).toContain('Choose a type');
});
- it('calls setSelectedTemplateType when clicking item', () => {
- jest.spyOn(vm, 'setSelectedTemplateType').mockImplementation();
-
- vm.$el.querySelector('.dropdown-menu button').click();
+ it('calls setSelectedTemplateType when clicking item', async () => {
+ await wrapper.find('.dropdown-menu button').trigger('click');
- expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
+ expect(store.dispatch).toHaveBeenCalledWith('fileTemplates/setSelectedTemplateType', {
name: '.gitlab-ci.yml',
key: 'gitlab_ci_ymls',
});
@@ -46,60 +41,52 @@ describe('IDE file templates bar component', () => {
});
describe('template dropdown', () => {
- beforeEach(async () => {
- vm.$store.state.fileTemplates.templates = [
+ beforeEach(() => {
+ store.state.fileTemplates.templates = [
{
name: 'test',
},
];
- vm.$store.state.fileTemplates.selectedTemplateType = {
+ store.state.fileTemplates.selectedTemplateType = {
name: '.gitlab-ci.yml',
key: 'gitlab_ci_ymls',
};
-
- await nextTick();
});
it('renders dropdown component', () => {
- expect(vm.$el.querySelectorAll('.dropdown')[1].textContent).toContain('Choose a template');
+ expect(wrapper.findAll('.dropdown').at(1).text()).toContain('Choose a template');
});
- it('calls fetchTemplate on dropdown open', () => {
- jest.spyOn(vm, 'fetchTemplate').mockImplementation();
-
- vm.$el.querySelectorAll('.dropdown-menu')[1].querySelector('button').click();
+ it('calls fetchTemplate on dropdown open', async () => {
+ await wrapper.findAll('.dropdown-menu').at(1).find('button').trigger('click');
- expect(vm.fetchTemplate).toHaveBeenCalledWith({
+ expect(store.dispatch).toHaveBeenCalledWith('fileTemplates/fetchTemplate', {
name: 'test',
});
});
});
+ const findUndoButton = () => wrapper.find('.btn-default-secondary');
it('shows undo button if updateSuccess is true', async () => {
- vm.$store.state.fileTemplates.updateSuccess = true;
-
+ store.state.fileTemplates.updateSuccess = true;
await nextTick();
- expect(vm.$el.querySelector('.btn-default').style.display).not.toBe('none');
- });
- it('calls undoFileTemplate when clicking undo button', () => {
- jest.spyOn(vm, 'undoFileTemplate').mockImplementation();
+ expect(findUndoButton().isVisible()).toBe(true);
+ });
- vm.$el.querySelector('.btn-default-secondary').click();
+ it('calls undoFileTemplate when clicking undo button', async () => {
+ await findUndoButton().trigger('click');
- expect(vm.undoFileTemplate).toHaveBeenCalled();
+ expect(store.dispatch).toHaveBeenCalledWith('fileTemplates/undoFileTemplate', undefined);
});
it('calls setSelectedTemplateType if activeFile name matches a template', async () => {
const fileName = '.gitlab-ci.yml';
-
- jest.spyOn(vm, 'setSelectedTemplateType').mockImplementation(() => {});
- vm.$store.state.openFiles[0].name = fileName;
-
- vm.setInitialType();
+ store.state.openFiles = [{ ...file(fileName), opened: true, active: true }];
await nextTick();
- expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
+
+ expect(store.dispatch).toHaveBeenCalledWith('fileTemplates/setSelectedTemplateType', {
name: fileName,
key: 'gitlab_ci_ymls',
});
diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
deleted file mode 100644
index 45444166a50..00000000000
--- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
+++ /dev/null
@@ -1,60 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`IDE pipeline stage renders stage details & icon 1`] = `
-<div
- class="ide-stage card gl-mt-3"
->
- <div
- class="card-header"
- >
- <ci-icon-stub
- cssclasses=""
- size="24"
- status="[object Object]"
- />
-
- <strong
- class="gl-ml-3 text-truncate"
- data-container="body"
- >
-
- build
-
- </strong>
-
- <div
- class="gl-mr-3 gl-ml-2"
- >
- <gl-badge-stub
- size="md"
- variant="muted"
- >
- 4
- </gl-badge-stub>
- </div>
-
- <gl-icon-stub
- class="ide-stage-collapse-icon"
- name="chevron-lg-down"
- size="16"
- />
- </div>
-
- <div
- class="card-body p-0"
- >
- <item-stub
- job="[object Object]"
- />
- <item-stub
- job="[object Object]"
- />
- <item-stub
- job="[object Object]"
- />
- <item-stub
- job="[object Object]"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index 128ccff6568..629c4424314 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -1,44 +1,43 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import Description from '~/ide/components/jobs/detail/description.vue';
import { jobs } from '../../../mock_data';
describe('IDE job description', () => {
- const Component = Vue.extend(Description);
- let vm;
+ let wrapper;
beforeEach(() => {
- vm = mountComponent(Component, {
- job: jobs[0],
+ wrapper = mount(Description, {
+ propsData: {
+ job: jobs[0],
+ },
});
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders job details', () => {
- expect(vm.$el.textContent).toContain('#1');
- expect(vm.$el.textContent).toContain('test');
+ expect(wrapper.text()).toContain('#1');
+ expect(wrapper.text()).toContain('test');
});
it('renders CI icon', () => {
- expect(
- vm.$el.querySelector('.ci-status-icon [data-testid="status_success_borderless-icon"]'),
- ).not.toBe(null);
+ expect(wrapper.find('.ci-status-icon').findComponent(GlIcon).exists()).toBe(true);
});
it('renders a borderless CI icon', () => {
- expect(
- vm.$el.querySelector('.borderless [data-testid="status_success_borderless-icon"]'),
- ).not.toBe(null);
+ expect(wrapper.find('.borderless').findComponent(GlIcon).exists()).toBe(true);
});
it('renders bridge job details without the job link', () => {
- vm = mountComponent(Component, {
- job: { ...jobs[0], path: undefined },
+ wrapper = mount(Description, {
+ propsData: {
+ job: { ...jobs[0], path: undefined },
+ },
});
- expect(vm.$el.querySelector('[data-testid="description-detail-link"]')).toBe(null);
+ expect(wrapper.find('[data-testid="description-detail-link"]').exists()).toBe(false);
});
});
diff --git a/spec/frontend/ide/components/jobs/detail_spec.js b/spec/frontend/ide/components/jobs/detail_spec.js
index 9122471d421..bf2be3aa595 100644
--- a/spec/frontend/ide/components/jobs/detail_spec.js
+++ b/spec/frontend/ide/components/jobs/detail_spec.js
@@ -1,15 +1,17 @@
-import Vue, { nextTick } from 'vue';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+
import { TEST_HOST } from 'helpers/test_constants';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import JobDetail from '~/ide/components/jobs/detail.vue';
import { createStore } from '~/ide/stores';
import { jobs } from '../../mock_data';
describe('IDE jobs detail view', () => {
- let vm;
+ let wrapper;
+ let store;
const createComponent = () => {
- const store = createStore();
+ store = createStore();
store.state.pipelines.detailJob = {
...jobs[0],
@@ -18,163 +20,129 @@ describe('IDE jobs detail view', () => {
rawPath: `${TEST_HOST}/raw`,
};
- return createComponentWithStore(Vue.extend(JobDetail), store);
+ jest.spyOn(store, 'dispatch');
+ store.dispatch.mockResolvedValue();
+
+ wrapper = mount(JobDetail, { store });
};
- beforeEach(() => {
- vm = createComponent();
+ const findBuildJobLog = () => wrapper.find('pre');
+ const findScrollToBottomButton = () => wrapper.find('button[aria-label="Scroll to bottom"]');
+ const findScrollToTopButton = () => wrapper.find('button[aria-label="Scroll to top"]');
- jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue();
+ beforeEach(() => {
+ createComponent();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('mounted', () => {
- beforeEach(() => {
- vm = vm.$mount();
- });
+ const findJobOutput = () => wrapper.find('.bash');
+ const findBuildLoaderAnimation = () => wrapper.find('.build-loader-animation');
it('calls fetchJobLogs', () => {
- expect(vm.fetchJobLogs).toHaveBeenCalled();
+ expect(store.dispatch).toHaveBeenCalledWith('pipelines/fetchJobLogs', undefined);
});
it('scrolls to bottom', () => {
- expect(vm.$refs.buildJobLog.scrollTo).toHaveBeenCalled();
+ expect(findBuildJobLog().element.scrollTo).toHaveBeenCalled();
});
it('renders job output', () => {
- expect(vm.$el.querySelector('.bash').textContent).toContain('testing');
+ expect(findJobOutput().text()).toContain('testing');
});
it('renders empty message output', async () => {
- vm.$store.state.pipelines.detailJob.output = '';
-
+ store.state.pipelines.detailJob.output = '';
await nextTick();
- expect(vm.$el.querySelector('.bash').textContent).toContain('No messages were logged');
+
+ expect(findJobOutput().text()).toContain('No messages were logged');
});
it('renders loading icon', () => {
- expect(vm.$el.querySelector('.build-loader-animation')).not.toBe(null);
- expect(vm.$el.querySelector('.build-loader-animation').style.display).toBe('');
+ expect(findBuildLoaderAnimation().exists()).toBe(true);
+ expect(findBuildLoaderAnimation().isVisible()).toBe(true);
});
it('hides output when loading', () => {
- expect(vm.$el.querySelector('.bash')).not.toBe(null);
- expect(vm.$el.querySelector('.bash').style.display).toBe('none');
+ expect(findJobOutput().exists()).toBe(true);
+ expect(findJobOutput().isVisible()).toBe(false);
});
it('hide loading icon when isLoading is false', async () => {
- vm.$store.state.pipelines.detailJob.isLoading = false;
-
+ store.state.pipelines.detailJob.isLoading = false;
await nextTick();
- expect(vm.$el.querySelector('.build-loader-animation').style.display).toBe('none');
- });
- it('resets detailJob when clicking header button', () => {
- jest.spyOn(vm, 'setDetailJob').mockImplementation();
+ expect(findBuildLoaderAnimation().isVisible()).toBe(false);
+ });
- vm.$el.querySelector('.btn').click();
+ it('resets detailJob when clicking header button', async () => {
+ await wrapper.find('.btn').trigger('click');
- expect(vm.setDetailJob).toHaveBeenCalledWith(null);
+ expect(store.dispatch).toHaveBeenCalledWith('pipelines/setDetailJob', null);
});
it('renders raw path link', () => {
- expect(vm.$el.querySelector('.controllers-buttons').getAttribute('href')).toBe(
- `${TEST_HOST}/raw`,
- );
+ expect(wrapper.find('.controllers-buttons').attributes('href')).toBe(`${TEST_HOST}/raw`);
});
});
describe('scroll buttons', () => {
beforeEach(() => {
- vm = createComponent();
- jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue();
- });
-
- afterEach(() => {
- vm.$destroy();
+ createComponent();
});
it.each`
- fnName | btnName | scrollPos
- ${'scrollDown'} | ${'down'} | ${0}
- ${'scrollUp'} | ${'up'} | ${1}
- `('triggers $fnName when clicking $btnName button', async ({ fnName, scrollPos }) => {
- jest.spyOn(vm, fnName).mockImplementation();
-
- vm = vm.$mount();
+ fnName | btnName | scrollPos | targetScrollPos
+ ${'scroll down'} | ${'down'} | ${0} | ${200}
+ ${'scroll up'} | ${'up'} | ${200} | ${0}
+ `('triggers $fnName when clicking $btnName button', async ({ scrollPos, targetScrollPos }) => {
+ jest.spyOn(findBuildJobLog().element, 'offsetHeight', 'get').mockReturnValue(0);
+ jest.spyOn(findBuildJobLog().element, 'scrollHeight', 'get').mockReturnValue(200);
+ jest.spyOn(findBuildJobLog().element, 'scrollTop', 'get').mockReturnValue(scrollPos);
+ findBuildJobLog().element.scrollTo.mockReset();
- vm.scrollPos = scrollPos;
-
- await nextTick();
- vm.$el.querySelector('.btn-scroll:not([disabled])').click();
- expect(vm[fnName]).toHaveBeenCalled();
- });
- });
-
- describe('scrollDown', () => {
- beforeEach(() => {
- vm = vm.$mount();
-
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTo').mockImplementation();
- });
-
- it('scrolls build trace to bottom', () => {
- jest.spyOn(vm.$refs.buildJobLog, 'scrollHeight', 'get').mockReturnValue(1000);
-
- vm.scrollDown();
-
- expect(vm.$refs.buildJobLog.scrollTo).toHaveBeenCalledWith(0, 1000);
- });
- });
-
- describe('scrollUp', () => {
- beforeEach(() => {
- vm = vm.$mount();
-
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTo').mockImplementation();
- });
+ await findBuildJobLog().trigger('scroll'); // trigger button updates
- it('scrolls build trace to top', () => {
- vm.scrollUp();
+ await wrapper.find('.controllers button:not(:disabled)').trigger('click');
- expect(vm.$refs.buildJobLog.scrollTo).toHaveBeenCalledWith(0, 0);
+ expect(findBuildJobLog().element.scrollTo).toHaveBeenCalledWith(0, targetScrollPos);
});
});
- describe('scrollBuildLog', () => {
+ describe('scrolling build log', () => {
beforeEach(() => {
- vm = vm.$mount();
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTo').mockImplementation();
- jest.spyOn(vm.$refs.buildJobLog, 'offsetHeight', 'get').mockReturnValue(100);
- jest.spyOn(vm.$refs.buildJobLog, 'scrollHeight', 'get').mockReturnValue(200);
+ jest.spyOn(findBuildJobLog().element, 'offsetHeight', 'get').mockReturnValue(100);
+ jest.spyOn(findBuildJobLog().element, 'scrollHeight', 'get').mockReturnValue(200);
});
- it('sets scrollPos to bottom when at the bottom', () => {
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTop', 'get').mockReturnValue(100);
+ it('keeps scroll at bottom when already at the bottom', async () => {
+ jest.spyOn(findBuildJobLog().element, 'scrollTop', 'get').mockReturnValue(100);
- vm.scrollBuildLog();
+ await findBuildJobLog().trigger('scroll');
- expect(vm.scrollPos).toBe(1);
+ expect(findScrollToBottomButton().attributes('disabled')).toBe('disabled');
+ expect(findScrollToTopButton().attributes('disabled')).not.toBe('disabled');
});
- it('sets scrollPos to top when at the top', () => {
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTop', 'get').mockReturnValue(0);
- vm.scrollPos = 1;
+ it('keeps scroll at top when already at top', async () => {
+ jest.spyOn(findBuildJobLog().element, 'scrollTop', 'get').mockReturnValue(0);
- vm.scrollBuildLog();
+ await findBuildJobLog().trigger('scroll');
- expect(vm.scrollPos).toBe(0);
+ expect(findScrollToBottomButton().attributes('disabled')).not.toBe('disabled');
+ expect(findScrollToTopButton().attributes('disabled')).toBe('disabled');
});
- it('resets scrollPos when not at top or bottom', () => {
- jest.spyOn(vm.$refs.buildJobLog, 'scrollTop', 'get').mockReturnValue(10);
+ it('resets scroll when not at top or bottom', async () => {
+ jest.spyOn(findBuildJobLog().element, 'scrollTop', 'get').mockReturnValue(10);
- vm.scrollBuildLog();
+ await findBuildJobLog().trigger('scroll');
- expect(vm.scrollPos).toBe('');
+ expect(findScrollToBottomButton().attributes('disabled')).not.toBe('disabled');
+ expect(findScrollToTopButton().attributes('disabled')).not.toBe('disabled');
});
});
});
diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js
index c76760a5522..32e27333e42 100644
--- a/spec/frontend/ide/components/jobs/item_spec.js
+++ b/spec/frontend/ide/components/jobs/item_spec.js
@@ -1,36 +1,38 @@
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+
import JobItem from '~/ide/components/jobs/item.vue';
import { jobs } from '../../mock_data';
describe('IDE jobs item', () => {
- const Component = Vue.extend(JobItem);
const job = jobs[0];
- let vm;
+ let wrapper;
beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- });
+ wrapper = mount(JobItem, { propsData: { job } });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders job details', () => {
- expect(vm.$el.textContent).toContain(job.name);
- expect(vm.$el.textContent).toContain(`#${job.id}`);
+ expect(wrapper.text()).toContain(job.name);
+ expect(wrapper.text()).toContain(`#${job.id}`);
});
it('renders CI icon', () => {
- expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
+ expect(wrapper.find('[data-testid="status_success_borderless-icon"]').exists()).toBe(true);
});
it('does not render view logs button if not started', async () => {
- vm.job.started = false;
+ await wrapper.setProps({
+ job: {
+ ...jobs[0],
+ started: false,
+ },
+ });
- await nextTick();
- expect(vm.$el.querySelector('.btn')).toBe(null);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(false);
});
});
diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js
index 1d5e5743a4d..52fbff2f497 100644
--- a/spec/frontend/ide/components/jobs/stage_spec.js
+++ b/spec/frontend/ide/components/jobs/stage_spec.js
@@ -18,8 +18,9 @@ describe('IDE pipeline stage', () => {
},
};
- const findHeader = () => wrapper.findComponent({ ref: 'cardHeader' });
- const findJobList = () => wrapper.findComponent({ ref: 'jobList' });
+ const findHeader = () => wrapper.find('[data-testid="card-header"]');
+ const findJobList = () => wrapper.find('[data-testid="job-list"]');
+ const findStageTitle = () => wrapper.find('[data-testid="stage-title"]');
const createComponent = (props) => {
wrapper = shallowMount(Stage, {
@@ -65,9 +66,9 @@ describe('IDE pipeline stage', () => {
expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
- it('renders stage details & icon', () => {
+ it('renders stage title', () => {
createComponent();
- expect(wrapper.element).toMatchSnapshot();
+ expect(findStageTitle().isVisible()).toBe(true);
});
describe('when collapsed', () => {
diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js
index 298d7b810e1..a9cfdfd20c1 100644
--- a/spec/frontend/ide/components/new_dropdown/button_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/button_spec.js
@@ -1,59 +1,60 @@
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import Button from '~/ide/components/new_dropdown/button.vue';
describe('IDE new entry dropdown button component', () => {
- let Component;
- let vm;
-
- beforeAll(() => {
- Component = Vue.extend(Button);
- });
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- label: 'Testing',
- icon: 'doc-new',
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(Button, {
+ propsData: {
+ label: 'Testing',
+ icon: 'doc-new',
+ ...props,
+ },
});
-
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders button with label', () => {
- expect(vm.$el.textContent).toContain('Testing');
+ createComponent();
+
+ expect(wrapper.text()).toContain('Testing');
});
it('renders icon', () => {
- expect(vm.$el.querySelector('[data-testid="doc-new-icon"]')).not.toBe(null);
+ createComponent();
+
+ expect(wrapper.find('[data-testid="doc-new-icon"]').exists()).toBe(true);
});
- it('emits click event', () => {
- vm.$el.click();
+ it('emits click event', async () => {
+ createComponent();
- expect(vm.$emit).toHaveBeenCalledWith('click');
+ await wrapper.trigger('click');
+
+ expect(wrapper.emitted('click')).toHaveLength(1);
});
- it('hides label if showLabel is false', async () => {
- vm.showLabel = false;
+ it('hides label if showLabel is false', () => {
+ createComponent({ showLabel: false });
- await nextTick();
- expect(vm.$el.textContent).not.toContain('Testing');
+ expect(wrapper.text()).not.toContain('Testing');
});
- describe('tooltipTitle', () => {
+ describe('tooltip title', () => {
it('returns empty string when showLabel is true', () => {
- expect(vm.tooltipTitle).toBe('');
+ createComponent({ showLabel: true });
+
+ expect(wrapper.attributes('title')).toBe('');
});
- it('returns label', async () => {
- vm.showLabel = false;
+ it('returns label', () => {
+ createComponent({ showLabel: false });
- await nextTick();
- expect(vm.tooltipTitle).toBe('Testing');
+ expect(wrapper.attributes('title')).toBe('Testing');
});
});
});
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index 68cc08d2ebc..c6f9fd0c4ea 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -1,6 +1,6 @@
import { GlButton, GlModal } from '@gitlab/ui';
import { nextTick } from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Modal from '~/ide/components/new_dropdown/modal.vue';
import { createStore } from '~/ide/stores';
import { stubComponent } from 'helpers/stub_component';
@@ -341,7 +341,7 @@ describe('new file modal component', () => {
});
it('does not trigger flash', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -360,7 +360,7 @@ describe('new file modal component', () => {
});
it('does not trigger flash', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
});
@@ -380,7 +380,7 @@ describe('new file modal component', () => {
});
it('creates flash', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'The name "src" is already taken in this directory.',
fadeTransition: false,
addBodyClass: true,
@@ -405,7 +405,7 @@ describe('new file modal component', () => {
});
it('does not create flash', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
it('dispatches event', () => {
diff --git a/spec/frontend/ide/components/new_dropdown/upload_spec.js b/spec/frontend/ide/components/new_dropdown/upload_spec.js
index 3eafe9e7ccb..fc643589d51 100644
--- a/spec/frontend/ide/components/new_dropdown/upload_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/upload_spec.js
@@ -1,39 +1,34 @@
-import Vue from 'vue';
-import createComponent from 'helpers/vue_mount_component_helper';
-import upload from '~/ide/components/new_dropdown/upload.vue';
+import { mount } from '@vue/test-utils';
+import Upload from '~/ide/components/new_dropdown/upload.vue';
describe('new dropdown upload', () => {
- let vm;
+ let wrapper;
beforeEach(() => {
- const Component = Vue.extend(upload);
-
- vm = createComponent(Component, {
- path: '',
+ wrapper = mount(Upload, {
+ propsData: {
+ path: '',
+ },
});
-
- vm.entryName = 'testing';
-
- jest.spyOn(vm, '$emit');
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('openFile', () => {
it('calls for each file', () => {
const files = ['test', 'test2', 'test3'];
- jest.spyOn(vm, 'readFile').mockImplementation(() => {});
- jest.spyOn(vm.$refs.fileUpload, 'files', 'get').mockReturnValue(files);
+ jest.spyOn(wrapper.vm, 'readFile').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.$refs.fileUpload, 'files', 'get').mockReturnValue(files);
- vm.openFile();
+ wrapper.vm.openFile();
- expect(vm.readFile.mock.calls.length).toBe(3);
+ expect(wrapper.vm.readFile.mock.calls.length).toBe(3);
files.forEach((file, i) => {
- expect(vm.readFile.mock.calls[i]).toEqual([file]);
+ expect(wrapper.vm.readFile.mock.calls[i]).toEqual([file]);
});
});
});
@@ -48,7 +43,7 @@ describe('new dropdown upload', () => {
type: 'images/png',
};
- vm.readFile(file);
+ wrapper.vm.readFile(file);
expect(FileReader.prototype.readAsDataURL).toHaveBeenCalledWith(file);
});
@@ -71,35 +66,39 @@ describe('new dropdown upload', () => {
it('calls readAsText and creates file in plain text (without encoding) if the file content is plain text', async () => {
const waitForCreate = new Promise((resolve) => {
- vm.$on('create', resolve);
+ wrapper.vm.$on('create', resolve);
});
- vm.createFile(textTarget, textFile);
+ wrapper.vm.createFile(textTarget, textFile);
expect(FileReader.prototype.readAsText).toHaveBeenCalledWith(textFile);
await waitForCreate;
- expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: textFile.name,
- type: 'blob',
- content: 'plain text',
- rawPath: '',
- mimeType: 'test/mime-text',
- });
+ expect(wrapper.emitted('create')[0]).toStrictEqual([
+ {
+ name: textFile.name,
+ type: 'blob',
+ content: 'plain text',
+ rawPath: '',
+ mimeType: 'test/mime-text',
+ },
+ ]);
});
it('creates a blob URL for the content if binary', () => {
- vm.createFile(binaryTarget, binaryFile);
+ wrapper.vm.createFile(binaryTarget, binaryFile);
expect(FileReader.prototype.readAsText).not.toHaveBeenCalled();
- expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: binaryFile.name,
- type: 'blob',
- content: 'ðððð',
- rawPath: 'blob:https://gitlab.com/048c7ac1-98de-4a37-ab1b-0206d0ea7e1b',
- mimeType: 'test/mime-binary',
- });
+ expect(wrapper.emitted('create')[0]).toStrictEqual([
+ {
+ name: binaryFile.name,
+ type: 'blob',
+ content: 'ðððð',
+ rawPath: 'blob:https://gitlab.com/048c7ac1-98de-4a37-ab1b-0206d0ea7e1b',
+ mimeType: 'test/mime-binary',
+ },
+ ]);
});
});
});
diff --git a/spec/frontend/ide/components/shared/tokened_input_spec.js b/spec/frontend/ide/components/shared/tokened_input_spec.js
index 2efef9918b1..b70c9659e46 100644
--- a/spec/frontend/ide/components/shared/tokened_input_spec.js
+++ b/spec/frontend/ide/components/shared/tokened_input_spec.js
@@ -1,5 +1,4 @@
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import TokenedInput from '~/ide/components/shared/tokened_input.vue';
const TEST_PLACEHOLDER = 'Searching in test';
@@ -10,120 +9,106 @@ const TEST_TOKENS = [
];
const TEST_VALUE = 'lorem';
-function getTokenElements(vm) {
- return Array.from(vm.$el.querySelectorAll('.filtered-search-token button'));
-}
-
-function createBackspaceEvent() {
- const e = new Event('keyup');
- e.keyCode = 8;
- e.which = e.keyCode;
- e.altKey = false;
- e.ctrlKey = true;
- e.shiftKey = false;
- e.metaKey = false;
- return e;
+function getTokenElements(wrapper) {
+ return wrapper.findAll('.filtered-search-token button');
}
describe('IDE shared/TokenedInput', () => {
- const Component = Vue.extend(TokenedInput);
- let vm;
-
- beforeEach(() => {
- vm = mountComponent(Component, {
- tokens: TEST_TOKENS,
- placeholder: TEST_PLACEHOLDER,
- value: TEST_VALUE,
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(TokenedInput, {
+ propsData: {
+ tokens: TEST_TOKENS,
+ placeholder: TEST_PLACEHOLDER,
+ value: TEST_VALUE,
+ ...props,
+ },
+ attachTo: document.body,
});
-
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders tokens', () => {
- const renderedTokens = getTokenElements(vm).map((x) => x.textContent.trim());
+ createComponent();
+ const renderedTokens = getTokenElements(wrapper).wrappers.map((w) => w.text());
expect(renderedTokens).toEqual(TEST_TOKENS.map((x) => x.label));
});
it('renders input', () => {
- expect(vm.$refs.input).toBeInstanceOf(HTMLInputElement);
- expect(vm.$refs.input).toHaveValue(TEST_VALUE);
- });
-
- it('renders placeholder, when tokens are empty', async () => {
- vm.tokens = [];
+ createComponent();
- await nextTick();
- expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER);
+ expect(wrapper.find('input').element).toBeInstanceOf(HTMLInputElement);
+ expect(wrapper.find('input').element).toHaveValue(TEST_VALUE);
});
- it('triggers "removeToken" on token click', () => {
- getTokenElements(vm)[0].click();
+ it('renders placeholder, when tokens are empty', () => {
+ createComponent({ tokens: [] });
- expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[0]);
+ expect(wrapper.find('input').attributes('placeholder')).toBe(TEST_PLACEHOLDER);
});
- it('when input triggers backspace event, it calls "onBackspace"', () => {
- jest.spyOn(vm, 'onBackspace').mockImplementation(() => {});
+ it('triggers "removeToken" on token click', async () => {
+ createComponent();
+ await getTokenElements(wrapper).at(0).trigger('click');
- vm.$refs.input.dispatchEvent(createBackspaceEvent());
- vm.$refs.input.dispatchEvent(createBackspaceEvent());
-
- expect(vm.onBackspace).toHaveBeenCalledTimes(2);
+ expect(wrapper.emitted('removeToken')[0]).toStrictEqual([TEST_TOKENS[0]]);
});
- it('triggers "removeToken" on backspaces when value is empty', () => {
- vm.value = '';
-
- vm.onBackspace();
+ it('removes token on backspace when value is empty', async () => {
+ createComponent({ value: '' });
- expect(vm.$emit).not.toHaveBeenCalled();
- expect(vm.backspaceCount).toEqual(1);
+ expect(wrapper.emitted('removeToken')).toBeUndefined();
- vm.onBackspace();
+ await wrapper.find('input').trigger('keyup.delete');
+ await wrapper.find('input').trigger('keyup.delete');
- expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[TEST_TOKENS.length - 1]);
- expect(vm.backspaceCount).toEqual(0);
+ expect(wrapper.emitted('removeToken')[0]).toStrictEqual([TEST_TOKENS[TEST_TOKENS.length - 1]]);
});
- it('does not trigger "removeToken" on backspaces when value is not empty', () => {
- vm.onBackspace();
- vm.onBackspace();
+ it('does not trigger "removeToken" on backspaces when value is not empty', async () => {
+ createComponent({ value: 'SOMETHING' });
+
+ await wrapper.find('input').trigger('keyup.delete');
+ await wrapper.find('input').trigger('keyup.delete');
- expect(vm.backspaceCount).toEqual(0);
- expect(vm.$emit).not.toHaveBeenCalled();
+ expect(wrapper.emitted('removeToken')).toBeUndefined();
});
- it('does not trigger "removeToken" on backspaces when tokens are empty', () => {
- vm.tokens = [];
+ it('does not trigger "removeToken" on backspaces when tokens are empty', async () => {
+ createComponent({ value: '', tokens: [] });
- vm.onBackspace();
- vm.onBackspace();
+ await wrapper.find('input').trigger('keyup.delete');
+ await wrapper.find('input').trigger('keyup.delete');
- expect(vm.backspaceCount).toEqual(0);
- expect(vm.$emit).not.toHaveBeenCalled();
+ expect(wrapper.emitted('removeToken')).toBeUndefined();
});
- it('triggers "focus" on input focus', () => {
- vm.$refs.input.dispatchEvent(new Event('focus'));
+ it('triggers "focus" on input focus', async () => {
+ createComponent();
- expect(vm.$emit).toHaveBeenCalledWith('focus');
+ await wrapper.find('input').trigger('focus');
+
+ expect(wrapper.emitted('focus')).toHaveLength(1);
});
- it('triggers "blur" on input blur', () => {
- vm.$refs.input.dispatchEvent(new Event('blur'));
+ it('triggers "blur" on input blur', async () => {
+ createComponent();
+
+ await wrapper.find('input').trigger('blur');
- expect(vm.$emit).toHaveBeenCalledWith('blur');
+ expect(wrapper.emitted('blur')).toHaveLength(1);
});
- it('triggers "input" with value on input change', () => {
- vm.$refs.input.value = 'something-else';
- vm.$refs.input.dispatchEvent(new Event('input'));
+ it('triggers "input" with value on input change', async () => {
+ createComponent();
+
+ await wrapper.find('input').setValue('something-else');
- expect(vm.$emit).toHaveBeenCalledWith('input', 'something-else');
+ expect(wrapper.emitted('input')[0]).toStrictEqual(['something-else']);
});
});
diff --git a/spec/frontend/ide/components/terminal/terminal_spec.js b/spec/frontend/ide/components/terminal/terminal_spec.js
index 4da3e1910e9..0d22f7f73fe 100644
--- a/spec/frontend/ide/components/terminal/terminal_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_spec.js
@@ -171,7 +171,7 @@ describe('IDE Terminal', () => {
it('creates the terminal', () => {
expect(GLTerminal).toHaveBeenCalledWith(wrapper.vm.$refs.terminal);
- expect(wrapper.vm.glterminal).toBeTruthy();
+ expect(wrapper.vm.glterminal).toBeInstanceOf(GLTerminal);
});
describe('scroll listener', () => {
diff --git a/spec/frontend/ide/init_gitlab_web_ide_spec.js b/spec/frontend/ide/init_gitlab_web_ide_spec.js
index ec8559f1b56..067da25cb52 100644
--- a/spec/frontend/ide/init_gitlab_web_ide_spec.js
+++ b/spec/frontend/ide/init_gitlab_web_ide_spec.js
@@ -6,7 +6,7 @@ jest.mock('@gitlab/web-ide');
const ROOT_ELEMENT_ID = 'ide';
const TEST_NONCE = 'test123nonce';
-const TEST_PROJECT = { path_with_namespace: 'group1/project1' };
+const TEST_PROJECT_PATH = 'group1/project1';
const TEST_BRANCH_NAME = '12345-foo-patch';
const TEST_GITLAB_URL = 'https://test-gitlab/';
const TEST_GITLAB_WEB_IDE_PUBLIC_PATH = 'test/webpack/assets/gitlab-web-ide/public/path';
@@ -18,7 +18,7 @@ describe('ide/init_gitlab_web_ide', () => {
el.id = ROOT_ELEMENT_ID;
// why: We'll test that this class is removed later
el.classList.add('ide-loading');
- el.dataset.project = JSON.stringify(TEST_PROJECT);
+ el.dataset.projectPath = TEST_PROJECT_PATH;
el.dataset.cspNonce = TEST_NONCE;
el.dataset.branchName = TEST_BRANCH_NAME;
@@ -43,7 +43,7 @@ describe('ide/init_gitlab_web_ide', () => {
it('calls start with element', () => {
expect(start).toHaveBeenCalledWith(findRootElement(), {
baseUrl: `${TEST_HOST}/${TEST_GITLAB_WEB_IDE_PUBLIC_PATH}`,
- projectPath: TEST_PROJECT.path_with_namespace,
+ projectPath: TEST_PROJECT_PATH,
ref: TEST_BRANCH_NAME,
gitlabUrl: TEST_GITLAB_URL,
nonce: TEST_NONCE,
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index abc3ba5b0a2..f1b2a7b881a 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -3,7 +3,7 @@ import { range } from 'lodash';
import { stubPerformanceWebAPI } from 'helpers/performance';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '~/ide/constants';
import service from '~/ide/services';
import { createStore } from '~/ide/stores';
@@ -139,8 +139,8 @@ describe('IDE store merge request actions', () => {
branchId: 'bar',
})
.catch(() => {
- expect(createFlash).toHaveBeenCalled();
- expect(createFlash.mock.calls[0][0].message).toBe(
+ expect(createAlert).toHaveBeenCalled();
+ expect(createAlert.mock.calls[0][0].message).toBe(
'Error fetching merge requests for bar',
);
});
@@ -520,7 +520,7 @@ describe('IDE store merge request actions', () => {
store.dispatch.mockRejectedValue();
return openMergeRequest(store, mr).catch(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.any(String),
});
});
diff --git a/spec/frontend/ide/stores/actions/project_spec.js b/spec/frontend/ide/stores/actions/project_spec.js
index cc7d39b4d43..5a5ead4c544 100644
--- a/spec/frontend/ide/stores/actions/project_spec.js
+++ b/spec/frontend/ide/stores/actions/project_spec.js
@@ -2,7 +2,7 @@ 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 { createAlert } from '~/flash';
import service from '~/ide/services';
import { createStore } from '~/ide/stores';
import {
@@ -97,7 +97,7 @@ describe('IDE store project actions', () => {
});
afterEach(() => {
- createFlash.mockRestore();
+ createAlert.mockRestore();
});
it.each`
@@ -122,7 +122,7 @@ describe('IDE store project actions', () => {
if (!responseSuccess) {
expect(logError).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
}
});
});
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index f6d54491d77..fd2c3d18813 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -4,6 +4,7 @@ import testAction from 'helpers/vuex_action_helper';
import eventHub from '~/ide/eventhub';
import { createRouter } from '~/ide/ide_router';
import { createStore } from '~/ide/stores';
+import { createAlert } from '~/flash';
import {
init,
stageAllChanges,
@@ -29,6 +30,7 @@ jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
joinPaths: jest.requireActual('~/lib/utils/url_utility').joinPaths,
}));
+jest.mock('~/flash');
describe('Multi-file store actions', () => {
let store;
@@ -138,7 +140,7 @@ describe('Multi-file store actions', () => {
name: 'testing/test',
type: 'tree',
});
- expect(tree.tree[0].tempFile).toBeTruthy();
+ expect(tree.tree[0].tempFile).toBe(true);
expect(tree.tree[0].name).toBe('test');
expect(tree.tree[0].type).toBe('tree');
});
@@ -158,7 +160,7 @@ describe('Multi-file store actions', () => {
type: 'tree',
});
expect(store.state.entries[tree.path].tempFile).toEqual(false);
- expect(document.querySelector('.flash-alert')).not.toBeNull();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -173,7 +175,7 @@ describe('Multi-file store actions', () => {
});
const f = store.state.entries[name];
- expect(f.tempFile).toBeTruthy();
+ expect(f.tempFile).toBe(true);
expect(f.mimeType).toBe('test/mime');
expect(store.state.trees['abcproject/mybranch'].tree.length).toBe(1);
});
@@ -216,8 +218,10 @@ describe('Multi-file store actions', () => {
name: 'test',
type: 'blob',
});
- expect(document.querySelector('.flash-alert')?.textContent.trim()).toEqual(
- `The name "${f.name}" is already taken in this directory.`,
+ expect(createAlert).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: `The name "${f.name}" is already taken in this directory.`,
+ }),
);
});
});
@@ -930,7 +934,7 @@ describe('Multi-file store actions', () => {
);
expect(dispatch.mock.calls).toHaveLength(0);
- expect(document.querySelector('.flash-alert')).not.toBeNull();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/ide/stores/modules/commit/mutations_spec.js b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
index 50342832d75..d277157e737 100644
--- a/spec/frontend/ide/stores/modules/commit/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
@@ -37,7 +37,7 @@ describe('IDE commit module mutations', () => {
it('updates submitCommitLoading', () => {
mutations.UPDATE_LOADING(state, true);
- expect(state.submitCommitLoading).toBeTruthy();
+ expect(state.submitCommitLoading).toBe(true);
});
});
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
index ecda7f304ba..f48797415df 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import * as actions from '~/ide/stores/modules/terminal/actions/session_controls';
import { STARTING, PENDING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
@@ -89,7 +89,7 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveStartSessionError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: messages.UNEXPECTED_ERROR_STARTING,
});
});
@@ -163,7 +163,7 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveStopSessionError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: messages.UNEXPECTED_ERROR_STOPPING,
});
});
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
index eabc69b23aa..fe2328f25c2 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import * as actions from '~/ide/stores/modules/terminal/actions/session_status';
import { PENDING, RUNNING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
@@ -115,7 +115,7 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveSessionStatusError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: messages.UNEXPECTED_ERROR_STATUS,
});
});
diff --git a/spec/frontend/ide/stores/mutations/tree_spec.js b/spec/frontend/ide/stores/mutations/tree_spec.js
index 6935e57578f..a8c0d7ba2c8 100644
--- a/spec/frontend/ide/stores/mutations/tree_spec.js
+++ b/spec/frontend/ide/stores/mutations/tree_spec.js
@@ -17,11 +17,11 @@ describe('Multi-file store tree mutations', () => {
it('toggles tree open', () => {
mutations.TOGGLE_TREE_OPEN(localState, localTree.path);
- expect(localTree.opened).toBeTruthy();
+ expect(localTree.opened).toBe(true);
mutations.TOGGLE_TREE_OPEN(localState, localTree.path);
- expect(localTree.opened).toBeFalsy();
+ expect(localTree.opened).toBe(false);
});
});
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 4602a0837e0..4117f2648bd 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -30,13 +30,13 @@ describe('Multi-file store mutations', () => {
entry,
});
- expect(entry.loading).toBeTruthy();
+ expect(entry.loading).toBe(true);
mutations.TOGGLE_LOADING(localState, {
entry,
});
- expect(entry.loading).toBeFalsy();
+ expect(entry.loading).toBe(false);
});
it('toggles loading of entry and sets specific value', () => {
@@ -44,14 +44,14 @@ describe('Multi-file store mutations', () => {
entry,
});
- expect(entry.loading).toBeTruthy();
+ expect(entry.loading).toBe(true);
mutations.TOGGLE_LOADING(localState, {
entry,
forceValue: true,
});
- expect(entry.loading).toBeTruthy();
+ expect(entry.loading).toBe(true);
});
});
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index fd9d481251d..4efc0ac6028 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -1,4 +1,5 @@
import { languages } from 'monaco-editor';
+import { setDiagnosticsOptions as yamlDiagnosticsOptions } from 'monaco-yaml';
import {
isTextFile,
registerLanguages,
@@ -203,7 +204,6 @@ describe('WebIDE utils', () => {
};
jest.spyOn(languages.json.jsonDefaults, 'setDiagnosticsOptions');
- jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
});
it('registers the given schemas with monaco for both json and yaml languages', () => {
@@ -212,7 +212,7 @@ describe('WebIDE utils', () => {
expect(languages.json.jsonDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining({ schemas: [schema] }),
);
- expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect(yamlDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining({ schemas: [schema] }),
);
});
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 f97ea046cbe..a0115cb9349 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
@@ -5,13 +5,14 @@ import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import httpStatus from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
import { STATUSES } from '~/import_entities/constants';
import { i18n, ROOT_NAMESPACE } from '~/import_entities/import_groups/constants';
import ImportTable from '~/import_entities/import_groups/components/import_table.vue';
import importGroupsMutation from '~/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import { availableNamespacesFixture, generateFakeEntry } from '../graphql/fixtures';
@@ -246,7 +247,7 @@ describe('import table', () => {
await findImportButtons()[0].trigger('click');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: i18n.ERROR_IMPORT,
}),
@@ -528,6 +529,17 @@ describe('import table', () => {
});
});
+ it('renders pagination bar with storage key', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => new Promise(() => {}),
+ });
+ await waitForPromises();
+
+ expect(wrapper.getComponent(PaginationBar).props('storageKey')).toBe(
+ ImportTable.LOCAL_STORAGE_KEY,
+ );
+ });
+
describe('unavailable features warning', () => {
it('renders alert when there are unavailable features', async () => {
createComponent({
diff --git a/spec/frontend/import_entities/import_groups/services/status_poller_spec.js b/spec/frontend/import_entities/import_groups/services/status_poller_spec.js
index 01f976562c6..13d2a95ca14 100644
--- a/spec/frontend/import_entities/import_groups/services/status_poller_spec.js
+++ b/spec/frontend/import_entities/import_groups/services/status_poller_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { STATUSES } from '~/import_entities/constants';
import { StatusPoller } from '~/import_entities/import_groups/services/status_poller';
import axios from '~/lib/utils/axios_utils';
@@ -83,7 +83,7 @@ describe('Bulk import status poller', () => {
it('when error occurs shows flash with error', () => {
const [[pollConfig]] = Poll.mock.calls;
pollConfig.errorCallback();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('when success response arrives updates relevant group status', () => {
diff --git a/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js b/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js
new file mode 100644
index 00000000000..68716600592
--- /dev/null
+++ b/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js
@@ -0,0 +1,60 @@
+import { mount } from '@vue/test-utils';
+import { GlFormCheckbox } from '@gitlab/ui';
+import AdvancedSettingsPanel from '~/import_entities/import_projects/components/advanced_settings.vue';
+
+describe('Import Advanced Settings', () => {
+ let wrapper;
+ const OPTIONAL_STAGES = [
+ { name: 'stage1', label: 'Stage 1' },
+ { name: 'stage2', label: 'Stage 2', details: 'Extra details' },
+ ];
+
+ const createComponent = () => {
+ wrapper = mount(AdvancedSettingsPanel, {
+ propsData: {
+ stages: OPTIONAL_STAGES,
+ value: {
+ stage1: false,
+ stage2: false,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders GLFormCheckbox for each optional stage', () => {
+ expect(wrapper.findAllComponents(GlFormCheckbox)).toHaveLength(OPTIONAL_STAGES.length);
+ });
+
+ it('renders label for each optional stage', () => {
+ wrapper.findAllComponents(GlFormCheckbox).wrappers.forEach((w, idx) => {
+ expect(w.text()).toContain(OPTIONAL_STAGES[idx].label);
+ });
+ });
+
+ it('renders details for stage with details', () => {
+ expect(wrapper.findAllComponents(GlFormCheckbox).at(1).text()).toContain(
+ OPTIONAL_STAGES[1].details,
+ );
+ });
+
+ it('emits new stages selection state when checkbox is changed', () => {
+ const firstCheckbox = wrapper.findComponent(GlFormCheckbox);
+
+ firstCheckbox.vm.$emit('change', true);
+
+ expect(wrapper.emitted('input')[0]).toStrictEqual([
+ {
+ stage1: true,
+ stage2: false,
+ },
+ ]);
+ });
+});
diff --git a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
index c0ae4294e3d..53807167fe8 100644
--- a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
@@ -5,6 +5,7 @@ import Vuex from 'vuex';
import { STATUSES } from '~/import_entities/constants';
import ImportProjectsTable from '~/import_entities/import_projects/components/import_projects_table.vue';
import ProviderRepoTableRow from '~/import_entities/import_projects/components/provider_repo_table_row.vue';
+import AdvancedSettingsPanel from '~/import_entities/import_projects/components/advanced_settings.vue';
import * as getters from '~/import_entities/import_projects/store/getters';
import state from '~/import_entities/import_projects/store/state';
@@ -45,6 +46,7 @@ describe('ImportProjectsTable', () => {
slots,
filterable,
paginatable,
+ optionalStages,
} = {}) {
Vue.use(Vuex);
@@ -71,6 +73,7 @@ describe('ImportProjectsTable', () => {
providerTitle,
filterable,
paginatable,
+ optionalStages,
},
slots,
stubs: {
@@ -271,4 +274,23 @@ describe('ImportProjectsTable', () => {
expect(wrapper.text().includes(INCOMPATIBLE_TEXT)).toBe(shouldRenderSlot);
},
);
+
+ it('should not render advanced settings panel when no optional steps are passed', () => {
+ createComponent({ state: { providerRepos: [providerRepo] } });
+
+ expect(wrapper.findComponent(AdvancedSettingsPanel).exists()).toBe(false);
+ });
+
+ it('should render advanced settings panel when no optional steps are passed', () => {
+ const OPTIONAL_STAGES = [{ name: 'step1', label: 'Step 1' }];
+ createComponent({ state: { providerRepos: [providerRepo] }, optionalStages: OPTIONAL_STAGES });
+
+ expect(wrapper.findComponent(AdvancedSettingsPanel).exists()).toBe(true);
+ expect(wrapper.findComponent(AdvancedSettingsPanel).props('stages')).toStrictEqual(
+ OPTIONAL_STAGES,
+ );
+ expect(wrapper.findComponent(AdvancedSettingsPanel).props('value')).toStrictEqual({
+ step1: false,
+ });
+ });
});
diff --git a/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js b/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
index 17a07b1e9f9..40934e90b78 100644
--- a/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js
@@ -44,7 +44,7 @@ describe('ProviderRepoTableRow', () => {
wrapper = shallowMount(ProviderRepoTableRow, {
store,
- propsData: { availableNamespaces, userNamespace, ...props },
+ propsData: { availableNamespaces, userNamespace, optionalStages: {}, ...props },
});
}
@@ -92,10 +92,24 @@ describe('ProviderRepoTableRow', () => {
await nextTick();
- const { calls } = fetchImport.mock;
+ expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
+ repoId: repo.importSource.id,
+ optionalStages: {},
+ });
+ });
+
+ it('includes optionalStages to import', async () => {
+ const OPTIONAL_STAGES = { stage1: true, stage2: false };
+ await wrapper.setProps({ optionalStages: OPTIONAL_STAGES });
+
+ findImportButton().vm.$emit('click');
+
+ await nextTick();
- expect(calls).toHaveLength(1);
- expect(calls[0][1]).toBe(repo.importSource.id);
+ expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
+ repoId: repo.importSource.id,
+ optionalStages: OPTIONAL_STAGES,
+ });
});
});
diff --git a/spec/frontend/import_entities/import_projects/store/actions_spec.js b/spec/frontend/import_entities/import_projects/store/actions_spec.js
index 0ebe8525b5a..e154863f339 100644
--- a/spec/frontend/import_entities/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { STATUSES } from '~/import_entities/constants';
import actionsFactory from '~/import_entities/import_projects/store/actions';
import { getImportTarget } from '~/import_entities/import_projects/store/getters';
@@ -155,7 +155,7 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Provider rate limit exceeded. Try again later',
});
});
@@ -198,7 +198,7 @@ describe('import_projects store actions', () => {
return testAction(
fetchImport,
- importRepoId,
+ { repoId: importRepoId, optionalStages: {} },
localState,
[
{
@@ -222,7 +222,7 @@ describe('import_projects store actions', () => {
await testAction(
fetchImport,
- importRepoId,
+ { repoId: importRepoId, optionalStages: {} },
localState,
[
{
@@ -234,7 +234,7 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Importing the project failed',
});
});
@@ -245,7 +245,7 @@ describe('import_projects store actions', () => {
await testAction(
fetchImport,
- importRepoId,
+ { repoId: importRepoId, optionalStages: {} },
localState,
[
{
@@ -257,7 +257,7 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Importing the project failed: ${ERROR_MESSAGE}`,
});
});
@@ -358,7 +358,7 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Requesting namespaces failed',
});
});
@@ -366,14 +366,22 @@ describe('import_projects store actions', () => {
describe('importAll', () => {
it('dispatches multiple fetchImport actions', async () => {
+ const OPTIONAL_STAGES = { stage1: true, stage2: false };
+
await testAction(
importAll,
- null,
+ { optionalStages: OPTIONAL_STAGES },
localState,
[],
[
- { type: 'fetchImport', payload: importRepoId },
- { type: 'fetchImport', payload: otherImportRepoId },
+ {
+ type: 'fetchImport',
+ payload: { repoId: importRepoId, optionalStages: OPTIONAL_STAGES },
+ },
+ {
+ type: 'fetchImport',
+ payload: { repoId: otherImportRepoId, optionalStages: OPTIONAL_STAGES },
+ },
],
);
});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 21e57a2e33c..0a3beee0507 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -18,6 +18,7 @@ import {
integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
+ INTEGRATION_FORM_TYPE_SLACK,
billingPlans,
billingPlanNames,
} from '~/integrations/constants';
@@ -88,6 +89,7 @@ describe('IntegrationForm', () => {
const findConnectionSection = () => findAllSections().at(0);
const findConnectionSectionComponent = () =>
findConnectionSection().findComponent(IntegrationSectionConnection);
+ const findHelpHtml = () => wrapper.findByTestId('help-html');
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@@ -712,5 +714,48 @@ describe('IntegrationForm', () => {
expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
});
});
+
+ describe('Help and sections rendering', () => {
+ const dummyHelp = 'Foo Help';
+
+ it.each`
+ integration | flagIsOn | helpHtml | sections | shouldShowSections | shouldShowHelp
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${''} | ${[]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${''} | ${[]} | ${false} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${true}
+ ${'foo'} | ${false} | ${''} | ${[]} | ${false} | ${false}
+ ${'foo'} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${'foo'} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${true} | ${''} | ${[]} | ${false} | ${false}
+ ${'foo'} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
+ ${'foo'} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
+ ${'foo'} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
+ `(
+ '$sections sections, and "$helpHtml" helpHtml when the FF is "$flagIsOn" for "$integration" integration',
+ ({ integration, flagIsOn, helpHtml, sections, shouldShowSections, shouldShowHelp }) => {
+ createComponent({
+ provide: {
+ helpHtml,
+ glFeatures: { integrationSlackAppNotifications: flagIsOn },
+ },
+ customStateProps: {
+ sections,
+ type: integration,
+ },
+ });
+ expect(findAllSections().length > 0).toEqual(shouldShowSections);
+ expect(findHelpHtml().exists()).toBe(shouldShowHelp);
+ if (shouldShowHelp) {
+ expect(findHelpHtml().html()).toContain(helpHtml);
+ }
+ },
+ );
+ });
});
});
diff --git a/spec/frontend/issuable/bulk_update_sidebar/components/status_dropdown_spec.js b/spec/frontend/issuable/bulk_update_sidebar/components/status_dropdown_spec.js
new file mode 100644
index 00000000000..2f281cb88f9
--- /dev/null
+++ b/spec/frontend/issuable/bulk_update_sidebar/components/status_dropdown_spec.js
@@ -0,0 +1,75 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import StatusDropdown from '~/issuable/bulk_update_sidebar/components/status_dropdown.vue';
+import { statusDropdownOptions } from '~/issuable/bulk_update_sidebar/constants';
+
+describe('SubscriptionsDropdown component', () => {
+ let wrapper;
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findHiddenInput = () => wrapper.find('input');
+
+ function createComponent() {
+ wrapper = shallowMount(StatusDropdown);
+ }
+
+ 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(
+ statusDropdownOptions[selectItemAtIndex].value,
+ );
+ });
+
+ it('updates the dropdown text prop', () => {
+ expect(findDropdown().props('text')).toBe(statusDropdownOptions[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/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 8ecbf41ce56..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/bulk_update_sidebar/components/subscriptions_dropdown_spec.js b/spec/frontend/issuable/bulk_update_sidebar/components/subscriptions_dropdown_spec.js
new file mode 100644
index 00000000000..56ef7a1ed39
--- /dev/null
+++ b/spec/frontend/issuable/bulk_update_sidebar/components/subscriptions_dropdown_spec.js
@@ -0,0 +1,76 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import SubscriptionsDropdown from '~/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue';
+import { subscriptionsDropdownOptions } from '~/issuable/bulk_update_sidebar/constants';
+
+describe('SubscriptionsDropdown component', () => {
+ let wrapper;
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findHiddenInput = () => wrapper.find('input');
+
+ function createComponent() {
+ wrapper = shallowMount(SubscriptionsDropdown);
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with no value selected', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('hidden input value is undefined', () => {
+ expect(findHiddenInput().attributes('value')).toBeUndefined();
+ });
+
+ it('renders default text', () => {
+ expect(findDropdown().props('text')).toBe(SubscriptionsDropdown.i18n.defaultDropdownText);
+ });
+
+ 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', () => {
+ beforeEach(() => {
+ createComponent();
+ findAllDropdownItems().at(0).vm.$emit('click');
+ });
+
+ it('updates value of the hidden input', () => {
+ expect(findHiddenInput().attributes('value')).toBe(subscriptionsDropdownOptions[0].value);
+ });
+
+ it('updates the dropdown text prop', () => {
+ expect(findDropdown().props('text')).toBe(subscriptionsDropdownOptions[0].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 () => {
+ findAllDropdownItems().at(0).vm.$emit('click');
+ await nextTick();
+ const dropdownItems = findAllDropdownItems();
+
+ expect(dropdownItems.at(0).props('isChecked')).toBe(false);
+ expect(dropdownItems.at(1).props('isChecked')).toBe(false);
+ expect(findDropdown().props('text')).toBe(SubscriptionsDropdown.i18n.defaultDropdownText);
+ });
+ });
+ });
+});
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 b518d2fbdec..680dbd68493 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
@@ -7,7 +7,7 @@ import {
issuable1,
issuable2,
} from 'jest/issuable/components/related_issuable_mock_data';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { linkedIssueTypesMap } from '~/related_issues/constants';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
@@ -136,7 +136,7 @@ describe('RelatedIssuesRoot', () => {
await createComponent();
jest.spyOn(wrapper.vm, 'processAllReferences');
jest.spyOn(wrapper.vm.service, 'addRelatedIssues');
- createFlash.mockClear();
+ createAlert.mockClear();
});
it('processes references before submitting', () => {
@@ -207,12 +207,12 @@ describe('RelatedIssuesRoot', () => {
mock.onPost(defaultProps.endpoint).reply(409, { message });
wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', input);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message });
+ expect(createAlert).toHaveBeenCalledWith({ message });
});
});
diff --git a/spec/frontend/issues/show/components/edited_spec.js b/spec/frontend/issues/show/components/edited_spec.js
index 8a240c38b5f..aa6e0a9dceb 100644
--- a/spec/frontend/issues/show/components/edited_spec.js
+++ b/spec/frontend/issues/show/components/edited_spec.js
@@ -1,7 +1,10 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import { getTimeago } from '~/lib/utils/datetime_utility';
import Edited from '~/issues/show/components/edited.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+const timeago = getTimeago();
+
describe('Edited component', () => {
let wrapper;
@@ -9,7 +12,8 @@ describe('Edited component', () => {
const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip);
const formatText = (text) => text.trim().replace(/\s\s+/g, ' ');
- const mountComponent = (propsData) => shallowMount(Edited, { propsData });
+ const mountComponent = (propsData) => mount(Edited, { propsData });
+ const updatedAt = '2017-05-15T12:31:04.428Z';
afterEach(() => {
wrapper.destroy();
@@ -17,12 +21,12 @@ describe('Edited component', () => {
it('renders an edited at+by string', () => {
wrapper = mountComponent({
- updatedAt: '2017-05-15T12:31:04.428Z',
+ updatedAt,
updatedByName: 'Some User',
updatedByPath: '/some_user',
});
- expect(formatText(wrapper.text())).toBe('Edited by Some User');
+ expect(formatText(wrapper.text())).toBe(`Edited ${timeago.format(updatedAt)} by Some User`);
expect(findAuthorLink().attributes('href')).toBe('/some_user');
expect(findTimeAgoTooltip().exists()).toBe(true);
});
@@ -40,10 +44,10 @@ describe('Edited component', () => {
it('if no updatedByName and updatedByPath is provided, no user element will be rendered', () => {
wrapper = mountComponent({
- updatedAt: '2017-05-15T12:31:04.428Z',
+ updatedAt,
});
- expect(formatText(wrapper.text())).toBe('Edited');
+ expect(formatText(wrapper.text())).toBe(`Edited ${timeago.format(updatedAt)}`);
expect(findAuthorLink().exists()).toBe(false);
expect(findTimeAgoTooltip().exists()).toBe(true);
});
diff --git a/spec/frontend/issues/show/components/fields/description_spec.js b/spec/frontend/issues/show/components/fields/description_spec.js
index 61433607a2b..cd4d422583b 100644
--- a/spec/frontend/issues/show/components/fields/description_spec.js
+++ b/spec/frontend/issues/show/components/fields/description_spec.js
@@ -2,13 +2,15 @@ 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';
+import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
describe('Description field component', () => {
let wrapper;
const findTextarea = () => wrapper.findComponent({ ref: 'textarea' });
+ const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
- const mountComponent = (description = 'test') =>
+ const mountComponent = ({ description = 'test', contentEditorOnIssues = false } = {}) =>
shallowMount(DescriptionField, {
attachTo: document.body,
propsData: {
@@ -17,6 +19,11 @@ describe('Description field component', () => {
quickActionsDocsPath: '/',
value: description,
},
+ provide: {
+ glFeatures: {
+ contentEditorOnIssues,
+ },
+ },
stubs: {
MarkdownField,
},
@@ -40,7 +47,7 @@ describe('Description field component', () => {
it('renders markdown field with a markdown description', () => {
const markdown = '**test**';
- wrapper = mountComponent(markdown);
+ wrapper = mountComponent({ description: markdown });
expect(findTextarea().element.value).toBe(markdown);
});
@@ -66,4 +73,52 @@ describe('Description field component', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
+
+ describe('when contentEditorOnIssues feature flag is on', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ contentEditorOnIssues: true });
+ });
+
+ it('uses the MarkdownEditor component to edit markdown', () => {
+ expect(findMarkdownEditor().props()).toEqual(
+ expect.objectContaining({
+ value: 'test',
+ renderMarkdownPath: '/',
+ markdownDocsPath: '/',
+ quickActionsDocsPath: expect.any(String),
+ initOnAutofocus: true,
+ supportsQuickActions: true,
+ enableAutocomplete: true,
+ }),
+ );
+ });
+
+ it('triggers update with meta+enter', () => {
+ findMarkdownEditor().vm.$emit('keydown', {
+ type: 'keydown',
+ keyCode: 13,
+ metaKey: true,
+ });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+
+ it('triggers update with ctrl+enter', () => {
+ findMarkdownEditor().vm.$emit('keydown', {
+ type: 'keydown',
+ keyCode: 13,
+ ctrlKey: true,
+ });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+
+ it('emits input event when MarkdownEditor emits input event', () => {
+ const markdown = 'markdown';
+
+ findMarkdownEditor().vm.$emit('input', markdown);
+
+ expect(wrapper.emitted('input')).toEqual([[markdown]]);
+ });
+ });
});
diff --git a/spec/frontend/issues/show/components/form_spec.js b/spec/frontend/issues/show/components/form_spec.js
index 5c0fe991b22..aedb974cbd0 100644
--- a/spec/frontend/issues/show/components/form_spec.js
+++ b/spec/frontend/issues/show/components/form_spec.js
@@ -1,14 +1,16 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import Autosave from '~/autosave';
+import { getDraft, updateDraft, clearDraft, getLockVersion } from '~/lib/utils/autosave';
import DescriptionTemplate from '~/issues/show/components/fields/description_template.vue';
+import IssuableTitleField from '~/issues/show/components/fields/title.vue';
+import DescriptionField from '~/issues/show/components/fields/description.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');
+jest.mock('~/lib/utils/autosave');
describe('Inline edit form component', () => {
let wrapper;
@@ -38,9 +40,14 @@ describe('Inline edit form component', () => {
...defaultProps,
...props,
},
+ stubs: {
+ DescriptionField,
+ },
});
};
+ const findTitleField = () => wrapper.findComponent(IssuableTitleField);
+ const findDescriptionField = () => wrapper.findComponent(DescriptionField);
const findDescriptionTemplate = () => wrapper.findComponent(DescriptionTemplate);
const findIssuableTypeField = () => wrapper.findComponent(IssueTypeField);
const findLockedWarning = () => wrapper.findComponent(LockedWarning);
@@ -108,16 +115,34 @@ describe('Inline edit form component', () => {
});
describe('autosave', () => {
- let spy;
-
beforeEach(() => {
- spy = jest.spyOn(Autosave.prototype, 'reset');
+ getDraft.mockImplementation((autosaveKey) => {
+ return autosaveKey[autosaveKey.length - 1];
+ });
});
- it('initialized Autosave on mount', () => {
+ it('initializes title and description fields with saved drafts', () => {
createComponent();
- expect(Autosave).toHaveBeenCalledTimes(2);
+ expect(findTitleField().props().value).toBe('title');
+ expect(findDescriptionField().props().value).toBe('description');
+ });
+
+ it('updates local storage drafts when title and description change', () => {
+ const updatedTitle = 'updated title';
+ const updatedDescription = 'updated description';
+
+ createComponent();
+
+ findTitleField().vm.$emit('input', updatedTitle);
+ findDescriptionField().vm.$emit('input', updatedDescription);
+
+ expect(updateDraft).toHaveBeenCalledWith(expect.any(Array), updatedTitle);
+ expect(updateDraft).toHaveBeenCalledWith(
+ expect.any(Array),
+ updatedDescription,
+ defaultProps.formState.lock_version,
+ );
});
it('calls reset on autosave when eventHub emits appropriate events', () => {
@@ -125,33 +150,60 @@ describe('Inline edit form component', () => {
eventHub.$emit('close.form');
- expect(spy).toHaveBeenCalledTimes(2);
+ expect(clearDraft).toHaveBeenCalledTimes(2);
eventHub.$emit('delete.issuable');
- expect(spy).toHaveBeenCalledTimes(4);
+ expect(clearDraft).toHaveBeenCalledTimes(4);
eventHub.$emit('update.issuable');
- expect(spy).toHaveBeenCalledTimes(6);
+ expect(clearDraft).toHaveBeenCalledTimes(6);
});
describe('outdated description', () => {
+ const clientSideMockVersion = 'lock version from local storage';
+ const serverSideMockVersion = 'lock version from server';
+
+ const mockGetLockVersion = () => getLockVersion.mockResolvedValue(clientSideMockVersion);
+
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');
+ mockGetLockVersion();
createComponent({
- formState: { ...defaultProps.formState, lock_version: 'lock version from server' },
+ formState: { ...defaultProps.formState, lock_version: serverSideMockVersion },
});
await nextTick();
expect(findAlert().exists()).toBe(true);
});
+
+ describe('when saved draft is discarded', () => {
+ beforeEach(async () => {
+ mockGetLockVersion();
+
+ createComponent({
+ formState: { ...defaultProps.formState, lock_version: serverSideMockVersion },
+ });
+
+ await nextTick();
+
+ findAlert().vm.$emit('secondaryAction');
+ });
+
+ it('hides the warning alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('clears the description draft', () => {
+ expect(clearDraft).toHaveBeenCalledWith(expect.any(Array));
+ });
+ });
});
});
});
diff --git a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
index d92aeabba0f..458c1c3f858 100644
--- a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
+++ b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
@@ -5,7 +5,6 @@ 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 TimelineTab from '~/issues/show/components/incidents/timeline_events_tab.vue';
import INVALID_URL from '~/lib/utils/invalid_url';
import Tracking from '~/tracking';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
@@ -38,7 +37,6 @@ describe('Incident Tabs component', () => {
projectId: '',
issuableId: '',
uploadMetricsFeatureAvailable: true,
- glFeatures: { incidentTimeline: true },
},
data() {
return { alert: mockAlert, ...data };
@@ -67,7 +65,6 @@ describe('Incident Tabs component', () => {
const findAlertDetailsComponent = () => wrapper.findComponent(AlertDetailsTable);
const findDescriptionComponent = () => wrapper.findComponent(DescriptionComponent);
const findHighlightBarComponent = () => wrapper.findComponent(HighlightBar);
- const findTimelineTab = () => wrapper.findComponent(TimelineTab);
describe('empty state', () => {
beforeEach(() => {
@@ -128,20 +125,4 @@ describe('Incident Tabs component', () => {
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
});
-
- describe('incident timeline tab', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders the timeline tab when feature flag is enabled', () => {
- expect(findTimelineTab().exists()).toBe(true);
- });
-
- it('does not render timeline tab when feature flag is disabled', () => {
- mountComponent({}, { provide: { glFeatures: { incidentTimeline: false } } });
-
- expect(findTimelineTab().exists()).toBe(false);
- });
- });
});
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
index 7f086a276f7..2e7449974e5 100644
--- a/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
+++ b/spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
@@ -22,12 +22,15 @@ describe('Timeline events form', () => {
useFakeDate(fakeDate);
let wrapper;
- const mountComponent = ({ mountMethod = shallowMountExtended }) => {
+ const mountComponent = ({ mountMethod = shallowMountExtended } = {}) => {
wrapper = mountMethod(TimelineEventsForm, {
propsData: {
showSaveAndAdd: true,
isEventProcessed: false,
},
+ stubs: {
+ GlButton: true,
+ },
});
};
@@ -48,17 +51,18 @@ describe('Timeline events form', () => {
findHourInput().setValue(5);
findMinuteInput().setValue(45);
};
+ const findTextarea = () => wrapper.findByTestId('input-note');
const submitForm = async () => {
- findSubmitButton().trigger('click');
+ findSubmitButton().vm.$emit('click');
await waitForPromises();
};
const submitFormAndAddAnother = async () => {
- findSubmitAndAddButton().trigger('click');
+ findSubmitAndAddButton().vm.$emit('click');
await waitForPromises();
};
const cancelForm = async () => {
- findCancelButton().trigger('click');
+ findCancelButton().vm.$emit('click');
await waitForPromises();
};
@@ -118,5 +122,17 @@ describe('Timeline events form', () => {
expect(findHourInput().element.value).toBe('0');
expect(findMinuteInput().element.value).toBe('0');
});
+
+ it('should disable the save buttons when event content does not exist', async () => {
+ expect(findSubmitButton().props('disabled')).toBe(true);
+ expect(findSubmitAndAddButton().props('disabled')).toBe(true);
+ });
+
+ it('should enable the save buttons when event content exists', async () => {
+ await findTextarea().setValue('hello');
+
+ expect(findSubmitButton().props('disabled')).toBe(false);
+ expect(findSubmitAndAddButton().props('disabled')).toBe(false);
+ });
});
});
diff --git a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
index cc8346253ee..d41031f9eaa 100644
--- a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
+++ b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js
@@ -238,7 +238,7 @@ describe('NewBranchForm', () => {
scenario | mutation | alertTitle | alertText
${'with errors-as-data'} | ${mockCreateBranchMutationWithErrors} | ${CREATE_BRANCH_ERROR_WITH_CONTEXT} | ${mockCreateBranchMutationResponseWithErrors.data.createBranch.errors[0]}
${'top-level error'} | ${mockCreateBranchMutationFailed} | ${''} | ${CREATE_BRANCH_ERROR_GENERIC}
- `('', ({ mutation, alertTitle, alertText }) => {
+ `('given $scenario', ({ mutation, alertTitle, alertText }) => {
beforeEach(async () => {
createComponent({
mockApollo: createMockApolloProvider({
diff --git a/spec/frontend/jira_connect/subscriptions/pkce_spec.js b/spec/frontend/jira_connect/subscriptions/pkce_spec.js
index 4ee88059b7a..671922c36d8 100644
--- a/spec/frontend/jira_connect/subscriptions/pkce_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/pkce_spec.js
@@ -1,11 +1,7 @@
import crypto from 'crypto';
-import { TextEncoder, TextDecoder } from 'util';
import { createCodeVerifier, createCodeChallenge } from '~/jira_connect/subscriptions/pkce';
-global.TextEncoder = TextEncoder;
-global.TextDecoder = TextDecoder;
-
describe('pkce', () => {
beforeAll(() => {
Object.defineProperty(global.self, 'crypto', {
diff --git a/spec/frontend/jobs/components/table/job_table_app_spec.js b/spec/frontend/jobs/components/table/job_table_app_spec.js
index 8c724a8030b..109cef6f817 100644
--- a/spec/frontend/jobs/components/table/job_table_app_spec.js
+++ b/spec/frontend/jobs/components/table/job_table_app_spec.js
@@ -12,7 +12,7 @@ import { s__ } from '~/locale';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import getJobsQuery from '~/jobs/components/table/graphql/queries/get_jobs.query.graphql';
import JobsTable from '~/jobs/components/table/jobs_table.vue';
import JobsTableApp from '~/jobs/components/table/jobs_table_app.vue';
@@ -229,7 +229,7 @@ describe('Job table app', () => {
await findFilteredSearch().vm.$emit('filterJobsBySearch', ['raw text']);
- expect(createFlash).toHaveBeenCalledWith(expectedWarning);
+ expect(createAlert).toHaveBeenCalledWith(expectedWarning);
expect(wrapper.vm.$apollo.queries.jobs.refetch).toHaveBeenCalledTimes(0);
});
diff --git a/spec/frontend/labels/components/promote_label_modal_spec.js b/spec/frontend/labels/components/promote_label_modal_spec.js
index 8cfaba6f98a..8953e3cbcd8 100644
--- a/spec/frontend/labels/components/promote_label_modal_spec.js
+++ b/spec/frontend/labels/components/promote_label_modal_spec.js
@@ -1,98 +1,100 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlModal, GlSprintf } from '@gitlab/ui';
+import AxiosMockAdapter from 'axios-mock-adapter';
+
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { stubComponent } from 'helpers/stub_component';
+
import axios from '~/lib/utils/axios_utils';
-import promoteLabelModal from '~/labels/components/promote_label_modal.vue';
+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);
+ let wrapper;
+ let axiosMock;
+
const labelMockData = {
labelTitle: 'Documentation',
- labelColor: '#5cb85c',
- labelTextColor: '#ffffff',
+ labelColor: 'rgb(92, 184, 92)',
+ labelTextColor: 'rgb(255, 255, 255)',
url: `${TEST_HOST}/dummy/promote/labels`,
groupName: 'group',
};
- describe('Modal title and description', () => {
- beforeEach(() => {
- vm = mountComponent(Component, labelMockData);
+ const createComponent = () => {
+ wrapper = shallowMount(PromoteLabelModal, {
+ propsData: labelMockData,
+ stubs: {
+ GlSprintf,
+ GlModal: stubComponent(GlModal, {
+ template: `<div><slot name="modal-title"></slot><slot></slot></div>`,
+ }),
+ },
});
+ };
- afterEach(() => {
- vm.$destroy();
- });
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ createComponent();
+ });
+ afterEach(() => {
+ axiosMock.reset();
+ wrapper.destroy();
+ });
+
+ describe('Modal title and description', () => {
it('contains the proper description', () => {
- expect(vm.text).toContain(
+ expect(wrapper.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);
+ const label = wrapper.find('.modal-title-with-label .label');
+
+ expect(label.element.style.backgroundColor).toBe(labelMockData.labelColor);
+ expect(label.element.style.color).toBe(labelMockData.labelTextColor);
+ expect(label.text()).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', () => {
+ it('redirects when a label is promoted', async () => {
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,
- },
- });
- });
+ axiosMock.onPost(labelMockData.url).reply(200, { url: responseURL });
- return vm.onSubmit().then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: true,
- });
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteLabelModal.requestStarted',
+ labelMockData.url,
+ );
+
+ await axios.waitForAll();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: true,
});
});
- it('displays an error if promoting a label failed', () => {
+ it('displays an error if promoting a label failed', async () => {
const dummyError = new Error('promoting label failed');
dummyError.response = { status: 500 };
+ axiosMock.onPost(labelMockData.url).reply(500, { error: dummyError });
- jest.spyOn(axios, 'post').mockImplementation((url) => {
- expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteLabelModal.requestStarted',
- labelMockData.url,
- );
+ wrapper.findComponent(GlModal).vm.$emit('primary');
- return Promise.reject(dummyError);
- });
+ await axios.waitForAll();
- return vm.onSubmit().catch((error) => {
- expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: false,
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: false,
});
});
});
diff --git a/spec/frontend/lib/dompurify_spec.js b/spec/frontend/lib/dompurify_spec.js
index 5523cc0606e..412408ce377 100644
--- a/spec/frontend/lib/dompurify_spec.js
+++ b/spec/frontend/lib/dompurify_spec.js
@@ -1,4 +1,4 @@
-import { sanitize } from '~/lib/dompurify';
+import { sanitize, defaultConfig } from '~/lib/dompurify';
// GDK
const rootGon = {
@@ -45,7 +45,7 @@ const invalidProtocolUrls = [
/* eslint-enable no-script-url */
const validProtocolUrls = ['slack://open', 'x-devonthink-item://90909', 'x-devonthink-item:90909'];
-const forbiddenDataAttrs = ['data-remote', 'data-url', 'data-type', 'data-method'];
+const forbiddenDataAttrs = defaultConfig.FORBID_ATTR;
const acceptedDataAttrs = ['data-random', 'data-custom'];
describe('~/lib/dompurify', () => {
diff --git a/spec/frontend/lib/utils/autosave_spec.js b/spec/frontend/lib/utils/autosave_spec.js
index 12e97f6cdec..afb49dd6db4 100644
--- a/spec/frontend/lib/utils/autosave_spec.js
+++ b/spec/frontend/lib/utils/autosave_spec.js
@@ -1,32 +1,42 @@
-import { clearDraft, getDraft, updateDraft } from '~/lib/utils/autosave';
+import { clearDraft, getDraft, updateDraft, getLockVersion } from '~/lib/utils/autosave';
describe('autosave utils', () => {
const autosaveKey = 'dummy-autosave-key';
const text = 'some dummy text';
+ const lockVersion = '2';
+ const normalizedAutosaveKey = `autosave/${autosaveKey}`;
+ const lockVersionKey = `autosave/${autosaveKey}/lockVersion`;
describe('clearDraft', () => {
beforeEach(() => {
- localStorage.setItem(`autosave/${autosaveKey}`, text);
+ localStorage.setItem(normalizedAutosaveKey, text);
+ localStorage.setItem(lockVersionKey, lockVersion);
});
afterEach(() => {
- localStorage.removeItem(`autosave/${autosaveKey}`);
+ localStorage.removeItem(normalizedAutosaveKey);
});
it('removes the draft from localStorage', () => {
clearDraft(autosaveKey);
- expect(localStorage.getItem(`autosave/${autosaveKey}`)).toBe(null);
+ expect(localStorage.getItem(normalizedAutosaveKey)).toBe(null);
+ });
+
+ it('removes the lockVersion from localStorage', () => {
+ clearDraft(autosaveKey);
+
+ expect(localStorage.getItem(lockVersionKey)).toBe(null);
});
});
describe('getDraft', () => {
beforeEach(() => {
- localStorage.setItem(`autosave/${autosaveKey}`, text);
+ localStorage.setItem(normalizedAutosaveKey, text);
});
afterEach(() => {
- localStorage.removeItem(`autosave/${autosaveKey}`);
+ localStorage.removeItem(normalizedAutosaveKey);
});
it('returns the draft from localStorage', () => {
@@ -36,7 +46,7 @@ describe('autosave utils', () => {
});
it('returns null if no entry exists in localStorage', () => {
- localStorage.removeItem(`autosave/${autosaveKey}`);
+ localStorage.removeItem(normalizedAutosaveKey);
const result = getDraft(autosaveKey);
@@ -46,19 +56,44 @@ describe('autosave utils', () => {
describe('updateDraft', () => {
beforeEach(() => {
- localStorage.setItem(`autosave/${autosaveKey}`, text);
+ localStorage.setItem(normalizedAutosaveKey, text);
});
afterEach(() => {
- localStorage.removeItem(`autosave/${autosaveKey}`);
+ localStorage.removeItem(normalizedAutosaveKey);
});
- it('removes the draft from localStorage', () => {
+ it('updates the stored draft', () => {
const newText = 'new text';
updateDraft(autosaveKey, newText);
- expect(localStorage.getItem(`autosave/${autosaveKey}`)).toBe(newText);
+ expect(localStorage.getItem(normalizedAutosaveKey)).toBe(newText);
+ });
+
+ describe('when lockVersion is provided', () => {
+ it('updates the stored lockVersion', () => {
+ const newText = 'new text';
+ const newLockVersion = '2';
+
+ updateDraft(autosaveKey, newText, lockVersion);
+
+ expect(localStorage.getItem(lockVersionKey)).toBe(newLockVersion);
+ });
+ });
+ });
+
+ describe('getLockVersion', () => {
+ beforeEach(() => {
+ localStorage.setItem(lockVersionKey, lockVersion);
+ });
+
+ afterEach(() => {
+ localStorage.removeItem(lockVersionKey);
+ });
+
+ it('returns the lockVersion from localStorage', () => {
+ expect(getLockVersion(autosaveKey)).toBe(lockVersion);
});
});
});
diff --git a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js
index 018ae12c908..2e0bb6a8dcd 100644
--- a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js
@@ -145,3 +145,22 @@ describe('durationTimeFormatted', () => {
expect(utils.durationTimeFormatted(duration)).toBe(expectedOutput);
});
});
+
+describe('formatUtcOffset', () => {
+ it.each`
+ offset | expected
+ ${-32400} | ${'- 9'}
+ ${'-12600'} | ${'- 3.5'}
+ ${0} | ${'0'}
+ ${'10800'} | ${'+ 3'}
+ ${19800} | ${'+ 5.5'}
+ ${0} | ${'0'}
+ ${[]} | ${'0'}
+ ${{}} | ${'0'}
+ ${true} | ${'0'}
+ ${null} | ${'0'}
+ ${undefined} | ${'0'}
+ `('returns $expected given $offset', ({ offset, expected }) => {
+ expect(utils.formatUtcOffset(offset)).toEqual(expected);
+ });
+});
diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js
index 8d179baa505..9fbb3d0a660 100644
--- a/spec/frontend/lib/utils/text_markdown_spec.js
+++ b/spec/frontend/lib/utils/text_markdown_spec.js
@@ -4,15 +4,30 @@ import {
keypressNoteText,
compositionStartNoteText,
compositionEndNoteText,
+ updateTextForToolbarBtn,
} from '~/lib/utils/text_markdown';
import '~/lib/utils/jquery_at_who';
+import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
describe('init markdown', () => {
+ let mdArea;
let textArea;
+ let indentButton;
+ let outdentButton;
beforeAll(() => {
- textArea = document.createElement('textarea');
- document.querySelector('body').appendChild(textArea);
+ setHTMLFixture(
+ `<div class='md-area'>
+ <textarea></textarea>
+ <button data-md-command="indentLines" id="indentButton"></button>
+ <button data-md-command="outdentLines" id="outdentButton"></button>
+ </div>`,
+ );
+ mdArea = document.querySelector('.md-area');
+ textArea = mdArea.querySelector('textarea');
+ indentButton = mdArea.querySelector('#indentButton');
+ outdentButton = mdArea.querySelector('#outdentButton');
+
textArea.focus();
// needed for the underlying insertText to work
@@ -20,7 +35,7 @@ describe('init markdown', () => {
});
afterAll(() => {
- textArea.parentNode.removeChild(textArea);
+ resetHTMLFixture();
});
describe('insertMarkdownText', () => {
@@ -183,6 +198,7 @@ describe('init markdown', () => {
textArea.addEventListener('keydown', keypressNoteText);
textArea.addEventListener('compositionstart', compositionStartNoteText);
textArea.addEventListener('compositionend', compositionEndNoteText);
+ gon.markdown_automatic_lists = true;
});
it.each`
@@ -302,19 +318,22 @@ describe('init markdown', () => {
expect(textArea.value).toEqual(expected);
expect(textArea.selectionStart).toBe(expected.length);
});
- });
- });
- describe('shifting selected lines left or right', () => {
- const indentEvent = new KeyboardEvent('keydown', { key: ']', metaKey: true });
- const outdentEvent = new KeyboardEvent('keydown', { key: '[', metaKey: true });
+ it('does nothing if user preference disabled', () => {
+ const text = '- test';
- beforeEach(() => {
- textArea.addEventListener('keydown', keypressNoteText);
- textArea.addEventListener('compositionstart', compositionStartNoteText);
- textArea.addEventListener('compositionend', compositionEndNoteText);
+ gon.markdown_automatic_lists = false;
+
+ textArea.value = text;
+ textArea.setSelectionRange(text.length, text.length);
+ textArea.dispatchEvent(enterEvent);
+
+ expect(textArea.value).toEqual(text);
+ });
});
+ });
+ describe('shifting selected lines left or right', () => {
it.each`
selectionStart | selectionEnd | expected | expectedSelectionStart | expectedSelectionEnd
${0} | ${0} | ${' 012\n456\n89'} | ${2} | ${2}
@@ -338,7 +357,7 @@ describe('init markdown', () => {
textArea.value = text;
textArea.setSelectionRange(selectionStart, selectionEnd);
- textArea.dispatchEvent(indentEvent);
+ updateTextForToolbarBtn($(indentButton));
expect(textArea.value).toEqual(expected);
expect(textArea.selectionStart).toEqual(expectedSelectionStart);
@@ -350,7 +369,7 @@ describe('init markdown', () => {
textArea.value = '012\n\n89';
textArea.setSelectionRange(4, 4);
- textArea.dispatchEvent(indentEvent);
+ updateTextForToolbarBtn($(indentButton));
expect(textArea.value).toEqual('012\n \n89');
expect(textArea.selectionStart).toEqual(6);
@@ -381,7 +400,7 @@ describe('init markdown', () => {
textArea.value = text;
textArea.setSelectionRange(selectionStart, selectionEnd);
- textArea.dispatchEvent(outdentEvent);
+ updateTextForToolbarBtn($(outdentButton));
expect(textArea.value).toEqual(expected);
expect(textArea.selectionStart).toEqual(expectedSelectionStart);
@@ -393,7 +412,7 @@ describe('init markdown', () => {
textArea.value = '012\n\n89';
textArea.setSelectionRange(4, 4);
- textArea.dispatchEvent(outdentEvent);
+ updateTextForToolbarBtn($(outdentButton));
expect(textArea.value).toEqual('012\n\n89');
expect(textArea.selectionStart).toEqual(4);
diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js
index 49a160c9f23..f2572ca0ad2 100644
--- a/spec/frontend/lib/utils/text_utility_spec.js
+++ b/spec/frontend/lib/utils/text_utility_spec.js
@@ -386,4 +386,16 @@ describe('text_utility', () => {
expect(textUtils.limitedCounterWithDelimiter(120)).toBe(120);
});
});
+
+ describe('base64EncodeUnicode', () => {
+ it('encodes unicode characters', () => {
+ expect(textUtils.base64EncodeUnicode('😀')).toBe('8J+YgA==');
+ });
+ });
+
+ describe('base64DecodeUnicode', () => {
+ it('decodes unicode characters', () => {
+ expect(textUtils.base64DecodeUnicode('8J+YgA==')).toBe('😀');
+ });
+ });
});
diff --git a/spec/frontend/listbox/index_spec.js b/spec/frontend/listbox/index_spec.js
index 07c6cca535a..fd41531796b 100644
--- a/spec/frontend/listbox/index_spec.js
+++ b/spec/frontend/listbox/index_spec.js
@@ -1,6 +1,6 @@
import { nextTick } from 'vue';
-import { getAllByRole, getByRole } from '@testing-library/dom';
-import { GlDropdown } from '@gitlab/ui';
+import { getAllByRole, getByTestId } from '@testing-library/dom';
+import { GlListbox } from '@gitlab/ui';
import { createWrapper } from '@vue/test-utils';
import { initListbox, parseAttributes } from '~/listbox';
import { getFixture, setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
@@ -28,20 +28,6 @@ describe('initListbox', () => {
instance = initListbox(...args);
};
- // TODO: Rewrite these finders to use better semantics once the
- // implementation is switched to GlListbox
- // https://gitlab.com/gitlab-org/gitlab/-/issues/348738
- const findToggleButton = () => document.body.querySelector('.gl-dropdown-toggle');
- const findItem = (text) => getByRole(document.body, 'menuitem', { name: text });
- const findItems = () => getAllByRole(document.body, 'menuitem');
- const findSelectedItems = () =>
- findItems().filter(
- (menuitem) =>
- !menuitem
- .querySelector('.gl-new-dropdown-item-check-icon')
- .classList.contains('gl-visibility-hidden'),
- );
-
it('returns null given no element', () => {
setup();
@@ -55,6 +41,10 @@ describe('initListbox', () => {
describe('given a valid element', () => {
let onChangeSpy;
+ const listbox = () => createWrapper(instance).findComponent(GlListbox);
+ const findToggleButton = () => getByTestId(document.body, 'base-dropdown-toggle');
+ const findSelectedItems = () => getAllByRole(document.body, 'option', { selected: true });
+
beforeEach(async () => {
setHTMLFixture(fixture);
onChangeSpy = jest.fn();
@@ -85,10 +75,9 @@ describe('initListbox', () => {
expect(instance.$el.classList).toContain('test-class-1', 'test-class-2');
});
- describe.each(parsedAttributes.items)('clicking on an item', (item) => {
+ describe.each(parsedAttributes.items)('selecting an item', (item) => {
beforeEach(async () => {
- findItem(item.text).click();
-
+ listbox().vm.$emit('select', item.value);
await nextTick();
});
@@ -108,8 +97,7 @@ describe('initListbox', () => {
});
it('passes the "right" prop through to the underlying component', () => {
- const wrapper = createWrapper(instance).findComponent(GlDropdown);
- expect(wrapper.props('right')).toBe(parsedAttributes.right);
+ expect(listbox().props('right')).toBe(parsedAttributes.right);
});
});
});
diff --git a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
index 5581fd52458..ef3c8bde3cf 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -45,7 +45,7 @@ describe('SortDropdown', () => {
const findSortingComponent = () => wrapper.findComponent(GlSorting);
const findSortDirectionToggle = () =>
- findSortingComponent().find('button[title="Sort direction"]');
+ findSortingComponent().find('button[title^="Sort direction"]');
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
const findDropdownItemByText = (text) =>
wrapper
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 f3f50bf620a..03cfc6ca0f6 100644
--- a/spec/frontend/members/components/table/member_action_buttons_spec.js
+++ b/spec/frontend/members/components/table/member_action_buttons_spec.js
@@ -27,7 +27,7 @@ describe('MemberActionButtons', () => {
wrapper.destroy();
});
- test.each`
+ it.each`
memberType | member | expectedComponent | expectedComponentName
${MEMBER_TYPES.user} | ${memberMock} | ${UserActionButtons} | ${'UserActionButtons'}
${MEMBER_TYPES.group} | ${group} | ${GroupActionButtons} | ${'GroupActionButtons'}
diff --git a/spec/frontend/members/components/table/member_avatar_spec.js b/spec/frontend/members/components/table/member_avatar_spec.js
index 35f82c28fc5..dc5c97f41df 100644
--- a/spec/frontend/members/components/table/member_avatar_spec.js
+++ b/spec/frontend/members/components/table/member_avatar_spec.js
@@ -22,7 +22,7 @@ describe('MemberList', () => {
wrapper.destroy();
});
- test.each`
+ it.each`
memberType | member | expectedComponent | expectedComponentName
${MEMBER_TYPES.user} | ${memberMock} | ${UserAvatar} | ${'UserAvatar'}
${MEMBER_TYPES.group} | ${group} | ${GroupAvatar} | ${'GroupAvatar'}
diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js
index fd56699602e..0b0140b0cdb 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -95,7 +95,7 @@ describe('MembersTableCell', () => {
wrapper = null;
});
- test.each`
+ it.each`
member | expectedMemberType
${memberMock} | ${MEMBER_TYPES.user}
${group} | ${MEMBER_TYPES.group}
diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js
index 0271483801c..8bef2096a2a 100644
--- a/spec/frontend/members/utils_spec.js
+++ b/spec/frontend/members/utils_spec.js
@@ -89,7 +89,7 @@ describe('Members Utils', () => {
});
describe('isGroup', () => {
- test.each`
+ it.each`
member | expected
${group} | ${true}
${memberMock} | ${false}
@@ -99,7 +99,7 @@ describe('Members Utils', () => {
});
describe('isDirectMember', () => {
- test.each`
+ it.each`
member | expected
${directMember} | ${true}
${inheritedMember} | ${false}
@@ -109,7 +109,7 @@ describe('Members Utils', () => {
});
describe('isCurrentUser', () => {
- test.each`
+ it.each`
currentUserId | expected
${IS_CURRENT_USER_ID} | ${true}
${IS_NOT_CURRENT_USER_ID} | ${false}
@@ -119,7 +119,7 @@ describe('Members Utils', () => {
});
describe('canRemove', () => {
- test.each`
+ it.each`
member | expected
${{ ...directMember, canRemove: true }} | ${true}
${{ ...inheritedMember, canRemove: true }} | ${false}
@@ -130,7 +130,7 @@ describe('Members Utils', () => {
});
describe('canResend', () => {
- test.each`
+ it.each`
member | expected
${invite} | ${true}
${{ ...invite, invite: { ...invite.invite, canResend: false } }} | ${false}
@@ -140,7 +140,7 @@ describe('Members Utils', () => {
});
describe('canUpdate', () => {
- test.each`
+ it.each`
member | currentUserId | expected
${{ ...directMember, canUpdate: true }} | ${IS_NOT_CURRENT_USER_ID} | ${true}
${{ ...directMember, canUpdate: true }} | ${IS_CURRENT_USER_ID} | ${false}
diff --git a/spec/frontend/merge_conflicts/store/actions_spec.js b/spec/frontend/merge_conflicts/store/actions_spec.js
index e73769cba51..50eac982e20 100644
--- a/spec/frontend/merge_conflicts/store/actions_spec.js
+++ b/spec/frontend/merge_conflicts/store/actions_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import Cookies from '~/lib/utils/cookies';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { INTERACTIVE_RESOLVE_MODE, EDIT_RESOLVE_MODE } from '~/merge_conflicts/constants';
import * as actions from '~/merge_conflicts/store/actions';
import * as types from '~/merge_conflicts/store/mutation_types';
@@ -125,7 +125,7 @@ describe('merge conflicts actions', () => {
],
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Failed to save merge conflicts resolutions. Please try again!',
});
});
diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js
index bcf64204c7a..16e3e49a297 100644
--- a/spec/frontend/merge_request_spec.js
+++ b/spec/frontend/merge_request_spec.js
@@ -3,9 +3,12 @@ import $ from 'jquery';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import MergeRequest from '~/merge_request';
+jest.mock('~/flash');
+
describe('MergeRequest', () => {
const test = {};
describe('task lists', () => {
@@ -95,8 +98,11 @@ describe('MergeRequest', () => {
await waitForPromises();
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
+ expect(createAlert).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message:
+ 'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
+ }),
);
});
});
diff --git a/spec/frontend/milestones/components/promote_milestone_modal_spec.js b/spec/frontend/milestones/components/promote_milestone_modal_spec.js
index 11eaa92f2b0..60657fbc9b8 100644
--- a/spec/frontend/milestones/components/promote_milestone_modal_spec.js
+++ b/spec/frontend/milestones/components/promote_milestone_modal_spec.js
@@ -3,7 +3,7 @@ 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 { createAlert } 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';
@@ -103,7 +103,7 @@ describe('Promote milestone modal', () => {
wrapper.findComponent(GlModal).vm.$emit('primary');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: dummyError });
+ expect(createAlert).toHaveBeenCalledWith({ message: dummyError });
});
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 1de6b6e3e98..1d17a9116df 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -4,7 +4,7 @@ import { nextTick } from 'vue';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { ESC_KEY } from '~/lib/utils/keys';
import { objectToQuery } from '~/lib/utils/url_utility';
@@ -198,7 +198,7 @@ describe('Dashboard', () => {
);
await nextTick();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('does not display a warning if there are no validation warnings', async () => {
@@ -210,7 +210,7 @@ describe('Dashboard', () => {
);
await nextTick();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -275,7 +275,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
await nextTick();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
expect(store.dispatch).not.toHaveBeenCalledWith(
'monitoringDashboard/setExpandedPanel',
expect.anything(),
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index a327e234581..9873654bdda 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
queryToObject,
@@ -115,7 +115,7 @@ describe('dashboard invalid url parameters', () => {
createMountedWrapper();
await nextTick();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange);
diff --git a/spec/frontend/monitoring/requests/index_spec.js b/spec/frontend/monitoring/requests/index_spec.js
index 03bf5d70153..6f9af911a9f 100644
--- a/spec/frontend/monitoring/requests/index_spec.js
+++ b/spec/frontend/monitoring/requests/index_spec.js
@@ -129,7 +129,7 @@ describe('monitoring metrics_requests', () => {
});
});
- test.each`
+ it.each`
code | reason
${statusCodes.BAD_REQUEST} | ${'Parameters are missing or incorrect'}
${statusCodes.UNPROCESSABLE_ENTITY} | ${"Expression can't be executed"}
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index a872a7780eb..ca66768c3cc 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { backoffMockImplementation } from 'helpers/backoff_helper';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import statusCodes from '~/lib/utils/http_status';
@@ -82,7 +82,7 @@ describe('Monitoring store actions', () => {
mock.reset();
commonUtils.backOff.mockReset();
- createFlash.mockReset();
+ createAlert.mockReset();
});
// Setup
@@ -241,7 +241,7 @@ describe('Monitoring store actions', () => {
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('dispatches a failure action when a message is returned', async () => {
@@ -250,7 +250,7 @@ describe('Monitoring store actions', () => {
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.stringContaining(mockDashboardsErrorResponse.message),
});
});
@@ -263,7 +263,7 @@ describe('Monitoring store actions', () => {
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
});
@@ -328,7 +328,7 @@ describe('Monitoring store actions', () => {
},
});
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
it('dispatches fetchPrometheusMetric for each panel query', async () => {
@@ -385,7 +385,7 @@ describe('Monitoring store actions', () => {
defaultQueryParams,
});
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
});
@@ -570,7 +570,7 @@ describe('Monitoring store actions', () => {
[],
[{ type: 'receiveDeploymentsDataFailure' }],
() => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
},
);
});
@@ -1084,8 +1084,8 @@ describe('Monitoring store actions', () => {
return testAction(fetchVariableMetricLabelValues, { defaultQueryParams }, state, [], []).then(
() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: expect.stringContaining('error getting options for variable "label1"'),
});
},
diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js
index 31975052077..6c6c3d6b90f 100644
--- a/spec/frontend/monitoring/utils_spec.js
+++ b/spec/frontend/monitoring/utils_spec.js
@@ -290,7 +290,7 @@ describe('monitoring/utils', () => {
expect(() => expandedPanelPayloadFromUrl(metricsDashboardViewModel, search)).toThrow();
});
- test.each`
+ it.each`
group | title | yLabel | missingField
${'NOT_A_GROUP'} | ${title} | ${yLabel} | ${'group'}
${group} | ${'NOT_A_TITLE'} | ${yLabel} | ${'title'}
@@ -367,7 +367,7 @@ describe('monitoring/utils', () => {
],
};
- [
+ it.each([
{
input: { metrics: undefined },
output: {},
@@ -393,12 +393,10 @@ describe('monitoring/utils', () => {
output: multipleMetricExpected,
testCase: 'barChartsDataParser returns multiple series object with multiple metrics',
},
- ].forEach(({ input, output, testCase }) => {
- it(testCase, () => {
- expect(monitoringUtils.barChartsDataParser(input.metrics)).toEqual(
- expect.objectContaining(output),
- );
- });
+ ])('$testCase', ({ input, output }) => {
+ expect(monitoringUtils.barChartsDataParser(input.metrics)).toEqual(
+ expect.objectContaining(output),
+ );
});
});
diff --git a/spec/frontend/nav/components/top_nav_app_spec.js b/spec/frontend/nav/components/top_nav_app_spec.js
index 745707c1d28..b32ab5ebe09 100644
--- a/spec/frontend/nav/components/top_nav_app_spec.js
+++ b/spec/frontend/nav/components/top_nav_app_spec.js
@@ -1,5 +1,6 @@
import { GlNavItemDropdown } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import { mockTracking } from 'helpers/tracking_helper';
import TopNavApp from '~/nav/components/top_nav_app.vue';
import TopNavDropdownMenu from '~/nav/components/top_nav_dropdown_menu.vue';
import { TEST_NAV_DATA } from '../mock_data';
@@ -8,6 +9,14 @@ describe('~/nav/components/top_nav_app.vue', () => {
let wrapper;
const createComponent = () => {
+ wrapper = mount(TopNavApp, {
+ propsData: {
+ navData: TEST_NAV_DATA,
+ },
+ });
+ };
+
+ const createComponentShallow = () => {
wrapper = shallowMount(TopNavApp, {
propsData: {
navData: TEST_NAV_DATA,
@@ -16,6 +25,7 @@ describe('~/nav/components/top_nav_app.vue', () => {
};
const findNavItemDropdown = () => wrapper.findComponent(GlNavItemDropdown);
+ const findNavItemDropdowToggle = () => findNavItemDropdown().find('.js-top-nav-dropdown-toggle');
const findMenu = () => wrapper.findComponent(TopNavDropdownMenu);
afterEach(() => {
@@ -24,7 +34,7 @@ describe('~/nav/components/top_nav_app.vue', () => {
describe('default', () => {
beforeEach(() => {
- createComponent();
+ createComponentShallow();
});
it('renders nav item dropdown', () => {
@@ -45,4 +55,18 @@ describe('~/nav/components/top_nav_app.vue', () => {
});
});
});
+
+ describe('tracking', () => {
+ it('emits a tracking event when the toggle is clicked', () => {
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ createComponent();
+
+ findNavItemDropdowToggle().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_nav', {
+ label: 'hamburger_menu',
+ property: 'top_navigation',
+ });
+ });
+ });
});
diff --git a/spec/frontend/notebook/cells/output/index_spec.js b/spec/frontend/notebook/cells/output/index_spec.js
index 97a7e22be60..8bf049235a9 100644
--- a/spec/frontend/notebook/cells/output/index_spec.js
+++ b/spec/frontend/notebook/cells/output/index_spec.js
@@ -53,6 +53,7 @@ describe('Output component', () => {
expect(iframe.exists()).toBe(true);
expect(iframe.element.getAttribute('sandbox')).toBe('');
expect(iframe.element.getAttribute('srcdoc')).toBe('<p>test</p>');
+ expect(iframe.element.getAttribute('scrolling')).toBe('auto');
});
it('renders multiple raw HTML outputs', () => {
diff --git a/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap b/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap
index 5f4b3e04a79..bc29903d4bf 100644
--- a/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap
+++ b/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap
@@ -3,15 +3,15 @@
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>
+ <skeleton-loading-container-stub class=\\"note-skeleton\\"></skeleton-loading-container-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>
+ <skeleton-loading-container-stub class=\\"note-skeleton\\"></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/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index 55e4ef42e37..701ff492702 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -7,7 +7,7 @@ import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import CommentForm from '~/notes/components/comment_form.vue';
import CommentTypeDropdown from '~/notes/components/comment_type_dropdown.vue';
@@ -71,11 +71,19 @@ describe('issue_comment_form component', () => {
};
const notableDataMockCanUpdateIssuable = createNotableDataMock({
- current_user: { can_update: true, can_create_note: true },
+ current_user: { can_update: true, can_create_note: true, can_create_confidential_note: true },
});
const notableDataMockCannotUpdateIssuable = createNotableDataMock({
- current_user: { can_update: false, can_create_note: true },
+ current_user: {
+ can_update: false,
+ can_create_note: false,
+ can_create_confidential_note: false,
+ },
+ });
+
+ const notableDataMockCannotCreateConfidentialNote = createNotableDataMock({
+ current_user: { can_update: false, can_create_note: true, can_create_confidential_note: false },
});
const mountComponent = ({
@@ -490,7 +498,7 @@ describe('issue_comment_form component', () => {
await nextTick();
await nextTick();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong while closing the ${type}. Please try again later.`,
});
});
@@ -526,7 +534,7 @@ describe('issue_comment_form component', () => {
await nextTick();
await nextTick();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong while reopening the ${type}. Please try again later.`,
});
});
@@ -562,6 +570,17 @@ describe('issue_comment_form component', () => {
expect(checkbox.element.checked).toBe(false);
});
+ it('should not render checkbox if user is not at least a reporter', () => {
+ mountComponent({
+ mountFunction: mount,
+ initialData: { note: 'confidential note' },
+ noteableData: { ...notableDataMockCannotCreateConfidentialNote },
+ });
+
+ const checkbox = findConfidentialNoteCheckbox();
+ expect(checkbox.exists()).toBe(false);
+ });
+
it.each`
noteableType | rendered | message
${'Issue'} | ${true} | ${'render'}
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index 5800f68b114..bb44563b87a 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -42,7 +42,7 @@ describe('diff_discussion_header component', () => {
expect(props).toMatchObject({
src: firstNoteAuthor.avatar_url,
alt: firstNoteAuthor.name,
- size: { default: 24, md: 32 },
+ size: 32,
});
});
});
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index d16c13d6fd3..e414ada1854 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -81,7 +81,7 @@ describe('DiscussionActions', () => {
});
});
- it(shouldRender ? 'renders resolve buttons' : 'does not render resolve buttons', () => {
+ it(`${shouldRender ? 'renders' : 'does not render'} resolve buttons`, () => {
expect(wrapper.findComponent(ResolveDiscussionButton).exists()).toBe(shouldRender);
expect(wrapper.findComponent(ResolveWithIssueButton).exists()).toBe(shouldRender);
});
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index 76177229cff..b870cda2a24 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -1,10 +1,7 @@
-import { GlSprintf } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import NoteHeader from '~/notes/components/note_header.vue';
-import { AVAILABILITY_STATUS } from '~/set_status_modal/constants';
-import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
Vue.use(Vuex);
@@ -23,7 +20,6 @@ describe('NoteHeader component', () => {
const findTimestamp = () => wrapper.findComponent({ ref: 'noteTimestamp' });
const findInternalNoteIndicator = () => wrapper.findByTestId('internalNoteIndicator');
const findSpinner = () => wrapper.findComponent({ ref: 'spinner' });
- const findAuthorStatus = () => wrapper.findComponent({ ref: 'authorStatus' });
const statusHtml =
'"<span class="user-status-emoji has-tooltip" title="foo bar" data-html="true" data-placement="top"><gl-emoji title="basketball and hoop" data-name="basketball" data-unicode-version="6.0">ðŸ€</gl-emoji></span>"';
@@ -37,22 +33,14 @@ describe('NoteHeader component', () => {
username: 'root',
show_status: true,
status_tooltip_html: statusHtml,
- availability: '',
};
- const createComponent = (props, userAttributes = false) => {
+ const createComponent = (props) => {
wrapper = shallowMountExtended(NoteHeader, {
store: new Vuex.Store({
actions,
}),
propsData: { ...props },
- stubs: { GlSprintf, UserNameWithStatus },
- provide: {
- glFeatures: {
- removeUserAttributesProjects: userAttributes,
- removeUserAttributesGroups: userAttributes,
- },
- },
});
};
@@ -61,26 +49,6 @@ describe('NoteHeader component', () => {
wrapper = null;
});
- describe('when removeUserAttributesProjects feature flag is enabled', () => {
- it('does not render busy status', () => {
- createComponent({ author: { ...author, availability: AVAILABILITY_STATUS.BUSY } }, true);
-
- expect(wrapper.find('.note-header-info').text()).not.toContain('(Busy)');
- });
-
- it('does not render author status', () => {
- createComponent({ author }, true);
-
- expect(findAuthorStatus().exists()).toBe(false);
- });
-
- it('does not render username', () => {
- createComponent({ author }, true);
-
- expect(wrapper.find('.note-header-info').text()).not.toContain('@');
- });
- });
-
it('does not render discussion actions when includeToggle is false', () => {
createComponent({
includeToggle: false,
@@ -145,39 +113,6 @@ describe('NoteHeader component', () => {
expect(wrapper.find('.js-user-link').exists()).toBe(true);
});
-
- it('renders busy status if author availability is set', () => {
- createComponent({ author: { ...author, availability: AVAILABILITY_STATUS.BUSY } });
-
- expect(wrapper.find('.js-user-link').text()).toContain('(Busy)');
- });
-
- it('renders author status', () => {
- createComponent({ author });
-
- expect(findAuthorStatus().exists()).toBe(true);
- });
-
- it('does not render author status if show_status=false', () => {
- createComponent({
- author: { ...author, status: { availability: AVAILABILITY_STATUS.BUSY }, show_status: false },
- });
-
- expect(findAuthorStatus().exists()).toBe(false);
- });
-
- it('does not render author status if status_tooltip_html=null', () => {
- createComponent({
- author: {
- ...author,
- status: { availability: AVAILABILITY_STATUS.BUSY },
- status_tooltip_html: null,
- },
- });
-
- expect(findAuthorStatus().exists()).toBe(false);
- });
-
it('renders deleted user text if author is not passed as a prop', () => {
createComponent();
@@ -270,24 +205,6 @@ describe('NoteHeader component', () => {
});
});
- describe('when author status tooltip is opened', () => {
- it('removes `title` attribute from emoji to prevent duplicate tooltips', () => {
- createComponent({
- author: {
- ...author,
- status_tooltip_html: statusHtml,
- },
- });
-
- return nextTick().then(() => {
- const authorStatus = findAuthorStatus();
- authorStatus.trigger('mouseenter');
-
- expect(authorStatus.find('gl-emoji').attributes('title')).toBeUndefined();
- });
- });
- });
-
describe('when author username link is hovered', () => {
it('toggles hover specific CSS classes on author name link', async () => {
createComponent({ author });
@@ -327,4 +244,18 @@ describe('NoteHeader component', () => {
);
});
});
+
+ it('does render username', () => {
+ createComponent({ author }, true);
+
+ expect(wrapper.find('.note-header-info').text()).toContain('@');
+ });
+
+ describe('with system note', () => {
+ it('does not render username', () => {
+ createComponent({ author, isSystemNote: true }, true);
+
+ expect(wrapper.find('.note-header-info').text()).not.toContain('@');
+ });
+ });
});
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index b044d40cbe4..3d7195752d3 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -214,7 +214,7 @@ describe('issue_note', () => {
expect(avatarProps.src).toBe(author.avatar_url);
expect(avatarProps.entityName).toBe(author.username);
expect(avatarProps.alt).toBe(author.name);
- expect(avatarProps.size).toEqual({ default: 24, md: 32 });
+ expect(avatarProps.size).toEqual(32);
});
it('should render note header content', () => {
diff --git a/spec/frontend/notes/components/notes_activity_header_spec.js b/spec/frontend/notes/components/notes_activity_header_spec.js
new file mode 100644
index 00000000000..5b3165bf401
--- /dev/null
+++ b/spec/frontend/notes/components/notes_activity_header_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import { __ } from '~/locale';
+import NotesActivityHeader from '~/notes/components/notes_activity_header.vue';
+import DiscussionFilter from '~/notes/components/discussion_filter.vue';
+import TimelineToggle from '~/notes/components/timeline_toggle.vue';
+import createStore from '~/notes/stores';
+import waitForPromises from 'helpers/wait_for_promises';
+import { notesFilters } from '../mock_data';
+
+describe('~/notes/components/notes_activity_header.vue', () => {
+ let wrapper;
+
+ const findTitle = () => wrapper.find('h2');
+
+ const createComponent = ({ props = {}, ...options } = {}) => {
+ wrapper = shallowMount(NotesActivityHeader, {
+ propsData: {
+ notesFilters,
+ ...props,
+ },
+ // why: Rendering async timeline toggle requires store
+ store: createStore(),
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders title', () => {
+ expect(findTitle().text()).toBe(__('Activity'));
+ });
+
+ it('renders discussion filter', () => {
+ expect(wrapper.findComponent(DiscussionFilter).props()).toEqual({
+ filters: notesFilters,
+ selectedValue: 0,
+ });
+ });
+
+ it('does not render timeline toggle', () => {
+ expect(wrapper.findComponent(TimelineToggle).exists()).toBe(false);
+ });
+ });
+
+ it('with notesFilterValue prop, passes to discussion filter', () => {
+ createComponent({ props: { notesFilterValue: 1 } });
+
+ expect(wrapper.findComponent(DiscussionFilter).props('selectedValue')).toBe(1);
+ });
+
+ it('with showTimelineViewToggle injected, renders timeline toggle asynchronously', async () => {
+ createComponent({ provide: { showTimelineViewToggle: () => true } });
+
+ expect(wrapper.findComponent(TimelineToggle).exists()).toBe(false);
+
+ await waitForPromises();
+
+ expect(wrapper.findComponent(TimelineToggle).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index d4cb07d97dc..9051fcab97f 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -11,6 +11,7 @@ import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
import CommentForm from '~/notes/components/comment_form.vue';
import NotesApp from '~/notes/components/notes_app.vue';
+import NotesActivityHeader from '~/notes/components/notes_activity_header.vue';
import * as constants from '~/notes/constants';
import createStore from '~/notes/stores';
import '~/behaviors/markdown/render_gfm';
@@ -20,11 +21,14 @@ import * as mockData from '../mock_data';
const TYPE_COMMENT_FORM = 'comment-form';
const TYPE_NOTES_LIST = 'notes-list';
+const TEST_NOTES_FILTER_VALUE = 1;
const propsData = {
noteableData: mockData.noteableDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
+ notesFilters: mockData.notesFilters,
+ notesFilterValue: TEST_NOTES_FILTER_VALUE,
};
describe('note_app', () => {
@@ -47,7 +51,7 @@ describe('note_app', () => {
axiosMock = new AxiosMockAdapter(axios);
store = createStore();
- mountComponent = () => {
+ mountComponent = ({ props = {} } = {}) => {
return mount(
{
components: {
@@ -58,7 +62,10 @@ describe('note_app', () => {
</div>`,
},
{
- propsData,
+ propsData: {
+ ...propsData,
+ ...props,
+ },
store,
},
);
@@ -144,6 +151,13 @@ describe('note_app', () => {
it('updates discussions badge', () => {
expect(document.querySelector('.js-discussions-count').textContent).toEqual('2');
});
+
+ it('should render notes activity header', () => {
+ expect(wrapper.findComponent(NotesActivityHeader).props()).toEqual({
+ notesFilterValue: TEST_NOTES_FILTER_VALUE,
+ notesFilters: mockData.notesFilters,
+ });
+ });
});
describe('render with comments disabled', () => {
@@ -151,8 +165,15 @@ describe('note_app', () => {
setHTMLFixture('<div class="js-discussions-count"></div>');
axiosMock.onAny().reply(mockData.getIndividualNoteResponse);
- store.state.commentsDisabled = true;
- wrapper = mountComponent();
+ wrapper = mountComponent({
+ // why: In this integration test, previously we manually set store.state.commentsDisabled
+ // This stopped working when we added `<discussion-filter>` into the component tree.
+ // Let's lean into the integration scope and use a prop that "disables comments".
+ props: {
+ notesFilterValue: constants.HISTORY_ONLY_FILTER_VALUE,
+ },
+ });
+
return waitForPromises();
});
@@ -358,7 +379,7 @@ describe('note_app', () => {
it('should listen hashchange event', () => {
const notesApp = wrapper.findComponent(NotesApp);
const hash = 'some dummy hash';
- jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce(hash);
+ jest.spyOn(urlUtility, 'getLocationHash').mockReturnValue(hash);
const setTargetNoteHash = jest.spyOn(notesApp.vm, 'setTargetNoteHash');
window.dispatchEvent(new Event('hashchange'), hash);
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 1b4e8026d84..45625d0a23f 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -4,7 +4,6 @@ import Vuex from 'vuex';
import { setHTMLFixture } from 'helpers/fixtures';
import createEventHub from '~/helpers/event_hub_factory';
import * as utils from '~/lib/utils/common_utils';
-import eventHub from '~/notes/event_hub';
import discussionNavigation from '~/notes/mixins/discussion_navigation';
import notesModule from '~/notes/stores/modules';
@@ -35,13 +34,15 @@ describe('Discussion navigation mixin', () => {
beforeEach(() => {
setHTMLFixture(
- [...'abcde']
+ `<div class="notes">
+ ${[...'abcde']
.map(
(id) =>
`<ul class="notes" data-discussion-id="${id}"></ul>
<div class="discussion" data-discussion-id="${id}"></div>`,
)
- .join(''),
+ .join('')}
+ </div>`,
);
jest.spyOn(utils, 'scrollToElementWithContext');
@@ -58,7 +59,7 @@ describe('Discussion navigation mixin', () => {
},
diffs: {
namespaced: true,
- actions: { scrollToFile },
+ actions: { scrollToFile, disableVirtualScroller: () => {} },
state: { diffFiles: [] },
},
},
@@ -73,9 +74,6 @@ describe('Discussion navigation mixin', () => {
jest.clearAllMocks();
});
- const findDiscussion = (selector, id) =>
- document.querySelector(`${selector}[data-discussion-id="${id}"]`);
-
describe('jumpToFirstUnresolvedDiscussion method', () => {
let vm;
@@ -110,14 +108,14 @@ describe('Discussion navigation mixin', () => {
});
describe.each`
- fn | args | currentId | expected
- ${'jumpToNextDiscussion'} | ${[]} | ${null} | ${'a'}
- ${'jumpToNextDiscussion'} | ${[]} | ${'a'} | ${'c'}
- ${'jumpToNextDiscussion'} | ${[]} | ${'e'} | ${'a'}
- ${'jumpToPreviousDiscussion'} | ${[]} | ${null} | ${'e'}
- ${'jumpToPreviousDiscussion'} | ${[]} | ${'e'} | ${'c'}
- ${'jumpToPreviousDiscussion'} | ${[]} | ${'c'} | ${'a'}
- `('$fn (args = $args, currentId = $currentId)', ({ fn, args, currentId, expected }) => {
+ fn | args | currentId
+ ${'jumpToNextDiscussion'} | ${[]} | ${null}
+ ${'jumpToNextDiscussion'} | ${[]} | ${'a'}
+ ${'jumpToNextDiscussion'} | ${[]} | ${'e'}
+ ${'jumpToPreviousDiscussion'} | ${[]} | ${null}
+ ${'jumpToPreviousDiscussion'} | ${[]} | ${'e'}
+ ${'jumpToPreviousDiscussion'} | ${[]} | ${'c'}
+ `('$fn (args = $args, currentId = $currentId)', ({ fn, args, currentId }) => {
beforeEach(() => {
store.state.notes.currentDiscussionId = currentId;
});
@@ -130,125 +128,18 @@ describe('Discussion navigation mixin', () => {
await nextTick();
});
- it('expands discussion', () => {
- expect(expandDiscussion).toHaveBeenCalled();
- });
-
- it('scrolls to element', () => {
- expect(utils.scrollToElement).toHaveBeenCalled();
- });
- });
-
- describe('on `diffs` active tab', () => {
- beforeEach(async () => {
- window.mrTabs.currentAction = 'diffs';
- wrapper.vm[fn](...args);
-
+ it('expands discussion', async () => {
await nextTick();
- });
- it('sets current discussion', () => {
- expect(store.state.notes.currentDiscussionId).toEqual(expected);
- });
-
- it('expands discussion', () => {
expect(expandDiscussion).toHaveBeenCalled();
});
- it('scrolls when scrollToDiscussion is emitted', () => {
- expect(utils.scrollToElementWithContext).not.toHaveBeenCalled();
-
- eventHub.$emit('scrollToDiscussion');
-
- expect(utils.scrollToElementWithContext).toHaveBeenCalledWith(
- findDiscussion('ul.notes', expected),
- { behavior: 'auto', offset: 0 },
- );
- });
- });
-
- describe('on `other` active tab', () => {
- beforeEach(async () => {
- window.mrTabs.currentAction = 'other';
- wrapper.vm[fn](...args);
-
+ it('scrolls to element', async () => {
await nextTick();
- });
- it('sets current discussion', () => {
- expect(store.state.notes.currentDiscussionId).toEqual(expected);
- });
-
- it('does not expand discussion yet', () => {
- expect(expandDiscussion).not.toHaveBeenCalled();
- });
-
- it('shows mrTabs', () => {
- expect(window.mrTabs.tabShown).toHaveBeenCalledWith('show');
- });
-
- describe('when tab is changed', () => {
- beforeEach(() => {
- window.mrTabs.eventHub.$emit('MergeRequestTabChange');
-
- jest.runAllTimers();
- });
-
- it('expands discussion', () => {
- expect(expandDiscussion).toHaveBeenCalledWith(expect.anything(), {
- discussionId: expected,
- });
- });
-
- it('scrolls to discussion', () => {
- expect(utils.scrollToElement).toHaveBeenCalledWith(
- findDiscussion('div.discussion', expected),
- { behavior: 'auto', offset: 0 },
- );
- });
+ expect(utils.scrollToElement).toHaveBeenCalled();
});
});
});
-
- describe('virtual scrolling feature', () => {
- beforeEach(() => {
- jest.spyOn(store, 'dispatch');
-
- store.state.notes.currentDiscussionId = 'a';
- window.location.hash = 'test';
- });
-
- afterEach(() => {
- window.gon = {};
- window.location.hash = '';
- });
-
- it('resets location hash', async () => {
- wrapper.vm.jumpToNextDiscussion();
-
- await nextTick();
-
- expect(window.location.hash).toBe('');
- });
-
- it.each`
- tabValue
- ${'diffs'}
- ${'other'}
- `(
- 'calls scrollToFile with setHash as $hashValue when the tab is $tabValue',
- async ({ tabValue }) => {
- window.mrTabs.currentAction = tabValue;
-
- wrapper.vm.jumpToNextDiscussion();
-
- await nextTick();
-
- expect(store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', {
- path: 'test.js',
- });
- },
- );
- });
});
});
diff --git a/spec/frontend/notes/mock_data.js b/spec/frontend/notes/mock_data.js
index 9fa7166474a..286f2adc1d8 100644
--- a/spec/frontend/notes/mock_data.js
+++ b/spec/frontend/notes/mock_data.js
@@ -1,4 +1,5 @@
// Copied to ee/spec/frontend/notes/mock_data.js
+import { __ } from '~/locale';
export const notesDataMock = {
discussionsPath: '/gitlab-org/gitlab-foss/issues/26/discussions.json',
@@ -35,6 +36,7 @@ export const noteableDataMock = {
can_create_note: true,
can_update: true,
can_award_emoji: true,
+ can_create_confidential_note: true,
},
description: '',
due_date: null,
@@ -1292,3 +1294,18 @@ export const draftDiffDiscussion = {
file_path: 'lib/foo.rb',
isDraft: true,
};
+
+export const notesFilters = [
+ {
+ title: __('Show all activity'),
+ value: 0,
+ },
+ {
+ title: __('Show comments only'),
+ value: 1,
+ },
+ {
+ title: __('Show history only'),
+ value: 2,
+ },
+];
diff --git a/spec/frontend/notes/utils/get_notes_filter_data_spec.js b/spec/frontend/notes/utils/get_notes_filter_data_spec.js
new file mode 100644
index 00000000000..c3a8d3bc619
--- /dev/null
+++ b/spec/frontend/notes/utils/get_notes_filter_data_spec.js
@@ -0,0 +1,44 @@
+import { getNotesFilterData } from '~/notes/utils/get_notes_filter_data';
+import { notesFilters } from '../mock_data';
+
+// what: This is the format we expect the element attribute to be in
+// why: For readability, we make this clear by hardcoding the indecise instead of using `reduce`.
+const TEST_NOTES_FILTERS_ATTR = {
+ [notesFilters[0].title]: notesFilters[0].value,
+ [notesFilters[1].title]: notesFilters[1].value,
+ [notesFilters[2].title]: notesFilters[2].value,
+};
+
+describe('~/notes/utils/get_notes_filter_data', () => {
+ it.each([
+ {
+ desc: 'empty',
+ attributes: {},
+ expectation: {
+ notesFilters: [],
+ notesFilterValue: undefined,
+ },
+ },
+ {
+ desc: 'valid attributes',
+ attributes: {
+ 'data-notes-filters': JSON.stringify(TEST_NOTES_FILTERS_ATTR),
+ 'data-notes-filter-value': '1',
+ },
+ expectation: {
+ notesFilters,
+ notesFilterValue: 1,
+ },
+ },
+ ])('with $desc, parses data from element attributes', ({ attributes, expectation }) => {
+ const el = document.createElement('div');
+
+ Object.entries(attributes).forEach(([key, value]) => {
+ el.setAttribute(key, value);
+ });
+
+ const actual = getNotesFilterData(el);
+
+ expect(actual).toStrictEqual(expectation);
+ });
+});
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index 810049220ae..732dfdd42fb 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -2,7 +2,7 @@ import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitla
import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { timezones } from '~/monitoring/format_date';
@@ -52,7 +52,7 @@ describe('operation settings external dashboard component', () => {
}
axios.patch.mockReset();
refreshCurrentPage.mockReset();
- createFlash.mockReset();
+ createAlert.mockReset();
});
it('renders header text', () => {
@@ -208,7 +208,7 @@ describe('operation settings external dashboard component', () => {
await nextTick();
await jest.runAllTicks();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `There was an error saving your changes. ${message}`,
});
});
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
index 6fe3dabc603..849215e286b 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
@@ -8,8 +8,8 @@ import { defaultConfig, harborTagsList } from '../../mock_data';
describe('Harbor tag list row', () => {
let wrapper;
- const findListItem = () => wrapper.find(ListItem);
- const findClipboardButton = () => wrapper.find(ClipboardButton);
+ const findListItem = () => wrapper.findComponent(ListItem);
+ const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
const findByTestId = (testId) => wrapper.findByTestId(testId);
const $route = {
@@ -58,7 +58,7 @@ describe('Harbor tag list row', () => {
expect(findByTestId('name').text()).toBe(harborTagsList[0].name);
});
- describe(' clipboard button', () => {
+ describe('clipboard button', () => {
it('exists', () => {
expect(findClipboardButton().exists()).toBe(true);
});
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
index 6bcf6611d07..4c6b2b6daaa 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
@@ -8,9 +8,9 @@ import { defaultConfig, harborTagsResponse } from '../../mock_data';
describe('Harbor Tags List', () => {
let wrapper;
- const findTagsLoader = () => wrapper.find(TagsLoader);
+ const findTagsLoader = () => wrapper.findComponent(TagsLoader);
const findTagsListRows = () => wrapper.findAllComponents(TagsListRow);
- const findRegistryList = () => wrapper.find(RegistryList);
+ const findRegistryList = () => wrapper.findComponent(RegistryList);
const mountComponent = ({ propsData, config = defaultConfig }) => {
wrapper = shallowMount(TagsList, {
diff --git a/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js b/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
index 7e0f05e736b..10901c6ec1e 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
@@ -15,8 +15,8 @@ jest.mock('~/rest_api', () => ({
describe('Harbor Tags page', () => {
let wrapper;
- const findTagsHeader = () => wrapper.find(TagsHeader);
- const findTagsList = () => wrapper.find(TagsList);
+ const findTagsHeader = () => wrapper.findComponent(TagsHeader);
+ const findTagsList = () => wrapper.findComponent(TagsList);
const waitForHarborTagsRequest = async () => {
await waitForPromises();
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 31ab108558c..bb970336b94 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
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages_and_registries/infrastructure_registry/details/constants';
import {
fetchPackageVersions,
@@ -67,9 +67,9 @@ describe('Actions Package details store', () => {
[],
);
expect(Api.projectPackage).toHaveBeenCalledWith(packageEntity.project_id, packageEntity.id);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: FETCH_PACKAGE_VERSIONS_ERROR,
- type: 'warning',
+ variant: VARIANT_WARNING,
});
});
});
@@ -87,9 +87,9 @@ describe('Actions Package details store', () => {
Api.deleteProjectPackage = jest.fn().mockRejectedValue();
await testAction(deletePackage, undefined, { packageEntity }, [], []);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_PACKAGE_ERROR_MESSAGE,
- type: 'warning',
+ variant: VARIANT_WARNING,
});
});
});
@@ -112,18 +112,18 @@ describe('Actions Package details store', () => {
packageEntity.id,
fileId,
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
- type: 'success',
+ variant: VARIANT_SUCCESS,
});
});
it('should create flash on API error', async () => {
Api.deleteProjectPackageFile = jest.fn().mockRejectedValue();
await testAction(deletePackageFile, fileId, { packageEntity }, [], []);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
- type: 'warning',
+ variant: VARIANT_WARNING,
});
});
});
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
index 93d013bb458..aca6b0942cc 100644
--- 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
@@ -74,7 +74,7 @@ describe('Infrastructure Title', () => {
mountComponent({ ...exampleProps, count });
});
- it(exist ? 'exists' : 'does not exist', () => {
+ it(`${exist ? 'exists' : 'does not exist'}`, () => {
expect(findMetadataItem().exists()).toBe(exist);
});
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
index db1d3f3f633..dff95364d7d 100644
--- 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
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_INFO } 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';
@@ -222,9 +222,9 @@ describe('packages_list_app', () => {
it(`creates a flash if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
mountComponent();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_PACKAGE_SUCCESS_MESSAGE,
- type: 'notice',
+ variant: VARIANT_INFO,
});
});
@@ -238,7 +238,7 @@ describe('packages_list_app', () => {
setWindowLocation('?');
mountComponent();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(commonUtils.historyReplaceState).not.toHaveBeenCalled();
});
});
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
index d596f2dae33..36417eaf793 100644
--- 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
@@ -2,7 +2,7 @@ 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 { createAlert } 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';
@@ -107,7 +107,7 @@ describe('Actions Package list store', () => {
{ type: 'setLoading', payload: false },
],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('should force the terraform_module type when forceTerraform is true', async () => {
@@ -209,17 +209,17 @@ describe('Actions Package list store', () => {
{ type: 'setLoading', payload: false },
],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it.each`
property | actionPayload
${'_links'} | ${{}}
${'delete_api_path'} | ${{ _links: {} }}
- `('should reject and createFlash when $property is missing', ({ actionPayload }) => {
+ `('should reject and createAlert when $property is missing', ({ actionPayload }) => {
return testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DELETE_PACKAGE_ERROR_MESSAGE,
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
index 61923233d2e..047fa04947c 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
@@ -79,6 +79,18 @@ exports[`PackageTitle renders with tags 1`] = `
texttooltip=""
/>
</div>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <metadata-item-stub
+ data-testid="package-last-downloaded-at"
+ icon="download"
+ link=""
+ size="m"
+ text="Last downloaded Aug 17, 2021"
+ texttooltip=""
+ />
+ </div>
</div>
</div>
@@ -164,6 +176,18 @@ exports[`PackageTitle renders without tags 1`] = `
texttooltip=""
/>
</div>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <metadata-item-stub
+ data-testid="package-last-downloaded-at"
+ icon="download"
+ link=""
+ size="m"
+ text="Last downloaded Aug 17, 2021"
+ texttooltip=""
+ />
+ </div>
</div>
</div>
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 37416dcd4e7..1fda77f2aaa 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
@@ -49,6 +49,7 @@ describe('PackageTitle', () => {
const findPackageSize = () => wrapper.findByTestId('package-size');
const findPipelineProject = () => wrapper.findByTestId('pipeline-project');
const findPackageRef = () => wrapper.findByTestId('package-ref');
+ const findPackageLastDownloadedAt = () => wrapper.findByTestId('package-last-downloaded-at');
const findPackageTags = () => wrapper.findComponent(PackageTags);
const findPackageBadges = () => wrapper.findAllByTestId('tag-badge');
const findSubHeaderText = () => wrapper.findByTestId('sub-header');
@@ -227,4 +228,25 @@ describe('PackageTitle', () => {
});
});
});
+
+ describe('package last downloaded at', () => {
+ it('does not display the data if missing', async () => {
+ await createComponent({
+ ...packageData(),
+ lastDownloadedAt: null,
+ });
+
+ expect(findPackageLastDownloadedAt().exists()).toBe(false);
+ });
+
+ it('correctly shows the data if present', async () => {
+ await createComponent();
+
+ expect(findPackageLastDownloadedAt().props()).toMatchObject({
+ text: 'Last downloaded Aug 17, 2021',
+ icon: 'download',
+ size: 'm',
+ });
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
index 14a70def7d0..93c2196b210 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
@@ -104,22 +104,22 @@ describe('DeletePackage', () => {
expect(wrapper.emitted('end')).toEqual([[]]);
});
- it('does not call createFlash', async () => {
+ it('does not call createAlert', async () => {
createComponent();
await clickOnButtonAndWait(eventPayload);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
- it('calls createFlash with the success message when showSuccessAlert is true', async () => {
+ it('calls createAlert with the success message when showSuccessAlert is true', async () => {
createComponent({ showSuccessAlert: true });
await clickOnButtonAndWait(eventPayload);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DeletePackage.i18n.successMessage,
- type: 'success',
+ variant: VARIANT_SUCCESS,
});
});
});
@@ -141,14 +141,14 @@ describe('DeletePackage', () => {
expect(wrapper.emitted('end')).toEqual([[]]);
});
- it('calls createFlash with the error message', async () => {
+ it('calls createAlert with the error message', async () => {
createComponent({ showSuccessAlert: true });
await clickOnButtonAndWait(eventPayload);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: DeletePackage.i18n.errorMessage,
- type: 'warning',
+ variant: VARIANT_WARNING,
captureError: true,
error: expect.any(Error),
});
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 22236424e6a..c2b6fb734d6 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -127,6 +127,7 @@ export const packageData = (extend) => ({
version: '1.0.0',
createdAt: '2020-08-17T14:23:32Z',
updatedAt: '2020-08-17T14:23:32Z',
+ lastDownloadedAt: '2021-08-17T14:23:32Z',
status: 'DEFAULT',
mavenUrl: 'http://gdk.test:3000/api/v4/projects/1/packages/maven',
npmUrl: 'http://gdk.test:3000/api/v4/projects/1/packages/npm',
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
index 83158d1cc5e..a32e76a132e 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlBadge, GlTabs, GlTab } from '@gitlab/ui';
+import { GlEmptyState, GlBadge, GlTabs, GlTab, GlSprintf } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -6,7 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import PackagesApp from '~/packages_and_registries/package_registry/pages/details.vue';
@@ -86,11 +86,17 @@ describe('PackagesApp', () => {
PackageTitle,
DeletePackage,
GlModal: {
- template: '<div></div>',
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <p><slot></slot></p>
+ </div>
+ `,
methods: {
show: jest.fn(),
},
},
+ GlSprintf,
GlTabs,
GlTab,
},
@@ -149,7 +155,7 @@ describe('PackagesApp', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
}),
@@ -245,7 +251,9 @@ describe('PackagesApp', () => {
await findDeleteButton().trigger('click');
- expect(findDeleteModal().exists()).toBe(true);
+ expect(findDeleteModal().find('p').text()).toBe(
+ 'You are about to delete version 1.0.0 of @gitlab-org/package-15. Are you sure?',
+ );
});
describe('successful request', () => {
@@ -359,6 +367,12 @@ describe('PackagesApp', () => {
expect(showDeletePackageSpy).toHaveBeenCalled();
expect(showDeleteFileSpy).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(findDeleteModal().find('p').text()).toBe(
+ 'Deleting the last package asset will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
+ );
});
it('confirming on the modal sets the loading state', async () => {
@@ -383,7 +397,7 @@ describe('PackagesApp', () => {
await doDeleteFile();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
}),
@@ -399,7 +413,7 @@ describe('PackagesApp', () => {
await doDeleteFile();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
}),
@@ -416,7 +430,7 @@ describe('PackagesApp', () => {
await doDeleteFile();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
}),
@@ -468,7 +482,7 @@ describe('PackagesApp', () => {
await doDeleteFiles();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
}),
@@ -484,7 +498,7 @@ describe('PackagesApp', () => {
await doDeleteFiles();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILES_ERROR_MESSAGE,
}),
@@ -501,7 +515,7 @@ describe('PackagesApp', () => {
await doDeleteFiles();
- expect(createFlash).toHaveBeenCalledWith(
+ expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILES_ERROR_MESSAGE,
}),
@@ -533,6 +547,12 @@ describe('PackagesApp', () => {
findPackageFiles().vm.$emit('delete-files', packageFiles());
expect(showDeletePackageSpy).toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(findDeleteModal().find('p').text()).toBe(
+ 'Deleting all package assets will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
+ );
});
});
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
index 8b60f31512b..2bb99fb8e8f 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
@@ -19,6 +19,7 @@ import {
expirationPolicyPayload,
emptyExpirationPolicyPayload,
containerExpirationPolicyData,
+ nullExpirationPolicyPayload,
} from '../mock_data';
describe('Cleanup image tags project settings', () => {
@@ -98,15 +99,30 @@ describe('Cleanup image tags project settings', () => {
expect(findDescription().text()).toMatchInterpolatedText(CONTAINER_CLEANUP_POLICY_DESCRIPTION);
});
+ it('when loading does not render form or alert components', () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(),
+ });
+
+ expect(findFormComponent().exists()).toBe(false);
+ expect(findAlert().exists()).toBe(false);
+ });
+
describe('the form is disabled', () => {
- it('hides the form', () => {
- mountComponent();
+ it('hides the form', async () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
expect(findFormComponent().exists()).toBe(false);
});
- it('shows an alert', () => {
- mountComponent();
+ it('shows an alert', async () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
const text = findAlert().text();
expect(text).toContain(UNAVAILABLE_FEATURE_INTRO_TEXT);
@@ -114,8 +130,12 @@ describe('Cleanup image tags project settings', () => {
});
describe('an admin is visiting the page', () => {
- it('shows the admin part of the alert message', () => {
- mountComponent({ ...defaultProvidedValues, isAdmin: true });
+ it('shows the admin part of the alert message', async () => {
+ mountComponentWithApollo({
+ provide: { ...defaultProvidedValues, isAdmin: true },
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
const sprintf = findAlert().findComponent(GlSprintf);
expect(sprintf.text()).toBe('administration settings');
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
index 35baeaeac61..43484d26d76 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
@@ -16,7 +16,11 @@ import {
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
-import { expirationPolicyPayload, emptyExpirationPolicyPayload } from '../mock_data';
+import {
+ expirationPolicyPayload,
+ emptyExpirationPolicyPayload,
+ nullExpirationPolicyPayload,
+} from '../mock_data';
describe('Container expiration policy project settings', () => {
let wrapper;
@@ -78,15 +82,30 @@ describe('Container expiration policy project settings', () => {
expect(findButton().attributes('href')).toBe(defaultProvidedValues.cleanupSettingsPath);
});
+ it('when loading does not render form or alert components', () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(),
+ });
+
+ expect(findFormComponent().exists()).toBe(false);
+ expect(findAlert().exists()).toBe(false);
+ });
+
describe('the form is disabled', () => {
- it('the form is hidden', () => {
- mountComponent();
+ it('hides the form', async () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
expect(findFormComponent().exists()).toBe(false);
});
- it('shows an alert', () => {
- mountComponent();
+ it('shows an alert', async () => {
+ mountComponentWithApollo({
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
const text = findAlert().text();
expect(text).toContain(UNAVAILABLE_FEATURE_INTRO_TEXT);
@@ -94,8 +113,12 @@ describe('Container expiration policy project settings', () => {
});
describe('an admin is visiting the page', () => {
- it('shows the admin part of the alert message', () => {
- mountComponent({ ...defaultProvidedValues, isAdmin: true });
+ it('shows the admin part of the alert message', async () => {
+ mountComponentWithApollo({
+ provide: { ...defaultProvidedValues, isAdmin: true },
+ resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
+ });
+ await waitForPromises();
const sprintf = findAlert().findComponent(GlSprintf);
expect(sprintf.text()).toBe('administration settings');
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 0696144215c..3204ca01f99 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
@@ -29,6 +29,15 @@ export const emptyExpirationPolicyPayload = () => ({
},
});
+export const nullExpirationPolicyPayload = () => ({
+ data: {
+ project: {
+ id: '1',
+ containerExpirationPolicy: null,
+ },
+ },
+});
+
export const expirationPolicyMutationPayload = ({ override, errors = [] } = {}) => ({
data: {
updateContainerExpirationPolicy: {
diff --git a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
index ebf21c01324..17669331370 100644
--- a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
+++ b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
@@ -1,9 +1,10 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
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 stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
+import StopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
@@ -14,20 +15,23 @@ describe('stop_jobs_modal.vue', () => {
const props = {
url: `${TEST_HOST}/stop_jobs_modal.vue/stopAll`,
};
- let vm;
+ let wrapper;
- afterEach(() => {
- vm.$destroy();
+ beforeEach(() => {
+ wrapper = mount(StopJobsModal, { propsData: props });
});
- beforeEach(() => {
- const Component = Vue.extend(stopJobsModal);
- vm = mountComponent(Component, props);
+ afterEach(() => {
+ wrapper.destroy();
});
- describe('onSubmit', () => {
+ describe('on submit', () => {
it('stops jobs and redirects to overview page', async () => {
const responseURL = `${TEST_HOST}/stop_jobs_modal.vue/jobs`;
+ // TODO: We can't use axios-mock-adapter because our current version
+ // does not support responseURL
+ //
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/375308 for details
jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(props.url);
return Promise.resolve({
@@ -37,18 +41,28 @@ describe('stop_jobs_modal.vue', () => {
});
});
- await vm.onSubmit();
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await nextTick();
+
expect(redirectTo).toHaveBeenCalledWith(responseURL);
});
it('displays error if stopping jobs failed', async () => {
+ Vue.config.errorHandler = () => {}; // silencing thrown error
+
const dummyError = new Error('stopping jobs failed');
+ // TODO: We can't use axios-mock-adapter because our current version
+ // does not support responseURL
+ //
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/375308 for details
jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(props.url);
return Promise.reject(dummyError);
});
- await expect(vm.onSubmit()).rejects.toEqual(dummyError);
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await nextTick();
+
expect(redirectTo).not.toHaveBeenCalled();
});
});
diff --git a/spec/frontend/pages/import/fogbugz/new_user_map/components/user_select_spec.js b/spec/frontend/pages/import/fogbugz/new_user_map/components/user_select_spec.js
new file mode 100644
index 00000000000..c1e1545944b
--- /dev/null
+++ b/spec/frontend/pages/import/fogbugz/new_user_map/components/user_select_spec.js
@@ -0,0 +1,81 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlListbox } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import searchUsersQuery from '~/graphql_shared/queries/users_search_all.query.graphql';
+
+import createMockApollo from 'helpers/mock_apollo_helper';
+import UserSelect from '~/pages/import/fogbugz/new_user_map/components/user_select.vue';
+
+Vue.use(VueApollo);
+
+const USERS_RESPONSE = {
+ data: {
+ users: {
+ nodes: [
+ {
+ id: 'gid://gitlab/User/44',
+ avatarUrl: '/avatar1',
+ webUrl: '/reported_user_22',
+ name: 'Birgit Steuber',
+ username: 'reported_user_22',
+ __typename: 'UserCore',
+ },
+ {
+ id: 'gid://gitlab/User/43',
+ avatarUrl: '/avatar2',
+ webUrl: '/reported_user_21',
+ name: 'Luke Spinka',
+ username: 'reported_user_21',
+ __typename: 'UserCore',
+ },
+ ],
+ __typename: 'UserCoreConnection',
+ },
+ },
+};
+
+describe('fogbugz user select component', () => {
+ let wrapper;
+ const searchQueryHandlerSuccess = jest.fn().mockResolvedValue(USERS_RESPONSE);
+
+ const createComponent = (propsData = { name: 'demo' }) => {
+ const fakeApollo = createMockApollo([[searchUsersQuery, searchQueryHandlerSuccess]]);
+
+ wrapper = shallowMount(UserSelect, {
+ apolloProvider: fakeApollo,
+ propsData,
+ });
+ };
+
+ it('renders hidden input with name from props', () => {
+ const name = 'test';
+ createComponent({ name });
+ expect(wrapper.find('input').attributes('name')).toBe(name);
+ });
+
+ it('syncs input value with value emitted from listbox', async () => {
+ createComponent();
+
+ const id = 8;
+
+ wrapper.findComponent(GlListbox).vm.$emit('select', `gid://gitlab/User/${id}`);
+ await nextTick();
+
+ expect(wrapper.get('input').attributes('value')).toBe(id.toString());
+ });
+
+ it('filters users when search is performed in listbox', async () => {
+ createComponent();
+ jest.runOnlyPendingTimers();
+
+ wrapper.findComponent(GlListbox).vm.$emit('search', 'test');
+ await nextTick();
+ jest.runOnlyPendingTimers();
+
+ expect(searchQueryHandlerSuccess).toHaveBeenCalledWith({
+ first: expect.anything(),
+ search: 'test',
+ });
+ });
+});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
index f221a90da61..727c5164cdc 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
@@ -6,7 +6,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import { kebabCase } from 'lodash';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import * as urlUtility from '~/lib/utils/url_utility';
import ForkForm from '~/pages/projects/forks/new/components/fork_form.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -449,7 +449,7 @@ describe('ForkForm component', () => {
await submitForm();
expect(urlUtility.redirectTo).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while forking the project. Please try again.',
});
});
diff --git a/spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js b/spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
index 1a88aebae32..f6d3957115f 100644
--- a/spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
@@ -10,7 +10,7 @@ import { mount, shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import searchQuery from '~/pages/projects/forks/new/queries/search_forkable_namespaces.query.graphql';
import ProjectNamespace from '~/pages/projects/forks/new/components/project_namespace.vue';
@@ -167,7 +167,7 @@ describe('ProjectNamespace component', () => {
});
it('creates a flash message and captures the error', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while loading data. Please refresh the page to try again.',
captureError: true,
error: expect.any(Error),
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index 5b9c48f0d9b..f54d56c3af4 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -1,8 +1,7 @@
import $ from 'jquery';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import { formatUtcOffset, formatTimezone } from '~/lib/utils/datetime_utility';
import TimezoneDropdown, {
- formatUtcOffset,
- formatTimezone,
findTimezoneByIdentifier,
} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
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 b37d2f06191..0f947e84e0f 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -1,15 +1,12 @@
import { nextTick } from 'vue';
-import { GlAlert, GlButton, GlFormInput, GlFormGroup, GlSegmentedControl } from '@gitlab/ui';
+import { GlAlert, GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { mockTracking } from 'helpers/tracking_helper';
-import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import ContentEditor from '~/content_editor/components/content_editor.vue';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import WikiForm from '~/pages/shared/wikis/components/wiki_form.vue';
+import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import {
CONTENT_EDITOR_LOADED_ACTION,
SAVED_USING_CONTENT_EDITOR_ACTION,
@@ -18,8 +15,6 @@ import {
WIKI_FORMAT_UPDATED_ACTION,
} from '~/pages/shared/wikis/constants';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-
jest.mock('~/emoji');
describe('WikiForm', () => {
@@ -30,16 +25,12 @@ describe('WikiForm', () => {
const findForm = () => wrapper.find('form');
const findTitle = () => wrapper.find('#wiki_title');
const findFormat = () => wrapper.find('#wiki_format');
- const findContent = () => wrapper.find('#wiki_content');
const findMessage = () => wrapper.find('#wiki_message');
+ const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
const findSubmitButton = () => wrapper.findByTestId('wiki-submit-button');
const findCancelButton = () => wrapper.findByTestId('wiki-cancel-button');
- const findToggleEditingModeButton = () => wrapper.findByTestId('toggle-editing-mode-button');
const findTitleHelpLink = () => wrapper.findByText('Learn more.');
const findMarkdownHelpLink = () => wrapper.findByTestId('wiki-markdown-help-link');
- const findContentEditor = () => wrapper.findComponent(ContentEditor);
- const findClassicEditor = () => wrapper.findComponent(MarkdownField);
- const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
const setFormat = (value) => {
const format = findFormat();
@@ -53,13 +44,6 @@ describe('WikiForm', () => {
await nextTick();
};
- const dispatchBeforeUnload = () => {
- const e = new Event('beforeunload');
- jest.spyOn(e, 'preventDefault');
- window.dispatchEvent(e);
- return e;
- };
-
const pageInfoNew = {
persisted: false,
uploadsPath: '/project/path/-/wikis/attachments',
@@ -103,11 +87,8 @@ describe('WikiForm', () => {
},
},
stubs: {
- MarkdownField,
GlAlert,
GlButton,
- GlSegmentedControl,
- LocalStorageSync: stubComponent(LocalStorageSync),
GlFormInput,
GlFormGroup,
},
@@ -126,6 +107,22 @@ describe('WikiForm', () => {
wrapper = null;
});
+ it('displays markdown editor', () => {
+ createWrapper({ persisted: true });
+
+ expect(findMarkdownEditor().props()).toEqual(
+ expect.objectContaining({
+ value: pageInfoPersisted.content,
+ renderMarkdownPath: pageInfoPersisted.markdownPreviewPath,
+ markdownDocsPath: pageInfoPersisted.markdownHelpPath,
+ uploadsPath: pageInfoPersisted.uploadsPath,
+ initOnAutofocus: pageInfoPersisted.persisted,
+ formFieldId: 'wiki_content',
+ formFieldName: 'wiki[content]',
+ }),
+ );
+ });
+
it.each`
title | persisted | message
${'my page'} | ${false} | ${'Create my page'}
@@ -154,7 +151,7 @@ describe('WikiForm', () => {
it('does not trim page content by default', () => {
createWrapper({ persisted: true });
- expect(findContent().element.value).toBe(' My page content ');
+ expect(findMarkdownEditor().props().value).toBe(' My page content ');
});
it.each`
@@ -168,7 +165,9 @@ describe('WikiForm', () => {
await setFormat(format);
- expect(findClassicEditor().props('enablePreview')).toBe(enabled);
+ nextTick();
+
+ expect(findMarkdownEditor().props('enablePreview')).toBe(enabled);
});
it.each`
@@ -185,14 +184,6 @@ describe('WikiForm', () => {
expect(wrapper.text()).toContain(text);
});
- it('starts with no unload warning', () => {
- createWrapper();
-
- const e = dispatchBeforeUnload();
- expect(typeof e.returnValue).not.toBe('string');
- expect(e.preventDefault).not.toHaveBeenCalled();
- });
-
it.each`
persisted | titleHelpText | titleHelpLink
${true} | ${'You can move this page by adding the path to the beginning of the title.'} | ${'/help/user/project/wiki/index#move-a-wiki-page'}
@@ -219,15 +210,7 @@ describe('WikiForm', () => {
beforeEach(async () => {
createWrapper({ mountFn: mount, persisted: true });
- const input = findContent();
-
- await input.setValue(' Lorem ipsum dolar sit! ');
- });
-
- it('sets before unload warning', () => {
- const e = dispatchBeforeUnload();
-
- expect(e.preventDefault).toHaveBeenCalledTimes(1);
+ await findMarkdownEditor().vm.$emit('input', ' Lorem ipsum dolar sit! ');
});
describe('form submit', () => {
@@ -235,17 +218,12 @@ describe('WikiForm', () => {
await triggerFormSubmit();
});
- it('when form submitted, unsets before unload warning', () => {
- const e = dispatchBeforeUnload();
- expect(e.preventDefault).not.toHaveBeenCalled();
- });
-
it('triggers wiki format tracking event', () => {
expect(trackingSpy).toHaveBeenCalledTimes(1);
});
it('does not trim page content', () => {
- expect(findContent().element.value).toBe(' Lorem ipsum dolar sit! ');
+ expect(findMarkdownEditor().props().value).toBe(' Lorem ipsum dolar sit! ');
});
});
});
@@ -264,7 +242,7 @@ describe('WikiForm', () => {
createWrapper({ mountFn: mount });
await findTitle().setValue(title);
- await findContent().setValue(content);
+ await findMarkdownEditor().vm.$emit('input', content);
expect(findSubmitButton().props().disabled).toBe(disabledAttr);
},
@@ -296,208 +274,59 @@ describe('WikiForm', () => {
);
});
- describe('toggle editing mode control', () => {
- beforeEach(() => {
- createWrapper({ mountFn: mount });
- });
+ it.each`
+ format | enabled | action
+ ${'markdown'} | ${true} | ${'enables'}
+ ${'rdoc'} | ${false} | ${'disables'}
+ ${'asciidoc'} | ${false} | ${'disables'}
+ ${'org'} | ${false} | ${'disables'}
+ `('$action content editor when format is $format', async ({ format, enabled }) => {
+ createWrapper({ mountFn: mount });
- it.each`
- format | exists | action
- ${'markdown'} | ${true} | ${'displays'}
- ${'rdoc'} | ${false} | ${'hides'}
- ${'asciidoc'} | ${false} | ${'hides'}
- ${'org'} | ${false} | ${'hides'}
- `('$action toggle editing mode button when format is $format', async ({ format, exists }) => {
- await setFormat(format);
-
- expect(findToggleEditingModeButton().exists()).toBe(exists);
- });
+ setFormat(format);
- describe('when content editor is not active', () => {
- it('displays "Source" label in the toggle editing mode button', () => {
- expect(findToggleEditingModeButton().props().checked).toBe('source');
- });
+ await nextTick();
- describe('when clicking the toggle editing mode button', () => {
- beforeEach(async () => {
- await findToggleEditingModeButton().vm.$emit('input', 'richText');
- });
+ expect(findMarkdownEditor().props().enableContentEditor).toBe(enabled);
+ });
- it('hides the classic editor', () => {
- expect(findClassicEditor().exists()).toBe(false);
- });
+ describe('when markdown editor activates the content editor', () => {
+ beforeEach(async () => {
+ createWrapper({ mountFn: mount, persisted: true });
- it('shows the content editor', () => {
- expect(findContentEditor().exists()).toBe(true);
- });
- });
+ await findMarkdownEditor().vm.$emit('contentEditor');
});
- describe('markdown editor type persistance', () => {
- it('loads content editor by default if it is persisted in local storage', async () => {
- expect(findClassicEditor().exists()).toBe(true);
- expect(findContentEditor().exists()).toBe(false);
-
- // enable content editor
- await findLocalStorageSync().vm.$emit('input', 'richText');
-
- expect(findContentEditor().exists()).toBe(true);
- expect(findClassicEditor().exists()).toBe(false);
- });
+ it('disables the format dropdown', () => {
+ expect(findFormat().element.getAttribute('disabled')).toBeDefined();
});
- describe('when content editor is active', () => {
- beforeEach(() => {
- createWrapper();
- findToggleEditingModeButton().vm.$emit('input', 'richText');
- });
-
- it('displays "Edit Rich" label in the toggle editing mode button', () => {
- expect(findToggleEditingModeButton().props().checked).toBe('richText');
- });
-
- describe('when clicking the toggle editing mode button', () => {
- beforeEach(async () => {
- await findToggleEditingModeButton().vm.$emit('input', 'source');
- await nextTick();
- });
-
- it('hides the content editor', () => {
- expect(findContentEditor().exists()).toBe(false);
- });
-
- it('displays the classic editor', () => {
- expect(findClassicEditor().exists()).toBe(true);
- });
- });
-
- describe('when content editor is loading', () => {
- beforeEach(async () => {
- findContentEditor().vm.$emit('loading');
-
- await nextTick();
- });
-
- it('disables toggle editing mode button', () => {
- expect(findToggleEditingModeButton().attributes().disabled).toBe('true');
- });
-
- describe('when content editor loads successfully', () => {
- it('enables toggle editing mode button', async () => {
- findContentEditor().vm.$emit('loadingSuccess');
-
- await nextTick();
-
- expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined();
- });
- });
-
- describe('when content editor fails to load', () => {
- it('enables toggle editing mode button', async () => {
- findContentEditor().vm.$emit('loadingError');
-
- await nextTick();
-
- expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined();
- });
- });
+ it('sends tracking event when editor loads', async () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, CONTENT_EDITOR_LOADED_ACTION, {
+ label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
});
});
- });
-
- describe('wiki content editor', () => {
- describe('clicking "Edit rich text": editor fails to load', () => {
- beforeEach(async () => {
- createWrapper({ mountFn: mount });
- mock.onPost(/preview-markdown/).reply(400);
-
- await findToggleEditingModeButton().vm.$emit('input', 'richText');
-
- // try waiting for content editor to load (but it will never actually load)
- await waitForPromises();
- });
-
- it('disables the submit button', () => {
- expect(findSubmitButton().props('disabled')).toBe(true);
- });
-
- describe('toggling editing modes to the classic editor', () => {
- beforeEach(() => {
- return findToggleEditingModeButton().vm.$emit('input', 'source');
- });
- it('switches to classic editor', () => {
- expect(findContentEditor().exists()).toBe(false);
- expect(findClassicEditor().exists()).toBe(true);
- });
- });
- });
+ describe('when triggering form submit', () => {
+ const updatedMarkdown = 'hello **world**';
- describe('clicking "Edit rich text": editor loads successfully', () => {
beforeEach(async () => {
- createWrapper({ persisted: true, mountFn: mount });
-
- mock.onPost(/preview-markdown/).reply(200, { body: '<p>hello <strong>world</strong></p>' });
-
- await findToggleEditingModeButton().vm.$emit('input', 'richText');
- await waitForPromises();
- });
-
- it('shows the rich text editor when loading finishes', async () => {
- expect(findContentEditor().exists()).toBe(true);
+ findMarkdownEditor().vm.$emit('input', updatedMarkdown);
+ await triggerFormSubmit();
});
- it('sends tracking event when editor loads', async () => {
- expect(trackingSpy).toHaveBeenCalledWith(undefined, CONTENT_EDITOR_LOADED_ACTION, {
+ it('triggers tracking events on form submit', async () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, {
label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
});
- });
-
- it('disables the format dropdown', () => {
- expect(findFormat().element.getAttribute('disabled')).toBeDefined();
- });
- describe('when wiki content is updated', () => {
- const updatedMarkdown = 'hello **world**';
-
- beforeEach(() => {
- findContentEditor().vm.$emit('change', {
- empty: false,
- changed: true,
- markdown: updatedMarkdown,
- });
- });
-
- it('sets before unload warning', () => {
- const e = dispatchBeforeUnload();
- expect(e.preventDefault).toHaveBeenCalledTimes(1);
- });
-
- it('unsets before unload warning on form submit', async () => {
- await triggerFormSubmit();
-
- const e = dispatchBeforeUnload();
- expect(e.preventDefault).not.toHaveBeenCalled();
- });
-
- it('triggers tracking events on form submit', async () => {
- await triggerFormSubmit();
- expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, {
- label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
- });
-
- expect(trackingSpy).toHaveBeenCalledWith(undefined, WIKI_FORMAT_UPDATED_ACTION, {
- label: WIKI_FORMAT_LABEL,
- extra: {
- value: findFormat().element.value,
- old_format: pageInfoPersisted.format,
- project_path: pageInfoPersisted.path,
- },
- });
- });
-
- it('sets content field to the content editor updated markdown', async () => {
- expect(findContent().element.value).toBe(updatedMarkdown);
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, WIKI_FORMAT_UPDATED_ACTION, {
+ label: WIKI_FORMAT_LABEL,
+ extra: {
+ value: findFormat().element.value,
+ old_format: pageInfoPersisted.format,
+ project_path: pageInfoPersisted.path,
+ },
});
});
});
diff --git a/spec/frontend/pdf/page_spec.js b/spec/frontend/pdf/page_spec.js
index 07a7f1bb2ff..4cf83a3252d 100644
--- a/spec/frontend/pdf/page_spec.js
+++ b/spec/frontend/pdf/page_spec.js
@@ -1,17 +1,16 @@
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import PageComponent from '~/pdf/page/index.vue';
jest.mock('pdfjs-dist/webpack', () => {
- return { default: jest.requireActual('pdfjs-dist/build/pdf') };
+ return { default: jest.requireActual('pdfjs-dist/legacy/build/pdf') };
});
describe('Page component', () => {
- const Component = Vue.extend(PageComponent);
- let vm;
+ let wrapper;
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders the page when mounting', async () => {
@@ -20,16 +19,18 @@ describe('Page component', () => {
getViewport: jest.fn().mockReturnValue({}),
};
- vm = mountComponent(Component, {
- page: testPage,
- number: 1,
+ wrapper = mount(PageComponent, {
+ propsData: {
+ page: testPage,
+ number: 1,
+ },
});
- expect(vm.rendering).toBe(true);
-
await nextTick();
- expect(testPage.render).toHaveBeenCalledWith(vm.renderContext);
- expect(vm.rendering).toBe(false);
+ expect(testPage.render).toHaveBeenCalledWith({
+ canvasContext: wrapper.find('canvas').element.getContext('2d'),
+ viewport: testPage.getViewport(),
+ });
});
});
diff --git a/spec/frontend/performance_bar/components/request_warning_spec.js b/spec/frontend/performance_bar/components/request_warning_spec.js
index d558c7b018a..9dd8ea9f933 100644
--- a/spec/frontend/performance_bar/components/request_warning_spec.js
+++ b/spec/frontend/performance_bar/components/request_warning_spec.js
@@ -2,14 +2,21 @@ import { shallowMount } from '@vue/test-utils';
import RequestWarning from '~/performance_bar/components/request_warning.vue';
describe('request warning', () => {
+ let wrapper;
const htmlId = 'request-123';
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
describe('when the request has warnings', () => {
- const wrapper = shallowMount(RequestWarning, {
- propsData: {
- htmlId,
- warnings: ['gitaly calls: 30 over 10', 'gitaly duration: 1500 over 1000'],
- },
+ beforeEach(() => {
+ wrapper = shallowMount(RequestWarning, {
+ propsData: {
+ htmlId,
+ warnings: ['gitaly calls: 30 over 10', 'gitaly duration: 1500 over 1000'],
+ },
+ });
});
it('adds a warning emoji with the correct ID', () => {
@@ -19,11 +26,13 @@ describe('request warning', () => {
});
describe('when the request does not have warnings', () => {
- const wrapper = shallowMount(RequestWarning, {
- propsData: {
- htmlId,
- warnings: [],
- },
+ beforeEach(() => {
+ wrapper = shallowMount(RequestWarning, {
+ propsData: {
+ htmlId,
+ warnings: [],
+ },
+ });
});
it('does nothing', () => {
diff --git a/spec/frontend/persistent_user_callout_spec.js b/spec/frontend/persistent_user_callout_spec.js
index 9cd5bb9e9a1..c9574208900 100644
--- a/spec/frontend/persistent_user_callout_spec.js
+++ b/spec/frontend/persistent_user_callout_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import PersistentUserCallout from '~/persistent_user_callout';
@@ -108,7 +108,7 @@ describe('PersistentUserCallout', () => {
await waitForPromises();
expect(persistentUserCallout.container.remove).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while dismissing the alert. Refresh the page and try again.',
});
});
@@ -214,7 +214,7 @@ describe('PersistentUserCallout', () => {
await waitForPromises();
expect(window.location.assign).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message:
'An error occurred while acknowledging the notification. Refresh the page and try again.',
});
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 8f6f4d8cff9..f0347ad19ac 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
@@ -360,7 +360,7 @@ describe('Pipeline editor branch switcher', () => {
});
describe('loading icon', () => {
- test.each`
+ it.each`
isQueryLoading | isRendered
${true} | ${true}
${false} | ${false}
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
index 8e0a73b6e7c..c76c3460e99 100644
--- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
@@ -7,6 +7,7 @@ describe('Pipeline editor empty state', () => {
let wrapper;
const defaultProvide = {
emptyStateIllustrationPath: 'my/svg/path',
+ usesExternalConfig: false,
};
const createComponent = ({ provide } = {}) => {
@@ -18,6 +19,7 @@ describe('Pipeline editor empty state', () => {
const findFileNav = () => wrapper.findComponent(PipelineEditorFileNav);
const findSvgImage = () => wrapper.find('img');
const findTitle = () => wrapper.find('h1');
+ const findExternalCiInstructions = () => wrapper.find('p');
const findConfirmButton = () => wrapper.findComponent(GlButton);
const findDescription = () => wrapper.findComponent(GlSprintf);
@@ -25,7 +27,33 @@ describe('Pipeline editor empty state', () => {
wrapper.destroy();
});
- describe('template', () => {
+ describe('when project uses an external CI config', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: { usesExternalConfig: true },
+ });
+ });
+
+ it('renders an svg image', () => {
+ expect(findSvgImage().exists()).toBe(true);
+ });
+
+ it('renders the correct title and instructions', () => {
+ expect(findTitle().exists()).toBe(true);
+ expect(findExternalCiInstructions().exists()).toBe(true);
+
+ expect(findExternalCiInstructions().html()).toContain(
+ wrapper.vm.$options.i18n.externalCiInstructions,
+ );
+ expect(findTitle().text()).toBe(wrapper.vm.$options.i18n.externalCiNote);
+ });
+
+ it('does not render the CTA button', () => {
+ expect(findConfirmButton().exists()).toBe(false);
+ });
+ });
+
+ describe('when project uses an accessible CI config', () => {
beforeEach(() => {
createComponent();
});
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 1989f23a415..9fe1536d3f5 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -55,11 +55,12 @@ jest.mock('~/lib/utils/url_utility', () => ({
const localVue = createLocalVue();
localVue.use(VueApollo);
-const mockProvide = {
+const defaultProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
newMergeRequestPath: mockNewMergeRequestPath,
projectFullPath: mockProjectFullPath,
+ usesExternalConfig: false,
};
describe('Pipeline editor app component', () => {
@@ -79,7 +80,7 @@ describe('Pipeline editor app component', () => {
stubs = {},
} = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
- provide: { ...mockProvide, ...provide },
+ provide: { ...defaultProvide, ...provide },
stubs,
mocks: {
$apollo: {
@@ -229,6 +230,22 @@ describe('Pipeline editor app component', () => {
mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
});
+ describe('when project uses an external CI config file', () => {
+ beforeEach(async () => {
+ await createComponentWithApollo({
+ provide: {
+ usesExternalConfig: true,
+ },
+ });
+ });
+
+ it('shows an empty state and does not show editor home component', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findAlert().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(false);
+ });
+ });
+
describe('when file exists', () => {
beforeEach(async () => {
await createComponentWithApollo();
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
index e317d1ddcc2..2b06660c4b3 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
@@ -149,20 +149,20 @@ describe('Pipeline editor home wrapper', () => {
await nextTick();
- expect(findCommitSection().exists()).toBe(shouldShow);
+ expect(findCommitSection().isVisible()).toBe(shouldShow);
},
);
it('shows the commit form again when coming back to the create tab', async () => {
- expect(findCommitSection().exists()).toBe(true);
+ expect(findCommitSection().isVisible()).toBe(true);
findPipelineEditorTabs().vm.$emit('set-current-tab', MERGED_TAB);
await nextTick();
- expect(findCommitSection().exists()).toBe(false);
+ expect(findCommitSection().isVisible()).toBe(false);
findPipelineEditorTabs().vm.$emit('set-current-tab', CREATE_TAB);
await nextTick();
- expect(findCommitSection().exists()).toBe(true);
+ expect(findCommitSection().isVisible()).toBe(true);
});
describe('rendering with tab params', () => {
@@ -178,7 +178,7 @@ describe('Pipeline editor home wrapper', () => {
setWindowLocation(`https://gitlab.test/ci/editor/?tab=${TABS_INDEX[tab]}`);
await createComponent({ stubs: { PipelineEditorTabs } });
- expect(findCommitSection().exists()).toBe(shouldShow);
+ expect(findCommitSection().isVisible()).toBe(shouldShow);
},
);
});
diff --git a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
index 5ce29bd6c5d..3e699b93fd3 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,72 +1,101 @@
-import { GlForm, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlForm, GlDropdownItem, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
import CreditCardValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
import { redirectTo } from '~/lib/utils/url_utility';
import PipelineNewForm from '~/pipeline_new/components/pipeline_new_form.vue';
+import ciConfigVariablesQuery from '~/pipeline_new/graphql/queries/ci_config_variables.graphql';
+import { resolvers } from '~/pipeline_new/graphql/resolvers';
import RefsDropdown from '~/pipeline_new/components/refs_dropdown.vue';
import {
+ mockCreditCardValidationRequiredError,
+ mockCiConfigVariablesResponse,
+ mockCiConfigVariablesResponseWithoutDesc,
+ mockEmptyCiConfigVariablesResponse,
+ mockError,
mockQueryParams,
mockPostParams,
mockProjectId,
- mockError,
mockRefs,
- mockCreditCardValidationRequiredError,
+ mockYamlVariables,
} from '../mock_data';
+Vue.use(VueApollo);
+
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
}));
const projectRefsEndpoint = '/root/project/refs';
const pipelinesPath = '/root/project/-/pipelines';
-const configVariablesPath = '/root/project/-/pipelines/config_variables';
+const projectPath = '/root/project/-/pipelines/config_variables';
const newPipelinePostResponse = { id: 1 };
const defaultBranch = 'main';
describe('Pipeline New Form', () => {
let wrapper;
let mock;
+ let mockApollo;
+ let mockCiConfigVariables;
let dummySubmitEvent;
const findForm = () => wrapper.findComponent(GlForm);
const findRefsDropdown = () => wrapper.findComponent(RefsDropdown);
- const findSubmitButton = () => wrapper.find('[data-testid="run_pipeline_button"]');
- const findVariableRows = () => wrapper.findAll('[data-testid="ci-variable-row"]');
- const findRemoveIcons = () => wrapper.findAll('[data-testid="remove-ci-variable-row"]');
- const findDropdowns = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-type"]');
- const findKeyInputs = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-key"]');
- const findValueInputs = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-value"]');
- const findErrorAlert = () => wrapper.find('[data-testid="run-pipeline-error-alert"]');
- const findWarningAlert = () => wrapper.find('[data-testid="run-pipeline-warning-alert"]');
+ const findSubmitButton = () => wrapper.findByTestId('run_pipeline_button');
+ const findVariableRows = () => wrapper.findAllByTestId('ci-variable-row');
+ const findRemoveIcons = () => wrapper.findAllByTestId('remove-ci-variable-row');
+ const findVariableTypes = () => wrapper.findAllByTestId('pipeline-form-ci-variable-type');
+ const findKeyInputs = () => wrapper.findAllByTestId('pipeline-form-ci-variable-key');
+ const findValueInputs = () => wrapper.findAllByTestId('pipeline-form-ci-variable-value');
+ const findValueDropdowns = () =>
+ wrapper.findAllByTestId('pipeline-form-ci-variable-value-dropdown');
+ const findValueDropdownItems = (dropdown) => dropdown.findAllComponents(GlDropdownItem);
+ const findErrorAlert = () => wrapper.findByTestId('run-pipeline-error-alert');
+ const findWarningAlert = () => wrapper.findByTestId('run-pipeline-warning-alert');
const findWarningAlertSummary = () => findWarningAlert().findComponent(GlSprintf);
- const findWarnings = () => wrapper.findAll('[data-testid="run-pipeline-warning"]');
+ const findWarnings = () => wrapper.findAllByTestId('run-pipeline-warning');
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findCCAlert = () => wrapper.findComponent(CreditCardValidationRequiredAlert);
const getFormPostParams = () => JSON.parse(mock.history.post[0].data);
- const selectBranch = (branch) => {
+ const selectBranch = async (branch) => {
// Select a branch in the dropdown
findRefsDropdown().vm.$emit('input', {
shortName: branch,
fullName: `refs/heads/${branch}`,
});
+
+ await waitForPromises();
+ };
+
+ const changeKeyInputValue = async (keyInputIndex, value) => {
+ const input = findKeyInputs().at(keyInputIndex);
+ input.element.value = value;
+ input.trigger('change');
+
+ await nextTick();
};
- const createComponent = (props = {}, method = shallowMount) => {
+ const createComponentWithApollo = ({ method = shallowMountExtended, props = {} } = {}) => {
+ const handlers = [[ciConfigVariablesQuery, mockCiConfigVariables]];
+ mockApollo = createMockApollo(handlers, resolvers);
+
wrapper = method(PipelineNewForm, {
+ apolloProvider: mockApollo,
provide: {
projectRefsEndpoint,
},
propsData: {
projectId: mockProjectId,
pipelinesPath,
- configVariablesPath,
+ projectPath,
defaultBranch,
refParam: defaultBranch,
settingsLink: '',
@@ -78,7 +107,7 @@ describe('Pipeline New Form', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {});
+ mockCiConfigVariables = jest.fn();
mock.onGet(projectRefsEndpoint).reply(httpStatusCodes.OK, mockRefs);
dummySubmitEvent = {
@@ -87,24 +116,20 @@ describe('Pipeline New Form', () => {
});
afterEach(() => {
- wrapper.destroy();
- wrapper = null;
-
mock.restore();
+ wrapper.destroy();
});
describe('Form', () => {
beforeEach(async () => {
- createComponent(mockQueryParams, mount);
-
- mock.onPost(pipelinesPath).reply(httpStatusCodes.OK, newPipelinePostResponse);
-
+ mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
+ createComponentWithApollo({ props: mockQueryParams, method: mountExtended });
await waitForPromises();
});
it('displays the correct values for the provided query params', async () => {
- expect(findDropdowns().at(0).props('text')).toBe('Variable');
- expect(findDropdowns().at(1).props('text')).toBe('File');
+ expect(findVariableTypes().at(0).props('text')).toBe('Variable');
+ expect(findVariableTypes().at(1).props('text')).toBe('File');
expect(findRefsDropdown().props('value')).toEqual({ shortName: 'tag-1' });
expect(findVariableRows()).toHaveLength(3);
});
@@ -117,7 +142,7 @@ describe('Pipeline New Form', () => {
it('displays an empty variable for the user to fill out', async () => {
expect(findKeyInputs().at(2).element.value).toBe('');
expect(findValueInputs().at(2).element.value).toBe('');
- expect(findDropdowns().at(2).props('text')).toBe('Variable');
+ expect(findVariableTypes().at(2).props('text')).toBe('Variable');
});
it('does not display remove icon for last row', () => {
@@ -147,13 +172,12 @@ describe('Pipeline New Form', () => {
describe('Pipeline creation', () => {
beforeEach(async () => {
+ mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
mock.onPost(pipelinesPath).reply(httpStatusCodes.OK, newPipelinePostResponse);
-
- await waitForPromises();
});
it('does not submit the native HTML form', async () => {
- createComponent();
+ createComponentWithApollo();
findForm().vm.$emit('submit', dummySubmitEvent);
@@ -161,7 +185,7 @@ describe('Pipeline New Form', () => {
});
it('disables the submit button immediately after submitting', async () => {
- createComponent();
+ createComponentWithApollo();
expect(findSubmitButton().props('disabled')).toBe(false);
@@ -172,7 +196,7 @@ describe('Pipeline New Form', () => {
});
it('creates pipeline with full ref and variables', async () => {
- createComponent();
+ createComponentWithApollo();
findForm().vm.$emit('submit', dummySubmitEvent);
await waitForPromises();
@@ -182,7 +206,7 @@ describe('Pipeline New Form', () => {
});
it('creates a pipeline with short ref and variables from the query params', async () => {
- createComponent(mockQueryParams);
+ createComponentWithApollo({ props: mockQueryParams });
await waitForPromises();
@@ -197,64 +221,51 @@ describe('Pipeline New Form', () => {
describe('When the ref has been changed', () => {
beforeEach(async () => {
- createComponent({}, mount);
+ mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
+ createComponentWithApollo({ method: mountExtended });
await waitForPromises();
});
- it('variables persist between ref changes', async () => {
- selectBranch('main');
-
- await waitForPromises();
- const mainInput = findKeyInputs().at(0);
- mainInput.element.value = 'build_var';
- mainInput.trigger('change');
+ it('variables persist between ref changes', async () => {
+ await selectBranch('main');
+ await changeKeyInputValue(0, 'build_var');
- await nextTick();
+ await selectBranch('branch-1');
+ await changeKeyInputValue(0, 'deploy_var');
- selectBranch('branch-1');
+ await selectBranch('main');
- await waitForPromises();
+ expect(findKeyInputs().at(0).element.value).toBe('build_var');
+ expect(findVariableRows().length).toBe(2);
- const branchOneInput = findKeyInputs().at(0);
- branchOneInput.element.value = 'deploy_var';
- branchOneInput.trigger('change');
+ await selectBranch('branch-1');
- await nextTick();
+ expect(findKeyInputs().at(0).element.value).toBe('deploy_var');
+ expect(findVariableRows().length).toBe(2);
+ });
- selectBranch('main');
+ it('skips query call when form variables are already cached', async () => {
+ await selectBranch('main');
+ await changeKeyInputValue(0, 'build_var');
- await waitForPromises();
+ expect(mockCiConfigVariables).toHaveBeenCalledTimes(1);
- expect(findKeyInputs().at(0).element.value).toBe('build_var');
- expect(findVariableRows().length).toBe(2);
+ await selectBranch('branch-1');
- selectBranch('branch-1');
+ expect(mockCiConfigVariables).toHaveBeenCalledTimes(2);
- await waitForPromises();
+ // no additional call since `main` form values have been cached
+ await selectBranch('main');
- expect(findKeyInputs().at(0).element.value).toBe('deploy_var');
- expect(findVariableRows().length).toBe(2);
+ expect(mockCiConfigVariables).toHaveBeenCalledTimes(2);
});
});
describe('when yml defines a variable', () => {
- const mockYmlKey = 'yml_var';
- const mockYmlValue = 'yml_var_val';
- const mockYmlMultiLineValue = `A value
- with multiple
- lines`;
- const mockYmlDesc = 'A var from yml.';
-
it('loading icon is shown when content is requested and hidden when received', async () => {
- createComponent(mockQueryParams, mount);
-
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
- [mockYmlKey]: {
- value: mockYmlValue,
- description: mockYmlDesc,
- },
- });
+ mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
+ createComponentWithApollo({ props: mockQueryParams, method: mountExtended });
expect(findLoadingIcon().exists()).toBe(true);
@@ -263,51 +274,62 @@ describe('Pipeline New Form', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
- it('multi-line strings are added to the value field without removing line breaks', async () => {
- createComponent(mockQueryParams, mount);
+ describe('with different predefined values', () => {
+ beforeEach(async () => {
+ mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponse);
+ createComponentWithApollo({ method: mountExtended });
+ await waitForPromises();
+ });
+
+ it('multi-line strings are added to the value field without removing line breaks', () => {
+ expect(findValueInputs().at(1).element.value).toBe(mockYamlVariables[1].value);
+ });
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
- [mockYmlKey]: {
- value: mockYmlMultiLineValue,
- description: mockYmlDesc,
- },
+ it('multiple predefined values are rendered as a dropdown', () => {
+ const dropdown = findValueDropdowns().at(0);
+ const dropdownItems = findValueDropdownItems(dropdown);
+ const { valueOptions } = mockYamlVariables[2];
+
+ expect(dropdownItems.at(0).text()).toBe(valueOptions[0]);
+ expect(dropdownItems.at(1).text()).toBe(valueOptions[1]);
+ expect(dropdownItems.at(2).text()).toBe(valueOptions[2]);
});
- await waitForPromises();
+ it('variables with multiple predefined values sets the first option as the default', () => {
+ const dropdown = findValueDropdowns().at(0);
+ const { valueOptions } = mockYamlVariables[2];
- expect(findValueInputs().at(0).element.value).toBe(mockYmlMultiLineValue);
+ expect(dropdown.props('text')).toBe(valueOptions[0]);
+ });
});
describe('with description', () => {
beforeEach(async () => {
- createComponent(mockQueryParams, mount);
-
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
- [mockYmlKey]: {
- value: mockYmlValue,
- description: mockYmlDesc,
- },
- });
-
+ mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponse);
+ createComponentWithApollo({ props: mockQueryParams, method: mountExtended });
await waitForPromises();
});
it('displays all the variables', async () => {
- expect(findVariableRows()).toHaveLength(4);
+ expect(findVariableRows()).toHaveLength(6);
});
it('displays a variable from yml', () => {
- expect(findKeyInputs().at(0).element.value).toBe(mockYmlKey);
- expect(findValueInputs().at(0).element.value).toBe(mockYmlValue);
+ expect(findKeyInputs().at(0).element.value).toBe(mockYamlVariables[0].key);
+ expect(findValueInputs().at(0).element.value).toBe(mockYamlVariables[0].value);
});
it('displays a variable from provided query params', () => {
- expect(findKeyInputs().at(1).element.value).toBe('test_var');
- expect(findValueInputs().at(1).element.value).toBe('test_var_val');
+ expect(findKeyInputs().at(3).element.value).toBe(
+ Object.keys(mockQueryParams.variableParams)[0],
+ );
+ expect(findValueInputs().at(3).element.value).toBe(
+ Object.values(mockQueryParams.fileParams)[0],
+ );
});
it('adds a description to the first variable from yml', () => {
- expect(findVariableRows().at(0).text()).toContain(mockYmlDesc);
+ expect(findVariableRows().at(0).text()).toContain(mockYamlVariables[0].description);
});
it('removes the description when a variable key changes', async () => {
@@ -316,39 +338,27 @@ describe('Pipeline New Form', () => {
await nextTick();
- expect(findVariableRows().at(0).text()).not.toContain(mockYmlDesc);
+ expect(findVariableRows().at(0).text()).not.toContain(mockYamlVariables[0].description);
});
});
describe('without description', () => {
beforeEach(async () => {
- createComponent(mockQueryParams, mount);
-
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
- [mockYmlKey]: {
- value: mockYmlValue,
- description: null,
- },
- yml_var2: {
- value: 'yml_var2_val',
- },
- yml_var3: {
- description: '',
- },
- });
-
+ mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponseWithoutDesc);
+ createComponentWithApollo({ method: mountExtended });
await waitForPromises();
});
- it('displays all the variables', async () => {
- expect(findVariableRows()).toHaveLength(3);
+ it('displays variables with description only', async () => {
+ expect(findVariableRows()).toHaveLength(2); // extra empty variable is added at the end
});
});
});
describe('Form errors and warnings', () => {
beforeEach(() => {
- createComponent();
+ mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
+ createComponentWithApollo();
});
describe('when the refs cannot be loaded', () => {
diff --git a/spec/frontend/pipeline_new/mock_data.js b/spec/frontend/pipeline_new/mock_data.js
index e99684ff417..e95a65171fc 100644
--- a/spec/frontend/pipeline_new/mock_data.js
+++ b/spec/frontend/pipeline_new/mock_data.js
@@ -65,3 +65,62 @@ export const mockVariables = [
},
{ uniqueId: 'var-refs/heads/main4', variable_type: 'env_var', key: '', value: '' },
];
+
+export const mockYamlVariables = [
+ {
+ description: 'This is a variable with a value.',
+ key: 'VAR_WITH_VALUE',
+ value: 'test_value',
+ valueOptions: null,
+ },
+ {
+ description: 'This is a variable with a multi-line value.',
+ key: 'VAR_WITH_MULTILINE',
+ value: `this is
+ a multiline value`,
+ valueOptions: null,
+ },
+ {
+ description: 'This is a variable with predefined values.',
+ key: 'VAR_WITH_OPTIONS',
+ value: 'development',
+ valueOptions: ['development', 'staging', 'production'],
+ },
+];
+
+export const mockYamlVariablesWithoutDesc = [
+ {
+ description: 'This is a variable with a value.',
+ key: 'VAR_WITH_VALUE',
+ value: 'test_value',
+ valueOptions: null,
+ },
+ {
+ description: null,
+ key: 'VAR_WITH_MULTILINE',
+ value: `this is
+ a multiline value`,
+ valueOptions: null,
+ },
+ {
+ description: null,
+ key: 'VAR_WITH_OPTIONS',
+ value: 'development',
+ valueOptions: ['development', 'staging', 'production'],
+ },
+];
+
+export const mockCiConfigVariablesQueryResponse = (ciConfigVariables) => ({
+ data: {
+ project: {
+ id: 1,
+ ciConfigVariables,
+ },
+ },
+});
+
+export const mockCiConfigVariablesResponse = mockCiConfigVariablesQueryResponse(mockYamlVariables);
+export const mockEmptyCiConfigVariablesResponse = mockCiConfigVariablesQueryResponse([]);
+export const mockCiConfigVariablesResponseWithoutDesc = mockCiConfigVariablesQueryResponse(
+ mockYamlVariablesWithoutDesc,
+);
diff --git a/spec/frontend/pipeline_schedules/components/pipeline_schedules_form_spec.js b/spec/frontend/pipeline_schedules/components/pipeline_schedules_form_spec.js
new file mode 100644
index 00000000000..4b5a9611251
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/pipeline_schedules_form_spec.js
@@ -0,0 +1,25 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlForm } from '@gitlab/ui';
+import PipelineSchedulesForm from '~/pipeline_schedules/components/pipeline_schedules_form.vue';
+
+describe('Pipeline schedules form', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(PipelineSchedulesForm);
+ };
+
+ const findForm = () => wrapper.findComponent(GlForm);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays form', () => {
+ expect(findForm().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js b/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js
new file mode 100644
index 00000000000..cce8f480928
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/pipeline_schedules_spec.js
@@ -0,0 +1,161 @@
+import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui';
+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 PipelineSchedules from '~/pipeline_schedules/components/pipeline_schedules.vue';
+import PipelineSchedulesTable from '~/pipeline_schedules/components/table/pipeline_schedules_table.vue';
+import deletePipelineScheduleMutation from '~/pipeline_schedules/graphql/mutations/delete_pipeline_schedule.mutation.graphql';
+import getPipelineSchedulesQuery from '~/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql';
+import {
+ mockGetPipelineSchedulesGraphQLResponse,
+ mockPipelineScheduleNodes,
+ deleteMutationResponse,
+} from '../mock_data';
+
+Vue.use(VueApollo);
+
+describe('Pipeline schedules app', () => {
+ let wrapper;
+
+ const successHandler = jest.fn().mockResolvedValue(mockGetPipelineSchedulesGraphQLResponse);
+ const failedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+
+ const deleteMutationHandlerSuccess = jest.fn().mockResolvedValue(deleteMutationResponse);
+ const deleteMutationHandlerFailed = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+
+ const createMockApolloProvider = (
+ requestHandlers = [[getPipelineSchedulesQuery, successHandler]],
+ ) => {
+ return createMockApollo(requestHandlers);
+ };
+
+ const createComponent = (requestHandlers) => {
+ wrapper = shallowMount(PipelineSchedules, {
+ provide: {
+ fullPath: 'gitlab-org/gitlab',
+ },
+ apolloProvider: createMockApolloProvider(requestHandlers),
+ });
+ };
+
+ const findTable = () => wrapper.findComponent(PipelineSchedulesTable);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findModal = () => wrapper.findComponent(GlModal);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays table', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findTable().exists()).toBe(true);
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('fetches query and passes an array of pipeline schedules', async () => {
+ createComponent();
+
+ expect(successHandler).toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(findTable().props('schedules')).toEqual(mockPipelineScheduleNodes);
+ });
+
+ it('handles loading state', async () => {
+ createComponent();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ await waitForPromises();
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('shows query error alert', async () => {
+ createComponent([[getPipelineSchedulesQuery, failedHandler]]);
+
+ await waitForPromises();
+
+ expect(findAlert().text()).toBe('There was a problem fetching pipeline schedules.');
+ });
+
+ it('shows delete mutation error alert', async () => {
+ createComponent([
+ [getPipelineSchedulesQuery, successHandler],
+ [deletePipelineScheduleMutation, deleteMutationHandlerFailed],
+ ]);
+
+ await waitForPromises();
+
+ findModal().vm.$emit('primary');
+
+ await waitForPromises();
+
+ expect(findAlert().text()).toBe('There was a problem deleting the pipeline schedule.');
+ });
+
+ it('deletes pipeline schedule and refetches query', async () => {
+ createComponent([
+ [getPipelineSchedulesQuery, successHandler],
+ [deletePipelineScheduleMutation, deleteMutationHandlerSuccess],
+ ]);
+
+ jest.spyOn(wrapper.vm.$apollo.queries.schedules, 'refetch');
+
+ await waitForPromises();
+
+ const scheduleId = mockPipelineScheduleNodes[0].id;
+
+ findTable().vm.$emit('showDeleteModal', scheduleId);
+
+ expect(wrapper.vm.$apollo.queries.schedules.refetch).not.toHaveBeenCalled();
+
+ findModal().vm.$emit('primary');
+
+ await waitForPromises();
+
+ expect(deleteMutationHandlerSuccess).toHaveBeenCalledWith({
+ id: scheduleId,
+ });
+ expect(wrapper.vm.$apollo.queries.schedules.refetch).toHaveBeenCalled();
+ });
+
+ it('modal should be visible after event', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findModal().props('visible')).toBe(false);
+
+ findTable().vm.$emit('showDeleteModal', mockPipelineScheduleNodes[0].id);
+
+ await nextTick();
+
+ expect(findModal().props('visible')).toBe(true);
+ });
+
+ it('modal should be hidden', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ findTable().vm.$emit('showDeleteModal', mockPipelineScheduleNodes[0].id);
+
+ await nextTick();
+
+ expect(findModal().props('visible')).toBe(true);
+
+ findModal().vm.$emit('hide');
+
+ await nextTick();
+
+ expect(findModal().props('visible')).toBe(false);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_actions_spec.js b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_actions_spec.js
new file mode 100644
index 00000000000..ecc1bdeb679
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_actions_spec.js
@@ -0,0 +1,49 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import PipelineScheduleActions from '~/pipeline_schedules/components/table/cells/pipeline_schedule_actions.vue';
+import { mockPipelineScheduleNodes, mockPipelineScheduleAsGuestNodes } from '../../../mock_data';
+
+describe('Pipeline schedule actions', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedule: mockPipelineScheduleNodes[0],
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = shallowMountExtended(PipelineScheduleActions, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findAllButtons = () => wrapper.findAllComponents(GlButton);
+ const findDeleteBtn = () => wrapper.findByTestId('delete-pipeline-schedule-btn');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays action buttons', () => {
+ createComponent();
+
+ expect(findAllButtons()).toHaveLength(3);
+ });
+
+ it('does not display action buttons', () => {
+ createComponent({ schedule: mockPipelineScheduleAsGuestNodes[0] });
+
+ expect(findAllButtons()).toHaveLength(0);
+ });
+
+ it('delete button emits showDeleteModal event and schedule id', () => {
+ createComponent();
+
+ findDeleteBtn().vm.$emit('click');
+
+ expect(wrapper.emitted()).toEqual({
+ showDeleteModal: [[mockPipelineScheduleNodes[0].id]],
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline_spec.js b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline_spec.js
new file mode 100644
index 00000000000..5a47b24232f
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline_spec.js
@@ -0,0 +1,42 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import PipelineScheduleLastPipeline from '~/pipeline_schedules/components/table/cells/pipeline_schedule_last_pipeline.vue';
+import { mockPipelineScheduleNodes } from '../../../mock_data';
+
+describe('Pipeline schedule last pipeline', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedule: mockPipelineScheduleNodes[2],
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = shallowMountExtended(PipelineScheduleLastPipeline, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findCIBadge = () => wrapper.findComponent(CiBadge);
+ const findStatusText = () => wrapper.findByTestId('pipeline-schedule-status-text');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays pipeline status', () => {
+ createComponent();
+
+ expect(findCIBadge().exists()).toBe(true);
+ expect(findCIBadge().props('status')).toBe(defaultProps.schedule.lastPipeline.detailedStatus);
+ expect(findStatusText().exists()).toBe(false);
+ });
+
+ it('displays "none" status text', () => {
+ createComponent({ schedule: mockPipelineScheduleNodes[0] });
+
+ expect(findStatusText().text()).toBe('None');
+ expect(findCIBadge().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_next_run_spec.js b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_next_run_spec.js
new file mode 100644
index 00000000000..b1bdc1e91a0
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_next_run_spec.js
@@ -0,0 +1,43 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import PipelineScheduleNextRun from '~/pipeline_schedules/components/table/cells/pipeline_schedule_next_run.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { mockPipelineScheduleNodes } from '../../../mock_data';
+
+describe('Pipeline schedule next run', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedule: mockPipelineScheduleNodes[0],
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = shallowMountExtended(PipelineScheduleNextRun, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
+ const findInactive = () => wrapper.findByTestId('pipeline-schedule-inactive');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays time ago', () => {
+ createComponent();
+
+ expect(findTimeAgo().exists()).toBe(true);
+ expect(findInactive().exists()).toBe(false);
+ expect(findTimeAgo().props('time')).toBe(defaultProps.schedule.realNextRun);
+ });
+
+ it('displays inactive state', () => {
+ const inactiveSchedule = mockPipelineScheduleNodes[1];
+ createComponent({ schedule: inactiveSchedule });
+
+ expect(findInactive().text()).toBe('Inactive');
+ expect(findTimeAgo().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_owner_spec.js b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_owner_spec.js
new file mode 100644
index 00000000000..3ab04958f5e
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_owner_spec.js
@@ -0,0 +1,40 @@
+import { GlAvatar, GlAvatarLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import PipelineScheduleOwner from '~/pipeline_schedules/components/table/cells/pipeline_schedule_owner.vue';
+import { mockPipelineScheduleNodes } from '../../../mock_data';
+
+describe('Pipeline schedule owner', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedule: mockPipelineScheduleNodes[0],
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = shallowMount(PipelineScheduleOwner, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
+ const findAvatarLink = () => wrapper.findComponent(GlAvatarLink);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays avatar', () => {
+ expect(findAvatar().exists()).toBe(true);
+ expect(findAvatar().props('src')).toBe(defaultProps.schedule.owner.avatarUrl);
+ });
+
+ it('avatar links to user', () => {
+ expect(findAvatarLink().attributes('href')).toBe(defaultProps.schedule.owner.webPath);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_target_spec.js b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_target_spec.js
new file mode 100644
index 00000000000..6817e58790b
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/cells/pipeline_schedule_target_spec.js
@@ -0,0 +1,41 @@
+import { GlIcon, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import PipelineScheduleTarget from '~/pipeline_schedules/components/table/cells/pipeline_schedule_target.vue';
+import { mockPipelineScheduleNodes } from '../../../mock_data';
+
+describe('Pipeline schedule target', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedule: mockPipelineScheduleNodes[0],
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = shallowMount(PipelineScheduleTarget, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findLink = () => wrapper.findComponent(GlLink);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays icon', () => {
+ expect(findIcon().exists()).toBe(true);
+ expect(findIcon().props('name')).toBe('fork');
+ });
+
+ it('displays ref link', () => {
+ expect(findLink().attributes('href')).toBe(defaultProps.schedule.refPath);
+ expect(findLink().text()).toBe(defaultProps.schedule.refForDisplay);
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/components/table/pipeline_schedules_table_spec.js b/spec/frontend/pipeline_schedules/components/table/pipeline_schedules_table_spec.js
new file mode 100644
index 00000000000..914897946ee
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/table/pipeline_schedules_table_spec.js
@@ -0,0 +1,39 @@
+import { GlTableLite } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import PipelineSchedulesTable from '~/pipeline_schedules/components/table/pipeline_schedules_table.vue';
+import { mockPipelineScheduleNodes } from '../../mock_data';
+
+describe('Pipeline schedules table', () => {
+ let wrapper;
+
+ const defaultProps = {
+ schedules: mockPipelineScheduleNodes,
+ };
+
+ const createComponent = (props = defaultProps) => {
+ wrapper = mountExtended(PipelineSchedulesTable, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findTable = () => wrapper.findComponent(GlTableLite);
+ const findScheduleDescription = () => wrapper.findByTestId('pipeline-schedule-description');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays table', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+
+ it('displays schedule description', () => {
+ expect(findScheduleDescription().text()).toBe('pipeline schedule');
+ });
+});
diff --git a/spec/frontend/pipeline_schedules/mock_data.js b/spec/frontend/pipeline_schedules/mock_data.js
new file mode 100644
index 00000000000..0a60998d8fb
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/mock_data.js
@@ -0,0 +1,35 @@
+// Fixture located at spec/frontend/fixtures/pipeline_schedules.rb
+import mockGetPipelineSchedulesGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.json';
+import mockGetPipelineSchedulesAsGuestGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.as_guest.json';
+
+const {
+ data: {
+ project: {
+ pipelineSchedules: { nodes },
+ },
+ },
+} = mockGetPipelineSchedulesGraphQLResponse;
+
+const {
+ data: {
+ project: {
+ pipelineSchedules: { nodes: guestNodes },
+ },
+ },
+} = mockGetPipelineSchedulesAsGuestGraphQLResponse;
+
+export const mockPipelineScheduleNodes = nodes;
+
+export const mockPipelineScheduleAsGuestNodes = guestNodes;
+
+export const deleteMutationResponse = {
+ data: {
+ pipelineScheduleDelete: {
+ clientMutationId: null,
+ errors: [],
+ __typename: 'PipelineScheduleDeletePayload',
+ },
+ },
+};
+
+export { mockGetPipelineSchedulesGraphQLResponse };
diff --git a/spec/frontend/pipeline_wizard/components/commit_spec.js b/spec/frontend/pipeline_wizard/components/commit_spec.js
index d7e019c642e..fa30b9c2b97 100644
--- a/spec/frontend/pipeline_wizard/components/commit_spec.js
+++ b/spec/frontend/pipeline_wizard/components/commit_spec.js
@@ -211,7 +211,7 @@ describe('Pipeline Wizard - Commit Page', () => {
}) => {
let consoleSpy;
- beforeAll(async () => {
+ beforeEach(async () => {
createComponent(
{
filename,
@@ -246,7 +246,7 @@ describe('Pipeline Wizard - Commit Page', () => {
await waitForPromises();
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
});
diff --git a/spec/frontend/pipeline_wizard/components/editor_spec.js b/spec/frontend/pipeline_wizard/components/editor_spec.js
index 26e4b8eb0ea..dd0a609043a 100644
--- a/spec/frontend/pipeline_wizard/components/editor_spec.js
+++ b/spec/frontend/pipeline_wizard/components/editor_spec.js
@@ -3,12 +3,20 @@ import { Document } from 'yaml';
import YamlEditor from '~/pipeline_wizard/components/editor.vue';
describe('Pages Yaml Editor wrapper', () => {
+ let wrapper;
+
const defaultOptions = {
propsData: { doc: new Document({ foo: 'bar' }), filename: 'foo.yml' },
};
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
describe('mount hook', () => {
- const wrapper = mount(YamlEditor, defaultOptions);
+ beforeEach(() => {
+ wrapper = mount(YamlEditor, defaultOptions);
+ });
it('editor is mounted', () => {
expect(wrapper.vm.editor).not.toBeUndefined();
@@ -19,16 +27,11 @@ describe('Pages Yaml Editor wrapper', () => {
describe('watchers', () => {
describe('doc', () => {
const doc = new Document({ baz: ['bar'] });
- let wrapper;
beforeEach(() => {
wrapper = mount(YamlEditor, defaultOptions);
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it("causes the editor's value to be set to the stringified document", async () => {
await wrapper.setProps({ doc });
expect(wrapper.vm.editor.getValue()).toEqual(doc.toString());
@@ -48,7 +51,10 @@ describe('Pages Yaml Editor wrapper', () => {
describe('highlight', () => {
const highlight = 'foo';
- const wrapper = mount(YamlEditor, defaultOptions);
+
+ beforeEach(() => {
+ wrapper = mount(YamlEditor, defaultOptions);
+ });
it('calls editor.highlight(path, keep=true)', async () => {
const highlightSpy = jest.spyOn(wrapper.vm.yamlEditorExtension.obj, 'highlight');
diff --git a/spec/frontend/pipeline_wizard/components/widgets/list_spec.js b/spec/frontend/pipeline_wizard/components/widgets/list_spec.js
index 796356634bc..c9e9f5caebe 100644
--- a/spec/frontend/pipeline_wizard/components/widgets/list_spec.js
+++ b/spec/frontend/pipeline_wizard/components/widgets/list_spec.js
@@ -22,6 +22,9 @@ describe('Pipeline Wizard - List Widget', () => {
const setValueOnInputField = (value, atIndex = 0) => {
return findGlFormInputGroupByIndex(atIndex).vm.$emit('input', value);
};
+ const getValueOfInputField = (atIndex = 0) => {
+ return findGlFormInputGroupByIndex(atIndex).get('input').element.value;
+ };
const findAddStepButton = () => wrapper.findByTestId('add-step-button');
const addStep = () => findAddStepButton().vm.$emit('click');
@@ -103,6 +106,24 @@ describe('Pipeline Wizard - List Widget', () => {
expect(addStepBtn.text()).toBe('add another step');
});
+ it('deletes the correct input item', async () => {
+ createComponent({}, mountExtended);
+
+ await addStep();
+ await addStep();
+ setValueOnInputField('foo', 0);
+ setValueOnInputField('bar', 1);
+ setValueOnInputField('baz', 2);
+
+ const button = findAllGlFormInputGroups().at(1).find('[data-testid="remove-step-button"]');
+
+ button.vm.$emit('click');
+ await nextTick();
+
+ expect(getValueOfInputField(0)).toBe('foo');
+ expect(getValueOfInputField(1)).toBe('baz');
+ });
+
it('the "add step" button increases the number of input fields', async () => {
createComponent();
diff --git a/spec/frontend/pipeline_wizard/components/wrapper_spec.js b/spec/frontend/pipeline_wizard/components/wrapper_spec.js
index f064bf01c86..d5b78cebcb3 100644
--- a/spec/frontend/pipeline_wizard/components/wrapper_spec.js
+++ b/spec/frontend/pipeline_wizard/components/wrapper_spec.js
@@ -132,7 +132,7 @@ describe('Pipeline Wizard - wrapper.vue', () => {
expectStepDef,
expectProgressBarValue,
}) => {
- beforeAll(async () => {
+ beforeEach(async () => {
createComponent();
for (const emittedValue of navigationEventChain) {
@@ -145,7 +145,7 @@ describe('Pipeline Wizard - wrapper.vue', () => {
}
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
});
@@ -184,11 +184,11 @@ describe('Pipeline Wizard - wrapper.vue', () => {
});
describe('editor overlay', () => {
- beforeAll(() => {
+ beforeEach(() => {
createComponent();
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
});
@@ -236,11 +236,11 @@ describe('Pipeline Wizard - wrapper.vue', () => {
});
describe('line highlights', () => {
- beforeAll(() => {
+ beforeEach(() => {
createComponent();
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
});
@@ -266,7 +266,7 @@ describe('Pipeline Wizard - wrapper.vue', () => {
});
describe('integration test', () => {
- beforeAll(async () => {
+ beforeEach(async () => {
createComponent({}, mountExtended);
});
@@ -290,14 +290,25 @@ describe('Pipeline Wizard - wrapper.vue', () => {
describe('navigating back', () => {
let inputField;
- beforeAll(async () => {
+ beforeEach(async () => {
+ createComponent({}, mountExtended);
+
+ findFirstInputFieldForTarget('$FOO').setValue('fooVal');
+ await nextTick();
+
+ findFirstVisibleStep().vm.$emit('next');
+ await nextTick();
+
+ findFirstInputFieldForTarget('$BAR').setValue('barVal');
+ await nextTick();
+
findFirstVisibleStep().vm.$emit('back');
await nextTick();
inputField = findFirstInputFieldForTarget('$FOO');
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
inputField = undefined;
});
diff --git a/spec/frontend/pipeline_wizard/mock/yaml.js b/spec/frontend/pipeline_wizard/mock/yaml.js
index 12b6f1052b2..014a32c5700 100644
--- a/spec/frontend/pipeline_wizard/mock/yaml.js
+++ b/spec/frontend/pipeline_wizard/mock/yaml.js
@@ -62,8 +62,7 @@ export const steps = `
export const compiledScenario1 = `foo: fooVal
`;
-export const compiledScenario2 = `foo: fooVal
-bar: barVal
+export const compiledScenario2 = `bar: barVal
`;
export const compiledScenario3 = `foo: newFooVal
diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js
index bfbb5f934b9..d1da7cb3acf 100644
--- a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js
+++ b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js
@@ -4,7 +4,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 createFlash from '~/flash';
+import { createAlert } from '~/flash';
import FailedJobsApp from '~/pipelines/components/jobs/failed_jobs_app.vue';
import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue';
import GetFailedJobsQuery from '~/pipelines/graphql/queries/get_failed_jobs.query.graphql';
@@ -70,7 +70,7 @@ describe('Failed Jobs App', () => {
await waitForPromises();
expect(findJobsTable().exists()).toBe(true);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
it('handles query fetch error correctly', async () => {
@@ -80,7 +80,7 @@ describe('Failed Jobs App', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching the failed jobs.',
});
});
diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js
index b597a3bf4b0..0df15afd70d 100644
--- a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js
+++ b/spec/frontend/pipelines/components/jobs/failed_jobs_table_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 { mountExtended } from 'helpers/vue_test_utils_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue';
import RetryFailedJobMutation from '~/pipelines/graphql/mutations/retry_failed_job.mutation.graphql';
@@ -88,7 +88,7 @@ describe('Failed Jobs Table', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem retrying the failed job.',
});
});
diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
index 89b6f764b2f..9bc14266593 100644
--- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
+++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
@@ -4,7 +4,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 createFlash from '~/flash';
+import { createAlert } 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';
@@ -88,7 +88,7 @@ describe('Jobs app', () => {
expect(findJobsTable().exists()).toBe(true);
expect(findSkeletonLoader().exists()).toBe(false);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
it('handles job fetch error correctly', async () => {
@@ -98,7 +98,7 @@ describe('Jobs app', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while fetching the pipelines jobs.',
});
});
diff --git a/spec/frontend/pipelines/pipeline_multi_actions_spec.js b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
index 149b40330e2..f0dae8ebcbe 100644
--- a/spec/frontend/pipelines/pipeline_multi_actions_spec.js
+++ b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlDropdown, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlDropdown, GlSprintf, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
@@ -46,6 +46,7 @@ describe('Pipeline Multi Actions Dropdown', () => {
},
stubs: {
GlSprintf,
+ GlDropdown,
},
}),
);
@@ -56,6 +57,7 @@ describe('Pipeline Multi Actions Dropdown', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAllArtifactItems = () => wrapper.findAllByTestId(artifactItemTestId);
const findFirstArtifactItem = () => wrapper.findByTestId(artifactItemTestId);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findEmptyMessage = () => wrapper.findByTestId('artifacts-empty-message');
beforeEach(() => {
@@ -75,7 +77,7 @@ describe('Pipeline Multi Actions Dropdown', () => {
});
describe('Artifacts', () => {
- it('should fetch artifacts on dropdown click', async () => {
+ it('should fetch artifacts and show search box on dropdown click', async () => {
const endpoint = artifactsEndpoint.replace(artifactsEndpointPlaceholder, pipelineId);
mockAxios.onGet(endpoint).replyOnce(200, { artifacts });
createComponent();
@@ -84,6 +86,16 @@ describe('Pipeline Multi Actions Dropdown', () => {
expect(mockAxios.history.get).toHaveLength(1);
expect(wrapper.vm.artifacts).toEqual(artifacts);
+ expect(findSearchBox().exists()).toBe(true);
+ });
+
+ it('should focus the search box when opened with artifacts', () => {
+ createComponent({ mockData: { artifacts } });
+ wrapper.vm.$refs.searchInput.focusInput = jest.fn();
+
+ findDropdown().vm.$emit('shown');
+
+ expect(wrapper.vm.$refs.searchInput.focusInput).toHaveBeenCalled();
});
it('should render all the provided artifacts when search query is empty', () => {
@@ -109,10 +121,11 @@ describe('Pipeline Multi Actions Dropdown', () => {
expect(findFirstArtifactItem().text()).toBe(artifacts[0].name);
});
- it('should render empty message when no artifacts are found', () => {
+ it('should render empty message and no search box when no artifacts are found', () => {
createComponent({ mockData: { artifacts: [] } });
expect(findEmptyMessage().exists()).toBe(true);
+ expect(findSearchBox().exists()).toBe(false);
});
describe('while loading artifacts', () => {
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index fdfced38dca..26e61efc4f6 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -5,7 +5,7 @@ import { nextTick } from 'vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipelines_manual_actions.vue';
@@ -95,7 +95,7 @@ describe('Pipelines Actions dropdown', () => {
await waitForPromises();
expect(findDropdown().props('loading')).toBe(false);
- expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index cc2ff90de57..a3f15e25f36 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -11,7 +11,7 @@ import { mockTracking } from 'helpers/tracking_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_WARNING } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
import PipelinesComponent from '~/pipelines/components/pipelines_list/pipelines.vue';
@@ -261,9 +261,14 @@ describe('Pipelines', () => {
);
});
- it('tracks tab change click', () => {
+ it.each(['all', 'finished', 'branches', 'tags'])('tracks %p tab click', async (scope) => {
+ goToTab(scope);
+
+ await waitForPromises();
+
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_filter_tabs', {
label: TRACKING_CATEGORIES.tabs,
+ property: scope,
});
});
});
@@ -356,8 +361,11 @@ describe('Pipelines', () => {
});
it('displays a warning message if raw text search is used', () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({ message: RAW_TEXT_WARNING, type: 'warning' });
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
+ message: RAW_TEXT_WARNING,
+ variant: VARIANT_WARNING,
+ });
});
it('should update browser bar', () => {
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
index 74a9d8c354f..6e61ef97257 100644
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testReports from 'test_fixtures/pipelines/test_report.json';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/pipelines/stores/test_reports/actions';
import * as types from '~/pipelines/stores/test_reports/mutation_types';
@@ -56,7 +56,7 @@ describe('Actions TestReports Store', () => {
[],
[{ type: 'toggleLoading' }, { type: 'toggleLoading' }],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js
index f9b9da01a2b..ed0cc71eb97 100644
--- a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js
@@ -1,7 +1,7 @@
import testReports from 'test_fixtures/pipelines/test_report.json';
import * as types from '~/pipelines/stores/test_reports/mutation_types';
import mutations from '~/pipelines/stores/test_reports/mutations';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
jest.mock('~/flash.js');
@@ -61,7 +61,7 @@ describe('Mutations TestReports Store', () => {
it('should show a flash message otherwise', () => {
mutations[types.SET_SUITE_ERROR](mockState, {});
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index e331eed1863..575df9fb3c0 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import UpdateUsername from '~/profile/account/components/update_username.vue';
@@ -149,7 +149,7 @@ describe('UpdateUsername component', () => {
await expect(wrapper.vm.onConfirm()).rejects.toThrow();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Invalid username',
});
});
@@ -161,7 +161,7 @@ describe('UpdateUsername component', () => {
await expect(wrapper.vm.onConfirm()).rejects.toThrow();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while updating your username, please try again.',
});
});
diff --git a/spec/frontend/profile/preferences/components/profile_preferences_spec.js b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
index 89ce838a383..91cd868daac 100644
--- a/spec/frontend/profile/preferences/components/profile_preferences_spec.js
+++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import createFlash from '~/flash';
+import { createAlert, VARIANT_DANGER, VARIANT_INFO } from '~/flash';
import IntegrationView from '~/profile/preferences/components/integration_view.vue';
import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue';
import { i18n } from '~/profile/preferences/constants';
@@ -149,7 +149,10 @@ describe('ProfilePreferences component', () => {
const successEvent = new CustomEvent('ajax:success');
form.dispatchEvent(successEvent);
- expect(createFlash).toHaveBeenCalledWith({ message: i18n.defaultSuccess, type: 'notice' });
+ expect(createAlert).toHaveBeenCalledWith({
+ message: i18n.defaultSuccess,
+ variant: VARIANT_INFO,
+ });
});
it('displays the custom success message', () => {
@@ -157,14 +160,17 @@ describe('ProfilePreferences component', () => {
const successEvent = new CustomEvent('ajax:success', { detail: [{ message }] });
form.dispatchEvent(successEvent);
- expect(createFlash).toHaveBeenCalledWith({ message, type: 'notice' });
+ expect(createAlert).toHaveBeenCalledWith({ message, variant: VARIANT_INFO });
});
it('displays the default error message', () => {
const errorEvent = new CustomEvent('ajax:error');
form.dispatchEvent(errorEvent);
- expect(createFlash).toHaveBeenCalledWith({ message: i18n.defaultError, type: 'alert' });
+ expect(createAlert).toHaveBeenCalledWith({
+ message: i18n.defaultError,
+ variant: VARIANT_DANGER,
+ });
});
it('displays the custom error message', () => {
@@ -172,7 +178,7 @@ describe('ProfilePreferences component', () => {
const errorEvent = new CustomEvent('ajax:error', { detail: [{ message }] });
form.dispatchEvent(errorEvent);
- expect(createFlash).toHaveBeenCalledWith({ message, type: 'alert' });
+ expect(createAlert).toHaveBeenCalledWith({ message, variant: VARIANT_DANGER });
});
});
diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js
index 56dffcbd48e..008710984b9 100644
--- a/spec/frontend/projects/commit/store/actions_spec.js
+++ b/spec/frontend/projects/commit/store/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
import * as actions from '~/projects/commit/store/actions';
@@ -68,7 +68,7 @@ describe('Commit form modal store actions', () => {
await testAction(actions.fetchBranches, {}, state, [], [{ type: 'requestBranches' }]);
- expect(createFlash).toHaveBeenCalledWith({ message: PROJECT_BRANCHES_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: PROJECT_BRANCHES_ERROR });
});
});
diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js
index fdb12640b26..930b801af71 100644
--- a/spec/frontend/projects/commits/store/actions_spec.js
+++ b/spec/frontend/projects/commits/store/actions_spec.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import actions from '~/projects/commits/store/actions';
import * as types from '~/projects/commits/store/mutation_types';
import createState from '~/projects/commits/store/state';
@@ -38,8 +38,8 @@ describe('Project commits actions', () => {
const mockDispatchContext = { dispatch: () => {}, commit: () => {}, state };
actions.receiveAuthorsError(mockDispatchContext);
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred fetching the project authors.',
});
});
diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js
index 2dbecf7cc61..9b052a17caa 100644
--- a/spec/frontend/projects/compare/components/app_spec.js
+++ b/spec/frontend/projects/compare/components/app_spec.js
@@ -134,6 +134,40 @@ describe('CompareApp component', () => {
});
});
+ describe('mode dropdown', () => {
+ const findModeDropdownButton = () => wrapper.find('[data-testid="modeDropdown"]');
+ const findEnableStraightModeButton = () =>
+ wrapper.find('[data-testid="enableStraightModeButton"]');
+ const findDisableStraightModeButton = () =>
+ wrapper.find('[data-testid="disableStraightModeButton"]');
+
+ it('renders the mode dropdown button', () => {
+ expect(findModeDropdownButton().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ expect(findEnableStraightModeButton().text()).toBe('...');
+ expect(findDisableStraightModeButton().text()).toBe('..');
+ });
+
+ it('straight mode button when clicked', async () => {
+ expect(wrapper.props('straight')).toBe(false);
+ expect(wrapper.find('input[name="straight"]').attributes('value')).toBe('false');
+
+ findEnableStraightModeButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(wrapper.find('input[name="straight"]').attributes('value')).toBe('true');
+
+ findDisableStraightModeButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(wrapper.find('input[name="straight"]').attributes('value')).toBe('false');
+ });
+ });
+
describe('merge request buttons', () => {
const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
diff --git a/spec/frontend/projects/compare/components/mock_data.js b/spec/frontend/projects/compare/components/mock_data.js
index 81d64469a2a..28d9a394038 100644
--- a/spec/frontend/projects/compare/components/mock_data.js
+++ b/spec/frontend/projects/compare/components/mock_data.js
@@ -17,6 +17,7 @@ export const appDefaultProps = {
projects: [sourceProject],
paramsFrom: 'main',
paramsTo: 'target/branch',
+ straight: false,
createMrPath: '',
sourceProjectRefsPath,
targetProjectRefsPath,
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
index f64af1aa994..c21c0f4f9d1 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
@@ -2,7 +2,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RevisionDropdown from '~/projects/compare/components/revision_dropdown_legacy.vue';
@@ -79,7 +79,7 @@ describe('RevisionDropdown component', () => {
axiosMock.onGet('some/invalid/path').replyOnce(404);
await wrapper.vm.fetchBranchesAndTags();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
describe('GlDropdown component', () => {
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
index 35e32fd3da0..d598bafea92 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -2,7 +2,7 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
import { revisionDropdownDefaultProps as defaultProps } from './mock_data';
@@ -67,7 +67,7 @@ describe('RevisionDropdown component', () => {
createComponent();
await wrapper.vm.fetchBranchesAndTags();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('makes a new request when refsProjectPath is changed', async () => {
@@ -93,7 +93,7 @@ describe('RevisionDropdown component', () => {
createComponent();
await wrapper.vm.searchBranchesAndTags();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('makes request with search param', async () => {
diff --git a/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js b/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js
deleted file mode 100644
index 79bce5a4b3f..00000000000
--- a/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import { GlDropdown, GlSearchBoxByType, GlDropdownItem, GlSprintf } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import BranchDropdown, {
- i18n,
-} from '~/projects/settings/branch_rules/components/branch_dropdown.vue';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import branchesQuery from '~/projects/settings/branch_rules/queries/branches.query.graphql';
-import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
-
-Vue.use(VueApollo);
-jest.mock('~/flash');
-
-describe('Branch dropdown', () => {
- let wrapper;
-
- const projectPath = 'test/project';
- const value = 'main';
- const mockBranchNames = ['test 1', 'test 2'];
-
- const createComponent = async ({ branchNames = mockBranchNames, resolver } = {}) => {
- const mockResolver =
- resolver ||
- jest.fn().mockResolvedValue({
- data: { project: { id: '1', repository: { branchNames } } },
- });
- const apolloProvider = createMockApollo([[branchesQuery, mockResolver]]);
-
- wrapper = shallowMountExtended(BranchDropdown, {
- apolloProvider,
- propsData: { projectPath, value },
- });
-
- await waitForPromises();
- };
-
- const findGlDropdown = () => wrapper.findComponent(GlDropdown);
- const findAllBranches = () => wrapper.findAllComponents(GlDropdownItem);
- const findNoDataMsg = () => wrapper.findByTestId('no-data');
- const findGlSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
- const findWildcardButton = () => wrapper.findByTestId('create-wildcard-button');
- const findHelpText = () => wrapper.findComponent(GlSprintf);
- const setSearchTerm = (searchTerm) => findGlSearchBoxByType().vm.$emit('input', searchTerm);
-
- beforeEach(() => createComponent());
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders a GlDropdown component with the correct props', () => {
- expect(findGlDropdown().props()).toMatchObject({ text: value });
- });
-
- it('renders GlDropdownItem components for each branch', () => {
- expect(findAllBranches().length).toBe(mockBranchNames.length);
-
- mockBranchNames.forEach((branchName, index) =>
- expect(findAllBranches().at(index).text()).toBe(branchName),
- );
- });
-
- it('emits `select` with the branch name when a branch is clicked', () => {
- findAllBranches().at(0).vm.$emit('click');
- expect(wrapper.emitted('input')).toEqual([[mockBranchNames[0]]]);
- });
-
- describe('branch searching', () => {
- it('displays a message if no branches can be found', async () => {
- await createComponent({ branchNames: [] });
-
- expect(findNoDataMsg().text()).toBe(i18n.noMatch);
- });
-
- it('displays a loading state while search request is in flight', async () => {
- setSearchTerm('test');
- await nextTick();
-
- expect(findGlSearchBoxByType().props()).toMatchObject({ isLoading: true });
- });
-
- it('renders a wildcard button', async () => {
- const searchTerm = 'test-*';
- setSearchTerm(searchTerm);
- await nextTick();
-
- expect(findWildcardButton().exists()).toBe(true);
- findWildcardButton().vm.$emit('click');
- expect(wrapper.emitted('createWildcard')).toEqual([[searchTerm]]);
- });
-
- it('renders help text', () => {
- expect(findHelpText().attributes('message')).toBe(i18n.branchHelpText);
- });
- });
-
- it('displays an error message if fetch failed', async () => {
- const error = new Error('an error occurred');
- const resolver = jest.fn().mockRejectedValueOnce(error);
- await createComponent({ resolver });
-
- expect(createAlert).toHaveBeenCalledWith({
- message: i18n.fetchBranchesError,
- captureError: true,
- error,
- });
- });
-});
diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js
new file mode 100644
index 00000000000..11f219c1f90
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js
@@ -0,0 +1,110 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlDropdown, GlSearchBoxByType, GlDropdownItem, GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import BranchDropdown, {
+ i18n,
+} from '~/projects/settings/branch_rules/components/edit/branch_dropdown.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import branchesQuery from '~/projects/settings/branch_rules/queries/branches.query.graphql';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+
+Vue.use(VueApollo);
+jest.mock('~/flash');
+
+describe('Branch dropdown', () => {
+ let wrapper;
+
+ const projectPath = 'test/project';
+ const value = 'main';
+ const mockBranchNames = ['test 1', 'test 2'];
+
+ const createComponent = async ({ branchNames = mockBranchNames, resolver } = {}) => {
+ const mockResolver =
+ resolver ||
+ jest.fn().mockResolvedValue({
+ data: { project: { id: '1', repository: { branchNames } } },
+ });
+ const apolloProvider = createMockApollo([[branchesQuery, mockResolver]]);
+
+ wrapper = shallowMountExtended(BranchDropdown, {
+ apolloProvider,
+ propsData: { projectPath, value },
+ });
+
+ await waitForPromises();
+ };
+
+ const findGlDropdown = () => wrapper.findComponent(GlDropdown);
+ const findAllBranches = () => wrapper.findAllComponents(GlDropdownItem);
+ const findNoDataMsg = () => wrapper.findByTestId('no-data');
+ const findGlSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
+ const findWildcardButton = () => wrapper.findByTestId('create-wildcard-button');
+ const findHelpText = () => wrapper.findComponent(GlSprintf);
+ const setSearchTerm = (searchTerm) => findGlSearchBoxByType().vm.$emit('input', searchTerm);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a GlDropdown component with the correct props', () => {
+ expect(findGlDropdown().props()).toMatchObject({ text: value });
+ });
+
+ it('renders GlDropdownItem components for each branch', () => {
+ expect(findAllBranches().length).toBe(mockBranchNames.length);
+
+ mockBranchNames.forEach((branchName, index) =>
+ expect(findAllBranches().at(index).text()).toBe(branchName),
+ );
+ });
+
+ it('emits `select` with the branch name when a branch is clicked', () => {
+ findAllBranches().at(0).vm.$emit('click');
+ expect(wrapper.emitted('input')).toEqual([[mockBranchNames[0]]]);
+ });
+
+ describe('branch searching', () => {
+ it('displays a message if no branches can be found', async () => {
+ await createComponent({ branchNames: [] });
+
+ expect(findNoDataMsg().text()).toBe(i18n.noMatch);
+ });
+
+ it('displays a loading state while search request is in flight', async () => {
+ setSearchTerm('test');
+ await nextTick();
+
+ expect(findGlSearchBoxByType().props()).toMatchObject({ isLoading: true });
+ });
+
+ it('renders a wildcard button', async () => {
+ const searchTerm = 'test-*';
+ setSearchTerm(searchTerm);
+ await nextTick();
+
+ expect(findWildcardButton().exists()).toBe(true);
+ findWildcardButton().vm.$emit('click');
+ expect(wrapper.emitted('createWildcard')).toEqual([[searchTerm]]);
+ });
+
+ it('renders help text', () => {
+ expect(findHelpText().attributes('message')).toBe(i18n.branchHelpText);
+ });
+ });
+
+ it('displays an error message if fetch failed', async () => {
+ const error = new Error('an error occurred');
+ const resolver = jest.fn().mockRejectedValueOnce(error);
+ await createComponent({ resolver });
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: i18n.fetchBranchesError,
+ captureError: true,
+ error,
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js
new file mode 100644
index 00000000000..21e63fdb24d
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js
@@ -0,0 +1,108 @@
+import { nextTick } from 'vue';
+import { getParameterByName } from '~/lib/utils/url_utility';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import RuleEdit from '~/projects/settings/branch_rules/components/edit/index.vue';
+import BranchDropdown from '~/projects/settings/branch_rules/components/edit/branch_dropdown.vue';
+import Protections from '~/projects/settings/branch_rules/components/edit/protections/index.vue';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ getParameterByName: jest.fn().mockImplementation(() => 'main'),
+ joinPaths: jest.fn(),
+ setUrlFragment: jest.fn(),
+}));
+
+describe('Edit branch rule', () => {
+ let wrapper;
+ const projectPath = 'test/testing';
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(RuleEdit, { propsData: { projectPath } });
+ };
+
+ const findBranchDropdown = () => wrapper.findComponent(BranchDropdown);
+ const findProtections = () => wrapper.findComponent(Protections);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('gets the branch param from url', () => {
+ expect(getParameterByName).toHaveBeenCalledWith('branch');
+ });
+
+ describe('BranchDropdown', () => {
+ it('renders a BranchDropdown component with the correct props', () => {
+ expect(findBranchDropdown().props()).toMatchObject({
+ projectPath,
+ value: 'main',
+ });
+ });
+
+ it('sets the correct value when `input` is emitted', async () => {
+ const branch = 'test';
+ findBranchDropdown().vm.$emit('input', branch);
+ await nextTick();
+ expect(findBranchDropdown().props('value')).toBe(branch);
+ });
+
+ it('sets the correct value when `createWildcard` is emitted', async () => {
+ const wildcard = 'test-*';
+ findBranchDropdown().vm.$emit('createWildcard', wildcard);
+ await nextTick();
+ expect(findBranchDropdown().props('value')).toBe(wildcard);
+ });
+ });
+
+ describe('Protections', () => {
+ it('renders a Protections component with the correct props', () => {
+ expect(findProtections().props('protections')).toMatchObject({
+ membersAllowedToPush: [],
+ allowForcePush: false,
+ membersAllowedToMerge: [],
+ requireCodeOwnersApproval: false,
+ });
+ });
+
+ it('updates protections when change-allowed-to-push-members is emitted', async () => {
+ const membersAllowedToPush = ['test'];
+ findProtections().vm.$emit('change-allowed-to-push-members', membersAllowedToPush);
+ await nextTick();
+
+ expect(findProtections().props('protections')).toEqual(
+ expect.objectContaining({ membersAllowedToPush }),
+ );
+ });
+
+ it('updates protections when change-allow-force-push is emitted', async () => {
+ const allowForcePush = true;
+ findProtections().vm.$emit('change-allow-force-push', allowForcePush);
+ await nextTick();
+
+ expect(findProtections().props('protections')).toEqual(
+ expect.objectContaining({ allowForcePush }),
+ );
+ });
+
+ it('updates protections when change-allowed-to-merge-members is emitted', async () => {
+ const membersAllowedToMerge = ['test'];
+ findProtections().vm.$emit('change-allowed-to-merge-members', membersAllowedToMerge);
+ await nextTick();
+
+ expect(findProtections().props('protections')).toEqual(
+ expect.objectContaining({ membersAllowedToMerge }),
+ );
+ });
+
+ it('updates protections when change-require-code-owners-approval is emitted', async () => {
+ const requireCodeOwnersApproval = true;
+ findProtections().vm.$emit('change-require-code-owners-approval', requireCodeOwnersApproval);
+ await nextTick();
+
+ expect(findProtections().props('protections')).toEqual(
+ expect.objectContaining({ requireCodeOwnersApproval }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js
new file mode 100644
index 00000000000..ee90ff8318f
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js
@@ -0,0 +1,57 @@
+import { nextTick } from 'vue';
+import { GlLink } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import Protections, {
+ i18n,
+} from '~/projects/settings/branch_rules/components/edit/protections/index.vue';
+import PushProtections from '~/projects/settings/branch_rules/components/edit/protections/push_protections.vue';
+import MergeProtections from '~/projects/settings/branch_rules/components/edit/protections/merge_protections.vue';
+import { protections } from '../../../mock_data';
+
+describe('Branch Protections', () => {
+ let wrapper;
+
+ const createComponent = async () => {
+ wrapper = mountExtended(Protections, {
+ propsData: { protections },
+ });
+ await nextTick();
+ };
+
+ const findHeading = () => wrapper.find('h4');
+ const findHelpText = () => wrapper.findByTestId('protections-help-text');
+ const findHelpLink = () => wrapper.findComponent(GlLink);
+ const findPushProtections = () => wrapper.findComponent(PushProtections);
+ const findMergeProtections = () => wrapper.findComponent(MergeProtections);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a heading', () => {
+ expect(findHeading().text()).toBe(i18n.protections);
+ });
+
+ it('renders help text', () => {
+ expect(findHelpText().text()).toMatchInterpolatedText(i18n.protectionsHelpText);
+ expect(findHelpLink().attributes('href')).toBe('/help/user/project/protected_branches');
+ });
+
+ it('renders a PushProtections component with correct props', () => {
+ expect(findPushProtections().props('membersAllowedToPush')).toStrictEqual(
+ protections.membersAllowedToPush,
+ );
+ expect(findPushProtections().props('allowForcePush')).toBe(protections.allowForcePush);
+ });
+
+ it('renders a MergeProtections component with correct props', () => {
+ expect(findMergeProtections().props('membersAllowedToMerge')).toStrictEqual(
+ protections.membersAllowedToMerge,
+ );
+ expect(findMergeProtections().props('requireCodeOwnersApproval')).toBe(
+ protections.requireCodeOwnersApproval,
+ );
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js
new file mode 100644
index 00000000000..b5fdc46d600
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js
@@ -0,0 +1,53 @@
+import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import MergeProtections, {
+ i18n,
+} from '~/projects/settings/branch_rules/components/edit/protections/merge_protections.vue';
+import { membersAllowedToMerge, requireCodeOwnersApproval } from '../../../mock_data';
+
+describe('Merge Protections', () => {
+ let wrapper;
+
+ const propsData = {
+ membersAllowedToMerge,
+ requireCodeOwnersApproval,
+ };
+
+ const createComponent = () => {
+ wrapper = mountExtended(MergeProtections, {
+ propsData,
+ });
+ };
+
+ const findFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findCodeOwnersApprovalCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a form group with the correct label', () => {
+ expect(findFormGroup().text()).toContain(i18n.allowedToMerge);
+ });
+
+ describe('Require code owners approval checkbox', () => {
+ it('renders a checkbox with the correct props', () => {
+ expect(findCodeOwnersApprovalCheckbox().vm.$attrs.checked).toBe(
+ propsData.requireCodeOwnersApproval,
+ );
+ });
+
+ it('renders help text', () => {
+ expect(findCodeOwnersApprovalCheckbox().text()).toContain(i18n.requireApprovalTitle);
+ expect(findCodeOwnersApprovalCheckbox().text()).toContain(i18n.requireApprovalHelpText);
+ });
+
+ it('emits a change-allow-force-push event when changed', () => {
+ findCodeOwnersApprovalCheckbox().vm.$emit('change', false);
+
+ expect(wrapper.emitted('change-require-code-owners-approval')[0]).toEqual([false]);
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js
new file mode 100644
index 00000000000..60bb7a51dcb
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js
@@ -0,0 +1,50 @@
+import { GlFormGroup, GlSprintf, GlFormCheckbox } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import PushProtections, {
+ i18n,
+} from '~/projects/settings/branch_rules/components/edit/protections/push_protections.vue';
+import { membersAllowedToPush, allowForcePush } from '../../../mock_data';
+
+describe('Push Protections', () => {
+ let wrapper;
+ const propsData = {
+ membersAllowedToPush,
+ allowForcePush,
+ };
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(PushProtections, {
+ propsData,
+ });
+ };
+
+ const findFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findAllowForcePushCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findHelpText = () => wrapper.findComponent(GlSprintf);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a form group with the correct label', () => {
+ expect(findFormGroup().attributes('label')).toBe(i18n.allowedToPush);
+ });
+
+ describe('Allow force push checkbox', () => {
+ it('renders a checkbox with the correct props', () => {
+ expect(findAllowForcePushCheckbox().vm.$attrs.checked).toBe(propsData.allowForcePush);
+ });
+
+ it('renders help text', () => {
+ expect(findHelpText().attributes('message')).toBe(i18n.forcePushTitle);
+ });
+
+ it('emits a change-allow-force-push event when changed', () => {
+ findAllowForcePushCheckbox().vm.$emit('change', false);
+
+ expect(wrapper.emitted('change-allow-force-push')[0]).toEqual([false]);
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/protections/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/protections/index_spec.js
deleted file mode 100644
index 3592fa50622..00000000000
--- a/spec/frontend/projects/settings/branch_rules/components/protections/index_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { nextTick } from 'vue';
-import { GlLink } from '@gitlab/ui';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import Protections, {
- i18n,
-} from '~/projects/settings/branch_rules/components/protections/index.vue';
-import PushProtections from '~/projects/settings/branch_rules/components/protections/push_protections.vue';
-import MergeProtections from '~/projects/settings/branch_rules/components/protections/merge_protections.vue';
-import { protections } from '../../mock_data';
-
-describe('Branch Protections', () => {
- let wrapper;
-
- const createComponent = async () => {
- wrapper = mountExtended(Protections, {
- propsData: { protections },
- });
- await nextTick();
- };
-
- const findHeading = () => wrapper.find('h4');
- const findHelpText = () => wrapper.findByTestId('protections-help-text');
- const findHelpLink = () => wrapper.findComponent(GlLink);
- const findPushProtections = () => wrapper.findComponent(PushProtections);
- const findMergeProtections = () => wrapper.findComponent(MergeProtections);
-
- beforeEach(() => createComponent());
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders a heading', () => {
- expect(findHeading().text()).toBe(i18n.protections);
- });
-
- it('renders help text', () => {
- expect(findHelpText().text()).toMatchInterpolatedText(i18n.protectionsHelpText);
- expect(findHelpLink().attributes('href')).toBe('/help/user/project/protected_branches');
- });
-
- it('renders a PushProtections component with correct props', () => {
- expect(findPushProtections().props('membersAllowedToPush')).toStrictEqual(
- protections.membersAllowedToPush,
- );
- expect(findPushProtections().props('allowForcePush')).toBe(protections.allowForcePush);
- });
-
- it('renders a MergeProtections component with correct props', () => {
- expect(findMergeProtections().props('membersAllowedToMerge')).toStrictEqual(
- protections.membersAllowedToMerge,
- );
- expect(findMergeProtections().props('requireCodeOwnersApproval')).toBe(
- protections.requireCodeOwnersApproval,
- );
- });
-});
diff --git a/spec/frontend/projects/settings/branch_rules/components/protections/merge_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/protections/merge_protections_spec.js
deleted file mode 100644
index 0e168a2ad78..00000000000
--- a/spec/frontend/projects/settings/branch_rules/components/protections/merge_protections_spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import MergeProtections, {
- i18n,
-} from '~/projects/settings/branch_rules/components/protections/merge_protections.vue';
-import { membersAllowedToMerge, requireCodeOwnersApproval } from '../../mock_data';
-
-describe('Merge Protections', () => {
- let wrapper;
-
- const propsData = {
- membersAllowedToMerge,
- requireCodeOwnersApproval,
- };
-
- const createComponent = () => {
- wrapper = mountExtended(MergeProtections, {
- propsData,
- });
- };
-
- const findFormGroup = () => wrapper.findComponent(GlFormGroup);
- const findCodeOwnersApprovalCheckbox = () => wrapper.findComponent(GlFormCheckbox);
-
- beforeEach(() => createComponent());
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders a form group with the correct label', () => {
- expect(findFormGroup().text()).toContain(i18n.allowedToMerge);
- });
-
- describe('Require code owners approval checkbox', () => {
- it('renders a checkbox with the correct props', () => {
- expect(findCodeOwnersApprovalCheckbox().vm.$attrs.checked).toBe(
- propsData.requireCodeOwnersApproval,
- );
- });
-
- it('renders help text', () => {
- expect(findCodeOwnersApprovalCheckbox().text()).toContain(i18n.requireApprovalTitle);
- expect(findCodeOwnersApprovalCheckbox().text()).toContain(i18n.requireApprovalHelpText);
- });
-
- it('emits a change-allow-force-push event when changed', () => {
- findCodeOwnersApprovalCheckbox().vm.$emit('change', false);
-
- expect(wrapper.emitted('change-require-code-owners-approval')[0]).toEqual([false]);
- });
- });
-});
diff --git a/spec/frontend/projects/settings/branch_rules/components/protections/push_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/protections/push_protections_spec.js
deleted file mode 100644
index d54dad08338..00000000000
--- a/spec/frontend/projects/settings/branch_rules/components/protections/push_protections_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import { GlFormGroup, GlSprintf, GlFormCheckbox } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import PushProtections, {
- i18n,
-} from '~/projects/settings/branch_rules/components/protections/push_protections.vue';
-import { membersAllowedToPush, allowForcePush } from '../../mock_data';
-
-describe('Push Protections', () => {
- let wrapper;
- const propsData = {
- membersAllowedToPush,
- allowForcePush,
- };
-
- const createComponent = () => {
- wrapper = shallowMountExtended(PushProtections, {
- propsData,
- });
- };
-
- const findFormGroup = () => wrapper.findComponent(GlFormGroup);
- const findAllowForcePushCheckbox = () => wrapper.findComponent(GlFormCheckbox);
- const findHelpText = () => wrapper.findComponent(GlSprintf);
-
- beforeEach(() => createComponent());
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders a form group with the correct label', () => {
- expect(findFormGroup().attributes('label')).toBe(i18n.allowedToPush);
- });
-
- describe('Allow force push checkbox', () => {
- it('renders a checkbox with the correct props', () => {
- expect(findAllowForcePushCheckbox().vm.$attrs.checked).toBe(propsData.allowForcePush);
- });
-
- it('renders help text', () => {
- expect(findHelpText().attributes('message')).toBe(i18n.forcePushTitle);
- });
-
- it('emits a change-allow-force-push event when changed', () => {
- findAllowForcePushCheckbox().vm.$emit('change', false);
-
- expect(wrapper.emitted('change-allow-force-push')[0]).toEqual([false]);
- });
- });
-});
diff --git a/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js
new file mode 100644
index 00000000000..bf4026b65db
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js
@@ -0,0 +1,113 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import * as util from '~/lib/utils/url_utility';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import RuleView from '~/projects/settings/branch_rules/components/view/index.vue';
+import {
+ I18N,
+ ALL_BRANCHES_WILDCARD,
+} from '~/projects/settings/branch_rules/components/view/constants';
+import Protection from '~/projects/settings/branch_rules/components/view/protection.vue';
+import branchRulesQuery from '~/projects/settings/branch_rules/queries/branch_rules_details.query.graphql';
+import { sprintf } from '~/locale';
+import { branchProtectionsMockResponse } from './mock_data';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ getParameterByName: jest.fn().mockReturnValue('main'),
+ joinPaths: jest.fn(),
+}));
+
+Vue.use(VueApollo);
+
+const protectionMockProps = {
+ headerLinkHref: 'protected/branches',
+ headerLinkTitle: 'Manage in Protected Branches',
+ roles: [{ accessLevelDescription: 'Maintainers' }],
+ users: [{ avatarUrl: 'test.com/user.png', name: 'peter', webUrl: 'test.com' }],
+};
+
+describe('View branch rules', () => {
+ let wrapper;
+ let fakeApollo;
+ const projectPath = 'test/testing';
+ const protectedBranchesPath = 'protected/branches';
+ const approvalRulesPath = 'approval/rules';
+ const branchProtectionsMockRequestHandler = jest
+ .fn()
+ .mockResolvedValue(branchProtectionsMockResponse);
+
+ const createComponent = async () => {
+ fakeApollo = createMockApollo([[branchRulesQuery, branchProtectionsMockRequestHandler]]);
+
+ wrapper = shallowMountExtended(RuleView, {
+ apolloProvider: fakeApollo,
+ provide: { projectPath, protectedBranchesPath, approvalRulesPath },
+ });
+
+ await waitForPromises();
+ };
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ const findBranchName = () => wrapper.findByTestId('branch');
+ const findBranchTitle = () => wrapper.findByTestId('branch-title');
+ const findBranchProtectionTitle = () => wrapper.findByText(I18N.protectBranchTitle);
+ const findBranchProtections = () => wrapper.findAllComponents(Protection);
+ const findForcePushTitle = () => wrapper.findByText(I18N.allowForcePushDescription);
+ const findApprovalsTitle = () => wrapper.findByText(I18N.approvalsTitle);
+
+ it('gets the branch param from url and renders it in the view', () => {
+ expect(util.getParameterByName).toHaveBeenCalledWith('branch');
+ expect(findBranchName().text()).toBe('main');
+ expect(findBranchTitle().text()).toBe(I18N.branchNameOrPattern);
+ });
+
+ it('renders the correct label if all branches are targeted', async () => {
+ jest.spyOn(util, 'getParameterByName').mockReturnValueOnce(ALL_BRANCHES_WILDCARD);
+ await createComponent();
+
+ expect(findBranchName().text()).toBe(I18N.allBranches);
+ expect(findBranchTitle().text()).toBe(I18N.targetBranch);
+ jest.restoreAllMocks();
+ });
+
+ it('renders the correct branch title', () => {
+ expect(findBranchTitle().exists()).toBe(true);
+ });
+
+ it('renders a branch protection title', () => {
+ expect(findBranchProtectionTitle().exists()).toBe(true);
+ });
+
+ it('renders a branch protection component for push rules', () => {
+ expect(findBranchProtections().at(0).props()).toMatchObject({
+ header: sprintf(I18N.allowedToPushHeader, { total: 2 }),
+ ...protectionMockProps,
+ });
+ });
+
+ it('renders force push protection', () => {
+ expect(findForcePushTitle().exists()).toBe(true);
+ });
+
+ it('renders a branch protection component for merge rules', () => {
+ expect(findBranchProtections().at(1).props()).toMatchObject({
+ header: sprintf(I18N.allowedToMergeHeader, { total: 2 }),
+ ...protectionMockProps,
+ });
+ });
+
+ it('renders a branch protection component for approvals', () => {
+ expect(findApprovalsTitle().exists()).toBe(true);
+
+ expect(findBranchProtections().at(2).props()).toMatchObject({
+ header: sprintf(I18N.approvalsHeader, { total: 0 }),
+ headerLinkHref: approvalRulesPath,
+ headerLinkTitle: I18N.manageApprovalsLinkTitle,
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/view/mock_data.js b/spec/frontend/projects/settings/branch_rules/components/view/mock_data.js
new file mode 100644
index 00000000000..c3f573061da
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/view/mock_data.js
@@ -0,0 +1,141 @@
+const usersMock = [
+ {
+ username: 'usr1',
+ webUrl: 'http://test.test/usr1',
+ name: 'User 1',
+ avatarUrl: 'http://test.test/avt1.png',
+ },
+ {
+ username: 'usr2',
+ webUrl: 'http://test.test/usr2',
+ name: 'User 2',
+ avatarUrl: 'http://test.test/avt2.png',
+ },
+ {
+ username: 'usr3',
+ webUrl: 'http://test.test/usr3',
+ name: 'User 3',
+ avatarUrl: 'http://test.test/avt3.png',
+ },
+ {
+ username: 'usr4',
+ webUrl: 'http://test.test/usr4',
+ name: 'User 4',
+ avatarUrl: 'http://test.test/avt4.png',
+ },
+ {
+ username: 'usr5',
+ webUrl: 'http://test.test/usr5',
+ name: 'User 5',
+ avatarUrl: 'http://test.test/avt5.png',
+ },
+];
+
+const accessLevelsMock = [
+ { accessLevelDescription: 'Administrator' },
+ { accessLevelDescription: 'Maintainer' },
+];
+
+const approvalsRequired = 3;
+
+const groupsMock = [{ name: 'test_group_1' }, { name: 'test_group_2' }];
+
+export const protectionPropsMock = {
+ header: 'Test protection',
+ headerLinkTitle: 'Test link title',
+ headerLinkHref: 'Test link href',
+ roles: accessLevelsMock,
+ users: usersMock,
+ groups: groupsMock,
+ approvals: [
+ {
+ name: 'test',
+ eligibleApprovers: { nodes: usersMock },
+ approvalsRequired,
+ },
+ ],
+};
+
+export const protectionRowPropsMock = {
+ title: 'Test title',
+ users: usersMock,
+ accessLevels: accessLevelsMock,
+ approvalsRequired,
+};
+
+export const accessLevelsMockResponse = [
+ {
+ __typename: 'PushAccessLevelEdge',
+ node: {
+ __typename: 'PushAccessLevel',
+ accessLevel: 40,
+ accessLevelDescription: 'Jona Langworth',
+ group: null,
+ user: {
+ __typename: 'UserCore',
+ id: '123',
+ webUrl: 'test.com',
+ name: 'peter',
+ avatarUrl: 'test.com/user.png',
+ },
+ },
+ },
+ {
+ __typename: 'PushAccessLevelEdge',
+ node: {
+ __typename: 'PushAccessLevel',
+ accessLevel: 40,
+ accessLevelDescription: 'Maintainers',
+ group: null,
+ user: null,
+ },
+ },
+];
+
+export const branchProtectionsMockResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/6',
+ __typename: 'Project',
+ branchRules: {
+ __typename: 'BranchRuleConnection',
+ nodes: [
+ {
+ __typename: 'BranchRule',
+ name: 'main',
+ branchProtection: {
+ __typename: 'BranchProtection',
+ allowForcePush: true,
+ codeOwnerApprovalRequired: true,
+ mergeAccessLevels: {
+ __typename: 'MergeAccessLevelConnection',
+ edges: accessLevelsMockResponse,
+ },
+ pushAccessLevels: {
+ __typename: 'PushAccessLevelConnection',
+ edges: accessLevelsMockResponse,
+ },
+ },
+ },
+ {
+ __typename: 'BranchRule',
+ name: '*',
+ branchProtection: {
+ __typename: 'BranchProtection',
+ allowForcePush: true,
+ codeOwnerApprovalRequired: true,
+ mergeAccessLevels: {
+ __typename: 'MergeAccessLevelConnection',
+ edges: [],
+ },
+ pushAccessLevels: {
+ __typename: 'PushAccessLevelConnection',
+ edges: [],
+ },
+ },
+ },
+ ],
+ },
+ },
+ },
+};
diff --git a/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js
new file mode 100644
index 00000000000..b0a69bedd3e
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js
@@ -0,0 +1,71 @@
+import { GlAvatarsInline, GlAvatar, GlAvatarLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ProtectionRow, {
+ MAX_VISIBLE_AVATARS,
+ AVATAR_SIZE,
+} from '~/projects/settings/branch_rules/components/view/protection_row.vue';
+import { protectionRowPropsMock } from './mock_data';
+
+describe('Branch rule protection row', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(ProtectionRow, {
+ propsData: protectionRowPropsMock,
+ stubs: { GlAvatarsInline },
+ });
+ };
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ const findTitle = () => wrapper.findByText(protectionRowPropsMock.title);
+ const findAvatarsInline = () => wrapper.findComponent(GlAvatarsInline);
+ const findAvatarLinks = () => wrapper.findAllComponents(GlAvatarLink);
+ const findAvatars = () => wrapper.findAllComponents(GlAvatar);
+ const findAccessLevels = () => wrapper.findAllByTestId('access-level');
+ const findApprovalsRequired = () =>
+ wrapper.findByText(`${protectionRowPropsMock.approvalsRequired} approvals required`);
+
+ it('renders a title', () => {
+ expect(findTitle().exists()).toBe(true);
+ });
+
+ it('renders an avatars-inline component', () => {
+ expect(findAvatarsInline().props('avatars')).toMatchObject(protectionRowPropsMock.users);
+ expect(findAvatarsInline().props('badgeSrOnlyText')).toBe('1 additional user');
+ });
+
+ it('renders avatar-link components', () => {
+ expect(findAvatarLinks().length).toBe(MAX_VISIBLE_AVATARS);
+
+ expect(findAvatarLinks().at(1).attributes('href')).toBe(protectionRowPropsMock.users[1].webUrl);
+ expect(findAvatarLinks().at(1).attributes('title')).toBe(protectionRowPropsMock.users[1].name);
+ });
+
+ it('renders avatar components', () => {
+ expect(findAvatars().length).toBe(MAX_VISIBLE_AVATARS);
+
+ expect(findAvatars().at(1).attributes('src')).toBe(protectionRowPropsMock.users[1].avatarUrl);
+ expect(findAvatars().at(1).attributes('label')).toBe(protectionRowPropsMock.users[1].name);
+ expect(findAvatars().at(1).props('size')).toBe(AVATAR_SIZE);
+ });
+
+ it('renders access level descriptions', () => {
+ expect(findAccessLevels().length).toBe(protectionRowPropsMock.accessLevels.length);
+
+ expect(findAccessLevels().at(0).text()).toBe(
+ protectionRowPropsMock.accessLevels[0].accessLevelDescription,
+ );
+ expect(findAccessLevels().at(1).text()).toContain(',');
+
+ expect(findAccessLevels().at(1).text()).toContain(
+ protectionRowPropsMock.accessLevels[1].accessLevelDescription,
+ );
+ });
+
+ it('renders the number of approvals required', () => {
+ expect(findApprovalsRequired().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js
new file mode 100644
index 00000000000..e2fbb4f5bbb
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js
@@ -0,0 +1,68 @@
+import { GlCard, GlLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import Protection, { i18n } from '~/projects/settings/branch_rules/components/view/protection.vue';
+import ProtectionRow from '~/projects/settings/branch_rules/components/view/protection_row.vue';
+import { protectionPropsMock } from './mock_data';
+
+describe('Branch rule protection', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(Protection, {
+ propsData: protectionPropsMock,
+ stubs: { GlCard },
+ });
+ };
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ const findCard = () => wrapper.findComponent(GlCard);
+ const findHeader = () => wrapper.findByText(protectionPropsMock.header);
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findProtectionRows = () => wrapper.findAllComponents(ProtectionRow);
+
+ it('renders a card component', () => {
+ expect(findCard().exists()).toBe(true);
+ });
+
+ it('renders a header with a link', () => {
+ expect(findHeader().exists()).toBe(true);
+ expect(findLink().text()).toBe(protectionPropsMock.headerLinkTitle);
+ expect(findLink().attributes('href')).toBe(protectionPropsMock.headerLinkHref);
+ });
+
+ it('renders a protection row for roles', () => {
+ expect(findProtectionRows().at(0).props()).toMatchObject({
+ accessLevels: protectionPropsMock.roles,
+ showDivider: false,
+ title: i18n.rolesTitle,
+ });
+ });
+
+ it('renders a protection row for users', () => {
+ expect(findProtectionRows().at(1).props()).toMatchObject({
+ users: protectionPropsMock.users,
+ showDivider: true,
+ title: i18n.usersTitle,
+ });
+ });
+
+ it('renders a protection row for groups', () => {
+ expect(findProtectionRows().at(2).props()).toMatchObject({
+ accessLevels: protectionPropsMock.groups,
+ showDivider: true,
+ title: i18n.groupsTitle,
+ });
+ });
+
+ it('renders a protection row for approvals', () => {
+ const approval = protectionPropsMock.approvals[0];
+ expect(findProtectionRows().at(3).props()).toMatchObject({
+ title: approval.name,
+ users: approval.eligibleApprovers.nodes,
+ approvalsRequired: approval.approvalsRequired,
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js b/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js
deleted file mode 100644
index b0b2b9191d4..00000000000
--- a/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import { nextTick } from 'vue';
-import { getParameterByName } from '~/lib/utils/url_utility';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import RuleEdit from '~/projects/settings/branch_rules/components/rule_edit.vue';
-import BranchDropdown from '~/projects/settings/branch_rules/components/branch_dropdown.vue';
-import Protections from '~/projects/settings/branch_rules/components/protections/index.vue';
-
-jest.mock('~/lib/utils/url_utility', () => ({
- getParameterByName: jest.fn().mockImplementation(() => 'main'),
- joinPaths: jest.fn(),
- setUrlFragment: jest.fn(),
-}));
-
-describe('Edit branch rule', () => {
- let wrapper;
- const projectPath = 'test/testing';
-
- const createComponent = () => {
- wrapper = shallowMountExtended(RuleEdit, { propsData: { projectPath } });
- };
-
- const findBranchDropdown = () => wrapper.findComponent(BranchDropdown);
- const findProtections = () => wrapper.findComponent(Protections);
-
- beforeEach(() => createComponent());
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('gets the branch param from url', () => {
- expect(getParameterByName).toHaveBeenCalledWith('branch');
- });
-
- describe('BranchDropdown', () => {
- it('renders a BranchDropdown component with the correct props', () => {
- expect(findBranchDropdown().props()).toMatchObject({
- projectPath,
- value: 'main',
- });
- });
-
- it('sets the correct value when `input` is emitted', async () => {
- const branch = 'test';
- findBranchDropdown().vm.$emit('input', branch);
- await nextTick();
- expect(findBranchDropdown().props('value')).toBe(branch);
- });
-
- it('sets the correct value when `createWildcard` is emitted', async () => {
- const wildcard = 'test-*';
- findBranchDropdown().vm.$emit('createWildcard', wildcard);
- await nextTick();
- expect(findBranchDropdown().props('value')).toBe(wildcard);
- });
- });
-
- describe('Protections', () => {
- it('renders a Protections component with the correct props', () => {
- expect(findProtections().props('protections')).toMatchObject({
- membersAllowedToPush: [],
- allowForcePush: false,
- membersAllowedToMerge: [],
- requireCodeOwnersApproval: false,
- });
- });
-
- it('updates protections when change-allowed-to-push-members is emitted', async () => {
- const membersAllowedToPush = ['test'];
- findProtections().vm.$emit('change-allowed-to-push-members', membersAllowedToPush);
- await nextTick();
-
- expect(findProtections().props('protections')).toEqual(
- expect.objectContaining({ membersAllowedToPush }),
- );
- });
-
- it('updates protections when change-allow-force-push is emitted', async () => {
- const allowForcePush = true;
- findProtections().vm.$emit('change-allow-force-push', allowForcePush);
- await nextTick();
-
- expect(findProtections().props('protections')).toEqual(
- expect.objectContaining({ allowForcePush }),
- );
- });
-
- it('updates protections when change-allowed-to-merge-members is emitted', async () => {
- const membersAllowedToMerge = ['test'];
- findProtections().vm.$emit('change-allowed-to-merge-members', membersAllowedToMerge);
- await nextTick();
-
- expect(findProtections().props('protections')).toEqual(
- expect.objectContaining({ membersAllowedToMerge }),
- );
- });
-
- it('updates protections when change-require-code-owners-approval is emitted', async () => {
- const requireCodeOwnersApproval = true;
- findProtections().vm.$emit('change-require-code-owners-approval', requireCodeOwnersApproval);
- await nextTick();
-
- expect(findProtections().props('protections')).toEqual(
- expect.objectContaining({ requireCodeOwnersApproval }),
- );
- });
- });
-});
diff --git a/spec/frontend/projects/settings/components/default_branch_selector_spec.js b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
new file mode 100644
index 00000000000..94648d87524
--- /dev/null
+++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
@@ -0,0 +1,46 @@
+import { shallowMount } from '@vue/test-utils';
+import DefaultBranchSelector from '~/projects/settings/components/default_branch_selector.vue';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { REF_TYPE_BRANCHES } from '~/ref/constants';
+
+describe('projects/settings/components/default_branch_selector', () => {
+ const persistedDefaultBranch = 'main';
+ const projectId = '123';
+ let wrapper;
+
+ const findRefSelector = () => wrapper.findComponent(RefSelector);
+
+ const buildWrapper = () => {
+ wrapper = shallowMount(DefaultBranchSelector, {
+ propsData: {
+ persistedDefaultBranch,
+ projectId,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('displays a RefSelector component', () => {
+ expect(findRefSelector().props()).toEqual({
+ value: persistedDefaultBranch,
+ enabledRefTypes: [REF_TYPE_BRANCHES],
+ projectId,
+ state: true,
+ translations: {
+ dropdownHeader: expect.any(String),
+ searchPlaceholder: expect.any(String),
+ },
+ useSymbolicRefNames: false,
+ name: 'project[default_branch]',
+ });
+
+ expect(findRefSelector().classes()).toContain('gl-w-full');
+ });
+});
diff --git a/spec/frontend/projects/settings/components/transfer_project_form_spec.js b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
index bde7148078d..6e639f895a8 100644
--- a/spec/frontend/projects/settings/components/transfer_project_form_spec.js
+++ b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
@@ -1,41 +1,65 @@
import Vue, { nextTick } from 'vue';
+import { GlAlert } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
-import searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1 from 'test_fixtures/graphql/projects/settings/search_namespaces_where_user_can_transfer_projects_page_1.query.graphql.json';
-import searchNamespacesWhereUserCanTransferProjectsQueryResponsePage2 from 'test_fixtures/graphql/projects/settings/search_namespaces_where_user_can_transfer_projects_page_2.query.graphql.json';
-import {
- groupNamespaces,
- userNamespaces,
-} from 'jest/vue_shared/components/namespace_select/mock_data';
+import currentUserNamespaceQueryResponse from 'test_fixtures/graphql/projects/settings/current_user_namespace.query.graphql.json';
+import transferLocationsResponsePage1 from 'test_fixtures/api/projects/transfer_locations_page_1.json';
+import transferLocationsResponsePage2 from 'test_fixtures/api/projects/transfer_locations_page_2.json';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import TransferProjectForm from '~/projects/settings/components/transfer_project_form.vue';
-import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select_deprecated.vue';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
-import searchNamespacesWhereUserCanTransferProjectsQuery from '~/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql';
+import currentUserNamespaceQuery from '~/projects/settings/graphql/queries/current_user_namespace.query.graphql';
+import { getTransferLocations } from '~/api/projects_api';
import waitForPromises from 'helpers/wait_for_promises';
+jest.mock('~/api/projects_api', () => ({
+ getTransferLocations: jest.fn(),
+}));
+
describe('Transfer project form', () => {
let wrapper;
+ const projectId = '1';
const confirmButtonText = 'Confirm';
const confirmationPhrase = 'You must construct additional pylons!';
- const runDebounce = () => jest.runAllTimers();
-
Vue.use(VueApollo);
- const defaultQueryHandler = jest
- .fn()
- .mockResolvedValue(searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1);
+ const defaultQueryHandler = jest.fn().mockResolvedValue(currentUserNamespaceQueryResponse);
+ const mockResolvedGetTransferLocations = ({
+ data = transferLocationsResponsePage1,
+ page = '1',
+ nextPage = '2',
+ prevPage = null,
+ } = {}) => {
+ getTransferLocations.mockResolvedValueOnce({
+ data,
+ headers: {
+ 'x-per-page': '2',
+ 'x-page': page,
+ 'x-total': '4',
+ 'x-total-pages': '2',
+ 'x-next-page': nextPage,
+ 'x-prev-page': prevPage,
+ },
+ });
+ };
+ const mockRejectedGetTransferLocations = () => {
+ const error = new Error();
+
+ getTransferLocations.mockRejectedValueOnce(error);
+ };
const createComponent = ({
- requestHandlers = [[searchNamespacesWhereUserCanTransferProjectsQuery, defaultQueryHandler]],
+ requestHandlers = [[currentUserNamespaceQuery, defaultQueryHandler]],
} = {}) => {
wrapper = shallowMountExtended(TransferProjectForm, {
+ provide: {
+ projectId,
+ },
propsData: {
- userNamespaces,
- groupNamespaces,
confirmButtonText,
confirmationPhrase,
},
@@ -44,7 +68,12 @@ describe('Transfer project form', () => {
};
const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect);
+ const showNamespaceSelect = async () => {
+ findNamespaceSelect().vm.$emit('show');
+ await waitForPromises();
+ };
const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger);
+ const findAlert = () => wrapper.findComponent(GlAlert);
afterEach(() => {
wrapper.destroy();
@@ -69,66 +98,113 @@ describe('Transfer project form', () => {
});
describe('with a selected namespace', () => {
- const [selectedItem] = groupNamespaces;
+ const [selectedItem] = transferLocationsResponsePage1;
- beforeEach(() => {
+ const arrange = async () => {
+ mockResolvedGetTransferLocations();
createComponent();
-
+ await showNamespaceSelect();
findNamespaceSelect().vm.$emit('select', selectedItem);
- });
+ };
+
+ it('emits the `selectNamespace` event when a namespace is selected', async () => {
+ await arrange();
- 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', () => {
+ it('enables the confirm button', async () => {
+ await arrange();
+
expect(findConfirmDanger().attributes('disabled')).toBeUndefined();
});
- it('clicking the confirm button emits the `confirm` event', () => {
+ it('clicking the confirm button emits the `confirm` event', async () => {
+ await arrange();
+
findConfirmDanger().vm.$emit('confirm');
expect(wrapper.emitted('confirm')).toBeDefined();
});
});
- it('passes correct props to `NamespaceSelect` component', async () => {
- createComponent();
+ describe('when `NamespaceSelect` is opened', () => {
+ it('fetches user and group namespaces and passes correct props to `NamespaceSelect` component', async () => {
+ mockResolvedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
+
+ const { namespace } = currentUserNamespaceQueryResponse.data.currentUser;
+
+ expect(findNamespaceSelect().props()).toMatchObject({
+ userNamespaces: [
+ {
+ id: getIdFromGraphQLId(namespace.id),
+ humanName: namespace.fullName,
+ },
+ ],
+ groupNamespaces: transferLocationsResponsePage1.map(({ id, full_name: humanName }) => ({
+ id,
+ humanName,
+ })),
+ hasNextPageOfGroups: true,
+ isLoading: false,
+ isSearchLoading: false,
+ shouldFilterNamespaces: false,
+ });
+ });
- runDebounce();
- await waitForPromises();
+ describe('when namespaces have already been fetched', () => {
+ beforeEach(async () => {
+ mockResolvedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
+ });
+
+ it('does not fetch namespaces', async () => {
+ getTransferLocations.mockClear();
+ defaultQueryHandler.mockClear();
+
+ await showNamespaceSelect();
- const {
- namespace,
- groups,
- } = searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1.data.currentUser;
-
- expect(findNamespaceSelect().props()).toMatchObject({
- userNamespaces: [
- {
- id: getIdFromGraphQLId(namespace.id),
- humanName: namespace.fullName,
- },
- ],
- groupNamespaces: groups.nodes.map((node) => ({
- id: getIdFromGraphQLId(node.id),
- humanName: node.fullName,
- })),
- hasNextPageOfGroups: true,
- isLoadingMoreGroups: false,
- isSearchLoading: false,
- shouldFilterNamespaces: false,
+ expect(getTransferLocations).not.toHaveBeenCalled();
+ expect(defaultQueryHandler).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when `getTransferLocations` API call fails', () => {
+ it('displays error alert', async () => {
+ mockRejectedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
+ describe('when `currentUser` GraphQL query fails', () => {
+ it('displays error alert', async () => {
+ mockResolvedGetTransferLocations();
+ const error = new Error();
+ createComponent({
+ requestHandlers: [[currentUserNamespaceQuery, jest.fn().mockRejectedValueOnce(error)]],
+ });
+ await showNamespaceSelect();
+
+ expect(findAlert().exists()).toBe(true);
+ });
});
});
describe('when `search` event is fired', () => {
const arrange = async () => {
+ mockResolvedGetTransferLocations();
createComponent();
-
+ await showNamespaceSelect();
+ mockResolvedGetTransferLocations();
findNamespaceSelect().vm.$emit('search', 'foo');
-
await nextTick();
};
@@ -138,87 +214,106 @@ describe('Transfer project form', () => {
expect(findNamespaceSelect().props('isSearchLoading')).toBe(true);
});
- it('passes `search` variable to query', async () => {
+ it('passes `search` param to API call', async () => {
await arrange();
- runDebounce();
await waitForPromises();
- expect(defaultQueryHandler).toHaveBeenCalledWith(expect.objectContaining({ search: 'foo' }));
+ expect(getTransferLocations).toHaveBeenCalledWith(
+ projectId,
+ expect.objectContaining({ search: 'foo' }),
+ );
+ });
+
+ describe('when `getTransferLocations` API call fails', () => {
+ it('displays dismissible error alert', async () => {
+ mockResolvedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
+ mockRejectedGetTransferLocations();
+ findNamespaceSelect().vm.$emit('search', 'foo');
+ await waitForPromises();
+
+ const alert = findAlert();
+
+ expect(alert.exists()).toBe(true);
+
+ alert.vm.$emit('dismiss');
+ await nextTick();
+
+ expect(alert.exists()).toBe(false);
+ });
});
});
describe('when `load-more-groups` event is fired', () => {
- let queryHandler;
-
const arrange = async () => {
- queryHandler = jest.fn();
- queryHandler.mockResolvedValueOnce(
- searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1,
- );
- queryHandler.mockResolvedValueOnce(
- searchNamespacesWhereUserCanTransferProjectsQueryResponsePage2,
- );
+ mockResolvedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
- createComponent({
- requestHandlers: [[searchNamespacesWhereUserCanTransferProjectsQuery, queryHandler]],
+ mockResolvedGetTransferLocations({
+ data: transferLocationsResponsePage2,
+ page: '2',
+ nextPage: null,
+ prevPage: '1',
});
- runDebounce();
- await waitForPromises();
-
findNamespaceSelect().vm.$emit('load-more-groups');
await nextTick();
};
- it('sets `isLoadingMoreGroups` prop to `true`', async () => {
+ it('sets `isLoading` prop to `true`', async () => {
await arrange();
- expect(findNamespaceSelect().props('isLoadingMoreGroups')).toBe(true);
+ expect(findNamespaceSelect().props('isLoading')).toBe(true);
});
- it('passes `after` and `first` variables to query', async () => {
+ it('passes `page` param to API call', async () => {
await arrange();
- runDebounce();
await waitForPromises();
- expect(queryHandler).toHaveBeenCalledWith(
- expect.objectContaining({
- first: 25,
- after:
- searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1.data.currentUser.groups
- .pageInfo.endCursor,
- }),
+ expect(getTransferLocations).toHaveBeenCalledWith(
+ projectId,
+ expect.objectContaining({ page: 2 }),
);
});
it('updates `groupNamespaces` prop with new groups', async () => {
await arrange();
- runDebounce();
await waitForPromises();
- expect(findNamespaceSelect().props('groupNamespaces')).toEqual(
- [
- ...searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1.data.currentUser.groups
- .nodes,
- ...searchNamespacesWhereUserCanTransferProjectsQueryResponsePage2.data.currentUser.groups
- .nodes,
- ].map((node) => ({
- id: getIdFromGraphQLId(node.id),
- humanName: node.fullName,
- })),
+ expect(findNamespaceSelect().props('groupNamespaces')).toMatchObject(
+ [...transferLocationsResponsePage1, ...transferLocationsResponsePage2].map(
+ ({ id, full_name: humanName }) => ({
+ id,
+ humanName,
+ }),
+ ),
);
});
it('updates `hasNextPageOfGroups` prop', async () => {
await arrange();
- runDebounce();
await waitForPromises();
expect(findNamespaceSelect().props('hasNextPageOfGroups')).toBe(false);
});
+
+ describe('when `getTransferLocations` API call fails', () => {
+ it('displays error alert', async () => {
+ mockResolvedGetTransferLocations();
+ createComponent();
+ await showNamespaceSelect();
+ mockRejectedGetTransferLocations();
+ findNamespaceSelect().vm.$emit('load-more-groups');
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
});
});
diff --git a/spec/frontend/projects/settings/repository/branch_rules/app_spec.js b/spec/frontend/projects/settings/repository/branch_rules/app_spec.js
index e920cd48163..4603436c40a 100644
--- a/spec/frontend/projects/settings/repository/branch_rules/app_spec.js
+++ b/spec/frontend/projects/settings/repository/branch_rules/app_spec.js
@@ -6,8 +6,8 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import BranchRules, { i18n } from '~/projects/settings/repository/branch_rules/app.vue';
import BranchRule from '~/projects/settings/repository/branch_rules/components/branch_rule.vue';
import branchRulesQuery from '~/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql';
-import createFlash from '~/flash';
-import { branchRulesMockResponse, propsDataMock } from './mock_data';
+import { createAlert } from '~/flash';
+import { branchRulesMockResponse, appProvideMock } from './mock_data';
jest.mock('~/flash');
@@ -24,9 +24,7 @@ describe('Branch rules app', () => {
wrapper = mountExtended(BranchRules, {
apolloProvider: fakeApollo,
- propsData: {
- ...propsDataMock,
- },
+ provide: appProvideMock,
});
await waitForPromises();
@@ -39,7 +37,7 @@ describe('Branch rules app', () => {
it('displays an error if branch rules query fails', async () => {
await createComponent({ queryHandler: jest.fn().mockRejectedValue() });
- expect(createFlash).toHaveBeenCalledWith({ message: i18n.queryError });
+ expect(createAlert).toHaveBeenCalledWith({ message: i18n.queryError });
});
it('displays an empty state if no branch rules are present', async () => {
@@ -49,7 +47,11 @@ describe('Branch rules app', () => {
it('renders branch rules', () => {
const { nodes } = branchRulesMockResponse.data.project.branchRules;
- expect(findAllBranchRules().at(0).text()).toBe(nodes[0].name);
- expect(findAllBranchRules().at(1).text()).toBe(nodes[1].name);
+
+ expect(findAllBranchRules().length).toBe(nodes.length);
+
+ expect(findAllBranchRules().at(0).props('name')).toBe(nodes[0].name);
+
+ expect(findAllBranchRules().at(1).props('name')).toBe(nodes[1].name);
});
});
diff --git a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js
index 924dab60704..2bc705f538b 100644
--- a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js
+++ b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js
@@ -2,26 +2,24 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import BranchRule, {
i18n,
} from '~/projects/settings/repository/branch_rules/components/branch_rule.vue';
-
-const defaultProps = {
- name: 'main',
- isDefault: true,
- isProtected: true,
- approvalDetails: ['requires approval from TEST', '2 status checks'],
-};
+import { branchRuleProvideMock, branchRulePropsMock } from '../mock_data';
describe('Branch rule', () => {
let wrapper;
const createComponent = (props = {}) => {
- wrapper = shallowMountExtended(BranchRule, { propsData: { ...defaultProps, ...props } });
+ wrapper = shallowMountExtended(BranchRule, {
+ provide: branchRuleProvideMock,
+ propsData: { ...branchRulePropsMock, ...props },
+ });
};
const findDefaultBadge = () => wrapper.findByText(i18n.defaultLabel);
const findProtectedBadge = () => wrapper.findByText(i18n.protectedLabel);
- const findBranchName = () => wrapper.findByText(defaultProps.name);
+ const findBranchName = () => wrapper.findByText(branchRulePropsMock.name);
const findProtectionDetailsList = () => wrapper.findByRole('list');
const findProtectionDetailsListItems = () => wrapper.findAllByRole('listitem');
+ const findDetailsButton = () => wrapper.findByText(i18n.detailsButtonLabel);
beforeEach(() => createComponent());
@@ -52,7 +50,17 @@ describe('Branch rule', () => {
});
it('renders the protection details list items', () => {
- expect(findProtectionDetailsListItems().at(0).text()).toBe(defaultProps.approvalDetails[0]);
- expect(findProtectionDetailsListItems().at(1).text()).toBe(defaultProps.approvalDetails[1]);
+ expect(findProtectionDetailsListItems().at(0).text()).toBe(
+ branchRulePropsMock.approvalDetails[0],
+ );
+ expect(findProtectionDetailsListItems().at(1).text()).toBe(
+ branchRulePropsMock.approvalDetails[1],
+ );
+ });
+
+ it('renders a detail button with the correct href', () => {
+ expect(findDetailsButton().attributes('href')).toBe(
+ `${branchRuleProvideMock.branchRulesPath}?branch=${branchRulePropsMock.name}`,
+ );
});
});
diff --git a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js
index 14ed35f047d..bac82992c4d 100644
--- a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js
+++ b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js
@@ -20,6 +20,17 @@ export const branchRulesMockResponse = {
},
};
-export const propsDataMock = {
+export const appProvideMock = {
projectPath: 'some/project/path',
};
+
+export const branchRuleProvideMock = {
+ branchRulesPath: 'settings/repository/branch_rules',
+};
+
+export const branchRulePropsMock = {
+ name: 'main',
+ isDefault: true,
+ isProtected: true,
+ approvalDetails: ['requires approval from TEST', '2 status checks'],
+};
diff --git a/spec/frontend/protected_branches/protected_branch_edit_spec.js b/spec/frontend/protected_branches/protected_branch_edit_spec.js
index 6ef1b58a956..0aec4fbc037 100644
--- a/spec/frontend/protected_branches/protected_branch_edit_spec.js
+++ b/spec/frontend/protected_branches/protected_branch_edit_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import ProtectedBranchEdit from '~/protected_branches/protected_branch_edit';
@@ -136,7 +136,7 @@ describe('ProtectedBranchEdit', () => {
expect(toggle).not.toHaveClass(IS_DISABLED_CLASS);
expect(toggle.querySelector(IS_LOADING_SELECTOR)).toBe(null);
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -149,7 +149,7 @@ describe('ProtectedBranchEdit', () => {
it('flashes error', async () => {
await axios.waitForAll();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 6c5af5a2625..96601a729b2 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -109,6 +109,8 @@ describe('Ref selector component', () => {
const findCommitDropdownItems = () => findCommitsSection().findAllComponents(GlDropdownItem);
const findFirstCommitDropdownItem = () => findCommitDropdownItems().at(0);
+ const findHiddenInputField = () => wrapper.find('[data-testid="selected-ref-form-field"]');
+
//
// Expecters
//
@@ -181,6 +183,24 @@ describe('Ref selector component', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
});
+
+ describe('when name property is provided', () => {
+ it('renders an forrm input hidden field', () => {
+ const name = 'default_tag';
+
+ createComponent({ propsData: { name } });
+
+ expect(findHiddenInputField().attributes().name).toBe(name);
+ });
+ });
+
+ describe('when name property is not provided', () => {
+ it('renders an forrm input hidden field', () => {
+ createComponent();
+
+ expect(findHiddenInputField().exists()).toBe(false);
+ });
+ });
});
describe('post-initialization behavior', () => {
@@ -194,7 +214,7 @@ describe('Ref selector component', () => {
});
it('adds the provided ID to the GlDropdown instance', () => {
- expect(wrapper.attributes().id).toBe(id);
+ expect(wrapper.findComponent(GlDropdown).attributes().id).toBe(id);
});
});
@@ -202,7 +222,7 @@ describe('Ref selector component', () => {
const preselectedRef = fixtures.branches[0].name;
beforeEach(() => {
- createComponent({ propsData: { value: preselectedRef } });
+ createComponent({ propsData: { value: preselectedRef, name: 'selectedRef' } });
return waitForRequests();
});
@@ -210,6 +230,10 @@ describe('Ref selector component', () => {
it('renders the pre-selected ref name', () => {
expect(findButtonContent().text()).toBe(preselectedRef);
});
+
+ it('binds hidden input field to the pre-selected ref', () => {
+ expect(findHiddenInputField().attributes().value).toBe(preselectedRef);
+ });
});
describe('when the selected ref is updated by the parent component', () => {
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index 55e3dda60a0..d88d79d2cde 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -155,8 +155,8 @@ Object {
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",
+ "filepath": Any<String>,
+ "id": Any<String>,
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
@@ -198,10 +198,10 @@ Object {
],
"paginationInfo": Object {
"__typename": "PageInfo",
- "endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwICswMDAwIiwiaWQiOiIxIn0",
+ "endCursor": Any<String>,
"hasNextPage": false,
"hasPreviousPage": false,
- "startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTktMDEtMTAgMDA6MDA6MDAuMDAwMDAwMDAwICswMDAwIiwiaWQiOiIyIn0",
+ "startCursor": Any<String>,
},
}
`;
@@ -377,8 +377,8 @@ Object {
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",
+ "filepath": Any<String>,
+ "id": Any<String>,
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js
index f64f07de90e..48589a54ec4 100644
--- a/spec/frontend/releases/components/app_index_spec.js
+++ b/spec/frontend/releases/components/app_index_spec.js
@@ -6,7 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { historyPushState } from '~/lib/utils/common_utils';
import { sprintf, __ } from '~/locale';
import ReleasesIndexApp from '~/releases/components/app_index.vue';
@@ -161,13 +161,13 @@ describe('app_index.vue', () => {
it(`${toDescription(flashMessage)} show a flash message`, async () => {
await waitForPromises();
if (flashMessage) {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: ReleasesIndexApp.i18n.errorMessage,
captureError: true,
error: expect.any(Error),
});
} else {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
}
});
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index 9ca25b3b69a..c5cb8589ee8 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import oneReleaseQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/one_release.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import ReleaseShowApp from '~/releases/components/app_show.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
@@ -53,13 +53,13 @@ describe('Release show component', () => {
const expectNoFlash = () => {
it('does not show a flash message', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
};
const expectFlashWithMessage = (message) => {
it(`shows a flash message that reads "${message}"`, () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message,
captureError: true,
error: expect.any(Error),
diff --git a/spec/frontend/releases/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js
index 2db1e9e38a2..6f935215dd7 100644
--- a/spec/frontend/releases/components/evidence_block_spec.js
+++ b/spec/frontend/releases/components/evidence_block_spec.js
@@ -36,7 +36,7 @@ describe('Evidence Block', () => {
});
it('renders the title for the dowload link', () => {
- expect(wrapper.findComponent(GlLink).text()).toBe(`v1.1-evidences-1.json`);
+ expect(wrapper.findComponent(GlLink).text()).toMatch(/v1\.1-evidences-[0-9]+\.json/);
});
it('renders the correct hover text for the download', () => {
@@ -44,7 +44,9 @@ describe('Evidence Block', () => {
});
it('renders the correct file link for download', () => {
- expect(wrapper.findComponent(GlLink).attributes().download).toBe(`v1.1-evidences-1.json`);
+ expect(wrapper.findComponent(GlLink).attributes().download).toMatch(
+ /v1\.1-evidences-[0-9]+\.json/,
+ );
});
describe('sha text', () => {
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index b8047cae8c2..fcba0da3462 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -1,14 +1,17 @@
-import { GlDropdownItem } from '@gitlab/ui';
+import { GlDropdownItem, GlFormGroup, GlSprintf } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
+import { trimText } from 'helpers/text_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { __ } from '~/locale';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
import createEditNewModule from '~/releases/stores/modules/edit_new';
const TEST_TAG_NAME = 'test-tag-name';
+const TEST_TAG_MESSAGE = 'Test tag message';
const TEST_PROJECT_ID = '1234';
const TEST_CREATE_FROM = 'test-create-from';
const NONEXISTENT_TAG_NAME = 'nonexistent-tag';
@@ -47,6 +50,8 @@ describe('releases/components/tag_field_new', () => {
store,
stubs: {
RefSelector: RefSelectorStub,
+ GlFormGroup,
+ GlSprintf,
},
});
};
@@ -61,9 +66,11 @@ describe('releases/components/tag_field_new', () => {
});
store.state.editNew.createFrom = TEST_CREATE_FROM;
+ store.state.editNew.showCreateFrom = true;
store.state.editNew.release = {
tagName: TEST_TAG_NAME,
+ tagMessage: '',
assets: {
links: [],
},
@@ -86,6 +93,9 @@ describe('releases/components/tag_field_new', () => {
const findCreateNewTagOption = () => wrapper.findComponent(GlDropdownItem);
+ const findAnnotatedTagMessageFormGroup = () =>
+ wrapper.find('[data-testid="annotated-tag-message-field"]');
+
describe('"Tag name" field', () => {
describe('rendering and behavior', () => {
beforeEach(() => createComponent());
@@ -124,6 +134,10 @@ describe('releases/components/tag_field_new', () => {
expect(findCreateFromFormGroup().exists()).toBe(false);
});
+ it('hides the "Tag message" field', () => {
+ expect(findAnnotatedTagMessageFormGroup().exists()).toBe(false);
+ });
+
it('fetches the release notes for the tag', () => {
const expectedUrl = `/api/v4/projects/1234/repository/tags/${updatedTagName}`;
expect(mock.history.get).toContainEqual(expect.objectContaining({ url: expectedUrl }));
@@ -230,4 +244,34 @@ describe('releases/components/tag_field_new', () => {
});
});
});
+
+ describe('"Annotated Tag" field', () => {
+ beforeEach(() => {
+ createComponent(mountExtended);
+ });
+
+ it('renders a label', () => {
+ expect(wrapper.findByRole('textbox', { name: 'Set tag message' }).exists()).toBe(true);
+ });
+
+ it('renders a description', () => {
+ expect(trimText(findAnnotatedTagMessageFormGroup().text())).toContain(
+ 'Add a message to the tag. Leaving this blank creates a lightweight tag.',
+ );
+ });
+
+ it('updates the store', async () => {
+ await findAnnotatedTagMessageFormGroup().find('textarea').setValue(TEST_TAG_MESSAGE);
+
+ expect(store.state.editNew.release.tagMessage).toBe(TEST_TAG_MESSAGE);
+ });
+
+ it('shows a link', () => {
+ const link = wrapper.findByRole('link', {
+ name: 'lightweight tag',
+ });
+
+ expect(link.attributes('href')).toBe('https://git-scm.com/book/en/v2/Git-Basics-Tagging/');
+ });
+ });
});
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index 48fba3adb24..eeee6747349 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -2,7 +2,7 @@ import { cloneDeep } from 'lodash';
import originalOneReleaseForEditingQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/one_release_for_editing.query.graphql.json';
import testAction from 'helpers/vuex_action_helper';
import { getTag } from '~/api/tags_api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { ASSET_LINK_TYPE } from '~/releases/constants';
@@ -59,7 +59,7 @@ describe('Release edit/new actions', () => {
releaseResponse = cloneDeep(originalOneReleaseForEditingQueryResponse);
gon.api_version = 'v4';
error = new Error('Yikes!');
- createFlash.mockClear();
+ createAlert.mockClear();
});
describe('when creating a new release', () => {
@@ -151,8 +151,8 @@ describe('Release edit/new actions', () => {
it(`shows a flash message`, () => {
return actions.fetchRelease({ commit: jest.fn(), state, rootState: state }).then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while getting the release details.',
});
});
@@ -169,6 +169,15 @@ describe('Release edit/new actions', () => {
});
});
+ describe('updateReleaseTagMessage', () => {
+ it(`commits ${types.UPDATE_RELEASE_TAG_MESSAGE} with the updated tag name`, () => {
+ const newMessage = 'updated-tag-message';
+ return testAction(actions.updateReleaseTagMessage, newMessage, state, [
+ { type: types.UPDATE_RELEASE_TAG_MESSAGE, payload: newMessage },
+ ]);
+ });
+ });
+
describe('updateReleasedAt', () => {
it(`commits ${types.UPDATE_RELEASED_AT} with the updated date`, () => {
const newDate = new Date();
@@ -370,8 +379,8 @@ describe('Release edit/new actions', () => {
return actions
.createRelease({ commit: jest.fn(), dispatch: jest.fn(), state, getters: {} })
.then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Yikes!',
});
});
@@ -396,8 +405,8 @@ describe('Release edit/new actions', () => {
return actions
.createRelease({ commit: jest.fn(), dispatch: jest.fn(), state, getters: {} })
.then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while creating a new release.',
});
});
@@ -527,8 +536,8 @@ describe('Release edit/new actions', () => {
it('shows a flash message', async () => {
await actions.updateRelease({ commit, dispatch, state, getters });
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while saving the release details.',
});
});
@@ -547,8 +556,8 @@ describe('Release edit/new actions', () => {
it('shows a flash message', async () => {
await actions.updateRelease({ commit, dispatch, state, getters });
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while saving the release details.',
});
});
@@ -700,8 +709,8 @@ describe('Release edit/new actions', () => {
it('shows a flash message', async () => {
await actions.deleteRelease({ commit, dispatch, state, getters });
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while deleting the release.',
});
});
@@ -736,8 +745,8 @@ describe('Release edit/new actions', () => {
it('shows a flash message', async () => {
await actions.deleteRelease({ commit, dispatch, state, getters });
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledTimes(1);
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while deleting the release.',
});
});
@@ -779,7 +788,7 @@ describe('Release edit/new actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: s__('Release|Unable to fetch the tag notes.'),
});
expect(getTag).toHaveBeenCalledWith(state.projectId, tagName);
diff --git a/spec/frontend/releases/stores/modules/detail/getters_spec.js b/spec/frontend/releases/stores/modules/detail/getters_spec.js
index 2982dc5c46c..f8b87ec71dc 100644
--- a/spec/frontend/releases/stores/modules/detail/getters_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/getters_spec.js
@@ -317,7 +317,7 @@ describe('Release edit/new getters', () => {
{ milestones: ['release.milestone[0].title'] },
],
])('releaseUpdateMutatationVariables', (description, state, expectedVariables) => {
- it(description, () => {
+ it(`${description}`, () => {
const expectedVariablesObject = { input: expect.objectContaining(expectedVariables) };
const actualVariables = getters.releaseUpdateMutatationVariables(state, {
@@ -332,6 +332,7 @@ describe('Release edit/new getters', () => {
it('returns all the data needed for the releaseCreate GraphQL query', () => {
const state = {
createFrom: 'main',
+ release: { tagMessage: 'hello' },
};
const otherGetters = {
@@ -352,6 +353,7 @@ describe('Release edit/new getters', () => {
const expectedVariables = {
input: {
name: 'release.name',
+ tagMessage: 'hello',
ref: 'main',
assets: {
links: [
diff --git a/spec/frontend/releases/stores/modules/detail/mutations_spec.js b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
index 8bbf550b77d..944769d22cc 100644
--- a/spec/frontend/releases/stores/modules/detail/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
@@ -26,6 +26,7 @@ describe('Release edit/new mutations', () => {
expect(state.release).toEqual({
tagName: 'v1.3',
+ tagMessage: '',
name: '',
description: '',
milestones: [],
@@ -90,6 +91,16 @@ describe('Release edit/new mutations', () => {
});
});
+ describe(`${types.UPDATE_RELEASE_TAG_MESSAGE}`, () => {
+ it("updates the release's tag message", () => {
+ state.release = release;
+ const newMessage = 'updated-tag-message';
+ mutations[types.UPDATE_RELEASE_TAG_MESSAGE](state, newMessage);
+
+ expect(state.release.tagMessage).toBe(newMessage);
+ });
+ });
+
describe(`${types.UPDATE_RELEASED_AT}`, () => {
it("updates the release's released at date", () => {
state.release = release;
diff --git a/spec/frontend/releases/util_spec.js b/spec/frontend/releases/util_spec.js
index 055c8e8b39f..14cce8320e9 100644
--- a/spec/frontend/releases/util_spec.js
+++ b/spec/frontend/releases/util_spec.js
@@ -115,8 +115,18 @@ describe('releases/util.js', () => {
author: {
id: expect.any(String),
},
+ evidences: [
+ {
+ id: expect.any(String),
+ filepath: expect.any(String),
+ },
+ ],
},
],
+ paginationInfo: {
+ startCursor: expect.any(String),
+ endCursor: expect.any(String),
+ },
});
});
});
@@ -128,6 +138,12 @@ describe('releases/util.js', () => {
author: {
id: expect.any(String),
},
+ evidences: [
+ {
+ id: expect.any(String),
+ filepath: expect.any(String),
+ },
+ ],
},
});
});
diff --git a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js b/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
deleted file mode 100644
index d835ca4c733..00000000000
--- a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
-
-const issue = {
- name:
- 'The accessibility scanning found 2 errors of the following type: WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- message: 'This element has insufficient contrast at this conformance level.',
- status: 'failed',
- className: 'spec.test_spec',
- learnMoreUrl: 'https://www.w3.org/TR/WCAG20-TECHS/H91.html',
-};
-
-describe('CustomMetricsForm', () => {
- let wrapper;
-
- const mountComponent = ({ name, code, message, status, className }, isNew = false) => {
- wrapper = shallowMount(AccessibilityIssueBody, {
- propsData: {
- issue: {
- name,
- code,
- message,
- status,
- className,
- },
- isNew,
- },
- });
- };
-
- const findIsNewBadge = () => wrapper.findComponent(GlBadge);
-
- beforeEach(() => {
- mountComponent(issue);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Displays the issue message', () => {
- const description = wrapper.findComponent({ ref: 'accessibility-issue-description' }).text();
-
- expect(description).toContain(`Message: ${issue.message}`);
- });
-
- describe('When an issue code is present', () => {
- it('Creates the correct URL for learning more about the issue code', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe(issue.learnMoreUrl);
- });
- });
-
- describe('When an issue code is not present', () => {
- beforeEach(() => {
- mountComponent({
- ...issue,
- code: undefined,
- });
- });
-
- it('Creates a URL leading to the overview documentation page', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
- });
- });
-
- describe('When an issue code does not contain the TECHS code', () => {
- beforeEach(() => {
- mountComponent({
- ...issue,
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2',
- });
- });
-
- it('Creates a URL leading to the overview documentation page', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
- });
- });
-
- describe('When issue is new', () => {
- beforeEach(() => {
- mountComponent(issue, true);
- });
-
- it('Renders the new badge', () => {
- expect(findIsNewBadge().exists()).toBe(true);
- });
- });
-
- describe('When issue is not new', () => {
- beforeEach(() => {
- mountComponent(issue, false);
- });
-
- it('Does not render the new badge', () => {
- expect(findIsNewBadge().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
deleted file mode 100644
index 9d3535291eb..00000000000
--- a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import { mount } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
-import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue';
-import { getStoreConfig } from '~/reports/accessibility_report/store';
-import { mockReport } from './mock_data';
-
-Vue.use(Vuex);
-
-describe('Grouped accessibility reports app', () => {
- let wrapper;
- let mockStore;
-
- const mountComponent = () => {
- wrapper = mount(GroupedAccessibilityReportsApp, {
- store: mockStore,
- propsData: {
- endpoint: 'endpoint.json',
- },
- });
- };
-
- const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
-
- beforeEach(() => {
- mockStore = new Vuex.Store({
- ...getStoreConfig(),
- actions: { fetchReport: () => {}, setEndpoint: () => {} },
- });
-
- mountComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('while loading', () => {
- beforeEach(() => {
- mockStore.state.isLoading = true;
- mountComponent();
- });
-
- it('renders loading state', () => {
- expect(findHeader().text()).toEqual('Accessibility scanning results are being parsed');
- });
- });
-
- describe('with error', () => {
- beforeEach(() => {
- mockStore.state.isLoading = false;
- mockStore.state.hasError = true;
- mountComponent();
- });
-
- it('renders error state', () => {
- expect(findHeader().text()).toEqual('Accessibility scanning failed loading results');
- });
- });
-
- describe('with a report', () => {
- describe('with no issues', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 0,
- },
- };
- });
-
- it('renders no issues header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected no issues for the source branch only',
- );
- });
- });
-
- describe('with one issue', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 1,
- },
- };
- });
-
- it('renders one issue header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected 1 issue for the source branch only',
- );
- });
- });
-
- describe('with multiple issues', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 2,
- },
- };
- });
-
- it('renders multiple issues header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected 2 issues for the source branch only',
- );
- });
- });
-
- describe('with issues to show', () => {
- beforeEach(() => {
- mockStore.state.report = mockReport;
- });
-
- it('renders custom accessibility issue body', () => {
- const issueBody = wrapper.findComponent(AccessibilityIssueBody);
-
- expect(issueBody.props('issue').code).toBe(mockReport.new_errors[0].code);
- expect(issueBody.props('issue').message).toBe(mockReport.new_errors[0].message);
- expect(issueBody.props('isNew')).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/mock_data.js b/spec/frontend/reports/accessibility_report/mock_data.js
deleted file mode 100644
index 9dace1e7c54..00000000000
--- a/spec/frontend/reports/accessibility_report/mock_data.js
+++ /dev/null
@@ -1,53 +0,0 @@
-export const mockReport = {
- status: 'failed',
- summary: {
- total: 2,
- resolved: 0,
- errored: 2,
- },
- new_errors: [
- {
- code: 'WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail',
- type: 'error',
- typeCode: 1,
- message:
- 'This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.84:1. Recommendation: change text colour to #767676.',
- context: '<a href="/stages-devops-lifecycle/" class="main-nav-link">Product</a>',
- selector: '#main-nav > div:nth-child(2) > ul > li:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- new_notes: [],
- new_warnings: [],
- resolved_errors: [
- {
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- type: 'error',
- typeCode: 1,
- message:
- 'Anchor element found with a valid href attribute, but no link content has been supplied.',
- context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>',
- selector: '#main-nav > div:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- resolved_notes: [],
- resolved_warnings: [],
- existing_errors: [
- {
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- type: 'error',
- typeCode: 1,
- message:
- 'Anchor element found with a valid href attribute, but no link content has been supplied.',
- context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>',
- selector: '#main-nav > div:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- existing_notes: [],
- existing_warnings: [],
-};
diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js
deleted file mode 100644
index bab6c4905a7..00000000000
--- a/spec/frontend/reports/accessibility_report/store/actions_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import createStore from '~/reports/accessibility_report/store';
-import * as actions from '~/reports/accessibility_report/store/actions';
-import * as types from '~/reports/accessibility_report/store/mutation_types';
-import { mockReport } from '../mock_data';
-
-describe('Accessibility Reports actions', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('setEndpoints', () => {
- it('should commit SET_ENDPOINTS mutation', () => {
- const endpoint = 'endpoint.json';
-
- return testAction(
- actions.setEndpoint,
- endpoint,
- localState,
- [{ type: types.SET_ENDPOINT, payload: endpoint }],
- [],
- );
- });
- });
-
- describe('fetchReport', () => {
- let mock;
-
- beforeEach(() => {
- localState.endpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- actions.stopPolling();
- actions.clearEtagPoll();
- });
-
- describe('success', () => {
- it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', () => {
- const data = { report: { summary: {} } };
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, data);
-
- return testAction(
- actions.fetchReport,
- null,
- localState,
- [{ type: types.REQUEST_REPORT }],
- [
- {
- payload: { status: 200, data },
- type: 'receiveReportSuccess',
- },
- ],
- );
- });
- });
-
- describe('error', () => {
- it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', () => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
-
- return testAction(
- actions.fetchReport,
- null,
- localState,
- [{ type: types.REQUEST_REPORT }],
- [{ type: 'receiveReportError' }],
- );
- });
- });
- });
-
- describe('receiveReportSuccess', () => {
- it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', () => {
- return testAction(
- actions.receiveReportSuccess,
- { status: 200, data: mockReport },
- localState,
- [{ type: types.RECEIVE_REPORT_SUCCESS, payload: mockReport }],
- [{ type: 'stopPolling' }],
- );
- });
-
- it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', () => {
- return testAction(
- actions.receiveReportSuccess,
- { status: 204, data: mockReport },
- localState,
- [],
- [],
- );
- });
- });
-
- describe('receiveReportError', () => {
- it('should commit RECEIVE_REPORT_ERROR mutation', () => {
- return testAction(
- actions.receiveReportError,
- null,
- localState,
- [{ type: types.RECEIVE_REPORT_ERROR }],
- [{ type: 'stopPolling' }],
- );
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/store/getters_spec.js b/spec/frontend/reports/accessibility_report/store/getters_spec.js
deleted file mode 100644
index 96344596003..00000000000
--- a/spec/frontend/reports/accessibility_report/store/getters_spec.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import createStore from '~/reports/accessibility_report/store';
-import * as getters from '~/reports/accessibility_report/store/getters';
-import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '~/reports/constants';
-
-describe('Accessibility reports store getters', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('summaryStatus', () => {
- describe('when summary is loading', () => {
- it('returns loading status', () => {
- localState.isLoading = true;
-
- expect(getters.summaryStatus(localState)).toEqual(LOADING);
- });
- });
-
- describe('when summary has error', () => {
- it('returns error status', () => {
- localState.hasError = true;
-
- expect(getters.summaryStatus(localState)).toEqual(ERROR);
- });
- });
-
- describe('when summary has failed status', () => {
- it('returns loading status', () => {
- localState.status = STATUS_FAILED;
-
- expect(getters.summaryStatus(localState)).toEqual(ERROR);
- });
- });
-
- describe('when summary has successfully loaded', () => {
- it('returns loading status', () => {
- expect(getters.summaryStatus(localState)).toEqual(SUCCESS);
- });
- });
- });
-
- describe('groupedSummaryText', () => {
- describe('when state is loading', () => {
- it('returns the loading summary message', () => {
- localState.isLoading = true;
- const result = 'Accessibility scanning results are being parsed';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when state has error', () => {
- it('returns the error summary message', () => {
- localState.hasError = true;
- const result = 'Accessibility scanning failed loading results';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when state has successfully loaded', () => {
- describe('when report has errors', () => {
- it('returns summary message containing number of errors', () => {
- localState.report = {
- summary: {
- errored: 2,
- },
- };
- const result = 'Accessibility scanning detected 2 issues for the source branch only';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when report has no errors', () => {
- it('returns summary message containing no errors', () => {
- localState.report = {
- summary: {
- errored: 0,
- },
- };
- const result = 'Accessibility scanning detected no issues for the source branch only';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
- });
- });
-
- describe('shouldRenderIssuesList', () => {
- describe('when has issues to render', () => {
- it('returns true', () => {
- localState.report = {
- existing_errors: [{ name: 'Issue' }],
- };
-
- expect(getters.shouldRenderIssuesList(localState)).toEqual(true);
- });
- });
-
- describe('when does not have issues to render', () => {
- it('returns false', () => {
- localState.report = {
- status: 'success',
- summary: { errored: 0 },
- };
-
- expect(getters.shouldRenderIssuesList(localState)).toEqual(false);
- });
- });
- });
-
- describe('unresolvedIssues', () => {
- it('returns the array unresolved errors', () => {
- localState.report = {
- existing_errors: [1],
- };
- const result = [1];
-
- expect(getters.unresolvedIssues(localState)).toEqual(result);
- });
- });
-
- describe('resolvedIssues', () => {
- it('returns array of resolved errors', () => {
- localState.report = {
- resolved_errors: [1],
- };
- const result = [1];
-
- expect(getters.resolvedIssues(localState)).toEqual(result);
- });
- });
-
- describe('newIssues', () => {
- it('returns array of new errors', () => {
- localState.report = {
- new_errors: [1],
- };
- const result = [1];
-
- expect(getters.newIssues(localState)).toEqual(result);
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/store/mutations_spec.js b/spec/frontend/reports/accessibility_report/store/mutations_spec.js
deleted file mode 100644
index b336261d804..00000000000
--- a/spec/frontend/reports/accessibility_report/store/mutations_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import createStore from '~/reports/accessibility_report/store';
-import mutations from '~/reports/accessibility_report/store/mutations';
-
-describe('Accessibility Reports mutations', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('SET_ENDPOINT', () => {
- it('sets endpoint to given value', () => {
- const endpoint = 'endpoint.json';
- mutations.SET_ENDPOINT(localState, endpoint);
-
- expect(localState.endpoint).toEqual(endpoint);
- });
- });
-
- describe('REQUEST_REPORT', () => {
- it('sets isLoading to true', () => {
- mutations.REQUEST_REPORT(localState);
-
- expect(localState.isLoading).toEqual(true);
- });
- });
-
- describe('RECEIVE_REPORT_SUCCESS', () => {
- it('sets isLoading to false', () => {
- mutations.RECEIVE_REPORT_SUCCESS(localState, {});
-
- expect(localState.isLoading).toEqual(false);
- });
-
- it('sets hasError to false', () => {
- mutations.RECEIVE_REPORT_SUCCESS(localState, {});
-
- expect(localState.hasError).toEqual(false);
- });
-
- it('sets report to response report', () => {
- const report = { data: 'testing' };
- mutations.RECEIVE_REPORT_SUCCESS(localState, report);
-
- expect(localState.report).toEqual(report);
- });
- });
-
- describe('RECEIVE_REPORT_ERROR', () => {
- it('sets isLoading to false', () => {
- mutations.RECEIVE_REPORT_ERROR(localState);
-
- expect(localState.isLoading).toEqual(false);
- });
-
- it('sets hasError to true', () => {
- mutations.RECEIVE_REPORT_ERROR(localState);
-
- expect(localState.hasError).toEqual(true);
- });
- });
-});
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index bdfba8d6878..cc35b99a199 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -7,9 +7,13 @@ import ReportSection from '~/reports/components/report_section.vue';
describe('ReportSection component', () => {
let wrapper;
- const findButton = () => wrapper.findComponent(GlButton);
+ const findExpandButton = () => wrapper.findComponent(GlButton);
const findPopover = () => wrapper.findComponent(HelpPopover);
const findReportSection = () => wrapper.find('.js-report-section-container');
+ const expectExpandButtonOpen = () =>
+ expect(findExpandButton().props('icon')).toBe('chevron-lg-up');
+ const expectExpandButtonClosed = () =>
+ expect(findExpandButton().props('icon')).toBe('chevron-lg-down');
const resolvedIssues = [
{
@@ -122,22 +126,22 @@ describe('ReportSection component', () => {
it('toggles issues', async () => {
createComponent({ props: { hasIssues: true } });
- await findButton().trigger('click');
+ await findExpandButton().trigger('click');
expect(findReportSection().isVisible()).toBe(true);
- expect(findButton().text()).toBe('Collapse');
+ expectExpandButtonOpen();
- await findButton().trigger('click');
+ await findExpandButton().trigger('click');
expect(findReportSection().isVisible()).toBe(false);
- expect(findButton().text()).toBe('Expand');
+ expectExpandButtonClosed();
});
it('is always expanded, if always-open is set to true', () => {
createComponent({ props: { hasIssues: true, alwaysOpen: true } });
expect(findReportSection().isVisible()).toBe(true);
- expect(findButton().exists()).toBe(false);
+ expect(findExpandButton().exists()).toBe(false);
});
});
});
@@ -148,7 +152,7 @@ describe('ReportSection component', () => {
expect(wrapper.emitted('toggleEvent')).toBeUndefined();
- findButton().trigger('click');
+ findExpandButton().trigger('click');
expect(wrapper.emitted('toggleEvent')).toEqual([[]]);
});
@@ -158,7 +162,7 @@ describe('ReportSection component', () => {
expect(wrapper.emitted('toggleEvent')).toBeUndefined();
- findButton().trigger('click');
+ findExpandButton().trigger('click');
expect(wrapper.emitted('toggleEvent')).toBeUndefined();
});
@@ -208,7 +212,7 @@ describe('ReportSection component', () => {
});
it('should still render the expand/collapse button', () => {
- expect(findButton().text()).toBe('Expand');
+ expectExpandButtonClosed();
});
});
diff --git a/spec/frontend/repository/commits_service_spec.js b/spec/frontend/repository/commits_service_spec.js
index 697fa7c4fd1..de7c56f239a 100644
--- a/spec/frontend/repository/commits_service_spec.js
+++ b/spec/frontend/repository/commits_service_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { loadCommits, isRequested, resetRequestedCommits } from '~/repository/commits_service';
import httpStatus from '~/lib/utils/http_status';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { I18N_COMMIT_DATA_FETCH_ERROR } from '~/repository/constants';
jest.mock('~/flash');
@@ -65,13 +65,13 @@ describe('commits service', () => {
expect(isRequested(300)).toBe(false);
});
- it('calls `createFlash` when the request fails', async () => {
+ it('calls `createAlert` when the request fails', async () => {
const invalidPath = '/#@ some/path';
const invalidUrl = `${url}${invalidPath}`;
mock.onGet(invalidUrl).replyOnce(httpStatus.INTERNAL_SERVER_ERROR, [], {});
await requestCommits(1, 'my-project', invalidPath);
- expect(createFlash).toHaveBeenCalledWith({ message: I18N_COMMIT_DATA_FETCH_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: I18N_COMMIT_DATA_FETCH_ERROR });
});
});
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 01494cb6a24..6fe60f3c2e6 100644
--- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
+++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
@@ -7,7 +7,7 @@ exports[`Repository last commit component renders commit widget 1`] = `
<user-avatar-link-stub
class="gl-my-2 gl-mr-4"
imgalt=""
- imgcssclasses="gl-mr-0!"
+ imgcssclasses=""
imgsize="32"
imgsrc="https://test.com"
linkhref="/test"
diff --git a/spec/frontend/repository/components/blob_controls_spec.js b/spec/frontend/repository/components/blob_controls_spec.js
index 6da1861ea7c..0d52542397f 100644
--- a/spec/frontend/repository/components/blob_controls_spec.js
+++ b/spec/frontend/repository/components/blob_controls_spec.js
@@ -8,9 +8,13 @@ import blobControlsQuery from '~/repository/queries/blob_controls.query.graphql'
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createRouter from '~/repository/router';
import { updateElementsVisibility } from '~/repository/utils/dom';
+import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';
+import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import { blobControlsDataMock, refMock } from '../mock_data';
jest.mock('~/repository/utils/dom');
+jest.mock('~/behaviors/shortcuts/shortcuts_blob');
+jest.mock('~/blob/blob_line_permalink_updater');
let router;
let wrapper;
@@ -82,4 +86,12 @@ describe('Blob controls component', () => {
expect(updateElementsVisibility).toHaveBeenCalledWith('.tree-controls', true);
},
);
+
+ it('loads the ShortcutsBlob', () => {
+ expect(ShortcutsBlob).toHaveBeenCalled();
+ });
+
+ it('loads the BlobLinePermalinkUpdater', () => {
+ expect(BlobLinePermalinkUpdater).toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js
index bf9528953b6..964b135bee3 100644
--- a/spec/frontend/repository/components/last_commit_spec.js
+++ b/spec/frontend/repository/components/last_commit_spec.js
@@ -185,7 +185,7 @@ describe('Repository last commit component', () => {
it('strips the first newline of the description', () => {
expect(findCommitRowDescription().html()).toBe(
- '<pre class="commit-row-description gl-mb-3">Update ADOPTERS.md</pre>',
+ '<pre class="commit-row-description gl-mb-3 gl-white-space-pre-line">Update ADOPTERS.md</pre>',
);
});
diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js
index aaf751a9a8d..cf0d48280f4 100644
--- a/spec/frontend/repository/components/new_directory_modal_spec.js
+++ b/spec/frontend/repository/components/new_directory_modal_spec.js
@@ -4,7 +4,7 @@ import { nextTick } from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
import NewDirectoryModal from '~/repository/components/new_directory_modal.vue';
@@ -194,7 +194,7 @@ describe('NewDirectoryModal', () => {
await fillForm({ dirName: 'foo', branchName: 'master', commitMessage: 'foo' });
await submitForm();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: NewDirectoryModal.i18n.ERROR_MESSAGE,
});
});
diff --git a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
index 26064e9b248..b99d741e984 100644
--- a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
+++ b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
@@ -40,10 +40,10 @@ exports[`Repository table row component renders a symlink table row 1`] = `
</td>
<td
- class="d-none d-sm-table-cell tree-commit cursor-default"
+ class="d-none d-sm-table-cell tree-commit cursor-default gl-text-secondary"
>
<gl-link-stub
- class="str-truncated-100 tree-commit-link"
+ class="str-truncated-100 tree-commit-link gl-text-secondary"
/>
<gl-intersection-observer-stub>
@@ -52,7 +52,7 @@ exports[`Repository table row component renders a symlink table row 1`] = `
</td>
<td
- class="tree-time-ago text-right cursor-default"
+ class="tree-time-ago text-right cursor-default gl-text-secondary"
>
<timeago-tooltip-stub
cssclass=""
@@ -105,10 +105,10 @@ exports[`Repository table row component renders table row 1`] = `
</td>
<td
- class="d-none d-sm-table-cell tree-commit cursor-default"
+ class="d-none d-sm-table-cell tree-commit cursor-default gl-text-secondary"
>
<gl-link-stub
- class="str-truncated-100 tree-commit-link"
+ class="str-truncated-100 tree-commit-link gl-text-secondary"
/>
<gl-intersection-observer-stub>
@@ -117,7 +117,7 @@ exports[`Repository table row component renders table row 1`] = `
</td>
<td
- class="tree-time-ago text-right cursor-default"
+ class="tree-time-ago text-right cursor-default gl-text-secondary"
>
<timeago-tooltip-stub
cssclass=""
@@ -170,10 +170,10 @@ exports[`Repository table row component renders table row for path with special
</td>
<td
- class="d-none d-sm-table-cell tree-commit cursor-default"
+ class="d-none d-sm-table-cell tree-commit cursor-default gl-text-secondary"
>
<gl-link-stub
- class="str-truncated-100 tree-commit-link"
+ class="str-truncated-100 tree-commit-link gl-text-secondary"
/>
<gl-intersection-observer-stub>
@@ -182,7 +182,7 @@ exports[`Repository table row component renders table row for path with special
</td>
<td
- class="tree-time-ago text-right cursor-default"
+ class="tree-time-ago text-right cursor-default gl-text-secondary"
>
<timeago-tooltip-stub
cssclass=""
diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js
index 697d2dcc7f5..2180f78a8df 100644
--- a/spec/frontend/repository/components/table/index_spec.js
+++ b/spec/frontend/repository/components/table/index_spec.js
@@ -159,7 +159,7 @@ describe('Repository table component', () => {
});
describe('Show more button', () => {
- const showMoreButton = () => vm.find(GlButton);
+ const showMoreButton = () => vm.findComponent(GlButton);
it.each`
hasMore | expectButtonToExist
diff --git a/spec/frontend/repository/components/table/parent_row_spec.js b/spec/frontend/repository/components/table/parent_row_spec.js
index 9daae8c36ef..03fb4242e40 100644
--- a/spec/frontend/repository/components/table/parent_row_spec.js
+++ b/spec/frontend/repository/components/table/parent_row_spec.js
@@ -39,7 +39,7 @@ describe('Repository parent row component', () => {
`('renders link in $path to $to', ({ path, to }) => {
factory(path);
- expect(vm.find(RouterLinkStub).props().to).toEqual({
+ expect(vm.findComponent(RouterLinkStub).props().to).toEqual({
path: to,
});
});
@@ -69,6 +69,6 @@ describe('Repository parent row component', () => {
it('renders loading icon when loading parent', () => {
factory('app/assets', 'app');
- expect(vm.find(GlLoadingIcon).exists()).toBe(true);
+ expect(vm.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 13b09e57473..64aa6d179a8 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -47,7 +47,7 @@ function factory(propsData = {}) {
}
describe('Repository table row component', () => {
- const findRouterLink = () => vm.find(RouterLinkStub);
+ const findRouterLink = () => vm.findComponent(RouterLinkStub);
const findIntersectionObserver = () => vm.findComponent(GlIntersectionObserver);
afterEach(() => {
@@ -124,7 +124,7 @@ describe('Repository table row component', () => {
});
await nextTick();
- expect(vm.find(component).exists()).toBe(true);
+ expect(vm.findComponent(component).exists()).toBe(true);
});
it.each`
@@ -141,7 +141,7 @@ describe('Repository table row component', () => {
});
await nextTick();
- expect(vm.find({ ref: 'link' }).props('to')).toEqual({
+ expect(vm.findComponent({ ref: 'link' }).props('to')).toEqual({
path: `/-/tree/main/${encodeURIComponent(path)}`,
});
});
@@ -197,7 +197,7 @@ describe('Repository table row component', () => {
});
await nextTick();
- expect(vm.find(GlBadge).exists()).toBe(true);
+ expect(vm.findComponent(GlBadge).exists()).toBe(true);
});
it('renders commit and web links with href for submodule', async () => {
@@ -213,7 +213,7 @@ describe('Repository table row component', () => {
await nextTick();
expect(vm.find('a').attributes('href')).toEqual('https://test.com');
- expect(vm.find(GlLink).attributes('href')).toEqual('https://test.com/commit');
+ expect(vm.findComponent(GlLink).attributes('href')).toEqual('https://test.com/commit');
});
it('renders lock icon', async () => {
@@ -226,8 +226,8 @@ describe('Repository table row component', () => {
});
await nextTick();
- expect(vm.find(GlIcon).exists()).toBe(true);
- expect(vm.find(GlIcon).props('name')).toBe('lock');
+ expect(vm.findComponent(GlIcon).exists()).toBe(true);
+ expect(vm.findComponent(GlIcon).props('name')).toBe('lock');
});
it('renders loading icon when path is loading', () => {
@@ -240,7 +240,7 @@ describe('Repository table row component', () => {
loadingPath: 'test',
});
- expect(vm.find(FileIcon).props('loading')).toBe(true);
+ expect(vm.findComponent(FileIcon).props('loading')).toBe(true);
});
describe('row visibility', () => {
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 9d3a5394df8..352f4314232 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -38,7 +38,7 @@ function factory(path, data = () => ({})) {
}
describe('Repository table component', () => {
- const findFileTable = () => vm.find(FileTable);
+ const findFileTable = () => vm.findComponent(FileTable);
afterEach(() => {
vm.destroy();
@@ -53,7 +53,7 @@ describe('Repository table component', () => {
await nextTick();
- expect(vm.find(FilePreview).exists()).toBe(true);
+ expect(vm.findComponent(FilePreview).exists()).toBe(true);
});
it('trigger fetchFiles and resetRequestedCommits when mounted', async () => {
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 505ff7f3dd6..8db169b02b4 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -4,7 +4,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
@@ -47,12 +47,12 @@ describe('UploadBlobModal', () => {
});
};
- const findModal = () => wrapper.find(GlModal);
- const findAlert = () => wrapper.find(GlAlert);
- const findCommitMessage = () => wrapper.find(GlFormTextarea);
- const findBranchName = () => wrapper.find(GlFormInput);
- const findMrToggle = () => wrapper.find(GlToggle);
- const findUploadDropzone = () => wrapper.find(UploadDropzone);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findCommitMessage = () => wrapper.findComponent(GlFormTextarea);
+ const findBranchName = () => wrapper.findComponent(GlFormInput);
+ const findMrToggle = () => wrapper.findComponent(GlToggle);
+ const findUploadDropzone = () => wrapper.findComponent(UploadDropzone);
const actionButtonDisabledState = () => findModal().props('actionPrimary').attributes[0].disabled;
const cancelButtonDisabledState = () => findModal().props('actionCancel').attributes[0].disabled;
const actionButtonLoadingState = () => findModal().props('actionPrimary').attributes[0].loading;
@@ -185,7 +185,7 @@ describe('UploadBlobModal', () => {
});
it('creates a flash error', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Error uploading file. Please try again.',
});
});
diff --git a/spec/frontend/repository/pages/blob_spec.js b/spec/frontend/repository/pages/blob_spec.js
index 41ab4d616b8..4fe6188370e 100644
--- a/spec/frontend/repository/pages/blob_spec.js
+++ b/spec/frontend/repository/pages/blob_spec.js
@@ -7,7 +7,7 @@ jest.mock('~/repository/utils/dom');
describe('Repository blob page component', () => {
let wrapper;
- const findBlobContentViewer = () => wrapper.find(BlobContentViewer);
+ const findBlobContentViewer = () => wrapper.findComponent(BlobContentViewer);
const path = 'file.js';
beforeEach(() => {
diff --git a/spec/frontend/repository/pages/index_spec.js b/spec/frontend/repository/pages/index_spec.js
index c0afb7931b1..559257d414c 100644
--- a/spec/frontend/repository/pages/index_spec.js
+++ b/spec/frontend/repository/pages/index_spec.js
@@ -34,7 +34,7 @@ describe('Repository index page component', () => {
it('renders TreePage', () => {
factory();
- const child = wrapper.find(TreePage);
+ const child = wrapper.findComponent(TreePage);
expect(child.exists()).toBe(true);
expect(child.props()).toEqual({ path: '/' });
diff --git a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
index 7ab4aeee9bc..64f66d8f3ba 100644
--- a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
+++ b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
@@ -104,6 +104,10 @@ describe('AdminRunnerShowApp', () => {
Platform darwin
Configuration Runs untagged jobs
Maximum job timeout None
+ Token expiry
+ Runner authentication token expiration
+ Runner authentication tokens will expire based on a set interval.
+ They will automatically rotate once expired. Learn more Never expires
Tags None`.replace(/\s+/g, ' ');
expect(wrapper.text().replace(/\s+/g, ' ')).toContain(expected);
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 55a298e1695..7afde3bdc96 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -20,8 +20,6 @@ import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue';
import RunnerStackedLayoutBanner from '~/runner/components/runner_stacked_layout_banner.vue';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
-import RunnerBulkDelete from '~/runner/components/runner_bulk_delete.vue';
-import RunnerBulkDeleteCheckbox from '~/runner/components/runner_bulk_delete_checkbox.vue';
import RunnerList from '~/runner/components/runner_list.vue';
import RunnerListEmptyState from '~/runner/components/runner_list_empty_state.vue';
import RunnerStats from '~/runner/components/stat/runner_stats.vue';
@@ -45,6 +43,7 @@ import {
PARAM_KEY_STATUS,
PARAM_KEY_TAG,
STATUS_ONLINE,
+ DEFAULT_MEMBERSHIP,
RUNNER_PAGE_SIZE,
} from '~/runner/constants';
import allRunnersQuery from 'ee_else_ce/runner/graphql/list/all_runners.query.graphql';
@@ -83,8 +82,6 @@ const COUNT_QUERIES = 7; // 4 tabs + 3 status queries
describe('AdminRunnersApp', () => {
let wrapper;
- let cacheConfig;
- let localMutations;
let showToast;
const findRunnerStackedLayoutBanner = () => wrapper.findComponent(RunnerStackedLayoutBanner);
@@ -92,8 +89,6 @@ describe('AdminRunnersApp', () => {
const findRunnerActionsCell = () => wrapper.findComponent(RunnerActionsCell);
const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
const findRunnerTypeTabs = () => wrapper.findComponent(RunnerTypeTabs);
- const findRunnerBulkDelete = () => wrapper.findComponent(RunnerBulkDelete);
- const findRunnerBulkDeleteCheckbox = () => wrapper.findComponent(RunnerBulkDeleteCheckbox);
const findRunnerList = () => wrapper.findComponent(RunnerList);
const findRunnerListEmptyState = () => wrapper.findComponent(RunnerListEmptyState);
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
@@ -106,7 +101,7 @@ describe('AdminRunnersApp', () => {
provide,
...options
} = {}) => {
- ({ cacheConfig, localMutations } = createLocalState());
+ const { cacheConfig, localMutations } = createLocalState();
const handlers = [
[allRunnersQuery, mockRunnersHandler],
@@ -195,7 +190,7 @@ describe('AdminRunnersApp', () => {
const { id, shortSha } = mockRunners[0];
const numericId = getIdFromGraphQLId(id);
- const runnerLink = wrapper.find('tr [data-testid="td-summary"]').find(GlLink);
+ const runnerLink = wrapper.find('tr [data-testid="td-summary"]').findComponent(GlLink);
expect(runnerLink.text()).toBe(`#${numericId} (${shortSha})`);
expect(runnerLink.attributes('href')).toBe(`http://localhost/admin/runners/${numericId}`);
@@ -204,7 +199,9 @@ describe('AdminRunnersApp', () => {
it('renders runner actions for each runner', async () => {
await createComponent({ mountFn: mountExtended });
- const runnerActions = wrapper.find('tr [data-testid="td-actions"]').find(RunnerActionsCell);
+ const runnerActions = wrapper
+ .find('tr [data-testid="td-actions"]')
+ .findComponent(RunnerActionsCell);
const runner = mockRunners[0];
expect(runnerActions.props()).toEqual({
@@ -219,6 +216,7 @@ describe('AdminRunnersApp', () => {
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
status: undefined,
type: undefined,
+ membership: DEFAULT_MEMBERSHIP,
sort: DEFAULT_SORT,
first: RUNNER_PAGE_SIZE,
});
@@ -255,7 +253,7 @@ describe('AdminRunnersApp', () => {
});
it('Links to the runner page', async () => {
- const runnerLink = wrapper.find('tr [data-testid="td-summary"]').find(GlLink);
+ const runnerLink = wrapper.find('tr [data-testid="td-summary"]').findComponent(GlLink);
expect(runnerLink.text()).toBe(`#${id} (${shortSha})`);
expect(runnerLink.attributes('href')).toBe(`http://localhost/admin/runners/${id}`);
@@ -288,6 +286,7 @@ describe('AdminRunnersApp', () => {
it('sets the filters in the search bar', () => {
expect(findRunnerFilteredSearchBar().props('value')).toEqual({
runnerType: INSTANCE_TYPE,
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } },
{ type: PARAM_KEY_PAUSED, value: { data: 'true', operator: '=' } },
@@ -301,6 +300,7 @@ describe('AdminRunnersApp', () => {
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
status: STATUS_ONLINE,
type: INSTANCE_TYPE,
+ membership: DEFAULT_MEMBERSHIP,
paused: true,
sort: DEFAULT_SORT,
first: RUNNER_PAGE_SIZE,
@@ -310,6 +310,7 @@ describe('AdminRunnersApp', () => {
it('fetches count results for requested status', () => {
expect(mockRunnersCountHandler).toHaveBeenCalledWith({
type: INSTANCE_TYPE,
+ membership: DEFAULT_MEMBERSHIP,
status: STATUS_ONLINE,
paused: true,
});
@@ -322,6 +323,7 @@ describe('AdminRunnersApp', () => {
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } }],
sort: CREATED_ASC,
});
@@ -339,6 +341,7 @@ describe('AdminRunnersApp', () => {
it('requests the runners with filters', () => {
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
status: STATUS_ONLINE,
+ membership: DEFAULT_MEMBERSHIP,
sort: CREATED_ASC,
first: RUNNER_PAGE_SIZE,
});
@@ -347,6 +350,7 @@ describe('AdminRunnersApp', () => {
it('fetches count results for requested status', () => {
expect(mockRunnersCountHandler).toHaveBeenCalledWith({
status: STATUS_ONLINE,
+ membership: DEFAULT_MEMBERSHIP,
});
});
});
@@ -357,65 +361,26 @@ describe('AdminRunnersApp', () => {
expect(findRunnerPagination().attributes('disabled')).toBe('true');
});
- describe('when bulk delete is enabled', () => {
+ describe('Bulk delete', () => {
describe('Before runners are deleted', () => {
beforeEach(async () => {
- await createComponent({
- mountFn: mountExtended,
- provide: {
- glFeatures: { adminRunnersBulkDelete: true },
- },
- });
- });
-
- it('runner bulk delete is available', () => {
- expect(findRunnerBulkDelete().props('runners')).toEqual(mockRunners);
- });
-
- it('runner bulk delete checkbox is available', () => {
- expect(findRunnerBulkDeleteCheckbox().props('runners')).toEqual(mockRunners);
+ await createComponent({ mountFn: mountExtended });
});
it('runner list is checkable', () => {
expect(findRunnerList().props('checkable')).toBe(true);
});
-
- it('responds to checked items by updating the local cache', () => {
- const setRunnerCheckedMock = jest
- .spyOn(localMutations, 'setRunnerChecked')
- .mockImplementation(() => {});
-
- const runner = mockRunners[0];
-
- expect(setRunnerCheckedMock).toHaveBeenCalledTimes(0);
-
- findRunnerList().vm.$emit('checked', {
- runner,
- isChecked: true,
- });
-
- expect(setRunnerCheckedMock).toHaveBeenCalledTimes(1);
- expect(setRunnerCheckedMock).toHaveBeenCalledWith({
- runner,
- isChecked: true,
- });
- });
});
describe('When runners are deleted', () => {
beforeEach(async () => {
- await createComponent({
- mountFn: mountExtended,
- provide: {
- glFeatures: { adminRunnersBulkDelete: true },
- },
- });
+ await createComponent({ mountFn: mountExtended });
});
it('count data is refetched', async () => {
expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES);
- findRunnerBulkDelete().vm.$emit('deleted', { message: 'Runners deleted' });
+ findRunnerList().vm.$emit('deleted', { message: 'Runners deleted' });
expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES * 2);
});
@@ -423,7 +388,7 @@ describe('AdminRunnersApp', () => {
it('toast is shown', async () => {
expect(showToast).toHaveBeenCalledTimes(0);
- findRunnerBulkDelete().vm.$emit('deleted', { message: 'Runners deleted' });
+ findRunnerList().vm.$emit('deleted', { message: 'Runners deleted' });
expect(showToast).toHaveBeenCalledTimes(1);
expect(showToast).toHaveBeenCalledWith('Runners deleted');
@@ -457,6 +422,7 @@ describe('AdminRunnersApp', () => {
beforeEach(async () => {
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } }],
sort: CREATED_ASC,
});
@@ -504,6 +470,7 @@ describe('AdminRunnersApp', () => {
await findRunnerPaginationNext().trigger('click');
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
+ membership: DEFAULT_MEMBERSHIP,
sort: CREATED_DESC,
first: RUNNER_PAGE_SIZE,
after: pageInfo.endCursor,
diff --git a/spec/frontend/runner/components/cells/link_cell_spec.js b/spec/frontend/runner/components/cells/link_cell_spec.js
index a59a0eaa5d8..46ab1adb6b6 100644
--- a/spec/frontend/runner/components/cells/link_cell_spec.js
+++ b/spec/frontend/runner/components/cells/link_cell_spec.js
@@ -5,7 +5,7 @@ import LinkCell from '~/runner/components/cells/link_cell.vue';
describe('LinkCell', () => {
let wrapper;
- const findGlLink = () => wrapper.find(GlLink);
+ const findGlLink = () => wrapper.findComponent(GlLink);
const findSpan = () => wrapper.find('span');
const createComponent = ({ props = {}, ...options } = {}) => {
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 ffd6f126627..58974d4f85f 100644
--- a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -122,7 +122,7 @@ describe('RunnerActionsCell', () => {
expect(wrapper.emitted('deleted')).toEqual([[value]]);
});
- it('Renders the runner delete disabled button when user cannot delete', () => {
+ it('Does not render the runner delete button when user cannot delete', () => {
createComponent({
runner: {
userPermissions: {
@@ -132,7 +132,7 @@ describe('RunnerActionsCell', () => {
},
});
- expect(findDeleteBtn().props('disabled')).toBe(true);
+ expect(findDeleteBtn().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/runner/components/cells/runner_owner_cell_spec.js b/spec/frontend/runner/components/cells/runner_owner_cell_spec.js
new file mode 100644
index 00000000000..e9965d8855d
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_owner_cell_spec.js
@@ -0,0 +1,111 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+import RunnerOwnerCell from '~/runner/components/cells/runner_owner_cell.vue';
+
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
+
+describe('RunnerOwnerCell', () => {
+ let wrapper;
+
+ const findLink = () => wrapper.findComponent(GlLink);
+ const getLinkTooltip = () => getBinding(findLink().element, 'gl-tooltip').value;
+
+ const createComponent = ({ runner } = {}) => {
+ wrapper = shallowMount(RunnerOwnerCell, {
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ propsData: {
+ runner,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('When its an instance runner', () => {
+ beforeEach(() => {
+ createComponent({
+ runner: {
+ runnerType: INSTANCE_TYPE,
+ },
+ });
+ });
+
+ it('shows an administrator label', () => {
+ expect(findLink().exists()).toBe(false);
+ expect(wrapper.text()).toBe(s__('Runners|Administrator'));
+ });
+ });
+
+ describe('When its a group runner', () => {
+ const mockName = 'Group 2';
+ const mockFullName = 'Group 1 / Group 2';
+ const mockWebUrl = '/group-1/group-2';
+
+ beforeEach(() => {
+ createComponent({
+ runner: {
+ runnerType: GROUP_TYPE,
+ groups: {
+ nodes: [
+ {
+ name: mockName,
+ fullName: mockFullName,
+ webUrl: mockWebUrl,
+ },
+ ],
+ },
+ },
+ });
+ });
+
+ it('Displays a group link', () => {
+ expect(findLink().attributes('href')).toBe(mockWebUrl);
+ expect(wrapper.text()).toBe(mockName);
+ expect(getLinkTooltip()).toBe(mockFullName);
+ });
+ });
+
+ describe('When its a project runner', () => {
+ const mockName = 'Project 1';
+ const mockNameWithNamespace = 'Group 1 / Project 1';
+ const mockWebUrl = '/group-1/project-1';
+
+ beforeEach(() => {
+ createComponent({
+ runner: {
+ runnerType: PROJECT_TYPE,
+ ownerProject: {
+ name: mockName,
+ nameWithNamespace: mockNameWithNamespace,
+ webUrl: mockWebUrl,
+ },
+ },
+ });
+ });
+
+ it('Displays a project link', () => {
+ expect(findLink().attributes('href')).toBe(mockWebUrl);
+ expect(wrapper.text()).toBe(mockName);
+ expect(getLinkTooltip()).toBe(mockNameWithNamespace);
+ });
+ });
+
+ describe('When its an empty runner', () => {
+ beforeEach(() => {
+ createComponent({
+ runner: {},
+ });
+ });
+
+ it('shows no label', () => {
+ expect(wrapper.text()).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_stacked_summary_cell_spec.js b/spec/frontend/runner/components/cells/runner_stacked_summary_cell_spec.js
index 21ec9f61f37..e7cadefc140 100644
--- a/spec/frontend/runner/components/cells/runner_stacked_summary_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_stacked_summary_cell_spec.js
@@ -85,7 +85,7 @@ describe('RunnerTypeCell', () => {
contactedAt: '2022-01-02',
});
- expect(findRunnerSummaryField('clock').find(TimeAgo).props('time')).toBe('2022-01-02');
+ expect(findRunnerSummaryField('clock').findComponent(TimeAgo).props('time')).toBe('2022-01-02');
});
it('Displays empty last contact', () => {
@@ -93,7 +93,7 @@ describe('RunnerTypeCell', () => {
contactedAt: null,
});
- expect(findRunnerSummaryField('clock').find(TimeAgo).exists()).toBe(false);
+ expect(findRunnerSummaryField('clock').findComponent(TimeAgo).exists()).toBe(false);
expect(findRunnerSummaryField('clock').text()).toContain(__('Never'));
});
@@ -134,7 +134,7 @@ describe('RunnerTypeCell', () => {
});
it('Displays created at', () => {
- expect(findRunnerSummaryField('calendar').find(TimeAgo).props('time')).toBe(
+ expect(findRunnerSummaryField('calendar').findComponent(TimeAgo).props('time')).toBe(
mockRunner.createdAt,
);
});
diff --git a/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js b/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js
index 0ac89e82314..424a4e61ccd 100644
--- a/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js
+++ b/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js
@@ -5,11 +5,21 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RunnerBulkDeleteCheckbox from '~/runner/components/runner_bulk_delete_checkbox.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createLocalState } from '~/runner/graphql/list/local_state';
-import { allRunnersData } from '../mock_data';
Vue.use(VueApollo);
-jest.mock('~/flash');
+const makeRunner = (id, deleteRunner = true) => ({
+ id,
+ userPermissions: { deleteRunner },
+});
+
+// Multi-select checkbox possible states:
+const stateToAttrs = {
+ unchecked: { disabled: undefined, checked: undefined, indeterminate: undefined },
+ checked: { disabled: undefined, checked: 'true', indeterminate: undefined },
+ indeterminate: { disabled: undefined, checked: undefined, indeterminate: 'true' },
+ disabled: { disabled: 'true', checked: undefined, indeterminate: undefined },
+};
describe('RunnerBulkDeleteCheckbox', () => {
let wrapper;
@@ -18,12 +28,14 @@ describe('RunnerBulkDeleteCheckbox', () => {
const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
- const mockRunners = allRunnersData.data.runners.nodes;
- const mockIds = allRunnersData.data.runners.nodes.map(({ id }) => id);
- const mockId = mockIds[0];
- const mockIdAnotherPage = 'RUNNER_IN_ANOTHER_PAGE_ID';
+ const expectCheckboxToBe = (state) => {
+ const expected = stateToAttrs[state];
+ expect(findCheckbox().attributes('disabled')).toBe(expected.disabled);
+ expect(findCheckbox().attributes('checked')).toBe(expected.checked);
+ expect(findCheckbox().attributes('indeterminate')).toBe(expected.indeterminate);
+ };
- const createComponent = ({ props = {} } = {}) => {
+ const createComponent = ({ runners = [] } = {}) => {
const { cacheConfig, localMutations } = mockState;
const apolloProvider = createMockApollo(undefined, undefined, cacheConfig);
@@ -33,8 +45,7 @@ describe('RunnerBulkDeleteCheckbox', () => {
localMutations,
},
propsData: {
- runners: mockRunners,
- ...props,
+ runners,
},
});
};
@@ -49,31 +60,61 @@ describe('RunnerBulkDeleteCheckbox', () => {
jest.spyOn(mockState.localMutations, 'setRunnersChecked');
});
- describe.each`
- case | is | checkedRunnerIds | disabled | checked | indeterminate
- ${'no runners'} | ${'unchecked'} | ${[]} | ${undefined} | ${undefined} | ${undefined}
- ${'no runners in this page'} | ${'unchecked'} | ${[mockIdAnotherPage]} | ${undefined} | ${undefined} | ${undefined}
- ${'all runners'} | ${'checked'} | ${mockIds} | ${undefined} | ${'true'} | ${undefined}
- ${'some runners'} | ${'indeterminate'} | ${[mockId]} | ${undefined} | ${undefined} | ${'true'}
- ${'all plus other runners'} | ${'checked'} | ${[...mockIds, mockIdAnotherPage]} | ${undefined} | ${'true'} | ${undefined}
- `('When $case are checked', ({ is, checkedRunnerIds, disabled, checked, indeterminate }) => {
- beforeEach(async () => {
+ describe('when all runners can be deleted', () => {
+ const mockIds = ['1', '2', '3'];
+ const mockIdAnotherPage = '4';
+ const mockRunners = mockIds.map((id) => makeRunner(id));
+
+ it.each`
+ case | checkedRunnerIds | state
+ ${'no runners'} | ${[]} | ${'unchecked'}
+ ${'no runners in this page'} | ${[mockIdAnotherPage]} | ${'unchecked'}
+ ${'all runners'} | ${mockIds} | ${'checked'}
+ ${'some runners'} | ${[mockIds[0]]} | ${'indeterminate'}
+ ${'all plus other runners'} | ${[...mockIds, mockIdAnotherPage]} | ${'checked'}
+ `('if $case are checked, checkbox is $state', ({ checkedRunnerIds, state }) => {
mockCheckedRunnerIds = checkedRunnerIds;
- createComponent();
+ createComponent({ runners: mockRunners });
+ expectCheckboxToBe(state);
});
+ });
+
+ describe('when some runners cannot be deleted', () => {
+ it('all allowed runners are selected, checkbox is checked', () => {
+ mockCheckedRunnerIds = ['a', 'b', 'c'];
+ createComponent({
+ runners: [makeRunner('a'), makeRunner('b'), makeRunner('c', false)],
+ });
- it(`is ${is}`, () => {
- expect(findCheckbox().attributes('disabled')).toBe(disabled);
- expect(findCheckbox().attributes('checked')).toBe(checked);
- expect(findCheckbox().attributes('indeterminate')).toBe(indeterminate);
+ expectCheckboxToBe('checked');
+ });
+
+ it('some allowed runners are selected, checkbox is indeterminate', () => {
+ mockCheckedRunnerIds = ['a', 'b'];
+ createComponent({
+ runners: [makeRunner('a'), makeRunner('b'), makeRunner('c')],
+ });
+
+ expectCheckboxToBe('indeterminate');
+ });
+
+ it('no allowed runners are selected, checkbox is disabled', () => {
+ mockCheckedRunnerIds = ['a', 'b'];
+ createComponent({
+ runners: [makeRunner('a', false), makeRunner('b', false)],
+ });
+
+ expectCheckboxToBe('disabled');
});
});
describe('When user selects', () => {
+ const mockRunners = [makeRunner('1'), makeRunner('2')];
+
beforeEach(() => {
- mockCheckedRunnerIds = mockIds;
- createComponent();
+ mockCheckedRunnerIds = ['1', '2'];
+ createComponent({ runners: mockRunners });
});
it.each([[true], [false]])('sets checked to %s', (checked) => {
@@ -89,13 +130,11 @@ describe('RunnerBulkDeleteCheckbox', () => {
describe('When runners are loading', () => {
beforeEach(() => {
- createComponent({ props: { runners: [] } });
+ createComponent();
});
- it(`is disabled`, () => {
- expect(findCheckbox().attributes('disabled')).toBe('true');
- expect(findCheckbox().attributes('checked')).toBe(undefined);
- expect(findCheckbox().attributes('indeterminate')).toBe(undefined);
+ it('is disabled', () => {
+ expectCheckboxToBe('disabled');
});
});
});
diff --git a/spec/frontend/runner/components/runner_delete_button_spec.js b/spec/frontend/runner/components/runner_delete_button_spec.js
index 52fe803c536..c8fb7a69379 100644
--- a/spec/frontend/runner/components/runner_delete_button_spec.js
+++ b/spec/frontend/runner/components/runner_delete_button_spec.js
@@ -9,11 +9,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { captureException } from '~/runner/sentry_utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { createAlert } from '~/flash';
-import {
- I18N_DELETE_RUNNER,
- I18N_DELETE_DISABLED_MANY_PROJECTS,
- I18N_DELETE_DISABLED_UNKNOWN_REASON,
-} from '~/runner/constants';
+import { I18N_DELETE_RUNNER } from '~/runner/constants';
import RunnerDeleteButton from '~/runner/components/runner_delete_button.vue';
import RunnerDeleteModal from '~/runner/components/runner_delete_modal.vue';
@@ -267,29 +263,4 @@ describe('RunnerDeleteButton', () => {
});
});
});
-
- describe.each`
- reason | runner | tooltip
- ${'runner belongs to more than 1 project'} | ${{ projectCount: 2 }} | ${I18N_DELETE_DISABLED_MANY_PROJECTS}
- ${'unknown reason'} | ${{}} | ${I18N_DELETE_DISABLED_UNKNOWN_REASON}
- `('When button is disabled because $reason', ({ runner, tooltip }) => {
- beforeEach(() => {
- createComponent({
- props: {
- disabled: true,
- runner,
- },
- });
- });
-
- it('Displays a disabled delete button', () => {
- expect(findBtn().props('disabled')).toBe(true);
- });
-
- it(`Tooltip "${tooltip}" is shown`, () => {
- // tabindex is required for a11y
- expect(wrapper.attributes('tabindex')).toBe('0');
- expect(getTooltip()).toBe(tooltip);
- });
- });
});
diff --git a/spec/frontend/runner/components/runner_details_spec.js b/spec/frontend/runner/components/runner_details_spec.js
index f2281223a25..e6cc936e260 100644
--- a/spec/frontend/runner/components/runner_details_spec.js
+++ b/spec/frontend/runner/components/runner_details_spec.js
@@ -25,12 +25,7 @@ describe('RunnerDetails', () => {
const findDetailGroups = () => wrapper.findComponent(RunnerGroups);
- const createComponent = ({
- props = {},
- stubs,
- mountFn = shallowMountExtended,
- enforceRunnerTokenExpiresAt = false,
- } = {}) => {
+ const createComponent = ({ props = {}, stubs, mountFn = shallowMountExtended } = {}) => {
wrapper = mountFn(RunnerDetails, {
propsData: {
...props,
@@ -39,9 +34,6 @@ describe('RunnerDetails', () => {
RunnerDetail,
...stubs,
},
- provide: {
- glFeatures: { enforceRunnerTokenExpiresAt },
- },
});
};
@@ -82,7 +74,6 @@ describe('RunnerDetails', () => {
...runner,
},
},
- enforceRunnerTokenExpiresAt: true,
stubs: {
GlIntersperse,
GlSprintf,
@@ -135,22 +126,5 @@ describe('RunnerDetails', () => {
expect(findDetailGroups().props('runner')).toEqual(mockGroupRunner);
});
});
-
- describe('Token expiration field', () => {
- it.each`
- case | flag | shown
- ${'is shown when feature flag is enabled'} | ${true} | ${true}
- ${'is not shown when feature flag is disabled'} | ${false} | ${false}
- `('$case', ({ flag, shown }) => {
- createComponent({
- props: {
- runner: mockGroupRunner,
- },
- enforceRunnerTokenExpiresAt: flag,
- });
-
- expect(findDd('Token expiry', wrapper).exists()).toBe(shown);
- });
- });
});
});
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 e35bec3aa38..c92e19f9263 100644
--- a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -4,10 +4,26 @@ import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_
import { statusTokenConfig } from '~/runner/components/search_tokens/status_token_config';
import TagToken from '~/runner/components/search_tokens/tag_token.vue';
import { tagTokenConfig } from '~/runner/components/search_tokens/tag_token_config';
-import { PARAM_KEY_STATUS, PARAM_KEY_TAG, STATUS_ONLINE, INSTANCE_TYPE } from '~/runner/constants';
+import {
+ PARAM_KEY_STATUS,
+ PARAM_KEY_TAG,
+ STATUS_ONLINE,
+ INSTANCE_TYPE,
+ DEFAULT_MEMBERSHIP,
+ DEFAULT_SORT,
+ CONTACTED_DESC,
+} from '~/runner/constants';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
+const mockSearch = {
+ runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
+ filters: [],
+ pagination: { page: 1 },
+ sort: DEFAULT_SORT,
+};
+
describe('RunnerList', () => {
let wrapper;
@@ -15,8 +31,7 @@ describe('RunnerList', () => {
const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem);
- const mockDefaultSort = 'CREATED_DESC';
- const mockOtherSort = 'CONTACTED_DESC';
+ const mockOtherSort = CONTACTED_DESC;
const mockFilters = [
{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
@@ -32,11 +47,7 @@ describe('RunnerList', () => {
propsData: {
namespace: 'runners',
tokens: [],
- value: {
- runnerType: null,
- filters: [],
- sort: mockDefaultSort,
- },
+ value: mockSearch,
...props,
},
stubs: {
@@ -115,6 +126,7 @@ describe('RunnerList', () => {
props: {
value: {
runnerType: INSTANCE_TYPE,
+ membership: DEFAULT_MEMBERSHIP,
sort: mockOtherSort,
filters: mockFilters,
},
@@ -141,6 +153,7 @@ describe('RunnerList', () => {
expectToHaveLastEmittedInput({
runnerType: INSTANCE_TYPE,
+ membership: DEFAULT_MEMBERSHIP,
filters: mockFilters,
sort: mockOtherSort,
pagination: {},
@@ -154,8 +167,9 @@ describe('RunnerList', () => {
expectToHaveLastEmittedInput({
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: mockFilters,
- sort: mockDefaultSort,
+ sort: DEFAULT_SORT,
pagination: {},
});
});
@@ -165,6 +179,7 @@ describe('RunnerList', () => {
expectToHaveLastEmittedInput({
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [],
sort: mockOtherSort,
pagination: {},
diff --git a/spec/frontend/runner/components/runner_list_empty_state_spec.js b/spec/frontend/runner/components/runner_list_empty_state_spec.js
index 59cff863106..038162b889e 100644
--- a/spec/frontend/runner/components/runner_list_empty_state_spec.js
+++ b/spec/frontend/runner/components/runner_list_empty_state_spec.js
@@ -8,6 +8,7 @@ import RunnerListEmptyState from '~/runner/components/runner_list_empty_state.vu
const mockSvgPath = 'mock-svg-path.svg';
const mockFilteredSvgPath = 'mock-filtered-svg-path.svg';
+const mockRegistrationToken = 'REGISTRATION_TOKEN';
describe('RunnerListEmptyState', () => {
let wrapper;
@@ -21,6 +22,7 @@ describe('RunnerListEmptyState', () => {
propsData: {
svgPath: mockSvgPath,
filteredSvgPath: mockFilteredSvgPath,
+ registrationToken: mockRegistrationToken,
...props,
},
directives: {
@@ -35,27 +37,52 @@ describe('RunnerListEmptyState', () => {
};
describe('when search is not filtered', () => {
- beforeEach(() => {
- createComponent();
- });
+ const title = s__('Runners|Get started with runners');
- it('renders an illustration', () => {
- expect(findEmptyState().props('svgPath')).toBe(mockSvgPath);
- });
+ describe('when there is a registration token', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders an illustration', () => {
+ expect(findEmptyState().props('svgPath')).toBe(mockSvgPath);
+ });
+
+ it('displays "no results" text with instructions', () => {
+ const desc = s__(
+ 'Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner.',
+ );
- it('displays "no results" text', () => {
- const title = s__('Runners|Get started with runners');
- const desc = s__(
- 'Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner.',
- );
+ expect(findEmptyState().text()).toMatchInterpolatedText(`${title} ${desc}`);
+ });
- expect(findEmptyState().text()).toMatchInterpolatedText(`${title} ${desc}`);
+ it('opens a runner registration instructions modal with a link', () => {
+ const { value } = getBinding(findLink().element, 'gl-modal');
+
+ expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
+ });
});
- it('opens a runner registration instructions modal with a link', () => {
- const { value } = getBinding(findLink().element, 'gl-modal');
+ describe('when there is no registration token', () => {
+ beforeEach(() => {
+ createComponent({ props: { registrationToken: null } });
+ });
+
+ it('renders an illustration', () => {
+ expect(findEmptyState().props('svgPath')).toBe(mockSvgPath);
+ });
+
+ it('displays "no results" text', () => {
+ const desc = s__(
+ 'Runners|Runners are the agents that run your CI/CD jobs. To register new runners, please contact your administrator.',
+ );
+
+ expect(findEmptyState().text()).toMatchInterpolatedText(`${title} ${desc}`);
+ });
- expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
+ it('has no registration instructions link', () => {
+ expect(findLink().exists()).toBe(false);
+ });
});
});
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index 54a9e713721..a31990f8f7e 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -1,12 +1,19 @@
import { GlTableLite, GlSkeletonLoader } from '@gitlab/ui';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
import {
extendedWrapper,
shallowMountExtended,
mountExtended,
} from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { s__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { createLocalState } from '~/runner/graphql/list/local_state';
+
import RunnerList from '~/runner/components/runner_list.vue';
-import RunnerStatusPopover from '~/runner/components/runner_status_popover.vue';
+import RunnerBulkDelete from '~/runner/components/runner_bulk_delete.vue';
+import RunnerBulkDeleteCheckbox from '~/runner/components/runner_bulk_delete_checkbox.vue';
+
import { I18N_PROJECT_TYPE, I18N_STATUS_NEVER_CONTACTED } from '~/runner/constants';
import { allRunnersData, onlineContactTimeoutSecs, staleTimeoutSecs } from '../mock_data';
@@ -15,6 +22,8 @@ const mockActiveRunnersCount = mockRunners.length;
describe('RunnerList', () => {
let wrapper;
+ let cacheConfig;
+ let localMutations;
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findTable = () => wrapper.findComponent(GlTableLite);
@@ -22,18 +31,24 @@ describe('RunnerList', () => {
const findRows = () => wrapper.findAll('[data-testid^="runner-row-"]');
const findCell = ({ row = 0, fieldKey }) =>
extendedWrapper(findRows().at(row).find(`[data-testid="td-${fieldKey}"]`));
+ const findRunnerBulkDelete = () => wrapper.findComponent(RunnerBulkDelete);
+ const findRunnerBulkDeleteCheckbox = () => wrapper.findComponent(RunnerBulkDeleteCheckbox);
const createComponent = (
{ props = {}, provide = {}, ...options } = {},
mountFn = shallowMountExtended,
) => {
+ ({ cacheConfig, localMutations } = createLocalState());
+
wrapper = mountFn(RunnerList, {
+ apolloProvider: createMockApollo([], {}, cacheConfig),
propsData: {
runners: mockRunners,
activeRunnersCount: mockActiveRunnersCount,
...props,
},
provide: {
+ localMutations,
onlineContactTimeoutSecs,
staleTimeoutSecs,
...provide,
@@ -50,7 +65,7 @@ describe('RunnerList', () => {
createComponent(
{
stubs: {
- RunnerStatusPopover: {
+ HelpPopover: {
template: '<div/>',
},
},
@@ -60,11 +75,13 @@ describe('RunnerList', () => {
const headerLabels = findHeaders().wrappers.map((w) => w.text());
- expect(findHeaders().at(0).findComponent(RunnerStatusPopover).exists()).toBe(true);
+ expect(findHeaders().at(0).findComponent(HelpPopover).exists()).toBe(true);
+ expect(findHeaders().at(2).findComponent(HelpPopover).exists()).toBe(true);
expect(headerLabels).toEqual([
- 'Status',
- 'Runner',
+ s__('Runners|Status'),
+ s__('Runners|Runner'),
+ s__('Runners|Owner'),
'', // actions has no label
]);
});
@@ -123,21 +140,40 @@ describe('RunnerList', () => {
);
});
+ it('runner bulk delete is available', () => {
+ expect(findRunnerBulkDelete().props('runners')).toEqual(mockRunners);
+ });
+
+ it('runner bulk delete checkbox is available', () => {
+ expect(findRunnerBulkDeleteCheckbox().props('runners')).toEqual(mockRunners);
+ });
+
it('Displays a checkbox field', () => {
expect(findCell({ fieldKey: 'checkbox' }).find('input').exists()).toBe(true);
});
- it('Emits a checked event', async () => {
- const checkbox = findCell({ fieldKey: 'checkbox' }).find('input');
+ it('Sets a runner as checked', async () => {
+ const runner = mockRunners[0];
+ const setRunnerCheckedMock = jest
+ .spyOn(localMutations, 'setRunnerChecked')
+ .mockImplementation(() => {});
+ const checkbox = findCell({ fieldKey: 'checkbox' }).find('input');
await checkbox.setChecked();
- expect(wrapper.emitted('checked')).toHaveLength(1);
- expect(wrapper.emitted('checked')[0][0]).toEqual({
+ expect(setRunnerCheckedMock).toHaveBeenCalledTimes(1);
+ expect(setRunnerCheckedMock).toHaveBeenCalledWith({
+ runner,
isChecked: true,
- runner: mockRunners[0],
});
});
+
+ it('Emits a deleted event', async () => {
+ const event = { message: 'Deleted!' };
+ findRunnerBulkDelete().vm.$emit('deleted', event);
+
+ expect(wrapper.emitted('deleted')).toEqual([[event]]);
+ });
});
describe('Scoped cell slots', () => {
diff --git a/spec/frontend/runner/components/runner_membership_toggle_spec.js b/spec/frontend/runner/components/runner_membership_toggle_spec.js
new file mode 100644
index 00000000000..1a7ae22618a
--- /dev/null
+++ b/spec/frontend/runner/components/runner_membership_toggle_spec.js
@@ -0,0 +1,57 @@
+import { GlToggle } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+import RunnerMembershipToggle from '~/runner/components/runner_membership_toggle.vue';
+import {
+ I18N_SHOW_ONLY_INHERITED,
+ MEMBERSHIP_DESCENDANTS,
+ MEMBERSHIP_ALL_AVAILABLE,
+} from '~/runner/constants';
+
+describe('RunnerMembershipToggle', () => {
+ let wrapper;
+
+ const findToggle = () => wrapper.findComponent(GlToggle);
+
+ const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(RunnerMembershipToggle, {
+ propsData: props,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays text', () => {
+ createComponent({ mountFn: mount });
+
+ expect(wrapper.text()).toBe(I18N_SHOW_ONLY_INHERITED);
+ });
+
+ it.each`
+ membershipValue | toggleValue
+ ${MEMBERSHIP_DESCENDANTS} | ${true}
+ ${MEMBERSHIP_ALL_AVAILABLE} | ${false}
+ `(
+ 'Displays a membership of $membershipValue as enabled=$toggleValue',
+ ({ membershipValue, toggleValue }) => {
+ createComponent({ props: { value: membershipValue } });
+
+ expect(findToggle().props('value')).toBe(toggleValue);
+ },
+ );
+
+ it.each`
+ changeEvt | membershipValue
+ ${true} | ${MEMBERSHIP_DESCENDANTS}
+ ${false} | ${MEMBERSHIP_ALL_AVAILABLE}
+ `(
+ 'Emits $changeEvt when value is changed to $membershipValue',
+ ({ changeEvt, membershipValue }) => {
+ createComponent();
+ findToggle().vm.$emit('change', changeEvt);
+
+ expect(wrapper.emitted('input')).toStrictEqual([[membershipValue]]);
+ },
+ );
+});
diff --git a/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js b/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js
index 1a8aced9292..d1f04f0ee37 100644
--- a/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js
+++ b/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js
@@ -29,6 +29,8 @@ describe('RunnerStackedLayoutBanner', () => {
});
it('Does not display a banner when dismissed', async () => {
+ createComponent();
+
findLocalStorageSync().vm.$emit('input', true);
await nextTick();
diff --git a/spec/frontend/runner/components/runner_type_tabs_spec.js b/spec/frontend/runner/components/runner_type_tabs_spec.js
index 45ab8684332..dde35533bc3 100644
--- a/spec/frontend/runner/components/runner_type_tabs_spec.js
+++ b/spec/frontend/runner/components/runner_type_tabs_spec.js
@@ -2,9 +2,21 @@ import { GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerCount from '~/runner/components/stat/runner_count.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
-
-const mockSearch = { runnerType: null, filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' };
+import {
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ DEFAULT_MEMBERSHIP,
+ DEFAULT_SORT,
+} from '~/runner/constants';
+
+const mockSearch = {
+ runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
+ filters: [],
+ pagination: { page: 1 },
+ sort: DEFAULT_SORT,
+};
const mockCount = (type, multiplier = 1) => {
let count;
@@ -113,7 +125,7 @@ describe('RunnerTypeTabs', () => {
});
findTabs().wrappers.forEach((tab) => {
- expect(tab.find(RunnerCount).props()).toEqual({
+ expect(tab.findComponent(RunnerCount).props()).toEqual({
scope: INSTANCE_TYPE,
skip: false,
variables: expect.objectContaining(mockVariables),
diff --git a/spec/frontend/runner/components/runner_update_form_spec.js b/spec/frontend/runner/components/runner_update_form_spec.js
index 7b67a89f989..e12736216a0 100644
--- a/spec/frontend/runner/components/runner_update_form_spec.js
+++ b/spec/frontend/runner/components/runner_update_form_spec.js
@@ -145,7 +145,7 @@ describe('RunnerUpdateForm', () => {
});
it('Form skeleton is shown', () => {
- expect(wrapper.find(GlSkeletonLoader).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
expect(findFields()).toHaveLength(0);
});
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 22f0561ca5f..a7363eb11cd 100644
--- a/spec/frontend/runner/components/search_tokens/tag_token_spec.js
+++ b/spec/frontend/runner/components/search_tokens/tag_token_spec.js
@@ -77,7 +77,7 @@ describe('TagToken', () => {
const findToken = () => wrapper.findComponent(GlToken);
const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- beforeEach(async () => {
+ beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet(TAG_SUGGESTIONS_PATH, { params: { search: '' } }).reply(200, mockTags);
@@ -86,9 +86,6 @@ describe('TagToken', () => {
.reply(200, mockTagsFiltered);
getRecentlyUsedSuggestions.mockReturnValue([]);
-
- createComponent();
- await waitForPromises();
});
afterEach(() => {
@@ -97,11 +94,17 @@ describe('TagToken', () => {
});
describe('when the tags token is displayed', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
it('requests tags suggestions', () => {
expect(mock.history.get[0].params).toEqual({ search: '' });
});
- it('displays tags suggestions', () => {
+ it('displays tags suggestions', async () => {
+ await waitForPromises();
+
mockTags.forEach(({ name }, i) => {
expect(findGlFilteredSearchSuggestions().at(i).text()).toBe(name);
});
@@ -132,13 +135,13 @@ describe('TagToken', () => {
});
describe('when the users filters suggestions', () => {
- beforeEach(async () => {
+ beforeEach(() => {
+ createComponent();
+
findGlFilteredSearchToken().vm.$emit('input', { data: mockSearchTerm });
});
- it('requests filtered tags suggestions', async () => {
- await waitForPromises();
-
+ it('requests filtered tags suggestions', () => {
expect(mock.history.get[1].params).toEqual({ search: mockSearchTerm });
});
@@ -166,7 +169,7 @@ describe('TagToken', () => {
await waitForPromises();
});
- it('error is shown', async () => {
+ it('error is shown', () => {
expect(createAlert).toHaveBeenCalledTimes(1);
expect(createAlert).toHaveBeenCalledWith({ message: expect.any(String) });
});
@@ -180,8 +183,26 @@ describe('TagToken', () => {
await waitForPromises();
});
- it('selected tag is displayed', async () => {
+ it('selected tag is displayed', () => {
expect(findToken().exists()).toBe(true);
});
});
+
+ describe('when suggestions are disabled', () => {
+ beforeEach(async () => {
+ createComponent({
+ config: {
+ ...mockTagTokenConfig,
+ suggestionsDisabled: true,
+ },
+ });
+
+ await waitForPromises();
+ });
+
+ it('displays no suggestions', () => {
+ expect(findGlFilteredSearchSuggestions()).toHaveLength(0);
+ expect(mock.history.get).toHaveLength(0);
+ });
+ });
});
diff --git a/spec/frontend/runner/graphql/local_state_spec.js b/spec/frontend/runner/graphql/local_state_spec.js
index ae874fef00d..915170b53f9 100644
--- a/spec/frontend/runner/graphql/local_state_spec.js
+++ b/spec/frontend/runner/graphql/local_state_spec.js
@@ -4,6 +4,13 @@ import { createLocalState } from '~/runner/graphql/list/local_state';
import getCheckedRunnerIdsQuery from '~/runner/graphql/list/checked_runner_ids.query.graphql';
import { RUNNER_TYPENAME } from '~/runner/constants';
+const makeRunner = (id, deleteRunner = true) => ({
+ id,
+ userPermissions: {
+ deleteRunner,
+ },
+});
+
describe('~/runner/graphql/list/local_state', () => {
let localState;
let apolloClient;
@@ -57,16 +64,21 @@ describe('~/runner/graphql/list/local_state', () => {
});
it('returns checked runners that have a reference in the cache', () => {
- addMockRunnerToCache('a');
- localState.localMutations.setRunnerChecked({ runner: { id: 'a' }, isChecked: true });
+ const id = 'a';
+
+ addMockRunnerToCache(id);
+ localState.localMutations.setRunnerChecked({
+ runner: makeRunner(id),
+ isChecked: true,
+ });
expect(queryCheckedRunnerIds()).toEqual(['a']);
});
it('return checked runners that are not dangling references', () => {
addMockRunnerToCache('a'); // 'b' is missing from the cache, perhaps because it was deleted
- localState.localMutations.setRunnerChecked({ runner: { id: 'a' }, isChecked: true });
- localState.localMutations.setRunnerChecked({ runner: { id: 'b' }, isChecked: true });
+ localState.localMutations.setRunnerChecked({ runner: makeRunner('a'), isChecked: true });
+ localState.localMutations.setRunnerChecked({ runner: makeRunner('b'), isChecked: true });
expect(queryCheckedRunnerIds()).toEqual(['a']);
});
@@ -81,7 +93,7 @@ describe('~/runner/graphql/list/local_state', () => {
beforeEach(() => {
inputs.forEach(([id, isChecked]) => {
addMockRunnerToCache(id);
- localState.localMutations.setRunnerChecked({ runner: { id }, isChecked });
+ localState.localMutations.setRunnerChecked({ runner: makeRunner(id), isChecked });
});
});
it(`for inputs="${inputs}" has a ids="[${expected}]"`, () => {
@@ -102,7 +114,7 @@ describe('~/runner/graphql/list/local_state', () => {
ids.forEach(addMockRunnerToCache);
localState.localMutations.setRunnersChecked({
- runners: ids.map((id) => ({ id })),
+ runners: ids.map((id) => makeRunner(id)),
isChecked,
});
});
@@ -117,7 +129,7 @@ describe('~/runner/graphql/list/local_state', () => {
it('clears all checked items', () => {
['a', 'b', 'c'].forEach((id) => {
addMockRunnerToCache(id);
- localState.localMutations.setRunnerChecked({ runner: { id }, isChecked: true });
+ localState.localMutations.setRunnerChecked({ runner: makeRunner(id), isChecked: true });
});
expect(queryCheckedRunnerIds()).toEqual(['a', 'b', 'c']);
@@ -127,4 +139,29 @@ describe('~/runner/graphql/list/local_state', () => {
expect(queryCheckedRunnerIds()).toEqual([]);
});
});
+
+ describe('when some runners cannot be deleted', () => {
+ beforeEach(() => {
+ addMockRunnerToCache('a');
+ addMockRunnerToCache('b');
+ });
+
+ it('setRunnerChecked does not check runner that cannot be deleted', () => {
+ localState.localMutations.setRunnerChecked({
+ runner: makeRunner('a', false),
+ isChecked: true,
+ });
+
+ expect(queryCheckedRunnerIds()).toEqual([]);
+ });
+
+ it('setRunnersChecked does not check runner that cannot be deleted', () => {
+ localState.localMutations.setRunnersChecked({
+ runners: [makeRunner('a', false), makeRunner('b', false)],
+ isChecked: true,
+ });
+
+ expect(queryCheckedRunnerIds()).toEqual([]);
+ });
+ });
});
diff --git a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
index cee1d436942..a3b67674c94 100644
--- a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
+++ b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
@@ -101,6 +101,11 @@ describe('GroupRunnerShowApp', () => {
Platform darwin
Configuration Runs untagged jobs
Maximum job timeout None
+ Token expiry
+ Runner authentication token expiration
+ Runner authentication tokens will expire based on a set interval.
+ They will automatically rotate once expired. Learn more
+ Never expires
Tags None`.replace(/\s+/g, ' ');
expect(wrapper.text().replace(/\s+/g, ' ')).toContain(expected);
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 a17502c7eec..7482926e151 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -14,6 +14,7 @@ import { s__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory } from '~/lib/utils/url_utility';
import { upgradeStatusTokenConfig } from 'ee_else_ce/runner/components/search_tokens/upgrade_status_token_config';
+import { createLocalState } from '~/runner/graphql/list/local_state';
import RunnerStackedLayoutBanner from '~/runner/components/runner_stacked_layout_banner.vue';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
@@ -24,6 +25,7 @@ import RunnerStats from '~/runner/components/stat/runner_stats.vue';
import RunnerActionsCell from '~/runner/components/cells/runner_actions_cell.vue';
import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
import RunnerPagination from '~/runner/components/runner_pagination.vue';
+import RunnerMembershipToggle from '~/runner/components/runner_membership_toggle.vue';
import {
CREATED_ASC,
@@ -36,9 +38,12 @@ import {
GROUP_TYPE,
PARAM_KEY_PAUSED,
PARAM_KEY_STATUS,
+ PARAM_KEY_TAG,
STATUS_ONLINE,
STATUS_OFFLINE,
STATUS_STALE,
+ MEMBERSHIP_ALL_AVAILABLE,
+ MEMBERSHIP_DESCENDANTS,
RUNNER_PAGE_SIZE,
I18N_EDIT,
} from '~/runner/constants';
@@ -89,15 +94,23 @@ describe('GroupRunnersApp', () => {
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
const findRunnerPaginationNext = () => findRunnerPagination().findByText(s__('Pagination|Next'));
const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
+ const findRunnerMembershipToggle = () => wrapper.findComponent(RunnerMembershipToggle);
+
+ const createComponent = ({
+ props = {},
+ provide = {},
+ mountFn = shallowMountExtended,
+ ...options
+ } = {}) => {
+ const { cacheConfig, localMutations } = createLocalState();
- const createComponent = ({ props = {}, mountFn = shallowMountExtended, ...options } = {}) => {
const handlers = [
[groupRunnersQuery, mockGroupRunnersHandler],
[groupRunnersCountQuery, mockGroupRunnersCountHandler],
];
wrapper = mountFn(GroupRunnersApp, {
- apolloProvider: createMockApollo(handlers),
+ apolloProvider: createMockApollo(handlers, {}, cacheConfig),
propsData: {
registrationToken: mockRegistrationToken,
groupFullPath: mockGroupFullPath,
@@ -105,10 +118,12 @@ describe('GroupRunnersApp', () => {
...props,
},
provide: {
+ localMutations,
onlineContactTimeoutSecs,
staleTimeoutSecs,
emptyStateSvgPath,
emptyStateFilteredSvgPath,
+ ...provide,
},
...options,
});
@@ -147,19 +162,50 @@ describe('GroupRunnersApp', () => {
expect(findRegistrationDropdown().props('type')).toBe(GROUP_TYPE);
});
+ describe('show all available runners toggle', () => {
+ it('shows the membership toggle', () => {
+ createComponent();
+ expect(findRunnerMembershipToggle().exists()).toBe(true);
+ });
+
+ it('sets the membership toggle', () => {
+ setWindowLocation(`?membership[]=${MEMBERSHIP_ALL_AVAILABLE}`);
+
+ createComponent();
+
+ expect(findRunnerMembershipToggle().props('value')).toBe(MEMBERSHIP_ALL_AVAILABLE);
+ });
+
+ it('requests filter', async () => {
+ createComponent();
+ findRunnerMembershipToggle().vm.$emit('input', MEMBERSHIP_ALL_AVAILABLE);
+
+ await waitForPromises();
+
+ expect(mockGroupRunnersHandler).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ membership: MEMBERSHIP_ALL_AVAILABLE,
+ }),
+ );
+ });
+ });
+
it('shows total runner counts', async () => {
await createComponent({ mountFn: mountExtended });
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
status: STATUS_ONLINE,
+ membership: MEMBERSHIP_DESCENDANTS,
groupFullPath: mockGroupFullPath,
});
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
status: STATUS_OFFLINE,
+ membership: MEMBERSHIP_DESCENDANTS,
groupFullPath: mockGroupFullPath,
});
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
status: STATUS_STALE,
+ membership: MEMBERSHIP_DESCENDANTS,
groupFullPath: mockGroupFullPath,
});
@@ -183,6 +229,7 @@ describe('GroupRunnersApp', () => {
groupFullPath: mockGroupFullPath,
status: undefined,
type: undefined,
+ membership: MEMBERSHIP_DESCENDANTS,
sort: DEFAULT_SORT,
first: RUNNER_PAGE_SIZE,
});
@@ -202,6 +249,10 @@ describe('GroupRunnersApp', () => {
type: PARAM_KEY_STATUS,
options: expect.any(Array),
}),
+ expect.objectContaining({
+ type: PARAM_KEY_TAG,
+ suggestionsDisabled: true,
+ }),
upgradeStatusTokenConfig,
]);
});
@@ -213,7 +264,7 @@ describe('GroupRunnersApp', () => {
const { id: graphqlId, shortSha } = node;
const id = getIdFromGraphQLId(graphqlId);
const COUNT_QUERIES = 6; // Smart queries that display a filtered count of runners
- const FILTERED_COUNT_QUERIES = 3; // Smart queries that display a count of runners in tabs
+ const FILTERED_COUNT_QUERIES = 6; // Smart queries that display a count of runners in tabs and single stats
beforeEach(async () => {
await createComponent({ mountFn: mountExtended });
@@ -266,6 +317,7 @@ describe('GroupRunnersApp', () => {
it('sets the filters in the search bar', () => {
expect(findRunnerFilteredSearchBar().props('value')).toEqual({
runnerType: INSTANCE_TYPE,
+ membership: MEMBERSHIP_DESCENDANTS,
filters: [{ type: 'status', value: { data: STATUS_ONLINE, operator: '=' } }],
sort: 'CREATED_DESC',
pagination: {},
@@ -277,6 +329,7 @@ describe('GroupRunnersApp', () => {
groupFullPath: mockGroupFullPath,
status: STATUS_ONLINE,
type: INSTANCE_TYPE,
+ membership: MEMBERSHIP_DESCENDANTS,
sort: DEFAULT_SORT,
first: RUNNER_PAGE_SIZE,
});
@@ -286,6 +339,7 @@ describe('GroupRunnersApp', () => {
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
groupFullPath: mockGroupFullPath,
type: INSTANCE_TYPE,
+ membership: MEMBERSHIP_DESCENDANTS,
status: STATUS_ONLINE,
});
});
@@ -297,6 +351,7 @@ describe('GroupRunnersApp', () => {
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
+ membership: MEMBERSHIP_DESCENDANTS,
filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } }],
sort: CREATED_ASC,
});
@@ -315,6 +370,7 @@ describe('GroupRunnersApp', () => {
expect(mockGroupRunnersHandler).toHaveBeenLastCalledWith({
groupFullPath: mockGroupFullPath,
status: STATUS_ONLINE,
+ membership: MEMBERSHIP_DESCENDANTS,
sort: CREATED_ASC,
first: RUNNER_PAGE_SIZE,
});
@@ -324,6 +380,7 @@ describe('GroupRunnersApp', () => {
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
groupFullPath: mockGroupFullPath,
status: STATUS_ONLINE,
+ membership: MEMBERSHIP_DESCENDANTS,
});
});
});
@@ -334,6 +391,11 @@ describe('GroupRunnersApp', () => {
expect(findRunnerPagination().attributes('disabled')).toBe('true');
});
+ it('runners cannot be deleted in bulk', () => {
+ createComponent();
+ expect(findRunnerList().props('checkable')).toBe(false);
+ });
+
describe('when no runners are found', () => {
beforeEach(async () => {
mockGroupRunnersHandler.mockResolvedValue({
@@ -395,6 +457,7 @@ describe('GroupRunnersApp', () => {
expect(mockGroupRunnersHandler).toHaveBeenLastCalledWith({
groupFullPath: mockGroupFullPath,
+ membership: MEMBERSHIP_DESCENDANTS,
sort: CREATED_DESC,
first: RUNNER_PAGE_SIZE,
after: pageInfo.endCursor,
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
index 555ec40184f..da0c0433b3e 100644
--- a/spec/frontend/runner/mock_data.js
+++ b/spec/frontend/runner/mock_data.js
@@ -17,7 +17,7 @@ import groupRunnersData from 'test_fixtures/graphql/runner/list/group_runners.qu
import groupRunnersDataPaginated from 'test_fixtures/graphql/runner/list/group_runners.query.graphql.paginated.json';
import groupRunnersCountData from 'test_fixtures/graphql/runner/list/group_runners_count.query.graphql.json';
-import { RUNNER_PAGE_SIZE } from '~/runner/constants';
+import { DEFAULT_MEMBERSHIP, RUNNER_PAGE_SIZE } from '~/runner/constants';
const emptyPageInfo = {
__typename: 'PageInfo',
@@ -34,8 +34,18 @@ export const mockSearchExamples = [
{
name: 'a default query',
urlQuery: '',
- search: { runnerType: null, filters: [], pagination: {}, sort: 'CREATED_DESC' },
- graphqlVariables: { sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ search: {
+ runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
+ filters: [],
+ pagination: {},
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
isDefault: true,
},
{
@@ -43,17 +53,24 @@ export const mockSearchExamples = [
urlQuery: '?status[]=ACTIVE',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ status: 'ACTIVE',
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'a single term text search',
urlQuery: '?search=something',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{
type: 'filtered-search-term',
@@ -63,13 +80,19 @@ export const mockSearchExamples = [
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { search: 'something', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ search: 'something',
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'a two terms text search',
urlQuery: '?search=something+else',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{
type: 'filtered-search-term',
@@ -83,24 +106,36 @@ export const mockSearchExamples = [
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { search: 'something else', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ search: 'something else',
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'single instance type',
urlQuery: '?runner_type[]=INSTANCE_TYPE',
search: {
runnerType: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
filters: [],
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { type: 'INSTANCE_TYPE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ type: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'multiple runner status',
urlQuery: '?status[]=ACTIVE&status[]=PAUSED',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{ type: 'status', value: { data: 'ACTIVE', operator: '=' } },
{ type: 'status', value: { data: 'PAUSED', operator: '=' } },
@@ -108,13 +143,19 @@ export const mockSearchExamples = [
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ status: 'ACTIVE',
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'multiple status, a single instance type and a non default sort',
urlQuery: '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&sort=CREATED_ASC',
search: {
runnerType: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
pagination: {},
sort: 'CREATED_ASC',
@@ -122,6 +163,7 @@ export const mockSearchExamples = [
graphqlVariables: {
status: 'ACTIVE',
type: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
sort: 'CREATED_ASC',
first: RUNNER_PAGE_SIZE,
},
@@ -131,11 +173,13 @@ export const mockSearchExamples = [
urlQuery: '?tag[]=tag-1',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: 'tag', value: { data: 'tag-1', operator: '=' } }],
pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
tagList: ['tag-1'],
first: 20,
sort: 'CREATED_DESC',
@@ -146,6 +190,7 @@ export const mockSearchExamples = [
urlQuery: '?tag[]=tag-1&tag[]=tag-2',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'tag', value: { data: 'tag-2', operator: '=' } },
@@ -154,6 +199,7 @@ export const mockSearchExamples = [
sort: 'CREATED_DESC',
},
graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
tagList: ['tag-1', 'tag-2'],
first: 20,
sort: 'CREATED_DESC',
@@ -164,22 +210,34 @@ export const mockSearchExamples = [
urlQuery: '?after=AFTER_CURSOR',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [],
pagination: { after: 'AFTER_CURSOR' },
sort: 'CREATED_DESC',
},
- graphqlVariables: { sort: 'CREATED_DESC', after: 'AFTER_CURSOR', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ after: 'AFTER_CURSOR',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'the previous page',
urlQuery: '?before=BEFORE_CURSOR',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [],
pagination: { before: 'BEFORE_CURSOR' },
sort: 'CREATED_DESC',
},
- graphqlVariables: { sort: 'CREATED_DESC', before: 'BEFORE_CURSOR', last: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ before: 'BEFORE_CURSOR',
+ last: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'the next page filtered by a status, an instance type, tags and a non default sort',
@@ -187,6 +245,7 @@ export const mockSearchExamples = [
'?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&tag[]=tag-1&tag[]=tag-2&sort=CREATED_ASC&after=AFTER_CURSOR',
search: {
runnerType: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
filters: [
{ type: 'status', value: { data: 'ACTIVE', operator: '=' } },
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
@@ -198,6 +257,7 @@ export const mockSearchExamples = [
graphqlVariables: {
status: 'ACTIVE',
type: 'INSTANCE_TYPE',
+ membership: DEFAULT_MEMBERSHIP,
tagList: ['tag-1', 'tag-2'],
sort: 'CREATED_ASC',
after: 'AFTER_CURSOR',
@@ -209,22 +269,34 @@ export const mockSearchExamples = [
urlQuery: '?paused[]=true',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: 'paused', value: { data: 'true', operator: '=' } }],
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { paused: true, sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ paused: true,
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
{
name: 'active runners',
urlQuery: '?paused[]=false',
search: {
runnerType: null,
+ membership: DEFAULT_MEMBERSHIP,
filters: [{ type: 'paused', value: { data: 'false', operator: '=' } }],
pagination: {},
sort: 'CREATED_DESC',
},
- graphqlVariables: { paused: false, sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ graphqlVariables: {
+ paused: false,
+ membership: DEFAULT_MEMBERSHIP,
+ sort: 'CREATED_DESC',
+ first: RUNNER_PAGE_SIZE,
+ },
},
];
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index 3bea0748c47..89959feec39 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -42,20 +42,39 @@ describe('GlobalSearchSidebar', () => {
const findResetLinkButton = () => wrapper.findComponent(GlLink);
describe('template', () => {
- beforeEach(() => {
- createComponent();
- });
+ describe('scope=projects', () => {
+ beforeEach(() => {
+ createComponent({ urlQuery: { ...MOCK_QUERY, scope: 'projects' } });
+ });
- it('renders StatusFilter always', () => {
- expect(findStatusFilter().exists()).toBe(true);
- });
+ it("doesn't render StatusFilter", () => {
+ expect(findStatusFilter().exists()).toBe(false);
+ });
+
+ it("doesn't render ConfidentialityFilter", () => {
+ expect(findConfidentialityFilter().exists()).toBe(false);
+ });
- it('renders ConfidentialityFilter always', () => {
- expect(findConfidentialityFilter().exists()).toBe(true);
+ it("doesn't render ApplyButton", () => {
+ expect(findApplyButton().exists()).toBe(false);
+ });
});
- it('renders ApplyButton always', () => {
- expect(findApplyButton().exists()).toBe(true);
+ describe('scope=issues', () => {
+ beforeEach(() => {
+ createComponent({ urlQuery: MOCK_QUERY });
+ });
+ it('renders StatusFilter', () => {
+ expect(findStatusFilter().exists()).toBe(true);
+ });
+
+ it('renders ConfidentialityFilter', () => {
+ expect(findConfidentialityFilter().exists()).toBe(true);
+ });
+
+ it('renders ApplyButton', () => {
+ expect(findApplyButton().exists()).toBe(true);
+ });
});
});
@@ -115,7 +134,7 @@ describe('GlobalSearchSidebar', () => {
describe('actions', () => {
beforeEach(() => {
- createComponent();
+ createComponent({});
});
it('clicking ApplyButton calls applyQuery', () => {
diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
index a377ddae0eb..c57eabd57b9 100644
--- a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
@@ -34,7 +34,7 @@ describe('ConfidentialityFilter', () => {
wrapper = null;
});
- const findRadioFilter = () => wrapper.find(RadioFilter);
+ const findRadioFilter = () => wrapper.findComponent(RadioFilter);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js
index c0a8259b4fe..94d529348a9 100644
--- a/spec/frontend/search/sidebar/components/radio_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js
@@ -43,7 +43,7 @@ describe('RadioFilter', () => {
wrapper = null;
});
- const findGlRadioButtonGroup = () => wrapper.find(GlFormRadioGroup);
+ const findGlRadioButtonGroup = () => wrapper.findComponent(GlFormRadioGroup);
const findGlRadioButtons = () => findGlRadioButtonGroup().findAllComponents(GlFormRadio);
const findGlRadioButtonsText = () => findGlRadioButtons().wrappers.map((w) => w.text());
diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js
index 5d8ecd8733a..f3152c014b6 100644
--- a/spec/frontend/search/sidebar/components/status_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/status_filter_spec.js
@@ -34,7 +34,7 @@ describe('StatusFilter', () => {
wrapper = null;
});
- const findRadioFilter = () => wrapper.find(RadioFilter);
+ const findRadioFilter = () => wrapper.findComponent(RadioFilter);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/search/sort/components/app_spec.js b/spec/frontend/search/sort/components/app_spec.js
index 0e8eebba3cb..a566b9b99d3 100644
--- a/spec/frontend/search/sort/components/app_spec.js
+++ b/spec/frontend/search/sort/components/app_spec.js
@@ -43,9 +43,9 @@ describe('GlobalSearchSort', () => {
wrapper = null;
});
- const findSortButtonGroup = () => wrapper.find(GlButtonGroup);
- const findSortDropdown = () => wrapper.find(GlDropdown);
- const findSortDirectionButton = () => wrapper.find(GlButton);
+ const findSortButtonGroup = () => wrapper.findComponent(GlButtonGroup);
+ const findSortDropdown = () => wrapper.findComponent(GlDropdown);
+ const findSortDirectionButton = () => wrapper.findComponent(GlButton);
const findDropdownItems = () => findSortDropdown().findAllComponents(GlDropdownItem);
const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text());
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index 2f93d3f6805..c442ffa521d 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import * as actions from '~/search/store/actions';
@@ -37,8 +37,8 @@ describe('Global Search Store Actions', () => {
let state;
const flashCallback = (callCount) => {
- expect(createFlash).toHaveBeenCalledTimes(callCount);
- createFlash.mockClear();
+ expect(createAlert).toHaveBeenCalledTimes(callCount);
+ createAlert.mockClear();
};
beforeEach(() => {
diff --git a/spec/frontend/search/topbar/components/app_spec.js b/spec/frontend/search/topbar/components/app_spec.js
index 0a44688bfe0..c7fd7084101 100644
--- a/spec/frontend/search/topbar/components/app_spec.js
+++ b/spec/frontend/search/topbar/components/app_spec.js
@@ -36,9 +36,9 @@ describe('GlobalSearchTopbar', () => {
wrapper.destroy();
});
- const findGlSearchBox = () => wrapper.find(GlSearchBoxByClick);
- const findGroupFilter = () => wrapper.find(GroupFilter);
- const findProjectFilter = () => wrapper.find(ProjectFilter);
+ const findGlSearchBox = () => wrapper.findComponent(GlSearchBoxByClick);
+ const findGroupFilter = () => wrapper.findComponent(GroupFilter);
+ const findProjectFilter = () => wrapper.findComponent(ProjectFilter);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/search/topbar/components/group_filter_spec.js b/spec/frontend/search/topbar/components/group_filter_spec.js
index bd173791fee..b2d0297fdc2 100644
--- a/spec/frontend/search/topbar/components/group_filter_spec.js
+++ b/spec/frontend/search/topbar/components/group_filter_spec.js
@@ -53,7 +53,7 @@ describe('GroupFilter', () => {
wrapper.destroy();
});
- const findSearchableDropdown = () => wrapper.find(SearchableDropdown);
+ const findSearchableDropdown = () => wrapper.findComponent(SearchableDropdown);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/search/topbar/components/project_filter_spec.js b/spec/frontend/search/topbar/components/project_filter_spec.js
index 5afcd281d0c..297a536e075 100644
--- a/spec/frontend/search/topbar/components/project_filter_spec.js
+++ b/spec/frontend/search/topbar/components/project_filter_spec.js
@@ -53,7 +53,7 @@ describe('ProjectFilter', () => {
wrapper.destroy();
});
- const findSearchableDropdown = () => wrapper.find(SearchableDropdown);
+ const findSearchableDropdown = () => wrapper.findComponent(SearchableDropdown);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/search_settings/components/search_settings_spec.js b/spec/frontend/search_settings/components/search_settings_spec.js
index d0a2018c7f0..3f856968db6 100644
--- a/spec/frontend/search_settings/components/search_settings_spec.js
+++ b/spec/frontend/search_settings/components/search_settings_spec.js
@@ -1,4 +1,4 @@
-import { GlSearchBoxByType } from '@gitlab/ui';
+import { GlEmptyState, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { setHTMLFixture } from 'helpers/fixtures';
import SearchSettings from '~/search_settings/components/search_settings.vue';
@@ -14,7 +14,7 @@ describe('search_settings/components/search_settings.vue', () => {
const EXTRA_SETTINGS_ID = 'js-extra-settings';
const TEXT_CONTAIN_SEARCH_TERM = `This text contain ${SEARCH_TERM}.`;
const TEXT_WITH_SIBLING_ELEMENTS = `${SEARCH_TERM} <a data-testid="sibling" href="#">Learn more</a>.`;
-
+ const HIDE_WHEN_EMPTY_CLASS = 'js-hide-when-nothing-matches-search';
let wrapper;
const buildWrapper = () => {
@@ -22,6 +22,7 @@ describe('search_settings/components/search_settings.vue', () => {
propsData: {
searchRoot: document.querySelector(`#${ROOT_ID}`),
sectionSelector: SECTION_SELECTOR,
+ hideWhenEmptySelector: `.${HIDE_WHEN_EMPTY_CLASS}`,
isExpandedFn: isExpanded,
},
// Add real listeners so we can simplify and strengthen some tests.
@@ -45,7 +46,9 @@ describe('search_settings/components/search_settings.vue', () => {
};
const findMatchSiblingElement = () => document.querySelector(`[data-testid="sibling"]`);
- const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findHideWhenEmpty = () => document.querySelector(`.${HIDE_WHEN_EMPTY_CLASS}`);
const search = (term) => {
findSearchBox().vm.$emit('input', term);
};
@@ -67,6 +70,9 @@ describe('search_settings/components/search_settings.vue', () => {
<span>${TEXT_CONTAIN_SEARCH_TERM}</span>
<span>${TEXT_WITH_SIBLING_ELEMENTS}</span>
</section>
+ <div class="row ${HIDE_WHEN_EMPTY_CLASS}">
+ <button type="submit">Save</button>
+ </div>
</div>
</div>
`);
@@ -93,13 +99,41 @@ describe('search_settings/components/search_settings.vue', () => {
expect(wrapper.emitted('expand')).toEqual([[section]]);
});
+ describe('when nothing matches the search term', () => {
+ beforeEach(() => {
+ search('xxxxxxxxxxx');
+ });
+
+ it('shows an empty state', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('hides the form buttons', () => {
+ expect(findHideWhenEmpty()).toHaveClass(HIDE_CLASS);
+ });
+ });
+
+ describe('when something matches the search term', () => {
+ beforeEach(() => {
+ search(SEARCH_TERM);
+ });
+
+ it('shows no empty state', () => {
+ expect(findEmptyState().exists()).toBe(false);
+ });
+
+ it('shows the form buttons', () => {
+ expect(findHideWhenEmpty()).not.toHaveClass(HIDE_CLASS);
+ });
+ });
+
it('highlight elements that match the search term', () => {
search(SEARCH_TERM);
expect(highlightedElementsCount()).toBe(3);
});
- it('highlight only search term and not the whole line', () => {
+ it('highlights only search term and not the whole line', () => {
search(SEARCH_TERM);
expect(highlightedTextNodes()).toBe(true);
@@ -142,6 +176,10 @@ describe('search_settings/components/search_settings.vue', () => {
expect(visibleSectionsCount()).toBe(sectionsCount());
});
+ it('hides the empty state', () => {
+ expect(findEmptyState().exists()).toBe(false);
+ });
+
it('removes the highlight from all elements', () => {
expect(highlightedElementsCount()).toBe(0);
});
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 222cabc6a63..ddefda2ffc3 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -281,7 +281,7 @@ describe('App component', () => {
});
});
- it(shouldRender ? 'renders' : 'does not render', () => {
+ it(`${shouldRender ? 'renders' : 'does not render'}`, () => {
expect(findAutoDevopsEnabledAlert().exists()).toBe(shouldRender);
});
});
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index b6451af57d7..8f2b5383191 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -193,7 +193,7 @@ describe('TrainingProviderList component', () => {
});
it(`shows the learn more link for enabled card ${index}`, () => {
- const learnMoreLink = findCards().at(index).find(GlLink);
+ const learnMoreLink = findCards().at(index).findComponent(GlLink);
const tempLogo = TEMP_PROVIDER_URLS[name];
if (tempLogo) {
@@ -224,7 +224,7 @@ describe('TrainingProviderList component', () => {
});
it('shows a info-tooltip that describes the purpose of a primary provider', () => {
- const infoIcon = findPrimaryProviderRadios().at(index).find(GlIcon);
+ const infoIcon = findPrimaryProviderRadios().at(index).findComponent(GlIcon);
const tooltip = getBinding(infoIcon.element, 'gl-tooltip');
expect(infoIcon.props()).toMatchObject({
diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
index ff44acfc4f9..c34d8e47a6c 100644
--- a/spec/frontend/security_configuration/components/upgrade_banner_spec.js
+++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
@@ -79,7 +79,7 @@ describe('UpgradeBanner component', () => {
expect(wrapperText).toContain('statistics in the merge request');
expect(wrapperText).toContain('statistics across projects');
expect(wrapperText).toContain('Runtime security metrics');
- expect(wrapperText).toContain('More scan types, including Container Scanning,');
+ expect(wrapperText).toContain('More scan types, including DAST,');
});
describe('when user interacts', () => {
diff --git a/spec/frontend/self_monitor/components/self_monitor_form_spec.js b/spec/frontend/self_monitor/components/self_monitor_form_spec.js
index 89ad5a00a14..c690bbf1c57 100644
--- a/spec/frontend/self_monitor/components/self_monitor_form_spec.js
+++ b/spec/frontend/self_monitor/components/self_monitor_form_spec.js
@@ -42,7 +42,7 @@ describe('self monitor component', () => {
it('renders as an expand button by default', () => {
wrapper = shallowMount(SelfMonitor, { store });
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.text()).toBe('Expand');
});
@@ -79,7 +79,7 @@ describe('self monitor component', () => {
wrapper = shallowMount(SelfMonitor, { store });
expect(
- wrapper.find({ ref: 'selfMonitoringFormText' }).find('a').attributes('href'),
+ wrapper.findComponent({ ref: 'selfMonitoringFormText' }).find('a').attributes('href'),
).toEqual(`${TEST_HOST}/instance-administrators-random/gitlab-self-monitoring`);
});
diff --git a/spec/frontend/set_status_modal/set_status_form_spec.js b/spec/frontend/set_status_modal/set_status_form_spec.js
index 8e1623eedf5..486e06d2906 100644
--- a/spec/frontend/set_status_modal/set_status_form_spec.js
+++ b/spec/frontend/set_status_modal/set_status_form_spec.js
@@ -127,6 +127,8 @@ describe('SetStatusForm', () => {
describe('when `Clear status after` dropdown is changed', () => {
it('emits `clear-status-after-click`', async () => {
+ await createComponent();
+
await wrapper.findByTestId('thirtyMinutes').trigger('click');
expect(wrapper.emitted('clear-status-after-click')).toEqual([[timeRanges[0]]]);
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 c5fb590646d..53d2a9e0978 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
@@ -4,7 +4,7 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import * as UserApi from '~/api/user_api';
import EmojiPicker from '~/emoji/components/picker.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import stubChildren from 'helpers/stub_children';
import SetStatusModalWrapper from '~/set_status_modal/set_status_modal_wrapper.vue';
import { AVAILABILITY_STATUS } from '~/set_status_modal/constants';
@@ -51,11 +51,11 @@ describe('SetStatusModalWrapper', () => {
});
};
- const findModal = () => wrapper.find(GlModal);
+ const findModal = () => wrapper.findComponent(GlModal);
const findMessageField = () =>
wrapper.findByPlaceholderText(SetStatusForm.i18n.statusMessagePlaceholder);
const findClearStatusButton = () => wrapper.find('.js-clear-user-status-button');
- const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findAvailabilityCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const findClearStatusAtMessage = () => wrapper.find('[data-testid="clear-status-at-message"]');
const getEmojiPicker = () => wrapper.findComponent(EmojiPickerStub);
@@ -253,7 +253,7 @@ describe('SetStatusModalWrapper', () => {
findModal().vm.$emit('primary');
await nextTick();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: "Sorry, we weren't able to set your status. Please try again later.",
});
});
diff --git a/spec/frontend/sidebar/assignee_title_spec.js b/spec/frontend/sidebar/assignee_title_spec.js
index e29e3d489a5..14a6bdbf907 100644
--- a/spec/frontend/sidebar/assignee_title_spec.js
+++ b/spec/frontend/sidebar/assignee_title_spec.js
@@ -85,7 +85,7 @@ describe('AssigneeTitle component', () => {
editable: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('renders spinner when loading', () => {
@@ -95,7 +95,7 @@ describe('AssigneeTitle component', () => {
editable: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('does not render edit link when not editable', () => {
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index c2aff456abb..7cf7fd33022 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -33,7 +33,7 @@ describe('Assignee component', () => {
it('displays no assignee icon when collapsed', () => {
createWrapper();
const collapsedChildren = findCollapsedChildren();
- const userIcon = collapsedChildren.at(0).find(GlIcon);
+ const userIcon = collapsedChildren.at(0).findComponent(GlIcon);
expect(collapsedChildren.length).toBe(1);
expect(collapsedChildren.at(0).attributes('aria-label')).toBe('None');
diff --git a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
index 8cde70ff8da..4764f3607bc 100644
--- a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
+++ b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
@@ -46,7 +46,7 @@ describe('AssigneeAvatarLink component', () => {
it('renders assignee avatar', () => {
createComponent();
- expect(wrapper.find(AssigneeAvatar).props()).toEqual(
+ expect(wrapper.findComponent(AssigneeAvatar).props()).toEqual(
expect.objectContaining({
issuableType: TEST_ISSUABLE_TYPE,
user: userDataMock(),
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
index 81ff51133bf..7e7d4921cfa 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
@@ -21,7 +21,7 @@ describe('CollapsedAssigneeList component', () => {
});
}
- const findNoUsersIcon = () => wrapper.find(GlIcon);
+ const findNoUsersIcon = () => wrapper.findComponent(GlIcon);
const findAvatarCounter = () => wrapper.find('.avatar-counter');
const findAssignees = () => wrapper.findAllComponents(CollapsedAssignee);
const getTooltipTitle = () => wrapper.attributes('title');
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
index 2d5a3653631..4db95114b96 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
@@ -34,7 +34,7 @@ describe('CollapsedAssignee assignee component', () => {
it('has assignee avatar', () => {
createComponent();
- expect(wrapper.find(AssigneeAvatar).props()).toEqual({
+ expect(wrapper.findComponent(AssigneeAvatar).props()).toEqual({
imgSize: 24,
user: TEST_USER,
issuableType: TEST_ISSUABLE_TYPE,
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 3644a51c7fd..cbb4c41dd14 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 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 { createAlert } from '~/flash';
import { IssuableType } from '~/issues/constants';
import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
@@ -167,7 +167,7 @@ describe('Sidebar assignees widget', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while fetching participants.',
});
});
@@ -333,7 +333,7 @@ describe('Sidebar assignees widget', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while updating assignees.',
});
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
index 724fba62479..6c22d2f687d 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
@@ -67,15 +67,33 @@ describe('boards sidebar remove issue', () => {
expect(findLoader().exists()).toBe(true);
});
- it('shows expanded content and hides collapsed content when clicking edit button', async () => {
- const slots = { default: '<div>Select item</div>' };
- createComponent({ canUpdate: true, slots });
- findEditButton().vm.$emit('click');
-
- await nextTick();
-
- expect(findCollapsed().isVisible()).toBe(false);
- expect(findExpanded().isVisible()).toBe(true);
+ describe('when clicking edit button', () => {
+ describe('when can edit', () => {
+ it('shows expanded (editable) content', async () => {
+ const slots = { default: '<div>Select item</div>' };
+ createComponent({ canUpdate: true, slots });
+ findEditButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(true);
+ });
+ });
+
+ describe('when cannot edit', () => {
+ it('shows collapsed (non-editable) content', async () => {
+ const slots = { default: '<div>Select item</div>' };
+ createComponent({ canUpdate: false, slots });
+ // Simulate parent component calling `expand` method when user
+ // clicks on collapsed sidebar (e.g. in sidebar_weight_widget.vue)
+ wrapper.vm.expand();
+ await nextTick();
+
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findExpanded().isVisible()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
index b902d7313fd..03c2e1a37a9 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -46,7 +46,7 @@ describe('UncollapsedAssigneeList component', () => {
});
it('calls the AssigneeAvatarLink with the proper props', () => {
- expect(wrapper.find(AssigneeAvatarLink).exists()).toBe(true);
+ expect(wrapper.findComponent(AssigneeAvatarLink).exists()).toBe(true);
});
it('Shows one user with avatar, username and author name', () => {
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
index 1ea035c7184..b27f7c6b4e1 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
@@ -2,7 +2,7 @@ import { GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import SidebarConfidentialityForm from '~/sidebar/components/confidential/sidebar_confidentiality_form.vue';
import { confidentialityQueries } from '~/sidebar/constants';
@@ -63,7 +63,7 @@ describe('Sidebar Confidentiality Form', () => {
findConfidentialToggle().vm.$emit('click', new MouseEvent('click'));
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while setting issue confidentiality.',
});
});
@@ -77,7 +77,7 @@ describe('Sidebar Confidentiality Form', () => {
findConfidentialToggle().vm.$emit('click', new MouseEvent('click'));
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'Houston, we have a problem!',
});
});
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
index 3a3f0b1d9fa..e486a8e9ec7 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
@@ -4,7 +4,7 @@ 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 { createAlert } from '~/flash';
import SidebarConfidentialityContent from '~/sidebar/components/confidential/sidebar_confidentiality_content.vue';
import SidebarConfidentialityForm from '~/sidebar/components/confidential/sidebar_confidentiality_form.vue';
import SidebarConfidentialityWidget, {
@@ -126,7 +126,7 @@ describe('Sidebar Confidentiality Widget', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('closes the form and dispatches an event when `closeForm` is emitted', async () => {
diff --git a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
index 699b2bbd0b1..69a8d645973 100644
--- a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
+++ b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
@@ -12,6 +12,6 @@ describe('CopyEmailToClipboard component', () => {
});
it('sets CopyableField `value` prop to issueEmailAddress', () => {
- expect(wrapper.find(CopyableField).props('value')).toBe(mockIssueEmailAddress);
+ expect(wrapper.findComponent(CopyableField).props('value')).toBe(mockIssueEmailAddress);
});
});
diff --git a/spec/frontend/sidebar/components/crm_contacts_spec.js b/spec/frontend/sidebar/components/crm_contacts_spec.js
index 6456829258f..6d76fa1f9df 100644
--- a/spec/frontend/sidebar/components/crm_contacts_spec.js
+++ b/spec/frontend/sidebar/components/crm_contacts_spec.js
@@ -3,7 +3,7 @@ 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 { createAlert } 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';
@@ -47,7 +47,7 @@ describe('Issue crm contacts component', () => {
mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('calls the query with correct variables', () => {
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 1e2173e2988..67413cffdda 100644
--- a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
@@ -4,7 +4,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 createFlash from '~/flash';
+import { createAlert } from '~/flash';
import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarFormattedDate from '~/sidebar/components/date/sidebar_formatted_date.vue';
import SidebarInheritDate from '~/sidebar/components/date/sidebar_inherit_date.vue';
@@ -28,7 +28,7 @@ describe('Sidebar date Widget', () => {
const findEditableItem = () => wrapper.findComponent(SidebarEditableItem);
const findPopoverIcon = () => wrapper.find('[data-testid="inherit-date-popover"]');
- const findDatePicker = () => wrapper.find(GlDatepicker);
+ const findDatePicker = () => wrapper.findComponent(GlDatepicker);
const createComponent = ({
dueDateQueryHandler = jest.fn().mockResolvedValue(issuableDueDateResponse()),
@@ -149,14 +149,14 @@ describe('Sidebar date Widget', () => {
createComponent({ canInherit });
await waitForPromises();
- expect(wrapper.find(component).exists()).toBe(expected);
+ expect(wrapper.findComponent(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);
+ expect(wrapper.findComponent(SidebarInheritDate).exists()).toBe(false);
});
it('displays a flash message when query is rejected', async () => {
@@ -165,7 +165,7 @@ describe('Sidebar date Widget', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it.each`
diff --git a/spec/frontend/sidebar/components/date/sidebar_formatted_date_spec.js b/spec/frontend/sidebar/components/date/sidebar_formatted_date_spec.js
index 1eda4ea977f..cbe01263dcd 100644
--- a/spec/frontend/sidebar/components/date/sidebar_formatted_date_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_formatted_date_spec.js
@@ -5,7 +5,7 @@ import SidebarFormattedDate from '~/sidebar/components/date/sidebar_formatted_da
describe('SidebarFormattedDate', () => {
let wrapper;
const findFormattedDate = () => wrapper.find("[data-testid='sidebar-date-value']");
- const findRemoveButton = () => wrapper.find(GlButton);
+ const findRemoveButton = () => wrapper.findComponent(GlButton);
const createComponent = ({ hasDate = true } = {}) => {
wrapper = shallowMount(SidebarFormattedDate, {
diff --git a/spec/frontend/sidebar/components/severity/severity_spec.js b/spec/frontend/sidebar/components/severity/severity_spec.js
index 1e4624e4dcd..2146155791e 100644
--- a/spec/frontend/sidebar/components/severity/severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/severity_spec.js
@@ -21,7 +21,7 @@ describe('SeverityToken', () => {
}
});
- const findIcon = () => wrapper.find(GlIcon);
+ const findIcon = () => wrapper.findComponent(GlIcon);
it('renders severity token for each severity type', () => {
Object.values(INCIDENT_SEVERITY).forEach((severity) => {
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
index 83eb9a18597..bdea33371d8 100644
--- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -2,7 +2,7 @@ import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlTooltip, GlSprintf } from
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { INCIDENT_SEVERITY, ISSUABLE_TYPES } from '~/sidebar/components/severity/constants';
import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
@@ -59,7 +59,7 @@ describe('SidebarSeverity', () => {
const findCriticalSeverityDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findTooltip = () => wrapper.findComponent(GlTooltip);
- const findCollapsedSeverity = () => wrapper.find({ ref: 'severity' });
+ const findCollapsedSeverity = () => wrapper.findComponent({ ref: 'severity' });
describe('Severity widget', () => {
it('renders severity dropdown and token', () => {
@@ -104,7 +104,7 @@ describe('SidebarSeverity', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('shows loading icon while updating', async () => {
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
index 6761731c093..8ab4d8ea051 100644
--- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
@@ -15,7 +15,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { IssuableType } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
@@ -369,9 +369,9 @@ describe('SidebarDropdownWidget', () => {
findDropdownItemWithText('title').vm.$emit('click');
});
- it(`calls createFlash with "${expectedMsg}"`, async () => {
+ it(`calls createAlert with "${expectedMsg}"`, async () => {
await nextTick();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: expectedMsg,
captureError: true,
error: expectedMsg,
@@ -455,14 +455,14 @@ describe('SidebarDropdownWidget', () => {
describe('milestones', () => {
let projectMilestonesSpy;
- it('should call createFlash if milestones query fails', async () => {
+ it('should call createAlert if milestones query fails', async () => {
await createComponentWithApollo({
projectMilestonesSpy: jest.fn().mockRejectedValue(error),
});
await clickEdit();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: wrapper.vm.i18n.listFetchError,
captureError: true,
error: expect.any(Error),
@@ -514,12 +514,12 @@ describe('SidebarDropdownWidget', () => {
});
describe('currentAttributes', () => {
- it('should call createFlash if currentAttributes query fails', async () => {
+ it('should call createAlert if currentAttributes query fails', async () => {
await createComponentWithApollo({
currentMilestoneSpy: jest.fn().mockRejectedValue(error),
});
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: wrapper.vm.i18n.currentFetchError,
captureError: true,
error: expect.any(Error),
diff --git a/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js b/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
index 430acf9f9e7..c94f9918243 100644
--- a/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
+++ b/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
@@ -4,7 +4,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 createFlash from '~/flash';
+import { createAlert } from '~/flash';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import SidebarSubscriptionWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import issueSubscribedQuery from '~/sidebar/queries/issue_subscribed.query.graphql';
@@ -144,7 +144,7 @@ describe('Sidebar Subscriptions Widget', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
describe('merge request', () => {
diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js
index 4e619a4e609..af72122052f 100644
--- a/spec/frontend/sidebar/components/time_tracking/report_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js
@@ -6,7 +6,7 @@ import VueApollo from 'vue-apollo';
import { extendedWrapper } 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 { createAlert } from '~/flash';
import Report from '~/sidebar/components/time_tracking/report.vue';
import getIssueTimelogsQuery from '~/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql';
import getMrTimelogsQuery from '~/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql';
@@ -65,7 +65,7 @@ describe('Issuable Time Tracking Report', () => {
mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
describe('for issue', () => {
@@ -153,7 +153,7 @@ describe('Issuable Time Tracking Report', () => {
await findDeleteButton().trigger('click');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(mutateSpy).toHaveBeenCalledWith({
mutation: deleteTimelogMutation,
variables: {
@@ -164,7 +164,7 @@ describe('Issuable Time Tracking Report', () => {
});
});
- it('calls `createFlash` with errorMessage and does not remove the row on promise reject', async () => {
+ it('calls `createAlert` with errorMessage and does not remove the row on promise reject', async () => {
const mutateSpy = jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue({});
await waitForPromises();
@@ -180,7 +180,7 @@ describe('Issuable Time Tracking Report', () => {
},
});
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while removing the timelog.',
captureError: true,
error: expect.any(Object),
diff --git a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
index ea931782d1e..f73491ca95f 100644
--- a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
+++ b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
@@ -4,7 +4,7 @@ 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 { createAlert } from '~/flash';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import epicTodoQuery from '~/sidebar/queries/epic_todo.query.graphql';
import TodoButton from '~/vue_shared/components/sidebar/todo_toggle/todo_button.vue';
@@ -83,7 +83,7 @@ describe('Sidebar Todo Widget', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
describe('collapsed', () => {
@@ -97,13 +97,13 @@ describe('Sidebar Todo Widget', () => {
});
it('shows add todo icon', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
- expect(wrapper.find(GlIcon).props('name')).toBe('todo-add');
+ expect(wrapper.findComponent(GlIcon).props('name')).toBe('todo-add');
});
it('sets default tooltip title', () => {
- expect(wrapper.find(GlButton).attributes('title')).toBe('Add a to do');
+ expect(wrapper.findComponent(GlButton).attributes('title')).toBe('Add a to do');
});
it('when user has a to do', async () => {
@@ -112,12 +112,12 @@ describe('Sidebar Todo Widget', () => {
});
await waitForPromises();
- expect(wrapper.find(GlIcon).props('name')).toBe('todo-done');
- expect(wrapper.find(GlButton).attributes('title')).toBe('Mark as done');
+ expect(wrapper.findComponent(GlIcon).props('name')).toBe('todo-done');
+ expect(wrapper.findComponent(GlButton).attributes('title')).toBe('Mark as done');
});
it('emits `todoUpdated` event on click on icon', async () => {
- wrapper.find(GlIcon).vm.$emit('click', event);
+ wrapper.findComponent(GlIcon).vm.$emit('click', event);
await nextTick();
expect(wrapper.emitted('todoUpdated')).toEqual([[false]]);
diff --git a/spec/frontend/sidebar/issuable_assignees_spec.js b/spec/frontend/sidebar/issuable_assignees_spec.js
index dc59b68bbd4..1161fefcc64 100644
--- a/spec/frontend/sidebar/issuable_assignees_spec.js
+++ b/spec/frontend/sidebar/issuable_assignees_spec.js
@@ -17,7 +17,7 @@ describe('IssuableAssignees', () => {
},
});
};
- const findUncollapsedAssigneeList = () => wrapper.find(UncollapsedAssigneeList);
+ const findUncollapsedAssigneeList = () => wrapper.findComponent(UncollapsedAssigneeList);
const findEmptyAssignee = () => wrapper.find('[data-testid="none"]');
afterEach(() => {
diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
index 971744edb0f..2abb0c24d7d 100644
--- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { createStore as createMrStore } from '~/mr_notes/stores';
import createStore from '~/notes/stores';
import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
@@ -129,7 +129,7 @@ describe('EditFormButtons', () => {
});
it('does not flash an error message', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -162,7 +162,7 @@ describe('EditFormButtons', () => {
});
it('calls flash with the correct message', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong trying to change the locked state of this ${issuableDisplayName}`,
});
});
diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
index 986ccaea4b6..8f825847cfc 100644
--- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
+++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
@@ -26,7 +26,7 @@ describe('IssuableLockForm', () => {
const findSidebarCollapseIcon = () => wrapper.find('[data-testid="sidebar-collapse-icon"]');
const findLockStatus = () => wrapper.find('[data-testid="lock-status"]');
const findEditLink = () => wrapper.find('[data-testid="edit-link"]');
- const findEditForm = () => wrapper.find(EditForm);
+ const findEditForm = () => wrapper.findComponent(EditForm);
const findSidebarLockStatusTooltip = () =>
getBinding(findSidebarCollapseIcon().element, 'gl-tooltip');
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index 2afe9647cbe..391cbb1e0d5 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -283,7 +283,6 @@ export const epicParticipantsResponse = () => ({
name: 'Jacki Kub',
username: 'francina.skiles',
webUrl: '/franc',
- status: null,
},
],
},
diff --git a/spec/frontend/sidebar/participants_spec.js b/spec/frontend/sidebar/participants_spec.js
index 2517b625225..f7a626a189c 100644
--- a/spec/frontend/sidebar/participants_spec.js
+++ b/spec/frontend/sidebar/participants_spec.js
@@ -36,7 +36,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('does not show loading spinner not loading', () => {
@@ -44,7 +44,7 @@ describe('Participants', () => {
loading: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('shows participant count when given', () => {
@@ -73,7 +73,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('when only showing visible participants, shows an avatar only for each participant under the limit', async () => {
diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js
index 6b4eed5ad0f..68ecd62e4c6 100644
--- a/spec/frontend/sidebar/reviewer_title_spec.js
+++ b/spec/frontend/sidebar/reviewer_title_spec.js
@@ -47,7 +47,7 @@ describe('ReviewerTitle component', () => {
editable: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('renders spinner when loading', () => {
@@ -57,7 +57,7 @@ describe('ReviewerTitle component', () => {
editable: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('does not render edit link when not editable', () => {
diff --git a/spec/frontend/sidebar/reviewers_spec.js b/spec/frontend/sidebar/reviewers_spec.js
index 88bacc9b7f7..229f7ffbe04 100644
--- a/spec/frontend/sidebar/reviewers_spec.js
+++ b/spec/frontend/sidebar/reviewers_spec.js
@@ -43,7 +43,7 @@ describe('Reviewer component', () => {
it('displays no reviewer icon when collapsed', () => {
createWrapper();
const collapsedChildren = findCollapsedChildren();
- const userIcon = collapsedChildren.at(0).find(GlIcon);
+ const userIcon = collapsedChildren.at(0).findComponent(GlIcon);
expect(collapsedChildren.length).toBe(1);
expect(collapsedChildren.at(0).attributes('aria-label')).toBe('None');
diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js
index 68d20060c37..2cb2425532b 100644
--- a/spec/frontend/sidebar/sidebar_assignees_spec.js
+++ b/spec/frontend/sidebar/sidebar_assignees_spec.js
@@ -73,19 +73,19 @@ describe('sidebar assignees', () => {
it('hides assignees until fetched', async () => {
createComponent();
- expect(wrapper.find(Assigness).exists()).toBe(false);
+ expect(wrapper.findComponent(Assigness).exists()).toBe(false);
wrapper.vm.store.isFetching.assignees = false;
await nextTick();
- expect(wrapper.find(Assigness).exists()).toBe(true);
+ expect(wrapper.findComponent(Assigness).exists()).toBe(true);
});
describe('when issuableType is issue', () => {
it('finds AssigneesRealtime component', () => {
createComponent();
- expect(wrapper.find(AssigneesRealtime).exists()).toBe(true);
+ expect(wrapper.findComponent(AssigneesRealtime).exists()).toBe(true);
});
});
@@ -93,7 +93,7 @@ describe('sidebar assignees', () => {
it('does not find AssigneesRealtime component', () => {
createComponent({ issuableType: 'MR' });
- expect(wrapper.find(AssigneesRealtime).exists()).toBe(false);
+ expect(wrapper.findComponent(AssigneesRealtime).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/sidebar_mediator_spec.js b/spec/frontend/sidebar/sidebar_mediator_spec.js
index 355f0c45bbe..bb5e7f7ff16 100644
--- a/spec/frontend/sidebar/sidebar_mediator_spec.js
+++ b/spec/frontend/sidebar/sidebar_mediator_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
-import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service';
+import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
@@ -42,22 +42,14 @@ describe('Sidebar mediator', () => {
});
});
- it('fetches the data', () => {
+ it('fetches the data', async () => {
const mockData = Mock.responseMap.GET[mediatorMockData.endpoint];
mock.onGet(mediatorMockData.endpoint).reply(200, mockData);
-
- const mockGraphQlData = Mock.graphQlResponseData;
- const graphQlSpy = jest.spyOn(gqClient, 'query').mockReturnValue({
- data: mockGraphQlData,
- });
const spy = jest.spyOn(mediator, 'processFetchedData').mockReturnValue(Promise.resolve());
+ await mediator.fetch();
- return mediator.fetch().then(() => {
- expect(spy).toHaveBeenCalledWith(mockData, mockGraphQlData);
-
- spy.mockRestore();
- graphQlSpy.mockRestore();
- });
+ expect(spy).toHaveBeenCalledWith(mockData);
+ spy.mockRestore();
});
it('processes fetched data', () => {
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js
index 2e6807ed9d8..195cc6ddeeb 100644
--- a/spec/frontend/sidebar/sidebar_move_issue_spec.js
+++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
import SidebarService from '~/sidebar/services/sidebar_service';
@@ -115,7 +115,7 @@ describe('SidebarMoveIssue', () => {
// Wait for the move issue request to fail
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
expect(test.$confirmButton.prop('disabled')).toBe(false);
expect(test.$confirmButton.hasClass('is-loading')).toBe(false);
});
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index 6ab8e1e0ebc..1a1aa370eef 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -108,7 +108,7 @@ describe('Subscriptions', () => {
expect(wrapper.findByTestId('subscription-title').text()).toContain(
subscribeDisabledDescription,
);
- expect(wrapper.find({ ref: 'tooltip' }).attributes('title')).toBe(
+ expect(wrapper.findComponent({ ref: 'tooltip' }).attributes('title')).toBe(
subscribeDisabledDescription,
);
});
diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js
index 5f696b237e0..8e6597bf80f 100644
--- a/spec/frontend/sidebar/todo_spec.js
+++ b/spec/frontend/sidebar/todo_spec.js
@@ -43,8 +43,8 @@ describe('SidebarTodo', () => {
({ isTodo, iconClass, label, icon }) => {
createComponent({ isTodo });
- expect(wrapper.find(GlIcon).classes().join(' ')).toStrictEqual(iconClass);
- expect(wrapper.find(GlIcon).props('name')).toStrictEqual(icon);
+ expect(wrapper.findComponent(GlIcon).classes().join(' ')).toStrictEqual(iconClass);
+ expect(wrapper.findComponent(GlIcon).props('name')).toStrictEqual(icon);
expect(wrapper.find('button').text()).toBe(label);
},
);
@@ -76,19 +76,19 @@ describe('SidebarTodo', () => {
it('renders button icon when `collapsed` prop is `true`', () => {
createComponent({ collapsed: true });
- expect(wrapper.find(GlIcon).props('name')).toBe('todo-done');
+ expect(wrapper.findComponent(GlIcon).props('name')).toBe('todo-done');
});
it('renders loading icon when `isActionActive` prop is true', () => {
createComponent({ isActionActive: true });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('hides button icon when `isActionActive` prop is true', () => {
createComponent({ collapsed: true, isActionActive: true });
- expect(wrapper.find(GlIcon).isVisible()).toBe(false);
+ expect(wrapper.findComponent(GlIcon).isVisible()).toBe(false);
});
});
});
diff --git a/spec/frontend/smart_interval_spec.js b/spec/frontend/smart_interval_spec.js
index 5dda097ae6a..64928fc4ae9 100644
--- a/spec/frontend/smart_interval_spec.js
+++ b/spec/frontend/smart_interval_spec.js
@@ -109,7 +109,7 @@ describe('SmartInterval', () => {
return waitForPromises().then(() => {
const { intervalId } = interval.state;
- expect(intervalId).toBeTruthy();
+ expect(intervalId).not.toBeUndefined();
});
});
});
@@ -130,7 +130,7 @@ describe('SmartInterval', () => {
jest.runOnlyPendingTimers();
return waitForPromises().then(() => {
- expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.state.intervalId).not.toBeUndefined();
// simulates triggering of visibilitychange event
interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
@@ -148,16 +148,16 @@ describe('SmartInterval', () => {
jest.runOnlyPendingTimers();
return waitForPromises().then(() => {
- expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.state.intervalId).not.toBeUndefined();
expect(
interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL,
- ).toBeTruthy();
+ ).toBe(true);
// simulates triggering of visibilitychange event
interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
- expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.state.intervalId).not.toBeUndefined();
expect(interval.getCurrentInterval()).toBe(HIDDEN_INTERVAL);
});
});
@@ -166,7 +166,7 @@ describe('SmartInterval', () => {
jest.runOnlyPendingTimers();
return waitForPromises().then(() => {
- expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.state.intervalId).not.toBeUndefined();
// simulates triggering of visibilitychange event
interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
@@ -176,7 +176,7 @@ describe('SmartInterval', () => {
// simulates triggering of visibilitychange event
interval.onVisibilityChange({ target: { visibilityState: 'visible' } });
- expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.state.intervalId).not.toBeUndefined();
});
});
@@ -194,7 +194,7 @@ describe('SmartInterval', () => {
it('should execute callback before first interval', () => {
interval = createDefaultSmartInterval({ immediateExecution: true });
- expect(interval.cfg.immediateExecution).toBeFalsy();
+ expect(interval.cfg.immediateExecution).toBe(false);
});
});
});
diff --git a/spec/frontend/snippet/collapsible_input_spec.js b/spec/frontend/snippet/collapsible_input_spec.js
index 56e64d136c2..4a6fd33b9e4 100644
--- a/spec/frontend/snippet/collapsible_input_spec.js
+++ b/spec/frontend/snippet/collapsible_input_spec.js
@@ -9,7 +9,7 @@ describe('~/snippet/collapsible_input', () => {
beforeEach(() => {
setHTMLFixture(`
- <form>
+ <form>
<div class="js-collapsible-input js-title">
<div class="js-collapsed d-none">
<input type="text" />
@@ -72,7 +72,7 @@ describe('~/snippet/collapsible_input', () => {
${'is collapsed'} | ${''} | ${true}
${'stays open if given value'} | ${'Hello world!'} | ${false}
`('when loses focus', ({ desc, value, isCollapsed }) => {
- it(desc, () => {
+ it(`${desc}`, () => {
findExpandedInput(descriptionEl).value = value;
focusIn(fooEl);
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index cf897414ccb..e7dab0ad79d 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -9,7 +9,7 @@ import { stubPerformanceWebAPI } from 'helpers/performance';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import * as urlUtils from '~/lib/utils/url_utility';
import SnippetEditApp from '~/snippets/components/edit.vue';
import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
@@ -206,7 +206,7 @@ describe('Snippet Edit app', () => {
});
it('should hide loader', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
});
@@ -237,7 +237,7 @@ describe('Snippet Edit app', () => {
!titleHasErrors,
);
- expect(wrapper.find(SnippetBlobActionsEdit).props('isValid')).toEqual(
+ expect(wrapper.findComponent(SnippetBlobActionsEdit).props('isValid')).toEqual(
!blobActionsHasErrors,
);
},
@@ -273,7 +273,7 @@ describe('Snippet Edit app', () => {
selectedLevel: visibility,
});
- expect(wrapper.find(SnippetVisibilityEdit).props('value')).toBe(visibility);
+ expect(wrapper.findComponent(SnippetVisibilityEdit).props('value')).toBe(visibility);
});
describe('form submission handling', () => {
@@ -361,7 +361,7 @@ describe('Snippet Edit app', () => {
await waitForPromises();
expect(urlUtils.redirectTo).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Can't create snippet: ${TEST_MUTATION_ERROR}`,
});
});
@@ -385,7 +385,7 @@ describe('Snippet Edit app', () => {
});
expect(urlUtils.redirectTo).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Can't update snippet: ${TEST_MUTATION_ERROR}`,
});
},
@@ -407,7 +407,7 @@ describe('Snippet Edit app', () => {
it('should flash', () => {
// Apollo automatically wraps the resolver's error in a NetworkError
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: `Can't update snippet: ${TEST_API_ERROR.message}`,
});
});
diff --git a/spec/frontend/snippets/components/embed_dropdown_spec.js b/spec/frontend/snippets/components/embed_dropdown_spec.js
index 389b1c618a3..ed5ea6cab8a 100644
--- a/spec/frontend/snippets/components/embed_dropdown_spec.js
+++ b/spec/frontend/snippets/components/embed_dropdown_spec.js
@@ -36,7 +36,7 @@ describe('snippets/components/embed_dropdown', () => {
sections.push(current);
} else {
- const value = x.find(GlFormInputGroup).props('value');
+ const value = x.findComponent(GlFormInputGroup).props('value');
const copyValue = x.find('button[title="Copy"]').attributes('data-clipboard-text');
Object.assign(current, {
diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
index 7ea27864519..33b8e2be969 100644
--- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
@@ -4,7 +4,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
@@ -46,9 +46,9 @@ describe('Snippet Blob Edit component', () => {
});
};
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findHeader = () => wrapper.find(BlobHeaderEdit);
- const findContent = () => wrapper.find(SourceEditor);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findHeader = () => wrapper.findComponent(BlobHeaderEdit);
+ const findContent = () => wrapper.findComponent(SourceEditor);
const getLastUpdatedArgs = () => {
const event = wrapper.emitted()['blob-updated'];
@@ -125,7 +125,7 @@ describe('Snippet Blob Edit component', () => {
it('should call flash', async () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: "Can't fetch content for the blob: Error: Request failed with status code 500",
});
});
diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js
index aa31377f390..c7ff8c21d80 100644
--- a/spec/frontend/snippets/components/snippet_blob_view_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js
@@ -69,13 +69,13 @@ describe('Blob Embeddable', () => {
describe('rendering', () => {
it('renders correct components', () => {
createComponent();
- expect(wrapper.find(BlobHeader).exists()).toBe(true);
- expect(wrapper.find(BlobContent).exists()).toBe(true);
+ expect(wrapper.findComponent(BlobHeader).exists()).toBe(true);
+ expect(wrapper.findComponent(BlobContent).exists()).toBe(true);
});
it('sets simple viewer correctly', () => {
createComponent();
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
});
it('sets rich viewer correctly', () => {
@@ -83,20 +83,20 @@ describe('Blob Embeddable', () => {
createComponent({
data,
});
- expect(wrapper.find(RichViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
});
it('correctly switches viewer type', async () => {
createComponent();
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
wrapper.vm.switchViewer(RichViewerMock.type);
await nextTick();
- expect(wrapper.find(RichViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
await wrapper.vm.switchViewer(SimpleViewerMock.type);
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
});
it('passes information about render error down to blob header', () => {
@@ -110,7 +110,7 @@ describe('Blob Embeddable', () => {
},
});
- expect(wrapper.find(BlobHeader).props('hasRenderError')).toBe(true);
+ expect(wrapper.findComponent(BlobHeader).props('hasRenderError')).toBe(true);
});
describe('bob content in multi-file scenario', () => {
@@ -161,7 +161,7 @@ describe('Blob Embeddable', () => {
await nextTick();
- const findContent = () => wrapper.find(BlobContent);
+ const findContent = () => wrapper.findComponent(BlobContent);
expect(findContent().props('content')).toBe(expectedContent);
},
@@ -169,36 +169,69 @@ describe('Blob Embeddable', () => {
});
describe('URLS with hash', () => {
- beforeEach(() => {
- window.location.hash = '#LC2';
- });
-
afterEach(() => {
window.location.hash = '';
});
- it('renders simple viewer by default if URL contains hash', () => {
- createComponent({
- data: {},
+ describe('if hash starts with #LC', () => {
+ beforeEach(() => {
+ window.location.hash = '#LC2';
+ });
+
+ it('renders simple viewer by default', () => {
+ createComponent({
+ data: {},
+ });
+
+ expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
});
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
+ describe('switchViewer()', () => {
+ it('switches to the passed viewer', async () => {
+ createComponent();
+
+ wrapper.vm.switchViewer(RichViewerMock.type);
+
+ await nextTick();
+ expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+
+ await wrapper.vm.switchViewer(SimpleViewerMock.type);
+ expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ });
+ });
});
- describe('switchViewer()', () => {
- it('switches to the passed viewer', async () => {
- createComponent();
+ describe('if hash starts with anything else', () => {
+ beforeEach(() => {
+ window.location.hash = '#last-headline';
+ });
- wrapper.vm.switchViewer(RichViewerMock.type);
+ it('renders rich viewer by default', () => {
+ createComponent({
+ data: {},
+ });
- await nextTick();
expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
- expect(wrapper.find(RichViewer).exists()).toBe(true);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ });
- await wrapper.vm.switchViewer(SimpleViewerMock.type);
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.find(SimpleViewer).exists()).toBe(true);
+ describe('switchViewer()', () => {
+ it('switches to the passed viewer', async () => {
+ createComponent();
+
+ wrapper.vm.switchViewer(SimpleViewerMock.type);
+
+ await nextTick();
+ expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+
+ await wrapper.vm.switchViewer(RichViewerMock.type);
+ expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ });
});
});
});
@@ -206,7 +239,7 @@ describe('Blob Embeddable', () => {
describe('functionality', () => {
describe('render error', () => {
- const findContentEl = () => wrapper.find(BlobContent);
+ const findContentEl = () => wrapper.findComponent(BlobContent);
it('correctly sets blob on the blob-content-error component', () => {
createComponent();
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index b750225a383..c930c9f635b 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -10,7 +10,7 @@ import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
import SnippetHeader, { i18n } from '~/snippets/components/snippet_header.vue';
import DeleteSnippetMutation from '~/snippets/mutations/delete_snippet.mutation.graphql';
import axios from '~/lib/utils/axios_utils';
-import createFlash, { FLASH_TYPES } from '~/flash';
+import { createAlert, VARIANT_DANGER, VARIANT_SUCCESS } from '~/flash';
jest.mock('~/flash');
@@ -267,9 +267,9 @@ describe('Snippet header component', () => {
});
it.each`
- request | variant | text
- ${200} | ${'SUCCESS'} | ${i18n.snippetSpamSuccess}
- ${500} | ${'DANGER'} | ${i18n.snippetSpamFailure}
+ request | variant | text
+ ${200} | ${VARIANT_SUCCESS} | ${i18n.snippetSpamSuccess}
+ ${500} | ${VARIANT_DANGER} | ${i18n.snippetSpamFailure}
`(
'renders a "$variant" flash message with "$text" message for a request with a "$request" response',
async ({ request, variant, text }) => {
@@ -278,9 +278,9 @@ describe('Snippet header component', () => {
submitAsSpamBtn.trigger('click');
await waitForPromises();
- expect(createFlash).toHaveBeenLastCalledWith({
+ expect(createAlert).toHaveBeenLastCalledWith({
message: expect.stringContaining(text),
- type: FLASH_TYPES[variant],
+ variant,
});
},
);
@@ -311,7 +311,7 @@ describe('Snippet header component', () => {
it('renders modal for deletion of a snippet', () => {
createComponent();
- expect(wrapper.find(GlModal).exists()).toBe(true);
+ expect(wrapper.findComponent(GlModal).exists()).toBe(true);
});
it.each`
diff --git a/spec/frontend/snippets/components/snippet_title_spec.js b/spec/frontend/snippets/components/snippet_title_spec.js
index 48fb51ce703..7c40735d64e 100644
--- a/spec/frontend/snippets/components/snippet_title_spec.js
+++ b/spec/frontend/snippets/components/snippet_title_spec.js
@@ -39,12 +39,12 @@ describe('Snippet header component', () => {
createComponent();
expect(wrapper.text().trim()).toContain(title);
- expect(wrapper.find(SnippetDescription).props('description')).toBe(descriptionHtml);
+ expect(wrapper.findComponent(SnippetDescription).props('description')).toBe(descriptionHtml);
});
it('does not render recent changes time stamp if there were no updates', () => {
createComponent();
- expect(wrapper.find(GlSprintf).exists()).toBe(false);
+ expect(wrapper.findComponent(GlSprintf).exists()).toBe(false);
});
it('does not render recent changes time stamp if the time for creation and updates match', () => {
@@ -57,7 +57,7 @@ describe('Snippet header component', () => {
});
createComponent({ props });
- expect(wrapper.find(GlSprintf).exists()).toBe(false);
+ expect(wrapper.findComponent(GlSprintf).exists()).toBe(false);
});
it('renders translated string with most recent changes timestamp if changes were made', () => {
@@ -70,6 +70,6 @@ describe('Snippet header component', () => {
});
createComponent({ props });
- expect(wrapper.find(GlSprintf).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSprintf).exists()).toBe(true);
});
});
diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
index 2d043a5caba..29eb002ef4a 100644
--- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
@@ -39,13 +39,13 @@ describe('Snippet Visibility Edit component', () => {
});
}
- const findLink = () => wrapper.find('label').find(GlLink);
- const findRadios = () => wrapper.find(GlFormRadioGroup).findAllComponents(GlFormRadio);
+ const findLink = () => wrapper.find('label').findComponent(GlLink);
+ const findRadios = () => wrapper.findComponent(GlFormRadioGroup).findAllComponents(GlFormRadio);
const findRadiosData = () =>
findRadios().wrappers.map((x) => {
return {
value: x.find('input').attributes('value'),
- icon: x.find(GlIcon).props('name'),
+ icon: x.findComponent(GlIcon).props('name'),
description: x.find('.help-text').text(),
text: x.find('.js-visibility-option').text(),
};
@@ -147,7 +147,7 @@ describe('Snippet Visibility Edit component', () => {
createComponent({ propsData: { value } });
- expect(wrapper.find(GlFormRadioGroup).attributes('checked')).toBe(value);
+ expect(wrapper.findComponent(GlFormRadioGroup).attributes('checked')).toBe(value);
});
});
});
diff --git a/spec/frontend/terms/components/app_spec.js b/spec/frontend/terms/components/app_spec.js
index ee78b35843a..f1dbc004da8 100644
--- a/spec/frontend/terms/components/app_spec.js
+++ b/spec/frontend/terms/components/app_spec.js
@@ -74,7 +74,7 @@ describe('TermsApp', () => {
expect(findButton(defaultProvide.paths.accept).attributes('disabled')).toBe('disabled');
- wrapper.find(GlIntersectionObserver).vm.$emit('appear');
+ wrapper.findComponent(GlIntersectionObserver).vm.$emit('appear');
await nextTick();
diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js
index 12a44452717..0b3b169891b 100644
--- a/spec/frontend/terraform/components/states_table_spec.js
+++ b/spec/frontend/terraform/components/states_table_spec.js
@@ -160,8 +160,8 @@ describe('StatesTable', () => {
const state = states.at(lineNumber);
expect(state.text()).toContain(name);
- expect(state.find(GlBadge).exists()).toBe(hasBadge);
- expect(state.find(GlLoadingIcon).exists()).toBe(loading);
+ expect(state.findComponent(GlBadge).exists()).toBe(hasBadge);
+ expect(state.findComponent(GlLoadingIcon).exists()).toBe(loading);
if (hasBadge) {
const badge = wrapper.findByTestId(`state-badge-${name}`);
@@ -198,7 +198,7 @@ describe('StatesTable', () => {
const states = wrapper.findAll('[data-testid="terraform-states-table-pipeline"]');
const state = states.at(lineNumber);
- expect(state.find(GlTooltip).exists()).toBe(toolTipAdded);
+ expect(state.findComponent(GlTooltip).exists()).toBe(toolTipAdded);
expect(state.text()).toMatchInterpolatedText(pipelineText);
},
);
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
index cfd82768098..580951e799a 100644
--- a/spec/frontend/terraform/components/terraform_list_spec.js
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -57,11 +57,11 @@ describe('TerraformList', () => {
});
};
- const findBadge = () => wrapper.find(GlBadge);
- const findEmptyState = () => wrapper.find(EmptyState);
- const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
- const findStatesTable = () => wrapper.find(StatesTable);
- const findTab = () => wrapper.find(GlTab);
+ const findBadge = () => wrapper.findComponent(GlBadge);
+ const findEmptyState = () => wrapper.findComponent(EmptyState);
+ const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
+ const findStatesTable = () => wrapper.findComponent(StatesTable);
+ const findTab = () => wrapper.findComponent(GlTab);
afterEach(() => {
wrapper.destroy();
@@ -182,7 +182,7 @@ describe('TerraformList', () => {
});
it('displays an alert message', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
});
});
@@ -195,7 +195,7 @@ describe('TerraformList', () => {
});
it('displays a loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/toggles/index_spec.js b/spec/frontend/toggles/index_spec.js
index 19c4d6f1f1d..f8c43e0ad0c 100644
--- a/spec/frontend/toggles/index_spec.js
+++ b/spec/frontend/toggles/index_spec.js
@@ -83,12 +83,12 @@ describe('toggles/index.js', () => {
expect(listener).toHaveBeenCalledTimes(0);
- wrapper.find(GlToggle).vm.$emit(event, true);
+ wrapper.findComponent(GlToggle).vm.$emit(event, true);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenLastCalledWith(true);
- wrapper.find(GlToggle).vm.$emit(event, false);
+ wrapper.findComponent(GlToggle).vm.$emit(event, false);
expect(listener).toHaveBeenCalledTimes(2);
expect(listener).toHaveBeenLastCalledWith(false);
diff --git a/spec/frontend/token_access/token_access_spec.js b/spec/frontend/token_access/token_access_spec.js
index 024e7dfff8c..c55ac32b6a6 100644
--- a/spec/frontend/token_access/token_access_spec.js
+++ b/spec/frontend/token_access/token_access_spec.js
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import TokenAccess from '~/token_access/components/token_access.vue';
import addProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/add_project_ci_job_token_scope.mutation.graphql';
import removeProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/remove_project_ci_job_token_scope.mutation.graphql';
@@ -40,7 +40,7 @@ describe('TokenAccess component', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAddProjectBtn = () => wrapper.findByRole('button', { name: 'Add project' });
const findRemoveProjectBtn = () => wrapper.findByRole('button', { name: 'Remove access' });
- const findTokenSection = () => wrapper.find('[data-testid="token-section"]');
+ const findTokenDisabledAlert = () => wrapper.findByTestId('token-disabled-alert');
const createMockApolloProvider = (requestHandlers) => {
return createMockApollo(requestHandlers);
@@ -80,7 +80,7 @@ describe('TokenAccess component', () => {
});
describe('toggle', () => {
- it('the toggle should be enabled and the token section should show', async () => {
+ it('the toggle is on and the alert is hidden', async () => {
createComponent([
[getCIJobTokenScopeQuery, enabledJobTokenScopeHandler],
[getProjectsWithCIJobTokenScopeQuery, getProjectsWithScope],
@@ -89,10 +89,10 @@ describe('TokenAccess component', () => {
await waitForPromises();
expect(findToggle().props('value')).toBe(true);
- expect(findTokenSection().exists()).toBe(true);
+ expect(findTokenDisabledAlert().exists()).toBe(false);
});
- it('the toggle should be disabled and the token section should show', async () => {
+ it('the toggle is off and the alert is visible', async () => {
createComponent([
[getCIJobTokenScopeQuery, disabledJobTokenScopeHandler],
[getProjectsWithCIJobTokenScopeQuery, getProjectsWithScope],
@@ -101,7 +101,7 @@ describe('TokenAccess component', () => {
await waitForPromises();
expect(findToggle().props('value')).toBe(false);
- expect(findTokenSection().exists()).toBe(true);
+ expect(findTokenDisabledAlert().exists()).toBe(true);
});
});
@@ -144,7 +144,7 @@ describe('TokenAccess component', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -187,7 +187,7 @@ describe('TokenAccess component', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index 998bb2a9ea2..d5a63a99601 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -49,7 +49,7 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).props('target')).toBe(target);
+ expect(wrapper.findComponent(GlTooltip).props('target')).toBe(target);
});
it('does not attach a tooltip to a target with empty title', async () => {
@@ -59,7 +59,7 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).exists()).toBe(false);
+ expect(wrapper.findComponent(GlTooltip).exists()).toBe(false);
});
it('does not attach a tooltip twice to the same element', async () => {
@@ -76,7 +76,7 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).text()).toBe(target.getAttribute('title'));
+ expect(wrapper.findComponent(GlTooltip).text()).toBe(target.getAttribute('title'));
});
it('supports HTML content', async () => {
@@ -88,7 +88,7 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title'));
+ expect(wrapper.findComponent(GlTooltip).html()).toContain(target.getAttribute('title'));
});
it('sets the configuration values passed in the config object', async () => {
@@ -96,7 +96,7 @@ describe('tooltips/components/tooltips.vue', () => {
target = createTooltipTarget();
wrapper.vm.addTooltips([target], config);
await nextTick();
- expect(wrapper.find(GlTooltip).props()).toMatchObject(config);
+ expect(wrapper.findComponent(GlTooltip).props()).toMatchObject(config);
});
it.each`
@@ -113,7 +113,7 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).props(prop)).toBe(value);
+ expect(wrapper.findComponent(GlTooltip).props(prop)).toBe(value);
},
);
});
@@ -180,7 +180,7 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.vm.triggerEvent(target, event);
- expect(wrapper.find(GlTooltip).emitted(event)).toHaveLength(1);
+ expect(wrapper.findComponent(GlTooltip).emitted(event)).toHaveLength(1);
});
});
@@ -198,14 +198,14 @@ describe('tooltips/components/tooltips.vue', () => {
await nextTick();
- expect(wrapper.find(GlTooltip).text()).toBe(currentTitle);
+ expect(wrapper.findComponent(GlTooltip).text()).toBe(currentTitle);
target.setAttribute('title', newTitle);
wrapper.vm.fixTitle(target);
await nextTick();
- expect(wrapper.find(GlTooltip).text()).toBe(newTitle);
+ expect(wrapper.findComponent(GlTooltip).text()).toBe(newTitle);
});
});
diff --git a/spec/frontend/user_lists/components/edit_user_list_spec.js b/spec/frontend/user_lists/components/edit_user_list_spec.js
index 941c8244247..5f067d9de3c 100644
--- a/spec/frontend/user_lists/components/edit_user_list_spec.js
+++ b/spec/frontend/user_lists/components/edit_user_list_spec.js
@@ -47,7 +47,7 @@ describe('user_lists/components/edit_user_list', () => {
});
it('should show a loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -60,7 +60,7 @@ describe('user_lists/components/edit_user_list', () => {
factory();
await waitForPromises();
- alert = wrapper.find(GlAlert);
+ alert = wrapper.findComponent(GlAlert);
});
it('should show a flash with the error respopnse', () => {
@@ -72,7 +72,7 @@ describe('user_lists/components/edit_user_list', () => {
});
it('should not show a user list form', () => {
- expect(wrapper.find(UserListForm).exists()).toBe(false);
+ expect(wrapper.findComponent(UserListForm).exists()).toBe(false);
});
});
@@ -129,7 +129,7 @@ describe('user_lists/components/edit_user_list', () => {
clickSave();
await waitForPromises();
- alert = wrapper.find(GlAlert);
+ alert = wrapper.findComponent(GlAlert);
});
it('should show a flash with the error respopnse', () => {
diff --git a/spec/frontend/user_lists/components/new_user_list_spec.js b/spec/frontend/user_lists/components/new_user_list_spec.js
index ace4a284347..8683cf2463c 100644
--- a/spec/frontend/user_lists/components/new_user_list_spec.js
+++ b/spec/frontend/user_lists/components/new_user_list_spec.js
@@ -72,7 +72,7 @@ describe('user_lists/components/new_user_list', () => {
await waitForPromises();
- alert = wrapper.find(GlAlert);
+ alert = wrapper.findComponent(GlAlert);
});
it('should show a flash with the error respopnse', () => {
diff --git a/spec/frontend/user_lists/components/user_list_spec.js b/spec/frontend/user_lists/components/user_list_spec.js
index f126c733dd5..e02862cad2b 100644
--- a/spec/frontend/user_lists/components/user_list_spec.js
+++ b/spec/frontend/user_lists/components/user_list_spec.js
@@ -50,7 +50,7 @@ describe('User List', () => {
});
it('shows a loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -157,7 +157,7 @@ describe('User List', () => {
});
describe('error', () => {
- const findAlert = () => wrapper.find(GlAlert);
+ const findAlert = () => wrapper.findComponent(GlAlert);
beforeEach(async () => {
Api.fetchFeatureFlagUserList.mockRejectedValue();
@@ -190,7 +190,7 @@ describe('User List', () => {
});
it('displays an empty state', () => {
- expect(wrapper.find(GlEmptyState).exists()).toBe(true);
+ expect(wrapper.findComponent(GlEmptyState).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/user_lists/components/user_lists_table_spec.js b/spec/frontend/user_lists/components/user_lists_table_spec.js
index fb5093eb065..3324b040b86 100644
--- a/spec/frontend/user_lists/components/user_lists_table_spec.js
+++ b/spec/frontend/user_lists/components/user_lists_table_spec.js
@@ -59,7 +59,7 @@ describe('User Lists Table', () => {
describe('delete button', () => {
it('should display the confirmation modal', async () => {
- const modal = wrapper.find(GlModal);
+ const modal = wrapper.findComponent(GlModal);
wrapper.find('[data-testid="delete-user-list"]').trigger('click');
@@ -73,7 +73,7 @@ describe('User Lists Table', () => {
let modal;
beforeEach(async () => {
- modal = wrapper.find(GlModal);
+ modal = wrapper.findComponent(GlModal);
wrapper.find('button').trigger('click');
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index 0530569c9df..8ce071c075f 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -188,8 +188,8 @@ describe('User Popovers', () => {
});
it('removes title attribute from user links', () => {
- expect(userLink.getAttribute('title')).toBeFalsy();
- expect(userLink.dataset.originalTitle).toBeFalsy();
+ expect(userLink.getAttribute('title')).toBe('');
+ expect(userLink.dataset.originalTitle).toBe('');
});
it('fetches user info and status from the user cache', () => {
diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
index 05cd1bb5b3d..1f3b6dce620 100644
--- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
@@ -1,7 +1,7 @@
import { nextTick } from 'vue';
import { GlButton, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Approvals from '~/vue_merge_request_widget/components/approvals/approvals.vue';
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue';
@@ -49,7 +49,7 @@ describe('MRWidget approvals', () => {
});
};
- const findAction = () => wrapper.find(GlButton);
+ const findAction = () => wrapper.findComponent(GlButton);
const findActionData = () => {
const action = findAction();
@@ -61,8 +61,8 @@ describe('MRWidget approvals', () => {
text: action.text(),
};
};
- const findSummary = () => wrapper.find(ApprovalsSummary);
- const findOptionalSummary = () => wrapper.find(ApprovalsSummaryOptional);
+ const findSummary = () => wrapper.findComponent(ApprovalsSummary);
+ const findOptionalSummary = () => wrapper.findComponent(ApprovalsSummaryOptional);
const findInvalidRules = () => wrapper.find('[data-testid="invalid-rules"]');
beforeEach(() => {
@@ -129,7 +129,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: FETCH_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: FETCH_ERROR });
});
});
@@ -268,7 +268,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: APPROVE_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: APPROVE_ERROR });
});
});
});
@@ -319,7 +319,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error message', () => {
- expect(createFlash).toHaveBeenCalledWith({ message: UNAPPROVE_ERROR });
+ expect(createAlert).toHaveBeenCalledWith({ message: UNAPPROVE_ERROR });
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js
index 65cafc647e0..e6fb0495947 100644
--- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js
@@ -18,7 +18,7 @@ describe('MRWidget approvals summary optional', () => {
wrapper = null;
});
- const findHelpLink = () => wrapper.find(GlLink);
+ const findHelpLink = () => wrapper.findComponent(GlLink);
describe('when can approve', () => {
beforeEach(() => {
diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js
index c2606346292..f4234083346 100644
--- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js
@@ -29,7 +29,7 @@ describe('MRWidget approvals summary', () => {
});
};
- const findAvatars = () => wrapper.find(UserAvatarList);
+ const findAvatars = () => wrapper.findComponent(UserAvatarList);
afterEach(() => {
wrapper.destroy();
@@ -136,7 +136,7 @@ describe('MRWidget approvals summary', () => {
});
it('does not render avatar list', () => {
- expect(wrapper.find(UserAvatarList).exists()).toBe(false);
+ expect(wrapper.findComponent(UserAvatarList).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js
index e2386bc7f2b..73fa4b7b08f 100644
--- a/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js
@@ -60,7 +60,7 @@ describe('Merge Requests Artifacts list app', () => {
});
it('renders a loading icon', () => {
- const loadingIcon = wrapper.find(GlLoadingIcon);
+ const loadingIcon = wrapper.findComponent(GlLoadingIcon);
expect(loadingIcon.exists()).toBe(true);
});
diff --git a/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js
index d519ad2cdb0..b7bf72cd215 100644
--- a/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js
@@ -31,11 +31,11 @@ describe('Artifacts List', () => {
});
it('renders link for the artifact', () => {
- expect(wrapper.find(GlLink).attributes('href')).toEqual(data.artifacts[0].url);
+ expect(wrapper.findComponent(GlLink).attributes('href')).toEqual(data.artifacts[0].url);
});
it('renders artifact name', () => {
- expect(wrapper.find(GlLink).text()).toEqual(data.artifacts[0].text);
+ expect(wrapper.findComponent(GlLink).text()).toEqual(data.artifacts[0].text);
});
it('renders job url', () => {
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js
index 01fbcb2154f..c253dc63f23 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js
@@ -23,7 +23,7 @@ describe('Merge Request Collapsible Extension', () => {
const findTitle = () => wrapper.find('[data-testid="mr-collapsible-title"]');
const findErrorMessage = () => wrapper.find('.js-error-state');
- const findIcon = () => wrapper.find(GlIcon);
+ const findIcon = () => wrapper.findComponent(GlIcon);
afterEach(() => {
wrapper.destroy();
@@ -77,7 +77,7 @@ describe('Merge Request Collapsible Extension', () => {
});
it('renders loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).isVisible()).toBe(true);
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js
index 8fd93809e01..90a29d15488 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js
@@ -32,7 +32,9 @@ describe('MrWidgetAuthorTime', () => {
});
it('renders author', () => {
- expect(wrapper.find(MrWidgetAuthor).props('author')).toStrictEqual(defaultProps.author);
+ expect(wrapper.findComponent(MrWidgetAuthor).props('author')).toStrictEqual(
+ defaultProps.author,
+ );
});
it('renders provided time', () => {
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js
index 631aef412a6..8eaed998eb5 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js
@@ -6,8 +6,8 @@ import MrCollapsibleSection from '~/vue_merge_request_widget/components/mr_widge
describe('MrWidgetExpanableSection', () => {
let wrapper;
- const findButton = () => wrapper.find(GlButton);
- const findCollapse = () => wrapper.find(GlCollapse);
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findCollapse = () => wrapper.findComponent(GlCollapse);
beforeEach(() => {
wrapper = shallowMount(MrCollapsibleSection, {
@@ -19,7 +19,7 @@ describe('MrWidgetExpanableSection', () => {
});
it('renders Icon', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
});
it('renders header slot', () => {
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js
index ebd10f31fa7..6a9b019fb4f 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js
@@ -21,6 +21,6 @@ describe('MrWidgetIcon', () => {
it('renders icon and container', () => {
expect(wrapper.element.className).toContain('circle-icon-container');
- expect(wrapper.find(GlIcon).props('name')).toEqual(TEST_ICON);
+ expect(wrapper.findComponent(GlIcon).props('name')).toEqual(TEST_ICON);
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
index efe2bf75c3f..c3f6331e560 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
@@ -41,8 +41,8 @@ describe('MrWidgetPipelineContainer', () => {
});
it('renders pipeline', () => {
- expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
- expect(wrapper.find(MrWidgetPipeline).props()).toMatchObject({
+ expect(wrapper.findComponent(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.findComponent(MrWidgetPipeline).props()).toMatchObject({
pipeline: mockStore.pipeline,
pipelineCoverageDelta: mockStore.pipelineCoverageDelta,
ciStatus: mockStore.ciStatus,
@@ -82,9 +82,9 @@ describe('MrWidgetPipelineContainer', () => {
});
it('renders pipeline', () => {
- expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.findComponent(MrWidgetPipeline).exists()).toBe(true);
expect(findCIErrorMessage().exists()).toBe(false);
- expect(wrapper.find(MrWidgetPipeline).props()).toMatchObject({
+ expect(wrapper.findComponent(MrWidgetPipeline).props()).toMatchObject({
pipeline: mockStore.mergePipeline,
pipelineCoverageDelta: mockStore.pipelineCoverageDelta,
ciStatus: mockStore.mergePipeline.details.status.text,
@@ -102,7 +102,7 @@ describe('MrWidgetPipelineContainer', () => {
targetBranch: 'Foo<script>alert("XSS")</script>',
},
});
- expect(wrapper.find(MrWidgetPipeline).props().sourceBranchLink).toBe('Foo');
+ expect(wrapper.findComponent(MrWidgetPipeline).props().sourceBranchLink).toBe('Foo');
});
it('renders deployments', () => {
@@ -125,7 +125,7 @@ describe('MrWidgetPipelineContainer', () => {
it('renders the artifacts app', () => {
factory();
- expect(wrapper.find(ArtifactsApp).isVisible()).toBe(true);
+ expect(wrapper.findComponent(ArtifactsApp).isVisible()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js
index d6c67dab381..73358edee78 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js
@@ -57,7 +57,7 @@ describe('MRWidgetSuggestPipeline', () => {
});
it('renders widget icon', () => {
- const icon = wrapper.find(MrWidgetIcon);
+ const icon = wrapper.findComponent(MrWidgetIcon);
expect(icon.exists()).toBe(true);
expect(icon.props()).toEqual(
@@ -115,7 +115,7 @@ describe('MRWidgetSuggestPipeline', () => {
});
describe('dismissible', () => {
- const findDismissContainer = () => wrapper.find(dismissibleContainer);
+ const findDismissContainer = () => wrapper.findComponent(dismissibleContainer);
beforeEach(() => {
wrapper = shallowMount(suggestPipelineComponent, { propsData: suggestProps });
diff --git a/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
index 635ef0f6b0d..5f383c468d8 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -72,11 +72,14 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
<div
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
>
- <div>
+ <div
+ class="gl-display-flex gl-align-items-flex-start"
+ >
<div
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
lazy=""
no-caret=""
+ title="Options"
>
<!---->
<button
@@ -246,11 +249,14 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
<div
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
>
- <div>
+ <div
+ class="gl-display-flex gl-align-items-flex-start"
+ >
<div
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
lazy=""
no-caret=""
+ title="Options"
>
<!---->
<button
diff --git a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
index 1900b53ac11..d85574262fe 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
@@ -15,9 +15,9 @@ describe('Merge request widget merge checks failed state component', () => {
});
it.each`
- mrState | displayText
- ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'}
- ${{ blockingMergeRequests: { total_count: 1 } }} | ${'blockingMergeRequests'}
+ mrState | displayText
+ ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'}
+ ${{ detailedMergeStatus: 'BLOCKED_STATUS' }} | ${'blockingMergeRequests'}
`('display $displayText text for $mrState', ({ mrState, displayText }) => {
factory({ mr: mrState });
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js
index 9320e733636..398a3912882 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js
@@ -7,7 +7,7 @@ import eventHub from '~/vue_merge_request_widget/event_hub';
describe('MRWidgetAutoMergeFailed', () => {
let wrapper;
const mergeError = 'This is the merge error';
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
const createComponent = (props = {}, mergeRequestWidgetGraphql = false) => {
wrapper = mount(AutoMergeFailedComponent, {
@@ -61,7 +61,7 @@ describe('MRWidgetAutoMergeFailed', () => {
await nextTick();
expect(findButton().attributes('disabled')).toBe('disabled');
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js
index 2606933450e..a3aa563b516 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js
@@ -1,180 +1,172 @@
import { getByRole } from '@testing-library/dom';
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
import modalEventHub from '~/projects/commit/event_hub';
-import mergedComponent from '~/vue_merge_request_widget/components/states/mr_widget_merged.vue';
+import MergedComponent from '~/vue_merge_request_widget/components/states/mr_widget_merged.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
describe('MRWidgetMerged', () => {
- let vm;
+ let wrapper;
const targetBranch = 'foo';
-
- beforeEach(() => {
- jest.spyOn(document, 'dispatchEvent');
- const Component = Vue.extend(mergedComponent);
- const mr = {
- isRemovingSourceBranch: false,
- cherryPickInForkPath: false,
- canCherryPickInCurrentMR: true,
- revertInForkPath: false,
- canRevertInCurrentMR: true,
- canRemoveSourceBranch: true,
- sourceBranchRemoved: true,
- metrics: {
- mergedBy: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'http://localhost:3000/root',
- avatarUrl:
- 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ const mr = {
+ isRemovingSourceBranch: false,
+ cherryPickInForkPath: false,
+ canCherryPickInCurrentMR: true,
+ revertInForkPath: false,
+ canRevertInCurrentMR: true,
+ canRemoveSourceBranch: true,
+ sourceBranchRemoved: true,
+ metrics: {
+ mergedBy: {
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://localhost:3000/root',
+ avatarUrl:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ },
+ mergedAt: 'Jan 24, 2018 1:02pm UTC',
+ readableMergedAt: '',
+ closedBy: {},
+ closedAt: 'Jan 24, 2018 1:02pm UTC',
+ readableClosedAt: '',
+ },
+ updatedAt: 'mergedUpdatedAt',
+ shortMergeCommitSha: '958c0475',
+ mergeCommitSha: '958c047516e182dfc52317f721f696e8a1ee85ed',
+ mergeCommitPath:
+ 'http://localhost:3000/root/nautilus/commit/f7ce827c314c9340b075657fd61c789fb01cf74d',
+ sourceBranch: 'bar',
+ targetBranch,
+ };
+
+ const service = {
+ removeSourceBranch: () => nextTick(),
+ };
+
+ const createComponent = (customMrFields = {}) => {
+ wrapper = mount(MergedComponent, {
+ propsData: {
+ mr: {
+ ...mr,
+ ...customMrFields,
},
- mergedAt: 'Jan 24, 2018 1:02pm UTC',
- readableMergedAt: '',
- closedBy: {},
- closedAt: 'Jan 24, 2018 1:02pm UTC',
- readableClosedAt: '',
+ service,
},
- updatedAt: 'mergedUpdatedAt',
- shortMergeCommitSha: '958c0475',
- mergeCommitSha: '958c047516e182dfc52317f721f696e8a1ee85ed',
- mergeCommitPath:
- 'http://localhost:3000/root/nautilus/commit/f7ce827c314c9340b075657fd61c789fb01cf74d',
- sourceBranch: 'bar',
- targetBranch,
- };
-
- const service = {
- removeSourceBranch() {},
- };
+ });
+ };
+ beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- vm = mountComponent(Component, { mr, service });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- describe('computed', () => {
- describe('shouldShowRemoveSourceBranch', () => {
- it('returns true when sourceBranchRemoved is false', () => {
- vm.mr.sourceBranchRemoved = false;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(true);
- });
-
- it('returns false when sourceBranchRemoved is true', () => {
- vm.mr.sourceBranchRemoved = true;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
- });
-
- it('returns false when canRemoveSourceBranch is false', () => {
- vm.mr.sourceBranchRemoved = false;
- vm.mr.canRemoveSourceBranch = false;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
- });
-
- it('returns false when is making request', () => {
- vm.mr.canRemoveSourceBranch = true;
- vm.isMakingRequest = true;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
- });
+ const findButtonByText = (text) =>
+ wrapper.findAll('button').wrappers.find((w) => w.text() === text);
+ const findRemoveSourceBranchButton = () => findButtonByText('Delete source branch');
- it('returns true when all are true', () => {
- vm.mr.isRemovingSourceBranch = true;
- vm.mr.canRemoveSourceBranch = true;
- vm.isMakingRequest = true;
+ describe('remove source branch button', () => {
+ it('is displayed when sourceBranchRemoved is false', () => {
+ createComponent({ sourceBranchRemoved: false });
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
- });
+ expect(findRemoveSourceBranchButton().exists()).toBe(true);
});
- describe('shouldShowSourceBranchRemoving', () => {
- it('should correct value when fields changed', () => {
- vm.mr.sourceBranchRemoved = false;
+ it('is not displayed when sourceBranchRemoved is true', () => {
+ createComponent({ sourceBranchRemoved: true });
- expect(vm.shouldShowSourceBranchRemoving).toEqual(false);
+ expect(findRemoveSourceBranchButton()).toBe(undefined);
+ });
- vm.mr.sourceBranchRemoved = true;
+ it('is not displayed when canRemoveSourceBranch is true', () => {
+ createComponent({ sourceBranchRemoved: false, canRemoveSourceBranch: false });
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
+ expect(findRemoveSourceBranchButton()).toBe(undefined);
+ });
- vm.mr.sourceBranchRemoved = false;
- vm.isMakingRequest = true;
+ it('is not displayed when is making request', async () => {
+ createComponent({ sourceBranchRemoved: false, canRemoveSourceBranch: true });
- expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
+ await findRemoveSourceBranchButton().trigger('click');
- vm.isMakingRequest = false;
- vm.mr.isRemovingSourceBranch = true;
+ expect(findRemoveSourceBranchButton()).toBe(undefined);
+ });
- expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
+ it('is not displayed when all are true', () => {
+ createComponent({
+ isRemovingSourceBranch: true,
+ sourceBranchRemoved: false,
+ canRemoveSourceBranch: true,
});
+
+ expect(findRemoveSourceBranchButton()).toBe(undefined);
});
});
- describe('methods', () => {
- describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', async () => {
- jest.spyOn(vm.service, 'removeSourceBranch').mockReturnValue(
- new Promise((resolve) => {
- resolve({
- data: {
- message: 'Branch was deleted',
- },
- });
- }),
- );
+ it('should set flag and call service then request main component to update the widget when branch is removed', async () => {
+ createComponent({ sourceBranchRemoved: false });
+ jest.spyOn(service, 'removeSourceBranch').mockResolvedValue({
+ data: {
+ message: 'Branch was deleted',
+ },
+ });
- vm.removeSourceBranch();
+ await findRemoveSourceBranchButton().trigger('click');
- await waitForPromises();
+ await waitForPromises();
- const args = eventHub.$emit.mock.calls[0];
+ const args = eventHub.$emit.mock.calls[0];
- expect(vm.isMakingRequest).toEqual(true);
- expect(args[0]).toEqual('MRWidgetUpdateRequested');
- expect(args[1]).not.toThrow();
- });
- });
+ expect(args[0]).toEqual('MRWidgetUpdateRequested');
+ expect(args[1]).not.toThrow();
});
it('calls dispatchDocumentEvent to load in the modal component', () => {
+ createComponent();
+
expect(document.dispatchEvent).toHaveBeenCalledWith(new CustomEvent('merged:UpdateActions'));
});
it('emits event to open the revert modal on revert button click', () => {
+ createComponent();
const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
- getByRole(vm.$el, 'button', { name: /Revert/i }).click();
+ getByRole(wrapper.element, 'button', { name: /Revert/i }).click();
expect(eventHubSpy).toHaveBeenCalledWith(OPEN_REVERT_MODAL);
});
it('emits event to open the cherry-pick modal on cherry-pick button click', () => {
+ createComponent();
const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
- getByRole(vm.$el, 'button', { name: /Cherry-pick/i }).click();
+ getByRole(wrapper.element, 'button', { name: /Cherry-pick/i }).click();
expect(eventHubSpy).toHaveBeenCalledWith(OPEN_CHERRY_PICK_MODAL);
});
it('has merged by information', () => {
- expect(vm.$el.textContent).toContain('Merged by');
- expect(vm.$el.textContent).toContain('Administrator');
+ createComponent();
+
+ expect(wrapper.text()).toContain('Merged by');
+ expect(wrapper.text()).toContain('Administrator');
});
it('shows revert and cherry-pick buttons', () => {
- expect(vm.$el.textContent).toContain('Revert');
- expect(vm.$el.textContent).toContain('Cherry-pick');
+ createComponent();
+
+ expect(wrapper.text()).toContain('Revert');
+ expect(wrapper.text()).toContain('Cherry-pick');
});
it('should use mergedEvent mergedAt as tooltip title', () => {
- expect(vm.$el.querySelector('time').getAttribute('title')).toBe('Jan 24, 2018 1:02pm UTC');
+ createComponent();
+
+ expect(wrapper.find('time').attributes('title')).toBe('Jan 24, 2018 1:02pm UTC');
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js
index d5619d4996d..bd158d59d74 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -6,31 +6,42 @@ import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_i
describe('PipelineFailed', () => {
let wrapper;
- const createComponent = () => {
+ const createComponent = (mr = {}) => {
wrapper = shallowMount(PipelineFailed, {
+ propsData: {
+ mr,
+ },
stubs: {
GlSprintf,
},
});
};
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('should render error status icon', () => {
+ createComponent();
+
expect(wrapper.findComponent(StatusIcon).exists()).toBe(true);
expect(wrapper.findComponent(StatusIcon).props().status).toBe('failed');
});
it('should render error message with a disabled merge button', () => {
+ createComponent();
+
expect(wrapper.text()).toContain('Merge blocked: pipeline must succeed.');
expect(wrapper.text()).toContain('Push a commit that fixes the failure');
expect(wrapper.findComponent(GlLink).text()).toContain('learn about other solutions');
});
+
+ it('should render pipeline blocked message', () => {
+ createComponent({ isPipelineBlocked: true });
+
+ expect(wrapper.text()).toContain(
+ "Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.",
+ );
+ });
});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
index 9a6bf66909e..48d3f15560b 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -105,16 +105,17 @@ const createComponent = (
},
stubs: {
CommitEdit,
+ GlSprintf,
},
apolloProvider: createMockApollo([[readyToMergeQuery, readyToMergeResponseSpy]]),
});
};
-const findCheckboxElement = () => wrapper.find(SquashBeforeMerge);
+const findCheckboxElement = () => wrapper.findComponent(SquashBeforeMerge);
const findCommitEditElements = () => wrapper.findAllComponents(CommitEdit);
-const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
+const findCommitDropdownElement = () => wrapper.findComponent(CommitMessageDropdown);
const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
-const findTipLink = () => wrapper.find(GlSprintf);
+const findTipLink = () => wrapper.findComponent(GlSprintf);
const findCommitEditWithInputId = (inputId) =>
findCommitEditElements().wrappers.find((x) => x.props('inputId') === inputId);
const findMergeCommitMessage = () => findCommitEditWithInputId('merge-message-edit').props('value');
@@ -300,6 +301,48 @@ describe('ReadyToMerge', () => {
expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
});
});
+
+ describe('sourceBranchDeletedText', () => {
+ const should = 'Source branch will be deleted.';
+ const shouldNot = 'Source branch will not be deleted.';
+ const did = 'Deleted the source branch.';
+ const didNot = 'Did not delete the source branch.';
+ const scenarios = [
+ "the MR hasn't merged yet, and the backend-provided value expects to delete the branch",
+ "the MR hasn't merged yet, and the backend-provided value expects to leave the branch",
+ "the MR hasn't merged yet, and the backend-provided value is a non-boolean falsey value",
+ "the MR hasn't merged yet, and the backend-provided value is a non-boolean truthy value",
+ 'the MR has been merged, and the backend reports that the branch has been removed',
+ 'the MR has been merged, and the backend reports that the branch has not been removed',
+ 'the MR has been merged, and the backend reports a non-boolean falsey value',
+ 'the MR has been merged, and the backend reports a non-boolean truthy value',
+ ];
+
+ it.each`
+ describe | premerge | mrShould | mrRemoved | output
+ ${scenarios[0]} | ${true} | ${true} | ${null} | ${should}
+ ${scenarios[1]} | ${true} | ${false} | ${null} | ${shouldNot}
+ ${scenarios[2]} | ${true} | ${null} | ${null} | ${shouldNot}
+ ${scenarios[3]} | ${true} | ${'yeah'} | ${null} | ${should}
+ ${scenarios[4]} | ${false} | ${null} | ${true} | ${did}
+ ${scenarios[5]} | ${false} | ${null} | ${false} | ${didNot}
+ ${scenarios[6]} | ${false} | ${null} | ${null} | ${didNot}
+ ${scenarios[7]} | ${false} | ${null} | ${'yep'} | ${did}
+ `(
+ 'in the case that $describe, returns "$output"',
+ ({ premerge, mrShould, mrRemoved, output }) => {
+ createComponent({
+ mr: {
+ state: !premerge ? 'merged' : 'literally-anything-else',
+ shouldRemoveSourceBranch: mrShould,
+ sourceBranchRemoved: mrRemoved,
+ },
+ });
+
+ expect(wrapper.vm.sourceBranchDeletedText).toBe(output);
+ },
+ );
+ });
});
describe('methods', () => {
@@ -733,6 +776,34 @@ describe('ReadyToMerge', () => {
});
});
+ describe('source and target branches diverged', () => {
+ describe('when the MR is showing the Merge button', () => {
+ it('does not display the diverged commits message if the source branch is not behind the target', () => {
+ createComponent({ mr: { divergedCommitsCount: 0 } });
+
+ const textBody = wrapper.text();
+
+ expect(textBody).toEqual(
+ expect.not.stringContaining('The source branch is 0 commits behind the target branch'),
+ );
+ expect(textBody).toEqual(
+ expect.not.stringContaining('The source branch is 0 commit behind the target branch'),
+ );
+ expect(textBody).toEqual(
+ expect.not.stringContaining('The source branch is behind the target branch'),
+ );
+ });
+
+ it('shows the diverged commits text when the source branch is behind the target', () => {
+ createComponent({ mr: { divergedCommitsCount: 9001, canMerge: false } });
+
+ expect(wrapper.text()).toEqual(
+ expect.stringContaining('The source branch is 9001 commits behind the target branch'),
+ );
+ });
+ });
+ });
+
describe('Merge button when pipeline has failed', () => {
beforeEach(() => {
createComponent({
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js
index 6ea2e8675d3..c839fa17fe5 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js
@@ -18,7 +18,7 @@ describe('Squash before merge component', () => {
wrapper.destroy();
});
- const findCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
describe('checkbox', () => {
it('is unchecked if passed value prop is false', () => {
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js
index af52901f508..7259f210b6e 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js
@@ -38,7 +38,7 @@ describe('Wip', () => {
it('should have default data', () => {
const vm = createComponent();
- expect(vm.isMakingRequest).toBeFalsy();
+ expect(vm.isMakingRequest).toBe(false);
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
deleted file mode 100644
index 7a868eb8cc9..00000000000
--- a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import MrWidgetExpanableSection from '~/vue_merge_request_widget/components/mr_widget_expandable_section.vue';
-import MrWidgetTerraformContainer from '~/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue';
-import TerraformPlan from '~/vue_merge_request_widget/components/terraform/terraform_plan.vue';
-import { invalidPlanWithName, plans, validPlanWithName } from './mock_data';
-
-describe('MrWidgetTerraformConainer', () => {
- let mock;
- let wrapper;
-
- const propsData = { endpoint: '/path/to/terraform/report.json' };
-
- const findHeader = () => wrapper.find('[data-testid="terraform-header-text"]');
- const findPlans = () =>
- wrapper.findAllComponents(TerraformPlan).wrappers.map((x) => x.props('plan'));
-
- const mockPollingApi = (response, body, header) => {
- mock.onGet(propsData.endpoint).reply(response, body, header);
- };
-
- const mountWrapper = () => {
- wrapper = shallowMount(MrWidgetTerraformContainer, {
- propsData,
- stubs: { MrWidgetExpanableSection, GlSprintf },
- });
- return axios.waitForAll();
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- wrapper.destroy();
- mock.restore();
- });
-
- describe('when data is loading', () => {
- beforeEach(async () => {
- mockPollingApi(200, plans, {});
-
- await mountWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ loading: true });
- await nextTick();
- });
-
- it('diplays loading skeleton', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
- expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(false);
- });
- });
-
- describe('when data has finished loading', () => {
- beforeEach(() => {
- mockPollingApi(200, plans, {});
- return mountWrapper();
- });
-
- it('displays terraform content', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
- expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(true);
- expect(findPlans()).toEqual(Object.values(plans));
- });
-
- describe('when data includes one invalid plan', () => {
- beforeEach(() => {
- const invalidPlanGroup = { bad_plan: invalidPlanWithName };
- mockPollingApi(200, invalidPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for one invalid plan', () => {
- expect(findHeader().text()).toBe('1 Terraform report failed to generate');
- });
- });
-
- describe('when data includes multiple invalid plans', () => {
- beforeEach(() => {
- const invalidPlanGroup = {
- bad_plan_one: invalidPlanWithName,
- bad_plan_two: invalidPlanWithName,
- };
-
- mockPollingApi(200, invalidPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for multiple invalid plans', () => {
- expect(findHeader().text()).toBe('2 Terraform reports failed to generate');
- });
- });
-
- describe('when data includes one valid plan', () => {
- beforeEach(() => {
- const validPlanGroup = { valid_plan: validPlanWithName };
- mockPollingApi(200, validPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for one valid plans', () => {
- expect(findHeader().text()).toBe('1 Terraform report was generated in your pipelines');
- });
- });
-
- describe('when data includes multiple valid plans', () => {
- beforeEach(() => {
- const validPlanGroup = {
- valid_plan_one: validPlanWithName,
- valid_plan_two: validPlanWithName,
- };
- mockPollingApi(200, validPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for multiple valid plans', () => {
- expect(findHeader().text()).toBe('2 Terraform reports were generated in your pipelines');
- });
- });
- });
-
- describe('polling', () => {
- let pollRequest;
- let pollStop;
-
- beforeEach(() => {
- pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
- pollStop = jest.spyOn(Poll.prototype, 'stop');
- });
-
- afterEach(() => {
- pollRequest.mockRestore();
- pollStop.mockRestore();
- });
-
- describe('successful poll', () => {
- beforeEach(() => {
- mockPollingApi(200, plans, {});
-
- return mountWrapper();
- });
-
- it('does not make additional requests after poll is successful', () => {
- expect(pollRequest).toHaveBeenCalledTimes(1);
- expect(pollStop).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('polling fails', () => {
- beforeEach(() => {
- mockPollingApi(500, null, {});
- return mountWrapper();
- });
-
- it('stops loading', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
- });
-
- it('generates one broken plan', () => {
- expect(findPlans()).toEqual([{ tf_report_error: 'api_error' }]);
- });
-
- it('does not make additional requests after poll is unsuccessful', () => {
- expect(pollRequest).toHaveBeenCalledTimes(1);
- expect(pollStop).toHaveBeenCalledTimes(1);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
deleted file mode 100644
index 3c9f6c2e165..00000000000
--- a/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { GlLink, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import TerraformPlan from '~/vue_merge_request_widget/components/terraform/terraform_plan.vue';
-import {
- invalidPlanWithName,
- invalidPlanWithoutName,
- validPlanWithName,
- validPlanWithoutName,
-} from './mock_data';
-
-describe('TerraformPlan', () => {
- let wrapper;
-
- const findIcon = () => wrapper.find('[data-testid="change-type-icon"]');
- const findLogButton = () => wrapper.find('[data-testid="terraform-report-link"]');
-
- const mountWrapper = (propsData) => {
- wrapper = shallowMount(TerraformPlan, { stubs: { GlLink, GlSprintf }, propsData });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('valid plan with job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: validPlanWithName });
- });
-
- it('displays a document icon', () => {
- expect(findIcon().attributes('name')).toBe('doc-changes');
- });
-
- it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(`The job ${validPlanWithName.job_name} generated a report.`);
- });
-
- it('diplays the reported changes', () => {
- expect(wrapper.text()).toContain(
- `Reported Resource Changes: ${validPlanWithName.create} to add, ${validPlanWithName.update} to change, ${validPlanWithName.delete} to delete`,
- );
- });
-
- it('renders button when url is found', () => {
- expect(findLogButton().exists()).toBe(true);
- expect(findLogButton().text()).toEqual('View full log');
- });
- });
-
- describe('valid plan without job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: validPlanWithoutName });
- });
-
- it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A report was generated in your pipelines.');
- });
- });
-
- describe('invalid plan with job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: invalidPlanWithName });
- });
-
- it('displays a warning icon', () => {
- expect(findIcon().attributes('name')).toBe('warning');
- });
-
- it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(
- `The job ${invalidPlanWithName.job_name} failed to generate a report.`,
- );
- });
-
- it('diplays generic error since report values are missing', () => {
- expect(wrapper.text()).toContain('Generating the report caused an error.');
- });
- });
-
- describe('invalid plan with out job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: invalidPlanWithoutName });
- });
-
- it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A report failed to generate.');
- });
-
- it('does not render button because url is missing', () => {
- expect(findLogButton().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/__snapshots__/dynamic_content_spec.js.snap b/spec/frontend/vue_merge_request_widget/components/widget/__snapshots__/dynamic_content_spec.js.snap
new file mode 100644
index 00000000000..08424077269
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/widget/__snapshots__/dynamic_content_spec.js.snap
@@ -0,0 +1,35 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`~/vue_merge_request_widget/components/widget/dynamic_content.vue renders given data 1`] = `
+"<content-row-stub level=\\"2\\" statusiconname=\\"success\\" widgetname=\\"MyWidget\\" header=\\"This is a header,This is a subheader\\">
+ <div class=\\"gl-display-flex gl-flex-direction-column\\">
+ <div>
+ <p class=\\"gl-mb-0\\">Main text for the row</p>
+ <gl-link-stub href=\\"https://gitlab.com\\">Optional link to display after text</gl-link-stub>
+ <!---->
+ <gl-badge-stub size=\\"md\\" variant=\\"info\\">
+ Badge is optional. Text to be displayed inside badge
+ </gl-badge-stub>
+ <actions-stub widget=\\"MyWidget\\" tertiarybuttons=\\"\\" class=\\"gl-ml-auto gl-pl-3\\"></actions-stub>
+ <p class=\\"gl-m-0 gl-font-sm\\">Optional: Smaller sub-text to be displayed below the main text</p>
+ </div>
+ <ul class=\\"gl-m-0 gl-p-0 gl-list-style-none\\">
+ <li>
+ <content-row-stub level=\\"3\\" statusiconname=\\"\\" widgetname=\\"MyWidget\\" header=\\"Child row header\\" data-qa-selector=\\"child_content\\">
+ <div class=\\"gl-display-flex gl-flex-direction-column\\">
+ <div>
+ <p class=\\"gl-mb-0\\">This is recursive. It will be listed in level 3.</p>
+ <!---->
+ <!---->
+ <!---->
+ <actions-stub widget=\\"MyWidget\\" tertiarybuttons=\\"\\" class=\\"gl-ml-auto gl-pl-3\\"></actions-stub>
+ <!---->
+ </div>
+ <!---->
+ </div>
+ </content-row-stub>
+ </li>
+ </ul>
+ </div>
+</content-row-stub>"
+`;
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/dynamic_content_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/dynamic_content_spec.js
new file mode 100644
index 00000000000..b7753a58747
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/widget/dynamic_content_spec.js
@@ -0,0 +1,52 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
+import DynamicContent from '~/vue_merge_request_widget/components/widget/dynamic_content.vue';
+
+describe('~/vue_merge_request_widget/components/widget/dynamic_content.vue', () => {
+ let wrapper;
+
+ const createComponent = ({ propsData } = {}) => {
+ wrapper = shallowMountExtended(DynamicContent, {
+ propsData: {
+ widgetName: 'MyWidget',
+ ...propsData,
+ },
+ stubs: {
+ DynamicContent,
+ },
+ });
+ };
+
+ it('renders given data', () => {
+ createComponent({
+ propsData: {
+ data: {
+ id: 'row-id',
+ header: ['This is a header', 'This is a subheader'],
+ text: 'Main text for the row',
+ subtext: 'Optional: Smaller sub-text to be displayed below the main text',
+ icon: {
+ name: EXTENSION_ICONS.success,
+ },
+ badge: {
+ text: 'Badge is optional. Text to be displayed inside badge',
+ variant: 'info',
+ },
+ link: {
+ text: 'Optional link to display after text',
+ href: 'https://gitlab.com',
+ },
+ children: [
+ {
+ id: 'row-id-2',
+ header: 'Child row header',
+ text: 'This is recursive. It will be listed in level 3.',
+ },
+ ],
+ },
+ },
+ });
+
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_content_row_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_content_row_spec.js
new file mode 100644
index 00000000000..9eddd091ad0
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_content_row_spec.js
@@ -0,0 +1,65 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import WidgetContentRow from '~/vue_merge_request_widget/components/widget/widget_content_row.vue';
+import StatusIcon from '~/vue_merge_request_widget/components/widget/status_icon.vue';
+
+describe('~/vue_merge_request_widget/components/widget/widget_content_row.vue', () => {
+ let wrapper;
+
+ const findStatusIcon = () => wrapper.findComponent(StatusIcon);
+
+ const createComponent = ({ propsData, slots } = {}) => {
+ wrapper = shallowMountExtended(WidgetContentRow, {
+ propsData: {
+ widgetName: 'MyWidget',
+ level: 2,
+ ...propsData,
+ },
+ slots,
+ });
+ };
+
+ describe('body', () => {
+ it('renders the status icon when provided', () => {
+ createComponent({ propsData: { statusIconName: 'failed' } });
+ expect(findStatusIcon().exists()).toBe(true);
+ });
+
+ it('does not render the status icon when it is not provided', () => {
+ createComponent();
+ expect(findStatusIcon().exists()).toBe(false);
+ });
+
+ it('renders slots properly', () => {
+ createComponent({
+ propsData: {
+ statusIconName: 'success',
+ },
+ slots: {
+ header: '<span>this is a header</span>',
+ body: '<span>this is a body</span>',
+ },
+ });
+
+ expect(wrapper.findByText('this is a body').exists()).toBe(true);
+ expect(wrapper.findByText('this is a header').exists()).toBe(true);
+ });
+ });
+
+ describe('header', () => {
+ it('renders an array of header and subheader', () => {
+ createComponent({ propsData: { header: ['this is a header', 'this is a subheader'] } });
+ expect(wrapper.findByText('this is a header').exists()).toBe(true);
+ expect(wrapper.findByText('this is a subheader').exists()).toBe(true);
+ });
+
+ it('renders a string', () => {
+ createComponent({ propsData: { header: 'this is a header' } });
+ expect(wrapper.findByText('this is a header').exists()).toBe(true);
+ });
+
+ it('escapes html injection properly', () => {
+ createComponent({ propsData: { header: '<b role="header">this is a header</b>' } });
+ expect(wrapper.findByText('<b role="header">this is a header</b>').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_content_section_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_content_section_spec.js
deleted file mode 100644
index c2128d3ff33..00000000000
--- a/spec/frontend/vue_merge_request_widget/components/widget/widget_content_section_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import WidgetContentSection from '~/vue_merge_request_widget/components/widget/widget_content_section.vue';
-import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
-
-describe('~/vue_merge_request_widget/components/widget/widget_content_section.vue', () => {
- let wrapper;
-
- const findStatusIcon = () => wrapper.findComponent(StatusIcon);
-
- const createComponent = ({ propsData, slots } = {}) => {
- wrapper = shallowMountExtended(WidgetContentSection, {
- propsData: {
- widgetName: 'MyWidget',
- ...propsData,
- },
- slots,
- });
- };
-
- it('does not render the status icon when it is not provided', () => {
- createComponent();
- expect(findStatusIcon().exists()).toBe(false);
- });
-
- it('renders the status icon when provided', () => {
- createComponent({ propsData: { statusIconName: 'failed' } });
- expect(findStatusIcon().exists()).toBe(true);
- });
-
- it('renders the default slot', () => {
- createComponent({
- slots: {
- default: 'Hello world',
- },
- });
-
- expect(wrapper.findByText('Hello world').exists()).toBe(true);
- });
-});
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
index b67b5703ad5..4826fecf98d 100644
--- a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
@@ -5,8 +5,9 @@ import waitForPromises from 'helpers/wait_for_promises';
import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
import ActionButtons from '~/vue_merge_request_widget/components/action_buttons.vue';
import Widget from '~/vue_merge_request_widget/components/widget/widget.vue';
+import WidgetContentRow from '~/vue_merge_request_widget/components/widget/widget_content_row.vue';
-describe('MR Widget', () => {
+describe('~/vue_merge_request_widget/components/widget/widget.vue', () => {
let wrapper;
const findStatusIcon = () => wrapper.findComponent(StatusIcon);
@@ -27,6 +28,10 @@ describe('MR Widget', () => {
...propsData,
},
slots,
+ stubs: {
+ StatusIcon,
+ ContentRow: WidgetContentRow,
+ },
});
};
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js
index 7e7438bcc0f..1bad5dacefa 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js
@@ -41,7 +41,7 @@ describe('Deployment action button', () => {
});
it('renders prop icon correctly', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
});
});
@@ -59,7 +59,7 @@ describe('Deployment action button', () => {
});
it('renders slot and icon prop correctly', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
expect(wrapper.text()).toContain(actionButtonMocks[DEPLOYING].toString());
});
});
@@ -75,8 +75,8 @@ describe('Deployment action button', () => {
});
it('is disabled and shows the loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(GlButton).props('disabled')).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlButton).props('disabled')).toBe(true);
});
});
@@ -90,8 +90,8 @@ describe('Deployment action button', () => {
});
});
it('is disabled and does not show the loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlButton).props('disabled')).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).props('disabled')).toBe(true);
});
});
@@ -106,8 +106,8 @@ describe('Deployment action button', () => {
});
});
it('is disabled and does not show the loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlButton).props('disabled')).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).props('disabled')).toBe(true);
});
});
@@ -118,8 +118,8 @@ describe('Deployment action button', () => {
});
});
it('is not disabled nor does it show the loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlButton).props('disabled')).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).props('disabled')).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
index a8912405fa8..58dadb2c679 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { visitUrl } from '~/lib/utils/url_utility';
import {
@@ -11,6 +11,7 @@ import {
REDEPLOYING,
STOPPING,
} from '~/vue_merge_request_widget/components/deployment/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
import DeploymentActions from '~/vue_merge_request_widget/components/deployment/deployment_actions.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import {
@@ -167,7 +168,7 @@ describe('DeploymentAction component', () => {
});
it('should not throw an error', () => {
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
});
describe('response includes redirect_url', () => {
@@ -192,6 +193,7 @@ describe('DeploymentAction component', () => {
describe('it should call the executeAction method', () => {
beforeEach(async () => {
jest.spyOn(wrapper.vm, 'executeAction').mockImplementation();
+ jest.spyOn(eventHub, '$emit');
await waitForPromises();
@@ -206,11 +208,16 @@ describe('DeploymentAction component', () => {
actionButtonMocks[configConst],
);
});
+
+ it('emits the FetchDeployments event', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('FetchDeployments');
+ });
});
describe('when executeInlineAction errors', () => {
beforeEach(async () => {
executeActionSpy.mockRejectedValueOnce();
+ jest.spyOn(eventHub, '$emit');
await waitForPromises();
@@ -218,12 +225,15 @@ describe('DeploymentAction component', () => {
finderFn().trigger('click');
});
- it('should call createFlash with error message', () => {
- expect(createFlash).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith({
+ it('should call createAlert with error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({
message: actionButtonMocks[configConst].errorMessage,
});
});
+
+ it('emits the FetchDeployments event', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('FetchDeployments');
+ });
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
index c27cbd8b781..f310f7669a9 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
@@ -37,7 +37,7 @@ describe('Deployment component', () => {
});
it('always renders DeploymentInfo', () => {
- expect(wrapper.find(DeploymentInfo).exists()).toBe(true);
+ expect(wrapper.findComponent(DeploymentInfo).exists()).toBe(true);
});
describe('status message and buttons', () => {
@@ -111,7 +111,7 @@ describe('Deployment component', () => {
});
it(`renders the text: ${text}`, () => {
- expect(wrapper.find(DeploymentInfo).text()).toContain(text);
+ expect(wrapper.findComponent(DeploymentInfo).text()).toContain(text);
});
if (actionButtons.length > 0) {
@@ -137,9 +137,11 @@ describe('Deployment component', () => {
if (actionButtons.includes(DeploymentViewButton)) {
it('renders the View button with expected text', () => {
if (status === SUCCESS) {
- expect(wrapper.find(DeploymentViewButton).text()).toContain('View app');
+ expect(wrapper.findComponent(DeploymentViewButton).text()).toContain('View app');
} else {
- expect(wrapper.find(DeploymentViewButton).text()).toContain('View latest app');
+ expect(wrapper.findComponent(DeploymentViewButton).text()).toContain(
+ 'View latest app',
+ );
}
});
}
@@ -150,7 +152,7 @@ describe('Deployment component', () => {
describe('hasExternalUrls', () => {
describe('when deployment has both external_url_formatted and external_url', () => {
it('should render the View Button', () => {
- expect(wrapper.find(DeploymentViewButton).exists()).toBe(true);
+ expect(wrapper.findComponent(DeploymentViewButton).exists()).toBe(true);
});
});
@@ -165,7 +167,7 @@ describe('Deployment component', () => {
});
it('should not render the View Button', () => {
- expect(wrapper.find(DeploymentViewButton).exists()).toBe(false);
+ expect(wrapper.findComponent(DeploymentViewButton).exists()).toBe(false);
});
});
@@ -180,7 +182,7 @@ describe('Deployment component', () => {
});
it('should not render the View Button', () => {
- expect(wrapper.find(DeploymentViewButton).exists()).toBe(false);
+ expect(wrapper.findComponent(DeploymentViewButton).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
index eb6e3711e2e..8994fa522d0 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
@@ -2,6 +2,7 @@ import { GlDropdown, GlLink } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import DeploymentViewButton from '~/vue_merge_request_widget/components/deployment/deployment_view_button.vue';
import ReviewAppLink from '~/vue_merge_request_widget/components/review_app_link.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import { deploymentMockData } from './deployment_mock_data';
const appButtonText = {
@@ -36,6 +37,7 @@ describe('Deployment View App button', () => {
const findMrWigdetDeploymentDropdownIcon = () =>
wrapper.findByTestId('mr-wigdet-deployment-dropdown-icon');
const findDeployUrlMenuItems = () => wrapper.findAllComponents(GlLink);
+ const findCopyButton = () => wrapper.findComponent(ModalCopyButton);
describe('text', () => {
it('renders text as passed', () => {
@@ -44,39 +46,93 @@ describe('Deployment View App button', () => {
});
describe('without changes', () => {
+ let deployment;
+
beforeEach(() => {
- createComponent({
- propsData: {
- deployment: { ...deploymentMockData, changes: null },
- appButtonText,
- },
+ deployment = { ...deploymentMockData, changes: null };
+ });
+
+ describe('with safe url', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ deployment,
+ appButtonText,
+ },
+ });
+ });
+
+ it('renders the link to the review app without dropdown', () => {
+ expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+ expect(findReviewAppLink().attributes('href')).toBe(deployment.external_url);
});
});
- it('renders the link to the review app without dropdown', () => {
- expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+ describe('without safe URL', () => {
+ beforeEach(() => {
+ deployment = { ...deployment, external_url: 'postgres://example' };
+ createComponent({
+ propsData: {
+ deployment,
+ appButtonText,
+ },
+ });
+ });
+
+ it('renders the link as a copy button', () => {
+ expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+ expect(findCopyButton().props('text')).toBe(deployment.external_url);
+ });
});
});
describe('with a single change', () => {
+ let deployment;
+ let change;
+
beforeEach(() => {
- createComponent({
- propsData: {
- deployment: { ...deploymentMockData, changes: [deploymentMockData.changes[0]] },
- appButtonText,
- },
- });
+ [change] = deploymentMockData.changes;
+ deployment = { ...deploymentMockData, changes: [change] };
});
- it('renders the link to the review app without dropdown', () => {
- expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
- expect(findMrWigdetDeploymentDropdownIcon().exists()).toBe(false);
+ describe('with safe URL', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ deployment,
+ appButtonText,
+ },
+ });
+ });
+
+ it('renders the link to the review app without dropdown', () => {
+ expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+ expect(findMrWigdetDeploymentDropdownIcon().exists()).toBe(false);
+ });
+
+ it('renders the link to the review app linked to to the first change', () => {
+ const expectedUrl = deploymentMockData.changes[0].external_url;
+
+ expect(findReviewAppLink().attributes('href')).toBe(expectedUrl);
+ });
});
- it('renders the link to the review app linked to to the first change', () => {
- const expectedUrl = deploymentMockData.changes[0].external_url;
+ describe('with unsafe URL', () => {
+ beforeEach(() => {
+ change = { ...change, external_url: 'postgres://example' };
+ deployment = { ...deployment, changes: [change] };
+ createComponent({
+ propsData: {
+ deployment,
+ appButtonText,
+ },
+ });
+ });
- expect(findReviewAppLink().attributes('href')).toBe(expectedUrl);
+ it('renders the link as a copy button', () => {
+ expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+ expect(findCopyButton().props('text')).toBe(change.external_url);
+ });
});
});
diff --git a/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js b/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js
index 82743275739..05df66165dd 100644
--- a/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js
@@ -42,7 +42,7 @@ describe('Test report extension', () => {
const findFullReportLink = () => wrapper.findByTestId('full-report-link');
const findCopyFailedSpecsBtn = () => wrapper.findByTestId('copy-failed-specs-btn');
const findAllExtensionListItems = () => wrapper.findAllByTestId('extension-list-item');
- const findModal = () => wrapper.find(TestCaseDetails);
+ const findModal = () => wrapper.findComponent(TestCaseDetails);
const createComponent = () => {
wrapper = mountExtended(extensionsContainer, {
diff --git a/spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js b/spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js
index 295b9df30b9..d038660e6d3 100644
--- a/spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js
+++ b/spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js
@@ -24,7 +24,7 @@ describe('MRWidgetHowToMerge', () => {
mountComponent();
});
- const findModal = () => wrapper.find(GlModal);
+ const findModal = () => wrapper.findComponent(GlModal);
const findInstructionsFields = () =>
wrapper.findAll('[ data-testid="how-to-merge-instructions"]');
const findTipLink = () => wrapper.find("[data-testid='docs-tip']");
diff --git a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
index cc894f94f80..6622749da92 100644
--- a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
@@ -368,12 +368,13 @@ describe('MrWidgetOptions', () => {
describe('bindEventHubListeners', () => {
it.each`
- event | method | methodArgs
- ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${(x) => [x]}
- ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${(x) => [x, true]}
- ${'FetchActionsContent'} | ${'fetchActionsContent'} | ${() => []}
- ${'EnablePolling'} | ${'resumePolling'} | ${() => []}
- ${'DisablePolling'} | ${'stopPolling'} | ${() => []}
+ event | method | methodArgs
+ ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${(x) => [x]}
+ ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${(x) => [x, true]}
+ ${'FetchActionsContent'} | ${'fetchActionsContent'} | ${() => []}
+ ${'EnablePolling'} | ${'resumePolling'} | ${() => []}
+ ${'DisablePolling'} | ${'stopPolling'} | ${() => []}
+ ${'FetchDeployments'} | ${'fetchPreMergeDeployments'} | ${() => []}
`('should bind to $event', ({ event, method, methodArgs }) => {
jest.spyOn(wrapper.vm, method).mockImplementation();
@@ -771,34 +772,40 @@ describe('MrWidgetOptions', () => {
});
describe('security widget', () => {
- describe.each`
- context | hasPipeline | shouldRender
- ${'there is a pipeline'} | ${true} | ${true}
- ${'no pipeline'} | ${false} | ${false}
- `('given $context', ({ hasPipeline, shouldRender }) => {
- beforeEach(() => {
- const mrData = {
- ...mockData,
- ...(hasPipeline ? {} : { pipeline: null }),
- };
+ const setup = async (hasPipeline) => {
+ const mrData = {
+ ...mockData,
+ ...(hasPipeline ? {} : { pipeline: null }),
+ };
- // Override top-level mocked requests, which always use a fresh copy of
- // mockData, which always includes the full pipeline object.
- mock.onGet(mockData.merge_request_widget_path).reply(() => [200, mrData]);
- mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, mrData]);
-
- return createComponent(mrData, {
- apolloProvider: createMockApollo([
- [
- securityReportMergeRequestDownloadPathsQuery,
- async () => ({ data: securityReportMergeRequestDownloadPathsQueryResponse }),
- ],
- ]),
- });
+ // Override top-level mocked requests, which always use a fresh copy of
+ // mockData, which always includes the full pipeline object.
+ mock.onGet(mockData.merge_request_widget_path).reply(() => [200, mrData]);
+ mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, mrData]);
+
+ return createComponent(mrData, {
+ apolloProvider: createMockApollo([
+ [
+ securityReportMergeRequestDownloadPathsQuery,
+ async () => ({ data: securityReportMergeRequestDownloadPathsQueryResponse }),
+ ],
+ ]),
});
+ };
+
+ describe('with a pipeline', () => {
+ it('renders the security widget', async () => {
+ await setup(true);
+
+ expect(findSecurityMrWidget().exists()).toBe(true);
+ });
+ });
+
+ describe('with no pipeline', () => {
+ it('does not render the security widget', async () => {
+ await setup(false);
- it(shouldRender ? 'renders' : 'does not render', () => {
- expect(findSecurityMrWidget().exists()).toBe(shouldRender);
+ expect(findSecurityMrWidget().exists()).toBe(false);
});
});
});
@@ -881,7 +888,10 @@ describe('MrWidgetOptions', () => {
await nextTick();
expect(
- wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
+ wrapper
+ .find('[data-testid="widget-extension-top-level"]')
+ .findComponent(GlDropdown)
+ .exists(),
).toBe(false);
await nextTick();
@@ -891,19 +901,19 @@ describe('MrWidgetOptions', () => {
expect(collapsedSection.text()).toContain('Hello world');
// Renders icon in the row
- expect(collapsedSection.find(GlIcon).exists()).toBe(true);
- expect(collapsedSection.find(GlIcon).props('name')).toBe('status-failed');
+ expect(collapsedSection.findComponent(GlIcon).exists()).toBe(true);
+ expect(collapsedSection.findComponent(GlIcon).props('name')).toBe('status-failed');
// Renders badge in the row
- expect(collapsedSection.find(GlBadge).exists()).toBe(true);
- expect(collapsedSection.find(GlBadge).text()).toBe('Closed');
+ expect(collapsedSection.findComponent(GlBadge).exists()).toBe(true);
+ expect(collapsedSection.findComponent(GlBadge).text()).toBe('Closed');
// Renders a link in the row
- expect(collapsedSection.find(GlLink).exists()).toBe(true);
- expect(collapsedSection.find(GlLink).text()).toBe('GitLab.com');
+ expect(collapsedSection.findComponent(GlLink).exists()).toBe(true);
+ expect(collapsedSection.findComponent(GlLink).text()).toBe('GitLab.com');
- expect(collapsedSection.find(GlButton).exists()).toBe(true);
- expect(collapsedSection.find(GlButton).text()).toBe('Full report');
+ expect(collapsedSection.findComponent(GlButton).exists()).toBe(true);
+ expect(collapsedSection.findComponent(GlButton).text()).toBe('Full report');
});
it('extension polling is not called if enablePolling flag is not passed', () => {
@@ -994,7 +1004,7 @@ describe('MrWidgetOptions', () => {
await createComponent();
- expect(pollRequest).toHaveBeenCalledTimes(4);
+ expect(pollRequest).toHaveBeenCalledTimes(2);
});
});
@@ -1032,7 +1042,7 @@ describe('MrWidgetOptions', () => {
registerExtension(pollingErrorExtension);
await createComponent();
- expect(pollRequest).toHaveBeenCalledTimes(4);
+ expect(pollRequest).toHaveBeenCalledTimes(2);
});
it('captures sentry error and displays error when poll has failed', async () => {
@@ -1134,7 +1144,7 @@ describe('MrWidgetOptions', () => {
${'WidgetCodeQuality'} | ${'i_testing_code_quality_widget_total'}
${'WidgetTerraform'} | ${'i_testing_terraform_widget_total'}
${'WidgetIssues'} | ${'i_testing_issues_widget_total'}
- ${'WidgetTestReport'} | ${'i_testing_summary_widget_total'}
+ ${'WidgetTestSummary'} | ${'i_testing_summary_widget_total'}
`(
"sends non-standard events for the '$widgetName' widget",
async ({ widgetName, nonStandardEvent }) => {
diff --git a/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js b/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js
index 0246a8d4b0f..88d9d0b4cff 100644
--- a/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js
+++ b/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js
@@ -16,12 +16,13 @@ describe('getStateKey', () => {
commitsCount: 2,
hasConflicts: false,
draft: false,
+ detailedMergeStatus: null,
};
const bound = getStateKey.bind(context);
expect(bound()).toEqual(null);
- context.canBeMerged = true;
+ context.detailedMergeStatus = 'MERGEABLE';
expect(bound()).toEqual('readyToMerge');
@@ -36,21 +37,15 @@ describe('getStateKey', () => {
expect(bound()).toEqual('shaMismatch');
context.canMerge = false;
- context.isPipelineBlocked = true;
-
- expect(bound()).toEqual('pipelineBlocked');
-
- context.hasMergeableDiscussionsState = true;
- context.autoMergeEnabled = false;
+ context.detailedMergeStatus = 'DISCUSSIONS_NOT_RESOLVED';
expect(bound()).toEqual('unresolvedDiscussions');
- context.draft = true;
+ context.detailedMergeStatus = 'DRAFT_STATUS';
expect(bound()).toEqual('draft');
- context.onlyAllowMergeIfPipelineSucceeds = true;
- context.isPipelineFailed = true;
+ context.detailedMergeStatus = 'CI_MUST_PASS';
expect(bound()).toEqual('pipelineFailed');
@@ -62,7 +57,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('conflicts');
- context.mergeStatus = 'unchecked';
+ context.detailedMergeStatus = 'CHECKING';
expect(bound()).toEqual('checking');
diff --git a/spec/frontend/vue_shared/components/ci_badge_link_spec.js b/spec/frontend/vue_shared/components/ci_badge_link_spec.js
index 27b6718fb8e..07cbfe1e79b 100644
--- a/spec/frontend/vue_shared/components/ci_badge_link_spec.js
+++ b/spec/frontend/vue_shared/components/ci_badge_link_spec.js
@@ -1,7 +1,7 @@
+import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
@@ -86,18 +86,14 @@ describe('CI Badge Link Component', () => {
wrapper.destroy();
});
- it.each(Object.keys(statuses))('should render badge for status: %s', async (status) => {
+ it.each(Object.keys(statuses))('should render badge for status: %s', (status) => {
createComponent({ status: statuses[status] });
- expect(wrapper.attributes('href')).toBe();
+ expect(wrapper.attributes('href')).toBe(statuses[status].details_path);
expect(wrapper.text()).toBe(statuses[status].text);
expect(wrapper.classes()).toContain('ci-status');
expect(wrapper.classes()).toContain(`ci-${statuses[status].group}`);
expect(findIcon().exists()).toBe(true);
-
- await wrapper.trigger('click');
-
- expect(visitUrl).toHaveBeenCalledWith(statuses[status].details_path);
});
it('should not render label', () => {
@@ -109,7 +105,7 @@ describe('CI Badge Link Component', () => {
it('should emit ciStatusBadgeClick event', async () => {
createComponent({ status: statuses.success });
- await wrapper.trigger('click');
+ await wrapper.findComponent(GlLink).vm.$emit('click');
expect(wrapper.emitted('ciStatusBadgeClick')).toEqual([[]]);
});
diff --git a/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js b/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js
index 441e21ee905..5b0772f6e34 100644
--- a/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_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 createFlash from '~/flash';
+import { createAlert } from '~/flash';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import DropdownContents from '~/vue_shared/components/color_select_dropdown/dropdown_contents.vue';
import DropdownValue from '~/vue_shared/components/color_select_dropdown/dropdown_value.vue';
@@ -146,7 +146,7 @@ describe('LabelsSelectRoot', () => {
});
it('creates flash with error message', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
captureError: true,
message: 'Error fetching epic color.',
});
@@ -186,7 +186,7 @@ describe('LabelsSelectRoot', () => {
findDropdownContents().vm.$emit('setColor', color);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
captureError: true,
error: expect.anything(),
message: 'An error occurred while updating color.',
diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
index 10eacff630d..7a8f94b3746 100644
--- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
+++ b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js
@@ -121,7 +121,7 @@ describe('date time picker lib', () => {
const utcResult = '2019-09-08T01:01:01Z';
const localResult = '2019-09-08T08:01:01Z';
- test.each`
+ it.each`
val | locatTimezone | utc | result
${value} | ${'UTC'} | ${undefined} | ${utcResult}
${value} | ${'UTC'} | ${false} | ${utcResult}
@@ -167,7 +167,7 @@ describe('date time picker lib', () => {
const utcResult = '2019-09-08 08:01:01';
const localResult = '2019-09-08 01:01:01';
- test.each`
+ it.each`
val | locatTimezone | utc | result
${value} | ${'UTC'} | ${undefined} | ${utcResult}
${value} | ${'UTC'} | ${false} | ${utcResult}
diff --git a/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js b/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js
index 68684004b82..99c973bdd26 100644
--- a/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js
@@ -106,11 +106,11 @@ describe('Diff Stats Dropdown', () => {
expectedAddedDeletedExpanded,
expectedAddedDeletedCollapsed,
}) => {
- beforeAll(() => {
+ beforeEach(() => {
createComponent({ changed, added, deleted });
});
- afterAll(() => {
+ afterEach(() => {
wrapper.destroy();
});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
index 69964b2687d..6e0717c29d7 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -1,8 +1,6 @@
-import Vue, { nextTick } from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
-import diffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
+import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
describe('DiffViewer', () => {
const requiredProps = {
@@ -14,37 +12,28 @@ describe('DiffViewer', () => {
oldPath: RED_BOX_IMAGE_URL,
oldSha: 'DEF',
};
- let vm;
-
- function createComponent(props) {
- const DiffViewer = Vue.extend(diffViewer);
+ let wrapper;
- vm = mountComponent(DiffViewer, props);
+ function createComponent(propsData) {
+ wrapper = mount(DiffViewer, { propsData });
}
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- it('renders image diff', async () => {
+ it('renders image diff', () => {
window.gon = {
relative_url_root: '',
};
createComponent({ ...requiredProps, projectPath: '' });
- await nextTick();
-
- expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
- `//-/raw/DEF/${RED_BOX_IMAGE_URL}`,
- );
-
- expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
- `//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`,
- );
+ expect(wrapper.find('.deleted img').attributes('src')).toBe(`//-/raw/DEF/${RED_BOX_IMAGE_URL}`);
+ expect(wrapper.find('.added img').attributes('src')).toBe(`//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`);
});
- it('renders fallback download diff display', async () => {
+ it('renders fallback download diff display', () => {
createComponent({
...requiredProps,
diffViewerMode: 'added',
@@ -52,18 +41,10 @@ describe('DiffViewer', () => {
oldPath: 'testold.abc',
});
- await nextTick();
-
- expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain('testold.abc');
-
- expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
-
- expect(vm.$el.querySelector('.added .file-info').textContent.trim()).toContain('test.abc');
- expect(vm.$el.querySelector('.added .btn.btn-default').textContent.trim()).toContain(
- 'Download',
- );
+ expect(wrapper.find('.deleted .file-info').text()).toContain('testold.abc');
+ expect(wrapper.find('.deleted .btn.btn-default').text()).toContain('Download');
+ expect(wrapper.find('.added .file-info').text()).toContain('test.abc');
+ expect(wrapper.find('.added .btn.btn-default').text()).toContain('Download');
});
describe('renamed file', () => {
@@ -85,7 +66,7 @@ describe('DiffViewer', () => {
oldPath: 'testold.abc',
});
- expect(vm.$el.textContent).toContain('File renamed with no changes.');
+ expect(wrapper.text()).toContain('File renamed with no changes.');
});
});
@@ -99,6 +80,6 @@ describe('DiffViewer', () => {
bMode: '321',
});
- expect(vm.$el.textContent).toContain('File mode changed from 123 to 321');
+ expect(wrapper.text()).toContain('File mode changed from 123 to 321');
});
});
diff --git a/spec/frontend/vue_shared/components/file_finder/item_spec.js b/spec/frontend/vue_shared/components/file_finder/item_spec.js
index b69c33055c1..f0998b1b5c6 100644
--- a/spec/frontend/vue_shared/components/file_finder/item_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/item_spec.js
@@ -1,127 +1,119 @@
-import Vue, { nextTick } from 'vue';
-import createComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import { file } from 'jest/ide/helpers';
import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
describe('File finder item spec', () => {
- const Component = Vue.extend(ItemComponent);
- let vm;
- let localFile;
-
- beforeEach(() => {
- localFile = {
- ...file(),
- name: 'test file',
- path: 'test/file',
- };
-
- vm = createComponent(Component, {
- file: localFile,
- focused: true,
- searchText: '',
- index: 0,
+ let wrapper;
+
+ const createComponent = ({ file: customFileFields = {}, ...otherProps } = {}) => {
+ wrapper = mount(ItemComponent, {
+ propsData: {
+ file: {
+ ...file(),
+ name: 'test file',
+ path: 'test/file',
+ ...customFileFields,
+ },
+ focused: true,
+ searchText: '',
+ index: 0,
+ ...otherProps,
+ },
});
- });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders file name & path', () => {
- expect(vm.$el.textContent).toContain('test file');
- expect(vm.$el.textContent).toContain('test/file');
+ createComponent();
+
+ expect(wrapper.text()).toContain('test file');
+ expect(wrapper.text()).toContain('test/file');
});
describe('focused', () => {
it('adds is-focused class', () => {
- expect(vm.$el.classList).toContain('is-focused');
+ createComponent();
+
+ expect(wrapper.classes()).toContain('is-focused');
});
it('does not have is-focused class when not focused', async () => {
- vm.focused = false;
+ createComponent({ focused: false });
- await nextTick();
- expect(vm.$el.classList).not.toContain('is-focused');
+ expect(wrapper.classes()).not.toContain('is-focused');
});
});
describe('changed file icon', () => {
it('does not render when not a changed or temp file', () => {
- expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
+ createComponent();
+
+ expect(wrapper.find('.diff-changed-stats').exists()).toBe(false);
});
it('renders when a changed file', async () => {
- vm.file.changed = true;
+ createComponent({ file: { changed: true } });
- await nextTick();
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
+ expect(wrapper.find('.diff-changed-stats').exists()).toBe(true);
});
it('renders when a temp file', async () => {
- vm.file.tempFile = true;
+ createComponent({ file: { tempFile: true } });
- await nextTick();
- expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
+ expect(wrapper.find('.diff-changed-stats').exists()).toBe(true);
});
});
- it('emits event when clicked', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ it('emits event when clicked', async () => {
+ createComponent();
- vm.$el.click();
+ await wrapper.find('*').trigger('click');
- expect(vm.$emit).toHaveBeenCalledWith('click', vm.file);
+ expect(wrapper.emitted('click')[0]).toStrictEqual([wrapper.props('file')]);
});
describe('path', () => {
- let el;
-
- beforeEach(async () => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-path');
-
- nextTick();
- });
+ const findChangedFilePath = () => wrapper.find('.diff-changed-file-path');
it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
+ createComponent({ searchText: 'file' });
+
+ expect(findChangedFilePath().findAll('.highlighted')).toHaveLength(4);
});
it('adds ellipsis to long text', async () => {
- vm.file.path = new Array(70)
+ const path = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
- await nextTick();
- expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
+ createComponent({ searchText: 'file', file: { path } });
+
+ expect(findChangedFilePath().text()).toBe(`...${path.substring(path.length - 60)}`);
});
});
describe('name', () => {
- let el;
-
- beforeEach(async () => {
- vm.searchText = 'file';
-
- el = vm.$el.querySelector('.diff-changed-file-name');
-
- await nextTick();
- });
+ const findChangedFileName = () => wrapper.find('.diff-changed-file-name');
it('highlights text', () => {
- expect(el.querySelectorAll('.highlighted').length).toBe(4);
+ createComponent({ searchText: 'file' });
+
+ expect(findChangedFileName().findAll('.highlighted')).toHaveLength(4);
});
it('does not add ellipsis to long text', async () => {
- vm.file.name = new Array(70)
+ const name = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
- await nextTick();
- expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
+ createComponent({ searchText: 'file', file: { name } });
+
+ expect(findChangedFileName().text()).not.toBe(`...${name.substring(name.length - 60)}`);
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
index 4140ec09b4e..66ef473f368 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { mockBranches } from 'jest/vue_shared/components/filtered_search_bar/mock_data';
import Api from '~/api';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import * as actions from '~/vue_shared/components/filtered_search_bar/store/modules/filters/actions';
import * as types from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutation_types';
@@ -159,7 +159,7 @@ describe('Filters actions', () => {
},
],
[],
- ).then(() => expect(createFlash).toHaveBeenCalled());
+ ).then(() => expect(createAlert).toHaveBeenCalled());
});
});
});
@@ -233,7 +233,7 @@ describe('Filters actions', () => {
[],
).then(() => {
expect(mock.history.get[0].url).toBe('/api/v1/groups/fake_group_endpoint/members');
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -252,7 +252,7 @@ describe('Filters actions', () => {
[],
).then(() => {
expect(mock.history.get[0].url).toBe('/api/v1/projects/fake_project_endpoint/users');
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
@@ -298,7 +298,7 @@ describe('Filters actions', () => {
},
],
[],
- ).then(() => expect(createFlash).toHaveBeenCalled());
+ ).then(() => expect(createAlert).toHaveBeenCalled());
});
});
});
@@ -376,7 +376,7 @@ describe('Filters actions', () => {
[],
).then(() => {
expect(mock.history.get[0].url).toBe('/api/v1/groups/fake_group_endpoint/members');
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -395,7 +395,7 @@ describe('Filters actions', () => {
[],
).then(() => {
expect(mock.history.get[0].url).toBe('/api/v1/projects/fake_project_endpoint/users');
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
});
@@ -441,7 +441,7 @@ describe('Filters actions', () => {
},
],
[],
- ).then(() => expect(createFlash).toHaveBeenCalled());
+ ).then(() => expect(createAlert).toHaveBeenCalled());
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 302dfabffb2..5371b9af475 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -8,7 +8,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
@@ -140,13 +140,13 @@ describe('AuthorToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', () => {
+ it('calls `createAlert` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
getBaseToken().vm.$emit('fetch-suggestions', 'root');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching users.',
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index 1de35daa3a5..05b42011fe1 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -9,7 +9,7 @@ import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
@@ -87,13 +87,13 @@ describe('BranchToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', () => {
+ it('calls `createAlert` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchBranches').mockRejectedValue({});
wrapper.vm.fetchBranches('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching branches.',
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js
index c9879987931..5b744521979 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js
@@ -8,7 +8,7 @@ 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 { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -94,7 +94,7 @@ describe('CrmContactToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', 'foo');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchGroupCrmContactsQueryHandler).toHaveBeenCalledWith({
fullPath: 'group',
isProject: false,
@@ -108,7 +108,7 @@ describe('CrmContactToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', '5');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchGroupCrmContactsQueryHandler).toHaveBeenCalledWith({
fullPath: 'group',
isProject: false,
@@ -134,7 +134,7 @@ describe('CrmContactToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', 'foo');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchProjectCrmContactsQueryHandler).toHaveBeenCalledWith({
fullPath: 'project',
isProject: true,
@@ -148,7 +148,7 @@ describe('CrmContactToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', '5');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchProjectCrmContactsQueryHandler).toHaveBeenCalledWith({
fullPath: 'project',
isProject: true,
@@ -159,7 +159,7 @@ describe('CrmContactToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', async () => {
+ it('calls `createAlert` with flash error message when request fails', async () => {
mountComponent();
jest.spyOn(wrapper.vm.$apollo, 'query').mockRejectedValue({});
@@ -167,7 +167,7 @@ describe('CrmContactToken', () => {
getBaseToken().vm.$emit('fetch-suggestions');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching CRM contacts.',
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js
index 16333b052e6..3a3e96032e8 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js
@@ -8,7 +8,7 @@ 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 { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -93,7 +93,7 @@ describe('CrmOrganizationToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', 'foo');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchGroupCrmOrganizationsQueryHandler).toHaveBeenCalledWith({
fullPath: 'group',
isProject: false,
@@ -107,7 +107,7 @@ describe('CrmOrganizationToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', '5');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchGroupCrmOrganizationsQueryHandler).toHaveBeenCalledWith({
fullPath: 'group',
isProject: false,
@@ -133,7 +133,7 @@ describe('CrmOrganizationToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', 'foo');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchProjectCrmOrganizationsQueryHandler).toHaveBeenCalledWith({
fullPath: 'project',
isProject: true,
@@ -147,7 +147,7 @@ describe('CrmOrganizationToken', () => {
getBaseToken().vm.$emit('fetch-suggestions', '5');
await waitForPromises();
- expect(createFlash).not.toHaveBeenCalled();
+ expect(createAlert).not.toHaveBeenCalled();
expect(searchProjectCrmOrganizationsQueryHandler).toHaveBeenCalledWith({
fullPath: 'project',
isProject: true,
@@ -158,7 +158,7 @@ describe('CrmOrganizationToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', async () => {
+ it('calls `createAlert` with flash error message when request fails', async () => {
mountComponent();
jest.spyOn(wrapper.vm.$apollo, 'query').mockRejectedValue({});
@@ -166,7 +166,7 @@ describe('CrmOrganizationToken', () => {
getBaseToken().vm.$emit('fetch-suggestions');
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching CRM organizations.',
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
index bf4a6eb7635..e8436d2db17 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
@@ -8,7 +8,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
@@ -93,13 +93,13 @@ describe('EmojiToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', () => {
+ it('calls `createAlert` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({});
wrapper.vm.fetchEmojis('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching emojis.',
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
index 01e281884ed..8ca12afacec 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -11,7 +11,7 @@ import {
mockRegularLabel,
mockLabels,
} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
@@ -116,13 +116,13 @@ describe('LabelToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', () => {
+ it('calls `createAlert` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchLabels').mockRejectedValue({});
wrapper.vm.fetchLabels('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching labels.',
});
});
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 f71ba51fc5b..589697fe542 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
@@ -8,7 +8,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { sortMilestonesByDueDate } from '~/milestones/utils';
@@ -112,13 +112,13 @@ describe('MilestoneToken', () => {
});
});
- it('calls `createFlash` with flash error message when request fails', () => {
+ it('calls `createAlert` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchMilestones').mockRejectedValue({});
wrapper.vm.fetchMilestones('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching milestones.',
});
});
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 4bbbaab9b7a..0e5fa0f66d4 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
@@ -2,7 +2,7 @@ import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui'
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
import { mockReleaseToken } from '../mock_data';
@@ -73,7 +73,7 @@ describe('ReleaseToken', () => {
});
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
message: 'There was a problem fetching releases.',
});
});
diff --git a/spec/frontend/vue_shared/components/gitlab_version_check_spec.js b/spec/frontend/vue_shared/components/gitlab_version_check_spec.js
index 6699ae5fb69..38f28837cc1 100644
--- a/spec/frontend/vue_shared/components/gitlab_version_check_spec.js
+++ b/spec/frontend/vue_shared/components/gitlab_version_check_spec.js
@@ -1,7 +1,9 @@
import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { mockTracking } from 'helpers/tracking_helper';
+import { helpPagePath } from '~/helpers/help_page_helper';
import axios from '~/lib/utils/axios_utils';
import GitlabVersionCheck from '~/vue_shared/components/gitlab_version_check.vue';
@@ -9,6 +11,8 @@ describe('GitlabVersionCheck', () => {
let wrapper;
let mock;
+ const UPGRADE_DOCS_URL = helpPagePath('update/index');
+
const defaultResponse = {
code: 200,
res: { severity: 'success' },
@@ -23,7 +27,7 @@ describe('GitlabVersionCheck', () => {
mock = new MockAdapter(axios);
mock.onGet().replyOnce(response.code, response.res);
- wrapper = shallowMount(GitlabVersionCheck);
+ wrapper = shallowMountExtended(GitlabVersionCheck);
};
const dummyGon = {
@@ -38,6 +42,7 @@ describe('GitlabVersionCheck', () => {
window.gon = originalGon;
});
+ const findGlBadgeClickWrapper = () => wrapper.findByTestId('badge-click-wrapper');
const findGlBadge = () => wrapper.findComponent(GlBadge);
describe.each`
@@ -77,7 +82,8 @@ describe('GitlabVersionCheck', () => {
await waitForPromises(); // Ensure we wrap up the axios call
});
- it(`does${renders ? '' : ' not'} render GlBadge`, () => {
+ it(`does${renders ? '' : ' not'} render Badge Click Wrapper and GlBadge`, () => {
+ expect(findGlBadgeClickWrapper().exists()).toBe(renders);
expect(findGlBadge().exists()).toBe(renders);
});
});
@@ -90,8 +96,11 @@ describe('GitlabVersionCheck', () => {
${{ code: 200, res: { severity: 'danger' } }} | ${{ title: 'Update ASAP', variant: 'danger' }}
`('badge ui', ({ mockResponse, expectedUI }) => {
describe(`when response is ${mockResponse.res.severity}`, () => {
+ let trackingSpy;
+
beforeEach(async () => {
createComponent(mockResponse);
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
await waitForPromises(); // Ensure we wrap up the axios call
});
@@ -102,6 +111,24 @@ describe('GitlabVersionCheck', () => {
it(`variant is ${expectedUI.variant}`, () => {
expect(findGlBadge().attributes('variant')).toBe(expectedUI.variant);
});
+
+ it(`tracks rendered_version_badge with label ${expectedUI.title}`, () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'rendered_version_badge', {
+ label: expectedUI.title,
+ });
+ });
+
+ it(`link is ${UPGRADE_DOCS_URL}`, () => {
+ expect(findGlBadge().attributes('href')).toBe(UPGRADE_DOCS_URL);
+ });
+
+ it(`tracks click_version_badge with label ${expectedUI.title} when badge is clicked`, async () => {
+ await findGlBadgeClickWrapper().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_version_badge', {
+ label: expectedUI.title,
+ });
+ });
});
});
});
diff --git a/spec/frontend/vue_shared/components/gl_countdown_spec.js b/spec/frontend/vue_shared/components/gl_countdown_spec.js
index 0d1d42082ab..af53d256236 100644
--- a/spec/frontend/vue_shared/components/gl_countdown_spec.js
+++ b/spec/frontend/vue_shared/components/gl_countdown_spec.js
@@ -1,10 +1,9 @@
import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { mount } from '@vue/test-utils';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
describe('GlCountdown', () => {
- const Component = Vue.extend(GlCountdown);
- let vm;
+ let wrapper;
let now = '2000-01-01T00:00:00Z';
beforeEach(() => {
@@ -12,21 +11,20 @@ describe('GlCountdown', () => {
});
afterEach(() => {
- vm.$destroy();
- jest.clearAllTimers();
+ wrapper.destroy();
});
describe('when there is time remaining', () => {
beforeEach(async () => {
- vm = mountComponent(Component, {
- endDateString: '2000-01-01T01:02:03Z',
+ wrapper = mount(GlCountdown, {
+ propsData: {
+ endDateString: '2000-01-01T01:02:03Z',
+ },
});
-
- await nextTick();
});
it('displays remaining time', () => {
- expect(vm.$el.textContent).toContain('01:02:03');
+ expect(wrapper.text()).toContain('01:02:03');
});
it('updates remaining time', async () => {
@@ -34,21 +32,21 @@ describe('GlCountdown', () => {
jest.advanceTimersByTime(1000);
await nextTick();
- expect(vm.$el.textContent).toContain('01:02:02');
+ expect(wrapper.text()).toContain('01:02:02');
});
});
describe('when there is no time remaining', () => {
beforeEach(async () => {
- vm = mountComponent(Component, {
- endDateString: '1900-01-01T00:00:00Z',
+ wrapper = mount(GlCountdown, {
+ propsData: {
+ endDateString: '1900-01-01T00:00:00Z',
+ },
});
-
- await nextTick();
});
it('displays 00:00:00', () => {
- expect(vm.$el.textContent).toContain('00:00:00');
+ expect(wrapper.text()).toContain('00:00:00');
});
});
@@ -62,8 +60,10 @@ describe('GlCountdown', () => {
});
it('throws a validation error', () => {
- vm = mountComponent(Component, {
- endDateString: 'this is invalid',
+ wrapper = mount(GlCountdown, {
+ propsData: {
+ endDateString: 'this is invalid',
+ },
});
expect(Vue.config.warnHandler).toHaveBeenCalledTimes(1);
diff --git a/spec/frontend/vue_shared/components/group_select/utils_spec.js b/spec/frontend/vue_shared/components/group_select/utils_spec.js
new file mode 100644
index 00000000000..5188e1aabf1
--- /dev/null
+++ b/spec/frontend/vue_shared/components/group_select/utils_spec.js
@@ -0,0 +1,24 @@
+import { groupsPath } from '~/vue_shared/components/group_select/utils';
+
+describe('group_select utils', () => {
+ describe('groupsPath', () => {
+ it.each`
+ groupsFilter | parentGroupID | expectedPath
+ ${undefined} | ${undefined} | ${'/api/:version/groups.json'}
+ ${undefined} | ${1} | ${'/api/:version/groups.json'}
+ ${'descendant_groups'} | ${1} | ${'/api/:version/groups/1/descendant_groups'}
+ ${'subgroups'} | ${1} | ${'/api/:version/groups/1/subgroups'}
+ `(
+ 'returns $expectedPath with groupsFilter = $groupsFilter and parentGroupID = $parentGroupID',
+ ({ groupsFilter, parentGroupID, expectedPath }) => {
+ expect(groupsPath(groupsFilter, parentGroupID)).toBe(expectedPath);
+ },
+ );
+ });
+
+ it('throws if groupsFilter is passed but parentGroupID is undefined', () => {
+ expect(() => {
+ groupsPath('descendant_groups');
+ }).toThrow('Cannot use groupsFilter without a parentGroupID');
+ });
+});
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index 9831908f806..ed417097e1e 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -54,6 +54,8 @@ describe('Markdown field header component', () => {
'Add a bullet list',
'Add a numbered list',
'Add a checklist',
+ 'Indent line (⌘])',
+ 'Outdent line (⌘[)',
'Add a collapsible section',
'Add a table',
'Go full screen',
@@ -140,7 +142,7 @@ describe('Markdown field header component', () => {
const tableButton = findToolbarButtonByProp('icon', 'table');
expect(tableButton.props('tag')).toEqual(
- '| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |',
+ '| header | header |\n| ------ | ------ |\n| | |\n| | |',
);
});
diff --git a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
new file mode 100644
index 00000000000..f7e93f45148
--- /dev/null
+++ b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
@@ -0,0 +1,289 @@
+import { GlSegmentedControl } from '@gitlab/ui';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { EDITING_MODE_MARKDOWN_FIELD, EDITING_MODE_CONTENT_EDITOR } from '~/vue_shared/constants';
+import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
+import ContentEditor from '~/content_editor/components/content_editor.vue';
+import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import { stubComponent } from 'helpers/stub_component';
+
+jest.mock('~/emoji');
+
+describe('vue_shared/component/markdown/markdown_editor', () => {
+ let wrapper;
+ const value = 'test markdown';
+ const renderMarkdownPath = '/api/markdown';
+ const markdownDocsPath = '/help/markdown';
+ const quickActionsDocsPath = '/help/quickactions';
+ const enableAutocomplete = true;
+ const enablePreview = false;
+ const formFieldId = 'markdown_field';
+ const formFieldName = 'form[markdown_field]';
+ const formFieldPlaceholder = 'Write some markdown';
+ const formFieldAriaLabel = 'Edit your content';
+ let mock;
+
+ const buildWrapper = ({ propsData = {}, attachTo } = {}) => {
+ wrapper = mountExtended(MarkdownEditor, {
+ attachTo,
+ propsData: {
+ value,
+ renderMarkdownPath,
+ markdownDocsPath,
+ quickActionsDocsPath,
+ enableAutocomplete,
+ enablePreview,
+ formFieldId,
+ formFieldName,
+ formFieldPlaceholder,
+ formFieldAriaLabel,
+ ...propsData,
+ },
+ stubs: {
+ BubbleMenu: stubComponent(BubbleMenu),
+ },
+ });
+ };
+ const findSegmentedControl = () => wrapper.findComponent(GlSegmentedControl);
+ const findMarkdownField = () => wrapper.findComponent(MarkdownField);
+ const findTextarea = () => wrapper.find('textarea');
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
+ const findContentEditor = () => wrapper.findComponent(ContentEditor);
+
+ beforeEach(() => {
+ window.uploads_path = 'uploads';
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ it('displays markdown field by default', () => {
+ buildWrapper({ propsData: { supportsQuickActions: true } });
+
+ expect(findMarkdownField().props()).toEqual(
+ expect.objectContaining({
+ markdownPreviewPath: renderMarkdownPath,
+ quickActionsDocsPath,
+ canAttachFile: true,
+ enableAutocomplete,
+ textareaValue: value,
+ markdownDocsPath,
+ uploadsPath: window.uploads_path,
+ enablePreview,
+ }),
+ );
+ });
+
+ it('renders markdown field textarea', () => {
+ buildWrapper();
+
+ expect(findTextarea().attributes()).toEqual(
+ expect.objectContaining({
+ id: formFieldId,
+ name: formFieldName,
+ placeholder: formFieldPlaceholder,
+ 'aria-label': formFieldAriaLabel,
+ }),
+ );
+
+ expect(findTextarea().element.value).toBe(value);
+ });
+
+ it('renders switch segmented control', () => {
+ buildWrapper();
+
+ expect(findSegmentedControl().props()).toEqual({
+ checked: EDITING_MODE_MARKDOWN_FIELD,
+ options: [
+ {
+ text: expect.any(String),
+ value: EDITING_MODE_MARKDOWN_FIELD,
+ },
+ {
+ text: expect.any(String),
+ value: EDITING_MODE_CONTENT_EDITOR,
+ },
+ ],
+ });
+ });
+
+ describe.each`
+ editingMode
+ ${EDITING_MODE_CONTENT_EDITOR}
+ ${EDITING_MODE_MARKDOWN_FIELD}
+ `('when segmented control emits change event with $editingMode value', ({ editingMode }) => {
+ it(`emits ${editingMode} event`, () => {
+ buildWrapper();
+
+ findSegmentedControl().vm.$emit('change', editingMode);
+
+ expect(wrapper.emitted(editingMode)).toHaveLength(1);
+ });
+ });
+
+ describe(`when editingMode is ${EDITING_MODE_MARKDOWN_FIELD}`, () => {
+ it('emits input event when markdown field textarea changes', async () => {
+ buildWrapper();
+ const newValue = 'new value';
+
+ await findTextarea().setValue(newValue);
+
+ expect(wrapper.emitted('input')).toEqual([[newValue]]);
+ });
+
+ describe('when initOnAutofocus is true', () => {
+ beforeEach(async () => {
+ buildWrapper({ attachTo: document.body, propsData: { initOnAutofocus: true } });
+
+ await nextTick();
+ });
+
+ it('sets the markdown field as the active element in the document', () => {
+ expect(document.activeElement).toBe(findTextarea().element);
+ });
+ });
+
+ it('bubbles up keydown event', async () => {
+ buildWrapper();
+
+ await findTextarea().trigger('keydown');
+
+ expect(wrapper.emitted('keydown')).toHaveLength(1);
+ });
+
+ describe(`when segmented control triggers input event with ${EDITING_MODE_CONTENT_EDITOR} value`, () => {
+ beforeEach(() => {
+ buildWrapper();
+ findSegmentedControl().vm.$emit('input', EDITING_MODE_CONTENT_EDITOR);
+ findSegmentedControl().vm.$emit('change', EDITING_MODE_CONTENT_EDITOR);
+ });
+
+ it('displays the content editor', () => {
+ expect(findContentEditor().props()).toEqual(
+ expect.objectContaining({
+ renderMarkdown: expect.any(Function),
+ uploadsPath: window.uploads_path,
+ markdown: value,
+ autofocus: 'end',
+ }),
+ );
+ });
+
+ it('adds hidden field with current markdown', () => {
+ const hiddenField = wrapper.find(`#${formFieldId}`);
+
+ expect(hiddenField.attributes()).toEqual(
+ expect.objectContaining({
+ id: formFieldId,
+ name: formFieldName,
+ }),
+ );
+ expect(hiddenField.element.value).toBe(value);
+ });
+
+ it('hides the markdown field', () => {
+ expect(findMarkdownField().exists()).toBe(false);
+ });
+
+ it('updates localStorage value', () => {
+ expect(findLocalStorageSync().props().value).toBe(EDITING_MODE_CONTENT_EDITOR);
+ });
+ });
+ });
+
+ describe(`when editingMode is ${EDITING_MODE_CONTENT_EDITOR}`, () => {
+ beforeEach(() => {
+ buildWrapper();
+ findSegmentedControl().vm.$emit('input', EDITING_MODE_CONTENT_EDITOR);
+ });
+
+ describe('when initOnAutofocus is true', () => {
+ beforeEach(() => {
+ buildWrapper({ propsData: { initOnAutofocus: true } });
+ findLocalStorageSync().vm.$emit('input', EDITING_MODE_CONTENT_EDITOR);
+ });
+
+ it('sets the content editor autofocus property to end', () => {
+ expect(findContentEditor().props().autofocus).toBe('end');
+ });
+ });
+
+ it('emits input event when content editor emits change event', async () => {
+ const newValue = 'new value';
+
+ await findContentEditor().vm.$emit('change', { markdown: newValue });
+
+ expect(wrapper.emitted('input')).toEqual([[newValue]]);
+ });
+
+ it('bubbles up keydown event', () => {
+ const event = new Event('keydown');
+
+ findContentEditor().vm.$emit('keydown', event);
+
+ expect(wrapper.emitted('keydown')).toEqual([[event]]);
+ });
+
+ describe(`when segmented control triggers input event with ${EDITING_MODE_MARKDOWN_FIELD} value`, () => {
+ beforeEach(() => {
+ findSegmentedControl().vm.$emit('input', EDITING_MODE_MARKDOWN_FIELD);
+ });
+
+ it('hides the content editor', () => {
+ expect(findContentEditor().exists()).toBe(false);
+ });
+
+ it('shows the markdown field', () => {
+ expect(findMarkdownField().exists()).toBe(true);
+ });
+
+ it('updates localStorage value', () => {
+ expect(findLocalStorageSync().props().value).toBe(EDITING_MODE_MARKDOWN_FIELD);
+ });
+
+ it('sets the textarea as the activeElement in the document', async () => {
+ // The component should be rebuilt to attach it to the document body
+ buildWrapper({ attachTo: document.body });
+ await findSegmentedControl().vm.$emit('input', EDITING_MODE_CONTENT_EDITOR);
+
+ expect(findContentEditor().exists()).toBe(true);
+
+ await findSegmentedControl().vm.$emit('input', EDITING_MODE_MARKDOWN_FIELD);
+ await findSegmentedControl().vm.$emit('change', EDITING_MODE_MARKDOWN_FIELD);
+
+ expect(document.activeElement).toBe(findTextarea().element);
+ });
+ });
+
+ describe('when content editor emits loading event', () => {
+ beforeEach(() => {
+ findContentEditor().vm.$emit('loading');
+ });
+
+ it('disables switch editing mode control', () => {
+ // This is the only way that I found to check the segmented control is disabled
+ expect(findSegmentedControl().find('input[disabled]').exists()).toBe(true);
+ });
+
+ describe.each`
+ event
+ ${'loadingSuccess'}
+ ${'loadingError'}
+ `('when content editor emits $event event', ({ event }) => {
+ beforeEach(() => {
+ findContentEditor().vm.$emit(event);
+ });
+ it('enables the switch editing mode control', () => {
+ expect(findSegmentedControl().find('input[disabled]').exists()).toBe(false);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js b/spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js
index d792bd46ccd..9c91dc9b5fc 100644
--- a/spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js
+++ b/spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js
@@ -139,8 +139,7 @@ describe('Metrics upload item', () => {
closeModal();
await waitForPromises();
-
- expect(findModal().attributes('visible')).toBeFalsy();
+ expect(findModal().attributes('visible')).toBeUndefined();
});
it('should delete the image when selected', async () => {
@@ -189,8 +188,7 @@ describe('Metrics upload item', () => {
closeEditModal();
await waitForPromises();
-
- expect(findEditModal().attributes('visible')).toBeFalsy();
+ expect(findEditModal().attributes('visible')).toBeUndefined();
});
it('should delete the image when selected', async () => {
diff --git a/spec/frontend/vue_shared/components/metric_images/store/actions_spec.js b/spec/frontend/vue_shared/components/metric_images/store/actions_spec.js
index 518cf354675..537367940e0 100644
--- a/spec/frontend/vue_shared/components/metric_images/store/actions_spec.js
+++ b/spec/frontend/vue_shared/components/metric_images/store/actions_spec.js
@@ -4,7 +4,7 @@ import actionsFactory from '~/vue_shared/components/metric_images/store/actions'
import * as types from '~/vue_shared/components/metric_images/store/mutation_types';
import createStore from '~/vue_shared/components/metric_images/store';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { fileList, initialData } from '../mock_data';
@@ -35,7 +35,7 @@ describe('Metrics tab store actions', () => {
});
afterEach(() => {
- createFlash.mockClear();
+ createAlert.mockClear();
});
describe('fetching metric images', () => {
@@ -61,7 +61,7 @@ describe('Metrics tab store actions', () => {
[{ type: types.REQUEST_METRIC_IMAGES }, { type: types.RECEIVE_METRIC_IMAGES_ERROR }],
[],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -98,7 +98,7 @@ describe('Metrics tab store actions', () => {
[{ type: types.REQUEST_METRIC_UPLOAD }, { type: types.RECEIVE_METRIC_UPLOAD_ERROR }],
[],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
@@ -129,7 +129,7 @@ describe('Metrics tab store actions', () => {
[{ type: types.REQUEST_METRIC_UPLOAD }, { type: types.RECEIVE_METRIC_UPLOAD_ERROR }],
[],
);
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
index b57efc88d57..61e4e774420 100644
--- a/spec/frontend/vue_shared/components/modal_copy_button_spec.js
+++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
@@ -17,9 +17,16 @@ describe('modal copy button', () => {
title: 'Copy this value',
id: 'test-id',
},
+ slots: {
+ default: 'test',
+ },
});
});
+ it('should show the default slot', () => {
+ expect(wrapper.text()).toBe('test');
+ });
+
describe('clipboard', () => {
it('should fire a `success` event on click', async () => {
const root = createWrapper(wrapper.vm.$root);
diff --git a/spec/frontend/vue_shared/components/namespace_select/namespace_select_deprecated_spec.js b/spec/frontend/vue_shared/components/namespace_select/namespace_select_deprecated_spec.js
new file mode 100644
index 00000000000..d930ef63dad
--- /dev/null
+++ b/spec/frontend/vue_shared/components/namespace_select/namespace_select_deprecated_spec.js
@@ -0,0 +1,236 @@
+import { nextTick } from 'vue';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import NamespaceSelect, {
+ i18n,
+ EMPTY_NAMESPACE_ID,
+} from '~/vue_shared/components/namespace_select/namespace_select_deprecated.vue';
+import { userNamespaces, groupNamespaces } from './mock_data';
+
+const FLAT_NAMESPACES = [...userNamespaces, ...groupNamespaces];
+const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
+const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
+
+describe('NamespaceSelectDeprecated', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) =>
+ shallowMountExtended(NamespaceSelect, {
+ propsData: {
+ userNamespaces,
+ groupNamespaces,
+ ...props,
+ },
+ stubs: {
+ // We have to "full" mount GlDropdown so that slot children will render
+ GlDropdown,
+ },
+ });
+
+ const wrappersText = (arr) => arr.wrappers.map((w) => w.text());
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownText = () => findDropdown().props('text');
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findGroupDropdownItems = () =>
+ wrapper.findByTestId('namespace-list-groups').findAllComponents(GlDropdownItem);
+ const findDropdownItemsTexts = () => findDropdownItems().wrappers.map((x) => x.text());
+ const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const search = (term) => findSearchBox().vm.$emit('input', term);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('renders the dropdown', () => {
+ expect(findDropdown().exists()).toBe(true);
+ });
+
+ it('renders each dropdown item', () => {
+ expect(findDropdownItemsTexts()).toEqual(FLAT_NAMESPACES.map((x) => x.humanName));
+ });
+
+ it('renders default dropdown text', () => {
+ expect(findDropdownText()).toBe(i18n.DEFAULT_TEXT);
+ });
+
+ it('splits group and user namespaces', () => {
+ const headers = findSectionHeaders();
+ expect(wrappersText(headers)).toEqual([i18n.USERS, i18n.GROUPS]);
+ });
+
+ it('does not render wrapper as full width', () => {
+ expect(findDropdown().attributes('block')).toBeUndefined();
+ });
+ });
+
+ it('with defaultText, it overrides dropdown text', () => {
+ const textOverride = 'Select an option';
+
+ wrapper = createComponent({ defaultText: textOverride });
+
+ expect(findDropdownText()).toBe(textOverride);
+ });
+
+ it('with includeHeaders=false, hides group/user headers', () => {
+ wrapper = createComponent({ includeHeaders: false });
+
+ expect(findSectionHeaders()).toHaveLength(0);
+ });
+
+ it('with fullWidth=true, sets the dropdown to full width', () => {
+ wrapper = createComponent({ fullWidth: true });
+
+ expect(findDropdown().attributes('block')).toBe('true');
+ });
+
+ describe('with search', () => {
+ it.each`
+ term | includeEmptyNamespace | shouldFilterNamespaces | expectedItems
+ ${''} | ${false} | ${true} | ${[...userNamespaces, ...groupNamespaces]}
+ ${'sub'} | ${false} | ${true} | ${[groupNamespaces[1]]}
+ ${'User'} | ${false} | ${true} | ${[...userNamespaces]}
+ ${'User'} | ${true} | ${true} | ${[...userNamespaces]}
+ ${'namespace'} | ${true} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...userNamespaces]}
+ ${'sub'} | ${false} | ${false} | ${[...userNamespaces, ...groupNamespaces]}
+ `(
+ 'with term=$term, includeEmptyNamespace=$includeEmptyNamespace, and shouldFilterNamespaces=$shouldFilterNamespaces should show $expectedItems.length',
+ async ({ term, includeEmptyNamespace, shouldFilterNamespaces, expectedItems }) => {
+ wrapper = createComponent({
+ includeEmptyNamespace,
+ emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
+ shouldFilterNamespaces,
+ });
+
+ search(term);
+
+ await nextTick();
+
+ const expected = expectedItems.map((x) => x.humanName);
+
+ expect(findDropdownItemsTexts()).toEqual(expected);
+ },
+ );
+ });
+
+ describe('when search is typed in', () => {
+ it('emits `search` event', async () => {
+ wrapper = createComponent();
+
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'foo');
+
+ await nextTick();
+
+ expect(wrapper.emitted('search')).toEqual([['foo']]);
+ });
+ });
+
+ describe('with a selected namespace', () => {
+ const selectedGroupIndex = 1;
+ const selectedItem = groupNamespaces[selectedGroupIndex];
+
+ beforeEach(() => {
+ wrapper = createComponent();
+
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'foo');
+ findGroupDropdownItems().at(selectedGroupIndex).vm.$emit('click');
+ });
+
+ it('sets the dropdown text', () => {
+ expect(findDropdownText()).toBe(selectedItem.humanName);
+ });
+
+ it('emits the `select` event when a namespace is selected', () => {
+ const args = [selectedItem];
+ expect(wrapper.emitted('select')).toEqual([args]);
+ });
+
+ it('clears search', () => {
+ expect(wrapper.findComponent(GlSearchBoxByType).props('value')).toBe('');
+ });
+ });
+
+ describe('with an empty namespace option', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ includeEmptyNamespace: true,
+ emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
+ });
+ });
+
+ it('includes the empty namespace', () => {
+ const first = findDropdownItems().at(0);
+
+ expect(first.text()).toBe(EMPTY_NAMESPACE_TITLE);
+ });
+
+ it('emits the `select` event when a namespace is selected', () => {
+ findDropdownItems().at(0).vm.$emit('click');
+
+ expect(wrapper.emitted('select')).toEqual([[EMPTY_NAMESPACE_ITEM]]);
+ });
+
+ it.each`
+ desc | term | shouldShow
+ ${'should hide empty option'} | ${'group'} | ${false}
+ ${'should show empty option'} | ${'Empty'} | ${true}
+ `('when search for $term, $desc', async ({ term, shouldShow }) => {
+ search(term);
+
+ await nextTick();
+
+ expect(findDropdownItemsTexts().includes(EMPTY_NAMESPACE_TITLE)).toBe(shouldShow);
+ });
+ });
+
+ describe('when `hasNextPageOfGroups` prop is `true`', () => {
+ it('renders `GlIntersectionObserver` and emits `load-more-groups` event when bottom is reached', () => {
+ wrapper = createComponent({ hasNextPageOfGroups: true });
+
+ const intersectionObserver = wrapper.findComponent(GlIntersectionObserver);
+
+ intersectionObserver.vm.$emit('appear');
+
+ expect(intersectionObserver.exists()).toBe(true);
+ expect(wrapper.emitted('load-more-groups')).toEqual([[]]);
+ });
+
+ describe('when `isLoading` prop is `true`', () => {
+ it('renders a loading icon', () => {
+ wrapper = createComponent({ hasNextPageOfGroups: true, isLoading: true });
+
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('when `isSearchLoading` prop is `true`', () => {
+ it('sets `isLoading` prop to `true`', () => {
+ wrapper = createComponent({ isSearchLoading: true });
+
+ expect(wrapper.findComponent(GlSearchBoxByType).props('isLoading')).toBe(true);
+ });
+ });
+
+ describe('when dropdown is opened', () => {
+ it('emits `show` event', () => {
+ wrapper = createComponent();
+
+ findDropdown().vm.$emit('show');
+
+ expect(wrapper.emitted('show')).toEqual([[]]);
+ });
+ });
+});
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
deleted file mode 100644
index 2c14d65186b..00000000000
--- a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
+++ /dev/null
@@ -1,226 +0,0 @@
-import { nextTick } from 'vue';
-import {
- GlDropdown,
- GlDropdownItem,
- GlDropdownSectionHeader,
- GlSearchBoxByType,
- GlIntersectionObserver,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import NamespaceSelect, {
- i18n,
- EMPTY_NAMESPACE_ID,
-} from '~/vue_shared/components/namespace_select/namespace_select.vue';
-import { userNamespaces, groupNamespaces } from './mock_data';
-
-const FLAT_NAMESPACES = [...userNamespaces, ...groupNamespaces];
-const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
-const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
-
-describe('Namespace Select', () => {
- let wrapper;
-
- const createComponent = (props = {}) =>
- shallowMountExtended(NamespaceSelect, {
- propsData: {
- userNamespaces,
- groupNamespaces,
- ...props,
- },
- stubs: {
- // We have to "full" mount GlDropdown so that slot children will render
- GlDropdown,
- },
- });
-
- const wrappersText = (arr) => arr.wrappers.map((w) => w.text());
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDropdownText = () => findDropdown().props('text');
- const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
- const findGroupDropdownItems = () =>
- wrapper.findByTestId('namespace-list-groups').findAllComponents(GlDropdownItem);
- const findDropdownItemsTexts = () => findDropdownItems().wrappers.map((x) => x.text());
- const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
- const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
- const search = (term) => findSearchBox().vm.$emit('input', term);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('default', () => {
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- it('renders the dropdown', () => {
- expect(findDropdown().exists()).toBe(true);
- });
-
- it('renders each dropdown item', () => {
- expect(findDropdownItemsTexts()).toEqual(FLAT_NAMESPACES.map((x) => x.humanName));
- });
-
- it('renders default dropdown text', () => {
- expect(findDropdownText()).toBe(i18n.DEFAULT_TEXT);
- });
-
- it('splits group and user namespaces', () => {
- const headers = findSectionHeaders();
- expect(wrappersText(headers)).toEqual([i18n.USERS, i18n.GROUPS]);
- });
-
- it('does not render wrapper as full width', () => {
- expect(findDropdown().attributes('block')).toBeUndefined();
- });
- });
-
- it('with defaultText, it overrides dropdown text', () => {
- const textOverride = 'Select an option';
-
- wrapper = createComponent({ defaultText: textOverride });
-
- expect(findDropdownText()).toBe(textOverride);
- });
-
- it('with includeHeaders=false, hides group/user headers', () => {
- wrapper = createComponent({ includeHeaders: false });
-
- expect(findSectionHeaders()).toHaveLength(0);
- });
-
- it('with fullWidth=true, sets the dropdown to full width', () => {
- wrapper = createComponent({ fullWidth: true });
-
- expect(findDropdown().attributes('block')).toBe('true');
- });
-
- describe('with search', () => {
- it.each`
- term | includeEmptyNamespace | shouldFilterNamespaces | expectedItems
- ${''} | ${false} | ${true} | ${[...userNamespaces, ...groupNamespaces]}
- ${'sub'} | ${false} | ${true} | ${[groupNamespaces[1]]}
- ${'User'} | ${false} | ${true} | ${[...userNamespaces]}
- ${'User'} | ${true} | ${true} | ${[...userNamespaces]}
- ${'namespace'} | ${true} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...userNamespaces]}
- ${'sub'} | ${false} | ${false} | ${[...userNamespaces, ...groupNamespaces]}
- `(
- 'with term=$term, includeEmptyNamespace=$includeEmptyNamespace, and shouldFilterNamespaces=$shouldFilterNamespaces should show $expectedItems.length',
- async ({ term, includeEmptyNamespace, shouldFilterNamespaces, expectedItems }) => {
- wrapper = createComponent({
- includeEmptyNamespace,
- emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
- shouldFilterNamespaces,
- });
-
- search(term);
-
- await nextTick();
-
- const expected = expectedItems.map((x) => x.humanName);
-
- expect(findDropdownItemsTexts()).toEqual(expected);
- },
- );
- });
-
- describe('when search is typed in', () => {
- it('emits `search` event', async () => {
- wrapper = createComponent();
-
- wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'foo');
-
- await nextTick();
-
- expect(wrapper.emitted('search')).toEqual([['foo']]);
- });
- });
-
- describe('with a selected namespace', () => {
- const selectedGroupIndex = 1;
- const selectedItem = groupNamespaces[selectedGroupIndex];
-
- beforeEach(() => {
- wrapper = createComponent();
-
- wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'foo');
- findGroupDropdownItems().at(selectedGroupIndex).vm.$emit('click');
- });
-
- it('sets the dropdown text', () => {
- expect(findDropdownText()).toBe(selectedItem.humanName);
- });
-
- it('emits the `select` event when a namespace is selected', () => {
- const args = [selectedItem];
- expect(wrapper.emitted('select')).toEqual([args]);
- });
-
- it('clears search', () => {
- expect(wrapper.findComponent(GlSearchBoxByType).props('value')).toBe('');
- });
- });
-
- describe('with an empty namespace option', () => {
- beforeEach(() => {
- wrapper = createComponent({
- includeEmptyNamespace: true,
- emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
- });
- });
-
- it('includes the empty namespace', () => {
- const first = findDropdownItems().at(0);
-
- expect(first.text()).toBe(EMPTY_NAMESPACE_TITLE);
- });
-
- it('emits the `select` event when a namespace is selected', () => {
- findDropdownItems().at(0).vm.$emit('click');
-
- expect(wrapper.emitted('select')).toEqual([[EMPTY_NAMESPACE_ITEM]]);
- });
-
- it.each`
- desc | term | shouldShow
- ${'should hide empty option'} | ${'group'} | ${false}
- ${'should show empty option'} | ${'Empty'} | ${true}
- `('when search for $term, $desc', async ({ term, shouldShow }) => {
- search(term);
-
- await nextTick();
-
- expect(findDropdownItemsTexts().includes(EMPTY_NAMESPACE_TITLE)).toBe(shouldShow);
- });
- });
-
- describe('when `hasNextPageOfGroups` prop is `true`', () => {
- it('renders `GlIntersectionObserver` and emits `load-more-groups` event when bottom is reached', () => {
- wrapper = createComponent({ hasNextPageOfGroups: true });
-
- const intersectionObserver = wrapper.findComponent(GlIntersectionObserver);
-
- intersectionObserver.vm.$emit('appear');
-
- expect(intersectionObserver.exists()).toBe(true);
- expect(wrapper.emitted('load-more-groups')).toEqual([[]]);
- });
-
- describe('when `isLoadingMoreGroups` prop is `true`', () => {
- it('renders a loading icon', () => {
- wrapper = createComponent({ hasNextPageOfGroups: true, isLoadingMoreGroups: true });
-
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
- });
- });
- });
-
- describe('when `isSearchLoading` prop is `true`', () => {
- it('sets `isLoading` prop to `true`', () => {
- wrapper = createComponent({ isSearchLoading: true });
-
- expect(wrapper.findComponent(GlSearchBoxByType).props('isLoading')).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap b/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
index bf6c8e8c704..3bac96069ec 100644
--- a/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
+++ b/spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
@@ -2,13 +2,12 @@
exports[`Issue placeholder note component matches snapshot 1`] = `
<timeline-entry-item-stub
- class="note note-wrapper being-posted fade-in-half"
+ class="note note-wrapper note-comment being-posted fade-in-half"
>
<div
- class="timeline-icon"
+ class="timeline-avatar gl-float-left"
>
<gl-avatar-link-stub
- class="gl-mr-3"
href="/root"
>
<gl-avatar-stub
@@ -16,7 +15,7 @@ exports[`Issue placeholder note component matches snapshot 1`] = `
entityid="0"
entityname="root"
shape="circle"
- size="[object Object]"
+ size="32"
src="mock_path"
/>
</gl-avatar-link-stub>
@@ -50,16 +49,20 @@ exports[`Issue placeholder note component matches snapshot 1`] = `
</div>
<div
- class="note-body"
+ class="timeline-discussion-body"
>
<div
- class="note-text md"
+ class="note-body"
>
- <p>
- Foo
- </p>
-
+ <div
+ class="note-text md"
+ >
+ <p>
+ Foo
+ </p>
+
+ </div>
</div>
</div>
</div>
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 b86c8946e96..8f9f1bb336f 100644
--- a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { GlAvatar } from '@gitlab/ui';
import Vue from 'vue';
import Vuex from 'vuex';
import IssuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
@@ -53,17 +52,4 @@ describe('Issue placeholder note component', () => {
expect(findNote().classes()).toContain('discussion');
});
-
- describe('avatar size', () => {
- it.each`
- size | line | isOverviewTab
- ${{ default: 24, md: 32 }} | ${null} | ${false}
- ${24} | ${{ line_code: '123' }} | ${false}
- ${{ default: 24, md: 32 }} | ${{ line_code: '123' }} | ${true}
- `('renders avatar $size for $line and $isOverviewTab', ({ size, line, isOverviewTab }) => {
- createComponent(false, { line, isOverviewTab });
-
- expect(wrapper.findComponent(GlAvatar).props('size')).toEqual(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
index b3be2f8a775..112cdaf74c6 100644
--- a/spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js
+++ b/spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js
@@ -2,6 +2,7 @@ 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';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
describe('Pagination bar', () => {
const DEFAULT_PROPS = {
@@ -20,6 +21,7 @@ describe('Pagination bar', () => {
...DEFAULT_PROPS,
...propsData,
},
+ stubs: { LocalStorageSync: true },
});
};
@@ -90,4 +92,28 @@ describe('Pagination bar', () => {
'Showing 21 - 40 of 1000+',
);
});
+
+ describe('local storage sync', () => {
+ it('does not perform local storage sync when no storage key is provided', () => {
+ createComponent();
+
+ expect(wrapper.findComponent(LocalStorageSync).exists()).toBe(false);
+ });
+
+ it('passes current page size to local storage sync when storage key is provided', () => {
+ const STORAGE_KEY = 'fakeStorageKey';
+ createComponent({ storageKey: STORAGE_KEY });
+
+ expect(wrapper.getComponent(LocalStorageSync).props('storageKey')).toBe(STORAGE_KEY);
+ });
+
+ it('emits set-page event when local storage sync provides new value', () => {
+ const SAVED_SIZE = 50;
+ createComponent({ storageKey: 'some storage key' });
+
+ wrapper.getComponent(LocalStorageSync).vm.$emit('input', SAVED_SIZE);
+
+ expect(wrapper.emitted('set-page-size')).toEqual([[SAVED_SIZE]]);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/panel_resizer_spec.js b/spec/frontend/vue_shared/components/panel_resizer_spec.js
index d8b903e5bfd..0e261124cbf 100644
--- a/spec/frontend/vue_shared/components/panel_resizer_spec.js
+++ b/spec/frontend/vue_shared/components/panel_resizer_spec.js
@@ -1,12 +1,10 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import panelResizer from '~/vue_shared/components/panel_resizer.vue';
+import { mount } from '@vue/test-utils';
+import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
describe('Panel Resizer component', () => {
- let vm;
- let PanelResizer;
+ let wrapper;
- const triggerEvent = (eventName, el = vm.$el, clientX = 0) => {
+ const triggerEvent = (eventName, el = wrapper.element, clientX = 0) => {
const event = document.createEvent('MouseEvents');
event.initMouseEvent(
eventName,
@@ -29,57 +27,64 @@ describe('Panel Resizer component', () => {
el.dispatchEvent(event);
};
- beforeEach(() => {
- PanelResizer = Vue.extend(panelResizer);
- });
-
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render a div element with the correct classes and styles', () => {
- vm = mountComponent(PanelResizer, {
- startSize: 100,
- side: 'left',
+ wrapper = mount(PanelResizer, {
+ propsData: {
+ startSize: 100,
+ side: 'left',
+ },
});
- expect(vm.$el.tagName).toEqual('DIV');
- expect(vm.$el.getAttribute('class')).toBe(
- 'position-absolute position-top-0 position-bottom-0 drag-handle position-left-0',
- );
+ expect(wrapper.element.tagName).toEqual('DIV');
+ expect(wrapper.classes().sort()).toStrictEqual([
+ 'drag-handle',
+ 'position-absolute',
+ 'position-bottom-0',
+ 'position-left-0',
+ 'position-top-0',
+ ]);
- expect(vm.$el.getAttribute('style')).toBe('cursor: ew-resize;');
+ expect(wrapper.element.getAttribute('style')).toBe('cursor: ew-resize;');
});
it('should render a div element with the correct classes for a right side panel', () => {
- vm = mountComponent(PanelResizer, {
- startSize: 100,
- side: 'right',
+ wrapper = mount(PanelResizer, {
+ propsData: {
+ startSize: 100,
+ side: 'right',
+ },
});
- expect(vm.$el.tagName).toEqual('DIV');
- expect(vm.$el.getAttribute('class')).toBe(
- 'position-absolute position-top-0 position-bottom-0 drag-handle position-right-0',
- );
+ expect(wrapper.element.tagName).toEqual('DIV');
+ expect(wrapper.classes().sort()).toStrictEqual([
+ 'drag-handle',
+ 'position-absolute',
+ 'position-bottom-0',
+ 'position-right-0',
+ 'position-top-0',
+ ]);
});
it('drag the resizer', () => {
- vm = mountComponent(PanelResizer, {
- startSize: 100,
- side: 'left',
+ wrapper = mount(PanelResizer, {
+ propsData: {
+ startSize: 100,
+ side: 'left',
+ },
});
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- triggerEvent('mousedown', vm.$el);
+ triggerEvent('mousedown');
triggerEvent('mousemove', document);
triggerEvent('mouseup', document);
- expect(vm.$emit.mock.calls).toEqual([
- ['resize-start', 100],
- ['update:size', 100],
- ['resize-end', 100],
- ]);
-
- expect(vm.size).toBe(100);
+ expect(wrapper.emitted()).toEqual({
+ 'resize-start': [[100]],
+ 'update:size': [[100]],
+ 'resize-end': [[100]],
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap b/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap
index 2abae33bc19..66cf2354bc7 100644
--- a/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap
+++ b/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap
@@ -2,7 +2,7 @@
exports[`History Item renders the correct markup 1`] = `
<li
- class="timeline-entry system-note note-wrapper gl-mb-6!"
+ class="timeline-entry system-note note-wrapper"
>
<div
class="timeline-entry-inner"
@@ -22,11 +22,13 @@ exports[`History Item renders the correct markup 1`] = `
<div
class="note-header"
>
- <span>
+ <div
+ class="note-header-info"
+ >
<div
data-testid="default-slot"
/>
- </span>
+ </div>
</div>
<div
diff --git a/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
index c5672bc28cc..09b0b3d43ad 100644
--- a/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
+++ b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
@@ -6,7 +6,7 @@ import {
expectedDownloadDropdownPropsWithTitle,
securityReportMergeRequestDownloadPathsQueryResponse,
} from 'jest/vue_shared/security_reports/mock_data';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import Component from '~/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue';
import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
import {
@@ -93,8 +93,8 @@ describe('Merge request artifact Download', () => {
});
});
- it('calls createFlash correctly', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ it('calls createAlert correctly', () => {
+ expect(createAlert).toHaveBeenCalledWith({
message: Component.i18n.apiError,
captureError: true,
error: expect.any(Error),
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 4c7ac6e9a6f..30c1a4b7d2f 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
@@ -67,9 +67,9 @@ describe('LabelsSelectRoot', () => {
// We're utilizing `onDropdownClose` event emitted from the component to always include `touchedLabels`
// while the first param of the method is the labels list which were added/removed.
- expect(wrapper.emitted('updateSelectedLabels')).toBeTruthy();
+ expect(wrapper.emitted('updateSelectedLabels')).toHaveLength(1);
expect(wrapper.emitted('updateSelectedLabels')[0]).toEqual([touchedLabels]);
- expect(wrapper.emitted('onDropdownClose')).toBeTruthy();
+ expect(wrapper.emitted('onDropdownClose')).toHaveLength(1);
expect(wrapper.emitted('onDropdownClose')[0]).toEqual([touchedLabels]);
});
@@ -88,7 +88,7 @@ describe('LabelsSelectRoot', () => {
},
);
- expect(wrapper.emitted('updateSelectedLabels')).toBeTruthy();
+ expect(wrapper.emitted('updateSelectedLabels')).toHaveLength(1);
expect(wrapper.emitted('updateSelectedLabels')[0]).toEqual([
[
{
@@ -97,7 +97,7 @@ describe('LabelsSelectRoot', () => {
},
],
]);
- expect(wrapper.emitted('onDropdownClose')).toBeTruthy();
+ expect(wrapper.emitted('onDropdownClose')).toHaveLength(1);
expect(wrapper.emitted('onDropdownClose')[0]).toEqual([[]]);
});
});
@@ -106,8 +106,7 @@ describe('LabelsSelectRoot', () => {
it('emits `toggleCollapse` event on component', () => {
createComponent();
wrapper.vm.handleCollapsedValueClick();
-
- expect(wrapper.emitted().toggleCollapse).toBeTruthy();
+ expect(wrapper.emitted().toggleCollapse).toHaveLength(1);
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
index 2bc513e87bf..edd044bd754 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions';
import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
@@ -102,7 +102,7 @@ describe('LabelsSelect Actions', () => {
it('shows flash error', () => {
actions.receiveLabelsFailure({ commit: () => {} });
- expect(createFlash).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
});
});
@@ -186,7 +186,7 @@ describe('LabelsSelect Actions', () => {
it('shows flash error', () => {
actions.receiveCreateLabelFailure({ commit: () => {} });
- expect(createFlash).toHaveBeenCalledWith({ message: 'Error creating label.' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'Error creating label.' });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
index 1819e750324..2b2508b5e11 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
@@ -189,10 +189,20 @@ describe('LabelsSelect Mutations', () => {
});
labelGroupIds.forEach((l) => {
- expect(state.labels[l.id - 1].touched).toBeFalsy();
+ expect(state.labels[l.id - 1].touched).toBeUndefined();
expect(state.labels[l.id - 1].set).toBe(false);
});
});
+ it('allows selection of multiple scoped labels', () => {
+ const state = { labels: cloneDeep(labels), allowMultipleScopedLabels: true };
+
+ mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: labels[4].id }] });
+ mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: labels[5].id }] });
+
+ expect(state.labels[4].set).toBe(true);
+ expect(state.labels[5].set).toBe(true);
+ expect(state.labels[6].set).toBe(true);
+ });
});
describe(`${types.UPDATE_LABELS_SET_STATE}`, () => {
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 9c29f304c71..237f174e048 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
@@ -4,7 +4,7 @@ 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 { createAlert } from '~/flash';
import { workspaceLabelsQueries } from '~/sidebar/constants';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue';
import createLabelMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql';
@@ -202,7 +202,7 @@ describe('DropdownContentsCreateView', () => {
});
});
- it('calls createFlash is mutation has a user-recoverable error', async () => {
+ it('calls createAlert is mutation has a user-recoverable error', async () => {
createComponent({ mutationHandler: createLabelUserRecoverableErrorHandler });
fillLabelAttributes();
await nextTick();
@@ -210,10 +210,10 @@ describe('DropdownContentsCreateView', () => {
findCreateButton().vm.$emit('click');
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
- it('calls createFlash is mutation was rejected', async () => {
+ it('calls createAlert is mutation was rejected', async () => {
createComponent({ mutationHandler: createLabelErrorHandler });
fillLabelAttributes();
await nextTick();
@@ -221,7 +221,7 @@ describe('DropdownContentsCreateView', () => {
findCreateButton().vm.$emit('click');
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('displays error in alert if label title is already taken', async () => {
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 7f6770e0bea..5d8ad5ddee5 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
@@ -9,7 +9,7 @@ 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 { createAlert } from '~/flash';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue';
@@ -143,13 +143,13 @@ describe('DropdownContentsLabelsView', () => {
expect(findNoResultsMessage().isVisible()).toBe(true);
});
- it('calls `createFlash` when fetching labels failed', async () => {
+ it('calls `createAlert` when fetching labels failed', async () => {
createComponent({ queryHandler: jest.fn().mockRejectedValue('Houston, we have a problem!') });
await makeObserverAppear();
jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalled();
});
it('emits an `input` event on label click', async () => {
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 cad401e0013..b58c44645d6 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
@@ -3,7 +3,7 @@ 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 { createAlert } from '~/flash';
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';
@@ -151,7 +151,7 @@ describe('LabelsSelectRoot', () => {
it('creates flash with error message when query is rejected', async () => {
createComponent({ queryHandler: errorQueryHandler });
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
});
});
@@ -197,7 +197,7 @@ describe('LabelsSelectRoot', () => {
findDropdownContents().vm.$emit('setLabels', [label]);
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
+ expect(createAlert).toHaveBeenCalledWith({
captureError: true,
error: expect.anything(),
message: 'An error occurred while updating labels.',
diff --git a/spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js b/spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js
index fd3ff9ce892..f661bd6747a 100644
--- a/spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js
@@ -1,10 +1,5 @@
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ChunkLine from '~/vue_shared/components/source_viewer/components/chunk_line.vue';
-import {
- BIDI_CHARS,
- BIDI_CHARS_CLASS_LIST,
- BIDI_CHAR_TOOLTIP,
-} from '~/vue_shared/components/source_viewer/constants';
const DEFAULT_PROPS = {
number: 2,
@@ -31,7 +26,6 @@ describe('Chunk Line component', () => {
const findLineLink = () => wrapper.find('.file-line-num');
const findBlameLink = () => wrapper.find('.file-line-blame');
const findContent = () => wrapper.findByTestId('content');
- const findWrappedBidiChars = () => wrapper.findAllByTestId('bidi-wrapper');
beforeEach(() => {
createComponent();
@@ -40,22 +34,6 @@ describe('Chunk Line component', () => {
afterEach(() => wrapper.destroy());
describe('rendering', () => {
- it('wraps BiDi characters', () => {
- const content = `// some content ${BIDI_CHARS.toString()} with BiDi chars`;
- createComponent({ content });
- const wrappedBidiChars = findWrappedBidiChars();
-
- expect(wrappedBidiChars.length).toBe(BIDI_CHARS.length);
-
- wrappedBidiChars.wrappers.forEach((_, i) => {
- expect(wrappedBidiChars.at(i).text()).toBe(BIDI_CHARS[i]);
- expect(wrappedBidiChars.at(i).attributes()).toMatchObject({
- class: BIDI_CHARS_CLASS_LIST,
- title: BIDI_CHAR_TOOLTIP,
- });
- });
- });
-
it('renders a blame link', () => {
expect(findBlameLink().attributes()).toMatchObject({
href: `${DEFAULT_PROPS.blamePath}#L${DEFAULT_PROPS.number}`,
diff --git a/spec/frontend/vue_shared/components/source_viewer/highlight_util_spec.js b/spec/frontend/vue_shared/components/source_viewer/highlight_util_spec.js
new file mode 100644
index 00000000000..4a995e2fde1
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer/highlight_util_spec.js
@@ -0,0 +1,44 @@
+import hljs from 'highlight.js/lib/core';
+import languageLoader from '~/content_editor/services/highlight_js_language_loader';
+import { registerPlugins } from '~/vue_shared/components/source_viewer/plugins/index';
+import { highlight } from '~/vue_shared/components/source_viewer/workers/highlight_utils';
+
+jest.mock('highlight.js/lib/core', () => ({
+ highlight: jest.fn().mockReturnValue({}),
+ registerLanguage: jest.fn(),
+}));
+
+jest.mock('~/content_editor/services/highlight_js_language_loader', () => ({
+ javascript: jest.fn().mockReturnValue({ default: jest.fn() }),
+}));
+
+jest.mock('~/vue_shared/components/source_viewer/plugins/index', () => ({
+ registerPlugins: jest.fn(),
+}));
+
+const fileType = 'text';
+const content = 'function test() { return true };';
+const language = 'javascript';
+
+describe('Highlight utility', () => {
+ beforeEach(() => highlight(fileType, content, language));
+
+ it('loads the language', () => {
+ expect(languageLoader.javascript).toHaveBeenCalled();
+ });
+
+ it('registers the plugins', () => {
+ expect(registerPlugins).toHaveBeenCalled();
+ });
+
+ it('registers the language', () => {
+ expect(hljs.registerLanguage).toHaveBeenCalledWith(
+ language,
+ languageLoader[language]().default,
+ );
+ });
+
+ it('highlights the content', () => {
+ expect(hljs.highlight).toHaveBeenCalledWith(content, { language });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/index_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/index_spec.js
index 83fdc5d669d..57045ca54ae 100644
--- a/spec/frontend/vue_shared/components/source_viewer/plugins/index_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/index_spec.js
@@ -1,14 +1,18 @@
-import { registerPlugins } from '~/vue_shared/components/source_viewer/plugins/index';
-import { HLJS_ON_AFTER_HIGHLIGHT } from '~/vue_shared/components/source_viewer/constants';
-import wrapComments from '~/vue_shared/components/source_viewer/plugins/wrap_comments';
+import {
+ registerPlugins,
+ HLJS_ON_AFTER_HIGHLIGHT,
+} from '~/vue_shared/components/source_viewer/plugins/index';
+import wrapChildNodes from '~/vue_shared/components/source_viewer/plugins/wrap_child_nodes';
+import wrapBidiChars from '~/vue_shared/components/source_viewer/plugins/wrap_bidi_chars';
-jest.mock('~/vue_shared/components/source_viewer/plugins/wrap_comments');
+jest.mock('~/vue_shared/components/source_viewer/plugins/wrap_child_nodes');
const hljsMock = { addPlugin: jest.fn() };
describe('Highlight.js plugin registration', () => {
beforeEach(() => registerPlugins(hljsMock));
it('registers our plugins', () => {
- expect(hljsMock.addPlugin).toHaveBeenCalledWith({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapComments });
+ expect(hljsMock.addPlugin).toHaveBeenCalledWith({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapBidiChars });
+ expect(hljsMock.addPlugin).toHaveBeenCalledWith({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapChildNodes });
});
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js
index 8079d5ad99a..e4ce07ec668 100644
--- a/spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js
@@ -15,7 +15,7 @@ describe('createLink', () => {
it('escapes the user-controlled content', () => {
const unescapedXSS = '<script>XSS</script>';
const escapedPackageName = '&lt;script&gt;XSS&lt;/script&gt;';
- const escapedHref = '&amp;lt;script&amp;gt;XSS&amp;lt;/script&amp;gt;';
+ const escapedHref = '&lt;script&gt;XSS&lt;/script&gt;';
const href = `http://test.com/${unescapedXSS}`;
const innerText = `testing${unescapedXSS}`;
const result = `<a href="http://test.com/${escapedHref}" rel="nofollow noreferrer noopener">testing${escapedPackageName}</a>`;
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_bidi_chars_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_bidi_chars_spec.js
new file mode 100644
index 00000000000..f40f8b22627
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_bidi_chars_spec.js
@@ -0,0 +1,17 @@
+import wrapBidiChars from '~/vue_shared/components/source_viewer/plugins/wrap_bidi_chars';
+import {
+ BIDI_CHARS,
+ BIDI_CHARS_CLASS_LIST,
+ BIDI_CHAR_TOOLTIP,
+} from '~/vue_shared/components/source_viewer/constants';
+
+describe('Highlight.js plugin for wrapping BiDi characters', () => {
+ it.each(BIDI_CHARS)('wraps %s BiDi char', (bidiChar) => {
+ const inputValue = `// some content ${bidiChar} with BiDi chars`;
+ const outputValue = `// some content <span class="${BIDI_CHARS_CLASS_LIST}" title="${BIDI_CHAR_TOOLTIP}">${bidiChar}</span>`;
+ const hljsResultMock = { value: inputValue };
+
+ wrapBidiChars(hljsResultMock);
+ expect(hljsResultMock.value).toContain(outputValue);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js
new file mode 100644
index 00000000000..bc6df1a2565
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js
@@ -0,0 +1,22 @@
+import wrapChildNodes from '~/vue_shared/components/source_viewer/plugins/wrap_child_nodes';
+
+describe('Highlight.js plugin for wrapping _emitter nodes', () => {
+ it('mutates the input value by wrapping each node in a span tag', () => {
+ const hljsResultMock = {
+ _emitter: {
+ rootNode: {
+ children: [
+ { kind: 'string', children: ['Text 1'] },
+ { kind: 'string', children: ['Text 2', { kind: 'comment', children: ['Text 3'] }] },
+ 'Text4\nText5',
+ ],
+ },
+ },
+ };
+
+ const outputValue = `<span class="hljs-string">Text 1</span><span class="hljs-string"><span class="hljs-string">Text 2</span><span class="hljs-comment">Text 3</span></span><span class="">Text4</span>\n<span class="">Text5</span>`;
+
+ wrapChildNodes(hljsResultMock);
+ expect(hljsResultMock.value).toBe(outputValue);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_comments_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_comments_spec.js
deleted file mode 100644
index 5fd4182da29..00000000000
--- a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_comments_spec.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { HLJS_COMMENT_SELECTOR } from '~/vue_shared/components/source_viewer/constants';
-import wrapComments from '~/vue_shared/components/source_viewer/plugins/wrap_comments';
-
-describe('Highlight.js plugin for wrapping comments', () => {
- it('mutates the input value by wrapping each line in a span tag', () => {
- const inputValue = `<span class="${HLJS_COMMENT_SELECTOR}">/* Line 1 \n* Line 2 \n*/</span>`;
- const outputValue = `<span class="${HLJS_COMMENT_SELECTOR}">/* Line 1 \n<span class="${HLJS_COMMENT_SELECTOR}">* Line 2 </span>\n<span class="${HLJS_COMMENT_SELECTOR}">*/</span>`;
- const hljsResultMock = { value: inputValue };
-
- wrapComments(hljsResultMock);
- expect(hljsResultMock.value).toBe(outputValue);
- });
-
- it('does not mutate the input value if the hljs comment selector is not present', () => {
- const inputValue = '<span class="hljs-keyword">const</span>';
- const hljsResultMock = { value: inputValue };
-
- wrapComments(hljsResultMock);
- expect(hljsResultMock.value).toBe(inputValue);
- });
-
- it('does not mutate the input value if the hljs comment line includes a closing tag', () => {
- const inputValue = `<span class="${HLJS_COMMENT_SELECTOR}">/* Line 1 </span> \n* Line 2 \n*/`;
- const hljsResultMock = { value: inputValue };
-
- wrapComments(hljsResultMock);
- expect(hljsResultMock.value).toBe(inputValue);
- });
-});
diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
index e020d9a557e..6d319b37b02 100644
--- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
@@ -22,10 +22,10 @@ jest.mock('~/vue_shared/components/source_viewer/plugins/index');
Vue.use(VueRouter);
const router = new VueRouter();
-const generateContent = (content, totalLines = 1) => {
+const generateContent = (content, totalLines = 1, delimiter = '\n') => {
let generatedContent = '';
for (let i = 0; i < totalLines; i += 1) {
- generatedContent += `Line: ${i + 1} = ${content}\n`;
+ generatedContent += `Line: ${i + 1} = ${content}${delimiter}`;
}
return generatedContent;
};
@@ -38,7 +38,9 @@ describe('Source Viewer component', () => {
const mappedLanguage = ROUGE_TO_HLJS_LANGUAGE_MAP[language];
const chunk1 = generateContent('// Some source code 1', 70);
const chunk2 = generateContent('// Some source code 2', 70);
- const content = chunk1 + chunk2;
+ const chunk3 = generateContent('// Some source code 3', 70, '\r\n');
+ const chunk3Result = generateContent('// Some source code 3', 70, '\n');
+ const content = chunk1 + chunk2 + chunk3;
const path = 'some/path.js';
const blamePath = 'some/blame/path.js';
const fileType = 'javascript';
@@ -152,6 +154,19 @@ describe('Source Viewer component', () => {
startingFrom: 70,
});
});
+
+ it('renders the third chunk', async () => {
+ const thirdChunk = findChunks().at(2);
+
+ expect(thirdChunk.props('content')).toContain(chunk3Result.trim());
+
+ expect(chunk3Result).toEqual(chunk3.replace(/\r?\n/g, '\n'));
+
+ expect(thirdChunk.props()).toMatchObject({
+ totalLines: 70,
+ startingFrom: 140,
+ });
+ });
});
it('emits showBlobInteractionZones on the eventHub when chunk appears', () => {
diff --git a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
index c6f01efa71a..79b1f17afa0 100644
--- a/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
+++ b/spec/frontend/vue_shared/components/stacked_progress_bar_spec.js
@@ -1,121 +1,109 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import stackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
-
-const createComponent = (config) => {
- const Component = Vue.extend(stackedProgressBarComponent);
- const defaultConfig = {
- successLabel: 'Synced',
- failureLabel: 'Failed',
- neutralLabel: 'Out of sync',
- successCount: 25,
- failureCount: 10,
- totalCount: 5000,
- ...config,
- };
-
- return mountComponent(Component, defaultConfig);
-};
+import { mount } from '@vue/test-utils';
+import StackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
describe('StackedProgressBarComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
+ let wrapper;
+
+ const createComponent = (config) => {
+ const defaultConfig = {
+ successLabel: 'Synced',
+ failureLabel: 'Failed',
+ neutralLabel: 'Out of sync',
+ successCount: 25,
+ failureCount: 10,
+ totalCount: 5000,
+ ...config,
+ };
+
+ wrapper = mount(StackedProgressBarComponent, { propsData: defaultConfig });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- const findSuccessBarText = (wrapper) =>
- wrapper.$el.querySelector('.status-green').innerText.trim();
- const findNeutralBarText = (wrapper) =>
- wrapper.$el.querySelector('.status-neutral').innerText.trim();
- const findFailureBarText = (wrapper) => wrapper.$el.querySelector('.status-red').innerText.trim();
- const findUnavailableBarText = (wrapper) =>
- wrapper.$el.querySelector('.status-unavailable').innerText.trim();
-
- describe('computed', () => {
- describe('neutralCount', () => {
- it('returns neutralCount based on totalCount, successCount and failureCount', () => {
- expect(vm.neutralCount).toBe(4965); // 5000 - 25 - 10
- });
- });
- });
+ const findSuccessBar = () => wrapper.find('.status-green');
+ const findNeutralBar = () => wrapper.find('.status-neutral');
+ const findFailureBar = () => wrapper.find('.status-red');
+ const findUnavailableBar = () => wrapper.find('.status-unavailable');
describe('template', () => {
it('renders container element', () => {
- expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
+ createComponent();
+
+ expect(wrapper.classes()).toContain('stacked-progress-bar');
});
it('renders empty state when count is unavailable', () => {
- const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
+ createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
- expect(findUnavailableBarText(vmX)).not.toBeUndefined();
+ expect(findUnavailableBar()).not.toBeUndefined();
});
it('renders bar elements when count is available', () => {
- expect(findSuccessBarText(vm)).not.toBeUndefined();
- expect(findNeutralBarText(vm)).not.toBeUndefined();
- expect(findFailureBarText(vm)).not.toBeUndefined();
+ createComponent();
+
+ expect(findSuccessBar().exists()).toBe(true);
+ expect(findNeutralBar().exists()).toBe(true);
+ expect(findFailureBar().exists()).toBe(true);
});
describe('getPercent', () => {
it('returns correct percentages from provided count based on `totalCount`', () => {
- vm = createComponent({ totalCount: 100, successCount: 25, failureCount: 10 });
+ createComponent({ totalCount: 100, successCount: 25, failureCount: 10 });
- expect(findSuccessBarText(vm)).toBe('25%');
- expect(findNeutralBarText(vm)).toBe('65%');
- expect(findFailureBarText(vm)).toBe('10%');
+ expect(findSuccessBar().text()).toBe('25%');
+ expect(findNeutralBar().text()).toBe('65%');
+ expect(findFailureBar().text()).toBe('10%');
});
it('returns percentage with decimal place when decimal is greater than 1', () => {
- vm = createComponent({ successCount: 67 });
+ createComponent({ successCount: 67 });
- expect(findSuccessBarText(vm)).toBe('1.3%');
+ expect(findSuccessBar().text()).toBe('1.3%');
});
it('returns percentage as `< 1%` from provided count based on `totalCount` when evaluated value is less than 1', () => {
- vm = createComponent({ successCount: 10 });
+ createComponent({ successCount: 10 });
- expect(findSuccessBarText(vm)).toBe('< 1%');
+ expect(findSuccessBar().text()).toBe('< 1%');
});
it('returns not available if totalCount is falsy', () => {
- vm = createComponent({ totalCount: 0 });
+ createComponent({ totalCount: 0 });
- expect(findUnavailableBarText(vm)).toBe('Not available');
+ expect(findUnavailableBar().text()).toBe('Not available');
});
it('returns 99.9% when numbers are extreme decimals', () => {
- vm = createComponent({ totalCount: 1000000 });
+ createComponent({ totalCount: 1000000 });
- expect(findNeutralBarText(vm)).toBe('99.9%');
+ expect(findNeutralBar().text()).toBe('99.9%');
});
});
- describe('barStyle', () => {
- it('returns style string based on percentage provided', () => {
- expect(vm.barStyle(50)).toBe('width: 50%;');
+ describe('bar style', () => {
+ it('renders width based on percentage provided', () => {
+ createComponent({ totalCount: 100, successCount: 25 });
+
+ expect(findSuccessBar().element.style.width).toBe('25%');
});
});
- describe('getTooltip', () => {
+ describe('tooltip', () => {
describe('when hideTooltips is false', () => {
it('returns label string based on label and count provided', () => {
- expect(vm.getTooltip('Synced', 10)).toBe('Synced: 10');
+ createComponent({ successCount: 10, successLabel: 'Synced', hideTooltips: false });
+
+ expect(findSuccessBar().attributes('title')).toBe('Synced: 10');
});
});
describe('when hideTooltips is true', () => {
- beforeEach(() => {
- vm = createComponent({ hideTooltips: true });
- });
-
it('returns an empty string', () => {
- expect(vm.getTooltip('Synced', 10)).toBe('');
+ createComponent({ successCount: 10, successLabel: 'Synced', hideTooltips: true });
+
+ expect(findSuccessBar().attributes('title')).toBe('');
});
});
});
diff --git a/spec/frontend/vue_shared/components/timezone_dropdown/helpers.js b/spec/frontend/vue_shared/components/timezone_dropdown/helpers.js
new file mode 100644
index 00000000000..dee4c92add4
--- /dev/null
+++ b/spec/frontend/vue_shared/components/timezone_dropdown/helpers.js
@@ -0,0 +1,6 @@
+import timezoneDataFixture from 'test_fixtures/timezones/short.json';
+
+export { timezoneDataFixture };
+
+export const findTzByName = (identifier = '') =>
+ timezoneDataFixture.find(({ name }) => name.toLowerCase() === identifier.toLowerCase());
diff --git a/spec/frontend/vue_shared/components/timezone_dropdown/timezone_dropdown_spec.js b/spec/frontend/vue_shared/components/timezone_dropdown/timezone_dropdown_spec.js
new file mode 100644
index 00000000000..e5f56c63031
--- /dev/null
+++ b/spec/frontend/vue_shared/components/timezone_dropdown/timezone_dropdown_spec.js
@@ -0,0 +1,111 @@
+import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
+import { formatTimezone } from '~/lib/utils/datetime_utility';
+import { findTzByName, timezoneDataFixture } from './helpers';
+
+describe('Deploy freeze timezone dropdown', () => {
+ let wrapper;
+ let store;
+
+ const createComponent = (searchTerm, selectedTimezone) => {
+ wrapper = shallowMountExtended(TimezoneDropdown, {
+ store,
+ propsData: {
+ value: selectedTimezone,
+ timezoneData: timezoneDataFixture,
+ name: 'user[timezone]',
+ },
+ });
+
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ searchTerm });
+ };
+
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
+ const findEmptyResultsItem = () => wrapper.findByTestId('noMatchingResults');
+ const findHiddenInput = () => wrapper.find('input');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('No time zones found', () => {
+ beforeEach(() => {
+ createComponent('UTC timezone');
+ });
+
+ it('renders empty results message', () => {
+ expect(findDropdownItemByIndex(0).text()).toBe('No matching results');
+ });
+ });
+
+ describe('Search term is empty', () => {
+ beforeEach(() => {
+ createComponent('');
+ });
+
+ it('renders all timezones when search term is empty', () => {
+ expect(findAllDropdownItems()).toHaveLength(timezoneDataFixture.length);
+ });
+ });
+
+ describe('Time zones found', () => {
+ beforeEach(() => {
+ createComponent('Alaska');
+ });
+
+ it('renders only the time zone searched for', () => {
+ const selectedTz = findTzByName('Alaska');
+ expect(findAllDropdownItems()).toHaveLength(1);
+ expect(findDropdownItemByIndex(0).text()).toBe(formatTimezone(selectedTz));
+ });
+
+ it('should not display empty results message', () => {
+ expect(findEmptyResultsItem().exists()).toBe(false);
+ });
+
+ describe('Custom events', () => {
+ const selectedTz = findTzByName('Alaska');
+
+ it('should emit input if a time zone is clicked', () => {
+ findDropdownItemByIndex(0).vm.$emit('click');
+ expect(wrapper.emitted('input')).toEqual([
+ [
+ {
+ formattedTimezone: formatTimezone(selectedTz),
+ identifier: selectedTz.identifier,
+ },
+ ],
+ ]);
+ });
+ });
+ });
+
+ describe('Selected time zone not found', () => {
+ beforeEach(() => {
+ createComponent('', 'Berlin');
+ });
+
+ it('renders empty selections', () => {
+ expect(wrapper.findComponent(GlDropdown).props().text).toBe('Select timezone');
+ });
+
+ it('preserves initial value in the associated input', () => {
+ expect(findHiddenInput().attributes('value')).toBe('Berlin');
+ });
+ });
+
+ describe('Selected time zone found', () => {
+ beforeEach(() => {
+ createComponent('', 'Europe/Berlin');
+ });
+
+ it('renders selected time zone as dropdown label', () => {
+ expect(wrapper.findComponent(GlDropdown).props().text).toBe('[UTC + 2] Berlin');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/url_sync_spec.js b/spec/frontend/vue_shared/components/url_sync_spec.js
index aefe6a5c3e8..acda1a64a75 100644
--- a/spec/frontend/vue_shared/components/url_sync_spec.js
+++ b/spec/frontend/vue_shared/components/url_sync_spec.js
@@ -1,10 +1,11 @@
import { shallowMount } from '@vue/test-utils';
import { historyPushState } from '~/lib/utils/common_utils';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import UrlSyncComponent from '~/vue_shared/components/url_sync.vue';
+import { mergeUrlParams, setUrlParams } from '~/lib/utils/url_utility';
+import UrlSyncComponent, { URL_SET_PARAMS_STRATEGY } from '~/vue_shared/components/url_sync.vue';
jest.mock('~/lib/utils/url_utility', () => ({
- mergeUrlParams: jest.fn((query, url) => `urlParams: ${query} ${url}`),
+ mergeUrlParams: jest.fn((query, url) => `urlParams: ${JSON.stringify(query)} ${url}`),
+ setUrlParams: jest.fn((query, url) => `urlParams: ${JSON.stringify(query)} ${url}`),
}));
jest.mock('~/lib/utils/common_utils', () => ({
@@ -17,9 +18,14 @@ describe('url sync component', () => {
const findButton = () => wrapper.find('button');
- const createComponent = ({ query = mockQuery, scopedSlots, slots } = {}) => {
+ const createComponent = ({
+ query = mockQuery,
+ scopedSlots,
+ slots,
+ urlParamsUpdateStrategy,
+ } = {}) => {
wrapper = shallowMount(UrlSyncComponent, {
- propsData: { query },
+ propsData: { query, ...(urlParamsUpdateStrategy && { urlParamsUpdateStrategy }) },
scopedSlots,
slots,
});
@@ -29,21 +35,39 @@ describe('url sync component', () => {
wrapper.destroy();
});
- const expectUrlSync = (query, times, mergeUrlParamsReturnValue) => {
- expect(mergeUrlParams).toHaveBeenCalledTimes(times);
- expect(mergeUrlParams).toHaveBeenCalledWith(query, window.location.href, {
- spreadArrays: true,
- });
+ const expectUrlSyncFactory = (
+ query,
+ times,
+ urlParamsUpdateStrategy,
+ urlOptions,
+ urlReturnValue,
+ ) => {
+ expect(urlParamsUpdateStrategy).toHaveBeenCalledTimes(times);
+ expect(urlParamsUpdateStrategy).toHaveBeenCalledWith(query, window.location.href, urlOptions);
expect(historyPushState).toHaveBeenCalledTimes(times);
- expect(historyPushState).toHaveBeenCalledWith(mergeUrlParamsReturnValue);
+ expect(historyPushState).toHaveBeenCalledWith(urlReturnValue);
+ };
+
+ const expectUrlSyncWithMergeUrlParams = (query, times, mergeUrlParamsReturnValue) => {
+ expectUrlSyncFactory(
+ query,
+ times,
+ mergeUrlParams,
+ { spreadArrays: true },
+ mergeUrlParamsReturnValue,
+ );
+ };
+
+ const expectUrlSyncWithSetUrlParams = (query, times, setUrlParamsReturnValue) => {
+ expectUrlSyncFactory(query, times, setUrlParams, true, setUrlParamsReturnValue);
};
describe('with query as a props', () => {
it('immediately syncs the query to the URL', () => {
createComponent();
- expectUrlSync(mockQuery, 1, mergeUrlParams.mock.results[0].value);
+ expectUrlSyncWithMergeUrlParams(mockQuery, 1, mergeUrlParams.mock.results[0].value);
});
describe('when the query is modified', () => {
@@ -54,11 +78,21 @@ describe('url sync component', () => {
// using setProps to test the watcher
await wrapper.setProps({ query: newQuery });
- expectUrlSync(mockQuery, 2, mergeUrlParams.mock.results[1].value);
+ expectUrlSyncWithMergeUrlParams(mockQuery, 2, mergeUrlParams.mock.results[1].value);
});
});
});
+ describe('with url-params-update-strategy equals to URL_SET_PARAMS_STRATEGY', () => {
+ it('uses setUrlParams to generate URL', () => {
+ createComponent({
+ urlParamsUpdateStrategy: URL_SET_PARAMS_STRATEGY,
+ });
+
+ expectUrlSyncWithSetUrlParams(mockQuery, 1, setUrlParams.mock.results[0].value);
+ });
+ });
+
describe('with scoped slot', () => {
const scopedSlots = {
default: `
@@ -77,7 +111,7 @@ describe('url sync component', () => {
findButton().trigger('click');
- expectUrlSync({ bar: 'baz' }, 1, mergeUrlParams.mock.results[0].value);
+ expectUrlSyncWithMergeUrlParams({ bar: 'baz' }, 1, mergeUrlParams.mock.results[0].value);
});
});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_new_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_new_spec.js
deleted file mode 100644
index f87737ca86a..00000000000
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_new_spec.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlAvatar, GlTooltip } from '@gitlab/ui';
-import defaultAvatarUrl from 'images/no_avatar.png';
-import { placeholderImage } from '~/lazy_loader';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image_new.vue';
-
-jest.mock('images/no_avatar.png', () => 'default-avatar-url');
-
-const PROVIDED_PROPS = {
- size: 32,
- imgSrc: 'myavatarurl.com',
- imgAlt: 'mydisplayname',
- cssClasses: 'myextraavatarclass',
- tooltipText: 'tooltip text',
- tooltipPlacement: 'bottom',
-};
-
-describe('User Avatar Image Component', () => {
- let wrapper;
-
- const findAvatar = () => wrapper.findComponent(GlAvatar);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('Initialization', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- },
- });
- });
-
- it('should render `GlAvatar` and provide correct properties to it', () => {
- expect(findAvatar().attributes('data-src')).toBe(
- `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- );
- expect(findAvatar().props()).toMatchObject({
- src: `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- alt: PROVIDED_PROPS.imgAlt,
- size: PROVIDED_PROPS.size,
- });
- });
-
- it('should add correct CSS classes', () => {
- const classes = wrapper.findComponent(GlAvatar).classes();
- expect(classes).toContain(PROVIDED_PROPS.cssClasses);
- expect(classes).not.toContain('lazy');
- });
- });
-
- describe('Initialization when lazy', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- lazy: true,
- },
- });
- });
-
- it('should add lazy attributes', () => {
- expect(findAvatar().classes()).toContain('lazy');
- expect(findAvatar().attributes()).toMatchObject({
- src: placeholderImage,
- 'data-src': `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- });
- });
-
- it('should use maximum number when size is provided as an object', () => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- size: { default: 16, md: 64, lg: 24 },
- lazy: true,
- },
- });
-
- expect(findAvatar().attributes('data-src')).toBe(`${PROVIDED_PROPS.imgSrc}?width=${64}`);
- });
- });
-
- describe('Initialization without src', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- imgSrc: null,
- },
- });
- });
-
- it('should have default avatar image', () => {
- expect(findAvatar().props('src')).toBe(`${defaultAvatarUrl}?width=${PROVIDED_PROPS.size}`);
- });
- });
-
- describe('Dynamic tooltip content', () => {
- const slots = {
- default: ['Action!'],
- };
-
- describe('when `tooltipText` is provided and no default slot', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: { ...PROVIDED_PROPS },
- });
- });
-
- it('renders the tooltip with `tooltipText` as content', () => {
- expect(wrapper.findComponent(GlTooltip).text()).toBe(PROVIDED_PROPS.tooltipText);
- });
- });
-
- describe('when `tooltipText` and default slot is provided', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: { ...PROVIDED_PROPS },
- slots,
- });
- });
-
- it('does not render `tooltipText` inside the tooltip', () => {
- expect(wrapper.findComponent(GlTooltip).text()).not.toBe(PROVIDED_PROPS.tooltipText);
- });
-
- it('renders the content provided via default slot', () => {
- expect(wrapper.findComponent(GlTooltip).text()).toContain(slots.default[0]);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_old_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_old_spec.js
deleted file mode 100644
index 2c1be6ec47e..00000000000
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_old_spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlTooltip } from '@gitlab/ui';
-import defaultAvatarUrl from 'images/no_avatar.png';
-import { placeholderImage } from '~/lazy_loader';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image_old.vue';
-
-jest.mock('images/no_avatar.png', () => 'default-avatar-url');
-
-const PROVIDED_PROPS = {
- size: 32,
- imgSrc: 'myavatarurl.com',
- imgAlt: 'mydisplayname',
- cssClasses: 'myextraavatarclass',
- tooltipText: 'tooltip text',
- tooltipPlacement: 'bottom',
-};
-
-const DEFAULT_PROPS = {
- size: 20,
-};
-
-describe('User Avatar Image Component', () => {
- let wrapper;
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('Initialization', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- },
- });
- });
-
- it('should have <img> as a child element', () => {
- const imageElement = wrapper.find('img');
-
- expect(imageElement.exists()).toBe(true);
- expect(imageElement.attributes('src')).toBe(
- `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- );
- expect(imageElement.attributes('data-src')).toBe(
- `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- );
- expect(imageElement.attributes('alt')).toBe(PROVIDED_PROPS.imgAlt);
- });
-
- it('should properly render img css', () => {
- const classes = wrapper.find('img').classes();
- expect(classes).toEqual(['avatar', 's32', PROVIDED_PROPS.cssClasses]);
- expect(classes).not.toContain('lazy');
- });
- });
-
- describe('Initialization when lazy', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- lazy: true,
- },
- });
- });
-
- it('should add lazy attributes', () => {
- const imageElement = wrapper.find('img');
-
- expect(imageElement.classes()).toContain('lazy');
- expect(imageElement.attributes('src')).toBe(placeholderImage);
- expect(imageElement.attributes('data-src')).toBe(
- `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
- );
- });
- });
-
- describe('Initialization without src', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage);
- });
-
- it('should have default avatar image', () => {
- const imageElement = wrapper.find('img');
-
- expect(imageElement.attributes('src')).toBe(
- `${defaultAvatarUrl}?width=${DEFAULT_PROPS.size}`,
- );
- });
- });
-
- describe('Dynamic tooltip content', () => {
- const slots = {
- default: ['Action!'],
- };
-
- describe('when `tooltipText` is provided and no default slot', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: { ...PROVIDED_PROPS },
- });
- });
-
- it('renders the tooltip with `tooltipText` as content', () => {
- expect(wrapper.findComponent(GlTooltip).text()).toBe(PROVIDED_PROPS.tooltipText);
- });
- });
-
- describe('when `tooltipText` and default slot is provided', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: { ...PROVIDED_PROPS },
- slots,
- });
- });
-
- it('does not render `tooltipText` inside the tooltip', () => {
- expect(wrapper.findComponent(GlTooltip).text()).not.toBe(PROVIDED_PROPS.tooltipText);
- });
-
- it('renders the content provided via default slot', () => {
- expect(wrapper.findComponent(GlTooltip).text()).toContain(slots.default[0]);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
index 6ad2ef226c2..d63b13981ac 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js
@@ -1,7 +1,10 @@
import { shallowMount } from '@vue/test-utils';
+import { GlAvatar, GlTooltip } from '@gitlab/ui';
+import defaultAvatarUrl from 'images/no_avatar.png';
+import { placeholderImage } from '~/lazy_loader';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import UserAvatarImageNew from '~/vue_shared/components/user_avatar/user_avatar_image_new.vue';
-import UserAvatarImageOld from '~/vue_shared/components/user_avatar/user_avatar_image_old.vue';
+
+jest.mock('images/no_avatar.png', () => 'default-avatar-url');
const PROVIDED_PROPS = {
size: 32,
@@ -15,37 +18,117 @@ const PROVIDED_PROPS = {
describe('User Avatar Image Component', () => {
let wrapper;
- const createWrapper = (props = {}, { glAvatarForAllUserAvatars } = {}) => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- ...props,
- },
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars,
- },
- },
- });
- };
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
afterEach(() => {
wrapper.destroy();
});
- describe.each([
- [false, true, true],
- [true, false, true],
- [true, true, true],
- [false, false, false],
- ])(
- 'when glAvatarForAllUserAvatars=%s and enforceGlAvatar=%s',
- (glAvatarForAllUserAvatars, enforceGlAvatar, isUsingNewVersion) => {
- it(`will render ${isUsingNewVersion ? 'new' : 'old'} version`, () => {
- createWrapper({ enforceGlAvatar }, { glAvatarForAllUserAvatars });
- expect(wrapper.findComponent(UserAvatarImageNew).exists()).toBe(isUsingNewVersion);
- expect(wrapper.findComponent(UserAvatarImageOld).exists()).toBe(!isUsingNewVersion);
- });
- },
- );
+ describe('Initialization', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ },
+ });
+ });
+
+ it('should render `GlAvatar` and provide correct properties to it', () => {
+ expect(findAvatar().attributes('data-src')).toBe(
+ `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
+ );
+ expect(findAvatar().props()).toMatchObject({
+ src: `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
+ alt: PROVIDED_PROPS.imgAlt,
+ size: PROVIDED_PROPS.size,
+ });
+ });
+
+ it('should add correct CSS classes', () => {
+ const classes = wrapper.findComponent(GlAvatar).classes();
+ expect(classes).toContain(PROVIDED_PROPS.cssClasses);
+ expect(classes).not.toContain('lazy');
+ });
+ });
+
+ describe('Initialization when lazy', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ lazy: true,
+ },
+ });
+ });
+
+ it('should add lazy attributes', () => {
+ expect(findAvatar().classes()).toContain('lazy');
+ expect(findAvatar().attributes()).toMatchObject({
+ src: placeholderImage,
+ 'data-src': `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
+ });
+ });
+
+ it('should use maximum number when size is provided as an object', () => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ size: { default: 16, md: 64, lg: 24 },
+ lazy: true,
+ },
+ });
+
+ expect(findAvatar().attributes('data-src')).toBe(`${PROVIDED_PROPS.imgSrc}?width=${64}`);
+ });
+ });
+
+ describe('Initialization without src', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ imgSrc: null,
+ },
+ });
+ });
+
+ it('should have default avatar image', () => {
+ expect(findAvatar().props('src')).toBe(`${defaultAvatarUrl}?width=${PROVIDED_PROPS.size}`);
+ });
+ });
+
+ describe('Dynamic tooltip content', () => {
+ const slots = {
+ default: ['Action!'],
+ };
+
+ describe('when `tooltipText` is provided and no default slot', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: { ...PROVIDED_PROPS },
+ });
+ });
+
+ it('renders the tooltip with `tooltipText` as content', () => {
+ expect(wrapper.findComponent(GlTooltip).text()).toBe(PROVIDED_PROPS.tooltipText);
+ });
+ });
+
+ describe('when `tooltipText` and default slot is provided', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: { ...PROVIDED_PROPS },
+ slots,
+ });
+ });
+
+ it('does not render `tooltipText` inside the tooltip', () => {
+ expect(wrapper.findComponent(GlTooltip).text()).not.toBe(PROVIDED_PROPS.tooltipText);
+ });
+
+ it('renders the content provided via default slot', () => {
+ expect(wrapper.findComponent(GlTooltip).text()).toContain(slots.default[0]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_new_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_new_spec.js
deleted file mode 100644
index f485a14cfea..00000000000
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_new_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { GlAvatarLink } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link_new.vue';
-
-describe('User Avatar Link Component', () => {
- let wrapper;
-
- const findUserName = () => wrapper.findByTestId('user-avatar-link-username');
-
- const defaultProps = {
- linkHref: `${TEST_HOST}/myavatarurl.com`,
- imgSize: 32,
- imgSrc: `${TEST_HOST}/myavatarurl.com`,
- imgAlt: 'mydisplayname',
- imgCssClasses: 'myextraavatarclass',
- tooltipText: 'tooltip text',
- tooltipPlacement: 'bottom',
- username: 'username',
- };
-
- const createWrapper = (props, slots) => {
- wrapper = shallowMountExtended(UserAvatarLink, {
- propsData: {
- ...defaultProps,
- ...props,
- ...slots,
- },
- });
- };
-
- beforeEach(() => {
- createWrapper();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should render GlLink with correct props', () => {
- const link = wrapper.findComponent(GlAvatarLink);
- expect(link.exists()).toBe(true);
- expect(link.attributes('href')).toBe(defaultProps.linkHref);
- });
-
- it('should render UserAvatarImage and provide correct props to it', () => {
- expect(wrapper.findComponent(UserAvatarImage).exists()).toBe(true);
- expect(wrapper.findComponent(UserAvatarImage).props()).toEqual({
- cssClasses: defaultProps.imgCssClasses,
- imgAlt: defaultProps.imgAlt,
- imgSrc: defaultProps.imgSrc,
- lazy: false,
- size: defaultProps.imgSize,
- tooltipPlacement: defaultProps.tooltipPlacement,
- tooltipText: '',
- enforceGlAvatar: false,
- });
- });
-
- describe('when username provided', () => {
- beforeEach(() => {
- createWrapper({ username: defaultProps.username });
- });
-
- it('should render provided username', () => {
- expect(findUserName().text()).toBe(defaultProps.username);
- });
-
- it('should provide the tooltip data for the username', () => {
- expect(findUserName().attributes()).toEqual(
- expect.objectContaining({
- title: defaultProps.tooltipText,
- 'tooltip-placement': defaultProps.tooltipPlacement,
- }),
- );
- });
- });
-
- describe('when username is NOT provided', () => {
- beforeEach(() => {
- createWrapper({ username: '' });
- });
-
- it('should NOT render username', () => {
- expect(findUserName().exists()).toBe(false);
- });
- });
-
- describe('avatar-badge slot', () => {
- const badge = '<span>User badge</span>';
-
- beforeEach(() => {
- createWrapper(defaultProps, {
- 'avatar-badge': badge,
- });
- });
-
- it('should render provided `avatar-badge` slot content', () => {
- expect(wrapper.html()).toContain(badge);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_old_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_old_spec.js
deleted file mode 100644
index cf7a1025dba..00000000000
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_old_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link_old.vue';
-
-describe('User Avatar Link Component', () => {
- let wrapper;
-
- const findUserName = () => wrapper.find('[data-testid="user-avatar-link-username"]');
-
- const defaultProps = {
- linkHref: `${TEST_HOST}/myavatarurl.com`,
- imgSize: 32,
- imgSrc: `${TEST_HOST}/myavatarurl.com`,
- imgAlt: 'mydisplayname',
- imgCssClasses: 'myextraavatarclass',
- tooltipText: 'tooltip text',
- tooltipPlacement: 'bottom',
- username: 'username',
- };
-
- const createWrapper = (props, slots) => {
- wrapper = shallowMountExtended(UserAvatarLink, {
- propsData: {
- ...defaultProps,
- ...props,
- ...slots,
- },
- });
- };
-
- beforeEach(() => {
- createWrapper();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should render GlLink with correct props', () => {
- const link = wrapper.findComponent(GlLink);
- expect(link.exists()).toBe(true);
- expect(link.attributes('href')).toBe(defaultProps.linkHref);
- });
-
- it('should render UserAvatarImage and povide correct props to it', () => {
- expect(wrapper.findComponent(UserAvatarImage).exists()).toBe(true);
- expect(wrapper.findComponent(UserAvatarImage).props()).toEqual({
- cssClasses: defaultProps.imgCssClasses,
- imgAlt: defaultProps.imgAlt,
- imgSrc: defaultProps.imgSrc,
- lazy: false,
- size: defaultProps.imgSize,
- tooltipPlacement: defaultProps.tooltipPlacement,
- tooltipText: '',
- enforceGlAvatar: false,
- });
- });
-
- describe('when username provided', () => {
- beforeEach(() => {
- createWrapper({ username: defaultProps.username });
- });
-
- it('should render provided username', () => {
- expect(findUserName().text()).toBe(defaultProps.username);
- });
-
- it('should provide the tooltip data for the username', () => {
- expect(findUserName().attributes()).toEqual(
- expect.objectContaining({
- title: defaultProps.tooltipText,
- 'tooltip-placement': defaultProps.tooltipPlacement,
- }),
- );
- });
- });
-
- describe('when username is NOT provided', () => {
- beforeEach(() => {
- createWrapper({ username: '' });
- });
-
- it('should NOT render username', () => {
- expect(findUserName().exists()).toBe(false);
- });
- });
-
- describe('avatar-badge slot', () => {
- const badge = '<span>User badge</span>';
-
- beforeEach(() => {
- createWrapper(defaultProps, {
- 'avatar-badge': badge,
- });
- });
-
- it('should render provided `avatar-badge` slot content', () => {
- expect(wrapper.html()).toContain(badge);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
index fd3f59008ec..df7ce449678 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -1,51 +1,102 @@
-import { shallowMount } from '@vue/test-utils';
+import { GlAvatarLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { TEST_HOST } from 'spec/test_constants';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import UserAvatarLinkNew from '~/vue_shared/components/user_avatar/user_avatar_link_new.vue';
-import UserAvatarLinkOld from '~/vue_shared/components/user_avatar/user_avatar_link_old.vue';
-
-const PROVIDED_PROPS = {
- size: 32,
- imgSrc: 'myavatarurl.com',
- imgAlt: 'mydisplayname',
- cssClasses: 'myextraavatarclass',
- tooltipText: 'tooltip text',
- tooltipPlacement: 'bottom',
-};
describe('User Avatar Link Component', () => {
let wrapper;
- const createWrapper = (props = {}, { glAvatarForAllUserAvatars } = {}) => {
- wrapper = shallowMount(UserAvatarLink, {
+ const findUserName = () => wrapper.findByTestId('user-avatar-link-username');
+
+ const defaultProps = {
+ linkHref: `${TEST_HOST}/myavatarurl.com`,
+ imgSize: 32,
+ imgSrc: `${TEST_HOST}/myavatarurl.com`,
+ imgAlt: 'mydisplayname',
+ imgCssClasses: 'myextraavatarclass',
+ tooltipText: 'tooltip text',
+ tooltipPlacement: 'bottom',
+ username: 'username',
+ };
+
+ const createWrapper = (props, slots) => {
+ wrapper = shallowMountExtended(UserAvatarLink, {
propsData: {
- ...PROVIDED_PROPS,
+ ...defaultProps,
...props,
- },
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars,
- },
+ ...slots,
},
});
};
+ beforeEach(() => {
+ createWrapper();
+ });
+
afterEach(() => {
wrapper.destroy();
});
- describe.each([
- [false, true, true],
- [true, false, true],
- [true, true, true],
- [false, false, false],
- ])(
- 'when glAvatarForAllUserAvatars=%s and enforceGlAvatar=%s',
- (glAvatarForAllUserAvatars, enforceGlAvatar, isUsingNewVersion) => {
- it(`will render ${isUsingNewVersion ? 'new' : 'old'} version`, () => {
- createWrapper({ enforceGlAvatar }, { glAvatarForAllUserAvatars });
- expect(wrapper.findComponent(UserAvatarLinkNew).exists()).toBe(isUsingNewVersion);
- expect(wrapper.findComponent(UserAvatarLinkOld).exists()).toBe(!isUsingNewVersion);
+ it('should render GlLink with correct props', () => {
+ const link = wrapper.findComponent(GlAvatarLink);
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(defaultProps.linkHref);
+ });
+
+ it('should render UserAvatarImage and provide correct props to it', () => {
+ expect(wrapper.findComponent(UserAvatarImage).exists()).toBe(true);
+ expect(wrapper.findComponent(UserAvatarImage).props()).toEqual({
+ cssClasses: defaultProps.imgCssClasses,
+ imgAlt: defaultProps.imgAlt,
+ imgSrc: defaultProps.imgSrc,
+ lazy: false,
+ size: defaultProps.imgSize,
+ tooltipPlacement: defaultProps.tooltipPlacement,
+ tooltipText: '',
+ });
+ });
+
+ describe('when username provided', () => {
+ beforeEach(() => {
+ createWrapper({ username: defaultProps.username });
+ });
+
+ it('should render provided username', () => {
+ expect(findUserName().text()).toBe(defaultProps.username);
+ });
+
+ it('should provide the tooltip data for the username', () => {
+ expect(findUserName().attributes()).toEqual(
+ expect.objectContaining({
+ title: defaultProps.tooltipText,
+ 'tooltip-placement': defaultProps.tooltipPlacement,
+ }),
+ );
+ });
+ });
+
+ describe('when username is NOT provided', () => {
+ beforeEach(() => {
+ createWrapper({ username: '' });
+ });
+
+ it('should NOT render username', () => {
+ expect(findUserName().exists()).toBe(false);
+ });
+ });
+
+ describe('avatar-badge slot', () => {
+ const badge = '<span>User badge</span>';
+
+ beforeEach(() => {
+ createWrapper(defaultProps, {
+ 'avatar-badge': badge,
});
- },
- );
+ });
+
+ it('should render provided `avatar-badge` slot content', () => {
+ expect(wrapper.html()).toContain(badge);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
index b9accbf0373..1ad6d043399 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js
@@ -153,29 +153,4 @@ describe('UserAvatarList', () => {
});
});
});
-
- describe('additional styling for the image', () => {
- it('should not add CSS class when feature flag `glAvatarForAllUserAvatars` is disabled', () => {
- factory({
- propsData: { items: createList(1) },
- });
-
- const link = wrapper.findComponent(UserAvatarLink);
- expect(link.props('imgCssClasses')).not.toBe('gl-mr-3');
- });
-
- it('should add CSS class when feature flag `glAvatarForAllUserAvatars` is enabled', () => {
- factory({
- propsData: { items: createList(1) },
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
- });
-
- const link = wrapper.findComponent(UserAvatarLink);
- expect(link.props('imgCssClasses')).toBe('gl-mr-3');
- });
- });
});
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index 6d48000beb0..f6316af6ad8 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -8,10 +8,12 @@ import {
I18N_USER_BLOCKED,
I18N_USER_LEARN,
I18N_USER_FOLLOW,
+ I18N_ERROR_FOLLOW,
I18N_USER_UNFOLLOW,
+ I18N_ERROR_UNFOLLOW,
} from '~/vue_shared/components/user_popover/constants';
import axios from '~/lib/utils/axios_utils';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { followUser, unfollowUser } from '~/api/user_api';
import { mockTracking } from 'helpers/tracking_helper';
@@ -239,6 +241,18 @@ describe('User Popover Component', () => {
expect(wrapper.html()).toContain('<gl-emoji data-name="basketball_player"');
});
+ it('should show only emoji', () => {
+ const user = {
+ ...DEFAULT_PROPS.user,
+ status: { emoji: 'basketball_player' },
+ };
+
+ createWrapper({ user });
+
+ expect(findUserStatus().exists()).toBe(true);
+ expect(wrapper.html()).toContain('<gl-emoji data-name="basketball_player"');
+ });
+
it('hides the div when status is null', () => {
const user = { ...DEFAULT_PROPS.user, status: null };
@@ -367,27 +381,49 @@ describe('User Popover Component', () => {
itTracksToggleFollowButtonClick('follow_from_user_popover');
describe('when an error occurs', () => {
- beforeEach(() => {
- followUser.mockRejectedValue({});
+ describe('api send error message', () => {
+ const mockedMessage = sprintf(I18N_ERROR_UNFOLLOW, { limit: 300 });
+ const apiResponse = { response: { data: { message: mockedMessage } } };
- findToggleFollowButton().trigger('click');
- });
+ beforeEach(() => {
+ followUser.mockRejectedValue(apiResponse);
+ findToggleFollowButton().trigger('click');
+ });
- it('shows an error message', async () => {
- await axios.waitForAll();
+ it('show an error message from api response', async () => {
+ await axios.waitForAll();
- expect(createFlash).toHaveBeenCalledWith({
- message: 'An error occurred while trying to follow this user, please try again.',
- error: {},
- captureError: true,
+ expect(createAlert).toHaveBeenCalledWith({
+ message: mockedMessage,
+ error: apiResponse,
+ captureError: true,
+ });
});
});
- it('emits no events', async () => {
- await axios.waitForAll();
+ describe('api did not send error message', () => {
+ beforeEach(() => {
+ followUser.mockRejectedValue({});
- expect(wrapper.emitted().follow).toBeUndefined();
- expect(wrapper.emitted().unfollow).toBeUndefined();
+ findToggleFollowButton().trigger('click');
+ });
+
+ it('shows an error message', async () => {
+ await axios.waitForAll();
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: I18N_ERROR_FOLLOW,
+ error: {},
+ captureError: true,
+ });
+ });
+
+ it('emits no events', async () => {
+ await axios.waitForAll();
+
+ expect(wrapper.emitted().follow).toBeUndefined();
+ expect(wrapper.emitted().unfollow).toBeUndefined();
+ });
});
});
});
@@ -425,8 +461,8 @@ describe('User Popover Component', () => {
});
it('shows an error message', () => {
- expect(createFlash).toHaveBeenCalledWith({
- message: 'An error occurred while trying to unfollow this user, please try again.',
+ expect(createAlert).toHaveBeenCalledWith({
+ message: I18N_ERROR_UNFOLLOW,
error: {},
captureError: true,
});
diff --git a/spec/frontend/vue_shared/directives/safe_html_spec.js b/spec/frontend/vue_shared/directives/safe_html_spec.js
new file mode 100644
index 00000000000..ba1de8e4596
--- /dev/null
+++ b/spec/frontend/vue_shared/directives/safe_html_spec.js
@@ -0,0 +1,116 @@
+import { shallowMount } from '@vue/test-utils';
+import safeHtml from '~/vue_shared/directives/safe_html';
+import { defaultConfig } from '~/lib/dompurify';
+/* eslint-disable no-script-url */
+const invalidProtocolUrls = [
+ 'javascript:alert(1)',
+ 'jAvascript:alert(1)',
+ 'data:text/html,<script>alert(1);</script>',
+ ' javascript:',
+ 'javascript :',
+];
+/* eslint-enable no-script-url */
+const validProtocolUrls = ['slack://open', 'x-devonthink-item://90909', 'x-devonthink-item:90909'];
+
+describe('safe html directive', () => {
+ let wrapper;
+
+ const createComponent = ({ template, html, config } = {}) => {
+ const defaultTemplate = `<div v-safe-html="rawHtml"></div>`;
+ const defaultHtml = 'hello <script>alert(1)</script>world';
+
+ const component = {
+ directives: {
+ safeHtml,
+ },
+ data() {
+ return {
+ rawHtml: html || defaultHtml,
+ config: config || {},
+ };
+ },
+ template: template || defaultTemplate,
+ };
+
+ wrapper = shallowMount(component);
+ };
+
+ describe('default', () => {
+ it('should remove the script tag', () => {
+ createComponent();
+
+ expect(wrapper.html()).toEqual('<div>hello world</div>');
+ });
+
+ it('should remove javascript hrefs', () => {
+ createComponent({ html: '<a href="javascript:prompt(1)">click here</a>' });
+
+ expect(wrapper.html()).toEqual('<div><a>click here</a></div>');
+ });
+
+ it('should remove any existing children', () => {
+ createComponent({
+ template: `<div v-safe-html="rawHtml">foo <i>bar</i></div>`,
+ });
+
+ expect(wrapper.html()).toEqual('<div>hello world</div>');
+ });
+
+ describe('with non-http links', () => {
+ it.each(validProtocolUrls)('should allow %s', (url) => {
+ createComponent({
+ html: `<a href="${url}">internal link</a>`,
+ });
+ expect(wrapper.html()).toContain(`<a href="${url}">internal link</a>`);
+ });
+
+ it.each(invalidProtocolUrls)('should not allow %s', (url) => {
+ createComponent({
+ html: `<a href="${url}">internal link</a>`,
+ });
+ expect(wrapper.html()).toContain(`<a>internal link</a>`);
+ });
+ });
+
+ describe('handles data attributes correctly', () => {
+ const allowedDataAttrs = ['data-safe', 'data-random'];
+
+ it.each(defaultConfig.FORBID_ATTR)('removes dangerous `%s` attribute', (attr) => {
+ const html = `<a ${attr}="true"></a>`;
+ createComponent({ html });
+
+ expect(wrapper.html()).not.toContain(html);
+ });
+
+ it.each(allowedDataAttrs)('does not remove allowed `%s` attribute', (attr) => {
+ const html = `<a ${attr}="true"></a>`;
+ createComponent({ html });
+
+ expect(wrapper.html()).toContain(html);
+ });
+ });
+ });
+
+ describe('advance config', () => {
+ const template = '<div v-safe-html:[config]="rawHtml"></div>';
+ it('should only allow <b> tags', () => {
+ createComponent({
+ template,
+ html: '<a href="javascript:prompt(1)"><b>click here</b></a>',
+ config: { ALLOWED_TAGS: ['b'] },
+ });
+
+ expect(wrapper.html()).toEqual('<div><b>click here</b></div>');
+ });
+
+ it('should strip all html tags', () => {
+ createComponent({
+ template,
+ html: '<a href="javascript:prompt(1)"><u>click here</u></a>',
+ config: { ALLOWED_TAGS: [] },
+ });
+
+ expect(wrapper.html()).toEqual('<div>click here</div>');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap b/spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap
new file mode 100644
index 00000000000..dd011b9d84e
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`IssuableBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
+"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issuable-blocked-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"issuable-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500 gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
+ <use href=\\"#issue-block\\"></use>
+ </svg>
+ <div class=\\"gl-popover\\">
+ <ul class=\\"gl-list-style-none gl-p-0 gl-mb-0\\">
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/6\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#6</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-3\\">
+ blocking issue title 1
+ </p>
+ </li>
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/5\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#5</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-3\\">
+ blocking issue title 2 + blocking issue title 2 + blocking issue title 2 + bloc…
+ </p>
+ </li>
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/4\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#4</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-0\\">
+ blocking issue title 3
+ </p>
+ </li>
+ </ul>
+ <div class=\\"gl-mt-4\\">
+ <p data-testid=\\"hidden-blocking-count\\" class=\\"gl-mb-3\\">+ 1 more issue</p> <a data-testid=\\"view-all-issues\\" href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/0#related-issues\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">View all blocking issues</a>
+ </div><span data-testid=\\"popover-title\\">Blocked by 4 issues</span>
+ </div>
+</div>"
+`;
diff --git a/spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js b/spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js
new file mode 100644
index 00000000000..d59cbce6633
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js
@@ -0,0 +1,265 @@
+import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } 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';
+import waitForPromises from 'helpers/wait_for_promises';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
+import { blockingIssuablesQueries } from '~/vue_shared/components/issuable_blocked_icon/constants';
+import { issuableTypes } from '~/boards/constants';
+import { truncate } from '~/lib/utils/text_utility';
+import {
+ mockIssue,
+ mockEpic,
+ mockBlockingIssue1,
+ mockBlockingIssue2,
+ mockBlockingEpic1,
+ mockBlockingIssuablesResponse1,
+ mockBlockingIssuablesResponse2,
+ mockBlockingIssuablesResponse3,
+ mockBlockedIssue1,
+ mockBlockedIssue2,
+ mockBlockedEpic1,
+ mockBlockingEpicIssuablesResponse1,
+} from '../../boards/mock_data';
+
+describe('IssuableBlockedIcon', () => {
+ let wrapper;
+ let mockApollo;
+
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
+ const findGlPopover = () => wrapper.findComponent(GlPopover);
+ const findGlLink = () => wrapper.findComponent(GlLink);
+ const findPopoverTitle = () => wrapper.findByTestId('popover-title');
+ const findIssuableTitle = () => wrapper.findByTestId('issuable-title');
+ const findHiddenBlockingCount = () => wrapper.findByTestId('hidden-blocking-count');
+ const findViewAllIssuableLink = () => wrapper.findByTestId('view-all-issues');
+
+ const waitForApollo = async () => {
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+ };
+
+ const mouseenter = async () => {
+ findGlIcon().vm.$emit('mouseenter');
+
+ await nextTick();
+ await waitForApollo();
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapperWithApollo = ({
+ item = mockBlockedIssue1,
+ blockingIssuablesSpy = jest.fn().mockResolvedValue(mockBlockingIssuablesResponse1),
+ issuableItem = mockIssue,
+ issuableType = issuableTypes.issue,
+ } = {}) => {
+ mockApollo = createMockApollo([
+ [blockingIssuablesQueries[issuableType].query, blockingIssuablesSpy],
+ ]);
+
+ Vue.use(VueApollo);
+ wrapper = extendedWrapper(
+ mount(IssuableBlockedIcon, {
+ apolloProvider: mockApollo,
+ propsData: {
+ item: {
+ ...issuableItem,
+ ...item,
+ },
+ uniqueId: 'uniqueId',
+ issuableType,
+ },
+ attachTo: document.body,
+ }),
+ );
+ };
+
+ const createWrapper = ({
+ item = {},
+ queries = {},
+ data = {},
+ loading = false,
+ mockIssuable = mockIssue,
+ issuableType = issuableTypes.issue,
+ } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(IssuableBlockedIcon, {
+ propsData: {
+ item: {
+ ...mockIssuable,
+ ...item,
+ },
+ uniqueId: 'uniqueid',
+ issuableType,
+ },
+ data() {
+ return {
+ ...data,
+ };
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ blockingIssuables: { loading },
+ ...queries,
+ },
+ },
+ },
+ stubs: {
+ GlPopover,
+ },
+ attachTo: document.body,
+ }),
+ );
+ };
+
+ it.each`
+ mockIssuable | issuableType | expectedIcon
+ ${mockIssue} | ${issuableTypes.issue} | ${'issue-block'}
+ ${mockEpic} | ${issuableTypes.epic} | ${'entity-blocked'}
+ `(
+ 'should render blocked icon for $issuableType',
+ ({ mockIssuable, issuableType, expectedIcon }) => {
+ createWrapper({
+ mockIssuable,
+ issuableType,
+ });
+
+ expect(findGlIcon().exists()).toBe(true);
+ const icon = findGlIcon();
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe(expectedIcon);
+ },
+ );
+
+ it('should display a loading spinner while loading', () => {
+ createWrapper({ loading: true });
+
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('should not query for blocking issuables by default', async () => {
+ createWrapperWithApollo();
+
+ expect(findGlPopover().text()).not.toContain(mockBlockingIssue1.title);
+ });
+
+ describe('on mouseenter on blocked icon', () => {
+ it.each`
+ item | issuableType | mockBlockingIssuable | issuableItem | blockingIssuablesSpy
+ ${mockBlockedIssue1} | ${issuableTypes.issue} | ${mockBlockingIssue1} | ${mockIssue} | ${jest.fn().mockResolvedValue(mockBlockingIssuablesResponse1)}
+ ${mockBlockedEpic1} | ${issuableTypes.epic} | ${mockBlockingEpic1} | ${mockEpic} | ${jest.fn().mockResolvedValue(mockBlockingEpicIssuablesResponse1)}
+ `(
+ 'should query for blocking issuables and render the result for $issuableType',
+ async ({ item, issuableType, issuableItem, mockBlockingIssuable, blockingIssuablesSpy }) => {
+ createWrapperWithApollo({
+ item,
+ issuableType,
+ issuableItem,
+ blockingIssuablesSpy,
+ });
+
+ expect(findGlPopover().text()).not.toContain(mockBlockingIssuable.title);
+
+ await mouseenter();
+
+ expect(findGlPopover().exists()).toBe(true);
+ expect(findIssuableTitle().text()).toContain(mockBlockingIssuable.title);
+ expect(wrapper.vm.skip).toBe(true);
+ },
+ );
+
+ it('should emit "blocking-issuables-error" event on query error', async () => {
+ const mockError = new Error('mayday');
+ createWrapperWithApollo({ blockingIssuablesSpy: jest.fn().mockRejectedValue(mockError) });
+
+ await mouseenter();
+
+ const [
+ [
+ {
+ message,
+ error: { networkError },
+ },
+ ],
+ ] = wrapper.emitted('blocking-issuables-error');
+ expect(message).toBe('Failed to fetch blocking issues');
+ expect(networkError).toBe(mockError);
+ });
+
+ describe('with a single blocking issue', () => {
+ beforeEach(async () => {
+ createWrapperWithApollo();
+
+ await mouseenter();
+ });
+
+ it('should render a title of the issuable', async () => {
+ expect(findIssuableTitle().text()).toBe(mockBlockingIssue1.title);
+ });
+
+ it('should render issuable reference and link to the issuable', async () => {
+ const formattedRef = mockBlockingIssue1.reference.split('/')[1];
+
+ expect(findGlLink().text()).toBe(formattedRef);
+ expect(findGlLink().attributes('href')).toBe(mockBlockingIssue1.webUrl);
+ });
+
+ it('should render popover title with correct blocking issuable count', async () => {
+ expect(findPopoverTitle().text()).toBe('Blocked by 1 issue');
+ });
+ });
+
+ describe('when issue has a long title', () => {
+ it('should render a truncated title', async () => {
+ createWrapperWithApollo({
+ blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse2),
+ });
+
+ await mouseenter();
+
+ const truncatedTitle = truncate(
+ mockBlockingIssue2.title,
+ wrapper.vm.$options.textTruncateWidth,
+ );
+ expect(findIssuableTitle().text()).toBe(truncatedTitle);
+ });
+ });
+
+ describe('with more than three blocking issues', () => {
+ beforeEach(async () => {
+ createWrapperWithApollo({
+ item: mockBlockedIssue2,
+ blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse3),
+ });
+
+ await mouseenter();
+ });
+
+ it('matches the snapshot', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('should render popover title with correct blocking issuable count', async () => {
+ expect(findPopoverTitle().text()).toBe('Blocked by 4 issues');
+ });
+
+ it('should render the number of hidden blocking issuables', () => {
+ expect(findHiddenBlockingCount().text()).toBe('+ 1 more issue');
+ });
+
+ it('should link to the blocked issue page at the related issue anchor', async () => {
+ expect(findViewAllIssuableLink().text()).toBe('View all blocking issues');
+ expect(findViewAllIssuableLink().attributes('href')).toBe(
+ `${mockBlockedIssue2.webUrl}#related-issues`,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
index 39a76a51191..6b20f0c77a3 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
@@ -138,7 +138,7 @@ describe('IssuableBody', () => {
wrapper.vm.handleTaskListUpdateSuccess(updatedIssuable);
- expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-success')).toHaveLength(1);
expect(wrapper.emitted('task-list-update-success')[0]).toEqual([updatedIssuable]);
});
});
@@ -147,7 +147,7 @@ describe('IssuableBody', () => {
it('emits `task-list-update-failure` event on component', () => {
wrapper.vm.handleTaskListUpdateFailure();
- expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-failure')).toHaveLength(1);
});
});
});
@@ -202,7 +202,7 @@ describe('IssuableBody', () => {
issuableTitle.vm.$emit('edit-issuable');
- expect(wrapper.emitted('edit-issuable')).toBeTruthy();
+ expect(wrapper.emitted('edit-issuable')).toHaveLength(1);
});
it.each(['keydown-title', 'keydown-description'])(
@@ -227,7 +227,7 @@ describe('IssuableBody', () => {
issuableEditForm.vm.$emit(eventName, eventObj, issuableMeta);
- expect(wrapper.emitted(eventName)).toBeTruthy();
+ expect(wrapper.emitted(eventName)).toHaveLength(1);
expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
},
);
diff --git a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
index a9651cf8bac..43ff68e30b5 100644
--- a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
+++ b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
@@ -14,7 +14,7 @@ import {
sastDiffSuccessMock,
secretDetectionDiffSuccessMock,
} from 'jest/vue_shared/security_reports/mock_data';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import HelpIcon from '~/vue_shared/security_reports/components/help_icon.vue';
import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
@@ -135,8 +135,8 @@ describe('Security reports app', () => {
});
});
- it('calls createFlash correctly', () => {
- expect(createFlash).toHaveBeenCalledWith({
+ it('calls createAlert correctly', () => {
+ expect(createAlert).toHaveBeenCalledWith({
message: SecurityReportsApp.i18n.apiError,
captureError: true,
error: expect.any(Error),
diff --git a/spec/frontend/webhooks/components/form_url_app_spec.js b/spec/frontend/webhooks/components/form_url_app_spec.js
new file mode 100644
index 00000000000..16e0a3f549e
--- /dev/null
+++ b/spec/frontend/webhooks/components/form_url_app_spec.js
@@ -0,0 +1,142 @@
+import { nextTick } from 'vue';
+import { GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
+
+import FormUrlApp from '~/webhooks/components/form_url_app.vue';
+import FormUrlMaskItem from '~/webhooks/components/form_url_mask_item.vue';
+
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('FormUrlApp', () => {
+ let wrapper;
+
+ const createComponent = ({ props } = {}) => {
+ wrapper = shallowMountExtended(FormUrlApp, {
+ propsData: { ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findAllRadioButtons = () => wrapper.findAllComponents(GlFormRadio);
+ const findRadioGroup = () => wrapper.findComponent(GlFormRadioGroup);
+ const findUrlMaskDisable = () => findAllRadioButtons().at(0);
+ const findUrlMaskEnable = () => findAllRadioButtons().at(1);
+ const findAllUrlMaskItems = () => wrapper.findAllComponents(FormUrlMaskItem);
+ const findAddItem = () => wrapper.findComponent(GlLink);
+ const findFormUrl = () => wrapper.findByTestId('form-url');
+ const findFormUrlPreview = () => wrapper.findByTestId('form-url-preview');
+ const findUrlMaskSection = () => wrapper.findByTestId('url-mask-section');
+
+ describe('template', () => {
+ it('renders radio buttons for URL masking', () => {
+ createComponent();
+
+ expect(findAllRadioButtons()).toHaveLength(2);
+ expect(findUrlMaskDisable().text()).toBe(FormUrlApp.i18n.radioFullUrlText);
+ expect(findUrlMaskEnable().text()).toBe(FormUrlApp.i18n.radioMaskUrlText);
+ });
+
+ it('does not render mask section', () => {
+ createComponent();
+
+ expect(findUrlMaskSection().exists()).toBe(false);
+ });
+
+ describe('on radio select', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ findRadioGroup().vm.$emit('input', true);
+ await nextTick();
+ });
+
+ it('renders mask section', () => {
+ expect(findUrlMaskSection().exists()).toBe(true);
+ });
+
+ it('renders an empty mask item by default', () => {
+ expect(findAllUrlMaskItems()).toHaveLength(1);
+
+ const firstItem = findAllUrlMaskItems().at(0);
+ expect(firstItem.props('itemKey')).toBeNull();
+ expect(firstItem.props('itemValue')).toBeNull();
+ });
+ });
+
+ describe('with mask items', () => {
+ const mockItem1 = { key: 'key1', value: 'value1' };
+ const mockItem2 = { key: 'key2', value: 'value2' };
+
+ beforeEach(() => {
+ createComponent({
+ props: { initialUrlVariables: [mockItem1, mockItem2] },
+ });
+ });
+
+ it('renders masked URL preview', async () => {
+ const mockUrl = 'https://test.host/value1?secret=value2';
+
+ findFormUrl().vm.$emit('input', mockUrl);
+ await nextTick();
+
+ expect(findFormUrlPreview().attributes('value')).toBe(
+ 'https://test.host/{key1}?secret={key2}',
+ );
+ });
+
+ it('renders mask items correctly', () => {
+ expect(findAllUrlMaskItems()).toHaveLength(2);
+
+ const firstItem = findAllUrlMaskItems().at(0);
+ expect(firstItem.props('itemKey')).toBe(mockItem1.key);
+ expect(firstItem.props('itemValue')).toBe(mockItem1.value);
+
+ const secondItem = findAllUrlMaskItems().at(1);
+ expect(secondItem.props('itemKey')).toBe(mockItem2.key);
+ expect(secondItem.props('itemValue')).toBe(mockItem2.value);
+ });
+
+ describe('on mask item input', () => {
+ const mockInput = { index: 0, key: 'display', value: 'secret' };
+
+ it('updates mask item', async () => {
+ const firstItem = findAllUrlMaskItems().at(0);
+ firstItem.vm.$emit('input', mockInput);
+ await nextTick();
+
+ expect(firstItem.props('itemKey')).toBe(mockInput.key);
+ expect(firstItem.props('itemValue')).toBe(mockInput.value);
+ });
+ });
+
+ describe('when add item is clicked', () => {
+ it('adds mask item', async () => {
+ findAddItem().vm.$emit('click');
+ await nextTick();
+
+ expect(findAllUrlMaskItems()).toHaveLength(3);
+
+ const lastItem = findAllUrlMaskItems().at(-1);
+ expect(lastItem.props('itemKey')).toBeNull();
+ expect(lastItem.props('itemValue')).toBeNull();
+ });
+ });
+
+ describe('when remove item is clicked', () => {
+ it('removes the correct mask item', async () => {
+ const firstItem = findAllUrlMaskItems().at(0);
+ firstItem.vm.$emit('remove');
+ await nextTick();
+
+ expect(findAllUrlMaskItems()).toHaveLength(1);
+
+ const newFirstItem = findAllUrlMaskItems().at(0);
+ expect(newFirstItem.props('itemKey')).toBe(mockItem2.key);
+ expect(newFirstItem.props('itemValue')).toBe(mockItem2.value);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/webhooks/components/form_url_mask_item_spec.js b/spec/frontend/webhooks/components/form_url_mask_item_spec.js
new file mode 100644
index 00000000000..ab028ef2997
--- /dev/null
+++ b/spec/frontend/webhooks/components/form_url_mask_item_spec.js
@@ -0,0 +1,100 @@
+import { nextTick } from 'vue';
+import { GlButton, GlFormInput } from '@gitlab/ui';
+
+import FormUrlMaskItem from '~/webhooks/components/form_url_mask_item.vue';
+
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('FormUrlMaskItem', () => {
+ let wrapper;
+
+ const defaultProps = {
+ index: 0,
+ };
+ const mockKey = 'key';
+ const mockValue = 'value';
+ const mockInput = 'input';
+
+ const createComponent = ({ props } = {}) => {
+ wrapper = shallowMountExtended(FormUrlMaskItem, {
+ propsData: { ...defaultProps, ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findMaskItemKey = () => wrapper.findByTestId('mask-item-key');
+ const findMaskItemValue = () => wrapper.findByTestId('mask-item-value');
+ const findRemoveButton = () => wrapper.findComponent(GlButton);
+
+ describe('template', () => {
+ it('renders input for key and value', () => {
+ createComponent();
+
+ const keyInput = findMaskItemKey();
+ expect(keyInput.attributes('label')).toBe(FormUrlMaskItem.i18n.keyLabel);
+ expect(keyInput.findComponent(GlFormInput).attributes('name')).toBe(
+ 'hook[url_variables][][key]',
+ );
+
+ const valueInput = findMaskItemValue();
+ expect(valueInput.attributes('label')).toBe(FormUrlMaskItem.i18n.valueLabel);
+ expect(valueInput.findComponent(GlFormInput).attributes('name')).toBe(
+ 'hook[url_variables][][value]',
+ );
+ });
+
+ describe('on key input', () => {
+ beforeEach(async () => {
+ createComponent({ props: { itemKey: mockKey, itemValue: mockValue } });
+
+ findMaskItemKey().findComponent(GlFormInput).vm.$emit('input', mockInput);
+ await nextTick();
+ });
+
+ it('emits input event', () => {
+ expect(wrapper.emitted('input')).toEqual([
+ [{ index: defaultProps.index, key: mockInput, value: mockValue }],
+ ]);
+ });
+ });
+
+ describe('on value input', () => {
+ beforeEach(async () => {
+ createComponent({ props: { itemKey: mockKey, itemValue: mockValue } });
+
+ findMaskItemValue().findComponent(GlFormInput).vm.$emit('input', mockInput);
+ await nextTick();
+ });
+
+ it('emits input event', () => {
+ expect(wrapper.emitted('input')).toEqual([
+ [{ index: defaultProps.index, key: mockKey, value: mockInput }],
+ ]);
+ });
+ });
+
+ it('renders remove button', () => {
+ createComponent();
+
+ expect(findRemoveButton().props('icon')).toBe('remove');
+ });
+
+ describe('when remove button is clicked', () => {
+ const mockIndex = 5;
+
+ beforeEach(async () => {
+ createComponent({ props: { index: mockIndex } });
+
+ findRemoveButton().vm.$emit('click');
+ await nextTick();
+ });
+
+ it('emits remove event', () => {
+ expect(wrapper.emitted('remove')).toEqual([[mockIndex]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index de5a814d3e7..da95b51c0b1 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -54,7 +54,7 @@ describe('App', () => {
});
};
- const findInfiniteScroll = () => wrapper.find(GlInfiniteScroll);
+ const findInfiniteScroll = () => wrapper.findComponent(GlInfiniteScroll);
const setup = async () => {
document.body.dataset.page = 'test-page';
@@ -80,7 +80,7 @@ describe('App', () => {
setup();
});
- const getDrawer = () => wrapper.find(GlDrawer);
+ const getDrawer = () => wrapper.findComponent(GlDrawer);
const getBackdrop = () => wrapper.find('.whats-new-modal-backdrop');
it('contains a drawer', () => {
@@ -173,7 +173,7 @@ describe('App', () => {
value();
- expect(getDrawerBodyHeight).toHaveBeenCalledWith(wrapper.find(GlDrawer).element);
+ expect(getDrawerBodyHeight).toHaveBeenCalledWith(wrapper.findComponent(GlDrawer).element);
expect(actions.setDrawerBodyHeight).toHaveBeenCalledWith(
expect.any(Object),
diff --git a/spec/frontend/work_items/components/work_item_assignees_spec.js b/spec/frontend/work_items/components/work_item_assignees_spec.js
index 28231fad108..1b204b6fd60 100644
--- a/spec/frontend/work_items/components/work_item_assignees_spec.js
+++ b/spec/frontend/work_items/components/work_item_assignees_spec.js
@@ -157,6 +157,14 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().props('viewOnly')).toBe(true);
});
+ it('has a label', () => {
+ createComponent();
+
+ expect(findTokenSelector().props('ariaLabelledby')).toEqual(
+ findAssigneesTitle().attributes('id'),
+ );
+ });
+
describe('when clicking outside the token selector', () => {
function arrange(args) {
createComponent(args);
diff --git a/spec/frontend/work_items/components/work_item_description_spec.js b/spec/frontend/work_items/components/work_item_description_spec.js
index d3165d8dc26..0691fe25e0d 100644
--- a/spec/frontend/work_items/components/work_item_description_spec.js
+++ b/spec/frontend/work_items/components/work_item_description_spec.js
@@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import EditedAt from '~/issues/show/components/edited.vue';
import { updateDraft } from '~/lib/utils/autosave';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
@@ -35,6 +36,7 @@ describe('WorkItemDescription', () => {
const findEditButton = () => wrapper.find('[data-testid="edit-description"]');
const findMarkdownField = () => wrapper.findComponent(MarkdownField);
+ const findEditedAt = () => wrapper.findComponent(EditedAt);
const editDescription = (newText) => wrapper.find('textarea').setValue(newText);
@@ -44,9 +46,9 @@ describe('WorkItemDescription', () => {
const createComponent = async ({
mutationHandler = mutationSuccessHandler,
canUpdate = true,
+ workItemResponse = workItemResponseFactory({ canUpdate }),
isEditing = false,
} = {}) => {
- const workItemResponse = workItemResponseFactory({ canUpdate });
const workItemResponseHandler = jest.fn().mockResolvedValue(workItemResponse);
const { id } = workItemQueryResponse.data.workItem;
@@ -100,6 +102,33 @@ describe('WorkItemDescription', () => {
});
describe('editing description', () => {
+ it('shows edited by text', async () => {
+ const lastEditedAt = '2022-09-21T06:18:42Z';
+ const lastEditedBy = {
+ name: 'Administrator',
+ webPath: '/root',
+ };
+
+ await createComponent({
+ workItemResponse: workItemResponseFactory({
+ lastEditedAt,
+ lastEditedBy,
+ }),
+ });
+
+ expect(findEditedAt().props()).toEqual({
+ updatedAt: lastEditedAt,
+ updatedByName: lastEditedBy.name,
+ updatedByPath: lastEditedBy.webPath,
+ });
+ });
+
+ it('does not show edited by text', async () => {
+ await createComponent();
+
+ expect(findEditedAt().exists()).toBe(false);
+ });
+
it('cancels when clicking cancel', async () => {
await createComponent({
isEditing: true,
diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js
index b047e0dc8d7..aae61b11196 100644
--- a/spec/frontend/work_items/components/work_item_detail_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_spec.js
@@ -1,8 +1,14 @@
-import { GlAlert, GlBadge, GlLoadingIcon, GlSkeletonLoader, GlButton } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlBadge,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+ GlButton,
+ GlEmptyState,
+} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import workItemWeightSubscription from 'ee_component/work_items/graphql/work_item_weight.subscription.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
@@ -14,11 +20,13 @@ import WorkItemState from '~/work_items/components/work_item_state.vue';
import WorkItemTitle from '~/work_items/components/work_item_title.vue';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
import WorkItemLabels from '~/work_items/components/work_item_labels.vue';
+import WorkItemMilestone from '~/work_items/components/work_item_milestone.vue';
import WorkItemInformation from '~/work_items/components/work_item_information.vue';
import { i18n } from '~/work_items/constants';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import workItemDatesSubscription from '~/work_items/graphql/work_item_dates.subscription.graphql';
import workItemTitleSubscription from '~/work_items/graphql/work_item_title.subscription.graphql';
+import workItemAssigneesSubscription from '~/work_items/graphql/work_item_assignees.subscription.graphql';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import updateWorkItemTaskMutation from '~/work_items/graphql/update_work_item_task.mutation.graphql';
import { temporaryConfig } from '~/graphql_shared/issuable_client';
@@ -28,7 +36,7 @@ import {
workItemDatesSubscriptionResponse,
workItemResponseFactory,
workItemTitleSubscriptionResponse,
- workItemWeightSubscriptionResponse,
+ workItemAssigneesSubscriptionResponse,
} from '../mock_data';
describe('WorkItemDetail component', () => {
@@ -46,9 +54,12 @@ describe('WorkItemDetail component', () => {
const successHandler = jest.fn().mockResolvedValue(workItemQueryResponse);
const datesSubscriptionHandler = jest.fn().mockResolvedValue(workItemDatesSubscriptionResponse);
const titleSubscriptionHandler = jest.fn().mockResolvedValue(workItemTitleSubscriptionResponse);
- const weightSubscriptionHandler = jest.fn().mockResolvedValue(workItemWeightSubscriptionResponse);
+ const assigneesSubscriptionHandler = jest
+ .fn()
+ .mockResolvedValue(workItemAssigneesSubscriptionResponse);
const findAlert = () => wrapper.findComponent(GlAlert);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findWorkItemActions = () => wrapper.findComponent(WorkItemActions);
@@ -58,6 +69,7 @@ describe('WorkItemDetail component', () => {
const findWorkItemDueDate = () => wrapper.findComponent(WorkItemDueDate);
const findWorkItemAssignees = () => wrapper.findComponent(WorkItemAssignees);
const findWorkItemLabels = () => wrapper.findComponent(WorkItemLabels);
+ const findWorkItemMilestone = () => wrapper.findComponent(WorkItemMilestone);
const findParent = () => wrapper.find('[data-testid="work-item-parent"]');
const findParentButton = () => findParent().findComponent(GlButton);
const findCloseButton = () => wrapper.find('[data-testid="work-item-close"]');
@@ -72,21 +84,18 @@ describe('WorkItemDetail component', () => {
handler = successHandler,
subscriptionHandler = titleSubscriptionHandler,
confidentialityMock = [updateWorkItemMutation, jest.fn()],
- workItemsMvc2Enabled = false,
- includeWidgets = false,
error = undefined,
+ includeWidgets = false,
+ workItemsMvc2Enabled = false,
} = {}) => {
const handlers = [
[workItemQuery, handler],
[workItemTitleSubscription, subscriptionHandler],
[workItemDatesSubscription, datesSubscriptionHandler],
+ [workItemAssigneesSubscription, assigneesSubscriptionHandler],
confidentialityMock,
];
- if (IS_EE) {
- handlers.push([workItemWeightSubscription, weightSubscriptionHandler]);
- }
-
wrapper = shallowMount(WorkItemDetail, {
apolloProvider: createMockApollo(
handlers,
@@ -107,6 +116,12 @@ describe('WorkItemDetail component', () => {
workItemsMvc2: workItemsMvc2Enabled,
},
hasIssueWeightsFeature: true,
+ hasIterationsFeature: true,
+ projectNamespace: 'namespace',
+ },
+ stubs: {
+ WorkItemWeight: true,
+ WorkItemIteration: true,
},
});
};
@@ -384,13 +399,14 @@ describe('WorkItemDetail component', () => {
});
});
- it('shows an error message when the work item query was unsuccessful', async () => {
+ it('shows empty state with an error message when the work item query was unsuccessful', async () => {
const errorHandler = jest.fn().mockRejectedValue('Oops');
createComponent({ handler: errorHandler });
await waitForPromises();
expect(errorHandler).toHaveBeenCalled();
- expect(findAlert().text()).toBe(i18n.fetchError);
+ expect(findEmptyState().props('description')).toBe(i18n.fetchError);
+ expect(findWorkItemTitle().exists()).toBe(false);
});
it('shows an error message when WorkItemTitle emits an `error` event', async () => {
@@ -413,6 +429,30 @@ describe('WorkItemDetail component', () => {
});
});
+ describe('assignees subscription', () => {
+ describe('when the assignees widget exists', () => {
+ it('calls the assignees subscription', async () => {
+ createComponent();
+ await waitForPromises();
+
+ expect(assigneesSubscriptionHandler).toHaveBeenCalledWith({
+ issuableId: workItemQueryResponse.data.workItem.id,
+ });
+ });
+ });
+
+ describe('when the assignees widget does not exist', () => {
+ it('does not call the assignees subscription', async () => {
+ const response = workItemResponseFactory({ assigneesWidgetPresent: false });
+ const handler = jest.fn().mockResolvedValue(response);
+ createComponent({ handler });
+ await waitForPromises();
+
+ expect(assigneesSubscriptionHandler).not.toHaveBeenCalled();
+ });
+ });
+ });
+
describe('dates subscription', () => {
describe('when the due date widget exists', () => {
it('calls the dates subscription', async () => {
@@ -429,7 +469,7 @@ describe('WorkItemDetail component', () => {
it('does not call the dates subscription', async () => {
const response = workItemResponseFactory({ datesWidgetPresent: false });
const handler = jest.fn().mockResolvedValue(response);
- createComponent({ handler, workItemsMvc2Enabled: true });
+ createComponent({ handler });
await waitForPromises();
expect(datesSubscriptionHandler).not.toHaveBeenCalled();
@@ -440,9 +480,7 @@ describe('WorkItemDetail component', () => {
describe('assignees widget', () => {
it('renders assignees component when widget is returned from the API', async () => {
- createComponent({
- workItemsMvc2Enabled: true,
- });
+ createComponent();
await waitForPromises();
expect(findWorkItemAssignees().exists()).toBe(true);
@@ -450,7 +488,6 @@ describe('WorkItemDetail component', () => {
it('does not render assignees component when widget is not returned from the API', async () => {
createComponent({
- workItemsMvc2Enabled: true,
handler: jest
.fn()
.mockResolvedValue(workItemResponseFactory({ assigneesWidgetPresent: false })),
@@ -463,11 +500,13 @@ describe('WorkItemDetail component', () => {
describe('labels widget', () => {
it.each`
- description | includeWidgets | exists
- ${'renders when widget is returned from API'} | ${true} | ${true}
- ${'does not render when widget is not returned from API'} | ${false} | ${false}
- `('$description', async ({ includeWidgets, exists }) => {
- createComponent({ includeWidgets, workItemsMvc2Enabled: true });
+ description | labelsWidgetPresent | exists
+ ${'renders when widget is returned from API'} | ${true} | ${true}
+ ${'does not render when widget is not returned from API'} | ${false} | ${false}
+ `('$description', async ({ labelsWidgetPresent, exists }) => {
+ const response = workItemResponseFactory({ labelsWidgetPresent });
+ const handler = jest.fn().mockResolvedValue(response);
+ createComponent({ handler });
await waitForPromises();
expect(findWorkItemLabels().exists()).toBe(exists);
@@ -483,7 +522,7 @@ describe('WorkItemDetail component', () => {
it(`${datesWidgetPresent ? 'renders' : 'does not render'} due date component`, async () => {
const response = workItemResponseFactory({ datesWidgetPresent });
const handler = jest.fn().mockResolvedValue(response);
- createComponent({ handler, workItemsMvc2Enabled: true });
+ createComponent({ handler });
await waitForPromises();
expect(findWorkItemDueDate().exists()).toBe(exists);
@@ -491,7 +530,7 @@ describe('WorkItemDetail component', () => {
});
it('shows an error message when it emits an `error` event', async () => {
- createComponent({ workItemsMvc2Enabled: true });
+ createComponent();
await waitForPromises();
const updateError = 'Failed to update';
@@ -502,6 +541,19 @@ describe('WorkItemDetail component', () => {
});
});
+ describe('milestone widget', () => {
+ it.each`
+ description | includeWidgets | exists
+ ${'renders when widget is returned from API'} | ${true} | ${true}
+ ${'does not render when widget is not returned from API'} | ${false} | ${false}
+ `('$description', async ({ includeWidgets, exists }) => {
+ createComponent({ includeWidgets, workItemsMvc2Enabled: true });
+ await waitForPromises();
+
+ expect(findWorkItemMilestone().exists()).toBe(exists);
+ });
+ });
+
describe('work item information', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/work_items/components/work_item_due_date_spec.js b/spec/frontend/work_items/components/work_item_due_date_spec.js
index 1d76154a1f0..701406b9588 100644
--- a/spec/frontend/work_items/components/work_item_due_date_spec.js
+++ b/spec/frontend/work_items/components/work_item_due_date_spec.js
@@ -62,7 +62,7 @@ describe('WorkItemDueDate component', () => {
createComponent({ canUpdate: true, startDate });
});
- it(exists ? 'renders' : 'does not render', () => {
+ it(`${exists ? 'renders' : 'does not render'}`, () => {
expect(findStartDateButton().exists()).toBe(exists);
});
});
@@ -172,7 +172,7 @@ describe('WorkItemDueDate component', () => {
createComponent({ canUpdate: true, dueDate });
});
- it(exists ? 'renders' : 'does not render', () => {
+ it(`${exists ? 'renders' : 'does not render'}`, () => {
expect(findDueDateButton().exists()).toBe(exists);
});
});
diff --git a/spec/frontend/work_items/components/work_item_labels_spec.js b/spec/frontend/work_items/components/work_item_labels_spec.js
index 1d976897c15..e6ff7e8502d 100644
--- a/spec/frontend/work_items/components/work_item_labels_spec.js
+++ b/spec/frontend/work_items/components/work_item_labels_spec.js
@@ -7,10 +7,18 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import labelSearchQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import workItemLabelsSubscription from 'ee_else_ce/work_items/graphql/work_item_labels.subscription.graphql';
+import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import WorkItemLabels from '~/work_items/components/work_item_labels.vue';
-import { i18n } from '~/work_items/constants';
-import { temporaryConfig, resolvers } from '~/graphql_shared/issuable_client';
-import { projectLabelsResponse, mockLabels, workItemQueryResponse } from '../mock_data';
+import { i18n, I18N_WORK_ITEM_ERROR_FETCHING_LABELS } from '~/work_items/constants';
+import {
+ projectLabelsResponse,
+ mockLabels,
+ workItemQueryResponse,
+ workItemResponseFactory,
+ updateWorkItemMutationResponse,
+ workItemLabelsSubscriptionResponse,
+} from '../mock_data';
Vue.use(VueApollo);
@@ -21,32 +29,32 @@ describe('WorkItemLabels component', () => {
const findTokenSelector = () => wrapper.findComponent(GlTokenSelector);
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
-
const findEmptyState = () => wrapper.findByTestId('empty-state');
+ const findLabelsTitle = () => wrapper.findByTestId('labels-title');
+ const workItemQuerySuccess = jest.fn().mockResolvedValue(workItemQueryResponse);
const successSearchQueryHandler = jest.fn().mockResolvedValue(projectLabelsResponse);
+ const successUpdateWorkItemMutationHandler = jest
+ .fn()
+ .mockResolvedValue(updateWorkItemMutationResponse);
+ const subscriptionHandler = jest.fn().mockResolvedValue(workItemLabelsSubscriptionResponse);
const errorHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
const createComponent = ({
- labels = mockLabels,
canUpdate = true,
+ workItemQueryHandler = workItemQuerySuccess,
searchQueryHandler = successSearchQueryHandler,
+ updateWorkItemMutationHandler = successUpdateWorkItemMutationHandler,
} = {}) => {
- const apolloProvider = createMockApollo([[labelSearchQuery, searchQueryHandler]], resolvers, {
- typePolicies: temporaryConfig.cacheConfig.typePolicies,
- });
-
- apolloProvider.clients.defaultClient.writeQuery({
- query: workItemQuery,
- variables: {
- id: workItemId,
- },
- data: workItemQueryResponse.data,
- });
+ const apolloProvider = createMockApollo([
+ [workItemQuery, workItemQueryHandler],
+ [labelSearchQuery, searchQueryHandler],
+ [updateWorkItemMutation, updateWorkItemMutationHandler],
+ [workItemLabelsSubscription, subscriptionHandler],
+ ]);
wrapper = mountExtended(WorkItemLabels, {
propsData: {
- labels,
workItemId,
canUpdate,
fullPath: 'test-project-path',
@@ -60,6 +68,12 @@ describe('WorkItemLabels component', () => {
wrapper.destroy();
});
+ it('has a label', () => {
+ createComponent();
+
+ expect(findTokenSelector().props('ariaLabelledby')).toEqual(findLabelsTitle().attributes('id'));
+ });
+
it('focuses token selector on token selector input event', async () => {
createComponent();
findTokenSelector().vm.$emit('input', [mockLabels[0]]);
@@ -151,7 +165,7 @@ describe('WorkItemLabels component', () => {
findTokenSelector().vm.$emit('focus');
await waitForPromises();
- expect(wrapper.emitted('error')).toEqual([[i18n.fetchError]]);
+ expect(wrapper.emitted('error')).toEqual([[I18N_WORK_ITEM_ERROR_FETCHING_LABELS]]);
});
it('should search for with correct key after text input', async () => {
@@ -163,7 +177,53 @@ describe('WorkItemLabels component', () => {
await waitForPromises();
expect(successSearchQueryHandler).toHaveBeenCalledWith(
- expect.objectContaining({ search: searchKey }),
+ expect.objectContaining({ searchTerm: searchKey }),
);
});
+
+ describe('when clicking outside the token selector', () => {
+ it('calls a mutation with correct variables', () => {
+ createComponent();
+
+ findTokenSelector().vm.$emit('input', [mockLabels[0]]);
+ findTokenSelector().vm.$emit('blur', new FocusEvent({ relatedTarget: null }));
+
+ expect(successUpdateWorkItemMutationHandler).toHaveBeenCalledWith({
+ input: {
+ labelsWidget: { addLabelIds: [mockLabels[0].id], removeLabelIds: [] },
+ id: 'gid://gitlab/WorkItem/1',
+ },
+ });
+ });
+
+ it('emits an error and resets labels if mutation was rejected', async () => {
+ const workItemQueryHandler = jest.fn().mockResolvedValue(workItemResponseFactory());
+
+ createComponent({ updateWorkItemMutationHandler: errorHandler, workItemQueryHandler });
+
+ await waitForPromises();
+
+ const initialLabels = findTokenSelector().props('selectedTokens');
+
+ findTokenSelector().vm.$emit('input', [mockLabels[0]]);
+ findTokenSelector().vm.$emit('blur', new FocusEvent({ relatedTarget: null }));
+
+ await waitForPromises();
+
+ const updatedLabels = findTokenSelector().props('selectedTokens');
+
+ expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
+ expect(updatedLabels).toEqual(initialLabels);
+ });
+
+ it('has a subscription', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(subscriptionHandler).toHaveBeenCalledWith({
+ issuableId: workItemId,
+ });
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js
index 434c1db8a2c..ab3ea623e3e 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js
@@ -28,6 +28,7 @@ describe('WorkItemLinksForm', () => {
listResponse = availableWorkItemsResponse,
typesResponse = projectWorkItemTypesQueryResponse,
parentConfidential = false,
+ hasIterationsFeature = false,
} = {}) => {
wrapper = shallowMountExtended(WorkItemLinksForm, {
apolloProvider: createMockApollo([
@@ -39,6 +40,7 @@ describe('WorkItemLinksForm', () => {
propsData: { issuableGid: 'gid://gitlab/WorkItem/1', parentConfidential },
provide: {
projectPath: 'project/path',
+ hasIterationsFeature,
},
});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js
index 287ec022d3f..e3f3b74f296 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js
@@ -10,8 +10,8 @@ describe('WorkItemLinksMenu', () => {
wrapper = shallowMountExtended(WorkItemLinksMenu);
};
- const findDropdown = () => wrapper.find(GlDropdown);
- const findRemoveDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findRemoveDropdownItem = () => wrapper.findComponent(GlDropdownItem);
beforeEach(async () => {
createComponent();
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
index 876aedff08b..6961996f912 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
@@ -5,7 +5,7 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import issueConfidentialQuery from '~/sidebar/queries/issue_confidential.query.graphql';
+import issueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql';
import WorkItemLinks from '~/work_items/components/work_item_links/work_item_links.vue';
import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
@@ -21,16 +21,29 @@ import {
Vue.use(VueApollo);
-const issueConfidentialityResponse = (confidential = false) => ({
+const issueDetailsResponse = (confidential = false) => ({
data: {
workspace: {
- id: '1',
- __typename: 'Project',
+ id: 'gid://gitlab/Project/1',
issuable: {
- __typename: 'Issue',
id: 'gid://gitlab/Issue/4',
confidential,
+ iteration: {
+ id: 'gid://gitlab/Iteration/1124',
+ title: null,
+ startDate: '2022-06-22',
+ dueDate: '2022-07-19',
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org/-/iterations/1124',
+ iterationCadence: {
+ id: 'gid://gitlab/Iterations::Cadence/1101',
+ title: 'Quod voluptates quidem ea eaque eligendi ex corporis.',
+ __typename: 'IterationCadence',
+ },
+ __typename: 'Iteration',
+ },
+ __typename: 'Issue',
},
+ __typename: 'Project',
},
},
});
@@ -55,14 +68,15 @@ describe('WorkItemLinks', () => {
data = {},
fetchHandler = jest.fn().mockResolvedValue(workItemHierarchyResponse),
mutationHandler = mutationChangeParentHandler,
- confidentialQueryHandler = jest.fn().mockResolvedValue(issueConfidentialityResponse()),
+ issueDetailsQueryHandler = jest.fn().mockResolvedValue(issueDetailsResponse()),
+ hasIterationsFeature = false,
} = {}) => {
mockApollo = createMockApollo(
[
[getWorkItemLinksQuery, fetchHandler],
[changeWorkItemParentMutation, mutationHandler],
[workItemQuery, childWorkItemQueryHandler],
- [issueConfidentialQuery, confidentialQueryHandler],
+ [issueDetailsQuery, issueDetailsQueryHandler],
],
{},
{ addTypename: true },
@@ -77,6 +91,7 @@ describe('WorkItemLinks', () => {
provide: {
projectPath: 'project/path',
iid: '1',
+ hasIterationsFeature,
},
propsData: { issuableId: 1 },
apolloProvider: mockApollo,
@@ -266,7 +281,7 @@ describe('WorkItemLinks', () => {
describe('when parent item is confidential', () => {
it('passes correct confidentiality status to form', async () => {
await createComponent({
- confidentialQueryHandler: jest.fn().mockResolvedValue(issueConfidentialityResponse(true)),
+ issueDetailsQueryHandler: jest.fn().mockResolvedValue(issueDetailsResponse(true)),
});
findToggleAddFormButton().vm.$emit('click');
await nextTick();
diff --git a/spec/frontend/work_items/components/work_item_milestone_spec.js b/spec/frontend/work_items/components/work_item_milestone_spec.js
new file mode 100644
index 00000000000..08cdf62ae52
--- /dev/null
+++ b/spec/frontend/work_items/components/work_item_milestone_spec.js
@@ -0,0 +1,247 @@
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlSkeletonLoader,
+ GlFormGroup,
+ GlDropdownText,
+} from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import WorkItemMilestone from '~/work_items/components/work_item_milestone.vue';
+import { resolvers, temporaryConfig } from '~/graphql_shared/issuable_client';
+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 { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
+import projectMilestonesQuery from '~/sidebar/queries/project_milestones.query.graphql';
+import {
+ projectMilestonesResponse,
+ projectMilestonesResponseWithNoMilestones,
+ mockMilestoneWidgetResponse,
+ workItemResponseFactory,
+ updateWorkItemMutationErrorResponse,
+} from 'jest/work_items/mock_data';
+import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+
+describe('WorkItemMilestone component', () => {
+ Vue.use(VueApollo);
+
+ let wrapper;
+
+ const workItemId = 'gid://gitlab/WorkItem/1';
+ const workItemType = 'Task';
+ const fullPath = 'full-path';
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findNoMilestoneDropdownItem = () => wrapper.findByTestId('no-milestone');
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findFirstDropdownItem = () => findDropdownItems().at(0);
+ const findDropdownTexts = () => wrapper.findAllComponents(GlDropdownText);
+ const findDropdownItemAtIndex = (index) => findDropdownItems().at(index);
+ const findDisabledTextSpan = () => wrapper.findByTestId('disabled-text');
+ const findDropdownTextAtIndex = (index) => findDropdownTexts().at(index);
+ const findInputGroup = () => wrapper.findComponent(GlFormGroup);
+
+ const workItemQueryResponse = workItemResponseFactory({ canUpdate: true, canDelete: true });
+
+ const networkResolvedValue = new Error();
+
+ const successSearchQueryHandler = jest.fn().mockResolvedValue(projectMilestonesResponse);
+ const successSearchWithNoMatchingMilestones = jest
+ .fn()
+ .mockResolvedValue(projectMilestonesResponseWithNoMilestones);
+
+ const showDropdown = () => {
+ findDropdown().vm.$emit('shown');
+ };
+
+ const hideDropdown = () => {
+ findDropdown().vm.$emit('hide');
+ };
+
+ const createComponent = ({
+ canUpdate = true,
+ milestone = mockMilestoneWidgetResponse,
+ searchQueryHandler = successSearchQueryHandler,
+ } = {}) => {
+ const apolloProvider = createMockApollo(
+ [[projectMilestonesQuery, searchQueryHandler]],
+ resolvers,
+ {
+ typePolicies: temporaryConfig.cacheConfig.typePolicies,
+ },
+ );
+
+ apolloProvider.clients.defaultClient.writeQuery({
+ query: workItemQuery,
+ variables: {
+ id: workItemId,
+ },
+ data: workItemQueryResponse.data,
+ });
+
+ wrapper = shallowMountExtended(WorkItemMilestone, {
+ apolloProvider,
+ propsData: {
+ canUpdate,
+ workItemMilestone: milestone,
+ workItemId,
+ workItemType,
+ fullPath,
+ },
+ stubs: {
+ GlDropdown,
+ GlSearchBoxByType,
+ },
+ });
+ };
+
+ it('has "Milestone" label', () => {
+ createComponent();
+
+ expect(findInputGroup().exists()).toBe(true);
+ expect(findInputGroup().attributes('label')).toBe(WorkItemMilestone.i18n.MILESTONE);
+ });
+
+ describe('Default text with canUpdate false and milestone value', () => {
+ describe.each`
+ description | milestone | value
+ ${'when no milestone'} | ${null} | ${WorkItemMilestone.i18n.NONE}
+ ${'when milestone set'} | ${mockMilestoneWidgetResponse} | ${mockMilestoneWidgetResponse.title}
+ `('$description', ({ milestone, value }) => {
+ it(`has a value of "${value}"`, () => {
+ createComponent({ canUpdate: false, milestone });
+
+ expect(findDisabledTextSpan().text()).toBe(value);
+ expect(findDropdown().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('Default text value when canUpdate true and no milestone set', () => {
+ it(`has a value of "Add to milestone"`, () => {
+ createComponent({ canUpdate: true, milestone: null });
+
+ expect(findDropdown().props('text')).toBe(WorkItemMilestone.i18n.MILESTONE_PLACEHOLDER);
+ });
+ });
+
+ describe('Dropdown search', () => {
+ it('has the search box', () => {
+ createComponent();
+
+ expect(findSearchBox().exists()).toBe(true);
+ });
+
+ it('shows no matching results when no items', () => {
+ createComponent({
+ searchQueryHandler: successSearchWithNoMatchingMilestones,
+ });
+
+ expect(findDropdownTextAtIndex(0).text()).toBe(WorkItemMilestone.i18n.NO_MATCHING_RESULTS);
+ expect(findDropdownItems()).toHaveLength(1);
+ expect(findDropdownTexts()).toHaveLength(1);
+ });
+ });
+
+ describe('Dropdown options', () => {
+ beforeEach(() => {
+ createComponent({ canUpdate: true });
+ });
+
+ it('shows the skeleton loader when the items are being fetched on click', async () => {
+ showDropdown();
+ await nextTick();
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
+
+ it('shows the milestones in dropdown when the items have finished fetching', async () => {
+ showDropdown();
+ await waitForPromises();
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ expect(findNoMilestoneDropdownItem().exists()).toBe(true);
+ expect(findDropdownItems()).toHaveLength(
+ projectMilestonesResponse.data.workspace.attributes.nodes.length + 1,
+ );
+ });
+
+ it('changes the milestone to null when clicked on no milestone', async () => {
+ showDropdown();
+ findFirstDropdownItem().vm.$emit('click');
+
+ hideDropdown();
+ await nextTick();
+ expect(findDropdown().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findDropdown().props('loading')).toBe(false);
+ expect(findDropdown().props('text')).toBe(WorkItemMilestone.i18n.MILESTONE_PLACEHOLDER);
+ });
+
+ it('changes the milestone to the selected milestone', async () => {
+ const milestoneIndex = 1;
+ /** the index is -1 since no matching results is also a dropdown item */
+ const milestoneAtIndex =
+ projectMilestonesResponse.data.workspace.attributes.nodes[milestoneIndex - 1];
+ showDropdown();
+
+ await waitForPromises();
+ findDropdownItemAtIndex(milestoneIndex).vm.$emit('click');
+
+ hideDropdown();
+ await waitForPromises();
+
+ expect(findDropdown().props('text')).toBe(milestoneAtIndex.title);
+ });
+ });
+
+ describe('Error handlers', () => {
+ it.each`
+ errorType | expectedErrorMessage | mockValue | resolveFunction
+ ${'graphql error'} | ${'Something went wrong while updating the task. Please try again.'} | ${updateWorkItemMutationErrorResponse} | ${'mockResolvedValue'}
+ ${'network error'} | ${'Something went wrong while updating the task. Please try again.'} | ${networkResolvedValue} | ${'mockRejectedValue'}
+ `(
+ 'emits an error when there is a $errorType',
+ async ({ mockValue, expectedErrorMessage, resolveFunction }) => {
+ createComponent({
+ mutationHandler: jest.fn()[resolveFunction](mockValue),
+ canUpdate: true,
+ });
+
+ showDropdown();
+ findFirstDropdownItem().vm.$emit('click');
+ hideDropdown();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[expectedErrorMessage]]);
+ },
+ );
+ });
+
+ describe('Tracking event', () => {
+ it('tracks updating the milestone', async () => {
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ createComponent({ canUpdate: true });
+
+ showDropdown();
+ findFirstDropdownItem().vm.$emit('click');
+ hideDropdown();
+
+ await waitForPromises();
+
+ expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_milestone', {
+ category: TRACKING_CATEGORY_SHOW,
+ label: 'item_milestone',
+ property: 'type_Task',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/work_items/components/work_item_type_icon_spec.js b/spec/frontend/work_items/components/work_item_type_icon_spec.js
index 95ddfc3980e..182fb0f8cb6 100644
--- a/spec/frontend/work_items/components/work_item_type_icon_spec.js
+++ b/spec/frontend/work_items/components/work_item_type_icon_spec.js
@@ -51,7 +51,7 @@ describe('Work Item type component', () => {
});
it('renders the icon in gray color', () => {
- expect(findIcon().classes()).toContain('gl-text-gray-500');
+ expect(findIcon().classes()).toContain('gl-text-secondary');
});
it('shows tooltip on hover when props passed', () => {
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index e1bc8d2f6b7..ed90b11222a 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -17,6 +17,25 @@ export const mockAssignees = [
},
];
+export const mockLabels = [
+ {
+ __typename: 'Label',
+ id: 'gid://gitlab/Label/1',
+ title: 'Label 1',
+ description: '',
+ color: '#f00',
+ textColor: '#00f',
+ },
+ {
+ __typename: 'Label',
+ id: 'gid://gitlab/Label/2',
+ title: 'Label::2',
+ description: '',
+ color: '#b00',
+ textColor: '#00b',
+ },
+];
+
export const workItemQueryResponse = {
data: {
workItem: {
@@ -50,6 +69,8 @@ export const workItemQueryResponse = {
description: 'some **great** text',
descriptionHtml:
'<p data-sourcepos="1:1-1:19" dir="auto">some <strong>great</strong> text</p>',
+ lastEditedAt: null,
+ lastEditedBy: null,
},
{
__typename: 'WorkItemWidgetAssignees',
@@ -163,9 +184,15 @@ export const workItemResponseFactory = ({
allowsMultipleAssignees = true,
assigneesWidgetPresent = true,
datesWidgetPresent = true,
+ labelsWidgetPresent = true,
weightWidgetPresent = true,
+ milestoneWidgetPresent = true,
+ iterationWidgetPresent = true,
confidential = false,
canInviteMembers = false,
+ allowsScopedLabels = false,
+ lastEditedAt = null,
+ lastEditedBy = null,
parent = mockParent.parent,
} = {}) => ({
data: {
@@ -200,6 +227,8 @@ export const workItemResponseFactory = ({
description: 'some **great** text',
descriptionHtml:
'<p data-sourcepos="1:1-1:19" dir="auto">some <strong>great</strong> text</p>',
+ lastEditedAt,
+ lastEditedBy,
},
assigneesWidgetPresent
? {
@@ -212,6 +241,16 @@ export const workItemResponseFactory = ({
},
}
: { type: 'MOCK TYPE' },
+ labelsWidgetPresent
+ ? {
+ __typename: 'WorkItemWidgetLabels',
+ type: 'LABELS',
+ allowsScopedLabels,
+ labels: {
+ nodes: mockLabels,
+ },
+ }
+ : { type: 'MOCK TYPE' },
datesWidgetPresent
? {
__typename: 'WorkItemWidgetStartAndDueDate',
@@ -227,6 +266,30 @@ export const workItemResponseFactory = ({
weight: 0,
}
: { type: 'MOCK TYPE' },
+ iterationWidgetPresent
+ ? {
+ __typename: 'WorkItemWidgetIteration',
+ type: 'ITERATION',
+ iteration: {
+ description: null,
+ id: 'gid://gitlab/Iteration/1215',
+ iid: '182',
+ title: 'Iteration default title',
+ startDate: '2022-09-22',
+ dueDate: '2022-09-30',
+ },
+ }
+ : { type: 'MOCK TYPE' },
+ milestoneWidgetPresent
+ ? {
+ __typename: 'WorkItemWidgetMilestone',
+ dueDate: null,
+ expired: false,
+ id: 'gid://gitlab/Milestone/30',
+ title: 'v4.0',
+ type: 'MILESTONE',
+ }
+ : { type: 'MOCK TYPE' },
{
__typename: 'WorkItemWidgetHierarchy',
type: 'HIERARCHY',
@@ -331,6 +394,11 @@ export const createWorkItemFromTaskMutationResponse = {
type: 'DESCRIPTION',
description: 'New description',
descriptionHtml: '<p>New description</p>',
+ lastEditedAt: '2022-09-21T06:18:42Z',
+ lastEditedBy: {
+ name: 'Administrator',
+ webPath: '/root',
+ },
},
],
},
@@ -444,6 +512,61 @@ export const workItemWeightSubscriptionResponse = {
},
};
+export const workItemAssigneesSubscriptionResponse = {
+ data: {
+ issuableAssigneesUpdated: {
+ id: 'gid://gitlab/WorkItem/1',
+ widgets: [
+ {
+ __typename: 'WorkItemAssigneesWeight',
+ assignees: {
+ nodes: [mockAssignees[0]],
+ },
+ },
+ ],
+ },
+ },
+};
+
+export const workItemLabelsSubscriptionResponse = {
+ data: {
+ issuableLabelsUpdated: {
+ id: 'gid://gitlab/WorkItem/1',
+ widgets: [
+ {
+ __typename: 'WorkItemWidgetLabels',
+ type: 'LABELS',
+ allowsScopedLabels: false,
+ labels: {
+ nodes: mockLabels,
+ },
+ },
+ ],
+ },
+ },
+};
+
+export const workItemIterationSubscriptionResponse = {
+ data: {
+ issuableIterationUpdated: {
+ id: 'gid://gitlab/WorkItem/1',
+ widgets: [
+ {
+ __typename: 'WorkItemWidgetIteration',
+ iteration: {
+ description: 'Iteration description',
+ dueDate: '2022-07-29',
+ id: 'gid://gitlab/Iteration/1125',
+ iid: '95',
+ startDate: '2022-06-22',
+ title: 'Iteration subcription title',
+ },
+ },
+ ],
+ },
+ },
+};
+
export const workItemHierarchyEmptyResponse = {
data: {
workItem: {
@@ -857,25 +980,6 @@ export const currentUserNullResponse = {
},
};
-export const mockLabels = [
- {
- __typename: 'Label',
- id: 'gid://gitlab/Label/1',
- title: 'Label 1',
- description: '',
- color: '#f00',
- textColor: '#00f',
- },
- {
- __typename: 'Label',
- id: 'gid://gitlab/Label/2',
- title: 'Label 2',
- description: '',
- color: '#b00',
- textColor: '#00b',
- },
-];
-
export const projectLabelsResponse = {
data: {
workspace: {
@@ -887,3 +991,134 @@ export const projectLabelsResponse = {
},
},
};
+
+export const mockIterationWidgetResponse = {
+ description: 'Iteration description',
+ dueDate: '2022-07-19',
+ id: 'gid://gitlab/Iteration/1124',
+ iid: '91',
+ startDate: '2022-06-22',
+ title: 'Iteration title widget',
+};
+
+export const groupIterationsResponse = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Group/22',
+ attributes: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Iteration/1124',
+ title: null,
+ startDate: '2022-06-22',
+ dueDate: '2022-07-19',
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org/-/iterations/1124',
+ iterationCadence: {
+ id: 'gid://gitlab/Iterations::Cadence/1101',
+ title: 'Quod voluptates quidem ea eaque eligendi ex corporis.',
+ __typename: 'IterationCadence',
+ },
+ __typename: 'Iteration',
+ state: 'current',
+ },
+ {
+ id: 'gid://gitlab/Iteration/1185',
+ title: null,
+ startDate: '2022-07-06',
+ dueDate: '2022-07-19',
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org/-/iterations/1185',
+ iterationCadence: {
+ id: 'gid://gitlab/Iterations::Cadence/1144',
+ title: 'Quo velit perspiciatis saepe aut omnis voluptas ab eos.',
+ __typename: 'IterationCadence',
+ },
+ __typename: 'Iteration',
+ state: 'current',
+ },
+ {
+ id: 'gid://gitlab/Iteration/1194',
+ title: null,
+ startDate: '2022-07-06',
+ dueDate: '2022-07-19',
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org/-/iterations/1194',
+ iterationCadence: {
+ id: 'gid://gitlab/Iterations::Cadence/1152',
+ title:
+ 'Minima aut consequatur magnam vero doloremque accusamus maxime repellat voluptatem qui.',
+ __typename: 'IterationCadence',
+ },
+ __typename: 'Iteration',
+ state: 'current',
+ },
+ ],
+ __typename: 'IterationConnection',
+ },
+ __typename: 'Group',
+ },
+ },
+};
+
+export const groupIterationsResponseWithNoIterations = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Group/22',
+ attributes: {
+ nodes: [],
+ __typename: 'IterationConnection',
+ },
+ __typename: 'Group',
+ },
+ },
+};
+
+export const mockMilestoneWidgetResponse = {
+ dueDate: null,
+ expired: false,
+ id: 'gid://gitlab/Milestone/30',
+ title: 'v4.0',
+};
+
+export const projectMilestonesResponse = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Project/1',
+ attributes: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Milestone/5',
+ title: 'v4.0',
+ webUrl: '/gitlab-org/gitlab-test/-/milestones/5',
+ dueDate: null,
+ expired: false,
+ __typename: 'Milestone',
+ state: 'active',
+ },
+ {
+ id: 'gid://gitlab/Milestone/4',
+ title: 'v3.0',
+ webUrl: '/gitlab-org/gitlab-test/-/milestones/4',
+ dueDate: null,
+ expired: false,
+ __typename: 'Milestone',
+ state: 'active',
+ },
+ ],
+ __typename: 'MilestoneConnection',
+ },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const projectMilestonesResponseWithNoMilestones = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Project/1',
+ attributes: {
+ nodes: [],
+ __typename: 'MilestoneConnection',
+ },
+ __typename: 'Project',
+ },
+ },
+};
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
index ab370e2ca8b..66a917d8052 100644
--- a/spec/frontend/work_items/router_spec.js
+++ b/spec/frontend/work_items/router_spec.js
@@ -4,15 +4,19 @@ import VueApollo from 'vue-apollo';
import workItemWeightSubscription from 'ee_component/work_items/graphql/work_item_weight.subscription.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import {
+ workItemAssigneesSubscriptionResponse,
workItemDatesSubscriptionResponse,
workItemResponseFactory,
workItemTitleSubscriptionResponse,
workItemWeightSubscriptionResponse,
+ workItemLabelsSubscriptionResponse,
} from 'jest/work_items/mock_data';
import App from '~/work_items/components/app.vue';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import workItemDatesSubscription from '~/work_items/graphql/work_item_dates.subscription.graphql';
import workItemTitleSubscription from '~/work_items/graphql/work_item_title.subscription.graphql';
+import workItemAssigneesSubscription from '~/work_items/graphql/work_item_assignees.subscription.graphql';
+import workItemLabelsSubscription from 'ee_else_ce/work_items/graphql/work_item_labels.subscription.graphql';
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';
@@ -26,6 +30,10 @@ describe('Work items router', () => {
const datesSubscriptionHandler = jest.fn().mockResolvedValue(workItemDatesSubscriptionResponse);
const titleSubscriptionHandler = jest.fn().mockResolvedValue(workItemTitleSubscriptionResponse);
const weightSubscriptionHandler = jest.fn().mockResolvedValue(workItemWeightSubscriptionResponse);
+ const assigneesSubscriptionHandler = jest
+ .fn()
+ .mockResolvedValue(workItemAssigneesSubscriptionResponse);
+ const labelsSubscriptionHandler = jest.fn().mockResolvedValue(workItemLabelsSubscriptionResponse);
const createComponent = async (routeArg) => {
const router = createRouter('/work_item');
@@ -37,6 +45,8 @@ describe('Work items router', () => {
[workItemQuery, workItemQueryHandler],
[workItemDatesSubscription, datesSubscriptionHandler],
[workItemTitleSubscription, titleSubscriptionHandler],
+ [workItemAssigneesSubscription, assigneesSubscriptionHandler],
+ [workItemLabelsSubscription, labelsSubscriptionHandler],
];
if (IS_EE) {
diff --git a/spec/frontend/work_items_hierarchy/components/app_spec.js b/spec/frontend/work_items_hierarchy/components/app_spec.js
index 1426fbfab80..124ff5f1608 100644
--- a/spec/frontend/work_items_hierarchy/components/app_spec.js
+++ b/spec/frontend/work_items_hierarchy/components/app_spec.js
@@ -32,7 +32,7 @@ describe('WorkItemsHierarchy App', () => {
it('shows when the banner is visible', () => {
createComponent({}, { bannerVisible: true });
- expect(wrapper.find(GlBanner).exists()).toBe(true);
+ expect(wrapper.findComponent(GlBanner).exists()).toBe(true);
});
it('hide when close is called', async () => {
@@ -42,7 +42,7 @@ describe('WorkItemsHierarchy App', () => {
await nextTick();
- expect(wrapper.find(GlBanner).exists()).toBe(false);
+ expect(wrapper.findComponent(GlBanner).exists()).toBe(false);
});
});
diff --git a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
index dca016dc317..084aaa754ab 100644
--- a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
+++ b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
@@ -57,7 +57,7 @@ describe('WorkItemsHierarchy Hierarchy', () => {
});
it('does not render badges', () => {
- expect(wrapper.find(GlBadge).exists()).toBe(false);
+ expect(wrapper.findComponent(GlBadge).exists()).toBe(false);
});
});
diff --git a/spec/frontend_integration/content_editor/content_editor_integration_spec.js b/spec/frontend_integration/content_editor/content_editor_integration_spec.js
index c0c6b5e5dc8..2fa491196ff 100644
--- a/spec/frontend_integration/content_editor/content_editor_integration_spec.js
+++ b/spec/frontend_integration/content_editor/content_editor_integration_spec.js
@@ -12,13 +12,16 @@ describe('content_editor', () => {
let wrapper;
let renderMarkdown;
- const buildWrapper = ({ markdown = '' } = {}) => {
+ const buildWrapper = ({ markdown = '', listeners = {} } = {}) => {
wrapper = mountExtended(ContentEditor, {
propsData: {
renderMarkdown,
uploadsPath: '/',
markdown,
},
+ listeners: {
+ ...listeners,
+ },
});
};
@@ -35,6 +38,10 @@ describe('content_editor', () => {
renderMarkdown = jest.fn();
});
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
describe('when loading initial content', () => {
describe('when the initial content is empty', () => {
it('still hides the loading indicator', async () => {
@@ -169,4 +176,16 @@ This reference tag is a mix of letters and numbers [^footnote].
});
});
});
+
+ it('bubbles up the keydown event captured by ProseMirror', async () => {
+ const keydownHandler = jest.fn();
+
+ buildWrapper({ listeners: { keydown: keydownHandler } });
+
+ await waitUntilContentIsLoaded();
+
+ wrapper.find('[contenteditable]').trigger('keydown', {});
+
+ expect(wrapper.emitted('keydown')).toHaveLength(1);
+ });
});
diff --git a/spec/frontend_integration/diffs/diffs_interopability_spec.js b/spec/frontend_integration/diffs/diffs_interopability_spec.js
index 8e9bc4f0a5f..5017fb8c49d 100644
--- a/spec/frontend_integration/diffs/diffs_interopability_spec.js
+++ b/spec/frontend_integration/diffs/diffs_interopability_spec.js
@@ -121,6 +121,7 @@ describe('diffs third party interoperability', () => {
vm = startDiffsApp();
+ // eslint-disable-next-line jest/no-standalone-expect
await waitFor(() => expect(hasLines(rowSelector)).toBe(true));
});
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 60b3edfc279..b5c2d4da9ac 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -232,11 +232,7 @@ RSpec.describe GitlabSchema do
end
end
- describe '.parse_gid' do
- let_it_be(:global_id) { 'gid://gitlab/TestOne/2147483647' }
-
- subject(:parse_gid) { described_class.parse_gid(global_id) }
-
+ context 'for gid parsing' do
before do
test_base = Class.new
test_one = Class.new(test_base)
@@ -249,66 +245,85 @@ RSpec.describe GitlabSchema do
stub_const('TestThree', test_three)
end
- it 'parses the gid' do
- gid = parse_gid
+ describe '.parse_gid' do
+ let_it_be(:global_id) { 'gid://gitlab/TestOne/2147483647' }
- expect(gid.model_id).to eq '2147483647'
- expect(gid.model_class).to eq TestOne
- end
+ subject(:parse_gid) { described_class.parse_gid(global_id) }
- context 'when gid is malformed' do
- let_it_be(:global_id) { 'malformed://gitlab/TestOne/2147483647' }
+ it 'parses the gid' do
+ gid = parse_gid
- it 'raises an error' do
- expect { parse_gid }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID.")
+ expect(gid.model_id).to eq '2147483647'
+ expect(gid.model_class).to eq TestOne
end
- end
- context 'when using expected_type' do
- it 'accepts a single type' do
- gid = described_class.parse_gid(global_id, expected_type: TestOne)
+ context 'when gid is malformed' do
+ let_it_be(:global_id) { 'malformed://gitlab/TestOne/2147483647' }
- expect(gid.model_class).to eq TestOne
+ it 'raises an error' do
+ expect { parse_gid }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID.")
+ end
end
- it 'accepts an ancestor type' do
- gid = described_class.parse_gid(global_id, expected_type: TestBase)
+ context 'when using expected_type' do
+ it 'accepts a single type' do
+ gid = described_class.parse_gid(global_id, expected_type: TestOne)
- expect(gid.model_class).to eq TestOne
- end
+ expect(gid.model_class).to eq TestOne
+ end
- it 'rejects an unknown type' do
- expect { described_class.parse_gid(global_id, expected_type: TestTwo) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestTwo.")
- end
+ it 'accepts an ancestor type' do
+ gid = described_class.parse_gid(global_id, expected_type: TestBase)
- context 'when expected_type is an array' do
- subject(:parse_gid) { described_class.parse_gid(global_id, expected_type: [TestOne, TestTwo]) }
+ expect(gid.model_class).to eq TestOne
+ end
- context 'when global_id is of type TestOne' do
- it 'returns an object of an expected type' do
- expect(parse_gid.model_class).to eq TestOne
- end
+ it 'rejects an unknown type' do
+ expect { described_class.parse_gid(global_id, expected_type: TestTwo) }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestTwo.")
end
- context 'when global_id is of type TestTwo' do
- let_it_be(:global_id) { 'gid://gitlab/TestTwo/2147483647' }
+ context 'when expected_type is an array' do
+ subject(:parse_gid) { described_class.parse_gid(global_id, expected_type: [TestOne, TestTwo]) }
- it 'returns an object of an expected type' do
- expect(parse_gid.model_class).to eq TestTwo
+ context 'when global_id is of type TestOne' do
+ it 'returns an object of an expected type' do
+ expect(parse_gid.model_class).to eq TestOne
+ end
+ end
+
+ context 'when global_id is of type TestTwo' do
+ let_it_be(:global_id) { 'gid://gitlab/TestTwo/2147483647' }
+
+ it 'returns an object of an expected type' do
+ expect(parse_gid.model_class).to eq TestTwo
+ end
end
- end
- context 'when global_id is of type TestThree' do
- let_it_be(:global_id) { 'gid://gitlab/TestThree/2147483647' }
+ context 'when global_id is of type TestThree' do
+ let_it_be(:global_id) { 'gid://gitlab/TestThree/2147483647' }
- it 'rejects an unknown type' do
- expect { parse_gid }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestOne, TestTwo.")
+ it 'rejects an unknown type' do
+ expect { parse_gid }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestOne, TestTwo.")
+ end
end
end
end
end
+
+ describe '.parse_gids' do
+ let_it_be(:global_ids) { %w[gid://gitlab/TestOne/123 gid://gitlab/TestTwo/456] }
+
+ subject(:parse_gids) { described_class.parse_gids(global_ids, expected_type: [TestOne, TestTwo]) }
+
+ it 'parses the gids' do
+ expect(described_class).to receive(:parse_gid).with('gid://gitlab/TestOne/123', { expected_type: [TestOne, TestTwo] }).and_call_original
+ expect(described_class).to receive(:parse_gid).with('gid://gitlab/TestTwo/456', { expected_type: [TestOne, TestTwo] }).and_call_original
+ expect(parse_gids.map(&:model_id)).to eq %w[123 456]
+ expect(parse_gids.map(&:model_class)).to eq [TestOne, TestTwo]
+ end
+ end
end
end
diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb
index 5e2ab74a0e5..a4a643582f5 100644
--- a/spec/graphql/graphql_triggers_spec.rb
+++ b/spec/graphql/graphql_triggers_spec.rb
@@ -32,6 +32,20 @@ RSpec.describe GraphqlTriggers do
end
end
+ describe '.issuable_description_updated' do
+ it 'triggers the issuableDescriptionUpdated subscription' do
+ work_item = create(:work_item)
+
+ expect(GitlabSchema.subscriptions).to receive(:trigger).with(
+ 'issuableDescriptionUpdated',
+ { issuable_id: work_item.to_gid },
+ work_item
+ ).and_call_original
+
+ GraphqlTriggers.issuable_description_updated(work_item)
+ end
+ end
+
describe '.issuable_labels_updated' do
it 'triggers the issuableLabelsUpdated subscription' do
project = create(:project)
@@ -61,4 +75,32 @@ RSpec.describe GraphqlTriggers do
GraphqlTriggers.issuable_dates_updated(work_item)
end
end
+
+ describe '.merge_request_reviewers_updated' do
+ it 'triggers the mergeRequestReviewersUpdated subscription' do
+ merge_request = build_stubbed(:merge_request)
+
+ expect(GitlabSchema.subscriptions).to receive(:trigger).with(
+ 'mergeRequestReviewersUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ ).and_call_original
+
+ GraphqlTriggers.merge_request_reviewers_updated(merge_request)
+ end
+ end
+
+ describe '.merge_request_merge_status_updated' do
+ it 'triggers the mergeRequestMergeStatusUpdated subscription' do
+ merge_request = build_stubbed(:merge_request)
+
+ expect(GitlabSchema.subscriptions).to receive(:trigger).with(
+ 'mergeRequestMergeStatusUpdated',
+ { issuable_id: merge_request.to_gid },
+ merge_request
+ ).and_call_original
+
+ GraphqlTriggers.merge_request_merge_status_updated(merge_request)
+ end
+ end
end
diff --git a/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
index 412be5f16a4..727db7e2361 100644
--- a/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
+++ b/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject do
describe '#resolve' do
let_it_be(:project) do
- create(:project, ci_job_token_scope_enabled: true).tap(&:save!)
+ create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!)
end
let_it_be(:target_project) { create(:project) }
diff --git a/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
index 0e706ea6e0c..d399e73f394 100644
--- a/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
+++ b/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::RemoveProject do
end
describe '#resolve' do
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let_it_be(:link) do
diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb
index 39fe2a53a68..ee65be1e085 100644
--- a/spec/graphql/mutations/ci/runner/update_spec.rb
+++ b/spec/graphql/mutations/ci/runner/update_spec.rb
@@ -45,7 +45,8 @@ RSpec.describe Mutations::Ci::Runner::Update do
end
context 'when user can update runner', :enable_admin_mode do
- let(:admin_user) { create(:user, :admin) }
+ let_it_be(:admin_user) { create(:user, :admin) }
+
let(:current_ctx) { { current_user: admin_user } }
context 'with valid arguments' do
@@ -134,8 +135,7 @@ RSpec.describe Mutations::Ci::Runner::Update do
response
expect(response[:errors]).to match_array(['user not allowed to assign runner'])
- expect(response[:runner]).to be_an_instance_of(Ci::Runner)
- expect(response[:runner]).not_to have_attributes(expected_attributes)
+ expect(response[:runner]).to be_nil
expect(runner.reload).not_to have_attributes(expected_attributes)
expect(runner.projects).to match_array([project1])
end
@@ -164,7 +164,7 @@ RSpec.describe Mutations::Ci::Runner::Update do
let(:mutation_params) do
{
id: runner.to_global_id,
- associated_projects: ['gid://gitlab/Project/-1']
+ associated_projects: ["gid://gitlab/Project/#{non_existing_record_id}"]
}
end
@@ -191,6 +191,7 @@ RSpec.describe Mutations::Ci::Runner::Update do
end
it 'returns a descriptive error' do
+ expect(response[:runner]).to be_nil
expect(response[:errors]).to contain_exactly(
'Maximum timeout needs to be at least 10 minutes',
'Tags list can not be empty when runner is not allowed to pick untagged jobs'
@@ -202,6 +203,7 @@ RSpec.describe Mutations::Ci::Runner::Update do
it 'returns a descriptive error' do
mutation_params[:maintenance_note] = '1' * 1025
+ expect(response[:runner]).to be_nil
expect(response[:errors]).to contain_exactly(
'Maintenance note is too long (maximum is 1024 characters)'
)
diff --git a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
index ea74e427dd6..9254d84b29c 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Create do
let(:args) { {} }
it_behaves_like 'responding with an incident timeline errors',
- errors: ["Occurred at can't be blank, Note can't be blank, and Note html can't be blank"]
+ errors: ["Occurred at can't be blank and Timeline text can't be blank"]
end
end
diff --git a/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
index 102d33378c6..7081fb7117e 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Update do
end
it 'responds with error' do
- expect(resolve).to eq(timeline_event: nil, errors: ["Note can't be blank"])
+ expect(resolve).to eq(timeline_event: nil, errors: ["Timeline text can't be blank"])
end
end
diff --git a/spec/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/graphql/mutations/namespace/package_settings/update_spec.rb
index 631e02ff3dc..09ac1c99b10 100644
--- a/spec/graphql/mutations/namespace/package_settings/update_spec.rb
+++ b/spec/graphql/mutations/namespace/package_settings/update_spec.rb
@@ -26,8 +26,29 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do
RSpec.shared_examples 'updating the namespace package setting' do
it_behaves_like 'updating the namespace package setting attributes',
- from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
- to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar' }
+ from: {
+ maven_duplicates_allowed: true,
+ maven_duplicate_exception_regex: 'SNAPSHOT',
+ generic_duplicates_allowed: true,
+ generic_duplicate_exception_regex: 'foo',
+ maven_package_requests_forwarding: nil,
+ lock_maven_package_requests_forwarding: false,
+ npm_package_requests_forwarding: nil,
+ lock_npm_package_requests_forwarding: false,
+ pypi_package_requests_forwarding: nil,
+ lock_pypi_package_requests_forwarding: false
+ }, to: {
+ maven_duplicates_allowed: false,
+ maven_duplicate_exception_regex: 'RELEASE',
+ generic_duplicates_allowed: false,
+ generic_duplicate_exception_regex: 'bar',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
+ }
it_behaves_like 'returning a success'
@@ -59,11 +80,19 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do
context 'with existing namespace package setting' do
let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
let_it_be(:params) do
- { namespace_path: namespace.full_path,
+ {
+ namespace_path: namespace.full_path,
maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'RELEASE',
generic_duplicates_allowed: false,
- generic_duplicate_exception_regex: 'bar' }
+ generic_duplicate_exception_regex: 'bar',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
+ }
end
where(:user_role, :shared_examples_name) do
diff --git a/spec/graphql/mutations/work_items/update_widgets_spec.rb b/spec/graphql/mutations/work_items/update_widgets_spec.rb
deleted file mode 100644
index 2e54b81b5c7..00000000000
--- a/spec/graphql/mutations/work_items/update_widgets_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Mutations::WorkItems::UpdateWidgets do
- include GraphqlHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
-
- let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
-
- describe '#resolve' do
- before do
- stub_spam_services
- end
-
- context 'when no work item matches the given id' do
- let(:current_user) { developer }
- let(:gid) { global_id_of(id: non_existing_record_id, model_name: WorkItem.name) }
-
- it 'raises an error' do
- expect { mutation.resolve(id: gid, resolve: true) }.to raise_error(
- Gitlab::Graphql::Errors::ResourceNotAvailable,
- Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
- )
- end
- end
-
- context 'when user can access the requested work item', :aggregate_failures do
- let(:current_user) { developer }
- let(:args) { {} }
-
- let_it_be(:work_item) { create(:work_item, project: project) }
-
- subject { mutation.resolve(id: work_item.to_global_id, **args) }
-
- context 'when `:work_items` is disabled for a project' do
- let_it_be(:project2) { create(:project) }
-
- it 'returns an error' do
- stub_feature_flags(work_items: project2) # only enable `work_item` for project2
-
- expect(subject[:errors]).to contain_exactly('`work_items` feature flag disabled for this project')
- end
- end
-
- context 'when resolved with an input for description widget' do
- let(:args) { { description_widget: { description: "updated description" } } }
-
- it 'returns the updated work item' do
- expect(subject[:work_item].description).to eq("updated description")
- expect(subject[:errors]).to be_empty
- end
- end
- end
- end
-end
diff --git a/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb
new file mode 100644
index 00000000000..2a7d0a8171b
--- /dev/null
+++ b/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::AllJobsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:successful_job) { create(:ci_build, :success, name: 'Job One') }
+ let_it_be(:successful_job_two) { create(:ci_build, :success, name: 'Job Two') }
+ let_it_be(:failed_job) { create(:ci_build, :failed, name: 'Job Three') }
+ let_it_be(:pending_job) { create(:ci_build, :pending, name: 'Job Three') }
+
+ let(:args) { {} }
+ let(:current_user) { create(:admin) }
+
+ subject { resolve_jobs(args) }
+
+ describe '#resolve' do
+ context 'with authorized user' do
+ context 'with statuses argument' do
+ let(:args) { { statuses: [Types::Ci::JobStatusEnum.coerce_isolated_input('SUCCESS')] } }
+
+ it { is_expected.to contain_exactly(successful_job, successful_job_two) }
+ end
+
+ context 'with multiple statuses' do
+ let(:args) do
+ { statuses: [Types::Ci::JobStatusEnum.coerce_isolated_input('SUCCESS'),
+ Types::Ci::JobStatusEnum.coerce_isolated_input('FAILED')] }
+ end
+
+ it { is_expected.to contain_exactly(successful_job, successful_job_two, failed_job) }
+ end
+
+ context 'without statuses argument' do
+ it { is_expected.to contain_exactly(successful_job, successful_job_two, failed_job, pending_job) }
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ private
+
+ def resolve_jobs(args = {}, context = { current_user: current_user })
+ resolve(described_class, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb
index 1bfd6fbf6b9..59ece15b745 100644
--- a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
specify do
expect(described_class).to have_nullable_graphql_type(::Types::Ci::JobTokenScopeType)
@@ -21,7 +21,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
end
it 'returns the same project in the allow list of projects for the Ci Job Token when scope is not enabled' do
- allow(project).to receive(:ci_job_token_scope_enabled?).and_return(false)
+ allow(project).to receive(:ci_outbound_job_token_scope_enabled?).and_return(false)
expect(resolve_scope.all_projects).to contain_exactly(project)
end
@@ -40,7 +40,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
context 'when job token scope is disabled' do
before do
- project.update!(ci_job_token_scope_enabled: false)
+ project.update!(ci_outbound_job_token_scope_enabled: false)
end
it 'resolves projects' do
diff --git a/spec/graphql/resolvers/project_pipeline_schedules_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_schedules_resolver_spec.rb
new file mode 100644
index 00000000000..159335adf79
--- /dev/null
+++ b/spec/graphql/resolvers/project_pipeline_schedules_resolver_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ProjectPipelineSchedulesResolver do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, public_builds: false) }
+
+ before do
+ project.add_owner(user)
+ end
+
+ describe 'With filters' do
+ let(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer) }
+
+ before do
+ pipeline_schedule.pipelines << build(:ci_pipeline, project: project)
+ end
+
+ it 'shows active pipeline schedules' do
+ schedules = resolve_pipeline_schedules
+
+ expect(schedules).to contain_exactly(pipeline_schedule)
+ end
+
+ it 'shows the inactive pipeline schedules' do
+ schedules = resolve_pipeline_schedules(args:
+ { status: ::Types::Ci::PipelineScheduleStatusEnum.values['INACTIVE'].value })
+
+ expect(schedules).to be_empty
+ end
+ end
+
+ def resolve_pipeline_schedules(args: {})
+ resolve(described_class, obj: project, ctx: { current_user: user }, args: args)
+ end
+end
diff --git a/spec/graphql/resolvers/users/participants_resolver_spec.rb b/spec/graphql/resolvers/users/participants_resolver_spec.rb
index 3f04d157410..eb2418b63f4 100644
--- a/spec/graphql/resolvers/users/participants_resolver_spec.rb
+++ b/spec/graphql/resolvers/users/participants_resolver_spec.rb
@@ -10,18 +10,31 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
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) }
+ let_it_be(:public_note_author) { create(:user) }
+ let_it_be(:public_reply_author) { create(:user) }
+ let_it_be(:internal_note_author) { create(:user) }
+ let_it_be(:internal_reply_author) { create(:user) }
+
+ let_it_be(:public_note) { create(:note, project: project, noteable: issue, author: public_note_author) }
+ let_it_be(:internal_note) { create(:note, :confidential, project: project, noteable: issue, author: internal_note_author) }
+
+ let_it_be(:public_reply) { create(:note, noteable: issue, in_reply_to: public_note, project: project, author: public_reply_author) }
+ let_it_be(:internal_reply) { create(:note, :confidential, noteable: issue, in_reply_to: internal_note, project: project, author: internal_reply_author) }
+
+ let_it_be(:note_metadata2) { create(:system_note_metadata, note: public_note) }
+
+ let_it_be(:issue_emoji) { create(:award_emoji, name: 'thumbsup', awardable: issue) }
+ let_it_be(:note_emoji1) { create(:award_emoji, name: 'thumbsup', awardable: public_note) }
+ let_it_be(:note_emoji2) { create(:award_emoji, name: 'thumbsup', awardable: internal_note) }
+ let_it_be(:note_emoji3) { create(:award_emoji, name: 'thumbsup', awardable: public_reply) }
+ let_it_be(:note_emoji4) { create(:award_emoji, name: 'thumbsup', awardable: internal_reply) }
+
+ let_it_be(:issue_emoji_author) { issue_emoji.user }
+ let_it_be(:public_note_emoji_author) { note_emoji1.user }
+ let_it_be(:internal_note_emoji_author) { note_emoji2.user }
+ let_it_be(:public_reply_emoji_author) { note_emoji3.user }
+ let_it_be(:internal_reply_emoji_author) { note_emoji4.user }
subject(:resolved_items) { resolve(described_class, args: {}, ctx: { current_user: current_user }, obj: issue)&.items }
@@ -34,7 +47,16 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
let(:current_user) { nil }
it 'returns only publicly visible participants for this user' do
- is_expected.to match_array([issue.author])
+ is_expected.to match_array(
+ [
+ issue.author,
+ issue_emoji_author,
+ public_note_author,
+ public_note_emoji_author,
+ public_reply_author,
+ public_reply_emoji_author
+ ]
+ )
end
end
@@ -42,15 +64,37 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
let(:current_user) { guest }
it 'returns only publicly visible participants for this user' do
- is_expected.to match_array([issue.author])
+ is_expected.to match_array(
+ [
+ issue.author,
+ issue_emoji_author,
+ public_note_author,
+ public_note_emoji_author,
+ public_reply_author,
+ public_reply_emoji_author
+ ]
+ )
end
end
- context 'when current user has access to confidential notes' do
+ context 'when current user has access to internal notes' do
let(:current_user) { user }
it 'returns all participants for this user' do
- is_expected.to match_array([issue.author, note.author])
+ is_expected.to match_array(
+ [
+ issue.author,
+ issue_emoji_author,
+ public_note_author,
+ public_note_emoji_author,
+ public_reply_author,
+ internal_note_author,
+ internal_note_emoji_author,
+ internal_reply_author,
+ public_reply_emoji_author,
+ internal_reply_emoji_author
+ ]
+ )
end
context 'N+1 queries' do
@@ -64,9 +108,14 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
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))
+ create(:award_emoji, :upvote, awardable: issue)
+ internal_note = create(:note, :confidential, project: project, noteable: issue, author: create(:user))
+ create(:award_emoji, name: 'thumbsup', awardable: internal_note)
+ public_note = create(:note, project: project, noteable: issue, author: create(:user))
+ create(:award_emoji, name: 'thumbsup', awardable: public_note)
- expect { query.call }.not_to exceed_query_limit(control_count)
+ # 1 extra query per source (3 emojis + 2 notes) to fetch participables collection
+ expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(5)
end
it 'does not execute N+1 for system note metadata relation' do
diff --git a/spec/graphql/types/branch_rule_type_spec.rb b/spec/graphql/types/branch_rule_type_spec.rb
deleted file mode 100644
index 277901f00bf..00000000000
--- a/spec/graphql/types/branch_rule_type_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GitlabSchema.types['BranchRule'] do
- include GraphqlHelpers
-
- subject { described_class }
-
- let(:fields) do
- %i[
- name
- branch_protection
- created_at
- updated_at
- ]
- end
-
- specify { is_expected.to require_graphql_authorizations(:read_protected_branch) }
-
- specify { is_expected.to have_graphql_fields(fields) }
-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 18f4d762d1e..569b59d6c70 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(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:current_user) { create(:user) }
let(:query) do
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index b3dee082d1f..ce1558c4097 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Types::Ci::JobType do
active
allow_failure
artifacts
+ browse_artifacts_path
cancelable
commitPath
coverage
@@ -64,4 +65,16 @@ RSpec.describe Types::Ci::JobType do
is_expected.to eq("/#{project.full_path}/-/jobs/#{build.id}")
end
end
+
+ describe '#browse_artifacts_path' do
+ subject { resolve_field(:browse_artifacts_path, build, current_user: user, object_type: described_class) }
+
+ let_it_be(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build, :artifacts, project: project, user: user) }
+
+ it 'returns the path to browse the artifacts of the job' do
+ is_expected.to eq("/#{project.full_path}/-/jobs/#{build.id}/artifacts/browse")
+ end
+ end
end
diff --git a/spec/graphql/types/ci/pipeline_schedule_status_enum_spec.rb b/spec/graphql/types/ci/pipeline_schedule_status_enum_spec.rb
new file mode 100644
index 00000000000..d271e72b17f
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_schedule_status_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::PipelineScheduleStatusEnum do
+ specify { expect(described_class.graphql_name ).to eq('PipelineScheduleStatus') }
+
+ it 'exposes the status of a pipeline schedule' do
+ expect(described_class.values.keys).to match_array(%w[ACTIVE INACTIVE])
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_schedule_type_spec.rb b/spec/graphql/types/ci/pipeline_schedule_type_spec.rb
new file mode 100644
index 00000000000..bf1413ef657
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_schedule_type_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::PipelineScheduleType do
+ include GraphqlHelpers
+
+ specify { expect(described_class.graphql_name).to eq('PipelineSchedule') }
+ specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Ci::PipelineSchedules) }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ id
+ description
+ owner
+ active
+ lastPipeline
+ refForDisplay
+ refPath
+ forTag
+ nextRunAt
+ realNextRun
+ cron
+ cronTimezone
+ userPermissions
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/environment_type_spec.rb b/spec/graphql/types/environment_type_spec.rb
index ae58fe00af7..2605beac95a 100644
--- a/spec/graphql/types/environment_type_spec.rb
+++ b/spec/graphql/types/environment_type_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['Environment'] do
specify { expect(described_class.graphql_name).to eq('Environment') }
- it 'has the expected fields' do
+ it 'includes the expected fields' do
expected_fields = %w[
name id state metrics_dashboard latest_opened_most_severe_alert path external_url deployments
slug createdAt updatedAt autoStopAt autoDeleteAt tier environmentType lastDeployment
]
- expect(described_class).to have_graphql_fields(*expected_fields)
+ expect(described_class).to include_graphql_fields(*expected_fields)
end
specify { expect(described_class).to require_graphql_authorizations(:read_environment) }
diff --git a/spec/graphql/types/namespace/package_settings_type_spec.rb b/spec/graphql/types/namespace/package_settings_type_spec.rb
index f63a0a7010f..5039f2d6153 100644
--- a/spec/graphql/types/namespace/package_settings_type_spec.rb
+++ b/spec/graphql/types/namespace/package_settings_type_spec.rb
@@ -14,4 +14,24 @@ RSpec.describe GitlabSchema.types['PackageSettings'] do
it { is_expected.to have_graphql_type(Types::UntrustedRegexp) }
end
+
+ it 'includes package setting fields' do
+ expected_fields = %w[
+ maven_duplicates_allowed
+ maven_duplicate_exception_regex
+ generic_duplicates_allowed
+ generic_duplicate_exception_regex
+ maven_package_requests_forwarding
+ lock_maven_package_requests_forwarding
+ npm_package_requests_forwarding
+ lock_npm_package_requests_forwarding
+ pypi_package_requests_forwarding
+ lock_pypi_package_requests_forwarding
+ maven_package_requests_forwarding_locked
+ npm_package_requests_forwarding_locked
+ pypi_package_requests_forwarding_locked
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
end
diff --git a/spec/graphql/types/packages/tag_type_spec.rb b/spec/graphql/types/packages/tag_type_spec.rb
index 83b705157d8..ea0801c7a0f 100644
--- a/spec/graphql/types/packages/tag_type_spec.rb
+++ b/spec/graphql/types/packages/tag_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['PackageTag'] do
it 'includes all the package tag fields' do
expected_fields = %w[
- id name created_at updated_at
+ id name created_at updated_at
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/permission_types/ci/pipeline_schedule_type_spec.rb b/spec/graphql/types/permission_types/ci/pipeline_schedule_type_spec.rb
new file mode 100644
index 00000000000..5929d22b202
--- /dev/null
+++ b/spec/graphql/types/permission_types/ci/pipeline_schedule_type_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::PipelineScheduleType do
+ specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Ci::PipelineSchedules) }
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 617cbdb07fe..b435f3ed5ff 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe GitlabSchema.types['Project'] do
cluster_agent cluster_agents agent_configurations
ci_template timelogs merge_commit_template squash_commit_template work_item_types
recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables
- timelog_categories fork_targets branch_rules ci_config_variables
+ timelog_categories fork_targets branch_rules ci_config_variables pipeline_schedules
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -508,20 +508,6 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_resolver(Resolvers::Ci::JobTokenScopeResolver) }
end
- describe 'branch_rules field' do
- subject { described_class.fields['branchRules'] }
-
- let(:br_resolver) { Resolvers::Projects::BranchRulesResolver }
-
- specify do
- is_expected.to have_graphql_type(
- Types::Projects::BranchRuleType.connection_type
- )
- end
-
- specify { is_expected.to have_graphql_resolver(br_resolver) }
- end
-
describe 'agent_configurations' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
diff --git a/spec/graphql/types/projects/branch_rule_type_spec.rb b/spec/graphql/types/projects/branch_rule_type_spec.rb
new file mode 100644
index 00000000000..119ecf8a097
--- /dev/null
+++ b/spec/graphql/types/projects/branch_rule_type_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['BranchRule'] do
+ include GraphqlHelpers
+
+ subject { described_class }
+
+ let(:fields) do
+ %i[
+ name
+ isDefault
+ branch_protection
+ created_at
+ updated_at
+ ]
+ end
+
+ specify { is_expected.to require_graphql_authorizations(:read_protected_branch) }
+
+ specify { is_expected.to have_graphql_fields(fields).at_least }
+end
diff --git a/spec/graphql/types/subscription_type_spec.rb b/spec/graphql/types/subscription_type_spec.rb
index 860cbbf0c15..c23a14deaf3 100644
--- a/spec/graphql/types/subscription_type_spec.rb
+++ b/spec/graphql/types/subscription_type_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe GitlabSchema.types['Subscription'] do
issuable_assignees_updated
issue_crm_contacts_updated
issuable_title_updated
+ issuable_description_updated
issuable_labels_updated
issuable_dates_updated
merge_request_reviewers_updated
+ merge_request_merge_status_updated
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/work_items/widgets/labels_update_input_type_spec.rb b/spec/graphql/types/work_items/widgets/labels_update_input_type_spec.rb
new file mode 100644
index 00000000000..3e5f40bde02
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/labels_update_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::WorkItems::Widgets::LabelsUpdateInputType do
+ it { expect(described_class.graphql_name).to eq('WorkItemWidgetLabelsUpdateInput') }
+
+ it { expect(described_class.arguments.keys).to contain_exactly('addLabelIds', 'removeLabelIds') }
+end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 264431b1bb5..a4b2c963c74 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -486,6 +486,25 @@ RSpec.describe ApplicationHelper do
end
end
+ describe '#gitlab_ui_form_with' do
+ let_it_be(:user) { build(:user) }
+
+ before do
+ allow(helper).to receive(:users_path).and_return('/root')
+ allow(helper).to receive(:form_with).and_call_original
+ end
+
+ it 'adds custom form builder to options and calls `form_with`' do
+ options = { model: user, html: { class: 'foo-bar' } }
+ expected_options = options.merge({ builder: ::Gitlab::FormBuilders::GitlabUiFormBuilder })
+
+ expect do |b|
+ helper.gitlab_ui_form_with(**options, &b)
+ end.to yield_with_args(::Gitlab::FormBuilders::GitlabUiFormBuilder)
+ expect(helper).to have_received(:form_with).with(expected_options)
+ end
+ end
+
describe '#page_class' do
context 'when logged_out_marketing_header experiment is enabled' do
let_it_be(:expected_class) { 'logged-out-marketing-header-candidate' }
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index 1703727db21..c75e9caa77a 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -51,12 +51,13 @@ RSpec.describe ApplicationSettingsHelper do
end
it 'contains rate limit parameters' do
- expect(helper.visible_attributes).to include(*%i(
- issues_create_limit notes_create_limit project_export_limit
- project_download_export_limit project_export_limit project_import_limit
- raw_blob_request_limit group_export_limit group_download_export_limit
- group_import_limit users_get_by_id_limit search_rate_limit search_rate_limit_unauthenticated
- ))
+ expect(helper.visible_attributes).to include(
+ *%i(
+ issues_create_limit notes_create_limit project_export_limit
+ project_download_export_limit project_export_limit project_import_limit
+ raw_blob_request_limit group_export_limit group_download_export_limit
+ group_import_limit users_get_by_id_limit search_rate_limit search_rate_limit_unauthenticated
+ ))
end
context 'when GitLab.com' do
@@ -233,23 +234,24 @@ RSpec.describe ApplicationSettingsHelper do
end
it 'returns available formats correctly' do
- expect(helper.kroki_available_formats).to eq([
- {
- name: 'kroki_formats_blockdiag',
- label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)',
- value: true
- },
- {
- name: 'kroki_formats_bpmn',
- label: 'BPMN',
- value: false
- },
- {
- name: 'kroki_formats_excalidraw',
- label: 'Excalidraw',
- value: false
- }
- ])
+ expect(helper.kroki_available_formats).to eq(
+ [
+ {
+ name: 'kroki_formats_blockdiag',
+ label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)',
+ value: true
+ },
+ {
+ name: 'kroki_formats_bpmn',
+ label: 'BPMN',
+ value: false
+ },
+ {
+ name: 'kroki_formats_excalidraw',
+ label: 'Excalidraw',
+ value: false
+ }
+ ])
end
end
diff --git a/spec/helpers/boards_helper_spec.rb b/spec/helpers/boards_helper_spec.rb
index ccc150c397a..27b7bac5a88 100644
--- a/spec/helpers/boards_helper_spec.rb
+++ b/spec/helpers/boards_helper_spec.rb
@@ -105,10 +105,6 @@ RSpec.describe BoardsHelper do
allow(helper).to receive(:can?).with(user, :admin_issue_board, project).and_return(false)
end
- it 'returns a board_lists_path as lists_endpoint' do
- expect(helper.board_data[:lists_endpoint]).to eq(board_lists_path(project_board))
- end
-
it 'returns board type as parent' do
expect(helper.board_data[:parent]).to eq('project')
end
@@ -189,14 +185,4 @@ RSpec.describe BoardsHelper do
end
end
end
-
- describe '#current_board_json' do
- let(:board_json) { helper.current_board_json }
-
- it 'can serialise with a basic set of attributes' do
- assign(:board, project_board)
-
- expect(board_json).to match_schema('current-board')
- end
- end
end
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index 1950d685980..c9aac63a883 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe Ci::PipelineEditorHelper do
- include CycleAnalyticsHelpers
-
let_it_be(:project) { create(:project) }
describe 'can_view_pipeline_editor?' do
@@ -25,6 +23,30 @@ RSpec.describe Ci::PipelineEditorHelper do
describe '#js_pipeline_editor_data' do
let(:project) { create(:project, :repository) }
+ let(:default_helper_data) do
+ {
+ "ci-config-path": project.ci_config_path_or_default,
+ "ci-examples-help-page-path" => help_page_path('ci/examples/index'),
+ "ci-help-page-path" => help_page_path('ci/index'),
+ "ci-lint-path" => project_ci_lint_path(project),
+ "default-branch" => project.default_branch_or_main,
+ "empty-state-illustration-path" => 'illustrations/empty.svg',
+ "initial-branch-name" => nil,
+ "includes-help-page-path" => help_page_path('ci/yaml/includes'),
+ "lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
+ "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
+ "needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
+ "new-merge-request-path" => '/mock/project/-/merge_requests/new',
+ "pipeline-page-path" => project_pipelines_path(project),
+ "project-path" => project.path,
+ "project-full-path" => project.full_path,
+ "project-namespace" => project.namespace.full_path,
+ "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
+ "uses-external-config" => 'false',
+ "validate-tab-illustration-path" => 'illustrations/validate.svg',
+ "yml-help-page-path" => help_page_path('ci/yaml/index')
+ }
+ end
before do
allow(helper)
@@ -46,29 +68,10 @@ RSpec.describe Ci::PipelineEditorHelper do
context 'with a project with commits' do
it 'returns pipeline editor data' do
- expect(pipeline_editor_data).to eq({
- "ci-config-path": project.ci_config_path_or_default,
- "ci-examples-help-page-path" => help_page_path('ci/examples/index'),
- "ci-help-page-path" => help_page_path('ci/index'),
- "ci-lint-path" => project_ci_lint_path(project),
- "default-branch" => project.default_branch_or_main,
- "empty-state-illustration-path" => 'illustrations/empty.svg',
- "initial-branch-name" => nil,
- "includes-help-page-path" => help_page_path('ci/yaml/includes'),
- "lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
- "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
- "needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
- "new-merge-request-path" => '/mock/project/-/merge_requests/new',
+ expect(pipeline_editor_data).to eq(default_helper_data.merge({
"pipeline_etag" => graphql_etag_pipeline_sha_path(project.commit.sha),
- "pipeline-page-path" => project_pipelines_path(project),
- "project-path" => project.path,
- "project-full-path" => project.full_path,
- "project-namespace" => project.namespace.full_path,
- "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
- "total-branches" => project.repository.branches.length,
- "validate-tab-illustration-path" => 'illustrations/validate.svg',
- "yml-help-page-path" => help_page_path('ci/yaml/index')
- })
+ "total-branches" => project.repository.branches.length
+ }))
end
end
@@ -76,29 +79,10 @@ RSpec.describe Ci::PipelineEditorHelper do
let(:project) { create(:project, :empty_repo) }
it 'returns pipeline editor data' do
- expect(pipeline_editor_data).to eq({
- "ci-config-path": project.ci_config_path_or_default,
- "ci-examples-help-page-path" => help_page_path('ci/examples/index'),
- "ci-help-page-path" => help_page_path('ci/index'),
- "ci-lint-path" => project_ci_lint_path(project),
- "default-branch" => project.default_branch_or_main,
- "empty-state-illustration-path" => 'illustrations/empty.svg',
- "initial-branch-name" => nil,
- "includes-help-page-path" => help_page_path('ci/yaml/includes'),
- "lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
- "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
- "needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
- "new-merge-request-path" => '/mock/project/-/merge_requests/new',
+ expect(pipeline_editor_data).to eq(default_helper_data.merge({
"pipeline_etag" => '',
- "pipeline-page-path" => project_pipelines_path(project),
- "project-path" => project.path,
- "project-full-path" => project.full_path,
- "project-namespace" => project.namespace.full_path,
- "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
- "total-branches" => 0,
- "validate-tab-illustration-path" => 'illustrations/validate.svg',
- "yml-help-page-path" => help_page_path('ci/yaml/index')
- })
+ "total-branches" => 0
+ }))
end
end
@@ -113,11 +97,38 @@ RSpec.describe Ci::PipelineEditorHelper do
end
end
+ context 'with a remote CI config' do
+ before do
+ create(:commit, project: project)
+ project.ci_config_path = 'http://example.com/path/to/ci/config.yml'
+ end
+
+ it 'returns true for uses-external-config in pipeline editor data' do
+ expect(pipeline_editor_data['uses-external-config']).to eq('true')
+ end
+ end
+
+ context 'with a CI config from an external project' do
+ before do
+ create(:commit, project: project)
+ project.ci_config_path = '.gitlab-ci.yml@group/project'
+ end
+
+ it 'returns true for uses-external-config in pipeline editor data' do
+ expect(pipeline_editor_data['uses-external-config']).to eq('true')
+ end
+ end
+
context 'with a non-default branch name' do
let(:user) { create(:user) }
before do
- create_commit('Message', project, user, 'feature')
+ project.repository.commit_files(
+ user,
+ branch_name: 'feature',
+ message: 'Message',
+ actions: [{ action: :create, file_path: 'a/new.file', content: 'This is a new file' }]
+ )
controller.params[:branch_name] = 'feature'
end
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 0cc53da98b2..27738f73ea5 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -227,10 +227,11 @@ RSpec.describe CommitsHelper do
end
it 'returns data for cherry picking into a project' do
- expect(helper.cherry_pick_projects_data(forked_project)).to match_array([
- { id: project.id.to_s, name: project.full_path, refsUrl: refs_project_path(project) },
- { id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) }
- ])
+ expect(helper.cherry_pick_projects_data(forked_project)).to match_array(
+ [
+ { id: project.id.to_s, name: project.full_path, refsUrl: refs_project_path(project) },
+ { id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) }
+ ])
end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index cc6804f0355..7005b3dc53e 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -24,6 +24,45 @@ RSpec.describe EventsHelper do
end
end
+ describe '#localized_action_name' do
+ it 'handles all valid design events' do
+ created, updated, destroyed = %i[created updated destroyed].map do |trait|
+ event = build(:design_event, trait)
+ helper.localized_action_name(event)
+ end
+
+ expect(created).to eq(_('added'))
+ expect(updated).to eq(_('updated'))
+ expect(destroyed).to eq(_('removed'))
+ end
+
+ context 'handles correct base actions' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:trait, :localized_action_name) do
+ :created | s_('Event|created')
+ :updated | s_('Event|opened')
+ :closed | s_('Event|closed')
+ :reopened | s_('Event|opened')
+ :commented | s_('Event|commented on')
+ :merged | s_('Event|accepted')
+ :joined | s_('Event|joined')
+ :left | s_('Event|left')
+ :destroyed | s_('Event|destroyed')
+ :expired | s_('Event|removed due to membership expiration from')
+ :approved | s_('Event|approved')
+ end
+
+ with_them do
+ it 'with correct name and method' do
+ event = build(:event, trait)
+
+ expect(helper.localized_action_name(event)).to eq(localized_action_name)
+ end
+ end
+ end
+ end
+
describe '#event_commit_title' do
let(:message) { 'foo & bar ' + 'A' * 70 + '\n' + 'B' * 80 }
diff --git a/spec/helpers/form_helper_spec.rb b/spec/helpers/form_helper_spec.rb
index 4b76c370810..14ff5d97057 100644
--- a/spec/helpers/form_helper_spec.rb
+++ b/spec/helpers/form_helper_spec.rb
@@ -6,35 +6,85 @@ RSpec.describe FormHelper do
include Devise::Test::ControllerHelpers
describe '#dropdown_max_select' do
+ let(:feature_flag) { :limit_reviewer_and_assignee_size }
+
context "with the :limit_reviewer_and_assignee_size feature flag on" do
+ before do
+ stub_feature_flags(feature_flag => true)
+ end
+
it 'correctly returns the max amount of reviewers or assignees to allow' do
- max = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ max = Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
- expect(helper.dropdown_max_select({}))
+ expect(helper.dropdown_max_select({}, feature_flag))
.to eq(max)
- expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }))
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }, feature_flag))
.to eq(5)
- expect(helper.dropdown_max_select({ 'max-select'.to_sym => max + 5 }))
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => max + 5 }, feature_flag))
.to eq(max)
end
end
context "with the :limit_reviewer_and_assignee_size feature flag off" do
before do
- stub_feature_flags(limit_reviewer_and_assignee_size: false)
+ stub_feature_flags(feature_flag => false)
end
it 'correctly returns the max amount of reviewers or assignees to allow' do
- expect(helper.dropdown_max_select({}))
+ expect(helper.dropdown_max_select({}, feature_flag))
.to eq(nil)
- expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }))
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }, feature_flag))
.to eq(5)
- expect(helper.dropdown_max_select({ 'max-select'.to_sym => 120 }))
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 120 }, feature_flag))
.to eq(120)
end
end
end
+ describe '#assignees_dropdown_options' do
+ let(:merge_request) { build(:merge_request) }
+
+ context "with the :limit_assignees_per_issuable feature flag on" do
+ context "with multiple assignees" do
+ it 'correctly returns the max amount of assignees to allow' do
+ allow(helper).to receive(:merge_request_supports_multiple_assignees?).and_return(true)
+
+ expect(helper.assignees_dropdown_options(:merge_request)[:data][:'max-select'])
+ .to eq(Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS)
+ end
+ end
+
+ context "with only 1 assignee" do
+ it 'correctly returns the max amount of assignees to allow' do
+ expect(helper.assignees_dropdown_options(:merge_request)[:data][:'max-select'])
+ .to eq(1)
+ end
+ end
+ end
+
+ context "with the :limit_assignees_per_issuable feature flag off" do
+ before do
+ stub_feature_flags(limit_assignees_per_issuable: false)
+ end
+
+ context "with multiple assignees" do
+ it 'correctly returns the max amount of assignees to allow' do
+ allow(helper).to receive(:merge_request_supports_multiple_assignees?).and_return(true)
+
+ expect(helper.assignees_dropdown_options(:merge_request)[:data][:'max-select'])
+ .to eq(nil)
+ end
+ end
+
+ context "with only 1 assignee" do
+ it 'correctly returns the max amount of assignees to allow' do
+ expect(helper.assignees_dropdown_options(:merge_request)[:data][:'max-select'])
+ .to eq(1)
+ end
+ end
+ end
+ end
+
describe '#reviewers_dropdown_options' do
let(:merge_request) { build(:merge_request) }
@@ -44,7 +94,7 @@ RSpec.describe FormHelper do
allow(helper).to receive(:merge_request_supports_multiple_reviewers?).and_return(true)
expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select'])
- .to eq(MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS)
+ .to eq(Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS)
end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 00e620832b3..a38483a956d 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -388,22 +388,30 @@ RSpec.describe GroupsHelper do
end
describe '#show_thanks_for_purchase_alert?' do
- subject { helper.show_thanks_for_purchase_alert? }
+ subject { helper.show_thanks_for_purchase_alert?(quantity) }
- it 'returns true with purchased_quantity present in params' do
- allow(controller).to receive(:params) { { purchased_quantity: '1' } }
+ context 'with quantity present' do
+ let(:quantity) { 1 }
- is_expected.to be_truthy
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
end
- it 'returns false with purchased_quantity not present in params' do
- is_expected.to be_falsey
+ context 'with quantity not present' do
+ let(:quantity) { nil }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
end
- it 'returns false with purchased_quantity is empty in params' do
- allow(controller).to receive(:params) { { purchased_quantity: '' } }
+ context 'with quantity empty' do
+ let(:quantity) { '' }
- is_expected.to be_falsey
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
end
end
@@ -523,12 +531,14 @@ RSpec.describe GroupsHelper do
describe '#group_overview_tabs_app_data' do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
+ let_it_be(:initial_sort) { 'created_asc' }
before do
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).with(user, :create_subgroup, group) { true }
allow(helper).to receive(:can?).with(user, :create_projects, group) { true }
+ allow(helper).to receive(:project_list_sort_by).and_return(initial_sort)
end
it 'returns expected hash' do
@@ -537,7 +547,8 @@ RSpec.describe GroupsHelper do
subgroups_and_projects_endpoint: including("/groups/#{group.path}/-/children.json"),
shared_projects_endpoint: including("/groups/#{group.path}/-/shared_projects.json"),
archived_projects_endpoint: including("/groups/#{group.path}/-/children.json?archived=only"),
- current_group_visibility: group.visibility
+ current_group_visibility: group.visibility,
+ initial_sort: initial_sort
}.merge(helper.group_overview_tabs_app_data(group))
)
end
diff --git a/spec/helpers/hooks_helper_spec.rb b/spec/helpers/hooks_helper_spec.rb
index bac73db5dd4..8f438a3ddc8 100644
--- a/spec/helpers/hooks_helper_spec.rb
+++ b/spec/helpers/hooks_helper_spec.rb
@@ -8,6 +8,13 @@ RSpec.describe HooksHelper do
let(:service_hook) { create(:service_hook, integration: create(:drone_ci_integration)) }
let(:system_hook) { create(:system_hook) }
+ describe '#webhook_form_data' do
+ subject { helper.webhook_form_data(project_hook) }
+
+ it { expect(subject[:url]).to eq(project_hook.url) }
+ it { expect(subject[:url_variables]).to be_nil }
+ end
+
describe '#link_to_test_hook' do
let(:trigger) { 'push_events' }
diff --git a/spec/helpers/ide_helper_spec.rb b/spec/helpers/ide_helper_spec.rb
index dc0a234f981..e750379f62d 100644
--- a/spec/helpers/ide_helper_spec.rb
+++ b/spec/helpers/ide_helper_spec.rb
@@ -5,75 +5,113 @@ require 'spec_helper'
RSpec.describe IdeHelper do
describe '#ide_data' do
let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.creator }
before do
- allow(helper).to receive(:current_user).and_return(project.creator)
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:content_security_policy_nonce).and_return('test-csp-nonce')
end
- context 'when instance vars are not set' do
- it 'returns instance data in the hash as nil' do
- expect(helper.ide_data)
- .to include(
- 'branch-name' => nil,
- 'file-path' => nil,
- 'merge-request' => nil,
- 'fork-info' => nil,
- 'project' => nil,
- 'preview-markdown-path' => nil
- )
- end
- end
-
- context 'when instance vars are set' do
- it 'returns instance data in the hash' do
- fork_info = { ide_path: '/test/ide/path' }
+ context 'with vscode_web_ide=true and instance vars set' do
+ before do
+ stub_feature_flags(vscode_web_ide: true)
self.instance_variable_set(:@branch, 'master')
- self.instance_variable_set(:@path, 'foo/bar')
- self.instance_variable_set(:@merge_request, '1')
- self.instance_variable_set(:@fork_info, fork_info)
self.instance_variable_set(:@project, project)
+ end
- serialized_project = API::Entities::Project.represent(project, current_user: project.creator).to_json
-
+ it 'returns hash' do
expect(helper.ide_data)
- .to include(
+ .to eq(
+ 'can-use-new-web-ide' => 'true',
+ 'use-new-web-ide' => 'true',
+ 'user-preferences-path' => profile_preferences_path,
'branch-name' => 'master',
- 'file-path' => 'foo/bar',
- 'merge-request' => '1',
- 'fork-info' => fork_info.to_json,
- 'project' => serialized_project,
- 'preview-markdown-path' => Gitlab::Routing.url_helpers.preview_markdown_project_path(project)
+ 'project-path' => project.path_with_namespace,
+ 'csp-nonce' => 'test-csp-nonce'
)
end
+
+ it 'does not use new web ide if user.use_legacy_web_ide' do
+ allow(user).to receive(:use_legacy_web_ide).and_return(true)
+
+ expect(helper.ide_data).to include('use-new-web-ide' => 'false')
+ end
end
- context 'environments guidance experiment', :experiment do
+ context 'with vscode_web_ide=false' do
before do
- stub_experiments(in_product_guidance_environments_webide: :candidate)
- self.instance_variable_set(:@project, project)
+ stub_feature_flags(vscode_web_ide: false)
end
- context 'when project has no enviornments' do
- it 'enables environment guidance' do
- expect(helper.ide_data).to include('enable-environments-guidance' => 'true')
+ context 'when instance vars are not set' do
+ it 'returns instance data in the hash as nil' do
+ expect(helper.ide_data)
+ .to include(
+ 'can-use-new-web-ide' => 'false',
+ 'use-new-web-ide' => 'false',
+ 'user-preferences-path' => profile_preferences_path,
+ 'branch-name' => nil,
+ 'file-path' => nil,
+ 'merge-request' => nil,
+ 'fork-info' => nil,
+ 'project' => nil,
+ 'preview-markdown-path' => nil
+ )
end
+ end
- context 'and the callout has been dismissed' do
- it 'disables environment guidance' do
- 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')
- end
+ context 'when instance vars are set' do
+ it 'returns instance data in the hash' do
+ fork_info = { ide_path: '/test/ide/path' }
+
+ self.instance_variable_set(:@branch, 'master')
+ self.instance_variable_set(:@path, 'foo/bar')
+ self.instance_variable_set(:@merge_request, '1')
+ self.instance_variable_set(:@fork_info, fork_info)
+ self.instance_variable_set(:@project, project)
+
+ serialized_project = API::Entities::Project.represent(project, current_user: project.creator).to_json
+
+ expect(helper.ide_data)
+ .to include(
+ 'branch-name' => 'master',
+ 'file-path' => 'foo/bar',
+ 'merge-request' => '1',
+ 'fork-info' => fork_info.to_json,
+ 'project' => serialized_project,
+ 'preview-markdown-path' => Gitlab::Routing.url_helpers.preview_markdown_project_path(project)
+ )
end
end
- context 'when the project has environments' do
- it 'disables environment guidance' do
- create(:environment, project: project)
+ context 'environments guidance experiment', :experiment do
+ before do
+ stub_experiments(in_product_guidance_environments_webide: :candidate)
+ self.instance_variable_set(:@project, project)
+ end
+
+ context 'when project has no enviornments' do
+ it 'enables environment guidance' do
+ expect(helper.ide_data).to include('enable-environments-guidance' => 'true')
+ end
+
+ context 'and the callout has been dismissed' do
+ it 'disables environment guidance' do
+ 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')
+ end
+ end
+ end
- expect(helper.ide_data).to include('enable-environments-guidance' => 'false')
+ context 'when the project has environments' do
+ it 'disables environment guidance' do
+ create(:environment, project: project)
+
+ expect(helper.ide_data).to include('enable-environments-guidance' => 'false')
+ end
end
end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 4d47732e008..c753d553371 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -11,10 +11,6 @@ RSpec.describe InviteMembersHelper do
let(:owner) { project.owner }
- before do
- helper.extend(Gitlab::Experimentation::ControllerConcern)
- end
-
describe '#common_invite_group_modal_data' do
it 'has expected common attributes' do
attributes = {
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index bd8af384d40..b32a99fe989 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -64,12 +64,12 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
it 'returns project templates' do
value = [
- "",
- [
- { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
- { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
- ]
- ].to_json
+ "",
+ [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
+ ]
+ ].to_json
expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index a58fe9a6cd9..e5bd8e6532f 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe IssuesHelper do
let(:project) { create(:project) }
- let(:issue) { create :issue, project: project }
- let(:ext_project) { create :redmine_project }
+ let(:issue) { create(:issue, project: project) }
+ let(:ext_project) { create(:project, :with_redmine_integration) }
describe '#work_item_type_icon' do
it 'returns icon of all standard base types' do
diff --git a/spec/helpers/listbox_helper_spec.rb b/spec/helpers/listbox_helper_spec.rb
index 0a27aa04b37..cba00b43ae5 100644
--- a/spec/helpers/listbox_helper_spec.rb
+++ b/spec/helpers/listbox_helper_spec.rb
@@ -26,13 +26,14 @@ RSpec.describe ListboxHelper do
describe '#gl_redirect_listbox_tag' do
it 'creates root element with expected classes' do
- expect(subject.classes).to include(*%w[
- dropdown
- b-dropdown
- gl-new-dropdown
- btn-group
- js-redirect-listbox
- ])
+ expect(subject.classes).to include(
+ *%w[
+ dropdown
+ b-dropdown
+ gl-new-dropdown
+ btn-group
+ js-redirect-listbox
+ ])
end
it 'sets data attributes for items and selected' do
@@ -41,14 +42,15 @@ RSpec.describe ListboxHelper do
end
it 'adds styled button' do
- expect(subject.at_css('button').classes).to include(*%w[
- btn
- dropdown-toggle
- btn-default
- btn-md
- gl-button
- gl-dropdown-toggle
- ])
+ expect(subject.at_css('button').classes).to include(
+ *%w[
+ btn
+ dropdown-toggle
+ btn-default
+ btn-md
+ gl-button
+ gl-dropdown-toggle
+ ])
end
it 'sets button text to selected item' do
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 8a7a6d003f4..a2e34471324 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -425,21 +425,21 @@ FooBar
end
it 'delegates to #markdown_unsafe when file name corresponds to Markdown' do
- expect(helper).to receive(:gitlab_markdown?).with('foo.md').and_return(true)
+ expect(Gitlab::MarkupHelper).to receive(:gitlab_markdown?).with('foo.md').and_return(true)
expect(helper).to receive(:markdown_unsafe).and_return('NOEL')
expect(helper.markup('foo.md', content)).to eq('NOEL')
end
it 'delegates to #asciidoc_unsafe when file name corresponds to AsciiDoc' do
- expect(helper).to receive(:asciidoc?).with('foo.adoc').and_return(true)
+ expect(Gitlab::MarkupHelper).to receive(:asciidoc?).with('foo.adoc').and_return(true)
expect(helper).to receive(:asciidoc_unsafe).and_return('NOEL')
expect(helper.markup('foo.adoc', content)).to eq('NOEL')
end
it 'uses passed in rendered content' do
- expect(helper).not_to receive(:gitlab_markdown?)
+ expect(Gitlab::MarkupHelper).not_to receive(:gitlab_markdown?)
expect(helper).not_to receive(:markdown_unsafe)
expect(helper.markup('foo.md', content, rendered: '<p>NOEL</p>')).to eq('<p>NOEL</p>')
@@ -562,20 +562,6 @@ FooBar
shared_examples_for 'common markdown examples' do
let(:project_base) { build(:project, :repository) }
- it 'displays inline code' do
- object = create_object('Text with `inline code`')
- expected = 'Text with <code>inline code</code>'
-
- expect(first_line_in_markdown(object, attribute, 100, project: project)).to match(expected)
- end
-
- it 'truncates the text with multiple paragraphs' do
- object = create_object("Paragraph 1\n\nParagraph 2")
- expected = 'Paragraph 1...'
-
- expect(first_line_in_markdown(object, attribute, 100, project: project)).to match(expected)
- end
-
it 'displays the first line of a code block' do
object = create_object("```\nCode block\nwith two lines\n```")
expected = %r{<pre.+><code><span class="line">Code block\.\.\.</span>\n</code></pre>}
@@ -591,18 +577,6 @@ FooBar
expect(first_line_in_markdown(object, attribute, 150, project: project)).to match(expected)
end
- it 'preserves a link href when link text is truncated' do
- text = 'The quick brown fox jumped over the lazy dog' # 44 chars
- link_url = 'http://example.com/foo/bar/baz' # 30 chars
- input = "#{text}#{text}#{text} #{link_url}" # 163 chars
- expected_link_text = 'http://example...</a>'
-
- object = create_object(input)
-
- expect(first_line_in_markdown(object, attribute, 150, project: project)).to match(link_url)
- expect(first_line_in_markdown(object, attribute, 150, project: project)).to match(expected_link_text)
- end
-
it 'preserves code color scheme' do
object = create_object("```ruby\ndef test\n 'hello world'\nend\n```")
expected = "\n<pre class=\"code highlight js-syntax-highlight language-ruby\">" \
@@ -669,40 +643,6 @@ FooBar
expect(result).to include(html)
end
- it 'truncates Markdown properly' do
- object = create_object("@#{user.username}, can you look at this?\nHello world\n")
- actual = first_line_in_markdown(object, attribute, 100, project: project)
-
- doc = Nokogiri::HTML.parse(actual)
-
- # Make sure we didn't create invalid markup
- expect(doc.errors).to be_empty
-
- # Leading user link
- expect(doc.css('a').length).to eq(1)
- expect(doc.css('a')[0].attr('href')).to eq user_path(user)
- expect(doc.css('a')[0].text).to eq "@#{user.username}"
-
- expect(doc.content).to eq "@#{user.username}, can you look at this?..."
- end
-
- it 'truncates Markdown with emoji properly' do
- object = create_object("foo :wink:\nbar :grinning:")
- actual = first_line_in_markdown(object, attribute, 100, project: project)
-
- doc = Nokogiri::HTML.parse(actual)
-
- # Make sure we didn't create invalid markup
- # But also account for the 2 errors caused by the unknown `gl-emoji` elements
- expect(doc.errors.length).to eq(2)
-
- expect(doc.css('gl-emoji').length).to eq(2)
- expect(doc.css('gl-emoji')[0].attr('data-name')).to eq 'wink'
- expect(doc.css('gl-emoji')[1].attr('data-name')).to eq 'grinning'
-
- expect(doc.content).to eq "foo 😉\nbar 😀"
- end
-
it 'does not post-process truncated text', :request_store do
object = create_object("hello \n\n [Test](README.md)")
diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb
new file mode 100644
index 00000000000..f7f3b7d8227
--- /dev/null
+++ b/spec/helpers/milestones_helper_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MilestonesHelper do
+ let_it_be(:issuable) { build(:merge_request) }
+
+ describe '#milestone_header_class' do
+ using RSpec::Parameterized::TableSyntax
+
+ color_primary = 'gl-bg-blue-500 gl-text-white'
+ border_empty = 'gl-border-bottom-0 gl-rounded-base'
+
+ where(:primary, :issuables, :header_color, :header_border) do
+ true | [issuable] | color_primary | ''
+ true | [] | color_primary | border_empty
+ false | [] | '' | border_empty
+ false | [issuable] | '' | ''
+ end
+
+ with_them do
+ subject { helper.milestone_header_class(primary, issuables) }
+
+ it { is_expected.to eq("#{header_color} #{header_border} gl-display-flex") }
+ end
+ end
+
+ describe '#milestone_counter_class' do
+ context 'when primary is set to true' do
+ subject { helper.milestone_counter_class(true) }
+
+ it { is_expected.to eq('gl-text-white') }
+ end
+
+ context 'when primary is set to false' do
+ subject { helper.milestone_counter_class(false) }
+
+ it { is_expected.to eq('gl-text-gray-500') }
+ end
+ end
+end
diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb
index f0ad2038347..4a37e17fb08 100644
--- a/spec/helpers/nav_helper_spec.rb
+++ b/spec/helpers/nav_helper_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe NavHelper do
using RSpec::Parameterized::TableSyntax
where path: %w(
- merge_requests#show
+ projects/merge_requests#show
projects/merge_requests/conflicts#show
issues#show
milestones#show
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index a9db2a1c008..07c2d50f70a 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -825,7 +825,7 @@ RSpec.describe ProjectsHelper do
end
context 'gitaly is working appropriately' do
- let(:license) { Licensee::License.new('mit') }
+ let(:license) { ::Gitlab::Git::DeclaredLicense.new(key: 'mit', name: 'MIT License') }
before do
expect(repository).to receive(:license).and_return(license)
@@ -1336,4 +1336,24 @@ RSpec.describe ProjectsHelper do
)
end
end
+
+ describe '#localized_project_human_access' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:key, :localized_project_human_access) do
+ Gitlab::Access::NO_ACCESS | _('No access')
+ Gitlab::Access::MINIMAL_ACCESS | _("Minimal Access")
+ Gitlab::Access::GUEST | _('Guest')
+ Gitlab::Access::REPORTER | _('Reporter')
+ Gitlab::Access::DEVELOPER | _('Developer')
+ Gitlab::Access::MAINTAINER | _('Maintainer')
+ Gitlab::Access::OWNER | _('Owner')
+ end
+
+ with_them do
+ it 'with correct key' do
+ expect(helper.localized_project_human_access(key)).to eq(localized_project_human_access)
+ end
+ end
+ end
end
diff --git a/spec/helpers/recaptcha_helper_spec.rb b/spec/helpers/recaptcha_helper_spec.rb
index 8ad91a0a217..2c327431437 100644
--- a/spec/helpers/recaptcha_helper_spec.rb
+++ b/spec/helpers/recaptcha_helper_spec.rb
@@ -9,21 +9,70 @@ RSpec.describe RecaptchaHelper, type: :helper do
allow(helper).to receive(:session) { session }
end
- describe '.show_recaptcha_sign_up?' do
- context 'when reCAPTCHA is disabled' do
- it 'returns false' do
- stub_application_setting(recaptcha_enabled: false)
+ shared_examples 'Gitlab QA bypass' do
+ context 'when GITLAB_QA_USER_AGENT env var is present' do
+ using RSpec::Parameterized::TableSyntax
- expect(helper.show_recaptcha_sign_up?).to be_falsey
+ where(:dot_com, :user_agent, :qa_user_agent, :result) do
+ false | 'qa_user_agent' | 'qa_user_agent' | true
+ true | nil | 'qa_user_agent' | true
+ true | '' | 'qa_user_agent' | true
+ true | 'qa_user_agent' | '' | true
+ true | 'qa_user_agent' | nil | true
+ true | 'qa_user_agent' | 'qa_user_agent' | false
end
- end
- context 'when reCAPTCHA is enabled' do
- it 'returns true' do
- stub_application_setting(recaptcha_enabled: true)
+ with_them do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(dot_com)
+ stub_env('GITLAB_QA_USER_AGENT', qa_user_agent)
+
+ request_double = instance_double(ActionController::TestRequest, user_agent: user_agent)
+ allow(helper).to receive(:request).and_return(request_double)
+ end
- expect(helper.show_recaptcha_sign_up?).to be_truthy
+ it { is_expected.to eq result }
end
end
end
+
+ describe '.show_recaptcha_sign_up?' do
+ let(:setting_state) { true }
+
+ before do
+ stub_application_setting(recaptcha_enabled: setting_state)
+ end
+
+ subject { helper.show_recaptcha_sign_up? }
+
+ it { is_expected.to eq true }
+
+ context 'when setting is disabled' do
+ let(:setting_state) { false }
+
+ it { is_expected.to eq false }
+ end
+
+ include_examples 'Gitlab QA bypass'
+ end
+
+ describe '.recaptcha_enabled_on_login?' do
+ let(:setting_state) { true }
+
+ before do
+ stub_application_setting(login_recaptcha_protection_enabled: setting_state)
+ end
+
+ subject { helper.recaptcha_enabled_on_login? }
+
+ it { is_expected.to eq true }
+
+ context 'when setting is disabled' do
+ let(:setting_state) { false }
+
+ it { is_expected.to eq false }
+ end
+
+ include_examples 'Gitlab QA bypass'
+ end
end
diff --git a/spec/helpers/releases_helper_spec.rb b/spec/helpers/releases_helper_spec.rb
index 59a92c067f4..5a9deb5c63b 100644
--- a/spec/helpers/releases_helper_spec.rb
+++ b/spec/helpers/releases_helper_spec.rb
@@ -49,6 +49,12 @@ RSpec.describe ReleasesHelper do
expect(helper.data_for_releases_page[:new_release_path]).to eq(new_project_release_path(project))
end
end
+
+ context 'new releases redirect new milestone creation' do
+ it 'redirects new_milestone_path back to the release page' do
+ expect(helper.data_for_new_release_page[:new_milestone_path]).to include('redirect_path')
+ end
+ end
end
describe '#data_for_edit_release_page' do
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index ad0705e4fbf..20718ad2f48 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -776,7 +776,7 @@ RSpec.describe SearchHelper do
end
context 'project data' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:project_metadata) { { project_path: project.path, issues_path: "/issues" } }
let(:scope) { 'issues' }
let(:code_search) { true }
@@ -848,4 +848,295 @@ RSpec.describe SearchHelper do
end
end
end
+
+ describe '.search_navigation' do
+ using RSpec::Parameterized::TableSyntax
+ let(:user) { build(:user) }
+ let_it_be(:project) { build(:project) }
+
+ before do
+ allow(self).to receive(:current_user).and_return(user)
+ allow(self).to receive(:can?).and_return(true)
+ allow(self).to receive(:project_search_tabs?).and_return(false)
+ allow(self).to receive(:feature_flag_tab_enabled?).and_return(false)
+ end
+
+ context 'projects' do
+ where(:global_project, :condition) do
+ nil | true
+ ref(:project) | false
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ @project = global_project
+
+ expect(search_navigation[:projects][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'code' do
+ where(:feature_flag_tab_enabled, :show_elasticsearch_tabs, :project_search_tabs, :condition) do
+ false | false | false | false
+ true | true | true | true
+ true | false | false | true
+ false | true | false | true
+ false | false | true | true
+ true | false | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
+ allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_code_tab).and_return(feature_flag_tab_enabled)
+ allow(self).to receive(:project_search_tabs?).with(:blobs).and_return(project_search_tabs)
+
+ expect(search_navigation[:blobs][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'issues' do
+ where(:feature_flag_tab_enabled, :project_search_tabs, :condition) do
+ false | false | false
+ true | true | true
+ true | false | true
+ false | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_issues_tab).and_return(feature_flag_tab_enabled)
+ allow(self).to receive(:project_search_tabs?).with(:issues).and_return(project_search_tabs)
+
+ expect(search_navigation[:issues][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'merge requests' do
+ where(:feature_flag_tab_enabled, :project_search_tabs, :condition) do
+ false | false | false
+ true | true | true
+ true | false | true
+ false | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_merge_requests_tab).and_return(feature_flag_tab_enabled)
+ allow(self).to receive(:project_search_tabs?).with(:merge_requests).and_return(project_search_tabs)
+
+ expect(search_navigation[:merge_requests][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'wiki' do
+ where(:project_search_tabs, :show_elasticsearch_tabs, :condition) do
+ false | false | false
+ true | true | true
+ true | false | true
+ false | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
+ allow(self).to receive(:project_search_tabs?).with(:wiki).and_return(project_search_tabs)
+
+ expect(search_navigation[:wiki_blobs][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'commits' do
+ where(:feature_flag_tab_enabled, :show_elasticsearch_tabs, :project_search_tabs, :condition) do
+ false | false | false | false
+ true | true | true | true
+ true | false | false | false
+ false | true | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
+ allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_commits_tab).and_return(feature_flag_tab_enabled)
+ allow(self).to receive(:project_search_tabs?).with(:commits).and_return(project_search_tabs)
+
+ expect(search_navigation[:commits][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'comments' do
+ where(:show_elasticsearch_tabs, :project_search_tabs, :condition) do
+ true | true | true
+ false | false | false
+ true | false | true
+ false | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
+ allow(self).to receive(:project_search_tabs?).with(:notes).and_return(project_search_tabs)
+
+ expect(search_navigation[:notes][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'milestones' do
+ where(:global_project, :project_search_tabs, :condition) do
+ ref(:project) | true | true
+ nil | false | true
+ ref(:project) | false | false
+ nil | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ @project = global_project
+ allow(self).to receive(:project_search_tabs?).with(:milestones).and_return(project_search_tabs)
+
+ expect(search_navigation[:milestones][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'users' do
+ where(:show_user_search_tab, :condition) do
+ true | true
+ false | false
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ allow(self).to receive(:show_user_search_tab?).and_return(show_user_search_tab)
+
+ expect(search_navigation[:users][:condition]).to eq(condition)
+ end
+ end
+ end
+
+ context 'snippet_titles' do
+ where(:global_project, :global_show_snippets, :condition) do
+ ref(:project) | true | false
+ nil | false | false
+ ref(:project) | false | false
+ nil | true | true
+ end
+
+ with_them do
+ it 'data item condition is set correctly' do
+ @show_snippets = global_show_snippets
+ @project = global_project
+
+ expect(search_navigation[:snippet_titles][:condition]).to eq(condition)
+ end
+ end
+ end
+ end
+
+ describe '.search_navigation_json' do
+ using RSpec::Parameterized::TableSyntax
+ context 'with data' do
+ example_data_1 = {
+ projects: { label: _("Projects"), condition: true },
+ blobs: { label: _("Code"), condition: false }
+ }
+
+ example_data_2 = {
+ projects: { label: _("Projects"), condition: false },
+ blobs: { label: _("Code"), condition: false }
+ }
+
+ example_data_3 = {
+ projects: { label: _("Projects"), condition: true },
+ blobs: { label: _("Code"), condition: true },
+ epics: { label: _("Epics"), condition: true }
+ }
+
+ where(:data, :matcher) do
+ example_data_1 | -> { include("projects") }
+ example_data_2 | -> { eq("{}") }
+ example_data_3 | -> { include("projects", "blobs", "epics") }
+ end
+
+ with_them do
+ it 'converts correctly' do
+ allow(self).to receive(:search_navigation).with(no_args).and_return(data)
+
+ expect(search_navigation_json).to instance_exec(&matcher)
+ end
+ end
+ end
+ end
+
+ describe '.search_filter_link_json' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'data' do
+ where(:scope, :label, :data, :search, :active_scope) do
+ "projects" | "Projects" | { qa_selector: 'projects_tab' } | nil | "projects"
+ "snippet_titles" | "Titles and Descriptions" | nil | { snippets: "test" } | "code"
+ "projects" | "Projects" | { qa_selector: 'projects_tab' } | nil | "issue"
+ "snippet_titles" | "Titles and Descriptions" | nil | { snippets: "test" } | "snippet_titles"
+ end
+
+ with_them do
+ it 'converts correctly' do
+ @timeout = false
+ @scope = active_scope
+ @search_results = double
+ dummy_count = 1000
+ allow(self).to receive(:search_path).with(any_args).and_return("link test")
+
+ allow(@search_results).to receive(:formatted_count).with(scope).and_return(dummy_count)
+ allow(self).to receive(:search_count_path).with(any_args).and_return("test count link")
+
+ current_scope = scope == active_scope
+
+ expected = {
+ label: label,
+ scope: scope,
+ data: data,
+ link: "link test",
+ active: current_scope
+ }
+
+ expected[:count] = dummy_count if current_scope
+ expected[:count_link] = "test count link" unless current_scope
+
+ expect(search_filter_link_json(scope, label, data, search)).to eq(expected)
+ end
+ end
+ end
+ end
+
+ describe 'show_elasticsearch_tabs' do
+ subject { search_service.show_elasticsearch_tabs? }
+
+ let(:user) { build(:user) }
+
+ before do
+ allow(self).to receive(:current_user).and_return(user)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ describe 'show_epics' do
+ subject { search_service.show_epics? }
+
+ let(:user) { build(:user) }
+
+ before do
+ allow(self).to receive(:current_user).and_return(user)
+ end
+
+ it { is_expected.to eq(false) }
+ end
end
diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb
index 15424425060..c7b8225b866 100644
--- a/spec/helpers/sessions_helper_spec.rb
+++ b/spec/helpers/sessions_helper_spec.rb
@@ -92,6 +92,12 @@ RSpec.describe SessionsHelper do
end
context 'when an email address is very short' do
+ let(:email) { 'a@b.c' }
+
+ it { is_expected.to eq('a@b.c') }
+ end
+
+ context 'when an email address is even shorter' do
let(:email) { 'a@b' }
it { is_expected.to eq('a@b') }
diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb
index a8945424877..c64d5990cd9 100644
--- a/spec/helpers/todos_helper_spec.rb
+++ b/spec/helpers/todos_helper_spec.rb
@@ -292,4 +292,22 @@ RSpec.describe TodosHelper do
it { is_expected.to eq(result) }
end
end
+
+ describe '#todos_filter_params' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:state, :result) do
+ 'done' | 'done'
+ 'pending' | 'pending'
+ '' | nil
+ end
+
+ with_them do
+ before do
+ allow(helper).to receive(:params).and_return({ state: state })
+ end
+
+ it { expect(helper.todos_filter_params[:state]).to eq(result) }
+ end
+ end
end
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 617a796781e..c2c78be6a0f 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -204,11 +204,12 @@ RSpec.describe UsersHelper do
badges = helper.user_badges_in_admin_section(user)
- expect(badges).to match_array([
- { text: s_("AdminUsers|Blocked"), variant: "danger" },
- { text: s_("AdminUsers|Admin"), variant: "success" },
- { text: s_("AdminUsers|External"), variant: "secondary" }
- ])
+ expect(badges).to match_array(
+ [
+ { text: s_("AdminUsers|Blocked"), variant: "danger" },
+ { text: s_("AdminUsers|Admin"), variant: "success" },
+ { text: s_("AdminUsers|External"), variant: "secondary" }
+ ])
end
end
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index 75128d758f9..59624dc0682 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -75,41 +75,38 @@ RSpec.describe WikiHelper do
describe '#wiki_sort_controls' do
let(:wiki) { create(:project_wiki) }
- let(:wiki_link) { helper.wiki_sort_controls(wiki, sort, direction) }
+ let(:wiki_link) { helper.wiki_sort_controls(wiki, direction) }
let(:classes) { "gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
- def expected_link(sort, direction, icon_class)
- path = "/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}"
-
- helper.link_to(path, type: 'button', class: classes, title: 'Sort direction') do
+ def expected_link(direction, icon_class)
+ path = "/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}"
+ title = direction == 'desc' ? _('Sort direction: Ascending') : _('Sort direction: Descending')
+ helper.link_to(path, type: 'button', class: classes, title: title) do
helper.sprite_icon("sort-#{icon_class}")
end
end
context 'initial call' do
- let(:sort) { nil }
let(:direction) { nil }
it 'renders with default values' do
- expect(wiki_link).to eq(expected_link('title', 'desc', 'lowest'))
+ expect(wiki_link).to eq(expected_link('desc', 'lowest'))
end
end
- context 'sort by title' do
- let(:sort) { 'title' }
+ context 'sort by asc order' do
let(:direction) { 'asc' }
it 'renders a link with opposite direction' do
- expect(wiki_link).to eq(expected_link('title', 'desc', 'lowest'))
+ expect(wiki_link).to eq(expected_link('desc', 'lowest'))
end
end
- context 'sort by created_at' do
- let(:sort) { 'created_at' }
+ context 'sort by desc order' do
let(:direction) { 'desc' }
it 'renders a link with opposite direction' do
- expect(wiki_link).to eq(expected_link('created_at', 'asc', 'highest'))
+ expect(wiki_link).to eq(expected_link('asc', 'highest'))
end
end
end
diff --git a/spec/initializers/100_patch_omniauth_oauth2_spec.rb b/spec/initializers/100_patch_omniauth_oauth2_spec.rb
index 36a14816b7e..8c8e2b24484 100644
--- a/spec/initializers/100_patch_omniauth_oauth2_spec.rb
+++ b/spec/initializers/100_patch_omniauth_oauth2_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'OmniAuth::Strategies::OAuth2' do
it 'verifies the gem version' do
current_version = OmniAuth::OAuth2::VERSION
- expected_version = '1.7.3'
+ expected_version = '1.8.0'
expect(current_version).to eq(expected_version), <<~EOF
New version #{current_version} of the `omniauth-oauth2` gem detected!
diff --git a/spec/initializers/attr_encrypted_no_db_connection_spec.rb b/spec/initializers/attr_encrypted_no_db_connection_spec.rb
deleted file mode 100644
index 34d9e182370..00000000000
--- a/spec/initializers/attr_encrypted_no_db_connection_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'GitLab monkey-patches to AttrEncrypted' do
- describe '#attribute_instance_methods_as_symbols_available?' do
- let(:klass) do
- Class.new(ActiveRecord::Base) do
- # We need some sort of table to work on
- self.table_name = 'projects'
-
- attr_encrypted :foo
- end
- end
-
- it 'returns false' do
- expect(ActiveRecord::Base.__send__(:attribute_instance_methods_as_symbols_available?)).to be_falsy
- end
-
- it 'does not define virtual attributes' do
- instance = klass.new
-
- aggregate_failures do
- %w[
- encrypted_foo encrypted_foo=
- encrypted_foo_iv encrypted_foo_iv=
- encrypted_foo_salt encrypted_foo_salt=
- ].each do |method_name|
- expect(instance).not_to respond_to(method_name)
- end
- end
- end
-
- it 'calls attr_changed? method with kwargs' do
- obj = klass.new
-
- expect(obj.foo_changed?).to eq(false)
- end
- end
-end
diff --git a/spec/initializers/attr_encrypted_thread_safe_spec.rb b/spec/initializers/attr_encrypted_thread_safe_spec.rb
deleted file mode 100644
index e79b7c716ec..00000000000
--- a/spec/initializers/attr_encrypted_thread_safe_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AttrEncrypted do
- describe '#encrypted_attributes' do
- subject do
- Class.new(ActiveRecord::Base) do
- self.table_name = 'projects'
-
- attr_accessor :encrypted_foo
- attr_accessor :encrypted_foo_iv
-
- attr_encrypted :foo, key: 'This is a key that is 256 bits!!'
- end
- end
-
- it 'does not share state with other instances' do
- instance = subject.new
- instance.foo = 'bar'
-
- another_instance = subject.new
-
- expect(instance.encrypted_attributes[:foo][:operation]).to eq(:encrypting)
- expect(another_instance.encrypted_attributes[:foo][:operation]).to be_nil
- end
- end
-end
diff --git a/spec/initializers/diagnostic_reports_spec.rb b/spec/initializers/diagnostic_reports_spec.rb
index 70574194916..01b1ed9b7b5 100644
--- a/spec/initializers/diagnostic_reports_spec.rb
+++ b/spec/initializers/diagnostic_reports_spec.rb
@@ -21,25 +21,33 @@ RSpec.describe 'diagnostic reports' do
stub_env('GITLAB_DIAGNOSTIC_REPORTS_ENABLED', true)
end
- context 'when run in application context' do
+ context 'when run in Puma context' do
before do
- allow(::Gitlab::Runtime).to receive(:application?).and_return(true)
+ allow(::Gitlab::Runtime).to receive(:puma?).and_return(true)
end
- it 'modifies worker startup hooks' do
- report_daemon = instance_double(Gitlab::Memory::ReportsDaemon)
+ let(:report_daemon) { instance_double(Gitlab::Memory::ReportsDaemon) }
+ it 'modifies worker startup hooks, starts Gitlab::Memory::ReportsDaemon' do
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_call_original
- expect(Gitlab::Memory::ReportsDaemon).to receive(:instance).and_return(report_daemon)
- expect(report_daemon).to receive(:start)
+
+ expect_next_instance_of(Gitlab::Memory::ReportsDaemon) do |daemon|
+ expect(daemon).to receive(:start).and_call_original
+
+ # make sleep no-op
+ allow(daemon).to receive(:sleep).and_return(nil)
+
+ # let alive return 3 times: true, true, false
+ allow(daemon).to receive(:alive).and_return(true, true, false)
+ end
load_initializer
end
end
- context 'when run in non-application context, such as rails console or tests' do
+ context 'when run in non-Puma context, such as rails console, tests, Sidekiq' do
before do
- allow(::Gitlab::Runtime).to receive(:application?).and_return(false)
+ allow(::Gitlab::Runtime).to receive(:puma?).and_return(false)
end
include_examples 'does not modify worker startup hooks'
@@ -48,7 +56,7 @@ RSpec.describe 'diagnostic reports' do
context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is not set' do
before do
- allow(::Gitlab::Runtime).to receive(:application?).and_return(true)
+ allow(::Gitlab::Runtime).to receive(:puma?).and_return(true)
end
include_examples 'does not modify worker startup hooks'
@@ -57,7 +65,7 @@ RSpec.describe 'diagnostic reports' do
context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is set to false' do
before do
stub_env('GITLAB_DIAGNOSTIC_REPORTS_ENABLED', false)
- allow(::Gitlab::Runtime).to receive(:application?).and_return(true)
+ allow(::Gitlab::Runtime).to receive(:puma?).and_return(true)
end
include_examples 'does not modify worker startup hooks'
diff --git a/spec/initializers/memory_watchdog_spec.rb b/spec/initializers/memory_watchdog_spec.rb
index 56f995b5cd3..36f96131c3d 100644
--- a/spec/initializers/memory_watchdog_spec.rb
+++ b/spec/initializers/memory_watchdog_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
RSpec.describe 'memory watchdog' do
subject(:run_initializer) do
- load Rails.root.join('config/initializers/memory_watchdog.rb')
+ load rails_root_join('config/initializers/memory_watchdog.rb')
end
context 'when GITLAB_MEMORY_WATCHDOG_ENABLED is truthy' do
@@ -17,6 +17,7 @@ RSpec.describe 'memory watchdog' do
context 'when runtime is an application' do
let(:watchdog) { instance_double(Gitlab::Memory::Watchdog) }
let(:background_task) { instance_double(Gitlab::BackgroundTask) }
+ let(:logger) { Gitlab::AppLogger }
before do
allow(Gitlab::Runtime).to receive(:application?).and_return(true)
@@ -28,16 +29,65 @@ RSpec.describe 'memory watchdog' do
run_initializer
end
- shared_examples 'starts watchdog with handler' do |handler_class|
- it "uses the #{handler_class} and starts the watchdog" do
- expect(Gitlab::Memory::Watchdog).to receive(:new).with(
- handler: an_instance_of(handler_class),
- logger: Gitlab::AppLogger).and_return(watchdog)
- expect(Gitlab::BackgroundTask).to receive(:new).with(watchdog).and_return(background_task)
- expect(background_task).to receive(:start)
- expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_yield
+ shared_examples 'starts configured watchdog' do |handler_class|
+ let(:configuration) { Gitlab::Memory::Watchdog::Configuration.new }
+ let(:watchdog_monitors_params) do
+ {
+ Gitlab::Memory::Watchdog::Monitor::HeapFragmentation => {
+ max_heap_fragmentation: max_heap_fragmentation,
+ max_strikes: max_strikes
+ },
+ Gitlab::Memory::Watchdog::Monitor::UniqueMemoryGrowth => {
+ max_mem_growth: max_mem_growth,
+ max_strikes: max_strikes
+ }
+ }
+ end
+
+ shared_examples 'configures and starts watchdog' do
+ it "correctly configures and starts watchdog", :aggregate_failures do
+ expect(watchdog).to receive(:configure).and_yield(configuration)
+
+ watchdog_monitors_params.each do |monitor_class, params|
+ expect(configuration.monitors).to receive(:use).with(monitor_class, **params)
+ end
+
+ expect(Gitlab::Memory::Watchdog).to receive(:new).and_return(watchdog)
+ expect(Gitlab::BackgroundTask).to receive(:new).with(watchdog).and_return(background_task)
+ expect(background_task).to receive(:start)
+ expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_yield
+
+ run_initializer
+
+ expect(configuration.handler).to be_an_instance_of(handler_class)
+ expect(configuration.logger).to eq(logger)
+ expect(configuration.sleep_time_seconds).to eq(sleep_time_seconds)
+ end
+ end
+
+ context 'when settings are not passed through the environment' do
+ let(:max_strikes) { 5 }
+ let(:max_heap_fragmentation) { 0.5 }
+ let(:max_mem_growth) { 3.0 }
+ let(:sleep_time_seconds) { 60 }
+
+ include_examples 'configures and starts watchdog'
+ end
+
+ context 'when settings are passed through the environment' do
+ let(:max_strikes) { 6 }
+ let(:max_heap_fragmentation) { 0.4 }
+ let(:max_mem_growth) { 2.0 }
+ let(:sleep_time_seconds) { 50 }
+
+ before do
+ stub_env('GITLAB_MEMWD_MAX_STRIKES', 6)
+ stub_env('GITLAB_MEMWD_SLEEP_TIME_SEC', 50)
+ stub_env('GITLAB_MEMWD_MAX_MEM_GROWTH', 2.0)
+ stub_env('GITLAB_MEMWD_MAX_HEAP_FRAG', 0.4)
+ end
- run_initializer
+ include_examples 'configures and starts watchdog'
end
end
@@ -59,7 +109,7 @@ RSpec.describe 'memory watchdog' do
allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
end
- it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::PumaHandler
+ it_behaves_like 'starts configured watchdog', Gitlab::Memory::Watchdog::PumaHandler
end
# rubocop: enable RSpec/VerifiedDoubles
@@ -68,11 +118,11 @@ RSpec.describe 'memory watchdog' do
allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
end
- it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::TermProcessHandler
+ it_behaves_like 'starts configured watchdog', Gitlab::Memory::Watchdog::TermProcessHandler
end
context 'when other runtime' do
- it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::NullHandler
+ it_behaves_like 'starts configured watchdog', Gitlab::Memory::Watchdog::NullHandler
end
end
diff --git a/spec/initializers/sawyer_patch_spec.rb b/spec/initializers/sawyer_patch_spec.rb
index dc922654d7d..b3c10e63460 100644
--- a/spec/initializers/sawyer_patch_spec.rb
+++ b/spec/initializers/sawyer_patch_spec.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
require 'sawyer'
require_relative '../../config/initializers/sawyer_patch'
@@ -64,6 +64,28 @@ RSpec.describe 'sawyer_patch' do
expect(sawyer_resource.count_total).to eq(1)
expect(sawyer_resource.count_total?).to eq(true)
expect(sawyer_resource.count_total + 1).to eq(2)
+ sawyer_resource.count_total = 3
+ expect(sawyer_resource.count_total).to eq(3)
expect(sawyer_resource.user.name).to eq('User name')
end
+
+ it 'logs when a sawyer resource dynamic method is called' do
+ sawyer_resource = Sawyer::Resource.new(
+ Sawyer::Agent.new(''),
+ {
+ count_total: 1,
+ user: { name: 'User name' }
+ }
+ )
+ expected_attributes = []
+ allow(Gitlab::Import::Logger).to receive(:warn) do |params|
+ expected_attributes.push(params[:attribute])
+ end
+
+ sawyer_resource.count_total
+ sawyer_resource.user
+ sawyer_resource.user.name
+
+ expect(expected_attributes).to match_array(%i[count_total user user name])
+ end
end
diff --git a/spec/initializers/sidekiq_spec.rb b/spec/initializers/sidekiq_spec.rb
index e34f59c3427..063dddd8c46 100644
--- a/spec/initializers/sidekiq_spec.rb
+++ b/spec/initializers/sidekiq_spec.rb
@@ -42,4 +42,61 @@ RSpec.describe 'sidekiq' do
it { is_expected.to be_falsey }
end
end
+
+ describe 'load_cron_jobs!' do
+ subject { load_cron_jobs! }
+
+ let(:cron_for_service_ping) { '4 7 * * 4' }
+
+ let(:cron_jobs_settings) do
+ {
+ 'gitlab_service_ping_worker' => {
+ 'cron' => nil,
+ 'job_class' => 'GitlabServicePingWorker'
+ },
+ 'import_export_project_cleanup_worker' => {
+ 'cron' => '0 * * * *',
+ 'job_class' => 'ImportExportProjectCleanupWorker'
+ },
+ "invalid_worker" => {
+ 'cron' => '0 * * * *'
+ }
+ }
+ end
+
+ let(:cron_jobs_hash) do
+ {
+ 'gitlab_service_ping_worker' => {
+ 'cron' => cron_for_service_ping,
+ 'class' => 'GitlabServicePingWorker'
+ },
+ 'import_export_project_cleanup_worker' => {
+ 'cron' => '0 * * * *',
+ 'class' => 'ImportExportProjectCleanupWorker'
+ }
+ }
+ end
+
+ around do |example|
+ original_settings = Gitlab.config['cron_jobs']
+ Gitlab.config['cron_jobs'] = cron_jobs_settings
+
+ example.run
+
+ Gitlab.config['cron_jobs'] = original_settings
+ end
+
+ it 'loads the cron jobs into sidekiq-cron' do
+ allow(Settings).to receive(:cron_for_service_ping).and_return(cron_for_service_ping)
+
+ expect(Sidekiq::Cron::Job).to receive(:load_from_hash!).with(cron_jobs_hash)
+
+ if Gitlab.ee?
+ expect(Gitlab::Mirror).to receive(:configure_cron_job!)
+ expect(Gitlab::Geo).to receive(:configure_cron_jobs!)
+ end
+
+ subject
+ end
+ end
end
diff --git a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb
index adc8fdcdd9c..0132102b117 100644
--- a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb
+++ b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb
@@ -9,11 +9,26 @@ RSpec.describe API::Entities::BulkImports::EntityFailure do
it 'has the correct attributes' do
expect(subject).to include(
- :pipeline_class,
- :pipeline_step,
+ :relation,
+ :step,
:exception_class,
+ :exception_message,
:correlation_id_value,
:created_at
)
end
+
+ describe 'exception message' do
+ it 'truncates exception message to 72 characters' do
+ failure.update!(exception_message: 'a' * 100)
+
+ expect(subject[:exception_message].length).to eq(72)
+ end
+
+ it 'removes paths from the message' do
+ failure.update!(exception_message: 'Test /foo/bar')
+
+ expect(subject[:exception_message]).to eq('Test [FILTERED]')
+ end
+ end
end
diff --git a/spec/lib/api/entities/ml/mlflow/run_spec.rb b/spec/lib/api/entities/ml/mlflow/run_spec.rb
index 84234f474f5..b8d38093681 100644
--- a/spec/lib/api/entities/ml/mlflow/run_spec.rb
+++ b/spec/lib/api/entities/ml/mlflow/run_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe API::Entities::Ml::Mlflow::Run do
- let_it_be(:candidate) { create(:ml_candidates) }
+ let_it_be(:candidate) { create(:ml_candidates, :with_metrics_and_params) }
subject { described_class.new(candidate).as_json }
@@ -12,10 +12,52 @@ RSpec.describe API::Entities::Ml::Mlflow::Run do
end
it 'has the id' do
- expect(subject[:run][:info][:run_id]).to eq(candidate.iid.to_s)
+ expect(subject.dig(:run, :info, :run_id)).to eq(candidate.iid.to_s)
end
- it 'data is empty' do
- expect(subject[:run][:data]).to be_empty
+ it 'presents the metrics' do
+ expect(subject.dig(:run, :data, :metrics).size).to eq(candidate.metrics.size)
+ end
+
+ it 'presents metrics correctly' do
+ presented_metric = subject.dig(:run, :data, :metrics)[0]
+ metric = candidate.metrics[0]
+
+ expect(presented_metric[:key]).to eq(metric.name)
+ expect(presented_metric[:value]).to eq(metric.value)
+ expect(presented_metric[:timestamp]).to eq(metric.tracked_at)
+ expect(presented_metric[:step]).to eq(metric.step)
+ end
+
+ it 'presents the params' do
+ expect(subject.dig(:run, :data, :params).size).to eq(candidate.params.size)
+ end
+
+ it 'presents params correctly' do
+ presented_param = subject.dig(:run, :data, :params)[0]
+ param = candidate.params[0]
+
+ expect(presented_param[:key]).to eq(param.name)
+ expect(presented_param[:value]).to eq(param.value)
+ end
+
+ context 'when candidate has no metrics' do
+ before do
+ allow(candidate).to receive(:metrics).and_return([])
+ end
+
+ it 'returns empty data' do
+ expect(subject.dig(:run, :data, :metrics)).to be_empty
+ end
+ end
+
+ context 'when candidate has no params' do
+ before do
+ allow(candidate).to receive(:params).and_return([])
+ end
+
+ it 'data is empty' do
+ expect(subject.dig(:run, :data, :params)).to be_empty
+ end
end
end
diff --git a/spec/lib/api/helpers/merge_requests_helpers_spec.rb b/spec/lib/api/helpers/merge_requests_helpers_spec.rb
index 1d68b7985f1..80810133469 100644
--- a/spec/lib/api/helpers/merge_requests_helpers_spec.rb
+++ b/spec/lib/api/helpers/merge_requests_helpers_spec.rb
@@ -25,9 +25,7 @@ RSpec.describe API::Helpers::MergeRequestsHelpers do
context 'when merge request is invalid' do
before do
allow(merge_request).to receive(:valid?).and_return(false)
- allow(helper).to receive_messages([
- :unprocessable_entity!, :conflict!, :render_validation_error!
- ])
+ allow(helper).to receive_messages([:unprocessable_entity!, :conflict!, :render_validation_error!])
end
API::Helpers::MergeRequestsHelpers::UNPROCESSABLE_ERROR_KEYS.each do |error_key|
diff --git a/spec/lib/api/helpers/open_api_spec.rb b/spec/lib/api/helpers/open_api_spec.rb
new file mode 100644
index 00000000000..fb14f7fe001
--- /dev/null
+++ b/spec/lib/api/helpers/open_api_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Helpers::OpenApi do
+ describe 'class methods' do
+ let(:klass) { Class.new.include(described_class) }
+
+ describe '.add_open_api_documentation!' do
+ before do
+ allow(YAML).to receive(:load_file).and_return({ 'metadata' => { 'key' => 'value' } })
+ end
+
+ it 'calls the add_swagger_documentation method' do
+ expect(klass).to receive(:add_swagger_documentation).with({ key: 'value' })
+
+ klass.add_open_api_documentation!
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
index aa4b0a137cd..66cf06cde20 100644
--- a/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
@@ -7,12 +7,23 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
describe '#redirect_registry_request' do
using RSpec::Parameterized::TableSyntax
+ include_context 'dependency proxy helpers context'
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be_with_reload(:package_setting) { create(:namespace_package_setting, namespace: group) }
+ let(:target) { project }
let(:options) { {} }
- subject { helper.redirect_registry_request(forward_to_registry, package_type, options) { helper.fallback } }
+ subject do
+ helper.redirect_registry_request(
+ forward_to_registry: forward_to_registry,
+ package_type: package_type,
+ target: target,
+ options: options
+ ) { helper.fallback }
+ end
before do
allow(helper).to receive(:options).and_return(for: described_class)
@@ -42,32 +53,57 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
%i[maven npm pypi].each do |forwardable_package_type|
context "with #{forwardable_package_type} packages" do
- include_context 'dependency proxy helpers context'
-
let(:package_type) { forwardable_package_type }
- let(:options) { { project: project } }
- where(:application_setting, :forward_to_registry, :example_name) do
- true | true | 'executing redirect'
- true | false | 'executing fallback'
- false | true | 'executing fallback'
- false | false | 'executing fallback'
+ where(:application_setting, :group_setting, :forward_to_registry, :example_name) do
+ true | nil | true | 'executing redirect'
+ true | nil | false | 'executing fallback'
+ false | nil | true | 'executing fallback'
+ false | nil | false | 'executing fallback'
+ true | false | true | 'executing fallback'
+ true | false | false | 'executing fallback'
+ false | true | true | 'executing redirect'
+ false | true | false | 'executing fallback'
end
with_them do
before do
- allow_fetch_application_setting(attribute: "#{forwardable_package_type}_package_requests_forwarding", return_value: application_setting)
+ allow_fetch_cascade_application_setting(attribute: "#{forwardable_package_type}_package_requests_forwarding", return_value: application_setting)
+ package_setting.update!("#{forwardable_package_type}_package_requests_forwarding" => group_setting)
end
it_behaves_like params[:example_name]
end
end
+ context 'when cascade_package_forwarding_settings is disabled' do
+ let(:package_type) { forwardable_package_type }
+ let(:forward_to_registry) { true }
+
+ before do
+ stub_feature_flags(cascade_package_forwarding_settings: false)
+ allow_fetch_cascade_application_setting(attribute: "#{forwardable_package_type}_package_requests_forwarding", return_value: true)
+ package_setting.update!("#{forwardable_package_type}_package_requests_forwarding" => false)
+ end
+
+ it_behaves_like 'executing redirect'
+ end
+
+ context 'when no target is present' do
+ let(:package_type) { forwardable_package_type }
+ let(:forward_to_registry) { true }
+ let(:target) { nil }
+
+ before do
+ allow_fetch_cascade_application_setting(attribute: "#{forwardable_package_type}_package_requests_forwarding", return_value: true)
+ package_setting.update!("#{forwardable_package_type}_package_requests_forwarding" => false)
+ end
+
+ it_behaves_like 'executing redirect'
+ end
+
context 'when maven_central_request_forwarding is disabled' do
let(:package_type) { :maven }
- let(:options) { { project: project } }
-
- include_context 'dependency proxy helpers context'
where(:application_setting, :forward_to_registry) do
true | true
@@ -79,7 +115,7 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
with_them do
before do
stub_feature_flags(maven_central_request_forwarding: false)
- allow_fetch_application_setting(attribute: "maven_package_requests_forwarding", return_value: application_setting)
+ allow_fetch_cascade_application_setting(attribute: "maven_package_requests_forwarding", return_value: application_setting)
end
it_behaves_like 'executing fallback'
diff --git a/spec/lib/api/helpers/packages_helpers_spec.rb b/spec/lib/api/helpers/packages_helpers_spec.rb
index cd6e718ce98..d764ed4afff 100644
--- a/spec/lib/api/helpers/packages_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages_helpers_spec.rb
@@ -35,26 +35,6 @@ RSpec.describe API::Helpers::PackagesHelpers do
expect(helper.send('authorize_read_package!', subject)).to eq nil
end
end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(read_package_policy_rule: false)
- end
-
- where(:subject, :expected_class) do
- ref(:project) | ::Project
- ref(:group) | ::Group
- ref(:package) | ::Packages::Package
- end
-
- with_them do
- it 'calls authorize! with correct subject' do
- expect(helper).to receive(:authorize!).with(:read_package, have_attributes(id: subject.id, class: expected_class))
-
- expect(helper.send('authorize_read_package!', subject)).to eq nil
- end
- end
- end
end
%i[create_package destroy_package].each do |action|
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index f25c75ef93c..652727f371b 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -110,6 +110,13 @@ RSpec.describe API::Helpers do
end
end
+ context 'when ID is a negative number' do
+ let(:existing_id) { project.id }
+ let(:non_existing_id) { -1 }
+
+ it_behaves_like 'project finder'
+ end
+
context 'when project is pending delete' do
let(:project_pending_delete) { create(:project, pending_delete: true) }
@@ -325,6 +332,13 @@ RSpec.describe API::Helpers do
it_behaves_like 'group finder'
end
+
+ context 'when ID is a negative number' do
+ let(:existing_id) { group.id }
+ let(:non_existing_id) { -1 }
+
+ it_behaves_like 'group finder'
+ end
end
end
@@ -421,6 +435,13 @@ RSpec.describe API::Helpers do
it_behaves_like 'namespace finder'
end
+
+ context 'when ID is a negative number' do
+ let(:existing_id) { namespace.id }
+ let(:non_existing_id) { -1 }
+
+ it_behaves_like 'namespace finder'
+ end
end
shared_examples 'user namespace finder' do
@@ -773,6 +794,58 @@ RSpec.describe API::Helpers do
end
end
+ describe '#present_artifacts_file!' do
+ context 'with object storage' do
+ let(:artifact) { create(:ci_job_artifact, :zip, :remote_store) }
+
+ subject { helper.present_artifacts_file!(artifact.file, project: artifact.job.project) }
+
+ before do
+ allow(helper).to receive(:env).and_return({})
+
+ stub_artifacts_object_storage(enabled: true)
+ end
+
+ it 'redirects to a CDN-fronted URL' do
+ expect(helper).to receive(:redirect)
+ expect(helper).to receive(:cdn_fronted_url).and_call_original
+ expect(Gitlab::ApplicationContext).to receive(:push).with(artifact: artifact.file.model).and_call_original
+ expect(Gitlab::ApplicationContext).to receive(:push).with(artifact_used_cdn: false).and_call_original
+
+ subject
+ end
+ end
+ end
+
+ describe '#cdn_frontend_url' do
+ before do
+ allow(helper).to receive(:env).and_return({})
+
+ stub_artifacts_object_storage(enabled: true)
+ end
+
+ context 'with a CI artifact' do
+ let(:artifact) { create(:ci_job_artifact, :zip, :remote_store) }
+
+ it 'retrieves a CDN-fronted URL' do
+ expect(artifact.file).to receive(:cdn_enabled_url).and_call_original
+ expect(Gitlab::ApplicationContext).to receive(:push).with(artifact_used_cdn: false).and_call_original
+ expect(helper.cdn_fronted_url(artifact.file, artifact.job.project)).to be_a(String)
+ end
+ end
+
+ context 'with a file upload' do
+ let(:url) { 'https://example.com/path/to/upload' }
+
+ it 'retrieves the file URL' do
+ file = double(url: url)
+
+ expect(Gitlab::ApplicationContext).not_to receive(:push)
+ expect(helper.cdn_fronted_url(file, nil)).to eq(url)
+ end
+ end
+ end
+
describe '#order_by_similarity?' do
where(:params, :allow_unauthorized, :current_user_set, :expected) do
{} | false | false | false
@@ -916,42 +989,5 @@ RSpec.describe API::Helpers do
it_behaves_like 'authorized'
end
-
- context 'when gitlab_shell_jwt_token is disabled' do
- let(:valid_secret_token) { +'valid' } # mutable string to use chomp!
- let(:invalid_secret_token) { +'invalid' } # mutable string to use chomp!
-
- before do
- stub_feature_flags(gitlab_shell_jwt_token: false)
- end
-
- context 'when shared secret is not provided' do
- it_behaves_like 'unauthorized'
- end
-
- context 'when shared secret provided via params' do
- let(:params) { { 'secret_token' => valid_secret_token } }
-
- it_behaves_like 'authorized'
-
- context 'but it is invalid' do
- let(:params) { { 'secret_token' => invalid_secret_token } }
-
- it_behaves_like 'unauthorized'
- end
- end
-
- context 'when shared secret provided via headers' do
- let(:headers) { { described_class::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(valid_secret_token) } }
-
- it_behaves_like 'authorized'
-
- context 'but it is invalid' do
- let(:headers) { { described_class::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(invalid_secret_token) } }
-
- it_behaves_like 'unauthorized'
- end
- end
- end
end
end
diff --git a/spec/lib/banzai/filter/pathological_markdown_filter_spec.rb b/spec/lib/banzai/filter/pathological_markdown_filter_spec.rb
deleted file mode 100644
index e0a07d1ea77..00000000000
--- a/spec/lib/banzai/filter/pathological_markdown_filter_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::PathologicalMarkdownFilter do
- include FilterSpecHelper
-
- let_it_be(:short_text) { '![a' * 5 }
- let_it_be(:long_text) { ([short_text] * 10).join(' ') }
- let_it_be(:with_images_text) { "![One ![one](one.jpg) #{'and\n' * 200} ![two ![two](two.jpg)" }
-
- it 'detects a significat number of unclosed image links' do
- msg = <<~TEXT
- _Unable to render markdown - too many unclosed markdown image links detected._
- TEXT
-
- expect(filter(long_text)).to eq(msg.strip)
- end
-
- it 'does nothing when there are only a few unclosed image links' do
- expect(filter(short_text)).to eq(short_text)
- end
-
- it 'does nothing when there are only a few unclosed image links and images' do
- expect(filter(with_images_text)).to eq(with_images_text)
- end
-end
diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
index c342a831d62..12cdb5cfb95 100644
--- a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
@@ -309,11 +309,12 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter do
it 'links to valid references' do
doc = reference_filter("See #{references}")
- expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
- urls.project_issues_url(project, label_name: bug.name),
- urls.project_issues_url(project, label_name: feature_proposal.name),
- urls.project_issues_url(project, label_name: technical_debt.name)
- ])
+ expect(doc.css('a').map { |a| a.attr('href') }).to match_array(
+ [
+ urls.project_issues_url(project, label_name: bug.name),
+ urls.project_issues_url(project, label_name: feature_proposal.name),
+ urls.project_issues_url(project, label_name: technical_debt.name)
+ ])
expect(doc.text).to eq 'See bug, feature proposal, technical debt'
end
end
@@ -324,11 +325,12 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter do
it 'links to valid references' do
doc = reference_filter("See #{references}")
- expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
- urls.project_issues_url(project, label_name: bug.name),
- urls.project_issues_url(project, label_name: feature_proposal.name),
- urls.project_issues_url(project, label_name: technical_debt.name)
- ])
+ expect(doc.css('a').map { |a| a.attr('href') }).to match_array(
+ [
+ urls.project_issues_url(project, label_name: bug.name),
+ urls.project_issues_url(project, label_name: feature_proposal.name),
+ urls.project_issues_url(project, label_name: technical_debt.name)
+ ])
expect(doc.text).to eq 'See bug feature proposal technical debt'
end
end
diff --git a/spec/lib/banzai/filter/truncate_visible_filter_spec.rb b/spec/lib/banzai/filter/truncate_visible_filter_spec.rb
new file mode 100644
index 00000000000..8daaed05264
--- /dev/null
+++ b/spec/lib/banzai/filter/truncate_visible_filter_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::TruncateVisibleFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { build(:project, :repository) }
+ let_it_be(:max_chars) { 100 }
+ let_it_be(:user) do
+ user = create(:user, username: 'gfm')
+ project.add_maintainer(user)
+ user
+ end
+
+ # Since we're truncating nodes of an html document, actually use the
+ # full pipeline to generate full documents.
+ def convert_markdown(text, context = {})
+ Banzai::Pipeline::FullPipeline.to_html(text, { project: project }.merge(context))
+ end
+
+ shared_examples_for 'truncates text' do
+ specify do
+ html = convert_markdown(markdown)
+ doc = filter(html, { truncate_visible_max_chars: max_chars })
+
+ expect(doc.to_html).to match(expected)
+ end
+ end
+
+ describe 'displays inline code' do
+ let(:markdown) { 'Text with `inline code`' }
+ let(:expected) { 'Text with <code>inline code</code>' }
+
+ it_behaves_like 'truncates text'
+ end
+
+ describe 'truncates the text with multiple paragraphs' do
+ let(:markdown) { "Paragraph 1\n\nParagraph 2" }
+ let(:expected) { 'Paragraph 1...' }
+
+ it_behaves_like 'truncates text'
+ end
+
+ describe 'truncates the first line of a code block' do
+ let(:markdown) { "```\nCode block\nwith two lines\n```" }
+ let(:expected) { "Code block...</span>\n</code>" }
+
+ it_behaves_like 'truncates text'
+ end
+
+ describe 'preserves code color scheme' do
+ let(:max_chars) { 150 }
+ let(:markdown) { "```ruby\ndef test\n 'hello world'\nend\n```" }
+ let(:expected) do
+ '<code><span id="LC1" class="line" lang="ruby">' \
+ '<span class="k">def</span> <span class="nf">test</span>...</span>'
+ end
+
+ it_behaves_like 'truncates text'
+ end
+
+ describe 'truncates a single long line of text' do
+ let(:max_chars) { 150 }
+ let(:text) { 'The quick brown fox jumped over the lazy dog twice' } # 50 chars
+ let(:markdown) { text * 4 }
+ let(:expected) { (text * 2).sub(/.{3}/, '...') }
+
+ it_behaves_like 'truncates text'
+ end
+
+ it 'preserves a link href when link text is truncated' do
+ max_chars = 150
+ text = 'The quick brown fox jumped over the lazy dog' # 44 chars
+ link_url = 'http://example.com/foo/bar/baz' # 30 chars
+ markdown = "#{text}#{text}#{text} #{link_url}" # 163 chars
+ expected_link_text = 'http://example...</a>'
+
+ html = convert_markdown(markdown)
+ doc = filter(html, { truncate_visible_max_chars: max_chars })
+
+ expect(doc.to_html).to match(link_url)
+ expect(doc.to_html).to match(expected_link_text)
+ end
+
+ it 'truncates HTML properly' do
+ markdown = "@#{user.username}, can you look at this?\nHello world\n"
+
+ html = convert_markdown(markdown)
+ doc = filter(html, { truncate_visible_max_chars: max_chars })
+
+ # Make sure we didn't create invalid markup
+ expect(doc.errors).to be_empty
+
+ # Leading user link
+ expect(doc.css('a').length).to eq(1)
+ expect(doc.css('a')[0].attr('href')).to eq urls.user_path(user)
+ expect(doc.css('a')[0].text).to eq "@#{user.username}"
+ expect(doc.content).to eq "@#{user.username}, can you look at this?..."
+ end
+
+ it 'truncates HTML with emoji properly' do
+ markdown = "foo :wink:\nbar :grinning:"
+ # actual = first_line_in_markdown(object, attribute, 100, project: project)
+
+ html = convert_markdown(markdown)
+ doc = filter(html, { truncate_visible_max_chars: max_chars })
+
+ # Make sure we didn't create invalid markup
+ # But also account for the 2 errors caused by the unknown `gl-emoji` elements
+ expect(doc.errors.length).to eq(2)
+
+ expect(doc.css('gl-emoji').length).to eq(2)
+ expect(doc.css('gl-emoji')[0].attr('data-name')).to eq 'wink'
+ expect(doc.css('gl-emoji')[1].attr('data-name')).to eq 'grinning'
+
+ expect(doc.content).to eq "foo 😉\nbar 😀"
+ end
+
+ it 'does not truncate if truncate_visible_max_chars not specified' do
+ markdown = "@#{user.username}, can you look at this?\nHello world"
+
+ html = convert_markdown(markdown)
+ doc = filter(html)
+
+ expect(doc.content).to eq markdown
+ end
+end
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index 70c7c3c74fb..9807e385a5a 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -47,6 +47,14 @@ RSpec.describe Banzai::Filter::WikiLinkFilter do
expect(filtered_link.attribute('href').value).to eq(path)
end
+
+ it 'does not rewrite links to old relative wiki path' do
+ old_wiki_base_path = wiki.wiki_base_path.sub('/-/', '/')
+ path = "#{old_wiki_base_path}/#{repository_upload_folder}/a.jpg"
+ filtered_link = filter("<a href='#{path}'>Link</a>", wiki: wiki, page_slug: 'home').children[0]
+
+ expect(filtered_link.attribute('href').value).to eq(path)
+ end
end
describe "when links point to the #{Wikis::CreateAttachmentService::ATTACHMENT_PATH} folder" do
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index c07f99dc9fc..1a0f5a53a23 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -168,15 +168,13 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
end
end
- describe 'unclosed image links' do
- it 'detects a significat number of unclosed image links' do
- markdown = '![a ' * 30
- msg = <<~TEXT
- Unable to render markdown - too many unclosed markdown image links detected.
- TEXT
- output = described_class.to_html(markdown, project: nil)
-
- expect(output).to include(msg.strip)
+ describe 'cmark-gfm and autlolinks' do
+ it 'does not hang with significant number of unclosed image links' do
+ markdown = '![a ' * 300000
+
+ expect do
+ Timeout.timeout(2.seconds) { described_class.to_html(markdown, project: nil) }
+ end.not_to raise_error
end
end
end
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index e24177a7043..f67f13b3862 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Banzai::Pipeline::GfmPipeline do
describe 'integration between parsing regular and external issue references' do
- let(:project) { create(:redmine_project, :public) }
+ let(:project) { create(:project, :with_redmine_integration, :public) }
context 'when internal issue tracker is enabled' do
context 'when shorthand pattern #ISSUE_ID is used' do
diff --git a/spec/lib/bitbucket/connection_spec.rb b/spec/lib/bitbucket/connection_spec.rb
index bed44b94f44..58a05c52b9f 100644
--- a/spec/lib/bitbucket/connection_spec.rb
+++ b/spec/lib/bitbucket/connection_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Bitbucket::Connection do
+ let(:token) { 'token' }
+
before do
allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:provider).and_return(double(app_id: '', app_secret: ''))
@@ -15,7 +17,7 @@ RSpec.describe Bitbucket::Connection do
expect(instance).to receive(:get).and_return(double(parsed: true))
end
- connection = described_class.new({})
+ connection = described_class.new({ token: token })
connection.get('/users')
end
@@ -27,19 +29,19 @@ RSpec.describe Bitbucket::Connection do
expect(instance).to receive(:expired?).and_return(true)
end
- expect(described_class.new({}).expired?).to be_truthy
+ expect(described_class.new({ token: token }).expired?).to be_truthy
end
end
describe '#refresh!' do
it 'calls connection.refresh!' do
- response = double(token: nil, expires_at: nil, expires_in: nil, refresh_token: nil)
+ response = double(token: token, expires_at: nil, expires_in: nil, refresh_token: nil)
expect_next_instance_of(OAuth2::AccessToken) do |instance|
expect(instance).to receive(:refresh!).and_return(response)
end
- described_class.new({}).refresh!
+ described_class.new({ token: token }).refresh!
end
end
end
diff --git a/spec/lib/bulk_imports/common/pipelines/entity_finisher_spec.rb b/spec/lib/bulk_imports/common/pipelines/entity_finisher_spec.rb
index f03a178b993..9ea519d367e 100644
--- a/spec/lib/bulk_imports/common/pipelines/entity_finisher_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/entity_finisher_spec.rb
@@ -13,11 +13,12 @@ RSpec.describe BulkImports::Common::Pipelines::EntityFinisher do
expect(logger)
.to receive(:info)
.with(
- bulk_import_id: entity.bulk_import.id,
+ bulk_import_id: entity.bulk_import_id,
bulk_import_entity_id: entity.id,
bulk_import_entity_type: entity.source_type,
pipeline_class: described_class.name,
- message: 'Entity finished'
+ message: 'Entity finished',
+ importer: 'gitlab_migration'
)
end
diff --git a/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb
index f0b461e518e..5220b9d37e5 100644
--- a/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe BulkImports::Common::Pipelines::LfsObjectsPipeline do
let_it_be(:oid) { 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' }
let(:tmpdir) { Dir.mktmpdir }
- let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test') }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test', source_xid: nil) }
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:lfs_dir_path) { tmpdir }
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 f650e931dc7..7a93365d098 100644
--- a/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
@@ -152,14 +152,14 @@ RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline do
context 'when importing to group' do
let(:portable) { group }
- let(:entity) { create(:bulk_import_entity, :group_entity, group: group, source_full_path: 'test') }
+ let(:entity) { create(:bulk_import_entity, :group_entity, group: group, source_full_path: 'test', source_xid: nil) }
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') }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: project, source_full_path: 'test', source_xid: nil) }
include_examples 'uploads import'
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
index 0a04c0a2243..fabef50af8b 100644
--- a/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb
+++ b/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb
@@ -9,15 +9,32 @@ RSpec.describe BulkImports::Common::Rest::GetBadgesQuery do
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
+ context 'when source id is present' do
+ it 'returns correct query using source id and page info' do
+ expected = {
+ resource: [entity.base_resource_path, 'badges'].join('/'),
+ query: {
+ page: context.tracker.next_page
+ }
}
- }
- expect(described_class.to_h(context)).to eq(expected)
+ expect(described_class.to_h(context)).to eq(expected)
+ end
+ end
+
+ context 'when source id is missing' do
+ it 'returns correct query using source full path' do
+ entity.update!(source_xid: nil)
+
+ 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
end
diff --git a/spec/lib/bulk_imports/features_spec.rb b/spec/lib/bulk_imports/features_spec.rb
new file mode 100644
index 00000000000..a92e4706bbe
--- /dev/null
+++ b/spec/lib/bulk_imports/features_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Features do
+ describe '.project_migration_enabled' do
+ let_it_be(:top_level_namespace) { create(:group) }
+
+ context 'when bulk_import_projects feature flag is enabled' do
+ it 'returns true' do
+ stub_feature_flags(bulk_import_projects: true)
+
+ expect(described_class.project_migration_enabled?).to eq(true)
+ end
+
+ context 'when feature flag is enabled on root ancestor level' do
+ it 'returns true' do
+ stub_feature_flags(bulk_import_projects: top_level_namespace)
+
+ expect(described_class.project_migration_enabled?(top_level_namespace.full_path)).to eq(true)
+ end
+ end
+
+ context 'when feature flag is enabled on a different top level namespace' do
+ it 'returns false' do
+ stub_feature_flags(bulk_import_projects: top_level_namespace)
+
+ different_namepace = create(:group)
+
+ expect(described_class.project_migration_enabled?(different_namepace.full_path)).to eq(false)
+ end
+ end
+ end
+
+ context 'when bulk_import_projects feature flag is disabled' do
+ it 'returns false' do
+ stub_feature_flags(bulk_import_projects: false)
+
+ expect(described_class.project_migration_enabled?(top_level_namespace.full_path)).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
index 441a34b0c74..36b425f4f12 100644
--- a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
:bulk_import_entity,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
- destination_name: 'My Destination Group',
+ destination_slug: 'my-destination-group',
destination_namespace: parent.full_path
)
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb
index 5b6c93e695f..c07d27e973f 100644
--- a/spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe BulkImports::Groups::Pipelines::ProjectEntitiesPipeline do
let(:extracted_data) do
BulkImports::Pipeline::ExtractedData.new(data: {
+ 'id' => 'gid://gitlab/Project/1234567',
'name' => 'project',
'full_path' => 'group/project'
})
@@ -44,6 +45,7 @@ RSpec.describe BulkImports::Groups::Pipelines::ProjectEntitiesPipeline do
expect(project_entity.source_full_path).to eq('group/project')
expect(project_entity.destination_name).to eq('project')
expect(project_entity.destination_namespace).to eq(destination_group.full_path)
+ expect(project_entity.source_xid).to eq(1234567)
end
end
diff --git a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
index 896af865c56..32d8dc8e207 100644
--- a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
@@ -24,59 +24,67 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
let(:data) do
{
'name' => 'Source Group Name',
+ 'description' => 'Source Group Description',
'path' => 'source-group-path',
'full_path' => 'source/full/path',
'visibility' => 'private',
'project_creation_level' => 'developer',
- 'subgroup_creation_level' => 'maintainer'
+ 'subgroup_creation_level' => 'maintainer',
+ 'emails_disabled' => true,
+ 'lfs_enabled' => false,
+ 'mentions_disabled' => true,
+ 'share_with_group_lock' => false,
+ 'require_two_factor_authentication' => false,
+ 'two_factor_grace_period' => 100,
+ 'request_access_enabled' => false
}
end
subject { described_class.new }
it 'returns original data with some keys transformed' do
- transformed_data = subject.transform(context, { 'name' => 'Name', 'description' => 'Description' })
+ transformed_data = subject.transform(context, data)
expect(transformed_data).to eq({
- 'name' => 'Name',
- 'description' => 'Description',
+ 'name' => 'Source Group Name',
+ 'description' => 'Source Group Description',
'parent_id' => parent.id,
- 'path' => 'destination-slug-path'
+ 'path' => entity.destination_slug,
+ 'visibility_level' => Gitlab::VisibilityLevel.string_options[data['visibility']],
+ 'project_creation_level' => Gitlab::Access.project_creation_string_options[data['project_creation_level']],
+ 'subgroup_creation_level' => Gitlab::Access.subgroup_creation_string_options[data['subgroup_creation_level']],
+ 'emails_disabled' => true,
+ 'lfs_enabled' => false,
+ 'mentions_disabled' => true,
+ 'share_with_group_lock' => false,
+ 'require_two_factor_authentication' => false,
+ 'two_factor_grace_period' => 100,
+ 'request_access_enabled' => false
})
end
- it 'transforms path from destination_slug' do
- transformed_data = subject.transform(context, data)
-
- expect(transformed_data['path']).to eq(entity.destination_slug)
- end
-
- it 'removes full path' do
- transformed_data = subject.transform(context, data)
-
- expect(transformed_data).not_to have_key('full_path')
- end
-
- it 'transforms visibility level' do
- visibility = data['visibility']
- transformed_data = subject.transform(context, data)
-
- expect(transformed_data).not_to have_key('visibility')
- expect(transformed_data['visibility_level']).to eq(Gitlab::VisibilityLevel.string_options[visibility])
- end
-
- it 'transforms project creation level' do
- level = data['project_creation_level']
- transformed_data = subject.transform(context, data)
+ context 'when some fields are not present' do
+ it 'does not include those fields' do
+ data = {
+ 'name' => 'Source Group Name',
+ 'description' => 'Source Group Description',
+ 'path' => 'source-group-path',
+ 'full_path' => 'source/full/path'
+ }
- expect(transformed_data['project_creation_level']).to eq(Gitlab::Access.project_creation_string_options[level])
- end
-
- it 'transforms subgroup creation level' do
- level = data['subgroup_creation_level']
- transformed_data = subject.transform(context, data)
+ transformed_data = subject.transform(context, data)
- expect(transformed_data['subgroup_creation_level']).to eq(Gitlab::Access.subgroup_creation_string_options[level])
+ expect(transformed_data).to eq({
+ 'name' => 'Source Group Name',
+ 'path' => 'destination-slug-path',
+ 'description' => 'Source Group Description',
+ 'parent_id' => parent.id,
+ 'share_with_group_lock' => nil,
+ 'emails_disabled' => nil,
+ 'lfs_enabled' => nil,
+ 'mentions_disabled' => nil
+ })
+ end
end
describe 'parent group transformation' do
diff --git a/spec/lib/bulk_imports/network_error_spec.rb b/spec/lib/bulk_imports/network_error_spec.rb
index 11f555fee09..54d6554df96 100644
--- a/spec/lib/bulk_imports/network_error_spec.rb
+++ b/spec/lib/bulk_imports/network_error_spec.rb
@@ -46,6 +46,22 @@ RSpec.describe BulkImports::NetworkError, :clean_gitlab_redis_cache do
expect(exception.retriable?(tracker)).to eq(false)
end
end
+
+ context 'when entity is passed' do
+ it 'increments entity cache key' do
+ entity = create(:bulk_import_entity)
+ exception = described_class.new('Error!')
+
+ allow(exception).to receive(:cause).and_return(SocketError.new('Error!'))
+
+ expect(Gitlab::Cache::Import::Caching)
+ .to receive(:increment)
+ .with("bulk_imports/#{entity.id}/network_error/SocketError")
+ .and_call_original
+
+ exception.retriable?(entity)
+ end
+ end
end
describe '#retry_delay' do
diff --git a/spec/lib/bulk_imports/pipeline/runner_spec.rb b/spec/lib/bulk_imports/pipeline/runner_spec.rb
index 810271818ae..a5a01354d0e 100644
--- a/spec/lib/bulk_imports/pipeline/runner_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/runner_spec.rb
@@ -60,7 +60,9 @@ RSpec.describe BulkImports::Pipeline::Runner do
pipeline_step: :extractor,
pipeline_class: 'BulkImports::MyPipeline',
exception_class: exception_class,
- exception_message: exception_message
+ exception_message: exception_message,
+ message: "Pipeline failed",
+ importer: 'gitlab_migration'
)
)
end
@@ -89,7 +91,8 @@ RSpec.describe BulkImports::Pipeline::Runner do
log_params(
context,
message: 'Aborting entity migration due to pipeline failure',
- pipeline_class: 'BulkImports::MyPipeline'
+ pipeline_class: 'BulkImports::MyPipeline',
+ importer: 'gitlab_migration'
)
)
end
@@ -290,9 +293,10 @@ RSpec.describe BulkImports::Pipeline::Runner do
def log_params(context, extra = {})
{
- bulk_import_id: context.bulk_import.id,
+ bulk_import_id: context.bulk_import_id,
bulk_import_entity_id: context.entity.id,
bulk_import_entity_type: context.entity.source_type,
+ importer: 'gitlab_migration',
context_extra: context.extra
}.merge(extra)
end
diff --git a/spec/lib/bulk_imports/pipeline_spec.rb b/spec/lib/bulk_imports/pipeline_spec.rb
index dc169bb8d88..72bc8bd7980 100644
--- a/spec/lib/bulk_imports/pipeline_spec.rb
+++ b/spec/lib/bulk_imports/pipeline_spec.rb
@@ -20,16 +20,17 @@ RSpec.describe BulkImports::Pipeline do
loader BulkImports::Loader, foo: :bar
end
- stub_const('BulkImports::MyPipeline', klass)
+ stub_const('BulkImports::TestWikiPipeline', klass)
end
describe 'pipeline attributes' do
describe 'getters' do
it 'retrieves class attributes' do
- expect(BulkImports::MyPipeline.get_extractor).to eq({ klass: BulkImports::Extractor, options: { foo: :bar } })
- expect(BulkImports::MyPipeline.transformers).to contain_exactly({ klass: BulkImports::Transformer, options: { foo: :bar } })
- expect(BulkImports::MyPipeline.get_loader).to eq({ klass: BulkImports::Loader, options: { foo: :bar } })
- expect(BulkImports::MyPipeline.abort_on_failure?).to eq(true)
+ expect(BulkImports::TestWikiPipeline.get_extractor).to eq({ klass: BulkImports::Extractor, options: { foo: :bar } })
+ expect(BulkImports::TestWikiPipeline.transformers).to contain_exactly({ klass: BulkImports::Transformer, options: { foo: :bar } })
+ expect(BulkImports::TestWikiPipeline.get_loader).to eq({ klass: BulkImports::Loader, options: { foo: :bar } })
+ expect(BulkImports::TestWikiPipeline.abort_on_failure?).to eq(true)
+ expect(BulkImports::TestWikiPipeline.relation).to eq('test_wiki')
end
context 'when extractor and loader are defined within the pipeline' do
@@ -59,23 +60,23 @@ RSpec.describe BulkImports::Pipeline do
klass = Class.new
options = { test: :test }
- BulkImports::MyPipeline.extractor(klass, options)
- BulkImports::MyPipeline.transformer(klass, options)
- BulkImports::MyPipeline.loader(klass, options)
- BulkImports::MyPipeline.abort_on_failure!
- BulkImports::MyPipeline.file_extraction_pipeline!
+ BulkImports::TestWikiPipeline.extractor(klass, options)
+ BulkImports::TestWikiPipeline.transformer(klass, options)
+ BulkImports::TestWikiPipeline.loader(klass, options)
+ BulkImports::TestWikiPipeline.abort_on_failure!
+ BulkImports::TestWikiPipeline.file_extraction_pipeline!
- expect(BulkImports::MyPipeline.get_extractor).to eq({ klass: klass, options: options })
+ expect(BulkImports::TestWikiPipeline.get_extractor).to eq({ klass: klass, options: options })
- expect(BulkImports::MyPipeline.transformers)
+ expect(BulkImports::TestWikiPipeline.transformers)
.to contain_exactly(
{ klass: BulkImports::Transformer, options: { foo: :bar } },
{ klass: klass, options: options })
- expect(BulkImports::MyPipeline.get_loader).to eq({ klass: klass, options: options })
+ expect(BulkImports::TestWikiPipeline.get_loader).to eq({ klass: klass, options: options })
- expect(BulkImports::MyPipeline.abort_on_failure?).to eq(true)
- expect(BulkImports::MyPipeline.file_extraction_pipeline?).to eq(true)
+ expect(BulkImports::TestWikiPipeline.abort_on_failure?).to eq(true)
+ expect(BulkImports::TestWikiPipeline.file_extraction_pipeline?).to eq(true)
end
end
end
@@ -87,7 +88,7 @@ RSpec.describe BulkImports::Pipeline do
expect(BulkImports::Transformer).to receive(:new).with(foo: :bar)
expect(BulkImports::Loader).to receive(:new).with(foo: :bar)
- pipeline = BulkImports::MyPipeline.new(context)
+ pipeline = BulkImports::TestWikiPipeline.new(context)
pipeline.send(:extractor)
pipeline.send(:transformers)
diff --git a/spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb
index 39b539ece21..6a509ca7f14 100644
--- a/spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb
@@ -8,7 +8,10 @@ RSpec.describe BulkImports::Projects::Pipelines::DesignBundlePipeline do
let(:portable) { create(:project) }
let(:tmpdir) { Dir.mktmpdir }
let(:design_bundle_path) { File.join(tmpdir, 'design.bundle') }
- let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test') }
+ let(:entity) do
+ create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test', source_xid: nil)
+ end
+
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
diff --git a/spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb
index 712c37ee578..b8c21feb05d 100644
--- a/spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb
@@ -8,7 +8,10 @@ RSpec.describe BulkImports::Projects::Pipelines::RepositoryBundlePipeline do
let(:portable) { create(:project) }
let(:tmpdir) { Dir.mktmpdir }
let(:bundle_path) { File.join(tmpdir, 'repository.bundle') }
- let(:entity) { create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test') }
+ let(:entity) do
+ create(:bulk_import_entity, :project_entity, project: portable, source_full_path: 'test', source_xid: nil)
+ end
+
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index f9e08df3399..cb2da24b712 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -423,6 +423,22 @@ RSpec.describe ContainerRegistry::Client do
end
end
+ describe '#repository_tags' do
+ let(:path) { 'repository/path' }
+
+ subject { client.repository_tags(path) }
+
+ before do
+ stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
+ end
+
+ it 'returns a successful response' do
+ stub_registry_tags_list(query_params: { n: described_class::DEFAULT_TAGS_PAGE_SIZE }, tags: %w[t1 t2])
+
+ expect(subject).to eq('tags' => %w[t1 t2])
+ end
+ end
+
describe '.registry_info' do
subject { described_class.registry_info }
@@ -458,6 +474,22 @@ RSpec.describe ContainerRegistry::Client do
)
end
+ def stub_registry_tags_list(query_params: {}, status: 200, tags: ['test_tag'])
+ url = "#{registry_api_url}/v2/#{path}/tags/list"
+
+ unless query_params.empty?
+ url += "?"
+ url += query_params.map { |k, v| "#{k}=#{v}" }.join(',')
+ end
+
+ stub_request(:get, url)
+ .with(headers: { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') })
+ .to_return(
+ status: status,
+ body: Gitlab::Json.dump(tags: tags),
+ headers: { 'Content-Type' => 'application/json' })
+ end
+
def expect_new_faraday(times: 1, timeout: true)
request_options = timeout ? expected_faraday_request_options : nil
expect(Faraday)
diff --git a/spec/lib/container_registry/gitlab_api_client_spec.rb b/spec/lib/container_registry/gitlab_api_client_spec.rb
index f19bedbda0e..7d78aad8b13 100644
--- a/spec/lib/container_registry/gitlab_api_client_spec.rb
+++ b/spec/lib/container_registry/gitlab_api_client_spec.rb
@@ -307,7 +307,16 @@ RSpec.describe ContainerRegistry::GitlabApiClient do
stub_tags(path, page_size: page_size, status_code: 404)
end
- it { is_expected.to eq({}) }
+ it 'logs an error and returns an empty hash' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception).with(
+ instance_of(described_class::UnsuccessfulResponseError),
+ class: described_class.name,
+ url: "/gitlab/v1/repositories/#{path}/tags/list/",
+ status_code: 404
+ )
+ expect(subject).to eq({})
+ end
end
end
diff --git a/spec/lib/csv_builders/stream_spec.rb b/spec/lib/csv_builders/stream_spec.rb
index 204baf965d0..7df55fe4230 100644
--- a/spec/lib/csv_builders/stream_spec.rb
+++ b/spec/lib/csv_builders/stream_spec.rb
@@ -25,18 +25,20 @@ RSpec.describe CsvBuilders::Stream do
end
it 'returns all rows up to default max value' do
- expect(builder.render.to_a).to eq([
- "Title,Description\n",
- "Added salt,A teaspoon\n",
- "Added sugar,Just a pinch\n"
- ])
+ expect(builder.render.to_a).to eq(
+ [
+ "Title,Description\n",
+ "Added salt,A teaspoon\n",
+ "Added sugar,Just a pinch\n"
+ ])
end
it 'truncates to max rows' do
- expect(builder.render(1).to_a).to eq([
- "Title,Description\n",
- "Added salt,A teaspoon\n"
- ])
+ expect(builder.render(1).to_a).to eq(
+ [
+ "Title,Description\n",
+ "Added salt,A teaspoon\n"
+ ])
end
end
end
diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb
index 1108d26b2a9..0c5d587d8e8 100644
--- a/spec/lib/expand_variables_spec.rb
+++ b/spec/lib/expand_variables_spec.rb
@@ -87,9 +87,7 @@ RSpec.describe ExpandVariables do
"simple expansion using Collection": {
value: 'key$variable',
result: 'keyvalue',
- variables: Gitlab::Ci::Variables::Collection.new([
- { key: 'variable', value: 'value' }
- ])
+ variables: Gitlab::Ci::Variables::Collection.new([{ key: 'variable', value: 'value' }])
}
}
end
diff --git a/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb b/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb
index 34c5bd6c6ae..06438f8497d 100644
--- a/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb
@@ -23,10 +23,11 @@ RSpec.describe Gitlab::Analytics::UsageTrends::WorkersArgumentBuilder do
subject { described_class.new(measurement_identifiers: measurement_identifiers, recorded_at: recorded_at).execute }
it 'returns worker arguments' do
- expect(subject).to eq([
- [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
- [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
- ])
+ expect(subject).to eq(
+ [
+ [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
+ [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
+ ])
end
context 'when bogus measurement identifiers are given' do
@@ -36,10 +37,11 @@ RSpec.describe Gitlab::Analytics::UsageTrends::WorkersArgumentBuilder do
end
it 'skips bogus measurement identifiers' do
- expect(subject).to eq([
- [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
- [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
- ])
+ expect(subject).to eq(
+ [
+ [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
+ [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
+ ])
end
end
diff --git a/spec/lib/gitlab/anonymous_session_spec.rb b/spec/lib/gitlab/anonymous_session_spec.rb
index 64186e9003a..08087096d49 100644
--- a/spec/lib/gitlab/anonymous_session_spec.rb
+++ b/spec/lib/gitlab/anonymous_session_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_sessions do
subject.cleanup_session_per_ip_count
Gitlab::Redis::Sessions.with do |redis|
- expect(redis.exists("session:lookup:ip:gitlab2:127.0.0.1")).to eq(false)
+ expect(redis.exists?("session:lookup:ip:gitlab2:127.0.0.1")).to eq(false)
end
end
end
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index d0b44135a2f..e2226952d15 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -188,7 +188,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
it 'returns nil if valid feed_token and disabled' do
- stub_application_setting(disable_feed_token: true)
+ allow(Gitlab::CurrentSettings).to receive_messages(disable_feed_token: true)
set_param(:feed_token, user.feed_token)
expect(find_user_from_feed_token(:rss)).to be_nil
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index b160f322fb8..95a518afcf1 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth::OAuth::User do
include LdapHelpers
- include TermsHelper
let(:oauth_user) { described_class.new(auth_hash) }
let(:oauth_user_2) { described_class.new(auth_hash_2) }
@@ -145,49 +144,6 @@ RSpec.describe Gitlab::Auth::OAuth::User do
expect(gl_user).to be_password_automatically_set
end
- context 'terms of service' do
- context 'when terms are enforced' do
- before do
- enforce_terms
- end
-
- context 'when feature flag update_oauth_registration_flow is enabled' do
- before do
- stub_feature_flags(update_oauth_registration_flow: true)
- end
-
- it 'creates the user with accepted terms' do
- oauth_user.save # rubocop:disable Rails/SaveBang
-
- expect(gl_user).to be_persisted
- expect(gl_user.terms_accepted?).to be(true)
- end
- end
-
- context 'when feature flag update_oauth_registration_flow is disabled' do
- before do
- stub_feature_flags(update_oauth_registration_flow: false)
- end
-
- it 'creates the user without accepted terms' do
- oauth_user.save # rubocop:disable Rails/SaveBang
-
- expect(gl_user).to be_persisted
- expect(gl_user.terms_accepted?).to be(false)
- end
- end
- end
-
- context 'when terms are not enforced' do
- it 'creates the user without accepted terms' do
- oauth_user.save # rubocop:disable Rails/SaveBang
-
- expect(gl_user).to be_persisted
- expect(gl_user.terms_accepted?).to be(false)
- end
- end
- end
-
shared_examples 'to verify compliance with allow_single_sign_on' do
context 'provider is marked as external' do
it 'marks user as external' do
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index c2d64aa2fb3..5a6fa7c416b 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -495,6 +495,12 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
end
end
+
+ it 'updates last_used_at column if token is valid' do
+ personal_access_token = create(:personal_access_token, scopes: ['write_repository'])
+
+ expect { gl_auth.find_for_git_client('', personal_access_token.token, project: nil, ip: 'ip') }.to change { personal_access_token.reload.last_used_at }
+ end
end
context 'while using regular user and password' do
diff --git a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb
index d8a7ec775dd..e6588644b4f 100644
--- a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb
@@ -7,13 +7,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat
let(:integrations) { table(:integrations) }
let(:namespaced_integrations) do
- Set.new(%w[
- Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
- Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost
- MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker
- Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao
- Github GitlabSlackApplication
- ]).freeze
+ Set.new(
+ %w[
+ Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
+ Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost
+ MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker
+ Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao
+ Github GitlabSlackApplication
+ ]).freeze
end
before do
@@ -40,13 +41,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat
expect(queries.count).to be(16)
expect(queries.log.grep(/^SELECT/).size).to be(11)
expect(queries.log.grep(/^UPDATE/).size).to be(5)
- expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq([
- 'WHERE integrations.id BETWEEN 2 AND 3',
- 'WHERE integrations.id BETWEEN 4 AND 5',
- 'WHERE integrations.id BETWEEN 6 AND 7',
- 'WHERE integrations.id BETWEEN 8 AND 9',
- 'WHERE integrations.id BETWEEN 10 AND 10'
- ])
+ expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq(
+ [
+ 'WHERE integrations.id BETWEEN 2 AND 3',
+ 'WHERE integrations.id BETWEEN 4 AND 5',
+ 'WHERE integrations.id BETWEEN 6 AND 7',
+ 'WHERE integrations.id BETWEEN 8 AND 9',
+ 'WHERE integrations.id BETWEEN 10 AND 10'
+ ])
expect(integrations.where(id: 2..10).pluck(:type, :type_new)).to contain_exactly(
['AssemblaService', 'Integrations::Assembla'],
diff --git a/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb
new file mode 100644
index 00000000000..40a4758ba5f
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillInternalOnNotes, :migration, schema: 20220920124709 do
+ let(:notes_table) { table(:notes) }
+
+ let!(:confidential_note) { notes_table.create!(id: 1, confidential: true, internal: false) }
+ let!(:non_confidential_note) { notes_table.create!(id: 2, confidential: false, internal: false) }
+
+ describe '#perform' do
+ subject(:perform) do
+ described_class.new(
+ start_id: 1,
+ end_id: 2,
+ batch_table: :notes,
+ batch_column: :id,
+ sub_batch_size: 1,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ ).perform
+ end
+
+ it 'backfills internal column on notes when confidential' do
+ expect { perform }
+ .to change { confidential_note.reload.internal }.from(false).to(true)
+ .and not_change { non_confidential_note.reload.internal }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb
new file mode 100644
index 00000000000..b6282de0da6
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceDetails, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:namespace_details) { table(:namespace_details) }
+
+ subject(:perform_migration) do
+ described_class.new(start_id: namespaces.minimum(:id),
+ end_id: namespaces.maximum(:id),
+ batch_table: :namespaces,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection)
+ .perform
+ end
+
+ describe '#perform' do
+ it 'creates details for all namespaces in range' do
+ namespace1 = namespaces.create!(id: 5, name: 'test1', path: 'test1', description: "Some description1",
+ description_html: "Some description html1", cached_markdown_version: 4)
+ namespaces.create!(id: 6, name: 'test2', path: 'test2', type: 'Project',
+ description: "Some description2", description_html: "Some description html2",
+ cached_markdown_version: 4)
+ namespace3 = namespaces.create!(id: 7, name: 'test3', path: 'test3', description: "Some description3",
+ description_html: "Some description html3", cached_markdown_version: 4)
+ namespace4 = namespaces.create!(id: 8, name: 'test4', path: 'test4', description: "Some description3",
+ description_html: "Some description html4", cached_markdown_version: 4)
+ namespace_details.delete_all
+
+ expect(namespace_details.pluck(:namespace_id)).to eql []
+
+ expect { perform_migration }
+ .to change { namespace_details.pluck(:namespace_id) }.from([]).to contain_exactly(
+ namespace1.id,
+ namespace3.id,
+ namespace4.id
+ )
+
+ expect(namespace_details.find_by_namespace_id(namespace1.id)).to have_attributes(migrated_attributes(namespace1))
+ expect(namespace_details.find_by_namespace_id(namespace3.id)).to have_attributes(migrated_attributes(namespace3))
+ expect(namespace_details.find_by_namespace_id(namespace4.id)).to have_attributes(migrated_attributes(namespace4))
+ end
+ end
+
+ def migrated_attributes(namespace)
+ {
+ description: namespace.description,
+ description_html: namespace.description_html,
+ cached_markdown_version: namespace.cached_markdown_version
+ }
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb
index 8a3671b2e53..dd202acc372 100644
--- a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb
@@ -40,23 +40,26 @@ RSpec.describe Gitlab::BackgroundMigration::CleanupOrphanedLfsObjectsProjects, s
it 'lfs_objects_projects without an existing lfs object or project are removed' do
subject.perform(without_object1.id, without_object3.id)
- expect(lfs_objects_projects.all).to match_array([
- with_project_and_object1, with_project_and_object2, with_project_and_object3,
- without_project1, without_project2, without_project_and_object
- ])
+ expect(lfs_objects_projects.all).to match_array(
+ [
+ with_project_and_object1, with_project_and_object2, with_project_and_object3,
+ without_project1, without_project2, without_project_and_object
+ ])
subject.perform(with_project_and_object1.id, with_project_and_object3.id)
- expect(lfs_objects_projects.all).to match_array([
- with_project_and_object1, with_project_and_object2, with_project_and_object3,
- without_project1, without_project2, without_project_and_object
- ])
+ expect(lfs_objects_projects.all).to match_array(
+ [
+ with_project_and_object1, with_project_and_object2, with_project_and_object3,
+ without_project1, without_project2, without_project_and_object
+ ])
subject.perform(without_project1.id, without_project_and_object.id)
- expect(lfs_objects_projects.all).to match_array([
- with_project_and_object1, with_project_and_object2, with_project_and_object3
- ])
+ expect(lfs_objects_projects.all).to match_array(
+ [
+ with_project_and_object1, with_project_and_object2, with_project_and_object3
+ ])
expect(lfs_objects.ids).to contain_exactly(lfs_object.id, another_lfs_object.id)
expect(projects.ids).to contain_exactly(project.id, another_project.id)
diff --git a/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..afa955a6056
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::DeleteOrphanedOperationalVulnerabilities, :migration do
+ include MigrationHelpers::VulnerabilitiesHelper
+
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let_it_be(:users) { table(:users) }
+ let_it_be(:user) do
+ users.create!(
+ name: "Example User",
+ email: "user@example.com",
+ username: "Example User",
+ projects_limit: 0,
+ confirmed_at: Time.current
+ )
+ end
+
+ let_it_be(:project) do
+ table(:projects).create!(
+ id: 123,
+ namespace_id: namespace.id,
+ project_namespace_id: namespace.id
+ )
+ end
+
+ let_it_be(:scanners) { table(:vulnerability_scanners) }
+ let_it_be(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let_it_be(:different_scanner) do
+ scanners.create!(
+ project_id: project.id,
+ external_id: 'test 2',
+ name: 'test scanner 2'
+ )
+ end
+
+ let_it_be(:vulnerabilities) { table(:vulnerabilities) }
+ let_it_be(:vulnerability_with_finding) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let_it_be(:vulnerability_without_finding) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let_it_be(:cis_vulnerability_without_finding) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id,
+ report_type: 7
+ )
+ end
+
+ let_it_be(:custom_vulnerability_without_finding) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id,
+ report_type: 99
+ )
+ end
+
+ let_it_be(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let_it_be(:primary_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ let_it_be(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let_it_be(:finding) do
+ create_finding!(
+ vulnerability_id: vulnerability_with_finding.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: primary_identifier.id
+ )
+ end
+
+ subject(:background_migration) do
+ described_class.new(start_id: vulnerabilities.minimum(:id),
+ end_id: vulnerabilities.maximum(:id),
+ batch_table: :vulnerabilities,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection)
+ end
+
+ it 'drops Cluster Image Scanning and Custom Vulnerabilities without any Findings' do
+ expect(vulnerabilities.pluck(:id)).to match_array([
+ vulnerability_with_finding.id,
+ vulnerability_without_finding.id,
+ cis_vulnerability_without_finding.id,
+ custom_vulnerability_without_finding.id
+ ])
+
+ expect { background_migration.perform }.to change(vulnerabilities, :count).by(-2)
+
+ expect(vulnerabilities.pluck(:id)).to match_array([vulnerability_with_finding.id, vulnerability_without_finding.id])
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb b/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb
new file mode 100644
index 00000000000..9b0cb96b30b
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# rubocop: disable RSpec/MultipleMemoizedHelpers
+RSpec.describe Gitlab::BackgroundMigration::DestroyInvalidMembers, :migration, schema: 20221004094814 do
+ let!(:migration_attrs) do
+ {
+ start_id: 1,
+ end_id: 1000,
+ batch_table: :members,
+ batch_column: :id,
+ sub_batch_size: 100,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ }
+ end
+
+ let(:users_table) { table(:users) }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:members_table) { table(:members) }
+ let(:projects_table) { table(:projects) }
+ let(:members_table_name) { 'members' }
+ let(:connection) { ApplicationRecord.connection }
+ let(:user1) { users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 5) }
+ let(:user2) { users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 5) }
+ let(:user3) { users_table.create!(name: 'user3', email: 'user3@example.com', projects_limit: 5) }
+ let(:user4) { users_table.create!(name: 'user4', email: 'user4@example.com', projects_limit: 5) }
+ let(:user5) { users_table.create!(name: 'user5', email: 'user5@example.com', projects_limit: 5) }
+ let(:user6) { users_table.create!(name: 'user6', email: 'user6@example.com', projects_limit: 5) }
+ let(:user7) { users_table.create!(name: 'user7', email: 'user7@example.com', projects_limit: 5) }
+ let(:user8) { users_table.create!(name: 'user8', email: 'user8@example.com', projects_limit: 5) }
+ let!(:group1) { namespaces_table.create!(name: 'marvellous group 1', path: 'group-path-1', type: 'Group') }
+ let!(:group2) { namespaces_table.create!(name: 'outstanding group 2', path: 'group-path-2', type: 'Group') }
+ let!(:project_namespace1) do
+ namespaces_table.create!(name: 'fabulous project', path: 'project-path-1',
+ type: 'ProjectNamespace', parent_id: group1.id)
+ end
+
+ let!(:project1) do
+ projects_table.create!(name: 'fabulous project', path: 'project-path-1',
+ project_namespace_id: project_namespace1.id, namespace_id: group1.id)
+ end
+
+ let!(:project_namespace2) do
+ namespaces_table.create!(name: 'splendiferous project', path: 'project-path-2',
+ type: 'ProjectNamespace', parent_id: group1.id)
+ end
+
+ let!(:project2) do
+ projects_table.create!(name: 'splendiferous project', path: 'project-path-2',
+ project_namespace_id: project_namespace2.id, namespace_id: group1.id)
+ end
+
+ # create valid project member records
+ let!(:project_member1) { create_valid_project_member(id: 1, user_id: user1.id, project: project1) }
+ let!(:project_member2) { create_valid_project_member(id: 2, user_id: user2.id, project: project2) }
+ # create valid group member records
+ let!(:group_member5) { create_valid_group_member(id: 5, user_id: user5.id, group_id: group1.id) }
+ let!(:group_member6) { create_valid_group_member(id: 6, user_id: user6.id, group_id: group2.id) }
+
+ let!(:migration) { described_class.new(**migration_attrs) }
+
+ subject(:perform_migration) { migration.perform }
+
+ # create invalid project and group member records
+ def create_members
+ [
+ create_invalid_project_member(id: 3, user_id: user3.id),
+ create_invalid_project_member(id: 4, user_id: user4.id),
+ create_invalid_group_member(id: 7, user_id: user7.id),
+ create_invalid_group_member(id: 8, user_id: user8.id)
+ ]
+ end
+
+ it 'removes invalid memberships but keeps valid ones', :aggregate_failures do
+ without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do
+ create_members
+
+ expect(members_table.count).to eq 8
+
+ queries = ActiveRecord::QueryRecorder.new do
+ perform_migration
+ end
+
+ expect(queries.count).to eq(4)
+ expect(members_table.all).to match_array([project_member1, project_member2, group_member5, group_member6])
+ end
+ end
+
+ it 'tracks timings of queries' do
+ without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do
+ create_members
+
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { perform_migration }.to change { migration.batch_metrics.timings }
+ end
+ end
+
+ it 'logs IDs of deleted records' do
+ without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do
+ members = create_members
+
+ member_data = members.map do |m|
+ { id: m.id, source_id: m.source_id, source_type: m.source_type }
+ end
+
+ expect(Gitlab::AppLogger).to receive(:info).with({ message: 'Removing invalid member records',
+ deleted_count: 4,
+ deleted_member_data: member_data })
+
+ perform_migration
+ end
+ end
+
+ def create_invalid_project_member(id:, user_id:)
+ members_table.create!(id: id, user_id: user_id, source_id: non_existing_record_id,
+ access_level: Gitlab::Access::MAINTAINER, type: "ProjectMember",
+ source_type: "Project", notification_level: 3, member_namespace_id: nil)
+ end
+
+ def create_valid_project_member(id:, user_id:, project:)
+ members_table.create!(id: id, user_id: user_id, source_id: project.id,
+ access_level: Gitlab::Access::MAINTAINER, type: "ProjectMember", source_type: "Project",
+ member_namespace_id: project.project_namespace_id, notification_level: 3)
+ end
+
+ def create_invalid_group_member(id:, user_id:)
+ members_table.create!(id: id, user_id: user_id, source_id: non_existing_record_id,
+ access_level: Gitlab::Access::MAINTAINER, type: "GroupMember",
+ source_type: "Namespace", notification_level: 3, member_namespace_id: nil)
+ end
+
+ def create_valid_group_member(id:, user_id:, group_id:)
+ members_table.create!(id: id, user_id: user_id, source_id: group_id,
+ access_level: Gitlab::Access::MAINTAINER, type: "GroupMember",
+ source_type: "Namespace", member_namespace_id: group_id, notification_level: 3)
+ end
+end
+# rubocop: enable RSpec/MultipleMemoizedHelpers
diff --git a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
index 31b6ee0c7cd..c3ae2cc060c 100644
--- a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
@@ -79,10 +79,11 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers,
it 'produces a union of the given queries' do
alice = commit_users.create!(name: 'Alice', email: 'alice@example.com')
bob = commit_users.create!(name: 'Bob', email: 'bob@example.com')
- users = commit_users.union([
- commit_users.where(name: 'Alice').to_sql,
- commit_users.where(name: 'Bob').to_sql
- ])
+ users = commit_users.union(
+ [
+ commit_users.where(name: 'Alice').to_sql,
+ commit_users.where(name: 'Bob').to_sql
+ ])
expect(users).to include(alice)
expect(users).to include(bob)
diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
index a609227be05..29cc4f34f6d 100644
--- a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
+++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
@@ -246,9 +246,15 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence
end
it 'drops duplicates and related records', :aggregate_failures do
- expect(vulnerability_findings.pluck(:id)).to match_array([
- finding_with_correct_uuid.id, finding_with_incorrect_uuid.id, finding_with_correct_uuid2.id, finding_with_incorrect_uuid2.id, finding_with_incorrect_uuid3.id, duplicate_not_in_the_same_batch.id
- ])
+ expect(vulnerability_findings.pluck(:id)).to match_array(
+ [
+ finding_with_correct_uuid.id,
+ finding_with_incorrect_uuid.id,
+ finding_with_correct_uuid2.id,
+ finding_with_incorrect_uuid2.id,
+ finding_with_incorrect_uuid3.id,
+ duplicate_not_in_the_same_batch.id
+ ])
expect { subject }.to change(vulnerability_finding_pipelines, :count).from(16).to(8)
.and change(vulnerability_findings, :count).from(6).to(3)
@@ -306,7 +312,8 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence
it 'retries the recalculation' do
subject
- expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding).to have_received(:find_by).with(uuid: uuid).once
+ expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding)
+ .to have_received(:find_by).with(uuid: uuid).once
end
it 'logs the conflict' do
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb
new file mode 100644
index 00000000000..b6da8f7fc2d
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValues,
+ :migration,
+ schema: 20220922143634 do
+ it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob }
+
+ describe '#perform' do
+ let(:ci_runners) { table(:ci_runners, database: :ci) }
+
+ let(:test_worker) do
+ described_class.new(
+ start_id: 1,
+ end_id: 4,
+ batch_table: :ci_runners,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: Ci::ApplicationRecord.connection
+ )
+ end
+
+ subject(:perform) { test_worker.perform }
+
+ before do
+ ci_runners.create!(id: 1, runner_type: 1, token_encrypted: 'duplicate')
+ ci_runners.create!(id: 2, runner_type: 1, token_encrypted: 'a-token')
+ ci_runners.create!(id: 3, runner_type: 1, token_encrypted: 'duplicate-2')
+ ci_runners.create!(id: 4, runner_type: 1, token_encrypted: nil)
+ ci_runners.create!(id: 5, runner_type: 1, token_encrypted: 'duplicate-2')
+ ci_runners.create!(id: 6, runner_type: 1, token_encrypted: 'duplicate')
+ ci_runners.create!(id: 7, runner_type: 1, token_encrypted: 'another-token')
+ ci_runners.create!(id: 8, runner_type: 1, token_encrypted: 'another-token')
+ end
+
+ it 'nullifies duplicate encrypted tokens', :aggregate_failures do
+ expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token_encrypted).to_h }
+ .from(
+ {
+ 1 => 'duplicate',
+ 2 => 'a-token',
+ 3 => 'duplicate-2',
+ 4 => nil,
+ 5 => 'duplicate-2',
+ 6 => 'duplicate',
+ 7 => 'another-token',
+ 8 => 'another-token'
+ }
+ )
+ .to(
+ {
+ 1 => nil,
+ 2 => 'a-token',
+ 3 => nil,
+ 4 => nil,
+ 5 => nil,
+ 6 => nil,
+ 7 => 'another-token',
+ 8 => 'another-token'
+ }
+ )
+ expect(ci_runners.count).to eq(8)
+ expect(ci_runners.pluck(:token_encrypted).uniq).to match_array [
+ nil, 'a-token', 'another-token'
+ ]
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb
new file mode 100644
index 00000000000..423b1815e75
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValues,
+ :migration,
+ schema: 20220922143143 do
+ it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob }
+
+ describe '#perform' do
+ let(:ci_runners) { table(:ci_runners, database: :ci) }
+
+ let(:test_worker) do
+ described_class.new(
+ start_id: 1,
+ end_id: 4,
+ batch_table: :ci_runners,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: Ci::ApplicationRecord.connection
+ )
+ end
+
+ subject(:perform) { test_worker.perform }
+
+ before do
+ ci_runners.create!(id: 1, runner_type: 1, token: 'duplicate')
+ ci_runners.create!(id: 2, runner_type: 1, token: 'a-token')
+ ci_runners.create!(id: 3, runner_type: 1, token: 'duplicate-2')
+ ci_runners.create!(id: 4, runner_type: 1, token: nil)
+ ci_runners.create!(id: 5, runner_type: 1, token: 'duplicate-2')
+ ci_runners.create!(id: 6, runner_type: 1, token: 'duplicate')
+ ci_runners.create!(id: 7, runner_type: 1, token: 'another-token')
+ ci_runners.create!(id: 8, runner_type: 1, token: 'another-token')
+ end
+
+ it 'nullifies duplicate tokens', :aggregate_failures do
+ expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token).to_h }
+ .from(
+ {
+ 1 => 'duplicate',
+ 2 => 'a-token',
+ 3 => 'duplicate-2',
+ 4 => nil,
+ 5 => 'duplicate-2',
+ 6 => 'duplicate',
+ 7 => 'another-token',
+ 8 => 'another-token'
+ }
+ )
+ .to(
+ {
+ 1 => nil,
+ 2 => 'a-token',
+ 3 => nil,
+ 4 => nil,
+ 5 => nil,
+ 6 => nil,
+ 7 => 'another-token',
+ 8 => 'another-token'
+ }
+ )
+ expect(ci_runners.count).to eq(8)
+ expect(ci_runners.pluck(:token).uniq).to match_array [
+ nil, 'a-token', 'another-token'
+ ]
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb b/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb
new file mode 100644
index 00000000000..98939e15952
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::UpdateCiPipelineArtifactsUnknownLockedStatus do
+ describe '#perform' do
+ let(:batch_table) { :ci_pipeline_artifacts }
+ let(:batch_column) { :id }
+
+ let(:sub_batch_size) { 1 }
+ let(:pause_ms) { 0 }
+ let(:connection) { Ci::ApplicationRecord.connection }
+
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:pipelines) { table(:ci_pipelines, database: :ci) }
+ let(:pipeline_artifacts) { table(:ci_pipeline_artifacts, database: :ci) }
+
+ let(:namespace) { namespaces.create!(name: 'name', path: 'path') }
+ let(:project) do
+ projects
+ .create!(name: "project", path: "project", namespace_id: namespace.id, project_namespace_id: namespace.id)
+ end
+
+ let(:unlocked) { 0 }
+ let(:locked) { 1 }
+ let(:unknown) { 2 }
+
+ let(:unlocked_pipeline) { pipelines.create!(locked: unlocked) }
+ let(:locked_pipeline) { pipelines.create!(locked: locked) }
+
+ # rubocop:disable Layout/LineLength
+ let!(:locked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: locked_pipeline.id, size: 1024, file_type: 0, file_format: 'gzip', file: 'a.gz', locked: unknown) }
+ let!(:unlocked_artifact_1) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 2048, file_type: 1, file_format: 'raw', file: 'b', locked: unknown) }
+ let!(:unlocked_artifact_2) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 4096, file_type: 2, file_format: 'gzip', file: 'c.gz', locked: unknown) }
+ let!(:already_unlocked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 8192, file_type: 3, file_format: 'raw', file: 'd', locked: unlocked) }
+ let!(:already_locked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: locked_pipeline.id, size: 8192, file_type: 3, file_format: 'raw', file: 'd', locked: locked) }
+ # rubocop:enable Layout/LineLength
+
+ subject do
+ described_class.new(
+ start_id: locked_artifact.id,
+ end_id: already_locked_artifact.id,
+ batch_table: batch_table,
+ batch_column: batch_column,
+ sub_batch_size: sub_batch_size,
+ pause_ms: pause_ms,
+ connection: connection
+ ).perform
+ end
+
+ it 'updates ci_pipeline_artifacts with unknown lock status' do
+ subject
+
+ expect(locked_artifact.reload.locked).to eq(locked)
+ expect(unlocked_artifact_1.reload.locked).to eq(unlocked)
+ expect(unlocked_artifact_2.reload.locked).to eq(unlocked)
+ expect(already_unlocked_artifact.reload.locked).to eq(unlocked)
+ expect(already_locked_artifact.reload.locked).to eq(locked)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/bare_repository_import/importer_spec.rb b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
index 8fb903154f3..3a885d70eb4 100644
--- a/spec/lib/gitlab/bare_repository_import/importer_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
@@ -192,6 +192,6 @@ RSpec.describe Gitlab::BareRepositoryImport::Importer do
cmd = %W(#{Gitlab.config.git.bin_path} clone --bare #{source_project} #{repo_path})
- system(git_env, *cmd, chdir: SEED_STORAGE_PATH, out: '/dev/null', err: '/dev/null')
+ system(git_env, *cmd, chdir: base_dir, out: '/dev/null', err: '/dev/null')
end
end
diff --git a/spec/lib/gitlab/bare_repository_import/repository_spec.rb b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
index becfdced5fb..a9778e0e8a7 100644
--- a/spec/lib/gitlab/bare_repository_import/repository_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe ::Gitlab::BareRepositoryImport::Repository do
context 'hashed storage' do
let(:hashed_path) { "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" }
- let(:root_path) { TestEnv.repos_path }
+ let(:root_path) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path } }
let(:repo_path) { File.join(root_path, "#{hashed_path}.git") }
let(:wiki_path) { File.join(root_path, "#{hashed_path}.wiki.git") }
let(:raw_repository) { Gitlab::Git::Repository.new('default', "#{hashed_path}.git", nil, nil) }
diff --git a/spec/lib/gitlab/batch_pop_queueing_spec.rb b/spec/lib/gitlab/batch_pop_queueing_spec.rb
deleted file mode 100644
index 5af78ddabe7..00000000000
--- a/spec/lib/gitlab/batch_pop_queueing_spec.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BatchPopQueueing do
- include ExclusiveLeaseHelpers
- using RSpec::Parameterized::TableSyntax
-
- describe '#initialize' do
- where(:namespace, :queue_id, :expect_error, :error_type) do
- 'feature' | '1' | false | nil
- :feature | '1' | false | nil
- nil | '1' | true | NoMethodError
- 'feature' | nil | true | NoMethodError
- '' | '1' | true | ArgumentError
- 'feature' | '' | true | ArgumentError
- 'feature' | 1 | true | NoMethodError
- end
-
- with_them do
- it do
- if expect_error
- expect { described_class.new(namespace, queue_id) }.to raise_error(error_type)
- else
- expect { described_class.new(namespace, queue_id) }.not_to raise_error
- end
- end
- end
- end
-
- describe '#safe_execute', :clean_gitlab_redis_queues do
- subject { queue.safe_execute(new_items, lock_timeout: lock_timeout) }
-
- let(:queue) { described_class.new(namespace, queue_id) }
- let(:namespace) { 'feature' }
- let(:queue_id) { '1' }
- let(:lock_timeout) { 10.minutes }
- let(:new_items) { %w[A B] }
- let(:lock_key) { queue.send(:lock_key) }
- let(:queue_key) { queue.send(:queue_key) }
-
- it 'enqueues new items always' do
- Gitlab::Redis::Queues.with do |redis|
- expect(redis).to receive(:sadd).with(queue_key, new_items)
- expect(redis).to receive(:expire).with(queue_key, (lock_timeout + described_class::EXTRA_QUEUE_EXPIRE_WINDOW).to_i)
- end
-
- subject
- end
-
- it 'yields the new items with exclusive lease' do
- uuid = 'test'
- expect_to_obtain_exclusive_lease(lock_key, uuid, timeout: lock_timeout)
- expect_to_cancel_exclusive_lease(lock_key, uuid)
-
- expect { |b| queue.safe_execute(new_items, lock_timeout: lock_timeout, &b) }
- .to yield_with_args(match_array(new_items))
- end
-
- it 'returns the result and no items in the queue' do
- expect(subject[:status]).to eq(:finished)
- expect(subject[:new_items]).to be_empty
-
- Gitlab::Redis::Queues.with do |redis|
- expect(redis.llen(queue_key)).to be(0)
- end
- end
-
- context 'when new items are enqueued during the process' do
- it 'returns the result with newly added items' do
- result = queue.safe_execute(new_items) do
- queue.safe_execute(['C'])
- end
-
- expect(result[:status]).to eq(:finished)
- expect(result[:new_items]).to eq(['C'])
-
- Gitlab::Redis::Queues.with do |redis|
- expect(redis.scard(queue_key)).to be(1)
- end
- end
- end
-
- context 'when interger items are enqueued' do
- let(:new_items) { [1, 2, 3] }
-
- it 'yields as String values' do
- expect { |b| queue.safe_execute(new_items, lock_timeout: lock_timeout, &b) }
- .to yield_with_args(%w[1 2 3])
- end
- end
-
- context 'when the queue key does not exist in Redis' do
- before do
- allow(queue).to receive(:enqueue) {}
- end
-
- it 'yields empty array' do
- expect { |b| queue.safe_execute(new_items, lock_timeout: lock_timeout, &b) }
- .to yield_with_args([])
- end
- end
-
- context 'when the other process has already been working on the queue' do
- before do
- stub_exclusive_lease_taken(lock_key, timeout: lock_timeout)
- end
-
- it 'does not yield the block' do
- expect { |b| queue.safe_execute(new_items, lock_timeout: lock_timeout, &b) }
- .not_to yield_control
- end
-
- it 'returns the result' do
- expect(subject[:status]).to eq(:enqueued)
- end
- end
-
- context 'when a duplicate item is enqueued' do
- it 'returns the poped items to the queue and raise an error' do
- expect { |b| queue.safe_execute(%w[1 1 2 2], &b) }
- .to yield_with_args(match_array(%w[1 2]))
- end
- end
-
- context 'when there are two queues' do
- it 'enqueues items to each queue' do
- queue_1 = described_class.new(namespace, '1')
- queue_2 = described_class.new(namespace, '2')
-
- result_2 = nil
-
- result_1 = queue_1.safe_execute(['A']) do |_|
- result_2 = queue_2.safe_execute(['B']) do |_|
- queue_1.safe_execute(['C'])
- queue_2.safe_execute(['D'])
- end
- end
-
- expect(result_1[:status]).to eq(:finished)
- expect(result_1[:new_items]).to eq(['C'])
- expect(result_2[:status]).to eq(:finished)
- expect(result_2[:new_items]).to eq(['D'])
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index e0a7044e5f9..186d4e1fb42 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -58,24 +58,15 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
issues
end
- let(:project_identifier) { 'namespace/repo' }
+ let_it_be(:project_identifier) { 'namespace/repo' }
- let(:data) do
- {
- 'bb_session' => {
- 'bitbucket_token' => "123456",
- 'bitbucket_refresh_token' => "secret"
- }
- }
- end
-
- let(:project) do
+ let_it_be_with_reload(:project) do
create(
:project,
:repository,
import_source: project_identifier,
import_url: "https://bitbucket.org/#{project_identifier}.git",
- import_data_attributes: { credentials: data }
+ import_data_attributes: { credentials: { 'token' => 'token' } }
)
end
@@ -88,6 +79,14 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
}
end
+ let(:last_issue_data) do
+ {
+ page: 1,
+ pagelen: 1,
+ values: [sample_issues_statuses.last]
+ }
+ end
+
let(:counter) { double('counter', increment: true) }
subject { described_class.new(project) }
@@ -253,6 +252,13 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
stub_request(
:get,
+ "https://api.bitbucket.org/2.0/repositories/#{project_identifier}/issues?pagelen=1&sort=-created_on&state=ALL"
+ ).to_return(status: 200,
+ headers: { "Content-Type" => "application/json" },
+ body: last_issue_data.to_json)
+
+ stub_request(
+ :get,
"https://api.bitbucket.org/2.0/repositories/#{project_identifier}/issues?pagelen=50&sort=created_on"
).to_return(status: 200,
headers: { "Content-Type" => "application/json" },
@@ -352,6 +358,12 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
end
describe 'issue import' do
+ it 'allocates internal ids' do
+ expect(Issue).to receive(:track_project_iid!).with(project, 6)
+
+ importer.execute
+ end
+
it 'maps reporters to anonymous if bitbucket reporter is nil' do
allow(importer).to receive(:import_wiki)
importer.execute
@@ -371,6 +383,29 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
expect(project.issues.map(&:work_item_type_id).uniq).to contain_exactly(WorkItems::Type.default_issue_type.id)
end
+
+ context 'with issue comments' do
+ let(:inline_note) do
+ instance_double(Bitbucket::Representation::Comment, note: 'Hello world', author: 'someuser', created_at: Time.now, updated_at: Time.now)
+ end
+
+ before do
+ allow_next_instance_of(Bitbucket::Client) do |instance|
+ allow(instance).to receive(:issue_comments).and_return([inline_note])
+ end
+ end
+
+ it 'imports issue comments' do
+ allow(importer).to receive(:import_wiki)
+ importer.execute
+
+ comment = project.notes.first
+ expect(project.notes.size).to eq(7)
+ expect(comment.note).to include(inline_note.note)
+ expect(comment.note).to include(inline_note.author)
+ expect(importer.errors).to be_empty
+ end
+ end
end
context 'metrics' do
diff --git a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
index c0e4d1b5355..c78140a70b3 100644
--- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
+++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
@@ -288,7 +288,7 @@ RSpec.describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cac
it 'deletes values from redis_cache' do
pipeline_status.delete_from_cache
- key_exists = Gitlab::Redis::Cache.with { |redis| redis.exists(cache_key) }
+ key_exists = Gitlab::Redis::Cache.with { |redis| redis.exists?(cache_key) }
expect(key_exists).to be_falsy
end
diff --git a/spec/lib/gitlab/ci/ansi2json_spec.rb b/spec/lib/gitlab/ci/ansi2json_spec.rb
index 4b3b049176f..0f8f3759834 100644
--- a/spec/lib/gitlab/ci/ansi2json_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json_spec.rb
@@ -7,70 +7,74 @@ RSpec.describe Gitlab::Ci::Ansi2json do
describe 'lines' do
it 'prints non-ansi as-is' do
- expect(convert_json('Hello')).to eq([
- { offset: 0, content: [{ text: 'Hello' }] }
- ])
+ expect(convert_json('Hello')).to eq([{ offset: 0, content: [{ text: 'Hello' }] }])
end
context 'new lines' do
it 'adds new line when encountering \n' do
- expect(convert_json("Hello\nworld")).to eq([
- { offset: 0, content: [{ text: 'Hello' }] },
- { offset: 6, content: [{ text: 'world' }] }
- ])
+ expect(convert_json("Hello\nworld")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello' }] },
+ { offset: 6, content: [{ text: 'world' }] }
+ ])
end
it 'adds new line when encountering \r\n' do
- expect(convert_json("Hello\r\nworld")).to eq([
- { offset: 0, content: [{ text: 'Hello' }] },
- { offset: 7, content: [{ text: 'world' }] }
- ])
+ expect(convert_json("Hello\r\nworld")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello' }] },
+ { offset: 7, content: [{ text: 'world' }] }
+ ])
end
it 'ignores empty newlines' do
- expect(convert_json("Hello\n\nworld")).to eq([
- { offset: 0, content: [{ text: 'Hello' }] },
- { offset: 7, content: [{ text: 'world' }] }
- ])
- expect(convert_json("Hello\r\n\r\nworld")).to eq([
- { offset: 0, content: [{ text: 'Hello' }] },
- { offset: 9, content: [{ text: 'world' }] }
- ])
+ expect(convert_json("Hello\n\nworld")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello' }] },
+ { offset: 7, content: [{ text: 'world' }] }
+ ])
+ expect(convert_json("Hello\r\n\r\nworld")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello' }] },
+ { offset: 9, content: [{ text: 'world' }] }
+ ])
end
it 'replace the current line when encountering \r' do
- expect(convert_json("Hello\rworld")).to eq([
- { offset: 0, content: [{ text: 'world' }] }
- ])
+ expect(convert_json("Hello\rworld")).to eq([{ offset: 0, content: [{ text: 'world' }] }])
end
end
it 'recognizes color changing ANSI sequences' do
- expect(convert_json("\e[31mHello\e[0m")).to eq([
- { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] }
- ])
+ expect(convert_json("\e[31mHello\e[0m")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] }
+ ])
end
it 'recognizes color changing ANSI sequences across multiple lines' do
- expect(convert_json("\e[31mHello\nWorld\e[0m")).to eq([
- { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] },
- { offset: 11, content: [{ text: 'World', style: 'term-fg-red' }] }
- ])
+ expect(convert_json("\e[31mHello\nWorld\e[0m")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] },
+ { offset: 11, content: [{ text: 'World', style: 'term-fg-red' }] }
+ ])
end
it 'recognizes background and foreground colors' do
- expect(convert_json("\e[31;44mHello")).to eq([
- { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red term-bg-blue' }] }
- ])
+ expect(convert_json("\e[31;44mHello")).to eq(
+ [
+ { offset: 0, content: [{ text: 'Hello', style: 'term-fg-red term-bg-blue' }] }
+ ])
end
it 'recognizes style changes within the same line' do
- expect(convert_json("\e[31;44mHello\e[0m world")).to eq([
- { offset: 0, content: [
- { text: 'Hello', style: 'term-fg-red term-bg-blue' },
- { text: ' world' }
- ] }
- ])
+ expect(convert_json("\e[31;44mHello\e[0m world")).to eq(
+ [
+ { offset: 0, content: [
+ { text: 'Hello', style: 'term-fg-red term-bg-blue' },
+ { text: ' world' }
+ ] }
+ ])
end
context 'with section markers' do
@@ -82,130 +86,137 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K" }
it 'marks the first line of the section as header' do
- expect(convert_json("Hello#{section_start}world!")).to eq([
- {
- offset: 0,
- content: [{ text: 'Hello' }]
- },
- {
- offset: 5,
- content: [{ text: 'world!' }],
- section: 'prepare-script',
- section_header: true
- }
- ])
+ expect(convert_json("Hello#{section_start}world!")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Hello' }]
+ },
+ {
+ offset: 5,
+ content: [{ text: 'world!' }],
+ section: 'prepare-script',
+ section_header: true
+ }
+ ])
end
it 'does not marks the other lines of the section as header' do
- expect(convert_json("outside section#{section_start}Hello\nworld!")).to eq([
- {
- offset: 0,
- content: [{ text: 'outside section' }]
- },
- {
- offset: 15,
- content: [{ text: 'Hello' }],
- section: 'prepare-script',
- section_header: true
- },
- {
- offset: 65,
- content: [{ text: 'world!' }],
- section: 'prepare-script'
- }
- ])
+ expect(convert_json("outside section#{section_start}Hello\nworld!")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'outside section' }]
+ },
+ {
+ offset: 15,
+ content: [{ text: 'Hello' }],
+ section: 'prepare-script',
+ section_header: true
+ },
+ {
+ offset: 65,
+ content: [{ text: 'world!' }],
+ section: 'prepare-script'
+ }
+ ])
end
it 'marks the last line of the section as footer' do
- expect(convert_json("#{section_start}Good\nmorning\nworld!#{section_end}")).to eq([
- {
- offset: 0,
- content: [{ text: 'Good' }],
- section: 'prepare-script',
- section_header: true
- },
- {
- offset: 49,
- content: [{ text: 'morning' }],
- section: 'prepare-script'
- },
- {
- offset: 57,
- content: [{ text: 'world!' }],
- section: 'prepare-script'
- },
- {
- offset: 63,
- content: [],
- section_duration: '01:03',
- section: 'prepare-script'
- }
- ])
+ expect(convert_json("#{section_start}Good\nmorning\nworld!#{section_end}")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Good' }],
+ section: 'prepare-script',
+ section_header: true
+ },
+ {
+ offset: 49,
+ content: [{ text: 'morning' }],
+ section: 'prepare-script'
+ },
+ {
+ offset: 57,
+ content: [{ text: 'world!' }],
+ section: 'prepare-script'
+ },
+ {
+ offset: 63,
+ content: [],
+ section_duration: '01:03',
+ section: 'prepare-script'
+ }
+ ])
end
it 'marks the first line as header and footer if is the only line in the section' do
- expect(convert_json("#{section_start}Hello world!#{section_end}")).to eq([
- {
- offset: 0,
- content: [{ text: 'Hello world!' }],
- section: 'prepare-script',
- section_header: true
- },
- {
- offset: 56,
- content: [],
- section: 'prepare-script',
- section_duration: '01:03'
- }
- ])
+ expect(convert_json("#{section_start}Hello world!#{section_end}")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Hello world!' }],
+ section: 'prepare-script',
+ section_header: true
+ },
+ {
+ offset: 56,
+ content: [],
+ section: 'prepare-script',
+ section_duration: '01:03'
+ }
+ ])
end
it 'does not add sections attribute to lines after the section is closed' do
- expect(convert_json("#{section_start}Hello#{section_end}world")).to eq([
- {
- offset: 0,
- content: [{ text: 'Hello' }],
- section: 'prepare-script',
- section_header: true
- },
- {
- offset: 49,
- content: [],
- section: 'prepare-script',
- section_duration: '01:03'
- },
- {
- offset: 91,
- content: [{ text: 'world' }]
- }
- ])
+ expect(convert_json("#{section_start}Hello#{section_end}world")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Hello' }],
+ section: 'prepare-script',
+ section_header: true
+ },
+ {
+ offset: 49,
+ content: [],
+ section: 'prepare-script',
+ section_duration: '01:03'
+ },
+ {
+ offset: 91,
+ content: [{ text: 'world' }]
+ }
+ ])
end
it 'ignores section_end marker if no section_start exists' do
- expect(convert_json("Hello #{section_end}world")).to eq([
- {
- offset: 0,
- content: [{ text: 'Hello world' }]
- }
- ])
+ expect(convert_json("Hello #{section_end}world")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Hello world' }]
+ }
+ ])
end
context 'when section name contains .-_ and capital letters' do
let(:section_name) { 'a.Legit-SeCtIoN_namE' }
it 'sanitizes the section name' do
- expect(convert_json("Hello#{section_start}world!")).to eq([
- {
- offset: 0,
- content: [{ text: 'Hello' }]
- },
- {
- offset: 5,
- content: [{ text: 'world!' }],
- section: 'a-legit-section-name',
- section_header: true
- }
- ])
+ expect(convert_json("Hello#{section_start}world!")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'Hello' }]
+ },
+ {
+ offset: 5,
+ content: [{ text: 'world!' }],
+ section: 'a-legit-section-name',
+ section_header: true
+ }
+ ])
end
end
@@ -213,12 +224,13 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:section_name) { 'my_$ection' }
it 'ignores the section' do
- expect(convert_json("#{section_start}hello")).to eq([
- {
- offset: 0,
- content: [{ text: 'hello' }]
- }
- ])
+ expect(convert_json("#{section_start}hello")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'hello' }]
+ }
+ ])
end
end
@@ -226,31 +238,33 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:section_name) { '<a_tag>' }
it 'ignores the section' do
- expect(convert_json("#{section_start}hello")).to eq([
- {
- offset: 0,
- content: [{ text: 'hello' }]
- }
- ])
+ expect(convert_json("#{section_start}hello")).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'hello' }]
+ }
+ ])
end
end
it 'prints HTML tags as is' do
trace = "#{section_start}section_end:1:2<div>hello</div>#{section_end}"
- expect(convert_json(trace)).to eq([
- {
- offset: 0,
- content: [{ text: 'section_end:1:2<div>hello</div>' }],
- section: 'prepare-script',
- section_header: true
- },
- {
- offset: 75,
- content: [],
- section: 'prepare-script',
- section_duration: '01:03'
- }
- ])
+ expect(convert_json(trace)).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'section_end:1:2<div>hello</div>' }],
+ section: 'prepare-script',
+ section_header: true
+ },
+ {
+ offset: 75,
+ content: [],
+ section: 'prepare-script',
+ section_duration: '01:03'
+ }
+ ])
end
context 'with nested section' do
@@ -264,7 +278,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do
it 'adds multiple sections to the lines inside the nested section' do
trace = "Hello#{section_start}foo#{nested_section_start}bar#{nested_section_end}baz#{section_end}world"
- expect(convert_json(trace)).to eq([
+ expect(convert_json(trace)).to eq(
+ [
{
offset: 0,
content: [{ text: 'Hello' }]
@@ -308,7 +323,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do
it 'adds multiple sections to the lines inside the nested section and closes all sections together' do
trace = "Hello#{section_start}\e[91mfoo\e[0m#{nested_section_start}bar#{nested_section_end}#{section_end}"
- expect(convert_json(trace)).to eq([
+ expect(convert_json(trace)).to eq(
+ [
{
offset: 0,
content: [{ text: 'Hello' }]
@@ -346,24 +362,25 @@ RSpec.describe Gitlab::Ci::Ansi2json do
it 'provides section options when set' do
trace = "#{option_section_start}hello#{section_end}"
- expect(convert_json(trace)).to eq([
- {
- offset: 0,
- content: [{ text: 'hello' }],
- section: 'prepare-script',
- section_header: true,
- section_options: {
- 'collapsed' => 'true',
- 'unused_option' => '123'
+ expect(convert_json(trace)).to eq(
+ [
+ {
+ offset: 0,
+ content: [{ text: 'hello' }],
+ section: 'prepare-script',
+ section_header: true,
+ section_options: {
+ 'collapsed' => 'true',
+ 'unused_option' => '123'
+ }
+ },
+ {
+ offset: 83,
+ content: [],
+ section: 'prepare-script',
+ section_duration: '01:03'
}
- },
- {
- offset: 83,
- content: [],
- section: 'prepare-script',
- section_duration: '01:03'
- }
- ])
+ ])
end
end
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index 234ba68d627..a22aa30304b 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
@@ -122,19 +122,17 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
context 'when compare_to is branch or tag' do
using RSpec::Parameterized::TableSyntax
- where(:pipeline_ref, :compare_to, :paths, :ff, :result) do
- 'feature_1' | 'master' | ['file1.txt'] | true | true
- 'feature_1' | 'master' | ['README.md'] | true | false
- 'feature_1' | 'master' | ['xyz.md'] | true | false
- 'feature_2' | 'master' | ['file1.txt'] | true | true
- 'feature_2' | 'master' | ['file2.txt'] | true | true
- 'feature_2' | 'feature_1' | ['file1.txt'] | true | false
- 'feature_2' | 'feature_1' | ['file1.txt'] | false | true
- 'feature_2' | 'feature_1' | ['file2.txt'] | true | true
- 'feature_1' | 'tag_1' | ['file1.txt'] | true | false
- 'feature_1' | 'tag_1' | ['file1.txt'] | false | true
- 'feature_1' | 'tag_1' | ['file2.txt'] | true | true
- 'feature_2' | 'tag_1' | ['file2.txt'] | true | true
+ where(:pipeline_ref, :compare_to, :paths, :result) do
+ 'feature_1' | 'master' | ['file1.txt'] | true
+ 'feature_1' | 'master' | ['README.md'] | false
+ 'feature_1' | 'master' | ['xyz.md'] | false
+ 'feature_2' | 'master' | ['file1.txt'] | true
+ 'feature_2' | 'master' | ['file2.txt'] | true
+ 'feature_2' | 'feature_1' | ['file1.txt'] | false
+ 'feature_2' | 'feature_1' | ['file2.txt'] | true
+ 'feature_1' | 'tag_1' | ['file1.txt'] | false
+ 'feature_1' | 'tag_1' | ['file2.txt'] | true
+ 'feature_2' | 'tag_1' | ['file2.txt'] | true
end
with_them do
@@ -144,10 +142,6 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
build(:ci_pipeline, project: project, ref: pipeline_ref, sha: project.commit(pipeline_ref).sha)
end
- before do
- stub_feature_flags(ci_rules_changes_compare: ff)
- end
-
it { is_expected.to eq(result) }
end
end
@@ -174,14 +168,6 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
::Gitlab::Ci::Build::Rules::Rule::Clause::ParseError, 'rules:changes:compare_to is not a valid ref'
)
end
-
- context 'when the FF ci_rules_changes_compare is disabled' do
- before do
- stub_feature_flags(ci_rules_changes_compare: false)
- end
-
- it { is_expected.to be_truthy }
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb b/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb
deleted file mode 100644
index e9edec9a0a4..00000000000
--- a/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Config::Entry::LegacyVariables do
- let(:config) { {} }
- let(:metadata) { {} }
-
- subject(:entry) { described_class.new(config, **metadata) }
-
- before do
- entry.compose!
- end
-
- shared_examples 'valid config' do
- describe '#value' do
- it 'returns hash with key value strings' do
- expect(entry.value).to eq result
- end
- end
-
- describe '#errors' do
- it 'does not append errors' do
- expect(entry.errors).to be_empty
- end
- end
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- shared_examples 'invalid config' do |error_message|
- describe '#valid?' do
- it 'is not valid' do
- expect(entry).not_to be_valid
- end
- end
-
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors)
- .to include(error_message)
- end
- end
- end
-
- context 'when entry config value has key-value pairs' do
- let(:config) do
- { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' }
- end
-
- let(:result) do
- { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' }
- end
-
- it_behaves_like 'valid config'
-
- describe '#value_with_data' do
- it 'returns variable with data' do
- expect(entry.value_with_data).to eq(
- 'VARIABLE_1' => { value: 'value 1' },
- 'VARIABLE_2' => { value: 'value 2' }
- )
- end
- end
- end
-
- context 'with numeric keys and values in the config' do
- let(:config) { { 10 => 20 } }
- let(:result) do
- { '10' => '20' }
- end
-
- it_behaves_like 'valid config'
- end
-
- context 'when key is an array' do
- let(:config) { { ['VAR1'] => 'val1' } }
- let(:result) do
- { 'VAR1' => 'val1' }
- end
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs/
- end
-
- context 'when value is a symbol' do
- let(:config) { { 'VAR1' => :val1 } }
- let(:result) do
- { 'VAR1' => 'val1' }
- end
-
- it_behaves_like 'valid config'
- end
-
- context 'when value is a boolean' do
- let(:config) { { 'VAR1' => true } }
- let(:result) do
- { 'VAR1' => 'val1' }
- end
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs/
- end
-
- context 'when entry config value has key-value pair and hash' do
- let(:config) do
- { 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
- 'VARIABLE_2' => 'value 2' }
- end
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs/
-
- context 'when metadata has use_value_data: true' do
- let(:metadata) { { use_value_data: true } }
-
- let(:result) do
- { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' }
- end
-
- it_behaves_like 'valid config'
-
- describe '#value_with_data' do
- it 'returns variable with data' do
- expect(entry.value_with_data).to eq(
- 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
- 'VARIABLE_2' => { value: 'value 2' }
- )
- end
- end
- end
- end
-
- context 'when entry value is an array' do
- let(:config) { [:VAR, 'test'] }
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs/
- end
-
- context 'when metadata has use_value_data: true' do
- let(:metadata) { { use_value_data: true } }
-
- context 'when entry value has hash with other key-pairs' do
- let(:config) do
- { 'VARIABLE_1' => { value: 'value 1', hello: 'variable 1' },
- 'VARIABLE_2' => 'value 2' }
- end
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs, value can be a hash/
- end
-
- context 'when entry config value has hash with nil description' do
- let(:config) do
- { 'VARIABLE_1' => { value: 'value 1', description: nil } }
- end
-
- it_behaves_like 'invalid config', /should be a hash of key value pairs, value can be a hash/
- end
-
- context 'when entry config value has hash without description' do
- let(:config) do
- { 'VARIABLE_1' => { value: 'value 1' } }
- end
-
- let(:result) do
- { 'VARIABLE_1' => 'value 1' }
- end
-
- it_behaves_like 'valid config'
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 5f42a8c49a7..ad90dd59585 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -210,20 +210,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
expect(entry.errors)
.to include 'variables:var2 config must be a string'
end
-
- context 'when the FF ci_variables_refactoring_to_variable is disabled' do
- let(:entry_without_ff) { node_class.new(config, name: :rspec) }
-
- before do
- stub_feature_flags(ci_variables_refactoring_to_variable: false)
- entry_without_ff.compose!
- end
-
- it 'reports error about variable' do
- expect(entry_without_ff.errors)
- .to include /config should be a hash of key value pairs/
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb
index 937642f07e7..a16f1cf9e43 100644
--- a/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb
@@ -91,10 +91,11 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Parallel do
describe '#value' do
it 'returns job needs configuration' do
- expect(parallel.value).to match(matrix: [
- { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] },
- { PROVIDER: 'gcp', STACK: %w[data processing] }
- ])
+ expect(parallel.value).to match(matrix:
+ [
+ { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] },
+ { PROVIDER: 'gcp', STACK: %w[data processing] }
+ ])
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 3d19987a0be..a55e13e7c2d 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -34,7 +34,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
image: 'image:1.0',
default: {},
services: ['postgres:9.1', 'mysql:5.5'],
- variables: { VAR: 'root', VAR2: { value: 'val 2', description: 'this is var 2' } },
+ variables: {
+ VAR: 'root',
+ VAR2: { value: 'val 2', description: 'this is var 2' },
+ VAR3: { value: %w[val3 val3b], description: 'this is var 3' }
+ },
after_script: ['make clean'],
stages: %w(build pages release),
cache: { key: 'k', untracked: true, paths: ['public/'] },
@@ -83,7 +87,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
end
it 'sets correct variables value' do
- expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2')
+ expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2', 'VAR3' => 'val3')
end
describe '#leaf?' do
@@ -361,20 +365,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
expect(root.errors)
.to include /var1 config uses invalid data keys: invalid/
end
-
- context 'when the FF ci_variables_refactoring_to_variable is disabled' do
- let(:root_without_ff) { described_class.new(hash, user: user, project: project) }
-
- before do
- stub_feature_flags(ci_variables_refactoring_to_variable: false)
- root_without_ff.compose!
- end
-
- it 'reports errors about the invalid variable' do
- expect(root_without_ff.errors)
- .to include /variables config should be a hash of key value pairs, value can be a hash/
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
index 303d825c591..3531d6e9f1a 100644
--- a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
@@ -364,19 +364,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do
it 'returns an error about invalid variables:' do
expect(subject.errors).to include(/variables config should be a hash/)
end
-
- context 'when the FF ci_variables_refactoring_to_variable is disabled' do
- let(:entry_without_ff) { factory.create! }
-
- before do
- stub_feature_flags(ci_variables_refactoring_to_variable: false)
- entry_without_ff.compose!
- end
-
- it 'returns an error about invalid variables:' do
- expect(subject.errors).to include(/variables config should be a hash/)
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/variable_spec.rb b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
index 744a89d4509..076a5b32e92 100644
--- a/spec/lib/gitlab/ci/config/entry/variable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
@@ -127,20 +127,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
end
end
- context 'when config value is an array' do
- let(:config) { { value: ['value'], description: 'description' } }
-
- describe '#valid?' do
- it { is_expected.not_to be_valid }
- end
-
- describe '#errors' do
- subject(:errors) { entry.errors }
-
- it { is_expected.to include 'var1 config value must be an alphanumeric string' }
- end
- end
-
context 'when config description is a symbol' do
let(:config) { { value: 'value', description: :description } }
@@ -209,4 +195,42 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
end
end
end
+
+ describe 'ComplexArrayVariable' do
+ context 'when allow_array_value metadata is false' do
+ let(:config) { { value: %w[value value2], description: 'description' } }
+ let(:metadata) { { allow_array_value: false } }
+
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ subject(:errors) { entry.errors }
+
+ it { is_expected.to include 'var1 config value must be an alphanumeric string' }
+ end
+ end
+
+ context 'when allow_array_value metadata is true' do
+ let(:config) { { value: %w[value value2], description: 'description' } }
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
+
+ describe '#value' do
+ subject(:value) { entry.value }
+
+ it { is_expected.to eq('value') }
+ end
+
+ describe '#value_with_data' do
+ subject(:value_with_data) { entry.value_with_data }
+
+ it { is_expected.to eq(value: 'value', description: 'description', value_options: %w[value value2]) }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
index ad7290d0589..085f304094e 100644
--- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
@@ -98,6 +98,62 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
it_behaves_like 'invalid config', /must be either a string or a hash/
end
+ context 'when entry config value has unallowed value key-value pair and value is a string' do
+ let(:config) do
+ { 'VARIABLE_1' => { value: 'value', description: 'variable 1' } }
+ end
+
+ context 'when there is no allowed_value_data metadata' do
+ it_behaves_like 'invalid config', /variable_1 config must be a string/
+ end
+
+ context 'when metadata has allow_array_value and allowed_value_data' do
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ let(:result) do
+ { 'VARIABLE_1' => 'value' }
+ end
+
+ it_behaves_like 'valid config'
+
+ describe '#value_with_data' do
+ it 'returns variable with data' do
+ expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value', description: 'variable 1' }
+ )
+ end
+ end
+ end
+ end
+
+ context 'when entry config value has key-value pair and value is an array' do
+ let(:config) do
+ { 'VARIABLE_1' => { value: %w[value1 value2], description: 'variable 1' } }
+ end
+
+ context 'when there is no allowed_value_data metadata' do
+ it_behaves_like 'invalid config', /variable_1 config value must be an alphanumeric string/
+ end
+
+ context 'when metadata has allow_array_value and allowed_value_data' do
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ let(:result) do
+ { 'VARIABLE_1' => 'value1' }
+ end
+
+ it_behaves_like 'valid config'
+
+ describe '#value_with_data' do
+ it 'returns variable with data' do
+ expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value1', value_options: %w[value1 value2], description: 'variable 1' }
+ )
+ end
+ end
+ end
+ end
+
context 'when entry config value has key-value pair and hash' do
let(:config) do
{ 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
diff --git a/spec/lib/gitlab/ci/config/entry/workflow_spec.rb b/spec/lib/gitlab/ci/config/entry/workflow_spec.rb
index 3d19832e13d..97ac199f47d 100644
--- a/spec/lib/gitlab/ci/config/entry/workflow_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/workflow_spec.rb
@@ -65,6 +65,54 @@ RSpec.describe Gitlab::Ci::Config::Entry::Workflow do
end
end
end
+
+ context 'with workflow name' do
+ let(:factory) { Gitlab::Config::Entry::Factory.new(described_class).value(workflow_hash) }
+
+ context 'with a blank name' do
+ let(:workflow_hash) do
+ { name: '' }
+ end
+
+ it 'is invalid' do
+ expect(config).not_to be_valid
+ end
+
+ it 'returns error about invalid name' do
+ expect(config.errors).to include('workflow name is too short (minimum is 1 character)')
+ end
+ end
+
+ context 'with too long name' do
+ let(:workflow_hash) do
+ { name: 'a' * 256 }
+ end
+
+ it 'is invalid' do
+ expect(config).not_to be_valid
+ end
+
+ it 'returns error about invalid name' do
+ expect(config.errors).to include('workflow name is too long (maximum is 255 characters)')
+ end
+ end
+
+ context 'when name is nil' do
+ let(:workflow_hash) { { name: nil } }
+
+ it 'is valid' do
+ expect(config).to be_valid
+ end
+ end
+
+ context 'when name is not provided' do
+ let(:workflow_hash) { { rules: [{ if: '$VAR' }] } }
+
+ it 'is valid' do
+ expect(config).to be_valid
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb
index 9da8d106862..a8dc7897082 100644
--- a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb
@@ -174,9 +174,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do
context 'when job is provided as a variable' do
let(:variables) do
- Gitlab::Ci::Variables::Collection.new([
- { key: 'VAR1', value: 'a_secret_variable_value', masked: true }
- ])
+ Gitlab::Ci::Variables::Collection.new(
+ [
+ { key: 'VAR1', value: 'a_secret_variable_value', masked: true }
+ ])
end
let(:params) { { artifact: 'generated.yml', job: 'a_secret_variable_value' } }
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
index 72a85c9b03d..0ba92d1e92d 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -163,9 +163,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
context 'when non-existing project is used with a masked variable' do
let(:variables) do
- Gitlab::Ci::Variables::Collection.new([
- { key: 'VAR1', value: 'a_secret_variable_value', masked: true }
- ])
+ Gitlab::Ci::Variables::Collection.new([{ key: 'VAR1', value: 'a_secret_variable_value', masked: true }])
end
let(:params) do
@@ -180,9 +178,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
context 'when a project contained in an array is used with a masked variable' do
let(:variables) do
- Gitlab::Ci::Variables::Collection.new([
- { key: 'VAR1', value: 'a_secret_variable_value', masked: true }
- ])
+ Gitlab::Ci::Variables::Collection.new([{ key: 'VAR1', value: 'a_secret_variable_value', masked: true }])
end
let(:params) do
@@ -231,10 +227,11 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
context 'when project name and ref include masked variables' do
let(:variables) do
- Gitlab::Ci::Variables::Collection.new([
- { key: 'VAR1', value: 'a_secret_variable_value1', masked: true },
- { key: 'VAR2', value: 'a_secret_variable_value2', masked: true }
- ])
+ Gitlab::Ci::Variables::Collection.new(
+ [
+ { key: 'VAR1', value: 'a_secret_variable_value1', masked: true },
+ { key: 'VAR2', value: 'a_secret_variable_value2', masked: true }
+ ])
end
let(:params) { { project: 'a_secret_variable_value1', ref: 'a_secret_variable_value2', file: '/file.yml' } }
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 9eaba12f388..e12f5dcee0a 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -207,9 +207,9 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
context "when duplicate 'include's are defined" do
let(:values) do
{ include: [
- { 'local' => local_file },
- { 'local' => local_file }
- ],
+ { 'local' => local_file },
+ { 'local' => local_file }
+ ],
image: 'image:1.0' }
end
@@ -416,17 +416,18 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
context "when locations are same after masking variables" do
let(:variables) do
- Gitlab::Ci::Variables::Collection.new([
- { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file1', 'masked' => true },
- { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file2', 'masked' => true }
- ])
+ Gitlab::Ci::Variables::Collection.new(
+ [
+ { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file1', 'masked' => true },
+ { 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file2', 'masked' => true }
+ ])
end
let(:values) do
{ include: [
- { 'local' => 'hello/secret-file1.yml' },
- { 'local' => 'hello/secret-file2.yml' }
- ],
+ { 'local' => 'hello/secret-file1.yml' },
+ { 'local' => 'hello/secret-file2.yml' }
+ ],
image: 'ruby:2.7' }
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 055114769ea..475503de7da 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -889,4 +889,31 @@ RSpec.describe Gitlab::Ci::Config do
it { is_expected.to eq([{ if: '$CI_COMMIT_REF_NAME == "master"' }]) }
end
+
+ describe '#workflow_name' do
+ subject(:workflow_name) { config.workflow_name }
+
+ let(:yml) do
+ <<-EOS
+ workflow:
+ name: 'Pipeline name'
+
+ rspec:
+ script: exit 0
+ EOS
+ end
+
+ it { is_expected.to eq('Pipeline name') }
+
+ context 'with no name' do
+ let(:yml) do
+ <<-EOS
+ rspec:
+ script: exit 0
+ EOS
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/jwt_v2_spec.rb b/spec/lib/gitlab/ci/jwt_v2_spec.rb
index 33aaa145a39..5eeab658a8e 100644
--- a/spec/lib/gitlab/ci/jwt_v2_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_v2_spec.rb
@@ -7,6 +7,8 @@ RSpec.describe Gitlab::Ci::JwtV2 do
let(:project) { build_stubbed(:project, namespace: namespace) }
let(:user) { build_stubbed(:user) }
let(:pipeline) { build_stubbed(:ci_pipeline, ref: 'auto-deploy-2020-03-19') }
+ let(:aud) { described_class::DEFAULT_AUD }
+
let(:build) do
build_stubbed(
:ci_build,
@@ -16,7 +18,7 @@ RSpec.describe Gitlab::Ci::JwtV2 do
)
end
- subject(:ci_job_jwt_v2) { described_class.new(build, ttl: 30) }
+ subject(:ci_job_jwt_v2) { described_class.new(build, ttl: 30, aud: aud) }
it { is_expected.to be_a Gitlab::Ci::Jwt }
@@ -30,5 +32,13 @@ RSpec.describe Gitlab::Ci::JwtV2 do
expect(payload[:sub]).to eq("project_path:#{project.full_path}:ref_type:branch:ref:#{pipeline.source_ref}")
end
end
+
+ context 'when given an aud' do
+ let(:aud) { 'AWS' }
+
+ it 'uses that aud in the payload' do
+ expect(payload[:aud]).to eq('AWS')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index 3d46d266c13..cf07e952f26 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -342,6 +342,7 @@ RSpec.describe Gitlab::Ci::Lint do
{
'count' => a_kind_of(Numeric),
'avg' => a_kind_of(Numeric),
+ 'sum' => a_kind_of(Numeric),
'max' => a_kind_of(Numeric),
'min' => a_kind_of(Numeric)
}
diff --git a/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
index 7222ebc3cb8..e12fa380209 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
@@ -19,8 +19,7 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning do
it 'returns expected source data' do
is_expected.to have_attributes(
source_type: :dependency_scanning,
- data: property_data,
- fingerprint: '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ data: property_data
)
end
end
diff --git a/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb
index c54a3268bbe..f58a463f047 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb
@@ -72,12 +72,13 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator d
it { is_expected.not_to be_valid }
it "outputs errors for each validation failure" do
- expect(validator.errors).to match_array([
- "property '/components/0' is missing required keys: name",
- "property '/components/0/type' is not one of: [\"application\", \"framework\"," \
- " \"library\", \"container\", \"operating-system\", \"device\", \"firmware\", \"file\"]",
- "property '/components/1' is missing required keys: type"
- ])
+ expect(validator.errors).to match_array(
+ [
+ "property '/components/0' is missing required keys: name",
+ "property '/components/0/type' is not one of: [\"application\", \"framework\"," \
+ " \"library\", \"container\", \"operating-system\", \"device\", \"firmware\", \"file\"]",
+ "property '/components/1' is missing required keys: type"
+ ])
end
end
end
@@ -121,10 +122,11 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator d
it { is_expected.not_to be_valid }
it "outputs errors for each validation failure" do
- expect(validator.errors).to match_array([
- "property '/metadata/properties/0/name' is not of type: string",
- "property '/metadata/properties/0/value' is not of type: string"
- ])
+ expect(validator.errors).to match_array(
+ [
+ "property '/metadata/properties/0/name' is not of type: string",
+ "property '/metadata/properties/0/value' is not of type: string"
+ ])
end
end
end
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index 297ef1f5bb9..7dbad354e4c 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -54,24 +54,15 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
context 'when the validate flag is set to `false`' do
let(:validate) { false }
- let(:valid?) { false }
- let(:errors) { ['foo'] }
- let(:warnings) { ['bar'] }
before do
- allow_next_instance_of(validator_class) do |instance|
- allow(instance).to receive(:valid?).and_return(valid?)
- allow(instance).to receive(:errors).and_return(errors)
- allow(instance).to receive(:warnings).and_return(warnings)
- end
-
allow(parser).to receive_messages(create_scanner: true, create_scan: true)
end
- it 'instantiates the validator with correct params' do
+ it 'does not instantiate the validator' do
parse_report
- expect(validator_class).to have_received(:new).with(
+ expect(validator_class).not_to have_received(:new).with(
report.type,
data.deep_stringify_keys,
report.version,
@@ -80,43 +71,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
)
end
- context 'when the report data is not valid according to the schema' do
- it 'adds warnings to the report' do
- expect { parse_report }.to change { report.warnings }.from([]).to(
- [
- { message: 'foo', type: 'Schema' },
- { message: 'bar', type: 'Schema' }
- ]
- )
- end
-
- it 'keeps the execution flow as normal' do
- parse_report
+ it 'marks the report as valid' do
+ parse_report
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
+ expect(report).not_to be_errored
end
- context 'when the report data is valid according to the schema' do
- let(:valid?) { true }
- let(:errors) { [] }
- let(:warnings) { [] }
-
- it 'does not add errors to the report' do
- expect { parse_report }.not_to change { report.errors }
- end
-
- it 'does not add warnings to the report' do
- expect { parse_report }.not_to change { report.warnings }
- end
-
- it 'keeps the execution flow as normal' do
- parse_report
+ it 'keeps the execution flow as normal' do
+ parse_report
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
end
end
@@ -152,12 +117,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
it 'adds errors to the report' do
expect { parse_report }.to change { report.errors }.from([]).to(
[
- { message: 'foo', type: 'Schema' },
- { message: 'bar', type: 'Schema' }
+ { message: 'foo', type: 'Schema' }
]
)
end
+ it 'marks the report as invalid' do
+ parse_report
+
+ expect(report).to be_errored
+ end
+
it 'does not try to create report entities' do
parse_report
@@ -175,8 +145,24 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
expect { parse_report }.not_to change { report.errors }.from([])
end
- it 'does not add warnings to the report' do
- expect { parse_report }.not_to change { report.warnings }.from([])
+ context 'and no warnings are present' do
+ let(:warnings) { [] }
+
+ it 'does not add warnings to the report' do
+ expect { parse_report }.not_to change { report.warnings }.from([])
+ end
+ end
+
+ context 'and some warnings are present' do
+ let(:warnings) { ['bar'] }
+
+ it 'does add warnings to the report' do
+ expect { parse_report }.to change { report.warnings }.from([]).to(
+ [
+ { message: 'bar', type: 'Schema' }
+ ]
+ )
+ end
end
it 'keeps the execution flow as normal' do
@@ -298,8 +284,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
scans = report.findings.map(&:scan)
expect(scans.map(&:status).all?('success')).to be(true)
- expect(scans.map(&:start_time).all?('placeholder-value')).to be(true)
- expect(scans.map(&:end_time).all?('placeholder-value')).to be(true)
+ expect(scans.map(&:start_time).all?('2022-08-10T21:37:00')).to be(true)
+ expect(scans.map(&:end_time).all?('2022-08-10T21:38:00')).to be(true)
expect(scans.size).to eq(7)
expect(scans.first).to be_a(::Gitlab::Ci::Reports::Security::Scan)
end
@@ -418,11 +404,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
{
'type' => 'source',
'items' => [
- 'signatures' => [
- { 'algorithm' => 'hash', 'value' => 'hash_value' },
- { 'algorithm' => 'location', 'value' => 'location_value' },
- { 'algorithm' => 'scope_offset', 'value' => 'scope_offset_value' }
- ]
+ 'signatures' => [
+ { 'algorithm' => 'hash', 'value' => 'hash_value' },
+ { 'algorithm' => 'location', 'value' => 'location_value' },
+ { 'algorithm' => 'scope_offset', 'value' => 'scope_offset_value' }
+ ]
]
}
end
@@ -440,11 +426,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
{
'type' => 'source',
'items' => [
- 'signatures' => [
- { 'algorithm' => 'hash', 'value' => 'hash_value' },
- { 'algorithm' => 'location', 'value' => 'location_value' },
- { 'algorithm' => 'INVALID', 'value' => 'scope_offset_value' }
- ]
+ 'signatures' => [
+ { 'algorithm' => 'hash', 'value' => 'hash_value' },
+ { 'algorithm' => 'location', 'value' => 'location_value' },
+ { 'algorithm' => 'INVALID', 'value' => 'scope_offset_value' }
+ ]
]
}
end
diff --git a/spec/lib/gitlab/ci/parsers/security/sast_spec.rb b/spec/lib/gitlab/ci/parsers/security/sast_spec.rb
index 4bc48f6611a..f6113308201 100644
--- a/spec/lib/gitlab/ci/parsers/security/sast_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/sast_spec.rb
@@ -10,24 +10,39 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do
let(:created_at) { 2.weeks.ago }
- context "when parsing valid reports" do
- where(:report_format, :report_version, :scanner_length, :finding_length, :identifier_length, :file_path, :line) do
- :sast | '14.0.0' | 1 | 5 | 6 | 'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy' | 47
- :sast_deprecated | '1.2' | 3 | 33 | 17 | 'python/hardcoded/hardcoded-tmp.py' | 1
+ context "when passing valid report" do
+ # rubocop: disable Layout/LineLength
+ where(:report_format, :report_version, :scanner_length, :finding_length, :identifier_length, :file_path, :start_line, :end_line, :primary_identifiers_length) do
+ :sast | '14.0.0' | 1 | 5 | 6 | 'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy' | 47 | 47 | nil
+ :sast_semgrep_for_multiple_findings | '14.0.4' | 1 | 2 | 6 | 'app/app.py' | 39 | nil | 2
end
+ # rubocop: enable Layout/LineLength
with_them do
- let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, created_at) }
+ let(:report) do
+ Gitlab::Ci::Reports::Security::Report.new(
+ artifact.file_type,
+ pipeline,
+ created_at
+ )
+ end
+
let(:artifact) { create(:ci_job_artifact, report_format) }
before do
- artifact.each_blob { |blob| described_class.parse!(blob, report) }
+ artifact.each_blob { |blob| described_class.parse!(blob, report, validate: true) }
end
it "parses all identifiers and findings" do
expect(report.findings.length).to eq(finding_length)
expect(report.identifiers.length).to eq(identifier_length)
expect(report.scanners.length).to eq(scanner_length)
+
+ if primary_identifiers_length
+ expect(
+ report.scanners.each_value.first.primary_identifiers.length
+ ).to eq(primary_identifiers_length)
+ end
end
it 'generates expected location' do
@@ -36,8 +51,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do
expect(location).to be_a(::Gitlab::Ci::Reports::Security::Locations::Sast)
expect(location).to have_attributes(
file_path: file_path,
- end_line: line,
- start_line: line
+ end_line: end_line,
+ start_line: start_line
)
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
index b570f2a7f75..fc3de2a14cd 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
@@ -44,6 +44,20 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines do
expect(build_statuses(pipeline)).to contain_exactly('pending')
end
+ it 'logs canceled pipelines' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ perform
+
+ expect(Gitlab::AppLogger).to have_received(:info).with(
+ class: described_class.name,
+ message: "Pipeline #{pipeline.id} auto-canceling pipeline #{prev_pipeline.id}",
+ canceled_pipeline_id: prev_pipeline.id,
+ canceled_by_pipeline_id: pipeline.id,
+ canceled_by_pipeline_source: pipeline.source
+ )
+ end
+
it 'cancels the builds with 2 queries to avoid query timeout' do
second_query_regex = /WHERE "ci_pipelines"\."id" = \d+ AND \(NOT EXISTS/
recorder = ActiveRecord::QueryRecorder.new { perform }
@@ -141,7 +155,42 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines do
end
end
- context 'when the prev pipeline source is webide' do
+ context 'when the pipeline is a child pipeline' do
+ let!(:parent_pipeline) { create(:ci_pipeline, project: project, sha: new_commit.sha) }
+ let(:pipeline) { create(:ci_pipeline, child_of: parent_pipeline) }
+
+ before do
+ create(:ci_build, :interruptible, :running, pipeline: parent_pipeline)
+ create(:ci_build, :interruptible, :running, pipeline: parent_pipeline)
+ end
+
+ it 'does not cancel any builds' do
+ expect(build_statuses(prev_pipeline)).to contain_exactly('running', 'success', 'created')
+ expect(build_statuses(parent_pipeline)).to contain_exactly('running', 'running')
+
+ perform
+
+ expect(build_statuses(prev_pipeline)).to contain_exactly('running', 'success', 'created')
+ expect(build_statuses(parent_pipeline)).to contain_exactly('running', 'running')
+ end
+
+ context 'when feature flag ci_skip_auto_cancelation_on_child_pipelines is disabled' do
+ before do
+ stub_feature_flags(ci_skip_auto_cancelation_on_child_pipelines: false)
+ end
+
+ it 'does not cancel the parent pipeline' do
+ expect(build_statuses(parent_pipeline)).to contain_exactly('running', 'running')
+
+ perform
+
+ expect(build_statuses(prev_pipeline)).to contain_exactly('success', 'canceled', 'canceled')
+ expect(build_statuses(parent_pipeline)).to contain_exactly('running', 'running')
+ end
+ end
+ end
+
+ context 'when the previous pipeline source is webide' do
let(:prev_pipeline) { create(:ci_pipeline, :webide, project: project) }
it 'does not cancel builds of the previous pipeline' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
index f451bd6bfef..e0d656f456e 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
@@ -11,9 +11,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject { described_class.new(pipeline, command) }
- # TODO: change this to `describe` and remove rubocop-disable
- # when removing the FF ci_project_pipeline_config_refactoring
- shared_context '#perform!' do # rubocop:disable RSpec/ContextWording
+ describe '#perform!' do
context 'when bridge job is passed in as parameter' do
let(:ci_config_path) { nil }
let(:bridge) { create(:ci_bridge) }
@@ -203,14 +201,4 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Config::Content do
end
end
end
-
- it_behaves_like '#perform!'
-
- context 'when the FF ci_project_pipeline_config_refactoring is disabled' do
- before do
- stub_feature_flags(ci_project_pipeline_config_refactoring: false)
- end
-
- it_behaves_like '#perform!'
- end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb
new file mode 100644
index 00000000000..bc453f1502b
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::ActiveJobs do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, namespace: namespace) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:default_plan) { create(:default_plan) }
+
+ let(:command) do
+ instance_double(
+ ::Gitlab::Ci::Pipeline::Chain::Command,
+ project: project,
+ current_user: user,
+ save_incompleted: true,
+ pipeline_seed: pipeline_seed_double
+ )
+ end
+
+ let(:pipeline_seed_double) do
+ instance_double(::Gitlab::Ci::Pipeline::Seed::Pipeline, size: 5)
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline, project: project)
+ end
+
+ let(:existing_pipeline) { create(:ci_pipeline, project: project) }
+ let(:step) { described_class.new(pipeline, command) }
+ let(:limit) { 10 }
+
+ subject { step.perform! }
+
+ before do
+ create(:plan_limits, plan: default_plan, ci_active_jobs: limit)
+ namespace.clear_memoization(:actual_plan)
+ end
+
+ shared_examples 'successful step' do
+ it 'doest not fail the pipeline and does not interrupt the chain' do
+ subject
+
+ expect(pipeline).not_to be_failed
+ expect(step).not_to be_break
+ end
+ end
+
+ context 'when active jobs limit is exceeded' do
+ before do
+ create_list(:ci_build, 3, pipeline: existing_pipeline)
+ create_list(:ci_bridge, 3, pipeline: existing_pipeline)
+ end
+
+ it 'fails the pipeline with an error', :aggregate_failures do
+ subject
+
+ expect(pipeline).to be_failed
+ expect(pipeline).to be_job_activity_limit_exceeded
+ expect(pipeline.errors.full_messages).to include(described_class::MESSAGE)
+ end
+
+ it 'logs the failure' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ subject
+
+ expect(Gitlab::AppLogger).to have_received(:info).with(
+ class: described_class.name,
+ message: described_class::MESSAGE,
+ project_id: project.id,
+ plan: default_plan.name
+ )
+ end
+
+ it 'breaks the chain' do
+ subject
+
+ expect(step).to be_break
+ end
+
+ context 'when active jobs limit not enabled' do
+ let(:limit) { 0 }
+
+ it_behaves_like 'successful step'
+ end
+ end
+
+ context 'when active jobs limit is not exceeded' do
+ before do
+ create_list(:ci_build, 3, pipeline: existing_pipeline)
+ create_list(:ci_bridge, 1, pipeline: existing_pipeline)
+ end
+
+ it_behaves_like 'successful step'
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 62de4d2e96d..51d1661b586 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -236,4 +236,47 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Populate do
end
end
end
+
+ context 'with pipeline name' do
+ let(:config) do
+ { workflow: { name: ' Pipeline name ' }, rspec: { script: 'rspec' } }
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(pipeline_name: false)
+ end
+
+ it 'does not build pipeline_metadata' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata).to be_nil
+ end
+ end
+
+ context 'with feature flag enabled' do
+ before do
+ stub_feature_flags(pipeline_name: true)
+ end
+
+ it 'builds pipeline_metadata' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata.title).to eq('Pipeline name')
+ expect(pipeline.pipeline_metadata.project).to eq(pipeline.project)
+ end
+
+ context 'with empty name' do
+ let(:config) do
+ { workflow: { name: ' ' }, rspec: { script: 'rspec' } }
+ end
+
+ it 'strips whitespace from name' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index 8c4f7af0ef4..323bab89e6a 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -68,8 +68,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
context 'when refs policy is specified' do
+ let(:tag_name) { project.repository.tags.first.name }
+
let(:pipeline) do
- build(:ci_pipeline, project: project, ref: 'feature', tag: true)
+ build(:ci_pipeline, project: project, ref: tag_name, tag: true)
end
let(:config) do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
index ee32661f267..c69aa661b05 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
@@ -100,19 +100,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Sequence do
expect(histogram).to have_received(:observe)
.with(hash_including(plan: project.actual_plan_name), 4)
end
-
- context 'when feature flag ci_limit_active_jobs_early is disabled' do
- before do
- stub_feature_flags(ci_limit_active_jobs_early: false)
- end
-
- it 'counts all the active builds' do
- subject.build!
-
- expect(histogram).to have_received(:observe)
- .with(hash_including(plan: project.actual_plan_name), 3)
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/duration_spec.rb b/spec/lib/gitlab/ci/pipeline/duration_spec.rb
index 46c7072ad8e..36714413da6 100644
--- a/spec/lib/gitlab/ci/pipeline/duration_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/duration_spec.rb
@@ -1,117 +1,187 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Duration do
- let(:calculated_duration) { calculate(data) }
+ describe '.from_periods' do
+ let(:calculated_duration) { calculate(data) }
- shared_examples 'calculating duration' do
- it do
- expect(calculated_duration).to eq(duration)
+ shared_examples 'calculating duration' do
+ it do
+ expect(calculated_duration).to eq(duration)
+ end
end
- end
- context 'test sample A' do
- let(:data) do
- [[0, 1],
- [1, 2],
- [3, 4],
- [5, 6]]
+ context 'test sample A' do
+ let(:data) do
+ [[0, 1],
+ [1, 2],
+ [3, 4],
+ [5, 6]]
+ end
+
+ let(:duration) { 4 }
+
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 4 }
+ context 'test sample B' do
+ let(:data) do
+ [[0, 1],
+ [1, 2],
+ [2, 3],
+ [3, 4],
+ [0, 4]]
+ end
- it_behaves_like 'calculating duration'
- end
+ let(:duration) { 4 }
- context 'test sample B' do
- let(:data) do
- [[0, 1],
- [1, 2],
- [2, 3],
- [3, 4],
- [0, 4]]
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 4 }
+ context 'test sample C' do
+ let(:data) do
+ [[0, 4],
+ [2, 6],
+ [5, 7],
+ [8, 9]]
+ end
- it_behaves_like 'calculating duration'
- end
+ let(:duration) { 8 }
- context 'test sample C' do
- let(:data) do
- [[0, 4],
- [2, 6],
- [5, 7],
- [8, 9]]
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 8 }
+ context 'test sample D' do
+ let(:data) do
+ [[0, 1],
+ [2, 3],
+ [4, 5],
+ [6, 7]]
+ end
- it_behaves_like 'calculating duration'
- end
+ let(:duration) { 4 }
+
+ it_behaves_like 'calculating duration'
+ end
- context 'test sample D' do
- let(:data) do
- [[0, 1],
- [2, 3],
- [4, 5],
- [6, 7]]
+ context 'test sample E' do
+ let(:data) do
+ [[0, 1],
+ [3, 9],
+ [3, 4],
+ [3, 5],
+ [3, 8],
+ [4, 5],
+ [4, 7],
+ [5, 8]]
+ end
+
+ let(:duration) { 7 }
+
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 4 }
+ context 'test sample F' do
+ let(:data) do
+ [[1, 3],
+ [2, 4],
+ [2, 4],
+ [2, 4],
+ [5, 8]]
+ end
- it_behaves_like 'calculating duration'
- end
+ let(:duration) { 6 }
- context 'test sample E' do
- let(:data) do
- [[0, 1],
- [3, 9],
- [3, 4],
- [3, 5],
- [3, 8],
- [4, 5],
- [4, 7],
- [5, 8]]
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 7 }
+ context 'test sample G' do
+ let(:data) do
+ [[1, 3],
+ [2, 4],
+ [6, 7]]
+ end
- it_behaves_like 'calculating duration'
- end
+ let(:duration) { 4 }
- context 'test sample F' do
- let(:data) do
- [[1, 3],
- [2, 4],
- [2, 4],
- [2, 4],
- [5, 8]]
+ it_behaves_like 'calculating duration'
end
- let(:duration) { 6 }
+ def calculate(data)
+ periods = data.shuffle.map do |(first, last)|
+ described_class::Period.new(first, last)
+ end
- it_behaves_like 'calculating duration'
+ described_class.from_periods(periods.sort_by(&:first))
+ end
end
- context 'test sample G' do
- let(:data) do
- [[1, 3],
- [2, 4],
- [6, 7]]
+ describe '.from_pipeline' do
+ let_it_be(:start_time) { Time.current.change(usec: 0) }
+ let_it_be(:current) { start_time + 1000 }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:success_build) { create_build(:success, started_at: start_time, finished_at: start_time + 60) }
+ let_it_be(:failed_build) { create_build(:failed, started_at: start_time + 60, finished_at: start_time + 120) }
+ let_it_be(:canceled_build) { create_build(:canceled, started_at: start_time + 120, finished_at: start_time + 180) }
+ let_it_be(:skipped_build) { create_build(:skipped, started_at: start_time) }
+ let_it_be(:pending_build) { create_build(:pending) }
+ let_it_be(:created_build) { create_build(:created) }
+ let_it_be(:preparing_build) { create_build(:preparing) }
+ let_it_be(:scheduled_build) { create_build(:scheduled) }
+ let_it_be(:expired_scheduled_build) { create_build(:expired_scheduled) }
+ let_it_be(:manual_build) { create_build(:manual) }
+
+ let!(:running_build) { create_build(:running, started_at: start_time) }
+
+ it 'returns the duration of the running build' do
+ travel_to(current) do
+ expect(described_class.from_pipeline(pipeline)).to eq 1000.seconds
+ end
end
- let(:duration) { 4 }
+ context 'when there is no running build' do
+ let(:running_build) { nil }
- it_behaves_like 'calculating duration'
- end
+ it 'returns the duration for all the builds' do
+ travel_to(current) do
+ expect(described_class.from_pipeline(pipeline)).to eq 180.seconds
+ end
+ end
+ end
- def calculate(data)
- periods = data.shuffle.map do |(first, last)|
- described_class::Period.new(first, last)
+ context 'when there are bridge jobs' do
+ let!(:success_bridge) { create_bridge(:success, started_at: start_time + 220, finished_at: start_time + 280) }
+ let!(:failed_bridge) { create_bridge(:failed, started_at: start_time + 180, finished_at: start_time + 240) }
+ let!(:skipped_bridge) { create_bridge(:skipped, started_at: start_time) }
+ let!(:created_bridge) { create_bridge(:created) }
+ let!(:manual_bridge) { create_bridge(:manual) }
+
+ it 'returns the duration of the running build' do
+ travel_to(current) do
+ expect(described_class.from_pipeline(pipeline)).to eq 1000.seconds
+ end
+ end
+
+ context 'when there is no running build' do
+ let!(:running_build) { nil }
+
+ it 'returns the duration for all the builds and bridge jobs' do
+ travel_to(current) do
+ expect(described_class.from_pipeline(pipeline)).to eq 280.seconds
+ end
+ end
+ end
end
- described_class.from_periods(periods.sort_by(&:first))
+ private
+
+ def create_build(trait, **opts)
+ create(:ci_build, trait, pipeline: pipeline, **opts)
+ end
+
+ def create_bridge(trait, **opts)
+ create(:ci_bridge, trait, pipeline: pipeline, **opts)
+ end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/logger_spec.rb b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
index f31361431f2..3af0ebe7484 100644
--- a/spec/lib/gitlab/ci/pipeline/logger_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
loggable_data = {
'expensive_operation_duration_s' => {
'count' => 1,
+ 'sum' => a_kind_of(Numeric),
'avg' => a_kind_of(Numeric),
'max' => a_kind_of(Numeric),
'min' => a_kind_of(Numeric)
@@ -62,6 +63,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
accumulator[key] = {
'count' => count,
'avg' => a_kind_of(Numeric),
+ 'sum' => a_kind_of(Numeric),
'max' => a_kind_of(Numeric),
'min' => a_kind_of(Numeric)
}
@@ -71,6 +73,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
data['expensive_operation_db_count']['max'] = db_count
data['expensive_operation_db_count']['min'] = db_count
data['expensive_operation_db_count']['avg'] = db_count
+ data['expensive_operation_db_count']['sum'] = count * db_count
end
data
@@ -131,7 +134,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
it 'records durations of observed operations' do
loggable_data = {
'pipeline_creation_duration_s' => {
- 'avg' => 30, 'count' => 1, 'max' => 30, 'min' => 30
+ 'avg' => 30, 'sum' => 30, 'count' => 1, 'max' => 30, 'min' => 30
}
}
@@ -165,10 +168,10 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
'pipeline_creation_caller' => 'source',
'pipeline_source' => pipeline.source,
'pipeline_save_duration_s' => {
- 'avg' => 60, 'count' => 1, 'max' => 60, 'min' => 60
+ 'avg' => 60, 'sum' => 60, 'count' => 1, 'max' => 60, 'min' => 60
},
'pipeline_creation_duration_s' => {
- 'avg' => 20, 'count' => 2, 'max' => 30, 'min' => 10
+ 'avg' => 20, 'sum' => 40, 'count' => 2, 'max' => 30, 'min' => 10
}
}
end
@@ -215,10 +218,10 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
'pipeline_creation_caller' => 'source',
'pipeline_save_duration_s' => {
- 'avg' => 60, 'count' => 1, 'max' => 60, 'min' => 60
+ 'avg' => 60, 'sum' => 60, 'count' => 1, 'max' => 60, 'min' => 60
},
'pipeline_creation_duration_s' => {
- 'avg' => 20, 'count' => 2, 'max' => 30, 'min' => 10
+ 'avg' => 20, 'sum' => 40, 'count' => 2, 'max' => 30, 'min' => 10
}
}
end
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
index e289e59b281..effa2c43418 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
@@ -191,11 +191,12 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
end
it 'includes the base report errors sorted by severity' do
- expect(existing_errors).to eq([
- blocker_degradation,
- critical_degradation,
- major_degradation
- ])
+ expect(existing_errors).to eq(
+ [
+ blocker_degradation,
+ critical_degradation,
+ major_degradation
+ ])
end
end
@@ -242,11 +243,12 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
end
it 'includes errors not found in the base report sorted by severity' do
- expect(new_errors).to eq([
- blocker_degradation,
- critical_degradation,
- minor_degradation
- ])
+ expect(new_errors).to eq(
+ [
+ blocker_degradation,
+ critical_degradation,
+ minor_degradation
+ ])
end
end
@@ -304,11 +306,12 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
end
it 'returns the base report errors not found in the head report, sorted by severity' do
- expect(resolved_errors).to eq([
- blocker_degradation,
- critical_degradation,
- minor_degradation
- ])
+ expect(resolved_errors).to eq(
+ [
+ blocker_degradation,
+ critical_degradation,
+ minor_degradation
+ ])
end
end
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
index f4b47893805..68e70525c55 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
@@ -103,15 +103,16 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
end
it 'sorts degradations based on severity' do
- expect(codequality_report.degradations.values).to eq([
- blocker,
- critical,
- major,
- major_2,
- minor,
- info,
- unknown
- ])
+ expect(codequality_report.degradations.values).to eq(
+ [
+ blocker,
+ critical,
+ major,
+ major_2,
+ minor,
+ info,
+ unknown
+ ])
end
context 'with non-existence and uppercase severities' do
@@ -126,12 +127,13 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
end
it 'sorts unknown last' do
- expect(other_report.degradations.values).to eq([
- blocker,
- uppercase_major,
- minor,
- non_existent
- ])
+ expect(other_report.degradations.values).to eq(
+ [
+ blocker,
+ uppercase_major,
+ minor,
+ non_existent
+ ])
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
index cb30bd721dd..343c0d8c15c 100644
--- a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
@@ -12,8 +12,7 @@ RSpec.describe Gitlab::Ci::Reports::Sbom::Source do
'source_file' => { 'path' => 'package.json' },
'package_manager' => { 'name' => 'npm' },
'language' => { 'name' => 'JavaScript' }
- },
- fingerprint: '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ }
}
end
@@ -22,8 +21,7 @@ RSpec.describe Gitlab::Ci::Reports::Sbom::Source do
it 'has correct attributes' do
expect(subject).to have_attributes(
source_type: attributes[:type],
- data: attributes[:data],
- fingerprint: attributes[:fingerprint]
+ data: attributes[:data]
)
end
end
diff --git a/spec/lib/gitlab/ci/reports/security/report_spec.rb b/spec/lib/gitlab/ci/reports/security/report_spec.rb
index ab0efb90901..d7f967f1c55 100644
--- a/spec/lib/gitlab/ci/reports/security/report_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/report_spec.rb
@@ -140,6 +140,24 @@ RSpec.describe Gitlab::Ci::Reports::Security::Report do
it { is_expected.to eq(scanner_1) }
end
+ describe '#primary_identifiers' do
+ it 'returns matching identifiers' do
+ scanner_with_identifiers = create(
+ :ci_reports_security_scanner,
+ external_id: 'external_id_1',
+ primary_identifiers: [create(:ci_reports_security_identifier, external_id: 'other_id', name: 'other_scanner')]
+ )
+ scanner_without_identifiers = create(
+ :ci_reports_security_scanner,
+ external_id: 'external_id_2')
+
+ report.add_scanner(scanner_with_identifiers)
+ report.add_scanner(scanner_without_identifiers)
+
+ expect(report.primary_identifiers).to eq(scanner_with_identifiers.primary_identifiers)
+ end
+ end
+
describe '#add_error' do
context 'when the message is not given' do
it 'adds a new error to report with the generic error message' do
diff --git a/spec/lib/gitlab/ci/secure_files/cer_spec.rb b/spec/lib/gitlab/ci/secure_files/cer_spec.rb
new file mode 100644
index 00000000000..6b9cd0e3bfc
--- /dev/null
+++ b/spec/lib/gitlab/ci/secure_files/cer_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::SecureFiles::Cer do
+ context 'when the supplied certificate cannot be parsed' do
+ let(:invalid_certificate) { described_class.new('xyzabc') }
+
+ describe '#certificate_data' do
+ it 'assigns the error message and returns nil' do
+ expect(invalid_certificate.certificate_data).to be nil
+ expect(invalid_certificate.error).to eq('not enough data')
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns an empty hash' do
+ expect(invalid_certificate.metadata).to eq({})
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns nil' do
+ expect(invalid_certificate.metadata[:expires_at]).to be_nil
+ end
+ end
+ end
+
+ context 'when the supplied certificate can be parsed' do
+ let(:sample_file) { fixture_file('ci_secure_files/sample.cer') }
+ let(:subject) { described_class.new(sample_file) }
+
+ describe '#certificate_data' do
+ it 'returns an OpenSSL::X509::Certificate object' do
+ expect(subject.certificate_data.class).to be(OpenSSL::X509::Certificate)
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns a hash with the expected keys' do
+ expect(subject.metadata.keys).to match_array([:issuer, :subject, :id, :expires_at])
+ end
+ end
+
+ describe '#id' do
+ it 'returns the certificate serial number' do
+ expect(subject.metadata[:id]).to eq('33669367788748363528491290218354043267')
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns the certificate expiration timestamp' do
+ expect(subject.metadata[:expires_at]).to eq('2022-04-26 19:20:40 UTC')
+ end
+ end
+
+ describe '#issuer' do
+ it 'calls parse on X509Name' do
+ expect(subject.metadata[:issuer]["O"]).to eq('Apple Inc.')
+ end
+ end
+
+ describe '#subject' do
+ it 'calls parse on X509Name' do
+ expect(subject.metadata[:subject]["OU"]).to eq('N7SYAN8PX8')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/secure_files/mobile_provision_spec.rb b/spec/lib/gitlab/ci/secure_files/mobile_provision_spec.rb
new file mode 100644
index 00000000000..fb382174c64
--- /dev/null
+++ b/spec/lib/gitlab/ci/secure_files/mobile_provision_spec.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::SecureFiles::MobileProvision do
+ context 'when the supplied profile cannot be parsed' do
+ context 'when the supplied certificate cannot be parsed' do
+ let(:invalid_profile) { described_class.new('xyzabc') }
+
+ describe '#decoded_plist' do
+ it 'assigns the error message and returns nil' do
+ expect(invalid_profile.decoded_plist).to be nil
+ expect(invalid_profile.error).to eq('Could not parse the PKCS7: not enough data')
+ end
+ end
+
+ describe '#properties' do
+ it 'returns nil' do
+ expect(invalid_profile.properties).to be_nil
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns an empty hash' do
+ expect(invalid_profile.metadata).to eq({})
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns nil' do
+ expect(invalid_profile.metadata[:expires_at]).to be_nil
+ end
+ end
+ end
+ end
+
+ context 'when the supplied profile can be parsed' do
+ let(:sample_file) { fixture_file('ci_secure_files/sample.mobileprovision') }
+ let(:subject) { described_class.new(sample_file) }
+
+ describe '#decoded_plist' do
+ it 'returns an XML string' do
+ expect(subject.decoded_plist.class).to be(String)
+ expect(subject.decoded_plist.starts_with?('<?xml version="1.0"')).to be true
+ end
+ end
+
+ describe '#properties' do
+ it 'returns the property list of the decoded plist provided' do
+ expect(subject.properties.class).to be(Hash)
+ expect(subject.properties.keys).to match_array(%w[AppIDName ApplicationIdentifierPrefix CreationDate
+ Platform IsXcodeManaged DeveloperCertificates
+ DER-Encoded-Profile PPQCheck Entitlements ExpirationDate
+ Name ProvisionedDevices TeamIdentifier TeamName
+ TimeToLive UUID Version])
+ end
+
+ it 'returns nil if the property list fails to be parsed from the decoded plist' do
+ allow(subject).to receive(:decoded_plist).and_return('foo/bar')
+ expect(subject.properties).to be nil
+ expect(subject.error).to start_with('invalid XML')
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns a hash with the expected keys' do
+ expect(subject.metadata.keys).to match_array([:id, :expires_at, :app_id, :app_id_prefix, :app_name,
+ :certificate_ids, :devices, :entitlements, :platforms,
+ :team_id, :team_name, :xcode_managed])
+ end
+ end
+
+ describe '#id' do
+ it 'returns the profile UUID' do
+ expect(subject.metadata[:id]).to eq('6b9fcce1-b9a9-4b37-b2ce-ec4da2044abf')
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns the expiration timestamp of the profile' do
+ expect(subject.metadata[:expires_at].utc).to eq('2023-08-01 23:15:13 UTC')
+ end
+ end
+
+ describe '#platforms' do
+ it 'returns the platforms assigned to the profile' do
+ expect(subject.metadata[:platforms]).to match_array(['iOS'])
+ end
+ end
+
+ describe '#team_name' do
+ it 'returns the team name in the profile' do
+ expect(subject.metadata[:team_name]).to eq('Darby Frey')
+ end
+ end
+
+ describe '#team_id' do
+ it 'returns the team ids in the profile' do
+ expect(subject.metadata[:team_id]).to match_array(['N7SYAN8PX8'])
+ end
+ end
+
+ describe '#app_name' do
+ it 'returns the app name in the profile' do
+ expect(subject.metadata[:app_name]).to eq('iOS Demo')
+ end
+ end
+
+ describe '#app_id' do
+ it 'returns the app id in the profile' do
+ expect(subject.metadata[:app_id]).to eq('match Development com.gitlab.ios-demo')
+ end
+ end
+
+ describe '#app_id_prefix' do
+ it 'returns the app id prefixes in the profile' do
+ expect(subject.metadata[:app_id_prefix]).to match_array(['N7SYAN8PX8'])
+ end
+ end
+
+ describe '#xcode_managed' do
+ it 'returns the xcode_managed property in the profile' do
+ expect(subject.metadata[:xcode_managed]).to be false
+ end
+ end
+
+ describe '#entitlements' do
+ it 'returns the entitlements in the profile' do
+ expect(subject.metadata[:entitlements].keys).to match_array(['application-identifier',
+ 'com.apple.developer.game-center',
+ 'com.apple.developer.team-identifier',
+ 'get-task-allow',
+ 'keychain-access-groups'])
+ end
+ end
+
+ describe '#devices' do
+ it 'returns the devices attached to the profile' do
+ expect(subject.metadata[:devices]).to match_array(["00008101-001454860C10001E"])
+ end
+ end
+
+ describe '#certificate_ids' do
+ it 'returns the certificate ids attached to the profile' do
+ expect(subject.metadata[:certificate_ids]).to match_array(["23380136242930206312716563638445789376"])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/secure_files/p12_spec.rb b/spec/lib/gitlab/ci/secure_files/p12_spec.rb
new file mode 100644
index 00000000000..beabf4b4856
--- /dev/null
+++ b/spec/lib/gitlab/ci/secure_files/p12_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::SecureFiles::P12 do
+ context 'when the supplied certificate cannot be parsed' do
+ let(:invalid_certificate) { described_class.new('xyzabc') }
+
+ describe '#certificate_data' do
+ it 'assigns the error message and returns nil' do
+ expect(invalid_certificate.certificate_data).to be nil
+ expect(invalid_certificate.error).to eq('PKCS12_parse: mac verify failure')
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns an empty hash' do
+ expect(invalid_certificate.metadata).to eq({})
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns nil' do
+ expect(invalid_certificate.metadata[:expires_at]).to be_nil
+ end
+ end
+ end
+
+ context 'when the supplied certificate can be parsed, but the password is invalid' do
+ let(:sample_file) { fixture_file('ci_secure_files/sample.p12') }
+ let(:subject) { described_class.new(sample_file, 'foo') }
+
+ describe '#certificate_data' do
+ it 'assigns the error message and returns nil' do
+ expect(subject.certificate_data).to be nil
+ expect(subject.error).to eq('PKCS12_parse: mac verify failure')
+ end
+ end
+ end
+
+ context 'when the supplied certificate can be parsed' do
+ let(:sample_file) { fixture_file('ci_secure_files/sample.p12') }
+ let(:subject) { described_class.new(sample_file) }
+
+ describe '#certificate_data' do
+ it 'returns an OpenSSL::X509::Certificate object' do
+ expect(subject.certificate_data.class).to be(OpenSSL::X509::Certificate)
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns a hash with the expected keys' do
+ expect(subject.metadata.keys).to match_array([:issuer, :subject, :id, :expires_at])
+ end
+ end
+
+ describe '#id' do
+ it 'returns the certificate serial number' do
+ expect(subject.metadata[:id]).to eq('75949910542696343243264405377658443914')
+ end
+ end
+
+ describe '#expires_at' do
+ it 'returns the certificate expiration timestamp' do
+ expect(subject.metadata[:expires_at]).to eq('2022-09-21 14:56:00 UTC')
+ end
+ end
+
+ describe '#issuer' do
+ it 'calls parse on X509Name' do
+ expect(subject.metadata[:issuer]["O"]).to eq('Apple Inc.')
+ end
+ end
+
+ describe '#subject' do
+ it 'calls parse on X509Name' do
+ expect(subject.metadata[:subject]["OU"]).to eq('N7SYAN8PX8')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/secure_files/x509_name_spec.rb b/spec/lib/gitlab/ci/secure_files/x509_name_spec.rb
new file mode 100644
index 00000000000..3a523924c5b
--- /dev/null
+++ b/spec/lib/gitlab/ci/secure_files/x509_name_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::SecureFiles::X509Name do
+ describe '.parse' do
+ it 'parses an X509Name object into a hash format' do
+ sample = OpenSSL::X509::Name.new([
+ ['C', 'Test Country'],
+ ['O', 'Test Org Name'],
+ ['OU', 'Test Org Unit'],
+ ['CN', 'Test Common Name'],
+ ['UID', 'Test UID']
+ ])
+
+ parsed_sample = described_class.parse(sample)
+
+ expect(parsed_sample["C"]).to eq('Test Country')
+ expect(parsed_sample["O"]).to eq('Test Org Name')
+ expect(parsed_sample["OU"]).to eq('Test Org Unit')
+ expect(parsed_sample["CN"]).to eq('Test Common Name')
+ expect(parsed_sample["UID"]).to eq('Test UID')
+ end
+
+ it 'returns an empty hash when an error occurs' do
+ parsed_sample = described_class.parse('unexpectedinput')
+ expect(parsed_sample).to eq({})
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 3043c8c5467..321a47c0634 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_defa
trace.being_watched!
result = Gitlab::Redis::SharedState.with do |redis|
- redis.exists(cache_key)
+ redis.exists?(cache_key)
end
expect(result).to eq(true)
diff --git a/spec/lib/gitlab/ci/variables/builder/group_spec.rb b/spec/lib/gitlab/ci/variables/builder/group_spec.rb
index 72487588cde..c3743ebd2d7 100644
--- a/spec/lib/gitlab/ci/variables/builder/group_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder/group_spec.rb
@@ -132,11 +132,12 @@ RSpec.describe Gitlab::Ci::Variables::Builder::Group do
end
it 'orders the variables from least to most matched' do
- variables_collection = Gitlab::Ci::Variables::Collection.new([
- variable,
- partially_matched_variable,
- perfectly_matched_variable
- ]).to_runner_variables
+ variables_collection = Gitlab::Ci::Variables::Collection.new(
+ [
+ variable,
+ partially_matched_variable,
+ perfectly_matched_variable
+ ]).to_runner_variables
expect(subject.to_runner_variables).to eq(variables_collection)
end
diff --git a/spec/lib/gitlab/ci/variables/builder/project_spec.rb b/spec/lib/gitlab/ci/variables/builder/project_spec.rb
index b64b6ea98e2..c1cefc425f5 100644
--- a/spec/lib/gitlab/ci/variables/builder/project_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder/project_spec.rb
@@ -132,11 +132,12 @@ RSpec.describe Gitlab::Ci::Variables::Builder::Project do
end
it 'puts variables matching environment scope more in the end' do
- variables_collection = Gitlab::Ci::Variables::Collection.new([
- variable,
- partially_matched_variable,
- perfectly_matched_variable
- ]).to_runner_variables
+ variables_collection = Gitlab::Ci::Variables::Collection.new(
+ [
+ variable,
+ partially_matched_variable,
+ perfectly_matched_variable
+ ]).to_runner_variables
expect(subject.to_runner_variables).to eq(variables_collection)
end
diff --git a/spec/lib/gitlab/ci/variables/builder/release_spec.rb b/spec/lib/gitlab/ci/variables/builder/release_spec.rb
new file mode 100644
index 00000000000..85b1659d07b
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/builder/release_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Builder::Release do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:release) { create(:release, project: project) }
+
+ let(:builder) { described_class.new(release) }
+
+ describe '#variables' do
+ let(:description_variable) do
+ {
+ key: 'CI_RELEASE_DESCRIPTION',
+ value: release.description,
+ public: true,
+ masked: false,
+ raw: true
+ }
+ end
+
+ subject do
+ builder.variables
+ end
+
+ context 'when the release is present' do
+ let(:description_item) { item(description_variable) }
+
+ it 'contains all the variables' do
+ is_expected.to contain_exactly(description_item)
+ end
+
+ context 'for large description' do
+ before do
+ release.update_attribute(:description, "Test Description ..." * 5000)
+ end
+
+ it 'truncates' do
+ expect(subject['CI_RELEASE_DESCRIPTION'].value.length).to eq(1024)
+ end
+ end
+
+ context 'when description is nil' do
+ before do
+ release.update_attribute(:description, nil)
+ end
+
+ it 'returns without error' do
+ builder = subject
+
+ expect(builder).to match_array([])
+ expect(builder.errors).to be_nil
+ end
+ end
+ end
+
+ context 'when the release is not present' do
+ let(:release) { nil }
+
+ it 'contains no variables' do
+ is_expected.to match_array([])
+ end
+ end
+ end
+
+ def item(variable)
+ ::Gitlab::Ci::Variables::Collection::Item.fabricate(variable)
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 4833ccf9093..52ba85d2df1 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:job) do
create(:ci_build,
+ name: 'rspec:test 1',
pipeline: pipeline,
user: user,
yaml_variables: [{ key: 'YAML_VARIABLE', value: 'value' }]
@@ -24,13 +25,15 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
let(:predefined_variables) do
[
{ key: 'CI_JOB_NAME',
- value: job.name },
+ value: 'rspec:test 1' },
+ { key: 'CI_JOB_NAME_SLUG',
+ value: 'rspec-test-1' },
{ key: 'CI_JOB_STAGE',
value: job.stage_name },
{ key: 'CI_NODE_TOTAL',
value: '1' },
{ key: 'CI_BUILD_NAME',
- value: job.name },
+ value: 'rspec:test 1' },
{ key: 'CI_BUILD_STAGE',
value: job.stage_name },
{ key: 'CI',
@@ -171,6 +174,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
allow(builder).to receive(:secret_project_variables) { [var('L', 12), var('M', 12)] }
allow(pipeline).to receive(:variables) { [var('M', 13), var('N', 13)] }
allow(pipeline).to receive(:pipeline_schedule) { double(job_variables: [var('N', 14), var('O', 14)]) }
+ allow(builder).to receive(:release_variables) { [var('P', 15), var('Q', 15)] }
end
it 'returns variables in order depending on resource hierarchy' do
@@ -187,7 +191,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
var('K', 11), var('L', 11),
var('L', 12), var('M', 12),
var('M', 13), var('N', 13),
- var('N', 14), var('O', 14)])
+ var('N', 14), var('O', 14),
+ var('P', 15), var('Q', 15)])
end
it 'overrides duplicate keys depending on resource hierarchy' do
@@ -199,7 +204,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
'I' => '9', 'J' => '10',
'K' => '11', 'L' => '12',
'M' => '13', 'N' => '14',
- 'O' => '14')
+ 'O' => '14', 'P' => '15',
+ 'Q' => '15')
end
end
@@ -216,6 +222,27 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
.to include(a_hash_including(key: schedule_variable.key, value: schedule_variable.value))
end
end
+
+ context 'with release variables' do
+ let(:release_description_key) { 'CI_RELEASE_DESCRIPTION' }
+
+ let_it_be(:tag) { project.repository.tags.first }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, tag: true, ref: tag.name) }
+ let_it_be(:release) { create(:release, tag: tag.name, project: project) }
+
+ it 'includes release variables' do
+ expect(subject.to_hash).to include(release_description_key => release.description)
+ end
+
+ context 'when there is no release' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, tag: false, ref: 'master') }
+ let(:release) { nil }
+
+ it 'does not include release variables' do
+ expect(subject.to_hash).not_to have_key(release_description_key)
+ end
+ end
+ end
end
describe '#user_variables' do
@@ -261,10 +288,11 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
end
it 'includes #deployment_variables and merges the KUBECONFIG values', :aggregate_failures do
- expect(builder).to receive(:deployment_variables).and_return([
- { key: 'KUBECONFIG', value: 'deployment-kubeconfig' },
- { key: 'OTHER', value: 'some value' }
- ])
+ expect(builder).to receive(:deployment_variables).and_return(
+ [
+ { key: 'KUBECONFIG', value: 'deployment-kubeconfig' },
+ { key: 'OTHER', value: 'some value' }
+ ])
expect(template).to receive(:merge_yaml).with('deployment-kubeconfig')
expect(subject['KUBECONFIG'].value).to eq('example-kubeconfig')
expect(subject['OTHER'].value).to eq('some value')
diff --git a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
index 57171e5be69..432225c53f0 100644
--- a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
@@ -192,13 +192,14 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
end
it 'preserves relative order of overridden variables' do
- is_expected.to eq([
- { 'TOP_LEVEL_GROUP_NAME' => 'top-level-group' },
- { 'SUBGROUP_VAR' => '$TOP_LEVEL_GROUP_NAME' },
- { 'SUB_GROUP_NAME' => 'vars-in-vars-subgroup' },
- { 'SUBGROUP_VAR' => '$SUB_GROUP_NAME' },
- { 'PROJECT_VAR' => '$SUBGROUP_VAR' }
- ])
+ is_expected.to eq(
+ [
+ { 'TOP_LEVEL_GROUP_NAME' => 'top-level-group' },
+ { 'SUBGROUP_VAR' => '$TOP_LEVEL_GROUP_NAME' },
+ { 'SUB_GROUP_NAME' => 'vars-in-vars-subgroup' },
+ { 'SUBGROUP_VAR' => '$SUB_GROUP_NAME' },
+ { 'PROJECT_VAR' => '$SUBGROUP_VAR' }
+ ])
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 8ac03301322..7d4a1eef70b 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -571,5 +571,42 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
end
end
end
+
+ context 'with the file_variable_is_referenced_in_another_variable logging' do
+ let(:collection) do
+ Gitlab::Ci::Variables::Collection.new
+ .append(key: 'VAR1', value: 'test-1')
+ .append(key: 'VAR2', value: '$VAR1')
+ .append(key: 'VAR3', value: '$VAR1', raw: true)
+ .append(key: 'FILEVAR4', value: 'file-test-4', file: true)
+ .append(key: 'VAR5', value: '$FILEVAR4')
+ .append(key: 'VAR6', value: '$FILEVAR4', raw: true)
+ end
+
+ subject(:sort_and_expand_all) { collection.sort_and_expand_all(project: project) }
+
+ context 'when a project is not passed' do
+ let(:project) {}
+
+ it 'does not log anything' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ sort_and_expand_all
+ end
+ end
+
+ context 'when a project is passed' do
+ let(:project) { create(:project) }
+
+ it 'logs file_variable_is_referenced_in_another_variable once for VAR5' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(
+ event: 'file_variable_is_referenced_in_another_variable',
+ project_id: project.id
+ ).once
+
+ sort_and_expand_all
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index f7a0905d9da..7f203168706 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -71,10 +71,11 @@ module Gitlab
subject(:yaml_variables_for) { result.yaml_variables_for(job_name) }
it 'returns calculated variables with root and job variables' do
- is_expected.to match_array([
- { key: 'VAR1', value: 'value 11' },
- { key: 'VAR2', value: 'value 2' }
- ])
+ is_expected.to match_array(
+ [
+ { key: 'VAR1', value: 'value 11' },
+ { key: 'VAR2', value: 'value 2' }
+ ])
end
context 'when an absent job is sent' do
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index cc327f5b5f1..ebf8422489e 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -15,8 +15,10 @@ module Gitlab
end
end
- describe '#build_attributes' do
- subject { described_class.new(config, user: nil).execute.build_attributes(:rspec) }
+ describe '#builds' do
+ subject(:builds) { described_class.new(config, user: nil).execute.builds }
+
+ let(:rspec_build) { builds.find { |build| build[:name] == 'rspec' } }
describe 'attributes list' do
let(:config) do
@@ -30,7 +32,7 @@ module Gitlab
end
it 'returns valid build attributes' do
- expect(subject).to eq({
+ expect(builds).to eq([{
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -45,7 +47,7 @@ module Gitlab
job_variables: [],
root_variables_inheritance: true,
scheduling_type: :stage
- })
+ }])
end
end
@@ -63,7 +65,7 @@ module Gitlab
end
it 'returns valid build attributes' do
- expect(subject).to eq({
+ expect(builds).to eq([{
stage: 'test',
stage_idx: 2,
name: 'rspec',
@@ -77,7 +79,7 @@ module Gitlab
job_variables: [],
root_variables_inheritance: true,
scheduling_type: :stage
- })
+ }])
end
end
@@ -89,21 +91,22 @@ module Gitlab
end
it 'includes coverage regexp in build attributes' do
- expect(subject)
+ expect(rspec_build)
.to include(coverage_regex: 'Code coverage: \d+\.\d+')
end
end
end
describe 'tags entry with default values' do
- it 'applies default values' do
- config = YAML.dump({ default: { tags: %w[A B] },
- rspec: { script: "rspec" } })
-
- config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ let(:config) do
+ YAML.dump(
+ default: { tags: %w[A B] },
+ rspec: { script: "rspec" }
+ )
+ end
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ it 'applies default values' do
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -125,7 +128,7 @@ module Gitlab
YAML.dump(rspec: { script: 'rspec', interruptible: true })
end
- it { expect(subject[:interruptible]).to be_truthy }
+ it { expect(rspec_build[:interruptible]).to be_truthy }
end
describe 'interruptible job with default value' do
@@ -133,7 +136,7 @@ module Gitlab
YAML.dump(rspec: { script: 'rspec' })
end
- it { expect(subject).not_to have_key(:interruptible) }
+ it { expect(rspec_build).not_to have_key(:interruptible) }
end
describe 'uninterruptible job' do
@@ -141,7 +144,7 @@ module Gitlab
YAML.dump(rspec: { script: 'rspec', interruptible: false })
end
- it { expect(subject[:interruptible]).to be_falsy }
+ it { expect(rspec_build[:interruptible]).to be_falsy }
end
it "returns interruptible when overridden for job" do
@@ -149,9 +152,10 @@ module Gitlab
rspec: { script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ builds = config_processor.builds.select { |b| b[:stage] == "test" }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(builds.size).to eq(1)
+ expect(builds.first).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -174,7 +178,7 @@ module Gitlab
end
it 'includes retry count in build options attribute' do
- expect(subject[:options]).to include(retry: { max: 1 })
+ expect(rspec_build[:options]).to include(retry: { max: 1 })
end
end
@@ -184,7 +188,7 @@ module Gitlab
end
it 'does not persist retry count in the database' do
- expect(subject[:options]).not_to have_key(:retry)
+ expect(rspec_build[:options]).not_to have_key(:retry)
end
end
@@ -195,7 +199,7 @@ module Gitlab
end
it 'does use the default value' do
- expect(subject[:options]).to include(retry: { max: 1 })
+ expect(rspec_build[:options]).to include(retry: { max: 1 })
end
end
@@ -206,7 +210,7 @@ module Gitlab
end
it 'does use the job value' do
- expect(subject[:options]).to include(retry: { max: 2 })
+ expect(rspec_build[:options]).to include(retry: { max: 2 })
end
end
end
@@ -221,7 +225,7 @@ module Gitlab
end
it 'is not allowed to fail' do
- expect(subject[:allow_failure]).to be false
+ expect(rspec_build[:allow_failure]).to be false
end
end
@@ -232,7 +236,7 @@ module Gitlab
end
it 'is allowed to fail' do
- expect(subject[:allow_failure]).to be true
+ expect(rspec_build[:allow_failure]).to be true
end
end
@@ -244,11 +248,11 @@ module Gitlab
end
it 'is not allowed to fail' do
- expect(subject[:allow_failure]).to be false
+ expect(rspec_build[:allow_failure]).to be false
end
it 'saves allow_failure_criteria into options' do
- expect(subject[:options]).to match(
+ expect(rspec_build[:options]).to match(
a_hash_including(allow_failure_criteria: { exit_codes: [1] }))
end
end
@@ -262,7 +266,7 @@ module Gitlab
end
it 'is not allowed to fail' do
- expect(subject[:allow_failure]).to be false
+ expect(rspec_build[:allow_failure]).to be false
end
end
@@ -272,7 +276,7 @@ module Gitlab
end
it 'is not allowed to fail' do
- expect(subject[:allow_failure]).to be false
+ expect(rspec_build[:allow_failure]).to be false
end
end
@@ -283,11 +287,11 @@ module Gitlab
end
it 'is not allowed to fail' do
- expect(subject[:allow_failure]).to be false
+ expect(rspec_build[:allow_failure]).to be false
end
it 'saves allow_failure_criteria into options' do
- expect(subject[:options]).to match(
+ expect(rspec_build[:options]).to match(
a_hash_including(allow_failure_criteria: { exit_codes: [1] }))
end
end
@@ -305,8 +309,8 @@ module Gitlab
end
it 'has the attributes' do
- expect(subject[:when]).to eq 'delayed'
- expect(subject[:options][:start_in]).to eq '1 day'
+ expect(rspec_build[:when]).to eq 'delayed'
+ expect(rspec_build[:options][:start_in]).to eq '1 day'
end
end
end
@@ -321,7 +325,7 @@ module Gitlab
end
it 'has the attributes' do
- expect(subject[:resource_group_key]).to eq 'iOS'
+ expect(rspec_build[:resource_group_key]).to eq 'iOS'
end
end
end
@@ -337,7 +341,7 @@ module Gitlab
end
it 'has the attributes' do
- expect(subject[:options]).to eq(
+ expect(rspec_build[:options]).to eq(
trigger: { project: 'namespace/project', branch: 'main' }
)
end
@@ -353,7 +357,7 @@ module Gitlab
end
it 'has the attributes' do
- expect(subject[:options]).to eq(
+ expect(rspec_build[:options]).to eq(
trigger: { project: 'namespace/project', forward: { pipeline_variables: true } }
)
end
@@ -510,6 +514,35 @@ module Gitlab
expect(subject.root_variables).to eq([])
end
end
+
+ context 'with name' do
+ let(:config) do
+ <<-EOYML
+ workflow:
+ name: 'Pipeline name'
+
+ hello:
+ script: echo world
+ EOYML
+ end
+
+ it 'parses the workflow:name as workflow_name' do
+ expect(subject.workflow_name).to eq('Pipeline name')
+ end
+ end
+
+ context 'with no name' do
+ let(:config) do
+ <<-EOYML
+ hello:
+ script: echo world
+ EOYML
+ end
+
+ it 'parses the workflow:name' do
+ expect(subject.workflow_name).to be_nil
+ end
+ end
end
describe '#warnings' do
@@ -682,7 +715,7 @@ module Gitlab
let(:config_data) { YAML.dump(config) }
let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config_data).execute }
- subject { config_processor.stage_builds_attributes('test').first }
+ subject(:test_build) { config_processor.builds.find { |build| build[:name] == 'test' } }
describe "before_script" do
context "in global context" do
@@ -850,9 +883,9 @@ module Gitlab
rspec: { script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -884,9 +917,9 @@ module Gitlab
script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -916,9 +949,9 @@ module Gitlab
rspec: { script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -944,9 +977,9 @@ module Gitlab
rspec: { image: "image:1.0", services: ["postgresql", "docker:dind"], script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -981,7 +1014,7 @@ module Gitlab
it { is_expected.to be_valid }
it "returns with image" do
- expect(processor.stage_builds_attributes("test")).to contain_exactly({
+ expect(processor.builds).to contain_exactly({
stage: "test",
stage_idx: 2,
name: "test",
@@ -1014,7 +1047,7 @@ module Gitlab
it { is_expected.to be_valid }
it "returns with service" do
- expect(processor.stage_builds_attributes("test")).to contain_exactly({
+ expect(processor.builds).to contain_exactly({
stage: "test",
stage_idx: 2,
name: "test",
@@ -1033,8 +1066,7 @@ module Gitlab
end
end
- # Change this to a `describe` block when removing the FF ci_variables_refactoring_to_variable
- shared_examples 'Variables' do
+ describe 'Variables' do
subject(:execute) { described_class.new(config).execute }
let(:build) { execute.builds.first }
@@ -1163,18 +1195,6 @@ module Gitlab
end
end
- context 'when ci_variables_refactoring_to_variable is enabled' do
- it_behaves_like 'Variables'
- end
-
- context 'when ci_variables_refactoring_to_variable is disabled' do
- before do
- stub_feature_flags(ci_variables_refactoring_to_variable: false)
- end
-
- it_behaves_like 'Variables'
- end
-
context 'when using `extends`' do
let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
@@ -1375,7 +1395,7 @@ module Gitlab
})
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
- builds = config_processor.stage_builds_attributes("test")
+ builds = config_processor.builds
expect(builds.size).to eq(1)
expect(builds.first[:when]).to eq(when_state)
@@ -1391,7 +1411,7 @@ module Gitlab
end
it 'creates one build and sets when:' do
- builds = subject.stage_builds_attributes("test")
+ builds = processor.builds
expect(builds.size).to eq(1)
expect(builds.first[:when]).to eq('delayed')
@@ -1419,7 +1439,7 @@ module Gitlab
end
let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
- let(:builds) { config_processor.stage_builds_attributes('test') }
+ let(:builds) { config_processor.builds }
context 'when job is parallelized' do
let(:parallel) { 5 }
@@ -1535,15 +1555,16 @@ module Gitlab
})
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq([
- paths: ["logs/", "binaries/"],
- untracked: true,
- key: 'key',
- policy: 'pull-push',
- when: 'on_success'
- ])
+ expect(rspec_build[:cache]).to eq(
+ [
+ paths: ["logs/", "binaries/"],
+ untracked: true,
+ key: 'key',
+ policy: 'pull-push',
+ when: 'on_success'
+ ])
end
it "returns cache when defined in default context" do
@@ -1558,32 +1579,34 @@ module Gitlab
})
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq([
- paths: ["logs/", "binaries/"],
- untracked: true,
- key: { files: ['file'] },
- policy: 'pull-push',
- when: 'on_success'
- ])
+ expect(rspec_build[:cache]).to eq(
+ [
+ paths: ["logs/", "binaries/"],
+ untracked: true,
+ key: { files: ['file'] },
+ policy: 'pull-push',
+ when: 'on_success'
+ ])
end
it 'returns cache key/s when defined in a job' do
- config = YAML.dump({
- rspec: {
- cache: [
- { paths: ['binaries/'], untracked: true, key: 'keya' },
- { paths: ['logs/', 'binaries/'], untracked: true, key: 'key' }
- ],
- script: 'rspec'
- }
- })
+ config = YAML.dump(
+ {
+ rspec: {
+ cache: [
+ { paths: ['binaries/'], untracked: true, key: 'keya' },
+ { paths: ['logs/', 'binaries/'], untracked: true, key: 'key' }
+ ],
+ script: 'rspec'
+ }
+ })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes('test').size).to eq(1)
- expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq(
+ expect(rspec_build[:cache]).to eq(
[
{
paths: ['binaries/'],
@@ -1616,15 +1639,16 @@ module Gitlab
)
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes('test').size).to eq(1)
- expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq([
- paths: ['binaries/'],
- untracked: true,
- key: { files: ['file'] },
- policy: 'pull-push',
- when: 'on_success'
- ])
+ expect(rspec_build[:cache]).to eq(
+ [
+ paths: ['binaries/'],
+ untracked: true,
+ key: { files: ['file'] },
+ policy: 'pull-push',
+ when: 'on_success'
+ ])
end
it 'returns cache files with prefix' do
@@ -1640,61 +1664,65 @@ module Gitlab
)
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes('test').size).to eq(1)
- expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq([
- paths: ['logs/', 'binaries/'],
- untracked: true,
- key: { files: ['file'], prefix: 'prefix' },
- policy: 'pull-push',
- when: 'on_success'
- ])
+ expect(rspec_build[:cache]).to eq(
+ [
+ paths: ['logs/', 'binaries/'],
+ untracked: true,
+ key: { files: ['file'], prefix: 'prefix' },
+ policy: 'pull-push',
+ when: 'on_success'
+ ])
end
it "overwrite cache when defined for a job and globally" do
- config = YAML.dump({
- cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' },
- rspec: {
- script: "rspec",
- cache: { paths: ["test/"], untracked: false, key: 'local' }
- }
- })
+ config = YAML.dump(
+ {
+ cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' },
+ rspec: {
+ script: "rspec",
+ cache: { paths: ["test/"], untracked: false, key: 'local' }
+ }
+ })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq([
- paths: ["test/"],
- untracked: false,
- key: 'local',
- policy: 'pull-push',
- when: 'on_success'
- ])
+ expect(rspec_build[:cache]).to eq(
+ [
+ paths: ["test/"],
+ untracked: false,
+ key: 'local',
+ policy: 'pull-push',
+ when: 'on_success'
+ ])
end
end
describe "Artifacts" do
it "returns artifacts when defined" do
- config = YAML.dump({
- image: "image:1.0",
- services: ["mysql"],
- before_script: ["pwd"],
- rspec: {
- artifacts: {
- paths: ["logs/", "binaries/"],
- expose_as: "Exposed artifacts",
- untracked: true,
- name: "custom_name",
- expire_in: "7d"
- },
- script: "rspec"
- }
- })
+ config = YAML.dump(
+ {
+ image: "image:1.0",
+ services: ["mysql"],
+ before_script: ["pwd"],
+ rspec: {
+ artifacts: {
+ paths: ["logs/", "binaries/"],
+ expose_as: "Exposed artifacts",
+ untracked: true,
+ name: "custom_name",
+ expire_in: "7d"
+ },
+ script: "rspec"
+ }
+ })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
+ rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' }
- expect(config_processor.stage_builds_attributes("test").size).to eq(1)
- expect(config_processor.stage_builds_attributes("test").first).to eq({
+ expect(rspec_build).to eq({
stage: "test",
stage_idx: 2,
name: "rspec",
@@ -1729,7 +1757,7 @@ module Gitlab
})
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
- builds = config_processor.stage_builds_attributes("test")
+ builds = config_processor.builds
expect(builds.size).to eq(1)
expect(builds.first[:options][:artifacts][:expire_in]).to eq('never')
@@ -1745,7 +1773,7 @@ module Gitlab
})
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
- builds = config_processor.stage_builds_attributes("test")
+ builds = config_processor.builds
expect(builds.size).to eq(1)
expect(builds.first[:options][:artifacts][:when]).to eq(when_state)
@@ -1778,7 +1806,7 @@ module Gitlab
- my/test/something
YAML
- attributes = Gitlab::Ci::YamlProcessor.new(config).execute.build_attributes('test')
+ attributes = Gitlab::Ci::YamlProcessor.new(config).execute.builds.find { |build| build[:name] == 'test' }
expect(attributes.dig(*%i[options artifacts exclude])).to eq(%w[my/test/something])
end
@@ -1819,7 +1847,7 @@ module Gitlab
end
it "returns release info" do
- expect(processor.stage_builds_attributes('release').first[:options])
+ expect(processor.builds.first[:options])
.to eq(config[:release].except(:stage, :only))
end
end
@@ -1833,7 +1861,7 @@ module Gitlab
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
- let(:builds) { subject.stage_builds_attributes('deploy') }
+ let(:builds) { subject.builds }
context 'when a production environment is specified' do
let(:environment) { 'production' }
@@ -1943,7 +1971,7 @@ module Gitlab
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
- let(:builds) { subject.stage_builds_attributes('deploy') }
+ let(:builds) { subject.builds }
context 'when no timeout was provided' do
it 'does not include job_timeout' do
@@ -2370,8 +2398,8 @@ module Gitlab
it 'returns a valid configuration and sets artifacts: true by default' do
expect(subject).to be_valid
- rspec = subject.build_attributes(:rspec)
- expect(rspec.dig(:options, :cross_dependencies)).to eq(
+ rspec_build = subject.builds.find { |build| build[:name] == 'rspec' }
+ expect(rspec_build.dig(:options, :cross_dependencies)).to eq(
[{ pipeline: '$THE_PIPELINE_ID', job: 'dependency-job', artifacts: true }]
)
end
@@ -2391,8 +2419,8 @@ module Gitlab
it 'returns a valid configuration and sets artifacts: true by default' do
expect(subject).to be_valid
- rspec = subject.build_attributes(:rspec)
- expect(rspec.dig(:options, :cross_dependencies)).to eq(
+ rspec_build = subject.builds.find { |build| build[:name] == 'rspec' }
+ expect(rspec_build.dig(:options, :cross_dependencies)).to eq(
[{ pipeline: '123', job: 'dependency-job', artifacts: true }]
)
end
@@ -2422,7 +2450,7 @@ module Gitlab
describe "Hidden jobs" do
let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
- subject { config_processor.stage_builds_attributes("test") }
+ subject { config_processor.builds }
shared_examples 'hidden_job_handling' do
it "doesn't create jobs that start with dot" do
@@ -2470,7 +2498,7 @@ module Gitlab
describe "YAML Alias/Anchor" do
let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
- subject { config_processor.stage_builds_attributes("build") }
+ subject { config_processor.builds }
shared_examples 'job_templates_handling' do
it "is correctly supported for jobs" do
diff --git a/spec/lib/gitlab/config/entry/validators_spec.rb b/spec/lib/gitlab/config/entry/validators_spec.rb
index cbc09aac586..0458bcd6354 100644
--- a/spec/lib/gitlab/config/entry/validators_spec.rb
+++ b/spec/lib/gitlab/config/entry/validators_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Gitlab::Config::Entry::Validators do
expect(instance.valid?).to be(valid_result)
unless valid_result
- expect(instance.errors.messages_for(:config)).to include /please use only one the following keys: foo, bar/
+ expect(instance.errors.messages_for(:config)).to include /please use only one of the following keys: foo, bar/
end
end
end
diff --git a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
index 933b6d6be9e..9af6aed2b02 100644
--- a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
+++ b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
@@ -6,36 +6,97 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
describe '#check' do
subject { described_class.check }
- context 'when database meets minimum supported version' do
+ let(:old_database_version) { 8 }
+ let(:old_database) { instance_double(Gitlab::Database::Reflection) }
+ let(:new_database) { instance_double(Gitlab::Database::Reflection) }
+
+ before do
+ allow(Gitlab::Database::Reflection).to receive(:new).and_return(new_database)
+ allow(old_database).to receive(:postgresql_minimum_supported_version?).and_return(false)
+ allow(old_database).to receive(:version).and_return(old_database_version)
+ allow(new_database).to receive(:postgresql_minimum_supported_version?).and_return(true)
+ end
+
+ context 'with a single database' do
before do
- allow(ApplicationRecord.database).to receive(:postgresql_minimum_supported_version?).and_return(true)
+ skip_if_multiple_databases_are_setup
+ end
+
+ context 'when database meets minimum supported version' do
+ before do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(new_database)
+ end
+
+ it { is_expected.to be_empty }
end
- it { is_expected.to be_empty }
+ context 'when database does not meet minimum supported version' do
+ before do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(old_database)
+ end
+
+ it 'reports deprecated database notice' do
+ is_expected.to contain_exactly(notice_deprecated_database(old_database_version))
+ end
+ end
end
- context 'when database does not meet minimum supported version' do
+ context 'with a multiple database' do
before do
- allow(ApplicationRecord.database).to receive(:postgresql_minimum_supported_version?).and_return(false)
+ skip_if_multiple_databases_not_setup
end
- let(:notice_deprecated_database) do
- {
- type: 'warning',
- message: _('You are using PostgreSQL %{pg_version_current}, but PostgreSQL ' \
- '%{pg_version_minimum} is required for this version of GitLab. ' \
- 'Please upgrade your environment to a supported PostgreSQL version, ' \
- 'see %{pg_requirements_url} for details.') % {
- pg_version_current: ApplicationRecord.database.version,
- pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
- pg_requirements_url: '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
- }
- }
+ context 'when both databases meets minimum supported version' do
+ before do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(new_database)
+ allow(Gitlab::Database::Reflection).to receive(:new).with(Ci::ApplicationRecord).and_return(new_database)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the one of the databases does not meet minimum supported version' do
+ it 'reports deprecated database notice if the main database is using an old version' do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(old_database)
+ allow(Gitlab::Database::Reflection).to receive(:new).with(Ci::ApplicationRecord).and_return(new_database)
+ is_expected.to contain_exactly(notice_deprecated_database(old_database_version))
+ end
+
+ it 'reports deprecated database notice if the ci database is using an old version' do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(new_database)
+ allow(Gitlab::Database::Reflection).to receive(:new).with(Ci::ApplicationRecord).and_return(old_database)
+ is_expected.to contain_exactly(notice_deprecated_database(old_database_version))
+ end
end
- it 'reports deprecated database notice' do
- is_expected.to contain_exactly(notice_deprecated_database)
+ context 'when both databases do not meet minimum supported version' do
+ before do
+ allow(Gitlab::Database::Reflection).to receive(:new).with(ActiveRecord::Base).and_return(old_database)
+ allow(Gitlab::Database::Reflection).to receive(:new).with(Ci::ApplicationRecord).and_return(old_database)
+ end
+
+ it 'reports deprecated database notice' do
+ is_expected.to match_array [
+ notice_deprecated_database(old_database_version),
+ notice_deprecated_database(old_database_version)
+ ]
+ end
end
end
end
+
+ def notice_deprecated_database(database_version)
+ {
+ type: 'warning',
+ message: _('You are using PostgreSQL %{pg_version_current}, but PostgreSQL ' \
+ '%{pg_version_minimum} is required for this version of GitLab. ' \
+ 'Please upgrade your environment to a supported PostgreSQL version, ' \
+ 'see %{pg_requirements_url} for details.') % \
+ {
+ pg_version_current: database_version,
+ pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
+ pg_requirements_url: Gitlab::ConfigChecker::ExternalDatabaseChecker::PG_REQUIREMENTS_LINK
+ }
+ }
+ end
end
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index aac4936b20e..1fa6eee9813 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -141,19 +141,20 @@ RSpec.describe Gitlab::Conflict::File do
let(:raw_conflict_content) { index.merge_file('files/ruby/popen.rb')[:data] }
it 'assign conflict types and adds match line to the end of the section' do
- expect(diff_line_types).to eq([
- 'match',
- nil, nil, nil,
- "conflict_marker_our",
- "conflict_our",
- "conflict_marker",
- "conflict_their",
- "conflict_their",
- "conflict_their",
- "conflict_marker_their",
- nil, nil, nil,
- "match"
- ])
+ expect(diff_line_types).to eq(
+ [
+ 'match',
+ nil, nil, nil,
+ "conflict_marker_our",
+ "conflict_our",
+ "conflict_marker",
+ "conflict_their",
+ "conflict_their",
+ "conflict_their",
+ "conflict_marker_their",
+ nil, nil, nil,
+ "match"
+ ])
end
end
end
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 86a1539a836..46a12d8c6f6 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -30,6 +30,7 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
expect(attributes[:sha]).to eq(pipeline.sha)
expect(attributes[:tag]).to eq(pipeline.tag)
expect(attributes[:id]).to eq(pipeline.id)
+ expect(attributes[:iid]).to eq(pipeline.iid)
expect(attributes[:source]).to eq(pipeline.source)
expect(attributes[:status]).to eq(pipeline.status)
expect(attributes[:detailed_status]).to eq('passed')
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 3daed2508a2..1ac9cbae036 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
describe '#execute!' do
context 'when an invalid transition is applied' do
- %i[finished finalizing].each do |state|
+ %i[finalizing finished].each do |state|
it 'raises an exception' do
batched_migration = create(:batched_background_migration, state)
@@ -103,6 +103,48 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
+ describe '#finish!' do
+ context 'when an invalid transition is applied' do
+ it 'raises an exception' do
+ batched_migration = create(:batched_background_migration, :failed)
+
+ expect { batched_migration.finish! }.to raise_error(StateMachines::InvalidTransition, /Cannot transition status/)
+ end
+ end
+
+ context 'when a valid transition is applied' do
+ %i[active paused finished finalizing].each do |state|
+ it 'moves to active' do
+ batched_migration = create(:batched_background_migration, state)
+
+ expect(batched_migration.finish!).to be_truthy
+ end
+ end
+ end
+ end
+
+ describe '#failure!' do
+ context 'when an invalid transition is applied' do
+ %i[paused finished].each do |state|
+ it 'raises an exception' do
+ batched_migration = create(:batched_background_migration, state)
+
+ expect { batched_migration.failure! }.to raise_error(StateMachines::InvalidTransition, /Cannot transition status/)
+ end
+ end
+ end
+
+ context 'when a valid transition is applied' do
+ %i[failed finalizing active].each do |state|
+ it 'moves to active' do
+ batched_migration = create(:batched_background_migration, state)
+
+ expect(batched_migration.failure!).to be_truthy
+ end
+ end
+ end
+ end
+
describe '.valid_status' do
valid_status = [:paused, :active, :finished, :failed, :finalizing]
diff --git a/spec/lib/gitlab/database/each_database_spec.rb b/spec/lib/gitlab/database/each_database_spec.rb
index 2a6eb8f779d..75b543bee85 100644
--- a/spec/lib/gitlab/database/each_database_spec.rb
+++ b/spec/lib/gitlab/database/each_database_spec.rb
@@ -93,12 +93,13 @@ RSpec.describe Gitlab::Database::EachDatabase do
end
it 'yields each model with SharedModel connected to each database connection' do
- expect_yielded_models([model1, model2], [
- { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
- { model: model1, connection: Ci::ApplicationRecord.connection, name: 'ci' },
- { model: model2, connection: ActiveRecord::Base.connection, name: 'main' },
- { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
- ])
+ expect_yielded_models([model1, model2],
+ [
+ { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model1, connection: Ci::ApplicationRecord.connection, name: 'ci' },
+ { model: model2, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ])
end
context 'when the model limits connection names' do
@@ -108,10 +109,11 @@ RSpec.describe Gitlab::Database::EachDatabase do
end
it 'only yields the model with SharedModel connected to the limited connections' do
- expect_yielded_models([model1, model2], [
- { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
- { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
- ])
+ expect_yielded_models([model1, model2],
+ [
+ { model: model1, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: model2, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ])
end
end
end
@@ -132,10 +134,11 @@ RSpec.describe Gitlab::Database::EachDatabase do
end
it 'yields each model after connecting SharedModel' do
- expect_yielded_models([main_model, ci_model], [
- { model: main_model, connection: main_connection, name: 'main' },
- { model: ci_model, connection: ci_connection, name: 'ci' }
- ])
+ expect_yielded_models([main_model, ci_model],
+ [
+ { model: main_model, connection: main_connection, name: 'main' },
+ { model: ci_model, connection: ci_connection, name: 'ci' }
+ ])
end
end
@@ -154,21 +157,23 @@ RSpec.describe Gitlab::Database::EachDatabase do
context 'when a single name is passed in' do
it 'yields models only connected to the given database' do
- expect_yielded_models([main_model, ci_model, shared_model], [
- { model: ci_model, connection: Ci::ApplicationRecord.connection, name: 'ci' },
- { model: shared_model, connection: Ci::ApplicationRecord.connection, name: 'ci' }
- ], only_on: 'ci')
+ expect_yielded_models([main_model, ci_model, shared_model],
+ [
+ { model: ci_model, connection: Ci::ApplicationRecord.connection, name: 'ci' },
+ { model: shared_model, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ], only_on: 'ci')
end
end
context 'when a list of names are passed in' do
it 'yields models only connected to the given databases' do
- expect_yielded_models([main_model, ci_model, shared_model], [
- { model: main_model, connection: ActiveRecord::Base.connection, name: 'main' },
- { model: ci_model, connection: Ci::ApplicationRecord.connection, name: 'ci' },
- { model: shared_model, connection: ActiveRecord::Base.connection, name: 'main' },
- { model: shared_model, connection: Ci::ApplicationRecord.connection, name: 'ci' }
- ], only_on: %i[main ci])
+ expect_yielded_models([main_model, ci_model, shared_model],
+ [
+ { model: main_model, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: ci_model, connection: Ci::ApplicationRecord.connection, name: 'ci' },
+ { model: shared_model, connection: ActiveRecord::Base.connection, name: 'main' },
+ { model: shared_model, connection: Ci::ApplicationRecord.connection, name: 'ci' }
+ ], only_on: %i[main ci])
end
end
end
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 9c09253b24c..997c7a31cba 100644
--- a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -210,10 +210,25 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
it 'uses a retry with exponential backoffs' do
- expect(lb).to receive(:retry_with_backoff).and_yield
+ expect(lb).to receive(:retry_with_backoff).and_yield(0)
lb.read_write { 10 }
end
+
+ it 'does not raise NoMethodError error when primary_only?' do
+ connection = ActiveRecord::Base.connection_pool.connection
+ expected_error = Gitlab::Database::LoadBalancing::CONNECTION_ERRORS.first
+
+ allow(lb).to receive(:primary_only?).and_return(true)
+
+ expect do
+ lb.read_write do
+ connection.transaction do
+ raise expected_error
+ end
+ end
+ end.to raise_error(expected_error)
+ end
end
describe '#host' do
@@ -330,6 +345,19 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
expect { lb.retry_with_backoff { raise } }.to raise_error(RuntimeError)
end
+
+ it 'yields the current retry iteration' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+ expect(lb).to receive(:release_primary_connection).exactly(3).times
+ iterations = []
+
+ # time: 0 so that we don't sleep and slow down the test
+ # rubocop: disable Style/Semicolon
+ expect { lb.retry_with_backoff(attempts: 3, time: 0) { |i| iterations << i; raise } }.to raise_error(RuntimeError)
+ # rubocop: enable Style/Semicolon
+
+ expect(iterations).to eq([1, 2, 3])
+ end
end
describe '#connection_error?' do
diff --git a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
index a1c141af537..713bff5feea 100644
--- a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
@@ -9,10 +9,10 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
let(:single_sticking_object) { Set.new([[ActiveRecord::Base.sticking, :user, 42]]) }
let(:multiple_sticking_objects) do
Set.new([
- [ActiveRecord::Base.sticking, :user, 42],
- [ActiveRecord::Base.sticking, :runner, '123456789'],
- [ActiveRecord::Base.sticking, :runner, '1234']
- ])
+ [ActiveRecord::Base.sticking, :user, 42],
+ [ActiveRecord::Base.sticking, :runner, '123456789'],
+ [ActiveRecord::Base.sticking, :runner, '1234']
+ ])
end
after do
@@ -182,11 +182,12 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
it 'returns the sticking object' do
env = { described_class::STICK_OBJECT => multiple_sticking_objects }
- expect(middleware.sticking_namespaces(env)).to eq([
- [ActiveRecord::Base.sticking, :user, 42],
- [ActiveRecord::Base.sticking, :runner, '123456789'],
- [ActiveRecord::Base.sticking, :runner, '1234']
- ])
+ expect(middleware.sticking_namespaces(env)).to eq(
+ [
+ [ActiveRecord::Base.sticking, :user, 42],
+ [ActiveRecord::Base.sticking, :runner, '123456789'],
+ [ActiveRecord::Base.sticking, :runner, '1234']
+ ])
end
end
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 8053bd57bba..88007de53d3 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
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:middleware) { described_class.new }
let(:worker) { worker_class.new }
let(:location) { '0/D525E3A8' }
- let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
+ let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_s => location } }
let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations } }
before do
@@ -315,6 +315,46 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
expect(middleware.send(:databases_in_sync?, locations))
.to eq(false)
end
+
+ context 'when locations have string keys' do
+ it 'returns false when the load balancers are not in sync' do
+ locations = {}
+
+ Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
+ locations[lb.name.to_s] = 'foo'
+
+ allow(lb)
+ .to receive(:select_up_to_date_host)
+ .with('foo')
+ .and_return(false)
+ end
+
+ expect(middleware.send(:databases_in_sync?, locations))
+ .to eq(false)
+ end
+
+ context 'when "indifferent_wal_location_keys" FF is off' do
+ before do
+ stub_feature_flags(indifferent_wal_location_keys: false)
+ end
+
+ it 'returns true when the load balancers are not in sync' do
+ locations = {}
+
+ Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
+ locations[lb.name.to_s] = 'foo'
+
+ allow(lb)
+ .to receive(:select_up_to_date_host)
+ .with('foo')
+ .and_return(false)
+ end
+
+ expect(middleware.send(:databases_in_sync?, locations))
+ .to eq(true)
+ end
+ end
+ end
end
def process_job(job)
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
index 2ffb2c32c32..1e316c55786 100644
--- a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -41,10 +41,12 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
sticking.stick_or_unstick_request(env, :user, 42)
sticking.stick_or_unstick_request(env, :runner, '123456789')
- expect(env[Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT].to_a).to eq([
- [sticking, :user, 42],
- [sticking, :runner, '123456789']
- ])
+ expect(env[Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT].to_a).to eq(
+ [
+ [sticking, :user, 42],
+ [sticking, :runner,
+ '123456789']
+ ])
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/transaction_leaking_spec.rb b/spec/lib/gitlab/database/load_balancing/transaction_leaking_spec.rb
index 30e5fbbd803..6026d979bcf 100644
--- a/spec/lib/gitlab/database/load_balancing/transaction_leaking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/transaction_leaking_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Load balancer behavior with errors inside a transaction', :redis, :delete do
+ include StubENV
let(:model) { ApplicationRecord }
let(:db_host) { model.connection_pool.db_config.host }
@@ -19,6 +20,10 @@ RSpec.describe 'Load balancer behavior with errors inside a transaction', :redis
model.connection.execute(<<~SQL)
CREATE TABLE IF NOT EXISTS #{test_table_name} (id SERIAL PRIMARY KEY, value INTEGER)
SQL
+
+ # The load balancer sleeps between attempts to retry a query.
+ # Mocking the sleep call significantly reduces the runtime of this spec file.
+ allow(model.connection.load_balancer).to receive(:sleep)
end
after do
@@ -46,36 +51,62 @@ RSpec.describe 'Load balancer behavior with errors inside a transaction', :redis
conn.execute("INSERT INTO #{test_table_name} (value) VALUES (2)")
end
- it 'logs a warning when violating transaction semantics with writes' do
- conn = model.connection
+ context 'with the PREVENT_LOAD_BALANCER_RETRIES_IN_TRANSACTION environment variable not set' do
+ it 'logs a warning when violating transaction semantics with writes' do
+ conn = model.connection
+
+ expect(::Gitlab::Database::LoadBalancing::Logger).to receive(:warn).with(hash_including(event: :transaction_leak))
+
+ conn.transaction do
+ expect(conn).to be_transaction_open
+
+ execute(conn)
- expect(::Gitlab::Database::LoadBalancing::Logger).to receive(:warn).with(hash_including(event: :transaction_leak))
+ expect(conn).not_to be_transaction_open
+ end
- conn.transaction do
- expect(conn).to be_transaction_open
+ values = conn.execute("SELECT value FROM #{test_table_name}").to_a.map { |row| row['value'] }
+ expect(values).to contain_exactly(2) # Does not include 1 because the transaction was aborted and leaked
+ end
+
+ it 'does not log a warning when no transaction is open to be leaked' do
+ conn = model.connection
+
+ expect(::Gitlab::Database::LoadBalancing::Logger)
+ .not_to receive(:warn).with(hash_including(event: :transaction_leak))
+
+ expect(conn).not_to be_transaction_open
execute(conn)
expect(conn).not_to be_transaction_open
- end
- values = conn.execute("SELECT value FROM #{test_table_name}").to_a.map { |row| row['value'] }
- expect(values).to contain_exactly(2) # Does not include 1 because the transaction was aborted and leaked
+ values = conn.execute("SELECT value FROM #{test_table_name}").to_a.map { |row| row['value'] }
+ expect(values).to contain_exactly(1, 2) # Includes both rows because there was no transaction to roll back
+ end
end
- it 'does not log a warning when no transaction is open to be leaked' do
- conn = model.connection
-
- expect(::Gitlab::Database::LoadBalancing::Logger)
- .not_to receive(:warn).with(hash_including(event: :transaction_leak))
+ context 'with the PREVENT_LOAD_BALANCER_RETRIES_IN_TRANSACTION environment variable set' do
+ before do
+ stub_env('PREVENT_LOAD_BALANCER_RETRIES_IN_TRANSACTION' => '1')
+ end
- expect(conn).not_to be_transaction_open
+ it 'raises an exception when a retry would occur during a transaction' do
+ expect(::Gitlab::Database::LoadBalancing::Logger)
+ .not_to receive(:warn).with(hash_including(event: :transaction_leak))
- execute(conn)
+ expect do
+ model.transaction do
+ execute(model.connection)
+ end
+ end.to raise_error(ActiveRecord::StatementInvalid) { |e| expect(e.cause).to be_a(PG::ConnectionBad) }
+ end
- expect(conn).not_to be_transaction_open
+ it 'retries when not in a transaction' do
+ expect(::Gitlab::Database::LoadBalancing::Logger)
+ .not_to receive(:warn).with(hash_including(event: :transaction_leak))
- values = conn.execute("SELECT value FROM #{test_table_name}").to_a.map { |row| row['value'] }
- expect(values).to contain_exactly(1, 2) # Includes both rows because there was no transaction to roll back
+ expect { execute(model.connection) }.not_to raise_error
+ end
end
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index d73b478ee7c..bcdd5646994 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -757,6 +757,58 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model.add_concurrent_foreign_key(:projects, :users, column: :user_id, reverse_lock_order: true)
end
end
+
+ context 'when creating foreign key for a group of columns' do
+ it 'references the custom target columns when provided', :aggregate_failures do
+ expect(model).to receive(:with_lock_retries).and_yield
+ expect(model).to receive(:execute).with(
+ "ALTER TABLE projects\n" \
+ "ADD CONSTRAINT fk_multiple_columns\n" \
+ "FOREIGN KEY \(partition_number, user_id\)\n" \
+ "REFERENCES users \(partition_number, id\)\n" \
+ "ON DELETE CASCADE\n" \
+ "NOT VALID;\n"
+ )
+
+ model.add_concurrent_foreign_key(
+ :projects,
+ :users,
+ column: [:partition_number, :user_id],
+ target_column: [:partition_number, :id],
+ validate: false,
+ name: :fk_multiple_columns
+ )
+ end
+
+ context 'when foreign key is already defined' do
+ before do
+ expect(model).to receive(:foreign_key_exists?).with(
+ :projects,
+ :users,
+ {
+ column: [:partition_number, :user_id],
+ name: :fk_multiple_columns,
+ on_delete: :cascade,
+ primary_key: [:partition_number, :id]
+ }
+ ).and_return(true)
+ end
+
+ it 'does not create foreign key', :aggregate_failures do
+ expect(model).not_to receive(:with_lock_retries).and_yield
+ expect(model).not_to receive(:execute).with(/FOREIGN KEY/)
+
+ model.add_concurrent_foreign_key(
+ :projects,
+ :users,
+ column: [:partition_number, :user_id],
+ target_column: [:partition_number, :id],
+ validate: false,
+ name: :fk_multiple_columns
+ )
+ end
+ end
+ end
end
end
@@ -813,6 +865,15 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(name).to be_an_instance_of(String)
expect(name.length).to eq(13)
end
+
+ context 'when using multiple columns' do
+ it 'returns the name of the foreign key', :aggregate_failures do
+ result = model.concurrent_foreign_key_name(:table_name, [:partition_number, :id])
+
+ expect(result).to be_an_instance_of(String)
+ expect(result.length).to eq(13)
+ end
+ end
end
describe '#foreign_key_exists?' do
@@ -887,6 +948,62 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
it 'compares by target table if no column given' do
expect(model.foreign_key_exists?(:projects, :other_table)).to be_falsey
end
+
+ context 'with foreign key using multiple columns' do
+ before do
+ key = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ :projects, :users,
+ {
+ column: [:partition_number, :id],
+ name: :fk_projects_users_partition_number_id,
+ on_delete: :cascade,
+ primary_key: [:partition_number, :id]
+ }
+ )
+ allow(model).to receive(:foreign_keys).with(:projects).and_return([key])
+ end
+
+ it 'finds existing foreign keys by columns' do
+ expect(model.foreign_key_exists?(:projects, :users, column: [:partition_number, :id])).to be_truthy
+ end
+
+ it 'finds existing foreign keys by name' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :fk_projects_users_partition_number_id)).to be_truthy
+ end
+
+ it 'finds existing foreign_keys by name and column' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :fk_projects_users_partition_number_id, column: [:partition_number, :id])).to be_truthy
+ end
+
+ it 'finds existing foreign_keys by name, column and on_delete' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :fk_projects_users_partition_number_id, column: [:partition_number, :id], on_delete: :cascade)).to be_truthy
+ end
+
+ it 'finds existing foreign keys by target table only' do
+ expect(model.foreign_key_exists?(:projects, :users)).to be_truthy
+ end
+
+ it 'compares by column name if given' do
+ expect(model.foreign_key_exists?(:projects, :users, column: :id)).to be_falsey
+ end
+
+ it 'compares by target column name if given' do
+ expect(model.foreign_key_exists?(:projects, :users, primary_key: :user_id)).to be_falsey
+ expect(model.foreign_key_exists?(:projects, :users, primary_key: [:partition_number, :id])).to be_truthy
+ end
+
+ it 'compares by foreign key name if given' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :non_existent_foreign_key_name)).to be_falsey
+ end
+
+ it 'compares by foreign key name and column if given' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :non_existent_foreign_key_name, column: [:partition_number, :id])).to be_falsey
+ end
+
+ it 'compares by foreign key name, column and on_delete if given' do
+ expect(model.foreign_key_exists?(:projects, :users, name: :fk_projects_users_partition_number_id, column: [:partition_number, :id], on_delete: :nullify)).to be_falsey
+ end
+ end
end
describe '#disable_statement_timeout' do
@@ -3359,6 +3476,73 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ describe '#drop_constraint' do
+ it "executes the statement to drop the constraint" do
+ expect(model).to receive(:execute).with("ALTER TABLE \"test_table\" DROP CONSTRAINT \"constraint_name\" CASCADE\n")
+
+ model.drop_constraint(:test_table, :constraint_name, cascade: true)
+ end
+
+ context 'when cascade option is false' do
+ it "executes the statement to drop the constraint without cascade" do
+ expect(model).to receive(:execute).with("ALTER TABLE \"test_table\" DROP CONSTRAINT \"constraint_name\" \n")
+
+ model.drop_constraint(:test_table, :constraint_name, cascade: false)
+ end
+ end
+ end
+
+ describe '#add_primary_key_using_index' do
+ it "executes the statement to add the primary key" do
+ expect(model).to receive(:execute).with /ALTER TABLE "test_table" ADD CONSTRAINT "old_name" PRIMARY KEY USING INDEX "new_name"/
+
+ model.add_primary_key_using_index(:test_table, :old_name, :new_name)
+ end
+ end
+
+ context 'when changing the primary key of a given table' do
+ before do
+ model.create_table(:test_table, primary_key: :id) do |t|
+ t.integer :partition_number, default: 1
+ end
+
+ model.add_index(:test_table, :id, unique: true, name: :old_index_name)
+ model.add_index(:test_table, [:id, :partition_number], unique: true, name: :new_index_name)
+ end
+
+ describe '#swap_primary_key' do
+ it 'executes statements to swap primary key', :aggregate_failures do
+ expect(model).to receive(:with_lock_retries).with(raise_on_exhaustion: true).ordered.and_yield
+ expect(model).to receive(:execute).with(/ALTER TABLE "test_table" DROP CONSTRAINT "test_table_pkey" CASCADE/).and_call_original
+ expect(model).to receive(:execute).with(/ALTER TABLE "test_table" ADD CONSTRAINT "test_table_pkey" PRIMARY KEY USING INDEX "new_index_name"/).and_call_original
+
+ model.swap_primary_key(:test_table, :test_table_pkey, :new_index_name)
+ end
+
+ context 'when new index does not exist' do
+ before do
+ model.remove_index(:test_table, column: [:id, :partition_number])
+ end
+
+ it 'raises ActiveRecord::StatementInvalid' do
+ expect do
+ model.swap_primary_key(:test_table, :test_table_pkey, :new_index_name)
+ end.to raise_error(ActiveRecord::StatementInvalid)
+ end
+ end
+ end
+
+ describe '#unswap_primary_key' do
+ it 'executes statements to unswap primary key' do
+ expect(model).to receive(:with_lock_retries).with(raise_on_exhaustion: true).ordered.and_yield
+ expect(model).to receive(:execute).with(/ALTER TABLE "test_table" DROP CONSTRAINT "test_table_pkey" CASCADE/).ordered.and_call_original
+ expect(model).to receive(:execute).with(/ALTER TABLE "test_table" ADD CONSTRAINT "test_table_pkey" PRIMARY KEY USING INDEX "old_index_name"/).ordered.and_call_original
+
+ model.unswap_primary_key(:test_table, :test_table_pkey, :old_index_name)
+ end
+ end
+ end
+
describe '#drop_sequence' do
it "executes the statement to drop the sequence" do
expect(model).to receive(:execute).with /ALTER TABLE "test_table" ALTER COLUMN "test_column" DROP DEFAULT;\nDROP SEQUENCE IF EXISTS "test_table_id_seq"/
diff --git a/spec/lib/gitlab/database/migrations/base_background_runner_spec.rb b/spec/lib/gitlab/database/migrations/base_background_runner_spec.rb
index 34c83c42056..c2dc260b2ff 100644
--- a/spec/lib/gitlab/database/migrations/base_background_runner_spec.rb
+++ b/spec/lib/gitlab/database/migrations/base_background_runner_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::BaseBackgroundRunner, :freeze_time do
+ let(:connection) { ApplicationRecord.connection }
+
let(:result_dir) { Dir.mktmpdir }
after do
@@ -10,7 +12,7 @@ RSpec.describe Gitlab::Database::Migrations::BaseBackgroundRunner, :freeze_time
end
context 'subclassing' do
- subject { described_class.new(result_dir: result_dir) }
+ subject { described_class.new(result_dir: result_dir, connection: connection) }
it 'requires that jobs_by_migration_name be implemented' do
expect { subject.jobs_by_migration_name }.to raise_error(NotImplementedError)
diff --git a/spec/lib/gitlab/database/migrations/runner_spec.rb b/spec/lib/gitlab/database/migrations/runner_spec.rb
index a37247ba0c6..f364ebfa522 100644
--- a/spec/lib/gitlab/database/migrations/runner_spec.rb
+++ b/spec/lib/gitlab/database/migrations/runner_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Gitlab::Database::Migrations::Runner do
+RSpec.describe Gitlab::Database::Migrations::Runner, :reestablished_active_record_base do
include Database::MultipleDatabases
- let(:result_dir) { Pathname.new(Dir.mktmpdir) }
+ let(:base_result_dir) { Pathname.new(Dir.mktmpdir) }
let(:migration_runs) { [] } # This list gets populated as the runner tries to run migrations
@@ -26,11 +26,14 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
end
before do
- stub_const('Gitlab::Database::Migrations::Runner::BASE_RESULT_DIR', result_dir)
+ skip_if_multiple_databases_not_setup unless database == :main
+
+ stub_const('Gitlab::Database::Migrations::Runner::BASE_RESULT_DIR', base_result_dir)
allow(ActiveRecord::Migrator).to receive(:new) do |dir, _all_migrations, _schema_migration_class, version_to_migrate|
migrator = double(ActiveRecord::Migrator)
expect(migrator).to receive(:run) do
- migration_runs << double('migrator', dir: dir, version_to_migrate: version_to_migrate)
+ config_for_migration_run = ActiveRecord::Base.connection_db_config
+ migration_runs << double('migrator', dir: dir, version_to_migrate: version_to_migrate, database: config_for_migration_run.name)
end
migrator
end
@@ -39,133 +42,153 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
migrations = applied_migrations_other_branches + applied_migrations_this_branch + pending_migrations
ctx = double(ActiveRecord::MigrationContext, get_all_versions: all_versions, migrations: migrations, schema_migration: ActiveRecord::SchemaMigration)
- allow(described_class).to receive(:migration_context).and_return(ctx)
+ allow(ActiveRecord::Base.connection).to receive(:migration_context).and_return(ctx)
names_this_branch = (applied_migrations_this_branch + pending_migrations).map { |m| "db/migrate/#{m.version}_#{m.name}.rb" }
allow(described_class).to receive(:migration_file_names_this_branch).and_return(names_this_branch)
end
after do
- FileUtils.rm_rf(result_dir)
+ FileUtils.rm_rf(base_result_dir)
end
- it 'creates the results dir when one does not exist' do
- FileUtils.rm_rf(result_dir)
-
- expect do
- described_class.new(direction: :up, migrations: [], result_dir: result_dir).run
- end.to change { Dir.exist?(result_dir) }.from(false).to(true)
+ where(:case_name, :database, :result_dir, :legacy_mode, :expected_schema_version) do
+ [
+ ['main database', :main, lazy { base_result_dir.join('main') }, false, described_class::SCHEMA_VERSION],
+ ['main database (legacy mode)', :main, lazy { base_result_dir }, true, 3],
+ ['ci database', :ci, lazy { base_result_dir.join('ci') }, false, described_class::SCHEMA_VERSION]
+ ]
end
- describe '.up' do
- context 'result directory' do
- it 'uses the /up subdirectory' do
- expect(described_class.up.result_dir).to eq(result_dir.join('up'))
- end
+ with_them do
+ it 'creates the results dir when one does not exist' do
+ FileUtils.rm_rf(result_dir)
+
+ expect do
+ described_class.new(direction: :up, migrations: [], database: database).run
+ end.to change { Dir.exist?(result_dir) }.from(false).to(true)
end
- context 'migrations to run' do
- subject(:up) { described_class.up }
+ describe '.up' do
+ context 'result directory' do
+ it 'uses the /up subdirectory' do
+ expect(described_class.up(database: database, legacy_mode: legacy_mode).result_dir).to eq(result_dir.join('up'))
+ end
+ end
+
+ context 'migrations to run' do
+ subject(:up) { described_class.up(database: database, legacy_mode: legacy_mode) }
- it 'is the list of pending migrations' do
- expect(up.migrations).to eq(pending_migrations)
+ it 'is the list of pending migrations' do
+ expect(up.migrations).to eq(pending_migrations)
+ end
end
- end
- context 'running migrations' do
- subject(:up) { described_class.up }
+ context 'running migrations' do
+ subject(:up) { described_class.up(database: database, legacy_mode: legacy_mode) }
- it 'runs the unapplied migrations in version order', :aggregate_failures do
- up.run
+ it 'runs the unapplied migrations in version order', :aggregate_failures do
+ up.run
- expect(migration_runs.map(&:dir)).to match_array([:up, :up])
- expect(migration_runs.map(&:version_to_migrate)).to eq(pending_migrations.map(&:version))
- end
+ expect(migration_runs.map(&:dir)).to match_array([:up, :up])
+ expect(migration_runs.map(&:version_to_migrate)).to eq(pending_migrations.map(&:version))
+ end
- it 'writes a metadata file with the current schema version' do
- up.run
+ it 'writes a metadata file with the current schema version and database name' do
+ up.run
- metadata_file = result_dir.join('up', described_class::METADATA_FILENAME)
- expect(metadata_file.exist?).to be_truthy
- metadata = Gitlab::Json.parse(File.read(metadata_file))
- expect(metadata).to match('version' => described_class::SCHEMA_VERSION)
+ metadata_file = result_dir.join('up', described_class::METADATA_FILENAME)
+ expect(metadata_file.exist?).to be_truthy
+ metadata = Gitlab::Json.parse(File.read(metadata_file))
+ expect(metadata).to match('version' => expected_schema_version, 'database' => database.to_s)
+ end
+
+ it 'runs the unapplied migrations on the correct database' do
+ up.run
+
+ expect(migration_runs.map(&:database).uniq).to contain_exactly(database.to_s)
+ end
end
end
- end
- describe '.down' do
- subject(:down) { described_class.down }
+ describe '.down' do
+ subject(:down) { described_class.down(database: database, legacy_mode: legacy_mode) }
- context 'result directory' do
- it 'is the /down subdirectory' do
- expect(down.result_dir).to eq(result_dir.join('down'))
+ context 'result directory' do
+ it 'is the /down subdirectory' do
+ expect(down.result_dir).to eq(result_dir.join('down'))
+ end
end
- end
- context 'migrations to run' do
- it 'is the list of migrations that are up and on this branch' do
- expect(down.migrations).to eq(applied_migrations_this_branch)
+ context 'migrations to run' do
+ it 'is the list of migrations that are up and on this branch' do
+ expect(down.migrations).to eq(applied_migrations_this_branch)
+ end
end
- end
- context 'running migrations' do
- it 'runs the applied migrations for the current branch in reverse order', :aggregate_failures do
- down.run
+ context 'running migrations' do
+ it 'runs the applied migrations for the current branch in reverse order', :aggregate_failures do
+ down.run
- 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))
+ 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
- end
-
- it 'writes a metadata file with the current schema version' do
- down.run
- metadata_file = result_dir.join('down', described_class::METADATA_FILENAME)
- expect(metadata_file.exist?).to be_truthy
- metadata = Gitlab::Json.parse(File.read(metadata_file))
- expect(metadata).to match('version' => described_class::SCHEMA_VERSION)
- end
- end
+ it 'writes a metadata file with the current schema version' do
+ down.run
- describe '.background_migrations' do
- it 'is a TestBackgroundRunner' do
- expect(described_class.background_migrations).to be_a(Gitlab::Database::Migrations::TestBackgroundRunner)
+ metadata_file = result_dir.join('down', described_class::METADATA_FILENAME)
+ expect(metadata_file.exist?).to be_truthy
+ metadata = Gitlab::Json.parse(File.read(metadata_file))
+ expect(metadata).to match('version' => expected_schema_version, 'database' => database.to_s)
+ end
end
- it 'is configured with a result dir of /background_migrations' do
- runner = described_class.background_migrations
+ describe '.background_migrations' do
+ it 'is a TestBackgroundRunner' do
+ expect(described_class.background_migrations).to be_a(Gitlab::Database::Migrations::TestBackgroundRunner)
+ end
- expect(runner.result_dir).to eq(described_class::BASE_RESULT_DIR.join( 'background_migrations'))
- end
- end
+ it 'is configured with a result dir of /background_migrations' do
+ runner = described_class.background_migrations
- describe '.batched_background_migrations' do
- it 'is a TestBatchedBackgroundRunner' do
- expect(described_class.batched_background_migrations(for_database: 'main')).to be_a(Gitlab::Database::Migrations::TestBatchedBackgroundRunner)
+ expect(runner.result_dir).to eq(described_class::BASE_RESULT_DIR.join( 'background_migrations'))
+ end
end
- context 'choosing the database to test against' do
- it 'chooses the main database' do
- runner = described_class.batched_background_migrations(for_database: 'main')
+ describe '.batched_background_migrations' do
+ it 'is a TestBatchedBackgroundRunner' do
+ expect(described_class.batched_background_migrations(for_database: database)).to be_a(Gitlab::Database::Migrations::TestBatchedBackgroundRunner)
+ end
- chosen_connection_name = Gitlab::Database.db_config_name(runner.connection)
+ context 'choosing the database to test against' do
+ it 'chooses the provided database' do
+ runner = described_class.batched_background_migrations(for_database: database)
- expect(chosen_connection_name).to eq('main')
- end
+ chosen_connection_name = Gitlab::Database.db_config_name(runner.connection)
- it 'chooses the ci database' do
- skip_if_multiple_databases_not_setup
+ expect(chosen_connection_name).to eq(database.to_s)
+ end
- runner = described_class.batched_background_migrations(for_database: 'ci')
+ it 'throws an error with an invalid name' do
+ expect { described_class.batched_background_migrations(for_database: 'not_a_database') }
+ .to raise_error(/not a valid database name/)
+ end
- chosen_connection_name = Gitlab::Database.db_config_name(runner.connection)
+ it 'includes the database name in the result dir' do
+ runner = described_class.batched_background_migrations(for_database: database)
- expect(chosen_connection_name).to eq('ci')
+ expect(runner.result_dir).to eq(base_result_dir.join(database.to_s, 'background_migrations'))
+ end
end
- it 'throws an error with an invalid name' do
- expect { described_class.batched_background_migrations(for_database: 'not_a_database') }
- .to raise_error(/not a valid database name/)
+ context 'legacy mode' do
+ it 'does not include the database name in the path' do
+ runner = described_class.batched_background_migrations(for_database: database, legacy_mode: true)
+
+ expect(runner.result_dir).to eq(base_result_dir.join('background_migrations'))
+ end
end
end
end
diff --git a/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb b/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb
index 3ac483c8ab7..07226f3d025 100644
--- a/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb
+++ b/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb
@@ -6,106 +6,156 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez
include Gitlab::Database::MigrationHelpers
include Database::MigrationTestingHelpers
- let(:result_dir) { Dir.mktmpdir }
-
- after do
- FileUtils.rm_rf(result_dir)
+ def queue_migration(
+ job_class_name,
+ batch_table_name,
+ batch_column_name,
+ *job_arguments,
+ job_interval:,
+ batch_size: Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers::BATCH_SIZE,
+ sub_batch_size: Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers::SUB_BATCH_SIZE
+ )
+
+ batch_max_value = define_batchable_model(batch_table_name, connection: connection).maximum(batch_column_name)
+
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ 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: Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers::BATCH_MIN_VALUE,
+ max_value: batch_max_value,
+ batch_class_name: Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers::BATCH_CLASS_NAME,
+ batch_size: batch_size,
+ sub_batch_size: sub_batch_size,
+ status_event: :execute,
+ max_batch_size: nil,
+ gitlab_schema: gitlab_schema
+ )
+ end
end
- let(:migration) do
- ActiveRecord::Migration.new.extend(Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers)
+ where(:case_name, :base_model, :gitlab_schema) do
+ [
+ ['main database', ApplicationRecord, :gitlab_main],
+ ['ci database', Ci::ApplicationRecord, :gitlab_ci]
+ ]
end
- let(:connection) { ApplicationRecord.connection }
+ with_them do
+ let(:result_dir) { Dir.mktmpdir }
- let(:table_name) { "_test_column_copying" }
+ after do
+ FileUtils.rm_rf(result_dir)
+ end
- before do
- connection.execute(<<~SQL)
- CREATE TABLE #{table_name} (
- id bigint primary key not null,
- data bigint default 0
- );
+ let(:connection) { base_model.connection }
- insert into #{table_name} (id) select i from generate_series(1, 1000) g(i);
- SQL
+ let(:table_name) { "_test_column_copying" }
- allow(migration).to receive(:transaction_open?).and_return(false)
- end
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id bigint primary key not null,
+ data bigint default 0
+ );
- context 'running a real background migration' do
- it 'runs sampled jobs from the batched background migration' do
- migration.queue_batched_background_migration('CopyColumnUsingBackgroundMigrationJob',
- table_name, :id,
- :id, :data,
- batch_size: 100,
- job_interval: 5.minutes) # job_interval is skipped when testing
-
- # Expect that running sampling for this migration processes some of the rows. Sampling doesn't run
- # over every row in the table, so this does not completely migrate the table.
- expect { described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 1.minute) }
- .to change { define_batchable_model(table_name).where('id IS DISTINCT FROM data').count }
- .by_at_most(-1)
+ insert into #{table_name} (id) select i from generate_series(1, 1000) g(i);
+ SQL
end
- end
- context 'with jobs to run' do
- let(:migration_name) { 'TestBackgroundMigration' }
+ context 'running a real background migration' do
+ before do
+ queue_migration('CopyColumnUsingBackgroundMigrationJob',
+ table_name, :id,
+ :id, :data,
+ batch_size: 100,
+ job_interval: 5.minutes) # job_interval is skipped when testing
+ end
- it 'samples jobs' do
- calls = []
- define_background_migration(migration_name) do |*args|
- calls << args
+ subject(:sample_migration) do
+ described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 1.minute)
end
- migration.queue_batched_background_migration(migration_name, table_name, :id,
- job_interval: 5.minutes,
- batch_size: 100)
+ it 'runs sampled jobs from the batched background migration' do
+ # Expect that running sampling for this migration processes some of the rows. Sampling doesn't run
+ # over every row in the table, so this does not completely migrate the table.
+ expect { subject }.to change {
+ define_batchable_model(table_name, connection: connection)
+ .where('id IS DISTINCT FROM data').count
+ }.by_at_most(-1)
+ end
- described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 3.minutes)
+ it 'uses the correct connection to instrument the background migration' do
+ expect_next_instance_of(Gitlab::Database::Migrations::Instrumentation) do |instrumentation|
+ expect(instrumentation).to receive(:observe).with(hash_including(connection: connection))
+ .at_least(:once).and_call_original
+ end
- expect(calls).not_to be_empty
+ subject
+ end
end
- context 'with multiple jobs to run' do
- it 'runs all jobs created within the last 3 hours' do
- old_migration = define_background_migration(migration_name)
- migration.queue_batched_background_migration(migration_name, table_name, :id,
- job_interval: 5.minutes,
- batch_size: 100)
-
- travel 4.hours
-
- new_migration = define_background_migration('NewMigration') { travel 1.second }
- migration.queue_batched_background_migration('NewMigration', table_name, :id,
- job_interval: 5.minutes,
- batch_size: 10,
- sub_batch_size: 5)
-
- other_new_migration = define_background_migration('NewMigration2') { travel 2.seconds }
- migration.queue_batched_background_migration('NewMigration2', table_name, :id,
- job_interval: 5.minutes,
- batch_size: 10,
- sub_batch_size: 5)
-
- expect_migration_runs(new_migration => 3, other_new_migration => 2, old_migration => 0) do
- described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 5.seconds)
+ context 'with jobs to run' do
+ let(:migration_name) { 'TestBackgroundMigration' }
+
+ it 'samples jobs' do
+ calls = []
+ define_background_migration(migration_name) do |*args|
+ calls << args
+ end
+
+ queue_migration(migration_name, table_name, :id,
+ job_interval: 5.minutes,
+ batch_size: 100)
+
+ described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 3.minutes)
+
+ expect(calls).not_to be_empty
+ end
+
+ context 'with multiple jobs to run' do
+ it 'runs all jobs created within the last 3 hours' do
+ old_migration = define_background_migration(migration_name)
+ queue_migration(migration_name, table_name, :id,
+ job_interval: 5.minutes,
+ batch_size: 100)
+
+ travel 4.hours
+
+ new_migration = define_background_migration('NewMigration') { travel 1.second }
+ queue_migration('NewMigration', table_name, :id,
+ job_interval: 5.minutes,
+ batch_size: 10,
+ sub_batch_size: 5)
+
+ other_new_migration = define_background_migration('NewMigration2') { travel 2.seconds }
+ queue_migration('NewMigration2', table_name, :id,
+ job_interval: 5.minutes,
+ batch_size: 10,
+ sub_batch_size: 5)
+
+ expect_migration_runs(new_migration => 3, other_new_migration => 2, old_migration => 0) do
+ described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 5.seconds)
+ end
end
end
end
- end
- context 'choosing uniform batches to run' do
- subject { described_class.new(result_dir: result_dir, connection: connection) }
+ context 'choosing uniform batches to run' do
+ subject { described_class.new(result_dir: result_dir, connection: connection) }
- describe '#uniform_fractions' do
- it 'generates evenly distributed sequences of fractions' do
- received = subject.uniform_fractions.take(9)
- expected = [0, 1, 1.0 / 2, 1.0 / 4, 3.0 / 4, 1.0 / 8, 3.0 / 8, 5.0 / 8, 7.0 / 8]
+ describe '#uniform_fractions' do
+ it 'generates evenly distributed sequences of fractions' do
+ received = subject.uniform_fractions.take(9)
+ expected = [0, 1, 1.0 / 2, 1.0 / 4, 3.0 / 4, 1.0 / 8, 3.0 / 8, 5.0 / 8, 7.0 / 8]
- # All the fraction numerators are small integers, and all denominators are powers of 2, so these
- # fit perfectly into floating point numbers with zero loss of precision
- expect(received).to eq(expected)
+ # All the fraction numerators are small integers, and all denominators are powers of 2, so these
+ # fit perfectly into floating point numbers with zero loss of precision
+ expect(received).to eq(expected)
+ end
end
end
end
diff --git a/spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb b/spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb
index 8a35d8149ad..b39b273bba9 100644
--- a/spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb
+++ b/spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb
@@ -53,15 +53,16 @@ RSpec.describe Gitlab::Database::ObsoleteIgnoredColumns do
describe '#execute' do
it 'returns a list of class names and columns pairs' do
travel_to(REMOVE_DATE) do
- expect(subject.execute).to eq([
- ['Testing::A', {
- 'unused' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-01-01'), '12.0'),
- 'also_unused' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-02-01'), '12.1')
- }],
- ['Testing::B', {
- 'other' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-01-01'), '12.0')
- }]
- ])
+ expect(subject.execute).to eq(
+ [
+ ['Testing::A', {
+ 'unused' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-01-01'), '12.0'),
+ 'also_unused' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-02-01'), '12.1')
+ }],
+ ['Testing::B', {
+ 'other' => IgnorableColumns::ColumnIgnore.new(Date.parse('2019-01-01'), '12.0')
+ }]
+ ])
end
end
end
diff --git a/spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb b/spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb
index af7d751a404..0e804b4feac 100644
--- a/spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb
@@ -153,6 +153,21 @@ RSpec.describe Gitlab::Database::Partitioning::ConvertTableToFirstListPartition
expect(parent_model.pluck(:id)).to match_array([1, 2, 3])
end
+ context 'when the existing table is owned by a different user' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE USER other_user SUPERUSER;
+ ALTER TABLE #{table_name} OWNER TO other_user;
+ SQL
+ end
+
+ let(:current_user) { model.connection.select_value('select current_user') }
+
+ it 'partitions without error' do
+ expect { partition }.not_to raise_error
+ end
+ end
+
context 'when an error occurs during the conversion' do
def fail_first_time
# We can't directly use a boolean here, as we need something that will be passed by-reference to the proc
diff --git a/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
index 67d80d71e2a..50115a6f3dd 100644
--- a/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
@@ -29,10 +29,11 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
end
it 'detects both partitions' do
- expect(subject).to eq([
- Gitlab::Database::Partitioning::TimePartition.new(table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000'),
- Gitlab::Database::Partitioning::TimePartition.new(table_name, '2020-05-01', '2020-06-01', partition_name: '_test_partitioned_test_202005')
- ])
+ expect(subject).to eq(
+ [
+ Gitlab::Database::Partitioning::TimePartition.new(table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000'),
+ Gitlab::Database::Partitioning::TimePartition.new(table_name, '2020-05-01', '2020-06-01', partition_name: '_test_partitioned_test_202005')
+ ])
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
index 07c2c6606d8..550f254c4da 100644
--- a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
@@ -36,14 +36,15 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
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'
- )
- ])
+ 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
diff --git a/spec/lib/gitlab/database/partitioning/time_partition_spec.rb b/spec/lib/gitlab/database/partitioning/time_partition_spec.rb
index 700202d81c5..5a17e8d20cf 100644
--- a/spec/lib/gitlab/database/partitioning/time_partition_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/time_partition_spec.rb
@@ -156,12 +156,13 @@ RSpec.describe Gitlab::Database::Partitioning::TimePartition do
described_class.new(table, '2020-03-01', '2020-04-01')
]
- expect(partitions.sort).to eq([
- described_class.new(table, nil, '2020-02-01'),
- described_class.new(table, '2020-02-01', '2020-03-01'),
- described_class.new(table, '2020-03-01', '2020-04-01'),
- described_class.new(table, '2020-04-01', '2020-05-01')
- ])
+ expect(partitions.sort).to eq(
+ [
+ described_class.new(table, nil, '2020-02-01'),
+ described_class.new(table, '2020-02-01', '2020-03-01'),
+ described_class.new(table, '2020-03-01', '2020-04-01'),
+ described_class.new(table, '2020-04-01', '2020-05-01')
+ ])
end
it 'returns nil for partitions of different tables' do
diff --git a/spec/lib/gitlab/database/partitioning_spec.rb b/spec/lib/gitlab/database/partitioning_spec.rb
index 94cdbfb2328..db5ca890155 100644
--- a/spec/lib/gitlab/database/partitioning_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_spec.rb
@@ -130,12 +130,14 @@ RSpec.describe Gitlab::Database::Partitioning do
context 'when no partitioned models are given' do
it 'manages partitions for each registered model' do
described_class.register_models([models.first])
- described_class.register_tables([
- {
- table_name: table_names.last,
- partitioned_column: :created_at, strategy: :monthly
- }
- ])
+ described_class.register_tables(
+ [
+ {
+ table_name: table_names.last,
+ partitioned_column: :created_at,
+ strategy: :monthly
+ }
+ ])
expect { described_class.sync_partitions }
.to change { find_partitions(table_names.first).size }.from(0)
diff --git a/spec/lib/gitlab/database/reflection_spec.rb b/spec/lib/gitlab/database/reflection_spec.rb
index efc5bd1c1e1..389e93364c8 100644
--- a/spec/lib/gitlab/database/reflection_spec.rb
+++ b/spec/lib/gitlab/database/reflection_spec.rb
@@ -314,6 +314,12 @@ RSpec.describe Gitlab::Database::Reflection do
expect(database.flavor).to eq('Azure Database for PostgreSQL - Single Server')
end
+ it 'recognizes AlloyDB for PostgreSQL' do
+ stub_statements("SELECT name FROM pg_settings WHERE name LIKE 'alloydb%'")
+
+ expect(database.flavor).to eq('AlloyDB for PostgreSQL')
+ end
+
it 'returns nil if can not recognize the flavor' do
expect(database.flavor).to be_nil
end
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
index e222a29c6a1..ac2de43b7c6 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
@@ -98,7 +98,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespa
it 'moves a project for a namespace' do
create(:project, :repository, :legacy_storage, namespace: namespace, path: 'hello-project')
- expected_path = File.join(TestEnv.repos_path, 'bye-group', 'hello-project.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'bye-group', 'hello-project.git')
+ end
subject.move_repositories(namespace, 'hello-group', 'bye-group')
@@ -109,7 +111,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespa
child_namespace = create(:group, name: 'sub-group', parent: namespace)
create(:project, :repository, :legacy_storage, namespace: child_namespace, path: 'hello-project')
- expected_path = File.join(TestEnv.repos_path, 'hello-group', 'renamed-sub-group', 'hello-project.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'hello-group', 'renamed-sub-group', 'hello-project.git')
+ end
subject.move_repositories(child_namespace, 'hello-group/sub-group', 'hello-group/renamed-sub-group')
@@ -119,7 +123,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespa
it 'moves a parent namespace with subdirectories' do
child_namespace = create(:group, name: 'sub-group', parent: namespace)
create(:project, :repository, :legacy_storage, namespace: child_namespace, path: 'hello-project')
- expected_path = File.join(TestEnv.repos_path, 'renamed-group', 'sub-group', 'hello-project.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'renamed-group', 'sub-group', 'hello-project.git')
+ end
subject.move_repositories(child_namespace, 'hello-group', 'renamed-group')
@@ -170,7 +176,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespa
describe '#rename_namespace_dependencies' do
it "moves the repository for a project in the namespace" do
create(:project, :repository, :legacy_storage, namespace: namespace, path: "the-path-project")
- expected_repo = File.join(TestEnv.repos_path, "the-path0", "the-path-project.git")
+ expected_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, "the-path0", "the-path-project.git")
+ end
subject.rename_namespace_dependencies(namespace, 'the-path', 'the-path0')
@@ -268,7 +276,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespa
project.create_repository
subject.rename_namespace(namespace)
- expected_path = File.join(TestEnv.repos_path, 'the-path', 'a-project.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'the-path', 'a-project.git')
+ end
expect(subject).to receive(:rename_namespace_dependencies)
.with(
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb
index 50071e3e22b..6292f0246f7 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb
@@ -126,7 +126,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProject
let(:project) { create(:project, :repository, :legacy_storage, path: 'the-path', namespace: known_parent) }
it 'moves the repository for a project' do
- expected_path = File.join(TestEnv.repos_path, 'known-parent', 'new-repo.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'known-parent', 'new-repo.git')
+ end
subject.move_repository(project, 'known-parent/the-path', 'known-parent/new-repo')
@@ -155,7 +157,9 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProject
project.create_repository
subject.rename_project(project)
- expected_path = File.join(TestEnv.repos_path, 'known-parent', 'the-path.git')
+ expected_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, 'known-parent', 'the-path.git')
+ end
expect(subject).to receive(:move_project_folders)
.with(
diff --git a/spec/lib/gitlab/database/similarity_score_spec.rb b/spec/lib/gitlab/database/similarity_score_spec.rb
index b7b66494390..cfee70ed208 100644
--- a/spec/lib/gitlab/database/similarity_score_spec.rb
+++ b/spec/lib/gitlab/database/similarity_score_spec.rb
@@ -78,10 +78,11 @@ RSpec.describe Gitlab::Database::SimilarityScore do
describe 'score multiplier' do
let(:order_expression) do
- Gitlab::Database::SimilarityScore.build_expression(search: search, rules: [
- { column: Arel.sql('path'), multiplier: 1 },
- { column: Arel.sql('name'), multiplier: 0.8 }
- ]).to_sql
+ Gitlab::Database::SimilarityScore.build_expression(search: search, rules:
+ [
+ { column: Arel.sql('path'), multiplier: 1 },
+ { column: Arel.sql('name'), multiplier: 0.8 }
+ ]).to_sql
end
let(:search) { 'different' }
@@ -93,10 +94,11 @@ RSpec.describe Gitlab::Database::SimilarityScore do
describe 'annotation' do
it 'annotates the generated SQL expression' do
- expression = Gitlab::Database::SimilarityScore.build_expression(search: 'test', rules: [
- { column: Arel.sql('path'), multiplier: 1 },
- { column: Arel.sql('name'), multiplier: 0.8 }
- ])
+ expression = Gitlab::Database::SimilarityScore.build_expression(search: 'test', rules:
+ [
+ { column: Arel.sql('path'), multiplier: 1 },
+ { column: Arel.sql('name'), multiplier: 0.8 }
+ ])
expect(Gitlab::Database::SimilarityScore).to be_order_by_similarity(expression)
end
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index c893bca9e62..eb42734d044 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -32,21 +32,6 @@ RSpec.describe Gitlab::Database do
end
describe '.has_config?' do
- context 'two tier database config' do
- before do
- allow(Gitlab::Application).to receive_message_chain(:config, :database_configuration, :[]).with(Rails.env)
- .and_return({ "adapter" => "postgresql", "database" => "gitlabhq_test" })
- end
-
- it 'returns false for primary' do
- expect(described_class.has_config?(:primary)).to eq(false)
- end
-
- it 'returns false for ci' do
- expect(described_class.has_config?(:ci)).to eq(false)
- end
- end
-
context 'three tier database config' do
before do
allow(Gitlab::Application).to receive_message_chain(:config, :database_configuration, :[]).with(Rails.env)
diff --git a/spec/lib/gitlab/diff/char_diff_spec.rb b/spec/lib/gitlab/diff/char_diff_spec.rb
index d38008c16f2..ca0ed6e840d 100644
--- a/spec/lib/gitlab/diff/char_diff_spec.rb
+++ b/spec/lib/gitlab/diff/char_diff_spec.rb
@@ -20,22 +20,24 @@ RSpec.describe Gitlab::Diff::CharDiff do
it 'treats nil values as blank strings' do
changes = subject.generate_diff
- expect(changes).to eq([
- [:insert, "Hello \n World"]
- ])
+ expect(changes).to eq(
+ [
+ [:insert, "Hello \n World"]
+ ])
end
end
it 'generates an array of changes' do
changes = subject.generate_diff
- expect(changes).to eq([
- [:equal, "Hel"],
- [:insert, "l"],
- [:equal, "o \n Worl"],
- [:delete, "l"],
- [:equal, "d"]
- ])
+ expect(changes).to eq(
+ [
+ [:equal, "Hel"],
+ [:insert, "l"],
+ [:equal, "o \n Worl"],
+ [:delete, "l"],
+ [:equal, "d"]
+ ])
end
end
diff --git a/spec/lib/gitlab/diff/file_collection_sorter_spec.rb b/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
index ca9c156c1ad..3f0b0ad5775 100644
--- a/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
@@ -33,27 +33,28 @@ RSpec.describe Gitlab::Diff::FileCollectionSorter do
let(:sorted_files_paths) { subject.sort.map { |file| file.new_path.presence || file.old_path } }
it 'returns list sorted directory first' do
- expect(sorted_files_paths).to eq([
- '.dir/test',
- '1-folder/nested/A-file.ext',
- '1-folder/nested/M-file.ext',
- '1-folder/nested/Z-file.ext',
- '1-folder/A-file.ext',
- '1-folder/M-file.ext',
- '1-folder/README',
- '1-folder/README',
- '1-folder/Z-file.ext',
- '2-folder/nested/A-file.ext',
- '2-folder/A-file.ext',
- '2-folder/M-file.ext',
- '2-folder/Z-file.ext',
- '.file',
- 'A-file.ext',
- 'M-file.ext',
- 'README',
- 'README',
- 'Z-file.ext'
- ])
+ expect(sorted_files_paths).to eq(
+ [
+ '.dir/test',
+ '1-folder/nested/A-file.ext',
+ '1-folder/nested/M-file.ext',
+ '1-folder/nested/Z-file.ext',
+ '1-folder/A-file.ext',
+ '1-folder/M-file.ext',
+ '1-folder/README',
+ '1-folder/README',
+ '1-folder/Z-file.ext',
+ '2-folder/nested/A-file.ext',
+ '2-folder/A-file.ext',
+ '2-folder/M-file.ext',
+ '2-folder/Z-file.ext',
+ '.file',
+ 'A-file.ext',
+ 'M-file.ext',
+ 'README',
+ 'README',
+ 'Z-file.ext'
+ ])
end
end
end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 28557aab830..d623a390dc8 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -309,12 +309,13 @@ RSpec.describe Gitlab::Diff::File do
let(:diffs) { commit.diffs }
before do
- info_dir_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- File.join(project.repository.path_to_repo, 'info')
- end
-
- FileUtils.mkdir(info_dir_path) unless File.exist?(info_dir_path)
- File.write(File.join(info_dir_path, 'attributes'), "*.md -diff\n")
+ project.repository.commit_files(
+ project.creator,
+ branch_name: 'master',
+ message: 'Add attributes',
+ actions: [{ action: :update, file_path: '.gitattributes', content: "*.md -diff\n" }]
+ )
+ project.repository.copy_gitattributes('master')
end
it "returns true for files that do not have attributes" do
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index 53e74748234..33e9360ee01 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -109,58 +109,36 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
end
shared_examples 'caches missing entries' do
- where(:expiration_period, :renewable_expiration_ff, :short_renewable_expiration_ff) do
- [
- [1.day, false, true],
- [1.day, false, false],
- [1.hour, true, true],
- [8.hours, true, false]
- ]
- end
-
- with_them do
- before do
- stub_feature_flags(
- highlight_diffs_renewable_expiration: renewable_expiration_ff,
- highlight_diffs_short_renewable_expiration: short_renewable_expiration_ff
- )
- end
+ it 'filters the key/value list of entries to be caches for each invocation' do
+ expect(cache).to receive(:write_to_redis_hash)
+ .with(hash_including(*paths))
+ .once
+ .and_call_original
- it 'filters the key/value list of entries to be caches for each invocation' do
- expect(cache).to receive(:write_to_redis_hash)
- .with(hash_including(*paths))
- .once
- .and_call_original
-
- 2.times { cache.write_if_empty }
- end
+ 2.times { cache.write_if_empty }
+ end
- it 'reads from cache once' do
- expect(cache).to receive(:read_cache).once.and_call_original
+ it 'reads from cache once' do
+ expect(cache).to receive(:read_cache).once.and_call_original
- cache.write_if_empty
- end
+ cache.write_if_empty
+ end
- it 'refreshes TTL of the key on read' do
- cache.write_if_empty
+ it 'refreshes TTL of the key on read' do
+ cache.write_if_empty
- time_until_expire = 30.minutes
+ time_until_expire = 30.minutes
- Gitlab::Redis::Cache.with do |redis|
- # Emulate that a key is going to expire soon
- redis.expire(cache.key, time_until_expire)
+ Gitlab::Redis::Cache.with do |redis|
+ # Emulate that a key is going to expire soon
+ redis.expire(cache.key, time_until_expire)
- expect(redis.ttl(cache.key)).to be <= time_until_expire
+ expect(redis.ttl(cache.key)).to be <= time_until_expire
- cache.send(:read_cache)
+ cache.send(:read_cache)
- if renewable_expiration_ff
- expect(redis.ttl(cache.key)).to be > time_until_expire
- expect(redis.ttl(cache.key)).to be_within(1.minute).of(expiration_period)
- else
- expect(redis.ttl(cache.key)).to be <= time_until_expire
- end
- end
+ expect(redis.ttl(cache.key)).to be > time_until_expire
+ expect(redis.ttl(cache.key)).to be_within(1.minute).of(described_class::EXPIRATION)
end
end
end
diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb
index 690396d4dbc..c62e3071fc1 100644
--- a/spec/lib/gitlab/encoding_helper_spec.rb
+++ b/spec/lib/gitlab/encoding_helper_spec.rb
@@ -114,18 +114,6 @@ RSpec.describe Gitlab::EncodingHelper do
expect(ext_class.encode_utf8_with_escaping!(input)).to eq(expected)
end
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(escape_gitaly_refs: false)
- end
-
- it 'uses #encode! method' do
- expect(ext_class).to receive(:encode!).with('String')
-
- ext_class.encode_utf8_with_escaping!('String')
- end
- end
end
describe '#encode_utf8' do
diff --git a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
index 3d23249d00d..73ebee49169 100644
--- a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
+++ b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
@@ -53,9 +53,9 @@ RSpec.describe Gitlab::ErrorTracking::StackTraceHighlightDecorator do
'lineNo' => 3,
'filename' => 'hello_world.php',
'context' => [
- [1, '<span id="LC1" class="line" lang="hack"><span class="c1">// PHP/Hack example</span></span>'],
- [2, '<span id="LC1" class="line" lang="hack"><span class="cp">&lt;?php</span></span>'],
- [3, '<span id="LC1" class="line" lang="hack"><span class="k">echo</span> <span class="s1">\'Hello, World!\'</span><span class="p">;</span></span>']
+ [1, '<span id="LC1" class="line" lang="hack"><span class="c1">// PHP/Hack example</span></span>'],
+ [2, '<span id="LC1" class="line" lang="hack"><span class="cp">&lt;?php</span></span>'],
+ [3, '<span id="LC1" class="line" lang="hack"><span class="k">echo</span> <span class="s1">\'Hello, World!\'</span><span class="p">;</span></span>']
]
},
{
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
deleted file mode 100644
index 799884d7a74..00000000000
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ /dev/null
@@ -1,675 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
- include TrackingHelpers
-
- before do
- stub_const('Gitlab::Experimentation::EXPERIMENTS', {
- test_experiment: {
- tracking_category: 'Team',
- rollout_strategy: rollout_strategy
- },
- my_experiment: {
- tracking_category: 'Team'
- }
- }
- )
-
- allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
-
- Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
- end
-
- let(:enabled_percentage) { 10 }
- let(:rollout_strategy) { nil }
- let(:is_gitlab_com) { true }
-
- controller(ApplicationController) do
- include Gitlab::Experimentation::ControllerConcern
-
- def index
- head :ok
- end
- end
-
- describe '#set_experimentation_subject_id_cookie' do
- let(:do_not_track) { nil }
- let(:cookie) { cookies.permanent.signed[:experimentation_subject_id] }
- let(:cookie_value) { nil }
-
- before do
- stub_do_not_track(do_not_track) if do_not_track.present?
- request.cookies[:experimentation_subject_id] = cookie_value if cookie_value
-
- get :index
- end
-
- context 'cookie is present' do
- let(:cookie_value) { 'test' }
-
- it 'does not change the cookie' do
- expect(cookies[:experimentation_subject_id]).to eq 'test'
- end
- end
-
- context 'cookie is not present' do
- it 'sets a permanent signed cookie' do
- expect(cookie).to be_present
- end
-
- context 'DNT: 0' do
- let(:do_not_track) { '0' }
-
- it 'sets a permanent signed cookie' do
- expect(cookie).to be_present
- end
- end
-
- context 'DNT: 1' do
- let(:do_not_track) { '1' }
-
- it 'does nothing' do
- expect(cookie).not_to be_present
- end
- end
- end
-
- context 'when not on gitlab.com' do
- let(:is_gitlab_com) { false }
-
- context 'when cookie was set' do
- let(:cookie_value) { 'test' }
-
- it 'cookie gets deleted' do
- expect(cookie).not_to be_present
- end
- end
-
- context 'when no cookie was set before' do
- it 'does nothing' do
- expect(cookie).not_to be_present
- end
- end
- end
- end
-
- describe '#push_frontend_experiment' do
- it 'pushes an experiment to the frontend' do
- gon = class_double('Gon')
- stub_experiment_for_subject(my_experiment: true)
- allow(controller).to receive(:gon).and_return(gon)
-
- expect(gon).to receive(:push).with({ experiments: { 'myExperiment' => true } }, true)
-
- controller.push_frontend_experiment(:my_experiment)
- end
- end
-
- describe '#experiment_enabled?' do
- def check_experiment(exp_key = :test_experiment, subject = nil)
- controller.experiment_enabled?(exp_key, subject: subject)
- end
-
- subject { check_experiment }
-
- context 'cookie is not present' do
- it { is_expected.to eq(false) }
- end
-
- context 'cookie is present' do
- before do
- cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234'
- get :index
- end
-
- it 'calls Gitlab::Experimentation.in_experiment_group? with the name of the experiment and the calculated experimentation_subject_index based on the uuid' do
- expect(Gitlab::Experimentation).to receive(:in_experiment_group?).with(:test_experiment, subject: 'abcd-1234')
-
- check_experiment(:test_experiment)
- end
-
- context 'when subject is given' do
- let(:rollout_strategy) { :user }
- let(:user) { build(:user) }
-
- it 'uses the subject' do
- expect(Gitlab::Experimentation).to receive(:in_experiment_group?).with(:test_experiment, subject: user)
-
- check_experiment(:test_experiment, user)
- end
- end
- end
-
- context 'do not track' do
- before do
- allow(Gitlab::Experimentation).to receive(:in_experiment_group?) { true }
- end
-
- context 'when do not track is disabled' do
- before do
- controller.request.headers['DNT'] = '0'
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'when do not track is enabled' do
- before do
- controller.request.headers['DNT'] = '1'
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- context 'URL parameter to force enable experiment' do
- it 'returns true unconditionally' do
- get :index, params: { force_experiment: :test_experiment }
-
- is_expected.to eq(true)
- end
- end
-
- context 'Cookie parameter to force enable experiment' do
- it 'returns true unconditionally' do
- cookies[:force_experiment] = 'test_experiment,another_experiment'
- get :index
-
- expect(check_experiment(:test_experiment)).to eq(true)
- expect(check_experiment(:another_experiment)).to eq(true)
- end
- end
- end
-
- describe '#track_experiment_event', :snowplow do
- let(:user) { build(:user) }
-
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_subject(test_experiment: true)
- end
-
- it 'tracks the event with the right parameters' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'experimental_group',
- value: 1,
- user: user
- )
- end
- end
-
- context 'the user is part of the control group' do
- before do
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it 'tracks the event with the right parameters' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1,
- user: user
- )
- end
- end
-
- context 'do not track is disabled' do
- before do
- stub_do_not_track('0')
- end
-
- it 'does track the event' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1,
- user: user
- )
- end
- end
-
- context 'do not track enabled' do
- before do
- stub_do_not_track('1')
- end
-
- it 'does not track the event' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_no_snowplow_event
- end
- end
-
- context 'subject is provided' do
- before do
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it "provides the subject's hashed global_id as label" do
- experiment_subject = double(:subject, to_global_id: 'abc')
- allow(Gitlab::Experimentation).to receive(:valid_subject_for_rollout_strategy?).and_return(true)
-
- controller.track_experiment_event(:test_experiment, 'start', 1, subject: experiment_subject)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1,
- label: Digest::SHA256.hexdigest('abc'),
- user: user
- )
- end
-
- it "provides the subject's hashed string representation as label" do
- experiment_subject = 'somestring'
-
- controller.track_experiment_event(:test_experiment, 'start', 1, subject: experiment_subject)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1,
- label: Digest::SHA256.hexdigest('somestring'),
- user: user
- )
- end
- end
-
- context 'no subject is provided but cookie is set' do
- before do
- get :index
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it 'uses the experimentation_subject_id as fallback' do
- controller.track_experiment_event(:test_experiment, 'start', 1)
-
- expect_snowplow_event(
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 1,
- label: cookies.permanent.signed[:experimentation_subject_id],
- user: user
- )
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- end
-
- it 'does not track the event' do
- controller.track_experiment_event(:test_experiment, 'start')
-
- expect_no_snowplow_event
- end
- end
- end
-
- describe '#frontend_experimentation_tracking_data' do
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_subject(test_experiment: true)
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'experimental_group',
- value: 'team_id'
- }
- )
- end
- end
-
- context 'the user is part of the control group' do
- before do
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group',
- value: 'team_id'
- }
- )
- end
-
- it 'does not send nil value to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group'
- }
- )
- end
- end
-
- context 'do not track disabled' do
- before do
- stub_do_not_track('0')
- end
-
- it 'pushes the right parameters to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
-
- expect(Gon.tracking_data).to eq(
- {
- category: 'Team',
- action: 'start',
- property: 'control_group'
- }
- )
- end
- end
-
- context 'do not track enabled' do
- before do
- stub_do_not_track('1')
- end
-
- it 'does not push data to gon' do
- controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
-
- expect(Gon.method_defined?(:tracking_data)).to eq(false)
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- end
-
- it 'does not push data to gon' do
- expect(Gon.method_defined?(:tracking_data)).to eq(false)
- controller.track_experiment_event(:test_experiment, 'start')
- end
- end
- end
-
- describe '#record_experiment_user' do
- let(:user) { build(:user) }
- let(:context) { { a: 42 } }
-
- context 'when the experiment is enabled' do
- before do
- stub_experiment(test_experiment: true)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- context 'the user is part of the experimental group' do
- before do
- stub_experiment_for_subject(test_experiment: true)
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user, context)
-
- controller.record_experiment_user(:test_experiment, context)
- end
-
- context 'with a cookie based rollout strategy' do
- it 'calls tracking_group with a nil subject' do
- expect(controller).to receive(:tracking_group).with(:test_experiment, nil, subject: nil).and_return(:experimental)
- allow(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user, context)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
-
- context 'with a user based rollout strategy' do
- let(:rollout_strategy) { :user }
-
- it 'calls tracking_group with a user subject' do
- expect(controller).to receive(:tracking_group).with(:test_experiment, nil, subject: user).and_return(:experimental)
- allow(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user, context)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
- end
-
- context 'the user is part of the control group' do
- before do
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user, context)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
- end
-
- context 'when the experiment is disabled' do
- before do
- stub_experiment(test_experiment: false)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
-
- context 'when there is no current_user' do
- before do
- stub_experiment(test_experiment: true)
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
-
- context 'do not track' do
- before do
- stub_experiment(test_experiment: true)
- allow(controller).to receive(:current_user).and_return(user)
- end
-
- context 'is disabled' do
- before do
- stub_do_not_track('0')
- stub_experiment_for_subject(test_experiment: false)
- end
-
- it 'calls add_user on the Experiment model' do
- expect(::Experiment).to receive(:add_user).with(:test_experiment, :control, user, context)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
-
- context 'is enabled' do
- before do
- stub_do_not_track('1')
- end
-
- it 'does not call add_user on the Experiment model' do
- expect(::Experiment).not_to receive(:add_user)
-
- controller.record_experiment_user(:test_experiment, context)
- end
- end
- end
- end
-
- describe '#record_experiment_group' do
- let(:group) { 'a group object' }
- let(:experiment_key) { :some_experiment_key }
- let(:dnt_enabled) { false }
- let(:experiment_active) { true }
- let(:rollout_strategy) { :whatever }
- let(:variant) { 'variant' }
-
- before do
- allow(controller).to receive(:dnt_enabled?).and_return(dnt_enabled)
- allow(::Gitlab::Experimentation).to receive(:active?).and_return(experiment_active)
- allow(::Gitlab::Experimentation).to receive(:rollout_strategy).and_return(rollout_strategy)
- allow(controller).to receive(:tracking_group).and_return(variant)
- allow(::Experiment).to receive(:add_group)
- end
-
- subject(:record_experiment_group) { controller.record_experiment_group(experiment_key, group) }
-
- shared_examples 'exits early without recording' do
- it 'returns early without recording the group as an ExperimentSubject' do
- expect(::Experiment).not_to receive(:add_group)
- record_experiment_group
- end
- end
-
- shared_examples 'calls tracking_group' do |using_cookie_rollout|
- it "calls tracking_group with #{using_cookie_rollout ? 'a nil' : 'the group as the'} subject" do
- expect(controller).to receive(:tracking_group).with(experiment_key, nil, subject: using_cookie_rollout ? nil : group).and_return(variant)
- record_experiment_group
- end
- end
-
- shared_examples 'records the group' do
- it 'records the group' do
- expect(::Experiment).to receive(:add_group).with(experiment_key, group: group, variant: variant)
- record_experiment_group
- end
- end
-
- context 'when DNT is enabled' do
- let(:dnt_enabled) { true }
-
- include_examples 'exits early without recording'
- end
-
- context 'when the experiment is not active' do
- let(:experiment_active) { false }
-
- include_examples 'exits early without recording'
- end
-
- context 'when a nil group is given' do
- let(:group) { nil }
-
- include_examples 'exits early without recording'
- end
-
- context 'when the experiment uses a cookie-based rollout strategy' do
- let(:rollout_strategy) { :cookie }
-
- include_examples 'calls tracking_group', true
- include_examples 'records the group'
- end
-
- context 'when the experiment uses a non-cookie-based rollout strategy' do
- let(:rollout_strategy) { :group }
-
- include_examples 'calls tracking_group', false
- include_examples 'records the group'
- end
- end
-
- describe '#record_experiment_conversion_event' do
- let(:user) { build(:user) }
-
- before do
- allow(controller).to receive(:dnt_enabled?).and_return(false)
- allow(controller).to receive(:current_user).and_return(user)
- stub_experiment(test_experiment: true)
- end
-
- subject(:record_conversion_event) do
- controller.record_experiment_conversion_event(:test_experiment)
- end
-
- it 'records the conversion event for the experiment & user' do
- expect(::Experiment).to receive(:record_conversion_event).with(:test_experiment, user, {})
- record_conversion_event
- end
-
- shared_examples 'does not record the conversion event' do
- it 'does not record the conversion event' do
- expect(::Experiment).not_to receive(:record_conversion_event)
- record_conversion_event
- end
- end
-
- context 'when DNT is enabled' do
- before do
- allow(controller).to receive(:dnt_enabled?).and_return(true)
- end
-
- include_examples 'does not record the conversion event'
- end
-
- context 'when there is no current user' do
- before do
- allow(controller).to receive(:current_user).and_return(nil)
- end
-
- include_examples 'does not record the conversion event'
- end
-
- context 'when the experiment is not enabled' do
- before do
- stub_experiment(test_experiment: false)
- end
-
- include_examples 'does not record the conversion event'
- end
- end
-
- describe '#experiment_tracking_category_and_group' do
- let_it_be(:experiment_key) { :test_something }
-
- subject { controller.experiment_tracking_category_and_group(experiment_key) }
-
- it 'returns a string with the experiment tracking category & group joined with a ":"' do
- expect(controller).to receive(:tracking_category).with(experiment_key).and_return('Experiment::Category')
- expect(controller).to receive(:tracking_group).with(experiment_key, '_group', subject: nil).and_return('experimental_group')
-
- expect(subject).to eq('Experiment::Category:experimental_group')
- end
- end
-end
diff --git a/spec/lib/gitlab/experimentation/experiment_spec.rb b/spec/lib/gitlab/experimentation/experiment_spec.rb
deleted file mode 100644
index a5cc69b9538..00000000000
--- a/spec/lib/gitlab/experimentation/experiment_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Experimentation::Experiment do
- using RSpec::Parameterized::TableSyntax
-
- let(:percentage) { 50 }
- let(:params) do
- {
- tracking_category: 'Category1',
- rollout_strategy: nil
- }
- end
-
- 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
-
- subject(:experiment) { described_class.new(:experiment_key, **params) }
-
- describe '#active?' do
- before do
- allow(Gitlab).to receive(:com?).and_return(on_gitlab_com)
- end
-
- subject { experiment.active? }
-
- where(:on_gitlab_com, :percentage, :is_active) do
- true | 0 | false
- true | 10 | true
- false | 0 | false
- false | 10 | false
- end
-
- with_them do
- it { is_expected.to eq(is_active) }
- end
- end
-
- describe '#enabled_for_index?' do
- subject { experiment.enabled_for_index?(index) }
-
- where(:index, :percentage, :is_enabled) do
- 50 | 40 | false
- 40 | 50 | true
- nil | 50 | false
- end
-
- with_them do
- it { is_expected.to eq(is_enabled) }
- end
- end
-end
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
deleted file mode 100644
index c482874b725..00000000000
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Experimentation do
- using RSpec::Parameterized::TableSyntax
-
- before do
- stub_const('Gitlab::Experimentation::EXPERIMENTS', {
- test_experiment: {
- tracking_category: 'Team'
- },
- tabular_experiment: {
- tracking_category: 'Team',
- rollout_strategy: rollout_strategy
- }
- })
-
- skip_feature_flags_yaml_validation
- skip_default_enabled_yaml_check
- Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
- allow(Gitlab).to receive(:com?).and_return(true)
- end
-
- let(:enabled_percentage) { 10 }
- let(:rollout_strategy) { nil }
-
- describe '.get_experiment' do
- subject { described_class.get_experiment(:test_experiment) }
-
- context 'returns experiment' do
- it { is_expected.to be_instance_of(Gitlab::Experimentation::Experiment) }
- end
-
- context 'experiment is not defined' do
- subject { described_class.get_experiment(:missing_experiment) }
-
- it { is_expected.to be_nil }
- end
- end
-
- describe '.active?' do
- subject { described_class.active?(:test_experiment) }
-
- context 'feature toggle is enabled' do
- it { is_expected.to eq(true) }
- end
-
- describe 'experiment is not defined' do
- it 'returns false' do
- expect(described_class.active?(:missing_experiment)).to eq(false)
- end
- end
-
- describe 'experiment is disabled' do
- let(:enabled_percentage) { 0 }
-
- it { is_expected.to eq(false) }
- end
- end
-
- describe '.in_experiment_group?' do
- let(:enabled_percentage) { 50 }
- let(:experiment_subject) { 'z' } # Zlib.crc32('test_experimentz') % 100 = 33
-
- subject { described_class.in_experiment_group?(:test_experiment, subject: experiment_subject) }
-
- context 'when experiment is active' do
- context 'when subject is part of the experiment' do
- it { is_expected.to eq(true) }
- end
-
- context 'when subject is not part of the experiment' do
- let(:experiment_subject) { 'a' } # Zlib.crc32('test_experimenta') % 100 = 61
-
- it { is_expected.to eq(false) }
- end
-
- context 'when subject has a global_id' do
- let(:experiment_subject) { double(:subject, to_global_id: 'z') }
-
- it { is_expected.to eq(true) }
- end
-
- context 'when subject is nil' do
- let(:experiment_subject) { nil }
-
- it { is_expected.to eq(false) }
- end
-
- context 'when subject is an empty string' do
- let(:experiment_subject) { '' }
-
- it { is_expected.to eq(false) }
- end
- end
-
- context 'when experiment is not active' do
- before do
- allow(described_class).to receive(:active?).and_return(false)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- describe '.log_invalid_rollout' do
- subject { described_class.log_invalid_rollout(:test_experiment, 1) }
-
- before do
- allow(described_class).to receive(:valid_subject_for_rollout_strategy?).and_return(valid)
- end
-
- context 'subject is not valid for experiment' do
- let(:valid) { false }
-
- it 'logs a warning message' do
- expect_next_instance_of(Gitlab::ExperimentationLogger) do |logger|
- expect(logger)
- .to receive(:warn)
- .with(
- message: 'Subject must conform to the rollout strategy',
- experiment_key: :test_experiment,
- subject: 'Integer',
- rollout_strategy: :cookie
- )
- end
-
- subject
- end
- end
-
- context 'subject is valid for experiment' do
- let(:valid) { true }
-
- it 'does not log a warning message' do
- expect(Gitlab::ExperimentationLogger).not_to receive(:build)
-
- subject
- end
- end
- end
-
- describe '.valid_subject_for_rollout_strategy?' do
- subject { described_class.valid_subject_for_rollout_strategy?(:tabular_experiment, experiment_subject) }
-
- where(:rollout_strategy, :experiment_subject, :result) do
- :cookie | nil | true
- nil | nil | true
- :cookie | 'string' | true
- nil | User.new | false
- :user | User.new | true
- :group | User.new | false
- :group | Group.new | true
- end
-
- with_them do
- it { is_expected.to be(result) }
- end
- end
-end
diff --git a/spec/lib/gitlab/git/keep_around_spec.rb b/spec/lib/gitlab/git/keep_around_spec.rb
index 44c3caf3f8d..d6359d55646 100644
--- a/spec/lib/gitlab/git/keep_around_spec.rb
+++ b/spec/lib/gitlab/git/keep_around_spec.rb
@@ -18,23 +18,14 @@ RSpec.describe Gitlab::Git::KeepAround do
expect(service.kept_around?(sample_commit.id)).to be_truthy
end
- it "attempting to call keep around on truncated ref does not fail" do
- service.execute([sample_commit.id])
- ref = service.send(:keep_around_ref_name, sample_commit.id)
-
- path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- File.join(repository.path, ref)
- end
- # Corrupt the reference
- File.truncate(path, 0)
+ it "does not fail if writting the ref fails" do
+ expect(repository.raw).to receive(:write_ref).and_raise(Gitlab::Git::CommandError)
expect(service.kept_around?(sample_commit.id)).to be_falsey
service.execute([sample_commit.id])
expect(service.kept_around?(sample_commit.id)).to be_falsey
-
- File.delete(path)
end
context 'for multiple SHAs' do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 9a87911b6e8..f3d3fd2034c 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -461,7 +461,11 @@ RSpec.describe Gitlab::Git::Repository do
end
it 'raises an error if it failed' do
- expect { repository.delete_refs('refs\heads\fix') }.to raise_error(Gitlab::Git::Repository::GitError)
+ # TODO: Once https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4921
+ # is merged, remove the assertion for Gitlab::Git::Repository::GitError
+ expect { repository.delete_refs('refs\heads\fix') }.to raise_error do |e|
+ expect(e).to be_a(Gitlab::Git::Repository::GitError).or be_a(Gitlab::Git::InvalidRefFormatError)
+ end
end
end
@@ -483,6 +487,12 @@ RSpec.describe Gitlab::Git::Repository do
it 'displays that branch' do
expect(repository.branch_names_contains_sha(head_id)).to include('master', new_branch, utf8_branch)
end
+
+ context 'when limit is provided' do
+ it 'displays limited number of branches' do
+ expect(repository.branch_names_contains_sha(head_id, limit: 1)).to match_array(['2-mb-file'])
+ end
+ end
end
describe "#refs_hash" do
@@ -668,11 +678,11 @@ RSpec.describe Gitlab::Git::Repository do
expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
.to receive(:find_remote_root_ref).and_call_original
- expect(repository.find_remote_root_ref(SeedHelper::GITLAB_GIT_TEST_REPO_URL)).to eq 'master'
+ expect(repository.find_remote_root_ref(TestEnv.factory_repo_path.to_s)).to eq 'master'
end
it 'returns UTF-8' do
- expect(repository.find_remote_root_ref(SeedHelper::GITLAB_GIT_TEST_REPO_URL)).to be_utf8
+ expect(repository.find_remote_root_ref(TestEnv.factory_repo_path.to_s)).to be_utf8
end
it 'returns nil when remote name is nil' do
@@ -690,7 +700,7 @@ RSpec.describe Gitlab::Git::Repository do
end
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RemoteService, :find_remote_root_ref do
- subject { repository.find_remote_root_ref(SeedHelper::GITLAB_GIT_TEST_REPO_URL) }
+ subject { repository.find_remote_root_ref(TestEnv.factory_repo_path.to_s) }
end
end
@@ -1769,12 +1779,13 @@ RSpec.describe Gitlab::Git::Repository do
it 'returns exactly the expected results' do
languages = repository.languages(TestEnv::BRANCH_SHA['master'])
- expect(languages).to match_array([
- { value: a_value_within(0.1).of(66.7), label: "Ruby", color: "#701516", highlight: "#701516" },
- { value: a_value_within(0.1).of(22.96), label: "JavaScript", color: "#f1e05a", highlight: "#f1e05a" },
- { value: a_value_within(0.1).of(7.9), label: "HTML", color: "#e34c26", highlight: "#e34c26" },
- { value: a_value_within(0.1).of(2.51), label: "CoffeeScript", color: "#244776", highlight: "#244776" }
- ])
+ expect(languages).to match_array(
+ [
+ { value: a_value_within(0.1).of(66.7), label: "Ruby", color: "#701516", highlight: "#701516" },
+ { value: a_value_within(0.1).of(22.96), label: "JavaScript", color: "#f1e05a", highlight: "#f1e05a" },
+ { value: a_value_within(0.1).of(7.9), label: "HTML", color: "#e34c26", highlight: "#e34c26" },
+ { value: a_value_within(0.1).of(2.51), label: "CoffeeScript", color: "#244776", highlight: "#244776" }
+ ])
end
it "uses the repository's HEAD when no ref is passed" do
@@ -1784,22 +1795,48 @@ RSpec.describe Gitlab::Git::Repository do
end
end
- describe '#license_short_name' do
- subject { repository.license_short_name }
+ describe '#license' do
+ where(from_gitaly: [true, false])
+ with_them do
+ subject(:license) { repository.license(from_gitaly) }
- context 'when no license file can be found' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository.raw_repository }
+ context 'when no license file can be found' do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw_repository }
- before do
- project.repository.delete_file(project.owner, 'LICENSE', message: 'remove license', branch_name: 'master')
+ before do
+ project.repository.delete_file(project.owner, 'LICENSE', message: 'remove license', branch_name: 'master')
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when an mit license is found' do
+ it { is_expected.to have_attributes(key: 'mit') }
end
- it { is_expected.to be_nil }
+ context 'when license is not recognized ' do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw_repository }
+
+ before do
+ project.repository.update_file(
+ project.owner,
+ 'LICENSE',
+ 'This software is licensed under the Dummy license.',
+ message: 'Update license',
+ branch_name: 'master')
+ end
+
+ it { is_expected.to have_attributes(key: 'other', nickname: 'LICENSE') }
+ end
end
- context 'when an mit license is found' do
- it { is_expected.to eq('mit') }
+ it 'does not crash when license is invalid' do
+ expect(Licensee::License).to receive(:new)
+ .and_raise(Licensee::InvalidLicense)
+
+ expect(repository.license(false)).to be_nil
end
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 747611a59e6..524b373a5b7 100644
--- a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
+++ b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
@@ -213,7 +213,8 @@ RSpec.describe Gitlab::Git::RuggedImpl::UseRugged do
end
def create_gitaly_metadata_file
- File.open(File.join(SEED_STORAGE_PATH, '.gitaly-metadata'), 'w+') do |f|
+ metadata_filename = File.join(TestEnv.repos_path, '.gitaly-metadata')
+ File.open(metadata_filename, 'w+') do |f|
gitaly_metadata = {
"gitaly_filesystem_id" => SecureRandom.uuid
}
diff --git a/spec/lib/gitlab/git/wiki_spec.rb b/spec/lib/gitlab/git/wiki_spec.rb
deleted file mode 100644
index 05c7ac149e4..00000000000
--- a/spec/lib/gitlab/git/wiki_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Git::Wiki do
- using RSpec::Parameterized::TableSyntax
-
- let(:project) { create(:project) }
- let(:user) { project.first_owner }
- let(:project_wiki) { ProjectWiki.new(project, user) }
- let(:repository) { project_wiki.repository }
- let(:default_branch) { described_class.default_ref(project) }
-
- subject(:wiki) { project_wiki.wiki }
-
- before do
- repository.create_if_not_exists(project_wiki.default_branch)
- end
-
- describe '#pages' do
- before do
- create_page('page1', 'content')
- create_page('page2', 'content2')
- end
-
- after do
- destroy_page('page1')
- destroy_page('page2')
- end
-
- it 'returns all the pages' do
- expect(subject.list_pages.count).to eq(2)
- expect(subject.list_pages.first.title).to eq 'page1'
- expect(subject.list_pages.last.title).to eq 'page2'
- end
-
- it 'returns only one page' do
- pages = subject.list_pages(limit: 1)
-
- expect(pages.count).to eq(1)
- expect(pages.first.title).to eq 'page1'
- end
- end
-
- describe '#page' do
- before do
- create_page('page1', 'content')
- create_page('foo/page1', 'content foo/page1')
- end
-
- after do
- destroy_page('page1')
- destroy_page('foo/page1')
- end
-
- it 'returns the right page' do
- page = subject.page(title: 'page1', dir: '')
- expect(page.url_path).to eq 'page1'
- expect(page.raw_data).to eq 'content'
-
- page = subject.page(title: 'page1', dir: 'foo')
- expect(page.url_path).to eq 'foo/page1'
- expect(page.raw_data).to eq 'content foo/page1'
- end
-
- it 'returns nil for invalid arguments' do
- expect(subject.page(title: '')).to be_nil
- expect(subject.page(title: 'foo', version: ':')).to be_nil
- end
-
- it 'does not return content if load_content param is set to false' do
- page = subject.page(title: 'page1', dir: '', load_content: false)
-
- expect(page.url_path).to eq 'page1'
- expect(page.raw_data).to be_empty
- end
- end
-
- describe '#preview_slug' do
- where(:title, :file_extension, :format, :expected_slug) do
- 'The Best Thing' | :md | :markdown | 'The-Best-Thing'
- 'The Best Thing' | :md | :md | 'The-Best-Thing'
- 'The Best Thing' | :txt | :txt | 'The-Best-Thing'
- 'A Subject/Title Here' | :txt | :txt | 'A-Subject/Title-Here'
- 'A subject' | :txt | :txt | 'A-subject'
- 'A 1/B 2/C 3' | :txt | :txt | 'A-1/B-2/C-3'
- 'subject/title' | :txt | :txt | 'subject/title'
- 'subject/title.md' | :txt | :txt | 'subject/title.md'
- 'foo<bar>+baz' | :txt | :txt | 'foo-bar--baz'
- 'foo%2Fbar' | :txt | :txt | 'foo%2Fbar'
- '' | :md | :markdown | '.md'
- '' | :md | :md | '.md'
- '' | :txt | :txt | '.txt'
- end
-
- with_them do
- subject { wiki.preview_slug(title, format) }
-
- let(:gitaly_slug) { wiki.list_pages.first }
-
- it { is_expected.to eq(expected_slug) }
-
- it 'matches the slug generated by gitaly' do
- skip('Gitaly cannot generate a slug for an empty title') unless title.present?
-
- create_page(title, 'content', file_extension)
-
- gitaly_slug = wiki.list_pages.first.url_path
-
- is_expected.to eq(gitaly_slug)
- end
- end
- end
-
- def create_page(name, content, extension = :md)
- repository.create_file(
- user, ::Wiki.sluggified_full_path(name, extension.to_s), content,
- branch_name: default_branch,
- message: "created page #{name}",
- author_email: user.email,
- author_name: user.name
- )
- end
-
- def destroy_page(name, extension = :md)
- repository.delete_file(
- user, ::Wiki.sluggified_full_path(name, extension.to_s),
- branch_name: described_class.default_ref(project),
- message: "delete page #{name}",
- author_email: user.email,
- author_name: user.name
- )
- end
-end
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index a7036a4f20a..0d069d36e48 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GitAccessSnippet do
include ProjectHelpers
+ include UserHelpers
include TermsHelper
include AdminModeHelper
include_context 'ProjectPolicyTable context'
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 8577cad1011..7e3a1bf61bc 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -4,11 +4,9 @@ require 'spec_helper'
RSpec.describe Gitlab::GitAccess, :aggregate_failures do
include TermsHelper
- include GitHelpers
include AdminModeHelper
let(:user) { create(:user) }
-
let(:actor) { user }
let(:project) { create(:project, :repository) }
let(:repository_path) { "#{project.full_path}.git" }
@@ -139,27 +137,18 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do
end
end
- # For backwards compatibility
+ # legacy behavior that is blocked/deprecated
context 'when actor is :ci' do
let(:actor) { :ci }
let(:authentication_abilities) { build_authentication_abilities }
- it 'allows pull access' do
- expect { pull_access_check }.not_to raise_error
+ it 'disallows pull access' do
+ expect { pull_access_check }.to raise_error(Gitlab::GitAccess::NotFoundError)
end
it 'does not block pushes with "not found"' do
expect { push_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:auth_upload])
end
-
- it 'logs' do
- expect(Gitlab::AppJsonLogger).to receive(:info).with(
- message: 'Actor was :ci',
- project_id: project.id
- ).once
-
- pull_access_check
- end
end
context 'when actor is DeployToken' do
@@ -741,18 +730,7 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do
describe 'generic CI (build without a user)' do
let(:actor) { :ci }
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
-
- it 'logs' do
- expect(Gitlab::AppJsonLogger).to receive(:info).with(
- message: 'Actor was :ci',
- project_id: project.id
- ).once
-
- pull_access_check
- end
- end
+ specify { expect { pull_access_check }.to raise_error Gitlab::GitAccess::NotFoundError }
end
end
end
@@ -810,18 +788,29 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do
def merge_into_protected_branch
@protected_branch_merge_commit ||= begin
project.repository.add_branch(user, unprotected_branch, 'feature')
- rugged = rugged_repo(project.repository)
- target_branch = rugged.rev_parse('feature')
+ target_branch = TestEnv::BRANCH_SHA['feature']
source_branch = project.repository.create_file(
user,
'filename',
'This is the file content',
message: 'This is a good commit message',
branch_name: unprotected_branch)
- author = { email: "email@example.com", time: Time.now, name: "Example Git User" }
-
- merge_index = rugged.merge_commits(target_branch, source_branch)
- Rugged::Commit.create(rugged, author: author, committer: author, message: "commit message", parents: [target_branch, source_branch], tree: merge_index.write_tree(rugged))
+ merge_id = project.repository.raw.merge_to_ref(
+ user,
+ branch: target_branch,
+ first_parent_ref: target_branch,
+ source_sha: source_branch,
+ target_ref: 'refs/merge-requests/test',
+ message: 'commit message'
+ )
+
+ # We are trying to simulate what the repository would look like
+ # during the pre-receive hook, before the actual ref is
+ # written/created. Repository#new_commits relies on there being no
+ # ref pointing to the merge commit.
+ project.repository.delete_refs('refs/merge-requests/test')
+
+ merge_id
end
end
diff --git a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
index f869c66337e..d02b4492216 100644
--- a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
@@ -174,20 +174,22 @@ RSpec.describe Gitlab::GitalyClient::BlobService do
expect(service)
.to receive(:list_blobs)
.with(gitaly_request_with_params(expected_params), kind_of(Hash))
- .and_return([
- Gitaly::ListBlobsResponse.new(blobs: [
- Gitaly::ListBlobsResponse::Blob.new(oid: "012345", size: 8, data: "0x01"),
- Gitaly::ListBlobsResponse::Blob.new(data: "23")
- ]),
- Gitaly::ListBlobsResponse.new(blobs: [
- Gitaly::ListBlobsResponse::Blob.new(data: "45"),
- Gitaly::ListBlobsResponse::Blob.new(oid: "56", size: 4, data: "0x5"),
- Gitaly::ListBlobsResponse::Blob.new(data: "6")
- ]),
- Gitaly::ListBlobsResponse.new(blobs: [
- Gitaly::ListBlobsResponse::Blob.new(oid: "78", size: 4, data: "0x78")
+ .and_return(
+ [
+ Gitaly::ListBlobsResponse.new(
+ blobs: [
+ Gitaly::ListBlobsResponse::Blob.new(oid: "012345", size: 8, data: "0x01"),
+ Gitaly::ListBlobsResponse::Blob.new(data: "23")
+ ]),
+ Gitaly::ListBlobsResponse.new(
+ blobs: [
+ Gitaly::ListBlobsResponse::Blob.new(data: "45"),
+ Gitaly::ListBlobsResponse::Blob.new(oid: "56", size: 4, data: "0x5"),
+ Gitaly::ListBlobsResponse::Blob.new(data: "6")
+ ]),
+ Gitaly::ListBlobsResponse.new(
+ blobs: [Gitaly::ListBlobsResponse::Blob.new(oid: "78", size: 4, data: "0x78")])
])
- ])
end
blobs = subject.to_a
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index b7c21516c77..5ce88b06241 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GitalyClient::RefService do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
+
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
let(:repository) { project.repository }
@@ -179,13 +180,22 @@ RSpec.describe Gitlab::GitalyClient::RefService do
)
)
end
+
local_branches = target_commits.each_with_index.map do |gitaly_commit, i|
Gitaly::Branch.new(name: "#{remote_name}/#{i}", target_commit: gitaly_commit)
end
- response = [
- Gitaly::FindLocalBranchesResponse.new(branches: branches[0, 2], local_branches: local_branches[0, 2]),
- Gitaly::FindLocalBranchesResponse.new(branches: branches[2, 2], local_branches: local_branches[2, 2])
- ]
+
+ response = if set_local_branches
+ [
+ Gitaly::FindLocalBranchesResponse.new(local_branches: local_branches[0, 2]),
+ Gitaly::FindLocalBranchesResponse.new(local_branches: local_branches[2, 2])
+ ]
+ else
+ [
+ Gitaly::FindLocalBranchesResponse.new(branches: branches[0, 2]),
+ Gitaly::FindLocalBranchesResponse.new(branches: branches[2, 2])
+ ]
+ end
expect_any_instance_of(Gitaly::RefService::Stub)
.to receive(:find_local_branches)
@@ -220,18 +230,14 @@ RSpec.describe Gitlab::GitalyClient::RefService do
end
end
- context 'when feature flag :gitaly_simplify_find_local_branches_response is enabled' do
- before do
- stub_feature_flags(gitaly_simplify_find_local_branches_response: true)
- end
+ context 'when local_branches variable is not set' do
+ let(:set_local_branches) { false }
it_behaves_like 'common examples'
end
- context 'when feature flag :gitaly_simplify_find_local_branches_response is disabled' do
- before do
- stub_feature_flags(gitaly_simplify_find_local_branches_response: false)
- end
+ context 'when local_branches variable is set' do
+ let(:set_local_branches) { true }
it_behaves_like 'common examples'
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 63d32cb906f..58ace05b0d3 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -308,7 +308,7 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
describe '#replicate' do
- let(:source_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') }
+ let(:source_repository) { Gitlab::Git::Repository.new('default', 'repo/path', '', 'group/project') }
it 'sends a replicate_repository message' do
expect_any_instance_of(Gitaly::RepositoryService::Stub)
@@ -343,4 +343,18 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
expect(client.full_path).to eq(path)
end
end
+
+ describe "#find_license" do
+ it 'sends a find_license request with medium timeout' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:find_license) do |_service, _request, headers|
+ expect(headers[:deadline]).to be_between(
+ Gitlab::GitalyClient.fast_timeout.seconds.from_now.to_f,
+ Gitlab::GitalyClient.medium_timeout.seconds.from_now.to_f
+ )
+ end
+
+ client.find_license
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb b/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
deleted file mode 100644
index 8a169acb69c..00000000000
--- a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::GitalyClient::WikiService do
- let(:project) { create(:project) }
- let(:storage_name) { project.repository_storage }
- let(:relative_path) { project.disk_path + '.git' }
- let(:client) { described_class.new(project.repository) }
- let(:commit) { create(:gitaly_commit) }
- let(:page_version) { Gitaly::WikiPageVersion.new(format: 'markdown', commit: commit) }
- let(:page_info) { { title: 'My Page', raw_data: 'a', version: page_version } }
-
- describe '#find_page' do
- let(:response) do
- [
- Gitaly::WikiFindPageResponse.new(page: Gitaly::WikiPage.new(page_info)),
- Gitaly::WikiFindPageResponse.new(page: Gitaly::WikiPage.new(raw_data: 'b'))
- ]
- end
-
- let(:wiki_page) { subject.first }
- let(:wiki_page_version) { subject.last }
-
- subject { client.find_page(title: 'My Page', version: 'master', dir: '') }
-
- it 'sends a wiki_find_page message' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_find_page)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .and_return([].each)
-
- subject
- end
-
- it 'concatenates the raw data and returns a pair of WikiPage and WikiPageVersion' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_find_page)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .and_return(response.each)
-
- expect(wiki_page.title).to eq('My Page')
- expect(wiki_page.raw_data).to eq('ab')
- expect(wiki_page_version.format).to eq('markdown')
-
- expect(wiki_page.title).to be_utf8
- expect(wiki_page.path).to be_utf8
- expect(wiki_page.name).to be_utf8
- end
- end
-
- describe '#load_all_pages' do
- let(:page_2_info) { { title: 'My Page 2', raw_data: 'c', version: page_version } }
- let(:response) do
- [
- Gitaly::WikiGetAllPagesResponse.new(page: Gitaly::WikiPage.new(page_info)),
- Gitaly::WikiGetAllPagesResponse.new(page: Gitaly::WikiPage.new(raw_data: 'b')),
- Gitaly::WikiGetAllPagesResponse.new(end_of_page: true),
- Gitaly::WikiGetAllPagesResponse.new(page: Gitaly::WikiPage.new(page_2_info)),
- Gitaly::WikiGetAllPagesResponse.new(page: Gitaly::WikiPage.new(raw_data: 'd')),
- Gitaly::WikiGetAllPagesResponse.new(end_of_page: true)
- ]
- end
-
- let(:wiki_page_1) { subject[0].first }
- let(:wiki_page_1_version) { subject[0].last }
- let(:wiki_page_2) { subject[1].first }
- let(:wiki_page_2_version) { subject[1].last }
-
- subject { client.load_all_pages }
-
- it 'sends a wiki_get_all_pages message' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_get_all_pages)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .and_return([].each)
-
- subject
- end
-
- it 'sends a limit of 0 to wiki_get_all_pages' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_get_all_pages)
- .with(gitaly_request_with_params(limit: 0), kind_of(Hash))
- .and_return([].each)
-
- subject
- end
-
- it 'concatenates the raw data and returns a pair of WikiPage and WikiPageVersion for each page' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_get_all_pages)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .and_return(response.each)
-
- expect(subject.size).to be(2)
- expect(wiki_page_1.title).to eq('My Page')
- expect(wiki_page_1.raw_data).to eq('ab')
- expect(wiki_page_1_version.format).to eq('markdown')
- expect(wiki_page_2.title).to eq('My Page 2')
- expect(wiki_page_2.raw_data).to eq('cd')
- expect(wiki_page_2_version.format).to eq('markdown')
- end
-
- context 'with limits' do
- subject { client.load_all_pages(limit: 1) }
-
- it 'sends a request with the limit' do
- expect_any_instance_of(Gitaly::WikiService::Stub)
- .to receive(:wiki_get_all_pages)
- .with(gitaly_request_with_params(limit: 1), kind_of(Hash))
- .and_return([].each)
-
- subject
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
index c88bb6de859..3361b039a27 100644
--- a/spec/lib/gitlab/github_import/client_spec.rb
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -148,7 +148,25 @@ RSpec.describe Gitlab::GithubImport::Client do
.to receive(:branch_protection).with('org/repo', 'bar')
expect(client).to receive(:with_rate_limit).and_yield
- client.branch_protection('org/repo', 'bar')
+ branch_protection = client.branch_protection('org/repo', 'bar')
+
+ expect(branch_protection).to be_a(Hash)
+ end
+ end
+
+ describe '#each_object' do
+ it 'converts each object into a hash' do
+ client = described_class.new('foo')
+
+ stub_request(:get, 'https://api.github.com/rate_limit')
+ .to_return(status: 200, headers: { 'X-RateLimit-Limit' => 5000, 'X-RateLimit-Remaining' => 5000 })
+
+ stub_request(:get, 'https://api.github.com/repos/foo/bar/releases?per_page=100')
+ .to_return(status: 200, body: [{ id: 1 }].to_json, headers: { 'Content-Type' => 'application/json' })
+
+ client.each_object(:releases, 'foo/bar') do |release|
+ expect(release).to eq({ id: 1 })
+ end
end
end
@@ -575,11 +593,11 @@ RSpec.describe Gitlab::GithubImport::Client do
describe 'search' do
let(:client) { described_class.new('foo') }
- let(:user) { double(:user, login: 'user') }
- let(:org1) { double(:org, login: 'org1') }
- let(:org2) { double(:org, login: 'org2') }
- let(:repo1) { double(:repo, full_name: 'repo1') }
- let(:repo2) { double(:repo, full_name: 'repo2') }
+ let(:user) { { login: 'user' } }
+ let(:org1) { { login: 'org1' } }
+ let(:org2) { { login: 'org2' } }
+ let(:repo1) { { full_name: 'repo1' } }
+ let(:repo2) { { full_name: 'repo2' } }
before do
allow(client)
diff --git a/spec/lib/gitlab/github_import/importer/attachments/base_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/base_importer_spec.rb
new file mode 100644
index 00000000000..5e60be44621
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/attachments/base_importer_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Attachments::BaseImporter do
+ subject(:importer) { importer_class.new(project, client) }
+
+ let(:project) { instance_double(Project, id: 1) }
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+ let(:importer_class) do
+ Class.new(described_class) do
+ private
+
+ def collection_method
+ 'test'
+ end
+ end
+ end
+
+ describe '#each_object_to_import' do
+ context 'with not implemented #collection interface' do
+ it 'raises NotImplementedError' do
+ expect { importer.each_object_to_import }
+ .to raise_error(Gitlab::GithubImport::Exceptions::NotImplementedError, '#collection')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb
new file mode 100644
index 00000000000..85bc67376d3
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Attachments::IssuesImporter do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+
+ describe '#sequential_import', :clean_gitlab_redis_cache do
+ let_it_be(:issue_1) { create(:issue, project: project) }
+ let_it_be(:issue_2) { create(:issue, project: project) }
+
+ let(:importer_stub) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+ let(:importer_attrs) { [instance_of(Gitlab::GithubImport::Representation::NoteText), project, client] }
+
+ it 'imports each project issue attachments' do
+ expect_next_instances_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2, false, *importer_attrs
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ importer.sequential_import
+ end
+
+ context 'when issue is already processed' do
+ it "doesn't import this issue attachments" do
+ importer.mark_as_imported(issue_1)
+
+ expect_next_instance_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter, *importer_attrs
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ importer.sequential_import
+ end
+ end
+ end
+
+ describe '#sidekiq_worker_class' do
+ it { expect(importer.sidekiq_worker_class).to eq(Gitlab::GithubImport::Attachments::ImportIssueWorker) }
+ end
+
+ describe '#collection_method' do
+ it { expect(importer.collection_method).to eq(:issue_attachments) }
+ end
+
+ describe '#object_type' do
+ it { expect(importer.object_type).to eq(:issue_attachment) }
+ end
+
+ describe '#id_for_already_imported_cache' do
+ let(:issue) { build_stubbed(:issue) }
+
+ it { expect(importer.id_for_already_imported_cache(issue)).to eq(issue.id) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb
new file mode 100644
index 00000000000..e4718c2d17c
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporter do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+
+ describe '#sequential_import', :clean_gitlab_redis_cache do
+ let_it_be(:merge_request_1) { create(:merge_request, source_project: project, target_branch: 'feature1') }
+ let_it_be(:merge_request_2) { create(:merge_request, source_project: project, target_branch: 'feature2') }
+
+ let(:importer_stub) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+ let(:importer_attrs) { [instance_of(Gitlab::GithubImport::Representation::NoteText), project, client] }
+
+ it 'imports each project merge request attachments' do
+ expect_next_instances_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter, 2, false, *importer_attrs
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ importer.sequential_import
+ end
+
+ context 'when merge request is already processed' do
+ it "doesn't import this merge request attachments" do
+ importer.mark_as_imported(merge_request_1)
+
+ expect_next_instance_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter, *importer_attrs
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ importer.sequential_import
+ end
+ end
+ end
+
+ describe '#sidekiq_worker_class' do
+ it { expect(importer.sidekiq_worker_class).to eq(Gitlab::GithubImport::Attachments::ImportMergeRequestWorker) }
+ end
+
+ describe '#collection_method' do
+ it { expect(importer.collection_method).to eq(:merge_request_attachments) }
+ end
+
+ describe '#object_type' do
+ it { expect(importer.object_type).to eq(:merge_request_attachment) }
+ end
+
+ describe '#id_for_already_imported_cache' do
+ let(:merge_request) { build_stubbed(:merge_request) }
+
+ it { expect(importer.id_for_already_imported_cache(merge_request)).to eq(merge_request.id) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb
new file mode 100644
index 00000000000..7ed353e1b71
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Attachments::NotesImporter do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+
+ describe '#sequential_import', :clean_gitlab_redis_cache do
+ let_it_be(:note_1) { create(:note, project: project) }
+ let_it_be(:note_2) { create(:note, project: project) }
+ let_it_be(:system_note) { create(:note, :system, project: project) }
+
+ let(:importer_stub) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+ let(:importer_attrs) { [instance_of(Gitlab::GithubImport::Representation::NoteText), project, client] }
+
+ it 'imports each project user note' do
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter).to receive(:new)
+ .with(*importer_attrs).twice.and_return(importer_stub)
+ expect(importer_stub).to receive(:execute).twice
+
+ importer.sequential_import
+ end
+
+ context 'when note is already processed' do
+ it "doesn't import this note" do
+ importer.mark_as_imported(note_1)
+
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter).to receive(:new)
+ .with(*importer_attrs).once.and_return(importer_stub)
+ expect(importer_stub).to receive(:execute).once
+
+ importer.sequential_import
+ end
+ end
+ end
+
+ describe '#sidekiq_worker_class' do
+ it { expect(importer.sidekiq_worker_class).to eq(Gitlab::GithubImport::Attachments::ImportNoteWorker) }
+ end
+
+ describe '#collection_method' do
+ it { expect(importer.collection_method).to eq(:note_attachments) }
+ end
+
+ describe '#object_type' do
+ it { expect(importer.object_type).to eq(:note_attachment) }
+ end
+
+ describe '#id_for_already_imported_cache' do
+ let(:note) { build_stubbed(:note) }
+
+ it { expect(importer.id_for_already_imported_cache(note)).to eq(note.id) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb
new file mode 100644
index 00000000000..b989345ae09
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Attachments::ReleasesImporter do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+
+ describe '#sequential_import', :clean_gitlab_redis_cache do
+ let_it_be(:release_1) { create(:release, project: project) }
+ let_it_be(:release_2) { create(:release, project: project) }
+
+ let(:importer_stub) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+ let(:importer_attrs) { [instance_of(Gitlab::GithubImport::Representation::NoteText), project, client] }
+
+ it 'imports each project release' do
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter).to receive(:new)
+ .with(*importer_attrs).twice.and_return(importer_stub)
+ expect(importer_stub).to receive(:execute).twice
+
+ importer.sequential_import
+ end
+
+ context 'when note is already processed' do
+ it "doesn't import this release" do
+ importer.mark_as_imported(release_1)
+
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter).to receive(:new)
+ .with(*importer_attrs).once.and_return(importer_stub)
+ expect(importer_stub).to receive(:execute).once
+
+ importer.sequential_import
+ end
+ end
+ end
+
+ describe '#sidekiq_worker_class' do
+ it { expect(importer.sidekiq_worker_class).to eq(Gitlab::GithubImport::Attachments::ImportReleaseWorker) }
+ end
+
+ describe '#collection_method' do
+ it { expect(importer.collection_method).to eq(:release_attachments) }
+ end
+
+ describe '#object_type' do
+ it { expect(importer.object_type).to eq(:release_attachment) }
+ end
+
+ describe '#id_for_already_imported_cache' do
+ let(:release) { build_stubbed(:release) }
+
+ it { expect(importer.id_for_already_imported_cache(release)).to eq(release.id) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
index 6eb92cdeab9..a8dd6b4725d 100644
--- a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
@@ -7,14 +7,13 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNotesImporter do
let(:client) { double(:client) }
let(:github_comment) do
- double(
- :response,
+ {
html_url: 'https://github.com/foo/bar/pull/42',
path: 'README.md',
commit_id: '123abc',
original_commit_id: 'original123abc',
diff_hunk: "@@ -1 +1 @@\n-Hello\n+Hello world",
- user: double(:user, id: 4, login: 'alice'),
+ user: { id: 4, login: 'alice' },
created_at: Time.zone.now,
updated_at: Time.zone.now,
line: 23,
@@ -29,7 +28,7 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNotesImporter do
sug1
```
BODY
- )
+ }
end
describe '#parallel?' do
@@ -98,9 +97,10 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNotesImporter do
.to receive(:each_object_to_import)
.and_yield(github_comment)
- expect(Gitlab::GithubImport::ImportDiffNoteWorker).to receive(:bulk_perform_in).with(1.second, [
- [project.id, an_instance_of(Hash), an_instance_of(String)]
- ], batch_size: 1000, batch_delay: 1.minute)
+ expect(Gitlab::GithubImport::ImportDiffNoteWorker).to receive(:bulk_perform_in)
+ .with(1.second, [
+ [project.id, an_instance_of(Hash), an_instance_of(String)]
+ ], batch_size: 1000, batch_delay: 1.minute)
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
index 6b807bdf098..308b8185589 100644
--- a/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
@@ -9,20 +9,19 @@ RSpec.describe Gitlab::GithubImport::Importer::IssuesImporter do
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
let(:github_issue) do
- double(
- :response,
+ {
number: 42,
title: 'My Issue',
body: 'This is my issue',
- milestone: double(:milestone, number: 4),
+ milestone: { number: 4 },
state: 'open',
- assignees: [double(:user, id: 4, login: 'alice')],
- labels: [double(:label, name: 'bug')],
- user: double(:user, id: 4, login: 'alice'),
+ assignees: [{ id: 4, login: 'alice' }],
+ labels: [{ name: 'bug' }],
+ user: { id: 4, login: 'alice' },
created_at: created_at,
updated_at: updated_at,
pull_request: false
- )
+ }
end
describe '#parallel?' do
@@ -110,4 +109,24 @@ RSpec.describe Gitlab::GithubImport::Importer::IssuesImporter do
.to eq(42)
end
end
+
+ describe '#increment_object_counter?' do
+ let(:importer) { described_class.new(project, client) }
+
+ context 'when issue is a pull request' do
+ let(:github_issue) { { pull_request: { url: 'some_url' } } }
+
+ it 'returns false' do
+ expect(importer).not_to be_increment_object_counter(github_issue)
+ end
+ end
+
+ context 'when issue is a regular issue' do
+ let(:github_issue) { {} }
+
+ it 'returns true' do
+ expect(importer).to be_increment_object_counter(github_issue)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
index ca9d3e1e21c..81d534c566f 100644
--- a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_red
describe '#build_labels' do
it 'returns an Array containnig label rows' do
- label = double(:label, name: 'bug', color: 'ffffff')
+ label = { name: 'bug', color: 'ffffff' }
expect(importer).to receive(:each_label).and_return([label])
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_red
it 'does not create labels that already exist' do
create(:label, project: project, title: 'bug')
- label = double(:label, name: 'bug', color: 'ffffff')
+ label = { name: 'bug', color: 'ffffff' }
expect(importer).to receive(:each_label).and_return([label])
expect(importer.build_labels).to be_empty
@@ -60,7 +60,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_red
describe '#build' do
let(:label_hash) do
- importer.build(double(:label, name: 'bug', color: 'ffffff'))
+ importer.build({ name: 'bug', color: 'ffffff' })
end
it 'returns the attributes of the label as a Hash' do
diff --git a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
index 251829b83a0..99536588718 100644
--- a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
@@ -118,9 +118,10 @@ RSpec.describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
expect(service).to receive(:execute).and_return([lfs_download_object])
end
- expect(Gitlab::GithubImport::ImportLfsObjectWorker).to receive(:bulk_perform_in).with(1.second, [
- [project.id, an_instance_of(Hash), an_instance_of(String)]
- ], batch_size: 1000, batch_delay: 1.minute)
+ expect(Gitlab::GithubImport::ImportLfsObjectWorker).to receive(:bulk_perform_in)
+ .with(1.second, [
+ [project.id, an_instance_of(Hash), an_instance_of(String)]
+ ], batch_size: 1000, batch_delay: 1.minute)
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
index dad1efc5a8d..04d76bd1f06 100644
--- a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
@@ -11,8 +11,7 @@ RSpec.describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
let(:milestone) do
- double(
- :milestone,
+ {
number: 1,
title: '1.0',
description: 'The first release',
@@ -20,12 +19,11 @@ RSpec.describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab
due_on: due_on,
created_at: created_at,
updated_at: updated_at
- )
+ }
end
let(:milestone2) do
- double(
- :milestone,
+ {
number: 1,
title: '1.0',
description: 'The first release',
@@ -33,7 +31,7 @@ RSpec.describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab
due_on: nil,
created_at: created_at,
updated_at: updated_at
- )
+ }
end
describe '#execute' do
diff --git a/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb b/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb
new file mode 100644
index 00000000000..7d4e3c3bcce
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::NoteAttachmentsImporter do
+ subject(:importer) { described_class.new(note_text, project, client) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:note_text) { Gitlab::GithubImport::Representation::NoteText.from_db_record(record) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+
+ let(:doc_url) { 'https://github.com/nickname/public-test-repo/files/9020437/git-cheat-sheet.txt' }
+ let(:image_url) { 'https://user-images.githubusercontent.com/6833842/0cf366b61ef2.jpeg' }
+ let(:image_tag_url) { 'https://user-images.githubusercontent.com/6833842/0cf366b61ea5.jpeg' }
+ let(:text) do
+ <<-TEXT.split("\n").map(&:strip).join("\n")
+ Some text...
+
+ [special-doc](#{doc_url})
+ ![image.jpeg](#{image_url})
+ <img width=\"248\" alt=\"tag-image\" src="#{image_tag_url}">
+ TEXT
+ end
+
+ shared_examples 'updates record description' do
+ it do
+ importer.execute
+
+ record.reload
+ expect(record.description).to start_with("Some text...\n\n[special-doc](/uploads/")
+ expect(record.description).to include('![image.jpeg](/uploads/')
+ expect(record.description).to include('<img width="248" alt="tag-image" src="/uploads')
+ end
+ end
+
+ describe '#execute' do
+ let(:downloader_stub) { instance_double(Gitlab::GithubImport::AttachmentsDownloader) }
+ let(:tmp_stub_doc) { Tempfile.create('attachment_download_test.txt') }
+ let(:tmp_stub_image) { Tempfile.create('image.jpeg') }
+ let(:tmp_stub_image_tag) { Tempfile.create('image-tag.jpeg') }
+
+ before do
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(doc_url)
+ .and_return(downloader_stub)
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_url)
+ .and_return(downloader_stub)
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_tag_url)
+ .and_return(downloader_stub)
+ allow(downloader_stub).to receive(:perform).and_return(tmp_stub_doc, tmp_stub_image, tmp_stub_image_tag)
+ allow(downloader_stub).to receive(:delete).exactly(3).times
+ end
+
+ context 'when importing release attachments' do
+ let(:record) { create(:release, project: project, description: text) }
+
+ it_behaves_like 'updates record description'
+ end
+
+ context 'when importing issue attachments' do
+ let(:record) { create(:issue, project: project, description: text) }
+
+ it_behaves_like 'updates record description'
+ end
+
+ context 'when importing merge request attachments' do
+ let(:record) { create(:merge_request, source_project: project, description: text) }
+
+ it_behaves_like 'updates record description'
+ end
+
+ context 'when importing note attachments' do
+ let(:record) { create(:note, project: project, note: text) }
+
+ it 'updates note text with new attachment urls' do
+ importer.execute
+
+ record.reload
+ expect(record.note).to start_with("Some text...\n\n[special-doc](/uploads/")
+ expect(record.note).to include('![image.jpeg](/uploads/')
+ expect(record.note).to include('<img width="248" alt="tag-image" src="/uploads')
+ 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 165f543525d..c60ecd85e92 100644
--- a/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
@@ -160,6 +160,13 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
expect(project.notes.take).to be_valid
end
+
+ # rubocop:disable RSpec/AnyInstanceOf
+ it 'skips markdown field cache callback' do
+ expect_any_instance_of(Note).not_to receive(:refresh_markdown_cache)
+ importer.execute
+ end
+ # rubocop:enable RSpec/AnyInstanceOf
end
describe '#find_noteable_id' do
diff --git a/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
index 3b4fe652da8..ca4560b6a1a 100644
--- a/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
@@ -7,15 +7,14 @@ RSpec.describe Gitlab::GithubImport::Importer::NotesImporter do
let(:client) { double(:client) }
let(:github_comment) do
- double(
- :response,
+ {
html_url: 'https://github.com/foo/bar/issues/42',
- user: double(:user, id: 4, login: 'alice'),
+ user: { id: 4, login: 'alice' },
body: 'Hello world',
created_at: Time.zone.now,
updated_at: Time.zone.now,
id: 1
- )
+ }
end
describe '#parallel?' do
@@ -84,9 +83,10 @@ RSpec.describe Gitlab::GithubImport::Importer::NotesImporter do
.to receive(:each_object_to_import)
.and_yield(github_comment)
- expect(Gitlab::GithubImport::ImportNoteWorker).to receive(:bulk_perform_in).with(1.second, [
- [project.id, an_instance_of(Hash), an_instance_of(String)]
- ], batch_size: 1000, batch_delay: 1.minute)
+ expect(Gitlab::GithubImport::ImportNoteWorker).to receive(:bulk_perform_in)
+ .with(1.second, [
+ [project.id, an_instance_of(Hash), an_instance_of(String)]
+ ], batch_size: 1000, batch_delay: 1.minute)
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/protected_branch_importer_spec.rb b/spec/lib/gitlab/github_import/importer/protected_branch_importer_spec.rb
index 6dc6db739f4..027b2ac422e 100644
--- a/spec/lib/gitlab/github_import/importer/protected_branch_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/protected_branch_importer_spec.rb
@@ -5,11 +5,21 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchImporter do
subject(:importer) { described_class.new(github_protected_branch, project, client) }
+ let(:branch_name) { 'protection' }
let(:allow_force_pushes_on_github) { true }
+ let(:required_conversation_resolution) { false }
+ let(:required_signatures) { false }
+ let(:required_pull_request_reviews) { false }
+ let(:expected_push_access_level) { Gitlab::Access::MAINTAINER }
+ let(:expected_merge_access_level) { Gitlab::Access::MAINTAINER }
+ let(:expected_allow_force_push) { true }
let(:github_protected_branch) do
Gitlab::GithubImport::Representation::ProtectedBranch.new(
- id: 'protection',
- allow_force_pushes: allow_force_pushes_on_github
+ id: branch_name,
+ allow_force_pushes: allow_force_pushes_on_github,
+ required_conversation_resolution: required_conversation_resolution,
+ required_signatures: required_signatures,
+ required_pull_request_reviews: required_pull_request_reviews
)
end
@@ -23,8 +33,8 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchImporter do
let(:expected_ruleset) do
{
name: 'protection',
- push_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }],
- merge_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }],
+ push_access_levels_attributes: [{ access_level: expected_push_access_level }],
+ merge_access_levels_attributes: [{ access_level: expected_merge_access_level }],
allow_force_push: expected_allow_force_push
}
end
@@ -47,6 +57,18 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchImporter do
end
end
+ shared_examples 'does not change project attributes' do
+ it 'does not change only_allow_merge_if_all_discussions_are_resolved' do
+ expect { importer.execute }.not_to change(project, :only_allow_merge_if_all_discussions_are_resolved)
+ end
+
+ it 'does not change push_rule for the project' do
+ expect(project).not_to receive(:push_rule)
+
+ importer.execute
+ end
+ end
+
context 'when branch is protected on GitLab' do
before do
create(
@@ -87,5 +109,193 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchImporter do
it_behaves_like 'create branch protection by the strictest ruleset'
end
+
+ context "when branch is default" do
+ before do
+ allow(project).to receive(:default_branch).and_return(branch_name)
+ end
+
+ context 'when required_conversation_resolution rule is enabled' do
+ let(:required_conversation_resolution) { true }
+
+ it 'changes project settings' do
+ expect { importer.execute }.to change(project, :only_allow_merge_if_all_discussions_are_resolved).to(true)
+ end
+ end
+
+ context 'when required_conversation_resolution rule is disabled' do
+ let(:required_conversation_resolution) { false }
+
+ it_behaves_like 'does not change project attributes'
+ end
+
+ context 'when required_signatures rule is enabled' do
+ let(:required_signatures) { true }
+ let(:push_rules_feature_available?) { true }
+
+ before do
+ stub_licensed_features(push_rules: push_rules_feature_available?)
+ end
+
+ context 'when the push_rules feature is available', if: Gitlab.ee? do
+ context 'when project push_rules did previously exist' do
+ before do
+ create(:push_rule, project: project)
+ end
+
+ it 'updates push_rule reject_unsigned_commits attribute' do
+ expect { importer.execute }.to change { project.reload.push_rule.reject_unsigned_commits }.to(true)
+ end
+ end
+
+ context 'when project push_rules did not previously exist' do
+ it 'creates project push_rule with the enabled reject_unsigned_commits attribute' do
+ expect { importer.execute }.to change(project, :push_rule).from(nil)
+ expect(project.push_rule.reject_unsigned_commits).to be_truthy
+ end
+ end
+ end
+
+ context 'when the push_rules feature is not available' do
+ let(:push_rules_feature_available?) { false }
+
+ it_behaves_like 'does not change project attributes'
+ end
+ end
+
+ context 'when required_signatures rule is disabled' do
+ let(:required_signatures) { false }
+
+ it_behaves_like 'does not change project attributes'
+ end
+ end
+
+ context 'when branch is not default' do
+ context 'when required_conversation_resolution rule is enabled' do
+ let(:required_conversation_resolution) { true }
+
+ it_behaves_like 'does not change project attributes'
+ end
+
+ context 'when required_conversation_resolution rule is disabled' do
+ let(:required_conversation_resolution) { false }
+
+ it_behaves_like 'does not change project attributes'
+ end
+
+ context 'when required_signatures rule is enabled' do
+ let(:required_signatures) { true }
+
+ it_behaves_like 'does not change project attributes'
+ end
+
+ context 'when required_signatures rule is disabled' do
+ let(:required_signatures) { false }
+
+ it_behaves_like 'does not change project attributes'
+ end
+ end
+
+ context 'when required_pull_request_reviews rule is enabled on GitHub' do
+ let(:required_pull_request_reviews) { true }
+ let(:expected_push_access_level) { Gitlab::Access::NO_ACCESS }
+ let(:expected_merge_access_level) { Gitlab::Access::MAINTAINER }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+
+ context 'when required_pull_request_reviews rule is disabled on GitHub' do
+ let(:required_pull_request_reviews) { false }
+
+ context 'when branch is default' do
+ before do
+ allow(project).to receive(:default_branch).and_return(branch_name)
+ end
+
+ context 'when default branch protection = Gitlab::Access::PROTECTION_DEV_CAN_PUSH' do
+ before do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
+ end
+
+ let(:expected_push_access_level) { Gitlab::Access::DEVELOPER }
+ let(:expected_merge_access_level) { Gitlab::Access::MAINTAINER }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+
+ context 'when default branch protection = Gitlab::Access::PROTECTION_DEV_CAN_MERGE' do
+ before do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+ end
+
+ let(:expected_push_access_level) { Gitlab::Access::MAINTAINER }
+ let(:expected_merge_access_level) { Gitlab::Access::DEVELOPER }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+ end
+
+ context 'when branch is protected on GitLab' do
+ let(:protected_branch) do
+ create(
+ :protected_branch,
+ project: project,
+ name: 'protect*',
+ allow_force_push: true
+ )
+ end
+
+ let(:push_access_level) { protected_branch.push_access_levels.first }
+ let(:merge_access_level) { protected_branch.merge_access_levels.first }
+
+ context 'when there is branch protection rule for the role' do
+ context 'when No one can merge' do
+ before do
+ merge_access_level.update_column(:access_level, Gitlab::Access::NO_ACCESS)
+ end
+
+ let(:expected_push_access_level) { push_access_level.access_level }
+ let(:expected_merge_access_level) { Gitlab::Access::NO_ACCESS }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+
+ context 'when Maintainers and Developers can merge' do
+ before do
+ merge_access_level.update_column(:access_level, Gitlab::Access::DEVELOPER)
+ end
+
+ let(:gitlab_push_access_level) { push_access_level.access_level }
+ let(:gitlab_merge_access_level) { merge_access_level.access_level }
+ let(:expected_push_access_level) { gitlab_push_access_level }
+ let(:expected_merge_access_level) { [gitlab_merge_access_level, github_default_merge_access_level].max }
+ let(:github_default_merge_access_level) do
+ Gitlab::GithubImport::Importer::ProtectedBranchImporter::GITHUB_DEFAULT_MERGE_ACCESS_LEVEL
+ end
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+ end
+
+ context 'when there is no branch protection rule for the role' do
+ before do
+ push_access_level.update_column(:user_id, project.owner.id)
+ merge_access_level.update_column(:user_id, project.owner.id)
+ end
+
+ let(:expected_push_access_level) { ProtectedBranch::PushAccessLevel::GITLAB_DEFAULT_ACCESS_LEVEL }
+ let(:expected_merge_access_level) { Gitlab::Access::MAINTAINER }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+ end
+
+ context 'when branch is neither default nor protected on GitLab' do
+ let(:expected_push_access_level) { ProtectedBranch::PushAccessLevel::GITLAB_DEFAULT_ACCESS_LEVEL }
+ let(:expected_merge_access_level) { ProtectedBranch::MergeAccessLevel::GITLAB_DEFAULT_ACCESS_LEVEL }
+
+ it_behaves_like 'create branch protection by the strictest ruleset'
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb b/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
index 4e9208be985..a0ced456391 100644
--- a/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
@@ -23,11 +23,13 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter do
let(:github_protection_rule) do
response = Struct.new(:name, :url, :required_signatures, :enforce_admins, :required_linear_history,
:allow_force_pushes, :allow_deletion, :block_creations, :required_conversation_resolution,
+ :required_pull_request_reviews,
keyword_init: true
)
required_signatures = Struct.new(:url, :enabled, keyword_init: true)
enforce_admins = Struct.new(:url, :enabled, keyword_init: true)
allow_option = Struct.new(:enabled, keyword_init: true)
+ required_pull_request_reviews = Struct.new(:url, :dismissal_restrictions, keyword_init: true)
response.new(
name: 'main',
url: 'https://example.com/branches/main/protection',
@@ -53,6 +55,10 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter do
),
required_conversation_resolution: allow_option.new(
enabled: false
+ ),
+ required_pull_request_reviews: required_pull_request_reviews.new(
+ url: 'https://example.com/branches/main/protection/required_pull_request_reviews',
+ dismissal_restrictions: {}
)
)
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
index 016f6e5377b..f3a9bbac785 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
@@ -7,15 +7,16 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestMergedByImporter, :cle
let(:project) { merge_request.project }
let(:merged_at) { Time.new(2017, 1, 1, 12, 00).utc }
- let(:client_double) { double(user: double(id: 999, login: 'merger', email: 'merger@email.com')) }
- let(:merger_user) { double(id: 999, login: 'merger') }
+ let(:client_double) { double(user: { id: 999, login: 'merger', email: 'merger@email.com' } ) }
+ let(:merger_user) { { id: 999, login: 'merger' } }
let(:pull_request) do
- instance_double(
- Gitlab::GithubImport::Representation::PullRequest,
- iid: merge_request.iid,
- merged_at: merged_at,
- merged_by: merger_user
+ Gitlab::GithubImport::Representation::PullRequest.from_api_response(
+ {
+ number: merge_request.iid,
+ merged_at: merged_at,
+ merged_by: merger_user
+ }
)
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
index a6da40f47f1..fb6024d0952 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestReviewImporter, :clean
let_it_be(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
- let(:client_double) { double(user: double(id: 999, login: 'author', email: 'author@email.com')) }
+ let(:client_double) { double(user: { id: 999, login: 'author', email: 'author@email.com' }) }
let(:submitted_at) { Time.new(2017, 1, 1, 12, 00).utc }
subject { described_class.new(review, project, client_double) }
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
index c5846fa7a87..aa92abdb110 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
@@ -8,33 +8,30 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
let(:client) { double(:client) }
let(:pull_request) do
- double(
- :response,
+ {
number: 42,
title: 'My Pull Request',
body: 'This is my pull request',
state: 'closed',
- head: double(
- :head,
+ head: {
sha: '123abc',
ref: 'my-feature',
- repo: double(:repo, id: 400),
- user: double(:user, id: 4, login: 'alice')
- ),
- base: double(
- :base,
+ repo: { id: 400 },
+ user: { id: 4, login: 'alice' }
+ },
+ base: {
sha: '456def',
ref: 'master',
- repo: double(:repo, id: 200)
- ),
- milestone: double(:milestone, number: 4),
- user: double(:user, id: 4, login: 'alice'),
- assignee: double(:user, id: 4, login: 'alice'),
- merged_by: double(:user, id: 4, login: 'alice'),
+ repo: { id: 200 }
+ },
+ milestone: { number: 4 },
+ user: { id: 4, login: 'alice' },
+ assignee: { id: 4, login: 'alice' },
+ merged_by: { id: 4, login: 'alice' },
created_at: 1.second.ago,
updated_at: 1.second.ago,
merged_at: 1.second.ago
- )
+ }
end
describe '#parallel?' do
@@ -184,12 +181,11 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
context 'when the pull request was updated after the last update' do
let(:pr) do
- double(
- :pr,
+ {
updated_at: Time.zone.now,
- head: double(:head, sha: '123'),
- base: double(:base, sha: '456')
- )
+ head: { sha: '123' },
+ base: { sha: '456' }
+ }
end
before do
@@ -201,7 +197,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
it 'returns true when the head SHA is not present' do
expect(importer)
.to receive(:commit_exists?)
- .with(pr.head.sha)
+ .with('123')
.and_return(false)
expect(importer.update_repository?(pr)).to eq(true)
@@ -210,12 +206,12 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
it 'returns true when the base SHA is not present' do
expect(importer)
.to receive(:commit_exists?)
- .with(pr.head.sha)
+ .with('123')
.and_return(true)
expect(importer)
.to receive(:commit_exists?)
- .with(pr.base.sha)
+ .with('456')
.and_return(false)
expect(importer.update_repository?(pr)).to eq(true)
@@ -224,12 +220,12 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
it 'returns false if both the head and base SHAs are present' do
expect(importer)
.to receive(:commit_exists?)
- .with(pr.head.sha)
+ .with('123')
.and_return(true)
expect(importer)
.to receive(:commit_exists?)
- .with(pr.base.sha)
+ .with('456')
.and_return(true)
expect(importer.update_repository?(pr)).to eq(false)
@@ -238,7 +234,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
context 'when the pull request was updated before the last update' do
it 'returns false' do
- pr = double(:pr, updated_at: 1.year.ago)
+ pr = { updated_at: 1.year.ago }
allow(project)
.to receive(:last_repository_updated_at)
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
index 0eb86feb040..5f9c73cbfff 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
end
describe '#id_for_already_imported_cache' do
- it { expect(subject.id_for_already_imported_cache(double(id: 1))).to eq(1) }
+ it { expect(subject.id_for_already_imported_cache({ id: 1 })).to eq(1) }
end
describe '#each_object_to_import', :clean_gitlab_redis_cache do
@@ -36,15 +36,11 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
)
end
- let(:review) { double(id: 1) }
+ let(:review) { { id: 1 } }
it 'fetches the pull requests reviews data' do
page = double(objects: [review], number: 1)
- expect(review)
- .to receive(:merge_request_id=)
- .with(merge_request.id)
-
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
@@ -55,6 +51,8 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
.to yield_with_args(review)
subject.each_object_to_import {}
+
+ expect(review[:merge_request_id]).to eq(merge_request.id)
end
it 'skips cached pages' do
diff --git a/spec/lib/gitlab/github_import/importer/release_attachments_importer_spec.rb b/spec/lib/gitlab/github_import/importer/release_attachments_importer_spec.rb
deleted file mode 100644
index 4779f9c8982..00000000000
--- a/spec/lib/gitlab/github_import/importer/release_attachments_importer_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::GithubImport::Importer::ReleaseAttachmentsImporter do
- subject(:importer) { described_class.new(release_attachments, project, client) }
-
- let_it_be(:project) { create(:project) }
-
- let(:client) { instance_double('Gitlab::GithubImport::Client') }
- let(:release) { create(:release, project: project, description: description) }
- let(:release_attachments) do
- Gitlab::GithubImport::Representation::ReleaseAttachments
- .from_json_hash(release_db_id: release.id, description: release.description)
- end
-
- let(:doc_url) { 'https://github.com/nickname/public-test-repo/files/9020437/git-cheat-sheet.txt' }
- let(:image_url) { 'https://user-images.githubusercontent.com/6833842/0cf366b61ef2.jpeg' }
- let(:description) do
- <<-TEXT.strip
- Some text...
-
- [special-doc](#{doc_url})
- ![image.jpeg](#{image_url})
- TEXT
- end
-
- describe '#execute' do
- let(:downloader_stub) { instance_double(Gitlab::GithubImport::AttachmentsDownloader) }
- let(:tmp_stub_doc) { Tempfile.create('attachment_download_test.txt') }
- let(:tmp_stub_image) { Tempfile.create('image.jpeg') }
-
- context 'when importing doc attachment' do
- before do
- allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(doc_url)
- .and_return(downloader_stub)
- allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_url)
- .and_return(downloader_stub)
- allow(downloader_stub).to receive(:perform).and_return(tmp_stub_doc, tmp_stub_image)
- allow(downloader_stub).to receive(:delete).twice
-
- allow(UploadService).to receive(:new)
- .with(project, tmp_stub_doc, FileUploader).and_call_original
- allow(UploadService).to receive(:new)
- .with(project, tmp_stub_image, FileUploader).and_call_original
- end
-
- it 'updates release description with new attachment url' do
- importer.execute
-
- release.reload
- expect(release.description).to start_with("Some text...\n\n [special-doc](/uploads/")
- expect(release.description).to include('![image.jpeg](/uploads/')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/github_import/importer/releases_attachments_importer_spec.rb b/spec/lib/gitlab/github_import/importer/releases_attachments_importer_spec.rb
deleted file mode 100644
index 1aeb3462cd5..00000000000
--- a/spec/lib/gitlab/github_import/importer/releases_attachments_importer_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::GithubImport::Importer::ReleasesAttachmentsImporter do
- subject { described_class.new(project, client) }
-
- let_it_be(:project) { create(:project) }
-
- let(:client) { instance_double(Gitlab::GithubImport::Client) }
-
- describe '#each_object_to_import', :clean_gitlab_redis_cache do
- let!(:release_1) { create(:release, project: project) }
- let!(:release_2) { create(:release, project: project) }
-
- it 'iterates each project release' do
- list = []
- subject.each_object_to_import do |object|
- list << object
- end
- expect(list).to contain_exactly(release_1, release_2)
- end
-
- context 'when release is already processed' do
- it "doesn't process this release" do
- subject.mark_as_imported(release_1)
-
- list = []
- subject.each_object_to_import do |object|
- list << object
- end
- expect(list).to contain_exactly(release_2)
- end
- end
- end
-
- describe '#representation_class' do
- it { expect(subject.representation_class).to eq(Gitlab::GithubImport::Representation::ReleaseAttachments) }
- end
-
- describe '#importer_class' do
- it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::ReleaseAttachmentsImporter) }
- end
-
- describe '#sidekiq_worker_class' do
- it { expect(subject.sidekiq_worker_class).to eq(Gitlab::GithubImport::ImportReleaseAttachmentsWorker) }
- end
-
- describe '#collection_method' do
- it { expect(subject.collection_method).to eq(:release_attachments) }
- end
-
- describe '#object_type' do
- it { expect(subject.object_type).to eq(:release_attachment) }
- end
-
- describe '#id_for_already_imported_cache' do
- let(:release) { build_stubbed(:release) }
-
- it { expect(subject.id_for_already_imported_cache(release)).to eq(release.id) }
- end
-
- describe '#object_representation' do
- let(:release) { build_stubbed(:release) }
-
- it 'returns release attachments representation' do
- representation = subject.object_representation(release)
-
- expect(representation.class).to eq subject.representation_class
- expect(representation.release_db_id).to eq release.id
- expect(representation.description).to eq release.description
- end
- end
-end
diff --git a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
index b0f553dbef7..84d639a09ef 100644
--- a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
@@ -10,22 +10,21 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:released_at) { Time.new(2017, 1, 1, 12, 00) }
let(:author) do
- double(
+ {
login: 'User A',
id: 1
- )
+ }
end
let(:github_release) do
- double(
- :github_release,
+ {
tag_name: '1.0',
name: github_release_name,
body: 'This is my release',
created_at: created_at,
published_at: released_at,
author: author
- )
+ }
end
def stub_email_for_github_username(user_name = 'User A', user_email = 'user@example.com')
@@ -56,7 +55,7 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
end
it 'imports draft releases' do
- release_double = double(
+ release_double = {
name: 'Test',
body: 'This is description',
tag_name: '1.0',
@@ -65,7 +64,7 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
updated_at: created_at,
published_at: nil,
author: author
- )
+ }
expect(importer).to receive(:each_release).and_return([release_double])
@@ -101,7 +100,7 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
end
it 'uses a default release description if none is provided' do
- expect(github_release).to receive(:body).and_return('')
+ github_release[:body] = nil
expect(importer).to receive(:each_release).and_return([github_release])
release = importer.build_releases.first
@@ -110,10 +109,10 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
end
it 'does not create releases that have a NULL tag' do
- null_tag_release = double(
+ null_tag_release = {
name: 'NULL Test',
tag_name: nil
- )
+ }
expect(importer).to receive(:each_release).and_return([null_tag_release])
expect(importer.build_releases).to be_empty
@@ -179,13 +178,13 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
end
it 'returns ghost user when author is empty in Github release' do
- allow(github_release).to receive(:author).and_return(nil)
+ github_release[:author] = nil
expect(release_hash[:author_id]).to eq(Gitlab::GithubImport.ghost_user_id)
end
context 'when Github author is not found in Gitlab' do
- let(:author) { double(login: 'octocat', id: 1 ) }
+ let(:author) { { login: 'octocat', id: 1 } }
before do
# Stub user email which does not match a Gitlab user.
@@ -222,11 +221,11 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
describe '#description_for' do
it 'returns the description when present' do
- expect(importer.description_for(github_release)).to eq(github_release.body)
+ expect(importer.description_for(github_release)).to eq(github_release[:body])
end
it 'returns a generated description when one is not present' do
- allow(github_release).to receive(:body).and_return('')
+ github_release[:body] = nil
expect(importer.description_for(github_release)).to eq('Release for tag 1.0')
end
diff --git a/spec/lib/gitlab/github_import/importer/single_endpoint_diff_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/single_endpoint_diff_notes_importer_spec.rb
index 471302cb31b..081d08edfb3 100644
--- a/spec/lib/gitlab/github_import/importer/single_endpoint_diff_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/single_endpoint_diff_notes_importer_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter d
it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::DiffNoteImporter) }
it { expect(subject.collection_method).to eq(:pull_request_comments) }
it { expect(subject.object_type).to eq(:diff_note) }
- it { expect(subject.id_for_already_imported_cache(double(id: 1))).to eq(1) }
+ it { expect(subject.id_for_already_imported_cache({ id: 1 })).to eq(1) }
describe '#each_object_to_import', :clean_gitlab_redis_cache do
let(:merge_request) do
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter d
)
end
- let(:note) { double(id: 1) }
+ let(:note) { { id: 1 } }
let(:page) { double(objects: [note], number: 1) }
it 'fetches data' do
diff --git a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb
index 4ed01fd7e0b..dde730d46d2 100644
--- a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
end
describe '#id_for_already_imported_cache' do
- let(:event) { instance_double('Event', id: 1) }
+ let(:event) { { id: 1 } }
it { expect(subject.id_for_already_imported_cache(event)).to eq(1) }
end
@@ -88,7 +88,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
describe '#each_object_to_import', :clean_gitlab_redis_cache do
let(:issue_event) do
struct = Struct.new(:id, :event, :created_at, :issue, keyword_init: true)
- struct.new(id: rand(10), event: 'closed', created_at: '2022-04-26 18:30:53 UTC')
+ struct.new(id: 1, event: 'closed', created_at: '2022-04-26 18:30:53 UTC')
end
let(:page) do
@@ -115,9 +115,17 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
it 'imports each issue event page by page' do
counter = 0
subject.each_object_to_import do |object|
- expect(object).to eq issue_event
- expect(issue_event.issue['number']).to eq issuable.iid
- expect(issue_event.issue['pull_request']).to eq false
+ expect(object).to eq(
+ {
+ id: 1,
+ event: 'closed',
+ created_at: '2022-04-26 18:30:53 UTC',
+ issue: {
+ number: issuable.iid,
+ pull_request: false
+ }
+ }
+ )
counter += 1
end
expect(counter).to eq 1
@@ -130,9 +138,17 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
it 'imports each merge request event page by page' do
counter = 0
subject.each_object_to_import do |object|
- expect(object).to eq issue_event
- expect(issue_event.issue['number']).to eq issuable.iid
- expect(issue_event.issue['pull_request']).to eq true
+ expect(object).to eq(
+ {
+ id: 1,
+ event: 'closed',
+ created_at: '2022-04-26 18:30:53 UTC',
+ issue: {
+ number: issuable.iid,
+ pull_request: true
+ }
+ }
+ )
counter += 1
end
expect(counter).to eq 1
diff --git a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_notes_importer_spec.rb
index d769f4fdcf5..e1f65546e1d 100644
--- a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_notes_importer_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::NoteImporter) }
it { expect(subject.collection_method).to eq(:issue_comments) }
it { expect(subject.object_type).to eq(:note) }
- it { expect(subject.id_for_already_imported_cache(double(id: 1))).to eq(1) }
+ it { expect(subject.id_for_already_imported_cache({ id: 1 })).to eq(1) }
describe '#each_object_to_import', :clean_gitlab_redis_cache do
let(:issue) do
@@ -25,7 +25,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
)
end
- let(:note) { double(id: 1) }
+ let(:note) { { id: 1 } }
let(:page) { double(objects: [note], number: 1) }
it 'fetches data' do
diff --git a/spec/lib/gitlab/github_import/importer/single_endpoint_merge_request_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/single_endpoint_merge_request_notes_importer_spec.rb
index 1dcc466d34c..5523b97acc3 100644
--- a/spec/lib/gitlab/github_import/importer/single_endpoint_merge_request_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/single_endpoint_merge_request_notes_importer_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesIm
it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::NoteImporter) }
it { expect(subject.collection_method).to eq(:issue_comments) }
it { expect(subject.object_type).to eq(:note) }
- it { expect(subject.id_for_already_imported_cache(double(id: 1))).to eq(1) }
+ it { expect(subject.id_for_already_imported_cache({ id: 1 })).to eq(1) }
describe '#each_object_to_import', :clean_gitlab_redis_cache do
let(:merge_request) do
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesIm
)
end
- let(:note) { double(id: 1) }
+ let(:note) { { id: 1 } }
let(:page) { double(objects: [note], number: 1) }
it 'fetches data' do
diff --git a/spec/lib/gitlab/github_import/issuable_finder_spec.rb b/spec/lib/gitlab/github_import/issuable_finder_spec.rb
index d550f15e8c5..d3236994cef 100644
--- a/spec/lib/gitlab/github_import/issuable_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/issuable_finder_spec.rb
@@ -3,11 +3,20 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache do
- let(:project) { double(:project, id: 4, group: nil) }
- let(:issue) do
- double(:issue, issuable_type: MergeRequest, issuable_id: 1)
+ let(:project) { double(:project, id: 4, import_data: import_data) }
+ let(:single_endpoint_optional_stage) { false }
+ let(:import_data) do
+ instance_double(
+ ProjectImportData,
+ data: {
+ optional_stages: {
+ single_endpoint_notes_import: single_endpoint_optional_stage
+ }
+ }.deep_stringify_keys
+ )
end
+ let(:issue) { double(:issue, issuable_type: MergeRequest, issuable_id: 1) }
let(:finder) { described_class.new(project, issue) }
describe '#database_id' do
@@ -28,13 +37,10 @@ RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache d
end
context 'when group is present' do
- context 'when github_importer_single_endpoint_notes_import feature flag is enabled' do
- it 'reads cache value with longer timeout' do
- project = create(:project, import_url: 'http://t0ken@github.com/user/repo.git')
- group = create(:group, projects: [project])
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: group)
+ context 'when settings single_endpoint_notes_import is enabled' do
+ let(:single_endpoint_optional_stage) { true }
+ it 'reads cache value with longer timeout' do
expect(Gitlab::Cache::Import::Caching)
.to receive(:read)
.with(anything, timeout: Gitlab::Cache::Import::Caching::LONGER_TIMEOUT)
@@ -43,12 +49,8 @@ RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache d
end
end
- context 'when github_importer_single_endpoint_notes_import feature flag is disabled' do
+ context 'when settings single_endpoint_notes_import is disabled' do
it 'reads cache value with default timeout' do
- project = double(:project, id: 4, group: create(:group))
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: false)
-
expect(Gitlab::Cache::Import::Caching)
.to receive(:read)
.with(anything, timeout: Gitlab::Cache::Import::Caching::TIMEOUT)
@@ -68,34 +70,25 @@ RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache d
finder.cache_database_id(10)
end
- context 'when group is present' do
- context 'when github_importer_single_endpoint_notes_import feature flag is enabled' do
- it 'caches value with longer timeout' do
- project = create(:project, import_url: 'http://t0ken@github.com/user/repo.git')
- group = create(:group, projects: [project])
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: group)
+ context 'when settings single_endpoint_notes_import is enabled' do
+ let(:single_endpoint_optional_stage) { true }
- expect(Gitlab::Cache::Import::Caching)
- .to receive(:write)
- .with(anything, anything, timeout: Gitlab::Cache::Import::Caching::LONGER_TIMEOUT)
+ it 'caches value with longer timeout' do
+ expect(Gitlab::Cache::Import::Caching)
+ .to receive(:write)
+ .with(anything, anything, timeout: Gitlab::Cache::Import::Caching::LONGER_TIMEOUT)
- described_class.new(project, issue).cache_database_id(10)
- end
+ described_class.new(project, issue).cache_database_id(10)
end
+ end
- context 'when github_importer_single_endpoint_notes_import feature flag is disabled' do
- it 'caches value with default timeout' do
- project = double(:project, id: 4, group: create(:group))
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: false)
-
- expect(Gitlab::Cache::Import::Caching)
- .to receive(:write)
- .with(anything, anything, timeout: Gitlab::Cache::Import::Caching::TIMEOUT)
+ context 'when settings single_endpoint_notes_import is disabled' do
+ it 'caches value with default timeout' do
+ expect(Gitlab::Cache::Import::Caching)
+ .to receive(:write)
+ .with(anything, anything, timeout: Gitlab::Cache::Import::Caching::TIMEOUT)
- described_class.new(project, issue).cache_database_id(10)
- end
+ described_class.new(project, issue).cache_database_id(10)
end
end
end
diff --git a/spec/lib/gitlab/github_import/markdown/attachment_spec.rb b/spec/lib/gitlab/github_import/markdown/attachment_spec.rb
new file mode 100644
index 00000000000..5d29de34141
--- /dev/null
+++ b/spec/lib/gitlab/github_import/markdown/attachment_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Markdown::Attachment do
+ let(:name) { FFaker::Lorem.word }
+ let(:url) { FFaker::Internet.uri('https') }
+
+ describe '.from_markdown' do
+ context "when it's a doc attachment" do
+ let(:doc_extension) { Gitlab::GithubImport::Markdown::Attachment::DOC_TYPES.sample }
+ let(:url) { "https://github.com/nickname/public-test-repo/files/3/git-cheat-sheet.#{doc_extension}" }
+ let(:name) { FFaker::Lorem.word }
+ let(:markdown_node) do
+ instance_double('CommonMarker::Node', url: url, to_plaintext: name, type: :link)
+ end
+
+ it 'returns instance with attachment info' do
+ attachment = described_class.from_markdown(markdown_node)
+
+ expect(attachment.name).to eq name
+ expect(attachment.url).to eq url
+ end
+
+ context "when type is not in whitelist" do
+ let(:doc_extension) { 'exe' }
+
+ it { expect(described_class.from_markdown(markdown_node)).to eq nil }
+ end
+
+ context 'when domain name is unknown' do
+ let(:url) do
+ "https://bitbucket.com/nickname/public-test-repo/files/3/git-cheat-sheet.#{doc_extension}"
+ end
+
+ it { expect(described_class.from_markdown(markdown_node)).to eq nil }
+ end
+ end
+
+ context "when it's an image attachment" do
+ let(:image_extension) { Gitlab::GithubImport::Markdown::Attachment::MEDIA_TYPES.sample }
+ let(:url) { "https://user-images.githubusercontent.com/1/uuid-1.#{image_extension}" }
+ let(:name) { FFaker::Lorem.word }
+ let(:markdown_node) do
+ instance_double('CommonMarker::Node', url: url, to_plaintext: name, type: :image)
+ end
+
+ it 'returns instance with attachment info' do
+ attachment = described_class.from_markdown(markdown_node)
+
+ expect(attachment.name).to eq name
+ expect(attachment.url).to eq url
+ end
+
+ context "when type is not in whitelist" do
+ let(:image_extension) { 'mkv' }
+
+ it { expect(described_class.from_markdown(markdown_node)).to eq nil }
+ end
+
+ context 'when domain name is unknown' do
+ let(:url) { "https://user-images.github.com/1/uuid-1.#{image_extension}" }
+
+ it { expect(described_class.from_markdown(markdown_node)).to eq nil }
+ end
+ end
+
+ context "when it's an inline html node" do
+ let(:name) { FFaker::Lorem.word }
+ let(:image_extension) { Gitlab::GithubImport::Markdown::Attachment::MEDIA_TYPES.sample }
+ let(:url) { "https://user-images.githubusercontent.com/1/uuid-1.#{image_extension}" }
+ let(:img) { "<img width=\"248\" alt=\"#{name}\" src=\"#{url}\">" }
+ let(:markdown_node) do
+ instance_double('CommonMarker::Node', string_content: img, type: :inline_html)
+ end
+
+ it 'returns instance with attachment info' do
+ attachment = described_class.from_markdown(markdown_node)
+
+ expect(attachment.name).to eq name
+ expect(attachment.url).to eq url
+ end
+ end
+ end
+
+ describe '#inspect' do
+ it 'returns attachment basic info' do
+ attachment = described_class.new(name, url)
+
+ expect(attachment.inspect).to eq "<Gitlab::GithubImport::Markdown::Attachment: { name: #{name}, url: #{url} }>"
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/markdown_text_spec.rb b/spec/lib/gitlab/github_import/markdown_text_spec.rb
index 1da6bb06403..3f771970588 100644
--- a/spec/lib/gitlab/github_import/markdown_text_spec.rb
+++ b/spec/lib/gitlab/github_import/markdown_text_spec.rb
@@ -60,31 +60,48 @@ RSpec.describe Gitlab::GithubImport::MarkdownText do
end
end
- describe '.fetch_attachment_urls' do
- let(:image_extension) { described_class::MEDIA_TYPES.sample }
+ describe '.fetch_attachments' do
+ let(:image_extension) { Gitlab::GithubImport::Markdown::Attachment::MEDIA_TYPES.sample }
let(:image_attachment) do
- "![special-image](https://user-images.githubusercontent.com/6833862/"\
- "176685788-e7a93168-7ded-406a-82b5-eb1c56685a93.#{image_extension})"
+ "![special-image](https://user-images.githubusercontent.com/1/uuid-1.#{image_extension})"
end
- let(:doc_extension) { described_class::DOC_TYPES.sample }
+ let(:img_tag_attachment) do
+ "<img width=\"248\" alt=\"tag-image\" src=\"https://user-images.githubusercontent.com/2/"\
+ "uuid-2.#{image_extension}\">"
+ end
+
+ let(:damaged_img_tag) do
+ "<img width=\"248\" alt=\"tag-image\" src=\"https://user-images.githubusercontent.com"
+ end
+
+ let(:doc_extension) { Gitlab::GithubImport::Markdown::Attachment::DOC_TYPES.sample }
let(:doc_attachment) do
"[some-doc](https://github.com/nickname/public-test-repo/"\
- "files/9020437/git-cheat-sheet.#{doc_extension})"
+ "files/3/git-cheat-sheet.#{doc_extension})"
end
let(:text) do
- <<-TEXT
+ <<-TEXT.split("\n").map(&:strip).join("\n")
Comment with an attachment
#{image_attachment}
#{FFaker::Lorem.sentence}
#{doc_attachment}
+ #{damaged_img_tag}
+ #{FFaker::Lorem.paragraph}
+ #{img_tag_attachment}
TEXT
end
- it 'fetches attachment urls' do
- expect(described_class.fetch_attachment_urls(text))
- .to contain_exactly(image_attachment, doc_attachment)
+ it 'fetches attachments' do
+ attachments = described_class.fetch_attachments(text)
+
+ expect(attachments.map(&:name)).to contain_exactly('special-image', 'tag-image', 'some-doc')
+ expect(attachments.map(&:url)).to contain_exactly(
+ "https://user-images.githubusercontent.com/1/uuid-1.#{image_extension}",
+ "https://user-images.githubusercontent.com/2/uuid-2.#{image_extension}",
+ "https://github.com/nickname/public-test-repo/files/3/git-cheat-sheet.#{doc_extension}"
+ )
end
end
diff --git a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
index 860bb60f3ed..cefad3baa31 100644
--- a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
@@ -295,11 +295,12 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
end
it 'imports data in parallel batches with delays' do
- expect(worker_class).to receive(:bulk_perform_in).with(1.second, [
- [project.id, { title: 'Foo' }, an_instance_of(String)],
- [project.id, { title: 'Foo' }, an_instance_of(String)],
- [project.id, { title: 'Foo' }, an_instance_of(String)]
- ], batch_size: batch_size, batch_delay: batch_delay)
+ expect(worker_class).to receive(:bulk_perform_in)
+ .with(1.second, [
+ [project.id, { title: 'Foo' }, an_instance_of(String)],
+ [project.id, { title: 'Foo' }, an_instance_of(String)],
+ [project.id, { title: 'Foo' }, an_instance_of(String)]
+ ], batch_size: batch_size, batch_delay: batch_delay)
importer.parallel_import
end
@@ -308,7 +309,8 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
describe '#each_object_to_import' do
let(:importer) { importer_class.new(project, client) }
- let(:object) { double(:object) }
+ let(:object) { {} }
+ let(:object_counter_class) { Gitlab::GithubImport::ObjectCounter }
before do
expect(importer)
@@ -334,6 +336,9 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
.with(object)
.and_return(false)
+ expect(object_counter_class)
+ .to receive(:increment)
+
expect(importer)
.to receive(:mark_as_imported)
.with(object)
@@ -364,6 +369,9 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
.with(object)
.and_return(false)
+ expect(object_counter_class)
+ .to receive(:increment)
+
expect(importer)
.to receive(:mark_as_imported)
.with(object)
@@ -407,6 +415,9 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
.with(object)
.and_return(true)
+ expect(object_counter_class)
+ .not_to receive(:increment)
+
expect(importer)
.not_to receive(:mark_as_imported)
@@ -463,4 +474,13 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
importer.mark_as_imported(object)
end
end
+
+ describe '#increment_object_counter?' do
+ let(:github_issue) { {} }
+ let(:importer) { importer_class.new(project, client) }
+
+ it 'returns true' do
+ expect(importer).to be_increment_object_counter(github_issue)
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
index fe3040c102b..a656cd0d056 100644
--- a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
let(:start_line) { nil }
let(:end_line) { 23 }
let(:note_body) { 'Hello world' }
- let(:user_data) { { 'id' => 4, 'login' => 'alice' } }
+ let(:user_data) { { id: 4, login: 'alice' } }
let(:side) { 'RIGHT' }
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
@@ -275,15 +275,14 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
describe '.from_api_response' do
it_behaves_like 'a DiffNote representation' do
let(:response) do
- double(
- :response,
+ {
id: note_id,
html_url: 'https://github.com/foo/bar/pull/42',
path: 'README.md',
commit_id: '123abc',
original_commit_id: 'original123abc',
side: side,
- user: user_data && double(:user, user_data),
+ user: user_data,
diff_hunk: hunk,
body: note_body,
created_at: created_at,
@@ -291,7 +290,7 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_red
line: end_line,
start_line: start_line,
in_reply_to_id: in_reply_to_id
- )
+ }
end
subject(:note) { described_class.from_api_response(response) }
diff --git a/spec/lib/gitlab/github_import/representation/issue_event_spec.rb b/spec/lib/gitlab/github_import/representation/issue_event_spec.rb
index 0256858ecf1..0dd281cb3b0 100644
--- a/spec/lib/gitlab/github_import/representation/issue_event_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/issue_event_spec.rb
@@ -186,7 +186,7 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
assignee: with_assignee ? user_resource.new(id: 5, login: 'tom') : nil,
requested_reviewer: with_reviewer ? user_resource.new(id: 6, login: 'mickey') : nil,
review_requester: with_reviewer ? user_resource.new(id: 7, login: 'minnie') : nil,
- issue: { 'number' => 2, 'pull_request' => pull_request },
+ issue: { number: 2, pull_request: pull_request },
created_at: '2022-04-26 18:30:53 UTC',
performed_via_github_app: nil
)
diff --git a/spec/lib/gitlab/github_import/representation/issue_spec.rb b/spec/lib/gitlab/github_import/representation/issue_spec.rb
index 5898518343a..263ef8b1708 100644
--- a/spec/lib/gitlab/github_import/representation/issue_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/issue_spec.rb
@@ -74,20 +74,19 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
describe '.from_api_response' do
let(:response) do
- double(
- :response,
+ {
number: 42,
title: 'My Issue',
body: 'This is my issue',
- milestone: double(:milestone, number: 4),
+ milestone: { number: 4 },
state: 'open',
- assignees: [double(:user, id: 4, login: 'alice')],
- labels: [double(:label, name: 'bug')],
- user: double(:user, id: 4, login: 'alice'),
+ assignees: [{ id: 4, login: 'alice' }],
+ labels: [{ name: 'bug' }],
+ user: { id: 4, login: 'alice' },
created_at: created_at,
updated_at: updated_at,
pull_request: false
- )
+ }
end
let(:additional_data) { { work_item_type_id: work_item_type_id } }
@@ -97,9 +96,7 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
end
it 'does not set the user if the response did not include a user' do
- allow(response)
- .to receive(:user)
- .and_return(nil)
+ response[:user] = nil
issue = described_class.from_api_response(response, additional_data)
diff --git a/spec/lib/gitlab/github_import/representation/note_spec.rb b/spec/lib/gitlab/github_import/representation/note_spec.rb
index 9f416eb3c02..49126dbe9c5 100644
--- a/spec/lib/gitlab/github_import/representation/note_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/note_spec.rb
@@ -48,15 +48,14 @@ RSpec.describe Gitlab::GithubImport::Representation::Note do
describe '.from_api_response' do
let(:response) do
- double(
- :response,
+ {
html_url: 'https://github.com/foo/bar/issues/42',
- user: double(:user, id: 4, login: 'alice'),
+ user: { id: 4, login: 'alice' },
body: 'Hello world',
created_at: created_at,
updated_at: updated_at,
id: 1
- )
+ }
end
it_behaves_like 'a Note' do
@@ -64,9 +63,7 @@ RSpec.describe Gitlab::GithubImport::Representation::Note do
end
it 'does not set the user if the response did not include a user' do
- allow(response)
- .to receive(:user)
- .and_return(nil)
+ response[:user] = nil
note = described_class.from_api_response(response)
diff --git a/spec/lib/gitlab/github_import/representation/note_text_spec.rb b/spec/lib/gitlab/github_import/representation/note_text_spec.rb
new file mode 100644
index 00000000000..8b57c9a0373
--- /dev/null
+++ b/spec/lib/gitlab/github_import/representation/note_text_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Representation::NoteText do
+ shared_examples 'a Note text data' do |match_record_type|
+ it 'returns an instance of NoteText' do
+ expect(representation).to be_an_instance_of(described_class)
+ end
+
+ it 'includes record DB id' do
+ expect(representation.record_db_id).to eq 42
+ end
+
+ it 'includes record type' do
+ expect(representation.record_type).to eq match_record_type
+ end
+
+ it 'includes note text' do
+ expect(representation.text).to eq 'Some text here..'
+ end
+ end
+
+ describe '.from_db_record' do
+ context 'with Release' do
+ let(:record) { build_stubbed(:release, id: 42, description: 'Some text here..') }
+
+ it_behaves_like 'a Note text data', 'Release' do
+ let(:representation) { described_class.from_db_record(record) }
+ end
+ end
+
+ context 'with Issue' do
+ let(:record) { build_stubbed(:issue, id: 42, description: 'Some text here..') }
+
+ it_behaves_like 'a Note text data', 'Issue' do
+ let(:representation) { described_class.from_db_record(record) }
+ end
+ end
+
+ context 'with MergeRequest' do
+ let(:record) { build_stubbed(:merge_request, id: 42, description: 'Some text here..') }
+
+ it_behaves_like 'a Note text data', 'MergeRequest' do
+ let(:representation) { described_class.from_db_record(record) }
+ end
+ end
+
+ context 'with Note' do
+ let(:record) { build_stubbed(:note, id: 42, note: 'Some text here..') }
+
+ it_behaves_like 'a Note text data', 'Note' do
+ let(:representation) { described_class.from_db_record(record) }
+ end
+ end
+ end
+
+ describe '.from_json_hash' do
+ it_behaves_like 'a Note text data', 'Release' do
+ let(:hash) do
+ {
+ 'record_db_id' => 42,
+ 'record_type' => 'Release',
+ 'text' => 'Some text here..'
+ }
+ end
+
+ let(:representation) { described_class.from_json_hash(hash) }
+ end
+ end
+
+ describe '#github_identifiers' do
+ it 'returns a hash with needed identifiers' do
+ record_id = rand(100)
+ representation = described_class.new(record_db_id: record_id, text: 'text')
+
+ expect(representation.github_identifiers).to eq({ db_id: record_id })
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/representation/protected_branch_spec.rb b/spec/lib/gitlab/github_import/representation/protected_branch_spec.rb
index e762dc469c1..30b29659eee 100644
--- a/spec/lib/gitlab/github_import/representation/protected_branch_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/protected_branch_spec.rb
@@ -9,24 +9,47 @@ RSpec.describe Gitlab::GithubImport::Representation::ProtectedBranch do
end
context 'with ProtectedBranch' do
- it 'includes the protected branch ID (name)' do
+ it 'includes the protected branch ID (name) attribute' do
expect(protected_branch.id).to eq 'main'
end
- it 'includes the protected branch allow_force_pushes' do
+ it 'includes the protected branch allow_force_pushes attribute' do
expect(protected_branch.allow_force_pushes).to eq true
end
+
+ it 'includes the protected branch required_conversation_resolution attribute' do
+ expect(protected_branch.required_conversation_resolution).to eq true
+ end
+
+ it 'includes the protected branch required_pull_request_reviews' do
+ expect(protected_branch.required_pull_request_reviews).to eq true
+ end
end
end
describe '.from_api_response' do
let(:response) do
- response = Struct.new(:url, :allow_force_pushes, keyword_init: true)
- allow_force_pushes = Struct.new(:enabled, keyword_init: true)
+ response = Struct.new(
+ :url, :allow_force_pushes, :required_conversation_resolution, :required_signatures,
+ :required_pull_request_reviews,
+ keyword_init: true
+ )
+ enabled_setting = Struct.new(:enabled, keyword_init: true)
+ required_pull_request_reviews = Struct.new(:url, :dismissal_restrictions, keyword_init: true)
response.new(
url: 'https://example.com/branches/main/protection',
- allow_force_pushes: allow_force_pushes.new(
+ allow_force_pushes: enabled_setting.new(
+ enabled: true
+ ),
+ required_conversation_resolution: enabled_setting.new(
+ enabled: true
+ ),
+ required_signatures: enabled_setting.new(
enabled: true
+ ),
+ required_pull_request_reviews: required_pull_request_reviews.new(
+ url: 'https://example.com/branches/main/protection/required_pull_request_reviews',
+ dismissal_restrictions: {}
)
)
end
@@ -41,7 +64,10 @@ RSpec.describe Gitlab::GithubImport::Representation::ProtectedBranch do
let(:hash) do
{
'id' => 'main',
- 'allow_force_pushes' => true
+ 'allow_force_pushes' => true,
+ 'required_conversation_resolution' => true,
+ 'required_signatures' => true,
+ 'required_pull_request_reviews' => true
}
end
diff --git a/spec/lib/gitlab/github_import/representation/pull_request_review_spec.rb b/spec/lib/gitlab/github_import/representation/pull_request_review_spec.rb
index d6e7a8172f7..0203da9f4fb 100644
--- a/spec/lib/gitlab/github_import/representation/pull_request_review_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/pull_request_review_spec.rb
@@ -21,15 +21,14 @@ RSpec.describe Gitlab::GithubImport::Representation::PullRequestReview do
describe '.from_api_response' do
let(:response) do
- double(
- :response,
+ {
id: 999,
merge_request_id: 42,
body: 'note',
state: 'APPROVED',
- user: double(:user, id: 4, login: 'alice'),
+ user: { id: 4, login: 'alice' },
submitted_at: submitted_at
- )
+ }
end
it_behaves_like 'a PullRequest review' do
@@ -37,9 +36,7 @@ RSpec.describe Gitlab::GithubImport::Representation::PullRequestReview do
end
it 'does not set the user if the response did not include a user' do
- allow(response)
- .to receive(:user)
- .and_return(nil)
+ response[:user] = nil
review = described_class.from_api_response(response)
diff --git a/spec/lib/gitlab/github_import/representation/pull_request_spec.rb b/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
index deb9535a845..b8c1c67e07c 100644
--- a/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/pull_request_spec.rb
@@ -93,33 +93,30 @@ RSpec.describe Gitlab::GithubImport::Representation::PullRequest do
describe '.from_api_response' do
let(:response) do
- double(
- :response,
+ {
number: 42,
title: 'My Pull Request',
body: 'This is my pull request',
state: 'closed',
- head: double(
- :head,
+ head: {
sha: '123abc',
ref: 'my-feature',
- repo: double(:repo, id: 400),
- user: double(:user, id: 4, login: 'alice')
- ),
- base: double(
- :base,
+ repo: { id: 400 },
+ user: { id: 4, login: 'alice' }
+ },
+ base: {
sha: '456def',
ref: 'master',
- repo: double(:repo, id: 200)
- ),
- milestone: double(:milestone, number: 4),
- user: double(:user, id: 4, login: 'alice'),
- assignee: double(:user, id: 4, login: 'alice'),
- merged_by: double(:user, id: 4, login: 'alice'),
+ repo: { id: 200 }
+ },
+ milestone: { number: 4 },
+ user: { id: 4, login: 'alice' },
+ assignee: { id: 4, login: 'alice' },
+ merged_by: { id: 4, login: 'alice' },
created_at: created_at,
updated_at: updated_at,
merged_at: merged_at
- )
+ }
end
it_behaves_like 'a PullRequest' do
@@ -127,9 +124,7 @@ RSpec.describe Gitlab::GithubImport::Representation::PullRequest do
end
it 'does not set the user if the response did not include a user' do
- allow(response)
- .to receive(:user)
- .and_return(nil)
+ response[:user] = nil
pr = described_class.from_api_response(response)
diff --git a/spec/lib/gitlab/github_import/representation/release_attachments_spec.rb b/spec/lib/gitlab/github_import/representation/release_attachments_spec.rb
deleted file mode 100644
index 0ef9dad6a13..00000000000
--- a/spec/lib/gitlab/github_import/representation/release_attachments_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::GithubImport::Representation::ReleaseAttachments do
- shared_examples 'a Release attachments data' do
- it 'returns an instance of ReleaseAttachments' do
- expect(representation).to be_an_instance_of(described_class)
- end
-
- it 'includes release DB id' do
- expect(representation.release_db_id).to eq 42
- end
-
- it 'includes release description' do
- expect(representation.description).to eq 'Some text here..'
- end
- end
-
- describe '.from_db_record' do
- let(:release) { build_stubbed(:release, id: 42, description: 'Some text here..') }
-
- it_behaves_like 'a Release attachments data' do
- let(:representation) { described_class.from_db_record(release) }
- end
- end
-
- describe '.from_json_hash' do
- it_behaves_like 'a Release attachments data' do
- let(:hash) do
- {
- 'release_db_id' => 42,
- 'description' => 'Some text here..'
- }
- end
-
- let(:representation) { described_class.from_json_hash(hash) }
- end
- end
-
- describe '#github_identifiers' do
- it 'returns a hash with needed identifiers' do
- release_id = rand(100)
- representation = described_class.new(release_db_id: release_id, description: 'text')
-
- expect(representation.github_identifiers).to eq({ db_id: release_id })
- end
- end
-end
diff --git a/spec/lib/gitlab/github_import/representation/user_spec.rb b/spec/lib/gitlab/github_import/representation/user_spec.rb
index d7219556ada..ccada558f8b 100644
--- a/spec/lib/gitlab/github_import/representation/user_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/user_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::GithubImport::Representation::User do
describe '.from_api_response' do
it_behaves_like 'a User' do
- let(:response) { double(:response, id: 42, login: 'alice') }
+ let(:response) { { id: 42, login: 'alice' } }
let(:user) { described_class.from_api_response(response) }
end
end
diff --git a/spec/lib/gitlab/github_import/settings_spec.rb b/spec/lib/gitlab/github_import/settings_spec.rb
new file mode 100644
index 00000000000..ad0c47e8e8a
--- /dev/null
+++ b/spec/lib/gitlab/github_import/settings_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Settings do
+ subject(:settings) { described_class.new(project) }
+
+ let_it_be(:project) { create(:project) }
+
+ let(:optional_stages) do
+ {
+ single_endpoint_issue_events_import: true,
+ single_endpoint_notes_import: false,
+ attachments_import: false
+ }
+ end
+
+ describe '.stages_array' do
+ let(:expected_list) do
+ stages = described_class::OPTIONAL_STAGES
+ [
+ {
+ name: 'single_endpoint_issue_events_import',
+ label: stages[:single_endpoint_issue_events_import][:label],
+ details: stages[:single_endpoint_issue_events_import][:details]
+ },
+ {
+ name: 'single_endpoint_notes_import',
+ label: stages[:single_endpoint_notes_import][:label],
+ details: stages[:single_endpoint_notes_import][:details]
+ },
+ {
+ name: 'attachments_import',
+ label: stages[:attachments_import][:label].strip,
+ details: stages[:attachments_import][:details]
+ }
+ ]
+ end
+
+ it 'returns stages list as array' do
+ expect(described_class.stages_array).to match_array(expected_list)
+ end
+ end
+
+ describe '#write' do
+ let(:data_input) do
+ {
+ single_endpoint_issue_events_import: true,
+ single_endpoint_notes_import: 'false',
+ attachments_import: nil,
+ foo: :bar
+ }.stringify_keys
+ end
+
+ it 'puts optional steps flags into projects import_data' do
+ settings.write(data_input)
+
+ expect(project.import_data.data['optional_stages'])
+ .to eq optional_stages.stringify_keys
+ end
+ end
+
+ describe '#enabled?' do
+ it 'returns is enabled or not specific optional stage' do
+ project.create_or_update_import_data(data: { optional_stages: optional_stages })
+
+ expect(settings.enabled?(:single_endpoint_issue_events_import)).to eq true
+ expect(settings.enabled?(:single_endpoint_notes_import)).to eq false
+ expect(settings.enabled?(:attachments_import)).to eq false
+ end
+ end
+
+ describe '#disabled?' do
+ it 'returns is disabled or not specific optional stage' do
+ project.create_or_update_import_data(data: { optional_stages: optional_stages })
+
+ expect(settings.disabled?(:single_endpoint_issue_events_import)).to eq false
+ expect(settings.disabled?(:single_endpoint_notes_import)).to eq true
+ expect(settings.disabled?(:attachments_import)).to eq true
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/user_finder_spec.rb b/spec/lib/gitlab/github_import/user_finder_spec.rb
index 8ebbff31f64..d77aaa0e846 100644
--- a/spec/lib/gitlab/github_import/user_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/user_finder_spec.rb
@@ -17,8 +17,8 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
describe '#author_id_for' do
context 'with default author_key' do
it 'returns the user ID for the author of an object' do
- user = double(:user, id: 4, login: 'kittens')
- note = double(:note, author: user)
+ user = { id: 4, login: 'kittens' }
+ note = { author: user }
expect(finder).to receive(:user_id_for).with(user).and_return(42)
@@ -26,8 +26,8 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
it 'returns the ID of the project creator if no user ID could be found' do
- user = double(:user, id: 4, login: 'kittens')
- note = double(:note, author: user)
+ user = { id: 4, login: 'kittens' }
+ note = { author: user }
expect(finder).to receive(:user_id_for).with(user).and_return(nil)
@@ -35,7 +35,7 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
it 'returns the ID of the ghost user when the object has no user' do
- note = double(:note, author: nil)
+ note = { author: nil }
expect(finder.author_id_for(note)).to eq([User.ghost.id, true])
end
@@ -46,7 +46,7 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
context 'with a non-default author_key' do
- let(:user) { double(:user, id: 4, login: 'kittens') }
+ let(:user) { { id: 4, login: 'kittens' } }
shared_examples 'user ID finder' do |author_key|
it 'returns the user ID for an object' do
@@ -57,25 +57,25 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
context 'when the author_key parameter is :actor' do
- let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', actor: user) }
+ let(:issue_event) { { actor: user } }
it_behaves_like 'user ID finder', :actor
end
context 'when the author_key parameter is :assignee' do
- let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', assignee: user) }
+ let(:issue_event) { { assignee: user } }
it_behaves_like 'user ID finder', :assignee
end
context 'when the author_key parameter is :requested_reviewer' do
- let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', requested_reviewer: user) }
+ let(:issue_event) { { requested_reviewer: user } }
it_behaves_like 'user ID finder', :requested_reviewer
end
context 'when the author_key parameter is :review_requester' do
- let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', review_requester: user) }
+ let(:issue_event) { { review_requester: user } }
it_behaves_like 'user ID finder', :review_requester
end
@@ -84,15 +84,15 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
describe '#assignee_id_for' do
it 'returns the user ID for the assignee of an issuable' do
- user = double(:user, id: 4, login: 'kittens')
- issue = double(:issue, assignee: user)
+ user = { id: 4, login: 'kittens' }
+ issue = { assignee: user }
expect(finder).to receive(:user_id_for).with(user).and_return(42)
expect(finder.assignee_id_for(issue)).to eq(42)
end
it 'returns nil if the issuable does not have an assignee' do
- issue = double(:issue, assignee: nil)
+ issue = { assignee: nil }
expect(finder).not_to receive(:user_id_for)
expect(finder.assignee_id_for(issue)).to be_nil
@@ -101,9 +101,9 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
describe '#user_id_for' do
it 'returns the user ID for the given user' do
- user = double(:user, id: 4, login: 'kittens')
+ user = { id: 4, login: 'kittens' }
- expect(finder).to receive(:find).with(user.id, user.login).and_return(42)
+ expect(finder).to receive(:find).with(user[:id], user[:login]).and_return(42)
expect(finder.user_id_for(user)).to eq(42)
end
@@ -221,7 +221,7 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
context 'when an Email address is not cached' do
- let(:user) { double(:user, email: email) }
+ let(:user) { { email: email } }
it 'retrieves the Email address from the GitHub API' do
expect(client).to receive(:user).with('kittens').and_return(user)
@@ -251,7 +251,7 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
end
it 'shortens the timeout for Email address in cache when an Email address is private/nil from GitHub' do
- user = double(:user, email: nil)
+ user = { email: nil }
expect(client).to receive(:user).with('kittens').and_return(user)
expect(Gitlab::Cache::Import::Caching)
diff --git a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
index 5006d27c356..f14f0098a1f 100644
--- a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
+++ b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
@@ -43,10 +43,11 @@ RSpec.describe Gitlab::GrapeLogging::Formatters::LogrageWithTimestamp do
it 're-formats the params hash' do
params = result['params']
- expect(params).to eq([
- { 'key' => 'description', 'value' => '[FILTERED]' },
- { 'key' => 'name', 'value' => 'gitlab test' },
- { 'key' => 'int', 'value' => 42 }
- ])
+ expect(params).to eq(
+ [
+ { 'key' => 'description', 'value' => '[FILTERED]' },
+ { 'key' => 'name', 'value' => 'gitlab test' },
+ { 'key' => 'int', 'value' => 42 }
+ ])
end
end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index bf09e98331f..1124868bdae 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -51,6 +51,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
before do
stub_feature_flags(graphql_keyset_pagination_without_next_page_query: false)
+ allow(GitlabSchema).to receive(:default_max_page_size).and_return(2)
end
it 'invokes an extra query for the next page check' do
diff --git a/spec/lib/gitlab/health_checks/master_check_spec.rb b/spec/lib/gitlab/health_checks/master_check_spec.rb
index 8a87b01c560..5cd26f6302a 100644
--- a/spec/lib/gitlab/health_checks/master_check_spec.rb
+++ b/spec/lib/gitlab/health_checks/master_check_spec.rb
@@ -4,16 +4,14 @@ require 'fast_spec_helper'
require_relative './simple_check_shared'
RSpec.describe Gitlab::HealthChecks::MasterCheck do
- before do
- stub_const('SUCCESS_CODE', 100)
- stub_const('FAILURE_CODE', 101)
- end
-
context 'when Puma runs in Clustered mode' do
before do
allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(true)
- described_class.register_master
+ # We need to capture the read pipe here to stub out the non-blocking read.
+ # The original implementation actually forked the test suite for a more
+ # end-to-end test but that caused knock-on effects on other tests.
+ @pipe_read, _ = described_class.register_master
end
after do
@@ -25,34 +23,40 @@ RSpec.describe Gitlab::HealthChecks::MasterCheck do
end
describe '.readiness' do
- context 'when master is running' do
- it 'worker does return success' do
- _, child_status = run_worker
-
- expect(child_status.exitstatus).to eq(SUCCESS_CODE)
+ context 'when no worker registered' do
+ it 'succeeds' do
+ expect(described_class.readiness.success).to be(true)
end
end
- context 'when master finishes early' do
- before do
- described_class.send(:close_write)
+ context 'when worker registers itself' do
+ context 'when reading from pipe succeeds' do
+ it 'succeeds' do
+ expect(@pipe_read).to receive(:read_nonblock) # rubocop: disable RSpec/InstanceVariable
+
+ described_class.register_worker
+
+ expect(described_class.readiness.success).to be(true)
+ end
end
- it 'worker does return failure' do
- _, child_status = run_worker
+ context 'when read pipe is open but not ready for reading' do
+ it 'succeeds' do
+ expect(@pipe_read).to receive(:read_nonblock).and_raise(IO::EAGAINWaitReadable) # rubocop: disable RSpec/InstanceVariable
+
+ described_class.register_worker
- expect(child_status.exitstatus).to eq(FAILURE_CODE)
+ expect(described_class.readiness.success).to be(true)
+ end
end
end
- def run_worker
- pid = fork do
- described_class.register_worker
+ context 'when master finishes early' do
+ it 'fails' do
+ described_class.finish_master
- exit(described_class.readiness.success ? SUCCESS_CODE : FAILURE_CODE)
+ expect(described_class.readiness.success).to be(false)
end
-
- Process.wait2(pid)
end
end
end
diff --git a/spec/lib/gitlab/hook_data/release_builder_spec.rb b/spec/lib/gitlab/hook_data/release_builder_spec.rb
index 449965f5df1..08f9de4a2ed 100644
--- a/spec/lib/gitlab/hook_data/release_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/release_builder_spec.rb
@@ -13,12 +13,12 @@ RSpec.describe Gitlab::HookData::ReleaseBuilder do
it 'includes safe attribute' do
%w[
- id
- created_at
- description
- name
- released_at
- tag
+ id
+ created_at
+ description
+ name
+ released_at
+ tag
].each do |key|
expect(data).to include(key)
end
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
index 42cf9c54798..297fe3ade07 100644
--- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
+++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
allow_next_instance_of(ProjectExportWorker) do |job|
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
end
-
- stub_feature_flags(import_export_web_upload_stream: false)
stub_uploads_object_storage(FileUploader, enabled: false)
end
@@ -109,108 +107,68 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
end
context 'when object store is enabled' do
+ let(:object_store_url) { 'http://object-storage/project.tar.gz' }
+
before do
- object_store_url = 'http://object-storage/project.tar.gz'
stub_uploads_object_storage(FileUploader)
- stub_request(:get, object_store_url)
- stub_request(:post, example_url)
+
allow(import_export_upload.export_file).to receive(:url).and_return(object_store_url)
allow(import_export_upload.export_file).to receive(:file_storage?).and_return(false)
end
- it 'reads file using Gitlab::HttpIO and uploads to external url' do
- expect_next_instance_of(Gitlab::HttpIO) do |http_io|
- expect(http_io).to receive(:read).and_call_original
+ it 'uploads file as a remote stream' do
+ arguments = {
+ download_url: object_store_url,
+ upload_url: example_url,
+ options: {
+ upload_method: :post,
+ upload_content_type: 'application/gzip'
+ }
+ }
+
+ expect_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload, arguments) do |remote_stream_upload|
+ expect(remote_stream_upload).to receive(:execute)
end
- expect(Gitlab::ImportExport::RemoteStreamUpload).not_to receive(:new)
+ expect(Gitlab::HttpIO).not_to receive(:new)
strategy.execute(user, project)
-
- expect(a_request(:post, example_url)).to have_been_made
end
- end
-
- context 'when `import_export_web_upload_stream` feature is enabled' do
- before do
- stub_feature_flags(import_export_web_upload_stream: true)
- end
-
- context 'when remote object store is disabled' do
- it 'reads file from disk and uploads to external url' do
- stub_request(:post, example_url).to_return(status: 200)
- expect(Gitlab::ImportExport::RemoteStreamUpload).not_to receive(:new)
- expect(Gitlab::HttpIO).not_to receive(:new)
-
- strategy.execute(user, project)
-
- expect(a_request(:post, example_url)).to have_been_made
- end
- end
-
- context 'when object store is enabled' do
- let(:object_store_url) { 'http://object-storage/project.tar.gz' }
+ context 'when upload as remote stream raises an exception' do
before do
- stub_uploads_object_storage(FileUploader)
-
- allow(import_export_upload.export_file).to receive(:url).and_return(object_store_url)
- allow(import_export_upload.export_file).to receive(:file_storage?).and_return(false)
+ allow_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload) do |remote_stream_upload|
+ allow(remote_stream_upload).to receive(:execute).and_raise(
+ Gitlab::ImportExport::RemoteStreamUpload::StreamError.new('Exception error message', 'Response body')
+ )
+ end
end
- it 'uploads file as a remote stream' do
- arguments = {
- download_url: object_store_url,
- upload_url: example_url,
- options: {
- upload_method: :post,
- upload_content_type: 'application/gzip'
- }
- }
-
- expect_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload, arguments) do |remote_stream_upload|
- expect(remote_stream_upload).to receive(:execute)
+ it 'logs the exception and stores the error message' do
+ expect_next_instance_of(Gitlab::Export::Logger) do |logger|
+ expect(logger).to receive(:error).ordered.with(
+ {
+ project_id: project.id,
+ project_name: project.name,
+ message: 'Exception error message',
+ response_body: 'Response body'
+ }
+ )
+
+ expect(logger).to receive(:error).ordered.with(
+ {
+ project_id: project.id,
+ project_name: project.name,
+ message: 'After export strategy failed',
+ 'exception.class' => 'Gitlab::ImportExport::RemoteStreamUpload::StreamError',
+ 'exception.message' => 'Exception error message',
+ 'exception.backtrace' => anything
+ }
+ )
end
- expect(Gitlab::HttpIO).not_to receive(:new)
strategy.execute(user, project)
- end
- context 'when upload as remote stream raises an exception' do
- before do
- allow_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload) do |remote_stream_upload|
- allow(remote_stream_upload).to receive(:execute).and_raise(
- Gitlab::ImportExport::RemoteStreamUpload::StreamError.new('Exception error message', 'Response body')
- )
- end
- end
-
- it 'logs the exception and stores the error message' do
- expect_next_instance_of(Gitlab::Export::Logger) do |logger|
- expect(logger).to receive(:error).ordered.with(
- {
- project_id: project.id,
- project_name: project.name,
- message: 'Exception error message',
- response_body: 'Response body'
- }
- )
-
- expect(logger).to receive(:error).ordered.with(
- {
- project_id: project.id,
- project_name: project.name,
- message: 'After export strategy failed',
- 'exception.class' => 'Gitlab::ImportExport::RemoteStreamUpload::StreamError',
- 'exception.message' => 'Exception error message',
- 'exception.backtrace' => anything
- }
- )
- end
-
- strategy.execute(user, project)
-
- expect(project.import_export_shared.errors.first).to eq('Exception error message')
- end
+ expect(project.import_export_shared.errors.first).to eq('Exception error message')
end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index e270ca9ec6a..ccc4f1f7149 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -61,6 +61,8 @@ issues:
- requirement
- incident_management_issuable_escalation_status
- incident_management_timeline_events
+- incident_management_timeline_event_tags
+- incident_management_timeline_event_links
- pending_escalations
- customer_relations_contacts
- issue_customer_relations_contacts
@@ -95,6 +97,7 @@ label_links:
label:
- subscriptions
- project
+- parent_container
- lists
- label_links
- issues
@@ -296,6 +299,10 @@ ci_pipelines:
- package_build_infos
- package_file_build_infos
- build_trace_chunks
+- pipeline_metadata
+pipeline_metadata:
+- project
+- pipeline
ci_refs:
- project
- ci_pipelines
@@ -541,6 +548,7 @@ project:
- path_locks
- approver_groups
- repository_state
+- wiki_repository_state
- source_pipelines
- sourced_pipelines
- prometheus_metrics
@@ -567,6 +575,7 @@ project:
- project_registry
- packages
- package_files
+- repository_files
- packages_cleanup_policy
- alerting_setting
- project_setting
@@ -615,6 +624,7 @@ project:
- incident_management_oncall_rotations
- incident_management_escalation_policies
- incident_management_issuable_escalation_statuses
+- incident_management_timeline_event_tags
- debian_distributions
- merge_request_metrics
- security_orchestration_policy_configuration
@@ -632,6 +642,7 @@ project:
- vulnerability_reads
- build_artifacts_size_refresh
- project_callouts
+- pipeline_metadata
award_emoji:
- awardable
- user
diff --git a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
index 89ae869ae86..1444897e136 100644
--- a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
@@ -116,15 +116,15 @@ RSpec.describe Gitlab::ImportExport::Group::TreeRestorer do
shared_examples 'excluded attributes' do
excluded_attributes = %w[
- id
- parent_id
- owner_id
- created_at
- updated_at
- runners_token
- runners_token_encrypted
- saml_discovery_token
- ]
+ id
+ parent_id
+ owner_id
+ created_at
+ updated_at
+ runners_token
+ runners_token_encrypted
+ saml_discovery_token
+ ]
before do
group.add_owner(importer_user)
diff --git a/spec/lib/gitlab/import_export/group/tree_saver_spec.rb b/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
index de4d193a21c..85d07e3fe63 100644
--- a/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
@@ -51,11 +51,12 @@ RSpec.describe Gitlab::ImportExport::Group::TreeSaver do
.map { |line| Integer(line) }
expect(groups_catalog.size).to eq(3)
- expect(groups_catalog).to eq([
- group.id,
- group.descendants.first.id,
- group.descendants.first.descendants.first.id
- ])
+ expect(groups_catalog).to eq(
+ [
+ group.id,
+ group.descendants.first.id,
+ group.descendants.first.descendants.first.id
+ ])
end
it 'has a file per group' do
diff --git a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
index 52b33e22089..936c63fd6cd 100644
--- a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
context 'hook object' do
let(:relation_sym) { :hooks }
let(:id) { 999 }
- let(:service_id) { 99 }
+ let(:integration_id) { 99 }
let(:original_project_id) { 8 }
let(:token) { 'secret' }
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
'project_id' => original_project_id,
'created_at' => '2016-08-12T09:41:03.462Z',
'updated_at' => '2016-08-12T09:41:03.462Z',
- 'service_id' => service_id,
+ 'integration_id' => integration_id,
'push_events' => true,
'issues_events' => false,
'confidential_issues_events' => false,
@@ -71,8 +71,8 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
expect(created_object.id).not_to eq(id)
end
- it 'does not have the original service_id' do
- expect(created_object.service_id).not_to eq(service_id)
+ it 'does not have the original integration_id' do
+ expect(created_object.integration_id).not_to eq(integration_id)
end
it 'does not have the original project_id' do
@@ -88,10 +88,10 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
end
context 'original service exists' do
- let(:service_id) { create(:integration, project: project).id }
+ let(:integration_id) { create(:integration, project: project).id }
- it 'does not have the original service_id' do
- expect(created_object.service_id).not_to eq(service_id)
+ it 'does not have the original integration_id' do
+ expect(created_object.integration_id).not_to eq(integration_id)
end
end
@@ -302,7 +302,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
let(:relation_sym) { :hazardous_foo_model }
let(:relation_hash) do
{
- 'service_id' => 99,
+ 'integration_id' => 99,
'moved_to_id' => 99,
'namespace_id' => 99,
'ci_id' => 99,
@@ -317,7 +317,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
before do
stub_const('HazardousFooModel', Class.new(FooModel))
HazardousFooModel.class_eval do
- attr_accessor :service_id, :moved_to_id, :namespace_id, :ci_id, :random_project_id, :random_id, :milestone_id, :project_id
+ attr_accessor :integration_id, :moved_to_id, :namespace_id, :ci_id, :random_project_id, :random_id, :milestone_id, :project_id
end
allow(HazardousFooModel).to receive(:reflect_on_association).and_return(nil)
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 299e107c881..fae94a3b544 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -140,13 +140,13 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it 'restores pipelines based on ascending id order' do
expected_ordered_shas = %w[
- 2ea1f3dec713d940208fb5ce4a38765ecb5d3f73
- ce84140e8b878ce6e7c4d298c7202ff38170e3ac
- 048721d90c449b244b7b4c53a9186b04330174ec
- sha-notes
- 5f923865dde3436854e9ceb9cdb7815618d4e849
- d2d430676773caa88cdaf7c55944073b2fd5561a
- 2ea1f3dec713d940208fb5ce4a38765ecb5d3f73
+ 2ea1f3dec713d940208fb5ce4a38765ecb5d3f73
+ ce84140e8b878ce6e7c4d298c7202ff38170e3ac
+ 048721d90c449b244b7b4c53a9186b04330174ec
+ sha-notes
+ 5f923865dde3436854e9ceb9cdb7815618d4e849
+ d2d430676773caa88cdaf7c55944073b2fd5561a
+ 2ea1f3dec713d940208fb5ce4a38765ecb5d3f73
]
project = Project.find_by_path('project')
@@ -156,6 +156,15 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
end
+ it 'restores pipeline metadata' do
+ pipeline = Ci::Pipeline.find_by_sha('sha-notes')
+ pipeline_metadata = pipeline.pipeline_metadata
+
+ expect(pipeline_metadata.title).to eq('Build pipeline')
+ expect(pipeline_metadata.pipeline_id).to eq(pipeline.id)
+ expect(pipeline_metadata.project_id).to eq(pipeline.project_id)
+ end
+
it 'preserves updated_at on issues' do
issue = Issue.find_by(description: 'Aliquam enim illo et possimus.')
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index e591cbd05a0..23eb93a1bce 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -332,6 +332,11 @@ Ci::Pipeline:
- iid
- merge_request_id
- external_pull_request_id
+Ci::PipelineMetadata:
+- id
+- project_id
+- pipeline_id
+- title
Ci::Stage:
- id
- name
@@ -697,6 +702,7 @@ ProjectCiCdSetting:
- runner_token_expiration_interval
ProjectSetting:
- allow_merge_on_skipped_pipeline
+- only_allow_merge_if_all_status_checks_passed
- has_confluence
- has_shimo
- has_vulnerabilities
diff --git a/spec/lib/gitlab/import_export/uploads_manager_spec.rb b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
index 0cfe3a69a09..5fc3a70169a 100644
--- a/spec/lib/gitlab/import_export/uploads_manager_spec.rb
+++ b/spec/lib/gitlab/import_export/uploads_manager_spec.rb
@@ -78,16 +78,30 @@ RSpec.describe Gitlab::ImportExport::UploadsManager do
context 'when upload is in object storage' do
before do
stub_uploads_object_storage(FileUploader)
- allow(manager).to receive(:download_or_copy_upload).and_raise(Errno::ENAMETOOLONG)
end
- it 'ignores problematic upload and logs exception' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(Errno::ENAMETOOLONG), project_id: project.id)
+ shared_examples 'export with invalid upload' do
+ it 'ignores problematic upload and logs exception' do
+ allow(manager).to receive(:download_or_copy_upload).and_raise(exception)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(exception), project_id: project.id)
- manager.save # rubocop:disable Rails/SaveBang
+ manager.save # rubocop:disable Rails/SaveBang
- expect(shared.errors).to be_empty
- expect(File).not_to exist(exported_file_path)
+ expect(shared.errors).to be_empty
+ expect(File).not_to exist(exported_file_path)
+ end
+ end
+
+ context 'when filename is too long' do
+ let(:exception) { Errno::ENAMETOOLONG }
+
+ include_examples 'export with invalid upload'
+ end
+
+ context 'when network exception occurs' do
+ let(:exception) { Net::OpenTimeout }
+
+ include_examples 'export with invalid upload'
end
end
end
diff --git a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
index c936d2bc27d..0e6173b611f 100644
--- a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::ImportExport::WikiRepoSaver do
allow_next_instance_of(Gitlab::ImportExport) do |instance|
allow(instance).to receive(:storage_path).and_return(export_path)
end
- project_wiki.wiki
+ project_wiki.create_wiki_repository
project_wiki.create_page("index", "test content")
end
diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
index a2a482dde7c..9f654bbcd15 100644
--- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
@@ -40,11 +40,11 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
context 'with results returned' do
jira_issue = Struct.new(:id)
- let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2), jira_issue.new(3)] }
+ let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2)] }
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
- next_iid = project.issues.maximum(:iid).to_i
+ allow(Issue).to receive(:with_project_iid_supply).and_return('issue_iid')
count.times do |i|
if raise_exception_on_even_mocks && i.even?
@@ -53,16 +53,15 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
jira_issues[i],
current_user.id,
default_issue_type_id,
- { iid: next_iid + 1 }
+ { iid: 'issue_iid' }
).and_raise('Some error')
else
- next_iid += 1
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new).with(
project,
jira_issues[i],
current_user.id,
default_issue_type_id,
- { iid: next_iid }
+ { iid: 'issue_iid' }
).and_return(serializer)
end
end
@@ -125,47 +124,6 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
expect(Gitlab::JiraImport.get_issues_next_start_at(project.id)).to eq(2)
end
end
-
- context 'when number of issues is above the threshold' do
- before do
- stub_const("#{described_class.name}::JIRA_IMPORT_THRESHOLD", 2)
- stub_const("#{described_class.name}::JIRA_IMPORT_PAUSE_LIMIT", 1)
- allow(Gitlab::ErrorTracking).to receive(:track_exception)
- allow_next_instance_of(Gitlab::JobWaiter) do |job_waiter|
- allow(job_waiter).to receive(:wait).with(5).and_return(job_waiter.wait(0.1))
- end
- end
-
- it 'schedules 2 import jobs with two pause points' do
- expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1], jira_issues[2]])
- expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).exactly(3).times
- expect(Gitlab::JiraImport::ImportIssueWorker)
- .to receive(:queue_size)
- .exactly(6).times
- .and_return(1, 2, 3, 2, 1, 0)
-
- mock_issue_serializer(3)
-
- expect(subject.execute).to have_received(:wait).with(5).twice
- end
-
- it 'tracks the exception if the queue size does not reduce' do
- expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0]])
- expect(Gitlab::JiraImport::ImportIssueWorker).not_to receive(:perform_async)
- expect(Gitlab::JiraImport::ImportIssueWorker)
- .to receive(:queue_size)
- .exactly(11).times
- .and_return(3)
-
- mock_issue_serializer(1)
-
- expect(subject.execute).to have_received(:wait).with(5).exactly(10).times
- expect(Gitlab::ErrorTracking)
- .to have_received(:track_exception)
- .with(described_class::RetriesExceededError, { project_id: project.id })
- .once
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/json_spec.rb b/spec/lib/gitlab/json_spec.rb
index 7c093049e18..73276288765 100644
--- a/spec/lib/gitlab/json_spec.rb
+++ b/spec/lib/gitlab/json_spec.rb
@@ -8,6 +8,12 @@ RSpec.describe Gitlab::Json do
end
describe ".parse" do
+ it "is aliased" do
+ [:parse!, :load, :decode].each do |method|
+ expect(described_class.method(method)).to eq(described_class.method(:parse))
+ end
+ end
+
context "legacy_mode is disabled by default" do
it "parses an object" do
expect(subject.parse('{ "foo": "bar" }')).to eq({ "foo" => "bar" })
@@ -178,6 +184,10 @@ RSpec.describe Gitlab::Json do
{ test: true, "foo.bar" => "baz", is_json: 1, some: [1, 2, 3] }
end
+ it "is aliased" do
+ expect(described_class.method(:encode)).to eq(described_class.method(:generate))
+ end
+
it "generates JSON" do
expected_string = <<~STR.chomp
{"test":true,"foo.bar":"baz","is_json":1,"some":[1,2,3]}
diff --git a/spec/lib/gitlab/kubernetes/rollout_instances_spec.rb b/spec/lib/gitlab/kubernetes/rollout_instances_spec.rb
index 3ac97ddc75d..a7b2352f496 100644
--- a/spec/lib/gitlab/kubernetes/rollout_instances_spec.rb
+++ b/spec/lib/gitlab/kubernetes/rollout_instances_spec.rb
@@ -51,13 +51,14 @@ RSpec.describe Gitlab::Kubernetes::RolloutInstances do
end
it 'returns instances when there are two stable deployments' do
- deployments, pods = setup([
- kube_deployment(name: 'one', track: 'stable', replicas: 1),
- kube_deployment(name: 'two', track: 'stable', replicas: 1)
- ], [
- kube_pod(name: 'one', status: 'Running', track: 'stable'),
- kube_pod(name: 'two', status: 'Running', track: 'stable')
- ])
+ deployments, pods = setup(
+ [
+ kube_deployment(name: 'one', track: 'stable', replicas: 1),
+ kube_deployment(name: 'two', track: 'stable', replicas: 1)
+ ], [
+ kube_pod(name: 'one', status: 'Running', track: 'stable'),
+ kube_pod(name: 'two', status: 'Running', track: 'stable')
+ ])
rollout_instances = described_class.new(deployments, pods)
expect(rollout_instances.pod_instances).to eq([{
@@ -76,13 +77,14 @@ RSpec.describe Gitlab::Kubernetes::RolloutInstances do
end
it 'returns instances for two deployments with different tracks' do
- deployments, pods = setup([
- kube_deployment(name: 'one', track: 'mytrack', replicas: 1),
- kube_deployment(name: 'two', track: 'othertrack', replicas: 1)
- ], [
- kube_pod(name: 'one', status: 'Running', track: 'mytrack'),
- kube_pod(name: 'two', status: 'Running', track: 'othertrack')
- ])
+ deployments, pods = setup(
+ [
+ kube_deployment(name: 'one', track: 'mytrack', replicas: 1),
+ kube_deployment(name: 'two', track: 'othertrack', replicas: 1)
+ ], [
+ kube_pod(name: 'one', status: 'Running', track: 'mytrack'),
+ kube_pod(name: 'two', status: 'Running', track: 'othertrack')
+ ])
rollout_instances = described_class.new(deployments, pods)
expect(rollout_instances.pod_instances).to eq([{
@@ -101,13 +103,14 @@ RSpec.describe Gitlab::Kubernetes::RolloutInstances do
end
it 'sorts stable tracks after canary tracks' do
- deployments, pods = setup([
- kube_deployment(name: 'one', track: 'stable', replicas: 1),
- kube_deployment(name: 'two', track: 'canary', replicas: 1)
- ], [
- kube_pod(name: 'one', status: 'Running', track: 'stable'),
- kube_pod(name: 'two', status: 'Running', track: 'canary')
- ])
+ deployments, pods = setup(
+ [
+ kube_deployment(name: 'one', track: 'stable', replicas: 1),
+ kube_deployment(name: 'two', track: 'canary', replicas: 1)
+ ], [
+ kube_pod(name: 'one', status: 'Running', track: 'stable'),
+ kube_pod(name: 'two', status: 'Running', track: 'canary')
+ ])
rollout_instances = described_class.new(deployments, pods)
expect(rollout_instances.pod_instances).to eq([{
diff --git a/spec/lib/gitlab/legacy_github_import/branch_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/branch_formatter_spec.rb
index 1a21ed29ab7..09dd04c76c9 100644
--- a/spec/lib/gitlab/legacy_github_import/branch_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/branch_formatter_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:commit) { create(:commit, project: project) }
let(:repo) { double }
let(:raw) do
@@ -16,19 +16,19 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#exists?' do
it 'returns true when branch exists and commit is part of the branch' do
- branch = described_class.new(project, double(raw))
+ branch = described_class.new(project, raw)
expect(branch.exists?).to eq true
end
it 'returns false when branch exists and commit is not part of the branch' do
- branch = described_class.new(project, double(raw.merge(ref: 'feature')))
+ branch = described_class.new(project, raw.merge(ref: 'feature'))
expect(branch.exists?).to eq false
end
it 'returns false when branch does not exist' do
- branch = described_class.new(project, double(raw.merge(ref: 'removed-branch')))
+ branch = described_class.new(project, raw.merge(ref: 'removed-branch'))
expect(branch.exists?).to eq false
end
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#repo' do
it 'returns raw repo' do
- branch = described_class.new(project, double(raw))
+ branch = described_class.new(project, raw)
expect(branch.repo).to eq repo
end
@@ -44,7 +44,7 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#sha' do
it 'returns raw sha' do
- branch = described_class.new(project, double(raw))
+ branch = described_class.new(project, raw)
expect(branch.sha).to eq commit.id
end
@@ -52,19 +52,19 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#valid?' do
it 'returns true when raw sha and ref are present' do
- branch = described_class.new(project, double(raw))
+ branch = described_class.new(project, raw)
expect(branch.valid?).to eq true
end
it 'returns false when raw sha is blank' do
- branch = described_class.new(project, double(raw.merge(sha: nil)))
+ branch = described_class.new(project, raw.merge(sha: nil))
expect(branch.valid?).to eq false
end
it 'returns false when raw ref is blank' do
- branch = described_class.new(project, double(raw.merge(ref: nil)))
+ branch = described_class.new(project, raw.merge(ref: nil))
expect(branch.valid?).to eq false
end
diff --git a/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb
index 85f7666fe85..8d6415b8179 100644
--- a/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
+ let_it_be(:project) { create(:project) }
let(:client) { double }
- let(:project) { create(:project) }
- let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
+ let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:created_at) { DateTime.strptime('2013-04-10T20:09:31Z') }
let(:updated_at) { DateTime.strptime('2014-03-03T18:58:10Z') }
let(:base) do
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
describe '#attributes' do
context 'when do not reference a portion of the diff' do
- let(:raw) { double(base) }
+ let(:raw) { base }
it 'returns formatted attributes' do
expected = {
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
}
end
- let(:raw) { double(base.merge(diff)) }
+ let(:raw) { base.merge(diff) }
it 'returns formatted attributes' do
expected = {
@@ -74,22 +74,22 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
end
context 'when author is a GitLab user' do
- let(:raw) { double(base.merge(user: octocat)) }
+ let(:raw) { base.merge(user: octocat) }
it 'returns GitLab user id associated with GitHub id as author_id' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(comment.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns GitLab user id associated with GitHub email as author_id' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(comment.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns note without created at tag line' do
- create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(comment.attributes.fetch(:note)).to eq("I'm having a problem with this.")
end
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 1800b42160d..cd66b93eb8b 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -59,23 +59,23 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
end
let(:label1) do
- double(
+ {
name: 'Bug',
color: 'ff0000',
url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
- )
+ }
end
let(:label2) do
- double(
+ {
name: nil,
color: 'ff0000',
url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
- )
+ }
end
let(:milestone) do
- double(
+ {
id: 1347, # For Gitea
number: 1347,
state: 'open',
@@ -86,11 +86,11 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at,
closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/milestones/1"
- )
+ }
end
let(:issue1) do
- double(
+ {
number: 1347,
milestone: nil,
state: 'open',
@@ -104,12 +104,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at,
closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/issues/1347",
- labels: [double(name: 'Label #1')]
- )
+ labels: [{ name: 'Label #1' }]
+ }
end
let(:issue2) do
- double(
+ {
number: 1348,
milestone: nil,
state: 'open',
@@ -123,12 +123,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at,
closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/issues/1348",
- labels: [double(name: 'Label #2')]
- )
+ labels: [{ name: 'Label #2' }]
+ }
end
let(:release1) do
- double(
+ {
tag_name: 'v1.0.0',
name: 'First release',
body: 'Release v1.0.0',
@@ -137,11 +137,11 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
published_at: created_at,
updated_at: updated_at,
url: "#{api_root}/repos/octocat/Hello-World/releases/1"
- )
+ }
end
let(:release2) do
- double(
+ {
tag_name: 'v1.1.0',
name: 'Second release',
body: nil,
@@ -150,7 +150,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
published_at: created_at,
updated_at: updated_at,
url: "#{api_root}/repos/octocat/Hello-World/releases/2"
- )
+ }
end
subject { described_class.new(project) }
@@ -210,18 +210,18 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
end
let(:project) { create(:project, :repository, :wiki_disabled, import_url: "#{repo_root}/octocat/Hello-World.git") }
- let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
+ let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:credentials) { { user: 'joe' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
- let(:repository) { double(id: 1, fork: false) }
+ let(:repository) { { id: 1, fork: false } }
let(:source_sha) { create(:commit, project: project).id }
- let(:source_branch) { double(ref: 'branch-merged', repo: repository, sha: source_sha, user: octocat) }
+ let(:source_branch) { { ref: 'branch-merged', repo: repository, sha: source_sha, user: octocat } }
let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
- let(:target_branch) { double(ref: 'master', repo: repository, sha: target_sha, user: octocat) }
+ let(:target_branch) { { ref: 'master', repo: repository, sha: target_sha, user: octocat } }
let(:pull_request) do
- double(
+ {
number: 1347,
milestone: nil,
state: 'open',
@@ -236,12 +236,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
closed_at: nil,
merged_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/pulls/1347",
- labels: [double(name: 'Label #2')]
- )
+ labels: [{ name: 'Label #2' }]
+ }
end
let(:closed_pull_request) do
- double(
+ {
number: 1347,
milestone: nil,
state: 'closed',
@@ -256,8 +256,8 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
closed_at: updated_at,
merged_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/pulls/1347",
- labels: [double(name: 'Label #2')]
- )
+ labels: [{ name: 'Label #2' }]
+ }
end
context 'when importing a Gitea project' do
diff --git a/spec/lib/gitlab/legacy_github_import/issuable_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/issuable_formatter_spec.rb
index a285a5820a2..56a51c6bddd 100644
--- a/spec/lib/gitlab/legacy_github_import/issuable_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/issuable_formatter_spec.rb
@@ -4,7 +4,7 @@ require 'fast_spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::IssuableFormatter do
let(:raw_data) do
- double(number: 42)
+ { number: 42 }
end
let(:project) { double(import_type: 'github') }
diff --git a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
index 454bab8846c..d3548fecbcd 100644
--- a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
+ let_it_be(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
let(:client) { double }
- let!(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
- let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
+ let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
@@ -34,7 +34,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#attributes' do
context 'when issue is open' do
- let(:raw_data) { double(base_data.merge(state: 'open')) }
+ let(:raw_data) { base_data.merge(state: 'open') }
it 'returns formatted attributes' do
expected = {
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
context 'when issue is closed' do
- let(:raw_data) { double(base_data.merge(state: 'closed')) }
+ let(:raw_data) { base_data.merge(state: 'closed') }
it 'returns formatted attributes' do
expected = {
@@ -76,28 +76,28 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
context 'when it is assigned to someone' do
- let(:raw_data) { double(base_data.merge(assignee: octocat)) }
+ let(:raw_data) { base_data.merge(assignee: octocat) }
it 'returns nil as assignee_id when is not a GitLab user' do
expect(issue.attributes.fetch(:assignee_ids)).to be_empty
end
it 'returns GitLab user id associated with GitHub id as assignee_id' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id]
end
it 'returns GitLab user id associated with GitHub email as assignee_id' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id]
end
end
context 'when it has a milestone' do
- let(:milestone) { double(id: 42, number: 42) }
- let(:raw_data) { double(base_data.merge(milestone: milestone)) }
+ let(:milestone) { { id: 42, number: 42 } }
+ let(:raw_data) { base_data.merge(milestone: milestone) }
it 'returns nil when milestone does not exist' do
expect(issue.attributes.fetch(:milestone)).to be_nil
@@ -111,26 +111,26 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
context 'when author is a GitLab user' do
- let(:raw_data) { double(base_data.merge(user: octocat)) }
+ let(:raw_data) { base_data.merge(user: octocat) }
it 'returns project creator_id as author_id when is not a GitLab user' do
expect(issue.attributes.fetch(:author_id)).to eq project.creator_id
end
it 'returns GitLab user id associated with GitHub id as author_id' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns GitLab user id associated with GitHub email as author_id' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(issue.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns description without created at tag line' do
- create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:description)).to eq("I'm having a problem with this.")
end
@@ -138,7 +138,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#number' do
- let(:raw_data) { double(base_data.merge(number: 1347)) }
+ let(:raw_data) { base_data.merge(number: 1347) }
it 'returns issue number' do
expect(issue.number).to eq 1347
@@ -161,7 +161,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
describe '#has_comments?' do
context 'when number of comments is greater than zero' do
- let(:raw_data) { double(base_data.merge(comments: 1)) }
+ let(:raw_data) { base_data.merge(comments: 1) }
it 'returns true' do
expect(issue.has_comments?).to eq true
@@ -169,7 +169,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
context 'when number of comments is equal to zero' do
- let(:raw_data) { double(base_data.merge(comments: 0)) }
+ let(:raw_data) { base_data.merge(comments: 0) }
it 'returns false' do
expect(issue.has_comments?).to eq false
@@ -179,7 +179,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
describe '#pull_request?' do
context 'when mention a pull request' do
- let(:raw_data) { double(base_data.merge(pull_request: double)) }
+ let(:raw_data) { base_data.merge(pull_request: double) }
it 'returns true' do
expect(issue.pull_request?).to eq true
@@ -187,7 +187,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end
context 'when does not mention a pull request' do
- let(:raw_data) { double(base_data.merge(pull_request: nil)) }
+ let(:raw_data) { base_data.merge(pull_request: nil) }
it 'returns false' do
expect(issue.pull_request?).to eq false
diff --git a/spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb
index ab7c8ea4a58..8e2c8031a6f 100644
--- a/spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::LabelFormatter do
- let(:project) { create(:project) }
- let(:raw) { double(name: 'improvements', color: 'e6e6e6') }
+ let_it_be(:project) { create(:project) }
+ let(:raw) { { name: 'improvements', color: 'e6e6e6' } }
subject { described_class.new(project, raw) }
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::LegacyGithubImport::LabelFormatter do
context 'when label exists' do
it 'does not create a new label' do
- Labels::CreateService.new(name: raw.name).execute(project: project)
+ Labels::CreateService.new(name: raw[:name]).execute(project: project)
expect { subject.create! }.not_to change(Label, :count)
end
diff --git a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
index 64fcc46d304..7c57bf9c707 100644
--- a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:base_data) do
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
let(:data) { base_data.merge(iid_attr => 1347) }
context 'when milestone is open' do
- let(:raw_data) { double(data.merge(state: 'open')) }
+ let(:raw_data) { data.merge(state: 'open') }
it 'returns formatted attributes' do
expected = {
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
end
context 'when milestone is closed' do
- let(:raw_data) { double(data.merge(state: 'closed')) }
+ let(:raw_data) { data.merge(state: 'closed') }
it 'returns formatted attributes' do
expected = {
@@ -65,7 +65,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
context 'when milestone has a due date' do
let(:due_date) { DateTime.strptime('2011-01-28T19:01:12Z') }
- let(:raw_data) { double(data.merge(due_on: due_date)) }
+ let(:raw_data) { data.merge(due_on: due_date) }
it 'returns formatted attributes' do
expected = {
diff --git a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
index 7d8875e36c3..90469693820 100644
--- a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
@@ -3,22 +3,22 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
+ let_it_be(:project) { create(:project, :repository) }
let(:client) { double }
- let(:project) { create(:project, :repository) }
let(:source_sha) { create(:commit, project: project).id }
let(:target_commit) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit) }
let(:target_sha) { target_commit.id }
let(:target_short_sha) { target_commit.id.to_s[0..7] }
- let(:repository) { double(id: 1, fork: false) }
+ let(:repository) { { id: 1, fork: false } }
let(:source_repo) { repository }
- let(:source_branch) { double(ref: 'branch-merged', repo: source_repo, sha: source_sha) }
- let(:forked_source_repo) { double(id: 2, fork: true, name: 'otherproject', full_name: 'company/otherproject') }
+ let(:source_branch) { { ref: 'branch-merged', repo: source_repo, sha: source_sha } }
+ let(:forked_source_repo) { { id: 2, fork: true, name: 'otherproject', full_name: 'company/otherproject' } }
let(:target_repo) { repository }
- let(:target_branch) { double(ref: 'master', repo: target_repo, sha: target_sha, user: octocat) }
- let(:removed_branch) { double(ref: 'removed-branch', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) }
- let(:forked_branch) { double(ref: 'master', repo: forked_source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) }
- let(:branch_deleted_repo) { double(ref: 'master', repo: nil, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) }
- let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
+ let(:target_branch) { { ref: 'master', repo: target_repo, sha: target_sha, user: octocat } }
+ let(:removed_branch) { { ref: 'removed-branch', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
+ let(:forked_branch) { { ref: 'master', repo: forked_source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
+ let(:branch_deleted_repo) { { ref: 'master', repo: nil, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
+ let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:base_data) do
@@ -48,7 +48,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#attributes' do
context 'when pull request is open' do
- let(:raw_data) { double(base_data.merge(state: 'open')) }
+ let(:raw_data) { base_data.merge(state: 'open') }
it 'returns formatted attributes' do
expected = {
@@ -75,7 +75,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when pull request is closed' do
- let(:raw_data) { double(base_data.merge(state: 'closed')) }
+ let(:raw_data) { base_data.merge(state: 'closed') }
it 'returns formatted attributes' do
expected = {
@@ -103,7 +103,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
context 'when pull request is merged' do
let(:merged_at) { DateTime.strptime('2011-01-28T13:01:12Z') }
- let(:raw_data) { double(base_data.merge(state: 'closed', merged_at: merged_at)) }
+ let(:raw_data) { base_data.merge(state: 'closed', merged_at: merged_at) }
it 'returns formatted attributes' do
expected = {
@@ -130,54 +130,54 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when it is assigned to someone' do
- let(:raw_data) { double(base_data.merge(assignee: octocat)) }
+ let(:raw_data) { base_data.merge(assignee: octocat) }
it 'returns nil as assignee_id when is not a GitLab user' do
expect(pull_request.attributes.fetch(:assignee_id)).to be_nil
end
it 'returns GitLab user id associated with GitHub id as assignee_id' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id
end
it 'returns GitLab user id associated with GitHub email as assignee_id' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id
end
end
context 'when author is a GitLab user' do
- let(:raw_data) { double(base_data.merge(user: octocat)) }
+ let(:raw_data) { base_data.merge(user: octocat) }
it 'returns project creator_id as author_id when is not a GitLab user' do
expect(pull_request.attributes.fetch(:author_id)).to eq project.creator_id
end
it 'returns GitLab user id associated with GitHub id as author_id' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns GitLab user id associated with GitHub email as author_id' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id
end
it 'returns description without created at tag line' do
- create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:description)).to eq('Please pull these awesome changes')
end
end
context 'when it has a milestone' do
- let(:milestone) { double(id: 42, number: 42) }
- let(:raw_data) { double(base_data.merge(milestone: milestone)) }
+ let(:milestone) { { id: 42, number: 42 } }
+ let(:raw_data) { base_data.merge(milestone: milestone) }
it 'returns nil when milestone does not exist' do
expect(pull_request.attributes.fetch(:milestone)).to be_nil
@@ -192,7 +192,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#number' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns pull request number' do
expect(pull_request.number).to eq 1347
@@ -201,7 +201,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#source_branch_name' do
context 'when source branch exists' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns branch ref' do
expect(pull_request.source_branch_name).to eq 'branch-merged'
@@ -209,7 +209,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source branch does not exist' do
- let(:raw_data) { double(base_data.merge(head: removed_branch)) }
+ let(:raw_data) { base_data.merge(head: removed_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/removed-branch"
@@ -217,7 +217,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source branch is from a fork' do
- let(:raw_data) { double(base_data.merge(head: forked_branch)) }
+ let(:raw_data) { base_data.merge(head: forked_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master"
@@ -225,7 +225,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source branch is from a deleted fork' do
- let(:raw_data) { double(base_data.merge(head: branch_deleted_repo)) }
+ let(:raw_data) { base_data.merge(head: branch_deleted_repo) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master"
@@ -235,7 +235,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#target_branch_name' do
context 'when target branch exists' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns branch ref' do
expect(pull_request.target_branch_name).to eq 'master'
@@ -243,7 +243,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when target branch does not exist' do
- let(:raw_data) { double(base_data.merge(base: removed_branch)) }
+ let(:raw_data) { base_data.merge(base: removed_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.target_branch_name).to eq 'gl-2e5d3239/1347/octocat/removed-branch'
@@ -271,7 +271,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
describe '#valid?' do
context 'when source, and target repos are not a fork' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns true' do
expect(pull_request.valid?).to eq true
@@ -279,8 +279,8 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source repo is a fork' do
- let(:source_repo) { double(id: 2) }
- let(:raw_data) { double(base_data) }
+ let(:source_repo) { { id: 2 } }
+ let(:raw_data) { base_data }
it 'returns true' do
expect(pull_request.valid?).to eq true
@@ -288,8 +288,8 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when target repo is a fork' do
- let(:target_repo) { double(id: 2) }
- let(:raw_data) { double(base_data) }
+ let(:target_repo) { { id: 2 } }
+ let(:raw_data) { base_data }
it 'returns true' do
expect(pull_request.valid?).to eq true
@@ -299,7 +299,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
describe '#cross_project?' do
context 'when source and target repositories are different' do
- let(:raw_data) { double(base_data.merge(head: forked_branch)) }
+ let(:raw_data) { base_data.merge(head: forked_branch) }
it 'returns true' do
expect(pull_request.cross_project?).to eq true
@@ -307,7 +307,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source repository does not exist anymore' do
- let(:raw_data) { double(base_data.merge(head: branch_deleted_repo)) }
+ let(:raw_data) { base_data.merge(head: branch_deleted_repo) }
it 'returns true' do
expect(pull_request.cross_project?).to eq true
@@ -315,7 +315,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
context 'when source and target repositories are the same' do
- let(:raw_data) { double(base_data.merge(head: source_branch)) }
+ let(:raw_data) { base_data.merge(head: source_branch) }
it 'returns false' do
expect(pull_request.cross_project?).to eq false
@@ -324,7 +324,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
describe '#source_branch_exists?' do
- let(:raw_data) { double(base_data.merge(head: forked_branch)) }
+ let(:raw_data) { base_data.merge(head: forked_branch) }
it 'returns false when is a cross_project' do
expect(pull_request.source_branch_exists?).to eq false
@@ -332,7 +332,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
describe '#url' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'return raw url' do
expect(pull_request.url).to eq 'https://api.github.com/repos/octocat/Hello-World/pulls/1347'
@@ -340,7 +340,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end
describe '#opened?' do
- let(:raw_data) { double(base_data.merge(state: 'open')) }
+ let(:raw_data) { base_data.merge(state: 'open') }
it 'returns true when state is "open"' do
expect(pull_request.opened?).to be_truthy
diff --git a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
index cbd1a30c417..237646f81dc 100644
--- a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
- let!(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
- let(:octocat) { double(id: 123456, login: 'octocat') }
+ let_it_be(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
+ let(:octocat) { { id: 123456, login: 'octocat' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:published_at) { DateTime.strptime('2011-01-26T20:00:00Z') }
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
subject(:release) { described_class.new(project, raw_data) }
describe '#attributes' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns formatted attributes' do
expected = {
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
describe '#valid' do
context 'when release is not a draft' do
- let(:raw_data) { double(base_data) }
+ let(:raw_data) { base_data }
it 'returns true' do
expect(release.valid?).to eq true
@@ -57,7 +57,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
end
context 'when release is draft' do
- let(:raw_data) { double(base_data.merge(draft: true)) }
+ let(:raw_data) { base_data.merge(draft: true) }
it 'returns false' do
expect(release.valid?).to eq false
@@ -65,7 +65,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
end
context 'when release has NULL tag' do
- let(:raw_data) { double(base_data.merge(tag_name: '')) }
+ let(:raw_data) { base_data.merge(tag_name: '') }
it 'returns false' do
expect(release.valid?).to eq false
diff --git a/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb
index ab3ffddc042..bc127f74e84 100644
--- a/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do
let(:client) { double }
- let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
+ let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
subject(:user) { described_class.new(client, octocat) }
@@ -15,33 +15,33 @@ RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do
describe '#gitlab_id' do
context 'when GitHub user is a GitLab user' do
it 'return GitLab user id when user associated their account with GitHub' do
- gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github')
+ gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(user.gitlab_id).to eq gl_user.id
end
it 'returns GitLab user id when user confirmed primary email matches GitHub email' do
- gl_user = create(:user, email: octocat.email)
+ gl_user = create(:user, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id
end
it 'returns GitLab user id when user unconfirmed primary email matches GitHub email' do
- gl_user = create(:user, :unconfirmed, email: octocat.email)
+ gl_user = create(:user, :unconfirmed, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id
end
it 'returns GitLab user id when user confirmed secondary email matches GitHub email' do
gl_user = create(:user, email: 'johndoe@example.com')
- create(:email, :confirmed, user: gl_user, email: octocat.email)
+ create(:email, :confirmed, user: gl_user, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id
end
it 'returns nil when user unconfirmed secondary email matches GitHub email' do
gl_user = create(:user, email: 'johndoe@example.com')
- create(:email, user: gl_user, email: octocat.email)
+ create(:email, user: gl_user, email: octocat[:email])
expect(user.gitlab_id).to be_nil
end
diff --git a/spec/lib/gitlab/memory/diagnostic_reports_logger_spec.rb b/spec/lib/gitlab/memory/diagnostic_reports_logger_spec.rb
new file mode 100644
index 00000000000..6be528e34b6
--- /dev/null
+++ b/spec/lib/gitlab/memory/diagnostic_reports_logger_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Memory::DiagnosticReportsLogger do
+ subject { described_class.new('/dev/null') }
+
+ let(:now) { Time.current }
+
+ describe '#format_message' do
+ it 'formats incoming hash properly' do
+ output = subject.format_message('INFO', now, 'test', { hello: 1 })
+ # Disabling the cop because it is not relevant, we encode with `JSON.generate`. Allows `fast_spec_helper`.
+ data = JSON.parse(output) # rubocop: disable Gitlab/Json
+
+ expect(data['severity']).to eq('INFO')
+ expect(data['time']).to eq(now.utc.iso8601(3))
+ expect(data['hello']).to eq(1)
+ expect(data['message']).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/reports_daemon_spec.rb b/spec/lib/gitlab/memory/reports_daemon_spec.rb
index c9562470971..0473e170502 100644
--- a/spec/lib/gitlab/memory/reports_daemon_spec.rb
+++ b/spec/lib/gitlab/memory/reports_daemon_spec.rb
@@ -2,9 +2,15 @@
require 'spec_helper'
-RSpec.describe Gitlab::Memory::ReportsDaemon do
+RSpec.describe Gitlab::Memory::ReportsDaemon, :aggregate_failures do
let(:daemon) { described_class.new }
+ let_it_be(:tmp_dir) { Dir.mktmpdir }
+
+ after(:all) do
+ FileUtils.remove_entry(tmp_dir)
+ end
+
describe '#run_thread' do
let(:report_duration_counter) { instance_double(::Prometheus::Client::Counter) }
let(:file_size) { 1_000_000 }
@@ -22,13 +28,10 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
allow(File).to receive(:size).with(/#{daemon.reports_path}.*\.json/).and_return(file_size)
end
- it 'runs reports' do
- expect(daemon.send(:reports)).to all(receive(:run).twice.and_call_original)
-
- daemon.send(:run_thread)
- end
+ it 'runs reports, logs and sets gauge' do
+ expect(daemon.send(:reports))
+ .to all(receive(:run).twice { Tempfile.new("report.json", tmp_dir).path })
- it 'logs report execution' do
expect(::Prometheus::PidProvider).to receive(:worker_id).at_least(:once).and_return('worker_1')
expect(Gitlab::AppLogger).to receive(:info).with(
@@ -42,6 +45,8 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
perf_report: 'jemalloc_stats'
)).twice
+ expect(report_duration_counter).to receive(:increment).with({ report: 'jemalloc_stats' }, an_instance_of(Float))
+
daemon.send(:run_thread)
end
@@ -51,18 +56,15 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
end
it 'logs `0` as `perf_report_size_bytes`' do
+ expect(daemon.send(:reports))
+ .to all(receive(:run).twice { Tempfile.new("report.json", tmp_dir).path })
+
expect(Gitlab::AppLogger).to receive(:info).with(hash_including(perf_report_size_bytes: 0)).twice
daemon.send(:run_thread)
end
end
- it 'sets real time duration gauge' do
- expect(report_duration_counter).to receive(:increment).with({ report: 'jemalloc_stats' }, an_instance_of(Float))
-
- daemon.send(:run_thread)
- end
-
it 'allows configure and run multiple reports' do
# rubocop: disable RSpec/VerifiedDoubles
# We test how ReportsDaemon could be extended in the future
@@ -74,8 +76,8 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
allow(daemon).to receive(:reports).and_return([active_report_1, inactive_report, active_report_2])
- expect(active_report_1).to receive(:run).and_return('/tmp/report_1.json').twice
- expect(active_report_2).to receive(:run).and_return('/tmp/report_2.json').twice
+ expect(active_report_1).to receive(:run).and_return(File.join(tmp_dir, 'report_1.json')).twice
+ expect(active_report_2).to receive(:run).and_return(File.join(tmp_dir, 'report_2.json')).twice
expect(inactive_report).not_to receive(:run)
daemon.send(:run_thread)
@@ -87,6 +89,9 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
daemon = described_class.new
allow(daemon).to receive(:alive).and_return(true, true, false)
+ expect(daemon.send(:reports))
+ .to all(receive(:run).twice { Tempfile.new("report.json", tmp_dir).path })
+
expect(daemon).to receive(:sleep).with(described_class::DEFAULT_SLEEP_S).ordered
expect(daemon).to receive(:sleep).with(described_class::DEFAULT_SLEEP_BETWEEN_REPORTS_S).ordered
expect(daemon).to receive(:sleep).with(described_class::DEFAULT_SLEEP_S).ordered
@@ -120,7 +125,7 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
stub_env('GITLAB_DIAGNOSTIC_REPORTS_SLEEP_S', 100)
stub_env('GITLAB_DIAGNOSTIC_REPORTS_SLEEP_MAX_DELTA_S', 50)
stub_env('GITLAB_DIAGNOSTIC_REPORTS_SLEEP_BETWEEN_REPORTS_S', 2)
- stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', '/empty-dir')
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_PATH', tmp_dir)
end
it 'uses provided values' do
@@ -129,7 +134,7 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
expect(daemon.sleep_s).to eq(100)
expect(daemon.sleep_max_delta_s).to eq(50)
expect(daemon.sleep_between_reports_s).to eq(2)
- expect(daemon.reports_path).to eq('/empty-dir')
+ expect(daemon.reports_path).to eq(tmp_dir)
end
end
end
diff --git a/spec/lib/gitlab/memory/reports_uploader_spec.rb b/spec/lib/gitlab/memory/reports_uploader_spec.rb
new file mode 100644
index 00000000000..9ff830716f2
--- /dev/null
+++ b/spec/lib/gitlab/memory/reports_uploader_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::ReportsUploader, :aggregate_failures do
+ let(:gcs_key) { 'test_gcs_key' }
+ let(:gcs_project) { 'test_gcs_project' }
+ let(:gcs_bucket) { 'test_gcs_bucket' }
+ let(:logger) { instance_double(Gitlab::Memory::DiagnosticReportsLogger) }
+
+ let(:uploader) do
+ described_class.new(gcs_key: gcs_key, gcs_project: gcs_project, gcs_bucket: gcs_bucket, logger: logger)
+ end
+
+ # rubocop: disable RSpec/VerifiedDoubles
+ # `Fog::Storage::Google` does not implement `put_object` itself, so it is tricky to pinpoint particular method
+ # with instance_double without revealing `Fog::Storage::Google` internals. For simplicity, we use a simple double.
+ let(:fog) { double("Fog::Storage::Google") }
+ # rubocop: enable RSpec/VerifiedDoubles
+
+ let(:report) { Tempfile.new("report.1.worker_1.#{Time.current.to_i}.json") }
+
+ after do
+ FileUtils.remove_entry(report)
+ end
+
+ describe '#upload' do
+ before do
+ allow(Fog::Storage::Google)
+ .to receive(:new)
+ .with(google_project: gcs_project, google_json_key_location: gcs_key)
+ .and_return(fog)
+ end
+
+ it 'calls fog, logs upload requested and success with duration' do
+ expect(logger)
+ .to receive(:info)
+ .with(hash_including(:pid, message: "Diagnostic reports", perf_report_status: "upload requested",
+ class: 'Gitlab::Memory::ReportsUploader', perf_report_path: report.path))
+ .ordered
+
+ expect(fog).to receive(:put_object).with(gcs_bucket, File.basename(report), instance_of(File))
+
+ expect(logger)
+ .to receive(:info)
+ .with(hash_including(:pid, :duration_s,
+ message: "Diagnostic reports", perf_report_status: "upload success",
+ class: 'Gitlab::Memory::ReportsUploader', perf_report_path: report.path))
+ .ordered
+
+ uploader.upload(report.path)
+ end
+
+ context 'when Google API responds with an error' do
+ let(:invalid_bucket) { 'WRONG BUCKET' }
+
+ let(:uploader) do
+ described_class.new(gcs_key: gcs_key, gcs_project: gcs_project, gcs_bucket: invalid_bucket, logger: logger)
+ end
+
+ it 'logs error raised by Fog and do not re-raise' do
+ expect(logger)
+ .to receive(:info)
+ .with(hash_including(:pid, message: "Diagnostic reports", perf_report_status: "upload requested",
+ class: 'Gitlab::Memory::ReportsUploader', perf_report_path: report.path))
+
+ expect(fog).to receive(:put_object).with(invalid_bucket, File.basename(report), instance_of(File))
+ .and_raise(Google::Apis::ClientError.new("invalid: Invalid bucket name: #{invalid_bucket}"))
+
+ expect(logger)
+ .to receive(:error)
+ .with(hash_including(:pid,
+ message: "Diagnostic reports", class: 'Gitlab::Memory::ReportsUploader',
+ perf_report_status: 'error', error: "invalid: Invalid bucket name: #{invalid_bucket}"))
+
+ expect { uploader.upload(report.path) }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/upload_and_cleanup_reports_spec.rb b/spec/lib/gitlab/memory/upload_and_cleanup_reports_spec.rb
new file mode 100644
index 00000000000..f3351b276cc
--- /dev/null
+++ b/spec/lib/gitlab/memory/upload_and_cleanup_reports_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::UploadAndCleanupReports, :aggregate_failures do
+ let(:uploader) { instance_double(Gitlab::Memory::ReportsUploader) }
+ let(:logger) { instance_double(Gitlab::Memory::DiagnosticReportsLogger) }
+
+ describe '#initalize' do
+ let(:reports_path) { '/path/to/reports' }
+
+ context 'when sleep_time_seconds is passed through the environment' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_UPLOADER_SLEEP_S', '600')
+ end
+
+ it 'initializes with these settings' do
+ upload_and_cleanup = described_class.new(uploader: uploader, reports_path: reports_path, logger: logger)
+
+ expect(upload_and_cleanup.sleep_time_seconds).to eq(600)
+ end
+ end
+
+ context 'when sleep_time_seconds is passed through the initializer' do
+ it 'initializes with these settings' do
+ upload_and_cleanup = described_class.new(uploader: uploader, reports_path: reports_path, sleep_time_seconds: 60,
+ logger: logger)
+
+ expect(upload_and_cleanup.sleep_time_seconds).to eq(60)
+ end
+ end
+
+ context 'when `sleep_time_seconds` is not passed' do
+ it 'initialized with the default' do
+ upload_and_cleanup = described_class.new(uploader: uploader, reports_path: reports_path, logger: logger)
+
+ expect(upload_and_cleanup.sleep_time_seconds).to eq(described_class::DEFAULT_SLEEP_TIME_SECONDS)
+ end
+ end
+ end
+
+ describe '#call' do
+ let(:upload_and_cleanup) do
+ described_class.new(sleep_time_seconds: 600, reports_path: dir, uploader: uploader,
+ logger: logger).tap do |instance|
+ allow(instance).to receive(:loop).and_yield
+ allow(instance).to receive(:sleep)
+ end
+ end
+
+ let(:dir) { Dir.mktmpdir }
+
+ let(:reports_count) { 3 }
+
+ let(:reports) do
+ (1..reports_count).map do |i|
+ Tempfile.new("report.1.worker_#{i}.#{Time.current.to_i}.json", dir)
+ end
+ end
+
+ after do
+ FileUtils.remove_entry(dir)
+ end
+
+ it 'invokes the uploader and cleans the files' do
+ expect(logger)
+ .to receive(:info)
+ .with(hash_including(:pid,
+ message: "Diagnostic reports",
+ class: 'Gitlab::Memory::UploadAndCleanupReports',
+ perf_report_status: 'started'))
+
+ reports.each do |report|
+ expect(upload_and_cleanup.uploader).to receive(:upload).with(report.path)
+ end
+
+ expect { upload_and_cleanup.call }
+ .to change { Dir.entries(dir).count { |e| e.match(/report.*/) } }
+ .from(reports_count).to(0)
+ end
+
+ context 'when there is an exception' do
+ let(:report) { Tempfile.new("report.1.worker_1.#{Time.current.to_i}.json", dir) }
+
+ it 'logs it and does not crash the loop' do
+ expect(logger)
+ .to receive(:info)
+ .with(hash_including(:pid,
+ message: "Diagnostic reports",
+ class: 'Gitlab::Memory::UploadAndCleanupReports',
+ perf_report_status: 'started'))
+ .ordered
+
+ expect(upload_and_cleanup.uploader)
+ .to receive(:upload)
+ .with(report.path)
+ .and_raise(StandardError, 'Error Message')
+
+ expect(logger)
+ .to receive(:error)
+ .with(hash_including(:pid, message: "Diagnostic reports", class: 'Gitlab::Memory::UploadAndCleanupReports',
+ perf_report_status: 'error', error: 'Error Message'))
+ .ordered
+
+ expect { upload_and_cleanup.call }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog/configuration_spec.rb b/spec/lib/gitlab/memory/watchdog/configuration_spec.rb
new file mode 100644
index 00000000000..892a4b06ad0
--- /dev/null
+++ b/spec/lib/gitlab/memory/watchdog/configuration_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_dependency 'gitlab/cluster/lifecycle_events'
+
+RSpec.describe Gitlab::Memory::Watchdog::Configuration do
+ subject(:configuration) { described_class.new }
+
+ describe '#initialize' do
+ it 'initialize monitors' do
+ expect(configuration.monitors).to be_an_instance_of(described_class::MonitorStack)
+ end
+ end
+
+ describe '#handler' do
+ context 'when handler is not set' do
+ it 'defaults to NullHandler' do
+ expect(configuration.handler).to be(Gitlab::Memory::Watchdog::NullHandler.instance)
+ end
+ end
+ end
+
+ describe '#logger' do
+ context 'when logger is not set, defaults to stdout logger' do
+ it 'defaults to Logger' do
+ expect(configuration.logger).to be_an_instance_of(::Gitlab::Logger)
+ end
+ end
+ end
+
+ describe '#sleep_time_seconds' do
+ context 'when sleep_time_seconds is not set' do
+ it 'defaults to SLEEP_TIME_SECONDS' do
+ expect(configuration.sleep_time_seconds).to eq(described_class::DEFAULT_SLEEP_TIME_SECONDS)
+ end
+ end
+ end
+
+ describe '#monitors' do
+ context 'when monitors are configured to be used' do
+ let(:payload1) do
+ {
+ message: 'monitor_1_text',
+ memwd_max_strikes: 5,
+ memwd_cur_strikes: 0
+ }
+ end
+
+ let(:payload2) do
+ {
+ message: 'monitor_2_text',
+ memwd_max_strikes: 0,
+ memwd_cur_strikes: 1
+ }
+ end
+
+ let(:monitor_class_1) do
+ Struct.new(:threshold_violated, :payload) do
+ def call
+ { threshold_violated: !!threshold_violated, payload: payload || {} }
+ end
+
+ def self.name
+ 'Monitor1'
+ end
+ end
+ end
+
+ let(:monitor_class_2) do
+ Struct.new(:threshold_violated, :payload) do
+ def call
+ { threshold_violated: !!threshold_violated, payload: payload || {} }
+ end
+
+ def self.name
+ 'Monitor2'
+ end
+ end
+ end
+
+ context 'when two monitors are configured to be used' do
+ before do
+ configuration.monitors.use monitor_class_1, false, { message: 'monitor_1_text' }, max_strikes: 5
+ configuration.monitors.use monitor_class_2, true, { message: 'monitor_2_text' }, max_strikes: 0
+ end
+
+ it 'calls each monitor and returns correct results', :aggregate_failures do
+ payloads = []
+ thresholds = []
+ strikes = []
+ monitor_names = []
+
+ configuration.monitors.call_each do |result|
+ payloads << result.payload
+ thresholds << result.threshold_violated?
+ strikes << result.strikes_exceeded?
+ monitor_names << result.monitor_name
+ end
+
+ expect(payloads).to eq([payload1, payload2])
+ expect(thresholds).to eq([false, true])
+ expect(strikes).to eq([false, true])
+ expect(monitor_names).to eq([:monitor1, :monitor2])
+ end
+ end
+
+ context 'when same monitor class is configured to be used twice' do
+ before do
+ configuration.monitors.use monitor_class_1, max_strikes: 1
+ configuration.monitors.use monitor_class_1, max_strikes: 1
+ end
+
+ it 'calls same monitor only once' do
+ expect do |b|
+ configuration.monitors.call_each(&b)
+ end.to yield_control.once
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog/monitor/heap_fragmentation_spec.rb b/spec/lib/gitlab/memory/watchdog/monitor/heap_fragmentation_spec.rb
new file mode 100644
index 00000000000..dad19cfd588
--- /dev/null
+++ b/spec/lib/gitlab/memory/watchdog/monitor/heap_fragmentation_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples'
+require 'prometheus/client'
+
+RSpec.describe Gitlab::Memory::Watchdog::Monitor::HeapFragmentation do
+ let(:heap_frag_limit_gauge) { instance_double(::Prometheus::Client::Gauge) }
+ let(:max_heap_fragmentation) { 0.2 }
+ let(:fragmentation) { 0.3 }
+
+ subject(:monitor) do
+ described_class.new(max_heap_fragmentation: max_heap_fragmentation)
+ end
+
+ before do
+ allow(Gitlab::Metrics).to receive(:gauge)
+ .with(:gitlab_memwd_heap_frag_limit, anything)
+ .and_return(heap_frag_limit_gauge)
+ allow(heap_frag_limit_gauge).to receive(:set)
+
+ allow(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation).and_return(fragmentation)
+ end
+
+ describe '#initialize' do
+ it 'sets the heap fragmentation limit gauge' do
+ expect(heap_frag_limit_gauge).to receive(:set).with({}, max_heap_fragmentation)
+
+ monitor
+ end
+ end
+
+ describe '#call' do
+ it 'gets gc_heap_fragmentation' do
+ expect(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation)
+
+ monitor.call
+ end
+
+ context 'when process exceeds threshold' do
+ let(:fragmentation) { max_heap_fragmentation + 0.1 }
+ let(:payload) do
+ {
+ message: 'heap fragmentation limit exceeded',
+ memwd_cur_heap_frag: fragmentation,
+ memwd_max_heap_frag: max_heap_fragmentation
+ }
+ end
+
+ include_examples 'returns Watchdog Monitor result', threshold_violated: true
+ end
+
+ context 'when process does not exceed threshold' do
+ let(:fragmentation) { max_heap_fragmentation - 0.1 }
+ let(:payload) { {} }
+
+ include_examples 'returns Watchdog Monitor result', threshold_violated: false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog/monitor/unique_memory_growth_spec.rb b/spec/lib/gitlab/memory/watchdog/monitor/unique_memory_growth_spec.rb
new file mode 100644
index 00000000000..22494af4425
--- /dev/null
+++ b/spec/lib/gitlab/memory/watchdog/monitor/unique_memory_growth_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples'
+require_dependency 'gitlab/cluster/lifecycle_events'
+
+RSpec.describe Gitlab::Memory::Watchdog::Monitor::UniqueMemoryGrowth do
+ let(:primary_memory) { 2048 }
+ let(:worker_memory) { 0 }
+ let(:max_mem_growth) { 2 }
+
+ subject(:monitor) do
+ described_class.new(max_mem_growth: max_mem_growth)
+ end
+
+ before do
+ allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).and_return({ uss: worker_memory })
+ allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(
+ pid: Gitlab::Cluster::PRIMARY_PID
+ ).and_return({ uss: primary_memory })
+ end
+
+ describe '#call' do
+ it 'gets memory_usage_uss_pss' do
+ expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(no_args)
+ expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(pid: Gitlab::Cluster::PRIMARY_PID)
+
+ monitor.call
+ end
+
+ context 'when monitor is called twice' do
+ it 'reference memory is calculated only once' do
+ expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(no_args).twice
+ expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(pid: Gitlab::Cluster::PRIMARY_PID).once
+
+ monitor.call
+ monitor.call
+ end
+ end
+
+ context 'when process exceeds threshold' do
+ let(:worker_memory) { max_mem_growth * primary_memory + 1 }
+ let(:payload) do
+ {
+ message: 'memory limit exceeded',
+ memwd_max_uss_bytes: max_mem_growth * primary_memory,
+ memwd_ref_uss_bytes: primary_memory,
+ memwd_uss_bytes: worker_memory
+ }
+ end
+
+ include_examples 'returns Watchdog Monitor result', threshold_violated: true
+ end
+
+ context 'when process does not exceed threshold' do
+ let(:worker_memory) { max_mem_growth * primary_memory - 1 }
+ let(:payload) { {} }
+
+ include_examples 'returns Watchdog Monitor result', threshold_violated: false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog/monitor_state_spec.rb b/spec/lib/gitlab/memory/watchdog/monitor_state_spec.rb
new file mode 100644
index 00000000000..ace1353c6e3
--- /dev/null
+++ b/spec/lib/gitlab/memory/watchdog/monitor_state_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Memory::Watchdog::MonitorState do
+ let(:max_strikes) { 2 }
+ let(:payload) { { message: 'DummyMessage' } }
+ let(:threshold_violated) { true }
+ let(:monitor) { monitor_class.new(threshold_violated, payload) }
+ let(:monitor_class) do
+ Struct.new(:threshold_violated, :payload) do
+ def call
+ { threshold_violated: threshold_violated, payload: payload }
+ end
+
+ def self.name
+ 'MonitorName'
+ end
+ end
+ end
+
+ subject(:monitor_state) { described_class.new(monitor, max_strikes: max_strikes) }
+
+ shared_examples 'returns correct result' do
+ it 'returns correct result', :aggregate_failures do
+ result = monitor_state.call
+
+ expect(result).to be_an_instance_of(described_class::Result)
+ expect(result.strikes_exceeded?).to eq(strikes_exceeded)
+ expect(result.threshold_violated?).to eq(threshold_violated)
+ expect(result.payload).to eq(expected_payload)
+ expect(result.monitor_name).to eq(:monitor_name)
+ end
+ end
+
+ describe '#call' do
+ let(:strikes_exceeded) { false }
+ let(:curr_strikes) { 0 }
+ let(:expected_payload) do
+ {
+ memwd_max_strikes: max_strikes,
+ memwd_cur_strikes: curr_strikes
+ }.merge(payload)
+ end
+
+ context 'when threshold is not violated' do
+ let(:threshold_violated) { false }
+
+ include_examples 'returns correct result'
+ end
+
+ context 'when threshold is violated' do
+ let(:curr_strikes) { 1 }
+ let(:threshold_violated) { true }
+
+ include_examples 'returns correct result'
+
+ context 'when strikes_exceeded' do
+ let(:max_strikes) { 0 }
+ let(:strikes_exceeded) { true }
+
+ include_examples 'returns correct result'
+ end
+ end
+ end
+
+ describe '#monitor_class' do
+ subject { monitor_state.monitor_class }
+
+ it { is_expected.to eq(monitor_class) }
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog_spec.rb b/spec/lib/gitlab/memory/watchdog_spec.rb
index beb49660022..84e9a577afb 100644
--- a/spec/lib/gitlab/memory/watchdog_spec.rb
+++ b/spec/lib/gitlab/memory/watchdog_spec.rb
@@ -1,35 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
-require_relative '../../../../lib/gitlab/cluster/lifecycle_events'
-RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
+RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
context 'watchdog' do
- let(:logger) { instance_double(::Logger) }
+ let(:configuration) { instance_double(described_class::Configuration) }
let(:handler) { instance_double(described_class::NullHandler) }
-
- let(:heap_frag_limit_gauge) { instance_double(::Prometheus::Client::Gauge) }
+ let(:logger) { instance_double(::Logger) }
+ let(:sleep_time_seconds) { 60 }
+ let(:threshold_violated) { false }
let(:violations_counter) { instance_double(::Prometheus::Client::Counter) }
let(:violations_handled_counter) { instance_double(::Prometheus::Client::Counter) }
-
- let(:sleep_time) { 0.1 }
- let(:max_heap_fragmentation) { 0.2 }
- let(:max_mem_growth) { 2 }
-
- # Defaults that will not trigger any events.
- let(:fragmentation) { 0 }
- let(:worker_memory) { 0 }
- let(:primary_memory) { 0 }
- let(:max_strikes) { 0 }
-
- # Tests should set this to control the number of loop iterations in `call`.
let(:watchdog_iterations) { 1 }
+ let(:name) { :monitor_name }
+ let(:payload) { { message: 'dummy_text' } }
+ let(:max_strikes) { 2 }
+ let(:monitor_class) do
+ Struct.new(:threshold_violated, :payload) do
+ def call
+ { threshold_violated: threshold_violated, payload: payload }
+ end
+
+ def self.name
+ 'MonitorName'
+ end
+ end
+ end
subject(:watchdog) do
- described_class.new(handler: handler, logger: logger, sleep_time_seconds: sleep_time,
- max_strikes: max_strikes, max_mem_growth: max_mem_growth,
- max_heap_fragmentation: max_heap_fragmentation).tap do |instance|
- # We need to defuse `sleep` and stop the internal loop after N iterations.
+ described_class.new.tap do |instance|
+ # We need to defuse `sleep` and stop the internal loop after 1 iteration
iterations = 0
allow(instance).to receive(:sleep) do
instance.stop if (iterations += 1) > watchdog_iterations
@@ -38,9 +38,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
end
def stub_prometheus_metrics
- allow(Gitlab::Metrics).to receive(:gauge)
- .with(:gitlab_memwd_heap_frag_limit, anything)
- .and_return(heap_frag_limit_gauge)
allow(Gitlab::Metrics).to receive(:counter)
.with(:gitlab_memwd_violations_total, anything, anything)
.and_return(violations_counter)
@@ -48,318 +45,195 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
.with(:gitlab_memwd_violations_handled_total, anything, anything)
.and_return(violations_handled_counter)
- allow(heap_frag_limit_gauge).to receive(:set)
allow(violations_counter).to receive(:increment)
allow(violations_handled_counter).to receive(:increment)
end
- before do
- stub_prometheus_metrics
-
- allow(handler).to receive(:call).and_return(true)
-
- allow(logger).to receive(:warn)
- allow(logger).to receive(:info)
-
- allow(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation).and_return(fragmentation)
- allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).and_return({ uss: worker_memory })
- allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(
- pid: Gitlab::Cluster::PRIMARY_PID
- ).and_return({ uss: primary_memory })
-
- allow(::Prometheus::PidProvider).to receive(:worker_id).and_return('worker_1')
- end
-
- context 'when created' do
- it 'sets the heap fragmentation limit gauge' do
- expect(heap_frag_limit_gauge).to receive(:set).with({}, max_heap_fragmentation)
+ describe '#initialize' do
+ it 'initialize new configuration' do
+ expect(described_class::Configuration).to receive(:new)
watchdog
end
-
- context 'when no settings are set in the environment' do
- it 'initializes with defaults' do
- watchdog = described_class.new(handler: handler, logger: logger)
-
- expect(watchdog.max_heap_fragmentation).to eq(described_class::DEFAULT_MAX_HEAP_FRAG)
- expect(watchdog.max_mem_growth).to eq(described_class::DEFAULT_MAX_MEM_GROWTH)
- expect(watchdog.max_strikes).to eq(described_class::DEFAULT_MAX_STRIKES)
- expect(watchdog.sleep_time_seconds).to eq(described_class::DEFAULT_SLEEP_TIME_SECONDS)
- end
- end
-
- context 'when settings are passed through the environment' do
- before do
- stub_env('GITLAB_MEMWD_MAX_HEAP_FRAG', 1)
- stub_env('GITLAB_MEMWD_MAX_STRIKES', 2)
- stub_env('GITLAB_MEMWD_SLEEP_TIME_SEC', 3)
- stub_env('GITLAB_MEMWD_MAX_MEM_GROWTH', 4)
- end
-
- it 'initializes with these settings' do
- watchdog = described_class.new(handler: handler, logger: logger)
-
- expect(watchdog.max_heap_fragmentation).to eq(1)
- expect(watchdog.max_strikes).to eq(2)
- expect(watchdog.sleep_time_seconds).to eq(3)
- expect(watchdog.max_mem_growth).to eq(4)
- end
- end
end
- shared_examples 'has strikes left' do |stat|
- context 'when process has not exceeded allowed number of strikes' do
- let(:watchdog_iterations) { max_strikes }
-
- it 'does not signal the handler' do
- expect(handler).not_to receive(:call)
-
- watchdog.call
- end
-
- it 'does not log any events' do
- expect(logger).not_to receive(:warn)
-
- watchdog.call
- end
-
- it 'increments the violations counter' do
- expect(violations_counter).to receive(:increment).with(reason: stat).exactly(watchdog_iterations)
-
- watchdog.call
+ describe '#call' do
+ before do
+ stub_prometheus_metrics
+ allow(Gitlab::Metrics::System).to receive(:memory_usage_rss).at_least(:once).and_return(1024)
+ allow(::Prometheus::PidProvider).to receive(:worker_id).and_return('worker_1')
+
+ watchdog.configure do |config|
+ config.handler = handler
+ config.logger = logger
+ config.sleep_time_seconds = sleep_time_seconds
+ config.monitors.use monitor_class, threshold_violated, payload, max_strikes: max_strikes
end
- it 'does not increment violations handled counter' do
- expect(violations_handled_counter).not_to receive(:increment)
-
- watchdog.call
- end
+ allow(handler).to receive(:call).and_return(true)
+ allow(logger).to receive(:info)
+ allow(logger).to receive(:warn)
end
- end
- shared_examples 'no strikes left' do |stat|
- it 'signals the handler and resets strike counter' do
- expect(handler).to receive(:call).and_return(true)
+ it 'logs start message once' do
+ expect(logger).to receive(:info).once
+ .with(
+ pid: Process.pid,
+ worker_id: 'worker_1',
+ memwd_handler_class: handler.class.name,
+ memwd_sleep_time_s: sleep_time_seconds,
+ memwd_rss_bytes: 1024,
+ message: 'started')
watchdog.call
-
- expect(watchdog.strikes(stat.to_sym)).to eq(0)
end
- it 'increments both the violations and violations handled counters' do
- expect(violations_counter).to receive(:increment).with(reason: stat).exactly(watchdog_iterations)
- expect(violations_handled_counter).to receive(:increment).with(reason: stat)
+ it 'waits for check interval seconds' do
+ expect(watchdog).to receive(:sleep).with(sleep_time_seconds)
watchdog.call
end
- context 'when enforce_memory_watchdog ops toggle is off' do
+ context 'when gitlab_memory_watchdog ops toggle is off' do
before do
- stub_feature_flags(enforce_memory_watchdog: false)
+ stub_feature_flags(gitlab_memory_watchdog: false)
end
- it 'always uses the NullHandler' do
- expect(handler).not_to receive(:call)
- expect(described_class::NullHandler.instance).to receive(:call).and_return(true)
-
- watchdog.call
+ it 'does not trigger any monitor' do
+ expect(configuration).not_to receive(:monitors)
end
end
- context 'when handler result is true' do
- it 'considers the event handled and stops itself' do
- expect(handler).to receive(:call).once.and_return(true)
- expect(logger).to receive(:info).with(hash_including(message: 'stopped'))
+ context 'when process does not exceed threshold' do
+ it 'does not increment violations counters' do
+ expect(violations_counter).not_to receive(:increment)
+ expect(violations_handled_counter).not_to receive(:increment)
watchdog.call
end
- end
-
- context 'when handler result is false' do
- let(:max_strikes) { 0 } # to make sure the handler fires each iteration
- let(:watchdog_iterations) { 3 }
- it 'keeps running' do
- expect(violations_counter).to receive(:increment).exactly(watchdog_iterations)
- expect(violations_handled_counter).to receive(:increment).exactly(watchdog_iterations)
- # Return true the third time to terminate the daemon.
- expect(handler).to receive(:call).and_return(false, false, true)
+ it 'does not log violation' do
+ expect(logger).not_to receive(:warn)
watchdog.call
end
- end
- end
-
- context 'when monitoring memory growth' do
- let(:primary_memory) { 2048 }
-
- context 'when process does not exceed threshold' do
- let(:worker_memory) { max_mem_growth * primary_memory - 1 }
- it 'does not signal the handler' do
+ it 'does not execute handler' do
expect(handler).not_to receive(:call)
watchdog.call
end
end
- context 'when process exceeds threshold permanently' do
- let(:worker_memory) { max_mem_growth * primary_memory + 1 }
- let(:max_strikes) { 3 }
-
- it_behaves_like 'has strikes left', 'mem_growth'
+ context 'when process exceeds threshold' do
+ let(:threshold_violated) { true }
- context 'when process exceeds the allowed number of strikes' do
- let(:watchdog_iterations) { max_strikes + 1 }
+ it 'increments violations counter' do
+ expect(violations_counter).to receive(:increment).with(reason: name)
- it_behaves_like 'no strikes left', 'mem_growth'
+ watchdog.call
+ end
- it 'only reads reference memory once' do
- expect(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss)
- .with(pid: Gitlab::Cluster::PRIMARY_PID)
- .once
+ context 'when process does not exceed the allowed number of strikes' do
+ it 'does not increment handled violations counter' do
+ expect(violations_handled_counter).not_to receive(:increment)
watchdog.call
end
- it 'logs the event' do
- expect(Gitlab::Metrics::System).to receive(:memory_usage_rss).at_least(:once).and_return(1024)
- expect(logger).to receive(:warn).with({
- message: 'memory limit exceeded',
- pid: Process.pid,
- worker_id: 'worker_1',
- memwd_handler_class: 'RSpec::Mocks::InstanceVerifyingDouble',
- memwd_sleep_time_s: sleep_time,
- memwd_max_uss_bytes: max_mem_growth * primary_memory,
- memwd_ref_uss_bytes: primary_memory,
- memwd_uss_bytes: worker_memory,
- memwd_rss_bytes: 1024,
- memwd_max_strikes: max_strikes,
- memwd_cur_strikes: max_strikes + 1
- })
+ it 'does not log violation' do
+ expect(logger).not_to receive(:warn)
watchdog.call
end
- end
- end
- context 'when process exceeds threshold temporarily' do
- let(:worker_memory) { max_mem_growth * primary_memory }
- let(:max_strikes) { 1 }
- let(:watchdog_iterations) { 4 }
+ it 'does not execute handler' do
+ expect(handler).not_to receive(:call)
- before do
- allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).and_return(
- { uss: worker_memory - 0.1 },
- { uss: worker_memory + 0.2 },
- { uss: worker_memory - 0.1 },
- { uss: worker_memory + 0.1 }
- )
- allow(Gitlab::Metrics::System).to receive(:memory_usage_uss_pss).with(
- pid: Gitlab::Cluster::PRIMARY_PID
- ).and_return({ uss: primary_memory })
+ watchdog.call
+ end
end
- it 'does not signal the handler' do
- expect(handler).not_to receive(:call)
+ context 'when monitor exceeds the allowed number of strikes' do
+ let(:max_strikes) { 0 }
- watchdog.call
- end
- end
- end
+ it 'increments handled violations counter' do
+ expect(violations_handled_counter).to receive(:increment).with(reason: name)
- context 'when monitoring heap fragmentation' do
- context 'when process does not exceed threshold' do
- let(:fragmentation) { max_heap_fragmentation - 0.1 }
-
- it 'does not signal the handler' do
- expect(handler).not_to receive(:call)
-
- watchdog.call
- end
- end
-
- context 'when process exceeds threshold permanently' do
- let(:fragmentation) { max_heap_fragmentation + 0.1 }
- let(:max_strikes) { 3 }
-
- it_behaves_like 'has strikes left', 'heap_frag'
+ watchdog.call
+ end
- context 'when process exceeds the allowed number of strikes' do
- let(:watchdog_iterations) { max_strikes + 1 }
+ it 'logs violation' do
+ expect(logger).to receive(:warn)
+ .with(
+ pid: Process.pid,
+ worker_id: 'worker_1',
+ memwd_handler_class: handler.class.name,
+ memwd_sleep_time_s: sleep_time_seconds,
+ memwd_rss_bytes: 1024,
+ memwd_cur_strikes: 1,
+ memwd_max_strikes: max_strikes,
+ message: 'dummy_text')
- it_behaves_like 'no strikes left', 'heap_frag'
+ watchdog.call
+ end
- it 'logs the event' do
- expect(Gitlab::Metrics::System).to receive(:memory_usage_rss).at_least(:once).and_return(1024)
- expect(logger).to receive(:warn).with({
- message: 'heap fragmentation limit exceeded',
- pid: Process.pid,
- worker_id: 'worker_1',
- memwd_handler_class: 'RSpec::Mocks::InstanceVerifyingDouble',
- memwd_sleep_time_s: sleep_time,
- memwd_max_heap_frag: max_heap_fragmentation,
- memwd_cur_heap_frag: fragmentation,
- memwd_max_strikes: max_strikes,
- memwd_cur_strikes: max_strikes + 1,
- memwd_rss_bytes: 1024
- })
+ it 'executes handler' do
+ expect(handler).to receive(:call)
watchdog.call
end
- end
- end
- context 'when process exceeds threshold temporarily' do
- let(:fragmentation) { max_heap_fragmentation }
- let(:max_strikes) { 1 }
- let(:watchdog_iterations) { 4 }
+ context 'when enforce_memory_watchdog ops toggle is off' do
+ before do
+ stub_feature_flags(enforce_memory_watchdog: false)
+ end
- before do
- allow(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation).and_return(
- fragmentation - 0.1,
- fragmentation + 0.2,
- fragmentation - 0.1,
- fragmentation + 0.1
- )
- end
+ it 'always uses the NullHandler' do
+ expect(handler).not_to receive(:call)
+ expect(described_class::NullHandler.instance).to receive(:call).and_return(true)
- it 'does not signal the handler' do
- expect(handler).not_to receive(:call)
+ watchdog.call
+ end
+ end
- watchdog.call
+ context 'when multiple monitors exceeds allowed number of strikes' do
+ before do
+ watchdog.configure do |config|
+ config.handler = handler
+ config.logger = logger
+ config.sleep_time_seconds = sleep_time_seconds
+ config.monitors.use monitor_class, threshold_violated, payload, max_strikes: max_strikes
+ config.monitors.use monitor_class, threshold_violated, payload, max_strikes: max_strikes
+ end
+ end
+
+ it 'only calls the handler once' do
+ expect(handler).to receive(:call).once.and_return(true)
+
+ watchdog.call
+ end
+ end
end
end
- end
-
- context 'when both memory fragmentation and growth exceed thresholds' do
- let(:fragmentation) { max_heap_fragmentation + 0.1 }
- let(:primary_memory) { 2048 }
- let(:worker_memory) { max_mem_growth * primary_memory + 1 }
- let(:watchdog_iterations) { max_strikes + 1 }
- it 'only calls the handler once' do
- expect(handler).to receive(:call).once.and_return(true)
+ it 'logs stop message once' do
+ expect(logger).to receive(:info).once
+ .with(
+ pid: Process.pid,
+ worker_id: 'worker_1',
+ memwd_handler_class: handler.class.name,
+ memwd_sleep_time_s: sleep_time_seconds,
+ memwd_rss_bytes: 1024,
+ message: 'stopped')
watchdog.call
end
end
- context 'when gitlab_memory_watchdog ops toggle is off' do
- before do
- stub_feature_flags(gitlab_memory_watchdog: false)
- end
-
- it 'does not monitor heap fragmentation' do
- expect(Gitlab::Metrics::Memory).not_to receive(:gc_heap_fragmentation)
-
- watchdog.call
- end
-
- it 'does not monitor memory growth' do
- expect(Gitlab::Metrics::System).not_to receive(:memory_usage_uss_pss)
-
- watchdog.call
+ describe '#configure' do
+ it 'yields block' do
+ expect { |b| watchdog.configure(&b) }.to yield_control
end
end
end
diff --git a/spec/lib/gitlab/metrics/global_search_slis_spec.rb b/spec/lib/gitlab/metrics/global_search_slis_spec.rb
index 28496eff2fc..0c09cf6dd71 100644
--- a/spec/lib/gitlab/metrics/global_search_slis_spec.rb
+++ b/spec/lib/gitlab/metrics/global_search_slis_spec.rb
@@ -5,26 +5,20 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::GlobalSearchSlis do
using RSpec::Parameterized::TableSyntax
- let(:apdex_feature_flag_enabled) { true }
let(:error_rate_feature_flag_enabled) { true }
before do
- stub_feature_flags(global_search_custom_slis: apdex_feature_flag_enabled)
stub_feature_flags(global_search_error_rate_sli: error_rate_feature_flag_enabled)
end
describe '#initialize_slis!' do
- context 'when global_search_custom_slis feature flag is enabled' do
- let(:apdex_feature_flag_enabled) { true }
+ it 'initializes Apdex SLIs for global_search' do
+ expect(Gitlab::Metrics::Sli::Apdex).to receive(:initialize_sli).with(
+ :global_search,
+ a_kind_of(Array)
+ )
- it 'initializes Apdex SLIs for global_search' do
- expect(Gitlab::Metrics::Sli::Apdex).to receive(:initialize_sli).with(
- :global_search,
- a_kind_of(Array)
- )
-
- described_class.initialize_slis!
- end
+ described_class.initialize_slis!
end
context 'when global_search_error_rate_sli feature flag is enabled' do
@@ -40,16 +34,6 @@ RSpec.describe Gitlab::Metrics::GlobalSearchSlis do
end
end
- context 'when global_search_custom_slis feature flag is disabled' do
- let(:apdex_feature_flag_enabled) { false }
-
- it 'does not initialize the Apdex SLIs for global_search' do
- expect(Gitlab::Metrics::Sli::Apdex).not_to receive(:initialize_sli)
-
- described_class.initialize_slis!
- end
- end
-
context 'when global_search_error_rate_sli feature flag is disabled' do
let(:error_rate_feature_flag_enabled) { false }
@@ -62,78 +46,59 @@ RSpec.describe Gitlab::Metrics::GlobalSearchSlis do
end
describe '#record_apdex' do
- context 'when global_search_custom_slis feature flag is enabled' do
- let(:apdex_feature_flag_enabled) { true }
-
- where(:search_type, :code_search, :duration_target) do
- 'basic' | false | 7.031
- 'basic' | true | 21.903
- 'advanced' | false | 4.865
- 'advanced' | true | 13.546
- end
-
- with_them do
- before do
- allow(::Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return('end')
- end
+ where(:search_type, :code_search, :duration_target) do
+ 'basic' | false | 7.031
+ 'basic' | true | 21.903
+ 'advanced' | false | 4.865
+ 'advanced' | true | 13.546
+ end
- let(:search_scope) { code_search ? 'blobs' : 'issues' }
+ with_them do
+ before do
+ allow(::Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return('end')
+ end
- it 'increments the global_search SLI as a success if the elapsed time is within the target' do
- duration = duration_target - 0.1
+ let(:search_scope) { code_search ? 'blobs' : 'issues' }
- expect(Gitlab::Metrics::Sli::Apdex[:global_search]).to receive(:increment).with(
- labels: {
- search_type: search_type,
- search_level: 'global',
- search_scope: search_scope,
- endpoint_id: 'end'
- },
- success: true
- )
+ it 'increments the global_search SLI as a success if the elapsed time is within the target' do
+ duration = duration_target - 0.1
- described_class.record_apdex(
- elapsed: duration,
- search_type: search_type,
- search_level: 'global',
- search_scope: search_scope
- )
- end
-
- it 'increments the global_search SLI as a failure if the elapsed time is not within the target' do
- duration = duration_target + 0.1
-
- expect(Gitlab::Metrics::Sli::Apdex[:global_search]).to receive(:increment).with(
- labels: {
- search_type: search_type,
- search_level: 'global',
- search_scope: search_scope,
- endpoint_id: 'end'
- },
- success: false
- )
-
- described_class.record_apdex(
- elapsed: duration,
+ expect(Gitlab::Metrics::Sli::Apdex[:global_search]).to receive(:increment).with(
+ labels: {
search_type: search_type,
search_level: 'global',
- search_scope: search_scope
- )
- end
+ search_scope: search_scope,
+ endpoint_id: 'end'
+ },
+ success: true
+ )
+
+ described_class.record_apdex(
+ elapsed: duration,
+ search_type: search_type,
+ search_level: 'global',
+ search_scope: search_scope
+ )
end
- end
- context 'when global_search_custom_slis feature flag is disabled' do
- let(:apdex_feature_flag_enabled) { false }
+ it 'increments the global_search SLI as a failure if the elapsed time is not within the target' do
+ duration = duration_target + 0.1
- it 'does not call increment on the apdex SLI' do
- expect(Gitlab::Metrics::Sli::Apdex[:global_search]).not_to receive(:increment)
+ expect(Gitlab::Metrics::Sli::Apdex[:global_search]).to receive(:increment).with(
+ labels: {
+ search_type: search_type,
+ search_level: 'global',
+ search_scope: search_scope,
+ endpoint_id: 'end'
+ },
+ success: false
+ )
described_class.record_apdex(
- elapsed: 1,
- search_type: 'basic',
+ elapsed: duration,
+ search_type: search_type,
search_level: 'global',
- search_scope: 'issues'
+ search_scope: search_scope
)
end
end
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
index 7739501dd95..b86469eacd1 100644
--- a/spec/lib/gitlab/metrics/system_spec.rb
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -71,6 +71,65 @@ RSpec.describe Gitlab::Metrics::System do
SNIP
end
+ let(:mem_info) do
+ # full snapshot
+ <<~SNIP
+ MemTotal: 15362536 kB
+ MemFree: 3403136 kB
+ MemAvailable: 13044528 kB
+ Buffers: 272188 kB
+ Cached: 8171312 kB
+ SwapCached: 0 kB
+ Active: 3332084 kB
+ Inactive: 6981076 kB
+ Active(anon): 1603868 kB
+ Inactive(anon): 9044 kB
+ Active(file): 1728216 kB
+ Inactive(file): 6972032 kB
+ Unevictable: 18676 kB
+ Mlocked: 18676 kB
+ SwapTotal: 0 kB
+ SwapFree: 0 kB
+ Dirty: 6808 kB
+ Writeback: 0 kB
+ AnonPages: 1888300 kB
+ Mapped: 166164 kB
+ Shmem: 12932 kB
+ KReclaimable: 1275120 kB
+ Slab: 1495480 kB
+ SReclaimable: 1275120 kB
+ SUnreclaim: 220360 kB
+ KernelStack: 7072 kB
+ PageTables: 11936 kB
+ NFS_Unstable: 0 kB
+ Bounce: 0 kB
+ WritebackTmp: 0 kB
+ CommitLimit: 7681268 kB
+ Committed_AS: 4976100 kB
+ VmallocTotal: 34359738367 kB
+ VmallocUsed: 25532 kB
+ VmallocChunk: 0 kB
+ Percpu: 23200 kB
+ HardwareCorrupted: 0 kB
+ AnonHugePages: 202752 kB
+ ShmemHugePages: 0 kB
+ ShmemPmdMapped: 0 kB
+ FileHugePages: 0 kB
+ FilePmdMapped: 0 kB
+ CmaTotal: 0 kB
+ CmaFree: 0 kB
+ HugePages_Total: 0
+ HugePages_Free: 0
+ HugePages_Rsvd: 0
+ HugePages_Surp: 0
+ Hugepagesize: 2048 kB
+ Hugetlb: 0 kB
+ DirectMap4k: 4637504 kB
+ DirectMap2M: 11087872 kB
+ DirectMap1G: 2097152 kB
+ SNIP
+ end
+
describe '.memory_usage_rss' do
context 'without PID' do
it "returns the current process' resident set size (RSS) in bytes" do
@@ -125,6 +184,14 @@ RSpec.describe Gitlab::Metrics::System do
end
end
+ describe '.memory_total' do
+ it "returns the current process' resident set size (RSS) in bytes" do
+ mock_existing_proc_file('/proc/meminfo', mem_info)
+
+ expect(described_class.memory_total).to eq(15731236864)
+ end
+ end
+
describe '.process_runtime_elapsed_seconds' do
it 'returns the seconds elapsed since the process was started' do
# sets process starttime ticks to 1000
diff --git a/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb b/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
index cf7b0dbb5fd..ed1440f23b6 100644
--- a/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
+++ b/spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
@@ -132,11 +132,12 @@ RSpec.describe Gitlab::Middleware::HandleMalformedStrings do
end
it "rejects bad params for arrays containing hashes with string values" do
- env = env_for(name: [
- {
- inner_key: "I am #{problematic_input} bad"
- }
- ])
+ env = env_for(
+ name: [
+ {
+ inner_key: "I am #{problematic_input} bad"
+ }
+ ])
expect(subject.call(env)).to eq error_400
end
@@ -148,11 +149,12 @@ RSpec.describe Gitlab::Middleware::HandleMalformedStrings do
it_behaves_like 'checks params'
it "gives up and does not reject too deeply nested params" do
- env = env_for(name: [
- {
- inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{problematic_input} bad" }] }
- }
- ])
+ env = env_for(
+ name: [
+ {
+ inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{problematic_input} bad" }] }
+ }
+ ])
expect(subject.call(env)).not_to eq error_400
end
diff --git a/spec/lib/gitlab/pages/cache_control_spec.rb b/spec/lib/gitlab/pages/cache_control_spec.rb
index 6ed823427fb..431c989e874 100644
--- a/spec/lib/gitlab/pages/cache_control_spec.rb
+++ b/spec/lib/gitlab/pages/cache_control_spec.rb
@@ -3,21 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Pages::CacheControl do
- it 'fails with invalid type' do
- expect { described_class.new(type: :unknown, id: nil) }
- .to raise_error(ArgumentError, "type must be :namespace or :project")
- end
-
describe '.for_namespace' do
- let(:subject) { described_class.for_namespace(1) }
+ subject(:cache_control) { described_class.for_namespace(1) }
- it { expect(subject.cache_key).to eq('pages_domain_for_namespace_1') }
+ it { expect(subject.cache_key).to match(/pages_domain_for_namespace_1_*/) }
describe '#clear_cache' do
it 'clears the cache' do
expect(Rails.cache)
.to receive(:delete)
- .with('pages_domain_for_namespace_1')
+ .with(/pages_domain_for_namespace_1_*/)
subject.clear_cache
end
@@ -25,18 +20,48 @@ RSpec.describe Gitlab::Pages::CacheControl do
end
describe '.for_project' do
- let(:subject) { described_class.for_project(1) }
+ subject(:cache_control) { described_class.for_project(1) }
- it { expect(subject.cache_key).to eq('pages_domain_for_project_1') }
+ it { expect(subject.cache_key).to match(/pages_domain_for_project_1_*/) }
describe '#clear_cache' do
it 'clears the cache' do
expect(Rails.cache)
.to receive(:delete)
- .with('pages_domain_for_project_1')
+ .with(/pages_domain_for_project_1_*/)
subject.clear_cache
end
end
end
+
+ describe '#cache_key' do
+ it 'does not change the pages config' do
+ expect { described_class.new(type: :project, id: 1).cache_key }
+ .not_to change(Gitlab.config, :pages)
+ end
+
+ it 'is based on pages settings' do
+ access_control = Gitlab.config.pages.access_control
+ cache_key = described_class.new(type: :project, id: 1).cache_key
+
+ stub_config(pages: { access_control: !access_control })
+
+ expect(described_class.new(type: :project, id: 1).cache_key).not_to eq(cache_key)
+ end
+
+ it 'is based on the force_pages_access_control settings' do
+ force_pages_access_control = ::Gitlab::CurrentSettings.force_pages_access_control
+ cache_key = described_class.new(type: :project, id: 1).cache_key
+
+ ::Gitlab::CurrentSettings.force_pages_access_control = !force_pages_access_control
+
+ expect(described_class.new(type: :project, id: 1).cache_key).not_to eq(cache_key)
+ end
+ end
+
+ it 'fails with invalid type' do
+ expect { described_class.new(type: :unknown, id: nil) }
+ .to raise_error(ArgumentError, "type must be :namespace or :project")
+ end
end
diff --git a/spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb b/spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb
index 100574cc75f..64bc4555bcc 100644
--- a/spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/column_order_definition_spec.rb
@@ -23,10 +23,11 @@ RSpec.describe Gitlab::Pagination::Keyset::ColumnOrderDefinition do
let_it_be(:project_calculated_column_expression) do
# COALESCE("projects"."description", 'No Description')
- Arel::Nodes::NamedFunction.new('COALESCE', [
- Project.arel_table[:description],
- Arel.sql("'No Description'")
- ])
+ Arel::Nodes::NamedFunction.new('COALESCE',
+ [
+ Project.arel_table[:description],
+ Arel.sql("'No Description'")
+ ])
end
let_it_be(:project_calculated_column) do
diff --git a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb
index 9f2ac9a953d..cc85c897019 100644
--- a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb
@@ -117,23 +117,24 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder
let(:order) do
# NULLS LAST ordering requires custom Order object for keyset pagination:
# https://docs.gitlab.com/ee/development/database/keyset_pagination.html#complex-order-configuration
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: :relative_position,
- column_expression: Issue.arel_table[:relative_position],
- order_expression: Issue.arel_table[:relative_position].desc.nulls_last,
- reversed_order_expression: Issue.arel_table[:relative_position].asc.nulls_first,
- order_direction: :desc,
- nullable: :nulls_last,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: :id,
- order_expression: Issue.arel_table[:id].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :relative_position,
+ column_expression: Issue.arel_table[:relative_position],
+ order_expression: Issue.arel_table[:relative_position].desc.nulls_last,
+ reversed_order_expression: Issue.arel_table[:relative_position].asc.nulls_first,
+ order_direction: :desc,
+ nullable: :nulls_last,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:in_operator_optimization_options) do
@@ -279,17 +280,18 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder
context 'when ordering by SQL expression' do
let(:order) do
# ORDER BY (id * 10), id
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id_multiplied_by_ten',
- order_expression: Arel.sql('(id * 10)').asc,
- sql_type: 'integer'
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: :id,
- order_expression: Issue.arel_table[:id].asc
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id_multiplied_by_ten',
+ order_expression: Arel.sql('(id * 10)').asc,
+ sql_type: 'integer'
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
end
let(:scope) { Issue.reorder(order) }
@@ -328,4 +330,148 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder
end
end
end
+
+ context 'when ordering by JOIN-ed columns' do
+ let(:scope) { cte_with_issues_and_projects.apply_to(Issue.where({})).reorder(order) }
+
+ let(:cte_with_issues_and_projects) do
+ cte_query = Issue.select('issues.id AS id', 'project_id', 'projects.id AS projects_id', 'projects.name AS projects_name').joins(:project)
+ Gitlab::SQL::CTE.new(:issue_with_project, cte_query, materialized: false)
+ end
+
+ let(:in_operator_optimization_options) do
+ {
+ array_scope: Project.where(namespace_id: top_level_group.self_and_descendants.select(:id)).select(:id),
+ array_mapping_scope: -> (id_expression) { Issue.where(Issue.arel_table[:project_id].eq(id_expression)) }
+ }
+ end
+
+ context 'when directions are project.id DESC, issues.id ASC' do
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_id',
+ order_expression: Issue.arel_table[:projects_id].asc,
+ sql_type: 'integer',
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
+ end
+
+ let(:expected_order) { issues.sort_by { |issue| [issue.project_id, issue.id] } }
+
+ context 'when iterating records one by one' do
+ let(:batch_size) { 1 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+
+ context 'when iterating records with LIMIT 2' do
+ let(:batch_size) { 2 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+ end
+
+ context 'when directions are projects.id DESC, issues.id ASC' do
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_id',
+ order_expression: Issue.arel_table[:projects_id].desc,
+ sql_type: 'integer',
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
+ end
+
+ let(:expected_order) { issues.sort_by { |issue| [issue.project_id * -1, issue.id] } }
+
+ context 'when iterating records one by one' do
+ let(:batch_size) { 1 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+
+ context 'when iterating records with LIMIT 2' do
+ let(:batch_size) { 2 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+ end
+
+ context 'when directions are projects.name ASC, projects.id ASC, issues.id ASC' do
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_name',
+ order_expression: Issue.arel_table[:projects_name].asc,
+ sql_type: 'character varying',
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_id',
+ order_expression: Issue.arel_table[:projects_id].asc,
+ sql_type: 'integer',
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
+ end
+
+ let(:expected_order) { issues.sort_by { |issue| [issue.project.name, issue.project.id, issue.id] } }
+
+ context 'when iterating records with LIMIT 2' do
+ let(:batch_size) { 2 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+ end
+
+ context 'when directions are projects.name ASC (nullable), issues.id ASC' do
+ let(:cte_with_issues_and_projects) do
+ cte_query = Issue.select('issues.id AS id', 'project_id', 'projects.id AS projects_id', 'NULL AS projects_name').joins(:project)
+ Gitlab::SQL::CTE.new(:issue_with_project, cte_query, materialized: false)
+ end
+
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'projects_name',
+ order_expression: Issue.arel_table[:projects_name].asc,
+ sql_type: 'character varying',
+ nullable: :nulls_last,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Issue.arel_table[:id].asc
+ )
+ ])
+ end
+
+ let(:expected_order) { issues.sort_by { |issue| [issue.id] } }
+
+ context 'when iterating records with LIMIT 2' do
+ let(:batch_size) { 2 }
+
+ it_behaves_like 'correct ordering examples', skip_finder_query_test: true
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb
index ab1037b318b..2073142f077 100644
--- a/spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/order_values_loader_strategy_spec.rb
@@ -25,22 +25,24 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::Strategies::O
describe '#initializer_columns' do
it 'returns NULLs for each ORDER BY columns' do
- expect(strategy.initializer_columns).to eq([
- 'NULL::timestamp without time zone AS created_at',
- 'NULL::integer AS id'
- ])
+ expect(strategy.initializer_columns).to eq(
+ [
+ 'NULL::timestamp without time zone AS created_at',
+ 'NULL::integer AS id'
+ ])
end
end
context 'when an SQL expression is given' do
context 'when the sql_type attribute is missing' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id_times_ten',
- order_expression: Arel.sql('id * 10').asc
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id_times_ten',
+ order_expression: Arel.sql('id * 10').asc
+ )
+ ])
end
let(:keyset_scope) { Project.order(order) }
@@ -52,13 +54,14 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::Strategies::O
context 'when the sql_type_attribute is present' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id_times_ten',
- order_expression: Arel.sql('id * 10').asc,
- sql_type: 'integer'
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id_times_ten',
+ order_expression: Arel.sql('id * 10').asc,
+ sql_type: 'integer'
+ )
+ ])
end
let(:keyset_scope) { Project.order(order) }
diff --git a/spec/lib/gitlab/pagination/keyset/iterator_spec.rb b/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
index d62d20d2d2c..eee743c5e48 100644
--- a/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
@@ -15,21 +15,22 @@ RSpec.describe Gitlab::Pagination::Keyset::Iterator do
let(:nulls_position) { :nulls_last }
let(:reverse_nulls_position) { ::Gitlab::Pagination::Keyset::ColumnOrderDefinition::REVERSED_NULL_POSITIONS[nulls_position] }
let(:custom_reorder) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: column,
- column_expression: klass.arel_table[column],
- order_expression: klass.arel_table[column].public_send(direction).public_send(nulls_position), # rubocop:disable GitlabSecurity/PublicSend
- reversed_order_expression: klass.arel_table[column].public_send(reverse_direction).public_send(reverse_nulls_position), # rubocop:disable GitlabSecurity/PublicSend
- order_direction: direction,
- nullable: nulls_position,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- order_expression: klass.arel_table[:id].send(direction)
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: column,
+ column_expression: klass.arel_table[column],
+ order_expression: klass.arel_table[column].public_send(direction).public_send(nulls_position), # rubocop:disable GitlabSecurity/PublicSend
+ reversed_order_expression: klass.arel_table[column].public_send(reverse_direction).public_send(reverse_nulls_position), # rubocop:disable GitlabSecurity/PublicSend
+ order_direction: direction,
+ nullable: nulls_position,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: klass.arel_table[:id].send(direction)
+ )
+ ])
end
let(:iterator_params) { nil }
diff --git a/spec/lib/gitlab/pagination/keyset/order_spec.rb b/spec/lib/gitlab/pagination/keyset/order_spec.rb
index c1fc73603d6..e99846ad424 100644
--- a/spec/lib/gitlab/pagination/keyset/order_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/order_spec.rb
@@ -148,15 +148,16 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:expected) do
@@ -192,29 +193,30 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'year',
- column_expression: table['year'],
- order_expression: table['year'].asc,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'month',
- column_expression: table['month'],
- order_expression: table['month'].asc,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].asc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'year',
+ column_expression: table['year'],
+ order_expression: table['year'].asc,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'month',
+ column_expression: table['month'],
+ order_expression: table['month'].asc,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].asc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:expected) do
@@ -258,33 +260,34 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'year',
- column_expression: table['year'],
- order_expression: table[:year].asc.nulls_last,
- reversed_order_expression: table[:year].desc.nulls_first,
- order_direction: :asc,
- nullable: :nulls_last,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'month',
- column_expression: table['month'],
- order_expression: table[:month].asc.nulls_last,
- reversed_order_expression: table[:month].desc.nulls_first,
- order_direction: :asc,
- nullable: :nulls_last,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].asc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'year',
+ column_expression: table['year'],
+ order_expression: table[:year].asc.nulls_last,
+ reversed_order_expression: table[:year].desc.nulls_first,
+ order_direction: :asc,
+ nullable: :nulls_last,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'month',
+ column_expression: table['month'],
+ order_expression: table[:month].asc.nulls_last,
+ reversed_order_expression: table[:month].desc.nulls_first,
+ order_direction: :asc,
+ nullable: :nulls_last,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].asc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:expected) do
@@ -324,33 +327,34 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'year',
- column_expression: table['year'],
- order_expression: table[:year].asc.nulls_first,
- reversed_order_expression: table[:year].desc.nulls_last,
- order_direction: :asc,
- nullable: :nulls_first,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'month',
- column_expression: table['month'],
- order_expression: table[:month].asc.nulls_first,
- order_direction: :asc,
- reversed_order_expression: table[:month].desc.nulls_last,
- nullable: :nulls_first,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].asc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'year',
+ column_expression: table['year'],
+ order_expression: table[:year].asc.nulls_first,
+ reversed_order_expression: table[:year].desc.nulls_last,
+ order_direction: :asc,
+ nullable: :nulls_first,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'month',
+ column_expression: table['month'],
+ order_expression: table[:month].asc.nulls_first,
+ order_direction: :asc,
+ reversed_order_expression: table[:month].desc.nulls_last,
+ nullable: :nulls_first,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].asc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:expected) do
@@ -390,22 +394,23 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'year',
- column_expression: table['year'],
- order_expression: table['year'].asc,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'year',
+ column_expression: table['year'],
+ order_expression: table['year'].asc,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:expected) do
@@ -432,33 +437,38 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
reversed = order.reversed_order
before_conditions = reversed.where_values_with_or_query(before_cursor)
- query = build_query(order: order, where_conditions: [Arel::Nodes::And.new([after_conditions, before_conditions])], limit: 100)
+ query = build_query(
+ order: order,
+ where_conditions: [Arel::Nodes::And.new([after_conditions, before_conditions])],
+ limit: 100)
- expect(run_query(query)).to eq([
- { "id" => 2, "year" => 2011, "month" => 0 },
- { "id" => 6, "year" => 2012, "month" => 0 }
- ])
+ expect(run_query(query)).to eq(
+ [
+ { "id" => 2, "year" => 2011, "month" => 0 },
+ { "id" => 6, "year" => 2012, "month" => 0 }
+ ])
end
end
context 'when ordering by the named function LOWER' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'title',
- column_expression: Arel::Nodes::NamedFunction.new("LOWER", [table['title'].desc]),
- order_expression: table['title'].lower.desc,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'title',
+ column_expression: Arel::Nodes::NamedFunction.new("LOWER", [table['title'].desc]),
+ order_expression: table['title'].lower.desc,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
let(:table_data) do
@@ -484,22 +494,23 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
context 'when the passed cursor values do not match with the order definition' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'year',
- column_expression: table['year'],
- order_expression: table['year'].asc,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- column_expression: table['id'],
- order_expression: table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'year',
+ column_expression: table['year'],
+ order_expression: table['year'].asc,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ column_expression: table['id'],
+ order_expression: table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
context 'when values are missing' do
@@ -553,14 +564,15 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
context 'when string attribute name is given' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- order_expression: Project.arel_table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: Project.arel_table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
it_behaves_like 'cursor attribute examples'
@@ -568,14 +580,15 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
context 'when symbol attribute name is given' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: :id,
- order_expression: Project.arel_table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Project.arel_table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
it_behaves_like 'cursor attribute examples'
@@ -593,20 +606,21 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
context 'when there are additional_projections' do
let(:order) do
- order = Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'created_at_field',
- column_expression: Project.arel_table[:created_at],
- order_expression: Project.arel_table[:created_at].desc,
- order_direction: :desc,
- distinct: false,
- add_to_projections: true
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- order_expression: Project.arel_table[:id].desc
- )
- ])
+ order = Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'created_at_field',
+ column_expression: Project.arel_table[:created_at],
+ order_expression: Project.arel_table[:created_at].desc,
+ order_direction: :desc,
+ distinct: false,
+ add_to_projections: true
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: Project.arel_table[:id].desc
+ )
+ ])
order
end
@@ -684,20 +698,21 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
describe '#attribute_names' do
let(:expected_attribute_names) { %w(id name) }
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'id',
- order_expression: Project.arel_table['id'].desc,
- nullable: :not_nullable,
- distinct: true
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'name',
- order_expression: Project.arel_table['name'].desc,
- nullable: :not_nullable,
- distinct: true
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: Project.arel_table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'name',
+ order_expression: Project.arel_table['name'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
end
subject { order.attribute_names }
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index bfe1a588489..7c365990627 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Profiler do
end
it 'returns a profile result' do
- expect(described_class.profile('/')).to be_an_instance_of(RubyProf::Profile)
+ expect(described_class.profile('/')).to be_an_instance_of(File)
end
it 'uses the custom logger given' do
@@ -59,28 +59,26 @@ RSpec.describe Gitlab::Profiler do
described_class.profile('/', user: user, private_token: private_token)
end
- context 'with sampling profiler' do
- it 'generates sampling data' do
- user = double(:user)
- temp_data = Tempfile.new
+ it 'generates sampling data' do
+ user = double(:user)
+ temp_data = Tempfile.new
- expect(described_class).to receive(:with_user).with(user).and_call_original
- described_class.profile('/', user: user, sampling_mode: true, profiler_options: { out: temp_data.path })
+ expect(described_class).to receive(:with_user).with(user).and_call_original
+ described_class.profile('/', user: user, profiler_options: { out: temp_data.path })
- expect(File.stat(temp_data).size).to be > 0
- File.unlink(temp_data)
- end
+ expect(File.stat(temp_data).size).to be > 0
+ File.unlink(temp_data)
+ end
- it 'saves sampling data with a randomly-generated filename' do
- user = double(:user)
+ it 'saves sampling data with a randomly-generated filename' do
+ user = double(:user)
- expect(described_class).to receive(:with_user).with(user).and_call_original
- result = described_class.profile('/', user: user, sampling_mode: true)
+ expect(described_class).to receive(:with_user).with(user).and_call_original
+ result = described_class.profile('/', user: user)
- expect(result).to be_a(File)
- expect(File.stat(result.path).size).to be > 0
- File.unlink(result.path)
- end
+ expect(result).to be_a(File)
+ expect(File.stat(result.path).size).to be > 0
+ File.unlink(result.path)
end
end
@@ -211,54 +209,4 @@ RSpec.describe Gitlab::Profiler do
expect(described_class.log_load_times_by_model(null_logger)).to be_nil
end
end
-
- describe '.print_by_total_time' do
- let(:stdout) { StringIO.new }
- let(:regexp) { /^\s+\d+\.\d+\s+(\d+\.\d+)/ }
-
- let(:output) do
- stdout.rewind
- stdout.read
- end
-
- let_it_be(:result) do
- Thread.new { sleep 1 }
-
- RubyProf.profile do
- sleep 0.1
- 1.to_s
- end
- end
-
- around do |example|
- original_stdout = $stdout
-
- $stdout = stdout # rubocop: disable RSpec/ExpectOutput
- example.run
- $stdout = original_stdout # rubocop: disable RSpec/ExpectOutput
- end
-
- it 'prints a profile result sorted by total time' do
- described_class.print_by_total_time(result)
-
- expect(output).to include('Kernel#sleep')
-
- thread_profiles = output.split('Sort by: total_time').select { |x| x =~ regexp }
-
- thread_profiles.each do |profile|
- total_times =
- profile
- .scan(regexp)
- .map { |(total)| total.to_f }
-
- expect(total_times).to eq(total_times.sort.reverse)
- end
- end
-
- it 'accepts a max_percent option' do
- described_class.print_by_total_time(result, max_percent: 50)
-
- expect(output).not_to include('Kernel#sleep')
- end
- end
end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index a9c0262fdb2..a762fdbde6b 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
shared_examples 'blob search repository ref' do |entity_type, blob_type|
let(:query) { 'files' }
let(:file_finder) { double }
- let(:project_branch) { 'project_branch' }
+ let(:project_branch) { blob_type == 'wiki_blobs' ? entity.default_branch : 'project_branch' }
subject(:objects) { results.objects(blob_type) }
@@ -209,8 +209,11 @@ RSpec.describe Gitlab::ProjectSearchResults do
describe 'wiki search' do
let(:project) { create(:project, :public, :wiki_repo) }
+ let(:project_branch) { 'project_branch' }
before do
+ allow(project.wiki).to receive(:root_ref).and_return(project_branch)
+
project.wiki.create_page('Files/Title', 'Content')
project.wiki.create_page('CHANGELOG', 'Files example')
end
diff --git a/spec/lib/gitlab/project_transfer_spec.rb b/spec/lib/gitlab/project_transfer_spec.rb
index 87c4014264f..3d6aa80c51f 100644
--- a/spec/lib/gitlab/project_transfer_spec.rb
+++ b/spec/lib/gitlab/project_transfer_spec.rb
@@ -15,10 +15,11 @@ RSpec.describe Gitlab::ProjectTransfer do
end
after do
- FileUtils.rm_rf([
- File.join(@root_dir, @namespace_path),
- File.join(@root_dir, @namespace_path_was)
- ])
+ FileUtils.rm_rf(
+ [
+ File.join(@root_dir, @namespace_path),
+ File.join(@root_dir, @namespace_path_was)
+ ])
end
describe '#move_project' do
diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb
index 9083c5625d4..d0bfc6e5610 100644
--- a/spec/lib/gitlab/prometheus_client_spec.rb
+++ b/spec/lib/gitlab/prometheus_client_spec.rb
@@ -300,12 +300,13 @@ RSpec.describe Gitlab::PrometheusClient do
it 'returns data from the API call' do
req_stub = stub_prometheus_request(query_url, body: prometheus_values_body('matrix'))
- expect(subject.query_range(prometheus_query)).to eq([
- {
- "metric" => {},
- "values" => [[1488758662.506, "0.00002996364761904785"], [1488758722.506, "0.00003090239047619091"]]
- }
- ])
+ expect(subject.query_range(prometheus_query)).to eq(
+ [
+ {
+ "metric" => {},
+ "values" => [[1488758662.506, "0.00002996364761904785"], [1488758722.506, "0.00003090239047619091"]]
+ }
+ ])
expect(req_stub).to have_been_requested
end
end
diff --git a/spec/lib/gitlab/push_options_spec.rb b/spec/lib/gitlab/push_options_spec.rb
index 3ff1c8e9012..054beaf7012 100644
--- a/spec/lib/gitlab/push_options_spec.rb
+++ b/spec/lib/gitlab/push_options_spec.rb
@@ -52,10 +52,11 @@ RSpec.describe Gitlab::PushOptions do
end
it 'can parse multiple push options' do
- options = described_class.new([
- 'merge_request.create',
- 'merge_request.target=value'
- ])
+ options = described_class.new(
+ [
+ 'merge_request.create',
+ 'merge_request.target=value'
+ ])
expect(options.get(:merge_request)).to include({
create: true,
@@ -66,19 +67,21 @@ RSpec.describe Gitlab::PushOptions do
end
it 'stores options internally as a HashWithIndifferentAccess' do
- options = described_class.new([
- 'merge_request.create'
- ])
+ options = described_class.new(
+ [
+ 'merge_request.create'
+ ])
expect(options.get('merge_request', 'create')).to eq(true)
expect(options.get(:merge_request, :create)).to eq(true)
end
it 'selects the last option when options contain duplicate namespace and key pairs' do
- options = described_class.new([
- 'merge_request.target=value1',
- 'merge_request.target=value2'
- ])
+ options = described_class.new(
+ [
+ 'merge_request.target=value1',
+ 'merge_request.target=value2'
+ ])
expect(options.get(:merge_request, :target)).to eq('value2')
end
diff --git a/spec/lib/gitlab/query_limiting/transaction_spec.rb b/spec/lib/gitlab/query_limiting/transaction_spec.rb
index 27da1f23556..d8eb2040ccc 100644
--- a/spec/lib/gitlab/query_limiting/transaction_spec.rb
+++ b/spec/lib/gitlab/query_limiting/transaction_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
context 'when the query threshold is exceeded' do
let(:transaction) do
trans = described_class.new
- trans.count = described_class::THRESHOLD + 1
+ trans.count = described_class.threshold + 1
trans
end
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
it 'returns true when the threshold is exceeded' do
transaction = described_class.new
- transaction.count = described_class::THRESHOLD + 1
+ transaction.count = described_class.threshold + 1
expect(transaction.threshold_exceeded?).to eq(true)
end
@@ -129,7 +129,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
describe '#error_message' do
it 'returns the error message to display when the threshold is exceeded' do
transaction = described_class.new
- transaction.count = max = described_class::THRESHOLD
+ transaction.count = max = described_class.threshold
expect(transaction.error_message).to eq(
"Too many SQL queries were executed: a maximum of #{max} " \
@@ -139,7 +139,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
it 'includes a list of executed queries' do
transaction = described_class.new
- transaction.count = max = described_class::THRESHOLD
+ transaction.count = max = described_class.threshold
%w[foo bar baz].each { |sql| transaction.executed_sql(sql) }
message = transaction.error_message
@@ -154,7 +154,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
it 'indicates if the log is truncated' do
transaction = described_class.new
- transaction.count = described_class::THRESHOLD * 2
+ transaction.count = described_class.threshold * 2
message = transaction.error_message
@@ -163,7 +163,7 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
it 'includes the action name in the error message when present' do
transaction = described_class.new
- transaction.count = max = described_class::THRESHOLD
+ transaction.count = max = described_class.threshold
transaction.action = 'UsersController#show'
expect(transaction.error_message).to eq(
diff --git a/spec/lib/gitlab/rack_attack/request_spec.rb b/spec/lib/gitlab/rack_attack/request_spec.rb
index b8a26a64e5b..5345205e15b 100644
--- a/spec/lib/gitlab/rack_attack/request_spec.rb
+++ b/spec/lib/gitlab/rack_attack/request_spec.rb
@@ -217,10 +217,11 @@ RSpec.describe Gitlab::RackAttack::Request do
subject { request.protected_path? }
before do
- stub_application_setting(protected_paths: [
- '/protected',
- '/secure'
- ])
+ stub_application_setting(
+ protected_paths: [
+ '/protected',
+ '/secure'
+ ])
end
where(:path, :expected) do
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 177e9d346b6..0ee8c35ae81 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -193,7 +193,7 @@ RSpec.describe Gitlab::ReferenceExtractor do
end
context 'with an external issue tracker' do
- let(:project) { create(:jira_project) }
+ let(:project) { create(:project, :with_jira_integration) }
let(:issue) { create(:issue, project: project) }
context 'when GitLab issues are enabled' do
diff --git a/spec/lib/gitlab/regex_requires_app_spec.rb b/spec/lib/gitlab/regex_requires_app_spec.rb
index 5808033dc4c..780184cdfd2 100644
--- a/spec/lib/gitlab/regex_requires_app_spec.rb
+++ b/spec/lib/gitlab/regex_requires_app_spec.rb
@@ -30,6 +30,8 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('AMD64') }
it { is_expected.not_to match('Amd64') }
it { is_expected.not_to match('aMD64') }
+
+ it_behaves_like 'regex rejecting path traversal'
end
describe '.npm_package_name_regex' do
@@ -73,6 +75,8 @@ RSpec.describe Gitlab::Regex do
# Do not allow Unicode
it { is_expected.not_to match('hé') }
+
+ it_behaves_like 'regex rejecting path traversal'
end
describe '.debian_component_regex' do
@@ -86,5 +90,7 @@ RSpec.describe Gitlab::Regex do
# Do not allow Unicode
it { is_expected.not_to match('hé') }
+
+ it_behaves_like 'regex rejecting path traversal'
end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index d8f182d903d..89ef76d246e 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -3,6 +3,7 @@
require 'fast_spec_helper'
require_relative '../../../lib/gitlab/regex'
+require_relative '../../support/shared_examples/lib/gitlab/regex_shared_examples'
# All specs that can be run with fast_spec_helper only
# See regex_requires_app_spec for tests that require the full spec_helper
@@ -543,6 +544,8 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('aA') }
# No underscore
it { is_expected.not_to match('a_b') }
+
+ it_behaves_like 'regex rejecting path traversal'
end
describe '.debian_version_regex' do
@@ -596,6 +599,13 @@ RSpec.describe Gitlab::Regex do
it { is_expected.to match('1-2-3-4-5-6-7-8-9-10-11-12-13-14-15') }
it { is_expected.not_to match('1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16') }
end
+
+ context 'path traversals' do
+ it { is_expected.not_to match('1../0') }
+ it { is_expected.not_to match('1..%2f0') }
+ it { is_expected.not_to match('1%2e%2e%2f0') }
+ it { is_expected.not_to match('1%2e%2e/0') }
+ end
end
describe '.helm_channel_regex' do
diff --git a/spec/lib/gitlab/search/abuse_detection_spec.rb b/spec/lib/gitlab/search/abuse_detection_spec.rb
index 2a8d74a62ab..7fb9621141c 100644
--- a/spec/lib/gitlab/search/abuse_detection_spec.rb
+++ b/spec/lib/gitlab/search/abuse_detection_spec.rb
@@ -21,16 +21,16 @@ RSpec.describe Gitlab::Search::AbuseDetection do
describe 'abusive character matching' do
refs = %w(
- main
- теÑÑ‚
- maiñ
- main123
- main-v123
- main-v12.3
- feature/it_works
- really_important!
- 测试
- )
+ 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
diff --git a/spec/lib/gitlab/search/query_spec.rb b/spec/lib/gitlab/search/query_spec.rb
index 234b683ba1f..cdab7f1c04b 100644
--- a/spec/lib/gitlab/search/query_spec.rb
+++ b/spec/lib/gitlab/search/query_spec.rb
@@ -64,4 +64,38 @@ RSpec.describe Gitlab::Search::Query do
expect(subject.filters[0]).to include(name: :name, negated: false, value: "MY TEST.TXT")
end
end
+
+ context 'with mutliple filename filters' do
+ let(:query) { 'something filename:myfile.txt -filename:ANOTHERFILE.yml filename:somethingelse.txt' }
+ let(:subject) do
+ described_class.new(query) do
+ filter :filename
+ end
+ end
+
+ it 'creates a filter for each filename in query' do
+ expect(subject.filters.count).to eq(3)
+ expect(subject.filters[0]).to include(name: :filename, negated: false, value: 'myfile.txt')
+ expect(subject.filters[1]).to include(name: :filename, negated: true, value: 'anotherfile.yml')
+ expect(subject.filters[2]).to include(name: :filename, negated: false, value: 'somethingelse.txt')
+ end
+
+ context 'when multiple extension filters are added' do
+ let(:query) { 'something filename:myfile.txt -extension:yml -filename:ANOTHERFILE.yml extension:txt' }
+ let(:subject) do
+ described_class.new(query) do
+ filter :filename
+ filter :extension
+ end
+ end
+
+ it 'creates a filter for each filename and extension in query' do
+ expect(subject.filters.count).to eq(4)
+ expect(subject.filters[0]).to include(name: :filename, negated: false, value: 'myfile.txt')
+ expect(subject.filters[1]).to include(name: :filename, negated: true, value: 'anotherfile.yml')
+ expect(subject.filters[2]).to include(name: :extension, negated: true, value: 'yml')
+ expect(subject.filters[3]).to include(name: :extension, negated: false, value: 'txt')
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/serializer/ci/variables_spec.rb b/spec/lib/gitlab/serializer/ci/variables_spec.rb
index 9b0475259fe..02f1d543e4b 100644
--- a/spec/lib/gitlab/serializer/ci/variables_spec.rb
+++ b/spec/lib/gitlab/serializer/ci/variables_spec.rb
@@ -13,9 +13,10 @@ RSpec.describe Gitlab::Serializer::Ci::Variables do
end
it 'converts keys into strings and symbolizes hash' do
- is_expected.to eq([
- { key: 'key', value: 'value', public: true },
- { key: 'wee', value: 1, public: false }
- ])
+ is_expected.to eq(
+ [
+ { key: 'key', value: 'value', public: true },
+ { key: 'wee', value: 1, public: false }
+ ])
end
end
diff --git a/spec/lib/gitlab/sidekiq_config_spec.rb b/spec/lib/gitlab/sidekiq_config_spec.rb
index c62302d8bba..c5b00afe672 100644
--- a/spec/lib/gitlab/sidekiq_config_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config_spec.rb
@@ -193,9 +193,7 @@ RSpec.describe Gitlab::SidekiqConfig do
it 'returns worker queue mappings that have queues in the current Sidekiq options' do
queues = described_class.routing_queues
- expect(queues).to match_array(%w[
- default mailers high_urgency gitaly
- ])
+ expect(queues).to match_array(%w[default mailers high_urgency gitaly])
expect(queues).not_to include('not_exist')
end
end
diff --git a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
index dff04a2e509..62681b21756 100644
--- a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
+++ b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
@@ -130,9 +130,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
end
it 'return true when everything is within limit', :aggregate_failures do
- expect(memory_killer).to receive(:get_rss).and_return(100)
- expect(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
- expect(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
+ expect(memory_killer).to receive(:get_rss_kb).and_return(100)
+ expect(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(200)
+ expect(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(300)
+ expect(memory_killer).to receive(:get_memory_total_kb).and_return(3072)
expect(memory_killer).to receive(:refresh_state)
.with(:running)
@@ -145,9 +146,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
end
it 'return false when rss exceeds hard_limit_rss', :aggregate_failures do
- expect(memory_killer).to receive(:get_rss).at_least(:once).and_return(400)
- expect(memory_killer).to receive(:get_soft_limit_rss).at_least(:once).and_return(200)
- expect(memory_killer).to receive(:get_hard_limit_rss).at_least(:once).and_return(300)
+ expect(memory_killer).to receive(:get_rss_kb).at_least(:once).and_return(400)
+ expect(memory_killer).to receive(:get_soft_limit_rss_kb).at_least(:once).and_return(200)
+ expect(memory_killer).to receive(:get_hard_limit_rss_kb).at_least(:once).and_return(300)
+ expect(memory_killer).to receive(:get_memory_total_kb).at_least(:once).and_return(3072)
expect(memory_killer).to receive(:refresh_state)
.with(:running)
@@ -165,9 +167,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
end
it 'return false when rss exceed hard_limit_rss after a while', :aggregate_failures do
- expect(memory_killer).to receive(:get_rss).and_return(250, 400, 400)
- expect(memory_killer).to receive(:get_soft_limit_rss).at_least(:once).and_return(200)
- expect(memory_killer).to receive(:get_hard_limit_rss).at_least(:once).and_return(300)
+ expect(memory_killer).to receive(:get_rss_kb).and_return(250, 400, 400)
+ expect(memory_killer).to receive(:get_soft_limit_rss_kb).at_least(:once).and_return(200)
+ expect(memory_killer).to receive(:get_hard_limit_rss_kb).at_least(:once).and_return(300)
+ expect(memory_killer).to receive(:get_memory_total_kb).at_least(:once).and_return(3072)
expect(memory_killer).to receive(:refresh_state)
.with(:running)
@@ -187,9 +190,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
end
it 'return true when rss below soft_limit_rss after a while within GRACE_BALLOON_SECONDS', :aggregate_failures do
- expect(memory_killer).to receive(:get_rss).and_return(250, 100)
- expect(memory_killer).to receive(:get_soft_limit_rss).and_return(200, 200)
- expect(memory_killer).to receive(:get_hard_limit_rss).and_return(300, 300)
+ expect(memory_killer).to receive(:get_rss_kb).and_return(250, 100)
+ expect(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(200, 200)
+ expect(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(300, 300)
+ expect(memory_killer).to receive(:get_memory_total_kb).and_return(3072, 3072)
expect(memory_killer).to receive(:refresh_state)
.with(:running)
@@ -211,9 +215,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
let(:grace_balloon_seconds) { 0 }
it 'return false when rss exceed soft_limit_rss', :aggregate_failures do
- allow(memory_killer).to receive(:get_rss).and_return(250)
- allow(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
- allow(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
+ allow(memory_killer).to receive(:get_rss_kb).and_return(250)
+ allow(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(200)
+ allow(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(300)
+ allow(memory_killer).to receive(:get_memory_total_kb).and_return(3072)
expect(memory_killer).to receive(:refresh_state)
.with(:running)
@@ -235,40 +240,57 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
subject { memory_killer.send(:restart_sidekiq) }
- before do
- stub_const("#{described_class}::SHUTDOWN_TIMEOUT_SECONDS", shutdown_timeout_seconds)
- allow(Sidekiq).to receive(:options).and_return(timeout: 9)
- allow(memory_killer).to receive(:get_rss).and_return(100)
- allow(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
- allow(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
+ context 'when sidekiq_memory_killer_read_only_mode is enabled' do
+ before do
+ stub_feature_flags(sidekiq_memory_killer_read_only_mode: true)
+ end
+
+ it 'does not send signal' do
+ expect(memory_killer).not_to receive(:refresh_state)
+ expect(memory_killer).not_to receive(:signal_and_wait)
+
+ subject
+ end
end
- it 'send signal' do
- expect(memory_killer).to receive(:refresh_state)
- .with(:stop_fetching_new_jobs)
- .ordered
- .and_call_original
- expect(memory_killer).to receive(:signal_and_wait)
- .with(shutdown_timeout_seconds, 'SIGTSTP', 'stop fetching new jobs')
- .ordered
+ context 'when sidekiq_memory_killer_read_only_mode is disabled' do
+ before do
+ stub_const("#{described_class}::SHUTDOWN_TIMEOUT_SECONDS", shutdown_timeout_seconds)
+ stub_feature_flags(sidekiq_memory_killer_read_only_mode: false)
+ allow(Sidekiq).to receive(:options).and_return(timeout: 9)
+ allow(memory_killer).to receive(:get_rss_kb).and_return(100)
+ allow(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(200)
+ allow(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(300)
+ allow(memory_killer).to receive(:get_memory_total_kb).and_return(3072)
+ end
- expect(memory_killer).to receive(:refresh_state)
- .with(:shutting_down)
- .ordered
- .and_call_original
- expect(memory_killer).to receive(:signal_and_wait)
- .with(11, 'SIGTERM', 'gracefully shut down')
- .ordered
+ it 'send signal' do
+ expect(memory_killer).to receive(:refresh_state)
+ .with(:stop_fetching_new_jobs)
+ .ordered
+ .and_call_original
+ expect(memory_killer).to receive(:signal_and_wait)
+ .with(shutdown_timeout_seconds, 'SIGTSTP', 'stop fetching new jobs')
+ .ordered
- expect(memory_killer).to receive(:refresh_state)
- .with(:killing_sidekiq)
- .ordered
- .and_call_original
- expect(memory_killer).to receive(:signal_pgroup)
- .with('SIGKILL', 'die')
- .ordered
+ expect(memory_killer).to receive(:refresh_state)
+ .with(:shutting_down)
+ .ordered
+ .and_call_original
+ expect(memory_killer).to receive(:signal_and_wait)
+ .with(11, 'SIGTERM', 'gracefully shut down')
+ .ordered
- subject
+ expect(memory_killer).to receive(:refresh_state)
+ .with(:killing_sidekiq)
+ .ordered
+ .and_call_original
+ expect(memory_killer).to receive(:signal_pgroup)
+ .with('SIGKILL', 'die')
+ .ordered
+
+ subject
+ end
end
end
@@ -351,6 +373,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
let(:current_rss) { 100 }
let(:soft_limit_rss) { 200 }
let(:hard_limit_rss) { 300 }
+ let(:memory_total) { 3072 }
let(:jid) { 1 }
let(:reason) { 'rss out of range reason description' }
let(:queue) { 'default' }
@@ -369,9 +392,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
before do
stub_const("DummyWorker", worker)
- allow(memory_killer).to receive(:get_rss).and_return(*current_rss)
- allow(memory_killer).to receive(:get_soft_limit_rss).and_return(soft_limit_rss)
- allow(memory_killer).to receive(:get_hard_limit_rss).and_return(hard_limit_rss)
+ allow(memory_killer).to receive(:get_rss_kb).and_return(*current_rss)
+ allow(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(soft_limit_rss)
+ allow(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(hard_limit_rss)
+ allow(memory_killer).to receive(:get_memory_total_kb).and_return(memory_total)
memory_killer.send(:refresh_state, :running)
end
@@ -389,7 +413,8 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
hard_limit_rss: hard_limit_rss,
soft_limit_rss: soft_limit_rss,
reason: reason,
- running_jobs: running_jobs)
+ running_jobs: running_jobs,
+ memory_total_kb: memory_total)
expect(metrics[:sidekiq_memory_killer_running_jobs]).to receive(:increment)
.with({ worker_class: "DummyWorker", deadline_exceeded: true })
@@ -525,9 +550,10 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
subject { memory_killer.send(:refresh_state, :shutting_down) }
it 'calls gitlab metrics gauge set methods' do
- expect(memory_killer).to receive(:get_rss) { 1010 }
- expect(memory_killer).to receive(:get_soft_limit_rss) { 1020 }
- expect(memory_killer).to receive(:get_hard_limit_rss) { 1040 }
+ expect(memory_killer).to receive(:get_rss_kb) { 1010 }
+ expect(memory_killer).to receive(:get_soft_limit_rss_kb) { 1020 }
+ expect(memory_killer).to receive(:get_hard_limit_rss_kb) { 1040 }
+ expect(memory_killer).to receive(:get_memory_total_kb) { 3072 }
expect(metrics[:sidekiq_memory_killer_phase]).to receive(:set)
.with({}, described_class::PHASE[:shutting_down])
diff --git a/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb
deleted file mode 100644
index 1667622ad8e..00000000000
--- a/spec/lib/gitlab/sidekiq_middleware/memory_killer_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::SidekiqMiddleware::MemoryKiller do
- subject { described_class.new }
-
- let(:pid) { 999 }
-
- let(:worker) { double(:worker, class: ProjectCacheWorker) }
- let(:job) { { 'jid' => 123 } }
- let(:queue) { 'test_queue' }
-
- def run
- thread = subject.call(worker, job, queue) { nil }
- thread&.join
- end
-
- before do
- allow(subject).to receive(:get_rss).and_return(10.kilobytes)
- allow(subject).to receive(:pid).and_return(pid)
- end
-
- context 'when MAX_RSS is set to 0' do
- before do
- stub_const("#{described_class}::MAX_RSS", 0)
- end
-
- it 'does nothing' do
- expect(subject).not_to receive(:sleep)
-
- run
- end
- end
-
- context 'when MAX_RSS is exceeded' do
- before do
- stub_const("#{described_class}::MAX_RSS", 5.kilobytes)
- end
-
- it 'sends the TSTP, TERM and KILL signals at expected times' do
- expect(subject).to receive(:sleep).with(15 * 60).ordered
- expect(Process).to receive(:kill).with('SIGTSTP', pid).ordered
-
- expect(subject).to receive(:sleep).with(30).ordered
- expect(Process).to receive(:kill).with('SIGTERM', pid).ordered
-
- expect(subject).to receive(:sleep).with(Sidekiq.options[:timeout] + 2).ordered
- expect(Process).to receive(:kill).with('SIGKILL', pid).ordered
-
- expect(Sidekiq.logger)
- .to receive(:warn).with(class: 'ProjectCacheWorker',
- message: anything,
- pid: pid,
- signal: anything).at_least(:once)
-
- run
- end
-
- it 'sends TSTP and TERM to the pid, but KILL to the pgroup, when running as process leader' do
- allow(Process).to receive(:getpgrp) { pid }
- allow(subject).to receive(:sleep)
-
- expect(Process).to receive(:kill).with('SIGTSTP', pid).ordered
- expect(Process).to receive(:kill).with('SIGTERM', pid).ordered
- expect(Process).to receive(:kill).with('SIGKILL', 0).ordered
-
- run
- end
- end
-
- context 'when MAX_RSS is not exceeded' do
- before do
- stub_const("#{described_class}::MAX_RSS", 15.kilobytes)
- end
-
- it 'does nothing' do
- expect(subject).not_to receive(:sleep)
-
- run
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 52b50a143fc..54a1723afbc 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -322,8 +322,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
with_sidekiq_server_middleware do |chain|
Gitlab::SidekiqMiddleware.server_configurator(
metrics: true,
- arguments_logger: false,
- memory_killer: false
+ arguments_logger: false
).call(chain)
Sidekiq::Testing.inline! { example.run }
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index e687c8e8cf7..14dbeac37e8 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -60,7 +60,6 @@ RSpec.describe Gitlab::SidekiqMiddleware do
::Labkit::Middleware::Sidekiq::Server,
::Gitlab::SidekiqMiddleware::ServerMetrics,
::Gitlab::SidekiqMiddleware::ArgumentsLogger,
- ::Gitlab::SidekiqMiddleware::MemoryKiller,
::Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
::Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata,
::Gitlab::SidekiqMiddleware::BatchLoader,
@@ -79,8 +78,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
with_sidekiq_server_middleware do |chain|
described_class.server_configurator(
metrics: true,
- arguments_logger: true,
- memory_killer: true
+ arguments_logger: true
).call(chain)
Sidekiq::Testing.inline! { example.run }
@@ -112,16 +110,14 @@ RSpec.describe Gitlab::SidekiqMiddleware do
let(:configurator) do
described_class.server_configurator(
metrics: false,
- arguments_logger: false,
- memory_killer: false
+ arguments_logger: false
)
end
let(:disabled_sidekiq_middlewares) do
[
Gitlab::SidekiqMiddleware::ServerMetrics,
- Gitlab::SidekiqMiddleware::ArgumentsLogger,
- Gitlab::SidekiqMiddleware::MemoryKiller
+ Gitlab::SidekiqMiddleware::ArgumentsLogger
]
end
diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb
index 027697db7e1..7f1504a8df9 100644
--- a/spec/lib/gitlab/sidekiq_status_spec.rb
+++ b/spec/lib/gitlab/sidekiq_status_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
key = described_class.key_for('123')
with_redis do |redis|
- expect(redis.exists(key)).to eq(true)
+ expect(redis.exists?(key)).to eq(true)
expect(redis.ttl(key) > 0).to eq(true)
expect(redis.get(key)).to eq('1')
end
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
key = described_class.key_for('123')
with_redis do |redis|
- expect(redis.exists(key)).to eq(true)
+ expect(redis.exists?(key)).to eq(true)
expect(redis.ttl(key) > described_class::DEFAULT_EXPIRATION).to eq(true)
expect(redis.get(key)).to eq('1')
end
@@ -35,7 +35,7 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
key = described_class.key_for('123')
with_redis do |redis|
- expect(redis.exists(key)).to eq(false)
+ expect(redis.exists?(key)).to eq(false)
end
end
end
@@ -48,7 +48,7 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
key = described_class.key_for('123')
with_redis do |redis|
- expect(redis.exists(key)).to eq(false)
+ expect(redis.exists?(key)).to eq(false)
end
end
end
diff --git a/spec/lib/gitlab/slash_commands/issue_new_spec.rb b/spec/lib/gitlab/slash_commands/issue_new_spec.rb
index c17cee887ee..29a941f3691 100644
--- a/spec/lib/gitlab/slash_commands/issue_new_spec.rb
+++ b/spec/lib/gitlab/slash_commands/issue_new_spec.rb
@@ -53,6 +53,21 @@ RSpec.describe Gitlab::SlashCommands::IssueNew do
expect(subject[:response_type]).to be(:ephemeral)
expect(subject[:text]).to match("- Title is too long")
end
+
+ context 'when create issue service return an unrecoverable error' do
+ let(:regex_match) { described_class.match("issue create title}") }
+
+ before do
+ allow_next_instance_of(Issues::CreateService) do |create_service|
+ allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'unauthorized'))
+ end
+ end
+
+ it 'displays the errors' do
+ expect(subject[:response_type]).to be(:ephemeral)
+ expect(subject[:text]).to eq('unauthorized')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ssh_public_key_spec.rb b/spec/lib/gitlab/ssh_public_key_spec.rb
index 114a18cf99a..a2524314458 100644
--- a/spec/lib/gitlab/ssh_public_key_spec.rb
+++ b/spec/lib/gitlab/ssh_public_key_spec.rb
@@ -88,12 +88,12 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true, fips_mode: false do
it 'returns all supported algorithms' do
expect(described_class.supported_algorithms).to eq(
%w(
- ssh-rsa
- ssh-dss
- ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
- ssh-ed25519
- sk-ecdsa-sha2-nistp256@openssh.com
- sk-ssh-ed25519@openssh.com
+ ssh-rsa
+ ssh-dss
+ ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
+ ssh-ed25519
+ sk-ecdsa-sha2-nistp256@openssh.com
+ sk-ssh-ed25519@openssh.com
)
)
end
@@ -102,12 +102,12 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true, fips_mode: false do
it 'returns all supported algorithms' do
expect(described_class.supported_algorithms).to eq(
%w(
- ssh-rsa
- ssh-dss
- ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
- ssh-ed25519
- sk-ecdsa-sha2-nistp256@openssh.com
- sk-ssh-ed25519@openssh.com
+ ssh-rsa
+ ssh-dss
+ ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
+ ssh-ed25519
+ sk-ecdsa-sha2-nistp256@openssh.com
+ sk-ssh-ed25519@openssh.com
)
)
end
diff --git a/spec/lib/gitlab/tracking/service_ping_context_spec.rb b/spec/lib/gitlab/tracking/service_ping_context_spec.rb
new file mode 100644
index 00000000000..d70dfaa4e0b
--- /dev/null
+++ b/spec/lib/gitlab/tracking/service_ping_context_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::ServicePingContext do
+ describe '#init' do
+ it 'does not accept unsupported data sources' do
+ expect { described_class.new(data_source: :random, event: 'event a') }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe '#to_context' do
+ let(:subject) { described_class.new(data_source: :redis_hll, event: 'sample_event') }
+
+ it 'contains event_name' do
+ expect(subject.to_context.to_json.dig(:data, :event_name)).to eq('sample_event')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
index 8e02f4f562c..76eec2755df 100644
--- a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
@@ -235,10 +235,27 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
end
end
- it 'allows for YAML aliases in aggregated metrics configs' do
- expect(YAML).to receive(:safe_load).with(kind_of(String), aliases: true).at_least(:once)
+ context 'legacy aggregated metrics configuration' do
+ let(:temp_dir) { Dir.mktmpdir }
+ let(:temp_file) { Tempfile.new(%w[common .yml], temp_dir) }
+
+ before do
+ stub_const("#{namespace}::AGGREGATED_METRICS_PATH", File.expand_path('*.yml', temp_dir))
+ File.open(temp_file.path, "w+b") do |file|
+ file.write [aggregated_metric(name: "gmau_1", time_frame: '7d')].to_yaml
+ end
+ end
+
+ after do
+ temp_file.unlink
+ FileUtils.remove_entry(temp_dir) if Dir.exist?(temp_dir)
+ end
- described_class.new(recorded_at)
+ it 'allows for YAML aliases in aggregated metrics configs' do
+ expect(YAML).to receive(:safe_load).with(kind_of(String), aliases: true).at_least(:once)
+
+ described_class.new(recorded_at)
+ end
end
describe '.aggregated_metrics_weekly_data' do
@@ -260,5 +277,132 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
it_behaves_like 'database_sourced_aggregated_metrics'
it_behaves_like 'redis_sourced_aggregated_metrics'
end
+
+ describe '.calculate_count_for_aggregation' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with valid configuration' do
+ where(:number_of_days, :operator, :datasource, :expected_method) do
+ 28 | 'AND' | 'redis' | :calculate_metrics_intersections
+ 7 | 'AND' | 'redis' | :calculate_metrics_intersections
+ 28 | 'AND' | 'database' | :calculate_metrics_intersections
+ 7 | 'AND' | 'database' | :calculate_metrics_intersections
+ 28 | 'OR' | 'redis' | :calculate_metrics_union
+ 7 | 'OR' | 'redis' | :calculate_metrics_union
+ 28 | 'OR' | 'database' | :calculate_metrics_union
+ 7 | 'OR' | 'database' | :calculate_metrics_union
+ end
+
+ with_them do
+ let(:time_frame) { "#{number_of_days}d" }
+ let(:start_date) { number_of_days.days.ago.to_date }
+ let(:params) { { start_date: start_date, end_date: end_date, recorded_at: recorded_at } }
+ let(:aggregate) do
+ {
+ source: datasource,
+ operator: operator,
+ events: %w[event1 event2]
+ }
+ end
+
+ subject(:calculate_count_for_aggregation) do
+ described_class
+ .new(recorded_at)
+ .calculate_count_for_aggregation(aggregation: aggregate, time_frame: time_frame)
+ end
+
+ it 'returns the number of unique events for aggregation', :aggregate_failures do
+ expect(namespace::SOURCES[datasource])
+ .to receive(expected_method)
+ .with(params.merge(metric_names: %w[event1 event2]))
+ .and_return(5)
+ expect(calculate_count_for_aggregation).to eq(5)
+ end
+ end
+ end
+
+ context 'with invalid configuration' do
+ where(:time_frame, :operator, :datasource, :expected_error) do
+ '28d' | 'SUM' | 'redis' | namespace::UnknownAggregationOperator
+ '7d' | 'AND' | 'mongodb' | namespace::UnknownAggregationSource
+ 'all' | 'AND' | 'redis' | namespace::DisallowedAggregationTimeFrame
+ end
+
+ with_them do
+ let(:aggregate) do
+ {
+ source: datasource,
+ operator: operator,
+ events: %w[event1 event2]
+ }
+ end
+
+ subject(:calculate_count_for_aggregation) do
+ described_class
+ .new(recorded_at)
+ .calculate_count_for_aggregation(aggregation: aggregate, time_frame: time_frame)
+ end
+
+ context 'with non prod environment' do
+ it 'raises error' do
+ expect { calculate_count_for_aggregation }.to raise_error expected_error
+ end
+ end
+
+ context 'with prod environment' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'returns fallback value' do
+ expect(calculate_count_for_aggregation).to be(-1)
+ end
+ end
+ end
+ end
+
+ context 'when union data is not available' do
+ subject(:calculate_count_for_aggregation) do
+ described_class
+ .new(recorded_at)
+ .calculate_count_for_aggregation(aggregation: aggregate, time_frame: time_frame)
+ end
+
+ where(:time_frame, :operator, :datasource) do
+ '28d' | 'OR' | 'redis'
+ '7d' | 'OR' | 'database'
+ end
+
+ with_them do
+ before do
+ allow(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).and_raise(sources::UnionNotAvailable)
+ end
+
+ let(:aggregate) do
+ {
+ source: datasource,
+ operator: operator,
+ events: %w[event1 event2]
+ }
+ end
+
+ context 'with non prod environment' do
+ it 'raises error' do
+ expect { calculate_count_for_aggregation }.to raise_error sources::UnionNotAvailable
+ end
+ end
+
+ context 'with prod environment' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'returns fallback value' do
+ expect(calculate_count_for_aggregation).to be(-1)
+ end
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/aggregated_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/aggregated_metric_spec.rb
new file mode 100644
index 00000000000..3e7b13e21c1
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/aggregated_metric_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::AggregatedMetric, :clean_gitlab_redis_shared_state do
+ using RSpec::Parameterized::TableSyntax
+ before do
+ # weekly AND 1 weekly OR 2
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_unapprove, values: 1, time: 1.week.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_unapprove, values: 2, time: 1.week.ago)
+
+ # monthly AND 2 weekly OR 3
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_unapprove, values: 3, time: 2.weeks.ago)
+
+ # out of date range
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 3, time: 2.months.ago)
+
+ # database events
+ Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll
+ .save_aggregated_metrics(
+ metric_name: :i_quickactions_approve,
+ time_period: { created_at: (1.week.ago..Date.current) },
+ recorded_at_timestamp: Time.current,
+ data: ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1)
+ )
+ Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll
+ .save_aggregated_metrics(
+ metric_name: :i_quickactions_unapprove,
+ time_period: { created_at: (1.week.ago..Date.current) },
+ recorded_at_timestamp: Time.current,
+ data: ::Gitlab::Database::PostgresHll::Buckets.new(10 => 1, 56 => 1)
+ )
+ end
+
+ where(:data_source, :time_frame, :operator, :expected_value) do
+ 'redis_hll' | '28d' | 'AND' | 2
+ 'redis_hll' | '28d' | 'OR' | 3
+ 'redis_hll' | '7d' | 'AND' | 1
+ 'redis_hll' | '7d' | 'OR' | 2
+ 'database' | '7d' | 'OR' | 3.0
+ 'database' | '7d' | 'AND' | 1.0
+ end
+
+ with_them do
+ let(:error_rate) { Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE }
+ let(:metric_definition) do
+ {
+ data_source: data_source,
+ time_frame: time_frame,
+ options: {
+ aggregate: {
+ operator: operator
+ },
+ events: %w[
+ i_quickactions_approve
+ i_quickactions_unapprove
+ ]
+ }
+ }
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ it 'has correct value' do
+ expect(described_class.new(metric_definition).value).to be_within(error_rate).percent_of(expected_value)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb
new file mode 100644
index 00000000000..757adee6117
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DistinctCountProjectsWithExpirationPolicyDisabledMetric do
+ before_all do
+ create(:container_expiration_policy, enabled: false)
+ create(:container_expiration_policy, enabled: false, created_at: 29.days.ago)
+ create(:container_expiration_policy, enabled: true)
+ end
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: '28d' } do
+ let(:expected_value) { 1 }
+ end
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'all' } do
+ let(:expected_value) { 2 }
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb
new file mode 100644
index 00000000000..061558085a1
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GitlabForJiraAppDirectInstallationsCountMetric do
+ before do
+ create(:jira_connect_subscription)
+ end
+
+ let(:expected_value) { 1 }
+ let(:expected_query) do
+ 'SELECT COUNT("jira_connect_installations"."id") FROM "jira_connect_installations"'\
+ ' INNER JOIN "jira_connect_subscriptions" ON "jira_connect_subscriptions"."jira_connect_installation_id"'\
+ ' = "jira_connect_installations"."id"'
+ end
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' }
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb
new file mode 100644
index 00000000000..4535bab7702
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GitlabForJiraAppProxyInstallationsCountMetric do
+ let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'http://self-managed-gitlab.com') }
+
+ before do
+ create(:jira_connect_subscription, installation: installation)
+ end
+
+ let(:expected_value) { 1 }
+ let(:expected_query) do
+ 'SELECT COUNT("jira_connect_installations"."id") FROM "jira_connect_installations"'\
+ ' WHERE "jira_connect_installations"."instance_url" IS NOT NULL'
+ end
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' }
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb
new file mode 100644
index 00000000000..c0ac00c9cdd
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::MergeRequestWidgetExtensionMetric,
+ :clean_gitlab_redis_shared_state do
+ before do
+ 4.times do
+ Gitlab::UsageDataCounters::MergeRequestWidgetExtensionCounter.count(:terraform_count_expand)
+ end
+ end
+
+ let(:expected_value) { 4 }
+
+ it_behaves_like 'a correct instrumented metric value', {
+ options: { event: 'expand', widget: 'terraform' },
+ time_frame: 'all'
+ }
+
+ it 'raises an exception if widget option is not present' do
+ expect do
+ described_class.new(options: { event: 'expand' }, time_frame: 'all')
+ end.to raise_error(ArgumentError, /'widget' option is required/)
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
index 80ae5c6fd21..c4d6edd43e1 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
@@ -11,14 +11,21 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisMetric, :clean_git
let(:expected_value) { 4 }
- it_behaves_like 'a correct instrumented metric value', { options: { event: 'pushes', prefix: 'source_code' } }
+ it_behaves_like 'a correct instrumented metric value', {
+ options: { event: 'pushes', prefix: 'source_code' },
+ time_frame: 'all'
+ }
it 'raises an exception if event option is not present' do
- expect { described_class.new(prefix: 'source_code') }.to raise_error(ArgumentError)
+ expect do
+ described_class.new(options: { prefix: 'source_code' }, time_frame: 'all')
+ end.to raise_error(ArgumentError, /'event' option is required/)
end
it 'raises an exception if prefix option is not present' do
- expect { described_class.new(event: 'pushes') }.to raise_error(ArgumentError)
+ expect do
+ described_class.new(options: { event: 'pushes' }, time_frame: 'all')
+ end.to raise_error(ArgumentError, /'prefix' option is required/)
end
describe 'children classes' do
@@ -55,7 +62,22 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisMetric, :clean_git
end
it_behaves_like 'a correct instrumented metric value', {
- options: { event: 'merge_requests_count', prefix: 'web_ide', include_usage_prefix: false }
+ options: { event: 'merge_requests_count', prefix: 'web_ide', include_usage_prefix: false },
+ time_frame: 'all'
+ }
+ end
+
+ context "with prefix disabled" do
+ let(:expected_value) { 3 }
+
+ before do
+ 3.times do
+ Gitlab::UsageDataCounters::SearchCounter.count(:all_searches)
+ end
+ end
+
+ it_behaves_like 'a correct instrumented metric value', {
+ options: { event: 'all_searches_count', prefix: nil, include_usage_prefix: false }, time_frame: 'all'
}
end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric_spec.rb
new file mode 100644
index 00000000000..3e315692d0a
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::WorkItemsActivityAggregatedMetric do
+ let(:metric_definition) do
+ {
+ data_source: 'redis_hll',
+ time_frame: time_frame,
+ options: {
+ aggregate: {
+ operator: 'OR'
+ },
+ events: %w[
+ users_creating_work_items
+ users_updating_work_item_title
+ users_updating_work_item_dates
+ users_updating_work_item_iteration
+ ]
+ }
+ }
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ where(:time_frame) { [['28d'], ['7d']] }
+
+ with_them do
+ describe '#available?' do
+ it 'returns false without track_work_items_activity feature' do
+ stub_feature_flags(track_work_items_activity: false)
+
+ expect(described_class.new(metric_definition).available?).to eq(false)
+ end
+
+ it 'returns true with track_work_items_activity feature' do
+ stub_feature_flags(track_work_items_activity: true)
+
+ expect(described_class.new(metric_definition).available?).to eq(true)
+ end
+ end
+
+ describe '#value', :clean_gitlab_redis_shared_state do
+ let(:counter) { Gitlab::UsageDataCounters::HLLRedisCounter }
+
+ before do
+ counter.track_event(:users_creating_work_items, values: 1, time: 1.week.ago)
+ counter.track_event(:users_updating_work_item_title, values: 1, time: 1.week.ago)
+ counter.track_event(:users_updating_work_item_dates, values: 2, time: 1.week.ago)
+ counter.track_event(:users_updating_work_item_iteration, values: 2, time: 1.week.ago)
+ end
+
+ it 'has correct value' do
+ expect(described_class.new(metric_definition).value).to eq 2
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data/topology_spec.rb b/spec/lib/gitlab/usage_data/topology_spec.rb
index dfdf8eaabe8..3fb87e77457 100644
--- a/spec/lib/gitlab/usage_data/topology_spec.rb
+++ b/spec/lib/gitlab/usage_data/topology_spec.rb
@@ -523,210 +523,210 @@ RSpec.describe Gitlab::UsageData::Topology do
receive(:query)
.with(/gitlab_usage_ping:ops:rate/)
.and_return(result || [
- {
- 'metric' => { 'component' => 'http_requests', 'service' => 'workhorse' },
- 'value' => [1000, '0.01']
- }
- ])
+ {
+ 'metric' => { 'component' => 'http_requests', 'service' => 'workhorse' },
+ 'value' => [1000, '0.01']
+ }
+ ])
end
def receive_query_apdex_ratio_query(result: nil)
receive(:query)
.with(/gitlab_usage_ping:sql_duration_apdex:ratio_rate5m/)
.and_return(result || [
- {
- 'metric' => {},
- 'value' => [1000, '0.996']
- }
- ])
+ {
+ 'metric' => {},
+ 'value' => [1000, '0.996']
+ }
+ ])
end
def receive_node_memory_query(result: nil)
receive(:query)
.with(/node_memory_total_bytes/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance1:8080' },
- 'value' => [1000, '512']
- },
- {
- 'metric' => { 'instance' => 'instance2:8090' },
- 'value' => [1000, '1024']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance1:8080' },
+ 'value' => [1000, '512']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:8090' },
+ 'value' => [1000, '1024']
+ }
+ ])
end
def receive_node_memory_utilization_query(result: nil)
receive(:query)
.with(/node_memory_utilization/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance1:8080' },
- 'value' => [1000, '0.45']
- },
- {
- 'metric' => { 'instance' => 'instance2:8090' },
- 'value' => [1000, '0.25']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance1:8080' },
+ 'value' => [1000, '0.45']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:8090' },
+ 'value' => [1000, '0.25']
+ }
+ ])
end
def receive_node_cpu_count_query(result: nil)
receive(:query)
.with(/node_cpus/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance2:8090' },
- 'value' => [1000, '16']
- },
- {
- 'metric' => { 'instance' => 'instance1:8080' },
- 'value' => [1000, '8']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance2:8090' },
+ 'value' => [1000, '16']
+ },
+ {
+ 'metric' => { 'instance' => 'instance1:8080' },
+ 'value' => [1000, '8']
+ }
+ ])
end
def receive_node_cpu_utilization_query(result: nil)
receive(:query)
.with(/node_cpu_utilization/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance2:8090' },
- 'value' => [1000, '0.2']
- },
- {
- 'metric' => { 'instance' => 'instance1:8080' },
- 'value' => [1000, '0.1']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance2:8090' },
+ 'value' => [1000, '0.2']
+ },
+ {
+ 'metric' => { 'instance' => 'instance1:8080' },
+ 'value' => [1000, '0.1']
+ }
+ ])
end
def receive_node_uname_info_query(result: nil)
receive(:query)
.with('node_uname_info')
.and_return(result || [
- {
- "metric" => {
- "__name__" => "node_uname_info",
- "domainname" => "(none)",
- "instance" => "instance1:9100",
- "job" => "node_exporter",
- "machine" => "x86_64",
- "nodename" => "instance1",
- "release" => "4.19.76-linuxkit",
- "sysname" => "Linux"
- },
- "value" => [1592463033.359, "1"]
- },
- {
- "metric" => {
- "__name__" => "node_uname_info",
- "domainname" => "(none)",
- "instance" => "instance2:9100",
- "job" => "node_exporter",
- "machine" => "x86_64",
- "nodename" => "instance2",
- "release" => "4.15.0-101-generic",
- "sysname" => "Linux"
- },
- "value" => [1592463033.359, "1"]
- }
- ])
+ {
+ "metric" => {
+ "__name__" => "node_uname_info",
+ "domainname" => "(none)",
+ "instance" => "instance1:9100",
+ "job" => "node_exporter",
+ "machine" => "x86_64",
+ "nodename" => "instance1",
+ "release" => "4.19.76-linuxkit",
+ "sysname" => "Linux"
+ },
+ "value" => [1592463033.359, "1"]
+ },
+ {
+ "metric" => {
+ "__name__" => "node_uname_info",
+ "domainname" => "(none)",
+ "instance" => "instance2:9100",
+ "job" => "node_exporter",
+ "machine" => "x86_64",
+ "nodename" => "instance2",
+ "release" => "4.15.0-101-generic",
+ "sysname" => "Linux"
+ },
+ "value" => [1592463033.359, "1"]
+ }
+ ])
end
def receive_node_service_memory_rss_query(result: nil)
receive(:query)
.with(/process_resident_memory_bytes/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
- 'value' => [1000, '300']
- },
- {
- 'metric' => { 'instance' => 'instance1:8090', 'job' => 'gitlab-sidekiq' },
- 'value' => [1000, '303']
- },
- # instance 2: runs a dedicated Sidekiq + Redis (which uses a different metric name)
- {
- 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
- 'value' => [1000, '400']
- },
- {
- 'metric' => { 'instance' => 'instance2:9121', 'job' => 'redis' },
- 'value' => [1000, '402']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
+ 'value' => [1000, '300']
+ },
+ {
+ 'metric' => { 'instance' => 'instance1:8090', 'job' => 'gitlab-sidekiq' },
+ 'value' => [1000, '303']
+ },
+ # instance 2: runs a dedicated Sidekiq + Redis (which uses a different metric name)
+ {
+ 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
+ 'value' => [1000, '400']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:9121', 'job' => 'redis' },
+ 'value' => [1000, '402']
+ }
+ ])
end
def receive_node_service_memory_uss_query(result: nil)
receive(:query)
.with(/process_unique_memory_bytes/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
- 'value' => [1000, '301']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
+ 'value' => [1000, '301']
+ }
+ ])
end
def receive_node_service_memory_pss_query(result: nil)
receive(:query)
.with(/process_proportional_memory_bytes/, an_instance_of(Hash))
.and_return(result || [
- {
- 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
- 'value' => [1000, '302']
- },
- {
- 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
- 'value' => [1000, '401']
- }
- ])
+ {
+ 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
+ 'value' => [1000, '302']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
+ 'value' => [1000, '401']
+ }
+ ])
end
def receive_node_service_process_count_query(result: nil)
receive(:query)
.with(/service_process:count/, an_instance_of(Hash))
.and_return(result || [
- # instance 1
- {
- 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
- 'value' => [1000, '10']
- },
- {
- 'metric' => { 'instance' => 'instance1:8090', 'job' => 'gitlab-sidekiq' },
- 'value' => [1000, '5']
- },
- # instance 2
- {
- 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
- 'value' => [1000, '15']
- },
- {
- 'metric' => { 'instance' => 'instance2:9121', 'job' => 'redis' },
- 'value' => [1000, '1']
- },
- {
- 'metric' => { 'instance' => 'instance2:8080', 'job' => 'registry' },
- 'value' => [1000, '1']
- }
- ])
+ # instance 1
+ {
+ 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails' },
+ 'value' => [1000, '10']
+ },
+ {
+ 'metric' => { 'instance' => 'instance1:8090', 'job' => 'gitlab-sidekiq' },
+ 'value' => [1000, '5']
+ },
+ # instance 2
+ {
+ 'metric' => { 'instance' => 'instance2:8090', 'job' => 'gitlab-sidekiq' },
+ 'value' => [1000, '15']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:9121', 'job' => 'redis' },
+ 'value' => [1000, '1']
+ },
+ {
+ 'metric' => { 'instance' => 'instance2:8080', 'job' => 'registry' },
+ 'value' => [1000, '1']
+ }
+ ])
end
def receive_node_service_app_server_workers_query(result: nil)
receive(:query)
.with(/app_server_workers/, an_instance_of(Hash))
.and_return(result || [
- # instance 1
- {
- 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails', 'server' => 'puma' },
- 'value' => [1000, '2']
- },
- # instance 2
- {
- 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'puma' },
- 'value' => [1000, '1']
- }
- ])
+ # instance 1
+ {
+ 'metric' => { 'instance' => 'instance1:8080', 'job' => 'gitlab-rails', 'server' => 'puma' },
+ 'value' => [1000, '2']
+ },
+ # instance 2
+ {
+ 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'puma' },
+ 'value' => [1000, '1']
+ }
+ ])
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
index 6a37bfd106d..1ca0bb0e9ea 100644
--- a/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
@@ -65,17 +65,11 @@ RSpec.describe Gitlab::UsageDataCounters::CiTemplateUniqueCounter do
context 'with implicit includes', :snowplow do
let(:config_source) { :auto_devops_source }
- [
- ['', ['Auto-DevOps.gitlab-ci.yml']],
- ['Jobs', described_class.ci_templates('lib/gitlab/ci/templates/Jobs')],
- ['Security', described_class.ci_templates('lib/gitlab/ci/templates/Security')]
- ].each do |directory, templates|
- templates.each do |template|
- context "for #{template}" do
- let(:template_path) { File.join(directory, template) }
-
- include_examples 'tracks template'
- end
+ described_class.all_included_templates('Auto-DevOps.gitlab-ci.yml').each do |template_name|
+ context "for #{template_name}" do
+ let(:template_path) { Gitlab::Template::GitlabCiYmlTemplate.find(template_name.delete_suffix('.gitlab-ci.yml')).full_name }
+
+ include_examples 'tracks template'
end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
index 01396602f29..e122d9a3026 100644
--- a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
@@ -6,19 +6,22 @@ require 'spec_helper'
# NOTE: ONLY user related metrics to be added to the aggregates - otherwise add it to the exception list
RSpec.describe 'Code review events' do
it 'the aggregated metrics contain all the code review metrics' do
- path = Rails.root.join('config/metrics/aggregates/code_review.yml')
- aggregated_events = YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
-
- code_review_aggregated_events = aggregated_events
- .map { |event| event['events'] }
- .flatten
- .uniq
-
code_review_events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category("code_review")
+ code_review_aggregated_events = Gitlab::Usage::MetricDefinition.all.flat_map do |definition|
+ next [] unless code_review_aggregated_metric?(definition.attributes)
+
+ definition.attributes.dig(:options, :events)
+ end.uniq
exceptions = %w[i_code_review_mr_diffs i_code_review_mr_with_invalid_approvers i_code_review_mr_single_file_diffs i_code_review_total_suggestions_applied i_code_review_total_suggestions_added i_code_review_create_note_in_ipynb_diff i_code_review_create_note_in_ipynb_diff_mr i_code_review_create_note_in_ipynb_diff_commit]
code_review_aggregated_events += exceptions
expect(code_review_events - code_review_aggregated_events).to be_empty
end
+
+ def code_review_aggregated_metric?(attributes)
+ return false unless attributes[:product_group] == 'code_review' && attributes[:status] == 'active'
+
+ attributes[:instrumentation_class] == 'AggregatedMetric'
+ end
end
diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
index 3fb2532521a..d0b935d59dd 100644
--- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
@@ -24,8 +24,10 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
context 'migration to instrumentation classes data collection' do
let_it_be(:instrumented_events) do
+ instrumentation_classes = %w[AggregatedMetric RedisHLLMetric]
::Gitlab::Usage::MetricDefinition.all.map do |definition|
- next unless definition.attributes[:instrumentation_class] == 'RedisHLLMetric' && definition.available?
+ next unless definition.available?
+ next unless instrumentation_classes.include?(definition.attributes[:instrumentation_class])
definition.attributes.dig(:options, :events)&.sort
end.compact.to_set
@@ -96,21 +98,17 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'source_code',
'incident_management',
'incident_management_alerts',
- 'incident_management_oncall',
'testing',
'issues_edit',
- 'ci_secrets_management',
'snippets',
'code_review',
'terraform',
'ci_templates',
'quickactions',
'pipeline_authoring',
- 'epics_usage',
'secure',
'importer',
'geo',
- 'growth',
'work_items',
'ci_users',
'error_tracking',
diff --git a/spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb
index 0bcdbe82a7a..2d251017c87 100644
--- a/spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb
@@ -28,4 +28,12 @@ RSpec.describe Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter, :clean_
it_behaves_like 'work item unique counter'
end
+
+ describe '.track_work_item_labels_changed_action' do
+ subject(:track_event) { described_class.track_work_item_labels_changed_action(author: user) }
+
+ let(:event_name) { described_class::WORK_ITEM_LABELS_CHANGED }
+
+ it_behaves_like 'work item unique counter'
+ end
end
diff --git a/spec/lib/gitlab/usage_data_metrics_spec.rb b/spec/lib/gitlab/usage_data_metrics_spec.rb
index ed0eabf1b4d..5d58933f1fd 100644
--- a/spec/lib/gitlab/usage_data_metrics_spec.rb
+++ b/spec/lib/gitlab/usage_data_metrics_spec.rb
@@ -31,6 +31,8 @@ RSpec.describe Gitlab::UsageDataMetrics do
it 'includes counts keys', :aggregate_failures do
expect(subject[:counts]).to include(:boards)
expect(subject[:counts]).to include(:issues)
+ expect(subject[:counts]).to include(:gitlab_for_jira_app_direct_installations)
+ expect(subject[:counts]).to include(:gitlab_for_jira_app_proxy_installations)
end
it 'includes usage_activity_by_stage keys' do
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 46ed4b57d3a..cb645ae3e53 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -624,7 +624,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it 'gathers usage data' do
expect(subject[:projects_with_expiration_policy_enabled]).to eq 19
- expect(subject[:projects_with_expiration_policy_disabled]).to eq 5
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_unset]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_1]).to eq 1
@@ -758,13 +757,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
- describe '.usage_counters' do
- subject { described_class.usage_counters }
-
- it { is_expected.to include(:kubernetes_agent_gitops_sync) }
- it { is_expected.to include(:kubernetes_agent_k8s_api_proxy_request) }
- end
-
describe '.usage_data_counters' do
subject { described_class.usage_data_counters }
@@ -1057,12 +1049,13 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
before do
allow(described_class).to receive(:operating_system).and_return('ubuntu-20.04')
- expect(prometheus_client).to receive(:query).with(/gitlab_usage_ping:gitaly_apdex:ratio_avg_over_time_5m/).and_return([
- {
- 'metric' => {},
- 'value' => [1616016381.473, '0.95']
- }
- ])
+ expect(prometheus_client).to receive(:query)
+ .with(/gitlab_usage_ping:gitaly_apdex:ratio_avg_over_time_5m/)
+ .and_return(
+ [
+ { 'metric' => {},
+ 'value' => [1616016381.473, '0.95'] }
+ ])
expect(described_class).to receive(:with_prometheus_client).and_yield(prometheus_client)
end
diff --git a/spec/lib/gitlab/user_access_snippet_spec.rb b/spec/lib/gitlab/user_access_snippet_spec.rb
index 4143a3017e8..916e920e2ac 100644
--- a/spec/lib/gitlab/user_access_snippet_spec.rb
+++ b/spec/lib/gitlab/user_access_snippet_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::UserAccessSnippet do
end
describe '#can_push_to_branch?' do
- include ProjectHelpers
+ include UserHelpers
[:anonymous, :non_member, :guest, :reporter, :maintainer, :admin, :author].each do |membership|
context membership.to_s do
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 61323f0646b..d1fdaf7a9db 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -582,11 +582,12 @@ RSpec.describe Gitlab::Utils do
end
it 'sorts items like the regular sort_by' do
- expect(sorted_list).to eq([
- { name: 'obj 2', priority: 1 },
- { name: 'obj 1', priority: 2 },
- { name: 'obj 3', priority: 3 }
- ])
+ expect(sorted_list).to eq(
+ [
+ { name: 'obj 2', priority: 1 },
+ { name: 'obj 1', priority: 2 },
+ { name: 'obj 3', priority: 3 }
+ ])
end
end
end
diff --git a/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb b/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
index 8d4629bf48b..7d96adf95e8 100644
--- a/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
+++ b/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
@@ -150,29 +150,6 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Terminal do
}
)
end
-
- context 'when the FF ci_variables_refactoring_to_variable is disabled' do
- let(:entry_without_ff) { described_class.new(config, with_image_ports: true) }
-
- before do
- stub_feature_flags(ci_variables_refactoring_to_variable: false)
- entry_without_ff.compose!
- end
-
- it 'returns correct value' do
- expect(entry_without_ff.value)
- .to eq(
- tag_list: ['webide'],
- job_variables: [{ key: 'KEY', value: 'value', public: true }],
- options: {
- image: { name: "image:1.0" },
- services: [{ name: "mysql" }],
- before_script: %w[ls pwd],
- script: ['sleep 100']
- }
- )
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/webpack/manifest_spec.rb b/spec/lib/gitlab/webpack/manifest_spec.rb
index 08b4774dd67..24a36258379 100644
--- a/spec/lib/gitlab/webpack/manifest_spec.rb
+++ b/spec/lib/gitlab/webpack/manifest_spec.rb
@@ -66,10 +66,11 @@ RSpec.describe Gitlab::Webpack::Manifest do
describe "webpack errors" do
context "when webpack has 'Module build failed' errors in its manifest" do
it "errors" do
- error_manifest = Gitlab::Json.parse(manifest).merge("errors" => [
- "somethingModule build failed something",
- "I am an error"
- ]).to_json
+ error_manifest = Gitlab::Json.parse(manifest).merge("errors" =>
+ [
+ "somethingModule build failed something",
+ "I am an error"
+ ]).to_json
stub_request(:get, "http://hostname:2000/public_path/my_manifest.json").to_return(body: error_manifest, status: 200)
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.to raise_error(Gitlab::Webpack::Manifest::WebpackError)
diff --git a/spec/lib/gitlab/x509/signature_spec.rb b/spec/lib/gitlab/x509/signature_spec.rb
index 5626e49bfe1..31f66232f38 100644
--- a/spec/lib/gitlab/x509/signature_spec.rb
+++ b/spec/lib/gitlab/x509/signature_spec.rb
@@ -30,6 +30,20 @@ RSpec.describe Gitlab::X509::Signature do
expect(signature.verification_status).to eq(:verified)
end
+ it 'returns a verified signature if email does match, case-insensitively' do
+ signature = described_class.new(
+ X509Helpers::User1.signed_commit_signature,
+ X509Helpers::User1.signed_commit_base_data,
+ X509Helpers::User1.certificate_email.upcase,
+ X509Helpers::User1.signed_commit_time
+ )
+
+ expect(signature.x509_certificate).to have_attributes(certificate_attributes)
+ expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
+ expect(signature.verified_signature).to be_truthy
+ expect(signature.verification_status).to eq(:verified)
+ end
+
context "if the email matches but isn't confirmed" do
let!(:user) { create(:user, :unconfirmed, email: X509Helpers::User1.certificate_email) }
diff --git a/spec/lib/gitlab/x509/tag_spec.rb b/spec/lib/gitlab/x509/tag_spec.rb
index f52880cfc52..e20ef688db5 100644
--- a/spec/lib/gitlab/x509/tag_spec.rb
+++ b/spec/lib/gitlab/x509/tag_spec.rb
@@ -5,8 +5,8 @@ RSpec.describe Gitlab::X509::Tag do
subject(:signature) { described_class.new(project.repository, tag).signature }
describe '#signature' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
describe 'signed tag' do
let(:tag) { project.repository.find_tag('v1.1.1') }
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index 0f117f495d1..0c207161927 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -17,17 +17,19 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
let(:tier) { 'mock-tier' }
let(:database_list) do
- Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: [
- Google::Apis::SqladminV1beta4::Database.new(name: 'db_01', instance: database_instance),
- Google::Apis::SqladminV1beta4::Database.new(name: 'db_02', instance: database_instance)
- ])
+ Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(
+ items: [
+ Google::Apis::SqladminV1beta4::Database.new(name: 'db_01', instance: database_instance),
+ Google::Apis::SqladminV1beta4::Database.new(name: 'db_02', instance: database_instance)
+ ])
end
let(:user_list) do
- Google::Apis::SqladminV1beta4::ListUsersResponse.new(items: [
- Google::Apis::SqladminV1beta4::User.new(name: 'user_01', instance: database_instance),
- Google::Apis::SqladminV1beta4::User.new(name: 'user_02', instance: database_instance)
- ])
+ Google::Apis::SqladminV1beta4::ListUsersResponse.new(
+ items: [
+ Google::Apis::SqladminV1beta4::User.new(name: 'user_01', instance: database_instance),
+ Google::Apis::SqladminV1beta4::User.new(name: 'user_02', instance: database_instance)
+ ])
end
describe '.session_key_for_redirect_uri' do
diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb
index 9a0e83bfd5e..2a81142ea44 100644
--- a/spec/lib/object_storage/config_spec.rb
+++ b/spec/lib/object_storage/config_spec.rb
@@ -136,7 +136,6 @@ RSpec.describe ObjectStorage::Config do
let(:credentials) do
{
provider: 'Google',
- google_client_email: 'foo@gcp-project.example.com',
google_json_key_location: '/path/to/gcp.json'
}
end
diff --git a/spec/lib/peek/views/bullet_detailed_spec.rb b/spec/lib/peek/views/bullet_detailed_spec.rb
index ec2f798a320..6eaf8c50cc0 100644
--- a/spec/lib/peek/views/bullet_detailed_spec.rb
+++ b/spec/lib/peek/views/bullet_detailed_spec.rb
@@ -44,10 +44,11 @@ RSpec.describe Peek::Views::BulletDetailed do
expect(subject.key).to eq('bullet')
expect(subject.results[:calls]).to eq(2)
expect(subject.results[:warnings]).to eq([Peek::Views::BulletDetailed::WARNING_MESSAGE])
- expect(subject.results[:details]).to eq([
- { notification: 'Title 1: Body 1', backtrace: "first\nsecond\n" },
- { notification: 'Title 2: Body 2', backtrace: "first\nsecond\n" }
- ])
+ expect(subject.results[:details]).to eq(
+ [
+ { notification: 'Title 1: Body 1', backtrace: "first\nsecond\n" },
+ { notification: 'Title 2: Body 2', backtrace: "first\nsecond\n" }
+ ])
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 c5666724acf..ce368ad5bd6 100644
--- a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
@@ -207,6 +207,16 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
it_behaves_like 'the menu entry is available'
end
+
+ context 'when config harbor registry setting is not activated' do
+ before do
+ harbor_integration.update!(active: false)
+ end
+
+ let(:harbor_registry_enabled) { true }
+
+ it_behaves_like 'the menu entry is not available'
+ end
end
end
diff --git a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
index 25a65015847..878da747abe 100644
--- a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be_with_refind(:project) { create(:project, :repository) }
let_it_be(:guest) do
create(:user).tap { |u| project.add_guest(u) }
end
@@ -125,6 +125,34 @@ RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
specify { is_expected.to be_nil }
end
+
+ describe 'when issues are disabled' do
+ before do
+ project.issues_enabled = false
+ project.save!
+ end
+
+ specify { is_expected.not_to be_nil }
+ end
+
+ describe 'when merge requests are disabled' do
+ before do
+ project.merge_requests_enabled = false
+ project.save!
+ end
+
+ specify { is_expected.not_to be_nil }
+ end
+
+ describe 'when the issues and merge requests are disabled' do
+ before do
+ project.issues_enabled = false
+ project.merge_requests_enabled = false
+ project.save!
+ end
+
+ specify { is_expected.to be_nil }
+ end
end
end
end
diff --git a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
index 90ff04a2064..685ba0c31c7 100644
--- a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
@@ -45,30 +45,30 @@ RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu do
it { is_expected.to be_nil }
end
+ end
+
+ shared_examples 'split_operations_visibility_permissions FF disabled' do
+ before do
+ stub_feature_flags(split_operations_visibility_permissions: false)
+ end
- describe 'when split_operations_visibility_permissions FF is disabled' do
+ it { is_expected.not_to be_nil }
+
+ context 'and the feature is disabled' do
before do
- stub_feature_flags(split_operations_visibility_permissions: false)
+ project.update_attribute("#{item_id}_access_level", 'disabled')
end
it { is_expected.not_to be_nil }
+ end
- context 'and the feature is disabled' do
- before do
- project.update_attribute("#{item_id}_access_level", 'disabled')
- end
-
- it { is_expected.not_to be_nil }
+ context 'and operations is disabled' do
+ before do
+ project.update_attribute(:operations_access_level, 'disabled')
end
- context 'and operations is disabled' do
- before do
- project.update_attribute(:operations_access_level, 'disabled')
- end
-
- it do
- is_expected.to be_nil if [:environments, :feature_flags].include?(item_id)
- end
+ it do
+ is_expected.to be_nil if [:environments, :feature_flags].include?(item_id)
end
end
end
@@ -77,12 +77,14 @@ RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu do
let(:item_id) { :feature_flags }
it_behaves_like 'access rights checks'
+ it_behaves_like 'split_operations_visibility_permissions FF disabled'
end
describe 'Environments' do
let(:item_id) { :environments }
it_behaves_like 'access rights checks'
+ it_behaves_like 'split_operations_visibility_permissions FF disabled'
end
describe 'Releases' do
diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
index 6491ef823e9..b03269c424a 100644
--- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
describe 'Packages Registry' do
let(:item_id) { :packages_registry }
- shared_examples 'when user can read packages' do
+ context 'when user can read packages' do
context 'when config package setting is disabled' do
it 'the menu item is not added to list of menu items' do
stub_config(packages: { enabled: false })
@@ -85,25 +85,13 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
end
end
- shared_examples 'when user cannot read packages' do
+ context 'when user cannot read packages' do
let(:user) { nil }
it 'the menu item is not added to list of menu items' do
is_expected.to be_nil
end
end
-
- it_behaves_like 'when user can read packages'
- it_behaves_like 'when user cannot read packages'
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(read_package_policy_rule: false)
- end
-
- it_behaves_like 'when user can read packages'
- it_behaves_like 'when user cannot read packages'
- end
end
describe 'Container Registry' do
@@ -178,6 +166,15 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
is_expected.not_to be_nil
end
end
+
+ context 'when config harbor registry setting is not activated' do
+ it 'does not add the menu item to the list' do
+ stub_feature_flags(harbor_registry_integration: true)
+ project.harbor_integration.update!(active: false)
+
+ is_expected.to be_nil
+ end
+ end
end
end
end
diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
index fc181947e60..f26433306b6 100644
--- a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
@@ -34,5 +34,29 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do
end
end
end
+
+ context 'for menu items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ describe 'Contributors' do
+ let_it_be(:item_id) { :contributors }
+
+ context 'when analytics is disabled' do
+ before do
+ project.project_feature.update!(analytics_access_level: ProjectFeature::DISABLED)
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when analytics is enabled' do
+ before do
+ project.project_feature.update!(analytics_access_level: ProjectFeature::ENABLED)
+ end
+
+ it { is_expected.not_to be_nil }
+ end
+ end
+ end
end
end
diff --git a/spec/lib/system_check/incoming_email_check_spec.rb b/spec/lib/system_check/incoming_email_check_spec.rb
index 5d93b810045..cf3fd3b7967 100644
--- a/spec/lib/system_check/incoming_email_check_spec.rb
+++ b/spec/lib/system_check/incoming_email_check_spec.rb
@@ -26,11 +26,12 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
end
it 'runs IMAP and mailroom checks' do
- expect(SystemCheck).to receive(:run).with('Reply by email', [
- SystemCheck::IncomingEmail::ImapAuthenticationCheck,
- SystemCheck::IncomingEmail::MailRoomEnabledCheck,
- SystemCheck::IncomingEmail::MailRoomRunningCheck
- ])
+ expect(SystemCheck).to receive(:run).with('Reply by email',
+ [
+ SystemCheck::IncomingEmail::ImapAuthenticationCheck,
+ SystemCheck::IncomingEmail::MailRoomEnabledCheck,
+ SystemCheck::IncomingEmail::MailRoomRunningCheck
+ ])
subject.multi_check
end
@@ -42,10 +43,11 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
end
it 'runs mailroom checks' do
- expect(SystemCheck).to receive(:run).with('Reply by email', [
- SystemCheck::IncomingEmail::MailRoomEnabledCheck,
- SystemCheck::IncomingEmail::MailRoomRunningCheck
- ])
+ expect(SystemCheck).to receive(:run).with('Reply by email',
+ [
+ SystemCheck::IncomingEmail::MailRoomEnabledCheck,
+ SystemCheck::IncomingEmail::MailRoomRunningCheck
+ ])
subject.multi_check
end
diff --git a/spec/lib/unnested_in_filters/rewriter_spec.rb b/spec/lib/unnested_in_filters/rewriter_spec.rb
index a808aec7728..21bab42c95c 100644
--- a/spec/lib/unnested_in_filters/rewriter_spec.rb
+++ b/spec/lib/unnested_in_filters/rewriter_spec.rb
@@ -41,14 +41,15 @@ RSpec.describe UnnestedInFilters::Rewriter do
context 'when the order is a Keyset order' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'user_type',
- order_expression: User.arel_table['user_type'].desc,
- nullable: :not_nullable,
- distinct: false
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'user_type',
+ order_expression: User.arel_table['user_type'].desc,
+ nullable: :not_nullable,
+ distinct: false
+ )
+ ])
end
it { is_expected.to be_truthy }
@@ -152,14 +153,15 @@ RSpec.describe UnnestedInFilters::Rewriter do
context 'when the order is a Keyset order' do
let(:order) do
- Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'user_type',
- order_expression: User.arel_table['user_type'].desc,
- nullable: :not_nullable,
- distinct: false
- )
- ])
+ Gitlab::Pagination::Keyset::Order.build(
+ [
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'user_type',
+ order_expression: User.arel_table['user_type'].desc,
+ nullable: :not_nullable,
+ distinct: false
+ )
+ ])
end
it 'changes the query' do
diff --git a/spec/lib/version_check_spec.rb b/spec/lib/version_check_spec.rb
index 736a8f9595e..1803dd66ba7 100644
--- a/spec/lib/version_check_spec.rb
+++ b/spec/lib/version_check_spec.rb
@@ -9,6 +9,20 @@ RSpec.describe VersionCheck do
end
end
+ context 'reactive cache properties' do
+ describe '.reactive_cache_refresh_interval' do
+ it 'returns 12.hours' do
+ expect(described_class.reactive_cache_refresh_interval).to eq(12.hours)
+ end
+ end
+
+ describe '.reactive_cache_lifetime' do
+ it 'returns 7.days' do
+ expect(described_class.reactive_cache_lifetime).to eq(7.days)
+ end
+ end
+ end
+
describe '#calculate_reactive_cache' do
context 'response code is 200' do
before do
diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb
index fce55256922..767eddb7f98 100644
--- a/spec/mailers/emails/profile_spec.rb
+++ b/spec/mailers/emails/profile_spec.rb
@@ -246,6 +246,35 @@ RSpec.describe Emails::Profile do
end
end
+ describe 'user personal access token has been revoked' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { create(:personal_access_token, user: user) }
+
+ context 'when valid' do
+ subject { Notify.access_token_revoked_email(user, token.name) }
+
+ it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'a user cannot unsubscribe through footer link'
+
+ it 'is sent to the user' do
+ is_expected.to deliver_to user.email
+ end
+
+ it 'has the correct subject' do
+ is_expected.to have_subject /^A personal access token has been revoked$/i
+ end
+
+ it 'provides the names of the token' do
+ is_expected.to have_body_text /#{token.name}/
+ end
+
+ it 'includes the email reason' do
+ is_expected.to have_body_text %r{You're receiving this email because of your account on <a .*>localhost<\/a>}
+ end
+ end
+ end
+
describe 'SSH key notification' do
let_it_be_with_reload(:user) { create(:user) }
let_it_be(:fingerprints) { ["aa:bb:cc:dd:ee:zz"] }
@@ -375,7 +404,7 @@ RSpec.describe Emails::Profile do
end
it 'includes a link to the change password documentation' do
- is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/#changing-your-password'
+ is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password'
end
it 'mentions two factor authentication when two factor is not enabled' do
@@ -396,6 +425,39 @@ RSpec.describe Emails::Profile do
end
end
+ describe 'user attempted sign in with wrong 2FA OTP email' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:ip) { '169.0.0.1' }
+ let_it_be(:current_time) { Time.current }
+ let_it_be(:email) { Notify.two_factor_otp_attempt_failed_email(user, ip, current_time) }
+
+ subject { email }
+
+ it_behaves_like 'an email sent from GitLab'
+ it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'a user cannot unsubscribe through footer link'
+
+ it 'is sent to the user' do
+ is_expected.to deliver_to user.email
+ end
+
+ it 'has the correct subject' do
+ is_expected.to have_subject "Attempted sign in to #{Gitlab.config.gitlab.host} using a wrong two-factor authentication code"
+ end
+
+ it 'mentions the IP address' do
+ is_expected.to have_body_text ip
+ end
+
+ it 'mentioned the time' do
+ is_expected.to have_body_text current_time.strftime('%Y-%m-%d %H:%M:%S %Z')
+ end
+
+ it 'includes a link to the change password documentation' do
+ is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password'
+ end
+ end
+
describe 'disabled two-factor authentication email' do
let_it_be(:user) { create(:user) }
diff --git a/spec/migrations/20220809002011_schedule_destroy_invalid_group_members_spec.rb b/spec/migrations/20220809002011_schedule_destroy_invalid_group_members_spec.rb
deleted file mode 100644
index 31dd4344d9f..00000000000
--- a/spec/migrations/20220809002011_schedule_destroy_invalid_group_members_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleDestroyInvalidGroupMembers, :migration do
- let_it_be(:migration) { described_class::MIGRATION }
-
- describe '#up' do
- it 'schedules background jobs for each batch of members' do
- migrate!
-
- expect(migration).to have_scheduled_batched_migration(
- table_name: :members,
- column_name: :id,
- interval: described_class::DELAY_INTERVAL,
- batch_size: described_class::BATCH_SIZE,
- max_batch_size: described_class::MAX_BATCH_SIZE
- )
- end
- end
-
- describe '#down' do
- it 'deletes all batched migration records' do
- migrate!
- schema_migrate_down!
-
- expect(migration).not_to have_scheduled_batched_migration
- end
- end
-end
diff --git a/spec/migrations/20220901035725_schedule_destroy_invalid_project_members_spec.rb b/spec/migrations/20220901035725_schedule_destroy_invalid_project_members_spec.rb
deleted file mode 100644
index ed9f7e3cd44..00000000000
--- a/spec/migrations/20220901035725_schedule_destroy_invalid_project_members_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleDestroyInvalidProjectMembers, :migration do
- let_it_be(:migration) { described_class::MIGRATION }
-
- describe '#up' do
- it 'schedules background jobs for each batch of members' do
- migrate!
-
- expect(migration).to have_scheduled_batched_migration(
- table_name: :members,
- column_name: :id,
- interval: described_class::DELAY_INTERVAL,
- batch_size: described_class::BATCH_SIZE,
- max_batch_size: described_class::MAX_BATCH_SIZE
- )
- end
- end
-
- describe '#down' do
- it 'deletes all batched migration records' do
- migrate!
- schema_migrate_down!
-
- expect(migration).not_to have_scheduled_batched_migration
- end
- end
-end
diff --git a/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb b/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb
new file mode 100644
index 00000000000..f4ac6e6fc8e
--- /dev/null
+++ b/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillInternalOnNotes, :migration do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of issues' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :notes,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20220921093355_schedule_backfill_namespace_details_spec.rb b/spec/migrations/20220921093355_schedule_backfill_namespace_details_spec.rb
new file mode 100644
index 00000000000..61e4af3d10c
--- /dev/null
+++ b/spec/migrations/20220921093355_schedule_backfill_namespace_details_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleBackfillNamespaceDetails, schema: 20220921093355 do
+ context 'when on gitlab.com' do
+ let(:background_migration) { described_class::MIGRATION }
+ let(:migration) { described_class.new }
+
+ before do
+ migration.up
+ end
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of projects' do
+ expect(background_migration).to(
+ have_scheduled_batched_migration(
+ table_name: :namespaces,
+ column_name: :id,
+ interval: described_class::INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migration.down
+
+ expect(described_class::MIGRATION).not_to have_scheduled_batched_migration
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20220921144258_remove_orphan_group_token_users_spec.rb b/spec/migrations/20220921144258_remove_orphan_group_token_users_spec.rb
new file mode 100644
index 00000000000..614044657ec
--- /dev/null
+++ b/spec/migrations/20220921144258_remove_orphan_group_token_users_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe RemoveOrphanGroupTokenUsers, :migration, :sidekiq_inline do
+ subject(:migration) { described_class.new }
+
+ let(:users) { table(:users) }
+ let!(:orphan_bot) do
+ create_bot(username: 'orphan_bot', email: 'orphan_bot@bot.com').tap do |bot|
+ namespaces.create!(type: 'User', path: 'n1', name: 'n1', owner_id: bot.id)
+ end
+ end
+
+ let!(:valid_used_bot) do
+ create_bot(username: 'used_bot', email: 'used_bot@bot.com').tap do |bot|
+ group = namespaces.create!(type: 'Group', path: 'used_bot_group', name: 'used_bot_group')
+ members.create!(user_id: bot.id,
+ source_id: group.id,
+ member_namespace_id: group.id,
+ source_type: 'Group',
+ access_level: 10,
+ notification_level: 0)
+ end
+ end
+
+ let!(:different_bot) do
+ create_bot(username: 'other_bot', email: 'other_bot@bot.com', user_type: 5)
+ end
+
+ let(:personal_access_tokens) { table(:personal_access_tokens) }
+ let(:members) { table(:members) }
+ let(:namespaces) { table(:namespaces) }
+
+ before do
+ stub_feature_flags(user_destroy_with_limited_execution_time_worker: false)
+ end
+
+ it 'removes orphan project bot and its tokens', :aggregate_failures do
+ expect(DeleteUserWorker)
+ .to receive(:perform_async)
+ .with(orphan_bot.id, orphan_bot.id, skip_authorization: true)
+ .and_call_original
+
+ migrate!
+
+ expect(users.count).to eq 2
+ expect(personal_access_tokens.count).to eq 2
+ expect(personal_access_tokens.find_by(user_id: orphan_bot.id)).to eq nil
+ end
+
+ context "when DeleteUserWorker doesn't fit anymore" do
+ it 'removes project bot tokens only', :aggregate_failures do
+ allow(DeleteUserWorker).to receive(:respond_to?).and_call_original
+ allow(DeleteUserWorker).to receive(:respond_to?).with(:perform_async).and_return(false)
+
+ migrate!
+
+ expect(users.count).to eq 3
+ expect(personal_access_tokens.count).to eq 2
+ expect(personal_access_tokens.find_by(user_id: orphan_bot.id)).to eq nil
+ end
+ end
+
+ private
+
+ def create_bot(**params)
+ users.create!({ projects_limit: 0, state: 'active', user_type: 6 }.merge(params)).tap do |bot|
+ personal_access_tokens.create!(user_id: bot.id, name: "BOT##{bot.id}")
+ end
+ end
+end
diff --git a/spec/migrations/20220922143143_schedule_reset_duplicate_ci_runners_token_values_spec.rb b/spec/migrations/20220922143143_schedule_reset_duplicate_ci_runners_token_values_spec.rb
new file mode 100644
index 00000000000..409f7d544ee
--- /dev/null
+++ b/spec/migrations/20220922143143_schedule_reset_duplicate_ci_runners_token_values_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleResetDuplicateCiRunnersTokenValues, migration: :gitlab_ci do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of runners' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ gitlab_schema: :gitlab_ci,
+ table_name: :ci_runners,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ max_batch_size: described_class::MAX_BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values_spec.rb b/spec/migrations/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values_spec.rb
new file mode 100644
index 00000000000..4f3103927d5
--- /dev/null
+++ b/spec/migrations/20220922143634_schedule_reset_duplicate_ci_runners_token_encrypted_values_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleResetDuplicateCiRunnersTokenEncryptedValues, migration: :gitlab_ci do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of runners' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ gitlab_schema: :gitlab_ci,
+ table_name: :ci_runners,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ max_batch_size: described_class::MAX_BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status_spec.rb b/spec/migrations/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status_spec.rb
new file mode 100644
index 00000000000..7e3f8caa966
--- /dev/null
+++ b/spec/migrations/20220928225711_schedule_update_ci_pipeline_artifacts_locked_status_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleUpdateCiPipelineArtifactsLockedStatus, migration: :gitlab_ci do
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of ci_pipeline_artifacts' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ gitlab_schema: :gitlab_ci,
+ table_name: :ci_pipeline_artifacts,
+ column_name: :id,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20220929213730_schedule_delete_orphaned_operational_vulnerabilities_spec.rb b/spec/migrations/20220929213730_schedule_delete_orphaned_operational_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..9220b5e8a95
--- /dev/null
+++ b/spec/migrations/20220929213730_schedule_delete_orphaned_operational_vulnerabilities_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleDeleteOrphanedOperationalVulnerabilities do
+ let_it_be(:migration) { described_class.new }
+ let_it_be(:post_migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of vulnerabilities' do
+ migration.up
+
+ expect(post_migration).to(
+ have_scheduled_batched_migration(
+ table_name: :vulnerabilities,
+ column_name: :id,
+ interval: described_class::INTERVAL,
+ batch_size: described_class::BATCH_SIZE
+ )
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migration.down
+
+ expect(post_migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20221004094814_schedule_destroy_invalid_members_spec.rb b/spec/migrations/20221004094814_schedule_destroy_invalid_members_spec.rb
new file mode 100644
index 00000000000..73fdfa78eb4
--- /dev/null
+++ b/spec/migrations/20221004094814_schedule_destroy_invalid_members_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleDestroyInvalidMembers, :migration do
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of members' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :members,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ max_batch_size: described_class::MAX_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/20221008032350_add_password_expiration_migration_spec.rb b/spec/migrations/20221008032350_add_password_expiration_migration_spec.rb
new file mode 100644
index 00000000000..05e557f1f52
--- /dev/null
+++ b/spec/migrations/20221008032350_add_password_expiration_migration_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddPasswordExpirationMigration do
+ let(:application_setting) { table(:application_settings).create! }
+
+ describe "#up" do
+ it 'allows to read password expiration fields' do
+ migrate!
+
+ expect(application_setting.password_expiration_enabled).to eq false
+ expect(application_setting.password_expires_in_days).to eq 90
+ expect(application_setting.password_expires_notice_before_days).to eq 7
+ end
+ end
+end
diff --git a/spec/migrations/20221012033107_add_password_last_changed_at_to_user_details_spec.rb b/spec/migrations/20221012033107_add_password_last_changed_at_to_user_details_spec.rb
new file mode 100644
index 00000000000..46a7b097d02
--- /dev/null
+++ b/spec/migrations/20221012033107_add_password_last_changed_at_to_user_details_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddPasswordLastChangedAtToUserDetails do
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let_it_be(:users) { table(:users) }
+ let_it_be(:user) { create_user! }
+ let(:user_detail) { table(:user_details).create!(user_id: user.id, provisioned_by_group_id: namespace.id) }
+
+ describe "#up" do
+ it 'allows to read password_last_changed_at' do
+ migrate!
+
+ expect(user_detail.password_last_changed_at).to eq nil
+ end
+ end
+
+ private
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: Time.current
+ )
+ end
+end
diff --git a/spec/migrations/20221013154159_update_invalid_dormant_user_setting_spec.rb b/spec/migrations/20221013154159_update_invalid_dormant_user_setting_spec.rb
new file mode 100644
index 00000000000..eac71e428be
--- /dev/null
+++ b/spec/migrations/20221013154159_update_invalid_dormant_user_setting_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe UpdateInvalidDormantUserSetting, :migration do
+ let(:settings) { table(:application_settings) }
+
+ context 'with no rows in the application_settings table' do
+ it 'does not insert a row' do
+ expect { migrate! }.to not_change { settings.count }
+ end
+ end
+
+ context 'with a row in the application_settings table' do
+ before do
+ settings.create!(deactivate_dormant_users_period: days)
+ end
+
+ context 'with deactivate_dormant_users_period set to a value greater than or equal to 90' do
+ let(:days) { 90 }
+
+ it 'does not update the row' do
+ expect { migrate! }
+ .to not_change { settings.count }
+ .and not_change { settings.first.deactivate_dormant_users_period }
+ end
+ end
+
+ context 'with deactivate_dormant_users_period set to a value less than or equal to 90' do
+ let(:days) { 1 }
+
+ it 'updates the existing row' do
+ expect { migrate! }
+ .to not_change { settings.count }
+ .and change { settings.first.deactivate_dormant_users_period }
+ end
+ end
+ end
+end
diff --git a/spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb b/spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb
index fb62fc3ca02..0ae4559ca9f 100644
--- a/spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb
+++ b/spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb
@@ -72,12 +72,14 @@ RSpec.describe AddPremiumAndUltimatePlanLimits, :migration do
it 'creates plan limits from the source plan' do
migrate!
- expect(AddPremiumAndUltimatePlanLimits::PlanLimits.pluck(:plan_id, :storage_size_limit)).to match_array([
- [silver.id, silver_limits.storage_size_limit],
- [gold.id, gold_limits.storage_size_limit],
- [premium.id, silver_limits.storage_size_limit],
- [ultimate.id, gold_limits.storage_size_limit]
- ])
+ expect(AddPremiumAndUltimatePlanLimits::PlanLimits.pluck(:plan_id, :storage_size_limit))
+ .to match_array(
+ [
+ [silver.id, silver_limits.storage_size_limit],
+ [gold.id, gold_limits.storage_size_limit],
+ [premium.id, silver_limits.storage_size_limit],
+ [ultimate.id, gold_limits.storage_size_limit]
+ ])
end
end
end
diff --git a/spec/migrations/adjust_task_note_rename_background_migration_values_spec.rb b/spec/migrations/adjust_task_note_rename_background_migration_values_spec.rb
new file mode 100644
index 00000000000..422d0655e36
--- /dev/null
+++ b/spec/migrations/adjust_task_note_rename_background_migration_values_spec.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe AdjustTaskNoteRenameBackgroundMigrationValues, :migration do
+ let(:finished_status) { 3 }
+ let(:failed_status) { described_class::MIGRATION_FAILED_STATUS }
+ let(:active_status) { described_class::MIGRATION_ACTIVE_STATUS }
+
+ shared_examples 'task note migration with failing batches' do
+ it 'updates batch sizes and resets failed batches' do
+ migration = create_background_migration(status: initial_status)
+ batches = []
+
+ batches << create_failed_batched_job(migration)
+ batches << create_failed_batched_job(migration)
+
+ migrate!
+
+ expect(described_class::JOB_CLASS_NAME).to have_scheduled_batched_migration(
+ table_name: :system_note_metadata,
+ column_name: :id,
+ interval: 2.minutes,
+ batch_size: described_class::NEW_BATCH_SIZE,
+ max_batch_size: 20_000,
+ sub_batch_size: described_class::NEW_SUB_BATCH_SIZE
+ )
+ expect(migration.reload.status).to eq(active_status)
+
+ updated_batches = batches.map { |b| b.reload.attributes.slice('attempts', 'sub_batch_size') }
+ expect(updated_batches).to all(eq("attempts" => 0, "sub_batch_size" => 10))
+ end
+ end
+
+ describe '#up' do
+ context 'when migration was already finished' do
+ it 'does not update batch sizes' do
+ create_background_migration(status: finished_status)
+
+ migrate!
+
+ expect(described_class::JOB_CLASS_NAME).to have_scheduled_batched_migration(
+ table_name: :system_note_metadata,
+ column_name: :id,
+ interval: 2.minutes,
+ batch_size: described_class::OLD_BATCH_SIZE,
+ max_batch_size: 20_000,
+ sub_batch_size: described_class::OLD_SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ context 'when the migration had failing batches' do
+ context 'when migration had a failed status' do
+ it_behaves_like 'task note migration with failing batches' do
+ let(:initial_status) { failed_status }
+ end
+
+ it 'updates started_at timestamp' do
+ migration = create_background_migration(status: failed_status)
+ now = Time.zone.now
+
+ travel_to now do
+ migrate!
+ migration.reload
+ end
+
+ expect(migration.started_at).to be_like_time(now)
+ end
+ end
+
+ context 'when migration had an active status' do
+ it_behaves_like 'task note migration with failing batches' do
+ let(:initial_status) { active_status }
+ end
+
+ it 'does not update started_at timestamp' do
+ migration = create_background_migration(status: active_status)
+ original_time = migration.started_at
+
+ migrate!
+ migration.reload
+
+ expect(migration.started_at).to be_like_time(original_time)
+ end
+ end
+ end
+ end
+
+ describe '#down' do
+ it 'reverts to old batch sizes' do
+ create_background_migration(status: finished_status)
+
+ migrate!
+ schema_migrate_down!
+
+ expect(described_class::JOB_CLASS_NAME).to have_scheduled_batched_migration(
+ table_name: :system_note_metadata,
+ column_name: :id,
+ interval: 2.minutes,
+ batch_size: described_class::OLD_BATCH_SIZE,
+ max_batch_size: 20_000,
+ sub_batch_size: described_class::OLD_SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ def create_failed_batched_job(migration)
+ table(:batched_background_migration_jobs).create!(
+ batched_background_migration_id: migration.id,
+ status: described_class::JOB_FAILED_STATUS,
+ min_value: 1,
+ max_value: 10,
+ attempts: 3,
+ batch_size: described_class::OLD_BATCH_SIZE,
+ sub_batch_size: described_class::OLD_SUB_BATCH_SIZE
+ )
+ end
+
+ def create_background_migration(status:)
+ migrations_table = table(:batched_background_migrations)
+ # make sure we only have on migration with that job class name in the specs
+ migrations_table.where(job_class_name: described_class::JOB_CLASS_NAME).delete_all
+
+ migrations_table.create!(
+ job_class_name: described_class::JOB_CLASS_NAME,
+ status: status,
+ max_value: 10,
+ max_batch_size: 20_000,
+ batch_size: described_class::OLD_BATCH_SIZE,
+ sub_batch_size: described_class::OLD_SUB_BATCH_SIZE,
+ interval: 2.minutes,
+ table_name: :system_note_metadata,
+ column_name: :id,
+ total_tuple_count: 100_000,
+ pause_ms: 100,
+ gitlab_schema: :gitlab_main,
+ job_arguments: [],
+ started_at: 2.days.ago
+ )
+ end
+end
diff --git a/spec/migrations/backfill_epic_cache_counts_spec.rb b/spec/migrations/backfill_epic_cache_counts_spec.rb
new file mode 100644
index 00000000000..6084fdad0a6
--- /dev/null
+++ b/spec/migrations/backfill_epic_cache_counts_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillEpicCacheCounts, :migration do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules a batched background migration' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :epics,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ max_batch_size: described_class::MAX_BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb b/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb
index da32e92ebb0..87855285203 100644
--- a/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb
+++ b/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb
@@ -57,36 +57,39 @@ RSpec.describe BackfillEscalationPoliciesForOncallSchedules do
expect(new_polices).to all have_attributes(name: 'On-call Escalation Policy')
expect(new_policy_b1.description).to eq('Immediately notify Schedule B1')
expect(new_policy_c1.description).to eq('Immediately notify Schedule C1')
- expect(policies.pluck(:project_id)).to eq([
- project_d.id,
- project_e.id,
- project_f.id,
- project_f.id,
- project_b.id,
- project_c.id
- ])
+ expect(policies.pluck(:project_id)).to eq(
+ [
+ project_d.id,
+ project_e.id,
+ project_f.id,
+ project_f.id,
+ project_b.id,
+ project_c.id
+ ])
expect(new_rules).to all have_attributes(status: 1, elapsed_time_seconds: 0)
- expect(rules.pluck(:policy_id)).to eq([
- rule_d1.policy_id,
- rule_e1.policy_id,
- rule_f1.policy_id,
- rule_f2.policy_id,
- rule_f3.policy_id,
- new_policy_b1.id,
- new_policy_c1.id,
- new_policy_c1.id
- ])
- expect(rules.pluck(:oncall_schedule_id)).to eq([
- rule_d1.oncall_schedule_id,
- rule_e1.oncall_schedule_id,
- rule_f1.oncall_schedule_id,
- rule_f2.oncall_schedule_id,
- rule_f3.oncall_schedule_id,
- schedule_b1.id,
- schedule_c1.id,
- schedule_c2.id
- ])
+ expect(rules.pluck(:policy_id)).to eq(
+ [
+ rule_d1.policy_id,
+ rule_e1.policy_id,
+ rule_f1.policy_id,
+ rule_f2.policy_id,
+ rule_f3.policy_id,
+ new_policy_b1.id,
+ new_policy_c1.id,
+ new_policy_c1.id
+ ])
+ expect(rules.pluck(:oncall_schedule_id)).to eq(
+ [
+ rule_d1.oncall_schedule_id,
+ rule_e1.oncall_schedule_id,
+ rule_f1.oncall_schedule_id,
+ rule_f2.oncall_schedule_id,
+ rule_f3.oncall_schedule_id,
+ schedule_b1.id,
+ schedule_c1.id,
+ schedule_c2.id
+ ])
end
end
diff --git a/spec/migrations/populate_releases_access_level_from_repository_spec.rb b/spec/migrations/populate_releases_access_level_from_repository_spec.rb
new file mode 100644
index 00000000000..2bb97662923
--- /dev/null
+++ b/spec/migrations/populate_releases_access_level_from_repository_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe PopulateReleasesAccessLevelFromRepository, :migration do
+ let(:projects) { table(:projects) }
+ let(:groups) { table(:namespaces) }
+ let(:project_features) { table(:project_features) }
+
+ let(:group) { groups.create!(name: 'test-group', path: 'test-group') }
+ let(:project) { projects.create!(namespace_id: group.id, project_namespace_id: group.id) }
+ let(:project_feature) do
+ project_features.create!(project_id: project.id, pages_access_level: 20, **project_feature_attributes)
+ end
+
+ # repository_access_level and releases_access_level default to ENABLED
+ describe '#up' do
+ context 'when releases_access_level is greater than repository_access_level' do
+ let(:project_feature_attributes) { { repository_access_level: ProjectFeature::PRIVATE } }
+
+ it 'reduces releases_access_level to match repository_access_level' do
+ expect { migrate! }.to change { project_feature.reload.releases_access_level }
+ .from(ProjectFeature::ENABLED)
+ .to(ProjectFeature::PRIVATE)
+ end
+ end
+
+ context 'when releases_access_level is less than repository_access_level' do
+ let(:project_feature_attributes) { { releases_access_level: ProjectFeature::DISABLED } }
+
+ it 'does not change releases_access_level' do
+ expect { migrate! }.not_to change { project_feature.reload.releases_access_level }
+ .from(ProjectFeature::DISABLED)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb b/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
index e03dd73ec8b..b03a5c41a11 100644
--- a/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
+++ b/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
@@ -49,12 +49,13 @@ RSpec.describe SliceMergeRequestDiffCommitMigrations, :migration do
.pending
.to_a
- expect(new_jobs.map(&:arguments)).to eq([
- [1, 5_001],
- [5_001, 10_001],
- [10_001, 15_001],
- [15_001, 20_001]
- ])
+ expect(new_jobs.map(&:arguments)).to eq(
+ [
+ [1, 5_001],
+ [5_001, 10_001],
+ [10_001, 15_001],
+ [15_001, 20_001]
+ ])
end
it 'schedules a background migration for the first job' do
diff --git a/spec/models/analytics/cycle_analytics/project_stage_spec.rb b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
index a67f9fec443..697b7aee022 100644
--- a/spec/models/analytics/cycle_analytics/project_stage_spec.rb
+++ b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
@@ -48,10 +48,11 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do
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]
- ])
+ 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 b5f153e7add..77bb6b502b5 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -203,6 +203,17 @@ RSpec.describe ApplicationSetting do
it { is_expected.to allow_value([]).for(:valid_runner_registrars) }
it { is_expected.to allow_value(%w(project group)).for(:valid_runner_registrars) }
+ context 'when deactivate_dormant_users is enabled' do
+ before do
+ stub_application_setting(deactivate_dormant_users: true)
+ end
+
+ it { is_expected.not_to allow_value(nil).for(:deactivate_dormant_users_period) }
+ it { is_expected.to allow_value(90).for(:deactivate_dormant_users_period) }
+ it { is_expected.to allow_value(365).for(:deactivate_dormant_users_period) }
+ it { is_expected.not_to allow_value(89).for(:deactivate_dormant_users_period) }
+ end
+
context 'help_page_documentation_base_url validations' do
it { is_expected.to allow_value(nil).for(:help_page_documentation_base_url) }
it { is_expected.to allow_value('https://docs.gitlab.com').for(:help_page_documentation_base_url) }
@@ -257,11 +268,12 @@ RSpec.describe ApplicationSetting do
subject.grafana_url = ' ' + http
expect(subject.save).to be false
- expect(subject.errors[:grafana_url]).to eq([
- 'must be a valid relative or absolute URL. ' \
- 'Please check your Grafana URL setting in ' \
- 'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
- ])
+ expect(subject.errors[:grafana_url]).to eq(
+ [
+ 'must be a valid relative or absolute URL. ' \
+ 'Please check your Grafana URL setting in ' \
+ 'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
+ ])
end
end
@@ -270,11 +282,12 @@ RSpec.describe ApplicationSetting do
subject.grafana_url = javascript
expect(subject.save).to be false
- expect(subject.errors[:grafana_url]).to eq([
- 'is blocked: Only allowed schemes are http, https. Please check your ' \
- 'Grafana URL setting in ' \
- 'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
- ])
+ expect(subject.errors[:grafana_url]).to eq(
+ [
+ 'is blocked: Only allowed schemes are http, https. Please check your ' \
+ 'Grafana URL setting in ' \
+ 'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
+ ])
end
end
end
@@ -1453,4 +1466,10 @@ RSpec.describe ApplicationSetting do
expect(setting.personal_access_token_prefix).to eql('glpat-')
end
end
+
+ describe '.personal_access_tokens_disabled?' do
+ it 'is false' do
+ expect(setting.personal_access_tokens_disabled?).to eq(false)
+ end
+ end
end
diff --git a/spec/models/award_emoji_spec.rb b/spec/models/award_emoji_spec.rb
index 4da19267b1c..2593c9b3595 100644
--- a/spec/models/award_emoji_spec.rb
+++ b/spec/models/award_emoji_spec.rb
@@ -290,4 +290,13 @@ RSpec.describe AwardEmoji do
end
end
end
+
+ describe '#to_ability_name' do
+ let(:merge_request) { create(:merge_request) }
+ let(:award_emoji) { build(:award_emoji, user: build(:user), awardable: merge_request) }
+
+ it 'returns correct ability name' do
+ expect(award_emoji.to_ability_name).to be('emoji')
+ end
+ end
end
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index 874009d552a..f4f2b174a7b 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -46,6 +46,8 @@ RSpec.describe BulkImports::Entity, type: :model do
end
it 'is invalid as a project_entity' do
+ stub_feature_flags(bulk_import_projects: true)
+
entity = build(:bulk_import_entity, :project_entity, group: build(:group), project: nil)
expect(entity).not_to be_valid
@@ -55,6 +57,8 @@ RSpec.describe BulkImports::Entity, type: :model do
context 'when associated with a project and no group' do
it 'is valid' do
+ stub_feature_flags(bulk_import_projects: true)
+
entity = build(:bulk_import_entity, :project_entity, group: nil, project: build(:project))
expect(entity).to be_valid
@@ -84,6 +88,8 @@ RSpec.describe BulkImports::Entity, type: :model do
context 'when the parent is a project import' do
it 'is invalid' do
+ stub_feature_flags(bulk_import_projects: true)
+
entity = build(:bulk_import_entity, parent: build(:bulk_import_entity, :project_entity))
expect(entity).not_to be_valid
@@ -124,6 +130,39 @@ RSpec.describe BulkImports::Entity, type: :model do
.to include('Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again.')
end
end
+
+ context 'when bulk_import_projects feature flag is disabled and source_type is a project_entity' do
+ it 'is invalid' do
+ stub_feature_flags(bulk_import_projects: false)
+
+ entity = build(:bulk_import_entity, :project_entity)
+
+ expect(entity).not_to be_valid
+ expect(entity.errors[:base]).to include('invalid entity source type')
+ end
+ end
+
+ context 'when bulk_import_projects feature flag is enabled and source_type is a project_entity' do
+ it 'is valid' do
+ stub_feature_flags(bulk_import_projects: true)
+
+ entity = build(:bulk_import_entity, :project_entity)
+
+ expect(entity).to be_valid
+ end
+ end
+
+ context 'when bulk_import_projects feature flag is enabled on root ancestor level and source_type is a project_entity' do
+ it 'is valid' do
+ top_level_namespace = create(:group)
+
+ stub_feature_flags(bulk_import_projects: top_level_namespace)
+
+ entity = build(:bulk_import_entity, :project_entity, destination_namespace: top_level_namespace.full_path)
+
+ expect(entity).to be_valid
+ end
+ end
end
describe '#encoded_source_full_path' do
@@ -209,7 +248,7 @@ RSpec.describe BulkImports::Entity, type: :model do
it 'returns group export relations url' do
entity = build(:bulk_import_entity, :group_entity)
- expect(entity.export_relations_url_path).to eq("/groups/#{entity.encoded_source_full_path}/export_relations")
+ expect(entity.export_relations_url_path).to eq("/groups/#{entity.source_xid}/export_relations")
end
end
@@ -217,7 +256,7 @@ RSpec.describe BulkImports::Entity, type: :model do
it 'returns project export relations url' do
entity = build(:bulk_import_entity, :project_entity)
- expect(entity.export_relations_url_path).to eq("/projects/#{entity.encoded_source_full_path}/export_relations")
+ expect(entity.export_relations_url_path).to eq("/projects/#{entity.source_xid}/export_relations")
end
end
end
@@ -227,7 +266,7 @@ RSpec.describe BulkImports::Entity, type: :model do
entity = build(:bulk_import_entity)
expect(entity.relation_download_url_path('test'))
- .to eq("/groups/#{entity.encoded_source_full_path}/export_relations/download?relation=test")
+ .to eq("/groups/#{entity.source_xid}/export_relations/download?relation=test")
end
end
@@ -263,15 +302,15 @@ RSpec.describe BulkImports::Entity, type: :model do
describe '#base_resource_url_path' do
it 'returns base entity url path' do
- entity = build(:bulk_import_entity)
+ entity = build(:bulk_import_entity, source_xid: nil)
- expect(entity.base_resource_url_path).to eq("/groups/#{entity.encoded_source_full_path}")
+ expect(entity.base_resource_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)
+ entity = build(:bulk_import_entity, source_xid: nil)
expect(entity.wikis_url_path).to eq("/groups/#{entity.encoded_source_full_path}/wikis")
end
diff --git a/spec/models/bulk_imports/export_status_spec.rb b/spec/models/bulk_imports/export_status_spec.rb
index 6ade82409dc..0921c3bdce2 100644
--- a/spec/models/bulk_imports/export_status_spec.rb
+++ b/spec/models/bulk_imports/export_status_spec.rb
@@ -157,12 +157,36 @@ RSpec.describe BulkImports::ExportStatus do
end
context 'when something goes wrong during export status fetch' do
- it 'returns exception class as error' do
+ let(:exception) { BulkImports::NetworkError.new('Error!') }
+
+ before do
allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
- allow(client).to receive(:get).and_raise(StandardError, 'Error!')
+ allow(client).to receive(:get).once.and_raise(exception)
end
+ end
+
+ it 'raises RetryPipelineError' do
+ allow(exception).to receive(:retriable?).with(tracker).and_return(true)
+
+ expect { subject.failed? }.to raise_error(BulkImports::RetryPipelineError)
+ end
- expect(subject.error).to eq('Error!')
+ context 'when error is not retriable' do
+ it 'returns exception class as error' do
+ expect(subject.error).to eq('Error!')
+ expect(subject.failed?).to eq(true)
+ end
+ end
+
+ context 'when error raised is not a network error' do
+ it 'returns exception class as error' do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:get).once.and_raise(StandardError, 'Standard Error!')
+ end
+
+ expect(subject.error).to eq('Standard Error!')
+ expect(subject.failed?).to eq(true)
+ end
end
end
end
diff --git a/spec/models/bulk_imports/failure_spec.rb b/spec/models/bulk_imports/failure_spec.rb
index cde62659a48..b3fd60ba348 100644
--- a/spec/models/bulk_imports/failure_spec.rb
+++ b/spec/models/bulk_imports/failure_spec.rb
@@ -3,15 +3,45 @@
require 'spec_helper'
RSpec.describe BulkImports::Failure, type: :model do
+ let(:failure) { create(:bulk_import_failure) }
+
describe 'associations' do
it { is_expected.to belong_to(:entity).required }
end
describe 'validations' do
- before do
- create(:bulk_import_failure)
+ it { is_expected.to validate_presence_of(:entity) }
+ end
+
+ describe '#relation' do
+ context 'when pipeline class is valid' do
+ it 'returns pipeline defined relation' do
+ failure.update!(pipeline_class: 'BulkImports::Common::Pipelines::WikiPipeline')
+
+ expect(failure.relation).to eq('wiki')
+ end
end
- it { is_expected.to validate_presence_of(:entity) }
+ context 'when pipeline class is invalid' do
+ it 'returns default relation' do
+ failure.update!(pipeline_class: 'foobar')
+
+ expect(failure.relation).to eq('foobar')
+ end
+
+ context 'when pipeline class is outside of BulkImports namespace' do
+ it 'returns default relation' do
+ failure.update!(pipeline_class: 'Gitlab::ImportExport::Importer')
+
+ expect(failure.relation).to eq('importer')
+ end
+ end
+
+ it 'returns demodulized, underscored, chomped string' do
+ failure.update!(pipeline_class: 'BulkImports::Pipelines::Test::TestRelationPipeline')
+
+ expect(failure.relation).to eq('test_relation')
+ end
+ end
end
end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 40c2d62c465..44a6bec0130 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -86,9 +86,9 @@ RSpec.describe Ci::Bridge do
describe '#scoped_variables' do
it 'returns a hash representing variables' do
variables = %w[
- CI_JOB_NAME CI_JOB_STAGE CI_COMMIT_SHA CI_COMMIT_SHORT_SHA
- CI_COMMIT_BEFORE_SHA CI_COMMIT_REF_NAME CI_COMMIT_REF_SLUG
- CI_PROJECT_ID CI_PROJECT_NAME CI_PROJECT_PATH
+ CI_JOB_NAME CI_JOB_NAME_SLUG CI_JOB_STAGE CI_COMMIT_SHA
+ CI_COMMIT_SHORT_SHA CI_COMMIT_BEFORE_SHA CI_COMMIT_REF_NAME
+ CI_COMMIT_REF_SLUG CI_PROJECT_ID CI_PROJECT_NAME CI_PROJECT_PATH
CI_PROJECT_PATH_SLUG CI_PROJECT_NAMESPACE CI_PROJECT_ROOT_NAMESPACE
CI_PIPELINE_IID CI_CONFIG_PATH CI_PIPELINE_SOURCE CI_COMMIT_MESSAGE
CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION CI_COMMIT_REF_PROTECTED
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index e904463a5ca..16cff72db64 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -14,8 +14,8 @@ RSpec.describe Ci::BuildMetadata do
status: 'success')
end
- let(:build) { create(:ci_build, pipeline: pipeline) }
- let(:metadata) { build.metadata }
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+ let(:metadata) { job.metadata }
it_behaves_like 'having unique enum values'
@@ -35,7 +35,7 @@ RSpec.describe Ci::BuildMetadata do
context 'when project timeout is set' do
context 'when runner is assigned to the job' do
before do
- build.update!(runner: runner)
+ job.update!(runner: runner)
end
context 'when runner timeout is not set' do
@@ -59,13 +59,13 @@ RSpec.describe Ci::BuildMetadata do
context 'when job timeout is set' do
context 'when job timeout is higher than project timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
+ let(:job) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
it_behaves_like 'sets timeout', 'job_timeout_source', 3000
end
context 'when job timeout is lower than project timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1000 }) }
+ let(:job) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1000 }) }
it_behaves_like 'sets timeout', 'job_timeout_source', 1000
end
@@ -73,18 +73,18 @@ RSpec.describe Ci::BuildMetadata do
context 'when both runner and job timeouts are set' do
before do
- build.update!(runner: runner)
+ job.update!(runner: runner)
end
context 'when job timeout is higher than runner timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
+ let(:job) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
it_behaves_like 'sets timeout', 'runner_timeout_source', 2100
end
context 'when job timeout is lower than runner timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1900 }) }
+ let(:job) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1900 }) }
let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
it_behaves_like 'sets timeout', 'job_timeout_source', 1900
@@ -135,20 +135,51 @@ RSpec.describe Ci::BuildMetadata do
describe 'set_cancel_gracefully' do
it 'sets cancel_gracefully' do
- build.set_cancel_gracefully
+ job.set_cancel_gracefully
- expect(build.cancel_gracefully?).to be true
+ expect(job.cancel_gracefully?).to be true
end
it 'returns false' do
- expect(build.cancel_gracefully?).to be false
+ expect(job.cancel_gracefully?).to be false
end
end
context 'loose foreign key on ci_builds_metadata.project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
- let!(:parent) { create(:project) }
- let!(:model) { create(:ci_build_metadata, project: parent) }
+ let!(:parent) { project }
+ let!(:model) { metadata }
+ end
+ end
+
+ describe 'partitioning' do
+ context 'with job' do
+ let(:status) { build(:commit_status, partition_id: 123) }
+ let(:metadata) { build(:ci_build_metadata, build: status) }
+
+ it 'copies the partition_id from job' do
+ expect { metadata.valid? }.to change(metadata, :partition_id).to(123)
+ end
+
+ context 'when it is already set' do
+ let(:metadata) { build(:ci_build_metadata, build: status, partition_id: 125) }
+
+ it 'does not change the partition_id value' do
+ expect { metadata.valid? }.not_to change(metadata, :partition_id)
+ end
+ end
+ end
+
+ context 'without job' do
+ subject(:metadata) do
+ build(:ci_build_metadata, build: nil)
+ end
+
+ it { is_expected.to validate_presence_of(:partition_id) }
+
+ it 'does not change the partition_id value' do
+ expect { metadata.valid? }.not_to change(metadata, :partition_id)
+ end
end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 7ee381b29ea..9713734e97a 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -160,6 +160,42 @@ RSpec.describe Ci::Build do
end
end
+ describe '.with_erasable_artifacts' do
+ subject { described_class.with_erasable_artifacts }
+
+ context 'when job does not have any artifacts' do
+ let!(:job) { create(:ci_build) }
+
+ it 'does not return the job' do
+ is_expected.not_to include(job)
+ end
+ end
+
+ ::Ci::JobArtifact.erasable_file_types.each do |type|
+ context "when job has a #{type} artifact" do
+ it 'returns the job' do
+ job = create(:ci_build)
+ create(
+ :ci_job_artifact,
+ file_format: ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS[type.to_sym],
+ file_type: type,
+ job: job
+ )
+
+ is_expected.to include(job)
+ end
+ end
+ end
+
+ context 'when job has a non-erasable artifact' do
+ let!(:job) { create(:ci_build, :trace_artifact) }
+
+ it 'does not return the job' do
+ is_expected.not_to include(job)
+ end
+ end
+ end
+
describe '.with_live_trace' do
subject { described_class.with_live_trace }
@@ -284,10 +320,10 @@ RSpec.describe Ci::Build do
let(:artifact_scope) { Ci::JobArtifact.where(file_type: 'archive') }
- let!(:build_1) { create(:ci_build, :artifacts) }
- let!(:build_2) { create(:ci_build, :codequality_reports) }
- let!(:build_3) { create(:ci_build, :test_reports) }
- let!(:build_4) { create(:ci_build, :artifacts) }
+ let!(:build_1) { create(:ci_build, :artifacts, pipeline: pipeline) }
+ let!(:build_2) { create(:ci_build, :codequality_reports, pipeline: pipeline) }
+ let!(:build_3) { create(:ci_build, :test_reports, pipeline: pipeline) }
+ let!(:build_4) { create(:ci_build, :artifacts, pipeline: pipeline) }
it 'returns artifacts matching the given scope' do
expect(builds).to contain_exactly(build_1, build_4)
@@ -596,15 +632,6 @@ RSpec.describe Ci::Build do
it { expect(subject).to be_falsey }
end
- context 'when prevent_outdated_deployment_jobs FF is disabled' do
- before do
- stub_feature_flags(prevent_outdated_deployment_jobs: false)
- expect(build.deployment).not_to receive(:rollback?)
- end
-
- it { expect(subject).to be_falsey }
- end
-
context 'when build can prevent rollback deployment' do
before do
expect(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(true)
@@ -2668,6 +2695,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_JOB_JWT_V1', value: 'ci.job.jwt', public: false, masked: true },
{ key: 'CI_JOB_JWT_V2', value: 'ci.job.jwtv2', public: false, masked: true },
{ key: 'CI_JOB_NAME', value: 'test', public: true, masked: false },
+ { key: 'CI_JOB_NAME_SLUG', value: 'test', public: true, masked: false },
{ key: 'CI_JOB_STAGE', value: 'test', public: true, masked: false },
{ key: 'CI_NODE_TOTAL', value: '1', public: true, masked: false },
{ key: 'CI_BUILD_NAME', value: 'test', public: true, masked: false },
@@ -2780,6 +2808,14 @@ RSpec.describe Ci::Build do
end
end
+ context 'when the opt_in_jwt project setting is true' do
+ it 'does not include the JWT variables' do
+ project.ci_cd_settings.update!(opt_in_jwt: true)
+
+ expect(subject.pluck(:key)).not_to include('CI_JOB_JWT', 'CI_JOB_JWT_V1', 'CI_JOB_JWT_V2')
+ end
+ end
+
describe 'variables ordering' do
context 'when variables hierarchy is stubbed' do
let(:build_pre_var) { { key: 'build', value: 'value', public: true, masked: false } }
@@ -3069,8 +3105,24 @@ RSpec.describe Ci::Build do
end
context 'when build is for tag' do
+ let(:tag_name) { project.repository.tags.first.name }
+ let(:tag_message) { project.repository.tags.first.message }
+
+ let!(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: tag_name,
+ status: 'success')
+ end
+
+ let!(:build) { create(:ci_build, pipeline: pipeline, ref: tag_name) }
+
let(:tag_variable) do
- { key: 'CI_COMMIT_TAG', value: 'master', public: true, masked: false }
+ { key: 'CI_COMMIT_TAG', value: tag_name, public: true, masked: false }
+ end
+
+ let(:tag_message_variable) do
+ { key: 'CI_COMMIT_TAG_MESSAGE', value: tag_message, public: true, masked: false }
end
before do
@@ -3081,7 +3133,7 @@ RSpec.describe Ci::Build do
it do
build.reload
- expect(subject).to include(tag_variable)
+ expect(subject).to include(tag_variable, tag_message_variable)
end
end
@@ -3474,6 +3526,49 @@ RSpec.describe Ci::Build do
it { is_expected.to include(key: job_variable.key, value: job_variable.value, public: false, masked: false) }
end
+
+ context 'when ID tokens are defined on the build' do
+ before do
+ rsa_key = OpenSSL::PKey::RSA.generate(3072).to_s
+ stub_application_setting(ci_jwt_signing_key: rsa_key)
+ build.metadata.update!(id_tokens: {
+ 'ID_TOKEN_1' => { id_token: { aud: 'developers' } },
+ 'ID_TOKEN_2' => { id_token: { aud: 'maintainers' } }
+ })
+ end
+
+ subject(:runner_vars) { build.variables.to_runner_variables }
+
+ it 'includes the ID token variables' do
+ expect(runner_vars).to include(
+ a_hash_including(key: 'ID_TOKEN_1', public: false, masked: true),
+ a_hash_including(key: 'ID_TOKEN_2', public: false, masked: true)
+ )
+
+ id_token_var_1 = runner_vars.find { |var| var[:key] == 'ID_TOKEN_1' }
+ id_token_var_2 = runner_vars.find { |var| var[:key] == 'ID_TOKEN_2' }
+ id_token_1 = JWT.decode(id_token_var_1[:value], nil, false).first
+ id_token_2 = JWT.decode(id_token_var_2[:value], nil, false).first
+ expect(id_token_1['aud']).to eq('developers')
+ expect(id_token_2['aud']).to eq('maintainers')
+ end
+
+ context 'when a NoSigningKeyError is raised' do
+ it 'does not include the ID token variables' do
+ allow(::Gitlab::Ci::JwtV2).to receive(:for_build).and_raise(::Gitlab::Ci::Jwt::NoSigningKeyError)
+
+ expect(runner_vars.map { |var| var[:key] }).not_to include('ID_TOKEN_1', 'ID_TOKEN_2')
+ end
+ end
+
+ context 'when a RSAError is raised' do
+ it 'does not include the ID token variables' do
+ allow(::Gitlab::Ci::JwtV2).to receive(:for_build).and_raise(::OpenSSL::PKey::RSAError)
+
+ expect(runner_vars.map { |var| var[:key] }).not_to include('ID_TOKEN_1', 'ID_TOKEN_2')
+ end
+ end
+ end
end
describe '#scoped_variables' do
@@ -5171,10 +5266,11 @@ RSpec.describe Ci::Build do
it { expect(matchers.size).to eq(2) }
it 'groups build ids' do
- expect(matchers.map(&:build_ids)).to match_array([
- [build_without_tags.id],
- match_array([build_with_tags.id, other_build_with_tags.id])
- ])
+ expect(matchers.map(&:build_ids)).to match_array(
+ [
+ [build_without_tags.id],
+ match_array([build_with_tags.id, other_build_with_tags.id])
+ ])
end
it { expect(matchers.map(&:tag_list)).to match_array([[], %w[tag1 tag2]]) }
@@ -5362,7 +5458,7 @@ RSpec.describe Ci::Build do
end
describe '#clone' do
- let_it_be(:user) { FactoryBot.build(:user) }
+ let_it_be(:user) { create(:user) }
context 'when given new job variables' do
context 'when the cloned build has an action' do
@@ -5371,10 +5467,11 @@ RSpec.describe Ci::Build do
create(:ci_job_variable, job: build, key: 'TEST_KEY', value: 'old value')
create(:ci_job_variable, job: build, key: 'OLD_KEY', value: 'i will not live for long')
- new_build = build.clone(current_user: user, new_job_variables_attributes: [
- { key: 'TEST_KEY', value: 'new value' },
- { key: 'NEW_KEY', value: 'exciting new value' }
- ])
+ new_build = build.clone(current_user: user, new_job_variables_attributes:
+ [
+ { key: 'TEST_KEY', value: 'new value' },
+ { key: 'NEW_KEY', value: 'exciting new value' }
+ ])
new_build.save!
expect(new_build.job_variables.count).to be(2)
@@ -5388,9 +5485,10 @@ RSpec.describe Ci::Build do
build = create(:ci_build)
create(:ci_job_variable, job: build, key: 'TEST_KEY', value: 'old value')
- new_build = build.clone(current_user: user, new_job_variables_attributes: [
- { key: 'TEST_KEY', value: 'new value' }
- ])
+ new_build = build.clone(
+ current_user: user,
+ new_job_variables_attributes: [{ key: 'TEST_KEY', value: 'new value' }]
+ )
new_build.save!
expect(new_build.job_variables.count).to be(1)
diff --git a/spec/models/ci/build_trace_chunks/redis_spec.rb b/spec/models/ci/build_trace_chunks/redis_spec.rb
index c004887d609..0d8cda7b3d8 100644
--- a/spec/models/ci/build_trace_chunks/redis_spec.rb
+++ b/spec/models/ci/build_trace_chunks/redis_spec.rb
@@ -211,15 +211,15 @@ RSpec.describe Ci::BuildTraceChunks::Redis, :clean_gitlab_redis_shared_state do
it 'deletes multiple data' do
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.exists("gitlab:ci:trace:#{build.id}:chunks:0")).to be_truthy
- expect(redis.exists("gitlab:ci:trace:#{build.id}:chunks:1")).to be_truthy
+ expect(redis.exists?("gitlab:ci:trace:#{build.id}:chunks:0")).to eq(true)
+ expect(redis.exists?("gitlab:ci:trace:#{build.id}:chunks:1")).to eq(true)
end
subject
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.exists("gitlab:ci:trace:#{build.id}:chunks:0")).to be_falsy
- expect(redis.exists("gitlab:ci:trace:#{build.id}:chunks:1")).to be_falsy
+ expect(redis.exists?("gitlab:ci:trace:#{build.id}:chunks:0")).to eq(false)
+ expect(redis.exists?("gitlab:ci:trace:#{build.id}:chunks:1")).to eq(false)
end
end
end
diff --git a/spec/models/ci/build_trace_spec.rb b/spec/models/ci/build_trace_spec.rb
index bd24e8be1ac..f2df4874b84 100644
--- a/spec/models/ci/build_trace_spec.rb
+++ b/spec/models/ci/build_trace_spec.rb
@@ -28,9 +28,10 @@ RSpec.describe Ci::BuildTrace do
it_behaves_like 'delegates methods'
it 'returns formatted trace' do
- expect(subject.lines).to eq([
- { offset: 0, content: [{ text: 'the-stream' }] }
- ])
+ expect(subject.lines).to eq(
+ [
+ { offset: 0, content: [{ text: 'the-stream' }] }
+ ])
end
context 'with invalid UTF-8 data' do
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index d0141a1469e..cd55817243f 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -41,24 +41,25 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
let!(:new_pipeline) { create(:ci_pipeline) }
it 'creates or updates matching report results' do
- described_class.upsert_reports([
- {
- project_id: rspec_coverage.project_id,
- ref_path: rspec_coverage.ref_path,
- last_pipeline_id: new_pipeline.id,
- date: rspec_coverage.date,
- group_name: 'rspec',
- data: { 'coverage' => 81.0 }
- },
- {
- project_id: rspec_coverage.project_id,
- ref_path: rspec_coverage.ref_path,
- last_pipeline_id: new_pipeline.id,
- date: rspec_coverage.date,
- group_name: 'karma',
- data: { 'coverage' => 87.0 }
- }
- ])
+ described_class.upsert_reports(
+ [
+ {
+ project_id: rspec_coverage.project_id,
+ ref_path: rspec_coverage.ref_path,
+ last_pipeline_id: new_pipeline.id,
+ date: rspec_coverage.date,
+ group_name: 'rspec',
+ data: { 'coverage' => 81.0 }
+ },
+ {
+ project_id: rspec_coverage.project_id,
+ ref_path: rspec_coverage.ref_path,
+ last_pipeline_id: new_pipeline.id,
+ date: rspec_coverage.date,
+ group_name: 'karma',
+ data: { 'coverage' => 87.0 }
+ }
+ ])
rspec_coverage.reload
diff --git a/spec/models/ci/job_token/project_scope_link_spec.rb b/spec/models/ci/job_token/project_scope_link_spec.rb
index c000a3e29f7..92ed86b55b2 100644
--- a/spec/models/ci/job_token/project_scope_link_spec.rb
+++ b/spec/models/ci/job_token/project_scope_link_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Ci::JobToken::ProjectScopeLink do
it { is_expected.to belong_to(:target_project) }
it { is_expected.to belong_to(:added_by) }
+ let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project) }
it_behaves_like 'cleanup by a loose foreign key' do
@@ -89,16 +90,22 @@ RSpec.describe Ci::JobToken::ProjectScopeLink do
end
end
+ describe 'enums' do
+ let(:directions) { { outbound: 0, inbound: 1 } }
+
+ it { is_expected.to define_enum_for(:direction).with_values(directions) }
+ end
+
context 'loose foreign key on ci_job_token_project_scope_links.source_project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
- let!(:parent) { create(:project) }
+ let!(:parent) { create(:project, namespace: group) }
let!(:model) { create(:ci_job_token_project_scope_link, source_project: parent) }
end
end
context 'loose foreign key on ci_job_token_project_scope_links.target_project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
- let!(:parent) { create(:project) }
+ let!(:parent) { create(:project, namespace: group) }
let!(:model) { create(:ci_job_token_project_scope_link, target_project: parent) }
end
end
diff --git a/spec/models/ci/job_token/scope_spec.rb b/spec/models/ci/job_token/scope_spec.rb
index 4b95adf8476..1e3f6d044d2 100644
--- a/spec/models/ci/job_token/scope_spec.rb
+++ b/spec/models/ci/job_token/scope_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::JobToken::Scope do
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let(:scope) { described_class.new(project) }
@@ -53,7 +53,7 @@ RSpec.describe Ci::JobToken::Scope do
context 'when project scope setting is disabled' do
before do
- project.ci_job_token_scope_enabled = false
+ project.ci_outbound_job_token_scope_enabled = false
end
it 'considers any project to be part of the scope' do
diff --git a/spec/models/ci/pipeline_metadata_spec.rb b/spec/models/ci/pipeline_metadata_spec.rb
new file mode 100644
index 00000000000..0704cbc8ec1
--- /dev/null
+++ b/spec/models/ci/pipeline_metadata_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineMetadata do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:pipeline) }
+
+ describe 'validations' do
+ it { is_expected.to validate_length_of(:title).is_at_least(1).is_at_most(255) }
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:pipeline) }
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index ec03030a4b8..b2316949497 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -43,12 +43,14 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it { is_expected.to have_one(:triggered_by_pipeline) }
it { is_expected.to have_one(:source_job) }
it { is_expected.to have_one(:pipeline_config) }
+ it { is_expected.to have_one(:pipeline_metadata) }
it { is_expected.to respond_to :git_author_name }
it { is_expected.to respond_to :git_author_email }
it { is_expected.to respond_to :git_author_full_text }
it { is_expected.to respond_to :short_sha }
it { is_expected.to delegate_method(:full_path).to(:project).with_prefix }
+ it { is_expected.to delegate_method(:title).to(:pipeline_metadata).allow_nil }
describe 'validations' do
it { is_expected.to validate_presence_of(:sha) }
@@ -2981,6 +2983,24 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+ it 'logs the event' do
+ allow(Gitlab::AppJsonLogger).to receive(:info)
+
+ pipeline.cancel_running
+
+ expect(Gitlab::AppJsonLogger)
+ .to have_received(:info)
+ .with(
+ a_hash_including(
+ event: 'pipeline_cancel_running',
+ pipeline_id: pipeline.id,
+ auto_canceled_by_pipeline_id: nil,
+ cascade_to_children: true,
+ execute_async: true
+ )
+ )
+ end
+
context 'when there is a running external job and a regular job' do
before do
create(:ci_build, :running, pipeline: pipeline)
@@ -3813,7 +3833,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#upstream_root' do
subject { pipeline.upstream_root }
- let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be_with_refind(:pipeline) { create(:ci_pipeline) }
context 'when pipeline is child of child pipeline' do
let!(:root_ancestor) { create(:ci_pipeline) }
@@ -4529,10 +4549,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
it 'returns accessibility report with collected data' do
- expect(subject.urls.keys).to match_array([
- "https://pa11y.org/",
- "https://about.gitlab.com/"
- ])
+ expect(subject.urls.keys).to match_array(
+ [
+ "https://pa11y.org/",
+ "https://about.gitlab.com/"
+ ])
end
context 'when builds are retried' do
@@ -5316,19 +5337,18 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
- describe '#authorized_cluster_agents' do
+ describe '#cluster_agent_authorizations' do
let(:pipeline) { create(:ci_empty_pipeline, :created) }
- let(:agent) { instance_double(Clusters::Agent) }
- let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization, agent: agent) }
+ let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization) }
let(:finder) { double(execute: [authorization]) }
- it 'retrieves agent records from the finder and caches the result' do
+ it 'retrieves authorization records from the finder and caches the result' do
expect(Clusters::AgentAuthorizationsFinder).to receive(:new).once
.with(pipeline.project)
.and_return(finder)
- expect(pipeline.authorized_cluster_agents).to contain_exactly(agent)
- expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached
+ expect(pipeline.cluster_agent_authorizations).to contain_exactly(authorization)
+ expect(pipeline.cluster_agent_authorizations).to contain_exactly(authorization) # cached
end
end
@@ -5486,7 +5506,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'partitioning' do
- let(:pipeline) { build(:ci_pipeline) }
+ let(:pipeline) { build(:ci_pipeline, partition_id: nil) }
before do
allow(described_class).to receive(:current_partition_value) { 123 }
@@ -5516,4 +5536,73 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
end
+
+ describe '#notes=' do
+ context 'when notes already exist' do
+ it 'does not create duplicate notes', :aggregate_failures do
+ time = Time.zone.now
+ pipeline = create(:ci_pipeline, user: user, project: project)
+ note = Note.new(
+ note: 'note',
+ noteable_type: 'Commit',
+ noteable_id: pipeline.id,
+ commit_id: pipeline.id,
+ author_id: user.id,
+ project_id: pipeline.project_id,
+ created_at: time
+ )
+ another_note = note.dup.tap { |note| note.note = 'another note' }
+
+ expect(project.notes.for_commit_id(pipeline.sha).count).to eq(0)
+
+ pipeline.notes = [note]
+
+ expect(project.notes.for_commit_id(pipeline.sha).count).to eq(1)
+
+ pipeline.notes = [note, note, another_note]
+
+ expect(project.notes.for_commit_id(pipeline.sha).count).to eq(2)
+ expect(project.notes.for_commit_id(pipeline.sha).pluck(:note)).to contain_exactly(note.note, another_note.note)
+ end
+ end
+ end
+
+ describe '#has_erasable_artifacts?' do
+ subject { pipeline.has_erasable_artifacts? }
+
+ context 'when pipeline is not complete' do
+ let(:pipeline) { create(:ci_pipeline, :running, :with_job) }
+
+ context 'and has erasable artifacts' do
+ before do
+ create(:ci_job_artifact, :archive, job: pipeline.builds.first)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when pipeline is complete' do
+ let(:pipeline) { create(:ci_pipeline, :success, :with_job) }
+
+ context 'and has no artifacts' do
+ it { is_expected.to be_falsey }
+ end
+
+ Ci::JobArtifact.erasable_file_types.each do |type|
+ context "and has an artifact of type #{type}" do
+ before do
+ create(
+ :ci_job_artifact,
+ file_format: ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS[type.to_sym],
+ file_type: type,
+ job: pipeline.builds.first
+ )
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index 61e2864a518..a199111b1e3 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -177,7 +177,7 @@ RSpec.describe Ci::Processable 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, :job_variables_attributes] -
+ [:tag_list, :needs_attributes, :job_variables_attributes, :id_tokens] -
# ToDo: Move EE accessors to ee/
::Ci::Build.extra_accessors -
[:dast_site_profiles_build, :dast_scanner_profiles_build]
diff --git a/spec/models/ci/resource_group_spec.rb b/spec/models/ci/resource_group_spec.rb
index 76e74f3193c..e8eccc233db 100644
--- a/spec/models/ci/resource_group_spec.rb
+++ b/spec/models/ci/resource_group_spec.rb
@@ -3,8 +3,10 @@
require 'spec_helper'
RSpec.describe Ci::ResourceGroup do
+ let_it_be(:group) { create(:group) }
+
it_behaves_like 'cleanup by a loose foreign key' do
- let!(:parent) { create(:project) }
+ let!(:parent) { create(:project, group: group) }
let!(:model) { create(:ci_resource_group, project: parent) }
end
@@ -94,7 +96,7 @@ RSpec.describe Ci::ResourceGroup do
describe '#upcoming_processables' do
subject { resource_group.upcoming_processables }
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
let_it_be(:pipeline_1) { create(:ci_pipeline, project: project) }
let_it_be(:pipeline_2) { create(:ci_pipeline, project: project) }
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 181351222c1..13eb7086586 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -1186,7 +1186,7 @@ RSpec.describe Ci::Runner do
end
end
- context 'Project-related queries' do
+ describe 'Project-related queries' do
let_it_be(:project1) { create(:project) }
let_it_be(:project2) { create(:project) }
@@ -1206,14 +1206,14 @@ RSpec.describe Ci::Runner do
end
end
- describe "belongs_to_one_project?" do
+ describe '#belongs_to_one_project?' do
it "returns false if there are two projects runner is assigned to" do
runner = create(:ci_runner, :project, projects: [project1, project2])
expect(runner.belongs_to_one_project?).to be_falsey
end
- it "returns true if there is only one project runner is assigned to" do
+ it 'returns true if there is only one project runner is assigned to' do
runner = create(:ci_runner, :project, projects: [project1])
expect(runner.belongs_to_one_project?).to be_truthy
@@ -1537,47 +1537,155 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq(contacted_at_stored) }
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])
+ describe 'Group-related queries' do
+ # Groups
+ let_it_be(:top_level_group) { create(:group) }
+ let_it_be(:child_group) { create(:group, parent: top_level_group) }
+ let_it_be(:child_group2) { create(:group, parent: top_level_group) }
+ let_it_be(:other_top_level_group) { create(:group) }
+
+ # Projects
+ let_it_be(:top_level_group_project) { create(:project, group: top_level_group) }
+ let_it_be(:child_group_project) { create(:project, group: child_group) }
+ let_it_be(:other_top_level_group_project) { create(:project, group: other_top_level_group) }
- expect(described_class.belonging_to_group(group.id)).to contain_exactly(runner)
+ # Runners
+ let_it_be(:instance_runner) { create(:ci_runner, :instance) }
+ let_it_be(:top_level_group_runner) { create(:ci_runner, :group, groups: [top_level_group]) }
+ let_it_be(:child_group_runner) { create(:ci_runner, :group, groups: [child_group]) }
+ let_it_be(:child_group2_runner) { create(:ci_runner, :group, groups: [child_group2]) }
+ let_it_be(:other_top_level_group_runner) do
+ create(:ci_runner, :group, groups: [other_top_level_group])
end
- end
- describe '.belonging_to_group_and_ancestors' 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) }
+ let_it_be(:top_level_group_project_runner) do
+ create(:ci_runner, :project, projects: [top_level_group_project])
+ end
- it 'returns the group runner from the parent group' do
- expect(described_class.belonging_to_group_and_ancestors(group.id)).to contain_exactly(parent_runner)
+ let_it_be(:child_group_project_runner) do
+ create(:ci_runner, :project, projects: [child_group_project])
end
- end
- describe '.belonging_to_group_or_project_descendants' do
- it 'returns the specific group runners' do
- group1 = create(:group)
- group2 = create(:group, parent: group1)
- group3 = create(:group)
-
- project1 = create(:project, namespace: group1)
- project2 = create(:project, namespace: group2)
- project3 = create(:project, namespace: group3)
-
- runner1 = create(:ci_runner, :group, groups: [group1])
- runner2 = create(:ci_runner, :group, groups: [group2])
- _runner3 = create(:ci_runner, :group, groups: [group3])
- runner4 = create(:ci_runner, :project, projects: [project1])
- runner5 = create(:ci_runner, :project, projects: [project2])
- _runner6 = create(:ci_runner, :project, projects: [project3])
-
- expect(described_class.belonging_to_group_or_project_descendants(group1.id)).to contain_exactly(
- runner1, runner2, runner4, runner5
- )
+ let_it_be(:other_top_level_group_project_runner) do
+ create(:ci_runner, :project, projects: [other_top_level_group_project])
+ end
+
+ let_it_be(:shared_top_level_group_project_runner) do
+ create(:ci_runner, :project, projects: [top_level_group_project, child_group_project])
+ end
+
+ describe '.belonging_to_group' do
+ subject(:relation) { described_class.belonging_to_group(scope.id) }
+
+ context 'with scope set to top_level_group' do
+ let(:scope) { top_level_group }
+
+ it 'returns the group runners from the top_level_group' do
+ is_expected.to contain_exactly(top_level_group_runner)
+ end
+ end
+
+ context 'with scope set to child_group' do
+ let(:scope) { child_group }
+
+ it 'returns the group runners from the child_group' do
+ is_expected.to contain_exactly(child_group_runner)
+ end
+ end
+ end
+
+ describe '.belonging_to_group_and_ancestors' do
+ subject(:relation) { described_class.belonging_to_group_and_ancestors(child_group.id) }
+
+ it 'returns the group runners from the group and parent group' do
+ is_expected.to contain_exactly(child_group_runner, top_level_group_runner)
+ end
+ end
+
+ describe '.belonging_to_group_or_project_descendants' do
+ subject(:relation) { described_class.belonging_to_group_or_project_descendants(scope.id) }
+
+ context 'with scope set to top_level_group' do
+ let(:scope) { top_level_group }
+
+ it 'returns the expected group and project runners without duplicates', :aggregate_failures do
+ expect(relation).to contain_exactly(
+ top_level_group_runner,
+ top_level_group_project_runner,
+ child_group_runner,
+ child_group_project_runner,
+ child_group2_runner,
+ shared_top_level_group_project_runner
+ )
+
+ # Ensure no duplicates are returned
+ expect(relation.distinct).to match_array(relation)
+ end
+ end
+
+ context 'with scope set to child_group' do
+ let(:scope) { child_group }
+
+ it 'returns the expected group and project runners without duplicates', :aggregate_failures do
+ expect(relation).to contain_exactly(
+ child_group_runner,
+ child_group_project_runner,
+ shared_top_level_group_project_runner
+ )
+
+ # Ensure no duplicates are returned
+ expect(relation.distinct).to match_array(relation)
+ end
+ end
+ end
+
+ describe '.usable_from_scope' do
+ subject(:relation) { described_class.usable_from_scope(scope) }
+
+ context 'with scope set to top_level_group' do
+ let(:scope) { top_level_group }
+
+ it 'returns all runners usable from top_level_group without duplicates' do
+ expect(relation).to contain_exactly(
+ instance_runner,
+ top_level_group_runner,
+ top_level_group_project_runner,
+ child_group_runner,
+ child_group_project_runner,
+ child_group2_runner,
+ shared_top_level_group_project_runner
+ )
+
+ # Ensure no duplicates are returned
+ expect(relation.distinct).to match_array(relation)
+ end
+ end
+
+ context 'with scope set to child_group' do
+ let(:scope) { child_group }
+
+ it 'returns all runners usable from child_group' do
+ expect(relation).to contain_exactly(
+ instance_runner,
+ top_level_group_runner,
+ child_group_runner,
+ child_group_project_runner,
+ shared_top_level_group_project_runner
+ )
+ end
+ end
+
+ context 'with scope set to other_top_level_group' do
+ let(:scope) { other_top_level_group }
+
+ it 'returns all runners usable from other_top_level_group' do
+ expect(relation).to contain_exactly(
+ instance_runner,
+ other_top_level_group_runner,
+ other_top_level_group_project_runner
+ )
+ end
+ end
end
end
diff --git a/spec/models/ci/secure_file_spec.rb b/spec/models/ci/secure_file_spec.rb
index e47efff5dfd..20f64d40865 100644
--- a/spec/models/ci/secure_file_spec.rb
+++ b/spec/models/ci/secure_file_spec.rb
@@ -81,4 +81,70 @@ RSpec.describe Ci::SecureFile do
expect(Base64.encode64(subject.file.read)).to eq(Base64.encode64(sample_file))
end
end
+
+ describe '#file_extension' do
+ it 'returns the extension for the file name' do
+ file = build(:ci_secure_file, name: 'file1.cer')
+ expect(file.file_extension).to eq('cer')
+ end
+
+ it 'returns only the last part of the extension for the file name' do
+ file = build(:ci_secure_file, name: 'file1.tar.gz')
+ expect(file.file_extension).to eq('gz')
+ end
+ end
+
+ describe '#metadata_parsable?' do
+ it 'returns true when the file extension has a supported parser' do
+ file = build(:ci_secure_file, name: 'file1.cer')
+ expect(file.metadata_parsable?).to be true
+ end
+
+ it 'returns false when the file extension does not have a supported parser' do
+ file = build(:ci_secure_file, name: 'file1.foo')
+ expect(file.metadata_parsable?).to be false
+ end
+ end
+
+ describe '#metadata_parser' do
+ it 'returns an instance of Gitlab::Ci::SecureFiles::Cer when a .cer file is supplied' do
+ file = build(:ci_secure_file, name: 'file1.cer')
+ expect(file.metadata_parser).to be_an_instance_of(Gitlab::Ci::SecureFiles::Cer)
+ end
+
+ it 'returns an instance of Gitlab::Ci::SecureFiles::P12 when a .p12 file is supplied' do
+ file = build(:ci_secure_file, name: 'file1.p12')
+ expect(file.metadata_parser).to be_an_instance_of(Gitlab::Ci::SecureFiles::P12)
+ end
+
+ it 'returns an instance of Gitlab::Ci::SecureFiles::MobileProvision when a .mobileprovision file is supplied' do
+ file = build(:ci_secure_file, name: 'file1.mobileprovision')
+ expect(file.metadata_parser).to be_an_instance_of(Gitlab::Ci::SecureFiles::MobileProvision)
+ end
+
+ it 'returns nil when the file type is not supported by any parsers' do
+ file = build(:ci_secure_file, name: 'file1.foo')
+ expect(file.metadata_parser).to be nil
+ end
+ end
+
+ describe '#update_metadata!' do
+ it 'assigns the expected metadata when a parsable file is supplied' do
+ file = create(:ci_secure_file, name: 'file1.cer',
+ file: CarrierWaveStringFile.new(fixture_file('ci_secure_files/sample.cer') ))
+ file.update_metadata!
+
+ expect(file.expires_at).to eq(DateTime.parse('2022-04-26 19:20:40'))
+ expect(file.metadata['id']).to eq('33669367788748363528491290218354043267')
+ expect(file.metadata['issuer']['CN']).to eq('Apple Worldwide Developer Relations Certification Authority')
+ expect(file.metadata['subject']['OU']).to eq('N7SYAN8PX8')
+ end
+
+ it 'logs an error when something goes wrong with the file parsing' do
+ corrupt_file = create(:ci_secure_file, name: 'file1.cer', file: CarrierWaveStringFile.new('11111111'))
+ message = 'Validation failed: Metadata must be a valid json schema - not enough data.'
+ expect(Gitlab::AppLogger).to receive(:error).with("Secure File Parser Failure (#{corrupt_file.id}): #{message}")
+ corrupt_file.update_metadata!
+ end
+ end
end
diff --git a/spec/models/ci/unit_test_spec.rb b/spec/models/ci/unit_test_spec.rb
index 556cf93c266..b3180492a36 100644
--- a/spec/models/ci/unit_test_spec.rb
+++ b/spec/models/ci/unit_test_spec.rb
@@ -43,18 +43,19 @@ RSpec.describe Ci::UnitTest do
result = described_class.find_or_create_by_batch(project, attrs)
- expect(result).to match_array([
- have_attributes(
- key_hash: existing_test.key_hash,
- suite_name: 'rspec',
- name: 'Math#sum adds numbers'
- ),
- have_attributes(
- key_hash: new_key,
- suite_name: 'jest',
- name: 'Component works'
- )
- ])
+ expect(result).to match_array(
+ [
+ have_attributes(
+ key_hash: existing_test.key_hash,
+ suite_name: 'rspec',
+ name: 'Math#sum adds numbers'
+ ),
+ have_attributes(
+ key_hash: new_key,
+ suite_name: 'jest',
+ name: 'Component works'
+ )
+ ])
expect(result).to all(be_persisted)
end
@@ -77,13 +78,14 @@ RSpec.describe Ci::UnitTest do
result = described_class.find_or_create_by_batch(project, attrs)
- expect(result).to match_array([
- have_attributes(
- key_hash: new_key,
- suite_name: 'abc...',
- name: 'abc...'
- )
- ])
+ expect(result).to match_array(
+ [
+ have_attributes(
+ key_hash: new_key,
+ suite_name: 'abc...',
+ name: 'abc...'
+ )
+ ])
expect(result).to all(be_persisted)
end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index f0af229ff2c..5f2b5971508 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe Ci::Variable do
context 'loose foreign key on ci_variables.project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
- let!(:parent) { create(:project) }
+ let!(:parent) { create(:project, namespace: create(:group)) }
let!(:model) { create(:ci_variable, project: parent) }
end
end
diff --git a/spec/models/clusters/agents/implicit_authorization_spec.rb b/spec/models/clusters/agents/implicit_authorization_spec.rb
index 2d6c3ddb426..1f4c5b1ac9e 100644
--- a/spec/models/clusters/agents/implicit_authorization_spec.rb
+++ b/spec/models/clusters/agents/implicit_authorization_spec.rb
@@ -10,5 +10,5 @@ RSpec.describe Clusters::Agents::ImplicitAuthorization do
it { expect(subject.agent).to eq(agent) }
it { expect(subject.agent_id).to eq(agent.id) }
it { expect(subject.config_project).to eq(agent.project) }
- it { expect(subject.config).to be_nil }
+ it { expect(subject.config).to eq({}) }
end
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 3044260a000..05ab8c4108e 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -49,13 +49,15 @@ RSpec.describe Clusters::Applications::CertManager do
expect(subject.version).to eq('v0.10.1')
expect(subject).to be_rbac
expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
- expect(subject.preinstall).to eq([
- 'kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.10/deploy/manifests/00-crds.yaml',
- 'kubectl label --overwrite namespace gitlab-managed-apps certmanager.k8s.io/disable-validation=true'
- ])
- expect(subject.postinstall).to eq([
- "for i in $(seq 1 90); do kubectl apply -f /data/helm/certmanager/config/cluster_issuer.yaml && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
- ])
+ expect(subject.preinstall).to eq(
+ [
+ 'kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.10/deploy/manifests/00-crds.yaml',
+ 'kubectl label --overwrite namespace gitlab-managed-apps certmanager.k8s.io/disable-validation=true'
+ ])
+ expect(subject.postinstall).to eq(
+ [
+ "for i in $(seq 1 90); do kubectl apply -f /data/helm/certmanager/config/cluster_issuer.yaml && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
+ ])
end
context 'for a specific user' do
@@ -99,15 +101,16 @@ RSpec.describe Clusters::Applications::CertManager do
end
it 'specifies a post delete command to remove custom resource definitions' do
- expect(subject.postdelete).to eq([
- 'kubectl delete secret -n gitlab-managed-apps letsencrypt-prod --ignore-not-found',
- 'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
- ])
+ expect(subject.postdelete).to eq(
+ [
+ 'kubectl delete secret -n gitlab-managed-apps letsencrypt-prod --ignore-not-found',
+ 'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
+ ])
end
context 'secret key name is not found' do
@@ -119,14 +122,15 @@ RSpec.describe Clusters::Applications::CertManager do
end
it 'does not try and delete the secret' do
- expect(subject.postdelete).to eq([
- 'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
- 'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
- ])
+ expect(subject.postdelete).to eq(
+ [
+ 'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
+ 'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
+ ])
end
end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 7b9ff409edd..4ac2fd022ba 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -601,19 +601,27 @@ RSpec.describe Clusters::Platforms::Kubernetes do
it 'creates a matching RolloutStatus' do
expect(rollout_status).to be_kind_of(::Gitlab::Kubernetes::RolloutStatus)
- expect(rollout_status.deployments.map(&:annotations)).to eq([
- { 'app.gitlab.com/app' => project.full_path_slug, 'app.gitlab.com/env' => 'env-000000' }
- ])
- expect(rollout_status.instances).to eq([{ pod_name: "kube-pod",
- stable: true,
- status: "pending",
- tooltip: "kube-pod (Pending)",
- track: "stable" },
- { pod_name: "Not provided",
- stable: true,
- status: "pending",
- tooltip: "Not provided (Pending)",
- track: "stable" }])
+ expect(rollout_status.deployments.map(&:annotations)).to eq(
+ [
+ { 'app.gitlab.com/app' => project.full_path_slug, 'app.gitlab.com/env' => 'env-000000' }
+ ])
+ expect(rollout_status.instances).to eq(
+ [
+ {
+ pod_name: "kube-pod",
+ stable: true,
+ status: "pending",
+ tooltip: "kube-pod (Pending)",
+ track: "stable"
+ },
+ {
+ pod_name: "Not provided",
+ stable: true,
+ status: "pending",
+ tooltip: "Not provided (Pending)",
+ track: "stable"
+ }
+ ])
end
context 'with canary ingress' do
@@ -720,11 +728,12 @@ RSpec.describe Clusters::Platforms::Kubernetes do
end
it 'returns a pending pod for each missing replica' do
- expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status) }).to eq([
- { pod_name: 'pod-a-1', status: 'running' },
- { pod_name: 'Not provided', status: 'pending' },
- { pod_name: 'Not provided', status: 'pending' }
- ])
+ expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status) }).to eq(
+ [
+ { pod_name: 'pod-a-1', status: 'running' },
+ { pod_name: 'Not provided', status: 'pending' },
+ { pod_name: 'Not provided', status: 'pending' }
+ ])
end
end
@@ -743,12 +752,13 @@ RSpec.describe Clusters::Platforms::Kubernetes do
end
it 'returns the correct track for the pending pods' do
- expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status, :track) }).to eq([
- { pod_name: 'pod-a-1', status: 'running', track: 'canary' },
- { pod_name: 'Not provided', status: 'pending', track: 'canary' },
- { pod_name: 'Not provided', status: 'pending', track: 'stable' },
- { pod_name: 'Not provided', status: 'pending', track: 'stable' }
- ])
+ expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status, :track) }).to eq(
+ [
+ { pod_name: 'pod-a-1', status: 'running', track: 'canary' },
+ { pod_name: 'Not provided', status: 'pending', track: 'canary' },
+ { pod_name: 'Not provided', status: 'pending', track: 'stable' },
+ { pod_name: 'Not provided', status: 'pending', track: 'stable' }
+ ])
end
end
@@ -765,10 +775,11 @@ RSpec.describe Clusters::Platforms::Kubernetes do
end
it 'returns the correct number of pending pods' do
- expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status, :track) }).to eq([
- { pod_name: 'Not provided', status: 'pending', track: 'mytrack' },
- { pod_name: 'Not provided', status: 'pending', track: 'mytrack' }
- ])
+ expect(rollout_status.instances.map { |p| p.slice(:pod_name, :status, :track) }).to eq(
+ [
+ { pod_name: 'Not provided', status: 'pending', track: 'mytrack' },
+ { pod_name: 'Not provided', status: 'pending', track: 'mytrack' }
+ ])
end
end
diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb
index de9b72c1da2..93c696cae54 100644
--- a/spec/models/commit_collection_spec.rb
+++ b/spec/models/commit_collection_spec.rb
@@ -42,10 +42,7 @@ RSpec.describe CommitCollection do
merge_commit = project.commit("60ecb67744cb56576c30214ff52294f8ce2def98")
expect(merge_commit).to receive(:merge_commit?).and_return(true)
- collection = described_class.new(project, [
- commit,
- merge_commit
- ])
+ collection = described_class.new(project, [commit, merge_commit])
expect(collection.without_merge_commits).to contain_exactly(commit)
end
diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb
index 0035fb8468a..dc8429fe77e 100644
--- a/spec/models/compare_spec.rb
+++ b/spec/models/compare_spec.rb
@@ -127,13 +127,14 @@ RSpec.describe Compare do
end
it 'returns affected file paths, without duplication' do
- expect(subject.modified_paths).to contain_exactly(*%w{
- foo/for_move.txt
- foo/bar/for_move.txt
- foo/for_create.txt
- foo/for_delete.txt
- foo/for_edit.txt
- })
+ expect(subject.modified_paths).to contain_exactly(
+ *%w{
+ foo/for_move.txt
+ foo/bar/for_move.txt
+ foo/for_create.txt
+ foo/for_delete.txt
+ foo/for_edit.txt
+ })
end
end
diff --git a/spec/models/concerns/approvable_spec.rb b/spec/models/concerns/approvable_spec.rb
index 1ddd9b3edca..25a4f51cd82 100644
--- a/spec/models/concerns/approvable_spec.rb
+++ b/spec/models/concerns/approvable_spec.rb
@@ -32,8 +32,8 @@ RSpec.describe Approvable do
end
end
- describe '#can_be_approved_by?' do
- subject { merge_request.can_be_approved_by?(user) }
+ describe '#eligible_for_approval_by?' do
+ subject { merge_request.eligible_for_approval_by?(user) }
before do
merge_request.project.add_developer(user) if user
@@ -60,8 +60,8 @@ RSpec.describe Approvable do
end
end
- describe '#can_be_unapproved_by?' do
- subject { merge_request.can_be_unapproved_by?(user) }
+ describe '#eligible_for_unapproval_by?' do
+ subject { merge_request.eligible_for_unapproval_by?(user) }
before do
merge_request.project.add_developer(user) if user
diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb
index b803e699b25..5fe3141eb17 100644
--- a/spec/models/concerns/atomic_internal_id_spec.rb
+++ b/spec/models/concerns/atomic_internal_id_spec.rb
@@ -3,10 +3,11 @@
require 'spec_helper'
RSpec.describe AtomicInternalId do
- let(:milestone) { build(:milestone) }
+ let_it_be(:project) { create(:project) }
+ let(:milestone) { build(:milestone, project: project) }
let(:iid) { double('iid', to_i: 42) }
let(:external_iid) { 100 }
- let(:scope_attrs) { { project: milestone.project } }
+ let(:scope_attrs) { { project: project } }
let(:usage) { :milestones }
describe '#save!' do
@@ -248,4 +249,12 @@ RSpec.describe AtomicInternalId do
end.to change { InternalId.find_by(project: milestone.project, usage: :milestones)&.last_value.to_i }.by(4)
end
end
+
+ describe '.track_project_iid!' do
+ it 'tracks the present value' do
+ expect do
+ ::Issue.track_project_iid!(milestone.project, external_iid)
+ end.to change { InternalId.find_by(project: milestone.project, usage: :issues)&.last_value.to_i }.to(external_iid)
+ end
+ end
end
diff --git a/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb b/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
deleted file mode 100644
index 6be6e3f048f..00000000000
--- a/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
+++ /dev/null
@@ -1,347 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe NamespaceSetting, 'CascadingNamespaceSettingAttribute' do
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
-
- def group_settings
- group.namespace_settings
- end
-
- def subgroup_settings
- subgroup.namespace_settings
- end
-
- describe '#delayed_project_removal' do
- subject(:delayed_project_removal) { subgroup_settings.delayed_project_removal }
-
- context 'when there is no parent' do
- context 'and the value is not nil' do
- before do
- group_settings.update!(delayed_project_removal: true)
- end
-
- it 'returns the local value' do
- expect(group_settings.delayed_project_removal).to eq(true)
- end
- end
-
- context 'and the value is nil' do
- before do
- group_settings.update!(delayed_project_removal: nil)
- stub_application_setting(delayed_project_removal: false)
- end
-
- it 'returns the application settings value' do
- expect(group_settings.delayed_project_removal).to eq(false)
- end
- end
- end
-
- context 'when parent does not lock the attribute' do
- context 'and value is not nil' do
- before do
- group_settings.update!(delayed_project_removal: false)
- end
-
- it 'returns local setting when present' do
- subgroup_settings.update!(delayed_project_removal: true)
-
- expect(delayed_project_removal).to eq(true)
- end
-
- it 'returns the parent value when local value is nil' do
- subgroup_settings.update!(delayed_project_removal: nil)
-
- expect(delayed_project_removal).to eq(false)
- end
-
- it 'returns the correct dirty value' do
- subgroup_settings.delayed_project_removal = true
-
- expect(delayed_project_removal).to eq(true)
- end
-
- it 'does not return the application setting value when parent value is false' do
- stub_application_setting(delayed_project_removal: true)
-
- expect(delayed_project_removal).to eq(false)
- end
- end
-
- context 'and the value is nil' do
- before do
- group_settings.update!(delayed_project_removal: nil, lock_delayed_project_removal: false)
- subgroup_settings.update!(delayed_project_removal: nil)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- end
-
- it 'cascades to the application settings value' do
- expect(delayed_project_removal).to eq(false)
- end
- end
-
- context 'when multiple ancestors set a value' do
- let(:third_level_subgroup) { create(:group, parent: subgroup) }
-
- before do
- group_settings.update!(delayed_project_removal: true)
- subgroup_settings.update!(delayed_project_removal: false)
- end
-
- it 'returns the closest ancestor value' do
- expect(third_level_subgroup.namespace_settings.delayed_project_removal).to eq(false)
- end
- end
- end
-
- context 'when parent locks the attribute' do
- before do
- subgroup_settings.update!(delayed_project_removal: true)
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
- end
-
- it 'returns the parent value' do
- expect(delayed_project_removal).to eq(false)
- end
-
- it 'does not allow the local value to be saved' do
- subgroup_settings.delayed_project_removal = nil
-
- expect { subgroup_settings.save! }
- .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be changed because it is locked by an ancestor/)
- end
- end
-
- context 'when the application settings locks the attribute' do
- before do
- subgroup_settings.update!(delayed_project_removal: true)
- stub_application_setting(lock_delayed_project_removal: true, delayed_project_removal: true)
- end
-
- it 'returns the application setting value' do
- expect(delayed_project_removal).to eq(true)
- end
-
- it 'does not allow the local value to be saved' do
- subgroup_settings.delayed_project_removal = false
-
- expect { subgroup_settings.save! }
- .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be changed because it is locked by an ancestor/)
- end
- end
-
- context 'when parent locked the attribute then the application settings locks it' do
- before do
- subgroup_settings.update!(delayed_project_removal: true)
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
- stub_application_setting(lock_delayed_project_removal: true, delayed_project_removal: true)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
- end
-
- it 'returns the application setting value' do
- expect(delayed_project_removal).to eq(true)
- end
- end
- end
-
- describe '#delayed_project_removal?' do
- before do
- subgroup_settings.update!(delayed_project_removal: true)
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
- end
-
- it 'aliases the method when the attribute is a boolean' do
- expect(subgroup_settings.delayed_project_removal?).to eq(subgroup_settings.delayed_project_removal)
- end
- end
-
- describe '#delayed_project_removal=' do
- before do
- subgroup_settings.update!(delayed_project_removal: nil)
- group_settings.update!(delayed_project_removal: true)
- end
-
- it 'does not save the value locally when it matches the cascaded value' do
- subgroup_settings.update!(delayed_project_removal: true)
-
- expect(subgroup_settings.read_attribute(:delayed_project_removal)).to eq(nil)
- end
- end
-
- describe '#delayed_project_removal_locked?' do
- shared_examples 'not locked' do
- it 'is not locked by an ancestor' do
- expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(false)
- end
-
- it 'is not locked by application setting' do
- expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(false)
- end
-
- it 'does not return a locked namespace' do
- expect(subgroup_settings.delayed_project_removal_locked_ancestor).to be_nil
- end
- end
-
- context 'when attribute is locked by self' do
- before do
- subgroup_settings.update!(lock_delayed_project_removal: true)
- end
-
- it 'is not locked by default' do
- expect(subgroup_settings.delayed_project_removal_locked?).to eq(false)
- end
-
- it 'is locked when including self' do
- expect(subgroup_settings.delayed_project_removal_locked?(include_self: true)).to eq(true)
- end
- end
-
- context 'when parent does not lock the attribute' do
- it_behaves_like 'not locked'
- end
-
- context 'when parent locks the attribute' do
- before do
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
- end
-
- it 'is locked by an ancestor' do
- expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(true)
- end
-
- it 'is not locked by application setting' do
- expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(false)
- end
-
- it 'returns a locked namespace settings object' do
- expect(subgroup_settings.delayed_project_removal_locked_ancestor.namespace_id).to eq(group_settings.namespace_id)
- end
- end
-
- context 'when not locked by application settings' do
- before do
- stub_application_setting(lock_delayed_project_removal: false)
- end
-
- it_behaves_like 'not locked'
- end
-
- context 'when locked by application settings' do
- before do
- stub_application_setting(lock_delayed_project_removal: true)
- end
-
- it 'is not locked by an ancestor' do
- expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(false)
- end
-
- it 'is locked by application setting' do
- expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(true)
- end
-
- it 'does not return a locked namespace' do
- expect(subgroup_settings.delayed_project_removal_locked_ancestor).to be_nil
- end
- end
- end
-
- describe '#lock_delayed_project_removal=' do
- context 'when parent locks the attribute' do
- before do
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
-
- subgroup_settings.clear_memoization(:delayed_project_removal)
- subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
- end
-
- it 'does not allow the attribute to be saved' do
- subgroup_settings.lock_delayed_project_removal = true
-
- expect { subgroup_settings.save! }
- .to raise_error(ActiveRecord::RecordInvalid, /Lock delayed project removal cannot be changed because it is locked by an ancestor/)
- end
- end
-
- context 'when parent does not lock the attribute' do
- before do
- group_settings.update!(lock_delayed_project_removal: false)
-
- subgroup_settings.lock_delayed_project_removal = true
- end
-
- it 'allows the lock to be set when the attribute is not nil' do
- subgroup_settings.delayed_project_removal = true
-
- expect(subgroup_settings.save).to eq(true)
- end
-
- it 'does not allow the lock to be saved when the attribute is nil' do
- subgroup_settings.delayed_project_removal = nil
-
- expect { subgroup_settings.save! }
- .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be nil when locking the attribute/)
- end
-
- it 'copies the cascaded value when locking the attribute if the local value is nil', :aggregate_failures do
- subgroup_settings.delayed_project_removal = nil
- subgroup_settings.lock_delayed_project_removal = true
-
- expect(subgroup_settings.read_attribute(:delayed_project_removal)).to eq(false)
- end
- end
-
- context 'when application settings locks the attribute' do
- before do
- stub_application_setting(lock_delayed_project_removal: true)
- end
-
- it 'does not allow the attribute to be saved' do
- subgroup_settings.lock_delayed_project_removal = true
-
- expect { subgroup_settings.save! }
- .to raise_error(ActiveRecord::RecordInvalid, /Lock delayed project removal cannot be changed because it is locked by an ancestor/)
- end
- end
-
- context 'when application_settings does not lock the attribute' do
- before do
- stub_application_setting(lock_delayed_project_removal: false)
- end
-
- it 'allows the attribute to be saved' do
- subgroup_settings.delayed_project_removal = true
- subgroup_settings.lock_delayed_project_removal = true
-
- expect(subgroup_settings.save).to eq(true)
- end
- end
- end
-
- describe 'after update callback' do
- before do
- subgroup_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
- end
-
- it 'clears descendant locks' do
- group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: true)
-
- expect(subgroup_settings.reload.lock_delayed_project_removal).to eq(false)
- end
- end
-end
diff --git a/spec/models/concerns/ci/partitionable_spec.rb b/spec/models/concerns/ci/partitionable_spec.rb
new file mode 100644
index 00000000000..d53501ccc3d
--- /dev/null
+++ b/spec/models/concerns/ci/partitionable_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Partitionable do
+ describe 'partitionable models inclusion' do
+ let(:ci_model) { Class.new(Ci::ApplicationRecord) }
+
+ subject { ci_model.include(described_class) }
+
+ it 'raises an exception' do
+ expect { subject }
+ .to raise_error(/must be included in PARTITIONABLE_MODELS/)
+ end
+
+ context 'when is included in the models list' do
+ before do
+ stub_const("#{described_class}::Testing::PARTITIONABLE_MODELS", [ci_model.name])
+ end
+
+ it 'does not raise exceptions' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/counter_attribute_spec.rb b/spec/models/concerns/counter_attribute_spec.rb
index 2dd70188740..66ccd4559e5 100644
--- a/spec/models/concerns/counter_attribute_spec.rb
+++ b/spec/models/concerns/counter_attribute_spec.rb
@@ -73,8 +73,8 @@ RSpec.describe CounterAttribute, :counter_attribute, :clean_gitlab_redis_shared_
subject
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.exists(increment_key)).to be_falsey
- expect(redis.exists(flushed_key)).to eq(flushed_key_present)
+ expect(redis.exists?(increment_key)).to eq(false)
+ expect(redis.exists?(flushed_key)).to eq(flushed_key_present)
end
end
end
diff --git a/spec/models/concerns/id_in_ordered_spec.rb b/spec/models/concerns/id_in_ordered_spec.rb
index a3b434caac6..15da079f2bc 100644
--- a/spec/models/concerns/id_in_ordered_spec.rb
+++ b/spec/models/concerns/id_in_ordered_spec.rb
@@ -12,9 +12,10 @@ RSpec.describe IdInOrdered do
issue4 = create(:issue)
issue5 = create(:issue)
- expect(Issue.id_in_ordered([issue3.id, issue1.id, issue4.id, issue5.id, issue2.id])).to eq([
- issue3, issue1, issue4, issue5, issue2
- ])
+ expect(Issue.id_in_ordered([issue3.id, issue1.id, issue4.id, issue5.id, issue2.id])).to eq(
+ [
+ issue3, issue1, issue4, issue5, issue2
+ ])
end
context 'when the ids are not an array of integers' do
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 6763cc904b4..8842a36f40a 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -75,6 +75,24 @@ RSpec.describe Issuable do
it_behaves_like 'truncates the description to its allowed maximum length on import'
end
+
+ describe '#validate_assignee_length' do
+ let(:assignee_1) { create(:user) }
+ let(:assignee_2) { create(:user) }
+ let(:assignee_3) { create(:user) }
+
+ subject { create(:merge_request) }
+
+ before do
+ stub_const("Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS", 2)
+ end
+
+ it 'will not exceed the assignee limit' do
+ expect do
+ subject.update!(assignees: [assignee_1, assignee_2, assignee_3])
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
end
describe "Scope" do
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index 9daea3438cb..7bbbd10ec8d 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe Commit, 'Mentionable' do
end
context 'with external issue tracker' do
- let(:project) { create(:jira_project, :repository) }
+ let(:project) { create(:project, :with_jira_integration, :repository) }
it 'is true if external issues referenced' do
allow(commit.raw).to receive(:message).and_return 'JIRA-123'
diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb
index 81ae30b7116..82aca13c929 100644
--- a/spec/models/concerns/noteable_spec.rb
+++ b/spec/models/concerns/noteable_spec.rb
@@ -47,18 +47,19 @@ RSpec.describe Noteable do
let(:discussions) { subject.discussions }
it 'includes discussions for diff notes, commit diff notes, commit notes, and regular notes' do
- expect(discussions).to eq([
- DiffDiscussion.new([active_diff_note1, active_diff_note2], subject),
- DiffDiscussion.new([active_diff_note3], subject),
- DiffDiscussion.new([outdated_diff_note1, outdated_diff_note2], subject),
- Discussion.new([discussion_note1, discussion_note2], subject),
- DiffDiscussion.new([commit_diff_note1, commit_diff_note2], subject),
- OutOfContextDiscussion.new([commit_note1, commit_note2], subject),
- Discussion.new([commit_discussion_note1, commit_discussion_note2], subject),
- Discussion.new([commit_discussion_note3], subject),
- IndividualNoteDiscussion.new([note1], subject),
- IndividualNoteDiscussion.new([note2], subject)
- ])
+ expect(discussions).to eq(
+ [
+ DiffDiscussion.new([active_diff_note1, active_diff_note2], subject),
+ DiffDiscussion.new([active_diff_note3], subject),
+ DiffDiscussion.new([outdated_diff_note1, outdated_diff_note2], subject),
+ Discussion.new([discussion_note1, discussion_note2], subject),
+ DiffDiscussion.new([commit_diff_note1, commit_diff_note2], subject),
+ OutOfContextDiscussion.new([commit_note1, commit_note2], subject),
+ Discussion.new([commit_discussion_note1, commit_discussion_note2], subject),
+ Discussion.new([commit_discussion_note3], subject),
+ IndividualNoteDiscussion.new([note1], subject),
+ IndividualNoteDiscussion.new([note2], subject)
+ ])
end
end
@@ -88,23 +89,24 @@ RSpec.describe Noteable do
{ table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
end
- expect(discussions).to match([
- a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id),
- a_hash_including(table_name: 'resource_label_events', id: label_event.id),
- a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
- a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
- a_hash_including(table_name: 'resource_state_events', id: state_event.id)
- ])
+ expect(discussions).to match(
+ [
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id),
+ a_hash_including(table_name: 'resource_label_events', id: label_event.id),
+ a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
+ a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
+ a_hash_including(table_name: 'resource_state_events', id: state_event.id)
+ ])
end
it 'filters by comments only' do
@@ -112,19 +114,20 @@ RSpec.describe Noteable do
{ table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
end
- expect(discussions).to match([
- a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
- a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id)
- ])
+ expect(discussions).to match(
+ [
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id)
+ ])
end
it 'filters by system notes only' do
@@ -132,12 +135,13 @@ RSpec.describe Noteable do
{ table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
end
- expect(discussions).to match([
- a_hash_including(table_name: 'resource_label_events', id: label_event.id),
- a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
- a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
- a_hash_including(table_name: 'resource_state_events', id: state_event.id)
- ])
+ expect(discussions).to match(
+ [
+ a_hash_including(table_name: 'resource_label_events', id: label_event.id),
+ a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
+ a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
+ a_hash_including(table_name: 'resource_state_events', id: state_event.id)
+ ])
end
end
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index f7f68cb38d8..58a44fec3aa 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -186,6 +186,9 @@ RSpec.describe Participable do
expect(instance.visible_participants(user1)).to match_array [user1, user2]
end
end
+
+ it_behaves_like 'visible participants for issuable with read ability', :issue
+ it_behaves_like 'visible participants for issuable with read ability', :merge_request
end
describe '#participant?' do
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index 4158e8a0a4c..d3a44ac8403 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
include PrometheusHelpers
include ReactiveCachingHelpers
- let(:project) { create(:prometheus_project) }
+ let(:project) { create(:project, :with_prometheus_integration) }
let(:integration) { project.prometheus_integration }
let(:described_class) do
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index cf66ba83e87..dc1002f3560 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -23,6 +23,12 @@ RSpec.shared_examples 'routable resource' do
end.not_to exceed_all_query_limit(control_count)
end
+ context 'when path is a negative number' do
+ it 'returns nil' do
+ expect(described_class.find_by_full_path(-1)).to be_nil
+ end
+ end
+
context 'with redirect routes' do
let_it_be(:redirect_route) { create(:redirect_route, source: record) }
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 3f6bbe795cc..e8db83b7144 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -314,52 +314,22 @@ RSpec.describe Ci::Runner, 'TokenAuthenticatable', :freeze_time do
describe '#token_expired?' do
subject { runner.token_expired? }
- context 'when enforce_runner_token_expires_at feature flag is disabled' do
- before do
- stub_feature_flags(enforce_runner_token_expires_at: false)
- end
-
- context 'when runner has no token expiration' do
- let(:runner) { non_expirable_runner }
-
- it { is_expected.to eq(false) }
- end
-
- context 'when runner token is not expired' do
- let(:runner) { non_expired_runner }
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
- it { is_expected.to eq(false) }
- end
-
- context 'when runner token is expired' do
- let(:runner) { expired_runner }
-
- it { is_expected.to eq(false) }
- end
+ it { is_expected.to eq(false) }
end
- context 'when enforce_runner_token_expires_at feature flag is enabled' do
- before do
- stub_feature_flags(enforce_runner_token_expires_at: true)
- end
-
- context 'when runner has no token expiration' do
- let(:runner) { non_expirable_runner }
-
- it { is_expected.to eq(false) }
- end
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
- context 'when runner token is not expired' do
- let(:runner) { non_expired_runner }
-
- it { is_expected.to eq(false) }
- end
+ it { is_expected.to eq(false) }
+ end
- context 'when runner token is expired' do
- let(:runner) { expired_runner }
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
- it { is_expected.to eq(true) }
- end
+ it { is_expected.to eq(true) }
end
end
@@ -386,52 +356,22 @@ RSpec.describe Ci::Runner, 'TokenAuthenticatable', :freeze_time do
describe '.find_by_token' do
subject { Ci::Runner.find_by_token(runner.token) }
- context 'when enforce_runner_token_expires_at feature flag is disabled' do
- before do
- stub_feature_flags(enforce_runner_token_expires_at: false)
- end
-
- context 'when runner has no token expiration' do
- let(:runner) { non_expirable_runner }
-
- it { is_expected.to eq(non_expirable_runner) }
- end
-
- context 'when runner token is not expired' do
- let(:runner) { non_expired_runner }
-
- it { is_expected.to eq(non_expired_runner) }
- end
-
- context 'when runner token is expired' do
- let(:runner) { expired_runner }
+ context 'when runner has no token expiration' do
+ let(:runner) { non_expirable_runner }
- it { is_expected.to eq(expired_runner) }
- end
+ it { is_expected.to eq(non_expirable_runner) }
end
- context 'when enforce_runner_token_expires_at feature flag is enabled' do
- before do
- stub_feature_flags(enforce_runner_token_expires_at: true)
- end
-
- context 'when runner has no token expiration' do
- let(:runner) { non_expirable_runner }
-
- it { is_expected.to eq(non_expirable_runner) }
- end
-
- context 'when runner token is not expired' do
- let(:runner) { non_expired_runner }
+ context 'when runner token is not expired' do
+ let(:runner) { non_expired_runner }
- it { is_expected.to eq(non_expired_runner) }
- end
+ it { is_expected.to eq(non_expired_runner) }
+ end
- context 'when runner token is expired' do
- let(:runner) { expired_runner }
+ context 'when runner token is expired' do
+ let(:runner) { expired_runner }
- it { is_expected.to be_nil }
- end
+ it { is_expected.to be_nil }
end
end
end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index a4329993e91..0033e9bbd08 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe ContainerRepository, :aggregate_failures do
api_url: 'http://registry.gitlab',
host_port: 'registry.gitlab')
- stub_request(:get, 'http://registry.gitlab/v2/group/test/my_image/tags/list')
+ stub_request(:get, "http://registry.gitlab/v2/group/test/my_image/tags/list?n=#{::ContainerRegistry::Client::DEFAULT_TAGS_PAGE_SIZE}")
.with(headers: { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') })
.to_return(
status: 200,
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 87fa5289795..b91d836f82f 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Deployment do
let(:deployment) { create(:deployment) }
it 'delegates to environment_manual_actions' do
- expect(deployment.deployable).to receive(:environment_manual_actions).and_call_original
+ expect(deployment.deployable).to receive(:other_manual_actions).and_call_original
deployment.manual_actions
end
@@ -38,7 +38,7 @@ RSpec.describe Deployment do
let(:deployment) { create(:deployment) }
it 'delegates to environment_scheduled_actions' do
- expect(deployment.deployable).to receive(:environment_scheduled_actions).and_call_original
+ expect(deployment.deployable).to receive(:other_scheduled_actions).and_call_original
deployment.scheduled_actions
end
@@ -171,11 +171,22 @@ RSpec.describe Deployment do
end
it 'executes Deployments::DropOlderDeploymentsWorker asynchronously' do
+ stub_feature_flags(prevent_outdated_deployment_jobs: false)
+
expect(Deployments::DropOlderDeploymentsWorker)
.to receive(:perform_async).once.with(deployment.id)
deployment.run!
end
+
+ it 'does not execute Deployments::DropOlderDeploymentsWorker when FF enabled' do
+ stub_feature_flags(prevent_outdated_deployment_jobs: true)
+
+ expect(Deployments::DropOlderDeploymentsWorker)
+ .not_to receive(:perform_async).with(deployment.id)
+
+ deployment.run!
+ end
end
context 'when deployment succeeded' do
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index d379ffeee02..a526f91ddc1 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -541,11 +541,12 @@ RSpec.describe DiffNote do
describe '#shas' do
it 'returns list of SHAs based on original_position' do
- expect(subject.shas).to match_array([
- position.base_sha,
- position.start_sha,
- position.head_sha
- ])
+ expect(subject.shas).to match_array(
+ [
+ position.base_sha,
+ position.start_sha,
+ position.head_sha
+ ])
end
context 'when position changes' do
@@ -554,14 +555,15 @@ RSpec.describe DiffNote do
end
it 'includes the new position SHAs' do
- expect(subject.shas).to match_array([
- position.base_sha,
- position.start_sha,
- position.head_sha,
- new_position.base_sha,
- new_position.start_sha,
- new_position.head_sha
- ])
+ expect(subject.shas).to match_array(
+ [
+ position.base_sha,
+ position.start_sha,
+ position.head_sha,
+ new_position.base_sha,
+ new_position.start_sha,
+ new_position.head_sha
+ ])
end
end
end
diff --git a/spec/models/diff_viewer/server_side_spec.rb b/spec/models/diff_viewer/server_side_spec.rb
index 28660b0d4b9..db0814af422 100644
--- a/spec/models/diff_viewer/server_side_spec.rb
+++ b/spec/models/diff_viewer/server_side_spec.rb
@@ -17,10 +17,30 @@ RSpec.describe DiffViewer::ServerSide do
subject { viewer_class.new(diff_file) }
describe '#prepare!' do
- it 'loads all diff file data' do
- expect(Blob).to receive(:lazy).at_least(:twice)
+ before do
+ stub_feature_flags(disable_load_entire_blob_for_diff_viewer: feature_flag_enabled)
+ end
+
+ context 'when the disable_load_entire_blob_for_diff_viewer flag is disabled' do
+ let(:feature_flag_enabled) { false }
- subject.prepare!
+ it 'loads all diff file data' do
+ subject
+ expect(diff_file).to receive_message_chain(:old_blob, :load_all_data!)
+ expect(diff_file).to receive_message_chain(:new_blob, :load_all_data!)
+ subject.prepare!
+ end
+ end
+
+ context 'when the disable_load_entire_blob_for_diff_viewer flag is enabled' do
+ let(:feature_flag_enabled) { true }
+
+ it 'does not load file data' do
+ subject
+ expect(diff_file).not_to receive(:old_blob)
+ expect(diff_file).not_to receive(:new_blob)
+ subject.prepare!
+ end
end
end
diff --git a/spec/models/discussion_spec.rb b/spec/models/discussion_spec.rb
index 212619a1c3d..7bd3c5743a6 100644
--- a/spec/models/discussion_spec.rb
+++ b/spec/models/discussion_spec.rb
@@ -37,10 +37,11 @@ RSpec.describe Discussion do
describe '.build_collection' do
it 'returns an array of discussions of the right type' do
discussions = described_class.build_collection([first_note, second_note, third_note], merge_request)
- expect(discussions).to eq([
- DiffDiscussion.new([first_note, second_note], merge_request),
- DiffDiscussion.new([third_note], merge_request)
- ])
+ expect(discussions).to eq(
+ [
+ DiffDiscussion.new([first_note, second_note], merge_request),
+ DiffDiscussion.new([third_note], merge_request)
+ ])
end
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 1e15b09a069..a442856d993 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -390,7 +390,10 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
'staging' | described_class.tiers[:staging]
'pre-prod' | described_class.tiers[:staging]
'blue-kit-stage' | described_class.tiers[:staging]
- 'pre-prod' | described_class.tiers[:staging]
+ 'nonprod' | described_class.tiers[:staging]
+ 'nonlive' | described_class.tiers[:staging]
+ 'non-prod' | described_class.tiers[:staging]
+ 'non-live' | described_class.tiers[:staging]
'gprd' | described_class.tiers[:production]
'gprd-cny' | described_class.tiers[:production]
'production' | described_class.tiers[:production]
@@ -1291,7 +1294,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
context 'when the environment is available' do
context 'with a deployment service' do
- let(:project) { create(:prometheus_project, :repository) }
+ let(:project) { create(:project, :with_prometheus_integration, :repository) }
context 'and a deployment' do
let!(:deployment) { create(:deployment, environment: environment) }
@@ -1364,7 +1367,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
context 'when the environment is unavailable' do
- let(:project) { create(:prometheus_project) }
+ let(:project) { create(:project, :with_prometheus_integration) }
before do
environment.stop
@@ -1391,7 +1394,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
describe '#metrics' do
- let(:project) { create(:prometheus_project) }
+ let(:project) { create(:project, :with_prometheus_integration) }
subject { environment.metrics }
@@ -1427,7 +1430,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
describe '#additional_metrics' do
- let(:project) { create(:prometheus_project) }
+ let(:project) { create(:project, :with_prometheus_integration) }
let(:metric_params) { [] }
subject { environment.additional_metrics(*metric_params) }
@@ -1617,44 +1620,30 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
nil | nil
'never' | nil
end
- with_them do
- it 'sets correct auto_stop_in' do
- freeze_time do
- if expected_result.is_a?(Integer) || expected_result.nil?
- subject
- expect(environment.auto_stop_in).to eq(expected_result)
- else
- expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
- an_instance_of(expected_result),
- project_id: environment.project_id,
- environment_id: environment.id
- )
+ with_them do
+ shared_examples 'for given values expected result is set' do
+ it do
+ freeze_time do
+ if expected_result.is_a?(Integer) || expected_result.nil?
+ subject
- expect { subject }.to raise_error(expected_result)
+ expect(environment.auto_stop_in).to eq(expected_result)
+ else
+ expect { subject }.to raise_error(expected_result)
+ end
end
end
end
- end
- context 'resets earlier value' do
- let(:environment) { create(:environment, auto_stop_at: 1.day.since.round) }
-
- where(:value, :expected_result) do
- '2 days' | 2.days.to_i
- '1 week' | 1.week.to_i
- '2h20min' | 2.hours.to_i + 20.minutes.to_i
- '' | nil
- 'never' | nil
+ context 'new assignment sets correct auto_stop_in' do
+ include_examples 'for given values expected result is set'
end
- with_them do
- it 'assigns new value' do
- freeze_time do
- subject
- expect(environment.auto_stop_in).to eq(expected_result)
- end
- end
+ context 'resets older value' do
+ let(:environment) { create(:environment, auto_stop_at: 1.day.since.round) }
+
+ include_examples 'for given values expected result is set'
end
end
end
diff --git a/spec/models/factories_spec.rb b/spec/models/factories_spec.rb
index 2993b2aee58..c931c96bafd 100644
--- a/spec/models/factories_spec.rb
+++ b/spec/models/factories_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe 'factories' do
[:issue_customer_relations_contact, :for_contact],
[:issue_customer_relations_contact, :for_issue],
[:package_file, :object_storage],
+ [:rpm_repository_file, :object_storage],
[:pages_domain, :without_certificate],
[:pages_domain, :without_key],
[:pages_domain, :with_missing_chain],
@@ -79,7 +80,6 @@ RSpec.describe 'factories' do
member_task
milestone_release
namespace
- project_broken_repo
project_namespace
project_repository
prometheus_alert
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 2ce75fb1290..68c2d1d3995 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -2293,10 +2293,11 @@ RSpec.describe Group do
it 'clears both self and descendant cache when the parent value is updated' do
expect(Rails.cache).to receive(:delete_multi)
.with(
- match_array([
- start_with("namespaces:{#{parent.traversal_ids.first}}:first_auto_devops_config:#{parent.id}"),
- start_with("namespaces:{#{parent.traversal_ids.first}}:first_auto_devops_config:#{group.id}")
- ])
+ match_array(
+ [
+ start_with("namespaces:{#{parent.traversal_ids.first}}:first_auto_devops_config:#{parent.id}"),
+ start_with("namespaces:{#{parent.traversal_ids.first}}:first_auto_devops_config:#{group.id}")
+ ])
)
parent.update!(auto_devops_enabled: true)
@@ -3312,16 +3313,6 @@ RSpec.describe Group do
expect(group.packages_policy_subject).to be_a(Packages::Policies::Group)
expect(group.packages_policy_subject.group).to eq(group)
end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(read_package_policy_rule: false)
- end
-
- it 'returns group' do
- expect(group.packages_policy_subject).to eq(group)
- end
- end
end
describe '#gitlab_deploy_token' do
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 036d2effc0f..da8c10b67a6 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -139,6 +139,16 @@ RSpec.describe WebHook do
it { is_expected.to contain_exactly(:token, :url, :url_variables) }
end
+ describe '.web_hooks_disable_failed?' do
+ it 'returns true when feature is enabled for parent' do
+ second_hook = build(:project_hook, project: create(:project))
+ stub_feature_flags(web_hooks_disable_failed: [false, second_hook.project])
+
+ expect(described_class.web_hooks_disable_failed?(hook)).to eq(false)
+ expect(described_class.web_hooks_disable_failed?(second_hook)).to eq(true)
+ end
+ end
+
describe 'execute' do
let(:data) { { key: 'value' } }
let(:hook_name) { 'project hook' }
@@ -170,7 +180,7 @@ RSpec.describe WebHook do
end
it 'does not async execute non-executable hooks' do
- hook.update!(disabled_until: 1.day.from_now)
+ allow(hook).to receive(:executable?).and_return(false)
expect(WebHookService).not_to receive(:new)
@@ -238,17 +248,18 @@ RSpec.describe WebHook do
[
[0, :not_set, true],
[0, :past, true],
- [0, :future, false],
- [0, :now, false],
+ [0, :future, true],
+ [0, :now, true],
[1, :not_set, true],
[1, :past, true],
- [1, :future, false],
+ [1, :future, true],
[3, :not_set, true],
[3, :past, true],
- [3, :future, false],
+ [3, :future, true],
[4, :not_set, false],
- [4, :past, false],
- [4, :future, false]
+ [4, :past, true], # expired suspension
+ [4, :now, false], # active suspension
+ [4, :future, false] # active suspension
]
end
@@ -315,7 +326,7 @@ RSpec.describe WebHook do
end
it 'is twice the initial value' do
- expect(hook.next_backoff).to eq(20.minutes)
+ expect(hook.next_backoff).to eq(2 * described_class::INITIAL_BACKOFF)
end
end
@@ -325,7 +336,7 @@ RSpec.describe WebHook do
end
it 'grows exponentially' do
- expect(hook.next_backoff).to eq(80.minutes)
+ expect(hook.next_backoff).to eq(2 * 2 * 2 * described_class::INITIAL_BACKOFF)
end
end
@@ -357,6 +368,7 @@ RSpec.describe WebHook do
end
it 'makes a hook executable if it is currently backed off' do
+ hook.recent_failures = 1000
hook.disabled_until = 1.hour.from_now
expect { hook.enable! }.to change(hook, :executable?).from(false).to(true)
@@ -378,55 +390,71 @@ RSpec.describe WebHook do
end
describe 'backoff!' do
- it 'sets disabled_until to the next backoff' do
- expect { hook.backoff! }.to change(hook, :disabled_until).to(hook.next_backoff.from_now)
- end
+ context 'when we have not backed off before' do
+ it 'does not disable the hook' do
+ expect { hook.backoff! }.not_to change(hook, :executable?).from(true)
+ end
- it 'increments the backoff count' do
- expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
+ it 'increments the recent_failures count' do
+ expect { hook.backoff! }.to change(hook, :recent_failures).by(1)
+ end
end
- context 'when the hook is permanently disabled' do
+ context 'when we have exhausted the grace period' 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)
+ hook.update!(recent_failures: described_class::FAILURE_THRESHOLD)
end
- it 'does not increment the backoff count' do
- expect { hook.backoff! }.not_to change(hook, :backoff_count)
+ it 'sets disabled_until to the next backoff' do
+ expect { hook.backoff! }.to change(hook, :disabled_until).to(hook.next_backoff.from_now)
end
- end
- context 'when we have backed off MAX_FAILURES times' do
- before do
- stub_const("#{described_class}::MAX_FAILURES", 5)
- 5.times { hook.backoff! }
+ it 'increments the backoff count' do
+ expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
end
- it 'does not let the backoff count exceed the maximum failure count' do
- expect { hook.backoff! }.not_to change(hook, :backoff_count)
- end
+ context 'when the hook is permanently disabled' do
+ before do
+ allow(hook).to receive(:permanently_disabled?).and_return(true)
+ end
- it 'does not change disabled_until', :skip_freeze_time do
- travel_to(hook.disabled_until - 1.minute) do
+ 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
- it 'changes disabled_until when it has elapsed', :skip_freeze_time do
- travel_to(hook.disabled_until + 1.minute) do
- expect { hook.backoff! }.to change { hook.disabled_until }
- expect(hook.backoff_count).to eq(described_class::MAX_FAILURES)
+ context 'when we have backed off MAX_FAILURES times' do
+ before do
+ stub_const("#{described_class}::MAX_FAILURES", 5)
+ (described_class::FAILURE_THRESHOLD + 5).times { hook.backoff! }
+ end
+
+ it 'does not let the backoff count exceed the maximum failure count' do
+ expect { hook.backoff! }.not_to change(hook, :backoff_count)
+ end
+
+ it 'does not change disabled_until', :skip_freeze_time do
+ travel_to(hook.disabled_until - 1.minute) do
+ expect { hook.backoff! }.not_to change(hook, :disabled_until)
+ end
+ end
+
+ it 'changes disabled_until when it has elapsed', :skip_freeze_time do
+ travel_to(hook.disabled_until + 1.minute) do
+ expect { hook.backoff! }.to change { hook.disabled_until }
+ expect(hook.backoff_count).to eq(described_class::MAX_FAILURES)
+ end
end
end
- end
- include_examples 'is tolerant of invalid records' do
- def run_expectation
- expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
+ include_examples 'is tolerant of invalid records' do
+ def run_expectation
+ expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
+ end
end
end
end
@@ -468,8 +496,19 @@ RSpec.describe WebHook do
expect(hook).not_to be_temporarily_disabled
end
+ it 'allows FAILURE_THRESHOLD initial failures before we back-off' do
+ described_class::FAILURE_THRESHOLD.times do
+ hook.backoff!
+ expect(hook).not_to be_temporarily_disabled
+ end
+
+ hook.backoff!
+ expect(hook).to be_temporarily_disabled
+ end
+
context 'when hook has been told to back off' do
before do
+ hook.update!(recent_failures: described_class::FAILURE_THRESHOLD)
hook.backoff!
end
@@ -550,6 +589,7 @@ RSpec.describe WebHook do
context 'when hook has been backed off' do
before do
+ hook.update!(recent_failures: described_class::FAILURE_THRESHOLD + 1)
hook.disabled_until = 1.hour.from_now
end
diff --git a/spec/models/incident_management/timeline_event_spec.rb b/spec/models/incident_management/timeline_event_spec.rb
index fea391acda3..d288cc1a75d 100644
--- a/spec/models/incident_management/timeline_event_spec.rb
+++ b/spec/models/incident_management/timeline_event_spec.rb
@@ -13,6 +13,12 @@ RSpec.describe IncidentManagement::TimelineEvent do
it { is_expected.to belong_to(:incident) }
it { is_expected.to belong_to(:updated_by_user) }
it { is_expected.to belong_to(:promoted_from_note) }
+ it { is_expected.to have_many(:timeline_event_tag_links).class_name('IncidentManagement::TimelineEventTagLink') }
+
+ it do
+ is_expected.to have_many(:timeline_event_tags)
+ .class_name('IncidentManagement::TimelineEventTag').through(:timeline_event_tag_links)
+ end
end
describe 'validations' do
@@ -22,7 +28,6 @@ RSpec.describe IncidentManagement::TimelineEvent do
it { is_expected.to validate_presence_of(:incident) }
it { is_expected.to validate_presence_of(:note) }
it { is_expected.to validate_length_of(:note).is_at_most(10_000) }
- it { is_expected.to validate_presence_of(:note_html) }
it { is_expected.to validate_length_of(:note_html).is_at_most(10_000) }
it { is_expected.to validate_presence_of(:occurred_at) }
it { is_expected.to validate_presence_of(:action) }
diff --git a/spec/models/incident_management/timeline_event_tag_link_spec.rb b/spec/models/incident_management/timeline_event_tag_link_spec.rb
new file mode 100644
index 00000000000..fe31a6604c1
--- /dev/null
+++ b/spec/models/incident_management/timeline_event_tag_link_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IncidentManagement::TimelineEventTagLink do
+ describe 'associations' do
+ it { is_expected.to belong_to(:timeline_event) }
+ it { is_expected.to belong_to(:timeline_event_tag) }
+ end
+end
diff --git a/spec/models/incident_management/timeline_event_tag_spec.rb b/spec/models/incident_management/timeline_event_tag_spec.rb
new file mode 100644
index 00000000000..cff8ad8469f
--- /dev/null
+++ b/spec/models/incident_management/timeline_event_tag_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IncidentManagement::TimelineEventTag do
+ describe 'associations' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:timeline_event_tag_links).class_name('IncidentManagement::TimelineEventTagLink') }
+
+ it {
+ is_expected.to have_many(:timeline_events)
+ .class_name('IncidentManagement::TimelineEvent').through(:timeline_event_tag_links)
+ }
+ end
+
+ describe 'validations' do
+ subject { build(:incident_management_timeline_event_tag) }
+
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_length_of(:name).is_at_most(255) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to([:project_id]) }
+
+ it { is_expected.to allow_value('Test tag 1').for(:name) }
+ it { is_expected.not_to allow_value('Test tag, 1').for(:name) }
+ it { is_expected.not_to allow_value('').for(:name) }
+ it { is_expected.not_to allow_value('s' * 256).for(:name) }
+ end
+end
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 950f2c639fb..baa3443b4c5 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -971,11 +971,12 @@ RSpec.describe Integration do
describe '#secret_fields' do
it 'returns all fields with type `password`' do
- allow(subject).to receive(:fields).and_return([
- { name: 'password', type: 'password' },
- { name: 'secret', type: 'password' },
- { name: 'public', type: 'text' }
- ])
+ allow(subject).to receive(:fields).and_return(
+ [
+ { name: 'password', type: 'password' },
+ { name: 'secret', type: 'password' },
+ { name: 'public', type: 'text' }
+ ])
expect(subject.secret_fields).to match_array(%w[password secret])
end
diff --git a/spec/models/integrations/chat_message/issue_message_spec.rb b/spec/models/integrations/chat_message/issue_message_spec.rb
index 4a86322cdaf..ff9f30efdca 100644
--- a/spec/models/integrations/chat_message/issue_message_spec.rb
+++ b/spec/models/integrations/chat_message/issue_message_spec.rb
@@ -47,14 +47,15 @@ RSpec.describe Integrations::ChatMessage::IssueMessage do
it 'returns a message regarding opening of issues' do
expect(subject.pretext).to eq(
'[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> opened by Test User (test.user)')
- expect(subject.attachments).to eq([
- {
- title: "#100 Issue title",
- title_link: "http://url.com",
- text: "issue description",
- color: color
- }
- ])
+ expect(subject.attachments).to eq(
+ [
+ {
+ title: "#100 Issue title",
+ title_link: "http://url.com",
+ text: "issue description",
+ color: color
+ }
+ ])
end
end
diff --git a/spec/models/integrations/chat_message/wiki_page_message_spec.rb b/spec/models/integrations/chat_message/wiki_page_message_spec.rb
index 16659311c52..dae8d293354 100644
--- a/spec/models/integrations/chat_message/wiki_page_message_spec.rb
+++ b/spec/models/integrations/chat_message/wiki_page_message_spec.rb
@@ -71,12 +71,13 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
end
it 'returns the commit message for a new wiki page' do
- expect(subject.attachments).to eq([
- {
- text: commit_message,
- color: color
- }
- ])
+ expect(subject.attachments).to eq(
+ [
+ {
+ text: commit_message,
+ color: color
+ }
+ ])
end
end
@@ -86,12 +87,13 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
end
it 'returns the commit message for an updated wiki page' do
- expect(subject.attachments).to eq([
- {
- text: commit_message,
- color: color
- }
- ])
+ expect(subject.attachments).to eq(
+ [
+ {
+ text: commit_message,
+ color: color
+ }
+ ])
end
end
end
diff --git a/spec/models/integrations/datadog_spec.rb b/spec/models/integrations/datadog_spec.rb
index b7da6a79e44..71a5bbc4db1 100644
--- a/spec/models/integrations/datadog_spec.rb
+++ b/spec/models/integrations/datadog_spec.rb
@@ -47,6 +47,10 @@ RSpec.describe Integrations::Datadog do
Gitlab::DataBuilder::ArchiveTrace.build(build)
end
+ it_behaves_like Integrations::ResetSecretFields do
+ let(:integration) { instance }
+ end
+
it_behaves_like Integrations::HasWebHook do
let(:integration) { instance }
let(:hook_url) { "#{described_class::URL_TEMPLATE % { datadog_domain: dd_site }}?dd-api-key={api_key}&env=#{dd_env}&service=#{dd_service}" }
diff --git a/spec/models/integrations/harbor_spec.rb b/spec/models/integrations/harbor_spec.rb
index 26b43fa3313..9ab37a92e89 100644
--- a/spec/models/integrations/harbor_spec.rb
+++ b/spec/models/integrations/harbor_spec.rb
@@ -7,7 +7,11 @@ RSpec.describe Integrations::Harbor do
let(:project_name) { 'testproject' }
let(:username) { 'harborusername' }
let(:password) { 'harborpassword' }
- let(:harbor_integration) { create(:harbor_integration) }
+ let(:harbor_integration) { build(:harbor_integration) }
+
+ it_behaves_like Integrations::ResetSecretFields do
+ let(:integration) { described_class.new }
+ end
describe "masked password" do
subject { build(:harbor_integration) }
@@ -66,6 +70,8 @@ RSpec.describe Integrations::Harbor do
end
context 'ci variables' do
+ let(:harbor_integration) { create(:harbor_integration) }
+
it 'returns vars when harbor_integration is activated' do
ci_vars = [
{ key: 'HARBOR_URL', value: url },
@@ -94,66 +100,4 @@ RSpec.describe Integrations::Harbor do
end
end
end
-
- describe 'before_validation :reset_username_and_password' do
- context 'when username/password was previously set' do
- it 'resets username and password if url changed' do
- harbor_integration.url = 'https://anotherharbor.com'
- harbor_integration.valid?
-
- expect(harbor_integration.password).to be_nil
- expect(harbor_integration.username).to be_nil
- end
-
- it 'does not reset password if username changed' do
- harbor_integration.username = 'newusername'
- harbor_integration.valid?
-
- expect(harbor_integration.password).to eq('harborpassword')
- end
-
- it 'does not reset username if password changed' do
- harbor_integration.password = 'newpassword'
- harbor_integration.valid?
-
- expect(harbor_integration.username).to eq('harborusername')
- end
-
- it "does not reset password if new url is set together with password, even if it's the same password" do
- harbor_integration.url = 'https://anotherharbor.com'
- harbor_integration.password = 'harborpassword'
- harbor_integration.valid?
-
- expect(harbor_integration.password).to eq('harborpassword')
- expect(harbor_integration.username).to be_nil
- expect(harbor_integration.url).to eq('https://anotherharbor.com')
- end
-
- it "does not reset username if new url is set together with username, even if it's the same username" do
- harbor_integration.url = 'https://anotherharbor.com'
- harbor_integration.username = 'harborusername'
- harbor_integration.valid?
-
- expect(harbor_integration.password).to be_nil
- expect(harbor_integration.username).to eq('harborusername')
- expect(harbor_integration.url).to eq('https://anotherharbor.com')
- end
- end
-
- it 'saves password if new url is set together with password when no password was previously set' do
- harbor_integration.password = nil
- harbor_integration.username = nil
-
- harbor_integration.url = 'https://anotherharbor.com'
- harbor_integration.password = 'newpassword'
- harbor_integration.username = 'newusername'
- harbor_integration.save!
-
- expect(harbor_integration).to have_attributes(
- url: 'https://anotherharbor.com',
- password: 'newpassword',
- username: 'newusername'
- )
- end
- end
end
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
index a52a4514ebe..9f928442b28 100644
--- a/spec/models/integrations/jira_spec.rb
+++ b/spec/models/integrations/jira_spec.rb
@@ -81,9 +81,10 @@ RSpec.describe Integrations::Jira do
jira_integration.jira_issue_transition_id = 'foo bar'
expect(jira_integration).not_to be_valid
- expect(jira_integration.errors.full_messages).to eq([
- 'Jira issue transition IDs must be a list of numbers that can be split with , or ;'
- ])
+ expect(jira_integration.errors.full_messages).to eq(
+ [
+ 'Jira issue transition IDs must be a list of numbers that can be split with , or ;'
+ ])
end
end
end
@@ -213,6 +214,8 @@ RSpec.describe Integrations::Jira do
'EXT_EXT-1234' | 'EXT_EXT-1234'
'EXT3_EXT-1234' | 'EXT3_EXT-1234'
'3EXT_EXT-1234' | ''
+ 'CVE-2022-123' | ''
+ 'CVE-123' | 'CVE-123'
end
with_them do
diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb
index b1b3e42b5e9..b6de2bb7176 100644
--- a/spec/models/integrations/microsoft_teams_spec.rb
+++ b/spec/models/integrations/microsoft_teams_spec.rb
@@ -81,10 +81,14 @@ RSpec.describe Integrations::MicrosoftTeams do
let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
let(:issues_sample_data) do
service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil)
- issue = service.execute
+ issue = service.execute[:issue]
service.hook_data(issue, 'open')
end
+ before do
+ project.add_developer(user)
+ end
+
it "calls Microsoft Teams API" do
chat_integration.execute(issues_sample_data)
diff --git a/spec/models/integrations/prometheus_spec.rb b/spec/models/integrations/prometheus_spec.rb
index ae965ed78d1..3971511872b 100644
--- a/spec/models/integrations/prometheus_spec.rb
+++ b/spec/models/integrations/prometheus_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching,
include PrometheusHelpers
include ReactiveCachingHelpers
- let_it_be_with_reload(:project) { create(:prometheus_project) }
+ let_it_be_with_reload(:project) { create(:project, :with_prometheus_integration) }
let(:integration) { project.prometheus_integration }
@@ -318,7 +318,7 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching,
context 'cluster belongs to projects group' do
let_it_be(:group) { create(:group) }
- let(:project) { create(:prometheus_project, group: group) }
+ let(:project) { create(:project, :with_prometheus_integration, group: group) }
let(:cluster) { create(:cluster_for_group, groups: [group]) }
it 'returns true' do
diff --git a/spec/models/jira_connect/public_key_spec.rb b/spec/models/jira_connect/public_key_spec.rb
new file mode 100644
index 00000000000..2e79a3ca4d2
--- /dev/null
+++ b/spec/models/jira_connect/public_key_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::PublicKey do
+ describe '.create!' do
+ let(:key) { 'key123' }
+
+ subject(:create_public_key) { described_class.create!(key: key) }
+
+ it 'only accepts valid public keys' do
+ expect { create_public_key }.to raise_error(ArgumentError, 'Invalid public key')
+ end
+
+ shared_examples 'creates a jira connect public key' do
+ it 'generates a Uuid' do
+ expect(create_public_key.uuid).to match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
+ end
+
+ it 'sets the key attribute' do
+ expect(create_public_key.key).to eq(expected_key)
+ end
+
+ it 'persists the values' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:set).with(anything, expected_key, anything)
+ end
+
+ create_public_key
+ end
+ end
+
+ context 'with OpenSSL::PKey::RSA object' do
+ let(:key) { OpenSSL::PKey::RSA.generate(3072).public_key }
+ let(:expected_key) { key.to_s }
+
+ it_behaves_like 'creates a jira connect public key'
+ end
+
+ context 'with string public key' do
+ let(:key) { OpenSSL::PKey::RSA.generate(3072).public_key.to_s }
+ let(:expected_key) { key }
+
+ it_behaves_like 'creates a jira connect public key'
+ end
+ end
+
+ describe '.find' do
+ let(:uuid) { '1234' }
+
+ subject(:find_public_key) { described_class.find(uuid) }
+
+ it 'raises an error' do
+ expect { find_public_key }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ context 'when the public key exists' do
+ let_it_be(:key) { OpenSSL::PKey::RSA.generate(3072).public_key }
+ let_it_be(:public_key) { described_class.create!(key: key) }
+
+ let(:uuid) { public_key.uuid }
+
+ it 'loads the public key', :aggregate_failures do
+ expect(find_public_key).to be_kind_of(described_class)
+ expect(find_public_key.uuid).to eq(public_key.uuid)
+ expect(find_public_key.key).to eq(key.to_s)
+ end
+ end
+ end
+
+ describe '#save!' do
+ let(:key) { OpenSSL::PKey::RSA.generate(3072).public_key }
+ let(:public_key) { described_class.new(key: key, uuid: '123') }
+ let(:jira_connect_installation) { build(:jira_connect_installation) }
+
+ subject(:save_public_key) { public_key.save! }
+
+ it 'persists the values' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:set).with(anything, key.to_s, ex: 5.minutes.to_i)
+ end
+
+ save_public_key
+ end
+
+ it 'returns itself' do
+ expect(save_public_key).to eq(public_key)
+ end
+ end
+end
diff --git a/spec/models/jira_connect_installation_spec.rb b/spec/models/jira_connect_installation_spec.rb
index 9c1f7c678a9..e57d3e78a4e 100644
--- a/spec/models/jira_connect_installation_spec.rb
+++ b/spec/models/jira_connect_installation_spec.rb
@@ -20,29 +20,53 @@ RSpec.describe JiraConnectInstallation do
it { is_expected.not_to allow_value('not/a/url').for(:instance_url) }
end
- describe '.for_project' do
- let(:other_group) { create(:group) }
- let(:parent_group) { create(:group) }
- let(:group) { create(:group, parent: parent_group) }
- let(:project) { create(:project, group: group) }
+ describe 'scopes' do
+ let_it_be(:jira_connect_subscription) { create(:jira_connect_subscription) }
- subject { described_class.for_project(project) }
+ describe '.for_project' do
+ let_it_be(:other_group) { create(:group) }
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
+ let_it_be(:project) { create(:project, group: group) }
- it 'returns installations with subscriptions for project' do
- sub_on_project_namespace = create(:jira_connect_subscription, namespace: group)
- sub_on_ancestor_namespace = create(:jira_connect_subscription, namespace: parent_group)
+ subject { described_class.for_project(project) }
- # Subscription on other group that shouldn't be returned
- create(:jira_connect_subscription, namespace: other_group)
+ it 'returns installations with subscriptions for project' do
+ sub_on_project_namespace = create(:jira_connect_subscription, namespace: group)
+ sub_on_ancestor_namespace = create(:jira_connect_subscription, namespace: parent_group)
- expect(subject).to contain_exactly(sub_on_project_namespace.installation, sub_on_ancestor_namespace.installation)
+ # Subscription on other group that shouldn't be returned
+ create(:jira_connect_subscription, namespace: other_group)
+
+ expect(subject).to contain_exactly(
+ sub_on_project_namespace.installation, sub_on_ancestor_namespace.installation
+ )
+ end
+
+ it 'returns distinct installations' do
+ subscription = create(:jira_connect_subscription, namespace: group)
+ create(:jira_connect_subscription, namespace: parent_group, installation: subscription.installation)
+
+ expect(subject).to contain_exactly(subscription.installation)
+ end
end
- it 'returns distinct installations' do
- subscription = create(:jira_connect_subscription, namespace: group)
- create(:jira_connect_subscription, namespace: parent_group, installation: subscription.installation)
+ describe '.direct_installations' do
+ subject { described_class.direct_installations }
+
+ it { is_expected.to contain_exactly(jira_connect_subscription.installation) }
+ end
+
+ describe '.proxy_installations' do
+ subject { described_class.proxy_installations }
+
+ it { is_expected.to be_empty }
- expect(subject).to contain_exactly(subscription.installation)
+ context 'with an installation on a self-managed instance' do
+ let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'http://self-managed-gitlab.com') }
+
+ it { is_expected.to contain_exactly(installation) }
+ end
end
end
@@ -71,4 +95,46 @@ RSpec.describe JiraConnectInstallation do
end
end
end
+
+ describe 'audience_url' do
+ let_it_be(:installation) { create(:jira_connect_installation) }
+
+ subject(:audience) { installation.audience_url }
+
+ it { is_expected.to eq(nil) }
+
+ context 'when proxy installation' do
+ let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') }
+
+ it { is_expected.to eq('https://example.com/-/jira_connect') }
+ end
+ end
+
+ describe 'audience_installed_event_url' do
+ let_it_be(:installation) { create(:jira_connect_installation) }
+
+ subject(:audience) { installation.audience_installed_event_url }
+
+ it { is_expected.to eq(nil) }
+
+ context 'when proxy installation' do
+ let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') }
+
+ it { is_expected.to eq('https://example.com/-/jira_connect/events/installed') }
+ end
+ end
+
+ describe 'proxy?' do
+ let_it_be(:installation) { create(:jira_connect_installation) }
+
+ subject { installation.proxy? }
+
+ it { is_expected.to eq(false) }
+
+ context 'when instance_url is present' do
+ let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') }
+
+ it { is_expected.to eq(true) }
+ end
+ end
end
diff --git a/spec/models/label_note_spec.rb b/spec/models/label_note_spec.rb
index 145ddd44834..6658d42f25e 100644
--- a/spec/models/label_note_spec.rb
+++ b/spec/models/label_note_spec.rb
@@ -18,9 +18,10 @@ RSpec.describe LabelNote do
it_behaves_like 'label note created from events'
it 'includes a link to the list of issues filtered by the label' do
- note = described_class.from_events([
- create(:resource_label_event, label: label, issue: resource)
- ])
+ note = described_class.from_events(
+ [
+ create(:resource_label_event, label: label, issue: resource)
+ ])
expect(note.note_html).to include(project_issues_path(project, label_name: label.title))
end
@@ -32,9 +33,10 @@ RSpec.describe LabelNote do
it_behaves_like 'label note created from events'
it 'includes a link to the list of merge requests filtered by the label' do
- note = described_class.from_events([
- create(:resource_label_event, label: label, merge_request: resource)
- ])
+ note = described_class.from_events(
+ [
+ create(:resource_label_event, label: label, merge_request: resource)
+ ])
expect(note.note_html).to include(project_merge_requests_path(project, label_name: label.title))
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 7b75a6ee1c2..04df8ecc882 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -178,8 +178,8 @@ RSpec.describe Member do
end
context 'member role is associated' do
- let_it_be(:member_role) do
- create(:member_role, members: [member])
+ let!(:member_role) do
+ create(:member_role, members: [member], base_access_level: Gitlab::Access::DEVELOPER)
end
context 'member role matches access level' do
@@ -201,7 +201,9 @@ RSpec.describe Member do
member.access_level = Gitlab::Access::MAINTAINER
expect(member).not_to be_valid
- expect(member.errors.full_messages).to include( "Access level cannot be changed since member is associated with a custom role")
+ expect(member.errors.full_messages).to include(
+ "Access level cannot be changed since member is associated with a custom role"
+ )
end
end
end
@@ -824,22 +826,6 @@ RSpec.describe Member do
expect(user.authorized_projects.reload).to include(project)
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(allow_non_blocking_member_refresh: false)
- end
-
- it 'successfully completes a blocking refresh', :delete, :sidekiq_inline do
- member.blocking_refresh = false
-
- expect(member).to receive(:refresh_member_authorized_projects).with(blocking: true).and_call_original
-
- member.accept_invite!(user)
-
- expect(user.authorized_projects.reload).to include(project)
- end
- end
end
it 'does not accept the invite if saving a new user fails' do
diff --git a/spec/models/members/member_role_spec.rb b/spec/models/members/member_role_spec.rb
index e8993491918..e2691e2e78c 100644
--- a/spec/models/members/member_role_spec.rb
+++ b/spec/models/members/member_role_spec.rb
@@ -11,7 +11,39 @@ RSpec.describe MemberRole do
describe 'validation' do
subject { described_class.new }
- it { is_expected.to validate_presence_of(:namespace_id) }
+ it { is_expected.to validate_presence_of(:namespace) }
it { is_expected.to validate_presence_of(:base_access_level) }
+
+ context 'for namespace' do
+ subject { build(:member_role) }
+
+ let_it_be(:root_group) { create(:group) }
+
+ context 'when namespace is a subgroup' do
+ it 'is invalid' do
+ subgroup = create(:group, parent: root_group)
+ subject.namespace = subgroup
+
+ expect(subject).to be_invalid
+ end
+ end
+
+ context 'when namespace is a root group' do
+ it 'is valid' do
+ subject.namespace = root_group
+
+ expect(subject).to be_valid
+ end
+ end
+
+ context 'when namespace is not present' do
+ it 'is invalid with a different error message' do
+ subject.namespace = nil
+
+ expect(subject).to be_invalid
+ expect(subject.errors.full_messages).to eq(["Namespace can't be blank"])
+ end
+ end
+ end
end
end
diff --git a/spec/models/merge_request/cleanup_schedule_spec.rb b/spec/models/merge_request/cleanup_schedule_spec.rb
index 9c50b64f2bd..1f1f33db5ed 100644
--- a/spec/models/merge_request/cleanup_schedule_spec.rb
+++ b/spec/models/merge_request/cleanup_schedule_spec.rb
@@ -111,12 +111,13 @@ RSpec.describe MergeRequest::CleanupSchedule do
let!(:cleanup_schedule_7) { create(:merge_request_cleanup_schedule, :failed, scheduled_at: 5.days.ago) }
it 'returns records that are scheduled before or on current time and unstarted (ordered by scheduled first)' do
- expect(described_class.scheduled_and_unstarted).to eq([
- cleanup_schedule_2,
- cleanup_schedule_1,
- cleanup_schedule_5,
- cleanup_schedule_4
- ])
+ expect(described_class.scheduled_and_unstarted).to eq(
+ [
+ cleanup_schedule_2,
+ cleanup_schedule_1,
+ cleanup_schedule_5,
+ cleanup_schedule_4
+ ])
end
end
diff --git a/spec/models/merge_request_diff_file_spec.rb b/spec/models/merge_request_diff_file_spec.rb
index 7dc550a6c93..f107a56c1b6 100644
--- a/spec/models/merge_request_diff_file_spec.rb
+++ b/spec/models/merge_request_diff_file_spec.rb
@@ -220,5 +220,25 @@ RSpec.describe MergeRequestDiffFile do
file.utf8_diff
end
end
+
+ context 'when exception is raised' do
+ it 'logs exception and returns an empty string' do
+ allow(file).to receive(:diff).and_raise(StandardError, 'Error!')
+
+ expect(Gitlab::AppLogger)
+ .to receive(:warn)
+ .with(
+ a_hash_including(
+ :message => 'Failed fetching merge request diff',
+ :merge_request_diff_file_id => file.id,
+ :merge_request_diff_id => file.merge_request_diff.id,
+ 'exception.class' => 'StandardError',
+ 'exception.message' => 'Error!'
+ )
+ )
+
+ expect(file.utf8_diff).to eq('')
+ end
+ end
end
end
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 007e84164a8..e9e8bd9bfea 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -466,19 +466,20 @@ RSpec.describe MergeRequestDiff do
diff_with_commits.update!(sorted: false) # Mark as unsorted so it'll re-order
# There will be 11 returned, as we have to take into account for new and old paths
- expect(diff_with_commits.diffs_in_batch(0, 10, diff_options: diff_options).diff_paths).to eq([
- 'bar/branch-test.txt',
- 'custom-highlighting/test.gitlab-custom',
- 'encoding/iso8859.txt',
- 'files/images/wm.svg',
- 'files/js/commit.js.coffee',
- 'files/js/commit.coffee',
- 'files/lfs/lfs_object.iso',
- 'files/ruby/popen.rb',
- 'files/ruby/regex.rb',
- 'files/.DS_Store',
- 'files/whitespace'
- ])
+ expect(diff_with_commits.diffs_in_batch(0, 10, diff_options: diff_options).diff_paths).to eq(
+ [
+ 'bar/branch-test.txt',
+ 'custom-highlighting/test.gitlab-custom',
+ 'encoding/iso8859.txt',
+ 'files/images/wm.svg',
+ 'files/js/commit.js.coffee',
+ 'files/js/commit.coffee',
+ 'files/lfs/lfs_object.iso',
+ 'files/ruby/popen.rb',
+ 'files/ruby/regex.rb',
+ 'files/.DS_Store',
+ 'files/whitespace'
+ ])
end
context 'when diff_options include ignore_whitespace_change' do
@@ -555,29 +556,30 @@ RSpec.describe MergeRequestDiff do
it 'sorts diff files directory first' do
diff_with_commits.update!(sorted: false) # Mark as unsorted so it'll re-order
- expect(diff_with_commits.diffs(diff_options).diff_paths).to eq([
- 'bar/branch-test.txt',
- 'custom-highlighting/test.gitlab-custom',
- 'encoding/iso8859.txt',
- 'files/images/wm.svg',
- 'files/js/commit.js.coffee',
- 'files/js/commit.coffee',
- 'files/lfs/lfs_object.iso',
- 'files/ruby/popen.rb',
- 'files/ruby/regex.rb',
- 'files/.DS_Store',
- 'files/whitespace',
- 'foo/bar/.gitkeep',
- 'with space/README.md',
- '.DS_Store',
- '.gitattributes',
- '.gitignore',
- '.gitmodules',
- 'CHANGELOG',
- 'README',
- 'gitlab-grack',
- 'gitlab-shell'
- ])
+ expect(diff_with_commits.diffs(diff_options).diff_paths).to eq(
+ [
+ 'bar/branch-test.txt',
+ 'custom-highlighting/test.gitlab-custom',
+ 'encoding/iso8859.txt',
+ 'files/images/wm.svg',
+ 'files/js/commit.js.coffee',
+ 'files/js/commit.coffee',
+ 'files/lfs/lfs_object.iso',
+ 'files/ruby/popen.rb',
+ 'files/ruby/regex.rb',
+ 'files/.DS_Store',
+ 'files/whitespace',
+ 'foo/bar/.gitkeep',
+ 'with space/README.md',
+ '.DS_Store',
+ '.gitattributes',
+ '.gitignore',
+ '.gitmodules',
+ 'CHANGELOG',
+ 'README',
+ 'gitlab-grack',
+ 'gitlab-shell'
+ ])
end
end
end
@@ -661,28 +663,29 @@ RSpec.describe MergeRequestDiff do
mr_diff = create(:merge_request).merge_request_diff
diff_files_paths = mr_diff.merge_request_diff_files.map { |file| file.new_path.presence || file.old_path }
- expect(diff_files_paths).to eq([
- 'bar/branch-test.txt',
- 'custom-highlighting/test.gitlab-custom',
- 'encoding/iso8859.txt',
- 'files/images/wm.svg',
- 'files/js/commit.coffee',
- 'files/lfs/lfs_object.iso',
- 'files/ruby/popen.rb',
- 'files/ruby/regex.rb',
- 'files/.DS_Store',
- 'files/whitespace',
- 'foo/bar/.gitkeep',
- 'with space/README.md',
- '.DS_Store',
- '.gitattributes',
- '.gitignore',
- '.gitmodules',
- 'CHANGELOG',
- 'README',
- 'gitlab-grack',
- 'gitlab-shell'
- ])
+ expect(diff_files_paths).to eq(
+ [
+ 'bar/branch-test.txt',
+ 'custom-highlighting/test.gitlab-custom',
+ 'encoding/iso8859.txt',
+ 'files/images/wm.svg',
+ 'files/js/commit.coffee',
+ 'files/lfs/lfs_object.iso',
+ 'files/ruby/popen.rb',
+ 'files/ruby/regex.rb',
+ 'files/.DS_Store',
+ 'files/whitespace',
+ 'foo/bar/.gitkeep',
+ 'with space/README.md',
+ '.DS_Store',
+ '.gitattributes',
+ '.gitignore',
+ '.gitmodules',
+ 'CHANGELOG',
+ 'README',
+ 'gitlab-grack',
+ 'gitlab-shell'
+ ])
end
it 'expands collapsed diffs before saving' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index f27f3b749b1..32518b867cb 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1837,9 +1837,8 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'persisted merge request' do
context 'with a limit' do
it 'returns a limited number of commit shas' do
- expect(subject.commit_shas(limit: 2)).to eq(%w[
- b83d6e391c22777fca1ed3012fce84f633d7fed0 498214de67004b1da3d820901307bed2a68a8ef6
- ])
+ expect(subject.commit_shas(limit: 2)).to eq(
+ %w[b83d6e391c22777fca1ed3012fce84f633d7fed0 498214de67004b1da3d820901307bed2a68a8ef6])
end
end
@@ -4200,6 +4199,45 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'state machine transitions' do
let(:project) { create(:project, :repository) }
+ shared_examples_for 'transition not triggering mergeRequestMergeStatusUpdated GraphQL subscription' do
+ specify do
+ expect(GraphqlTriggers).not_to receive(:merge_request_merge_status_updated)
+
+ transition!
+ end
+ end
+
+ shared_examples_for 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription' do
+ specify do
+ expect(GraphqlTriggers).to receive(:merge_request_merge_status_updated).with(subject).and_call_original
+
+ transition!
+ end
+
+ context 'when trigger_mr_subscription_on_merge_status_change is disabled' do
+ before do
+ stub_feature_flags(trigger_mr_subscription_on_merge_status_change: false)
+ end
+
+ it_behaves_like 'transition not triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+ end
+
+ shared_examples 'for an invalid state transition' do
+ specify 'is not a valid state transition' do
+ expect { transition! }.to raise_error(StateMachines::InvalidTransition)
+ end
+ end
+
+ shared_examples 'for a valid state transition' do
+ it 'is a valid state transition' do
+ expect { transition! }
+ .to change { subject.merge_status }
+ .from(merge_status.to_s)
+ .to(expected_merge_status)
+ end
+ end
+
describe '#unlock_mr' do
subject { create(:merge_request, state: 'locked', source_project: project, merge_jid: 123) }
@@ -4214,22 +4252,58 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- describe '#mark_as_unchecked' do
+ describe '#mark_as_preparing' do
subject { create(:merge_request, source_project: project, merge_status: merge_status) }
- shared_examples 'for an invalid state transition' do
- it 'is not a valid state transition' do
- expect { subject.mark_as_unchecked! }.to raise_error(StateMachines::InvalidTransition)
- end
+ let(:expected_merge_status) { 'preparing' }
+
+ def transition!
+ subject.mark_as_preparing!
end
- shared_examples 'for an valid state transition' do
- it 'is a valid state transition' do
- expect { subject.mark_as_unchecked! }
- .to change { subject.merge_status }
- .from(merge_status.to_s)
- .to(expected_merge_status)
- end
+ context 'when the status is unchecked' do
+ let(:merge_status) { :unchecked }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition not triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is checking' do
+ let(:merge_status) { :checking }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is can_be_merged' do
+ let(:merge_status) { :can_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_recheck' do
+ let(:merge_status) { :cannot_be_merged_recheck }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged' do
+ let(:merge_status) { :cannot_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_rechecking' do
+ let(:merge_status) { :cannot_be_merged_rechecking }
+
+ include_examples 'for an invalid state transition'
+ end
+ end
+
+ describe '#mark_as_unchecked' do
+ subject { create(:merge_request, source_project: project, merge_status: merge_status) }
+
+ def transition!
+ subject.mark_as_unchecked!
end
context 'when the status is unchecked' do
@@ -4242,14 +4316,16 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:merge_status) { :checking }
let(:expected_merge_status) { 'unchecked' }
- include_examples 'for an valid state transition'
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
end
context 'when the status is can_be_merged' do
let(:merge_status) { :can_be_merged }
let(:expected_merge_status) { 'unchecked' }
- include_examples 'for an valid state transition'
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
end
context 'when the status is cannot_be_merged_recheck' do
@@ -4262,14 +4338,164 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:merge_status) { :cannot_be_merged }
let(:expected_merge_status) { 'cannot_be_merged_recheck' }
- include_examples 'for an valid state transition'
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is cannot_be_merged_rechecking' do
+ let(:merge_status) { :cannot_be_merged_rechecking }
+ let(:expected_merge_status) { 'cannot_be_merged_recheck' }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+ end
+
+ describe '#mark_as_checking' do
+ subject { create(:merge_request, source_project: project, merge_status: merge_status) }
+
+ def transition!
+ subject.mark_as_checking!
+ end
+
+ context 'when the status is unchecked' do
+ let(:merge_status) { :unchecked }
+ let(:expected_merge_status) { 'checking' }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is checking' do
+ let(:merge_status) { :checking }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is can_be_merged' do
+ let(:merge_status) { :can_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_recheck' do
+ let(:merge_status) { :cannot_be_merged_recheck }
+ let(:expected_merge_status) { 'cannot_be_merged_rechecking' }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
end
context 'when the status is cannot_be_merged' do
let(:merge_status) { :cannot_be_merged }
- let(:expected_merge_status) { 'cannot_be_merged_recheck' }
- include_examples 'for an valid state transition'
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_rechecking' do
+ let(:merge_status) { :cannot_be_merged_rechecking }
+
+ include_examples 'for an invalid state transition'
+ end
+ end
+
+ describe '#mark_as_mergeable' do
+ subject { create(:merge_request, source_project: project, merge_status: merge_status) }
+
+ let(:expected_merge_status) { 'can_be_merged' }
+
+ def transition!
+ subject.mark_as_mergeable!
+ end
+
+ context 'when the status is unchecked' do
+ let(:merge_status) { :unchecked }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is checking' do
+ let(:merge_status) { :checking }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is can_be_merged' do
+ let(:merge_status) { :can_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_recheck' do
+ let(:merge_status) { :cannot_be_merged_recheck }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is cannot_be_merged' do
+ let(:merge_status) { :cannot_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_rechecking' do
+ let(:merge_status) { :cannot_be_merged_rechecking }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+ end
+
+ describe '#mark_as_unmergeable' do
+ subject { create(:merge_request, source_project: project, merge_status: merge_status) }
+
+ let(:expected_merge_status) { 'cannot_be_merged' }
+
+ def transition!
+ subject.mark_as_unmergeable!
+ end
+
+ context 'when the status is unchecked' do
+ let(:merge_status) { :unchecked }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is checking' do
+ let(:merge_status) { :checking }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is can_be_merged' do
+ let(:merge_status) { :can_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_recheck' do
+ let(:merge_status) { :cannot_be_merged_recheck }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
+ end
+
+ context 'when the status is cannot_be_merged' do
+ let(:merge_status) { :cannot_be_merged }
+
+ include_examples 'for an invalid state transition'
+ end
+
+ context 'when the status is cannot_be_merged_rechecking' do
+ let(:merge_status) { :cannot_be_merged_rechecking }
+
+ include_examples 'for a valid state transition'
+ it_behaves_like 'transition triggering mergeRequestMergeStatusUpdated GraphQL subscription'
end
end
@@ -4739,15 +4965,17 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'persisted merge request' do
context 'with a limit' do
it 'returns a limited number of commits' do
- expect(subject.commits(limit: 2).map(&:sha)).to eq(%w[
- b83d6e391c22777fca1ed3012fce84f633d7fed0
- 498214de67004b1da3d820901307bed2a68a8ef6
- ])
- expect(subject.commits(limit: 3).map(&:sha)).to eq(%w[
- b83d6e391c22777fca1ed3012fce84f633d7fed0
- 498214de67004b1da3d820901307bed2a68a8ef6
- 1b12f15a11fc6e62177bef08f47bc7b5ce50b141
- ])
+ expect(subject.commits(limit: 2).map(&:sha)).to eq(
+ %w[
+ b83d6e391c22777fca1ed3012fce84f633d7fed0
+ 498214de67004b1da3d820901307bed2a68a8ef6
+ ])
+ expect(subject.commits(limit: 3).map(&:sha)).to eq(
+ %w[
+ b83d6e391c22777fca1ed3012fce84f633d7fed0
+ 498214de67004b1da3d820901307bed2a68a8ef6
+ 1b12f15a11fc6e62177bef08f47bc7b5ce50b141
+ ])
end
end
@@ -4792,9 +5020,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it 'returns the safe number of commits' do
- expect(subject.recent_commits.map(&:sha)).to eq(%w[
- b83d6e391c22777fca1ed3012fce84f633d7fed0 498214de67004b1da3d820901307bed2a68a8ef6
- ])
+ expect(subject.recent_commits.map(&:sha)).to eq(
+ %w[
+ b83d6e391c22777fca1ed3012fce84f633d7fed0 498214de67004b1da3d820901307bed2a68a8ef6
+ ])
end
end
@@ -5171,4 +5400,22 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
end
+
+ describe '#can_suggest_reviewers?' do
+ let_it_be(:merge_request) { build(:merge_request, :opened, project: project) }
+
+ subject(:can_suggest_reviewers) { merge_request.can_suggest_reviewers? }
+
+ it 'returns false' do
+ expect(can_suggest_reviewers).to be(false)
+ end
+ end
+
+ describe '#suggested_reviewer_users' do
+ let_it_be(:merge_request) { build(:merge_request, project: project) }
+
+ subject(:suggested_reviewer_users) { merge_request.suggested_reviewer_users }
+
+ it { is_expected.to be_empty }
+ end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index af1383b68bf..9f6b1f8016b 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -5,9 +5,35 @@ require 'spec_helper'
RSpec.describe Milestone do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
+ let_it_be(:group) { create(:group) }
let_it_be(:issue) { create(:issue, project: project) }
+ describe 'modules' do
+ context 'with a project' do
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:milestone, project: create(:project), group: nil) }
+ let(:scope) { :project }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :milestones }
+ end
+ end
+
+ context 'with a group' do
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:milestone, project: nil, group: create(:group)) }
+ let(:scope) { :group }
+ let(:scope_attrs) { { namespace: instance.group } }
+ let(:usage) { :milestones }
+ end
+ end
+ end
+
it_behaves_like 'a timebox', :milestone do
+ let(:project) { create(:project, :public) }
+ let(:timebox) { create(:milestone, project: project) }
+
describe "#uniqueness_of_title" do
context "per project" do
it "does not accept the same title in a project twice" do
@@ -25,7 +51,7 @@ RSpec.describe Milestone do
end
context "per group" do
- let(:timebox) { create(:milestone, *timebox_args, group: group) }
+ let(:timebox) { create(:milestone, group: group) }
before do
project.update!(group: group)
@@ -96,9 +122,22 @@ RSpec.describe Milestone do
end
end
end
+
+ describe '#parent_type_check' do
+ let(:milestone) { build(:milestone, group: group) }
+
+ it 'is invalid if it has both project_id and group_id' do
+ milestone.project = project
+
+ expect(milestone).not_to be_valid
+ expect(milestone.errors[:project_id]).to include("milestone should belong either to a project or a group.")
+ end
+ end
end
describe "Associations" do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:group) }
it { is_expected.to have_many(:releases) }
it { is_expected.to have_many(:milestone_releases) }
end
@@ -562,6 +601,57 @@ RSpec.describe Milestone do
it { is_expected.not_to match("gitlab-org/gitlab-ce/milestones/123") }
end
+ describe '#merge_requests_enabled?' do
+ context "per project" do
+ it "is true for projects with MRs enabled" do
+ project = create(:project, :merge_requests_enabled)
+ milestone = build(:milestone, project: project)
+
+ expect(milestone.merge_requests_enabled?).to be_truthy
+ end
+
+ it "is false for projects with MRs disabled" do
+ project = create(:project, :repository_enabled, :merge_requests_disabled)
+ milestone = build(:milestone, project: project)
+
+ expect(milestone.merge_requests_enabled?).to be_falsey
+ end
+
+ it "is false for projects with repository disabled" do
+ project = create(:project, :repository_disabled)
+ milestone = build(:milestone, project: project)
+
+ expect(milestone.merge_requests_enabled?).to be_falsey
+ end
+ end
+
+ context "per group" do
+ let(:milestone) { build(:milestone, group: group) }
+
+ it "is always true for groups, for performance reasons" do
+ expect(milestone.merge_requests_enabled?).to be_truthy
+ end
+ end
+ end
+
+ describe '#resource_parent' do
+ context 'when group is present' do
+ let(:milestone) { build(:milestone, group: group) }
+
+ it 'returns the group' do
+ expect(milestone.resource_parent).to eq(group)
+ end
+ end
+
+ context 'when project is present' do
+ let(:milestone) { build(:milestone, project: project) }
+
+ it 'returns the project' do
+ expect(milestone.resource_parent).to eq(project)
+ end
+ end
+ end
+
describe '#parent' do
context 'with group' do
it 'returns the expected parent' do
@@ -598,4 +688,40 @@ RSpec.describe Milestone do
end
end
end
+
+ describe '#project_milestone?' do
+ context 'when project_id is present' do
+ let(:milestone) { build(:milestone, project: project) }
+
+ it 'returns true' do
+ expect(milestone.project_milestone?).to be_truthy
+ end
+ end
+
+ context 'when project_id is not present' do
+ let(:milestone) { build(:milestone, group: group) }
+
+ it 'returns false' do
+ expect(milestone.project_milestone?).to be_falsey
+ end
+ end
+ end
+
+ describe '#group_milestone?' do
+ context 'when group_id is present' do
+ let(:milestone) { build(:milestone, group: group) }
+
+ it 'returns true' do
+ expect(milestone.group_milestone?).to be_truthy
+ end
+ end
+
+ context 'when group_id is not present' do
+ let(:milestone) { build(:milestone, project: project) }
+
+ it 'returns false' do
+ expect(milestone.group_milestone?).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/ml/candidate_spec.rb b/spec/models/ml/candidate_spec.rb
index f58d30f81a0..3bf1e80a152 100644
--- a/spec/models/ml/candidate_spec.rb
+++ b/spec/models/ml/candidate_spec.rb
@@ -2,7 +2,9 @@
require 'spec_helper'
-RSpec.describe Ml::Candidate do
+RSpec.describe Ml::Candidate, factory_default: :keep do
+ let_it_be(:candidate) { create_default(:ml_candidates, :with_metrics_and_params) }
+
describe 'associations' do
it { is_expected.to belong_to(:experiment) }
it { is_expected.to belong_to(:user) }
@@ -12,13 +14,11 @@ RSpec.describe Ml::Candidate do
describe '#new' do
it 'iid is not null' do
- expect(create(:ml_candidates).iid).not_to be_nil
+ expect(candidate.iid).not_to be_nil
end
end
- describe 'by_project_id_and_iid' do
- let_it_be(:candidate) { create(:ml_candidates) }
-
+ describe '#by_project_id_and_iid' do
let(:project_id) { candidate.experiment.project_id }
let(:iid) { candidate.iid }
diff --git a/spec/models/ml/experiment_spec.rb b/spec/models/ml/experiment_spec.rb
index e300f82d290..789bb3aa88a 100644
--- a/spec/models/ml/experiment_spec.rb
+++ b/spec/models/ml/experiment_spec.rb
@@ -3,16 +3,19 @@
require 'spec_helper'
RSpec.describe Ml::Experiment do
+ let_it_be(:exp) { create(:ml_experiments) }
+ let_it_be(:exp2) { create(:ml_experiments, project: exp.project) }
+
+ let(:iid) { exp.iid }
+ let(:exp_name) { exp.name }
+
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:user) }
it { is_expected.to have_many(:candidates) }
end
- describe '#by_project_id_and_iid?' do
- let(:exp) { create(:ml_experiments) }
- let(:iid) { exp.iid }
-
+ describe '#by_project_id_and_iid' do
subject { described_class.by_project_id_and_iid(exp.project_id, iid) }
context 'if exists' do
@@ -26,10 +29,7 @@ RSpec.describe Ml::Experiment do
end
end
- describe '#by_project_id_and_name?' do
- let(:exp) { create(:ml_experiments) }
- let(:exp_name) { exp.name }
-
+ describe '#by_project_id_and_name' do
subject { described_class.by_project_id_and_name(exp.project_id, exp_name) }
context 'if exists' do
@@ -43,20 +43,17 @@ RSpec.describe Ml::Experiment do
end
end
- describe '#has_record?' do
- let(:exp) { create(:ml_experiments) }
- let(:exp_name) { exp.name }
+ describe '#by_project_id' do
+ let(:project_id) { exp.project_id }
- subject { described_class.has_record?(exp.project_id, exp_name) }
+ subject { described_class.by_project_id(project_id) }
- context 'if exists' do
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to match_array([exp, exp2]) }
- context 'if does not exist' do
- let(:exp_name) { 'hello' }
+ context 'when project does not have experiment' do
+ let(:project_id) { non_existing_record_iid }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_empty }
end
end
end
diff --git a/spec/models/namespace/aggregation_schedule_spec.rb b/spec/models/namespace/aggregation_schedule_spec.rb
index 38bf8089411..45b66fa12dd 100644
--- a/spec/models/namespace/aggregation_schedule_spec.rb
+++ b/spec/models/namespace/aggregation_schedule_spec.rb
@@ -5,8 +5,24 @@ require 'spec_helper'
RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, type: :model do
include ExclusiveLeaseHelpers
+ let(:default_timeout) { described_class.default_lease_timeout }
+
it { is_expected.to belong_to :namespace }
+ describe "#default_lease_timeout" do
+ subject(:default_lease_timeout) { default_timeout }
+
+ it { is_expected.to eq 30.minutes.to_i }
+
+ context 'when remove_namespace_aggregator_delay FF is disabled' do
+ before do
+ stub_feature_flags(remove_namespace_aggregator_delay: false)
+ end
+
+ it { is_expected.to eq 1.hour.to_i }
+ end
+ end
+
describe '#schedule_root_storage_statistics' do
let(:namespace) { create(:namespace) }
let(:aggregation_schedule) { namespace.build_aggregation_schedule }
@@ -14,7 +30,7 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state,
context "when we can't obtain the lease" do
it 'does not schedule the workers' do
- stub_exclusive_lease_taken(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT)
+ stub_exclusive_lease_taken(lease_key, timeout: default_timeout)
expect(Namespaces::RootStatisticsWorker)
.not_to receive(:perform_async)
@@ -28,20 +44,20 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state,
context 'when we can obtain the lease' do
it 'schedules a root storage statistics after create' do
- stub_exclusive_lease(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT)
+ stub_exclusive_lease(lease_key, timeout: default_timeout)
expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_async).once
expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_in).once
- .with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id)
+ .with(default_timeout, aggregation_schedule.namespace_id)
aggregation_schedule.save!
end
it 'does not release the lease' do
- stub_exclusive_lease(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT)
+ stub_exclusive_lease(lease_key, timeout: default_timeout)
aggregation_schedule.save!
@@ -58,7 +74,7 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state,
expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_in).once
- .with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id)
+ .with(default_timeout, aggregation_schedule.namespace_id)
.and_return(nil)
# Scheduling workers for the first time
diff --git a/spec/models/namespace/package_setting_spec.rb b/spec/models/namespace/package_setting_spec.rb
index 4308c8c06bc..2584fa597ad 100644
--- a/spec/models/namespace/package_setting_spec.rb
+++ b/spec/models/namespace/package_setting_spec.rb
@@ -85,4 +85,13 @@ RSpec.describe Namespace::PackageSetting do
end
end
end
+
+ describe 'package forwarding attributes' do
+ %i[maven_package_requests_forwarding
+ pypi_package_requests_forwarding
+ npm_package_requests_forwarding].each do |attribute|
+ it_behaves_like 'a cascading namespace setting boolean attribute', settings_attribute_name: attribute,
+ settings_association: :package_settings
+ end
+ end
end
diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb
index 4ac248802b8..a4446bfedd1 100644
--- a/spec/models/namespace_setting_spec.rb
+++ b/spec/models/namespace_setting_spec.rb
@@ -177,4 +177,8 @@ RSpec.describe NamespaceSetting, type: :model do
end
end
end
+
+ describe '#delayed_project_removal' do
+ it_behaves_like 'a cascading namespace setting boolean attribute', settings_attribute_name: :delayed_project_removal
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 2e8d22cb9db..c6d028af22d 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -362,6 +362,9 @@ RSpec.describe Namespace do
it { is_expected.to delegate_method(:name).to(:owner).with_prefix.allow_nil }
it { is_expected.to delegate_method(:avatar_url).to(:owner).allow_nil }
it { is_expected.to delegate_method(:prevent_sharing_groups_outside_hierarchy).to(:namespace_settings).allow_nil }
+ it { is_expected.to delegate_method(:maven_package_requests_forwarding).to(:package_settings) }
+ it { is_expected.to delegate_method(:pypi_package_requests_forwarding).to(:package_settings) }
+ it { is_expected.to delegate_method(:npm_package_requests_forwarding).to(:package_settings) }
it do
is_expected.to delegate_method(:prevent_sharing_groups_outside_hierarchy=).to(:namespace_settings)
@@ -1036,7 +1039,9 @@ RSpec.describe Namespace do
let(:pages_dir) { File.join(TestEnv.pages_path) }
def expect_project_directories_at(namespace_path, with_pages: true)
- expected_repository_path = File.join(TestEnv.repos_path, namespace_path, 'the-project.git')
+ expected_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, namespace_path, 'the-project.git')
+ end
expected_upload_path = File.join(uploads_dir, namespace_path, 'the-project')
expected_pages_path = File.join(pages_dir, namespace_path, 'the-project')
@@ -1046,15 +1051,19 @@ RSpec.describe Namespace do
end
before do
- FileUtils.mkdir_p(File.join(TestEnv.repos_path, "#{project.full_path}.git"))
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ FileUtils.mkdir_p(File.join(TestEnv.repos_path, "#{project.full_path}.git"))
+ end
FileUtils.mkdir_p(File.join(uploads_dir, project.full_path))
FileUtils.mkdir_p(File.join(pages_dir, project.full_path))
end
after do
- FileUtils.remove_entry(File.join(TestEnv.repos_path, parent.full_path), true)
- FileUtils.remove_entry(File.join(TestEnv.repos_path, new_parent.full_path), true)
- FileUtils.remove_entry(File.join(TestEnv.repos_path, child.full_path), true)
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, parent.full_path), true)
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, new_parent.full_path), true)
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, child.full_path), true)
+ end
FileUtils.remove_entry(File.join(uploads_dir, project.full_path), true)
FileUtils.remove_entry(pages_dir, true)
end
@@ -1962,7 +1971,7 @@ RSpec.describe Namespace do
it 'returns the virual domain' do
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
expect(virtual_domain.lookup_paths).not_to be_empty
- expect(virtual_domain.cache_key).to eq("pages_domain_for_namespace_#{namespace.root_ancestor.id}")
+ expect(virtual_domain.cache_key).to match(/pages_domain_for_namespace_#{namespace.root_ancestor.id}_/)
end
context 'when :cache_pages_domain_api is disabled' do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 1fce1f97dcb..670a6237788 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -1839,6 +1839,12 @@ RSpec.describe Note do
let(:note) { create(:note, :system, :on_issue, note: original_note_body) }
it { is_expected.to eq(expected_text_replacement) }
+
+ context 'context when note and cache are null (happens in bulk insert)' do
+ let(:note) { build(:note, :system, :on_issue, note: nil, note_html: nil).tap { |note| note.save!(validate: false) } }
+
+ it { is_expected.to be_in([nil, '']) }
+ end
end
end
end
@@ -1868,7 +1874,7 @@ RSpec.describe Note do
let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as completed</p>' }
before do
- note.update_columns(note_html: unchanged_note_body)
+ note.update_columns(note_html: unchanged_note_body) unless note.note.nil?
end
end
@@ -1878,7 +1884,7 @@ RSpec.describe Note do
let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as incomplete</p>' }
before do
- note.update_columns(note_html: unchanged_note_body)
+ note.update_columns(note_html: unchanged_note_body) unless note.note.nil?
end
end
end
diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb
index 8105262aada..068166ebb0d 100644
--- a/spec/models/notification_recipient_spec.rb
+++ b/spec/models/notification_recipient_spec.rb
@@ -57,16 +57,6 @@ RSpec.describe NotificationRecipient do
it 'returns false' do
expect(recipient.notifiable?).to eq(false)
end
-
- context 'when block_emails_with_failures is disabled' do
- before do
- stub_feature_flags(block_emails_with_failures: false)
- end
-
- it 'returns true' do
- expect(recipient.notifiable?).to eq(true)
- end
- end
end
context 'with temporary failures' do
@@ -77,16 +67,6 @@ RSpec.describe NotificationRecipient do
it 'returns false' do
expect(recipient.notifiable?).to eq(false)
end
-
- context 'when block_emails_with_failures is disabled' do
- before do
- stub_feature_flags(block_emails_with_failures: false)
- end
-
- it 'returns true' do
- expect(recipient.notifiable?).to eq(true)
- end
- end
end
end
end
diff --git a/spec/models/operations/feature_flags/strategy_spec.rb b/spec/models/operations/feature_flags/strategy_spec.rb
index de1b9d2c855..949f92b3b2a 100644
--- a/spec/models/operations/feature_flags/strategy_spec.rb
+++ b/spec/models/operations/feature_flags/strategy_spec.rb
@@ -130,14 +130,15 @@ RSpec.describe Operations::FeatureFlags::Strategy do
context 'when the strategy name is flexibleRollout' do
valid_parameters = { rollout: '40', groupId: 'mygroup', stickiness: 'default' }
- where(invalid_parameters: [
- nil,
- {},
- *valid_parameters.to_a.combination(1).to_a.map { |p| p.to_h },
- *valid_parameters.to_a.combination(2).to_a.map { |p| p.to_h },
- { **valid_parameters, userIds: '4' },
- { **valid_parameters, extra: nil }
- ])
+ where(
+ invalid_parameters: [
+ nil,
+ {},
+ *valid_parameters.to_a.combination(1).to_a.map { |p| p.to_h },
+ *valid_parameters.to_a.combination(2).to_a.map { |p| p.to_h },
+ { **valid_parameters, userIds: '4' },
+ { **valid_parameters, extra: nil }
+ ])
with_them do
it 'must have valid parameters for the strategy' do
strategy = build(:operations_strategy,
@@ -180,9 +181,7 @@ RSpec.describe Operations::FeatureFlags::Strategy do
expect(strategy).to be_invalid
- expect(strategy.errors[:parameters]).to eq([
- 'rollout must be a string between 0 and 100 inclusive'
- ])
+ expect(strategy.errors[:parameters]).to eq(['rollout must be a string between 0 and 100 inclusive'])
end
end
@@ -243,9 +242,8 @@ RSpec.describe Operations::FeatureFlags::Strategy do
expect(strategy).to be_invalid
- expect(strategy.errors[:parameters]).to eq([
- 'stickiness parameter must be default, userId, sessionId, or random'
- ])
+ expect(strategy.errors[:parameters]).to eq(
+ ['stickiness parameter must be default, userId, sessionId, or random'])
end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index fb88dbb4212..0edb04224a3 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -904,6 +904,14 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to match_array([pypi_package]) }
end
+ describe '.with_case_insensitive_version' do
+ let_it_be(:nuget_package) { create(:nuget_package, version: '1.0.0-ABC') }
+
+ subject { described_class.with_case_insensitive_version('1.0.0-abC') }
+
+ it { is_expected.to match_array([nuget_package]) }
+ end
+
context 'status scopes' do
let_it_be(:default_package) { create(:maven_package, :default) }
let_it_be(:hidden_package) { create(:maven_package, :hidden) }
diff --git a/spec/models/packages/rpm/repository_file_spec.rb b/spec/models/packages/rpm/repository_file_spec.rb
new file mode 100644
index 00000000000..34347793dd8
--- /dev/null
+++ b/spec/models/packages/rpm/repository_file_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rpm::RepositoryFile, type: :model do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:repository_file) { create(:rpm_repository_file) }
+
+ it_behaves_like 'having unique enum values'
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ end
+
+ context 'when updating project statistics' do
+ context 'when the package file has an explicit size' do
+ it_behaves_like 'UpdateProjectStatistics' do
+ subject { build(:rpm_repository_file, size: 42) }
+ end
+ end
+
+ context 'when the package file does not have a size' do
+ it_behaves_like 'UpdateProjectStatistics' do
+ subject { build(:rpm_repository_file, size: nil) }
+ end
+ end
+ end
+
+ context 'with status scopes' do
+ let_it_be(:pending_destruction_repository_package_file) do
+ create(:rpm_repository_file, :pending_destruction)
+ end
+
+ describe '.with_status' do
+ subject { described_class.with_status(:pending_destruction) }
+
+ it { is_expected.to contain_exactly(pending_destruction_repository_package_file) }
+ end
+ end
+end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index b50bfaed528..463ec904e9a 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -563,7 +563,7 @@ RSpec.describe PagesDomain do
it 'returns the virual domain when there are pages deployed for the project' do
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
expect(virtual_domain.lookup_paths).not_to be_empty
- expect(virtual_domain.cache_key).to eq("pages_domain_for_project_#{project.id}")
+ expect(virtual_domain.cache_key).to match(/pages_domain_for_project_#{project.id}_/)
end
context 'when :cache_pages_domain_api is disabled' do
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 5bce6a2cc3f..67e7d444d25 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -105,6 +105,31 @@ RSpec.describe PersonalAccessToken do
end
end
+ describe '.last_used_before' do
+ context 'last_used_*' do
+ let_it_be(:date) { DateTime.new(2022, 01, 01) }
+ let_it_be(:token) { create(:personal_access_token, last_used_at: date ) }
+ # This token should never occur in the following tests and indicates that filtering was done correctly with it
+ let_it_be(:never_used_token) { create(:personal_access_token) }
+
+ describe '.last_used_before' do
+ it 'returns personal access tokens used before the specified date only' do
+ expect(described_class.last_used_before(date + 1)).to contain_exactly(token)
+ end
+ end
+
+ it 'does not return token that is last_used_at after given date' do
+ expect(described_class.last_used_before(date + 1)).not_to contain_exactly(never_used_token)
+ end
+
+ describe '.last_used_after' do
+ it 'returns personal access tokens used after the specified date only' do
+ expect(described_class.last_used_after(date - 1)).to contain_exactly(token)
+ end
+ end
+ end
+ end
+
describe '.last_used_before_or_unused' do
let(:last_used_at) { 1.month.ago.beginning_of_hour }
let!(:unused_token) { create(:personal_access_token) }
diff --git a/spec/models/pool_repository_spec.rb b/spec/models/pool_repository_spec.rb
index bf88e941540..9861e832bef 100644
--- a/spec/models/pool_repository_spec.rb
+++ b/spec/models/pool_repository_spec.rb
@@ -26,8 +26,6 @@ RSpec.describe PoolRepository do
describe '#unlink_repository' do
let(:pool) { create(:pool_repository, :ready) }
- let(:repository_path) { File.join(TestEnv.repos_path, pool.source_project.repository.relative_path) }
- let(:alternates_file) { File.join(repository_path, 'objects', 'info', 'alternates') }
before do
pool.link_repository(pool.source_project.repository)
@@ -36,19 +34,17 @@ RSpec.describe PoolRepository do
context 'when the last member leaves' do
it 'schedules pool removal' do
expect(::ObjectPool::DestroyWorker).to receive(:perform_async).with(pool.id).and_call_original
+ expect(pool.source_project.repository).to receive(:disconnect_alternates).and_call_original
pool.unlink_repository(pool.source_project.repository)
-
- expect(File).not_to exist(alternates_file)
end
end
context 'when skipping disconnect' do
it 'does not change the alternates file' do
- before = File.read(alternates_file)
- pool.unlink_repository(pool.source_project.repository, disconnect: false)
+ expect(pool.source_project.repository).not_to receive(:disconnect_alternates)
- expect(File.read(alternates_file)).to eq(before)
+ pool.unlink_repository(pool.source_project.repository, disconnect: false)
end
end
@@ -58,10 +54,9 @@ RSpec.describe PoolRepository do
pool.link_repository(other_project.repository)
expect(::ObjectPool::DestroyWorker).not_to receive(:perform_async).with(pool.id)
+ expect(pool.source_project.repository).to receive(:disconnect_alternates).and_call_original
pool.unlink_repository(pool.source_project.repository)
-
- expect(File).not_to exist(alternates_file)
end
end
end
diff --git a/spec/models/preloaders/project_root_ancestor_preloader_spec.rb b/spec/models/preloaders/project_root_ancestor_preloader_spec.rb
index 30036a6a033..bb0de24abe5 100644
--- a/spec/models/preloaders/project_root_ancestor_preloader_spec.rb
+++ b/spec/models/preloaders/project_root_ancestor_preloader_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Preloaders::ProjectRootAncestorPreloader do
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(:root_parent2) { create(:group, name: 'root-2', path: 'root-2') }
let_it_be(:guest_project) { create(:project, name: 'public guest', path: 'public-guest') }
let_it_be(:private_maintainer_project) do
create(:project, :private, name: 'b private maintainer', path: 'b-private-maintainer', namespace: root_parent1)
@@ -15,7 +15,7 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
end
let_it_be(:public_maintainer_project) do
- create(:project, :private, name: 'a public maintainer', path: 'a-public-maintainer', namespace: root_parent2)
+ create(:project, name: 'a public maintainer', path: 'a-public-maintainer', namespace: root_parent2)
end
let(:root_query_regex) { /\ASELECT.+FROM "namespaces" WHERE "namespaces"."id" = \d+/ }
@@ -36,20 +36,20 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
it 'strong_memoizes the correct root_ancestor' do
pristine_projects.each do |project|
- expected_parent_id = project.root_ancestor&.id
+ preloaded_parent_id = project.root_ancestor&.id
- expect(project.parent_id).to eq(expected_parent_id)
+ expect(preloaded_parent_id).to eq(project.parent_id)
end
end
end
context 'when use_traversal_ids FF is enabled' do
context 'when the preloader is used' do
- before do
- preload_ancestors
- end
-
context 'when no additional preloads are provided' do
+ before do
+ preload_ancestors(:group)
+ end
+
it_behaves_like 'executes N matching DB queries', 0
end
@@ -57,6 +57,10 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
let(:additional_preloads) { [:route] }
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
+ before do
+ preload_ancestors
+ end
+
it_behaves_like 'executes N matching DB queries', 0, :full_path
end
end
@@ -64,6 +68,17 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
+
+ context 'when using a :group sti name and passing projects in a user namespace' do
+ let(:projects) { [private_developer_project] }
+ let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
+
+ it 'does not load a nil value for root_ancestor' do
+ preload_ancestors(:group)
+
+ expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
+ end
+ end
end
context 'when use_traversal_ids FF is disabled' do
@@ -91,9 +106,22 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
+
+ context 'when using a :group sti name and passing projects in a user namespace' do
+ let(:projects) { [private_developer_project] }
+ let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
+
+ it 'does not load a nil value for root_ancestor' do
+ preload_ancestors(:group)
+
+ expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
+ end
+ end
end
- def preload_ancestors
- described_class.new(pristine_projects, :namespace, additional_preloads).execute
+ private
+
+ def preload_ancestors(namespace_sti_name = :namespace)
+ described_class.new(pristine_projects, namespace_sti_name, additional_preloads).execute
end
end
diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb
index 14220007966..55fe28ceb6f 100644
--- a/spec/models/project_authorization_spec.rb
+++ b/spec/models/project_authorization_spec.rb
@@ -92,20 +92,192 @@ RSpec.describe ProjectAuthorization do
let_it_be(:project_2) { create(:project) }
let_it_be(:project_3) { create(:project) }
- let(:per_batch_size) { 2 }
-
- it 'inserts the rows in batches, as per the `per_batch` size' do
- attributes = [
+ let(:attributes) do
+ [
{ 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 }
]
+ end
- expect(described_class).to receive(:insert_all).twice.and_call_original
+ before do
+ # Configure as if a replica database is enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(false)
+ stub_feature_flags(enable_minor_delay_during_project_authorizations_refresh: true)
+ end
- described_class.insert_all_in_batches(attributes, per_batch_size)
+ shared_examples_for 'inserts the rows in batches, as per the `per_batch` size, without a delay between each batch' do
+ specify do
+ expect(described_class).not_to receive(:sleep)
- expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(attributes.map(&:values))
+ described_class.insert_all_in_batches(attributes, per_batch_size)
+
+ expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(attributes.map(&:values))
+ end
+ end
+
+ context 'when the total number of records to be inserted is greater than the batch size' do
+ let(:per_batch_size) { 2 }
+
+ it 'inserts the rows in batches, as per the `per_batch` size, with a delay between each batch' do
+ expect(described_class).to receive(:insert_all).twice.and_call_original
+ expect(described_class).to receive(:sleep).twice
+
+ described_class.insert_all_in_batches(attributes, per_batch_size)
+
+ expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(attributes.map(&:values))
+ end
+
+ context 'when the GitLab installation does not have a replica database configured' do
+ before do
+ # Configure as if a replica database is not enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(true)
+ end
+
+ it_behaves_like 'inserts the rows in batches, as per the `per_batch` size, without a delay between each batch'
+ end
+ end
+
+ context 'when the total number of records to be inserted is less than the batch size' do
+ let(:per_batch_size) { 5 }
+
+ it_behaves_like 'inserts the rows in batches, as per the `per_batch` size, without a delay between each batch'
+ end
+ end
+
+ describe '.delete_all_in_batches_for_project' 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) }
+ let_it_be(:user_4) { create(:user) }
+
+ let(:user_ids) { [user_1.id, user_2.id, user_3.id] }
+
+ before do
+ # Configure as if a replica database is enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(false)
+ stub_feature_flags(enable_minor_delay_during_project_authorizations_refresh: true)
+ end
+
+ before_all 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)
+ create(:project_authorization, user: user_4, project: project)
+ end
+
+ shared_examples_for 'removes the project authorizations of the specified users in the current project, without a delay between each batch' do
+ specify do
+ expect(described_class).not_to receive(:sleep)
+
+ described_class.delete_all_in_batches_for_project(
+ project: project,
+ user_ids: user_ids,
+ per_batch: per_batch_size
+ )
+
+ expect(project.project_authorizations.pluck(:user_id)).not_to include(*user_ids)
+ end
+ end
+
+ context 'when the total number of records to be removed is greater than the batch size' do
+ let(:per_batch_size) { 2 }
+
+ it 'removes the project authorizations of the specified users in the current project, with a delay between each batch' do
+ expect(described_class).to receive(:sleep).twice
+
+ described_class.delete_all_in_batches_for_project(
+ project: project,
+ user_ids: user_ids,
+ per_batch: per_batch_size
+ )
+
+ expect(project.project_authorizations.pluck(:user_id)).not_to include(*user_ids)
+ end
+
+ context 'when the GitLab installation does not have a replica database configured' do
+ before do
+ # Configure as if a replica database is not enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(true)
+ end
+
+ it_behaves_like 'removes the project authorizations of the specified users in the current project, without a delay between each batch'
+ end
+ end
+
+ context 'when the total number of records to be removed is less than the batch size' do
+ let(:per_batch_size) { 5 }
+
+ it_behaves_like 'removes the project authorizations of the specified users in the current project, without a delay between each batch'
+ end
+ end
+
+ describe '.delete_all_in_batches_for_user' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project_1) { create(:project) }
+ let_it_be(:project_2) { create(:project) }
+ let_it_be(:project_3) { create(:project) }
+ let_it_be(:project_4) { create(:project) }
+
+ let(:project_ids) { [project_1.id, project_2.id, project_3.id] }
+
+ before do
+ # Configure as if a replica database is enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(false)
+ stub_feature_flags(enable_minor_delay_during_project_authorizations_refresh: true)
+ end
+
+ before_all do
+ create(:project_authorization, user: user, project: project_1)
+ create(:project_authorization, user: user, project: project_2)
+ create(:project_authorization, user: user, project: project_3)
+ create(:project_authorization, user: user, project: project_4)
+ end
+
+ shared_examples_for 'removes the project authorizations of the specified projects from the current user, without a delay between each batch' do
+ specify do
+ expect(described_class).not_to receive(:sleep)
+
+ described_class.delete_all_in_batches_for_user(
+ user: user,
+ project_ids: project_ids,
+ per_batch: per_batch_size
+ )
+
+ expect(user.project_authorizations.pluck(:project_id)).not_to include(*project_ids)
+ end
+ end
+
+ context 'when the total number of records to be removed is greater than the batch size' do
+ let(:per_batch_size) { 2 }
+
+ it 'removes the project authorizations of the specified projects from the current user, with a delay between each batch' do
+ expect(described_class).to receive(:sleep).twice
+
+ described_class.delete_all_in_batches_for_user(
+ user: user,
+ project_ids: project_ids,
+ per_batch: per_batch_size
+ )
+
+ expect(user.project_authorizations.pluck(:project_id)).not_to include(*project_ids)
+ end
+
+ context 'when the GitLab installation does not have a replica database configured' do
+ before do
+ # Configure as if a replica database is not enabled
+ allow(::Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(true)
+ end
+
+ it_behaves_like 'removes the project authorizations of the specified projects from the current user, without a delay between each batch'
+ end
+ end
+
+ context 'when the total number of records to be removed is less than the batch size' do
+ let(:per_batch_size) { 5 }
+
+ it_behaves_like 'removes the project authorizations of the specified projects from the current user, without a delay between each batch'
end
end
end
diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb
index 8b95b86b14b..f141b8e83d6 100644
--- a/spec/models/project_group_link_spec.rb
+++ b/spec/models/project_group_link_spec.rb
@@ -47,9 +47,9 @@ RSpec.describe ProjectGroupLink do
it 'returns all records which are greater than Guests access' do
expect(described_class.non_guests).to match_array([
- project_group_link_reporter,
- project_group_link_developer,
- project_group_link_maintainer
+ project_group_link_reporter,
+ project_group_link_developer,
+ project_group_link_maintainer
])
end
end
diff --git a/spec/models/project_setting_spec.rb b/spec/models/project_setting_spec.rb
index a09ae7ec7ae..5730ca58e9e 100644
--- a/spec/models/project_setting_spec.rb
+++ b/spec/models/project_setting_spec.rb
@@ -21,6 +21,10 @@ RSpec.describe ProjectSetting, type: :model do
it { is_expected.not_to allow_value(nil).for(:target_platforms) }
it { is_expected.to allow_value([]).for(:target_platforms) }
+ it { is_expected.not_to allow_value(nil).for(:suggested_reviewers_enabled) }
+ it { is_expected.to allow_value(true).for(:suggested_reviewers_enabled) }
+ it { is_expected.to allow_value(false).for(:suggested_reviewers_enabled) }
+
it 'allows any combination of the allowed target platforms' do
valid_target_platform_combinations.each do |target_platforms|
expect(subject).to allow_value(target_platforms).for(:target_platforms)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 99b984ff547..75887e49dc9 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -28,7 +28,6 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:issues) }
it { is_expected.to have_many(:incident_management_issuable_escalation_statuses).through(:issues).inverse_of(:project).class_name('IncidentManagement::IssuableEscalationStatus') }
it { is_expected.to have_many(:milestones) }
- it { is_expected.to have_many(:iterations) }
it { is_expected.to have_many(:project_members).dependent(:delete_all) }
it { is_expected.to have_many(:users).through(:project_members) }
it { is_expected.to have_many(:requesters).dependent(:delete_all) }
@@ -149,6 +148,8 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:secure_files).class_name('Ci::SecureFile').dependent(:restrict_with_error) }
it { is_expected.to have_one(:build_artifacts_size_refresh).class_name('Projects::BuildArtifactsSizeRefresh') }
it { is_expected.to have_many(:project_callouts).class_name('Users::ProjectCallout').with_foreign_key(:project_id) }
+ it { is_expected.to have_many(:pipeline_metadata).class_name('Ci::PipelineMetadata') }
+ it { is_expected.to have_many(:incident_management_timeline_event_tags).class_name('IncidentManagement::TimelineEventTag') }
# GitLab Pages
it { is_expected.to have_many(:pages_domains) }
@@ -845,6 +846,8 @@ RSpec.describe Project, factory_default: :keep do
end
describe 'delegation' do
+ let_it_be(:project) { create(:project) }
+
[:add_guest, :add_reporter, :add_developer, :add_maintainer, :add_member, :add_members].each do |method|
it { is_expected.to delegate_method(method).to(:team) }
end
@@ -859,6 +862,9 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to delegate_method(:environments_access_level).to(:project_feature) }
it { is_expected.to delegate_method(:feature_flags_access_level).to(:project_feature) }
it { is_expected.to delegate_method(:releases_access_level).to(:project_feature) }
+ it { is_expected.to delegate_method(:maven_package_requests_forwarding).to(:namespace) }
+ it { is_expected.to delegate_method(:pypi_package_requests_forwarding).to(:namespace) }
+ it { is_expected.to delegate_method(:npm_package_requests_forwarding).to(:namespace) }
describe 'read project settings' do
%i(
@@ -884,8 +890,24 @@ RSpec.describe Project, factory_default: :keep do
end
include_examples 'ci_cd_settings delegation' do
- # Skip attributes defined in EE code
+ let(:attributes_with_prefix) do
+ {
+ 'group_runners_enabled' => '',
+ 'default_git_depth' => 'ci_',
+ 'forward_deployment_enabled' => 'ci_',
+ 'keep_latest_artifact' => '',
+ 'restrict_user_defined_variables' => '',
+ 'runner_token_expiration_interval' => '',
+ 'separated_caches' => 'ci_',
+ 'opt_in_jwt' => 'ci_',
+ 'allow_fork_pipelines_to_run_in_parent_project' => 'ci_',
+ 'inbound_job_token_scope_enabled' => 'ci_',
+ 'job_token_scope_enabled' => 'ci_outbound_'
+ }
+ end
+
let(:exclude_attributes) do
+ # Skip attributes defined in EE code
%w(
merge_pipelines_enabled
merge_trains_enabled
@@ -906,12 +928,18 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#ci_job_token_scope_enabled?' do
- it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
+ describe '#ci_outbound_job_token_scope_enabled?' do
+ it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_outbound_' do
let(:delegated_method) { :job_token_scope_enabled? }
end
end
+ describe '#ci_inbound_job_token_scope_enabled?' do
+ it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
+ let(:delegated_method) { :inbound_job_token_scope_enabled? }
+ end
+ end
+
describe '#restrict_user_defined_variables?' do
it_behaves_like 'a ci_cd_settings predicate method' do
let(:delegated_method) { :restrict_user_defined_variables? }
@@ -937,23 +965,6 @@ 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 '#merge_commit_template_or_default' do
let_it_be(:project) { create(:project) }
@@ -1426,7 +1437,7 @@ RSpec.describe Project, factory_default: :keep do
it "is false if used other tracker" do
# NOTE: The current nature of this factory requires persistence
- project = create(:redmine_project)
+ project = create(:project, :with_redmine_integration)
expect(project.default_issues_tracker?).to be_falsey
end
@@ -1471,7 +1482,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#external_issue_tracker' do
it 'sets Project#has_external_issue_tracker when it is nil' do
project_with_no_tracker = create(:project, has_external_issue_tracker: nil)
- project_with_tracker = create(:redmine_project, has_external_issue_tracker: nil)
+ project_with_tracker = create(:project, :with_redmine_integration, has_external_issue_tracker: nil)
expect do
project_with_no_tracker.external_issue_tracker
@@ -1490,7 +1501,7 @@ RSpec.describe Project, factory_default: :keep do
end
it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
- project = create(:redmine_project)
+ project = create(:project, :with_redmine_integration)
expect(project).to receive(:integrations).once.and_call_original
2.times { expect(project.external_issue_tracker).to be_a_kind_of(Integrations::Redmine) }
@@ -4620,6 +4631,7 @@ RSpec.describe Project, factory_default: :keep do
describe '.filter_by_feature_visibility' do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
+ include UserHelpers
let_it_be(:group) { create(:group) }
let_it_be_with_reload(:project) { create(:project, namespace: group) }
@@ -5761,40 +5773,40 @@ RSpec.describe Project, factory_default: :keep do
describe '#has_active_hooks?' do
let_it_be_with_refind(:project) { create(:project) }
- it { expect(project.has_active_hooks?).to be_falsey }
+ it { expect(project.has_active_hooks?).to eq(false) }
it 'returns true when a matching push hook exists' do
create(:project_hook, push_events: true, project: project)
- expect(project.has_active_hooks?(:merge_request_events)).to be_falsey
- expect(project.has_active_hooks?).to be_truthy
+ expect(project.has_active_hooks?(:merge_request_hooks)).to eq(false)
+ expect(project.has_active_hooks?).to eq(true)
end
it 'returns true when a matching system hook exists' do
create(:system_hook, push_events: true)
- expect(project.has_active_hooks?(:merge_request_events)).to be_falsey
- expect(project.has_active_hooks?).to be_truthy
+ expect(project.has_active_hooks?(:merge_request_hooks)).to eq(false)
+ expect(project.has_active_hooks?).to eq(true)
end
it 'returns true when a plugin exists' do
expect(Gitlab::FileHook).to receive(:any?).twice.and_return(true)
- expect(project.has_active_hooks?(:merge_request_events)).to be_truthy
- expect(project.has_active_hooks?).to be_truthy
+ expect(project.has_active_hooks?(:merge_request_hooks)).to eq(true)
+ expect(project.has_active_hooks?).to eq(true)
end
end
describe '#has_active_integrations?' do
let_it_be(:project) { create(:project) }
- it { expect(project.has_active_integrations?).to be_falsey }
+ it { expect(project.has_active_integrations?).to eq(false) }
it 'returns true when a matching service exists' do
create(:custom_issue_tracker_integration, push_events: true, merge_requests_events: false, project: project)
- expect(project.has_active_integrations?(:merge_request_hooks)).to be_falsey
- expect(project.has_active_integrations?).to be_truthy
+ expect(project.has_active_integrations?(:merge_request_hooks)).to eq(false)
+ expect(project.has_active_integrations?).to eq(true)
end
end
@@ -8308,16 +8320,6 @@ RSpec.describe Project, factory_default: :keep do
expect(project.packages_policy_subject).to be_a(Packages::Policies::Project)
expect(project.packages_policy_subject.project).to eq(project)
end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(read_package_policy_rule: false)
- end
-
- it 'returns project' do
- expect(project.packages_policy_subject).to eq(project)
- end
- end
end
describe '#destroy_deployment_by_id' do
@@ -8356,6 +8358,22 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#can_suggest_reviewers?' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:can_suggest_reviewers) { project.can_suggest_reviewers? }
+
+ it { is_expected.to be(false) }
+ end
+
+ describe '#suggested_reviewers_available?' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:suggested_reviewers_available) { project.suggested_reviewers_available? }
+
+ it { is_expected.to be(false) }
+ end
+
private
def finish_job(export_job)
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index b2158baa670..9de31ea66e4 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -98,6 +98,8 @@ RSpec.describe ProjectStatistics do
end
describe '#refresh!' do
+ subject(:refresh_statistics) { statistics.refresh! }
+
before do
allow(statistics).to receive(:update_commit_count)
allow(statistics).to receive(:update_repository_size)
@@ -111,7 +113,7 @@ RSpec.describe ProjectStatistics do
context "without arguments" do
before do
- statistics.refresh!
+ refresh_statistics
end
it "sums all counters" do
@@ -146,7 +148,7 @@ RSpec.describe ProjectStatistics do
expect(project.repository.exists?).to be_falsey
expect(project.wiki.repository.exists?).to be_falsey
- statistics.refresh!
+ refresh_statistics
expect(statistics).to have_received(:update_commit_count)
expect(statistics).to have_received(:update_repository_size)
@@ -167,14 +169,12 @@ RSpec.describe ProjectStatistics do
let(:project) { create(:project, :repository, :wiki_repo) }
before do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- FileUtils.rm_rf(project.repository.path)
- FileUtils.rm_rf(project.wiki.repository.path)
- end
+ project.repository.remove
+ project.wiki.repository.remove
end
it 'does not crash' do
- statistics.refresh!
+ refresh_statistics
expect(statistics).to have_received(:update_commit_count)
expect(statistics).to have_received(:update_repository_size)
@@ -209,7 +209,7 @@ RSpec.describe ProjectStatistics do
expect(Namespaces::ScheduleAggregationWorker)
.to receive(:perform_async)
- statistics.refresh!
+ refresh_statistics
end
end
end
@@ -238,9 +238,13 @@ RSpec.describe ProjectStatistics do
expect(Namespaces::ScheduleAggregationWorker)
.not_to receive(:perform_async)
- statistics.refresh!
+ refresh_statistics
end
end
+
+ it_behaves_like 'obtaining lease to update database' do
+ let(:model) { statistics }
+ end
end
describe '#update_commit_count' do
@@ -408,6 +412,8 @@ RSpec.describe ProjectStatistics do
end
describe '#refresh_storage_size!' do
+ subject(:refresh_storage_size) { statistics.refresh_storage_size! }
+
it 'recalculates storage size from its components and save it' do
statistics.update_columns(
repository_size: 2,
@@ -422,7 +428,29 @@ RSpec.describe ProjectStatistics do
storage_size: 0
)
- expect { statistics.refresh_storage_size! }.to change { statistics.storage_size }.from(0).to(28)
+ expect { refresh_storage_size }.to change { statistics.reload.storage_size }.from(0).to(28)
+ end
+
+ context 'when nullable columns are nil' do
+ before do
+ statistics.update_columns(
+ repository_size: 2,
+ wiki_size: nil,
+ storage_size: 0
+ )
+ end
+
+ it 'does not raise any error' do
+ expect { refresh_storage_size }.not_to raise_error
+ end
+
+ it 'recalculates storage size from its components' do
+ expect { refresh_storage_size }.to change { statistics.reload.storage_size }.from(0).to(2)
+ end
+ end
+
+ it_behaves_like 'obtaining lease to update database' do
+ let(:model) { statistics }
end
end
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index 54a90ca6049..b88367b9ca2 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -435,4 +435,28 @@ RSpec.describe ProtectedBranch do
expect(described_class.downcase_humanized_name).to eq 'protected branch'
end
end
+
+ describe '.default_branch?' do
+ before do
+ allow(subject.project).to receive(:default_branch).and_return(branch)
+ end
+
+ context 'when the name matches the default branch' do
+ let(:branch) { subject.name }
+
+ it { is_expected.to be_default_branch }
+ end
+
+ context 'when the name does not match the default branch' do
+ let(:branch) { "#{subject.name}qwerty" }
+
+ it { is_expected.not_to be_default_branch }
+ end
+
+ context 'when a wildcard name matches the default branch' do
+ let(:branch) { "#{subject.name}*" }
+
+ it { is_expected.not_to be_default_branch }
+ end
+ end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 4e386bf584f..6fbf69ec23a 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -8,12 +8,12 @@ RSpec.describe Repository do
TestBlob = Struct.new(:path)
- let(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
let(:repository) { project.repository }
let(:broken_repository) { create(:project, :broken_storage).repository }
- let(:user) { create(:user) }
let(:git_user) { Gitlab::Git::User.from_gitlab(user) }
-
let(:message) { 'Test message' }
let(:merge_commit) do
@@ -40,16 +40,20 @@ RSpec.describe Repository do
end
describe '#branch_names_contains' do
- let_it_be(:project) { create(:project, :repository) }
+ subject { repository.branch_names_contains(sample_commit.id, **opts) }
- let(:repository) { project.repository }
-
- subject { repository.branch_names_contains(sample_commit.id) }
+ let(:opts) { {} }
it { is_expected.to include('master') }
it { is_expected.not_to include('feature') }
it { is_expected.not_to include('fix') }
+ context 'when limit is provided' do
+ let(:opts) { { limit: 1 } }
+
+ it { is_expected.to match_array(["'test'"]) }
+ end
+
describe 'when storage is broken', :broken_storage do
it 'raises a storage error' do
expect_to_raise_storage_error do
@@ -60,10 +64,18 @@ RSpec.describe Repository do
end
describe '#tag_names_contains' do
- subject { repository.tag_names_contains(sample_commit.id) }
+ subject { repository.tag_names_contains(sample_commit.id, **opts) }
+
+ let(:opts) { {} }
it { is_expected.to include('v1.1.0') }
it { is_expected.not_to include('v1.0.0') }
+
+ context 'when limit is provided' do
+ let(:opts) { { limit: 1 } }
+
+ it { is_expected.to match_array(['v1.1.0']) }
+ end
end
describe '#tags_sorted_by' do
@@ -359,6 +371,8 @@ RSpec.describe Repository do
end
describe '#commits' do
+ let_it_be(:project) { create(:project, :repository) }
+
context 'when neither the all flag nor a ref are specified' do
it 'returns every commit from default branch' do
expect(repository.commits(nil, limit: 60).size).to eq(37)
@@ -431,10 +445,6 @@ RSpec.describe Repository do
end
describe '#new_commits' do
- let_it_be(:project) { create(:project, :repository) }
-
- let(:repository) { project.repository }
-
subject { repository.new_commits(rev) }
context 'when there are no new commits' do
@@ -498,6 +508,8 @@ RSpec.describe Repository do
end
describe '#commits_between' do
+ let_it_be(:project) { create(:project, :repository) }
+
let(:commit) { project.commit }
it 'delegates to Gitlab::Git::Commit#between, returning decorated commits' do
@@ -614,6 +626,8 @@ RSpec.describe Repository do
end
describe '#merged_to_root_ref?' do
+ let_it_be(:project) { create(:project, :repository) }
+
context 'merged branch without ff' do
subject { repository.merged_to_root_ref?('branch-merged') }
@@ -843,14 +857,16 @@ RSpec.describe Repository do
end
describe "#create_dir" do
+ let_it_be(:project) { create(:project, :repository) }
+
it "commits a change that creates a new directory" do
expect do
- repository.create_dir(user, 'newdir',
+ repository.create_dir(user, 'newdir1',
message: 'Create newdir', branch_name: 'master')
end.to change { repository.count_commits(ref: 'master') }.by(1)
- newdir = repository.tree('master', 'newdir')
- expect(newdir.path).to eq('newdir')
+ newdir = repository.tree('master', 'newdir1')
+ expect(newdir.path).to eq('newdir1')
end
context "when committing to another project" do
@@ -858,7 +874,7 @@ RSpec.describe Repository do
it "creates a fork and commit to the forked project" do
expect do
- repository.create_dir(user, 'newdir',
+ repository.create_dir(user, 'newdir2',
message: 'Create newdir', branch_name: 'patch',
start_branch_name: 'master', start_project: forked_project)
end.to change { repository.count_commits(ref: 'master') }.by(0)
@@ -866,15 +882,15 @@ RSpec.describe Repository do
expect(repository.branch_exists?('patch')).to be_truthy
expect(forked_project.repository.branch_exists?('patch')).to be_falsy
- newdir = repository.tree('patch', 'newdir')
- expect(newdir.path).to eq('newdir')
+ newdir = repository.tree('patch', 'newdir2')
+ expect(newdir.path).to eq('newdir2')
end
end
context "when an author is specified" do
it "uses the given email/name to set the commit's author" do
expect do
- repository.create_dir(user, 'newdir',
+ repository.create_dir(user, 'newdir3',
message: 'Add newdir',
branch_name: 'master',
author_email: author_email, author_name: author_name)
@@ -987,6 +1003,8 @@ RSpec.describe Repository do
end
describe "#delete_file" do
+ let(:project) { create(:project, :repository) }
+
it 'removes file successfully' do
expect do
repository.delete_file(user, 'README',
@@ -1013,6 +1031,8 @@ RSpec.describe Repository do
end
describe "search_files_by_content" do
+ let_it_be(:project) { create(:project, :repository) }
+
let(:results) { repository.search_files_by_content('feature', 'master') }
subject { results }
@@ -1248,6 +1268,8 @@ RSpec.describe Repository do
end
describe "#changelog", :use_clean_rails_memory_store_caching do
+ let(:project) { create(:project, :repository) }
+
it 'accepts changelog' do
expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('changelog')])
@@ -1280,6 +1302,8 @@ RSpec.describe Repository do
end
describe "#license_blob", :use_clean_rails_memory_store_caching do
+ let(:project) { create(:project, :repository) }
+
before do
repository.delete_file(
user, 'LICENSE', message: 'Remove LICENSE', branch_name: 'master')
@@ -1323,7 +1347,9 @@ RSpec.describe Repository do
end
end
- describe '#license_key', :use_clean_rails_memory_store_caching do
+ describe '#license_key', :clean_gitlab_redis_cache do
+ let(:project) { create(:project, :repository) }
+
before do
repository.delete_file(user, 'LICENSE',
message: 'Remove LICENSE', branch_name: 'master')
@@ -1367,50 +1393,52 @@ RSpec.describe Repository do
end
end
- describe '#license' do
- before do
- repository.delete_file(user, 'LICENSE',
- message: 'Remove LICENSE', branch_name: 'master')
- end
+ [true, false].each do |ff|
+ context "with feature flag license_from_gitaly=#{ff}" do
+ before do
+ stub_feature_flags(license_from_gitaly: ff)
+ end
- it 'returns nil when no license is detected' do
- expect(repository.license).to be_nil
- end
+ describe '#license', :use_clean_rails_memory_store_caching, :clean_gitlab_redis_cache do
+ let(:project) { create(:project, :repository) }
- it 'returns nil when the repository does not exist' do
- expect(repository).to receive(:exists?).and_return(false)
+ before do
+ repository.delete_file(user, 'LICENSE',
+ message: 'Remove LICENSE', branch_name: 'master')
+ end
- expect(repository.license).to be_nil
- end
+ it 'returns nil when no license is detected' do
+ expect(repository.license).to be_nil
+ end
- it 'returns nil when license_key is not recognized' do
- expect(repository).to receive(:license_key).twice.and_return('not-recognized')
- expect(Gitlab::ErrorTracking).to receive(:track_exception) do |ex|
- expect(ex).to be_a(Licensee::InvalidLicense)
- end
+ it 'returns nil when the repository does not exist' do
+ expect(repository).to receive(:exists?).and_return(false)
- expect(repository.license).to be_nil
- end
+ expect(repository.license).to be_nil
+ end
- it 'returns other when the content is not recognizable' do
- license = Licensee::License.new('other')
- repository.create_file(user, 'LICENSE', 'Gitlab B.V.',
- message: 'Add LICENSE', branch_name: 'master')
+ it 'returns other when the content is not recognizable' do
+ repository.create_file(user, 'LICENSE', 'Gitlab B.V.',
+ message: 'Add LICENSE', branch_name: 'master')
- expect(repository.license).to eq(license)
- end
+ expect(repository.license_key).to eq('other')
+ end
- it 'returns the license' do
- license = Licensee::License.new('mit')
- repository.create_file(user, 'LICENSE',
- license.content,
- message: 'Add LICENSE', branch_name: 'master')
+ it 'returns the license' do
+ license = Licensee::License.new('mit')
+ repository.create_file(user, 'LICENSE',
+ license.content,
+ message: 'Add LICENSE', branch_name: 'master')
- expect(repository.license).to eq(license)
+ expect(repository.license_key).to eq(license.key)
+ end
+ end
end
end
describe "#gitlab_ci_yml", :use_clean_rails_memory_store_caching do
+ let(:project) { create(:project, :repository) }
+
it 'returns valid file' do
files = [TestBlob.new('file'), TestBlob.new('.gitlab-ci.yml'), TestBlob.new('copying')]
expect(repository.tree).to receive(:blobs).and_return(files)
@@ -1430,11 +1458,11 @@ RSpec.describe Repository do
end
describe '#ambiguous_ref?' do
- let(:ref) { 'ref' }
-
subject { repository.ambiguous_ref?(ref) }
context 'when ref is ambiguous' do
+ let(:ref) { 'ref' }
+
before do
repository.add_tag(project.creator, ref, 'master')
repository.add_branch(project.creator, ref, 'master')
@@ -1446,6 +1474,8 @@ RSpec.describe Repository do
end
context 'when ref is not ambiguous' do
+ let(:ref) { 'another_ref' }
+
before do
repository.add_tag(project.creator, ref, 'master')
end
@@ -1457,6 +1487,8 @@ RSpec.describe Repository do
end
describe '#has_ambiguous_refs?' do
+ let(:project) { create(:project, :repository) }
+
using RSpec::Parameterized::TableSyntax
where(:branch_names, :tag_names, :result) do
@@ -1484,6 +1516,7 @@ RSpec.describe Repository do
end
describe '#expand_ref' do
+ let(:project) { create(:project, :repository) }
let(:ref) { 'ref' }
subject { repository.expand_ref(ref) }
@@ -1520,6 +1553,7 @@ RSpec.describe Repository do
describe '#add_branch' do
let(:branch_name) { 'new_feature' }
let(:target) { 'master' }
+ let(:project) { create(:project, :repository) }
subject { repository.add_branch(user, branch_name, target) }
@@ -1604,6 +1638,8 @@ RSpec.describe Repository do
end
describe '#exists?' do
+ let(:project) { create(:project, :repository) }
+
it 'returns true when a repository exists' do
expect(repository.exists?).to be(true)
end
@@ -1624,6 +1660,8 @@ RSpec.describe Repository do
end
describe '#has_visible_content?' do
+ let(:project) { create(:project, :repository) }
+
it 'delegates to raw_repository when true' do
expect(repository.raw_repository).to receive(:has_visible_content?)
.and_return(true)
@@ -1690,6 +1728,8 @@ RSpec.describe Repository do
end
describe '#branch_names', :clean_gitlab_redis_cache do
+ let_it_be(:project) { create(:project, :repository) }
+
let(:fake_branch_names) { ['foobar'] }
it 'gets cached across Repository instances' do
@@ -1706,6 +1746,7 @@ RSpec.describe Repository do
end
describe '#empty?' do
+ let(:project) { create(:project, :repository) }
let(:empty_repository) { create(:project_empty_repo).repository }
it 'returns true for an empty repository' do
@@ -1752,6 +1793,8 @@ RSpec.describe Repository do
end
describe '#root_ref' do
+ let(:project) { create(:project, :repository) }
+
it 'returns a branch name' do
expect(repository.root_ref).to be_an_instance_of(String)
end
@@ -1792,6 +1835,8 @@ RSpec.describe Repository do
describe '#expire_branch_cache' do
# This method is private but we need it for testing purposes. Sadly there's
# no other proper way of testing caching operations.
+ let_it_be(:project) { create(:project, :repository) }
+
let(:cache) { repository.send(:cache) }
it 'expires the cache for all branches' do
@@ -2003,6 +2048,7 @@ RSpec.describe Repository do
end
describe '#revert' do
+ let(:project) { create(:project, :repository) }
let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
let(:message) { 'revert message' }
@@ -2039,6 +2085,7 @@ RSpec.describe Repository do
end
describe '#cherry_pick' do
+ let(:project) { create(:project, :repository) }
let(:conflict_commit) { repository.commit('c642fe9b8b9f28f9225d7ea953fe14e74748d53b') }
let(:pickable_commit) { repository.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') }
@@ -2174,7 +2221,8 @@ RSpec.describe Repository do
:contribution_guide,
:changelog,
:license_blob,
- :license_key,
+ :license_licensee,
+ :license_gitaly,
:gitignore,
:gitlab_ci_yml,
:branch_names,
@@ -2404,7 +2452,7 @@ RSpec.describe Repository do
end
it 'returns a Gitlab::Git::Tag object' do
- tag = repository.add_tag(user, '8.5', 'master', 'foo')
+ tag = repository.add_tag(user, '8.6', 'master', 'foo')
expect(tag).to be_a(Gitlab::Git::Tag)
end
@@ -2412,12 +2460,14 @@ RSpec.describe Repository do
context 'with an invalid target' do
it 'returns false' do
- expect(repository.add_tag(user, '8.5', 'bar', 'foo')).to be false
+ expect(repository.add_tag(user, '8.7', 'bar', 'foo')).to be false
end
end
end
describe '#rm_branch' do
+ let(:project) { create(:project, :repository) }
+
it 'removes a branch' do
expect(repository).to receive(:before_remove_branch)
expect(repository).to receive(:after_remove_branch)
@@ -2452,6 +2502,8 @@ RSpec.describe Repository do
end
describe '#find_tag' do
+ let_it_be(:project) { create(:project, :repository) }
+
before do
allow(Gitlab::GitalyClient).to receive(:call).and_call_original
end
@@ -2477,6 +2529,8 @@ RSpec.describe Repository do
end
describe '#avatar' do
+ let(:project) { create(:project, :repository) }
+
it 'returns nil if repo does not exist' do
allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository)
@@ -2519,6 +2573,8 @@ RSpec.describe Repository do
end
describe '#xcode_project?' do
+ let(:project) { create(:project, :repository) }
+
before do
allow(repository).to receive(:tree).with(:head).and_return(double(:tree, trees: [tree]))
end
@@ -2654,7 +2710,7 @@ RSpec.describe Repository do
match[1].to_sym if match
end.compact
- expect(Repository::CACHED_METHODS + Repository::MEMOIZED_CACHED_METHODS).to include(*methods)
+ expect(Repository::CACHED_METHODS).to include(*methods)
end
end
@@ -2819,18 +2875,20 @@ RSpec.describe Repository do
describe '#refresh_method_caches' do
it 'refreshes the caches of the given types' do
expect(repository).to receive(:expire_method_caches)
- .with(%i(readme_path license_blob license_key license))
+ .with(%i(readme_path license_blob license_licensee license_gitaly))
expect(repository).to receive(:readme_path)
expect(repository).to receive(:license_blob)
- expect(repository).to receive(:license_key)
- expect(repository).to receive(:license)
+ expect(repository).to receive(:license_licensee)
+ expect(repository).to receive(:license_gitaly)
repository.refresh_method_caches(%i(readme license))
end
end
describe '#gitlab_ci_yml_for' do
+ let(:project) { create(:project, :repository) }
+
before do
repository.create_file(User.last, '.gitlab-ci.yml', 'CONTENT', message: 'Add .gitlab-ci.yml', branch_name: 'master')
end
@@ -2849,7 +2907,7 @@ RSpec.describe Repository do
end
describe '#changelog_config' do
- let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
let(:changelog_config_path) { Gitlab::Changelog::Config::DEFAULT_FILE_PATH }
before do
@@ -2865,6 +2923,7 @@ RSpec.describe Repository do
context 'when there is a changelog_config_path at the commit' do
it 'returns the content' do
expect(repository.changelog_config(repository.commit.sha, changelog_config_path)).to eq('CONTENT')
+ expect(repository.changelog_config(repository.commit.parent.sha, changelog_config_path)).to be_nil
end
end
@@ -2876,6 +2935,8 @@ RSpec.describe Repository do
end
describe '#route_map_for' do
+ let(:project) { create(:project, :repository) }
+
before do
repository.create_file(User.last, '.gitlab/route-map.yml', 'CONTENT', message: 'Add .gitlab/route-map.yml', branch_name: 'master')
end
@@ -3148,7 +3209,6 @@ RSpec.describe Repository do
describe '#create_if_not_exists' do
let(:project) { create(:project) }
- let(:repository) { project.repository }
it 'creates the repository if it did not exist' do
expect { repository.create_if_not_exists }.to change { repository.exists? }.from(false).to(true)
@@ -3204,7 +3264,6 @@ RSpec.describe Repository do
describe '#create_from_bundle' do
let(:project) { create(:project) }
- let(:repository) { project.repository }
let(:valid_bundle_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") }
let(:raw_repository) { repository.raw }
@@ -3244,8 +3303,6 @@ RSpec.describe Repository do
describe "#blobs_metadata" do
let_it_be(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
-
def expect_metadata_blob(thing)
expect(thing).to be_a(Blob)
expect(thing.data).to be_empty
@@ -3313,8 +3370,6 @@ RSpec.describe Repository do
subject { repository.lfs_enabled? }
context 'for a project repository' do
- let(:repository) { project.repository }
-
it 'returns true when LFS is enabled' do
stub_lfs_setting(enabled: true)
@@ -3425,6 +3480,8 @@ RSpec.describe Repository do
end
describe '#change_head' do
+ let_it_be(:project) { create(:project, :repository) }
+
let(:branch) { repository.container.default_branch }
context 'when the branch exists' do
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index 44de83d9240..5087a8e8524 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -144,4 +144,14 @@ RSpec.describe ResourceLabelEvent, type: :model do
create(:resource_label_event, issue: issue, label: label)
end
end
+
+ describe '#discussion_id' do
+ it 'generates different discussion ID for events created milliseconds apart' do
+ now = Time.current
+ event_1 = create(:resource_label_event, issue: issue, label: label, user: issue.author, created_at: now)
+ event_2 = create(:resource_label_event, issue: issue, label: label, user: issue.author, created_at: now.advance(seconds: 0.001))
+
+ expect(event_1.discussion_id).not_to eq(event_2.discussion_id)
+ end
+ end
end
diff --git a/spec/models/user_detail_spec.rb b/spec/models/user_detail_spec.rb
index 9189b9a1469..04964d36dcd 100644
--- a/spec/models/user_detail_spec.rb
+++ b/spec/models/user_detail_spec.rb
@@ -25,5 +25,140 @@ RSpec.describe UserDetail do
describe '#bio' do
it { is_expected.to validate_length_of(:bio).is_at_most(255) }
end
+
+ describe '#linkedin' do
+ it { is_expected.to validate_length_of(:linkedin).is_at_most(500) }
+ end
+
+ describe '#twitter' do
+ it { is_expected.to validate_length_of(:twitter).is_at_most(500) }
+ end
+
+ describe '#skype' do
+ it { is_expected.to validate_length_of(:skype).is_at_most(500) }
+ end
+
+ describe '#location' do
+ it { is_expected.to validate_length_of(:location).is_at_most(500) }
+ end
+
+ describe '#organization' do
+ it { is_expected.to validate_length_of(:organization).is_at_most(500) }
+ end
+
+ describe '#website_url' do
+ it { is_expected.to validate_length_of(:website_url).is_at_most(500) }
+ end
+ end
+
+ describe '.user_fields_changed?' do
+ let(:user) { create(:user) }
+
+ context 'when user detail fields unchanged' do
+ it 'returns false' do
+ expect(described_class.user_fields_changed?(user)).to be false
+ end
+
+ %i[linkedin location organization skype twitter website_url].each do |attr|
+ context "when #{attr} is changed" do
+ before do
+ user[attr] = 'new value'
+ end
+
+ it 'returns true' do
+ expect(described_class.user_fields_changed?(user)).to be true
+ end
+ end
+ end
+ end
+ end
+
+ describe '#sanitize_attrs' do
+ shared_examples 'sanitizes html' do |attr|
+ it 'sanitizes html tags' do
+ details = build_stubbed(:user_detail, attr => '<a href="//evil.com">https://example.com<a>')
+ expect { details.sanitize_attrs }.to change { details[attr] }.to('https://example.com')
+ end
+
+ it 'sanitizes iframe scripts' do
+ details = build_stubbed(:user_detail, attr => '<iframe src=javascript:alert()><iframe>')
+ expect { details.sanitize_attrs }.to change { details[attr] }.to('')
+ end
+
+ it 'sanitizes js scripts' do
+ details = build_stubbed(:user_detail, attr => '<script>alert("Test")</script>')
+ expect { details.sanitize_attrs }.to change { details[attr] }.to('')
+ end
+ end
+
+ %i[linkedin skype twitter website_url].each do |attr|
+ it_behaves_like 'sanitizes html', attr
+
+ it 'encodes HTML entities' do
+ details = build_stubbed(:user_detail, attr => 'test&attr')
+ expect { details.sanitize_attrs }.to change { details[attr] }.to('test&amp;attr')
+ end
+ end
+
+ %i[location organization].each do |attr|
+ it_behaves_like 'sanitizes html', attr
+
+ it 'does not encode HTML entities' do
+ details = build_stubbed(:user_detail, attr => 'test&attr')
+ expect { details.sanitize_attrs }.not_to change { details[attr] }
+ end
+ end
+
+ it 'sanitizes on validation' do
+ details = build(:user_detail)
+
+ expect(details)
+ .to receive(:sanitize_attrs)
+ .at_least(:once)
+ .and_call_original
+
+ details.save!
+ end
+ end
+
+ describe '#assign_changed_fields_from_user' do
+ let(:user_detail) { build(:user_detail) }
+
+ shared_examples 'syncs field with `user_details`' do |field|
+ it 'does not sync the field to `user_details` if unchanged' do
+ expect { user_detail.assign_changed_fields_from_user }
+ .to not_change { user_detail.public_send(field) }
+ end
+
+ it 'syncs the field to `user_details` if changed' do
+ user_detail.user[field] = "new_value"
+ expect { user_detail.assign_changed_fields_from_user }
+ .to change { user_detail.public_send(field) }
+ .to("new_value")
+ end
+
+ it 'truncates the field if too long' do
+ user_detail.user[field] = 'a' * (UserDetail::DEFAULT_FIELD_LENGTH + 1)
+ expect { user_detail.assign_changed_fields_from_user }
+ .to change { user_detail.public_send(field) }
+ .to('a' * UserDetail::DEFAULT_FIELD_LENGTH)
+ end
+
+ it 'properly syncs nil field to `user_details' do
+ user_detail.user[field] = 'Test'
+ user_detail.user.save!(validate: false)
+ user_detail.user[field] = nil
+ expect { user_detail.assign_changed_fields_from_user }
+ .to change { user_detail.public_send(field) }
+ .to('')
+ end
+ end
+
+ it_behaves_like 'syncs field with `user_details`', :linkedin
+ it_behaves_like 'syncs field with `user_details`', :location
+ it_behaves_like 'syncs field with `user_details`', :organization
+ it_behaves_like 'syncs field with `user_details`', :skype
+ it_behaves_like 'syncs field with `user_details`', :twitter
+ it_behaves_like 'syncs field with `user_details`', :website_url
end
end
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index 2492521c634..d76334d7c9e 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -10,20 +10,20 @@ RSpec.describe UserPreference do
using RSpec::Parameterized::TableSyntax
where(color: [
- '#000000',
- '#123456',
- '#abcdef',
- '#AbCdEf',
- '#ffffff',
- '#fFfFfF',
- '#000',
- '#123',
- '#abc',
- '#AbC',
- '#fff',
- '#fFf',
- ''
- ])
+ '#000000',
+ '#123456',
+ '#abcdef',
+ '#AbCdEf',
+ '#ffffff',
+ '#fFfFfF',
+ '#000',
+ '#123',
+ '#abc',
+ '#AbC',
+ '#fff',
+ '#fFf',
+ ''
+ ])
with_them do
it { is_expected.to allow_value(color).for(:diffs_deletion_color) }
@@ -31,20 +31,27 @@ RSpec.describe UserPreference do
end
where(color: [
- '#1',
- '#12',
- '#1234',
- '#12345',
- '#1234567',
- '123456',
- '#12345x'
- ])
+ '#1',
+ '#12',
+ '#1234',
+ '#12345',
+ '#1234567',
+ '123456',
+ '#12345x'
+ ])
with_them do
it { is_expected.not_to allow_value(color).for(:diffs_deletion_color) }
it { is_expected.not_to allow_value(color).for(:diffs_addition_color) }
end
end
+
+ describe 'use_legacy_web_ide' do
+ it { is_expected.to allow_value(true).for(:use_legacy_web_ide) }
+ it { is_expected.to allow_value(false).for(:use_legacy_web_ide) }
+ it { is_expected.not_to allow_value(nil).for(:use_legacy_web_ide) }
+ it { is_expected.not_to allow_value("").for(:use_legacy_web_ide) }
+ end
end
describe 'notes filters global keys' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3cc34681ad6..8ebf3d70165 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -69,12 +69,18 @@ RSpec.describe User do
it { is_expected.to delegate_method(:markdown_surround_selection).to(:user_preference) }
it { is_expected.to delegate_method(:markdown_surround_selection=).to(:user_preference).with_arguments(:args) }
+ it { is_expected.to delegate_method(:markdown_automatic_lists).to(:user_preference) }
+ it { is_expected.to delegate_method(:markdown_automatic_lists=).to(:user_preference).with_arguments(:args) }
+
it { is_expected.to delegate_method(:diffs_deletion_color).to(:user_preference) }
it { is_expected.to delegate_method(:diffs_deletion_color=).to(:user_preference).with_arguments(:args) }
it { is_expected.to delegate_method(:diffs_addition_color).to(:user_preference) }
it { is_expected.to delegate_method(:diffs_addition_color=).to(:user_preference).with_arguments(:args) }
+ it { is_expected.to delegate_method(:use_legacy_web_ide).to(:user_preference) }
+ it { is_expected.to delegate_method(:use_legacy_web_ide=).to(:user_preference).with_arguments(:args) }
+
it { is_expected.to delegate_method(:job_title).to(:user_detail).allow_nil }
it { is_expected.to delegate_method(:job_title=).to(:user_detail).with_arguments(:args).allow_nil }
@@ -101,6 +107,7 @@ RSpec.describe User do
it { is_expected.to have_one(:atlassian_identity) }
it { is_expected.to have_one(:user_highest_role) }
it { is_expected.to have_one(:credit_card_validation) }
+ it { is_expected.to have_one(:phone_number_validation) }
it { is_expected.to have_one(:banned_user) }
it { is_expected.to have_many(:snippets).dependent(:destroy) }
it { is_expected.to have_many(:members) }
@@ -136,7 +143,6 @@ RSpec.describe User do
it { is_expected.to have_many(:timelogs) }
it { is_expected.to have_many(:callouts).class_name('Users::Callout') }
it { is_expected.to have_many(:group_callouts).class_name('Users::GroupCallout') }
- it { is_expected.to have_many(:namespace_callouts).class_name('Users::NamespaceCallout') }
it { is_expected.to have_many(:project_callouts).class_name('Users::ProjectCallout') }
describe '#user_detail' do
@@ -1163,6 +1169,20 @@ RSpec.describe User do
'ORDER BY "users"."last_activity_on" ASC NULLS FIRST, "users"."id" DESC')
end
end
+
+ describe '.order_recent_sign_in' do
+ it 'sorts users by current_sign_in_at in descending order' do
+ expect(described_class.order_recent_sign_in.to_sql).to include(
+ 'ORDER BY "users"."current_sign_in_at" DESC NULLS LAST')
+ end
+ end
+
+ describe '.order_oldest_sign_in' do
+ it 'sorts users by current_sign_in_at in ascending order' do
+ expect(described_class.order_oldest_sign_in.to_sql).to include(
+ 'ORDER BY "users"."current_sign_in_at" ASC NULLS LAST')
+ end
+ end
end
context 'strip attributes' do
@@ -1882,9 +1902,9 @@ RSpec.describe User do
end
it 'ensures correct rights and limits for user' do
- stub_config_setting(default_can_create_group: true)
+ stub_application_setting(can_create_group: true)
- expect { user.update!(external: false) }.to change { user.can_create_group }.to(true)
+ expect { user.update!(external: false) }.to change { user.can_create_group }.from(false).to(true)
.and change { user.projects_limit }.to(Gitlab::CurrentSettings.default_projects_limit)
end
end
@@ -2604,7 +2624,7 @@ RSpec.describe User do
it 'applies defaults to user' do
expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit)
- expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group)
+ expect(user.can_create_group).to eq(Gitlab::CurrentSettings.can_create_group)
expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme)
expect(user.external).to be_falsey
expect(user.private_profile).to eq(false)
@@ -3719,6 +3739,22 @@ RSpec.describe User do
expect(user.followees).to be_empty
end
+
+ it 'does not follow if max followee limit is reached' do
+ stub_const('Users::UserFollowUser::MAX_FOLLOWEE_LIMIT', 2)
+
+ user = create(:user)
+ Users::UserFollowUser::MAX_FOLLOWEE_LIMIT.times { user.follow(create(:user)) }
+
+ followee = create(:user)
+ user_follow_user = user.follow(followee)
+
+ expect(user_follow_user).not_to be_persisted
+ expected_message = format(_("You can't follow more than %{limit} users. To follow more users, unfollow some others."), limit: Users::UserFollowUser::MAX_FOLLOWEE_LIMIT)
+ expect(user_follow_user.errors.messages[:base].first).to eq(expected_message)
+
+ expect(user.following?(followee)).to be_falsey
+ end
end
describe '#unfollow' do
@@ -3747,6 +3783,18 @@ RSpec.describe User do
expect(user.followees).to be_empty
end
+
+ it 'unfollows when over followee limit' do
+ user = create(:user)
+
+ followees = create_list(:user, 4)
+ followees.each { |f| expect(user.follow(f)).to be_truthy }
+
+ stub_const('Users::UserFollowUser::MAX_FOLLOWEE_LIMIT', followees.length - 2)
+
+ expect(user.unfollow(followees.first)).to be_truthy
+ expect(user.following?(followees.first)).to be_falsey
+ end
end
describe '#notification_email_or_default' do
@@ -4838,23 +4886,6 @@ RSpec.describe User do
end
end
- describe '#remove_project_authorizations' do
- let_it_be(:project1) { create(:project) }
- let_it_be(:project2) { create(:project) }
- let_it_be(:project3) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- it 'removes the project authorizations of the user, in specified projects' do
- create(:project_authorization, user: user, project: project1)
- create(:project_authorization, user: user, project: project2)
- create(:project_authorization, user: user, project: project3)
-
- user.remove_project_authorizations([project1.id, project2.id])
-
- expect(user.project_authorizations.pluck(:project_id)).to match_array([project3.id])
- end
- end
-
describe '#access_level=' do
let(:user) { build(:user) }
@@ -5393,6 +5424,41 @@ RSpec.describe User do
end
end
+ describe '#ensure_user_detail_assigned' do
+ let(:user) { build(:user) }
+
+ context 'when no user detail field has been changed' do
+ before do
+ allow(UserDetail)
+ .to receive(:user_fields_changed?)
+ .and_return(false)
+ end
+
+ it 'does not assign user details before save' do
+ expect(user.user_detail)
+ .not_to receive(:assign_changed_fields_from_user)
+
+ user.save!
+ end
+ end
+
+ context 'when a user detail field has been changed' do
+ before do
+ allow(UserDetail)
+ .to receive(:user_fields_changed?)
+ .and_return(true)
+ end
+
+ it 'assigns user details before save' do
+ expect(user.user_detail)
+ .to receive(:assign_changed_fields_from_user)
+ .and_call_original
+
+ user.save!
+ end
+ end
+ end
+
describe '#username_changed_hook' do
context 'for a new user' do
let(:user) { build(:user) }
@@ -6251,6 +6317,64 @@ RSpec.describe User do
it { is_expected.to be_falsey }
end
end
+
+ context 'user with autogenerated_password' do
+ let(:user) { build_stubbed(:user, password_automatically_set: true) }
+ let(:password) { user.password }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#generate_otp_backup_codes!' do
+ let(:user) { create(:user) }
+
+ context 'with FIPS mode', :fips_mode do
+ it 'attempts to use #generate_otp_backup_codes_pbkdf2!' do
+ expect(user).to receive(:generate_otp_backup_codes_pbkdf2!).and_call_original
+
+ user.generate_otp_backup_codes!
+ end
+ end
+
+ context 'outside FIPS mode' do
+ it 'does not attempt to use #generate_otp_backup_codes_pbkdf2!' do
+ expect(user).not_to receive(:generate_otp_backup_codes_pbkdf2!)
+
+ user.generate_otp_backup_codes!
+ end
+ end
+ end
+
+ describe '#invalidate_otp_backup_code!' do
+ let(:user) { create(:user) }
+
+ context 'with FIPS mode', :fips_mode do
+ context 'with a PBKDF2-encrypted password' do
+ let(:encrypted_password) { '$pbkdf2-sha512$20000$boHGAw0hEyI$DBA67J7zNZebyzLtLk2X9wRDbmj1LNKVGnZLYyz6PGrIDGIl45fl/BPH0y1TPZnV90A20i.fD9C3G9Bp8jzzOA' }
+
+ it 'attempts to use #invalidate_otp_backup_code_pdkdf2!' do
+ expect(user).to receive(:otp_backup_codes).at_least(:once).and_return([encrypted_password])
+ expect(user).to receive(:invalidate_otp_backup_code_pdkdf2!).and_return(true)
+
+ user.invalidate_otp_backup_code!(user.password)
+ end
+ end
+
+ it 'does not attempt to use #invalidate_otp_backup_code_pdkdf2!' do
+ expect(user).not_to receive(:invalidate_otp_backup_code_pdkdf2!)
+
+ user.invalidate_otp_backup_code!(user.password)
+ end
+ end
+
+ context 'outside FIPS mode' do
+ it 'does not attempt to use #invalidate_otp_backup_code_pdkdf2!' do
+ expect(user).not_to receive(:invalidate_otp_backup_code_pdkdf2!)
+
+ user.invalidate_otp_backup_code!(user.password)
+ end
+ end
end
# These entire test section can be removed once the :pbkdf2_password_encryption feature flag is removed.
@@ -6593,96 +6717,6 @@ RSpec.describe User do
end
end
- describe 'Users::NamespaceCallout' do
- describe '#dismissed_callout_for_namespace?' do
- let_it_be(:user, refind: true) { create(:user) }
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:feature_name) { Users::NamespaceCallout.feature_names.each_key.first }
-
- let(:query) do
- { feature_name: feature_name, namespace: namespace }
- end
-
- def have_dismissed_callout
- be_dismissed_callout_for_namespace(**query)
- end
-
- context 'when no callout dismissal record exists' do
- it 'returns false when no ignore_dismissal_earlier_than provided' do
- expect(user).not_to have_dismissed_callout
- end
- end
-
- context 'when dismissed callout exists' do
- before_all do
- create(:namespace_callout,
- user: user,
- namespace_id: namespace.id,
- feature_name: feature_name,
- dismissed_at: 4.months.ago)
- end
-
- it 'returns true when no ignore_dismissal_earlier_than provided' do
- expect(user).to have_dismissed_callout
- end
-
- it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do
- query[:ignore_dismissal_earlier_than] = 6.months.ago
-
- expect(user).to have_dismissed_callout
- end
-
- it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do
- query[:ignore_dismissal_earlier_than] = 2.months.ago
-
- expect(user).not_to have_dismissed_callout
- end
- end
- end
-
- describe '#find_or_initialize_namespace_callout' do
- let_it_be(:user, refind: true) { create(:user) }
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:feature_name) { Users::NamespaceCallout.feature_names.each_key.first }
-
- subject(:callout_with_source) do
- user.find_or_initialize_namespace_callout(feature_name, namespace.id)
- end
-
- context 'when callout exists' do
- let!(:callout) do
- create(:namespace_callout, user: user, feature_name: feature_name, namespace_id: namespace.id)
- end
-
- it 'returns existing callout' do
- expect(callout_with_source).to eq(callout)
- end
- end
-
- context 'when callout does not exist' do
- context 'when feature name is valid' do
- it 'initializes a new callout' do
- expect(callout_with_source)
- .to be_a_new(Users::NamespaceCallout)
- .and be_valid
- end
- end
-
- context 'when feature name is not valid' do
- let(:feature_name) { 'notvalid' }
-
- it 'initializes a new callout' do
- expect(callout_with_source).to be_a_new(Users::NamespaceCallout)
- end
-
- it 'is not valid' do
- expect(callout_with_source).not_to be_valid
- end
- end
- end
- end
- end
-
describe '#dismissed_callout_for_group?' do
let_it_be(:user, refind: true) { create(:user) }
let_it_be(:group) { create(:group) }
@@ -7432,9 +7466,10 @@ RSpec.describe User do
let_it_be(:internal_user) { User.alert_bot.tap { |u| u.confirm } }
it 'does not return blocked or banned users' do
- expect(described_class.without_forbidden_states).to match_array([
- normal_user, admin_user, external_user, unconfirmed_user, omniauth_user, internal_user
- ])
+ expect(described_class.without_forbidden_states).to match_array(
+ [
+ normal_user, admin_user, external_user, unconfirmed_user, omniauth_user, internal_user
+ ])
end
end
diff --git a/spec/models/users/namespace_callout_spec.rb b/spec/models/users/namespace_callout_spec.rb
deleted file mode 100644
index f8207f2abc8..00000000000
--- a/spec/models/users/namespace_callout_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Users::NamespaceCallout do
- let_it_be(:user) { create_default(:user) }
- let_it_be(:namespace) { create_default(:namespace) }
- let_it_be(:callout) { create(:namespace_callout) }
-
- it_behaves_like 'having unique enum values'
-
- describe 'relationships' do
- it { is_expected.to belong_to(:namespace) }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:namespace) }
- it { is_expected.to validate_presence_of(:user) }
- it { is_expected.to validate_presence_of(:feature_name) }
-
- specify do
- is_expected.to validate_uniqueness_of(:feature_name)
- .scoped_to(:user_id, :namespace_id)
- .ignoring_case_sensitivity
- end
-
- it { is_expected.to allow_value(:web_hook_disabled).for(:feature_name) }
-
- it 'rejects invalid feature names' do
- expect { callout.feature_name = :non_existent_feature }.to raise_error(ArgumentError)
- end
- end
-
- describe '#source_feature_name' do
- it 'provides string based off source and feature' do
- expect(callout.source_feature_name).to eq "#{callout.feature_name}_#{callout.namespace_id}"
- end
- end
-end
diff --git a/spec/models/users/phone_number_validation_spec.rb b/spec/models/users/phone_number_validation_spec.rb
new file mode 100644
index 00000000000..2f0fd1d3ac9
--- /dev/null
+++ b/spec/models/users/phone_number_validation_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::PhoneNumberValidation do
+ it { is_expected.to belong_to(:user) }
+ it { is_expected.to belong_to(:banned_user) }
+
+ it { is_expected.to validate_presence_of(:country) }
+ it { is_expected.to validate_length_of(:country).is_at_most(3) }
+
+ it { is_expected.to validate_presence_of(:international_dial_code) }
+
+ it {
+ is_expected.to validate_numericality_of(:international_dial_code)
+ .only_integer
+ .is_greater_than_or_equal_to(1)
+ .is_less_than_or_equal_to(999)
+ }
+
+ it { is_expected.to validate_presence_of(:phone_number) }
+ it { is_expected.to validate_length_of(:phone_number).is_at_most(12) }
+ it { is_expected.to allow_value('555555').for(:phone_number) }
+ it { is_expected.not_to allow_value('555-555').for(:phone_number) }
+ it { is_expected.not_to allow_value('+555555').for(:phone_number) }
+ it { is_expected.not_to allow_value('555 555').for(:phone_number) }
+
+ it { is_expected.to validate_length_of(:telesign_reference_xid).is_at_most(255) }
+
+ describe '.related_to_banned_user?' do
+ let_it_be(:international_dial_code) { 1 }
+ let_it_be(:phone_number) { '555' }
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:banned_user) { create(:user, :banned) }
+
+ subject(:related_to_banned_user?) do
+ described_class.related_to_banned_user?(international_dial_code, phone_number)
+ end
+
+ context 'when banned user has the same international dial code and phone number' do
+ before do
+ create(:phone_number_validation, user: banned_user)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when banned user has the same international dial code and phone number, but different country code' do
+ before do
+ create(:phone_number_validation, user: banned_user, country: 'CA')
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when banned user does not have the same international dial code' do
+ before do
+ create(:phone_number_validation, user: banned_user, international_dial_code: 61)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when banned user does not have the same phone number' do
+ before do
+ create(:phone_number_validation, user: banned_user, phone_number: '666')
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when not-banned user has the same international dial code and phone number' do
+ before do
+ create(:phone_number_validation, user: user)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+end
diff --git a/spec/models/wiki_directory_spec.rb b/spec/models/wiki_directory_spec.rb
index 9b6cec99ddb..44c6f6c9c1a 100644
--- a/spec/models/wiki_directory_spec.rb
+++ b/spec/models/wiki_directory_spec.rb
@@ -24,31 +24,32 @@ RSpec.describe WikiDirectory do
[toplevel1, toplevel2, toplevel3, child1, child2, child3, grandchild1, grandchild2].sort_by(&:title)
)
- expect(entries).to match([
- toplevel1,
- a_kind_of(WikiDirectory).and(
- having_attributes(
- slug: 'parent1', entries: [
- child1,
- child2,
- a_kind_of(WikiDirectory).and(
- having_attributes(
- slug: 'parent1/subparent',
- entries: [grandchild1, grandchild2]
+ expect(entries).to match(
+ [
+ toplevel1,
+ a_kind_of(WikiDirectory).and(
+ having_attributes(
+ slug: 'parent1', entries: [
+ child1,
+ child2,
+ a_kind_of(WikiDirectory).and(
+ having_attributes(
+ slug: 'parent1/subparent',
+ entries: [grandchild1, grandchild2]
+ )
)
- )
- ]
- )
- ),
- a_kind_of(WikiDirectory).and(
- having_attributes(
- slug: 'parent2',
- entries: [child3]
- )
- ),
- toplevel2,
- toplevel3
- ])
+ ]
+ )
+ ),
+ a_kind_of(WikiDirectory).and(
+ having_attributes(
+ slug: 'parent2',
+ entries: [child3]
+ )
+ ),
+ toplevel2,
+ toplevel3
+ ])
end
end
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index 96c396f085c..fcb041aebe5 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -3,27 +3,24 @@
require "spec_helper"
RSpec.describe WikiPage do
- let_it_be(:user) { create(:user) }
- let_it_be(:container) { create(:project) }
+ let(:user) { create(:user) }
+ let(:container) { create(:project) }
+ let(:wiki) { container.wiki }
- def create_wiki_page(attrs = {})
- page = build_wiki_page(attrs)
+ def create_wiki_page(container, attrs = {})
+ page = build_wiki_page(container, attrs)
page.create(message: (attrs[:message] || 'test commit'))
container.wiki.find_page(page.slug)
end
- def build_wiki_page(attrs = {})
+ def build_wiki_page(container, attrs = {})
wiki_page_attrs = { container: container, content: 'test content' }.merge(attrs)
build(:wiki_page, wiki_page_attrs)
end
- def wiki
- container.wiki
- end
-
def disable_front_matter
stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => false)
end
@@ -32,11 +29,20 @@ RSpec.describe WikiPage do
stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => thing)
end
+ def force_wiki_change_branch
+ old_default_branch = wiki.default_branch
+ wiki.repository.add_branch(user, 'another_branch', old_default_branch)
+ wiki.repository.rm_branch(user, old_default_branch)
+ wiki.repository.expire_status_cache
+
+ wiki.container.clear_memoization(:wiki)
+ end
+
# Use for groups of tests that do not modify their `subject`.
#
# include_context 'subject is persisted page', title: 'my title'
shared_context 'subject is persisted page' do |attrs = {}|
- let_it_be(:persisted_page) { create_wiki_page(attrs) }
+ let(:persisted_page) { create_wiki_page(container, attrs) }
subject { persisted_page }
end
@@ -192,7 +198,7 @@ RSpec.describe WikiPage do
end
describe "validations" do
- subject { build_wiki_page }
+ subject { build_wiki_page(container) }
it "validates presence of title" do
subject.attributes.delete(:title)
@@ -357,7 +363,7 @@ RSpec.describe WikiPage do
let(:title) { attributes[:title] }
- subject { build_wiki_page }
+ subject { build_wiki_page(container) }
context "with valid attributes" do
it "saves the wiki page" do
@@ -394,7 +400,7 @@ RSpec.describe WikiPage do
let(:title) { 'Index v1.2.3' }
describe "#create" do
- subject { build_wiki_page }
+ subject { build_wiki_page(container) }
it "saves the wiki page and returns true", :aggregate_failures do
attributes = { title: title, content: "Home Page", format: "markdown" }
@@ -405,7 +411,7 @@ RSpec.describe WikiPage do
end
describe '#update' do
- subject { create_wiki_page(title: title) }
+ subject { create_wiki_page(container, title: title) }
it 'updates the content of the page and returns true', :aggregate_failures do
expect(subject.update(content: 'new content')).to be_truthy
@@ -420,7 +426,7 @@ RSpec.describe WikiPage do
describe "#update" do
let!(:original_title) { subject.title }
- subject { create_wiki_page }
+ subject { create_wiki_page(container) }
context "with valid attributes" do
it "updates the content of the page" do
@@ -527,7 +533,7 @@ RSpec.describe WikiPage do
describe 'in subdir' do
it 'keeps the page in the same dir when the content is updated' do
title = 'foo/Existing Page'
- page = create_wiki_page(title: title)
+ page = create_wiki_page(container, title: title)
expect(page.slug).to eq 'foo/Existing-Page'
expect(page.update(title: title, content: 'new_content')).to be_truthy
@@ -541,7 +547,7 @@ RSpec.describe WikiPage do
context 'when renaming a page' do
it 'raises an error if the page already exists' do
- existing_page = create_wiki_page
+ existing_page = create_wiki_page(container)
expect { subject.update(title: existing_page.title, content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
expect(subject.title).to eq original_title
@@ -584,7 +590,7 @@ RSpec.describe WikiPage do
describe 'in subdir' do
it 'moves the page to the root folder if the title is preceded by /' do
- page = create_wiki_page(title: 'foo/Existing Page')
+ page = create_wiki_page(container, title: 'foo/Existing Page')
expect(page.slug).to eq 'foo/Existing-Page'
expect(page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
@@ -592,7 +598,7 @@ RSpec.describe WikiPage do
end
it 'does nothing if it has the same title' do
- page = create_wiki_page(title: 'foo/Another Existing Page')
+ page = create_wiki_page(container, title: 'foo/Another Existing Page')
original_path = page.slug
@@ -625,7 +631,7 @@ RSpec.describe WikiPage do
describe "#delete" do
it "deletes the page and returns true", :aggregate_failures do
- page = create_wiki_page
+ page = create_wiki_page(container)
expect do
expect(page.delete).to eq(true)
@@ -634,22 +640,88 @@ RSpec.describe WikiPage do
end
describe "#versions" do
- let(:subject) { create_wiki_page }
+ let(:subject) { create_wiki_page(container) }
+
+ before do
+ 3.times { |i| subject.update(content: "content #{i}") }
+ end
+
+ context 'number of versions is less than the default paginiated per page' do
+ it "returns an array of all commits for the page" do
+ expect(subject.versions).to be_a(::CommitCollection)
+ expect(subject.versions.length).to eq(4)
+ expect(subject.versions.first.id).to eql(subject.last_version.id)
+ end
+ end
+
+ context 'number of versions is more than the default paginiated per page' do
+ before do
+ allow(Kaminari.config).to receive(:default_per_page).and_return(3)
+ end
+
+ it "returns an arrary containing the first page of commits for the page" do
+ expect(subject.versions).to be_a(::CommitCollection)
+ expect(subject.versions.length).to eq(3)
+ expect(subject.versions.first.id).to eql(subject.last_version.id)
+ end
+
+ it "returns an arrary containing the second page of commits for the page with options[:page] = 2" do
+ versions = subject.versions(page: 2)
+ expect(versions).to be_a(::CommitCollection)
+ expect(versions.length).to eq(1)
+ end
+ end
+
+ context "wiki repository's default is updated" do
+ before do
+ force_wiki_change_branch
+ end
+
+ it "returns the correct versions in the default branch" do
+ page = container.wiki.find_page(subject.title)
- it "returns an array of all commits for the page" do
+ expect(page.versions).to be_a(::CommitCollection)
+ expect(page.versions.length).to eq(4)
+ expect(page.versions.first.id).to eql(page.last_version.id)
+
+ page.update(content: "final content")
+ expect(page.versions.length).to eq(5)
+ end
+ end
+ end
+
+ describe "#count_versions" do
+ let(:subject) { create_wiki_page(container) }
+
+ it "returns the total numbers of commits" do
expect do
3.times { |i| subject.update(content: "content #{i}") }
- end.to change { subject.versions.count }.by(3)
+ end.to change(subject, :count_versions).from(1).to(4)
+ end
+
+ context "wiki repository's default is updated" do
+ before do
+ subject
+ force_wiki_change_branch
+ end
+
+ it "returns the correct number of versions in the default branch" do
+ page = container.wiki.find_page(subject.title)
+ expect(page.count_versions).to eq(1)
+
+ page.update(content: "final content")
+ expect(page.count_versions).to eq(2)
+ end
end
end
describe '#title_changed?' do
using RSpec::Parameterized::TableSyntax
- let_it_be(:unsaved_page) { build_wiki_page(title: 'test page') }
- let_it_be(:existing_page) { create_wiki_page(title: 'test page') }
- let_it_be(:directory_page) { create_wiki_page(title: 'parent directory/child page') }
- let_it_be(:page_with_special_characters) { create_wiki_page(title: 'test+page') }
+ let(:unsaved_page) { build_wiki_page(container, title: 'test page') }
+ let(:existing_page) { create_wiki_page(container, title: 'test page') }
+ let(:directory_page) { create_wiki_page(container, title: 'parent directory/child page') }
+ let(:page_with_special_characters) { create_wiki_page(container, title: 'test+page') }
let(:untitled_page) { described_class.new(wiki) }
@@ -704,7 +776,7 @@ RSpec.describe WikiPage do
describe '#content_changed?' do
context 'with a new page' do
- subject { build_wiki_page }
+ subject { build_wiki_page(container) }
it 'returns true if content is set' do
subject.attributes[:content] = 'new'
@@ -756,13 +828,13 @@ RSpec.describe WikiPage do
describe '#path' do
it 'returns the path when persisted' do
- existing_page = create_wiki_page(title: 'path test')
+ existing_page = create_wiki_page(container, title: 'path test')
expect(existing_page.path).to eq('path-test.md')
end
it 'returns nil when not persisted' do
- unsaved_page = build_wiki_page(title: 'path test')
+ unsaved_page = build_wiki_page(container, title: 'path test')
expect(unsaved_page.path).to be_nil
end
@@ -789,7 +861,7 @@ RSpec.describe WikiPage do
describe '#historical?' do
let!(:container) { create(:project) }
- subject { create_wiki_page }
+ subject { create_wiki_page(container) }
let(:wiki) { subject.wiki }
let(:old_version) { subject.versions.last.id }
@@ -830,17 +902,17 @@ RSpec.describe WikiPage do
describe '#persisted?' do
it 'returns true for a persisted page' do
- expect(create_wiki_page).to be_persisted
+ expect(create_wiki_page(container)).to be_persisted
end
it 'returns false for an unpersisted page' do
- expect(build_wiki_page).not_to be_persisted
+ expect(build_wiki_page(container)).not_to be_persisted
end
end
describe '#to_partial_path' do
it 'returns the relative path to the partial to be used' do
- expect(build_wiki_page.to_partial_path).to eq('../shared/wikis/wiki_page')
+ expect(build_wiki_page(container).to_partial_path).to eq('../shared/wikis/wiki_page')
end
end
@@ -868,7 +940,7 @@ RSpec.describe WikiPage do
end
it 'returns false for page with different slug on same container' do
- other_page = create_wiki_page
+ other_page = create_wiki_page(container)
expect(subject.slug).not_to eq(other_page.slug)
expect(subject.container).to eq(other_page.container)
@@ -902,7 +974,7 @@ RSpec.describe WikiPage do
end
describe '#hook_attrs' do
- subject { build_wiki_page }
+ subject { build_wiki_page(container) }
it 'adds absolute urls for images in the content' do
subject.attributes[:content] = 'test![WikiPage_Image](/uploads/abc/WikiPage_Image.png)'
@@ -914,13 +986,13 @@ RSpec.describe WikiPage do
describe '#version_commit_timestamp' do
context 'for a new page' do
it 'returns nil' do
- expect(build_wiki_page.version_commit_timestamp).to be_nil
+ expect(build_wiki_page(container).version_commit_timestamp).to be_nil
end
end
context 'for page that exists' do
it 'returns the timestamp of the commit' do
- existing_page = create_wiki_page
+ existing_page = create_wiki_page(container)
expect(existing_page.version_commit_timestamp).to eq(existing_page.version.commit.committed_date)
end
diff --git a/spec/policies/blob_policy_spec.rb b/spec/policies/blob_policy_spec.rb
index 1be2318a0fe..c1df4e66677 100644
--- a/spec/policies/blob_policy_spec.rb
+++ b/spec/policies/blob_policy_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe BlobPolicy do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
+ include UserHelpers
let_it_be_with_reload(:project) { create(:project, :repository) }
diff --git a/spec/policies/ci/runner_policy_spec.rb b/spec/policies/ci/runner_policy_spec.rb
index 880ff0722fa..773d3d9a01d 100644
--- a/spec/policies/ci/runner_policy_spec.rb
+++ b/spec/policies/ci/runner_policy_spec.rb
@@ -6,42 +6,64 @@ RSpec.describe Ci::RunnerPolicy do
describe 'ability :read_runner' do
let_it_be(:guest) { create(:user) }
let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
let_it_be(:owner) { create(:user) }
- let_it_be(:group1) { create(:group, name: 'top-level', path: 'top-level') }
- let_it_be(:subgroup1) { create(:group, name: 'subgroup1', path: 'subgroup1', parent: group1) }
- let_it_be(:project1) { create(:project, group: subgroup1) }
+ let_it_be_with_reload(:group) { create(:group, name: 'top-level', path: 'top-level') }
+ let_it_be_with_reload(:subgroup) { create(:group, name: 'subgroup', path: 'subgroup', parent: group) }
+ let_it_be_with_reload(:project) { create(:project, group: subgroup) }
+
let_it_be(:instance_runner) { create(:ci_runner, :instance) }
- let_it_be(:group1_runner) { create(:ci_runner, :group, groups: [group1]) }
- let_it_be(:project1_runner) { create(:ci_runner, :project, projects: [project1]) }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) }
subject(:policy) { described_class.new(user, runner) }
- before do
- group1.add_guest(guest)
- group1.add_developer(developer)
- group1.add_owner(owner)
+ before_all do
+ group.add_guest(guest)
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ group.add_owner(owner)
end
- shared_context 'on hierarchy with shared runners disabled' do
- around do |example|
- group1.update!(shared_runners_enabled: false)
- project1.update!(shared_runners_enabled: false)
+ shared_examples 'a policy allowing reading instance runner depending on runner sharing' do
+ context 'with instance runner' do
+ let(:runner) { instance_runner }
+
+ it { expect_allowed :read_runner }
+
+ context 'with shared runners disabled on projects' do
+ before do
+ project.update!(shared_runners_enabled: false)
+ end
+
+ it { expect_allowed :read_runner }
+ end
- example.run
- ensure
- project1.update!(shared_runners_enabled: true)
- group1.update!(shared_runners_enabled: true)
+ context 'with shared runners disabled for groups and projects' do
+ before do
+ group.update!(shared_runners_enabled: false)
+ project.update!(shared_runners_enabled: false)
+ end
+
+ it { expect_disallowed :read_runner }
+ end
end
end
- shared_context 'on hierarchy with group runners disabled' do
- around do |example|
- project1.update!(group_runners_enabled: false)
+ shared_examples 'a policy allowing reading group runner depending on runner sharing' do
+ context 'with group runner' do
+ let(:runner) { group_runner }
+
+ it { expect_allowed :read_runner }
- example.run
- ensure
- project1.update!(group_runners_enabled: true)
+ context 'with sharing of group runners disabled' do
+ before do
+ project.update!(group_runners_enabled: false)
+ end
+
+ it { expect_disallowed :read_runner }
+ end
end
end
@@ -51,27 +73,32 @@ RSpec.describe Ci::RunnerPolicy do
it { expect_disallowed :read_runner }
- context 'with shared runners disabled' do
- include_context 'on hierarchy with shared runners disabled' do
- it { expect_disallowed :read_runner }
+ context 'with shared runners disabled for groups and projects' do
+ before do
+ group.update!(shared_runners_enabled: false)
+ project.update!(shared_runners_enabled: false)
end
+
+ it { expect_disallowed :read_runner }
end
end
context 'with group runner' do
- let(:runner) { group1_runner }
+ let(:runner) { group_runner }
it { expect_disallowed :read_runner }
- context 'with group runner disabled' do
- include_context 'on hierarchy with group runners disabled' do
- it { expect_disallowed :read_runner }
+ context 'with sharing of group runners disabled' do
+ before do
+ project.update!(group_runners_enabled: false)
end
+
+ it { expect_disallowed :read_runner }
end
end
context 'with project runner' do
- let(:runner) { project1_runner }
+ let(:runner) { project_runner }
it { expect_disallowed :read_runner }
end
@@ -92,66 +119,52 @@ RSpec.describe Ci::RunnerPolicy do
context 'with developer access' do
let(:user) { developer }
- context 'with instance runner' do
- let(:runner) { instance_runner }
+ it_behaves_like 'a policy allowing reading instance runner depending on runner sharing'
- it { expect_allowed :read_runner }
+ it_behaves_like 'a policy allowing reading group runner depending on runner sharing'
- context 'with shared runners disabled' do
- include_context 'on hierarchy with shared runners disabled' do
- it { expect_disallowed :read_runner }
- end
- end
+ context 'with project runner' do
+ let(:runner) { project_runner }
+
+ it { expect_disallowed :read_runner }
end
+ end
- context 'with group runner' do
- let(:runner) { group1_runner }
+ context 'with maintainer access' do
+ let(:user) { maintainer }
- it { expect_allowed :read_runner }
+ it_behaves_like 'a policy allowing reading instance runner depending on runner sharing'
- context 'with group runner disabled' do
- include_context 'on hierarchy with group runners disabled' do
- it { expect_disallowed :read_runner }
- end
- end
- end
+ it_behaves_like 'a policy allowing reading group runner depending on runner sharing'
context 'with project runner' do
- let(:runner) { project1_runner }
+ let(:runner) { project_runner }
- it { expect_disallowed :read_runner }
+ it { expect_allowed :read_runner }
end
end
context 'with owner access' do
let(:user) { owner }
- context 'with instance runner' do
- let(:runner) { instance_runner }
+ it_behaves_like 'a policy allowing reading instance runner depending on runner sharing'
- context 'with shared runners disabled' do
- include_context 'on hierarchy with shared runners disabled' do
- it { expect_disallowed :read_runner }
- end
- end
+ context 'with group runner' do
+ let(:runner) { group_runner }
it { expect_allowed :read_runner }
- end
- context 'with group runner' do
- let(:runner) { group1_runner }
-
- context 'with group runners disabled' do
- include_context 'on hierarchy with group runners disabled' do
- it { expect_allowed :read_runner }
+ context 'with sharing of group runners disabled' do
+ before do
+ project.update!(group_runners_enabled: false)
end
- end
- it { expect_allowed :read_runner }
+ it { expect_allowed :read_runner }
+ end
end
context 'with project runner' do
- let(:runner) { project1_runner }
+ let(:runner) { project_runner }
it { expect_allowed :read_runner }
end
diff --git a/spec/policies/concerns/crud_policy_helpers_spec.rb b/spec/policies/concerns/crud_policy_helpers_spec.rb
index 69bf9ad12d6..1e7b99178c3 100644
--- a/spec/policies/concerns/crud_policy_helpers_spec.rb
+++ b/spec/policies/concerns/crud_policy_helpers_spec.rb
@@ -17,34 +17,37 @@ RSpec.describe CrudPolicyHelpers do
describe '.create_read_update_admin_destroy' do
it 'returns an array of the appropriate abilites given a feature name' do
- expect(PolicyTestClass.create_read_update_admin_destroy(feature_name)).to eq([
- :read_foo,
- :create_foo,
- :update_foo,
- :admin_foo,
- :destroy_foo
- ])
+ expect(PolicyTestClass.create_read_update_admin_destroy(feature_name)).to eq(
+ [
+ :read_foo,
+ :create_foo,
+ :update_foo,
+ :admin_foo,
+ :destroy_foo
+ ])
end
end
describe '.create_update_admin_destroy' do
it 'returns an array of the appropriate abilites given a feature name' do
- expect(PolicyTestClass.create_update_admin_destroy(feature_name)).to eq([
- :create_foo,
- :update_foo,
- :admin_foo,
- :destroy_foo
- ])
+ expect(PolicyTestClass.create_update_admin_destroy(feature_name)).to eq(
+ [
+ :create_foo,
+ :update_foo,
+ :admin_foo,
+ :destroy_foo
+ ])
end
end
describe '.create_update_admin' do
it 'returns an array of the appropriate abilites given a feature name' do
- expect(PolicyTestClass.create_update_admin(feature_name)).to eq([
- :create_foo,
- :update_foo,
- :admin_foo
- ])
+ expect(PolicyTestClass.create_update_admin(feature_name)).to eq(
+ [
+ :create_foo,
+ :update_foo,
+ :admin_foo
+ ])
end
end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index da0270c15b9..c65933c5208 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -1175,28 +1175,14 @@ RSpec.describe GroupPolicy do
let(:current_user) { admin }
context 'when admin mode is enabled', :enable_admin_mode 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
+ it { is_expected.to be_allowed(:register_group_runners) }
- context 'with runner_registration_control FF enabled' do
+ context 'with group runner registration disabled' do
before do
- stub_feature_flags(runner_registration_control: true)
+ stub_application_setting(valid_runner_registrars: ['project'])
end
it { is_expected.to be_allowed(:register_group_runners) }
-
- context 'with group runner registration disabled' do
- before do
- stub_application_setting(valid_runner_registrars: ['project'])
- end
-
- it { is_expected.to be_allowed(:register_group_runners) }
- end
end
end
@@ -1210,28 +1196,12 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_allowed(:register_group_runners) }
- 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
+ context 'with group runner registration disabled' do
before do
- stub_feature_flags(runner_registration_control: true)
+ stub_application_setting(valid_runner_registrars: ['project'])
end
- it { is_expected.to be_allowed(:register_group_runners) }
-
- 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
+ it { is_expected.to be_disallowed(:register_group_runners) }
end
end
@@ -1266,6 +1236,62 @@ RSpec.describe GroupPolicy do
end
end
+ describe 'read_group_all_available_runners' do
+ context 'admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ specify { is_expected.to be_allowed(:read_group_all_available_runners) }
+ end
+
+ context 'when admin mode is disabled' do
+ specify { is_expected.to be_disallowed(:read_group_all_available_runners) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ specify { is_expected.to be_allowed(:read_group_all_available_runners) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ specify { is_expected.to be_allowed(:read_group_all_available_runners) }
+ end
+
+ context 'with developer' do
+ let(:current_user) { developer }
+
+ specify { is_expected.to be_allowed(:read_group_all_available_runners) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ specify { is_expected.to be_disallowed(:read_group_all_available_runners) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ specify { is_expected.to be_disallowed(:read_group_all_available_runners) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ specify { is_expected.to be_disallowed(:read_group_all_available_runners) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ specify { is_expected.to be_disallowed(:read_group_all_available_runners) }
+ end
+ end
+
describe 'change_prevent_sharing_groups_outside_hierarchy' do
context 'with owner' do
let(:current_user) { owner }
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index c02294571ff..2bedcf60539 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -31,8 +31,8 @@ RSpec.describe IssuablePolicy, models: true do
expect(policies).to be_allowed(:resolve_note)
end
- it 'allows reading confidential notes' do
- expect(policies).to be_allowed(:read_confidential_notes)
+ it 'allows reading internal notes' do
+ expect(policies).to be_allowed(:read_internal_note)
end
context 'when user is able to read project' do
@@ -94,8 +94,8 @@ RSpec.describe IssuablePolicy, models: true do
let(:issue) { create(:issue, project: project, assignees: [user]) }
let(:policies) { described_class.new(user, issue) }
- it 'allows reading confidential notes' do
- expect(policies).to be_allowed(:read_confidential_notes)
+ it 'allows reading internal notes' do
+ expect(policies).to be_allowed(:read_internal_note)
end
end
@@ -145,6 +145,10 @@ RSpec.describe IssuablePolicy, models: true do
it 'does not allow timelogs creation' do
expect(policies).to be_disallowed(:create_timelog)
end
+
+ it 'does not allow reading internal notes' do
+ expect(permissions(guest, issue)).to be_disallowed(:read_internal_note)
+ end
end
context 'when user is a guest member of the project' do
@@ -152,8 +156,8 @@ RSpec.describe IssuablePolicy, models: true do
expect(permissions(guest, issue)).to be_disallowed(:create_timelog)
end
- it 'does not allow reading confidential notes' do
- expect(permissions(guest, issue)).to be_disallowed(:read_confidential_notes)
+ it 'does not allow reading internal notes' do
+ expect(permissions(guest, issue)).to be_disallowed(:read_internal_note)
end
end
@@ -170,8 +174,8 @@ RSpec.describe IssuablePolicy, models: true do
expect(permissions(reporter, issue)).to be_allowed(:create_timelog)
end
- it 'allows reading confidential notes' do
- expect(permissions(reporter, issue)).to be_allowed(:read_confidential_notes)
+ it 'allows reading internal notes' do
+ expect(permissions(reporter, issue)).to be_allowed(:read_internal_note)
end
end
@@ -188,6 +192,7 @@ RSpec.describe IssuablePolicy, models: true do
it 'does not allow :read_issuable' do
expect(policy).not_to be_allowed(:read_issuable)
+ expect(policy).not_to be_allowed(:read_issuable_participables)
end
end
@@ -196,6 +201,7 @@ RSpec.describe IssuablePolicy, models: true do
it 'allows :read_issuable' do
expect(policy).to be_allowed(:read_issuable)
+ expect(policy).to be_allowed(:read_issuable_participables)
end
end
end
@@ -213,6 +219,7 @@ RSpec.describe IssuablePolicy, models: true do
it 'does not allow :read_issuable' do
expect(policy).not_to be_allowed(:read_issuable)
+ expect(policy).not_to be_allowed(:read_issuable_participables)
end
end
@@ -221,6 +228,7 @@ RSpec.describe IssuablePolicy, models: true do
it 'allows :read_issuable' do
expect(policy).to be_allowed(:read_issuable)
+ expect(policy).to be_allowed(:read_issuable_participables)
end
end
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 4d492deb54c..c110ca705bd 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe IssuePolicy do
include_context 'ProjectPolicyTable context'
include ExternalAuthorizationServiceHelpers
include ProjectHelpers
+ include UserHelpers
let(:guest) { create(:user) }
let(:author) { create(:user) }
@@ -84,7 +85,7 @@ RSpec.describe IssuePolicy do
it 'allows guests to read issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
+ expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :mark_note_as_confidential)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
@@ -92,10 +93,10 @@ RSpec.describe IssuePolicy do
expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality)
end
- it 'allows reporters to read, update, and admin issues' do
+ it 'allows reporters to read, update, admin and create confidential notes' do
expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
- expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality)
+ expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality, :mark_note_as_confidential)
end
it 'allows reporters from group links to read, update, and admin issues' do
diff --git a/spec/policies/namespaces/user_namespace_policy_spec.rb b/spec/policies/namespaces/user_namespace_policy_spec.rb
index 22c3f6a6d67..42d27d0f3d6 100644
--- a/spec/policies/namespaces/user_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/user_namespace_policy_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Namespaces::UserNamespacePolicy do
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, :admin_package] }
+ let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects, :admin_package, :read_billing, :edit_billing] }
subject { described_class.new(current_user, namespace) }
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index fefd9f71408..40ee2e662b2 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -103,6 +103,20 @@ RSpec.describe ProjectPolicy do
end
end
+ context 'when both issues and merge requests are disabled' do
+ let(:current_user) { owner }
+
+ before do
+ project.issues_enabled = false
+ project.merge_requests_enabled = false
+ project.save!
+ end
+
+ it 'does not include the issues permissions' do
+ expect_disallowed :read_cycle_analytics
+ end
+ end
+
context 'creating_merge_request_in' do
context 'when the current_user can download_code' do
before do
@@ -465,15 +479,14 @@ RSpec.describe ProjectPolicy do
end
context 'owner access' do
- let!(:owner_user) { create(:user) }
- let!(:owner_of_different_thing) { create(:user) }
- let(:stranger) { create(:user) }
+ let_it_be(:owner_user) { owner }
+ let_it_be(:owner_of_different_thing) { create(:user) }
context 'personal project' do
- let!(:project) { create(:project) }
- let!(:project2) { create(:project) }
+ let_it_be(:project) { private_project }
+ let_it_be(:project2) { create(:project) }
- before do
+ before_all do
project.add_guest(guest)
project.add_reporter(reporter)
project.add_developer(developer)
@@ -483,7 +496,7 @@ RSpec.describe ProjectPolicy do
it 'allows owner access', :aggregate_failures do
expect(described_class.new(owner_of_different_thing, project)).to be_disallowed(:owner_access)
- expect(described_class.new(stranger, project)).to be_disallowed(:owner_access)
+ expect(described_class.new(non_member, project)).to be_disallowed(:owner_access)
expect(described_class.new(guest, project)).to be_disallowed(:owner_access)
expect(described_class.new(reporter, project)).to be_disallowed(:owner_access)
expect(described_class.new(developer, project)).to be_disallowed(:owner_access)
@@ -493,12 +506,12 @@ RSpec.describe ProjectPolicy do
end
context 'group project' do
- let(:group) { create(:group) }
- let!(:group2) { create(:group) }
- let!(:project) { create(:project, group: group) }
+ let_it_be(:project) { private_project_in_group }
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:group) { project.group }
context 'group members' do
- before do
+ before_all do
group.add_guest(guest)
group.add_reporter(reporter)
group.add_developer(developer)
@@ -509,7 +522,7 @@ RSpec.describe ProjectPolicy do
it 'allows owner access', :aggregate_failures do
expect(described_class.new(owner_of_different_thing, project)).to be_disallowed(:owner_access)
- expect(described_class.new(stranger, project)).to be_disallowed(:owner_access)
+ expect(described_class.new(non_member, project)).to be_disallowed(:owner_access)
expect(described_class.new(guest, project)).to be_disallowed(:owner_access)
expect(described_class.new(reporter, project)).to be_disallowed(:owner_access)
expect(described_class.new(developer, project)).to be_disallowed(:owner_access)
@@ -1692,7 +1705,7 @@ RSpec.describe ProjectPolicy do
let_it_be(:project_with_analytics_private) { create(:project, :analytics_private) }
let_it_be(:project_with_analytics_enabled) { create(:project, :analytics_enabled) }
- before do
+ before_all do
project_with_analytics_disabled.add_guest(guest)
project_with_analytics_private.add_guest(guest)
project_with_analytics_enabled.add_guest(guest)
@@ -2424,7 +2437,7 @@ RSpec.describe ProjectPolicy do
before do
current_user.set_ci_job_token_scope!(job)
current_user.external = external_user
- scope_project.update!(ci_job_token_scope_enabled: token_scope_enabled)
+ scope_project.update!(ci_outbound_job_token_scope_enabled: token_scope_enabled)
end
it "enforces the expected permissions" do
@@ -2617,28 +2630,14 @@ RSpec.describe ProjectPolicy do
let(:current_user) { admin }
context 'when admin mode is enabled', :enable_admin_mode 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_project_runners) }
- end
+ it { is_expected.to be_allowed(:register_project_runners) }
- context 'with runner_registration_control FF enabled' do
+ context 'with project runner registration disabled' do
before do
- stub_feature_flags(runner_registration_control: true)
+ stub_application_setting(valid_runner_registrars: ['group'])
end
it { is_expected.to be_allowed(:register_project_runners) }
-
- context 'with project runner registration disabled' do
- before do
- stub_application_setting(valid_runner_registrars: ['group'])
- end
-
- it { is_expected.to be_allowed(:register_project_runners) }
- end
end
end
@@ -2652,28 +2651,12 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:register_project_runners) }
- 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_project_runners) }
- end
-
- context 'with runner_registration_control FF enabled' do
+ context 'with project runner registration disabled' do
before do
- stub_feature_flags(runner_registration_control: true)
+ stub_application_setting(valid_runner_registrars: ['group'])
end
- it { is_expected.to be_allowed(:register_project_runners) }
-
- context 'with project runner registration disabled' do
- before do
- stub_application_setting(valid_runner_registrars: ['group'])
- end
-
- it { is_expected.to be_disallowed(:register_project_runners) }
- end
+ it { is_expected.to be_disallowed(:register_project_runners) }
end
end
@@ -2764,6 +2747,50 @@ RSpec.describe ProjectPolicy do
end
end
+ describe 'role_enables_download_code' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'default roles' do
+ let(:current_user) { public_send(role) }
+
+ context 'public project' do
+ let(:project) { public_project }
+
+ where(:role, :allowed) do
+ :owner | true
+ :maintainer | true
+ :developer | true
+ :reporter | true
+ :guest | true
+
+ with_them do
+ it do
+ expect(subject.can?(:download_code)).to be(allowed)
+ end
+ end
+ end
+ end
+
+ context 'private project' do
+ let(:project) { private_project }
+
+ where(:role, :allowed) do
+ :owner | true
+ :maintainer | true
+ :developer | true
+ :reporter | true
+ :guest | false
+ end
+
+ with_them do
+ it do
+ expect(subject.can?(:download_code)).to be(allowed)
+ end
+ end
+ end
+ end
+ end
+
private
def project_subject(project_type)
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index 8b96aa99f69..c6d8ef05cfd 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -2,29 +2,28 @@
require 'spec_helper'
-# Snippet visibility scenarios are included in more details in spec/support/snippet_visibility.rb
+# Snippet visibility scenarios are included in more details in spec/finders/snippets_finder_spec.rb
RSpec.describe ProjectSnippetPolicy do
+ let_it_be(:group) { create(:group, :public) }
let_it_be(:regular_user) { create(:user) }
- let_it_be(:other_user) { create(:user) }
let_it_be(:external_user) { create(:user, :external) }
- let_it_be(:project) { create(:project, :public) }
-
- let(:snippet) { create(:project_snippet, snippet_visibility, project: project, author: author) }
- let(:author) { other_user }
- let(:author_permissions) do
+ let_it_be(:author) { create(:user) }
+ let_it_be(:author_permissions) do
[
:update_snippet,
:admin_snippet
]
end
+ let(:snippet) { build(:project_snippet, snippet_visibility, project: project, author: author) }
+
subject { described_class.new(current_user, snippet) }
- shared_examples 'regular user access rights' do
+ shared_examples 'regular user member permissions' do
context 'not snippet author' do
- context 'project team member (non guest)' do
+ context 'member (guest)' do
before do
- project.add_developer(current_user)
+ membership_target.add_guest(current_user)
end
it do
@@ -33,25 +32,35 @@ RSpec.describe ProjectSnippetPolicy do
end
end
- context 'project team member (guest)' do
+ context 'member (reporter)' do
before do
- project.add_guest(current_user)
+ membership_target.add_reporter(current_user)
end
it do
expect_allowed(:read_snippet, :create_note)
- expect_disallowed(:admin_snippet)
+ expect_disallowed(*author_permissions)
end
end
- context 'project team member (maintainer)' do
+ context 'member (developer)' do
before do
- project.add_maintainer(current_user)
+ membership_target.add_developer(current_user)
end
it do
expect_allowed(:read_snippet, :create_note)
- expect_allowed(*author_permissions)
+ expect_disallowed(*author_permissions)
+ end
+ end
+
+ context 'member (maintainer)' do
+ before do
+ membership_target.add_maintainer(current_user)
+ end
+
+ it do
+ expect_allowed(:read_snippet, :create_note, *author_permissions)
end
end
end
@@ -59,196 +68,263 @@ RSpec.describe ProjectSnippetPolicy do
context 'snippet author' do
let(:author) { current_user }
- context 'project member (non guest)' do
+ context 'member (guest)' do
before do
- project.add_developer(current_user)
+ membership_target.add_guest(current_user)
end
it do
- expect_allowed(:read_snippet, :create_note)
- expect_allowed(*author_permissions)
+ expect_allowed(:read_snippet, :create_note, :update_snippet)
+ expect_disallowed(:admin_snippet)
end
end
- context 'project member (guest)' do
+ context 'member (reporter)' do
before do
- project.add_guest(current_user)
+ membership_target.add_reporter(current_user)
end
it do
- expect_allowed(:read_snippet, :create_note)
- expect_disallowed(:admin_snippet)
+ expect_allowed(:read_snippet, :create_note, *author_permissions)
end
end
- context 'project team member (maintainer)' do
+ context 'member (developer)' do
before do
- project.add_maintainer(current_user)
+ membership_target.add_developer(current_user)
end
it do
- expect_allowed(:read_snippet, :create_note)
- expect_allowed(*author_permissions)
+ expect_allowed(:read_snippet, :create_note, *author_permissions)
end
end
- context 'not a project member' do
+ context 'member (maintainer)' do
+ before do
+ membership_target.add_maintainer(current_user)
+ end
+
it do
- expect_allowed(:read_snippet, :create_note)
- expect_disallowed(:admin_snippet)
+ expect_allowed(:read_snippet, :create_note, *author_permissions)
end
end
end
end
- context 'public snippet' do
- let(:snippet_visibility) { :public }
-
- context 'no user' do
- let(:current_user) { nil }
+ shared_examples 'regular user non-member author permissions' do
+ let(:author) { current_user }
- it do
- expect_allowed(:read_snippet)
- expect_disallowed(*author_permissions)
- end
+ it do
+ expect_allowed(:read_snippet, :create_note, :update_snippet)
+ expect_disallowed(:admin_snippet)
end
+ end
- context 'regular user' do
- let(:current_user) { regular_user }
-
- it do
- expect_allowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
- end
+ context 'when project is public' do
+ let_it_be(:project) { create(:project, :public, group: group) }
- it_behaves_like 'regular user access rights'
- end
+ context 'with public snippet' do
+ let(:snippet_visibility) { :public }
- context 'external user' do
- let(:current_user) { external_user }
+ context 'no user' do
+ let(:current_user) { nil }
- it do
- expect_allowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ it do
+ expect_allowed(:read_snippet)
+ expect_disallowed(*author_permissions)
+ end
end
- context 'project team member' do
- before do
- project.add_developer(external_user)
+ context 'regular user' do
+ let(:current_user) { regular_user }
+ let(:membership_target) { project }
+
+ context 'when user is not a member' do
+ context 'and is not the snippet author' do
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
+ end
+
+ context 'and is the snippet author' do
+ it_behaves_like 'regular user non-member author permissions'
+ end
end
+ context 'when user is a member' do
+ it_behaves_like 'regular user member permissions'
+ end
+ end
+
+ context 'external user' do
+ let(:current_user) { external_user }
+
it do
expect_allowed(:read_snippet, :create_note)
expect_disallowed(*author_permissions)
end
- end
- end
- end
-
- context 'internal snippet' do
- let(:snippet_visibility) { :internal }
- context 'no user' do
- let(:current_user) { nil }
+ context 'when user is a member' do
+ before do
+ project.add_developer(external_user)
+ end
- it do
- expect_disallowed(:read_snippet)
- expect_disallowed(*author_permissions)
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
+ end
end
end
- context 'regular user' do
- let(:current_user) { regular_user }
+ context 'with internal snippet' do
+ let(:snippet_visibility) { :internal }
- it do
- expect_allowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
- end
+ context 'no user' do
+ let(:current_user) { nil }
- it_behaves_like 'regular user access rights'
- end
+ it do
+ expect_disallowed(:read_snippet)
+ expect_disallowed(*author_permissions)
+ end
+ end
- context 'external user' do
- let(:current_user) { external_user }
+ context 'regular user' do
+ let(:current_user) { regular_user }
+ let(:membership_target) { project }
+
+ context 'when user is not a member' do
+ context 'and is not the snippet author' do
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
+ end
+
+ context 'and is the snippet author' do
+ it_behaves_like 'regular user non-member author permissions'
+ end
+ end
- it do
- expect_disallowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ context 'when user is a member' do
+ it_behaves_like 'regular user member permissions'
+ end
end
- context 'project team member' do
- before do
- project.add_developer(external_user)
- end
+ context 'external user' do
+ let(:current_user) { external_user }
it do
- expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(:read_snippet, :create_note)
expect_disallowed(*author_permissions)
end
+
+ context 'when user is a member' do
+ before do
+ project.add_developer(external_user)
+ end
+
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
+ end
end
end
- end
- context 'private snippet' do
- let(:snippet_visibility) { :private }
+ context 'with private snippet' do
+ let(:snippet_visibility) { :private }
- context 'no user' do
- let(:current_user) { nil }
+ context 'no user' do
+ let(:current_user) { nil }
- it do
- expect_disallowed(:read_snippet)
- expect_disallowed(*author_permissions)
+ it do
+ expect_disallowed(:read_snippet)
+ expect_disallowed(*author_permissions)
+ end
end
- end
- context 'regular user' do
- let(:current_user) { regular_user }
+ context 'regular user' do
+ let(:current_user) { regular_user }
+ let(:membership_target) { project }
+
+ context 'when user is not a member' do
+ context 'and is not the snippet author' do
+ it do
+ expect_disallowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
+ end
+
+ context 'and is the snippet author' do
+ it_behaves_like 'regular user non-member author permissions'
+ end
+ end
- it do
- expect_disallowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ context 'when user is a member' do
+ it_behaves_like 'regular user member permissions'
+ end
end
- it_behaves_like 'regular user access rights'
- end
-
- context 'external user' do
- let(:current_user) { external_user }
+ context 'inherited user' do
+ let(:current_user) { regular_user }
+ let(:membership_target) { group }
- it do
- expect_disallowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ it_behaves_like 'regular user member permissions'
end
- context 'project team member' do
- before do
- project.add_developer(current_user)
- end
+ context 'external user' do
+ let(:current_user) { external_user }
it do
- expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(:read_snippet, :create_note)
expect_disallowed(*author_permissions)
end
- end
- end
- context 'admin user' do
- let(:snippet_visibility) { :private }
- let(:current_user) { create(:admin) }
+ context 'when user is a member' do
+ before do
+ project.add_developer(current_user)
+ end
- context 'when admin mode is enabled', :enable_admin_mode do
- it do
- expect_allowed(:read_snippet, :create_note)
- expect_allowed(*author_permissions)
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
end
end
- context 'when admin mode is disabled' do
- it do
- expect_disallowed(:read_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ context 'admin user' do
+ let(:snippet_visibility) { :private }
+ let(:current_user) { create(:admin) }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it do
+ expect_allowed(:read_snippet, :create_note)
+ expect_allowed(*author_permissions)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it do
+ expect_disallowed(:read_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
end
end
end
end
+
+ context 'when project is private' do
+ let_it_be(:project) { create(:project, :private, group: group) }
+
+ let(:snippet_visibility) { :private }
+
+ context 'inherited user' do
+ let(:current_user) { regular_user }
+ let(:membership_target) { group }
+
+ it_behaves_like 'regular user member permissions'
+ end
+ end
end
diff --git a/spec/policies/wiki_page_policy_spec.rb b/spec/policies/wiki_page_policy_spec.rb
index a2fa7f29135..2712026035c 100644
--- a/spec/policies/wiki_page_policy_spec.rb
+++ b/spec/policies/wiki_page_policy_spec.rb
@@ -5,28 +5,43 @@ require 'spec_helper'
RSpec.describe WikiPagePolicy do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
+ include UserHelpers
using RSpec::Parameterized::TableSyntax
- let(:project) { create(:project, :wiki_repo, project_level) }
- let(:user) { create_user_from_membership(project, membership) }
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki) }
+ let(:group) { build(:group, :public) }
+ let(:project) { build(:project, :wiki_repo, project_level, group: group) }
+ let(:wiki_page) { build(:wiki_page, container: project) }
- subject(:policy) { described_class.new(user, wiki_page) }
+ shared_context 'with :read_wiki_page policy' do
+ subject(:policy) { described_class.new(user, wiki_page) }
- where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
- permission_table_for_guest_feature_access
- end
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
+ permission_table_for_guest_feature_access
+ end
- with_them do
- it "grants permission" do
- enable_admin_mode!(user) if admin_mode
- update_feature_access_level(project, feature_access_level)
+ with_them do
+ it 'grants the expected permissions' do
+ enable_admin_mode!(user) if admin_mode
+ update_feature_access_level(project, feature_access_level)
- if expected_count == 1
- expect(policy).to be_allowed(:read_wiki_page)
- else
- expect(policy).to be_disallowed(:read_wiki_page)
+ if expected_count == 1
+ expect(policy).to be_allowed(:read_wiki_page)
+ else
+ expect(policy).to be_disallowed(:read_wiki_page)
+ end
end
end
end
+
+ context 'when user is a direct project member' do
+ let(:user) { build_user_from_membership(project, membership) }
+
+ include_context 'with :read_wiki_page policy'
+ end
+
+ context 'when user is an inherited member from the group' do
+ let(:user) { build_user_from_membership(group, membership) }
+
+ include_context 'with :read_wiki_page policy'
+ end
end
diff --git a/spec/presenters/blobs/unfold_presenter_spec.rb b/spec/presenters/blobs/unfold_presenter_spec.rb
index 14c36461e90..9b3b7f5a1c8 100644
--- a/spec/presenters/blobs/unfold_presenter_spec.rb
+++ b/spec/presenters/blobs/unfold_presenter_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe Blobs::UnfoldPresenter do
include FakeBlobHelpers
- let(:project) { create(:project, :repository) }
- let(:blob) { fake_blob(path: 'foo', data: "1\n2\n3") }
- let(:subject) { described_class.new(blob, params) }
+ let(:project) { nil } # Project object is not needed but `fake_blob` helper requires it to be defined.
+ let(:blob) { fake_blob(path: 'foo', data: data) }
+ let(:data) { "1\n\2\n3" }
- describe '#initialize' do
- let(:result) { subject }
+ subject(:result) { described_class.new(blob, params) }
+ describe '#initialize' do
context 'with empty params' do
let(:params) { {} }
@@ -71,7 +71,7 @@ RSpec.describe Blobs::UnfoldPresenter do
describe '#diff_lines' do
let(:total_lines) { 50 }
- let(:blob) { fake_blob(path: 'foo', data: (1..total_lines).to_a.join("\n")) }
+ let(:data) { (1..total_lines).to_a.join("\n") }
context 'when "full" is true' do
let(:params) { { full: true } }
@@ -91,7 +91,7 @@ RSpec.describe Blobs::UnfoldPresenter do
end
context 'when last line is empty' do
- let(:blob) { fake_blob(path: 'foo', data: "1\n2\n") }
+ let(:data) { "1\n2\n" }
it 'disregards last line' do
lines = subject.diff_lines
@@ -123,7 +123,7 @@ RSpec.describe Blobs::UnfoldPresenter do
expect(line.new_pos).to eq(5)
end
- context '"to" is higher than blob size' do
+ context 'when "to" is higher than blob size' do
let(:params) { default_params.merge(to: total_lines + 10, bottom: true) }
it 'does not add bottom match line' do
@@ -133,7 +133,7 @@ RSpec.describe Blobs::UnfoldPresenter do
end
end
- context '"to" is equal to blob size' do
+ context 'when "to" is equal to blob size' do
let(:params) { default_params.merge(to: total_lines, bottom: true) }
it 'does not add bottom match line' do
@@ -143,7 +143,7 @@ RSpec.describe Blobs::UnfoldPresenter do
end
end
- context '"to" is less than blob size' do
+ context 'when "to" is less than blob size' do
let(:params) { default_params.merge(to: total_lines - 3, bottom: true) }
it 'adds bottom match line' do
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index fe2d8f0f670..396fe7843ba 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -350,6 +350,15 @@ RSpec.describe Ci::BuildRunnerPresenter do
)
end
+ it 'logs file_variable_is_referenced_in_another_variable' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(
+ event: 'file_variable_is_referenced_in_another_variable',
+ project_id: project.id
+ ).once
+
+ runner_variables
+ end
+
context 'when the FF ci_stop_expanding_file_vars_for_runners is disabled' do
before do
stub_feature_flags(ci_stop_expanding_file_vars_for_runners: false)
@@ -383,10 +392,10 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns expanded and sorted variables' do
is_expected.to eq [
- { key: 'C', value: 'value', public: false, masked: false },
- { key: 'B', value: 'refB-value-$D', public: false, masked: false },
- { key: 'A', value: 'refA-refB-value-$D', public: false, masked: false }
- ]
+ { key: 'C', value: 'value', public: false, masked: false },
+ { key: 'B', value: 'refB-value-$D', public: false, masked: false },
+ { key: 'A', value: 'refA-refB-value-$D', public: false, masked: false }
+ ]
end
end
end
diff --git a/spec/presenters/commit_presenter_spec.rb b/spec/presenters/commit_presenter_spec.rb
index df3ee69621b..eba393da2b7 100644
--- a/spec/presenters/commit_presenter_spec.rb
+++ b/spec/presenters/commit_presenter_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe CommitPresenter do
- let(:project) { create(:project, :repository) }
let(:commit) { project.commit }
- let(:user) { create(:user) }
let(:presenter) { described_class.new(commit, current_user: user) }
+ let_it_be(:user) { build_stubbed(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
describe '#web_path' do
it { expect(presenter.web_path).to eq("/#{project.full_path}/-/commit/#{commit.sha}") }
end
diff --git a/spec/presenters/deploy_key_presenter_spec.rb b/spec/presenters/deploy_key_presenter_spec.rb
new file mode 100644
index 00000000000..9e50da12395
--- /dev/null
+++ b/spec/presenters/deploy_key_presenter_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DeployKeyPresenter do
+ let(:presenter) { described_class.new(deploy_key) }
+
+ describe '#humanized_error_message' do
+ subject { presenter.humanized_error_message }
+
+ before do
+ deploy_key.valid?
+ end
+
+ context 'when public key is unsupported' do
+ let(:deploy_key) { build(:deploy_key, key: 'a') }
+
+ it 'returns the custom error message' do
+ expect(subject).to eq('Deploy Key must be a <a target="_blank" rel="noopener noreferrer" ' \
+ 'href="/help/user/ssh#supported-ssh-key-types">supported SSH public key.</a>')
+ end
+ end
+ end
+end
diff --git a/spec/presenters/event_presenter_spec.rb b/spec/presenters/event_presenter_spec.rb
index 5a67fd92c9d..9093791421d 100644
--- a/spec/presenters/event_presenter_spec.rb
+++ b/spec/presenters/event_presenter_spec.rb
@@ -51,6 +51,14 @@ RSpec.describe EventPresenter do
it 'returns milestone for a milestone event' do
expect(group_event.present).to have_attributes(target_type_name: 'milestone')
end
+
+ it 'returns the issue_type for issue events' do
+ expect(build(:event, :for_issue, :created).present).to have_attributes(target_type_name: 'issue')
+ end
+
+ it 'returns the issue_type for work item events' do
+ expect(build(:event, :for_work_item, :created).present).to have_attributes(target_type_name: 'task')
+ end
end
describe '#note_target_type_name' do
diff --git a/spec/presenters/key_presenter_spec.rb b/spec/presenters/key_presenter_spec.rb
new file mode 100644
index 00000000000..d5aa39d5933
--- /dev/null
+++ b/spec/presenters/key_presenter_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe KeyPresenter do
+ let(:presenter) { described_class.new(key) }
+
+ describe '#humanized_error_message' do
+ subject { presenter.humanized_error_message }
+
+ before do
+ key.valid?
+ end
+
+ context 'when public key is unsupported' do
+ let(:key) { build(:key, key: 'a') }
+
+ it 'returns the custom error message' do
+ expect(subject).to eq('Key must be a <a target="_blank" rel="noopener noreferrer" ' \
+ 'href="/help/user/ssh#supported-ssh-key-types">supported SSH public key.</a>')
+ end
+ end
+
+ context 'when key is expired' do
+ let(:key) { build(:key, :expired) }
+
+ it 'returns Active Record error message' do
+ expect(subject).to eq('Key has expired')
+ end
+ end
+ end
+end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 7ff19b1b770..832deee6186 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -10,13 +10,15 @@ RSpec.describe ProjectPresenter do
describe '#license_short_name' do
context 'when project.repository has a license_key' do
it 'returns the nickname of the license if present' do
- allow(project.repository).to receive(:license_key).and_return('agpl-3.0')
+ allow(project.repository).to receive(:license).and_return(
+ ::Gitlab::Git::DeclaredLicense.new(name: 'foo', nickname: 'GNU AGPLv3'))
expect(presenter.license_short_name).to eq('GNU AGPLv3')
end
it 'returns the name of the license if nickname is not present' do
- allow(project.repository).to receive(:license_key).and_return('mit')
+ allow(project.repository).to receive(:license).and_return(
+ ::Gitlab::Git::DeclaredLicense.new(name: 'MIT License'))
expect(presenter.license_short_name).to eq('MIT License')
end
@@ -24,7 +26,7 @@ RSpec.describe ProjectPresenter do
context 'when project.repository has no license_key but a license_blob' do
it 'returns LICENSE' do
- allow(project.repository).to receive(:license_key).and_return(nil)
+ allow(project.repository).to receive(:license).and_return(nil)
expect(presenter.license_short_name).to eq('LICENSE')
end
diff --git a/spec/presenters/projects/security/configuration_presenter_spec.rb b/spec/presenters/projects/security/configuration_presenter_spec.rb
index 05e5a9d4f1d..ca7f96b567d 100644
--- a/spec/presenters/projects/security/configuration_presenter_spec.rb
+++ b/spec/presenters/projects/security/configuration_presenter_spec.rb
@@ -6,9 +6,8 @@ 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_it_be(:current_user) { build_stubbed(:user) }
+
let(:presenter) { described_class.new(project, current_user: current_user) }
before do
@@ -19,9 +18,9 @@ RSpec.describe Projects::Security::ConfigurationPresenter 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_it_be(:project) { create(:project, :repository) }
- let(:pipeline) do
+ let_it_be(:pipeline) do
create(
:ci_pipeline,
project: project,
@@ -119,6 +118,16 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
context 'when the job has more than one report' do
let(:features) { Gitlab::Json.parse(html_data[:features]) }
+ let(:project) { create(:project, :repository) }
+
+ let(:pipeline) do
+ create(
+ :ci_pipeline,
+ project: project,
+ ref: project.default_branch,
+ sha: project.commit.sha
+ )
+ end
let!(:artifacts) do
{ artifacts: { reports: { other_job: ['gl-other-report.json'], sast: ['gl-sast-report.json'] } } }
@@ -161,6 +170,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
end
context "while retrieving information about gitlab ci file" do
+ let(:project) { create(:project, :repository) }
+
context 'when a .gitlab-ci.yml file exists' do
let!(:ci_config) do
project.repository.create_file(
@@ -189,7 +200,7 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
end
context 'when the project is empty' do
- let(:project) { project_with_no_repo }
+ let(:project) { create(:project) }
it 'includes a blank gitlab_ci history path' do
expect(html_data[:gitlab_ci_history_path]).to eq('')
@@ -197,7 +208,7 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
end
context 'when the project has no default branch set' do
- let(:project) { project_with_repo }
+ let(:project) { create(:project, :repository) }
it 'includes the path to gitlab_ci history' do
allow(project).to receive(:default_branch).and_return(nil)
@@ -207,9 +218,9 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
end
context "when the latest default branch pipeline's source is auto devops" do
- let(:project) { project_with_repo }
+ let_it_be(:project) { create(:project, :repository) }
- let(:pipeline) do
+ let_it_be(:pipeline) do
create(
:ci_pipeline,
:auto_devops_source,
@@ -256,7 +267,7 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
end
context 'when the project has no default branch pipeline' do
- let(:project) { project_with_repo }
+ let_it_be(:project) { create(:project, :repository) }
it 'reports that auto devops is disabled' do
expect(html_data[:auto_devops_enabled]).to be_falsy
diff --git a/spec/requests/admin/impersonation_tokens_controller_spec.rb b/spec/requests/admin/impersonation_tokens_controller_spec.rb
index 018f497e7e5..ee0e12ad0c0 100644
--- a/spec/requests/admin/impersonation_tokens_controller_spec.rb
+++ b/spec/requests/admin/impersonation_tokens_controller_spec.rb
@@ -10,6 +10,18 @@ RSpec.describe Admin::ImpersonationTokensController, :enable_admin_mode do
sign_in(admin)
end
+ context 'when impersonation is enabled' do
+ before do
+ stub_config_setting(impersonation_enabled: true)
+ end
+
+ it 'responds ok' do
+ get admin_user_impersonation_tokens_path(user_id: user.username)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
context "when impersonation is disabled" do
before do
stub_config_setting(impersonation_enabled: false)
@@ -35,4 +47,10 @@ RSpec.describe Admin::ImpersonationTokensController, :enable_admin_mode do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ describe "#create" do
+ it_behaves_like "#create access token" do
+ let(:url) { admin_user_impersonation_tokens_path(user_id: user.username) }
+ end
+ end
end
diff --git a/spec/requests/api/admin/batched_background_migrations_spec.rb b/spec/requests/api/admin/batched_background_migrations_spec.rb
index c99b21c0c27..3b396a91d3e 100644
--- a/spec/requests/api/admin/batched_background_migrations_spec.rb
+++ b/spec/requests/api/admin/batched_background_migrations_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
describe 'GET /admin/batched_background_migrations/:id' do
let!(:migration) { create(:batched_background_migration, :paused) }
let(:database) { :main }
+ let(:params) { { database: database } }
subject(:show_migration) do
get api("/admin/batched_background_migrations/#{migration.id}", admin), params: { database: database }
@@ -27,10 +28,8 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
end
context 'when the batched background migration does not exist' do
- let(:params) { { database: database } }
-
it 'returns 404' do
- put api("/admin/batched_background_migrations/#{non_existing_record_id}", admin), params: params
+ get api("/admin/batched_background_migrations/#{non_existing_record_id}", admin), params: params
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -58,6 +57,17 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
expect(response).to have_gitlab_http_status(:forbidden)
end
end
+
+ context 'when the database name does not exist' do
+ let(:database) { :wrong_database }
+
+ it 'returns bad request' do
+ get api("/admin/batched_background_migrations/#{migration.id}", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include('database does not have a valid value')
+ end
+ end
end
describe 'GET /admin/batched_background_migrations' do
@@ -82,6 +92,7 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
let(:database) { :ci }
let(:schema) { :gitlab_ci }
let(:ci_model) { Ci::ApplicationRecord }
+ let(:params) { { database: database } }
context 'when CI database is provided' do
let(:db_config) { instance_double(ActiveRecord::DatabaseConfigurations::HashConfig, name: 'fake_db') }
@@ -94,7 +105,18 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield
- get api('/admin/batched_background_migrations', admin), params: { database: :ci }
+ get api('/admin/batched_background_migrations', admin), params: params
+ end
+
+ context 'when the database name does not exist' do
+ let(:database) { :wrong_database }
+
+ it 'returns bad request' do
+ get api("/admin/batched_background_migrations", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include('database does not have a valid value')
+ end
end
it 'returns CI database records' do
@@ -105,7 +127,7 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
create(:batched_background_migration, :active, gitlab_schema: schema)
end
- get api('/admin/batched_background_migrations', admin), params: { database: :ci }
+ get api('/admin/batched_background_migrations', admin), params: params
aggregate_failures "testing response" do
expect(response).to have_gitlab_http_status(:ok)
@@ -133,9 +155,10 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
describe 'PUT /admin/batched_background_migrations/:id/resume' do
let!(:migration) { create(:batched_background_migration, :paused) }
let(:database) { :main }
+ let(:params) { { database: database } }
subject(:resume) do
- put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: { database: database }
+ put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
end
it 'pauses the batched background migration' do
@@ -149,8 +172,6 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
end
context 'when the batched background migration does not exist' do
- let(:params) { { database: database } }
-
it 'returns 404' do
put api("/admin/batched_background_migrations/#{non_existing_record_id}/resume", admin), params: params
@@ -158,6 +179,16 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
end
end
+ context 'when the migration is not paused' do
+ let!(:migration) { create(:batched_background_migration, :failed) }
+
+ it 'returns 422' do
+ put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
context 'when multiple database is enabled' do
let(:ci_model) { Ci::ApplicationRecord }
let(:database) { :ci }
@@ -171,6 +202,17 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
resume
end
+
+ context 'when the database name does not exist' do
+ let(:database) { :wrong_database }
+
+ it 'returns bad request' do
+ put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include('database does not have a valid value')
+ end
+ end
end
context 'when authenticated as a non-admin user' do
@@ -184,9 +226,11 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
describe 'PUT /admin/batched_background_migrations/:id/pause' do
let!(:migration) { create(:batched_background_migration, :active) }
+ let(:database) { :main }
+ let(:params) { { database: database } }
it 'pauses the batched background migration' do
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: { database: :main }
+ put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
aggregate_failures "testing response" do
expect(response).to have_gitlab_http_status(:ok)
@@ -196,8 +240,6 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
end
context 'when the batched background migration does not exist' do
- let(:params) { { database: :main } }
-
it 'returns 404' do
put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", admin), params: params
@@ -205,8 +247,19 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
end
end
+ context 'when the migration is not active' do
+ let!(:migration) { create(:batched_background_migration, :failed) }
+
+ it 'returns 422' do
+ put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
context 'when multiple database is enabled' do
let(:ci_model) { Ci::ApplicationRecord }
+ let(:database) { :ci }
before do
skip_if_multiple_databases_not_setup
@@ -215,7 +268,18 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do
it 'uses the correct connection' do
expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: { database: :ci }
+ put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+ end
+
+ context 'when the database name does not exist' do
+ let(:database) { :wrong_database }
+
+ it 'returns bad request' do
+ put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include('database does not have a valid value')
+ end
end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index f7539e13b80..750b9a39e15 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -221,55 +221,25 @@ RSpec.describe API::Branches do
get api(route), params: { per_page: 1 }
end
- context 'when increase_branch_cache_expiry is enabled' do
- it 'uses the cache up to 60 minutes' do
- time_of_request = Time.current
+ it 'uses the cache up to 60 minutes' do
+ time_of_request = Time.current
- get api(route), params: { per_page: 1 }
-
- travel_to time_of_request + 59.minutes do
- expect(API::Entities::Branch).not_to receive(:represent)
+ get api(route), params: { per_page: 1 }
- get api(route), params: { per_page: 1 }
- end
- end
+ travel_to time_of_request + 59.minutes do
+ expect(API::Entities::Branch).not_to receive(:represent)
- it 'requests for new value after 60 minutes' do
get api(route), params: { per_page: 1 }
-
- travel_to 61.minutes.from_now do
- expect(API::Entities::Branch).to receive(:represent)
-
- get api(route), params: { per_page: 1 }
- end
end
end
- context 'when increase_branch_cache_expiry is disabled' do
- before do
- stub_feature_flags(increase_branch_cache_expiry: false)
- end
-
- it 'uses the cache up to 10 minutes' do
- time_of_request = Time.current
-
- get api(route), params: { per_page: 1 }
+ it 'requests for new value after 60 minutes' do
+ get api(route), params: { per_page: 1 }
- travel_to time_of_request + 9.minutes do
- expect(API::Entities::Branch).not_to receive(:represent)
+ travel_to 61.minutes.from_now do
+ expect(API::Entities::Branch).to receive(:represent)
- get api(route), params: { per_page: 1 }
- end
- end
-
- it 'requests for new value after 10 minutes' do
get api(route), params: { per_page: 1 }
-
- travel_to 11.minutes.from_now do
- expect(API::Entities::Branch).to receive(:represent)
-
- get api(route), params: { per_page: 1 }
- end
end
end
end
diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb
index 6a3d13567bd..ad57a370fc5 100644
--- a/spec/requests/api/bulk_imports_spec.rb
+++ b/spec/requests/api/bulk_imports_spec.rb
@@ -53,6 +53,18 @@ RSpec.describe API::BulkImports do
end
end
+ context 'when bulk_import feature flag is disabled' do
+ before do
+ stub_feature_flags(bulk_import: false)
+ end
+
+ it 'returns 404' do
+ post api('/bulk_imports', user), params: {}
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
shared_examples 'starting a new migration' do
it 'starts a new migration' do
post api('/bulk_imports', user), params: {
diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb
index 0fb11bf98d2..2bf242f06ed 100644
--- a/spec/requests/api/ci/job_artifacts_spec.rb
+++ b/spec/requests/api/ci/job_artifacts_spec.rb
@@ -389,6 +389,49 @@ RSpec.describe API::Ci::JobArtifacts do
end
end
+ context 'when Google CDN is enabled' do
+ let(:cdn_enabled) { true }
+ let(:cdn_config) do
+ {
+ 'provider' => 'Google',
+ 'url' => 'https://cdn.example.org',
+ 'key_name' => 'stanhu-key',
+ 'key' => Base64.urlsafe_encode64(SecureRandom.hex)
+ }
+ end
+
+ before do
+ stub_feature_flags(ci_job_artifacts_cdn: cdn_enabled)
+ stub_object_storage_uploader(config: Gitlab.config.artifacts.object_store,
+ uploader: JobArtifactUploader,
+ proxy_download: proxy_download,
+ cdn: cdn_config)
+ allow(Gitlab::ApplicationContext).to receive(:push).and_call_original
+ end
+
+ subject { get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user), env: { 'REMOTE_ADDR': '18.245.0.1' } }
+
+ it 'returns CDN-signed URL' do
+ expect(Gitlab::ApplicationContext).to receive(:push).with(artifact_used_cdn: true).and_call_original
+
+ subject
+
+ expect(response.redirect_url).to start_with("https://cdn.example.org/#{artifact.file.path}")
+ end
+
+ context 'when ci_job_artifacts_cdn feature flag is disabled' do
+ let(:cdn_enabled) { false }
+
+ it 'returns the file remote URL' do
+ expect(Gitlab::ApplicationContext).to receive(:push).with(artifact_used_cdn: false).and_call_original
+
+ subject
+
+ expect(response).to redirect_to(artifact.file.url)
+ end
+ end
+ end
+
context 'authorized user' do
it 'returns the file remote URL' do
expect(response).to redirect_to(artifact.file.url)
diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb
index b8983e9632e..0e17db516f4 100644
--- a/spec/requests/api/ci/jobs_spec.rb
+++ b/spec/requests/api/ci/jobs_spec.rb
@@ -226,18 +226,19 @@ RSpec.describe API::Ci::Jobs do
expect(json_response.dig('user', 'username')).to eq(api_user.username)
expect(json_response.dig('user', 'roles_in_project')).to match_array %w(guest reporter developer)
expect(json_response).not_to include('environment')
- expect(json_response['allowed_agents']).to match_array([
- {
- 'id' => implicit_authorization.agent_id,
- 'config_project' => hash_including('id' => implicit_authorization.agent.project_id),
- 'configuration' => implicit_authorization.config
- },
- {
- 'id' => group_authorization.agent_id,
- 'config_project' => hash_including('id' => group_authorization.agent.project_id),
- 'configuration' => group_authorization.config
- }
- ])
+ expect(json_response['allowed_agents']).to match_array(
+ [
+ {
+ 'id' => implicit_authorization.agent_id,
+ 'config_project' => hash_including('id' => implicit_authorization.agent.project_id),
+ 'configuration' => implicit_authorization.config
+ },
+ {
+ 'id' => group_authorization.agent_id,
+ 'config_project' => hash_including('id' => group_authorization.agent.project_id),
+ 'configuration' => group_authorization.config
+ }
+ ])
end
end
diff --git a/spec/requests/api/ci/resource_groups_spec.rb b/spec/requests/api/ci/resource_groups_spec.rb
index 864c363e6d3..87df71f6096 100644
--- a/spec/requests/api/ci/resource_groups_spec.rb
+++ b/spec/requests/api/ci/resource_groups_spec.rb
@@ -77,6 +77,48 @@ RSpec.describe API::Ci::ResourceGroups do
end
end
+ describe 'GET /projects/:id/resource_groups/:key/upcoming_jobs' do
+ subject { get api("/projects/#{project.id}/resource_groups/#{key}/upcoming_jobs", user) }
+
+ let_it_be(:resource_group) { create(:ci_resource_group, project: project) }
+ let_it_be(:processable) { create(:ci_processable, resource_group: resource_group) }
+ let_it_be(:upcoming_processable) { create(:ci_processable, :waiting_for_resource, resource_group: resource_group) }
+
+ let(:key) { resource_group.key }
+
+ it 'returns upcoming jobs of resource group', :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.length).to eq(1)
+ expect(json_response[0]['id']).to eq(upcoming_processable.id)
+ expect(json_response[0]['name']).to eq(upcoming_processable.name)
+ expect(json_response[0]['ref']).to eq(upcoming_processable.ref)
+ expect(json_response[0]['stage']).to eq(upcoming_processable.stage)
+ expect(json_response[0]['status']).to eq(upcoming_processable.status)
+ end
+
+ context 'when user is reporter' do
+ let(:user) { reporter }
+
+ it 'returns forbidden' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when there is no corresponding resource group' do
+ let(:key) { 'unknown' }
+
+ it 'returns not found' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe 'PUT /projects/:id/resource_groups/:key' do
subject { put api("/projects/#{project.id}/resource_groups/#{key}", user), params: params }
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 b33b97f90d7..d4f734e7bdd 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -220,14 +220,15 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['image']).to eq(
{ 'name' => 'image:1.0', 'entrypoint' => '/bin/sh', 'ports' => [], 'pull_policy' => nil }
)
- expect(json_response['services']).to eq([
- { 'name' => 'postgres', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
- 'variables' => nil, 'pull_policy' => nil },
- { 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh', 'alias' => 'docker', 'command' => 'sleep 30',
- 'ports' => [], 'variables' => [], 'pull_policy' => nil },
- { 'name' => 'mysql:latest', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
- 'variables' => [{ 'key' => 'MYSQL_ROOT_PASSWORD', 'value' => 'root123.' }], 'pull_policy' => nil }
- ])
+ expect(json_response['services']).to eq(
+ [
+ { 'name' => 'postgres', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
+ 'variables' => nil, 'pull_policy' => nil },
+ { 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh', 'alias' => 'docker', 'command' => 'sleep 30',
+ 'ports' => [], 'variables' => [], 'pull_policy' => nil },
+ { 'name' => 'mysql:latest', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
+ 'variables' => [{ 'key' => 'MYSQL_ROOT_PASSWORD', 'value' => 'root123.' }], 'pull_policy' => nil }
+ ])
expect(json_response['steps']).to eq(expected_steps)
expect(json_response['artifacts']).to eq(expected_artifacts)
expect(json_response['cache']).to match(expected_cache)
@@ -383,23 +384,24 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:created)
expect(response.headers).not_to have_key('X-GitLab-Last-Update')
- expect(json_response['steps']).to eq([
- {
- "name" => "script",
- "script" => ["make changelog | tee release_changelog.txt"],
- "timeout" => 3600,
- "when" => "on_success",
- "allow_failure" => false
- },
- {
- "name" => "release",
- "script" =>
- ["release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\" --assets-link \"{\\\"url\\\":\\\"https://example.com/assets/1\\\",\\\"name\\\":\\\"asset1\\\"}\""],
- "timeout" => 3600,
- "when" => "on_success",
- "allow_failure" => false
- }
- ])
+ expect(json_response['steps']).to eq(
+ [
+ {
+ "name" => "script",
+ "script" => ["make changelog | tee release_changelog.txt"],
+ "timeout" => 3600,
+ "when" => "on_success",
+ "allow_failure" => false
+ },
+ {
+ "name" => "release",
+ "script" =>
+ ["release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\" --assets-link \"{\\\"url\\\":\\\"https://example.com/assets/1\\\",\\\"name\\\":\\\"asset1\\\"}\""],
+ "timeout" => 3600,
+ "when" => "on_success",
+ "allow_failure" => false
+ }
+ ])
end
end
diff --git a/spec/requests/api/ci/runner/runners_reset_spec.rb b/spec/requests/api/ci/runner/runners_reset_spec.rb
index 8a61012ead1..02b66a89a0a 100644
--- a/spec/requests/api/ci/runner/runners_reset_spec.rb
+++ b/spec/requests/api/ci/runner/runners_reset_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
before do
stub_feature_flags(ci_enable_live_trace: true)
- stub_feature_flags(runner_registration_control: false)
stub_gitlab_calls
stub_application_setting(valid_runner_registrars: ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
end
diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb
index fa1f713e757..69f26d3f257 100644
--- a/spec/requests/api/ci/runners_spec.rb
+++ b/spec/requests/api/ci/runners_spec.rb
@@ -918,10 +918,11 @@ RSpec.describe API::Ci::Runners do
create(:ci_build, :failed, runner: shared_runner, project: project_with_repo, pipeline: pipeline)
expect_next_instance_of(Repository) do |repo|
- expect(repo).to receive(:commits_by).with(oids: %w[
- 1a0b36b3cdad1d2ee32457c102a8c0b7056fa863
- c1c67abbaf91f624347bb3ae96eabe3a1b742478
- ]).once.and_call_original
+ expect(repo).to receive(:commits_by).with(oids:
+ %w[
+ 1a0b36b3cdad1d2ee32457c102a8c0b7056fa863
+ c1c67abbaf91f624347bb3ae96eabe3a1b742478
+ ]).once.and_call_original
end
get api("/runners/#{shared_runner.id}/jobs", admin), params: { per_page: 2, order_by: 'id', sort: 'desc' }
@@ -1124,30 +1125,27 @@ RSpec.describe API::Ci::Runners do
it 'returns all runners' do
get api("/groups/#{group.id}/runners", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Group runner A', 'active' => true, 'paused' => false),
- a_hash_including('description' => 'Shared runner', 'active' => true, 'paused' => false)
- ])
+ expect(json_response).to match_array(
+ [
+ a_hash_including('description' => 'Group runner A', 'active' => true, 'paused' => false),
+ a_hash_including('description' => 'Shared runner', 'active' => true, 'paused' => false)
+ ])
end
context 'filter by type' do
it 'returns record when valid and present' do
get api("/groups/#{group.id}/runners?type=group_type", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Group runner A')
- ])
+ expect(json_response).to match_array([a_hash_including('description' => 'Group runner A')])
end
it 'returns instance runners when instance_type is specified' do
get api("/groups/#{group.id}/runners?type=instance_type", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Shared runner')
- ])
+ expect(json_response).to match_array([a_hash_including('description' => 'Shared runner')])
end
- # TODO: Remove in %15.0 (https://gitlab.com/gitlab-org/gitlab/-/issues/351466)
+ # TODO: Remove when REST API v5 is implemented (https://gitlab.com/gitlab-org/gitlab/-/issues/351466)
it 'returns empty result when type does not match' do
get api("/groups/#{group.id}/runners?type=project_type", user)
@@ -1167,18 +1165,14 @@ RSpec.describe API::Ci::Runners do
it 'returns runners by paused state' do
get api("/groups/#{group.id}/runners?paused=true", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Inactive group runner')
- ])
+ expect(json_response).to match_array([a_hash_including('description' => 'Inactive group runner')])
end
context 'filter runners by status' do
it 'returns runners by valid status' do
get api("/groups/#{group.id}/runners?status=paused", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Inactive group runner')
- ])
+ expect(json_response).to match_array([a_hash_including('description' => 'Inactive group runner')])
end
it 'does not filter by invalid status' do
@@ -1195,9 +1189,7 @@ RSpec.describe API::Ci::Runners do
get api("/groups/#{group.id}/runners?tag_list=tag1,tag2", user)
- expect(json_response).to match_array([
- a_hash_including('description' => 'Runner tagged with tag1 and tag2')
- ])
+ expect(json_response).to match_array([a_hash_including('description' => 'Runner tagged with tag1 and tag2')])
end
end
diff --git a/spec/requests/api/deploy_tokens_spec.rb b/spec/requests/api/deploy_tokens_spec.rb
index b5f8da1f327..e0296248a03 100644
--- a/spec/requests/api/deploy_tokens_spec.rb
+++ b/spec/requests/api/deploy_tokens_spec.rb
@@ -44,14 +44,15 @@ RSpec.describe API::DeployTokens do
token_ids = json_response.map { |token| token['id'] }
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/deploy_tokens')
- expect(token_ids).to match_array([
- deploy_token.id,
- revoked_deploy_token.id,
- expired_deploy_token.id,
- group_deploy_token.id,
- revoked_group_deploy_token.id,
- expired_group_deploy_token.id
- ])
+ expect(token_ids).to match_array(
+ [
+ deploy_token.id,
+ revoked_deploy_token.id,
+ expired_deploy_token.id,
+ group_deploy_token.id,
+ revoked_group_deploy_token.id,
+ expired_group_deploy_token.id
+ ])
end
context 'and active=true' do
@@ -61,10 +62,11 @@ RSpec.describe API::DeployTokens do
token_ids = json_response.map { |token| token['id'] }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
- expect(token_ids).to match_array([
- deploy_token.id,
- group_deploy_token.id
- ])
+ expect(token_ids).to match_array(
+ [
+ deploy_token.id,
+ group_deploy_token.id
+ ])
end
end
end
@@ -110,11 +112,12 @@ RSpec.describe API::DeployTokens do
subject
token_ids = json_response.map { |token| token['id'] }
- expect(token_ids).to match_array([
- deploy_token.id,
- expired_deploy_token.id,
- revoked_deploy_token.id
- ])
+ expect(token_ids).to match_array(
+ [
+ deploy_token.id,
+ expired_deploy_token.id,
+ revoked_deploy_token.id
+ ])
end
context 'and active=true' do
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index b54be4f5258..d0334cf6dd2 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -92,402 +92,292 @@ RSpec.describe API::Features, stub_feature_flags: false do
describe 'POST /feature' do
let(:feature_name) { known_feature_flag.name }
- context 'when the feature does not exist' do
- it 'returns a 401 for anonymous users' do
- post api("/features/#{feature_name}")
+ # TODO: remove this shared examples block when set_feature_flag_service feature flag
+ # is removed. Then remove also any duplicate specs covered by the service class.
+ shared_examples 'sets the feature flag status' do
+ context 'when the feature does not exist' do
+ it 'returns a 401 for anonymous users' do
+ post api("/features/#{feature_name}")
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
- it 'returns a 403 for users' do
- post api("/features/#{feature_name}", user)
+ it 'returns a 403 for users' do
+ post api("/features/#{feature_name}", user)
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- context 'when passed value=true' do
- it 'creates an enabled feature' do
- post api("/features/#{feature_name}", admin), params: { value: 'true' }
+ context 'when passed value=true' do
+ it 'creates an enabled feature' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true' }
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'on',
- 'gates' => [{ 'key' => 'boolean', 'value' => true }],
- 'definition' => known_feature_flag_definition_hash
- )
- end
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'on',
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
- it 'logs the event' do
- expect(Feature.logger).to receive(:info).once
+ it 'logs the event' do
+ expect(Feature.logger).to receive(:info).once
- post api("/features/#{feature_name}", admin), params: { value: 'true' }
- end
+ post api("/features/#{feature_name}", admin), params: { value: 'true' }
+ end
- it 'creates an enabled feature for the given Flipper group when passed feature_group=perf_team' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
+ it 'creates an enabled feature for the given Flipper group when passed feature_group=perf_team' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'groups', 'value' => ['perf_team'] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'groups', 'value' => ['perf_team'] }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
+ it 'creates an enabled feature for the given user when passed user=username' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
- it 'creates an enabled feature for the given user when passed user=username' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
+ it 'creates an enabled feature for the given user and feature group when passed user=username and feature_group=perf_team' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username, feature_group: 'perf_team' }
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq(feature_name)
+ expect(json_response['state']).to eq('conditional')
+ expect(json_response['gates']).to contain_exactly(
{ 'key' => 'boolean', 'value' => false },
+ { 'key' => 'groups', 'value' => ['perf_team'] },
{ 'key' => 'actors', 'value' => ["User:#{user.id}"] }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
-
- it 'creates an enabled feature for the given user and feature group when passed user=username and feature_group=perf_team' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username, feature_group: 'perf_team' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq(feature_name)
- expect(json_response['state']).to eq('conditional')
- expect(json_response['gates']).to contain_exactly(
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'groups', 'value' => ['perf_team'] },
- { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
- )
+ )
+ end
end
- end
- shared_examples 'does not enable the flag' do |actor_type|
- let(:actor_path) { raise NotImplementedError }
- let(:expected_inexistent_path) { actor_path }
+ shared_examples 'does not enable the flag' do |actor_type|
+ let(:actor_path) { raise NotImplementedError }
+ let(:expected_inexistent_path) { actor_path }
- it 'returns the current state of the flag without changes' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor_path }
+ it 'returns the current state of the flag without changes' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor_path }
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to eq("400 Bad request - #{expected_inexistent_path} is not found!")
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq("400 Bad request - #{expected_inexistent_path} is not found!")
+ end
end
- end
- shared_examples 'enables the flag for the actor' do |actor_type|
- it 'sets the feature gate' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor.full_path }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'actors', 'value' => ["#{actor.class}:#{actor.id}"] }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ shared_examples 'enables the flag for the actor' do |actor_type|
+ it 'sets the feature gate' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor.full_path }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["#{actor.class}:#{actor.id}"] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
end
- end
- shared_examples 'creates an enabled feature for the specified entries' do
- it do
- post api("/features/#{feature_name}", admin), params: { value: 'true', **gate_params }
+ shared_examples 'creates an enabled feature for the specified entries' do
+ it do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', **gate_params }
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq(feature_name)
- expect(json_response['gates']).to contain_exactly(
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'actors', 'value' => array_including(expected_gate_params) }
- )
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq(feature_name)
+ expect(json_response['gates']).to contain_exactly(
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => array_including(expected_gate_params) }
+ )
+ end
end
- end
- context 'when enabling for a project by path' do
- context 'when the project exists' do
- it_behaves_like 'enables the flag for the actor', :project do
- let(:actor) { create(:project) }
+ context 'when enabling for a project by path' do
+ context 'when the project exists' do
+ it_behaves_like 'enables the flag for the actor', :project do
+ let(:actor) { create(:project) }
+ end
end
- end
- context 'when the project does not exist' do
- it_behaves_like 'does not enable the flag', :project do
- let(:actor_path) { 'mep/to/the/mep/mep' }
+ context 'when the project does not exist' do
+ it_behaves_like 'does not enable the flag', :project do
+ let(:actor_path) { 'mep/to/the/mep/mep' }
+ end
end
end
- end
- context 'when enabling for a group by path' do
- context 'when the group exists' do
- it_behaves_like 'enables the flag for the actor', :group do
- let(:actor) { create(:group) }
+ context 'when enabling for a group by path' do
+ context 'when the group exists' do
+ it_behaves_like 'enables the flag for the actor', :group do
+ let(:actor) { create(:group) }
+ end
end
- end
- context 'when the group does not exist' do
- it_behaves_like 'does not enable the flag', :group do
- let(:actor_path) { 'not/a/group' }
+ context 'when the group does not exist' do
+ it_behaves_like 'does not enable the flag', :group do
+ let(:actor_path) { 'not/a/group' }
+ end
end
end
- end
- context 'when enabling for a namespace by path' do
- context 'when the user namespace exists' do
- it_behaves_like 'enables the flag for the actor', :namespace do
- let(:actor) { create(:namespace) }
+ context 'when enabling for a namespace by path' do
+ context 'when the user namespace exists' do
+ it_behaves_like 'enables the flag for the actor', :namespace do
+ let(:actor) { create(:namespace) }
+ end
end
- end
- context 'when the group namespace exists' do
- it_behaves_like 'enables the flag for the actor', :namespace do
- let(:actor) { create(:group) }
+ context 'when the group namespace exists' do
+ it_behaves_like 'enables the flag for the actor', :namespace do
+ let(:actor) { create(:group) }
+ end
end
- end
- context 'when the user namespace does not exist' do
- it_behaves_like 'does not enable the flag', :namespace do
- let(:actor_path) { 'not/a/group' }
+ context 'when the user namespace does not exist' do
+ it_behaves_like 'does not enable the flag', :namespace do
+ let(:actor_path) { 'not/a/group' }
+ end
end
- end
- context 'when a project namespace exists' do
- let(:project_namespace) { create(:project_namespace) }
+ context 'when a project namespace exists' do
+ let(:project_namespace) { create(:project_namespace) }
- it_behaves_like 'does not enable the flag', :namespace do
- let(:actor_path) { project_namespace.full_path }
+ it_behaves_like 'does not enable the flag', :namespace do
+ let(:actor_path) { project_namespace.full_path }
+ end
end
end
- end
- context 'with multiple users' do
- let_it_be(:users) { create_list(:user, 3) }
+ context 'with multiple users' do
+ let_it_be(:users) { create_list(:user, 3) }
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { user: users.map(&:username).join(',') } }
- let(:expected_gate_params) { users.map(&:flipper_id) }
- end
-
- context 'when empty value exists between comma' do
it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { user: "#{users.first.username},,,," } }
- let(:expected_gate_params) { users.first.flipper_id }
+ let(:gate_params) { { user: users.map(&:username).join(',') } }
+ let(:expected_gate_params) { users.map(&:flipper_id) }
end
- end
- context 'when one of the users does not exist' do
- it_behaves_like 'does not enable the flag', :user do
- let(:actor_path) { "#{users.first.username},inexistent-entry" }
- let(:expected_inexistent_path) { "inexistent-entry" }
+ context 'when empty value exists between comma' do
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { user: "#{users.first.username},,,," } }
+ let(:expected_gate_params) { users.first.flipper_id }
+ end
end
- end
- end
- context 'with multiple projects' do
- let_it_be(:projects) { create_list(:project, 3) }
-
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { project: projects.map(&:full_path).join(',') } }
- let(:expected_gate_params) { projects.map(&:flipper_id) }
- end
-
- context 'when empty value exists between comma' do
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { project: "#{projects.first.full_path},,,," } }
- let(:expected_gate_params) { projects.first.flipper_id }
+ context 'when one of the users does not exist' do
+ it_behaves_like 'does not enable the flag', :user do
+ let(:actor_path) { "#{users.first.username},inexistent-entry" }
+ let(:expected_inexistent_path) { "inexistent-entry" }
+ end
end
end
- context 'when one of the projects does not exist' do
- it_behaves_like 'does not enable the flag', :project do
- let(:actor_path) { "#{projects.first.full_path},inexistent-entry" }
- let(:expected_inexistent_path) { "inexistent-entry" }
- end
- end
- end
-
- context 'with multiple groups' do
- let_it_be(:groups) { create_list(:group, 3) }
+ context 'with multiple projects' do
+ let_it_be(:projects) { create_list(:project, 3) }
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { group: groups.map(&:full_path).join(',') } }
- let(:expected_gate_params) { groups.map(&:flipper_id) }
- end
-
- context 'when empty value exists between comma' do
it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { group: "#{groups.first.full_path},,,," } }
- let(:expected_gate_params) { groups.first.flipper_id }
+ let(:gate_params) { { project: projects.map(&:full_path).join(',') } }
+ let(:expected_gate_params) { projects.map(&:flipper_id) }
end
- end
- context 'when one of the groups does not exist' do
- it_behaves_like 'does not enable the flag', :group do
- let(:actor_path) { "#{groups.first.full_path},inexistent-entry" }
- let(:expected_inexistent_path) { "inexistent-entry" }
+ context 'when empty value exists between comma' do
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { project: "#{projects.first.full_path},,,," } }
+ let(:expected_gate_params) { projects.first.flipper_id }
+ end
end
- end
- end
-
- context 'with multiple namespaces' do
- let_it_be(:namespaces) { create_list(:namespace, 3) }
-
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { namespace: namespaces.map(&:full_path).join(',') } }
- let(:expected_gate_params) { namespaces.map(&:flipper_id) }
- end
- context 'when empty value exists between comma' do
- it_behaves_like 'creates an enabled feature for the specified entries' do
- let(:gate_params) { { namespace: "#{namespaces.first.full_path},,,," } }
- let(:expected_gate_params) { namespaces.first.flipper_id }
+ context 'when one of the projects does not exist' do
+ it_behaves_like 'does not enable the flag', :project do
+ let(:actor_path) { "#{projects.first.full_path},inexistent-entry" }
+ let(:expected_inexistent_path) { "inexistent-entry" }
+ end
end
end
- context 'when one of the namespaces does not exist' do
- it_behaves_like 'does not enable the flag', :namespace do
- let(:actor_path) { "#{namespaces.first.full_path},inexistent-entry" }
- let(:expected_inexistent_path) { "inexistent-entry" }
- end
- end
- end
-
- it 'creates a feature with the given percentage of time if passed an integer' do
- post api("/features/#{feature_name}", admin), params: { value: '50' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_time', 'value' => 50 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
-
- it 'creates a feature with the given percentage of time if passed a float' do
- post api("/features/#{feature_name}", admin), params: { value: '0.01' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_time', 'value' => 0.01 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
-
- it 'creates a feature with the given percentage of actors if passed an integer' do
- post api("/features/#{feature_name}", admin), params: { value: '50', key: 'percentage_of_actors' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_actors', 'value' => 50 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
-
- it 'creates a feature with the given percentage of actors if passed a float' do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_actors', 'value' => 0.01 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
- end
+ context 'with multiple groups' do
+ let_it_be(:groups) { create_list(:group, 3) }
- describe 'mutually exclusive parameters' do
- shared_examples 'fails to set the feature flag' do
- it 'returns an error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to match(/key, \w+ are mutually exclusive/)
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { group: groups.map(&:full_path).join(',') } }
+ let(:expected_gate_params) { groups.map(&:flipper_id) }
end
- end
- context 'when key and feature_group are provided' do
- before do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', feature_group: 'some-value' }
+ context 'when empty value exists between comma' do
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { group: "#{groups.first.full_path},,,," } }
+ let(:expected_gate_params) { groups.first.flipper_id }
+ end
end
- it_behaves_like 'fails to set the feature flag'
- end
-
- context 'when key and user are provided' do
- before do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', user: 'some-user' }
+ context 'when one of the groups does not exist' do
+ it_behaves_like 'does not enable the flag', :group do
+ let(:actor_path) { "#{groups.first.full_path},inexistent-entry" }
+ let(:expected_inexistent_path) { "inexistent-entry" }
+ end
end
-
- it_behaves_like 'fails to set the feature flag'
end
- context 'when key and group are provided' do
- before do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', group: 'somepath' }
- end
-
- it_behaves_like 'fails to set the feature flag'
- end
+ context 'with multiple namespaces' do
+ let_it_be(:namespaces) { create_list(:namespace, 3) }
- context 'when key and namespace are provided' do
- before do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', namespace: 'somepath' }
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { namespace: namespaces.map(&:full_path).join(',') } }
+ let(:expected_gate_params) { namespaces.map(&:flipper_id) }
end
- it_behaves_like 'fails to set the feature flag'
- end
-
- context 'when key and project are provided' do
- before do
- post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', project: 'somepath' }
+ context 'when empty value exists between comma' do
+ it_behaves_like 'creates an enabled feature for the specified entries' do
+ let(:gate_params) { { namespace: "#{namespaces.first.full_path},,,," } }
+ let(:expected_gate_params) { namespaces.first.flipper_id }
+ end
end
- it_behaves_like 'fails to set the feature flag'
+ context 'when one of the namespaces does not exist' do
+ it_behaves_like 'does not enable the flag', :namespace do
+ let(:actor_path) { "#{namespaces.first.full_path},inexistent-entry" }
+ let(:expected_inexistent_path) { "inexistent-entry" }
+ end
+ end
end
- end
- end
- context 'when the feature exists' do
- before do
- Feature.disable(feature_name) # This also persists the feature on the DB
- end
-
- context 'when passed value=true' do
- it 'enables the feature' do
- post api("/features/#{feature_name}", admin), params: { value: 'true' }
+ it 'creates a feature with the given percentage of time if passed an integer' do
+ post api("/features/#{feature_name}", admin), params: { value: '50' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
'name' => feature_name,
- 'state' => 'on',
- 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_time', 'value' => 50 }
+ ],
'definition' => known_feature_flag_definition_hash
)
end
- it 'enables the feature for the given Flipper group when passed feature_group=perf_team' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
+ it 'creates a feature with the given percentage of time if passed a float' do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
@@ -495,14 +385,14 @@ RSpec.describe API::Features, stub_feature_flags: false do
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
- { 'key' => 'groups', 'value' => ['perf_team'] }
+ { 'key' => 'percentage_of_time', 'value' => 0.01 }
],
'definition' => known_feature_flag_definition_hash
)
end
- it 'enables the feature for the given user when passed user=username' do
- post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
+ it 'creates a feature with the given percentage of actors if passed an integer' do
+ post api("/features/#{feature_name}", admin), params: { value: '50', key: 'percentage_of_actors' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
@@ -510,102 +400,230 @@ RSpec.describe API::Features, stub_feature_flags: false do
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
- { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
+ { 'key' => 'percentage_of_actors', 'value' => 50 }
],
'definition' => known_feature_flag_definition_hash
)
end
- end
-
- context 'when feature is enabled and value=false is passed' do
- it 'disables the feature' do
- Feature.enable(feature_name)
- expect(Feature.enabled?(feature_name)).to eq(true)
- post api("/features/#{feature_name}", admin), params: { value: 'false' }
+ it 'creates a feature with the given percentage of actors if passed a float' do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
'name' => feature_name,
- 'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_actors', 'value' => 0.01 }
+ ],
'definition' => known_feature_flag_definition_hash
)
end
- it 'disables the feature for the given Flipper group when passed feature_group=perf_team' do
- Feature.enable(feature_name, Feature.group(:perf_team))
- expect(Feature.enabled?(feature_name, admin)).to be_truthy
+ describe 'mutually exclusive parameters' do
+ shared_examples 'fails to set the feature flag' do
+ it 'returns an error' do
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to match(/key, \w+ are mutually exclusive/)
+ end
+ end
- post api("/features/#{feature_name}", admin), params: { value: 'false', feature_group: 'perf_team' }
+ context 'when key and feature_group are provided' do
+ before do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', feature_group: 'some-value' }
+ end
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }],
- 'definition' => known_feature_flag_definition_hash
- )
- end
+ it_behaves_like 'fails to set the feature flag'
+ end
- it 'disables the feature for the given user when passed user=username' do
- Feature.enable(feature_name, user)
- expect(Feature.enabled?(feature_name, user)).to be_truthy
+ context 'when key and user are provided' do
+ before do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', user: 'some-user' }
+ end
- post api("/features/#{feature_name}", admin), params: { value: 'false', user: user.username }
+ it_behaves_like 'fails to set the feature flag'
+ end
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }],
- 'definition' => known_feature_flag_definition_hash
- )
+ context 'when key and group are provided' do
+ before do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', group: 'somepath' }
+ end
+
+ it_behaves_like 'fails to set the feature flag'
+ end
+
+ context 'when key and namespace are provided' do
+ before do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', namespace: 'somepath' }
+ end
+
+ it_behaves_like 'fails to set the feature flag'
+ end
+
+ context 'when key and project are provided' do
+ before do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors', project: 'somepath' }
+ end
+
+ it_behaves_like 'fails to set the feature flag'
+ end
end
end
- context 'with a pre-existing percentage of time value' do
+ context 'when the feature exists' do
before do
- Feature.enable_percentage_of_time(feature_name, 50)
+ Feature.disable(feature_name) # This also persists the feature on the DB
end
- it 'updates the percentage of time if passed an integer' do
- post api("/features/#{feature_name}", admin), params: { value: '30' }
+ context 'when passed value=true' do
+ it 'enables the feature' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true' }
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_time', 'value' => 30 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'on',
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+
+ it 'enables the feature for the given Flipper group when passed feature_group=perf_team' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'groups', 'value' => ['perf_team'] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+
+ it 'enables the feature for the given user when passed user=username' do
+ post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
end
- end
- context 'with a pre-existing percentage of actors value' do
- before do
- Feature.enable_percentage_of_actors(feature_name, 42)
+ context 'when feature is enabled and value=false is passed' do
+ it 'disables the feature' do
+ Feature.enable(feature_name)
+ expect(Feature.enabled?(feature_name)).to eq(true)
+
+ post api("/features/#{feature_name}", admin), params: { value: 'false' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'off',
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+
+ it 'disables the feature for the given Flipper group when passed feature_group=perf_team' do
+ Feature.enable(feature_name, Feature.group(:perf_team))
+ expect(Feature.enabled?(feature_name, admin)).to be_truthy
+
+ post api("/features/#{feature_name}", admin), params: { value: 'false', feature_group: 'perf_team' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'off',
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+
+ it 'disables the feature for the given user when passed user=username' do
+ Feature.enable(feature_name, user)
+ expect(Feature.enabled?(feature_name, user)).to be_truthy
+
+ post api("/features/#{feature_name}", admin), params: { value: 'false', user: user.username }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'off',
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
end
- it 'updates the percentage of actors if passed an integer' do
- post api("/features/#{feature_name}", admin), params: { value: '74', key: 'percentage_of_actors' }
+ context 'with a pre-existing percentage of time value' do
+ before do
+ Feature.enable_percentage_of_time(feature_name, 50)
+ end
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to match(
- 'name' => feature_name,
- 'state' => 'conditional',
- 'gates' => [
- { 'key' => 'boolean', 'value' => false },
- { 'key' => 'percentage_of_actors', 'value' => 74 }
- ],
- 'definition' => known_feature_flag_definition_hash
- )
+ it 'updates the percentage of time if passed an integer' do
+ post api("/features/#{feature_name}", admin), params: { value: '30' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_time', 'value' => 30 }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+ end
+
+ context 'with a pre-existing percentage of actors value' do
+ before do
+ Feature.enable_percentage_of_actors(feature_name, 42)
+ end
+
+ it 'updates the percentage of actors if passed an integer' do
+ post api("/features/#{feature_name}", admin), params: { value: '74', key: 'percentage_of_actors' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_actors', 'value' => 74 }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
end
end
end
+
+ before do
+ stub_feature_flags(set_feature_flag_service: true)
+ end
+
+ it_behaves_like 'sets the feature flag status'
+
+ context 'when feature flag set_feature_flag_service is disabled' do
+ before do
+ stub_feature_flags(set_feature_flag_service: false)
+ end
+
+ it_behaves_like 'sets the feature flag status'
+ end
end
describe 'DELETE /feature/:name' do
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 823eafab734..0478e123086 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -602,6 +602,21 @@ RSpec.describe API::GenericPackages do
end
end
+ context 'with access to package registry for everyone' do
+ let_it_be(:user_role) { :anonymous }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+ end
+
+ it 'responds with success' do
+ download_file(auth_header)
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
context 'with package status' do
where(:package_status, :expected_status) do
:default | :success
diff --git a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
index c19defa37e8..2dc7b9764fe 100644
--- a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
+++ b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
@@ -48,6 +48,8 @@ RSpec.describe 'Getting Ci Cd Setting' do
expect(settings_data['mergeTrainsEnabled']).to eql project.ci_cd_settings.merge_trains_enabled?
expect(settings_data['keepLatestArtifact']).to eql project.keep_latest_artifacts_available?
expect(settings_data['jobTokenScopeEnabled']).to eql project.ci_cd_settings.job_token_scope_enabled?
+ expect(settings_data['inboundJobTokenScopeEnabled']).to eql(
+ project.ci_cd_settings.inbound_job_token_scope_enabled?)
end
end
end
diff --git a/spec/requests/api/graphql/ci/config_spec.rb b/spec/requests/api/graphql/ci/config_spec.rb
index 960fda80dd9..784019ee926 100644
--- a/spec/requests/api/graphql/ci/config_spec.rb
+++ b/spec/requests/api/graphql/ci/config_spec.rb
@@ -176,22 +176,22 @@ RSpec.describe 'Query.ciConfig' do
"jobs" =>
{
"nodes" => [
- {
- "name" => "docker",
- "groupName" => "docker",
- "stage" => "test",
- "script" => ["curl http://dockerhub/URL"],
- "beforeScript" => ["bundle install", "bundle exec rake db:create"],
- "afterScript" => ["echo 'run this after'"],
- "allowFailure" => true,
- "only" => { "refs" => %w[branches tags] },
- "when" => "manual",
- "except" => { "refs" => ["branches"] },
- "environment" => nil,
- "tags" => [],
- "needs" => { "nodes" => [{ "name" => "spinach" }, { "name" => "rspec 0 1" }] }
- }
- ]
+ {
+ "name" => "docker",
+ "groupName" => "docker",
+ "stage" => "test",
+ "script" => ["curl http://dockerhub/URL"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => true,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "manual",
+ "except" => { "refs" => ["branches"] },
+ "environment" => nil,
+ "tags" => [],
+ "needs" => { "nodes" => [{ "name" => "spinach" }, { "name" => "rspec 0 1" }] }
+ }
+ ]
}
}
]
@@ -209,22 +209,22 @@ RSpec.describe 'Query.ciConfig' do
"jobs" =>
{
"nodes" => [
- {
- "name" => "deploy_job",
- "groupName" => "deploy_job",
- "stage" => "deploy",
- "script" => ["echo 'done'"],
- "beforeScript" => ["bundle install", "bundle exec rake db:create"],
- "afterScript" => ["echo 'run this after'"],
- "allowFailure" => false,
- "only" => { "refs" => %w[branches tags] },
- "when" => "on_success",
- "except" => nil,
- "environment" => "production",
- "tags" => [],
- "needs" => { "nodes" => [] }
- }
- ]
+ {
+ "name" => "deploy_job",
+ "groupName" => "deploy_job",
+ "stage" => "deploy",
+ "script" => ["echo 'done'"],
+ "beforeScript" => ["bundle install", "bundle exec rake db:create"],
+ "afterScript" => ["echo 'run this after'"],
+ "allowFailure" => false,
+ "only" => { "refs" => %w[branches tags] },
+ "when" => "on_success",
+ "except" => nil,
+ "environment" => "production",
+ "tags" => [],
+ "needs" => { "nodes" => [] }
+ }
+ ]
}
}
]
diff --git a/spec/requests/api/graphql/ci/config_variables_spec.rb b/spec/requests/api/graphql/ci/config_variables_spec.rb
index 2b5a5d0dc93..17133d7ea66 100644
--- a/spec/requests/api/graphql/ci/config_variables_spec.rb
+++ b/spec/requests/api/graphql/ci/config_variables_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)' do
ciConfigVariables(sha: "#{sha}") {
key
value
+ valueOptions
description
}
}
@@ -53,13 +54,21 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)' do
expect(graphql_data.dig('project', 'ciConfigVariables')).to contain_exactly(
{
+ 'key' => 'KEY_VALUE_VAR',
+ 'value' => 'value x',
+ 'valueOptions' => nil,
+ 'description' => 'value of KEY_VALUE_VAR'
+ },
+ {
'key' => 'DB_NAME',
'value' => 'postgres',
+ 'valueOptions' => nil,
'description' => nil
},
{
'key' => 'ENVIRONMENT_VAR',
'value' => 'env var value',
+ 'valueOptions' => ['env var value', 'env var value2'],
'description' => 'env var description'
}
)
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb
index fa8fb1d54aa..47e3221c567 100644
--- a/spec/requests/api/graphql/ci/jobs_spec.rb
+++ b/spec/requests/api/graphql/ci/jobs_spec.rb
@@ -25,11 +25,12 @@ RSpec.describe 'Query.project.pipeline' do
let(:first_n) { var('Int') }
let(:query) do
- with_signature([first_n], wrap_fields(query_graphql_path([
- [:project, { full_path: project.full_path }],
- [:pipeline, { iid: pipeline.iid.to_s }],
- [:stages, { first: first_n }]
- ], stage_fields)))
+ with_signature([first_n], wrap_fields(query_graphql_path(
+ [
+ [:project, { full_path: project.full_path }],
+ [:pipeline, { iid: pipeline.iid.to_s }],
+ [:stages, { first: first_n }]
+ ], stage_fields)))
end
let(:stage_fields) do
diff --git a/spec/requests/api/graphql/ci/pipeline_schedules_spec.rb b/spec/requests/api/graphql/ci/pipeline_schedules_spec.rb
new file mode 100644
index 00000000000..8b8ba09a95c
--- /dev/null
+++ b/spec/requests/api/graphql/ci/pipeline_schedules_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project.pipelineSchedules' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+
+ let(:pipeline_schedule_graphql_data) { graphql_data_at(:project, :pipeline_schedules, :nodes, 0) }
+
+ let(:params) { {} }
+
+ let(:fields) do
+ <<~QUERY
+ nodes {
+ id
+ description
+ active
+ nextRunAt
+ realNextRun
+ lastPipeline {
+ id
+ }
+ refForDisplay
+ refPath
+ forTag
+ cron
+ cronTimezone
+ }
+ QUERY
+ end
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelineSchedules {
+ #{fields}
+ }
+ }
+ }
+ )
+ end
+
+ describe 'computed graphql fields' do
+ before do
+ pipeline_schedule.pipelines << build(:ci_pipeline, project: project)
+
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns calculated fields for a pipeline schedule' do
+ ref_for_display = pipeline_schedule_graphql_data['refForDisplay']
+
+ expect(ref_for_display).to eq('master')
+ expect(pipeline_schedule_graphql_data['refPath']).to eq("/#{project.full_path}/-/commits/#{ref_for_display}")
+ expect(pipeline_schedule_graphql_data['forTag']).to be(false)
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ create_pipeline_schedules(1)
+
+ control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: user) }
+
+ create_pipeline_schedules(3)
+
+ action = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: user) }
+
+ expect(action).not_to exceed_query_limit(control)
+ end
+
+ def create_pipeline_schedules(count)
+ create_list(:ci_pipeline_schedule, count, project: project)
+ .each do |pipeline_schedule|
+ create(:user).tap do |user|
+ project.add_developer(user)
+ pipeline_schedule.update!(owner: user)
+ end
+ pipeline_schedule.pipelines << build(:ci_pipeline, project: project)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/jobs_query_spec.rb b/spec/requests/api/graphql/jobs_query_spec.rb
new file mode 100644
index 00000000000..5907566be7f
--- /dev/null
+++ b/spec/requests/api/graphql/jobs_query_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting job information' do
+ include GraphqlHelpers
+
+ let_it_be(:job) { create(:ci_build, :success, name: 'job1') }
+
+ let(:query) do
+ graphql_query_for(:jobs)
+ end
+
+ context 'when user is admin' do
+ let_it_be(:current_user) { create(:admin) }
+
+ it 'has full access to all jobs', :aggregate_failure do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:jobs, :count)).to eq(1)
+ expect(graphql_data_at(:jobs, :nodes)).to contain_exactly(a_graphql_entity_for(job))
+ end
+
+ context 'when filtered by status' do
+ let_it_be(:pending_job) { create(:ci_build, :pending) }
+ let_it_be(:failed_job) { create(:ci_build, :failed) }
+
+ it 'gets pending jobs', :aggregate_failure do
+ post_graphql(graphql_query_for(:jobs, { statuses: :PENDING }), current_user: current_user)
+
+ expect(graphql_data_at(:jobs, :count)).to eq(1)
+ expect(graphql_data_at(:jobs, :nodes)).to contain_exactly(a_graphql_entity_for(pending_job))
+ end
+
+ it 'gets pending and failed jobs', :aggregate_failure do
+ post_graphql(graphql_query_for(:jobs, { statuses: [:PENDING, :FAILED] }), current_user: current_user)
+
+ expect(graphql_data_at(:jobs, :count)).to eq(2)
+ expect(graphql_data_at(:jobs, :nodes)).to match_array([a_graphql_entity_for(pending_job),
+ a_graphql_entity_for(failed_job)])
+ end
+ end
+ end
+
+ context 'if the user is not an admin' do
+ let_it_be(:current_user) { create(:user) }
+
+ it 'has no access to the jobs', :aggregate_failure do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:jobs, :count)).to eq(0)
+ expect(graphql_data_at(:jobs, :nodes)).to match_array([])
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/milestone_spec.rb b/spec/requests/api/graphql/milestone_spec.rb
index f6835936418..78e7ec39ee3 100644
--- a/spec/requests/api/graphql/milestone_spec.rb
+++ b/spec/requests/api/graphql/milestone_spec.rb
@@ -5,8 +5,12 @@ require 'spec_helper'
RSpec.describe 'Querying a Milestone' do
include GraphqlHelpers
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:guest) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:inherited_guest) { create(:user) }
+ let_it_be(:inherited_reporter) { create(:user) }
+ let_it_be(:inherited_developer) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:release_a) { create(:release, project: project) }
let_it_be(:release_b) { create(:release, project: project) }
@@ -14,116 +18,137 @@ RSpec.describe 'Querying a Milestone' do
before_all do
milestone.releases << [release_a, release_b]
project.add_guest(guest)
+ group.add_guest(inherited_guest)
+ group.add_reporter(inherited_reporter)
+ group.add_developer(inherited_developer)
end
let(:expected_release_nodes) do
contain_exactly(a_graphql_entity_for(release_a), a_graphql_entity_for(release_b))
end
- context 'when we post the query' do
- let(:current_user) { nil }
- let(:query) do
- graphql_query_for('milestone', { id: milestone.to_global_id.to_s }, all_graphql_fields_for('Milestone'))
- end
+ shared_examples 'returns the milestone successfully' do
+ it_behaves_like 'a working graphql query'
- subject { graphql_data['milestone'] }
+ it { is_expected.to include('title' => milestone.name) }
- before do
- post_graphql(query, current_user: current_user)
+ it 'contains release information' do
+ is_expected.to include('releases' => include('nodes' => expected_release_nodes))
end
+ end
- context 'when the user has access to the milestone' do
- let(:current_user) { guest }
-
- it_behaves_like 'a working graphql query'
-
- it { is_expected.to include('title' => milestone.name) }
-
- it 'contains release information' do
- is_expected.to include('releases' => include('nodes' => expected_release_nodes))
+ context 'when we post the query' do
+ context 'and the project is private' do
+ let(:query) do
+ graphql_query_for('milestone', { id: milestone.to_global_id.to_s }, all_graphql_fields_for('Milestone'))
end
- end
- context 'when the user does not have access to the milestone' do
- it_behaves_like 'a working graphql query'
-
- it { is_expected.to be_nil }
- end
+ subject { graphql_data['milestone'] }
- context 'when ID argument is missing' do
- let(:query) do
- graphql_query_for('milestone', {}, 'title')
+ before do
+ post_graphql(query, current_user: current_user)
end
- it 'raises an exception' do
- expect(graphql_errors).to include(a_hash_including('message' => "Field 'milestone' is missing required arguments: id"))
+ context 'when the user is a direct project member' do
+ context 'and the user is a guest' do
+ let(:current_user) { guest }
+
+ it_behaves_like 'returns the milestone successfully'
+
+ context 'when there are two milestones' do
+ let_it_be(:milestone_b) { create(:milestone, project: project) }
+
+ let(:milestone_fields) do
+ <<~GQL
+ fragment milestoneFields on Milestone {
+ #{all_graphql_fields_for('Milestone', max_depth: 1)}
+ releases { nodes { #{all_graphql_fields_for('Release', max_depth: 1)} } }
+ }
+ GQL
+ end
+
+ let(:single_query) do
+ <<~GQL
+ query ($id_a: MilestoneID!) {
+ a: milestone(id: $id_a) { ...milestoneFields }
+ }
+
+ #{milestone_fields}
+ GQL
+ end
+
+ let(:multi_query) do
+ <<~GQL
+ query ($id_a: MilestoneID!, $id_b: MilestoneID!) {
+ a: milestone(id: $id_a) { ...milestoneFields }
+ b: milestone(id: $id_b) { ...milestoneFields }
+ }
+ #{milestone_fields}
+ GQL
+ end
+
+ it 'returns the correct releases associated with each milestone' do
+ r = run_with_clean_state(multi_query,
+ context: { current_user: current_user },
+ variables: {
+ id_a: global_id_of(milestone).to_s,
+ id_b: milestone_b.to_global_id.to_s
+ })
+
+ expect(r.to_h['errors']).to be_blank
+ expect(graphql_dig_at(r.to_h, :data, :a, :releases, :nodes)).to match expected_release_nodes
+ expect(graphql_dig_at(r.to_h, :data, :b, :releases, :nodes)).to be_empty
+ end
+
+ it 'does not suffer from N+1 performance issues' do
+ baseline = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(single_query,
+ context: { current_user: current_user },
+ variables: { id_a: milestone.to_global_id.to_s })
+ end
+
+ multi = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(multi_query,
+ context: { current_user: current_user },
+ variables: {
+ id_a: milestone.to_global_id.to_s,
+ id_b: milestone_b.to_global_id.to_s
+ })
+ end
+
+ expect(multi).not_to exceed_query_limit(baseline)
+ end
+ end
+ end
end
- end
- end
- context 'when there are two milestones' do
- let_it_be(:milestone_b) { create(:milestone, project: project) }
-
- let(:current_user) { guest }
- let(:milestone_fields) do
- <<~GQL
- fragment milestoneFields on Milestone {
- #{all_graphql_fields_for('Milestone', max_depth: 1)}
- releases { nodes { #{all_graphql_fields_for('Release', max_depth: 1)} } }
- }
- GQL
- end
+ context 'when the user is an inherited member from the group' do
+ where(:user) { [ref(:inherited_guest), ref(:inherited_reporter), ref(:inherited_developer)] }
- let(:single_query) do
- <<~GQL
- query ($id_a: MilestoneID!) {
- a: milestone(id: $id_a) { ...milestoneFields }
- }
+ with_them do
+ let(:current_user) { user }
- #{milestone_fields}
- GQL
- end
+ it_behaves_like 'returns the milestone successfully'
+ end
+ end
- let(:multi_query) do
- <<~GQL
- query ($id_a: MilestoneID!, $id_b: MilestoneID!) {
- a: milestone(id: $id_a) { ...milestoneFields }
- b: milestone(id: $id_b) { ...milestoneFields }
- }
- #{milestone_fields}
- GQL
- end
+ context 'when unauthenticated' do
+ let(:current_user) { nil }
- it 'produces correct results' do
- r = run_with_clean_state(multi_query,
- context: { current_user: current_user },
- variables: {
- id_a: global_id_of(milestone).to_s,
- id_b: milestone_b.to_global_id.to_s
- })
-
- expect(r.to_h['errors']).to be_blank
- expect(graphql_dig_at(r.to_h, :data, :a, :releases, :nodes)).to match expected_release_nodes
- expect(graphql_dig_at(r.to_h, :data, :b, :releases, :nodes)).to be_empty
- end
+ it_behaves_like 'a working graphql query'
- it 'does not suffer from N+1 performance issues' do
- baseline = ActiveRecord::QueryRecorder.new do
- run_with_clean_state(single_query,
- context: { current_user: current_user },
- variables: { id_a: milestone.to_global_id.to_s })
- end
+ it { is_expected.to be_nil }
- multi = ActiveRecord::QueryRecorder.new do
- run_with_clean_state(multi_query,
- context: { current_user: current_user },
- variables: {
- id_a: milestone.to_global_id.to_s,
- id_b: milestone_b.to_global_id.to_s
- })
- end
+ context 'when ID argument is missing' do
+ let(:query) do
+ graphql_query_for('milestone', {}, 'title')
+ end
- expect(multi).not_to exceed_query_limit(baseline)
+ it 'raises an exception' do
+ expect(graphql_errors).to include(a_hash_including('message' => "Field 'milestone' is missing required arguments: id"))
+ end
+ end
+ end
end
end
end
diff --git a/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb
new file mode 100644
index 00000000000..bdad80995ea
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/job/artifacts_destroy_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'JobArtifactsDestroy' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:job) { create(:ci_build) }
+
+ let(:mutation) do
+ variables = {
+ id: job.to_global_id.to_s
+ }
+ graphql_mutation(:job_artifacts_destroy, variables, <<~FIELDS)
+ job {
+ name
+ }
+ destroyedArtifactsCount
+ errors
+ FIELDS
+ end
+
+ before do
+ create(:ci_job_artifact, :archive, job: job)
+ create(:ci_job_artifact, :junit, job: job)
+ end
+
+ context 'when the user is not allowed to destroy the job artifacts' do
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).not_to be_empty
+ expect(job.reload.job_artifacts.count).to be(2)
+ end
+ end
+
+ context 'when the user is allowed to destroy the job artifacts' do
+ before do
+ job.project.add_maintainer(user)
+ end
+
+ it 'destroys the job artifacts and returns the expected data' do
+ expected_data = {
+ 'jobArtifactsDestroy' => {
+ 'errors' => [],
+ 'destroyedArtifactsCount' => 2,
+ 'job' => {
+ 'name' => job.name
+ }
+ }
+ }
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_data).to eq(expected_data)
+ expect(job.reload.job_artifacts.count).to be(0)
+ end
+
+ context 'when the the project this job belongs to is undergoing stats refresh' do
+ it 'destroys no artifacts and returns the correct error' do
+ allow_next_found_instance_of(Project) do |project|
+ allow(project).to receive(:refreshing_build_artifacts_size?).and_return(true)
+ end
+
+ expected_data = {
+ 'jobArtifactsDestroy' => {
+ 'errors' => ['Action temporarily disabled. The project this job belongs to is undergoing stats refresh.'],
+ 'destroyedArtifactsCount' => 0,
+ 'job' => {
+ 'name' => job.name
+ }
+ }
+ }
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_data).to eq(expected_data)
+ expect(job.reload.job_artifacts.count).to be(2)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
index 5269c60b50a..b2f84ab2869 100644
--- a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'CiJobTokenScopeAddProject' do
include GraphqlHelpers
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let(:variables) do
diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
index b62291d1ebd..2b0adf89f40 100644
--- a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'CiJobTokenScopeRemoveProject' do
include GraphqlHelpers
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let_it_be(:link) do
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb
new file mode 100644
index 00000000000..b197d223463
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_delete_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineScheduleDelete' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+
+ let(:mutation) do
+ graphql_mutation(
+ :pipeline_schedule_delete,
+ { id: pipeline_schedule_id },
+ <<-QL
+ errors
+ QL
+ )
+ end
+
+ let(:pipeline_schedule_id) { pipeline_schedule.to_global_id.to_s }
+ let(:mutation_response) { graphql_mutation_response(:pipeline_schedule_delete) }
+
+ context 'when unauthorized' do
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ expect(graphql_errors[0]['message'])
+ .to eq(
+ "The resource that you are attempting to access does not exist " \
+ "or you don't have permission to perform this action"
+ )
+ end
+ end
+
+ context 'when authorized' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when success' do
+ it do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['errors']).to eq([])
+ end
+ end
+
+ context 'when failure' do
+ context 'when destroy fails' do
+ before do
+ allow_next_found_instance_of(Ci::PipelineSchedule) do |pipeline_schedule|
+ allow(pipeline_schedule).to receive(:destroy).and_return(false)
+ end
+ end
+
+ it do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+
+ expect(mutation_response['errors']).to match_array(['Failed to remove the pipeline schedule'])
+ end
+ end
+
+ context 'when pipeline schedule not found' do
+ let(:pipeline_schedule_id) { 'gid://gitlab/Ci::PipelineSchedule/0' }
+
+ it do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).not_to be_empty
+ expect(graphql_errors[0]['message'])
+ .to eq("Internal server error: Couldn't find Ci::PipelineSchedule with 'id'=0")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb b/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb
index 394d9ff53d1..c808cf5ede9 100644
--- a/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/project_ci_cd_settings_update_spec.rb
@@ -6,15 +6,19 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
include GraphqlHelpers
let_it_be(:project) do
- create(:project, keep_latest_artifact: true, ci_job_token_scope_enabled: true)
- .tap(&:save!)
+ create(:project,
+ keep_latest_artifact: true,
+ ci_outbound_job_token_scope_enabled: true,
+ ci_inbound_job_token_scope_enabled: true
+ ).tap(&:save!)
end
let(:variables) do
{
full_path: project.full_path,
keep_latest_artifact: false,
- job_token_scope_enabled: false
+ job_token_scope_enabled: false,
+ inbound_job_token_scope_enabled: false
}
end
@@ -62,7 +66,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
project.reload
expect(response).to have_gitlab_http_status(:success)
- expect(project.ci_job_token_scope_enabled).to eq(false)
+ expect(project.ci_outbound_job_token_scope_enabled).to eq(false)
end
it 'does not update job_token_scope_enabled if not specified' do
@@ -73,7 +77,44 @@ RSpec.describe 'ProjectCiCdSettingsUpdate' do
project.reload
expect(response).to have_gitlab_http_status(:success)
- expect(project.ci_job_token_scope_enabled).to eq(true)
+ expect(project.ci_outbound_job_token_scope_enabled).to eq(true)
+ end
+
+ describe 'inbound_job_token_scope_enabled' do
+ it 'updates inbound_job_token_scope_enabled' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_inbound_job_token_scope_enabled).to eq(false)
+ end
+
+ it 'does not update inbound_job_token_scope_enabled if not specified' do
+ variables.except!(:inbound_job_token_scope_enabled)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_inbound_job_token_scope_enabled).to eq(true)
+ end
+
+ context 'when ci_inbound_job_token_scope disabled' do
+ before do
+ stub_feature_flags(ci_inbound_job_token_scope: false)
+ end
+
+ it 'does not update inbound_job_token_scope_enabled' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_inbound_job_token_scope_enabled).to eq(true)
+ end
+ end
end
context 'when bad arguments are provided' do
diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
index 194e42bf59d..567d8799d93 100644
--- a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
@@ -14,7 +14,13 @@ RSpec.describe 'Updating the package settings' do
maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'foo-.*',
generic_duplicates_allowed: false,
- generic_duplicate_exception_regex: 'bar-.*'
+ generic_duplicate_exception_regex: 'bar-.*',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
}
end
@@ -26,6 +32,12 @@ RSpec.describe 'Updating the package settings' do
mavenDuplicateExceptionRegex
genericDuplicatesAllowed
genericDuplicateExceptionRegex
+ mavenPackageRequestsForwarding
+ lockMavenPackageRequestsForwarding
+ npmPackageRequestsForwarding
+ lockNpmPackageRequestsForwarding
+ pypiPackageRequestsForwarding
+ lockPypiPackageRequestsForwarding
}
errors
QL
@@ -46,6 +58,12 @@ RSpec.describe 'Updating the package settings' do
expect(package_settings_response['mavenDuplicateExceptionRegex']).to eq(params[:maven_duplicate_exception_regex])
expect(package_settings_response['genericDuplicatesAllowed']).to eq(params[:generic_duplicates_allowed])
expect(package_settings_response['genericDuplicateExceptionRegex']).to eq(params[:generic_duplicate_exception_regex])
+ expect(package_settings_response['mavenPackageRequestsForwarding']).to eq(params[:maven_package_requests_forwarding])
+ expect(package_settings_response['lockMavenPackageRequestsForwarding']).to eq(params[:lock_maven_package_requests_forwarding])
+ expect(package_settings_response['pypiPackageRequestsForwarding']).to eq(params[:pypi_package_requests_forwarding])
+ expect(package_settings_response['lockPypiPackageRequestsForwarding']).to eq(params[:lock_pypi_package_requests_forwarding])
+ expect(package_settings_response['npmPackageRequestsForwarding']).to eq(params[:npm_package_requests_forwarding])
+ expect(package_settings_response['lockNpmPackageRequestsForwarding']).to eq(params[:lock_npm_package_requests_forwarding])
end
end
@@ -75,8 +93,29 @@ RSpec.describe 'Updating the package settings' do
RSpec.shared_examples 'accepting the mutation request updating the package settings' do
it_behaves_like 'updating the namespace package setting attributes',
- from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
- to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'foo-.*', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar-.*' }
+ from: {
+ maven_duplicates_allowed: true,
+ maven_duplicate_exception_regex: 'SNAPSHOT',
+ generic_duplicates_allowed: true,
+ generic_duplicate_exception_regex: 'foo',
+ maven_package_requests_forwarding: nil,
+ lock_maven_package_requests_forwarding: false,
+ npm_package_requests_forwarding: nil,
+ lock_npm_package_requests_forwarding: false,
+ pypi_package_requests_forwarding: nil,
+ lock_pypi_package_requests_forwarding: false
+ }, to: {
+ maven_duplicates_allowed: false,
+ maven_duplicate_exception_regex: 'foo-.*',
+ generic_duplicates_allowed: false,
+ generic_duplicate_exception_regex: 'bar-.*',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
+ }
it_behaves_like 'returning a success'
it_behaves_like 'rejecting invalid regex'
diff --git a/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb b/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb
new file mode 100644
index 00000000000..1fe01af4f1c
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/packages/bulk_destroy_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Destroying multiple packages' do
+ using RSpec::Parameterized::TableSyntax
+
+ include GraphqlHelpers
+
+ let_it_be(:project1) { create(:project) }
+ let_it_be(:project2) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:packages1) { create_list(:package, 3, project: project1) }
+ let_it_be_with_reload(:packages2) { create_list(:package, 2, project: project2) }
+
+ let(:ids) { packages1.append(packages2).flatten.map(&:to_global_id).map(&:to_s) }
+
+ let(:query) do
+ <<~GQL
+ errors
+ GQL
+ end
+
+ let(:params) do
+ {
+ ids: ids
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:destroy_packages, params, query) }
+
+ describe 'post graphql mutation' do
+ subject(:mutation_request) { post_graphql_mutation(mutation, current_user: user) }
+
+ shared_examples 'destroying the packages' do
+ it 'marks the packages as pending destruction' do
+ expect { mutation_request }.to change { ::Packages::Package.pending_destruction.count }.by(5)
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ shared_examples 'denying the mutation request' do
+ |response = ::Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR|
+ it 'does not mark the packages as pending destruction' do
+ expect { mutation_request }.not_to change { ::Packages::Package.pending_destruction.count }
+ expect_graphql_errors_to_include(response)
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'with valid params' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'destroying the packages'
+ :developer | 'denying the mutation request'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :not_in_project | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ unless user_role == :not_in_project
+ project1.send("add_#{user_role}", user)
+ project2.send("add_#{user_role}", user)
+ end
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+
+ context 'for over the limit' do
+ before do
+ project1.add_maintainer(user)
+ project2.add_maintainer(user)
+ stub_const("Mutations::Packages::BulkDestroy::MAX_PACKAGES", 2)
+ end
+
+ it_behaves_like 'denying the mutation request', ::Mutations::Packages::BulkDestroy::TOO_MANY_IDS_ERROR
+ end
+
+ context 'with packages outside of the project' do
+ before do
+ project1.add_maintainer(user)
+ end
+
+ it_behaves_like 'denying the mutation request'
+ end
+ end
+
+ context 'with invalid params' do
+ let(:ids) { 'foo' }
+
+ it_behaves_like 'denying the mutation request', 'invalid value for id'
+ end
+
+ context 'with multi mutations' do
+ let(:package1) { packages1.first }
+ let(:package2) { packages2.first }
+ let(:query) do
+ <<~QUERY
+ mutation {
+ a: destroyPackages(input: { ids: ["#{package1.to_global_id}"]}) {
+ errors
+ }
+ b: destroyPackages(input: { ids: ["#{package2.to_global_id}"]}) {
+ errors
+ }
+ }
+ QUERY
+ end
+
+ subject(:mutation_request) { post_graphql(query, current_user: user) }
+
+ before do
+ project1.add_maintainer(user)
+ project2.add_maintainer(user)
+ end
+
+ it 'executes the first mutation but not the second one' do
+ expect { mutation_request }.to change { package1.reload.status }.from('default').to('pending_destruction')
+ .and not_change { package2.reload.status }
+ expect_graphql_errors_to_include('"destroyPackages" field can be requested only for 1 Mutation(s) at a time.')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/uploads/delete_spec.rb b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb
index f44bf179397..2d1b33cc086 100644
--- a/spec/requests/api/graphql/mutations/uploads/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb
@@ -47,10 +47,11 @@ RSpec.describe 'Delete an upload' do
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['upload']).to be_nil
- expect(mutation_response['errors']).to match_array([
- "The resource that you are attempting to access does not "\
- "exist or you don't have permission to perform this action."
- ])
+ expect(mutation_response['errors']).to match_array(
+ [
+ "The resource that you are attempting to access does not "\
+ "exist or you don't have permission to perform this action."
+ ])
end
end
end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
index 909d6549fa5..6b0129c457f 100644
--- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -144,6 +144,78 @@ RSpec.describe 'Update a work item' do
end
end
+ context 'with labels widget input' do
+ shared_examples 'mutation updating work item labels' do
+ it 'updates labels' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change { work_item.labels.count }.to(expected_labels.count)
+
+ expect(work_item.labels).to match_array(expected_labels)
+ expect(mutation_response['workItem']['widgets']).to include(
+ 'labels' => {
+ 'nodes' => match_array(expected_labels.map { |l| { 'id' => l.to_gid.to_s } })
+ },
+ 'type' => 'LABELS'
+ )
+ end
+ end
+
+ let_it_be(:existing_label) { create(:label, project: project) }
+ let_it_be(:label1) { create(:label, project: project) }
+ let_it_be(:label2) { create(:label, project: project) }
+
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ widgets {
+ type
+ ... on WorkItemWidgetLabels {
+ labels {
+ nodes { id }
+ }
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ let(:input) do
+ { 'labelsWidget' => { 'addLabelIds' => add_label_ids, 'removeLabelIds' => remove_label_ids } }
+ end
+
+ let(:add_label_ids) { [] }
+ let(:remove_label_ids) { [] }
+
+ before_all do
+ work_item.update!(labels: [existing_label])
+ end
+
+ context 'when only removing labels' do
+ let(:remove_label_ids) { [existing_label.to_gid.to_s] }
+ let(:expected_labels) { [] }
+
+ it_behaves_like 'mutation updating work item labels'
+ end
+
+ context 'when only adding labels' do
+ let(:add_label_ids) { [label1.to_gid.to_s, label2.to_gid.to_s] }
+ let(:expected_labels) { [label1, label2, existing_label] }
+
+ it_behaves_like 'mutation updating work item labels'
+ end
+
+ context 'when adding and removing labels' do
+ let(:remove_label_ids) { [existing_label.to_gid.to_s] }
+ let(:add_label_ids) { [label1.to_gid.to_s, label2.to_gid.to_s] }
+ let(:expected_labels) { [label1, label2] }
+
+ it_behaves_like 'mutation updating work item labels'
+ end
+ end
+
context 'with due and start date widget input' do
let(:start_date) { Date.today }
let(:due_date) { 1.week.from_now.to_date }
diff --git a/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb
deleted file mode 100644
index 2a5cb937a2f..00000000000
--- a/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Update work item widgets' do
- include GraphqlHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
- let_it_be(:work_item, refind: true) { create(:work_item, project: project) }
-
- let(:input) { { 'descriptionWidget' => { 'description' => 'updated description' } } }
- let(:mutation_response) { graphql_mutation_response(:work_item_update_widgets) }
- let(:mutation) do
- graphql_mutation(:workItemUpdateWidgets, input.merge('id' => work_item.to_global_id.to_s), <<~FIELDS)
- errors
- workItem {
- description
- widgets {
- type
- ... on WorkItemWidgetDescription {
- description
- }
- }
- }
- FIELDS
- end
-
- context 'the user is not allowed to update a work item' do
- let(:current_user) { create(:user) }
-
- it_behaves_like 'a mutation that returns a top-level access error'
- end
-
- context 'when user has permissions to update a work item', :aggregate_failures do
- let(:current_user) { developer }
-
- it_behaves_like 'update work item description widget' do
- let(:new_description) { 'updated description' }
- end
-
- it_behaves_like 'has spam protection' do
- let(:mutation_class) { ::Mutations::WorkItems::UpdateWidgets }
- end
-
- context 'when the work_items feature flag is disabled' do
- before do
- stub_feature_flags(work_items: false)
- end
-
- it 'does not update the work item and returns and error' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- work_item.reload
- end.to not_change(work_item, :description)
-
- expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
- end
- end
- end
-end
diff --git a/spec/requests/api/graphql/project/branch_rules_spec.rb b/spec/requests/api/graphql/project/branch_rules_spec.rb
index 70fb37941e2..1aaf0e9edc7 100644
--- a/spec/requests/api/graphql/project/branch_rules_spec.rb
+++ b/spec/requests/api/graphql/project/branch_rules_spec.rb
@@ -21,27 +21,24 @@ RSpec.describe 'getting list of branch rules for a project' do
let(:branch_rules_data) { graphql_data_at('project', 'branchRules', 'edges') }
let(:variables) { { path: project.full_path } }
-
- let(:fields) do
- <<~QUERY
- pageInfo {
- hasNextPage
- hasPreviousPage
- }
- edges {
- cursor
- node {
- #{all_graphql_fields_for('branch_rules'.classify)}
- }
- }
- QUERY
- end
-
+ # fields must use let as the all_graphql_fields_for also configures some spies
+ let(:fields) { all_graphql_fields_for('BranchRule') }
let(:query) do
<<~GQL
query($path: ID!, $n: Int, $cursor: String) {
project(fullPath: $path) {
- branchRules(first: $n, after: $cursor) { #{fields} }
+ branchRules(first: $n, after: $cursor) {
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ }
+ edges {
+ cursor
+ node {
+ #{fields}
+ }
+ }
+ }
}
}
GQL
@@ -55,7 +52,9 @@ RSpec.describe 'getting list of branch rules for a project' do
it_behaves_like 'a working graphql query'
- it { expect(branch_rules_data).to be_empty }
+ it 'hides branch rules data' do
+ expect(branch_rules_data).to be_empty
+ end
end
context 'when the user does have read_protected_branch abilities' do
@@ -66,12 +65,17 @@ RSpec.describe 'getting list of branch rules for a project' do
it_behaves_like 'a working graphql query'
- it 'includes a name' do
+ it 'returns branch rules data' do
expect(branch_rules_data.dig(0, 'node', 'name')).to be_present
- end
-
- it 'includes created_at and updated_at' do
+ expect(branch_rules_data.dig(0, 'node', 'isDefault')).to be(true).or be(false)
+ expect(branch_rules_data.dig(0, 'node', 'branchProtection')).to be_present
expect(branch_rules_data.dig(0, 'node', 'createdAt')).to be_present
+ expect(branch_rules_data.dig(0, 'node', 'updatedAt')).to be_present
+
+ expect(branch_rules_data.dig(1, 'node', 'name')).to be_present
+ expect(branch_rules_data.dig(1, 'node', 'isDefault')).to be(true).or be(false)
+ expect(branch_rules_data.dig(1, 'node', 'branchProtection')).to be_present
+ expect(branch_rules_data.dig(1, 'node', 'createdAt')).to be_present
expect(branch_rules_data.dig(1, 'node', 'updatedAt')).to be_present
end
@@ -82,16 +86,16 @@ RSpec.describe 'getting list of branch rules for a project' do
{ path: project.full_path, n: branch_rule_limit, cursor: last_cursor }
end
- it_behaves_like 'a working graphql query' do
- it 'only returns N branch_rules' do
- expect(branch_rules_data.size).to eq(branch_rule_limit)
- expect(has_next_page).to be_truthy
- expect(has_prev_page).to be_falsey
- post_graphql(query, current_user: current_user, variables: next_variables)
- expect(branch_rules_data.size).to eq(branch_rule_limit)
- expect(has_next_page).to be_falsey
- expect(has_prev_page).to be_truthy
- end
+ it_behaves_like 'a working graphql query'
+
+ it 'returns pagination information' do
+ expect(branch_rules_data.size).to eq(branch_rule_limit)
+ expect(has_next_page).to be_truthy
+ expect(has_prev_page).to be_falsey
+ post_graphql(query, current_user: current_user, variables: next_variables)
+ expect(branch_rules_data.size).to eq(branch_rule_limit)
+ expect(has_next_page).to be_falsey
+ expect(has_prev_page).to be_truthy
end
context 'when no limit is provided' do
diff --git a/spec/requests/api/graphql/project/cluster_agents_spec.rb b/spec/requests/api/graphql/project/cluster_agents_spec.rb
index a34df0ee6f4..bb716cf2849 100644
--- a/spec/requests/api/graphql/project/cluster_agents_spec.rb
+++ b/spec/requests/api/graphql/project/cluster_agents_spec.rb
@@ -61,11 +61,12 @@ RSpec.describe 'Project.cluster_agents' do
tokens = graphql_data_at(:project, :cluster_agents, :nodes, :tokens, :nodes)
- expect(tokens).to match([
- a_graphql_entity_for(token_3),
- a_graphql_entity_for(token_2),
- a_graphql_entity_for(token_1)
- ])
+ expect(tokens).to match(
+ [
+ a_graphql_entity_for(token_3),
+ a_graphql_entity_for(token_2),
+ a_graphql_entity_for(token_1)
+ ])
end
it 'does not suffer from N+1 performance issues' do
diff --git a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
index 02bc9457c07..965534654ea 100644
--- a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb
@@ -245,9 +245,10 @@ RSpec.describe 'Getting designs related to an issue' do
end
it 'only returns one version record for the design (the original version)' do
- expect(version_nodes).to eq([
- [{ 'node' => { 'id' => global_id(version) } }]
- ])
+ expect(version_nodes).to eq(
+ [
+ [{ 'node' => { 'id' => global_id(version) } }]
+ ])
end
end
@@ -289,10 +290,11 @@ RSpec.describe 'Getting designs related to an issue' do
end
it 'returns the correct versions records for both designs' do
- expect(version_nodes).to eq([
- [{ 'node' => { 'id' => global_id(design.versions.first) } }],
- [{ 'node' => { 'id' => global_id(second_design.versions.first) } }]
- ])
+ expect(version_nodes).to eq(
+ [
+ [{ 'node' => { 'id' => global_id(design.versions.first) } }],
+ [{ 'node' => { 'id' => global_id(second_design.versions.first) } }]
+ ])
end
end
@@ -341,15 +343,16 @@ RSpec.describe 'Getting designs related to an issue' do
end
it 'returns all versions records for the designs' do
- expect(version_nodes).to eq([
- [
- { 'node' => { 'id' => global_id(design.versions.first) } }
- ],
+ expect(version_nodes).to eq(
[
- { 'node' => { 'id' => global_id(second_design.versions.second) } },
- { 'node' => { 'id' => global_id(second_design.versions.first) } }
- ]
- ])
+ [
+ { 'node' => { 'id' => global_id(design.versions.first) } }
+ ],
+ [
+ { 'node' => { 'id' => global_id(second_design.versions.second) } },
+ { 'node' => { 'id' => global_id(second_design.versions.first) } }
+ ]
+ ])
end
end
end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 28282860416..3b8beb4f798 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -662,6 +662,7 @@ RSpec.describe 'getting an issue list for a project' do
include_examples 'N+1 query check'
end
+
context 'when requesting `closed_as_duplicate_of`' do
let(:requested_fields) { 'closedAsDuplicateOf { id }' }
let(:issue_a_dup) { create(:issue, project: project) }
@@ -674,6 +675,55 @@ RSpec.describe 'getting an issue list for a project' do
include_examples 'N+1 query check'
end
+
+ context 'when award emoji votes' do
+ let(:requested_fields) { [:upvotes, :downvotes] }
+
+ before do
+ create_list(:award_emoji, 2, name: 'thumbsup', awardable: issue_a)
+ create_list(:award_emoji, 2, name: 'thumbsdown', awardable: issue_b)
+ end
+
+ include_examples 'N+1 query check'
+ end
+
+ context 'when requesting participants' do
+ let_it_be(:issue_c) { create(:issue, project: project) }
+
+ let(:search_params) { { iids: [issue_a.iid.to_s, issue_c.iid.to_s] } }
+ let(:requested_fields) { 'participants { nodes { name } }' }
+
+ before do
+ create(:award_emoji, :upvote, awardable: issue_a)
+ create(:award_emoji, :upvote, awardable: issue_b)
+ create(:award_emoji, :upvote, awardable: issue_c)
+
+ note_with_emoji_a = create(:note_on_issue, noteable: issue_a, project: project)
+ note_with_emoji_b = create(:note_on_issue, noteable: issue_b, project: project)
+ note_with_emoji_c = create(:note_on_issue, noteable: issue_c, project: project)
+
+ create(:award_emoji, :upvote, awardable: note_with_emoji_a)
+ create(:award_emoji, :upvote, awardable: note_with_emoji_b)
+ create(:award_emoji, :upvote, awardable: note_with_emoji_c)
+ end
+
+ # Executes 3 extra queries to fetch participant_attrs
+ include_examples 'N+1 query check', threshold: 3
+ end
+
+ context 'when requesting labels' do
+ let(:requested_fields) { ['labels { nodes { id } }'] }
+
+ before do
+ project_labels = create_list(:label, 2, project: project)
+ group_labels = create_list(:group_label, 2, group: group)
+
+ issue_a.update!(labels: [project_labels.first, group_labels.first].flatten)
+ issue_b.update!(labels: [project_labels, group_labels].flatten)
+ end
+
+ include_examples 'N+1 query check', skip_cached: false
+ end
end
def issues_ids
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index 5daec5543c0..2895737ae6f 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -5,12 +5,14 @@ require 'spec_helper'
RSpec.describe 'getting merge request listings nested in a project' do
include GraphqlHelpers
- let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, :public, group: group) }
let_it_be(:current_user) { create(:user) }
let_it_be(:label) { create(:label, project: project) }
+ let_it_be(:group_label) { create(:group_label, group: group) }
let_it_be_with_reload(:merge_request_a) do
- create(:labeled_merge_request, :unique_branches, source_project: project, labels: [label])
+ create(:labeled_merge_request, :unique_branches, source_project: project, labels: [label, group_label])
end
let_it_be(:merge_request_b) do
@@ -18,7 +20,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
let_it_be(:merge_request_c) do
- create(:labeled_merge_request, :closed, :unique_branches, source_project: project, labels: [label])
+ create(:labeled_merge_request, :closed, :unique_branches, source_project: project, labels: [label, group_label])
end
let_it_be(:merge_request_d) do
@@ -327,6 +329,51 @@ RSpec.describe 'getting merge request listings nested in a project' do
include_examples 'N+1 query check'
end
+
+ context 'when award emoji votes' do
+ let(:requested_fields) { [:upvotes, :downvotes] }
+
+ before do
+ create_list(:award_emoji, 2, name: 'thumbsup', awardable: merge_request_a)
+ create_list(:award_emoji, 2, name: 'thumbsdown', awardable: merge_request_b)
+ end
+
+ include_examples 'N+1 query check'
+ end
+
+ context 'when requesting participants' do
+ let(:requested_fields) { 'participants { nodes { name } }' }
+
+ before do
+ create(:award_emoji, :upvote, awardable: merge_request_a)
+ create(:award_emoji, :upvote, awardable: merge_request_b)
+ create(:award_emoji, :upvote, awardable: merge_request_c)
+
+ note_with_emoji_a = create(:note_on_merge_request, noteable: merge_request_a, project: project)
+ note_with_emoji_b = create(:note_on_merge_request, noteable: merge_request_b, project: project)
+ note_with_emoji_c = create(:note_on_merge_request, noteable: merge_request_c, project: project)
+
+ create(:award_emoji, :upvote, awardable: note_with_emoji_a)
+ create(:award_emoji, :upvote, awardable: note_with_emoji_b)
+ create(:award_emoji, :upvote, awardable: note_with_emoji_c)
+ end
+
+ # Executes 3 extra queries to fetch participant_attrs
+ include_examples 'N+1 query check', threshold: 3
+ end
+
+ context 'when requesting labels' do
+ let(:requested_fields) { ['labels { nodes { id } }'] }
+
+ before do
+ project_labels = create_list(:label, 2, project: project)
+ group_labels = create_list(:group_label, 2, group: group)
+
+ merge_request_c.update!(labels: [project_labels, group_labels].flatten)
+ end
+
+ include_examples 'N+1 query check', skip_cached: false
+ end
end
describe 'performance' do
diff --git a/spec/requests/api/graphql/project/milestones_spec.rb b/spec/requests/api/graphql/project/milestones_spec.rb
index d1ee157fc74..a577c367fe5 100644
--- a/spec/requests/api/graphql/project/milestones_spec.rb
+++ b/spec/requests/api/graphql/project/milestones_spec.rb
@@ -25,9 +25,10 @@ RSpec.describe 'getting milestone listings nested in a project' do
graphql_query_for(
:project,
{ full_path: project.full_path },
- query_graphql_field(:milestones, search_params, [
- query_graphql_field(:nodes, nil, %i[id title])
- ])
+ query_graphql_field(:milestones, search_params,
+ [
+ query_graphql_field(:nodes, nil, %i[id title])
+ ])
)
end
diff --git a/spec/requests/api/graphql/project/work_items_spec.rb b/spec/requests/api/graphql/project/work_items_spec.rb
index 69f8d1cac74..e82f6ad24a2 100644
--- a/spec/requests/api/graphql/project/work_items_spec.rb
+++ b/spec/requests/api/graphql/project/work_items_spec.rb
@@ -2,16 +2,25 @@
require 'spec_helper'
-RSpec.describe 'getting an work item list for a project' do
+RSpec.describe 'getting a work item list for a project' do
include GraphqlHelpers
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :repository, :public, group: group) }
let_it_be(:current_user) { create(:user) }
+ let_it_be(:label1) { create(:label, project: project) }
+ let_it_be(:label2) { create(:label, project: project) }
- let_it_be(:item1) { create(:work_item, project: project, discussion_locked: true, title: 'item1') }
+ let_it_be(:item1) { create(:work_item, project: project, discussion_locked: true, title: 'item1', labels: [label1]) }
let_it_be(:item2) do
- create(:work_item, project: project, title: 'item2', last_edited_by: current_user, last_edited_at: 1.day.ago)
+ create(
+ :work_item,
+ project: project,
+ title: 'item2',
+ last_edited_by: current_user,
+ last_edited_at: 1.day.ago,
+ labels: [label2]
+ )
end
let_it_be(:confidential_item) { create(:work_item, confidential: true, project: project, title: 'item3') }
@@ -30,6 +39,70 @@ RSpec.describe 'getting an work item list for a project' do
QUERY
end
+ shared_examples 'work items resolver without N + 1 queries' do
+ it 'avoids N+1 queries' do
+ post_graphql(query, current_user: current_user) # warm-up
+
+ control = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: current_user)
+ end
+
+ expect_graphql_errors_to_be_empty
+
+ create_list(
+ :work_item, 3,
+ :task,
+ :last_edited_by_user,
+ last_edited_at: 1.week.ago,
+ project: project,
+ labels: [label1, label2]
+ )
+
+ expect_graphql_errors_to_be_empty
+ expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
+ end
+ end
+
+ describe 'N + 1 queries' do
+ context 'when querying root fields' do
+ it_behaves_like 'work items resolver without N + 1 queries'
+ end
+
+ # We need a separate example since all_graphql_fields_for will not fetch fields from types
+ # that implement the widget interface. Only `type` for the widgets field.
+ context 'when querying the widget interface' do
+ let(:fields) do
+ <<~GRAPHQL
+ nodes {
+ widgets {
+ type
+ ... on WorkItemWidgetDescription {
+ edited
+ lastEditedAt
+ lastEditedBy {
+ webPath
+ username
+ }
+ }
+ ... on WorkItemWidgetAssignees {
+ assignees { nodes { id } }
+ }
+ ... on WorkItemWidgetHierarchy {
+ parent { id }
+ }
+ ... on WorkItemWidgetLabels {
+ labels { nodes { id } }
+ allowsScopedLabels
+ }
+ }
+ }
+ GRAPHQL
+ end
+
+ it_behaves_like 'work items resolver without N + 1 queries'
+ end
+ end
+
it_behaves_like 'a working graphql query' do
before do
post_graphql(query, current_user: current_user)
@@ -78,40 +151,6 @@ RSpec.describe 'getting an work item list for a project' do
end
end
- context 'when fetching description edit information' do
- let(:fields) do
- <<~GRAPHQL
- nodes {
- widgets {
- type
- ... on WorkItemWidgetDescription {
- edited
- lastEditedAt
- lastEditedBy {
- webPath
- username
- }
- }
- }
- }
- GRAPHQL
- end
-
- it 'avoids N+1 queries' do
- post_graphql(query, current_user: current_user) # warm-up
-
- control = ActiveRecord::QueryRecorder.new do
- post_graphql(query, current_user: current_user)
- end
- expect_graphql_errors_to_be_empty
-
- create_list(:work_item, 3, :last_edited_by_user, last_edited_at: 1.week.ago, project: project)
-
- expect_graphql_errors_to_be_empty
- expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
- end
- end
-
context 'when filtering by search' do
it_behaves_like 'query with a search term' do
let(:issuable_data) { items_data }
diff --git a/spec/requests/api/graphql/todo_query_spec.rb b/spec/requests/api/graphql/todo_query_spec.rb
index be7242d95bd..7fe19448083 100644
--- a/spec/requests/api/graphql/todo_query_spec.rb
+++ b/spec/requests/api/graphql/todo_query_spec.rb
@@ -14,6 +14,11 @@ RSpec.describe 'Todo Query' do
let_it_be(:todo) { create(:todo, user: todo_owner, target: issue) }
let(:todo_subject) { todo }
+
+ before do
+ project.add_developer(todo_owner)
+ end
+
let(:fields) do
<<~GRAPHQL
id
@@ -31,10 +36,6 @@ RSpec.describe 'Todo Query' do
graphql_query_for(:todo, { id: todo_subject.to_global_id.to_s }, fields)
end
- before do
- project.add_developer(todo_owner)
- end
-
subject(:graphql_response) do
result = GitlabSchema.execute(query, context: { current_user: current_user }).to_h
graphql_dig_at(result, :data, :todo)
diff --git a/spec/requests/api/graphql/usage_trends_measurements_spec.rb b/spec/requests/api/graphql/usage_trends_measurements_spec.rb
index 69a3ed7e09c..78a4321f522 100644
--- a/spec/requests/api/graphql/usage_trends_measurements_spec.rb
+++ b/spec/requests/api/graphql/usage_trends_measurements_spec.rb
@@ -17,19 +17,25 @@ RSpec.describe 'UsageTrendsMeasurements' do
end
it 'returns measurement objects' do
- expect(graphql_data.dig('usageTrendsMeasurements', 'nodes')).to eq([
- { "count" => 10, 'identifier' => 'PROJECTS' },
- { "count" => 5, 'identifier' => 'PROJECTS' }
- ])
+ expect(graphql_data.dig('usageTrendsMeasurements', 'nodes')).to eq(
+ [
+ { "count" => 10, 'identifier' => 'PROJECTS' },
+ { "count" => 5, 'identifier' => 'PROJECTS' }
+ ])
end
context 'with recorded_at filters' do
- let(:arguments) { %(identifier: PROJECTS, recordedAfter: "#{15.days.ago.to_date}", recordedBefore: "#{5.days.ago.to_date}") }
+ let(:arguments) do
+ %(identifier: PROJECTS,
+ recordedAfter: "#{15.days.ago.to_date}",
+ recordedBefore: "#{5.days.ago.to_date}")
+ end
it 'returns filtered measurement objects' do
- expect(graphql_data.dig('usageTrendsMeasurements', 'nodes')).to eq([
- { "count" => 10, 'identifier' => 'PROJECTS' }
- ])
+ expect(graphql_data.dig('usageTrendsMeasurements', 'nodes')).to eq(
+ [
+ { "count" => 10, 'identifier' => 'PROJECTS' }
+ ])
end
end
end
diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb
index e4bb4109c76..2105e479ed2 100644
--- a/spec/requests/api/graphql/work_item_spec.rb
+++ b/spec/requests/api/graphql/work_item_spec.rb
@@ -128,10 +128,11 @@ RSpec.describe 'Query.work_item(id)' do
hash_including(
'type' => 'HIERARCHY',
'parent' => nil,
- 'children' => { 'nodes' => match_array([
- hash_including('id' => child_link1.work_item.to_gid.to_s),
- hash_including('id' => child_link2.work_item.to_gid.to_s)
- ]) }
+ 'children' => { 'nodes' => match_array(
+ [
+ hash_including('id' => child_link1.work_item.to_gid.to_s),
+ hash_including('id' => child_link2.work_item.to_gid.to_s)
+ ]) }
)
)
)
@@ -161,9 +162,10 @@ RSpec.describe 'Query.work_item(id)' do
hash_including(
'type' => 'HIERARCHY',
'parent' => nil,
- 'children' => { 'nodes' => match_array([
- hash_including('id' => child_link1.work_item.to_gid.to_s)
- ]) }
+ 'children' => { 'nodes' => match_array(
+ [
+ hash_including('id' => child_link1.work_item.to_gid.to_s)
+ ]) }
)
)
)
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 6169bc9b2a2..02d29601ceb 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -505,13 +505,35 @@ RSpec.describe API::Groups do
group3.add_maintainer(user2)
end
- it 'returns an array of groups the user has at least master access' do
- get api('/groups', user2), params: { min_access_level: 40 }
+ context 'with min_access_level parameter' do
+ it 'returns an array of groups the user has at least master access' do
+ get api('/groups', user2), params: { min_access_level: 40 }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(response_groups).to contain_exactly(group2.id, group3.id)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(response_groups).to contain_exactly(group2.id, group3.id)
+ end
+
+ context 'distinct count with present_groups_select_all feature flag' do
+ subject { get api('/groups', user2), params: { min_access_level: 40 } }
+
+ it 'counts with *' do
+ count_sql = /#{Regexp.escape('SELECT count(*)')}/i
+ expect { subject }.to make_queries_matching count_sql
+ end
+
+ context 'when present_groups_select_all feature flag is disabled' do
+ before do
+ stub_feature_flags(present_groups_select_all: false)
+ end
+
+ it 'counts with count_column' do
+ count_sql = /#{Regexp.escape('SELECT count(count_column)')}/i
+ expect { subject }.to make_queries_matching count_sql
+ end
+ end
+ end
end
end
diff --git a/spec/requests/api/helm_packages_spec.rb b/spec/requests/api/helm_packages_spec.rb
index 5212e225351..6bd81f64913 100644
--- a/spec/requests/api/helm_packages_spec.rb
+++ b/spec/requests/api/helm_packages_spec.rb
@@ -73,6 +73,17 @@ RSpec.describe API::HelmPackages do
end
end
+ context 'with access to package registry for everyone' do
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
+
+ before do
+ project.update!(visibility: Gitlab::VisibilityLevel::PRIVATE)
+ project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+ end
+
+ it_behaves_like 'process helm download content request', :anonymous, :success
+ end
+
context 'when an invalid token is passed' do
let(:headers) { basic_auth_header(user.username, 'wrong') }
diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb
index d2fa3dabe69..015a09d41ab 100644
--- a/spec/requests/api/import_github_spec.rb
+++ b/spec/requests/api/import_github_spec.rb
@@ -70,7 +70,8 @@ RSpec.describe API::ImportGithub do
target_namespace: user.namespace_path,
personal_access_token: token,
repo_id: non_existing_record_id,
- github_hostname: "https://github.somecompany.com/"
+ github_hostname: "https://github.somecompany.com/",
+ optional_stages: { attachments_import: true }
}
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to be_a Hash
@@ -89,4 +90,42 @@ RSpec.describe API::ImportGithub do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
+
+ describe "POST /import/github/cancel" do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :import_started, import_type: 'github', import_url: 'https://fake.url') }
+
+ context 'when project import was canceled' do
+ before do
+ allow(Import::Github::CancelProjectImportService)
+ .to receive(:new).with(project, user)
+ .and_return(double(execute: { status: :success, project: project }))
+ end
+
+ it 'returns success' do
+ post api("/import/github/cancel", user), params: {
+ project_id: project.id
+ }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when project import was not canceled' do
+ before do
+ allow(Import::Github::CancelProjectImportService)
+ .to receive(:new).with(project, user)
+ .and_return(double(execute: { status: :error, message: 'The import cannot be canceled because it is finished', http_status: :bad_request }))
+ end
+
+ it 'returns error' do
+ post api("/import/github/cancel", user), params: {
+ project_id: project.id
+ }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq('The import cannot be canceled because it is finished')
+ end
+ end
+ end
end
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 1f6c241b3f5..32cacfc713c 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -68,24 +68,6 @@ RSpec.describe API::Internal::Base do
expect(response).to have_gitlab_http_status(:unauthorized)
end
-
- context 'when gitlab_shell_jwt_token is disabled' do
- before do
- stub_feature_flags(gitlab_shell_jwt_token: false)
- end
-
- it 'authenticates using a header' do
- perform_request(headers: { API::Helpers::GITLAB_SHARED_SECRET_HEADER => Base64.encode64(secret_token) })
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns 401 when no credentials provided' do
- get(api("/internal/check"))
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
end
end
@@ -1033,7 +1015,7 @@ RSpec.describe API::Internal::Base do
context 'git push' do
before do
- stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 120)
+ allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(120)
end
subject { push_with_path(key, full_path: path, changes: '_any') }
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index dd7d32f3565..f5c73846173 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -1164,6 +1164,21 @@ RSpec.describe API::Issues do
expect(json_response['title']).to eq('new issue')
expect(json_response['issue_type']).to eq('issue')
end
+
+ context 'when issue create service returns an unrecoverable error' do
+ before do
+ allow_next_instance_of(Issues::CreateService) do |create_service|
+ allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error', http_status: 403))
+ end
+ end
+
+ it 'returns and error message and status code from the service' do
+ post api("/projects/#{project.id}/issues", user), params: { title: 'new issue' }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to eq('some error')
+ end
+ end
end
describe 'PUT /projects/:id/issues/:issue_iid' do
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
index 7c8994ad9ba..3883eb01391 100644
--- a/spec/requests/api/issues/post_projects_issues_spec.rb
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -274,9 +274,7 @@ RSpec.describe API::Issues do
post api("/projects/#{project.id}/issues", user),
params: { title: 'g' * 256 }
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
+ expect(json_response['message']['title']).to eq(['is too long (maximum is 255 characters)'])
end
context 'resolving discussions' do
diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb
index 6ea77cc6578..d6c57b460e0 100644
--- a/spec/requests/api/issues/put_projects_issues_spec.rb
+++ b/spec/requests/api/issues/put_projects_issues_spec.rb
@@ -381,9 +381,7 @@ RSpec.describe API::Issues do
put api_for_user, params: { title: 'g' * 256 }
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
+ expect(json_response['message']['title']).to eq(['is too long (maximum is 255 characters)'])
end
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index d7cc6991ef4..d771c1e2dcc 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -254,7 +254,7 @@ RSpec.describe API::MavenPackages do
let(:package_name) { package_in_project ? package_file.file_name : 'foo' }
before do
- allow_fetch_application_setting(attribute: 'maven_package_requests_forwarding', return_value: forward)
+ allow_fetch_cascade_application_setting(attribute: 'maven_package_requests_forwarding', return_value: forward)
end
it_behaves_like params[:shared_examples_name]
@@ -273,7 +273,7 @@ RSpec.describe API::MavenPackages do
before do
stub_feature_flags(maven_central_request_forwarding: false)
- allow_fetch_application_setting(attribute: 'maven_package_requests_forwarding', return_value: forward)
+ allow_fetch_cascade_application_setting(attribute: 'maven_package_requests_forwarding', return_value: forward)
end
it_behaves_like params[:shared_examples_name]
@@ -438,21 +438,7 @@ RSpec.describe API::MavenPackages do
it_behaves_like 'processing HEAD requests', instance_level: true
end
- context 'with check_maven_path_first enabled' do
- before do
- stub_feature_flags(check_maven_path_first: true)
- end
-
- it_behaves_like 'handling groups, subgroups and user namespaces for', 'heading a file'
- end
-
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
- end
-
- it_behaves_like 'handling groups, subgroups and user namespaces for', 'heading a file'
- end
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'heading a file'
end
describe 'GET /api/v4/groups/:id/-/packages/maven/*path/:file_name' do
@@ -668,21 +654,7 @@ RSpec.describe API::MavenPackages do
let(:path) { package.maven_metadatum.path }
let(:url) { "/groups/#{group.id}/-/packages/maven/#{path}/#{package_file.file_name}" }
- context 'with check_maven_path_first enabled' do
- before do
- stub_feature_flags(check_maven_path_first: true)
- end
-
- it_behaves_like 'handling groups and subgroups for', 'processing HEAD requests'
- end
-
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
- end
-
- it_behaves_like 'handling groups and subgroups for', 'processing HEAD requests'
- end
+ it_behaves_like 'handling groups and subgroups for', 'processing HEAD requests'
end
describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do
@@ -774,21 +746,7 @@ RSpec.describe API::MavenPackages do
let(:path) { package.maven_metadatum.path }
let(:url) { "/projects/#{project.id}/packages/maven/#{path}/#{package_file.file_name}" }
- context 'with check_maven_path_first enabled' do
- before do
- stub_feature_flags(check_maven_path_first: true)
- end
-
- it_behaves_like 'processing HEAD requests'
- end
-
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
- end
-
- it_behaves_like 'processing HEAD requests'
- end
+ it_behaves_like 'processing HEAD requests'
end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name/authorize' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 9d153286d14..d593e369d27 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -119,10 +119,13 @@ RSpec.describe API::MergeRequests do
it 'returns an array of all merge_requests' do
get api(endpoint_path, user)
- expect_paginated_array_response([
- merge_request_merged.id, merge_request_locked.id,
- merge_request_closed.id, merge_request.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request_merged.id,
+ merge_request_locked.id,
+ merge_request_closed.id,
+ merge_request.id
+ ])
expect(json_response.last['title']).to eq(merge_request.title)
expect(json_response.last).to have_key('web_url')
@@ -172,10 +175,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request_merged.id, merge_request_locked.id,
- merge_request_closed.id, merge_request.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request_merged.id,
+ merge_request_locked.id,
+ merge_request_closed.id,
+ merge_request.id
+ ])
expect(json_response.last.keys).to match_array(%w(id iid title web_url created_at description project_id state updated_at))
expect(json_response.last['iid']).to eq(merge_request.iid)
expect(json_response.last['title']).to eq(merge_request.title)
@@ -190,10 +196,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request_merged.id, merge_request_locked.id,
- merge_request_closed.id, merge_request.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request_merged.id,
+ merge_request_locked.id,
+ merge_request_closed.id,
+ merge_request.id
+ ])
expect(json_response.last['title']).to eq(merge_request.title)
end
@@ -354,10 +363,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request.id, merge_request_closed.id,
- merge_request_locked.id, merge_request_merged.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request.id,
+ merge_request_closed.id,
+ merge_request_locked.id,
+ merge_request_merged.id
+ ])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort)
end
@@ -367,10 +379,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request_merged.id, merge_request_locked.id,
- merge_request_closed.id, merge_request.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request_merged.id,
+ merge_request_locked.id,
+ merge_request_closed.id,
+ merge_request.id
+ ])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -398,10 +413,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request.id, merge_request_locked.id,
- merge_request_merged.id, merge_request_closed.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request.id,
+ merge_request_locked.id,
+ merge_request_merged.id,
+ merge_request_closed.id
+ ])
response_dates = json_response.map { |merge_request| merge_request['updated_at'] }
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -411,10 +429,13 @@ RSpec.describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
- merge_request.id, merge_request_closed.id,
- merge_request_locked.id, merge_request_merged.id
- ])
+ expect_paginated_array_response(
+ [
+ merge_request.id,
+ merge_request_closed.id,
+ merge_request_locked.id,
+ merge_request_merged.id
+ ])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort)
end
@@ -1023,6 +1044,14 @@ RSpec.describe API::MergeRequests do
it_behaves_like 'a non-cached MergeRequest api request', 1
end
+ context 'when the label changes' do
+ before do
+ merge_request.labels << create(:label, project: merge_request.project)
+ end
+
+ it_behaves_like 'a non-cached MergeRequest api request', 1
+ end
+
context 'when the assignees change' do
before do
merge_request.assignees << create(:user)
@@ -3315,7 +3344,7 @@ RSpec.describe API::MergeRequests do
end
it 'handles external issues' do
- jira_project = create(:jira_project, :public, :repository, name: 'JIR_EXT1')
+ jira_project = create(:project, :with_jira_integration, :public, :repository, name: 'JIR_EXT1')
ext_issue = ExternalIssue.new("#{jira_project.name}-123", jira_project)
issue = create(:issue, project: jira_project)
description = "Closes #{ext_issue.to_reference(jira_project)}\ncloses #{issue.to_reference}"
diff --git a/spec/requests/api/metadata_spec.rb b/spec/requests/api/metadata_spec.rb
index dbca06b7f3e..5b6407c689b 100644
--- a/spec/requests/api/metadata_spec.rb
+++ b/spec/requests/api/metadata_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe API::Metadata do
shared_examples_for 'GET /metadata' do
context 'when unauthenticated' do
it 'returns authentication error' do
- get api('/metadata')
+ get api(endpoint)
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -16,7 +16,7 @@ RSpec.describe API::Metadata do
let(:user) { create(:user) }
it 'returns the metadata information' do
- get api('/metadata', user)
+ get api(endpoint, user)
expect_metadata
end
@@ -29,13 +29,13 @@ RSpec.describe API::Metadata do
let(:scopes) { %i(api) }
it 'returns the metadata information' do
- get api('/metadata', personal_access_token: personal_access_token)
+ get api(endpoint, personal_access_token: personal_access_token)
expect_metadata
end
it 'returns "200" response on head requests' do
- head api('/metadata', personal_access_token: personal_access_token)
+ head api(endpoint, personal_access_token: personal_access_token)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -45,13 +45,13 @@ RSpec.describe API::Metadata do
let(:scopes) { %i(read_user) }
it 'returns the metadata information' do
- get api('/metadata', personal_access_token: personal_access_token)
+ get api(endpoint, personal_access_token: personal_access_token)
expect_metadata
end
it 'returns "200" response on head requests' do
- head api('/metadata', personal_access_token: personal_access_token)
+ head api(endpoint, personal_access_token: personal_access_token)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -61,7 +61,7 @@ RSpec.describe API::Metadata do
let(:scopes) { %i(read_repository) }
it 'returns authorization error' do
- get api('/metadata', personal_access_token: personal_access_token)
+ get api(endpoint, personal_access_token: personal_access_token)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -76,18 +76,14 @@ RSpec.describe API::Metadata do
end
end
- context 'with graphql enabled' do
- before do
- stub_feature_flags(graphql: true)
- end
+ describe 'GET /metadata' do
+ let(:endpoint) { '/metadata' }
include_examples 'GET /metadata'
end
- context 'with graphql disabled' do
- before do
- stub_feature_flags(graphql: false)
- end
+ describe 'GET /version' do
+ let(:endpoint) { '/version' }
include_examples 'GET /metadata'
end
diff --git a/spec/requests/api/ml/mlflow_spec.rb b/spec/requests/api/ml/mlflow_spec.rb
index 4e7091a5b0f..09e9359c0b3 100644
--- a/spec/requests/api/ml/mlflow_spec.rb
+++ b/spec/requests/api/ml/mlflow_spec.rb
@@ -10,27 +10,35 @@ RSpec.describe API::Ml::Mlflow do
let_it_be(:project) { create(:project, :private) }
let_it_be(:developer) { create(:user).tap { |u| project.add_developer(u) } }
+ let_it_be(:another_project) { build(:project).tap { |p| p.add_developer(developer) } }
let_it_be(:experiment) do
create(:ml_experiments, user: project.creator, project: project)
end
let_it_be(:candidate) do
- create(:ml_candidates, user: experiment.user, start_time: 1234, experiment: experiment)
+ create(:ml_candidates,
+ :with_metrics_and_params, user: experiment.user, start_time: 1234, experiment: experiment)
end
- let_it_be(:another_candidate) do
- create(:ml_candidates,
- experiment: create(:ml_experiments, project: create(:project)))
+ let_it_be(:tokens) do
+ {
+ write: create(:personal_access_token, scopes: %w[read_api api], user: developer),
+ read: create(:personal_access_token, scopes: %w[read_api], user: developer),
+ no_access: create(:personal_access_token, scopes: %w[read_user], user: developer),
+ different_user: create(:personal_access_token, scopes: %w[read_api api], user: build(:user))
+ }
end
let(:current_user) { developer }
let(:ff_value) { true }
- let(:scopes) { %w[read_api api] }
+ let(:access_token) { tokens[:write] }
let(:headers) do
- { 'Authorization' => "Bearer #{create(:personal_access_token, scopes: scopes, user: current_user).token}" }
+ { 'Authorization' => "Bearer #{access_token.token}" }
end
- let(:params) { {} }
+ let(:project_id) { project.id }
+ let(:default_params) { {} }
+ let(:params) { default_params }
let(:request) { get api(route), params: params, headers: headers }
before do
@@ -57,7 +65,7 @@ RSpec.describe API::Ml::Mlflow do
shared_examples 'Requires api scope' do
context 'when user has access but token has wrong scope' do
- let(:scopes) { %w[read_api] }
+ let(:access_token) { tokens[:read] }
it { expect(response).to have_gitlab_http_status(:forbidden) }
end
@@ -65,7 +73,7 @@ RSpec.describe API::Ml::Mlflow do
shared_examples 'Requires read_api scope' do
context 'when user has access but token has wrong scope' do
- let(:scopes) { %w[read_user] }
+ let(:access_token) { tokens[:no_access] }
it { expect(response).to have_gitlab_http_status(:forbidden) }
end
@@ -89,7 +97,7 @@ RSpec.describe API::Ml::Mlflow do
end
context 'when user does not have access' do
- let(:current_user) { create(:user) }
+ let(:access_token) { tokens[:different_user] }
it_behaves_like 'Not Found'
end
@@ -101,11 +109,41 @@ RSpec.describe API::Ml::Mlflow do
end
end
- describe 'GET /projects/:id/ml/mflow/api/2.0/mlflow/get' do
+ shared_examples 'run_id param error cases' do
+ context 'when run id is not passed' do
+ let(:params) { {} }
+
+ it_behaves_like 'Bad Request'
+ end
+
+ context 'when run_id is invalid' do
+ let(:params) { default_params.merge(run_id: non_existing_record_iid.to_s) }
+
+ it_behaves_like 'Not Found - Resource Does Not Exist'
+ end
+
+ context 'when run_id is not in in the project' do
+ let(:project_id) { another_project.id }
+
+ it_behaves_like 'Not Found - Resource Does Not Exist'
+ end
+ end
+
+ shared_examples 'Bad Request on missing required' do |keys|
+ keys.each do |key|
+ context "when \"#{key}\" is missing" do
+ let(:params) { default_params.tap { |p| p.delete(key) } }
+
+ it_behaves_like 'Bad Request'
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/ml/mlflow/api/2.0/mlflow/experiments/get' do
let(:experiment_iid) { experiment.iid.to_s }
- let(:route) { "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/experiments/get?experiment_id=#{experiment_iid}" }
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/get?experiment_id=#{experiment_iid}" }
- it 'returns the experiment' do
+ it 'returns the experiment', :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/get_experiment')
expect(json_response).to include({
@@ -127,7 +165,7 @@ RSpec.describe API::Ml::Mlflow do
end
context 'and experiment_id is not passed' do
- let(:route) { "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/experiments/get" }
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/get" }
it_behaves_like 'Not Found - Resource Does Not Exist'
end
@@ -138,13 +176,43 @@ RSpec.describe API::Ml::Mlflow do
end
end
- describe 'GET /projects/:id/ml/mflow/api/2.0/mlflow/experiments/get-by-name' do
+ describe 'GET /projects/:id/ml/mlflow/api/2.0/mlflow/experiments/list' do
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/list" }
+
+ it 'returns the experiments' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('ml/list_experiments')
+ expect(json_response).to include({
+ 'experiments' => [
+ 'experiment_id' => experiment.iid.to_s,
+ 'name' => experiment.name,
+ 'lifecycle_stage' => 'active',
+ 'artifact_location' => 'not_implemented'
+ ]
+ })
+ end
+
+ context 'when there are no experiments' do
+ let(:project_id) { another_project.id }
+
+ it 'returns an empty list' do
+ expect(json_response).to include({ 'experiments' => [] })
+ end
+ end
+
+ describe 'Error States' do
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires read_api scope'
+ end
+ end
+
+ describe 'GET /projects/:id/ml/mlflow/api/2.0/mlflow/experiments/get-by-name' do
let(:experiment_name) { experiment.name }
let(:route) do
- "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/experiments/get-by-name?experiment_name=#{experiment_name}"
+ "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/get-by-name?experiment_name=#{experiment_name}"
end
- it 'returns the experiment' do
+ it 'returns the experiment', :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/get_experiment')
expect(json_response).to include({
@@ -165,7 +233,7 @@ RSpec.describe API::Ml::Mlflow do
end
context 'when has access but experiment_name is not passed' do
- let(:route) { "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/experiments/get-by-name" }
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/get-by-name" }
it_behaves_like 'Not Found - Resource Does Not Exist'
end
@@ -175,16 +243,16 @@ RSpec.describe API::Ml::Mlflow do
end
end
- describe 'POST /projects/:id/ml/mflow/api/2.0/mlflow/experiments/create' do
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/experiments/create' do
let(:route) do
- "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/experiments/create"
+ "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/experiments/create"
end
let(:params) { { name: 'new_experiment' } }
let(:request) { post api(route), params: params, headers: headers }
- it 'creates the experiment' do
- expect(response).to have_gitlab_http_status(:created)
+ it 'creates the experiment', :aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include('experiment_id' )
end
@@ -206,7 +274,7 @@ RSpec.describe API::Ml::Mlflow do
end
context 'when project does not exist' do
- let(:route) { "/projects/#{non_existing_record_id}/ml/mflow/api/2.0/mlflow/experiments/create" }
+ let(:route) { "/projects/#{non_existing_record_id}/ml/mlflow/api/2.0/mlflow/experiments/create" }
it_behaves_like 'Not Found', '404 Project Not Found'
end
@@ -217,15 +285,12 @@ RSpec.describe API::Ml::Mlflow do
end
describe 'Runs' do
- describe 'POST /projects/:id/ml/mflow/api/2.0/mlflow/runs/create' do
- let(:route) do
- "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/runs/create"
- end
-
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/runs/create' do
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/create" }
let(:params) { { experiment_id: experiment.iid.to_s, start_time: Time.now.to_i } }
let(:request) { post api(route), params: params, headers: headers }
- it 'creates the run' do
+ it 'creates the run', :aggregate_failures do
expected_properties = {
'experiment_id' => params[:experiment_id],
'user_id' => current_user.id.to_s,
@@ -235,9 +300,10 @@ RSpec.describe API::Ml::Mlflow do
'lifecycle_stage' => "active"
}
- expect(response).to have_gitlab_http_status(:created)
+ expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/run')
- expect(json_response['run']).to include('info' => hash_including(**expected_properties), 'data' => {})
+ expect(json_response['run']).to include('info' => hash_including(**expected_properties),
+ 'data' => { 'metrics' => [], 'params' => [] })
end
describe 'Error States' do
@@ -253,21 +319,22 @@ RSpec.describe API::Ml::Mlflow do
it_behaves_like 'Not Found - Resource Does Not Exist'
end
+ context 'when experiment exists but is not part of the project' do
+ let(:project_id) { another_project.id }
+
+ it_behaves_like 'Not Found - Resource Does Not Exist'
+ end
+
it_behaves_like 'shared error cases'
it_behaves_like 'Requires api scope'
end
end
- describe 'GET /projects/:id/ml/mflow/api/2.0/mlflow/runs/get' do
- let_it_be(:route) do
- "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/runs/get"
- end
-
- let_it_be(:candidate) { create(:ml_candidates, user: experiment.user, start_time: 1234, experiment: experiment) }
-
- let(:params) { { 'run_id' => candidate.iid } }
+ describe 'GET /projects/:id/ml/mlflow/api/2.0/mlflow/runs/get' do
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/get" }
+ let(:default_params) { { 'run_id' => candidate.iid } }
- it 'gets the run' do
+ it 'gets the run', :aggregate_failures do
expected_properties = {
'experiment_id' => candidate.experiment.iid.to_s,
'user_id' => candidate.user.id.to_s,
@@ -277,90 +344,173 @@ RSpec.describe API::Ml::Mlflow do
'lifecycle_stage' => "active"
}
- expect(response).to have_gitlab_http_status(:success)
+ expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/run')
- expect(json_response['run']).to include('info' => hash_including(**expected_properties), 'data' => {})
+ expect(json_response['run']).to include(
+ 'info' => hash_including(**expected_properties),
+ 'data' => {
+ 'metrics' => [
+ hash_including('key' => candidate.metrics[0].name),
+ hash_including('key' => candidate.metrics[1].name)
+ ],
+ 'params' => [
+ { 'key' => candidate.params[0].name, 'value' => candidate.params[0].value },
+ { 'key' => candidate.params[1].name, 'value' => candidate.params[1].value }
+ ]
+ })
end
describe 'Error States' do
- context 'when run id is not passed' do
- let(:params) { {} }
+ it_behaves_like 'run_id param error cases'
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires read_api scope'
+ end
+ end
- it_behaves_like 'Not Found - Resource Does Not Exist'
- end
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/runs/update' do
+ let(:default_params) { { run_id: candidate.iid.to_s, status: 'FAILED', end_time: Time.now.to_i } }
+ let(:request) { post api(route), params: params, headers: headers }
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/update" }
- context 'when run id does not exist' do
- let(:params) { { run_id: non_existing_record_iid.to_s } }
+ it 'updates the run', :aggregate_failures do
+ expected_properties = {
+ 'experiment_id' => candidate.experiment.iid.to_s,
+ 'user_id' => candidate.user.id.to_s,
+ 'start_time' => candidate.start_time,
+ 'end_time' => params[:end_time],
+ 'artifact_uri' => 'not_implemented',
+ 'status' => 'FAILED',
+ 'lifecycle_stage' => 'active'
+ }
- it_behaves_like 'Not Found - Resource Does Not Exist'
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('ml/update_run')
+ expect(json_response).to include('run_info' => hash_including(**expected_properties))
+ end
+
+ describe 'Error States' do
+ context 'when status in invalid' do
+ let(:params) { default_params.merge(status: 'YOLO') }
+
+ it_behaves_like 'Bad Request'
end
- context 'when run id exists but does not belong to project' do
- let(:params) { { run_id: another_candidate.iid.to_s } }
+ context 'when end_time is invalid' do
+ let(:params) { default_params.merge(end_time: 's') }
- it_behaves_like 'Not Found - Resource Does Not Exist'
+ it_behaves_like 'Bad Request'
end
it_behaves_like 'shared error cases'
- it_behaves_like 'Requires read_api scope'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
end
end
- end
- describe 'POST /projects/:id/ml/mflow/api/2.0/mlflow/runs/update' do
- let(:route) { "/projects/#{project.id}/ml/mflow/api/2.0/mlflow/runs/update" }
- let(:params) { { run_id: candidate.iid.to_s, status: 'FAILED', end_time: Time.now.to_i } }
- let(:request) { post api(route), params: params, headers: headers }
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/runs/log-metric' do
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/log-metric" }
+ let(:default_params) { { run_id: candidate.iid.to_s, key: 'some_key', value: 10.0, timestamp: Time.now.to_i } }
+ let(:request) { post api(route), params: params, headers: headers }
- it 'updates the run' do
- expected_properties = {
- 'experiment_id' => candidate.experiment.iid.to_s,
- 'user_id' => candidate.user.id.to_s,
- 'start_time' => candidate.start_time,
- 'end_time' => params[:end_time],
- 'artifact_uri' => 'not_implemented',
- 'status' => 'FAILED',
- 'lifecycle_stage' => 'active'
- }
-
- expect(response).to have_gitlab_http_status(:success)
- expect(response).to match_response_schema('ml/update_run')
- expect(json_response).to include('run_info' => hash_including(**expected_properties))
+ it 'logs the metric', :aggregate_failures do
+ candidate.metrics.reload
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ expect(candidate.metrics.length).to eq(3)
+ end
+
+ describe 'Error Cases' do
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
+ it_behaves_like 'Bad Request on missing required', [:key, :value, :timestamp]
+ end
end
- describe 'Error States' do
- context 'when run id is not passed' do
- let(:params) { {} }
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/runs/log-parameter' do
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/log-parameter" }
+ let(:default_params) { { run_id: candidate.iid.to_s, key: 'some_key', value: 'value' } }
+ let(:request) { post api(route), params: params, headers: headers }
- it_behaves_like 'Not Found - Resource Does Not Exist'
+ it 'logs the parameter', :aggregate_failures do
+ candidate.params.reload
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ expect(candidate.params.length).to eq(3)
end
- context 'when run id does not exist' do
- let(:params) { { run_id: non_existing_record_iid.to_s } }
+ describe 'Error Cases' do
+ context 'when parameter was already logged' do
+ let(:params) { default_params.tap { |p| p[:key] = candidate.params[0].name } }
- it_behaves_like 'Not Found - Resource Does Not Exist'
+ it_behaves_like 'Bad Request'
+ end
+
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
+ it_behaves_like 'Bad Request on missing required', [:key, :value]
end
+ end
- context 'when run id exists but does not belong to project' do
- let(:params) { { run_id: another_candidate.iid.to_s } }
+ describe 'POST /projects/:id/ml/mlflow/api/2.0/mlflow/runs/log-batch' do
+ let(:candidate2) do
+ create(:ml_candidates, user: experiment.user, start_time: 1234, experiment: experiment)
+ end
- it_behaves_like 'Not Found - Resource Does Not Exist'
+ let(:route) { "/projects/#{project_id}/ml/mlflow/api/2.0/mlflow/runs/log-batch" }
+ let(:default_params) do
+ {
+ run_id: candidate2.iid.to_s,
+ metrics: [
+ { key: 'mae', value: 2.5, timestamp: 1552550804 },
+ { key: 'rmse', value: 2.7, timestamp: 1552550804 }
+ ],
+ params: [{ key: 'model_class', value: 'LogisticRegression' }]
+ }
end
- context 'when run id exists but status in invalid' do
- let(:params) { { run_id: candidate.iid.to_s, status: 'YOLO', end_time: Time.now.to_i } }
+ let(:request) { post api(route), params: params, headers: headers }
- it_behaves_like 'Bad Request'
+ it 'logs parameters and metrics', :aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ expect(candidate2.params.size).to eq(1)
+ expect(candidate2.metrics.size).to eq(2)
end
- context 'when run id exists but end_time is invalid' do
- let(:params) { { run_id: candidate.iid.to_s, status: 'FAILED', end_time: 's' } }
+ context 'when parameter was already logged' do
+ let(:params) do
+ default_params.tap { |p| p[:params] = [{ key: 'hello', value: 'a' }, { key: 'hello', value: 'b' }] }
+ end
- it_behaves_like 'Bad Request'
+ it 'does not log', :aggregate_failures do
+ candidate.params.reload
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(candidate2.params.size).to eq(1)
+ end
end
- it_behaves_like 'shared error cases'
- it_behaves_like 'Requires api scope'
+ describe 'Error Cases' do
+ context 'when required metric key is missing' do
+ let(:params) { default_params.tap { |p| p[:metrics] = [p[:metrics][0].delete(:key)] } }
+
+ it_behaves_like 'Bad Request'
+ end
+
+ context 'when required param key is missing' do
+ let(:params) { default_params.tap { |p| p[:params] = [p[:params][0].delete(:key)] } }
+
+ it_behaves_like 'Bad Request'
+ end
+
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
+ end
end
end
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index cd4e8b30d8f..8ef4e899193 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -259,7 +259,15 @@ RSpec.describe API::PagesDomains do
shared_examples_for 'post pages domains' do
it 'creates a new pages domain' do
- post api(route, user), params: params
+ expect { post api(route, user), params: params }
+ .to publish_event(PagesDomains::PagesDomainCreatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: params[:domain]
+ )
+
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
expect(response).to have_gitlab_http_status(:created)
@@ -378,6 +386,17 @@ RSpec.describe API::PagesDomains do
expect(pages_domain_secure.auto_ssl_enabled).to be false
end
+ it 'publishes PagesDomainUpdatedEvent event' do
+ expect { put api(route_secure_domain, user), params: { certificate: nil, key: nil } }
+ .to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain_secure.domain
+ )
+ end
+
it 'updates pages domain adding certificate' do
put api(route_domain, user), params: params_secure
pages_domain.reload
@@ -446,22 +465,29 @@ RSpec.describe API::PagesDomains do
end.to change { pages_domain.reload.certificate_source }.from('gitlab_provided').to('user_provided')
end
- it 'fails to update pages domain adding certificate without key' do
- put api(route_domain, user), params: params_secure_nokey
+ context 'with invalid params' do
+ it 'fails to update pages domain adding certificate without key' do
+ put api(route_domain, user), params: params_secure_nokey
- expect(response).to have_gitlab_http_status(:bad_request)
- end
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
- it 'fails to update pages domain adding certificate with missing chain' do
- put api(route_domain, user), params: pages_domain_secure_missing_chain_params.slice(:certificate)
+ it 'does not publish PagesDomainUpdatedEvent event' do
+ expect { put api(route_domain, user), params: params_secure_nokey }
+ .not_to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ end
- expect(response).to have_gitlab_http_status(:bad_request)
- end
+ it 'fails to update pages domain adding certificate with missing chain' do
+ put api(route_domain, user), params: pages_domain_secure_missing_chain_params.slice(:certificate)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
- it 'fails to update pages domain with key missmatch' do
- put api(route_secure_domain, user), params: pages_domain_secure_key_missmatch_params.slice(:certificate, :key)
+ it 'fails to update pages domain with key missmatch' do
+ put api(route_secure_domain, user), params: pages_domain_secure_key_missmatch_params.slice(:certificate, :key)
- expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
end
end
@@ -523,7 +549,15 @@ RSpec.describe API::PagesDomains do
describe 'DELETE /projects/:project_id/pages/domains/:domain' do
shared_examples_for 'delete pages domain' do
it 'deletes a pages domain' do
- delete api(route_domain, user)
+ expect { delete api(route_domain, user) }
+ .to change(PagesDomain, :count).by(-1)
+ .and publish_event(PagesDomains::PagesDomainDeletedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: pages_domain.domain
+ )
expect(response).to have_gitlab_http_status(:no_content)
end
diff --git a/spec/requests/api/personal_access_tokens/self_information_spec.rb b/spec/requests/api/personal_access_tokens/self_information_spec.rb
new file mode 100644
index 00000000000..bdfac3ed14f
--- /dev/null
+++ b/spec/requests/api/personal_access_tokens/self_information_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::PersonalAccessTokens::SelfInformation do
+ let(:path) { '/personal_access_tokens/self' }
+ let(:token) { create(:personal_access_token, user: current_user) }
+
+ let_it_be(:current_user) { create(:user) }
+
+ describe 'DELETE /personal_access_tokens/self' do
+ subject(:delete_token) { delete api(path, personal_access_token: token) }
+
+ shared_examples 'revoking token succeeds' do
+ it 'revokes token' do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(token.reload).to be_revoked
+ end
+ end
+
+ shared_examples 'revoking token denied' do |status|
+ it 'cannot revoke token' do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ context 'when current_user is an administrator', :enable_admin_mode do
+ let(:current_user) { create(:admin) }
+
+ it_behaves_like 'revoking token succeeds'
+
+ context 'with impersonated token' do
+ let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
+
+ it_behaves_like 'revoking token succeeds'
+ end
+ end
+
+ context 'when current_user is not an administrator' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'revoking token succeeds'
+
+ context 'with impersonated token' do
+ let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
+
+ it_behaves_like 'revoking token denied', :bad_request
+ end
+
+ context 'with already revoked token' do
+ let(:token) { create(:personal_access_token, :revoked, user: current_user) }
+
+ it_behaves_like 'revoking token denied', :unauthorized
+ end
+ end
+
+ Gitlab::Auth.all_available_scopes.each do |scope|
+ context "with a '#{scope}' scoped token" do
+ let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
+
+ it_behaves_like 'revoking token succeeds'
+ end
+ end
+ end
+
+ describe 'GET /personal_access_tokens/self' do
+ Gitlab::Auth.all_available_scopes.each do |scope|
+ context "with a '#{scope}' scoped token" do
+ let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
+
+ it 'shows token info' do
+ get api(path, personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['scopes']).to match_array([scope.to_s])
+ end
+ end
+ end
+
+ context 'when token is invalid' do
+ it 'returns 401' do
+ get api(path, personal_access_token: instance_double(PersonalAccessToken, token: 'invalidtoken'))
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when token is expired' do
+ it 'returns 401' do
+ token = create(:personal_access_token, expires_at: 1.day.ago, user: current_user)
+
+ get api(path, personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/personal_access_tokens/self_revocation_spec.rb b/spec/requests/api/personal_access_tokens/self_revocation_spec.rb
deleted file mode 100644
index f829b39cc1e..00000000000
--- a/spec/requests/api/personal_access_tokens/self_revocation_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe API::PersonalAccessTokens::SelfRevocation do
- let_it_be(:current_user) { create(:user) }
-
- describe 'DELETE /personal_access_tokens/self' do
- let(:path) { '/personal_access_tokens/self' }
- let(:token) { create(:personal_access_token, user: current_user) }
-
- subject(:delete_token) { delete api(path, personal_access_token: token) }
-
- shared_examples 'revoking token succeeds' do
- it 'revokes token' do
- delete_token
-
- expect(response).to have_gitlab_http_status(:no_content)
- expect(token.reload).to be_revoked
- end
- end
-
- shared_examples 'revoking token denied' do |status|
- it 'cannot revoke token' do
- delete_token
-
- expect(response).to have_gitlab_http_status(status)
- end
- end
-
- context 'when current_user is an administrator', :enable_admin_mode do
- let(:current_user) { create(:admin) }
-
- it_behaves_like 'revoking token succeeds'
-
- context 'with impersonated token' do
- let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
-
- it_behaves_like 'revoking token succeeds'
- end
- end
-
- context 'when current_user is not an administrator' do
- let(:current_user) { create(:user) }
-
- it_behaves_like 'revoking token succeeds'
-
- context 'with impersonated token' do
- let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
-
- it_behaves_like 'revoking token denied', :bad_request
- end
-
- context 'with already revoked token' do
- let(:token) { create(:personal_access_token, :revoked, user: current_user) }
-
- it_behaves_like 'revoking token denied', :unauthorized
- end
- end
-
- Gitlab::Auth.all_available_scopes.each do |scope|
- context "with a '#{scope}' scoped token" do
- let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
-
- it_behaves_like 'revoking token succeeds'
- end
- end
- end
-end
diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb
index 37b5a594f2a..31c4e8803e3 100644
--- a/spec/requests/api/personal_access_tokens_spec.rb
+++ b/spec/requests/api/personal_access_tokens_spec.rb
@@ -4,14 +4,34 @@ require 'spec_helper'
RSpec.describe API::PersonalAccessTokens do
let_it_be(:path) { '/personal_access_tokens' }
- let_it_be(:token1) { create(:personal_access_token) }
- let_it_be(:token2) { create(:personal_access_token) }
- let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: token1.user) }
- let_it_be(:current_user) { create(:user) }
describe 'GET /personal_access_tokens' do
+ using RSpec::Parameterized::TableSyntax
+
+ def map_id(json_resonse)
+ json_response.map { |pat| pat['id'] }
+ end
+
+ shared_examples 'response as expected' do |params|
+ subject { get api(path, personal_access_token: current_users_token), params: params }
+
+ it "status, count and result as expected" do
+ subject
+
+ if status == :bad_request
+ expect(json_response).to eq(result)
+ elsif status == :ok
+ expect(map_id(json_response)).to a_collection_containing_exactly(*result)
+ end
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(json_response.count).to eq(result_count)
+ end
+ end
+
context 'logged in as an Administrator' do
let_it_be(:current_user) { create(:admin) }
+ let_it_be(:current_users_token) { create(:personal_access_token, user: current_user) }
it 'returns all PATs by default' do
get api(path, current_user)
@@ -21,60 +41,348 @@ RSpec.describe API::PersonalAccessTokens do
end
context 'filtered with user_id parameter' do
+ let_it_be(:token) { create(:personal_access_token) }
+ let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: token.user) }
+
it 'returns only PATs belonging to that user' do
- get api(path, current_user), params: { user_id: token1.user.id }
+ get api(path, current_user), params: { user_id: token.user.id }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(2)
- expect(json_response.first['user_id']).to eq(token1.user.id)
+ expect(json_response.first['user_id']).to eq(token.user.id)
expect(json_response.last['id']).to eq(token_impersonated.id)
end
end
- context 'logged in as a non-Administrator' do
- let_it_be(:current_user) { create(:user) }
+ context 'filter with revoked parameter' do
+ let_it_be(:revoked_token) { create(:personal_access_token, revoked: true) }
+ let_it_be(:not_revoked_token1) { create(:personal_access_token, revoked: false) }
+ let_it_be(:not_revoked_token2) { create(:personal_access_token, revoked: false) }
+
+ where(:revoked, :status, :result_count, :result) do
+ true | :ok | 1 | lazy { [revoked_token.id] }
+ false | :ok | 3 | lazy { [not_revoked_token1.id, not_revoked_token2.id, current_users_token.id] }
+ 'asdf' | :bad_request | 1 | { "error" => "revoked is invalid" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', revoked: params[:revoked]
+ end
+ end
+
+ context 'filter with active parameter' do
+ let_it_be(:inactive_token1) { create(:personal_access_token, revoked: true) }
+ let_it_be(:inactive_token2) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
+ let_it_be(:active_token) { create(:personal_access_token) }
+
+ where(:state, :status, :result_count, :result) do
+ 'inactive' | :ok | 2 | lazy { [inactive_token1.id, inactive_token2.id] }
+ 'active' | :ok | 2 | lazy { [active_token.id, current_users_token.id] }
+ 'asdf' | :bad_request | 1 | { "error" => "state does not have a valid value" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', state: params[:state]
+ end
+ end
+
+ context 'filter with created parameter' do
+ let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
+
+ context 'test created_before' do
+ where(:created_at, :status, :result_count, :result) do
+ '2022-01-02' | :ok | 1 | lazy { [token1.id] }
+ '2022-01-01' | :ok | 0 | lazy { [] }
+ '2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
+ '2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
+ '2022-01-01T:12:30:26' | :ok | 1 | lazy { [token1.id] }
+ 'asdf' | :bad_request | 1 | { "error" => "created_before is invalid" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', created_before: params[:created_at]
+ end
+ end
+
+ context 'test created_after' do
+ where(:created_at, :status, :result_count, :result) do
+ '2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
+ '2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ '2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ '2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
+ (DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
+ 'asdf' | :bad_request | 1 | { "error" => "created_after is invalid" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', created_after: params[:created_at]
+ end
+ end
+ end
+
+ context 'filter with last_used parameter' do
+ let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
+ let_it_be(:never_used_token) { create(:personal_access_token) }
+
+ context 'test last_used_before' do
+ where(:last_used_at, :status, :result_count, :result) do
+ '2022-01-02' | :ok | 1 | lazy { [token1.id] }
+ '2022-01-01' | :ok | 0 | lazy { [] }
+ '2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
+ '2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
+ '2022-01-01T12:30:26' | :ok | 1 | lazy { [token1.id] }
+ 'asdf' | :bad_request | 1 | { "error" => "last_used_before is invalid" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', last_used_before: params[:last_used_at]
+ end
+ end
+
+ context 'test last_used_after' do
+ where(:last_used_at, :status, :result_count, :result) do
+ '2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
+ '2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ '2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
+ '2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ (DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
+ 'asdf' | :bad_request | 1 | { "error" => "last_used_after is invalid" }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', last_used_after: params[:last_used_at]
+ end
+ end
+ end
+
+ context 'filter with search parameter' do
+ let_it_be(:token1) { create(:personal_access_token, name: 'test_1') }
+ let_it_be(:token2) { create(:personal_access_token, name: 'test_2') }
+ let_it_be(:token3) { create(:personal_access_token, name: '') }
+
+ where(:pattern, :status, :result_count, :result) do
+ 'test' | :ok | 2 | lazy { [token1.id, token2.id] }
+ '' | :ok | 4 | lazy { [token1.id, token2.id, token3.id, current_users_token.id] }
+ 'test_1' | :ok | 1 | lazy { [token1.id] }
+ 'asdf' | :ok | 0 | lazy { [] }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', search: params[:pattern]
+ end
+ end
+
+ context 'filter created_before/created_after combined with last_used_before/last_used_after' do
+ let_it_be(:date) { DateTime.new(2022, 01, 02) }
+ let_it_be(:token1) { create(:personal_access_token, created_at: date, last_used_at: date) }
+
+ where(:date_before, :date_after, :status, :result_count, :result) do
+ '2022-01-03' | '2022-01-01' | :ok | 1 | lazy { [token1.id] }
+ '2022-01-01' | '2022-01-03' | :ok | 0 | lazy { [] }
+ '2022-01-03' | nil | :ok | 1 | lazy { [token1.id] }
+ nil | '2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', { created_before: params[:date_before],
+ created_after: params[:date_after] }
+ it_behaves_like 'response as expected', { last_used_before: params[:date_before],
+ last_used_after: params[:date_after] }
+ end
+ end
+
+ context 'filter created_before and created_after combined is valid' do
+ let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02)) }
+
+ where(:created_before, :created_after, :status, :result) do
+ '2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
+ '2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
+ '2022-01-01' | '2022-01-03' | :ok | lazy { [] }
+ '2022-01-03' | nil | :ok | lazy { [token1.id] }
+ nil | '2022-01-01' | :ok | lazy { [token1.id] }
+ end
+
+ with_them do
+ it "returns all valid tokens" do
+ get api(path, personal_access_token: current_users_token),
+ params: { created_before: created_before, created_after: created_after }
+
+ expect(response).to have_gitlab_http_status(status)
+
+ expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok
+ end
+ end
+ end
+
+ context 'filter last_used_before and last_used_after combined is valid' do
+ let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 02) ) }
+
+ where(:last_used_before, :last_used_after, :status, :result) do
+ '2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
+ '2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
+ '2022-01-01' | '2022-01-03' | :ok | lazy { [] }
+ '2022-01-03' | nil | :ok | lazy { [token1.id] }
+ nil | '2022-01-01' | :ok | lazy { [token1.id] }
+ end
+
+ with_them do
+ it "returns all valid tokens" do
+ get api(path, personal_access_token: current_users_token),
+ params: { last_used_before: last_used_before, last_used_after: last_used_after }
+
+ expect(response).to have_gitlab_http_status(status)
+
+ expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok
+ end
+ end
+ end
+ end
+
+ context 'logged in as a non-Administrator' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:current_users_token) { create(:personal_access_token, user: current_user) }
+
+ it 'returns all PATs belonging to the signed-in user' do
+ get api(path, personal_access_token: current_users_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
+ expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
+ end
+
+ context 'filtered with user_id parameter' do
let_it_be(:user) { create(:user) }
- let_it_be(:token) { create(:personal_access_token, user: current_user) }
- let_it_be(:other_token) { create(:personal_access_token, user: user) }
- let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: current_user) }
- it 'returns all PATs belonging to the signed-in user' do
- get api(path, current_user, personal_access_token: token)
+ it 'returns PATs belonging to the specific user' do
+ get api(path, current_user, personal_access_token: current_users_token), params: { user_id: current_user.id }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
+ expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
end
- context 'filtered with user_id parameter' do
- it 'returns PATs belonging to the specific user' do
- get api(path, current_user, personal_access_token: token), params: { user_id: current_user.id }
+ it 'is unauthorized if filtered by a user other than current_user' do
+ get api(path, current_user, personal_access_token: current_users_token), params: { user_id: user.id }
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.count).to eq(1)
- expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
- end
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
- it 'is unauthorized if filtered by a user other than current_user' do
- get api(path, current_user, personal_access_token: token), params: { user_id: user.id }
+ context 'filter with revoked parameter' do
+ let_it_be(:users_revoked_token) { create(:personal_access_token, revoked: true, user: current_user) }
+ let_it_be(:not_revoked_token) { create(:personal_access_token, revoked: false) }
+ let_it_be(:oter_revoked_token) { create(:personal_access_token, revoked: true) }
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
+ where(:revoked, :status, :result_count, :result) do
+ true | :ok | 1 | lazy { [users_revoked_token.id] }
+ false | :ok | 1 | lazy { [current_users_token.id] }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', revoked: params[:revoked]
end
end
- context 'not authenticated' do
- it 'is forbidden' do
- get api(path)
+ context 'filter with active parameter' do
+ let_it_be(:users_inactive_token) { create(:personal_access_token, revoked: true, user: current_user) }
+ let_it_be(:inactive_token) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
+ let_it_be(:other_active_token) { create(:personal_access_token) }
- expect(response).to have_gitlab_http_status(:unauthorized)
+ where(:state, :status, :result_count, :result) do
+ 'inactive' | :ok | 1 | lazy { [users_inactive_token.id] }
+ 'active' | :ok | 1 | lazy { [current_users_token.id] }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', state: params[:state]
+ end
+ end
+
+ # The created_before filter has been extensively tested in the 'logged in as administrator' section.
+ # Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
+ context 'filter with created parameter' do
+ let_it_be(:token1) do
+ create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25), user: current_user )
+ end
+
+ let_it_be(:token2) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25)) }
+ let_it_be(:status) { :ok }
+
+ context 'created_before' do
+ let_it_be(:result_count) { 1 }
+ let_it_be(:result) { [token1.id] }
+
+ it_behaves_like 'response as expected', created_before: '2022-01-03'
+ end
+
+ context 'created_after' do
+ let_it_be(:result_count) { 2 }
+ let_it_be(:result) { [token1.id, current_users_token.id] }
+
+ it_behaves_like 'response as expected', created_after: '2022-01-01'
+ end
+ end
+
+ # The last_used_before filter has been extensively tested in the 'logged in as administrator' section.
+ # Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
+ context 'filter with last_used' do
+ let_it_be(:token1) do
+ create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25), user: current_user)
+ end
+
+ let_it_be(:token2) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
+ let_it_be(:never_used_token) { create(:personal_access_token) }
+ let_it_be(:status) { :ok }
+
+ context 'last_used_before' do
+ let_it_be(:result_count) { 1 }
+ let_it_be(:result) { [token1.id] }
+
+ it_behaves_like 'response as expected', last_used_before: '2022-01-02'
+ end
+
+ context 'last_used_after' do
+ let_it_be(:result_count) { 2 }
+ let_it_be(:result) { [token1.id, current_users_token.id] }
+
+ it_behaves_like 'response as expected', last_used_after: '2022-01-01'
+ end
+ end
+
+ # The search filter has been extensively tested in the 'logged in as administrator' section.
+ # Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
+ context 'filter with search parameter' do
+ let_it_be(:token1) { create(:personal_access_token, name: 'test_1', user: current_user) }
+ let_it_be(:token2) { create(:personal_access_token, name: 'test_1') }
+ let_it_be(:token3) { create(:personal_access_token, name: '') }
+
+ where(:pattern, :status, :result_count, :result) do
+ 'test' | :ok | 1 | lazy { [token1.id] }
+ '' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
+ 'test_1' | :ok | 1 | lazy { [token1.id] }
+ end
+
+ with_them do
+ it_behaves_like 'response as expected', search: params[:pattern]
end
end
end
+
+ context 'not authenticated' do
+ it 'is forbidden' do
+ get api(path)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
end
describe 'GET /personal_access_tokens/:id' do
+ let_it_be(:current_user) { create(:user) }
let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
+ let_it_be(:token1) { create(:personal_access_token) }
let_it_be(:user_read_only_token) { create(:personal_access_token, scopes: ['read_repository'], user: current_user) }
let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
let_it_be(:invalid_path) { "/personal_access_tokens/#{non_existing_record_id}" }
@@ -136,6 +444,9 @@ RSpec.describe API::PersonalAccessTokens do
end
describe 'DELETE /personal_access_tokens/:id' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:token1) { create(:personal_access_token) }
+
let(:path) { "/personal_access_tokens/#{token1.id}" }
context 'when current_user is an administrator', :enable_admin_mode do
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index 1335fa02aaf..0b4a96896d6 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -90,11 +90,10 @@ ci_cd_settings:
- id
- project_id
- group_runners_enabled
- - merge_pipelines_enabled
- merge_trains_enabled
- merge_pipelines_enabled
- - merge_trains_enabled
- auto_rollback_enabled
+ - inbound_job_token_scope_enabled
remapped_attributes:
default_git_depth: ci_default_git_depth
forward_deployment_enabled: ci_forward_deployment_enabled
@@ -129,7 +128,6 @@ project_feature:
- infrastructure_access_level
- feature_flags_access_level
- environments_access_level
- - releases_access_level
- project_id
- updated_at
computed_attributes:
@@ -149,6 +147,7 @@ project_setting:
- has_vulnerabilities
- legacy_open_source_license_available
- prevent_merge_without_jira_issue
+ - only_allow_merge_if_all_status_checks_passed
- warn_about_potentially_unwanted_characters
- previous_default_branch
- project_id
@@ -161,6 +160,8 @@ project_setting:
- target_platforms
- selective_code_owner_removals
- show_diff_preview_in_email
+ - suggested_reviewers_enabled
+ - jitsu_key
build_service_desk_setting: # service_desk_setting
unexposed_attributes:
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 7ad1ce0ede9..38f7d6e3eba 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -221,6 +221,16 @@ RSpec.describe API::Projects do
expect(project_response['container_registry_enabled']).to eq(false)
end
+ it 'includes releases_access_level', :aggregate_failures do
+ project.project_feature.update!(releases_access_level: ProjectFeature::DISABLED)
+
+ get api('/projects', user)
+ project_response = json_response.find { |p| p['id'] == project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project_response['releases_access_level']).to eq('disabled')
+ end
+
context 'when some projects are in a group' do
before do
create(:project, :public, group: create(:group))
@@ -1171,6 +1181,7 @@ RSpec.describe API::Projects do
attrs[:analytics_access_level] = 'disabled'
attrs[:container_registry_access_level] = 'private'
attrs[:security_and_compliance_access_level] = 'private'
+ attrs[:releases_access_level] = 'disabled'
end
post api('/projects', user), params: project
@@ -1180,7 +1191,7 @@ RSpec.describe API::Projects do
project.each_pair do |k, v|
next if %i[
has_external_issue_tracker has_external_wiki issues_enabled merge_requests_enabled wiki_enabled storage_version
- container_registry_access_level
+ container_registry_access_level releases_access_level
].include?(k)
expect(json_response[k.to_s]).to eq(v)
@@ -1195,6 +1206,7 @@ RSpec.describe API::Projects do
expect(project.project_feature.analytics_access_level).to eq(ProjectFeature::DISABLED)
expect(project.project_feature.container_registry_access_level).to eq(ProjectFeature::PRIVATE)
expect(project.project_feature.security_and_compliance_access_level).to eq(ProjectFeature::PRIVATE)
+ expect(project.project_feature.releases_access_level).to eq(ProjectFeature::DISABLED)
end
it 'assigns container_registry_enabled to project', :aggregate_failures do
@@ -2333,6 +2345,7 @@ RSpec.describe API::Projects do
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
expect(json_response['operations_access_level']).to be_present
expect(json_response['security_and_compliance_access_level']).to be_present
+ expect(json_response['releases_access_level']).to be_present
end
it 'exposes all necessary attributes' do
@@ -2402,6 +2415,7 @@ RSpec.describe API::Projects do
expect(json_response['builds_access_level']).to be_present
expect(json_response['operations_access_level']).to be_present
expect(json_response['security_and_compliance_access_level']).to be_present
+ expect(json_response['releases_access_level']).to be_present
expect(json_response).to have_key('emails_disabled')
expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
expect(json_response['remove_source_branch_after_merge']).to be_truthy
@@ -2516,7 +2530,7 @@ RSpec.describe API::Projects do
'name' => project.repository.license.name,
'nickname' => project.repository.license.nickname,
'html_url' => project.repository.license.url,
- 'source_url' => project.repository.license.meta['source']
+ 'source_url' => nil
})
end
@@ -3386,6 +3400,14 @@ RSpec.describe API::Projects do
expect(Project.find_by(path: project[:path]).analytics_access_level).to eq(ProjectFeature::PRIVATE)
end
+ it 'sets releases_access_level', :aggregate_failures do
+ put api("/projects/#{project.id}", user), params: { releases_access_level: 'private' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['releases_access_level']).to eq('private')
+ expect(Project.find_by(path: project[:path]).releases_access_level).to eq(ProjectFeature::PRIVATE)
+ end
+
it 'returns 400 when nothing sent' do
project_param = {}
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 315c76c8ac3..3a9b2d02af5 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -60,6 +60,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['inactive_projects_delete_after_months']).to eq(2)
expect(json_response['inactive_projects_min_size_mb']).to eq(0)
expect(json_response['inactive_projects_send_warning_email_after_months']).to eq(1)
+ expect(json_response['can_create_group']).to eq(true)
end
end
@@ -156,7 +157,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
delete_inactive_projects: true,
inactive_projects_delete_after_months: 24,
inactive_projects_min_size_mb: 10,
- inactive_projects_send_warning_email_after_months: 12
+ inactive_projects_send_warning_email_after_months: 12,
+ can_create_group: false
}
expect(response).to have_gitlab_http_status(:ok)
@@ -217,6 +219,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['inactive_projects_delete_after_months']).to eq(24)
expect(json_response['inactive_projects_min_size_mb']).to eq(10)
expect(json_response['inactive_projects_send_warning_email_after_months']).to eq(12)
+ expect(json_response['can_create_group']).to eq(false)
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index b62fbaead6f..c635d73efe3 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -418,14 +418,6 @@ RSpec.describe API::Tags do
context 'annotated tag' do
it 'creates a new annotated tag' do
- # Identity must be set in .gitconfig to create annotated tag.
- repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path_to_repo
- end
-
- system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.name #{user.name}))
- system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.email #{user.email}))
-
post api(route, current_user), params: { tag_name: 'v7.1.0', ref: 'master', message: 'Release 7.1.0' }
expect(response).to have_gitlab_http_status(:created)
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 96e23337411..1b0a27e78e3 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -165,6 +165,7 @@ RSpec.describe API::Users do
expect(json_response.first).not_to have_key('note')
expect(json_response.first).not_to have_key('namespace_id')
+ expect(json_response.first).not_to have_key('created_by')
end
end
@@ -175,6 +176,7 @@ RSpec.describe API::Users do
expect(json_response.first).not_to have_key('note')
expect(json_response.first).not_to have_key('namespace_id')
+ expect(json_response.first).not_to have_key('created_by')
end
end
@@ -186,6 +188,26 @@ RSpec.describe API::Users do
expect(json_response.first).to have_key('note')
expect(json_response.first['note']).to eq '2018-11-05 | 2FA removed | user requested | www.gitlab.com'
end
+
+ context 'with `created_by` details' do
+ it 'has created_by as nil with a self-registered account' do
+ get api("/users", admin), params: { username: user.username }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response.first).to have_key('created_by')
+ expect(json_response.first['created_by']).to eq(nil)
+ end
+
+ it 'is created_by a user and has those details' do
+ created = create(:user, created_by_id: user.id)
+
+ get api("/users", admin), params: { username: created.username }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response.first['created_by'].symbolize_keys)
+ .to eq(API::Entities::UserBasic.new(user).as_json)
+ end
+ end
end
context 'N+1 queries' do
@@ -940,6 +962,17 @@ RSpec.describe API::Users do
expect(user.followees).to contain_exactly(followee)
expect(response).to have_gitlab_http_status(:created)
end
+
+ it 'alerts and not follow when over followee limit' do
+ stub_const('Users::UserFollowUser::MAX_FOLLOWEE_LIMIT', 2)
+ Users::UserFollowUser::MAX_FOLLOWEE_LIMIT.times { user.follow(create(:user)) }
+
+ post api("/users/#{followee.id}/follow", user)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expected_message = format(_("You can't follow more than %{limit} users. To follow more users, unfollow some others."), limit: Users::UserFollowUser::MAX_FOLLOWEE_LIMIT)
+ expect(json_response['message']).to eq(expected_message)
+ expect(user.following?(followee)).to be_falsey
+ end
end
context 'on a followed user' do
diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb
deleted file mode 100644
index 7abbaf4f9ec..00000000000
--- a/spec/requests/api/version_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe API::Version do
- shared_examples_for 'GET /version' do
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get api('/version')
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'when authenticated as user' do
- let(:user) { create(:user) }
-
- it 'returns the version information' do
- get api('/version', user)
-
- expect_version
- end
- end
-
- context 'when authenticated with token' do
- let(:personal_access_token) { create(:personal_access_token, scopes: scopes) }
-
- context 'with api scope' do
- let(:scopes) { %i(api) }
-
- it 'returns the version information' do
- get api('/version', personal_access_token: personal_access_token)
-
- expect_version
- end
-
- it 'returns "200" response on head requests' do
- head api('/version', personal_access_token: personal_access_token)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with read_user scope' do
- let(:scopes) { %i(read_user) }
-
- it 'returns the version information' do
- get api('/version', personal_access_token: personal_access_token)
-
- expect_version
- end
-
- it 'returns "200" response on head requests' do
- head api('/version', personal_access_token: personal_access_token)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with neither api nor read_user scope' do
- let(:scopes) { %i(read_repository) }
-
- it 'returns authorization error' do
- get api('/version', personal_access_token: personal_access_token)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- def expect_version
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['version']).to eq(Gitlab::VERSION)
- expect(json_response['revision']).to eq(Gitlab.revision)
- end
- end
-
- context 'with graphql enabled' do
- before do
- stub_feature_flags(graphql: true)
- end
-
- include_examples 'GET /version'
- end
-
- context 'with graphql disabled' do
- before do
- stub_feature_flags(graphql: false)
- end
-
- include_examples 'GET /version'
- end
-end
diff --git a/spec/requests/boards/lists_controller_spec.rb b/spec/requests/boards/lists_controller_spec.rb
deleted file mode 100644
index 47f4925d5b0..00000000000
--- a/spec/requests/boards/lists_controller_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Boards::ListsController do
- describe '#index' do
- let(:board) { create(:board) }
- let(:user) { board.project.first_owner }
-
- it 'does not have N+1 queries' do
- login_as(user)
-
- # First request has more queries because we create the default `backlog` list
- get board_lists_path(board)
-
- create(:list, board: board)
-
- control_count = ActiveRecord::QueryRecorder.new { get board_lists_path(board) }.count
-
- create_list(:list, 5, board: board)
-
- expect { get board_lists_path(board) }.not_to exceed_query_limit(control_count)
- end
- end
-end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 81e923983ab..20d298edfe5 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -880,29 +880,20 @@ RSpec.describe 'Git HTTP requests' do
let(:path) { "#{project.full_path}.git" }
let(:env) { { user: 'gitlab-ci-token', password: build.token } }
- it_behaves_like 'pulls are allowed'
+ it 'rejects pulls' do
+ download(path, **env) do |response|
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
- # A non-401 here is not an information leak since the system is
- # "authenticated" as CI using the correct token. It does not have
- # push access, so pushes should be rejected as forbidden, and giving
- # a reason is fine.
- #
- # We know for sure it is not an information leak since pulls using
- # the build token must be allowed.
- it "rejects pushes with 403 Forbidden" do
+ it 'rejects pushes' do
push_get(path, **env)
expect(response).to have_gitlab_http_status(:forbidden)
- expect(response.body).to eq(git_access_error(:auth_upload))
end
- # We are "authenticated" as CI using a valid token here. But we are
- # not authorized to see any other project, so return "not found".
- it "rejects pulls for other project with 404 Not Found" do
- clone_get("#{other_project.full_path}.git", **env)
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.body).to eq(git_access_error(:project_not_found))
+ def pull
+ download(path, **env)
end
end
@@ -1494,33 +1485,21 @@ RSpec.describe 'Git HTTP requests' do
added_by: user)
end
+ # legacy behavior that is blocked/deprecated
context 'when build created by system is authenticated' do
let(:path) { "#{project.full_path}.git" }
let(:env) { { user: 'gitlab-ci-token', password: build.token } }
- it_behaves_like 'pulls are allowed'
+ it 'rejects pulls' do
+ download(path, **env) do |response|
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
- # A non-401 here is not an information leak since the system is
- # "authenticated" as CI using the correct token. It does not have
- # push access, so pushes should be rejected as forbidden, and giving
- # a reason is fine.
- #
- # We know for sure it is not an information leak since pulls using
- # the build token must be allowed.
- it "rejects pushes with 403 Forbidden" do
+ it 'rejects pushes' do
push_get(path, **env)
expect(response).to have_gitlab_http_status(:forbidden)
- expect(response.body).to eq(git_access_error(:auth_upload))
- end
-
- # We are "authenticated" as CI using a valid token here. But we are
- # not authorized to see any other project, so return "not found".
- it "rejects pulls for other project with 404 Not Found" do
- clone_get("#{other_project.full_path}.git", **env)
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(response.body).to eq(git_access_error(:project_not_found))
end
end
@@ -1780,8 +1759,7 @@ RSpec.describe 'Git HTTP requests' do
end
describe "User with LDAP identity" do
- let(:user) { create(:omniauth_user, extern_uid: dn) }
- let(:dn) { 'uid=john,ou=people,dc=example,dc=com' }
+ let(:user) { create(:omniauth_user, :ldap) }
let(:path) { 'doesnt/exist.git' }
before do
diff --git a/spec/requests/groups/settings/access_tokens_controller_spec.rb b/spec/requests/groups/settings/access_tokens_controller_spec.rb
index eabdef3c41e..cf728b3935f 100644
--- a/spec/requests/groups/settings/access_tokens_controller_spec.rb
+++ b/spec/requests/groups/settings/access_tokens_controller_spec.rb
@@ -87,4 +87,19 @@ RSpec.describe Groups::Settings::AccessTokensController do
it_behaves_like 'feature unavailable'
it_behaves_like 'PUT resource access tokens available'
end
+
+ describe '#index' do
+ let_it_be(:resource_access_tokens) { create_list(:personal_access_token, 3, user: bot_user) }
+
+ before do
+ get group_settings_access_tokens_path(resource)
+ end
+
+ it 'includes details of the active group access tokens' do
+ active_resource_access_tokens =
+ ::GroupAccessTokenSerializer.new.represent(resource_access_tokens.reverse, group: resource)
+
+ expect(assigns(:active_resource_access_tokens).to_json).to eq(active_resource_access_tokens.to_json)
+ end
+ end
end
diff --git a/spec/requests/ide_controller_spec.rb b/spec/requests/ide_controller_spec.rb
index 151fa89b819..8d61399c824 100644
--- a/spec/requests/ide_controller_spec.rb
+++ b/spec/requests/ide_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe IdeController do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:reporter) { create(:user) }
let_it_be(:project) do
@@ -14,6 +16,8 @@ RSpec.describe IdeController do
let_it_be(:creator) { project.creator }
let_it_be(:other_user) { create(:user) }
+ let_it_be(:top_nav_partial) { 'layouts/header/_default' }
+
let(:user) { creator }
let(:branch) { '' }
@@ -233,6 +237,33 @@ RSpec.describe IdeController do
end
end
end
+
+ # This indirectly tests that `minimal: true` was passed to the fullscreen layout
+ describe 'layout' do
+ where(:ff_state, :use_legacy_web_ide, :expect_top_nav) do
+ false | false | true
+ false | true | true
+ true | true | true
+ true | false | false
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(vscode_web_ide: ff_state)
+ allow(user).to receive(:use_legacy_web_ide).and_return(use_legacy_web_ide)
+
+ subject
+ end
+
+ it 'handles rendering top nav' do
+ if expect_top_nav
+ expect(response).to render_template(top_nav_partial)
+ else
+ expect(response).not_to render_template(top_nav_partial)
+ end
+ end
+ end
+ end
end
end
end
diff --git a/spec/requests/import/github_groups_controller_spec.rb b/spec/requests/import/github_groups_controller_spec.rb
new file mode 100644
index 00000000000..544cbf88cd2
--- /dev/null
+++ b/spec/requests/import/github_groups_controller_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::GithubGroupsController do
+ describe 'GET status' do
+ subject(:status) { get '/import/github_group/status', params: params, headers: headers }
+
+ let_it_be(:user) { create(:user) }
+ let(:headers) { { 'Accept' => 'application/json' } }
+ let(:params) { {} }
+
+ before do
+ login_as(user)
+ end
+
+ context 'when OAuth config is missing' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for).with('github').and_return(nil)
+ end
+
+ it 'returns missing config error' do
+ status
+
+ expect(json_response['errors']).to eq('Missing OAuth configuration for GitHub.')
+ end
+ end
+
+ context 'when OAuth config present' do
+ let(:github_access_token) { 'asdasd12345' }
+
+ before do
+ post '/import/github/personal_access_token', params: { personal_access_token: github_access_token }
+ end
+
+ it 'fetches organizations' do
+ expect_next_instance_of(Octokit::Client) do |client|
+ expect(client).to receive(:organizations).and_return([].to_enum)
+ end
+
+ status
+ end
+
+ context 'with pagination' do
+ context 'when no page is specified' do
+ it 'requests first page' do
+ expect_next_instance_of(Octokit::Client) do |client|
+ expect(client).to receive(:organizations).with(nil, { page: 1, per_page: 25 }).and_return([].to_enum)
+ end
+
+ status
+ end
+ end
+
+ context 'when page is specified' do
+ let(:params) { { page: 2 } }
+
+ it 'responds with organizations with specified page' do
+ expect_next_instance_of(Octokit::Client) do |client|
+ expect(client).to receive(:organizations).with(nil, { page: 2, per_page: 25 }).and_return([].to_enum)
+ end
+
+ status
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/jira_connect/public_keys_controller_spec.rb b/spec/requests/jira_connect/public_keys_controller_spec.rb
new file mode 100644
index 00000000000..2eca4c0ea2f
--- /dev/null
+++ b/spec/requests/jira_connect/public_keys_controller_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::PublicKeysController do
+ describe 'GET /-/jira_connect/public_keys/:uuid' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(dot_com)
+ end
+
+ let(:uuid) { non_existing_record_id }
+ let(:dot_com) { true }
+
+ it 'renders 404' do
+ get jira_connect_public_key_path(id: uuid)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when public key exists' do
+ let_it_be(:public_key) { JiraConnect::PublicKey.create!(key: OpenSSL::PKey::RSA.generate(3072).public_key) }
+
+ let(:uuid) { public_key.uuid }
+
+ it 'renders 200' do
+ get jira_connect_public_key_path(id: uuid)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(public_key.key)
+ end
+
+ context 'when not on GitLab.com' do
+ let(:dot_com) { false }
+
+ it 'renders 404' do
+ get jira_connect_public_key_path(id: uuid)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when jira_connect_oauth_self_managed disabled' do
+ before do
+ stub_feature_flags(jira_connect_oauth_self_managed: false)
+ end
+
+ it 'renders 404' do
+ get jira_connect_public_key_path(id: uuid)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb b/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb
index 7d5eb1c9685..c5e7369b0a9 100644
--- a/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb
+++ b/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb
@@ -8,10 +8,11 @@ RSpec.describe 'Projects::Ci::PrometheusMetrics::HistogramsController' do
describe 'POST /*namespace_id/:project_id/-/ci/prometheus_metrics/histograms' do
context 'with known histograms' do
it 'returns 201 Created' do
- post histograms_route(histograms: [
- { name: :pipeline_graph_link_calculation_duration_seconds, value: 1 },
- { name: :pipeline_graph_links_total, value: 10 }
- ])
+ post histograms_route(histograms:
+ [
+ { name: :pipeline_graph_link_calculation_duration_seconds, value: 1 },
+ { name: :pipeline_graph_links_total, value: 10 }
+ ])
expect(response).to have_gitlab_http_status(:created)
end
diff --git a/spec/requests/projects/incident_management/timeline_events_spec.rb b/spec/requests/projects/incident_management/timeline_events_spec.rb
new file mode 100644
index 00000000000..f7dead4834d
--- /dev/null
+++ b/spec/requests/projects/incident_management/timeline_events_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Timeline Events' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:incident) { create(:incident, project: project) }
+
+ describe 'POST /preview_markdown' do
+ let(:timeline_text) { "timeline text with image ![img](img/src.png) and reference #{incident.to_reference}" }
+
+ context 'when authorized' do
+ let(:expected_img) do
+ '<a class="with-attachment-icon" href="img/src.png" target="_blank" rel="noopener noreferrer">img</a>'
+ end
+
+ let(:expected_reference) do
+ %(<a href="/#{project.full_path}/-/issues/#{incident.iid}" data-reference-type="issue" ) +
+ %(data-original="##{incident.iid}" data-link="false" data-link-reference="false" ) +
+ %(data-project="#{project.id}" data-issue="#{incident.id}" data-project-path="#{project.full_path}" ) +
+ %(data-iid="#{incident.iid}" data-issue-type="incident" data-container="body" data-placement="top" ) +
+ %(title="#{incident.title}" class="gfm gfm-issue">##{incident.iid}</a>)
+ end
+
+ let(:expected_body) do
+ "<p>timeline text with image #{expected_img} and reference #{expected_reference}</p>"
+ end
+
+ before do
+ project.add_developer(user)
+ login_as(user)
+ end
+
+ it 'renders JSON in a correct format' do
+ post preview_markdown_project_incident_management_timeline_events_path(project, format: :json),
+ params: { text: timeline_text }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({
+ body: expected_body,
+ references: {
+ commands: '',
+ suggestions: [],
+ users: []
+ }
+ }.as_json)
+ end
+ end
+
+ context 'when not authorized' do
+ it 'returns 302' do
+ post preview_markdown_project_incident_management_timeline_events_path(project, format: :json),
+ params: { text: timeline_text }
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb
index de1d55ff5be..aa2ba5e114b 100644
--- a/spec/requests/projects/issues_controller_spec.rb
+++ b/spec/requests/projects/issues_controller_spec.rb
@@ -31,11 +31,12 @@ RSpec.describe Projects::IssuesController do
notes = discussions.flat_map { |d| d['notes'] }
expect(discussions.count).to eq(2)
- expect(notes).to match([
- a_hash_including('id' => discussion.id.to_s),
- a_hash_including('id' => discussion_reply.id.to_s),
- a_hash_including('type' => 'StateNote')
- ])
+ expect(notes).to match(
+ [
+ a_hash_including('id' => discussion.id.to_s),
+ a_hash_including('id' => discussion_reply.id.to_s),
+ a_hash_including('type' => 'StateNote')
+ ])
cursor = response.header['X-Next-Page-Cursor']
expect(cursor).to be_present
@@ -46,9 +47,7 @@ RSpec.describe Projects::IssuesController do
notes = discussions.flat_map { |d| d['notes'] }
expect(discussions.count).to eq(1)
- expect(notes).to match([
- a_hash_including('id' => discussion_2.id.to_s)
- ])
+ expect(notes).to match([a_hash_including('id' => discussion_2.id.to_s)])
end
end
end
diff --git a/spec/requests/projects/merge_requests_controller_spec.rb b/spec/requests/projects/merge_requests_controller_spec.rb
index 6580fc8b80f..2ee86bb423b 100644
--- a/spec/requests/projects/merge_requests_controller_spec.rb
+++ b/spec/requests/projects/merge_requests_controller_spec.rb
@@ -29,11 +29,12 @@ RSpec.describe Projects::MergeRequestsController do
notes = discussions.flat_map { |d| d['notes'] }
expect(discussions.count).to eq(2)
- expect(notes).to match([
- a_hash_including('id' => discussion.id.to_s),
- a_hash_including('id' => discussion_reply.id.to_s),
- a_hash_including('type' => 'StateNote')
- ])
+ expect(notes).to match(
+ [
+ a_hash_including('id' => discussion.id.to_s),
+ a_hash_including('id' => discussion_reply.id.to_s),
+ a_hash_including('type' => 'StateNote')
+ ])
cursor = response.header['X-Next-Page-Cursor']
expect(cursor).to be_present
@@ -44,9 +45,7 @@ RSpec.describe Projects::MergeRequestsController do
notes = discussions.flat_map { |d| d['notes'] }
expect(discussions.count).to eq(1)
- expect(notes).to match([
- a_hash_including('id' => discussion_2.id.to_s)
- ])
+ expect(notes).to match([a_hash_including('id' => discussion_2.id.to_s)])
end
context 'when paginated_mr_discussions is disabled' do
diff --git a/spec/requests/projects/settings/access_tokens_controller_spec.rb b/spec/requests/projects/settings/access_tokens_controller_spec.rb
index 780d1b8caef..48114834c65 100644
--- a/spec/requests/projects/settings/access_tokens_controller_spec.rb
+++ b/spec/requests/projects/settings/access_tokens_controller_spec.rb
@@ -88,4 +88,19 @@ RSpec.describe Projects::Settings::AccessTokensController do
it_behaves_like 'feature unavailable'
it_behaves_like 'PUT resource access tokens available'
end
+
+ describe '#index' do
+ let_it_be(:resource_access_tokens) { create_list(:personal_access_token, 3, user: bot_user) }
+
+ before do
+ get project_settings_access_tokens_path(resource)
+ end
+
+ it 'includes details of the active project access tokens' do
+ active_resource_access_tokens =
+ ::ProjectAccessTokenSerializer.new.represent(resource_access_tokens.reverse, project: resource)
+
+ expect(assigns(:active_resource_access_tokens).to_json).to eq(active_resource_access_tokens.to_json)
+ end
+ end
end
diff --git a/spec/requests/users/namespace_callouts_spec.rb b/spec/requests/users/namespace_callouts_spec.rb
deleted file mode 100644
index 5a4e269eefb..00000000000
--- a/spec/requests/users/namespace_callouts_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Namespace callouts' do
- let_it_be(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- describe 'POST /-/users/namespace_callouts' do
- let(:params) { { feature_name: feature_name, namespace_id: user.namespace.id } }
-
- subject { post namespace_callouts_path, params: params, headers: { 'ACCEPT' => 'application/json' } }
-
- context 'with valid feature name and group' do
- let(:feature_name) { Users::NamespaceCallout.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::NamespaceCallout.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) do
- create(:namespace_callout,
- feature_name: Users::GroupCallout.feature_names.each_key.first,
- user: user,
- namespace: user.namespace)
- end
-
- it 'returns success', :aggregate_failures do
- expect { subject }.not_to change { Users::NamespaceCallout.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/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index 42f14392117..e78d4cc326e 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -828,6 +828,26 @@ RSpec.describe UsersController do
end
end
+ describe 'POST #follow' do
+ context 'when over followee limit' do
+ before do
+ stub_const('Users::UserFollowUser::MAX_FOLLOWEE_LIMIT', 2)
+ sign_in(user)
+ end
+
+ it 'alerts and not follow' do
+ Users::UserFollowUser::MAX_FOLLOWEE_LIMIT.times { user.follow(create(:user)) }
+
+ post user_follow_url(username: public_user.username)
+ expect(response).to be_redirect
+
+ expected_message = format(_("You can't follow more than %{limit} users. To follow more users, unfollow some others."), limit: Users::UserFollowUser::MAX_FOLLOWEE_LIMIT)
+ expect(flash[:alert]).to eq(expected_message)
+ expect(user).not_to be_following(public_user)
+ end
+ end
+ end
+
context 'token authentication' do
it_behaves_like 'authenticates sessionless user for the request spec', 'show atom', public_resource: true do
let(:url) { user_url(user, format: :atom) }
diff --git a/spec/routing/import_routing_spec.rb b/spec/routing/import_routing_spec.rb
index b1da2eaa33b..b63ae1e7e4e 100644
--- a/spec/routing/import_routing_spec.rb
+++ b/spec/routing/import_routing_spec.rb
@@ -177,3 +177,10 @@ RSpec.describe Import::PhabricatorController, 'routing' do
expect(get("/import/phabricator/new")).to route_to("import/phabricator#new")
end
end
+
+# status_import_github_group GET /import/github_group/status(.:format) import/github_groups#status
+RSpec.describe Import::GithubGroupsController, 'routing' do
+ it 'to #status' do
+ expect(get('/import/github_group/status')).to route_to('import/github_groups#status')
+ end
+end
diff --git a/spec/rubocop/check_graceful_task_spec.rb b/spec/rubocop/check_graceful_task_spec.rb
index 0364820a602..c39a00470fd 100644
--- a/spec/rubocop/check_graceful_task_spec.rb
+++ b/spec/rubocop/check_graceful_task_spec.rb
@@ -62,25 +62,35 @@ RSpec.describe RuboCop::CheckGracefulTask do
let(:adjusted_rubocop_status) { status_success }
context 'with sufficient environment variables' do
+ let(:script) { 'scripts/slack' }
let(:channel) { 'f_rubocop' }
+ let(:emoji) { 'rubocop' }
+ let(:user_name) { 'GitLab Bot' }
+ let(:job_name) { 'some job name' }
+ let(:job_url) { 'some job url' }
+ let(:docs_link) { 'https://docs.gitlab.com/ee/development/contributing/style_guides.html#silenced-offenses' }
before do
env = {
'CI_SLACK_WEBHOOK_URL' => 'webhook_url',
- 'CI_JOB_NAME' => 'job_name',
- 'CI_JOB_URL' => 'job_url'
+ 'CI_JOB_NAME' => job_name,
+ 'CI_JOB_URL' => job_url
}
stub_const('ENV', ENV.to_hash.update(env))
end
it 'notifies slack' do
- popen_args = ['scripts/slack', channel, kind_of(String), 'rubocop', kind_of(String)]
popen_result = ['', 0]
- expect(Gitlab::Popen).to receive(:popen).with(popen_args).and_return(popen_result)
+ allow(Gitlab::Popen).to receive(:popen).with(anything).and_return(popen_result)
subject
+ message = a_kind_of(String).and include(job_name).and include(job_url).and include(docs_link)
+
+ expect(Gitlab::Popen).to have_received(:popen)
+ .with([script, channel, message, emoji, user_name])
+
expect(output.string).to include("Notifying Slack ##{channel}.")
end
diff --git a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
index 9a1639806c8..0a121a495c9 100644
--- a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
+++ b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
@@ -4,7 +4,7 @@ require 'rubocop_spec_helper'
require_relative '../../../../rubocop/cop/gitlab/duplicate_spec_location'
-RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation do
+RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec do
let(:rails_root) { '../../../../' }
def full_path(path)
diff --git a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb
index ac7e41dda44..a3c9ae8916e 100644
--- a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb
+++ b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb
@@ -7,7 +7,7 @@ require_relative '../../../../rubocop/cop/gitlab/mark_used_feature_flags'
RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do
let(:defined_feature_flags) do
- %w[a_feature_flag foo_hello foo_world baz_experiment_percentage bar_baz]
+ %w[a_feature_flag foo_hello foo_world bar_baz baz]
end
before do
@@ -118,40 +118,33 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do
end
end
- %w[
- experiment
- experiment_enabled?
- push_frontend_experiment
- Gitlab::Experimentation.active?
- ].each do |feature_flag_method|
- context "#{feature_flag_method} method" do
- context 'a string feature flag' do
- include_examples 'sets flag as used', %Q|#{feature_flag_method}("baz")|, %w[baz baz_experiment_percentage]
- end
+ context 'with the experiment method' do
+ context 'a string feature flag' do
+ include_examples 'sets flag as used', %q|experiment("baz")|, %w[baz]
+ end
- context 'a symbol feature flag' do
- include_examples 'sets flag as used', %Q|#{feature_flag_method}(:baz)|, %w[baz baz_experiment_percentage]
- end
+ context 'a symbol feature flag' do
+ include_examples 'sets flag as used', %q|experiment(:baz)|, %w[baz]
+ end
- context 'an interpolated string feature flag with a string prefix' do
- include_examples 'sets flag as used', %Q|#{feature_flag_method}("foo_\#{bar}")|, %w[foo_hello foo_world]
- end
+ context 'an interpolated string feature flag with a string prefix' do
+ include_examples 'sets flag as used', %Q|experiment("foo_\#{bar}")|, %w[foo_hello foo_world]
+ end
- context 'an interpolated symbol feature flag with a string prefix' do
- include_examples 'sets flag as used', %Q|#{feature_flag_method}(:"foo_\#{bar}")|, %w[foo_hello foo_world]
- end
+ context 'an interpolated symbol feature flag with a string prefix' do
+ include_examples 'sets flag as used', %Q|experiment(:"foo_\#{bar}")|, %w[foo_hello foo_world]
+ end
- context 'an interpolated string feature flag with a string prefix and suffix' do
- include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(:"foo_\#{bar}_baz")|
- end
+ context 'an interpolated string feature flag with a string prefix and suffix' do
+ include_examples 'does not set any flags as used', %Q|experiment(:"foo_\#{bar}_baz")|
+ end
- context 'a dynamic string feature flag as a variable' do
- include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(a_variable, an_arg)|
- end
+ context 'a dynamic string feature flag as a variable' do
+ include_examples 'does not set any flags as used', %q|experiment(a_variable, an_arg)|
+ end
- context 'an integer feature flag' do
- include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(123)|
- end
+ context 'an integer feature flag' do
+ include_examples 'does not set any flags as used', %q|experiment(123)|
end
end
diff --git a/spec/rubocop/cop/gitlab/no_code_coverage_comment_spec.rb b/spec/rubocop/cop/gitlab/no_code_coverage_comment_spec.rb
new file mode 100644
index 00000000000..f0c0297d266
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/no_code_coverage_comment_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+require_relative '../../../../rubocop/cop/gitlab/no_code_coverage_comment'
+
+RSpec.describe RuboCop::Cop::Gitlab::NoCodeCoverageComment do
+ let(:msg) { format(described_class::MSG, nocov_comment: nocov_comment) }
+ let(:nocov_comment) { ":#{comment_token}:" }
+
+ shared_examples 'nocov check' do
+ it 'flags related code comments' do
+ expect_offense(<<~RUBY, nocov_token: comment_token, msg: msg)
+ # :%{nocov_token}:
+ ^^^{nocov_token} %{msg}
+ def method
+ end
+ #:%{nocov_token}:
+ ^^^{nocov_token} %{msg}
+
+ def other_method
+ if expr
+ # :%{nocov_token}: With some additional comments
+ ^^^{nocov_token} %{msg}
+ value << line.strip
+ # :%{nocov_token}:
+ ^^^{nocov_token} %{msg}
+ end
+ end
+ RUBY
+ end
+
+ it 'ignores unrelated comments' do
+ expect_no_offenses(<<~RUBY)
+ # Other comments are ignored :#{comment_token}:
+ #
+ # # :#{comment_token}:
+ RUBY
+ end
+ end
+
+ context 'with nocov as default comment token' do
+ it_behaves_like 'nocov check' do
+ let(:comment_token) { described_class::DEFAULT_COMMENT_TOKEN }
+ end
+ end
+
+ context 'with configured comment token' do
+ it_behaves_like 'nocov check' do
+ let(:comment_token) { 'skipit' }
+
+ let(:config) do
+ RuboCop::Config.new(
+ 'Gitlab/NoCodeCoverageComment' => {
+ 'CommentToken' => comment_token
+ }
+ )
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/service_response_spec.rb b/spec/rubocop/cop/gitlab/service_response_spec.rb
new file mode 100644
index 00000000000..84cf0dbff52
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/service_response_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+require_relative '../../../../rubocop/cop/gitlab/service_response'
+
+RSpec.describe RuboCop::Cop::Gitlab::ServiceResponse do
+ subject(:cop) { described_class.new }
+
+ it 'does not flag the `http_status:` param on a homonym method' do
+ expect_no_offenses("MyClass.error(http_status: :ok)")
+ end
+
+ it 'does not flag calls without params' do
+ expect_no_offenses('ServiceResponse.error')
+ end
+
+ it 'does not flag the offense when `http_status` is not used' do
+ expect_no_offenses('ServiceResponse.error(message: "some error", reason: :bad_time)')
+ end
+
+ it 'flags the use of `http_status:` parameter in ServiceResponse in error' do
+ expect_offense(<<~CODE, msg: described_class::MSG)
+ ServiceResponse.error(message: "some error", http_status: :bad_request)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ %{msg}
+ CODE
+ end
+
+ it 'flags the use of `http_status:` parameter in ServiceResponse in success' do
+ expect_offense(<<~CODE, msg: described_class::MSG)
+ ServiceResponse.success(message: "some error", http_status: :bad_request)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ %{msg}
+ CODE
+ end
+
+ it 'flags the use of `http_status:` parameter in ServiceResponse in initializer' do
+ expect_offense(<<~CODE, msg: described_class::MSG)
+ ServiceResponse.new(message: "some error", http_status: :bad_request)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ %{msg}
+ CODE
+ end
+end
diff --git a/spec/rubocop/cop/migration/background_migration_missing_active_concern_spec.rb b/spec/rubocop/cop/migration/background_migration_missing_active_concern_spec.rb
new file mode 100644
index 00000000000..c74a7d29056
--- /dev/null
+++ b/spec/rubocop/cop/migration/background_migration_missing_active_concern_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+require_relative '../../../../rubocop/cop/migration/background_migration_missing_active_concern'
+
+RSpec.describe RuboCop::Cop::Migration::BackgroundMigrationMissingActiveConcern do
+ shared_examples 'offense is not registered' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ module Gitlab
+ module BackgroundMigration
+ prepended do
+ scope_to -> (relation) { relation }
+ end
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'when outside of a migration' do
+ it_behaves_like 'offense is not registered'
+ end
+
+ context 'in non-ee background migration' do
+ before do
+ allow(cop).to receive(:in_ee_background_migration?).and_return(false)
+ end
+
+ it_behaves_like 'offense is not registered'
+ end
+
+ context 'in ee background migration' do
+ before do
+ allow(cop).to receive(:in_ee_background_migration?).and_return(true)
+ end
+
+ context 'when scope_to is not used inside prepended block' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ module Gitlab
+ module BackgroundMigration
+ prepended do
+ some_method_to -> (relation) { relation }
+ end
+
+ def foo
+ scope_to -> (relation) { relation }
+ end
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'when scope_to is used inside prepended block' do
+ it 'does not register any offenses if the module does extend ActiveSupport::Concern' do
+ expect_no_offenses(<<~RUBY)
+ module Gitlab
+ module BackgroundMigration
+ extend ::Gitlab::Utils::Override
+ extend ActiveSupport::Concern
+
+ prepended do
+ scope_to -> (relation) { relation }
+ end
+ end
+ end
+ RUBY
+ end
+
+ it 'registers an offense if the module does not extend ActiveSupport::Concern' do
+ expect_offense(<<~RUBY)
+ module Gitlab
+ module BackgroundMigration
+ prepended do
+ scope_to -> (relation) { relation }
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Extend `ActiveSupport::Concern` [...]
+ end
+ end
+ end
+ RUBY
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/cop/redis_queue_usage_spec.rb b/spec/rubocop/cop/redis_queue_usage_spec.rb
new file mode 100644
index 00000000000..9861a6a79d9
--- /dev/null
+++ b/spec/rubocop/cop/redis_queue_usage_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+
+require_relative '../../../rubocop/cop/redis_queue_usage'
+
+RSpec.describe RuboCop::Cop::RedisQueueUsage do
+ let(:msg) { described_class::MSG }
+
+ context 'when assigning Gitlab::Redis::Queues as a variable' do
+ it 'registers offence for any variable assignment' do
+ expect_offense(<<~PATTERN)
+ x = Gitlab::Redis::Queues
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignment' do
+ expect_offense(<<~PATTERN)
+ X = Gitlab::Redis::Queues
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+ end
+
+ context 'when assigning Gitlab::Redis::Queues as a part of an array' do
+ it 'registers offence for variable assignments' do
+ expect_offense(<<~PATTERN)
+ x = [ Gitlab::Redis::Cache, Gitlab::Redis::Queues, Gitlab::Redis::SharedState ]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments' do
+ expect_offense(<<~PATTERN)
+ ALL = [ Gitlab::Redis::Cache, Gitlab::Redis::Queues, Gitlab::Redis::SharedState ]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments while invoking function' do
+ expect_offense(<<~PATTERN)
+ ALL = [ Gitlab::Redis::Cache, Gitlab::Redis::Queues, Gitlab::Redis::SharedState ].freeze
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments while invoking multiple functions' do
+ expect_offense(<<~PATTERN)
+ ALL = [ Gitlab::Redis::Cache, Gitlab::Redis::Queues, Gitlab::Redis::SharedState ].foo.freeze
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+ end
+
+ context 'when assigning Gitlab::Redis::Queues as a part of a hash' do
+ it 'registers offence for variable assignments' do
+ expect_offense(<<~PATTERN)
+ x = { "test": Gitlab::Redis::Queues, "test2": Gitlab::Redis::SharedState }
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments' do
+ expect_offense(<<~PATTERN)
+ ALL = { "test": Gitlab::Redis::Queues, "test2": Gitlab::Redis::SharedState }
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments while invoking function' do
+ expect_offense(<<~PATTERN)
+ ALL = { "test": Gitlab::Redis::Queues, "test2": Gitlab::Redis::SharedState }.freeze
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for constant assignments while invoking multiple functions' do
+ expect_offense(<<~PATTERN)
+ ALL = { "test": Gitlab::Redis::Queues, "test2": Gitlab::Redis::SharedState }.foo.freeze
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+ end
+
+ it 'registers offence for any invocation of Gitlab::Redis::Queues methods' do
+ expect_offense(<<~PATTERN)
+ Gitlab::Redis::Queues.params
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence for using Gitlab::Redis::Queues as parameter in method calls' do
+ expect_offense(<<~PATTERN)
+ use_redis(Gitlab::Redis::Queues)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+end
diff --git a/spec/rubocop/cop/rspec/factory_bot/avoid_create_spec.rb b/spec/rubocop/cop/rspec/factory_bot/avoid_create_spec.rb
new file mode 100644
index 00000000000..7f45661c13d
--- /dev/null
+++ b/spec/rubocop/cop/rspec/factory_bot/avoid_create_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+
+require_relative '../../../../../rubocop/cop/rspec/factory_bot/avoid_create'
+
+RSpec.describe RuboCop::Cop::RSpec::FactoryBot::AvoidCreate do
+ shared_examples 'an offensive factory call' do |namespace|
+ %i[create create_list].each do |forbidden_method|
+ namespaced_forbidden_method = "#{namespace}#{forbidden_method}(:user)"
+
+ it "registers an offense for #{namespaced_forbidden_method}" do
+ expect_offense(<<-RUBY)
+ describe 'foo' do
+ let(:user) { #{namespaced_forbidden_method} }
+ #{'^' * namespaced_forbidden_method.size} Prefer using `build_stubbed` or similar over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#optimize-factory-usage
+ end
+ RUBY
+ end
+ end
+ end
+
+ it_behaves_like 'an offensive factory call', ''
+ it_behaves_like 'an offensive factory call', 'FactoryBot.'
+end
diff --git a/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb b/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
index 90101e09023..6c596210f4e 100644
--- a/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
+++ b/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
@@ -22,6 +22,19 @@ RSpec.describe RuboCop::Cop::RSpec::TopLevelDescribePath do
end
end
+ context 'when the describe is in a shared context' do
+ context 'with shared_context' do
+ it 'registers no offenses' do
+ expect_no_offenses(<<~SOURCE, 'spec/foo.rb')
+ shared_context 'Foo' do
+ describe '#bar' do
+ end
+ end
+ SOURCE
+ end
+ end
+ end
+
context 'when the describe is in a shared example' do
context 'with shared_examples' do
it 'registers no offenses' do
diff --git a/spec/rubocop/cop/sidekiq_api_usage_spec.rb b/spec/rubocop/cop/sidekiq_api_usage_spec.rb
new file mode 100644
index 00000000000..79a0774e625
--- /dev/null
+++ b/spec/rubocop/cop/sidekiq_api_usage_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+
+require_relative '../../../rubocop/cop/sidekiq_api_usage'
+
+RSpec.describe RuboCop::Cop::SidekiqApiUsage do
+ let(:msg) { described_class::MSG }
+
+ context 'when calling Sidekiq::Worker' do
+ it 'registers no offences for calling skipping_transaction_check' do
+ expect_no_offenses(<<~PATTERN)
+ Sidekiq::Worker.skipping_transaction_check do
+ end
+ PATTERN
+ end
+
+ it 'registers no offences for calling raise_inside_transaction_exception' do
+ expect_no_offenses(<<~PATTERN)
+ Sidekiq::Worker.raise_inside_transaction_exception(cause: "testing")
+ PATTERN
+ end
+
+ it 'registers no offences for calling raise_exception_for_being_inside_a_transaction?' do
+ expect_no_offenses(<<~PATTERN)
+ return if Sidekiq::Worker.raise_exception_for_being_inside_a_transaction?
+ PATTERN
+ end
+
+ it 'registers offence for calling other Sidekiq::Worker methods' do
+ expect_offense(<<~PATTERN)
+ Sidekiq::Worker.drain_all
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+ end
+
+ it 'does not registers offence when calling Sidekiq::Testing' do
+ expect_no_offenses(<<~PATTERN)
+ Sidekiq::Testing.inline! do
+ create_real_projects!
+ create_large_projects!
+ end
+ PATTERN
+ end
+
+ it 'registers offence when calling Sidekiq API' do
+ expect_offense(<<~PATTERN)
+ Sidekiq::Queue.new('testing').all
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+
+ it 'registers offence when assigning Sidekiq API classes' do
+ expect_offense(<<~PATTERN)
+ retry_set = Sidekiq::RetrySet.new
+ ^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ PATTERN
+ end
+end
diff --git a/spec/rubocop/cop/sidekiq_redis_call_spec.rb b/spec/rubocop/cop/sidekiq_redis_call_spec.rb
new file mode 100644
index 00000000000..7d1c68bfabe
--- /dev/null
+++ b/spec/rubocop/cop/sidekiq_redis_call_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+
+require_relative '../../../rubocop/cop/sidekiq_redis_call'
+
+RSpec.describe RuboCop::Cop::SidekiqRedisCall do
+ it 'flags any use of Sidekiq.redis even without blocks' do
+ expect_offense(<<~PATTERN)
+ Sidekiq.redis
+ ^^^^^^^^^^^^^ Refrain from directly using Sidekiq.redis unless for migration. For admin operations, use Sidekiq APIs.
+ PATTERN
+ end
+
+ it 'flags the use of Sidekiq.redis in single-line blocks' do
+ expect_offense(<<~PATTERN)
+ Sidekiq.redis { |redis| yield redis }
+ ^^^^^^^^^^^^^ Refrain from directly using Sidekiq.redis unless for migration. For admin operations, use Sidekiq APIs.
+ PATTERN
+ end
+
+ it 'flags the use of Sidekiq.redis in multi-line blocks' do
+ expect_offense(<<~PATTERN)
+ Sidekiq.redis do |conn|
+ ^^^^^^^^^^^^^ Refrain from directly using Sidekiq.redis unless for migration. For admin operations, use Sidekiq APIs.
+ conn.sadd('queues', queues)
+ end
+ PATTERN
+ end
+end
diff --git a/spec/rubocop/cop/static_translation_definition_spec.rb b/spec/rubocop/cop/static_translation_definition_spec.rb
index 10b4f162504..9f45f6f8c5b 100644
--- a/spec/rubocop/cop/static_translation_definition_spec.rb
+++ b/spec/rubocop/cop/static_translation_definition_spec.rb
@@ -38,6 +38,15 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
C = n_("c")
^^^^^^^ #{msg}
CODE
+ <<~'CODE',
+ A = _('a' \
+ ^^^^^^^ [...]
+ 'b')
+ CODE
+ <<~'CODE',
+ A = _("a#{s}")
+ ^^^^^^^^^^ [...]
+ CODE
<<~CODE,
class MyClass
def self.translations
@@ -100,6 +109,9 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
'CONSTANT_1 = __("a")',
'CONSTANT_2 = s__("a")',
'CONSTANT_3 = n__("a")',
+ 'CONSTANT_var = _(code)',
+ 'CONSTANT_int = _(1)',
+ 'CONSTANT_none = _()',
<<~CODE,
class MyClass
def self.method
diff --git a/spec/rubocop/cop_todo_spec.rb b/spec/rubocop/cop_todo_spec.rb
index 3f9c378b303..c641001789f 100644
--- a/spec/rubocop/cop_todo_spec.rb
+++ b/spec/rubocop/cop_todo_spec.rb
@@ -66,6 +66,38 @@ RSpec.describe RuboCop::CopTodo do
end
end
+ describe '#generate?' do
+ subject { cop_todo.generate? }
+
+ context 'when empty todo' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when previously disabled' do
+ before do
+ cop_todo.previously_disabled = true
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when in grace period' do
+ before do
+ cop_todo.grace_period = true
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'with offenses recorded' do
+ before do
+ cop_todo.record('a.rb', 1)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
describe '#to_yaml' do
subject(:yaml) { cop_todo.to_yaml }
@@ -77,9 +109,8 @@ RSpec.describe RuboCop::CopTodo do
specify do
expect(yaml).to eq(<<~YAML)
---
- # Cop supports --auto-correct.
+ # Cop supports --autocorrect.
#{cop_name}:
- Exclude:
YAML
end
end
diff --git a/spec/rubocop/formatter/graceful_formatter_spec.rb b/spec/rubocop/formatter/graceful_formatter_spec.rb
index 0e0c1d52067..1ed8533ac16 100644
--- a/spec/rubocop/formatter/graceful_formatter_spec.rb
+++ b/spec/rubocop/formatter/graceful_formatter_spec.rb
@@ -2,7 +2,8 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
-require 'rubocop/rspec/shared_contexts'
+require 'rubocop'
+require 'rubocop/rspec/support'
require 'stringio'
require_relative '../../../rubocop/formatter/graceful_formatter'
@@ -225,14 +226,14 @@ RSpec.describe RuboCop::Formatter::GracefulFormatter, :isolated_environment do
cop_name: cop_name,
corrected?: false,
correctable?: false,
- severity: double(:severity, name: 'convention', code: :C),
+ severity: double(:severity, name: :convention, code: :C),
line: 5,
column: 23,
real_column: 23,
corrected_with_todo?: false,
message: "#{cop_name} message",
- location: double(:location, source_line: 'line', first_line: 1, last_line: 2),
- highlighted_area: double(:highlighted_area, begin_pos: 1, size: 2)
+ location: double(:location, source_line: 'line', first_line: 1, last_line: 1, single_line?: true),
+ highlighted_area: double(:highlighted_area, begin_pos: 1, size: 2, source_buffer: 'line', source: 'i')
)
# rubocop:enable RSpec/VerifiedDoubles
end
diff --git a/spec/rubocop/formatter/todo_formatter_spec.rb b/spec/rubocop/formatter/todo_formatter_spec.rb
index edd84632409..5494d518605 100644
--- a/spec/rubocop/formatter/todo_formatter_spec.rb
+++ b/spec/rubocop/formatter/todo_formatter_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
expect(todo_yml('B/AutoCorrect')).to eq(<<~YAML)
---
- # Cop supports --auto-correct.
+ # Cop supports --autocorrect.
B/AutoCorrect:
Exclude:
- 'd.rb'
@@ -309,18 +309,78 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
context 'without offenses detected' do
before do
+ todo_dir.write('A/Cop', yaml) if yaml
+ todo_dir.inspect_all
+
formatter.started(%w[a.rb b.rb])
formatter.file_finished('a.rb', [])
formatter.file_finished('b.rb', [])
formatter.finished(%w[a.rb b.rb])
+
+ todo_dir.delete_inspected
end
- it 'does not output anything' do
- expect(stdout.string).to eq('')
+ context 'without existing TODOs' do
+ let(:yaml) { nil }
+
+ it 'does not output anything' do
+ expect(stdout.string).to eq('')
+ end
+
+ it 'does not write any YAML files' do
+ expect(rubocop_todo_dir_listing).to be_empty
+ end
end
- it 'does not write any YAML files' do
- expect(rubocop_todo_dir_listing).to be_empty
+ context 'with existing TODOs' do
+ context 'when existing offenses only' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ A/Cop:
+ Exclude:
+ - x.rb
+ YAML
+ end
+
+ it 'does not output anything' do
+ expect(stdout.string).to eq('')
+ end
+
+ it 'does not write any YAML files' do
+ expect(rubocop_todo_dir_listing).to be_empty
+ end
+ end
+
+ context 'when in grace period' do
+ let(:yaml) do
+ <<~YAML
+ ---
+ A/Cop:
+ Details: grace period
+ Exclude:
+ - x.rb
+ YAML
+ end
+
+ it 'outputs its actions' do
+ expect(stdout.string).to eq(<<~OUTPUT)
+ Written to .rubocop_todo/a/cop.yml
+ OUTPUT
+ end
+
+ it 'creates YAML file with Details only', :aggregate_failures do
+ expect(rubocop_todo_dir_listing).to contain_exactly(
+ 'a/cop.yml'
+ )
+
+ expect(todo_yml('A/Cop')).to eq(<<~YAML)
+ ---
+ A/Cop:
+ Details: grace period
+ YAML
+ end
+ end
end
end
diff --git a/spec/rubocop_spec_helper.rb b/spec/rubocop_spec_helper.rb
index a37415a25de..cf747132ec1 100644
--- a/spec/rubocop_spec_helper.rb
+++ b/spec/rubocop_spec_helper.rb
@@ -8,13 +8,23 @@ require 'fast_spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
-RSpec.configure do |config|
- config.include RuboCop::RSpec::ExpectOffense, type: :rubocop
+require_relative './support/shared_contexts/rubocop_default_rspec_language_config_context'
+RSpec.configure do |config|
config.define_derived_metadata(file_path: %r{spec/rubocop}) do |metadata|
- metadata[:type] = :rubocop
+ # TODO: move DuplicateSpecLocation cop to RSpec::DuplicateSpecLocation
+ unless metadata[:type] == :rubocop_rspec
+ metadata[:type] = :rubocop
+ end
end
- # Include config shared context for all cop specs.
+ config.define_derived_metadata(file_path: %r{spec/rubocop/cop/rspec}) do |metadata|
+ metadata[:type] = :rubocop_rspec
+ end
+
+ config.include RuboCop::RSpec::ExpectOffense, type: :rubocop
+ config.include RuboCop::RSpec::ExpectOffense, type: :rubocop_rspec
+
config.include_context 'config', type: :rubocop
+ config.include_context 'with default RSpec/Language config', type: :rubocop_rspec
end
diff --git a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
index f96936c0a6f..c97226c1a2d 100644
--- a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
+++ b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
@@ -2,8 +2,8 @@
require 'fast_spec_helper'
require_relative '../../../../scripts/lib/glfm/update_example_snapshots'
-# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/
-# for details on the implementation and usage of the `update_example_snapshots` script being tested.
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-example-snapshotsrb-script
+# for details on the implementation and usage of the `update_example_snapshots.rb` script being tested.
# This developers guide contains diagrams and documentation of the script,
# including explanations and examples of all files it reads and writes.
#
@@ -16,17 +16,18 @@ require_relative '../../../../scripts/lib/glfm/update_example_snapshots'
# which runs a jest test environment. This results in each full run of the script
# taking between 30-60 seconds. The majority of this is spent loading the Rails environment.
#
-# However, only the `writing html.yml and prosemirror_json.yml` context is used
-# to test these slow sub-processes, and it only contains a single example.
+# However, only the `with full processing of static and WYSIWYG HTML` context is used
+# to test these slow sub-processes, and it only contains two examples.
#
# All other tests currently in the file pass the `skip_static_and_wysiwyg: true`
-# flag to `#process`, which skips the slow sub-processes. All of these tests
+# flag to `#process`, which skips the slow sub-processes. All of these other tests
# should run in sub-second time when the Spring pre-loader is used. This allows
# logic which is not directly related to the slow sub-processes to be TDD'd with a
# very rapid feedback cycle.
#
# Also, the textual content of the individual fixture file entries is also crafted to help
# indicate which scenarios which they are covering.
+# rubocop:disable RSpec/MultipleMemoizedHelpers
RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
subject { described_class.new }
@@ -34,9 +35,8 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
let(:glfm_spec_txt_path) { described_class::GLFM_SPEC_TXT_PATH }
let(:glfm_spec_txt_local_io) { StringIO.new(glfm_spec_txt_contents) }
let(:glfm_example_status_yml_path) { described_class::GLFM_EXAMPLE_STATUS_YML_PATH }
- let(:glfm_example_status_yml_io) { StringIO.new(glfm_example_status_yml_contents) }
let(:glfm_example_metadata_yml_path) { described_class::GLFM_EXAMPLE_METADATA_YML_PATH }
- let(:glfm_example_metadata_yml_io) { StringIO.new(glfm_example_metadata_yml_contents) }
+ let(:glfm_example_normalizations_yml_path) { described_class::GLFM_EXAMPLE_NORMALIZATIONS_YML_PATH }
# Example Snapshot (ES) output files
let(:es_examples_index_yml_path) { described_class::ES_EXAMPLES_INDEX_YML_PATH }
@@ -285,10 +285,25 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
YAML
end
+ let(:test1) { '\1\2URI_PREFIX\4' }
+
+ let(:glfm_example_normalizations_yml_contents) do
+ # NOTE: This heredoc identifier must be quoted because we are using control characters in the heredoc body.
+ # See https://stackoverflow.com/a/73831037/25192
+ <<~'YAML'
+ ---
+ # If a config file entry starts with `00_`, it will be skipped for validation that it exists in `examples_index.yml`
+ 00_shared:
+ 00_uri: &00_uri
+ - regex: '(href|data-src)(=")(.*?)(test-file\.(png|zip)")'
+ replacement: '\1\2URI_PREFIX\4'
+ YAML
+ end
+
let(:es_html_yml_io_existing_contents) do
<<~YAML
---
- 00_00_00__obsolete_entry_to_be_deleted__001:
+ 01_00_00__obsolete_entry_to_be_deleted__001:
canonical: |
This entry is no longer exists in the spec.txt, so it will be deleted.
static: |-
@@ -315,7 +330,7 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
let(:es_prosemirror_json_yml_io_existing_contents) do
<<~YAML
---
- 00_00_00__obsolete_entry_to_be_deleted__001: |-
+ 01_00_00__obsolete_entry_to_be_deleted__001: |-
{
"obsolete": "This entry is no longer exists in the spec.txt, and is not skipped, so it will be deleted."
}
@@ -356,9 +371,14 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
# input files
allow(File).to receive(:open).with(glfm_spec_txt_path) { glfm_spec_txt_local_io }
- allow(File).to receive(:open).with(glfm_example_status_yml_path) { glfm_example_status_yml_io }
+ allow(File).to receive(:open).with(glfm_example_status_yml_path) do
+ StringIO.new(glfm_example_status_yml_contents)
+ end
allow(File).to receive(:open).with(glfm_example_metadata_yml_path) do
- glfm_example_metadata_yml_io
+ StringIO.new(glfm_example_metadata_yml_contents)
+ end
+ allow(File).to receive(:open).with(glfm_example_normalizations_yml_path) do
+ StringIO.new(glfm_example_normalizations_yml_contents)
end
# output files
@@ -525,353 +545,404 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
end
end
- # rubocop:disable RSpec/MultipleMemoizedHelpers
- describe 'writing html.yml and prosemirror_json.yml' do
- let(:es_html_yml_contents) { reread_io(es_html_yml_io) }
- let(:es_prosemirror_json_yml_contents) { reread_io(es_prosemirror_json_yml_io) }
+ describe 'error handling when manually-curated input specification config files contain invalid example names:' do
+ let(:err_msg) do
+ /#{config_file}.*01_00_00__invalid__001.*does not have.*entry in.*#{described_class::ES_EXAMPLES_INDEX_YML_PATH}/m
+ end
- # NOTE: This example_status.yml is crafted in conjunction with expected_html_yml_contents
- # to test the behavior of the `skip_update_*` flags
- let(:glfm_example_status_yml_contents) do
+ let(:invalid_example_name_file_contents) do
<<~YAML
---
- 02_01_00__inlines__strong__002:
- # NOTE: 02_01_00__inlines__strong__002: is omitted from the existing prosemirror_json.yml file, and is also
- # skipped here, to show that an example does not need to exist in order to be skipped.
- # TODO: This should be changed to raise an error instead, to enforce that there cannot be orphaned
- # entries in glfm_example_status.yml. This task is captured in
- # https://gitlab.com/gitlab-org/gitlab/-/issues/361241#other-cleanup-tasks
- skip_update_example_snapshot_prosemirror_json: "skipping because JSON isn't cool enough"
- 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
- skip_update_example_snapshot_html_static: "skipping because there's too much static"
- 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
- skip_update_example_snapshot_html_wysiwyg: 'skipping because what you see is NOT what you get'
- skip_update_example_snapshot_prosemirror_json: "skipping because JSON still isn't cool enough"
- 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001:
- skip_update_example_snapshots: 'skipping this example because it is very bad'
- 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
- skip_update_example_snapshots: 'skipping this example because we have manually modified it'
+ 01_00_00__invalid__001:
+ a: 1
YAML
end
- let(:expected_html_yml_contents) do
- <<~YAML
- ---
- 02_01_00__inlines__strong__001:
- canonical: |
- <p><strong>bold</strong></p>
- static: |-
- <p data-sourcepos="1:1-1:8" dir="auto"><strong>bold</strong></p>
- wysiwyg: |-
- <p><strong>bold</strong></p>
- 02_01_00__inlines__strong__002:
- canonical: |
- <p><strong>bold with more text</strong></p>
- static: |-
- <p data-sourcepos="1:1-1:23" dir="auto"><strong>bold with more text</strong></p>
- wysiwyg: |-
- <p><strong>bold with more text</strong></p>
- 02_03_00__inlines__strikethrough_extension__001:
- canonical: |
- <p><del>Hi</del> Hello, world!</p>
- static: |-
- <p data-sourcepos="1:1-1:20" dir="auto"><del>Hi</del> Hello, world!</p>
- wysiwyg: |-
- <p><s>Hi</s> Hello, world!</p>
- 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
- canonical: |
- <p><strong>bold</strong></p>
- wysiwyg: |-
- <p><strong>bold</strong></p>
- 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001:
- canonical: |
- <p>Example in an H3</p>
- static: |-
- <p data-sourcepos="1:1-1:16" dir="auto">Example in an H3</p>
- wysiwyg: |-
- <p>Example in an H3</p>
- 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
- canonical: |
- <p><strong>
- bold
- </strong></p>
- static: |-
- <strong>
- bold
- </strong>
- 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
- canonical: |
- <p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p>
- static: |-
- <p>This is the manually modified static HTML which will be preserved</p>
- wysiwyg: |-
- <p>This is the manually modified WYSIWYG HTML which will be preserved</p>
- 06_01_00__api_request_overrides__group_upload_link__001:
- canonical: |
- <p><a href="groups-test-file">groups-test-file</a></p>
- static: |-
- <p data-sourcepos="1:1-1:45" dir="auto"><a href="/groups/glfm_group/-/uploads/groups-test-file" data-canonical-src="/uploads/groups-test-file" data-link="true" class="gfm">groups-test-file</a></p>
- wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uploads/groups-test-file">groups-test-file</a></p>
- 06_02_00__api_request_overrides__project_repo_link__001:
- canonical: |
- <p><a href="projects-test-file">projects-test-file</a></p>
- static: |-
- <p data-sourcepos="1:1-1:40" dir="auto"><a href="/glfm_group/glfm_project/-/blob/master/projects-test-file">projects-test-file</a></p>
- wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="projects-test-file">projects-test-file</a></p>
- 06_03_00__api_request_overrides__project_snippet_ref__001:
- canonical: |
- <p>This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888">$88888</a>
- static: |-
- <p data-sourcepos="1:1-1:53" dir="auto">This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888" data-reference-type="snippet" data-original="$88888" data-link="false" data-link-reference="false" data-project="77777" data-snippet="88888" data-container="body" data-placement="top" title="glfm_project_snippet" class="gfm gfm-snippet has-tooltip">$88888</a></p>
- wysiwyg: |-
- <p>This project snippet ID reference IS filtered: $88888</p>
- 06_04_00__api_request_overrides__personal_snippet_ref__001:
- canonical: |
- <p>This personal snippet ID reference is NOT filtered: $99999</p>
- static: |-
- <p data-sourcepos="1:1-1:58" dir="auto">This personal snippet ID reference is NOT filtered: $99999</p>
- wysiwyg: |-
- <p>This personal snippet ID reference is NOT filtered: $99999</p>
- 06_05_00__api_request_overrides__project_wiki_link__001:
- canonical: |
- <p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
- static: |-
- <p data-sourcepos="1:1-1:50" dir="auto"><a href="/glfm_group/glfm_project/-/wikis/project-wikis-test-file" data-canonical-src="project-wikis-test-file">project-wikis-test-file</a></p>
- wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="project-wikis-test-file">project-wikis-test-file</a></p>
- YAML
+ context 'for glfm_example_status.yml' do
+ let(:config_file) { described_class::GLFM_EXAMPLE_STATUS_YML_PATH }
+ let(:glfm_example_status_yml_contents) { invalid_example_name_file_contents }
+
+ it 'raises error' do
+ expect { subject.process(skip_static_and_wysiwyg: true) }.to raise_error(err_msg)
+ end
end
- let(:expected_prosemirror_json_contents) do
- <<~YAML
- ---
- 02_01_00__inlines__strong__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "bold"
- }
- ],
- "text": "bold"
- }
- ]
- }
- ]
- }
- 02_03_00__inlines__strikethrough_extension__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "strike"
- }
- ],
- "text": "Hi"
- },
- {
- "type": "text",
- "text": " Hello, world!"
- }
- ]
- }
- ]
- }
- 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "bold"
- }
- ],
- "text": "bold"
- }
- ]
- }
- ]
- }
- 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "text": "Example in an H3"
- }
- ]
- }
- ]
- }
- 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |-
- {
- "existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy"
- }
- 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |-
- {
- "existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy"
- }
- 06_01_00__api_request_overrides__group_upload_link__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "link",
- "attrs": {
- "href": "/uploads/groups-test-file",
- "target": "_blank",
- "class": null,
- "title": null,
- "canonicalSrc": "/uploads/groups-test-file",
- "isReference": false
- }
- }
- ],
- "text": "groups-test-file"
- }
- ]
- }
- ]
- }
- 06_02_00__api_request_overrides__project_repo_link__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "link",
- "attrs": {
- "href": "projects-test-file",
- "target": "_blank",
- "class": null,
- "title": null,
- "canonicalSrc": "projects-test-file",
- "isReference": false
- }
- }
- ],
- "text": "projects-test-file"
- }
- ]
- }
- ]
- }
- 06_03_00__api_request_overrides__project_snippet_ref__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "text": "This project snippet ID reference IS filtered: $88888"
- }
- ]
- }
- ]
- }
- 06_04_00__api_request_overrides__personal_snippet_ref__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "text": "This personal snippet ID reference is NOT filtered: $99999"
- }
- ]
- }
- ]
- }
- 06_05_00__api_request_overrides__project_wiki_link__001: |-
- {
- "type": "doc",
- "content": [
- {
- "type": "paragraph",
- "content": [
- {
- "type": "text",
- "marks": [
- {
- "type": "link",
- "attrs": {
- "href": "project-wikis-test-file",
- "target": "_blank",
- "class": null,
- "title": null,
- "canonicalSrc": "project-wikis-test-file",
- "isReference": false
- }
- }
- ],
- "text": "project-wikis-test-file"
- }
- ]
- }
- ]
- }
- YAML
+ context 'for glfm_example_metadata.yml' do
+ let(:config_file) { described_class::GLFM_EXAMPLE_METADATA_YML_PATH }
+ let(:glfm_example_metadata_yml_contents) { invalid_example_name_file_contents }
+
+ it 'raises error' do
+ expect { subject.process(skip_static_and_wysiwyg: true) }.to raise_error(err_msg)
+ end
end
- before do
- # NOTE: This is a necessary to avoid an `error Couldn't find an integrity file` error
- # when invoking `yarn jest ...` on CI from within an RSpec job. It could be solved by
- # adding `.yarn-install` to be included in the RSpec CI job, but that would be a performance
- # hit to all RSpec jobs. We could also make a dedicate job just for this spec. However,
- # since this is just a single script, those options may not be justified.
- described_class.new.run_external_cmd('yarn install') if ENV['CI']
+ context 'for glfm_example_normalizations.yml' do
+ let(:config_file) { described_class::GLFM_EXAMPLE_NORMALIZATIONS_YML_PATH }
+ let(:glfm_example_normalizations_yml_contents) { invalid_example_name_file_contents }
+
+ it 'raises error' do
+ expect { subject.process(skip_static_and_wysiwyg: true) }.to raise_error(err_msg)
+ end
end
+ end
+
+ context 'with full processing of static and WYSIWYG HTML' do
+ before(:all) do
+ # NOTE: It is a necessary to do a `yarn install` in order to ensure that
+ # `scripts/lib/glfm/render_wysiwyg_html_and_json.js` can be invoked successfully
+ # on the CI job (which will not be set up for frontend specs since this is
+ # an RSpec spec), or if the current yarn dependencies are not installed locally.
+ described_class.new.run_external_cmd('yarn install --frozen-lockfile')
+ end
+
+ describe 'manually-curated input specification config files' do
+ let(:glfm_example_status_yml_contents) { '' }
+ let(:glfm_example_metadata_yml_contents) { '' }
+ let(:glfm_example_normalizations_yml_contents) { '' }
+
+ it 'can be empty' do
+ expect { subject.process }.not_to raise_error
+ end
+ end
+
+ describe 'writing html.yml and prosemirror_json.yml' do
+ let(:es_html_yml_contents) { reread_io(es_html_yml_io) }
+ let(:es_prosemirror_json_yml_contents) { reread_io(es_prosemirror_json_yml_io) }
+
+ # NOTE: This example_status.yml is crafted in conjunction with expected_html_yml_contents
+ # to test the behavior of the `skip_update_*` flags
+ let(:glfm_example_status_yml_contents) do
+ <<~YAML
+ ---
+ 02_01_00__inlines__strong__002:
+ # NOTE: 02_01_00__inlines__strong__002: is omitted from the existing prosemirror_json.yml file, and is also
+ # skipped here, to show that an example does not need to exist in order to be skipped.
+ # TODO: This should be changed to raise an error instead, to enforce that there cannot be orphaned
+ # entries in glfm_example_status.yml. This task is captured in
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/361241#other-cleanup-tasks
+ skip_update_example_snapshot_prosemirror_json: "skipping because JSON isn't cool enough"
+ 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
+ skip_update_example_snapshot_html_static: "skipping because there's too much static"
+ 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
+ skip_update_example_snapshot_html_wysiwyg: 'skipping because what you see is NOT what you get'
+ skip_update_example_snapshot_prosemirror_json: "skipping because JSON still isn't cool enough"
+ 05_01_00__third_gitlab_specific_section_with_skipped_examples__strong_but_skipped__001:
+ skip_update_example_snapshots: 'skipping this example because it is very bad'
+ 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
+ skip_update_example_snapshots: 'skipping this example because we have manually modified it'
+ YAML
+ end
+
+ let(:expected_html_yml_contents) do
+ <<~YAML
+ ---
+ 02_01_00__inlines__strong__001:
+ canonical: |
+ <p><strong>bold</strong></p>
+ static: |-
+ <p data-sourcepos="1:1-1:8" dir="auto"><strong>bold</strong></p>
+ wysiwyg: |-
+ <p><strong>bold</strong></p>
+ 02_01_00__inlines__strong__002:
+ canonical: |
+ <p><strong>bold with more text</strong></p>
+ static: |-
+ <p data-sourcepos="1:1-1:23" dir="auto"><strong>bold with more text</strong></p>
+ wysiwyg: |-
+ <p><strong>bold with more text</strong></p>
+ 02_03_00__inlines__strikethrough_extension__001:
+ canonical: |
+ <p><del>Hi</del> Hello, world!</p>
+ static: |-
+ <p data-sourcepos="1:1-1:20" dir="auto"><del>Hi</del> Hello, world!</p>
+ wysiwyg: |-
+ <p><s>Hi</s> Hello, world!</p>
+ 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001:
+ canonical: |
+ <p><strong>bold</strong></p>
+ wysiwyg: |-
+ <p><strong>bold</strong></p>
+ 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001:
+ canonical: |
+ <p>Example in an H3</p>
+ static: |-
+ <p data-sourcepos="1:1-1:16" dir="auto">Example in an H3</p>
+ wysiwyg: |-
+ <p>Example in an H3</p>
+ 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001:
+ canonical: |
+ <p><strong>
+ bold
+ </strong></p>
+ static: |-
+ <strong>
+ bold
+ </strong>
+ 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001:
+ canonical: |
+ <p><strong>This example will have its manually modified static HTML, WYSIWYG HTML, and ProseMirror JSON preserved</strong></p>
+ static: |-
+ <p>This is the manually modified static HTML which will be preserved</p>
+ wysiwyg: |-
+ <p>This is the manually modified WYSIWYG HTML which will be preserved</p>
+ 06_01_00__api_request_overrides__group_upload_link__001:
+ canonical: |
+ <p><a href="groups-test-file">groups-test-file</a></p>
+ static: |-
+ <p data-sourcepos="1:1-1:45" dir="auto"><a href="/groups/glfm_group/-/uploads/groups-test-file" data-canonical-src="/uploads/groups-test-file" data-link="true" class="gfm">groups-test-file</a></p>
+ wysiwyg: |-
+ <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uploads/groups-test-file">groups-test-file</a></p>
+ 06_02_00__api_request_overrides__project_repo_link__001:
+ canonical: |
+ <p><a href="projects-test-file">projects-test-file</a></p>
+ static: |-
+ <p data-sourcepos="1:1-1:40" dir="auto"><a href="/glfm_group/glfm_project/-/blob/master/projects-test-file">projects-test-file</a></p>
+ wysiwyg: |-
+ <p><a target="_blank" rel="noopener noreferrer nofollow" href="projects-test-file">projects-test-file</a></p>
+ 06_03_00__api_request_overrides__project_snippet_ref__001:
+ canonical: |
+ <p>This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888">$88888</a>
+ static: |-
+ <p data-sourcepos="1:1-1:53" dir="auto">This project snippet ID reference IS filtered: <a href="/glfm_group/glfm_project/-/snippets/88888" data-reference-type="snippet" data-original="$88888" data-link="false" data-link-reference="false" data-project="77777" data-snippet="88888" data-container="body" data-placement="top" title="glfm_project_snippet" class="gfm gfm-snippet has-tooltip">$88888</a></p>
+ wysiwyg: |-
+ <p>This project snippet ID reference IS filtered: $88888</p>
+ 06_04_00__api_request_overrides__personal_snippet_ref__001:
+ canonical: |
+ <p>This personal snippet ID reference is NOT filtered: $99999</p>
+ static: |-
+ <p data-sourcepos="1:1-1:58" dir="auto">This personal snippet ID reference is NOT filtered: $99999</p>
+ wysiwyg: |-
+ <p>This personal snippet ID reference is NOT filtered: $99999</p>
+ 06_05_00__api_request_overrides__project_wiki_link__001:
+ canonical: |
+ <p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
+ static: |-
+ <p data-sourcepos="1:1-1:50" dir="auto"><a href="/glfm_group/glfm_project/-/wikis/project-wikis-test-file" data-canonical-src="project-wikis-test-file">project-wikis-test-file</a></p>
+ wysiwyg: |-
+ <p><a target="_blank" rel="noopener noreferrer nofollow" href="project-wikis-test-file">project-wikis-test-file</a></p>
+ YAML
+ end
+
+ let(:expected_prosemirror_json_contents) do
+ <<~YAML
+ ---
+ 02_01_00__inlines__strong__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "bold"
+ }
+ ],
+ "text": "bold"
+ }
+ ]
+ }
+ ]
+ }
+ 02_03_00__inlines__strikethrough_extension__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "strike"
+ }
+ ],
+ "text": "Hi"
+ },
+ {
+ "type": "text",
+ "text": " Hello, world!"
+ }
+ ]
+ }
+ ]
+ }
+ 03_01_00__first_gitlab_specific_section_with_examples__strong_but_with_two_asterisks__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "bold"
+ }
+ ],
+ "text": "bold"
+ }
+ ]
+ }
+ ]
+ }
+ 03_02_01__first_gitlab_specific_section_with_examples__h2_which_contains_an_h3__example_in_an_h3__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "Example in an H3"
+ }
+ ]
+ }
+ ]
+ }
+ 04_01_00__second_gitlab_specific_section_with_examples__strong_but_with_html__001: |-
+ {
+ "existing": "This entry is manually modified and preserved because skip_update_example_snapshot_prosemirror_json will be truthy"
+ }
+ 05_02_00__third_gitlab_specific_section_with_skipped_examples__strong_but_manually_modified_and_skipped__001: |-
+ {
+ "existing": "This entry is manually modified and preserved because skip_update_example_snapshots will be truthy"
+ }
+ 06_01_00__api_request_overrides__group_upload_link__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "link",
+ "attrs": {
+ "href": "/uploads/groups-test-file",
+ "target": "_blank",
+ "class": null,
+ "title": null,
+ "canonicalSrc": "/uploads/groups-test-file",
+ "isReference": false
+ }
+ }
+ ],
+ "text": "groups-test-file"
+ }
+ ]
+ }
+ ]
+ }
+ 06_02_00__api_request_overrides__project_repo_link__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "link",
+ "attrs": {
+ "href": "projects-test-file",
+ "target": "_blank",
+ "class": null,
+ "title": null,
+ "canonicalSrc": "projects-test-file",
+ "isReference": false
+ }
+ }
+ ],
+ "text": "projects-test-file"
+ }
+ ]
+ }
+ ]
+ }
+ 06_03_00__api_request_overrides__project_snippet_ref__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "This project snippet ID reference IS filtered: $88888"
+ }
+ ]
+ }
+ ]
+ }
+ 06_04_00__api_request_overrides__personal_snippet_ref__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "This personal snippet ID reference is NOT filtered: $99999"
+ }
+ ]
+ }
+ ]
+ }
+ 06_05_00__api_request_overrides__project_wiki_link__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "marks": [
+ {
+ "type": "link",
+ "attrs": {
+ "href": "project-wikis-test-file",
+ "target": "_blank",
+ "class": null,
+ "title": null,
+ "canonicalSrc": "project-wikis-test-file",
+ "isReference": false
+ }
+ }
+ ],
+ "text": "project-wikis-test-file"
+ }
+ ]
+ }
+ ]
+ }
+ YAML
+ end
- # NOTE: Both `html.yml` and `prosemirror_json.yml` generation are tested in a single example, to
- # avoid slower tests, because generating the static HTML is slow due to the need to invoke
- # the rails environment. We could have separate sections, but this would require an extra flag
- # to the `process` method to independently skip static vs. WYSIWYG, which is not worth the effort.
- it 'writes the correct content', :unlimited_max_formatted_output_length do
- # expectation that skipping message is only output once per example
- expect(subject).to receive(:output).once.with(/reason.*skipping this example because it is very bad/i)
+ # NOTE: Both `html.yml` and `prosemirror_json.yml` generation are tested in a single example, to
+ # avoid slower tests, because generating the static HTML is slow due to the need to invoke
+ # the rails environment. We could have separate sections, but this would require an extra flag
+ # to the `process` method to independently skip static vs. WYSIWYG, which is not worth the effort.
+ it 'writes the correct content', :unlimited_max_formatted_output_length do
+ # expectation that skipping message is only output once per example
+ expect(subject).to receive(:output).once.with(/reason.*skipping this example because it is very bad/i)
- subject.process
+ subject.process
- expect(es_html_yml_contents).to eq(expected_html_yml_contents)
- expect(es_prosemirror_json_yml_contents).to eq(expected_prosemirror_json_contents)
+ expect(es_html_yml_contents).to eq(expected_html_yml_contents)
+ expect(es_prosemirror_json_yml_contents).to eq(expected_prosemirror_json_contents)
+ end
end
end
# rubocop:enable RSpec/MultipleMemoizedHelpers
diff --git a/spec/scripts/lib/glfm/update_specification_spec.rb b/spec/scripts/lib/glfm/update_specification_spec.rb
index 9fb671e0016..852b2b580e6 100644
--- a/spec/scripts/lib/glfm/update_specification_spec.rb
+++ b/spec/scripts/lib/glfm/update_specification_spec.rb
@@ -1,21 +1,53 @@
# frozen_string_literal: true
+
require 'fast_spec_helper'
require_relative '../../../../scripts/lib/glfm/update_specification'
-
+require_relative '../../../support/helpers/next_instance_of'
+
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-specificationrb-script
+# for details on the implementation and usage of the `update_specification.rb` script being tested.
+# This developers guide contains diagrams and documentation of the script,
+# including explanations and examples of all files it reads and writes.
+#
+# Note that this test is not structured in a traditional way, with multiple examples
+# to cover all different scenarios. Instead, the content of the stubbed test fixture
+# files are crafted to cover multiple scenarios with in a single example run.
+#
+# This is because the invocation of the full script is slow, because it executes
+# a subshell for processing, which runs a full Rails environment.
+# This results in each full run of the script taking between 30-60 seconds.
+# The majority of this is spent loading the Rails environment.
+#
+# However, only the `with generation of spec.html` context is used
+# to test this slow sub-process, and it only contains one example.
+#
+# All other tests currently in the file pass the `skip_spec_html_generation: true`
+# flag to `#process`, which skips the slow sub-process. All of these other tests
+# should run in sub-second time when the Spring pre-loader is used. This allows
+# logic which is not directly related to the slow sub-processes to be TDD'd with a
+# very rapid feedback cycle.
RSpec.describe Glfm::UpdateSpecification, '#process' do
+ include NextInstanceOf
+
subject { described_class.new }
let(:ghfm_spec_txt_uri) { described_class::GHFM_SPEC_TXT_URI }
+ let(:ghfm_spec_txt_uri_parsed) { instance_double(URI::HTTPS, :ghfm_spec_txt_uri_parsed) }
let(:ghfm_spec_txt_uri_io) { StringIO.new(ghfm_spec_txt_contents) }
- let(:ghfm_spec_txt_path) { described_class::GHFM_SPEC_TXT_PATH }
+ let(:ghfm_spec_md_path) { described_class::GHFM_SPEC_MD_PATH }
let(:ghfm_spec_txt_local_io) { StringIO.new(ghfm_spec_txt_contents) }
- let(:glfm_intro_txt_path) { described_class::GLFM_INTRO_TXT_PATH }
- let(:glfm_intro_txt_io) { StringIO.new(glfm_intro_txt_contents) }
- let(:glfm_examples_txt_path) { described_class::GLFM_EXAMPLES_TXT_PATH }
- let(:glfm_examples_txt_io) { StringIO.new(glfm_examples_txt_contents) }
+ let(:glfm_intro_md_path) { described_class::GLFM_INTRO_MD_PATH }
+ let(:glfm_intro_md_io) { StringIO.new(glfm_intro_md_contents) }
+ let(:glfm_official_specification_examples_md_path) { described_class::GLFM_OFFICIAL_SPECIFICATION_EXAMPLES_MD_PATH }
+ let(:glfm_official_specification_examples_md_io) { StringIO.new(glfm_official_specification_examples_md_contents) }
+ let(:glfm_internal_extension_examples_md_path) { described_class::GLFM_INTERNAL_EXTENSION_EXAMPLES_MD_PATH }
+ let(:glfm_internal_extension_examples_md_io) { StringIO.new(glfm_internal_extension_examples_md_contents) }
let(:glfm_spec_txt_path) { described_class::GLFM_SPEC_TXT_PATH }
let(:glfm_spec_txt_io) { StringIO.new }
+ let(:glfm_spec_html_path) { described_class::GLFM_SPEC_HTML_PATH }
+ let(:glfm_spec_html_io) { StringIO.new }
+ let(:markdown_tempfile_io) { StringIO.new }
let(:ghfm_spec_txt_contents) do
<<~MARKDOWN
@@ -52,7 +84,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
MARKDOWN
end
- let(:glfm_intro_txt_contents) do
+ let(:glfm_intro_md_contents) do
# language=Markdown
<<~MARKDOWN
# Introduction
@@ -63,9 +95,17 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
MARKDOWN
end
- let(:glfm_examples_txt_contents) do
+ let(:glfm_official_specification_examples_md_contents) do
<<~MARKDOWN
- # GitLab-Specific Section with Examples
+ # Official Specification Section with Examples
+
+ Some examples.
+ MARKDOWN
+ end
+
+ let(:glfm_internal_extension_examples_md_contents) do
+ <<~MARKDOWN
+ # Internal Extension Section with Examples
Some examples.
MARKDOWN
@@ -73,44 +113,66 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
before do
# Mock default ENV var values
- allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_TXT').and_return(nil)
+ allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_MD').and_return(nil)
allow(ENV).to receive(:[]).and_call_original
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
# objects. This gives better and more realistic coverage, while still avoiding
# actual network and filesystem I/O during the spec run.
- allow(URI).to receive(:open).with(ghfm_spec_txt_uri) { ghfm_spec_txt_uri_io }
- allow(File).to receive(:open).with(ghfm_spec_txt_path) { ghfm_spec_txt_local_io }
- allow(File).to receive(:open).with(glfm_intro_txt_path) { glfm_intro_txt_io }
- allow(File).to receive(:open).with(glfm_examples_txt_path) { glfm_examples_txt_io }
+
+ # input files
+ allow(URI).to receive(:parse).with(ghfm_spec_txt_uri).and_return(ghfm_spec_txt_uri_parsed)
+ allow(ghfm_spec_txt_uri_parsed).to receive(:open).and_return(ghfm_spec_txt_uri_io)
+ allow(File).to receive(:open).with(ghfm_spec_md_path) { ghfm_spec_txt_local_io }
+ allow(File).to receive(:open).with(glfm_intro_md_path) { glfm_intro_md_io }
+ allow(File).to receive(:open).with(glfm_official_specification_examples_md_path) do
+ glfm_official_specification_examples_md_io
+ end
+ allow(File).to receive(:open).with(glfm_internal_extension_examples_md_path) do
+ glfm_internal_extension_examples_md_io
+ end
+
+ # output files
allow(File).to receive(:open).with(glfm_spec_txt_path, 'w') { glfm_spec_txt_io }
+ allow(File).to receive(:open).with(glfm_spec_html_path, 'w') { glfm_spec_html_io }
+
+ # Allow normal opening of Tempfile files created during script execution.
+ tempfile_basenames = [
+ described_class::MARKDOWN_TEMPFILE_BASENAME[0],
+ described_class::STATIC_HTML_TEMPFILE_BASENAME[0]
+ ].join('|')
+ # NOTE: This approach with a single regex seems to be the only way this can work. If you
+ # attempt to have multiple `allow...and_call_original` with `any_args`, the mocked
+ # parameter matching will fail to match the second one.
+ tempfiles_regex = /(#{tempfile_basenames})/
+ allow(File).to receive(:open).with(tempfiles_regex, any_args).and_call_original
# Prevent console output when running tests
allow(subject).to receive(:output)
end
describe 'retrieving latest GHFM spec.txt' do
- context 'when UPDATE_GHFM_SPEC_TXT is not true (default)' do
+ context 'when UPDATE_GHFM_SPEC_MD is not true (default)' do
it 'does not download' do
- expect(URI).not_to receive(:open).with(ghfm_spec_txt_uri)
+ expect(URI).not_to receive(:parse).with(ghfm_spec_txt_uri)
- subject.process
+ subject.process(skip_spec_html_generation: true)
expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
end
end
- context 'when UPDATE_GHFM_SPEC_TXT is true' do
+ context 'when UPDATE_GHFM_SPEC_MD is true' do
let(:ghfm_spec_txt_local_io) { StringIO.new }
before do
- allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_TXT').and_return('true')
- allow(File).to receive(:open).with(ghfm_spec_txt_path, 'w') { ghfm_spec_txt_local_io }
+ allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_MD').and_return('true')
+ allow(File).to receive(:open).with(ghfm_spec_md_path, 'w') { ghfm_spec_txt_local_io }
end
context 'with success' do
it 'downloads and saves' do
- subject.process
+ subject.process(skip_spec_html_generation: true)
expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
end
@@ -128,7 +190,9 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
it 'raises an error' do
- expect { subject.process }.to raise_error /version mismatch.*expected.*29.*got.*30/i
+ expect do
+ subject.process(skip_spec_html_generation: true)
+ end.to raise_error /version mismatch.*expected.*29.*got.*30/i
end
end
@@ -136,7 +200,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
let(:ghfm_spec_txt_contents) { '' }
it 'raises an error if lines cannot be read' do
- expect { subject.process }.to raise_error /unable to read lines/i
+ expect { subject.process(skip_spec_html_generation: true) }.to raise_error /unable to read lines/i
end
end
@@ -146,7 +210,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
it 'raises an error if file is blank' do
- expect { subject.process }.to raise_error /unable to read string/i
+ expect { subject.process(skip_spec_html_generation: true) }.to raise_error /unable to read string/i
end
end
end
@@ -157,7 +221,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
let(:glfm_contents) { reread_io(glfm_spec_txt_io) }
before do
- subject.process
+ subject.process(skip_spec_html_generation: true)
end
it 'replaces the header text with the GitLab version' do
@@ -170,14 +234,18 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
it 'replaces the intro section with the GitLab version' do
expect(glfm_contents).not_to match(/What is GitHub Flavored Markdown/m)
- expect(glfm_contents).to match(/#{Regexp.escape(glfm_intro_txt_contents)}/m)
+ expect(glfm_contents).to match(/#{Regexp.escape(glfm_intro_md_contents)}/m)
end
- it 'inserts the GitLab examples sections before the appendix section' do
+ it 'inserts the GitLab official spec and internal extension examples sections before the appendix section' do
expected = <<~MARKDOWN
End of last GitHub examples section.
- # GitLab-Specific Section with Examples
+ # Official Specification Section with Examples
+
+ Some examples.
+
+ # Internal Extension Section with Examples
Some examples.
@@ -189,6 +257,51 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
end
+ describe 'writing GLFM spec.html' do
+ let(:glfm_contents) { reread_io(glfm_spec_html_io) }
+
+ before do
+ subject.process
+ end
+
+ it 'renders HTML from spec.txt', :unlimited_max_formatted_output_length do
+ expected = <<~HTML
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-4: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">GitLab Flavored Markdown (GLFM) Spec</span></span>
+ <span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+ <h1 data-sourcepos="6:1-6:14" dir="auto">
+ <a id="user-content-introduction" class="anchor" href="#introduction" aria-hidden="true"></a>Introduction</h1>
+ <h2 data-sourcepos="8:1-8:36" dir="auto">
+ <a id="user-content-what-is-gitlab-flavored-markdown" class="anchor" href="#what-is-gitlab-flavored-markdown" aria-hidden="true"></a>What is GitLab Flavored Markdown?</h2>
+ <p data-sourcepos="10:1-10:42" dir="auto">Intro text about GitLab Flavored Markdown.</p>
+ <h1 data-sourcepos="12:1-12:23" dir="auto">
+ <a id="user-content-section-with-examples" class="anchor" href="#section-with-examples" aria-hidden="true"></a>Section with Examples</h1>
+ <h2 data-sourcepos="14:1-14:9" dir="auto">
+ <a id="user-content-strong" class="anchor" href="#strong" aria-hidden="true"></a>Strong</h2>
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="16:1-20:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__bold__</span>
+ <span id="LC2" class="line" lang="plaintext">.</span>
+ <span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;bold&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
+ <copy-code></copy-code>
+ </div>
+ <p data-sourcepos="22:1-22:36" dir="auto">End of last GitHub examples section.</p>
+ <h1 data-sourcepos="24:1-24:46" dir="auto">
+ <a id="user-content-official-specification-section-with-examples" class="anchor" href="#official-specification-section-with-examples" aria-hidden="true"></a>Official Specification Section with Examples</h1>
+ <p data-sourcepos="26:1-26:14" dir="auto">Some examples.</p>
+ <h1 data-sourcepos="28:1-28:42" dir="auto">
+ <a id="user-content-internal-extension-section-with-examples" class="anchor" href="#internal-extension-section-with-examples" aria-hidden="true"></a>Internal Extension Section with Examples</h1>
+ <p data-sourcepos="30:1-30:14" dir="auto">Some examples.</p>
+
+ <h1 data-sourcepos="34:1-34:10" dir="auto">
+ <a id="user-content-appendix" class="anchor" href="#appendix" aria-hidden="true"></a>Appendix</h1>
+ <p data-sourcepos="36:1-36:14" dir="auto">Appendix text.</p>
+ HTML
+ expect(glfm_contents).to be == expected
+ end
+ end
+
def reread_io(io)
# Reset the io StringIO to the beginning position of the buffer
io.seek(0)
diff --git a/spec/scripts/lib/glfm/verify_all_generated_files_are_up_to_date_spec.rb b/spec/scripts/lib/glfm/verify_all_generated_files_are_up_to_date_spec.rb
new file mode 100644
index 00000000000..fca037c9ff3
--- /dev/null
+++ b/spec/scripts/lib/glfm/verify_all_generated_files_are_up_to_date_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+require 'fast_spec_helper'
+require_relative '../../../../scripts/lib/glfm/verify_all_generated_files_are_up_to_date'
+
+# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#verify-all-generated-files-are-up-to-daterb-script
+# for details on the implementation and usage of the `verify_all_generated_files_are_up_to_date.rb` script being tested.
+# This developers guide contains diagrams and documentation of the script,
+# including explanations and examples of all files it reads and writes.
+RSpec.describe Glfm::VerifyAllGeneratedFilesAreUpToDate, '#process' do
+ subject { described_class.new }
+
+ let(:output_path) { described_class::GLFM_SPEC_OUTPUT_PATH }
+ let(:snapshots_path) { described_class::EXAMPLE_SNAPSHOTS_PATH }
+ let(:verify_cmd) { "git status --porcelain #{output_path} #{snapshots_path}" }
+
+ before do
+ # Prevent console output when running tests
+ allow(subject).to receive(:output)
+ end
+
+ context 'when repo is dirty' do
+ before do
+ # Simulate a dirty repo
+ allow(subject).to receive(:run_external_cmd).with(verify_cmd).and_return(" M #{output_path}")
+ end
+
+ it 'raises an error', :unlimited_max_formatted_output_length do
+ expect { subject.process }.to raise_error(/Cannot run.*uncommitted changes.*#{output_path}/m)
+ end
+ end
+
+ context 'when repo is clean' do
+ before do
+ # Mock out all yarn install and script execution
+ allow(subject).to receive(:run_external_cmd).with('yarn install --frozen-lockfile')
+ allow(subject).to receive(:run_external_cmd).with(/update-specification.rb/)
+ allow(subject).to receive(:run_external_cmd).with(/update-example-snapshots.rb/)
+ end
+
+ context 'when all generated files are up to date' do
+ before do
+ # Simulate a clean repo, then simulate no changes to generated files
+ allow(subject).to receive(:run_external_cmd).twice.with(verify_cmd).and_return('', '')
+ end
+
+ it 'does not raise an error', :unlimited_max_formatted_output_length do
+ expect { subject.process }.not_to raise_error
+ end
+ end
+
+ context 'when generated file(s) are not up to date' do
+ before do
+ # Simulate a clean repo, then simulate changes to generated files
+ allow(subject).to receive(:run_external_cmd).twice.with(verify_cmd).and_return('', "M #{snapshots_path}")
+ end
+
+ it 'raises an error', :unlimited_max_formatted_output_length do
+ expect { subject.process }.to raise_error(/following files were modified.*#{snapshots_path}/m)
+ end
+ end
+ end
+end
diff --git a/spec/scripts/trigger-build_spec.rb b/spec/scripts/trigger-build_spec.rb
index 46023d5823d..ac8e3c7797c 100644
--- a/spec/scripts/trigger-build_spec.rb
+++ b/spec/scripts/trigger-build_spec.rb
@@ -21,8 +21,6 @@ RSpec.describe Trigger do
'GITLAB_USER_NAME' => 'gitlab_user_name',
'GITLAB_USER_LOGIN' => 'gitlab_user_login',
'QA_IMAGE' => 'qa_image',
- 'OMNIBUS_GITLAB_CACHE_UPDATE' => 'omnibus_gitlab_cache_update',
- 'OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN' => nil,
'DOCS_PROJECT_API_TOKEN' => nil
}
end
diff --git a/spec/serializers/board_serializer_spec.rb b/spec/serializers/board_serializer_spec.rb
deleted file mode 100644
index 9e6d5a93d53..00000000000
--- a/spec/serializers/board_serializer_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BoardSerializer do
- let(:resource) { create(:board) }
- let(:json_entity) do
- described_class.new
- .represent(resource, serializer: serializer)
- .with_indifferent_access
- end
-
- context 'serialization' do
- let(:serializer) { 'board' }
-
- it 'matches issue_sidebar json schema' do
- expect(json_entity).to match_schema('board')
- end
- end
-end
diff --git a/spec/serializers/board_simple_entity_spec.rb b/spec/serializers/board_simple_entity_spec.rb
deleted file mode 100644
index c5ab9833adf..00000000000
--- a/spec/serializers/board_simple_entity_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BoardSimpleEntity do
- let_it_be(:project) { create(:project) }
- let_it_be(:board) { create(:board, project: project) }
-
- subject { described_class.new(board).as_json }
-
- describe '#name' do
- it 'has `name` attribute' do
- is_expected.to include(:name)
- end
- end
-end
diff --git a/spec/serializers/build_trace_entity_spec.rb b/spec/serializers/build_trace_entity_spec.rb
index 82bd56caaac..f3d1d0a21a8 100644
--- a/spec/serializers/build_trace_entity_spec.rb
+++ b/spec/serializers/build_trace_entity_spec.rb
@@ -38,8 +38,9 @@ RSpec.describe BuildTraceEntity do
end
it 'includes the trace content in json' do
- expect(subject[:lines]).to eq([
- { offset: 0, content: [{ text: 'the-trace' }] }
- ])
+ expect(subject[:lines]).to eq(
+ [
+ { offset: 0, content: [{ text: 'the-trace' }] }
+ ])
end
end
diff --git a/spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb b/spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb
index ddeeb367afe..6fe1376b890 100644
--- a/spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb
+++ b/spec/serializers/ci/daily_build_group_report_result_serializer_spec.rb
@@ -18,22 +18,23 @@ RSpec.describe Ci::DailyBuildGroupReportResultSerializer do
let(:json) { Gitlab::Json.parse(serializer.to_json) }
it 'returns an array of group results' do
- expect(json).to eq([
- {
- 'group_name' => 'rspec',
- 'data' => [
- { 'date' => '2020-05-20', 'coverage' => 79.1 },
- { 'date' => '2020-05-19', 'coverage' => 77.1 }
- ]
- },
- {
- 'group_name' => 'karma',
- 'data' => [
- { 'date' => '2020-05-20', 'coverage' => 90.1 },
- { 'date' => '2020-05-19', 'coverage' => 89.1 }
- ]
- }
- ])
+ expect(json).to eq(
+ [
+ {
+ 'group_name' => 'rspec',
+ 'data' => [
+ { 'date' => '2020-05-20', 'coverage' => 79.1 },
+ { 'date' => '2020-05-19', 'coverage' => 77.1 }
+ ]
+ },
+ {
+ 'group_name' => 'karma',
+ 'data' => [
+ { 'date' => '2020-05-20', 'coverage' => 90.1 },
+ { 'date' => '2020-05-19', 'coverage' => 89.1 }
+ ]
+ }
+ ])
end
end
end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index 433ce344680..0746e68d7c5 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -3,56 +3,47 @@
require 'spec_helper'
RSpec.describe DeploymentEntity do
- let(:user) { developer }
- let(:developer) { create(:user) }
- let(:reporter) { create(:user) }
- let(:project) { create(:project, :repository) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:user) { developer }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:environment) { create(:environment, project: project) }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+ let_it_be_with_reload(:build) { create(:ci_build, :manual, :environment_with_deployment_tier, pipeline: pipeline) }
+
+ let_it_be_with_refind(:deployment) { create(:deployment, deployable: build, environment: environment) }
+
let(:request) { double('request') }
- let(:deployment) { create(:deployment, deployable: build, project: project) }
- let(:build) { create(:ci_build, :manual, :environment_with_deployment_tier, pipeline: pipeline) }
- let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
let(:entity) { described_class.new(deployment, request: request) }
subject { entity.as_json }
- before do
+ before_all do
project.add_developer(developer)
project.add_reporter(reporter)
+ end
+
+ before do
allow(request).to receive(:current_user).and_return(user)
allow(request).to receive(:project).and_return(project)
end
- it 'exposes internal deployment id' do
+ it 'exposes fields', :aggregate_failures do
expect(subject).to include(:iid)
- end
-
- it 'exposes nested information about branch' do
expect(subject[:ref][:name]).to eq 'master'
- end
-
- it 'exposes status' do
expect(subject).to include(:status)
- end
-
- it 'exposes creation date' do
expect(subject).to include(:created_at)
- end
-
- it 'exposes deployed_at' do
expect(subject).to include(:deployed_at)
- end
-
- it 'exposes last? as is_last' do
expect(subject).to include(:is_last)
- end
-
- it 'exposes deployment tier in yaml' do
expect(subject).to include(:tier_in_yaml)
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) }
+
+ before do
+ deployment.update!(deployable: nil)
+ end
it 'does not expose deployable entry' do
expect(subject).not_to include(:deployable)
@@ -60,19 +51,19 @@ RSpec.describe DeploymentEntity do
end
context 'when the pipeline has another manual action' do
- let!(:other_build) do
+ let_it_be(:other_build) do
create(:ci_build, :manual, name: 'another deploy', pipeline: pipeline, environment: build.environment)
end
- let!(:other_deployment) { create(:deployment, deployable: build) }
+ let_it_be(:other_deployment) { create(:deployment, deployable: build, environment: environment) }
it 'returns another manual action' do
- expect(subject[:manual_actions].count).to eq(2)
- expect(subject[:manual_actions].pluck(:name)).to match_array(['test', 'another deploy'])
+ expect(subject[:manual_actions].count).to eq(1)
+ expect(subject[:manual_actions].pluck(:name)).to match_array(['another deploy'])
end
context 'when user is a reporter' do
- let(:user) { reporter }
+ let_it_be(:user) { reporter }
it 'returns another manual action' do
expect(subject[:manual_actions]).not_to be_present
@@ -91,14 +82,15 @@ RSpec.describe DeploymentEntity do
end
describe 'scheduled_actions' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
let(:build) { create(:ci_build, :success, pipeline: pipeline) }
- let(:deployment) { create(:deployment, deployable: build) }
+
+ before do
+ deployment.update!(deployable: build)
+ end
context 'when the same pipeline has a scheduled action' do
let(:other_build) { create(:ci_build, :schedulable, :success, pipeline: pipeline, name: 'other build') }
- let!(:other_deployment) { create(:deployment, deployable: other_build) }
+ let!(:other_deployment) { create(:deployment, deployable: other_build, environment: environment) }
it 'returns other scheduled actions' do
expect(subject[:scheduled_actions][0][:name]).to eq 'other build'
@@ -123,7 +115,9 @@ RSpec.describe DeploymentEntity do
end
describe 'playable_build' do
- let_it_be(:project) { create(:project, :repository) }
+ before do
+ deployment.update!(deployable: build)
+ end
context 'when the deployment has a playable deployable' do
context 'when this build is ready to be played' do
@@ -144,7 +138,7 @@ RSpec.describe DeploymentEntity do
end
context 'when the deployment does not have a playable deployable' do
- let(:build) { create(:ci_build) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
it 'is not exposed' do
expect(subject[:playable_build]).to be_nil
diff --git a/spec/serializers/environment_status_entity_spec.rb b/spec/serializers/environment_status_entity_spec.rb
index 77ef06f90c2..2ee4e8ade8f 100644
--- a/spec/serializers/environment_status_entity_spec.rb
+++ b/spec/serializers/environment_status_entity_spec.rb
@@ -3,21 +3,26 @@
require 'spec_helper'
RSpec.describe EnvironmentStatusEntity do
- let(:user) { create(:user) }
+ let_it_be(:non_member) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:deployment) { create(:deployment, :succeed, :review_app) }
+ let_it_be(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
+ let_it_be(:environment) { deployment.environment }
+ let_it_be(:project) { deployment.project }
+
+ let(:user) { non_member }
let(:request) { double('request', project: project) }
-
- let(:deployment) { create(:deployment, :succeed, :review_app) }
- let(:environment) { deployment.environment }
- let(:project) { deployment.project }
- let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
-
let(:environment_status) { EnvironmentStatus.new(project, environment, merge_request, merge_request.diff_head_sha) }
- let(:entity) { described_class.new(environment_status, request: request) }
+ let(:entity) { described_class.new(environment_status, request: request) }
subject { entity.as_json }
- before do
+ before_all do
+ project.add_maintainer(maintainer)
deployment.update!(sha: merge_request.diff_head_sha)
+ end
+
+ before do
allow(request).to receive(:current_user).and_return(user)
end
@@ -37,14 +42,13 @@ RSpec.describe EnvironmentStatusEntity do
it { is_expected.not_to include(:metrics_monitoring_url) }
context 'when the user is project maintainer' do
- before do
- project.add_maintainer(user)
- end
+ let(:user) { maintainer }
it { is_expected.to include(:stop_url) }
end
context 'when deployment has metrics' do
+ let(:user) { maintainer }
let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true, configured?: true) }
let(:simple_metrics) do
@@ -56,7 +60,6 @@ RSpec.describe EnvironmentStatusEntity do
end
before do
- project.add_maintainer(user)
allow(deployment).to receive(:prometheus_adapter).and_return(prometheus_adapter)
allow(entity).to receive(:deployment).and_return(deployment)
@@ -69,8 +72,6 @@ RSpec.describe EnvironmentStatusEntity do
end
context 'when deployment succeeded' do
- let(:deployment) { create(:deployment, :succeed, :review_app) }
-
it 'returns metrics url' do
expect(subject[:metrics_url])
.to eq("/#{project.full_path}/-/environments/#{environment.id}/deployments/#{deployment.iid}/metrics")
@@ -78,7 +79,9 @@ RSpec.describe EnvironmentStatusEntity do
end
context 'when deployment is running' do
- let(:deployment) { create(:deployment, :running, :review_app) }
+ before do
+ deployment.update!(status: :running)
+ end
it 'does not return metrics url' do
expect(subject[:metrics_url]).to be_nil
diff --git a/spec/serializers/group_access_token_entity_spec.rb b/spec/serializers/group_access_token_entity_spec.rb
index 05609dc3c7a..586eb0a8588 100644
--- a/spec/serializers/group_access_token_entity_spec.rb
+++ b/spec/serializers/group_access_token_entity_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe GroupAccessTokenEntity do
expected_revoke_path = Gitlab::Routing.url_helpers
.revoke_group_settings_access_token_path(
{ id: token,
- group_id: group.path })
+ group_id: group.full_path })
expect(json).to(
include(
@@ -39,7 +39,7 @@ RSpec.describe GroupAccessTokenEntity do
expected_revoke_path = Gitlab::Routing.url_helpers
.revoke_group_settings_access_token_path(
{ id: token,
- group_id: group.path })
+ group_id: group.full_path })
expect(json).to(
include(
diff --git a/spec/serializers/import/github_org_entity_spec.rb b/spec/serializers/import/github_org_entity_spec.rb
new file mode 100644
index 00000000000..46fceb8ac60
--- /dev/null
+++ b/spec/serializers/import/github_org_entity_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::GithubOrgEntity do
+ let(:org_data) do
+ {
+ 'id' => 12345,
+ 'login' => 'org-name',
+ 'url' => 'https://api.github.com/orgs/org-name',
+ 'avatar_url' => 'https://avatars.githubusercontent.com/u/12345?v=4',
+ 'node_id' => 'O_teStT',
+ 'description' => ''
+ }
+ end
+
+ subject { described_class.new(org_data).as_json }
+
+ it 'exposes correct attributes' do
+ expect(subject.keys).to contain_exactly(
+ :description,
+ :name
+ )
+ end
+end
diff --git a/spec/serializers/import/github_org_serializer_spec.rb b/spec/serializers/import/github_org_serializer_spec.rb
new file mode 100644
index 00000000000..4206914cd6e
--- /dev/null
+++ b/spec/serializers/import/github_org_serializer_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::GithubOrgSerializer do
+ it 'represents GithubOrgEntity entities' do
+ expect(described_class.entity_class).to eq(Import::GithubOrgEntity)
+ end
+
+ describe '#represent' do
+ let(:org_data) do
+ {
+ id: 123456,
+ login: 'org-name',
+ node_id: 'O_teStT',
+ url: 'https://api.github.com/orgs/org-name',
+ repos_url: 'https://api.github.com/orgs/org-name/repos',
+ events_url: 'https://api.github.com/orgs/org-name/events',
+ hooks_url: 'https://api.github.com/orgs/org-name/hooks',
+ issues_url: 'https://api.github.com/orgs/org-name/issues',
+ members_url: 'https://api.github.com/orgs/org-name/members{/member}',
+ public_members_url: 'https://api.github.com/orgs/org-name/public_members{/member}',
+ avatar_url: 'avatar_url',
+ description: 'description'
+ }
+ end
+
+ subject { described_class.new.represent(resource) }
+
+ context 'when a single object is being serialized' do
+ let(:resource) { org_data }
+
+ it 'serializes organization object' do
+ expect(subject).to eq({ name: 'org-name', description: 'description' })
+ end
+ end
+
+ context 'when multiple objects are being serialized' do
+ let(:count) { 3 }
+ let(:resource) { Array.new(count, org_data) }
+
+ it 'serializes array of organizations' do
+ expect(subject).to all(eq({ name: 'org-name', description: 'description' }))
+ end
+ end
+ end
+end
diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb
index 9335ca61b7d..25e9e8c17e2 100644
--- a/spec/serializers/issue_entity_spec.rb
+++ b/spec/serializers/issue_entity_spec.rb
@@ -150,4 +150,6 @@ RSpec.describe IssueEntity do
end
end
end
+
+ it_behaves_like 'issuable entity current_user properties'
end
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 90a82d16e38..59ffba0e7a9 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -152,17 +152,19 @@ RSpec.describe MergeRequestPollWidgetEntity do
describe '#builds_with_coverage' do
it 'serializes the builds with coverage' do
- allow(resource).to receive(:head_pipeline_builds_with_coverage).and_return([
- double(name: 'rspec', coverage: 91.5),
- double(name: 'jest', coverage: 94.1)
- ])
+ allow(resource).to receive(:head_pipeline_builds_with_coverage).and_return(
+ [
+ double(name: 'rspec', coverage: 91.5),
+ double(name: 'jest', coverage: 94.1)
+ ])
result = subject[:builds_with_coverage]
- expect(result).to eq([
- { name: 'rspec', coverage: 91.5 },
- { name: 'jest', coverage: 94.1 }
- ])
+ expect(result).to eq(
+ [
+ { name: 'rspec', coverage: 91.5 },
+ { name: 'jest', coverage: 94.1 }
+ ])
end
end
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index f5398013a70..4d9bdc4bb17 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe PipelineSerializer do
end
context 'when a single object is being serialized' do
- let(:resource) { create(:ci_empty_pipeline, project: project) }
+ let(:resource) { build_stubbed(:ci_empty_pipeline, project: project) }
it 'serializers the pipeline object' do
expect(subject[:id]).to eq resource.id
@@ -27,10 +27,11 @@ RSpec.describe PipelineSerializer do
end
context 'when multiple objects are being serialized' do
- let(:resource) { create_list(:ci_pipeline, 2, project: project) }
+ let(:resource) { Array.new(2) { build_stubbed(:ci_pipeline, project: project) } }
it 'serializers the array of pipelines' do
expect(subject).not_to be_empty
+ expect(subject.size).to eq(2)
end
end
end
@@ -41,8 +42,7 @@ RSpec.describe PipelineSerializer do
let(:query) { {} }
let(:serializer) do
- described_class.new(current_user: user)
- .with_pagination(request, response)
+ described_class.new(current_user: user, project: project).with_pagination(request, response)
end
it 'created a paginated serializer' do
@@ -67,7 +67,7 @@ RSpec.describe PipelineSerializer do
context 'when a single pipeline object is present in relation' do
before do
- create(:ci_empty_pipeline)
+ create(:ci_empty_pipeline, project: project)
end
it 'serializes pipeline relation' do
@@ -77,7 +77,7 @@ RSpec.describe PipelineSerializer do
context 'when a multiple pipeline objects are being serialized' do
before do
- create_list(:ci_empty_pipeline, 3)
+ create_list(:ci_empty_pipeline, 3, project: project)
end
it 'serializes appropriate number of objects' do
@@ -100,28 +100,28 @@ RSpec.describe PipelineSerializer do
let!(:merge_request_1) do
create(:merge_request,
- :with_detached_merge_request_pipeline,
- target_project: project,
- target_branch: 'master',
- source_project: project,
- source_branch: 'feature')
+ :with_detached_merge_request_pipeline,
+ target_project: project,
+ target_branch: 'master',
+ source_project: project,
+ source_branch: 'feature')
end
let!(:merge_request_2) do
create(:merge_request,
- :with_detached_merge_request_pipeline,
- target_project: project,
- target_branch: 'master',
- source_project: project,
- source_branch: '2-mb-file')
+ :with_detached_merge_request_pipeline,
+ target_project: project,
+ target_branch: 'master',
+ source_project: project,
+ source_branch: '2-mb-file')
end
- before do
+ before_all do
project.add_developer(user)
end
it 'includes merge requests information' do
- expect(subject.all? { |entry| entry[:merge_request].present? }).to be_truthy
+ expect(subject).to be_all { |entry| entry[:merge_request].present? }
end
it 'preloads related merge requests' do
@@ -138,7 +138,8 @@ RSpec.describe PipelineSerializer do
let(:resource) { Ci::Pipeline.all }
- before do
+ # Create pipelines only once and change their attributes if needed.
+ before_all do
# Since RequestStore.active? is true we have to allow the
# gitaly calls in this block
# Issue: https://gitlab.com/gitlab-org/gitlab-foss/issues/37772
@@ -151,8 +152,6 @@ RSpec.describe PipelineSerializer do
end
context 'with the same ref' do
- let(:ref) { 'feature' }
-
it 'verifies number of queries', :request_store do
recorded = ActiveRecord::QueryRecorder.new { subject }
expected_queries = Gitlab.ee? ? 33 : 30
@@ -163,10 +162,11 @@ RSpec.describe PipelineSerializer do
end
context 'with different refs' do
- def ref
- @sequence ||= 0
- @sequence += 1
- "feature-#{@sequence}"
+ before do
+ # rubocop:disable Rails/SkipsModelValidations
+ Ci::Pipeline.update_all(%(ref = 'feature-' || id))
+ Ci::Build.update_all(%(ref = 'feature-' || stage_id))
+ # rubocop:enable Rails/SkipsModelValidations
end
it 'verifies number of queries', :request_store do
@@ -184,8 +184,6 @@ RSpec.describe PipelineSerializer do
end
context 'with triggered pipelines' do
- let(:ref) { 'feature' }
-
before do
pipeline_1 = create(:ci_pipeline)
build_1 = create(:ci_build, pipeline: pipeline_1)
@@ -210,8 +208,6 @@ RSpec.describe PipelineSerializer do
end
context 'with build environments' do
- let(:ref) { 'feature' }
-
let_it_be(:production) { create(:environment, :production, project: project) }
let_it_be(:staging) { create(:environment, :staging, project: project) }
@@ -222,13 +218,11 @@ RSpec.describe PipelineSerializer do
create(:ci_build, :scheduled, pipeline: pipeline, environment: production.name)
create(:ci_build, :scheduled, pipeline: pipeline, environment: staging.name)
- expect { subject }.not_to exceed_query_limit(1).for_query /SELECT "environments".*/
+ expect { subject }.not_to exceed_query_limit(1).for_query(/SELECT "environments".*/)
end
end
context 'with scheduled and manual builds' do
- let(:ref) { 'feature' }
-
before do
create(:ci_build, :scheduled, pipeline: resource.first)
create(:ci_build, :scheduled, pipeline: resource.second)
@@ -238,7 +232,7 @@ RSpec.describe PipelineSerializer do
it 'sends at most one metadata query for each type of build', :request_store do
# 1 for the existing failed builds and 2 for the added scheduled and manual builds
- expect { subject }.not_to exceed_query_limit(1 + 2).for_query /SELECT "ci_builds_metadata".*/
+ expect { subject }.not_to exceed_query_limit(1 + 2).for_query(/SELECT "ci_builds_metadata".*/)
end
end
@@ -246,25 +240,25 @@ RSpec.describe PipelineSerializer do
create(:ci_empty_pipeline,
project: project,
status: status,
- ref: ref).tap do |pipeline|
- Ci::Build::AVAILABLE_STATUSES.each do |status|
- create_build(pipeline, status, status)
+ ref: 'feature').tap do |pipeline|
+ Ci::Build::AVAILABLE_STATUSES.each do |build_status|
+ create_build(pipeline, status, build_status)
end
end
end
def create_build(pipeline, stage, status)
create(:ci_build, :tags, :triggered, :artifacts,
- pipeline: pipeline, stage: stage,
- name: stage, status: status, ref: pipeline.ref)
+ pipeline: pipeline, stage: stage,
+ name: stage, status: status, ref: pipeline.ref)
end
end
end
describe '#represent_status' do
context 'when represents only status' do
- let(:resource) { create(:ci_pipeline) }
- let(:status) { resource.detailed_status(double('user')) }
+ let(:resource) { build_stubbed(:ci_pipeline) }
+ let(:status) { resource.detailed_status(instance_double('User')) }
subject { serializer.represent_status(resource) }
diff --git a/spec/serializers/project_access_token_entity_spec.rb b/spec/serializers/project_access_token_entity_spec.rb
index 4b5b4d4d77d..8af09b0a45d 100644
--- a/spec/serializers/project_access_token_entity_spec.rb
+++ b/spec/serializers/project_access_token_entity_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe ProjectAccessTokenEntity do
expected_revoke_path = Gitlab::Routing.url_helpers
.revoke_namespace_project_settings_access_token_path(
{ id: token,
- namespace_id: project.namespace.path,
+ namespace_id: project.namespace.full_path,
project_id: project.path })
expect(json).to(
@@ -42,7 +42,7 @@ RSpec.describe ProjectAccessTokenEntity do
expected_revoke_path = Gitlab::Routing.url_helpers
.revoke_namespace_project_settings_access_token_path(
{ id: token,
- namespace_id: project.namespace.path,
+ namespace_id: project.namespace.full_path,
project_id: project.path })
expect(json).to(
diff --git a/spec/services/admin/set_feature_flag_service_spec.rb b/spec/services/admin/set_feature_flag_service_spec.rb
new file mode 100644
index 00000000000..6fa806644c9
--- /dev/null
+++ b/spec/services/admin/set_feature_flag_service_spec.rb
@@ -0,0 +1,300 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::SetFeatureFlagService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+
+ let(:feature_name) { known_feature_flag.name }
+ let(:service) { described_class.new(feature_flag_name: feature_name, params: params) }
+
+ # Find any `development` feature flag name
+ let(:known_feature_flag) do
+ Feature::Definition.definitions
+ .values.find(&:development?)
+ end
+
+ describe '#execute' do
+ before do
+ Feature.reset
+ Flipper.unregister_groups
+ Flipper.register(:perf_team) do |actor|
+ actor.respond_to?(:admin) && actor.admin?
+ end
+ end
+
+ subject { service.execute }
+
+ context 'when enabling the feature flag' do
+ let(:params) { { value: 'true' } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name)
+ expect(subject).to be_success
+
+ feature_flag = subject.payload[:feature_flag]
+ expect(feature_flag.name).to eq(feature_name)
+ end
+
+ it 'logs the event' do
+ expect(Feature.logger).to receive(:info).once
+
+ subject
+ end
+
+ context 'when enabling for a user actor' do
+ let(:params) { { value: 'true', user: user.username } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, user)
+ expect(subject).to be_success
+ end
+
+ context 'when user does not exist' do
+ let(:params) { { value: 'true', user: 'unknown-user' } }
+
+ it 'does nothing' do
+ expect(Feature).not_to receive(:enable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when enabling for a feature group' do
+ let(:params) { { value: 'true', feature_group: 'perf_team' } }
+ let(:feature_group) { Feature.group('perf_team') }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, feature_group)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when enabling for a project' do
+ let(:params) { { value: 'true', project: project.full_path } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, project)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when enabling for a group' do
+ let(:params) { { value: 'true', group: group.full_path } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, group)
+ expect(subject).to be_success
+ end
+
+ context 'when group does not exist' do
+ let(:params) { { value: 'true', group: 'unknown-group' } }
+
+ it 'returns an error' do
+ expect(Feature).not_to receive(:disable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when enabling for a user namespace' do
+ let(:namespace) { user.namespace }
+ let(:params) { { value: 'true', namespace: namespace.full_path } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, namespace)
+ expect(subject).to be_success
+ end
+
+ context 'when namespace does not exist' do
+ let(:params) { { value: 'true', namespace: 'unknown-namespace' } }
+
+ it 'returns an error' do
+ expect(Feature).not_to receive(:disable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when enabling for a group namespace' do
+ let(:params) { { value: 'true', namespace: group.full_path } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, group)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when enabling for a user actor and a feature group' do
+ let(:params) { { value: 'true', user: user.username, feature_group: 'perf_team' } }
+ let(:feature_group) { Feature.group('perf_team') }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable).with(feature_name, user)
+ expect(Feature).to receive(:enable).with(feature_name, feature_group)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when enabling given a percentage of time' do
+ let(:params) { { value: '50' } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable_percentage_of_time).with(feature_name, 50)
+ expect(subject).to be_success
+ end
+
+ context 'when value is a float' do
+ let(:params) { { value: '0.01' } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable_percentage_of_time).with(feature_name, 0.01)
+ expect(subject).to be_success
+ end
+ end
+ end
+
+ context 'when enabling given a percentage of actors' do
+ let(:params) { { value: '50', key: 'percentage_of_actors' } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable_percentage_of_actors).with(feature_name, 50)
+ expect(subject).to be_success
+ end
+
+ context 'when value is a float' do
+ let(:params) { { value: '0.01', key: 'percentage_of_actors' } }
+
+ it 'enables the feature flag' do
+ expect(Feature).to receive(:enable_percentage_of_actors).with(feature_name, 0.01)
+ expect(subject).to be_success
+ end
+ end
+ end
+ end
+
+ context 'when disabling the feature flag' do
+ before do
+ Feature.enable(feature_name)
+ end
+
+ let(:params) { { value: 'false' } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name)
+ expect(subject).to be_success
+
+ feature_flag = subject.payload[:feature_flag]
+ expect(feature_flag.name).to eq(feature_name)
+ end
+
+ it 'logs the event' do
+ expect(Feature.logger).to receive(:info).once
+
+ subject
+ end
+
+ context 'when disabling for a user actor' do
+ let(:params) { { value: 'false', user: user.username } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, user)
+ expect(subject).to be_success
+ end
+
+ context 'when user does not exist' do
+ let(:params) { { value: 'false', user: 'unknown-user' } }
+
+ it 'returns an error' do
+ expect(Feature).not_to receive(:disable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when disabling for a feature group' do
+ let(:params) { { value: 'false', feature_group: 'perf_team' } }
+ let(:feature_group) { Feature.group('perf_team') }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, feature_group)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when disabling for a project' do
+ let(:params) { { value: 'false', project: project.full_path } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, project)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when disabling for a group' do
+ let(:params) { { value: 'false', group: group.full_path } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, group)
+ expect(subject).to be_success
+ end
+
+ context 'when group does not exist' do
+ let(:params) { { value: 'false', group: 'unknown-group' } }
+
+ it 'returns an error' do
+ expect(Feature).not_to receive(:disable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when disabling for a user namespace' do
+ let(:namespace) { user.namespace }
+ let(:params) { { value: 'false', namespace: namespace.full_path } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, namespace)
+ expect(subject).to be_success
+ end
+
+ context 'when namespace does not exist' do
+ let(:params) { { value: 'false', namespace: 'unknown-namespace' } }
+
+ it 'returns an error' do
+ expect(Feature).not_to receive(:disable)
+ expect(subject).to be_error
+ expect(subject.reason).to eq(:actor_not_found)
+ end
+ end
+ end
+
+ context 'when disabling for a group namespace' do
+ let(:params) { { value: 'false', namespace: group.full_path } }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, group)
+ expect(subject).to be_success
+ end
+ end
+
+ context 'when disabling for a user actor and a feature group' do
+ let(:params) { { value: 'false', user: user.username, feature_group: 'perf_team' } }
+ let(:feature_group) { Feature.group('perf_team') }
+
+ it 'disables the feature flag' do
+ expect(Feature).to receive(:disable).with(feature_name, user)
+ expect(Feature).to receive(:disable).with(feature_name, feature_group)
+ expect(subject).to be_success
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/alert_management/create_alert_issue_service_spec.rb b/spec/services/alert_management/create_alert_issue_service_spec.rb
index 083e5b8c6f1..7255a722d26 100644
--- a/spec/services/alert_management/create_alert_issue_service_spec.rb
+++ b/spec/services/alert_management/create_alert_issue_service_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
it 'checks permissions' do
execute
- expect(user).to have_received(:can?).with(:create_issue, project)
+ expect(user).to have_received(:can?).with(:create_issue, project).exactly(2).times
end
context 'with alert severity' do
@@ -161,7 +161,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
it 'has an unsuccessful status' do
expect(execute).to be_error
- expect(execute.message).to eq("Title can't be blank")
+ expect(execute.errors).to contain_exactly("Title can't be blank")
end
end
@@ -170,7 +170,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
it 'responds with error' do
expect(execute).to be_error
- expect(execute.message).to eq('Hosts hosts array is over 255 chars')
+ expect(execute.errors).to contain_exactly('Hosts hosts array is over 255 chars')
end
end
diff --git a/spec/services/award_emojis/copy_service_spec.rb b/spec/services/award_emojis/copy_service_spec.rb
index e85c548968e..abb9c65e25d 100644
--- a/spec/services/award_emojis/copy_service_spec.rb
+++ b/spec/services/award_emojis/copy_service_spec.rb
@@ -4,10 +4,12 @@ require 'spec_helper'
RSpec.describe AwardEmojis::CopyService do
let_it_be(:from_awardable) do
- create(:issue, award_emoji: [
- build(:award_emoji, name: 'thumbsup'),
- build(:award_emoji, name: 'thumbsdown')
- ])
+ create(
+ :issue,
+ award_emoji: [
+ build(:award_emoji, name: 'thumbsup'),
+ build(:award_emoji, name: 'thumbsdown')
+ ])
end
describe '#initialize' do
diff --git a/spec/services/boards/issues/create_service_spec.rb b/spec/services/boards/issues/create_service_spec.rb
index 9a6b48c13bf..c4f1eb093dc 100644
--- a/spec/services/boards/issues/create_service_spec.rb
+++ b/spec/services/boards/issues/create_service_spec.rb
@@ -29,9 +29,10 @@ RSpec.describe Boards::Issues::CreateService do
end
it 'adds the label of the list to the issue' do
- issue = service.execute
+ result = service.execute
- expect(issue.labels).to eq [label]
+ expect(result).to be_success
+ expect(result[:issue].labels).to contain_exactly(label)
end
end
end
diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb
deleted file mode 100644
index 9597c8e0f54..00000000000
--- a/spec/services/boards/lists/generate_service_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Boards::Lists::GenerateService do
- describe '#execute' do
- let(:project) { create(:project) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
-
- subject(:service) { described_class.new(project, user) }
-
- before do
- project.add_developer(user)
- end
-
- context 'when board lists is empty' do
- it 'creates the default lists' do
- expect { service.execute(board) }.to change(board.lists, :count).by(2)
- end
- end
-
- context 'when board lists is not empty' do
- it 'does not creates the default lists' do
- create(:list, board: board)
-
- expect { service.execute(board) }.not_to change(board.lists, :count)
- end
- end
-
- context 'when project labels does not contains any list label' do
- it 'creates labels' do
- expect { service.execute(board) }.to change(project.labels, :count).by(2)
- end
- end
-
- context 'when project labels contains some of list label' do
- it 'creates the missing labels' do
- create(:label, project: project, name: 'Doing')
-
- expect { service.execute(board) }.to change(project.labels, :count).by(1)
- end
- end
- end
-end
diff --git a/spec/services/boards/lists/list_service_spec.rb b/spec/services/boards/lists/list_service_spec.rb
index 0c8a8dc7329..2d41de42581 100644
--- a/spec/services/boards/lists/list_service_spec.rb
+++ b/spec/services/boards/lists/list_service_spec.rb
@@ -3,13 +3,40 @@
require 'spec_helper'
RSpec.describe Boards::Lists::ListService do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ RSpec.shared_examples 'FOSS lists only' do
+ context 'when board contains a non FOSS list' do
+ # This scenario may happen when there used to be an EE license and user downgraded
+ let!(:backlog_list) { create_backlog_list(board) }
+ let_it_be(:milestone) { create(:milestone, group: group) }
+ let_it_be(:assignee_list) do
+ list = build(:list, board: board, user_id: user.id, list_type: List.list_types[:assignee], position: 0)
+ list.save!(validate: false)
+ list
+ end
+
+ let_it_be(:milestone_list) do
+ list = build(:list, board: board, milestone_id: milestone.id, list_type: List.list_types[:milestone], position: 1) # rubocop:disable Layout/LineLength
+ list.save!(validate: false)
+ list
+ end
+
+ it "returns only FOSS board's lists" do
+ # just making sure these non FOSS lists actually exist on the board
+ expect(board.lists.with_types([List.list_types[:assignee], List.list_types[:milestone]]).count).to eq 2
+ # check that the FOSS lists are not returned from the service
+ expect(service.execute(board)).to match_array [backlog_list, list, board.lists.closed.first]
+ end
+ end
+ end
describe '#execute' do
let(:service) { described_class.new(parent, user) }
context 'when board parent is a project' do
- let_it_be(:project) { create(:project) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be_with_reload(:board) { create(:board, project: project) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:list) { create(:list, board: board, label: label) }
@@ -18,10 +45,10 @@ RSpec.describe Boards::Lists::ListService do
let(:parent) { project }
it_behaves_like 'lists list service'
+ it_behaves_like 'FOSS lists only'
end
context 'when board parent is a group' do
- let_it_be(:group) { create(:group) }
let_it_be_with_reload(:board) { create(:board, group: group) }
let_it_be(:label) { create(:group_label, group: group) }
let_it_be(:list) { create(:list, board: board, label: label) }
@@ -30,6 +57,7 @@ RSpec.describe Boards::Lists::ListService do
let(:parent) { group }
it_behaves_like 'lists list service'
+ it_behaves_like 'FOSS lists only'
end
def create_backlog_list(board)
diff --git a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb b/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
index d7b00ba04ab..0de962328c5 100644
--- a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
+++ b/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
@@ -75,7 +75,9 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:info).with({
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ importer: 'gitlab_migration',
pipeline_name: 'PipelineClass4',
minimum_source_version: '15.1.0',
maximum_source_version: nil,
@@ -84,7 +86,9 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
expect(logger).to receive(:info).with({
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ importer: 'gitlab_migration',
pipeline_name: 'PipelineClass5',
minimum_source_version: '16.0.0',
maximum_source_version: nil,
diff --git a/spec/services/bulk_imports/create_service_spec.rb b/spec/services/bulk_imports/create_service_spec.rb
index 4b655dd5d6d..bf174f5d5a2 100644
--- a/spec/services/bulk_imports/create_service_spec.rb
+++ b/spec/services/bulk_imports/create_service_spec.rb
@@ -50,6 +50,11 @@ RSpec.describe BulkImports::CreateService do
expect(last_bulk_import.user).to eq(user)
expect(last_bulk_import.source_version).to eq(source_version.to_s)
expect(last_bulk_import.user).to eq(user)
+ expect_snowplow_event(
+ category: 'BulkImports::CreateService',
+ action: 'create',
+ label: 'bulk_import_group'
+ )
end
it 'creates bulk import entities' do
diff --git a/spec/services/bulk_imports/repository_bundle_export_service_spec.rb b/spec/services/bulk_imports/repository_bundle_export_service_spec.rb
index a7d98a7474a..f0d63de1ab9 100644
--- a/spec/services/bulk_imports/repository_bundle_export_service_spec.rb
+++ b/spec/services/bulk_imports/repository_bundle_export_service_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe BulkImports::RepositoryBundleExportService do
context 'when repository exists' do
it 'bundles repository to disk' do
allow(repository).to receive(:exists?).and_return(true)
+ allow(repository).to receive(:empty?).and_return(false)
expect(repository).to receive(:bundle_to_disk).with(File.join(export_path, "#{export_filename}.bundle"))
service.execute
@@ -31,6 +32,15 @@ RSpec.describe BulkImports::RepositoryBundleExportService do
service.execute
end
end
+
+ context 'when repository is empty' do
+ it 'does not bundle repository to disk' do
+ allow(repository).to receive(:empty?).and_return(true)
+ expect(repository).not_to receive(:bundle_to_disk)
+
+ service.execute
+ end
+ end
end
include_examples 'repository export' do
diff --git a/spec/services/bulk_imports/uploads_export_service_spec.rb b/spec/services/bulk_imports/uploads_export_service_spec.rb
index 39bcacfdc5e..ad6e005485c 100644
--- a/spec/services/bulk_imports/uploads_export_service_spec.rb
+++ b/spec/services/bulk_imports/uploads_export_service_spec.rb
@@ -3,9 +3,11 @@
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 }
+ let_it_be(:project) { create(:project, avatar: fixture_file_upload('spec/fixtures/rails_sample.png', 'image/png')) }
+
+ let!(:upload) { create(:upload, :with_file, :issuable_upload, uploader: FileUploader, model: project) }
+ let(:exported_filepath) { File.join(export_path, upload.secret, upload.retrieve_uploader.filename) }
subject(:service) { described_class.new(project, export_path) }
@@ -15,10 +17,60 @@ RSpec.describe BulkImports::UploadsExportService do
describe '#execute' do
it 'exports project uploads and avatar' do
- subject.execute
+ service.execute
+
+ expect(File).to exist(File.join(export_path, 'avatar', 'rails_sample.png'))
+ expect(File).to exist(exported_filepath)
+ end
+
+ context 'when upload has underlying file missing' do
+ context 'with an upload missing its file' do
+ it 'does not cause errors' do
+ File.delete(upload.absolute_path)
+
+ expect { service.execute }.not_to raise_error
+
+ expect(File).not_to exist(exported_filepath)
+ end
+ end
+
+ context 'when upload is in object storage' do
+ before do
+ stub_uploads_object_storage(FileUploader)
+ end
+
+ shared_examples 'export with invalid upload' do
+ it 'ignores problematic upload and logs exception' do
+ allow(service).to receive(:download_or_copy_upload).and_raise(exception)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(
+ instance_of(exception), {
+ portable_id: project.id,
+ portable_class: 'Project',
+ upload_id: upload.id
+ }
+ )
+
+ service.execute
+
+ expect(File).not_to exist(exported_filepath)
+ end
+ end
+
+ context 'when filename is too long' do
+ let(:exception) { Errno::ENAMETOOLONG }
+
+ include_examples 'export with invalid upload'
+ end
+
+ context 'when network exception occurs' do
+ let(:exception) { Net::OpenTimeout }
- 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)
+ include_examples 'export with invalid upload'
+ end
+ end
end
end
end
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index 7c5bd1db565..24a868b524d 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe BulkUpdateIntegrationService do
let(:excluded_attributes) do
%w[
- id project_id group_id inherit_from_id instance template
- created_at updated_at encrypted_properties encrypted_properties_iv
+ id project_id group_id inherit_from_id instance template
+ created_at updated_at encrypted_properties encrypted_properties_iv
]
end
diff --git a/spec/services/ci/compare_test_reports_service_spec.rb b/spec/services/ci/compare_test_reports_service_spec.rb
index 01d58b2095f..6d3df0f5383 100644
--- a/spec/services/ci/compare_test_reports_service_spec.rb
+++ b/spec/services/ci/compare_test_reports_service_spec.rb
@@ -72,10 +72,11 @@ RSpec.describe Ci::CompareTestReportsService do
it 'loads recent failures on limited test cases to avoid building up a huge DB query', :aggregate_failures do
expect(comparison[:data]).to match_schema('entities/test_reports_comparer')
- expect(recent_failures_per_test_case).to eq([
- { 'count' => 1, 'base_branch' => 'master' },
- { 'count' => 1, 'base_branch' => 'master' }
- ])
+ expect(recent_failures_per_test_case).to eq(
+ [
+ { 'count' => 1, 'base_branch' => 'master' },
+ { 'count' => 1, 'base_branch' => 'master' }
+ ])
expect(new_failures.count).to eq(2)
end
end
diff --git a/spec/services/ci/create_pipeline_service/include_spec.rb b/spec/services/ci/create_pipeline_service/include_spec.rb
index 67d8530525a..3764663fd74 100644
--- a/spec/services/ci/create_pipeline_service/include_spec.rb
+++ b/spec/services/ci/create_pipeline_service/include_spec.rb
@@ -126,51 +126,5 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
it_behaves_like 'not including the file'
end
end
-
- context 'with ci_increase_includes_to_250 enabled on root project' do
- let_it_be(:included_project) do
- create(:project, :repository).tap { |p| p.add_developer(user) }
- end
-
- before do
- stub_const('::Gitlab::Ci::Config::External::Context::MAX_INCLUDES', 0)
- stub_const('::Gitlab::Ci::Config::External::Context::TRIAL_MAX_INCLUDES', 3)
-
- stub_feature_flags(ci_increase_includes_to_250: false)
- stub_feature_flags(ci_increase_includes_to_250: project)
-
- allow(Project)
- .to receive(:find_by_full_path)
- .with(included_project.full_path)
- .and_return(included_project)
-
- allow(included_project.repository)
- .to receive(:blob_data_at).with(included_project.commit.id, '.gitlab-ci.yml')
- .and_return(local_config)
-
- allow(included_project.repository)
- .to receive(:blob_data_at).with(included_project.commit.id, file_location)
- .and_return(File.read(Rails.root.join(file_location)))
- end
-
- let(:config) do
- <<~EOY
- include:
- - project: #{included_project.full_path}
- file: .gitlab-ci.yml
- EOY
- end
-
- let(:local_config) do
- <<~EOY
- include: #{file_location}
-
- job:
- script: exit 0
- EOY
- end
-
- it_behaves_like 'including the file'
- end
end
end
diff --git a/spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb b/spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb
new file mode 100644
index 00000000000..003d109a27c
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/limit_active_jobs_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectness do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.first_owner }
+ let_it_be(:existing_pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:service) { described_class.new(project, user, ref: 'refs/heads/master') }
+
+ subject(:pipeline) { service.execute(:push).payload }
+
+ before do
+ create_list(:ci_build, 8, pipeline: existing_pipeline)
+ create_list(:ci_bridge, 1, pipeline: existing_pipeline)
+
+ stub_ci_pipeline_yaml_file(<<~YAML)
+ job1:
+ script: echo
+ job3:
+ trigger:
+ project: org/my-project
+ job4:
+ script: echo
+ only: [tags]
+ YAML
+ end
+
+ context 'when project has exceeded the active jobs limit' do
+ before do
+ project.namespace.actual_limits.update!(ci_active_jobs: 10)
+ end
+
+ it 'fails the pipeline before populating it' do
+ expect(pipeline).to be_failed
+ expect(pipeline).to be_job_activity_limit_exceeded
+
+ expect(pipeline.errors.full_messages)
+ .to include("Project exceeded the allowed number of jobs in active pipelines. Retry later.")
+ expect(pipeline.statuses).to be_empty
+ end
+ end
+
+ context 'when project has not exceeded the active jobs limit' do
+ before do
+ project.namespace.actual_limits.update!(ci_active_jobs: 20)
+ end
+
+ it 'creates the pipeline successfully' do
+ expect(pipeline).to be_created
+ 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
index 2be23802757..3045f8e92b1 100644
--- a/spec/services/ci/create_pipeline_service/logger_spec.rb
+++ b/spec/services/ci/create_pipeline_service/logger_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
{
'count' => a_kind_of(Numeric),
'avg' => a_kind_of(Numeric),
+ 'sum' => a_kind_of(Numeric),
'max' => a_kind_of(Numeric),
'min' => a_kind_of(Numeric)
}
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index fc57ca66d3a..c737b8cc329 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -540,19 +540,10 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
let(:compare_to) { 'invalid-branch' }
it 'returns an error' do
- expect(pipeline.errors.full_messages).to eq([
- 'Failed to parse rule for job1: rules:changes:compare_to is not a valid ref'
- ])
- end
-
- context 'when the FF ci_rules_changes_compare is not enabled' do
- before do
- stub_feature_flags(ci_rules_changes_compare: false)
- end
-
- it 'ignores compare_to and changes is always true' do
- expect(build_names).to contain_exactly('job1', 'job2')
- end
+ expect(pipeline.errors.full_messages).to eq(
+ [
+ 'Failed to parse rule for job1: rules:changes:compare_to is not a valid ref'
+ ])
end
end
@@ -563,16 +554,6 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
it 'creates job1 and job2' do
expect(build_names).to contain_exactly('job1', 'job2')
end
-
- context 'when the FF ci_rules_changes_compare is not enabled' do
- before do
- stub_feature_flags(ci_rules_changes_compare: false)
- end
-
- it 'ignores compare_to and changes is always true' do
- expect(build_names).to contain_exactly('job1', 'job2')
- end
- end
end
context 'when the rule does not match' do
@@ -581,16 +562,6 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
it 'does not create job1' do
expect(build_names).to contain_exactly('job2')
end
-
- context 'when the FF ci_rules_changes_compare is not enabled' do
- before do
- stub_feature_flags(ci_rules_changes_compare: false)
- end
-
- it 'ignores compare_to and changes is always true' do
- expect(build_names).to contain_exactly('job1', 'job2')
- end
- end
end
end
end
@@ -616,17 +587,6 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
expect(pipeline).to be_created_successfully
expect(build_names).to contain_exactly('job1')
end
-
- context 'when the FF ci_rules_changes_compare is not enabled' do
- before do
- stub_feature_flags(ci_rules_changes_compare: false)
- end
-
- it 'ignores compare_to and changes is always true' do
- expect(pipeline).to be_created_successfully
- expect(build_names).to contain_exactly('job1')
- end
- end
end
context 'when the rule does not match' do
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index c2e80316d26..458692ba1c0 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -293,7 +293,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
pipeline_on_previous_commit
.builds
.joins(:metadata)
- .pluck(:name, 'ci_builds_metadata.interruptible')
+ .pluck(:name, "#{Ci::BuildMetadata.quoted_table_name}.interruptible")
expect(interruptible_status).to contain_exactly(
['build_1_1', true],
@@ -423,7 +423,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
expect(response.message).to eq('Missing CI config file')
expect(response.payload).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
- expect(Namespaces::OnboardingPipelineCreatedWorker).not_to receive(:perform_async)
+ expect(Onboarding::PipelineCreatedWorker).not_to receive(:perform_async)
end
shared_examples 'a failed pipeline' do
@@ -1547,7 +1547,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
end
it 'schedules a namespace onboarding create action worker' do
- expect(Namespaces::OnboardingPipelineCreatedWorker)
+ expect(Onboarding::PipelineCreatedWorker)
.to receive(:perform_async).with(project.namespace_id)
pipeline
diff --git a/spec/services/ci/find_exposed_artifacts_service_spec.rb b/spec/services/ci/find_exposed_artifacts_service_spec.rb
index 32d96471f16..6e11c153a75 100644
--- a/spec/services/ci/find_exposed_artifacts_service_spec.rb
+++ b/spec/services/ci/find_exposed_artifacts_service_spec.rb
@@ -157,20 +157,21 @@ RSpec.describe Ci::FindExposedArtifactsService do
subject { described_class.new(project, user).for_pipeline(pipeline, limit: 2) }
it 'returns first 2 results' do
- expect(subject).to eq([
- {
- text: 'artifact 1',
- url: file_project_job_artifacts_path(project, job1, 'ci_artifacts.txt'),
- job_name: job1.name,
- job_path: project_job_path(project, job1)
- },
- {
- text: 'artifact 2',
- url: browse_project_job_artifacts_path(project, job2),
- job_name: job2.name,
- job_path: project_job_path(project, job2)
- }
- ])
+ expect(subject).to eq(
+ [
+ {
+ text: 'artifact 1',
+ url: file_project_job_artifacts_path(project, job1, 'ci_artifacts.txt'),
+ job_name: job1.name,
+ job_path: project_job_path(project, job1)
+ },
+ {
+ text: 'artifact 2',
+ url: browse_project_job_artifacts_path(project, job2),
+ job_name: job2.name,
+ job_path: project_job_path(project, job2)
+ }
+ ])
end
end
@@ -199,20 +200,21 @@ RSpec.describe Ci::FindExposedArtifactsService do
subject { described_class.new(project, user).for_pipeline(pipeline, limit: 2) }
it 'returns the correct path for cross-project MRs' do
- expect(subject).to eq([
- {
- text: 'file artifact',
- url: file_project_job_artifacts_path(foreign_project, job_show, 'ci_artifacts.txt'),
- job_name: job_show.name,
- job_path: project_job_path(foreign_project, job_show)
- },
- {
- text: 'directory artifact',
- url: browse_project_job_artifacts_path(foreign_project, job_browse),
- job_name: job_browse.name,
- job_path: project_job_path(foreign_project, job_browse)
- }
- ])
+ expect(subject).to eq(
+ [
+ {
+ text: 'file artifact',
+ url: file_project_job_artifacts_path(foreign_project, job_show, 'ci_artifacts.txt'),
+ job_name: job_show.name,
+ job_path: project_job_path(foreign_project, job_show)
+ },
+ {
+ text: 'directory artifact',
+ url: browse_project_job_artifacts_path(foreign_project, job_browse),
+ job_name: job_browse.name,
+ job_path: project_job_path(foreign_project, job_browse)
+ }
+ ])
end
end
end
diff --git a/spec/services/ci/generate_kubeconfig_service_spec.rb b/spec/services/ci/generate_kubeconfig_service_spec.rb
index e3088ca6ea7..bfde39780dd 100644
--- a/spec/services/ci/generate_kubeconfig_service_spec.rb
+++ b/spec/services/ci/generate_kubeconfig_service_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe Ci::GenerateKubeconfigService do
let(:pipeline) { build.pipeline }
let(:agent1) { create(:cluster_agent, project: project) }
let(:agent2) { create(:cluster_agent) }
+ let(:authorization1) { create(:agent_project_authorization, agent: agent1) }
+ let(:authorization2) { create(:agent_project_authorization, agent: agent2) }
let(:template) { instance_double(Gitlab::Kubernetes::Kubeconfig::Template) }
@@ -16,7 +18,7 @@ RSpec.describe Ci::GenerateKubeconfigService do
before do
expect(Gitlab::Kubernetes::Kubeconfig::Template).to receive(:new).and_return(template)
- expect(pipeline).to receive(:authorized_cluster_agents).and_return([agent1, agent2])
+ expect(pipeline).to receive(:cluster_agent_authorizations).and_return([authorization1, authorization2])
end
it 'adds a cluster, and a user and context for each available agent' do
@@ -36,11 +38,13 @@ RSpec.describe Ci::GenerateKubeconfigService do
expect(template).to receive(:add_context).with(
name: "#{project.full_path}:#{agent1.name}",
+ namespace: 'production',
cluster: 'gitlab',
user: "agent:#{agent1.id}"
)
expect(template).to receive(:add_context).with(
name: "#{agent2.project.full_path}:#{agent2.name}",
+ namespace: 'production',
cluster: 'gitlab',
user: "agent:#{agent2.id}"
)
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index a2259f9813b..030ba84951e 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -182,7 +182,8 @@ RSpec.describe Ci::JobArtifacts::CreateService do
end
context 'with job partitioning' do
- let(:job) { create(:ci_build, project: project, partition_id: 123) }
+ let(:pipeline) { create(:ci_pipeline, project: project, partition_id: 123) }
+ let(:job) { create(:ci_build, pipeline: pipeline) }
it 'sets partition_id on artifacts' do
expect { subject }.to change { Ci::JobArtifact.count }
diff --git a/spec/services/ci/job_artifacts/delete_service_spec.rb b/spec/services/ci/job_artifacts/delete_service_spec.rb
index 62a755eb44a..78e8be48255 100644
--- a/spec/services/ci/job_artifacts/delete_service_spec.rb
+++ b/spec/services/ci/job_artifacts/delete_service_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
result = service.execute
expect(result).to be_success
+ expect(result[:destroyed_artifacts_count]).to be(2)
end
it 'deletes erasable artifacts' do
@@ -24,7 +25,7 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
expect { service.execute }.not_to change { build.has_trace? }.from(true)
end
- context 'when project is undergoing statistics refresh' do
+ context 'when project is undergoing stats refresh' do
before do
allow(build.project).to receive(:refreshing_build_artifacts_size?).and_return(true)
end
@@ -36,6 +37,30 @@ RSpec.describe Ci::JobArtifacts::DeleteService do
service.execute
end
+
+ it 'returns an error response with the correct message and reason' do
+ result = service.execute
+
+ expect(result).to be_error
+ expect(result[:message]).to be('Action temporarily disabled. ' \
+ 'The project this job belongs to is undergoing stats refresh.')
+ expect(result[:reason]).to be(:project_stats_refresh)
+ end
+ end
+
+ context 'when an error response is received from DestroyBatchService' do
+ before do
+ allow_next_instance_of(Ci::JobArtifacts::DestroyBatchService) do |service|
+ allow(service).to receive(:execute).and_return({ status: :error, message: 'something went wrong' })
+ end
+ end
+
+ it 'returns an error response with the correct message' do
+ result = service.execute
+
+ expect(result).to be_error
+ expect(result[:message]).to be('something went wrong')
+ end
end
end
end
diff --git a/spec/services/ci/job_token_scope/add_project_service_spec.rb b/spec/services/ci/job_token_scope/add_project_service_spec.rb
index bb6df4268dd..bf7df3a5595 100644
--- a/spec/services/ci/job_token_scope/add_project_service_spec.rb
+++ b/spec/services/ci/job_token_scope/add_project_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::JobTokenScope::AddProjectService do
let(:service) { described_class.new(project, current_user) }
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let_it_be(:current_user) { create(:user) }
diff --git a/spec/services/ci/job_token_scope/remove_project_service_spec.rb b/spec/services/ci/job_token_scope/remove_project_service_spec.rb
index 155e60ac48e..c3f9081cbd8 100644
--- a/spec/services/ci/job_token_scope/remove_project_service_spec.rb
+++ b/spec/services/ci/job_token_scope/remove_project_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::JobTokenScope::RemoveProjectService do
let(:service) { described_class.new(project, current_user) }
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let_it_be(:current_user) { create(:user) }
diff --git a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb
index 6d4dcf28108..c4558bddc85 100644
--- a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb
+++ b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe Ci::PipelineArtifacts::CoverageReportService do
end
it 'logs relevant information' do
+ allow(Gitlab::AppLogger).to receive(:info).and_call_original
expect(Gitlab::AppLogger).to receive(:info).with({
project_id: project.id,
pipeline_id: pipeline.id,
@@ -52,28 +53,12 @@ RSpec.describe Ci::PipelineArtifacts::CoverageReportService do
it_behaves_like 'creating or updating a pipeline coverage report'
- context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do
- it "artifact has pipeline's locked status" do
- subject
-
- artifact = Ci::PipelineArtifact.first
-
- expect(artifact.locked).to eq(pipeline.locked)
- end
- end
+ it "artifact has pipeline's locked status" do
+ subject
- context 'when ci_update_unlocked_pipeline_artifacts is disabled' do
- before do
- stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false)
- end
-
- it 'artifact has unknown locked status' do
- subject
+ artifact = Ci::PipelineArtifact.first
- artifact = Ci::PipelineArtifact.first
-
- expect(artifact.locked).to eq('unknown')
- end
+ expect(artifact.locked).to eq(pipeline.locked)
end
end
diff --git a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb
index 75233248113..5d854b61f14 100644
--- a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb
+++ b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb
@@ -51,28 +51,12 @@ RSpec.describe ::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService do
end
end
- context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do
- it "artifact has pipeline's locked status" do
- subject
-
- artifact = Ci::PipelineArtifact.first
-
- expect(artifact.locked).to eq(head_pipeline.locked)
- end
- end
-
- context 'when ci_update_unlocked_pipeline_artifacts is disabled' do
- before do
- stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false)
- end
-
- it 'artifact has unknown locked status' do
- subject
+ it "artifact has pipeline's locked status" do
+ subject
- artifact = Ci::PipelineArtifact.first
+ artifact = Ci::PipelineArtifact.first
- expect(artifact.locked).to eq('unknown')
- end
+ expect(artifact.locked).to eq(head_pipeline.locked)
end
it 'does not persist the same artifact twice' do
diff --git a/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb b/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb
index eb664043567..47e8766c215 100644
--- a/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb
+++ b/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService do
+RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_shared_state do
let(:service) { described_class.new }
describe '.execute' do
@@ -85,6 +85,36 @@ RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService do
is_expected.to eq(0)
end
end
+
+ context 'with unlocked pipeline artifacts' do
+ let_it_be(:not_expired_artifact) { create(:ci_pipeline_artifact, :artifact_unlocked, expire_at: 2.days.from_now) }
+
+ before do
+ create_list(:ci_pipeline_artifact, 2, :artifact_unlocked, expire_at: 1.week.ago)
+ allow(service).to receive(:legacy_destroy_pipeline_artifacts)
+ end
+
+ it 'destroys all expired artifacts' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
+ expect(not_expired_artifact.reload).to be_present
+ end
+
+ context 'when the loop limit is reached' do
+ before do
+ stub_const('::Ci::PipelineArtifacts::DestroyAllExpiredService::LOOP_LIMIT', 1)
+ stub_const('::Ci::PipelineArtifacts::DestroyAllExpiredService::BATCH_SIZE', 1)
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-1)
+ expect(not_expired_artifact.reload).to be_present
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
+ end
+ end
end
describe '.destroy_artifacts_batch' do
diff --git a/spec/services/ci/runners/register_runner_service_spec.rb b/spec/services/ci/runners/register_runner_service_spec.rb
index 6d7b39de21e..2d1b109072f 100644
--- a/spec/services/ci/runners/register_runner_service_spec.rb
+++ b/spec/services/ci/runners/register_runner_service_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:runner) { execute.payload[:runner] }
before do
- stub_feature_flags(runner_registration_control: false)
stub_application_setting(runners_registration_token: registration_token)
stub_application_setting(valid_runner_registrars: ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
end
@@ -166,25 +165,9 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
stub_application_setting(valid_runner_registrars: ['group'])
end
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
-
- it 'returns 403 error' do
- expect(execute).to be_error
- expect(execute.http_status).to eq :forbidden
- end
- end
-
- context 'when feature flag is disabled' do
- it 'registers the runner' do
- expect(execute).to be_success
-
- expect(runner).to be_an_instance_of(::Ci::Runner)
- expect(runner.errors).to be_empty
- expect(runner.active).to be true
- end
+ it 'returns 403 error' do
+ expect(execute).to be_error
+ expect(execute.http_status).to eq :forbidden
end
end
end
@@ -244,24 +227,8 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
stub_application_setting(valid_runner_registrars: ['project'])
end
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
-
- it 'returns error response' do
- is_expected.to be_error
- end
- end
-
- context 'when feature flag is disabled' do
- it 'registers the runner' do
- expect(execute).to be_success
-
- expect(runner).to be_an_instance_of(::Ci::Runner)
- expect(runner.errors).to be_empty
- expect(runner.active).to be true
- end
+ it 'returns error response' do
+ is_expected.to be_error
end
end
end
diff --git a/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb b/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb
index 0d2e237c87b..1f44612947b 100644
--- a/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb
+++ b/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb
@@ -47,7 +47,11 @@ RSpec.describe ::Ci::Runners::SetRunnerAssociatedProjectsService, '#execute' do
it 'reassigns associated projects and returns success response' do
expect(execute).to be_success
- expect(runner.reload.projects.ids).to eq([owner_project.id] + project_ids)
+
+ runner.reload
+
+ expect(runner.owner_project).to eq(owner_project)
+ expect(runner.projects.ids).to match_array([owner_project.id] + project_ids)
end
end
@@ -56,7 +60,11 @@ RSpec.describe ::Ci::Runners::SetRunnerAssociatedProjectsService, '#execute' do
it 'reassigns associated projects and returns success response' do
expect(execute).to be_success
- expect(runner.reload.projects.ids).to eq([owner_project.id] + project_ids)
+
+ runner.reload
+
+ expect(runner.owner_project).to eq(owner_project)
+ expect(runner.projects.ids).to match_array([owner_project.id] + project_ids)
end
end
end
diff --git a/spec/services/ci/unlock_artifacts_service_spec.rb b/spec/services/ci/unlock_artifacts_service_spec.rb
index 776019f03f8..f21afc7fe9e 100644
--- a/spec/services/ci/unlock_artifacts_service_spec.rb
+++ b/spec/services/ci/unlock_artifacts_service_spec.rb
@@ -5,15 +5,11 @@ require 'spec_helper'
RSpec.describe Ci::UnlockArtifactsService do
using RSpec::Parameterized::TableSyntax
- where(:tag, :ci_update_unlocked_job_artifacts, :ci_update_unlocked_pipeline_artifacts) do
- false | false | false
- false | true | false
- true | false | false
- true | true | false
- false | false | true
- false | true | true
- true | false | true
- true | true | true
+ where(:tag, :ci_update_unlocked_job_artifacts) do
+ false | false
+ false | true
+ true | false
+ true | true
end
with_them do
@@ -35,8 +31,7 @@ RSpec.describe Ci::UnlockArtifactsService do
before do
stub_const("#{described_class}::BATCH_SIZE", 1)
- stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts,
- ci_update_unlocked_pipeline_artifacts: ci_update_unlocked_pipeline_artifacts)
+ stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts)
end
describe '#execute' do
@@ -80,7 +75,7 @@ RSpec.describe Ci::UnlockArtifactsService do
end
it 'unlocks pipeline artifact records' do
- if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts
+ if ci_update_unlocked_job_artifacts
expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1)
else
expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count }
@@ -122,7 +117,7 @@ RSpec.describe Ci::UnlockArtifactsService do
end
it 'unlocks pipeline artifact records' do
- if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts
+ if ci_update_unlocked_job_artifacts
expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1)
else
expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count }
diff --git a/spec/services/clusters/applications/destroy_service_spec.rb b/spec/services/clusters/applications/destroy_service_spec.rb
deleted file mode 100644
index 7306256e68e..00000000000
--- a/spec/services/clusters/applications/destroy_service_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Applications::DestroyService, '#execute' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:user) { create(:user) }
- let(:params) { { application: 'prometheus' } }
- let(:service) { described_class.new(cluster, user, params) }
- let(:test_request) { double }
- let(:worker_class) { Clusters::Applications::UninstallWorker }
-
- subject { service.execute(test_request) }
-
- before do
- allow(worker_class).to receive(:perform_async)
- end
-
- context 'application is not installed' do
- it 'raises Clusters::Applications::BaseService::InvalidApplicationError' do
- expect(worker_class).not_to receive(:perform_async)
-
- expect { subject }
- .to raise_exception { Clusters::Applications::BaseService::InvalidApplicationError }
- .and not_change { Clusters::Applications::Prometheus.count }
- .and not_change { Clusters::Applications::Prometheus.with_status(:scheduled).count }
- end
- end
-
- context 'application is installed' do
- context 'application is schedulable' do
- let!(:application) do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
- end
-
- it 'makes application scheduled!' do
- subject
-
- expect(application.reload).to be_scheduled
- end
-
- it 'schedules UninstallWorker' do
- expect(worker_class).to receive(:perform_async).with(application.name, application.id)
-
- subject
- end
- end
-
- context 'application is not schedulable' do
- let!(:application) do
- create(:clusters_applications_prometheus, :updating, cluster: cluster)
- end
-
- it 'raises StateMachines::InvalidTransition' do
- expect(worker_class).not_to receive(:perform_async)
-
- expect { subject }
- .to raise_exception { StateMachines::InvalidTransition }
- .and not_change { Clusters::Applications::Prometheus.with_status(:scheduled).count }
- end
- end
- end
-end
diff --git a/spec/services/clusters/applications/uninstall_service_spec.rb b/spec/services/clusters/applications/uninstall_service_spec.rb
deleted file mode 100644
index bfe38ba670d..00000000000
--- a/spec/services/clusters/applications/uninstall_service_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Applications::UninstallService, '#execute' do
- let(:application) { create(:clusters_applications_prometheus, :scheduled) }
- let(:service) { described_class.new(application) }
- let(:helm_client) { instance_double(Gitlab::Kubernetes::Helm::API) }
- let(:worker_class) { Clusters::Applications::WaitForUninstallAppWorker }
-
- before do
- allow(service).to receive(:helm_api).and_return(helm_client)
- end
-
- context 'when there are no errors' do
- before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand))
- allow(worker_class).to receive(:perform_in).and_return(nil)
- end
-
- it 'make the application to be uninstalling' do
- expect(application.cluster).not_to be_nil
- service.execute
-
- expect(application).to be_uninstalling
- end
-
- it 'schedule async installation status check' do
- expect(worker_class).to receive(:perform_in).once
-
- service.execute
- end
- end
-
- context 'when k8s cluster communication fails' do
- let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
-
- before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
- end
-
- include_examples 'logs kubernetes errors' do
- let(:error_name) { 'Kubeclient::HttpError' }
- let(:error_message) { 'system failure' }
- let(:error_code) { 500 }
- end
-
- it 'make the application errored' do
- service.execute
-
- expect(application).to be_uninstall_errored
- expect(application.status_reason).to match('Kubernetes error: 500')
- end
- end
-
- context 'a non kubernetes error happens' do
- let(:application) { create(:clusters_applications_prometheus, :scheduled) }
- let(:error) { StandardError.new('something bad happened') }
-
- before do
- expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
- end
-
- include_examples 'logs kubernetes errors' do
- let(:error_name) { 'StandardError' }
- let(:error_message) { 'something bad happened' }
- let(:error_code) { nil }
- end
-
- it 'make the application errored' do
- service.execute
-
- expect(application).to be_uninstall_errored
- expect(application.status_reason).to eq('Failed to uninstall.')
- end
- end
-end
diff --git a/spec/services/design_management/move_designs_service_spec.rb b/spec/services/design_management/move_designs_service_spec.rb
index c8abce77325..519378a8dd4 100644
--- a/spec/services/design_management/move_designs_service_spec.rb
+++ b/spec/services/design_management/move_designs_service_spec.rb
@@ -88,23 +88,24 @@ RSpec.describe DesignManagement::MoveDesignsService do
expect(subject).to be_success
- expect(issue.designs.ordered).to eq([
- # Existing designs which already had a relative_position set.
- # These should stay at the beginning, in the same order.
- other_design1,
- other_design2,
-
- # The designs we're passing into the service.
- # These should be placed between the existing designs, in the correct order.
- previous_design,
- current_design,
- next_design,
-
- # Existing designs which didn't have a relative_position set.
- # These should be placed at the end, in the order of their IDs.
- other_design3,
- other_design4
- ])
+ expect(issue.designs.ordered).to eq(
+ [
+ # Existing designs which already had a relative_position set.
+ # These should stay at the beginning, in the same order.
+ other_design1,
+ other_design2,
+
+ # The designs we're passing into the service.
+ # These should be placed between the existing designs, in the correct order.
+ previous_design,
+ current_design,
+ next_design,
+
+ # Existing designs which didn't have a relative_position set.
+ # These should be placed at the end, in the order of their IDs.
+ other_design3,
+ other_design4
+ ])
end
end
end
diff --git a/spec/services/git/tag_hooks_service_spec.rb b/spec/services/git/tag_hooks_service_spec.rb
index 2d50c64d63c..01a0d2e8600 100644
--- a/spec/services/git/tag_hooks_service_spec.rb
+++ b/spec/services/git/tag_hooks_service_spec.rb
@@ -104,12 +104,12 @@ RSpec.describe Git::TagHooksService, :service do
id: commit.id,
message: commit.safe_message,
url: [
- Gitlab.config.gitlab.url,
- project.namespace.to_param,
- project.to_param,
- '-',
- 'commit',
- commit.id
+ Gitlab.config.gitlab.url,
+ project.namespace.to_param,
+ project.to_param,
+ '-',
+ 'commit',
+ commit.id
].join('/')
)
end
diff --git a/spec/services/google_cloud/enable_cloudsql_service_spec.rb b/spec/services/google_cloud/enable_cloudsql_service_spec.rb
index f267f6d3bc2..aa6d2402d7c 100644
--- a/spec/services/google_cloud/enable_cloudsql_service_spec.rb
+++ b/spec/services/google_cloud/enable_cloudsql_service_spec.rb
@@ -4,15 +4,29 @@ require 'spec_helper'
RSpec.describe GoogleCloud::EnableCloudsqlService do
let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:params) do
+ {
+ google_oauth2_token: 'mock-token',
+ gcp_project_id: 'mock-gcp-project-id',
+ environment_name: 'main'
+ }
+ end
- subject(:result) { described_class.new(project).execute }
+ subject(:result) { described_class.new(project, user, params).execute }
context 'when a project does not have any GCP_PROJECT_IDs configured' do
- it 'returns error' do
- message = 'No GCP projects found. Configure a service account or GCP_PROJECT_ID CI variable.'
+ it 'creates GCP_PROJECT_ID project var' do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
+ expect(instance).to receive(:enable_cloud_sql_admin).with('mock-gcp-project-id')
+ expect(instance).to receive(:enable_compute).with('mock-gcp-project-id')
+ expect(instance).to receive(:enable_service_networking).with('mock-gcp-project-id')
+ end
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq(message)
+ expect(result[:status]).to eq(:success)
+ expect(project.variables.count).to eq(1)
+ expect(project.variables.first.key).to eq('GCP_PROJECT_ID')
+ expect(project.variables.first.value).to eq('mock-gcp-project-id')
end
end
@@ -30,6 +44,9 @@ RSpec.describe GoogleCloud::EnableCloudsqlService do
it 'enables cloudsql, compute and service networking Google APIs', :aggregate_failures do
expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
+ expect(instance).to receive(:enable_cloud_sql_admin).with('mock-gcp-project-id')
+ expect(instance).to receive(:enable_compute).with('mock-gcp-project-id')
+ expect(instance).to receive(:enable_service_networking).with('mock-gcp-project-id')
expect(instance).to receive(:enable_cloud_sql_admin).with('prj-prod')
expect(instance).to receive(:enable_compute).with('prj-prod')
expect(instance).to receive(:enable_service_networking).with('prj-prod')
@@ -44,6 +61,9 @@ RSpec.describe GoogleCloud::EnableCloudsqlService do
context 'when Google APIs raise an error' do
it 'returns error result' do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
+ allow(instance).to receive(:enable_cloud_sql_admin).with('mock-gcp-project-id')
+ allow(instance).to receive(:enable_compute).with('mock-gcp-project-id')
+ allow(instance).to receive(:enable_service_networking).with('mock-gcp-project-id')
allow(instance).to receive(:enable_cloud_sql_admin).with('prj-prod')
allow(instance).to receive(:enable_compute).with('prj-prod')
allow(instance).to receive(:enable_service_networking).with('prj-prod')
diff --git a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb b/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb
index e0a622bfa4a..0a0f05ab4be 100644
--- a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb
+++ b/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb
@@ -8,17 +8,19 @@ RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
let(:list_databases_empty) { Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: []) }
let(:list_users_empty) { Google::Apis::SqladminV1beta4::ListUsersResponse.new(items: []) }
let(:list_databases) do
- Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: [
- Google::Apis::SqladminV1beta4::Database.new(name: 'postgres'),
- Google::Apis::SqladminV1beta4::Database.new(name: 'main_db')
- ])
+ Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(
+ items: [
+ Google::Apis::SqladminV1beta4::Database.new(name: 'postgres'),
+ Google::Apis::SqladminV1beta4::Database.new(name: 'main_db')
+ ])
end
let(:list_users) do
- Google::Apis::SqladminV1beta4::ListUsersResponse.new(items: [
- Google::Apis::SqladminV1beta4::User.new(name: 'postgres'),
- Google::Apis::SqladminV1beta4::User.new(name: 'main_user')
- ])
+ Google::Apis::SqladminV1beta4::ListUsersResponse.new(
+ items: [
+ Google::Apis::SqladminV1beta4::User.new(name: 'postgres'),
+ Google::Apis::SqladminV1beta4::User.new(name: 'main_user')
+ ])
end
context 'when unauthorized user triggers worker' do
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 9288793cc7a..36e868fa5f1 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -117,12 +117,6 @@ RSpec.describe Groups::DestroyService do
Sidekiq::Testing.fake! { destroy_group(group, user, true) }
end
- after do
- # Clean up stale directories
- TestEnv.rm_storage_dir(project.repository_storage, group.path)
- TestEnv.rm_storage_dir(project.repository_storage, remove_path)
- end
-
it 'verifies original paths and projects still exist' do
expect(TestEnv.storage_dir_exists?(project.repository_storage, group.path)).to be_truthy
expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_falsey
diff --git a/spec/services/groups/import_export/import_service_spec.rb b/spec/services/groups/import_export/import_service_spec.rb
index a4dfec4723a..66b50704939 100644
--- a/spec/services/groups/import_export/import_service_spec.rb
+++ b/spec/services/groups/import_export/import_service_spec.rb
@@ -86,6 +86,16 @@ RSpec.describe Groups::ImportExport::ImportService do
service.execute
end
+
+ it 'tracks the event' do
+ service.execute
+
+ expect_snowplow_event(
+ category: 'Groups::ImportExport::ImportService',
+ action: 'create',
+ label: 'import_group_from_file'
+ )
+ end
end
context 'with a ndjson file' do
@@ -105,12 +115,11 @@ RSpec.describe Groups::ImportExport::ImportService do
context 'when importing a ndjson export' do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let(:service) { described_class.new(group: group, user: user) }
let(:import_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') }
let(:import_logger) { instance_double(Gitlab::Import::Logger) }
- subject { service.execute }
+ subject(:service) { described_class.new(group: group, user: user) }
before do
ImportExportUpload.create!(group: group, import_file: import_file)
@@ -128,11 +137,21 @@ RSpec.describe Groups::ImportExport::ImportService do
end
it 'imports group structure successfully' do
- expect(subject).to be_truthy
+ expect(service.execute).to be_truthy
+ end
+
+ it 'tracks the event' do
+ service.execute
+
+ expect_snowplow_event(
+ category: 'Groups::ImportExport::ImportService',
+ action: 'create',
+ label: 'import_group_from_file'
+ )
end
it 'removes import file' do
- subject
+ service.execute
expect(group.import_export_upload.import_file.file).to be_nil
end
@@ -141,7 +160,7 @@ RSpec.describe Groups::ImportExport::ImportService do
shared = Gitlab::ImportExport::Shared.new(group)
allow(Gitlab::ImportExport::Shared).to receive(:new).and_return(shared)
- subject
+ service.execute
expect(FileUtils).to have_received(:rm_rf).with(shared.base_path)
expect(Dir.exist?(shared.base_path)).to eq(false)
@@ -154,7 +173,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: 'Group Import/Export: Import succeeded'
).once
- subject
+ service.execute
end
end
@@ -166,7 +185,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: a_string_including('Errors occurred')
)
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
it 'tracks the error' do
@@ -177,7 +196,7 @@ RSpec.describe Groups::ImportExport::ImportService do
expect(param.message).to include 'does not have required permissions for'
end
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
end
@@ -191,7 +210,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: a_string_including('Errors occurred')
).once
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
end
@@ -203,7 +222,7 @@ RSpec.describe Groups::ImportExport::ImportService do
end
it 'successfully imports the group' do
- expect(subject).to be_truthy
+ expect(service.execute).to be_truthy
end
it 'logs the import success' do
@@ -215,7 +234,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: 'Group Import/Export: Import succeeded'
)
- subject
+ service.execute
end
end
end
@@ -223,12 +242,11 @@ RSpec.describe Groups::ImportExport::ImportService do
context 'when importing a json export' do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let(:service) { described_class.new(group: group, user: user) }
let(:import_file) { fixture_file_upload('spec/fixtures/legacy_group_export.tar.gz') }
let(:import_logger) { instance_double(Gitlab::Import::Logger) }
- subject { service.execute }
+ subject(:service) { described_class.new(group: group, user: user) }
before do
ImportExportUpload.create!(group: group, import_file: import_file)
@@ -246,11 +264,21 @@ RSpec.describe Groups::ImportExport::ImportService do
end
it 'imports group structure successfully' do
- expect(subject).to be_truthy
+ expect(service.execute).to be_truthy
+ end
+
+ it 'tracks the event' do
+ service.execute
+
+ expect_snowplow_event(
+ category: 'Groups::ImportExport::ImportService',
+ action: 'create',
+ label: 'import_group_from_file'
+ )
end
it 'removes import file' do
- subject
+ service.execute
expect(group.import_export_upload.import_file.file).to be_nil
end
@@ -259,7 +287,7 @@ RSpec.describe Groups::ImportExport::ImportService do
shared = Gitlab::ImportExport::Shared.new(group)
allow(Gitlab::ImportExport::Shared).to receive(:new).and_return(shared)
- subject
+ service.execute
expect(FileUtils).to have_received(:rm_rf).with(shared.base_path)
expect(Dir.exist?(shared.base_path)).to eq(false)
@@ -272,7 +300,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: 'Group Import/Export: Import succeeded'
).once
- subject
+ service.execute
end
end
@@ -284,7 +312,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: a_string_including('Errors occurred')
)
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
it 'tracks the error' do
@@ -295,7 +323,7 @@ RSpec.describe Groups::ImportExport::ImportService do
expect(param.message).to include 'does not have required permissions for'
end
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
end
@@ -309,7 +337,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: a_string_including('Errors occurred')
).once
- expect { subject }.to raise_error(Gitlab::ImportExport::Error)
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
end
@@ -321,7 +349,7 @@ RSpec.describe Groups::ImportExport::ImportService do
end
it 'successfully imports the group' do
- expect(subject).to be_truthy
+ expect(service.execute).to be_truthy
end
it 'logs the import success' do
@@ -333,7 +361,7 @@ RSpec.describe Groups::ImportExport::ImportService do
message: 'Group Import/Export: Import succeeded'
)
- subject
+ service.execute
end
end
end
diff --git a/spec/services/import/github/cancel_project_import_service_spec.rb b/spec/services/import/github/cancel_project_import_service_spec.rb
new file mode 100644
index 00000000000..77b8771ee65
--- /dev/null
+++ b/spec/services/import/github/cancel_project_import_service_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::Github::CancelProjectImportService do
+ subject(:import_cancel) { described_class.new(project, project.owner) }
+
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project, :import_started, import_type: 'github', import_url: 'https://fake.url') }
+
+ describe '.execute' do
+ context 'when user is an owner' do
+ context 'when import is in progress' do
+ it 'update import state to be canceled' do
+ expect(import_cancel.execute).to eq({ status: :success, project: project })
+ end
+ end
+
+ context 'when import is finished' do
+ let(:expected_result) do
+ {
+ status: :error,
+ http_status: :bad_request,
+ message: 'The import cannot be canceled because it is finished'
+ }
+ end
+
+ before do
+ project.import_state.finish!
+ end
+
+ it 'returns error' do
+ expect(import_cancel.execute).to eq(expected_result)
+ end
+ end
+ end
+
+ context 'when user is not allowed to read project' do
+ it 'returns 404' do
+ expect(described_class.new(project, user).execute)
+ .to eq({ status: :error, http_status: :not_found, message: 'Not Found' })
+ end
+ end
+
+ context 'when user is not allowed to cancel project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns 403' do
+ expect(described_class.new(project, user).execute)
+ .to eq({ status: :error, http_status: :forbidden, message: 'Unauthorized access' })
+ end
+ end
+ end
+end
diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb
index 67a2c237e43..38d84009f08 100644
--- a/spec/services/import/github_service_spec.rb
+++ b/spec/services/import/github_service_spec.rb
@@ -6,7 +6,16 @@ RSpec.describe Import::GithubService do
let_it_be(:user) { create(:user) }
let_it_be(:token) { 'complex-token' }
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(:settings) { instance_double(Gitlab::GithubImport::Settings) }
+ let(:optional_stages) { nil }
+ let(:params) do
+ {
+ repo_id: 123,
+ new_name: 'new_repo',
+ target_namespace: 'root',
+ optional_stages: optional_stages
+ }
+ end
subject(:github_importer) { described_class.new(client, user, params) }
@@ -16,6 +25,12 @@ RSpec.describe Import::GithubService do
shared_examples 'handles errors' do |klass|
let(:client) { klass.new(token) }
+ let(:project_double) { instance_double(Project, persisted?: true) }
+
+ before do
+ allow(Gitlab::GithubImport::Settings).to receive(:new).with(project_double).and_return(settings)
+ allow(settings).to receive(:write).with(optional_stages)
+ end
context 'do not raise an exception on input error' do
let(:exception) { Octokit::ClientError.new(status: 404, body: 'Not Found') }
@@ -62,13 +77,14 @@ RSpec.describe Import::GithubService do
expect(client).to receive(:repository).and_return(repository_double)
allow_next_instance_of(Gitlab::LegacyGithubImport::ProjectCreator) do |creator|
- allow(creator).to receive(:execute).and_return(double(persisted?: true))
+ allow(creator).to receive(:execute).and_return(project_double)
end
end
context 'when there is no repository size limit defined' do
it 'skips the check and succeeds' do
expect(subject.execute(access_params, :github)).to include(status: :success)
+ expect(settings).to have_received(:write).with(nil)
end
end
@@ -81,6 +97,7 @@ RSpec.describe Import::GithubService do
it 'succeeds when the repository is smaller than the limit' do
expect(subject.execute(access_params, :github)).to include(status: :success)
+ expect(settings).to have_received(:write).with(nil)
end
it 'returns error when the repository is larger than the limit' do
@@ -100,6 +117,7 @@ RSpec.describe Import::GithubService do
context 'when application size limit is defined' do
it 'succeeds when the repository is smaller than the limit' do
expect(subject.execute(access_params, :github)).to include(status: :success)
+ expect(settings).to have_received(:write).with(nil)
end
it 'returns error when the repository is larger than the limit' do
@@ -109,6 +127,22 @@ RSpec.describe Import::GithubService do
end
end
end
+
+ context 'when optional stages params present' do
+ let(:optional_stages) do
+ {
+ single_endpoint_issue_events_import: true,
+ single_endpoint_notes_import: 'false',
+ attachments_import: false
+ }
+ end
+
+ it 'saves optional stages choice to import_data' do
+ subject.execute(access_params, :github)
+
+ expect(settings).to have_received(:write).with(optional_stages)
+ end
+ end
end
context 'when import source is disabled' do
@@ -170,7 +204,7 @@ RSpec.describe Import::GithubService do
include_examples 'handles errors', Gitlab::GithubImport::Client
end
- context 'when remove_legacy_github_client feature flag is enabled' do
+ context 'when remove_legacy_github_client feature flag is disabled' do
before do
stub_feature_flags(remove_legacy_github_client: false)
end
diff --git a/spec/services/import/gitlab_projects/create_project_service_spec.rb b/spec/services/import/gitlab_projects/create_project_service_spec.rb
index 0da897448b8..59c384bad3c 100644
--- a/spec/services/import/gitlab_projects/create_project_service_spec.rb
+++ b/spec/services/import/gitlab_projects/create_project_service_spec.rb
@@ -139,10 +139,11 @@ RSpec.describe ::Import::GitlabProjects::CreateProjectService, :aggregate_failur
expect(response.http_status).to eq(:bad_request)
expect(response.message)
.to eq(%{Project namespace path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'})
- expect(response.payload).to eq(other_errors: [
- %{Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'},
- %{Path must not start or end with a special character and must not contain consecutive special characters.}
- ])
+ expect(response.payload).to eq(
+ other_errors: [
+ %{Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'},
+ %{Path must not start or end with a special character and must not contain consecutive special characters.}
+ ])
end
end
end
diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb
index ac44bc4608c..851b21e1227 100644
--- a/spec/services/incident_management/incidents/create_service_spec.rb
+++ b/spec/services/incident_management/incidents/create_service_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
it 'responds with errors' do
expect(create_incident).to be_error
- expect(create_incident.message).to eq("Title can't be blank")
+ expect(create_incident.errors).to contain_exactly("Title can't be blank")
end
it 'result payload contains an Issue object' do
@@ -98,7 +98,7 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
it 'responds with errors' do
expect(create_incident).to be_error
- expect(create_incident.message).to eq('Hosts hosts array is over 255 chars')
+ expect(create_incident.errors).to contain_exactly('Hosts hosts array is over 255 chars')
end
end
end
diff --git a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
index 761cc5c92ea..e8208c410d5 100644
--- a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
+++ b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService do
+RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService, factory_default: :keep do
+ let_it_be(:project) { create_default(:project) }
let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, :triggered) }
let_it_be(:user_with_permissions) { create(:user) }
@@ -10,7 +11,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
let(:issue) { escalation_status.issue }
let(:status) { :acknowledged }
let(:params) { { status: status } }
- let(:service) { IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService.new(issue, current_user, params) }
+ let(:service) { described_class.new(issue, current_user, params) }
subject(:result) { service.execute }
@@ -71,9 +72,17 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
end
end
- context 'when called without params' do
+ context 'when called nil params' do
let(:params) { nil }
+ it 'raises an exception' do
+ expect { result }.to raise_error NoMethodError
+ end
+ end
+
+ context 'when called without params' do
+ let(:params) { {} }
+
it_behaves_like 'successful response', {}
end
diff --git a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
index fb536df5d17..572b1a20166 100644
--- a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService do
it 'responds with error' do
expect(execute).to be_error
- expect(execute.message).to eq("Title can't be blank")
+ expect(execute.errors).to contain_exactly("Title can't be blank")
end
end
end
diff --git a/spec/services/incident_management/timeline_events/create_service_spec.rb b/spec/services/incident_management/timeline_events/create_service_spec.rb
index b999403e168..a7f448c825f 100644
--- a/spec/services/incident_management/timeline_events/create_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/create_service_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
context 'when error occurs during creation' do
let(:args) { {} }
- it_behaves_like 'error response', "Occurred at can't be blank, Note can't be blank, and Note html can't be blank"
+ it_behaves_like 'error response', "Occurred at can't be blank and Timeline text can't be blank"
end
context 'with default action' do
@@ -84,50 +84,6 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
expect(result.action).to eq(IncidentManagement::TimelineEvents::DEFAULT_ACTION)
end
- end
-
- context 'with non_default action' do
- it_behaves_like 'success response'
-
- it 'matches the action from arguments', :aggregate_failures do
- result = execute.payload[:timeline_event]
-
- expect(result.action).to eq(args[:action])
- end
- end
-
- context 'with editable param' do
- let(:args) do
- {
- note: 'note',
- occurred_at: Time.current,
- action: 'new comment',
- promoted_from_note: comment,
- editable: editable
- }
- end
-
- context 'when editable is true' do
- let(:editable) { true }
-
- it_behaves_like 'success response'
- end
-
- context 'when editable is false' do
- let(:editable) { false }
-
- it_behaves_like 'success response'
- end
- end
-
- it 'successfully creates a database record', :aggregate_failures do
- expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
- end
-
- context 'when incident_timeline feature flag is enabled' do
- before do
- stub_feature_flags(incident_timeline: project)
- end
it 'creates a system note' do
expect { execute }.to change { incident.notes.reload.count }.by(1)
@@ -168,14 +124,42 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
end
end
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
+ context 'with non_default action' do
+ it_behaves_like 'success response'
+
+ it 'matches the action from arguments', :aggregate_failures do
+ result = execute.payload[:timeline_event]
+
+ expect(result.action).to eq(args[:action])
end
+ end
- it 'does not create a system note' do
- expect { execute }.not_to change { incident.notes.reload.count }
+ context 'with editable param' do
+ let(:args) do
+ {
+ note: 'note',
+ occurred_at: Time.current,
+ action: 'new comment',
+ promoted_from_note: comment,
+ editable: editable
+ }
+ end
+
+ context 'when editable is true' do
+ let(:editable) { true }
+
+ it_behaves_like 'success response'
end
+
+ context 'when editable is false' do
+ let(:editable) { false }
+
+ it_behaves_like 'success response'
+ end
+ end
+
+ it 'successfully creates a database record', :aggregate_failures do
+ expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
end
end
diff --git a/spec/services/incident_management/timeline_events/destroy_service_spec.rb b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
index 09026f87116..e1b258960ae 100644
--- a/spec/services/incident_management/timeline_events/destroy_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
@@ -48,10 +48,10 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do
timeline_event.errors.add(:note, 'cannot be removed')
end
- it_behaves_like 'error response', 'Note cannot be removed'
+ it_behaves_like 'error response', 'Timeline text cannot be removed'
end
- context 'success response' do
+ context 'with success response' do
it 'successfully returns the timeline event', :aggregate_failures do
expect(execute).to be_success
@@ -60,27 +60,11 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do
expect(result.id).to eq(timeline_event.id)
end
- it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_deleted
- end
-
- context 'when incident_timeline feature flag is enabled' do
- before do
- stub_feature_flags(incident_timeline: project)
- end
-
it 'creates a system note' do
expect { execute }.to change { incident.notes.reload.count }.by(1)
end
- end
-
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
- end
- it 'does not create a system note' do
- expect { execute }.not_to change { incident.notes.reload.count }
- end
+ it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_deleted
end
end
end
diff --git a/spec/services/incident_management/timeline_events/update_service_spec.rb b/spec/services/incident_management/timeline_events/update_service_spec.rb
index f612c72e2a8..5d8518cf2ef 100644
--- a/spec/services/incident_management/timeline_events/update_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/update_service_spec.rb
@@ -12,10 +12,6 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
let(:params) { { note: 'Updated note', occurred_at: occurred_at } }
let(:current_user) { user }
- before do
- stub_feature_flags(incident_timeline: project)
- end
-
describe '#execute' do
shared_examples 'successful response' do
it 'responds with success', :aggregate_failures do
@@ -70,16 +66,6 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
it_behaves_like 'passing the correct was_changed value', :occurred_at_and_note
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
- end
-
- it 'does not add a system note' do
- expect { execute }.not_to change { incident.notes }
- end
- end
-
context 'when note is nil' do
let(:params) { { occurred_at: occurred_at } }
@@ -98,7 +84,7 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
context 'when note is blank' do
let(:params) { { note: '', occurred_at: occurred_at } }
- it_behaves_like 'error response', "Note can't be blank"
+ it_behaves_like 'error response', "Timeline text can't be blank"
end
context 'when occurred_at is nil' do
diff --git a/spec/services/issuable/process_assignees_spec.rb b/spec/services/issuable/process_assignees_spec.rb
index 45d57a1772a..9e909b68172 100644
--- a/spec/services/issuable/process_assignees_spec.rb
+++ b/spec/services/issuable/process_assignees_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Issuable::ProcessAssignees do
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(5 7 9).sort)
+ expect(result).to contain_exactly(5, 7, 9)
end
it 'combines other ids when assignee_ids is nil' do
@@ -23,7 +23,7 @@ RSpec.describe Issuable::ProcessAssignees do
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(1 2 3 5 11 12).sort)
+ expect(result).to contain_exactly(1, 2, 3, 5, 11, 12)
end
it 'combines other ids when both add_assignee_ids and remove_assignee_ids are not empty' do
@@ -34,7 +34,7 @@ RSpec.describe Issuable::ProcessAssignees do
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(1 2 3 5 6 12).sort)
+ expect(result).to contain_exactly(1, 2, 3, 5, 6, 12)
end
it 'combines other ids when remove_assignee_ids is not empty' do
@@ -45,7 +45,7 @@ RSpec.describe Issuable::ProcessAssignees do
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(1 2 3 5 12).sort)
+ expect(result).to contain_exactly(1, 2, 3, 5, 12)
end
it 'combines other ids when add_assignee_ids is not empty' do
@@ -56,7 +56,7 @@ RSpec.describe Issuable::ProcessAssignees do
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(1 2 4 3 5 6 11 12).sort)
+ expect(result).to contain_exactly(1, 2, 4, 3, 5, 6, 11, 12)
end
it 'combines ids when existing_assignee_ids and extra_assignee_ids are omitted' do
@@ -65,7 +65,18 @@ RSpec.describe Issuable::ProcessAssignees do
remove_assignee_ids: %w(4 7 11))
result = process.execute
- expect(result.sort).to eq(%w(2 6).sort)
+ expect(result.sort).to eq([2, 6].sort)
+ end
+
+ it 'handles mixed string and integer arrays' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
+ add_assignee_ids: [2, 4, 6],
+ remove_assignee_ids: %w(4 7 11),
+ existing_assignee_ids: [1, 3, 11],
+ extra_assignee_ids: %w(2 5 12))
+ result = process.execute
+
+ expect(result).to contain_exactly(1, 2, 3, 5, 6, 12)
end
end
end
diff --git a/spec/services/issues/clone_service_spec.rb b/spec/services/issues/clone_service_spec.rb
index 435488b7f66..67f32b85350 100644
--- a/spec/services/issues/clone_service_spec.rb
+++ b/spec/services/issues/clone_service_spec.rb
@@ -36,6 +36,21 @@ RSpec.describe Issues::CloneService do
context 'issue movable' do
include_context 'user can clone issue'
+ context 'when issue creation fails' do
+ before do
+ allow_next_instance_of(Issues::CreateService) do |create_service|
+ allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error'))
+ end
+ end
+
+ it 'raises a clone error' do
+ expect { clone_service.execute(old_issue, new_project) }.to raise_error(
+ Issues::CloneService::CloneError,
+ 'some error'
+ )
+ end
+ end
+
context 'generic issue' do
let!(:new_issue) { clone_service.execute(old_issue, new_project, with_notes: with_notes) }
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 3d52dc07c4f..5fe4c693451 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Issues::CreateService do
include AfterNextHelpers
let_it_be(:group) { create(:group, :crm_enabled) }
- let_it_be_with_reload(:project) { create(:project, group: group) }
+ let_it_be_with_reload(:project) { create(:project, :public, group: group) }
let_it_be(:user) { create(:user) }
let(:spam_params) { double }
@@ -23,12 +23,27 @@ RSpec.describe Issues::CreateService do
let_it_be(:assignee) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
- let(:issue) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute }
+ let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute }
+ let(:issue) { result[:issue] }
before do
stub_spam_services
end
+ context 'when params are invalid' do
+ let(:opts) { { title: '' } }
+
+ before_all do
+ project.add_guest(assignee)
+ end
+
+ it 'returns an error service response' do
+ expect(result).to be_error
+ expect(result.errors).to include("Title can't be blank")
+ expect(issue).not_to be_persisted
+ end
+ end
+
context 'when params are valid' do
let_it_be(:labels) { create_pair(:label, project: project) }
@@ -60,6 +75,30 @@ RSpec.describe Issues::CreateService do
end
end
+ describe 'authorization' do
+ let_it_be(:project) { create(:project, :private, group: group).tap { |project| project.add_guest(user) } }
+
+ let(:opts) { { title: 'private issue', description: 'please fix' } }
+
+ context 'when the user is authorized' do
+ it 'allows the user to create an issue' do
+ expect(result).to be_success
+ expect(issue).to be_persisted
+ end
+ end
+
+ context 'when the user is not authorized' do
+ let(:user) { create(:user) }
+
+ it 'does not allow the user to create an issue' do
+ expect(result).to be_error
+ expect(result.errors).to contain_exactly('Operation not allowed')
+ expect(result.http_status).to eq(403)
+ expect(issue).to be_nil
+ end
+ end
+ end
+
it 'works if base work item types were not created yet' do
WorkItems::Type.delete_all
@@ -71,6 +110,7 @@ RSpec.describe Issues::CreateService do
it 'creates the issue with the given params' do
expect(Issuable::CommonSystemNotesService).to receive_message_chain(:new, :execute)
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue).to be_a(::Issue)
expect(issue.title).to eq('Awesome issue')
@@ -89,12 +129,13 @@ RSpec.describe Issues::CreateService do
end
context 'when a build_service is provided' do
- let(:issue) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute }
+ let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute }
let(:issue_from_builder) { WorkItem.new(project: project, title: 'Issue from builder') }
let(:build_service) { double(:build_service, execute: issue_from_builder) }
it 'uses the provided service to build the issue' do
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue).to be_a(WorkItem)
end
@@ -119,6 +160,7 @@ RSpec.describe Issues::CreateService do
end
it 'sets the correct relative position' do
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.relative_position).to be_present
expect(issue.relative_position).to be_between(issue_before.relative_position, issue_after.relative_position)
@@ -196,8 +238,10 @@ RSpec.describe Issues::CreateService do
let_it_be(:non_member) { create(:user) }
it 'filters out params that cannot be set without the :set_issue_metadata permission' do
- issue = described_class.new(project: project, current_user: non_member, params: opts, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: non_member, params: opts, spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.title).to eq('Awesome issue')
expect(issue.description).to eq('please fix')
@@ -208,8 +252,10 @@ RSpec.describe Issues::CreateService do
end
it 'can create confidential issues' do
- issue = described_class.new(project: project, current_user: non_member, params: { confidential: true }, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: non_member, params: opts.merge(confidential: true), spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue.confidential).to be_truthy
end
end
@@ -298,7 +344,7 @@ RSpec.describe Issues::CreateService do
let(:opts) do
{ title: 'Title',
description: 'Description',
- assignees: [assignee] }
+ assignee_ids: [assignee.id] }
end
it 'invalidates open issues counter for assignees when issue is assigned' do
@@ -389,7 +435,7 @@ RSpec.describe Issues::CreateService do
end
it 'schedules a namespace onboarding create action worker' do
- expect(Namespaces::OnboardingIssueCreatedWorker).to receive(:perform_async).with(project.namespace.id)
+ expect(Onboarding::IssueCreatedWorker).to receive(:perform_async).with(project.namespace.id)
issue
end
@@ -404,16 +450,20 @@ RSpec.describe Issues::CreateService do
it 'removes assignee when user id is invalid' do
opts = { title: 'Title', description: 'Description', assignee_ids: [-1] }
- issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue.assignees).to be_empty
end
it 'removes assignee when user id is 0' do
opts = { title: 'Title', description: 'Description', assignee_ids: [0] }
- issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue.assignees).to be_empty
end
@@ -421,8 +471,10 @@ RSpec.describe Issues::CreateService do
project.add_maintainer(assignee)
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
- issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue.assignees).to eq([assignee])
end
@@ -439,8 +491,10 @@ RSpec.describe Issues::CreateService do
project.update!(visibility_level: level)
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
- issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue.assignees).to be_empty
end
end
@@ -449,7 +503,7 @@ RSpec.describe Issues::CreateService do
end
it_behaves_like 'issuable record that supports quick actions' do
- let(:issuable) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params).execute }
+ let(:issuable) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params).execute[:issue] }
end
context 'Quick actions' do
@@ -472,6 +526,7 @@ RSpec.describe Issues::CreateService do
end
it 'assigns, sets milestone, and sets contact to issuable from command' do
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.assignees).to eq([assignee])
expect(issue.milestone).to eq(milestone)
@@ -493,6 +548,8 @@ RSpec.describe Issues::CreateService do
context 'with permission' do
it 'assigns contact to issue' do
group.add_reporter(user)
+
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.issue_customer_relations_contacts.last.contact).to eq(contact)
end
@@ -501,6 +558,8 @@ RSpec.describe Issues::CreateService do
context 'without permission' do
it 'does not assign contact to issue' do
group.add_guest(user)
+
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.issue_customer_relations_contacts).to be_empty
end
@@ -535,6 +594,7 @@ RSpec.describe Issues::CreateService do
end
it 'can apply labels' do
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.labels).to eq([label])
end
@@ -569,25 +629,32 @@ RSpec.describe Issues::CreateService do
end
it 'sets default title and description values if not provided' do
- issue = described_class.new(
+ result = described_class.new(
project: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
end
it 'takes params from the request over the default values' do
- issue = described_class.new(project: project, current_user: user,
- params: opts.merge(
- description: 'Custom issue description',
- title: 'My new issue'
- ),
- spam_params: spam_params).execute
+ result = described_class.new(
+ project: project,
+ current_user: user,
+ params: opts.merge(
+ description: 'Custom issue description',
+ title: 'My new issue'
+ ),
+ spam_params: spam_params
+ ).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
@@ -613,25 +680,32 @@ RSpec.describe Issues::CreateService do
end
it 'sets default title and description values if not provided' do
- issue = described_class.new(
+ result = described_class.new(
project: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
end
it 'takes params from the request over the default values' do
- issue = described_class.new(project: project, current_user: user,
- params: opts.merge(
- description: 'Custom issue description',
- title: 'My new issue'
- ),
- spam_params: spam_params).execute
+ result = described_class.new(
+ project: project,
+ current_user: user,
+ params: opts.merge(
+ description: 'Custom issue description',
+ title: 'My new issue'
+ ),
+ spam_params: spam_params
+ ).execute
+ issue = result[:issue]
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
@@ -648,6 +722,7 @@ RSpec.describe Issues::CreateService do
it 'ignores related issue if not accessible' do
expect { issue }.not_to change { IssueLink.count }
+ expect(result).to be_success
expect(issue).to be_persisted
end
@@ -658,6 +733,7 @@ RSpec.describe Issues::CreateService do
it 'adds a link to the issue' do
expect { issue }.to change { IssueLink.count }.by(1)
+ expect(result).to be_success
expect(issue).to be_persisted
expect(issue.related_issues(user)).to eq([related_issue])
end
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index 863df810d01..23180f75eb3 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -35,6 +35,23 @@ RSpec.describe Issues::MoveService do
let!(:new_issue) { move_service.execute(old_issue, new_project) }
end
+ context 'when issue creation fails' do
+ include_context 'user can move issue'
+
+ before do
+ allow_next_instance_of(Issues::CreateService) do |create_service|
+ allow(create_service).to receive(:execute).and_return(ServiceResponse.error(message: 'some error'))
+ end
+ end
+
+ it 'raises a move error' do
+ expect { move_service.execute(old_issue, new_project) }.to raise_error(
+ Issues::MoveService::MoveError,
+ 'some error'
+ )
+ end
+ end
+
context 'issue movable' do
include_context 'user can move issue'
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 634a4206d48..20b1a1f58bb 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -512,6 +512,20 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(note.note).to eq('changed the description')
end
+
+ it 'triggers GraphQL description updated subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_description_updated).with(issue).and_call_original
+
+ update_issue(description: 'Changed description')
+ end
+ end
+
+ context 'when decription is not changed' do
+ it 'does not trigger GraphQL description updated subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_description_updated)
+
+ update_issue(title: 'Changed title')
+ end
end
context 'when issue turns confidential' do
@@ -838,6 +852,24 @@ RSpec.describe Issues::UpdateService, :mailer do
service.execute(issue)
end
+ # At the moment of writting old associations are not necessary for update_task
+ # and doing this will prevent fetching associations from the DB and comparing old and new labels
+ it 'does not pass old_associations to the after_update method' do
+ params = {
+ update_task: {
+ index: 1,
+ checked: false,
+ line_source: '- [x] Task 1',
+ line_number: 1
+ }
+ }
+ service = described_class.new(project: project, current_user: user, params: params)
+
+ expect(service).to receive(:after_update).with(issue, {})
+
+ service.execute(issue)
+ end
+
it 'creates system note about task status change' do
note1 = find_note('marked the checklist item **Task 1** as completed')
note2 = find_note('marked the checklist item **Task 2** as completed')
diff --git a/spec/services/jira_connect/create_asymmetric_jwt_service_spec.rb b/spec/services/jira_connect/create_asymmetric_jwt_service_spec.rb
new file mode 100644
index 00000000000..f5359e5b643
--- /dev/null
+++ b/spec/services/jira_connect/create_asymmetric_jwt_service_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::CreateAsymmetricJwtService do
+ describe '#execute' do
+ let_it_be(:jira_connect_installation) { create(:jira_connect_installation) }
+
+ let(:service) { described_class.new(jira_connect_installation) }
+
+ subject(:jwt_token) { service.execute }
+
+ it 'raises an error' do
+ expect { jwt_token }.to raise_error(ArgumentError, 'jira_connect_installation is not a proxy installation')
+ end
+
+ context 'with proxy installation' do
+ let_it_be(:jira_connect_installation) { create(:jira_connect_installation, instance_url: 'https://gitlab.test') }
+
+ let(:public_key_id) { Atlassian::Jwt.decode(jwt_token, nil, false, algorithm: 'RS256').last['kid'] }
+ let(:public_key_cdn) { 'https://gitlab.com/-/jira_connect/public_keys/' }
+ let(:jwt_verification_claims) do
+ {
+ aud: 'https://gitlab.test/-/jira_connect',
+ iss: jira_connect_installation.client_key,
+ qsh: Atlassian::Jwt.create_query_string_hash('https://gitlab.test/-/jira_connect/events/installed', 'POST', 'https://gitlab.test/-/jira_connect')
+ }
+ end
+
+ subject(:jwt_token) { service.execute }
+
+ it 'stores the public key' do
+ expect { JiraConnect::PublicKey.find(public_key_id) }.not_to raise_error
+ end
+
+ it 'is produces a valid JWT' do
+ public_key = OpenSSL::PKey.read(JiraConnect::PublicKey.find(public_key_id).key)
+ options = jwt_verification_claims.except(:qsh).merge({ verify_aud: true, verify_iss: true, algorithm: 'RS256' })
+
+ decoded_token = Atlassian::Jwt.decode(jwt_token, public_key, true, options).first
+
+ expect(decoded_token).to eq(jwt_verification_claims.stringify_keys)
+ end
+ end
+ end
+end
diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb
index 7242b1f41f9..32580a7735f 100644
--- a/spec/services/jira_connect/sync_service_spec.rb
+++ b/spec/services/jira_connect/sync_service_spec.rb
@@ -46,10 +46,11 @@ RSpec.describe JiraConnect::SyncService do
context 'when a request returns an error' do
it 'logs the response as an error' do
- expect_next(client).to store_info([
- { 'errorMessages' => ['some error message'] },
- { 'errorMessages' => ['x'] }
- ])
+ expect_next(client).to store_info(
+ [
+ { 'errorMessages' => ['some error message'] },
+ { 'errorMessages' => ['x'] }
+ ])
expect_log(:error, { 'errorMessages' => ['some error message'] })
expect_log(:error, { 'errorMessages' => ['x'] })
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 25696ca209e..756e1cf403c 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -110,12 +110,61 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
expect(execute_service[:status]).to eq(:success)
end
end
+
+ context 'when only one user fails validations' do
+ let_it_be(:source) { create(:project, group: create(:group)) }
+ let(:user_id) { [member.id, user_invited_by_id.id] }
+
+ before do
+ # validations will fail because we try to invite them to the project as a guest
+ source.group.add_developer(member)
+ end
+
+ it 'triggers the members added event' do
+ expect(Gitlab::EventStore)
+ .to receive(:publish)
+ .with(an_instance_of(Members::MembersAddedEvent))
+ .and_call_original
+
+ expect(execute_service[:status]).to eq(:error)
+ expect(execute_service[:message])
+ .to include 'Access level should be greater than or equal to Developer inherited membership from group'
+ expect(source.users).not_to include(member)
+ expect(source.users).to include(user_invited_by_id)
+ end
+ end
+
+ context 'when all users fail validations' do
+ let_it_be(:source) { create(:project, group: create(:group)) }
+ let(:user_id) { [member.id, user_invited_by_id.id] }
+
+ before do
+ # validations will fail because we try to invite them to the project as a guest
+ source.group.add_developer(member)
+ source.group.add_developer(user_invited_by_id)
+ end
+
+ it 'does not trigger the members added event' do
+ expect(Gitlab::EventStore)
+ .not_to receive(:publish)
+ .with(an_instance_of(Members::MembersAddedEvent))
+
+ expect(execute_service[:status]).to eq(:error)
+ expect(execute_service[:message])
+ .to include 'Access level should be greater than or equal to Developer inherited membership from group'
+ expect(source.users).not_to include(member, user_invited_by_id)
+ end
+ end
end
context 'when passing no user ids' do
let(:user_id) { '' }
it 'does not add a member' do
+ expect(Gitlab::EventStore)
+ .not_to receive(:publish)
+ .with(an_instance_of(Members::MembersAddedEvent))
+
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
expect(source.users).not_to include member
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 9f0daba3327..8559c02be57 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -95,6 +95,37 @@ RSpec.describe Members::DestroyService do
end
end
+ context 'With ExclusiveLeaseHelpers' do
+ let(:service_object) { described_class.new(current_user) }
+ let!(:member) { group_project.add_developer(member_user) }
+
+ subject(:destroy_member) { service_object.execute(member, **opts) }
+
+ before do
+ group_project.add_maintainer(current_user)
+
+ allow(service_object).to receive(:in_lock) do |_, &block|
+ block.call if lock_obtained
+ end
+ end
+
+ context 'when lock is obtained' do
+ let(:lock_obtained) { true }
+
+ it 'destroys the membership' do
+ expect { destroy_member }.to change { group_project.members.count }.by(-1)
+ end
+ end
+
+ context 'when the lock can not be obtained' do
+ let(:lock_obtained) { false }
+
+ it 'does not destroy the membership' do
+ expect { destroy_member }.not_to change { group_project.members.count }
+ end
+ end
+ end
+
context 'with a member with access' do
before do
group_project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index 8f448184b45..b3c4ed4c544 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe MergeRequests::CloseService do
let(:merge_request) { create(:merge_request, assignees: [user2], author: create(:user)) }
let(:project) { merge_request.project }
let!(:todo) { create(:todo, :assigned, user: user, project: project, target: merge_request, author: user2) }
+ let(:service) { described_class.new(project: project, current_user: user) }
before do
project.add_maintainer(user)
@@ -16,18 +17,20 @@ RSpec.describe MergeRequests::CloseService do
project.add_guest(guest)
end
+ def execute
+ service.execute(merge_request)
+ end
+
describe '#execute' do
it_behaves_like 'cache counters invalidator'
it_behaves_like 'merge request reviewers cache counters invalidator'
context 'valid params' do
- let(:service) { described_class.new(project: project, current_user: user) }
-
before do
allow(service).to receive(:execute_hooks)
perform_enqueued_jobs do
- @merge_request = service.execute(merge_request)
+ @merge_request = execute
end
end
@@ -73,7 +76,7 @@ RSpec.describe MergeRequests::CloseService do
expect(metrics_service).to receive(:close)
- described_class.new(project: project, current_user: user).execute(merge_request)
+ execute
end
it 'calls the merge request activity counter' do
@@ -81,13 +84,11 @@ RSpec.describe MergeRequests::CloseService do
.to receive(:track_close_mr_action)
.with(user: user)
- described_class.new(project: project, current_user: user).execute(merge_request)
+ execute
end
it 'refreshes the number of open merge requests for a valid MR', :use_clean_rails_memory_store_caching do
- service = described_class.new(project: project, current_user: user)
-
- expect { service.execute(merge_request) }
+ expect { execute }
.to change { project.open_merge_requests_count }.from(1).to(0)
end
@@ -96,25 +97,39 @@ RSpec.describe MergeRequests::CloseService do
expect(service).to receive(:execute_for_merge_request_pipeline).with(merge_request)
end
- described_class.new(project: project, current_user: user).execute(merge_request)
+ execute
end
it 'schedules CleanupRefsService' do
expect(MergeRequests::CleanupRefsService).to receive(:schedule).with(merge_request)
- described_class.new(project: project, current_user: user).execute(merge_request)
+ execute
+ end
+
+ it 'triggers GraphQL subscription mergeRequestMergeStatusUpdated' do
+ expect(GraphqlTriggers).to receive(:merge_request_merge_status_updated).with(merge_request)
+
+ execute
end
context 'current user is not authorized to close merge request' do
+ let(:user) { guest }
+
before do
perform_enqueued_jobs do
- @merge_request = described_class.new(project: project, current_user: guest).execute(merge_request)
+ @merge_request = execute
end
end
it 'does not close the merge request' do
expect(@merge_request).to be_open
end
+
+ it 'does not trigger GraphQL subscription mergeRequestMergeStatusUpdated' do
+ expect(GraphqlTriggers).not_to receive(:merge_request_merge_status_updated)
+
+ execute
+ end
end
end
end
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index 749b30bff5f..0eefbed252b 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -34,19 +34,19 @@ RSpec.describe MergeRequests::CreateFromIssueService do
expect(result[:message]).to eq('Invalid issue iid')
end
- it 'creates a branch based on issue title', :sidekiq_might_not_need_inline do
+ it 'creates a branch based on issue title' do
service.execute
expect(target_project.repository.branch_exists?(issue.to_branch_name)).to be_truthy
end
- it 'creates a branch using passed name', :sidekiq_might_not_need_inline do
+ it 'creates a branch using passed name' do
service_with_custom_source_branch.execute
expect(target_project.repository.branch_exists?(custom_source_branch)).to be_truthy
end
- it 'creates the new_merge_request system note', :sidekiq_might_not_need_inline do
+ it 'creates the new_merge_request system note' do
expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest))
service.execute
@@ -60,7 +60,7 @@ RSpec.describe MergeRequests::CreateFromIssueService do
service.execute
end
- it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created', :sidekiq_might_not_need_inline do
+ it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do
expect_next_instance_of(MergeRequest) do |instance|
expect(instance).to receive(:valid?).at_least(:once).and_return(false)
end
@@ -81,36 +81,36 @@ RSpec.describe MergeRequests::CreateFromIssueService do
service.execute
end
- it 'creates a merge request', :sidekiq_might_not_need_inline do
+ it 'creates a merge request' do
expect { service.execute }.to change(target_project.merge_requests, :count).by(1)
end
- it 'sets the merge request author to current user and assigns them', :sidekiq_might_not_need_inline do
+ it 'sets the merge request author to current user and assigns them' do
result = service.execute
expect(result[:merge_request].author).to eq(user)
expect(result[:merge_request].assignees).to eq([user])
end
- it 'sets the merge request source branch to the new issue branch', :sidekiq_might_not_need_inline do
+ it 'sets the merge request source branch to the new issue branch' do
result = service.execute
expect(result[:merge_request].source_branch).to eq(issue.to_branch_name)
end
- it 'sets the merge request source branch to the passed branch name', :sidekiq_might_not_need_inline do
+ it 'sets the merge request source branch to the passed branch name' do
result = service_with_custom_source_branch.execute
expect(result[:merge_request].source_branch).to eq(custom_source_branch)
end
- it 'sets the merge request target branch to the project default branch', :sidekiq_might_not_need_inline do
+ it 'sets the merge request target branch to the project default branch' do
result = service.execute
expect(result[:merge_request].target_branch).to eq(target_project.default_branch)
end
- it 'executes quick actions if the build service sets them in the description', :sidekiq_might_not_need_inline do
+ it 'executes quick actions if the build service sets them in the description' do
allow(service).to receive(:merge_request).and_wrap_original do |m, *args|
m.call(*args).tap do |merge_request|
merge_request.description = "/assign #{user.to_reference}"
@@ -122,7 +122,7 @@ RSpec.describe MergeRequests::CreateFromIssueService do
expect(result[:merge_request].assignees).to eq([user])
end
- context 'when ref branch is set', :sidekiq_might_not_need_inline do
+ context 'when ref branch is set' do
subject { described_class.new(project: project, current_user: user, mr_params: { ref: 'feature', **service_params }).execute }
it 'sets the merge request source branch to the new issue branch' do
@@ -213,7 +213,7 @@ RSpec.describe MergeRequests::CreateFromIssueService do
it_behaves_like 'a service that creates a merge request from an issue'
- it 'sets the merge request title to: "Draft: $issue-branch-name', :sidekiq_might_not_need_inline do
+ it 'sets the merge request title to: "Draft: $issue-branch-name' do
result = service.execute
expect(result[:merge_request].title).to eq("Draft: #{issue.to_branch_name.titleize.humanize}")
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index 4102cdc101e..0bc8258af42 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
description: 'please fix',
source_branch: 'feature',
target_branch: 'master',
- assignees: [user2]
+ assignee_ids: [user2.id]
}
end
diff --git a/spec/services/merge_requests/ff_merge_service_spec.rb b/spec/services/merge_requests/ff_merge_service_spec.rb
index aa5d6dcd1fb..5027acbba0a 100644
--- a/spec/services/merge_requests/ff_merge_service_spec.rb
+++ b/spec/services/merge_requests/ff_merge_service_spec.rb
@@ -108,7 +108,8 @@ RSpec.describe MergeRequests::FfMergeService do
service.execute(merge_request)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(message: a_string_matching(error_message)))
end
it 'logs and saves error if there is an PreReceiveError exception' do
@@ -122,7 +123,8 @@ RSpec.describe MergeRequests::FfMergeService do
service.execute(merge_request)
expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(message: a_string_matching(error_message)))
end
it 'does not update squash_commit_sha if squash merge is not successful' do
diff --git a/spec/services/merge_requests/link_lfs_objects_service_spec.rb b/spec/services/merge_requests/link_lfs_objects_service_spec.rb
index 2fb6bbaf02f..96cb72baac2 100644
--- a/spec/services/merge_requests/link_lfs_objects_service_spec.rb
+++ b/spec/services/merge_requests/link_lfs_objects_service_spec.rb
@@ -52,10 +52,11 @@ RSpec.describe MergeRequests::LinkLfsObjectsService, :sidekiq_inline do
it 'calls Projects::LfsPointers::LfsLinkService#execute with OIDs of LFS objects in merge request' do
expect_next_instance_of(Projects::LfsPointers::LfsLinkService) do |service|
- expect(service).to receive(:execute).with(%w[
- 8b12507783d5becacbf2ebe5b01a60024d8728a8f86dcc818bce699e8b3320bc
- 94a72c074cfe574742c9e99e863322f73feff82981d065ff65a0308f44f19f62
- ])
+ expect(service).to receive(:execute).with(
+ %w[
+ 8b12507783d5becacbf2ebe5b01a60024d8728a8f86dcc818bce699e8b3320bc
+ 94a72c074cfe574742c9e99e863322f73feff82981d065ff65a0308f44f19f62
+ ])
end
execute
diff --git a/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb b/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb
index 4d7bd3d8800..8437876c3cf 100644
--- a/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb
+++ b/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb
@@ -15,20 +15,26 @@ RSpec.describe MergeRequests::MarkReviewerReviewedService do
end
describe '#execute' do
- describe 'invalid permissions' do
- let(:service) { described_class.new(project: project, current_user: create(:user)) }
-
+ shared_examples_for 'failed service execution' do
it 'returns an error' do
expect(result[:status]).to eq :error
end
+
+ it_behaves_like 'does not trigger GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { result }
+ end
+ end
+
+ describe 'invalid permissions' do
+ let(:service) { described_class.new(project: project, current_user: create(:user)) }
+
+ it_behaves_like 'failed service execution'
end
describe 'reviewer does not exist' do
let(:service) { described_class.new(project: project, current_user: create(:user)) }
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
+ it_behaves_like 'failed service execution'
end
describe 'reviewer exists' do
@@ -40,6 +46,10 @@ RSpec.describe MergeRequests::MarkReviewerReviewedService do
expect(result[:status]).to eq :success
expect(reviewer.state).to eq 'reviewed'
end
+
+ it_behaves_like 'triggers GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { result }
+ end
end
end
end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index a2d73d8c9b1..d3bf203d6bb 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -95,6 +95,42 @@ RSpec.describe MergeRequests::MergeService do
end
end
+ context 'running the service once' do
+ let(:ref) { merge_request.to_reference(full: true) }
+ let(:jid) { SecureRandom.hex }
+
+ let(:messages) do
+ [
+ /#{ref} - Git merge started on JID #{jid}/,
+ /#{ref} - Git merge finished on JID #{jid}/,
+ /#{ref} - Post merge started on JID #{jid}/,
+ /#{ref} - Post merge finished on JID #{jid}/,
+ /#{ref} - Merge process finished on JID #{jid}/
+ ]
+ end
+
+ before do
+ merge_request.update!(merge_jid: jid)
+ ::Gitlab::ApplicationContext.push(caller_id: 'MergeWorker')
+ end
+
+ it 'logs status messages' do
+ allow(Gitlab::AppLogger).to receive(:info).and_call_original
+
+ messages.each do |message|
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ 'meta.caller_id' => 'MergeWorker',
+ message: message,
+ merge_request_info: ref
+ )
+ ).and_call_original
+ end
+
+ service.execute(merge_request)
+ end
+ end
+
context 'running the service multiple time' do
it 'is idempotent' do
2.times { service.execute(merge_request) }
@@ -315,7 +351,9 @@ RSpec.describe MergeRequests::MergeService do
service.execute(merge_request)
expect(merge_request.merge_error).to eq(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
end
@@ -328,7 +366,9 @@ RSpec.describe MergeRequests::MergeService do
service.execute(merge_request)
expect(merge_request.merge_error).to eq(described_class::GENERIC_ERROR_MESSAGE)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
it 'logs and saves error if user is not authorized' do
@@ -354,7 +394,9 @@ RSpec.describe MergeRequests::MergeService do
service.execute(merge_request)
expect(merge_request.merge_error).to include('Something went wrong during merge pre-receive hook')
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
it 'logs and saves error if commit is not created' do
@@ -366,7 +408,9 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
expect(merge_request.merge_error).to include(described_class::GENERIC_ERROR_MESSAGE)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(described_class::GENERIC_ERROR_MESSAGE))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(described_class::GENERIC_ERROR_MESSAGE)))
end
context 'when squashing is required' do
@@ -385,7 +429,9 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request.merge_commit_sha).to be_nil
expect(merge_request.squash_commit_sha).to be_nil
expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
end
@@ -406,7 +452,9 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request.merge_commit_sha).to be_nil
expect(merge_request.squash_commit_sha).to be_nil
expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
it 'logs and saves error if there is an PreReceiveError exception' do
@@ -422,7 +470,9 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request.merge_commit_sha).to be_nil
expect(merge_request.squash_commit_sha).to be_nil
expect(merge_request.merge_error).to include('Something went wrong during merge pre-receive hook')
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
context 'when fast-forward merge is not allowed' do
@@ -444,7 +494,9 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request.merge_commit_sha).to be_nil
expect(merge_request.squash_commit_sha).to be_nil
expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
end
end
@@ -461,7 +513,9 @@ RSpec.describe MergeRequests::MergeService do
it 'logs and saves error' do
service.execute(merge_request)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
end
@@ -473,7 +527,9 @@ RSpec.describe MergeRequests::MergeService do
it 'logs and saves error' do
service.execute(merge_request)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(Gitlab::AppLogger).to have_received(:error)
+ .with(hash_including(merge_request_info: merge_request.to_reference(full: true),
+ message: a_string_matching(error_message)))
end
context 'when passing `skip_discussions_check: true` as `options` parameter' do
diff --git a/spec/services/merge_requests/mergeability/logger_spec.rb b/spec/services/merge_requests/mergeability/logger_spec.rb
index a4d544884b9..3e2a1e9f9fd 100644
--- a/spec/services/merge_requests/mergeability/logger_spec.rb
+++ b/spec/services/merge_requests/mergeability/logger_spec.rb
@@ -94,25 +94,6 @@ RSpec.describe MergeRequests::Mergeability::Logger, :request_store do
end
end
- context 'when disabled' do
- before do
- stub_feature_flags(mergeability_checks_logger: false)
- end
-
- it "returns the block's value" do
- expect(logger.instrument(mergeability_name: :expensive_operation) { 123 }).to eq(123)
- end
-
- it 'does not call the logger' do
- expect(Gitlab::AppJsonLogger).not_to receive(:new)
-
- expect(logger.instrument(mergeability_name: :expensive_operation) { Project.count + MergeRequest.count })
- .to eq(2)
-
- logger.commit
- end
- end
-
it 'raises an error when block is not provided' do
expect { logger.instrument(mergeability_name: :expensive_operation) }
.to raise_error(ArgumentError, 'block not given')
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index 391377ad801..251bf6f0d9d 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -730,6 +730,15 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'with a deleted branch'
it_behaves_like 'with the project default branch'
+
+ context 'when passing in usernames' do
+ # makes sure that usernames starting with numbers aren't treated as IDs
+ let(:user2) { create(:user, username: '123user', developer_projects: [project]) }
+ let(:user3) { create(:user, username: '999user', developer_projects: [project]) }
+ let(:assigned) { { user2.username => 1, user3.username => 1 } }
+
+ it_behaves_like 'with an existing branch that has a merge request open in foss'
+ end
end
describe '`unassign` push option' do
@@ -743,6 +752,13 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'with a deleted branch'
it_behaves_like 'with the project default branch'
+
+ context 'when passing in usernames' do
+ let(:assigned) { { user2.username => 1, user3.username => 1 } }
+ let(:unassigned) { { user1.username => 1, user3.username => 1 } }
+
+ it_behaves_like 'with an existing branch that has a merge request open in foss'
+ end
end
describe 'multiple pushed branches' do
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 09d06b8b2ab..5174ceaaa82 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequests::RefreshService do
include ProjectForksHelper
- include ProjectHelpers
+ include UserHelpers
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
@@ -189,7 +189,7 @@ RSpec.describe MergeRequests::RefreshService do
subject { service.new(project: @project, current_user: @user).execute(@oldrev, @newrev, 'refs/heads/master') }
- it 'updates the head_pipeline_id for @merge_request', :sidekiq_might_not_need_inline do
+ it 'updates the head_pipeline_id for @merge_request', :sidekiq_inline do
expect { subject }.to change { @merge_request.reload.head_pipeline_id }.from(nil).to(pipeline.id)
end
@@ -306,7 +306,7 @@ RSpec.describe MergeRequests::RefreshService do
subject
end
- it 'sets the latest detached merge request pipeline as a head pipeline', :sidekiq_might_not_need_inline do
+ it 'sets the latest detached merge request pipeline as a head pipeline' do
@merge_request.reload
expect(@merge_request.actual_head_pipeline).to be_merge_request_event
end
@@ -424,7 +424,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'push to origin repo target branch', :sidekiq_might_not_need_inline do
+ context 'push to origin repo target branch' do
context 'when all MRs to the target branch had diffs' do
before do
service.new(project: @project, current_user: @user).execute(@oldrev, @newrev, 'refs/heads/feature')
@@ -474,7 +474,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'manual merge of source branch', :sidekiq_might_not_need_inline do
+ context 'manual merge of source branch' do
before do
# Merge master -> feature branch
@project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, 'Test message')
@@ -496,7 +496,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'push to fork repo source branch', :sidekiq_might_not_need_inline do
+ context 'push to fork repo source branch' do
let(:refresh_service) { service.new(project: @fork_project, current_user: @user) }
def refresh
@@ -561,7 +561,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'push to fork repo target branch', :sidekiq_might_not_need_inline do
+ context 'push to fork repo target branch' do
describe 'changes to merge requests' do
before do
service.new(project: @fork_project, current_user: @user).execute(@oldrev, @newrev, 'refs/heads/feature')
@@ -587,7 +587,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- context 'forked projects with the same source branch name as target branch', :sidekiq_might_not_need_inline do
+ context 'forked projects with the same source branch name as target branch' do
let!(:first_commit) do
@fork_project.repository.create_file(@user, 'test1.txt', 'Test data',
message: 'Test commit',
@@ -671,7 +671,7 @@ RSpec.describe MergeRequests::RefreshService do
context 'push new branch that exists in a merge request' do
let(:refresh_service) { service.new(project: @fork_project, current_user: @user) }
- it 'refreshes the merge request', :sidekiq_might_not_need_inline do
+ it 'refreshes the merge request' do
expect(refresh_service).to receive(:execute_hooks)
.with(@fork_merge_request, 'update', old_rev: Gitlab::Git::BLANK_SHA)
allow_any_instance_of(Repository).to receive(:merge_base).and_return(@oldrev)
@@ -799,23 +799,24 @@ RSpec.describe MergeRequests::RefreshService do
it 'does not mark as draft based on commits that do not belong to an MR' do
allow(refresh_service).to receive(:find_new_commits)
- refresh_service.instance_variable_set("@commits", [
- double(
- id: 'aaaaaaa',
- sha: 'aaaaaaa',
- short_id: 'aaaaaaa',
- title: 'Fix issue',
- draft?: false
- ),
- double(
- id: 'bbbbbbb',
- sha: 'bbbbbbbb',
- short_id: 'bbbbbbb',
- title: 'fixup! Fix issue',
- draft?: true,
- to_reference: 'bbbbbbb'
- )
- ])
+ refresh_service.instance_variable_set("@commits",
+ [
+ double(
+ id: 'aaaaaaa',
+ sha: 'aaaaaaa',
+ short_id: 'aaaaaaa',
+ title: 'Fix issue',
+ draft?: false
+ ),
+ double(
+ id: 'bbbbbbb',
+ sha: 'bbbbbbbb',
+ short_id: 'bbbbbbb',
+ title: 'fixup! Fix issue',
+ draft?: true,
+ to_reference: 'bbbbbbb'
+ )
+ ])
refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
reload_mrs
diff --git a/spec/services/merge_requests/request_review_service_spec.rb b/spec/services/merge_requests/request_review_service_spec.rb
index 8bc31df605c..1d3f92b083f 100644
--- a/spec/services/merge_requests/request_review_service_spec.rb
+++ b/spec/services/merge_requests/request_review_service_spec.rb
@@ -25,20 +25,26 @@ RSpec.describe MergeRequests::RequestReviewService do
end
describe '#execute' do
- describe 'invalid permissions' do
- let(:service) { described_class.new(project: project, current_user: create(:user)) }
-
+ shared_examples_for 'failed service execution' do
it 'returns an error' do
expect(result[:status]).to eq :error
end
+
+ it_behaves_like 'does not trigger GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { result }
+ end
+ end
+
+ describe 'invalid permissions' do
+ let(:service) { described_class.new(project: project, current_user: create(:user)) }
+
+ it_behaves_like 'failed service execution'
end
describe 'reviewer does not exist' do
let(:result) { service.execute(merge_request, create(:user)) }
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
+ it_behaves_like 'failed service execution'
end
describe 'reviewer exists' do
@@ -64,6 +70,10 @@ RSpec.describe MergeRequests::RequestReviewService do
service.execute(merge_request, user)
end
+
+ it_behaves_like 'triggers GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { result }
+ end
end
end
end
diff --git a/spec/services/merge_requests/update_assignees_service_spec.rb b/spec/services/merge_requests/update_assignees_service_spec.rb
index 3a0b17c2768..2d80d75a262 100644
--- a/spec/services/merge_requests/update_assignees_service_spec.rb
+++ b/spec/services/merge_requests/update_assignees_service_spec.rb
@@ -36,6 +36,20 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
service.execute(merge_request)
end
+ shared_examples 'it updates and enqueues the job' do
+ it 'correctly updates the MR and enqueues the job' do
+ expect_next(MergeRequests::HandleAssigneesChangeService, project: project, current_user: user) do |service|
+ expect(service)
+ .to receive(:async_execute).with(merge_request, [user3], execute_hooks: true)
+ end
+
+ expect { update_merge_request }
+ .to change { merge_request.reload.assignees }.from([user3]).to(new_users)
+ .and change(merge_request, :updated_at)
+ .and change(merge_request, :updated_by).to(user)
+ end
+ end
+
shared_examples 'removing all assignees' do
it 'removes all assignees' do
expect(update_merge_request).to have_attributes(assignees: be_empty, errors: be_none)
@@ -73,16 +87,8 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
it_behaves_like 'removing all assignees'
end
- it 'updates the MR, and queues the more expensive work for later' do
- expect_next(MergeRequests::HandleAssigneesChangeService, project: project, current_user: user) do |service|
- expect(service)
- .to receive(:async_execute).with(merge_request, [user3], execute_hooks: true)
- end
-
- expect { update_merge_request }
- .to change { merge_request.reload.assignees }.from([user3]).to([user2])
- .and change(merge_request, :updated_at)
- .and change(merge_request, :updated_by).to(user)
+ it_behaves_like 'it updates and enqueues the job' do
+ let(:new_users) { [user2] }
end
it 'does not update the assignees if they do not have access' do
diff --git a/spec/services/merge_requests/update_reviewers_service_spec.rb b/spec/services/merge_requests/update_reviewers_service_spec.rb
index 8920141adbb..9f935e1cecf 100644
--- a/spec/services/merge_requests/update_reviewers_service_spec.rb
+++ b/spec/services/merge_requests/update_reviewers_service_spec.rb
@@ -128,6 +128,10 @@ RSpec.describe MergeRequests::UpdateReviewersService do
set_reviewers
end
+ it_behaves_like 'triggers GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { set_reviewers }
+ end
+
it 'calls MergeRequest::ResolveTodosService#async_execute' do
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
expect(service).to receive(:async_execute)
@@ -149,6 +153,14 @@ RSpec.describe MergeRequests::UpdateReviewersService do
set_reviewers
end
+ context 'when reviewers did not change' do
+ let(:opts) { { reviewer_ids: merge_request.reviewer_ids } }
+
+ it_behaves_like 'does not trigger GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { set_reviewers }
+ end
+ end
+
it 'does not update the reviewers if they do not have access' do
opts[:reviewer_ids] = [create(:user).id]
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 8ebabd64d8a..1d67574b06d 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -425,16 +425,10 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
create(:merge_request, :simple, source_project: project, reviewer_ids: [user2.id])
end
- context 'when merge_request_reviewer feature is enabled' do
- before do
- stub_feature_flags(merge_request_reviewer: true)
- end
-
- let(:opts) { { reviewer_ids: [IssuableFinder::Params::NONE] } }
+ let(:opts) { { reviewer_ids: [IssuableFinder::Params::NONE] } }
- it 'removes reviewers' do
- expect(update_merge_request(opts).reviewers).to eq []
- end
+ it 'removes reviewers' do
+ expect(update_merge_request(opts).reviewers).to eq []
end
end
end
@@ -625,6 +619,20 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(Todo.count).to eq(2)
end
+
+ it 'triggers GraphQL description updated subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_description_updated).with(merge_request).and_call_original
+
+ update_merge_request(description: 'updated description')
+ end
+ end
+
+ context 'when decription is not changed' do
+ it 'does not trigger GraphQL description updated subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_description_updated)
+
+ update_merge_request(title: 'updated title')
+ end
end
context 'when is reassigned' do
@@ -685,6 +693,16 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(user2.review_requested_open_merge_requests_count).to eq(1)
expect(user3.review_requested_open_merge_requests_count).to eq(0)
end
+
+ it_behaves_like 'triggers GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { update_merge_request({ reviewer_ids: [user2.id] }) }
+ end
+ end
+
+ context 'when reviewers did not change' do
+ it_behaves_like 'does not trigger GraphQL subscription mergeRequestReviewersUpdated' do
+ let(:action) { update_merge_request({ reviewer_ids: [merge_request.reviewer_ids] }) }
+ end
end
context 'when the milestone is removed' do
@@ -827,6 +845,12 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
should_not_email(non_subscriber)
end
+ it 'triggers GraphQL subscription mergeRequestMergeStatusUpdated' do
+ expect(GraphqlTriggers).to receive(:merge_request_merge_status_updated).with(merge_request)
+
+ update_merge_request(title: 'New title')
+ end
+
context 'when removing through wip_event param' do
it 'removes Draft from the title' do
expect { update_merge_request({ wip_event: "ready" }) }
@@ -853,6 +877,12 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
should_not_email(non_subscriber)
end
+ it 'triggers GraphQL subscription mergeRequestMergeStatusUpdated' do
+ expect(GraphqlTriggers).to receive(:merge_request_merge_status_updated).with(merge_request)
+
+ update_merge_request(title: 'Draft: New title')
+ end
+
context 'when adding through wip_event param' do
it 'adds Draft to the title' do
expect { update_merge_request({ wip_event: "draft" }) }
diff --git a/spec/services/ml/experiment_tracking/candidate_repository_spec.rb b/spec/services/ml/experiment_tracking/candidate_repository_spec.rb
new file mode 100644
index 00000000000..8002b2ebc86
--- /dev/null
+++ b/spec/services/ml/experiment_tracking/candidate_repository_spec.rb
@@ -0,0 +1,199 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ml::ExperimentTracking::CandidateRepository do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:experiment) { create(:ml_experiments, user: user, project: project) }
+ let_it_be(:candidate) { create(:ml_candidates, user: user, experiment: experiment) }
+
+ let(:repository) { described_class.new(project, user) }
+
+ describe '#by_iid' do
+ let(:iid) { candidate.iid }
+
+ subject { repository.by_iid(iid) }
+
+ it { is_expected.to eq(candidate) }
+
+ context 'when iid does not exist' do
+ let(:iid) { non_existing_record_iid.to_s }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when iid belongs to a different project' do
+ let(:repository) { described_class.new(create(:project), user) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#create!' do
+ subject { repository.create!(experiment, 1234) }
+
+ it 'creates the candidate' do
+ expect(subject.start_time).to eq(1234)
+ expect(subject.iid).not_to be_nil
+ expect(subject.end_time).to be_nil
+ end
+ end
+
+ describe '#update' do
+ let(:end_time) { 123456 }
+ let(:status) { 'running' }
+
+ subject { repository.update(candidate, status, end_time) }
+
+ it { is_expected.to be_truthy }
+
+ context 'when end_time is missing ' do
+ let(:end_time) { nil }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when status is wrong' do
+ let(:status) { 's' }
+
+ it 'fails assigning the value' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when status is missing' do
+ let(:status) { nil }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#add_metric!' do
+ let(:props) { { name: 'abc', value: 1234, tracked: 12345678, step: 0 } }
+ let(:metrics_before) { candidate.metrics.size }
+
+ before do
+ metrics_before
+ end
+
+ subject { repository.add_metric!(candidate, props[:name], props[:value], props[:tracked], props[:step]) }
+
+ it 'adds a new metric' do
+ expect { subject }.to change { candidate.metrics.size }.by(1)
+ end
+
+ context 'when name missing' do
+ let(:props) { { value: 1234, tracked: 12345678, step: 0 } }
+
+ it 'does not add metric' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+
+ describe '#add_param!' do
+ let(:props) { { name: 'abc', value: 'def' } }
+
+ subject { repository.add_param!(candidate, props[:name], props[:value]) }
+
+ it 'adds a new param' do
+ expect { subject }.to change { candidate.params.size }.by(1)
+ end
+
+ context 'when name missing' do
+ let(:props) { { value: 1234 } }
+
+ it 'throws RecordInvalid' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
+ context 'when param was already added' do
+ it 'throws RecordInvalid' do
+ repository.add_param!(candidate, 'new', props[:value])
+
+ expect { repository.add_param!(candidate, 'new', props[:value]) }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+
+ describe "#add_params" do
+ let(:params) do
+ [{ key: 'model_class', value: 'LogisticRegression' }, { 'key': 'pythonEnv', value: '3.10' }]
+ end
+
+ subject { repository.add_params(candidate, params) }
+
+ it 'adds the parameters' do
+ expect { subject }.to change { candidate.reload.params.size }.by(2)
+ end
+
+ context 'if parameter misses key' do
+ let(:params) do
+ [{ value: 'LogisticRegression' }]
+ end
+
+ it 'does not throw and does not add' do
+ expect { subject }.to raise_error(ActiveRecord::ActiveRecordError)
+ end
+ end
+
+ context 'if parameter misses value' do
+ let(:params) do
+ [{ key: 'pythonEnv2' }]
+ end
+
+ it 'does not throw and does not add' do
+ expect { subject }.to raise_error(ActiveRecord::ActiveRecordError)
+ end
+ end
+
+ context 'if parameter repeated do' do
+ let(:params) do
+ [
+ { 'key': 'pythonEnv0', value: '2.7' },
+ { 'key': 'pythonEnv1', value: '3.9' },
+ { 'key': 'pythonEnv1', value: '3.10' }
+ ]
+ end
+
+ before do
+ repository.add_param!(candidate, 'pythonEnv0', '0')
+ end
+
+ it 'does not throw and adds only the first of each kind' do
+ expect { subject }.to change { candidate.reload.params.size }.by(1)
+ end
+ end
+ end
+
+ describe "#add_metrics" do
+ let(:metrics) do
+ [
+ { key: 'mae', value: 2.5, timestamp: 1552550804 },
+ { key: 'rmse', value: 2.7, timestamp: 1552550804 }
+ ]
+ end
+
+ subject { repository.add_metrics(candidate, metrics) }
+
+ it 'adds the metrics' do
+ expect { subject }.to change { candidate.reload.metrics.size }.by(2)
+ end
+
+ context 'when metrics have repeated keys' do
+ let(:metrics) do
+ [
+ { key: 'mae', value: 2.5, timestamp: 1552550804 },
+ { key: 'rmse', value: 2.7, timestamp: 1552550804 },
+ { key: 'mae', value: 2.7, timestamp: 1552550805 }
+ ]
+ end
+
+ it 'adds all of them' do
+ expect { subject }.to change { candidate.reload.metrics.size }.by(3)
+ end
+ end
+ end
+end
diff --git a/spec/services/ml/experiment_tracking/experiment_repository_spec.rb b/spec/services/ml/experiment_tracking/experiment_repository_spec.rb
new file mode 100644
index 00000000000..80e1fa025d1
--- /dev/null
+++ b/spec/services/ml/experiment_tracking/experiment_repository_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ml::ExperimentTracking::ExperimentRepository do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:experiment) { create(:ml_experiments, user: user, project: project) }
+ let_it_be(:experiment2) { create(:ml_experiments, user: user, project: project) }
+ let_it_be(:experiment3) { create(:ml_experiments, user: user, project: project) }
+ let_it_be(:experiment4) { create(:ml_experiments, user: user) }
+
+ let(:repository) { described_class.new(project, user) }
+
+ describe '#by_iid_or_name' do
+ let(:iid) { experiment.iid }
+ let(:name) { nil }
+
+ subject { repository.by_iid_or_name(iid: iid, name: name) }
+
+ context 'when iid passed' do
+ it('fetches the experiment') { is_expected.to eq(experiment) }
+
+ context 'and name passed' do
+ let(:name) { experiment2.name }
+
+ it('ignores the name') { is_expected.to eq(experiment) }
+ end
+
+ context 'and does not exist' do
+ let(:iid) { non_existing_record_iid }
+
+ it { is_expected.to eq(nil) }
+ end
+ end
+
+ context 'when iid is not passed', 'and name is passed' do
+ let(:iid) { nil }
+
+ context 'when name exists' do
+ let(:name) { experiment2.name }
+
+ it('fetches the experiment') { is_expected.to eq(experiment2) }
+ end
+
+ context 'when name does not exist' do
+ let(:name) { non_existing_record_iid }
+
+ it { is_expected.to eq(nil) }
+ end
+ end
+ end
+
+ describe '#all' do
+ it 'fetches experiments for project' do
+ expect(repository.all).to match_array([experiment, experiment2, experiment3])
+ end
+ end
+
+ describe '#create!' do
+ let(:name) { 'hello' }
+
+ subject { repository.create!(name) }
+
+ it 'creates the candidate' do
+ expect { subject }.to change { repository.all.size }.by(1)
+ end
+
+ context 'when name exists' do
+ let(:name) { experiment.name }
+
+ it 'throws error' do
+ expect { subject }.to raise_error(ActiveRecord::ActiveRecordError)
+ end
+ end
+
+ context 'when name is missing' do
+ let(:name) { nil }
+
+ it 'throws error' do
+ expect { subject }.to raise_error(ActiveRecord::ActiveRecordError)
+ end
+ end
+ end
+end
diff --git a/spec/services/namespaces/package_settings/update_service_spec.rb b/spec/services/namespaces/package_settings/update_service_spec.rb
index ed385f1cd7f..10926c5ef57 100644
--- a/spec/services/namespaces/package_settings/update_service_spec.rb
+++ b/spec/services/namespaces/package_settings/update_service_spec.rb
@@ -33,8 +33,29 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do
shared_examples 'updating the namespace package setting' do
it_behaves_like 'updating the namespace package setting attributes',
- from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
- to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar' }
+ from: {
+ maven_duplicates_allowed: true,
+ maven_duplicate_exception_regex: 'SNAPSHOT',
+ generic_duplicates_allowed: true,
+ generic_duplicate_exception_regex: 'foo',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: false,
+ npm_package_requests_forwarding: nil,
+ lock_npm_package_requests_forwarding: false,
+ pypi_package_requests_forwarding: nil,
+ lock_pypi_package_requests_forwarding: false
+ }, to: {
+ maven_duplicates_allowed: false,
+ maven_duplicate_exception_regex: 'RELEASE',
+ generic_duplicates_allowed: false,
+ generic_duplicate_exception_regex: 'bar',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
+ }
it_behaves_like 'returning a success'
@@ -63,10 +84,18 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do
context 'with existing namespace package setting' do
let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
let_it_be(:params) do
- { maven_duplicates_allowed: false,
+ {
+ maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'RELEASE',
generic_duplicates_allowed: false,
- generic_duplicate_exception_regex: 'bar' }
+ generic_duplicate_exception_regex: 'bar',
+ maven_package_requests_forwarding: true,
+ lock_maven_package_requests_forwarding: true,
+ npm_package_requests_forwarding: true,
+ lock_npm_package_requests_forwarding: true,
+ pypi_package_requests_forwarding: true,
+ lock_pypi_package_requests_forwarding: true
+ }
end
where(:user_role, :shared_examples_name) do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 935dcef1011..8fbf023cda0 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -337,6 +337,27 @@ RSpec.describe NotificationService, :mailer do
end
end
end
+
+ describe '#access_token_revoked' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pat) { create(:personal_access_token, user: user) }
+
+ subject(:notification_service) { notification.access_token_revoked(user, pat.name) }
+
+ it 'sends email to the token owner' do
+ expect { notification_service }.to have_enqueued_email(user, pat.name, mail: "access_token_revoked_email")
+ end
+
+ context 'when user is not allowed to receive notifications' do
+ before do
+ user.block!
+ end
+
+ it 'does not send email to the token owner' do
+ expect { notification_service }.not_to have_enqueued_email(user, pat.name, mail: "access_token_revoked_email")
+ end
+ end
+ end
end
describe 'SSH Keys' do
diff --git a/spec/services/onboarding/progress_service_spec.rb b/spec/services/onboarding/progress_service_spec.rb
index e9b8ea2e859..8f3f723613e 100644
--- a/spec/services/onboarding/progress_service_spec.rb
+++ b/spec/services/onboarding/progress_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Onboarding::ProgressService do
context 'when not onboarded' do
it 'does not schedule a worker' do
- expect(Namespaces::OnboardingProgressWorker).not_to receive(:perform_async)
+ expect(Onboarding::ProgressWorker).not_to receive(:perform_async)
execute_service
end
@@ -28,7 +28,7 @@ RSpec.describe Onboarding::ProgressService do
end
it 'does not schedule a worker' do
- expect(Namespaces::OnboardingProgressWorker).not_to receive(:perform_async)
+ expect(Onboarding::ProgressWorker).not_to receive(:perform_async)
execute_service
end
@@ -36,7 +36,7 @@ RSpec.describe Onboarding::ProgressService do
context 'when action is not yet completed' do
it 'schedules a worker' do
- expect(Namespaces::OnboardingProgressWorker).to receive(:perform_async)
+ expect(Onboarding::ProgressWorker).to receive(:perform_async)
execute_service
end
diff --git a/spec/services/packages/debian/create_package_file_service_spec.rb b/spec/services/packages/debian/create_package_file_service_spec.rb
index c8292b2d5c2..291f6df991c 100644
--- a/spec/services/packages/debian/create_package_file_service_spec.rb
+++ b/spec/services/packages/debian/create_package_file_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Packages::Debian::CreatePackageFileService do
include WorkhorseHelpers
let_it_be(:package) { create(:debian_incoming, without_package_files: true) }
+ let_it_be(:current_user) { create(:user) }
describe '#execute' do
let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
@@ -20,12 +21,13 @@ RSpec.describe Packages::Debian::CreatePackageFileService do
}.with_indifferent_access
end
- let(:service) { described_class.new(package, params) }
+ let(:service) { described_class.new(package: package, current_user: current_user, params: params) }
subject(:package_file) { service.execute }
shared_examples 'a valid deb' do
it 'creates a new package file', :aggregate_failures do
+ expect(::Packages::Debian::ProcessChangesWorker).not_to receive(:perform_async)
expect(package_file).to be_valid
expect(package_file.file.read).to start_with('!<arch>')
expect(package_file.size).to eq(1124)
@@ -40,6 +42,24 @@ RSpec.describe Packages::Debian::CreatePackageFileService do
end
end
+ shared_examples 'a valid changes' do
+ it 'creates a new package file', :aggregate_failures do
+ expect(::Packages::Debian::ProcessChangesWorker).to receive(:perform_async)
+
+ expect(package_file).to be_valid
+ expect(package_file.file.read).to start_with('Format: 1.8')
+ expect(package_file.size).to eq(2143)
+ expect(package_file.file_name).to eq(file_name)
+ expect(package_file.file_sha1).to eq('54321')
+ expect(package_file.file_sha256).to eq('543212345')
+ expect(package_file.file_md5).to eq('12345')
+ expect(package_file.debian_file_metadatum).to be_valid
+ expect(package_file.debian_file_metadatum.file_type).to eq('unknown')
+ expect(package_file.debian_file_metadatum.architecture).to be_nil
+ expect(package_file.debian_file_metadatum.fields).to be_nil
+ end
+ end
+
context 'with temp file' do
let!(:file) do
upload_path = ::Packages::PackageFileUploader.workhorse_local_upload_path
@@ -52,6 +72,21 @@ RSpec.describe Packages::Debian::CreatePackageFileService do
end
it_behaves_like 'a valid deb'
+
+ context 'with a .changes file' do
+ let(:file_name) { 'sample_1.2.3~alpha2_amd64.changes' }
+ let(:fixture_path) { "spec/fixtures/packages/debian/#{file_name}" }
+
+ it_behaves_like 'a valid changes'
+ end
+
+ context 'when current_user is missing' do
+ let(:current_user) { nil }
+
+ it 'raises an error' do
+ expect { package_file }.to raise_error(ArgumentError, 'Invalid user')
+ end
+ end
end
context 'with remote file' do
@@ -77,37 +112,37 @@ RSpec.describe Packages::Debian::CreatePackageFileService do
it_behaves_like 'a valid deb'
end
- context 'package is missing' do
+ context 'when package is missing' do
let(:package) { nil }
let(:params) { {} }
it 'raises an error' do
- expect { subject.execute }.to raise_error(ArgumentError, 'Invalid package')
+ expect { package_file }.to raise_error(ArgumentError, 'Invalid package')
end
end
- context 'params is empty' do
+ context 'when params is empty' do
let(:params) { {} }
it 'raises an error' do
- expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ expect { package_file }.to raise_error(ActiveRecord::RecordInvalid)
end
end
- context 'file is missing' do
+ context 'when file is missing' do
let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
let(:file) { nil }
it 'raises an error' do
- expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
+ expect { package_file }.to raise_error(ActiveRecord::RecordInvalid)
end
end
- context 'FIPS mode enabled', :fips_mode do
+ context 'when FIPS mode enabled', :fips_mode do
let(:file) { nil }
it 'raises an error' do
- expect { subject.execute }.to raise_error(::Packages::FIPS::DisabledError)
+ expect { package_file }.to raise_error(::Packages::FIPS::DisabledError)
end
end
end
diff --git a/spec/services/packages/mark_packages_for_destruction_service_spec.rb b/spec/services/packages/mark_packages_for_destruction_service_spec.rb
new file mode 100644
index 00000000000..5c043b89de8
--- /dev/null
+++ b/spec/services/packages/mark_packages_for_destruction_service_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::MarkPackagesForDestructionService, :sidekiq_inline do
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:packages) { create_list(:npm_package, 3, project: project) }
+
+ let(:user) { project.owner }
+
+ # The service only accepts ActiveRecord relationships and not arrays.
+ let(:service) { described_class.new(packages: ::Packages::Package.id_in(package_ids), current_user: user) }
+ let(:package_ids) { packages.map(&:id) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'when the user is authorized' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when it is successful' do
+ it 'marks the packages as pending destruction' do
+ expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new)
+
+ expect { subject }.to change { ::Packages::Package.pending_destruction.count }.from(0).to(3)
+ .and change { Packages::PackageFile.pending_destruction.count }.from(0).to(3)
+ packages.each { |pkg| expect(pkg.reload).to be_pending_destruction }
+
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_success
+ expect(subject.message).to eq('Packages were successfully marked as pending destruction')
+ end
+
+ context 'with maven packages' do
+ let_it_be_with_reload(:packages) { create_list(:maven_package, 3, project: project) }
+
+ it 'marks the packages as pending destruction' do
+ expect(::Packages::Maven::Metadata::SyncService).to receive(:new).once.and_call_original
+
+ expect { subject }.to change { ::Packages::Package.pending_destruction.count }.from(0).to(3)
+ .and change { Packages::PackageFile.pending_destruction.count }.from(0).to(9)
+ packages.each { |pkg| expect(pkg.reload).to be_pending_destruction }
+
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_success
+ expect(subject.message).to eq('Packages were successfully marked as pending destruction')
+ end
+
+ context 'without version' do
+ before do
+ ::Packages::Package.id_in(package_ids).update_all(version: nil)
+ end
+
+ it 'marks the packages as pending destruction' do
+ expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new)
+
+ expect { subject }.to change { ::Packages::Package.pending_destruction.count }.from(0).to(3)
+ .and change { Packages::PackageFile.pending_destruction.count }.from(0).to(9)
+ packages.each { |pkg| expect(pkg.reload).to be_pending_destruction }
+
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_success
+ expect(subject.message).to eq('Packages were successfully marked as pending destruction')
+ end
+ end
+ end
+ end
+
+ context 'when it is not successful' do
+ before do
+ allow(service).to receive(:can_destroy_packages?).and_raise(StandardError, 'test')
+ end
+
+ it 'returns an error ServiceResponse' do
+ expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new)
+
+ expect { subject }.to not_change { ::Packages::Package.pending_destruction.count }
+ .and not_change { ::Packages::PackageFile.pending_destruction.count }
+
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_error
+ expect(subject.message).to eq("Failed to mark the packages as pending destruction")
+ expect(subject.status).to eq(:error)
+ end
+ end
+ end
+
+ context 'when the user is not authorized' do
+ let(:user) { nil }
+
+ it 'returns an error ServiceResponse' do
+ expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new)
+
+ expect { subject }.to not_change { ::Packages::Package.pending_destruction.count }
+ .and not_change { ::Packages::PackageFile.pending_destruction.count }
+
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_error
+ expect(subject.message).to eq("You don't have the permission to perform this action")
+ expect(subject.status).to eq(:error)
+ expect(subject.reason).to eq(:unauthorized)
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/rpm/parse_package_service_spec.rb b/spec/services/packages/rpm/parse_package_service_spec.rb
new file mode 100644
index 00000000000..f330587bfa0
--- /dev/null
+++ b/spec/services/packages/rpm/parse_package_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rpm::ParsePackageService do
+ let(:package_file) { File.open('spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.x86_64.rpm') }
+
+ describe 'dynamic private methods' do
+ described_class::BUILD_ATTRIBUTES_METHOD_NAMES.each do |attribute|
+ it 'define dynamic build attribute method' do
+ expect(described_class).to be_private_method_defined("build_#{attribute}")
+ end
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(package_file).execute }
+
+ shared_examples 'valid package parsing' do
+ it 'return hash' do
+ expect(subject).to be_a(Hash)
+ end
+
+ it 'has all static attribute keys' do
+ expect(subject.keys).to include(*described_class::STATIC_ATTRIBUTES)
+ end
+
+ it 'includes epoch attribute' do
+ expect(subject[:epoch]).not_to be_blank
+ end
+
+ it 'has all built attributes with array values' do
+ result = subject
+ described_class::BUILD_ATTRIBUTES_METHOD_NAMES.each do |attribute|
+ expect(result).to have_key(attribute)
+ expect(result[attribute]).to be_a(Array)
+ end
+ end
+ end
+
+ context 'when wrong format file received' do
+ let(:package_file) { File.open('spec/fixtures/rails_sample.jpg') }
+
+ it 'raise error' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when valid file uploaded' do
+ context 'when .rpm file uploaded' do
+ it_behaves_like 'valid package parsing'
+ end
+
+ context 'when .src.rpm file uploaded' do
+ let(:package_file) { File.open('spec/fixtures/packages/rpm/hello-0.0.1-1.fc29.src.rpm') }
+
+ it_behaves_like 'valid package parsing'
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/rpm/repository_metadata/base_builder_spec.rb b/spec/services/packages/rpm/repository_metadata/base_builder_spec.rb
index 0fb58cc27d5..524c224177b 100644
--- a/spec/services/packages/rpm/repository_metadata/base_builder_spec.rb
+++ b/spec/services/packages/rpm/repository_metadata/base_builder_spec.rb
@@ -3,7 +3,10 @@ require 'spec_helper'
RSpec.describe Packages::Rpm::RepositoryMetadata::BaseBuilder do
describe '#execute' do
- subject { described_class.new.execute }
+ subject { described_class.new(xml: xml, data: data).execute }
+
+ let(:xml) { nil }
+ let(:data) { {} }
before do
stub_const("#{described_class}::ROOT_TAG", 'test')
@@ -18,5 +21,13 @@ RSpec.describe Packages::Rpm::RepositoryMetadata::BaseBuilder do
expect(result.children.first.attributes['foo1'].value).to eq('bar1')
expect(result.children.first.attributes['foo2'].value).to eq('bar2')
end
+
+ context 'when call with parameters' do
+ let(:xml) { 'test' }
+
+ it 'raise NotImplementedError' do
+ expect { subject }.to raise_error NotImplementedError
+ end
+ end
end
end
diff --git a/spec/services/packages/rpm/repository_metadata/build_primary_xml_spec.rb b/spec/services/packages/rpm/repository_metadata/build_primary_xml_spec.rb
index f5294d6f7f7..147d5862a71 100644
--- a/spec/services/packages/rpm/repository_metadata/build_primary_xml_spec.rb
+++ b/spec/services/packages/rpm/repository_metadata/build_primary_xml_spec.rb
@@ -3,18 +3,32 @@ require 'spec_helper'
RSpec.describe Packages::Rpm::RepositoryMetadata::BuildPrimaryXml do
describe '#execute' do
- subject { described_class.new.execute }
+ subject { described_class.new(xml: xml, data: data).execute }
- context "when generate empty xml" do
- let(:expected_xml) do
- <<~XML
- <?xml version="1.0" encoding="UTF-8"?>
- <metadata xmlns="http://linux.duke.edu/metadata/common" xmlns:rpm="http://linux.duke.edu/metadata/rpm" packages="0"/>
- XML
- end
+ let(:empty_xml) do
+ <<~XML
+ <?xml version="1.0" encoding="UTF-8"?>
+ <metadata xmlns="http://linux.duke.edu/metadata/common" xmlns:rpm="http://linux.duke.edu/metadata/rpm" packages="0"/>
+ XML
+ end
+
+ it_behaves_like 'handling rpm xml file'
+
+ context 'when updating existing xml' do
+ include_context 'with rpm package data'
+
+ let(:xml) { empty_xml }
+ let(:data) { xml_update_params }
+ let(:required_text_only_attributes) { %i[description summary arch name] }
+
+ it 'adds node with required_text_only_attributes' do
+ result = Nokogiri::XML::Document.parse(subject).remove_namespaces!
- it 'generate expected xml' do
- expect(subject).to eq(expected_xml)
+ required_text_only_attributes.each do |attribute|
+ expect(
+ result.at("//#{described_class::ROOT_TAG}/package/#{attribute}").text
+ ).to eq(data[attribute])
+ end
end
end
end
diff --git a/spec/services/packages/rpm/repository_metadata/build_repomd_xml_spec.rb b/spec/services/packages/rpm/repository_metadata/build_repomd_xml_spec.rb
index 29b0f73e3c1..0843a983b7e 100644
--- a/spec/services/packages/rpm/repository_metadata/build_repomd_xml_spec.rb
+++ b/spec/services/packages/rpm/repository_metadata/build_repomd_xml_spec.rb
@@ -62,5 +62,25 @@ RSpec.describe Packages::Rpm::RepositoryMetadata::BuildRepomdXml do
end
end
end
+
+ context 'when data values has unexpected keys' do
+ let(:data) do
+ {
+ filelists: described_class::ALLOWED_DATA_VALUE_KEYS.each_with_object({}) do |key, result|
+ result[:"#{key}-wrong"] = { value: 'value' }
+ end
+ }
+ end
+
+ it 'ignores wrong keys' do
+ result = Nokogiri::XML::Document.parse(subject).remove_namespaces!
+
+ data.each do |tag_name, tag_attributes|
+ tag_attributes.each_key do |key|
+ expect(result.at("//repomd/data[@type=\"#{tag_name}\"]/#{key}")).to be_nil
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/services/pages_domains/create_acme_order_service_spec.rb b/spec/services/pages_domains/create_acme_order_service_spec.rb
index b882c253613..35b2cc56973 100644
--- a/spec/services/pages_domains/create_acme_order_service_spec.rb
+++ b/spec/services/pages_domains/create_acme_order_service_spec.rb
@@ -38,21 +38,13 @@ RSpec.describe PagesDomains::CreateAcmeOrderService do
expect(challenge).to have_received(:request_validation).ordered
end
- it 'generates and saves private key: rsa' do
- stub_feature_flags(pages_lets_encrypt_ecdsa: false)
+ it 'generates and saves private key' do
service.execute
saved_order = PagesDomainAcmeOrder.last
expect { OpenSSL::PKey::RSA.new(saved_order.private_key) }.not_to raise_error
end
- it 'generates and saves private key: ec' do
- service.execute
-
- saved_order = PagesDomainAcmeOrder.last
- expect { OpenSSL::PKey::EC.new(saved_order.private_key) }.not_to raise_error
- end
-
it 'properly saves order attributes' do
service.execute
diff --git a/spec/services/pages_domains/create_service_spec.rb b/spec/services/pages_domains/create_service_spec.rb
new file mode 100644
index 00000000000..cac941fb134
--- /dev/null
+++ b/spec/services/pages_domains/create_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::PagesDomains::CreateService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :in_subgroup) }
+
+ let(:domain) { 'new.domain.com' }
+ let(:attributes) { { domain: domain } }
+
+ subject(:service) { described_class.new(project, user, attributes) }
+
+ context 'when the user does not have the required permissions' do
+ it 'does not create a pages domain and does not publish a PagesDomainCreatedEvent' do
+ expect(service.execute).to be_nil
+
+ expect { service.execute }
+ .to not_publish_event(PagesDomains::PagesDomainCreatedEvent)
+ .and not_change(project.pages_domains, :count)
+ end
+ end
+
+ context 'when the user has the required permissions' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when it saves the domain successfully' do
+ it 'creates the domain and publishes a PagesDomainCreatedEvent' do
+ pages_domain = nil
+
+ expect { pages_domain = service.execute }
+ .to change(project.pages_domains, :count)
+ .and publish_event(PagesDomains::PagesDomainCreatedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace.id,
+ root_namespace_id: project.root_namespace.id,
+ domain: domain
+ )
+
+ expect(pages_domain).to be_persisted
+ end
+ end
+
+ context 'when it fails to save the domain' do
+ let(:domain) { nil }
+
+ it 'does not create a pages domain and does not publish a PagesDomainCreatedEvent' do
+ pages_domain = nil
+
+ expect { pages_domain = service.execute }
+ .to not_publish_event(PagesDomains::PagesDomainCreatedEvent)
+ .and not_change(project.pages_domains, :count)
+
+ expect(pages_domain).not_to be_persisted
+ end
+ end
+ end
+end
diff --git a/spec/services/pages_domains/delete_service_spec.rb b/spec/services/pages_domains/delete_service_spec.rb
new file mode 100644
index 00000000000..5f98fe3c7f7
--- /dev/null
+++ b/spec/services/pages_domains/delete_service_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::PagesDomains::DeleteService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pages_domain) { create(:pages_domain, :with_project) }
+
+ let(:params) do
+ attributes_for(:pages_domain, :with_trusted_chain).slice(:key, :certificate).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
+ end
+
+ subject(:service) { described_class.new(pages_domain.project, user, params) }
+
+ context 'when the user does not have the required permissions' do
+ it 'does not delete the pages domain and does not publish a PagesDomainDeletedEvent' do
+ result_match = -> { expect(service.execute(pages_domain)).to be_nil }
+
+ expect(&result_match)
+ .to not_publish_event(PagesDomains::PagesDomainDeletedEvent)
+ end
+ end
+
+ context 'when the user has the required permissions' do
+ before do
+ pages_domain.project.add_maintainer(user)
+ end
+
+ context 'when it updates the domain successfully' do
+ it 'deletes the domain and publishes a PagesDomainDeletedEvent' do
+ result_match = -> { expect(service.execute(pages_domain)).not_to be_nil }
+
+ expect(&result_match)
+ .to publish_event(PagesDomains::PagesDomainDeletedEvent)
+ .with(
+ project_id: pages_domain.project.id,
+ namespace_id: pages_domain.project.namespace.id,
+ root_namespace_id: pages_domain.project.root_namespace.id,
+ domain: pages_domain.domain
+ )
+ end
+ end
+ end
+end
diff --git a/spec/services/pages_domains/update_service_spec.rb b/spec/services/pages_domains/update_service_spec.rb
new file mode 100644
index 00000000000..f6558f56422
--- /dev/null
+++ b/spec/services/pages_domains/update_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PagesDomains::UpdateService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pages_domain) { create(:pages_domain, :with_project) }
+
+ let(:params) do
+ attributes_for(:pages_domain, :with_trusted_chain).slice(:key, :certificate).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
+ end
+
+ subject(:service) { described_class.new(pages_domain.project, user, params) }
+
+ context 'when the user does not have the required permissions' do
+ it 'does not update the pages domain and does not publish a PagesDomainUpdatedEvent' do
+ expect do
+ expect(service.execute(pages_domain)).to be_nil
+ end.to not_publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ end
+ end
+
+ context 'when the user has the required permissions' do
+ before do
+ pages_domain.project.add_maintainer(user)
+ end
+
+ context 'when it updates the domain successfully' do
+ it 'updates the domain' do
+ expect(service.execute(pages_domain)).to eq(true)
+ end
+
+ it 'publishes a PagesDomainUpdatedEvent' do
+ expect { service.execute(pages_domain) }
+ .to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ .with(
+ project_id: pages_domain.project.id,
+ namespace_id: pages_domain.project.namespace.id,
+ root_namespace_id: pages_domain.project.root_namespace.id,
+ domain: pages_domain.domain
+ )
+ end
+ end
+
+ context 'when it fails to update the domain' do
+ let(:params) { { user_provided_certificate: 'blabla' } }
+
+ it 'does not update a pages domain' do
+ expect(service.execute(pages_domain)).to be(false)
+ end
+
+ it 'does not publish a PagesDomainUpdatedEvent' do
+ expect { service.execute(pages_domain) }
+ .not_to publish_event(PagesDomains::PagesDomainUpdatedEvent)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index 54a21d2f22b..bc95a1f3c8b 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -154,23 +154,49 @@ RSpec.describe Projects::AutocompleteService do
let_it_be(:project) { create(:project, group: group) }
let_it_be(:contact_1) { create(:contact, group: group) }
let_it_be(:contact_2) { create(:contact, group: group) }
+ let_it_be(:contact_3) { create(:contact, :inactive, group: group) }
- subject { described_class.new(project, user).contacts.as_json }
+ let(:issue) { nil }
+
+ subject { described_class.new(project, user).contacts(issue).as_json }
before do
group.add_developer(user)
end
- it 'returns contact data correctly' do
+ it 'returns CRM contacts from group' do
expected_contacts = [
{ 'id' => contact_1.id, 'email' => contact_1.email,
- 'first_name' => contact_1.first_name, 'last_name' => contact_1.last_name },
+ 'first_name' => contact_1.first_name, 'last_name' => contact_1.last_name, 'state' => contact_1.state },
{ 'id' => contact_2.id, 'email' => contact_2.email,
- 'first_name' => contact_2.first_name, 'last_name' => contact_2.last_name }
+ 'first_name' => contact_2.first_name, 'last_name' => contact_2.last_name, 'state' => contact_2.state },
+ { 'id' => contact_3.id, 'email' => contact_3.email,
+ 'first_name' => contact_3.first_name, 'last_name' => contact_3.last_name, 'state' => contact_3.state }
]
expect(subject).to match_array(expected_contacts)
end
+
+ context 'some contacts are already assigned to the issue' do
+ let(:issue) { create(:issue, project: project) }
+
+ before do
+ issue.customer_relations_contacts << [contact_2, contact_3]
+ end
+
+ it 'marks already assigned contacts as set' do
+ expected_contacts = [
+ { 'id' => contact_1.id, 'email' => contact_1.email,
+ 'first_name' => contact_1.first_name, 'last_name' => contact_1.last_name, 'state' => contact_1.state, 'set' => false },
+ { 'id' => contact_2.id, 'email' => contact_2.email,
+ 'first_name' => contact_2.first_name, 'last_name' => contact_2.last_name, 'state' => contact_2.state, 'set' => true },
+ { 'id' => contact_3.id, 'email' => contact_3.email,
+ 'first_name' => contact_3.first_name, 'last_name' => contact_3.last_name, 'state' => contact_3.state, 'set' => true }
+ ]
+
+ expect(subject).to match_array(expected_contacts)
+ end
+ end
end
describe '#labels_as_hash' do
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
index 2008de195ab..8311c4e4d9b 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -2,372 +2,134 @@
require 'spec_helper'
-RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_redis_cache do
- using RSpec::Parameterized::TableSyntax
+RSpec.describe Projects::ContainerRepository::CleanupTagsService do
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+ let_it_be(:user) { container_repository.project.owner }
- include_context 'for a cleanup tags service'
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project, reload: true) { create(:project, :private) }
-
- let(:repository) { create(:container_repository, :root, project: project) }
- let(:service) { described_class.new(container_repository: repository, current_user: user, params: params) }
- let(:tags) { %w[latest A Ba Bb C D E] }
+ let(:params) { {} }
+ let(:extra_params) { {} }
+ let(:service) { described_class.new(container_repository: container_repository, current_user: user, params: params.merge(extra_params)) }
before do
- project.add_maintainer(user) if user
-
stub_container_registry_config(enabled: true)
-
- stub_container_registry_tags(
- repository: repository.path,
- tags: tags
- )
-
- stub_tag_digest('latest', 'sha256:configA')
- stub_tag_digest('A', 'sha256:configA')
- stub_tag_digest('Ba', 'sha256:configB')
- stub_tag_digest('Bb', 'sha256:configB')
- stub_tag_digest('C', 'sha256:configC')
- stub_tag_digest('D', 'sha256:configD')
- stub_tag_digest('E', nil)
-
- stub_digest_config('sha256:configA', 1.hour.ago)
- stub_digest_config('sha256:configB', 5.days.ago)
- stub_digest_config('sha256:configC', 1.month.ago)
- stub_digest_config('sha256:configD', nil)
end
describe '#execute' do
subject { service.execute }
- it_behaves_like 'handling invalid params',
- service_response_extra: {
- before_truncate_size: 0,
- after_truncate_size: 0,
- before_delete_size: 0,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when regex matching everything is specified',
- delete_expectations: [%w(A Ba Bb C D E)],
- service_response_extra: {
- before_truncate_size: 6,
- after_truncate_size: 6,
- before_delete_size: 6,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when delete regex matching specific tags is used',
- service_response_extra: {
- before_truncate_size: 2,
- after_truncate_size: 2,
- before_delete_size: 2,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when delete regex matching specific tags is used with overriding allow regex',
- service_response_extra: {
- before_truncate_size: 1,
- after_truncate_size: 1,
- before_delete_size: 1,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'with allow regex value',
- delete_expectations: [%w(A C D E)],
- service_response_extra: {
- before_truncate_size: 4,
- after_truncate_size: 4,
- before_delete_size: 4,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when keeping only N tags',
- delete_expectations: [%w(Bb Ba C)],
- service_response_extra: {
- before_truncate_size: 4,
- after_truncate_size: 4,
- before_delete_size: 3,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when not keeping N tags',
- delete_expectations: [%w(A Ba Bb C)],
- service_response_extra: {
- before_truncate_size: 4,
- after_truncate_size: 4,
- before_delete_size: 4,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when removing keeping only 3',
- delete_expectations: [%w(Bb Ba C)],
- service_response_extra: {
- before_truncate_size: 6,
- after_truncate_size: 6,
- before_delete_size: 3,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when removing older than 1 day',
- delete_expectations: [%w(Ba Bb C)],
- service_response_extra: {
- before_truncate_size: 6,
- after_truncate_size: 6,
- before_delete_size: 3,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when combining all parameters',
- delete_expectations: [%w(Bb Ba C)],
- service_response_extra: {
- before_truncate_size: 6,
- after_truncate_size: 6,
- before_delete_size: 3,
- cached_tags_count: 0
- },
- supports_caching: true
-
- it_behaves_like 'when running a container_expiration_policy',
- delete_expectations: [%w(Bb Ba C)],
- service_response_extra: {
- before_truncate_size: 6,
- after_truncate_size: 6,
- before_delete_size: 3,
- cached_tags_count: 0
- },
- supports_caching: true
-
- context 'when running a container_expiration_policy with caching' do
- let(:user) { nil }
- let(:params) do
- {
- 'name_regex_delete' => '.*',
- 'keep_n' => 1,
- 'older_than' => '1 day',
- 'container_expiration_policy' => true
- }
- end
-
- it 'expects caching to be used' do
- expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- expect_caching
-
- subject
- end
-
- context 'when setting set to false' do
- before do
- stub_application_setting(container_registry_expiration_policies_caching: false)
- end
-
- it 'does not use caching' do
- expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- expect_no_caching
+ shared_examples 'returning error message' do |message|
+ it "returns error #{message}" do
+ expect(::Projects::ContainerRepository::Gitlab::CleanupTagsService).not_to receive(:new)
+ expect(::Projects::ContainerRepository::ThirdParty::CleanupTagsService).not_to receive(:new)
+ expect(service).not_to receive(:log_info)
- subject
- end
+ expect(subject).to eq(status: :error, message: message)
end
end
- context 'truncating the tags list' do
- let(:params) do
- {
- 'name_regex_delete' => '.*',
- 'keep_n' => 1
- }
- end
-
- shared_examples 'returning the response' do |status:, original_size:, before_truncate_size:, after_truncate_size:, before_delete_size:|
- it 'returns the response' do
- expect_no_caching
+ shared_examples 'handling invalid regular expressions' do
+ shared_examples 'handling invalid regex' do
+ it_behaves_like 'returning error message', 'invalid regex'
- result = subject
+ it 'calls error tracking service' do
+ expect(::Gitlab::ErrorTracking).to receive(:log_exception).and_call_original
- service_response = expected_service_response(
- status: status,
- original_size: original_size,
- deleted: nil
- ).merge(
- before_truncate_size: before_truncate_size,
- after_truncate_size: after_truncate_size,
- before_delete_size: before_delete_size,
- cached_tags_count: 0
- )
-
- expect(result).to eq(service_response)
+ subject
end
end
- where(:max_list_size, :delete_tags_service_status, :expected_status, :expected_truncated) do
- 10 | :success | :success | false
- 10 | :error | :error | false
- 3 | :success | :error | true
- 3 | :error | :error | true
- 0 | :success | :success | false
- 0 | :error | :error | false
- end
+ context 'when name_regex_delete is invalid' do
+ let(:extra_params) { { 'name_regex_delete' => '*test*' } }
- with_them do
- before do
- stub_application_setting(container_registry_cleanup_tags_service_max_list_size: max_list_size)
- allow_next_instance_of(Projects::ContainerRepository::DeleteTagsService) do |service|
- expect(service).to receive(:execute).and_return(status: delete_tags_service_status)
- end
- end
-
- original_size = 7
- keep_n = 1
-
- it_behaves_like(
- 'returning the response',
- status: params[:expected_status],
- original_size: original_size,
- before_truncate_size: original_size - keep_n,
- after_truncate_size: params[:expected_truncated] ? params[:max_list_size] + keep_n : original_size - keep_n,
- before_delete_size: params[:expected_truncated] ? params[:max_list_size] : original_size - keep_n - 1 # one tag is filtered out with older_than filter
- )
+ it_behaves_like 'handling invalid regex'
end
- end
- context 'caching', :freeze_time do
- let(:params) do
- {
- 'name_regex_delete' => '.*',
- 'keep_n' => 1,
- 'older_than' => '1 day',
- 'container_expiration_policy' => true
- }
- end
+ context 'when name_regex is invalid' do
+ let(:extra_params) { { 'name_regex' => '*test*' } }
- let(:tags_and_created_ats) do
- {
- 'A' => 1.hour.ago,
- 'Ba' => 5.days.ago,
- 'Bb' => 5.days.ago,
- 'C' => 1.month.ago,
- 'D' => nil,
- 'E' => nil
- }
+ it_behaves_like 'handling invalid regex'
end
- let(:cacheable_tags) { tags_and_created_ats.reject { |_, value| value.nil? } }
+ context 'when name_regex_keep is invalid' do
+ let(:extra_params) { { 'name_regex_keep' => '*test*' } }
- before do
- expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- # We froze time so we need to set the created_at stubs again
- stub_digest_config('sha256:configA', 1.hour.ago)
- stub_digest_config('sha256:configB', 5.days.ago)
- stub_digest_config('sha256:configC', 1.month.ago)
+ it_behaves_like 'handling invalid regex'
end
+ end
- it 'caches the created_at values' do
- expect_mget(tags_and_created_ats.keys)
- expect_set(cacheable_tags)
-
- expect(subject).to include(cached_tags_count: 0)
+ shared_examples 'handling all types of container repositories' do
+ shared_examples 'calling service' do |service_class, extra_log_data: {}|
+ let(:service_double) { instance_double(service_class.to_s) }
+
+ it "uses cleanup tags service #{service_class}" do
+ expect(service_class).to receive(:new).with(container_repository: container_repository, current_user: user, params: params).and_return(service_double)
+ expect(service_double).to receive(:execute).and_return('return value')
+ expect(service).to receive(:log_info)
+ .with(
+ {
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ project_id: container_repository.project.id
+ }.merge(extra_log_data))
+ expect(subject).to eq('return value')
+ end
end
- context 'with cached values' do
+ context 'with a migrated repository' do
before do
- ::Gitlab::Redis::Cache.with do |redis|
- redis.set(cache_key('C'), rfc3339(1.month.ago))
- end
+ container_repository.update_column(:migration_state, :import_done)
end
- it 'uses them' do
- expect_mget(tags_and_created_ats.keys)
-
- # because C is already in cache, it should not be cached again
- expect_set(cacheable_tags.except('C'))
-
- # We will ping the container registry for all tags *except* for C because it's cached
- expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configA" }).and_call_original
- expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configB" }).twice.and_call_original
- expect(ContainerRegistry::Blob).not_to receive(:new).with(repository, { "digest" => "sha256:configC" })
- expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configD" }).and_call_original
-
- expect(subject).to include(cached_tags_count: 1)
- end
- end
+ context 'supporting the gitlab api' do
+ before do
+ allow(container_repository.gitlab_api_client).to receive(:supports_gitlab_api?).and_return(true)
+ end
- def expect_mget(keys)
- Gitlab::Redis::Cache.with do |redis|
- expect(redis).to receive(:mget).with(keys.map(&method(:cache_key))).and_call_original
+ it_behaves_like 'calling service', ::Projects::ContainerRepository::Gitlab::CleanupTagsService, extra_log_data: { gitlab_cleanup_tags_service: true }
end
- end
-
- def expect_set(tags)
- selected_tags = tags.map do |tag_name, created_at|
- ex = 1.day.seconds - (Time.zone.now - created_at).seconds
- [tag_name, created_at, ex.to_i] if ex.positive?
- end.compact
-
- return if selected_tags.count.zero?
- Gitlab::Redis::Cache.with do |redis|
- expect(redis).to receive(:pipelined).and_call_original
-
- expect_next_instance_of(Redis::PipelinedConnection) do |pipeline|
- selected_tags.each do |tag_name, created_at, ex|
- expect(pipeline).to receive(:set).with(cache_key(tag_name), rfc3339(created_at), ex: ex)
- end
+ context 'not supporting the gitlab api' do
+ before do
+ allow(container_repository.gitlab_api_client).to receive(:supports_gitlab_api?).and_return(false)
end
+
+ it_behaves_like 'calling service', ::Projects::ContainerRepository::ThirdParty::CleanupTagsService, extra_log_data: { third_party_cleanup_tags_service: true }
end
end
- def cache_key(tag_name)
- "container_repository:{#{repository.id}}:tag:#{tag_name}:created_at"
- end
+ context 'with a non migrated repository' do
+ before do
+ container_repository.update_column(:migration_state, :default)
+ container_repository.update!(created_at: ContainerRepository::MIGRATION_PHASE_1_ENDED_AT - 1.week)
+ end
- def rfc3339(date_time)
- # DateTime rfc3339 is different ActiveSupport::TimeWithZone rfc3339
- # The caching will use DateTime rfc3339
- DateTime.rfc3339(date_time.rfc3339).rfc3339
+ it_behaves_like 'calling service', ::Projects::ContainerRepository::ThirdParty::CleanupTagsService, extra_log_data: { third_party_cleanup_tags_service: true }
end
end
- end
- private
+ context 'with valid user' do
+ it_behaves_like 'handling invalid regular expressions'
+ it_behaves_like 'handling all types of container repositories'
+ end
- def stub_tag_digest(tag, digest)
- allow_any_instance_of(ContainerRegistry::Client)
- .to receive(:repository_tag_digest)
- .with(repository.path, tag) { digest }
+ context 'for container expiration policy' do
+ let(:user) { nil }
+ let(:params) { { 'container_expiration_policy' => true } }
- allow_any_instance_of(ContainerRegistry::Client)
- .to receive(:repository_manifest)
- .with(repository.path, tag) do
- { 'config' => { 'digest' => digest } } if digest
+ it_behaves_like 'handling invalid regular expressions'
+ it_behaves_like 'handling all types of container repositories'
end
- end
- def stub_digest_config(digest, created_at)
- allow_any_instance_of(ContainerRegistry::Client)
- .to receive(:blob)
- .with(repository.path, digest, nil) do
- { 'created' => created_at.to_datetime.rfc3339 }.to_json if created_at
+ context 'with not allowed user' do
+ let_it_be(:user) { create(:user) }
+
+ it_behaves_like 'returning error message', 'access denied'
end
- end
- def expect_caching
- ::Gitlab::Redis::Cache.with do |redis|
- expect(redis).to receive(:mget).and_call_original
- expect(redis).to receive(:pipelined).and_call_original
+ context 'with no user' do
+ let(:user) { nil }
- expect_next_instance_of(Redis::PipelinedConnection) do |pipeline|
- expect(pipeline).to receive(:set).and_call_original
- end
+ it_behaves_like 'returning error message', 'access denied'
end
end
end
diff --git a/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb
index d2cdb667659..59827ea035e 100644
--- a/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb
@@ -46,8 +46,6 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do
context 'with several tags pages' do
let(:tags_page_size) { 2 }
- it_behaves_like 'handling invalid params'
-
it_behaves_like 'when regex matching everything is specified',
delete_expectations: [%w[A], %w[Ba Bb], %w[C D], %w[E]]
@@ -105,8 +103,6 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do
context 'with a single tags page' do
let(:tags_page_size) { 1000 }
- it_behaves_like 'handling invalid params'
-
it_behaves_like 'when regex matching everything is specified',
delete_expectations: [%w[A Ba Bb C D E]]
diff --git a/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb
new file mode 100644
index 00000000000..2d034d577ac
--- /dev/null
+++ b/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb
@@ -0,0 +1,370 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ContainerRepository::ThirdParty::CleanupTagsService, :clean_gitlab_redis_cache do
+ using RSpec::Parameterized::TableSyntax
+
+ include_context 'for a cleanup tags service'
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :private) }
+
+ let(:repository) { create(:container_repository, :root, project: project) }
+ let(:service) { described_class.new(container_repository: repository, current_user: user, params: params) }
+ let(:tags) { %w[latest A Ba Bb C D E] }
+
+ before do
+ project.add_maintainer(user) if user
+
+ stub_container_registry_config(enabled: true)
+
+ stub_container_registry_tags(
+ repository: repository.path,
+ tags: tags
+ )
+
+ stub_tag_digest('latest', 'sha256:configA')
+ stub_tag_digest('A', 'sha256:configA')
+ stub_tag_digest('Ba', 'sha256:configB')
+ stub_tag_digest('Bb', 'sha256:configB')
+ stub_tag_digest('C', 'sha256:configC')
+ stub_tag_digest('D', 'sha256:configD')
+ stub_tag_digest('E', nil)
+
+ stub_digest_config('sha256:configA', 1.hour.ago)
+ stub_digest_config('sha256:configB', 5.days.ago)
+ stub_digest_config('sha256:configC', 1.month.ago)
+ stub_digest_config('sha256:configD', nil)
+ end
+
+ describe '#execute' do
+ subject { service.execute }
+
+ it_behaves_like 'when regex matching everything is specified',
+ delete_expectations: [%w[A Ba Bb C D E]],
+ service_response_extra: {
+ before_truncate_size: 6,
+ after_truncate_size: 6,
+ before_delete_size: 6,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when delete regex matching specific tags is used',
+ service_response_extra: {
+ before_truncate_size: 2,
+ after_truncate_size: 2,
+ before_delete_size: 2,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when delete regex matching specific tags is used with overriding allow regex',
+ service_response_extra: {
+ before_truncate_size: 1,
+ after_truncate_size: 1,
+ before_delete_size: 1,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'with allow regex value',
+ delete_expectations: [%w[A C D E]],
+ service_response_extra: {
+ before_truncate_size: 4,
+ after_truncate_size: 4,
+ before_delete_size: 4,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when keeping only N tags',
+ delete_expectations: [%w[Bb Ba C]],
+ service_response_extra: {
+ before_truncate_size: 4,
+ after_truncate_size: 4,
+ before_delete_size: 3,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when not keeping N tags',
+ delete_expectations: [%w[A Ba Bb C]],
+ service_response_extra: {
+ before_truncate_size: 4,
+ after_truncate_size: 4,
+ before_delete_size: 4,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when removing keeping only 3',
+ delete_expectations: [%w[Bb Ba C]],
+ service_response_extra: {
+ before_truncate_size: 6,
+ after_truncate_size: 6,
+ before_delete_size: 3,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when removing older than 1 day',
+ delete_expectations: [%w[Ba Bb C]],
+ service_response_extra: {
+ before_truncate_size: 6,
+ after_truncate_size: 6,
+ before_delete_size: 3,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when combining all parameters',
+ delete_expectations: [%w[Bb Ba C]],
+ service_response_extra: {
+ before_truncate_size: 6,
+ after_truncate_size: 6,
+ before_delete_size: 3,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ it_behaves_like 'when running a container_expiration_policy',
+ delete_expectations: [%w[Bb Ba C]],
+ service_response_extra: {
+ before_truncate_size: 6,
+ after_truncate_size: 6,
+ before_delete_size: 3,
+ cached_tags_count: 0
+ },
+ supports_caching: true
+
+ context 'when running a container_expiration_policy with caching' do
+ let(:user) { nil }
+ let(:params) do
+ {
+ 'name_regex_delete' => '.*',
+ 'keep_n' => 1,
+ 'older_than' => '1 day',
+ 'container_expiration_policy' => true
+ }
+ end
+
+ it 'expects caching to be used' do
+ expect_delete(%w[Bb Ba C], container_expiration_policy: true)
+ expect_caching
+
+ subject
+ end
+
+ context 'when setting set to false' do
+ before do
+ stub_application_setting(container_registry_expiration_policies_caching: false)
+ end
+
+ it 'does not use caching' do
+ expect_delete(%w[Bb Ba C], container_expiration_policy: true)
+ expect_no_caching
+
+ subject
+ end
+ end
+ end
+
+ context 'when truncating the tags list' do
+ let(:params) do
+ {
+ 'name_regex_delete' => '.*',
+ 'keep_n' => 1
+ }
+ end
+
+ shared_examples 'returning the response' do
+ |status:, original_size:, before_truncate_size:, after_truncate_size:, before_delete_size:|
+ it 'returns the response' do
+ expect_no_caching
+
+ result = subject
+
+ service_response = expected_service_response(
+ status: status,
+ original_size: original_size,
+ deleted: nil
+ ).merge(
+ before_truncate_size: before_truncate_size,
+ after_truncate_size: after_truncate_size,
+ before_delete_size: before_delete_size,
+ cached_tags_count: 0
+ )
+
+ expect(result).to eq(service_response)
+ end
+ end
+
+ where(:max_list_size, :delete_tags_service_status, :expected_status, :expected_truncated) do
+ 10 | :success | :success | false
+ 10 | :error | :error | false
+ 3 | :success | :error | true
+ 3 | :error | :error | true
+ 0 | :success | :success | false
+ 0 | :error | :error | false
+ end
+
+ with_them do
+ before do
+ stub_application_setting(container_registry_cleanup_tags_service_max_list_size: max_list_size)
+ allow_next_instance_of(Projects::ContainerRepository::DeleteTagsService) do |service|
+ allow(service).to receive(:execute).and_return(status: delete_tags_service_status)
+ end
+ end
+
+ original_size = 7
+ keep_n = 1
+
+ it_behaves_like(
+ 'returning the response',
+ status: params[:expected_status],
+ original_size: original_size,
+ before_truncate_size: original_size - keep_n,
+ after_truncate_size: params[:expected_truncated] ? params[:max_list_size] + keep_n : original_size - keep_n,
+ # one tag is filtered out with older_than filter
+ before_delete_size: params[:expected_truncated] ? params[:max_list_size] : original_size - keep_n - 1
+ )
+ end
+ end
+
+ context 'with caching', :freeze_time do
+ let(:params) do
+ {
+ 'name_regex_delete' => '.*',
+ 'keep_n' => 1,
+ 'older_than' => '1 day',
+ 'container_expiration_policy' => true
+ }
+ end
+
+ let(:tags_and_created_ats) do
+ {
+ 'A' => 1.hour.ago,
+ 'Ba' => 5.days.ago,
+ 'Bb' => 5.days.ago,
+ 'C' => 1.month.ago,
+ 'D' => nil,
+ 'E' => nil
+ }
+ end
+
+ let(:cacheable_tags) { tags_and_created_ats.reject { |_, value| value.nil? } }
+
+ before do
+ expect_delete(%w[Bb Ba C], container_expiration_policy: true)
+ # We froze time so we need to set the created_at stubs again
+ stub_digest_config('sha256:configA', 1.hour.ago)
+ stub_digest_config('sha256:configB', 5.days.ago)
+ stub_digest_config('sha256:configC', 1.month.ago)
+ end
+
+ it 'caches the created_at values' do
+ expect_mget(tags_and_created_ats.keys)
+ expect_set(cacheable_tags)
+
+ expect(subject).to include(cached_tags_count: 0)
+ end
+
+ context 'with cached values' do
+ before do
+ ::Gitlab::Redis::Cache.with do |redis|
+ redis.set(cache_key('C'), rfc3339(1.month.ago))
+ end
+ end
+
+ it 'uses them' do
+ expect_mget(tags_and_created_ats.keys)
+
+ # because C is already in cache, it should not be cached again
+ expect_set(cacheable_tags.except('C'))
+
+ # We will ping the container registry for all tags *except* for C because it's cached
+ expect(ContainerRegistry::Blob)
+ .to receive(:new).with(repository, { "digest" => "sha256:configA" }).and_call_original
+ expect(ContainerRegistry::Blob)
+ .to receive(:new).with(repository, { "digest" => "sha256:configB" }).twice.and_call_original
+ expect(ContainerRegistry::Blob).not_to receive(:new).with(repository, { "digest" => "sha256:configC" })
+ expect(ContainerRegistry::Blob)
+ .to receive(:new).with(repository, { "digest" => "sha256:configD" }).and_call_original
+
+ expect(subject).to include(cached_tags_count: 1)
+ end
+ end
+
+ def expect_mget(keys)
+ Gitlab::Redis::Cache.with do |redis|
+ parameters = keys.map { |k| cache_key(k) }
+ expect(redis).to receive(:mget).with(parameters).and_call_original
+ end
+ end
+
+ def expect_set(tags)
+ selected_tags = tags.map do |tag_name, created_at|
+ ex = 1.day.seconds - (Time.zone.now - created_at).seconds
+ [tag_name, created_at, ex.to_i] if ex.positive?
+ end.compact
+
+ return if selected_tags.count.zero?
+
+ Gitlab::Redis::Cache.with do |redis|
+ expect(redis).to receive(:pipelined).and_call_original
+
+ expect_next_instance_of(Redis::PipelinedConnection) do |pipeline|
+ selected_tags.each do |tag_name, created_at, ex|
+ expect(pipeline).to receive(:set).with(cache_key(tag_name), rfc3339(created_at), ex: ex)
+ end
+ end
+ end
+ end
+
+ def cache_key(tag_name)
+ "container_repository:{#{repository.id}}:tag:#{tag_name}:created_at"
+ end
+
+ def rfc3339(date_time)
+ # DateTime rfc3339 is different ActiveSupport::TimeWithZone rfc3339
+ # The caching will use DateTime rfc3339
+ DateTime.rfc3339(date_time.rfc3339).rfc3339
+ end
+ end
+ end
+
+ private
+
+ def stub_tag_digest(tag, digest)
+ allow(repository.client)
+ .to receive(:repository_tag_digest)
+ .with(repository.path, tag) { digest }
+
+ allow(repository.client)
+ .to receive(:repository_manifest)
+ .with(repository.path, tag) do
+ { 'config' => { 'digest' => digest } } if digest
+ end
+ end
+
+ def stub_digest_config(digest, created_at)
+ allow(repository.client)
+ .to receive(:blob)
+ .with(repository.path, digest, nil) do
+ { 'created' => created_at.to_datetime.rfc3339 }.to_json if created_at
+ end
+ end
+
+ def expect_caching
+ ::Gitlab::Redis::Cache.with do |redis|
+ expect(redis).to receive(:mget).and_call_original
+ expect(redis).to receive(:pipelined).and_call_original
+
+ expect_next_instance_of(Redis::PipelinedConnection) do |pipeline|
+ expect(pipeline).to receive(:set).and_call_original
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 8269dbebccb..f7f02769f6a 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -146,20 +146,6 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi
expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
expect { another_project_mr.reload }.not_to raise_error
end
-
- context 'when extract_mr_diff_deletions feature flag is disabled' do
- before do
- stub_feature_flags(extract_mr_diff_deletions: false)
- end
-
- it 'also deletes merge request diffs' do
- merge_request_diffs = merge_request.merge_request_diffs
- expect(merge_request_diffs.size).to eq(1)
-
- expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
- expect { another_project_mr.reload }.not_to raise_error
- end
- end
end
it_behaves_like 'deleting the project'
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index ab9f99f893d..6dc72948541 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -276,6 +276,15 @@ RSpec.describe Projects::ImportService do
expect(result[:status]).to eq :error
expect(result[:message]).to include('Only allowed ports are 80, 443')
end
+
+ it 'fails with file scheme' do
+ project.import_url = "file:///tmp/dir.git"
+
+ result = subject.execute
+
+ expect(result[:status]).to eq :error
+ expect(result[:message]).to include('Only allowed schemes are http, https')
+ end
end
it_behaves_like 'measurable service' do
diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb
index 17d01a57221..ee8f7fb2ef2 100644
--- a/spec/services/projects/update_repository_storage_service_spec.rb
+++ b/spec/services/projects/update_repository_storage_service_spec.rb
@@ -37,10 +37,6 @@ RSpec.describe Projects::UpdateRepositoryStorageService do
context 'when the move succeeds' do
it 'moves the repository to the new storage and unmarks the repository as read-only' do
- old_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path_to_repo
- end
-
expect(project_repository_double).to receive(:replicate)
.with(project.repository.raw)
expect(project_repository_double).to receive(:checksum)
@@ -53,7 +49,6 @@ RSpec.describe Projects::UpdateRepositoryStorageService do
expect(result).to be_success
expect(project).not_to be_repository_read_only
expect(project.repository_storage).to eq('test_second_storage')
- expect(gitlab_shell.repository_exists?('default', old_path)).to be(false)
expect(project.project_repository.shard_name).to eq('test_second_storage')
end
end
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 85d3e99109d..7d8951bf111 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -11,10 +11,27 @@ RSpec.describe Projects::UpdateService do
create(:project, creator: user, namespace: user.namespace)
end
+ shared_examples 'publishing Projects::ProjectAttributesChangedEvent' do |params:, attributes:|
+ it "publishes Projects::ProjectAttributesChangedEvent" do
+ expect { update_project(project, user, params) }
+ .to publish_event(Projects::ProjectAttributesChangedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id,
+ attributes: attributes
+ )
+ end
+ end
+
describe '#execute' do
let(:admin) { create(:admin) }
context 'when changing visibility level' do
+ it_behaves_like 'publishing Projects::ProjectAttributesChangedEvent',
+ params: { visibility_level: Gitlab::VisibilityLevel::INTERNAL },
+ attributes: %w[updated_at visibility_level]
+
context 'when visibility_level changes to INTERNAL' do
it 'updates the project to internal' do
expect(TodosDestroyer::ProjectPrivateWorker).not_to receive(:perform_in)
@@ -290,7 +307,7 @@ RSpec.describe Projects::UpdateService do
context 'when we update project but not enabling a wiki' do
it 'does not try to create an empty wiki' do
- TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path)
+ project.wiki.repository.raw.remove
result = update_project(project, user, { name: 'test1' })
@@ -311,7 +328,7 @@ RSpec.describe Projects::UpdateService do
context 'when enabling a wiki' do
it 'creates a wiki' do
project.project_feature.update!(wiki_access_level: ProjectFeature::DISABLED)
- TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path)
+ project.wiki.repository.raw.remove
result = update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED })
@@ -323,7 +340,7 @@ RSpec.describe Projects::UpdateService do
it 'logs an error and creates a metric when wiki can not be created' do
project.project_feature.update!(wiki_access_level: ProjectFeature::DISABLED)
- expect_any_instance_of(ProjectWiki).to receive(:wiki).and_raise(Wiki::CouldNotCreateWikiError)
+ expect_any_instance_of(ProjectWiki).to receive(:create_wiki_repository).and_raise(Wiki::CouldNotCreateWikiError)
expect_any_instance_of(described_class).to receive(:log_error).with("Could not create wiki for #{project.full_name}")
counter = double(:counter)
@@ -348,7 +365,37 @@ RSpec.describe Projects::UpdateService do
end
end
+ context 'when changes project features' do
+ # Using some sample features for testing.
+ # Not using all the features because some of them must be enabled/disabled together
+ %w[issues wiki forking].each do |feature_name|
+ let(:feature) { "#{feature_name}_access_level" }
+ let(:params) do
+ { project_feature_attributes: { feature => ProjectFeature::ENABLED } }
+ end
+
+ before do
+ project.project_feature.update!(feature => ProjectFeature::DISABLED)
+ end
+
+ it 'publishes Projects::ProjectFeaturesChangedEvent' do
+ expect { update_project(project, user, params) }
+ .to publish_event(Projects::ProjectFeaturesChangedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id,
+ features: ["updated_at", feature]
+ )
+ end
+ end
+ end
+
context 'when archiving a project' do
+ it_behaves_like 'publishing Projects::ProjectAttributesChangedEvent',
+ params: { archived: true },
+ attributes: %w[updated_at archived]
+
it 'publishes a ProjectTransferedEvent' do
expect { update_project(project, user, archived: true) }
.to publish_event(Projects::ProjectArchivedEvent)
diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb
index 3615747e191..47ebd55022f 100644
--- a/spec/services/repositories/changelog_service_spec.rb
+++ b/spec/services/repositories/changelog_service_spec.rb
@@ -67,10 +67,11 @@ RSpec.describe Repositories::ChangelogService 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 }
- ])
+ .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)
@@ -135,10 +136,11 @@ RSpec.describe Repositories::ChangelogService 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 }
- ])
+ .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)
diff --git a/spec/services/resource_events/merge_into_notes_service_spec.rb b/spec/services/resource_events/merge_into_notes_service_spec.rb
index abe00e72f20..ebfd942066f 100644
--- a/spec/services/resource_events/merge_into_notes_service_spec.rb
+++ b/spec/services/resource_events/merge_into_notes_service_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe ResourceEvents::MergeIntoNotesService do
notes = described_class.new(resource, user).execute([note1, note2])
- expected = [note1, event1, note2, event2].map(&:discussion_id)
+ expected = [note1, event1, note2, event2].map(&:reload).map(&:discussion_id)
expect(notes.map(&:discussion_id)).to eq expected
end
@@ -65,7 +65,7 @@ RSpec.describe ResourceEvents::MergeIntoNotesService do
last_fetched_at: 2.days.ago).execute
expect(notes.count).to eq 1
- expect(notes.first.discussion_id).to eq event.discussion_id
+ expect(notes.first.discussion_id).to eq event.reload.discussion_id
end
it "preloads the note author's status" do
diff --git a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
index 9c6b6a33b57..f368e107c60 100644
--- a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
+++ b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
@@ -19,10 +19,11 @@ RSpec.describe ResourceEvents::SyntheticMilestoneNotesBuilderService do
notes = described_class.new(issue, user).execute
expect(notes.map(&:created_at)).to eq(events.map(&:created_at))
- expect(notes.map(&:note)).to eq([
- "changed milestone to %#{milestone.iid}",
- 'removed milestone'
- ])
+ expect(notes.map(&:note)).to eq(
+ [
+ "changed milestone to %#{milestone.iid}",
+ 'removed milestone'
+ ])
end
it_behaves_like 'filters by paginated notes', :resource_milestone_event
diff --git a/spec/services/snippets/update_repository_storage_service_spec.rb b/spec/services/snippets/update_repository_storage_service_spec.rb
index fdea3615fb1..9874189f73a 100644
--- a/spec/services/snippets/update_repository_storage_service_spec.rb
+++ b/spec/services/snippets/update_repository_storage_service_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe Snippets::UpdateRepositoryStorageService do
- include Gitlab::ShellAdapter
-
subject { described_class.new(repository_storage_move) }
describe "#execute" do
@@ -32,10 +30,6 @@ RSpec.describe Snippets::UpdateRepositoryStorageService do
context 'when the move succeeds' do
it 'moves the repository to the new storage and unmarks the repository as read-only' do
- old_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- snippet.repository.path_to_repo
- end
-
expect(snippet_repository_double).to receive(:replicate)
.with(snippet.repository.raw)
expect(snippet_repository_double).to receive(:checksum)
@@ -48,7 +42,6 @@ RSpec.describe Snippets::UpdateRepositoryStorageService do
expect(result).to be_success
expect(snippet).not_to be_repository_read_only
expect(snippet.repository_storage).to eq(destination)
- expect(gitlab_shell.repository_exists?('default', old_path)).to be(false)
expect(snippet.snippet_repository.shard_name).to eq(destination)
end
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index b32599d4af8..03e1811c8a5 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -388,24 +388,95 @@ RSpec.describe Users::DestroyService do
context 'batched nullify' do
let(:other_user) { create(:user) }
+ # rubocop:disable Layout/LineLength
+ def nullify_in_batches_regexp(table, column, user, batch_size: 100)
+ %r{^UPDATE "#{table}" SET "#{column}" = NULL WHERE "#{table}"."id" IN \(SELECT "#{table}"."id" FROM "#{table}" WHERE "#{table}"."#{column}" = #{user.id} LIMIT #{batch_size}\)}
+ end
+
+ def delete_in_batches_regexps(table, column, user, items, batch_size: 1000)
+ select_query = %r{^SELECT "#{table}".* FROM "#{table}" WHERE "#{table}"."#{column}" = #{user.id}.*ORDER BY "#{table}"."id" ASC LIMIT #{batch_size}}
+
+ [select_query] + items.map { |item| %r{^DELETE FROM "#{table}" WHERE "#{table}"."id" = #{item.id}} }
+ end
+ # rubocop:enable Layout/LineLength
+
it 'nullifies related associations in batches' do
expect(other_user).to receive(:nullify_dependent_associations_in_batches).and_call_original
described_class.new(user).execute(other_user, skip_authorization: true)
end
- it 'nullifies last_updated_issues, closed_issues, resource_label_events' do
+ it 'nullifies issues and resource associations', :aggregate_failures do
issue = create(:issue, closed_by: other_user, updated_by: other_user)
resource_label_event = create(:resource_label_event, user: other_user)
+ resource_state_event = create(:resource_state_event, user: other_user)
+ todos = create_list(:todo, 2, project: issue.project, user: other_user, author: other_user, target: issue)
+ event = create(:event, project: issue.project, author: other_user)
- described_class.new(user).execute(other_user, skip_authorization: true)
+ query_recorder = ActiveRecord::QueryRecorder.new do
+ described_class.new(user).execute(other_user, skip_authorization: true)
+ end
issue.reload
resource_label_event.reload
+ resource_state_event.reload
expect(issue.closed_by).to be_nil
expect(issue.updated_by).to be_nil
expect(resource_label_event.user).to be_nil
+ expect(resource_state_event.user).to be_nil
+ expect(other_user.authored_todos).to be_empty
+ expect(other_user.todos).to be_empty
+ expect(other_user.authored_events).to be_empty
+
+ expected_queries = [
+ nullify_in_batches_regexp(:issues, :updated_by_id, other_user),
+ nullify_in_batches_regexp(:issues, :closed_by_id, other_user),
+ nullify_in_batches_regexp(:resource_label_events, :user_id, other_user),
+ nullify_in_batches_regexp(:resource_state_events, :user_id, other_user)
+ ]
+
+ expected_queries += delete_in_batches_regexps(:todos, :user_id, other_user, todos)
+ expected_queries += delete_in_batches_regexps(:todos, :author_id, other_user, todos)
+ expected_queries += delete_in_batches_regexps(:events, :author_id, other_user, [event])
+
+ expect(query_recorder.log).to include(*expected_queries)
+ end
+
+ it 'nullifies merge request associations', :aggregate_failures do
+ merge_request = create(:merge_request, source_project: project, target_project: project,
+ assignee: other_user, updated_by: other_user, merge_user: other_user)
+ merge_request.metrics.update!(merged_by: other_user, latest_closed_by: other_user)
+ merge_request.reviewers = [other_user]
+ merge_request.assignees = [other_user]
+
+ query_recorder = ActiveRecord::QueryRecorder.new do
+ described_class.new(user).execute(other_user, skip_authorization: true)
+ end
+
+ merge_request.reload
+
+ expect(merge_request.updated_by).to be_nil
+ expect(merge_request.assignee).to be_nil
+ expect(merge_request.assignee_id).to be_nil
+ expect(merge_request.metrics.merged_by).to be_nil
+ expect(merge_request.metrics.latest_closed_by).to be_nil
+ expect(merge_request.reviewers).to be_empty
+ expect(merge_request.assignees).to be_empty
+
+ expected_queries = [
+ nullify_in_batches_regexp(:merge_requests, :updated_by_id, other_user),
+ nullify_in_batches_regexp(:merge_requests, :assignee_id, other_user),
+ nullify_in_batches_regexp(:merge_request_metrics, :merged_by_id, other_user),
+ nullify_in_batches_regexp(:merge_request_metrics, :latest_closed_by_id, other_user)
+ ]
+
+ expected_queries += delete_in_batches_regexps(:merge_request_assignees, :user_id, other_user,
+ merge_request.assignees)
+ expected_queries += delete_in_batches_regexps(:merge_request_reviewers, :user_id, other_user,
+ merge_request.reviewers)
+
+ expect(query_recorder.log).to include(*expected_queries)
end
end
end
diff --git a/spec/services/users/dismiss_namespace_callout_service_spec.rb b/spec/services/users/dismiss_namespace_callout_service_spec.rb
deleted file mode 100644
index fbcdb66c9e8..00000000000
--- a/spec/services/users/dismiss_namespace_callout_service_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Users::DismissNamespaceCalloutService do
- describe '#execute' do
- let_it_be(:user) { create(:user) }
-
- let(:params) { { feature_name: feature_name, namespace_id: user.namespace.id } }
- let(:feature_name) { Users::NamespaceCallout.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::NamespaceCallout
-
- it 'sets the namespace_id' do
- expect(execute.namespace_id).to eq(user.namespace.id)
- end
- end
-end
diff --git a/spec/services/users/refresh_authorized_projects_service_spec.rb b/spec/services/users/refresh_authorized_projects_service_spec.rb
index e6ccb2b16e7..e33886d2add 100644
--- a/spec/services/users/refresh_authorized_projects_service_spec.rb
+++ b/spec/services/users/refresh_authorized_projects_service_spec.rb
@@ -108,8 +108,8 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
describe '#update_authorizations' do
context 'when there are no rows to add and remove' do
it 'does not change authorizations' do
- expect(user).not_to receive(:remove_project_authorizations)
- expect(ProjectAuthorization).not_to receive(:insert_authorizations)
+ expect(ProjectAuthorization).not_to receive(:delete_all_in_batches_for_user)
+ expect(ProjectAuthorization).not_to receive(:insert_all_in_batches)
service.update_authorizations([], [])
end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index fed3ae7a543..551c3dbcc82 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -75,7 +75,8 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
'Content-Type' => 'application/json',
'User-Agent' => "GitLab/#{Gitlab::VERSION}",
'X-Gitlab-Event' => 'Push Hook',
- 'X-Gitlab-Event-UUID' => uuid
+ 'X-Gitlab-Event-UUID' => uuid,
+ 'X-Gitlab-Instance' => Gitlab.config.gitlab.base_url
}
end
@@ -164,7 +165,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
end
end
- it 'POSTs the data as JSON' do
+ it 'POSTs the data as JSON and returns expected headers' do
stub_full_request(project_hook.url, method: :post)
service_instance.execute
@@ -174,6 +175,22 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
).once
end
+ context 'when webhooks_gitlab_instance_header flag is disabled' do
+ before do
+ stub_feature_flags(webhooks_gitlab_instance_header: false)
+ end
+
+ it 'excludes the X-Gitlab-Instance header' do
+ stub_full_request(project_hook.url, method: :post)
+
+ service_instance.execute
+
+ expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url)).with(
+ headers: headers.except('X-Gitlab-Instance')
+ ).once
+ end
+ end
+
context 'when the data is a Gitlab::DataBuilder::Pipeline' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:data) { ::Gitlab::DataBuilder::Pipeline.new(pipeline) }
diff --git a/spec/services/web_hooks/log_execution_service_spec.rb b/spec/services/web_hooks/log_execution_service_spec.rb
index 1967a8368fb..1b8ff9f2a05 100644
--- a/spec/services/web_hooks/log_execution_service_spec.rb
+++ b/spec/services/web_hooks/log_execution_service_spec.rb
@@ -41,12 +41,21 @@ RSpec.describe WebHooks::LogExecutionService do
service.execute
end
+ it 'does not update the last failure when the feature flag is disabled' do
+ stub_feature_flags(web_hooks_disable_failed: false)
+
+ expect(project_hook).not_to receive(:update_last_failure)
+
+ service.execute
+ end
+
context 'obtaining an exclusive lease' do
let(:lease_key) { "web_hooks:update_hook_failure_state:#{project_hook.id}" }
it 'updates failure state using a lease that ensures fresh state is written' do
service = described_class.new(hook: project_hook, log_data: data, response_category: :error)
- WebHook.find(project_hook.id).update!(backoff_count: 1)
+ # Write state somewhere else, so that the hook is out-of-date
+ WebHook.find(project_hook.id).update!(recent_failures: 5, disabled_until: 10.minutes.from_now, backoff_count: 1)
lease = stub_exclusive_lease(lease_key, timeout: described_class::LOCK_TTL)
@@ -69,6 +78,8 @@ RSpec.describe WebHooks::LogExecutionService do
subject(:service) { described_class.new(hook: project_hook, log_data: data, response_category: response_category) }
before do
+ # stub LOCK_RETRY to be 0 in order for tests to run quicker
+ stub_const("#{described_class.name}::LOCK_RETRY", 0)
stub_exclusive_lease_taken(lease_key, timeout: described_class::LOCK_TTL)
allow(project_hook).to receive(:executable?).and_return(executable)
end
@@ -146,36 +157,10 @@ RSpec.describe WebHooks::LogExecutionService do
data[:response_status] = '500'
end
- it 'does not increment the failure count' do
- expect { service.execute }.not_to change(project_hook, :recent_failures)
- end
-
it 'backs off' do
- expect { service.execute }.to change(project_hook, :disabled_until)
- end
-
- it 'increases the backoff count' do
- expect { service.execute }.to change(project_hook, :backoff_count).by(1)
- end
-
- context 'when the previous cool-off was near the maximum' do
- before do
- project_hook.update!(disabled_until: 5.minutes.ago, backoff_count: 8)
- end
+ expect(project_hook).to receive(:backoff!)
- it 'sets the disabled_until attribute' do
- expect { service.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
- end
- end
-
- context 'when we have backed-off many many times' do
- before do
- project_hook.update!(disabled_until: 5.minutes.ago, backoff_count: 365)
- end
-
- it 'sets the disabled_until attribute' do
- expect { service.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
- end
+ service.execute
end
end
end
diff --git a/spec/services/work_items/update_service_spec.rb b/spec/services/work_items/update_service_spec.rb
index e8b82b0b4f2..1761d1104dd 100644
--- a/spec/services/work_items/update_service_spec.rb
+++ b/spec/services/work_items/update_service_spec.rb
@@ -88,6 +88,26 @@ RSpec.describe WorkItems::UpdateService do
end
end
+ context 'when decription is changed' do
+ let(:opts) { { description: 'description changed' } }
+
+ it 'triggers GraphQL description updated subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_description_updated).with(work_item).and_call_original
+
+ update_work_item
+ end
+ end
+
+ context 'when decription is not changed' do
+ let(:opts) { { title: 'title changed' } }
+
+ it 'does not trigger GraphQL description updated subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_description_updated)
+
+ update_work_item
+ end
+ end
+
context 'when updating state_event' do
context 'when state_event is close' do
let(:opts) { { state_event: 'close' } }
@@ -292,5 +312,65 @@ RSpec.describe WorkItems::UpdateService do
end
end
end
+
+ describe 'label updates' do
+ let_it_be(:label1) { create(:label, project: project) }
+ let_it_be(:label2) { create(:label, project: project) }
+
+ context 'when labels are changed' do
+ let(:label) { create(:label, project: project) }
+ let(:opts) { { label_ids: [label1.id] } }
+
+ it 'tracks users updating work item labels' do
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).to receive(:track_work_item_labels_changed_action).with(author: current_user)
+
+ update_work_item
+ end
+
+ it_behaves_like 'broadcasting issuable labels updates' do
+ let(:issuable) { work_item }
+ let(:label_a) { label1 }
+ let(:label_b) { label2 }
+
+ def update_issuable(update_params)
+ described_class.new(
+ project: project,
+ current_user: current_user,
+ params: update_params,
+ spam_params: spam_params,
+ widget_params: widget_params
+ ).execute(work_item)
+ end
+ end
+ end
+
+ context 'when labels are not changed' do
+ shared_examples 'work item update that does not track label updates' do
+ it 'does not track users updating work item labels' do
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).not_to receive(:track_work_item_labels_changed_action)
+
+ update_work_item
+ end
+ end
+
+ context 'when labels param is not provided' do
+ let(:opts) { { title: 'not updating labels' } }
+
+ it_behaves_like 'work item update that does not track label updates'
+ end
+
+ context 'when labels param is provided but labels remain unchanged' do
+ let(:opts) { { label_ids: [] } }
+
+ it_behaves_like 'work item update that does not track label updates'
+ end
+
+ context 'when labels param is provided invalid values' do
+ let(:opts) { { label_ids: [non_existing_record_id] } }
+
+ it_behaves_like 'work item update that does not track label updates'
+ end
+ end
+ end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c75f651fb92..8a1fa486bde 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-if $".include?(File.expand_path('fast_spec_helper.rb', __dir__))
+if $LOADED_FEATURES.include?(File.expand_path('fast_spec_helper.rb', __dir__))
warn 'Detected fast_spec_helper is loaded first than spec_helper.'
warn 'If running test files using both spec_helper and fast_spec_helper,'
warn 'make sure spec_helper is loaded first, or run rspec with `-r spec_helper`.'
@@ -140,7 +140,6 @@ RSpec.configure do |config|
config.include FixtureHelpers
config.include NonExistingRecordsHelpers
config.include GitlabRoutingHelper
- config.include StubExperiments
config.include StubGitlabCalls
config.include NextFoundInstanceOf
config.include NextInstanceOf
@@ -181,13 +180,15 @@ RSpec.configure do |config|
config.include RSpec::Benchmark::Matchers, type: :benchmark
config.include DetailedErrorHelpers
+ config.include_context 'when rendered has no HTML escapes', type: :view
+
include StubFeatureFlags
include StubSnowplow
include StubMember
if ENV['CI'] || ENV['RETRIES']
- # This includes the first try, i.e. tests will be run 4 times before failing.
- config.default_retry_count = ENV.fetch('RETRIES', 3).to_i + 1
+ # This includes the first try, i.e. tests will be run 2 times before failing.
+ config.default_retry_count = ENV.fetch('RETRIES', 1).to_i + 1
# Do not retry controller tests because rspec-retry cannot properly
# reset the controller which may contain data from last attempt. See
@@ -310,9 +311,6 @@ RSpec.configure do |config|
# See https://docs.gitlab.com/ee/development/feature_flags/#selectively-disable-by-actor
stub_feature_flags(legacy_merge_request_state_check_for_merged_result_pipelines: false)
- # Will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/369875
- stub_feature_flags(override_group_level_protected_environment_settings_permission: false)
-
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
else
unstub_all_feature_flags
@@ -407,8 +405,7 @@ RSpec.configure do |config|
with_sidekiq_server_middleware do |chain|
Gitlab::SidekiqMiddleware.server_configurator(
metrics: false, # The metrics don't go anywhere in tests
- arguments_logger: false, # We're not logging the regular messages for inline jobs
- memory_killer: false # This is not a thing we want to do inline in tests
+ arguments_logger: false # We're not logging the regular messages for inline jobs
).call(chain)
chain.add DisableQueryLimit
chain.insert_after ::Gitlab::SidekiqMiddleware::RequestStoreMiddleware, IsolatedRequestStore
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index a5d845f5177..57065400220 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -7,7 +7,7 @@ require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
# Give CI some extra time
-timeout = ENV['CI'] || ENV['CI_SERVER'] ? 60 : 30
+timeout = ENV['CI'] || ENV['CI_SERVER'] ? 30 : 10
# Support running Capybara on a specific port to allow saving commonly used pages
Capybara.server_port = ENV['CAPYBARA_PORT'] if ENV['CAPYBARA_PORT']
diff --git a/spec/support/capybara_slow_finder.rb b/spec/support/capybara_slow_finder.rb
new file mode 100644
index 00000000000..975ddd52c1f
--- /dev/null
+++ b/spec/support/capybara_slow_finder.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Capybara
+ MESSAGE = <<~MSG
+ Timeout (%{timeout}s) reached while running a waiting Capybara finder.
+ Consider using a non-waiting finder.
+
+ See https://www.cloudbees.com/blog/faster-rails-tests
+ MSG
+
+ module Node
+ class Base
+ # Inspired by https://github.com/ngauthier/capybara-slow_finder_errors
+ module SlowFinder
+ def synchronize(seconds = nil, errors: nil)
+ start_time = Gitlab::Metrics::System.monotonic_time
+
+ super
+ rescue Capybara::ElementNotFound => e
+ seconds ||= Capybara.default_max_wait_time
+
+ raise e unless seconds > 0 && Gitlab::Metrics::System.monotonic_time - start_time > seconds
+
+ message = format(MESSAGE, timeout: seconds)
+ raise e, "#{$!}\n\n#{message}", e.backtrace
+ end
+ end
+
+ prepend SlowFinder
+ end
+ end
+end
diff --git a/spec/support/cross_database_modification.rb b/spec/support/cross_database_modification.rb
deleted file mode 100644
index e0d91001c03..00000000000
--- a/spec/support/cross_database_modification.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.configure do |config|
- config.after do |example|
- [::ApplicationRecord, ::Ci::ApplicationRecord].each do |base_class|
- base_class.gitlab_transactions_stack.clear if base_class.respond_to?(:gitlab_transactions_stack)
- end
- end
-end
diff --git a/spec/support/database/multiple_databases.rb b/spec/support/database/multiple_databases.rb
index 05f26e57e9c..25c3b6e74ce 100644
--- a/spec/support/database/multiple_databases.rb
+++ b/spec/support/database/multiple_databases.rb
@@ -2,6 +2,15 @@
module Database
module MultipleDatabases
+ def run_and_cleanup(example)
+ # Each example may call `migrate!`, so we must ensure we are migrated down every time
+ schema_migrate_down!
+
+ example.run
+
+ delete_from_all_tables!(except: deletion_except_tables)
+ end
+
def skip_if_multiple_databases_not_setup
skip 'Skipping because multiple databases not set up' unless Gitlab::Database.has_config?(:ci)
end
@@ -22,6 +31,21 @@ module Database
model.establish_connection(new_db_config)
end
+ def ensure_schema_and_empty_tables
+ # Ensure all schemas for both databases are migrated back
+ Gitlab::Database.database_base_models.each do |_, base_model|
+ with_reestablished_active_record_base do
+ reconfigure_db_connection(
+ model: ActiveRecord::Base,
+ config_model: base_model
+ )
+
+ schema_migrate_up!
+ delete_from_all_tables!(except: deletion_except_tables)
+ end
+ end
+ end
+
# The usage of this method switches temporarily used `connection_handler`
# allowing full manipulation of ActiveRecord::Base connections without
# having side effects like:
@@ -87,6 +111,16 @@ module Database
end
RSpec.configure do |config|
+ # Ensure database versions are memoized to prevent query counts from
+ # being affected by version checks. Note that
+ # Gitlab::Database.check_postgres_version_and_print_warning is called
+ # at startup, but that generates its own
+ # `Gitlab::Database::Reflection` so the result is not memoized by
+ # callers of `ApplicationRecord.database.version`, such as
+ # `Gitlab::Database::AsWithMaterialized.materialized_supported?`.
+ # TODO This can be removed once https://gitlab.com/gitlab-org/gitlab/-/issues/325639 is completed.
+ [ApplicationRecord, ::Ci::ApplicationRecord].each { |record| record.database.version }
+
config.around(:each, :reestablished_active_record_base) do |example|
with_reestablished_active_record_base(reconnect: example.metadata.fetch(:reconnect, true)) do
example.run
@@ -99,7 +133,15 @@ RSpec.configure do |config|
end
end
+ config.append_after(:context, :migration) do
+ break if recreate_databases_and_seed_if_needed
+
+ ensure_schema_and_empty_tables
+ end
+
config.around(:each, :migration) do |example|
+ self.class.use_transactional_tests = false
+
migration_schema = example.metadata[:migration]
migration_schema = :gitlab_main if migration_schema == true
base_model = Gitlab::Database.schemas_to_base_models.fetch(migration_schema).first
@@ -112,11 +154,13 @@ RSpec.configure do |config|
config_model: base_model
)
- example.run
+ run_and_cleanup(example)
end
else
- example.run
+ run_and_cleanup(example)
end
+
+ self.class.use_transactional_tests = true
end
end
diff --git a/spec/support/database/prevent_cross_database_modification.rb b/spec/support/database/prevent_cross_database_modification.rb
index c509aecf9b8..759e8316cc5 100644
--- a/spec/support/database/prevent_cross_database_modification.rb
+++ b/spec/support/database/prevent_cross_database_modification.rb
@@ -14,18 +14,22 @@ RSpec.configure do |config|
# By default allow cross-modifications as we want to observe only transactions
# within a specific block of execution which is defined be `before(:each)` and `after(:each)`
config.before(:all) do
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress = true
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress_in_rspec = true
end
# Using before and after blocks because the around block causes problems with the let_it_be
# record creations. It makes an extra savepoint which breaks the transaction count logic.
config.before do |example_file|
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress =
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress_in_rspec =
CROSS_DB_MODIFICATION_ALLOW_LIST.include?(example_file.file_path_rerun_argument)
end
# Reset after execution to preferred state
config.after do |example_file|
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress = true
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress_in_rspec = true
+
+ [::ApplicationRecord, ::Ci::ApplicationRecord].each do |base_class|
+ base_class.gitlab_transactions_stack.clear if base_class.respond_to?(:gitlab_transactions_stack)
+ end
end
end
diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb
index f8ddf3e66a5..7bd1f0c5dfa 100644
--- a/spec/support/database_cleaner.rb
+++ b/spec/support/database_cleaner.rb
@@ -13,19 +13,6 @@ RSpec.configure do |config|
DatabaseCleaner.clean_with(:deletion)
end
- config.append_after(:context, :migration) do
- delete_from_all_tables!(except: ['work_item_types'])
-
- # Postgres maximum number of columns in a table is 1600 (https://github.com/postgres/postgres/blob/de41869b64d57160f58852eab20a27f248188135/src/include/access/htup_details.h#L23-L47).
- # We drop and recreate the database if any table has more than 1200 columns, just to be safe.
- if any_connection_class_with_more_than_allowed_columns?
- recreate_all_databases!
-
- # Seed required data as recreating DBs will delete it
- TestEnv.seed_db
- end
- end
-
config.around(:each, :delete) do |example|
self.class.use_transactional_tests = false
@@ -35,14 +22,4 @@ RSpec.configure do |config|
self.class.use_transactional_tests = true
end
-
- config.around(:each, :migration) do |example|
- self.class.use_transactional_tests = false
-
- example.run
-
- delete_from_all_tables!(except: ['work_item_types'])
-
- self.class.use_transactional_tests = true
- end
end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index e3a05f17593..24cdbe04fc2 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -78,22 +78,32 @@ module DbCleaner
puts "Databases re-creation done in #{Gitlab::Metrics::System.monotonic_time - start}"
end
+ def recreate_databases_and_seed_if_needed
+ # Postgres maximum number of columns in a table is 1600 (https://github.com/postgres/postgres/blob/de41869b64d57160f58852eab20a27f248188135/src/include/access/htup_details.h#L23-L47).
+ # We drop and recreate the database if any table has more than 1200 columns, just to be safe.
+ return false unless any_connection_class_with_more_than_allowed_columns?
+
+ recreate_all_databases!
+
+ # Seed required data as recreating DBs will delete it
+ TestEnv.seed_db
+
+ true
+ end
+
def force_disconnect_all_connections!
- all_connection_classes.each do |connection_class|
- # We use `connection_pool` to avoid going through
- # Load Balancer since it does retry ops
- pool = connection_class.connection_pool
-
- # Force disconnect https://www.cybertec-postgresql.com/en/terminating-database-connections-in-postgresql/
- pool.connection.execute(<<-SQL)
- SELECT pg_terminate_backend(pid)
- FROM pg_stat_activity
- WHERE datname = #{pool.connection.quote(pool.db_config.database)}
- AND pid != pg_backend_pid();
- SQL
-
- connection_class.connection_pool.disconnect!
+ cmd = <<~SQL
+ SELECT pg_terminate_backend(pg_stat_activity.pid)
+ FROM pg_stat_activity
+ WHERE datname = current_database()
+ AND pid <> pg_backend_pid();
+ SQL
+
+ Gitlab::Database::EachDatabase.each_database_connection(include_shared: false) do |connection|
+ connection.execute(cmd)
end
+
+ ActiveRecord::Base.clear_all_connections! # rubocop:disable Database/MultipleDatabases
end
end
diff --git a/spec/support/finder_collection_allowlist.yml b/spec/support/finder_collection_allowlist.yml
index 1ac8e49fb45..c8af07905c2 100644
--- a/spec/support/finder_collection_allowlist.yml
+++ b/spec/support/finder_collection_allowlist.yml
@@ -55,6 +55,7 @@
- Security::FindingsFinder
- Security::PipelineVulnerabilitiesFinder
- Security::ScanExecutionPoliciesFinder
+- Security::ScanResultPoliciesFinder
- Security::TrainingProviders::BaseUrlFinder
- Security::TrainingUrlsFinder
- Security::TrainingProviders::KontraUrlFinder
diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml
index b6a66cfa2c6..94523591765 100644
--- a/spec/support/gitlab_stubs/gitlab_ci.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci.yml
@@ -7,9 +7,12 @@ before_script:
- bundle exec rake db:create
variables:
+ KEY_VALUE_VAR:
+ value: 'value x'
+ description: 'value of KEY_VALUE_VAR'
DB_NAME: postgres
ENVIRONMENT_VAR:
- value: 'env var value'
+ value: ['env var value', 'env var value2']
description: 'env var description'
stages:
diff --git a/spec/support/helpers/exclusive_lease_helpers.rb b/spec/support/helpers/exclusive_lease_helpers.rb
index 95cfc56c273..06e5ae5427c 100644
--- a/spec/support/helpers/exclusive_lease_helpers.rb
+++ b/spec/support/helpers/exclusive_lease_helpers.rb
@@ -2,6 +2,8 @@
module ExclusiveLeaseHelpers
def stub_exclusive_lease(key = nil, uuid = 'uuid', renew: false, timeout: nil)
+ prepare_exclusive_lease_stub
+
key ||= instance_of(String)
timeout ||= instance_of(Integer)
@@ -37,4 +39,21 @@ module ExclusiveLeaseHelpers
.to receive(:cancel)
.with(key, uuid)
end
+
+ private
+
+ # This prepares the stub to be able to stub specific lease keys
+ # while allowing unstubbed lease keys to behave as original.
+ #
+ # allow(Gitlab::ExclusiveLease).to receive(:new).and_call_original
+ # can only be called once to prevent resetting stubs when
+ # `stub_exclusive_lease` is called multiple times.
+ def prepare_exclusive_lease_stub
+ return if @exclusive_lease_allowed_to_call_original
+
+ allow(Gitlab::ExclusiveLease)
+ .to receive(:new).and_call_original
+
+ @exclusive_lease_allowed_to_call_original = true
+ end
end
diff --git a/spec/support/helpers/features/web_ide_spec_helpers.rb b/spec/support/helpers/features/web_ide_spec_helpers.rb
index 70dedc3ac50..551749a43de 100644
--- a/spec/support/helpers/features/web_ide_spec_helpers.rb
+++ b/spec/support/helpers/features/web_ide_spec_helpers.rb
@@ -8,7 +8,6 @@
# ...
#
# ide_visit(project)
-# ide_create_new_file('path/to/file.txt', content: 'Lorem ipsum')
# ide_commit
#
module WebIdeSpecHelpers
@@ -40,29 +39,6 @@ module WebIdeSpecHelpers
row.matches_css?('.folder.is-open')
end
- # Creates a file in the IDE by expanding directories
- # then using the dropdown next to the parent directory
- #
- # - Throws an error if the parent directory is not found
- def ide_create_new_file(path, content: '')
- parent_path = path.split('/')[0...-1].join('/')
-
- container = ide_traverse_to_file(parent_path)
-
- if container
- click_file_action(container, 'New file')
- else
- ide_tree_actions.click_button('New file')
- end
-
- within '#ide-new-entry' do
- find('input').fill_in(with: path)
- click_button('Create file')
- end
-
- ide_set_editor_value(content)
- end
-
# Deletes a file by traversing to `path`
# then clicking the 'Delete' action.
#
diff --git a/spec/support/helpers/git_helpers.rb b/spec/support/helpers/git_helpers.rb
index 99c5871ba54..72bba419116 100644
--- a/spec/support/helpers/git_helpers.rb
+++ b/spec/support/helpers/git_helpers.rb
@@ -2,7 +2,9 @@
module GitHelpers
def rugged_repo(repository)
- path = File.join(TestEnv.repos_path, repository.disk_path + '.git')
+ path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ File.join(TestEnv.repos_path, repository.disk_path + '.git')
+ end
Rugged::Repository.new(path)
end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 9d745f2cb70..b2fc6ae3286 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -17,6 +17,9 @@ module GraphqlHelpers
# makes an underscored string look like a fieldname
# "merge_request" => "mergeRequest"
def self.fieldnamerize(underscored_field_name)
+ # Skip transformation for a field with leading underscore
+ return underscored_field_name.to_s if underscored_field_name.start_with?('_')
+
underscored_field_name.to_s.camelize(:lower)
end
@@ -717,7 +720,7 @@ module GraphqlHelpers
end
def allow_high_graphql_transaction_threshold
- stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 1000)
+ allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(1000)
end
def allow_high_graphql_query_size
diff --git a/spec/support/helpers/html_escaped_helpers.rb b/spec/support/helpers/html_escaped_helpers.rb
index 7f6825e9598..7cbea7e7428 100644
--- a/spec/support/helpers/html_escaped_helpers.rb
+++ b/spec/support/helpers/html_escaped_helpers.rb
@@ -21,4 +21,35 @@ module HtmlEscapedHelpers
match_data
end
+
+ # Checks if +content+ contains HTML escaped tags and raises an exception
+ # if it does.
+ #
+ # See #match_html_escaped_tags for details.
+ def ensure_no_html_escaped_tags!(content, example)
+ match_data = match_html_escaped_tags(content)
+ return unless match_data
+
+ # Truncate
+ pre_match = match_data.pre_match.last(50)
+ match = match_data[0]
+ post_match = match_data.post_match.first(50)
+
+ string = "#{pre_match}«#{match}»#{post_match}"
+
+ raise <<~MESSAGE
+ The following string contains HTML escaped tags:
+
+ #{string}
+
+ Please consider using `.html_safe`.
+
+ This check can be disabled via:
+
+ it #{example.description.inspect}, :skip_html_escaped_tags_check do
+ ...
+ end
+
+ MESSAGE
+ end
end
diff --git a/spec/support/helpers/ldap_helpers.rb b/spec/support/helpers/ldap_helpers.rb
index 2f5f8be518c..48b593fb3d1 100644
--- a/spec/support/helpers/ldap_helpers.rb
+++ b/spec/support/helpers/ldap_helpers.rb
@@ -69,6 +69,32 @@ module LdapHelpers
allow_any_instance_of(Gitlab::Auth::Ldap::Adapter)
.to receive(:ldap_search).and_raise(Gitlab::Auth::Ldap::LdapConnectionError)
end
+
+ def stub_ldap_access(user, provider, provider_label)
+ ldap_server_config =
+ {
+ 'label' => provider_label,
+ 'provider_name' => provider,
+ 'attributes' => {},
+ 'encryption' => 'plain',
+ 'uid' => 'uid',
+ 'base' => 'dc=example,dc=com'
+ }
+ uid = 'my-uid'
+ allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config])
+ allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym])
+
+ Ldap::OmniauthCallbacksController.define_providers!
+ Rails.application.reload_routes!
+
+ mock_auth_hash(provider, uid, user.email)
+ allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true)
+
+ allow_next_instance_of(ActionDispatch::Routing::RoutesProxy) do |instance|
+ allow(instance).to receive(:"user_#{provider}_omniauth_callback_path")
+ .and_return("/users/auth/#{provider}/callback")
+ end
+ end
end
LdapHelpers.include_mod_with('LdapHelpers')
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 87a1f5459ec..44237b821c3 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -119,6 +119,16 @@ module LoginHelpers
click_button "oauth-login-#{provider}"
end
+ def sign_in_using_ldap!(user, ldap_tab, ldap_name)
+ visit new_user_session_path
+ click_link ldap_tab
+ fill_in 'username', with: user.username
+ fill_in 'password', with: user.password
+ within("##{ldap_name}") do
+ click_button 'Sign in'
+ end
+ end
+
def register_via(provider, uid, email, additional_info: {})
mock_auth_hash(provider, uid, email, additional_info: additional_info)
visit new_user_registration_path
diff --git a/spec/support/helpers/migrations_helpers/vulnerabilities_helper.rb b/spec/support/helpers/migrations_helpers/vulnerabilities_helper.rb
new file mode 100644
index 00000000000..0a86d7abc83
--- /dev/null
+++ b/spec/support/helpers/migrations_helpers/vulnerabilities_helper.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module MigrationHelpers
+ module VulnerabilitiesHelper
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'b1cee17e-3d7a-11ed-b878-0242ac120002')
+ table(:vulnerability_occurrences).create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ table(:vulnerabilities).create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+ end
+end
diff --git a/spec/support/helpers/project_helpers.rb b/spec/support/helpers/project_helpers.rb
index 2427ed2bcc9..daa07e385ea 100644
--- a/spec/support/helpers/project_helpers.rb
+++ b/spec/support/helpers/project_helpers.rb
@@ -1,22 +1,6 @@
# frozen_string_literal: true
module ProjectHelpers
- # @params target [Project] membership target
- # @params membership [Symbol] accepts the membership levels :guest, :reporter...
- # and phony levels :non_member and :anonymous
- def create_user_from_membership(target, membership)
- case membership
- when :anonymous
- nil
- when :non_member
- create(:user, name: membership)
- when :admin
- create(:user, :admin, name: 'admin')
- else
- create(:user, name: membership).tap { |u| target.add_member(u, membership) }
- end
- end
-
def update_feature_access_level(project, access_level, additional_params = {})
features = ProjectFeature::FEATURES.dup
features.delete(:pages)
diff --git a/spec/support/helpers/seed_helper.rb b/spec/support/helpers/seed_helper.rb
deleted file mode 100644
index 9628762d46a..00000000000
--- a/spec/support/helpers/seed_helper.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'test_env'
-
-# This file is specific to specs in spec/lib/gitlab/git/
-
-SEED_STORAGE_PATH = Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path }
-TEST_REPO_PATH = 'gitlab-git-test.git'
-TEST_NORMAL_REPO_PATH = 'not-bare-repo.git'
-TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'
-TEST_BROKEN_REPO_PATH = 'broken-repo.git'
-
-module SeedHelper
- GITLAB_GIT_TEST_REPO_URL = File.expand_path('../gitlab-git-test.git', __dir__)
-
- def ensure_seeds
- if File.exist?(SEED_STORAGE_PATH)
- FileUtils.rm_r(SEED_STORAGE_PATH)
- end
-
- FileUtils.mkdir_p(SEED_STORAGE_PATH)
-
- create_bare_seeds
- create_normal_seeds
- create_mutable_seeds
- create_broken_seeds
- end
-
- def create_bare_seeds
- system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{GITLAB_GIT_TEST_REPO_URL}),
- chdir: SEED_STORAGE_PATH,
- out: '/dev/null',
- err: '/dev/null')
- end
-
- def create_normal_seeds
- system(git_env, *%W(#{Gitlab.config.git.bin_path} clone #{TEST_REPO_PATH} #{TEST_NORMAL_REPO_PATH}),
- chdir: SEED_STORAGE_PATH,
- out: '/dev/null',
- err: '/dev/null')
- end
-
- def create_mutable_seeds
- system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} #{TEST_MUTABLE_REPO_PATH}),
- chdir: SEED_STORAGE_PATH,
- out: '/dev/null',
- err: '/dev/null')
-
- mutable_repo_full_path = File.join(SEED_STORAGE_PATH, TEST_MUTABLE_REPO_PATH)
- system(git_env, *%W(#{Gitlab.config.git.bin_path} branch -t feature origin/feature),
- chdir: mutable_repo_full_path, out: '/dev/null', err: '/dev/null')
-
- system(git_env, *%W(#{Gitlab.config.git.bin_path} remote add expendable #{GITLAB_GIT_TEST_REPO_URL}),
- chdir: mutable_repo_full_path, out: '/dev/null', err: '/dev/null')
- end
-
- def create_broken_seeds
- system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} #{TEST_BROKEN_REPO_PATH}),
- chdir: SEED_STORAGE_PATH,
- out: '/dev/null',
- err: '/dev/null')
-
- refs_path = File.join(SEED_STORAGE_PATH, TEST_BROKEN_REPO_PATH, 'refs')
-
- FileUtils.rm_r(refs_path)
- end
-end
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index c08e35912c3..f41457d2420 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -81,7 +81,7 @@ module StubConfiguration
messages['default'] ||= Gitlab.config.repositories.storages.default
messages.each do |storage_name, storage_hash|
if !storage_hash.key?('path') || storage_hash['path'] == Gitlab::GitalyClient::StorageSettings::Deprecated
- storage_hash['path'] = TestEnv.repos_path
+ storage_hash['path'] = Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path }
end
messages[storage_name] = Gitlab::GitalyClient::StorageSettings.new(storage_hash.to_h)
diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb
deleted file mode 100644
index 8995b8f5f7b..00000000000
--- a/spec/support/helpers/stub_experiments.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module StubExperiments
- # Stub Experiment with `key: true/false`
- #
- # @param [Hash] experiment where key is feature name and value is boolean whether active or not.
- #
- # Examples
- # - `stub_experiment(signup_flow: false)` ... Disables `signup_flow` experiment.
- def stub_experiment(experiments)
- allow(Gitlab::Experimentation).to receive(:active?).and_call_original
-
- experiments.each do |experiment_key, enabled|
- allow(Gitlab::Experimentation).to receive(:active?).with(experiment_key) { enabled }
- end
- end
-
- # Stub Experiment for user with `key: true/false`
- #
- # @param [Hash] experiment where key is feature name and value is boolean whether enabled or not.
- #
- # Examples
- # - `stub_experiment_for_subject(signup_flow: false)` ... Disable `signup_flow` experiment for user.
- def stub_experiment_for_subject(experiments)
- allow(Gitlab::Experimentation).to receive(:in_experiment_group?).and_call_original
-
- experiments.each do |experiment_key, enabled|
- allow(Gitlab::Experimentation).to receive(:in_experiment_group?).with(experiment_key, anything) { enabled }
- end
- end
-
- private
-
- def feature_flag_suffix
- Gitlab::Experimentation::Experiment::FEATURE_FLAG_SUFFIX
- end
-end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index 749554f7786..e5c30769531 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -96,9 +96,9 @@ module StubGitlabCalls
def stub_commonmark_sourcepos_disabled
render_options = Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS
- allow_any_instance_of(Banzai::Filter::MarkdownEngines::CommonMark)
- .to receive(:render_options)
- .and_return(render_options)
+ allow_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
+ allow(instance).to receive(:render_options).and_return(render_options)
+ end
end
private
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index 661c1c683b0..87e2a71b1cd 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -13,13 +13,16 @@ module StubObjectStorage
enabled: true,
proxy_download: false,
background_upload: false,
- direct_upload: false
+ direct_upload: false,
+ cdn: {}
)
+
new_config = config.to_h.deep_symbolize_keys.merge({
enabled: enabled,
proxy_download: proxy_download,
background_upload: background_upload,
- direct_upload: direct_upload
+ direct_upload: direct_upload,
+ cdn: cdn
})
# Needed for ObjectStorage::Config compatibility
@@ -30,6 +33,10 @@ module StubObjectStorage
allow(config).to receive(:background_upload) { background_upload }
allow(config).to receive(:direct_upload) { direct_upload }
+ uploader_config = Settingslogic.new(new_config.deep_stringify_keys)
+ allow(uploader).to receive(:object_store_options).and_return(uploader_config)
+ allow(uploader.options).to receive(:object_store).and_return(uploader_config)
+
return unless enabled
stub_object_storage(connection_params: uploader.object_store_credentials,
@@ -74,6 +81,12 @@ module StubObjectStorage
**params)
end
+ def stub_rpm_repository_file_object_storage(**params)
+ stub_object_storage_uploader(config: Gitlab.config.packages.object_store,
+ uploader: ::Packages::Rpm::RepositoryFileUploader,
+ **params)
+ end
+
def stub_composer_cache_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.packages.object_store,
uploader: ::Packages::Composer::CacheUploader,
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 691f978550a..c58353558df 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -295,14 +295,6 @@ module TestEnv
end
end
- def rm_storage_dir(storage, dir)
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- target_repo_refs_path = File.join(GitalySetup.repos_path(storage), dir)
- FileUtils.remove_dir(target_repo_refs_path)
- end
- rescue Errno::ENOENT
- end
-
def storage_dir_exists?(storage, dir)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
File.exist?(File.join(GitalySetup.repos_path(storage), dir))
@@ -348,6 +340,14 @@ module TestEnv
Capybara.current_session.visit '/'
end
+ def factory_repo_path
+ @factory_repo_path ||= Rails.root.join('tmp', 'tests', factory_repo_name)
+ end
+
+ def forked_repo_path
+ @forked_repo_path ||= Rails.root.join('tmp', 'tests', forked_repo_name)
+ end
+
def factory_repo_bundle_path
"#{factory_repo_path}.bundle"
end
@@ -377,18 +377,10 @@ module TestEnv
]
end
- def factory_repo_path
- @factory_repo_path ||= Rails.root.join('tmp', 'tests', factory_repo_name)
- end
-
def factory_repo_name
'gitlab-test'
end
- def forked_repo_path
- @forked_repo_path ||= Rails.root.join('tmp', 'tests', forked_repo_name)
- end
-
def forked_repo_name
'gitlab-test-fork'
end
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index 1aea3545ae0..b4f0cbd8527 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -1,21 +1,6 @@
# frozen_string_literal: true
module UsageDataHelpers
- SMAU_KEYS = %i(
- snippet_create
- snippet_update
- snippet_comment
- merge_request_comment
- commit_comment
- wiki_pages_create
- wiki_pages_update
- wiki_pages_delete
- navbar_searches
- cycle_analytics_views
- productivity_analytics_views
- source_code_pushes
- ).freeze
-
COUNTS_KEYS = %i(
assignee_lists
ci_builds
@@ -83,7 +68,6 @@ module UsageDataHelpers
projects_with_error_tracking_enabled
projects_with_enabled_alert_integrations
projects_with_expiration_policy_enabled
- projects_with_expiration_policy_disabled
projects_with_expiration_policy_enabled_with_keep_n_unset
projects_with_expiration_policy_enabled_with_keep_n_set_to_1
projects_with_expiration_policy_enabled_with_keep_n_set_to_5
@@ -118,7 +102,7 @@ module UsageDataHelpers
uploads
web_hooks
user_preferences_user_gitpod_enabled
- ).push(*SMAU_KEYS)
+ ).freeze
USAGE_DATA_KEYS = %i(
active_user_count
diff --git a/spec/support/helpers/user_helpers.rb b/spec/support/helpers/user_helpers.rb
new file mode 100644
index 00000000000..30fa5b3ad8d
--- /dev/null
+++ b/spec/support/helpers/user_helpers.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module UserHelpers
+ def create_user_from_membership(target, membership)
+ generate_user_from_membership(:create, target, membership)
+ end
+
+ def build_user_from_membership(target, membership)
+ generate_user_from_membership(:build, target, membership)
+ end
+
+ private
+
+ # @param method [Symbol] FactoryBot methods :create, :build, :build_stubbed
+ # @param target [Project, Group] membership target
+ # @param membership [Symbol] accepts the membership levels :guest, :reporter...
+ # and pseudo levels :non_member and :anonymous
+ def generate_user_from_membership(method, target, membership)
+ case membership
+ when :anonymous
+ nil
+ when :non_member
+ FactoryBot.send(method, :user, name: membership)
+ when :admin
+ FactoryBot.send(method, :user, :admin, name: 'admin')
+ else
+ # `.tap` can only be used with `create`, and if we want to `build` a user,
+ # it is more performant than creating a `project_member` or `group_member`
+ # with a built user
+ create(:user, name: membership).tap { |u| target.add_member(u, membership) }
+ end
+ end
+end
diff --git a/spec/support/matchers/event_store.rb b/spec/support/matchers/event_store.rb
index 4ecb924b3ed..582ea202187 100644
--- a/spec/support/matchers/event_store.rb
+++ b/spec/support/matchers/event_store.rb
@@ -6,7 +6,7 @@ RSpec::Matchers.define :publish_event do |expected_event_class|
supports_block_expectations
match do |proc|
- raise ArgumentError, 'This matcher only supports block expectation' unless proc.respond_to?(:call)
+ raise ArgumentError, 'publish_event matcher only supports block expectation' unless proc.respond_to?(:call)
@events ||= []
@@ -22,6 +22,8 @@ RSpec::Matchers.define :publish_event do |expected_event_class|
end
def match_data?(actual, expected)
+ return if actual.blank? || expected.blank?
+
values_match?(actual.keys, expected.keys) &&
actual.keys.all? do |key|
values_match?(expected[key], actual[key])
@@ -33,11 +35,20 @@ RSpec::Matchers.define :publish_event do |expected_event_class|
end
failure_message do
- "expected #{expected_event_class} with #{@expected_data} to be published, but got #{@events}"
+ message = "expected #{expected_event_class} with #{@expected_data || 'no data'} to be published"
+
+ if @events.present?
+ <<~MESSAGE
+ #{message}, but only the following events were published:
+ #{events_list}
+ MESSAGE
+ else
+ "#{message}, but no events were published."
+ end
end
match_when_negated do |proc|
- raise ArgumentError, 'This matcher only supports block expectation' unless proc.respond_to?(:call)
+ raise ArgumentError, 'publish_event matcher only supports block expectation' unless proc.respond_to?(:call)
allow(Gitlab::EventStore).to receive(:publish)
@@ -45,4 +56,48 @@ RSpec::Matchers.define :publish_event do |expected_event_class|
expect(Gitlab::EventStore).not_to have_received(:publish).with(instance_of(expected_event_class))
end
+
+ def events_list
+ @events.map do |event|
+ " - #{event.class.name} with #{event.data}"
+ end.join("\n")
+ end
+end
+
+# not_publish_event enables multiple assertions on a single block, for example:
+# expect { Model.create(invalid: :attribute) }
+# .to not_change(Model, :count)
+# .and not_publish_event(ModelCreated)
+RSpec::Matchers.define :not_publish_event do |expected_event_class|
+ include RSpec::Matchers::Composable
+
+ supports_block_expectations
+
+ match do |proc|
+ raise ArgumentError, 'not_publish_event matcher only supports block expectation' unless proc.respond_to?(:call)
+
+ @events ||= []
+
+ allow(Gitlab::EventStore).to receive(:publish) do |published_event|
+ @events << published_event
+ end
+
+ proc.call
+
+ @events.none? do |event|
+ event.instance_of?(expected_event_class)
+ end
+ end
+
+ failure_message do
+ "expected #{expected_event_class} not to be published"
+ end
+
+ chain :with do |_| # rubocop: disable Lint/UnreachableLoop
+ raise ArgumentError, 'not_publish_event does not permit .with to avoid ambiguity'
+ end
+
+ match_when_negated do |proc|
+ raise ArgumentError, 'not_publish_event matcher does not support negation. Use `expect {}.to publish_event` instead'
+ end
end
diff --git a/spec/support/migration.rb b/spec/support/migration.rb
index 3c359af886d..24e2fc2ff31 100644
--- a/spec/support/migration.rb
+++ b/spec/support/migration.rb
@@ -19,13 +19,9 @@ RSpec.configure do |config|
# Each example may call `migrate!`, so we must ensure we are migrated down every time
config.before(:each, :migration) do
use_fake_application_settings
-
- schema_migrate_down!
end
config.after(:context, :migration) do
- schema_migrate_up!
-
Gitlab::CurrentSettings.clear_in_memory_application_settings!
end
end
diff --git a/spec/support/models/partitionable_check.rb b/spec/support/models/partitionable_check.rb
new file mode 100644
index 00000000000..2c09c1b3408
--- /dev/null
+++ b/spec/support/models/partitionable_check.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module PartitioningTesting
+ module CascadeCheck
+ extend ActiveSupport::Concern
+
+ included do
+ after_create :check_partition_cascade_value
+ end
+
+ def check_partition_cascade_value
+ raise 'Partition value not found' unless partition_scope_value
+ raise 'Default value detected' if partition_id == 100
+
+ return if partition_id == partition_scope_value
+
+ raise "partition_id was expected to equal #{partition_scope_value} but it was #{partition_id}."
+ end
+ end
+
+ module DefaultPartitionValue
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def current_partition_value
+ current = super
+
+ if current == 100
+ 54321
+ else
+ current
+ end
+ end
+ end
+ end
+end
+
+Ci::Partitionable::Testing::PARTITIONABLE_MODELS.each do |klass|
+ model = klass.safe_constantize
+
+ if klass == 'Ci::Pipeline'
+ model.prepend(PartitioningTesting::DefaultPartitionValue)
+ else
+ model.include(PartitioningTesting::CascadeCheck)
+ end
+end
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index b5e3d707d50..c4377e368ee 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -189,7 +189,6 @@
- './ee/spec/controllers/subscriptions_controller_spec.rb'
- './ee/spec/controllers/subscriptions/groups_controller_spec.rb'
- './ee/spec/controllers/trial_registrations_controller_spec.rb'
-- './ee/spec/controllers/trials_controller_spec.rb'
- './ee/spec/controllers/users_controller_spec.rb'
- './ee/spec/db/production/license_spec.rb'
- './ee/spec/elastic_integration/global_search_spec.rb'
@@ -533,7 +532,6 @@
- './ee/spec/features/trial_registrations/company_information_spec.rb'
- './ee/spec/features/trial_registrations/signin_spec.rb'
- './ee/spec/features/trial_registrations/signup_spec.rb'
-- './ee/spec/features/trials/capture_lead_spec.rb'
- './ee/spec/features/trials/select_namespace_spec.rb'
- './ee/spec/features/trials/show_trial_banner_spec.rb'
- './ee/spec/features/users/arkose_labs_csp_spec.rb'
@@ -2017,7 +2015,6 @@
- './ee/spec/models/milestone_spec.rb'
- './ee/spec/models/namespace_limit_spec.rb'
- './ee/spec/models/namespace_setting_spec.rb'
-- './ee/spec/models/namespaces/free_user_cap/preview_spec.rb'
- './ee/spec/models/namespaces/free_user_cap_spec.rb'
- './ee/spec/models/namespaces/free_user_cap/standard_spec.rb'
- './ee/spec/models/namespaces/storage/root_excess_size_spec.rb'
@@ -3266,12 +3263,10 @@
- './ee/spec/services/users_ops_dashboard_projects/destroy_service_spec.rb'
- './ee/spec/services/users/update_highest_member_role_service_spec.rb'
- './ee/spec/services/vulnerabilities/confirm_service_spec.rb'
-- './ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb'
- './ee/spec/services/vulnerabilities/create_service_spec.rb'
- './ee/spec/services/vulnerabilities/destroy_dismissal_feedback_service_spec.rb'
- './ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
- './ee/spec/services/vulnerabilities/finding_dismiss_service_spec.rb'
-- './ee/spec/services/vulnerabilities/findings/create_from_security_finding_service_spec.rb'
- './ee/spec/services/vulnerabilities/historical_statistics/adjustment_service_spec.rb'
- './ee/spec/services/vulnerabilities/historical_statistics/deletion_service_spec.rb'
- './ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
@@ -8850,7 +8845,6 @@
- './spec/presenters/award_emoji_presenter_spec.rb'
- './spec/presenters/blob_presenter_spec.rb'
- './spec/presenters/blobs/notebook_presenter_spec.rb'
-- './spec/presenters/blobs/unfold_presenter_spec.rb'
- './spec/presenters/ci/bridge_presenter_spec.rb'
- './spec/presenters/ci/build_presenter_spec.rb'
- './spec/presenters/ci/build_runner_presenter_spec.rb'
@@ -9535,7 +9529,6 @@
- './spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb'
- './spec/serializers/deploy_keys/deploy_key_entity_spec.rb'
- './spec/serializers/deployment_cluster_entity_spec.rb'
-- './spec/serializers/deployment_entity_spec.rb'
- './spec/serializers/deployment_serializer_spec.rb'
- './spec/serializers/detailed_status_entity_spec.rb'
- './spec/serializers/diff_file_base_entity_spec.rb'
@@ -9552,7 +9545,6 @@
- './spec/serializers/entity_request_spec.rb'
- './spec/serializers/environment_entity_spec.rb'
- './spec/serializers/environment_serializer_spec.rb'
-- './spec/serializers/environment_status_entity_spec.rb'
- './spec/serializers/evidences/evidence_entity_spec.rb'
- './spec/serializers/evidences/evidence_serializer_spec.rb'
- './spec/serializers/evidences/issue_entity_spec.rb'
@@ -9634,7 +9626,6 @@
- './spec/serializers/personal_access_token_entity_spec.rb'
- './spec/serializers/personal_access_token_serializer_spec.rb'
- './spec/serializers/pipeline_details_entity_spec.rb'
-- './spec/serializers/pipeline_serializer_spec.rb'
- './spec/serializers/project_access_token_entity_spec.rb'
- './spec/serializers/project_access_token_serializer_spec.rb'
- './spec/serializers/project_import_entity_spec.rb'
@@ -10017,7 +10008,6 @@
- './spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb'
- './spec/services/incident_management/issuable_escalation_statuses/build_service_spec.rb'
- './spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb'
-- './spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb'
- './spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb'
- './spec/services/incident_management/pager_duty/process_webhook_service_spec.rb'
- './spec/services/incident_management/timeline_events/create_service_spec.rb'
diff --git a/spec/support/services/issuable_update_service_shared_examples.rb b/spec/support/services/issuable_update_service_shared_examples.rb
index c168df7a7d2..94061b140f4 100644
--- a/spec/support/services/issuable_update_service_shared_examples.rb
+++ b/spec/support/services/issuable_update_service_shared_examples.rb
@@ -47,7 +47,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
it 'triggers the GraphQL subscription' do
expect(GraphqlTriggers).to receive(:issuable_labels_updated).with(issuable)
- update_issuable({ add_label_ids: [label_b.id] })
+ update_issuable(add_label_ids: [label_b.id])
end
end
@@ -55,7 +55,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
it 'triggers the GraphQL subscription' do
expect(GraphqlTriggers).to receive(:issuable_labels_updated).with(issuable)
- update_issuable({ remove_label_ids: [label_a.id] })
+ update_issuable(remove_label_ids: [label_a.id])
end
end
@@ -63,7 +63,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
it 'does not trigger the GraphQL subscription' do
expect(GraphqlTriggers).not_to receive(:issuable_labels_updated).with(issuable)
- update_issuable({ label_ids: [label_a.id] })
+ update_issuable(label_ids: [label_a.id])
end
end
end
diff --git a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
index 91b6baac610..8a64efe9df5 100644
--- a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb
@@ -50,8 +50,8 @@ RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests
allow_gitaly_n_plus_1 { create(:project, group: subgroup) }
end
- let!(:label) { create(:label, project: project1) }
- let!(:label2) { create(:label, project: project1) }
+ let_it_be(:label) { create(:label, project: project1) }
+ let_it_be(:label2) { create(:label, project: project1) }
let!(:merge_request1) do
create(:merge_request, assignees: [user], author: user, reviewers: [user2],
@@ -87,13 +87,16 @@ RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests
let!(:label_link) { create(:label_link, label: label, target: merge_request2) }
let!(:label_link2) { create(:label_link, label: label2, target: merge_request3) }
- before do
+ before_all do
project1.add_maintainer(user)
- project2.add_developer(user)
- project3.add_developer(user)
project4.add_developer(user)
project5.add_developer(user)
project6.add_developer(user)
+ end
+
+ before do
+ project2.add_developer(user)
+ project3.add_developer(user)
project2.add_developer(user2)
end
diff --git a/spec/support/shared_contexts/html_safe_shared_context.rb b/spec/support/shared_contexts/html_safe_shared_context.rb
new file mode 100644
index 00000000000..9bdaea9fe64
--- /dev/null
+++ b/spec/support/shared_contexts/html_safe_shared_context.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'when rendered has no HTML escapes' do
+ # Check once per example if `rendered` contains HTML escapes.
+ let(:rendered) do |example|
+ super().tap do |rendered|
+ next if example.metadata[:skip_html_escaped_tags_check]
+
+ HtmlEscapedHelpers.ensure_no_html_escaped_tags!(rendered, example)
+ end
+ end
+end
+
+RSpec.shared_context 'when page has no HTML escapes' do
+ # Check once per example if `page` contains HTML escapes.
+ let(:page) do |example|
+ super().tap do |page|
+ next if example.metadata[:skip_html_escaped_tags_check]
+
+ HtmlEscapedHelpers.ensure_no_html_escaped_tags!(page.native.to_s, example)
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/lib/api/helpers/packages/dependency_proxy_helpers_shared_context.rb b/spec/support/shared_contexts/lib/api/helpers/packages/dependency_proxy_helpers_shared_context.rb
index 7c8b6250d24..1963248142c 100644
--- a/spec/support/shared_contexts/lib/api/helpers/packages/dependency_proxy_helpers_shared_context.rb
+++ b/spec/support/shared_contexts/lib/api/helpers/packages/dependency_proxy_helpers_shared_context.rb
@@ -1,6 +1,11 @@
# frozen_string_literal: true
RSpec.shared_context 'dependency proxy helpers context' do
+ def allow_fetch_cascade_application_setting(attribute:, return_value:)
+ allow(Gitlab::CurrentSettings).to receive(:public_send).with(attribute.to_sym).and_return(return_value)
+ allow(Gitlab::CurrentSettings).to receive(:public_send).with("lock_#{attribute}").and_return(false)
+ end
+
def allow_fetch_application_setting(attribute:, return_value:)
attributes = double
allow(::Gitlab::CurrentSettings.current_application_settings).to receive(:attributes).and_return(attributes)
diff --git a/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
index 168aef0f174..72e23e6d5fa 100644
--- a/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
+++ b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
@@ -13,6 +13,8 @@ RSpec.shared_context 'API::Markdown Golden Master shared context' do |markdown_y
let_it_be(:project) { create(:project, :public, :repository, group: group) }
let_it_be(:label) { create(:label, project: project, title: 'bug') }
+ let_it_be(:label2) { create(:label, project: project, title: 'UX 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) }
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 893d3702407..bb1b794c2b6 100644
--- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -74,6 +74,8 @@ RSpec.shared_context 'GroupPolicy context' do
read_group_runners
admin_group_runners
register_group_runners
+ read_billing
+ edit_billing
]
end
diff --git a/spec/support/shared_contexts/rubocop_default_rspec_language_config_context.rb b/spec/support/shared_contexts/rubocop_default_rspec_language_config_context.rb
new file mode 100644
index 00000000000..a207c6ae9d1
--- /dev/null
+++ b/spec/support/shared_contexts/rubocop_default_rspec_language_config_context.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# From https://github.com/rubocop/rubocop-rspec/blob/master/spec/shared/default_rspec_language_config_context.rb
+# This can be removed once we have https://github.com/rubocop/rubocop-rspec/pull/1377
+
+RSpec.shared_context 'with default RSpec/Language config' do
+ include_context 'config'
+
+ # Deep duplication is needed to prevent config leakage between examples
+ let(:other_cops) do
+ default_language = RuboCop::ConfigLoader
+ .default_configuration['RSpec']['Language']
+ default_include = RuboCop::ConfigLoader
+ .default_configuration['RSpec']['Include']
+ { 'RSpec' =>
+ {
+ 'Include' => default_include,
+ 'Language' => deep_dup(default_language)
+ } }
+ end
+
+ def deep_dup(object)
+ case object
+ when Array
+ object.map { |item| deep_dup(item) }
+ when Hash
+ object.transform_values { |value| deep_dup(value) }
+ else
+ object # only collections undergo modifications and need duping
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/services/packages/rpm/xml_shared_context.rb b/spec/support/shared_contexts/services/packages/rpm/xml_shared_context.rb
new file mode 100644
index 00000000000..784092d40da
--- /dev/null
+++ b/spec/support/shared_contexts/services/packages/rpm/xml_shared_context.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'with rpm package data' do
+ def xml_update_params
+ Gitlab::Json.parse(fixture_file('packages/rpm/payload.json')).with_indifferent_access
+ end
+end
diff --git a/spec/support/shared_contexts/views/html_safe_render_shared_context.rb b/spec/support/shared_contexts/views/html_safe_render_shared_context.rb
deleted file mode 100644
index 3acca60c901..00000000000
--- a/spec/support/shared_contexts/views/html_safe_render_shared_context.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'when rendered view has no HTML escapes', type: :view do
- # Check once per example if `rendered` contains HTML escapes.
- let(:rendered) do |example|
- super().tap do |rendered|
- next if example.metadata[:skip_html_escaped_tags_check]
-
- ensure_no_html_escaped_tags!(rendered, example)
- end
- end
-
- def ensure_no_html_escaped_tags!(content, example)
- match_data = HtmlEscapedHelpers.match_html_escaped_tags(content)
- return unless match_data
-
- # Truncate
- pre_match = match_data.pre_match.last(50)
- match = match_data[0]
- post_match = match_data.post_match.first(50)
-
- string = "#{pre_match}«#{match}»#{post_match}"
-
- raise <<~MESSAGE
- The following string contains HTML escaped tags:
-
- #{string}
-
- Please consider using `.html_safe`.
-
- This check can be disabled via:
-
- it #{example.description.inspect}, :skip_html_escaped_tags_check do
- ...
- end
-
- MESSAGE
- end
-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 7e7460cd602..cd4432af4ed 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
@@ -57,5 +57,53 @@ RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
expect(tracker.entity.failures.first.exception_message).to eq('Only allowed schemes are http, https')
end
end
+
+ context 'when wiki is disabled' do
+ before do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client)
+ .to receive(:get)
+ .and_raise(
+ BulkImports::NetworkError.new(
+ 'Unsuccessful response 403 from ...',
+ response: response_double
+ )
+ )
+ end
+ end
+
+ describe 'unsuccessful response' do
+ shared_examples 'does not raise an error' do
+ it 'does not raise an error' do
+ 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
+
+ context 'when response is forbidden' do
+ let(:response_double) { instance_double(HTTParty::Response, forbidden?: true, code: 403) }
+
+ include_examples 'does not raise an error'
+ end
+
+ context 'when response is not found' do
+ let(:response_double) { instance_double(HTTParty::Response, forbidden?: false, not_found?: true) }
+
+ include_examples 'does not raise an error'
+ end
+
+ context 'when response is not 403' do
+ let(:response_double) { instance_double(HTTParty::Response, forbidden?: false, not_found?: false, code: 301) }
+
+ it 'marks tracker as failed' do
+ subject.run
+
+ expect(tracker.failed?).to eq(true)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
index 4af3c0cc6cc..6749ebd471f 100644
--- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
+++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
@@ -32,7 +32,8 @@ RSpec.shared_examples 'Snowplow event tracking' do |overrides: {}|
user: try(:user),
project: try(:project),
label: try(:label),
- property: try(:property)
+ property: try(:property),
+ context: try(:context)
}.merge(overrides).compact.merge(extra)
subject
@@ -40,3 +41,12 @@ RSpec.shared_examples 'Snowplow event tracking' do |overrides: {}|
expect_snowplow_event(**params)
end
end
+
+RSpec.shared_examples 'Snowplow event tracking with RedisHLL context' do |overrides: {}|
+ it_behaves_like 'Snowplow event tracking', overrides: overrides do
+ let(:context) do
+ event = try(:property) || action
+ [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json]
+ end
+ end
+end
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 885c0229038..5d77ed5fdfc 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -48,7 +48,7 @@ RSpec.shared_examples 'wiki controller actions' do
context 'when the wiki repository cannot be created' do
before do
expect(Wiki).to receive(:for_container).and_return(wiki)
- expect(wiki).to receive(:wiki) { raise Wiki::CouldNotCreateWikiError }
+ expect(wiki).to receive(:create_wiki_repository) { raise Wiki::CouldNotCreateWikiError }
end
it 'redirects to the wiki container and displays an error message' do
@@ -200,7 +200,7 @@ RSpec.shared_examples 'wiki controller actions' do
context 'the sidebar fails to load' do
before do
allow(Wiki).to receive(:for_container).and_return(wiki)
- wiki.wiki
+ wiki.create_wiki_repository
expect(wiki).to receive(:find_sidebar) do
raise ::Gitlab::Git::CommandTimedOut, 'Deadline Exceeded'
end
@@ -288,7 +288,7 @@ RSpec.shared_examples 'wiki controller actions' do
context 'when page is a file' do
include WikiHelpers
- where(:file_name) { ['dk.png', 'unsanitized.svg', 'git-cheat-sheet.pdf'] }
+ where(:file_name) { ['dk.png', 'unsanitized.svg', 'sample.pdf'] }
with_them do
let(:id) { upload_file_to_wiki(wiki, user, file_name) }
@@ -300,7 +300,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('max-age=60, private')
+ expect(response.headers['Cache-Control']).to eq('max-age=60, private, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60')
end
end
end
diff --git a/spec/support/shared_examples/features/access_tokens_shared_examples.rb b/spec/support/shared_examples/features/access_tokens_shared_examples.rb
index 0fc45b154d8..cd255abd7a8 100644
--- a/spec/support/shared_examples/features/access_tokens_shared_examples.rb
+++ b/spec/support/shared_examples/features/access_tokens_shared_examples.rb
@@ -10,11 +10,11 @@ end
RSpec.shared_examples 'resource access tokens creation' do |resource_type|
def active_resource_access_tokens
- find('.table.active-tokens')
+ find("[data-testid='active-tokens']")
end
def created_resource_access_token
- find('#created-personal-access-token').value
+ find_field('new-access-token').value
end
it 'allows creation of an access token', :aggregate_failures do
@@ -106,7 +106,7 @@ end
RSpec.shared_examples 'active resource access tokens' do
def active_resource_access_tokens
- find('.table.active-tokens')
+ find("[data-testid='active-tokens']")
end
it 'shows active access tokens' do
@@ -129,24 +129,22 @@ RSpec.shared_examples 'active resource access tokens' do
end
RSpec.shared_examples 'inactive resource access tokens' do |no_active_tokens_text|
- def no_resource_access_tokens_message
- find('.settings-message')
+ def active_resource_access_tokens
+ find("[data-testid='active-tokens']")
end
it 'allows revocation of an active token' do
visit resource_settings_access_tokens_path
accept_gl_confirm(button_text: 'Revoke') { click_on 'Revoke' }
- expect(page).to have_selector('.settings-message')
- expect(no_resource_access_tokens_message).to have_text(no_active_tokens_text)
+ expect(active_resource_access_tokens).to have_text(no_active_tokens_text)
end
it 'removes expired tokens from active section' do
resource_access_token.update!(expires_at: 5.days.ago)
visit resource_settings_access_tokens_path
- expect(page).to have_selector('.settings-message')
- expect(no_resource_access_tokens_message).to have_text(no_active_tokens_text)
+ expect(active_resource_access_tokens).to have_text(no_active_tokens_text)
end
context 'when resource access token creation is not allowed' do
@@ -158,8 +156,39 @@ RSpec.shared_examples 'inactive resource access tokens' do |no_active_tokens_tex
visit resource_settings_access_tokens_path
accept_gl_confirm(button_text: 'Revoke') { click_on 'Revoke' }
- expect(page).to have_selector('.settings-message')
- expect(no_resource_access_tokens_message).to have_text(no_active_tokens_text)
+ expect(active_resource_access_tokens).to have_text(no_active_tokens_text)
+ end
+ end
+end
+
+RSpec.shared_examples '#create access token' do
+ let(:url) { {} }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:token_attributes) { attributes_for(:personal_access_token) }
+
+ before do
+ sign_in(admin)
+ end
+
+ context "when POST is successful" do
+ it "renders JSON with a new token" do
+ post url, params: { personal_access_token: token_attributes }
+
+ parsed_body = Gitlab::Json.parse(response.body)
+ expect(parsed_body['new_token']).not_to be_blank
+ expect(parsed_body['errors']).to be_blank
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
+ context "when POST is unsuccessful" do
+ it "renders JSON with an error" do
+ post url, params: { personal_access_token: token_attributes.merge(scopes: []) }
+
+ parsed_body = Gitlab::Json.parse(response.body)
+ expect(parsed_body['new_token']).to be_blank
+ expect(parsed_body['errors']).not_to be_blank
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
end
diff --git a/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb b/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
index f7cdc4c61ec..8a07e52019c 100644
--- a/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/comments_on_merge_request_files_shared_examples.rb
@@ -1,10 +1,6 @@
# frozen_string_literal: true
RSpec.shared_examples 'comment on merge request file' do
- before do
- stub_feature_flags(remove_user_attributes_projects: false)
- end
-
it 'adds a comment' do
click_diff_line(find_by_scrolling("[id='#{sample_commit.line_code}']"))
diff --git a/spec/support/shared_examples/features/content_editor_shared_examples.rb b/spec/support/shared_examples/features/content_editor_shared_examples.rb
index 21f264a8b6a..7863548e7f3 100644
--- a/spec/support/shared_examples/features/content_editor_shared_examples.rb
+++ b/spec/support/shared_examples/features/content_editor_shared_examples.rb
@@ -35,6 +35,34 @@ RSpec.shared_examples 'edits content using the content editor' do
attach_file('content_editor_image', Rails.root.join('spec', 'fixtures', fixture_name), make_visible: true)
end
+ def wait_until_hidden_field_is_updated(value)
+ expect(page).to have_field('wiki[content]', with: value, type: 'hidden')
+ end
+
+ it 'saves page content in local storage if the user navigates away' do
+ switch_to_content_editor
+
+ expect(page).to have_css(content_editor_testid)
+
+ type_in_content_editor ' Typing text in the content editor'
+
+ wait_until_hidden_field_is_updated /Typing text in the content editor/
+
+ refresh
+
+ expect(page).to have_text('Typing text in the content editor')
+
+ refresh # also retained after second refresh
+
+ expect(page).to have_text('Typing text in the content editor')
+
+ click_link 'Cancel' # draft is deleted on cancel
+
+ page.go_back
+
+ expect(page).not_to have_text('Typing text in the content editor')
+ end
+
describe 'formatting bubble menu' do
it 'shows a formatting bubble menu for a regular paragraph and headings' do
switch_to_content_editor
@@ -189,4 +217,101 @@ RSpec.shared_examples 'edits content using the content editor' do
end
end
end
+
+ describe 'autocomplete suggestions' do
+ let(:suggestions_dropdown) { '[data-testid="content-editor-suggestions-dropdown"]' }
+
+ before do
+ if defined?(project)
+ create(:issue, project: project, title: 'My Cool Linked Issue')
+ create(:merge_request, source_project: project, title: 'My Cool Merge Request')
+ create(:label, project: project, title: 'My Cool Label')
+ create(:milestone, project: project, title: 'My Cool Milestone')
+
+ project.add_maintainer(create(:user, name: 'abc123', username: 'abc123'))
+ else # group wikis
+ project = create(:project, group: group)
+
+ create(:issue, project: project, title: 'My Cool Linked Issue')
+ create(:merge_request, source_project: project, title: 'My Cool Merge Request')
+ create(:group_label, group: group, title: 'My Cool Label')
+ create(:milestone, group: group, title: 'My Cool Milestone')
+
+ project.add_maintainer(create(:user, name: 'abc123', username: 'abc123'))
+ end
+
+ switch_to_content_editor
+
+ type_in_content_editor :enter
+ end
+
+ it 'shows suggestions for members with descriptions' do
+ type_in_content_editor '@a'
+
+ expect(find(suggestions_dropdown)).to have_text('abc123')
+ expect(find(suggestions_dropdown)).to have_text('all')
+ expect(find(suggestions_dropdown)).to have_text('Group Members (2)')
+
+ send_keys [:arrow_down, :enter]
+
+ expect(page).not_to have_css(suggestions_dropdown)
+ expect(page).to have_text('@abc123')
+ end
+
+ it 'shows suggestions for merge requests' do
+ type_in_content_editor '!'
+
+ expect(find(suggestions_dropdown)).to have_text('My Cool Merge Request')
+
+ send_keys :enter
+
+ expect(page).not_to have_css(suggestions_dropdown)
+ expect(page).to have_text('!1')
+ end
+
+ it 'shows suggestions for issues' do
+ type_in_content_editor '#'
+
+ expect(find(suggestions_dropdown)).to have_text('My Cool Linked Issue')
+
+ send_keys :enter
+
+ expect(page).not_to have_css(suggestions_dropdown)
+ expect(page).to have_text('#1')
+ end
+
+ it 'shows suggestions for milestones' do
+ type_in_content_editor '%'
+
+ expect(find(suggestions_dropdown)).to have_text('My Cool Milestone')
+
+ send_keys :enter
+
+ expect(page).not_to have_css(suggestions_dropdown)
+ expect(page).to have_text('%My Cool Milestone')
+ end
+
+ it 'shows suggestions for emojis' do
+ type_in_content_editor ':smile'
+
+ expect(find(suggestions_dropdown)).to have_text('🙂 slight_smile')
+ expect(find(suggestions_dropdown)).to have_text('😸 smile_cat')
+
+ send_keys :enter
+
+ expect(page).not_to have_css(suggestions_dropdown)
+
+ expect(page).to have_text('🙂')
+ end
+
+ it 'doesn\'t show suggestions dropdown if there are no suggestions to show' do
+ type_in_content_editor '%'
+
+ expect(find(suggestions_dropdown)).to have_text('My Cool Milestone')
+
+ type_in_content_editor 'x'
+
+ expect(page).not_to have_css(suggestions_dropdown)
+ end
+ end
end
diff --git a/spec/support/shared_examples/features/deploy_token_shared_examples.rb b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
index 79ad5bd6c7f..9fe08e5c996 100644
--- a/spec/support/shared_examples/features/deploy_token_shared_examples.rb
+++ b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
@@ -14,32 +14,32 @@ RSpec.shared_examples 'a deploy token in settings' do
end
end
- it 'add a new deploy token' do
+ it 'add a new deploy token', :js do
visit page_path
- fill_in 'deploy_token_name', with: 'new_deploy_key'
- fill_in 'deploy_token_expires_at', with: (Date.today + 1.month).to_s
- fill_in 'deploy_token_username', with: 'deployer'
- check 'deploy_token_read_repository'
- check 'deploy_token_read_registry'
+ fill_in _('Name'), with: 'new_deploy_key'
+ fill_in _('Expiration date (optional)'), with: (Date.today + 1.month).to_s
+ fill_in _('Username (optional)'), with: 'deployer'
+ check 'read_repository'
+ check 'read_registry'
click_button 'Create deploy token'
expect(page).to have_content("Your new #{entity_type} deploy token has been created")
within('.created-deploy-token-container') do
- expect(page).to have_selector("input[name='deploy-token-user'][value='deployer']")
- expect(page).to have_selector("input[name='deploy-token'][readonly='readonly']")
+ expect(find("input[name='deploy-token-user']").value).to eq("deployer")
+ expect(find("input[name='deploy-token'][readonly='readonly']")).to be_visible
end
- expect(find("input#deploy_token_name").value).to eq nil
+ expect(find("input#deploy_token_name").value).to be_empty
expect(find("input#deploy_token_read_repository").checked?).to eq false
end
- context "with form errors" do
+ context "with form errors", :js do
before do
visit page_path
- fill_in "deploy_token_name", with: "new_deploy_key"
- fill_in "deploy_token_username", with: "deployer"
+ fill_in _('Name'), with: "new_deploy_key"
+ fill_in _('Username (optional)'), with: "deployer"
click_button "Create deploy token"
end
diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
index f209070d82a..68c0d06e7d0 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -209,7 +209,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
wait_for_all_requests
expect(page).to have_content(comment)
- expect(page).to have_content "@#{user.username} closed"
+ expect(page).to have_content "#{user.name} closed"
new_comment = all(comments_selector).last
@@ -334,7 +334,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
click_button 'Start thread & close issue'
expect(page).to have_content(comment)
- expect(page).to have_content "@#{user.username} closed"
+ expect(page).to have_content "#{user.name} closed"
new_discussion = all(comments_selector)[-2]
diff --git a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
index 0a5ad5a59c0..7737f8a73c5 100644
--- a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
@@ -77,9 +77,9 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false|
end
if drop
- find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'))
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'))
else
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true)
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'), make_visible: true)
end
page.within('#modal-upload-blob') do
@@ -90,7 +90,7 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false|
wait_for_all_requests
- visit(project_blob_path(project, 'upload_image/git-cheat-sheet.pdf'))
+ visit(project_blob_path(project, 'upload_image/sample.pdf'))
expect(page).to have_css('.js-pdf-viewer')
end
diff --git a/spec/support/shared_examples/features/runners_shared_examples.rb b/spec/support/shared_examples/features/runners_shared_examples.rb
index 31ee08ea9db..1d4af944187 100644
--- a/spec/support/shared_examples/features/runners_shared_examples.rb
+++ b/spec/support/shared_examples/features/runners_shared_examples.rb
@@ -146,6 +146,18 @@ RSpec.shared_examples 'pauses, resumes and deletes a runner' do
end
end
+RSpec.shared_examples 'filters by tag' do
+ it 'shows correct runner when tag matches' do
+ expect(page).to have_content found_runner
+ expect(page).to have_content missing_runner
+
+ input_filtered_search_filter_is_only('Tags', tag)
+
+ expect(page).to have_content found_runner
+ expect(page).not_to have_content missing_runner
+ end
+end
+
RSpec.shared_examples 'submits edit runner form' do
it 'breadcrumb contains runner id and token' do
page.within '[data-testid="breadcrumb-links"]' do
diff --git a/spec/support/shared_examples/features/search/search_timeouts_shared_examples.rb b/spec/support/shared_examples/features/search/search_timeouts_shared_examples.rb
index 095c48cade8..84dc2b20ddc 100644
--- a/spec/support/shared_examples/features/search/search_timeouts_shared_examples.rb
+++ b/spec/support/shared_examples/features/search/search_timeouts_shared_examples.rb
@@ -3,6 +3,7 @@
RSpec.shared_examples 'search timeouts' do |scope|
context 'when search times out' do
before do
+ stub_feature_flags(search_page_vertical_nav: false)
allow_next_instance_of(SearchService) do |service|
allow(service).to receive(:search_objects).and_raise(ActiveRecord::QueryCanceled)
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
index 95c0a76d726..206116d66c8 100644
--- 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
@@ -20,6 +20,8 @@ RSpec.shared_examples 'date sidebar widget' do
scroll_to(button)
button.click
+ execute_script('document.querySelector(".issuable-sidebar")?.scrollBy(0, 50)')
+
click_button today.to_s
wait_for_requests
diff --git a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
index 8081c51577a..ed885d7a226 100644
--- a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
@@ -147,6 +147,18 @@ RSpec.shared_examples 'User creates wiki page' do
end
end
+ it 'saves page content in local storage if the user navigates away', :js do
+ fill_in(:wiki_title, with: "Test title")
+ fill_in(:wiki_content, with: "This is a test")
+ fill_in(:wiki_message, with: "Test commit message")
+
+ refresh
+
+ expect(page).to have_field(:wiki_title, with: "Test title")
+ expect(page).to have_field(:wiki_content, with: "This is a test")
+ expect(page).to have_field(:wiki_message, with: "Test commit message")
+ end
+
it 'creates a wiki page with Org markup', :aggregate_failures, :js do
org_content = <<~ORG
* Heading
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 5c63d6a973d..0334187e4b1 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
@@ -78,6 +78,18 @@ RSpec.shared_examples 'User updates wiki page' do
expect(page).to have_content('My awesome wiki!')
end
+ it 'saves page content in local storage if the user navigates away', :js do
+ fill_in(:wiki_title, with: "Test title")
+ fill_in(:wiki_content, with: "This is a test")
+ fill_in(:wiki_message, with: "Test commit message")
+
+ refresh
+
+ expect(page).to have_field(:wiki_title, with: "Test title")
+ expect(page).to have_field(:wiki_content, with: "This is a test")
+ expect(page).to have_field(:wiki_message, with: "Test commit message")
+ end
+
it 'updates the commit message as the title is changed', :js do
fill_in(:wiki_title, with: '& < > \ \ { } &')
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb
index 32cb2b1d187..9b5326026b1 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb
@@ -53,37 +53,4 @@ RSpec.shared_examples 'User views wiki pages' do
end
end
end
-
- context 'ordered by created_at' do
- let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] }
-
- before do
- page.within('.wiki-sort-dropdown') do
- click_button('Title')
- click_button('Created date')
- end
- end
-
- context 'asc' do
- it 'pages are displayed in direct order' do
- pages.each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_created_at[index].title)
- end
- end
- end
-
- context 'desc' do
- before do
- page.within('.wiki-sort-dropdown') do
- page.find('.rspec-reverse-sort').click
- end
- end
-
- it 'pages are displayed in reversed order' do
- pages.reverse_each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_created_at[index].title)
- end
- end
- end
- end
end
diff --git a/spec/support/shared_examples/graphql/n_plus_one_query_examples.rb b/spec/support/shared_examples/graphql/n_plus_one_query_examples.rb
index faf1bb204c9..b4afde311ba 100644
--- a/spec/support/shared_examples/graphql/n_plus_one_query_examples.rb
+++ b/spec/support/shared_examples/graphql/n_plus_one_query_examples.rb
@@ -1,13 +1,23 @@
# frozen_string_literal: true
-RSpec.shared_examples 'N+1 query check' do
+
+RSpec.shared_examples 'N+1 query check' do |threshold: 0, skip_cached: true|
it 'prevents N+1 queries' do
execute_query # "warm up" to prevent undeterministic counts
expect(graphql_errors).to be_blank # Sanity check - ex falso quodlibet!
- control = ActiveRecord::QueryRecorder.new { execute_query }
+ control = ActiveRecord::QueryRecorder.new(skip_cached: skip_cached) { execute_query }
expect(control.count).to be > 0
search_params[:iids] << extra_iid_for_second_query
- expect { execute_query }.not_to exceed_query_limit(control)
+
+ expect { execute_query }.not_to exceed_query_count_limit(control, skip_cached: skip_cached, threshold: threshold)
+ end
+
+ def exceed_query_count_limit(control, skip_cached: true, threshold: 0)
+ if skip_cached
+ exceed_query_limit(control).with_threshold(threshold)
+ else
+ exceed_all_query_limit(control).with_threshold(threshold)
+ end
end
end
diff --git a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
index 82a9e8130f7..2e00abe2f8e 100644
--- a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
+++ b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
@@ -54,31 +54,6 @@ RSpec.shared_examples_for 'object cache helper' do
allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return(caller_id)
end
- context 'when feature flag is off' do
- before do
- stub_feature_flags(add_timing_to_certain_cache_actions: false)
- end
-
- it 'does not call increment' do
- expect(transaction).not_to receive(:increment).with(:cached_object_operations_total, any_args)
-
- subject
- end
-
- it 'does not call histogram' do
- expect(Gitlab::Metrics).not_to receive(:histogram)
-
- subject
- end
-
- it "is valid JSON" do
- parsed = Gitlab::Json.parse(subject.to_s)
-
- expect(parsed).to be_a(Hash)
- expect(parsed["id"]).to eq(presentable.id)
- end
- end
-
it 'increments the counter' do
expect(transaction)
.to receive(:increment)
@@ -157,34 +132,6 @@ RSpec.shared_examples_for 'collection cache helper' do
allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return(caller_id)
end
- context 'when feature flag is off' do
- before do
- stub_feature_flags(add_timing_to_certain_cache_actions: false)
- end
-
- it 'does not call increment' do
- expect(transaction).not_to receive(:increment).with(:cached_object_operations_total, any_args)
-
- subject
- end
-
- it 'does not call histogram' do
- expect(Gitlab::Metrics).not_to receive(:histogram)
-
- subject
- end
-
- it "is valid JSON" do
- parsed = Gitlab::Json.parse(subject.to_s)
-
- expect(parsed).to be_an(Array)
-
- presentable.each_with_index do |item, i|
- expect(parsed[i]["id"]).to eq(item.id)
- end
- end
- end
-
context 'when presentable has a group by clause' do
let(:presentable) { MergeRequest.group(:id) }
diff --git a/spec/support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples.rb
new file mode 100644
index 00000000000..98c0e7d506b
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/memory/watchdog/monitor_result_shared_examples.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'returns Watchdog Monitor result' do |threshold_violated:|
+ it 'returns if threshold is violated and payload' do
+ result = monitor.call
+
+ expect(result[:threshold_violated]).to eq(threshold_violated)
+ expect(result[:payload]).to eq(payload)
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/regex_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/regex_shared_examples.rb
new file mode 100644
index 00000000000..150741c6344
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/regex_shared_examples.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'regex rejecting path traversal' do
+ it { is_expected.not_to match('a../b') }
+ it { is_expected.not_to match('a..%2fb') }
+ it { is_expected.not_to match('a%2e%2e%2fb') }
+ it { is_expected.not_to match('a%2e%2e/b') }
+end
diff --git a/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb
index 6b6e25ca1dd..4b4a7f4ce9d 100644
--- a/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb
@@ -47,3 +47,47 @@ RSpec.shared_examples 'file template shared examples' do |filename, file_extensi
end
end
end
+
+RSpec.shared_examples 'acts as branch pipeline' do |jobs|
+ context 'when branch pipeline' do
+ let(:pipeline_branch) { default_branch }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch) }
+ let(:pipeline) { service.execute!(:push).payload }
+
+ it 'includes a job' do
+ expect(pipeline.builds.pluck(:name)).to match_array(jobs)
+ end
+ end
+end
+
+RSpec.shared_examples 'acts as MR pipeline' do |jobs, files|
+ context 'when MR pipeline' do
+ let(:pipeline_branch) { 'patch-1' }
+ let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
+ let(:pipeline) { service.execute(merge_request).payload }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: pipeline_branch,
+ target_project: project,
+ target_branch: default_branch)
+ end
+
+ before do
+ files.each do |filename, contents|
+ project.repository.create_file(
+ project.creator,
+ filename,
+ contents,
+ message: "Add #{filename}",
+ branch_name: pipeline_branch)
+ end
+ end
+
+ it 'includes a job' do
+ expect(pipeline).to be_merge_request_event
+ expect(pipeline.builds.pluck(:name)).to match_array(jobs)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/boards/listable_shared_examples.rb b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
index 250a4c1b1bd..ac8655a907f 100644
--- a/spec/support/shared_examples/models/boards/listable_shared_examples.rb
+++ b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
@@ -27,14 +27,6 @@ RSpec.shared_examples 'boards listable model' do |list_factory|
.to eq([list1, list3, list4, list2])
end
end
-
- describe '.without_types' do
- it 'excludes lists of given types' do
- lists = described_class.without_types([:label, :closed])
-
- expect(lists).to match_array([list1])
- end
- end
end
describe '#destroyable?' do
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 6cfeeabc952..6d0462a9ee8 100644
--- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -166,10 +166,14 @@ RSpec.shared_examples "chat integration" do |integration_name|
let(:opts) { { title: "Awesome issue", description: "please fix" } }
let(:sample_data) do
service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil)
- issue = service.execute
+ issue = service.execute[:issue]
service.hook_data(issue, "open")
end
+ before do
+ project.add_developer(user)
+ end
+
it_behaves_like "triggered #{integration_name} integration"
end
diff --git a/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb b/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb
new file mode 100644
index 00000000000..a4db4e25db3
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb
@@ -0,0 +1,355 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'a cascading namespace setting boolean attribute' do
+ |settings_attribute_name:, settings_association: :namespace_settings|
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let(:group_settings) { group.send(settings_association) }
+ let(:subgroup_settings) { subgroup.send(settings_association) }
+
+ describe "##{settings_attribute_name}" do
+ subject(:cascading_attribute) { subgroup_settings.send(settings_attribute_name) }
+
+ before do
+ stub_application_setting(settings_attribute_name => false)
+ end
+
+ context 'when there is no parent' do
+ context 'and the value is not nil' do
+ before do
+ group_settings.update!(settings_attribute_name => true)
+ end
+
+ it 'returns the local value' do
+ expect(group_settings.send(settings_attribute_name)).to eq(true)
+ end
+ end
+
+ context 'and the value is nil' do
+ before do
+ group_settings.update!(settings_attribute_name => nil)
+ end
+
+ it 'returns the application settings value' do
+ expect(group_settings.send(settings_attribute_name)).to eq(false)
+ end
+ end
+ end
+
+ context 'when parent does not lock the attribute' do
+ context 'and value is not nil' do
+ before do
+ group_settings.update!(settings_attribute_name => false)
+ end
+
+ it 'returns local setting when present' do
+ subgroup_settings.update!(settings_attribute_name => true)
+
+ expect(cascading_attribute).to eq(true)
+ end
+
+ it 'returns the parent value when local value is nil' do
+ subgroup_settings.update!(settings_attribute_name => nil)
+
+ expect(cascading_attribute).to eq(false)
+ end
+
+ it 'returns the correct dirty value' do
+ subgroup_settings.send("#{settings_attribute_name}=", true)
+
+ expect(cascading_attribute).to eq(true)
+ end
+
+ it 'does not return the application setting value when parent value is false' do
+ stub_application_setting(settings_attribute_name => true)
+
+ expect(cascading_attribute).to eq(false)
+ end
+ end
+
+ context 'and the value is nil' do
+ before do
+ group_settings.update!(settings_attribute_name => nil, "lock_#{settings_attribute_name}".to_sym => false)
+ subgroup_settings.update!(settings_attribute_name => nil)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ end
+
+ it 'cascades to the application settings value' do
+ expect(cascading_attribute).to eq(false)
+ end
+ end
+
+ context 'when multiple ancestors set a value' do
+ let(:third_level_subgroup) { create(:group, parent: subgroup) }
+
+ before do
+ group_settings.update!(settings_attribute_name => true)
+ subgroup_settings.update!(settings_attribute_name => false)
+ end
+
+ it 'returns the closest ancestor value' do
+ expect(third_level_subgroup.send(settings_association).send(settings_attribute_name)).to eq(false)
+ end
+ end
+ end
+
+ context 'when parent locks the attribute' do
+ before do
+ subgroup_settings.update!(settings_attribute_name => true)
+ group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor")
+ end
+
+ it 'returns the parent value' do
+ expect(cascading_attribute).to eq(false)
+ end
+
+ it 'does not allow the local value to be saved' do
+ subgroup_settings.send("#{settings_attribute_name}=", nil)
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid,
+ /cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when the application settings locks the attribute' do
+ before do
+ subgroup_settings.update!(settings_attribute_name => true)
+ stub_application_setting("lock_#{settings_attribute_name}" => true, settings_attribute_name => true)
+ end
+
+ it 'returns the application setting value' do
+ expect(cascading_attribute).to eq(true)
+ end
+
+ it 'does not allow the local value to be saved' do
+ subgroup_settings.send("#{settings_attribute_name}=", false)
+
+ expect { subgroup_settings.save! }
+ .to raise_error(
+ ActiveRecord::RecordInvalid,
+ /cannot be changed because it is locked by an ancestor/
+ )
+ end
+ end
+
+ context 'when parent locked the attribute then the application settings locks it' do
+ before do
+ subgroup_settings.update!(settings_attribute_name => true)
+ group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false)
+ stub_application_setting("lock_#{settings_attribute_name}" => true, settings_attribute_name => true)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor")
+ end
+
+ it 'returns the application setting value' do
+ expect(cascading_attribute).to eq(true)
+ end
+ end
+ end
+
+ describe "##{settings_attribute_name}?" do
+ before do
+ subgroup_settings.update!(settings_attribute_name => true)
+ group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor")
+ end
+
+ it 'aliases the method when the attribute is a boolean' do
+ expect(subgroup_settings.send("#{settings_attribute_name}?"))
+ .to eq(subgroup_settings.send(settings_attribute_name))
+ end
+ end
+
+ describe "##{settings_attribute_name}=" do
+ before do
+ subgroup_settings.update!(settings_attribute_name => nil)
+ group_settings.update!(settings_attribute_name => true)
+ end
+
+ it 'does not save the value locally when it matches the cascaded value' do
+ subgroup_settings.update!(settings_attribute_name => true)
+
+ expect(subgroup_settings.read_attribute(settings_attribute_name)).to eq(nil)
+ end
+ end
+
+ describe "##{settings_attribute_name}_locked?" do
+ shared_examples 'not locked' do
+ it 'is not locked by an ancestor' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(false)
+ end
+
+ it 'is not locked by application setting' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(false)
+ end
+
+ it 'does not return a locked namespace' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor")).to be_nil
+ end
+ end
+
+ context 'when attribute is locked by self' do
+ before do
+ subgroup_settings.update!("lock_#{settings_attribute_name}" => true)
+ end
+
+ it 'is not locked by default' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked?")).to eq(false)
+ end
+
+ it 'is locked when including self' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked?", include_self: true)).to eq(true)
+ end
+ end
+
+ context 'when parent does not lock the attribute' do
+ it_behaves_like 'not locked'
+ end
+
+ context 'when parent locks the attribute' do
+ before do
+ group_settings.update!("lock_#{settings_attribute_name}".to_sym => true, settings_attribute_name => false)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor")
+ end
+
+ it 'is locked by an ancestor' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(true)
+ end
+
+ it 'is not locked by application setting' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(false)
+ end
+
+ it 'returns a locked namespace settings object' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor").namespace_id)
+ .to eq(group_settings.namespace_id)
+ end
+ end
+
+ context 'when not locked by application settings' do
+ before do
+ stub_application_setting("lock_#{settings_attribute_name}" => false)
+ end
+
+ it_behaves_like 'not locked'
+ end
+
+ context 'when locked by application settings' do
+ before do
+ stub_application_setting("lock_#{settings_attribute_name}" => true)
+ end
+
+ it 'is not locked by an ancestor' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(false)
+ end
+
+ it 'is locked by application setting' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(true)
+ end
+
+ it 'does not return a locked namespace' do
+ expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor")).to be_nil
+ end
+ end
+ end
+
+ describe "#lock_#{settings_attribute_name}=" do
+ context 'when parent locks the attribute' do
+ before do
+ group_settings.update!("lock_#{settings_attribute_name}".to_sym => true, settings_attribute_name => false)
+
+ subgroup_settings.clear_memoization(settings_attribute_name)
+ subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor")
+ end
+
+ it 'does not allow the attribute to be saved' do
+ subgroup_settings.send("lock_#{settings_attribute_name}=", true)
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid,
+ /cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when parent does not lock the attribute' do
+ before do
+ group_settings.update!("lock_#{settings_attribute_name}" => false, settings_attribute_name => false)
+
+ subgroup_settings.send("lock_#{settings_attribute_name}=", true)
+ end
+
+ it 'allows the lock to be set when the attribute is not nil' do
+ subgroup_settings.send("#{settings_attribute_name}=", true)
+
+ expect(subgroup_settings.save).to eq(true)
+ end
+
+ it 'does not allow the lock to be saved when the attribute is nil' do
+ subgroup_settings.send("#{settings_attribute_name}=", nil)
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid,
+ /cannot be nil when locking the attribute/)
+ end
+
+ it 'copies the cascaded value when locking the attribute if the local value is nil', :aggregate_failures do
+ subgroup_settings.send("#{settings_attribute_name}=", nil)
+ subgroup_settings.send("lock_#{settings_attribute_name}=", true)
+
+ expect(subgroup_settings.read_attribute(settings_attribute_name)).to eq(false)
+ end
+ end
+
+ context 'when application settings locks the attribute' do
+ before do
+ stub_application_setting("lock_#{settings_attribute_name}".to_sym => true)
+ end
+
+ it 'does not allow the attribute to be saved' do
+ subgroup_settings.send("lock_#{settings_attribute_name}=", true)
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid,
+ /cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when application_settings does not lock the attribute' do
+ before do
+ stub_application_setting("lock_#{settings_attribute_name}".to_sym => false)
+ end
+
+ it 'allows the attribute to be saved' do
+ subgroup_settings.send("#{settings_attribute_name}=", true)
+ subgroup_settings.send("lock_#{settings_attribute_name}=", true)
+
+ expect(subgroup_settings.save).to eq(true)
+ end
+ end
+ end
+
+ describe 'after update callback' do
+ before do
+ group_settings.update!("lock_#{settings_attribute_name}" => false, settings_attribute_name => false)
+ subgroup_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false)
+ end
+
+ it 'clears descendant locks' do
+ group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => true)
+
+ expect(subgroup_settings.reload.send("lock_#{settings_attribute_name}")).to eq(false)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb b/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb
index f3a12578912..a658d02f09a 100644
--- a/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb
@@ -92,8 +92,8 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
it 'obtains an exclusive lease during processing' do
expect(model)
.to receive(:in_lock)
- .with(model.counter_lock_key(incremented_attribute), ttl: described_class::WORKER_LOCK_TTL)
- .and_call_original
+ .with(model.counter_lock_key(incremented_attribute), ttl: described_class::WORKER_LOCK_TTL)
+ .and_call_original
subject
end
@@ -104,7 +104,14 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
model.delayed_increment_counter(incremented_attribute, -3)
end
- it 'updates the record and logs it' do
+ it 'updates the record and logs it', :aggregate_failures do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ message: 'Acquiring lease for project statistics update',
+ attributes: [incremented_attribute]
+ )
+ )
+
expect(Gitlab::AppLogger).to receive(:info).with(
hash_including(
message: 'Flush counter attribute to database',
@@ -124,14 +131,14 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
it 'removes the increment entry from Redis' do
Gitlab::Redis::SharedState.with do |redis|
- key_exists = redis.exists(model.counter_key(incremented_attribute))
+ key_exists = redis.exists?(model.counter_key(incremented_attribute))
expect(key_exists).to be_truthy
end
subject
Gitlab::Redis::SharedState.with do |redis|
- key_exists = redis.exists(model.counter_key(incremented_attribute))
+ key_exists = redis.exists?(model.counter_key(incremented_attribute))
expect(key_exists).to be_falsey
end
end
@@ -162,7 +169,7 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
subject
Gitlab::Redis::SharedState.with do |redis|
- key_exists = redis.exists(model.counter_flushed_key(incremented_attribute))
+ key_exists = redis.exists?(model.counter_flushed_key(incremented_attribute))
expect(key_exists).to be_falsey
end
end
@@ -186,31 +193,88 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
end
end
- describe '#clear_counter!' do
+ describe '#reset_counter!' do
let(:attribute) { counter_attributes.first }
before do
+ model.update!(attribute => 123)
model.increment_counter(attribute, 10)
end
- it 'deletes the counter key for the given attribute and logs it' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- hash_including(
- message: 'Clear counter attribute',
- attribute: attribute,
- project_id: model.project_id,
- 'correlation_id' => an_instance_of(String),
- 'meta.feature_category' => 'test',
- 'meta.caller_id' => 'caller'
- )
- )
+ subject { model.reset_counter!(attribute) }
- model.clear_counter!(attribute)
+ it 'resets the attribute value to 0 and clears existing counter', :aggregate_failures do
+ expect { subject }.to change { model.reload.send(attribute) }.from(123).to(0)
Gitlab::Redis::SharedState.with do |redis|
- key_exists = redis.exists(model.counter_key(attribute))
+ key_exists = redis.exists?(model.counter_key(attribute))
expect(key_exists).to be_falsey
end
end
+
+ it_behaves_like 'obtaining lease to update database' do
+ context 'when the execution raises error' do
+ before do
+ allow(model).to receive(:update!).and_raise(StandardError, 'Something went wrong')
+ end
+
+ it 'reraises error' do
+ expect { subject }.to raise_error(StandardError, 'Something went wrong')
+ end
+ end
+ end
+ end
+
+ describe '#update_counters_with_lease' do
+ let(:increments) { { build_artifacts_size: 1, packages_size: 2 } }
+
+ subject { model.update_counters_with_lease(increments) }
+
+ it 'updates counters of the record' do
+ expect { subject }
+ .to change { model.reload.build_artifacts_size }.by(1)
+ .and change { model.reload.packages_size }.by(2)
+ end
+
+ it_behaves_like 'obtaining lease to update database' do
+ context 'when the execution raises error' do
+ before do
+ allow(model.class).to receive(:update_counters).and_raise(StandardError, 'Something went wrong')
+ end
+
+ it 'reraises error' do
+ expect { subject }.to raise_error(StandardError, 'Something went wrong')
+ end
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'obtaining lease to update database' do
+ context 'when it is unable to obtain lock' do
+ before do
+ allow(model).to receive(:in_lock).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+ end
+
+ it 'logs a warning' do
+ allow(model).to receive(:in_lock).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+
+ expect(Gitlab::AppLogger).to receive(:warn).once
+
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when feature flag counter_attribute_db_lease_for_update is disabled' do
+ before do
+ stub_feature_flags(counter_attribute_db_lease_for_update: false)
+ allow(model).to receive(:in_lock).and_call_original
+ end
+
+ it 'does not attempt to get a lock' do
+ expect(model).not_to receive(:in_lock)
+
+ subject
+ end
end
end
diff --git a/spec/support/shared_examples/models/concerns/has_wiki_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_wiki_shared_examples.rb
index 0357b7462fb..65bc6c10490 100644
--- a/spec/support/shared_examples/models/concerns/has_wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/has_wiki_shared_examples.rb
@@ -15,7 +15,7 @@ RSpec.shared_examples 'model with wiki' do
context 'when the repository cannot be created' do
before do
- expect(container.wiki).to receive(:wiki) { raise Wiki::CouldNotCreateWikiError }
+ expect(container.wiki).to receive(:create_wiki_repository) { raise Wiki::CouldNotCreateWikiError }
end
it 'returns false and adds a validation error' do
diff --git a/spec/support/shared_examples/models/concerns/participable_shared_examples.rb b/spec/support/shared_examples/models/concerns/participable_shared_examples.rb
new file mode 100644
index 00000000000..ec7a9105bb2
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/participable_shared_examples.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'visible participants for issuable with read ability' do |model_class|
+ let_it_be(:user1) { create(:user) }
+
+ let(:model) { model_class.to_s.classify.constantize }
+
+ before do
+ allow(Ability).to receive(:allowed?).with(anything, :"read_#{model_class}", anything).and_return(true)
+ allow(model).to receive(:participant_attrs).and_return([:bar])
+ end
+
+ shared_examples 'check for participables read ability' do |ability_name|
+ it 'receives expected ability' do
+ instance = model.new
+
+ allow(instance).to receive(:bar).and_return(participable_source)
+
+ expect(Ability).to receive(:allowed?).with(anything, ability_name, instance)
+
+ expect(instance.visible_participants(user1)).to be_empty
+ end
+ end
+
+ context 'when source is an award emoji' do
+ let(:participable_source) { build(:award_emoji, :upvote) }
+
+ it_behaves_like 'check for participables read ability', :read_issuable_participables
+ end
+
+ context 'when source is a note' do
+ let(:participable_source) { build(:note) }
+
+ it_behaves_like 'check for participables read ability', :read_note
+ end
+
+ context 'when source is an internal note' do
+ let(:participable_source) { build(:note, :confidential) }
+
+ it_behaves_like 'check for participables read ability', :read_internal_note
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
index d06e8391a9a..e4958779957 100644
--- a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'a timebox' do |timebox_type|
- let(:project) { create(:project, :public) }
- let(:group) { create(:group) }
let(:timebox_args) { [] }
- let(:timebox) { create(timebox_type, *timebox_args, project: project) }
let(:issue) { create(:issue, project: project) }
let(:user) { create(:user) }
let(:timebox_table_name) { timebox_type.to_s.pluralize.to_sym }
@@ -14,28 +11,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
let(:open_on_left) { nil }
let(:open_on_right) { nil }
- describe 'modules' do
- context 'with a project' do
- it_behaves_like 'AtomicInternalId' do
- let(:internal_id_attribute) { :iid }
- let(:instance) { build(timebox_type, *timebox_args, project: create(:project), group: nil) }
- let(:scope) { :project }
- let(:scope_attrs) { { project: instance.project } }
- let(:usage) { timebox_table_name }
- end
- end
-
- context 'with a group' do
- it_behaves_like 'AtomicInternalId' do
- let(:internal_id_attribute) { :iid }
- let(:instance) { build(timebox_type, *timebox_args, project: nil, group: create(:group)) }
- let(:scope) { :group }
- let(:scope_attrs) { { namespace: instance.group } }
- let(:usage) { timebox_table_name }
- end
- end
- end
-
describe "Validation" do
before do
allow(subject).to receive(:set_iid).and_return(false)
@@ -65,21 +40,9 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
expect(timebox.errors[:due_date]).to include("date must not be after 9999-12-31")
end
end
-
- describe '#timebox_type_check' do
- it 'is invalid if it has both project_id and group_id' do
- timebox = build(timebox_type, *timebox_args, group: group)
- timebox.project = project
-
- expect(timebox).not_to be_valid
- expect(timebox.errors[:project_id]).to include("#{timebox_type} should belong either to a project or a group.")
- end
- end
end
describe "Associations" do
- it { is_expected.to belong_to(:project) }
- it { is_expected.to belong_to(:group) }
it { is_expected.to have_many(:issues) }
it { is_expected.to have_many(:merge_requests) }
it { is_expected.to have_many(:labels).through(:issues) }
@@ -91,38 +54,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
end
end
- describe '#project_timebox?' do
- context 'when project_id is present' do
- it 'returns true' do
- expect(timebox.project_timebox?).to be_truthy
- end
- end
-
- context 'when project_id is not present' do
- let(:timebox) { build(timebox_type, *timebox_args, group: group) }
-
- it 'returns false' do
- expect(timebox.project_timebox?).to be_falsey
- end
- end
- end
-
- describe '#group_timebox?' do
- context 'when group_id is present' do
- let(:timebox) { build(timebox_type, *timebox_args, group: group) }
-
- it 'returns true' do
- expect(timebox.group_timebox?).to be_truthy
- end
- end
-
- context 'when group_id is not present' do
- it 'returns false' do
- expect(timebox.group_timebox?).to be_falsey
- end
- end
- end
-
describe '#safe_title' do
let(:timebox) { create(timebox_type, *timebox_args, title: "<b>foo & bar -> 2.2</b>") }
@@ -131,22 +62,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
end
end
- describe '#resource_parent' do
- context 'when group is present' do
- let(:timebox) { build(timebox_type, *timebox_args, group: group) }
-
- it 'returns the group' do
- expect(timebox.resource_parent).to eq(group)
- end
- end
-
- context 'when project is present' do
- it 'returns the project' do
- expect(timebox.resource_parent).to eq(project)
- end
- end
- end
-
describe "#title" do
let(:timebox) { create(timebox_type, *timebox_args, title: "<b>foo & bar -> 2.2</b>") }
@@ -155,39 +70,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
end
end
- describe '#merge_requests_enabled?' do
- context "per project" do
- it "is true for projects with MRs enabled" do
- project = create(:project, :merge_requests_enabled)
- timebox = create(timebox_type, *timebox_args, project: project)
-
- expect(timebox.merge_requests_enabled?).to be_truthy
- end
-
- it "is false for projects with MRs disabled" do
- project = create(:project, :repository_enabled, :merge_requests_disabled)
- timebox = create(timebox_type, *timebox_args, project: project)
-
- expect(timebox.merge_requests_enabled?).to be_falsey
- end
-
- it "is false for projects with repository disabled" do
- project = create(:project, :repository_disabled)
- timebox = create(timebox_type, *timebox_args, project: project)
-
- expect(timebox.merge_requests_enabled?).to be_falsey
- end
- end
-
- context "per group" do
- let(:timebox) { create(timebox_type, *timebox_args, group: group) }
-
- it "is always true for groups, for performance reasons" do
- expect(timebox.merge_requests_enabled?).to be_truthy
- end
- end
- end
-
describe '#to_ability_name' do
it 'returns timebox' do
timebox = build(timebox_type, *timebox_args)
diff --git a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb
index e309aa50c6e..31ec25249d7 100644
--- a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb
+++ b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb
@@ -4,7 +4,7 @@ RSpec.shared_examples Integrations::HasWebHook do
include AfterNextHelpers
describe 'associations' do
- it { is_expected.to have_one(:service_hook).inverse_of(:integration).with_foreign_key(:service_id) }
+ it { is_expected.to have_one(:service_hook).inverse_of(:integration).with_foreign_key(:integration_id) }
end
describe 'callbacks' do
diff --git a/spec/support/shared_examples/models/project_ci_cd_settings_shared_examples.rb b/spec/support/shared_examples/models/project_ci_cd_settings_shared_examples.rb
index c92e819db19..3caf58da4d2 100644
--- a/spec/support/shared_examples/models/project_ci_cd_settings_shared_examples.rb
+++ b/spec/support/shared_examples/models/project_ci_cd_settings_shared_examples.rb
@@ -5,12 +5,14 @@ RSpec.shared_examples 'ci_cd_settings delegation' do
context 'when ci_cd_settings is destroyed but project is not' do
it 'allows methods delegated to ci_cd_settings to be nil', :aggregate_failures do
- project = create(:project)
attributes = project.ci_cd_settings.attributes.keys - %w(id project_id) - exclude_attributes
+
+ expect(attributes).to match_array(attributes_with_prefix.keys)
+
project.ci_cd_settings.destroy!
project.reload
- attributes.each do |attr|
- method = project.respond_to?("ci_#{attr}") ? "ci_#{attr}" : attr
+ attributes_with_prefix.each do |attr, prefix|
+ method = "#{prefix}#{attr}"
expect(project.send(method)).to be_nil, "#{attr} was not nil"
end
end
@@ -20,8 +22,6 @@ end
RSpec.shared_examples 'a ci_cd_settings predicate method' do |prefix: ''|
using RSpec::Parameterized::TableSyntax
- let_it_be(:project) { create(:project) }
-
context 'when ci_cd_settings is nil' do
before do
allow(project).to receive(:ci_cd_settings).and_return(nil)
diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb
index 5f6a10bd754..b1aa90449e1 100644
--- a/spec/support/shared_examples/models/wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/wiki_shared_examples.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'wiki model' do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:user) { create(:user, :commit_email) }
let(:wiki_container) { raise NotImplementedError }
@@ -124,36 +126,6 @@ RSpec.shared_examples 'wiki model' do
end
end
- describe '#wiki' do
- it 'contains a Gitlab::Git::Wiki instance' do
- expect(subject.wiki).to be_a Gitlab::Git::Wiki
- end
-
- it 'creates a new wiki repo if one does not yet exist' do
- expect(subject.create_page('index', 'test content')).to be_truthy
- end
-
- it 'creates a new wiki repo with a default commit message' do
- expect(subject.create_page('index', 'test content', :markdown, '')).to be_truthy
-
- page = subject.find_page('index')
-
- expect(page.last_version.message).to eq("#{user.username} created page: index")
- end
-
- context 'when the repository cannot be created' do
- let(:wiki_container) { wiki_container_without_repo }
-
- before do
- expect(subject.repository).to receive(:create_if_not_exists) { false }
- end
-
- it 'raises CouldNotCreateWikiError' do
- expect { subject.wiki }.to raise_exception(Wiki::CouldNotCreateWikiError)
- end
- end
- end
-
describe '#empty?' do
context 'when the wiki repository is empty' do
it 'returns true' do
@@ -180,70 +152,71 @@ RSpec.shared_examples 'wiki model' do
it 'returns false' do
expect(subject.empty?).to be(false)
end
-
- it 'only instantiates a Wiki page once' do
- expect(WikiPage).to receive(:new).once.and_call_original
-
- subject.empty?
- end
end
end
end
describe '#list_pages' do
- let(:wiki_pages) { subject.list_pages }
+ shared_examples 'wiki model #list_pages' do
+ let(:wiki_pages) { subject.list_pages }
- before do
- subject.create_page('index', 'This is an index')
- subject.create_page('index2', 'This is an index2')
- subject.create_page('an index3', 'This is an index3')
- end
+ before do
+ subject.create_page('index', 'This is an index')
+ subject.create_page('index2', 'This is an index2')
+ subject.create_page('an index3', 'This is an index3')
+ end
- it 'returns an array of WikiPage instances' do
- expect(wiki_pages).to be_present
- expect(wiki_pages).to all(be_a(WikiPage))
- end
+ it 'returns an array of WikiPage instances' do
+ expect(wiki_pages).to be_present
+ expect(wiki_pages).to all(be_a(WikiPage))
+ end
- it 'does not load WikiPage content by default' do
- wiki_pages.each do |page|
- expect(page.content).to be_empty
+ it 'does not load WikiPage content by default' do
+ wiki_pages.each do |page|
+ expect(page.content).to be_empty
+ end
end
- end
- it 'returns all pages by default' do
- expect(wiki_pages.count).to eq(3)
- end
+ it 'returns all pages by default' do
+ expect(wiki_pages.count).to eq(3)
+ end
- context 'with limit option' do
- it 'returns limited set of pages' do
- expect(subject.list_pages(limit: 1).count).to eq(1)
+ context 'with limit option' do
+ it 'returns limited set of pages' do
+ expect(subject.list_pages(limit: 1).count).to eq(1)
+ end
end
- end
- context 'with sorting options' do
- it 'returns pages sorted by title by default' do
- pages = ['an index3', 'index', 'index2']
+ context 'with sorting options' do
+ it 'returns pages sorted by title by default' do
+ pages = ['an index3', 'index', 'index2']
- expect(subject.list_pages.map(&:title)).to eq(pages)
- expect(subject.list_pages(direction: 'desc').map(&:title)).to eq(pages.reverse)
+ expect(subject.list_pages.map(&:title)).to eq(pages)
+ expect(subject.list_pages(direction: 'desc').map(&:title)).to eq(pages.reverse)
+ end
end
- it 'returns pages sorted by created_at' do
- pages = ['index', 'index2', 'an index3']
+ context 'with load_content option' do
+ let(:pages) { subject.list_pages(load_content: true) }
- expect(subject.list_pages(sort: 'created_at').map(&:title)).to eq(pages)
- expect(subject.list_pages(sort: 'created_at', direction: 'desc').map(&:title)).to eq(pages.reverse)
+ it 'loads WikiPage content' do
+ expect(pages.first.content).to eq('This is an index3')
+ expect(pages.second.content).to eq('This is an index')
+ expect(pages.third.content).to eq('This is an index2')
+ end
end
end
- context 'with load_content option' do
- let(:pages) { subject.list_pages(load_content: true) }
-
- it 'loads WikiPage content' do
- expect(pages.first.content).to eq('This is an index3')
- expect(pages.second.content).to eq('This is an index')
- expect(pages.third.content).to eq('This is an index2')
+ context 'list pages with legacy wiki rpcs' do
+ before do
+ stub_feature_flags(wiki_list_page_with_normal_repository_rpcs: false)
end
+
+ it_behaves_like 'wiki model #list_pages'
+ end
+
+ context 'list pages with normal repository rpcs' do
+ it_behaves_like 'wiki model #list_pages'
end
end
@@ -338,6 +311,74 @@ RSpec.shared_examples 'wiki model' do
end
end
+ context "wiki repository's default branch is updated" do
+ before do
+ old_default_branch = wiki.default_branch
+ subject.create_page('page in updated default branch', 'content')
+ subject.repository.add_branch(user, 'another_branch', old_default_branch)
+ subject.repository.rm_branch(user, old_default_branch)
+ subject.repository.expire_status_cache
+ end
+
+ it 'returns the page in the updated default branch' do
+ wiki = described_class.new(wiki_container, user)
+ page = wiki.find_page('page in updated default branch')
+
+ expect(wiki.default_branch).to eql('another_branch')
+ expect(page.title).to eq('page in updated default branch')
+ end
+ end
+
+ context "wiki repository's HEAD is updated" do
+ before do
+ subject.create_page('page in updated HEAD', 'content')
+ subject.repository.add_branch(user, 'another_branch', subject.default_branch)
+ subject.repository.change_head('another_branch')
+ subject.repository.expire_status_cache
+ end
+
+ it 'returns the page in the new HEAD' do
+ wiki = described_class.new(wiki_container, user)
+ page = subject.find_page('page in updated HEAD')
+
+ expect(wiki.default_branch).to eql('another_branch')
+ expect(page.title).to eq('page in updated HEAD')
+ end
+ end
+
+ context 'pages with relative paths' do
+ where(:path, :title) do
+ [
+ ['~hello.md', '~Hello'],
+ ['hello~world.md', 'Hello~World'],
+ ['~~~hello.md', '~~~Hello'],
+ ['~/hello.md', '~/Hello'],
+ ['hello.md', '/Hello'],
+ ['hello.md', '../Hello'],
+ ['hello.md', './Hello'],
+ ['dir/hello.md', '/dir/Hello']
+ ]
+ end
+
+ with_them do
+ before do
+ wiki.repository.create_file(
+ user, path, "content of wiki file",
+ branch_name: wiki.default_branch,
+ message: "created page #{path}",
+ author_email: user.email,
+ author_name: user.name
+ )
+ end
+
+ it "can find page with `#{params[:title]}` title" do
+ page = subject.find_page(title)
+
+ expect(page.content).to eq("content of wiki file")
+ end
+ end
+ end
+
context 'pages with different file extensions' do
where(:extension, :path, :title) do
[
@@ -378,14 +419,6 @@ RSpec.shared_examples 'wiki model' do
end
end
- context 'find page with legacy wiki service' do
- before do
- stub_feature_flags(wiki_find_page_with_normal_repository_rpcs: false)
- end
-
- it_behaves_like 'wiki model #find_page'
- end
-
context 'find page with normal repository RPCs' do
it_behaves_like 'wiki model #find_page'
end
@@ -404,14 +437,6 @@ RSpec.shared_examples 'wiki model' do
end
end
- context 'find sidebar with legacy wiki service' do
- before do
- stub_feature_flags(wiki_find_page_with_normal_repository_rpcs: false)
- end
-
- it_behaves_like 'wiki model #find_sidebar'
- end
-
context 'find sidebar with normal repository RPCs' do
it_behaves_like 'wiki model #find_sidebar'
end
@@ -421,7 +446,7 @@ RSpec.shared_examples 'wiki model' do
let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
before do
- subject.wiki # Make sure the wiki repo exists
+ subject.create_wiki_repository # Make sure the wiki repo exists
subject.repository.create_file(user, 'image.png', image, branch_name: subject.default_branch, message: 'add image')
end
@@ -456,6 +481,22 @@ RSpec.shared_examples 'wiki model' do
expect(file.raw_data).to be_empty
end
end
+
+ context "wiki repository's default branch is updated" do
+ before do
+ old_default_branch = wiki.default_branch
+ subject.repository.add_branch(user, 'another_branch', old_default_branch)
+ subject.repository.rm_branch(user, old_default_branch)
+ subject.repository.expire_status_cache
+ end
+
+ it 'returns the page in the updated default branch' do
+ wiki = described_class.new(wiki_container, user)
+ file = wiki.find_file('image.png')
+
+ expect(file.mime_type).to eq('image/png')
+ end
+ end
end
describe '#create_page' do
@@ -480,7 +521,7 @@ RSpec.shared_examples 'wiki model' do
it 'sets the correct commit message' do
subject.create_page('test page', 'some content', :markdown, 'commit message')
- expect(subject.list_pages.first.page.version.message).to eq('commit message')
+ expect(subject.list_pages.first.version.message).to eq('commit message')
end
it 'sets the correct commit email' do
@@ -577,6 +618,8 @@ RSpec.shared_examples 'wiki model' do
'foo' | :org | ['foo.md'] | false
'foo' | :markdown | ['dir/foo.md'] | true
'/foo' | :markdown | ['foo.md'] | false
+ '~foo' | :markdown | [] | true
+ '~~~foo' | :markdown | [] | true
'./foo' | :markdown | ['foo.md'] | false
'../foo' | :markdown | ['foo.md'] | false
'../../foo' | :markdown | ['foo.md'] | false
@@ -607,14 +650,6 @@ RSpec.shared_examples 'wiki model' do
end
it_behaves_like 'create_page tests'
-
- context 'create page with legacy find_page wiki service' do
- it_behaves_like 'create_page tests' do
- before do
- stub_feature_flags(wiki_find_page_with_normal_repository_rpcs: false)
- end
- end
- end
end
describe '#update_page' do
@@ -687,6 +722,8 @@ RSpec.shared_examples 'wiki model' do
using RSpec::Parameterized::TableSyntax
where(:original_title, :original_format, :updated_title, :updated_format, :expected_title, :expected_path) do
+ 'test page' | :markdown | '~new test page' | :asciidoc | '~new test page' | '~new-test-page.asciidoc'
+ 'test page' | :markdown | '~~~new test page' | :asciidoc | '~~~new test page' | '~~~new-test-page.asciidoc'
'test page' | :markdown | 'new test page' | :asciidoc | 'new test page' | 'new-test-page.asciidoc'
'test page' | :markdown | 'new dir/new test page' | :asciidoc | 'new dir/new test page' | 'new-dir/new-test-page.asciidoc'
'test dir/test page' | :markdown | 'new dir/new test page' | :asciidoc | 'new dir/new test page' | 'new-dir/new-test-page.asciidoc'
@@ -696,13 +733,13 @@ RSpec.shared_examples 'wiki model' do
'test dir/test page' | :markdown | nil | :markdown | 'test dir/test page' | 'test-dir/test-page.md'
'test page' | :markdown | '' | :markdown | 'test page' | 'test-page.md'
'test.page' | :markdown | '' | :markdown | 'test.page' | 'test.page.md'
- 'testpage' | :markdown | '../testpage' | :markdown | 'testpage' | 'testpage.md'
- 'dir/testpage' | :markdown | 'dir/../testpage' | :markdown | 'testpage' | 'testpage.md'
- 'dir/testpage' | :markdown | './dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
- 'dir/testpage' | :markdown | '../dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
- 'dir/testpage' | :markdown | '../dir/../testpage' | :markdown | 'testpage' | 'testpage.md'
- 'dir/testpage' | :markdown | '../dir/../dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
- 'dir/testpage' | :markdown | '../dir/../another/testpage' | :markdown | 'another/testpage' | 'another/testpage.md'
+ 'testpage' | :markdown | '../testpage' | :markdown | 'testpage' | 'testpage.md'
+ 'dir/testpage' | :markdown | 'dir/../testpage' | :markdown | 'testpage' | 'testpage.md'
+ 'dir/testpage' | :markdown | './dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
+ 'dir/testpage' | :markdown | '../dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
+ 'dir/testpage' | :markdown | '../dir/../testpage' | :markdown | 'testpage' | 'testpage.md'
+ 'dir/testpage' | :markdown | '../dir/../dir/testpage' | :markdown | 'dir/testpage' | 'dir/testpage.md'
+ 'dir/testpage' | :markdown | '../dir/../another/testpage' | :markdown | 'another/testpage' | 'another/testpage.md'
end
end
@@ -711,17 +748,6 @@ RSpec.shared_examples 'wiki model' do
include_context 'extended examples'
end
- context 'update page with legacy find_page wiki service' do
- it_behaves_like 'update_page tests' do
- before do
- stub_feature_flags(wiki_find_page_with_normal_repository_rpcs: false)
- end
-
- include_context 'common examples'
- include_context 'extended examples'
- end
- end
-
context 'when format is invalid' do
let!(:page) { create(:wiki_page, wiki: subject, title: 'test page') }
@@ -862,7 +888,7 @@ RSpec.shared_examples 'wiki model' do
end
describe '#create_wiki_repository' do
- let(:head_path) { Rails.root.join(TestEnv.repos_path, "#{wiki.disk_path}.git", 'HEAD') }
+ let(:head_path) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { Rails.root.join(TestEnv.repos_path, "#{wiki.disk_path}.git", 'HEAD') } }
let(:default_branch) { 'foo' }
before do
@@ -895,4 +921,40 @@ RSpec.shared_examples 'wiki model' do
end
end
end
+
+ describe '#preview_slug' do
+ where(:title, :file_extension, :format, :expected_slug) do
+ 'The Best Thing' | :md | :markdown | 'The-Best-Thing'
+ 'The Best Thing' | :txt | :plaintext | 'The-Best-Thing'
+ 'A Subject/Title Here' | :txt | :plaintext | 'A-Subject/Title-Here'
+ 'A subject' | :txt | :plaintext | 'A-subject'
+ 'A 1/B 2/C 3' | :txt | :plaintext | 'A-1/B-2/C-3'
+ 'subject/title' | :txt | :plaintext | 'subject/title'
+ 'subject/title.md' | :txt | :plaintext | 'subject/title.md'
+ 'foo%2Fbar' | :txt | :plaintext | 'foo%2Fbar'
+ '' | :md | :markdown | '.md'
+ '' | :txt | :plaintext | '.txt'
+ end
+
+ with_them do
+ before do
+ subject.repository.create_file(
+ user, "#{title}.#{file_extension}", 'content',
+ branch_name: subject.default_branch,
+ message: "Add #{title}"
+ )
+ end
+
+ it do
+ expect(described_class.preview_slug(title, file_extension)).to eq(expected_slug)
+ end
+
+ it 'matches the slug generated by gitaly' do
+ skip('Gitaly cannot generate a slug for an empty title') unless title.present?
+
+ gitaly_slug = subject.list_pages.first.slug
+ expect(described_class.preview_slug(title, file_extension)).to eq(gitaly_slug)
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/policies/wiki_policies_shared_examples.rb b/spec/support/shared_examples/policies/wiki_policies_shared_examples.rb
index 991d6289373..b9d4709efd5 100644
--- a/spec/support/shared_examples/policies/wiki_policies_shared_examples.rb
+++ b/spec/support/shared_examples/policies/wiki_policies_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'model with wiki policies' do
- include ProjectHelpers
+ include UserHelpers
include AdminModeHelper
let(:container) { raise NotImplementedError }
diff --git a/spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb b/spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb
index 9c2d30a9c8c..f7731af8dc6 100644
--- a/spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb
+++ b/spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb
@@ -1,53 +1,5 @@
# frozen_string_literal: true
-RSpec.shared_examples 'handling invalid params' do |service_response_extra: {}, supports_caching: false|
- context 'when no params are specified' do
- let(:params) { {} }
-
- it_behaves_like 'not removing anything',
- service_response_extra: service_response_extra,
- supports_caching: supports_caching
- end
-
- context 'with invalid regular expressions' do
- shared_examples 'handling an invalid regex' do
- it 'keeps all tags' do
- expect(Projects::ContainerRepository::DeleteTagsService)
- .not_to receive(:new)
- expect_no_caching unless supports_caching
-
- subject
- end
-
- it { is_expected.to eq(status: :error, message: 'invalid regex') }
-
- it 'calls error tracking service' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).and_call_original
-
- subject
- end
- end
-
- context 'when name_regex_delete is invalid' do
- let(:params) { { 'name_regex_delete' => '*test*' } }
-
- it_behaves_like 'handling an invalid regex'
- end
-
- context 'when name_regex is invalid' do
- let(:params) { { 'name_regex' => '*test*' } }
-
- it_behaves_like 'handling an invalid regex'
- end
-
- context 'when name_regex_keep is invalid' do
- let(:params) { { 'name_regex_keep' => '*test*' } }
-
- it_behaves_like 'handling an invalid regex'
- end
- end
-end
-
RSpec.shared_examples 'when regex matching everything is specified' do
|service_response_extra: {}, supports_caching: false, delete_expectations:|
let(:params) do
@@ -227,20 +179,6 @@ RSpec.shared_examples 'when running a container_expiration_policy' do
is_expected.to eq(expected_service_response(deleted: delete_expectations.flatten).merge(service_response_extra))
end
end
-
- context 'without container_expiration_policy param' do
- let(:params) do
- {
- 'name_regex_delete' => '.*',
- 'keep_n' => 1,
- 'older_than' => '1 day'
- }
- end
-
- it 'fails' do
- is_expected.to eq(status: :error, message: 'access denied')
- end
- end
end
RSpec.shared_examples 'not removing anything' do |service_response_extra: {}, supports_caching: false|
diff --git a/spec/support/shared_examples/quick_actions/issuable/max_issuable_examples.rb b/spec/support/shared_examples/quick_actions/issuable/max_issuable_examples.rb
new file mode 100644
index 00000000000..e725de8ad31
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/max_issuable_examples.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'does not exceed the issuable size limit' do
+ let(:user1) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ project.add_maintainer(user1)
+ project.add_maintainer(user2)
+ project.add_maintainer(user3)
+ end
+
+ context 'when feature flag is turned on' do
+ context "when the number of users of issuable does exceed the limit" do
+ before do
+ stub_const("Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS", 2)
+ end
+
+ it 'will not add more than the allowed number of users' do
+ allow_next_instance_of(update_service) do |service|
+ expect(service).not_to receive(:execute)
+ end
+
+ note = described_class.new(project, user, opts.merge(
+ note: note_text,
+ noteable_type: noteable_type,
+ noteable_id: issuable.id,
+ confidential: false
+ )).execute
+
+ expect(note.errors[:validation]).to match_array([validation_message])
+ end
+ end
+
+ context "when the number of users does not exceed the limit" do
+ before do
+ stub_const("Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS", 6)
+ end
+
+ it 'calls execute and does not return an error' do
+ allow_next_instance_of(update_service) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ note = described_class.new(project, user, opts.merge(
+ note: note_text,
+ noteable_type: noteable_type,
+ noteable_id: issuable.id,
+ confidential: false
+ )).execute
+
+ expect(note.errors[:validation]).to be_empty
+ end
+ end
+ end
+
+ context 'when feature flag is off' do
+ before do
+ stub_feature_flags(feature_flag_hash)
+ end
+
+ context "when the number of users of issuable does exceed the limit" do
+ before do
+ stub_const("Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS", 2)
+ end
+
+ it 'will not add more than the allowed number of users' do
+ allow_next_instance_of(MergeRequests::UpdateService) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ note = described_class.new(project, user, opts.merge(
+ note: note_text,
+ noteable_type: 'MergeRequest',
+ noteable_id: issuable.id,
+ confidential: false
+ )).execute
+
+ expect(note.errors[:validation]).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb b/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
index 017e6274cb0..59e641e2af6 100644
--- a/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
+++ b/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
@@ -2,18 +2,13 @@
RSpec.shared_examples 'GET resource access tokens available' do
let_it_be(:active_resource_access_token) { create(:personal_access_token, user: bot_user) }
- let_it_be(:inactive_resource_access_token) { create(:personal_access_token, :revoked, user: bot_user) }
it 'retrieves active resource access tokens' do
subject
- expect(assigns(:active_resource_access_tokens)).to contain_exactly(active_resource_access_token)
- end
-
- it 'retrieves inactive resource access tokens' do
- subject
-
- expect(assigns(:inactive_resource_access_tokens)).to contain_exactly(inactive_resource_access_token)
+ token_entities = assigns(:active_resource_access_tokens)
+ expect(token_entities.length).to eq(1)
+ expect(token_entities[0][:name]).to eq(active_resource_access_token.name)
end
it 'lists all available scopes' do
@@ -21,15 +16,6 @@ RSpec.shared_examples 'GET resource access tokens available' do
expect(assigns(:scopes)).to eq(Gitlab::Auth.resource_bot_scopes)
end
-
- it 'retrieves newly created personal access token value' do
- token_value = 'random-value'
- allow(PersonalAccessToken).to receive(:redis_getdel).with("#{user.id}:#{resource.id}").and_return(token_value)
-
- subject
-
- expect(assigns(:new_resource_access_token)).to eq(token_value)
- end
end
RSpec.shared_examples 'POST resource access tokens available' do
@@ -37,10 +23,13 @@ RSpec.shared_examples 'POST resource access tokens available' do
PersonalAccessToken.order(:created_at).last
end
- it 'returns success message' do
+ it 'renders JSON with a token' do
subject
- expect(flash[:notice]).to match('Your new access token has been created.')
+ parsed_body = Gitlab::Json.parse(response.body)
+ expect(parsed_body['new_token']).not_to be_blank
+ expect(parsed_body['errors']).to be_blank
+ expect(response).to have_gitlab_http_status(:success)
end
it 'creates resource access token' do
@@ -59,12 +48,6 @@ RSpec.shared_examples 'POST resource access tokens available' do
expect(created_token.user).to be_project_bot
end
- it 'stores newly created token redis store' do
- expect(PersonalAccessToken).to receive(:redis_store!)
-
- subject
- end
-
it { expect { subject }.to change { User.count }.by(1) }
it { expect { subject }.to change { PersonalAccessToken.count }.by(1) }
@@ -87,10 +70,13 @@ RSpec.shared_examples 'POST resource access tokens available' do
expect { subject }.not_to change { User.count }
end
- it 'shows a failure alert' do
+ it 'renders JSON with an error' do
subject
- expect(flash[:alert]).to match("Failed to create new access token: Failed!")
+ parsed_body = Gitlab::Json.parse(response.body)
+ expect(parsed_body['new_token']).to be_blank
+ expect(parsed_body['errors']).to contain_exactly('Failed!')
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index de7032450a5..14a83d2889b 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -24,7 +24,7 @@ RSpec.shared_examples 'Debian packages upload request' do |status, body = nil|
if status == :created
it 'creates package files', :aggregate_failures do
expect(::Packages::Debian::FindOrCreateIncomingService).to receive(:new).with(container, user).and_call_original
- expect(::Packages::Debian::CreatePackageFileService).to receive(:new).with(be_a(Packages::Package), be_an(Hash)).and_call_original
+ expect(::Packages::Debian::CreatePackageFileService).to receive(:new).with(package: be_a(Packages::Package), current_user: be_an(User), params: be_an(Hash)).and_call_original
if file_name.end_with? '.changes'
expect(::Packages::Debian::ProcessChangesWorker).to receive(:perform_async)
diff --git a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
index 06ed0448b50..8bf6b162508 100644
--- a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
@@ -247,6 +247,15 @@ RSpec.shared_examples 'handling helm chart index requests' do
end
end
+ context 'with access to package registry for everyone' do
+ before do
+ project.update!(visibility: Gitlab::VisibilityLevel::PRIVATE)
+ project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+ end
+
+ it_behaves_like 'process helm service index request', :anonymous, :success
+ end
+
context 'when an invalid token is passed' do
let(:headers) { basic_auth_header(user.username, 'wrong') }
diff --git a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
index 013945bd578..d666a754d9f 100644
--- a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
@@ -134,6 +134,7 @@ RSpec.shared_examples 'web-hook API endpoints' do |prefix|
context 'the hook is backed-off' do
before do
+ WebHook::FAILURE_THRESHOLD.times { hook.backoff! }
hook.backoff!
end
diff --git a/spec/support/shared_examples/requests/api/issuable_update_shared_examples.rb b/spec/support/shared_examples/requests/api/issuable_update_shared_examples.rb
index a3378d4619b..1045a92f332 100644
--- a/spec/support/shared_examples/requests/api/issuable_update_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/issuable_update_shared_examples.rb
@@ -20,7 +20,7 @@ RSpec.shared_examples 'issuable update endpoint' do
end
it 'updates the issuable with labels param as array' do
- stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 110)
+ allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(110)
params = { labels: ['label1', 'label2', 'foo, bar', '&,?'] }
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 b651ffc8996..85ac2b5e1ea 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
@@ -260,7 +260,11 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
project.send("add_#{user_role}", user) if user_role
project.update!(visibility: visibility.to_s)
package.update!(name: package_name) unless package_name == 'non-existing-package'
- allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward)
+ if scope == :instance
+ allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward)
+ else
+ allow_fetch_cascade_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward)
+ end
end
example_name = "#{params[:expected_result]} metadata request"
diff --git a/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb
index 86b6975bf9f..1d79a61fbb0 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb
@@ -14,6 +14,7 @@ RSpec.shared_examples 'accept package tags request' do |status:|
before do
allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: false)
+ allow_fetch_cascade_application_setting(attribute: "npm_package_requests_forwarding", return_value: false)
end
context 'with valid package name' do
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 f411b5699a9..11e19d8d067 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
@@ -291,7 +291,7 @@ RSpec.shared_examples 'pypi simple API endpoint' do
end
before do
- allow_fetch_application_setting(attribute: "pypi_package_requests_forwarding", return_value: forward)
+ allow_fetch_cascade_application_setting(attribute: "pypi_package_requests_forwarding", return_value: forward)
end
it_behaves_like params[:shared_examples_name], :reporter, params[:expected_status]
diff --git a/spec/support/shared_examples/requests/projects/google_cloud/google_oauth2_token_examples.rb b/spec/support/shared_examples/requests/projects/google_cloud/google_oauth2_token_examples.rb
index 379327be0db..e2e2658d803 100644
--- a/spec/support/shared_examples/requests/projects/google_cloud/google_oauth2_token_examples.rb
+++ b/spec/support/shared_examples/requests/projects/google_cloud/google_oauth2_token_examples.rb
@@ -18,6 +18,7 @@ RSpec.shared_examples 'requires valid Google Oauth2 token' 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(mock_gcp_projects) if mock_gcp_projects
+ allow(client).to receive(:create_cloudsql_instance)
end
allow_next_instance_of(BranchesFinder) do |finder|
diff --git a/spec/support/shared_examples/serializers/issuable_current_user_properties_shared_examples.rb b/spec/support/shared_examples/serializers/issuable_current_user_properties_shared_examples.rb
new file mode 100644
index 00000000000..6c285bfba91
--- /dev/null
+++ b/spec/support/shared_examples/serializers/issuable_current_user_properties_shared_examples.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable entity current_user properties' do
+ describe 'can_create_confidential_note' do
+ subject do
+ described_class.new(resource, request: request)
+ .as_json[:current_user][:can_create_confidential_note]
+ end
+
+ context 'when user can create confidential notes' do
+ before do
+ resource.resource_parent.add_reporter(user)
+ end
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when user cannot create confidential notes' do
+ it { is_expected.to eq(false) }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/base_rpm_service_shared_examples.rb b/spec/support/shared_examples/services/base_rpm_service_shared_examples.rb
new file mode 100644
index 00000000000..c9520852a5b
--- /dev/null
+++ b/spec/support/shared_examples/services/base_rpm_service_shared_examples.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'handling rpm xml file' do
+ include_context 'with rpm package data'
+
+ let(:xml) { nil }
+ let(:data) { {} }
+
+ context 'when generate empty xml' do
+ it 'generate expected xml' do
+ expect(subject).to eq(empty_xml)
+ end
+ end
+
+ context 'when updating existing xml' do
+ let(:xml) { empty_xml }
+ let(:data) { xml_update_params }
+
+ shared_examples 'changing root tag attribute' do
+ it "increment previous 'packages' value by 1" do
+ previous_value = Nokogiri::XML(xml).at(described_class::ROOT_TAG).attributes["packages"].value.to_i
+ new_value = Nokogiri::XML(subject).at(described_class::ROOT_TAG).attributes["packages"].value.to_i
+
+ expect(previous_value + 1).to eq(new_value)
+ end
+ end
+
+ it 'generate valid xml add expected xml node to existing xml' do
+ # Have one root attribute
+ result = Nokogiri::XML::Document.parse(subject).remove_namespaces!
+ expect(result.children.count).to eq(1)
+
+ # Root node has 1 child with generated node
+ expect(result.xpath("//#{described_class::ROOT_TAG}/package").count).to eq(1)
+ end
+
+ context 'when empty xml' do
+ it_behaves_like 'changing root tag attribute'
+ end
+
+ context 'when xml has children' do
+ let(:xml) { described_class.new(xml: empty_xml, data: data).execute }
+
+ it 'has children nodes' do
+ result = Nokogiri::XML::Document.parse(xml).remove_namespaces!
+ expect(result.children.count).to be > 0
+ end
+
+ it_behaves_like 'changing root tag attribute'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/merge_request_shared_examples.rb b/spec/support/shared_examples/services/merge_request_shared_examples.rb
index b3ba0a1be93..cfd75d3cfcd 100644
--- a/spec/support/shared_examples/services/merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/services/merge_request_shared_examples.rb
@@ -19,29 +19,13 @@ RSpec.shared_examples 'reviewer_ids filter' do
let(:reviewer2) { create(:user) }
context 'when the current user can admin the merge_request' do
- context 'when merge_request_reviewer feature is enabled' do
+ context 'with a reviewer who can read the merge_request' do
before do
- stub_feature_flags(merge_request_reviewer: true)
+ project.add_developer(reviewer1)
end
- context 'with a reviewer who can read the merge_request' do
- before do
- project.add_developer(reviewer1)
- end
-
- it 'contains reviewers who can read the merge_request' do
- expect(execute.reviewers).to contain_exactly(reviewer1)
- end
- end
- end
-
- context 'when merge_request_reviewer feature is disabled' do
- before do
- stub_feature_flags(merge_request_reviewer: false)
- end
-
- it 'contains no reviewers' do
- expect(execute.reviewers).to eq []
+ it 'contains reviewers who can read the merge_request' do
+ expect(execute.reviewers).to contain_exactly(reviewer1)
end
end
end
diff --git a/spec/support/shared_examples/services/reviewers_change_trigger_shared_examples.rb b/spec/support/shared_examples/services/reviewers_change_trigger_shared_examples.rb
new file mode 100644
index 00000000000..cc37ea0c6f0
--- /dev/null
+++ b/spec/support/shared_examples/services/reviewers_change_trigger_shared_examples.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'triggers GraphQL subscription mergeRequestReviewersUpdated' do
+ specify do
+ expect(GraphqlTriggers).to receive(:merge_request_reviewers_updated).with(merge_request)
+
+ action
+ end
+end
+
+RSpec.shared_examples 'does not trigger GraphQL subscription mergeRequestReviewersUpdated' do
+ specify do
+ expect(GraphqlTriggers).not_to receive(:merge_request_reviewers_updated)
+
+ action
+ end
+end
diff --git a/spec/support/view_component.rb b/spec/support/view_component.rb
index 9166a06fc8c..912bfda6d33 100644
--- a/spec/support/view_component.rb
+++ b/spec/support/view_component.rb
@@ -4,4 +4,11 @@ require 'view_component/test_helpers'
RSpec.configure do |config|
config.include ViewComponent::TestHelpers, type: :component
config.include Capybara::RSpecMatchers, type: :component
+ config.include Devise::Test::ControllerHelpers, type: :component
+
+ config.before(:each, type: :component) do
+ @request = controller.request
+ end
+
+ config.include_context 'when page has no HTML escapes', type: :component
end
diff --git a/spec/support_specs/capybara_slow_finder_spec.rb b/spec/support_specs/capybara_slow_finder_spec.rb
new file mode 100644
index 00000000000..b0438a7a78b
--- /dev/null
+++ b/spec/support_specs/capybara_slow_finder_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'capybara'
+require 'support/capybara_slow_finder'
+
+RSpec.describe Capybara::Node::Base::SlowFinder do # rubocop:disable RSpec/FilePath
+ context 'without timeout' do
+ context 'when element is found' do
+ let(:slow_finder) do
+ Class.new do
+ def synchronize(seconds = nil, errors: nil)
+ true
+ end
+
+ prepend Capybara::Node::Base::SlowFinder
+ end.new
+ end
+
+ it 'does not raise error' do
+ expect { slow_finder.synchronize }.not_to raise_error
+ end
+ end
+
+ context 'when element is not found' do
+ let(:slow_finder) do
+ Class.new do
+ def synchronize(seconds = nil, errors: nil)
+ raise Capybara::ElementNotFound
+ end
+
+ prepend Capybara::Node::Base::SlowFinder
+ end.new
+ end
+
+ it 'raises Capybara::ElementNotFound error' do
+ expect { slow_finder.synchronize }.to raise_error(Capybara::ElementNotFound)
+ end
+ end
+ end
+
+ context 'with timeout' do
+ let(:timeout) { 0.01 }
+
+ let(:slow_finder) do
+ Class.new do
+ def synchronize(seconds = nil, errors: nil)
+ sleep 0.02
+
+ raise Capybara::ElementNotFound
+ end
+
+ prepend Capybara::Node::Base::SlowFinder
+ end.new
+ end
+
+ context 'with default timeout' do
+ it 'raises a timeout error' do
+ expect(Capybara).to receive(:default_max_wait_time).and_return(timeout)
+
+ expect { slow_finder.synchronize }.to raise_error_element_not_found
+ end
+ end
+
+ context 'when passed as paramater' do
+ it 'raises a timeout error' do
+ expect { slow_finder.synchronize(timeout) }.to raise_error_element_not_found
+ end
+ end
+
+ def raise_error_element_not_found
+ raise_error(
+ Capybara::ElementNotFound,
+ /\n\nTimeout \(#{timeout}s\) reached while running a waiting Capybara finder./
+ )
+ end
+ end
+end
diff --git a/spec/support_specs/database/multiple_databases_spec.rb b/spec/support_specs/database/multiple_databases_spec.rb
index b4cfa253813..0b019462077 100644
--- a/spec/support_specs/database/multiple_databases_spec.rb
+++ b/spec/support_specs/database/multiple_databases_spec.rb
@@ -3,6 +3,28 @@
require 'spec_helper'
RSpec.describe 'Database::MultipleDatabases' do
+ let(:query) do
+ <<~SQL
+ WITH cte AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (SELECT 1) SELECT 1;
+ SQL
+ end
+
+ it 'preloads database version for ApplicationRecord' do
+ counts = ActiveRecord::QueryRecorder
+ .new { ApplicationRecord.connection.execute(query) }
+ .count
+
+ expect(counts).to eq(1)
+ end
+
+ it 'preloads database version for Ci::ApplicationRecord' do
+ counts = ActiveRecord::QueryRecorder
+ .new { Ci::ApplicationRecord.connection.execute(query) }
+ .count
+
+ expect(counts).to eq(1)
+ end
+
describe '.with_reestablished_active_record_base' do
context 'when doing establish_connection' do
context 'on ActiveRecord::Base' do
diff --git a/spec/support_specs/helpers/graphql_helpers_spec.rb b/spec/support_specs/helpers/graphql_helpers_spec.rb
index c02e4adf983..12a6e561257 100644
--- a/spec/support_specs/helpers/graphql_helpers_spec.rb
+++ b/spec/support_specs/helpers/graphql_helpers_spec.rb
@@ -133,6 +133,23 @@ RSpec.describe GraphqlHelpers do
expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([nil, 2, 3, nil])
end
+
+ it 'supports fields with leading underscore' do
+ web_path = '/namespace1/project1/-/packages/997'
+ data = {
+ 'packages' => {
+ 'nodes' => [
+ {
+ '_links' => {
+ 'webPath' => web_path
+ }
+ }
+ ]
+ }
+ }
+
+ expect(graphql_dig_at(data, :packages, :nodes, :_links, :web_path)).to match_array([web_path])
+ end
end
describe 'var' do
@@ -417,4 +434,22 @@ RSpec.describe GraphqlHelpers do
end
end
end
+
+ describe '.fieldnamerize' do
+ subject { described_class.fieldnamerize(field) }
+
+ let(:field) { 'merge_request' }
+
+ it 'makes an underscored string look like a fieldname' do
+ is_expected.to eq('mergeRequest')
+ end
+
+ context 'when field has a leading underscore' do
+ let(:field) { :_links }
+
+ it 'skips a transformation' do
+ is_expected.to eq('_links')
+ end
+ end
+ end
end
diff --git a/spec/support_specs/helpers/html_escaped_helpers_spec.rb b/spec/support_specs/helpers/html_escaped_helpers_spec.rb
index 337f7ecc659..77ca6231881 100644
--- a/spec/support_specs/helpers/html_escaped_helpers_spec.rb
+++ b/spec/support_specs/helpers/html_escaped_helpers_spec.rb
@@ -40,4 +40,33 @@ RSpec.describe HtmlEscapedHelpers do
specify { expect(actual_match).to eq(expected_match) }
end
end
+
+ describe '#ensure_no_html_escaped_tags!' do
+ subject { |example| described_class.ensure_no_html_escaped_tags!(content, example) }
+
+ context 'when content contains HTML escaped chars' do
+ let(:content) { 'See &lt;a href=""&gt;Link&lt;/a&gt;' }
+
+ it 'raises an exception' do
+ parts = [
+ 'The following string contains HTML escaped tags:',
+ 'See «&lt;a» href=""&gt;Link&lt;/a&gt;',
+ 'This check can be disabled via:',
+ %(it "raises an exception", :skip_html_escaped_tags_check do)
+ ]
+
+ regexp = Regexp.new(parts.join('.*'), Regexp::MULTILINE)
+
+ expect { subject }.to raise_error(regexp)
+ end
+ end
+
+ context 'when content does not contain HTML escaped tags' do
+ let(:content) { 'See <a href="">Link</a>' }
+
+ it 'does not raise anything' do
+ expect(subject).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/support_specs/helpers/stub_method_calls_spec.rb b/spec/support_specs/helpers/stub_method_calls_spec.rb
index 837a2162bcd..7a842f83cd2 100644
--- a/spec/support_specs/helpers/stub_method_calls_spec.rb
+++ b/spec/support_specs/helpers/stub_method_calls_spec.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+
+require_relative '../../support/helpers/stub_method_calls'
RSpec.describe StubMethodCalls do
include described_class
diff --git a/spec/support_specs/matchers/event_store_spec.rb b/spec/support_specs/matchers/event_store_spec.rb
new file mode 100644
index 00000000000..3614d05fde8
--- /dev/null
+++ b/spec/support_specs/matchers/event_store_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'json_schemer'
+
+load File.expand_path('../../../spec/support/matchers/event_store.rb', __dir__)
+
+RSpec.describe 'event store matchers', :aggregate_errors do
+ let(:event_type1) do
+ Class.new(Gitlab::EventStore::Event) do
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[id]
+ }
+ end
+ end
+ end
+
+ let(:event_type2) do
+ Class.new(Gitlab::EventStore::Event) do
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[id]
+ }
+ end
+ end
+ end
+
+ before do
+ stub_const('FakeEventType1', event_type1)
+ stub_const('FakeEventType2', event_type2)
+ end
+
+ def publishing_event(event_type, data = {})
+ ::Gitlab::EventStore.publish(event_type.new(data: data))
+ end
+
+ describe 'publish_event' do
+ it 'requires a block matcher' do
+ matcher = -> { expect(:anything).to publish_event(:anything) } # rubocop: disable RSpec/ExpectActual
+
+ expect(&matcher).to raise_error(
+ ArgumentError,
+ 'publish_event matcher only supports block expectation'
+ )
+ end
+
+ it 'validates the event type' do
+ valid_event_type = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to publish_event(FakeEventType1).with('id' => 1)
+ end
+
+ expect(&valid_event_type).not_to raise_error
+
+ invalid_event_type = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to publish_event(FakeEventType2).with('id' => 1)
+ end
+
+ expect(&invalid_event_type).to raise_error <<~MESSAGE
+ expected FakeEventType2 with {"id"=>1} to be published, but only the following events were published:
+ - FakeEventType1 with {"id"=>1}
+ MESSAGE
+ end
+
+ it 'validates the event data' do
+ missing_data = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to publish_event(FakeEventType1)
+ end
+
+ expect(&missing_data).to raise_error <<~MESSAGE
+ expected FakeEventType1 with no data to be published, but only the following events were published:
+ - FakeEventType1 with {"id"=>1}
+ MESSAGE
+
+ different_data = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to publish_event(FakeEventType1).with({ 'id' => 2 })
+ end
+
+ expect(&different_data).to raise_error <<~MESSAGE
+ expected FakeEventType1 with {"id"=>2} to be published, but only the following events were published:
+ - FakeEventType1 with {"id"=>1}
+ MESSAGE
+ end
+ end
+
+ describe 'not_publish_event' do
+ it 'requires a block matcher' do
+ matcher = -> { expect(:anything).to not_publish_event(:anything) } # rubocop: disable RSpec/ExpectActual
+
+ expect(&matcher)
+ .to raise_error(ArgumentError, 'not_publish_event matcher only supports block expectation')
+ end
+
+ it 'does not permit .with' do
+ matcher = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to not_publish_event(FakeEventType2).with({ 'id' => 1 })
+ end
+
+ expect(&matcher)
+ .to raise_error(ArgumentError, 'not_publish_event does not permit .with to avoid ambiguity')
+ end
+
+ it 'validates the event type' do
+ matcher = -> do
+ expect { publishing_event(FakeEventType1, { 'id' => 1 }) }
+ .to not_publish_event(FakeEventType1)
+ end
+
+ expect(&matcher)
+ .to raise_error('expected FakeEventType1 not to be published')
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index dc112b885ae..dc74f25db87 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -4,9 +4,10 @@ require 'rake_helper'
RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { true }
- let(:backup_tasks) { %w{db repo uploads builds artifacts pages lfs terraform_state registry packages} }
+ let(:backup_restore_pid_path) { "#{Rails.application.root}/tmp/backup_restore.pid" }
+ let(:backup_tasks) { %w[db repo uploads builds artifacts pages lfs terraform_state registry packages] }
let(:backup_types) do
- %w{main_db repositories uploads builds artifacts pages lfs terraform_state registry packages}.tap do |array|
+ %w[main_db repositories uploads builds artifacts pages lfs terraform_state registry packages].tap do |array|
array.insert(1, 'ci_db') if Gitlab::Database.has_config?(:ci)
end
end
@@ -20,11 +21,19 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
def backup_files
- %w(backup_information.yml artifacts.tar.gz builds.tar.gz lfs.tar.gz terraform_state.tar.gz pages.tar.gz packages.tar.gz)
+ %w[
+ backup_information.yml
+ artifacts.tar.gz
+ builds.tar.gz
+ lfs.tar.gz
+ terraform_state.tar.gz
+ pages.tar.gz
+ packages.tar.gz
+ ]
end
def backup_directories
- %w(db repositories)
+ %w[db repositories]
end
before(:all) do
@@ -58,11 +67,88 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
end
+ describe 'lock parallel backups' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'when a process is running' do
+ let(:pid_file) { instance_double(File) }
+
+ it 'exits the new process' do
+ allow(File).to receive(:open).and_call_original
+ allow(File).to receive(:open).with(backup_restore_pid_path, any_args).and_yield(pid_file)
+ allow(pid_file).to receive(:read).and_return('123456')
+ allow(pid_file).to receive(:flock).with(any_args)
+
+ expect { run_rake_task('gitlab:backup:create') }.to raise_error(SystemExit).and output(
+ <<~HEREDOC
+ Backup and restore in progress:
+ There is a backup and restore task in progress. Please, try to run the current task once the previous one ends.
+ If there is no other process running, please remove the PID file manually: rm #{backup_restore_pid_path}
+ HEREDOC
+ ).to_stdout
+ end
+ end
+
+ context 'when no processes are running' do
+ let(:progress) { $stdout }
+ let(:pid_file) { instance_double(File, write: 12345) }
+
+ where(:tasks_name, :rake_task) do
+ %w[main_db ci_db] | 'gitlab:backup:db:restore'
+ 'repositories' | 'gitlab:backup:repo:restore'
+ 'builds' | 'gitlab:backup:builds:restore'
+ 'uploads' | 'gitlab:backup:uploads:restore'
+ 'artifacts' | 'gitlab:backup:artifacts:restore'
+ 'pages' | 'gitlab:backup:pages:restore'
+ 'lfs' | 'gitlab:backup:lfs:restore'
+ 'terraform_state' | 'gitlab:backup:terraform_state:restore'
+ 'registry' | 'gitlab:backup:registry:restore'
+ 'packages' | 'gitlab:backup:packages:restore'
+ end
+
+ with_them do
+ before do
+ allow(Kernel).to receive(:system).and_return(true)
+ allow(YAML).to receive(:load_file).and_return({ gitlab_version: Gitlab::VERSION })
+ allow(File).to receive(:delete).with(backup_restore_pid_path).and_return(1)
+ allow(File).to receive(:open).and_call_original
+ allow(File).to receive(:open).with(backup_restore_pid_path, any_args).and_yield(pid_file)
+ allow(pid_file).to receive(:read).and_return('')
+ allow(pid_file).to receive(:flock).with(any_args)
+ allow(pid_file).to receive(:write).with(12345).and_return(true)
+ allow(pid_file).to receive(:flush)
+ allow(progress).to receive(:puts).at_least(:once)
+
+ allow_next_instance_of(::Backup::Manager) do |instance|
+ Array(tasks_name).each do |task|
+ allow(instance).to receive(:run_restore_task).with(task)
+ end
+ end
+ end
+
+ it 'locks the PID file' do
+ expect(pid_file).to receive(:flock).with(File::LOCK_EX)
+ expect(pid_file).to receive(:flock).with(File::LOCK_UN)
+
+ run_rake_task(rake_task)
+ end
+
+ it 'deletes the PID file and logs a message' do
+ expect(File).to receive(:delete).with(backup_restore_pid_path)
+ expect(progress).to receive(:puts).with(/-- Deleting backup and restore lock file/)
+
+ run_rake_task(rake_task)
+ end
+ end
+ end
+ end
+
describe 'backup_restore' do
- context 'gitlab version' do
+ context 'with gitlab version' do
before do
allow(Dir).to receive(:glob).and_return(['1_gitlab_backup.tar'])
allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:exist?).with(backup_restore_pid_path).and_return(false)
allow(Kernel).to receive(:system).and_return(true)
allow(FileUtils).to receive(:cp_r).and_return(true)
allow(FileUtils).to receive(:mv).and_return(true)
@@ -72,7 +158,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:gitlab_version) { Gitlab::VERSION }
- context 'restore with matching gitlab version' do
+ context 'when restore matches gitlab version' do
before do
allow(YAML).to receive(:load_file)
.and_return({ gitlab_version: gitlab_version })
@@ -124,6 +210,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
backup_tar = Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')).last
allow(Dir).to receive(:glob).and_return([backup_tar])
allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:exist?).with(backup_restore_pid_path).and_return(false)
allow(Kernel).to receive(:system).and_return(true)
allow(FileUtils).to receive(:cp_r).and_return(true)
allow(FileUtils).to receive(:mv).and_return(true)
@@ -161,74 +248,42 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
let!(:project) { create(:project, :repository) }
- describe 'backup creation and deletion using custom_hooks' do
- let(:user_backup_path) { "repositories/#{project.disk_path}" }
-
+ context 'with specific backup tasks' do
before do
stub_env('SKIP', 'db')
- path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- File.join(project.repository.path_to_repo, 'custom_hooks')
- end
- FileUtils.mkdir_p(path)
- FileUtils.touch(File.join(path, "dummy.txt"))
end
- context 'project uses custom_hooks and successfully creates backup' do
- it 'creates custom_hooks.tar and project bundle' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
-
- tar_contents, exit_status = Gitlab::Popen.popen(%W{tar -tvf #{backup_tar}})
-
- expect(exit_status).to eq(0)
- expect(tar_contents).to match(user_backup_path)
- expect(tar_contents).to match("#{user_backup_path}/.+/001.custom_hooks.tar")
- expect(tar_contents).to match("#{user_backup_path}/.+/001.bundle")
- end
-
- it 'restores files correctly' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
-
- repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path
- end
- expect(Dir.entries(File.join(repo_path, 'custom_hooks'))).to include("dummy.txt")
+ it 'prints a progress message to stdout' do
+ backup_tasks.each do |task|
+ expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end
end
- context 'specific backup tasks' do
- it 'prints a progress message to stdout' do
- backup_tasks.each do |task|
- expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
- end
- end
-
- it 'logs the progress to log file' do
- ci_database_status = Gitlab::Database.has_config?(:ci) ? "[SKIPPED]" : "[DISABLED]"
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping main_database ... [SKIPPED]")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping ci_database ... #{ci_database_status}")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... done")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... ")
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... done")
-
- backup_tasks.each do |task|
- run_rake_task("gitlab:backup:#{task}:create")
- end
+ it 'logs the progress to log file' do
+ ci_database_status = Gitlab::Database.has_config?(:ci) ? "[SKIPPED]" : "[DISABLED]"
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping main_database ... [SKIPPED]")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping ci_database ... #{ci_database_status}")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... done")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... ")
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... done")
+
+ backup_tasks.each do |task|
+ run_rake_task("gitlab:backup:#{task}:create")
end
end
end
@@ -264,18 +319,18 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
end
- context 'tar creation' do
- context 'archive file permissions' do
+ context 'with tar creation' do
+ context 'with archive file permissions' do
it 'sets correct permissions on the tar file' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
- expect(File.exist?(backup_tar)).to be_truthy
+ expect(File).to exist(backup_tar)
expect(File::Stat.new(backup_tar).mode.to_s(8)).to eq('100600')
end
context 'with custom archive_permissions' do
before do
- allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651)
+ allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0o651)
end
it 'uses the custom permissions' do
@@ -290,11 +345,21 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz registry.tar.gz packages.tar.gz}
+ %W[
+ tar -tvf #{backup_tar}
+ db
+ uploads.tar.gz
+ repositories
+ builds.tar.gz
+ artifacts.tar.gz
+ pages.tar.gz
+ lfs.tar.gz
+ terraform_state.tar.gz
+ registry.tar.gz
+ packages.tar.gz
+ ]
)
- puts "CONTENT: #{tar_contents}"
-
expect(exit_status).to eq(0)
expect(tar_contents).to match('db')
expect(tar_contents).to match('uploads.tar.gz')
@@ -306,27 +371,31 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(tar_contents).to match('terraform_state.tar.gz')
expect(tar_contents).to match('registry.tar.gz')
expect(tar_contents).to match('packages.tar.gz')
- expect(tar_contents).not_to match(%r{^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|pages.tar.gz|artifacts.tar.gz|registry.tar.gz)/$})
+ expect(tar_contents).not_to match(%r{^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|
+ pages.tar.gz|artifacts.tar.gz|registry.tar.gz)/$})
end
it 'deletes temp directories' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
temp_dirs = Dir.glob(
- File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,pages,lfs,terraform_state,registry,packages}')
+ File.join(
+ Gitlab.config.backup.path,
+ '{db,repositories,uploads,builds,artifacts,pages,lfs,terraform_state,registry,packages}'
+ )
)
expect(temp_dirs).to be_empty
end
- context 'registry disabled' do
+ context 'when registry is disabled' do
let(:enable_registry) { false }
it 'does not create registry.tar.gz' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{backup_tar}}
+ %W[tar -tvf #{backup_tar}]
)
expect(exit_status).to eq(0)
@@ -335,7 +404,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
end
- context 'multiple repository storages' do
+ context 'with multiple repository storages' do
include StubConfiguration
let(:default_storage_name) { 'default' }
@@ -344,10 +413,10 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
before do
# We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,terraform_state,registry')
- stub_storage_settings( second_storage_name => {
- 'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
- 'path' => TestEnv::SECOND_STORAGE_PATH
- })
+ stub_storage_settings(second_storage_name => {
+ 'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
+ 'path' => TestEnv::SECOND_STORAGE_PATH
+ })
end
shared_examples 'includes repositories in all repository storages' do
@@ -368,27 +437,27 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{backup_tar} repositories}
+ %W[tar -tvf #{backup_tar} repositories]
)
tar_lines = tar_contents.lines.grep(/\.bundle/)
expect(exit_status).to eq(0)
- [
- "#{project_a.disk_path}/.+/001.bundle",
- "#{project_a.disk_path}.wiki/.+/001.bundle",
- "#{project_a.disk_path}.design/.+/001.bundle",
- "#{project_b.disk_path}/.+/001.bundle",
- "#{project_snippet_a.disk_path}/.+/001.bundle",
- "#{project_snippet_b.disk_path}/.+/001.bundle"
+ %W[
+ #{project_a.disk_path}/.+/001.bundle
+ #{project_a.disk_path}.wiki/.+/001.bundle
+ #{project_a.disk_path}.design/.+/001.bundle
+ #{project_b.disk_path}/.+/001.bundle
+ #{project_snippet_a.disk_path}/.+/001.bundle
+ #{project_snippet_b.disk_path}/.+/001.bundle
].each do |repo_name|
expect(tar_lines).to include(a_string_matching(repo_name))
end
end
end
- context 'no concurrency' do
+ context 'with no concurrency' do
it_behaves_like 'includes repositories in all repository storages'
end
@@ -400,7 +469,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
it_behaves_like 'includes repositories in all repository storages'
end
- context 'REPOSITORIES_STORAGES set' do
+ context 'when REPOSITORIES_STORAGES is set' do
before do
stub_env('REPOSITORIES_STORAGES', default_storage_name)
end
@@ -422,25 +491,25 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{backup_tar} repositories}
+ %W[tar -tvf #{backup_tar} repositories]
)
tar_lines = tar_contents.lines.grep(/\.bundle/)
expect(exit_status).to eq(0)
- [
- "#{project_a.disk_path}/.+/001.bundle",
- "#{project_a.disk_path}.wiki/.+/001.bundle",
- "#{project_a.disk_path}.design/.+/001.bundle",
- "#{project_snippet_a.disk_path}/.+/001.bundle"
+ %W[
+ #{project_a.disk_path}/.+/001.bundle
+ #{project_a.disk_path}.wiki/.+/001.bundle
+ #{project_a.disk_path}.design/.+/001.bundle
+ #{project_snippet_a.disk_path}/.+/001.bundle
].each do |repo_name|
expect(tar_lines).to include(a_string_matching(repo_name))
end
- [
- "#{project_b.disk_path}/.+/001.bundle",
- "#{project_snippet_b.disk_path}/.+/001.bundle"
+ %W[
+ #{project_b.disk_path}/.+/001.bundle
+ #{project_snippet_b.disk_path}/.+/001.bundle
].each do |repo_name|
expect(tar_lines).not_to include(a_string_matching(repo_name))
end
@@ -448,7 +517,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
end
- context 'concurrency settings' do
+ context 'with concurrency settings' do
before do
# We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,terraform_state,registry')
@@ -463,13 +532,18 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(::Backup::Repositories).to receive(:new)
.with(anything, strategy: anything, storages: [], paths: [])
.and_call_original
- expect(::Backup::GitalyBackup).to receive(:new).with(anything, max_parallelism: 5, storage_parallelism: 2, incremental: false).and_call_original
+ expect(::Backup::GitalyBackup).to receive(:new).with(
+ anything,
+ max_parallelism: 5,
+ storage_parallelism: 2,
+ incremental: false
+ ).and_call_original
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
end
end
- context 'CRON env is set' do
+ context 'when CRON env is set' do
before do
stub_env('CRON', '1')
end
@@ -481,7 +555,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
# backup_create task
- describe "Skipping items in a backup" do
+ describe "skipping items in a backup" do
before do
stub_env('SKIP', 'an-unknown-type,repositories,uploads,anotherunknowntype')
@@ -492,7 +566,19 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, _exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz registry.tar.gz packages.tar.gz}
+ %W[
+ tar -tvf #{backup_tar}
+ db
+ uploads.tar.gz
+ repositories
+ builds.tar.gz
+ artifacts.tar.gz
+ pages.tar.gz
+ lfs.tar.gz
+ terraform_state.tar.gz
+ registry.tar.gz
+ packages.tar.gz
+ ]
)
expect(tar_contents).to match('db/')
@@ -515,7 +601,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.to receive(:invoke).and_return(true)
expect_next_instance_of(::Backup::Manager) do |instance|
- (backup_types - %w{repositories uploads}).each do |subtask|
+ (backup_types - %w[repositories uploads]).each do |subtask|
expect(instance).to receive(:run_restore_task).with(subtask).ordered
end
expect(instance).not_to receive(:run_restore_task)
diff --git a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
index d03e15224cb..ebea644bbf0 100644
--- a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
+++ b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
@@ -89,6 +89,26 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
end
end
+ context 'when running in dry_run mode' do
+ before do
+ stub_env('DRY_RUN', 'true')
+ end
+
+ it 'allows writes on the main tables on the ci database' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ ci_connection.execute("delete from projects")
+ end.not_to raise_error
+ end
+
+ it 'allows writes on the ci tables on the main database' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ main_connection.execute("delete from ci_builds")
+ end.not_to raise_error
+ end
+ end
+
context 'multiple shared databases' do
before do
allow(::Gitlab::Database).to receive(:db_config_share_with).and_return(nil)
diff --git a/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb b/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb
index f9ebb985255..e95c2e241a8 100644
--- a/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb
+++ b/spec/tasks/gitlab/db/truncate_legacy_tables_rake_spec.rb
@@ -43,10 +43,6 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
end
shared_examples 'truncating legacy tables' do
- before do
- allow(ENV).to receive(:[]).and_return(nil)
- end
-
context 'when tables are not locked for writes' do
it 'raises an error when trying to truncate the tables' do
error_message = /is not locked for writes. Run the rake task gitlab:db:lock_writes first/
@@ -97,7 +93,7 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
context 'when running in dry_run mode' do
before do
- allow(ENV).to receive(:[]).with("DRY_RUN").and_return("true")
+ stub_env('DRY_RUN', 'true')
end
it 'does not truncate any tables' do
@@ -115,7 +111,7 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
context 'when passing until_table parameter via environment variable' do
before do
- allow(ENV).to receive(:[]).with("UNTIL_TABLE").and_return(legacy_table)
+ stub_env('UNTIL_TABLE', legacy_table)
end
it 'sends the table name to TablesTruncate' do
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 8f8178cde4d..08bec9fda78 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -665,21 +665,15 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
describe '#migrate_with_instrumentation' do
- describe '#up' do
- subject { run_rake_task('gitlab:db:migration_testing:up') }
-
- it 'delegates to the migration runner' do
- expect(::Gitlab::Database::Migrations::Runner).to receive_message_chain(:up, :run)
+ let(:runner) { instance_double(::Gitlab::Database::Migrations::Runner) }
- subject
- end
- end
-
- describe '#down' do
- subject { run_rake_task('gitlab:db:migration_testing:down') }
+ describe '#up (legacy mode)' do
+ subject { run_rake_task('gitlab:db:migration_testing:up') }
- it 'delegates to the migration runner' do
- expect(::Gitlab::Database::Migrations::Runner).to receive_message_chain(:down, :run)
+ it 'delegates to the migration runner in legacy mode' do
+ expect(::Gitlab::Database::Migrations::Runner).to receive(:up).with(database: 'main', legacy_mode: true)
+ .and_return(runner)
+ expect(runner).to receive(:run)
subject
end
@@ -699,31 +693,51 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
end
- describe '#sample_batched_background_migrations' do
- let(:batched_runner) { instance_double(::Gitlab::Database::Migrations::TestBatchedBackgroundRunner) }
+ where(:db) do
+ Gitlab::Database::DATABASE_NAMES.map(&:to_sym)
+ end
+
+ with_them do
+ describe '#up' do
+ subject { run_rake_task("gitlab:db:migration_testing:up:#{db}") }
- it 'delegates to the migration runner for the main database with a default sample duration' do
- expect(::Gitlab::Database::Migrations::Runner).to receive(:batched_background_migrations)
- .with(for_database: 'main').and_return(batched_runner)
- expect(batched_runner).to receive(:run_jobs).with(for_duration: 30.minutes)
+ it 'delegates to the migration runner' do
+ expect(::Gitlab::Database::Migrations::Runner).to receive(:up).with(database: db).and_return(runner)
+ expect(runner).to receive(:run)
- run_rake_task('gitlab:db:migration_testing:sample_batched_background_migrations')
+ subject
+ end
end
- it 'delegates to the migration runner for a specified database with a default sample duration' do
- expect(::Gitlab::Database::Migrations::Runner).to receive(:batched_background_migrations)
- .with(for_database: 'ci').and_return(batched_runner)
- expect(batched_runner).to receive(:run_jobs).with(for_duration: 30.minutes)
+ describe '#down' do
+ subject { run_rake_task("gitlab:db:migration_testing:down:#{db}") }
+
+ it 'delegates to the migration runner' do
+ expect(::Gitlab::Database::Migrations::Runner).to receive(:down).with(database: db).and_return(runner)
+ expect(runner).to receive(:run)
- run_rake_task('gitlab:db:migration_testing:sample_batched_background_migrations', '[ci]')
+ subject
+ end
end
- it 'delegates to the migration runner for a specified database and sample duration' do
- expect(::Gitlab::Database::Migrations::Runner).to receive(:batched_background_migrations)
- .with(for_database: 'ci').and_return(batched_runner)
- expect(batched_runner).to receive(:run_jobs).with(for_duration: 100.seconds)
+ describe '#sample_batched_background_migrations' do
+ let(:batched_runner) { instance_double(::Gitlab::Database::Migrations::TestBatchedBackgroundRunner) }
+
+ it 'delegates to the migration runner for a specified database with a default sample duration' do
+ expect(::Gitlab::Database::Migrations::Runner).to receive(:batched_background_migrations)
+ .with(for_database: db).and_return(batched_runner)
+ expect(batched_runner).to receive(:run_jobs).with(for_duration: 30.minutes)
- run_rake_task('gitlab:db:migration_testing:sample_batched_background_migrations', '[ci, 100]')
+ run_rake_task("gitlab:db:migration_testing:sample_batched_background_migrations:#{db}")
+ end
+
+ it 'delegates to the migration runner for a specified database and sample duration' do
+ expect(::Gitlab::Database::Migrations::Runner).to receive(:batched_background_migrations)
+ .with(for_database: db).and_return(batched_runner)
+ expect(batched_runner).to receive(:run_jobs).with(for_duration: 100.seconds)
+
+ run_rake_task("gitlab:db:migration_testing:sample_batched_background_migrations:#{db}", '[100]')
+ end
end
end
end
diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb
index f54d06f406f..7ddba4ceb9b 100644
--- a/spec/tasks/gitlab/usage_data_rake_spec.rb
+++ b/spec/tasks/gitlab/usage_data_rake_spec.rb
@@ -69,6 +69,15 @@ RSpec.describe 'gitlab:usage data take tasks', :silence_stdout do
expect { run_rake_task('gitlab:usage_data:generate_and_send') }.to output(/.*201.*/).to_stdout
end
+ describe 'generate_ci_template_events' do
+ it "generates #{Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH}" do
+ FileUtils.rm_rf(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH)
+ run_rake_task('gitlab:usage_data:generate_ci_template_events')
+
+ expect(File.exist?(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH)).to be true
+ end
+ end
+
private
def stub_response(url: service_ping_payload_url, body:, status: 201)
diff --git a/spec/tooling/danger/config_files_spec.rb b/spec/tooling/danger/config_files_spec.rb
index 0e01908a1dd..88b327df63f 100644
--- a/spec/tooling/danger/config_files_spec.rb
+++ b/spec/tooling/danger/config_files_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Tooling::Danger::ConfigFiles do
let(:file_lines) do
[
"---",
- "name: about_your_company_registration_flow",
+ "name: about_some_new_flow",
"introduced_by_url: #{url}",
"rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355909",
"milestone: '14.10'"
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index 4cc5df385a5..6793a4b8de3 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -98,10 +98,11 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'vendor/languages.yml' | [:backend]
'file_hooks/examples/' | [:backend]
- 'Gemfile' | [:backend]
- 'Gemfile.lock' | [:backend]
- 'Rakefile' | [:backend]
- 'FOO_VERSION' | [:backend]
+ 'Gemfile' | [:backend]
+ 'Gemfile.lock' | [:backend]
+ 'Gemfile.checksum' | [:backend]
+ 'Rakefile' | [:backend]
+ 'FOO_VERSION' | [:backend]
'scripts/glfm/bar.rb' | [:backend]
'scripts/glfm/bar.js' | [:frontend]
diff --git a/spec/tooling/danger/specs_spec.rb b/spec/tooling/danger/specs_spec.rb
index 6c1fbbb903d..d6aed86e7dc 100644
--- a/spec/tooling/danger/specs_spec.rb
+++ b/spec/tooling/danger/specs_spec.rb
@@ -13,7 +13,9 @@ RSpec.describe Tooling::Danger::Specs do
include_context "with dangerfile"
let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
- let(:fake_project_helper) { double('fake-project-helper', helper: fake_helper).tap { |h| h.class.include(Tooling::Danger::ProjectHelper) } }
+ let(:fake_project_helper) { instance_double('Tooling::Danger::ProjectHelper') }
+ let(:filename) { 'spec/foo_spec.rb' }
+
let(:file_lines) do
[
" describe 'foo' do",
@@ -32,6 +34,7 @@ RSpec.describe Tooling::Danger::Specs do
let(:matching_lines) do
[
+ "+ expect(foo).to match(['should not error'])",
"+ expect(foo).to match(['bar'])",
"+ expect(foo).to match(['bar'])",
"+ expect(foo).to match ['bar']",
@@ -42,31 +45,28 @@ RSpec.describe Tooling::Danger::Specs do
]
end
+ let(:changed_lines) do
+ [
+ " expect(foo).to match(['bar'])",
+ " expect(foo).to match(['bar'])",
+ " expect(foo).to match ['bar']",
+ " expect(foo).to eq(['bar'])",
+ " expect(foo).to eq ['bar']",
+ "- expect(foo).to match(['bar'])",
+ "- expect(foo).to match(['bar'])",
+ "- expect(foo).to match ['bar']",
+ "- expect(foo).to eq(['bar'])",
+ "- expect(foo).to eq ['bar']",
+ "+ expect(foo).to eq([])"
+ ] + matching_lines
+ end
+
subject(:specs) { fake_danger.new(helper: fake_helper) }
before do
allow(specs).to receive(:project_helper).and_return(fake_project_helper)
- end
-
- describe '#add_suggestions_for_match_with_array' do
- let(:filename) { 'spec/foo_spec.rb' }
-
- before do
- expect(specs).to receive(:added_line_matching_match_with_array).and_return(matching_lines)
- allow(specs.project_helper).to receive(:file_lines).and_return(file_lines)
- end
-
- it 'adds suggestions at the correct lines' do
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to match_array(['bar'])"), file: filename, line: 2)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to match_array(['bar'])"), file: filename, line: 4)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to match_array ['bar']"), file: filename, line: 6)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to match_array(['bar'])"), file: filename, line: 7)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to match_array ['bar']"), file: filename, line: 8)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to(match_array(['bar']))"), file: filename, line: 9)
- expect(specs).to receive(:markdown).with(format(described_class::SUGGEST_MR_COMMENT, suggested_line: " expect(foo).to(match_array(['bar']))"), file: filename, line: 10)
-
- specs.add_suggestions_for_match_with_array(filename)
- end
+ allow(specs.helper).to receive(:changed_lines).with(filename).and_return(matching_lines)
+ allow(specs.project_helper).to receive(:file_lines).and_return(file_lines)
end
describe '#changed_specs_files' do
@@ -105,30 +105,116 @@ RSpec.describe Tooling::Danger::Specs do
end
end
- describe '#added_line_matching_match_with_array' do
- let(:filename) { 'spec/foo_spec.rb' }
+ describe '#add_suggestions_for_match_with_array' do
+ let(:template) do
+ <<~MARKDOWN
+ ```suggestion
+ %<suggested_line>s
+ ```
+
+ If order of the result is not important, please consider using `match_array` to avoid flakiness.
+ MARKDOWN
+ end
+
+ it 'adds suggestions at the correct lines' do
+ [
+ { suggested_line: " expect(foo).to match_array(['bar'])", number: 2 },
+ { suggested_line: " expect(foo).to match_array(['bar'])", number: 4 },
+ { suggested_line: " expect(foo).to match_array ['bar']", number: 6 },
+ { suggested_line: " expect(foo).to match_array(['bar'])", number: 7 },
+ { suggested_line: " expect(foo).to match_array ['bar']", number: 8 },
+ { suggested_line: " expect(foo).to(match_array(['bar']))", number: 9 },
+ { suggested_line: " expect(foo).to(match_array(['bar']))", number: 10 }
+ ].each do |test_case|
+ comment = format(template, suggested_line: test_case[:suggested_line])
+ expect(specs).to receive(:markdown).with(comment, file: filename, line: test_case[:number])
+ end
+
+ specs.add_suggestions_for_match_with_array(filename)
+ end
+ end
+
+ describe '#add_suggestions_for_project_factory_usage' do
+ let(:template) do
+ <<~MARKDOWN
+ ```suggestion
+ %<suggested_line>s
+ ```
+
+ Project creations are very slow. Use `let_it_be`, `build` or `build_stubbed` if possible.
+ See [testing best practices](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#optimize-factory-usage)
+ for background information and alternative options.
+ MARKDOWN
+ end
+
+ let(:file_lines) do
+ [
+ " let(:project) { create(:project) }",
+ " let_it_be(:project) { create(:project, :repository)",
+ " let!(:project) { create(:project) }",
+ " let(:var) { create(:project) }",
+ " let(:merge_request) { create(:merge_request, project: project)",
+ " context 'when merge request exists' do",
+ " it { is_expected.to be_success }",
+ " end",
+ " let!(:var) { create(:project) }",
+ " let(:project) { create(:thing) }",
+ " let(:project) { build(:project) }",
+ " let(:project) do",
+ " create(:project)",
+ " end",
+ " let(:project) { create(:project, :repository) }",
+ " str = 'let(:project) { create(:project) }'",
+ " let(:project) { create(:project_empty_repo) }",
+ " let(:project) { create(:forked_project_with_submodules) }",
+ " let(:project) { create(:project_with_design) }",
+ " let(:authorization) { create(:project_authorization) }"
+ ]
+ end
+
+ let(:matching_lines) do
+ [
+ "+ let(:should_not_error) { create(:project) }",
+ "+ let(:project) { create(:project) }",
+ "+ let!(:project) { create(:project) }",
+ "+ let(:var) { create(:project) }",
+ "+ let!(:var) { create(:project) }",
+ "+ let(:project) { create(:project, :repository) }",
+ "+ let(:project) { create(:project_empty_repo) }",
+ "+ let(:project) { create(:forked_project_with_submodules) }",
+ "+ let(:project) { create(:project_with_design) }"
+ ]
+ end
+
let(:changed_lines) do
[
- " expect(foo).to match(['bar'])",
- " expect(foo).to match(['bar'])",
- " expect(foo).to match ['bar']",
- " expect(foo).to eq(['bar'])",
- " expect(foo).to eq ['bar']",
- "- expect(foo).to match(['bar'])",
- "- expect(foo).to match(['bar'])",
- "- expect(foo).to match ['bar']",
- "- expect(foo).to eq(['bar'])",
- "- expect(foo).to eq ['bar']",
- "+ expect(foo).to eq([])"
+ "+ line which doesn't exist in the file and should not cause an error",
+ "+ let_it_be(:project) { create(:project, :repository)",
+ "+ let(:project) { create(:thing) }",
+ "+ let(:project) do",
+ "+ create(:project)",
+ "+ end",
+ "+ str = 'let(:project) { create(:project) }'",
+ "+ let(:authorization) { create(:project_authorization) }"
] + matching_lines
end
- before do
- allow(specs.helper).to receive(:changed_lines).with(filename).and_return(changed_lines)
- end
+ it 'adds suggestions at the correct lines', :aggregate_failures do
+ [
+ { suggested_line: " let_it_be(:project) { create(:project) }", number: 1 },
+ { suggested_line: " let_it_be(:project) { create(:project) }", number: 3 },
+ { suggested_line: " let_it_be(:var) { create(:project) }", number: 4 },
+ { suggested_line: " let_it_be(:var) { create(:project) }", number: 9 },
+ { suggested_line: " let_it_be(:project) { create(:project, :repository) }", number: 15 },
+ { suggested_line: " let_it_be(:project) { create(:project_empty_repo) }", number: 17 },
+ { suggested_line: " let_it_be(:project) { create(:forked_project_with_submodules) }", number: 18 },
+ { suggested_line: " let_it_be(:project) { create(:project_with_design) }", number: 19 }
+ ].each do |test_case|
+ comment = format(template, suggested_line: test_case[:suggested_line])
+ expect(specs).to receive(:markdown).with(comment, file: filename, line: test_case[:number])
+ end
- it 'returns all lines using an array equality matcher' do
- expect(specs.added_line_matching_match_with_array(filename)).to match_array(matching_lines)
+ specs.add_suggestions_for_project_factory_usage(filename)
end
end
end
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
index f4eea28b66f..6084dc194da 100644
--- a/spec/tooling/quality/test_level_spec.rb
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
require_relative '../../../tooling/quality/test_level'
diff --git a/spec/uploaders/job_artifact_uploader_spec.rb b/spec/uploaders/job_artifact_uploader_spec.rb
index 9ccf216d1fc..a7fd040837f 100644
--- a/spec/uploaders/job_artifact_uploader_spec.rb
+++ b/spec/uploaders/job_artifact_uploader_spec.rb
@@ -23,6 +23,14 @@ RSpec.describe JobArtifactUploader do
it_behaves_like "builds correct paths",
store_dir: %r[\h{2}/\h{2}/\h{64}/\d{4}_\d{1,2}_\d{1,2}/\d+/\d+\z]
+
+ describe '#cdn_enabled_url' do
+ it 'returns URL and false' do
+ result = uploader.cdn_enabled_url(nil, '127.0.0.1')
+
+ expect(result.used_cdn).to be false
+ end
+ end
end
context 'file is stored in valid local_path' do
diff --git a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
index b72f6d66d69..8e209dabddc 100644
--- a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
+++ b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
@@ -30,6 +30,8 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
'2600:1900:4180:0000:0000:0000:0000:0000' | false
'10.10.1.5' | false
'fc00:0000:0000:0000:0000:0000:0000:0000' | false
+ '127.0.0.1' | false
+ '169.254.0.0' | false
end
with_them do
@@ -68,6 +70,26 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
expect(subject.use_cdn?(public_ip)).to be false
end
end
+
+ context 'when URL is a domain' do
+ before do
+ options[:url] = 'cdn.gitlab.example.com'
+ end
+
+ it 'returns false' do
+ expect(subject.use_cdn?(public_ip)).to be false
+ end
+ end
+
+ context 'when URL uses HTTP' do
+ before do
+ options[:url] = 'http://cdn.gitlab.example.com'
+ end
+
+ it 'returns false' do
+ expect(subject.use_cdn?(public_ip)).to be false
+ end
+ end
end
describe '#signed_url' do
diff --git a/spec/uploaders/object_storage/cdn_spec.rb b/spec/uploaders/object_storage/cdn_spec.rb
index 246cb1bf349..f99450b274f 100644
--- a/spec/uploaders/object_storage/cdn_spec.rb
+++ b/spec/uploaders/object_storage/cdn_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe ObjectStorage::CDN do
'provider' => 'google',
'url' => 'https://gitlab.example.com',
'key_name' => 'test-key',
- 'key' => '12345'
+ 'key' => Base64.urlsafe_encode64('12345')
}
}
}.freeze
@@ -31,21 +31,49 @@ RSpec.describe ObjectStorage::CDN do
end
let(:object) { build_stubbed(:user) }
+ let(:public_ip) { '18.245.0.1' }
+
+ let_it_be(:project) { build(:project) }
subject { uploader_class.new(object, :file) }
context 'with CDN config' do
before do
+ stub_artifacts_object_storage(enabled: true)
uploader_class.options = Settingslogic.new(Gitlab.config.uploads.deep_merge(cdn_options))
end
- describe '#use_cdn?' do
- it 'returns true' do
- expect_next_instance_of(ObjectStorage::CDN::GoogleCDN) do |cdn|
- expect(cdn).to receive(:use_cdn?).and_return(true)
+ describe '#cdn_enabled_url' do
+ context 'with ci_job_artifacts_cdn feature flag disabled' do
+ before do
+ stub_feature_flags(ci_job_artifacts_cdn: false)
end
- expect(subject.use_cdn?('18.245.0.1')).to be true
+ it 'calls #url' do
+ expect(subject).to receive(:url).and_call_original
+ expect(subject).not_to receive(:cdn_signed_url)
+
+ result = subject.cdn_enabled_url(project, public_ip)
+
+ expect(result.used_cdn).to be false
+ end
+ end
+
+ context 'with ci_job_artifacts_cdn feature flag enabled' do
+ it 'calls #cdn_signed_url' do
+ expect(subject).not_to receive(:url)
+ expect(subject).to receive(:cdn_signed_url).and_call_original
+
+ result = subject.cdn_enabled_url(project, public_ip)
+
+ expect(result.used_cdn).to be true
+ end
+ end
+ end
+
+ describe '#use_cdn?' do
+ it 'returns true' do
+ expect(subject.use_cdn?(public_ip)).to be true
end
end
@@ -67,7 +95,7 @@ RSpec.describe ObjectStorage::CDN do
describe '#use_cdn?' do
it 'returns false' do
- expect(subject.use_cdn?('18.245.0.1')).to be false
+ expect(subject.use_cdn?(public_ip)).to be false
end
end
end
@@ -79,7 +107,7 @@ RSpec.describe ObjectStorage::CDN do
end
it 'raises an error' do
- expect { subject.use_cdn?('18.245.0.1') }.to raise_error("Unknown CDN provider: amazon")
+ expect { subject.use_cdn?(public_ip) }.to raise_error("Unknown CDN provider: amazon")
end
end
end
diff --git a/spec/uploaders/packages/rpm/repository_file_uploader_spec.rb b/spec/uploaders/packages/rpm/repository_file_uploader_spec.rb
new file mode 100644
index 00000000000..720e109533b
--- /dev/null
+++ b/spec/uploaders/packages/rpm/repository_file_uploader_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rpm::RepositoryFileUploader do
+ let_it_be(:repository_file) { create(:rpm_repository_file) }
+ let(:uploader) { described_class.new(repository_file, :file) }
+ let(:path) { Gitlab.config.packages.storage_path }
+
+ subject { uploader }
+
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/projects/\d+/rpm/repository_files/\d+$],
+ cache_dir: %r{/packages/tmp/cache},
+ work_dir: %r{/packages/tmp/work}
+
+ context 'when object store is remote' do
+ before do
+ stub_rpm_repository_file_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/projects/\d+/rpm/repository_files/\d+$]
+ end
+
+ describe 'remote file' do
+ let(:repository_file) { create(:rpm_repository_file, :object_storage) }
+
+ context 'with object storage enabled' do
+ before do
+ stub_rpm_repository_file_object_storage
+ end
+
+ it 'can store file remotely' do
+ allow(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async)
+
+ repository_file
+
+ expect(repository_file.file_store).to eq(described_class::Store::REMOTE)
+ expect(repository_file.file.path).not_to be_blank
+ end
+ end
+ end
+end
diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
index 18a2e29adab..cb41f2e636e 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
@@ -47,7 +47,7 @@ RSpec.describe 'admin/application_settings/_package_registry' do
it 'does not display the plan name when there is only one plan' do
subject
- expect(page).not_to have_content('Default')
+ expect(page).not_to have_selector('a[data-action="plan0"]')
end
end
diff --git a/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb b/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb
index 4d40bf5671e..e4ebdd706d4 100644
--- a/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb
+++ b/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb
@@ -15,42 +15,17 @@ RSpec.describe 'admin/application_settings/ci_cd.html.haml' do
end
describe 'CI CD Runner Registration' do
- context 'when feature flag is enabled' do
- before do
- stub_feature_flags(runner_registration_control: true)
- end
+ it 'has the setting section' do
+ render
- it 'has the setting section' do
- render
-
- expect(rendered).to have_css("#js-runner-settings")
- end
-
- it 'renders the correct setting section content' do
- render
-
- expect(rendered).to have_content("Runner registration")
- expect(rendered).to have_content("If no options are selected, only administrators can register runners.")
- end
+ expect(rendered).to have_css("#js-runner-settings")
end
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(runner_registration_control: false)
- end
-
- it 'does not have the setting section' do
- render
-
- expect(rendered).not_to have_css("#js-runner-settings")
- end
-
- it 'does not render the correct setting section content' do
- render
+ it 'renders the correct setting section content' do
+ render
- expect(rendered).not_to have_content("Runner registration")
- expect(rendered).not_to have_content("If no options are selected, only administrators can register runners.")
- end
+ expect(rendered).to have_content("Runner registration")
+ expect(rendered).to have_content("If no options are selected, only administrators can register runners.")
end
end
end
diff --git a/spec/views/admin/broadcast_messages/index.html.haml_spec.rb b/spec/views/admin/broadcast_messages/index.html.haml_spec.rb
index e1dc76428df..ba998085bf9 100644
--- a/spec/views/admin/broadcast_messages/index.html.haml_spec.rb
+++ b/spec/views/admin/broadcast_messages/index.html.haml_spec.rb
@@ -3,20 +3,22 @@
require 'spec_helper'
RSpec.describe 'admin/broadcast_messages/index' do
- describe 'Target roles select and table column' do
- let(:feature_flag_state) { true }
+ let(:role_targeted_broadcast_messages) { true }
+ let(:vue_broadcast_messages) { false }
- let_it_be(:message) { create(:broadcast_message, broadcast_type: 'banner', target_access_levels: [Gitlab::Access::GUEST, Gitlab::Access::DEVELOPER]) }
+ let_it_be(:message) { create(:broadcast_message, broadcast_type: 'banner', target_access_levels: [Gitlab::Access::GUEST, Gitlab::Access::DEVELOPER]) }
- before do
- assign(:broadcast_messages, BroadcastMessage.page(1))
- assign(:broadcast_message, BroadcastMessage.new)
+ before do
+ assign(:broadcast_messages, BroadcastMessage.page(1))
+ assign(:broadcast_message, BroadcastMessage.new)
- stub_feature_flags(role_targeted_broadcast_messages: feature_flag_state)
+ stub_feature_flags(role_targeted_broadcast_messages: role_targeted_broadcast_messages)
+ stub_feature_flags(vue_broadcast_messages: vue_broadcast_messages)
- render
- end
+ render
+ end
+ describe 'Target roles select and table column' do
it 'rendered' do
expect(rendered).to have_content('Target roles')
expect(rendered).to have_content('Owner')
@@ -24,7 +26,7 @@ RSpec.describe 'admin/broadcast_messages/index' do
end
context 'when feature flag is off' do
- let(:feature_flag_state) { false }
+ let(:role_targeted_broadcast_messages) { false }
it 'is not rendered' do
expect(rendered).not_to have_content('Target roles')
@@ -33,4 +35,18 @@ RSpec.describe 'admin/broadcast_messages/index' do
end
end
end
+
+ describe 'Vue application' do
+ it 'is not rendered' do
+ expect(rendered).not_to have_selector('#js-broadcast-messages')
+ end
+
+ context 'when feature flag is on' do
+ let(:vue_broadcast_messages) { true }
+
+ it 'is rendered' do
+ expect(rendered).to have_selector('#js-broadcast-messages')
+ end
+ end
+ end
end
diff --git a/spec/views/events/event/_common.html.haml_spec.rb b/spec/views/events/event/_common.html.haml_spec.rb
index 0de84e2fdb8..ad8e5c2ef77 100644
--- a/spec/views/events/event/_common.html.haml_spec.rb
+++ b/spec/views/events/event/_common.html.haml_spec.rb
@@ -7,33 +7,41 @@ RSpec.describe 'events/event/_common.html.haml' do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
+ before do
+ render partial: 'events/event/common', locals: { event: event.present }
+ end
+
context 'when it is a work item event' do
- let(:work_item) { create(:work_item, project: project) }
+ let_it_be(:work_item) { create(:work_item, :task, project: project) }
- let(:event) do
+ let_it_be(:event) do
create(:event, :created, project: project, target: work_item, target_type: 'WorkItem', author: user)
end
it 'renders the correct url' do
- render partial: 'events/event/common', locals: { event: event.present }
-
expect(rendered).to have_link(
work_item.reference_link_text, href: "/#{project.full_path}/-/work_items/#{work_item.id}"
)
end
+
+ it 'uses issue_type for the target_name' do
+ expect(rendered).to have_content("#{s_('Event|opened')} task #{work_item.to_reference}")
+ end
end
- context 'when it is an isssue event' do
- let(:issue) { create(:issue, project: project) }
+ context 'when it is an issue event' do
+ let_it_be(:issue) { create(:issue, project: project) }
- let(:event) do
+ let_it_be(:event) do
create(:event, :created, project: project, target: issue, author: user)
end
it 'renders the correct url' do
- render partial: 'events/event/common', locals: { event: event.present }
-
expect(rendered).to have_link(issue.reference_link_text, href: "/#{project.full_path}/-/issues/#{issue.iid}")
end
+
+ it 'uses issue_type for the target_name' do
+ expect(rendered).to have_content("#{s_('Event|opened')} issue #{issue.to_reference}")
+ end
end
end
diff --git a/spec/views/groups/new.html.haml_spec.rb b/spec/views/groups/new.html.haml_spec.rb
index 5c7378e8dc7..0bbc4c1d717 100644
--- a/spec/views/groups/new.html.haml_spec.rb
+++ b/spec/views/groups/new.html.haml_spec.rb
@@ -36,4 +36,11 @@ RSpec.describe 'groups/new.html.haml' do
expect(rendered).to have_field('Public')
end
end
+
+ describe 'role field' do
+ it 'does have a default selection' do
+ expect(rendered).to have_content('Role')
+ expect(rendered).to have_select('Role', selected: 'Software Developer')
+ end
+ end
end
diff --git a/spec/views/layouts/_flash.html.haml_spec.rb b/spec/views/layouts/_flash.html.haml_spec.rb
index a4bed09368f..d88977b194a 100644
--- a/spec/views/layouts/_flash.html.haml_spec.rb
+++ b/spec/views/layouts/_flash.html.haml_spec.rb
@@ -3,9 +3,20 @@
require 'spec_helper'
RSpec.describe 'layouts/_flash' do
+ let_it_be(:template) { 'layouts/_flash' }
+ let_it_be(:flash_container_no_margin_class) { 'flash-container-no-margin' }
+
+ let(:locals) { {} }
+
before do
allow(view).to receive(:flash).and_return(flash)
- render
+ render(template: template, locals: locals)
+ end
+
+ describe 'default' do
+ it 'does not render flash container no margin class' do
+ expect(rendered).not_to have_selector(".#{flash_container_no_margin_class}")
+ end
end
describe 'closable flash messages' do
@@ -17,7 +28,7 @@ RSpec.describe 'layouts/_flash' do
let(:flash) { { flash_type => 'This is a closable flash message' } }
it 'shows a close button' do
- expect(rendered).to include('js-close-icon')
+ expect(rendered).to include('js-close')
end
end
end
@@ -31,8 +42,16 @@ RSpec.describe 'layouts/_flash' do
let(:flash) { { flash_type => 'This is a non closable flash message' } }
it 'does not show a close button' do
- expect(rendered).not_to include('js-close-icon')
+ expect(rendered).not_to include('js-close')
end
end
end
+
+ describe 'with flash_class in locals' do
+ let(:locals) { { flash_container_no_margin: true } }
+
+ it 'adds class to flash-container' do
+ expect(rendered).to have_selector(".flash-container.#{flash_container_no_margin_class}")
+ end
+ end
end
diff --git a/spec/views/layouts/fullscreen.html.haml_spec.rb b/spec/views/layouts/fullscreen.html.haml_spec.rb
index 14b382bc238..7b345fea2ad 100644
--- a/spec/views/layouts/fullscreen.html.haml_spec.rb
+++ b/spec/views/layouts/fullscreen.html.haml_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe 'layouts/fullscreen' do
+ let_it_be(:template) { 'layouts/fullscreen' }
+ let_it_be(:top_nav_partial) { 'layouts/header/_default' }
+ let_it_be(:top_nav_responsive_partial) { 'layouts/nav/_top_nav_responsive' }
+
let_it_be(:user) { create(:user) }
before do
@@ -16,6 +20,20 @@ RSpec.describe 'layouts/fullscreen' do
expect(rendered).to have_selector(".gl--flex-full.gl-w-full")
end
+ it 'renders flash container' do
+ render
+
+ expect(view).to render_template("layouts/_flash")
+ expect(rendered).to have_selector(".flash-container.flash-container-no-margin")
+ end
+
+ it 'renders top nav' do
+ render
+
+ expect(view).to render_template(top_nav_partial)
+ expect(view).to render_template(top_nav_responsive_partial)
+ end
+
it_behaves_like 'a layout which reflects the application theme setting'
describe 'sidebar' do
@@ -51,4 +69,15 @@ RSpec.describe 'layouts/fullscreen' do
end
end
end
+
+ context 'when minimal is set' do
+ subject { render(template: template, formats: :html, locals: { minimal: true }) }
+
+ it 'does not render top nav' do
+ subject
+
+ expect(view).not_to render_template(top_nav_partial)
+ expect(view).not_to render_template(top_nav_responsive_partial)
+ end
+ end
end
diff --git a/spec/views/layouts/header/_gitlab_version.html.haml_spec.rb b/spec/views/layouts/header/_gitlab_version.html.haml_spec.rb
index 0e24810f835..2f423c72ca6 100644
--- a/spec/views/layouts/header/_gitlab_version.html.haml_spec.rb
+++ b/spec/views/layouts/header/_gitlab_version.html.haml_spec.rb
@@ -12,5 +12,11 @@ RSpec.describe 'layouts/header/_gitlab_version' do
it 'renders the version check badge' do
expect(rendered).to have_selector('.js-gitlab-version-check')
end
+
+ it 'renders the container as a link' do
+ expect(rendered).to have_selector(
+ 'a[data-testid="gitlab-version-container"][href="/help/update/index"]'
+ )
+ end
end
end
diff --git a/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
index 3d28be68b25..f5a0a7a935c 100644
--- a/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
@@ -11,4 +11,20 @@ RSpec.describe 'layouts/nav/sidebar/_profile' do
it_behaves_like 'has nav sidebar'
it_behaves_like 'sidebar includes snowplow attributes', 'render', 'user_side_navigation', 'user_side_navigation'
+
+ it 'has a link to access tokens' do
+ render
+
+ expect(rendered).to have_link(_('Access Tokens'), href: profile_personal_access_tokens_path)
+ end
+
+ context 'when personal access tokens are disabled' do
+ it 'does not have a link to access tokens' do
+ allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
+
+ render
+
+ expect(rendered).not_to have_link(_('Access Tokens'), href: profile_personal_access_tokens_path)
+ end
+ end
end
diff --git a/spec/views/projects/hooks/edit.html.haml_spec.rb b/spec/views/projects/hooks/edit.html.haml_spec.rb
index c4ec2149794..2a95656645e 100644
--- a/spec/views/projects/hooks/edit.html.haml_spec.rb
+++ b/spec/views/projects/hooks/edit.html.haml_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'projects/hooks/edit' do
it 'renders alert' do
render
- expect(rendered).to have_text(s_('Webhooks|Webhook was automatically disabled'))
+ expect(rendered).to have_text(s_('Webhooks|Webhook rate limit has been reached'))
end
end
diff --git a/spec/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml_spec.rb b/spec/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml_spec.rb
new file mode 100644
index 00000000000..416f4253e1b
--- /dev/null
+++ b/spec/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'projects/merge_requests/_close_reopen_draft_report_toggle.html.haml' do
+ let_it_be(:merge_request) { create(:merge_request, state: :merged) }
+
+ before do
+ assign(:merge_request, merge_request)
+ assign(:project, merge_request.target_project)
+
+ allow(view).to receive(:moved_mr_sidebar_enabled?).and_return(true)
+ end
+
+ describe 'notifcations toggle' do
+ context 'when mr merged and logged in' do
+ it 'is present' do
+ allow(view).to receive(:current_user).and_return(merge_request.author)
+
+ render
+
+ expect(rendered).to have_css('li', class: 'js-sidebar-subscriptions-entry-point')
+ end
+ end
+
+ context 'when mr merged and not logged in' do
+ it 'is not present' do
+ render
+
+ expect(rendered).not_to have_css('li', class: 'js-sidebar-subscriptions-entry-point')
+ end
+ end
+ end
+end
diff --git a/spec/views/registrations/welcome/show.html.haml_spec.rb b/spec/views/registrations/welcome/show.html.haml_spec.rb
index d9c5d348e15..99d87ac449b 100644
--- a/spec/views/registrations/welcome/show.html.haml_spec.rb
+++ b/spec/views/registrations/welcome/show.html.haml_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'registrations/welcome/show' do
allow(view).to receive(:in_trial_flow?).and_return(false)
allow(view).to receive(:user_has_memberships?).and_return(false)
allow(view).to receive(:in_oauth_flow?).and_return(false)
+ allow(view).to receive(:glm_tracking_params).and_return({})
render
end
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index 72e2d7131c0..2149c394320 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -12,6 +12,13 @@ RSpec.describe 'search/_results' do
controller.params[:action] = 'show'
controller.params[:search] = term
+ allow(self).to receive(:current_user).and_return(user)
+ allow(@search_results).to receive(:formatted_count).with(scope).and_return(10)
+ allow(self).to receive(:search_count_path).with(any_args).and_return("test count link")
+ allow(self).to receive(:search_path).with(any_args).and_return("link test")
+
+ stub_feature_flags(search_page_vertical_nav: false)
+
create_list(:issue, 3)
@search_objects = search_objects
@@ -147,7 +154,7 @@ RSpec.describe 'search/_results' do
it 'does not render the sidebar' do
render
- expect(rendered).not_to have_selector('#js-search-sidebar')
+ expect(rendered).not_to have_selector('form.search-sidebar')
end
end
end
diff --git a/spec/views/search/show.html.haml_spec.rb b/spec/views/search/show.html.haml_spec.rb
index a336ec91ff2..565dadd64fe 100644
--- a/spec/views/search/show.html.haml_spec.rb
+++ b/spec/views/search/show.html.haml_spec.rb
@@ -4,93 +4,118 @@ require 'spec_helper'
RSpec.describe 'search/show' do
let(:search_term) { nil }
+ let(:user) { build(:user) }
before do
stub_template "search/_category.html.haml" => 'Category Partial'
stub_template "search/_results.html.haml" => 'Results Partial'
-
- @search_term = search_term
-
- render
end
- context 'when the search page is opened' do
- it 'displays the title' do
- expect(rendered).to have_selector('h1.page-title', text: 'Search')
- expect(rendered).not_to have_selector('h1.page-title code')
+ context 'feature flag enabled' do
+ before do
+ allow(self).to receive(:current_user).and_return(user)
+ @search_term = search_term
+
+ render
end
- it 'does not render partials' do
- expect(rendered).not_to render_template('search/_category')
- expect(rendered).not_to render_template('search/_results')
+ context 'when search term is supplied' do
+ let(:search_term) { 'Search Foo' }
+
+ it 'will not render category partial' do
+ expect(rendered).not_to render_template('search/_category')
+ expect(rendered).to render_template('search/_results')
+ end
end
end
- context 'when search term is supplied' do
- let(:search_term) { 'Search Foo' }
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(search_page_vertical_nav: false)
- it 'renders partials' do
- expect(rendered).to render_template('search/_category')
- expect(rendered).to render_template('search/_results')
+ @search_term = search_term
+
+ render
end
- context 'unfurling support' do
- let(:group) { build(:group) }
- let(:search_results) do
- instance_double(Gitlab::GroupSearchResults).tap do |double|
- allow(double).to receive(:formatted_count).and_return(0)
- end
+ context 'when the search page is opened' do
+ it 'displays the title' do
+ expect(rendered).to have_selector('h1.page-title', text: 'Search')
+ expect(rendered).not_to have_selector('h1.page-title code')
end
- before do
- assign(:search_results, search_results)
- assign(:scope, 'issues')
- assign(:group, group)
+ it 'does not render partials' do
+ expect(rendered).not_to render_template('search/_category')
+ expect(rendered).not_to render_template('search/_results')
end
+ end
+
+ context 'when search term is supplied' do
+ let(:search_term) { 'Search Foo' }
+
+ it 'renders partials' do
+ expect(rendered).to render_template('search/_category')
+ expect(rendered).to render_template('search/_results')
+ end
+
+ context 'unfurling support' do
+ let(:group) { build(:group) }
+ let(:search_results) do
+ instance_double(Gitlab::GroupSearchResults).tap do |double|
+ allow(double).to receive(:formatted_count).and_return(0)
+ end
+ end
- context 'search with full count' do
before do
- assign(:without_count, false)
+ assign(:search_results, search_results)
+ assign(:scope, 'issues')
+ assign(:group, group)
end
- it 'renders meta tags for a group' do
- render
+ context 'search with full count' do
+ before do
+ assign(:without_count, false)
+ end
- expect(view.page_description).to match(/\d+ issues for term '#{search_term}'/)
- expect(view.page_card_attributes).to eq("Namespace" => group.full_path)
- end
+ it 'renders meta tags for a group' do
+ render
- it 'renders meta tags for both group and project' do
- project = build(:project, group: group)
- assign(:project, project)
+ expect(view.page_description).to match(/\d+ issues for term '#{search_term}'/)
+ expect(view.page_card_attributes).to eq("Namespace" => group.full_path)
+ end
- render
+ it 'renders meta tags for both group and project' do
+ project = build(:project, group: group)
+ assign(:project, project)
- expect(view.page_description).to match(/\d+ issues for term '#{search_term}'/)
- expect(view.page_card_attributes).to eq("Namespace" => group.full_path, "Project" => project.full_path)
- end
- end
+ render
- context 'search without full count' do
- before do
- assign(:without_count, true)
+ expect(view.page_description).to match(/\d+ issues for term '#{search_term}'/)
+ expect(view.page_card_attributes).to eq("Namespace" => group.full_path, "Project" => project.full_path)
+ end
end
- it 'renders meta tags for a group' do
- render
+ context 'search without full count' do
+ before do
+ assign(:without_count, true)
+ end
- expect(view.page_description).to match(/issues results for term '#{search_term}'/)
- expect(view.page_card_attributes).to eq("Namespace" => group.full_path)
- end
+ it 'renders meta tags for a group' do
+ render
+
+ expect(view.page_description).to match(/issues results for term '#{search_term}'/)
+ expect(view.page_card_attributes).to eq("Namespace" => group.full_path)
+ end
- it 'renders meta tags for both group and project' do
- project = build(:project, group: group)
- assign(:project, project)
+ it 'renders meta tags for both group and project' do
+ project = build(:project, group: group)
+ assign(:project, project)
- render
+ render
- expect(view.page_description).to match(/issues results for term '#{search_term}'/)
- expect(view.page_card_attributes).to eq("Namespace" => group.full_path, "Project" => project.full_path)
+ expect(view.page_description).to match(/issues results for term '#{search_term}'/)
+ expect(view.page_card_attributes).to eq("Namespace" => group.full_path, "Project" => project.full_path)
+ end
end
end
end
diff --git a/spec/views/shared/projects/_project.html.haml_spec.rb b/spec/views/shared/projects/_project.html.haml_spec.rb
index 62f23338c48..7575c3b8b92 100644
--- a/spec/views/shared/projects/_project.html.haml_spec.rb
+++ b/spec/views/shared/projects/_project.html.haml_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'shared/projects/_project.html.haml' do
it 'renders creator avatar if project has a creator' do
render 'shared/projects/project', use_creator_avatar: true, project: project
- expect(rendered).to have_selector('img.avatar')
+ expect(rendered).to have_selector('img.gl-avatar')
end
it 'renders a generic avatar if project does not have a creator' do
@@ -21,6 +21,6 @@ RSpec.describe 'shared/projects/_project.html.haml' do
render 'shared/projects/project', use_creator_avatar: true, project: project
- expect(rendered).to have_selector('.project-avatar')
+ expect(rendered).to have_selector('.gl-avatar-identicon')
end
end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index 7e301efe708..0d0b81d2ec0 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -87,7 +87,6 @@ RSpec.describe BulkImportWorker do
create(:bulk_import_entity, :created, bulk_import: bulk_import)
expect(described_class).to receive(:perform_in).with(described_class::PERFORM_DELAY, bulk_import.id)
- expect(BulkImports::EntityWorker).to receive(:perform_async).twice
expect(BulkImports::ExportRequestWorker).to receive(:perform_async).twice
subject.perform(bulk_import.id)
@@ -111,7 +110,7 @@ RSpec.describe BulkImportWorker do
bulk_import = create(:bulk_import, :created)
create(:bulk_import_entity, :created, bulk_import: bulk_import)
- allow(BulkImports::EntityWorker).to receive(:perform_async).and_raise(StandardError)
+ allow(BulkImports::ExportRequestWorker).to receive(:perform_async).and_raise(StandardError)
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(kind_of(StandardError), bulk_import_id: bulk_import.id)
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index ab85b587975..0fcdbccc304 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -37,9 +37,11 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
'current_stage' => nil,
- 'message' => 'Stage starting'
+ 'message' => 'Stage starting',
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -67,8 +69,10 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
- 'current_stage' => nil
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'current_stage' => nil,
+ 'importer' => 'gitlab_migration'
)
)
@@ -76,16 +80,23 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:error)
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
'current_stage' => nil,
- 'message' => 'Error!'
+ 'message' => 'Error!',
+ 'importer' => 'gitlab_migration'
)
)
end
expect(Gitlab::ErrorTracking)
.to receive(:track_exception)
- .with(exception, entity_id: entity.id)
+ .with(
+ exception,
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ importer: 'gitlab_migration'
+ )
subject
end
@@ -99,9 +110,11 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
'current_stage' => 0,
- 'message' => 'Stage running'
+ 'message' => 'Stage running',
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -127,8 +140,10 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
- 'current_stage' => 0
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'current_stage' => 0,
+ 'importer' => 'gitlab_migration'
)
)
end
diff --git a/spec/workers/bulk_imports/export_request_worker_spec.rb b/spec/workers/bulk_imports/export_request_worker_spec.rb
index a7f7aaa7dba..597eed3a9b9 100644
--- a/spec/workers/bulk_imports/export_request_worker_spec.rb
+++ b/spec/workers/bulk_imports/export_request_worker_spec.rb
@@ -21,38 +21,128 @@ RSpec.describe BulkImports::ExportRequestWorker do
shared_examples 'requests relations export for api resource' do
include_examples 'an idempotent worker' do
- it 'requests relations export' do
+ it 'requests relations export & schedules entity worker' do
expect_next_instance_of(BulkImports::Clients::HTTP) do |client|
expect(client).to receive(:post).with(expected).twice
end
+ expect(BulkImports::EntityWorker).to receive(:perform_async).twice
+
perform_multiple(job_args)
end
context 'when network error is raised' do
- it 'logs export failure and marks entity as failed' do
+ let(:exception) { BulkImports::NetworkError.new('Export error') }
+
+ before do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:post).and_raise(exception).twice
+ end
+ end
+
+ context 'when error is retriable' do
+ it 'logs retry request and reenqueues' do
+ allow(exception).to receive(:retriable?).twice.and_return(true)
+
+ expect(Gitlab::Import::Logger).to receive(:error).with(
+ hash_including(
+ 'bulk_import_entity_id' => entity.id,
+ 'pipeline_class' => 'ExportRequestWorker',
+ 'exception_class' => 'BulkImports::NetworkError',
+ 'exception_message' => 'Export error',
+ 'bulk_import_id' => bulk_import.id,
+ 'bulk_import_entity_type' => entity.source_type,
+ 'importer' => 'gitlab_migration',
+ 'message' => 'Retrying export request'
+ )
+ ).twice
+
+ expect(described_class).to receive(:perform_in).twice.with(2.seconds, entity.id)
+
+ perform_multiple(job_args)
+ end
+ end
+
+ context 'when error is not retriable' do
+ it 'logs export failure and marks entity as failed' do
+ expect(Gitlab::Import::Logger).to receive(:error).with(
+ hash_including(
+ 'bulk_import_entity_id' => entity.id,
+ 'pipeline_class' => 'ExportRequestWorker',
+ 'exception_class' => 'BulkImports::NetworkError',
+ 'exception_message' => 'Export error',
+ 'correlation_id_value' => anything,
+ 'bulk_import_id' => bulk_import.id,
+ 'bulk_import_entity_type' => entity.source_type,
+ 'importer' => 'gitlab_migration'
+ )
+ ).twice
+
+ perform_multiple(job_args)
+
+ failure = entity.failures.last
+
+ expect(failure.pipeline_class).to eq('ExportRequestWorker')
+ expect(failure.exception_message).to eq('Export error')
+ end
+ end
+ end
+
+ context 'when source id is nil' do
+ let(:entity_source_id) { 'gid://gitlab/Model/1234567' }
+
+ before do
+ graphql_client = instance_double(BulkImports::Clients::Graphql)
+ response = double(original_hash: { 'data' => { entity.entity_type => { 'id' => entity_source_id } } })
+
+ allow(BulkImports::Clients::Graphql).to receive(:new).and_return(graphql_client)
+ allow(graphql_client).to receive(:parse)
+ allow(graphql_client).to receive(:execute).and_return(response)
+ end
+
+ it 'updates entity source id & requests export using source id' do
expect_next_instance_of(BulkImports::Clients::HTTP) do |client|
- expect(client).to receive(:post).and_raise(BulkImports::NetworkError, 'Export error').twice
+ expect(client)
+ .to receive(:post)
+ .with("/#{entity.pluralized_name}/1234567/export_relations")
+ .twice
end
- expect(Gitlab::Import::Logger).to receive(:error).with(
- hash_including(
- 'bulk_import_entity_id' => entity.id,
- 'pipeline_class' => 'ExportRequestWorker',
- 'exception_class' => 'BulkImports::NetworkError',
- 'exception_message' => 'Export error',
- 'correlation_id_value' => anything,
- 'bulk_import_id' => bulk_import.id,
- 'bulk_import_entity_type' => entity.source_type
- )
- ).twice
+ entity.update!(source_xid: nil)
perform_multiple(job_args)
- failure = entity.failures.last
+ expect(entity.reload.source_xid).to eq(1234567)
+ end
+
+ context 'when something goes wrong during source id fetch' do
+ let(:entity_source_id) { 'invalid' }
+
+ it 'logs the error & requests relations export using full path url' do
+ expect_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ expect(client).to receive(:post).with(full_path_url).twice
+ end
+
+ entity.update!(source_xid: nil)
- expect(failure.pipeline_class).to eq('ExportRequestWorker')
- expect(failure.exception_message).to eq('Export error')
+ expect(Gitlab::Import::Logger).to receive(:error).with(
+ a_hash_including(
+ 'message' => 'Failed to fetch source entity id',
+ 'bulk_import_entity_id' => entity.id,
+ 'pipeline_class' => 'ExportRequestWorker',
+ 'exception_class' => 'NoMethodError',
+ 'exception_message' => "undefined method `model_id' for nil:NilClass",
+ 'correlation_id_value' => anything,
+ 'bulk_import_id' => bulk_import.id,
+ 'bulk_import_entity_type' => entity.source_type,
+ 'importer' => 'gitlab_migration'
+ )
+ ).twice
+
+ perform_multiple(job_args)
+
+ expect(entity.source_xid).to be_nil
+ end
end
end
end
@@ -60,14 +150,16 @@ RSpec.describe BulkImports::ExportRequestWorker do
context 'when entity is group' do
let(:entity) { create(:bulk_import_entity, :group_entity, source_full_path: 'foo/bar', bulk_import: bulk_import) }
- let(:expected) { '/groups/foo%2Fbar/export_relations' }
+ let(:expected) { "/groups/#{entity.source_xid}/export_relations" }
+ let(:full_path_url) { '/groups/foo%2Fbar/export_relations' }
include_examples 'requests relations export for api resource'
end
context 'when entity is project' do
let(:entity) { create(:bulk_import_entity, :project_entity, source_full_path: 'foo/bar', bulk_import: bulk_import) }
- let(:expected) { '/projects/foo%2Fbar/export_relations' }
+ let(:expected) { "/projects/#{entity.source_xid}/export_relations" }
+ let(:full_path_url) { '/projects/foo%2Fbar/export_relations' }
include_examples 'requests relations export for api resource'
end
diff --git a/spec/workers/bulk_imports/pipeline_worker_spec.rb b/spec/workers/bulk_imports/pipeline_worker_spec.rb
index fe2039bd79e..ee65775f170 100644
--- a/spec/workers/bulk_imports/pipeline_worker_spec.rb
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -37,7 +37,9 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -83,8 +85,10 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_tracker_id' => pipeline_tracker.id,
- 'entity_id' => entity.id,
- 'message' => 'Unstarted pipeline not found'
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'message' => 'Unstarted pipeline not found',
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -120,8 +124,10 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id,
- 'message' => 'Error!'
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'message' => 'Error!',
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -130,8 +136,10 @@ RSpec.describe BulkImports::PipelineWorker do
.to receive(:track_exception)
.with(
instance_of(StandardError),
- entity_id: entity.id,
- pipeline_name: pipeline_tracker.pipeline_name
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ pipeline_name: pipeline_tracker.pipeline_name,
+ importer: 'gitlab_migration'
)
expect(BulkImports::EntityWorker)
@@ -160,7 +168,7 @@ RSpec.describe BulkImports::PipelineWorker do
end
context 'when entity is failed' do
- it 'marks tracker as failed and logs the error' do
+ it 'marks tracker as skipped and logs the skip' do
pipeline_tracker = create(
:bulk_import_tracker,
entity: entity,
@@ -170,22 +178,25 @@ RSpec.describe BulkImports::PipelineWorker do
entity.update!(status: -1)
- expect(BulkImports::Failure).to receive(:create)
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ allow(logger).to receive(:info)
+
expect(logger)
- .to receive(:error)
+ .to receive(:info)
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id,
- 'message' => 'Failed entity status'
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'message' => 'Skipping pipeline due to failed entity',
+ 'importer' => 'gitlab_migration'
)
)
end
subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
- expect(pipeline_tracker.reload.status_name).to eq(:failed)
+ expect(pipeline_tracker.reload.status_name).to eq(:skipped)
end
end
@@ -224,7 +235,9 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id
+ 'bulk_import_entity_id' => entity.id,
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -347,8 +360,10 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'NdjsonPipeline',
- 'entity_id' => entity.id,
- 'message' => 'Pipeline timeout'
+ 'bulk_import_entity_id' => entity.id,
+ 'message' => 'Pipeline timeout',
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'importer' => 'gitlab_migration'
)
)
end
@@ -374,8 +389,10 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'NdjsonPipeline',
- 'entity_id' => entity.id,
- 'message' => 'Error!'
+ 'bulk_import_entity_id' => entity.id,
+ 'message' => 'Export from source instance failed: Error!',
+ 'bulk_import_id' => entity.bulk_import_id,
+ 'importer' => 'gitlab_migration'
)
)
end
diff --git a/spec/workers/ci/parse_secure_file_metadata_worker_spec.rb b/spec/workers/ci/parse_secure_file_metadata_worker_spec.rb
new file mode 100644
index 00000000000..57bbd8a6ff0
--- /dev/null
+++ b/spec/workers/ci/parse_secure_file_metadata_worker_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::ParseSecureFileMetadataWorker do
+ describe '#perform' do
+ include_examples 'an idempotent worker' do
+ let(:secure_file) { create(:ci_secure_file) }
+ subject { described_class.new.perform(secure_file&.id) }
+
+ context 'when the file is found' do
+ it 'calls update_metadata!' do
+ allow(::Ci::SecureFile).to receive(:find_by_id).and_return(secure_file)
+ expect(secure_file).to receive(:update_metadata!)
+
+ subject
+ end
+ end
+ end
+
+ context 'when file is not found' do
+ let(:secure_file) { nil }
+
+ it 'does not call update_metadata!' do
+ expect(secure_file).not_to receive(:update_metadata!)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pipeline_success_unlock_artifacts_worker_spec.rb b/spec/workers/ci/pipeline_success_unlock_artifacts_worker_spec.rb
index cb2cf58d50b..3b33972c76f 100644
--- a/spec/workers/ci/pipeline_success_unlock_artifacts_worker_spec.rb
+++ b/spec/workers/ci/pipeline_success_unlock_artifacts_worker_spec.rb
@@ -27,15 +27,18 @@ RSpec.describe Ci::PipelineSuccessUnlockArtifactsWorker do
end
context 'when pipeline exists' do
- let(:pipeline) { create(:ci_pipeline, :success, :with_job) }
+ let!(:pipeline) { create(:ci_pipeline, :success, :with_job) }
let(:pipeline_id) { pipeline.id }
- context 'when pipeline has artifacts' do
- before do
- create(:ci_job_artifact, job: pipeline.builds.first)
- end
+ before do
+ allow(Ci::Pipeline).to receive(:find_by_id).with(pipeline.id).and_return(pipeline)
+ allow(pipeline).to receive(:has_erasable_artifacts?).and_return(has_erasable_artifacts)
+ end
- it 'calls the service' do
+ context 'when pipeline has erasable artifacts' do
+ let(:has_erasable_artifacts) { true }
+
+ it 'calls the unlock service' do
service = spy(Ci::UnlockArtifactsService)
expect(Ci::UnlockArtifactsService).to receive(:new).and_return(service)
@@ -45,8 +48,10 @@ RSpec.describe Ci::PipelineSuccessUnlockArtifactsWorker do
end
end
- context 'when pipeline does not have artifacts' do
- it 'does not call service' do
+ context 'when pipeline has no erasable artifacts' do
+ let(:has_erasable_artifacts) { false }
+
+ it 'does not call the unlock service' do
expect(Ci::UnlockArtifactsService).not_to receive(:new)
perform
diff --git a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
index 5a32c1b40bb..ece0c5053cb 100644
--- a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
+++ b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
@@ -159,11 +159,13 @@ RSpec.describe Gitlab::GithubImport::ObjectImporter, :aggregate_failures do
.with(
project_id: project.id,
exception: exception,
- error_source: 'klass_name'
+ error_source: 'klass_name',
+ fail_import: false
)
.and_call_original
- worker.import(project, client, { 'number' => 10, 'github_id' => 1 })
+ expect { worker.import(project, client, { 'number' => 10, 'github_id' => 1 }) }
+ .to raise_error(exception)
expect(project.import_state.reload.status).to eq('started')
@@ -193,4 +195,12 @@ RSpec.describe Gitlab::GithubImport::ObjectImporter, :aggregate_failures do
end
end
end
+
+ describe '#increment_object_counter?' do
+ let(:issue) { double(:issue, pull_request?: true) }
+
+ it 'returns true' do
+ expect(worker).to be_increment_object_counter(issue)
+ end
+ end
end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 6b67c2b474c..322f516fbeb 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -225,7 +225,6 @@ RSpec.describe 'Every Sidekiq worker' do
'Environments::CanaryIngress::UpdateWorker' => false,
'Epics::UpdateEpicsDatesWorker' => 3,
'ErrorTrackingIssueLinkWorker' => 3,
- 'Experiments::RecordConversionEventWorker' => 3,
'ExportCsvWorker' => 3,
'ExternalServiceReactiveCachingWorker' => 3,
'FileHookWorker' => false,
@@ -258,6 +257,10 @@ RSpec.describe 'Every Sidekiq worker' do
'GitGarbageCollectWorker' => false,
'Gitlab::GithubImport::AdvanceStageWorker' => 3,
'Gitlab::GithubImport::ImportReleaseAttachmentsWorker' => 5,
+ 'Gitlab::GithubImport::Attachments::ImportReleaseWorker' => 5,
+ 'Gitlab::GithubImport::Attachments::ImportNoteWorker' => 5,
+ 'Gitlab::GithubImport::Attachments::ImportIssueWorker' => 5,
+ 'Gitlab::GithubImport::Attachments::ImportMergeRequestWorker' => 5,
'Gitlab::GithubImport::ImportDiffNoteWorker' => 5,
'Gitlab::GithubImport::ImportIssueWorker' => 5,
'Gitlab::GithubImport::ImportIssueEventWorker' => 5,
@@ -344,10 +347,10 @@ RSpec.describe 'Every Sidekiq worker' do
'Metrics::Dashboard::PruneOldAnnotationsWorker' => 3,
'Metrics::Dashboard::SyncDashboardsWorker' => 3,
'MigrateExternalDiffsWorker' => 3,
- 'Namespaces::OnboardingIssueCreatedWorker' => 3,
- 'Namespaces::OnboardingPipelineCreatedWorker' => 3,
- 'Namespaces::OnboardingProgressWorker' => 3,
- 'Namespaces::OnboardingUserAddedWorker' => 3,
+ 'Onboarding::IssueCreatedWorker' => 3,
+ 'Onboarding::PipelineCreatedWorker' => 3,
+ 'Onboarding::ProgressWorker' => 3,
+ 'Onboarding::UserAddedWorker' => 3,
'Namespaces::RefreshRootStatisticsWorker' => 3,
'Namespaces::RootStatisticsWorker' => 3,
'Namespaces::ScheduleAggregationWorker' => 3,
diff --git a/spec/workers/experiments/record_conversion_event_worker_spec.rb b/spec/workers/experiments/record_conversion_event_worker_spec.rb
deleted file mode 100644
index 05e4ebc13ba..00000000000
--- a/spec/workers/experiments/record_conversion_event_worker_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Experiments::RecordConversionEventWorker, '#perform' do
- subject(:perform) { described_class.new.perform(:experiment_key, 1234) }
-
- before do
- stub_experiment(experiment_key: experiment_active)
- end
-
- context 'when the experiment is active' do
- let(:experiment_active) { true }
-
- include_examples 'an idempotent worker' do
- subject { perform }
-
- it 'records the event' do
- expect(Experiment).to receive(:record_conversion_event).with(:experiment_key, 1234)
-
- perform
- end
- end
- end
-
- context 'when the experiment is not active' do
- let(:experiment_active) { false }
-
- it 'records the event' do
- expect(Experiment).not_to receive(:record_conversion_event)
-
- perform
- end
- end
-end
diff --git a/spec/workers/gitlab/github_import/attachments/import_issue_worker_spec.rb b/spec/workers/gitlab/github_import/attachments/import_issue_worker_spec.rb
new file mode 100644
index 00000000000..6d617755861
--- /dev/null
+++ b/spec/workers/gitlab/github_import/attachments/import_issue_worker_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Attachments::ImportIssueWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#import' do
+ let(:import_state) { create(:import_state, :started) }
+
+ let(:project) do
+ instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state)
+ end
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+
+ it 'imports an issue attachments' do
+ expect_next_instance_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter,
+ an_instance_of(Gitlab::GithubImport::Representation::NoteText),
+ project,
+ client
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ expect(Gitlab::GithubImport::ObjectCounter)
+ .to receive(:increment)
+ .and_call_original
+
+ worker.import(project, client, {})
+ end
+ end
+end
diff --git a/spec/workers/gitlab/github_import/attachments/import_merge_request_worker_spec.rb b/spec/workers/gitlab/github_import/attachments/import_merge_request_worker_spec.rb
new file mode 100644
index 00000000000..66dfc027e6e
--- /dev/null
+++ b/spec/workers/gitlab/github_import/attachments/import_merge_request_worker_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Attachments::ImportMergeRequestWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#import' do
+ let(:import_state) { create(:import_state, :started) }
+
+ let(:project) do
+ instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state)
+ end
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+
+ it 'imports an merge request attachments' do
+ expect_next_instance_of(
+ Gitlab::GithubImport::Importer::NoteAttachmentsImporter,
+ an_instance_of(Gitlab::GithubImport::Representation::NoteText),
+ project,
+ client
+ ) do |note_attachments_importer|
+ expect(note_attachments_importer).to receive(:execute)
+ end
+
+ expect(Gitlab::GithubImport::ObjectCounter)
+ .to receive(:increment)
+ .and_call_original
+
+ worker.import(project, client, {})
+ end
+ end
+end
diff --git a/spec/workers/gitlab/github_import/attachments/import_note_worker_spec.rb b/spec/workers/gitlab/github_import/attachments/import_note_worker_spec.rb
new file mode 100644
index 00000000000..7b60cdecca6
--- /dev/null
+++ b/spec/workers/gitlab/github_import/attachments/import_note_worker_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Attachments::ImportNoteWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#import' do
+ let(:import_state) { create(:import_state, :started) }
+
+ let(:project) do
+ instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state)
+ end
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+ let(:importer) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+
+ let(:note_hash) do
+ {
+ 'record_db_id' => rand(100),
+ 'record_type' => 'Note',
+ 'text' => <<-TEXT
+ Some text...
+
+ ![special-image](https://user-images.githubusercontent.com...)
+ TEXT
+ }
+ end
+
+ it 'imports an release attachments' do
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter)
+ .to receive(:new)
+ .with(
+ an_instance_of(Gitlab::GithubImport::Representation::NoteText),
+ project,
+ client
+ )
+ .and_return(importer)
+
+ expect(importer).to receive(:execute)
+
+ expect(Gitlab::GithubImport::ObjectCounter)
+ .to receive(:increment)
+ .and_call_original
+
+ worker.import(project, client, note_hash)
+ end
+ end
+end
diff --git a/spec/workers/gitlab/github_import/attachments/import_release_worker_spec.rb b/spec/workers/gitlab/github_import/attachments/import_release_worker_spec.rb
new file mode 100644
index 00000000000..e49b2fb6504
--- /dev/null
+++ b/spec/workers/gitlab/github_import/attachments/import_release_worker_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Attachments::ImportReleaseWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#import' do
+ let(:import_state) { create(:import_state, :started) }
+
+ let(:project) do
+ instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state)
+ end
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+ let(:importer) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
+
+ let(:note_hash) do
+ {
+ 'record_db_id' => rand(100),
+ 'record_type' => 'Release',
+ 'text' => <<-TEXT
+ Some text...
+
+ ![special-image](https://user-images.githubusercontent.com...)
+ TEXT
+ }
+ end
+
+ it 'imports an release attachments' do
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter)
+ .to receive(:new)
+ .with(
+ an_instance_of(Gitlab::GithubImport::Representation::NoteText),
+ project,
+ client
+ )
+ .and_return(importer)
+
+ expect(importer).to receive(:execute)
+
+ expect(Gitlab::GithubImport::ObjectCounter)
+ .to receive(:increment)
+ .and_call_original
+
+ worker.import(project, client, note_hash)
+ end
+ end
+end
diff --git a/spec/workers/gitlab/github_import/import_issue_worker_spec.rb b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb
index c2a7639fde4..ef1d2e3f3e7 100644
--- a/spec/workers/gitlab/github_import/import_issue_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb
@@ -45,4 +45,15 @@ RSpec.describe Gitlab::GithubImport::ImportIssueWorker do
worker.import(project, client, hash)
end
end
+
+ describe '#increment_object_counter?' do
+ context 'when github issue is a pull request' do
+ let(:issue) { double(:issue, pull_request?: true) }
+ let(:project) { double(:project) }
+
+ it 'returns false' do
+ expect(worker).not_to be_increment_object_counter(issue)
+ end
+ end
+ end
end
diff --git a/spec/workers/gitlab/github_import/import_release_attachments_worker_spec.rb b/spec/workers/gitlab/github_import/import_release_attachments_worker_spec.rb
index cd53c6ee9c0..1d32d5c0e21 100644
--- a/spec/workers/gitlab/github_import/import_release_attachments_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/import_release_attachments_worker_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::GithubImport::ImportReleaseAttachmentsWorker do
end
let(:client) { instance_double('Gitlab::GithubImport::Client') }
- let(:importer) { instance_double('Gitlab::GithubImport::Importer::ReleaseAttachmentsImporter') }
+ let(:importer) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
let(:release_hash) do
{
@@ -27,10 +27,10 @@ RSpec.describe Gitlab::GithubImport::ImportReleaseAttachmentsWorker do
end
it 'imports an issue event' do
- expect(Gitlab::GithubImport::Importer::ReleaseAttachmentsImporter)
+ expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter)
.to receive(:new)
.with(
- an_instance_of(Gitlab::GithubImport::Representation::ReleaseAttachments),
+ an_instance_of(Gitlab::GithubImport::Representation::NoteText),
project,
client
)
diff --git a/spec/workers/gitlab/github_import/stage/import_attachments_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_attachments_worker_spec.rb
index c2c5e1dbf4e..ecfece735af 100644
--- a/spec/workers/gitlab/github_import/stage/import_attachments_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_attachments_worker_spec.rb
@@ -5,40 +5,60 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Stage::ImportAttachmentsWorker do
subject(:worker) { described_class.new }
- let(:project) { create(:project) }
- let!(:group) { create(:group, projects: [project]) }
- let(:feature_flag_state) { [group] }
+ let_it_be(:project) { create(:project) }
+ let(:settings) { ::Gitlab::GithubImport::Settings.new(project) }
+ let(:stage_enabled) { true }
+
+ before do
+ settings.write({ attachments_import: stage_enabled })
+ end
describe '#import' do
- let(:importer) { instance_double('Gitlab::GithubImport::Importer::ReleasesAttachmentsImporter') }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
-
- before do
- stub_feature_flags(github_importer_attachments_import: feature_flag_state)
+ let(:importers) do
+ [
+ {
+ klass: Gitlab::GithubImport::Importer::Attachments::ReleasesImporter,
+ double: instance_double('Gitlab::GithubImport::Importer::Attachments::ReleasesImporter'),
+ waiter: Gitlab::JobWaiter.new(2, '123')
+ },
+ {
+ klass: Gitlab::GithubImport::Importer::Attachments::NotesImporter,
+ double: instance_double('Gitlab::GithubImport::Importer::Attachments::NotesImporter'),
+ waiter: Gitlab::JobWaiter.new(3, '234')
+ },
+ {
+ klass: Gitlab::GithubImport::Importer::Attachments::IssuesImporter,
+ double: instance_double('Gitlab::GithubImport::Importer::Attachments::IssuesImporter'),
+ waiter: Gitlab::JobWaiter.new(4, '345')
+ },
+ {
+ klass: Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporter,
+ double: instance_double('Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporter'),
+ waiter: Gitlab::JobWaiter.new(5, '456')
+ }
+ ]
end
- it 'imports release attachments' do
- waiter = Gitlab::JobWaiter.new(2, '123')
-
- expect(Gitlab::GithubImport::Importer::ReleasesAttachmentsImporter)
- .to receive(:new)
- .with(project, client)
- .and_return(importer)
-
- expect(importer).to receive(:execute).and_return(waiter)
+ it 'imports attachments' do
+ importers.each do |importer|
+ expect_next_instance_of(importer[:klass], project, client) do |instance|
+ expect(instance).to receive(:execute).and_return(importer[:waiter])
+ end
+ end
expect(Gitlab::GithubImport::AdvanceStageWorker)
.to receive(:perform_async)
- .with(project.id, { '123' => 2 }, :protected_branches)
+ .with(project.id, { '123' => 2, '234' => 3, '345' => 4, '456' => 5 }, :protected_branches)
worker.import(client, project)
end
- context 'when feature flag is disabled' do
- let(:feature_flag_state) { false }
+ context 'when stage is disabled' do
+ let(:stage_enabled) { false }
it 'skips release attachments import and calls next stage' do
- expect(Gitlab::GithubImport::Importer::ReleasesAttachmentsImporter).not_to receive(:new)
+ importers.each { |importer| expect(importer[:klass]).not_to receive(:new) }
expect(Gitlab::GithubImport::AdvanceStageWorker)
.to receive(:perform_async).with(project.id, {}, :protected_branches)
diff --git a/spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb
index 932152c0764..199d1b9a3ca 100644
--- a/spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb
@@ -7,23 +7,21 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportIssueEventsWorker do
let(:project) { create(:project) }
let!(:group) { create(:group, projects: [project]) }
- let(:feature_flag_state) { [group] }
- let(:single_endpoint_feature_flag_state) { [group] }
+ let(:settings) { ::Gitlab::GithubImport::Settings.new(project) }
+ let(:stage_enabled) { true }
+
+ before do
+ settings.write({ single_endpoint_issue_events_import: stage_enabled })
+ end
describe '#import' do
let(:importer) { instance_double('Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter') }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
- before do
- stub_feature_flags(github_importer_single_endpoint_issue_events_import: single_endpoint_feature_flag_state)
- stub_feature_flags(github_importer_issue_events_import: feature_flag_state)
- end
-
- context 'when single endpoint feature flag enabled' do
- it 'imports all the issue events' do
+ context 'when stage is enabled' do
+ it 'imports issue events' do
waiter = Gitlab::JobWaiter.new(2, '123')
- expect(Gitlab::GithubImport::Importer::IssueEventsImporter).not_to receive(:new)
expect(Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter)
.to receive(:new)
.with(project, client)
@@ -39,35 +37,11 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportIssueEventsWorker do
end
end
- context 'when import issue events feature flag enabled' do
- let(:single_endpoint_feature_flag_state) { false }
-
- it 'imports the issue events partly' do
- waiter = Gitlab::JobWaiter.new(2, '123')
-
- expect(Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter).not_to receive(:new)
- expect(Gitlab::GithubImport::Importer::IssueEventsImporter)
- .to receive(:new)
- .with(project, client)
- .and_return(importer)
-
- expect(importer).to receive(:execute).and_return(waiter)
-
- expect(Gitlab::GithubImport::AdvanceStageWorker)
- .to receive(:perform_async)
- .with(project.id, { '123' => 2 }, :notes)
-
- worker.import(client, project)
- end
- end
-
- context 'when feature flags are disabled' do
- let(:feature_flag_state) { false }
- let(:single_endpoint_feature_flag_state) { false }
+ context 'when stage is disabled' do
+ let(:stage_enabled) { false }
it 'skips issue events import and calls next stage' do
expect(Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter).not_to receive(:new)
- expect(Gitlab::GithubImport::Importer::IssueEventsImporter).not_to receive(:new)
expect(Gitlab::GithubImport::AdvanceStageWorker).to receive(:perform_async).with(project.id, {}, :notes)
worker.import(client, project)
diff --git a/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb
index a88256b3cae..beef0864715 100644
--- a/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb
@@ -6,6 +6,13 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportIssuesAndDiffNotesWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
+ let(:settings) { ::Gitlab::GithubImport::Settings.new(project) }
+ let(:single_endpoint_optional_stage) { true }
+
+ before do
+ settings.write({ single_endpoint_notes_import: single_endpoint_optional_stage })
+ end
+
describe '#import' do
it 'imports the issues and diff notes' do
client = double(:client)
@@ -33,37 +40,18 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportIssuesAndDiffNotesWorker do
end
describe '#importers' do
- context 'when project group is present' do
- let_it_be(:project) { create(:project) }
- let_it_be(:group) { create(:group, projects: [project]) }
-
- context 'when feature flag github_importer_single_endpoint_notes_import is enabled' do
- it 'includes single endpoint diff notes importer' do
- project = create(:project)
- group = create(:group, projects: [project])
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: group)
-
- expect(worker.importers(project)).to contain_exactly(
- Gitlab::GithubImport::Importer::IssuesImporter,
- Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter
- )
- end
- end
-
- context 'when feature flag github_importer_single_endpoint_notes_import is disabled' do
- it 'includes default diff notes importer' do
- stub_feature_flags(github_importer_single_endpoint_notes_import: false)
-
- expect(worker.importers(project)).to contain_exactly(
- Gitlab::GithubImport::Importer::IssuesImporter,
- Gitlab::GithubImport::Importer::DiffNotesImporter
- )
- end
+ context 'when optional stage single_endpoint_notes_import is enabled' do
+ it 'includes single endpoint diff notes importer' do
+ expect(worker.importers(project)).to contain_exactly(
+ Gitlab::GithubImport::Importer::IssuesImporter,
+ Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter
+ )
end
end
- context 'when project group is missing' do
+ context 'when optional stage single_endpoint_notes_import is disabled' do
+ let(:single_endpoint_optional_stage) { false }
+
it 'includes default diff notes importer' do
expect(worker.importers(project)).to contain_exactly(
Gitlab::GithubImport::Importer::IssuesImporter,
diff --git a/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb
index adf20d24a7e..dbcf2083ec1 100644
--- a/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb
@@ -6,6 +6,13 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportNotesWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
+ let(:settings) { ::Gitlab::GithubImport::Settings.new(project) }
+ let(:single_endpoint_optional_stage) { true }
+
+ before do
+ settings.write({ single_endpoint_notes_import: single_endpoint_optional_stage })
+ end
+
describe '#import' do
it 'imports all the notes' do
client = double(:client)
@@ -33,37 +40,19 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportNotesWorker do
end
describe '#importers' do
- context 'when project group is present' do
- let_it_be(:project) { create(:project) }
- let_it_be(:group) { create(:group, projects: [project]) }
-
- context 'when feature flag github_importer_single_endpoint_notes_import is enabled' do
- it 'includes single endpoint mr and issue notes importers' do
- project = create(:project)
- group = create(:group, projects: [project])
-
- stub_feature_flags(github_importer_single_endpoint_notes_import: group)
-
- expect(worker.importers(project)).to contain_exactly(
- Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesImporter,
- Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
- )
- end
- end
-
- context 'when feature flag github_importer_single_endpoint_notes_import is disabled' do
- it 'includes default notes importer' do
- stub_feature_flags(github_importer_single_endpoint_notes_import: false)
-
- expect(worker.importers(project)).to contain_exactly(
- Gitlab::GithubImport::Importer::NotesImporter
- )
- end
+ context 'when settings single_endpoint_notes_import is enabled' do
+ it 'includes single endpoint mr and issue notes importers' do
+ expect(worker.importers(project)).to contain_exactly(
+ Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesImporter,
+ Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
+ )
end
end
- context 'when project group is missing' do
- it 'includes default diff notes importer' do
+ context 'when settings single_endpoint_notes_import is disabled' do
+ let(:single_endpoint_optional_stage) { false }
+
+ it 'includes default notes importer' do
expect(worker.importers(project)).to contain_exactly(
Gitlab::GithubImport::Importer::NotesImporter
)
diff --git a/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb
index 582cb76a6cd..24fca3b7c73 100644
--- a/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb
@@ -19,18 +19,69 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportRepositoryWorker do
end
context 'when the import succeeds' do
- it 'schedules the importing of the base data' do
- client = double(:client)
+ context 'with issues' do
+ it 'schedules the importing of the base data' do
+ client = double(:client)
+ options = { state: 'all', sort: 'number', direction: 'desc', per_page: '1' }
- expect_next_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) do |instance|
- expect(instance).to receive(:execute).and_return(true)
+ expect_next_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) do |instance|
+ expect(instance).to receive(:execute).and_return(true)
+ end
+
+ expect(InternalId).to receive(:exists?).and_return(false)
+ expect(client).to receive(:each_object).with(
+ :issues, project.import_source, options
+ ).and_return([{ number: 5 }].each)
+
+ expect(Issue).to receive(:track_project_iid!).with(project, 5)
+
+ expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker)
+ .to receive(:perform_async)
+ .with(project.id)
+
+ worker.import(client, project)
end
+ end
- expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker)
- .to receive(:perform_async)
- .with(project.id)
+ context 'without issues' do
+ it 'schedules the importing of the base data' do
+ client = double(:client)
+ options = { state: 'all', sort: 'number', direction: 'desc', per_page: '1' }
+
+ expect_next_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) do |instance|
+ expect(instance).to receive(:execute).and_return(true)
+ end
+
+ expect(InternalId).to receive(:exists?).and_return(false)
+ expect(client).to receive(:each_object).with(:issues, project.import_source, options).and_return([nil].each)
+ expect(Issue).not_to receive(:track_project_iid!)
- worker.import(client, project)
+ expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker)
+ .to receive(:perform_async)
+ .with(project.id)
+
+ worker.import(client, project)
+ end
+ end
+
+ context 'when retrying' do
+ it 'does not allocate internal ids' do
+ client = double(:client)
+
+ expect_next_instance_of(Gitlab::GithubImport::Importer::RepositoryImporter) do |instance|
+ expect(instance).to receive(:execute).and_return(true)
+ end
+
+ expect(InternalId).to receive(:exists?).and_return(true)
+ expect(client).not_to receive(:each_object)
+ expect(Issue).not_to receive(:track_project_iid!)
+
+ expect(Gitlab::GithubImport::Stage::ImportBaseDataWorker)
+ .to receive(:perform_async)
+ .with(project.id)
+
+ worker.import(client, project)
+ end
end
end
@@ -43,6 +94,10 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportRepositoryWorker do
expect(instance).to receive(:execute).and_raise(exception_class)
end
+ expect(InternalId).to receive(:exists?).and_return(false)
+ expect(client).to receive(:each_object).and_return([nil].each)
+ expect(Issue).not_to receive(:track_project_iid!)
+
expect(Gitlab::Import::ImportFailureService).to receive(:track)
.with(
project_id: project.id,
diff --git a/spec/workers/integrations/create_external_cross_reference_worker_spec.rb b/spec/workers/integrations/create_external_cross_reference_worker_spec.rb
index 61723f44aa5..8e586b90905 100644
--- a/spec/workers/integrations/create_external_cross_reference_worker_spec.rb
+++ b/spec/workers/integrations/create_external_cross_reference_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Integrations::CreateExternalCrossReferenceWorker do
include AfterNextHelpers
using RSpec::Parameterized::TableSyntax
- let_it_be(:project) { create(:jira_project, :repository) }
+ let_it_be(:project) { create(:project, :with_jira_integration, :repository) }
let_it_be(:author) { create(:user) }
let_it_be(:commit) { project.commit }
let_it_be(:issue) { create(:issue, project: project) }
diff --git a/spec/workers/merge_requests/delete_source_branch_worker_spec.rb b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
index 957adbbbd6e..fe677103fd0 100644
--- a/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
+++ b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
@@ -53,6 +53,48 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker do
worker.perform(merge_request.id, 'new-source-branch-sha', user.id)
end
end
+
+ context 'when delete service returns an error' do
+ let(:service_result) { ServiceResponse.error(message: 'placeholder') }
+
+ it 'tracks the exception' do
+ expect_next_instance_of(::Branches::DeleteService) do |instance|
+ expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
+ end
+
+ expect(service_result).to receive(:track_exception).and_call_original
+
+ worker.perform(merge_request.id, sha, user.id)
+ end
+
+ context 'when track_delete_source_errors is disabled' do
+ before do
+ stub_feature_flags(track_delete_source_errors: false)
+ end
+
+ it 'does not track the exception' do
+ expect_next_instance_of(::Branches::DeleteService) do |instance|
+ expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
+ end
+
+ expect(service_result).not_to receive(:track_exception)
+
+ worker.perform(merge_request.id, sha, user.id)
+ end
+ end
+
+ it 'still retargets the merge request' do
+ expect_next_instance_of(::Branches::DeleteService) do |instance|
+ expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
+ end
+
+ expect_next_instance_of(::MergeRequests::RetargetChainService) do |instance|
+ expect(instance).to receive(:execute).with(merge_request)
+ end
+
+ worker.perform(merge_request.id, sha, user.id)
+ end
+ end
end
it_behaves_like 'an idempotent worker' do
diff --git a/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb b/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb
deleted file mode 100644
index 0a896d864b7..00000000000
--- a/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Namespaces::OnboardingIssueCreatedWorker, '#perform' do
- let_it_be(:issue) { create(:issue) }
-
- let(:namespace) { issue.project.namespace }
-
- it_behaves_like 'records an onboarding progress action', :issue_created do
- subject { described_class.new.perform(namespace.id) }
- end
-
- it_behaves_like 'does not record an onboarding progress action' do
- subject { described_class.new.perform(nil) }
- end
-
- it_behaves_like 'an idempotent worker' do
- let(:job_args) { [namespace.id] }
-
- it 'sets the onboarding progress action' do
- Onboarding::Progress.onboard(namespace)
-
- subject
-
- expect(Onboarding::Progress.completed?(namespace, :issue_created)).to eq(true)
- end
- end
-end
diff --git a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
deleted file mode 100644
index 6d69ccb50bd..00000000000
--- a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Namespaces::OnboardingPipelineCreatedWorker, '#perform' do
- let_it_be(:ci_pipeline) { create(:ci_pipeline) }
-
- it_behaves_like 'records an onboarding progress action', :pipeline_created do
- let(:namespace) { ci_pipeline.project.namespace }
-
- subject { described_class.new.perform(ci_pipeline.project.namespace_id) }
- end
-
- it_behaves_like 'does not record an onboarding progress action' do
- subject { described_class.new.perform(nil) }
- end
-end
diff --git a/spec/workers/namespaces/onboarding_progress_worker_spec.rb b/spec/workers/namespaces/onboarding_progress_worker_spec.rb
deleted file mode 100644
index 76ac078ddcf..00000000000
--- a/spec/workers/namespaces/onboarding_progress_worker_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Namespaces::OnboardingProgressWorker, '#perform' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:action) { 'git_pull' }
-
- it_behaves_like 'records an onboarding progress action', :git_pull do
- include_examples 'an idempotent worker' do
- subject { described_class.new.perform(namespace.id, action) }
- end
- end
-
- it_behaves_like 'does not record an onboarding progress action' do
- subject { described_class.new.perform(namespace.id, nil) }
- end
-
- it_behaves_like 'does not record an onboarding progress action' do
- subject { described_class.new.perform(nil, action) }
- end
-end
diff --git a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
deleted file mode 100644
index 14428c0ecb8..00000000000
--- a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Namespaces::OnboardingUserAddedWorker, '#perform' do
- let_it_be(:namespace) { create(:group) }
-
- subject { described_class.new.perform(namespace.id) }
-
- it_behaves_like 'records an onboarding progress action', :user_added
-end
diff --git a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
index 11f2501cbe3..d8c60932d92 100644
--- a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
+++ b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Namespaces::PruneAggregationSchedulesWorker, '#perform', :clean_g
include ExclusiveLeaseHelpers
let(:namespaces) { create_list(:namespace, 5, :with_aggregation_schedule) }
- let(:timeout) { Namespace::AggregationSchedule::DEFAULT_LEASE_TIMEOUT }
+ let(:timeout) { Namespace::AggregationSchedule.default_lease_timeout }
subject(:worker) { described_class.new }
diff --git a/spec/workers/onboarding/issue_created_worker_spec.rb b/spec/workers/onboarding/issue_created_worker_spec.rb
new file mode 100644
index 00000000000..70a0156d444
--- /dev/null
+++ b/spec/workers/onboarding/issue_created_worker_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Onboarding::IssueCreatedWorker, '#perform' do
+ let_it_be(:issue) { create(:issue) }
+
+ let(:namespace) { issue.project.namespace }
+
+ it_behaves_like 'records an onboarding progress action', :issue_created do
+ subject { described_class.new.perform(namespace.id) }
+ end
+
+ it_behaves_like 'does not record an onboarding progress action' do
+ subject { described_class.new.perform(nil) }
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [namespace.id] }
+
+ it 'sets the onboarding progress action' do
+ Onboarding::Progress.onboard(namespace)
+
+ subject
+
+ expect(Onboarding::Progress.completed?(namespace, :issue_created)).to eq(true)
+ end
+ end
+end
diff --git a/spec/workers/onboarding/pipeline_created_worker_spec.rb b/spec/workers/onboarding/pipeline_created_worker_spec.rb
new file mode 100644
index 00000000000..75bdea28eef
--- /dev/null
+++ b/spec/workers/onboarding/pipeline_created_worker_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Onboarding::PipelineCreatedWorker, '#perform' do
+ let_it_be(:ci_pipeline) { create(:ci_pipeline) }
+
+ it_behaves_like 'records an onboarding progress action', :pipeline_created do
+ let(:namespace) { ci_pipeline.project.namespace }
+
+ subject { described_class.new.perform(ci_pipeline.project.namespace_id) }
+ end
+
+ it_behaves_like 'does not record an onboarding progress action' do
+ subject { described_class.new.perform(nil) }
+ end
+end
diff --git a/spec/workers/onboarding/progress_worker_spec.rb b/spec/workers/onboarding/progress_worker_spec.rb
new file mode 100644
index 00000000000..bbf4875069e
--- /dev/null
+++ b/spec/workers/onboarding/progress_worker_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Onboarding::ProgressWorker, '#perform' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:action) { 'git_pull' }
+
+ it_behaves_like 'records an onboarding progress action', :git_pull do
+ include_examples 'an idempotent worker' do
+ subject { described_class.new.perform(namespace.id, action) }
+ end
+ end
+
+ it_behaves_like 'does not record an onboarding progress action' do
+ subject { described_class.new.perform(namespace.id, nil) }
+ end
+
+ it_behaves_like 'does not record an onboarding progress action' do
+ subject { described_class.new.perform(nil, action) }
+ end
+end
diff --git a/spec/workers/onboarding/user_added_worker_spec.rb b/spec/workers/onboarding/user_added_worker_spec.rb
new file mode 100644
index 00000000000..6dbd875c93b
--- /dev/null
+++ b/spec/workers/onboarding/user_added_worker_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Onboarding::UserAddedWorker, '#perform' do
+ let_it_be(:namespace) { create(:group) }
+
+ subject { described_class.new.perform(namespace.id) }
+
+ it_behaves_like 'records an onboarding progress action', :user_added
+end
diff --git a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
index 9272e26a34f..b9c27c54fa1 100644
--- a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
+++ b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
@@ -126,6 +126,107 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do
{ type: :namespace, id: 3 }
]
+ it_behaves_like 'clears caches with',
+ event_class: PagesDomains::PagesDomainDeletedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ domain: 'somedomain.com'
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: PagesDomains::PagesDomainUpdatedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ domain: 'somedomain.com'
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: PagesDomains::PagesDomainCreatedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ domain: 'somedomain.com'
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 }
+ ]
+
+ context 'when project attributes change' do
+ Projects::ProjectAttributesChangedEvent::PAGES_RELATED_ATTRIBUTES.each do |attribute|
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectAttributesChangedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ attributes: [attribute]
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 }
+ ]
+ end
+
+ it 'does not clear the cache when the attributes is not pages related' do
+ event = Projects::ProjectAttributesChangedEvent.new(
+ data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ attributes: ['unknown']
+ }
+ )
+
+ expect(described_class).not_to receive(:clear_cache)
+
+ ::Gitlab::EventStore.publish(event)
+ end
+ end
+
+ context 'when project features change' do
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectFeaturesChangedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ features: ["pages_access_level"]
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 }
+ ]
+
+ it 'does not clear the cache when the features is not pages related' do
+ event = Projects::ProjectFeaturesChangedEvent.new(
+ data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ features: ['unknown']
+ }
+ )
+
+ expect(described_class).not_to receive(:clear_cache)
+
+ ::Gitlab::EventStore.publish(event)
+ end
+ end
+
context 'when namespace based cache keys are duplicated' do
# de-dups namespace cache keys
it_behaves_like 'clears caches with',
diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb
index a445db3a276..01c44399b0c 100644
--- a/spec/workers/process_commit_worker_spec.rb
+++ b/spec/workers/process_commit_worker_spec.rb
@@ -120,34 +120,6 @@ RSpec.describe ProcessCommitWorker do
worker.close_issues(project, user, user, commit, [issue])
end.to change(Issues::CloseWorker.jobs, :size).by(1)
end
-
- context 'when process_issue_closure_in_background flag is disabled' do
- before do
- stub_feature_flags(process_issue_closure_in_background: false)
- end
-
- context 'when the user can update the issues' do
- it 'closes the issues' do
- worker.close_issues(project, user, user, commit, [issue])
-
- issue.reload
-
- expect(issue.closed?).to eq(true)
- end
- end
-
- context 'when the user can not update the issues' do
- it 'does not close the issues' do
- other_user = create(:user)
-
- worker.close_issues(project, other_user, other_user, commit, [issue])
-
- issue.reload
-
- expect(issue.closed?).to eq(false)
- end
- end
- end
end
describe '#update_issue_metrics', :clean_gitlab_redis_cache do
diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb
index 30c85464452..3c807ef9ffd 100644
--- a/spec/workers/project_cache_worker_spec.rb
+++ b/spec/workers/project_cache_worker_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe ProjectCacheWorker do
context 'with an existing project' do
before do
lease_key = "namespace:namespaces_root_statistics:#{project.namespace_id}"
- stub_exclusive_lease_taken(lease_key, timeout: Namespace::AggregationSchedule::DEFAULT_LEASE_TIMEOUT)
+ stub_exclusive_lease_taken(lease_key, timeout: Namespace::AggregationSchedule.default_lease_timeout)
end
it 'refreshes the method caches' do
@@ -74,8 +74,8 @@ RSpec.describe ProjectCacheWorker do
context 'with plain readme' do
it 'refreshes the method caches' do
- allow(MarkupHelper).to receive(:gitlab_markdown?).and_return(false)
- allow(MarkupHelper).to receive(:plain?).and_return(true)
+ allow(Gitlab::MarkupHelper).to receive(:gitlab_markdown?).and_return(false)
+ allow(Gitlab::MarkupHelper).to receive(:plain?).and_return(true)
expect_any_instance_of(Repository).to receive(:refresh_method_caches)
.with(%i(readme))
diff --git a/spec/workers/project_destroy_worker_spec.rb b/spec/workers/project_destroy_worker_spec.rb
index 0b0543a5089..25508928bbf 100644
--- a/spec/workers/project_destroy_worker_spec.rb
+++ b/spec/workers/project_destroy_worker_spec.rb
@@ -4,11 +4,7 @@ require 'spec_helper'
RSpec.describe ProjectDestroyWorker do
let(:project) { create(:project, :repository, pending_delete: true) }
- let(:path) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path_to_repo
- end
- end
+ let!(:repository) { project.repository.raw }
subject { described_class.new }
@@ -17,7 +13,7 @@ RSpec.describe ProjectDestroyWorker do
subject.perform(project.id, project.first_owner.id, {})
expect(Project.all).not_to include(project)
- expect(Dir.exist?(path)).to be_falsey
+ expect(repository).not_to exist
end
it 'does not raise error when project could not be found' do
diff --git a/spec/workers/repository_check/single_repository_worker_spec.rb b/spec/workers/repository_check/single_repository_worker_spec.rb
index 205d7c08f54..dbb24cc047e 100644
--- a/spec/workers/repository_check/single_repository_worker_spec.rb
+++ b/spec/workers/repository_check/single_repository_worker_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
it 'creates missing wikis' do
project = create(:project, :wiki_enabled)
- TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path)
+ project.wiki.repository.raw.remove
subject.perform(project.id)
@@ -77,8 +77,8 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
it 'does not create a wiki if the main repo does not exist at all' do
project = create(:project, :repository)
- TestEnv.rm_storage_dir(project.repository_storage, project.path)
- TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path)
+ project.repository.raw.remove
+ project.wiki.repository.raw.remove
subject.perform(project.id)
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 9c46b1e2a87..85dee935001 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe RepositoryForkWorker do
context 'project ID, storage and repo paths passed' do
def perform!
- subject.perform(forked_project.id, TestEnv.repos_path, project.disk_path)
+ subject.perform(forked_project.id, 'repos/path', project.disk_path)
end
it_behaves_like 'RepositoryForkWorker performing'
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index 846b4455bf9..10c22b736d2 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe RunPipelineScheduleWorker do
describe '#perform' do
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:user) { create(:user) }
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) }
diff --git a/tooling/config/CODEOWNERS.yml b/tooling/config/CODEOWNERS.yml
index 6b24134ea17..0fb336f3857 100644
--- a/tooling/config/CODEOWNERS.yml
+++ b/tooling/config/CODEOWNERS.yml
@@ -75,7 +75,6 @@
- '**/merge_requests/**'
- '/config/feature_flags/**/*'
- '/ee/app/services/audit_events/**/*'
- - '/ee/config/feature_flags/development/auditor_group_runner_access.yml'
- '/ee/spec/services/audit_events/**/*'
- '/ee/spec/services/ci/*'
- '/ee/spec/services/personal_access_tokens/*'
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index 1d052bf6bbd..e98ae156246 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -152,7 +152,7 @@ module Tooling
%r{\A((ee|jh)/)?spec/migrations} => :database,
%r{\A((ee|jh)/)?spec/} => :backend,
%r{\A((ee|jh)/)?vendor/} => :backend,
- %r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
+ %r{\A(Gemfile.*|Rakefile)\z} => :backend,
%r{\A[A-Z_]+_VERSION\z} => :backend,
%r{\A\.rubocop(_todo)?\.yml\z} => :backend,
%r{\A\.rubocop_todo/.*\.yml\z} => :backend,
diff --git a/tooling/danger/specs.rb b/tooling/danger/specs.rb
index 36ec83dd7d2..6832f7d10d1 100644
--- a/tooling/danger/specs.rb
+++ b/tooling/danger/specs.rb
@@ -6,14 +6,45 @@ module Tooling
SPEC_FILES_REGEX = 'spec/'
EE_PREFIX = 'ee/'
MATCH_WITH_ARRAY_REGEX = /(?<to>to\(?\s*)(?<matcher>match|eq)(?<expectation>[( ]?\[[^\]]+)/.freeze
- SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT
+ MATCH_WITH_ARRAY_REPLACEMENT = '\k<to>match_array\k<expectation>'
+
+ PROJECT_FACTORIES = %w[
+ :project
+ :project_empty_repo
+ :forked_project_with_submodules
+ :project_with_design
+ ].freeze
+
+ PROJECT_FACTORY_REGEX = /
+ ^\+? # Start of the line, which may or may not have a `+`
+ (?<head>\s*) # 0-many leading whitespace captured in a group named head
+ let!? # Literal `let` which may or may not end in `!`
+ (?<tail> # capture group named tail
+ \([^)]+\) # Two parenthesis with any non-parenthesis characters between them
+ \s*\{\s* # Opening curly brace surrounded by 0-many whitespace characters
+ create\( # literal
+ (?:#{PROJECT_FACTORIES.join('|')}) # Any of the project factory names
+ \W # Non-word character, avoid matching factories like :project_authorization
+ ) # end capture group named tail
+ /x.freeze
+
+ PROJECT_FACTORY_REPLACEMENT = '\k<head>let_it_be\k<tail>'
+ SUGGESTION_MARKDOWN = <<~SUGGESTION_MARKDOWN
```suggestion
%<suggested_line>s
```
+ SUGGESTION_MARKDOWN
+ MATCH_WITH_ARRAY_SUGGESTION = <<~SUGGEST_COMMENT
If order of the result is not important, please consider using `match_array` to avoid flakiness.
SUGGEST_COMMENT
+ PROJECT_FACTORY_SUGGESTION = <<~SUGGEST_COMMENT
+ Project creations are very slow. Use `let_it_be`, `build` or `build_stubbed` if possible.
+ See [testing best practices](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#optimize-factory-usage)
+ for background information and alternative options.
+ SUGGEST_COMMENT
+
def changed_specs_files(ee: :include)
changed_files = helper.all_changed_files
folder_prefix =
@@ -30,29 +61,58 @@ module Tooling
end
def add_suggestions_for_match_with_array(filename)
- added_lines = added_line_matching_match_with_array(filename)
+ add_suggestion(
+ filename,
+ MATCH_WITH_ARRAY_REGEX,
+ MATCH_WITH_ARRAY_REPLACEMENT,
+ MATCH_WITH_ARRAY_SUGGESTION
+ )
+ end
+
+ def add_suggestions_for_project_factory_usage(filename)
+ add_suggestion(
+ filename,
+ PROJECT_FACTORY_REGEX,
+ PROJECT_FACTORY_REPLACEMENT,
+ PROJECT_FACTORY_SUGGESTION
+ )
+ end
+
+ private
+
+ def added_lines_matching(filename, regex)
+ helper.changed_lines(filename).grep(/\A\+ /).grep(regex)
+ end
+
+ def add_suggestion(filename, regex, replacement, comment_text)
+ added_lines = added_lines_matching(filename, regex)
return if added_lines.empty?
spec_file_lines = project_helper.file_lines(filename)
added_lines.each_with_object([]) do |added_line, processed_line_numbers|
line_number = find_line_number(spec_file_lines, added_line.delete_prefix('+'), exclude_indexes: processed_line_numbers)
+ next unless line_number
+
processed_line_numbers << line_number
- markdown(format(SUGGEST_MR_COMMENT, suggested_line: spec_file_lines[line_number].gsub(MATCH_WITH_ARRAY_REGEX, '\k<to>match_array\k<expectation>')), file: filename, line: line_number.succ)
+ text = format(comment(comment_text), suggested_line: spec_file_lines[line_number].gsub(regex, replacement))
+ markdown(text, file: filename, line: line_number.succ)
end
end
- def added_line_matching_match_with_array(filename)
- helper.changed_lines(filename).grep(/\A\+ /).grep(MATCH_WITH_ARRAY_REGEX)
+ def comment(comment_text)
+ <<~COMMENT_BODY.chomp
+ #{SUGGESTION_MARKDOWN}
+ #{comment_text}
+ COMMENT_BODY
end
- private
-
def find_line_number(file_lines, searched_line, exclude_indexes: [])
- file_lines.each_with_index do |file_line, index|
- next if exclude_indexes.include?(index)
- break index if file_line == searched_line
+ _, index = file_lines.each_with_index.find do |file_line, index|
+ file_line == searched_line && !exclude_indexes.include?(index)
end
+
+ index
end
end
end
diff --git a/tooling/graphql/docs/helper.rb b/tooling/graphql/docs/helper.rb
index a76773ed28d..f25e69a1e2f 100644
--- a/tooling/graphql/docs/helper.rb
+++ b/tooling/graphql/docs/helper.rb
@@ -55,9 +55,9 @@ module Tooling
def auto_generated_comment
<<-MD.strip_heredoc
---
- stage: Ecosystem
+ stage: Manage
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
+ info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
<!---
diff --git a/vendor/gems/attr_encrypted/.gitignore b/vendor/gems/attr_encrypted/.gitignore
new file mode 100644
index 00000000000..b25958999b0
--- /dev/null
+++ b/vendor/gems/attr_encrypted/.gitignore
@@ -0,0 +1,5 @@
+.bundle
+.DS_Store
+.ruby-version
+pkg
+coverage
diff --git a/vendor/gems/attr_encrypted/.gitlab-ci.yml b/vendor/gems/attr_encrypted/.gitlab-ci.yml
new file mode 100644
index 00000000000..42b2b9e1e01
--- /dev/null
+++ b/vendor/gems/attr_encrypted/.gitlab-ci.yml
@@ -0,0 +1,26 @@
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+
+default:
+ image: "ruby:${RUBY_VERSION}"
+
+rspec:
+ cache:
+ key: attr_encrypted-ruby
+ paths:
+ - vendor/gems/attr_encrypted/vendor/ruby
+ before_script:
+ - cd vendor/gems/attr_encrypted
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-document # Bundler is not installed with the image
+ - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby
+ - bundle config set with 'development' # This is set to 'deployment' otherwise
+ - bundle config set --local frozen 'true' # Disallow Gemfile.lock changes on CI
+ - bundle config # Show bundler configuration
+ - bundle install -j $(nproc)
+ script:
+ - bundle exec rake test
+ parallel:
+ matrix:
+ - RUBY_VERSION: ["2.7", "3.0"]
diff --git a/vendor/gems/attr_encrypted/CHANGELOG.md b/vendor/gems/attr_encrypted/CHANGELOG.md
new file mode 100644
index 00000000000..52ef721b311
--- /dev/null
+++ b/vendor/gems/attr_encrypted/CHANGELOG.md
@@ -0,0 +1,98 @@
+# attr_encrypted #
+
+## 3.1.0 ##
+* Added: Abitilty to encrypt empty values. (@tamird)
+* Added: MIT license
+* Added: MRI 2.5.x support (@saghaulor)
+* Fixed: No long generate IV and salt if value is empty, unless :allow_empty_value options is passed. (@saghaulor)
+* Fixed: Only generate IV and salt when :if and :unless options evaluate such that encryption should be performed. (@saghaulor)
+* Fixed: Private methods are correctly evaluated as options. (@saghaulor)
+* Fixed: Mark virtual attributes for Rails 5.x compatibility (@grosser)
+* Fixed: Only check empty on strings, allows for encrypting non-string type objects
+* Fixed: Fixed how accessors for db columns are defined in the ActiveRecord adapter, preventing premature definition. (@nagachika)
+
+## 3.0.3 ##
+* Fixed: attr_was would decrypt the attribute upon every call. This is inefficient and introduces problems when the options change between decrypting an old value and encrypting a new value; for example, when rotating the encryption key. As such, the new approach caches the decrypted value of the old encrypted value such that the old options are no longer needed. (@johnny-lai) (@saghaulor)
+
+## 3.0.2 ##
+* Changed: Removed alias_method_chain for compatibility with Rails v5.x (@grosser)
+* Changed: Updated Travis build matrix to include Rails 5. (@saghaulor) (@connorshea)
+* Changed: Removed `.silence_stream` from tests as it has been removed from Rails 5. (@sblackstone)
+
+## 3.0.1 ##
+* Fixed: attr_was method no longer calls undefined methods. (@saghaulor)
+
+## 3.0.0 ##
+* Changed: Updated gemspec to use Encryptor v3.0.0. (@saghaulor)
+* Changed: Updated README with instructions related to moving from v2.0.0 to v3.0.0. (@saghaulor)
+* Fixed: ActiveModel::Dirty methods in the ActiveRecord adapter. (@saghaulor)
+
+## 2.0.0 ##
+* Added: Now using Encryptor v2.0.0 (@saghaulor)
+* Added: Options are copied to the instance. (@saghaulor)
+* Added: Operation option is set during encryption/decryption to allow options to be evaluated in the context of the current operation. (@saghaulor)
+* Added: IV and salt can be conditionally encoded. (@saghaulor)
+* Added: Changelog! (@saghaulor)
+* Changed: attr_encrypted no longer extends object, to use with PORO extend your class, all supported ORMs are already extended. (@saghaulor)
+* Changed: Salt is now generated with more entropy. (@saghaulor)
+* Changed: The default algorithm is now `aes-256-gcm`. (@saghaulor)
+* Changed: The default mode is now `:per_attribute_iv`' (@saghaulor)
+* Changed: Extracted class level default options hash to a private method. (@saghaulor)
+* Changed: Dynamic finders only work with `:single_iv_and_salt` mode. (@saghaulor)
+* Changed: Updated documentation to include v2.0.0 changes and 'things to consider' section. (@saghaulor)
+* Fixed: All options are evaluated correctly. (@saghaulor)
+* Fixed: IV is generated for every encryption operation. (@saghaulor)
+* Deprecated: `:single_iv_and_salt` and `:per_attribute_iv_and_salt` modes are deprecated and will be removed in the next major release. (@saghaulor)
+* Deprecated: Dynamic finders via `method_missing` is deprecated and will be removed in the next major release. (@saghaulor)
+* Removed: Support for Ruby < 2.x (@saghaulor)
+* Removed: Support for Rails < 3.x (@saghaulor)
+* Removed: Unnecessary use of `alias_method` from ActiveRecord adapter. (@saghaulor)
+
+## 1.4.0 ##
+* Added: ActiveModel::Dirty#attribute_was (@saghaulor)
+* Added: ActiveModel::Dirty#attribute_changed? (@mwean)
+
+## 1.3.5 ##
+* Changed: Fixed gemspec to explicitly depend on Encryptor v1.3.0 (@saghaulor)
+* Fixed: Evaluate `:mode` option as a symbol or proc. (@cheynewallace)
+
+## 1.3.4 ##
+* Added: ActiveRecord::Base.reload support. (@rcook)
+* Fixed: ActiveRecord adapter no longer forces attribute hashes to be string-keyed. (@tamird)
+* Fixed: Mass assignment protection in ActiveRecord 4. (@tamird)
+* Changed: Now using rubygems over https. (@tamird)
+* Changed: Let ActiveRecord define attribute methods. (@saghaulor)
+
+## 1.3.3 ##
+* Added: Alias attr_encryptor and attr_encrpted. (@Billy Monk)
+
+## 1.3.2 ##
+* Fixed: Bug regarding strong parameters. (@S. Brent Faulkner)
+* Fixed: Bug regarding loading per instance IV and salt. (@S. Brent Faulkner)
+* Fixed: Bug regarding assigning nil. (@S. Brent Faulkner)
+* Added: Support for protected attributes. (@S. Brent Faulkner)
+* Added: Support for ActiveRecord 4. (@S. Brent Faulkner)
+
+## 1.3.1 ##
+* Added: Support for Rails 2.3.x and 3.1.x. (@S. Brent Faulkner)
+
+## 1.3.0 ##
+* Fixed: Serialization bug. (@Billy Monk)
+* Added: Support for :per_attribute_iv_and_salt mode. (@rcook)
+* Fixed: Added dependencies to gemspec. (@jmazzi)
+
+## 1.2.1 ##
+* Added: Force encoding when not marshaling. (@mosaicxm)
+* Fixed: Issue specifying multiple attributes on the same line. (@austintaylor)
+* Added: Typecasting to String before encryption (@shuber)
+* Added: `"#{attribute}?"` method. (@shuber)
+
+## 1.2.0 ##
+* Changed: General code refactoring (@shuber)
+
+## 1.1.2 ##
+* No significant changes
+
+## 1.1.1 ##
+* Changled: Updated README. (@shuber)
+* Added: `before_type_cast` alias to ActiveRecord adapter. (@shuber)
diff --git a/vendor/gems/attr_encrypted/Gemfile b/vendor/gems/attr_encrypted/Gemfile
new file mode 100644
index 00000000000..fa75df15632
--- /dev/null
+++ b/vendor/gems/attr_encrypted/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/vendor/gems/attr_encrypted/Gemfile.lock b/vendor/gems/attr_encrypted/Gemfile.lock
new file mode 100644
index 00000000000..1094e6da3fc
--- /dev/null
+++ b/vendor/gems/attr_encrypted/Gemfile.lock
@@ -0,0 +1,155 @@
+PATH
+ remote: .
+ specs:
+ attr_encrypted (3.2.4)
+ encryptor (~> 3.0.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionpack (6.1.7)
+ actionview (= 6.1.7)
+ activesupport (= 6.1.7)
+ rack (~> 2.0, >= 2.0.9)
+ rack-test (>= 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
+ actionview (6.1.7)
+ activesupport (= 6.1.7)
+ builder (~> 3.1)
+ erubi (~> 1.4)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
+ activemodel (6.1.7)
+ activesupport (= 6.1.7)
+ activerecord (6.1.7)
+ activemodel (= 6.1.7)
+ activesupport (= 6.1.7)
+ activesupport (6.1.7)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
+ addressable (2.8.1)
+ public_suffix (>= 2.0.2, < 6.0)
+ bcrypt (3.1.18)
+ bcrypt-ruby (3.1.5)
+ bcrypt (>= 3.1.3)
+ builder (3.2.4)
+ codeclimate-test-reporter (0.6.0)
+ simplecov (>= 0.7.1, < 1.0.0)
+ concurrent-ruby (1.1.10)
+ crass (1.0.6)
+ data_objects (0.10.17)
+ addressable (~> 2.1)
+ datamapper (1.2.0)
+ dm-aggregates (~> 1.2.0)
+ dm-constraints (~> 1.2.0)
+ dm-core (~> 1.2.0)
+ dm-migrations (~> 1.2.0)
+ dm-serializer (~> 1.2.0)
+ dm-timestamps (~> 1.2.0)
+ dm-transactions (~> 1.2.0)
+ dm-types (~> 1.2.0)
+ dm-validations (~> 1.2.0)
+ dm-aggregates (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-constraints (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-core (1.2.1)
+ addressable (~> 2.3)
+ dm-do-adapter (1.2.0)
+ data_objects (~> 0.10.6)
+ dm-core (~> 1.2.0)
+ dm-migrations (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-serializer (1.2.2)
+ dm-core (~> 1.2.0)
+ fastercsv (~> 1.5)
+ json (~> 1.6)
+ json_pure (~> 1.6)
+ multi_json (~> 1.0)
+ dm-sqlite-adapter (1.2.0)
+ dm-do-adapter (~> 1.2.0)
+ do_sqlite3 (~> 0.10.6)
+ dm-timestamps (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-transactions (1.2.0)
+ dm-core (~> 1.2.0)
+ dm-types (1.2.2)
+ bcrypt-ruby (~> 3.0)
+ dm-core (~> 1.2.0)
+ fastercsv (~> 1.5)
+ json (~> 1.6)
+ multi_json (~> 1.0)
+ stringex (~> 1.4)
+ uuidtools (~> 2.1)
+ dm-validations (1.2.0)
+ dm-core (~> 1.2.0)
+ do_sqlite3 (0.10.17)
+ data_objects (= 0.10.17)
+ docile (1.4.0)
+ encryptor (3.0.0)
+ erubi (1.11.0)
+ fastercsv (1.5.5)
+ i18n (1.12.0)
+ concurrent-ruby (~> 1.0)
+ json (1.8.6)
+ json_pure (1.8.6)
+ loofah (2.19.0)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ mini_portile2 (2.8.0)
+ minitest (5.16.3)
+ multi_json (1.15.0)
+ nokogiri (1.13.8)
+ mini_portile2 (~> 2.8.0)
+ racc (~> 1.4)
+ public_suffix (5.0.0)
+ racc (1.6.0)
+ rack (2.2.4)
+ rack-test (2.0.2)
+ rack (>= 1.3)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.4.3)
+ loofah (~> 2.3)
+ rake (13.0.6)
+ sequel (5.60.1)
+ simplecov (0.21.2)
+ docile (~> 1.1)
+ simplecov-html (~> 0.11)
+ simplecov_json_formatter (~> 0.1)
+ simplecov-html (0.12.3)
+ simplecov-rcov (0.3.1)
+ simplecov (>= 0.4.1)
+ simplecov_json_formatter (0.1.4)
+ sqlite3 (1.5.0)
+ mini_portile2 (~> 2.8.0)
+ stringex (1.5.1)
+ tzinfo (2.0.5)
+ concurrent-ruby (~> 1.0)
+ uuidtools (2.2.0)
+ zeitwerk (2.6.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ actionpack (~> 6.1)
+ activerecord (~> 6.1)
+ attr_encrypted!
+ codeclimate-test-reporter (<= 0.6.0)
+ datamapper
+ dm-sqlite-adapter
+ minitest
+ rake
+ sequel
+ simplecov
+ simplecov-rcov
+ sqlite3
+
+BUNDLED WITH
+ 2.3.22
diff --git a/vendor/gems/attr_encrypted/MIT-LICENSE b/vendor/gems/attr_encrypted/MIT-LICENSE
new file mode 100644
index 00000000000..07f53f78f58
--- /dev/null
+++ b/vendor/gems/attr_encrypted/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Sean Huber - shuber@huberry.com
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/vendor/gems/attr_encrypted/README.md b/vendor/gems/attr_encrypted/README.md
new file mode 100644
index 00000000000..87ac7219a92
--- /dev/null
+++ b/vendor/gems/attr_encrypted/README.md
@@ -0,0 +1,466 @@
+## Maintainer(s) wanted!!!
+
+**If you have an interest in maintaining this project... please see https://github.com/attr-encrypted/attr_encrypted/issues/379**
+
+# attr_encrypted
+
+[![Build Status](https://secure.travis-ci.org/attr-encrypted/attr_encrypted.svg)](https://travis-ci.org/attr-encrypted/attr_encrypted) [![Test Coverage](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/coverage.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted/coverage) [![Code Climate](https://codeclimate.com/github/attr-encrypted/attr_encrypted/badges/gpa.svg)](https://codeclimate.com/github/attr-encrypted/attr_encrypted) [![Gem Version](https://badge.fury.io/rb/attr_encrypted.svg)](https://badge.fury.io/rb/attr_encrypted) [![security](https://hakiri.io/github/attr-encrypted/attr_encrypted/master.svg)](https://hakiri.io/github/attr-encrypted/attr_encrypted/master)
+
+Generates attr_accessors that transparently encrypt and decrypt attributes.
+
+It works with ANY class, however, you get a few extra features when you're using it with `ActiveRecord`, `DataMapper`, or `Sequel`.
+
+
+## Installation
+
+Add attr_encrypted to your gemfile:
+
+```ruby
+ gem "attr_encrypted", "~> 3.1.0"
+```
+
+Then install the gem:
+
+```bash
+ bundle install
+```
+
+## Usage
+
+If you're using an ORM like `ActiveRecord`, `DataMapper`, or `Sequel`, using attr_encrypted is easy:
+
+```ruby
+ class User
+ attr_encrypted :ssn, key: 'This is a key that is 256 bits!!'
+ end
+```
+
+If you're using a PORO, you have to do a little bit more work by extending the class:
+
+```ruby
+ class User
+ extend AttrEncrypted
+ attr_accessor :name
+ attr_encrypted :ssn, key: 'This is a key that is 256 bits!!'
+
+ def load
+ # loads the stored data
+ end
+
+ def save
+ # saves the :name and :encrypted_ssn attributes somewhere (e.g. filesystem, database, etc)
+ end
+ end
+
+ user = User.new
+ user.ssn = '123-45-6789'
+ user.ssn # returns the unencrypted object ie. '123-45-6789'
+ user.encrypted_ssn # returns the encrypted version of :ssn
+ user.save
+
+ user = User.load
+ user.ssn # decrypts :encrypted_ssn and returns '123-45-6789'
+```
+
+### Encrypt/decrypt attribute class methods
+
+Two class methods are available for each attribute: `User.encrypt_email` and `User.decrypt_email`. They accept as arguments the same options that the `attr_encrypted` class method accepts. For example:
+
+```ruby
+ key = SecureRandom.random_bytes(32)
+ iv = SecureRandom.random_bytes(12)
+ encrypted_email = User.encrypt_email('test@test.com', iv: iv, key: key)
+ email = User.decrypt_email(encrypted_email, iv: iv, key: key)
+```
+
+The `attr_encrypted` class method is also aliased as `attr_encryptor` to conform to Ruby's `attr_` naming conventions. I should have called this project `attr_encryptor` but it was too late when I realized it ='(.
+
+### attr_encrypted with database persistence
+
+By default, `attr_encrypted` uses the `:per_attribute_iv` encryption mode. This mode requires a column to store your cipher text and a column to store your IV (initialization vector).
+
+Create or modify the table that your model uses to add a column with the `encrypted_` prefix (which can be modified, see below), e.g. `encrypted_ssn` via a migration like the following:
+
+```ruby
+ create_table :users do |t|
+ t.string :name
+ t.string :encrypted_ssn
+ t.string :encrypted_ssn_iv
+ t.timestamps
+ end
+```
+
+You can use a string or binary column type. (See the encode option section below for more info)
+
+If you use the same key for each record, add a unique index on the IV. Repeated IVs with AES-GCM (the default algorithm) allow an attacker to recover the key.
+
+```ruby
+ add_index :users, :encrypted_ssn_iv, unique: true
+```
+
+### Specifying the encrypted attribute name
+
+By default, the encrypted attribute name is `encrypted_#{attribute}` (e.g. `attr_encrypted :email` would create an attribute named `encrypted_email`). So, if you're storing the encrypted attribute in the database, you need to make sure the `encrypted_#{attribute}` field exists in your table. You have a couple of options if you want to name your attribute or db column something else, see below for more details.
+
+
+## attr_encrypted options
+
+#### Options are evaluated
+All options will be evaluated at the instance level. If you pass in a symbol it will be passed as a message to the instance of your class. If you pass a proc or any object that responds to `:call` it will be called. You can pass in the instance of your class as an argument to the proc. Anything else will be returned. For example:
+
+##### Symbols representing instance methods
+
+Here is an example class that uses an instance method to determines the encryption key to use.
+
+```ruby
+ class User
+ attr_encrypted :email, key: :encryption_key
+
+ def encryption_key
+ # does some fancy logic and returns an encryption key
+ end
+ end
+```
+
+
+##### Procs
+
+Here is an example of passing a proc/lambda object as the `:key` option as well:
+
+```ruby
+ class User
+ attr_encrypted :email, key: proc { |user| user.key }
+ end
+```
+
+
+### Default options
+
+The following are the default options used by `attr_encrypted`:
+
+```ruby
+ prefix: 'encrypted_',
+ suffix: '',
+ if: true,
+ unless: false,
+ encode: false,
+ encode_iv: true,
+ encode_salt: true,
+ default_encoding: 'm',
+ marshal: false,
+ marshaler: Marshal,
+ dump_method: 'dump',
+ load_method: 'load',
+ encryptor: Encryptor,
+ encrypt_method: 'encrypt',
+ decrypt_method: 'decrypt',
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ allow_empty_value: false
+```
+
+All of the aforementioned options are explained in depth below.
+
+Additionally, you can specify default options for all encrypted attributes in your class. Instead of having to define your class like this:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!', prefix: '', suffix: '_crypted'
+ attr_encrypted :ssn, key: 'a different secret key', prefix: '', suffix: '_crypted'
+ attr_encrypted :credit_card, key: 'another secret key', prefix: '', suffix: '_crypted'
+ end
+```
+
+You can simply define some default options like so:
+
+```ruby
+ class User
+ attr_encrypted_options.merge!(prefix: '', :suffix => '_crypted')
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!'
+ attr_encrypted :ssn, key: 'a different secret key'
+ attr_encrypted :credit_card, key: 'another secret key'
+ end
+```
+
+This should help keep your classes clean and DRY.
+
+### The `:attribute` option
+
+You can simply pass the name of the encrypted attribute as the `:attribute` option:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!', attribute: 'email_encrypted'
+ end
+```
+
+This would generate an attribute named `email_encrypted`
+
+
+### The `:prefix` and `:suffix` options
+
+If you don't like the `encrypted_#{attribute}` naming convention then you can specify your own:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!', prefix: 'secret_', suffix: '_crypted'
+ end
+```
+
+This would generate the following attribute: `secret_email_crypted`.
+
+
+### The `:key` option
+
+The `:key` option is used to pass in a data encryption key to be used with whatever encryption class you use. If you're using `Encryptor`, the key must meet minimum length requirements respective to the algorithm that you use; aes-256 requires a 256 bit key, etc. The `:key` option is not required (see custom encryptor below).
+
+
+##### Unique keys for each attribute
+
+You can specify unique keys for each attribute if you'd like:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!'
+ attr_encrypted :ssn, key: 'a different secret key'
+ end
+```
+
+It is recommended to use a symbol or a proc for the key and to store information regarding what key was used to encrypt your data. (See below for more details.)
+
+
+### The `:if` and `:unless` options
+
+There may be times that you want to only encrypt when certain conditions are met. For example maybe you're using rails and you don't want to encrypt attributes when you're in development mode. You can specify conditions like this:
+
+```ruby
+ class User < ActiveRecord::Base
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!', unless: Rails.env.development?
+ attr_encrypted :ssn, key: 'This is a key that is 256 bits!!', if: Rails.env.development?
+ end
+```
+
+You can specify both `:if` and `:unless` options.
+
+
+### The `:encryptor`, `:encrypt_method`, and `:decrypt_method` options
+
+The `Encryptor` class is used by default. You may use your own custom encryptor by specifying the `:encryptor`, `:encrypt_method`, and `:decrypt_method` options.
+
+Lets suppose you'd like to use this custom encryptor class:
+
+```ruby
+ class SillyEncryptor
+ def self.silly_encrypt(options)
+ (options[:value] + options[:secret_key]).reverse
+ end
+
+ def self.silly_decrypt(options)
+ options[:value].reverse.gsub(/#{options[:secret_key]}$/, '')
+ end
+ end
+```
+
+Simply set up your class like so:
+
+```ruby
+ class User
+ attr_encrypted :email, secret_key: 'This is a key that is 256 bits!!', encryptor: SillyEncryptor, encrypt_method: :silly_encrypt, decrypt_method: :silly_decrypt
+ end
+```
+
+Any options that you pass to `attr_encrypted` will be passed to the encryptor class along with the `:value` option which contains the string to encrypt/decrypt. Notice that the above example uses `:secret_key` instead of `:key`. See [encryptor](https://github.com/attr-encrypted/encryptor) for more info regarding the default encryptor class.
+
+
+### The `:mode` option
+
+The mode options allows you to specify in what mode your data will be encrypted. There are currently three modes: `:per_attribute_iv`, `:per_attribute_iv_and_salt`, and `:single_iv_and_salt`.
+
+__NOTE: `:per_attribute_iv_and_salt` and `:single_iv_and_salt` modes are deprecated and will be removed in the next major release.__
+
+
+### The `:algorithm` option
+
+The default `Encryptor` class uses the standard ruby OpenSSL library. Its default algorithm is `aes-256-gcm`. You can modify this by passing the `:algorithm` option to the `attr_encrypted` call like so:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!', algorithm: 'aes-256-cbc'
+ end
+```
+
+To view a list of all cipher algorithms that are supported on your platform, run the following code in your favorite Ruby REPL:
+
+```ruby
+ require 'openssl'
+ puts OpenSSL::Cipher.ciphers
+```
+See [Encryptor](https://github.com/attr-encrypted/encryptor#algorithms) for more information.
+
+
+### The `:encode`, `:encode_iv`, `:encode_salt`, and `:default_encoding` options
+
+You're probably going to be storing your encrypted attributes somehow (e.g. filesystem, database, etc). You can simply pass the `:encode` option to automatically encode/decode when encrypting/decrypting. The default behavior assumes that you're using a string column type and will base64 encode your cipher text. If you choose to use the binary column type then encoding is not required, but be sure to pass in `false` with the `:encode` option.
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'some secret key', encode: true, encode_iv: true, encode_salt: true
+ end
+```
+
+The default encoding is `m` (base64). You can change this by setting `encode: 'some encoding'`. See [`Array#pack`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-pack) for more encoding options.
+
+
+### The `:marshal`, `:dump_method`, and `:load_method` options
+
+You may want to encrypt objects other than strings (e.g. hashes, arrays, etc). If this is the case, simply pass the `:marshal` option to automatically marshal when encrypting/decrypting.
+
+```ruby
+ class User
+ attr_encrypted :credentials, key: 'some secret key', marshal: true
+ end
+```
+
+You may also optionally specify `:marshaler`, `:dump_method`, and `:load_method` if you want to use something other than the default `Marshal` object.
+
+### The `:allow_empty_value` option
+
+You may want to encrypt empty strings or nil so as to not reveal which records are populated and which records are not.
+
+```ruby
+ class User
+ attr_encrypted :credentials, key: 'some secret key', marshal: true, allow_empty_value: true
+ end
+```
+
+
+## ORMs
+
+### ActiveRecord
+
+If you're using this gem with `ActiveRecord`, you get a few extra features:
+
+#### Default options
+
+The `:encode` option is set to true by default.
+
+#### Dynamic `find_by_` and `scoped_by_` methods
+
+Let's say you'd like to encrypt your user's email addresses, but you also need a way for them to login. Simply set up your class like so:
+
+```ruby
+ class User < ActiveRecord::Base
+ attr_encrypted :email, key: 'This is a key that is 256 bits!!'
+ attr_encrypted :password, key: 'some other secret key'
+ end
+```
+
+You can now lookup and login users like so:
+
+```ruby
+ User.find_by_email_and_password('test@example.com', 'testing')
+```
+
+The call to `find_by_email_and_password` is intercepted and modified to `find_by_encrypted_email_and_encrypted_password('ENCRYPTED EMAIL', 'ENCRYPTED PASSWORD')`. The dynamic scope methods like `scoped_by_email_and_password` work the same way.
+
+NOTE: This only works if all records are encrypted with the same encryption key (per attribute).
+
+__NOTE: This feature is deprecated and will be removed in the next major release.__
+
+
+### DataMapper and Sequel
+
+#### Default options
+
+The `:encode` option is set to true by default.
+
+
+## Deprecations
+
+attr_encrypted v2.0.0 now depends on encryptor v2.0.0. As part of both major releases many insecure defaults and behaviors have been deprecated. The new default behavior is as follows:
+
+* Default `:mode` is now `:per_attribute_iv`, the default `:mode` in attr_encrypted v1.x was `:single_iv_and_salt`.
+* Default `:algorithm` is now 'aes-256-gcm', the default `:algorithm` in attr_encrypted v1.x was 'aes-256-cbc'.
+* The encryption key provided must be of appropriate length respective to the algorithm used. Previously, encryptor did not verify minimum key length.
+* The dynamic finders available in ActiveRecord will only work with `:single_iv_and_salt` mode. It is strongly advised that you do not use this mode. If you can search the encrypted data, it wasn't encrypted securely. This functionality will be deprecated in the next major release.
+* `:per_attribute_iv_and_salt` and `:single_iv_and_salt` modes are deprecated and will be removed in the next major release.
+
+Backwards compatibility is supported by providing a special option that is passed to encryptor, namely, `:insecure_mode`:
+
+```ruby
+ class User
+ attr_encrypted :email, key: 'a secret key', algorithm: 'aes-256-cbc', mode: :single_iv_and_salt, insecure_mode: true
+ end
+```
+
+The `:insecure_mode` option will allow encryptor to ignore the new security requirements. It is strongly advised that if you use this older insecure behavior that you migrate to the newer more secure behavior.
+
+
+## Upgrading from attr_encrypted v1.x to v3.x
+
+Modify your gemfile to include the new version of attr_encrypted:
+
+```ruby
+ gem attr_encrypted, "~> 3.0.0"
+```
+
+The update attr_encrypted:
+
+```bash
+ bundle update attr_encrypted
+```
+
+Then modify your models using attr\_encrypted to account for the changes in default options. Specifically, pass in the `:mode` and `:algorithm` options that you were using if you had not previously done so. If your key is insufficient length relative to the algorithm that you use, you should also pass in `insecure_mode: true`; this will prevent Encryptor from raising an exception regarding insufficient key length. Please see the Deprecations sections for more details including an example of how to specify your model with default options from attr_encrypted v1.x.
+
+## Upgrading from attr_encrypted v2.x to v3.x
+
+A bug was discovered in Encryptor v2.0.0 that inccorectly set the IV when using an AES-\*-GCM algorithm. Unfornately fixing this major security issue results in the inability to decrypt records encrypted using an AES-*-GCM algorithm from Encryptor v2.0.0. Please see [Upgrading to Encryptor v3.0.0](https://github.com/attr-encrypted/encryptor#upgrading-from-v200-to-v300) for more info.
+
+It is strongly advised that you re-encrypt your data encrypted with Encryptor v2.0.0. However, you'll have to take special care to re-encrypt. To decrypt data encrypted with Encryptor v2.0.0 using an AES-\*-GCM algorithm you can use the `:v2_gcm_iv` option.
+
+It is recommended that you implement a strategy to insure that you do not mix the encryption implementations of Encryptor. One way to do this is to re-encrypt everything while your application is offline.Another way is to add a column that keeps track of what implementation was used. The path that you choose will depend on your situtation. Below is an example of how you might go about re-encrypting your data.
+
+```ruby
+ class User
+ attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: is_decrypting?(:ssn)
+
+ def is_decrypting?(attribute)
+ encrypted_attributes[attribute][:operation] == :decrypting
+ end
+ end
+
+ User.all.each do |user|
+ old_ssn = user.ssn
+ user.ssn= old_ssn
+ user.save
+ end
+```
+
+## Things to consider before using attr_encrypted
+
+#### Searching, joining, etc
+While choosing to encrypt at the attribute level is the most secure solution, it is not without drawbacks. Namely, you cannot search the encrypted data, and because you can't search it, you can't index it either. You also can't use joins on the encrypted data. Data that is securely encrypted is effectively noise. So any operations that rely on the data not being noise will not work. If you need to do any of the aforementioned operations, please consider using database and file system encryption along with transport encryption as it moves through your stack.
+
+#### Data leaks
+Please also consider where your data leaks. If you're using attr_encrypted with Rails, it's highly likely that this data will enter your app as a request parameter. You'll want to be sure that you're filtering your request params from you logs or else your data is sitting in the clear in your logs. [Parameter Filtering in Rails](http://apidock.com/rails/ActionDispatch/Http/FilterParameters) Please also consider other possible leak points.
+
+#### Storage requirements
+When storing your encrypted data, please consider the length requirements of the db column that you're storing the cipher text in. Older versions of Mysql attempt to 'help' you by truncating strings that are too large for the column. When this happens, you will not be able to decrypt your data. [MySQL Strict Trans](http://www.davidpashley.com/2009/02/15/silently-truncated/)
+
+#### Metadata regarding your crypto implementation
+It is advisable to also store metadata regarding the circumstances of your encrypted data. Namely, you should store information about the key used to encrypt your data, as well as the algorithm. Having this metadata with every record will make key rotation and migrating to a new algorithm signficantly easier. It will allow you to continue to decrypt old data using the information provided in the metadata and new data can be encrypted using your new key and algorithm of choice.
+
+#### Enforcing the IV as a nonce
+On a related note, most algorithms require that your IV be unique for every record and key combination. You can enforce this using composite unique indexes on your IV and encryption key name/id column. [RFC 5084](https://tools.ietf.org/html/rfc5084#section-1.5)
+
+#### Unique key per record
+Lastly, while the `:per_attribute_iv_and_salt` mode is more secure than `:per_attribute_iv` mode because it uses a unique key per record, it uses a PBKDF function which introduces a huge performance hit (175x slower by my benchmarks). There are other ways of deriving a unique key per record that would be much faster.
+
+## Note on Patches/Pull Requests
+
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a
+ future version unintentionally.
+* Commit, do not mess with rakefile, version, changelog, or history.
+* Send me a pull request. Bonus points for topic branches.
diff --git a/vendor/gems/attr_encrypted/Rakefile b/vendor/gems/attr_encrypted/Rakefile
new file mode 100644
index 00000000000..3dbc96ceb14
--- /dev/null
+++ b/vendor/gems/attr_encrypted/Rakefile
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rake/testtask'
+require 'rdoc/task'
+require "bundler/gem_tasks"
+
+desc 'Test the attr_encrypted gem.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.warning = false
+ t.verbose = true
+end
+
+desc 'Generate documentation for the attr_encrypted gem.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'attr_encrypted'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+desc 'Default: run unit tests.'
+task :default => :test
diff --git a/vendor/gems/attr_encrypted/attr_encrypted.gemspec b/vendor/gems/attr_encrypted/attr_encrypted.gemspec
new file mode 100644
index 00000000000..b6a39bddd2c
--- /dev/null
+++ b/vendor/gems/attr_encrypted/attr_encrypted.gemspec
@@ -0,0 +1,52 @@
+# -*- encoding: utf-8 -*-
+
+lib = File.expand_path('../lib/', __FILE__)
+$:.unshift lib unless $:.include?(lib)
+
+require 'attr_encrypted/version'
+require 'date'
+
+Gem::Specification.new do |s|
+ s.name = 'attr_encrypted'
+ s.version = AttrEncrypted::Version.string
+ s.date = Date.today
+
+ s.summary = 'GitLab fork of attr_encrypted'
+ s.description = "Generates attr_accessors that encrypt and decrypt attributes transparently.\n\n
+Forked from https://github.com/attr-encrypted/attr_encrypted."
+
+ s.authors = ['Sean Huber', 'S. Brent Faulkner', 'William Monk', 'Stephen Aghaulor']
+ s.email = ['seah@shuber.io', 'sbfaulkner@gmail.com', 'billy.monk@gmail.com', 'saghaulor@gmail.com']
+ s.homepage = 'https://gitlab.com/gitlab-org/ruby/gems/attr_encrypted'
+ s.license = 'MIT'
+
+ s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']
+
+ s.require_paths = ['lib']
+
+ s.files = Dir['lib/**/*.rb']
+ s.test_files = Dir['test/**/*']
+
+ s.required_ruby_version = '>= 2.7.0'
+
+ s.add_dependency('encryptor', ['~> 3.0.0'])
+
+ activerecord_version = "~> 6.1"
+ s.add_development_dependency('activerecord', activerecord_version)
+ s.add_development_dependency('actionpack', activerecord_version)
+ s.add_development_dependency('datamapper')
+ s.add_development_dependency('rake')
+ s.add_development_dependency('minitest')
+ s.add_development_dependency('sequel')
+ s.add_development_dependency('sqlite3')
+ s.add_development_dependency('dm-sqlite-adapter')
+ s.add_development_dependency('simplecov')
+ s.add_development_dependency('simplecov-rcov')
+ s.add_development_dependency("codeclimate-test-reporter", '<= 0.6.0')
+
+ s.post_install_message = "\n\n\nWARNING: Several insecure default options and features were deprecated in attr_encrypted v2.0.0.\n
+Additionally, there was a bug in Encryptor v2.0.0 that insecurely encrypted data when using an AES-*-GCM algorithm.\n
+This bug was fixed but introduced breaking changes between v2.x and v3.x.\n
+Please see the README for more information regarding upgrading to attr_encrypted v3.0.0.\n\n\n"
+
+end
diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted.rb
new file mode 100644
index 00000000000..88e5f65e3c8
--- /dev/null
+++ b/vendor/gems/attr_encrypted/lib/attr_encrypted.rb
@@ -0,0 +1,473 @@
+# frozen_string_literal: true
+
+require 'encryptor'
+
+# Adds attr_accessors that encrypt and decrypt an object's attributes
+module AttrEncrypted
+ autoload :Version, 'attr_encrypted/version'
+
+ def self.extended(base) # :nodoc:
+ base.class_eval do
+ include InstanceMethods
+ attr_writer :attr_encrypted_options
+ @attr_encrypted_options, @encrypted_attributes = {}, {}
+ end
+ end
+
+ # Generates attr_accessors that encrypt and decrypt attributes transparently
+ #
+ # Options (any other options you specify are passed to the Encryptor's encrypt and decrypt methods)
+ #
+ # attribute: The name of the referenced encrypted attribute. For example
+ # <tt>attr_accessor :email, attribute: :ee</tt> would generate an
+ # attribute named 'ee' to store the encrypted email. This is useful when defining
+ # one attribute to encrypt at a time or when the :prefix and :suffix options
+ # aren't enough.
+ # Defaults to nil.
+ #
+ # prefix: A prefix used to generate the name of the referenced encrypted attributes.
+ # For example <tt>attr_accessor :email, prefix: 'crypted_'</tt> would
+ # generate attributes named 'crypted_email' to store the encrypted
+ # email and password.
+ # Defaults to 'encrypted_'.
+ #
+ # suffix: A suffix used to generate the name of the referenced encrypted attributes.
+ # For example <tt>attr_accessor :email, prefix: '', suffix: '_encrypted'</tt>
+ # would generate attributes named 'email_encrypted' to store the
+ # encrypted email.
+ # Defaults to ''.
+ #
+ # key: The encryption key. This option may not be required if
+ # you're using a custom encryptor. If you pass a symbol
+ # representing an instance method then the :key option
+ # will be replaced with the result of the method before
+ # being passed to the encryptor. Objects that respond
+ # to :call are evaluated as well (including procs).
+ # Any other key types will be passed directly to the encryptor.
+ # Defaults to nil.
+ #
+ # encode: If set to true, attributes will be encoded as well as
+ # encrypted. This is useful if you're planning on storing
+ # the encrypted attributes in a database. The default
+ # encoding is 'm' (base64), however this can be overwritten
+ # by setting the :encode option to some other encoding
+ # string instead of just 'true'. See
+ # http://www.ruby-doc.org/core/classes/Array.html#M002245
+ # for more encoding directives.
+ # Defaults to false unless you're using it with ActiveRecord, DataMapper, or Sequel.
+ #
+ # encode_iv: Defaults to true.
+
+ # encode_salt: Defaults to true.
+ #
+ # default_encoding: Defaults to 'm' (base64).
+ #
+ # marshal: If set to true, attributes will be marshaled as well
+ # as encrypted. This is useful if you're planning on
+ # encrypting something other than a string.
+ # Defaults to false.
+ #
+ # marshaler: The object to use for marshaling.
+ # Defaults to Marshal.
+ #
+ # dump_method: The dump method name to call on the <tt>:marshaler</tt> object to.
+ # Defaults to 'dump'.
+ #
+ # load_method: The load method name to call on the <tt>:marshaler</tt> object.
+ # Defaults to 'load'.
+ #
+ # encryptor: The object to use for encrypting.
+ # Defaults to Encryptor.
+ #
+ # encrypt_method: The encrypt method name to call on the <tt>:encryptor</tt> object.
+ # Defaults to 'encrypt'.
+ #
+ # decrypt_method: The decrypt method name to call on the <tt>:encryptor</tt> object.
+ # Defaults to 'decrypt'.
+ #
+ # if: Attributes are only encrypted if this option evaluates
+ # to true. If you pass a symbol representing an instance
+ # method then the result of the method will be evaluated.
+ # Any objects that respond to <tt>:call</tt> are evaluated as well.
+ # Defaults to true.
+ #
+ # unless: Attributes are only encrypted if this option evaluates
+ # to false. If you pass a symbol representing an instance
+ # method then the result of the method will be evaluated.
+ # Any objects that respond to <tt>:call</tt> are evaluated as well.
+ # Defaults to false.
+ #
+ # mode: Selects encryption mode for attribute: choose <tt>:single_iv_and_salt</tt> for compatibility
+ # with the old attr_encrypted API: the IV is derived from the encryption key by the underlying Encryptor class; salt is not used.
+ # The <tt>:per_attribute_iv_and_salt</tt> mode uses a per-attribute IV and salt. The salt is used to derive a unique key per attribute.
+ # A <tt>:per_attribute_iv</default> mode derives a unique IV per attribute; salt is not used.
+ # Defaults to <tt>:per_attribute_iv</tt>.
+ #
+ # allow_empty_value: Attributes which have nil or empty string values will not be encrypted unless this option
+ # has a truthy value.
+ #
+ # You can specify your own default options
+ #
+ # class User
+ # # Now all attributes will be encoded and marshaled by default
+ # attr_encrypted_options.merge!(encode: true, marshal: true, some_other_option: true)
+ # attr_encrypted :configuration, key: 'my secret key'
+ # end
+ #
+ #
+ # Example
+ #
+ # class User
+ # attr_encrypted :email, key: 'some secret key'
+ # attr_encrypted :configuration, key: 'some other secret key', marshal: true
+ # end
+ #
+ # @user = User.new
+ # @user.encrypted_email # nil
+ # @user.email? # false
+ # @user.email = 'test@example.com'
+ # @user.email? # true
+ # @user.encrypted_email # returns the encrypted version of 'test@example.com'
+ #
+ # @user.configuration = { time_zone: 'UTC' }
+ # @user.encrypted_configuration # returns the encrypted version of configuration
+ #
+ # See README for more examples
+ def attr_encrypted(*attributes)
+ options = attributes.last.is_a?(Hash) ? attributes.pop : {}
+ options = attr_encrypted_default_options.dup.merge!(attr_encrypted_options).merge!(options)
+
+ options[:encode] = options[:default_encoding] if options[:encode] == true
+ options[:encode_iv] = options[:default_encoding] if options[:encode_iv] == true
+ options[:encode_salt] = options[:default_encoding] if options[:encode_salt] == true
+
+ attributes.each do |attribute|
+ encrypted_attribute_name = (options[:attribute] ? options[:attribute] : [options[:prefix], attribute, options[:suffix]].join).to_sym
+
+ instance_methods_as_symbols = attribute_instance_methods_as_symbols
+
+ if attribute_instance_methods_as_symbols_available?
+ attr_reader encrypted_attribute_name unless instance_methods_as_symbols.include?(encrypted_attribute_name)
+ attr_writer encrypted_attribute_name unless instance_methods_as_symbols.include?(:"#{encrypted_attribute_name}=")
+
+ iv_name = "#{encrypted_attribute_name}_iv".to_sym
+ attr_reader iv_name unless instance_methods_as_symbols.include?(iv_name)
+ attr_writer iv_name unless instance_methods_as_symbols.include?(:"#{iv_name}=")
+
+ salt_name = "#{encrypted_attribute_name}_salt".to_sym
+ attr_reader salt_name unless instance_methods_as_symbols.include?(salt_name)
+ attr_writer salt_name unless instance_methods_as_symbols.include?(:"#{salt_name}=")
+ end
+
+ define_method(attribute) do
+ instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name)))
+ end
+
+ define_method("#{attribute}=") do |value|
+ send("#{encrypted_attribute_name}=", encrypt(attribute, value))
+ instance_variable_set("@#{attribute}", value)
+ end
+
+ define_method("#{attribute}?") do
+ value = send(attribute)
+ value.respond_to?(:empty?) ? !value.empty? : !!value
+ end
+
+ encrypted_attributes[attribute.to_sym] = options.merge(attribute: encrypted_attribute_name)
+ end
+ end
+
+ alias_method :attr_encryptor, :attr_encrypted
+
+ # Default options to use with calls to <tt>attr_encrypted</tt>
+ #
+ # It will inherit existing options from its superclass
+ def attr_encrypted_options
+ @attr_encrypted_options ||= superclass.attr_encrypted_options.dup
+ end
+
+ def attr_encrypted_default_options
+ {
+ prefix: 'encrypted_',
+ suffix: '',
+ if: true,
+ unless: false,
+ encode: false,
+ encode_iv: true,
+ encode_salt: true,
+ default_encoding: 'm',
+ marshal: false,
+ marshaler: Marshal,
+ dump_method: 'dump',
+ load_method: 'load',
+ encryptor: Encryptor,
+ encrypt_method: 'encrypt',
+ decrypt_method: 'decrypt',
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ allow_empty_value: false,
+ }
+ end
+
+ private :attr_encrypted_default_options
+
+ # Checks if an attribute is configured with <tt>attr_encrypted</tt>
+ #
+ # Example
+ #
+ # class User
+ # attr_accessor :name
+ # attr_encrypted :email
+ # end
+ #
+ # User.attr_encrypted?(:name) # false
+ # User.attr_encrypted?(:email) # true
+ def attr_encrypted?(attribute)
+ encrypted_attributes.has_key?(attribute.to_sym)
+ end
+
+ # Decrypts a value for the attribute specified
+ #
+ # Example
+ #
+ # class User
+ # attr_encrypted :email
+ # end
+ #
+ # email = User.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING')
+ def decrypt(attribute, encrypted_value, options = {})
+ options = encrypted_attributes[attribute.to_sym].merge(options)
+ if options[:if] && !options[:unless] && not_empty?(encrypted_value)
+ encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode]
+ value = options[:encryptor].send(options[:decrypt_method], options.merge!(value: encrypted_value))
+ if options[:marshal]
+ value = options[:marshaler].send(options[:load_method], value)
+ elsif defined?(Encoding)
+ encoding = Encoding.default_internal || Encoding.default_external
+ value = value.force_encoding(encoding.name)
+ end
+ value
+ else
+ encrypted_value
+ end
+ end
+
+ # Encrypts a value for the attribute specified
+ #
+ # Example
+ #
+ # class User
+ # attr_encrypted :email
+ # end
+ #
+ # encrypted_email = User.encrypt(:email, 'test@example.com')
+ def encrypt(attribute, value, options = {})
+ options = encrypted_attributes[attribute.to_sym].merge(options)
+ if options[:if] && !options[:unless] && (options[:allow_empty_value] || not_empty?(value))
+ value = options[:marshal] ? options[:marshaler].send(options[:dump_method], value) : value.to_s
+ encrypted_value = options[:encryptor].send(options[:encrypt_method], options.merge!(value: value))
+ encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
+ encrypted_value
+ else
+ value
+ end
+ end
+
+ def not_empty?(value)
+ !value.nil? && !(value.is_a?(String) && value.empty?)
+ end
+
+ # Contains a hash of encrypted attributes with virtual attribute names as keys
+ # and their corresponding options as values
+ #
+ # Example
+ #
+ # class User
+ # attr_encrypted :email, key: 'my secret key'
+ # end
+ #
+ # User.encrypted_attributes # { email: { attribute: 'encrypted_email', key: 'my secret key' } }
+ def encrypted_attributes
+ @encrypted_attributes ||= superclass.encrypted_attributes.dup
+ end
+
+ # Forwards calls to :encrypt_#{attribute} or :decrypt_#{attribute} to the corresponding encrypt or decrypt method
+ # if attribute was configured with attr_encrypted
+ #
+ # Example
+ #
+ # class User
+ # attr_encrypted :email, key: 'my secret key'
+ # end
+ #
+ # User.encrypt_email('SOME_ENCRYPTED_EMAIL_STRING')
+ def method_missing(method, *arguments, &block)
+ if method.to_s =~ /^((en|de)crypt)_(.+)$/ && attr_encrypted?($3)
+ send($1, $3, *arguments)
+ else
+ super
+ end
+ end
+
+ module InstanceMethods
+ # Decrypts a value for the attribute specified using options evaluated in the current object's scope
+ #
+ # Example
+ #
+ # class User
+ # attr_accessor :secret_key
+ # attr_encrypted :email, key: :secret_key
+ #
+ # def initialize(secret_key)
+ # self.secret_key = secret_key
+ # end
+ # end
+ #
+ # @user = User.new('some-secret-key')
+ # @user.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING')
+ def decrypt(attribute, encrypted_value)
+ encrypted_attributes[attribute.to_sym][:operation] = :decrypting
+ encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value)
+ self.class.decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute))
+ end
+
+ # Encrypts a value for the attribute specified using options evaluated in the current object's scope
+ #
+ # Example
+ #
+ # class User
+ # attr_accessor :secret_key
+ # attr_encrypted :email, key: :secret_key
+ #
+ # def initialize(secret_key)
+ # self.secret_key = secret_key
+ # end
+ # end
+ #
+ # @user = User.new('some-secret-key')
+ # @user.encrypt(:email, 'test@example.com')
+ def encrypt(attribute, value)
+ encrypted_attributes[attribute.to_sym][:operation] = :encrypting
+ encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value)
+ self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute))
+ end
+
+ # Copies the class level hash of encrypted attributes with virtual attribute names as keys
+ # and their corresponding options as values to the instance
+ #
+ def encrypted_attributes
+ @encrypted_attributes ||= begin
+ duplicated= {}
+ self.class.encrypted_attributes.map { |key, value| duplicated[key] = value.dup }
+ duplicated
+ end
+ end
+
+ protected
+
+ # Returns attr_encrypted options evaluated in the current object's scope for the attribute specified
+ def evaluated_attr_encrypted_options_for(attribute)
+ evaluated_options = Hash.new
+ attributes = encrypted_attributes[attribute.to_sym]
+ attribute_option_value = attributes[:attribute]
+
+ [:if, :unless, :value_present, :allow_empty_value].each do |option|
+ evaluated_options[option] = evaluate_attr_encrypted_option(attributes[option])
+ end
+
+ evaluated_options[:attribute] = attribute_option_value
+
+ evaluated_options.tap do |options|
+ if options[:if] && !options[:unless] && options[:value_present] || options[:allow_empty_value]
+ (attributes.keys - evaluated_options.keys).each do |option|
+ options[option] = evaluate_attr_encrypted_option(attributes[option])
+ end
+
+ unless options[:mode] == :single_iv_and_salt
+ load_iv_for_attribute(attribute, options)
+ end
+
+ if options[:mode] == :per_attribute_iv_and_salt
+ load_salt_for_attribute(attribute, options)
+ end
+ end
+ end
+ end
+
+ # Evaluates symbol (method reference) or proc (responds to call) options
+ #
+ # If the option is not a symbol or proc then the original option is returned
+ def evaluate_attr_encrypted_option(option)
+ if option.is_a?(Symbol) && respond_to?(option, true)
+ send(option)
+ elsif option.respond_to?(:call)
+ option.call(self)
+ else
+ option
+ end
+ end
+
+ def load_iv_for_attribute(attribute, options)
+ encrypted_attribute_name = options[:attribute]
+ encode_iv = options[:encode_iv]
+ iv = options[:iv] || send("#{encrypted_attribute_name}_iv")
+ if options[:operation] == :encrypting
+ begin
+ iv = generate_iv(options[:algorithm])
+ iv = [iv].pack(encode_iv) if encode_iv
+ send("#{encrypted_attribute_name}_iv=", iv)
+ rescue RuntimeError
+ end
+ end
+ if iv && !iv.empty?
+ iv = iv.unpack(encode_iv).first if encode_iv
+ options[:iv] = iv
+ end
+ end
+
+ def generate_iv(algorithm)
+ algo = OpenSSL::Cipher.new(algorithm)
+ algo.encrypt
+ algo.random_iv
+ end
+
+ def load_salt_for_attribute(attribute, options)
+ encrypted_attribute_name = options[:attribute]
+ encode_salt = options[:encode_salt]
+ salt = options[:salt] || send("#{encrypted_attribute_name}_salt")
+ if options[:operation] == :encrypting
+ salt = SecureRandom.random_bytes
+ salt = prefix_and_encode_salt(salt, encode_salt) if encode_salt
+ send("#{encrypted_attribute_name}_salt=", salt)
+ end
+ if salt && !salt.empty?
+ salt = decode_salt_if_encoded(salt, encode_salt) if encode_salt
+ options[:salt] = salt
+ end
+ end
+
+ def prefix_and_encode_salt(salt, encoding)
+ prefix = '_'
+ prefix + [salt].pack(encoding)
+ end
+
+ def decode_salt_if_encoded(salt, encoding)
+ prefix = '_'
+ salt.slice(0).eql?(prefix) ? salt.slice(1..-1).unpack(encoding).first : salt
+ end
+ end
+
+ protected
+
+ def attribute_instance_methods_as_symbols
+ instance_methods.collect { |method| method.to_sym }
+ end
+
+ def attribute_instance_methods_as_symbols_available?
+ true
+ end
+
+end
+
+
+Dir[File.join(File.dirname(__FILE__), 'attr_encrypted', 'adapters', '*.rb')].each { |adapter| require adapter }
diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb
new file mode 100644
index 00000000000..ec8d0208e92
--- /dev/null
+++ b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+
+if defined?(ActiveRecord::Base)
+ module AttrEncrypted
+ module Adapters
+ module ActiveRecord
+ def self.extended(base) # :nodoc:
+ base.class_eval do
+
+ # https://github.com/attr-encrypted/attr_encrypted/issues/68
+ alias_method :reload_without_attr_encrypted, :reload
+ def reload(*args, &block)
+ result = reload_without_attr_encrypted(*args, &block)
+ self.class.encrypted_attributes.keys.each do |attribute_name|
+ instance_variable_set("@#{attribute_name}", nil)
+ end
+ result
+ end
+
+ attr_encrypted_options[:encode] = true
+
+ class << self
+ alias_method :method_missing_without_attr_encrypted, :method_missing
+ alias_method :method_missing, :method_missing_with_attr_encrypted
+ end
+
+ def perform_attribute_assignment(method, new_attributes, *args)
+ return if new_attributes.blank?
+
+ send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args
+ send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args
+ end
+ private :perform_attribute_assignment
+
+ if ::ActiveRecord::VERSION::STRING > "3.1"
+ alias_method :assign_attributes_without_attr_encrypted, :assign_attributes
+ def assign_attributes(*args)
+ perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args
+ end
+ end
+
+ alias_method :attributes_without_attr_encrypted=, :attributes=
+ def attributes=(*args)
+ perform_attribute_assignment :attributes_without_attr_encrypted=, *args
+ end
+ end
+ end
+
+ protected
+
+ # <tt>attr_encrypted</tt> method
+ def attr_encrypted(*attrs)
+ super
+ options = attrs.extract_options!
+ attr = attrs.pop
+ attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0"
+ options.merge! encrypted_attributes[attr]
+
+ define_method("#{attr}_was") do
+ attribute_was(attr)
+ end
+
+ if ::ActiveRecord::VERSION::STRING >= "4.1"
+ define_method("#{attr}_changed?") do |options = {}|
+ attribute_changed?(attr, **options)
+ end
+ else
+ define_method("#{attr}_changed?") do
+ attribute_changed?(attr)
+ end
+ end
+
+ define_method("#{attr}_change") do
+ attribute_change(attr)
+ end
+
+ define_method("#{attr}_with_dirtiness=") do |value|
+ attribute_will_change!(attr) if value != __send__(attr)
+ __send__("#{attr}_without_dirtiness=", value)
+ end
+
+ alias_method "#{attr}_without_dirtiness=", "#{attr}="
+ alias_method "#{attr}=", "#{attr}_with_dirtiness="
+
+ alias_method "#{attr}_before_type_cast", attr
+ end
+
+ def attribute_instance_methods_as_symbols
+ # We add accessor methods of the db columns to the list of instance
+ # methods returned to let ActiveRecord define the accessor methods
+ # for the db columns
+
+ if connected? && table_exists?
+ columns_hash.keys.inject(super) {|instance_methods, column_name| instance_methods.concat [column_name.to_sym, :"#{column_name}="]}
+ else
+ super
+ end
+ end
+
+ # Prevent attr_encrypted from defining virtual accessors for encryption
+ # data when the code and schema are out of sync. See this issue for more
+ # details: https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def attribute_instance_methods_as_symbols_available?
+ false
+ end
+
+ # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
+ # encrypted attributes
+ #
+ # NOTE: This only works when the <tt>:key</tt> option is specified as a string (see the README)
+ #
+ # This is useful for encrypting fields like email addresses. Your user's email addresses
+ # are encrypted in the database, but you can still look up a user by email for logging in
+ #
+ # Example
+ #
+ # class User < ActiveRecord::Base
+ # attr_encrypted :email, key: 'secret key'
+ # end
+ #
+ # User.find_by_email_and_password('test@example.com', 'testing')
+ # # results in a call to
+ # User.find_by_encrypted_email_and_password('the_encrypted_version_of_test@example.com', 'testing')
+ def method_missing_with_attr_encrypted(method, *args, &block)
+ if match = /^(find|scoped)_(all_by|by)_([_a-zA-Z]\w*)$/.match(method.to_s)
+ attribute_names = match.captures.last.split('_and_')
+ attribute_names.each_with_index do |attribute, index|
+ if attr_encrypted?(attribute) && encrypted_attributes[attribute.to_sym][:mode] == :single_iv_and_salt
+ args[index] = send("encrypt_#{attribute}", args[index])
+ warn "DEPRECATION WARNING: This feature will be removed in the next major release."
+ attribute_names[index] = encrypted_attributes[attribute.to_sym][:attribute]
+ end
+ end
+ method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym
+ end
+ method_missing_without_attr_encrypted(method, *args, &block)
+ end
+ end
+ end
+ end
+
+ ActiveSupport.on_load(:active_record) do
+ extend AttrEncrypted
+ extend AttrEncrypted::Adapters::ActiveRecord
+ end
+end
diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/data_mapper.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/data_mapper.rb
new file mode 100644
index 00000000000..03fb5caa457
--- /dev/null
+++ b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/data_mapper.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+if defined?(DataMapper)
+ module AttrEncrypted
+ module Adapters
+ module DataMapper
+ def self.extended(base) # :nodoc:
+ class << base
+ alias_method :included_without_attr_encrypted, :included
+ alias_method :included, :included_with_attr_encrypted
+ end
+ end
+
+ def included_with_attr_encrypted(base)
+ included_without_attr_encrypted(base)
+ base.extend AttrEncrypted
+ base.attr_encrypted_options[:encode] = true
+ end
+ end
+ end
+ end
+
+ DataMapper::Resource.extend AttrEncrypted::Adapters::DataMapper
+end
diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/sequel.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/sequel.rb
new file mode 100644
index 00000000000..ff14b9a0c8b
--- /dev/null
+++ b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/sequel.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+if defined?(Sequel)
+ module AttrEncrypted
+ module Adapters
+ module Sequel
+ def self.extended(base) # :nodoc:
+ base.attr_encrypted_options[:encode] = true
+ end
+ end
+ end
+ end
+
+ Sequel::Model.extend AttrEncrypted
+ Sequel::Model.extend AttrEncrypted::Adapters::Sequel
+end
diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted/version.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted/version.rb
new file mode 100644
index 00000000000..d97f1532249
--- /dev/null
+++ b/vendor/gems/attr_encrypted/lib/attr_encrypted/version.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module AttrEncrypted
+ # Contains information about this gem's version
+ module Version
+ MAJOR = 3
+ MINOR = 2
+ PATCH = 4
+
+ # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
+ #
+ # Example
+ #
+ # Version.string # '1.0.2'
+ def self.string
+ [MAJOR, MINOR, PATCH].join('.')
+ end
+ end
+end
diff --git a/vendor/gems/attr_encrypted/test/active_record_test.rb b/vendor/gems/attr_encrypted/test/active_record_test.rb
new file mode 100644
index 00000000000..4c903bc3cd8
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/active_record_test.rb
@@ -0,0 +1,368 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
+
+def create_tables
+ ActiveRecord::Schema.define(version: 1) do
+ self.verbose = false
+ create_table :people do |t|
+ t.string :encrypted_email
+ t.string :password
+ t.string :encrypted_credentials
+ t.binary :salt
+ t.binary :key_iv
+ t.string :encrypted_email_salt
+ t.string :encrypted_credentials_salt
+ t.string :encrypted_email_iv
+ t.string :encrypted_credentials_iv
+ end
+ create_table :accounts do |t|
+ t.string :encrypted_password
+ t.string :encrypted_password_iv
+ t.string :encrypted_password_salt
+ t.string :key
+ end
+ create_table :users do |t|
+ t.string :login
+ t.string :encrypted_password
+ t.string :encrypted_password_iv
+ t.boolean :is_admin
+ end
+ create_table :prime_ministers do |t|
+ t.string :encrypted_name
+ t.string :encrypted_name_iv
+ end
+ create_table :addresses do |t|
+ t.binary :encrypted_street
+ t.binary :encrypted_street_iv
+ t.binary :encrypted_zipcode
+ t.string :mode
+ end
+ end
+end
+
+ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
+
+if ::ActiveRecord::VERSION::STRING > "4.0"
+ module Rack
+ module Test
+ class UploadedFile; end
+ end
+ end
+
+ require 'action_controller/metal/strong_parameters'
+end
+
+class Person < ActiveRecord::Base
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+ attr_encrypted :email, key: SECRET_KEY
+ attr_encrypted :credentials, key: Proc.new { |user| Encryptor.encrypt(value: user.salt, key: SECRET_KEY, iv: user.key_iv) }, marshal: true
+
+ after_initialize :initialize_salt_and_credentials
+
+ protected
+
+ def initialize_salt_and_credentials
+ self.key_iv ||= SecureRandom.random_bytes(12)
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
+ self.credentials ||= { username: 'example', password: 'test' }
+ end
+end
+
+class PersonWithValidation < Person
+ validates_presence_of :email
+end
+
+class PersonWithProcMode < Person
+ attr_encrypted :email, key: SECRET_KEY, mode: Proc.new { :per_attribute_iv_and_salt }
+ attr_encrypted :credentials, key: SECRET_KEY, mode: Proc.new { :single_iv_and_salt }, insecure_mode: true
+end
+
+class PersonWithInstanceAttribute < Person
+ attr_encrypted :age
+end
+
+class Account < ActiveRecord::Base
+ ACCOUNT_ENCRYPTION_KEY = SecureRandom.urlsafe_base64(24)
+ attr_encrypted :password, key: :password_encryption_key
+
+ def encrypting?(attr)
+ encrypted_attributes[attr][:operation] == :encrypting
+ end
+
+ def password_encryption_key
+ if encrypting?(:password)
+ self.key = ACCOUNT_ENCRYPTION_KEY
+ else
+ self.key
+ end
+ end
+end
+
+class PersonWithSerialization < ActiveRecord::Base
+ self.table_name = 'people'
+ attr_encrypted :email, key: SECRET_KEY
+ serialize :password
+end
+
+class UserWithProtectedAttribute < ActiveRecord::Base
+ self.table_name = 'users'
+ attr_encrypted :password, key: SECRET_KEY
+ attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
+end
+
+class PersonUsingAlias < ActiveRecord::Base
+ self.table_name = 'people'
+ attr_encryptor :email, key: SECRET_KEY
+end
+
+class PrimeMinister < ActiveRecord::Base
+ attr_encrypted :name, marshal: true, key: SECRET_KEY
+end
+
+class Address < ActiveRecord::Base
+ self.attr_encrypted_options[:marshal] = false
+ self.attr_encrypted_options[:encode] = false
+ attr_encrypted :street, encode_iv: false, key: SECRET_KEY
+ attr_encrypted :zipcode, key: SECRET_KEY, mode: Proc.new { |address| address.mode.to_sym }, insecure_mode: true
+end
+
+class ActiveRecordTest < Minitest::Test
+
+ def setup
+ drop_all_tables
+ create_tables
+ end
+
+ def test_should_encrypt_email
+ @person = Person.create(email: 'test@example.com')
+ refute_nil @person.encrypted_email
+ refute_equal @person.email, @person.encrypted_email
+ assert_equal @person.email, Person.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @person = Person.create
+ refute_nil @person.encrypted_credentials
+ refute_equal @person.credentials, @person.encrypted_credentials
+ assert_equal @person.credentials, Person.first.credentials
+ end
+
+ def test_should_encode_by_default
+ assert Person.attr_encrypted_options[:encode]
+ end
+
+ def test_should_validate_presence_of_email
+ @person = PersonWithValidation.new
+ assert !@person.valid?
+ assert !@person.errors[:email].empty? || @person.errors.on(:email)
+ end
+
+ def test_should_encrypt_decrypt_with_iv
+ @person = Person.create(email: 'test@example.com')
+ @person2 = Person.find(@person.id)
+ refute_nil @person2.encrypted_email_iv
+ assert_equal 'test@example.com', @person2.email
+ end
+
+ def test_should_ensure_attributes_can_be_deserialized
+ @person = PersonWithSerialization.new(email: 'test@example.com', password: %w(an array of strings))
+ @person.save
+ assert_equal @person.password, %w(an array of strings)
+ end
+
+ def test_should_create_an_account_regardless_of_arguments_order
+ Account.create!(key: SECRET_KEY, password: "password")
+ Account.create!(password: "password" , key: SECRET_KEY)
+ end
+
+ def test_should_set_attributes_regardless_of_arguments_order
+ # minitest does not implement `assert_nothing_raised` https://github.com/seattlerb/minitest/issues/112
+ Account.new.attributes = { password: "password", key: SECRET_KEY }
+ end
+
+ def test_should_create_changed_predicate
+ person = Person.create!(email: 'test@example.com')
+ refute person.email_changed?
+ person.email = 'test@example.com'
+ refute person.email_changed?
+ person.email = nil
+ assert person.email_changed?
+ person.email = 'test2@example.com'
+ assert person.email_changed?
+ end
+
+ # PENDING - this test is failing because attr_encrypted does not adhere to the
+ # interface contract for ActiveModel::Dirty as of ActiveRecord 6.1:
+ # https://devdocs.io/rails~6.1/activemodel/dirty
+ def pending_test_should_create_was_predicate
+ original_email = 'test@example.com'
+ person = Person.create!(email: original_email)
+ assert_equal original_email, person.email_was
+ person.email = 'test2@example.com'
+ assert_equal original_email, person.email_was
+ old_pm_name = "Winston Churchill"
+ pm = PrimeMinister.create!(name: old_pm_name)
+ assert_equal old_pm_name, pm.name_was
+ old_zipcode = "90210"
+ address = Address.create!(zipcode: old_zipcode, mode: "single_iv_and_salt")
+ assert_equal old_zipcode, address.zipcode_was
+ end
+
+ # PENDING - this test is failing because attr_encrypted does not adhere to the
+ # interface contract for ActiveModel::Dirty as of ActiveRecord 6.1:
+ # https://devdocs.io/rails~6.1/activemodel/dirty
+ def pending_test_attribute_was_works_when_options_for_old_encrypted_value_are_different_than_options_for_new_encrypted_value
+ pw = 'password'
+ crypto_key = SecureRandom.urlsafe_base64(24)
+ old_iv = SecureRandom.random_bytes(12)
+ account = Account.create
+ encrypted_value = Encryptor.encrypt(value: pw, iv: old_iv, key: crypto_key)
+ Account.where(id: account.id).update_all(key: crypto_key, encrypted_password_iv: [old_iv].pack('m'), encrypted_password: [encrypted_value].pack('m'))
+ account = Account.find(account.id)
+ assert_equal pw, account.password
+ account.password = pw.reverse
+ assert_equal pw, account.password_was
+ account.save
+ account.reload
+ assert_equal Account::ACCOUNT_ENCRYPTION_KEY, account.key
+ assert_equal pw.reverse, account.password
+ end
+
+ if ::ActiveRecord::VERSION::STRING > "4.0"
+ def test_should_assign_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
+ assert_equal 'modified', @user.login
+ end
+
+ def test_should_not_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
+ assert !@user.is_admin?
+ end
+
+ def test_should_raise_exception_if_not_permitted
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ assert_raises ActiveModel::ForbiddenAttributesError do
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
+ end
+ end
+
+ def test_should_raise_exception_on_init_if_not_permitted
+ assert_raises ActiveModel::ForbiddenAttributesError do
+ @user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
+ end
+ end
+ else
+ def test_should_assign_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = { login: 'modified', is_admin: true }
+ assert_equal 'modified', @user.login
+ end
+
+ def test_should_not_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = { login: 'modified', is_admin: true }
+ assert !@user.is_admin?
+ end
+
+ def test_should_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ if ::ActiveRecord::VERSION::STRING > "3.1"
+ @user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
+ else
+ @user.send(:attributes=, { login: 'modified', is_admin: true }, false)
+ end
+ assert @user.is_admin?
+ end
+ end
+
+ def test_should_allow_assignment_of_nil_attributes
+ @person = Person.new
+ assert_nil(@person.attributes = nil)
+ end
+
+ def test_should_allow_proc_based_mode
+ @person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123')
+
+ # Email is :per_attribute_iv_and_salt
+ assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
+ assert_equal @person.class.encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt
+ refute_nil @person.encrypted_email_salt
+ refute_nil @person.encrypted_email_iv
+
+ # Credentials is :single_iv_and_salt
+ assert_equal @person.class.encrypted_attributes[:credentials][:mode].class, Proc
+ assert_equal @person.class.encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt
+ assert_nil @person.encrypted_credentials_salt
+ assert_nil @person.encrypted_credentials_iv
+ end
+
+ if ::ActiveRecord::VERSION::STRING > "3.1"
+ def test_should_allow_assign_attributes_with_nil
+ @person = Person.new
+ assert_nil(@person.assign_attributes nil)
+ end
+ end
+
+ def test_that_alias_encrypts_column
+ user = PersonUsingAlias.new
+ user.email = 'test@example.com'
+ user.save
+
+ refute_nil user.encrypted_email
+ refute_equal user.email, user.encrypted_email
+ assert_equal user.email, PersonUsingAlias.first.email
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/68
+ def test_should_invalidate_virtual_attributes_on_reload
+ old_pm_name = 'Winston Churchill'
+ new_pm_name = 'Neville Chamberlain'
+ pm = PrimeMinister.create!(name: old_pm_name)
+ assert_equal old_pm_name, pm.name
+ pm.name = new_pm_name
+ assert_equal new_pm_name, pm.name
+
+ result = pm.reload
+ assert_equal pm, result
+ assert_equal old_pm_name, pm.name
+ end
+
+ def test_should_save_encrypted_data_as_binary
+ street = '123 Elm'
+ address = Address.create!(street: street)
+ refute_equal address.encrypted_street, street
+ assert_equal Address.first.street, street
+ end
+
+ def test_should_evaluate_proc_based_mode
+ street = '123 Elm'
+ zipcode = '12345'
+ address = Address.create(street: street, zipcode: zipcode, mode: :single_iv_and_salt)
+ address.reload
+ refute_equal address.encrypted_zipcode, zipcode
+ assert_equal address.zipcode, zipcode
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def test_attribute_instance_methods_as_symbols_available_returns_false
+ assert_equal false, ActiveRecord::Base.__send__(:attribute_instance_methods_as_symbols_available?)
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def test_does_not_define_virtual_attributes
+ instance = Person.new
+
+ %w[
+ encrypted_age encrypted_age=
+ encrypted_age_iv encrypted_age_iv=
+ encrypted_age_salt encrypted_age_salt=
+ ].each do |method_name|
+ assert_equal false, instance.respond_to?(method_name), "should not define #{method_name}"
+ end
+ end
+end
diff --git a/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb b/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb
new file mode 100644
index 00000000000..84cb130aa50
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb
@@ -0,0 +1,490 @@
+# frozen_string_literal: true
+
+# encoding: UTF-8
+require_relative 'test_helper'
+
+class SillyEncryptor
+ def self.silly_encrypt(options)
+ (options[:value] + options[:some_arg]).reverse
+ end
+
+ def self.silly_decrypt(options)
+ options[:value].reverse.gsub(/#{options[:some_arg]}$/, '')
+ end
+end
+
+class User
+ extend AttrEncrypted
+ self.attr_encrypted_options[:key] = Proc.new { |user| SECRET_KEY } # default key
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+
+ attr_encrypted :email, :without_encoding, :key => SECRET_KEY
+ attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
+ attr_encrypted :ssn, :key => :secret_key, :attribute => 'ssn_encrypted'
+ attr_encrypted :credit_card, :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt, :some_arg => 'test'
+ attr_encrypted :with_encoding, :key => SECRET_KEY, :encode => true
+ attr_encrypted :with_custom_encoding, :key => SECRET_KEY, :encode => 'm'
+ attr_encrypted :with_marshaling, :key => SECRET_KEY, :marshal => true
+ attr_encrypted :with_true_if, :key => SECRET_KEY, :if => true, mode: :per_attribute_iv_and_salt
+ attr_encrypted :with_false_if, :key => SECRET_KEY, :if => false, mode: :per_attribute_iv_and_salt
+ attr_encrypted :with_true_unless, :key => SECRET_KEY, :unless => true, mode: :per_attribute_iv_and_salt
+ attr_encrypted :with_false_unless, :key => SECRET_KEY, :unless => false, mode: :per_attribute_iv_and_salt
+ attr_encrypted :with_if_changed, :key => SECRET_KEY, :if => :should_encrypt
+ attr_encrypted :with_allow_empty_value, key: SECRET_KEY, allow_empty_value: true, marshal: true
+
+ attr_encryptor :aliased, :key => SECRET_KEY
+
+ attr_accessor :salt
+ attr_accessor :should_encrypt
+
+ def initialize(email: nil)
+ self.email = email
+ self.salt = Time.now.to_i.to_s
+ self.should_encrypt = true
+ end
+
+ private
+ def secret_key
+ SECRET_KEY
+ end
+end
+
+class Admin < User
+ attr_encrypted :testing
+end
+
+class SomeOtherClass
+ extend AttrEncrypted
+ def self.call(object)
+ object.class
+ end
+end
+
+class YetAnotherClass
+ extend AttrEncrypted
+ self.attr_encrypted_options[:encode_iv] = false
+
+ attr_encrypted :email, :key => SECRET_KEY
+ attr_encrypted :phone_number, :key => SECRET_KEY, mode: Proc.new { |thing| thing.mode }, encode_iv: Proc.new { |thing| thing.encode_iv }, encode_salt: Proc.new { |thing| thing.encode_salt }
+
+ def initialize(email: nil, encode_iv: 'm', encode_salt: 'm', mode: :per_attribute_iv_and_salt)
+ self.email = email
+ @encode_iv = encode_iv
+ @encode_salt = encode_salt
+ @mode = mode
+ end
+
+ attr_reader :encode_iv, :encode_salt, :mode
+end
+
+class AttrEncryptedTest < Minitest::Test
+ def setup
+ @iv = SecureRandom.random_bytes(12)
+ end
+
+ def test_should_store_email_in_encrypted_attributes
+ assert User.encrypted_attributes.include?(:email)
+ end
+
+ def test_should_not_store_salt_in_encrypted_attributes
+ refute User.encrypted_attributes.include?(:salt)
+ end
+
+ def test_attr_encrypted_should_return_true_for_email
+ assert User.attr_encrypted?('email')
+ end
+
+ def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line
+ refute_equal User.encrypted_attributes[:email][:attribute], User.encrypted_attributes[:without_encoding][:attribute]
+ end
+
+ def test_attr_encrypted_should_return_false_for_salt
+ assert !User.attr_encrypted?('salt')
+ end
+
+ def test_should_generate_an_encrypted_attribute
+ assert User.new.respond_to?(:encrypted_email)
+ end
+
+ def test_should_generate_an_encrypted_attribute_with_a_prefix_and_suffix
+ assert User.new.respond_to?(:crypted_password_test)
+ end
+
+ def test_should_generate_an_encrypted_attribute_with_the_attribute_option
+ assert User.new.respond_to?(:ssn_encrypted)
+ end
+
+ def test_should_not_encrypt_nil_value
+ assert_nil User.encrypt_email(nil, iv: @iv)
+ end
+
+ def test_should_not_encrypt_empty_string_by_default
+ assert_equal '', User.encrypt_email('', iv: @iv)
+ end
+
+ def test_should_encrypt_email
+ refute_nil User.encrypt_email('test@example.com', iv: @iv)
+ refute_equal 'test@example.com', User.encrypt_email('test@example.com', iv: @iv)
+ end
+
+ def test_should_encrypt_email_when_modifying_the_attr_writer
+ @user = User.new
+ assert_nil @user.encrypted_email
+ @user.email = 'test@example.com'
+ refute_nil @user.encrypted_email
+ iv = @user.encrypted_email_iv.unpack('m').first
+ salt = @user.encrypted_email_salt[1..-1].unpack('m').first
+ assert_equal User.encrypt_email('test@example.com', iv: iv, salt: salt), @user.encrypted_email
+ end
+
+ def test_should_not_decrypt_nil_value
+ assert_nil User.decrypt_email(nil, iv: @iv)
+ end
+
+ def test_should_not_decrypt_empty_string
+ assert_equal '', User.decrypt_email('', iv: @iv)
+ end
+
+ def test_should_decrypt_email
+ encrypted_email = User.encrypt_email('test@example.com', iv: @iv)
+ refute_equal 'test@test.com', encrypted_email
+ assert_equal 'test@example.com', User.decrypt_email(encrypted_email, iv: @iv)
+ end
+
+ def test_should_decrypt_email_when_reading
+ @user = User.new
+ assert_nil @user.email
+ options = @user.encrypted_attributes[:email]
+ iv = @user.send(:generate_iv, options[:algorithm])
+ encoded_iv = [iv].pack(options[:encode_iv])
+ salt = SecureRandom.random_bytes
+ encoded_salt = @user.send(:prefix_and_encode_salt, salt, options[:encode_salt])
+ @user.encrypted_email = User.encrypt_email('test@example.com', iv: iv, salt: salt)
+ @user.encrypted_email_iv = encoded_iv
+ @user.encrypted_email_salt = encoded_salt
+ assert_equal 'test@example.com', @user.email
+ end
+
+ def test_should_encrypt_with_encoding
+ assert_equal User.encrypt_with_encoding('test', iv: @iv), [User.encrypt_without_encoding('test', iv: @iv)].pack('m')
+ end
+
+ def test_should_decrypt_with_encoding
+ encrypted = User.encrypt_with_encoding('test', iv: @iv)
+ assert_equal 'test', User.decrypt_with_encoding(encrypted, iv: @iv)
+ assert_equal User.decrypt_with_encoding(encrypted, iv: @iv), User.decrypt_without_encoding(encrypted.unpack('m').first, iv: @iv)
+ end
+
+ def test_should_encrypt_with_custom_encoding
+ assert_equal User.encrypt_with_encoding('test', iv: @iv), [User.encrypt_without_encoding('test', iv: @iv)].pack('m')
+ end
+
+ def test_should_decrypt_with_custom_encoding
+ encrypted = User.encrypt_with_encoding('test', iv: @iv)
+ assert_equal 'test', User.decrypt_with_encoding(encrypted, iv: @iv)
+ assert_equal User.decrypt_with_encoding(encrypted, iv: @iv), User.decrypt_without_encoding(encrypted.unpack('m').first, iv: @iv)
+ end
+
+ def test_should_encrypt_with_marshaling
+ @user = User.new
+ @user.with_marshaling = [1, 2, 3]
+ refute_nil @user.encrypted_with_marshaling
+ end
+
+ def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
+ assert_equal SillyEncryptor.silly_encrypt(:value => 'testing', :some_arg => 'test'), User.encrypt_credit_card('testing')
+ end
+
+ def test_should_evaluate_a_key_passed_as_a_symbol
+ @user = User.new
+ assert_nil @user.ssn_encrypted
+ @user.ssn = 'testing'
+ refute_nil @user.ssn_encrypted
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt.unpack("m").first )
+ assert_equal encrypted, @user.ssn_encrypted
+ end
+
+ def test_should_evaluate_a_key_passed_as_a_proc
+ @user = User.new
+ assert_nil @user.crypted_password_test
+ @user.password = 'testing'
+ refute_nil @user.crypted_password_test
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt.unpack("m").first)
+ assert_equal encrypted, @user.crypted_password_test
+ end
+
+ def test_should_use_options_found_in_the_attr_encrypted_options_attribute
+ @user = User.new
+ assert_nil @user.crypted_password_test
+ @user.password = 'testing'
+ refute_nil @user.crypted_password_test
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt.unpack("m").first)
+ assert_equal encrypted, @user.crypted_password_test
+ end
+
+ def test_should_inherit_encrypted_attributes
+ assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort
+ end
+
+ def test_should_inherit_attr_encrypted_options
+ assert !User.attr_encrypted_options.empty?
+ assert_equal User.attr_encrypted_options, Admin.attr_encrypted_options
+ end
+
+ def test_should_not_inherit_unrelated_attributes
+ assert SomeOtherClass.attr_encrypted_options.empty?
+ assert SomeOtherClass.encrypted_attributes.empty?
+ end
+
+ def test_should_evaluate_a_symbol_option
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, :class)
+ end
+
+ def test_should_evaluate_a_proc_option
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
+ end
+
+ def test_should_evaluate_a_lambda_option
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
+ end
+
+ def test_should_evaluate_a_method_option
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call))
+ end
+
+ def test_should_return_a_string_option
+ class_string = 'SomeOtherClass'
+ assert_equal class_string, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, class_string)
+ end
+
+ def test_should_encrypt_with_true_if
+ @user = User.new
+ assert_nil @user.encrypted_with_true_if
+ @user.with_true_if = 'testing'
+ refute_nil @user.encrypted_with_true_if
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt.unpack("m").first)
+ assert_equal encrypted, @user.encrypted_with_true_if
+ end
+
+ def test_should_not_encrypt_with_false_if
+ @user = User.new
+ assert_nil @user.encrypted_with_false_if
+ @user.with_false_if = 'testing'
+ refute_nil @user.encrypted_with_false_if
+ assert_equal 'testing', @user.encrypted_with_false_if
+ end
+
+ def test_should_encrypt_with_false_unless
+ @user = User.new
+ assert_nil @user.encrypted_with_false_unless
+ @user.with_false_unless = 'testing'
+ refute_nil @user.encrypted_with_false_unless
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt.unpack("m").first)
+ assert_equal encrypted, @user.encrypted_with_false_unless
+ end
+
+ def test_should_not_encrypt_with_true_unless
+ @user = User.new
+ assert_nil @user.encrypted_with_true_unless
+ @user.with_true_unless = 'testing'
+ refute_nil @user.encrypted_with_true_unless
+ assert_equal 'testing', @user.encrypted_with_true_unless
+ end
+
+ def test_should_encrypt_empty_with_truthy_allow_empty_value_option
+ @user = User.new
+ assert_nil @user.encrypted_with_allow_empty_value
+ @user.with_allow_empty_value = ''
+ refute_nil @user.encrypted_with_allow_empty_value
+ assert_equal '', @user.with_allow_empty_value
+ @user = User.new
+ @user.with_allow_empty_value = nil
+ refute_nil @user.encrypted_with_allow_empty_value
+ assert_nil @user.with_allow_empty_value
+ end
+
+ def test_should_work_with_aliased_attr_encryptor
+ assert User.encrypted_attributes.include?(:aliased)
+ end
+
+ def test_should_always_reset_options
+ @user = User.new
+ @user.with_if_changed = "encrypt_stuff"
+
+ @user = User.new
+ @user.should_encrypt = false
+ @user.with_if_changed = "not_encrypted_stuff"
+ assert_equal "not_encrypted_stuff", @user.with_if_changed
+ assert_equal "not_encrypted_stuff", @user.encrypted_with_if_changed
+ end
+
+ def test_should_cast_values_as_strings_before_encrypting
+ string_encrypted_email = User.encrypt_email('3', iv: @iv)
+ assert_equal string_encrypted_email, User.encrypt_email(3, iv: @iv)
+ assert_equal '3', User.decrypt_email(string_encrypted_email, iv: @iv)
+ end
+
+ def test_should_create_query_accessor
+ @user = User.new
+ assert !@user.email?
+ @user.email = ''
+ assert !@user.email?
+ @user.email = 'test@example.com'
+ assert @user.email?
+ end
+
+ def test_should_vary_iv_per_attribute
+ @user = User.new
+ @user.email = 'email@example.com'
+ @user.password = 'p455w0rd'
+ refute_equal @user.encrypted_email_iv, @user.crypted_password_test_iv
+ end
+
+ def test_should_generate_iv_per_attribute_by_default
+ thing = YetAnotherClass.new(email: 'thing@thing.com')
+ refute_nil thing.encrypted_email_iv
+ end
+
+ def test_should_vary_iv_per_instance
+ @user1 = User.new
+ @user1.email = 'email@example.com'
+ @user2 = User.new
+ @user2.email = 'email@example.com'
+ refute_equal @user1.encrypted_email_iv, @user2.encrypted_email_iv
+ refute_equal @user1.encrypted_email, @user2.encrypted_email
+ end
+
+ def test_should_vary_salt_per_attribute
+ @user = User.new
+ @user.email = 'email@example.com'
+ @user.password = 'p455w0rd'
+ refute_equal @user.encrypted_email_salt, @user.crypted_password_test_salt
+ end
+
+ def test_should_vary_salt_per_instance
+ @user1 = User.new
+ @user1.email = 'email@example.com'
+ @user2 = User.new
+ @user2.email = 'email@example.com'
+ refute_equal @user1.encrypted_email_salt, @user2.encrypted_email_salt
+ end
+
+ def test_should_not_generate_salt_per_attribute_by_default
+ thing = YetAnotherClass.new(email: 'thing@thing.com')
+ assert_nil thing.encrypted_email_salt
+ end
+
+ def test_should_decrypt_second_record
+ @user1 = User.new
+ @user1.email = 'test@example.com'
+
+ @user2 = User.new
+ @user2.email = 'test@example.com'
+
+ assert_equal 'test@example.com', @user1.decrypt(:email, @user1.encrypted_email)
+ end
+
+ def test_should_specify_the_default_algorithm
+ assert YetAnotherClass.encrypted_attributes[:email][:algorithm]
+ assert_equal YetAnotherClass.encrypted_attributes[:email][:algorithm], 'aes-256-gcm'
+ end
+
+ def test_should_not_encode_iv_when_encode_iv_is_false
+ email = 'thing@thing.com'
+ thing = YetAnotherClass.new(email: email)
+ refute thing.encrypted_email_iv =~ base64_encoding_regex
+ assert_equal thing.email, email
+ end
+
+ def test_should_base64_encode_iv_by_default
+ phone_number = '555-555-5555'
+ thing = YetAnotherClass.new
+ thing.phone_number = phone_number
+ assert thing.encrypted_phone_number_iv =~ base64_encoding_regex
+ assert_equal thing.phone_number, phone_number
+ end
+
+ def test_should_generate_unique_iv_for_every_encrypt_operation
+ user = User.new
+ user.email = 'initial_value@test.com'
+ original_iv = user.encrypted_email_iv
+ user.email = 'revised_value@test.com'
+ refute_equal original_iv, user.encrypted_email_iv
+ end
+
+ def test_should_not_generate_iv_for_attribute_when_if_option_is_false
+ user = User.new
+ user.with_false_if = 'derp'
+ assert_nil user.encrypted_with_false_if_iv
+ end
+
+ def test_should_generate_iv_for_attribute_when_if_option_is_true
+ user = User.new
+ user.with_true_if = 'derp'
+ refute_nil user.encrypted_with_true_if_iv
+
+ user.with_true_if = Object.new
+ refute_nil user.encrypted_with_true_if_iv
+ end
+
+ def test_should_not_generate_salt_for_attribute_when_if_option_is_false
+ user = User.new
+ user.with_false_if = 'derp'
+ assert_nil user.encrypted_with_false_if_salt
+ end
+
+ def test_should_generate_salt_for_attribute_when_if_option_is_true
+ user = User.new
+ user.with_true_if = 'derp'
+ refute_nil user.encrypted_with_true_if_salt
+ end
+
+ def test_should_generate_iv_for_attribute_when_unless_option_is_false
+ user = User.new
+ user.with_false_unless = 'derp'
+ refute_nil user.encrypted_with_false_unless_iv
+ end
+
+ def test_should_not_generate_iv_for_attribute_when_unless_option_is_true
+ user = User.new
+ user.with_true_unless = 'derp'
+ assert_nil user.encrypted_with_true_unless_iv
+ end
+
+ def test_should_generate_salt_for_attribute_when_unless_option_is_false
+ user = User.new
+ user.with_false_unless = 'derp'
+ refute_nil user.encrypted_with_false_unless_salt
+ end
+
+ def test_should_not_generate_salt_for_attribute_when_unless_option_is_true
+ user = User.new
+ user.with_true_unless = 'derp'
+ assert_nil user.encrypted_with_true_unless_salt
+ end
+
+ def test_should_not_by_default_generate_iv_when_attribute_is_empty
+ user = User.new
+ user.with_true_if = nil
+ assert_nil user.encrypted_with_true_if_iv
+ end
+
+ def test_encrypted_attributes_state_is_not_shared
+ user = User.new
+ user.ssn = '123456789'
+
+ another_user = User.new
+
+ assert_equal :encrypting, user.encrypted_attributes[:ssn][:operation]
+ assert_nil another_user.encrypted_attributes[:ssn][:operation]
+ end
+
+ def test_should_not_by_default_generate_key_when_attribute_is_empty
+ user = User.new
+ calls = 0
+ user.stub(:secret_key, lambda { calls += 1; SECRET_KEY }) do
+ user.ssn
+ end
+ assert_equal 0, calls
+ end
+end
diff --git a/vendor/gems/attr_encrypted/test/compatibility_test.rb b/vendor/gems/attr_encrypted/test/compatibility_test.rb
new file mode 100644
index 00000000000..7585895e16e
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/compatibility_test.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+# -*- encoding: utf-8 -*-
+require_relative 'test_helper'
+
+# Test to ensure that existing representations in database do not break on
+# migrating to new versions of this gem. This ensures that future versions of
+# this gem will retain backwards compatibility with data generated by earlier
+# versions.
+class CompatibilityTest < Minitest::Test
+ class NonmarshallingPet < ActiveRecord::Base
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
+
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:insecure_mode] = true
+
+ attr_encrypted :nickname,
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
+ attr_encrypted :birthdate,
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
+ end
+
+ class MarshallingPet < ActiveRecord::Base
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
+
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:insecure_mode] = true
+
+ attr_encrypted :nickname,
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
+ :marshal => true
+ attr_encrypted :birthdate,
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
+ :marshal => true
+ end
+
+ def setup
+ drop_all_tables
+ create_tables
+ end
+
+ def test_nonmarshalling_backwards_compatibility
+ pet = NonmarshallingPet.create!(
+ :name => 'Fido',
+ :encrypted_nickname => 'E4lJTxFG/EfkfPg5MpnriQ==',
+ :encrypted_nickname_iv => 'z4Q8deE4h7f6S8NNZcbPNg==',
+ :encrypted_nickname_salt => 'adcd833001a873db',
+ :encrypted_birthdate => '6uKEAiFVdJw+N5El+U6Gow==',
+ :encrypted_birthdate_iv => 'zxtc1XPssL4s2HwA69nORQ==',
+ :encrypted_birthdate_salt => '4f879270045eaad7'
+ )
+
+ assert_equal 'Fido', pet.name
+ assert_equal 'Fido the Dog', pet.nickname
+ assert_equal '2011-07-09', pet.birthdate
+ end
+
+ def test_marshalling_backwards_compatibility
+ pet = MarshallingPet.create!(
+ :name => 'Fido',
+ :encrypted_nickname => 'EsQScJYkPw80vVGvKWkE37Px99HHpXPFjoEPTNa4rbs=',
+ :encrypted_nickname_iv => 'fNq1OZcGvty4KfcvGTcFSw==',
+ :encrypted_nickname_salt => '733b459b7d34c217',
+ :encrypted_birthdate => '+VUlKQGfNWkOgCwI4hv+3qlGIwh9h6cJ/ranJlaxvU+xxQdL3H3cOzTcI2rkYkdR',
+ :encrypted_birthdate_iv => 'Ka+zF/SwEYZKwVa24lvFfA==',
+ :encrypted_birthdate_salt => 'd5e892d5bbd81566'
+ )
+
+ assert_equal 'Fido', pet.name
+ assert_equal 'Mummy\'s little helper', pet.nickname
+
+ assert_equal Date.new(2011, 7, 9), pet.birthdate
+ end
+
+ private
+
+ def create_tables
+ ActiveRecord::Schema.define(:version => 1) do
+ create_table :nonmarshalling_pets do |t|
+ t.string :name
+ t.string :encrypted_nickname
+ t.string :encrypted_nickname_iv
+ t.string :encrypted_nickname_salt
+ t.string :encrypted_birthdate
+ t.string :encrypted_birthdate_iv
+ t.string :encrypted_birthdate_salt
+ end
+ create_table :marshalling_pets do |t|
+ t.string :name
+ t.string :encrypted_nickname
+ t.string :encrypted_nickname_iv
+ t.string :encrypted_nickname_salt
+ t.string :encrypted_birthdate
+ t.string :encrypted_birthdate_iv
+ t.string :encrypted_birthdate_salt
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
diff --git a/vendor/gems/attr_encrypted/test/data_mapper_test.rb b/vendor/gems/attr_encrypted/test/data_mapper_test.rb
new file mode 100644
index 00000000000..3fb284a6ca4
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/data_mapper_test.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+DataMapper.setup(:default, 'sqlite3::memory:')
+
+class Client
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :encrypted_email, String
+ property :encrypted_email_iv, String
+ property :encrypted_email_salt, String
+
+ property :encrypted_credentials, Text
+ property :encrypted_credentials_iv, Text
+ property :encrypted_credentials_salt, Text
+
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+
+ attr_encrypted :email, :key => SECRET_KEY
+ attr_encrypted :credentials, :key => SECRET_KEY, :marshal => true
+
+ def initialize(attrs = {})
+ super attrs
+ self.credentials ||= { :username => 'example', :password => 'test' }
+ end
+end
+
+DataMapper.auto_migrate!
+
+class DataMapperTest < Minitest::Test
+
+ def setup
+ Client.all.each(&:destroy)
+ end
+
+ def test_should_encrypt_email
+ @client = Client.new :email => 'test@example.com'
+ assert @client.save
+ refute_nil @client.encrypted_email
+ refute_equal @client.email, @client.encrypted_email
+ assert_equal @client.email, Client.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @client = Client.new
+ assert @client.save
+ refute_nil @client.encrypted_credentials
+ refute_equal @client.credentials, @client.encrypted_credentials
+ assert_equal @client.credentials, Client.first.credentials
+ assert Client.first.credentials.is_a?(Hash)
+ end
+
+ def test_should_encode_by_default
+ assert Client.attr_encrypted_options[:encode]
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/legacy_active_record_test.rb b/vendor/gems/attr_encrypted/test/legacy_active_record_test.rb
new file mode 100644
index 00000000000..802318570fa
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/legacy_active_record_test.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+# -*- encoding: utf-8 -*-
+require_relative 'test_helper'
+
+ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
+
+def create_people_table
+ ActiveRecord::Schema.define(:version => 1) do
+ create_table :legacy_people do |t|
+ t.string :encrypted_email
+ t.string :password
+ t.string :encrypted_credentials
+ t.string :salt
+ end
+ end
+end
+
+# The table needs to exist before defining the class
+create_people_table
+
+ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
+
+class LegacyPerson < ActiveRecord::Base
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ attr_encrypted :email, :key => 'a secret key'
+ attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true
+
+ ActiveSupport::Deprecation.silenced = true
+ def after_initialize; end
+ ActiveSupport::Deprecation.silenced = false
+
+ after_initialize :initialize_salt_and_credentials
+
+ protected
+
+ def initialize_salt_and_credentials
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
+ self.credentials ||= { :username => 'example', :password => 'test' }
+ rescue ActiveRecord::MissingAttributeError
+ end
+end
+
+class LegacyPersonWithValidation < LegacyPerson
+ validates_presence_of :email
+ validates_uniqueness_of :encrypted_email
+end
+
+class LegacyActiveRecordTest < Minitest::Test
+
+ def setup
+ drop_all_tables
+ create_people_table
+ end
+
+ def test_should_decrypt_with_correct_encoding
+ if defined?(Encoding)
+ @person = LegacyPerson.create :email => 'test@example.com'
+ assert_equal 'UTF-8', LegacyPerson.first.email.encoding.name
+ end
+ end
+
+ def test_should_encrypt_email
+ @person = LegacyPerson.create :email => 'test@example.com'
+ refute_nil @person.encrypted_email
+ refute_equal @person.email, @person.encrypted_email
+ assert_equal @person.email, LegacyPerson.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @person = LegacyPerson.create
+ refute_nil @person.encrypted_credentials
+ refute_equal @person.credentials, @person.encrypted_credentials
+ assert_equal @person.credentials, LegacyPerson.first.credentials
+ end
+
+ def test_should_find_by_email
+ @person = LegacyPerson.create(:email => 'test@example.com')
+ assert_equal @person, LegacyPerson.find_by_email('test@example.com')
+ end
+
+ def test_should_find_by_email_and_password
+ LegacyPerson.create(:email => 'test@example.com', :password => 'invalid')
+ @person = LegacyPerson.create(:email => 'test@example.com', :password => 'test')
+ assert_equal @person, LegacyPerson.find_by_email_and_password('test@example.com', 'test')
+ end
+
+ def test_should_scope_by_email
+ @person = LegacyPerson.create(:email => 'test@example.com')
+ assert_equal @person, LegacyPerson.scoped_by_email('test@example.com').first rescue NoMethodError
+ end
+
+ def test_should_scope_by_email_and_password
+ LegacyPerson.create(:email => 'test@example.com', :password => 'invalid')
+ @person = LegacyPerson.create(:email => 'test@example.com', :password => 'test')
+ assert_equal @person, LegacyPerson.scoped_by_email_and_password('test@example.com', 'test').first rescue NoMethodError
+ end
+
+ def test_should_encode_by_default
+ assert LegacyPerson.attr_encrypted_options[:encode]
+ end
+
+ def test_should_validate_presence_of_email
+ @person = LegacyPersonWithValidation.new
+ assert !@person.valid?
+ assert !@person.errors[:email].empty? || @person.errors.on(:email)
+ end
+
+ def test_should_validate_uniqueness_of_email
+ @person = LegacyPersonWithValidation.new :email => 'test@example.com'
+ assert @person.save
+ @person2 = LegacyPersonWithValidation.new :email => @person.email
+ assert !@person2.valid?
+ assert !@person2.errors[:encrypted_email].empty? || @person2.errors.on(:encrypted_email)
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb b/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb
new file mode 100644
index 00000000000..875086d2351
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb
@@ -0,0 +1,300 @@
+# frozen_string_literal: true
+
+# -*- encoding: utf-8 -*-
+require_relative 'test_helper'
+
+class LegacySillyEncryptor
+ def self.silly_encrypt(options)
+ (options[:value] + options[:some_arg]).reverse
+ end
+
+ def self.silly_decrypt(options)
+ options[:value].reverse.gsub(/#{options[:some_arg]}$/, '')
+ end
+end
+
+class LegacyUser
+ extend AttrEncrypted
+ self.attr_encrypted_options[:key] = Proc.new { |user| user.class.to_s } # default key
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ attr_encrypted :email, :without_encoding, :key => 'secret key'
+ attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
+ attr_encrypted :ssn, :key => :salt, :attribute => 'ssn_encrypted'
+ attr_encrypted :credit_card, :encryptor => LegacySillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt, :some_arg => 'test'
+ attr_encrypted :with_encoding, :key => 'secret key', :encode => true
+ attr_encrypted :with_custom_encoding, :key => 'secret key', :encode => 'm'
+ attr_encrypted :with_marshaling, :key => 'secret key', :marshal => true
+ attr_encrypted :with_true_if, :key => 'secret key', :if => true
+ attr_encrypted :with_false_if, :key => 'secret key', :if => false
+ attr_encrypted :with_true_unless, :key => 'secret key', :unless => true
+ attr_encrypted :with_false_unless, :key => 'secret key', :unless => false
+ attr_encrypted :with_if_changed, :key => 'secret key', :if => :should_encrypt
+
+ attr_encryptor :aliased, :key => 'secret_key'
+
+ attr_accessor :salt
+ attr_accessor :should_encrypt
+
+ def initialize
+ self.salt = Time.now.to_i.to_s
+ self.should_encrypt = true
+ end
+end
+
+class LegacyAdmin < LegacyUser
+ attr_encrypted :testing
+end
+
+class LegacySomeOtherClass
+ extend AttrEncrypted
+ def self.call(object)
+ object.class
+ end
+end
+
+class LegacyAttrEncryptedTest < Minitest::Test
+
+ def test_should_store_email_in_encrypted_attributes
+ assert LegacyUser.encrypted_attributes.include?(:email)
+ end
+
+ def test_should_not_store_salt_in_encrypted_attributes
+ assert !LegacyUser.encrypted_attributes.include?(:salt)
+ end
+
+ def test_attr_encrypted_should_return_true_for_email
+ assert LegacyUser.attr_encrypted?('email')
+ end
+
+ def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line
+ refute_equal LegacyUser.encrypted_attributes[:email][:attribute], LegacyUser.encrypted_attributes[:without_encoding][:attribute]
+ end
+
+ def test_attr_encrypted_should_return_false_for_salt
+ assert !LegacyUser.attr_encrypted?('salt')
+ end
+
+ def test_should_generate_an_encrypted_attribute
+ assert LegacyUser.new.respond_to?(:encrypted_email)
+ end
+
+ def test_should_generate_an_encrypted_attribute_with_a_prefix_and_suffix
+ assert LegacyUser.new.respond_to?(:crypted_password_test)
+ end
+
+ def test_should_generate_an_encrypted_attribute_with_the_attribute_option
+ assert LegacyUser.new.respond_to?(:ssn_encrypted)
+ end
+
+ def test_should_not_encrypt_nil_value
+ assert_nil LegacyUser.encrypt_email(nil)
+ end
+
+ def test_should_not_encrypt_empty_string
+ assert_equal '', LegacyUser.encrypt_email('')
+ end
+
+ def test_should_encrypt_email
+ refute_nil LegacyUser.encrypt_email('test@example.com')
+ refute_equal 'test@example.com', LegacyUser.encrypt_email('test@example.com')
+ end
+
+ def test_should_encrypt_email_when_modifying_the_attr_writer
+ @user = LegacyUser.new
+ assert_nil @user.encrypted_email
+ @user.email = 'test@example.com'
+ refute_nil @user.encrypted_email
+ assert_equal LegacyUser.encrypt_email('test@example.com'), @user.encrypted_email
+ end
+
+ def test_should_not_decrypt_nil_value
+ assert_nil LegacyUser.decrypt_email(nil)
+ end
+
+ def test_should_not_decrypt_empty_string
+ assert_equal '', LegacyUser.decrypt_email('')
+ end
+
+ def test_should_decrypt_email
+ encrypted_email = LegacyUser.encrypt_email('test@example.com')
+ refute_equal 'test@test.com', encrypted_email
+ assert_equal 'test@example.com', LegacyUser.decrypt_email(encrypted_email)
+ end
+
+ def test_should_decrypt_email_when_reading
+ @user = LegacyUser.new
+ assert_nil @user.email
+ @user.encrypted_email = LegacyUser.encrypt_email('test@example.com')
+ assert_equal 'test@example.com', @user.email
+ end
+
+ def test_should_encrypt_with_encoding
+ assert_equal LegacyUser.encrypt_with_encoding('test'), [LegacyUser.encrypt_without_encoding('test')].pack('m')
+ end
+
+ def test_should_decrypt_with_encoding
+ encrypted = LegacyUser.encrypt_with_encoding('test')
+ assert_equal 'test', LegacyUser.decrypt_with_encoding(encrypted)
+ assert_equal LegacyUser.decrypt_with_encoding(encrypted), LegacyUser.decrypt_without_encoding(encrypted.unpack('m').first)
+ end
+
+ def test_should_decrypt_utf8_with_encoding
+ encrypted = LegacyUser.encrypt_with_encoding("test\xC2\xA0utf-8\xC2\xA0text")
+ assert_equal "test\xC2\xA0utf-8\xC2\xA0text", LegacyUser.decrypt_with_encoding(encrypted)
+ assert_equal LegacyUser.decrypt_with_encoding(encrypted), LegacyUser.decrypt_without_encoding(encrypted.unpack('m').first)
+ end
+
+ def test_should_encrypt_with_custom_encoding
+ assert_equal LegacyUser.encrypt_with_custom_encoding('test'), [LegacyUser.encrypt_without_encoding('test')].pack('m')
+ end
+
+ def test_should_decrypt_with_custom_encoding
+ encrypted = LegacyUser.encrypt_with_custom_encoding('test')
+ assert_equal 'test', LegacyUser.decrypt_with_custom_encoding(encrypted)
+ assert_equal LegacyUser.decrypt_with_custom_encoding(encrypted), LegacyUser.decrypt_without_encoding(encrypted.unpack('m').first)
+ end
+
+ def test_should_encrypt_with_marshaling
+ @user = LegacyUser.new
+ @user.with_marshaling = [1, 2, 3]
+ refute_nil @user.encrypted_with_marshaling
+ assert_equal LegacyUser.encrypt_with_marshaling([1, 2, 3]), @user.encrypted_with_marshaling
+ end
+
+ def test_should_decrypt_with_marshaling
+ encrypted = LegacyUser.encrypt_with_marshaling([1, 2, 3])
+ @user = LegacyUser.new
+ assert_nil @user.with_marshaling
+ @user.encrypted_with_marshaling = encrypted
+ assert_equal [1, 2, 3], @user.with_marshaling
+ end
+
+ def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
+ assert_equal LegacySillyEncryptor.silly_encrypt(:value => 'testing', :some_arg => 'test'), LegacyUser.encrypt_credit_card('testing')
+ end
+
+ def test_should_evaluate_a_key_passed_as_a_symbol
+ @user = LegacyUser.new
+ assert_nil @user.ssn_encrypted
+ @user.ssn = 'testing'
+ refute_nil @user.ssn_encrypted
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt, insecure_mode: true, algorithm: 'aes-256-cbc'), @user.ssn_encrypted
+ end
+
+ def test_should_evaluate_a_key_passed_as_a_proc
+ @user = LegacyUser.new
+ assert_nil @user.crypted_password_test
+ @user.password = 'testing'
+ refute_nil @user.crypted_password_test
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.crypted_password_test
+ end
+
+ def test_should_use_options_found_in_the_attr_encrypted_options_attribute
+ @user = LegacyUser.new
+ assert_nil @user.crypted_password_test
+ @user.password = 'testing'
+ refute_nil @user.crypted_password_test
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.crypted_password_test
+ end
+
+ def test_should_inherit_encrypted_attributes
+ assert_equal [LegacyUser.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, LegacyAdmin.encrypted_attributes.keys.collect { |key| key.to_s }.sort
+ end
+
+ def test_should_inherit_attr_encrypted_options
+ assert !LegacyUser.attr_encrypted_options.empty?
+ assert_equal LegacyUser.attr_encrypted_options, LegacyAdmin.attr_encrypted_options
+ end
+
+ def test_should_not_inherit_unrelated_attributes
+ assert LegacySomeOtherClass.attr_encrypted_options.empty?
+ assert LegacySomeOtherClass.encrypted_attributes.empty?
+ end
+
+ def test_should_evaluate_a_symbol_option
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, :class)
+ end
+
+ def test_should_evaluate_a_proc_option
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
+ end
+
+ def test_should_evaluate_a_lambda_option
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
+ end
+
+ def test_should_evaluate_a_method_option
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, LegacySomeOtherClass.method(:call))
+ end
+
+ def test_should_return_a_string_option
+ class_string = 'LegacySomeOtherClass'
+ assert_equal class_string, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, class_string)
+ end
+
+ def test_should_encrypt_with_true_if
+ @user = LegacyUser.new
+ assert_nil @user.encrypted_with_true_if
+ @user.with_true_if = 'testing'
+ refute_nil @user.encrypted_with_true_if
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.encrypted_with_true_if
+ end
+
+ def test_should_not_encrypt_with_false_if
+ @user = LegacyUser.new
+ assert_nil @user.encrypted_with_false_if
+ @user.with_false_if = 'testing'
+ refute_nil @user.encrypted_with_false_if
+ assert_equal 'testing', @user.encrypted_with_false_if
+ end
+
+ def test_should_encrypt_with_false_unless
+ @user = LegacyUser.new
+ assert_nil @user.encrypted_with_false_unless
+ @user.with_false_unless = 'testing'
+ refute_nil @user.encrypted_with_false_unless
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.encrypted_with_false_unless
+ end
+
+ def test_should_not_encrypt_with_true_unless
+ @user = LegacyUser.new
+ assert_nil @user.encrypted_with_true_unless
+ @user.with_true_unless = 'testing'
+ refute_nil @user.encrypted_with_true_unless
+ assert_equal 'testing', @user.encrypted_with_true_unless
+ end
+
+ def test_should_work_with_aliased_attr_encryptor
+ assert LegacyUser.encrypted_attributes.include?(:aliased)
+ end
+
+ def test_should_always_reset_options
+ @user = LegacyUser.new
+ @user.with_if_changed = "encrypt_stuff"
+
+ @user = LegacyUser.new
+ @user.should_encrypt = false
+ @user.with_if_changed = "not_encrypted_stuff"
+ assert_equal "not_encrypted_stuff", @user.with_if_changed
+ assert_equal "not_encrypted_stuff", @user.encrypted_with_if_changed
+ end
+
+ def test_should_cast_values_as_strings_before_encrypting
+ string_encrypted_email = LegacyUser.encrypt_email('3')
+ assert_equal string_encrypted_email, LegacyUser.encrypt_email(3)
+ assert_equal '3', LegacyUser.decrypt_email(string_encrypted_email)
+ end
+
+ def test_should_create_query_accessor
+ @user = LegacyUser.new
+ assert !@user.email?
+ @user.email = ''
+ assert !@user.email?
+ @user.email = 'test@example.com'
+ assert @user.email?
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/legacy_compatibility_test.rb b/vendor/gems/attr_encrypted/test/legacy_compatibility_test.rb
new file mode 100644
index 00000000000..68985816f94
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/legacy_compatibility_test.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+# -*- encoding: utf-8 -*-
+require_relative 'test_helper'
+
+# Test to ensure that existing representations in database do not break on
+# migrating to new versions of this gem. This ensures that future versions of
+# this gem will retain backwards compatibility with data generated by earlier
+# versions.
+class LegacyCompatibilityTest < Minitest::Test
+ class LegacyNonmarshallingPet < ActiveRecord::Base
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
+
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ attr_encrypted :nickname,
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
+ attr_encrypted :birthdate,
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
+ end
+
+ class LegacyMarshallingPet < ActiveRecord::Base
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
+
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ attr_encrypted :nickname,
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
+ :marshal => true
+ attr_encrypted :birthdate,
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
+ :marshal => true
+ end
+
+ def setup
+ drop_all_tables
+ create_tables
+ end
+
+ def test_nonmarshalling_backwards_compatibility
+ pet = LegacyNonmarshallingPet.create!(
+ :name => 'Fido',
+ :encrypted_nickname => 'uSUB6KGzta87yxesyVc3DA==',
+ :encrypted_birthdate => 'I3d691B2PtFXLx15kO067g=='
+ )
+
+ assert_equal 'Fido', pet.name
+ assert_equal 'Fido the Dog', pet.nickname
+ assert_equal '2011-07-09', pet.birthdate
+ end
+
+ def test_marshalling_backwards_compatibility
+ pet = LegacyMarshallingPet.create!(
+ :name => 'Fido',
+ :encrypted_nickname => '7RwoT64in4H+fGVBPYtRcN0K4RtriIy1EP4nDojUa8g=',
+ :encrypted_birthdate => 'bSp9sJhXQSp2QlNZHiujtcK4lRVBE8HQhn1y7moQ63bGJR20hvRSZ73ePAmm+wc5'
+ )
+
+ assert_equal 'Fido', pet.name
+ assert_equal 'Mummy\'s little helper', pet.nickname
+
+ assert_equal Date.new(2011, 7, 9), pet.birthdate
+ end
+
+ private
+
+ def create_tables
+ ActiveRecord::Schema.define(:version => 1) do
+ create_table :legacy_nonmarshalling_pets do |t|
+ t.string :name
+ t.string :encrypted_nickname
+ t.string :encrypted_birthdate
+ t.string :salt
+ end
+ create_table :legacy_marshalling_pets do |t|
+ t.string :name
+ t.string :encrypted_nickname
+ t.string :encrypted_birthdate
+ t.string :salt
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
diff --git a/vendor/gems/attr_encrypted/test/legacy_data_mapper_test.rb b/vendor/gems/attr_encrypted/test/legacy_data_mapper_test.rb
new file mode 100644
index 00000000000..03916dd9728
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/legacy_data_mapper_test.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+DataMapper.setup(:default, 'sqlite3::memory:')
+
+class LegacyClient
+ include DataMapper::Resource
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ property :id, Serial
+ property :encrypted_email, String
+ property :encrypted_credentials, Text
+ property :salt, String
+
+ attr_encrypted :email, :key => 'a secret key', mode: :single_iv_and_salt
+ attr_encrypted :credentials, :key => Proc.new { |client| Encryptor.encrypt(:value => client.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true, mode: :single_iv_and_salt
+
+ def initialize(attrs = {})
+ super attrs
+ self.salt ||= Digest::SHA1.hexdigest((Time.now.to_i * rand(5)).to_s)
+ self.credentials ||= { :username => 'example', :password => 'test' }
+ end
+end
+
+DataMapper.auto_migrate!
+
+class LegacyDataMapperTest < Minitest::Test
+
+ def setup
+ LegacyClient.all.each(&:destroy)
+ end
+
+ def test_should_encrypt_email
+ @client = LegacyClient.new :email => 'test@example.com'
+ assert @client.save
+ refute_nil @client.encrypted_email
+ refute_equal @client.email, @client.encrypted_email
+ assert_equal @client.email, LegacyClient.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @client = LegacyClient.new
+ assert @client.save
+ refute_nil @client.encrypted_credentials
+ refute_equal @client.credentials, @client.encrypted_credentials
+ assert_equal @client.credentials, LegacyClient.first.credentials
+ assert LegacyClient.first.credentials.is_a?(Hash)
+ end
+
+ def test_should_encode_by_default
+ assert LegacyClient.attr_encrypted_options[:encode]
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/legacy_sequel_test.rb b/vendor/gems/attr_encrypted/test/legacy_sequel_test.rb
new file mode 100644
index 00000000000..fd46301e25e
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/legacy_sequel_test.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+DB.create_table :legacy_humans do
+ primary_key :id
+ column :encrypted_email, :string
+ column :password, :string
+ column :encrypted_credentials, :string
+ column :salt, :string
+end
+
+class LegacyHuman < Sequel::Model(:legacy_humans)
+ self.attr_encrypted_options[:insecure_mode] = true
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
+
+ attr_encrypted :email, :key => 'a secret key', mode: :single_iv_and_salt
+ attr_encrypted :credentials, :key => Proc.new { |human| Encryptor.encrypt(:value => human.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true, mode: :single_iv_and_salt
+
+ def after_initialize(attrs = {})
+ self.salt ||= Digest::SHA1.hexdigest((Time.now.to_i * rand(5)).to_s)
+ self.credentials ||= { :username => 'example', :password => 'test' }
+ end
+end
+
+class LegacySequelTest < Minitest::Test
+
+ def setup
+ LegacyHuman.all.each(&:destroy)
+ end
+
+ def test_should_encrypt_email
+ @human = LegacyHuman.new :email => 'test@example.com'
+ assert @human.save
+ refute_nil @human.encrypted_email
+ refute_equal @human.email, @human.encrypted_email
+ assert_equal @human.email, LegacyHuman.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @human = LegacyHuman.new
+ assert @human.save
+ refute_nil @human.encrypted_credentials
+ refute_equal @human.credentials, @human.encrypted_credentials
+ assert_equal @human.credentials, LegacyHuman.first.credentials
+ assert LegacyHuman.first.credentials.is_a?(Hash)
+ end
+
+ def test_should_encode_by_default
+ assert LegacyHuman.attr_encrypted_options[:encode]
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/run.sh b/vendor/gems/attr_encrypted/test/run.sh
new file mode 100755
index 00000000000..7e9b777eebf
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/run.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env sh -e
+
+for RUBY in 1.9.3 2.0.0 2.1 2.2
+do
+ for RAILS in 2.3.8 3.0.0 3.1.0 3.2.0 4.0.0 4.1.0 4.2.0
+ do
+ if [[ $RUBY -gt 1.9.3 && $RAILS -lt 4.0.0 ]]; then
+ continue
+ fi
+ RBENV_VERSION=$RUBY ACTIVERECORD=$RAILS bundle && bundle exec rake
+ done
+done
diff --git a/vendor/gems/attr_encrypted/test/sequel_test.rb b/vendor/gems/attr_encrypted/test/sequel_test.rb
new file mode 100644
index 00000000000..1df520319b1
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/sequel_test.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+DB.create_table :humans do
+ primary_key :id
+ column :encrypted_email, :string
+ column :encrypted_email_salt, String
+ column :encrypted_email_iv, :string
+ column :password, :string
+ column :encrypted_credentials, :string
+ column :encrypted_credentials_iv, :string
+ column :encrypted_credentials_salt, String
+end
+
+class Human < Sequel::Model(:humans)
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+
+ attr_encrypted :email, :key => SECRET_KEY
+ attr_encrypted :credentials, :key => SECRET_KEY, :marshal => true
+
+ def after_initialize(attrs = {})
+ self.credentials ||= { :username => 'example', :password => 'test' }
+ end
+end
+
+class SequelTest < Minitest::Test
+
+ def setup
+ Human.all.each(&:destroy)
+ end
+
+ def test_should_encrypt_email
+ @human = Human.new :email => 'test@example.com'
+ assert @human.save
+ refute_nil @human.encrypted_email
+ refute_equal @human.email, @human.encrypted_email
+ assert_equal @human.email, Human.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+
+ @human = Human.new :credentials => { :username => 'example', :password => 'test' }
+ assert @human.save
+ refute_nil @human.encrypted_credentials
+ refute_equal @human.credentials, @human.encrypted_credentials
+ assert_equal @human.credentials, Human.first.credentials
+ assert Human.first.credentials.is_a?(Hash)
+ end
+
+ def test_should_encode_by_default
+ assert Human.attr_encrypted_options[:encode]
+ end
+
+end
diff --git a/vendor/gems/attr_encrypted/test/test_helper.rb b/vendor/gems/attr_encrypted/test/test_helper.rb
new file mode 100644
index 00000000000..091e81bb9d7
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/test_helper.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'simplecov'
+require 'simplecov-rcov'
+require "codeclimate-test-reporter"
+
+SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
+ [
+ SimpleCov::Formatter::HTMLFormatter,
+ SimpleCov::Formatter::RcovFormatter,
+ CodeClimate::TestReporter::Formatter
+ ]
+)
+
+# Disabling for now since there are issues with Ruby 3 support.
+# See https://gitlab.com/gitlab-org/ruby/gems/attr_encrypted/-/merge_requests/1
+#
+# SimpleCov.start do
+# add_filter 'test'
+# end
+
+CodeClimate::TestReporter.start
+
+require 'minitest/autorun'
+
+# Rails 4.0.x pins to an old minitest
+unless defined?(MiniTest::Test)
+ MiniTest::Test = MiniTest::Unit::TestCase
+end
+
+require 'active_record'
+require 'data_mapper'
+require 'digest/sha2'
+require 'sequel'
+ActiveSupport::Deprecation.behavior = :raise
+
+$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+$:.unshift(File.dirname(__FILE__))
+require 'attr_encrypted'
+
+DB = if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_sym == :jruby
+ Sequel.jdbc('jdbc:sqlite::memory:')
+else
+ Sequel.sqlite
+end
+
+# The :after_initialize hook was removed in Sequel 4.0
+# and had been deprecated for a while before that:
+# http://sequel.rubyforge.org/rdoc-plugins/classes/Sequel/Plugins/AfterInitialize.html
+# This plugin re-enables it.
+Sequel::Model.plugin :after_initialize
+
+SECRET_KEY = SecureRandom.random_bytes(32)
+
+def base64_encoding_regex
+ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/
+end
+
+def drop_all_tables
+ connection = ActiveRecord::Base.connection
+ tables = (ActiveRecord::VERSION::MAJOR >= 5 ? connection.data_sources : connection.tables)
+ tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
+end
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum
index cf70611c97a..1670ac8e688 100644
--- a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum
@@ -21,6 +21,7 @@
{"name":"marcel","version":"1.0.2","platform":"ruby","checksum":"a013b677ef46cbcb49fd5c59b3d35803d2ee04dd75d8bfdc43533fc5a31f7e4e"},
{"name":"method_source","version":"1.0.0","platform":"ruby","checksum":"d779455a2b5666a079ce58577bfad8534f571af7cec8107f4dce328f0981dede"},
{"name":"mini_mime","version":"1.1.2","platform":"ruby","checksum":"a54aec0cc7438a03a850adb00daca2bdb60747f839e28186994df057cea87151"},
+{"name":"mini_portile2","version":"2.8.0","platform":"ruby","checksum":"1e06b286ff19b73cfc9193cb3dd2bd80416f8262443564b25b23baea74a05765"},
{"name":"minitest","version":"5.16.2","platform":"ruby","checksum":"c1be0c6b57fab451faa08e74ffa71e7d6a259b90f4bacb881c7f4808ec8b4991"},
{"name":"nio4r","version":"2.5.8","platform":"java","checksum":"b2b1800f6bf7ce4b797ca8b639ad278a99c9c904fb087a91d944f38e4bd71401"},
{"name":"nio4r","version":"2.5.8","platform":"ruby","checksum":"3becb4ad95ab8ac0a9bd2e1b16466869402be62848082bf6329ae9091f276676"},
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock
index 8f4bb5fa40d..d633184e300 100644
--- a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock
@@ -76,11 +76,11 @@ GEM
marcel (1.0.2)
method_source (1.0.0)
mini_mime (1.1.2)
+ mini_portile2 (2.8.0)
minitest (5.16.2)
nio4r (2.5.8)
- nokogiri (1.13.8-arm64-darwin)
- racc (~> 1.4)
- nokogiri (1.13.8-x86_64-linux)
+ nokogiri (1.13.8)
+ mini_portile2 (~> 2.8.0)
racc (~> 1.4)
racc (1.6.0)
rack (2.2.4)
@@ -129,11 +129,10 @@ GEM
zeitwerk (2.6.0)
PLATFORMS
- arm64-darwin-21
- x86_64-linux
+ ruby
DEPENDENCIES
rails (~> 6.1.6.1)
BUNDLED WITH
- 2.3.19
+ 2.3.22
diff --git a/vendor/gems/devise-pbkdf2-encryptable/Gemfile.lock b/vendor/gems/devise-pbkdf2-encryptable/Gemfile.lock
index ce0cb0c1025..617ee7d91f5 100644
--- a/vendor/gems/devise-pbkdf2-encryptable/Gemfile.lock
+++ b/vendor/gems/devise-pbkdf2-encryptable/Gemfile.lock
@@ -3,6 +3,7 @@ PATH
specs:
devise-pbkdf2-encryptable (0.0.0)
devise (~> 4.0)
+ devise-two-factor (~> 4.0)
GEM
remote: https://rubygems.org/
@@ -28,6 +29,8 @@ GEM
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
+ attr_encrypted (3.1.0)
+ encryptor (~> 3.0.0)
bcrypt (3.1.18)
builder (3.2.4)
concurrent-ruby (1.1.10)
@@ -38,7 +41,14 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
+ devise-two-factor (4.0.2)
+ activesupport (< 7.1)
+ attr_encrypted (>= 1.3, < 4, != 2)
+ devise (~> 4.0)
+ railties (< 7.1)
+ rotp (~> 6.0)
diff-lcs (1.5.0)
+ encryptor (3.0.0)
erubi (1.10.0)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
@@ -71,6 +81,7 @@ GEM
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
+ rotp (6.2.0)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
diff --git a/vendor/gems/devise-pbkdf2-encryptable/devise-pbkdf2-encryptable.gemspec b/vendor/gems/devise-pbkdf2-encryptable/devise-pbkdf2-encryptable.gemspec
index e507633c0bf..9c7e3dd5af5 100644
--- a/vendor/gems/devise-pbkdf2-encryptable/devise-pbkdf2-encryptable.gemspec
+++ b/vendor/gems/devise-pbkdf2-encryptable/devise-pbkdf2-encryptable.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
spec.version = '0.0.0'
spec.add_runtime_dependency 'devise', '~> 4.0'
+ spec.add_runtime_dependency 'devise-two-factor', '~> 4.0'
spec.add_development_dependency 'activemodel', '~> 6.1', '< 8'
spec.add_development_dependency 'rspec', '~> 3.10.0'
diff --git a/vendor/gems/devise-pbkdf2-encryptable/lib/devise-pbkdf2-encryptable.rb b/vendor/gems/devise-pbkdf2-encryptable/lib/devise-pbkdf2-encryptable.rb
index 4db9b82052f..3f635fde280 100644
--- a/vendor/gems/devise-pbkdf2-encryptable/lib/devise-pbkdf2-encryptable.rb
+++ b/vendor/gems/devise-pbkdf2-encryptable/lib/devise-pbkdf2-encryptable.rb
@@ -1 +1,2 @@
require "devise/pbkdf2_encryptable/encryptable"
+require "devise/models/two_factor_backupable_pbkdf2"
diff --git a/vendor/gems/devise-pbkdf2-encryptable/lib/devise/models/two_factor_backupable_pbkdf2.rb b/vendor/gems/devise-pbkdf2-encryptable/lib/devise/models/two_factor_backupable_pbkdf2.rb
new file mode 100644
index 00000000000..eef906f5377
--- /dev/null
+++ b/vendor/gems/devise-pbkdf2-encryptable/lib/devise/models/two_factor_backupable_pbkdf2.rb
@@ -0,0 +1,58 @@
+module Devise
+ module Models
+ module TwoFactorBackupablePbkdf2
+ extend ActiveSupport::Concern
+
+ # 1) Invalidates all existing backup codes
+ # 2) Generates otp_number_of_backup_codes backup codes
+ # 3) Stores the hashed backup codes in the database
+ # 4) Returns a plaintext array of the generated backup codes
+ #
+ def generate_otp_backup_codes_pbkdf2!
+ codes = []
+ number_of_codes = self.class.otp_number_of_backup_codes
+ code_length = self.class.otp_backup_code_length
+
+ number_of_codes.times do
+ codes << SecureRandom.hex(code_length / 2) # Hexstring has length 2*n
+ end
+
+ hashed_codes = codes.map do |code|
+ Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.digest(
+ code,
+ Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512::STRETCHES,
+ Devise.friendly_token[0, 16])
+ end
+
+ self.otp_backup_codes = hashed_codes
+
+ codes
+ end
+
+ # Returns true and invalidates the given code if that code is a valid
+ # backup code.
+ #
+ def invalidate_otp_backup_code_pdkdf2!(code)
+ codes = self.otp_backup_codes || []
+
+ codes.each do |backup_code|
+ next unless Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.compare(backup_code, code)
+
+ codes.delete(backup_code)
+ self.otp_backup_codes = codes
+ return true
+ end
+
+ false
+ end
+
+ protected
+
+ module ClassMethods
+ Devise::Models.config(self, :otp_backup_code_length,
+ :otp_number_of_backup_codes,
+ :pepper)
+ end
+ end
+ end
+end
diff --git a/vendor/gems/devise-pbkdf2-encryptable/spec/lib/models/two_factor_backupable_pbkdf2_spec.rb b/vendor/gems/devise-pbkdf2-encryptable/spec/lib/models/two_factor_backupable_pbkdf2_spec.rb
new file mode 100644
index 00000000000..bc1e6c47109
--- /dev/null
+++ b/vendor/gems/devise-pbkdf2-encryptable/spec/lib/models/two_factor_backupable_pbkdf2_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'active_model'
+
+class TwoFactorBackupablePbkdf2Double
+ extend ::ActiveModel::Callbacks
+ include ::ActiveModel::Validations::Callbacks
+ extend ::Devise::Models
+
+ # stub out the ::ActiveRecord::Encryption::EncryptableRecord API
+ attr_accessor :otp_secret
+ def self.encrypts(*attrs)
+ nil
+ end
+
+ define_model_callbacks :update
+
+ devise :two_factor_backupable, otp_number_of_backup_codes: 10
+ devise :two_factor_backupable_pbkdf2
+
+ attr_accessor :otp_backup_codes
+end
+
+module Gitlab
+ class FIPS
+ def enabled?
+ end
+ end
+end
+
+RSpec.describe ::Devise::Models::TwoFactorBackupablePbkdf2 do
+ subject { TwoFactorBackupablePbkdf2Double.new }
+
+ describe '#generate_otp_backup_codes_pbkdf2!' do
+ context 'with no existing recovery codes' do
+ before do
+ @plaintext_codes = subject.generate_otp_backup_codes_pbkdf2!
+ end
+
+ it 'generates the correct number of new recovery codes' do
+ expect(subject.otp_backup_codes.length).to eq(subject.class.otp_number_of_backup_codes)
+ end
+
+ it 'generates recovery codes of the correct length' do
+ @plaintext_codes.each do |code|
+ expect(code.length).to eq(subject.class.otp_backup_code_length)
+ end
+ end
+
+ it 'generates distinct recovery codes' do
+ expect(@plaintext_codes.uniq).to contain_exactly(*@plaintext_codes)
+ end
+
+ it 'stores the codes as pbkdf2 hashes' do
+ subject.otp_backup_codes.each do |code|
+ expect(code.start_with?("$pbkdf2-sha512$")).to be_truthy
+ end
+ end
+ end
+ end
+
+ describe '#invalidate_otp_backup_code_pdkdf2!' do
+ before do
+ @plaintext_codes = subject.generate_otp_backup_codes_pbkdf2!
+ end
+
+ context 'given an invalid recovery code' do
+ it 'returns false' do
+ expect(subject.invalidate_otp_backup_code_pdkdf2!('password')).to be false
+ end
+ end
+
+ context 'given a valid recovery code' do
+ it 'returns true' do
+ @plaintext_codes.each do |code|
+ expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be true
+ end
+ end
+
+ it 'invalidates that recovery code' do
+ code = @plaintext_codes.sample
+
+ subject.invalidate_otp_backup_code_pdkdf2!(code)
+ expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be false
+ end
+
+ it 'does not invalidate the other recovery codes' do
+ code = @plaintext_codes.sample
+ subject.invalidate_otp_backup_code_pdkdf2!(code)
+
+ @plaintext_codes.delete(code)
+
+ @plaintext_codes.each do |code|
+ expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be true
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/devise-pbkdf2-encryptable/spec/spec_helper.rb b/vendor/gems/devise-pbkdf2-encryptable/spec/spec_helper.rb
index ced0cf6fdab..932fd3b8452 100644
--- a/vendor/gems/devise-pbkdf2-encryptable/spec/spec_helper.rb
+++ b/vendor/gems/devise-pbkdf2-encryptable/spec/spec_helper.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
require 'devise'
+require 'devise-two-factor'
require 'devise/pbkdf2_encryptable/encryptable'
+require 'devise/models/two_factor_backupable_pbkdf2'
diff --git a/vendor/gems/microsoft_graph_mailer/README.md b/vendor/gems/microsoft_graph_mailer/README.md
index dd9dfecfc56..c87748ffdf9 100644
--- a/vendor/gems/microsoft_graph_mailer/README.md
+++ b/vendor/gems/microsoft_graph_mailer/README.md
@@ -1,6 +1,6 @@
# microsoft_graph_mailer
-This gem allows delivery of emails using [Microsoft Graph API](https://docs.microsoft.com/en-us/graph/api/user-sendmail) with [OAuth 2.0 client credentials flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).
+This gem allows delivery of emails using [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/api/user-sendmail) with [OAuth 2.0 client credentials flow](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).
## The reason for this gem
@@ -30,7 +30,7 @@ gem install microsoft_graph_mailer
To use the Microsoft Graph API to send mails, you will
need to create an application in the Azure Active Directory. See the
-[Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details:
+[Microsoft instructions](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details:
1. Sign in to the [Azure portal](https://portal.azure.com).
1. Search for and select `Azure Active Directory`.
diff --git a/vendor/gems/omniauth-gitlab/Gemfile.lock b/vendor/gems/omniauth-gitlab/Gemfile.lock
index b59ba59b95b..9f69874e124 100644
--- a/vendor/gems/omniauth-gitlab/Gemfile.lock
+++ b/vendor/gems/omniauth-gitlab/Gemfile.lock
@@ -3,7 +3,7 @@ PATH
specs:
omniauth-gitlab (4.0.0)
omniauth (~> 2.0)
- omniauth-oauth2 (~> 1.7.1)
+ omniauth-oauth2 (~> 1.8)
GEM
remote: https://rubygems.org/
@@ -28,9 +28,9 @@ GEM
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
- omniauth-oauth2 (1.7.3)
+ omniauth-oauth2 (1.8.0)
oauth2 (>= 1.4, < 3)
- omniauth (>= 1.9, < 3)
+ omniauth (~> 2.0)
rack (2.2.4)
rack-protection (2.2.2)
rack
diff --git a/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec b/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
index ca4b8d904f0..82f7c55ee02 100644
--- a/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
+++ b/vendor/gems/omniauth-gitlab/omniauth-gitlab.gemspec
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
gem.require_paths = ['lib']
gem.add_dependency 'omniauth', '~> 2.0'
- gem.add_dependency 'omniauth-oauth2', '~> 1.7.1'
+ gem.add_dependency 'omniauth-oauth2', '~> 1.8'
gem.add_development_dependency 'rspec', '~> 3.1'
gem.add_development_dependency 'rspec-its', '~> 1.0'
gem.add_development_dependency 'simplecov'
diff --git a/vendor/gems/omniauth-google-oauth2/.gitlab-ci.yml b/vendor/gems/omniauth-google-oauth2/.gitlab-ci.yml
deleted file mode 100644
index dbc4a7c16b1..00000000000
--- a/vendor/gems/omniauth-google-oauth2/.gitlab-ci.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-workflow:
- rules:
- - if: $CI_MERGE_REQUEST_ID
-
-.rspec:
- cache:
- key: omniauth-google-oauth2
- paths:
- - vendor/gems/omniauth-google-oauth2/vendor/ruby
- before_script:
- - cd vendor/gems/omniauth-google-oauth2
- - ruby -v # Print out ruby version for debugging
- - gem install bundler --no-document # Bundler is not installed with the image
- - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby
- - bundle config set with 'development'
- - bundle config set --local frozen 'true' # Disallow Gemfile.lock changes on CI
- - bundle config # Show bundler configuration
- - bundle install -j $(nproc)
- script:
- - bundle exec rspec
-
-rspec-2.7:
- image: "ruby:2.7"
- extends: .rspec
-
-rspec-3.0:
- image: "ruby:3.0"
- extends: .rspec
diff --git a/vendor/gems/omniauth-google-oauth2/CHANGELOG.md b/vendor/gems/omniauth-google-oauth2/CHANGELOG.md
deleted file mode 100644
index 5b252048fd6..00000000000
--- a/vendor/gems/omniauth-google-oauth2/CHANGELOG.md
+++ /dev/null
@@ -1,354 +0,0 @@
-# Changelog
-All notable changes to this project will be documented in this file.
-
-## 1.0.1 - 2022-03-10
-
-### Added
-- Output granted scopes in credentials block of the auth hash.
-- Migrated to GitHub actions.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Overriding the `redirect_uri` via params or JSON request body.
-
-## 1.0.0 - 2021-03-14
-
-### Added
-- Support for Omniauth 2.x!
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Support for Omniauth 1.x.
-
-### Fixed
-- Nothing.
-
-## 0.8.2 - 2021-03-14
-
-### Added
-- Constrains the version to Omniauth 1.x.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Nothing.
-
-## 0.8.1 - 2020-12-12
-
-### Added
-- Support reading the access token from a json request body.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- No longer verify the iat claim for JWT.
-
-### Fixed
-- A few minor issues with .rubocop.yml.
-- Issues with image resizing code when the image came with size information from Google.
-
-## 0.8.0 - 2019-08-21
-
-### Added
-- Updated omniauth-oauth2 to v1.6.0 for security fixes.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Ruby 2.1 support.
-
-### Fixed
-- Nothing.
-
-## 0.7.0 - 2019-06-03
-
-### Added
-- Ensure `info[:email]` is always verified, and include `unverified_email`
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Nothing.
-
-## 0.6.1 - 2019-03-07
-
-### Added
-- Return `email` and `email_verified` keys in response.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Nothing.
-
-## 0.6.0 - 2018-12-28
-
-### Added
-- Support for JWT 2.x.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Support for JWT 1.x.
-- Support for `raw_friend_info` and `raw_image_info`.
-- Stop using Google+ API endpoints.
-
-### Fixed
-- Nothing.
-
-## 0.5.4 - 2018-12-07
-
-### Added
-- New recommended endpoints for Google OAuth.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Nothing.
-
-## 0.5.3 - 2018-01-25
-
-### Added
-- Added support for the JWT 2.x gem.
-- Now fully qualifies the `JWT` class to prevent conflicts with the `Omniauth::JWT` strategy.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Removed the `multijson` dependency.
-- Support for versions of `omniauth-oauth2` < 1.5.
-
-### Fixed
-- Nothing.
-
-## 0.5.2 - 2017-07-30
-
-### Added
-- Nothing.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- New `authorize_url` and `token_url` endpoints are reverted until JWT 2.0 ships.
-
-### Fixed
-- Nothing.
-
-## 0.5.1 - 2017-07-19
-
-### Added
-- *Breaking* JWT iss verification can be enabled/disabled with the `verify_iss` flag - see the README for more details.
-- Authorize options now includes `device_id` and `device_name` for private ip ranges.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Updated `authorize_url` and `token_url` to new endpoints.
-
-## 0.5.0 - 2017-05-29
-
-### Added
-- Rubocop checks to specs.
-- Defaulted dev environment to ruby 2.3.4.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Testing support for older versions of ruby not supported by OmniAuth 1.5.
-- Key `[:urls]['Google']` no longer exists, it has been renamed to `[:urls][:google]`.
-
-### Fixed
-- Updated all code to rubocop conventions. This includes the Ruby 1.9 hash syntax when appropriate.
-- Example javascript flow now picks up ENV vars for google key and secret.
-
-## 0.4.1 - 2016-03-14
-
-### Added
-- Nothing.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Fixed JWT iat leeway by requiring ruby-jwt 1.5.2
-
-## 0.4.0 - 2016-03-11
-
-### Added
-- Addedd ability to specify multiple hosted domains.
-- Added a default leeway of 1 minute to JWT token validation.
-- Now requires ruby-jwt 1.5.x.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Removed support for ruby 1.9.3 as ruby-jwt 1.5.x does not support it.
-
-### Fixed
-- Nothing.
-
-## 0.3.1 - 2016-01-28
-
-### Added
-- Verify Hosted Domain if hd is set in options.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Dependency on addressable.
-
-### Fixed
-- Nothing.
-
-## 0.3.0 - 2016-01-09
-
-### Added
-- Updated verify_token to use the v3 tokeninfo endpoint.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Compatibility with omniauth-oauth2 1.4.0
-
-## 0.2.10 - 2015-11-05
-
-### Added
-- Nothing.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Removed some checks on the id_token. Now only parses the id_token in the JWT processing.
-
-### Fixed
-- Nothing.
-
-## 0.2.9 - 2015-10-29
-
-### Added
-- Nothing.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Issue with omniauth-oauth2 where redirect_uri was handled improperly. We now lock the dependency to ~> 1.3.1
-
-## 0.2.8 - 2015-10-01
-
-### Added
-- Added skip_jwt option to bypass JWT decoding in case you get decoding errors.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Resolved JWT::InvalidIatError. https://github.com/zquestz/omniauth-google-oauth2/issues/195
-
-## 0.2.7 - 2015-09-25
-
-### Added
-- Now strips out the 'sz' parameter from profile image urls.
-- Now uses 'addressable' gem for URI actions.
-- Added image data to extras hash.
-- Override validation on JWT token for open_id token.
-- Handle authorization codes coming from an installed applications.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Fixes double slashes in google image urls.
-
-## 0.2.6 - 2014-10-26
-
-### Added
-- Nothing.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Hybrid authorization issues due to bad method alias.
-
-## 0.2.5 - 2014-07-09
-
-### Added
-- Support for versions of omniauth past 1.0.x.
-
-### Deprecated
-- Nothing.
-
-### Removed
-- Nothing.
-
-### Fixed
-- Nothing.
-
-## 0.2.4 - 2014-04-25
-
-### Added
-- Now requiring the "Contacts API" and "Google+ API" to be enabled in your Google API console.
-
-### Deprecated
-- The old Google OAuth API support was removed without deprecation.
-
-### Removed
-- Support for the old Google OAuth API. `OAuth2::Error` will be thrown and state that access is not configured when you attempt to authenticate using the old API. See Added section for this release.
-
-### Fixed
-- Nothing.
diff --git a/vendor/gems/omniauth-google-oauth2/Gemfile b/vendor/gems/omniauth-google-oauth2/Gemfile
deleted file mode 100644
index 7f4f5e950d1..00000000000
--- a/vendor/gems/omniauth-google-oauth2/Gemfile
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-source 'https://rubygems.org'
-
-gemspec
diff --git a/vendor/gems/omniauth-google-oauth2/Gemfile.lock b/vendor/gems/omniauth-google-oauth2/Gemfile.lock
deleted file mode 100644
index 6c3f5ff3f68..00000000000
--- a/vendor/gems/omniauth-google-oauth2/Gemfile.lock
+++ /dev/null
@@ -1,87 +0,0 @@
-PATH
- remote: .
- specs:
- omniauth-google-oauth2 (1.0.1)
- jwt (>= 2.0)
- oauth2 (~> 2.0)
- omniauth (~> 2.0)
- omniauth-oauth2 (~> 1.7.1)
-
-GEM
- remote: https://rubygems.org/
- specs:
- ast (2.4.2)
- diff-lcs (1.5.0)
- faraday (2.5.2)
- faraday-net_http (>= 2.0, < 3.1)
- ruby2_keywords (>= 0.0.4)
- faraday-net_http (3.0.0)
- hashie (5.0.0)
- jwt (2.4.1)
- multi_xml (0.6.0)
- oauth2 (2.0.3)
- faraday (>= 0.17.3, < 3.0)
- jwt (>= 1.0, < 3.0)
- multi_xml (~> 0.5)
- rack (>= 1.2, < 3)
- rash_alt (>= 0.4, < 1)
- version_gem (~> 1.0)
- omniauth (2.1.0)
- hashie (>= 3.4.6)
- rack (>= 2.2.3)
- rack-protection
- omniauth-oauth2 (1.7.3)
- oauth2 (>= 1.4, < 3)
- omniauth (>= 1.9, < 3)
- parallel (1.22.1)
- parser (3.1.2.0)
- ast (~> 2.4.1)
- rack (2.2.4)
- rack-protection (2.2.2)
- rack
- rainbow (3.1.1)
- rake (12.3.3)
- rash_alt (0.4.12)
- hashie (>= 3.4)
- regexp_parser (2.5.0)
- rexml (3.2.5)
- rspec (3.11.0)
- rspec-core (~> 3.11.0)
- rspec-expectations (~> 3.11.0)
- rspec-mocks (~> 3.11.0)
- rspec-core (3.11.0)
- rspec-support (~> 3.11.0)
- rspec-expectations (3.11.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-mocks (3.11.1)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-support (3.11.0)
- rubocop (0.93.1)
- parallel (~> 1.10)
- parser (>= 2.7.1.5)
- rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.8)
- rexml
- rubocop-ast (>= 0.6.0)
- ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (1.19.1)
- parser (>= 3.1.1.0)
- ruby-progressbar (1.11.0)
- ruby2_keywords (0.0.5)
- unicode-display_width (1.8.0)
- version_gem (1.1.0)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- omniauth-google-oauth2!
- rake (~> 12.0)
- rspec (~> 3.6)
- rubocop (~> 0.49)
-
-BUNDLED WITH
- 2.3.21
diff --git a/vendor/gems/omniauth-google-oauth2/README.md b/vendor/gems/omniauth-google-oauth2/README.md
deleted file mode 100644
index 80c611392ca..00000000000
--- a/vendor/gems/omniauth-google-oauth2/README.md
+++ /dev/null
@@ -1,368 +0,0 @@
-[![Gem Version](https://badge.fury.io/rb/omniauth-google-oauth2.svg)](https://badge.fury.io/rb/omniauth-google-oauth2)
-
-# OmniAuth Google OAuth2 Strategy
-
-Strategy to authenticate with Google via OAuth2 in OmniAuth.
-
-Get your API key at: https://code.google.com/apis/console/ Note the Client ID and the Client Secret.
-
-For more details, read the Google docs: https://developers.google.com/accounts/docs/OAuth2
-
-## Installation
-
-Add to your `Gemfile`:
-
-```ruby
-gem 'omniauth-google-oauth2'
-```
-
-Then `bundle install`.
-
-## Google API Setup
-
-* Go to 'https://console.developers.google.com'
-* Select your project.
-* Go to Credentials, then select the "OAuth consent screen" tab on top, and provide an 'EMAIL ADDRESS' and a 'PRODUCT NAME'
-* Wait 10 minutes for changes to take effect.
-
-## Usage
-
-Here's an example for adding the middleware to a Rails app in `config/initializers/omniauth.rb`:
-
-```ruby
-Rails.application.config.middleware.use OmniAuth::Builder do
- provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']
-end
-OmniAuth.config.allowed_request_methods = %i[get]
-```
-
-You can now access the OmniAuth Google OAuth2 URL: `/auth/google_oauth2`
-
-For more examples please check out `examples/omni_auth.rb`
-
-NOTE: While developing your application, if you change the scope in the initializer you will need to restart your app server. Remember that either the 'email' or 'profile' scope is required!
-
-## Configuration
-
-You can configure several options, which you pass in to the `provider` method via a hash:
-
-* `scope`: A comma-separated list of permissions you want to request from the user. See the [Google OAuth 2.0 Playground](https://developers.google.com/oauthplayground/) for a full list of available permissions. Caveats:
- * The `email` and `profile` scopes are used by default. By defining your own `scope`, you override these defaults, but Google requires at least one of `email` or `profile`, so make sure to add at least one of them to your scope!
- * Scopes starting with `https://www.googleapis.com/auth/` do not need that prefix specified. So while you can use the smaller scope `books` since that permission starts with the mentioned prefix, you should use the full scope URL `https://docs.google.com/feeds/` to access a user's docs, for example.
-
-* `redirect_uri`: Override the redirect_uri used by the gem.
-
-* `prompt`: A space-delimited list of string values that determines whether the user is re-prompted for authentication and/or consent. Possible values are:
- * `none`: No authentication or consent pages will be displayed; it will return an error if the user is not already authenticated and has not pre-configured consent for the requested scopes. This can be used as a method to check for existing authentication and/or consent.
- * `consent`: The user will always be prompted for consent, even if they have previously allowed access a given set of scopes.
- * `select_account`: The user will always be prompted to select a user account. This allows a user who has multiple current account sessions to select one amongst them.
-
- If no value is specified, the user only sees the authentication page if they are not logged in and only sees the consent page the first time they authorize a given set of scopes.
-
-* `image_aspect_ratio`: The shape of the user's profile picture. Possible values are:
- * `original`: Picture maintains its original aspect ratio.
- * `square`: Picture presents equal width and height.
-
- Defaults to `original`.
-
-* `image_size`: The size of the user's profile picture. The image returned will have width equal to the given value and variable height, according to the `image_aspect_ratio` chosen. Additionally, a picture with specific width and height can be requested by setting this option to a hash with `width` and `height` as keys. If only `width` or `height` is specified, a picture whose width or height is closest to the requested size and requested aspect ratio will be returned. Defaults to the original width and height of the picture.
-
-* `name`: The name of the strategy. The default name is `google_oauth2` but it can be changed to any value, for example `google`. The OmniAuth URL will thus change to `/auth/google` and the `provider` key in the auth hash will then return `google`.
-
-* `access_type`: Defaults to `offline`, so a refresh token is sent to be used when the user is not present at the browser. Can be set to `online`. More about [offline access](https://developers.google.com/identity/protocols/OAuth2WebServer#offline)
-
-* `hd`: (Optional) Limit sign-in to a particular Google Apps hosted domain. This can be simply string `'domain.com'` or an array `%w(domain.com domain.co)`. More information at: https://developers.google.com/accounts/docs/OpenIDConnect#hd-param
-
-* `jwt_leeway`: Number of seconds passed to the JWT library as leeway. Defaults to 60 seconds. Note this only works if you use jwt 2.1, as the leeway option was removed in later versions.
-
-* `skip_jwt`: Skip JWT processing. This is for users who are seeing JWT decoding errors with the `iat` field. Always try adjusting the leeway before disabling JWT processing.
-
-* `login_hint`: When your app knows which user it is trying to authenticate, it can provide this parameter as a hint to the authentication server. Passing this hint suppresses the account chooser and either pre-fill the email box on the sign-in form, or select the proper session (if the user is using multiple sign-in), which can help you avoid problems that occur if your app logs in the wrong user account. The value can be either an email address or the sub string, which is equivalent to the user's Google+ ID.
-
-* `include_granted_scopes`: If this is provided with the value true, and the authorization request is granted, the authorization will include any previous authorizations granted to this user/application combination for other scopes. See Google's [Incremental Authorization](https://developers.google.com/accounts/docs/OAuth2WebServer#incrementalAuth) for additional details.
-
-* `openid_realm`: Set the OpenID realm value, to allow upgrading from OpenID based authentication to OAuth 2 based authentication. When this is set correctly an `openid_id` value will be set in `['extra']['id_info']` in the authentication hash with the value of the user's OpenID ID URL.
-
-* `provider_ignores_state`: You will need to set this to `true` when using the `One-time Code Flow` below. In this flow there is no server side redirect that would set the state.
-
-Here's an example of a possible configuration where the strategy name is changed, the user is asked for extra permissions, the user is always prompted to select their account when logging in and the user's profile picture is returned as a thumbnail:
-
-```ruby
-Rails.application.config.middleware.use OmniAuth::Builder do
- provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'],
- {
- scope: 'userinfo.email, userinfo.profile, http://gdata.youtube.com',
- prompt: 'select_account',
- image_aspect_ratio: 'square',
- image_size: 50
- }
-end
-```
-
-## Auth Hash
-
-Here's an example of an authentication hash available in the callback by accessing `request.env['omniauth.auth']`:
-
-```ruby
-{
- "provider" => "google_oauth2",
- "uid" => "100000000000000000000",
- "info" => {
- "name" => "John Smith",
- "email" => "john@example.com",
- "first_name" => "John",
- "last_name" => "Smith",
- "image" => "https://lh4.googleusercontent.com/photo.jpg",
- "urls" => {
- "google" => "https://plus.google.com/+JohnSmith"
- }
- },
- "credentials" => {
- "token" => "TOKEN",
- "refresh_token" => "REFRESH_TOKEN",
- "expires_at" => 1496120719,
- "expires" => true
- },
- "extra" => {
- "id_token" => "ID_TOKEN",
- "id_info" => {
- "azp" => "APP_ID",
- "aud" => "APP_ID",
- "sub" => "100000000000000000000",
- "email" => "john@example.com",
- "email_verified" => true,
- "at_hash" => "HK6E_P6Dh8Y93mRNtsDB1Q",
- "iss" => "accounts.google.com",
- "iat" => 1496117119,
- "exp" => 1496120719
- },
- "raw_info" => {
- "sub" => "100000000000000000000",
- "name" => "John Smith",
- "given_name" => "John",
- "family_name" => "Smith",
- "profile" => "https://plus.google.com/+JohnSmith",
- "picture" => "https://lh4.googleusercontent.com/photo.jpg?sz=50",
- "email" => "john@example.com",
- "email_verified" => "true",
- "locale" => "en",
- "hd" => "company.com"
- }
- }
-}
-```
-
-### Devise
-
-First define your application id and secret in `config/initializers/devise.rb`. Do not use the snippet mentioned in the [Usage](https://github.com/zquestz/omniauth-google-oauth2#usage) section.
-
-Configuration options can be passed as the last parameter here as key/value pairs.
-
-```ruby
-config.omniauth :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', {}
-```
-NOTE: If you are using this gem with devise with above snippet in `config/initializers/devise.rb` then do not create `config/initializers/omniauth.rb` which will conflict with devise configurations.
-
-Then add the following to 'config/routes.rb' so the callback routes are defined.
-
-```ruby
-devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
-```
-
-Make sure your model is omniauthable. Generally this is "/app/models/user.rb"
-
-```ruby
-devise :omniauthable, omniauth_providers: [:google_oauth2]
-```
-
-Then make sure your callbacks controller is setup.
-
-```ruby
-# app/controllers/users/omniauth_callbacks_controller.rb:
-
-class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
- def google_oauth2
- # You need to implement the method below in your model (e.g. app/models/user.rb)
- @user = User.from_omniauth(request.env['omniauth.auth'])
-
- if @user.persisted?
- flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
- sign_in_and_redirect @user, event: :authentication
- else
- session['devise.google_data'] = request.env['omniauth.auth'].except('extra') # Removing extra as it can overflow some session stores
- redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
- end
- end
-end
-```
-
-and bind to or create the user
-
-```ruby
-def self.from_omniauth(access_token)
- data = access_token.info
- user = User.where(email: data['email']).first
-
- # Uncomment the section below if you want users to be created if they don't exist
- # unless user
- # user = User.create(name: data['name'],
- # email: data['email'],
- # password: Devise.friendly_token[0,20]
- # )
- # end
- user
-end
-```
-
-For your views you can login using:
-
-```erb
-<%# omniauth-google-oauth2 1.0.x uses OmniAuth 2 and requires using HTTP Post to initiate authentication: %>
-<%= link_to "Sign in with Google", user_google_oauth2_omniauth_authorize_path, method: :post %>
-
-<%# omniauth-google-oauth2 prior 1.0.0: %>
-<%= link_to "Sign in with Google", user_google_oauth2_omniauth_authorize_path %>
-
-<%# Devise prior 4.1.0: %>
-<%= link_to "Sign in with Google", user_omniauth_authorize_path(:google_oauth2) %>
-```
-
-An overview is available at https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
-
-### One-time Code Flow (Hybrid Authentication)
-
-Google describes the One-time Code Flow [here](https://developers.google.com/identity/sign-in/web/server-side-flow). This hybrid authentication flow has significant functional and security advantages over a pure server-side or pure client-side flow. The following steps occur in this flow:
-
-1. The client (web browser) authenticates the user directly via Google's JS API. During this process assorted modals may be rendered by Google.
-2. On successful authentication, Google returns a one-time use code, which requires the Google client secret (which is only available server-side).
-3. Using a AJAX request, the code is POSTed to the Omniauth Google OAuth2 callback.
-4. The Omniauth Google OAuth2 gem will validate the code via a server-side request to Google. If the code is valid, then Google will return an access token and, if this is the first time this user is authenticating against this application, a refresh token. Both of these should be stored on the server. The response to the AJAX request indicates the success or failure of this process.
-
-This flow is immune to replay attacks, and conveys no useful information to a man in the middle.
-
-The omniauth-google-oauth2 gem supports this mode of operation when `provider_ignores_state` is set to `true`. Implementors simply need to add the appropriate JavaScript to their web page, and they can take advantage of this flow. An example JavaScript snippet follows.
-
-```javascript
-// Basic hybrid auth example following the pattern at:
-// https://developers.google.com/identity/sign-in/web/reference
-
-<script src="https://apis.google.com/js/platform.js?onload=init" async defer></script>
-
-...
-
-function init() {
- gapi.load('auth2', function() {
- // Ready.
- $('.google-login-button').click(function(e) {
- e.preventDefault();
-
- gapi.auth2.authorize({
- client_id: 'YOUR_CLIENT_ID',
- cookie_policy: 'single_host_origin',
- scope: 'email profile',
- response_type: 'code'
- }, function(response) {
- if (response && !response.error) {
- // google authentication succeed, now post data to server.
- jQuery.ajax({type: 'POST', url: '/auth/google_oauth2/callback', data: response,
- success: function(data) {
- // response from server
- }
- });
- } else {
- // google authentication failed
- }
- });
- });
- });
-};
-```
-
-#### Note about mobile clients (iOS, Android)
-
-The documentation at https://developers.google.com/identity/sign-in/ios/offline-access specifies the _REDIRECT_URI_ to be either a set value or an EMPTY string for mobile logins to work. Else, you will run into _redirect_uri_mismatch_ errors.
-
-In that case, ensure to send an additional parameter `redirect_uri=` (empty string) to the `/auth/google_oauth2/callback` URL from your mobile device.
-
-#### Note about CORS
-
-If you're making POST requests to `/auth/google_oauth2/callback` from another domain, then you need to make sure `'X-Requested-With': 'XMLHttpRequest'` header is included with your request, otherwise your server might respond with `OAuth2::Error, : Invalid Value` error.
-
-#### Getting around the `redirect_uri_mismatch` error (See [Issue #365](https://github.com/zquestz/omniauth-google-oauth2/issues/365))
-
-If you are struggling with a persistent `redirect_uri_mismatch`, you can instead pass the `access_token` from [`getAuthResponse`](https://developers.google.com/identity/sign-in/web/reference#googleusergetauthresponseincludeauthorizationdata) directly to the `auth/google_oauth2/callback` endpoint, like so:
-
-```javascript
-// Initialize the GoogleAuth object
-let googleAuth;
-gapi.load('client:auth2', async () => {
- await gapi.client.init({ scope: '...', client_id: '...' });
- googleAuth = gapi.auth2.getAuthInstance();
-});
-
-// Call this when the Google Sign In button is clicked
-async function signInGoogle() {
- const googleUser = await googleAuth.signIn(); // wait for the user to authorize through the modal
- const { access_token } = googleUser.getAuthResponse();
-
- const data = new FormData();
- data.append('access_token', access_token);
-
- const response = await api.post('/auth/google_oauth2/callback', data)
- console.log(response);
-}
-```
-
-#### Using Axios
-If you're making a GET resquests from another domain using `access_token`.
-```
-axios
- .get(
- 'url(path to your callback}',
- { params: { access_token: 'token' } },
- headers....
- )
-```
-
-If you're making a POST resquests from another domain using `access_token`.
-```
-axios
- .post(
- 'url(path to your callback}',
- { access_token: 'token' },
- headers....
- )
-
---OR--
-
-axios
- .post(
- 'url(path to your callback}',
- null,
- {
- params: {
- access_token: 'token'
- },
- headers....
- }
- )
-```
-
-## Fixing Protocol Mismatch for `redirect_uri` in Rails
-
-Just set the `full_host` in OmniAuth based on the Rails.env.
-
-```
-# config/initializers/omniauth.rb
-OmniAuth.config.full_host = Rails.env.production? ? 'https://domain.com' : 'http://localhost:3000'
-```
-
-## License
-
-Copyright (c) 2018 by Josh Ellithorpe
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/gems/omniauth-google-oauth2/Rakefile b/vendor/gems/omniauth-google-oauth2/Rakefile
deleted file mode 100644
index db36369bc12..00000000000
--- a/vendor/gems/omniauth-google-oauth2/Rakefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-require File.join('bundler', 'gem_tasks')
-require File.join('rspec', 'core', 'rake_task')
-
-RSpec::Core::RakeTask.new(:spec)
-
-task default: :spec
diff --git a/vendor/gems/omniauth-google-oauth2/examples/Gemfile b/vendor/gems/omniauth-google-oauth2/examples/Gemfile
deleted file mode 100644
index ba019344a67..00000000000
--- a/vendor/gems/omniauth-google-oauth2/examples/Gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-source 'https://rubygems.org'
-
-gem 'omniauth-google-oauth2', '~> 0.8.1'
-gem 'rubocop'
-gem 'sinatra', '~> 1.4'
-gem 'webrick'
diff --git a/vendor/gems/omniauth-google-oauth2/examples/Gemfile.lock b/vendor/gems/omniauth-google-oauth2/examples/Gemfile.lock
new file mode 100644
index 00000000000..5ac8f1be5e0
--- /dev/null
+++ b/vendor/gems/omniauth-google-oauth2/examples/Gemfile.lock
@@ -0,0 +1,72 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ ast (2.4.2)
+ faraday (2.5.2)
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.0)
+ hashie (5.0.0)
+ json (2.6.2)
+ jwt (2.5.0)
+ multi_json (1.15.0)
+ multi_xml (0.6.0)
+ oauth2 (1.4.11)
+ faraday (>= 0.17.3, < 3.0)
+ jwt (>= 1.0, < 3.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 4)
+ omniauth (1.9.2)
+ hashie (>= 3.4.6)
+ rack (>= 1.6.2, < 3)
+ omniauth-google-oauth2 (0.8.2)
+ jwt (>= 2.0)
+ oauth2 (~> 1.1)
+ omniauth (~> 1.1)
+ omniauth-oauth2 (>= 1.6)
+ omniauth-oauth2 (1.7.3)
+ oauth2 (>= 1.4, < 3)
+ omniauth (>= 1.9, < 3)
+ parallel (1.22.1)
+ parser (3.1.2.1)
+ ast (~> 2.4.1)
+ rack (1.6.13)
+ rack-protection (1.5.5)
+ rack
+ rainbow (3.1.1)
+ regexp_parser (2.6.0)
+ rexml (3.2.5)
+ rubocop (1.36.0)
+ json (~> 2.3)
+ parallel (~> 1.10)
+ parser (>= 3.1.2.1)
+ rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml (>= 3.2.5, < 4.0)
+ rubocop-ast (>= 1.20.1, < 2.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (>= 1.4.0, < 3.0)
+ rubocop-ast (1.21.0)
+ parser (>= 3.1.1.0)
+ ruby-progressbar (1.11.0)
+ ruby2_keywords (0.0.5)
+ sinatra (1.4.8)
+ rack (~> 1.5)
+ rack-protection (~> 1.4)
+ tilt (>= 1.3, < 3)
+ tilt (2.0.11)
+ unicode-display_width (2.3.0)
+ webrick (1.7.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ omniauth-google-oauth2 (~> 0.8.1)
+ rubocop
+ sinatra (~> 1.4)
+ webrick
+
+BUNDLED WITH
+ 2.3.22
diff --git a/vendor/gems/omniauth-google-oauth2/examples/config.ru b/vendor/gems/omniauth-google-oauth2/examples/config.ru
deleted file mode 100644
index ee17929094c..00000000000
--- a/vendor/gems/omniauth-google-oauth2/examples/config.ru
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-
-# Sample app for Google OAuth2 Strategy
-# Make sure to setup the ENV variables GOOGLE_KEY and GOOGLE_SECRET
-# Run with "bundle exec rackup"
-
-require 'rubygems'
-require 'bundler'
-require 'sinatra'
-require 'omniauth'
-require 'omniauth-google-oauth2'
-
-# Do not use for production code.
-# This is only to make setup easier when running through the sample.
-#
-# If you do have issues with certs in production code, this could help:
-# http://railsapps.github.io/openssl-certificate-verify-failed.html
-OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
-
-# Main example app for omniauth-google-oauth2
-class App < Sinatra::Base
- get '/' do
- <<-HTML
- <!DOCTYPE html>
- <html>
- <head>
- <title>Google OAuth2 Example</title>
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
- <script>
- jQuery(function() {
- return $.ajax({
- url: 'https://apis.google.com/js/client:plus.js?onload=gpAsyncInit',
- dataType: 'script',
- cache: true
- });
- });
-
- window.gpAsyncInit = function() {
- gapi.auth.authorize({
- immediate: true,
- response_type: 'code',
- cookie_policy: 'single_host_origin',
- client_id: '#{ENV['GOOGLE_KEY']}',
- scope: 'email profile'
- }, function(response) {
- return;
- });
- $('.googleplus-login').click(function(e) {
- e.preventDefault();
- gapi.auth.authorize({
- immediate: false,
- response_type: 'code',
- cookie_policy: 'single_host_origin',
- client_id: '#{ENV['GOOGLE_KEY']}',
- scope: 'email profile'
- }, function(response) {
- if (response && !response.error) {
- // google authentication succeed, now post data to server.
- jQuery.ajax({type: 'POST', url: "/auth/google_oauth2/callback", data: response,
- success: function(data) {
- // Log the data returning from google.
- console.log(data)
- }
- });
- } else {
- // google authentication failed.
- console.log("FAILED")
- }
- });
- });
- };
- </script>
- </head>
- <body>
- <ul>
- <li><a href='/auth/google_oauth2'>Sign in with Google</a></li>
- <li><a href='#' class="googleplus-login">Sign in with Google via AJAX</a></li>
- </ul>
- </body>
- </html>
- HTML
- end
-
- post '/auth/:provider/callback' do
- content_type 'text/plain'
- begin
- request.env['omniauth.auth'].to_hash.inspect
- rescue StandardError
- 'No Data'
- end
- end
-
- get '/auth/:provider/callback' do
- content_type 'text/plain'
- begin
- request.env['omniauth.auth'].to_hash.inspect
- rescue StandardError
- 'No Data'
- end
- end
-
- get '/auth/failure' do
- content_type 'text/plain'
- begin
- request.env['omniauth.auth'].to_hash.inspect
- rescue StandardError
- 'No Data'
- end
- end
-end
-
-use Rack::Session::Cookie, secret: ENV['RACK_COOKIE_SECRET']
-
-use OmniAuth::Builder do
- # For additional provider examples please look at 'omni_auth.rb'
- # The key provider_ignores_state is only for AJAX flows. It is not recommended for normal logins.
- provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline', prompt: 'consent', provider_ignores_state: true, scope: 'email,profile,calendar'
-end
-
-run App.new
diff --git a/vendor/gems/omniauth-google-oauth2/examples/omni_auth.rb b/vendor/gems/omniauth-google-oauth2/examples/omni_auth.rb
deleted file mode 100644
index 0a94164d766..00000000000
--- a/vendor/gems/omniauth-google-oauth2/examples/omni_auth.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-# Google's OAuth2 docs. Make sure you are familiar with all the options
-# before attempting to configure this gem.
-# https://developers.google.com/accounts/docs/OAuth2Login
-
-Rails.application.config.middleware.use OmniAuth::Builder do
- # Default usage, this will give you offline access and a refresh token
- # using default scopes 'email' and 'profile'
- #
- provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile'
-
- # Custom redirect_uri
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile', redirect_uri: 'https://localhost:3000/redirect'
-
- # Manual setup for offline access with a refresh token.
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline'
-
- # Custom scope supporting youtube. If you are customizing scopes, remember
- # to include the default scopes 'email' and 'profile'
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'http://gdata.youtube.com,email,profile,plus.me'
-
- # Custom scope for users only using Google for account creation/auth and do not require a refresh token.
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'online', prompt: ''
-
- # To include information about people in your circles you must include the 'plus.login' scope.
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_friends: false, scope: 'email,profile,plus.login'
-
- # If you need to acquire whether user picture is a default one or uploaded by user.
- #
- # provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_image_info: false
-end
diff --git a/vendor/gems/omniauth-google-oauth2/lib/omniauth-google-oauth2.rb b/vendor/gems/omniauth-google-oauth2/lib/omniauth-google-oauth2.rb
deleted file mode 100644
index a5cc57ab4c9..00000000000
--- a/vendor/gems/omniauth-google-oauth2/lib/omniauth-google-oauth2.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-require 'omniauth/google_oauth2'
diff --git a/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2.rb b/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2.rb
deleted file mode 100644
index 594c9a4eed9..00000000000
--- a/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-require 'omniauth/strategies/google_oauth2'
diff --git a/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2/version.rb b/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2/version.rb
deleted file mode 100644
index 93ae5e9e990..00000000000
--- a/vendor/gems/omniauth-google-oauth2/lib/omniauth/google_oauth2/version.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module OmniAuth
- module GoogleOauth2
- VERSION = '1.0.1'
- end
-end
diff --git a/vendor/gems/omniauth-google-oauth2/lib/omniauth/strategies/google_oauth2.rb b/vendor/gems/omniauth-google-oauth2/lib/omniauth/strategies/google_oauth2.rb
deleted file mode 100644
index 4ce32eb80d1..00000000000
--- a/vendor/gems/omniauth-google-oauth2/lib/omniauth/strategies/google_oauth2.rb
+++ /dev/null
@@ -1,254 +0,0 @@
-# frozen_string_literal: true
-
-require 'jwt'
-require 'oauth2'
-require 'omniauth/strategies/oauth2'
-require 'uri'
-
-module OmniAuth
- module Strategies
- # Main class for Google OAuth2 strategy.
- class GoogleOauth2 < OmniAuth::Strategies::OAuth2
- ALLOWED_ISSUERS = ['accounts.google.com', 'https://accounts.google.com'].freeze
- BASE_SCOPE_URL = 'https://www.googleapis.com/auth/'
- BASE_SCOPES = %w[profile email openid].freeze
- DEFAULT_SCOPE = 'email,profile'
- USER_INFO_URL = 'https://www.googleapis.com/oauth2/v3/userinfo'
- IMAGE_SIZE_REGEXP = /(s\d+(-c)?)|(w\d+-h\d+(-c)?)|(w\d+(-c)?)|(h\d+(-c)?)|c/
-
- option :name, 'google_oauth2'
- option :skip_friends, true
- option :skip_image_info, true
- option :skip_jwt, false
- option :jwt_leeway, 60
- option :authorize_options, %i[access_type hd login_hint prompt request_visible_actions scope state redirect_uri include_granted_scopes openid_realm device_id device_name]
- option :authorized_client_ids, []
-
- option :client_options,
- site: 'https://oauth2.googleapis.com',
- authorize_url: 'https://accounts.google.com/o/oauth2/auth',
- token_url: '/token'
-
- def authorize_params
- super.tap do |params|
- options[:authorize_options].each do |k|
- params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
- end
-
- params[:scope] = get_scope(params)
- params[:access_type] = 'offline' if params[:access_type].nil?
- params['openid.realm'] = params.delete(:openid_realm) unless params[:openid_realm].nil?
-
- session['omniauth.state'] = params[:state] if params[:state]
- end
- end
-
- uid { raw_info['sub'] }
-
- info do
- prune!(
- name: raw_info['name'],
- email: verified_email,
- unverified_email: raw_info['email'],
- email_verified: raw_info['email_verified'],
- first_name: raw_info['given_name'],
- last_name: raw_info['family_name'],
- image: image_url,
- urls: {
- google: raw_info['profile']
- }
- )
- end
-
- credentials do
- # Tokens and expiration will be used from OAuth2 strategy credentials block
- prune!({ 'scope' => token_info(access_token.token)['scope'] })
- end
-
- extra do
- hash = {}
- hash[:id_token] = access_token['id_token']
- if !options[:skip_jwt] && !access_token['id_token'].nil?
- decoded = ::JWT.decode(access_token['id_token'], nil, false).first
-
- # We have to manually verify the claims because the third parameter to
- # JWT.decode is false since no verification key is provided.
- ::JWT::Verify.verify_claims(decoded,
- verify_iss: true,
- iss: ALLOWED_ISSUERS,
- verify_aud: true,
- aud: options.client_id,
- verify_sub: false,
- verify_expiration: true,
- verify_not_before: true,
- verify_iat: false,
- verify_jti: false,
- leeway: options[:jwt_leeway])
-
- hash[:id_info] = decoded
- end
- hash[:raw_info] = raw_info unless skip_info?
- prune! hash
- end
-
- def raw_info
- @raw_info ||= access_token.get(USER_INFO_URL).parsed
- end
-
- def custom_build_access_token
- access_token = get_access_token(request)
-
- verify_hd(access_token)
- access_token
- end
-
- alias build_access_token custom_build_access_token
-
- private
-
- def callback_url
- options[:redirect_uri] || (full_host + callback_path)
- end
-
- def get_access_token(request)
- verifier = request.params['code']
- redirect_uri = request.params['redirect_uri']
- access_token = request.params['access_token']
- if verifier && request.xhr?
- client_get_token(verifier, redirect_uri || 'postmessage')
- elsif verifier
- client_get_token(verifier, redirect_uri || callback_url)
- elsif access_token && verify_token(access_token)
- ::OAuth2::AccessToken.from_hash(client, request.params.dup)
- elsif request.content_type =~ /json/i
- begin
- body = JSON.parse(request.body.read)
- request.body.rewind # rewind request body for downstream middlewares
- verifier = body && body['code']
- access_token = body && body['access_token']
- redirect_uri ||= body && body['redirect_uri']
- if verifier
- client_get_token(verifier, redirect_uri || 'postmessage')
- elsif verify_token(access_token)
- ::OAuth2::AccessToken.from_hash(client, body.dup)
- end
- rescue JSON::ParserError => e
- warn "[omniauth google-oauth2] JSON parse error=#{e}"
- end
- end
- end
-
- def client_get_token(verifier, redirect_uri)
- client.auth_code.get_token(verifier, get_token_options(redirect_uri), get_token_params)
- end
-
- def get_token_params
- deep_symbolize(options.auth_token_params || {})
- end
-
- def get_scope(params)
- raw_scope = params[:scope] || DEFAULT_SCOPE
- scope_list = raw_scope.split(' ').map { |item| item.split(',') }.flatten
- scope_list.map! { |s| s =~ %r{^https?://} || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" }
- scope_list.join(' ')
- end
-
- def verified_email
- raw_info['email_verified'] ? raw_info['email'] : nil
- end
-
- def get_token_options(redirect_uri = '')
- { redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true))
- end
-
- def prune!(hash)
- hash.delete_if do |_, v|
- prune!(v) if v.is_a?(Hash)
- v.nil? || (v.respond_to?(:empty?) && v.empty?)
- end
- end
-
- def image_url
- return nil unless raw_info['picture']
-
- u = URI.parse(raw_info['picture'].gsub('https:https', 'https'))
-
- path_index = u.path.to_s.index('/photo.jpg')
-
- if path_index && image_size_opts_passed?
- u.path.insert(path_index, image_params)
- u.path = u.path.gsub('//', '/')
-
- # Check if the image is already sized!
- split_path = u.path.split('/')
- u.path = u.path.sub("/#{split_path[-3]}", '') if split_path[-3] =~ IMAGE_SIZE_REGEXP
- end
-
- u.query = strip_unnecessary_query_parameters(u.query)
-
- u.to_s
- end
-
- def image_size_opts_passed?
- options[:image_size] || options[:image_aspect_ratio]
- end
-
- def image_params
- image_params = []
- if options[:image_size].is_a?(Integer)
- image_params << "s#{options[:image_size]}"
- elsif options[:image_size].is_a?(Hash)
- image_params << "w#{options[:image_size][:width]}" if options[:image_size][:width]
- image_params << "h#{options[:image_size][:height]}" if options[:image_size][:height]
- end
- image_params << 'c' if options[:image_aspect_ratio] == 'square'
-
- '/' + image_params.join('-')
- end
-
- def strip_unnecessary_query_parameters(query_parameters)
- # strip `sz` parameter (defaults to sz=50) which overrides `image_size` options
- return nil if query_parameters.nil?
-
- params = CGI.parse(query_parameters)
- stripped_params = params.delete_if { |key| key == 'sz' }
-
- # don't return an empty Hash since that would result
- # in URLs with a trailing ? character: http://image.url?
- return nil if stripped_params.empty?
-
- URI.encode_www_form(stripped_params)
- end
-
- def token_info(access_token)
- return nil unless access_token
-
- @token_info ||= Hash.new do |h, k|
- h[k] = client.request(:get, 'https://www.googleapis.com/oauth2/v3/tokeninfo', params: { access_token: access_token }).parsed
- end
-
- @token_info[access_token]
- end
-
- def verify_token(access_token)
- return false unless access_token
-
- token_info = token_info(access_token)
- token_info['aud'] == options.client_id || options.authorized_client_ids.include?(token_info['aud'])
- end
-
- def verify_hd(access_token)
- return true unless options.hd
-
- @raw_info ||= access_token.get(USER_INFO_URL).parsed
-
- options.hd = options.hd.call if options.hd.is_a? Proc
- allowed_hosted_domains = Array(options.hd)
-
- raise CallbackError.new(:invalid_hd, 'Invalid Hosted Domain') unless allowed_hosted_domains.include?(@raw_info['hd']) || options.hd == '*'
-
- true
- end
- end
- end
-end
diff --git a/vendor/gems/omniauth-google-oauth2/omniauth-google-oauth2.gemspec b/vendor/gems/omniauth-google-oauth2/omniauth-google-oauth2.gemspec
deleted file mode 100644
index a50d67bc9a0..00000000000
--- a/vendor/gems/omniauth-google-oauth2/omniauth-google-oauth2.gemspec
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require File.expand_path(
- File.join('..', 'lib', 'omniauth', 'google_oauth2', 'version'),
- __FILE__
-)
-
-Gem::Specification.new do |gem|
- gem.name = 'omniauth-google-oauth2'
- gem.version = OmniAuth::GoogleOauth2::VERSION
- gem.license = 'MIT'
- gem.summary = %(A Google OAuth2 strategy for OmniAuth 1.x)
- gem.description = %(A Google OAuth2 strategy for OmniAuth 1.x. This allows you to login to Google with your ruby app.)
- gem.authors = ['Josh Ellithorpe', 'Yury Korolev']
- gem.email = ['quest@mac.com']
- gem.homepage = 'https://github.com/zquestz/omniauth-google-oauth2'
-
- gem.files = Dir.glob("lib/**/*.*")
- gem.require_paths = ['lib']
-
- gem.required_ruby_version = '>= 2.2'
-
- gem.add_runtime_dependency 'jwt', '>= 2.0'
- gem.add_runtime_dependency 'oauth2', '~> 2.0'
- gem.add_runtime_dependency 'omniauth', '~> 2.0'
- gem.add_runtime_dependency 'omniauth-oauth2', '~> 1.7.1'
-
- gem.add_development_dependency 'rake', '~> 12.0'
- gem.add_development_dependency 'rspec', '~> 3.6'
- gem.add_development_dependency 'rubocop', '~> 0.49'
-end
diff --git a/vendor/gems/omniauth-google-oauth2/spec/omniauth/strategies/google_oauth2_spec.rb b/vendor/gems/omniauth-google-oauth2/spec/omniauth/strategies/google_oauth2_spec.rb
deleted file mode 100644
index 3a2bcf07e54..00000000000
--- a/vendor/gems/omniauth-google-oauth2/spec/omniauth/strategies/google_oauth2_spec.rb
+++ /dev/null
@@ -1,850 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'json'
-require 'omniauth-google-oauth2'
-require 'stringio'
-
-describe OmniAuth::Strategies::GoogleOauth2 do
- let(:request) { double('Request', params: {}, cookies: {}, env: {}) }
- let(:app) do
- lambda do
- [200, {}, ['Hello.']]
- end
- end
-
- subject do
- OmniAuth::Strategies::GoogleOauth2.new(app, 'appid', 'secret', @options || {}).tap do |strategy|
- allow(strategy).to receive(:request) do
- request
- end
- end
- end
-
- before do
- OmniAuth.config.test_mode = true
- end
-
- after do
- OmniAuth.config.test_mode = false
- end
-
- describe '#client_options' do
- it 'has correct site' do
- expect(subject.client.site).to eq('https://oauth2.googleapis.com')
- end
-
- it 'has correct authorize_url' do
- expect(subject.client.options[:authorize_url]).to eq('https://accounts.google.com/o/oauth2/auth')
- end
-
- it 'has correct token_url' do
- expect(subject.client.options[:token_url]).to eq('/token')
- end
-
- describe 'overrides' do
- context 'as strings' do
- it 'should allow overriding the site' do
- @options = { client_options: { 'site' => 'https://example.com' } }
- expect(subject.client.site).to eq('https://example.com')
- end
-
- it 'should allow overriding the authorize_url' do
- @options = { client_options: { 'authorize_url' => 'https://example.com' } }
- expect(subject.client.options[:authorize_url]).to eq('https://example.com')
- end
-
- it 'should allow overriding the token_url' do
- @options = { client_options: { 'token_url' => 'https://example.com' } }
- expect(subject.client.options[:token_url]).to eq('https://example.com')
- end
- end
-
- context 'as symbols' do
- it 'should allow overriding the site' do
- @options = { client_options: { site: 'https://example.com' } }
- expect(subject.client.site).to eq('https://example.com')
- end
-
- it 'should allow overriding the authorize_url' do
- @options = { client_options: { authorize_url: 'https://example.com' } }
- expect(subject.client.options[:authorize_url]).to eq('https://example.com')
- end
-
- it 'should allow overriding the token_url' do
- @options = { client_options: { token_url: 'https://example.com' } }
- expect(subject.client.options[:token_url]).to eq('https://example.com')
- end
- end
- end
- end
-
- describe '#authorize_options' do
- %i[access_type hd login_hint prompt scope state device_id device_name].each do |k|
- it "should support #{k}" do
- @options = { k => 'http://someval' }
- expect(subject.authorize_params[k.to_s]).to eq('http://someval')
- end
- end
-
- describe 'redirect_uri' do
- it 'should default to nil' do
- @options = {}
- expect(subject.authorize_params['redirect_uri']).to eq(nil)
- end
-
- it 'should set the redirect_uri parameter if present' do
- @options = { redirect_uri: 'https://example.com' }
- expect(subject.authorize_params['redirect_uri']).to eq('https://example.com')
- end
- end
-
- describe 'access_type' do
- it 'should default to "offline"' do
- @options = {}
- expect(subject.authorize_params['access_type']).to eq('offline')
- end
-
- it 'should set the access_type parameter if present' do
- @options = { access_type: 'online' }
- expect(subject.authorize_params['access_type']).to eq('online')
- end
- end
-
- describe 'hd' do
- it 'should default to nil' do
- expect(subject.authorize_params['hd']).to eq(nil)
- end
-
- it 'should set the hd (hosted domain) parameter if present' do
- @options = { hd: 'example.com' }
- expect(subject.authorize_params['hd']).to eq('example.com')
- end
-
- it 'should set the hd parameter and work with nil hd (gmail)' do
- @options = { hd: nil }
- expect(subject.authorize_params['hd']).to eq(nil)
- end
-
- it 'should set the hd parameter to * if set (only allows G Suite emails)' do
- @options = { hd: '*' }
- expect(subject.authorize_params['hd']).to eq('*')
- end
- end
-
- describe 'login_hint' do
- it 'should default to nil' do
- expect(subject.authorize_params['login_hint']).to eq(nil)
- end
-
- it 'should set the login_hint parameter if present' do
- @options = { login_hint: 'john@example.com' }
- expect(subject.authorize_params['login_hint']).to eq('john@example.com')
- end
- end
-
- describe 'prompt' do
- it 'should default to nil' do
- expect(subject.authorize_params['prompt']).to eq(nil)
- end
-
- it 'should set the prompt parameter if present' do
- @options = { prompt: 'consent select_account' }
- expect(subject.authorize_params['prompt']).to eq('consent select_account')
- end
- end
-
- describe 'request_visible_actions' do
- it 'should default to nil' do
- expect(subject.authorize_params['request_visible_actions']).to eq(nil)
- end
-
- it 'should set the request_visible_actions parameter if present' do
- @options = { request_visible_actions: 'something' }
- expect(subject.authorize_params['request_visible_actions']).to eq('something')
- end
- end
-
- describe 'include_granted_scopes' do
- it 'should default to nil' do
- expect(subject.authorize_params['include_granted_scopes']).to eq(nil)
- end
-
- it 'should set the include_granted_scopes parameter if present' do
- @options = { include_granted_scopes: 'true' }
- expect(subject.authorize_params['include_granted_scopes']).to eq('true')
- end
- end
-
- describe 'scope' do
- it 'should expand scope shortcuts' do
- @options = { scope: 'calendar' }
- expect(subject.authorize_params['scope']).to eq('https://www.googleapis.com/auth/calendar')
- end
-
- it 'should leave base scopes as is' do
- @options = { scope: 'profile' }
- expect(subject.authorize_params['scope']).to eq('profile')
- end
-
- it 'should join scopes' do
- @options = { scope: 'profile,email' }
- expect(subject.authorize_params['scope']).to eq('profile email')
- end
-
- it 'should deal with whitespace when joining scopes' do
- @options = { scope: 'profile, email' }
- expect(subject.authorize_params['scope']).to eq('profile email')
- end
-
- it 'should set default scope to email,profile' do
- expect(subject.authorize_params['scope']).to eq('email profile')
- end
-
- it 'should support space delimited scopes' do
- @options = { scope: 'profile email' }
- expect(subject.authorize_params['scope']).to eq('profile email')
- end
-
- it 'should support extremely badly formed scopes' do
- @options = { scope: 'profile email,foo,steve yeah http://example.com' }
- expect(subject.authorize_params['scope']).to eq('profile email https://www.googleapis.com/auth/foo https://www.googleapis.com/auth/steve https://www.googleapis.com/auth/yeah http://example.com')
- end
- end
-
- describe 'state' do
- it 'should set the state parameter' do
- @options = { state: 'some_state' }
- expect(subject.authorize_params['state']).to eq('some_state')
- expect(subject.authorize_params[:state]).to eq('some_state')
- expect(subject.session['omniauth.state']).to eq('some_state')
- end
-
- it 'should set the omniauth.state dynamically' do
- allow(subject).to receive(:request) { double('Request', params: { 'state' => 'some_state' }, env: {}) }
- expect(subject.authorize_params['state']).to eq('some_state')
- expect(subject.authorize_params[:state]).to eq('some_state')
- expect(subject.session['omniauth.state']).to eq('some_state')
- end
- end
-
- describe 'overrides' do
- it 'should include top-level options that are marked as :authorize_options' do
- @options = { authorize_options: %i[scope foo request_visible_actions], scope: 'http://bar', foo: 'baz', hd: 'wow', request_visible_actions: 'something' }
- expect(subject.authorize_params['scope']).to eq('http://bar')
- expect(subject.authorize_params['foo']).to eq('baz')
- expect(subject.authorize_params['hd']).to eq(nil)
- expect(subject.authorize_params['request_visible_actions']).to eq('something')
- end
-
- describe 'request overrides' do
- %i[access_type hd login_hint prompt scope state].each do |k|
- context "authorize option #{k}" do
- let(:request) { double('Request', params: { k.to_s => 'http://example.com' }, cookies: {}, env: {}) }
-
- it "should set the #{k} authorize option dynamically in the request" do
- @options = { k: '' }
- expect(subject.authorize_params[k.to_s]).to eq('http://example.com')
- end
- end
- end
-
- describe 'custom authorize_options' do
- let(:request) { double('Request', params: { 'foo' => 'something' }, cookies: {}, env: {}) }
-
- it 'should support request overrides from custom authorize_options' do
- @options = { authorize_options: [:foo], foo: '' }
- expect(subject.authorize_params['foo']).to eq('something')
- end
- end
- end
- end
- end
-
- describe '#authorize_params' do
- it 'should include any authorize params passed in the :authorize_params option' do
- @options = { authorize_params: { request_visible_actions: 'something', foo: 'bar', baz: 'zip' }, hd: 'wow', bad: 'not_included' }
- expect(subject.authorize_params['request_visible_actions']).to eq('something')
- expect(subject.authorize_params['foo']).to eq('bar')
- expect(subject.authorize_params['baz']).to eq('zip')
- expect(subject.authorize_params['hd']).to eq('wow')
- expect(subject.authorize_params['bad']).to eq(nil)
- end
- end
-
- describe '#token_params' do
- it 'should include any token params passed in the :token_params option' do
- @options = { token_params: { foo: 'bar', baz: 'zip' } }
- expect(subject.token_params['foo']).to eq('bar')
- expect(subject.token_params['baz']).to eq('zip')
- end
- end
-
- describe '#token_options' do
- it 'should include top-level options that are marked as :token_options' do
- @options = { token_options: %i[scope foo], scope: 'bar', foo: 'baz', bad: 'not_included' }
- expect(subject.token_params['scope']).to eq('bar')
- expect(subject.token_params['foo']).to eq('baz')
- expect(subject.token_params['bad']).to eq(nil)
- end
- end
-
- describe '#callback_url' do
- let(:base_url) { 'https://example.com' }
-
- it 'has the correct default callback path' do
- allow(subject).to receive(:full_host) { base_url }
- allow(subject).to receive(:script_name) { '' }
- expect(subject.send(:callback_url)).to eq(base_url + '/auth/google_oauth2/callback')
- end
-
- it 'should set the callback path with script_name if present' do
- allow(subject).to receive(:full_host) { base_url }
- allow(subject).to receive(:script_name) { '/v1' }
- expect(subject.send(:callback_url)).to eq(base_url + '/v1/auth/google_oauth2/callback')
- end
-
- it 'should set the callback_path parameter if present' do
- @options = { callback_path: '/auth/foo/callback' }
- allow(subject).to receive(:full_host) { base_url }
- allow(subject).to receive(:script_name) { '' }
- expect(subject.send(:callback_url)).to eq(base_url + '/auth/foo/callback')
- end
- end
-
- describe '#info' do
- let(:client) do
- OAuth2::Client.new('abc', 'def') do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/userinfo') { [200, { 'content-type' => 'application/json' }, response_hash.to_json] }
- end
- end
- end
- let(:access_token) { OAuth2::AccessToken.from_hash(client, {}) }
- before { allow(subject).to receive(:access_token).and_return(access_token) }
-
- context 'with verified email' do
- let(:response_hash) do
- { email: 'something@domain.invalid', email_verified: true }
- end
-
- it 'should return equal email and unverified_email' do
- expect(subject.info[:email]).to eq('something@domain.invalid')
- expect(subject.info[:unverified_email]).to eq('something@domain.invalid')
- end
- end
-
- context 'with unverified email' do
- let(:response_hash) do
- { email: 'something@domain.invalid', email_verified: false }
- end
-
- it 'should return nil email, and correct unverified email' do
- expect(subject.info[:email]).to eq(nil)
- expect(subject.info[:unverified_email]).to eq('something@domain.invalid')
- end
- end
- end
-
- describe '#credentials' do
- let(:client) { OAuth2::Client.new('abc', 'def') }
- let(:access_token) { OAuth2::AccessToken.from_hash(client, access_token: 'valid_access_token', expires_at: 123_456_789, refresh_token: 'valid_refresh_token') }
- before(:each) do
- allow(subject).to receive(:access_token).and_return(access_token)
- subject.options.client_options[:connection_build] = proc do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do
- [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump(
- aud: '000000000000.apps.googleusercontent.com',
- sub: '123456789',
- scope: 'profile email'
- )]
- end
- end
- end
- end
-
- it 'should return access token and (optionally) refresh token' do
- expect(subject.credentials.to_h).to \
- match(hash_including(
- 'token' => 'valid_access_token',
- 'refresh_token' => 'valid_refresh_token',
- 'scope' => 'profile email',
- 'expires_at' => 123_456_789,
- 'expires' => true
- ))
- end
- end
-
- describe '#extra' do
- let(:client) do
- OAuth2::Client.new('abc', 'def') do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/userinfo') { [200, { 'content-type' => 'application/json' }, '{"sub": "12345"}'] }
- end
- end
- end
- let(:access_token) { OAuth2::AccessToken.from_hash(client, {}) }
-
- before { allow(subject).to receive(:access_token).and_return(access_token) }
-
- describe 'id_token' do
- shared_examples 'id_token issued by valid issuer' do |issuer|
- context 'when the id_token is passed into the access token' do
- let(:token_info) do
- {
- 'abc' => 'xyz',
- 'exp' => Time.now.to_i + 3600,
- 'nbf' => Time.now.to_i - 60,
- 'iat' => Time.now.to_i,
- 'aud' => 'appid',
- 'iss' => issuer
- }
- end
- let(:id_token) { JWT.encode(token_info, 'secret') }
- let(:access_token) { OAuth2::AccessToken.from_hash(client, 'id_token' => id_token) }
-
- it 'should include id_token when set on the access_token' do
- expect(subject.extra).to include(id_token: id_token)
- end
-
- it 'should include id_info when id_token is set on the access_token and skip_jwt is false' do
- subject.options[:skip_jwt] = false
- expect(subject.extra).to include(id_info: token_info)
- end
-
- it 'should not include id_info when id_token is set on the access_token and skip_jwt is true' do
- subject.options[:skip_jwt] = true
- expect(subject.extra).not_to have_key(:id_info)
- end
-
- it 'should include id_info when id_token is set on the access_token by default' do
- expect(subject.extra).to include(id_info: token_info)
- end
- end
- end
-
- it_behaves_like 'id_token issued by valid issuer', 'accounts.google.com'
- it_behaves_like 'id_token issued by valid issuer', 'https://accounts.google.com'
-
- context 'when the id_token is issued by an invalid issuer' do
- let(:token_info) do
- {
- 'abc' => 'xyz',
- 'exp' => Time.now.to_i + 3600,
- 'nbf' => Time.now.to_i - 60,
- 'iat' => Time.now.to_i,
- 'aud' => 'appid',
- 'iss' => 'fake.google.com'
- }
- end
- let(:id_token) { JWT.encode(token_info, 'secret') }
- let(:access_token) { OAuth2::AccessToken.from_hash(client, 'id_token' => id_token) }
-
- it 'raises JWT::InvalidIssuerError' do
- expect { subject.extra }.to raise_error(JWT::InvalidIssuerError)
- end
- end
-
- context 'when the id_token is missing' do
- it 'should not include id_token' do
- expect(subject.extra).not_to have_key(:id_token)
- end
-
- it 'should not include id_info' do
- expect(subject.extra).not_to have_key(:id_info)
- end
- end
- end
-
- describe 'raw_info' do
- context 'when skip_info is true' do
- before { subject.options[:skip_info] = true }
-
- it 'should not include raw_info' do
- expect(subject.extra).not_to have_key(:raw_info)
- end
- end
-
- context 'when skip_info is false' do
- before { subject.options[:skip_info] = false }
-
- it 'should include raw_info' do
- expect(subject.extra[:raw_info]).to eq('sub' => '12345')
- end
- end
- end
- end
-
- describe 'populate auth hash urls' do
- it 'should populate url map in auth hash if link present in raw_info' do
- allow(subject).to receive(:raw_info) { { 'name' => 'Foo', 'profile' => 'https://plus.google.com/123456' } }
- expect(subject.info[:urls][:google]).to eq('https://plus.google.com/123456')
- end
-
- it 'should not populate url map in auth hash if no link present in raw_info' do
- allow(subject).to receive(:raw_info) { { 'name' => 'Foo' } }
- expect(subject.info).not_to have_key(:urls)
- end
- end
-
- describe 'image options' do
- it 'should have no image if a picture is not present' do
- @options = { image_aspect_ratio: 'square' }
- allow(subject).to receive(:raw_info) { { 'name' => 'User Without Pic' } }
- expect(subject.info[:image]).to be_nil
- end
-
- describe 'when a picture is returned from google' do
- it 'should return the image with size specified in the `image_size` option' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
- end
-
- it 'should return the image with size specified in the `image_size` option when sizing is in the picture' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh4.googleusercontent.com/url/s96-c/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh4.googleusercontent.com/url/s50/photo.jpg')
- end
-
- it 'should handle a picture with too many slashes correctly' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url//photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
- end
-
- it 'should handle a picture with a size query parameter correctly' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
- end
-
- it 'should handle a picture with a size query parameter and other valid query parameters correctly' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50&hello=true&life=42' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42')
- end
-
- it 'should handle a picture with other valid query parameters correctly' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?hello=true&life=42' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42')
- end
-
- it 'should return the image with width and height specified in the `image_size` option' do
- @options = { image_size: { width: 50, height: 40 } }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40/photo.jpg')
- end
-
- it 'should return the image with width and height specified in the `image_size` option when sizing is in the picture' do
- @options = { image_size: { width: 50, height: 40 } }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/w100-h80-c/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40/photo.jpg')
- end
-
- it 'should return square image when `image_aspect_ratio` is specified' do
- @options = { image_aspect_ratio: 'square' }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/c/photo.jpg')
- end
-
- it 'should return square image when `image_aspect_ratio` is specified and sizing is in the picture' do
- @options = { image_aspect_ratio: 'square' }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/c/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/c/photo.jpg')
- end
-
- it 'should return square sized image when `image_aspect_ratio` and `image_size` is set' do
- @options = { image_aspect_ratio: 'square', image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50-c/photo.jpg')
- end
-
- it 'should return square sized image when `image_aspect_ratio` and `image_size` is set and sizing is in the picture' do
- @options = { image_aspect_ratio: 'square', image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/s90/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50-c/photo.jpg')
- end
-
- it 'should return square sized image when `image_aspect_ratio` and `image_size` has height and width' do
- @options = { image_aspect_ratio: 'square', image_size: { width: 50, height: 40 } }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40-c/photo.jpg')
- end
-
- it 'should return square sized image when `image_aspect_ratio` and `image_size` has height and width and sizing is in the picture' do
- @options = { image_aspect_ratio: 'square', image_size: { width: 50, height: 40 } }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/w100-h80/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40-c/photo.jpg')
- end
-
- it 'should return original image if image url does not end in `photo.jpg`' do
- @options = { image_size: 50 }
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photograph.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photograph.jpg')
- end
- end
-
- it 'should return original image if no options are provided' do
- allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photo.jpg')
- end
-
- it 'should return correct image if google image url has double https' do
- allow(subject).to receive(:raw_info) { { 'picture' => 'https:https://lh3.googleusercontent.com/url/photo.jpg' } }
- expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photo.jpg')
- end
- end
-
- describe 'build_access_token' do
- it 'should use a hybrid authorization request_uri if this is an AJAX request with a code parameter' do
- allow(request).to receive(:xhr?).and_return(true)
- allow(request).to receive(:params).and_return('code' => 'valid_code')
-
- client = double(:client)
- auth_code = double(:auth_code)
- allow(client).to receive(:auth_code).and_return(auth_code)
- expect(subject).to receive(:client).and_return(client)
- expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'postmessage' }, {})
-
- expect(subject).not_to receive(:orig_build_access_token)
- subject.build_access_token
- end
-
- it 'should use a hybrid authorization request_uri if this is an AJAX request (mobile) with a code parameter' do
- allow(request).to receive(:xhr?).and_return(true)
- allow(request).to receive(:params).and_return('code' => 'valid_code', 'redirect_uri' => '')
-
- client = double(:client)
- auth_code = double(:auth_code)
- allow(client).to receive(:auth_code).and_return(auth_code)
- expect(subject).to receive(:client).and_return(client)
- expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: '' }, {})
-
- expect(subject).not_to receive(:orig_build_access_token)
- subject.build_access_token
- end
-
- it 'should use the request_uri from params if this not an AJAX request (request from installed app) with a code parameter' do
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:params).and_return('code' => 'valid_code', 'redirect_uri' => 'redirect_uri')
-
- client = double(:client)
- auth_code = double(:auth_code)
- allow(client).to receive(:auth_code).and_return(auth_code)
- expect(subject).to receive(:client).and_return(client)
- expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri' }, {})
-
- expect(subject).not_to receive(:orig_build_access_token)
- subject.build_access_token
- end
-
- it 'should read access_token from hash if this is not an AJAX request with a code parameter' do
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:params).and_return('access_token' => 'valid_access_token')
- expect(subject).to receive(:verify_token).with('valid_access_token').and_return true
- expect(subject).to receive(:client).and_return(:client)
-
- token = subject.build_access_token
- expect(token).to be_instance_of(::OAuth2::AccessToken)
- expect(token.token).to eq('valid_access_token')
- expect(token.client).to eq(:client)
- end
-
- it 'reads the code from a json request body' do
- body = StringIO.new(%({"code":"json_access_token"}))
- client = double(:client)
- auth_code = double(:auth_code)
-
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:content_type).and_return('application/json')
- allow(request).to receive(:body).and_return(body)
- allow(client).to receive(:auth_code).and_return(auth_code)
- expect(subject).to receive(:client).and_return(client)
-
- expect(auth_code).to receive(:get_token).with('json_access_token', { redirect_uri: 'postmessage' }, {})
-
- subject.build_access_token
- end
-
- it 'reads the redirect uri from a json request body' do
- body = StringIO.new(%({"code":"json_access_token", "redirect_uri":"sample"}))
- client = double(:client)
- auth_code = double(:auth_code)
-
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:content_type).and_return('application/json')
- allow(request).to receive(:body).and_return(body)
- allow(client).to receive(:auth_code).and_return(auth_code)
- expect(subject).to receive(:client).and_return(client)
-
- expect(auth_code).to receive(:get_token).with('json_access_token', { redirect_uri: 'sample' }, {})
-
- subject.build_access_token
- end
-
- it 'reads the access token from a json request body' do
- body = StringIO.new(%({"access_token":"valid_access_token"}))
-
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:content_type).and_return('application/json')
- allow(request).to receive(:body).and_return(body)
- expect(subject).to receive(:client).and_return(:client)
-
- expect(subject).to receive(:verify_token).with('valid_access_token').and_return true
-
- token = subject.build_access_token
- expect(token).to be_instance_of(::OAuth2::AccessToken)
- expect(token.token).to eq('valid_access_token')
- expect(token.client).to eq(:client)
- end
-
- it 'should use callback_url without query_string if this is not an AJAX request' do
- allow(request).to receive(:xhr?).and_return(false)
- allow(request).to receive(:params).and_return('code' => 'valid_code')
- allow(request).to receive(:content_type).and_return('application/x-www-form-urlencoded')
-
- client = double(:client)
- auth_code = double(:auth_code)
- allow(client).to receive(:auth_code).and_return(auth_code)
- allow(subject).to receive(:callback_url).and_return('redirect_uri_without_query_string')
-
- expect(subject).to receive(:client).and_return(client)
- expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri_without_query_string' }, {})
- subject.build_access_token
- end
- end
-
- describe 'verify_token' do
- before(:each) do
- subject.options.client_options[:connection_build] = proc do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do
- [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump(
- aud: '000000000000.apps.googleusercontent.com',
- sub: '123456789',
- email_verified: 'true',
- email: 'example@example.com',
- access_type: 'offline',
- scope: 'profile email',
- expires_in: 436
- )]
- end
- stub.get('/oauth2/v3/tokeninfo?access_token=invalid_access_token') do
- [400, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump(error_description: 'Invalid Value')]
- end
- end
- end
- end
-
- it 'should verify token if access_token is valid and app_id equals' do
- subject.options.client_id = '000000000000.apps.googleusercontent.com'
- expect(subject.send(:verify_token, 'valid_access_token')).to eq(true)
- end
-
- it 'should verify token if access_token is valid and app_id authorized' do
- subject.options.authorized_client_ids = ['000000000000.apps.googleusercontent.com']
- expect(subject.send(:verify_token, 'valid_access_token')).to eq(true)
- end
-
- it 'should not verify token if access_token is valid but app_id is false' do
- expect(subject.send(:verify_token, 'valid_access_token')).to eq(false)
- end
-
- it 'should raise error if access_token is invalid' do
- expect do
- subject.send(:verify_token, 'invalid_access_token')
- end.to raise_error(OAuth2::Error)
- end
- end
-
- describe 'verify_hd' do
- let(:client) do
- OAuth2::Client.new('abc', 'def') do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/userinfo') do
- [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump(
- hd: 'example.com'
- )]
- end
- end
- end
- end
- let(:access_token) { OAuth2::AccessToken.from_hash(client, {}) }
-
- context 'when domain is nil' do
- let(:client) do
- OAuth2::Client.new('abc', 'def') do |builder|
- builder.request :url_encoded
- builder.adapter :test do |stub|
- stub.get('/oauth2/v3/userinfo') do
- [200, { 'Content-Type' => 'application/json; charset=UTF-8' }, JSON.dump({})]
- end
- end
- end
- end
-
- it 'should verify hd if options hd is set and correct' do
- subject.options.hd = nil
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should verify hd if options hd is set as an array and is correct' do
- subject.options.hd = ['example.com', 'example.co', nil]
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should raise an exception if nil is not included' do
- subject.options.hd = ['example.com', 'example.co']
- expect do
- subject.send(:verify_hd, access_token)
- end.to raise_error(OmniAuth::Strategies::OAuth2::CallbackError)
- end
- end
-
- it 'should verify hd if options hd is not set' do
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should verify hd if options hd is set and correct' do
- subject.options.hd = 'example.com'
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should verify hd if options hd is set as an array and is correct' do
- subject.options.hd = ['example.com', 'example.co', nil]
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should verify hd if options hd is set as an Proc and is correct' do
- subject.options.hd = proc { 'example.com' }
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should verify hd if options hd is set as an Proc returning an array and is correct' do
- subject.options.hd = proc { ['example.com', 'example.co'] }
- expect(subject.send(:verify_hd, access_token)).to eq(true)
- end
-
- it 'should raise error if options hd is set and wrong' do
- subject.options.hd = 'invalid.com'
- expect do
- subject.send(:verify_hd, access_token)
- end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
- end
-
- it 'should raise error if options hd is set as an array and is not correct' do
- subject.options.hd = ['invalid.com', 'invalid.co']
- expect do
- subject.send(:verify_hd, access_token)
- end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
- end
- end
-end
diff --git a/vendor/gems/omniauth-google-oauth2/spec/spec_helper.rb b/vendor/gems/omniauth-google-oauth2/spec/spec_helper.rb
deleted file mode 100644
index 3c2325389c2..00000000000
--- a/vendor/gems/omniauth-google-oauth2/spec/spec_helper.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-require File.join('bundler', 'setup')
-require 'rspec'
diff --git a/workhorse/.tool-versions b/workhorse/.tool-versions
index c90984122a3..ee9584ceddc 100644
--- a/workhorse/.tool-versions
+++ b/workhorse/.tool-versions
@@ -1 +1 @@
-golang 1.17.9
+golang 1.18.7
diff --git a/workhorse/README.md b/workhorse/README.md
index c57f90b4a49..3e1b2486426 100644
--- a/workhorse/README.md
+++ b/workhorse/README.md
@@ -1,7 +1,7 @@
---
stage: Create
group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Workhorse documentation
diff --git a/workhorse/doc/architecture/channel.md b/workhorse/doc/architecture/channel.md
deleted file mode 100644
index 04bb0e7652f..00000000000
--- a/workhorse/doc/architecture/channel.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-redirect_to: '../../../doc/development/backend/create_source_code_be/workhorse/channel.md'
-remove_date: '2022-07-01'
----
-
-# Websocket channel support
-
-This document was moved to [another location](../../../doc/development/workhorse/channel.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/architecture/gitlab_features.md b/workhorse/doc/architecture/gitlab_features.md
deleted file mode 100644
index 42dd919690d..00000000000
--- a/workhorse/doc/architecture/gitlab_features.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Features that rely on Workhorse
-
-This document was moved to [another location](../../../doc/development/workhorse/gitlab_features.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/channel.md b/workhorse/doc/channel.md
deleted file mode 100644
index 86078321dff..00000000000
--- a/workhorse/doc/channel.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Websocket channel support
-
-This document was moved to [another location](../../doc/development/workhorse/channel.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/development/new_features.md b/workhorse/doc/development/new_features.md
deleted file mode 100644
index 60f0ad75539..00000000000
--- a/workhorse/doc/development/new_features.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Adding new features to Workhorse
-
-This document was moved to [another location](../../../doc/development/workhorse/new_features.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/development/tests.md b/workhorse/doc/development/tests.md
deleted file mode 100644
index a5eb7571cc0..00000000000
--- a/workhorse/doc/development/tests.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Testing your code
-
-This document was moved to [another location](../../../doc/development/workhorse/index.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/operations/configuration.md b/workhorse/doc/operations/configuration.md
deleted file mode 100644
index 62dc8369dfb..00000000000
--- a/workhorse/doc/operations/configuration.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Workhorse configuration
-
-This document was moved to [another location](../../../doc/development/workhorse/configuration.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/doc/operations/install.md b/workhorse/doc/operations/install.md
deleted file mode 100644
index 9f0a8212783..00000000000
--- a/workhorse/doc/operations/install.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-stage: Create
-group: Source Code
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Installation
-
-This document was moved to [another location](../../../doc/development/workhorse/index.md).
-
-<!-- This redirect file can be deleted after <2022-07-01>. -->
-<!-- Redirects that point to other docs in the same project expire in three months. -->
-<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 500753bbf97..ec78a85e413 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -5,9 +5,9 @@ go 1.17
require (
github.com/Azure/azure-storage-blob-go v0.14.0
github.com/BurntSushi/toml v1.2.0
- github.com/FZambia/sentinel v1.1.0
- github.com/alecthomas/chroma/v2 v2.2.0
- github.com/aws/aws-sdk-go v1.43.31
+ github.com/FZambia/sentinel v1.1.1
+ github.com/alecthomas/chroma/v2 v2.3.0
+ github.com/aws/aws-sdk-go v1.44.116
github.com/disintegration/imaging v1.6.2
github.com/getsentry/raven-go v0.2.0
github.com/golang-jwt/jwt/v4 v4.4.2
@@ -26,7 +26,7 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/smartystreets/goconvey v1.7.2
github.com/stretchr/testify v1.8.0
- gitlab.com/gitlab-org/gitaly/v15 v15.4.0-rc2
+ gitlab.com/gitlab-org/gitaly/v15 v15.4.2
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
gitlab.com/gitlab-org/labkit v1.16.0
gocloud.dev v0.26.0
@@ -34,7 +34,7 @@ require (
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
golang.org/x/tools v0.1.12
- google.golang.org/grpc v1.49.0
+ google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
honnef.co/go/tools v0.3.3
)
@@ -108,7 +108,7 @@ require (
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
- golang.org/x/text v0.3.7 // indirect
+ golang.org/x/text v0.3.8 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/api v0.74.0 // indirect
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 30c7fec32d2..67392ede877 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -134,8 +134,8 @@ github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
github.com/DataDog/gostackparse v0.5.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
github.com/DataDog/sketches-go v1.0.0 h1:chm5KSXO7kO+ywGWJ0Zs6tdmWU8PBXSbywFVciL6BG4=
github.com/DataDog/sketches-go v1.0.0/go.mod h1:O+XkJHWk9w4hDwY2ZUDU31ZC9sNYlYo8DiFsxjYeo1k=
-github.com/FZambia/sentinel v1.1.0 h1:qrCBfxc8SvJihYNjBWgwUI93ZCvFe/PJIPTHKmlp8a8=
-github.com/FZambia/sentinel v1.1.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
+github.com/FZambia/sentinel v1.1.1 h1:0ovTimlR7Ldm+wR15GgO+8C2dt7kkn+tm3PQS+Qk3Ek=
+github.com/FZambia/sentinel v1.1.1/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
github.com/GoogleCloudPlatform/cloudsql-proxy v1.29.0/go.mod h1:spvB9eLJH9dutlbPSRmHvSXXHOwGRyeXh1jVdquA2G8=
github.com/HdrHistogram/hdrhistogram-go v1.1.1 h1:cJXY5VLMHgejurPjZH6Fo9rIwRGLefBGdiaENZALqrg=
github.com/HdrHistogram/hdrhistogram-go v1.1.1/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
@@ -149,17 +149,17 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/ProtonMail/go-crypto v0.0.0-20220810064516-de89276ce0f3/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
+github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
-github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
-github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
-github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
-github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
+github.com/alecthomas/chroma/v2 v2.3.0 h1:83xfxrnjv8eK+Cf8qZDzNo3PPF9IbTWHs7z28GY6D0U=
+github.com/alecthomas/chroma/v2 v2.3.0/go.mod h1:mZxeWZlxP2Dy+/8cBob2PYd8O2DwNAzave5AY7A2eQw=
+github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
+github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -178,8 +178,9 @@ github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevB
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
-github.com/aws/aws-sdk-go v1.43.31 h1:yJZIr8nMV1hXjAvvOLUFqZRJcHV7udPQBfhJqawDzI0=
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/aws/aws-sdk-go v1.44.116 h1:NpLIhcvLWXJZAEwvPj3TDHeqp7DleK6ZUVYyW01WNHY=
+github.com/aws/aws-sdk-go v1.44.116/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v1.16.2 h1:fqlCk6Iy3bnCumtrLz9r3mJ/2gUT0pJ0wLFVIdWh+JA=
github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 h1:SdK4Ppk5IzLs64ZMvr6MrSficMtjY2oS0WOORXTlxwU=
@@ -604,11 +605,12 @@ github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
-github.com/jackc/pgx/v4 v4.17.0/go.mod h1:Gd6RmOhtFLTu8cp/Fhq4kP195KrshxYJH3oW8AWJ1pw=
+github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
@@ -781,7 +783,7 @@ github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwp
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml/v2 v2.0.3/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
+github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
@@ -947,8 +949,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
-gitlab.com/gitlab-org/gitaly/v15 v15.4.0-rc2 h1:ngV/NWEMz4TRlnJFzBpatdXkEIDMHsU3YUzGdZU63qY=
-gitlab.com/gitlab-org/gitaly/v15 v15.4.0-rc2/go.mod h1:Rv/LoDU5I3cOP6KLUWFjC1eigcay2u8b8ZcsW86A0Xo=
+gitlab.com/gitlab-org/gitaly/v15 v15.4.2 h1:evAILjEjT7M+pegcbP4QsViK4Hkt1I1IwJAr5AQjbdY=
+gitlab.com/gitlab-org/gitaly/v15 v15.4.2/go.mod h1:anANn2UwrECvFOEvLx8DkXYYDQ6g3+jmv0kP2VDYm70=
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 v1.16.0 h1:Vm3NAMZ8RqAunXlvPWby3GJ2R35vsYGP6Uu0YjyMIlY=
@@ -1278,8 +1280,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1546,9 +1549,9 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index aa6d7cf1bc7..6a6a51b27bb 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -19,7 +19,6 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
-
"gitlab.com/gitlab-org/gitlab/workhorse/internal/secret"
)
diff --git a/workhorse/internal/dependencyproxy/dependencyproxy.go b/workhorse/internal/dependencyproxy/dependencyproxy.go
index 90f3042a342..6651b5aee84 100644
--- a/workhorse/internal/dependencyproxy/dependencyproxy.go
+++ b/workhorse/internal/dependencyproxy/dependencyproxy.go
@@ -9,12 +9,12 @@ import (
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport"
)
var httpClient = &http.Client{
- Transport: httptransport.New(),
+ Transport: transport.NewRestrictedTransport(),
}
type Injector struct {
diff --git a/workhorse/internal/helper/httptransport/http_transport.go b/workhorse/internal/helper/httptransport/http_transport.go
deleted file mode 100644
index c7c3c5283f5..00000000000
--- a/workhorse/internal/helper/httptransport/http_transport.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package httptransport
-
-import (
- "net/http"
- "time"
-
- "gitlab.com/gitlab-org/labkit/correlation"
- "gitlab.com/gitlab-org/labkit/tracing"
-)
-
-type Option func(*http.Transport)
-
-// Defines a http.Transport with values
-// that are more restrictive than for http.DefaultTransport,
-// they define shorter TLS Handshake, and more aggressive connection closing
-// to prevent the connection hanging and reduce FD usage
-func New(options ...Option) http.RoundTripper {
- t := http.DefaultTransport.(*http.Transport).Clone()
-
- // To avoid keep around TCP connections to http servers we're done with
- t.MaxIdleConns = 2
-
- // A stricter timeout for fetching from external sources that can be slow
- t.ResponseHeaderTimeout = 30 * time.Second
-
- for _, option := range options {
- option(t)
- }
-
- return tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(t))
-}
-
-func WithDisabledCompression() Option {
- return func(t *http.Transport) {
- t.DisableCompression = true
- }
-}
diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go
index 8c3271b6f11..092369cd2af 100644
--- a/workhorse/internal/imageresizer/image_resizer.go
+++ b/workhorse/internal/imageresizer/image_resizer.go
@@ -21,9 +21,9 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport"
)
type Resizer struct {
@@ -69,7 +69,7 @@ const (
var envInjector = tracing.NewEnvInjector()
var httpClient = &http.Client{
- Transport: httptransport.New(),
+ Transport: transport.NewRestrictedTransport(),
}
const (
diff --git a/workhorse/internal/queueing/queue.go b/workhorse/internal/queueing/queue.go
index db082cf19c6..c8d32280355 100644
--- a/workhorse/internal/queueing/queue.go
+++ b/workhorse/internal/queueing/queue.go
@@ -26,11 +26,10 @@ type queueMetrics struct {
// newQueueMetrics prepares Prometheus metrics for queueing mechanism
// name specifies name of the queue, used to label metrics with ConstLabel `queue_name`
-// Don't call newQueueMetrics twice with the same name argument!
// timeout specifies the timeout of storing a request in queue - queueMetrics
// uses it to calculate histogram buckets for gitlab_workhorse_queueing_waiting_time
// metric
-func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
+func newQueueMetrics(name string, timeout time.Duration, reg prometheus.Registerer) *queueMetrics {
waitingTimeBuckets := []float64{
timeout.Seconds() * 0.01,
timeout.Seconds() * 0.05,
@@ -44,8 +43,9 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
timeout.Seconds(),
}
+ promFactory := promauto.With(reg)
metrics := &queueMetrics{
- queueingLimit: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingLimit: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_limit",
Help: "Current limit set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -53,7 +53,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingQueueLimit: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingQueueLimit: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_queue_limit",
Help: "Current queueLimit set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -61,7 +61,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingQueueTimeout: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingQueueTimeout: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_queue_timeout",
Help: "Current queueTimeout set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -69,7 +69,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingBusy: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingBusy: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_busy",
Help: "How many queued requests are now processed",
ConstLabels: prometheus.Labels{
@@ -77,7 +77,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingWaiting: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingWaiting: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_waiting",
Help: "How many requests are now queued",
ConstLabels: prometheus.Labels{
@@ -85,7 +85,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingWaitingTime: promauto.NewHistogram(prometheus.HistogramOpts{
+ queueingWaitingTime: promFactory.NewHistogram(prometheus.HistogramOpts{
Name: "gitlab_workhorse_queueing_waiting_time",
Help: "How many time a request spent in queue",
ConstLabels: prometheus.Labels{
@@ -94,7 +94,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
Buckets: waitingTimeBuckets,
}),
- queueingErrors: promauto.NewCounterVec(
+ queueingErrors: promFactory.NewCounterVec(
prometheus.CounterOpts{
Name: "gitlab_workhorse_queueing_errors",
Help: "How many times the TooManyRequests or QueueintTimedout errors were returned while queueing, partitioned by error type",
@@ -120,12 +120,11 @@ type Queue struct {
// newQueue creates a new queue
// name specifies name used to label queue metrics.
-// Don't call newQueue twice with the same name argument!
// limit specifies number of requests run concurrently
// queueLimit specifies maximum number of requests that can be queued
// timeout specifies the time limit of storing the request in the queue
// if the number of requests is above the limit
-func newQueue(name string, limit, queueLimit uint, timeout time.Duration) *Queue {
+func newQueue(name string, limit, queueLimit uint, timeout time.Duration, reg prometheus.Registerer) *Queue {
queue := &Queue{
name: name,
busyCh: make(chan struct{}, limit),
@@ -133,7 +132,7 @@ func newQueue(name string, limit, queueLimit uint, timeout time.Duration) *Queue
timeout: timeout,
}
- queue.queueMetrics = newQueueMetrics(name, timeout)
+ queue.queueMetrics = newQueueMetrics(name, timeout, reg)
queue.queueingLimit.Set(float64(limit))
queue.queueingQueueLimit.Set(float64(queueLimit))
queue.queueingQueueTimeout.Set(timeout.Seconds())
diff --git a/workhorse/internal/queueing/queue_test.go b/workhorse/internal/queueing/queue_test.go
index 7f5ed9154f4..dee0df76c67 100644
--- a/workhorse/internal/queueing/queue_test.go
+++ b/workhorse/internal/queueing/queue_test.go
@@ -3,10 +3,12 @@ package queueing
import (
"testing"
"time"
+
+ "github.com/prometheus/client_golang/prometheus"
)
func TestNormalQueueing(t *testing.T) {
- q := newQueue("queue 1", 2, 1, time.Microsecond)
+ q := newQueue("queue name", 2, 1, time.Microsecond, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
@@ -31,7 +33,7 @@ func TestNormalQueueing(t *testing.T) {
}
func TestQueueLimit(t *testing.T) {
- q := newQueue("queue 2", 1, 0, time.Microsecond)
+ q := newQueue("queue name", 1, 0, time.Microsecond, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
@@ -44,7 +46,7 @@ func TestQueueLimit(t *testing.T) {
}
func TestQueueProcessing(t *testing.T) {
- q := newQueue("queue 3", 1, 1, time.Second)
+ q := newQueue("queue name", 1, 1, time.Second, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
diff --git a/workhorse/internal/queueing/requests.go b/workhorse/internal/queueing/requests.go
index 3a22cb367ce..34d4c985f53 100644
--- a/workhorse/internal/queueing/requests.go
+++ b/workhorse/internal/queueing/requests.go
@@ -4,6 +4,8 @@ import (
"net/http"
"time"
+ "github.com/prometheus/client_golang/prometheus"
+
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
)
@@ -19,7 +21,7 @@ const (
// limit specifies number of requests run concurrently
// queueLimit specifies maximum number of requests that can be queued
// queueTimeout specifies the time limit of storing the request in the queue
-func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTimeout time.Duration) http.Handler {
+func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTimeout time.Duration, reg prometheus.Registerer) http.Handler {
if limit == 0 {
return h
}
@@ -27,7 +29,7 @@ func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTim
queueTimeout = DefaultTimeout
}
- queue := newQueue(name, limit, queueLimit, queueTimeout)
+ queue := newQueue(name, limit, queueLimit, queueTimeout, reg)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := queue.Acquire()
diff --git a/workhorse/internal/queueing/requests_test.go b/workhorse/internal/queueing/requests_test.go
index f1c52e5c6f5..eb098a6242e 100644
--- a/workhorse/internal/queueing/requests_test.go
+++ b/workhorse/internal/queueing/requests_test.go
@@ -6,6 +6,8 @@ import (
"net/http/httptest"
"testing"
"time"
+
+ "github.com/prometheus/client_golang/prometheus"
)
var httpHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -21,7 +23,7 @@ func pausedHttpHandler(pauseCh chan struct{}) http.Handler {
func TestNormalRequestProcessing(t *testing.T) {
w := httptest.NewRecorder()
- h := QueueRequests("Normal request processing", httpHandler, 1, 1, time.Second)
+ h := QueueRequests("Normal request processing", httpHandler, 1, 1, time.Second, prometheus.NewRegistry())
h.ServeHTTP(w, nil)
if w.Code != 200 {
t.Fatal("QueueRequests should process request")
@@ -36,7 +38,7 @@ func testSlowRequestProcessing(name string, count int, limit, queueLimit uint, q
pauseCh := make(chan struct{})
defer close(pauseCh)
- handler := QueueRequests("Slow request processing: "+name, pausedHttpHandler(pauseCh), limit, queueLimit, queueTimeout)
+ handler := QueueRequests("Slow request processing: "+name, pausedHttpHandler(pauseCh), limit, queueLimit, queueTimeout, prometheus.NewRegistry())
respCh := make(chan *httptest.ResponseRecorder, count)
diff --git a/workhorse/internal/redis/redis.go b/workhorse/internal/redis/redis.go
index 588fba6e242..03118cfcef6 100644
--- a/workhorse/internal/redis/redis.go
+++ b/workhorse/internal/redis/redis.go
@@ -1,7 +1,6 @@
package redis
import (
- "errors"
"fmt"
"net"
"net/url"
@@ -164,7 +163,15 @@ func sentinelDialer(dopts []redis.DialOption) redisDialerFunc {
return nil, err
}
dopts = append(dopts, redis.DialNetDial(keepAliveDialer))
- return redisDial("tcp", address, dopts...)
+ conn, err := redisDial("tcp", address, dopts...)
+ if err != nil {
+ return nil, err
+ }
+ if !sentinel.TestRole(conn, "master") {
+ conn.Close()
+ return nil, fmt.Errorf("%s is not redis master", address)
+ }
+ return conn, nil
}
}
@@ -247,14 +254,6 @@ func Configure(cfg *config.RedisConfig, dialFunc func(*config.RedisConfig, bool)
Dial: poolDialFunc,
Wait: true,
}
- if sntnl != nil {
- pool.TestOnBorrow = func(c redis.Conn, t time.Time) error {
- if !sentinel.TestRole(c, "master") {
- return errors.New("role check failed")
- }
- return nil
- }
- }
}
// Get a connection for the Redis-pool
diff --git a/workhorse/internal/sendurl/sendurl.go b/workhorse/internal/sendurl/sendurl.go
index 205ec8a0e9f..8e679c6b475 100644
--- a/workhorse/internal/sendurl/sendurl.go
+++ b/workhorse/internal/sendurl/sendurl.go
@@ -11,9 +11,9 @@ import (
"gitlab.com/gitlab-org/labkit/mask"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport"
)
type entry struct{ senddata.Prefix }
@@ -44,7 +44,7 @@ var preserveHeaderKeys = map[string]bool{
"Pragma": true, // Support for HTTP 1.0 proxies
}
-var httpTransport = httptransport.New()
+var httpTransport = transport.NewRestrictedTransport()
var httpClient = &http.Client{
Transport: httpTransport,
diff --git a/workhorse/internal/transport/transport.go b/workhorse/internal/transport/transport.go
new file mode 100644
index 00000000000..f19d332a28a
--- /dev/null
+++ b/workhorse/internal/transport/transport.go
@@ -0,0 +1,58 @@
+package transport
+
+import (
+ "net/http"
+ "time"
+
+ "gitlab.com/gitlab-org/labkit/correlation"
+ "gitlab.com/gitlab-org/labkit/tracing"
+
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/version"
+)
+
+// Creates a new default transport that has Workhorse's User-Agent header set.
+func NewDefaultTransport() http.RoundTripper {
+ return &DefaultTransport{Next: http.DefaultTransport}
+}
+
+// Defines a http.Transport with values that are more restrictive than for
+// http.DefaultTransport, they define shorter TLS Handshake, and more
+// aggressive connection closing to prevent the connection hanging and reduce
+// FD usage
+func NewRestrictedTransport(options ...Option) http.RoundTripper {
+ return &DefaultTransport{Next: newRestrictedTransport(options...)}
+}
+
+type DefaultTransport struct {
+ Next http.RoundTripper
+}
+
+func (t DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ req.Header.Set("User-Agent", version.GetUserAgent())
+
+ return t.Next.RoundTrip(req)
+}
+
+type Option func(*http.Transport)
+
+func WithDisabledCompression() Option {
+ return func(t *http.Transport) {
+ t.DisableCompression = true
+ }
+}
+
+func newRestrictedTransport(options ...Option) http.RoundTripper {
+ t := http.DefaultTransport.(*http.Transport).Clone()
+
+ // To avoid keep around TCP connections to http servers we're done with
+ t.MaxIdleConns = 2
+
+ // A stricter timeout for fetching from external sources that can be slow
+ t.ResponseHeaderTimeout = 30 * time.Second
+
+ for _, option := range options {
+ option(t)
+ }
+
+ return tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(t))
+}
diff --git a/workhorse/internal/upload/destination/objectstore/object.go b/workhorse/internal/upload/destination/objectstore/object.go
index 36ffa0eb12e..1086332312c 100644
--- a/workhorse/internal/upload/destination/objectstore/object.go
+++ b/workhorse/internal/upload/destination/objectstore/object.go
@@ -8,11 +8,11 @@ import (
"gitlab.com/gitlab-org/labkit/mask"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport"
)
var httpClient = &http.Client{
- Transport: httptransport.New(),
+ Transport: transport.NewRestrictedTransport(),
}
// Object represents an object on a S3 compatible Object Store service.
diff --git a/workhorse/internal/upload/destination/objectstore/s3_session.go b/workhorse/internal/upload/destination/objectstore/s3_session.go
index d71b38eb22e..e1fe6fbbdc9 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_session.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_session.go
@@ -37,17 +37,13 @@ func (s *s3Session) isExpired() bool {
return time.Now().After(s.expiry)
}
-func newS3SessionCache() *s3SessionCache {
- return &s3SessionCache{sessions: make(map[config.S3Config]*s3Session)}
-}
-
var (
// By default, it looks like IAM instance profiles may last 6 hours
// (via curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role_name>),
// but this may be configurable from anywhere for 15 minutes to 12
// hours. To be safe, refresh AWS sessions every 10 minutes.
sessionExpiration = time.Duration(10 * time.Minute)
- sessionCache = newS3SessionCache()
+ sessionCache = &s3SessionCache{sessions: make(map[config.S3Config]*s3Session)}
)
// SetupS3Session initializes a new AWS S3 session and refreshes one if
@@ -105,10 +101,3 @@ func setupS3Session(s3Credentials config.S3Credentials, s3Config config.S3Config
return sess, nil
}
-
-func ResetS3Session(s3Config config.S3Config) {
- sessionCache.Lock()
- defer sessionCache.Unlock()
-
- delete(sessionCache.sessions, s3Config)
-}
diff --git a/workhorse/internal/upload/destination/objectstore/s3_session_test.go b/workhorse/internal/upload/destination/objectstore/s3_session_test.go
index 4bbe38f90ec..b7bbee0ef69 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_session_test.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_session_test.go
@@ -12,6 +12,8 @@ import (
)
func TestS3SessionSetup(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
cfg := config.S3Config{Region: "us-west-1", PathStyle: true}
@@ -28,11 +30,11 @@ func TestS3SessionSetup(t *testing.T) {
_, err = setupS3Session(credentials, anotherConfig)
require.NoError(t, err)
require.Equal(t, len(sessionCache.sessions), 1)
-
- ResetS3Session(cfg)
}
func TestS3SessionEndpointSetup(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
const customS3Endpoint = "https://example.com"
const region = "us-west-2"
@@ -48,11 +50,11 @@ func TestS3SessionEndpointSetup(t *testing.T) {
stsConfig := sess.ClientConfig(endpoints.StsServiceID)
require.Equal(t, "https://sts.amazonaws.com", stsConfig.Endpoint, "STS should use default endpoint")
-
- ResetS3Session(cfg)
}
func TestS3SessionExpiry(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
cfg := config.S3Config{Region: "us-west-1", PathStyle: true}
@@ -75,6 +77,10 @@ func TestS3SessionExpiry(t *testing.T) {
nextSession, ok := sessionCache.sessions[cfg]
require.True(t, ok)
require.False(t, nextSession.isExpired())
+}
- ResetS3Session(cfg)
+func resetS3Sessions() {
+ sessionCache.Lock()
+ defer sessionCache.Unlock()
+ sessionCache.sessions = make(map[config.S3Config]*s3Session)
}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 40cd012a890..08e3ef8c9f1 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -6,6 +6,7 @@ import (
"regexp"
"github.com/gorilla/websocket"
+ "github.com/prometheus/client_golang/prometheus"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/labkit/tracing"
@@ -221,7 +222,7 @@ func configureRoutes(u *upstream) {
mimeMultipartUploader := upload.Multipart(api, signingProxy, preparer)
tempfileMultipartProxy := upload.FixedPreAuthMultipart(api, proxy, preparer)
- ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout)
+ ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout, prometheus.DefaultRegisterer)
ciAPILongPolling := builds.RegisterHandler(ciAPIProxyQueue, u.watchKeyHandler, u.APICILongPollingDuration)
dependencyProxyInjector.SetUploadHandler(requestBodyUploader)
diff --git a/workhorse/internal/version/version.go b/workhorse/internal/version/version.go
new file mode 100644
index 00000000000..790edf8ffca
--- /dev/null
+++ b/workhorse/internal/version/version.go
@@ -0,0 +1,20 @@
+package version
+
+import "fmt"
+
+var version = "unknown"
+var build = "unknown"
+var schema = "gitlab-workhorse (%s)-(%s)"
+
+func SetVersion(v, b string) {
+ version = v
+ build = b
+}
+
+func GetUserAgent() string {
+ return GetApplicationVersion()
+}
+
+func GetApplicationVersion() string {
+ return fmt.Sprintf(schema, version, build)
+}
diff --git a/workhorse/internal/version/version_test.go b/workhorse/internal/version/version_test.go
new file mode 100644
index 00000000000..9d0581e093b
--- /dev/null
+++ b/workhorse/internal/version/version_test.go
@@ -0,0 +1,19 @@
+package version
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestVersion(t *testing.T) {
+ require.Equal(t, GetApplicationVersion(), "gitlab-workhorse (unknown)-(unknown)")
+
+ SetVersion("15.3", "123.123")
+
+ require.Equal(t, GetApplicationVersion(), "gitlab-workhorse (15.3)-(123.123)")
+
+ SetVersion("", "123.123")
+
+ require.Equal(t, GetApplicationVersion(), "gitlab-workhorse ()-(123.123)")
+}
diff --git a/workhorse/internal/zipartifacts/open_archive.go b/workhorse/internal/zipartifacts/open_archive.go
index 881ef915d75..d477725a39f 100644
--- a/workhorse/internal/zipartifacts/open_archive.go
+++ b/workhorse/internal/zipartifacts/open_archive.go
@@ -8,16 +8,16 @@ import (
"os"
"strings"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/httprs"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport"
zip "gitlab.com/gitlab-org/golang-archive-zip"
"gitlab.com/gitlab-org/labkit/mask"
)
var httpClient = &http.Client{
- Transport: httptransport.New(
- httptransport.WithDisabledCompression(), // To avoid bugs when serving compressed files from object storage
+ Transport: transport.NewRestrictedTransport(
+ transport.WithDisabledCompression(), // To avoid bugs when serving compressed files from object storage
),
}
diff --git a/workhorse/main.go b/workhorse/main.go
index b0f9760b0d5..ca9b86de528 100644
--- a/workhorse/main.go
+++ b/workhorse/main.go
@@ -23,6 +23,7 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/redis"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/secret"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upstream"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/version"
)
// Version is the current version of GitLab Workhorse
@@ -55,8 +56,10 @@ func main() {
os.Exit(2)
}
+ version.SetVersion(Version, BuildTime)
+
if boot.printVersion {
- fmt.Printf("gitlab-workhorse %s-%s\n", Version, BuildTime)
+ fmt.Println(version.GetApplicationVersion())
os.Exit(0)
}
diff --git a/yarn.lock b/yarn.lock
index a0e22985f97..1d8029ca500 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -38,12 +38,12 @@
tslib "^2.3.0"
zen-observable-ts "^1.2.0"
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7":
- version "7.16.7"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
- integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
+ integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
dependencies:
- "@babel/highlight" "^7.16.7"
+ "@babel/highlight" "^7.18.6"
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.17.10":
version "7.17.10"
@@ -264,10 +264,10 @@
dependencies:
"@babel/types" "^7.16.7"
-"@babel/helper-validator-identifier@^7.15.7", "@babel/helper-validator-identifier@^7.16.7":
- version "7.16.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
- integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
+"@babel/helper-validator-identifier@^7.15.7", "@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
+ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
"@babel/helper-validator-option@^7.16.7":
version "7.16.7"
@@ -293,12 +293,12 @@
"@babel/traverse" "^7.18.2"
"@babel/types" "^7.18.2"
-"@babel/highlight@^7.16.7":
- version "7.16.10"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
- integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
+"@babel/highlight@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
+ integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
dependencies:
- "@babel/helper-validator-identifier" "^7.16.7"
+ "@babel/helper-validator-identifier" "^7.18.6"
chalk "^2.0.0"
js-tokens "^4.0.0"
@@ -987,6 +987,13 @@
codesandbox-import-utils "^1.2.3"
lodash.isequal "^4.5.0"
+"@cspotcode/source-map-support@^0.8.0":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
+ integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
+ dependencies:
+ "@jridgewell/trace-mapping" "0.3.9"
+
"@csstools/selector-specificity@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87"
@@ -997,20 +1004,20 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==
-"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d"
- integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==
- dependencies:
- lodash.get "^4"
- make-error "^1"
- ts-node "^9"
- tslib "^2"
+"@esbuild/android-arm@0.15.9":
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.9.tgz#7e1221604ab88ed5021ead74fa8cca4405e1e431"
+ integrity sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==
-"@eslint/eslintrc@^1.3.2":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356"
- integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==
+"@esbuild/linux-loong64@0.15.9":
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz#b658a97babf1f40783354af7039b84c3fdfc3fc3"
+ integrity sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==
+
+"@eslint/eslintrc@^1.3.3":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95"
+ integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
@@ -1027,10 +1034,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
-"@gitlab/eslint-plugin@17.0.0":
- version "17.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-17.0.0.tgz#5451fbbad96b09d812af2afb247f6602fe0be6c6"
- integrity sha512-c+sJtjzYl+KGPtZScU8Mji9seJw7dSEn31APyYEYTyWp72yMsFvXmg46txT2QCz+ueZlqk0/C2IQmgfe6fLcBw==
+"@gitlab/eslint-plugin@18.1.0":
+ version "18.1.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-18.1.0.tgz#8300cc938f50114b3e74d97660721486c13caea5"
+ integrity sha512-O803ResZfPpbSk8USzYwT79OXKSyuR4z4qbjOae/NIhzobxrlEHm4LbauVuaFpHurF5gYceNtHltczwK8e+mOg==
dependencies:
"@babel/core" "^7.17.0"
"@babel/eslint-parser" "^7.17.0"
@@ -1039,8 +1046,8 @@
eslint-config-prettier "^6.10.0"
eslint-plugin-babel "^5.3.0"
eslint-plugin-import "^2.26.0"
- eslint-plugin-jest "^23.8.2"
- eslint-plugin-promise "^4.2.1"
+ eslint-plugin-jest "^27.0.4"
+ eslint-plugin-promise "^6.0.1"
eslint-plugin-unicorn "^40.1.0"
eslint-plugin-vue "^9.3.0"
lodash "^4.17.21"
@@ -1059,15 +1066,15 @@
stylelint-declaration-strict-value "1.8.0"
stylelint-scss "4.2.0"
-"@gitlab/svgs@3.3.0":
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.3.0.tgz#99b044484fcf3d5a6431281e320e2405540ff5a9"
- integrity sha512-S8Hqf+ms8aNrSgmci9SVoIyj/0qQnizU5uV5vUPAOwiufMDFDyI5qfcgn4EYZ6mnju3LiO+ReSL/PPTD4qNgHA==
+"@gitlab/svgs@3.5.0":
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.5.0.tgz#226240b7aa93db986f4c6f7738ca2a1846b5234d"
+ integrity sha512-/djPsJzUY7i/FaydRVt3ZyXiFf5HGNo1rg2mfLn1EpXvT4zc2ag5ECwnYcPb97KgqFCJX6Tk+Ndu8Wh3GoOW1g==
-"@gitlab/ui@43.16.0":
- version "43.16.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-43.16.0.tgz#cb383b5ca95b7b3d3fbb5d134a71676050c0aa20"
- integrity sha512-wdB2Mjto7UgLaeeW6mSmUiWW2xxhl98msB18kcDFqth2cJ59JHvA6eUydmt8Es6pJ9kKj7MLUiC64wEaNgpQBA==
+"@gitlab/ui@46.1.0":
+ version "46.1.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-46.1.0.tgz#df5918dfcf76ee444ad587f325d55555e8001de7"
+ integrity sha512-11zdly3bDWRqlbPo5kmhoDzcJ0n16kuhuxk2U4N8TMfHXgu6vUYp5NgjPrxzZRHlNVXsYiz7cAqifbr56fxTPg==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.20.1"
@@ -1090,19 +1097,19 @@
dependencies:
mustache "^4.2.0"
-"@graphql-eslint/eslint-plugin@3.10.7":
- version "3.10.7"
- resolved "https://registry.yarnpkg.com/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.10.7.tgz#9a203e2084371eca933d88b73ce7a6bebbbb9872"
- integrity sha512-Vp32LMsHTgRNc2q+OrXRNR1i2nlAbVfN0tMTlFHgnzJfnEJDV332cpjiUF9F82IKjNFSde/pF3cuYccu+UUR/g==
+"@graphql-eslint/eslint-plugin@3.12.0":
+ version "3.12.0"
+ resolved "https://registry.yarnpkg.com/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.12.0.tgz#8676ef4ae113a8f0e5893e41ab0e391bf6667381"
+ integrity sha512-DHa6hhCYxGjUtGK6VWcaWHs1RNSIpuZaQOzI7F2ZoVdtd3+amxv6S7h0KwUe+CX+oV3Oxa7x5bFonc/Td6wjaw==
dependencies:
- "@babel/code-frame" "^7.16.7"
- "@graphql-tools/code-file-loader" "^7.2.14"
- "@graphql-tools/graphql-tag-pluck" "^7.2.6"
- "@graphql-tools/utils" "^8.6.9"
+ "@babel/code-frame" "^7.18.6"
+ "@graphql-tools/code-file-loader" "^7.3.6"
+ "@graphql-tools/graphql-tag-pluck" "^7.3.6"
+ "@graphql-tools/utils" "^8.12.0"
chalk "^4.1.2"
debug "^4.3.4"
- fast-glob "^3.2.11"
- graphql-config "^4.3.0"
+ fast-glob "^3.2.12"
+ graphql-config "^4.3.6"
graphql-depth-limit "^1.1.0"
lodash.lowercase "^4.3.0"
@@ -1116,15 +1123,15 @@
tslib "~2.3.0"
value-or-promise "1.0.11"
-"@graphql-tools/code-file-loader@^7.2.14":
- version "7.2.15"
- resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.2.15.tgz#2307741bec6987c88a1a53695cb17dc59c8ba7a0"
- integrity sha512-tqViC0MEXadcGofqDU4mL7eA/+TyM4iCP+XRkL/mdAMYWp1JdzMYUJcCH47ZK1+EvNctYx8sJOpSGlvLR4ZFFg==
+"@graphql-tools/code-file-loader@^7.3.6":
+ version "7.3.6"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.3.6.tgz#3e6bdd4dc93c592be3d6fbcc2c2bad1228ca0f8d"
+ integrity sha512-PNWWSwSuQAqANerDwS0zdQ5FPipirv75TjjzBHnY+6AF/WvKq5sQiUQheA2P7B+MZc/KdQ7h/JAGMQOhKNVA+Q==
dependencies:
- "@graphql-tools/graphql-tag-pluck" "7.2.7"
- "@graphql-tools/utils" "8.6.10"
+ "@graphql-tools/graphql-tag-pluck" "7.3.6"
+ "@graphql-tools/utils" "8.12.0"
globby "^11.0.3"
- tslib "~2.4.0"
+ tslib "^2.4.0"
unixify "^1.0.0"
"@graphql-tools/delegate@8.7.1":
@@ -1151,16 +1158,16 @@
tslib "~2.3.0"
unixify "^1.0.0"
-"@graphql-tools/graphql-tag-pluck@7.2.7", "@graphql-tools/graphql-tag-pluck@^7.2.6":
- version "7.2.7"
- resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.2.7.tgz#c137a3460898c7f82fcab20b958010637009a9b1"
- integrity sha512-leh6rVHNoGXjmbOtTaKNXQtFw4Gu7PokTlEOweNKYMssbH6L1zrKA0G4cE55s60JBo9SF4hjg8X7Gkech5t+mQ==
+"@graphql-tools/graphql-tag-pluck@7.3.6", "@graphql-tools/graphql-tag-pluck@^7.3.6":
+ version "7.3.6"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.3.6.tgz#27029ef9e8d7f4bcf8dd8627fb93bd45cc0215fd"
+ integrity sha512-qULgqsOGKY1/PBqmP7fJZqbCg/TzPHKB9Wl51HGA9QjGymrzmrH5EjvsC8RtgdubF8yuTTVVFTz1lmSQ7RPssQ==
dependencies:
"@babel/parser" "^7.16.8"
"@babel/traverse" "^7.16.8"
"@babel/types" "^7.16.8"
- "@graphql-tools/utils" "8.6.10"
- tslib "~2.4.0"
+ "@graphql-tools/utils" "8.12.0"
+ tslib "^2.4.0"
"@graphql-tools/import@6.6.9":
version "6.6.9"
@@ -1233,12 +1240,12 @@
value-or-promise "^1.0.11"
ws "^8.3.0"
-"@graphql-tools/utils@8.6.10", "@graphql-tools/utils@^8.6.5", "@graphql-tools/utils@^8.6.9":
- version "8.6.10"
- resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.6.10.tgz#38e42a97a74ffcf5a21e816401e2ca1647194f6a"
- integrity sha512-bJH9qwuyM3BP0PTU6/lvBDkk6jdEIOn+dbyk4pHMVNnvbJ1gZQwo62To8SHxxaUTus8OMhhVPSh9ApWXREURcg==
+"@graphql-tools/utils@8.12.0", "@graphql-tools/utils@^8.12.0", "@graphql-tools/utils@^8.6.5":
+ version "8.12.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.12.0.tgz#243bc4f5fc2edbc9e8fd1038189e57d837cbe31f"
+ integrity sha512-TeO+MJWGXjUTS52qfK4R8HiPoF/R7X+qmgtOYd8DTH0l6b+5Y/tlg5aGeUJefqImRq7nvi93Ms40k/Uz4D5CWw==
dependencies:
- tslib "~2.4.0"
+ tslib "^2.4.0"
"@graphql-tools/utils@8.6.5":
version "8.6.5"
@@ -1263,20 +1270,15 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950"
integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==
-"@humanwhocodes/config-array@^0.10.4":
- version "0.10.4"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c"
- integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==
+"@humanwhocodes/config-array@^0.10.5":
+ version "0.10.5"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.5.tgz#bb679745224745fff1e9a41961c1d45a49f81c04"
+ integrity sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==
dependencies:
"@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
minimatch "^3.0.4"
-"@humanwhocodes/gitignore-to-minimatch@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
- integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
-
"@humanwhocodes/module-importer@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
@@ -1512,10 +1514,10 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
-"@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.9":
- version "0.3.13"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
- integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
+"@jridgewell/trace-mapping@0.3.9", "@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.9"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
+ integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
dependencies:
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
@@ -1877,6 +1879,15 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.17.tgz#4fdd1bdf62c82c1af6feef91c689906a8f5b171e"
integrity sha512-OyKL+pqWJEtjyd9/mrsuY1kZh2b3LWpOQDWKtd4aWR4EA0efmQG+7FPwcIeAVEh7ZoqM+/ABCnPjN6IjzIrSfg==
+"@tiptap/suggestion@^2.0.0-beta.96":
+ version "2.0.0-beta.98"
+ resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.0.0-beta.98.tgz#b953ae9153eab6ea07fa39ec5aafaa3eba695117"
+ integrity sha512-zdXMdLBt+i/LWu3ZxGV9/UpMCrArqhno73/Tfno+9Gz2Y+jrUsex01sPuf3L/e8YlySAdLmZImNtTc7LjXsvEQ==
+ dependencies:
+ prosemirror-model "1.18.1"
+ prosemirror-state "1.4.1"
+ prosemirror-view "1.26.2"
+
"@tiptap/vue-2@^2.0.0-beta.84":
version "2.0.0-beta.84"
resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.84.tgz#abf2e8e53759e9d7c69b6a7f62164a1a8be2c013"
@@ -1891,6 +1902,26 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+"@tsconfig/node10@^1.0.7":
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
+ integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==
+
+"@tsconfig/node12@^1.0.7":
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
+ integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
+
+"@tsconfig/node14@^1.0.0":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
+ integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
+
+"@tsconfig/node16@^1.0.2":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
+ integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
+
"@types/aria-query@^4.2.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
@@ -2047,10 +2078,10 @@
jest-matcher-utils "^27.0.0"
pretty-format "^27.0.0"
-"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
- version "7.0.9"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
- integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
+"@types/json-schema@^7.0.0", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+ version "7.0.11"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
"@types/json5@^0.0.29":
version "0.0.29"
@@ -2204,28 +2235,51 @@
dependencies:
"@types/yargs-parser" "*"
-"@typescript-eslint/experimental-utils@^2.5.0":
- version "2.30.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.30.0.tgz#9845e868c01f3aed66472c561d4b6bac44809dd0"
- integrity sha512-L3/tS9t+hAHksy8xuorhOzhdefN0ERPDWmR9CclsIGOUqGKy6tqc/P+SoXeJRye5gazkuPO0cK9MQRnolykzkA==
+"@typescript-eslint/scope-manager@5.38.0":
+ version "5.38.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz#8f0927024b6b24e28671352c93b393a810ab4553"
+ integrity sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==
dependencies:
- "@types/json-schema" "^7.0.3"
- "@typescript-eslint/typescript-estree" "2.30.0"
- eslint-scope "^5.0.0"
- eslint-utils "^2.0.0"
+ "@typescript-eslint/types" "5.38.0"
+ "@typescript-eslint/visitor-keys" "5.38.0"
-"@typescript-eslint/typescript-estree@2.30.0":
- version "2.30.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.30.0.tgz#1b8e848b55144270255ffbfe4c63291f8f766615"
- integrity sha512-nI5WOechrA0qAhnr+DzqwmqHsx7Ulr/+0H7bWCcClDhhWkSyZR5BmTvnBEyONwJCTWHfc5PAQExX24VD26IAVw==
+"@typescript-eslint/types@5.38.0":
+ version "5.38.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.0.tgz#8cd15825e4874354e31800dcac321d07548b8a5f"
+ integrity sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==
+
+"@typescript-eslint/typescript-estree@5.38.0":
+ version "5.38.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz#89f86b2279815c6fb7f57d68cf9b813f0dc25d98"
+ integrity sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==
dependencies:
- debug "^4.1.1"
- eslint-visitor-keys "^1.1.0"
- glob "^7.1.6"
- is-glob "^4.0.1"
- lodash "^4.17.15"
- semver "^6.3.0"
- tsutils "^3.17.1"
+ "@typescript-eslint/types" "5.38.0"
+ "@typescript-eslint/visitor-keys" "5.38.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@^5.10.0":
+ version "5.38.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.38.0.tgz#5b31f4896471818153790700eb02ac869a1543f4"
+ integrity sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@typescript-eslint/scope-manager" "5.38.0"
+ "@typescript-eslint/types" "5.38.0"
+ "@typescript-eslint/typescript-estree" "5.38.0"
+ eslint-scope "^5.1.1"
+ eslint-utils "^3.0.0"
+
+"@typescript-eslint/visitor-keys@5.38.0":
+ version "5.38.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz#60591ca3bf78aa12b25002c0993d067c00887e34"
+ integrity sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==
+ dependencies:
+ "@typescript-eslint/types" "5.38.0"
+ eslint-visitor-keys "^3.3.0"
"@vue/component-compiler-utils@^3.1.0":
version "3.3.0"
@@ -2461,6 +2515,11 @@
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
+JSV@^4.0.x:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57"
+ integrity sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==
+
abab@^2.0.3, abab@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
@@ -2504,10 +2563,10 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn-walk@^8.0.0:
- version "8.0.2"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3"
- integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==
+acorn-walk@^8.0.0, acorn-walk@^8.1.1:
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
+ integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
acorn@^6.4.1:
version "6.4.2"
@@ -2519,7 +2578,7 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-acorn@^8.0.4, acorn@^8.2.4, acorn@^8.8.0:
+acorn@^8.0.4, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.0:
version "8.8.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
@@ -2624,6 +2683,11 @@ ansi-styles@^5.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+ansi-styles@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
+ integrity sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==
+
anymatch@^3.0.3, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
@@ -3124,16 +3188,15 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
-browserslist@^4.20.2, browserslist@^4.20.3:
- version "4.20.3"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf"
- integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==
+browserslist@^4.20.2, browserslist@^4.20.3, browserslist@^4.21.3:
+ version "4.21.3"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a"
+ integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
dependencies:
- caniuse-lite "^1.0.30001332"
- electron-to-chromium "^1.4.118"
- escalade "^3.1.1"
- node-releases "^2.0.3"
- picocolors "^1.0.0"
+ caniuse-lite "^1.0.30001370"
+ electron-to-chromium "^1.4.202"
+ node-releases "^2.0.6"
+ update-browserslist-db "^1.0.5"
bser@2.1.1:
version "2.1.1"
@@ -3297,10 +3360,10 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-caniuse-lite@^1.0.30001332:
- version "1.0.30001340"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz#029a2f8bfc025d4820fafbfaa6259fd7778340c7"
- integrity sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==
+caniuse-lite@^1.0.30001370:
+ version "1.0.30001388"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001388.tgz#88e01f4591cbd81f9f665f3f078c66b509fbe55d"
+ integrity sha512-znVbq4OUjqgLxMxoNX2ZeeLR0d7lcDiE5uJ4eUiWdml1J1EkxbnQq6opT9jb9SMfJxB0XA16/ziHwni4u1I3GQ==
canvas-confetti@^1.4.0:
version "1.4.0"
@@ -3329,6 +3392,15 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
+chalk@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
+ integrity sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==
+ dependencies:
+ ansi-styles "~1.0.0"
+ has-color "~0.1.0"
+ strip-ansi "~0.1.0"
+
char-regex@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
@@ -3765,10 +3837,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.25.1:
- version "3.25.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.1.tgz#5818e09de0db8956e16bf10e2a7141e931b7c69c"
- integrity sha512-sr0FY4lnO1hkQ4gLDr24K0DGnweGO1QwSj5BpfQjpSJPdqWalja4cTps29Y/PJVG/P7FYlPDkH3hO+Tr0CvDgQ==
+core-js@^3.25.5:
+ version "3.25.5"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
+ integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
core-util-is@~1.0.0:
version "1.0.3"
@@ -3782,6 +3854,11 @@ cosmiconfig-toml-loader@1.0.0:
dependencies:
"@iarna/toml" "^2.2.5"
+cosmiconfig-typescript-loader@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.1.1.tgz#38dd3578344038dae40fdf09792bc2e9df529f78"
+ integrity sha512-9DHpa379Gp0o0Zefii35fcmuuin6q92FnLDffzdZ0l9tVd3nEobG3O+MZ06+kuBvFTSVScvNb/oHA13Nd4iipg==
+
cosmiconfig@7.0.1, cosmiconfig@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
@@ -4836,6 +4913,11 @@ domhandler@^4.0.0, domhandler@^4.2.0:
dependencies:
domelementtype "^2.2.0"
+dommatrix@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/dommatrix/-/dommatrix-1.0.3.tgz#e7c18e8d6f3abdd1fef3dd4aa74c4d2e620a0525"
+ integrity sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==
+
dompurify@2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
@@ -4908,10 +4990,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-electron-to-chromium@^1.4.118:
- version "1.4.137"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f"
- integrity sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==
+electron-to-chromium@^1.4.202:
+ version "1.4.230"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.230.tgz#666909fdf5765acb1348b69752ee9955dc1664b7"
+ integrity sha512-3pwjAK0qHSDN9+YAF4fJknsSruP7mpjdWzUSruIJD/JCH77pEh0SorEyb3xVaKkfwk2tzjOt2D8scJ0KAdfXLA==
elliptic@^6.0.0:
version "6.5.4"
@@ -5055,6 +5137,146 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
+esbuild-android-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz#4a7eb320ca8d3a305f14792061fd9614ccebb7c0"
+ integrity sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==
+
+esbuild-android-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz#c948e5686df20857ad361ec67e070d40d7cab985"
+ integrity sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==
+
+esbuild-darwin-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz#25f564fa4b39c1cec84dc46bce5634fdbce1d5e4"
+ integrity sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==
+
+esbuild-darwin-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz#60faea3ed95d15239536aa88d06bb82b29278a86"
+ integrity sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==
+
+esbuild-freebsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz#0339ef1c90a919175e7816788224517896657a0e"
+ integrity sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==
+
+esbuild-freebsd-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz#32abfc0be3ae3dd38e5a86a9beadbbcf592f1b57"
+ integrity sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==
+
+esbuild-linux-32@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz#93581348a4da7ed2b29bc5539f2605ad7fcee77b"
+ integrity sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==
+
+esbuild-linux-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz#0d171e7946c95d0d3ed4826026af2c5632d7dcc4"
+ integrity sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==
+
+esbuild-linux-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz#9838795a3720cbe736d3bc20621bd366eac22f24"
+ integrity sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==
+
+esbuild-linux-arm@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz#dce96cd817bc7376f6af3967649c4ab1f2f79506"
+ integrity sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==
+
+esbuild-linux-mips64le@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz#0335a0739e61aa97cb9b4a018e3facfcca9cdcfd"
+ integrity sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==
+
+esbuild-linux-ppc64le@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz#18482afb95b8a705e2da0a59d7131bff221281f9"
+ integrity sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==
+
+esbuild-linux-riscv64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz#03b6f9708272c117006b9ce1c9ae8aab91b5a5b6"
+ integrity sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==
+
+esbuild-linux-s390x@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz#65fb645623d575780f155f0ee52935e62f9cca4f"
+ integrity sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==
+
+esbuild-loader@^2.20.0:
+ version "2.20.0"
+ resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.20.0.tgz#28fcff0142fa7bd227512d69f31e9a6e202bb88f"
+ integrity sha512-dr+j8O4w5RvqZ7I4PPB4EIyVTd679EBQnMm+JBB7av+vu05Zpje2IpK5N3ld1VWa+WxrInIbNFAg093+E1aRsA==
+ dependencies:
+ esbuild "^0.15.6"
+ joycon "^3.0.1"
+ json5 "^2.2.0"
+ loader-utils "^2.0.0"
+ tapable "^2.2.0"
+ webpack-sources "^2.2.0"
+
+esbuild-netbsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz#7894297bb9e11f3d2f6f31efecd1be4e181f0d54"
+ integrity sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==
+
+esbuild-openbsd-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz#0f9d4c6b6772ae50d491d68ad4cc028300dda7c0"
+ integrity sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==
+
+esbuild-sunos-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz#c32b7ce574b08f814de810ce7c1e34b843768126"
+ integrity sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==
+
+esbuild-windows-32@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz#37a8f7cfccdb2177cd46613a1a1e1fcb419d36df"
+ integrity sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==
+
+esbuild-windows-64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz#5fe1e76fc13dd7f520febecaea110b6f1649c7b2"
+ integrity sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==
+
+esbuild-windows-arm64@0.15.9:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz#98504428f7ba7d2cfc11940be68ee1139173fdce"
+ integrity sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==
+
+esbuild@0.15.9, esbuild@^0.15.6:
+ version "0.15.9"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.9.tgz#33fb18b67b85004b6f7616bec955ca4b3e58935d"
+ integrity sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==
+ optionalDependencies:
+ "@esbuild/android-arm" "0.15.9"
+ "@esbuild/linux-loong64" "0.15.9"
+ esbuild-android-64 "0.15.9"
+ esbuild-android-arm64 "0.15.9"
+ esbuild-darwin-64 "0.15.9"
+ esbuild-darwin-arm64 "0.15.9"
+ esbuild-freebsd-64 "0.15.9"
+ esbuild-freebsd-arm64 "0.15.9"
+ esbuild-linux-32 "0.15.9"
+ esbuild-linux-64 "0.15.9"
+ esbuild-linux-arm "0.15.9"
+ esbuild-linux-arm64 "0.15.9"
+ esbuild-linux-mips64le "0.15.9"
+ esbuild-linux-ppc64le "0.15.9"
+ esbuild-linux-riscv64 "0.15.9"
+ esbuild-linux-s390x "0.15.9"
+ esbuild-netbsd-64 "0.15.9"
+ esbuild-openbsd-64 "0.15.9"
+ esbuild-sunos-64 "0.15.9"
+ esbuild-windows-32 "0.15.9"
+ esbuild-windows-64 "0.15.9"
+ esbuild-windows-arm64 "0.15.9"
+
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@@ -5181,12 +5403,12 @@ eslint-plugin-import@^2.26.0:
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
-eslint-plugin-jest@^23.8.2:
- version "23.8.2"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4"
- integrity sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==
+eslint-plugin-jest@^27.0.4:
+ version "27.0.4"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.0.4.tgz#ab9c7b3f48bfade4762c24c415a5d9bbc0174a61"
+ integrity sha512-BuvY78pHMpMJ6Cio7sKg6jrqEcnRYPUc4Nlihku4vKx3FjlmMINSX4vcYokZIe+8TKcyr1aI5Kq7vYwgJNdQSA==
dependencies:
- "@typescript-eslint/experimental-utils" "^2.5.0"
+ "@typescript-eslint/utils" "^5.10.0"
eslint-plugin-no-jquery@2.7.0:
version "2.7.0"
@@ -5198,10 +5420,10 @@ eslint-plugin-no-unsanitized@^4.0.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz#e2343265467ba2270ade478cbe07bbafeaea412d"
integrity sha512-y/lAMWnPPC7RYuUdxlEL/XiCL8FehN9h9s3Kjqbp/Kv0i9NZs+IXSC2kS546Fa4Bumwy31HlVS/OdWX0Kxb5Xg==
-eslint-plugin-promise@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
- integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
+eslint-plugin-promise@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz#a8cddf96a67c4059bdabf4d724a29572188ae423"
+ integrity sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==
eslint-plugin-unicorn@^40.1.0:
version "40.1.0"
@@ -5249,7 +5471,7 @@ eslint-scope@^4.0.3:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-scope@^5.0.0, eslint-scope@^5.1.1:
+eslint-scope@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
@@ -5265,13 +5487,6 @@ eslint-scope@^7.1.1:
esrecurse "^4.3.0"
estraverse "^5.2.0"
-eslint-utils@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
- integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
- dependencies:
- eslint-visitor-keys "^1.1.0"
-
eslint-utils@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
@@ -5279,11 +5494,6 @@ eslint-utils@^3.0.0:
dependencies:
eslint-visitor-keys "^2.0.0"
-eslint-visitor-keys@^1.1.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
- integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
-
eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
@@ -5294,14 +5504,13 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
-eslint@8.23.1:
- version "8.23.1"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc"
- integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==
+eslint@8.25.0:
+ version "8.25.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.25.0.tgz#00eb962f50962165d0c4ee3327708315eaa8058b"
+ integrity sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==
dependencies:
- "@eslint/eslintrc" "^1.3.2"
- "@humanwhocodes/config-array" "^0.10.4"
- "@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
+ "@eslint/eslintrc" "^1.3.3"
+ "@humanwhocodes/config-array" "^0.10.5"
"@humanwhocodes/module-importer" "^1.0.1"
ajv "^6.10.0"
chalk "^4.0.0"
@@ -5560,10 +5769,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-fast-glob@^3.2.11, fast-glob@^3.2.4, fast-glob@^3.2.9:
- version "3.2.11"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
- integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
+fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.4, fast-glob@^3.2.9:
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
@@ -6069,12 +6278,11 @@ graphlib@^2.1.8:
dependencies:
lodash "^4.17.15"
-graphql-config@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.3.0.tgz#b9bb7bf9c892a90e66ea937e8d7ed170eb1fd5e2"
- integrity sha512-Uiu3X7+s5c056WyrvdZVz2vG1fhAipMlYmtiCU/4Z2mX79OXDr1SqIon2MprC/pExIWJfAQZCcjYDY76fPBUQg==
+graphql-config@^4.3.6:
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.3.6.tgz#908ef03d6670c3068e51fe2e84e10e3e0af220b6"
+ integrity sha512-i7mAPwc0LAZPnYu2bI8B6yXU5820Wy/ArvmOseDLZIu0OU1UTULEuexHo6ZcHXeT9NvGGaUPQZm8NV3z79YydA==
dependencies:
- "@endemolshinegroup/cosmiconfig-typescript-loader" "3.0.2"
"@graphql-tools/graphql-file-loader" "^7.3.7"
"@graphql-tools/json-file-loader" "^7.3.7"
"@graphql-tools/load" "^7.5.5"
@@ -6083,8 +6291,11 @@ graphql-config@^4.3.0:
"@graphql-tools/utils" "^8.6.5"
cosmiconfig "7.0.1"
cosmiconfig-toml-loader "1.0.0"
+ cosmiconfig-typescript-loader "^4.0.0"
minimatch "4.2.1"
string-env-interpolation "1.0.1"
+ ts-node "^10.8.1"
+ tslib "^2.4.0"
graphql-depth-limit@^1.1.0:
version "1.1.0"
@@ -6120,6 +6331,11 @@ graphql@^15.7.2:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.7.2.tgz#85ab0eeb83722977151b3feb4d631b5f2ab287ef"
integrity sha512-AnnKk7hFQFmU/2I9YSQf3xw44ctnSFCfp3zE0N6W174gqe9fWG/2rKaKxROK7CcI3XtERpjEKFqts8o319Kf7A==
+gridstack@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-7.0.0.tgz#2d00b28efa8d22a8b9ad2640c8ab64b494bbfdc9"
+ integrity sha512-iBts/PRuqg6OQvdpv7A84p3RROxzXVSKjM3SJHrdl2pdDZKmIpGo2oxjdCHv6l+SzU2EuptcHd1Rqouocwl1Cg==
+
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@@ -6142,6 +6358,11 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+has-color@~0.1.0:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
+ integrity sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -7396,11 +7617,6 @@ jest-snapshot@^27.5.1:
pretty-format "^27.5.1"
semver "^7.3.2"
-jest-transform-graphql@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/jest-transform-graphql/-/jest-transform-graphql-2.1.0.tgz#903cb66bb27bc2772fd3e5dd4f7e9b57230f5829"
- integrity sha1-kDy2a7J7wncv0+XdT36bVyMPWCk=
-
jest-util@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
@@ -7456,6 +7672,11 @@ jest@^27.5.1:
import-local "^3.0.2"
jest-cli "^27.5.1"
+joycon@^3.0.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
+ integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
+
jquery.caret@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/jquery.caret/-/jquery.caret-0.3.1.tgz#9c093318faf327eff322e826ca9f3241368bc7b8"
@@ -7492,7 +7713,7 @@ js-sdsl@^4.1.4:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@^3.13.1, js-yaml@^3.14.1:
+js-yaml@^3.13.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@@ -7582,12 +7803,12 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-json5@^2.1.2, json5@^2.2.1:
+json5@^2.1.2, json5@^2.2.0, json5@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
-jsonc-parser@~3.1.0:
+jsonc-parser@^3.0.0, jsonc-parser@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.1.0.tgz#73b8f0e5c940b83d03476bc2e51a20ef0932615d"
integrity sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==
@@ -7599,6 +7820,14 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
+jsonlint@^1.6.3:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/jsonlint/-/jsonlint-1.6.3.tgz#cb5e31efc0b78291d0d862fbef05900adf212988"
+ integrity sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A==
+ dependencies:
+ JSV "^4.0.x"
+ nomnom "^1.5.x"
+
jszip@^3.1.3:
version "3.10.1"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
@@ -7805,7 +8034,7 @@ lodash.forin@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.forin/-/lodash.forin-4.4.0.tgz#5d3f20ae564011fbe88381f7d98949c9c9519731"
integrity sha1-XT8grlZAEfvog4H32YlJyclRlzE=
-lodash.get@^4, lodash.get@^4.4.2:
+lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
@@ -7968,7 +8197,7 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
dependencies:
semver "^6.0.0"
-make-error@^1, make-error@^1.1.1:
+make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
@@ -8840,14 +9069,31 @@ monaco-editor@^0.30.1:
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.30.1.tgz#47f8d18a0aa2264fc5654581741ab8d7bec01689"
integrity sha512-B/y4+b2O5G2gjuxIFtCE2EkM17R2NM7/3F8x0qcPsqy4V83bitJTIO4TIeZpYlzu/xy6INiY/+84BEm6+7Cmzg==
-monaco-yaml@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-3.0.0.tgz#b3d59c3485bd5a161438072a8e5a8aaf74041dfd"
- integrity sha512-WkgdfjCj0L2VPPwPoiwc4l8+B78FyVpSsMoufEWqe3ukm8+WygKUtmtCFOFnehmMih6tSqhy4DUtoAhfnicyZA==
- dependencies:
- "@types/json-schema" "^7.0.8"
- js-yaml "^3.14.1"
- yaml-ast-parser-custom-tags "^0.0.43"
+monaco-marker-data-provider@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/monaco-marker-data-provider/-/monaco-marker-data-provider-1.1.1.tgz#0ca69f367152f5aa12cec2bda95f32b7403e876f"
+ integrity sha512-PGB7TJSZE5tmHzkxv/OEwK2RGNC2A7dcq4JRJnnj31CUAsfmw0Gl+1QTrH0W0deKhcQmQM0YVPaqgQ+0wCt8Mg==
+
+monaco-worker-manager@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/monaco-worker-manager/-/monaco-worker-manager-2.0.1.tgz#f67c54dfca34ed4b225d5de84e77b24b4e36de8a"
+ integrity sha512-kdPL0yvg5qjhKPNVjJoym331PY/5JC11aPJXtCZNwWRvBr6jhkIamvYAyiY5P1AWFmNOy0aRDRoMdZfa71h8kg==
+
+monaco-yaml@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-4.0.0.tgz#3bf8624f984665aba7e5f10c4987cecf2890e89b"
+ integrity sha512-7/CbvZIHE1iOQF6ny+uPclcsrBnkK54lcZugIB9SzqADljhb3TliJyYs7vouaGNDF73RWvrtZrMsWCC5N/GW+g==
+ dependencies:
+ "@types/json-schema" "^7.0.0"
+ jsonc-parser "^3.0.0"
+ monaco-marker-data-provider "^1.0.0"
+ monaco-worker-manager "^2.0.0"
+ path-browserify "^1.0.0"
+ prettier "^2.0.0"
+ vscode-languageserver-textdocument "^1.0.0"
+ vscode-languageserver-types "^3.0.0"
+ vscode-uri "^3.0.0"
+ yaml "^2.0.0"
mousetrap@1.6.5:
version "1.6.5"
@@ -8946,11 +9192,6 @@ node-domexception@1.0.0:
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
-node-ensure@^0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
- integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
-
node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
@@ -8997,10 +9238,10 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
-node-releases@^2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476"
- integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==
+node-releases@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
+ integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
nodemon@^2.0.19:
version "2.0.19"
@@ -9018,6 +9259,14 @@ nodemon@^2.0.19:
touch "^3.1.0"
undefsafe "^2.0.5"
+nomnom@^1.5.x:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
+ integrity sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ==
+ dependencies:
+ chalk "~0.4.0"
+ underscore "~1.6.0"
+
nopt@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
@@ -9437,6 +9686,11 @@ path-browserify@0.0.1:
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
+path-browserify@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
+ integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
+
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -9488,13 +9742,13 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
-pdfjs-dist@^2.0.943:
- version "2.1.266"
- resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz#cded02268b389559e807f410d2a729db62160026"
- integrity sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ==
+pdfjs-dist@^2.16.105:
+ version "2.16.105"
+ resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz#937b9c4a918f03f3979c88209d84c1ce90122c2a"
+ integrity sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==
dependencies:
- node-ensure "^0.0.0"
- worker-loader "^2.0.0"
+ dommatrix "^1.0.3"
+ web-streams-polyfill "^3.2.1"
picocolors@^0.2.1:
version "0.2.1"
@@ -9670,7 +9924,7 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@2.2.1, "prettier@^1.18.2 || ^2.0.0":
+prettier@2.2.1, "prettier@^1.18.2 || ^2.0.0", prettier@^2.0.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
@@ -10417,9 +10671,9 @@ saxes@^5.0.1:
xmlchars "^2.2.0"
schema-utils@^0.4.0:
- version "0.4.5"
- resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e"
- integrity sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==
+ version "0.4.7"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
+ integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==
dependencies:
ajv "^6.1.0"
ajv-keywords "^3.1.0"
@@ -10481,10 +10735,10 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
-selfsigned@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56"
- integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==
+selfsigned@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61"
+ integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==
dependencies:
node-forge "^1"
@@ -10745,10 +10999,10 @@ sortablejs@^1.10.2, sortablejs@^1.9.0:
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.10.2.tgz#6e40364d913f98b85a14f6678f92b5c1221f5290"
integrity sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==
-source-list-map@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
- integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==
+source-list-map@^2.0.0, source-list-map@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2:
version "1.0.2"
@@ -10766,7 +11020,7 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
-source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.12:
+source-map-support@^0.5.6, source-map-support@~0.5.12:
version "0.5.20"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
@@ -10992,6 +11246,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
+strip-ansi@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
+ integrity sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==
+
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
@@ -11208,6 +11467,11 @@ tapable@^1.0.0, tapable@^1.1.3:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
tar@^6.0.2:
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
@@ -11437,16 +11701,23 @@ ts-invariant@^0.9.4:
dependencies:
tslib "^2.1.0"
-ts-node@^9:
- version "9.1.1"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
- integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
- dependencies:
+ts-node@^10.8.1:
+ version "10.9.1"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
+ integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
+ dependencies:
+ "@cspotcode/source-map-support" "^0.8.0"
+ "@tsconfig/node10" "^1.0.7"
+ "@tsconfig/node12" "^1.0.7"
+ "@tsconfig/node14" "^1.0.0"
+ "@tsconfig/node16" "^1.0.2"
+ acorn "^8.4.1"
+ acorn-walk "^8.1.1"
arg "^4.1.0"
create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
- source-map-support "^0.5.17"
+ v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
tsconfig-paths@^3.14.1:
@@ -11459,7 +11730,7 @@ tsconfig-paths@^3.14.1:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@2.3.0, tslib@~2.3.0:
+tslib@2.3.0, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
@@ -11469,15 +11740,15 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@~2.4.0:
+tslib@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
-tsutils@^3.17.1:
- version "3.17.1"
- resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
- integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
dependencies:
tslib "^1.8.1"
@@ -11575,6 +11846,11 @@ undefsafe@^2.0.5:
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
+underscore@~1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
+ integrity sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ==
+
undici@^5.0.0:
version "5.8.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.0.tgz#dec9a8ccd90e5a1d81d43c0eab6503146d649a4f"
@@ -11730,6 +12006,14 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
+update-browserslist-db@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
+ integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
@@ -11813,6 +12097,11 @@ uvu@^0.5.0:
kleur "^4.0.3"
sade "^1.7.3"
+v8-compile-cache-lib@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
+ integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
+
v8-compile-cache@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
@@ -11881,6 +12170,21 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
+vscode-languageserver-textdocument@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.5.tgz#838769940ece626176ec5d5a2aa2d0aa69f5095c"
+ integrity sha512-1ah7zyQjKBudnMiHbZmxz5bYNM9KKZYz+5VQLj+yr8l+9w3g+WAhCkUkWbhMEdC5u0ub4Ndiye/fDyS8ghIKQg==
+
+vscode-languageserver-types@^3.0.0:
+ version "3.17.2"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz#b2c2e7de405ad3d73a883e91989b850170ffc4f2"
+ integrity sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==
+
+vscode-uri@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84"
+ integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==
+
vue-apollo@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.7.tgz#97a031d45641faa4888a6d5a7f71c40834359704"
@@ -12050,10 +12354,10 @@ web-streams-polyfill@4.0.0-beta.1:
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz#3b19b9817374b7cee06d374ba7eeb3aeb80e8c95"
integrity sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ==
-web-streams-polyfill@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965"
- integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==
+web-streams-polyfill@^3.2.0, web-streams-polyfill@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
+ integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
web-vitals@^0.2.4:
version "0.2.4"
@@ -12119,10 +12423,10 @@ webpack-dev-middleware@^5.3.1:
range-parser "^1.2.1"
schema-utils "^4.0.0"
-webpack-dev-server@4.11.0:
- version "4.11.0"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.0.tgz#290ee594765cd8260adfe83b2d18115ea04484e7"
- integrity sha512-L5S4Q2zT57SK7tazgzjMiSMBdsw+rGYIX27MgPgx7LDhWO0lViPrHKoLS7jo5In06PWYAhlYu3PbyoC6yAThbw==
+webpack-dev-server@4.11.1:
+ version "4.11.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5"
+ integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==
dependencies:
"@types/bonjour" "^3.5.9"
"@types/connect-history-api-fallback" "^1.3.5"
@@ -12147,7 +12451,7 @@ webpack-dev-server@4.11.0:
p-retry "^4.5.0"
rimraf "^3.0.2"
schema-utils "^4.0.0"
- selfsigned "^2.0.1"
+ selfsigned "^2.1.1"
serve-index "^1.9.1"
sockjs "^0.3.24"
spdy "^4.0.2"
@@ -12170,6 +12474,14 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
source-list-map "^2.0.0"
source-map "~0.6.1"
+webpack-sources@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
+ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
+ dependencies:
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
webpack-stats-plugin@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.3.1.tgz#1103c39a305a4e6ba15d5078db84bc0b35447417"
@@ -12402,20 +12714,15 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-yaml-ast-parser-custom-tags@^0.0.43:
- version "0.0.43"
- resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02"
- integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ==
-
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-yaml@^2.0.0-10:
- version "2.0.0-10"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-10.tgz#d5b59e2d14b8683313a534f2bbc648e211a2753e"
- integrity sha512-FHV8s5ODFFQXX/enJEU2EkanNl1UDBUz8oa4k5Qo/sR+Iq7VmhCDkRMb0/mjJCNeAWQ31W8WV6PYStDE4d9EIw==
+yaml@^2.0.0, yaml@^2.0.0-10:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec"
+ integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==
yargs-parser@^20.2.2, yargs-parser@^20.2.3:
version "20.2.9"